LearningMFC
Jump to navigation
Jump to search
This page contains notes on MFC.
A lot of the content of this page is in German - I never got around to translate this.
References
General
Window management
- http://msdn.microsoft.com/en-us/library/1xb05f0h.aspx (CWnd Class Reference)
- http://msdn.microsoft.com/en-us/library/kc6x1ya0.aspx (Window Objects)
- http://msdn.microsoft.com/en-us/library/ms632597.aspx (About Windows)
- http://msdn.microsoft.com/en-us/library/ms632599.aspx (Window Features)
- http://msdn.microsoft.com/en-us/library/ms632598.aspx (Using Windows)
Overview
- MFC = Microsoft Foundation Classes
- MFC is a C++ class library that provides an object-oriented wrapper around parts of the Win32 API.
- When you start working with MFC you'll soon realize that the layer is very thin.
- Sometimes the question arises: Is this object orientation at all?
- The reason is historical: At the time when MFC was created (1992) C++ was practically in its infancy when it came to commercial application development.
- MFC is not just a library, it's also an application framework.
- The prefix "Afx" means "Application Framework Extensions". This was MFC's name while it was developed.
MFC macros and functions
- AfxGetStaticModuleState()
-
- http://msdn.microsoft.com/en-us/library/cc6feexs.aspx
- Code example:
AFX_MANAGE_STATE(AfxGetStaticModuleState());
- The current module state temporarily is changed until end of scope.
- The new state is the state of the module to which the code currently executing belongs.
- This construct is used, for instance, to change the module state before a resource is loaded.
- AfxGetInstanceHandle()
-
- http://msdn.microsoft.com/en-us/library/36z3tfsb.aspx
- Returns an HINSTANCE module handle.
- This is either the handle of the application (.exe), or the handle of the DLL to which the function belongs that is currently executing.
- Important: The latter only works for DLLs that are linked against the USRDLL version of MFC.
- AfxFindResourceHandle()
-
- http://msdn.microsoft.com/en-us/library/zf0f9ezz.aspx
- Searches through the "resource chain" for the specified resource (resource ID and type)
- Returns an HINSTANCE module handle of the module (.exe or .dll) that contains the resource.
- Searches through all DLLs that are currently loaded.
- TODO: It is currently not clear in which order the resource chain is searched.
- AfxGetResourceHandle()
-
- http://msdn.microsoft.com/en-us/library/zaewt3xs.aspx
- Returns an HINSTANCE module handle.
- This is the handle of the module (.exe oder .dll) that contains the default resources of the application.
- The return value can be used, for instance, for invoking FindResource() or LoadString()
- When the application starts the handle refers to the .exe, but it can be changed - see the next entry.
- AfxSetResourceHandle()
-
- http://msdn.microsoft.com/en-us/library/d8ws31ff.aspx
- Requires an HINSTANCE module handle parameter
- Sets the module (.exe or .dll) that contains the default resources of the application.
- This is the handle that AfxGetResourceHandle() returns.
- Purpose: Load a dedicated resource DLL with LoadLibrary(), then "point" MFC to it.
Window Management
CWnd
- GUI windows are identified by an HWND handle
- A CWnd object exists separately from the actual GUI window object, but is coupled with it via the HWND reference
- The HWND reference is available via the public member variable
m_hWnd
- Many global API functions, which require an HWND parameter, are accessible as CWnd member functions
- The member functions invoke the corresponding global API functions and simply pass the HWND reference contained by the CWnd object
- The HWND reference is available via the public member variable
- Lifecycle of CWnd and the GUI window object
- Create
- Someone creates the CWnd object
- Someone invokes CWnd::Create()
- As a side effect CWnd::Create() stores the HWND reference in the CWnd object
- Before CWnd::Create() returns control to the caller the following things happen in the listed order:
- WM_NCCREATE is sent, which causes CWnd::OnNcCreate() to be called, after the non-client area of the windows is created
- WM_CREATE is sent, which causes CWnd::OnCreate() to be called, after the client area of the window is created
- Destruction
- Someone invokes CWnd::DestroyWindow()
- If the function is not explicitly called, the GUI window object is destroyed in ~CWnd() at the latest; CWnd::DestroyWindow() in this case is not called.
- The function sends WM_DESTROY and WM_NCDESTROY
- The function is invoked by the default implementation of CWnd::OnClose()
- Apparently there are CWnd subclasses in MFC that never invoke CWnd::DestroyWindow() (e.g. CFramwWnd subclasses)
- For those cases some user code must explicitly invoke CWnd::DestroyWindow()
- CWnd::OnNcDestroy()
- Is automatically invoked as part of the window destruction cycle - it's the last function that is called in the cycle
- The default implementation of CWnd::OnNcDestroy() performs cleanup and then invokes CWnd::PostNcDestroy()
- The function should not be overridden; if an override is created it must invoke the default implementation.
- CWnd::PostNcDestroy()
- The function should be overridden to perform user code cleanup
- One possible application is
delete this
- Someone destroys the CWnd object
- Someone invokes CWnd::DestroyWindow()
- Create
- CWnd and HWND reference
- HWND CWnd::Detach()
- Removes the reference to the window object from the CWnd
- BOOL CWnd::Attach(HWND)
- Adds a reference to a window object to a CWnd
- HWND CWnd::Detach()
Window hierarchy
- Ein Window kann Child Windows haben
- Der Begriff "Child Window" ist in diesem Kontext unabh‰ngig davon, ob das Window mit dem Style WS_CHILD erzeugt wurde oder nicht
- Beim Erzeugen des Child Windows mit CWnd::Create() wird ein Handle auf das Parent Window angegeben
- Wird kein Handle angegeben (null), so ist das Window ein Child des Desktop Window
- Es wird WM_PARENTNOTIFY an den Parent gesendet, nachdem das Child Window erzeugt wurde (*nach* WM_NCCREATE und WM_CREATE auf dem Child)
- Wird das Child Window mit CWnd::DestroyWindow() oder ~CWnd() zerstˆrt, so wird es automatisch vom Parent entfernt
- Es wird WM_PARENTNOTIFY an den Parent gesendet, bevor die eigentliche Zerstˆrung stattfindet
- Hat ein Parent Window noch Child Windows, so werden diese von CWnd::DestroyWindow() automatisch zerstˆrt, und zwar vor dem Parent Window
- Die Message WM_DESTROY wird zuerst an das Parent Window gesendet und erst danach an alle Child Windows
- Ein Fenster kann mit SetParent() einem neuen Parent zugeteilt werden (http://msdn.microsoft.com/en-us/library/ms633541.aspx)
- Scheinbar ist das nicht mˆglich f¸r "Owned Windows", sondern nur f¸r WS_CHILD Windows (siehe "Window Features" Artikel)
- SetParent() passt die Style Flags des Window nicht an, deshalb m¸ssen die folgenden Operationen bei Bedarf manuell vorgenommen werden
- Parent HWND war non-null, ist neu aber null = Der Style muss *nach* dem Aufruf von SetParent() angepasst werden
- WS_CHILD lˆschen
- WS_POPUP setzen
- Parent HWND war null, ist neu aber non-null = Der Style muss *vor* dem Aufruf von SetParent() angepasst werden
- WS_CHILD setzen
- WS_POPUP lˆschen
- Zus‰tzlich muss der UISTATE sowohl des neuen Parents als auch des Childs angepasst werden (siehe Doku von SetParent())
- IsChild() pr¸ft, ob ein Window das direkte oder indirekte Child des angegebenen Parents ist
- Child Window = Direktes Child
- Descendant Window = Indirektes Child
Messages
- CWnd und Message Maps sorgen daf¸r, dass OnFoo() Handler Methoden automatisch aufgerufen werden
Window styles
- Overlapped Window (WS_OVERLAPPED) = Top-level Window, typischerweise das Hauptfenster der Applikation mit Title Bar, Border, Client Area, etc.
- Pop-up Window (WS_POPUP) = Spezieller Typ eines Overlapped Window; Fenster dieses Typs erscheinen ausserhalb des Main Window
- Child Window (WS_CHILD) = Ein Fenster, das innerhalb der Client Area des Parent Window gezeichnet wird
- In diesem Kontext hat "Child Window" eine andere Bedeutung als die reine Parent/Child Beziehung zwischen Windows
- Wird beim Erzeugen des Window WS_CHILD angegeben, so muss *zwingend* auch ein Parent Window angegeben werden
Window roles
- Foreground/Background
- Ein Window ist mit dem Thread assoziiert, der es erzeugt hat (d.h. auch andere Threads als der Main Thread kˆnnen Windows erzeugen)
- Foreground Window = Dasjenige Window, mit dem der Benutzer zur Zeit arbeitet
- Foreground Thread = Derjenige Thread, der das Foreground Window erzeugt hat
- Background Window = Alle Fenster, die nicht das Foreground Window sind
- Background Thread = Alle Threads, die nicht der Foreground Thread sind
- Der Foreground Thread hat per Default eine leicht hˆhere Priorit‰t als die anderen Threads
- GetForegroundWindow() gibt das HWND des Foreground Window zur¸ck (http://msdn.microsoft.com/en-us/library/ms633505.aspx)
- Owned Windows
- Ein "Owned Window" ist ein WS_OVERLAPPED oder WS_POPUP Window, dessen Parent ein anderes WS_OVERLAPPED oder WS_POPUP Window ist
- Weder das Owned Window noch dessen Parent wurden also mit WS_CHILD erzeugt
- Mit anderen Worten: Beim Erzeugen eines Owned Window wird ein Parent HWND angegeben, ohne dass WS_CHILD gesetzt wird
- Owned Windows kˆnnen nach ihrem Erzeugen nicht einem neuen Parent zugeteilt werden
- Typische F‰lle f¸r Owned Windows sind Dialog Boxes und Message Boxes
- Active Window
- Dasjenige Window, mit dem der Benutzer zur Zeit arbeitet
- Im gesamten System kann immer nur ein Window das Active Window sein
- Nur top-level Windows kˆnnen zum Active Window werden
- Wird ein Child Window aktiv, so macht das System automatisch dessen top-level Parent zum Active Window
- GetActiveWindow() gibt das HWND des Active Window zur¸ck (http://msdn.microsoft.com/en-us/library/ms646292.aspx)
- *Unklar* ist zur Zeit, was der Unterschied zwischen Active Window und Foreground Window ist
- Ein Unterschied scheint zu sein, dass GetActiveWindow() null zur¸ckgibt, falls das Active Window nicht zum aktiven Thread gehˆrt
Z order
- Zus‰tzlich zu ihrer x/y-Position auf dem Bildschirm sind Windows zus‰tzlich entlang einer imagin‰ren Z-Achse angeordnet
- Diese Z-Achse hat ihren Null-Punkt im Bildschirm und zeigt von ihm weg zum Benutzer
- Das System hat eine einfache Liste mit allen Windows gem‰ss ihrer Position auf der Z-Achse
- Ein Window, das weiter vorne auf der Z-Achse liegt ¸berdeckt Windows, die weiter hinten liegen
- F¸r Details siehe den entsprechenden Abschnitt im Artikel "Window Features"