The next content is that I reship somebody's article.
Universal control initialization comctl32.dll
This is a problem that I accidentally thought of when I was reading a source code. After some research, I have posted the result and hope it will be helpful to those who are interested.
Initcommoncontrols and initcommoncontrolsex
Since Win95, Windows has provided some new Win32 controls, called universal controls. for example, toolbar, status bar, Tree View, list view, animation, hot-key, image list, and tab. the executable code of these controls is stored in comctl32.dll. to use a common control, you must load comctl32.dll.
You can call the initcommoncontrols function or initcommoncontrolsex function to initialize the control. Both functions are functions in the dynamic link library comctl32.dll. The prototype of the two functions is as follows:
Void initcommoncontrols (void );
Bool initcommoncontrolsex (lpinitcommoncontrolsex lpinitctrls );
As you can see, initcommoncontrols does not have a parameter, which indicates initializing all (in fact, most of them, see the following) general controls. initcommoncontrolsex can specify which controls to initialize.
The meaning of "initialization" is clear, that is, registering the corresponding window class. For example, you can create a window for the control only after you have registered the "systreeview32" window class in advance.
Note that the registration window class is only valid for the current process, because a window address must be specified during registration, and the address is only valid for one process. therefore, each process must be initialized before a common control can be used.
The initcommoncontrols function is an empty function and does nothing. however, if you call this function, the linker will link your program to comcl32.lib, and then load comctl32.dll when the program starts. the actual initialization work is done at the entry point of the library. Here, the common control window class will be registered, and then the application can create the control window, just like creating other child window controls.
Initcommoncontrolsex is a function used to register the control window class. It determines which controls to call the registration code based on the Content class of the parameter lpinitctrls-> dwicc. The related values are as follows:
# Define icc_listview_classes 0x00000001 // listview, Header
# Define icc_treeview_classes 0x00000002 // Treeview, tooltips
# Define icc_bar_classes 0x00000004 // toolbar, statusbar, trackbar, tooltips
# Define icc_tab_classes 0x00000008 // tab, tooltips
# Define icc_updown_class 0x00000010 // updown
# Define icc_progress_class 0x00000020 // progress
# Define icc_hotkey_class 0x00000040 // hotkey
# Define icc_animate_class 0x00000080 // animate
# Define icc_win95_classes 0x000000ff
# Define icc_date_classes 0x00000100 // month Picker, Date Picker, time Picker, updown
# Define icc_userex_classes 0x00000200 // comboex
# Define icc_cool_classes 0x00000400 // rebar (coolbar) Control
# Define icc_internet_classes 0x00000800
# Define icc_pagescroller_class 0x00001000 // page scroller
# Define icc_nativefntctl_class 0x00002000 // native font Control
Note that icc_win95_classes is equal to or of all previous values. Therefore, using this flag to call initcommoncontrolsex will initialize controls such as listview, header, and Treeview.
When a process loads a DLL for the first time, the system calls dllmain with the dll_process_attach parameter. in the dynamic library comctl32.dll, icc_win95_classes is used to mark the call to initcommoncontrolsex. Therefore, once the process loads comctl32.dll, it registers a series of general controls.
The system calls dllmain with the dll_process_detach parameter when the process uninstalls the DLL. In the dynamic library comctl32.dll, unregisterclass is called to cancel all the common control window classes that have been written.
Note:
For Windows 95/98/me, when the DLL is uninstalled, all the window classes registered in it will be automatically canceled. This is automatic and you do not need to write the unregisterclass call code.
For Windows NT/2000/XP, when the DLL is uninstalled, the window class registered in the DLL does not automatically cancel registration. Therefore, the unregisterclass must be called by human code in dllmain. otherwise, once the DLL is uninstalled and the control is created again (because there is no anti-registration, the system determines that the window class is still valid), The Window Process of the control points to an Invalid Address.
Control initialization in MFC
The delay loading method is used in MFC to initialize general controls. in this way, comctl32.dll is not loaded if the program does not use any universal control. if any common control is used, the corresponding general control is initialized in the precreatewindow function of the control. this is why you can use the depends tool to view an MFC program using a common control. Generally, the existence of comctl32.dll is invisible. in general, if you call one of the two initialization functions in your code, it will link to comctl32.dll normally.
It is easy to find the place for initializing a universal control in the source code of MFC. You just need to check when a program using a universal control loads comctl32.dll. you can debug such a program, execute it in one step or set a breakpoint for every piece of code, and then use a tool to check whether the EXE has loaded the comctl32.dll module, so that the scope is gradually reduced, it will be available soon. there are many tools to view the modules in the EXE running, such as icesword or a process management tool provided by Windows optimization master.
Take the syslistview32 control as an example. The packaging class of MFC is clistview.
Bool clistview: precreatewindow (createstruct & CS)
{
Return cctrlview: precreatewindow (CS );
}
Bool cctrlview: precreatewindow (createstruct & CS)
{
...
// Initialize common controls
Verify (afxdeferregisterclass (afx_wndcommctls_reg ));
Afxdeferregisterclass (afx_wndcommctlsnew_reg );
...
Return cview: precreatewindow (CS );
}
Afxdeferregisterclass sets different parameters based on different types of controls, and then calls _ afxinitcommoncontrols, for example, the following code:
Init. dwicc = icc_win95_classes;
Fregisteredclasses | = _ afxinitcommoncontrols (& init, afx_win95ctls_mask );
Function _ afxinitcommoncontrols initializes the actual common control.
Long afxapi _ afxinitcommoncontrols (lpinitcommoncontrolsex lpinitctrls, long ftoregister)
{
...
Hinstance hinst =: loadlibrarya ("comctl32.dll ");
...
(Farproc &) pfninit =: getprocaddress (hinst, "initcommoncontrolsex ");
If (pfninit = NULL)
{
...
}
Else if (initcommoncontrolsex (lpinitctrls ))
{
...
}
Freelibrary (hinst );
...
}
Loadlibrary and freelibrary appear in pairs to keep the reference count of DLL unchanged. the dllmain function is called only when the reference count of the DLL is changed from 0 to 1. The dllmain function is called only when the reference count of the DLL is changed from 1 to 0. in the above Code, in addition to loading and unloading the DLL, there is also a call to the initcommoncontrolsex function in the DLL, which is exactly the call that causes the system to call the loadlibrary (Note: As mentioned above, MFC uses the delayed loading technology for this DLL. Therefore, the DLL will not be loaded as soon as the program starts, but will be delayed until the first time any function or data in the DLL is accessed ). this additional call makes the registration of the universal control not canceled by the subsequent freelibrary. therefore, after this, the program can generate a window for the universal control.
As for why does MFC use direct call and function address retrieval to call initcommoncontrolsex? This is clearly stated in the function comment to adapt to various link options.
IP control provided by Windows
Windows has two important dynamic connection libraries: commctrl. dll and comctl32.dll. They are windows custom control libraries (Windows Common controls ). The custom control library contains many common Windows controls, such as statusbar, coolbar, and hotkey. In C builder, most of these controls have been packaged as visual controls. After Microsoft launched Internet Explorer 3, some controls were added to the custom control library, including windows IP address edit control ).
● Initialize the Windows custom control library ●
Windows provides two API functions: initcommoncontrols and initcommoncontrolsex, which are used to initialize the custom control library. From the name, we can easily see the relationship between the two API functions: the latter is the enhancement of the former. If you want to use the IP Control in your program, you must use initcommoncontrolsex to initialize the same type of connection to the custom control library. The prototype of the initcommoncontrolsex function is as follows:
Typedef struct taginitcommoncontrolsex {
DWORD dwsize; // size of this structure
DWORD dwicc; // flags indicating which classes to be initialized
} Initcommoncontrolsex, * lpinitcommoncontrolsex;
Wincommctrlapi bool winapi initcommoncontrolsex (lpinitcommoncontrolsex );
The IP control belongs to the icc_internet_classes class. To use this control, you should include the following initialization code in the program:
Tinitcommoncontrolsex ICC;
ICC. dwsize = sizeof (tinitcommoncontrolsex );
ICC. dwicc = icc_internet_classes;
If (! Initcommoncontrolsex (& ICC ))
Return; // component initialization failed
● Create an IP Control ●
Both the Windows API functions createwindow and createdomainwex can be used to create an IP Control instance. The window class of the IP control is "sysipaddress32". The commctrl. Pas unit of C builder defines a symbolic constant wc_ipaddress. The following statement creates an IP Control on form1.
Hwnd hipedit = createwindow (wc_ipaddress, null, ws_child | ws_visible, 10, 10, 135,47, handle, 0, hinstance, null );
● Use IP Control ●
In a program, we send a message to the IP Control to communicate with it. The IP control can respond to the following six messages. The following table lists the messages and their meanings:
Message constant message value parameters and return values
Ipm_clearaddress wm_user 100 clear IP address string parameters in the IP Control
Ipm_setaddress wm_user 101 configure the IP address string of the IP control. The lparam value is a 32-bit IP address.
Ipm_getaddress wm_user 102 obtains the IP value (32-bit integer) lparam corresponding to the IP string in the IP control as a pointer to the integer variable. The returned value is equal to the number of non-controlled fields in the IP control. The obtained IP value is stored in the integer variable pointed to by lparam.
Ipm_setrange wm_user 103 indicates the IP value range of one of the four parts of the IP control. wparam indicates the part of the value range to be configured. lparam's 16-bit characters indicate the range of this field: high byte is the upper limit, and low byte is the lower limit.
Ipm_setfocus wm_user 104 sets the input focus wparam to specify which part gets the focus
Whether the ipm_isblank wm_user 105 IP string is null or not. Return Value: If it is null, non-0 is returned. If it is not null, 0 is returned.
★(I) Clear the IP string (ipm_clearaddress)★
Sendmessage (hipedit, ipm_clearaddress, 0, 0 );
★(Ii) configure the IP string (ipm_setaddress)★
Int NIP;
Nip = makeipaddress (192,168 );
Sendmessage (hipedit, ipm_setaddress, 0, nip );
In this example, the content of the IP control is set to "192.168.0.1", where makeipaddress is a Win32 macro, defined in the commctrl. h header document, which is used to synthesize a 32-bit IP value:
# Define makeipaddress (B1, B2, B3, b4)
(Lparam) (DWORD) (B1) <24) (DWORD) (B2) <16) (DWORD) (B3) <8) (DWORD) (B4 ))))
★(3) obtain the IP value (ipm_getaddress)★
Int NIP;
Sendmessage (hipedit, ipm_getaddress, 0, INT (& NIP ));
// NIP;
// Sendmessage (hipedit, ipm_setaddress, 0, nip); // Add 1 to the IP address and then assign it to the IP control.
To obtain the IP value corresponding to the IP string in the IP control, you must send an ipm_getaddress message to the IP control and use a 32-bit integer address as the last parameter of sendmessage.
★(Iv) Configuration value range (ipm_setrange)★
Sendmessage (hipedit, ipm_setrange, 0,200 <8 | 100 );
This statement limits the range of the first part of the IP Control to 100 ~ 200. In the ipm_setrange message, wparam indicates the field to be configured, and the low 16-bit character of lparam indicates the range of this field: the high byte is the upper limit, and the low byte is the lower limit.
★(V) configure the input focus (ipm_setfocus)★
Sendmessage (hipedit, ipm_setfocus, 3, 0 );
// Set the input focus to the fourth part of the IP control.
(6) Determine whether the IP string is null (ipm_isblank)
If (! Sendmessage (hipedit, ipm_isblank, 0, 0 ))
{
// The IP string in the IP control is null.
}
Else
{
// At least some of the IP strings in the IP control are not empty
}
● IP Control notification message ●
When the IP string is changed or the input focus is transferred, the IP Control sends a notification message ipn_fieldchanged to its parent window. In most cases, we can ignore this notification message. The following is an example of processing the notification message ipn_fieldchanged:
Void _ fastcall tform1: wndproc (tmessage & MSG)
{
Lpnmhdr P = (lpnmhdr) msg. lparam;
If (msg. MSG = wm_policy)
{
If (p-> code = ipn_fieldchanged)
{
// Process the ipn_fieldchanged notification message of the IP Control
}
}
Tform: wndproc (MSG );
}