|
|
1.1 root 1:
2: /******************************************************************************\
3: * This is a part of the Microsoft Source Code Samples.
4: * Copyright (C) 1993 Microsoft Corporation.
5: * All rights reserved.
6: * This source code is only intended as a supplement to
7: * Microsoft Development Tools and/or WinHelp documentation.
8: * See these sources for detailed information regarding the
9: * Microsoft samples programs.
10: \******************************************************************************/
11:
12: /****************************** Module Header *******************************
13: * Module Name: toolbox.c
14: *
15: * Contains routines that handle the toolbox.
16: *
17: * Functions:
18: *
19: * ToolboxShow()
20: * ToolboxOnTop()
21: * ToolboxWndProc()
22: * ToolBtnWndProc()
23: * ToolboxSelectTool()
24: * ToolboxCreate()
25: * ToolboxDrawBitmap()
26: *
27: * Comments:
28: *
29: ****************************************************************************/
30:
31: #include "dlgedit.h"
32: #include "dlgfuncs.h"
33: #include "dlgextrn.h"
34:
35: #include "dialogs.h"
36:
37:
38: #define TOOLBOXMARGIN 2 // Pixels around the buttons in the Toolbox.
39: #define TOOLBOXCOLUMNS 2 // Columns in the Toolbox.
40:
41: /*
42: * Style of the toolbox window.
43: */
44: #define TOOLBOXSTYLE (WS_POPUP | WS_CLIPSIBLINGS | WS_CAPTION | WS_SYSMENU)
45:
46: STATICFN VOID ToolboxCreate(VOID);
47: STATICFN VOID ToolboxDrawBitmap(HDC hDC, INT type);
48:
49: /*
50: * Dimensions of a tool button bitmap.
51: */
52: static INT cxToolBtn;
53: static INT cyToolBtn;
54:
55:
56:
57: /****************************************************************************
58: * ToolboxShow
59: *
60: * This function shows or hides the toolbox window. It will create
61: * the Toolbox if necessary.
62: *
63: * Arguments:
64: * BOOL fShow - whether to show or hide the toolbox window.
65: *
66: ****************************************************************************/
67:
68: VOID ToolboxShow(
69: BOOL fShow)
70: {
71: if (fShow) {
72: /*
73: * Don't allow a toolbox to be shown in Translate mode.
74: */
75: if (gfTranslateMode)
76: return;
77:
78: /*
79: * Create it if it doesn't exist yet.
80: */
81: if (!ghwndToolbox)
82: ToolboxCreate();
83:
84: if (ghwndToolbox)
85: ShowWindow(ghwndToolbox, SW_SHOWNA);
86: }
87: else {
88: if (ghwndToolbox)
89: ShowWindow(ghwndToolbox, SW_HIDE);
90: }
91: }
92:
93:
94:
95: /****************************************************************************
96: * ToolboxOnTop
97: *
98: * This function positions the toolbox window on top. It needs to be
99: * called any time that a new dialog window is created to be sure the
100: * dialog does not cover the toolbox.
101: *
102: * It can be called even if the toolbox is not created yet (it will
103: * be a noop in that case).
104: *
105: ****************************************************************************/
106:
107: VOID ToolboxOnTop(VOID)
108: {
109: if (ghwndToolbox) {
110: SetWindowPos(ghwndToolbox, NULL, 0, 0, 0, 0,
111: SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
112: }
113: }
114:
115:
116:
117: /****************************************************************************
118: * ToolboxCreate
119: *
120: * This function creates the toolbox window.
121: *
122: ****************************************************************************/
123:
124: STATICFN VOID ToolboxCreate(VOID)
125: {
126: BITMAP bmp;
127: INT i;
128: INT x;
129: INT y;
130: INT cx;
131: INT cy;
132: INT cxDummy;
133: INT cyDummy;
134: RECT rc;
135: RECT rcSubClient;
136: BOOL fMaximized;
137:
138: /*
139: * Load the bitmaps.
140: */
141: if (!(ghbmPointerToolUp = LoadBitmap(ghInst,
142: MAKEINTRESOURCE(IDBM_TUPOINTR))) ||
143: !(ghbmPointerToolDown = LoadBitmap(ghInst,
144: MAKEINTRESOURCE(IDBM_TDPOINTR))))
145: return;
146:
147: for (i = 0; i < CCONTROLS; i++) {
148: if (!(awcd[i].hbmToolBtnUp = LoadBitmap(ghInst,
149: MAKEINTRESOURCE(awcd[i].idbmToolBtnUp))))
150: return;
151:
152: if (!(awcd[i].hbmToolBtnDown = LoadBitmap(ghInst,
153: MAKEINTRESOURCE(awcd[i].idbmToolBtnDown))))
154: return;
155: }
156:
157: /*
158: * Get the dimensions of the tool button bitmaps.
159: */
160: GetObject(awcd[0].hbmToolBtnUp, sizeof(BITMAP), &bmp);
161: cxToolBtn = bmp.bmWidth;
162: cyToolBtn = bmp.bmHeight;
163:
164: /*
165: * Calculate the required window size for the client area
166: * size we want. The size leaves room for a margin, and
167: * assumes that adjacent buttons overlap their borders by
168: * one pixel.
169: */
170: rc.left = 0;
171: rc.top = 0;
172: rc.right = TOOLBOXMARGIN + ((cxToolBtn - 1) * 2) + 1 + TOOLBOXMARGIN;
173: rc.bottom = TOOLBOXMARGIN + ((cyToolBtn - 1) *
174: ((CCONTROLS / 2) + 1)) + 1 + TOOLBOXMARGIN;
175: AdjustWindowRect(&rc, TOOLBOXSTYLE, FALSE);
176: cx = rc.right - rc.left;
177: cy = rc.bottom - rc.top;
178:
179: /*
180: * Get the saved position of the Toolbox. Note that we throw away
181: * the size fields, because we just calculated the required size.
182: */
183: if (!ReadWindowPos(szTBPos, &x, &y, &cxDummy, &cyDummy, &fMaximized)) {
184: /*
185: * The previous position of the Toolbox couldn't be found.
186: * Position the toolbox to the upper right corner of the
187: * "client" area of the editor, but make sure it is completely
188: * visible.
189: */
190: GetWindowRect(ghwndSubClient, &rcSubClient);
191: x = rcSubClient.right - cx - (2 * TOOLBOXMARGIN);
192: y = rcSubClient.top + (2 * TOOLBOXMARGIN);
193: SetRect(&rc, x, y, x + cx, y + cy);
194: FitRectToScreen(&rc);
195: x = rc.left;
196: y = rc.top;
197: }
198:
199: /*
200: * Create the toolbox window.
201: */
202: if (!(ghwndToolbox = CreateWindow(szToolboxClass, NULL, TOOLBOXSTYLE,
203: x, y, cx, cy, ghwndMain, NULL, ghInst, NULL)))
204: return;
205:
206: /*
207: * Create the Pointer (W_NOTHING) button.
208: */
209: CreateWindow(szToolBtnClass, NULL,
210: WS_CHILD | WS_VISIBLE,
211: TOOLBOXMARGIN, TOOLBOXMARGIN, (cxToolBtn * 2) - 1, cyToolBtn,
212: ghwndToolbox, (HMENU)W_NOTHING, ghInst, NULL);
213:
214: /*
215: * Create the other buttons.
216: */
217: x = TOOLBOXMARGIN;
218: y = TOOLBOXMARGIN + cyToolBtn - 1;
219: for (i = 0; i < CCONTROLS; i++) {
220: CreateWindow(szToolBtnClass, NULL,
221: WS_CHILD | WS_VISIBLE,
222: x, y, cxToolBtn, cyToolBtn,
223: ghwndToolbox, (HMENU)i, ghInst, NULL);
224:
225: if (x == TOOLBOXMARGIN) {
226: x += cxToolBtn - 1;
227: }
228: else {
229: x = TOOLBOXMARGIN;
230: y += cyToolBtn - 1;
231: }
232: }
233: }
234:
235:
236:
237: /****************************************************************************
238: * ToolboxWndProc
239: *
240: * This is the window procedure for the toolbox window.
241: *
242: ****************************************************************************/
243:
244: WINDOWPROC ToolboxWndProc(
245: HWND hwnd,
246: UINT msg,
247: WPARAM wParam,
248: LPARAM lParam)
249: {
250: switch (msg) {
251: case WM_CREATE:
252: {
253: HMENU hmenu = GetSystemMenu(hwnd, FALSE);
254:
255: RemoveMenu(hmenu, 7, MF_BYPOSITION); // Second separator.
256: RemoveMenu(hmenu, 5, MF_BYPOSITION); // First separator.
257:
258: RemoveMenu(hmenu, SC_RESTORE, MF_BYCOMMAND);
259: RemoveMenu(hmenu, SC_SIZE, MF_BYCOMMAND);
260: RemoveMenu(hmenu, SC_MINIMIZE, MF_BYCOMMAND);
261: RemoveMenu(hmenu, SC_MAXIMIZE, MF_BYCOMMAND);
262: RemoveMenu(hmenu, SC_TASKLIST, MF_BYCOMMAND);
263: }
264:
265: return 0;
266:
267: case WM_KEYDOWN:
268: {
269: INT iToolNext;
270:
271: switch (wParam) {
272: case VK_UP:
273: if ((GetKeyState(VK_SHIFT) & 0x8000) ||
274: (GetKeyState(VK_CONTROL) & 0x8000))
275: break;
276:
277: /*
278: * Go up a row, but don't go beyond the top.
279: */
280: iToolNext = gCurTool - TOOLBOXCOLUMNS;
281: if (iToolNext < 0)
282: iToolNext = W_NOTHING;
283:
284: ToolboxSelectTool(iToolNext, FALSE);
285:
286: break;
287:
288: case VK_DOWN:
289: if ((GetKeyState(VK_SHIFT) & 0x8000) ||
290: (GetKeyState(VK_CONTROL) & 0x8000))
291: break;
292:
293: if (gCurTool == W_NOTHING) {
294: iToolNext = 0;
295: }
296: else {
297: /*
298: * Go down a row, but don't go beyond the bottom.
299: */
300: iToolNext = gCurTool + TOOLBOXCOLUMNS;
301: if (iToolNext >= CCONTROLS)
302: break;
303: }
304:
305: ToolboxSelectTool(iToolNext, FALSE);
306:
307: break;
308:
309: case VK_LEFT:
310: if ((GetKeyState(VK_SHIFT) & 0x8000) ||
311: (GetKeyState(VK_CONTROL) & 0x8000))
312: break;
313:
314: if (gCurTool == W_NOTHING ||
315: !(gCurTool % TOOLBOXCOLUMNS))
316: break;
317:
318: /*
319: * Go left a column.
320: */
321: ToolboxSelectTool(gCurTool - 1, FALSE);
322:
323: break;
324:
325: case VK_RIGHT:
326: if ((GetKeyState(VK_SHIFT) & 0x8000) ||
327: (GetKeyState(VK_CONTROL) & 0x8000))
328: break;
329:
330: if (gCurTool == W_NOTHING ||
331: (gCurTool % TOOLBOXCOLUMNS) ==
332: TOOLBOXCOLUMNS - 1)
333: break;
334:
335: /*
336: * Go right a column.
337: */
338: ToolboxSelectTool(gCurTool + 1, FALSE);
339:
340: break;
341:
342: case VK_TAB:
343: if (GetKeyState(VK_CONTROL) & 0x8000)
344: break;
345:
346: /*
347: * Is the shift key pressed also?
348: */
349: if (GetKeyState(VK_SHIFT) & 0x8000) {
350: if (gCurTool == W_NOTHING)
351: iToolNext = CCONTROLS - 1;
352: else if (gCurTool == 0)
353: iToolNext = W_NOTHING;
354: else
355: iToolNext = gCurTool - 1;
356: }
357: else {
358: if (gCurTool == W_NOTHING)
359: iToolNext = 0;
360: else if (gCurTool == CCONTROLS - 1)
361: iToolNext = W_NOTHING;
362: else
363: iToolNext = gCurTool + 1;
364: }
365:
366: ToolboxSelectTool(iToolNext, FALSE);
367:
368: break;
369:
370: case VK_END:
371: if ((GetKeyState(VK_SHIFT) & 0x8000) ||
372: (GetKeyState(VK_CONTROL) & 0x8000))
373: break;
374:
375: ToolboxSelectTool(CCONTROLS - 1, FALSE);
376:
377: break;
378:
379: case VK_HOME:
380: case VK_ESCAPE:
381: if ((GetKeyState(VK_SHIFT) & 0x8000) ||
382: (GetKeyState(VK_CONTROL) & 0x8000))
383: break;
384:
385: ToolboxSelectTool(W_NOTHING, FALSE);
386:
387: break;
388: }
389: }
390:
391: break;
392:
393: case WM_ACTIVATE:
394: if (LOWORD(wParam))
395: gidCurrentDlg = DID_TOOLBOX;
396:
397: break;
398:
399: case WM_CLOSE:
400: /*
401: * The user closed the toolbox from the system menu.
402: * Hide the toolbox (we don't actually destroy it so
403: * that it will appear in the same spot when they show
404: * it again).
405: */
406: ToolboxShow(FALSE);
407: gfShowToolbox = FALSE;
408: break;
409:
410: case WM_DESTROY:
411: {
412: INT i;
413: RECT rc;
414:
415: DeleteObject(ghbmPointerToolUp);
416: ghbmPointerToolUp = NULL;
417: DeleteObject(ghbmPointerToolDown);
418: ghbmPointerToolDown = NULL;
419:
420: for (i = 0; i < CCONTROLS; i++) {
421: DeleteObject(awcd[i].hbmToolBtnUp);
422: awcd[i].hbmToolBtnUp = NULL;
423: DeleteObject(awcd[i].hbmToolBtnDown);
424: awcd[i].hbmToolBtnDown = NULL;
425: }
426:
427: /*
428: * Save the position of the toolbox.
429: */
430: GetWindowRect(hwnd, &rc);
431: WriteWindowPos(&rc, FALSE, szTBPos);
432:
433: /*
434: * Null out the global window handle for the toolbox
435: * for safety's sake.
436: */
437: ghwndToolbox = NULL;
438: }
439:
440: break;
441:
442: default:
443: return DefWindowProc(hwnd, msg, wParam, lParam);
444: }
445:
446: return 0;
447: }
448:
449:
450:
451: /****************************************************************************
452: * ToolBtnWndProc
453: *
454: * This is the window procedure for the buttons in the toolbox window.
455: *
456: ****************************************************************************/
457:
458: WINDOWPROC ToolBtnWndProc(
459: HWND hwnd,
460: UINT msg,
461: WPARAM wParam,
462: LPARAM lParam)
463: {
464: switch (msg) {
465: case WM_LBUTTONDOWN:
466: /*
467: * Be sure any outstanding changes get applied
468: * without errors.
469: */
470: if (!StatusApplyChanges())
471: return TRUE;
472:
473: /*
474: * Select the tool that was clicked on. If the Ctrl
475: * key is down, lock the tool also.
476: */
477: ToolboxSelectTool((UINT)GetWindowLong((hwnd), GWL_ID),
478: (GetKeyState(VK_CONTROL) & 0x8000) ? TRUE : FALSE);
479:
480: break;
481:
482: case WM_PAINT:
483: {
484: HDC hDC;
485: PAINTSTRUCT ps;
486:
487: hDC = BeginPaint(hwnd, &ps);
488: ToolboxDrawBitmap(hDC, (UINT)GetWindowLong((hwnd), GWL_ID));
489: EndPaint(hwnd, &ps);
490: }
491:
492: break;
493:
494: default:
495: return DefWindowProc(hwnd, msg, wParam, lParam);
496: }
497:
498: return 0;
499: }
500:
501:
502:
503: /****************************************************************************
504: * ToolboxDrawBitmap
505: *
506: * Draws the current tool bitmap.
507: *
508: * Arguments:
509: * HDC hDC - handle to the DC for the toolbox window.
510: * INR type - type of bitmap to draw.
511: *
512: ****************************************************************************/
513:
514: STATICFN VOID ToolboxDrawBitmap(
515: HDC hDC,
516: INT type)
517: {
518: HDC hMemDC;
519: HBITMAP hbm;
520: HBITMAP hbmOld;
521: INT cxBitmap;
522:
523: if (type == W_NOTHING) {
524: hbm = (type == gCurTool) ? ghbmPointerToolDown : ghbmPointerToolUp;
525:
526: /*
527: * Note that the size of the Pointer tool is twice the width
528: * of the other bitmaps, but less one pixel. This is because
529: * the other tools overlap their adjacent borders.
530: */
531: cxBitmap = (cxToolBtn * 2) - 1;
532: }
533: else {
534: hbm = (type == gCurTool) ?
535: awcd[type].hbmToolBtnDown : awcd[type].hbmToolBtnUp;
536: cxBitmap = cxToolBtn;
537: }
538:
539: /*
540: * Draw the image.
541: */
542: hMemDC = CreateCompatibleDC(hDC);
543: hbmOld = SelectObject(hMemDC, hbm);
544: BitBlt(hDC, 0, 0, cxBitmap, cyToolBtn, hMemDC, 0, 0, SRCCOPY);
545: SelectObject(hMemDC, hbmOld);
546: DeleteDC(hMemDC);
547: }
548:
549:
550:
551: /****************************************************************************
552: * ToolboxSelectTool
553: *
554: * This function selects a tool to be the current tool.
555: *
556: * Arguments:
557: * INT type - Type of control (one of the W_* defines).
558: * BOOL fLock - TRUE if the tool should be locked down.
559: *
560: ****************************************************************************/
561:
562: VOID ToolboxSelectTool(
563: INT type,
564: BOOL fLock)
565: {
566: PWINDOWCLASSDESC pwcd;
567:
568: if (gCurTool != type) {
569: /*
570: * Set the current wcd global for the current tool type.
571: * This will point to the WINDOWCLASSDESC structure of the
572: * current tool. If the Custom tool was selected, the user
573: * is asked which of the installed custom controls that they
574: * really want.
575: */
576: if (type == W_CUSTOM) {
577: /*
578: * There are no custom controls installed. Beep and
579: * return without doing anything.
580: */
581: if (!gpclHead) {
582: MessageBeep(0);
583: return;
584: }
585:
586: /*
587: * If there are multiple custom controls installed,
588: * ask the user which one they want. Note that they
589: * can press Cancel and return NULL!
590: */
591: if (gpclHead->pclNext) {
592: if (!(pwcd = SelCustDialog()))
593: return;
594:
595: gpwcdCurTool = pwcd;
596: }
597: else {
598: /*
599: * Since there is only one type of custom control
600: * installed, there is no need to ask the user
601: * which one they want.
602: */
603: gpwcdCurTool = gpclHead->pwcd;
604: }
605: }
606: else {
607: gpwcdCurTool = (type == W_NOTHING) ? NULL : &awcd[type];
608: }
609:
610: /*
611: * Force the previous and current buttons to repaint.
612: */
613: if (ghwndToolbox) {
614: InvalidateRect(GetDlgItem(ghwndToolbox, gCurTool), NULL, FALSE);
615: InvalidateRect(GetDlgItem(ghwndToolbox, type), NULL, FALSE);
616: }
617:
618: /*
619: * Set the current tool type global. This will be W_CUSTOM for
620: * all custom controls.
621: */
622: gCurTool = type;
623: }
624:
625: gfToolLocked = fLock;
626: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.