How to add resources in dll

Source: Internet
Author: User
Use resources in DLL
The most common problem about DLL is how to use the dialog box in DLL. This is a common question about how to use resources in dl l. Here we analyze and solve this problem from the Win32 DLL and mfc d ll aspects.

1. Wi n32 DLL

It is very easy to use the dialog box in Win32 DLL. You only need to add the dialog box resources in your DLL, And you can set the required control on the dialog box. Then, use the DialogBox or CreateDialog functions (or other functions with the same function) to create a dialog box and define your own dialog box callback function to process the messages received in the dialog box. The following example shows how to use the dialog box in Win32 DLL through a specific instance. You can follow the steps below to complete this example:

1) in the VC menu, choose File>
Create A New Win32 Dynamic-Link Library job named UseD lg. Next, select A simple DLL project. <Br>
2) Insert->
Reso urce adds a Dialog resource with ID IDD_DLG_SHOW. Remove the Cancel button on the Dialog, and retain only the OK button. Then add a dialog box with ID IDD_ABOUTBOX and its Ca ption is About. Save the resource and name the resource file UseD lg. rc. Add resource. h and UseDlg. rc to the project.

3) include resource. h In UseDlg. app and add the following code:

H instance hinst = NULL;

Hwn d hwndDLG = NULL;

Bool callback DlgProc (HWND hDlg, u int message,
WPARAM wParam, LPARAM lParam );

Bool callback AboutProc (HWND hDlg, UINT message,
WPARAM wPar am, LPARAM lParam );

Ex tern"
C"
_ Declspec (dllexport) void ShowDlg ();

Bool apientry DllMain (ha ndle hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
Switch (ul_reaso n_for_call)
{
Case DLL_PROCESS_ATTACH:
H inst = (HINSTANCE) hModule;

Case DLL_PROCESS_DETACH:Break;

}
Retu rn TRUE;

}

Extern"
C"
_ Declspec (dllex port) void ShowDlg ()
{
HwndDLG = CreateDialog (hins t, MAKEINTRESOURCE (IDD_DLG_SHOW ),
NULL, (DLGPROC) DlgProc );

ShowWindow (hwndDLG, SW _ SHOW );

}

Bool call back DlgProc (HWND hDlg, UINT m essage,
WPARAM wParam, lpa ram lParam)
{
Switch (message)
{
Case WM _ INITDIALOG:
Return tru e;

Case WM_COMMAND:
If (LOWORD (wParam) = IDOK) <br> DialogBox (hinst, makein tresource (IDD_ABOUTBOX ),
H Dlg, (DLGPROC) AboutProc );

Return TRUE;

Case WM _ CLOSE:
DestroyWindow (h Dlg );

HwndDLG = NULL;

Return TRUE;

}Return FALSE;

}

Bool callback AboutProc (h wnd hDlg, UINT message,
Wp aram wParam, LPARAM lParam){
Switch (message)
{
Case WM_CLOSE:
EndDialog (hDlg, NULL );
HwndDLG = NULL;

Return TRUE;

}
R eturn false;

}

4) compile and generate usedlg. dll and usedlg. Lib.
<Br> next, create an application that calls this dll. The procedure is as follows:
1) in the VC menu, choose File>
Create an MFC AppWizard (exe) project named "Use". Select "Dialog Based" in the next step and click "Finish.
2) Add a button on the Main Dialog Box and double-click this button. The Add Member Function dialog box is displayed. Click OK to enter the void CUseDlg: OnButton1 () Function. Add a function call in the function: ShowDlg ();
.

3) Add the following code next to the # include statement:

Extern"
C"
_ Declspec (dllexport) void sh owdlg ();

# Pragma comment (l ib ,"
Debug/usedlg"
) <Br>
4) copy the usedlg. dll and usedlg. Lib files generated in the usedlg project above to the De bug directory of the Use Project.

5. compile and generate use.exe.

Run use.exe and click the button1 button. A non-Modal Dialog Box named dialog is displayed. Click the button above to bring up the modal dialog box about. Run successfully.

