"Reprint" How to integrate C # window in C + + engineering

Source: Internet
Author: User

Original: http://www.cnblogs.com/clever101/archive/2009/12/14/1624204.html

This article is transferred from the blog garden, this article author according to codeproject English version translation!

Original address: Http://www.codeproject.com/KB/cs/DotNetActiveX.aspx

Original Daniel Yanovsky

Translation: Zhu Jinchan

This article describes how to integrate C # windows (Window Form) in C + + engineering.

Introduced

This article describes how to integrate a C # form (also known as a Windows Form) in a C + + window. Our C + + window is created using purely WIN32 API functions and does not require MFC.

Background

In general, using C # for Windows programming is much easier than using C + +, especially when we cannot use the MFC library. So many programmers like to use the C # environment to build their projects. But sometimes it needs to be programmed in a C + + environment. For example, when you want to develop an attachment software on a C + + program. The way we solve this problem is to develop a plugin for it, such as the famous notepad++ program. Notepad++ is written in the C + + language, using purely WIN32 API functions and STL to ensure that it has a high speed and a smaller executable file. But the disadvantage is that the design and development of the interface becomes difficult. So we faced this challenge and decided to use C # to create our plugins. How we successfully integrate our. NET plugin to a window created using purely WIN32 API functions? I hope that this article will help you understand this.

We have prepared a small example for this article. If you would like to see the full source of the plugin we have written for notepad++, please visit our plugin homepage.

Creating ActiveX Control basics with the C # language

This part of the solution is based on the article "Exposing Windows Forms controls in the form of ActiveX Controls", published by Morgan Skinner. Although Skinner offered his solution to be developed by the visual Studio 8 Beta, his example runs very well (only minor changes) in the VS8 release. Here is a list of the changes we made to the Skinner solution:

1.       Set upClassInterface为ClassInterfaceType.None(这样我们暴露唯一指定的接口到COM)。更多的信息在下一章。

2. The project should be set as visible to COM. to do this:assembly information on the Application tab on the Project Properties menu item Make assembly COM visible on the dialog boxis selected (specifically):

1. You should also register the project for COM interop (note that in VS8.0 's release, the "Build" Property window and the beta version have different designs). When this feature is selected, Visual Studio automatically registers. NET ActiveX controls when the project is successfully compiled. (as specific)

4.       In Skinner's article, theComUnregisterFunction()函数中有一个小错误。下面是正确的函数:

<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 a 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 ();
}

Exporting a clear method for COM

For a more precise design, we export the specified method for COM. Every external program that uses our controls will only access the methods they need.

The best way to export a concrete method is to create an interface for all related methods. Then, the specific attributes should be added to this interface. The form class should be implemented on this interface.

<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);
}

Using the Microsoft messaging System

We use the Microsoft Messaging System and VC engineering container windows and other windows to communicate. We do not handle any events, because if so it will become more complex and it is not required for our solution.

Let's add the following code to ourMyDotNetActiveX类去允许消息传输:


private static UINT dot_net_button_pressed = 0x0400;

private void Btnok_click (object sender, EventArgs e)
{
SendMessage (M_adapterdllptr.toint32 (),
dot_net_button_pressed, IntPtr.Zero, IntPtr.Zero);
}

#region Mapping_of_user32_dll_section

[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);

#endregion

In the initialization code, we assume that our container window will be passed to its window handle ( hwnd 参数 ) to communicate.

Compiling the project

Now we are ready to compile and test this control. Visual Studio automatically registers our ActiveX controls after a successful compilation. You can view the registration information through the free software Regdllview.

To test the control in the ActiveX Control Test Container

Before we jump to the next step in this article, it's a good time to test our controls in a third-party program. We tested using the ActiveX Control Test Container (tstcon32.exe). This program can be found in the installation directory of Visual Studio.

1. Insert a control from theInsert New controlmenu item of theEditmenu bar

1. Now select theInvoke Methodsmenu item in theControlmenu bar.

2. in the method Name Combo-box control, select the setbuttoncaption function.

3. Enter "Hello" in the Parameter Value text box and press the "Invoke" button

5. Here are the test results

Add C # ActiveX controls to the C + + window using the ATL control containment

Any ActiveX control can be included by using the active Template Library (ATL).

In this section of the guide, we will complete the following work:

    1. Create a C + + WIN32 Application project
    2. Inserting our ActiveX control into the C + + window
    3. Send command to ActiveX control
    4. Receive a message from our ActiveX control
