这部分的解决方案是基于由Morgan Skinner发表的文章《以ActiveX控件的形式暴露Windows窗体控件》。尽管Skinner提供他的解决方案是由Visual Studio 8 Beta版本开发的,但他的例子在VS8的发行版运行得也很好(只是做了小小改动)。下面是我们对Skinner的解决方案所作的改动的一个列表:
/// <summary> /// Unregister ActiveX DLL function /// </summary> /// <param name="i_Key"></param> [ComUnregisterFunction()] public static void UnregisterClass(string i_Key) { // strip off HKEY_CLASSES_ROOT\ from the passed key as I don't need it StringBuilder sb = new StringBuilder(i_Key); sb.Replace(@"HKEY_CLASSES_ROOT\", "");
// open HKCR\CLSID\{guid} for write access RegistryKey registerKey = Registry.ClassesRoot.OpenSubKey(sb.ToString(), true);
// delete the 'Control' key, // but don't throw an exception if it does not exist registerKey.DeleteSubKey("Control", false);
// next open up InprocServer32 RegistryKey inprocServer32 = registerKey.OpenSubKey("InprocServer32", true);
// and delete the CodeBase key, again not throwing if missing inprocServer32.DeleteSubKey("CodeBase", false);
// finally close the main key registerKey.Close(); }
/// <summary> /// COM Interface - enables to run c# code from c++ /// </summary> [InterfaceType(ComInterfaceType.InterfaceIsDual)] public interface ICSSExplorerInterface { void setButtonCaption(String strNewCaption); void setAdapterDllPtr(IntPtr i_AdapterDllPtr); }
[DllImport("user32.dll", EntryPoint = "SendMessage")] public static extern IntPtr SendMessage( int hwnd, uint wMsg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", EntryPoint = "SendMessage")] public static extern int SendMessage( int hwnd, uint wMsg, int wParam, string lParam);
[DllImport("user32.dll", EntryPoint = "SendMessage")] public static extern int SendMessage( int hwnd, uint wMsg, int wParam, out int lParam);
[DllImport("user32.dll", EntryPoint = "SendMessage")] public static extern int GetNbFiles( int hwnd, uint wMsg, int wParam, int lParam);
[DllImport("user32.dll", EntryPoint = "SendMessage")] public static extern int GetFileNames( int hwnd, uint wMsg, [MarshalAs(UnmanagedType.LPArray)]IntPtr[] wParam, int lParam);
[DllImport("user32.dll", EntryPoint = "SendMessage")] public static extern int SendMessage( int hwnd, uint wMsg, int wParam, StringBuilder lParam);
// Get the dimensions of the main window's client // area, and enumerate the child windows. Pass the // dimensions to the child windows during enumeration. RECT rcClient;
if (_pDotNetCOMPtr != NULL) { _pDotNetCOMPtr->setAdapterDllPtr((long) _hSelf); } else { // Get the dimensions of the main window's client // area, and enumerate the child windows. Pass the // dimensions to the child windows during enumeration. RECT rcClient; GetClientRect(_hSelf, &rcClient);
::DestroyWindow(_hAtl); _hAtl = ::CreateWindowEx( WS_EX_CLIENTEDGE,\ TEXT("AtlAxWin"),\ TEXT("MSHTML:""Please register ActiveX control before using this plugin."""),\ WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_EX_RTLREADING,\ 0, 0, rcClient.right, rcClient.bottom,\ _hSelf,\ NULL,\ NULL,\ NULL); } } 复制代码 4.为了更准确的开发,在WndProc函数中添加下面代码到WM_DESTORY消息处理块中(注:为了销毁C# ActiveX控件窗口和释放加载的内存)。