Let's review the process of using the dialog box in Win32 DLL.

In DLL, we define two resource sources: idd_dlg_show and idd_aboutbox, and export the showdlg function. In the showdlg function, use the crecreatedialog function to create the non-Modal Dialog Box idd_dlg_sh ow and specify the callback function dlgproc in the dialog box. Wm_initdialog, wm_comman D, and wm_close messages are processed in the dlgpr oC to respond to users' actions on the dialog box. When processing the button action, use the dialogbox function to create the idd_ AB outbox modal dialog box, specify its callback function as aboutpro C, and process the corresponding messages in aboutproc.

In EXE, we use the implicit link method to call the DLL, and use the ShowDlg function exported from dl l to call the dialog box in the DLL.

Using the dialog box in Win32 DLL is so simple. Let's take a look at how to use the dialog box in mfc dll.

2. MFC DLL
The dialog box used in mfc dll is not as simple as that in Win32 DLL. It is mainly because there is a Module State problem in the MFC procedure, which is also a duplicate of resources. (The term module here refers to an executable program, or a DLL (or a group of DLL) whose operations do not depend on the rest of the application but use the shared copy of the MFC Runtime Library ). The mfc dll we created is a typical instance of this module .)

In each module (e xe or DLL), there is a global state data. MFC relies on this full-board State data to distinguish different modules and perform the correct operations. Such data includes Windows Instance handles (used to load resources), pointers to the current CWinApp and CWinThread objects of the application, and OLE module reference count, maintain mappings between Windows Object handles and corresponding MFC object instances. However, when an application uses multiple modules, the status data of each module is not within the application scope. On the contrary, each module has its own private copy of the MFC-like state data. The global status data is called the status of the MFC module.

The module status data is contained in the structure and can always be used by a pointer to the structure. When the code is executed into a module, only the module is in the "current" or "valid" status, MFC can correctly distinguish this module and perform the correct operations.

For example, you can use the following code to load a string from a resource file in the MFC application process:

CString str;

Str. LoadStrin g (IDS_MYSTRING );

This code generation is very convenient, but it masks the fact that IDS_MYS TRING in this program may not be a unique identifier. A program can load multiple DLL files. Some DLL files may also use the IDS_MYSTRING identifier to define a resource source. How does MFC know which resource to load? MFC uses the current module status to find the resource handle. If the current module is not the correct module we want to use, it will produce incorrect calls or errors.

According to the Link Method of the MFC library, an mfc dll has two methods to use the MFC Library: static link to the mfc dll and dynamic link to the mfc dll. Next we will follow these two types of mfc dll to introduce how to switch the current module status to use resources correctly in m fc dll.

1. DLL statically linked to MF C

When the rule DLL with static link to the MFC is statically linked to the m fc library, the MFC Library cannot be shared at this time, so the MFC always uses the module status of the DLL it is linked. In this way, the status of the management module does not exist. However, the disadvantage of using this method is that the DLL program will become larger and duplicate code will be left in the program. The example below demonstrates this. In this example, follow these steps:

1) in the VC menu, choose File>
N ew creates a project named DLLStatic MFC AppWiza rd. Next, select Regular DLL with mf c statically linked.

2) Add a dialog box resource in the project. Its ID is IDD_ABOUTBO X. In resource. h, change the IDD_ABOUTBOX value to 100.

3) define the following functions in DLLStatic. cpp:

Void Show Dlg ()
{
CDialog dlg (IDD_ABOUTBOX );

Dlg. DoMod al ();

}

4) Add a row ShowD lg to the EXPORTS statement in the DLLStat ic. def file to export the ShowDlg function.

5) compile and generate DLLStatic. dll and DLLStatic. lib. <Br>
Continue to Use the Use project in the previous section and copy the previously generated DL LStatic. dll and DLLStatic. lib files to the Debug directory of the project.

Exter n"
C"
_ Declspec (dll export) void ShowDlg ();

# P ragma comment (lib ,"
Debug/UseDlg"
)

The two rows are changed to: <br>
Void ShowDlg ();

# Pr agma comment (lib ,"
Debug/D LLStatic"
)

Compile and run use.exe. Click the button to see the modal dialog box in DLLStatic.

In this example, we can note that the resources in the About dialog box defined in DLL are exactly the same as those in the resource D of the About dialog box defined in EXE. However, when we click the button above use.exe, the modal dialog box in DLL is displayed. Note: When you use the static link to the MFC Rule d ll, the status of the management module does not exist.

2. DLL dynamically linked to MFC

Let's look at an example before discussing the module status of DLL dynamically linked to MFC. In this example, follow these steps:

1) in the VC menu, Fil e->
Create a New project named DLLShared MFC AppWizard. Next, select Regular DLL using shared mfc dll.

2) Add a dialog box resource in the project. Its ID is IDD_ABOUTB OX. In resource. h, change the IDD_ABOUTBOX value to 100.

3) define the following functions in DLLShared. cpp:

Void ShowD lg ()
{
CDialog dlg (I DD_ABOUTBOX );

Dlg. DoModa l ();

}

4) add a line: ShowDl g to the EXPORTS statement in the DLLShare d. def file to export the ShowDlg function.

5) compile and generate D LLShared. dll and DLLShared. lib.
Continue to Use the above Use project, copy the previously generated DLLSh ared. dll and DLLShared. lib files to the Debug directory of the job, and

Extern & quot;
C"
_ Declspec (dllexp ort) void ShowDlg ();

# Prag ma comment (lib ,"
Debug/DLL Static"
)

The two rows are changed to: <br>
Void ShowDlg ();

# Pr agma comment (lib ,"
Debug/D LLShared"
)

Compile and run use.exe. Click the button. What do you see this time? Yes, that's right. This pop-up dialog box about use.exe. Changing the DLL type in the above example to m fc Extension DLL (using shared mfc dll) also causes the same problem.

Why is the above problem? This is because when the MFC shared library is used, by default, MFC uses the resource handle of the main application to load the resource template. Although we call functions in DLL to display the dialog box in DLL, and the corresponding dialog template is stored in DLL, MFC is still in the main application, that is, Use. find the corresponding dialog box template in exe. Because the resource ID of the dialog box defined in DLL is the same as the resource ID of the dialog box defined in the main application, MFC displays the dialog box in the main application. If the two are different, MFC considers that the dialog box resource defined in the DLL does not exist, and dlg. Do Modal returns 0, that is, nothing is displayed.

So how can we solve the above problems? The solution is to switch the module status when appropriate to ensure that the module with the current status is what we need to use the correct resources. MFC provides the following functions and macros to complete these tasks:
AfxGetStaticModuleState: This is a function. Its prototype is:

AFX_MODULE_S TATE * AFXAPI AfxGetStaticModul eState ();

This function constructs the instance pModuleState of the AF X_MODULE_STATE class on the stack and assigns a value to it to return it. In the constructor of the AFX_MODULE_STATE class, this class obtains the pointer pointing to the current module status and stores it in the member variation. Then, it sets the pModuleState to the new valid module status. In its destructor, this class restores the pointer stored in its member variables to the status of the previous stored module.

AFX_MANAGE_STA TE: This is a macro. Its prototype is:

AFX_MAN AGE_STATE (AFX_MODULE_STATE * p ModuleState)

