SubclassWindow and SubclassDlgItem

Source: Internet
Author: User

In general, there are three ways to map a control to a variable in a dialog box:

    1. Methods of DDX
    2. GetDlgItem methods, such as CEdit PEDT = (CEdit *) GetDlgItem (IDC_EDIT1);
    3. The SubclassWindow method (or its extended subclassdlgitem), such as CEdit M_edit;m_edit. SubclassDlgItem (IDC_EDIT1);
SubclassWindow

Cwnd::subclasswindow (HWND hwnd) calls two main operations: Attach (HWND) and WNDPROC Oldwndproc = (WNDPROC):: SetWindowLong (hwnd, Gwl_ WNDPROC, (DWORD) Afxgetafxwndproc ());

The function of the former is to set the M_hwnd in CWnd to HWND, the latter function is to change the window function for Afxgetafxwndproc () return.

Afxgetafxwndproc returned a function pointer to AfxWndProc, a pointer to a window function, AfxWndProc wrapped Afxcallwndproc, and the latter called Pwnd->windowproc (Nmsg, WParam, LParam);.

Visible SubclassWindow has completed two functions:

    1. We call the member function on the form instance to directly change the form corresponding to the related form handle (Attach)
    2. The message that the system passes to the related form handle first passes the message map (SetWindowLong) of the form instance.
SubclassDlgItem

SubclassWindow was called, but was previously called:: GetDlgItem gets the window handle for a control ID.

GetDlgItem

Just call:: GetDlgItem gets the window handle corresponding to the control ID, and then uses FromHandle to convert the handle to a CWnd pointer.

the difference between SubclassDlgItem and GetDlgItem

If you just want to invoke a control corresponding to the method of the class, there is little difference. Just the former generates a class object, and the latter gets a pointer to the object.

However, if the message is relevant, the former will have a corresponding message. For example:

For example, I wrote a class called Csuperedit (the parent class is CEdit), in which I declared void OnChar (UINT NChar, uint nrepcnt, uint nflags), and added a On_wm_char line to the message loop. Now I'll just declare csuperedit m_edit in the dialog box Cprog1dlg, and then in Cprog1dlg::oninitdialog, add the following code to complete the superclass:

HWND Hwndcontrol =:: GetDlgItem (Pparent->m_hwnd, idc_edit1);

M_edit. SubclassWindow (Hwndcontrol);

In this way, the message processing flow of a control can be dynamically changed so that the overloaded messages in the Csuperedit can be executed. If you do not use sub-typing, you cannot execute it.

Example:::

Many Windows programmers are skipping the SDK directly for RAD development tools [or VC, I think VC should not belong to RAD] learning, some people may be more unfamiliar with the mechanism of sub-class. Let's start by looking at what is the subclass of Windows.

Windows has given us or given itself a lot of rich general-purpose controls, such as: Edit, ComboBox, ListBox ... And so on, these controls are feature-rich and can bring great aspects to our development, just imagine how hard it is for us to implement an edit control alone! However, there are still some situations in the actual development of these standard controls, such as: In our application requires an edit to get the teacher's evaluation of students A, B, c[do not say to me you want to use a ComboBox to implement J], at this time, required in the edit to prohibit the input of other letters, numbers, What to do? The edit control itself does not provide such a mechanism, and we can use subclasses to solve such problems well.

We know that every Windows window [here is edit] has a window handler that is responsible for message processing, and the subclass method is to use our own message processing functions instead of the original, standard processing functions of the window. Of course our own window handlers are only concerned with those specific messages [where the WM_CHAR is of course], while other messages are sent back to the original window function.

The implementation method in the SDK is to call the function SetWindowLong:

WNDPROC * Oldwndproc = (WNDPROC) SetWindowLong (HWnd, GWL_WNDPROC, (DWORD) Afxgetafxwndproc ()); where Afxgetafxwndproc () is our own window processing function, in which we have processed the message we are interested in, it is possible to return to the original window processing function pointer oldwndproc to the other message by the standard method, please refer to the relevant information.

But to the MFC "era", everything is packaged up, the original window class registration, window functions are gone [or stealth], I think for those "inquisitive" programmers are interested in understanding the sub-class mechanism in MFC, I do a little "exploration" to make a summary, I hope to give you some inspiration.

