[CEndSession : End Session handler (CHook derived class) ] |
Environment: Win 95/98 VC6 SP4
Management of End Session
Most programmers forget/aren't aware of a situation where some app
calls ExitWindowEx (want to end-session) : End Windows session by booting/ logging off. When this happens windows starts a process of End-Session.
The first thisng that windows does is query whether all applications in the system are willing to let
the system end ist session (well , comittinf suicide is rather the same).
A hidden implementation in DefWindowProc and the window procedure of the basic window in the system returns TRUE,
means uts permits . This may result in a lost of unsaved data , because the system shuts down.This is why any application needs a
manager for this unique situation.
The manager is based on the CHook class : it hooks the window procedure of the top level window,
(mainly in MFC apps : CFrameWnd derived class) , and manipulate the relevant messages :
WM_QUERYENDSESSION ,WM_ENDSESSION.
Manipulation of these messages
An arriving WM_QUERYENDSESSION message indicates the system asks the window : "Do you permit to continue with the boot process?"
The default implementation in CEndSession is returning TRUE (Though its logical to return FALSE , because the DefWindowProc returns TRUE,
:so implementation of this function isn't necessary . I did returned TRUE to make programmers aware of situation (and message : that should be handeled
in various ways :TRUE/FALSE ).
When the system sends EndSession you need to check WPARAM parameter .
if TRUE : then the ststem does Ends and the app has the opportunity to save any data it loaded.
(It also means that every top level windows in the system -applications- allowed the continuation of process).
If WPARAM contains FALSE . The system doesnt boot(or logoff...) and youre free to continue
everything you already did . (and needs to reload data if you started unloading when previous message : WM_QUERYENDSESSION
reached the handler.)
Using this class
Since only top level window is involved in in this situation you need only one class of this type,
per instance.
How to create(copied from source code) : (read source code for more)
CEndSession class : This class manages situation of end session : when some application calls ExitWindows (whenever the situation is ... for example : when installing new hardware...) it sends all top level windows (or apps) in the system the message :WM_QUERYENDSESSION . an application should respond to that message : save its data. The default implementation in DefWindowProc in insufficient (return TRUE to permit) in case that an app has some critical data so it has to save data. How to use : 1) Override this class and override virtual functions : 2) Create session manager (it actually hooks the main wnd) 3) instantiate the class as a member variable in CFrameWnd derived class and call Create inside the function of OnCreate handler : AFTER the CFrameWnd was created. class CMySessionMgr : public CEndSession { protected: // of you permit to end session no need to override this function // because CEndSession permits it. BOOL OnPermitEndSession() { return FALSE; } virtual void OnSessionEnding() { // I allow continuation of boot process but only after saving // my data ... (use can do it asynchonously and start the process //of unloading modules in OnPermitEndSession but you'll take the risk of need to reload them if ExitWindows (boot/reset...) is canceled) CDocument *pDoc = GetDocument(); // some function to get document // or place where data is stored : no such function in CFrameWnd so // you build one or use you view to get it. CDocument::OnSaveDocument(...) // save data // all the process of saving may be done here } virtual void OnSessionNotEnded() { // do what you have to do : If you want to shoot , shoot dont talk! // (Its really late). If you did something (unloaded something) when // OnPermitEndSession was called its time that you reload it back // because system doesnt going to be unloaded. } }; // Example for instantiation of class: class CMainFrame : public CFrameWnd { ... protected: CMySessionMgr m_sessionMgr; }; // in cpp file int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; // check responce : assert or verify responce ASSERT(m_sessionMgr.Create()); // A better approach is to : VERIFY(m_sessionMgr.Create()); // creating toolbars .... status bar etc ... // ... return 0; }