home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / sdktools / zoomin / zoomin.c < prev    next >
C/C++ Source or Header  |  1996-06-12  |  20KB  |  737 lines

  1. /****************************************************************************/
  2. /*                                                                          */
  3. /*                         Microsoft Confidential                           */
  4. /*                                                                          */
  5. /*                 Copyright (c) Microsoft Corp.  1987-1996                 */
  6. /*                           All Rights Reserved                            */
  7. /*                                                                          */
  8. /****************************************************************************/
  9. /****************************** Module Header *******************************
  10. * Module Name: zoomin.c
  11. *
  12. * Microsoft ZoomIn utility.  This tool magnifies a portion of the screen,
  13. * allowing you to see things at a pixel level.
  14. *
  15. * History:
  16. * 01/01/88                              Created.
  17. * 01/01/92                              Ported to NT.
  18. * 03/06/92                              Cleanup.
  19. *
  20. ****************************************************************************/
  21.  
  22. #include "zoomin.h"
  23.  
  24.  
  25. CHAR szAppName[] = "ZoomIn";            // Aplication name.
  26. HINSTANCE ghInst;                       // Instance handle.
  27. HWND ghwndApp;                          // Main window handle.
  28. HANDLE ghaccelTable;                    // Main accelerator table.
  29. INT gnZoom = 4;                         // Zoom (magnification) factor.
  30. HPALETTE ghpalPhysical;                 // Handle to the physical palette.
  31. INT gcxScreenMax;                       // Width of the screen (less 1).
  32. INT gcyScreenMax;                       // Height of the screen (less 1).
  33. INT gcxZoomed;                          // Client width in zoomed pixels.
  34. INT gcyZoomed;                          // Client height in zoomed pixels.
  35. BOOL gfRefEnable = FALSE;               // TRUE if refresh is enabled.
  36. INT gnRefInterval = 20;                 // Refresh interval in 10ths of seconds.
  37. BOOL gfTracking = FALSE;                // TRUE if tracking is in progress.
  38. POINT gptZoom = {100, 100};             // The center of the zoomed area.
  39.  
  40.  
  41.  
  42. /************************************************************************
  43. * WinMain
  44. *
  45. * Main entry point for the application.
  46. *
  47. * Arguments:
  48. *
  49. * History:
  50. *
  51. ************************************************************************/
  52.  
  53. INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, INT nCmdShow)
  54. {
  55.     MSG msg;
  56.  
  57.     if (!InitInstance(hInst, nCmdShow))
  58.         return FALSE;
  59.  
  60.     /*     * Polling messages from event queue
  61.      */
  62.  
  63.     while (GetMessage(&msg, NULL, 0, 0)) {
  64.         if (!TranslateAccelerator(ghwndApp, ghaccelTable, &msg)) {
  65.             TranslateMessage(&msg);
  66.             DispatchMessage(&msg);
  67.         }
  68.     }
  69.  
  70.     return msg.wParam;
  71. }
  72.  
  73.  
  74.  
  75. /************************************************************************
  76. * InitInstance
  77. *
  78. * Instance initialization for the app.
  79. *
  80. * Arguments:
  81. *
  82. * History:
  83. *
  84. ************************************************************************/
  85.  
  86. BOOL InitInstance(
  87.     HINSTANCE hInst,
  88.     INT cmdShow)
  89. {
  90.     WNDCLASS wc;
  91.     INT dx;
  92.     INT dy;
  93.     DWORD flStyle;
  94.     RECT rc;
  95.  
  96.     ghInst = hInst;
  97.  
  98.     /*
  99.      * Register a class for the main application window.
  100.      */
  101.     wc.hCursor        = LoadCursor(NULL, IDC_ARROW);
  102.     wc.hIcon          = LoadIcon(hInst, "zoomin");
  103.     wc.lpszMenuName   = MAKEINTRESOURCE(IDMENU_ZOOMIN);
  104.     wc.lpszClassName  = szAppName;
  105.     wc.hbrBackground  = GetStockObject(BLACK_BRUSH);
  106.     wc.hInstance      = hInst;
  107.     wc.style          = CS_BYTEALIGNCLIENT | CS_VREDRAW | CS_HREDRAW;
  108.     wc.lpfnWndProc    = (WNDPROC)AppWndProc;
  109.     wc.cbWndExtra     = 0;
  110.     wc.cbClsExtra     = 0;
  111.  
  112.     if (!RegisterClass(&wc))
  113.         return FALSE;
  114.  
  115.     if (!(ghaccelTable = LoadAccelerators(hInst, MAKEINTRESOURCE(IDACCEL_ZOOMIN))))
  116.         return FALSE;
  117.  
  118.     if (!(ghpalPhysical = CreatePhysicalPalette()))
  119.         return FALSE;
  120.  
  121.     gcxScreenMax = GetSystemMetrics(SM_CXSCREEN) - 1;    gcyScreenMax = GetSystemMetrics(SM_CYSCREEN) - 1;
  122.  
  123.     flStyle = WS_CAPTION | WS_OVERLAPPED | WS_SYSMENU | WS_THICKFRAME |
  124.             WS_MINIMIZEBOX | WS_VSCROLL;
  125.     dx = 44 * gnZoom;
  126.     dy = 36 * gnZoom;
  127.  
  128.     SetRect(&rc, 0, 0, dx, dy);
  129.     AdjustWindowRect(&rc, flStyle, TRUE);
  130.  
  131.     ghwndApp = CreateWindow(szAppName, szAppName, flStyle,
  132.             CW_USEDEFAULT, 0, rc.right - rc.left, rc.bottom - rc.top,
  133.             NULL, NULL, hInst, NULL);
  134.  
  135.     if (!ghwndApp)
  136.         return FALSE;
  137.     ShowWindow(ghwndApp, cmdShow);
  138.  
  139.     return TRUE;
  140. }
  141.  
  142.  
  143.  
  144. /************************************************************************
  145. * CreatePhysicalPalette
  146. *
  147. * Creates a palette for the app to use.  The palette references the
  148. * physical palette, so that it can properly display images grabbed
  149. * from palette managed apps.
  150. *
  151. * History:
  152. *
  153. ************************************************************************/
  154.  
  155. HPALETTE CreatePhysicalPalette(VOID)
  156. {
  157.     PLOGPALETTE ppal;
  158.     HPALETTE hpal = NULL;
  159.     INT i;
  160.  
  161.     ppal = (PLOGPALETTE)LocalAlloc(LPTR,
  162.             sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * NPAL);
  163.     if (ppal) {
  164.         ppal->palVersion = 0x300;
  165.         ppal->palNumEntries = NPAL;
  166.  
  167.         for (i = 0; i < NPAL; i++) {
  168.             ppal->palPalEntry[i].peFlags = (BYTE)PC_EXPLICIT;
  169.             ppal->palPalEntry[i].peRed   = (BYTE)i;
  170.             ppal->palPalEntry[i].peGreen = (BYTE)0;
  171.             ppal->palPalEntry[i].peBlue  = (BYTE)0;
  172.         }
  173.  
  174.         hpal = CreatePalette(ppal);
  175.         LocalFree(ppal);
  176.     }
  177.  
  178.     return hpal;
  179. }
  180.  
  181.  
  182.  
  183. /************************************************************************
  184. * AppWndProc
  185. *
  186. * Main window proc for the zoomin utility.
  187. *
  188. * Arguments:
  189. *   Standard window proc args.
  190. *
  191. * History:
  192. *
  193. ************************************************************************/
  194.  
  195. LONG APIENTRY AppWndProc(
  196.     HWND hwnd,
  197.     UINT msg,
  198.     WPARAM wParam,
  199.     LPARAM lParam)
  200. {
  201.     PAINTSTRUCT ps;
  202.     HCURSOR hcurOld;
  203.  
  204.     switch (msg) {
  205.         case WM_CREATE:
  206.             SetScrollRange(hwnd, SB_VERT, MIN_ZOOM, MAX_ZOOM, FALSE);
  207.             SetScrollPos(hwnd, SB_VERT, gnZoom, FALSE);
  208.             break;
  209.  
  210.         case WM_TIMER:
  211.             /*
  212.              * Update on every timer message.  The cursor will be
  213.              * flashed to the hourglash for some visual feedback
  214.              * of when a snapshot is being taken.
  215.              */
  216.             hcurOld = SetCursor(LoadCursor(NULL, IDC_WAIT));
  217.             DoTheZoomIn(NULL);
  218.             SetCursor(hcurOld);
  219.             break;
  220.  
  221.         case WM_PAINT:
  222.             BeginPaint(hwnd, &ps);
  223.             DoTheZoomIn(ps.hdc);
  224.             EndPaint(hwnd, &ps);
  225.             return 0L;
  226.  
  227.         case WM_SIZE:
  228.             CalcZoomedSize();
  229.             break;
  230.  
  231.         case WM_LBUTTONDOWN:
  232.             ((gptZoom).x = (SHORT)LOWORD(lParam), (gptZoom).y = (SHORT)HIWORD(lParam));
  233.             ClientToScreen(hwnd, &gptZoom);
  234.             DrawZoomRect();
  235.             DoTheZoomIn(NULL);
  236.  
  237.             SetCapture(hwnd);
  238.             gfTracking = TRUE;
  239.  
  240.             break;
  241.  
  242.         case WM_MOUSEMOVE:
  243.             if (gfTracking) {
  244.                 DrawZoomRect();
  245.                 ((gptZoom).x = (SHORT)LOWORD(lParam), (gptZoom).y = (SHORT)HIWORD(lParam));
  246.                 ClientToScreen(hwnd, &gptZoom);
  247.                 DrawZoomRect();
  248.                 DoTheZoomIn(NULL);
  249.             }
  250.  
  251.             break;
  252.  
  253.         case WM_LBUTTONUP:
  254.             if (gfTracking) {
  255.                 DrawZoomRect();
  256.                 ReleaseCapture();
  257.                 gfTracking = FALSE;
  258.             }
  259.  
  260.             break;
  261.  
  262.         case WM_VSCROLL:
  263.             switch (LOWORD(wParam)) {
  264.                 case SB_LINEDOWN:
  265.                     gnZoom++;
  266.                     break;
  267.  
  268.                 case SB_LINEUP:
  269.                     gnZoom--;
  270.                     break;
  271.  
  272.                 case SB_PAGEUP:
  273.                     gnZoom -= 2;
  274.                     break;
  275.  
  276.                 case SB_PAGEDOWN:
  277.                     gnZoom += 2;
  278.                     break;
  279.  
  280.                 case SB_THUMBPOSITION:
  281.                 case SB_THUMBTRACK:
  282.                     gnZoom = HIWORD(wParam);
  283.                     break;
  284.             }
  285.  
  286.             gnZoom = BOUND(gnZoom, MIN_ZOOM, MAX_ZOOM);
  287.             SetScrollPos(hwnd, SB_VERT, gnZoom, TRUE);
  288.             CalcZoomedSize();
  289.             DoTheZoomIn(NULL);
  290.             break;
  291.  
  292.         case WM_KEYDOWN:
  293.             switch (wParam) {
  294.                 case VK_UP:
  295.                 case VK_DOWN:
  296.                 case VK_LEFT:
  297.                 case VK_RIGHT:
  298.                     MoveView((INT)wParam, GetKeyState(VK_SHIFT) & 0x8000,
  299.                             GetKeyState(VK_CONTROL) & 0x8000);
  300.                     break;
  301.             }
  302.  
  303.             break;
  304.  
  305.         case WM_COMMAND:
  306.             switch (LOWORD(wParam)) {
  307.                 case MENU_EDIT_COPY:
  308.                     CopyToClipboard();
  309.                     break;
  310.  
  311.                 case MENU_EDIT_REFRESH:
  312.                     DoTheZoomIn(NULL);
  313.                     break;
  314.  
  315.                 case MENU_OPTIONS_REFRESHRATE:
  316.                     DialogBox(ghInst, (LPSTR)MAKEINTRESOURCE(DID_REFRESHRATE),
  317.                             hwnd, (WNDPROC)RefreshRateDlgProc);
  318.  
  319.                     break;
  320.  
  321.                 case MENU_HELP_ABOUT:
  322.                     DialogBox(ghInst, (LPSTR)MAKEINTRESOURCE(DID_ABOUT),
  323.                             hwnd, (WNDPROC)AboutDlgProc);
  324.  
  325.                     break;
  326.  
  327.                 default:
  328.                      break;
  329.             }
  330.  
  331.             break;
  332.  
  333.         case WM_CLOSE:
  334.             if (ghpalPhysical)
  335.                 DeleteObject(ghpalPhysical);
  336.  
  337.             DestroyWindow(hwnd);
  338.  
  339.             break;
  340.  
  341.         case WM_DESTROY:
  342.             PostQuitMessage(0);
  343.             break;
  344.  
  345.         default:
  346.             return DefWindowProc(hwnd, msg, wParam, lParam);
  347.     }
  348.  
  349.     return 0L;
  350. }
  351.  
  352.  
  353.  
  354. /************************************************************************
  355. * CalcZoomedSize
  356. *
  357. * Calculates some globals.  This routine needs to be called any
  358. * time that the size of the app or the zoom factor changes.
  359. *
  360. * History:
  361. *
  362. ************************************************************************/
  363.  
  364. VOID CalcZoomedSize(VOID)
  365. {
  366.     RECT rc;
  367.  
  368.     GetClientRect(ghwndApp, &rc);
  369.  
  370.     gcxZoomed = (rc.right / gnZoom) + 1;
  371.     gcyZoomed = (rc.bottom / gnZoom) + 1;
  372. }
  373.  
  374.  
  375.  
  376. /************************************************************************
  377. * DoTheZoomIn
  378. *
  379. * Does the actual paint of the zoomed image.
  380. *
  381. * Arguments:
  382. *   HDC hdc - If not NULL, this hdc will be used to paint with.
  383. *             If NULL, a dc for the apps window will be obtained.
  384. *
  385. * History:
  386. *
  387. ************************************************************************/
  388.  
  389. VOID DoTheZoomIn(
  390.     HDC hdc)
  391. {
  392.     BOOL fRelease;
  393.     HPALETTE hpalOld = NULL;
  394.     HDC hdcScreen;
  395.     INT x;
  396.     INT y;
  397.  
  398.     if (!hdc) {
  399.         hdc = GetDC(ghwndApp);
  400.         fRelease = TRUE;
  401.     }
  402.     else {
  403.         fRelease = FALSE;
  404.     }
  405.  
  406.     if (ghpalPhysical) {
  407.         hpalOld = SelectPalette(hdc, ghpalPhysical, FALSE);
  408.         RealizePalette(hdc);
  409.     }
  410.  
  411.     /*
  412.      * The point must not include areas outside the screen dimensions.
  413.      */
  414.     x = BOUND(gptZoom.x, gcxZoomed / 2, gcxScreenMax - (gcxZoomed / 2));
  415.     y = BOUND(gptZoom.y, gcyZoomed / 2, gcyScreenMax - (gcyZoomed / 2));
  416.  
  417.     hdcScreen = GetDC(NULL);
  418.     SetStretchBltMode(hdc, COLORONCOLOR);
  419.     StretchBlt(hdc, 0, 0, gnZoom * gcxZoomed, gnZoom * gcyZoomed,
  420.             hdcScreen, x - gcxZoomed / 2,
  421.             y - gcyZoomed / 2, gcxZoomed, gcyZoomed, SRCCOPY);
  422.     ReleaseDC(NULL, hdcScreen);
  423.  
  424.     if (hpalOld)
  425.         SelectPalette(hdc, hpalOld, FALSE);
  426.  
  427.     if (fRelease)
  428.         ReleaseDC(ghwndApp, hdc);
  429. }
  430.  
  431.  
  432.  
  433. /************************************************************************
  434. * MoveView
  435. *
  436. * This function moves the current view around.
  437. *
  438. * Arguments:
  439. *   INT nDirectionCode - Direction to move.  Must be VK_UP, VK_DOWN,
  440. *                        VK_LEFT or VK_RIGHT.
  441. *   BOOL fFast         - TRUE if the move should jump a larger increment.
  442. *                        If FALSE, the move is just one pixel.
  443. *   BOOL fPeg          - If TRUE, the view will be pegged to the screen
  444. *                        boundary in the specified direction.  This overides
  445. *                        the fFast parameter.
  446. *
  447. * History:
  448. *
  449. ************************************************************************/
  450.  
  451. VOID MoveView(
  452.     INT nDirectionCode,
  453.     BOOL fFast,
  454.     BOOL fPeg)
  455. {
  456.     INT delta;
  457.  
  458.     if (fFast)
  459.         delta = FASTDELTA;
  460.     else
  461.         delta = 1;
  462.  
  463.     switch (nDirectionCode) {
  464.         case VK_UP:
  465.             if (fPeg)
  466.                 gptZoom.y = gcyZoomed / 2;
  467.             else
  468.                 gptZoom.y -= delta;
  469.  
  470.             gptZoom.y = BOUND(gptZoom.y, 0, gcyScreenMax);
  471.  
  472.             break;
  473.  
  474.         case VK_DOWN:
  475.             if (fPeg)
  476.                 gptZoom.y = gcyScreenMax - (gcyZoomed / 2);
  477.             else
  478.                 gptZoom.y += delta;
  479.  
  480.             gptZoom.y = BOUND(gptZoom.y, 0, gcyScreenMax);
  481.  
  482.             break;
  483.  
  484.         case VK_LEFT:
  485.             if (fPeg)
  486.                 gptZoom.x = gcxZoomed / 2;
  487.             else
  488.                 gptZoom.x -= delta;
  489.  
  490.             gptZoom.x = BOUND(gptZoom.x, 0, gcxScreenMax);
  491.  
  492.             break;
  493.  
  494.         case VK_RIGHT:
  495.             if (fPeg)
  496.                 gptZoom.x = gcxScreenMax - (gcxZoomed / 2);
  497.             else
  498.                 gptZoom.x += delta;
  499.  
  500.             gptZoom.x = BOUND(gptZoom.x, 0, gcxScreenMax);
  501.  
  502.             break;
  503.     }
  504.  
  505.     DoTheZoomIn(NULL);
  506. }
  507.  
  508.  
  509.  
  510. /************************************************************************
  511. * DrawZoomRect
  512. *
  513. * This function draws the tracking rectangle.  The size and shape of
  514. * the rectangle will be proportional to the size and shape of the
  515. * app's client, and will be affected by the zoom factor as well.
  516. *
  517. * History:
  518. *
  519. ************************************************************************/
  520.  
  521. VOID DrawZoomRect(VOID)
  522. {
  523.     HDC hdc;
  524.     RECT rc;
  525.     INT x;
  526.     INT y;
  527.  
  528.     x = BOUND(gptZoom.x, gcxZoomed / 2, gcxScreenMax - (gcxZoomed / 2));
  529.     y = BOUND(gptZoom.y, gcyZoomed / 2, gcyScreenMax - (gcyZoomed / 2));
  530.  
  531.     rc.left   = x - gcxZoomed / 2;
  532.     rc.top    = y - gcyZoomed / 2;
  533.     rc.right  = rc.left + gcxZoomed;
  534.     rc.bottom = rc.top + gcyZoomed;
  535.  
  536.     InflateRect(&rc, 1, 1);
  537.  
  538.     hdc = GetDC(NULL);
  539.  
  540.     PatBlt(hdc, rc.left,    rc.top,     rc.right-rc.left, 1,  DSTINVERT);
  541.     PatBlt(hdc, rc.left,    rc.bottom,  1, -(rc.bottom-rc.top),   DSTINVERT);
  542.     PatBlt(hdc, rc.right-1, rc.top,     1,   rc.bottom-rc.top,   DSTINVERT);
  543.     PatBlt(hdc, rc.right,   rc.bottom-1, -(rc.right-rc.left), 1, DSTINVERT);
  544.  
  545.     ReleaseDC(NULL, hdc);
  546. }
  547.  
  548.  
  549.  
  550. /************************************************************************
  551. * EnableRefresh
  552. *
  553. * This function turns on or off the auto-refresh feature.
  554. *
  555. * Arguments:
  556. *   BOOL fEnable - TRUE to turn the refresh feature on, FALSE to
  557. *                  turn it off.
  558. *
  559. * History:
  560. *
  561. ************************************************************************/
  562.  
  563. VOID EnableRefresh(
  564.     BOOL fEnable)
  565. {
  566.     if (fEnable) {
  567.         /*
  568.          * Already enabled.  Do nothing.
  569.          */
  570.         if (gfRefEnable)
  571.             return;
  572.  
  573.         if (SetTimer(ghwndApp, IDTIMER_ZOOMIN, gnRefInterval * 100, NULL))
  574.             gfRefEnable = TRUE;
  575.     }
  576.     else {
  577.         /*
  578.          * Not enabled yet.  Do nothing.
  579.          */
  580.         if (!gfRefEnable)
  581.             return;
  582.  
  583.         KillTimer(ghwndApp, IDTIMER_ZOOMIN);
  584.         gfRefEnable = FALSE;
  585.     }
  586. }
  587.  
  588.  
  589.  
  590. /************************************************************************
  591. * CopyToClipboard
  592. *
  593. * This function copies the client area image of the app into the
  594. * clipboard.
  595. *
  596. * History:
  597. *
  598. ************************************************************************/
  599.  
  600. VOID CopyToClipboard(VOID)
  601. {
  602.     HDC hdcSrc;
  603.     HDC hdcDst;
  604.     RECT rc;
  605.     HBITMAP hbm;
  606.  
  607.     if (OpenClipboard(ghwndApp)) {
  608.         EmptyClipboard();
  609.  
  610.         if (hdcSrc = GetDC(ghwndApp)) {
  611.             GetClientRect(ghwndApp, &rc);
  612.             if (hbm = CreateCompatibleBitmap(hdcSrc,
  613.                     rc.right - rc.left, rc.bottom - rc.top)) {
  614.                 if (hdcDst = CreateCompatibleDC(hdcSrc)) {
  615.                     /*
  616.                      * Calculate the dimensions of the bitmap and
  617.                      * convert them to tenths of a millimeter for
  618.                      * setting the size with the SetBitmapDimensionEx
  619.                      * call.  This allows programs like WinWord to
  620.                      * retrieve the bitmap and know what size to
  621.                      * display it as.
  622.                      */
  623.                     
  624.  
  625.  
  626.  
  627.  
  628.  
  629. SetBitmapDimensionEx(hbm, (DWORD)((INT)(((DWORD)(rc.right - rc.left) * MM10PERINCH) / (DWORD)GetDeviceCaps(hdcSrc, LOGPIXELSX))), (DWORD)((INT)(((DWORD)(rc.bottom - rc.top) * MM10PERINCH) / (DWORD)GetDeviceCaps(hdcSrc, LOGPIXELSY))), NULL);
  630.  
  631.                     SelectObject(hdcDst, hbm);
  632.                     BitBlt(hdcDst, 0, 0,
  633.                             rc.right - rc.left, rc.bottom - rc.top,
  634.                             hdcSrc, rc.left, rc.top, SRCCOPY);
  635.                     DeleteDC(hdcDst);
  636.                     SetClipboardData(CF_BITMAP, hbm);
  637.                 }
  638.                 else {
  639.                     DeleteObject(hbm);
  640.                 }
  641.             }
  642.  
  643.             ReleaseDC(ghwndApp, hdcSrc);
  644.         }
  645.  
  646.         CloseClipboard();
  647.     }
  648.     else {
  649.         MessageBeep(0);
  650.     }
  651. }
  652.  
  653.  
  654.  
  655. /************************************************************************
  656. * AboutDlgProc
  657. *
  658. * This is the About Box dialog procedure.
  659. *
  660. * History:
  661. *
  662. ************************************************************************/
  663.  
  664. BOOL APIENTRY AboutDlgProc(
  665.     HWND hwnd,
  666.     UINT msg,
  667.     WPARAM wParam,
  668.     LPARAM lParam)
  669. {
  670.     switch (msg) {
  671.         case WM_INITDIALOG:
  672.             return TRUE;
  673.  
  674.         case WM_COMMAND:
  675.             EndDialog(hwnd, IDOK);
  676.             return TRUE;
  677.  
  678.         default:
  679.             return FALSE;
  680.     }
  681. }
  682.  
  683.  
  684.  
  685. /************************************************************************
  686. * RefreshRateDlgProc
  687. *
  688. * This is the Refresh Rate dialog procedure.
  689. *
  690. * History:
  691. *
  692. ************************************************************************/
  693.  
  694. BOOL APIENTRY RefreshRateDlgProc(
  695.     HWND hwnd,
  696.     UINT msg,
  697.     WPARAM wParam,
  698.     LPARAM lParam)
  699. {
  700.     BOOL fTranslated;
  701.  
  702.     switch (msg) {
  703.         case WM_INITDIALOG:
  704.             SendDlgItemMessage(hwnd, DID_REFRESHRATEINTERVAL, EM_LIMITTEXT,
  705.                     3, 0L);
  706.             SetDlgItemInt(hwnd, DID_REFRESHRATEINTERVAL, gnRefInterval, FALSE);
  707.             CheckDlgButton(hwnd, DID_REFRESHRATEENABLE, gfRefEnable ? 1 : 0);
  708.             return TRUE;
  709.  
  710.         case WM_COMMAND:
  711.             switch (LOWORD(wParam)) {
  712.                 case IDOK:
  713.                     gnRefInterval = GetDlgItemInt(hwnd, DID_REFRESHRATEINTERVAL,
  714.                             &fTranslated, FALSE);
  715.  
  716.                     /*
  717.                      * Stop any existing timers then start one with the
  718.                      * new interval if requested to.
  719.                      */
  720.                     EnableRefresh(FALSE);
  721.                     EnableRefresh(
  722.                             IsDlgButtonChecked(hwnd, DID_REFRESHRATEENABLE));
  723.  
  724.                     EndDialog(hwnd, IDOK);
  725.                     break;
  726.  
  727.                 case IDCANCEL:
  728.                     EndDialog(hwnd, IDCANCEL);
  729.                     break;
  730.             }
  731.  
  732.             break;
  733.     }
  734.  
  735.     return FALSE;
  736. }
  737.