Main Page | Data Structures | Directories | File List | Data Fields | Globals

winmain.c

Go to the documentation of this file.
00001 /* ---------------------------------------------------------------------- *
00002  * winmain.c
00003  * This file is part of lincity.
00004  * Lincity is copyright (c) I J Peters 1995-1997, (c) Greg Sharp 1997-2001.
00005  * ---------------------------------------------------------------------- */
00006 #include <stdio.h>
00007 #include <stdlib.h>
00008 #include <math.h>
00009 #include <malloc.h>
00010 #include <memory.h>
00011 #include "lcstring.h"
00012 #include "lin-city.h"
00013 #include "common.h"
00014 #include "generic.h"
00015 #include "mouse.h"
00016 #include "lchelp.h"
00017 #include "module_buttons.h"
00018 
00019 // Define this to use DIB's instead of DDB's
00020 // GCS: WIN32_USEDIB will no longer work, since I didn't update the 
00021 // window resizing code for DIB's.
00022 //#define WIN32_USEDIB
00023 
00024 // Global Variables
00025 static char szClassNameWithMenu[] = APPNAME " (with menu)";
00026 static char szClassNameWithoutMenu[] = APPNAME " (without menu)";
00027 static char szAppName[] = APPNAME;      // The name of this application
00028 static char szTitle[] = APPNAME;        // The title bar text
00029 static HBRUSH hbrBackground = 0;
00030 
00031 int pending_mouse_event = 0;
00032 int pending_mouse_x = 0;
00033 int pending_mouse_y = 0;
00034 
00035 int pending_resize_event = 0;
00036 int pending_resize_w = 0;
00037 int pending_resize_h = 0;
00038 
00039 // Private Function Prototypes
00040 static ATOM MyRegisterClass (CONST WNDCLASS *);
00041 static BOOL InitApplication (HINSTANCE);
00042 static BOOL InitInstance (HINSTANCE, int);
00043 static LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
00044 static LRESULT CALLBACK About (HWND, UINT, WPARAM, LPARAM);
00045 static BOOL CenterWindow (HWND, HWND);
00046 static void InitializeBackingStore (HWND);
00047 static BOOL CopyBackingStoreToScreen (HDC, HWND, LPPAINTSTRUCT);
00048 static void CreateDDB (HWND hWnd);
00049 static void CreateDIB (void);
00050 static void InitializePalette (void);
00051 static void DoSquareMouse (HDC hdc);
00052 static void ResizeBackingStore (HWND hWnd);
00053 static void ResizeDDB (HWND hWnd);
00054 
00055 
00056 //----------------------------------------------------------------------------
00057 //  FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
00058 //
00059 //  PURPOSE: Entry point for the application.
00060 //
00061 //  COMMENTS:
00062 //
00063 //      This function initializes the application and processes the
00064 //      message loop.
00065 //----------------------------------------------------------------------------
00066 int WINAPI
00067 WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) 
00068 {
00069     char *args[] = {"wlincity"};
00070   
00071     if (!hPrevInstance) {
00072         // Perform instance initialization:
00073         if (!InitApplication (hInstance)) {
00074             return (FALSE);
00075         }
00076     }
00077     
00078     // Perform application initialization, including creating the
00079     // Lin-City main window.
00080     if (!InitInstance (hInstance, nCmdShow)) {
00081         return (FALSE);
00082     }
00083 
00084     // Load keyboard accelerators (shortkut keys)
00085     display.hAccelTable = LoadAccelerators (hInstance, szAppName);
00086   
00087     // Take care of any outstanding messages
00088     ProcessPendingEvents ();
00089     
00090     // lincity_main() contains main message loop
00091     lincity_main (1, args);
00092 
00093     // Take care of any outstanding messages after main() finishes.
00094     ProcessPendingEvents ();
00095 
00096     return 0;
00097     lpCmdLine;  // This prevents 'unused formal parameter' warnings
00098 }
00099 
00100 
00101 
00102 //----------------------------------------------------------------------------
00103 //  FUNCTION: MyRegisterClass(CONST WNDCLASS*)
00104 //
00105 //  PURPOSE: Registers the window class.
00106 //
00107 //  COMMENTS:
00108 //
00109 //      This function and its usage is only necessary if you want this code
00110 //      to be compatible with Win32 systems prior to the 'RegisterClassEx'
00111 //      function that was added to Windows 95. It is important to call this function
00112 //      so that the application will get 'well formed' small icons associated
00113 //      with it.
00114 //----------------------------------------------------------------------------
00115 ATOM MyRegisterClass (CONST WNDCLASS * lpwc) 
00116 {
00117     HANDLE hMod;
00118     FARPROC proc;
00119     WNDCLASSEX wcex;
00120     
00121     hMod = GetModuleHandle ("USER32");
00122     if (hMod != NULL) {
00123 #if defined (UNICODE)
00124         proc = GetProcAddress ((HMODULE) hMod, "RegisterClassExW");
00125 #else /*  */
00126         proc = GetProcAddress ((HMODULE) hMod, "RegisterClassExA");
00127 #endif /*  */
00128         if (proc != NULL) {
00129             // GCS: This typedef is for the typecast in the return stmt below
00130             typedef int (FAR WINAPI * my_FARPROC) (WNDCLASSEX *);
00131 
00132             wcex.style = lpwc->style;
00133             wcex.lpfnWndProc = lpwc->lpfnWndProc;
00134             wcex.cbClsExtra = lpwc->cbClsExtra;
00135             wcex.cbWndExtra = lpwc->cbWndExtra;
00136             wcex.hInstance = lpwc->hInstance;
00137             wcex.hIcon = lpwc->hIcon;
00138             wcex.hCursor = lpwc->hCursor;
00139             wcex.hbrBackground = lpwc->hbrBackground;
00140             wcex.lpszMenuName = lpwc->lpszMenuName;
00141             wcex.lpszClassName = lpwc->lpszClassName;
00142             
00143             // Added elements for Windows 95:
00144             wcex.cbSize = sizeof (WNDCLASSEX);
00145             wcex.hIconSm = LoadIcon (wcex.hInstance, "SMALL");
00146             
00147             return (*((my_FARPROC) (proc))) (&wcex);
00148         }
00149     }
00150     return (RegisterClass (lpwc));
00151 }
00152 
00153 
00154 //----------------------------------------------------------------------------
00155 //  FUNCTION: InitApplication(HANDLE)
00156 //
00157 //  PURPOSE: Initializes window data and registers window classes
00158 //
00159 //  COMMENTS:
00160 //         We need two classes -- one which has a menu, one without a menu
00161 //         (for full-screen).  This is registered by calling RegisterClass 
00162 //         for Win 3.1/NT, or MyRegisterClass for Win 95.
00163 //----------------------------------------------------------------------------
00164 BOOL InitApplication (HINSTANCE hInstance) 
00165 {
00166     WNDCLASS wcWithMenu;
00167     WNDCLASS wcWithoutMenu;
00168     // If Lin City is already running, focus existing process.
00169     // Win32 always sets hPrevInstance to NULL, so check w/ FindWindow()
00170     HWND hwnd = FindWindow (szClassNameWithMenu, NULL);
00171   
00172     if (!hwnd)
00173         hwnd = FindWindow (szClassNameWithoutMenu, NULL);
00174     if (hwnd) {
00175         // We found another version of ourself. Lets defer to it:
00176         if (IsIconic (hwnd)) {
00177             ShowWindow (hwnd, SW_RESTORE);
00178         }
00179         SetForegroundWindow (hwnd);
00180         return FALSE;
00181     }
00182 
00183     // Create brush for background: Nasty Brown (Lin City color # 105)
00184     hbrBackground = CreateSolidBrush (RGB (0x4C, 0x4C, 0));
00185 
00186     // Fill in WNDCLASS for class WITH MENU.
00187     wcWithMenu.style = 0;
00188     wcWithMenu.lpfnWndProc = (WNDPROC) WndProc;
00189     wcWithMenu.cbClsExtra = 0;
00190     wcWithMenu.cbWndExtra = 0;
00191     wcWithMenu.hInstance = hInstance;
00192     wcWithMenu.hIcon = LoadIcon (hInstance, szAppName);
00193     wcWithMenu.hCursor = LoadCursor (NULL, IDC_ARROW);
00194     wcWithMenu.hbrBackground = hbrBackground;
00195   
00196     // Windows95 has different recommended help menu format.
00197 #if defined (USE_WIN32_MENU)
00198     if (IS_WIN95) {
00199         wcWithMenu.lpszMenuName = "WIN95";
00200     } else {
00201         wcWithMenu.lpszMenuName = szAppName;
00202     }
00203     wcWithMenu.lpszClassName = szClassNameWithMenu;
00204 #else
00205     wcWithMenu.lpszMenuName = "";
00206     wcWithMenu.lpszClassName = szClassNameWithMenu;
00207 #endif
00208 
00209     // Fill in WNDCLASS for class WITHOUT MENU.
00210     wcWithoutMenu.style = 0;
00211     wcWithoutMenu.lpfnWndProc = (WNDPROC) WndProc;
00212     wcWithoutMenu.cbClsExtra = 0;
00213     wcWithoutMenu.cbWndExtra = 0;
00214     wcWithoutMenu.hInstance = hInstance;
00215     wcWithoutMenu.hIcon = LoadIcon (hInstance, szAppName);
00216     wcWithoutMenu.hCursor = LoadCursor (NULL, IDC_ARROW);
00217     wcWithoutMenu.hbrBackground = hbrBackground;
00218     wcWithoutMenu.lpszMenuName = "";
00219     wcWithoutMenu.lpszClassName = szClassNameWithoutMenu;
00220     
00221     // Register the window classes and return success/failure code.
00222     if (IS_WIN95) {
00223         BOOL rv;
00224         rv = MyRegisterClass (&wcWithMenu);
00225         if (!rv)
00226             return rv;
00227         rv = MyRegisterClass (&wcWithoutMenu);
00228         return rv;
00229     } else {
00230         BOOL rv;
00231         rv = RegisterClass (&wcWithMenu);
00232         if (!rv)
00233             return rv;
00234         rv = RegisterClass (&wcWithoutMenu);
00235         return rv;
00236     }
00237 }
00238 
00239 
00240 //----------------------------------------------------------------------------
00241 // CheckClientSize (int width, int height, int with_menus)
00242 // --
00243 // Return 1 if the screen can support a client of this size
00244 //----------------------------------------------------------------------------
00245 void
00246 CheckClientSize (int width, int height, int with_menus)
00247 {
00248     display.screenW = GetSystemMetrics (SM_CXSCREEN);
00249     display.screenH = GetSystemMetrics (SM_CYSCREEN);
00250 }
00251 
00252 //----------------------------------------------------------------------------
00253 //   FUNCTION: InitInstance(HANDLE, int)
00254 //
00255 //   PURPOSE:  Creates main window 
00256 //----------------------------------------------------------------------------
00257 BOOL
00258 InitInstance (HINSTANCE hInstance, int nCmdShow)
00259 {
00260     HDC hDCGlobal = GetDC (NULL);
00261     INT iRasterCaps;
00262     char *szClassName = 0;
00263     DWORD dwStyle;
00264     RECT client_size;
00265 
00266     // Determine graphics capabilities
00267     iRasterCaps = GetDeviceCaps (hDCGlobal, RASTERCAPS);
00268     if (iRasterCaps & RC_PALETTE) {
00269         display.hasPalette = TRUE;
00270         display.paletteSize = GetDeviceCaps (hDCGlobal, SIZEPALETTE);
00271         display.defaultPaletteSize = GetDeviceCaps (hDCGlobal, NUMCOLORS);
00272     } else {
00273         display.hasPalette = FALSE;
00274     }
00275 
00276     display.colorDepth = GetDeviceCaps (hDCGlobal, BITSPIXEL);
00277     ReleaseDC (NULL, hDCGlobal);
00278   
00279     // Decide whether to use DIB's or DDB's
00280 #if defined (WIN32_USEDIB)
00281     if (display.colorDepth == 8)        // Only use DIB for 256 colors
00282         display.useDIB = TRUE;
00283     else
00284         display.useDIB = FALSE;
00285 #else /*  */
00286     display.useDIB = FALSE;
00287 #endif /*  */
00288     
00289     // Do some global initializations
00290     display.hInst = hInstance;
00291     display.fullscreen = FALSE;
00292     //display.fullscreen = TRUE;
00293     display.screenW = GetSystemMetrics (SM_CXSCREEN);
00294     display.screenH = GetSystemMetrics (SM_CYSCREEN);
00295     display.winFullscreenClientW = (INT) GetSystemMetrics (SM_CXFULLSCREEN);
00296     display.winFullscreenClientH = (INT) GetSystemMetrics (SM_CYFULLSCREEN);
00297     InitializePalette ();
00298 
00299     // Choose one of Lin City window types
00300     //    a)  no pix doubling, no border
00301     //    b)  no pix doubling, 30 pixel border
00302     //    c)  pix doubling, no border
00303     // GCS FIX: This doesn't work.  I need to call AdjustWindowRect on these values (?)
00304     if ((display.screenW >= 2*WINWIDTH + 2*BORDERX) &&
00305         (display.screenH >= 2*WINHEIGHT + 2*BORDERY)) {
00306         pix_double = 1;
00307         borderx = 1;
00308         bordery = 1;
00309     }
00310     else if ((display.screenW >= 2*WINWIDTH) &&
00311              (display.screenH >= 2*WINHEIGHT)) {
00312         pix_double = 1;
00313         borderx = 0;
00314         bordery = 0;
00315     }
00316     else if ((display.screenW >= WINWIDTH + (2 * BORDERX)) 
00317              &&(display.screenH >= WINHEIGHT + (2 * BORDERY))) {
00318         pix_double = 0;
00319         borderx = BORDERX;
00320         bordery = BORDERY;
00321     } else {
00322         pix_double = 0;
00323         borderx = 0;
00324         bordery = 0;
00325     }
00326     display.clientW = ((pix_double + 1) * WINWIDTH) + (2 * borderx);
00327     display.clientH = ((pix_double + 1) * WINHEIGHT) + (2 * bordery);
00328     
00329     // Choose one of three client window types
00330     //    a)  full screen
00331     //    b)  maximized window
00332     //    c)  regular window
00333     // Prefer regular over maximized over full screen
00334     dwStyle = WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SIZEBOX;
00335     client_size.left = 0;
00336     client_size.top = 0;
00337     client_size.right = display.clientW;
00338     client_size.bottom = display.clientH;
00339     AdjustWindowRect (&client_size, dwStyle, TRUE);
00340 
00341     if (((client_size.right - client_size.left) <= display.screenW) 
00342         &&((client_size.bottom - client_size.top) <= display.screenH))
00343     {
00344         // Use regular (overlapped) window
00345         szClassName = szClassNameWithMenu;
00346         if (client_size.left < 0) {
00347             client_size.right -= client_size.left;
00348             client_size.left = CW_USEDEFAULT;
00349         }
00350         if (client_size.top < 0) {
00351             client_size.bottom -= client_size.top;
00352             client_size.top = CW_USEDEFAULT;
00353         }
00354     } else {
00355         // Check maximized by subtracting out the DLGFRAME size.
00356         // Note that the "obvious" method of calling AdjustWindowRect()
00357         // with style WS_MAXIMIZE doesn't work!
00358         int win_border_x = GetSystemMetrics (SM_CXDLGFRAME);
00359         int win_border_y = GetSystemMetrics (SM_CYDLGFRAME);
00360         if (((client_size.right - client_size.left - 2 * win_border_x) <= display.screenW) 
00361             &&((client_size.bottom - client_size.top - 2 * win_border_y) <= display.screenH))
00362         {
00363             // Use maximized window
00364             szClassName = szClassNameWithMenu;
00365             // dwStyle |= WS_MAXIMIZE;
00366             if (client_size.left < 0) {
00367                 client_size.right -= client_size.left;
00368                 client_size.left = CW_USEDEFAULT;
00369             }
00370             if (client_size.top < 0) {
00371                 client_size.bottom -= client_size.top;
00372                 client_size.top = CW_USEDEFAULT;
00373             }
00374             nCmdShow = SW_SHOWMAXIMIZED;
00375         } else {
00376             // Need fullsize window
00377             szClassName = szClassNameWithoutMenu;
00378             dwStyle = WS_POPUP;
00379             client_size.left = 0;
00380             client_size.top = 0;
00381             client_size.right = display.screenW;
00382             client_size.bottom = display.screenH;
00383         }
00384     }
00385     
00386     display.min_h = client_size.bottom - client_size.top;
00387     display.min_w = client_size.right - client_size.left;
00388 
00389     // Create the window
00390     display.hWnd = CreateWindow (szClassName,   // Class name
00391                                  szTitle,       // Caption
00392                                  dwStyle,       // Style
00393                                  client_size.left, client_size.top,     // Position
00394                                  client_size.right, client_size.bottom, // Size
00395                                  (HWND) NULL,   // Parent window (no parent)
00396                                  (HMENU) NULL,          // use class menu
00397                                  (HINSTANCE) hInstance, // handle to window instance
00398                                  (LPVOID) NULL          // no params to pass on
00399                                  );
00400   
00401     if (!display.hWnd) {
00402         return (FALSE);
00403     }
00404   
00405     // Display the window
00406     ShowWindow (display.hWnd, nCmdShow);
00407     UpdateWindow (display.hWnd);
00408     
00409     return (TRUE);
00410 }
00411 
00412 
00413 //----------------------------------------------------------------------------
00414 //  FUNCTION: ProcessNextEvent ()
00415 //            Wait for a message if necessary,
00416 //            then process all messages.
00417 //----------------------------------------------------------------------------
00418 void
00419 ProcessNextEvent (void) 
00420 {
00421   
00422     MSG msg;
00423     if (GetMessage (&msg, NULL, 0, 0)) {
00424         if (!TranslateAccelerator (msg.hwnd, (HACCEL) display.hAccelTable, 
00425                                    &msg)) {
00426             TranslateMessage (&msg);
00427             DispatchMessage (&msg);
00428         }
00429     }
00430     ProcessPendingEvents ();
00431 }
00432 
00433 
00434 
00435 //----------------------------------------------------------------------------
00436 //  FUNCTION: ProcessPendingEvents ()
00437 //            Process all outstanding messages.
00438 //----------------------------------------------------------------------------
00439 void
00440 ProcessPendingEvents (void) 
00441 {
00442     MSG msg;
00443     while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) {
00444         if (!TranslateAccelerator (msg.hwnd, (HACCEL) display.hAccelTable, 
00445                                    &msg)) {
00446             TranslateMessage (&msg);
00447             DispatchMessage (&msg);
00448         }
00449     }
00450 }
00451 
00452 
00453 
00454 //----------------------------------------------------------------------------
00455 //  FUNCTION: EnableWindowsMenuItems ()
00456 //  FUNCTION: DisableWindowsMenuItems ()
00457 //            Enable and Disable "Load" and "Save" items
00458 //----------------------------------------------------------------------------
00459 void
00460 EnableWindowsMenuItems (void) 
00461 {
00462 #if defined (USE_WIN32_MENU)
00463     HMENU hMenu = GetMenu (display.hWnd);
00464     EnableMenuItem (hMenu, IDM_OPEN, MF_BYCOMMAND | MF_ENABLED);
00465     EnableMenuItem (hMenu, IDM_SAVE, MF_BYCOMMAND | MF_ENABLED);
00466     EnableMenuItem (hMenu, IDM_HELPCONTENTS, MF_BYCOMMAND | MF_ENABLED);
00467 #endif
00468 }
00469 
00470 
00471 void
00472 DisableWindowsMenuItems (void) 
00473 {
00474 #if defined (USE_WIN32_MENU)
00475     HMENU hMenu = GetMenu (display.hWnd);
00476     EnableMenuItem (hMenu, IDM_OPEN, MF_BYCOMMAND | MF_GRAYED);
00477     EnableMenuItem (hMenu, IDM_SAVE, MF_BYCOMMAND | MF_GRAYED);
00478     EnableMenuItem (hMenu, IDM_HELPCONTENTS, MF_BYCOMMAND | MF_GRAYED);
00479 #endif
00480 }
00481 
00482 
00483 
00484 //----------------------------------------------------------------------------
00485 //  FUNCTION: HandleMouse ()
00486 //----------------------------------------------------------------------------
00487 void
00488 HandleMouse () 
00489 {
00490     MSG msg;
00491     /* Process queued events, ignoring mouse moves. */
00492     while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) {
00493         if (!TranslateAccelerator (msg.hwnd, (HACCEL) display.hAccelTable, 
00494                                    &msg)) {
00495             pending_mouse_x = cs_mouse_x;
00496             pending_mouse_y = cs_mouse_y;
00497             pending_mouse_event = 0;
00498             pending_resize_event = 0;
00499             TranslateMessage (&msg);
00500             DispatchMessage (&msg);
00501             if (pending_mouse_event)
00502                 cs_mouse_handler (pending_mouse_event,
00503                                   pending_mouse_x - cs_mouse_x,
00504                                   pending_mouse_y - cs_mouse_y);
00505             if (pending_resize_event) {
00506                 /* Force resize, because I can't tell difference between
00507                    size change and restoring a minimized window.  Ideally,
00508                    this would simply redraw. */
00509                 display.winW = 0;
00510                 resize_geometry (pending_resize_w, pending_resize_h);
00511             }
00512         }
00513     }
00514   
00515     /* Now move the mouse if necessary. */
00516     if (pending_mouse_x != cs_mouse_x 
00517         || pending_mouse_y != cs_mouse_y)
00518         cs_mouse_handler (0, pending_mouse_x - cs_mouse_x, 
00519                           pending_mouse_y - cs_mouse_y);
00520 }
00521 
00522 
00523 
00524 //----------------------------------------------------------------------------
00525 //  FUNCTION: GetKeystroke ()
00526 //----------------------------------------------------------------------------
00527 char
00528 GetKeystroke () 
00529 {
00530     char key;
00531     /* GCS 02/02/2003  I found out that sometimes the mouse events were
00532                        getting lost here. */
00533     HandleMouse ();
00534 //    ProcessPendingEvents ();
00535     key = x_key_value;
00536     x_key_value = 0;
00537     return key;
00538 }
00539 
00540 
00541 
00542 //----------------------------------------------------------------------------
00543 //  FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
00544 //
00545 //  PURPOSE:  Processes messages for the main window.
00546 //----------------------------------------------------------------------------
00547 LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 
00548 {
00549 #if defined (USE_WIN32_MENU)
00550     int wmId, wmEvent;
00551 #endif
00552     
00553     switch (message)
00554     {
00555 #if defined (USE_WIN32_MENU)
00556     case WM_COMMAND: {
00557         wmId = LOWORD (wParam);
00558         wmEvent = HIWORD (wParam);
00559 
00560         //Parse the menu selections:
00561         switch (wmId)
00562         {
00563 
00564         case IDM_OPEN:
00565             load_flag = 1;
00566             DisableWindowsMenuItems ();
00567             break;
00568 
00569         case IDM_SAVE:
00570             save_flag = 1;
00571             DisableWindowsMenuItems ();
00572             break;
00573 
00574         case IDM_EXIT:
00575             // GCS FIX: I'm still not quite satisfied with this...
00576             // x_key_value = 'q';
00577             DestroyWindow (hWnd);
00578             break;
00579 
00580         case IDM_ABOUT:
00581             DialogBox (display.hInst, "AboutBox", hWnd, (DLGPROC) About);
00582             break;
00583 
00584         case IDM_HELPCONTENTS:
00585             help_flag = 1;
00586             DisableWindowsMenuItems ();
00587             activate_help ("index.hlp");
00588             break;
00589 
00590         default:
00591             return (DefWindowProc (hWnd, message, wParam, lParam));
00592         }
00593     }
00594     break;
00595 #endif
00596     
00597     case WM_KEYDOWN: {
00598         int nVirtKey = (int) wParam;
00599         x_key_shifted = (GetKeyState (VK_SHIFT) & 0x80000000) ? TRUE : FALSE;
00600         switch (nVirtKey)
00601         {
00602         case VK_LEFT:
00603             x_key_value = 1;
00604             break;
00605   
00606         case VK_DOWN:
00607             x_key_value = 2;
00608             break;
00609   
00610         case VK_UP:
00611             x_key_value = 3;
00612             break;
00613   
00614         case VK_RIGHT:
00615             x_key_value = 4;
00616             break;
00617   
00618         case VK_ESCAPE:
00619             x_key_value = 5;
00620             break;
00621         }
00622     }
00623     break;
00624       
00625     case WM_CHAR: {
00626         TCHAR chCharCode = (TCHAR) wParam;      // character code
00627         LPARAM lKeyData = lParam;       // key data
00628         if (chCharCode == 8) {          // Fix backspace
00629             chCharCode = 127;
00630         } else if (chCharCode == VK_ESCAPE) {  // Fix escape
00631             chCharCode = 5;
00632         }
00633         x_key_value = chCharCode;
00634     }
00635     break;
00636         
00637     // RightClick on windows non-client area
00638     case WM_NCRBUTTONUP:
00639         if (IS_WIN95 && SendMessage (hWnd, WM_NCHITTEST, 0, lParam) == HTSYSMENU)
00640         {
00641             // The user has clicked the right button on the applications
00642             // 'System Menu'. Here is where you would alter the default
00643             // system menu to reflect your application. Notice how the
00644             // explorer deals with this. For this app, we aren't doing
00645             // anything
00646             return (DefWindowProc (hWnd, message, wParam, lParam));
00647         } else {
00648             // Nothing we are interested in, allow default handling...
00649             return (DefWindowProc (hWnd, message, wParam, lParam));
00650         }
00651         break;
00652         
00653         // RightClick in windows client area
00654     case WM_RBUTTONDOWN:
00655         pending_mouse_x = UnAdjustX (LOWORD (lParam));
00656         pending_mouse_y = UnAdjustY (HIWORD (lParam));
00657         pending_mouse_event = LC_MOUSE_RIGHTBUTTON | LC_MOUSE_PRESS;
00658         cs_mouse_shifted = (wParam & MK_SHIFT) ? 1 : 0;
00659         break;
00660         
00661         // Left Click in windows client area
00662     case WM_LBUTTONDOWN:
00663         pending_mouse_x = UnAdjustX (LOWORD (lParam));
00664         pending_mouse_y = UnAdjustY (HIWORD (lParam));
00665         pending_mouse_event = LC_MOUSE_LEFTBUTTON | LC_MOUSE_PRESS;
00666         cs_mouse_shifted = (wParam & MK_SHIFT) ? 1 : 0;
00667         break;
00668       
00669     case WM_RBUTTONUP:
00670         pending_mouse_x = UnAdjustX (LOWORD (lParam));
00671         pending_mouse_y = UnAdjustY (HIWORD (lParam));
00672         pending_mouse_event = LC_MOUSE_RIGHTBUTTON | LC_MOUSE_RELEASE;
00673         cs_mouse_shifted = (wParam & MK_SHIFT) ? 1 : 0;
00674         break;
00675 
00676     case WM_LBUTTONUP:
00677         pending_mouse_x = UnAdjustX (LOWORD (lParam));
00678         pending_mouse_y = UnAdjustY (HIWORD (lParam));
00679         pending_mouse_event = LC_MOUSE_LEFTBUTTON | LC_MOUSE_RELEASE;
00680         cs_mouse_shifted = (wParam & MK_SHIFT) ? 1 : 0;
00681         break;
00682         
00683     case WM_MOUSEMOVE:
00684         pending_mouse_x = UnAdjustX (LOWORD (lParam));
00685         pending_mouse_y = UnAdjustY (HIWORD (lParam));
00686         cs_mouse_shifted = (wParam & MK_SHIFT) ? 1 : 0;
00687         break;
00688         
00689         // Only comes through on plug'n'play systems
00690     case WM_DISPLAYCHANGE: {
00691         SIZE szScreen;
00692         BOOL fChanged = (BOOL) wParam;
00693           
00694         szScreen.cx = LOWORD (lParam);
00695         szScreen.cy = HIWORD (lParam);
00696           
00697         if (fChanged) {
00698             // The display 'has' changed. szScreen reflects the
00699             // new size.
00700             MessageBox (GetFocus (), "Display Changed", szAppName, 0);
00701         } else {
00702             // The display 'is' changing. szScreen reflects the
00703             // original size.
00704             MessageBeep (0);
00705         }
00706     }
00707     break;
00708         
00709     case WM_PAINT: {
00710         PAINTSTRUCT ps;
00711         HDC hdc;
00712           
00713         hdc = BeginPaint (hWnd, &ps);
00714         CopyBackingStoreToScreen (hdc, hWnd, &ps);
00715         EndPaint (hWnd, &ps);
00716     }
00717     break;
00718         
00719     // Create client area
00720     case WM_CREATE:
00721         InitializeBackingStore (hWnd);
00722         break;
00723         
00724     case WM_DESTROY:
00725         // PostQuitMessage(0);
00726         exit (0);               // OK??
00727         break;
00728         
00729     case WM_SIZE:
00730         // Resize window
00731         if (wParam != SIZE_MINIMIZED) {
00732             pending_resize_event = 1;
00733             pending_resize_w = LOWORD (lParam);
00734             pending_resize_h = HIWORD (lParam);
00735             ResizeBackingStore (hWnd);
00736         }
00737         break;
00738 
00739     case WM_GETMINMAXINFO: {
00740         /* GCS FIX */
00741         /* This needs to include client menu */
00742         /* To do this, I need to call AdjustWindowRect, but 
00743             probably I need consider that the window might be POPUP... */
00744         LPMINMAXINFO lpmmi = (LPMINMAXINFO) lParam;
00745 #if defined (commentout)
00746         lpmmi->ptMinTrackSize.x = (640 << pix_double) + 2 * borderx;
00747         lpmmi->ptMinTrackSize.y = (480 << pix_double) + 2 * bordery;
00748 #endif
00749         lpmmi->ptMinTrackSize.x = display.min_w;
00750         lpmmi->ptMinTrackSize.y = display.min_h;
00751         break;
00752         }
00753 
00754     default:
00755         return (DefWindowProc (hWnd, message, wParam, lParam));
00756     }
00757     return (0);
00758 }
00759 
00760 
00761 
00762 //----------------------------------------------------------------------------
00763 //  FUNCTION: InitializeBackingStore ()
00764 //----------------------------------------------------------------------------
00765 void
00766 InitializeBackingStore (HWND hWnd) 
00767 {
00768     RECT rc;
00769     
00770     GetClientRect (hWnd, &rc);
00771     display.winW = rc.right - rc.left;
00772     display.winH = rc.bottom - rc.top;
00773     
00774     InitializePalette ();
00775     CreateDDB (hWnd);
00776     if (display.useDIB) {
00777         CreateDIB ();
00778     }
00779     display.hSaveUnderHdc = 0;
00780     display.hSaveUnderBitmap = 0;
00781 }
00782 
00783 void
00784 ResizeBackingStore (HWND hWnd) 
00785 {
00786     ResizeDDB (hWnd);
00787     if (display.useDIB) {
00788         // This had better be false
00789         exit(-1);
00790     }
00791 }
00792 
00793 
00794 
00795 //----------------------------------------------------------------------------
00796 //  FUNCTION: InitializePalette ()
00797 //----------------------------------------------------------------------------
00798 void
00799 InitializePalette (void)
00800 {
00801     INT iLoop;
00802     
00803     display.hPal = 0;
00804     display.pLogPal = 0;
00805     // Clear out palette arrays
00806     for (iLoop = 0; iLoop < 256; iLoop++) {
00807         display.colorrefPal[iLoop] = 0;
00808         display.brushPal[iLoop] = 0;
00809     }
00810     
00811     // If the device uses a palette (e.g. 8 bit display),
00812     // we need to create an HPALETTE for the HDC.
00813     if (display.hasPalette) {
00814         // Allocate memory for LOGPALETTE
00815         display.pLogPal = (NPLOGPALETTE) LocalAlloc (LMEM_FIXED, 
00816                                                      (sizeof (LOGPALETTE) + 
00817                                                       (sizeof (PALETTEENTRY) * (display.paletteSize))));
00818         if (!display.pLogPal) {
00819             MessageBox (display.hWnd, "Not enough memory for logical palette.", NULL, MB_OK | MB_ICONHAND);
00820             PostQuitMessage (0);
00821             exit (-1);
00822         }
00823         display.pLogPal->palVersion = 0x300;
00824         display.pLogPal->palNumEntries = display.paletteSize;
00825       
00826         // Fill palette with system colors by default
00827         for (iLoop = 0; iLoop < display.paletteSize; iLoop++) {
00828             *((WORD *) (&display.pLogPal->palPalEntry[iLoop].peRed)) = (WORD) iLoop;
00829             display.pLogPal->palPalEntry[iLoop].peBlue = 0;
00830             display.pLogPal->palPalEntry[iLoop].peFlags = PC_EXPLICIT;
00831         }
00832       
00833         // Convert LOGPALETTE into HPALETTE
00834         display.hPal = CreatePalette ((LPLOGPALETTE) display.pLogPal);
00835     }
00836 }
00837 
00838 
00839 //----------------------------------------------------------------------------
00840 //  FUNCTION: CreateDIB ()
00841 //----------------------------------------------------------------------------
00842 void
00843 CreateDIB (void) 
00844 {
00845     // Let's create a 256 color DIB, just for testing!
00846     ULONG sizBMI;
00847     INT iNumClr = 256;
00848     INT iLoop;
00849     
00850     // Get memory for 256 color BITMAPINFO
00851     sizBMI = sizeof (BITMAPINFOHEADER) + sizeof (RGBQUAD) * iNumClr;
00852     if ((display.pbminfo = (PBITMAPINFO) GlobalAlloc (GMEM_FIXED | GMEM_ZEROINIT, sizBMI)) == NULL) {
00853         MessageBox (display.hWnd, "Failed in Memory Allocation for bminfo!", "Error", MB_OK);
00854         exit (-1);
00855     }
00856 
00857     // Fill in bitmap info
00858     display.pbminfo->bmiHeader.biSize = 0x28;   // GDI needs this to work
00859     display.pbminfo->bmiHeader.biWidth = display.winW;
00860     display.pbminfo->bmiHeader.biHeight = display.winH;
00861     display.pbminfo->bmiHeader.biPlanes = 1;
00862     display.pbminfo->bmiHeader.biBitCount = 8;
00863     display.pbminfo->bmiHeader.biCompression = BI_RGB;
00864     // this choice for biSizeImage reflects one byte per pixel
00865     display.pbminfo->bmiHeader.biSizeImage = display.winW * display.winH;
00866     display.pbminfo->bmiHeader.biXPelsPerMeter = 0;
00867     display.pbminfo->bmiHeader.biYPelsPerMeter = 0;
00868     display.pbminfo->bmiHeader.biClrUsed = 0;
00869     display.pbminfo->bmiHeader.biClrImportant = 0;
00870     
00871     // Fill in colormap w/ black
00872     for (iLoop = 0; iNumClr; iLoop++) {
00873         display.pbminfo->bmiColors[iLoop].rgbRed = 0;
00874         display.pbminfo->bmiColors[iLoop].rgbGreen = 0;
00875         display.pbminfo->bmiColors[iLoop].rgbBlue = 0;
00876         display.pbminfo->bmiColors[iLoop].rgbReserved = 0;
00877     }
00878   
00879     // CreateDIBSection() will allocate the pBits.
00880     display.hDIB = CreateDIBSection (display.hdcMem, display.pbminfo, 
00881                                      DIB_RGB_COLORS, 
00882                                      (void **) (&display.pBits), NULL, 0);
00883 }
00884 
00885 
00886 
00887 //----------------------------------------------------------------------------
00888 //  FUNCTION: CreateDDB ()
00889 //----------------------------------------------------------------------------
00890 void
00891 CreateDDB (HWND hWnd) 
00892 {
00893     HDC hdc;
00894     HBITMAP hBitmapOri;
00895     HPALETTE hPalOld;
00896     RECT rect;
00897     HBRUSH hbr, hbrOld;
00898 
00899     hdc = GetDC (hWnd);
00900     if (display.hasPalette) {
00901         hPalOld = SelectPalette (hdc, (HPALETTE) display.hPal, FALSE);
00902         if (RealizePalette (hdc)) {
00903             UpdateColors (hdc);
00904         }
00905     }
00906   
00907     // Before an application can use a memory device 
00908     // context for drawing operations, it must select 
00909     // a bitmap of the correct width and height into 
00910     // the device context. Once a bitmap has been selected, 
00911     // the device context can be used to prepare images 
00912     // that will be copied to the screen or printed. 
00913     display.hdcMem = CreateCompatibleDC (hdc);
00914     if (display.hasPalette) {
00915         display.hPaletteMemOri = SelectPalette (display.hdcMem, (HPALETTE) display.hPal, FALSE);
00916         RealizePalette (display.hdcMem);
00917     }
00918     display.hBitmap = CreateCompatibleBitmap (hdc, display.winW, display.winH);
00919     hBitmapOri = (HBITMAP) SelectObject (display.hdcMem, display.hBitmap);
00920   
00921     // Write that nasty brown color into the backing store
00922     rect.left = 0;
00923     rect.top = 0;
00924     rect.right = display.winW;
00925     rect.bottom = display.winH;
00926     hbr = hbrBackground;
00927     hbrOld = (HBRUSH) SelectObject (hdc, hbr);  // Select brush
00928     FillRect (display.hdcMem, &rect, (HBRUSH) hbr);     // Draw rectangle
00929     hbr = (HBRUSH) SelectObject (display.hdcMem, hbrOld);               // Unselect brush
00930   
00931 #if defined (commentout)
00932     // GCS: For now, just keep the old bitmap around.
00933     //      I'll use it to swap out the full-sized color bitmap
00934     //      when I do a SetDIBits/GetDIBits.
00935     display.hBitmapOri = hBitmapOri;
00936 #endif /*  */
00937     
00938 #if defined (commentout)
00939     // GCS: Instead of reselecting the default bitmap back into the hdc,
00940     //      I'm gonna delete it. Any problems with this??
00941     DeleteObject (hBitmapOri);
00942 #endif /*  */
00943     
00944     ReleaseDC (hWnd, hdc);
00945 }
00946 
00947 
00948 void
00949 ResizeDDB (HWND hWnd) 
00950 {
00951     RECT rect;
00952     HDC hdc;
00953     HBRUSH hbr, hbrOld;
00954 
00955     hdc = GetDC (hWnd);
00956     DeleteObject (display.hBitmap);
00957     display.hBitmap = CreateCompatibleBitmap (hdc, pending_resize_w, pending_resize_h);
00958     SelectObject (display.hdcMem, display.hBitmap);
00959 
00960     rect.left = 0;
00961     rect.top = 0;
00962     rect.right = pending_resize_w;
00963     rect.bottom = pending_resize_h;
00964     hbr = hbrBackground;
00965     hbrOld = (HBRUSH) SelectObject (hdc, hbr);              // Select brush
00966     FillRect (display.hdcMem, &rect, (HBRUSH) hbr);         // Draw rectangle
00967     hbr = (HBRUSH) SelectObject (display.hdcMem, hbrOld);   // Unselect brush
00968 
00969     ReleaseDC (hWnd, hdc);
00970 }
00971 
00972 //----------------------------------------------------------------------------
00973 //  FUNCTION: CopyBackingStoreToScreen ()
00974 //----------------------------------------------------------------------------
00975 BOOL CopyBackingStoreToScreen (HDC hdc, HWND hWnd, LPPAINTSTRUCT ps) 
00976 {
00977     HPALETTE hPalOld, hPalOldMem;
00978     
00979     // Is this necessary???
00980     if (display.hasPalette) {
00981         hPalOldMem = SelectPalette (display.hdcMem, (HPALETTE) display.hPal, FALSE);
00982         RealizePalette (display.hdcMem);
00983         hPalOld = SelectPalette (hdc, (HPALETTE) display.hPal, FALSE);
00984         RealizePalette (hdc);
00985     }
00986     
00987     // Copy DIB into DDB
00988     if (display.useDIB) {
00989         if (SetDIBits (display.hdcMem, display.hBitmap, 0, 
00990                        display.pbminfo->bmiHeader.biHeight, (LPSTR) display.pBits, 
00991                        display.pbminfo, DIB_RGB_COLORS) == 0)
00992         {
00993             MessageBox (display.hWnd, "Failed in SetDIBits!", "Error", MB_OK);
00994             exit (-1);
00995         }
00996     }
00997   
00998     // Blast DDB onto screen
00999     if (!BitBlt (hdc, ps->rcPaint.left, ps->rcPaint.top, 
01000                  (int) ps->rcPaint.right - ps->rcPaint.left, 
01001                  (int) ps->rcPaint.bottom - ps->rcPaint.top, 
01002                  display.hdcMem, ps->rcPaint.left, 
01003                  ps->rcPaint.top, SRCCOPY))
01004     {
01005         MessageBox (NULL, "BitBlt failed!", "Failure!", MB_OK);
01006     }
01007   
01008     
01009     // Draw square mouse
01010     if (cs_square_mouse_visible) {
01011         DoSquareMouse (hdc);
01012     }
01013     
01014     if (display.hasPalette) {
01015         display.hPal = SelectPalette (display.hdcMem, hPalOldMem, FALSE);
01016         display.hPal = SelectPalette (hdc, hPalOld, FALSE);
01017     }
01018     return TRUE;
01019 }
01020 
01021 
01022 //----------------------------------------------------------------------------
01023 //  FUNCTION: DoSquareMouse ()
01024 //----------------------------------------------------------------------------
01025 void
01026 DoSquareMouse (HDC hdc) 
01027 {
01028     RECT rect;
01029     int size;
01030     HBRUSH hbr, hbrOld;
01031 
01032     size = (main_groups[selected_module_group].size) * 16;
01033   
01034   // Select Brush
01035     hbr = GetPaletteBrush (white (31));
01036     hbrOld = (HBRUSH) SelectObject (hdc, hbr);
01037   
01038   // Top rectangle
01039     rect.left = AdjustX (omx - 2);
01040     rect.top = AdjustY (omy - 2);
01041     rect.right = AdjustX (omx + size + 1);
01042     rect.bottom = AdjustY (omy - 1);
01043     FillRect (hdc, &rect, hbr);
01044   
01045     
01046   // Left rectangle
01047     rect.left = AdjustX (omx - 2);
01048     rect.top = AdjustY (omy);
01049     rect.right = AdjustX (omx - 1);
01050     rect.bottom = AdjustY (omy + size - 1);
01051     FillRect (hdc, &rect, hbr);
01052     
01053   // Right rectangle
01054     rect.left = AdjustX (omx + size);
01055     rect.top = AdjustY (omy);
01056     rect.right = AdjustX (omx + size + 1);
01057     rect.bottom = AdjustY (omy + size - 1);
01058     FillRect (hdc, &rect, hbr);
01059   
01060   // Bottom rectangle
01061     rect.left = AdjustX (omx - 2);
01062     rect.top = AdjustY (omy + size);
01063     rect.right = AdjustX (omx + size + 1);
01064     rect.bottom = AdjustY (omy + size + 1);
01065     FillRect (hdc, &rect, hbr);
01066     
01067   // Unselect brush
01068     hbr = (HBRUSH) SelectObject (display.hdcMem, hbrOld);
01069 }
01070 
01071 
01072 //----------------------------------------------------------------------------
01073 //  FUNCTION: CopyPixmapToScreen ()
01074 //----------------------------------------------------------------------------
01075 #if defined (USE_PIXMAPS)
01076 void
01077 CopyPixmapToScreen (int t2, int src_x, int src_y, int width, int height, 
01078                     int dst_x, int dst_y) 
01079 {
01080     HDC hdcPixmap;
01081     RECT rect;
01082   
01083     // Calculate update rectangle
01084     rect.left = AdjustX (dst_x);
01085     rect.top = AdjustY (dst_y);
01086     rect.right = AdjustX (dst_x + width + 1);
01087     rect.bottom = AdjustY (dst_y + height + 1);
01088   
01089     // Copy bitmap
01090     if (display.useDIB) {
01091         HBITMAP hOldBitmap, hOldBitmapMem;
01092         hdcPixmap = CreateCompatibleDC (display.hdcMem);
01093         hOldBitmap = (HBITMAP) SelectObject (hdcPixmap, icon_pixmap[t2]);
01094         hOldBitmapMem = (HBITMAP) SelectObject (display.hdcMem, display.hDIB);
01095         BitBlt (display.hdcMem, dst_x, dst_y, width, height, hdcPixmap, 
01096                 src_x, src_y, SRCCOPY);
01097         icon_pixmap[t2] = (HBITMAP) SelectObject (hdcPixmap, hOldBitmap);
01098         display.hDIB = (HBITMAP) SelectObject (display.hdcMem, hOldBitmapMem);
01099         DeleteDC (hdcPixmap);
01100     } else {
01101         HBITMAP hOldBitmap;
01102         hdcPixmap = CreateCompatibleDC (display.hdcMem);
01103         hOldBitmap = (HBITMAP) SelectObject (hdcPixmap, icon_pixmap[t2]);
01104         BitBlt (display.hdcMem, AdjustX (dst_x), AdjustY (dst_y), 
01105                 width << pix_double, height << pix_double, hdcPixmap, 
01106                 src_x << pix_double, src_y << pix_double, SRCCOPY);
01107         icon_pixmap[t2] = (HBITMAP) SelectObject (hdcPixmap, hOldBitmap);
01108         DeleteDC (hdcPixmap);
01109     }
01110     
01111     // Queue up refresh
01112     InvalidateRect (display.hWnd, &rect, FALSE);
01113 }
01114 #endif /*  */
01115 
01116 
01117 //----------------------------------------------------------------------------
01118 //  FUNCTION: About(HWND, unsigned, WORD, LONG)
01119 //
01120 //  PURPOSE:  Processes messages for "About" dialog box
01121 //              This version allows greater flexibility over the contents of the 'About' box,
01122 //              by pulling out values from the 'Version' resource.
01123 //
01124 //  MESSAGES:
01125 //
01126 //      WM_INITDIALOG - initialize dialog box
01127 //      WM_COMMAND      - Input received
01128 //
01129 //----------------------------------------------------------------------------
01130 #if defined (USE_WIN32_MENU)
01131 LRESULT CALLBACK About (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 
01132 {
01133     static HFONT hfontDlg;      // Font for dialog text
01134     static HFONT hFinePrint;    // Font for 'fine print' in dialog
01135     DWORD dwVerInfoSize;                // Size of version information block
01136     LPSTR lpVersion;            // String pointer to 'version' text
01137     DWORD dwVerHnd = 0;         // An 'ignored' parameter, always '0'
01138     UINT uVersionLen;
01139     WORD wRootLen;
01140     BOOL bRetCode;
01141     int i;
01142     char szFullPath[256];
01143     char szResult[256];
01144     char szGetName[256];
01145     DWORD dwVersion;
01146     char szVersion[40];
01147     DWORD dwResult;
01148     
01149     switch (message)
01150     {
01151     case WM_INITDIALOG:
01152         ShowWindow (hDlg, SW_HIDE);
01153         hfontDlg = CreateFont (16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
01154                                VARIABLE_PITCH | FF_SWISS, "");
01155         hFinePrint = CreateFont (16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
01156                                  VARIABLE_PITCH | FF_SWISS, "");
01157         CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
01158         GetModuleFileName (display.hInst, szFullPath, sizeof (szFullPath));
01159         
01160         // Now lets dive in and pull out the version information:
01161         dwVerInfoSize = GetFileVersionInfoSize (szFullPath, &dwVerHnd);
01162         if (dwVerInfoSize) {
01163             LPSTR lpstrVffInfo;
01164             HANDLE hMem;
01165             hMem = GlobalAlloc (GMEM_MOVEABLE, dwVerInfoSize);
01166             lpstrVffInfo = (char *) GlobalLock (hMem);
01167             GetFileVersionInfo (szFullPath, dwVerHnd, dwVerInfoSize, lpstrVffInfo);
01168 
01169             // The below 'hex' value looks a little confusing, but
01170             // essentially what it is, is the hexidecimal representation
01171             // of a couple different values that represent the language
01172             // and character set that we are wanting string values for.
01173             // 040904E4 is a very common one, because it means:
01174             //   US English, Windows MultiLingual characterset
01175             // Or to pull it all apart:
01176             // 04------             = SUBLANG_ENGLISH_USA
01177             // --09----             = LANG_ENGLISH
01178             // ----04E4 = 1252 = Codepage for Windows:Multilingual
01179             lstrcpy (szGetName, "\\StringFileInfo\\040904E4\\");
01180             wRootLen = lstrlen (szGetName);     // Save this position
01181           
01182             // Set the title of the dialog:
01183             lstrcat (szGetName, "ProductName");
01184             bRetCode = VerQueryValue ((LPVOID) lpstrVffInfo, 
01185                                       (LPSTR) szGetName, 
01186                                       (LPVOID *) & lpVersion, 
01187                                       (UINT *) & uVersionLen);
01188             lstrcpy (szResult, "About ");
01189             lstrcat (szResult, lpVersion);
01190             SetWindowText (hDlg, szResult);
01191           
01192             // Walk through the dialog items that we want to replace:
01193             for (i = DLG_VERFIRST; i <= DLG_VERLAST; i++) {
01194                 GetDlgItemText (hDlg, i, szResult, sizeof (szResult));
01195                 szGetName[wRootLen] = (char) 0;
01196                 lstrcat (szGetName, szResult);
01197                 uVersionLen = 0;
01198                 lpVersion = NULL;
01199                 bRetCode = VerQueryValue ((LPVOID) lpstrVffInfo, 
01200                                           (LPSTR) szGetName, 
01201                                           (LPVOID *) & lpVersion, 
01202                                           (UINT *) & uVersionLen);
01203                 
01204                 if (bRetCode && uVersionLen && lpVersion) {
01205                     // Replace dialog item text with version info
01206                     lstrcpy (szResult, lpVersion);
01207                     SetDlgItemText (hDlg, i, szResult);
01208                 } else {
01209                     dwResult = GetLastError ();
01210                     wsprintf (szResult, "Error %lu", dwResult);
01211                     SetDlgItemText (hDlg, i, szResult);
01212                 }
01213                 SendMessage (GetDlgItem (hDlg, i), WM_SETFONT, 
01214                              (UINT) ((i == DLG_VERLAST) ? hFinePrint : hfontDlg), 
01215                              TRUE);
01216             }
01217             GlobalUnlock (hMem);
01218             GlobalFree (hMem);
01219         } else {
01220             // No version information available.
01221         }
01222         SendMessage (GetDlgItem (hDlg, IDC_LABEL), WM_SETFONT, 
01223                      (WPARAM) hfontDlg, (LPARAM) TRUE);
01224       
01225         // We are  using GetVersion rather then GetVersionEx
01226         // because earlier versions of Windows NT and Win32s
01227         // didn't include GetVersionEx:
01228         dwVersion = GetVersion ();
01229         if (dwVersion < 0x80000000) {
01230             // Windows NT
01231             wsprintf (szVersion, "Microsoft Windows NT %u.%u (Build: %u)", 
01232                       (DWORD) (LOBYTE (LOWORD (dwVersion))), 
01233                       (DWORD) (HIBYTE (LOWORD (dwVersion))), 
01234                       (DWORD) (HIWORD (dwVersion)));
01235           
01236         } else if (LOBYTE (LOWORD (dwVersion)) < 4) {
01237             // Win32s
01238             wsprintf (szVersion, "Microsoft Win32s %u.%u (Build: %u)", 
01239                       (DWORD) (LOBYTE (LOWORD (dwVersion))), 
01240                       (DWORD) (HIBYTE (LOWORD (dwVersion))), 
01241                       (DWORD) (HIWORD (dwVersion) & ~0x8000));
01242         } else {
01243             // Windows 95
01244             wsprintf (szVersion, "Microsoft Windows 95 %u.%u", 
01245                       (DWORD) (LOBYTE (LOWORD (dwVersion))), 
01246                       (DWORD) (HIBYTE (LOWORD (dwVersion))));
01247         }
01248         SetWindowText (GetDlgItem (hDlg, IDC_OSVERSION), szVersion);
01249         ShowWindow (hDlg, SW_SHOW);
01250         return (TRUE);
01251 
01252     case WM_COMMAND:
01253         if (LOWORD (wParam) == IDOK || LOWORD (wParam) == IDCANCEL) {
01254             EndDialog (hDlg, TRUE);
01255             DeleteObject (hfontDlg);
01256             DeleteObject (hFinePrint);
01257             return (TRUE);
01258         }
01259         break;
01260     }
01261     return FALSE;
01262 }
01263 
01264 
01265 
01266 //----------------------------------------------------------------------------
01267 //   FUNCTION: CenterWindow(HWND, HWND)
01268 //
01269 //   PURPOSE: Centers one window over another. 
01270 //
01271 //   COMMENTS:
01272 //
01273 //              In this function, we save the instance handle in a global variable and
01274 //              create and display the main program window.
01275 //
01276 //              This functionwill center one window over another ensuring that 
01277 //              the placement of the window is within the 'working area', meaning 
01278 //              that it is both within the display limits of the screen, and not 
01279 //              obscured by the tray or other framing elements of the desktop.
01280 //----------------------------------------------------------------------------
01281 BOOL CenterWindow (HWND hwndChild, HWND hwndParent) 
01282 {
01283     RECT rChild, rParent, rWorkArea;
01284     int wChild, hChild, wParent, hParent;
01285     int xNew, yNew;
01286     BOOL bResult;
01287 
01288     // Get the Height and Width of the child window
01289     GetWindowRect (hwndChild, &rChild);
01290     wChild = rChild.right - rChild.left;
01291     hChild = rChild.bottom - rChild.top;
01292   
01293     // Get the Height and Width of the parent window
01294     GetWindowRect (hwndParent, &rParent);
01295     wParent = rParent.right - rParent.left;
01296     hParent = rParent.bottom - rParent.top;
01297   
01298     // Get the limits of the 'workarea'
01299     bResult = SystemParametersInfo (SPI_GETWORKAREA,
01300                                     sizeof (RECT), 
01301                                     &rWorkArea, 
01302                                     0);
01303   
01304     if (!bResult) {
01305         rWorkArea.left = rWorkArea.top = 0;
01306         rWorkArea.right = GetSystemMetrics (SM_CXSCREEN);
01307         rWorkArea.bottom = GetSystemMetrics (SM_CYSCREEN);
01308     }
01309     
01310     // Calculate new X position, then adjust for workarea
01311     xNew = rParent.left + ((wParent - wChild) / 2);
01312   
01313     if (xNew < rWorkArea.left) {
01314         xNew = rWorkArea.left;
01315     }
01316     else if ((xNew + wChild) > rWorkArea.right) {
01317         xNew = rWorkArea.right - wChild;
01318     }
01319   
01320     // Calculate new Y position, then adjust for workarea
01321     yNew = rParent.top + ((hParent - hChild) / 2);
01322     if (yNew < rWorkArea.top) {
01323         yNew = rWorkArea.top;
01324     } else if ((yNew + hChild) > rWorkArea.bottom) {
01325         yNew = rWorkArea.bottom - hChild;
01326     }
01327   
01328     // Set it, and return
01329     return SetWindowPos (hwndChild, NULL, xNew, yNew, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
01330 }
01331 #endif /* USE_WIN32_MENU */
01332 
01333 
01334 //----------------------------------------------------------------------------
01335 //   FUNCTION: AddPaletteEntry ()
01336 //----------------------------------------------------------------------------
01337 void
01338 AddPaletteEntry (int col, int red, int grn, int blu) 
01339 {
01340   
01341     red = (red * 255) / 62;
01342     if (red > 255)
01343         red = 255;
01344   
01345     grn = (grn * 255) / 62;
01346     if (grn > 255)
01347         grn = 255;
01348   
01349     blu = (blu * 255) / 62;
01350     if (blu > 255)
01351         blu = 255;
01352     
01353     display.colorrefPal[col] = RGB (red, grn, blu);
01354     
01355     if (display.brushPal[col]) {
01356         DeleteObject (display.brushPal[col]);
01357         display.brushPal[col] = 0;
01358     }
01359   
01360     if (display.hasPalette) {
01361         display.pLogPal->palPalEntry[col].peRed = red;
01362         display.pLogPal->palPalEntry[col].peGreen = grn;
01363         display.pLogPal->palPalEntry[col].peBlue = blu;
01364         display.pLogPal->palPalEntry[col].peFlags = PC_NOCOLLAPSE;
01365     }
01366   
01367     if (display.useDIB) {
01368         display.pbminfo->bmiColors[col].rgbRed = red;
01369         display.pbminfo->bmiColors[col].rgbGreen = grn;
01370         display.pbminfo->bmiColors[col].rgbBlue = blu;
01371         display.pbminfo->bmiColors[col].rgbReserved = 0;
01372     }
01373 }
01374 
01375 
01376 //----------------------------------------------------------------------------
01377 //  FUNCTION: UpdatePalette ()
01378 //----------------------------------------------------------------------------
01379 void
01380 UpdatePalette (void) 
01381 {
01382     if (display.hasPalette) {
01383         // Make a new HPALETTE and select to hdcGlobal and hdcMem
01384         HPALETTE hPalNew;
01385         hPalNew = CreatePalette ((LPLOGPALETTE) display.pLogPal);
01386         SelectPalette (display.hdcMem, hPalNew, FALSE);
01387         RealizePalette (display.hdcMem);
01388         DeleteObject (display.hPal);
01389         display.hPal = hPalNew;
01390     }
01391 }
01392 

Generated on Sun Dec 26 11:23:26 2004 for lincity by  doxygen 1.3.9.1