From 201c969f84546b2625fba0eff2015313f3813ab7 Mon Sep 17 00:00:00 2001 From: patthoyts Date: Mon, 23 Feb 2009 10:18:38 +0000 Subject: [Patch 2507419] fixes the image drawing bug on windows menus. --- ChangeLog | 5 ++++ win/tkWinMenu.c | 85 +++++++++++++++++++++++++++++++++++++-------------------- 2 files changed, 61 insertions(+), 29 deletions(-) diff --git a/ChangeLog b/ChangeLog index fd5f8c5..d725fbc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2009-02-23 Pat Thoyts + + * win/tkWinMenu.c: Applied patch for menu image display bug + [Bug 1329198, 456299] [Patch 2507419] (cjmcdonald) + 2009-02-22 Pat Thoyts * win/tkWinCursor.c: Applied patch to support stock Win32 help arrow diff --git a/win/tkWinMenu.c b/win/tkWinMenu.c index aa3e046..b88e57d 100644 --- a/win/tkWinMenu.c +++ b/win/tkWinMenu.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: tkWinMenu.c,v 1.63 2009/01/28 20:47:49 nijtmans Exp $ + * RCS: @(#) $Id: tkWinMenu.c,v 1.64 2009/02/23 10:18:38 patthoyts Exp $ */ #define OEMRESOURCE @@ -35,9 +35,6 @@ #define ALIGN_BITMAP_TOP 0x00000004 #define ALIGN_BITMAP_BOTTOM 0x00000008 -#ifndef TPM_NOANIMATION -#define TPM_NOANIMATION 0x4000L -#endif /* * Platform-specific menu flags: @@ -715,12 +712,11 @@ TkpPostMenu( int x, int y) { HMENU winMenuHdl = (HMENU) menuPtr->platformData; - int i, result, flags; + int result, flags; RECT noGoawayRect; POINT point; Tk_Window parentWindow = Tk_Parent(menuPtr->tkwin); int oldServiceMode = Tcl_GetServiceMode(); - TkMenuEntry *mePtr; ThreadSpecificData *tsdPtr = (ThreadSpecificData *) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); @@ -783,18 +779,6 @@ TkpPostMenu( } } - /* - * Disable menu animation if an image is present, as clipping isn't - * handled correctly with temp DCs. [Bug 1329198] - */ - for (i = 0; i < menuPtr->numEntries; i++) { - mePtr = menuPtr->entries[i]; - if (mePtr->image != NULL) { - flags |= TPM_NOANIMATION; - break; - } - } - TrackPopupMenu(winMenuHdl, flags, x, y, 0, tsdPtr->menuHWND, &noGoawayRect); Tcl_SetServiceMode(oldServiceMode); @@ -2429,7 +2413,7 @@ TkpConfigureMenuEntry( void TkpDrawMenuEntry( TkMenuEntry *mePtr, /* The entry to draw */ - Drawable d, /* What to draw into */ + Drawable menuDrawable, /* Menu to draw into */ Tk_Font tkfont, /* Precalculated font for menu */ const Tk_FontMetrics *menuMetricsPtr, /* Precalculated metrics for menu */ @@ -2448,8 +2432,38 @@ TkpDrawMenuEntry( const Tk_FontMetrics *fmPtr; Tk_FontMetrics entryMetrics; int padY = (menuPtr->menuType == MENUBAR) ? 3 : 0; - int adjustedY = y + padY; + int adjustedX, adjustedY; int adjustedHeight = height - 2 * padY; + TkWinDrawable memWinDraw; + TkWinDCState dcState; + HBITMAP oldBitmap; + Drawable d; + HDC memDc, menuDc; + + /* + * If the menu entry includes an image then draw the entry into a + * compatible bitmap first. This avoids problems with clipping on + * animated menus. [Bug 1329198] + */ + + if (mePtr->image != NULL) { + menuDc = TkWinGetDrawableDC(menuPtr->display, menuDrawable, &dcState); + + memDc = CreateCompatibleDC(menuDc); + oldBitmap = SelectObject(memDc, + CreateCompatibleBitmap(menuDc, width, height) ); + + memWinDraw.type = TWD_WINDC; + memWinDraw.winDC.hdc = memDc; + d = (Drawable)&memWinDraw; + adjustedX = 0; + adjustedY = padY; + + } else { + d = menuDrawable; + adjustedX = x; + adjustedY = y + padY; + } /* * Choose the gc for drawing the foreground part of the entry. @@ -2521,26 +2535,39 @@ TkpDrawMenuEntry( */ DrawMenuEntryBackground(menuPtr, mePtr, d, activeBorder, - bgBorder, x, y, width, height); + bgBorder, adjustedX, adjustedY-padY, width, height); if (mePtr->type == SEPARATOR_ENTRY) { DrawMenuSeparator(menuPtr, mePtr, d, gc, tkfont, - fmPtr, x, adjustedY, width, adjustedHeight); + fmPtr, adjustedX, adjustedY, width, adjustedHeight); } else if (mePtr->type == TEAROFF_ENTRY) { - DrawTearoffEntry(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, adjustedY, - width, adjustedHeight); + DrawTearoffEntry(menuPtr, mePtr, d, gc, tkfont, fmPtr, + adjustedX, adjustedY, width, adjustedHeight); } else { - DrawMenuEntryLabel(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, adjustedY, - width, adjustedHeight); + DrawMenuEntryLabel(menuPtr, mePtr, d, gc, tkfont, fmPtr, + adjustedX, adjustedY, width, adjustedHeight); DrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr, - activeBorder, x, adjustedY, width, adjustedHeight); + activeBorder, adjustedX, adjustedY, width, adjustedHeight); DrawMenuEntryArrow(menuPtr, mePtr, d, gc, - activeBorder, x, adjustedY, width, adjustedHeight, drawArrow); + activeBorder, adjustedX, adjustedY, width, adjustedHeight, + drawArrow); if (!mePtr->hideMargin) { DrawMenuEntryIndicator(menuPtr, mePtr, d, gc, indicatorGC, tkfont, - fmPtr, x, adjustedY, width, adjustedHeight); + fmPtr, adjustedX, adjustedY, width, adjustedHeight); } } + + /* + * Copy the entry contents from the temporary bitmap to the menu. + */ + + if (mePtr->image != NULL) { + BitBlt(menuDc, x, y, width, height, memDc, 0, 0, SRCCOPY); + DeleteObject(SelectObject(memDc, oldBitmap)); + DeleteDC(memDc); + + TkWinReleaseDrawableDC(menuDrawable, menuDc, &dcState); + } } /* -- cgit v0.12