VC + + to encapsulate the form in the DLL and invoke __c++

Source: Internet
Author: User
Tags function prototype win32

Original address:: HTTP://WENKU.BAIDU.COM/LINK?URL=LE3KTWKCW1IS09HMEBFLOHITGGPSHT4I7S6J3DX0Q84_3XEQLZWUCYUWGRO-L8Y9F8SOOJJS _mzytoxgvbomg3asmcljoaigdircitdmv1c



Using Resources in DLLs
The most common question about DLLs now is how to use dialog boxes in DLLs, which is a general question about how to use resources in DLLs. Here we analyze and solve this problem from two aspects of WIN32 DLL and MFC DLL.


1. Win32 DLL
Using a dialog box in a Win32 DLL is simple, you only need to add dialog resources to your DLL, and you can set up the controls you need on the dialog box. Then use DialogBox or createdialog these two functions (or other functions of the same function) to create the dialog box and define your own dialog box callback function to process the messages received by the dialog box. Here's a concrete example to learn how to use a dialog box in a Win32 DLL, you can follow these steps to complete this example:


1 in the VC menu file->new a new Win32 Dynamic-link library project named Usedlg, the next step is to select a simple DLL project.


2 in the VC menu Insert->resource Add a dialog resource with ID idd_dlg_show, remove the Cancel button on this dialog and leave only the OK button. Add a dialog box with an ID of Idd_aboutbox, whose caption is about. Save this resource and name the resource file usedlg.rc. and add resource.h and usedlg.rc to the project.


3 include the resource.h in the Usedlg.app and add the following code:


HINSTANCE hinst = NULL;
HWND Hwnddlg = NULL;
BOOL CALLBACK Dlgproc (HWND hdlg, UINT message,wparam WPARAM, LPARAM LPARAM);


BOOL CALLBACK Aboutproc (HWND hdlg, UINT message,wparam WPARAM, LPARAM LPARAM);


extern "C" __declspec (dllexport) void Showdlg ();


BOOL apientry DllMain (HANDLE hmodule,
DWORD Ul_reason_for_call,
LPVOID lpreserved
)
{
Switch (Ul_reason_for_call)
{
Case Dll_process_attach:
Hinst = (hinstance) hmodule;
Case Dll_process_detach:
Break
}
return TRUE;
}


extern "C" __declspec (dllexport) void Showdlg ()
{
Hwnddlg = Createdialog (Hinst,makeintresource (idd_dlg_show), NULL, (Dlgproc) dlgproc);
ShowWindow (Hwnddlg, sw_show);
}






BOOL CALLBACK Dlgproc (HWND hdlg, UINT message,wparam WPARAM, LPARAM LPARAM)
{
Switch (message)
{
Case WM_INITDIALOG:
return TRUE;
Case WM_COMMAND:
if (LoWord (WParam) ==idok)
DialogBox (Hinst,makeintresource (Idd_aboutbox), Hdlg, (Dlgproc) aboutproc);
return TRUE;
Case WM_CLOSE:
DestroyWindow (HDLG);
Hwnddlg = NULL;
return TRUE;
}
return FALSE;
}






BOOL CALLBACK Aboutproc (HWND hdlg, UINT message,wparam WPARAM, LPARAM LPARAM)
{
Switch (message)
{
Case WM_CLOSE:
EndDialog (Hdlg,null);
Hwnddlg = NULL;
return TRUE;
}
return FALSE;
}






4 compile and generate UseDlg.dll and UseDlg.lib.


Next we build the application that calls this DLL, and the steps are as follows:


1 in the VC menu file->new new one named use of the MFC AppWizard (EXE) project, the next choice dialog based click the Finish button.


2 Add a button to the main dialog box, www.qqme5.com, and then double-click this button, will pop up the Add member Function dialog box, click OK to enter the void Cusedlg::onbutton1 () function. and add a function call within this function: Showdlg ();.


3 followed by the #include statement followed by the following code:


extern "C" __declspec (dllexport) void Showdlg ();
#pragma comment (lib, "Debug/usedlg")


