Dear,
I have a problem opening a form from within a DLL. I'll explain the situation.
I have to make a program who needs a certification by the goverment, once certified the program may not change anymore. But each time I sell the program to a new client a new form with the clients layout has to be made. So I use a DLL with all my clients there unique forms with the layout they want. So I have a STARTUP-form on a buttonclick the layout-form of a specified client opens from the DLL. So far no problem, now when I push a button on the DLL-form (clients layout form) I want to open the GENERAL-form of my windowsapplication. And here is the problem, I don't know how to open the GENERAL-form from within the DLL-form.
By far, the simplest solution is to give both the main app and the dll some common knowledge. The way you would do this is to define the common things, such as interfaces, delegates, and the like, in a dll which is referenced both by the main application as well as by the dll. I was thinking that you may not be allowed to do something like that, but you have made it clear that the main app is allowed to reference dlls that you have created, so this solution should work.
As it stands, the problem is that the main application knows about types in the dll because the main application has a reference to the dll. The dll doesn't know about types defined in the main application because the dll does not (and can not) have a reference to the main application. That means that some of the simpler solutions, such as passing an instance of the main form to the dll, won't work because the dll wouldn't recognize the main form as a type. By using a common dll, you could define a delegate in that dll. The working dll could have a method that accepts a delegate of that type and calls it when it is ready to show the main form. Therefore, the main application could have a method that launches the main form, and could pass that method to the dll as a delegate.
Another alternative, which may be simpler, would be to pass an instance of the mainform to the dll as type Form (in other words, the mainform would be cast to its base, which is a type that the dll will know about). The dll would then be able to call Show or ShowDialog on that Form object, without knowing what specific type of form is being shown. The dll wouldn't be able to interact with that form in pretty nearly any other way, though, as it would only be able to call methods of the base Form class, and would know nothing about it being a mainform, or even what a mainform was.
By far, the simplest solution is to give both the main app and the dll some common knowledge. The way you would do this is to define the common things, such as interfaces, delegates, and the like, in a dll which is referenced both by the main application as well as by the dll. I was thinking that you may not be allowed to do something like that, but you have made it clear that the main app is allowed to reference dlls that you have created, so this solution should work.
As it stands, the problem is that the main application knows about types in the dll because the main application has a reference to the dll. The dll doesn't know about types defined in the main application because the dll does not (and can not) have a reference to the main application. That means that some of the simpler solutions, such as passing an instance of the main form to the dll, won't work because the dll wouldn't recognize the main form as a type. By using a common dll, you could define a delegate in that dll. The working dll could have a method that accepts a delegate of that type and calls it when it is ready to show the main form. Therefore, the main application could have a method that launches the main form, and could pass that method to the dll as a delegate.
Another alternative, which may be simpler, would be to pass an instance of the mainform to the dll as type Form (in other words, the mainform would be cast to its base, which is a type that the dll will know about). The dll would then be able to call Show or ShowDialog on that Form object, without knowing what specific type of form is being shown. The dll wouldn't be able to interact with that form in pretty nearly any other way, though, as it would only be able to call methods of the base Form class, and would know nothing about it being a mainform, or even what a mainform was.
I have never used forms in a DLL ,so I don't know how they work (I imagine it should be the same as referencing anything else in a project), but would there be a way to use AddHandler?
Code:
AddHandler Dll.Event, AddressOf MyAppForm.Show
From the application, attach to an event in the DLL. When that event in the DLL occurs, that should trigger the application to do something? I dont have a DLL with forms in it or any way to test.
:EDIT: I found this answer, this is basically what I meant:
Code in the dll:
Code:
Public Event MySpecialEvent ()
Private Sub Test
RaiseEvent MySpecialEvent
End Sub
Code in the form:
Code:
Private _MyDll as MyDLL
Public Sub Main
_MyDLL = New MyDLL
AddHandler _MyDLL.MySpecialEvent, AddressOf MySpecialEventHandler
End Sub
Private Sub MySpecialEventHandler
'Put your code here to act upon the handled event
End Sub
RemoveHandler _MyDLL.MySpecialEvent, AddressOf MySpecialEventHandler
Credits to Walter on SO
Last edited by jayinthe813; Dec 26th, 2014 at 02:00 PM.
You can do that, but only one way. The main application can add handlers for events raised by objects in the dll, because the main application knows about objects in the dll. The dll can't handle events from the main application, because it doesn't know about any of the objects there. In theory, there ought to be a way around that, since an event handler is just a list of functions maintained by the object that raises the event, and adding a handler amounts to adding a method to call to the list. The dll should be able to supply a method, but it can't know who to supply it to, since it knows nothing about the objects in the main application.
For one application, I created an object that was just responsible for raising events. The main application passed an instance of this object to all the dlls. By doing this, any of the dlls could raise an event and all the other dlls could handle that event, which allowed for communication between the dlls and the main app, as well as communication between dlls. However, that required that the event raiser object be defined in a dll that was referenced by the main app and all the dlls that wanted to work with that object.
"The dll can't handle events from the main application, because it doesn't know about any of the objects there. " -- it doesn't need to. From the main app, I can wire up event handlers in the dll to objects in the main app... done this a few times before. Granted within that handler you can't reference objects from the main app... but the handler is just that, a handler - NOTE: this works by using AddHandler, it will not work using the Handles keyword. When the object in the main app then raises its events, control will transfer to all handlers, even ones in the dll.
That's how some plugins work. The main application scans for assemblies with a given interface, then wire up known objects (from the main app) to handlers in the plugins.
Right, I see what you mean. As long as the main app is doing the hooking up it isn't a voodoo black magic love spell.....oops, got sucked into that spammers lingo.....I meant that the dll doesn't have to hook up the events if the main app does. However, if you allow the main application to scan for that interface, doesn't that necessarily mean that both the dll and the main app reference some common dll where the interface is defined? If you are willing to allow for that common dll, then all kinds of alternatives become available.
I was trying to think of a solution that didn't require a common dll. As far as showing the form, that's not too hard, because the dll can call .Show or .ShowDialog on a Form object without knowing whether that form is actually a Form1, Form2, or FormLessTree. I think it might be able to add handlers to events of the form, as well, as long as it never goes beyond the methods, properties, and events exposed via the Form base class (or any other classes that Form derives from, of course).
SH is of course correct, but I'll add that the DLL and EXE are effectively using the framework as a 'third party' or 'common' DLL: both the DLL and EXE reference the same Form object. Of course, this is easy to distribute in this situation.
To be honest, I wouldn't shy away from a common DLL. It's not hard to do, and it's just another file. Instead of one DLL and one EXE, it's two DLLs and one EXE. While it may be the app requires only to 'show' a EXE form from the DLL, but the added versatility of the common DLL could make some functionality easier.
"Ok, my response to that is pending a Google search" - Bucky Katt. "There are two types of people in the world: Those who can extrapolate from incomplete data sets." - Unk. "Before you can 'think outside the box' you need to understand where the box is."
... - NOTE: this works by using AddHandler, it will not work using the Handles keyword. When the object in the main app then raises its events, control will transfer to all handlers, even ones in the dll...
Why can't you use WithEvents and Handles? This essentially does the same thing. You can use WithEvents on a Form object in a DLL, pass in a variety of forms, and the one assigned to the WithEvents variable will raise the events.
Is there some aspect I'm missing?
"Ok, my response to that is pending a Google search" - Bucky Katt. "There are two types of people in the world: Those who can extrapolate from incomplete data sets." - Unk. "Before you can 'think outside the box' you need to understand where the box is."
The reason I'm thinking that the WithEvents / Handles wouldn't work:
The main app has a text box and 2 buttons...
FooBarText is the TextBox and Foo is the first button, and Bar being the second button.
they would have the WithEvents in the main app... now, the DLL has no reference to the main app so how could it have a Handles to the buttons? Only the main app could have the withEvents and handles.... Now I suppose if you want to expose a couple of properties in the dll that are type button... then you could define the backing members WithEvents and use the Handles...
This is how I did it, it's a way around and I know there must be a better and easier way than to catch it when the Main_Form is activated. (It get's the focus back when the DLL-Form close)
code is included in the zip. Start the project via ClassLibrary1.vbproj