Let's first use MFC to implement the requirements I mentioned above: an edit control that can only input a,b,c. The interface at startup is as follows: Only A, B, C can be entered, and only one letter is allowed.

Implementation method: First derive a own class Csuperedit,ctrl + W, in which to process the WM_CHAR, and then edit the message handler function:

void Csuperedit::onchar (UINT NChar, uint nrepcnt, uint nflags)

{

Todo:add your message handler code here and/or call default

TCHAR CH[20];

GetWindowText (ch,20);

if (strlen (ch) = = 1 && (nChar <= ' C ' && nChar >= ' A '))

Return

if (NChar! = ' A ' && nChar! = ' B ' && nChar! = ' C ')

Return

Cedit::onchar (NChar, nrepcnt, nflags);

}

Then add a data member Csuperedit M_edit to our Cprog1dlg class, in Cprog1dlg::oninitdialog () into: M_edit. SubclassDlgItem (Idc_edit1,this);

M_edit. SetWindowText ("< Please enter a, B, c>");

and process the notification message sent by edit to Dialog: En_setfocus:

void Cprog1dlg::onsetfocusedit1 ()

{

Todo:add your control notification handler code here

M_edit. SetWindowText (""); M_edit. SetFocus ();

}

OK, everything is done! How easy it is to compare with the sub-class method of the SDK! Let's see what MFC has done behind our backs! Here are the main solutions to two easy to let beginners more puzzled questions:

1, M_edit is just a C + + class object that we define, why do we call its member function SetWindowText can control the resource number in our program is: Idc_edit1 control?

2. Why can the Csuperedit class handle WM_CHAR messages? As you know, control Windows window, controls, resources ... are implemented through their handles, such as Hhandle, HWND, HDC are handles, it is represented as a 32-bit long shaping data, stored in a specific area of windows, we can interpret it as pointing to the window, control, resource index we want to control, with it, We can control the objects we want to control. Here you can think of why most API functions have a parameter HWND hwnd!