Create a C + + WIN32 Application project
    1. Create a new Win32 project and name it " CPP_Container :":

2. Use the default settings and press the "OK" button:

Inserting a C # ActiveX control into a C + + window
    1. Add the following code to the beginning of cpp_container.cpp :
#define Dot_net_button_pressed 0x0400

HWND _hatl;
HWND _hself;
iunknown* _punk;
Dotnetactivex::icssexplorerinterfaceptr _pdotnetcomptr;

HInstance _hweblib =:: LoadLibrary (TEXT ("ATL. DLL "));

2. When Visual Studio compiles our C # project, it creates the dotnetactivex.tlb file. This file contains all the methods and structures of the project. We will import the data using the following command:

Import C # control function and structures
#import "Dotnetactivex.tlb" Named_guids raw_interfaces_only

3. Add the following function to Cpp_container.cpp. This function inserts an ATL container into the window and loads our C # ActiveX controls:

void Loadactivex (LPCTSTR stractivexname)
{
Initialize ATL Control Containment code.
BOOL (WINAPI *m_atlaxwininit) ();
M_atlaxwininit = (BOOL (WINAPI *) (void)):: GetProcAddress
(_hweblib, "AtlAxWinInit");
M_atlaxwininit ();

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);

_hatl =:: CreateWindowEx (
Ws_ex_clientedge,\
TEXT ("Atlaxwin"), \
Stractivexname,\
Ws_child | ws_visible | /*ws_clipchildren | */ws_ex_rtlreading,\
0, 0, Rcclient.right, rcclient.bottom,\
_hself,\
Null,\
Null,\
NULL);

if (!_hatl)
{
MessageBox (NULL, TEXT ("Can not load atlaxwin!"),
SzTitle, MB_OK | Mb_iconstop);
throw int (106901);
}

HRESULT (WINAPI *m_atlaxgetcontrol) (HWND H, iunknown** pp);
M_atlaxgetcontrol = (HRESULT (WINAPI *)
(HWND, iunknown**)):: GetProcAddress (_hweblib, "Atlaxgetcontrol");

M_atlaxgetcontrol (_hatl, &_punk);

_punk->queryinterface (__uuidof (Dotnetactivex::icssexplorerinterface),
(LPVOID *) &_pdotnetcomptr);

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);

::D Estroywindow (_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. For more accurate development, add the following code in the WndProc function to the Wm_destory message processing block (note: In order to destroy the C # ActiveX control window and free the loaded memory).

_pdotnetcomptr->release ();
::D Estroywindow (_hatl);
_punk->release ();
:: FreeLibrary (_hweblib);

5. Finally, in_tWinMain函数调用loadActiveX函数。

Loadactivex (TEXT ("Dotnetactivex.mydotnetactivex"));

Send command to C # ActiveX control

After inserting the TLB file, all of the methods that we exported in the C # project will be displayed. Now we simply call the relevant method:

Char *strhelloworld = "Hello world!";
_bstr_t Bstrhelloworld (Strhelloworld);
_pdotnetcomptr->setbuttoncaption (Bstrhelloworld);

This will change the title of the button to "Hello world!".

Receiving messages from C # ActiveX controls

Messages from the C # control through Microsoft's messaging system can reach the C + + window. By invoking a loadActiveX 函数我们已经将我们的窗口句柄发给 C # control. So now, we just need to add some code to the WndProc function (note: Message processing code). WndProc函数是负责处理到达该窗口的每个消息。所以我们将在这个函数添加一个另外的case分支:

Case dot_net_button_pressed:
MessageBox (NULL, TEXT ("Message from C # Arrived:button pressed!!"),
SzTitle, MB_OK | Mb_iconinformation);
Break

Now, you can press the button in the C # ActiveX control and see the following result:

Conclusion

We hope this article will help developers who mix the C # and C + + languages in their projects. You can view the notepad++ plugin we developed: Cssexplorer plug-in for notepad++. All of the ideas mentioned above have been implemented in our plugins.

Reference documents
    1. C # programming Guide-example COM Class (C # Programming Guide)
    2. How to add an ATL control containment support to any windows in Visual C + +
    3. Exposing Windows Forms controls as ActiveX Controls
History
    • October 10, 2009: initial submission
Authorized

This article, including all relevant source code and files, follows the code Project Open License (CPOL) licensing agreement.

About the author

Daniel Yanovsky: Career: Software development engineer. Nationality: Israel.

"Reprint" How to integrate C # window in C + + engineering

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.