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