SPINCUBE.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:20k
源码类别:

Windows编程

开发平台:

Visual C++

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