Up to now IntelliSense listed all public variables, methods and properties of a class, when I used the name somewhere else, but now it only shows a few properties and methods. The problem also occurs with forms and other controls.
There is a post, which dealed already with this issue (link to the post), but it does not provide a working solution. Maybe someone knows the reason for this behaviour.
Edit: Here is a screenshot with an example:
From your screenshot the problem is easier to spot. You are using the Default Instance of a form. As Hans said, intellisense not displaying here is a probably a minor bug that Microsoft will likely not fix. Your code is easier to fix however. Don't use the default instance; it should look like this:
dim f as new Form1
f.Sub1 '<--- should get intellisense here now.
You should avoid using default instance of forms. In my experience, they cause nothing but problems. Creating a form instance, storing it in a local variable or field, and passing those references around is easy enough. It's also a much better practice that will make your code stronger overall.
Related
I have one VB6 ActiveX DLL that exposes a class INewReport. I added some new methods to this class and I was able to rebuild it and keep binary compatibility.
I have a second DLL that exposes a class clsNewReport, which implements the first class using:
Implements RSInterfaces.INewReport
Since I added new methods to INewReport, I had to also add those new methods to clsNewReport.
However, when I try to compile the second DLL, I get the binary-compatibility error "...class implemented an interface in the version-compatible component, but not in the current project".
I'm not sure what is happening here. Since I'm only adding to the class, why can't I maintain binary compatibility with the second DLL? Is there any way around this?
I think this is a correct explanation of what is happening, and some potential workarounds.
I made up a test case which reproduced the problem in the description and then dumped the IDL using OLEView from the old & new DLL which contained the interface.
Here is a diff of the old (left) and new IDL from INewReport:
Important differences:
The UUID of interface _INewReport has changed
A typedef called INewReport___v0 has been added which refers to the original UUID of the interface
(I assume that this is also what is happening to the code referred to in the question.)
So now in the client project the bincomp DLL refers to the original interface UUID; but that UUID only matches against a different name (INewReport___v0 instead of INewReport) than it did originally. I think this is the reason VB6 thinks there is a bincomp mismatch.
How to fix this problem? I've not been able to do anything in VB6 that would allow you to use the updated interface DLL with the client code without having to break bincomp of the client code.
A (bad) option could be to just change the client DLL to use project compatibility... but that may or may not be acceptable in your circumstances. It could cause whatever uses the client DLL to break unless all the consumers were also recompiled. (And this could potentially cause a cascade of broken bincomp).
A better but more complex option would be to define the interface in IDL itself, use the MIDL compiler to generate a typelib (TLB file), and reference that directly. Then you would have full control over the interface naming, etc. You could use the IDL generated from OLEView as a starting point for doing this.
This second option assumes that the interface class is really truly an interface only and has no functional code in it.
Here's how I setup a case to reproduce this:
Step 1. Original interface definition - class called INewReport set to binary compatible:
Sub ProcA()
End Sub
Sub ProcB()
End Sub
Step 2. Create a test client DLL which implements INewReport, also set to binary compatible:
Implements INewReport
Sub INewReport_ProcA()
End Sub
Sub INewReport_ProcB()
End Sub
Step 3: Add ProcC to INewReport and recompile (which also registers the newly built DLL):
(above code, plus:)
Sub ProcC()
End Sub
Step 4: Try to run or compile the test client DLL - instantly get the OP's error. No need to change any references or anything at all.
I was able to recreate your problem, using something similar to DaveInCaz's code. I tried a number of things to fix it, probably repeating things you've already tried. I came up with a possible hypothesis as to why this is happening. It doesn't fix the problem, but it may throw some additional light on it.
Quoting from This doc page:
To ensure compatibility, Visual Basic places certain restrictions on changes you make to default interfaces. Visual Basic allows you to add new classes, and to enhance the default interface of any existing class by adding properties and methods. Removing classes, properties, or methods, or changing the arguments of existing properties or methods, will cause Visual Basic to issue incompatibility warnings.
Another quote:
The ActiveX rule you must follow to ensure compatibility with multiple interfaces is simple: once an interface is in use, it can never be changed. The interface ID of a standard interface is fixed by the type library that defines the interface.
So, here's a hypothesis. The first quote mentions the default interface, which suggests that it may not be possible to alter custom interfaces in any way. That's suggested by the second quote as well. You're able to alter the interface class, because you are essentially altering its default interface. However, when you attempt to alter the implementing class in kind, to reflect the changes in your interface, your implementation reference is pointing to the older version of the interface, which no longer exists. Of course, the error message doesn't hint at this at all, because it appears to be based on the idea that you didn't attempt to implement the interface.
I haven't been able to prove this, but looking at DaveInCaz's answer, the fact that the UUID has changed seems to bear this idea out.
I'm a bit confused on exactly how the architecture for a VB.NET forms app actually works.
I've noticed in others' code, lines that read a little like this:
If frmMain.someBooleanProperty Then
but, I'm a bit confused because someBooleanProperty is then defined as an instance variable (i.e., as Public someBooleanProperty As Boolean in frmMain). How is it being referenced statically to access an instance variable? Is this just bad coding practice?
For reasons of backwards compatibility, VB.NET automatically creates an instance of every Form. This instance is accessible through a global property which has the same name as the Form class itself.
More details can be found here:
Why is there a default instance of every form in VB.Net but not in C#?
I have some serious trouble with Visual Studio, its driving me insane...
When a Class makes a new instance of another Class, I usually pass "this" to its constructor, and have an easy access to the parent Class.
parentPointer->myVariable
But with visual studio it just won't work.
I have the pointer, and i can access 8 million methods/variables, but just not my own public variables.
With the debugger i can actually see the variables and their values...
the structure looks like this:
parentPointer->MyClass::myVariable
So I can actually find the variables with that (weird) syntax. But then I get this error:
qualified name is not a member of class "CWnd" or its base class.
So I wasted one more hour on a super simple task with that Visual Studio...
(If it helps, its a MFC Application)
Any help would be highly appreciated!
Greetings
UPDATE
Ok finally got it...
I simply modified the new standard constructor:
newClass::newClass(CWnd* pParent, parentClass* parentPointer);
With the additional Parameter 'parentPointer' i can now use:
parentPointer->myVariable ! :)
I somehow thought it should automatically work with pParent...
(Its still pretty strange that with debugger I had all values ect. accessible in the pParent...)
PS: Thanks for making my Thread more readable, i still haven't figured out how to format it properly xD
VB in VS2008 under Windows 7 (64):
I need to change the value of a Property of a Component at some unpredictable time in DesignMode, and want the previously unknown new value to be embedded in the executable that results from VS compilation (as opposed to serializing it to some external file).
I have resorted to a text edit to swap the new value into the autogenerated Component initialization code in a prebuild event handler. This works fine, but it is a little hacky for my taste. Is there some way instead to force VS to refresh that text?
By luck, I found something that seems to work to force VS to autogenerate initialization code for the runtime instance of a Component, which is what I was after (I needed to have successful communication between designtime and runtime for Components -- easy for Controls, which use the latest designtime BackgroundImage bitmap at runtime (you need only to hide the Property value in the bitmap, which can be done entirely within the rules by using GetPixel and SetPixel). I considered various hacks, but I hit upon the following, which works and makes sense (though I might be completely FoS about the "why". If you know better, please educate me):
As I understand it, soon after a Component is dropped on a design surface in VS (and before it is rendered in the Component Tray), Visual Studio adds it to a collection of Components belonging to a Container. Adding it to the Container's collection is one step in a sequence of happenings that includes Visual Studio's autoregeneration of the Init procedure that will be used for the Component's root at runtime, and which includes values for the Public Properties of the Component. If you overload the Set Site procedure (the creation of ISite is an early step in that sequence) for your Component, and set a value for one of its Public Properties in the Overload, that value will show up in the autoregen text. This is almost what I wanted, except that it only worked when VS called Set Site, and I needed it to happen any time I chose.
Then I took a flyer, and in the UI that sets the Property value in question (at some unknowable time), I added code to remove the Component from the Container's collection and then re-add it, hoping that this might again set off a sequence of happenings that would lead to VS again autoregenerating the Init code, this time with the new value of the Property. It apparently did. Yay.
By deciding when to re-add a Component to the Container's Components collection, I am now able to force VS to write in the autogenerated Init text any value I assign to a Public Property of that Component, and hence embed the value in the executable when it is compiled.
This technique is vulnerable to changes in the (undocumented) way that Microsoft implements autogeneration, and so is arguably a hack. But even documented features are subject to change. Backward-compatibility is a nice idea, but sometimes it has to give way. And delivery is a requirement. It would be great to know that your code will still be good in any future version of VS, but that, sadly, can't happen, hack or no.
Of course, documented features are in general less subject to change than undocumented ones. But the logic of autogeneration after all the initial Property values are set is pretty compelling. That Microsoft uses the same sequence later on is not so inherently logical, but doing it a different way would cost Microsoft money for no apparent gain. And Microsoft and their ilk (are legally required to) make decisions based on the bottom line. So the status quo seems like a good bet.
Hi i'm having to learn VB.net for a new job having previously been a C# guy. I just come across an interesting feature of VB.net. I can reference objects on a second form that has not been instatiated!
So from Form1 i can get the text property of textbox1 on Form2 as follows
Dim txt As String = Form2.TextBox1.Text
Can anyone explain how this works? Are all forms instatiated at the start of the program and then their visibility is toggled throughout the program lifespan?
Forms in VB are a special case. The compiler generates a strongly-typed list of forms in the My.Forms object of the My namespace. Each form is exposed as a property My.Forms.TheNameOfTheForm. These properties always return valid instances – i.e. if a form hasn’t been instantiated before, it will when you first use the property.
So far, so good.
But Microsoft also made the brain-dead (!) decision of importing the properties from the My.Forms object by default, everywhere, and there’s nothing you can do. Superficially, this is for backwards compatibility reasons to VB6 but that’s nonsense since VB7 (.NET 1.0) didn’t have this feature, it only came later.
But just to clarify:
Are all forms instatiated at the start of the program …?
No, luckily not. They are instantiated the first time you access the property.