⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 menu.c

📁 dos 1.0 其中包含quick basic源代码、内存管理himem emm386 发展历史
💻 C
📖 第 1 页 / 共 3 页
字号:
		    arcMenu.axRight + daxShadow + daxDbcs,
		    arcMenu.ayBottom + dayShadow,
		    lpbMenu);
		FreeWorkFar(lpbMenu);

#ifdef KANJI
		fRestoreDbcs = FALSE;
#endif	/*KANJI*/

		}

	mniCur.pmenuOpen = NULL;
	mniCur.iitem = iitemNil;

#else	// MENU_NOSAVE
	mniCur.pmenuOpen = NULL;
	mniCur.iitem = iitemNil;

	ScreenRedraw();
#endif	// MENU_NOSAVE

	if (fMessage)
		SendMessage(pwndMenu, WM_COMMAND, mniCur.pmenuOpen->idMenu,
				MAKELONG(mniCur.pmenuOpen,mmdMenu));
	ReportMenuInactive();
	}



/********** MENU selection **********/


STATIC VOID
HiliteMenuMnem(fOn)
/*
  -- hilite or unhilite the menu mnemonics
  -- do nothing if menu is open
  -- update global state (mniCur.fMenuMnem)
*/
BOOL fOn;
	{
	REGISTER PMENU pmenu;
	REGISTER WORD imenu;
	WORD di;

	if (FMenuOpen())
		{
		/* menu is open, this should be a no op */
		Assert(mniCur.fMenuMnem == fOn);
		return;
		}

	if (!FShowMenuBar())
		return;

	DrawThisWnd(NULL);

	for (imenu = 0, pmenu = pmenubarCur->rgmenu;
	    imenu < pmenubarCur->cmenu;
	    imenu++, pmenu++)
		{
		AX ax = axMenuMin + pmenu->rxTitle + (BYTE) pmenu->ichHilite;

		if (imenu != mniCur.imenu)
			di = (fOn) ? (dmAttrOnly | isaMenuHilite) :
				( (pmenu->fEnabled) ? (dmAttrOnly | isaMenu) :
				 	(dmAttrOnly | isaDisabledMenuItem));
		else
			{
			di = (fOn) ? (dmAttrOnly | isaMenuHiliteSel) :
			   (dmAttrOnly | isaMenuSelected);
			}

		FillArc(ax, ayMenu, ax + 1, ayMenu + 1, '\0', di);
		}
	mniCur.fMenuMnem = fOn;
	}



STATIC BOOL
FMakeSelection()
/*
  -- attempt to make a selection
  -- if applicable send messages for menu selection
  -- valid selection closes menu and returns TRUE
  -- invalid selection (i.e. disabled item) optionally beeps,
	keeps menu open, and returns FALSE
  -- note : will set menu state to idle before returning TRUE
*/
	{
	WORD id;
	DWORD lParam;
	REGISTER PMENU pmenu = mniCur.pmenuOpen;
	
	Assert(mniCur.imenu != imenuNil);
	if (mniCur.iitem != iitemNil)
		{
		PMENUITEM pmenuitem = &(PmenuitemOfPmenu(pmenu)[mniCur.iitem]);
		if (!pmenuitem->fEnabled)
			{
			/* selection of disabled item */
			Beep();
			return FALSE;
			}

		id = pmenuitem->idItem;
		lParam = MAKELONG(pmenuitem, mmdItem);
		}
	else
		{
		id = pmenu->idMenu;	/* menu but no selection */
		lParam = MAKELONG(pmenu, mmdMenu);
		}

	/* valid selection : close menu - keep menu name hilited */
	CloseMenuCur(FALSE);
	/* send message while menu name hilited - the menu may change */
	mniCur.imenu = imenuNil;
	SendMessage(pwndMenu, WM_COMMAND, id, lParam);
	ReportMenuInactive();
	/* do both : unhilite menu title and redraw optionally changed bar */
	DrawMenubar();
	UpdateCursor();
	return TRUE;
	}



STATIC WORD
ImenuPickVk(vk)
/*
  -- Search for menu based on "hilite" character in menu title
  -- if found return imenu
  -- if not found, return imenuNil
*/
WORD vk;	/* virtual key of first character */
	{
	WORD imenu;
	REGISTER PMENU pmenu = pmenubarCur->rgmenu;
	
	for (imenu = 0; imenu < pmenubarCur->cmenu; imenu++, pmenu++)
		{
#ifndef KANJI
		if (FMatchVkCh(vk, *(pmenu->pchTitle + pmenu->ichHilite)))
#else
		if (FMatchVkCh(vk, fKanaAccel ? (char) pmenu->chKanaAccel :
		    *(pmenu->pchTitle + pmenu->ichHilite)))
#endif /*KANJI*/
			{
			/* go one */
			return imenu;
			}
		}
	return imenuNil;
	}



STATIC WORD
ImenuPickMsp(msp)
/*
  -- mouse is on menu title line
  -- return index of selected menu or imenuNil
*/
MSP msp;
	{
	REGISTER MENU *pmenu;
	REGISTER AX ax = msp.s.ax;
	WORD imenu;

	Assert(msp.s.ay == ayMenu);

	pmenu = pmenubarCur->rgmenu;
	
	for (imenu = 0; imenu < pmenubarCur->cmenu; imenu++, pmenu++)
		{
		if (ax + 1 >= (AX) pmenu->rxTitle &&
		    ax <= ((AX) pmenu->rxTitle + pmenu->cchTitle))
			{
			return imenu;
			}
		}
	return imenuNil;
	}




/********** MENUITEMS **********/

STATIC VOID
DrawMenuItem(axLeft, ay, axRight, pmenuitem)
/*
  -- output a menu item
  -- left justify the portion to the left of a tab
  -- right justify the portion after the tab
  -- output checkmark if on
  -- only called by OpenMenuCur().
*/
AX axLeft, axRight;
AY ay;
REGISTER PMENUITEM pmenuitem;
	{
	char * sz = SzItem(pmenuitem);
	WORD di = pmenuitem->fEnabled ?
	    DiNormal(isaEnabledMenuItem) :
	    DiNormal(isaDisabledMenuItem);
	AX ax = axLeft + rxMenuText;

#ifdef MENU_RIGHT_JUSTIFY
	REGISTER char * szT = sz;
	WORD cch;

	for (cch = 0; *szT != '\t' && *szT != '\0'; cch++)
		szT++;
	Assert(pmenuitem->ichHilite < cch);
	TextOutAbs(ax, ay, sz, cch, di);
#else
	TextOutAbs(ax, ay, sz, strlen(sz), di);
	Unreferenced(axRight);	/* right coordinate not used */
#endif

#ifdef KANJI
	/* kana accelerator at start ? */
	if (fKanaAccel)
		CharOutAbs(ax, ay, pmenuitem->chKanaAccel, di);
#endif /*KANJI*/

	/* select hilited character (if enabled) */
	if (pmenuitem->fEnabled)
		{
		ax += (BYTE) pmenuitem->ichHilite;
		FillArc(ax, ay, ax + 1, ay + 1, '\0',
		    (dmAttrOnly | isaMenuHilite));
		}

	if (pmenuitem->fChecked)
		CharOutAbs(axLeft + rxMenuMark, ay, chMenuMark, di);

#ifdef MENU_RIGHT_JUSTIFY
	/* output right aligned stuff if any */
	if (*szT != '\0')
		{
		cch = strlen(++szT);
		TextOutAbs(axRight - cch - 1, ay, szT, cch, di);
		}
#endif
	}



STATIC VOID
HiliteItem(fSelected)
/*
  -- highlight current menu item within current menu list
*/
BOOL fSelected;
	{
	if (mniCur.iitem != iitemNil)
		{
		REGISTER PMENUITEM pmenuitem;
		REGISTER ISA isa;
		AX ax;
		AY ay;

		Assert(mniCur.pmenuOpen != NULL && mniCur.pmenuOpen->citem != 0);
		Assert(mniCur.pmenuOpen == &pmenubarCur->rgmenu[mniCur.imenu]);

		DrawThisWnd(NULL);
		pmenuitem = &PmenuitemOfPmenu(mniCur.pmenuOpen)[mniCur.iitem];

		if (fSelected)
			isa = isaSelectedMenuItem;
		else
			isa = (ISA) (pmenuitem->fEnabled ?
			    isaEnabledMenuItem :
			    isaDisabledMenuItem);

		ay = arcMenu.ayTop + mniCur.iitem + 1;
		FillArc(arcMenu.axLeft + daxBorder, ay,
		    arcMenu.axRight - daxBorder,
		    ay + dayBorder, '\0', dmAttrOnly | isa);

		/* restore hilite character */
		if (pmenuitem->fEnabled)
			{
			ax = arcMenu.axLeft + rxMenuText + pmenuitem->ichHilite;
			FillArc(ax, ay, ax + 1, ay + 1,
			    '\0', fSelected ? (dmAttrOnly | isaItemHiliteSel) :
			     (dmAttrOnly | isaMenuHilite));
			}

		/* If Selected then update help line */
		if (fSelected)
			SendMessage(pwndMenu, WM_MENUSELECT, pmenuitem->idItem,
			    MAKELONG(pmenuitem, mmdItem));
		}
	}



STATIC BOOL
FSelectItem(iitem)
/*
  -- set specified item to be current selected item
  -- if item is valid, change current selection and return TRUE
  -- if item is invalid (separator), change to no selection, return FALSE
  -- return TRUE if selection made
  -- item may be beyond valid range, do wrapping here
*/
WORD iitem;
	{
	Assert(FMenuOpen());
	Assert(mniCur.pmenuOpen == &pmenubarCur->rgmenu[mniCur.imenu]);

	/* check for empty drop downs */
	if (mniCur.pmenuOpen->citem == 0)
		return TRUE;

	/* check for menu wrapping */
	if (iitem != imenuNil && iitem >= mniCur.pmenuOpen->citem)
		{
		/* perform wrap */
		if (iitem == (WORD) -1)	/* wrapped to -1 */
			iitem = mniCur.pmenuOpen->citem - 1;
		else
			{
			Assert(iitem == mniCur.pmenuOpen->citem);
			iitem = 0;
			}
		}

	Assert(iitem == iitemNil || iitem < mniCur.pmenuOpen->citem);

	if (iitem != mniCur.iitem)
		{
		HiliteItem(FALSE);

		if (PmenuitemOfPmenu(mniCur.pmenuOpen)[iitem].fSeparator)
			{
			mniCur.iitem = iitemNil;
			ReportMenuInactive();
			return FALSE;
			}
		else
			{
			/* real item : hilite even if disabled */
			mniCur.iitem = iitem;
			HiliteItem(TRUE);
			}
		}
	return TRUE;
	}



STATIC BOOL
FMatchItemVk(vk)
/*
  -- Search for menu item based on first character (using ichHilite)
  -- if found changed current selection
  -- if found and enabled : select item and return TRUE
  --  otherwise return FALSE
*/
WORD vk;
	{
	REGISTER PMENU pmenu = mniCur.pmenuOpen;
	WORD	citem;
	WORD	iitem;
	REGISTER PMENUITEM pmenuitem;
#ifdef ACCEL_MULTIPLE
	WORD	citemMatch;

	citemMatch = 0;
	pmenuitem = &(PmenuitemOfPmenu(pmenu)[0]);
	citem = pmenu->citem;
	while (citem--)
		{
#ifdef KANJI
		/* Kanji Accelerator matching */
		if (!pmenuitem->fSeparator &&
		    FMatchVkCh(vk, fKanaAccel ? (char) pmenuitem->chKanaAccel :
		    *(SzItem(pmenuitem) + pmenuitem->ichHilite)))
#else
		if (!pmenuitem->fSeparator &&
		    FMatchVkCh(vk, *(SzItem(pmenuitem) + pmenuitem->ichHilite)))
#endif
			citemMatch++;
		pmenuitem++;
		}
	if (citemMatch == 0)
		return FALSE;	/* no match */
	fOneOfMultiple = (citemMatch > 1);
#endif /*ACCEL_MULTIPLE*/

	citem = pmenu->citem;
	iitem = mniCur.iitem;
	pmenuitem = &(PmenuitemOfPmenu(pmenu)[++iitem]);

	while (citem--)
		{
		if (iitem >= pmenu->citem)
			{
			/* wrap to top */
			iitem = 0;
			pmenuitem = PmenuitemOfPmenu(pmenu);
			}
#ifdef KANJI
		/* Kanji Accelerator matching */
		if (!pmenuitem->fSeparator &&
		    FMatchVkCh(vk, fKanaAccel ? (char) pmenuitem->chKanaAccel :
		    *(SzItem(pmenuitem) + pmenuitem->ichHilite)))
#else
		if (!pmenuitem->fSeparator &&
		    FMatchVkCh(vk, *(SzItem(pmenuitem) + pmenuitem->ichHilite)))
#endif
			{
			/* found ! */
			return (FSelectItem(iitem) && pmenuitem->fEnabled);
			}

		pmenuitem++;
		iitem++;
		}
	return FALSE;	/* not found */
	}



