.NET Forum / .NET Framework / Interop / August 2006
Usercontrol as ActiveX - trouble with events
|
|
Thread rating:  |
Aled Hughes - 20 Jul 2006 16:25 GMT Hi, I'm having trouble with a UserControl (written in C# with framework v2.0) that I've made into an ActiveX control. It seems to be OK except for event handling. As a test I use VB6 as the container (I've also tried from C++6 too).
If I create the control in VB6 code as follows:
Dim WithEvents myControl As WinControl1.UserControl1 Private Sub Form_Load() Set myControl = New UserControl1 End Sub
Private Sub Command1_Click() ' Run a method that invokes the TestEvent() delegate myControl.Test End Sub
Private Sub myControl_TestEvent() MsgBox "Event Fired!" End Sub
This works absolutely fine - the event gets fired as expected.
However, if I add the control in onto the VB form at design time (the control has a button on it that fires the event) rather than creating it in code, I cannot get the event to fire at all. The event delegate in the C# control code remains at null.
Any idea as to why the event isn't working when the UserControl is hosted this way?
Cheers, aled.
Ken Halter - 20 Jul 2006 21:35 GMT emembrance.htm
> Hi, > I'm having trouble with a UserControl (written in C# with framework v2.0) [quoted text clipped - 8 lines] > Set myControl = New UserControl1 > End Sub Try....
Set myControl = Controls.Add("WinControl1.UserControl1","WhoCares")
 Signature Ken Halter - MS-MVP-VB (visiting from VB6 world) - http://www.vbsight.com Please keep all discussions in the groups.. In Loving Memory - http://www.vbsight.com/R
Aled Hughes - 21 Jul 2006 07:52 GMT I'm testing with a VB6 client (no 'Controls.Add') and really I don't want any of that VB code at all - all I want is the UserControl on the form and a "UserControl11_DoStuff()" event handler, just like a button has its Click() handler.
At design time, when I double-click the UserControl on the form then VB creates the DoStuff() handler, but at run-time it never gets called.
Ken Halter - 24 Jul 2006 18:17 GMT > I'm testing with a VB6 client (no 'Controls.Add') and really I don't want > any [quoted text clipped - 5 lines] > At design time, when I double-click the UserControl on the form then VB > creates the DoStuff() handler, but at run-time it never gets called. Whether it works or not is besides the point... I guarantee that VB6 supports Controls.Add <g>... and, Set XX = New YY takes no less code than Set XX = Controls.Add("blah, blah")... plus, VB6 doesn't like controls to be added to a forms Controls collection without using Controls.Add or Load. Take yer pick. I have a bare-bones example of the two methods VB6 supports, Controls.Add and Load, if interested, see: http://www.vbsight.com/CodeA.htm#AddControls
 Signature Ken Halter - MS-MVP-VB (visiting from VB6 world) - http://www.vbsight.com Please keep all discussions in the groups.. In Loving Memory - http://www.vbsight.com/Remembrance.htm
Christian Fröschlin - 21 Jul 2006 09:02 GMT > Hi, > I'm having trouble with a UserControl (written in C# with framework v2.0) > that I've made into an ActiveX control. It seems to be OK except for event > handling. Try explicitely exposing a dispatch interface like (untested)
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)] public interface TestEventInterface { void TestEvent() }
and decorating the class raising the event with:
[ClassInterface(ClassInterfaceType.None), ComSourceInterfaces("<yournamespace>.TestEventInterface")]
Aled Hughes - 21 Jul 2006 14:10 GMT Yes, I've got that explicit IDispatch interface declared for the user control's event. Still no luck though! Here is the entire code for the C# control (which has only a button on it!):
namespace WinControl1 { [ComVisible(false)] public delegate void TestEventDelegate();
[Guid("C9CCDB9B-5A41-44b7-A54E-6D6DE0826EF5")] [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] [ComVisible(true)] public interface IUserControl1 { [DispId(1)] void Test(); }
[Guid("DCFF96F9-9F3B-4576-A144-E4CD030614B0")] [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] [ComVisible(true)] public interface IUserControl1Events { [DispId(1)] void TestEvent(); }
[Guid("F4A79199-9FA1-4810-AE34-F1EAC0437980")] [ComVisible(true)] [ClassInterface(ClassInterfaceType.None)] [ComSourceInterfacesAttribute(typeof(IUserControl1Events))] public partial class UserControl1 : UserControl, IUserControl1 { public event TestEventDelegate TestEvent;
public UserControl1() { InitializeComponent(); }
public void button1_Click(object sender, EventArgs e) { MessageBox.Show(".net control: Button Press"); if (TestEvent == null) MessageBox.Show("TestEvent delegate is null"); else TestEvent(); } public void Test() { MessageBox.Show("Test method called"); if (TestEvent != null) TestEvent(); } [ComRegisterFunction] static void ComRegister(Type t) { string keyName = @"CLSID\" + t.GUID.ToString("B"); using (RegistryKey key = Registry.ClassesRoot.OpenSubKey(keyName, true)) { key.CreateSubKey("Control").Close(); using (RegistryKey subkey = key.CreateSubKey("MiscStatus")) { subkey.SetValue("", "131457"); } using (RegistryKey subkey = key.CreateSubKey("TypeLib")) { Guid libid = Marshal.GetTypeLibGuidForAssembly(t.Assembly); subkey.SetValue("", libid.ToString("B")); } using (RegistryKey subkey = key.CreateSubKey("Version")) { Version ver = t.Assembly.GetName().Version; string version = string.Format("{0}.{1}", ver.Major, ver.Minor); if (version == "0.0") version = "1.0"; subkey.SetValue("", version); } } }
[ComUnregisterFunction] static void ComUnregister(Type t) { // Delete entire CLSID\{clsid} subtree string keyName = @"CLSID\" + t.GUID.ToString("B"); Registry.ClassesRoot.DeleteSubKeyTree(keyName); } } }
Nick Hall - 24 Jul 2006 12:44 GMT Hi Aled,
Unfortunately, NET controls are not supported in the VB6 environment.
(See http://support.microsoft.com/default.aspx?scid=KB;EN-US;311334 for more details.)
I belive the suggested workaround is to host the control inside a WebBrowser control.
Regards,
Nick Hall
> Hi, > I'm having trouble with a UserControl (written in C# with framework v2.0) [quoted text clipped - 31 lines] > Cheers, > aled. Aled Hughes - 26 Jul 2006 11:45 GMT My understanding was that this applies only to .net framework 1 and that support had improved for version 2.0. The KB article says it only applies to .net framework 1.0 and 1.1.
This whole subject area does seem somewhat vague in the MS documentation!
> Hi Aled, > [quoted text clipped - 45 lines] > > Cheers, > > aled. Nick Hall - 26 Jul 2006 12:28 GMT Hi Aled,
Yes, I hadn't noticed that the article only applied to 1.1. However I have been unable to find anything that suggests that has changed for 2.0; so I would tend to believe that the restriction still applies (unless you have seen something that suggests different..?)
As you say, the documentation is less than impresive on this point.
Regards,
Nick Hall
> My understanding was that this applies only to .net framework 1 and that > support had improved for version 2.0. The KB article says it only applies [quoted text clipped - 59 lines] >> > Cheers, >> > aled. Aled Hughes - 26 Jul 2006 17:05 GMT Hi Nick, I noticed in the KB article that MFC 7.x is a supported host for .net ActiveX controls. Well I tried in MFC8 and the same incorrect behaviour (events not firing) occurs.
As far as I've been able to deduce, MFC passes in its event sink interface pointer when it uses IQuickActivate on the ActiveX .net user control. The .net control then does a QueryInterface on the event sink for a number of other interface IDs, but never does a QI for the event interface itself (i.e. IID_IUserControl1Events as obtained from the AX control). If I constrast this with a native ActiveX control, that does QI for the event interface ID. So it seems to me that the .net control simply doesn't bother checking to see if the client supports the appropriate event sink. Strange! I wonder how the 'WithEvents' keyword in VB6 gets events to work?
Aled.
> Hi Aled, > [quoted text clipped - 72 lines] > >> > Cheers, > >> > aled. Aled Hughes - 26 Jul 2006 18:37 GMT I've discovered some more:
I've managed to get events working now in the ActiveX Control Test Container application and I can get them working too in MFC world.
The problem seems to lie around IQuickActivate - if I prevent this being used in MFC (using the debugger), all is well and the event hooks up correctly. MFC falls back to using the IConnectionPoint::Advise system when IQuickActivate isn't present, and that seems to work fine.
The other important thing I discovered was that setting the DispId of the event interface in the .net control is important. If I miss off that attribute I get an exception thrown. So I set [DispID(1)].
So I guess that the fault lies with .net's implementation of IQuickActivate. I guess in the VB6 world, it too uses IQuickActivate if the control is on a form, whereas if it created in code with 'WithEvents' keyword, it does it differently and uses IConnectionPoint which works.
In MFC I won't be able to prevent it using IQuickActivate normally, but even so it is possible to work around it by manually calling IConnectionPoint::Advise at an approriate time.
"Peter Huang" [MSFT] - 27 Jul 2006 08:55 GMT Hi Aled,
Based on my research, so far the VS.NET 2005 did not support write a UserControl and register for Com Interop and use it as an ActiveX control in VB6. But from VC.NET 2005, we have new MFC-Winform Application, you may have a try. Using WinForms controls in an MFC dialog http://www.codeproject.com/managedcpp/mfcdialogwinforms.asp
Using the Windows Forms 2.0 MenuStrip and ToolStrip controls to give your MFC applications a new look and feel http://www.codeproject.com/managedcpp/MfcWinFormsOff.asp
Best regards,
Peter Huang
Microsoft Online Community Support ================================================== When responding to posts, please "Reply to Group" via your newsreader so that others may learn and benefit from your issue. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights.
Aled Hughes - 27 Jul 2006 09:21 GMT Hi Peter,
To be honest, I'm not particularly worried about VB6 support. I was using VB6 simply as a test bed.
What I am aiming for is getting a WinForm into an existing MFC6 application. I've seen that it's possible to get a WinForm control into an MFC8 app but I was hoping to avoid migrating the MFC6 app to MFC8. Hence me thinking down the route of wrapping the WinForm control in ActiveX. (I was initially hoping for embedding a WinForms "Form" and having it appear as an MDI child rather than a WinForm control but this seems a non-starter).
Cheers, Aled.
"Peter Huang" [MSFT] - 28 Jul 2006 03:14 GMT Hi Aled,
Because there are some problem to host .NET Control as an ActiveX control in unmanaged application. there goes the KB per Nick suggested. So from in MFC8 we add this feature for the customers who needs the feature to host Winform Control in MFC8.
I understand you may want to use MFC6(VC6.0) to host .NET User Control. But based on my knowledge, the VC6.0 is out of support lifetime. Here is a link for your reference. http://support.microsoft.com/lifecycle/?p1=3003
So if you want to develop application based on VC, why not use vc++2005 directly? Do you have any concern to use MFC8 as your targeted platform?
Best regards,
Peter Huang
Microsoft Online Community Support ================================================== When responding to posts, please "Reply to Group" via your newsreader so that others may learn and benefit from your issue. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights.
Aled Hughes - 28 Jul 2006 09:43 GMT Hi Peter,
Ideally it would be good to use MFC8 with the CWinFormsControl support and avoid the ActiveX stuff altogether. Trouble is that I have an existing application developed in MFC6 and I don't really want to go through what will probably be a non-trivial task of migrating it to MFC8 and doing a full retest. Though, increasingly this looks like it may be the way I have to go.
Another way I thought of is wrapping up the WinForms control in an MFC8 ActiveX control and then using that ActiveX control in MFC6. This sounds like it could be fraught with difficulties though!
Cheers, Aled.
"Peter Huang" [MSFT] - 01 Aug 2006 09:00 GMT Hi Aled,
I do understand your scenario. But the VC6 is out of support lifetime, even MSPSS did not support MFC6 including using MFC 8 control in MFC 6. They only support the scenario related with MFC6 is that migration MFC6 to MFC8.
So for your scenario, I do recommend you try to write code in MFC 8, if you have existing MFC6 code, you may try to use that in MFC8 scenario which is the supported scenario so far.
Thanks for your understanding!
Best regards,
Peter Huang
Microsoft Online Community Support ================================================== When responding to posts, please "Reply to Group" via your newsreader so that others may learn and benefit from your issue. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights.
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|