📄 menu.c
字号:
mniCur.pmenuOpen->idMenu,
MAKELONG(mniCur.pmenuOpen, mmdMenu));
}
else if (FMenuActive())
{
/* selecting an item (maybe) */
if (!FSelectItemMsp(msp))
ReportMenuInactive();
}
/* is he releasing the mouse button ?? */
if (pmsg->message == WM_LBUTTONUP)
{
if (!FMenuActive())
{
/* do nothing (except cursor enable) */
UpdateCursor();
}
else if (mniCur.iitem != iitemNil)
{
FMakeSelection();
}
else if (msp.s.ay == ayMenu)
{
/* selecting title - close or keep open */
Assert(FMenuOpen());
if (mniCur.fMouseOnTitle)
{
/* stay on title => close it */
SetIdleState();
}
/* else : keep it open */
else if (mniCur.pmenuOpen->citem != 0)
{
FSelectItem(0);
}
else
{
FMakeSelection();
}
}
else
SetIdleState();
mniCur.fMouse = FALSE;
}
return TRUE; /* eat it */
}
else if (mniCur.fMouse)
{
/* mouse control of the menu --> nothing gets through */
return TRUE;
}
#ifdef MULTIPLE_ACTION
else if ((pmsg->wParam == vkActionPrim ||
pmsg->wParam == vkActionSec) &&
(pmsg->wParam == VK_MENU) &&
(pmsg->message == WM_KEYUP))
#else /* MULTIPLE_ACTION */
else if (pmsg->wParam == VK_MENU && pmsg->message == WM_KEYUP)
#endif /* MULTIPLE_ACTION */
{
/* convert keys to Menu Action events */
if (fNonAltKey)
{
/* ignore it */
if (!FMenuActive())
HiliteMenuMnem(FALSE);
return TRUE;
}
fMenuAction = TRUE;
}
#ifdef MULTIPLE_ACTION
else if ((pmsg->wParam == vkActionPrim ||
pmsg->wParam == vkActionSec) &&
(pmsg->message == WM_CHAR))
{
fMenuAction = TRUE;
}
#endif /* MULTIPLE_ACTION */
else if (pmsg->message == WM_CHAR)
fNonAltKey = (BYTE) (pmsg->wParam != VK_MENU);
/* allow all non-alt key shifted keys to slip by (if accelerators) */
if (pmsg->message == WM_CHAR)
{
if (FTranslateAccelerator(pmsg->wParam, kk))
return TRUE; /* eat it */
#ifdef MULTIPLE_ACTION
if ((!FMenuActive()) &&
(pmsg->wParam != vkActionPrim) &&
(pmsg->wParam != vkActionSec))
return FALSE; /* pass through if menu off */
}
#else /* ! MULTIPLE_ACTION */
if (!(kk & KK_ALT) && !FMenuActive())
return FALSE; /* pass through if menu off */
}
#endif /* MULTIPLE_ACTION */
if (!FMenuActive())
{
/* we are in idle - handle as fast as possible */
Assert(mniCur.imenu == imenuNil); /* no menu yet */
if (fMenuAction)
{
/* Turn on first menu - don't open */
SelectMenu(0);
HiliteMenuTitle(TRUE);
HiliteMenuMnem(TRUE);
return TRUE; /* eat it */
}
else if (pmsg->message == WM_CHAR)
{
/* a character */
#ifdef MULTIPLE_ACTION
if ((pmsg->wParam == vkActionPrim) ||
(pmsg->wParam == vkActionSec))
#else /* MULTIPLE_ACTION */
if (pmsg->wParam == VK_MENU)
#endif /* MULTIPLE_ACTION */
{
HiliteMenuMnem(TRUE);
return TRUE; /* eat it */
}
if (kk & KK_ALT)
#ifdef MULTIPLE_ACTION
{
WORD imenuT;
/* otherwise a menu selection */
if ((imenuT = ImenuPickVk(kk & KK_VK))
!= imenuNil)
{
/* if we don't have a menubar -- get one !! */
if (pmenubarCur == NULL)
SendMessageShort(pwndMenu, WM_MENUSTART);
/* open that menu */
SelectMenu(imenuT);
OpenMenuCur();
}
else
return FALSE;
return TRUE; /* eat it */
}
#else /* !MULTIPLE_ACTION */
{
WORD imenuT;
/* if we don't have a menubar -- get one !! */
if (pmenubarCur == NULL)
SendMessageShort(pwndMenu, WM_MENUSTART);
/* otherwise a menu selection */
if ((imenuT = ImenuPickVk(kk & KK_VK))
!= imenuNil)
{
/* open that menu */
SelectMenu(imenuT);
OpenMenuCur();
}
else
Beep();
return TRUE; /* eat it */
}
#endif /* MULTIPLE_ACTION */
return FALSE; /* pass through */
}
return FALSE; /* let the message pass */
}
/* not in idle !!!! */
Assert(mniCur.imenu != imenuNil);
AssertSz(pmenubarCur != NULL, "processing without a menu bar");
#ifdef DUAL
/* if we get a null message while processing the menu, we are
* therefore in an idle loop and should go to sleep for DOS 5
*/
if (fProtectMode && pmsg->message == WM_NULL)
{
SendMessageShort(pwndMenu, WM_MENUIDLE);
DosSemWait(hsemaMessage, -1L);
return TRUE; /* eat the message */
}
#else /*!DUAL*/
#ifdef DOS5
/* if we get a null message while processing the menu, we are
* therefore in an idle loop and should go to sleep for DOS 5
*/
if (pmsg->message == WM_NULL)
{
SendMessageShort(pwndMenu, WM_MENUIDLE);
DosSemWait(hsemaMessage, -1L);
return TRUE; /* eat the message */
}
#endif
#endif /*!DUAL*/
if (fMenuAction)
{
/* Menu Action */
if (FMenuOpen())
{
PMENU pmenu;
/* close menu */
CloseMenuCur(TRUE);
HiliteMenuMnem(TRUE); /* back to menu browse */
/* update the help */
pmenu = &pmenubarCur->rgmenu[mniCur.imenu];
SendMessage(pwndMenu, WM_MENUSELECT, pmenu->idMenu,
MAKELONG(pmenu, mmdMenu));
}
else
{
/* go back to idle */
SetIdleState();
}
}
else if (pmsg->message == WM_CHAR)
{
WORD imenuT;
BOOL fWasOpen;
/* undo repeat before processing */
UndoRepeat(pmsg->wParam, pmsg->lParam);
imenuT = mniCur.imenu;
#ifdef MULTIPLE_ACTION
if (pmsg->wParam == vkActionPrim ||
pmsg->wParam == vkActionSec)
return(TRUE);
if (pmsg->wParam == vkCancelPrim || pmsg->wParam == vkCancelSec) {
SetIdleState();
return TRUE;
}
#endif /* MULTIPLE_ACTION */
/* Cases : similar whether menu is open or not */
switch (pmsg->wParam)
{
default:
break; /* drop out & do second set of cases */
#ifndef MULTIPLE_ACTION
case LOBYTE(VK_ESCAPE): /* escape character */
SetIdleState();
return TRUE;
#endif /* !MULTIPLE_ACTION */
case VK_LEFT:
imenuT -= 2;
/* fall through to right */
case VK_RIGHT:
imenuT++; /* right +1, left -2+1 == -1 */
/* check for wrap */
if (imenuT >= pmenubarCur->cmenu)
{
if (imenuT == (WORD) -1) /* wrapped */
imenuT = pmenubarCur->cmenu - 1;
else
{
Assert(imenuT == pmenubarCur->cmenu);
imenuT = 0;
}
}
/* select new menu */
fWasOpen = FMenuOpen();
BeginDraw();
CloseMenuCur(TRUE);
ReportMenuInactive();
HiliteMenuTitle(FALSE);
SelectMenu(imenuT);
if (fWasOpen)
OpenMenuCur();
EndDraw();
return TRUE;
#ifndef MULTIPLE_ACTION
case VK_MENU:
return TRUE;
#endif /* !MULTIPLE_ACTION */
case VK_HELP_KEY:
SendMenuHelp(kk);
MoveHardwareCursor(0, 0, FALSE);
return TRUE;
}
/* cases which are different whether FMenuOpen() or not */
if (!FMenuOpen())
{
/* Menu not open, let's try and open one */
switch (pmsg->wParam)
{
default:
/* select menu */
if ((imenuT = ImenuPickVk(pmsg->wParam))
!= imenuNil)
{
SelectMenu(imenuT);
OpenMenuCur();
}
else
Beep(); /* bad choice */
break;
case LOBYTE(VK_RETURN):
case VK_UP:
case VK_DOWN: /* same as up */
/* Open the current menu */
OpenMenuCur();
break;
}
}
else
{
/* Menu open, keys effect item selection */
WORD iitemT = mniCur.iitem;
switch (pmsg->wParam)
{
default:
/* select item */
if (!FMatchItemVk(pmsg->wParam))
{
/* bad key */
Beep();
break;
}
#ifdef ACCEL_MULTIPLE
if (fOneOfMultiple)
break;
#endif /*ACCEL_MULTIPLE*/
/* fall through to accept */
case LOBYTE(VK_RETURN):
FMakeSelection();
break;
case VK_UP:
case VK_DOWN:
/* previous / next menu item */
do
{
if (pmsg->wParam == VK_UP)
iitemT--;
else
iitemT++;
}
while (!FSelectItem(iitemT));
}
}
}
return TRUE; /* normally eat */
}
STATIC VOID
SetIdleState()
/*
-- jump to idle state
*/
{
/* do it all -- all routines handle nil cases */
CloseMenuCur(TRUE);
HiliteMenuTitle(FALSE);
mniCur.imenu = imenuNil;
HiliteMenuMnem(FALSE);
ReportMenuInactive();
mniCur.fMouse = FALSE;
UpdateCursor();
}
/********** Utilities **********/
STATIC BOOL
FTranslateAccelerator(vk, kk)
/*
-- check to see if key "vk" should be treated as an accelerator
-- send 2 messages if it is an accelerator (DO NOT POST!!!) and return TRUE
-- return FALSE if not translated
*/
WORD vk;
WORD kk;
{
REGISTER MPVKEYID *pmpvkeyid = pmenubarCur->rgmpvkeyid;
WORD vkeyCur, vkeyFind;
/* look for correct "VKEY" value & proper shift states */
vkeyFind = VkeyOfVkKk(vk, kk & (KK_ALT | KK_CONTROL | KK_SHIFT));
while ((vkeyCur = pmpvkeyid->vkey) != 0)
{
if (vkeyCur == vkeyFind)
{
WORD idItem = pmpvkeyid->idItem;
PMENUITEM pmenuitem = FindMenuItem(idItem);
/* found an accelerator */
if (FMenuActive())
SetIdleState();
if (pmenuitem != NULL)
{
SendMessage(pwndMenu, WM_INITMENUPOPUP,
pmenuFound->idMenu, MAKELONG(pmenuFound, 1));
if (!pmenuitem->fEnabled)
return TRUE;
}
/* send item message even if not with menu item */
SendMessage(pwndMenu, WM_COMMAND, idItem,
MAKELONG(pmenuitem, mmdAccel));
return TRUE;
}
else
pmpvkeyid++;
}
return FALSE;
}
STATIC BOOL
FMatchVkCh(vk, chMenu)
/*
-- return TRUE if virtual key "vk" matches matches menu character "ch"
-- (i.e. vk will be Upper case ASCII, menu char may be upper or lower case)
-- for KANJI -- also check the alternate KANA/ROMAN key
*/
WORD vk;
char chMenu;
{
char ch = (char) LOBYTE(vk);
if (vk >= 'a' && vk <= 'z')
ch -= ('a' - 'A');
else if ((unsigned) ch > 0x7f)
ch = ChUpperFromChExt(ch);
if (chMenu >= 'a' && chMenu <= 'z')
chMenu -= ('a' - 'A');
else if ((unsigned) chMenu > 0x7f)
chMenu = ChUpperFromChExt(chMenu);
#ifdef KANJI
if (ch != chMenu)
{
/* possibly the alternate character on that key -- try it */
ch = ChAlternateKeytop(ch);
}
#endif /*KANJI*/
return(chMenu == ch);
}
STATIC char *
SzItem(pmenuitem)
/*
-- return the text of the menu item
*/
REGISTER PMENUITEM pmenuitem;
{
return (pmenuitem->fHandle ? *(pmenuitem->u.pszItem) :
pmenuitem->u.szItem);
}
STATIC VOID
SendMenuHelp(kk)
/*
-- send menu help message
*/
WORD kk;
{
/* process HELP */
WORD imenuSave;
/* save old state, turn off menu for the help portion */
imenuSave = mniCur.imenu;
Assert(imenuSave != imenuNil);
mniCur.imenu = imenuNil;
if (mniCur.iitem != iitemNil)
{
PMENUITEM pmenuitem;
Assert(FMenuOpen());
pmenuitem = &PmenuitemOfPmenu(mniCur.pmenuOpen)[mniCur.iitem];
Help(hemMenuItem, pmenuitem->idItem, pmenuitem, kk);
}
else
{
PMENU pmenu;
pmenu = &pmenubarCur->rgmenu[imenuSave];
Help(hemMenu, pmenu->idMenu, pmenu, kk);
}
mniCur.imenu = imenuSave;
#ifdef DIALOG_NOSAVE
DrawMenuCur();
#endif
}
#ifdef MENU_UTILS
VOID FARPUBLIC
OpenMenu(idMenu)
/*
-- application wants a menu open
*/
WORD idMenu; /* id of menu to open */
{
REGISTER PMENU pmenu;
WORD imenu;
Assert(mniCur.imenu == imenuNil); /* must be closed */
for (imenu = 0, pmenu = pmenubarCur->rgmenu;
imenu < pmenubarCur->cmenu;
pmenu++, imenu++)
{
if (pmenu->idMenu == idMenu)
{
/* found it */
SelectMenu(imenu);
OpenMenuCur();
fNonAltKey = FALSE; /* allow up transition */
return;
}
}
AssertSz(FALSE, "Invalid call to OpenMenu()");
}
#endif /*MENU_UTILS*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -