Raising events from .NET UserControl inside a VB6 MDI form(Interop Forms Toolkit)
-
quarta-feira, 3 de janeiro de 2007 09:24
I have used the Interop Forms Toolkit example: http://blogs.msdn.com/vbteam/archive/2006/11/02/interop-roadmap-usercontrols-mdi-and-data.aspx, and am using the example InteropUserControl.
I want to raise an event from my .NET UserControl which is hosted inside a VB6 VBControlExtender type:
Private WithEvents moDynamic As VBControlExtender
Set moDynamic = Controls.Add("InteropUserControl.InteropUserControl", "DynamicControl")
The control loads fine.
How do I raise an event from the .NET UserControl so it is trapped by the VBControlExtender?
Todas as Respostas
-
quinta-feira, 4 de janeiro de 2007 01:38Moderador
You'll need to handle the events using the same method you would for non-dynamic controls.
1. Add a reference to the TLB (not in the toolbox, but by clicking Project->References)
2. Use the following code:
Dim WithEvents myCtl As VBControlExtender
Dim WithEvents ctlEvents As CtlExtenderTest.InteropUserControlPrivate Sub ctlEvents_Click()
MsgBox "Click event fired"
End SubPrivate Sub Form_Load()
Set myCtl = Controls.Add("CtlExtenderTest.InteropUserControl", "NameOfNewControl")
Set ctlEvents = myCtl.object
myCtl.Visible = True
End SubHope that helps,
Jonathan
-
quarta-feira, 21 de fevereiro de 2007 17:44
Hi,
I have similar problem as David,
is it possible to catch .NET UserControl events by VBControlExtender global event handler?
Like:
Private Sub mExtender_ObjectEvent(info As EventInfo)
On Error GoTo ErrHandler
msgbox "Event catched: " & info.Name
ExitPoint:
Exit Sub
ErrHandler:
MsgBox Err.Description, vbCritical, "mExtender_ObjectEvent"
Resume ExitPoint
End SubThanks for any hint.
-
terça-feira, 27 de fevereiro de 2007 05:44Moderador
Unfortunately you won't be able to use ObjectEvent to catch these events centrally for the time being. This wasn't a supported scenario when .NET 2.0 shipped, but we're adding this functionality in the next version. This code will work for you if you have framework 3.5 installed (even if you're targetting the 2.0 framework, since the 3.5 framework will patch the assembly).
If you really want a central way of handling the events I'd suggest handling the events on ctlEvents (in my code example above) and then for each instance call a procedure that has the central event handling code.
Hope that helps,
Jonathan
-
terça-feira, 27 de fevereiro de 2007 13:06
Hi,
It's good to see that MS team is working on this, because I was realy missing this, while using System.Runtime.Interop. So thanks for your reply.
I done it by this way if it will help someone else: In .NET I created a interface with Register() method (ISender) and code that creates InteropOCX is calling this Register() method so .NET after knowes the caller. Caller of Register() method is implementing IListener interface.
After if .NET OCX wants to raise event it will call caller.ExtendedEventHandler(ExtenderEventInfo info) with event params. So after we are in VB6 with extended EventInfo object, which we can pass to extender_ObjectEvent(byval info as EventInfo).
I have to say also that you should implement ExtendedEventInfo in VB6 and add reference to generated dll in VS.NET from COM tab. Because if you will try to implement it in .NET and extend VBRUN.EventInfo and other interfaces. You will fail will Type Missmatch error on VB6 side.
So it after behaves as event raised from .NET and catched in VB6 global event handler.
Hope that helps someone and spend less time then me on this problem.
Michal
-
quinta-feira, 25 de outubro de 2007 01:30
I have just tried the following code using Dev Studio 2008 Beta 2 (With build target set to .Net Framework 3.5) and my event was not captured in the VBControlExtender.ObjectEvent event. In fact, as far as .NET is concerned when using my test control under VB, the Save delegate is null indicating that nothing is "listening" to this event. However, interestingly, when run under the Active X Control Test Container (TstCon32.exe, Visual Studio 6.0), something is listening, but an exception is thrown (show below).
Ok, here's my test code:
namespace
VBActiveXTest{
[Guid("C2361FB8-D0C4-4d2d-B782-028C45AA5DAD")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IFinshAction
{
void Save(FinishAction fa);
}
public delegate void delSave(FinishAction fa);
[Guid("766DAE80-E94A-4000-AAF2-83110E015BEB")]
[ComSourceInterfaces(typeof(IFinshAction))]
[ClassInterface(ClassInterfaceType.AutoDual)]
// you need to select ".NET Category" under "Insert Control"->"Implemented Categories"
// to see this prog ID in TSTCON32.EXE
[ProgId("VBTest.BasicUI")]
public partial class BasicUI : UserControl, MyOwnSomeOtherInterface
{
public event delSave Save;
public BasicUI()
{
InitializeComponent();
}
#region
MyOwnSomeOtherInterface Members// Implementation of MyOwnSomeOtherInterface Removed!!
private void btnCancel_Click(object sender, EventArgs e)
{
// FinishAction is an enumration defined in some IDL I have.
// Its definition should be irrelevent to this test and can be
// changed to int for testing
FinishAction myAction = FinishAction.faCancel;
if (Save != null)
{
Save(myAction);
}
else
{
// If created and used within VBControlExtender we get here!!!!
MessageBox.Show("No Event Sink!");
}
}
}
}
TSTCON32.EXE reports the following .NET exception when the bnCancel_Click method in invoked.
just-in-time (JIT) debugging instead of this dialog box.
************** Exception Text **************
System.NotImplementedException: The method or operation is not implemented.
at System.RuntimeType.InvokeDispMethod(String name, BindingFlags invokeAttr, Object target, Object[] args, Boolean[] byrefModifiers, Int32 culture, String[] namedParameters)
at System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams)
at System.RuntimeType.ForwardCallToInvokeMember(String memberName, BindingFlags flags, Object target, Int32[] aWrapperTypes, MessageData& msgData)
at FMUITest3.IFinshAction.Save(FinishAction fa)
at FMUITest3.BasicUI.btnCancel_Click(Object sender, EventArgs e) in C:\Documents and Settings\khazeldi\My Documents\Visual Studio 2008\Projects\FMUITest3\FMUITest3\BasicUI.cs:line 63
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)************** Loaded Assemblies **************
mscorlib
Assembly Version: 2.0.0.0
Win32 Version: 2.0.50727.1378 (REDBITSB2.050727-1300)
CodeBase: file:///C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/mscorlib.dllAlso...
After shutting down TXTCON32.EXE with File->Exit. TSTCON32.EXE it is still visible in the Task Manager. This seems to happen only if it created a .NET "Active X Control" at sometime during its existence.
Conclusion.
Either I am doing something wrong here or the code you allude to being in place in Framwork 3.5 (and patched 2.0) isn't yet in in place.
If anyone else has any similar experience or has managed to get more success than I, I'd like to hear from you.
-
quinta-feira, 25 de outubro de 2007 19:17Moderador
Hi Kevin,
I just tested this out quickly in VB and everything works fine, here's what I did:
1. New Interop UserControl, add a button called btnCancel and the following code at the bottom of the class:
<ComClass(BasicUI.ClassId, BasicUI.InterfaceId, BasicUI.EventsId)> _
Public
Class BasicUI...
'Please enter any new code here, below the Interop code Public Delegate Sub delSave(ByVal fa As Integer) Public Event Save As delSavePrivate Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As EventArgs) Handles btnCancel.Click
RaiseEvent Save(1)
End Sub
End Class
2. Open VB6 and add the following code:
Dim WithEvents myCtl As VBControlExtender
Private Sub Form_Load()
Set myCtl = Controls.Add("VB6ActiveXTest.BasicUI", "NameOfNewControl")
myCtl.Visible = True
End SubPrivate Sub myCtl_ObjectEvent(Info As EventInfo)
MsgBox Info.Name & " - " & Info.EventParameters(0)
End SubThe event fires and everything works fine. Try changing your C# code to use ClassInterfaceType.None instead of AutoDual. Other than that your code looks fine...if it's still not working try out the VB example above and open it in Reflector. The VB compiler supports ComClass (C# doesn't) and so it takes care of a lot of this stuff for you automatically. For more information check out http://blogs.msdn.com/vbteam/archive/2007/06/01/so-what-does-lt-comclass-gt-actually-do.aspx.
Hope that helps,
Jonathan
-
sexta-feira, 26 de outubro de 2007 04:30
It did help - a lot. I tried using ClassInterfaceType.None in C# to no avail. However, redoing the whole project using the Interop UserControl Template (a downloadable add-in, I discovered) with VB.NET (3.5, in Dev Studio 2008) it worked. Top banana. Given some more time I might have another go at getting the C# version to work.
Kevin.
-
quarta-feira, 23 de janeiro de 2008 21:19I've had this working for quite some time in C#, however, recently one of my PV guys' machines started encoutering this exception every time an interop event occurs. Since only one machine exhibits this behaviour and (most thankfully) it has never happened on site to any of our clients, I must conclude that I'm missing something........ No one knows what changed on that machine.
On a lighter note, I'd like to say how pleased I am that I can create .NET ActiveX controls, wrap them in an ocx, and painlessly replace our old vb ocx. -
terça-feira, 4 de maio de 2010 21:19
Getting the events raised proved to be complicated in VB.Net, but this allows your assembly object to be declared WithEvents inside the VB6 project:
<ComClass(ctrlTriSysV9_04.ClassId, ctrlTriSysV9_04.InterfaceId, ctrlTriSysV9_04.EventsId)> _
Public
Class ctrlTriSysV9_04
Public Const ClassId As String = "aaaaaaaa-dd4f-424b-1234-ce0753900fd1"
Public Const InterfaceId As String = "bbbbbbbb-aa6d-44c5-5678-fe82bedd30e6"
Public Const EventsId As String = "cccccccc-bb33-4c49-9012-c173f09485e6"
Obviously replace the above with your own GUID's
- Sugerido como Resposta TriSys Business Software terça-feira, 4 de maio de 2010 21:20
-
terça-feira, 21 de fevereiro de 2012 06:15
I had the exact problem is that you are missing the despatch ID the interface should be as follows:
[Guid("C2361FB8-D0C4-4d2d-B782-028C45AA5DAD")] [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] public interface IFinshAction { [DispId(1)] void Save(FinishAction fa); }

