|
|
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: menu.c
14: *
15: * Contains the main menu switching functions and the clipboard functions.
16: *
17: * Functions:
18: * DialogMenu()
19: * LoadMenuBitmaps()
20: * FreeMenuBitmaps()
21: * InitMenu()
22: * MsgFilterHookFunc()
23: * ShowHelp()
24: * CopyToClipboard()
25: * DlgInClipboard()
26: * PasteFromClipboard()
27: * GetHelpContext()
28: *
29: * Comments:
30: *
31: ****************************************************************************/
32:
33: #include "dlgedit.h"
34: #include "dlgfuncs.h"
35: #include "dlgextrn.h"
36: #include "dialogs.h"
37:
38: #include <string.h>
39:
40:
41: #define MM10PERINCH 254 // Tenths of a millimeter per inch.
42:
43: typedef struct {
44: WORD idm;
45: INT idbm;
46: HBITMAP hbm;
47: } BITMAPMENU;
48:
49:
50: STATICFN VOID CopyToClipboard(VOID);
51: STATICFN BOOL DlgInClipboard(VOID);
52: STATICFN VOID PasteFromClipboard(VOID);
53: STATICFN INT GetHelpContext(INT idSubject, PHELPMAP phmap);
54:
55:
56: static BITMAPMENU bmpmenuTable[] = {
57: {MENU_ALIGNLEFT, IDBM_ALEFT, NULL },
58: {MENU_ALIGNVERT, IDBM_AVERT, NULL },
59: {MENU_ALIGNRIGHT, IDBM_ARIGHT, NULL },
60: {MENU_ALIGNTOP, IDBM_ATOP, NULL },
61: {MENU_ALIGNHORZ, IDBM_AHORZ, NULL },
62: {MENU_ALIGNBOTTOM, IDBM_ABOTTOM, NULL },
63: {MENU_SPACEVERT, IDBM_ASPCVERT, NULL },
64: {MENU_SPACEHORZ, IDBM_ASPCHORZ, NULL },
65: {MENU_ARRSIZEWIDTH, IDBM_ASZWIDTH, NULL },
66: {MENU_ARRSIZEHEIGHT, IDBM_ASZHGHT, NULL },
67: {MENU_ARRPUSHBOTTOM, IDBM_APBBOTTM, NULL },
68: {MENU_ARRPUSHRIGHT, IDBM_APBRIGHT, NULL }
69: };
70:
71:
72:
73: /************************************************************************
74: * DialogMenu
75: *
76: * This is the main switching function to send menu commands to the
77: * appropriate function.
78: *
79: * Arguments:
80: * INT - the menu command
81: *
82: ************************************************************************/
83:
84: VOID DialogMenu(
85: INT cmd)
86: {
87: /*
88: * Be sure any outstanding changes get applied without errors.
89: */
90: if (!StatusApplyChanges())
91: return;
92:
93: switch (cmd) {
94:
95: /*
96: * File menu ----------------------------------------------------
97: */
98:
99: case MENU_NEWRES:
100: if (DoWeSave(FILE_INCLUDE) == IDCANCEL ||
101: DoWeSave(FILE_RESOURCE) == IDCANCEL)
102: break;
103:
104: FreeInclude();
105: FreeRes();
106: AddNewDialog();
107: ShowFileStatus(TRUE);
108: break;
109:
110: case MENU_OPEN:
111: if (DoWeSave(FILE_INCLUDE) == IDCANCEL ||
112: DoWeSave(FILE_RESOURCE) == IDCANCEL)
113: break;
114:
115: Open(FILE_RESOURCE);
116:
117: break;
118:
119: case MENU_SAVE:
120: if (gfIncChged) {
121: if (!Save(FILE_NOSHOW | FILE_INCLUDE))
122: break;
123: }
124:
125: if (gfResChged)
126: Save(FILE_NOSHOW | FILE_RESOURCE);
127:
128: break;
129:
130: case MENU_SAVEAS:
131: /*
132: * Save the include file, but only if there is one.
133: */
134: if (pszIncludeFile || plInclude) {
135: if (!Save(FILE_NOSHOW | FILE_INCLUDE | FILE_SAVEAS))
136: break;
137: }
138:
139: /*
140: * Save the resource file.
141: */
142: Save(FILE_NOSHOW | FILE_RESOURCE | FILE_SAVEAS);
143:
144: break;
145:
146: case MENU_NEWCUST:
147: DlgBox(DID_NEWCUST, (WNDPROC)NewCustDlgProc);
148: break;
149:
150: case MENU_OPENCUST:
151: OpenCustomDialog();
152: break;
153:
154: case MENU_REMCUST:
155: DlgBox(DID_REMCUST, (WNDPROC)RemCustDlgProc);
156: break;
157:
158: case MENU_SETINCLUDE:
159: if (DoWeSave(FILE_INCLUDE) != IDCANCEL)
160: Open(FILE_INCLUDE);
161:
162: break;
163:
164: case MENU_EXIT:
165: PostMessage(ghwndMain, WM_CLOSE, 0, 0L);
166: break;
167:
168: /*
169: * Edit menu ----------------------------------------------------
170: */
171:
172: case MENU_RESTOREDIALOG:
173: RestoreDialog();
174: break;
175:
176: case MENU_CUT:
177: case MENU_COPY:
178: if (gfEditingDlg) {
179: /*
180: * Save current stuff in clipboard.
181: */
182: CopyToClipboard();
183:
184: /*
185: * Clear the selection if they did a "cut" instead of
186: * a "copy".
187: */
188: if (cmd == MENU_CUT)
189: DeleteControl();
190: }
191:
192: break;
193:
194: case MENU_PASTE:
195: PasteFromClipboard();
196: break;
197:
198: case MENU_DELETE:
199: DeleteControl();
200: break;
201:
202: case MENU_DUPLICATE:
203: Duplicate();
204: break;
205:
206: case MENU_SYMBOLS:
207: ViewInclude();
208: break;
209:
210: case MENU_STYLES:
211: StylesDialog();
212: break;
213:
214: case MENU_SIZETOTEXT:
215: SizeToText();
216: break;
217:
218: case MENU_NEWDIALOG:
219: AddNewDialog();
220: break;
221:
222: case MENU_SELECTDIALOG:
223: SelectDialogDialog();
224: break;
225:
226: /*
227: * Arrange menu -------------------------------------------------
228: */
229:
230: case MENU_ALIGNLEFT:
231: case MENU_ALIGNVERT:
232: case MENU_ALIGNRIGHT:
233: case MENU_ALIGNTOP:
234: case MENU_ALIGNHORZ:
235: case MENU_ALIGNBOTTOM:
236: AlignControls(cmd);
237: break;
238:
239: case MENU_SPACEVERT:
240: case MENU_SPACEHORZ:
241: ArrangeSpacing(cmd);
242: break;
243:
244: case MENU_ARRSIZEWIDTH:
245: case MENU_ARRSIZEHEIGHT:
246: ArrangeSize(cmd);
247: break;
248:
249: case MENU_ARRPUSHBOTTOM:
250: case MENU_ARRPUSHRIGHT:
251: ArrangePushButtons(cmd);
252: break;
253:
254: case MENU_ORDERGROUP:
255: OrderGroupDialog();
256: break;
257:
258: case MENU_ARRSETTINGS:
259: ArrangeSettingsDialog();
260: break;
261:
262: /*
263: * Options menu -------------------------------------------------
264: */
265:
266: case MENU_TESTMODE:
267: if (gfTestMode)
268: DestroyTestDialog();
269: else
270: CreateTestDialog();
271:
272: break;
273:
274: case MENU_HEXMODE:
275: /*
276: * Flip the flag, and update the status display so that
277: * the id value will be displayed in the new format.
278: */
279: gfHexMode = gfHexMode ? FALSE : TRUE;
280: StatusUpdate();
281: break;
282:
283: case MENU_TRANSLATE:
284: /*
285: * Flip the flag, and set the enable state of the fields
286: * in the status window. Changing the translate mode can
287: * effect whether they are allowed to change ids of controls.
288: */
289: gfTranslateMode = gfTranslateMode ? FALSE : TRUE;
290:
291: /*
292: * If they turned on Translate mode, reset the tool and
293: * hide the Toolbox. Otherwise, show the toolbox if they
294: * want it shown.
295: */
296: if (gfTranslateMode) {
297: ToolboxShow(FALSE);
298: ToolboxSelectTool(W_NOTHING, FALSE);
299: }
300: else if (gfShowToolbox) {
301: ToolboxShow(TRUE);
302: }
303:
304: StatusSetEnable();
305: break;
306:
307: case MENU_USENEWKEYWORDS:
308: /*
309: * Flip the flag.
310: */
311: gfUseNewKeywords = gfUseNewKeywords ? FALSE : TRUE;
312: break;
313:
314: case MENU_SHOWTOOLBOX:
315: /*
316: * Toggle the state of the Toolbox.
317: */
318: gfShowToolbox = gfShowToolbox ? FALSE : TRUE;
319: ToolboxShow(gfShowToolbox);
320:
321: break;
322:
323: /*
324: * Help menu ----------------------------------------------------
325: */
326:
327: case MENU_CONTENTS:
328: WinHelp(ghwndMain, gszHelpFile, HELP_CONTENTS, 0L);
329: break;
330:
331: case MENU_SEARCH:
332: /*
333: * Tell winhelp to be sure this app's help file is current,
334: * then invoke a search with an empty starting key.
335: */
336: WinHelp(ghwndMain, gszHelpFile, HELP_FORCEFILE, 0);
337: WinHelp(ghwndMain, gszHelpFile, HELP_PARTIALKEY, (DWORD)szEmpty);
338: break;
339:
340: case MENU_ABOUT:
341: DlgBox(DID_ABOUT, (WNDPROC)AboutDlgProc);
342: break;
343:
344: /*
345: * Hidden menu commands (accessed by accelerators) --------------
346: */
347:
348: case MENU_HIDDEN_TOTOOLBOX:
349: if (ghwndToolbox && IsWindowVisible(ghwndToolbox))
350: SetFocus(ghwndToolbox);
351:
352: break;
353:
354: case MENU_HIDDEN_TOPROPBAR:
355: SetFocus(hwndStatus);
356: break;
357: }
358: }
359:
360:
361:
362: /************************************************************************
363: * LoadMenuBitmaps
364: *
365: * This function loads and inserts the menu items that are bitmaps.
366: * This has to be done at runtime because windows does not have a
367: * way to specify bitmap menu items in the rc file.
368: *
369: * Arguments:
370: * HMENU hMenu - The menu handle.
371: *
372: ************************************************************************/
373:
374: VOID LoadMenuBitmaps(
375: HMENU hMenu)
376: {
377: INT i;
378:
379: for (i = 0; i < sizeof(bmpmenuTable) / sizeof(BITMAPMENU); i++) {
380: bmpmenuTable[i].hbm =
381: LoadBitmap(ghInst, MAKEINTRESOURCE(bmpmenuTable[i].idbm));
382:
383: ModifyMenu(hMenu, bmpmenuTable[i].idm,
384: MF_BYCOMMAND | MF_BITMAP, bmpmenuTable[i].idm,
385: (LPTSTR)(DWORD)bmpmenuTable[i].hbm);
386: }
387: }
388:
389:
390:
391: /************************************************************************
392: * FreeMenuBitmaps
393: *
394: * This function frees the menu bitmaps that were loaded by
395: * LoadMenuBitmaps. This function should be called only when
396: * the application is exiting, because it frees the bitmaps
397: * without removing them from the menu first.
398: *
399: ************************************************************************/
400:
401: VOID FreeMenuBitmaps(VOID)
402: {
403: INT i;
404:
405: for (i = 0; i < sizeof(bmpmenuTable) / sizeof(BITMAPMENU); i++)
406: if (bmpmenuTable[i].hbm)
407: DeleteObject(bmpmenuTable[i].hbm);
408: }
409:
410:
411:
412: /************************************************************************
413: * InitMenu
414: *
415: * This function grays/enables and checks/unchecks the menu items
416: * appropriately for the given state.
417: *
418: * Arguments:
419: * HMENU hMenu - The menu handle.
420: *
421: ************************************************************************/
422:
423: VOID InitMenu(
424: HMENU hMenu)
425: {
426: register INT i;
427: BOOL fEnable;
428: NPCTYPE npc;
429: HMENU hMenuArrange;
430:
431: MyEnableMenuItem(hMenu, MENU_NEWRES, !gfTranslateMode);
432:
433: MyEnableMenuItem(hMenu, MENU_SAVE,
434: (gfEditingDlg || gprlHead) && (gfResChged || gfIncChged));
435:
436: MyEnableMenuItem(hMenu, MENU_SAVEAS, gfEditingDlg || gprlHead);
437:
438: MyEnableMenuItem(hMenu, MENU_SETINCLUDE,
439: (gfEditingDlg || gprlHead) && !gfTranslateMode);
440:
441: MyEnableMenuItem(hMenu, MENU_REMCUST, gpclHead);
442:
443: MyEnableMenuItem(hMenu, MENU_RESTOREDIALOG, gfDlgChanged && gcd.prl);
444:
445: MyEnableMenuItem(hMenu, MENU_CUT,
446: gnpcSel && gfEditingDlg && !gfTranslateMode);
447:
448: MyEnableMenuItem(hMenu, MENU_COPY, gnpcSel && gfEditingDlg);
449:
450: MyEnableMenuItem(hMenu, MENU_PASTE, !gfTranslateMode &&
451: IsClipboardFormatAvailable(fmtDlg) &&
452: (gfEditingDlg || DlgInClipboard()));
453:
454: MyEnableMenuItem(hMenu, MENU_DELETE, gnpcSel && !gfTranslateMode);
455:
456: MyEnableMenuItem(hMenu, MENU_DUPLICATE, gnpcSel && !gfTranslateMode);
457:
458: MyEnableMenuItem(hMenu, MENU_SYMBOLS,
459: (gfEditingDlg || gprlHead) && !gfTranslateMode);
460:
461: MyEnableMenuItem(hMenu, MENU_STYLES, gnpcSel && !gfTranslateMode);
462:
463: /*
464: * For the "Size to text" menu command to be enabled, there
465: * must be at least one control selected, and one of the
466: * controls selected has to be able to be sized to its text.
467: */
468: fEnable = FALSE;
469: if (gcSelected) {
470: for (npc = npcHead; npc; npc = npc->npcNext) {
471: if (npc->fSelected && npc->pwcd->fSizeToText) {
472: fEnable = TRUE;
473: break;
474: }
475: }
476: }
477:
478: MyEnableMenuItem(hMenu, MENU_SIZETOTEXT, fEnable);
479:
480: MyEnableMenuItem(hMenu, MENU_NEWDIALOG, !gfTranslateMode);
481:
482: MyEnableMenuItem(hMenu, MENU_SELECTDIALOG, gfEditingDlg || gprlHead);
483:
484: hMenuArrange = GetSubMenu(hMenu, MENUPOS_ARRANGE);
485:
486: MyEnableMenuItemByPos(hMenuArrange, MENUPOS_ARRANGEALIGN, gcSelected > 1);
487:
488: MyEnableMenuItemByPos(hMenuArrange, MENUPOS_ARRANGESPACE, gcSelected > 1);
489:
490: /*
491: * For the "Same size" menu option to be enabled, there
492: * must be more than one control selected, and they
493: * must be sizeable controls.
494: */
495: fEnable = FALSE;
496: if (gcSelected > 1) {
497: for (i = 0, npc = npcHead; npc; npc = npc->npcNext) {
498: if (npc->fSelected && npc->pwcd->fSizeable) {
499: i++;
500:
501: if (i > 1) {
502: fEnable = TRUE;
503: break;
504: }
505: }
506: }
507: }
508:
509: MyEnableMenuItemByPos(hMenuArrange, MENUPOS_ARRANGESIZE, fEnable);
510:
511: /*
512: * For the Arrange/Push buttons menu item to be enabled,
513: * there must be a dialog up and it must have at least one
514: * push button. In addition, if there are control(s) other
515: * than the dialog selected, at least one of the selected
516: * controls must be a push button.
517: */
518: fEnable = FALSE;
519: if (gfEditingDlg || gprlHead) {
520: if (!gcSelected || gfDlgSelected) {
521: for (npc = npcHead; npc; npc = npc->npcNext) {
522: if (npc->pwcd->iType == W_PUSHBUTTON) {
523: fEnable = TRUE;
524: break;
525: }
526: }
527: }
528: else {
529: for (npc = npcHead; npc; npc = npc->npcNext) {
530: if (npc->pwcd->iType == W_PUSHBUTTON && npc->fSelected) {
531: fEnable = TRUE;
532: break;
533: }
534: }
535: }
536: }
537:
538: MyEnableMenuItemByPos(hMenuArrange, MENUPOS_ARRANGEPUSH, fEnable);
539:
540: MyEnableMenuItem(hMenu, MENU_ORDERGROUP,
541: npcHead && !gfTranslateMode && !gfTestMode && cWindows > 1);
542:
543: MyEnableMenuItem(hMenu, MENU_TESTMODE, gfEditingDlg);
544: MyCheckMenuItem(hMenu, MENU_TESTMODE, gfTestMode);
545:
546: MyEnableMenuItem(hMenu, MENU_HEXMODE, !gfTestMode);
547: MyCheckMenuItem(hMenu, MENU_HEXMODE, gfHexMode);
548:
549: MyEnableMenuItem(hMenu, MENU_TRANSLATE, !gfTestMode);
550: MyCheckMenuItem(hMenu, MENU_TRANSLATE, gfTranslateMode);
551:
552: MyEnableMenuItem(hMenu, MENU_USENEWKEYWORDS, !gfTestMode);
553: MyCheckMenuItem(hMenu, MENU_USENEWKEYWORDS, gfUseNewKeywords);
554:
555: MyEnableMenuItem(hMenu, MENU_SHOWTOOLBOX, !gfTestMode && !gfTranslateMode);
556: MyCheckMenuItem(hMenu, MENU_SHOWTOOLBOX, gfShowToolbox);
557: }
558:
559:
560:
561: /************************************************************************
562: * CopyToClipboard
563: *
564: * Puts the current dialog and a bitmap image of it into the clipboard.
565: * Gives a dialog box resource to the Clipboard.
566: * Gives a bit map to the clipboard.
567: * Clears everything else out of clipboard.
568: *
569: ************************************************************************/
570:
571: STATICFN VOID CopyToClipboard(VOID)
572: {
573: INT cbRes;
574: HANDLE hResClip;
575: PRES lpRes;
576: PRES pRes;
577: HDC hdcSrc;
578: HDC hdcDst;
579: RECT rc;
580: HBITMAP hbm;
581:
582: /*
583: * Store the current selection in a dialog resource.
584: */
585: if (!(pRes = AllocDialogResource(FALSE, TRUE)))
586: return;
587:
588: /*
589: * Allocate global memory for it.
590: */
591: cbRes = ResourceSize(pRes);
592: if (!cbRes || !(hResClip = GlobalAlloc(GHND | GMEM_DDESHARE, cbRes))) {
593: MyFree(pRes);
594: Message(MSG_OUTOFMEMORY);
595: return;
596: }
597:
598: /*
599: * Copy it to the global memory.
600: */
601: lpRes = (PRES)GlobalLock(hResClip);
602: memcpy(lpRes, pRes, cbRes);
603: GlobalUnlock(hResClip);
604: MyFree(pRes);
605:
606: /*
607: * Now place it in the clipboard.
608: */
609: if (OpenClipboard(ghwndMain)) {
610: EmptyClipboard();
611: SetClipboardData(fmtDlg, hResClip);
612:
613: /*
614: * If the dialog is selected, place a bitmap image of it
615: * in the clipboard also. The drag handles will be removed
616: * first and the dialog will be activated so that the
617: * image looks proper.
618: */
619: if (gfDlgSelected) {
620: CancelSelection(FALSE);
621: SetActiveWindow(gcd.npc->hwnd);
622: UpdateWindow(gcd.npc->hwnd);
623:
624: if (hdcSrc = GetDC(NULL)) {
625: GetWindowRect(gcd.npc->hwnd, &rc);
626: if (hbm = CreateCompatibleBitmap(hdcSrc,
627: rc.right - rc.left, rc.bottom - rc.top)) {
628: if (hdcDst = CreateCompatibleDC(hdcSrc)) {
629: /*
630: * Calculate the dimensions of the bitmap and
631: * convert them to tenths of a millimeter for
632: * setting the size with the SetBitmapDimensionEx
633: * call. This allows programs like WinWord to
634: * retrieve the bitmap and know what size to
635: * display it as.
636: */
637: SetBitmapDimensionEx(hbm,
638: ((rc.right - rc.left) * MM10PERINCH) /
639: GetDeviceCaps(hdcSrc, LOGPIXELSX),
640: ((rc.bottom - rc.top) * MM10PERINCH) /
641: GetDeviceCaps(hdcSrc, LOGPIXELSY),
642: NULL);
643:
644: SelectObject(hdcDst, hbm);
645: BitBlt(hdcDst, 0, 0,
646: rc.right - rc.left, rc.bottom - rc.top,
647: hdcSrc, rc.left, rc.top, SRCCOPY);
648: DeleteDC(hdcDst);
649: SetClipboardData(CF_BITMAP, hbm);
650: }
651: else {
652: DeleteObject(hbm);
653: }
654: }
655:
656: ReleaseDC(NULL, hdcSrc);
657: }
658:
659: SetActiveWindow(ghwndMain);
660: SelectControl(gcd.npc, FALSE);
661: }
662:
663: CloseClipboard();
664: }
665: else {
666: Message(MSG_NOCLIP);
667: }
668: }
669:
670:
671:
672: /************************************************************************
673: * DlgInClipboard
674: *
675: * This function returns TRUE if there is data in the clipboard in the
676: * dialog format, and this data is for a complete dialog, not just for
677: * a group of controls.
678: *
679: ************************************************************************/
680:
681: STATICFN BOOL DlgInClipboard(VOID)
682: {
683: HANDLE hClip;
684: PRES pRes;
685: PDIALOGBOXHEADER pdbh;
686: BOOL fDlgResFound = FALSE;
687:
688: if (!OpenClipboard(ghwndMain))
689: return FALSE;
690:
691: if (hClip = GetClipboardData(fmtDlg)) {
692: pRes = (PRES)GlobalLock(hClip);
693:
694: /*
695: * If cx is CONTROLS_ONLY, then we know that we only
696: * want to copy the controls in the template, not the
697: * entire dialog plus controls.
698: */
699: pdbh = (PDIALOGBOXHEADER)SkipResHeader(pRes);
700: if (pdbh->cx != CONTROLS_ONLY)
701: fDlgResFound = TRUE;
702:
703: GlobalUnlock(hClip);
704: }
705:
706: CloseClipboard();
707:
708: return fDlgResFound;
709: }
710:
711:
712:
713: /************************************************************************
714: * PasteFromClipboard
715: *
716: * This routine pastes any data from the clipboard into the current
717: * resource file. If the data represents a complete dialog, a new dialog
718: * is added. If it represents some controls, the operation to drop them
719: * into the current dialog is begun.
720: *
721: ************************************************************************/
722:
723: STATICFN VOID PasteFromClipboard(VOID)
724: {
725: HANDLE hClip;
726: PRES pResClip;
727: PRES pResCopy;
728: INT cbRes;
729:
730: if (!OpenClipboard(ghwndMain)) {
731: Message(MSG_NOCLIP);
732: return;
733: }
734:
735: if (hClip = GetClipboardData(fmtDlg)) {
736: pResClip = (PRES)GlobalLock(hClip);
737: cbRes = ResourceSize(pResClip);
738:
739: /*
740: * Make a copy of the clipboard data. This needs to be done
741: * because we may need to drag the new controls for a while,
742: * and it is rude to leave the clipboard open that long.
743: */
744: if (pResCopy = (PRES)MyAlloc(cbRes)) {
745: memcpy((PBYTE)pResCopy, (PBYTE)pResClip, cbRes);
746:
747: /*
748: * Now duplicate the dialog or controls in the clipboard.
749: * The pResCopy buffer does NOT need to be freed here, because
750: * it will be freed after the drag operation is complete.
751: */
752: MakeCopyFromRes(pResCopy);
753: }
754:
755: GlobalUnlock(hClip);
756: }
757:
758: CloseClipboard();
759: }
760:
761:
762:
763: /************************************************************************
764: * MsgFilterHookFunc
765: *
766: * This is the exported message filter function that is hooked into
767: * the message stream for detecting the pressing of the F1 key, at
768: * which time it calls up the appropriate help.
769: *
770: ************************************************************************/
771:
772: BOOL APIENTRY MsgFilterHookFunc(
773: INT nCode,
774: WPARAM wParam,
775: LPMSG lpMsg)
776: {
777: if ((nCode == MSGF_MENU || nCode == MSGF_DIALOGBOX) &&
778: (lpMsg->message == WM_KEYDOWN && lpMsg->wParam == VK_F1)) {
779: /*
780: * Display help.
781: */
782: ShowHelp((nCode == MSGF_MENU) ? TRUE : FALSE);
783:
784: /*
785: * Tell Windows to swallow this message.
786: */
787: return 1;
788: }
789:
790: return CallNextHookEx(ghhkMsgFilter, nCode, wParam, (LONG)lpMsg);
791: }
792:
793:
794:
795: /************************************************************************
796: * ShowHelp
797: *
798: * This function is called when the user has requested help. It will
799: * look at the menu state (if fMenuHelp is TRUE) or which dialog
800: * is currently up to determine the help topic, then it calls WinHelp.
801: *
802: * Arguments:
803: * BOOL fMenuHelp - TRUE if this help is for a menu (help was requested
804: * in the menu modal loop). If FALSE, general help
805: * or help for a dialog is assumed.
806: *
807: ************************************************************************/
808:
809: VOID ShowHelp(
810: BOOL fMenuHelp)
811: {
812: INT nHelpContext = 0;
813: HWND hwndFocus;
814:
815: if (fMenuHelp) {
816: nHelpContext = GetHelpContext(gMenuSelected, gahmapMenu);
817: }
818: else {
819: /*
820: * Look for help for the current dialog.
821: */
822: if (gidCurrentDlg) {
823: nHelpContext = GetHelpContext(gidCurrentDlg, gahmapDialog);
824: }
825: else {
826: /*
827: * There is no current dialog. Is the window with the
828: * focus a control on the Properties Bar?
829: */
830: if ((hwndFocus = GetFocus()) && IsChild(hwndStatus, hwndFocus))
831: nHelpContext = GetHelpContext(DID_STATUS, gahmapDialog);
832: }
833: }
834:
835: /*
836: * If there is help context, display it. Otherwise display
837: * the Contents screen.
838: */
839: if (nHelpContext)
840: WinHelp(ghwndMain, gszHelpFile, HELP_CONTEXT, nHelpContext);
841: else
842: WinHelp(ghwndMain, gszHelpFile, HELP_CONTENTS, 0L);
843: }
844:
845:
846:
847: /************************************************************************
848: * GetHelpContext
849: *
850: * This function takes a subject and returns its matching help
851: * context id from the given HELPMAP table.
852: *
853: * Arguments:
854: * INT idSubject - ID of the subject to find the help context for.
855: * PHELPMAP phmap - The help map table. It is assumed that the
856: * last entry in the table has a NULL subject id.
857: *
858: ************************************************************************/
859:
860: STATICFN INT GetHelpContext(
861: INT idSubject,
862: PHELPMAP phmap)
863: {
864: while (phmap->idSubject) {
865: if (phmap->idSubject == idSubject)
866: return phmap->HelpContext;
867:
868: phmap++;
869: }
870:
871: return 0;
872: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.