BOOL SetWindowText (HWND hwnd,//Handle to window or control LPCTSTR lpstring//title or text);

Our C + + variable M_edit to control the IDC_EDIT1, but also through its handle, but how is this implemented? You may have noticed the m_edit. SubclassDlgItem (idc_edit1,this); Yes, that's the key! Here F9 set breakpoints, after F5, the program arrives here, F11 follows into SubclassDlgItem function: BOOL cwnd::subclassdlgitem (UINT NID, cwnd* pparent)

{

ASSERT (pparent! = NULL);

ASSERT (:: IsWindow (Pparent->m_hwnd)); Check for normal dialog control first HWND

Hwndcontrol =:: GetDlgItem (Pparent->m_hwnd, NID);

if (Hwndcontrol! = NULL)

Return SubclassWindow (Hwndcontrol);

#ifndef _afx_no_occ_support

if (pparent->m_pctrlcont! = NULL)

{

Normal dialog control not found

colecontrolsite* psite = Pparent->m_pctrlcont->finditem (NID);

if (psite! = NULL)

{

ASSERT (Psite->m_hwnd! = NULL);

VERIFY (SubclassWindow (Psite->m_hwnd));

#ifndef _afx_no_occ_support//If The control has reparented itself (e.g., invisible control),//Make sure that the CWnd Gets properly wired to its control site.

if (Pparent->m_hwnd! =:: GetParent (Psite->m_hwnd)) Attachcontrolsite (pparent);

#endif

!_afx_no_occ_support return TRUE;

}

}

#endif return FALSE; Control not Found} code at the beginning of the incoming parent window to do some checking, and then is

HWND Hwndcontrol =:: GetDlgItem (Pparent->m_hwnd, NID);

if (Hwndcontrol! = NULL)

Return SubclassWindow (Hwndcontrol);

This is the key code, first use Hwndcontrol to get our idc_edit1 control handle, and then call the SubclassWindow function, this function is the key to implementation, we look at what it does:

BOOL Cwnd::subclasswindow (HWND hwnd)

{

if (! Attach (HWND))

return FALSE;

Subclassing to occur

Presubclasswindow (); Now hooks into the AFX WndProc

wndproc* LPLPFN = Getsuperwndprocaddr ();

WNDPROC Oldwndproc = (WNDPROC):: Setwindowlongptr (HWnd, Gwlp_wndproc, (INT_PTR) Afxgetafxwndproc ());
ASSERT (Oldwndproc! = Afxgetafxwndproc ());
if (*LPLPFN = = NULL) *lplpfn = Oldwndproc; The first control of that type created
#ifdef _DEBUG
else if (*lplpfn! = Oldwndproc)
{
TRACE (traceappmsg, 0, "error:trying to use SubclassWindow with incorrect cwnd/n");
TRACE (traceappmsg, 0, "/tderived class./n");
TRACE (traceappmsg, 0, "/thwnd = $%08x (nidc=$%08x) is not a%hs./n",
(UINT) (uint_ptr) HWnd, _afxgetdlgctrlid (hwnd), Getruntimeclass ()->m_lpszclassname);
ASSERT (FALSE); Undo the subclassing if continuing after assert
:: Setwindowlongptr (HWnd, Gwlp_wndproc, (INT_PTR) oldwndproc);
}
#endif return TRUE;
}
The function attach is internally as follows:
BOOL Cwnd::attach (HWND hwndnew)
{
ASSERT (m_hwnd = = NULL); Only attach once, detach on destroy
ASSERT (fromhandlepermanent (hwndnew) = = NULL); Must not already is in permanent map
if (hwndnew = = NULL) return FALSE; chandlemap* PMap = Afxmaphwnd (TRUE); Create map if not exist
ASSERT (PMap! = NULL);
Pmap->setpermanent (m_hwnd = hwndnew, this);
#ifndef _afx_no_occ_support Attachcontrolsite (PMAP);
#endif
return TRUE;
}
This is to show that
Pmap->setpermanent (m_hwnd = hwndnew, this); it assigns the handle of our idc_edit1 to the data member Csuperedit the class M_hwnd [ Don't forget that our Csuperedit class is derived from CEdit],
People may have now vaguely understood something, yes, in M_edit. SetWindowText ("< Please enter a, B, c>"), it is through this data member M_hwnd implementation of the IDC_EDIT1 control:
void Cwnd::setwindowtext (LPCTSTR lpszstring)
{
ASSERT (:: IsWindow (m_hwnd));
if (M_pctrlsite = = NULL):: SetWindowText (M_hwnd, lpszstring);
else M_pctrlsite->setwindowtext (lpszstring);
}
Other functions of the CEdit class are also wrapped around "M_hwnd + API Functions". The DDX_Control method we commonly use is also called SubclassWindow. What do you think? Do you understand the context of the first question?
Now take a look at the second question: Why does the Csuperedit class handle WM_CHAR messages? Perhaps some friends are now puzzled, although through the handle to achieve the M_edit to Idc_edit control, but the message sent to it still ran to edit the standard processing function, how to handle the WM_CHAR how to achieve it? If the message goes to the standard processing function of edit, then of course it can't be handled! I wonder if you have seen such a small segment in the SubclassWindow function above I added the key indicator://Now hooks into the AFX WndProc wndproc* lplpfn = getsuperwndprocaddr (); WNDPROC Oldwndproc = (WNDPROC):: SetWindowLong (HWnd, GWL_WNDPROC, (DWORD) Afxgetafxwndproc ()); ASSERT (Oldwndproc! = (WNDPROC) afxgetafxwndproc ()); if (*LPLPFN = = NULL) *lplpfn = Oldwndproc; The first control of that type created is linked to the SDK neutron-class mechanism we're talking about, okay? MFC in here do not know the bogus to engage in the activities! This afxgetafxwndproc () function is this: WNDPROC AFXAPI Afxgetafxwndproc () {#ifdef _afxdll return afxgetmodulestate ()->m_ Pfnafxwndproc; #else return &AfxWndProc; #endif} Read Mr. Houtie "in the understanding of MFC" Friends do not know whether or not remember MFC command routing mechanism is based on this function as the starting point! So when the program receives the WM_CHAR to edit, it should have called the Edit Standard window handler function, which is now changed to call Lresult CALLBACK AfxWndProc (HWND hwnd, UINT nmsg, WPARAM WPARAM, LPARAM LParam), and then wm_char the message for a series of flows, and finally successfully reached our handler function Csuperedit::onchar (UINT NChar, uint nrepcnt, uint nflags), as to how it was going, how it arrived.Please refer to "MFC in Simplified Chinese" [If your book is a traditional electronic version, please read from page 566]. Finally, we walked out of the MFC sub-class maze.

SubclassWindow and SubclassDlgItem

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.