Wxwidgets Source Analysis (5)-Window management

Source: Internet
Author: User
Tags win32 window wxwidgets

Window Management

All windows are inherited from wxTopLevelWindows :

WXDLLIMPEXP_DATA_CORE(wxWindowList) wxTopLevelWindows;wxTopLevelWindows
frame window creation Process

When using the frame window, we typically inherit from Wxframe, which is created by invoking the Create method:

debugWXFrame::debugWXFrame(wxWindow* parent,wxWindowID id){    ...    Create(parent, id, wxEmptyString, wxDefaultPosition, ...);    ...}

Let's look at wxFrame the inheritance of the class:

wxFrame -> wxFrameBase -> wxTopLevelWindow ->         -> wxTopLevelWindowMSW(wxTopLevelWindowNative) -> wxTopLevelWindowBase         

Note: Wxtoplevelwindow inherits from Wxtoplevelwindownative, but wxtoplevelwindownative is a macro definition and is defined in the include/wx/toplevel.h file as follows:

#if defined(__WXMSW__)    #include "wx/msw/toplevel.h"    #define wxTopLevelWindowNative wxTopLevelWindowMSW

We then look at the process of creating the window, wxFrame invoking wxTopLevelWindow::Create the creation of the implementation window:

    1. Add a window to the wxTopLevelWindows queue, this global variable holds pointers to all current Topwindow;
    2. CreateBaseUsed to set the basic parameters;
    3. Depending on the window type, the CreateDialog creation is called or CreateFrame executed separately.
bool wxFrame::Create(wxWindow *parent, ...){    if ( !wxTopLevelWindow::Create(parent, id, title, pos, size, style, name) )        return false;    ...}bool wxTopLevelWindowMSW::Create(wxWindow *parent, ...){    // notice that we should append this window to wxTopLevelWindows list    // before calling CreateBase() as it behaves differently for TLW and    // non-TLW windows    wxTopLevelWindows.Append(this);    bool ret = CreateBase(parent, id, pos, sizeReal, style, name);    if ( !ret )        return false;    if ( parent )        parent->AddChild(this);    if ( GetExtraStyle() & wxTOPLEVEL_EX_DIALOG )    {        ...        ret = CreateDialog(dlgTemplate, title, pos, sizeReal);        free(dlgTemplate);    }    else // !dialog    {        ret = CreateFrame(title, pos, sizeReal);    }    return ret;}

Continue to look CreateFrame , according to the inheritance relationship we can find the actual call is wxTopLevelWindowMSW::CreateFrame , this function call MSWCreate implementation window creation:

bool wxTopLevelWindowMSW::CreateFrame(const wxString& title,                                      const wxPoint& pos,                                      const wxSize& size){    WXDWORD exflags;    WXDWORD flags = MSWGetCreateWindowFlags(&exflags);    const wxSize sz = IsAlwaysMaximized() ? wxDefaultSize : size;        return MSWCreate(MSWGetRegisteredClassName(),                     title.t_str(), pos, sz, flags, exflags);}

Let's take a look at the parameters of this function, which is MSWGetRegisteredClassName used to register the window class

Note: When creating a custom window, a Windows program needs to call:: RegisterClass registers the window class, creates a custom window class, registers the window class before using the window class, and registers the window class with RegisterClass.

MSWGetRegisteredClassNamewxApp::GetRegisteredClassNameto register by calling:

    1. First, query whether this window class already exists, if present, use registered;
    2. The name of the registered window class is wxWindow , the message handler function is wxWndProc ;
    3. After the registration is successful, put this type into gs_regClassesInfo the

Note: Two types of windows are registered here, one marked and the other without this tag, and when the window is created, it is CS_HREDRAW | CS_VREDRAW wxFULL_REPAINT_ON_RESIZE used without the tag window type, otherwise the window type with the tag is used:

Implementation code:

/* Static */const Wxchar *wxwindowmsw::mswgetregisteredclassname () {return wxapp::getregisteredclassname (WxT (" Wxwindow "), color_btnface);} Const Wxchar *wxapp::getregisteredclassname (const Wxchar *name, ...)    {Const size_t count = Gs_regclassesinfo.size (); for (size_t n = 0; n < count; n++) {if (gs_regclassesinfo[n].regname = = name) return GS_REGCL    Assesinfo[n].regname.c_str ();    }//We need to register this class WNDCLASS wndclass;    Wndclass.lpfnwndproc = (WNDPROC) Wxwndproc; Wndclass.style = Cs_hredraw | Cs_vredraw | cs_dblclks |    Extrastyles;    Classreginfo Regclass (name);    Wndclass.lpszclassname = RegClass.regname.t_str (); if (!::registerclass (&wndclass)) ... wndclass.style &= ~ (Cs_hredraw |    Cs_vredraw);    Wndclass.lpszclassname = RegClass.regnameNR.t_str ();    if (!::registerclass (&wndclass)) ... gs_regclassesinfo.push_back (regclass); Return Gs_regclassesinfo.back (). Regname.t_str ();} 

Continue to look at the actual creation function of the window MSWCreate :

    1. Depending on whether the window tag has a wxFULL_REPAINT_ON_RESIZE decision to use that window class;
    2. Called ::CreateWindowEx to create a real window, the window handle saved in m_hWnd .
    3. Note that there is a more important function here to SubclassWin(m_hWnd) Save this window handle to the system, after the app received the message, through this handle to find which Wxwindow associated with this handle, will be detailed later.
bool wxWindowMSW::MSWCreate(const wxChar *wclass, ...){    int x, y, w, h;    (void)MSWGetCreateWindowCoords(pos, size, x, y, w, h);    int controlId = style & WS_CHILD ? GetId() : 0;    wxString className(wclass);    if ( !HasFlag(wxFULL_REPAINT_ON_RESIZE) )    {        className += wxApp::GetNoRedrawClassSuffix();    }    wxWindowCreationHook hook(this);    m_hWnd = (WXHWND)::CreateWindowEx                       (                        extendedStyle,                        className.t_str(), ...                       );    SubclassWin(m_hWnd);    return true;}

Another call for attention is that wxWindowCreationHook hook(this); this class is used to write the current window's pointer to a global variable, which is used in the gs_winBeingCreated wxWinProc function, as described below.

wxWindowCreationHook::wxWindowCreationHook(wxWindowMSW *winBeingCreated){    gs_winBeingCreated = winBeingCreated;}
Window Global Management

Wxwidgets is a Windows-based Win32API to implement window operations, including the message mechanism, there is a question is how Wxwindow class associated with the Win32 window class?

In fact, the implementation of wxwidgets is very simple, through a global map table to save, the index is HWND, the target is the Wxwindow pointer, so you can Win32 handle directly find Wxwindow.

wxGUIEventLoop::PreProcessMessageWe see the following code:

bool wxGUIEventLoop::PreProcessMessage(WXMSG *msg){    HWND hwnd = msg->hwnd;    wxWindow *wndThis = wxGetWindowFromHWND((WXHWND)hwnd);

Which wxGetWindowFromHWND is used to map from the HWND to the Wxwindow pointer, this function implementation, through the call to wxFindWinFromHandle get the corresponding window, there is also processing is if the current HWND cannot find the window, then use the window's parent window to find.

extern wxWindow *wxGetWindowFromHWND(WXHWND hWnd){    HWND hwnd = (HWND)hWnd;    wxWindow *win = NULL;    if ( hwnd )    {        win = wxFindWinFromHandle(hwnd);    }    while ( hwnd && !win )    {        hwnd = ::GetParent(hwnd);        win = wxFindWinFromHandle(hwnd);    }    return win;}

Continue to look, wxFindWinFromHandle it is through in the gs_windowHandles search, and then we look at gs_windowHandles the definition, he is a hashmap table, similar to std::map the function, the implementation can be self-looking code:

wxWindow *wxFindWinFromHandle(HWND hwnd){    WindowHandles::const_iterator i = gs_windowHandles.find(hwnd);    return i == gs_windowHandles.end() ? NULL : i->second;}WX_DECLARE_HASH_MAP(HWND, wxWindow *,                    wxPointerHash, wxPointerEqual,                    WindowHandles);WindowHandles gs_windowHandles;
Window HWND timing associated with Wxwindows

Management mechanism Yes, let's see when this window was registered. In general, there are two times when the HWND is associated with the Wxwindows window:

    1. The link is called when the window is created wxWindowMSW::SubclassWin ;
    2. Associated in a message handler function wxWndProc .
After you create a complete association

After the window is created, the call puts SubclassWin this window into the global variable, and the gs_windowHandles wxAssociateWinWithHandle associated HWND and Wxwindow are called in the function:

void wxWindowMSW::SubclassWin(WXHWND hWnd){    wxAssociateWinWithHandle(hwnd, this);    // we‘re officially created now, send the event    wxWindowCreateEvent event((wxWindow *)this);    (void)HandleWindowEvent(event);}

Keep Tracking wxAssociateWinWithHandle , this is a global function, which is to associate the data together:

void wxAssociateWinWithHandle(HWND hwnd, wxWindowMSW *win){    gs_windowHandles[hwnd] = (wxWindow *)win;}
Associating in Wxwndproc

The window message processing function is unified wxWndProc , this function in the first after entering the wxwindows based on the HWND, find not to directly associate this HWND to the newly created window.

The key global variable gs_winbeingcreated, which is called in Wxwindowmsw::mswcreate, writes itself to the Gs_ by Wxwindowcreationhook constructor when creating the window. Winbeingcreated this is associated with the first time a message is received and the wxwindows corresponding to the HWND is not found.

// Main window procLRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){    wxWindowMSW *wnd = wxFindWinFromHandle(hWnd);    // 关联HWND和wxWindows    if ( !wnd && gs_winBeingCreated )    {        wxAssociateWinWithHandle(hWnd, gs_winBeingCreated);        wnd = gs_winBeingCreated;        gs_winBeingCreated = NULL;        wnd->SetHWND((WXHWND)hWnd);    }    LRESULT rc;    if ( wnd && wxGUIEventLoop::AllowProcessing(wnd) )        rc = wnd->MSWWindowProc(message, wParam, lParam);    else        rc = ::DefWindowProc(hWnd, message, wParam, lParam);    return rc;}
Why does it appear in two places?

In a Windows system, once the call to the CreateEx function Creation window is complete, the window will immediately receive the message, which is called wxWndProc for processing, the problem is that there is no call wxWindowMSW::SubclassWin to associate, so the solution is to use the right time to perform the association, This associated window is passed through a global variable.

Summarize

Wxwidgets provides a complete window management mechanism, effectively combined with the Windows system to form a good middle layer, completely shielding the WIN32API, so that users no matter on which platform to write GUI code, no need to know the platform information.

Wxwidgets Source Analysis (5)-Window management

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.