mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
885 lines
24 KiB
885 lines
24 KiB
/****************************************************************************/
|
|
/* */
|
|
/* Microsoft Confidential */
|
|
/* */
|
|
/* Copyright (c) Microsoft Corp. 1987, 1990 */
|
|
/* All Rights Reserved */
|
|
/* */
|
|
/****************************************************************************/
|
|
/****************************** Module Header *******************************
|
|
* Module Name: menu.c
|
|
*
|
|
* Contains the main menu switching functions.
|
|
* Also has the clipboard functions.
|
|
*
|
|
* History:
|
|
*
|
|
****************************************************************************/
|
|
|
|
#include "dlgedit.h"
|
|
#include "dlgfuncs.h"
|
|
#include "dlgextrn.h"
|
|
#include "dialogs.h"
|
|
|
|
#include <string.h>
|
|
|
|
|
|
#define MM10PERINCH 254 // Tenths of a millimeter per inch.
|
|
|
|
typedef struct {
|
|
WORD idm;
|
|
INT idbm;
|
|
HBITMAP hbm;
|
|
} BITMAPMENU;
|
|
|
|
|
|
STATICFN VOID CopyToClipboard(VOID);
|
|
STATICFN BOOL DlgInClipboard(VOID);
|
|
STATICFN VOID PasteFromClipboard(VOID);
|
|
STATICFN INT GetHelpContext(INT idSubject, PHELPMAP phmap);
|
|
|
|
|
|
static BITMAPMENU bmpmenuTable[] = {
|
|
{MENU_ALIGNLEFT, IDBM_ALEFT, NULL },
|
|
{MENU_ALIGNVERT, IDBM_AVERT, NULL },
|
|
{MENU_ALIGNRIGHT, IDBM_ARIGHT, NULL },
|
|
{MENU_ALIGNTOP, IDBM_ATOP, NULL },
|
|
{MENU_ALIGNHORZ, IDBM_AHORZ, NULL },
|
|
{MENU_ALIGNBOTTOM, IDBM_ABOTTOM, NULL },
|
|
{MENU_SPACEVERT, IDBM_ASPCVERT, NULL },
|
|
{MENU_SPACEHORZ, IDBM_ASPCHORZ, NULL },
|
|
{MENU_ARRSIZEWIDTH, IDBM_ASZWIDTH, NULL },
|
|
{MENU_ARRSIZEHEIGHT, IDBM_ASZHGHT, NULL },
|
|
{MENU_ARRPUSHBOTTOM, IDBM_APBBOTTM, NULL },
|
|
{MENU_ARRPUSHRIGHT, IDBM_APBRIGHT, NULL }
|
|
};
|
|
|
|
|
|
|
|
/************************************************************************
|
|
* DialogMenu
|
|
*
|
|
* This is the main switching function to send menu commands to the
|
|
* appropriate function.
|
|
*
|
|
* Side Effects:
|
|
* Being a major switching function, it basically alters anything
|
|
* and everything indirectly.
|
|
*
|
|
* History:
|
|
*
|
|
************************************************************************/
|
|
|
|
VOID DialogMenu(
|
|
INT cmd)
|
|
{
|
|
/*
|
|
* Be sure any outstanding changes get applied without errors.
|
|
*/
|
|
if (!StatusApplyChanges())
|
|
return;
|
|
|
|
switch (cmd) {
|
|
|
|
/*
|
|
* File menu ----------------------------------------------------
|
|
*/
|
|
|
|
case MENU_NEWRES:
|
|
if (DoWeSave(FILE_INCLUDE) == IDCANCEL ||
|
|
DoWeSave(FILE_RESOURCE) == IDCANCEL)
|
|
break;
|
|
|
|
FreeInclude();
|
|
FreeRes();
|
|
AddNewDialog();
|
|
ShowFileStatus(TRUE);
|
|
break;
|
|
|
|
case MENU_OPEN:
|
|
if (DoWeSave(FILE_INCLUDE) == IDCANCEL ||
|
|
DoWeSave(FILE_RESOURCE) == IDCANCEL)
|
|
break;
|
|
|
|
Open(FILE_RESOURCE);
|
|
|
|
break;
|
|
|
|
case MENU_SAVE:
|
|
if (gfIncChged) {
|
|
if (!Save(FILE_NOSHOW | FILE_INCLUDE))
|
|
break;
|
|
}
|
|
|
|
if (gfResChged)
|
|
Save(FILE_NOSHOW | FILE_RESOURCE);
|
|
|
|
break;
|
|
|
|
case MENU_SAVEAS:
|
|
/*
|
|
* Save the include file, but only if there is one.
|
|
*/
|
|
if (pszIncludeFile || plInclude) {
|
|
if (!Save(FILE_NOSHOW | FILE_INCLUDE | FILE_SAVEAS))
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* Save the resource file.
|
|
*/
|
|
Save(FILE_NOSHOW | FILE_RESOURCE | FILE_SAVEAS);
|
|
|
|
break;
|
|
|
|
case MENU_NEWCUST:
|
|
DlgBox(DID_NEWCUST, (WNDPROC)NewCustDlgProc);
|
|
break;
|
|
|
|
case MENU_OPENCUST:
|
|
OpenCustomDialog();
|
|
break;
|
|
|
|
case MENU_REMCUST:
|
|
DlgBox(DID_REMCUST, (WNDPROC)RemCustDlgProc);
|
|
break;
|
|
|
|
case MENU_SETINCLUDE:
|
|
if (DoWeSave(FILE_INCLUDE) != IDCANCEL)
|
|
Open(FILE_INCLUDE);
|
|
|
|
break;
|
|
|
|
case MENU_EXIT:
|
|
PostMessage(ghwndMain, WM_CLOSE, 0, 0L);
|
|
break;
|
|
|
|
/*
|
|
* Edit menu ----------------------------------------------------
|
|
*/
|
|
|
|
case MENU_RESTOREDIALOG:
|
|
RestoreDialog();
|
|
break;
|
|
|
|
case MENU_CUT:
|
|
case MENU_COPY:
|
|
if (gfEditingDlg) {
|
|
/*
|
|
* Save current stuff in clipboard.
|
|
*/
|
|
CopyToClipboard();
|
|
|
|
/*
|
|
* Clear the selection if they did a "cut" instead of
|
|
* a "copy".
|
|
*/
|
|
if (cmd == MENU_CUT)
|
|
DeleteControl();
|
|
}
|
|
|
|
break;
|
|
|
|
case MENU_PASTE:
|
|
PasteFromClipboard();
|
|
break;
|
|
|
|
case MENU_DELETE:
|
|
DeleteControl();
|
|
break;
|
|
|
|
case MENU_DUPLICATE:
|
|
Duplicate();
|
|
break;
|
|
|
|
case MENU_SYMBOLS:
|
|
ViewInclude();
|
|
break;
|
|
|
|
case MENU_STYLES:
|
|
StylesDialog();
|
|
break;
|
|
|
|
case MENU_SIZETOTEXT:
|
|
SizeToText();
|
|
break;
|
|
|
|
case MENU_NEWDIALOG:
|
|
AddNewDialog();
|
|
break;
|
|
|
|
case MENU_SELECTDIALOG:
|
|
SelectDialogDialog();
|
|
break;
|
|
|
|
/*
|
|
* Arrange menu -------------------------------------------------
|
|
*/
|
|
|
|
case MENU_ALIGNLEFT:
|
|
case MENU_ALIGNVERT:
|
|
case MENU_ALIGNRIGHT:
|
|
case MENU_ALIGNTOP:
|
|
case MENU_ALIGNHORZ:
|
|
case MENU_ALIGNBOTTOM:
|
|
AlignControls(cmd);
|
|
break;
|
|
|
|
case MENU_SPACEVERT:
|
|
case MENU_SPACEHORZ:
|
|
ArrangeSpacing(cmd);
|
|
break;
|
|
|
|
case MENU_ARRSIZEWIDTH:
|
|
case MENU_ARRSIZEHEIGHT:
|
|
ArrangeSize(cmd);
|
|
break;
|
|
|
|
case MENU_ARRPUSHBOTTOM:
|
|
case MENU_ARRPUSHRIGHT:
|
|
ArrangePushButtons(cmd);
|
|
break;
|
|
|
|
case MENU_ORDERGROUP:
|
|
OrderGroupDialog();
|
|
break;
|
|
|
|
case MENU_ARRSETTINGS:
|
|
ArrangeSettingsDialog();
|
|
break;
|
|
|
|
/*
|
|
* Options menu -------------------------------------------------
|
|
*/
|
|
|
|
case MENU_TESTMODE:
|
|
if (gfTestMode)
|
|
DestroyTestDialog();
|
|
else
|
|
CreateTestDialog();
|
|
|
|
break;
|
|
|
|
case MENU_HEXMODE:
|
|
/*
|
|
* Flip the flag, and update the status display so that
|
|
* the id value will be displayed in the new format.
|
|
*/
|
|
gfHexMode = gfHexMode ? FALSE : TRUE;
|
|
StatusUpdate();
|
|
break;
|
|
|
|
case MENU_TRANSLATE:
|
|
/*
|
|
* Flip the flag, and set the enable state of the fields
|
|
* in the status window. Changing the translate mode can
|
|
* effect whether they are allowed to change ids of controls.
|
|
*/
|
|
gfTranslateMode = gfTranslateMode ? FALSE : TRUE;
|
|
|
|
/*
|
|
* If they turned on Translate mode, reset the tool and
|
|
* hide the Toolbox. Otherwise, show the toolbox if they
|
|
* want it shown.
|
|
*/
|
|
if (gfTranslateMode) {
|
|
ToolboxShow(FALSE);
|
|
ToolboxSelectTool(W_NOTHING, FALSE);
|
|
}
|
|
else if (gfShowToolbox) {
|
|
ToolboxShow(TRUE);
|
|
}
|
|
|
|
StatusSetEnable();
|
|
break;
|
|
|
|
case MENU_USENEWKEYWORDS:
|
|
/*
|
|
* Flip the flag.
|
|
*/
|
|
gfUseNewKeywords = gfUseNewKeywords ? FALSE : TRUE;
|
|
break;
|
|
|
|
case MENU_SHOWTOOLBOX:
|
|
/*
|
|
* Toggle the state of the Toolbox.
|
|
*/
|
|
gfShowToolbox = gfShowToolbox ? FALSE : TRUE;
|
|
ToolboxShow(gfShowToolbox);
|
|
|
|
break;
|
|
|
|
/*
|
|
* Help menu ----------------------------------------------------
|
|
*/
|
|
|
|
case MENU_CONTENTS:
|
|
WinHelp(ghwndMain, gszHelpFile, HELP_CONTENTS, 0L);
|
|
break;
|
|
|
|
case MENU_SEARCH:
|
|
/*
|
|
* Tell winhelp to be sure this app's help file is current,
|
|
* then invoke a search with an empty starting key.
|
|
*/
|
|
WinHelp(ghwndMain, gszHelpFile, HELP_FORCEFILE, 0);
|
|
WinHelp(ghwndMain, gszHelpFile, HELP_PARTIALKEY, (DWORD)szEmpty);
|
|
break;
|
|
|
|
case MENU_ABOUT:
|
|
DlgBox(DID_ABOUT, (WNDPROC)AboutDlgProc);
|
|
break;
|
|
|
|
/*
|
|
* Hidden menu commands (accessed by accelerators) --------------
|
|
*/
|
|
|
|
case MENU_HIDDEN_TOTOOLBOX:
|
|
if (ghwndToolbox && IsWindowVisible(ghwndToolbox))
|
|
SetFocus(ghwndToolbox);
|
|
|
|
break;
|
|
|
|
case MENU_HIDDEN_TOPROPBAR:
|
|
SetFocus(hwndStatus);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
* LoadMenuBitmaps
|
|
*
|
|
* This function loads and inserts the menu items that are bitmaps.
|
|
* This has to be done at runtime because windows does not have a
|
|
* way to specify bitmap menu items in the rc file.
|
|
*
|
|
* Arguments:
|
|
* HMENU hMenu - The menu handle.
|
|
*
|
|
* History:
|
|
*
|
|
************************************************************************/
|
|
|
|
VOID LoadMenuBitmaps(
|
|
HMENU hMenu)
|
|
{
|
|
INT i;
|
|
|
|
for (i = 0; i < sizeof(bmpmenuTable) / sizeof(BITMAPMENU); i++) {
|
|
bmpmenuTable[i].hbm =
|
|
LoadBitmap(ghInst, MAKEINTRESOURCE(bmpmenuTable[i].idbm));
|
|
|
|
ModifyMenu(hMenu, bmpmenuTable[i].idm,
|
|
MF_BYCOMMAND | MF_BITMAP, bmpmenuTable[i].idm,
|
|
(LPTSTR)(DWORD)bmpmenuTable[i].hbm);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
* FreeMenuBitmaps
|
|
*
|
|
* This function frees the menu bitmaps that were loaded by
|
|
* LoadMenuBitmaps. This function should be called only when
|
|
* the application is exiting, because it frees the bitmaps
|
|
* without removing them from the menu first.
|
|
*
|
|
* History:
|
|
*
|
|
************************************************************************/
|
|
|
|
VOID FreeMenuBitmaps(VOID)
|
|
{
|
|
INT i;
|
|
|
|
for (i = 0; i < sizeof(bmpmenuTable) / sizeof(BITMAPMENU); i++)
|
|
if (bmpmenuTable[i].hbm)
|
|
DeleteObject(bmpmenuTable[i].hbm);
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
* InitMenu
|
|
*
|
|
* This function grays/enables and checks/unchecks the menu items
|
|
* appropriately for the given state.
|
|
*
|
|
* Arguments:
|
|
* HMENU hMenu - The menu handle.
|
|
*
|
|
* History:
|
|
*
|
|
************************************************************************/
|
|
|
|
VOID InitMenu(
|
|
HMENU hMenu)
|
|
{
|
|
register INT i;
|
|
BOOL fEnable;
|
|
NPCTYPE npc;
|
|
HMENU hMenuArrange;
|
|
|
|
MyEnableMenuItem(hMenu, MENU_NEWRES, !gfTranslateMode);
|
|
|
|
MyEnableMenuItem(hMenu, MENU_SAVE,
|
|
(gfEditingDlg || gprlHead) && (gfResChged || gfIncChged));
|
|
|
|
MyEnableMenuItem(hMenu, MENU_SAVEAS, gfEditingDlg || gprlHead);
|
|
|
|
MyEnableMenuItem(hMenu, MENU_SETINCLUDE,
|
|
(gfEditingDlg || gprlHead) && !gfTranslateMode);
|
|
|
|
MyEnableMenuItem(hMenu, MENU_REMCUST, gpclHead);
|
|
|
|
MyEnableMenuItem(hMenu, MENU_RESTOREDIALOG, gfDlgChanged && gcd.prl);
|
|
|
|
MyEnableMenuItem(hMenu, MENU_CUT,
|
|
gnpcSel && gfEditingDlg && !gfTranslateMode);
|
|
|
|
MyEnableMenuItem(hMenu, MENU_COPY, gnpcSel && gfEditingDlg);
|
|
|
|
MyEnableMenuItem(hMenu, MENU_PASTE, !gfTranslateMode &&
|
|
IsClipboardFormatAvailable(fmtDlg) &&
|
|
(gfEditingDlg || DlgInClipboard()));
|
|
|
|
MyEnableMenuItem(hMenu, MENU_DELETE, gnpcSel && !gfTranslateMode);
|
|
|
|
MyEnableMenuItem(hMenu, MENU_DUPLICATE, gnpcSel && !gfTranslateMode);
|
|
|
|
MyEnableMenuItem(hMenu, MENU_SYMBOLS,
|
|
(gfEditingDlg || gprlHead) && !gfTranslateMode);
|
|
|
|
MyEnableMenuItem(hMenu, MENU_STYLES, gnpcSel && !gfTranslateMode);
|
|
|
|
/*
|
|
* For the "Size to text" menu command to be enabled, there
|
|
* must be at least one control selected, and one of the
|
|
* controls selected has to be able to be sized to its text.
|
|
*/
|
|
fEnable = FALSE;
|
|
if (gcSelected) {
|
|
for (npc = npcHead; npc; npc = npc->npcNext) {
|
|
if (npc->fSelected && npc->pwcd->fSizeToText) {
|
|
fEnable = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
MyEnableMenuItem(hMenu, MENU_SIZETOTEXT, fEnable);
|
|
|
|
MyEnableMenuItem(hMenu, MENU_NEWDIALOG, !gfTranslateMode);
|
|
|
|
MyEnableMenuItem(hMenu, MENU_SELECTDIALOG, gfEditingDlg || gprlHead);
|
|
|
|
hMenuArrange = GetSubMenu(hMenu, MENUPOS_ARRANGE);
|
|
|
|
MyEnableMenuItemByPos(hMenuArrange, MENUPOS_ARRANGEALIGN, gcSelected > 1);
|
|
|
|
MyEnableMenuItemByPos(hMenuArrange, MENUPOS_ARRANGESPACE, gcSelected > 1);
|
|
|
|
/*
|
|
* For the "Same size" menu option to be enabled, there
|
|
* must be more than one control selected, and they
|
|
* must be sizeable controls.
|
|
*/
|
|
fEnable = FALSE;
|
|
if (gcSelected > 1) {
|
|
for (i = 0, npc = npcHead; npc; npc = npc->npcNext) {
|
|
if (npc->fSelected && npc->pwcd->fSizeable) {
|
|
i++;
|
|
|
|
if (i > 1) {
|
|
fEnable = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
MyEnableMenuItemByPos(hMenuArrange, MENUPOS_ARRANGESIZE, fEnable);
|
|
|
|
/*
|
|
* For the Arrange/Push buttons menu item to be enabled,
|
|
* there must be a dialog up and it must have at least one
|
|
* push button. In addition, if there are control(s) other
|
|
* than the dialog selected, at least one of the selected
|
|
* controls must be a push button.
|
|
*/
|
|
fEnable = FALSE;
|
|
if (gfEditingDlg || gprlHead) {
|
|
if (!gcSelected || gfDlgSelected) {
|
|
for (npc = npcHead; npc; npc = npc->npcNext) {
|
|
if (npc->pwcd->iType == W_PUSHBUTTON) {
|
|
fEnable = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
for (npc = npcHead; npc; npc = npc->npcNext) {
|
|
if (npc->pwcd->iType == W_PUSHBUTTON && npc->fSelected) {
|
|
fEnable = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
MyEnableMenuItemByPos(hMenuArrange, MENUPOS_ARRANGEPUSH, fEnable);
|
|
|
|
MyEnableMenuItem(hMenu, MENU_ORDERGROUP,
|
|
npcHead && !gfTranslateMode && !gfTestMode && cWindows > 1);
|
|
|
|
MyEnableMenuItem(hMenu, MENU_TESTMODE, gfEditingDlg);
|
|
MyCheckMenuItem(hMenu, MENU_TESTMODE, gfTestMode);
|
|
|
|
MyEnableMenuItem(hMenu, MENU_HEXMODE, !gfTestMode);
|
|
MyCheckMenuItem(hMenu, MENU_HEXMODE, gfHexMode);
|
|
|
|
MyEnableMenuItem(hMenu, MENU_TRANSLATE, !gfTestMode);
|
|
MyCheckMenuItem(hMenu, MENU_TRANSLATE, gfTranslateMode);
|
|
|
|
MyEnableMenuItem(hMenu, MENU_USENEWKEYWORDS, !gfTestMode);
|
|
MyCheckMenuItem(hMenu, MENU_USENEWKEYWORDS, gfUseNewKeywords);
|
|
|
|
MyEnableMenuItem(hMenu, MENU_SHOWTOOLBOX, !gfTestMode && !gfTranslateMode);
|
|
MyCheckMenuItem(hMenu, MENU_SHOWTOOLBOX, gfShowToolbox);
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
* CopyToClipboard
|
|
*
|
|
* Puts the current dialog and a bitmap image of it into the clipboard.
|
|
*
|
|
* Side Effects:
|
|
* Gives a dialog box resource to the Clipboard.
|
|
* Gives a bit map to the clipboard.
|
|
* Clears everything else out of clipboard.
|
|
*
|
|
* History:
|
|
*
|
|
************************************************************************/
|
|
|
|
STATICFN VOID CopyToClipboard(VOID)
|
|
{
|
|
INT cbRes;
|
|
HANDLE hResClip;
|
|
PRES lpRes;
|
|
PRES pRes;
|
|
HDC hdcSrc;
|
|
HDC hdcDst;
|
|
RECT rc;
|
|
HBITMAP hbm;
|
|
|
|
/*
|
|
* Store the current selection in a dialog resource.
|
|
*/
|
|
if (!(pRes = AllocDialogResource(FALSE, TRUE)))
|
|
return;
|
|
|
|
/*
|
|
* Allocate global memory for it.
|
|
*/
|
|
cbRes = ResourceSize(pRes);
|
|
if (!cbRes || !(hResClip = GlobalAlloc(GHND | GMEM_DDESHARE, cbRes))) {
|
|
MyFree(pRes);
|
|
Message(MSG_OUTOFMEMORY);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Copy it to the global memory.
|
|
*/
|
|
lpRes = (PRES)GlobalLock(hResClip);
|
|
memcpy(lpRes, pRes, cbRes);
|
|
GlobalUnlock(hResClip);
|
|
MyFree(pRes);
|
|
|
|
/*
|
|
* Now place it in the clipboard.
|
|
*/
|
|
if (OpenClipboard(ghwndMain)) {
|
|
EmptyClipboard();
|
|
SetClipboardData(fmtDlg, hResClip);
|
|
|
|
/*
|
|
* If the dialog is selected, place a bitmap image of it
|
|
* in the clipboard also. The drag handles will be removed
|
|
* first and the dialog will be activated so that the
|
|
* image looks proper.
|
|
*/
|
|
if (gfDlgSelected) {
|
|
CancelSelection(FALSE);
|
|
SetActiveWindow(gcd.npc->hwnd);
|
|
UpdateWindow(gcd.npc->hwnd);
|
|
|
|
if (hdcSrc = GetDC(NULL)) {
|
|
GetWindowRect(gcd.npc->hwnd, &rc);
|
|
if (hbm = CreateCompatibleBitmap(hdcSrc,
|
|
rc.right - rc.left, rc.bottom - rc.top)) {
|
|
if (hdcDst = CreateCompatibleDC(hdcSrc)) {
|
|
/*
|
|
* Calculate the dimensions of the bitmap and
|
|
* convert them to tenths of a millimeter for
|
|
* setting the size with the SetBitmapDimensionEx
|
|
* call. This allows programs like WinWord to
|
|
* retrieve the bitmap and know what size to
|
|
* display it as.
|
|
*/
|
|
SetBitmapDimensionEx(hbm,
|
|
((rc.right - rc.left) * MM10PERINCH) /
|
|
GetDeviceCaps(hdcSrc, LOGPIXELSX),
|
|
((rc.bottom - rc.top) * MM10PERINCH) /
|
|
GetDeviceCaps(hdcSrc, LOGPIXELSY),
|
|
NULL);
|
|
|
|
SelectObject(hdcDst, hbm);
|
|
BitBlt(hdcDst, 0, 0,
|
|
rc.right - rc.left, rc.bottom - rc.top,
|
|
hdcSrc, rc.left, rc.top, SRCCOPY);
|
|
DeleteDC(hdcDst);
|
|
SetClipboardData(CF_BITMAP, hbm);
|
|
}
|
|
else {
|
|
DeleteObject(hbm);
|
|
}
|
|
}
|
|
|
|
ReleaseDC(NULL, hdcSrc);
|
|
}
|
|
|
|
SetActiveWindow(ghwndMain);
|
|
SelectControl(gcd.npc, FALSE);
|
|
}
|
|
|
|
CloseClipboard();
|
|
}
|
|
else {
|
|
Message(MSG_NOCLIP);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
* DlgInClipboard
|
|
*
|
|
* This function returns TRUE if there is data in the clipboard in the
|
|
* dialog format, and this data is for a complete dialog, not just for
|
|
* a group of controls.
|
|
*
|
|
* History:
|
|
*
|
|
************************************************************************/
|
|
|
|
STATICFN BOOL DlgInClipboard(VOID)
|
|
{
|
|
HANDLE hClip;
|
|
PRES pRes;
|
|
PDIALOGBOXHEADER pdbh;
|
|
BOOL fDlgResFound = FALSE;
|
|
|
|
if (!OpenClipboard(ghwndMain))
|
|
return FALSE;
|
|
|
|
if (hClip = GetClipboardData(fmtDlg)) {
|
|
pRes = (PRES)GlobalLock(hClip);
|
|
|
|
/*
|
|
* If cx is CONTROLS_ONLY, then we know that we only
|
|
* want to copy the controls in the template, not the
|
|
* entire dialog plus controls.
|
|
*/
|
|
pdbh = (PDIALOGBOXHEADER)SkipResHeader(pRes);
|
|
if (pdbh->cx != CONTROLS_ONLY)
|
|
fDlgResFound = TRUE;
|
|
|
|
GlobalUnlock(hClip);
|
|
}
|
|
|
|
CloseClipboard();
|
|
|
|
return fDlgResFound;
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
* PasteFromClipboard
|
|
*
|
|
* This routine pastes any data from the clipboard into the current
|
|
* resource file. If the data represents a complete dialog, a new dialog
|
|
* is added. If it represents some controls, the operation to drop them
|
|
* into the current dialog is begun.
|
|
*
|
|
* History:
|
|
*
|
|
************************************************************************/
|
|
|
|
STATICFN VOID PasteFromClipboard(VOID)
|
|
{
|
|
HANDLE hClip;
|
|
PRES pResClip;
|
|
PRES pResCopy;
|
|
INT cbRes;
|
|
|
|
if (!OpenClipboard(ghwndMain)) {
|
|
Message(MSG_NOCLIP);
|
|
return;
|
|
}
|
|
|
|
if (hClip = GetClipboardData(fmtDlg)) {
|
|
pResClip = (PRES)GlobalLock(hClip);
|
|
cbRes = ResourceSize(pResClip);
|
|
|
|
/*
|
|
* Make a copy of the clipboard data. This needs to be done
|
|
* because we may need to drag the new controls for a while,
|
|
* and it is rude to leave the clipboard open that long.
|
|
*/
|
|
if (pResCopy = (PRES)MyAlloc(cbRes)) {
|
|
memcpy((PBYTE)pResCopy, (PBYTE)pResClip, cbRes);
|
|
|
|
/*
|
|
* Now duplicate the dialog or controls in the clipboard.
|
|
* The pResCopy buffer does NOT need to be freed here, because
|
|
* it will be freed after the drag operation is complete.
|
|
*/
|
|
MakeCopyFromRes(pResCopy);
|
|
}
|
|
|
|
GlobalUnlock(hClip);
|
|
}
|
|
|
|
CloseClipboard();
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
* MsgFilterHookFunc
|
|
*
|
|
* This is the exported message filter function that is hooked into
|
|
* the message stream for detecting the pressing of the F1 key, at
|
|
* which time it calls up the appropriate help.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* History:
|
|
*
|
|
************************************************************************/
|
|
|
|
DWORD FAR PASCAL MsgFilterHookFunc(
|
|
INT nCode,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
LPMSG lpMsg = (LPMSG)lParam;
|
|
|
|
if ((nCode == MSGF_MENU || nCode == MSGF_DIALOGBOX) &&
|
|
(lpMsg->message == WM_KEYDOWN && lpMsg->wParam == VK_F1)) {
|
|
/*
|
|
* Display help.
|
|
*/
|
|
ShowHelp((nCode == MSGF_MENU) ? TRUE : FALSE);
|
|
|
|
/*
|
|
* Tell Windows to swallow this message.
|
|
*/
|
|
return 1;
|
|
}
|
|
|
|
return CallNextHookEx(ghhkMsgFilter, nCode, wParam, (LONG)lpMsg);
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
* ShowHelp
|
|
*
|
|
* This function is called when the user has requested help. It will
|
|
* look at the menu state (if fMenuHelp is TRUE) or which dialog
|
|
* is currently up to determine the help topic, then it calls WinHelp.
|
|
*
|
|
* Arguments:
|
|
* BOOL fMenuHelp - TRUE if this help is for a menu (help was requested
|
|
* in the menu modal loop). If FALSE, general help
|
|
* or help for a dialog is assumed.
|
|
*
|
|
* History:
|
|
*
|
|
************************************************************************/
|
|
|
|
VOID ShowHelp(
|
|
BOOL fMenuHelp)
|
|
{
|
|
INT nHelpContext = 0;
|
|
HWND hwndFocus;
|
|
|
|
if (fMenuHelp) {
|
|
nHelpContext = GetHelpContext(gMenuSelected, gahmapMenu);
|
|
}
|
|
else {
|
|
/*
|
|
* Look for help for the current dialog.
|
|
*/
|
|
if (gidCurrentDlg) {
|
|
nHelpContext = GetHelpContext(gidCurrentDlg, gahmapDialog);
|
|
}
|
|
else {
|
|
/*
|
|
* There is no current dialog. Is the window with the
|
|
* focus a control on the Properties Bar?
|
|
*/
|
|
if ((hwndFocus = GetFocus()) && IsChild(hwndStatus, hwndFocus))
|
|
nHelpContext = GetHelpContext(DID_STATUS, gahmapDialog);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* If there is help context, display it. Otherwise display
|
|
* the Contents screen.
|
|
*/
|
|
if (nHelpContext)
|
|
WinHelp(ghwndMain, gszHelpFile, HELP_CONTEXT, nHelpContext);
|
|
else
|
|
WinHelp(ghwndMain, gszHelpFile, HELP_CONTENTS, 0L);
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
* GetHelpContext
|
|
*
|
|
* This function takes a subject and returns its matching help
|
|
* context id from the given HELPMAP table.
|
|
*
|
|
* Arguments:
|
|
* INT idSubject - ID of the subject to find the help context for.
|
|
* PHELPMAP phmap - The help map table. It is assumed that the
|
|
* last entry in the table has a NULL subject id.
|
|
*
|
|
* History:
|
|
*
|
|
************************************************************************/
|
|
|
|
STATICFN INT GetHelpContext(
|
|
INT idSubject,
|
|
PHELPMAP phmap)
|
|
{
|
|
while (phmap->idSubject) {
|
|
if (phmap->idSubject == idSubject)
|
|
return phmap->HelpContext;
|
|
|
|
phmap++;
|
|
}
|
|
|
|
return 0;
|
|
}
|