These patches aim to fix the bug 47018.
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/comctl32/static.c | 92 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 76 insertions(+), 16 deletions(-)
diff --git a/dlls/comctl32/static.c b/dlls/comctl32/static.c index 5cc02ced97..d08710c06f 100644 --- a/dlls/comctl32/static.c +++ b/dlls/comctl32/static.c @@ -36,6 +36,7 @@ #include "winuser.h" #include "commctrl.h"
+#include "wine/heap.h" #include "wine/debug.h"
#include "comctl32.h" @@ -50,10 +51,16 @@ static void STATIC_PaintBitmapfn( HWND hwnd, HDC hdc, DWORD style ); static void STATIC_PaintEnhMetafn( HWND hwnd, HDC hdc, DWORD style ); static void STATIC_PaintEtchedfn( HWND hwnd, HDC hdc, DWORD style );
-/* offsets for GetWindowLong for static private information */ -#define HFONT_GWL_OFFSET 0 -#define HICON_GWL_OFFSET (sizeof(HFONT)) -#define STATIC_EXTRA_BYTES (HICON_GWL_OFFSET + sizeof(HICON)) +struct static_extra_info +{ + HFONT hfont; + union + { + HICON hicon; + HBITMAP hbitmap; + HENHMETAFILE hemf; + } image; +};
typedef void (*pfPaint)( HWND hwnd, HDC hdc, DWORD style );
@@ -80,6 +87,18 @@ static const pfPaint staticPaintFunc[SS_TYPEMASK+1] = STATIC_PaintEtchedfn, /* SS_ETCHEDFRAME */ };
+static struct static_extra_info *get_extra_ptr( HWND hwnd, BOOL force ) +{ + struct static_extra_info *extra = (struct static_extra_info *)GetWindowLongPtrW( hwnd, 0 ); + if (!extra && force) + { + extra = heap_alloc_zero( sizeof(*extra) ); + if (extra) + SetWindowLongPtrW( hwnd, 0, (ULONG_PTR)extra ); + } + return extra; +} + static BOOL get_icon_size( HICON handle, SIZE *size ) { ICONINFO info; @@ -111,6 +130,7 @@ static HICON STATIC_SetIcon( HWND hwnd, HICON hicon, DWORD style ) { HICON prevIcon; SIZE size; + struct static_extra_info *extra;
if ((style & SS_TYPEMASK) != SS_ICON) return 0; if (hicon && !get_icon_size( hicon, &size )) @@ -118,7 +138,12 @@ static HICON STATIC_SetIcon( HWND hwnd, HICON hicon, DWORD style ) WARN("hicon != 0, but invalid\n"); return 0; } - prevIcon = (HICON)SetWindowLongPtrW( hwnd, HICON_GWL_OFFSET, (LONG_PTR)hicon ); + + extra = get_extra_ptr( hwnd, TRUE ); + if (!extra) return 0; + + prevIcon = extra->image.hicon; + extra->image.hicon = hicon; if (hicon && !(style & SS_CENTERIMAGE) && !(style & SS_REALSIZECONTROL)) { /* Windows currently doesn't implement SS_RIGHTJUST */ @@ -146,6 +171,7 @@ static HICON STATIC_SetIcon( HWND hwnd, HICON hicon, DWORD style ) static HBITMAP STATIC_SetBitmap( HWND hwnd, HBITMAP hBitmap, DWORD style ) { HBITMAP hOldBitmap; + struct static_extra_info *extra;
if ((style & SS_TYPEMASK) != SS_BITMAP) return 0; if (hBitmap && GetObjectType(hBitmap) != OBJ_BITMAP) @@ -153,7 +179,12 @@ static HBITMAP STATIC_SetBitmap( HWND hwnd, HBITMAP hBitmap, DWORD style ) WARN("hBitmap != 0, but it's not a bitmap\n"); return 0; } - hOldBitmap = (HBITMAP)SetWindowLongPtrW( hwnd, HICON_GWL_OFFSET, (LONG_PTR)hBitmap ); + + extra = get_extra_ptr( hwnd, TRUE ); + if (!extra) return 0; + + hOldBitmap = extra->image.hbitmap; + extra->image.hbitmap = hBitmap; if (hBitmap && !(style & SS_CENTERIMAGE) && !(style & SS_REALSIZECONTROL)) { BITMAP bm; @@ -183,13 +214,23 @@ static HBITMAP STATIC_SetBitmap( HWND hwnd, HBITMAP hBitmap, DWORD style ) */ static HENHMETAFILE STATIC_SetEnhMetaFile( HWND hwnd, HENHMETAFILE hEnhMetaFile, DWORD style ) { + HENHMETAFILE old_hemf; + struct static_extra_info *extra; + if ((style & SS_TYPEMASK) != SS_ENHMETAFILE) return 0; if (hEnhMetaFile && GetObjectType(hEnhMetaFile) != OBJ_ENHMETAFILE) { WARN("hEnhMetaFile != 0, but it's not an enhanced metafile\n"); return 0; } - return (HENHMETAFILE)SetWindowLongPtrW( hwnd, HICON_GWL_OFFSET, (LONG_PTR)hEnhMetaFile ); + + extra = get_extra_ptr( hwnd, TRUE ); + if (!extra) return 0; + + old_hemf = extra->image.hemf; + extra->image.hemf = hEnhMetaFile; + + return old_hemf; }
/*********************************************************************** @@ -200,6 +241,8 @@ static HENHMETAFILE STATIC_SetEnhMetaFile( HWND hwnd, HENHMETAFILE hEnhMetaFile, */ static HANDLE STATIC_GetImage( HWND hwnd, WPARAM wParam, DWORD style ) { + struct static_extra_info *extra; + switch (style & SS_TYPEMASK) { case SS_ICON: @@ -215,7 +258,22 @@ static HANDLE STATIC_GetImage( HWND hwnd, WPARAM wParam, DWORD style ) default: return NULL; } - return (HANDLE)GetWindowLongPtrW( hwnd, HICON_GWL_OFFSET ); + + extra = get_extra_ptr( hwnd, FALSE ); + return extra ? extra->image.hbitmap : 0; +} + +static void STATIC_SetFont( HWND hwnd, HFONT hfont ) +{ + struct static_extra_info *extra = get_extra_ptr( hwnd, TRUE ); + if (extra) + extra->hfont = hfont; +} + +static HFONT STATIC_GetFont( HWND hwnd ) +{ + struct static_extra_info *extra = get_extra_ptr( hwnd, FALSE ); + return extra ? extra->hfont : 0; }
/*********************************************************************** @@ -327,6 +385,8 @@ static LRESULT CALLBACK STATIC_WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, case WM_NCDESTROY: if (style == SS_ICON) { + struct static_extra_info *extra = get_extra_ptr( hwnd, FALSE ); + heap_free( extra ); /* * FIXME * DestroyIcon32( STATIC_SetIcon( wndPtr, 0 ) ); @@ -423,14 +483,14 @@ static LRESULT CALLBACK STATIC_WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, case WM_SETFONT: if (hasTextStyle( full_style )) { - SetWindowLongPtrW( hwnd, HFONT_GWL_OFFSET, wParam ); + STATIC_SetFont( hwnd, (HFONT)wParam ); if (LOWORD(lParam)) RedrawWindow( hwnd, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_ALLCHILDREN ); } break;
case WM_GETFONT: - return GetWindowLongPtrW( hwnd, HFONT_GWL_OFFSET ); + return (LRESULT)STATIC_GetFont( hwnd );
case WM_NCHITTEST: if (full_style & SS_NOTIFY) @@ -508,7 +568,7 @@ static void STATIC_PaintOwnerDrawfn( HWND hwnd, HDC hdc, DWORD style ) dis.itemData = 0; GetClientRect( hwnd, &dis.rcItem );
- font = (HFONT)GetWindowLongPtrW( hwnd, HFONT_GWL_OFFSET ); + font = STATIC_GetFont( hwnd ); if (font) oldFont = SelectObject( hdc, font ); SendMessageW( GetParent(hwnd), WM_CTLCOLORSTATIC, (WPARAM)hdc, (LPARAM)hwnd ); SendMessageW( GetParent(hwnd), WM_DRAWITEM, id, (LPARAM)&dis ); @@ -572,7 +632,7 @@ static void STATIC_PaintTextfn( HWND hwnd, HDC hdc, DWORD style ) format |= DT_SINGLELINE | DT_WORD_ELLIPSIS; }
- if ((hFont = (HFONT)GetWindowLongPtrW( hwnd, HFONT_GWL_OFFSET ))) + if ((hFont = STATIC_GetFont( hwnd ))) hOldFont = SelectObject( hdc, hFont );
/* SS_SIMPLE controls: WM_CTLCOLORSTATIC is sent, but the returned @@ -668,7 +728,7 @@ static void STATIC_PaintIconfn( HWND hwnd, HDC hdc, DWORD style )
GetClientRect( hwnd, &rc ); hbrush = STATIC_SendWmCtlColorStatic(hwnd, hdc); - hIcon = (HICON)GetWindowLongPtrW( hwnd, HICON_GWL_OFFSET ); + hIcon = STATIC_GetImage( hwnd, IMAGE_ICON, style ); if (!hIcon || !get_icon_size( hIcon, &size )) { FillRect(hdc, &rc, hbrush); @@ -698,7 +758,7 @@ static void STATIC_PaintBitmapfn(HWND hwnd, HDC hdc, DWORD style )
hbrush = STATIC_SendWmCtlColorStatic(hwnd, hdc);
- if ((hBitmap = (HBITMAP)GetWindowLongPtrW( hwnd, HICON_GWL_OFFSET )) + if ((hBitmap = STATIC_GetImage( hwnd, IMAGE_BITMAP, style )) && (GetObjectType(hBitmap) == OBJ_BITMAP) && (hMemDC = CreateCompatibleDC( hdc ))) { @@ -742,7 +802,7 @@ static void STATIC_PaintEnhMetafn(HWND hwnd, HDC hdc, DWORD style ) GetClientRect(hwnd, &rc); hbrush = STATIC_SendWmCtlColorStatic(hwnd, hdc); FillRect(hdc, &rc, hbrush); - if ((hEnhMetaFile = (HENHMETAFILE)GetWindowLongPtrW( hwnd, HICON_GWL_OFFSET ))) + if ((hEnhMetaFile = STATIC_GetImage( hwnd, IMAGE_ENHMETAFILE, style ))) { /* The control's current font is not selected into the device context! */ @@ -779,7 +839,7 @@ void STATIC_Register(void) wndClass.style = CS_DBLCLKS | CS_PARENTDC | CS_GLOBALCLASS; wndClass.lpfnWndProc = STATIC_WindowProc; wndClass.cbClsExtra = 0; - wndClass.cbWndExtra = STATIC_EXTRA_BYTES; + wndClass.cbWndExtra = sizeof(struct static_extra_info *); wndClass.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW); wndClass.hbrBackground = NULL; wndClass.lpszClassName = WC_STATICW;