home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / winui / controls / spincube / spincube.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  20KB  |  717 lines

  1. /******************************************************************************\
  2. *
  3. *  MODULE:      SPINCUBE.C
  4. *
  5. *
  6. *  PURPOSE:     To provide a generic Windows NT dynamic link library
  7. *               sample demonstrating the use of DLL entry points, exported
  8. *               variables, using C runtime in a DLL, etc...
  9. *
  10. *               This module also provides a functional example of how
  11. *               to create a custom control library which may be used by
  12. *               applications (i.e. SPINTEST.EXE) and the Dialog Editor.
  13. *
  14. *
  15. *  FUNCTIONS:   DllMain()      - Registers spincube class when a
  16. *                                      process loads this DLL.
  17. *               CustomControlInfoA() - Called by DLGEDIT to initialize
  18. *                                      a CCINFO structure(s).
  19. *               SpincubeStyle()      - Brings up dialog box which allows
  20. *                                      user to modify control style.
  21. *               SpincubeSizeToText() - Called by DLGEDIT if user requests
  22. *                                      that control be sized to fit text.
  23. *               SpincubeWndProc()    - Window procedure for spincube
  24. *                                      control.
  25. *               SpincubeDlgProc()    - Procedure for control style dialog.
  26. *
  27. *
  28. *  COMMMENTS:   The dialog editor interface has changed since Win 3.0.
  29. *               Recommend browsing the NT CUSTCNTL.H file to get an
  30. *               idea of the new interface.
  31. *
  32. *
  33. *                           Microsoft Developer Support
  34. *                  Copyright (c) 1992-1997 Microsoft Corporation
  35. *
  36. \******************************************************************************/
  37.  
  38. #include <windows.h>
  39. #include <stdlib.h>
  40. #include "spincube.h"
  41.  
  42.  
  43. //
  44. // function prototype for C runtime initialization routine
  45. //
  46.  
  47. BOOL WINAPI _CRT_INIT (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved);
  48.  
  49.  
  50. //
  51. // function prototype for Paint() in PAINT.C
  52. //
  53.  
  54. void Paint (HWND);
  55.  
  56. //
  57. // function prototype for looking up string resources
  58. //
  59.  
  60. LPTSTR GetStringRes (int);
  61.  
  62.  
  63. //
  64. // Declared below are the module's 2 exported variables.
  65. //
  66. //   giNumSpincubesThisProcess is an instance variable that contains
  67. //   the number of (existing) Spincube controls created by the
  68. //   current process.
  69. //
  70. //   giNumSpincubesAllProcesses is a shared (between processes) variable
  71. //   which contains the total number of (existing) Spincube controls
  72. //   created by all processes in the system.
  73. //
  74. //
  75.  
  76. int giNumSpincubesThisProcess = 0;
  77.  
  78. #pragma data_seg(".MYSEG")
  79.  
  80.   int giNumSpincubesAllProcesses = 0;
  81.  
  82. #pragma data_seg()
  83.  
  84.  
  85. //
  86. // Some global vars for this module
  87. //
  88.  
  89. HANDLE    ghMod;   // DLL's module handle
  90. LPCCSTYLE gpccs;   // global pointer to a CCSTYLE structure
  91.  
  92. CCSTYLEFLAGA aSpincubeStyleFlags[] = { { SS_ERASE,    0, "SS_ERASE"    },
  93.                                        { SS_INMOTION, 0, "SS_INMOTION" } };
  94.  
  95.  
  96.  
  97. /******************************************************************************\
  98. *
  99. *  FUNCTION:    DllMain
  100. *
  101. *  INPUTS:      hDLL       - DLL module handle
  102. *               dwReason   - reason being called (e.g. process attaching)
  103. *               lpReserved - reserved
  104. *
  105. *  RETURNS:     TRUE if initialization passed, or
  106. *               FALSE if initialization failed.
  107. *
  108. *  COMMENTS:    On DLL_PROCESS_ATTACH registers the SPINCUBECLASS
  109. *
  110. *               DLL initialization serialization is guaranteed within a
  111. *               process (if multiple threads then DLL entry points are
  112. *               serialized), but is not guaranteed across processes.
  113. *
  114. *               When synchronization objects are created, it is necesaary
  115. *               to check the return code of GetLastError even if the create
  116. *               call succeeded. If the object existed, ERROR_ALREADY_EXISTED
  117. *               will be returned.
  118. *
  119. *               If your DLL uses any C runtime functions then you should
  120. *               always call _CRT_INIT so that the C runtime can initialize
  121. *               itself appropriately. Failure to do this may result in
  122. *               indeterminate behavior. When the DLL entry point is called
  123. *               for DLL_PROCESS_ATTACH & DLL_THREAD_ATTACH circumstances,
  124. *               _CRT_INIT should be called before any other initilization
  125. *               is performed. When the DLL entry point is called for
  126. *               DLL_PROCESS_DETACH & DLL_THREAD_DETACH circumstances,
  127. *               _CRT_INIT should be called after all cleanup has been
  128. *               performed, i.e. right before the function returns.
  129. *
  130. \******************************************************************************/
  131.  
  132. BOOL WINAPI DllMain (HANDLE hDLL, DWORD dwReason, LPVOID lpReserved)
  133. {
  134.   ghMod = hDLL;
  135.   switch (dwReason)
  136.   {
  137.     case DLL_PROCESS_ATTACH:
  138.     {
  139.       WNDCLASS wc;
  140.  
  141.       if (!_CRT_INIT (hDLL, dwReason, lpReserved))
  142.  
  143.         return FALSE;
  144.  
  145.       wc.style         = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_OWNDC |
  146.                          CS_GLOBALCLASS ;
  147.       wc.lpfnWndProc   = (WNDPROC) SpincubeWndProc;
  148.       wc.cbClsExtra    = 0;
  149.       wc.cbWndExtra    = SPINCUBE_EXTRA;
  150.       wc.hInstance     = hDLL;
  151.       wc.hIcon         = NULL;
  152.       wc.hCursor       = LoadCursor (NULL, IDC_ARROW);
  153.       wc.hbrBackground = NULL;
  154.       wc.lpszMenuName  = (LPSTR) NULL;
  155.       wc.lpszClassName = (LPSTR) SPINCUBECLASS;
  156.  
  157.       if (!RegisterClass (&wc))
  158.       {
  159.         MessageBox (NULL,
  160.                     GetStringRes (IDS_REGCLASSFAIL),
  161.                     (LPCTSTR) "SPINCUBE.DLL",
  162.                     MB_OK | MB_ICONEXCLAMATION);
  163.  
  164.         return FALSE;
  165.       }
  166.  
  167.       break;
  168.     }
  169.  
  170.  
  171.     case DLL_PROCESS_DETACH:
  172.     {
  173.  
  174.       if (!_CRT_INIT (hDLL, dwReason, lpReserved))
  175.  
  176.         return FALSE;
  177.  
  178.       if (!UnregisterClass ((LPSTR) SPINCUBECLASS, hDLL ))
  179.       {
  180.         MessageBox (NULL,
  181.                     GetStringRes (IDS_UNREGFAIL),
  182.                     (LPCTSTR) "SPINCUBE.DLL",
  183.                     MB_OK | MB_ICONEXCLAMATION);
  184.  
  185.         return FALSE;
  186.       }
  187.  
  188.       break;
  189.     }
  190.  
  191.  
  192.     default:
  193.  
  194.       if (!_CRT_INIT (hDLL, dwReason, lpReserved))
  195.  
  196.         return FALSE;
  197.  
  198.       break;
  199.   }
  200.   return TRUE;
  201. }
  202.  
  203.  
  204.  
  205. /******************************************************************************\
  206. *
  207. *  FUNCTION:    CustomControlInfoA
  208. *
  209. *  INPUTS:      acci - pointer to an array od CCINFOA structures
  210. *
  211. *  RETURNS:     Number of controls supported by this DLL
  212. *
  213. *  COMMENTS:    See CUSTCNTL.H for more info
  214. *
  215. \******************************************************************************/
  216.  
  217. UINT CALLBACK CustomControlInfoA (LPCCINFOA acci)
  218. {
  219.   //
  220.   // Dlgedit is querying the number of controls this DLL supports, so return 1.
  221.   //   Then we'll get called again with a valid "acci"
  222.   //
  223.  
  224.   if (!acci)
  225.  
  226.     return 1;
  227.  
  228.  
  229.   //
  230.   // Fill in the constant calues.
  231.   //
  232.  
  233.   acci[0].flOptions         = 0;
  234.   acci[0].cxDefault         = 40;      // default width  (dialog units)
  235.   acci[0].cyDefault         = 40;      // default height (dialog units)
  236.   acci[0].flStyleDefault    = WS_CHILD |
  237.                               WS_VISIBLE |
  238.                               SS_INMOTION;
  239.   acci[0].flExtStyleDefault = 0;
  240.   acci[0].flCtrlTypeMask    = 0;
  241.   acci[0].cStyleFlags       = NUM_SPINCUBE_STYLES;
  242.   acci[0].aStyleFlags       = aSpincubeStyleFlags;
  243.   acci[0].lpfnStyle         = SpincubeStyle;
  244.   acci[0].lpfnSizeToText    = SpincubeSizeToText;
  245.   acci[0].dwReserved1       = 0;
  246.   acci[0].dwReserved2       = 0;
  247.  
  248.  
  249.   //
  250.   // Copy the strings
  251.   //
  252.   // NOTE: MAKE SURE THE STRINGS COPIED DO NOT EXCEED THE LENGTH OF
  253.   //       THE BUFFERS IN THE CCINFO STRUCTURE!
  254.   //
  255.  
  256.   lstrcpy (acci[0].szClass, SPINCUBECLASS);
  257.   lstrcpy (acci[0].szDesc,  SPINCUBEDESCRIPTION);
  258.   lstrcpy (acci[0].szTextDefault, SPINCUBEDEFAULTTEXT);
  259.  
  260.  
  261.   //
  262.   // Return the number of controls that the DLL supports
  263.   //
  264.  
  265.   return 1;
  266. }
  267.  
  268.  
  269.  
  270. /******************************************************************************\
  271. *
  272. *  FUNCTION:    SpincubeStyle
  273. *
  274. *  INPUTS:      hWndParent - handle of parent window (dialog editor)
  275. *               pccs       - pointer to a CCSTYLE structure
  276. *
  277. *  RETURNS:     TRUE  if success,
  278. *               FALSE if error occured
  279. *
  280. *  LOCAL VARS:  rc - return code from DialogBox
  281. *
  282. \******************************************************************************/
  283.  
  284. BOOL CALLBACK SpincubeStyle (HWND hWndParent, LPCCSTYLE pccs)
  285. {
  286.   int rc;
  287.  
  288.   gpccs = pccs;
  289.  
  290.   if ((rc = DialogBox (ghMod, "SpincubeStyle", hWndParent,
  291.                        (DLGPROC)SpincubeDlgProc)) == -1)
  292.   {
  293.     MessageBox (hWndParent,
  294.                 GetStringRes (IDS_DLGBOXFAIL),
  295.                 (LPCTSTR) "Spincube.dll",
  296.                 MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL);
  297.     rc = 0;
  298.   }
  299.  
  300.   return (BOOL) rc;
  301. }
  302.  
  303.  
  304.  
  305. /******************************************************************************\
  306. *
  307. *  FUNCTION:    SpincubeSizeToText
  308. *
  309. *  INPUTS:      flStyle    - control style
  310. *               flExtStyle - control extended style
  311. *               hFont      - handle of font used to draw text
  312. *               pszText    - control text
  313. *
  314. *  RETURNS:     Width (in pixels) control must be to accomodate text, or
  315. *               -1 if an error occurs.
  316. *
  317. *  COMMENTS:    Just no-op here (since we never actually display text in
  318. *               the control it doesn't need to be resized).
  319. *
  320. \******************************************************************************/
  321.  
  322. INT CALLBACK SpincubeSizeToText (DWORD flStyle, DWORD flExtStyle,
  323.                                  HFONT hFont,   LPSTR pszText)
  324. {
  325.   return -1;
  326. }
  327.  
  328.  
  329.  
  330. /******************************************************************************\
  331. *
  332. *  FUNCTION:    SpincubeWndProc (standard window procedure INPUTS/RETURNS)
  333. *
  334. *  COMMENTS:    This is the window procedure for our custom control. At
  335. *               creation we alloc a SPINCUBEINFO struct, initialize it,
  336. *               and associate it with this particular control. We also
  337. *               start a timer which will invalidate the window every so
  338. *               often; this causes a repaint, and the cube gets drawn in
  339. *               a new position. Left button clicks will turn toggle the
  340. *               erase option, causing a "trail" of cubes to be left when
  341. *               off. Right button clicks will toggle the motion state of
  342. *               the control (and turn the timer on/off).
  343. *
  344. \******************************************************************************/
  345.  
  346. LRESULT CALLBACK SpincubeWndProc (HWND hwnd, UINT msg, WPARAM wParam,
  347.                                   LPARAM lParam)
  348. {
  349.   switch (msg)
  350.   {
  351.     case WM_CREATE:
  352.     {
  353.       //
  354.       // Alloc & init a SPINCUBEINFO struct for this particular control
  355.       //
  356.  
  357.       HDC            hdc;
  358.       LPCREATESTRUCT lpcs = (LPCREATESTRUCT) lParam;
  359.       PSPINCUBEINFO  pSCI = (PSPINCUBEINFO) LocalAlloc (LPTR,
  360.                                                         sizeof(SPINCUBEINFO));
  361.       if (!pSCI)
  362.       {
  363.         MessageBox (NULL,
  364.                     GetStringRes (IDS_ALLOCFAIL),
  365.                     (LPCTSTR) "SPINCUBE.DLL",
  366.                     MB_OK | MB_ICONEXCLAMATION);
  367.         return -1;
  368.       }
  369.  
  370.  
  371.       //
  372.       // Alloc the compatible DC for this control.
  373.       //
  374.  
  375.       hdc = GetDC (hwnd);
  376.  
  377.       if ((pSCI->hdcCompat = CreateCompatibleDC (hdc)) == NULL)
  378.       {
  379.         MessageBox (NULL,
  380.                     GetStringRes (IDS_CREATEDCFAIL),
  381.                     (LPCTSTR) "SPINCUBE.DLL",
  382.                     MB_OK | MB_ICONEXCLAMATION);
  383.         return -1;
  384.       }
  385.  
  386.       ReleaseDC (hwnd, hdc);
  387.  
  388.  
  389.       //
  390.       // Initialize this instance structure
  391.       //
  392.  
  393.       pSCI->fCurrentXRotation =
  394.       pSCI->fCurrentYRotation =
  395.       pSCI->fCurrentZRotation = (float) 0.0;
  396.  
  397.       pSCI->fCurrentXRotationInc =
  398.       pSCI->fCurrentYRotationInc =
  399.       pSCI->fCurrentZRotationInc = (float) 0.2617; // a random # (15 degrees)
  400.  
  401.       pSCI->iCurrentXTranslation =
  402.       pSCI->iCurrentYTranslation =
  403.       pSCI->iCurrentZTranslation = 0;
  404.  
  405.       //
  406.       // All these calculations so the cubes start out with random movements.
  407.       //
  408.  
  409.       if ((pSCI->iCurrentXTranslationInc = (rand() % 10) + 2) > 7)
  410.  
  411.         pSCI->iCurrentXTranslationInc = -pSCI->iCurrentXTranslationInc;
  412.  
  413.       if ((pSCI->iCurrentYTranslationInc = (rand() % 10) + 2) <= 7)
  414.  
  415.         pSCI->iCurrentYTranslationInc = -pSCI->iCurrentYTranslationInc;
  416.  
  417.       if ((pSCI->iCurrentZTranslationInc = (rand() % 10) + 2) > 7)
  418.  
  419.         pSCI->iCurrentZTranslationInc = -pSCI->iCurrentZTranslationInc;
  420.  
  421.       pSCI->rcCubeBoundary.left   =
  422.       pSCI->rcCubeBoundary.top    = 0;
  423.       pSCI->rcCubeBoundary.right  = lpcs->cx;
  424.       pSCI->rcCubeBoundary.bottom = lpcs->cy;
  425.  
  426.       pSCI->iOptions  = SPINCUBE_REPAINT_BKGND;
  427.       pSCI->hbmCompat = NULL;
  428.  
  429.       SetWindowLong (hwnd, GWL_SPINCUBEDATA, (LONG) pSCI);
  430.  
  431.       SetTimer (hwnd, SPIN_EVENT, SPIN_INTERVAL, NULL);
  432.  
  433.       //
  434.       // Increment the count vars
  435.       //
  436.  
  437.       giNumSpincubesThisProcess++;
  438.       giNumSpincubesAllProcesses++;
  439.  
  440.       break;
  441.     }
  442.  
  443.     case WM_PAINT:
  444.  
  445.       Paint (hwnd);
  446.       break;
  447.  
  448.     case WM_TIMER:
  449.  
  450.       switch (wParam)
  451.       {
  452.         case SPIN_EVENT:
  453.         {
  454.           PSPINCUBEINFO pSCI = (PSPINCUBEINFO) GetWindowLong (hwnd,
  455.                                                               GWL_SPINCUBEDATA);
  456.  
  457.           InvalidateRect (hwnd, &pSCI->rcCubeBoundary, FALSE);
  458.  
  459.           break;
  460.         }
  461.       }
  462.  
  463.       break;
  464.  
  465.     case WM_LBUTTONDBLCLK:
  466.     {
  467.       //
  468.       // Toggle the erase state of the control
  469.       //
  470.  
  471.       if (DO_ERASE(hwnd))
  472.  
  473.         SetWindowLong (hwnd, GWL_STYLE,
  474.                        GetWindowLong (hwnd, GWL_STYLE) & ~SS_ERASE);
  475.  
  476.  
  477.       else
  478.       {
  479.         //
  480.         // Repaint the entire control to get rid of the (cube trails) mess
  481.         //
  482.  
  483.         PSPINCUBEINFO pSCI = (PSPINCUBEINFO) GetWindowLong (hwnd,
  484.                                                             GWL_SPINCUBEDATA);
  485.  
  486.         SetWindowLong (hwnd, GWL_STYLE,
  487.                        GetWindowLong (hwnd, GWL_STYLE) | SS_ERASE);
  488.         pSCI->iOptions |= SPINCUBE_REPAINT_BKGND;
  489.         InvalidateRect (hwnd, NULL, FALSE);
  490.         SendMessage (hwnd, WM_PAINT, 0, 0);
  491.       }
  492.       break;
  493.     }
  494.  
  495.     case WM_RBUTTONDBLCLK:
  496.     {
  497.       //
  498.       // Toggle the motion state of the control
  499.       //
  500.  
  501.       if (IN_MOTION(hwnd))
  502.       {
  503.         KillTimer (hwnd, SPIN_EVENT);
  504.         SetWindowLong (hwnd, GWL_STYLE,
  505.                        GetWindowLong (hwnd, GWL_STYLE) & ~SS_INMOTION);
  506.       }
  507.       else
  508.       {
  509.         SetTimer (hwnd, SPIN_EVENT, SPIN_INTERVAL, NULL);
  510.         SetWindowLong (hwnd, GWL_STYLE,
  511.                        GetWindowLong (hwnd, GWL_STYLE) | SS_INMOTION);
  512.       }
  513.  
  514.       break;
  515.     }
  516.  
  517.     case WM_SIZE:
  518.  
  519.       if (wParam == SIZE_MAXIMIZED || wParam == SIZE_RESTORED)
  520.       {
  521.         PSPINCUBEINFO pSCI = (PSPINCUBEINFO) GetWindowLong (hwnd,
  522.                                                             GWL_SPINCUBEDATA);
  523.         //
  524.         // Get a new bitmap which is the new size of our window
  525.         //
  526.  
  527.         HDC hdc = GetDC (hwnd);
  528.         HBITMAP hbmTemp = CreateCompatibleBitmap (hdc,
  529.                                                   (int) LOWORD (lParam),
  530.                                                   (int) HIWORD (lParam));
  531.         if (!hbmTemp)
  532.         {
  533.           //
  534.           // Scream, yell, & committ an untimely demise...
  535.           //
  536.  
  537.           MessageBox (NULL,
  538.                       GetStringRes (IDS_CREATEBITMAPFAIL),
  539.                       (LPCTSTR) "SPINCUBE.DLL",
  540.                       MB_OK | MB_ICONEXCLAMATION);
  541.           DestroyWindow (hwnd);
  542.         }
  543.  
  544.         pSCI->hbmSave = SelectObject (pSCI->hdcCompat, hbmTemp);
  545.         if (pSCI->hbmCompat)
  546.             DeleteObject (pSCI->hbmCompat);
  547.         ReleaseDC    (hwnd, hdc);
  548.         pSCI->hbmCompat = hbmTemp;
  549.  
  550.  
  551.         //
  552.         // Reset the translation so the cube doesn't go spinning off into
  553.         //   space somewhere- we'd never see it again!
  554.         //
  555.  
  556.         pSCI->iCurrentXTranslation =
  557.         pSCI->iCurrentYTranslation =
  558.         pSCI->iCurrentZTranslation = 0;
  559.  
  560.         //
  561.         // All these calculations so the cube starts out with random movements,
  562.         //
  563.  
  564.         if ((pSCI->iCurrentXTranslationInc = (rand() % 10) + 2) > 7)
  565.  
  566.           pSCI->iCurrentXTranslationInc = -pSCI->iCurrentXTranslationInc;
  567.  
  568.         if ((pSCI->iCurrentYTranslationInc = (rand() % 10) + 2) <= 7)
  569.  
  570.           pSCI->iCurrentYTranslationInc = -pSCI->iCurrentYTranslationInc;
  571.  
  572.         if ((pSCI->iCurrentZTranslationInc = (rand() % 10) + 2) > 7)
  573.  
  574.           pSCI->iCurrentZTranslationInc = -pSCI->iCurrentZTranslationInc;
  575.  
  576.         pSCI->rcCubeBoundary.left   =
  577.         pSCI->rcCubeBoundary.top    = 0;
  578.         pSCI->rcCubeBoundary.right  = (int) LOWORD (lParam);
  579.         pSCI->rcCubeBoundary.bottom = (int) HIWORD (lParam);
  580.  
  581.         pSCI->iOptions |= SPINCUBE_REPAINT_BKGND;
  582.  
  583.         InvalidateRect (hwnd, NULL, FALSE);
  584.       }
  585.  
  586.       break;
  587.  
  588.     case WM_DESTROY:
  589.     {
  590.       PSPINCUBEINFO pSCI = (PSPINCUBEINFO) GetWindowLong (hwnd,
  591.                                                           GWL_SPINCUBEDATA);
  592.       //
  593.       // Clean up all the resources used for this control
  594.       //
  595.  
  596.       if (IN_MOTION(hwnd))
  597.  
  598.         KillTimer (hwnd, SPIN_EVENT);
  599.  
  600.       SelectObject (pSCI->hdcCompat, pSCI->hbmSave);
  601.       DeleteObject (pSCI->hbmCompat);
  602.       DeleteDC     (pSCI->hdcCompat);
  603.  
  604.       LocalFree (LocalHandle ((LPVOID) pSCI));
  605.  
  606.  
  607.       //
  608.       // Decrement the global count vars
  609.       //
  610.  
  611.       giNumSpincubesThisProcess--;
  612.       giNumSpincubesAllProcesses--;
  613.  
  614.       break;
  615.     }
  616.  
  617.     default:
  618.  
  619.       return (DefWindowProc(hwnd, msg, wParam, lParam));
  620.   }
  621.  
  622.   return ((LONG) TRUE);
  623. }
  624.  
  625.  
  626.  
  627. /******************************************************************************\
  628. *
  629. *  FUNCTION:    SpincubeDlgProc (standard dialog procedure INPUTS/RETURNS)
  630. *
  631. *  COMMENTS:    This dialog comes up in response to a user requesting to
  632. *               modify the control style. This sample allows for changing
  633. *               the control's text, and this is done by modifying the
  634. *               CCSTYLE structure pointed at by "gpccs" (a pointer
  635. *               that was passed to us by dlgedit).
  636. *
  637. \******************************************************************************/
  638.  
  639. LRESULT CALLBACK SpincubeDlgProc (HWND hDlg, UINT msg, WPARAM wParam,
  640.                                   LPARAM lParam)
  641. {
  642.   switch (msg)
  643.   {
  644.     case WM_INITDIALOG :
  645.     {
  646.       if (gpccs->flStyle & SS_ERASE)
  647.  
  648.         CheckDlgButton (hDlg, DID_ERASE, 1);
  649.  
  650.       if (gpccs->flStyle & SS_INMOTION)
  651.  
  652.         CheckDlgButton (hDlg, DID_INMOTION, 1);
  653.  
  654.       break;
  655.     }
  656.  
  657.     case WM_COMMAND:
  658.  
  659.       switch (LOWORD(wParam))
  660.       {
  661.         case DID_ERASE:
  662.  
  663.           if (IsDlgButtonChecked (hDlg, DID_ERASE))
  664.  
  665.             gpccs->flStyle |= SS_ERASE;
  666.  
  667.           else
  668.  
  669.             gpccs->flStyle &= ~SS_ERASE;
  670.  
  671.           break;
  672.  
  673.         case DID_INMOTION:
  674.  
  675.           if (IsDlgButtonChecked (hDlg, DID_INMOTION))
  676.  
  677.             gpccs->flStyle |= SS_INMOTION;
  678.  
  679.           else
  680.  
  681.             gpccs->flStyle &= ~SS_INMOTION;
  682.  
  683.           break;
  684.  
  685.         case DID_OK:
  686.  
  687.           EndDialog  (hDlg, 1);
  688.           break;
  689.       }
  690.       break;
  691.   }
  692.   return FALSE;
  693. }
  694.  
  695.  
  696.  
  697.  
  698.  
  699. /******************************************************************************\
  700. *
  701. *  FUNCTION:    GetStringRes (int id INPUT ONLY)
  702. *
  703. *  COMMENTS:    Load the resource string with the ID given, and return a
  704. *               pointer to it.  Notice that the buffer is common memory so
  705. *               the string must be used before this call is made a second time.
  706. *
  707. \******************************************************************************/
  708.  
  709. LPTSTR   GetStringRes (int id)
  710. {
  711.   static TCHAR buffer[MAX_PATH];
  712.  
  713.   buffer[0]=0;
  714.   LoadString (GetModuleHandle (NULL), id, buffer, MAX_PATH);
  715.   return buffer;
  716. }
  717.