This macro is used to point to the pMo duleState (pointer to the AF X_MODULE_STATE structure that contains the global data of the module, that is, the module state) set the status of the valid module in the current real-time space (the remainder of the immed iate containing scope. When the space containing the macro is removed, the status of the previous valid module is automatically restored.

AfxGetResourceHandle: the prototype of this function is:

HINSTANCE Af xGetResourceHandle ();

This function returns the handle of a module that saves the HINSTANCE type and loads resources by default in the application process.

AfxSetR esourceHandle: the prototype of this function is:
Void AfxSetResourceHandle (h instance hInstResource );

This function sets the module represented by hInstResource as a module with the current status.

By using the above four functions or macros, You can correctly switch the module status in the DLL dynamically linked to the MFC. Next we will introduce how to use the above four functions or macros by modifying the example with the above problem. Let's take a look at the Regular DLL using shar ed mfc dll type:

Add the following statement before the first statement of the ShowDlg function in step 3 of the preceding example (to ensure that the statement is in the first line of function implementation ):

AFX_MANAGE _ STATE (AfxGetStaticModuleState ());

Then, recompile and generate DLLShared. dll and DLLShared. lib, and copy the two files to the Debug directory of the Use Project. Compile and run use.exe. click the button to see the dialog box we added to the DLL during the pop-up, instead of the box about use.exe.

Through the above explanation, I believe you already know the role of this statement. After the first line of the Sho wDlg function is added, the MFC Library automatically switches the status of the current module every time the DLL application is called to use the function, this ensures the correctness of resource reading.

AFX_MANAGE_S TATE (AfxGetStaticModuleState ());
Is to automatically switch the current module status, you can also manually switch the current module status by using AfxGetRes ourceHandle and AfxSetResourceHand le. The usage is as follows:
Add the following statement before the first statement of the ShowDlg function in step 3 of the preceding example (to ensure that the statement is in the first line of function implementation ):

HINSTANCE save_hInstance = Af xGetResourceHandle ();

Af xSetResourceHandle (theApp. m_hI nstance );

After the dialog box is successfully called, that is, dlg. DoModal ();
Then, add:
AfxS etResourceHandle (save_hInstanc e );

After entering the ShowDlg function, This method uses AfxGetResourceHandle to obtain and save the handle of the Current Status Module. Then obtain the DLL module handle theApp. m_hInstance (of course, you can also use the GetModuleH andle function to obtain the DLL module handle), and use the AfxSetR esourceHandle function to set it to the current state. Finally, after the call dialog box is successful, use the AfxSetResourceHa ndle resource handle to restore the current module status.

This is troublesome, but one advantage is that the resource handle can be restored immediately after the resource usage task is completed. AFX_MANAGE_STATE (AfxGetStaticModuleState ());
The resource handle can be restored only after the function's workspace ends. Because the executable file must be re-painted with a toolbar, we recommend that you restore the resource handle whenever possible. Otherwise, you may encounter many problems. For example, if the user moves the DLL dialog box and the resource handle is still the DLL resource, the program will crash. The best time to restore the handle is when the dialog box responds to the WM_INITDIALOG message, because the template of the dialog box has been read.

For m fc Extension DLL (using shared mfc dll) type mfc dll, the method for switching the current module status is similar to that used by Regular DLL using shared mfc dll type mfc dll, this example is not provided here. The difference between the two is as follows:

Use AFX_MANAGE_STATE (AfxGetSt aticModuleState () in the MFC extension d ll ());
The following error occurs:

Mfcs42d. lib (dllmodul. o bj): error LNK2005: _ pRawDll Main already defined in dllext end. obj
Mfcs42d. lib (dllmod ul. obj): error LNK2005: _ DllM ain @ 12 already defined in dlle xtend. obj
Mfcs42d. lib (dllm odul. obj): error LNK2005: _ p RawDllMain already defined in dllextend. obj

Therefore, in the MFC extension DLL, AFX_MANAGE_STATE (AfxGet StaticModuleState () must be set ());
Change to AFX_MAN AGE_STATE (AfxGetAppModuleState ());
In order to switch the current module status correctly.

The AfxGetResourceHandle and Af xSetResourceHandle methods in the MFC extension DLL are the same as those used in the Regular DLL using shared mfc dll type mf c dll. In addition, the DLL module handle can be obtained through the hModule Member of the DlgextentDLL structure provided by MFC. AfxSetResourceHandle (DlgextentDLL. hModule );
Statement.

Of course, for DLL dynamically linked to MFC, you can also use the AfxGetResourceHan dle and AfxSetResourceHandle functions in the MFC application that calls the d ll to switch the current status module. The handle of the DLL module can be obtained using the GetModuleH andle function. I will not go into details here.

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.