📄 tkwinmenu.c
字号:
for (i = 0; i < mePtr->accelLength; i++) { if (mePtr->accel[i] == '&') { size++; } } itemText = ckalloc(size); if (mePtr->labelLength == 0) { itemText[0] = 0; } else { for (i = 0, j = 0; i < mePtr->labelLength; i++, j++) { if (mePtr->label[i] == '&') { itemText[j++] = '&'; } if (i == mePtr->underline) { itemText[j++] = '&'; } itemText[j] = mePtr->label[i]; } itemText[j] = '\0'; } if (mePtr->accelLength > 0) { strcat(itemText, "\t"); for (i = 0, j = strlen(itemText); i < mePtr->accelLength; i++, j++) { if (mePtr->accel[i] == '&') { itemText[j++] = '&'; } itemText[j] = mePtr->accel[i]; } itemText[j] = '\0'; } } return itemText;}/* *---------------------------------------------------------------------- * * ReconfigureWindowsMenu -- * * Tears down and rebuilds the platform-specific part of this menu. * * Results: * None. * * Side effects: * Configuration information get set for mePtr; old resources * get freed, if any need it. * *---------------------------------------------------------------------- */static voidReconfigureWindowsMenu( ClientData clientData) /* The menu we are rebuilding */{ TkMenu *menuPtr = (TkMenu *) clientData; TkMenuEntry *mePtr; HMENU winMenuHdl = (HMENU) menuPtr->platformData; char *itemText = NULL; LPCTSTR lpNewItem; UINT flags; UINT itemID; int i, count, systemMenu = 0, base; int width, height; if (NULL == winMenuHdl) { return; } /* * Reconstruct the entire menu. Takes care of nasty system menu and index * problem. * */ if ((menuPtr->menuType == MENUBAR) && (menuPtr->parentTopLevelPtr != NULL)) { width = Tk_Width(menuPtr->parentTopLevelPtr); height = Tk_Height(menuPtr->parentTopLevelPtr); } base = (menuPtr->menuFlags & MENU_SYSTEM_MENU) ? 7 : 0; count = GetMenuItemCount(winMenuHdl); for (i = base; i < count; i++) { RemoveMenu(winMenuHdl, base, MF_BYPOSITION); } count = menuPtr->numEntries; for (i = 0; i < count; i++) { mePtr = menuPtr->entries[i]; lpNewItem = NULL; flags = MF_BYPOSITION; itemID = 0; if ((menuPtr->menuType == MENUBAR) && (mePtr->type == TEAROFF_ENTRY)) { continue; } if (mePtr->type == SEPARATOR_ENTRY) { flags |= MF_SEPARATOR; } else { itemText = GetEntryText(mePtr); if ((menuPtr->menuType == MENUBAR) || (menuPtr->menuFlags & MENU_SYSTEM_MENU)) { lpNewItem = itemText; } else { lpNewItem = (LPCTSTR) mePtr; flags |= MF_OWNERDRAW; } /* * Set enabling and disabling correctly. */ if (mePtr->state == tkDisabledUid) { flags |= MF_DISABLED; } /* * Set the check mark for check entries and radio entries. */ if (((mePtr->type == CHECK_BUTTON_ENTRY) || (mePtr->type == RADIO_BUTTON_ENTRY)) && (mePtr->entryFlags & ENTRY_SELECTED)) { flags |= MF_CHECKED; } if (mePtr->columnBreak) { flags |= MF_MENUBREAK; } itemID = (int) mePtr->platformEntryData; if ((mePtr->type == CASCADE_ENTRY) && (mePtr->childMenuRefPtr != NULL) && (mePtr->childMenuRefPtr->menuPtr != NULL)) { HMENU childMenuHdl = (HMENU) mePtr->childMenuRefPtr->menuPtr ->platformData; if (childMenuHdl != NULL) { itemID = (UINT) childMenuHdl; flags |= MF_POPUP; } if ((menuPtr->menuType == MENUBAR) && !(mePtr->childMenuRefPtr->menuPtr->menuFlags & MENU_SYSTEM_MENU)) { TkMenuReferences *menuRefPtr; TkMenu *systemMenuPtr = mePtr->childMenuRefPtr ->menuPtr; char *systemMenuName = ckalloc(strlen( Tk_PathName(menuPtr->masterMenuPtr->tkwin)) + strlen(".system") + 1); strcpy(systemMenuName, Tk_PathName(menuPtr->masterMenuPtr->tkwin)); strcat(systemMenuName, ".system"); menuRefPtr = TkFindMenuReferences(menuPtr->interp, systemMenuName); if ((menuRefPtr != NULL) && (menuRefPtr->menuPtr != NULL) && (menuPtr->parentTopLevelPtr != NULL) && (systemMenuPtr->masterMenuPtr == menuRefPtr->menuPtr)) { HMENU systemMenuHdl = (HMENU) systemMenuPtr->platformData; HWND wrapper = TkWinGetWrapperWindow(menuPtr ->parentTopLevelPtr); if (wrapper != NULL) { DestroyMenu(systemMenuHdl); systemMenuHdl = GetSystemMenu(wrapper, FALSE); systemMenuPtr->menuFlags |= MENU_SYSTEM_MENU; systemMenuPtr->platformData = (TkMenuPlatformData) systemMenuHdl; if (!(systemMenuPtr->menuFlags & MENU_RECONFIGURE_PENDING)) { systemMenuPtr->menuFlags |= MENU_RECONFIGURE_PENDING; Tcl_DoWhenIdle(ReconfigureWindowsMenu, (ClientData) systemMenuPtr); } } } ckfree(systemMenuName); } if (mePtr->childMenuRefPtr->menuPtr->menuFlags & MENU_SYSTEM_MENU) { systemMenu++; } } } if (!systemMenu) { InsertMenu(winMenuHdl, 0xFFFFFFFF, flags, itemID, lpNewItem); } if (itemText != NULL) { ckfree(itemText); itemText = NULL; } } if ((menuPtr->menuType == MENUBAR) && (menuPtr->parentTopLevelPtr != NULL)) { DrawMenuBar(TkWinGetWrapperWindow(menuPtr->parentTopLevelPtr)); Tk_GeometryRequest(menuPtr->parentTopLevelPtr, width, height); } menuPtr->menuFlags &= ~(MENU_RECONFIGURE_PENDING);}/* *---------------------------------------------------------------------- * * TkpPostMenu -- * * Posts a menu on the screen * * Results: * None. * * Side effects: * The menu is posted and handled. * *---------------------------------------------------------------------- */intTkpPostMenu(interp, menuPtr, x, y) Tcl_Interp *interp; TkMenu *menuPtr; int x; int y;{ HMENU winMenuHdl = (HMENU) menuPtr->platformData; int result, flags; RECT noGoawayRect; POINT point; Tk_Window parentWindow = Tk_Parent(menuPtr->tkwin); int oldServiceMode = Tcl_GetServiceMode(); inPostMenu++; if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) { Tcl_CancelIdleCall(ReconfigureWindowsMenu, (ClientData) menuPtr); ReconfigureWindowsMenu((ClientData) menuPtr); } result = TkPreprocessMenu(menuPtr); if (result != TCL_OK) { inPostMenu--; return result; } /* * The post commands could have deleted the menu, which means * we are dead and should go away. */ if (menuPtr->tkwin == NULL) { inPostMenu--; return TCL_OK; } if (NULL == parentWindow) { noGoawayRect.top = y - 50; noGoawayRect.bottom = y + 50; noGoawayRect.left = x - 50; noGoawayRect.right = x + 50; } else { int left, top; Tk_GetRootCoords(parentWindow, &left, &top); noGoawayRect.left = left; noGoawayRect.top = top; noGoawayRect.bottom = noGoawayRect.top + Tk_Height(parentWindow); noGoawayRect.right = noGoawayRect.left + Tk_Width(parentWindow); } Tcl_SetServiceMode(TCL_SERVICE_NONE); /* * Make an assumption here. If the right button is down, * then we want to track it. Otherwise, track the left mouse button. */ flags = TPM_LEFTALIGN; if (GetSystemMetrics(SM_SWAPBUTTON)) { if (GetAsyncKeyState(VK_LBUTTON) < 0) { flags |= TPM_RIGHTBUTTON; } else { flags |= TPM_LEFTBUTTON; } } else { if (GetAsyncKeyState(VK_RBUTTON) < 0) { flags |= TPM_RIGHTBUTTON; } else { flags |= TPM_LEFTBUTTON; } } TrackPopupMenu(winMenuHdl, flags, x, y, 0, menuHWND, &noGoawayRect); Tcl_SetServiceMode(oldServiceMode); GetCursorPos(&point); Tk_PointerEvent(NULL, point.x, point.y); if (inPostMenu) { inPostMenu = 0; } return TCL_OK;}/* *---------------------------------------------------------------------- * * TkpMenuNewEntry -- * * Adds a pointer to a new menu entry structure with the platform- * specific fields filled in. * * Results: * Standard TCL error. * * Side effects: * A new command ID is allocated and stored in the platformEntryData * field of mePtr. * *---------------------------------------------------------------------- */intTkpMenuNewEntry(mePtr) TkMenuEntry *mePtr;{ int commandID; TkMenu *menuPtr = mePtr->menuPtr; if (GetNewID(mePtr, &commandID) != TCL_OK) { return TCL_ERROR; } if (!(menuPtr->menuFlags & MENU_RECONFIGURE_PENDING)) { menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING; Tcl_DoWhenIdle(ReconfigureWindowsMenu, (ClientData) menuPtr); } mePtr->platformEntryData = (TkMenuPlatformEntryData) commandID; return TCL_OK;}/* *---------------------------------------------------------------------- * * TkWinMenuProc -- * * The window proc for the dummy window we put popups in. This allows * is to post a popup whether or not we know what the parent window * is. * * Results: * Returns whatever is appropriate for the message in question. * * Side effects: * Normal side-effect for windows messages. * *---------------------------------------------------------------------- */static LRESULT CALLBACKTkWinMenuProc(hwnd, message, wParam, lParam) HWND hwnd; UINT message; WPARAM wParam; LPARAM lParam;{ LRESULT lResult; if (!TkWinHandleMenuEvent(&hwnd, &message, &wParam, &lParam, &lResult)) { lResult = DefWindowProc(hwnd, message, wParam, lParam); } return lResult;}/* *---------------------------------------------------------------------- * * TkWinHandleMenuEvent -- * * Filters out menu messages from messages passed to a top-level. * Will respond appropriately to WM_COMMAND, WM_MENUSELECT, * WM_MEASUREITEM, WM_DRAWITEM * * Result: * Returns 1 if this handled the message; 0 if it did not. * * Side effects: * All of the parameters may be modified so that the caller can * think it is getting a different message. plResult points to * the result that should be returned to windows from this message. * *---------------------------------------------------------------------- */intTkWinHandleMenuEvent(phwnd, pMessage, pwParam, plParam, plResult) HWND *phwnd; UINT *pMessage; WPARAM *pwParam; LPARAM *plParam; LRESULT *plResult;{ Tcl_HashEntry *hashEntryPtr; int returnResult = 0; TkMenu *menuPtr; TkMenuEntry *mePtr; switch (*pMessage) { case WM_INITMENU: TkMenuInit(); hashEntryPtr = Tcl_FindHashEntry(&winMenuTable, (char *) *pwParam); if (hashEntryPtr != NULL) { oldServiceMode = Tcl_SetServiceMode(TCL_SERVICE_ALL); menuPtr = (TkMenu *) Tcl_GetHashValue(hashEntryPtr); modalMenuPtr = menuPtr; if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) { Tcl_CancelIdleCall(ReconfigureWindowsMenu, (ClientData) menuPtr); ReconfigureWindowsMenu((ClientData) menuPtr); } if (!inPostMenu) { Tcl_Interp *interp; int code; interp = menuPtr->interp; Tcl_Preserve((ClientData)interp); code = TkPreprocessMenu(menuPtr); if ((code != TCL_OK) && (code != TCL_CONTINUE) && (code != TCL_BREAK)) { Tcl_AddErrorInfo(interp, "\n (menu preprocess)"); Tcl_BackgroundError(interp); } Tcl_Release((ClientData)interp); } TkActivateMenuEntry(menuPtr, -1); *plResult = 0; returnResult = 1; } else { modalMenuPtr = NULL; } break; case WM_SYSCOMMAND: case WM_COMMAND: { TkMenuInit(); if (HIWORD(*pwParam) != 0) { break; } hashEntryPtr = Tcl_FindHashEntry(&commandTable, (char *)LOWORD(*pwParam)); if (hashEntryPtr == NULL) { break; } mePtr = (TkMenuEntry *) Tcl_GetHashValue(hashEntryPtr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -