diff --git a/dlls/user32/static.c b/dlls/user32/static.c index b70754aef40..1e6c1d9e31b 100644 --- a/dlls/user32/static.c +++ b/dlls/user32/static.c @@ -323,13 +323,17 @@ static VOID STATIC_TryPaintFcn(HWND hwnd, LONG full_style) static HBRUSH STATIC_SendWmCtlColorStatic(HWND hwnd, HDC hdc) { - HBRUSH hBrush = (HBRUSH) SendMessageW( GetParent(hwnd), + HBRUSH hBrush; + HWND parent = GetParent(hwnd); + + if (!parent) parent = hwnd; + hBrush = (HBRUSH) SendMessageW( parent, WM_CTLCOLORSTATIC, (WPARAM)hdc, (LPARAM)hwnd ); if (!hBrush) /* did the app forget to call DefWindowProc ? */ { /* FIXME: DefWindowProc should return different colors if a manifest is present */ - hBrush = (HBRUSH)DefWindowProcW(GetParent(hwnd), WM_CTLCOLORSTATIC, + hBrush = (HBRUSH)DefWindowProcW( parent, WM_CTLCOLORSTATIC, (WPARAM)hdc, (LPARAM)hwnd); } return hBrush; @@ -399,6 +403,10 @@ static LRESULT StaticWndProc_common( HWND hwnd, UINT uMsg, WPARAM wParam, else return unicode ? DefWindowProcW(hwnd, uMsg, wParam, lParam) : DefWindowProcA(hwnd, uMsg, wParam, lParam); + case WM_ERASEBKGND: + /* do all painting in WM_PAINT like Windows does */ + return 1; + case WM_PRINTCLIENT: case WM_PAINT: { @@ -496,7 +504,7 @@ static LRESULT StaticWndProc_common( HWND hwnd, UINT uMsg, WPARAM wParam, { SetWindowLongPtrW( hwnd, HFONT_GWL_OFFSET, wParam ); if (LOWORD(lParam)) - STATIC_TryPaintFcn( hwnd, full_style ); + RedrawWindow( hwnd, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_ALLCHILDREN ); } break; @@ -612,7 +620,7 @@ static void STATIC_PaintTextfn( HWND hwnd, HDC hdc, DWORD style ) HBRUSH hBrush; HFONT hFont, hOldFont = NULL; WORD wFormat; - INT len; + INT len, buf_size; WCHAR *text; GetClientRect( hwnd, &rc); @@ -645,7 +653,7 @@ static void STATIC_PaintTextfn( HWND hwnd, HDC hdc, DWORD style ) if (style & SS_NOPREFIX) wFormat |= DT_NOPREFIX; - + if ((style & SS_TYPEMASK) != SS_SIMPLE) { if (style & SS_CENTERIMAGE) @@ -666,17 +674,22 @@ static void STATIC_PaintTextfn( HWND hwnd, HDC hdc, DWORD style ) /* SS_SIMPLE controls: WM_CTLCOLORSTATIC is sent, but the returned brush is not used */ hBrush = STATIC_SendWmCtlColorStatic(hwnd, hdc); - + if ((style & SS_TYPEMASK) != SS_SIMPLE) { FillRect( hdc, &rc, hBrush ); if (!IsWindowEnabled(hwnd)) SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT)); } - if (!(len = SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 ))) return; - if (!(text = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return; - SendMessageW( hwnd, WM_GETTEXT, len + 1, (LPARAM)text ); - + buf_size = 256; + if (!(text = HeapAlloc( GetProcessHeap(), 0, buf_size * sizeof(WCHAR) ))) return; + + while ((len = InternalGetWindowText( hwnd, text, buf_size )) == buf_size - 1) + { + buf_size *= 2; + if (!(text = HeapReAlloc( GetProcessHeap(), 0, text, buf_size * sizeof(WCHAR) ))) return; + } + if (((style & SS_TYPEMASK) == SS_SIMPLE) && (style & SS_NOPREFIX)) { /* Windows uses the faster ExtTextOut() to draw the text and @@ -689,9 +702,9 @@ static void STATIC_PaintTextfn( HWND hwnd, HDC hdc, DWORD style ) { DrawTextW( hdc, text, -1, &rc, wFormat ); } - + HeapFree( GetProcessHeap(), 0, text ); - + if (hFont) SelectObject( hdc, hOldFont ); } diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c index bdb156bd44c..8df68391ebb 100644 --- a/dlls/user32/tests/msg.c +++ b/dlls/user32/tests/msg.c @@ -4217,6 +4217,98 @@ static void test_button_messages(void) DestroyWindow(hwnd); } +/****************** static message test *************************/ +static const struct message WmSetFontStaticSeq[] = +{ + { WM_SETFONT, sent }, + { WM_PAINT, sent|defwinproc }, + { WM_ERASEBKGND, sent|defwinproc }, + { WM_CTLCOLORSTATIC, sent|defwinproc }, + { 0 } +}; + +static WNDPROC old_static_proc; + +static LRESULT CALLBACK static_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + static long defwndproc_counter = 0; + LRESULT ret; + struct message msg; + + trace("static: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam); + + /* explicitly ignore WM_GETICON message */ + if (message == WM_GETICON) return 0; + + msg.message = message; + msg.flags = sent|wparam|lparam; + if (defwndproc_counter) msg.flags |= defwinproc; + msg.wParam = wParam; + msg.lParam = lParam; + add_message(&msg); + + + defwndproc_counter++; + ret = CallWindowProcA(old_static_proc, hwnd, message, wParam, lParam); + defwndproc_counter--; + + return ret; +} + +static void subclass_static(void) +{ + WNDCLASSA cls; + + if (!GetClassInfoA(0, "static", &cls)) assert(0); + + old_static_proc = cls.lpfnWndProc; + + cls.hInstance = GetModuleHandle(0); + cls.lpfnWndProc = static_hook_proc; + cls.lpszClassName = "my_static_class"; + if (!RegisterClassA(&cls)) assert(0); +} + +static void test_static_messages(void) +{ + /* FIXME: make as comprehensive as the button message test */ + static const struct + { + DWORD style; + DWORD dlg_code; + const struct message *setfont; + } static_ctrl[] = { + { SS_LEFT, DLGC_STATIC, + WmSetFontStaticSeq } + }; + unsigned int i; + HWND hwnd; + DWORD dlg_code; + + subclass_static(); + + for (i = 0; i < sizeof(static_ctrl)/sizeof(static_ctrl[0]); i++) + { + hwnd = CreateWindowExA(0, "my_static_class", "test", static_ctrl[i].style | WS_POPUP, + 0, 0, 50, 14, 0, 0, 0, NULL); + ok(hwnd != 0, "Failed to create static window\n"); + + dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0); + ok(dlg_code == static_ctrl[i].dlg_code, "%u: wrong dlg_code %08x\n", i, dlg_code); + + ShowWindow(hwnd, SW_SHOW); + UpdateWindow(hwnd); + SetFocus(0); + flush_sequence(); + + trace("static style %08x\n", static_ctrl[i].style); + SendMessage(hwnd, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), TRUE); + ok_sequence(static_ctrl[i].setfont, "WM_SETFONT on a static", FALSE); + + DestroyWindow(hwnd); + } +} + /************* painting message test ********************/ void dump_region(HRGN hrgn) @@ -8137,6 +8229,7 @@ START_TEST(msg) invisible_parent_tests(); test_mdi_messages(); test_button_messages(); + test_static_messages(); test_paint_messages(); test_interthread_messages(); test_message_conversion();