4 Copy the UseDlg.dll and UseDlg.lib two files generated in the above Usedlg project to the debug directory of the Use project.


5 compile and generate Use.exe.


Run Use.exe, click the Button1 button, and you can see a modeless dialog box called dialog pops up. Click on the button above to eject the modal dialog box about. Run successfully.


Let's review the process of using dialog boxes in Win32 DLLs.




In the DLL, we defined two dialog resources: Idd_dlg_show and Idd_aboutbox, and derived the function Showdlg. A modeless dialog box Idd_dlg_show is created using the Createdialog function in the function Showdlg, and the callback function for the dialog box is specified Dlgproc. Wm_initdialog, WM_COMMAND, and WM_CLOSE messages are processed in Dlgproc in response to User action on the dialog box. When the button action is processed, use the DialogBox function to create the modal dialog Idd_aboutbox, specify that its callback function is Aboutproc, and process its corresponding message in Aboutproc.


In the EXE, we invoke the DLL using an implicitly linked method and use the Showdlg function exported in the DLL to invoke the dialog box in the DLL.
Using the dialog box in the Win32 DLL is simple, let's take a look at how to use the dialog box in an MFC DLL.


2. MFC DLLs
Using dialog boxes in an MFC DLL is not as simple as Win32 DLLs, primarily because of the problem of a module state in an MFC program, which is a problem with resource duplication. (The term module here refers to an executable program, or a DLL (or a set of DLLs) whose operations do not depend on the rest of the application but use the shared copy of the MFC runtime. The MFC DLL we create is a typical example of this module. )
In each module (EXE or DLL), there is a global state data, MFC relies on this global state data to differentiate between different modules to perform the correct operation. This data includes Windows instance handles (for loading resources), pointers to the application's current CWinApp and CWinThread objects, OLE module reference counts, and various mappings for maintaining connections between Windows object handles and corresponding MFC object instances. However, when an application uses multiple modules, the state data for each module is not application-scoped. Instead, each module has a private copy of its own MFC state data. This global state data is called the MFC module state.
The state data of a module is contained in a structure and can always be used by pointers to that structure. When the code enters a module at execution time, MFC can correctly differentiate the module and perform the correct action only if the module has a status of current or valid.
For example, an MFC application can load a string from a resource file using the following code:
CString str;
Str. LoadString (ids_mystring);


It is convenient to use this code, but it masks the fact that ids_mystring in this program may not be unique identifiers. A program can load multiple DLLs, and some DLLs may also define a resource with the ids_mystring identifier. How does MFC know which resources should be loaded? MFC uses the current module state to find resource handles. If the current module is not the correct module we want to use, then an incorrect call or error is generated.


By linking to the MFC library, an MFC DLL has two ways to use the MFC library: statically linking to MFC's DLLs and DLLs that are dynamically linked to MFC. Below we will follow these two types of MFC DLLs to describe how to toggle the current module state to use resources correctly in the MFC DLL.


1, statically linked to MFC DLL


Statically linked to MFC's rule DLL and the MFC library static link, the MFC library cannot be shared at this time, so MFC always uses the module state of the DLL it links to. This also does not have the problem of managing the module state. However, the disadvantage of using this method is that the DLL program will become larger and will leave duplicate code in the program. The example given below validates this. This example can be accomplished by following these steps:


1 in the VC menu file->new a new project named Dllstatic MFC AppWizard, next choose regular DLL with MFC statically linked.


2 in the project to add a dialog box resources, in the VC menu Insert->resource add an ID: Idd_aboutbox. Save this resource and name the resource file usedlg.rc. The resource.h and usedlg.rc were added to the project and the Idd_aboutbox values were changed to 100 in the resource.h.


3 The following functions are defined in DLLStatic.cpp:


void Showdlg ()
{
CDialog dlg (Idd_aboutbox);
Dlg. DoModal ();
}


4 Add a row to the exports statement in the Dllstatic.def file: Showdlg to export the Showdlg function.
; MFCDLLStatic.def:Declares the module parameters for the DLL.
LIBRARY "Mfcdllstatic"
DESCRIPTION ' mfcdllstatic Windows Dynamic Link Library '
Exports
Showdlg; Add this line
; Explicit exports can go


