comctl32: Switch to using a structure for extra storage.

Signed-off-by: Dmitry Timoshkov <dmitry@baikal.ru>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
feature/deterministic
Dmitry Timoshkov 2020-02-10 16:31:39 +08:00 committed by Alexandre Julliard
parent fa72a28c51
commit 0caf5af18e
1 changed files with 76 additions and 16 deletions

View File

@ -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;