📄 tkwinmenu.c
字号:
SelectObject(scratchDC, bitmap); SetMapMode(scratchDC, GetMapMode(hdc)); GetObject(bitmap, sizeof(BITMAP), &bm); ptSize.x = bm.bmWidth; ptSize.y = bm.bmHeight; DPtoLP(hdc, &ptSize, 1); ptOrg.y = ptOrg.x = 0; DPtoLP(hdc, &ptOrg, 1); if (alignFlags & ALIGN_BITMAP_TOP) { topOffset = 0; } else if (alignFlags & ALIGN_BITMAP_BOTTOM) { topOffset = (rectPtr->bottom - rectPtr->top) - ptSize.y; } else { topOffset = (rectPtr->bottom - rectPtr->top) / 2 - (ptSize.y / 2); } if (alignFlags & ALIGN_BITMAP_LEFT) { leftOffset = 0; } else if (alignFlags & ALIGN_BITMAP_RIGHT) { leftOffset = (rectPtr->right - rectPtr->left) - ptSize.x; } else { leftOffset = (rectPtr->right - rectPtr->left) / 2 - (ptSize.x / 2); } BitBlt(hdc, rectPtr->left + leftOffset, rectPtr->top + topOffset, ptSize.x, ptSize.y, scratchDC, ptOrg.x, ptOrg.y, SRCCOPY); DeleteDC(scratchDC); DeleteObject(bitmap); TkWinReleaseDrawableDC(drawable, hdc, &state);}/* *---------------------------------------------------------------------- * * DrawMenuEntryIndicator -- * * This procedure draws the indicator part of a menu. * * Results: * None. * * Side effects: * Commands are output to X to display the menu in its * current mode. * *---------------------------------------------------------------------- */voidDrawMenuEntryIndicator(menuPtr, mePtr, d, gc, indicatorGC, tkfont, fmPtr, x, y, width, height) TkMenu *menuPtr; /* The menu we are drawing */ TkMenuEntry *mePtr; /* The entry we are drawing */ Drawable d; /* What we are drawing into */ GC gc; /* The gc we are drawing with */ GC indicatorGC; /* The gc for indicator objects */ Tk_Font tkfont; /* The precalculated font */ CONST Tk_FontMetrics *fmPtr; /* The precalculated font metrics */ int x; /* Left edge */ int y; /* Top edge */ int width; int height;{ if ((mePtr->type == CHECK_BUTTON_ENTRY || mePtr->type == RADIO_BUTTON_ENTRY) && mePtr->indicatorOn && mePtr->entryFlags & ENTRY_SELECTED) { RECT rect; GC whichGC; if (mePtr->state != tkNormalUid) { whichGC = gc; } else { whichGC = indicatorGC; } rect.top = y; rect.bottom = y + mePtr->height; rect.left = menuPtr->borderWidth + menuPtr->activeBorderWidth + x; rect.right = mePtr->indicatorSpace + x; if ((mePtr->state == tkDisabledUid) && (menuPtr->disabledFg != NULL) && (versionInfo.dwMajorVersion >= 4)) { RECT hilightRect; COLORREF oldFgColor = whichGC->foreground; whichGC->foreground = GetSysColor(COLOR_3DHILIGHT); hilightRect.top = rect.top + 1; hilightRect.bottom = rect.bottom + 1; hilightRect.left = rect.left + 1; hilightRect.right = rect.right + 1; DrawWindowsSystemBitmap(menuPtr->display, d, whichGC, &hilightRect, OBM_CHECK, 0); whichGC->foreground = oldFgColor; } DrawWindowsSystemBitmap(menuPtr->display, d, whichGC, &rect, OBM_CHECK, 0); if ((mePtr->state == tkDisabledUid) && (menuPtr->disabledImageGC != None) && (versionInfo.dwMajorVersion < 4)) { XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC, rect.left, rect.top, rect.right, rect.bottom); } } }/* *---------------------------------------------------------------------- * * DrawMenuEntryAccelerator -- * * This procedure draws the accelerator part of a menu. We * need to decide what to draw here. Should we replace strings * like "Control", "Command", etc? * * Results: * None. * * Side effects: * Commands are output to X to display the menu in its * current mode. * *---------------------------------------------------------------------- */voidDrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr, activeBorder, x, y, width, height, drawArrow) TkMenu *menuPtr; /* The menu we are drawing */ TkMenuEntry *mePtr; /* The entry we are drawing */ Drawable d; /* What we are drawing into */ GC gc; /* The gc we are drawing with */ Tk_Font tkfont; /* The precalculated font */ CONST Tk_FontMetrics *fmPtr; /* The precalculated font metrics */ Tk_3DBorder activeBorder; /* The border when an item is active */ int x; /* left edge */ int y; /* top edge */ int width; /* Width of menu entry */ int height; /* Height of menu entry */ int drawArrow; /* For cascade menus, whether of not * to draw the arraw. I cannot figure * out Windows' algorithm for where * to draw this. */{ int baseline; int leftEdge = x + mePtr->indicatorSpace + mePtr->labelWidth; baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2; if ((mePtr->state == tkDisabledUid) && (menuPtr->disabledFg != NULL) && ((mePtr->accel != NULL) || ((mePtr->type == CASCADE_ENTRY) && drawArrow))) { if (versionInfo.dwMajorVersion >= 4) { COLORREF oldFgColor = gc->foreground; gc->foreground = GetSysColor(COLOR_3DHILIGHT); if (mePtr->accel != NULL) { Tk_DrawChars(menuPtr->display, d, gc, tkfont, mePtr->accel, mePtr->accelLength, leftEdge + 1, baseline + 1); } if (mePtr->type == CASCADE_ENTRY) { RECT rect; rect.top = y + GetSystemMetrics(SM_CYBORDER) + 1; rect.bottom = y + height - GetSystemMetrics(SM_CYBORDER) + 1; rect.left = x + mePtr->indicatorSpace + mePtr->labelWidth + 1; rect.right = x + width; DrawWindowsSystemBitmap(menuPtr->display, d, gc, &rect, OBM_MNARROW, ALIGN_BITMAP_RIGHT); } gc->foreground = oldFgColor; } } if (mePtr->accel != NULL) { Tk_DrawChars(menuPtr->display, d, gc, tkfont, mePtr->accel, mePtr->accelLength, leftEdge, baseline); } if ((mePtr->state == tkDisabledUid) && (menuPtr->disabledImageGC != None) && (versionInfo.dwMajorVersion < 4)) { XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC, leftEdge, y, width - mePtr->labelWidth - mePtr->indicatorSpace, height); } if ((mePtr->type == CASCADE_ENTRY) && drawArrow) { RECT rect; rect.top = y + GetSystemMetrics(SM_CYBORDER); rect.bottom = y + height - GetSystemMetrics(SM_CYBORDER); rect.left = x + mePtr->indicatorSpace + mePtr->labelWidth; rect.right = x + width - 1; DrawWindowsSystemBitmap(menuPtr->display, d, gc, &rect, OBM_MNARROW, ALIGN_BITMAP_RIGHT); if ((mePtr->state == tkDisabledUid) && (menuPtr->disabledImageGC != None) && (versionInfo.dwMajorVersion < 4)) { XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC, rect.left, rect.top, rect.right, rect.bottom); } }}/* *---------------------------------------------------------------------- * * DrawMenuSeparator -- * * The menu separator is drawn. * * Results: * None. * * Side effects: * Commands are output to X to display the menu in its * current mode. * *---------------------------------------------------------------------- */voidDrawMenuSeparator(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, y, width, height) TkMenu *menuPtr; /* The menu we are drawing */ TkMenuEntry *mePtr; /* The entry we are drawing */ Drawable d; /* What we are drawing into */ GC gc; /* The gc we are drawing with */ Tk_Font tkfont; /* The precalculated font */ CONST Tk_FontMetrics *fmPtr; /* The precalculated font metrics */ int x; /* left edge */ int y; /* top edge */ int width; /* width of item */ int height; /* height of item */{ XPoint points[2]; points[0].x = x; points[0].y = y + height / 2; points[1].x = x + width - 1; points[1].y = points[0].y; Tk_Draw3DPolygon(menuPtr->tkwin, d, menuPtr->border, points, 2, 1, TK_RELIEF_RAISED);}/* *---------------------------------------------------------------------- * * DrawMenuUnderline -- * * On appropriate platforms, draw the underline character for the * menu. * * Results: * None. * * Side effects: * Commands are output to X to display the menu in its * current mode. * *---------------------------------------------------------------------- */static voidDrawMenuUnderline( TkMenu *menuPtr, /* The menu to draw into */ TkMenuEntry *mePtr, /* The entry we are drawing */ Drawable d, /* What we are drawing into */ GC gc, /* The gc to draw into */ Tk_Font tkfont, /* The precalculated font */ CONST Tk_FontMetrics *fmPtr, /* The precalculated font metrics */ int x, /* Left Edge */ int y, /* Top Edge */ int width, /* Width of entry */ int height) /* Height of entry */{ if (mePtr->underline >= 0) { Tk_UnderlineChars(menuPtr->display, d, gc, tkfont, mePtr->label, x + mePtr->indicatorSpace, y + (height + fmPtr->ascent - fmPtr->descent) / 2, mePtr->underline, mePtr->underline + 1); } }/* *-------------------------------------------------------------- * * MenuKeyBindProc -- * * This procedure is invoked when keys related to pulling * down menus is pressed. The corresponding Windows events * are generated and passed to DefWindowProc if appropriate. * * Results: * Always returns TCL_OK. * * Side effects: * The menu system may take over and process user events * for menu input. * *-------------------------------------------------------------- */static intMenuKeyBindProc(clientData, interp, eventPtr, tkwin, keySym) ClientData clientData; /* not used in this proc */ Tcl_Interp *interp; /* The interpreter of the receiving window. */ XEvent *eventPtr; /* The XEvent to process */ Tk_Window tkwin; /* The window receiving the event */ KeySym keySym; /* The key sym that is produced. */{ UINT scanCode; UINT virtualKey; TkWindow *winPtr = (TkWindow *)tkwin; int i; if (eventPtr->type == KeyPress) { switch (keySym) { case XK_Alt_L: scanCode = MapVirtualKey(VK_LMENU, 0); CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)), WM_SYSKEYDOWN, VK_MENU, (scanCode << 16) | (1 << 29)); break; case XK_Alt_R: scanCode = MapVirtualKey(VK_RMENU, 0); CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)), WM_SYSKEYDOWN, VK_MENU, (scanCode << 16) | (1 << 29) | (1 << 24)); break; case XK_F10: scanCode = MapVirtualKey(VK_F10, 0); CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)), WM_SYSKEYDOWN, VK_F10, (scanCode << 16)); break; default: virtualKey = XKeysymToKeycode(winPtr->display, keySym); scanCode = MapVirtualKey(virtualKey, 0); if (0 != scanCode) { CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)), WM_SYSKEYDOWN, virtualKey, ((scanCode << 16) | (1 << 29))); if (eventPtr->xkey.nchars > 0) { for (i = 0; i < eventPtr->xkey.nchars; i++) { CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)), WM_SYSCHAR, eventPtr->xkey.trans_chars[i], ((scanCode << 16) | (1 << 29))); } } } } } else if (eventPtr->type == KeyRelease) { switch (keySym) { case XK_Alt_L: scanCode = MapVirtualKey(VK_LMENU, 0); CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)), WM_SYSKEYUP, VK_MENU, (scanCode << 16) | (1 << 29) | (1 << 30) | (1 << 31)); break; case XK_Alt_R: scanCode = MapVirtualKey(VK_RMENU, 0); CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)), WM_SYSKEYUP, VK_MENU, (scanCode << 16) | (1 << 24) | (0x111 << 29) | (1 << 30) | (1 << 31)); break; case XK_F10: scanCode = MapVirtualKey(VK_F10, 0); CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)), WM_SYSKEYUP, VK_F10, (scanCode << 16) | (1 << 30) | (1 << 31)); break; default: virtualKey = XKeysymToKeycode(winPtr->display, keySym); scanCode = MapVirtualKey(virtualKey, 0); if (0 != scanCode) { CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)), WM_SYSKEYUP, virtualKey, ((scanCode << 16) | (1 << 29) | (1 << 30) | (1 << 31))); } } } return TCL_OK;} /* *-------------------------------------------------------------- * * TkpInitializeMenuBindings -- * * For every interp, initializes the bindings for Windows * menus. Does nothing on Mac or XWindows. * * Results: * None. * * Side effects: * C-level bindings are setup for the interp which will * handle Alt-key sequences for menus without beeping * or interfering with user-defined Alt-key bindings. * *-------------------------------------------------------------- */voidTkpInitializeMenuBindings(interp, bindingTable) Tcl_Interp *interp; /* The interpreter to set. */ Tk_BindingTable bindingTable; /* The table to add to. */{ Tk_Uid uid = Tk_GetUid("all"); /* * We need to set up the bindings for menubars. These have to * recreate windows events, so we need to have a C-level * binding for this. We have to generate the WM_SYSKEYDOWNS * and WM_SYSKEYUPs appropriately. */ TkCreateBindingProcedure(interp, bindingTable, (ClientData)uid, "<Alt_L>", MenuKeyBindProc, NULL, NULL); TkCreateBindingProcedure(interp, bindingTable, (ClientData)uid, "<KeyRelease-Alt_L>", MenuKeyBindProc, NULL, NULL); TkCreateBindingProcedure(interp, bindingTable, (ClientData)uid, "<Alt_R>", MenuKeyBindProc, NULL, NULL); TkCreateBindingProcedure(interp, bindingTable, (ClientData)uid, "<KeyRelease-Alt_R>", MenuKeyBindProc, NULL, NULL); TkCreateBindingProcedure(interp, bindingTable, (ClientData)uid, "<Alt-KeyPress>", MenuKeyBindProc, NULL, NULL); TkCreateBindingProcedure(interp, bindingTable, (ClientData)uid, "<Alt-KeyRelease>", MenuKeyBindProc, NULL, NULL); TkCreateBindingProcedure(interp, bindingTable, (ClientData)uid, "<KeyPress-F10>", MenuKeyBindProc, NULL, NULL); TkCreateBindingProcedure(interp, bindingTable, (ClientData)uid, "<KeyRelease-F10>", MenuKeyBindProc, NULL, NULL);}/* *---------------------------------------------------------------------- * * DrawMenuEntryLabel -- * * This procedure draws the label part of a menu. * * Results: * None. * * Side effects: * Commands are output to X to display the menu in its * current mode. * *---------------------------------------------------------------------- */static voidDrawMenuEntryLabel( TkMenu *menuPtr, /* The menu we are drawing */ TkMenuEntry *mePtr, /* The entry we are drawing */ Drawable d, /* What we are drawing into */ GC gc, /* The gc we are drawing into */ Tk_Font tkfont, /* The precalculated font */ CONST Tk_FontMetrics *fmPtr, /* The precalculated font metrics */ int x, /* left edge */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -