📄 menu.c
字号:
if (PtInRect (&rc, x, y))
return pmi;
rc.top += pmi->h;
if (pmi->type == TYPE_PPPMENU)
psubmi = pmi->submenu;
else
psubmi = pmi->next;
while (psubmi) {
rc.bottom = rc.top + psubmi->h;
if (PtInRect (&rc, x, y))
return psubmi;
rc.top = rc.bottom;
psubmi = psubmi->next;
}
return NULL;
}
static void mnuHiliteMenuItem (PTRACKMENUINFO ptmi, PMENUITEM pmi, BOOL bHilite)
{
RECT rc;
PMENUITEM ptemp = ptmi->pmi;
int inter;
int mioffx;
int marginlx, marginrx;
int offy;
PBITMAP bmp;
if (pmi->type == TYPE_PPPMENU) return;
inter = GetMainWinMetrics (MWM_INTERMENUITEMY);
mioffx = GetMainWinMetrics (MWM_MENUITEMOFFX);
marginlx = GetMainWinMetrics (MWM_MENULEFTMARGIN);
marginrx = GetMainWinMetrics (MWM_MENURIGHTMARGIN);
rc.left = ptmi->rc.left;
rc.right = ptmi->rc.right;
rc.top = ptmi->rc.top + GetMainWinMetrics (MWM_MENUTOPMARGIN);
if (ptemp == pmi)
ptemp = pmi;
else {
rc.top += ptemp->h;
if (ptemp->type == TYPE_PPPMENU)
ptemp = ptemp->submenu;
else
ptemp = ptemp->next;
while (ptemp != pmi) {
rc.top += ptemp->h;
ptemp = ptemp->next;
}
}
rc.bottom = rc.top + ptemp->h;
if (ptemp->mnutype & MFT_SEPARATOR) return;
if (bHilite)
ptemp->mnustate |= MFS_HILITE;
else
ptemp->mnustate &= ~MFS_HILITE;
SetBrushColor (HDC_SCREEN,
bHilite ? GetWindowElementColor(BKC_MENUITEM_HILITE)
: GetWindowElementColor(BKC_MENUITEM_NORMAL));
FillBox (HDC_SCREEN, rc.left + marginlx, rc.top,
RECTW (rc) - marginlx - marginrx, RECTH (rc));
#if defined(_FLAT_WINDOW_STYLE) && !defined(_GRAY_SCREEN)
if (bHilite) {
SetPenColor(HDC_SCREEN, GetWindowElementColor(FGC_MENUITEM_FRAME));
Rectangle (HDC_SCREEN, rc.left + marginlx, rc.top,
rc.left + RECTW (rc) - marginrx, rc.top + RECTH (rc));
}
else {
SetPenColor(HDC_SCREEN, GetWindowElementColor(BKC_MENUITEM_NORMAL));
Rectangle (HDC_SCREEN, rc.left + marginlx, rc.top,
rc.left + RECTW (rc) - marginrx, rc.top + RECTH (rc));
}
#endif
if (ptemp->mnutype & MFT_BITMAP) {
if (ptemp->mnustate & MFS_CHECKED)
bmp = ptemp->hbmpChecked;
else
bmp = ptemp->hbmpUnchecked;
FillBoxWithBitmap (HDC_SCREEN, rc.left + marginlx, rc.top,
bmp->bmWidth,
bmp->bmHeight,
bmp);
}
else if (ptemp->mnutype & MFT_OWNERDRAW) {
}
else {
int old_mode, bmp_w = mioffx;
// draw check bitmap
bmp = mnuGetCheckBitmap (ptemp);
if (bmp) {
offy = (ptemp->h - bmp->bmHeight)>>1;
FillBoxWithBitmap (HDC_SCREEN, rc.left + marginlx, rc.top + offy,
bmp->bmWidth, ptemp->h - (offy<<1), bmp);
bmp_w = MAX (bmp->bmWidth, mioffx);
}
SelectFont (HDC_SCREEN, GetSystemFont (SYSLOGFONT_MENU));
SetBkColor (HDC_SCREEN,
bHilite ? GetWindowElementColor(BKC_MENUITEM_HILITE)
: GetWindowElementColor(BKC_MENUITEM_NORMAL));
old_mode = SetBkMode (HDC_SCREEN, BM_TRANSPARENT);
if (ptemp->mnustate & MFS_DISABLED) {
SetTextColor (HDC_SCREEN, GetWindowElementColor(FGC_MENUITEM_DISABLED));
}
else {
SetTextColor (HDC_SCREEN,
bHilite ? GetWindowElementColor(FGC_MENUITEM_HILITE)
: GetWindowElementColor(FGC_MENUITEM_NORMAL));
}
TextOut (HDC_SCREEN, rc.left + bmp_w + marginlx, rc.top + inter,
(char*)ptemp->typedata);
SetBkMode (HDC_SCREEN, old_mode);
if (ptemp->submenu) {
bmp = mnuGetSubMenuBitmap (ptemp);
offy = (ptemp->h - bmp->bmHeight)>>1;
FillBoxWithBitmap (HDC_SCREEN,
rc.right - mioffx - marginrx,
rc.top + offy,
bmp->bmWidth, ptemp->h - (offy<<1), bmp);
}
}
}
static int mnuOpenNewSubMenu (PTRACKMENUINFO ptmi, PMENUITEM pmi,
int x, int y)
{
PTRACKMENUINFO pnewtmi;
pnewtmi = TrackMenuInfoAlloc ();
pnewtmi->rc.left = x;
pnewtmi->rc.top = y;
pnewtmi->pmi = pmi;
pnewtmi->pmb = ptmi->pmb;
pnewtmi->philite = NULL;
pnewtmi->hwnd = ptmi->hwnd;
pnewtmi->flags = ptmi->flags;
pnewtmi->next = NULL;
pnewtmi->prev = NULL;
return SendMessage (HWND_DESKTOP, MSG_TRACKPOPUPMENU,
0, (LPARAM)(pnewtmi));
}
static PMENUITEM mnuGetNextMenuItem (PTRACKMENUINFO ptmi, PMENUITEM pmi)
{
PMENUITEM head = ptmi->pmi;
PMENUITEM next;
if (head->type == TYPE_PPPMENU)
head = head->submenu;
if (pmi == NULL)
next = head;
else if (pmi->next)
next = pmi->next;
else
next = head;
while (next && next->mnutype & MFT_SEPARATOR)
next = next->next;
if (next == NULL)
next = head;
while (next && next->mnutype & MFT_SEPARATOR)
next = next->next;
return next;
}
static PMENUITEM mnuGetPrevItem (PMENUITEM head, PMENUITEM pmi)
{
if (head == pmi)
return NULL;
while (head) {
if (head->next == pmi)
return head;
head = head->next;
}
return NULL;
}
static PMENUITEM mnuGetPrevMenuItem (PTRACKMENUINFO ptmi, PMENUITEM pmi)
{
PMENUITEM head = ptmi->pmi, tail;
PMENUITEM prev;
if (head->type == TYPE_PPPMENU)
head = head->submenu;
prev = pmi;
do {
prev = mnuGetPrevItem (head, prev);
if (prev) {
if (prev->mnutype & MFT_SEPARATOR)
continue;
else
return prev;
}
else
break;
}while (TRUE);
tail = head;
while (tail && tail->next)
tail = tail->next;
prev = tail;
do {
if (prev) {
if (!(prev->mnutype & MFT_SEPARATOR))
return prev;
}
else
break;
prev = mnuGetPrevItem (head, prev);
}while (TRUE);
return NULL;
}
static int mnuGetMenuItemY (PTRACKMENUINFO ptmi, PMENUITEM pmi)
{
PMENUITEM head = ptmi->pmi;
int y = ptmi->rc.top + GetMainWinMetrics (MWM_MENUTOPMARGIN);
if (pmi == head) return y;
y += head->h;
if (head->type == TYPE_PPPMENU)
head = head->submenu;
else
head = head->next;
while (head) {
if (head == pmi)
return y;
y += head->h;
head = head->next;
}
return 0;
}
static void mnuTrackMenuWithKey (PTRACKMENUINFO ptmi,
int message, int scan, DWORD status)
{
PTRACKMENUINFO phead, pcurtmi, pprevtmi;
PMENUITEM pcurmi, pnewmi;
HWND hwnd;
HMENU hmnu;
UINT flags;
int barItem;
int id;
flags = ptmi->flags;
hmnu = (HMENU)ptmi->pmi;
phead = ptmi;
while (phead->prev) {
phead = phead->prev;
}
// get last tracking menu, the last menu is the current menu.
pcurtmi = ptmi;
while (pcurtmi->next) {
pcurtmi = pcurtmi->next;
}
pprevtmi = pcurtmi->prev;
pcurmi = pcurtmi->philite;
if (message == MSG_KEYDOWN) {
switch (scan) {
case SCANCODE_CURSORBLOCKDOWN:
case SCANCODE_CURSORBLOCKUP:
if (scan == SCANCODE_CURSORBLOCKDOWN)
pnewmi = mnuGetNextMenuItem (pcurtmi, pcurmi);
else
pnewmi = mnuGetPrevMenuItem (pcurtmi, pcurmi);
if (pnewmi != pcurmi) {
if (pcurmi)
mnuHiliteMenuItem (pcurtmi, pcurmi, FALSE);
if (pnewmi) {
mnuHiliteMenuItem (pcurtmi, pnewmi, TRUE);
pcurtmi->philite = pnewmi;
}
}
break;
break;
case SCANCODE_CURSORBLOCKRIGHT:
if (pcurmi && pcurmi->submenu)
mnuOpenNewSubMenu (pcurtmi,
pcurmi->submenu,
pcurtmi->rc.right,
mnuGetMenuItemY (pcurtmi, pcurmi));
else {
if (phead->pmb) {
barItem = mnuGetNextMenuBarItem (phead->pmb,
phead->barPos);
if (barItem != phead->barPos) {
hwnd = phead->hwnd;
// close current popup menu.
SendMessage (HWND_DESKTOP, MSG_CLOSEMENU, 0, 0);
// open new popup menu.
TrackMenuBar (hwnd, barItem);
}
}
}
break;
case SCANCODE_ESCAPE:
if (pprevtmi)
SendMessage (HWND_DESKTOP,
MSG_ENDTRACKMENU, 0, (LPARAM)pcurtmi);
break;
case SCANCODE_CURSORBLOCKLEFT:
if (pprevtmi)
SendMessage (HWND_DESKTOP,
MSG_ENDTRACKMENU, 0, (LPARAM)pcurtmi);
else {
if (phead->pmb) {
barItem = mnuGetPrevMenuBarItem (phead->pmb,
phead->barPos);
if (barItem != phead->barPos) {
hwnd = phead->hwnd;
// close current popup menu.
SendMessage (HWND_DESKTOP, MSG_CLOSEMENU, 0, 0);
// open new popup menu.
TrackMenuBar (hwnd, barItem);
}
}
}
break;
case SCANCODE_ENTER:
if (pcurmi == NULL) return;
if (pcurmi->mnutype & MFT_SEPARATOR) return;
if (pcurmi->mnustate & MFS_DISABLED) return;
if (pcurmi->submenu) {
mnuOpenNewSubMenu (pcurtmi,
pcurmi->submenu,
pcurtmi->rc.right,
mnuGetMenuItemY (pcurtmi, pcurmi));
return;
}
if (pcurmi && pcurmi->type != TYPE_PPPMENU &&
pcurmi->submenu == NULL) {
hwnd = ptmi->hwnd;
id = pcurmi->id;
SendMessage (HWND_DESKTOP, MSG_CLOSEMENU, 0, 1);
if (flags & TPM_SYSCMD)
SendNotifyMessage (hwnd, MSG_SYSCOMMAND, id, 0);
else
SendNotifyMessage (hwnd, MSG_COMMAND, id, 0);
if (flags & TPM_DESTROY)
DestroyMenu (hmnu);
}
break;
}
}
else if (message == MSG_KEYUP) {
switch (scan) {
case SCANCODE_LEFTALT:
case SCANCODE_RIGHTALT:
SendMessage (HWND_DESKTOP, MSG_CLOSEMENU, 0, 1);
if (flags & TPM_DESTROY)
DestroyMenu (hmnu);
break;
}
}
}
static void mnuTrackMenu (PTRACKMENUINFO ptmi, int x, int y)
{
PTRACKMENUINFO phead, plast;
PTRACKMENUINFO pcurtmi, pclose, ptemp;
PMENUITEM pcurmi;
PMENUITEM philite;
int barItem;
HWND hwnd;
// get first tracking menu.
phead = ptmi;
while (phead->prev) {
phead = phead->prev;
}
// get last tracking menu.
plast = ptmi;
while (plast->next) {
plast = plast->next;
}
pcurtmi = mnuHitTestMenu (plast, x, y);
if (pcurtmi == NULL) {
if (plast->philite)
mnuHiliteMenuItem (plast, plast->philite, FALSE);
// check to see if move to the other sub menu of menu bar.
if (phead->pmb) {
barItem = MenuBarHitTest (phead->hwnd, x, y);
if (barItem >= 0 && barItem != phead->barPos) {
hwnd = phead->hwnd;
// close current popup menu.
SendMessage (HWND_DESKTOP, MSG_CLOSEMENU, 0, 0);
// open new popup menu.
TrackMenuBar (hwnd, barItem);
}
}
return;
}
pcurmi = mnuHitTestMenuItem (pcurtmi, x, y);
if (pcurtmi != plast) {
pclose = pcurtmi->next->next;
if (pclose != NULL) {
while (pclose != plast) {
ptemp = plast->prev;
SendMessage (HWND_DESKTOP, MSG_ENDTRACKMENU, 0, (LPARAM)plast);
plast = ptemp;
}
SendMessage (HWND_DESKTOP, MSG_ENDTRACKMENU, 0, (LPARAM)plast);
plast = pcurtmi->next;
}
if (plast->philite) {
mnuHiliteMenuItem (plast, plast->philite, FALSE);
plast->philite = NULL;
}
}
philite = pcurtmi->philite;
if (pcurmi == philite) return;
// current hilite menu item is a bottom most item.
if (philite) {
if (pcurtmi != plast)
SendMessage (HWND_DESKTOP, MSG_ENDTRACKMENU, 0, (LPARAM)plast);
mnuHiliteMenuItem (pcurtmi, philite, FALSE);
}
pcurtmi->philite = pcurmi;
if (pcurmi == N
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -