home *** CD-ROM | disk | FTP | other *** search
- /*
- * $Id: WINEXIT.C 1.0 1993/07/19 15:26:48 nino Exp $
- *
- * Copyright (c) 1993. Nino Margetic. All rights reserved.
- *
- * General permission is hereby granted to copy this
- * program freely provided no charge is made for its
- * distribution and provided this copyright notice
- * remains in place.
- *
- * Abstract: WINEXIT.C - Exit from Windows from an icon.
- *
- * This program provides an easy way to get out of Windows.
- * It can be run either from the Program Manager or it can
- * be started and minimized so that its icon shows up in
- * the icon area.
- *
- * Operating procedures:
- *
- * This program can be placed in a convenient group in the
- * Program Manager or it can be placed in the StartUp group
- * so that it shows up in the main icon area. If it is put
- * in the StartUp group it should probably be run minimized.
- *
- * Written: 16-Jul-1993 Nino Margetic <nino@medphys.ucl.ac.uk>
- *
- * Acknowledgements:
- * Thanks to Bruce C. Wright and his EXIT utility which served
- * as a template for this exercise in Windows programming.
- *
- *
- */
-
- #define STRICT
- #define WIN31
-
- #include <windows.h>
- #include <bwcc.h>
- #ifdef __BORLANDC__
- #pragma hdrstop
- #endif
-
- #include "winexit.h"
-
-
-
- /*
- * Main procedure
- */
- int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
- LPSTR lpszCmdLine, int nCmdShow)
- {
- MSG msg;
- UINT fuErr;
- WORD winVer;
-
-
- // save the program instance
- hInst = hInstance;
-
- // turn off Windows error "file not found" box.
- // HOWEVER, it doesn't seem to work for BWCC.DLL ...
- fuErr = SetErrorMode ( SEM_NOOPENFILEERRORBOX ) ;
-
- // load the BWCC.DLL
- BWCCGetVersion();
-
- // turn it back on.
- SetErrorMode ( fuErr ) ;
-
- // check version of Windows. At the moment we support 3.1 or higher!
- // this test courtesy of: davidds@microsoft.com (David D'Souza)
- winVer = LOWORD(GetVersion());
- winVer = (((WORD)(LOBYTE(winVer))) << 8)|(WORD)HIBYTE(winVer);
- if (winVer < 0x030A) // NOTE: Always use a HEX value here!!!
- { //exit
- char szTemp[256];
- LoadString( hInstance,
- (UINT)MAKEINTRESOURCE(IDS_BADVERSION),
- szTemp, sizeof szTemp );
- BWCCMessageBox (NULL, szTemp, szAppName,
- MB_ICONSTOP | MB_OK );
- FreeLibrary ( hBWCCDLL );
- return FALSE;
- }
-
- // check command line options
- // debug switch.
- if ( (lstrcmpi(lpszCmdLine,"/d") == 0 ) ||
- (lstrcmpi(lpszCmdLine,"-d") == 0 ) ) iDebugValue = DEBUG;
-
- // check for another instance.
- if ( !hPrevInstance ) {
-
- WNDCLASS wndclass;
-
- // first run - register class.
- wndclass.style = CS_HREDRAW | CS_VREDRAW;
- wndclass.lpfnWndProc = ExitWndProc; // our WndProc.
- wndclass.cbClsExtra = 0;
- wndclass.cbWndExtra = DLGWINDOWEXTRA; // IMPORTANT!!!
- wndclass.hInstance = hInstance;
- wndclass.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE(IDI_EXIT1));
- wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
- wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
- wndclass.lpszMenuName = MAKEINTRESOURCE(ExitWindowsMenu);
- wndclass.lpszClassName = szClassName;
-
- if (!RegisterClass (&wndclass))
- return FALSE;
- }
- else { // we have another instance running.
- HWND hOldWnd;
- char szTemp[256];
-
- // if there is an old window, find it and open it up.
- if ( NULL != (hOldWnd = FindWindow( szClassName, "Exit Windows")) ) {
- // if its iconic, open it up.
- if( IsIconic(hOldWnd) ) {
- if ( !OpenIcon ( hOldWnd ) ) {
- // error. Couldn't open iconized program.
- LoadString( hInstance,
- (UINT)MAKEINTRESOURCE(IDS_BADOLDICON),
- szTemp, sizeof szTemp );
- BWCCMessageBox (NULL, szTemp, szAppName,
- MB_ICONSTOP | MB_OK );
- return FALSE;
- }
- }
- // and bring it to the top.
- if ( !BringWindowToTop( hOldWnd ) ) {
- // error. Couldn't bring window to top.
- LoadString( hInstance,
- (UINT)MAKEINTRESOURCE(IDS_BADWINDOWTOP),
- szTemp, sizeof szTemp );
- BWCCMessageBox (NULL, szTemp, szAppName,
- MB_ICONSTOP | MB_OK );
- return FALSE;
- }
- // we found it OK - now bail out.
- return FALSE ;
- }
- else
- { // error. We have a NULL from FindWindow call.
- LoadString( hInstance,
- (UINT)MAKEINTRESOURCE(IDS_BADOLDWINDOW),
- szTemp, sizeof szTemp );
- BWCCMessageBox (NULL, szTemp, szAppName,
- MB_ICONSTOP | MB_OK );
- return FALSE;
- }
- }
-
-
- // and tell Windows to that our DialogProc is going to
- // handle the dialog
- hExitWnd = CreateDialog (hInstance, MAKEINTRESOURCE(ExitDialog),
- 0, NULL);
- // check window handle.
- if ( !hExitWnd )
- return FALSE;
-
- // show it
- ShowWindow (hExitWnd, nCmdShow);
-
- // load accelerators
- hAccel = LoadAccelerators ( hInstance, MAKEINTRESOURCE(ExitAccelerators) );
- if ( ! hAccel )
- return FALSE;
-
- // message loop
- while (GetMessage (&msg, NULL, 0, 0))
- {
- if ( !TranslateAccelerator ( hExitWnd, hAccel, &msg ) )
- {
- TranslateMessage (&msg);
- DispatchMessage (&msg);
- }
- }
-
-
- // and exit.
- return msg.wParam;
- }
-
-
- // -----------------------------------------------------------------------
-
- /*
- * AboutDlgProc - Routine to handle the About dialog window.
- */
- #ifdef __BORLANDC__
- #pragma argsused
- #endif
- BOOL FAR PASCAL AboutDlgProc (HWND hDlg, UINT iMessage, UINT wParam, LONG lParam)
- {
-
- // set focus to OK button so that the keyboard works.
- SetFocus ( GetDlgItem ( hDlg, IDOK ) );
- // display credits.
- if ((iMessage == WM_COMMAND) && (wParam == IDOK))
- EndDialog(hDlg, 0); // dismiss dialog if OK
-
- return(0); // otherwise just sit there
- }
-
-
-
- // -------------------------------------------------------------------------
-
- /*
- * ExitWndProc - Routine to handle main window
- *
- * All messages that we do NOT process, go to the BWCCDefWindowProc
- * which will handle them...
- *
- */
-
- LRESULT FAR PASCAL _export ExitWndProc (HWND hDlg, UINT iMessage, UINT wParam, LONG lParam)
- {
- static HMENU hSysMenu;
- FARPROC lpfnAboutDlgProc;
- static BOOL fbWriteIni = FALSE ;
- static char szMenuExitOption[25];
-
-
- switch (iMessage)
- {
-
-
- // create window and fix the system menu
- case WM_CREATE:
- // get the handle to the menu
- hSysMenu = GetSystemMenu(hDlg,FALSE);
- // add separator line and quick exit.
- AppendMenu(hSysMenu, MF_SEPARATOR, 900, NULL);
- // default exit mode
- iBootAction = IDD_EXIT;
- // get default exit mode
- if ( IDD_EXIT != ( iBootAction += GetPrivateProfileInt (
- szSection, szIconExit,
- 0, szIniFile)) )
- {
- // INI file sanity check.
- if ( iBootAction < IDD_EXIT ||
- iBootAction > IDD_BOOT ) iBootAction = IDD_EXIT;
- // we saved the flag (0,1,2) only, *not* the IDD_VALUE.
- // iBootAction += IDD_EXIT;
- }
- // prepare menu strings. The menu item itself will be
- // added during the WM_INIEXIT message, when we are sure
- // that the dialog has been created already.
- switch ( iBootAction )
- {
- case IDD_EXIT:
- wsprintf(szMenuExitOption, "Exit &DOS" );
- break;
-
- case IDD_REST:
- wsprintf(szMenuExitOption, "Restart &Windows" );
- break;
-
- case IDD_BOOT:
- wsprintf(szMenuExitOption, "Reboot &System" );
- break;
-
- }
-
- // No add the Quick Exit (no questions asked)
- AppendMenu(hSysMenu, MF_STRING, IDM_QUICKEXIT, "&Quick Exit");
- // check last state, and act accordingly.
- if ( EW_SLOW != ( iQuickExitValue = GetPrivateProfileInt(szSection,
- szQuickExit, EW_SLOW, szIniFile))) {
- // sanity check.
- iQuickExitValue = EW_QUICK;
- CheckMenuItem(hSysMenu, IDM_QUICKEXIT, MF_CHECKED);
- }
- // add AlwaysOnTop
- AppendMenu(hSysMenu, MF_STRING, IDM_ALWAYSONTOP, "Always on &Top");
- // check last state, and act accordingly.
- if ( GetPrivateProfileInt(szSection,
- szAlwaysOnTop, 0, szIniFile)) {
- CheckMenuItem(hSysMenu, IDM_ALWAYSONTOP, MF_CHECKED);
- SetWindowPos (hDlg, HWND_TOPMOST, 0, 0, 0, 0,
- SWP_NOMOVE | SWP_NOSIZE);
- }
- //
- // Finally, post ourselves a window (or in this case
- // application) specific message which will initialize
- // our dialog. As we have posted the message, rather
- // than sent it, initialisation will be executed AFTER
- // the dialog window (and all its child windows) has been
- // created.
- //
- // WM_INITDIALOG is NOT processed since this is a MODELESS
- // dialog main window, and we have our OWN window procedure
- // which processes dialog messages. Windows sends all
- // dialog messages to our routine, *and not* to
- // (BWCC)DefDlgProc.
- //
- PostMessage ( hDlg, WM_INIWINEXIT, 0, 0L );
- return 0;
-
-
-
- // custom message
- case WM_INIWINEXIT:
- // our intialisation of the dialog:
- // init radio button group (and potentially other stuff)
- SendMessage ( hDlg, WM_COMMAND, iBootAction, 0L );
- return 0;
-
-
-
- case WM_SYSCOMMAND:
- // process messages that come from the system menu.
- // we *would have to* combine it with 0xFFF0 (the four
- // low-order bits of wParam are used internally by
- // Windows) if we were processing SC_* messages, but
- // now we do not have to.
- switch ( wParam )
- {
-
- // if we are iconized, we will get this.
- case IDD_EXIT:
- case IDD_REST:
- case IDD_BOOT:
- SendMessage ( hDlg, WM_COMMAND, wParam, 0L );
- SendMessage ( hDlg, WM_COMMAND, IDOK, 0L );
- return 0;
-
-
- // always on top.
- case IDM_ALWAYSONTOP:
-
- fbWriteIni = TRUE;
- if ( ( GetMenuState ( hSysMenu, IDM_ALWAYSONTOP,
- MF_BYCOMMAND) & MF_CHECKED))
- { // currently topmost, change to notopmost
- CheckMenuItem ( hSysMenu, IDM_ALWAYSONTOP,
- MF_UNCHECKED);
- SetWindowPos ( hDlg, HWND_NOTOPMOST, 0, 0, 0, 0,
- SWP_NOMOVE | SWP_NOSIZE);
- }
- else
- { // currently notopmost, change to topmost.
- CheckMenuItem ( hSysMenu, IDM_ALWAYSONTOP,
- MF_CHECKED);
- SetWindowPos ( hDlg, HWND_TOPMOST, 0, 0, 0, 0,
- SWP_NOMOVE | SWP_NOSIZE);
- }
- return 0;
-
-
- // Quick exit.
- case IDM_QUICKEXIT:
-
- fbWriteIni = TRUE;
- if ( ( GetMenuState ( hSysMenu, IDM_QUICKEXIT,
- MF_BYCOMMAND) & MF_CHECKED))
- { // currently quickexit, change to slowexit
- CheckMenuItem ( hSysMenu, IDM_QUICKEXIT,
- MF_UNCHECKED);
- iQuickExitValue = EW_SLOW;
- }
- else
- { // currently slowexit, change to quickexit.
- CheckMenuItem ( hSysMenu, IDM_QUICKEXIT,
- MF_CHECKED);
- iQuickExitValue = EW_QUICK;
- }
- return 0;
- }
- // rest goes to BWCCDefWindowProc.
- break;
-
-
-
- // we need to trap WM_SIZE message cases SIZE_MINIMIZED,
- // SIZE_RESTORED and SIZE_MAXIMIZED so we can modify the
- // system menu. However, the rest of the action goes back
- // to Windows, so we do *not* return a zero.
- // I've tried trapping WM_SYSCOMMAND (SC_MINIMIZE SC_MAXIMIZE)
- // but they work only when invoked from the menu (not when
- // invoked from the 2nd instance of the program!!).
- case WM_SIZE:
- switch ( wParam )
- {
- case SIZE_MINIMIZED:
- AppendMenu(hSysMenu, MF_SEPARATOR, 901, NULL);
- AppendMenu(hSysMenu, MF_STRING, iBootAction, szMenuExitOption);
- break;
-
-
- case SIZE_MAXIMIZED:
- case SIZE_RESTORED:
- DeleteMenu ( hSysMenu, 901, MF_BYCOMMAND );
- DeleteMenu ( hSysMenu, iBootAction, MF_BYCOMMAND );
- break;
- }
- // rest goes to BWCCDefWindowProc.
- break;
-
-
-
- // add a bit of keyboard control.
- case WM_KEYDOWN:
- switch ( wParam )
- {
- // up and down move radiobuttons.
- case VK_UP:
- case VK_LEFT:
- iBootAction = ((iBootAction - IDD_EXIT + 2) % 3)
- + IDD_EXIT;
- SendMessage ( hDlg, WM_COMMAND, iBootAction, 0L );
- return 0;
-
- case VK_DOWN:
- case VK_RIGHT:
- iBootAction = ((iBootAction - IDD_EXIT + 1) % 3)
- + IDD_EXIT;
- SendMessage ( hDlg, WM_COMMAND, iBootAction, 0L );
- return 0;
-
- // Escape is same as Cancel button
- case VK_ESCAPE:
- SendMessage ( hDlg, WM_COMMAND, IDCANCEL, 0L );
- return 0;
-
- // Return & Space simulate OK.
- case VK_RETURN:
- case VK_SPACE:
- SendMessage ( hDlg, WM_COMMAND, IDOK, 0L );
- return 0;
- }
- // rest goes to BWCCDefWindowProc.
- break;
-
-
-
- // process messages which come from the
- // buttons and the Exit menu.
- case WM_COMMAND:
-
- // set focus to parent window so we can process keyboard.
- SetFocus ( hDlg );
-
- switch (wParam)
- {
- // Button choices.
- case IDOK:
- {
- // Let's get out of this...
- char szTemp[256];
-
-
- // check for quick exit (no questions asked)
- switch ( iQuickExitValue )
- {
- // slow mover, wants confirmation.
- case EW_SLOW:
-
- LoadString ( hInst,
- (UINT)MAKEINTRESOURCE(IDS_EXITMESSAGE),
- szTemp, sizeof szTemp );
- if ( IDOK != BWCCMessageBox ( hDlg,
- szTemp, szAppName,
- MB_OKCANCEL |
- MB_ICONQUESTION ) )
- return 0;
-
- // else falls thru!!!
-
-
- // wants to get out ASAP
- case EW_QUICK:
-
- // only kidding...
- if (iDebugValue)
- {
- LoadString ( hInst,
- (UINT)MAKEINTRESOURCE(IDS_DEBUGMESSAGE),
- szTemp, sizeof szTemp );
- BWCCMessageBox ( hDlg,
- szTemp, szAppName,
- MB_OK | MB_ICONASTERISK );
- return 0;
- }
-
- // first destroy the window
- SendMessage ( hDlg, WM_CLOSE, 0, 0L );
- // end then exit.
- ExitWindows ( lAction [iBootAction -
- IDD_EXIT], 0);
- }
- }
- break;
-
-
- // No, we are staying in Windows....
- case IDCANCEL:
- SendMessage( hDlg, WM_CLOSE, 0, 0L );
- return 0;
-
-
- // radio buttons (how do we exit Windows)
- case IDD_EXIT:
- case IDD_REST:
- case IDD_BOOT:
- // set the INI write flag
- fbWriteIni = TRUE;
- // and prepare the menu item string.
- switch ( wParam )
- {
- case IDD_EXIT:
- wsprintf(szMenuExitOption, "Exit to &DOS" );
- break;
-
- case IDD_REST:
- wsprintf(szMenuExitOption, "R&estart Windows" );
- break;
-
- case IDD_BOOT:
- wsprintf(szMenuExitOption, "Reboot &System" );
- break;
- }
- // set the appropriate radio button.
- iBootAction = wParam;
- CheckRadioButton(hDlg,IDD_EXIT,IDD_BOOT,iBootAction);
- return 0;
-
-
-
- // give us some credit :-)
- case IDD_ABOUT:
- // obtain a "thunk"
- lpfnAboutDlgProc =
- MakeProcInstance ((FARPROC)AboutDlgProc,hInst);
- // launch box
- DialogBox (hInst, MAKEINTRESOURCE(AboutDialog),
- hDlg, (DLGPROC)lpfnAboutDlgProc);
- // free thunk.
- FreeProcInstance (lpfnAboutDlgProc);
- return 0;
-
-
-
- // Menu choices.
- case IDM_EXIT:
- SendMessage ( hDlg, WM_COMMAND, IDD_EXIT, 1L );
- SendMessage ( hDlg, WM_COMMAND, IDOK, 1L );
- return 0;
-
- case IDM_REST:
- SendMessage ( hDlg, WM_COMMAND, IDD_REST, 1L );
- SendMessage ( hDlg, WM_COMMAND, IDOK, 1L );
- return 0;
-
- case IDM_BOOT:
- SendMessage ( hDlg, WM_COMMAND, IDD_BOOT, 1L );
- SendMessage ( hDlg, WM_COMMAND, IDOK, 1L );
- return 0;
-
- case IDM_ABOUT:
- SendMessage ( hDlg, WM_COMMAND, IDD_ABOUT, 1L );
- return 0;
-
- }
- // rest goes to BWCCDefWindowProc.
- break;
-
-
- case WM_DESTROY:
- // flush things to disk if needed.
- if ( fbWriteIni ) {
- // make block to allocate szTemp.
- BOOL bfChecked;
- char szTemp[5];
- int iExit;
-
- // Exit Windows mode.
- iExit = iBootAction - IDD_EXIT;
- wsprintf(szTemp,"%d",iExit);
- WritePrivateProfileString (szSection,
- szIconExit,
- szTemp,
- szIniFile );
- // AlwaysOnTop.
- WritePrivateProfileString (szSection, szAlwaysOnTop,
- ( GetMenuState(hSysMenu, IDM_ALWAYSONTOP,
- MF_BYCOMMAND) & MF_CHECKED ) ?
- "1" : "0", szIniFile);
-
-
- // QuickExit.
- bfChecked = GetMenuState(hSysMenu, IDM_QUICKEXIT,MF_BYCOMMAND);
- iExit = ( bfChecked & MF_CHECKED ) ? EW_QUICK : EW_SLOW ;
- wsprintf(szTemp,"%d",iExit);
- WritePrivateProfileString (szSection,
- szQuickExit,
- szTemp,
- szIniFile );
-
- // this will flush buffers to disk NOW.
- WritePrivateProfileString ( NULL, NULL, NULL, szIniFile );
- }
- // bye...
- PostQuitMessage ( 0 ) ;
- return 0;
-
- }
-
- // handle all other messages.
- return BWCCDefWindowProc( hDlg, iMessage, wParam, lParam);
-
- }
-