#define WIN32_LEAN_AND_MEAN
#include "windows.h"
#include <stdio.h>
#include "resource.h"
const long cPauseTimeout = 45000; //milliseconds
const long cUserTimeout = 15; //seconds
enum DialogState {cNotSet, cCancel, cOk, cTimeout};
class BePolite
{
public:
explicit BePolite(HINSTANCE h)
: mAppInstance(h)
{
}
bool IsUserCancelled()
{
return mDialogState == cCancel;
}
void AskUser(void)
{
mDialogState = cNotSet;
RunMsgLoop(::CreateDialog(mAppInstance, MAKEINTRESOURCE(IDD_DLG), ::GetDesktopWindow(), DialogProc));
}
private:
void RunMsgLoop(HWND dlghwnd)
{
MSG Msg;
while (GetMessage(&Msg, NULL, 0, 0))
{
if (IsDialogMessage(dlghwnd, &Msg))
continue;
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
}
static BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static DialogProcHandler h;
h.DlgHwnd = hwndDlg;
switch(uMsg)
{
case WM_INITDIALOG: h.OnInitDialog(); return 1;
case WM_TIMER: h.OnTimer(); return 1;
case WM_DESTROY: h.OnDestroy(); return 0;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDOK: h.OnOk(); return 1;
case IDCANCEL: h.OnCancel(); return 1;
default: return 0;
}
default: return 0;
}
}
//-----------------------
class DialogProcHandler
{
public:
HWND DlgHwnd;
int mTime;
void OnInitDialog()
{
mTime = cUserTimeout;
SetTimeoutText();
StartOneSecondTimer();
::ShowWindow(DlgHwnd, SW_SHOW);
}
void OnDestroy()
{
::PostQuitMessage(mDialogState);
}
void OnTimer()
{
if (mTime <= 0)
{
SetState(cTimeout);
EndDialog();
}
else
{
mTime--;
SetTimeoutText();
}
}
void OnOk()
{
SetState(cOk);
EndDialog();
}
void OnCancel()
{
SetState(cCancel);
EndDialog();
}
private:
void EndDialog()
{
KillTimer(DlgHwnd, TimerId);
DestroyWindow(DlgHwnd);
}
void SetState(BePolite::DialogState newstate)
{
if (mDialogState == cNotSet)
mDialogState = newstate;
}
void StartOneSecondTimer()
{
SetTimer(DlgHwnd, TimerId, 1000, NULL);
}
void SetTimeoutText()
{
char buf[20];
sprintf(buf, "%d", mTime);
::SetWindowText(GetDlgItem(DlgHwnd, IDC_TIMEOUTTEXT), buf);
}
} ;
private:
static const int TimerId = 99;
static DialogState mDialogState;
HINSTANCE mAppInstance;
} ;
DialogState BePolite::mDialogState = cNotSet;
class Terminator
{
public:
void Die()
{
SendCloseToAllWindows();
SendQuitToAllWindows();
AttemptLogoff();
ForceLogoff();
}
private:
void Snooze()
{
Sleep(cPauseTimeout);
}
void SendCloseToAllWindows()
{
SendToAllWindows(WM_CLOSE);
Snooze();
}
void SendQuitToAllWindows()
{
SendToAllWindows(WM_QUIT);
Snooze();
}
void SendToAllWindows(UINT msg)
{
PostMessage(HWND_BROADCAST, msg, 0, 0);
}
void AttemptLogoff()
{
//log off nicely
ExitWindowsEx(EWX_LOGOFF, 0);
Snooze();
}
void ForceLogoff()
{
// Force all processes to die
ExitWindowsEx(EWX_FORCE, 0);
Snooze();
}
} ;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int )
{
BePolite politely(hInstance);
politely.AskUser();
if (politely.IsUserCancelled())
return 1;
// User hit OK or a cPauseTimeout happened
Terminator t;
t.Die();
return 0;
}
|
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_DLG DIALOGEX 0, 0, 187, 99
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION
CAPTION "Logging Off!"
FONT 8, "MS Sans Serif", 0, 0, 0x0
BEGIN
DEFPUSHBUTTON "OK",IDOK,24,78,50,14
PUSHBUTTON "Cancel",IDCANCEL,102,78,50,14
LTEXT "Press Cancel to stop logging off! Press OK to continue logging off.",
IDC_STATIC,33,18,114,34,WS_BORDER
LTEXT "You have",IDC_STATIC,33,58,32,8
LTEXT "seconds to decide.",IDC_STATIC,97,58,61,8
CTEXT "0",IDC_TIMEOUTTEXT,69,58,24,11,SS_CENTERIMAGE |
SS_SUNKEN
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_DLG, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 180
TOPMARGIN, 7
BOTTOMMARGIN, 92
END
END
#endif // APSTUDIO_INVOKED
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
|