5 compile and generate DLLStatic.dll and DLLStatic.lib.


Continue using the use project in the previous section to copy the previously generated DLLStatic.dll and DLLStatic.lib two files to the project's debug directory, and


extern "C" __declspec (dllexport) void Showdlg ();
#pragma comment (lib, "Debug/usedlg")


The two lines should read:


void Showdlg ();
#pragma comment (lib, "Debug/dllstatic")


Compile and run Use.exe. Click the button to see the modal dialog box in the Dllstatic pop-up.


In this example, you can note that the About dialog resource defined in the DLL is exactly the same as the About dialog resource ID defined in the EXE, http://youximingzhi.qqq23.com, But when we clicked on the button above the Use.exe, the modal dialog box in the DLL was popped up. Explains that there is no problem with the state of the management module when you use a static link to an MFC rule DLL.
2, dynamically linked to MFC DLL


Before discussing the module state of a DLL that is dynamically linked to MFC, let's look at an example. This example can be accomplished with the following steps:


1 in the VC menu file->new a new project named Dllshared MFC AppWizard, the next step is to select the regular DLL using shared MFC DLL.


2 Add a dialog box resource in the project ID: Idd_aboutbox. In Resource.h, the Idd_aboutbox value was changed to 100.


3 The following functions are defined in DLLShared.cpp:


void Showdlg ()
{
CDialog dlg (Idd_aboutbox);
Dlg. DoModal ();
}
4 Add a row to the exports statement in the Dllshared.def file: Showdlg to export the Showdlg function.


5 compile and generate DLLShared.dll and DLLShared.lib.


Continue using the use project above to copy the previously generated DLLShared.dll and DLLShared.lib two files to the debug directory of the project and


extern "C" __declspec (dllexport) void Showdlg ();
#pragma comment (lib, "Debug/dllstatic")


The two lines should read:


void Showdlg ();
#pragma comment (lib, "debug/dllshared")




Compile and run Use.exe. Click on the button and what you see this time. Yes, that's right, this one is Use.exe about the dialog box. Replacing the DLL type of the example above with an MFC Extension DLL (using a shared MFC DLL) can also cause the same problem.


Why the above problem arises. This is because, by default, MFC uses the main application's resource handle to load resource templates when MFC shared libraries are used. Although we call a function in a DLL to display a dialog box in a DLL, and the corresponding dialog template is stored in a DLL, MFC still looks for the appropriate dialog template in the main application, the Use.exe. Because the dialog box resource ID defined in the DLL is the same as the resource ID for the dialog box defined in the main application, MFC displays the dialog box in the main application. If they are different, MFC considers the dialog box resources defined in the DLL to be dlg. DoModal will return 0, which means nothing will be displayed.


So how to solve the above problems. The solution is to switch the module state at the right time to ensure that the module with the current state is the module we need to use the correct resources. MFC provides the following functions and macros to do these things:


AfxGetStaticModuleState: This is a function whose function prototype is:
afx_module_state* Afxapi afxgetstaticmodulestate ();


This function constructs an instance of the Afx_module_state class on the stack pmodulestate and assigns it a value and returns it. In the constructor of the Afx_module_state class, the class takes a pointer to the state of the current module and stores it in a member variable, and then sets the pmodulestate to the new valid module state. In its destructor, the class restores the pointer stored in its member variable to the previous module state of storage.


Afx_manage_state: This is a macro, and its prototype is:


Afx_manage_state (afx_module_state* pmodulestate)