STATIC BOOL
FSelectItemMsp(msp)
/*
  -- Mouse form to pick an item
  -- returns TRUE if picking an item (and changes item selection)
*/
MSP msp;
	{
	Assert(msp.s.ay != ayMenu);

	if (FInsideMenuMsp(msp.s.ax, msp.s.ay))
		{
		Assert(mniCur.pmenuOpen->citem != 0);
		FSelectItem(msp.s.ay - arcMenu.ayTop - 1);
		mniCur.fMouseOnTitle = FALSE;	/* selected something */
		return TRUE;
		}

	/* not selecting anything */
	HiliteItem(FALSE);
	mniCur.iitem = iitemNil;
	return FALSE;
	}



STATIC BOOL
FInsideMenuMsp(ax, ay)
/*
  -- return TRUE if inside Menu dropdown, or on menu title bar
*/
REGISTER AX ax;
REGISTER AY ay;
	{
	if (ay == ayMenu)
		{
		mniCur.fMouseOnTitle = TRUE;
		return TRUE;
		}
	if (!FMenuOpen())
		return FALSE;
	return (ay > arcMenu.ayTop &&
	    ay < arcMenu.ayBottom - 1 &&
	    ax >= arcMenu.axLeft &&
	    ax < arcMenu.axRight);
	}





/********** The Filter **********/


PRIVATE BOOL FARPRIVATE
MenuFilterProc(pmsg)
/*
  -- menu manager filter procedure
  -- returns true if message is to be filtered out
*/
REGISTER PMSG pmsg;  /* access pmsg-> with same speed as local auto vars */
	{
	REGISTER WORD kk;		/* Key bits + vk */
	MSP msp;
	BOOL fMenuAction;

	if (pwndCapture != NULL)
		return(FALSE);
	kk = HIWORD(pmsg->lParam);
	fMenuAction = FALSE;

	msp.lParam = pmsg->lParam;

	/* is it a valid (LEFT) menu mouse message ?? */
	if (pmsg->message >= WM_MOUSEFIRST && pmsg->message <= WM_LMOUSELAST &&
	    FShowMenuBar())
		{
		if ((pmsg->message == WM_LBUTTONDBLCLK ||
		    pmsg->message == WM_LBUTTONDOWN) && !mniCur.fMouse)
			{
			/* Menu Button */
			BOOL fInside = FInsideMenuMsp(msp.s.ax, msp.s.ay);

			if (!mniCur.fMouse && !fInside &&
			   (FMenuActive() || mniCur.fMenuMnem))
				{
				/* click not in drop down */
				SetIdleState();
				return FALSE; /* pass message through */
				}
			mniCur.fMouse |= fInside;
			}

		/* now see if we should do any mouse work */
		if (!mniCur.fMouse)
			return FMenuActive();	/* eat if menu active */

		if (msp.s.ay == ayMenu)
			{
			WORD imenuT;

			imenuT = ImenuPickMsp(msp);
			if (imenuT != imenuNil && !FMenuOpen())
				goto open_new_menu;
			else if (imenuT != mniCur.imenu)
				{
				CloseMenuCur(TRUE);
open_new_menu:
				mniCur.fMouseOnTitle = FALSE; /* selection */
				SelectMenu(imenuT);
				OpenMenuCur();
				}
			else if (FMenuActive())
				{
				/* clear any selection */
				Assert(FMenuOpen());
				FSelectItem(iitemNil);
				}
			/* re-send menu title message (for help) */
				if (mniCur.pmenuOpen->citem != 0)
			if (mniCur.pmenuOpen != NULL)
				SendMessage(pwndMenu, WM_MENUSELECT,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -