1 /*
2  * PROJECT:         ReactOS API tests
3  * LICENSE:         LGPLv2.1+ - See COPYING.LIB in the top level directory
4  * PURPOSE:         Test for SetParent
5  * PROGRAMMERS:     Thomas Faber <thomas.faber@reactos.org>
6  */
7 
8 #include <apitest.h>
9 
10 #include <winuser.h>
11 #include <msgtrace.h>
12 #include <user32testhelpers.h>
13 
14 static HWND hWndList[5 + 1];
15 static const int hWndCount = sizeof(hWndList) / sizeof(hWndList[0]) - 1;
16 static DWORD dwThreadId;
17 
18 #define ok_hwnd(val, exp) do                                                                    \
19     {                                                                                           \
20         HWND _val = (val), _exp = (exp);                                                        \
21         int _ival = get_iwnd(_val, FALSE);                                                      \
22         int _iexp = get_iwnd(_exp, FALSE);                                                      \
23         ok(_val == _exp, #val " = %p (%d), expected %p (%d)\n", _val, _ival, _exp, _iexp);      \
24     } while (0)
25 
26 static
27 int
28 get_iwnd(
29     _In_ HWND hWnd,
30     _In_ BOOL set)
31 {
32     int i;
33     if (!hWnd)
34         return 0;
35     for (i = 1; i <= hWndCount; i++)
36     {
37         if (hWndList[i] == hWnd)
38             return i;
39     }
40     if (!set)
41         return 0;
42     for (i = 1; i <= hWndCount; i++)
43     {
44         if (hWndList[i] == NULL)
45         {
46             hWndList[i] = hWnd;
47             return i;
48         }
49     }
50     ok(0, "Too many windows!\n");
51     return 0;
52 }
53 
54 static
55 BOOL
56 CALLBACK
57 EnumProc(
58     _In_ HWND hWnd,
59     _In_ LPARAM lParam)
60 {
61     HWND hLookingFor = (HWND)lParam;
62     return hWnd != hLookingFor;
63 }
64 
65 static
66 LRESULT
67 CALLBACK
68 WndProc(
69     _In_ HWND hWnd,
70     _In_ UINT message,
71     _In_ WPARAM wParam,
72     _In_ LPARAM lParam)
73 {
74     HWND hTest;
75     int iwnd = get_iwnd(hWnd, TRUE);
76 
77     ok(GetCurrentThreadId() == dwThreadId, "Thread 0x%lx instead of 0x%lx\n", GetCurrentThreadId(), dwThreadId);
78     if (message > WM_USER || IsDWmMsg(message) || IseKeyMsg(message))
79         return DefWindowProcW(hWnd, message, wParam, lParam);
80 
81     RECORD_MESSAGE(iwnd, message, SENT, wParam, lParam);
82 
83     switch(message)
84     {
85     case WM_DESTROY:
86         if (GetParent(hWnd))
87         {
88             /* child window */
89             ok(EnumThreadWindows(dwThreadId, EnumProc, (LPARAM)hWnd), "Child window %p (%d) enumerated\n", hWnd, iwnd);
90             ok(!EnumChildWindows(GetParent(hWnd), EnumProc, (LPARAM)hWnd), "Child window %p (%d) not enumerated\n", hWnd, iwnd);
91             ok(!EnumThreadWindows(dwThreadId, EnumProc, (LPARAM)GetParent(hWnd)), "Parent window of %p (%d) not enumerated\n", hWnd, iwnd);
92         }
93         else
94         {
95             /* top-level window */
96             ok(!EnumThreadWindows(dwThreadId, EnumProc, (LPARAM)hWnd), "Window %p (%d) not enumerated in WM_DESTROY\n", hWnd, iwnd);
97         }
98         if (hWnd == hWndList[3])
99         {
100             hTest = SetParent(hWndList[4], hWndList[2]);
101             ok_hwnd(hTest, hWndList[1]);
102             hTest = SetParent(hWndList[5], hWndList[1]);
103             ok_hwnd(hTest, hWndList[2]);
104 
105             ok_hwnd(GetParent(hWndList[1]), NULL);
106             ok_hwnd(GetParent(hWndList[2]), NULL);
107             ok_hwnd(GetParent(hWndList[3]), hWndList[1]);
108             ok_hwnd(GetParent(hWndList[4]), hWndList[2]);
109             ok_hwnd(GetParent(hWndList[5]), hWndList[1]);
110         }
111         break;
112     }
113 
114     return DefWindowProcW(hWnd, message, wParam, lParam);
115 }
116 
117 
118 START_TEST(SetParent)
119 {
120     HWND hWnd;
121     MSG msg;
122 
123     SetCursorPos(0,0);
124 
125     dwThreadId = GetCurrentThreadId();
126     hWndList[0] = INVALID_HANDLE_VALUE;
127     RegisterSimpleClass(WndProc, L"CreateTest");
128 
129     hWnd = CreateWindowExW(0, L"CreateTest", NULL, 0,  10, 10, 20, 20,  NULL, NULL, 0, NULL);
130     ok(hWnd != NULL, "CreateWindow failed\n");
131     ok(hWnd == hWndList[1], "Got %p, expected %p\n", hWnd, hWndList[1]);
132 
133     hWnd = CreateWindowExW(0, L"CreateTest", NULL, 0,  40, 10, 20, 20,  NULL, NULL, 0, NULL);
134     ok(hWnd != NULL, "CreateWindow failed\n");
135     ok(hWnd == hWndList[2], "Got %p, expected %p\n", hWnd, hWndList[2]);
136 
137     hWnd = CreateWindowExW(0, L"CreateTest", NULL, WS_CHILD,  60, 10, 20, 20, hWndList[1], NULL, 0, NULL);
138     ok(hWnd != NULL, "CreateWindow failed\n");
139     ok(hWnd == hWndList[3], "Got %p, expected %p\n", hWnd, hWndList[3]);
140 
141     hWnd = CreateWindowExW(0, L"CreateTest", NULL, WS_CHILD,  80, 10, 20, 20, hWndList[1], NULL, 0, NULL);
142     ok(hWnd != NULL, "CreateWindow failed\n");
143     ok(hWnd == hWndList[4], "Got %p, expected %p\n", hWnd, hWndList[4]);
144 
145     hWnd = CreateWindowExW(0, L"CreateTest", NULL, WS_CHILD,  60, 10, 20, 20, hWndList[2], NULL, 0, NULL);
146     ok(hWnd != NULL, "CreateWindow failed\n");
147     ok(hWnd == hWndList[5], "Got %p, expected %p\n", hWnd, hWndList[5]);
148 
149 trace("\n");
150     while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE ))
151     {
152         int iwnd = get_iwnd(msg.hwnd, FALSE);
153         if(!(msg.message > WM_USER || IsDWmMsg(msg.message) || IseKeyMsg(msg.message)))
154             RECORD_MESSAGE(iwnd, msg.message, POST, 0, 0);
155         DispatchMessageA( &msg );
156     }
157 trace("\n");
158     TRACE_CACHE();
159 trace("\n");
160 
161     ok_hwnd(GetParent(hWndList[1]), NULL);
162     ok_hwnd(GetParent(hWndList[2]), NULL);
163     ok_hwnd(GetParent(hWndList[3]), hWndList[1]);
164     ok_hwnd(GetParent(hWndList[4]), hWndList[1]);
165     ok_hwnd(GetParent(hWndList[5]), hWndList[2]);
166 
167     DestroyWindow(hWndList[1]);
168     ok(!IsWindow(hWndList[1]), "\n");
169     ok( IsWindow(hWndList[2]), "\n");
170     ok(!IsWindow(hWndList[3]), "\n");
171     ok( IsWindow(hWndList[4]), "\n");
172     ok(!IsWindow(hWndList[5]), "\n");
173 
174     ok_hwnd(GetParent(hWndList[1]), NULL);
175     ok_hwnd(GetParent(hWndList[2]), NULL);
176     ok_hwnd(GetParent(hWndList[3]), NULL);
177     ok_hwnd(GetParent(hWndList[4]), hWndList[2]);
178     ok_hwnd(GetParent(hWndList[5]), NULL);
179 
180 trace("\n");
181     while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE ))
182     {
183         int iwnd = get_iwnd(msg.hwnd, FALSE);
184         if(!(msg.message > WM_USER || IsDWmMsg(msg.message) || IseKeyMsg(msg.message)))
185             RECORD_MESSAGE(iwnd, msg.message, POST, 0, 0);
186         DispatchMessageA( &msg );
187     }
188 trace("\n");
189     TRACE_CACHE();
190  }
191