diff options
author | mdejong <mdejong> | 2004-09-23 00:56:13 (GMT) |
---|---|---|
committer | mdejong <mdejong> | 2004-09-23 00:56:13 (GMT) |
commit | a5886e42f370fd93341943130884c3f271c4d119 (patch) | |
tree | a5ef654dd2cffd06d968ff35befb088f3e4a8054 /win | |
parent | de0d8e4322d9601ff5a95bf50c8d2c9d0065accf (diff) | |
download | tk-a5886e42f370fd93341943130884c3f271c4d119.zip tk-a5886e42f370fd93341943130884c3f271c4d119.tar.gz tk-a5886e42f370fd93341943130884c3f271c4d119.tar.bz2 |
* generic/tkInt.decls: Add decl for TkWinGetPlatformTheme.
It is only defined under Win32.
* generic/tkIntPlatDecls.h: Regen.
* generic/tkStubInit.c: Regen.
* win/tkWinInt.h: Define TK_THEME_WIN_CLASSIC and
TK_THEME_WIN_XP.
* win/tkWinMenu.c (DrawMenuEntryAccelerator, DrawMenuEntryLabel):
Draw a disabled 3D text highlight for the accelerator only
with the Win95/98 look. Same goes for the menu entry text.
* win/tkWinX.c (TkWinGetPlatformId, TkWinGetPlatformTheme):
Automatically detect the Windows theme in use and return
either TK_THEME_WIN_CLASSIC or TK_THEME_WIN_XP when the
TkWinGetPlatformTheme function is invoked.
[Patch 866194]
* win/tkWinMenu.c: only provide a submenu handle when the
MF_POPUP flag is given, fixing a recently-introduced crash
when submenus are disabled. Also better error checking for
this sort of situation in the future.
* win/tkWinMenu.c (ReconfigureWindowsMenu): Fix drawing of a disabled
(TkWinHandleMenuEvent, DrawMenuEntryArrow): cascade menu arrow. Tk was
displaying a disabled cascade menu arrow in black instead of
gray. This was caused by a bug in the Win32 code for user drawn
menu items. The fix is to avoid telling Windows that the menu item
is a cascade type and then draw the gray arrow bitmap on our own.
[Patch 865842]
* win/tkWinMenu.c (DrawWindowsSystemBitmap): Fix a strange Win32
bug where the logical coordinates returned by a call to DPtoLP are
wrong the first time a menu is posted. This bug manifested itself
by drawing the bitmap in the wrong place in a menu. The fix was
to pass the newly created DC instead of the DC from the window.
* win/tkWinMenu.c (DrawMenuEntryAccelerator):
(DrawMenuEntryLabel): When drawing the label text and accelerator
text for a disabled menu entry be sure to draw a 3D highlight.
The only exception to this is when a disabled menu entry is
highlighted, in that case do not draw a 3D hightlight.
* win/tkWinMenu.c (DrawMenuEntryAccelerator, DrawMenuEntryArrow):
Move the unused menu arrow drawing code in
DrawMenuEntryAccelerator into a new function named
DrawMenuEntryArrow. This makes no functional change but it will
make it easier to fix things in the future.
Diffstat (limited to 'win')
-rw-r--r-- | win/tkWinInt.h | 8 | ||||
-rw-r--r-- | win/tkWinMenu.c | 191 | ||||
-rw-r--r-- | win/tkWinX.c | 57 |
3 files changed, 205 insertions, 51 deletions
diff --git a/win/tkWinInt.h b/win/tkWinInt.h index 0266099..7a1d1d7 100644 --- a/win/tkWinInt.h +++ b/win/tkWinInt.h @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWinInt.h,v 1.14.2.3 2004/09/17 23:36:16 hobbs Exp $ + * RCS: @(#) $Id: tkWinInt.h,v 1.14.2.4 2004/09/23 00:56:15 mdejong Exp $ */ #ifndef _TKWININT @@ -210,5 +210,11 @@ EXTERN TkWinProcs *tkWinProcs; extern Tcl_Encoding TkWinGetKeyInputEncoding _ANSI_ARGS_((void)); extern Tcl_Encoding TkWinGetUnicodeEncoding _ANSI_ARGS_((void)); +/* + * Values returned by TkWinGetPlatformTheme. + */ +#define TK_THEME_WIN_CLASSIC 1 +#define TK_THEME_WIN_XP 2 + #endif /* _TKWININT */ diff --git a/win/tkWinMenu.c b/win/tkWinMenu.c index aea7d73..8dec5d8 100644 --- a/win/tkWinMenu.c +++ b/win/tkWinMenu.c @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWinMenu.c,v 1.21.2.2 2004/05/03 23:23:42 hobbs Exp $ + * RCS: @(#) $Id: tkWinMenu.c,v 1.21.2.3 2004/09/23 00:56:15 mdejong Exp $ */ #define OEMRESOURCE @@ -91,6 +91,11 @@ static void DrawMenuEntryAccelerator _ANSI_ARGS_(( Drawable d, GC gc, Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr, Tk_3DBorder activeBorder, int x, int y, + int width, int height)); +static void DrawMenuEntryArrow _ANSI_ARGS_(( + TkMenu *menuPtr, TkMenuEntry *mePtr, + Drawable d, GC gc, + Tk_3DBorder activeBorder, int x, int y, int width, int height, int drawArrow)); static void DrawMenuEntryBackground _ANSI_ARGS_(( TkMenu *menuPtr, TkMenuEntry *mePtr, @@ -124,7 +129,7 @@ static void DrawWindowsSystemBitmap _ANSI_ARGS_(( Display *display, Drawable drawable, GC gc, CONST RECT *rectPtr, int bitmapID, int alignFlags)); -static void FreeID _ANSI_ARGS_((int commandID)); +static void FreeID _ANSI_ARGS_((WORD commandID)); static TCHAR * GetEntryText _ANSI_ARGS_((TkMenuEntry *mePtr)); static void GetMenuAccelGeometry _ANSI_ARGS_((TkMenu *menuPtr, TkMenuEntry *mePtr, Tk_Font tkfont, @@ -146,7 +151,7 @@ static void GetTearoffEntryGeometry _ANSI_ARGS_((TkMenu *menuPtr, CONST Tk_FontMetrics *fmPtr, int *widthPtr, int *heightPtr)); static int GetNewID _ANSI_ARGS_((TkMenuEntry *mePtr, - int *menuIDPtr)); + WORD *menuIDPtr)); static int MenuKeyBindProc _ANSI_ARGS_(( ClientData clientData, Tcl_Interp *interp, XEvent *eventPtr, @@ -186,7 +191,7 @@ static LRESULT CALLBACK TkWinMenuProc _ANSI_ARGS_((HWND hwnd, static int GetNewID(mePtr, menuIDPtr) TkMenuEntry *mePtr; /* The menu we are working with */ - int *menuIDPtr; /* The resulting id */ + WORD *menuIDPtr; /* The resulting id */ { int found = 0; int newEntry; @@ -215,7 +220,7 @@ GetNewID(mePtr, menuIDPtr) if (found) { Tcl_SetHashValue(commandEntryPtr, (char *) mePtr); - *menuIDPtr = (int) returnID; + *menuIDPtr = returnID; tsdPtr->lastCommandID = returnID; return TCL_OK; } else { @@ -241,7 +246,7 @@ GetNewID(mePtr, menuIDPtr) static void FreeID(commandID) - int commandID; + WORD commandID; { ThreadSpecificData *tsdPtr = (ThreadSpecificData *) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); @@ -414,7 +419,7 @@ TkpDestroyMenuEntry(mePtr) Tcl_DoWhenIdle(ReconfigureWindowsMenu, (ClientData) menuPtr); } } - FreeID((int) mePtr->platformEntryData); + FreeID((WORD) mePtr->platformEntryData); mePtr->platformEntryData = NULL; } @@ -572,6 +577,7 @@ ReconfigureWindowsMenu( || (menuPtr->menuFlags & MENU_SYSTEM_MENU)) { Tcl_WinUtfToTChar(itemText, -1, &translatedText); lpNewItem = Tcl_DStringValue(&translatedText); + flags |= MF_STRING; } else { lpNewItem = (LPCTSTR) mePtr; flags |= MF_OWNERDRAW; @@ -611,15 +617,27 @@ ReconfigureWindowsMenu( flags |= MF_MENUBREAK; } - itemID = (int) mePtr->platformEntryData; + itemID = (UINT) 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; + /* + * Win32 draws the popup arrow in the wrong color + * for a disabled cascade menu, so do it by hand. + * Given it is disabled, there's no need for it to + * be connected to its child. + */ + if (mePtr->state != ENTRY_DISABLED) { + flags |= MF_POPUP; + /* + * If the MF_POPUP flag is set, then the id + * is interpreted as the handle of a submenu. + */ + itemID = (UINT) childMenuHdl; + } } if ((menuPtr->menuType == MENUBAR) && !(mePtr->childMenuRefPtr->menuPtr->menuFlags @@ -815,7 +833,7 @@ int TkpMenuNewEntry(mePtr) TkMenuEntry *mePtr; { - int commandID; + WORD commandID; TkMenu *menuPtr = mePtr->menuPtr; if (GetNewID(mePtr, &commandID) != TCL_OK) { @@ -1064,6 +1082,7 @@ TkWinHandleMenuEvent(phwnd, pMessage, pwParam, plParam, plResult) TkWinDrawable *twdPtr; LPDRAWITEMSTRUCT itemPtr = (LPDRAWITEMSTRUCT) *plParam; Tk_FontMetrics fontMetrics; + int drawArrow = 0; if (itemPtr != NULL) { Tk_Font tkfont; @@ -1092,6 +1111,12 @@ TkWinHandleMenuEvent(phwnd, pMessage, pwParam, plParam, plResult) } else { mePtr->entryFlags &= ~ENTRY_PLATFORM_FLAG1; } + /* Also, set the drawArrow flag for a disabled cascade + ** menu since we need to draw the arrow ourselves. + */ + if (mePtr->type == CASCADE_ENTRY) { + drawArrow = 1; + } } tkfont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr); @@ -1100,7 +1125,7 @@ TkWinHandleMenuEvent(phwnd, pMessage, pwParam, plParam, plResult) &fontMetrics, itemPtr->rcItem.left, itemPtr->rcItem.top, itemPtr->rcItem.right - itemPtr->rcItem.left, itemPtr->rcItem.bottom - - itemPtr->rcItem.top, 0, 0); + - itemPtr->rcItem.top, 0, drawArrow); ckfree((char *) twdPtr); *plResult = 1; @@ -1148,6 +1173,9 @@ TkWinHandleMenuEvent(phwnd, pMessage, pwParam, plParam, plResult) if ((mePtr == NULL) || (mePtr->state == ENTRY_DISABLED)) { TkActivateMenuEntry(menuPtr, -1); } else { + if (mePtr->index >= menuPtr->numEntries) { + Tcl_Panic("Trying to activate an entry which doesn't exist."); + } TkActivateMenuEntry(menuPtr, mePtr->index); } MenuSelectEvent(menuPtr); @@ -1464,7 +1492,7 @@ DrawWindowsSystemBitmap(display, drawable, gc, rectPtr, bitmapID, alignFlags) GetObject(bitmap, sizeof(BITMAP), &bm); ptSize.x = bm.bmWidth; ptSize.y = bm.bmHeight; - DPtoLP(hdc, &ptSize, 1); + DPtoLP(scratchDC, &ptSize, 1); ptOrg.y = ptOrg.x = 0; DPtoLP(scratchDC, &ptOrg, 1); @@ -1571,15 +1599,17 @@ DrawMenuEntryIndicator(menuPtr, mePtr, d, gc, indicatorGC, tkfont, fmPtr, x, * * DrawMenuEntryAccelerator -- * - * This procedure draws the accelerator part of a menu. We - * need to decide what to draw here. Should we replace strings + * This procedure draws the accelerator part of a menu. + * For example, the string "CTRL-Z" could be drawn to + * to the right of the label text for an Undo menu entry. + * 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 + * Commands are output to display the menu in its * current mode. * *---------------------------------------------------------------------- @@ -1587,7 +1617,7 @@ DrawMenuEntryIndicator(menuPtr, mePtr, d, gc, indicatorGC, tkfont, fmPtr, x, void DrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr, - activeBorder, x, y, width, height, drawArrow) + activeBorder, 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 */ @@ -1599,10 +1629,6 @@ DrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr, 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; @@ -1614,45 +1640,97 @@ DrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr, baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2; - if ((mePtr->state == ENTRY_DISABLED) && (menuPtr->disabledFgPtr != NULL) - && ((mePtr->accelPtr != NULL) - || ((mePtr->type == CASCADE_ENTRY) && drawArrow))) { - COLORREF oldFgColor = gc->foreground; + /* Draw disabled 3D text highlight only with the Win95/98 look. */ - gc->foreground = GetSysColor(COLOR_3DHILIGHT); - if (mePtr->accelPtr != NULL) { - Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel, - mePtr->accelLength, leftEdge + 1, baseline + 1); - } + if (TkWinGetPlatformTheme() == TK_THEME_WIN_CLASSIC) { + if ((mePtr->state == ENTRY_DISABLED) && (menuPtr->disabledFgPtr != NULL) + && (mePtr->accelPtr != NULL)) { + COLORREF oldFgColor = gc->foreground; - 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 = GetSysColor(COLOR_3DHILIGHT); + if ((mePtr->accelPtr != NULL) && + ((mePtr->entryFlags & ENTRY_PLATFORM_FLAG1) == 0)) { + Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel, + mePtr->accelLength, leftEdge + 1, baseline + 1); + } + gc->foreground = oldFgColor; } - gc->foreground = oldFgColor; } if (mePtr->accelPtr != NULL) { Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel, mePtr->accelLength, leftEdge, baseline); } +} + +/* + *---------------------------------------------------------------------- + * + * DrawMenuEntryArrow -- + * + * This function draws the arrow bitmap on the right side of a + * a menu entry. This function is currently unused. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ - if ((mePtr->type == CASCADE_ENTRY) && drawArrow) { - RECT rect; +void +DrawMenuEntryArrow(menuPtr, mePtr, d, gc, + 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_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. */ +{ + COLORREF oldFgColor; + COLORREF oldBgColor; + RECT rect; + + if (!drawArrow || (mePtr->type != CASCADE_ENTRY) || + (mePtr->state != ENTRY_DISABLED)) + return; + + oldFgColor = gc->foreground; + oldBgColor = gc->background; - 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); + /* Set bitmap bg to highlight color if the menu is highlighted */ + if (mePtr->entryFlags & ENTRY_PLATFORM_FLAG1) { + XColor *activeBgColor = Tk_3DBorderColor(Tk_Get3DBorderFromObj( + mePtr->menuPtr->tkwin, + (mePtr->activeBorderPtr == NULL) ? + mePtr->menuPtr->activeBorderPtr : + mePtr->activeBorderPtr)); + gc->background = activeBgColor->pixel; } + + gc->foreground = GetSysColor(COLOR_GRAYTEXT); + + rect.top = y + GetSystemMetrics(SM_CYBORDER); + rect.bottom = y + height - GetSystemMetrics(SM_CYBORDER); + rect.left = x + mePtr->indicatorSpace + mePtr->labelWidth; + rect.right = x + width; + + DrawWindowsSystemBitmap(menuPtr->display, d, gc, &rect, OBM_MNARROW, + ALIGN_BITMAP_RIGHT); + + gc->foreground = oldFgColor; + gc->background = oldBgColor; + return; } /* @@ -2045,13 +2123,26 @@ DrawMenuEntryLabel( if (mePtr->labelLength > 0) { int baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2; char *label = Tcl_GetStringFromObj(mePtr->labelPtr, NULL); + if (TkWinGetPlatformTheme() == TK_THEME_WIN_CLASSIC) { + /* Win 95/98 systems draw disabled menu text with a + * 3D highlight, unless the menu item is highlighted */ + if ((mePtr->state == ENTRY_DISABLED) && + ((mePtr->entryFlags & ENTRY_PLATFORM_FLAG1) == 0)) { + COLORREF oldFgColor = gc->foreground; + gc->foreground = GetSysColor(COLOR_3DHILIGHT); + Tk_DrawChars(menuPtr->display, d, gc, tkfont, label, + mePtr->labelLength, leftEdge + textXOffset + 1, + baseline + textYOffset + 1); + gc->foreground = oldFgColor; + } + } Tk_DrawChars(menuPtr->display, d, gc, tkfont, label, mePtr->labelLength, leftEdge + textXOffset, baseline + textYOffset); DrawMenuUnderline(menuPtr, mePtr, d, gc, tkfont, fmPtr, x + textXOffset, y + textYOffset, width, height); - } + } } if (mePtr->state == ENTRY_DISABLED) { @@ -2308,6 +2399,8 @@ TkpDrawMenuEntry(mePtr, d, tkfont, menuMetricsPtr, x, y, width, height, DrawMenuEntryLabel(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, adjustedY, width, adjustedHeight); DrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr, + activeBorder, x, adjustedY, width, adjustedHeight); + DrawMenuEntryArrow(menuPtr, mePtr, d, gc, activeBorder, x, adjustedY, width, adjustedHeight, drawArrow); if (!mePtr->hideMargin) { DrawMenuEntryIndicator(menuPtr, mePtr, d, gc, indicatorGC, tkfont, diff --git a/win/tkWinX.c b/win/tkWinX.c index 550bc34..94b3c6c 100644 --- a/win/tkWinX.c +++ b/win/tkWinX.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWinX.c,v 1.25.2.2 2004/05/03 22:40:58 hobbs Exp $ + * RCS: @(#) $Id: tkWinX.c,v 1.25.2.3 2004/09/23 00:56:15 mdejong Exp $ */ #include "tkWinInt.h" @@ -84,6 +84,7 @@ static HINSTANCE tkInstance = NULL; /* Application instance handle. */ static int childClassInitialized; /* Registered child class? */ static WNDCLASS childClass; /* Window class for child windows. */ static int tkPlatformId = 0; /* version of Windows platform */ +static int tkWinTheme = 0; /* See TkWinGetPlatformTheme */ static Tcl_Encoding keyInputEncoding = NULL;/* The current character * encoding for keyboard input */ static int keyInputCharset = -1; /* The Win32 CHARSET for the keyboard @@ -356,6 +357,33 @@ TkWinGetPlatformId() os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&os); tkPlatformId = os.dwPlatformId; + + /* Set tkWinTheme to be TK_THEME_WIN_XP or TK_THEME_WIN_CLASSIC. + * The TK_THEME_WIN_CLASSIC could be set even when running + * under XP if the windows classic theme was selected. */ + if ((os.dwPlatformId == VER_PLATFORM_WIN32_NT) && + (os.dwMajorVersion == 5 && os.dwMinorVersion == 1)) { + HKEY hKey; + LPCSTR szSubKey = TEXT("Control Panel\\Appearance"); + LPCSTR szCurrent = TEXT("Current"); + DWORD dwSize = 200; + char pBuffer[200]; + memset(pBuffer, 0, dwSize); + if (RegOpenKeyEx(HKEY_CURRENT_USER, szSubKey, 0L, + KEY_READ, &hKey) != ERROR_SUCCESS) { + tkWinTheme = TK_THEME_WIN_XP; + } else { + RegQueryValueEx(hKey, szCurrent, NULL, NULL, pBuffer, &dwSize); + RegCloseKey(hKey); + if (strcmp(pBuffer, "Windows Standard") == 0) { + tkWinTheme = TK_THEME_WIN_CLASSIC; + } else { + tkWinTheme = TK_THEME_WIN_XP; + } + } + } else { + tkWinTheme = TK_THEME_WIN_CLASSIC; + } } return tkPlatformId; } @@ -363,6 +391,33 @@ TkWinGetPlatformId() /* *---------------------------------------------------------------------- * + * TkWinGetPlatformTheme -- + * + * Return the Windows drawing style we should be using. + * + * Results: + * The return value is one of: + * TK_THEME_WIN_CLASSIC 95/98/NT or XP in classic mode + * TK_THEME_WIN_XP XP not in classic mode + * + * Side effects: + * Could invoke TkWinGetPlatformId. + * + *---------------------------------------------------------------------- + */ + +int +TkWinGetPlatformTheme() +{ + if (tkPlatformId == 0) { + TkWinGetPlatformId(); + } + return tkWinTheme; +} + +/* + *---------------------------------------------------------------------- + * * TkGetDefaultScreenName -- * * Returns the name of the screen that Tk should use during |