1 /* Unit test suite for static controls.
2  *
3  * Copyright 2007 Google (Mikolaj Zalewski)
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19 
20 #include "precomp.h"
21 
22 #define TODO_COUNT 1
23 
24 #define CTRL_ID 1995
25 
26 static HWND hMainWnd;
27 
28 #define expect_eq(expr, value, type, fmt) { type val = expr; ok(val == (value), #expr " expected " fmt " got " fmt "\n", (value), val); }
29 
30 static int g_nReceivedColorStatic = 0;
31 
32 /* try to make sure pending X events have been processed before continuing */
33 static void flush_events(void)
34 {
35     MSG msg;
36     int diff = 200;
37     int min_timeout = 100;
38     DWORD time = GetTickCount() + diff;
39 
40     while (diff > 0)
41     {
42         if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
43         while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
44         diff = time - GetTickCount();
45     }
46 }
47 
48 static HWND build_static(DWORD style)
49 {
50     return CreateWindowA("static", "Test", WS_VISIBLE|WS_CHILD|style, 5, 5, 100, 100, hMainWnd, (HMENU)CTRL_ID, NULL, 0);
51 }
52 
53 static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
54 {
55     switch (msg)
56     {
57     case WM_CTLCOLORSTATIC:
58         {
59             HDC hdc = (HDC)wparam;
60             HRGN hrgn = CreateRectRgn(0, 0, 1, 1);
61             ok(GetClipRgn(hdc, hrgn) == 1, "Static controls during a WM_CTLCOLORSTATIC must have a clipping region\n");
62             DeleteObject(hrgn);
63             g_nReceivedColorStatic++;
64             return (LRESULT) GetStockObject(BLACK_BRUSH);
65         }
66         break;
67     }
68 
69     return DefWindowProcA(hwnd, msg, wparam, lparam);
70 }
71 
72 static void test_updates(int style, int flags)
73 {
74     RECT r1 = {20, 20, 30, 30};
75     HWND hStatic = build_static(style);
76     int exp;
77 
78     flush_events();
79     trace("Testing style 0x%x\n", style);
80     g_nReceivedColorStatic = 0;
81     /* during each update parent WndProc will test the WM_CTLCOLORSTATIC message */
82     InvalidateRect(hMainWnd, NULL, FALSE);
83     UpdateWindow(hMainWnd);
84     InvalidateRect(hMainWnd, &r1, FALSE);
85     UpdateWindow(hMainWnd);
86     InvalidateRect(hStatic, &r1, FALSE);
87     UpdateWindow(hStatic);
88     InvalidateRect(hStatic, NULL, FALSE);
89     UpdateWindow(hStatic);
90 
91     if( (style & SS_TYPEMASK) == SS_BITMAP) {
92         HDC hdc = GetDC( hStatic);
93         COLORREF colour = GetPixel( hdc, 10, 10);
94         ok ( colour != 0, "pixel should NOT be painted black!\n");
95     }
96     if (style != SS_ETCHEDHORZ && style != SS_ETCHEDVERT)
97         exp = 4;
98     else
99         exp = 1; /* SS_ETCHED* seems to send WM_CTLCOLORSTATIC only sometimes */
100 
101     if (flags & TODO_COUNT)
102         todo_wine { expect_eq(g_nReceivedColorStatic, exp, int, "%d"); }
103     else if ((style & SS_TYPEMASK) == SS_ICON || (style & SS_TYPEMASK) == SS_BITMAP)
104         ok( g_nReceivedColorStatic == exp, "expected %u got %u\n", exp, g_nReceivedColorStatic );
105     else
106         expect_eq(g_nReceivedColorStatic, exp, int, "%d");
107     DestroyWindow(hStatic);
108 }
109 
110 static void test_set_text(void)
111 {
112     HWND hStatic = build_static(SS_SIMPLE);
113     char buffA[10];
114 
115     GetWindowTextA(hStatic, buffA, sizeof(buffA));
116     ok(!strcmp(buffA, "Test"), "got wrong text %s\n", buffA);
117 
118     SetWindowTextA(hStatic, NULL);
119     GetWindowTextA(hStatic, buffA, sizeof(buffA));
120     ok(buffA[0] == 0, "got wrong text %s\n", buffA);
121 
122     DestroyWindow(hStatic);
123 }
124 
125 START_TEST(static)
126 {
127     static const char szClassName[] = "testclass";
128     WNDCLASSEXA  wndclass;
129 
130     wndclass.cbSize         = sizeof(wndclass);
131     wndclass.style          = CS_HREDRAW | CS_VREDRAW;
132     wndclass.lpfnWndProc    = WndProc;
133     wndclass.cbClsExtra     = 0;
134     wndclass.cbWndExtra     = 0;
135     wndclass.hInstance      = GetModuleHandleA(NULL);
136     wndclass.hIcon          = LoadIconA(NULL, (LPCSTR)IDI_APPLICATION);
137     wndclass.hIconSm        = LoadIconA(NULL, (LPCSTR)IDI_APPLICATION);
138     wndclass.hCursor        = LoadCursorA(NULL, (LPCSTR)IDC_ARROW);
139     wndclass.hbrBackground  = GetStockObject(WHITE_BRUSH);
140     wndclass.lpszClassName  = szClassName;
141     wndclass.lpszMenuName   = NULL;
142     RegisterClassExA(&wndclass);
143 
144     hMainWnd = CreateWindowA(szClassName, "Test", WS_OVERLAPPEDWINDOW, 0, 0, 500, 500, NULL, NULL, GetModuleHandleA(NULL), NULL);
145     ShowWindow(hMainWnd, SW_SHOW);
146 
147     test_updates(0, 0);
148     test_updates(SS_SIMPLE, 0);
149     test_updates(SS_ICON, 0);
150     test_updates(SS_BITMAP, 0);
151     test_updates(SS_BITMAP | SS_CENTERIMAGE, 0);
152     test_updates(SS_BLACKRECT, TODO_COUNT);
153     test_updates(SS_WHITERECT, TODO_COUNT);
154     test_updates(SS_ETCHEDHORZ, TODO_COUNT);
155     test_updates(SS_ETCHEDVERT, TODO_COUNT);
156     test_set_text();
157 
158     DestroyWindow(hMainWnd);
159 }
160