This macro is used to set the Pmodulestate (pointer to the AFX_MODULE_STATE structure that contains the module's global data, which is the module state) to the current immediate space (the remainder of the immediate containing SCOPE) in a valid module state. The previous valid module state is automatically restored when you leave the active space that contains the macro.


AfxGetResourceHandle: The prototype of this function is:
HInstance AfxGetResourceHandle ();


This function returns a handle to a module that holds the HINSTANCE type of the application's default loaded resource.
AfxSetResourceHandle: The prototype of this function is:
void AfxSetResourceHandle (HInstance hinstresource);


This function sets the module represented by Hinstresource as a module with the current state.


By using the four functions or macros above, you can switch the module state correctly in DLLs that are dynamically linked to MFC. Next we'll show you how to use the four functions or macros by modifying the example above that shows the problem. Let's take a look at the regular DLL using shared MFC DLL type:


In the third step of the previous example, precede the first statement of the SHOWDLG function with the following statement (to ensure that the statement is the first line of the function implementation):


Afx_manage_state (AfxGetStaticModuleState ());
Then recompile the build DLLShared.dll and DLLShared.lib, and copy the two files back into the debug directory of the Use project. This compilation generates Use.exe and runs, click on the button, and you can see the dialog box that we joined in the DLL when it pops up, not the Use.exe about the dialog box.


Through the above explanation, I believe you already know the function of the statement. After the first line of function Showdlg is added, the MFC library automatically switches the current module state every time the application that invokes the DLL uses the function, thus guaranteeing the correctness of the resource reading.


Afx_manage_state (AfxGetStaticModuleState ()); is automatically switching the current module state, You can also manually switch the current module state by using AfxGetResourceHandle and AfxSetResourceHandle. The specific use of the following methods:


In the third step of the previous example, precede the first statement of the SHOWDLG function with the following statement (to ensure that the statement is the first line of the function implementation):


HInstance save_hinstance = AfxGetResourceHandle ();
AfxSetResourceHandle (theapp.m_hinstance);


After the call dialog box succeeds, that is, dlg. DoModal (), after which, add:


AfxSetResourceHandle (save_hinstance);


After entering the Showdlg function, this method obtains and saves the handle of the current state module through AfxGetResourceHandle. It then obtains the handle theapp.m_hinstance of the DLL module (of course, you can also use the GetModuleHandle function to get the handle to the DLL module) and use the AfxSetResourceHandle function to set it to the current state state. Finally, the current module state is restored by restoring the AfxSetResourceHandle resource handle after the call dialog box succeeds.


This is a bit of a hassle, but one advantage is that the resource handle can be recovered immediately after the task that uses the resource is completed. The Afx_manage_state (AfxGetStaticModuleState ()) method only restores the resource handle after the function space has ended. Because the executable must redraw the toolbar and so on, it is recommended that you recover the resource handle whenever possible, or you may experience many problems. For example, if a user moves a dialog box for a DLL, and the resource handle is still a resource for the DLL, the program crashes. The best time to recover the handle is when the dialog box responds to the WM_INITDIALOG message, because the dialog box template has been read out.


For MFC DLLs of the MFC Extension DLL (using shared MFC DLL) type, the method for switching the current module state is similar to the method used by the MFC DLL for the regular DLL using a shared MFC DLL type, where no more examples Realize. The two different places are as follows:




When you use Afx_manage_state (AfxGetStaticModuleState ()) in an MFC extension DLL, the following error occurs:


Mfcs42d.lib (dllmodul.obj): Error LNK2005: __prawdllmain already defined in Dllextend.obj
Mfcs42d.lib (dllmodul.obj): Error LNK2005: _dllmain@12 already defined in Dllextend.obj
Mfcs42d.lib (dllmodul.obj): Error LNK2005: __prawdllmain already defined in Dllextend.obj


Therefore, the afx_manage_state (AfxGetStaticModuleState ()) is required in the MFC extension DLL, and the Afx_manage_state (Afxgetappmodulestate ()) is replaced. To correctly toggle the current module state.


The use of AfxGetResourceHandle and AfxSetResourceHandle in an MFC extension DLL is the same as the method used in an MFC DLL of a regular DLL using a shared MFC DLL type. Also, the handle of the DLL module can be obtained by the Hmodule member of the Dlgextentdll structure provided by MFC. Even with AfxSetResourceHandle (Dlgextentdll.hmodule);


Of course, for DLLs that are dynamically linked to MFC, you can also switch the current state module by using the AfxGetResourceHandle and AfxSetResourceHandle two functions in the MFC application that calls the DLL. The handle of the DLL module can be obtained by using the GetModuleHandle function. No longer dwell on this.

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.