1 /* 2 * Unit tests for window message handling 3 * 4 * Copyright 1999 Ove Kaaven 5 * Copyright 2003 Dimitrie O. Paun 6 * Copyright 2004,2005,2016 Dmitry Timoshkov 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public 10 * License as published by the Free Software Foundation; either 11 * version 2.1 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with this library; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 21 */ 22 23 #ifndef __REACTOS__ 24 #define _WIN32_WINNT 0x0600 /* For WM_CHANGEUISTATE,QS_RAWINPUT,WM_DWMxxxx */ 25 #define WINVER 0x0600 /* for WM_GETTITLEBARINFOEX */ 26 #endif 27 28 #include <assert.h> 29 #include <limits.h> 30 #include <stdarg.h> 31 #include <stdio.h> 32 33 #include "windef.h" 34 #include "winbase.h" 35 #include "wingdi.h" 36 #include "winuser.h" 37 #include "winnls.h" 38 #include "dbt.h" 39 40 #include "wine/test.h" 41 42 #define MDI_FIRST_CHILD_ID 2004 43 44 /* undocumented SWP flags - from SDK 3.1 */ 45 #define SWP_NOCLIENTSIZE 0x0800 46 #define SWP_NOCLIENTMOVE 0x1000 47 #define SWP_STATECHANGED 0x8000 48 49 #define SW_NORMALNA 0xCC /* undoc. flag in MinMaximize */ 50 51 #ifndef WM_KEYF1 52 #define WM_KEYF1 0x004d 53 #endif 54 55 #ifndef WM_SYSTIMER 56 #define WM_SYSTIMER 0x0118 57 #endif 58 59 #define WND_PARENT_ID 1 60 #define WND_POPUP_ID 2 61 #define WND_CHILD_ID 3 62 63 #ifndef WM_LBTRACKPOINT 64 #define WM_LBTRACKPOINT 0x0131 65 #endif 66 67 #ifdef __i386__ 68 #define ARCH "x86" 69 #elif defined __x86_64__ 70 #define ARCH "amd64" 71 #elif defined __arm__ 72 #define ARCH "arm" 73 #elif defined __aarch64__ 74 #define ARCH "arm64" 75 #else 76 #define ARCH "none" 77 #endif 78 79 static BOOL (WINAPI *pActivateActCtx)(HANDLE,ULONG_PTR*); 80 static HANDLE (WINAPI *pCreateActCtxW)(PCACTCTXW); 81 static BOOL (WINAPI *pDeactivateActCtx)(DWORD,ULONG_PTR); 82 static BOOL (WINAPI *pGetCurrentActCtx)(HANDLE *); 83 static BOOL (WINAPI *pQueryActCtxW)(DWORD,HANDLE,void*,ULONG,void*,SIZE_T,SIZE_T*); 84 static void (WINAPI *pReleaseActCtx)(HANDLE); 85 86 /* encoded DRAWITEMSTRUCT into an LPARAM */ 87 typedef struct 88 { 89 union 90 { 91 struct 92 { 93 UINT type : 4; /* ODT_* flags */ 94 UINT ctl_id : 4; /* Control ID */ 95 UINT item_id : 4; /* Menu item ID */ 96 UINT action : 4; /* ODA_* flags */ 97 UINT state : 16; /* ODS_* flags */ 98 } item; 99 LPARAM lp; 100 } u; 101 } DRAW_ITEM_STRUCT; 102 103 /* encoded MEASUREITEMSTRUCT into a WPARAM */ 104 typedef struct 105 { 106 union 107 { 108 struct 109 { 110 UINT CtlType : 4; 111 UINT CtlID : 4; 112 UINT itemID : 4; 113 UINT wParam : 20; 114 } item; 115 WPARAM wp; 116 } u; 117 } MEASURE_ITEM_STRUCT; 118 119 static BOOL test_DestroyWindow_flag; 120 static HWINEVENTHOOK hEvent_hook; 121 static HHOOK hKBD_hook; 122 static HHOOK hCBT_hook; 123 static DWORD cbt_hook_thread_id; 124 125 static const WCHAR testWindowClassW[] = 126 { 'T','e','s','t','W','i','n','d','o','w','C','l','a','s','s','W',0 }; 127 128 static LRESULT WINAPI ParentMsgCheckProcA(HWND, UINT, WPARAM, LPARAM); 129 130 /* 131 FIXME: add tests for these 132 Window Edge Styles (Win31/Win95/98 look), in order of precedence: 133 WS_EX_DLGMODALFRAME: double border, WS_CAPTION allowed 134 WS_THICKFRAME: thick border 135 WS_DLGFRAME: double border, WS_CAPTION not allowed (but possibly shown anyway) 136 WS_BORDER (default for overlapped windows): single black border 137 none (default for child (and popup?) windows): no border 138 */ 139 140 typedef enum { 141 sent=0x1, 142 posted=0x2, 143 parent=0x4, 144 wparam=0x8, 145 lparam=0x10, 146 defwinproc=0x20, 147 beginpaint=0x40, 148 optional=0x80, 149 hook=0x100, 150 winevent_hook=0x200, 151 kbd_hook=0x400 152 } msg_flags_t; 153 154 struct message { 155 UINT message; /* the WM_* code */ 156 msg_flags_t flags; /* message props */ 157 WPARAM wParam; /* expected value of wParam */ 158 LPARAM lParam; /* expected value of lParam */ 159 WPARAM wp_mask; /* mask for wParam checks */ 160 LPARAM lp_mask; /* mask for lParam checks */ 161 }; 162 163 struct recvd_message { 164 UINT message; /* the WM_* code */ 165 msg_flags_t flags; /* message props */ 166 HWND hwnd; /* window that received the message */ 167 WPARAM wParam; /* expected value of wParam */ 168 LPARAM lParam; /* expected value of lParam */ 169 int line; /* source line where logged */ 170 const char *descr; /* description for trace output */ 171 char output[512]; /* trace output */ 172 }; 173 174 /* Empty message sequence */ 175 static const struct message WmEmptySeq[] = 176 { 177 { 0 } 178 }; 179 /* CreateWindow (for overlapped window, not initially visible) (16/32) */ 180 static const struct message WmCreateOverlappedSeq[] = { 181 { HCBT_CREATEWND, hook }, 182 { WM_GETMINMAXINFO, sent }, 183 { WM_NCCREATE, sent }, 184 { WM_NCCALCSIZE, sent|wparam, 0 }, 185 { 0x0093, sent|defwinproc|optional }, 186 { 0x0094, sent|defwinproc|optional }, 187 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, 188 { WM_CREATE, sent }, 189 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 190 { 0 } 191 }; 192 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE) 193 * for a not visible overlapped window. 194 */ 195 static const struct message WmSWP_ShowOverlappedSeq[] = { 196 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 197 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 198 { WM_NCPAINT, sent|wparam|optional, 1 }, 199 { WM_GETTEXT, sent|defwinproc|optional }, 200 { WM_ERASEBKGND, sent|optional }, 201 { HCBT_ACTIVATE, hook }, 202 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 203 { WM_NOTIFYFORMAT, sent|optional }, 204 { WM_QUERYUISTATE, sent|optional }, 205 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 206 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* Win9x: SWP_NOSENDCHANGING */ 207 { WM_ACTIVATEAPP, sent|wparam, 1 }, 208 { WM_NCACTIVATE, sent }, 209 { WM_GETTEXT, sent|defwinproc|optional }, 210 { WM_ACTIVATE, sent|wparam, 1 }, 211 { HCBT_SETFOCUS, hook }, 212 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 213 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 214 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 215 { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, 216 { WM_GETTEXT, sent|optional }, 217 { WM_NCPAINT, sent|wparam|optional, 1 }, 218 { WM_GETTEXT, sent|defwinproc|optional }, 219 { WM_ERASEBKGND, sent|optional }, 220 /* Win9x adds SWP_NOZORDER below */ 221 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 222 { WM_GETTEXT, sent|optional }, 223 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, 224 { WM_NCPAINT, sent|wparam|optional, 1 }, 225 { WM_ERASEBKGND, sent|optional }, 226 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 227 { WM_SYNCPAINT, sent|optional }, 228 { WM_GETTITLEBARINFOEX, sent|optional }, 229 { WM_PAINT, sent|optional }, 230 { WM_NCPAINT, sent|beginpaint|optional }, 231 { WM_GETTEXT, sent|beginpaint|defwinproc|optional }, 232 { WM_ERASEBKGND, sent|beginpaint|optional }, 233 { 0 } 234 }; 235 /* SetWindowPos(SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE) 236 * for a visible overlapped window. 237 */ 238 static const struct message WmSWP_HideOverlappedSeq[] = { 239 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 240 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 241 { HCBT_ACTIVATE, hook|optional }, 242 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 243 { WM_ACTIVATEAPP, sent|wparam|optional, 1 }, 244 { WM_NCACTIVATE, sent|optional }, 245 { WM_ACTIVATE, sent|optional }, 246 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 247 { 0 } 248 }; 249 250 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE) 251 * for a visible overlapped window. 252 */ 253 static const struct message WmSWP_ResizeSeq[] = { 254 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE }, 255 { WM_GETMINMAXINFO, sent|defwinproc }, 256 { WM_NCCALCSIZE, sent|wparam|optional, TRUE }, 257 { WM_NCPAINT, sent|optional }, 258 { WM_GETTEXT, sent|defwinproc|optional }, 259 { WM_ERASEBKGND, sent|optional }, 260 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOCLIENTMOVE }, 261 { WM_SIZE, sent|defwinproc|optional }, 262 { WM_NCCALCSIZE, sent|wparam|optional, TRUE }, 263 { WM_NCPAINT, sent|optional }, 264 { WM_GETTEXT, sent|defwinproc|optional }, 265 { WM_ERASEBKGND, sent|optional }, 266 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 267 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP sends a duplicate */ 268 { 0 } 269 }; 270 271 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE) 272 * for a visible popup window. 273 */ 274 static const struct message WmSWP_ResizePopupSeq[] = { 275 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE }, 276 { WM_GETMINMAXINFO, sent|defwinproc|optional }, /* Win9x */ 277 { WM_NCCALCSIZE, sent|wparam|optional, TRUE }, 278 { WM_NCPAINT, sent|optional }, 279 { WM_GETTEXT, sent|defwinproc|optional }, 280 { WM_ERASEBKGND, sent|optional }, 281 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOCLIENTMOVE }, 282 { WM_SIZE, sent|defwinproc|wparam|optional, SIZE_RESTORED }, 283 { WM_NCCALCSIZE, sent|wparam|optional, TRUE }, 284 { WM_NCPAINT, sent|optional }, 285 { WM_GETTEXT, sent|defwinproc|optional }, 286 { WM_ERASEBKGND, sent|optional }, 287 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 288 { 0 } 289 }; 290 291 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE) 292 * for a visible overlapped window. 293 */ 294 static const struct message WmSWP_MoveSeq[] = { 295 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOSIZE }, 296 { WM_NCPAINT, sent|optional }, 297 { WM_GETTEXT, sent|defwinproc|optional }, 298 { WM_ERASEBKGND, sent|optional }, 299 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOCLIENTSIZE }, 300 { WM_MOVE, sent|defwinproc|wparam, 0 }, 301 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 302 { 0 } 303 }; 304 /* Resize with SetWindowPos(SWP_NOZORDER) 305 * for a visible overlapped window 306 * SWP_NOZORDER is stripped by the logging code 307 */ 308 static const struct message WmSWP_ResizeNoZOrder[] = { 309 { WM_WINDOWPOSCHANGING, sent|wparam, /*SWP_NOZORDER|*/SWP_NOACTIVATE }, 310 { WM_GETMINMAXINFO, sent|defwinproc }, 311 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, 312 { WM_NCPAINT, sent|optional }, 313 { WM_GETTEXT, sent|defwinproc|optional }, 314 { WM_ERASEBKGND, sent|optional }, 315 { WM_WINDOWPOSCHANGED, sent|wparam|optional, /*SWP_NOZORDER|*/SWP_NOACTIVATE, 0, 316 SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOCLIENTSIZE }, 317 { WM_MOVE, sent|defwinproc|optional }, 318 { WM_SIZE, sent|defwinproc|optional }, 319 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* Win9x doesn't send it */ 320 { WM_NCPAINT, sent|optional }, /* Win9x doesn't send it */ 321 { WM_GETTEXT, sent|defwinproc|optional }, /* Win9x doesn't send it */ 322 { WM_ERASEBKGND, sent|optional }, /* Win9x doesn't send it */ 323 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 324 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 325 { 0 } 326 }; 327 328 /* Switch visible mdi children */ 329 static const struct message WmSwitchChild[] = { 330 /* Switch MDI child */ 331 { WM_MDIACTIVATE, sent },/* in the MDI client */ 332 { WM_WINDOWPOSCHANGING, sent|wparam,SWP_NOSIZE|SWP_NOMOVE },/* in the 1st MDI child */ 333 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 334 { WM_CHILDACTIVATE, sent },/* in the 1st MDI child */ 335 /* Deactivate 2nd MDI child */ 336 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 2nd MDI child */ 337 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 2nd MDI child */ 338 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 339 /* Preparing for maximize and maximize the 1st MDI child */ 340 { WM_GETMINMAXINFO, sent|defwinproc }, /* in the 1st MDI child */ 341 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_STATECHANGED }, /* in the 1st MDI child */ 342 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, /* in the 1st MDI child */ 343 { WM_CHILDACTIVATE, sent|defwinproc }, /* in the 1st MDI child */ 344 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, /* in the 1st MDI child */ 345 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, /* in the 1st MDI child */ 346 /* Lock redraw 2nd MDI child */ 347 { WM_SETREDRAW, sent|wparam|defwinproc, 0 }, /* in the 2nd MDI child */ 348 { HCBT_MINMAX, hook|lparam, 0, SW_NORMALNA }, 349 /* Restore 2nd MDI child */ 350 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_STATECHANGED },/* in the 2nd MDI child */ 351 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },/* in the 2nd MDI child */ 352 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, /* in the 2nd MDI child */ 353 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, /* in the 2nd MDI child */ 354 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, /* in the 2nd MDI child */ 355 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* in the 2nd MDI child */ 356 /* Redraw 2nd MDI child */ 357 { WM_SETREDRAW, sent|wparam|defwinproc, 1 },/* in the 2nd MDI child */ 358 /* Redraw MDI frame */ 359 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE },/* in MDI frame */ 360 { WM_NCCALCSIZE, sent|wparam, 1 },/* in MDI frame */ 361 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE}, /* in MDI frame */ 362 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* in MDI frame */ 363 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* in the 1st MDI child */ 364 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, /* in the 1st MDI child */ 365 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, /* in the 1st MDI child */ 366 { HCBT_SETFOCUS, hook }, 367 { WM_KILLFOCUS, sent|defwinproc }, /* in the 2nd MDI child */ 368 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 },/* in the 1st MDI child */ 369 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 370 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 371 { WM_SETFOCUS, sent },/* in the MDI client */ 372 { HCBT_SETFOCUS, hook }, 373 { WM_KILLFOCUS, sent },/* in the MDI client */ 374 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 375 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, /* in the 1st MDI child */ 376 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 377 { WM_SETFOCUS, sent|defwinproc }, /* in the 1st MDI child */ 378 { WM_MDIACTIVATE, sent|defwinproc },/* in the 1st MDI child */ 379 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, /* in the 1st MDI child */ 380 { 0 } 381 }; 382 383 /* Switch visible not maximized mdi children */ 384 static const struct message WmSwitchNotMaximizedChild[] = { 385 /* Switch not maximized MDI child */ 386 { WM_MDIACTIVATE, sent },/* in the MDI client */ 387 { WM_WINDOWPOSCHANGING, sent|wparam,SWP_NOSIZE|SWP_NOMOVE },/* in the 2nd MDI child */ 388 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 389 { WM_CHILDACTIVATE, sent },/* in the 2nd MDI child */ 390 /* Deactivate 1st MDI child */ 391 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 1st MDI child */ 392 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 1st MDI child */ 393 /* Activate 2nd MDI child */ 394 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE}, /* in the 2nd MDI child */ 395 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, /* in the 2nd MDI child */ 396 { HCBT_SETFOCUS, hook }, /* in the 1st MDI child */ 397 { WM_KILLFOCUS, sent|defwinproc }, /* in the 1st MDI child */ 398 { WM_IME_SETCONTEXT, sent|defwinproc|optional }, /* in the 1st MDI child */ 399 { WM_IME_SETCONTEXT, sent|optional }, /* in the MDI client */ 400 { WM_SETFOCUS, sent, 0 }, /* in the MDI client */ 401 { HCBT_SETFOCUS, hook }, 402 { WM_KILLFOCUS, sent }, /* in the MDI client */ 403 { WM_IME_SETCONTEXT, sent|optional }, /* in the MDI client */ 404 { WM_IME_SETCONTEXT, sent|defwinproc|optional }, /* in the 1st MDI child */ 405 { WM_SETFOCUS, sent|defwinproc }, /* in the 2nd MDI child */ 406 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 2nd MDI child */ 407 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE}, /* in the 2nd MDI child */ 408 { 0 } 409 }; 410 411 412 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE| 413 SWP_NOZORDER|SWP_FRAMECHANGED) 414 * for a visible overlapped window with WS_CLIPCHILDREN style set. 415 */ 416 static const struct message WmSWP_FrameChanged_clip[] = { 417 { WM_WINDOWPOSCHANGING, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED }, 418 { WM_NCCALCSIZE, sent|wparam|parent, 1 }, 419 { WM_NCPAINT, sent|parent|optional }, /* wparam != 1 */ 420 { WM_GETTEXT, sent|parent|defwinproc|optional }, 421 { WM_ERASEBKGND, sent|parent|optional }, /* FIXME: remove optional once Wine is fixed */ 422 { WM_NCPAINT, sent }, /* wparam != 1 */ 423 { WM_ERASEBKGND, sent }, 424 { WM_WINDOWPOSCHANGED, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 425 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 426 { WM_PAINT, sent }, 427 { 0 } 428 }; 429 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_DEFERERASE|SWP_NOACTIVATE| 430 SWP_NOZORDER|SWP_FRAMECHANGED) 431 * for a visible overlapped window. 432 */ 433 static const struct message WmSWP_FrameChangedDeferErase[] = { 434 { WM_WINDOWPOSCHANGING, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_DEFERERASE|SWP_NOACTIVATE|SWP_FRAMECHANGED }, 435 { WM_NCCALCSIZE, sent|wparam|parent, 1 }, 436 { WM_WINDOWPOSCHANGED, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_DEFERERASE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 437 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 438 { WM_PAINT, sent|parent|optional }, 439 { WM_NCPAINT, sent|beginpaint|parent|optional }, /* wparam != 1 */ 440 { WM_GETTEXT, sent|beginpaint|parent|defwinproc|optional }, 441 { WM_PAINT, sent }, 442 { WM_NCPAINT, sent|beginpaint }, /* wparam != 1 */ 443 { WM_ERASEBKGND, sent|beginpaint|optional }, 444 { 0 } 445 }; 446 447 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE| 448 SWP_NOZORDER|SWP_FRAMECHANGED) 449 * for a visible overlapped window without WS_CLIPCHILDREN style set. 450 */ 451 static const struct message WmSWP_FrameChanged_noclip[] = { 452 { WM_WINDOWPOSCHANGING, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED }, 453 { WM_NCCALCSIZE, sent|wparam|parent, 1 }, 454 { WM_NCPAINT, sent|parent|optional }, /* wparam != 1 */ 455 { WM_GETTEXT, sent|parent|defwinproc|optional }, 456 { WM_ERASEBKGND, sent|parent|optional }, 457 { WM_WINDOWPOSCHANGED, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 458 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 459 { WM_PAINT, sent }, 460 { WM_NCPAINT, sent|beginpaint }, /* wparam != 1 */ 461 { WM_ERASEBKGND, sent|beginpaint|optional }, 462 { 0 } 463 }; 464 465 /* ShowWindow(SW_SHOW) for a not visible overlapped window */ 466 static const struct message WmShowOverlappedSeq[] = { 467 { WM_SHOWWINDOW, sent|wparam, 1 }, 468 { WM_NCPAINT, sent|wparam|optional, 1 }, 469 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 470 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 471 { WM_NCPAINT, sent|wparam|optional, 1 }, 472 { WM_GETTEXT, sent|defwinproc|optional }, 473 { WM_ERASEBKGND, sent|optional }, 474 { HCBT_ACTIVATE, hook|optional }, 475 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 476 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 477 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 478 { WM_NCPAINT, sent|wparam|optional, 1 }, 479 { WM_ACTIVATEAPP, sent|wparam|optional, 1 }, 480 { WM_NCACTIVATE, sent|wparam|optional, 1 }, 481 { WM_GETTEXT, sent|defwinproc|optional }, 482 { WM_ACTIVATE, sent|wparam|optional, 1 }, 483 { HCBT_SETFOCUS, hook|optional }, 484 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 485 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 486 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 487 { WM_SETFOCUS, sent|wparam|defwinproc|optional, 0 }, 488 { WM_GETTEXT, sent|optional }, 489 { WM_NCPAINT, sent|wparam|optional, 1 }, 490 { WM_GETTEXT, sent|defwinproc|optional }, 491 { WM_ERASEBKGND, sent|optional }, 492 /* Win9x adds SWP_NOZORDER below */ 493 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 494 { WM_NCCALCSIZE, sent|optional }, 495 { WM_GETTEXT, sent|optional }, 496 { WM_NCPAINT, sent|optional }, 497 { WM_ERASEBKGND, sent|optional }, 498 { WM_SYNCPAINT, sent|optional }, 499 #if 0 /* CreateWindow/ShowWindow(SW_SHOW) also generates WM_SIZE/WM_MOVE 500 * messages. Does that mean that CreateWindow doesn't set initial 501 * window dimensions for overlapped windows? 502 */ 503 { WM_SIZE, sent }, 504 { WM_MOVE, sent }, 505 #endif 506 { WM_PAINT, sent|optional }, 507 { WM_NCPAINT, sent|beginpaint|optional }, 508 { 0 } 509 }; 510 /* ShowWindow(SW_SHOWMAXIMIZED) for a not visible overlapped window */ 511 static const struct message WmShowMaxOverlappedSeq[] = { 512 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 513 { WM_GETMINMAXINFO, sent }, 514 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_STATECHANGED }, 515 { WM_GETMINMAXINFO, sent|defwinproc }, 516 { WM_NCCALCSIZE, sent|wparam, TRUE }, 517 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 518 { HCBT_ACTIVATE, hook|optional }, 519 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 520 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 521 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 522 { WM_ACTIVATEAPP, sent|wparam|optional, 1 }, 523 { WM_NCACTIVATE, sent|wparam|optional, 1 }, 524 { WM_GETTEXT, sent|defwinproc|optional }, 525 { WM_ACTIVATE, sent|wparam|optional, 1 }, 526 { HCBT_SETFOCUS, hook|optional }, 527 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 528 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 529 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 530 { WM_SETFOCUS, sent|wparam|defwinproc|optional, 0 }, 531 { WM_GETTEXT, sent|optional }, 532 { WM_NCPAINT, sent|wparam|optional, 1 }, 533 { WM_GETTEXT, sent|defwinproc|optional }, 534 { WM_ERASEBKGND, sent|optional }, 535 /* Win9x adds SWP_NOZORDER below */ 536 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_STATECHANGED }, 537 { WM_MOVE, sent|defwinproc }, 538 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 539 { WM_GETTEXT, sent|optional }, 540 { WM_NCCALCSIZE, sent|optional }, 541 { WM_NCPAINT, sent|optional }, 542 { WM_ERASEBKGND, sent|optional }, 543 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 544 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 545 { WM_SYNCPAINT, sent|optional }, 546 { WM_GETTITLEBARINFOEX, sent|optional }, 547 { WM_PAINT, sent|optional }, 548 { WM_NCPAINT, sent|beginpaint|optional }, 549 { WM_ERASEBKGND, sent|beginpaint|optional }, 550 { 0 } 551 }; 552 /* ShowWindow(SW_RESTORE) for a not visible maximized overlapped window */ 553 static const struct message WmShowRestoreMaxOverlappedSeq[] = { 554 { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE }, 555 { WM_GETTEXT, sent|optional }, 556 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, 557 { WM_GETMINMAXINFO, sent|defwinproc }, 558 { WM_NCCALCSIZE, sent|wparam, TRUE }, 559 { WM_NCPAINT, sent|optional }, 560 { WM_GETTEXT, sent|defwinproc|optional }, 561 { WM_ERASEBKGND, sent|optional }, 562 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOMOVE }, 563 { WM_MOVE, sent|defwinproc|optional }, 564 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 565 { WM_NCCALCSIZE, sent|wparam|optional, TRUE }, 566 { WM_NCPAINT, sent|optional }, 567 { WM_ERASEBKGND, sent|optional }, 568 { WM_PAINT, sent|optional }, 569 { WM_GETTITLEBARINFOEX, sent|optional }, 570 { WM_NCPAINT, sent|beginpaint|optional }, 571 { WM_ERASEBKGND, sent|beginpaint|optional }, 572 { 0 } 573 }; 574 /* ShowWindow(SW_RESTORE) for a not visible minimized overlapped window */ 575 static const struct message WmShowRestoreMinOverlappedSeq[] = { 576 { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE }, 577 { WM_QUERYOPEN, sent|optional }, 578 { WM_GETTEXT, sent|optional }, 579 { WM_NCACTIVATE, sent|wparam|optional, 1 }, 580 { WM_WINDOWPOSCHANGING, sent|optional }, /* SWP_NOSIZE|SWP_NOMOVE */ 581 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 582 { WM_NCCALCSIZE, sent|wparam|optional, TRUE }, 583 { WM_MOVE, sent|optional }, 584 { WM_SIZE, sent|wparam|optional, SIZE_RESTORED }, 585 { WM_GETTEXT, sent|optional }, 586 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_FRAMECHANGED|SWP_STATECHANGED|SWP_NOCOPYBITS }, 587 { WM_GETMINMAXINFO, sent|defwinproc|optional }, 588 { WM_NCCALCSIZE, sent|wparam|optional, TRUE }, 589 { HCBT_ACTIVATE, hook|optional }, 590 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 591 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 592 { WM_ACTIVATEAPP, sent|wparam|optional, 1 }, 593 { WM_NCACTIVATE, sent|wparam|optional, 1 }, 594 { WM_GETTEXT, sent|defwinproc|optional }, 595 { WM_ACTIVATE, sent|wparam|optional, 1 }, 596 { HCBT_SETFOCUS, hook|optional }, 597 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 598 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 599 { WM_SETFOCUS, sent|wparam|defwinproc|optional, 0 }, 600 { WM_GETTEXT, sent|optional }, 601 { WM_NCPAINT, sent|wparam|optional, 1 }, 602 { WM_GETTEXT, sent|defwinproc|optional }, 603 { WM_ERASEBKGND, sent }, 604 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_STATECHANGED|SWP_FRAMECHANGED|SWP_NOCOPYBITS }, 605 { WM_MOVE, sent|defwinproc }, 606 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 607 { HCBT_SETFOCUS, hook|optional }, 608 { WM_SETFOCUS, sent|wparam|optional, 0 }, 609 { WM_NCCALCSIZE, sent|wparam|optional, TRUE }, 610 { WM_NCPAINT, sent|wparam|optional, 1 }, 611 { WM_ERASEBKGND, sent|optional }, 612 { HCBT_SETFOCUS, hook|optional }, 613 { WM_SETFOCUS, sent|wparam|optional, 0 }, 614 { WM_ACTIVATE, sent|wparam, 1 }, 615 { WM_GETTEXT, sent|optional }, 616 { WM_PAINT, sent|optional }, 617 { WM_GETTITLEBARINFOEX, sent|optional }, 618 { WM_NCPAINT, sent|beginpaint|optional }, 619 { WM_ERASEBKGND, sent|beginpaint|optional }, 620 { 0 } 621 }; 622 /* ShowWindow(SW_SHOWMINIMIZED) for a not visible overlapped window */ 623 static const struct message WmShowMinOverlappedSeq[] = { 624 { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, 625 { HCBT_SETFOCUS, hook|optional }, 626 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 627 { WM_KILLFOCUS, sent|optional }, 628 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 629 { WM_IME_NOTIFY, sent|wparam|optional|defwinproc, 1 }, 630 { WM_GETTEXT, sent|optional }, 631 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOCOPYBITS|SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_STATECHANGED }, 632 { WM_GETMINMAXINFO, sent|defwinproc }, 633 { WM_NCCALCSIZE, sent|wparam, TRUE }, 634 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, 635 { WM_NCPAINT, sent|optional }, 636 { WM_GETTEXT, sent|defwinproc|optional }, 637 { WM_WINDOWPOSCHANGED, sent }, 638 { WM_MOVE, sent|defwinproc }, 639 { WM_SIZE, sent|defwinproc|wparam|lparam, SIZE_MINIMIZED, 0 }, 640 { WM_NCCALCSIZE, sent|optional }, 641 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 642 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 643 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 }, 644 { WM_NCACTIVATE, sent|wparam|optional, 0 }, 645 { WM_GETTEXT, sent|defwinproc|optional }, 646 { WM_ACTIVATE, sent|optional }, 647 { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, 648 649 /* Vista sometimes restores the window right away... */ 650 { WM_SYSCOMMAND, sent|optional|wparam, SC_RESTORE }, 651 { HCBT_SYSCOMMAND, hook|optional|wparam, SC_RESTORE }, 652 { HCBT_MINMAX, hook|optional|lparam, 0, SW_RESTORE }, 653 { WM_QUERYOPEN, sent|optional }, 654 { WM_WINDOWPOSCHANGING, sent|optional|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, 655 { WM_GETMINMAXINFO, sent|optional|defwinproc }, 656 { WM_NCCALCSIZE, sent|optional|wparam, TRUE }, 657 { HCBT_ACTIVATE, hook|optional }, 658 { WM_ACTIVATEAPP, sent|optional|wparam, 1 }, 659 { WM_NCACTIVATE, sent|optional }, 660 { WM_GETTEXT, sent|optional }, 661 { WM_ACTIVATE, sent|optional|wparam, 1 }, 662 { HCBT_SETFOCUS, hook|optional }, 663 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 664 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 665 { WM_SETFOCUS, sent|optional }, 666 { WM_NCPAINT, sent|optional }, 667 { WM_GETTEXT, sent|defwinproc|optional }, 668 { WM_ERASEBKGND, sent|optional }, 669 { WM_WINDOWPOSCHANGED, sent|optional|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, 670 { WM_MOVE, sent|defwinproc|optional }, 671 { WM_SIZE, sent|defwinproc|optional|wparam, SIZE_RESTORED }, 672 { WM_ACTIVATE, sent|optional|wparam, 1 }, 673 { WM_SYSCOMMAND, sent|optional|wparam, SC_RESTORE }, 674 { HCBT_SYSCOMMAND, hook|optional|wparam, SC_RESTORE }, 675 676 { WM_PAINT, sent|optional }, 677 { WM_NCPAINT, sent|beginpaint|optional }, 678 { WM_ERASEBKGND, sent|beginpaint|optional }, 679 { 0 } 680 }; 681 /* ShowWindow(SW_HIDE) for a visible overlapped window */ 682 static const struct message WmHideOverlappedSeq[] = { 683 { WM_SHOWWINDOW, sent|wparam, 0 }, 684 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 685 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 686 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 687 { WM_SIZE, sent|optional }, /* XP doesn't send it */ 688 { WM_MOVE, sent|optional }, /* XP doesn't send it */ 689 { WM_NCACTIVATE, sent|wparam|optional, 0 }, 690 { WM_ACTIVATE, sent|wparam|optional, 0 }, 691 { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, 692 { HCBT_SETFOCUS, hook|optional }, 693 { WM_KILLFOCUS, sent|wparam|optional, 0 }, 694 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 695 { WM_IME_NOTIFY, sent|wparam|optional|defwinproc, 1 }, 696 { 0 } 697 }; 698 /* DestroyWindow for a visible overlapped window */ 699 static const struct message WmDestroyOverlappedSeq[] = { 700 { HCBT_DESTROYWND, hook }, 701 { 0x0090, sent|optional }, 702 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 703 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 704 { 0x0090, sent|optional }, 705 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 706 { WM_NCACTIVATE, sent|optional|wparam, 0 }, 707 { WM_ACTIVATE, sent|optional }, 708 { WM_ACTIVATEAPP, sent|optional|wparam, 0 }, 709 { WM_KILLFOCUS, sent|optional|wparam, 0 }, 710 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 711 { WM_IME_NOTIFY, sent|wparam|optional|defwinproc, 1 }, 712 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, 713 { WM_DESTROY, sent }, 714 { WM_NCDESTROY, sent }, 715 { 0 } 716 }; 717 /* CreateWindow(WS_MAXIMIZE|WS_VISIBLE) for popup window */ 718 static const struct message WmCreateMaxPopupSeq[] = { 719 { HCBT_CREATEWND, hook }, 720 { WM_NCCREATE, sent }, 721 { WM_NCCALCSIZE, sent|wparam, 0 }, 722 { WM_CREATE, sent }, 723 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 724 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 725 { WM_MOVE, sent }, 726 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 727 { WM_GETMINMAXINFO, sent }, 728 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_STATECHANGED }, 729 { WM_NCCALCSIZE, sent|wparam, TRUE }, 730 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOREDRAW|SWP_STATECHANGED }, 731 { WM_MOVE, sent|defwinproc }, 732 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 733 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 734 { WM_SHOWWINDOW, sent|wparam, 1 }, 735 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 736 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 737 { HCBT_ACTIVATE, hook }, 738 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 739 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 740 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 741 { WM_NCPAINT, sent|wparam|optional, 1 }, 742 { WM_ERASEBKGND, sent|optional }, 743 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOCLIENTMOVE|SWP_NOCLIENTSIZE|SWP_NOMOVE|SWP_NOSIZE }, 744 { WM_ACTIVATEAPP, sent|wparam, 1 }, 745 { WM_NCACTIVATE, sent }, 746 { WM_ACTIVATE, sent|wparam, 1 }, 747 { HCBT_SETFOCUS, hook }, 748 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 749 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 750 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 751 { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, 752 { WM_GETTEXT, sent|optional }, 753 { WM_SYNCPAINT, sent|wparam|optional, 4 }, 754 { WM_NCPAINT, sent|wparam|optional, 1 }, 755 { WM_ERASEBKGND, sent|optional }, 756 { WM_NCPAINT, sent|wparam|defwinproc|optional, 1 }, 757 { WM_ERASEBKGND, sent|defwinproc|optional }, 758 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTMOVE|SWP_NOCLIENTSIZE|SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOSIZE }, 759 { 0 } 760 }; 761 /* CreateWindow(WS_MAXIMIZE) for popup window, not initially visible */ 762 static const struct message WmCreateInvisibleMaxPopupSeq[] = { 763 { HCBT_CREATEWND, hook }, 764 { WM_NCCREATE, sent }, 765 { WM_NCCALCSIZE, sent|wparam, 0 }, 766 { WM_CREATE, sent }, 767 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 768 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 769 { WM_MOVE, sent }, 770 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 771 { WM_GETMINMAXINFO, sent }, 772 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_STATECHANGED }, 773 { WM_NCCALCSIZE, sent|wparam, TRUE }, 774 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOREDRAW|SWP_STATECHANGED }, 775 { WM_MOVE, sent|defwinproc }, 776 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 777 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 778 { 0 } 779 }; 780 /* ShowWindow(SW_SHOWMAXIMIZED) for a resized not visible popup window */ 781 static const struct message WmShowMaxPopupResizedSeq_todo[] = { 782 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 783 { WM_GETMINMAXINFO, sent }, 784 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED }, 785 { WM_NCCALCSIZE, sent|wparam, TRUE }, 786 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 787 { HCBT_ACTIVATE, hook }, 788 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 789 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 790 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 791 { WM_NCPAINT, sent|wparam|optional, 1 }, 792 { WM_ERASEBKGND, sent|optional }, 793 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 794 { WM_ACTIVATEAPP, sent|wparam, 1 }, 795 { WM_NCACTIVATE, sent }, 796 { WM_ACTIVATE, sent|wparam, 1 }, 797 { HCBT_SETFOCUS, hook }, 798 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 799 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 800 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 801 { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, 802 { WM_GETTEXT, sent|optional }, 803 { WM_NCPAINT, sent|wparam|optional, 1 }, 804 { WM_ERASEBKGND, sent|optional }, 805 { WM_WINDOWPOSCHANGED, sent }, 806 /* WinNT4.0 sends WM_MOVE */ 807 { WM_MOVE, sent|defwinproc|optional }, 808 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 809 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 810 { 0 } 811 }; 812 static const struct message WmShowMaxPopupResizedSeq[] = { 813 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 814 { WM_GETMINMAXINFO, sent }, 815 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED }, 816 { WM_NCCALCSIZE, sent|wparam, TRUE }, 817 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 818 { HCBT_ACTIVATE, hook }, 819 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 820 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 821 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 822 { WM_NCPAINT, sent|wparam|optional, 1 }, 823 { WM_ERASEBKGND, sent|optional }, 824 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 825 { WM_ACTIVATEAPP, sent|wparam, 1 }, 826 { WM_NCACTIVATE, sent }, 827 { WM_ACTIVATE, sent|wparam, 1 }, 828 { HCBT_SETFOCUS, hook }, 829 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 830 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 831 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 832 { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, 833 { WM_GETTEXT, sent|optional }, 834 { WM_NCPAINT, sent|optional }, /* We'll check WM_NCPAINT behaviour in another test */ 835 { WM_ERASEBKGND, sent|optional }, 836 { WM_WINDOWPOSCHANGED, sent }, 837 /* WinNT4.0 sends WM_MOVE */ 838 { WM_MOVE, sent|defwinproc|optional }, 839 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 840 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 841 { 0 } 842 }; 843 /* ShowWindow(SW_SHOWMAXIMIZED) for a not visible popup window */ 844 static const struct message WmShowMaxPopupSeq[] = { 845 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 846 { WM_GETMINMAXINFO, sent }, 847 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED }, 848 { WM_NCCALCSIZE, sent|wparam, TRUE }, 849 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 850 { HCBT_ACTIVATE, hook }, 851 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 852 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 853 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 854 { WM_NCPAINT, sent|wparam|optional, 1 }, 855 { WM_ERASEBKGND, sent|optional }, 856 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOMOVE|SWP_NOSIZE }, 857 { WM_ACTIVATEAPP, sent|wparam, 1 }, 858 { WM_NCACTIVATE, sent }, 859 { WM_ACTIVATE, sent|wparam, 1 }, 860 { HCBT_SETFOCUS, hook }, 861 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 862 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 863 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 864 { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, 865 { WM_GETTEXT, sent|optional }, 866 { WM_SYNCPAINT, sent|wparam|optional, 4 }, 867 { WM_NCPAINT, sent|wparam|optional, 1 }, 868 { WM_ERASEBKGND, sent|optional }, 869 { WM_NCPAINT, sent|wparam|defwinproc|optional, 1 }, 870 { WM_ERASEBKGND, sent|defwinproc|optional }, 871 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOSIZE }, 872 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 873 { 0 } 874 }; 875 /* CreateWindow(WS_VISIBLE) for popup window */ 876 static const struct message WmCreatePopupSeq[] = { 877 { HCBT_CREATEWND, hook }, 878 { WM_NCCREATE, sent }, 879 { WM_NCCALCSIZE, sent|wparam, 0 }, 880 { WM_CREATE, sent }, 881 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 882 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 883 { WM_MOVE, sent }, 884 { WM_SHOWWINDOW, sent|wparam, 1 }, 885 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 886 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 887 { HCBT_ACTIVATE, hook }, 888 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 889 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 890 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 891 { WM_NCPAINT, sent|wparam|optional, 1 }, 892 { WM_ERASEBKGND, sent|optional }, 893 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 894 { WM_ACTIVATEAPP, sent|wparam, 1 }, 895 { WM_NCACTIVATE, sent }, 896 { WM_ACTIVATE, sent|wparam, 1 }, 897 { HCBT_SETFOCUS, hook }, 898 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 899 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 900 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 901 { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, 902 { WM_GETTEXT, sent|optional }, 903 { WM_SYNCPAINT, sent|wparam|optional, 4 }, 904 { WM_NCPAINT, sent|wparam|optional, 1 }, 905 { WM_ERASEBKGND, sent|optional }, 906 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTMOVE|SWP_NOCLIENTSIZE|SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOSIZE }, 907 { 0 } 908 }; 909 /* ShowWindow(SW_SHOWMAXIMIZED) for a visible popup window */ 910 static const struct message WmShowVisMaxPopupSeq[] = { 911 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 912 { WM_GETMINMAXINFO, sent }, 913 { WM_GETTEXT, sent|optional }, 914 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, 915 { WM_GETTEXT, sent|optional }, 916 { WM_NCCALCSIZE, sent|wparam, TRUE }, 917 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 918 { WM_NCPAINT, sent|wparam|optional, 1 }, 919 { WM_ERASEBKGND, sent|optional }, 920 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, 921 { WM_MOVE, sent|defwinproc }, 922 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 923 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 924 { 0 } 925 }; 926 /* CreateWindow (for a child popup window, not initially visible) */ 927 static const struct message WmCreateChildPopupSeq[] = { 928 { HCBT_CREATEWND, hook }, 929 { WM_NCCREATE, sent }, 930 { WM_NCCALCSIZE, sent|wparam, 0 }, 931 { WM_CREATE, sent }, 932 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 933 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 934 { WM_MOVE, sent }, 935 { 0 } 936 }; 937 /* CreateWindow (for a popup window, not initially visible, 938 * which sets WS_VISIBLE in WM_CREATE handler) 939 */ 940 static const struct message WmCreateInvisiblePopupSeq[] = { 941 { HCBT_CREATEWND, hook }, 942 { WM_NCCREATE, sent }, 943 { WM_NCCALCSIZE, sent|wparam, 0 }, 944 { WM_CREATE, sent }, 945 { WM_STYLECHANGING, sent }, 946 { WM_STYLECHANGED, sent }, 947 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 948 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 949 { WM_MOVE, sent }, 950 { 0 } 951 }; 952 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER) 953 * for a popup window with WS_VISIBLE style set 954 */ 955 static const struct message WmShowVisiblePopupSeq_2[] = { 956 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 957 { 0 } 958 }; 959 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE) 960 * for a popup window with WS_VISIBLE style set 961 */ 962 static const struct message WmShowVisiblePopupSeq_3[] = { 963 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 964 { HCBT_ACTIVATE, hook }, 965 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 966 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 967 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 968 { WM_NCACTIVATE, sent }, 969 { WM_ACTIVATE, sent|wparam, 1 }, 970 { HCBT_SETFOCUS, hook }, 971 { WM_KILLFOCUS, sent|parent }, 972 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, 973 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 974 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 975 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 976 { WM_SETFOCUS, sent|defwinproc }, 977 { WM_GETTEXT, sent|optional }, 978 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE, 0, SWP_SHOWWINDOW }, 979 { 0 } 980 }; 981 /* CreateWindow (for a popup window with WS_VISIBLE style set and extreme location) 982 */ 983 static const struct message WmShowPopupExtremeLocationSeq[] = { 984 { HCBT_CREATEWND, hook }, 985 { WM_NCCREATE, sent }, 986 { WM_NCCALCSIZE, sent|wparam, 0 }, 987 { WM_CREATE, sent }, 988 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 989 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 990 { WM_MOVE, sent }, 991 { WM_SHOWWINDOW, sent|wparam, 1 }, 992 { WM_WINDOWPOSCHANGING, sent }, 993 { HCBT_ACTIVATE, hook }, 994 { WM_WINDOWPOSCHANGING, sent|optional }, 995 { WM_QUERYNEWPALETTE, sent|optional }, 996 { WM_ACTIVATEAPP, sent }, 997 { WM_NCACTIVATE, sent }, 998 { WM_ACTIVATE, sent }, 999 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, 1000 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 1001 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 1002 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1003 { HCBT_SETFOCUS, hook }, 1004 { WM_SETFOCUS, sent|defwinproc }, 1005 { WM_NCPAINT, sent|wparam, 1 }, 1006 { WM_ERASEBKGND, sent }, 1007 { WM_WINDOWPOSCHANGED, sent }, 1008 /* occasionally received on test machines */ 1009 { WM_NCPAINT, sent|optional }, 1010 { WM_ERASEBKGND, sent|optional }, 1011 { 0 } 1012 }; 1013 /* CreateWindow (for a popup window with WS_VISIBLE style set) 1014 */ 1015 static const struct message WmShowPopupFirstDrawSeq_1[] = { 1016 { HCBT_CREATEWND, hook }, 1017 { WM_NCCREATE, sent }, 1018 { WM_NCCALCSIZE, sent|wparam, 0 }, 1019 { WM_CREATE, sent }, 1020 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1021 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 1022 { WM_MOVE, sent }, 1023 { WM_SHOWWINDOW, sent|wparam, 1 }, 1024 { WM_WINDOWPOSCHANGING, sent }, 1025 { HCBT_ACTIVATE, hook }, 1026 { WM_WINDOWPOSCHANGING, sent|optional }, 1027 { WM_QUERYNEWPALETTE, sent|optional }, 1028 { WM_ACTIVATEAPP, sent }, 1029 { WM_NCACTIVATE, sent }, 1030 { WM_ACTIVATE, sent }, 1031 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, 1032 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 1033 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 1034 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1035 { HCBT_SETFOCUS, hook }, 1036 { WM_SETFOCUS, sent|defwinproc }, 1037 { WM_NCPAINT, sent|wparam, 1 }, 1038 { WM_ERASEBKGND, sent }, 1039 { WM_WINDOWPOSCHANGED, sent }, 1040 { WM_PAINT, sent }, 1041 /* occasionally received on test machines */ 1042 { WM_NCPAINT, sent|beginpaint|optional }, 1043 { WM_ERASEBKGND, sent|beginpaint|optional }, 1044 { 0 } 1045 }; 1046 /* CreateWindow (for a popup window that is shown with ShowWindow(SW_SHOWMAXIMIZED)) 1047 */ 1048 static const struct message WmShowPopupFirstDrawSeq_2[] = { 1049 { HCBT_CREATEWND, hook }, 1050 { WM_NCCREATE, sent }, 1051 { WM_NCCALCSIZE, sent|wparam, 0 }, 1052 { WM_CREATE, sent }, 1053 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1054 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 1055 { WM_MOVE, sent }, 1056 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 1057 { WM_GETMINMAXINFO, sent }, 1058 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_STATECHANGED|SWP_SHOWWINDOW|SWP_FRAMECHANGED }, 1059 { WM_NCCALCSIZE, sent|wparam, TRUE }, 1060 { HCBT_ACTIVATE, hook }, 1061 { WM_WINDOWPOSCHANGING, sent|optional }, 1062 { WM_NCPAINT, sent|optional|wparam, 1 }, 1063 { WM_ERASEBKGND, sent|optional }, 1064 { WM_WINDOWPOSCHANGED, sent|optional }, 1065 { WM_QUERYNEWPALETTE, sent|optional }, 1066 { WM_ACTIVATEAPP, sent }, 1067 { WM_NCACTIVATE, sent }, 1068 { WM_ACTIVATE, sent }, 1069 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, 1070 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 1071 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 1072 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1073 { HCBT_SETFOCUS, hook }, 1074 { WM_SETFOCUS, sent|defwinproc }, 1075 { WM_NCPAINT, sent|wparam, 1 }, 1076 { WM_ERASEBKGND, sent }, 1077 { WM_WINDOWPOSCHANGED, sent|optional }, 1078 { WM_MOVE, sent|defwinproc }, 1079 { WM_SIZE, sent|defwinproc, 0 }, 1080 { WM_PAINT, sent}, 1081 /* occasionally received on test machines */ 1082 { WM_NCPAINT, sent|beginpaint|optional }, 1083 { WM_ERASEBKGND, sent|beginpaint|optional }, 1084 { 0 } 1085 }; 1086 static const struct message WmFirstDrawSetWindowPosSeq1[] = { 1087 { HCBT_CREATEWND, hook }, 1088 { WM_NCCREATE, sent }, 1089 { WM_NCCALCSIZE, sent|wparam, 0 }, 1090 { WM_CREATE, sent }, 1091 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1092 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 1093 { WM_MOVE, sent }, 1094 { WM_WINDOWPOSCHANGING, sent }, 1095 { HCBT_ACTIVATE, hook }, 1096 { WM_WINDOWPOSCHANGING, sent|optional }, 1097 { WM_QUERYNEWPALETTE, sent|optional }, 1098 { WM_ACTIVATEAPP, sent }, 1099 { WM_NCACTIVATE, sent }, 1100 { WM_ACTIVATE, sent }, 1101 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, 1102 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 1103 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 1104 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1105 { HCBT_SETFOCUS, hook }, 1106 { WM_SETFOCUS, sent|defwinproc }, 1107 { WM_NCPAINT, sent|wparam, 1 }, 1108 { WM_ERASEBKGND, sent }, 1109 { WM_WINDOWPOSCHANGED, sent }, 1110 { WM_MOVE, sent|defwinproc }, 1111 { 0 } 1112 }; 1113 static const struct message WmFirstDrawSetWindowPosSeq2[] = { 1114 { HCBT_CREATEWND, hook }, 1115 { WM_NCCREATE, sent }, 1116 { WM_NCCALCSIZE, sent|wparam, 0 }, 1117 { WM_CREATE, sent }, 1118 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1119 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 1120 { WM_MOVE, sent }, 1121 { WM_WINDOWPOSCHANGING, sent }, 1122 { HCBT_ACTIVATE, hook }, 1123 { WM_QUERYNEWPALETTE, sent|optional }, 1124 { WM_WINDOWPOSCHANGING, sent|optional }, 1125 { WM_ACTIVATEAPP, sent }, 1126 { WM_NCACTIVATE, sent }, 1127 { WM_ACTIVATE, sent }, 1128 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, 1129 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 1130 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 1131 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1132 { HCBT_SETFOCUS, hook }, 1133 { WM_SETFOCUS, sent|defwinproc }, 1134 { WM_WINDOWPOSCHANGED, sent }, 1135 { WM_MOVE, sent|defwinproc }, 1136 { 0 } 1137 }; 1138 static const struct message WmFirstDrawSetWindowPosSeq3[] = { 1139 { HCBT_CREATEWND, hook }, 1140 { WM_NCCREATE, sent }, 1141 { WM_NCCALCSIZE, sent|wparam, 0 }, 1142 { WM_CREATE, sent }, 1143 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1144 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 1145 { WM_MOVE, sent }, 1146 { HCBT_ACTIVATE, hook|optional }, 1147 /* Probably shouldn't happen, but not part of this test */ 1148 { WM_QUERYNEWPALETTE, sent|optional }, 1149 { WM_ACTIVATEAPP, sent|optional }, 1150 { WM_NCACTIVATE, sent|optional }, 1151 { WM_ACTIVATE, sent|optional }, 1152 { HCBT_SETFOCUS, hook|optional }, 1153 { WM_SETFOCUS, sent|defwinproc|optional }, 1154 { 0 } 1155 }; 1156 static const struct message WmFirstDrawSetWindowPosSeq4[] = { 1157 { HCBT_CREATEWND, hook }, 1158 { WM_NCCREATE, sent }, 1159 { WM_NCCALCSIZE, sent|wparam, 0 }, 1160 { WM_CREATE, sent }, 1161 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1162 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 1163 { WM_MOVE, sent }, 1164 { WM_WINDOWPOSCHANGING, sent }, 1165 { HCBT_ACTIVATE, hook }, 1166 { WM_WINDOWPOSCHANGING, sent|optional }, 1167 { WM_QUERYNEWPALETTE, sent|optional }, 1168 { WM_ACTIVATEAPP, sent }, 1169 { WM_NCACTIVATE, sent }, 1170 { WM_ACTIVATE, sent }, 1171 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, 1172 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 1173 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 1174 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1175 { HCBT_SETFOCUS, hook }, 1176 { WM_SETFOCUS, sent|defwinproc }, 1177 { WM_NCPAINT, sent|wparam, 1 }, 1178 { WM_ERASEBKGND, sent }, 1179 { WM_WINDOWPOSCHANGED, sent }, 1180 { 0 } 1181 }; 1182 static const struct message WmFirstDrawSetWindowPosSeq5[] = { 1183 { HCBT_CREATEWND, hook }, 1184 { WM_NCCREATE, sent }, 1185 { WM_NCCALCSIZE, sent|wparam, 0 }, 1186 { WM_CREATE, sent }, 1187 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1188 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 1189 { WM_MOVE, sent }, 1190 { WM_WINDOWPOSCHANGING, sent }, 1191 { HCBT_ACTIVATE, hook }, 1192 { WM_WINDOWPOSCHANGING, sent|optional }, 1193 { WM_QUERYNEWPALETTE, sent|optional }, 1194 { WM_ACTIVATEAPP, sent }, 1195 { WM_NCACTIVATE, sent }, 1196 { WM_ACTIVATE, sent }, 1197 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, 1198 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 1199 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 1200 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1201 { HCBT_SETFOCUS, hook }, 1202 { WM_SETFOCUS, sent|defwinproc }, 1203 { WM_WINDOWPOSCHANGED, sent }, 1204 { 0 } 1205 }; 1206 static const struct message WmFirstDrawChildSeq1[] = { 1207 { 0 } 1208 }; 1209 static const struct message WmFirstDrawChildSeq2[] = { 1210 { WM_NCPAINT, sent|wparam, 1 }, 1211 { WM_ERASEBKGND, sent }, 1212 /* occasionally received on test machines */ 1213 { WM_NCPAINT, sent|optional }, 1214 { WM_ERASEBKGND, sent|optional }, 1215 { 0 } 1216 }; 1217 /* CreateWindow (for child window, not initially visible) */ 1218 static const struct message WmCreateChildSeq[] = { 1219 { HCBT_CREATEWND, hook }, 1220 { WM_NCCREATE, sent }, 1221 /* child is inserted into parent's child list after WM_NCCREATE returns */ 1222 { WM_NCCALCSIZE, sent|wparam, 0 }, 1223 { WM_CREATE, sent }, 1224 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1225 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 1226 { WM_MOVE, sent }, 1227 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE }, 1228 { 0 } 1229 }; 1230 /* CreateWindow (for maximized child window, not initially visible) */ 1231 static const struct message WmCreateMaximizedChildSeq[] = { 1232 { HCBT_CREATEWND, hook }, 1233 { WM_NCCREATE, sent }, 1234 { WM_NCCALCSIZE, sent|wparam, 0 }, 1235 { WM_CREATE, sent }, 1236 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1237 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 1238 { WM_MOVE, sent }, 1239 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 1240 { WM_GETMINMAXINFO, sent }, 1241 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_STATECHANGED }, 1242 { WM_NCCALCSIZE, sent|wparam, 1 }, 1243 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 1244 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 1245 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1246 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE }, 1247 { 0 } 1248 }; 1249 /* CreateWindow (for a child window, initially visible) */ 1250 static const struct message WmCreateVisibleChildSeq[] = { 1251 { HCBT_CREATEWND, hook }, 1252 { WM_NCCREATE, sent }, 1253 /* child is inserted into parent's child list after WM_NCCREATE returns */ 1254 { WM_NCCALCSIZE, sent|wparam, 0 }, 1255 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, 1256 { WM_CREATE, sent }, 1257 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1258 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 1259 { WM_MOVE, sent }, 1260 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE }, 1261 { WM_SHOWWINDOW, sent|wparam, 1 }, 1262 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, 1263 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1264 { WM_ERASEBKGND, sent|parent|optional }, 1265 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1266 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* WinXP */ 1267 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1268 { 0 } 1269 }; 1270 /* ShowWindow(SW_SHOW) for a not visible child window */ 1271 static const struct message WmShowChildSeq[] = { 1272 { WM_SHOWWINDOW, sent|wparam, 1 }, 1273 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1274 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1275 { WM_ERASEBKGND, sent|parent|optional }, 1276 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1277 { 0 } 1278 }; 1279 /* ShowWindow(SW_HIDE) for a visible child window */ 1280 static const struct message WmHideChildSeq[] = { 1281 { WM_SHOWWINDOW, sent|wparam, 0 }, 1282 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1283 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 1284 { WM_ERASEBKGND, sent|parent|optional }, 1285 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1286 { 0 } 1287 }; 1288 /* ShowWindow(SW_HIDE) for a visible child window checking all parent events*/ 1289 static const struct message WmHideChildSeq2[] = { 1290 { WM_SHOWWINDOW, sent|wparam, 0 }, 1291 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1292 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 1293 { WM_ERASEBKGND, sent|parent|optional }, 1294 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1295 { 0 } 1296 }; 1297 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE) 1298 * for a not visible child window 1299 */ 1300 static const struct message WmShowChildSeq_2[] = { 1301 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 1302 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1303 { WM_CHILDACTIVATE, sent }, 1304 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1305 { 0 } 1306 }; 1307 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE) 1308 * for a not visible child window 1309 */ 1310 static const struct message WmShowChildSeq_3[] = { 1311 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, 1312 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1313 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1314 { 0 } 1315 }; 1316 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE) 1317 * for a visible child window with a caption 1318 */ 1319 static const struct message WmShowChildSeq_4[] = { 1320 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 1321 { WM_CHILDACTIVATE, sent }, 1322 { 0 } 1323 }; 1324 /* ShowWindow(SW_MINIMIZE) for child with invisible parent */ 1325 static const struct message WmShowChildInvisibleParentSeq_1[] = { 1326 { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, 1327 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE }, 1328 { WM_NCCALCSIZE, sent|wparam, 1 }, 1329 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1330 { WM_CHILDACTIVATE, sent|optional }, 1331 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOREDRAW|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE }, 1332 { WM_MOVE, sent|defwinproc }, 1333 { WM_SIZE, sent|defwinproc|wparam|lparam, SIZE_MINIMIZED, 0 }, 1334 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1335 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 }, 1336 /* FIXME: Wine creates an icon/title window while Windows doesn't */ 1337 { WM_PARENTNOTIFY, sent|parent|wparam|optional, WM_CREATE }, 1338 { WM_GETTEXT, sent|optional }, 1339 { 0 } 1340 }; 1341 /* repeated ShowWindow(SW_MINIMIZE) for child with invisible parent */ 1342 static const struct message WmShowChildInvisibleParentSeq_1r[] = { 1343 { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, 1344 { 0 } 1345 }; 1346 /* ShowWindow(SW_MAXIMIZE) for child with invisible parent */ 1347 static const struct message WmShowChildInvisibleParentSeq_2[] = { 1348 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 1349 { WM_GETMINMAXINFO, sent }, 1350 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_STATECHANGED }, 1351 { WM_NCCALCSIZE, sent|wparam, 1 }, 1352 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1353 { WM_CHILDACTIVATE, sent }, 1354 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 1355 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 1356 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1357 { 0 } 1358 }; 1359 /* repeated ShowWindow(SW_MAXIMIZE) for child with invisible parent */ 1360 static const struct message WmShowChildInvisibleParentSeq_2r[] = { 1361 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 1362 { 0 } 1363 }; 1364 /* ShowWindow(SW_SHOWMINIMIZED) for child with invisible parent */ 1365 static const struct message WmShowChildInvisibleParentSeq_3[] = { 1366 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINIMIZED }, 1367 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 1368 { WM_NCCALCSIZE, sent|wparam, 1 }, 1369 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1370 { WM_CHILDACTIVATE, sent }, 1371 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOREDRAW|SWP_NOCOPYBITS|SWP_STATECHANGED }, 1372 { WM_MOVE, sent|defwinproc }, 1373 { WM_SIZE, sent|defwinproc|wparam|lparam, SIZE_MINIMIZED, 0 }, 1374 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1375 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 }, 1376 /* FIXME: Wine creates an icon/title window while Windows doesn't */ 1377 { WM_PARENTNOTIFY, sent|parent|wparam|optional, WM_CREATE }, 1378 { WM_GETTEXT, sent|optional }, 1379 { 0 } 1380 }; 1381 /* repeated ShowWindow(SW_SHOWMINIMIZED) for child with invisible parent */ 1382 static const struct message WmShowChildInvisibleParentSeq_3r[] = { 1383 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINIMIZED }, 1384 { 0 } 1385 }; 1386 /* ShowWindow(SW_SHOWMINNOACTIVE) for child with invisible parent */ 1387 static const struct message WmShowChildInvisibleParentSeq_4[] = { 1388 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINNOACTIVE }, 1389 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_STATECHANGED }, 1390 { WM_NCCALCSIZE, sent|wparam, 1 }, 1391 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1392 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOCOPYBITS|SWP_STATECHANGED }, 1393 { WM_MOVE, sent|defwinproc }, 1394 { WM_SIZE, sent|defwinproc|wparam|lparam, SIZE_MINIMIZED, 0 }, 1395 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1396 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 }, 1397 /* FIXME: Wine creates an icon/title window while Windows doesn't */ 1398 { WM_PARENTNOTIFY, sent|parent|wparam|optional, WM_CREATE }, 1399 { WM_GETTEXT, sent|optional }, 1400 { 0 } 1401 }; 1402 /* repeated ShowWindow(SW_SHOWMINNOACTIVE) for child with invisible parent */ 1403 static const struct message WmShowChildInvisibleParentSeq_4r[] = { 1404 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINNOACTIVE }, 1405 { 0 } 1406 }; 1407 /* ShowWindow(SW_SHOW) for child with invisible parent */ 1408 static const struct message WmShowChildInvisibleParentSeq_5[] = { 1409 { WM_SHOWWINDOW, sent|wparam, 1 }, 1410 { 0 } 1411 }; 1412 /* ShowWindow(SW_HIDE) for child with invisible parent */ 1413 static const struct message WmHideChildInvisibleParentSeq[] = { 1414 { WM_SHOWWINDOW, sent|wparam, 0 }, 1415 { 0 } 1416 }; 1417 /* SetWindowPos(SWP_SHOWWINDOW) for child with invisible parent */ 1418 static const struct message WmShowChildInvisibleParentSeq_6[] = { 1419 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, 1420 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1421 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1422 { 0 } 1423 }; 1424 /* SetWindowPos(SWP_HIDEWINDOW) for child with invisible parent */ 1425 static const struct message WmHideChildInvisibleParentSeq_2[] = { 1426 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1427 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 1428 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1429 { 0 } 1430 }; 1431 /* DestroyWindow for a visible child window */ 1432 static const struct message WmDestroyChildSeq[] = { 1433 { HCBT_DESTROYWND, hook }, 1434 { 0x0090, sent|optional }, 1435 { WM_PARENTNOTIFY, sent|parent|wparam, WM_DESTROY }, 1436 { WM_SHOWWINDOW, sent|wparam, 0 }, 1437 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1438 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 1439 { WM_ERASEBKGND, sent|parent|optional }, 1440 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1441 { HCBT_SETFOCUS, hook }, /* set focus to a parent */ 1442 { WM_KILLFOCUS, sent }, 1443 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 1444 { WM_IME_SETCONTEXT, sent|wparam|parent|optional, 1 }, 1445 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1446 { WM_SETFOCUS, sent|parent }, 1447 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, 1448 { WM_DESTROY, sent }, 1449 { WM_DESTROY, sent|optional }, /* some other (IME?) window */ 1450 { WM_NCDESTROY, sent|optional }, /* some other (IME?) window */ 1451 { WM_NCDESTROY, sent }, 1452 { 0 } 1453 }; 1454 /* visible child window destroyed by thread exit */ 1455 static const struct message WmExitThreadSeq[] = { 1456 { WM_NCDESTROY, sent }, /* actually in grandchild */ 1457 { WM_PAINT, sent|parent }, 1458 { WM_ERASEBKGND, sent|parent|beginpaint }, 1459 { 0 } 1460 }; 1461 /* DestroyWindow for a visible child window with invisible parent */ 1462 static const struct message WmDestroyInvisibleChildSeq[] = { 1463 { HCBT_DESTROYWND, hook }, 1464 { 0x0090, sent|optional }, 1465 { WM_PARENTNOTIFY, sent|parent|wparam, WM_DESTROY }, 1466 { WM_SHOWWINDOW, sent|wparam, 0 }, 1467 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, 1468 { WM_DESTROY, sent }, 1469 { WM_NCDESTROY, sent }, 1470 { 0 } 1471 }; 1472 /* Resizing child window with MoveWindow (32) */ 1473 static const struct message WmResizingChildWithMoveWindowSeq[] = { 1474 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE }, 1475 { WM_NCCALCSIZE, sent|wparam, 1 }, 1476 { WM_ERASEBKGND, sent|parent|optional }, 1477 { WM_ERASEBKGND, sent|optional }, 1478 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE }, 1479 { WM_MOVE, sent|defwinproc }, 1480 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 1481 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1482 { 0 } 1483 }; 1484 /* Creation of a custom dialog (32) */ 1485 static const struct message WmCreateCustomDialogSeq[] = { 1486 { HCBT_CREATEWND, hook }, 1487 { WM_GETMINMAXINFO, sent }, 1488 { WM_NCCREATE, sent }, 1489 { WM_NCCALCSIZE, sent|wparam, 0 }, 1490 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, 1491 { WM_CREATE, sent }, 1492 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1493 { WM_NOTIFYFORMAT, sent|optional }, 1494 { WM_QUERYUISTATE, sent|optional }, 1495 { WM_WINDOWPOSCHANGING, sent|optional }, 1496 { WM_GETMINMAXINFO, sent|optional }, 1497 { WM_NCCALCSIZE, sent|optional }, 1498 { WM_WINDOWPOSCHANGED, sent|optional }, 1499 { WM_SHOWWINDOW, sent|wparam, 1 }, 1500 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 1501 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1502 { HCBT_ACTIVATE, hook }, 1503 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 1504 1505 1506 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 1507 1508 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 1509 1510 { WM_NCACTIVATE, sent }, 1511 { WM_GETTEXT, sent|optional|defwinproc }, 1512 { WM_GETTEXT, sent|optional|defwinproc }, 1513 { WM_GETTEXT, sent|optional|defwinproc }, 1514 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 }, 1515 { WM_ACTIVATE, sent|wparam, 1 }, 1516 { WM_GETTEXT, sent|optional }, 1517 { WM_KILLFOCUS, sent|parent }, 1518 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, 1519 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 1520 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 1521 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1522 { WM_SETFOCUS, sent }, 1523 { WM_GETDLGCODE, sent|defwinproc|wparam, 0 }, 1524 { WM_NCPAINT, sent|wparam, 1 }, 1525 { WM_GETTEXT, sent|optional|defwinproc }, 1526 { WM_GETTEXT, sent|optional|defwinproc }, 1527 { WM_ERASEBKGND, sent }, 1528 { WM_CTLCOLORDLG, sent|optional|defwinproc }, 1529 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1530 { WM_GETTEXT, sent|optional }, 1531 { WM_GETTEXT, sent|optional }, 1532 { WM_NCCALCSIZE, sent|optional }, 1533 { WM_NCPAINT, sent|optional }, 1534 { WM_GETTEXT, sent|optional|defwinproc }, 1535 { WM_GETTEXT, sent|optional|defwinproc }, 1536 { WM_ERASEBKGND, sent|optional }, 1537 { WM_CTLCOLORDLG, sent|optional|defwinproc }, 1538 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1539 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 1540 { WM_MOVE, sent }, 1541 { 0 } 1542 }; 1543 /* Calling EndDialog for a custom dialog (32) */ 1544 static const struct message WmEndCustomDialogSeq[] = { 1545 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1546 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 1547 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1548 { WM_GETTEXT, sent|optional }, 1549 { HCBT_ACTIVATE, hook }, 1550 { WM_NCACTIVATE, sent|wparam, 0 }, 1551 { WM_GETTEXT, sent|optional|defwinproc }, 1552 { WM_GETTEXT, sent|optional|defwinproc }, 1553 { WM_ACTIVATE, sent|wparam, 0 }, 1554 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 1555 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1556 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1557 { WM_GETTEXT, sent|optional|defwinproc }, 1558 { WM_GETTEXT, sent|optional|defwinproc }, 1559 { HCBT_SETFOCUS, hook }, 1560 { WM_KILLFOCUS, sent }, 1561 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 1562 { WM_IME_SETCONTEXT, sent|parent|wparam|defwinproc|optional, 1 }, 1563 { WM_IME_NOTIFY, sent|wparam|optional, 1 }, 1564 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1565 { WM_SETFOCUS, sent|parent|defwinproc }, 1566 { 0 } 1567 }; 1568 /* ShowWindow(SW_SHOW) for a custom dialog (initially invisible) */ 1569 static const struct message WmShowCustomDialogSeq[] = { 1570 { WM_SHOWWINDOW, sent|wparam, 1 }, 1571 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 1572 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1573 { HCBT_ACTIVATE, hook }, 1574 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 1575 1576 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 1577 1578 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 1579 { WM_ACTIVATEAPP, sent|wparam|optional, 1 }, 1580 { WM_NCACTIVATE, sent }, 1581 { WM_ACTIVATE, sent|wparam, 1 }, 1582 { WM_GETTEXT, sent|optional }, 1583 1584 { WM_KILLFOCUS, sent|parent }, 1585 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, 1586 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 1587 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 1588 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1589 { WM_SETFOCUS, sent }, 1590 { WM_GETDLGCODE, sent|defwinproc|wparam, 0 }, 1591 { WM_NCPAINT, sent|wparam, 1 }, 1592 { WM_ERASEBKGND, sent }, 1593 { WM_CTLCOLORDLG, sent|defwinproc }, 1594 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1595 { 0 } 1596 }; 1597 /* Creation and destruction of a modal dialog (32) */ 1598 static const struct message WmModalDialogSeq[] = { 1599 { WM_CANCELMODE, sent|parent }, 1600 { HCBT_SETFOCUS, hook }, 1601 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1602 { WM_KILLFOCUS, sent|parent }, 1603 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, 1604 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1605 { WM_ENABLE, sent|parent|wparam, 0 }, 1606 { HCBT_CREATEWND, hook }, 1607 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, 1608 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1609 { WM_SETFONT, sent }, 1610 { WM_INITDIALOG, sent }, 1611 { WM_CHANGEUISTATE, sent|optional }, 1612 { WM_UPDATEUISTATE, sent|optional }, 1613 { WM_SHOWWINDOW, sent }, 1614 { HCBT_ACTIVATE, hook }, 1615 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 1616 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 1617 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE }, 1618 { WM_NCACTIVATE, sent }, 1619 { WM_GETTEXT, sent|optional }, 1620 { WM_ACTIVATE, sent|wparam, 1 }, 1621 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, 1622 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1623 { WM_NCPAINT, sent|optional }, 1624 { WM_GETTEXT, sent|optional }, 1625 { WM_ERASEBKGND, sent|optional }, 1626 { WM_CTLCOLORDLG, sent|optional }, 1627 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1628 { WM_GETTEXT, sent|optional }, 1629 { WM_NCCALCSIZE, sent|optional }, 1630 { WM_NCPAINT, sent|optional }, 1631 { WM_GETTEXT, sent|optional }, 1632 { WM_ERASEBKGND, sent|optional }, 1633 { WM_CTLCOLORDLG, sent|optional }, 1634 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1635 { WM_PAINT, sent|optional }, 1636 { WM_CTLCOLORBTN, sent|optional }, 1637 { WM_GETTITLEBARINFOEX, sent|optional }, 1638 { WM_ENTERIDLE, sent|parent|optional }, 1639 { WM_ENTERIDLE, sent|parent|optional }, 1640 { WM_ENTERIDLE, sent|parent|optional }, 1641 { WM_ENTERIDLE, sent|parent|optional }, 1642 { WM_ENTERIDLE, sent|parent|optional }, 1643 { WM_ENTERIDLE, sent|parent|optional }, 1644 { WM_ENTERIDLE, sent|parent|optional }, 1645 { WM_ENTERIDLE, sent|parent|optional }, 1646 { WM_ENTERIDLE, sent|parent|optional }, 1647 { WM_ENTERIDLE, sent|parent|optional }, 1648 { WM_ENTERIDLE, sent|parent|optional }, 1649 { WM_ENTERIDLE, sent|parent|optional }, 1650 { WM_ENTERIDLE, sent|parent|optional }, 1651 { WM_ENTERIDLE, sent|parent|optional }, 1652 { WM_ENTERIDLE, sent|parent|optional }, 1653 { WM_ENTERIDLE, sent|parent|optional }, 1654 { WM_ENTERIDLE, sent|parent|optional }, 1655 { WM_ENTERIDLE, sent|parent|optional }, 1656 { WM_ENTERIDLE, sent|parent|optional }, 1657 { WM_ENTERIDLE, sent|parent|optional }, 1658 { WM_TIMER, sent }, 1659 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1660 { WM_ENABLE, sent|parent|wparam, 1 }, 1661 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, 1662 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 1663 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1664 { WM_GETTEXT, sent|optional }, 1665 { HCBT_ACTIVATE, hook }, 1666 { WM_NCACTIVATE, sent|wparam, 0 }, 1667 { WM_GETTEXT, sent|optional }, 1668 { WM_ACTIVATE, sent|wparam, 0 }, 1669 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 1670 { WM_WINDOWPOSCHANGING, sent|optional }, 1671 { WM_WINDOWPOSCHANGED, sent|optional }, 1672 { HCBT_SETFOCUS, hook }, 1673 { WM_IME_SETCONTEXT, sent|parent|wparam|defwinproc|optional, 1 }, 1674 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1675 { WM_SETFOCUS, sent|parent|defwinproc }, 1676 { EVENT_SYSTEM_DIALOGEND, winevent_hook|wparam|lparam, 0, 0 }, 1677 { HCBT_DESTROYWND, hook }, 1678 { 0x0090, sent|optional }, 1679 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, 1680 { WM_DESTROY, sent }, 1681 { WM_NCDESTROY, sent }, 1682 { 0 } 1683 }; 1684 static const struct message WmModalDialogSeq_2[] = { 1685 { WM_CANCELMODE, sent }, 1686 { HCBT_SETFOCUS, hook }, 1687 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1688 { WM_KILLFOCUS, sent }, 1689 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, 1690 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1691 { WM_ENABLE, sent|wparam, 0 }, 1692 { HCBT_CREATEWND, hook }, 1693 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, 1694 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1695 { WM_SETFONT, sent }, 1696 { WM_INITDIALOG, sent }, 1697 { WM_CHANGEUISTATE, sent|optional }, 1698 { WM_UPDATEUISTATE, sent|optional }, 1699 { WM_ENABLE, sent|wparam, 1 }, 1700 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, 1701 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 1702 { WM_CHANGEUISTATE, sent|optional }, 1703 { WM_UPDATEUISTATE, sent|optional }, 1704 { HCBT_DESTROYWND, hook }, 1705 { 0x0090, sent|optional }, 1706 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, 1707 { WM_DESTROY, sent }, 1708 { WM_NCDESTROY, sent }, 1709 { 0 } 1710 }; 1711 /* SetMenu for NonVisible windows with size change*/ 1712 static const struct message WmSetMenuNonVisibleSizeChangeSeq[] = { 1713 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1714 { WM_NCCALCSIZE, sent|wparam, 1 }, 1715 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, 1716 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW }, 1717 { WM_MOVE, sent|defwinproc }, 1718 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 1719 { WM_NCCALCSIZE,sent|wparam|optional, 1 }, /* XP */ 1720 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1721 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP sends a duplicate */ 1722 { WM_GETTEXT, sent|optional }, 1723 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, 1724 { 0 } 1725 }; 1726 /* SetMenu for NonVisible windows with no size change */ 1727 static const struct message WmSetMenuNonVisibleNoSizeChangeSeq[] = { 1728 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1729 { WM_NCCALCSIZE, sent|wparam, 1 }, 1730 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1731 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1732 { 0 } 1733 }; 1734 /* SetMenu for Visible windows with size change */ 1735 static const struct message WmSetMenuVisibleSizeChangeSeq[] = { 1736 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1737 { WM_NCCALCSIZE, sent|wparam, 1 }, 1738 { 0x0093, sent|defwinproc|optional }, 1739 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, 1740 { WM_NCPAINT, sent|optional }, /* wparam != 1 */ 1741 { 0x0093, sent|defwinproc|optional }, 1742 { 0x0093, sent|defwinproc|optional }, 1743 { 0x0091, sent|defwinproc|optional }, 1744 { 0x0092, sent|defwinproc|optional }, 1745 { WM_GETTEXT, sent|defwinproc|optional }, 1746 { WM_ERASEBKGND, sent|optional }, 1747 { WM_ACTIVATE, sent|optional }, 1748 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1749 { WM_MOVE, sent|defwinproc }, 1750 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 1751 { 0x0093, sent|optional }, 1752 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, 1753 { 0x0093, sent|defwinproc|optional }, 1754 { WM_NCPAINT, sent|optional }, /* wparam != 1 */ 1755 { 0x0093, sent|defwinproc|optional }, 1756 { 0x0093, sent|defwinproc|optional }, 1757 { 0x0091, sent|defwinproc|optional }, 1758 { 0x0092, sent|defwinproc|optional }, 1759 { WM_ERASEBKGND, sent|optional }, 1760 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1761 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP sends a duplicate */ 1762 { 0 } 1763 }; 1764 /* SetMenu for Visible windows with no size change */ 1765 static const struct message WmSetMenuVisibleNoSizeChangeSeq[] = { 1766 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1767 { WM_NCCALCSIZE, sent|wparam, 1 }, 1768 { WM_NCPAINT, sent|optional }, /* wparam != 1 */ 1769 { WM_GETTEXT, sent|defwinproc|optional }, 1770 { WM_ERASEBKGND, sent|optional }, 1771 { WM_ACTIVATE, sent|optional }, 1772 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1773 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1774 { 0 } 1775 }; 1776 /* DrawMenuBar for a visible window */ 1777 static const struct message WmDrawMenuBarSeq[] = 1778 { 1779 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1780 { WM_NCCALCSIZE, sent|wparam, 1 }, 1781 { 0x0093, sent|defwinproc|optional }, 1782 { WM_NCPAINT, sent|optional }, /* wparam != 1 */ 1783 { 0x0093, sent|defwinproc|optional }, 1784 { 0x0093, sent|defwinproc|optional }, 1785 { 0x0091, sent|defwinproc|optional }, 1786 { 0x0092, sent|defwinproc|optional }, 1787 { WM_GETTEXT, sent|defwinproc|optional }, 1788 { WM_ERASEBKGND, sent|optional }, 1789 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1790 { 0x0093, sent|optional }, 1791 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1792 { 0 } 1793 }; 1794 1795 static const struct message WmSetRedrawFalseSeq[] = 1796 { 1797 { WM_SETREDRAW, sent|wparam, 0 }, 1798 { 0 } 1799 }; 1800 1801 static const struct message WmSetRedrawTrueSeq[] = 1802 { 1803 { WM_SETREDRAW, sent|wparam, 1 }, 1804 { 0 } 1805 }; 1806 1807 static const struct message WmEnableWindowSeq_1[] = 1808 { 1809 { WM_CANCELMODE, sent|wparam|lparam, 0, 0 }, 1810 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1811 { HCBT_SETFOCUS, hook|optional }, 1812 { WM_KILLFOCUS, sent|optional }, 1813 { WM_ENABLE, sent|wparam|lparam, FALSE, 0 }, 1814 { 0 } 1815 }; 1816 1817 static const struct message WmEnableWindowSeq_2[] = 1818 { 1819 { WM_CANCELMODE, sent|wparam|lparam, 0, 0 }, 1820 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1821 { 0 } 1822 }; 1823 1824 static const struct message WmEnableWindowSeq_3[] = 1825 { 1826 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1827 { WM_ENABLE, sent|wparam|lparam, TRUE, 0 }, 1828 { 0 } 1829 }; 1830 1831 static const struct message WmEnableWindowSeq_4[] = 1832 { 1833 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1834 { 0 } 1835 }; 1836 1837 static const struct message WmGetScrollRangeSeq[] = 1838 { 1839 { SBM_GETRANGE, sent }, 1840 { 0 } 1841 }; 1842 static const struct message WmGetScrollInfoSeq[] = 1843 { 1844 { SBM_GETSCROLLINFO, sent }, 1845 { 0 } 1846 }; 1847 static const struct message WmSetScrollRangeSeq[] = 1848 { 1849 /* MSDN claims that Windows sends SBM_SETRANGE message, but win2k SP4 1850 sends SBM_SETSCROLLINFO. 1851 */ 1852 { SBM_SETSCROLLINFO, sent }, 1853 { 0 } 1854 }; 1855 /* SetScrollRange for a window without a non-client area */ 1856 static const struct message WmSetScrollRangeHSeq_empty[] = 1857 { 1858 { EVENT_OBJECT_VALUECHANGE, winevent_hook|wparam|lparam, OBJID_HSCROLL, 0 }, 1859 { 0 } 1860 }; 1861 static const struct message WmSetScrollRangeVSeq_empty[] = 1862 { 1863 { EVENT_OBJECT_VALUECHANGE, winevent_hook|wparam|lparam, OBJID_VSCROLL, 0 }, 1864 { 0 } 1865 }; 1866 static const struct message WmSetScrollRangeHVSeq[] = 1867 { 1868 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE }, 1869 { WM_NCCALCSIZE, sent|wparam, 1 }, 1870 { WM_GETTEXT, sent|defwinproc|optional }, 1871 { WM_ERASEBKGND, sent|optional }, 1872 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1873 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1874 { EVENT_OBJECT_VALUECHANGE, winevent_hook|lparam|optional, 0/*OBJID_HSCROLL or OBJID_VSCROLL*/, 0 }, 1875 { 0 } 1876 }; 1877 /* SetScrollRange for a window with a non-client area */ 1878 static const struct message WmSetScrollRangeHV_NC_Seq[] = 1879 { 1880 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE }, 1881 { WM_NCCALCSIZE, sent|wparam, 1 }, 1882 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, 1883 { WM_NCPAINT, sent|optional }, 1884 { WM_STYLECHANGING, sent|defwinproc|optional }, 1885 { WM_STYLECHANGED, sent|defwinproc|optional }, 1886 { WM_STYLECHANGING, sent|defwinproc|optional }, 1887 { WM_STYLECHANGED, sent|defwinproc|optional }, 1888 { WM_STYLECHANGING, sent|defwinproc|optional }, 1889 { WM_STYLECHANGED, sent|defwinproc|optional }, 1890 { WM_STYLECHANGING, sent|defwinproc|optional }, 1891 { WM_STYLECHANGED, sent|defwinproc|optional }, 1892 { WM_GETTEXT, sent|defwinproc|optional }, 1893 { WM_GETTEXT, sent|defwinproc|optional }, 1894 { WM_ERASEBKGND, sent|optional }, 1895 { WM_CTLCOLORDLG, sent|defwinproc|optional }, /* sent to a parent of the dialog */ 1896 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOCLIENTMOVE, 0, SWP_NOCLIENTSIZE }, 1897 { WM_SIZE, sent|defwinproc|optional }, 1898 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1899 { EVENT_OBJECT_VALUECHANGE, winevent_hook|lparam|optional, 0/*OBJID_HSCROLL or OBJID_VSCROLL*/, 0 }, 1900 { WM_GETTEXT, sent|optional }, 1901 { WM_GETTEXT, sent|optional }, 1902 { WM_GETTEXT, sent|optional }, 1903 { WM_GETTEXT, sent|optional }, 1904 { 0 } 1905 }; 1906 /* test if we receive the right sequence of messages */ 1907 /* after calling ShowWindow( SW_SHOWNA) */ 1908 static const struct message WmSHOWNAChildInvisParInvis[] = { 1909 { WM_SHOWWINDOW, sent|wparam, 1 }, 1910 { 0 } 1911 }; 1912 static const struct message WmSHOWNAChildVisParInvis[] = { 1913 { WM_SHOWWINDOW, sent|wparam, 1 }, 1914 { 0 } 1915 }; 1916 static const struct message WmSHOWNAChildVisParVis[] = { 1917 { WM_SHOWWINDOW, sent|wparam, 1 }, 1918 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, 1919 { 0 } 1920 }; 1921 static const struct message WmSHOWNAChildInvisParVis[] = { 1922 { WM_SHOWWINDOW, sent|wparam, 1 }, 1923 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1924 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1925 { WM_ERASEBKGND, sent|optional }, 1926 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOACTIVATE|SWP_NOCLIENTMOVE }, 1927 { 0 } 1928 }; 1929 static const struct message WmSHOWNATopVisible[] = { 1930 { WM_SHOWWINDOW, sent|wparam, 1 }, 1931 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, 1932 { WM_NCPAINT, sent|wparam|optional, 1 }, 1933 { WM_GETTEXT, sent|defwinproc|optional }, 1934 { WM_ERASEBKGND, sent|optional }, 1935 { WM_WINDOWPOSCHANGED, sent|optional }, 1936 { 0 } 1937 }; 1938 static const struct message WmSHOWNATopInvisible[] = { 1939 { WM_NOTIFYFORMAT, sent|optional }, 1940 { WM_QUERYUISTATE, sent|optional }, 1941 { WM_WINDOWPOSCHANGING, sent|optional }, 1942 { WM_GETMINMAXINFO, sent|optional }, 1943 { WM_NCCALCSIZE, sent|optional }, 1944 { WM_WINDOWPOSCHANGED, sent|optional }, 1945 { WM_SHOWWINDOW, sent|wparam, 1 }, 1946 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1947 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1948 { WM_NCPAINT, sent|wparam|optional, 1 }, 1949 { WM_GETTEXT, sent|defwinproc|optional }, 1950 { WM_ERASEBKGND, sent|optional }, 1951 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1952 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, 1953 { WM_NCPAINT, sent|wparam|optional, 1 }, 1954 { WM_ERASEBKGND, sent|optional }, 1955 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1956 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 1957 { WM_MOVE, sent }, 1958 { 0 } 1959 }; 1960 1961 static const struct message WmTrackPopupMenu[] = { 1962 { HCBT_CREATEWND, hook }, 1963 { WM_ENTERMENULOOP, sent|wparam|lparam, TRUE, 0 }, 1964 { WM_INITMENU, sent|lparam, 0, 0 }, 1965 { WM_INITMENUPOPUP, sent|lparam, 0, 0 }, 1966 { 0x0093, sent|optional }, 1967 { 0x0094, sent|optional }, 1968 { 0x0094, sent|optional }, 1969 { WM_ENTERIDLE, sent|wparam, 2 }, 1970 { WM_CAPTURECHANGED, sent }, 1971 { HCBT_DESTROYWND, hook }, 1972 { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, 1973 { WM_MENUSELECT, sent|wparam|lparam, 0xffff0000, 0 }, 1974 { WM_EXITMENULOOP, sent|wparam|lparam, 1, 0 }, 1975 { 0 } 1976 }; 1977 1978 static const struct message WmTrackPopupMenuEsc[] = { 1979 { 0 } 1980 }; 1981 1982 static const struct message WmTrackPopupMenuCapture[] = { 1983 { HCBT_CREATEWND, hook }, 1984 { WM_ENTERMENULOOP, sent|wparam|lparam, TRUE, 0 }, 1985 { WM_CAPTURECHANGED, sent }, 1986 { WM_INITMENU, sent|lparam, 0, 0 }, 1987 { WM_INITMENUPOPUP, sent|lparam, 0, 0 }, 1988 { 0x0093, sent|optional }, 1989 { 0x0094, sent|optional }, 1990 { 0x0094, sent|optional }, 1991 { WM_ENTERIDLE, sent|wparam, 2 }, 1992 { WM_CAPTURECHANGED, sent }, 1993 { HCBT_DESTROYWND, hook }, 1994 { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, 1995 { WM_MENUSELECT, sent|wparam|lparam, 0xffff0000, 0 }, 1996 { WM_EXITMENULOOP, sent|wparam|lparam, 1, 0 }, 1997 { 0 } 1998 }; 1999 2000 static const struct message WmTrackPopupMenuEmpty[] = { 2001 { HCBT_CREATEWND, hook }, 2002 { WM_ENTERMENULOOP, sent|wparam|lparam, TRUE, 0 }, 2003 { WM_INITMENU, sent|lparam, 0, 0 }, 2004 { WM_INITMENUPOPUP, sent|lparam, 0, 0 }, 2005 { 0x0093, sent|optional }, 2006 { 0x0094, sent|optional }, 2007 { 0x0094, sent|optional }, 2008 { WM_CAPTURECHANGED, sent }, 2009 { WM_EXITMENULOOP, sent|wparam|lparam, 1, 0 }, 2010 { HCBT_DESTROYWND, hook }, 2011 { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, 2012 { 0 } 2013 }; 2014 2015 static const struct message WmTrackPopupMenuAbort[] = { 2016 { HCBT_CREATEWND, hook }, 2017 { WM_ENTERMENULOOP, sent|wparam|lparam, TRUE, 0 }, 2018 { WM_INITMENU, sent|lparam, 0, 0 }, 2019 { WM_INITMENUPOPUP, sent|lparam, 0, 0 }, 2020 { 0x0093, sent|optional }, 2021 { 0x0094, sent|optional }, 2022 { 0x0094, sent|optional }, 2023 { WM_CAPTURECHANGED, sent }, 2024 { HCBT_DESTROYWND, hook }, 2025 { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, 2026 { WM_MENUSELECT, sent|wparam|lparam, 0xffff0000, 0 }, 2027 { WM_EXITMENULOOP, sent|wparam|lparam, 1, 0 }, 2028 { 0 } 2029 }; 2030 2031 static BOOL after_end_dialog, test_def_id, paint_loop_done; 2032 static int sequence_cnt, sequence_size; 2033 static struct recvd_message* sequence; 2034 static int log_all_parent_messages; 2035 static CRITICAL_SECTION sequence_cs; 2036 2037 /* user32 functions */ 2038 static HWND (WINAPI *pGetAncestor)(HWND,UINT); 2039 static BOOL (WINAPI *pGetMenuInfo)(HMENU,LPCMENUINFO); 2040 static void (WINAPI *pNotifyWinEvent)(DWORD, HWND, LONG, LONG); 2041 static BOOL (WINAPI *pSetMenuInfo)(HMENU,LPCMENUINFO); 2042 static HWINEVENTHOOK (WINAPI *pSetWinEventHook)(DWORD, DWORD, HMODULE, WINEVENTPROC, DWORD, DWORD, DWORD); 2043 static BOOL (WINAPI *pTrackMouseEvent)(TRACKMOUSEEVENT*); 2044 static BOOL (WINAPI *pUnhookWinEvent)(HWINEVENTHOOK); 2045 static BOOL (WINAPI *pGetMonitorInfoA)(HMONITOR,LPMONITORINFO); 2046 static HMONITOR (WINAPI *pMonitorFromPoint)(POINT,DWORD); 2047 static BOOL (WINAPI *pUpdateLayeredWindow)(HWND,HDC,POINT*,SIZE*,HDC,POINT*,COLORREF,BLENDFUNCTION*,DWORD); 2048 static UINT_PTR (WINAPI *pSetSystemTimer)(HWND, UINT_PTR, UINT, TIMERPROC); 2049 static UINT_PTR (WINAPI *pKillSystemTimer)(HWND, UINT_PTR); 2050 static UINT_PTR (WINAPI *pSetCoalescableTimer)(HWND, UINT_PTR, UINT, TIMERPROC, ULONG); 2051 /* kernel32 functions */ 2052 static BOOL (WINAPI *pGetCPInfoExA)(UINT, DWORD, LPCPINFOEXA); 2053 2054 static void init_procs(void) 2055 { 2056 HMODULE user32 = GetModuleHandleA("user32.dll"); 2057 HMODULE kernel32 = GetModuleHandleA("kernel32.dll"); 2058 2059 #define GET_PROC(dll, func) \ 2060 p ## func = (void*)GetProcAddress(dll, #func); \ 2061 if(!p ## func) { \ 2062 trace("GetProcAddress(%s) failed\n", #func); \ 2063 } 2064 2065 GET_PROC(user32, GetAncestor) 2066 GET_PROC(user32, GetMenuInfo) 2067 GET_PROC(user32, NotifyWinEvent) 2068 GET_PROC(user32, SetMenuInfo) 2069 GET_PROC(user32, SetWinEventHook) 2070 GET_PROC(user32, TrackMouseEvent) 2071 GET_PROC(user32, UnhookWinEvent) 2072 GET_PROC(user32, GetMonitorInfoA) 2073 GET_PROC(user32, MonitorFromPoint) 2074 GET_PROC(user32, UpdateLayeredWindow) 2075 GET_PROC(user32, SetSystemTimer) 2076 GET_PROC(user32, KillSystemTimer) 2077 GET_PROC(user32, SetCoalescableTimer) 2078 2079 GET_PROC(kernel32, GetCPInfoExA) 2080 2081 #undef GET_PROC 2082 } 2083 2084 static const char *get_winpos_flags(UINT flags) 2085 { 2086 static char buffer[300]; 2087 2088 buffer[0] = 0; 2089 #define DUMP(flag) do { if (flags & flag) { strcat( buffer, "|" #flag ); flags &= ~flag; } } while(0) 2090 DUMP( SWP_SHOWWINDOW ); 2091 DUMP( SWP_HIDEWINDOW ); 2092 DUMP( SWP_NOACTIVATE ); 2093 DUMP( SWP_FRAMECHANGED ); 2094 DUMP( SWP_NOCOPYBITS ); 2095 DUMP( SWP_NOOWNERZORDER ); 2096 DUMP( SWP_NOSENDCHANGING ); 2097 DUMP( SWP_DEFERERASE ); 2098 DUMP( SWP_ASYNCWINDOWPOS ); 2099 DUMP( SWP_NOZORDER ); 2100 DUMP( SWP_NOREDRAW ); 2101 DUMP( SWP_NOSIZE ); 2102 DUMP( SWP_NOMOVE ); 2103 DUMP( SWP_NOCLIENTSIZE ); 2104 DUMP( SWP_NOCLIENTMOVE ); 2105 if (flags) sprintf(buffer + strlen(buffer),"|0x%04x", flags); 2106 return buffer + 1; 2107 #undef DUMP 2108 } 2109 2110 static BOOL ignore_message( UINT message ) 2111 { 2112 /* these are always ignored */ 2113 return (message >= 0xc000 || 2114 message == WM_GETICON || 2115 message == WM_GETOBJECT || 2116 message == WM_TIMECHANGE || 2117 message == WM_DISPLAYCHANGE || 2118 message == WM_DEVICECHANGE || 2119 message == WM_DWMNCRENDERINGCHANGED); 2120 } 2121 2122 static unsigned hash_Ly_W(const WCHAR *str) 2123 { 2124 unsigned hash = 0; 2125 2126 for (; *str; str++) 2127 hash = hash * 1664525u + (unsigned char)(*str) + 1013904223u; 2128 2129 return hash; 2130 } 2131 2132 static unsigned hash_Ly(const char *str) 2133 { 2134 unsigned hash = 0; 2135 2136 for (; *str; str++) 2137 hash = hash * 1664525u + (unsigned char)(*str) + 1013904223u; 2138 2139 return hash; 2140 } 2141 2142 #define add_message(msg) add_message_(__LINE__,msg); 2143 static void add_message_(int line, const struct recvd_message *msg) 2144 { 2145 struct recvd_message *seq; 2146 2147 EnterCriticalSection( &sequence_cs ); 2148 if (!sequence) 2149 { 2150 sequence_size = 10; 2151 sequence = HeapAlloc( GetProcessHeap(), 0, sequence_size * sizeof(*sequence) ); 2152 } 2153 if (sequence_cnt == sequence_size) 2154 { 2155 sequence_size *= 2; 2156 sequence = HeapReAlloc( GetProcessHeap(), 0, sequence, sequence_size * sizeof(*sequence) ); 2157 } 2158 assert(sequence); 2159 2160 seq = &sequence[sequence_cnt++]; 2161 seq->hwnd = msg->hwnd; 2162 seq->message = msg->message; 2163 seq->flags = msg->flags; 2164 seq->wParam = msg->wParam; 2165 seq->lParam = msg->lParam; 2166 seq->line = line; 2167 seq->descr = msg->descr; 2168 seq->output[0] = 0; 2169 LeaveCriticalSection( &sequence_cs ); 2170 2171 if (msg->descr) 2172 { 2173 if (msg->flags & hook) 2174 { 2175 static const char * const CBT_code_name[10] = 2176 { 2177 "HCBT_MOVESIZE", 2178 "HCBT_MINMAX", 2179 "HCBT_QS", 2180 "HCBT_CREATEWND", 2181 "HCBT_DESTROYWND", 2182 "HCBT_ACTIVATE", 2183 "HCBT_CLICKSKIPPED", 2184 "HCBT_KEYSKIPPED", 2185 "HCBT_SYSCOMMAND", 2186 "HCBT_SETFOCUS" 2187 }; 2188 const char *code_name = (msg->message <= HCBT_SETFOCUS) ? CBT_code_name[msg->message] : "Unknown"; 2189 2190 sprintf( seq->output, "%s: hook %d (%s) wp %08lx lp %08lx", 2191 msg->descr, msg->message, code_name, msg->wParam, msg->lParam ); 2192 } 2193 else if (msg->flags & winevent_hook) 2194 { 2195 sprintf( seq->output, "%s: winevent %p %08x %08lx %08lx", 2196 msg->descr, msg->hwnd, msg->message, msg->wParam, msg->lParam ); 2197 } 2198 else 2199 { 2200 switch (msg->message) 2201 { 2202 case WM_WINDOWPOSCHANGING: 2203 case WM_WINDOWPOSCHANGED: 2204 { 2205 WINDOWPOS *winpos = (WINDOWPOS *)msg->lParam; 2206 2207 sprintf( seq->output, "%s: %p WM_WINDOWPOS%s wp %08lx lp %08lx after %p x %d y %d cx %d cy %d flags %s", 2208 msg->descr, msg->hwnd, 2209 (msg->message == WM_WINDOWPOSCHANGING) ? "CHANGING" : "CHANGED", 2210 msg->wParam, msg->lParam, winpos->hwndInsertAfter, 2211 winpos->x, winpos->y, winpos->cx, winpos->cy, 2212 get_winpos_flags(winpos->flags) ); 2213 2214 /* Log only documented flags, win2k uses 0x1000 and 0x2000 2215 * in the high word for internal purposes 2216 */ 2217 seq->wParam = winpos->flags & 0xffff; 2218 /* We are not interested in the flags that don't match under XP and Win9x */ 2219 seq->wParam &= ~SWP_NOZORDER; 2220 break; 2221 } 2222 2223 case WM_DRAWITEM: 2224 { 2225 DRAW_ITEM_STRUCT di; 2226 DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)msg->lParam; 2227 2228 sprintf( seq->output, "%s: %p WM_DRAWITEM: type %x, ctl_id %x, item_id %x, action %x, state %x", 2229 msg->descr, msg->hwnd, dis->CtlType, dis->CtlID, 2230 dis->itemID, dis->itemAction, dis->itemState); 2231 2232 di.u.lp = 0; 2233 di.u.item.type = dis->CtlType; 2234 di.u.item.ctl_id = dis->CtlID; 2235 if (dis->CtlType == ODT_LISTBOX || 2236 dis->CtlType == ODT_COMBOBOX || 2237 dis->CtlType == ODT_MENU) 2238 di.u.item.item_id = dis->itemID; 2239 di.u.item.action = dis->itemAction; 2240 di.u.item.state = dis->itemState; 2241 2242 seq->lParam = di.u.lp; 2243 break; 2244 } 2245 2246 case WM_MEASUREITEM: 2247 { 2248 MEASURE_ITEM_STRUCT mi; 2249 MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *)msg->lParam; 2250 BOOL is_unicode_data = TRUE; 2251 2252 sprintf( seq->output, "%s: %p WM_MEASUREITEM: CtlType %#x, CtlID %#x, itemID %#x, itemData %#lx", 2253 msg->descr, msg->hwnd, mis->CtlType, mis->CtlID, 2254 mis->itemID, mis->itemData); 2255 2256 if (mis->CtlType == ODT_LISTBOX) 2257 { 2258 HWND ctrl = GetDlgItem(msg->hwnd, mis->CtlID); 2259 is_unicode_data = GetWindowLongA(ctrl, GWL_STYLE) & LBS_HASSTRINGS; 2260 } 2261 2262 mi.u.wp = 0; 2263 mi.u.item.CtlType = mis->CtlType; 2264 mi.u.item.CtlID = mis->CtlID; 2265 mi.u.item.itemID = mis->itemID; 2266 mi.u.item.wParam = msg->wParam; 2267 seq->wParam = mi.u.wp; 2268 if (is_unicode_data) 2269 seq->lParam = mis->itemData ? hash_Ly_W((const WCHAR *)mis->itemData) : 0; 2270 else 2271 seq->lParam = mis->itemData ? hash_Ly((const char *)mis->itemData) : 0; 2272 break; 2273 } 2274 2275 case WM_COMPAREITEM: 2276 { 2277 COMPAREITEMSTRUCT *cis = (COMPAREITEMSTRUCT *)msg->lParam; 2278 HWND ctrl = GetDlgItem(msg->hwnd, cis->CtlID); 2279 BOOL is_unicode_data = TRUE; 2280 2281 ok(msg->wParam == cis->CtlID, "expected %#x, got %#lx\n", cis->CtlID, msg->wParam); 2282 ok(cis->hwndItem == ctrl, "expected %p, got %p\n", ctrl, cis->hwndItem); 2283 ok((int)cis->itemID1 >= 0, "expected >= 0, got %d\n", cis->itemID1); 2284 ok((int)cis->itemID2 == -1, "expected -1, got %d\n", cis->itemID2); 2285 2286 sprintf( seq->output, "%s: %p WM_COMPAREITEM: CtlType %#x, CtlID %#x, itemID1 %#x, itemData1 %#lx, itemID2 %#x, itemData2 %#lx", 2287 msg->descr, msg->hwnd, cis->CtlType, cis->CtlID, 2288 cis->itemID1, cis->itemData1, cis->itemID2, cis->itemData2); 2289 2290 if (cis->CtlType == ODT_LISTBOX) 2291 is_unicode_data = GetWindowLongA(ctrl, GWL_STYLE) & LBS_HASSTRINGS; 2292 2293 if (is_unicode_data) 2294 { 2295 seq->wParam = cis->itemData1 ? hash_Ly_W((const WCHAR *)cis->itemData1) : 0; 2296 seq->lParam = cis->itemData2 ? hash_Ly_W((const WCHAR *)cis->itemData2) : 0; 2297 } 2298 else 2299 { 2300 seq->wParam = cis->itemData1 ? hash_Ly((const char *)cis->itemData1) : 0; 2301 seq->lParam = cis->itemData2 ? hash_Ly((const char *)cis->itemData2) : 0; 2302 } 2303 break; 2304 } 2305 2306 default: 2307 if (msg->message >= 0xc000) return; /* ignore registered messages */ 2308 sprintf( seq->output, "%s: %p %04x wp %08lx lp %08lx", 2309 msg->descr, msg->hwnd, msg->message, msg->wParam, msg->lParam ); 2310 } 2311 if (msg->flags & (sent|posted|parent|defwinproc|beginpaint)) 2312 sprintf( seq->output + strlen(seq->output), " (flags %x)", msg->flags ); 2313 } 2314 } 2315 } 2316 2317 /* try to make sure pending X events have been processed before continuing */ 2318 static void flush_events(void) 2319 { 2320 MSG msg; 2321 int diff = 200; 2322 int min_timeout = 100; 2323 DWORD time = GetTickCount() + diff; 2324 2325 while (diff > 0) 2326 { 2327 if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break; 2328 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 2329 diff = time - GetTickCount(); 2330 } 2331 } 2332 2333 static void flush_sequence(void) 2334 { 2335 EnterCriticalSection( &sequence_cs ); 2336 HeapFree(GetProcessHeap(), 0, sequence); 2337 sequence = 0; 2338 sequence_cnt = sequence_size = 0; 2339 LeaveCriticalSection( &sequence_cs ); 2340 } 2341 2342 static void dump_sequence(const struct message *expected, const char *context, const char *file, int line) 2343 { 2344 const struct recvd_message *actual = sequence; 2345 unsigned int count = 0; 2346 2347 trace_(file, line)("Failed sequence %s:\n", context ); 2348 while (expected->message && actual->message) 2349 { 2350 if (actual->output[0]) 2351 { 2352 if (expected->flags & hook) 2353 { 2354 trace_(file, line)( " %u: expected: hook %04x - actual: %s\n", 2355 count, expected->message, actual->output ); 2356 } 2357 else if (expected->flags & winevent_hook) 2358 { 2359 trace_(file, line)( " %u: expected: winevent %04x - actual: %s\n", 2360 count, expected->message, actual->output ); 2361 } 2362 else if (expected->flags & kbd_hook) 2363 { 2364 trace_(file, line)( " %u: expected: kbd %04x - actual: %s\n", 2365 count, expected->message, actual->output ); 2366 } 2367 else 2368 { 2369 trace_(file, line)( " %u: expected: msg %04x - actual: %s\n", 2370 count, expected->message, actual->output ); 2371 } 2372 } 2373 2374 if (expected->message == actual->message) 2375 { 2376 if ((expected->flags & defwinproc) != (actual->flags & defwinproc) && 2377 (expected->flags & optional)) 2378 { 2379 /* don't match messages if their defwinproc status differs */ 2380 expected++; 2381 } 2382 else 2383 { 2384 expected++; 2385 actual++; 2386 } 2387 } 2388 /* silently drop winevent messages if there is no support for them */ 2389 else if ((expected->flags & optional) || ((expected->flags & winevent_hook) && !hEvent_hook)) 2390 expected++; 2391 else 2392 { 2393 expected++; 2394 actual++; 2395 } 2396 count++; 2397 } 2398 2399 /* optional trailing messages */ 2400 while (expected->message && ((expected->flags & optional) || 2401 ((expected->flags & winevent_hook) && !hEvent_hook))) 2402 { 2403 trace_(file, line)( " %u: expected: msg %04x - actual: nothing\n", count, expected->message ); 2404 expected++; 2405 count++; 2406 } 2407 2408 if (expected->message) 2409 { 2410 trace_(file, line)( " %u: expected: msg %04x - actual: nothing\n", count, expected->message ); 2411 return; 2412 } 2413 2414 while (actual->message && actual->output[0]) 2415 { 2416 trace_(file, line)( " %u: expected: nothing - actual: %s\n", count, actual->output ); 2417 actual++; 2418 count++; 2419 } 2420 } 2421 2422 #define ok_sequence( exp, contx, todo) \ 2423 ok_sequence_( (exp), (contx), (todo), __FILE__, __LINE__) 2424 2425 2426 static void ok_sequence_(const struct message *expected_list, const char *context, BOOL todo, 2427 const char *file, int line) 2428 { 2429 static const struct recvd_message end_of_sequence; 2430 const struct message *expected = expected_list; 2431 const struct recvd_message *actual; 2432 int failcount = 0, dump = 0; 2433 unsigned int count = 0; 2434 2435 add_message(&end_of_sequence); 2436 2437 actual = sequence; 2438 2439 while (expected->message && actual->message) 2440 { 2441 if (expected->message == actual->message && 2442 !((expected->flags ^ actual->flags) & (hook|winevent_hook|kbd_hook))) 2443 { 2444 if (expected->flags & wparam) 2445 { 2446 if (((expected->wParam ^ actual->wParam) & ~expected->wp_mask) && todo) 2447 { 2448 todo_wine { 2449 failcount ++; 2450 if (strcmp(winetest_platform, "wine")) dump++; 2451 ok_( file, line) (FALSE, 2452 "%s: %u: in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n", 2453 context, count, expected->message, expected->wParam, actual->wParam); 2454 } 2455 } 2456 else 2457 { 2458 ok_( file, line)( ((expected->wParam ^ actual->wParam) & ~expected->wp_mask) == 0, 2459 "%s: %u: in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n", 2460 context, count, expected->message, expected->wParam, actual->wParam); 2461 if ((expected->wParam ^ actual->wParam) & ~expected->wp_mask) dump++; 2462 } 2463 2464 } 2465 if (expected->flags & lparam) 2466 { 2467 if (((expected->lParam ^ actual->lParam) & ~expected->lp_mask) && todo) 2468 { 2469 todo_wine { 2470 failcount ++; 2471 if (strcmp(winetest_platform, "wine")) dump++; 2472 ok_( file, line) (FALSE, 2473 "%s: %u: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n", 2474 context, count, expected->message, expected->lParam, actual->lParam); 2475 } 2476 } 2477 else 2478 { 2479 ok_( file, line)(((expected->lParam ^ actual->lParam) & ~expected->lp_mask) == 0, 2480 "%s: %u: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n", 2481 context, count, expected->message, expected->lParam, actual->lParam); 2482 if ((expected->lParam ^ actual->lParam) & ~expected->lp_mask) dump++; 2483 } 2484 } 2485 if ((expected->flags & optional) && 2486 ((expected->flags ^ actual->flags) & (defwinproc|parent))) 2487 { 2488 /* don't match optional messages if their defwinproc or parent status differs */ 2489 expected++; 2490 count++; 2491 continue; 2492 } 2493 if ((expected->flags & defwinproc) != (actual->flags & defwinproc) && todo) 2494 { 2495 todo_wine { 2496 failcount ++; 2497 if (strcmp(winetest_platform, "wine")) dump++; 2498 ok_( file, line) (FALSE, 2499 "%s: %u: the msg 0x%04x should %shave been sent by DefWindowProc\n", 2500 context, count, expected->message, (expected->flags & defwinproc) ? "" : "NOT "); 2501 } 2502 } 2503 else 2504 { 2505 ok_( file, line) ((expected->flags & defwinproc) == (actual->flags & defwinproc), 2506 "%s: %u: the msg 0x%04x should %shave been sent by DefWindowProc\n", 2507 context, count, expected->message, (expected->flags & defwinproc) ? "" : "NOT "); 2508 if ((expected->flags & defwinproc) != (actual->flags & defwinproc)) dump++; 2509 } 2510 2511 ok_( file, line) ((expected->flags & beginpaint) == (actual->flags & beginpaint), 2512 "%s: %u: the msg 0x%04x should %shave been sent by BeginPaint\n", 2513 context, count, expected->message, (expected->flags & beginpaint) ? "" : "NOT "); 2514 if ((expected->flags & beginpaint) != (actual->flags & beginpaint)) dump++; 2515 2516 ok_( file, line) ((expected->flags & (sent|posted)) == (actual->flags & (sent|posted)), 2517 "%s: %u: the msg 0x%04x should have been %s\n", 2518 context, count, expected->message, (expected->flags & posted) ? "posted" : "sent"); 2519 if ((expected->flags & (sent|posted)) != (actual->flags & (sent|posted))) dump++; 2520 2521 ok_( file, line) ((expected->flags & parent) == (actual->flags & parent), 2522 "%s: %u: the msg 0x%04x was expected in %s\n", 2523 context, count, expected->message, (expected->flags & parent) ? "parent" : "child"); 2524 if ((expected->flags & parent) != (actual->flags & parent)) dump++; 2525 2526 ok_( file, line) ((expected->flags & hook) == (actual->flags & hook), 2527 "%s: %u: the msg 0x%04x should have been sent by a hook\n", 2528 context, count, expected->message); 2529 if ((expected->flags & hook) != (actual->flags & hook)) dump++; 2530 2531 ok_( file, line) ((expected->flags & winevent_hook) == (actual->flags & winevent_hook), 2532 "%s: %u: the msg 0x%04x should have been sent by a winevent hook\n", 2533 context, count, expected->message); 2534 if ((expected->flags & winevent_hook) != (actual->flags & winevent_hook)) dump++; 2535 2536 ok_( file, line) ((expected->flags & kbd_hook) == (actual->flags & kbd_hook), 2537 "%s: %u: the msg 0x%04x should have been sent by a keyboard hook\n", 2538 context, count, expected->message); 2539 if ((expected->flags & kbd_hook) != (actual->flags & kbd_hook)) dump++; 2540 2541 expected++; 2542 actual++; 2543 } 2544 /* silently drop hook messages if there is no support for them */ 2545 else if ((expected->flags & optional) || 2546 ((expected->flags & hook) && !hCBT_hook) || 2547 ((expected->flags & winevent_hook) && !hEvent_hook) || 2548 ((expected->flags & kbd_hook) && !hKBD_hook)) 2549 expected++; 2550 else if (todo) 2551 { 2552 failcount++; 2553 todo_wine { 2554 if (strcmp(winetest_platform, "wine")) dump++; 2555 ok_( file, line) (FALSE, "%s: %u: the msg 0x%04x was expected, but got msg 0x%04x instead\n", 2556 context, count, expected->message, actual->message); 2557 } 2558 goto done; 2559 } 2560 else 2561 { 2562 ok_( file, line) (FALSE, "%s: %u: the msg 0x%04x was expected, but got msg 0x%04x instead\n", 2563 context, count, expected->message, actual->message); 2564 dump++; 2565 expected++; 2566 actual++; 2567 } 2568 count++; 2569 } 2570 2571 /* skip all optional trailing messages */ 2572 while (expected->message && ((expected->flags & optional) || 2573 ((expected->flags & hook) && !hCBT_hook) || 2574 ((expected->flags & winevent_hook) && !hEvent_hook))) 2575 expected++; 2576 2577 if (todo) 2578 { 2579 todo_wine { 2580 if (expected->message || actual->message) { 2581 failcount++; 2582 if (strcmp(winetest_platform, "wine")) dump++; 2583 ok_( file, line) (FALSE, "%s: %u: the msg sequence is not complete: expected %04x - actual %04x\n", 2584 context, count, expected->message, actual->message); 2585 } 2586 } 2587 } 2588 else 2589 { 2590 if (expected->message || actual->message) 2591 { 2592 dump++; 2593 ok_( file, line) (FALSE, "%s: %u: the msg sequence is not complete: expected %04x - actual %04x\n", 2594 context, count, expected->message, actual->message); 2595 } 2596 } 2597 if( todo && !failcount) /* succeeded yet marked todo */ 2598 todo_wine { 2599 if (!strcmp(winetest_platform, "wine")) dump++; 2600 ok_( file, line)( TRUE, "%s: marked \"todo_wine\" but succeeds\n", context); 2601 } 2602 2603 done: 2604 if (dump) dump_sequence(expected_list, context, file, line); 2605 flush_sequence(); 2606 } 2607 2608 #define expect(EXPECTED,GOT) ok((GOT)==(EXPECTED), "Expected %d, got %d\n", (EXPECTED), (GOT)) 2609 2610 /******************************** MDI test **********************************/ 2611 2612 /* CreateWindow for MDI frame window, initially visible */ 2613 static const struct message WmCreateMDIframeSeq[] = { 2614 { HCBT_CREATEWND, hook }, 2615 { WM_GETMINMAXINFO, sent }, 2616 { WM_NCCREATE, sent }, 2617 { WM_NCCALCSIZE, sent|wparam, 0 }, 2618 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, 2619 { WM_CREATE, sent }, 2620 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 2621 { WM_NOTIFYFORMAT, sent|optional }, 2622 { WM_QUERYUISTATE, sent|optional }, 2623 { WM_WINDOWPOSCHANGING, sent|optional }, 2624 { WM_GETMINMAXINFO, sent|optional }, 2625 { WM_NCCALCSIZE, sent|optional }, 2626 { WM_WINDOWPOSCHANGED, sent|optional }, 2627 { WM_SHOWWINDOW, sent|wparam, 1 }, 2628 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 2629 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 2630 { HCBT_ACTIVATE, hook }, 2631 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 2632 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 2633 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* XP */ 2634 { WM_ACTIVATEAPP, sent|wparam|optional, 1 }, /* Win9x doesn't send it */ 2635 { WM_NCACTIVATE, sent }, 2636 { WM_GETTEXT, sent|defwinproc|optional }, 2637 { WM_ACTIVATE, sent|wparam, 1 }, 2638 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* Win9x */ 2639 { HCBT_SETFOCUS, hook }, 2640 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 2641 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 2642 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2643 { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, 2644 /* Win9x adds SWP_NOZORDER below */ 2645 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2646 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* XP */ 2647 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 2648 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 2649 { WM_MOVE, sent }, 2650 { 0 } 2651 }; 2652 /* DestroyWindow for MDI frame window, initially visible */ 2653 static const struct message WmDestroyMDIframeSeq[] = { 2654 { HCBT_DESTROYWND, hook }, 2655 { 0x0090, sent|optional }, 2656 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2657 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 2658 { WM_NCACTIVATE, sent|wparam|optional, 0 }, /* Win9x */ 2659 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2660 { WM_NCACTIVATE, sent|wparam|optional, 0 }, /* XP */ 2661 { WM_ACTIVATE, sent|wparam|optional, 0 }, /* Win9x */ 2662 { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, /* Win9x */ 2663 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 2664 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, 2665 { WM_DESTROY, sent }, 2666 { WM_NCDESTROY, sent }, 2667 { 0 } 2668 }; 2669 /* CreateWindow for MDI client window, initially visible */ 2670 static const struct message WmCreateMDIclientSeq[] = { 2671 { HCBT_CREATEWND, hook }, 2672 { WM_NCCREATE, sent }, 2673 { WM_NCCALCSIZE, sent|wparam, 0 }, 2674 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|optional, 0, 0 }, 2675 { WM_CREATE, sent }, 2676 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|optional, 0, 0 }, 2677 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 2678 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 2679 { WM_MOVE, sent }, 2680 { WM_PARENTNOTIFY, sent|wparam, WM_CREATE }, /* in MDI frame */ 2681 { WM_SHOWWINDOW, sent|wparam, 1 }, 2682 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2683 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 2684 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2685 { 0 } 2686 }; 2687 /* ShowWindow(SW_SHOW) for MDI client window */ 2688 static const struct message WmShowMDIclientSeq[] = { 2689 { WM_SHOWWINDOW, sent|wparam, 1 }, 2690 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2691 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 2692 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2693 { 0 } 2694 }; 2695 /* ShowWindow(SW_HIDE) for MDI client window */ 2696 static const struct message WmHideMDIclientSeq[] = { 2697 { WM_SHOWWINDOW, sent|wparam, 0 }, 2698 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2699 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam|optional, 0, 0 }, /* win2000 */ 2700 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP */ 2701 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2702 { 0 } 2703 }; 2704 /* DestroyWindow for MDI client window, initially visible */ 2705 static const struct message WmDestroyMDIclientSeq[] = { 2706 { HCBT_DESTROYWND, hook }, 2707 { 0x0090, sent|optional }, 2708 { WM_PARENTNOTIFY, sent|wparam, WM_DESTROY }, /* in MDI frame */ 2709 { WM_SHOWWINDOW, sent|wparam, 0 }, 2710 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2711 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 2712 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2713 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, 2714 { WM_DESTROY, sent }, 2715 { WM_NCDESTROY, sent }, 2716 { 0 } 2717 }; 2718 /* CreateWindow for MDI child window, initially visible */ 2719 static const struct message WmCreateMDIchildVisibleSeq[] = { 2720 { HCBT_CREATEWND, hook }, 2721 { WM_NCCREATE, sent }, 2722 { WM_NCCALCSIZE, sent|wparam, 0 }, 2723 { WM_CREATE, sent }, 2724 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 2725 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 2726 { WM_MOVE, sent }, 2727 /* Win2k sends wparam set to 2728 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated), 2729 * while Win9x doesn't bother to set child window id according to 2730 * CLIENTCREATESTRUCT.idFirstChild 2731 */ 2732 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */ 2733 { WM_SHOWWINDOW, sent|wparam, 1 }, 2734 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2735 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 2736 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2737 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ }, 2738 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 2739 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 2740 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2741 2742 /* Win9x: message sequence terminates here. */ 2743 2744 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, 2745 { HCBT_SETFOCUS, hook }, /* in MDI client */ 2746 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 2747 { WM_IME_NOTIFY, sent|wparam|optional, 2 }, /* in MDI client */ 2748 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2749 { WM_SETFOCUS, sent }, /* in MDI client */ 2750 { HCBT_SETFOCUS, hook }, 2751 { WM_KILLFOCUS, sent }, /* in MDI client */ 2752 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 2753 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 2754 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2755 { WM_SETFOCUS, sent|defwinproc }, 2756 { WM_MDIACTIVATE, sent|defwinproc }, 2757 { 0 } 2758 }; 2759 /* WM_CHILDACTIVATE sent to disabled window */ 2760 static const struct message WmChildActivateDisabledWindowSeq[] = { 2761 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 2762 { 0 } 2763 }; 2764 /* WM_CHILDACTIVATE sent to enabled window */ 2765 static const struct message WmChildActivateWindowSeq[] = { 2766 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 2767 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, 2768 { WM_MDIACTIVATE, sent|defwinproc }, 2769 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2770 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2771 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, 2772 { HCBT_SETFOCUS, hook }, 2773 { WM_KILLFOCUS, sent|defwinproc }, 2774 { WM_SETFOCUS, sent }, 2775 { HCBT_SETFOCUS, hook }, 2776 { WM_KILLFOCUS, sent }, 2777 { WM_SETFOCUS, sent|defwinproc }, 2778 { WM_MDIACTIVATE, sent|defwinproc }, 2779 { 0 } 2780 }; 2781 /* CreateWindow for MDI child window with invisible parent */ 2782 static const struct message WmCreateMDIchildInvisibleParentSeq[] = { 2783 { HCBT_CREATEWND, hook }, 2784 { WM_GETMINMAXINFO, sent }, 2785 { WM_NCCREATE, sent }, 2786 { WM_NCCALCSIZE, sent|wparam, 0 }, 2787 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|optional, 0, 0 }, 2788 { WM_CREATE, sent }, 2789 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 2790 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 2791 { WM_MOVE, sent }, 2792 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */ 2793 { WM_SHOWWINDOW, sent|wparam, 1 }, 2794 { WM_MDIREFRESHMENU, sent }, /* in MDI client */ 2795 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 2796 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 2797 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2798 2799 /* Win9x: message sequence terminates here. */ 2800 2801 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, 2802 { HCBT_SETFOCUS, hook }, /* in MDI client */ 2803 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 2804 { WM_IME_NOTIFY, sent|wparam|optional, 2 }, /* in MDI client */ 2805 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2806 { WM_SETFOCUS, sent }, /* in MDI client */ 2807 { HCBT_SETFOCUS, hook }, 2808 { WM_KILLFOCUS, sent }, /* in MDI client */ 2809 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 2810 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 2811 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2812 { WM_SETFOCUS, sent|defwinproc }, 2813 { WM_MDIACTIVATE, sent|defwinproc }, 2814 { 0 } 2815 }; 2816 /* DestroyWindow for MDI child window, initially visible */ 2817 static const struct message WmDestroyMDIchildVisibleSeq[] = { 2818 { HCBT_DESTROYWND, hook }, 2819 /* Win2k sends wparam set to 2820 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated), 2821 * while Win9x doesn't bother to set child window id according to 2822 * CLIENTCREATESTRUCT.idFirstChild 2823 */ 2824 { 0x0090, sent|optional }, 2825 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */ 2826 { WM_SHOWWINDOW, sent|wparam, 0 }, 2827 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2828 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 2829 { WM_ERASEBKGND, sent|parent|optional }, 2830 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2831 2832 /* { WM_DESTROY, sent } 2833 * Win9x: message sequence terminates here. 2834 */ 2835 2836 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */ 2837 { WM_KILLFOCUS, sent }, 2838 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 2839 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 2840 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2841 { WM_SETFOCUS, sent }, /* in MDI client */ 2842 2843 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */ 2844 { WM_KILLFOCUS, sent }, /* in MDI client */ 2845 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 2846 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 2847 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2848 { WM_SETFOCUS, sent }, /* in MDI client */ 2849 2850 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, 2851 2852 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */ 2853 { WM_KILLFOCUS, sent }, 2854 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 2855 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 2856 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2857 { WM_SETFOCUS, sent }, /* in MDI client */ 2858 2859 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */ 2860 { WM_KILLFOCUS, sent }, /* in MDI client */ 2861 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 2862 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 2863 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2864 { WM_SETFOCUS, sent }, /* in MDI client */ 2865 2866 { WM_DESTROY, sent }, 2867 2868 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */ 2869 { WM_KILLFOCUS, sent }, 2870 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 2871 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 2872 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2873 { WM_SETFOCUS, sent }, /* in MDI client */ 2874 2875 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */ 2876 { WM_KILLFOCUS, sent }, /* in MDI client */ 2877 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 2878 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 2879 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2880 { WM_SETFOCUS, sent }, /* in MDI client */ 2881 2882 { WM_NCDESTROY, sent }, 2883 { 0 } 2884 }; 2885 /* CreateWindow for MDI child window, initially invisible */ 2886 static const struct message WmCreateMDIchildInvisibleSeq[] = { 2887 { HCBT_CREATEWND, hook }, 2888 { WM_NCCREATE, sent }, 2889 { WM_NCCALCSIZE, sent|wparam, 0 }, 2890 { WM_CREATE, sent }, 2891 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 2892 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 2893 { WM_MOVE, sent }, 2894 /* Win2k sends wparam set to 2895 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated), 2896 * while Win9x doesn't bother to set child window id according to 2897 * CLIENTCREATESTRUCT.idFirstChild 2898 */ 2899 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */ 2900 { 0 } 2901 }; 2902 /* DestroyWindow for MDI child window, initially invisible */ 2903 static const struct message WmDestroyMDIchildInvisibleSeq[] = { 2904 { HCBT_DESTROYWND, hook }, 2905 /* Win2k sends wparam set to 2906 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated), 2907 * while Win9x doesn't bother to set child window id according to 2908 * CLIENTCREATESTRUCT.idFirstChild 2909 */ 2910 { 0x0090, sent|optional }, 2911 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */ 2912 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, 2913 { WM_DESTROY, sent }, 2914 { WM_NCDESTROY, sent }, 2915 /* FIXME: Wine destroys an icon/title window while Windows doesn't */ 2916 { WM_PARENTNOTIFY, sent|wparam|optional, WM_DESTROY }, /* MDI client */ 2917 { 0 } 2918 }; 2919 /* CreateWindow for the 1st MDI child window, initially visible and maximized */ 2920 static const struct message WmCreateMDIchildVisibleMaxSeq1[] = { 2921 { HCBT_CREATEWND, hook }, 2922 { WM_NCCREATE, sent }, 2923 { WM_NCCALCSIZE, sent|wparam, 0 }, 2924 { WM_CREATE, sent }, 2925 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 2926 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 2927 { WM_MOVE, sent }, 2928 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 2929 { WM_GETMINMAXINFO, sent }, 2930 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_STATECHANGED }, 2931 { WM_NCCALCSIZE, sent|wparam, 1 }, 2932 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 2933 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 2934 /* in MDI frame */ 2935 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2936 { WM_NCCALCSIZE, sent|wparam, 1 }, 2937 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2938 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 2939 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 2940 /* Win2k sends wparam set to 2941 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated), 2942 * while Win9x doesn't bother to set child window id according to 2943 * CLIENTCREATESTRUCT.idFirstChild 2944 */ 2945 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */ 2946 { WM_SHOWWINDOW, sent|wparam, 1 }, 2947 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2948 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 2949 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2950 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ }, 2951 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 2952 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 2953 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc|optional, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE, 0, SWP_FRAMECHANGED }, 2954 2955 /* Win9x: message sequence terminates here. */ 2956 2957 { WM_NCACTIVATE, sent|wparam|defwinproc|optional, 1 }, 2958 { HCBT_SETFOCUS, hook|optional }, /* in MDI client */ 2959 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 2960 { WM_IME_NOTIFY, sent|wparam|optional, 2 }, /* in MDI client */ 2961 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2962 { WM_SETFOCUS, sent|optional }, /* in MDI client */ 2963 { HCBT_SETFOCUS, hook|optional }, 2964 { WM_KILLFOCUS, sent|optional }, /* in MDI client */ 2965 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 2966 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 2967 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2968 { WM_SETFOCUS, sent|defwinproc|optional }, 2969 { WM_MDIACTIVATE, sent|defwinproc|optional }, 2970 /* in MDI frame */ 2971 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2972 { WM_NCCALCSIZE, sent|wparam, 1 }, 2973 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2974 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 2975 { 0 } 2976 }; 2977 /* CreateWindow for the 2nd MDI child window, initially visible and maximized */ 2978 static const struct message WmCreateMDIchildVisibleMaxSeq2[] = { 2979 /* restore the 1st MDI child */ 2980 { WM_SETREDRAW, sent|wparam, 0 }, 2981 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWNORMAL }, 2982 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, 2983 { WM_NCCALCSIZE, sent|wparam, 1 }, 2984 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 2985 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 2986 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 2987 /* in MDI frame */ 2988 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2989 { WM_NCCALCSIZE, sent|wparam, 1 }, 2990 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2991 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 2992 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 2993 { WM_SETREDRAW, sent|wparam, 1 }, /* in the 1st MDI child */ 2994 /* create the 2nd MDI child */ 2995 { HCBT_CREATEWND, hook }, 2996 { WM_NCCREATE, sent }, 2997 { WM_NCCALCSIZE, sent|wparam, 0 }, 2998 { WM_CREATE, sent }, 2999 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 3000 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 3001 { WM_MOVE, sent }, 3002 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 3003 { WM_GETMINMAXINFO, sent }, 3004 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_STATECHANGED }, 3005 { WM_NCCALCSIZE, sent|wparam, 1 }, 3006 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3007 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 3008 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 3009 /* in MDI frame */ 3010 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3011 { WM_NCCALCSIZE, sent|wparam, 1 }, 3012 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3013 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3014 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3015 /* Win2k sends wparam set to 3016 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated), 3017 * while Win9x doesn't bother to set child window id according to 3018 * CLIENTCREATESTRUCT.idFirstChild 3019 */ 3020 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */ 3021 { WM_SHOWWINDOW, sent|wparam, 1 }, 3022 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3023 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 3024 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3025 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ }, 3026 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 3027 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 3028 3029 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 1st MDI child */ 3030 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 1st MDI child */ 3031 3032 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3033 3034 /* Win9x: message sequence terminates here. */ 3035 3036 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, 3037 { HCBT_SETFOCUS, hook }, 3038 { WM_KILLFOCUS, sent|defwinproc|optional }, /* in the 1st MDI child */ 3039 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 }, /* in the 1st MDI child */ 3040 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 3041 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3042 { WM_SETFOCUS, sent }, /* in MDI client */ 3043 { HCBT_SETFOCUS, hook }, 3044 { WM_KILLFOCUS, sent }, /* in MDI client */ 3045 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 3046 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 3047 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3048 { WM_SETFOCUS, sent|defwinproc }, 3049 3050 { WM_MDIACTIVATE, sent|defwinproc }, 3051 /* in MDI frame */ 3052 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3053 { WM_NCCALCSIZE, sent|wparam, 1 }, 3054 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3055 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3056 { 0 } 3057 }; 3058 /* WM_MDICREATE MDI child window, initially visible and maximized */ 3059 static const struct message WmCreateMDIchildVisibleMaxSeq3[] = { 3060 { WM_MDICREATE, sent }, 3061 { HCBT_CREATEWND, hook }, 3062 { WM_NCCREATE, sent }, 3063 { WM_NCCALCSIZE, sent|wparam, 0 }, 3064 { WM_CREATE, sent }, 3065 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 3066 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 3067 { WM_MOVE, sent }, 3068 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 3069 { WM_GETMINMAXINFO, sent }, 3070 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_STATECHANGED }, 3071 { WM_NCCALCSIZE, sent|wparam, 1 }, 3072 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 3073 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 3074 3075 /* in MDI frame */ 3076 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3077 { WM_NCCALCSIZE, sent|wparam, 1 }, 3078 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3079 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3080 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3081 3082 /* Win2k sends wparam set to 3083 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated), 3084 * while Win9x doesn't bother to set child window id according to 3085 * CLIENTCREATESTRUCT.idFirstChild 3086 */ 3087 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */ 3088 { WM_SHOWWINDOW, sent|wparam, 1 }, 3089 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3090 3091 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 3092 3093 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3094 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ }, 3095 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 3096 3097 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 3098 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3099 3100 /* Win9x: message sequence terminates here. */ 3101 3102 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, 3103 { WM_SETFOCUS, sent|optional }, /* in MDI client */ 3104 { HCBT_SETFOCUS, hook }, /* in MDI client */ 3105 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 3106 { WM_IME_NOTIFY, sent|wparam|optional, 2 }, 3107 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 }, 3108 { WM_SETFOCUS, sent|optional }, /* in MDI client */ 3109 { HCBT_SETFOCUS, hook|optional }, 3110 { WM_KILLFOCUS, sent }, /* in MDI client */ 3111 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 3112 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 3113 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3114 { WM_SETFOCUS, sent|defwinproc }, 3115 3116 { WM_MDIACTIVATE, sent|defwinproc }, 3117 3118 /* in MDI child */ 3119 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3120 { WM_NCCALCSIZE, sent|wparam, 1 }, 3121 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3122 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 3123 3124 /* in MDI frame */ 3125 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3126 { WM_NCCALCSIZE, sent|wparam, 1 }, 3127 { 0x0093, sent|defwinproc|optional }, 3128 { 0x0093, sent|defwinproc|optional }, 3129 { 0x0093, sent|defwinproc|optional }, 3130 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3131 { WM_MOVE, sent|defwinproc }, 3132 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 3133 3134 /* in MDI client */ 3135 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE }, 3136 { WM_NCCALCSIZE, sent|wparam, 1 }, 3137 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOCLIENTMOVE }, 3138 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 3139 3140 /* in MDI child */ 3141 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE }, 3142 { WM_NCCALCSIZE, sent|wparam, 1 }, 3143 { 0x0093, sent|optional }, 3144 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOCLIENTMOVE }, 3145 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 3146 3147 { 0x0093, sent|optional }, 3148 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3149 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */ 3150 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* XP sends it to MDI frame */ 3151 { 0x0093, sent|defwinproc|optional }, 3152 { 0x0093, sent|defwinproc|optional }, 3153 { 0x0093, sent|defwinproc|optional }, 3154 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3155 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* XP sends a duplicate */ 3156 3157 { 0 } 3158 }; 3159 /* CreateWindow for the 1st MDI child window, initially invisible and maximized */ 3160 static const struct message WmCreateMDIchildInvisibleMaxSeq4[] = { 3161 { HCBT_CREATEWND, hook }, 3162 { WM_GETMINMAXINFO, sent }, 3163 { WM_NCCREATE, sent }, 3164 { WM_NCCALCSIZE, sent|wparam, 0 }, 3165 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, 3166 { WM_CREATE, sent }, 3167 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 3168 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 3169 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE, 0, SWP_NOZORDER }, /* MDI frame */ 3170 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* MDI frame */ 3171 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE, 0, SWP_NOZORDER }, /* MDI frame */ 3172 { WM_MOVE, sent }, 3173 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 3174 { WM_GETMINMAXINFO, sent }, 3175 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_STATECHANGED }, 3176 { WM_GETMINMAXINFO, sent|defwinproc }, 3177 { WM_NCCALCSIZE, sent|wparam, 1 }, 3178 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOREDRAW|SWP_STATECHANGED }, 3179 { WM_MOVE, sent|defwinproc }, 3180 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 3181 /* in MDI frame */ 3182 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3183 { WM_NCCALCSIZE, sent|wparam, 1 }, 3184 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3185 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3186 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* MDI child */ 3187 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3188 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3189 /* Win2k sends wparam set to 3190 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated), 3191 * while Win9x doesn't bother to set child window id according to 3192 * CLIENTCREATESTRUCT.idFirstChild 3193 */ 3194 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */ 3195 { 0 } 3196 }; 3197 /* WM_SYSCOMMAND/SC_CLOSE for the 2nd MDI child window, initially visible and maximized */ 3198 static const struct message WmDestroyMDIchildVisibleMaxSeq2[] = { 3199 { WM_SYSCOMMAND, sent|wparam, SC_CLOSE }, 3200 { HCBT_SYSCOMMAND, hook }, 3201 { WM_CLOSE, sent|defwinproc }, 3202 { WM_MDIDESTROY, sent }, /* in MDI client */ 3203 3204 /* bring the 1st MDI child to top */ 3205 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOSIZE|SWP_NOMOVE }, /* in the 1st MDI child */ 3206 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, /* in the 2nd MDI child */ 3207 3208 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3209 3210 { WM_CHILDACTIVATE, sent|defwinproc|wparam|lparam, 0, 0 }, /* in the 1st MDI child */ 3211 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 1st MDI child */ 3212 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 1st MDI child */ 3213 3214 /* maximize the 1st MDI child */ 3215 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 3216 { WM_GETMINMAXINFO, sent|defwinproc }, 3217 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_STATECHANGED }, 3218 { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 }, 3219 { WM_CHILDACTIVATE, sent|defwinproc|wparam|lparam, 0, 0 }, 3220 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 3221 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 3222 3223 /* restore the 2nd MDI child */ 3224 { WM_SETREDRAW, sent|defwinproc|wparam, 0 }, 3225 { HCBT_MINMAX, hook|lparam, 0, SW_NORMALNA }, 3226 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_STATECHANGED }, 3227 { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 }, 3228 3229 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 3230 3231 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 3232 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 3233 3234 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3235 3236 { WM_SETREDRAW, sent|defwinproc|wparam, 1 }, 3237 /* in MDI frame */ 3238 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3239 { WM_NCCALCSIZE, sent|wparam, 1 }, 3240 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3241 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3242 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3243 3244 /* bring the 1st MDI child to top */ 3245 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3246 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, 3247 { HCBT_SETFOCUS, hook }, 3248 { WM_KILLFOCUS, sent|defwinproc }, 3249 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 }, 3250 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 3251 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3252 { WM_SETFOCUS, sent }, /* in MDI client */ 3253 { HCBT_SETFOCUS, hook }, 3254 { WM_KILLFOCUS, sent }, /* in MDI client */ 3255 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 3256 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 3257 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3258 { WM_SETFOCUS, sent|defwinproc }, 3259 { WM_MDIACTIVATE, sent|defwinproc }, 3260 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3261 3262 /* apparently ShowWindow(SW_SHOW) on an MDI client */ 3263 { WM_SHOWWINDOW, sent|wparam, 1 }, 3264 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3265 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 3266 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3267 { WM_MDIREFRESHMENU, sent }, 3268 3269 { HCBT_DESTROYWND, hook }, 3270 /* Win2k sends wparam set to 3271 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated), 3272 * while Win9x doesn't bother to set child window id according to 3273 * CLIENTCREATESTRUCT.idFirstChild 3274 */ 3275 { 0x0090, sent|defwinproc|optional }, 3276 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */ 3277 { WM_SHOWWINDOW, sent|defwinproc|wparam, 0 }, 3278 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3279 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 3280 { WM_ERASEBKGND, sent|parent|optional }, 3281 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3282 3283 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, 3284 { WM_DESTROY, sent|defwinproc }, 3285 { WM_NCDESTROY, sent|defwinproc }, 3286 { 0 } 3287 }; 3288 /* WM_MDIDESTROY for the single MDI child window, initially visible and maximized */ 3289 static const struct message WmDestroyMDIchildVisibleMaxSeq1[] = { 3290 { WM_MDIDESTROY, sent }, /* in MDI client */ 3291 { WM_SHOWWINDOW, sent|wparam, 0 }, 3292 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3293 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 3294 { WM_ERASEBKGND, sent|parent|optional }, 3295 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3296 3297 { HCBT_SETFOCUS, hook }, 3298 { WM_KILLFOCUS, sent }, 3299 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 3300 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 3301 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3302 { WM_SETFOCUS, sent }, /* in MDI client */ 3303 { HCBT_SETFOCUS, hook }, 3304 { WM_KILLFOCUS, sent }, /* in MDI client */ 3305 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 3306 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 3307 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3308 { WM_SETFOCUS, sent }, 3309 3310 /* in MDI child */ 3311 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3312 { WM_NCCALCSIZE, sent|wparam, 1 }, 3313 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3314 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3315 3316 /* in MDI frame */ 3317 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3318 { WM_NCCALCSIZE, sent|wparam, 1 }, 3319 { 0x0093, sent|defwinproc|optional }, 3320 { 0x0093, sent|defwinproc|optional }, 3321 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3322 { WM_MOVE, sent|defwinproc }, 3323 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 3324 3325 /* in MDI client */ 3326 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE }, 3327 { WM_NCCALCSIZE, sent|wparam, 1 }, 3328 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOCLIENTMOVE }, 3329 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 3330 3331 /* in MDI child */ 3332 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE }, 3333 { WM_NCCALCSIZE, sent|wparam, 1 }, 3334 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE }, 3335 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 3336 3337 /* in MDI child */ 3338 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3339 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, 3340 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3341 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3342 3343 /* in MDI frame */ 3344 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3345 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, 3346 { 0x0093, sent|defwinproc|optional }, 3347 { 0x0093, sent|defwinproc|optional }, 3348 { 0x0093, sent|defwinproc|optional }, 3349 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3350 { WM_MOVE, sent|defwinproc }, 3351 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 3352 3353 /* in MDI client */ 3354 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE }, 3355 { WM_NCCALCSIZE, sent|wparam, 1 }, 3356 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOCLIENTMOVE }, 3357 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 3358 3359 /* in MDI child */ 3360 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE }, 3361 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, 3362 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE }, 3363 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 3364 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3365 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */ 3366 3367 { 0x0093, sent|defwinproc|optional }, 3368 { WM_NCCALCSIZE, sent|wparam|defwinproc|optional, 1 }, /* XP sends it to MDI frame */ 3369 { 0x0093, sent|defwinproc|optional }, 3370 { 0x0093, sent|defwinproc|optional }, 3371 { 0x0093, sent|defwinproc|optional }, 3372 { 0x0093, sent|optional }, 3373 3374 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3375 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3376 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */ 3377 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3378 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* XP sends a duplicate */ 3379 3380 /* in MDI frame */ 3381 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3382 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, 3383 { 0x0093, sent|defwinproc|optional }, 3384 { 0x0093, sent|defwinproc|optional }, 3385 { 0x0093, sent|defwinproc|optional }, 3386 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3387 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3388 { 0x0093, sent|optional }, 3389 3390 { WM_NCACTIVATE, sent|wparam, 0 }, 3391 { WM_MDIACTIVATE, sent }, 3392 3393 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWNORMAL }, 3394 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_STATECHANGED }, 3395 { WM_NCCALCSIZE, sent|wparam, 1 }, 3396 3397 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 3398 3399 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 3400 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 3401 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 3402 3403 /* in MDI child */ 3404 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3405 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, 3406 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3407 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3408 3409 /* in MDI frame */ 3410 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3411 { WM_NCCALCSIZE, sent|wparam, 1 }, 3412 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3413 { WM_MOVE, sent|defwinproc }, 3414 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 3415 3416 /* in MDI client */ 3417 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE }, 3418 { WM_NCCALCSIZE, sent|wparam, 1 }, 3419 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOCLIENTMOVE }, 3420 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 3421 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3422 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* XP */ 3423 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */ 3424 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3425 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* XP sends a duplicate */ 3426 3427 { HCBT_SETFOCUS, hook }, 3428 { WM_KILLFOCUS, sent }, 3429 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 3430 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 3431 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3432 { WM_SETFOCUS, sent }, /* in MDI client */ 3433 3434 { WM_MDIREFRESHMENU, sent }, /* in MDI client */ 3435 3436 { HCBT_DESTROYWND, hook }, 3437 /* Win2k sends wparam set to 3438 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated), 3439 * while Win9x doesn't bother to set child window id according to 3440 * CLIENTCREATESTRUCT.idFirstChild 3441 */ 3442 { 0x0090, sent|optional }, 3443 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */ 3444 3445 { WM_SHOWWINDOW, sent|wparam, 0 }, 3446 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3447 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 3448 { WM_ERASEBKGND, sent|parent|optional }, 3449 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3450 3451 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, 3452 { WM_DESTROY, sent }, 3453 { WM_NCDESTROY, sent }, 3454 { 0 } 3455 }; 3456 /* ShowWindow(SW_MAXIMIZE) for a not visible MDI child window */ 3457 static const struct message WmMaximizeMDIchildInvisibleSeq[] = { 3458 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 3459 { WM_GETMINMAXINFO, sent }, 3460 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_STATECHANGED }, 3461 { WM_NCCALCSIZE, sent|wparam, 1 }, 3462 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 3463 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 3464 3465 { WM_WINDOWPOSCHANGING, sent|wparam|optional|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3466 { WM_NCACTIVATE, sent|wparam|optional|defwinproc, 1 }, 3467 { HCBT_SETFOCUS, hook|optional }, 3468 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 3469 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3470 { WM_SETFOCUS, sent|optional }, /* in MDI client */ 3471 { HCBT_SETFOCUS, hook|optional }, 3472 { WM_KILLFOCUS, sent|optional }, /* in MDI client */ 3473 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 3474 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 3475 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3476 { WM_SETFOCUS, sent|optional|defwinproc }, 3477 { WM_MDIACTIVATE, sent|optional|defwinproc }, 3478 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 3479 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 3480 /* in MDI frame */ 3481 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3482 { WM_NCCALCSIZE, sent|wparam, 1 }, 3483 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3484 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3485 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3486 { 0 } 3487 }; 3488 /* ShowWindow(SW_MAXIMIZE) for a not visible maximized MDI child window */ 3489 static const struct message WmMaximizeMDIchildInvisibleSeq2[] = { 3490 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 3491 { WM_GETMINMAXINFO, sent }, 3492 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED }, 3493 { WM_GETMINMAXINFO, sent|defwinproc }, 3494 { WM_NCCALCSIZE, sent|wparam, 1 }, 3495 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 3496 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 3497 3498 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc|optional, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3499 { WM_NCACTIVATE, sent|wparam|defwinproc|optional, 1 }, 3500 { HCBT_SETFOCUS, hook|optional }, 3501 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 3502 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3503 { WM_SETFOCUS, sent|optional }, /* in MDI client */ 3504 { HCBT_SETFOCUS, hook|optional }, 3505 { WM_KILLFOCUS, sent|optional }, /* in MDI client */ 3506 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 3507 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 3508 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3509 { WM_SETFOCUS, sent|defwinproc|optional }, 3510 { WM_MDIACTIVATE, sent|defwinproc|optional }, 3511 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3512 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3513 { 0 } 3514 }; 3515 /* WM_MDIMAXIMIZE for an MDI child window with invisible parent */ 3516 static const struct message WmMaximizeMDIchildInvisibleParentSeq[] = { 3517 { WM_MDIMAXIMIZE, sent }, /* in MDI client */ 3518 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 3519 { WM_GETMINMAXINFO, sent }, 3520 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, 3521 { WM_GETMINMAXINFO, sent|defwinproc }, 3522 { WM_NCCALCSIZE, sent|wparam, 1 }, 3523 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP doesn't send it */ 3524 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 3525 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOREDRAW|SWP_STATECHANGED }, 3526 { WM_MOVE, sent|defwinproc }, 3527 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 3528 3529 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3530 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, 3531 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3532 { WM_NCCALCSIZE, sent|wparam|defwinproc|optional, 1 }, 3533 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI child XP */ 3534 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI client XP */ 3535 /* in MDI frame */ 3536 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3537 { WM_NCCALCSIZE, sent|wparam, 1 }, 3538 { 0x0093, sent|defwinproc|optional }, 3539 { 0x0094, sent|defwinproc|optional }, 3540 { 0x0094, sent|defwinproc|optional }, 3541 { 0x0094, sent|defwinproc|optional }, 3542 { 0x0094, sent|defwinproc|optional }, 3543 { 0x0093, sent|defwinproc|optional }, 3544 { 0x0093, sent|defwinproc|optional }, 3545 { 0x0091, sent|defwinproc|optional }, 3546 { 0x0092, sent|defwinproc|optional }, 3547 { 0x0092, sent|defwinproc|optional }, 3548 { 0x0092, sent|defwinproc|optional }, 3549 { 0x0092, sent|defwinproc|optional }, 3550 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3551 { WM_MOVE, sent|defwinproc }, 3552 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 3553 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI frame win2000 */ 3554 /* in MDI client */ 3555 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE }, 3556 { WM_NCCALCSIZE, sent|wparam, 1 }, 3557 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE }, 3558 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 3559 /* in MDI child */ 3560 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE }, 3561 { WM_GETMINMAXINFO, sent|defwinproc }, 3562 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, 3563 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE }, 3564 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 3565 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI child win2000 */ 3566 { WM_NCCALCSIZE, sent|wparam|defwinproc|optional, 1 }, 3567 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI child XP */ 3568 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI child XP */ 3569 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI client XP */ 3570 /* in MDI frame */ 3571 { 0x0093, sent|optional }, 3572 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, 3573 { 0x0093, sent|defwinproc|optional }, 3574 { 0x0093, sent|defwinproc|optional }, 3575 { 0x0093, sent|defwinproc|optional }, 3576 { 0x0091, sent|defwinproc|optional }, 3577 { 0x0092, sent|defwinproc|optional }, 3578 { 0x0092, sent|defwinproc|optional }, 3579 { 0x0092, sent|defwinproc|optional }, 3580 { 0x0092, sent|defwinproc|optional }, 3581 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI frame XP */ 3582 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI frame XP */ 3583 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI child XP */ 3584 { 0 } 3585 }; 3586 /* ShowWindow(SW_MAXIMIZE) for a visible MDI child window */ 3587 static const struct message WmMaximizeMDIchildVisibleSeq[] = { 3588 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 3589 { WM_GETMINMAXINFO, sent }, 3590 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, 3591 { WM_NCCALCSIZE, sent|wparam, 1 }, 3592 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 3593 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 3594 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 3595 /* in MDI frame */ 3596 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3597 { WM_NCCALCSIZE, sent|wparam, 1 }, 3598 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3599 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3600 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3601 { 0 } 3602 }; 3603 /* ShowWindow(SW_RESTORE) for a visible maximized MDI child window */ 3604 static const struct message WmRestoreMDIchildVisibleSeq[] = { 3605 { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE }, 3606 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, 3607 { WM_NCCALCSIZE, sent|wparam, 1 }, 3608 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 3609 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 3610 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 3611 /* in MDI frame */ 3612 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3613 { WM_NCCALCSIZE, sent|wparam, 1 }, 3614 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3615 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3616 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3617 { 0 } 3618 }; 3619 /* ShowWindow(SW_RESTORE) for a visible minimized MDI child window */ 3620 static const struct message WmRestoreMDIchildVisibleSeq_2[] = { 3621 { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE }, 3622 { WM_QUERYOPEN, sent|wparam|lparam, 0, 0 }, 3623 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 3624 { WM_NCCALCSIZE, sent|wparam, 1 }, 3625 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 3626 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 3627 { WM_MOVE, sent|defwinproc }, 3628 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 3629 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3630 { EVENT_SYSTEM_MINIMIZEEND, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3631 { HCBT_SETFOCUS, hook }, 3632 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 3633 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 3634 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3635 { WM_SETFOCUS, sent }, 3636 { 0 } 3637 }; 3638 /* ShowWindow(SW_MINIMIZE) for a visible restored MDI child window */ 3639 static const struct message WmMinimizeMDIchildVisibleSeq[] = { 3640 { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, 3641 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_STATECHANGED }, 3642 { WM_NCCALCSIZE, sent|wparam, 1 }, 3643 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_STATECHANGED }, 3644 { WM_MOVE, sent|defwinproc }, 3645 { WM_SIZE, sent|defwinproc|wparam|lparam, SIZE_MINIMIZED, 0 }, 3646 { WM_CHILDACTIVATE, sent|wparam|lparam|defwinproc, 0, 0 }, 3647 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3648 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3649 /* FIXME: Wine creates an icon/title window while Windows doesn't */ 3650 { WM_PARENTNOTIFY, sent|parent|wparam|optional, WM_CREATE }, /* MDI client */ 3651 { 0 } 3652 }; 3653 /* ShowWindow(SW_RESTORE) for a not visible MDI child window */ 3654 static const struct message WmRestoreMDIchildInvisibleSeq[] = { 3655 { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE }, 3656 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_STATECHANGED }, 3657 { WM_NCCALCSIZE, sent|wparam, 1 }, 3658 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 3659 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 3660 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 3661 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 3662 /* in MDI frame */ 3663 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3664 { WM_NCCALCSIZE, sent|wparam, 1 }, 3665 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3666 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3667 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3668 { 0 } 3669 }; 3670 3671 static HWND mdi_client; 3672 static WNDPROC old_mdi_client_proc; 3673 3674 static LRESULT WINAPI mdi_client_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 3675 { 3676 struct recvd_message msg; 3677 3678 /* do not log painting messages */ 3679 if (message != WM_PAINT && 3680 message != WM_NCPAINT && 3681 message != WM_SYNCPAINT && 3682 message != WM_ERASEBKGND && 3683 message != WM_NCHITTEST && 3684 message != WM_GETTEXT && 3685 message != WM_MDIGETACTIVE && 3686 !ignore_message( message )) 3687 { 3688 msg.hwnd = hwnd; 3689 msg.message = message; 3690 msg.flags = sent|wparam|lparam; 3691 msg.wParam = wParam; 3692 msg.lParam = lParam; 3693 msg.descr = "mdi client"; 3694 add_message(&msg); 3695 } 3696 3697 return CallWindowProcA(old_mdi_client_proc, hwnd, message, wParam, lParam); 3698 } 3699 3700 static LRESULT WINAPI mdi_child_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 3701 { 3702 static LONG defwndproc_counter = 0; 3703 LRESULT ret; 3704 struct recvd_message msg; 3705 3706 /* do not log painting messages */ 3707 if (message != WM_PAINT && 3708 message != WM_NCPAINT && 3709 message != WM_SYNCPAINT && 3710 message != WM_ERASEBKGND && 3711 message != WM_NCHITTEST && 3712 message != WM_GETTEXT && 3713 !ignore_message( message )) 3714 { 3715 switch (message) 3716 { 3717 case WM_MDIACTIVATE: 3718 { 3719 HWND active, client = GetParent(hwnd); 3720 3721 active = (HWND)SendMessageA(client, WM_MDIGETACTIVE, 0, 0); 3722 3723 if (hwnd == (HWND)lParam) /* if we are being activated */ 3724 ok (active == (HWND)lParam, "new active %p != active %p\n", (HWND)lParam, active); 3725 else 3726 ok (active == (HWND)wParam, "old active %p != active %p\n", (HWND)wParam, active); 3727 break; 3728 } 3729 } 3730 3731 msg.hwnd = hwnd; 3732 msg.message = message; 3733 msg.flags = sent|wparam|lparam; 3734 if (defwndproc_counter) msg.flags |= defwinproc; 3735 msg.wParam = wParam; 3736 msg.lParam = lParam; 3737 msg.descr = "mdi child"; 3738 add_message(&msg); 3739 } 3740 3741 defwndproc_counter++; 3742 ret = DefMDIChildProcA(hwnd, message, wParam, lParam); 3743 defwndproc_counter--; 3744 3745 return ret; 3746 } 3747 3748 static LRESULT WINAPI mdi_frame_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 3749 { 3750 static LONG defwndproc_counter = 0; 3751 LRESULT ret; 3752 struct recvd_message msg; 3753 3754 /* do not log painting messages */ 3755 if (message != WM_PAINT && 3756 message != WM_NCPAINT && 3757 message != WM_SYNCPAINT && 3758 message != WM_ERASEBKGND && 3759 message != WM_NCHITTEST && 3760 message != WM_GETTEXT && 3761 !ignore_message( message )) 3762 { 3763 msg.hwnd = hwnd; 3764 msg.message = message; 3765 msg.flags = sent|wparam|lparam; 3766 if (defwndproc_counter) msg.flags |= defwinproc; 3767 msg.wParam = wParam; 3768 msg.lParam = lParam; 3769 msg.descr = "mdi frame"; 3770 add_message(&msg); 3771 } 3772 3773 defwndproc_counter++; 3774 ret = DefFrameProcA(hwnd, mdi_client, message, wParam, lParam); 3775 defwndproc_counter--; 3776 3777 return ret; 3778 } 3779 3780 static BOOL mdi_RegisterWindowClasses(void) 3781 { 3782 WNDCLASSA cls; 3783 3784 cls.style = 0; 3785 cls.lpfnWndProc = mdi_frame_wnd_proc; 3786 cls.cbClsExtra = 0; 3787 cls.cbWndExtra = 0; 3788 cls.hInstance = GetModuleHandleA(0); 3789 cls.hIcon = 0; 3790 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 3791 cls.hbrBackground = GetStockObject(WHITE_BRUSH); 3792 cls.lpszMenuName = NULL; 3793 cls.lpszClassName = "MDI_frame_class"; 3794 if (!RegisterClassA(&cls)) return FALSE; 3795 3796 cls.lpfnWndProc = mdi_child_wnd_proc; 3797 cls.lpszClassName = "MDI_child_class"; 3798 if (!RegisterClassA(&cls)) return FALSE; 3799 3800 if (!GetClassInfoA(0, "MDIClient", &cls)) assert(0); 3801 old_mdi_client_proc = cls.lpfnWndProc; 3802 cls.hInstance = GetModuleHandleA(0); 3803 cls.lpfnWndProc = mdi_client_hook_proc; 3804 cls.lpszClassName = "MDI_client_class"; 3805 if (!RegisterClassA(&cls)) assert(0); 3806 3807 return TRUE; 3808 } 3809 3810 static void test_mdi_messages(void) 3811 { 3812 MDICREATESTRUCTA mdi_cs; 3813 CLIENTCREATESTRUCT client_cs; 3814 HWND mdi_frame, mdi_child, mdi_child2, active_child; 3815 BOOL zoomed; 3816 RECT rc; 3817 HMENU hMenu = CreateMenu(); 3818 LONG val; 3819 3820 if (!mdi_RegisterWindowClasses()) assert(0); 3821 3822 flush_sequence(); 3823 3824 trace("creating MDI frame window\n"); 3825 mdi_frame = CreateWindowExA(0, "MDI_frame_class", "MDI frame window", 3826 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | 3827 WS_MAXIMIZEBOX | WS_VISIBLE, 3828 100, 100, CW_USEDEFAULT, CW_USEDEFAULT, 3829 GetDesktopWindow(), hMenu, 3830 GetModuleHandleA(0), NULL); 3831 assert(mdi_frame); 3832 ok_sequence(WmCreateMDIframeSeq, "Create MDI frame window", FALSE); 3833 3834 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 3835 ok(GetFocus() == mdi_frame, "wrong focus window %p\n", GetFocus()); 3836 3837 trace("creating MDI client window\n"); 3838 GetClientRect(mdi_frame, &rc); 3839 client_cs.hWindowMenu = 0; 3840 client_cs.idFirstChild = MDI_FIRST_CHILD_ID; 3841 mdi_client = CreateWindowExA(0, "MDI_client_class", 3842 NULL, 3843 WS_CHILD | WS_VISIBLE | MDIS_ALLCHILDSTYLES, 3844 rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, 3845 mdi_frame, 0, GetModuleHandleA(0), &client_cs); 3846 assert(mdi_client); 3847 SetWindowLongA(mdi_client, 0, 0xdeadbeef); 3848 3849 ok_sequence(WmCreateMDIclientSeq, "Create visible MDI client window", FALSE); 3850 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 3851 ok(GetFocus() == mdi_frame, "input focus should be on MDI frame not on %p\n", GetFocus()); 3852 3853 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 3854 ok(!active_child, "wrong active MDI child %p\n", active_child); 3855 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 3856 3857 SetFocus(0); 3858 flush_sequence(); 3859 3860 trace("creating invisible MDI child window\n"); 3861 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", 3862 WS_CHILD, 3863 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 3864 mdi_client, 0, GetModuleHandleA(0), NULL); 3865 assert(mdi_child); 3866 3867 flush_sequence(); 3868 ShowWindow(mdi_child, SW_SHOWNORMAL); 3869 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOWNORMAL) MDI child window", FALSE); 3870 3871 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n"); 3872 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n"); 3873 3874 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 3875 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 3876 3877 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 3878 ok(!active_child, "wrong active MDI child %p\n", active_child); 3879 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 3880 3881 ShowWindow(mdi_child, SW_HIDE); 3882 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE) MDI child window", FALSE); 3883 flush_sequence(); 3884 3885 ShowWindow(mdi_child, SW_SHOW); 3886 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW) MDI child window", FALSE); 3887 3888 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n"); 3889 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n"); 3890 3891 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 3892 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 3893 3894 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 3895 ok(!active_child, "wrong active MDI child %p\n", active_child); 3896 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 3897 3898 DestroyWindow(mdi_child); 3899 flush_sequence(); 3900 3901 trace("creating visible MDI child window\n"); 3902 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", 3903 WS_CHILD | WS_VISIBLE, 3904 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 3905 mdi_client, 0, GetModuleHandleA(0), NULL); 3906 assert(mdi_child); 3907 ok_sequence(WmCreateMDIchildVisibleSeq, "Create visible MDI child window", FALSE); 3908 3909 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n"); 3910 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n"); 3911 3912 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 3913 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus()); 3914 3915 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 3916 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child); 3917 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 3918 flush_sequence(); 3919 3920 DestroyWindow(mdi_child); 3921 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE); 3922 3923 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 3924 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 3925 3926 /* Win2k: MDI client still returns a just destroyed child as active 3927 * Win9x: MDI client returns 0 3928 */ 3929 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 3930 ok(active_child == mdi_child || /* win2k */ 3931 !active_child, /* win9x */ 3932 "wrong active MDI child %p\n", active_child); 3933 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 3934 3935 flush_sequence(); 3936 3937 trace("creating invisible MDI child window\n"); 3938 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", 3939 WS_CHILD, 3940 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 3941 mdi_client, 0, GetModuleHandleA(0), NULL); 3942 assert(mdi_child2); 3943 ok_sequence(WmCreateMDIchildInvisibleSeq, "Create invisible MDI child window", FALSE); 3944 3945 ok(!(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE), "MDI child should not be visible\n"); 3946 ok(!IsWindowVisible(mdi_child2), "MDI child should not be visible\n"); 3947 3948 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 3949 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 3950 3951 /* Win2k: MDI client still returns a just destroyed child as active 3952 * Win9x: MDI client returns mdi_child2 3953 */ 3954 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 3955 ok(active_child == mdi_child || /* win2k */ 3956 active_child == mdi_child2, /* win9x */ 3957 "wrong active MDI child %p\n", active_child); 3958 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 3959 flush_sequence(); 3960 3961 ShowWindow(mdi_child2, SW_MAXIMIZE); 3962 ok_sequence(WmMaximizeMDIchildInvisibleSeq, "ShowWindow(SW_MAXIMIZE):invisible MDI child", FALSE); 3963 3964 ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n"); 3965 ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n"); 3966 3967 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 3968 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); 3969 ok(zoomed, "wrong zoomed state %d\n", zoomed); 3970 flush_sequence(); 3971 3972 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 3973 ok(GetFocus() == mdi_child2 || /* win2k */ 3974 GetFocus() == 0, /* win9x */ 3975 "wrong focus window %p\n", GetFocus()); 3976 3977 SetFocus(0); 3978 flush_sequence(); 3979 3980 ShowWindow(mdi_child2, SW_HIDE); 3981 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE); 3982 3983 ShowWindow(mdi_child2, SW_RESTORE); 3984 ok_sequence(WmRestoreMDIchildInvisibleSeq, "ShowWindow(SW_RESTORE):invisible MDI child", FALSE); 3985 flush_sequence(); 3986 3987 ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n"); 3988 ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n"); 3989 3990 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 3991 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); 3992 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 3993 flush_sequence(); 3994 3995 SetFocus(0); 3996 flush_sequence(); 3997 3998 ShowWindow(mdi_child2, SW_HIDE); 3999 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE); 4000 4001 ShowWindow(mdi_child2, SW_SHOW); 4002 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):MDI child", FALSE); 4003 4004 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4005 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 4006 4007 ShowWindow(mdi_child2, SW_MAXIMIZE); 4008 ok_sequence(WmMaximizeMDIchildVisibleSeq, "ShowWindow(SW_MAXIMIZE):MDI child", FALSE); 4009 4010 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4011 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 4012 4013 ShowWindow(mdi_child2, SW_RESTORE); 4014 ok_sequence(WmRestoreMDIchildVisibleSeq, "ShowWindow(SW_RESTORE):maximized MDI child", FALSE); 4015 4016 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4017 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 4018 4019 ShowWindow(mdi_child2, SW_MINIMIZE); 4020 ok_sequence(WmMinimizeMDIchildVisibleSeq, "ShowWindow(SW_MINIMIZE):MDI child", TRUE); 4021 4022 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4023 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 4024 4025 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4026 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); 4027 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 4028 flush_sequence(); 4029 4030 ShowWindow(mdi_child2, SW_RESTORE); 4031 ok_sequence(WmRestoreMDIchildVisibleSeq_2, "ShowWindow(SW_RESTORE):minimized MDI child", FALSE); 4032 4033 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4034 ok(GetFocus() == mdi_child2, "wrong focus window %p\n", GetFocus()); 4035 4036 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4037 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); 4038 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 4039 flush_sequence(); 4040 4041 SetFocus(0); 4042 flush_sequence(); 4043 4044 ShowWindow(mdi_child2, SW_HIDE); 4045 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE); 4046 4047 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4048 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 4049 4050 DestroyWindow(mdi_child2); 4051 ok_sequence(WmDestroyMDIchildInvisibleSeq, "Destroy invisible MDI child window", FALSE); 4052 4053 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4054 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 4055 4056 trace("Testing WM_CHILDACTIVATE\n"); 4057 4058 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", 4059 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_DISABLED, 4060 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 4061 mdi_client, 0, GetModuleHandleA(0), NULL); 4062 4063 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", 4064 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX, 4065 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 4066 mdi_client, 0, GetModuleHandleA(0), NULL); 4067 4068 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4069 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); 4070 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 4071 4072 flush_sequence(); 4073 SendMessageW(mdi_child, WM_CHILDACTIVATE, 0, 0); 4074 ok_sequence(WmChildActivateDisabledWindowSeq, "WM_CHILDACTIVATE sent to disabled window", FALSE); 4075 4076 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4077 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); 4078 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 4079 flush_sequence(); 4080 4081 EnableWindow(mdi_child, TRUE); 4082 4083 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4084 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); 4085 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 4086 4087 flush_sequence(); 4088 SendMessageW(mdi_child, WM_CHILDACTIVATE, 0, 0); 4089 ok_sequence(WmChildActivateWindowSeq, "WM_CHILDACTIVATE sent to enabled window", FALSE); 4090 4091 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4092 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child); 4093 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 4094 flush_sequence(); 4095 4096 DestroyWindow(mdi_child); 4097 DestroyWindow(mdi_child2); 4098 flush_sequence(); 4099 4100 /* test for maximized MDI children */ 4101 trace("creating maximized visible MDI child window 1\n"); 4102 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", 4103 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE, 4104 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 4105 mdi_client, 0, GetModuleHandleA(0), NULL); 4106 assert(mdi_child); 4107 ok_sequence(WmCreateMDIchildVisibleMaxSeq1, "Create maximized visible 1st MDI child window", TRUE); 4108 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n"); 4109 4110 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4111 ok(GetFocus() == mdi_child || /* win2k */ 4112 GetFocus() == 0, /* win9x */ 4113 "wrong focus window %p\n", GetFocus()); 4114 4115 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4116 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child); 4117 ok(zoomed, "wrong zoomed state %d\n", zoomed); 4118 flush_sequence(); 4119 4120 trace("creating maximized visible MDI child window 2\n"); 4121 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", 4122 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE, 4123 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 4124 mdi_client, 0, GetModuleHandleA(0), NULL); 4125 assert(mdi_child2); 4126 ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child 2 window", TRUE); 4127 ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized\n"); 4128 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n"); 4129 4130 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4131 ok(GetFocus() == mdi_child2, "wrong focus window %p\n", GetFocus()); 4132 4133 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4134 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); 4135 ok(zoomed, "wrong zoomed state %d\n", zoomed); 4136 flush_sequence(); 4137 4138 trace("destroying maximized visible MDI child window 2\n"); 4139 DestroyWindow(mdi_child2); 4140 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE); 4141 4142 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n"); 4143 4144 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4145 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 4146 4147 /* Win2k: MDI client still returns a just destroyed child as active 4148 * Win9x: MDI client returns 0 4149 */ 4150 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4151 ok(active_child == mdi_child2 || /* win2k */ 4152 !active_child, /* win9x */ 4153 "wrong active MDI child %p\n", active_child); 4154 flush_sequence(); 4155 4156 ShowWindow(mdi_child, SW_MAXIMIZE); 4157 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n"); 4158 flush_sequence(); 4159 4160 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4161 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus()); 4162 4163 trace("re-creating maximized visible MDI child window 2\n"); 4164 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", 4165 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE, 4166 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 4167 mdi_client, 0, GetModuleHandleA(0), NULL); 4168 assert(mdi_child2); 4169 ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child 2 window", TRUE); 4170 ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized\n"); 4171 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n"); 4172 4173 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4174 ok(GetFocus() == mdi_child2, "wrong focus window %p\n", GetFocus()); 4175 4176 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4177 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); 4178 ok(zoomed, "wrong zoomed state %d\n", zoomed); 4179 flush_sequence(); 4180 4181 SendMessageA(mdi_child2, WM_SYSCOMMAND, SC_CLOSE, 0); 4182 ok_sequence(WmDestroyMDIchildVisibleMaxSeq2, "WM_SYSCOMMAND/SC_CLOSE on a visible maximized MDI child window", TRUE); 4183 ok(!IsWindow(mdi_child2), "MDI child 2 should be destroyed\n"); 4184 4185 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n"); 4186 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4187 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus()); 4188 4189 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4190 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child); 4191 ok(zoomed, "wrong zoomed state %d\n", zoomed); 4192 flush_sequence(); 4193 4194 DestroyWindow(mdi_child); 4195 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE); 4196 4197 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4198 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 4199 4200 /* Win2k: MDI client still returns a just destroyed child as active 4201 * Win9x: MDI client returns 0 4202 */ 4203 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4204 ok(active_child == mdi_child || /* win2k */ 4205 !active_child, /* win9x */ 4206 "wrong active MDI child %p\n", active_child); 4207 flush_sequence(); 4208 4209 trace("creating maximized invisible MDI child window\n"); 4210 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", 4211 WS_CHILD | WS_MAXIMIZE | WS_CAPTION | WS_THICKFRAME, 4212 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 4213 mdi_client, 0, GetModuleHandleA(0), NULL); 4214 assert(mdi_child2); 4215 ok_sequence(WmCreateMDIchildInvisibleMaxSeq4, "Create maximized invisible MDI child window", FALSE); 4216 ok(IsZoomed(mdi_child2), "MDI child should be maximized\n"); 4217 ok(!(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE), "MDI child should be not visible\n"); 4218 ok(!IsWindowVisible(mdi_child2), "MDI child should be not visible\n"); 4219 4220 /* Win2k: MDI client still returns a just destroyed child as active 4221 * Win9x: MDI client returns 0 4222 */ 4223 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4224 ok(active_child == mdi_child || /* win2k */ 4225 !active_child || active_child == mdi_child2, /* win9x */ 4226 "wrong active MDI child %p\n", active_child); 4227 flush_sequence(); 4228 4229 trace("call ShowWindow(mdi_child, SW_MAXIMIZE)\n"); 4230 ShowWindow(mdi_child2, SW_MAXIMIZE); 4231 ok_sequence(WmMaximizeMDIchildInvisibleSeq2, "ShowWindow(SW_MAXIMIZE):invisible maximized MDI child", FALSE); 4232 ok(IsZoomed(mdi_child2), "MDI child should be maximized\n"); 4233 ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n"); 4234 ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n"); 4235 4236 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4237 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); 4238 ok(zoomed, "wrong zoomed state %d\n", zoomed); 4239 flush_sequence(); 4240 4241 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child2, 0); 4242 flush_sequence(); 4243 4244 /* end of test for maximized MDI children */ 4245 SetFocus(0); 4246 flush_sequence(); 4247 trace("creating maximized visible MDI child window 1(Switch test)\n"); 4248 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", 4249 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE, 4250 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 4251 mdi_client, 0, GetModuleHandleA(0), NULL); 4252 assert(mdi_child); 4253 ok_sequence(WmCreateMDIchildVisibleMaxSeq1, "Create maximized visible 1st MDI child window(Switch test)", TRUE); 4254 ok(IsZoomed(mdi_child), "1st MDI child should be maximized(Switch test)\n"); 4255 4256 ok(GetActiveWindow() == mdi_frame, "wrong active window %p(Switch test)\n", GetActiveWindow()); 4257 ok(GetFocus() == mdi_child || /* win2k */ 4258 GetFocus() == 0, /* win9x */ 4259 "wrong focus window %p(Switch test)\n", GetFocus()); 4260 4261 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4262 ok(active_child == mdi_child, "wrong active MDI child %p(Switch test)\n", active_child); 4263 ok(zoomed, "wrong zoomed state %d(Switch test)\n", zoomed); 4264 flush_sequence(); 4265 4266 trace("creating maximized visible MDI child window 2(Switch test)\n"); 4267 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", 4268 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE, 4269 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 4270 mdi_client, 0, GetModuleHandleA(0), NULL); 4271 assert(mdi_child2); 4272 ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child window (Switch test)", TRUE); 4273 4274 ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized(Switch test)\n"); 4275 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized(Switch test)\n"); 4276 4277 ok(GetActiveWindow() == mdi_frame, "wrong active window %p(Switch test)\n", GetActiveWindow()); 4278 ok(GetFocus() == mdi_child2, "wrong focus window %p(Switch test)\n", GetFocus()); 4279 4280 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4281 ok(active_child == mdi_child2, "wrong active MDI child %p(Switch test)\n", active_child); 4282 ok(zoomed, "wrong zoomed state %d(Switch test)\n", zoomed); 4283 flush_sequence(); 4284 4285 trace("Switch child window.\n"); 4286 SendMessageA(mdi_client, WM_MDIACTIVATE, (WPARAM)mdi_child, 0); 4287 ok_sequence(WmSwitchChild, "Child did not switch correctly", TRUE); 4288 trace("end of test for switch maximized MDI children\n"); 4289 flush_sequence(); 4290 4291 /* Prepare for switching test of not maximized MDI children */ 4292 ShowWindow( mdi_child, SW_NORMAL ); 4293 ok(!IsZoomed(mdi_child), "wrong zoomed state for %p(Switch test)\n", mdi_child); 4294 ok(!IsZoomed(mdi_child2), "wrong zoomed state for %p(Switch test)\n", mdi_child2); 4295 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0); 4296 ok(active_child == mdi_child, "wrong active MDI child %p(Switch test)\n", active_child); 4297 flush_sequence(); 4298 4299 SendMessageA(mdi_client, WM_MDIACTIVATE, (WPARAM)mdi_child2, 0); 4300 ok_sequence(WmSwitchNotMaximizedChild, "Not maximized child did not switch correctly", FALSE); 4301 trace("end of test for switch not maximized MDI children\n"); 4302 flush_sequence(); 4303 4304 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0); 4305 flush_sequence(); 4306 4307 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child2, 0); 4308 flush_sequence(); 4309 4310 SetFocus(0); 4311 flush_sequence(); 4312 /* end of tests for switch maximized/not maximized MDI children */ 4313 4314 mdi_cs.szClass = "MDI_child_Class"; 4315 mdi_cs.szTitle = "MDI child"; 4316 mdi_cs.hOwner = GetModuleHandleA(0); 4317 mdi_cs.x = 0; 4318 mdi_cs.y = 0; 4319 mdi_cs.cx = CW_USEDEFAULT; 4320 mdi_cs.cy = CW_USEDEFAULT; 4321 mdi_cs.style = WS_CHILD | WS_SYSMENU | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE; 4322 mdi_cs.lParam = 0; 4323 mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs); 4324 ok(mdi_child != 0, "MDI child creation failed\n"); 4325 ok_sequence(WmCreateMDIchildVisibleMaxSeq3, "WM_MDICREATE for maximized visible MDI child window", TRUE); 4326 4327 ok(GetMenuItemID(hMenu, GetMenuItemCount(hMenu) - 1) == SC_CLOSE, "SC_CLOSE menu item not found\n"); 4328 4329 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4330 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child); 4331 4332 ok(IsZoomed(mdi_child), "MDI child should be maximized\n"); 4333 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4334 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus()); 4335 4336 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4337 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child); 4338 ok(zoomed, "wrong zoomed state %d\n", zoomed); 4339 flush_sequence(); 4340 4341 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0); 4342 ok_sequence(WmDestroyMDIchildVisibleMaxSeq1, "Destroy visible maximized MDI child window", TRUE); 4343 4344 ok(!IsWindow(mdi_child), "MDI child should be destroyed\n"); 4345 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4346 ok(!active_child, "wrong active MDI child %p\n", active_child); 4347 4348 SetFocus(0); 4349 flush_sequence(); 4350 4351 val = GetWindowLongA(mdi_client, 0); 4352 ok(val == 0xdeadbeef || broken(val == 0) /* >= Win Vista */, "Expected 0xdeadbeef, got 0x%x\n", val); 4353 DestroyWindow(mdi_client); 4354 ok_sequence(WmDestroyMDIclientSeq, "Destroy MDI client window", FALSE); 4355 4356 /* test maximization of MDI child with invisible parent */ 4357 client_cs.hWindowMenu = 0; 4358 mdi_client = CreateWindowA("MDI_client_class", 4359 NULL, 4360 WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL | WS_VISIBLE, 4361 0, 0, 660, 430, 4362 mdi_frame, 0, GetModuleHandleA(0), &client_cs); 4363 ok_sequence(WmCreateMDIclientSeq, "Create MDI client window", FALSE); 4364 4365 ShowWindow(mdi_client, SW_HIDE); 4366 ok_sequence(WmHideMDIclientSeq, "Hide MDI client window", FALSE); 4367 4368 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", 4369 WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL, 4370 0, 0, 650, 440, 4371 mdi_client, 0, GetModuleHandleA(0), NULL); 4372 ok_sequence(WmCreateMDIchildInvisibleParentSeq, "Create MDI child window with invisible parent", FALSE); 4373 4374 SendMessageA(mdi_client, WM_MDIMAXIMIZE, (WPARAM) mdi_child, 0); 4375 ok_sequence(WmMaximizeMDIchildInvisibleParentSeq, "Maximize MDI child window with invisible parent", TRUE); 4376 zoomed = IsZoomed(mdi_child); 4377 ok(zoomed, "wrong zoomed state %d\n", zoomed); 4378 4379 ShowWindow(mdi_client, SW_SHOW); 4380 ok_sequence(WmShowMDIclientSeq, "Show MDI client window", FALSE); 4381 4382 DestroyWindow(mdi_child); 4383 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible maximized MDI child window", TRUE); 4384 4385 /* end of test for maximization of MDI child with invisible parent */ 4386 4387 DestroyWindow(mdi_client); 4388 ok_sequence(WmDestroyMDIclientSeq, "Destroy MDI client window", FALSE); 4389 4390 DestroyWindow(mdi_frame); 4391 ok_sequence(WmDestroyMDIframeSeq, "Destroy MDI frame window", FALSE); 4392 } 4393 /************************* End of MDI test **********************************/ 4394 4395 static void test_WM_SETREDRAW(HWND hwnd) 4396 { 4397 DWORD style = GetWindowLongA(hwnd, GWL_STYLE); 4398 4399 flush_events(); 4400 flush_sequence(); 4401 4402 SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0); 4403 ok_sequence(WmSetRedrawFalseSeq, "SetRedraw:FALSE", FALSE); 4404 4405 ok(!(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should NOT be set\n"); 4406 ok(!IsWindowVisible(hwnd), "IsWindowVisible() should return FALSE\n"); 4407 4408 flush_sequence(); 4409 SendMessageA(hwnd, WM_SETREDRAW, TRUE, 0); 4410 ok_sequence(WmSetRedrawTrueSeq, "SetRedraw:TRUE", FALSE); 4411 4412 ok(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 4413 ok(IsWindowVisible(hwnd), "IsWindowVisible() should return TRUE\n"); 4414 4415 /* restore original WS_VISIBLE state */ 4416 SetWindowLongA(hwnd, GWL_STYLE, style); 4417 4418 flush_events(); 4419 flush_sequence(); 4420 } 4421 4422 static INT_PTR CALLBACK TestModalDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 4423 { 4424 struct recvd_message msg; 4425 4426 if (ignore_message( message )) return 0; 4427 4428 switch (message) 4429 { 4430 /* ignore */ 4431 case WM_MOUSEMOVE: 4432 case WM_NCMOUSEMOVE: 4433 case WM_NCMOUSELEAVE: 4434 case WM_SETCURSOR: 4435 return 0; 4436 case WM_NCHITTEST: 4437 return HTCLIENT; 4438 } 4439 4440 msg.hwnd = hwnd; 4441 msg.message = message; 4442 msg.flags = sent|wparam|lparam; 4443 msg.wParam = wParam; 4444 msg.lParam = lParam; 4445 msg.descr = "dialog"; 4446 add_message(&msg); 4447 4448 if (message == WM_INITDIALOG) SetTimer( hwnd, 1, 100, NULL ); 4449 if (message == WM_TIMER) EndDialog( hwnd, 0 ); 4450 return 0; 4451 } 4452 4453 static INT_PTR CALLBACK TestModalDlgProc2(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 4454 { 4455 struct recvd_message msg; 4456 4457 if (ignore_message( message )) return 0; 4458 4459 switch (message) 4460 { 4461 /* ignore */ 4462 case WM_MOUSEMOVE: 4463 case WM_NCMOUSEMOVE: 4464 case WM_NCMOUSELEAVE: 4465 case WM_SETCURSOR: 4466 return 0; 4467 case WM_NCHITTEST: 4468 return HTCLIENT; 4469 } 4470 4471 msg.hwnd = hwnd; 4472 msg.message = message; 4473 msg.flags = sent|wparam|lparam; 4474 msg.wParam = wParam; 4475 msg.lParam = lParam; 4476 msg.descr = "dialog"; 4477 add_message(&msg); 4478 4479 if (message == WM_INITDIALOG) EndDialog( hwnd, 0 ); 4480 return 0; 4481 } 4482 4483 static void test_hv_scroll_1(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max) 4484 { 4485 DWORD style, exstyle; 4486 INT xmin, xmax; 4487 BOOL ret; 4488 4489 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE); 4490 style = GetWindowLongA(hwnd, GWL_STYLE); 4491 /* do not be confused by WS_DLGFRAME set */ 4492 if ((style & WS_CAPTION) == WS_CAPTION) style &= ~WS_CAPTION; 4493 4494 if (clear) ok(style & clear, "style %08x should be set\n", clear); 4495 if (set) ok(!(style & set), "style %08x should not be set\n", set); 4496 4497 ret = SetScrollRange(hwnd, ctl, min, max, FALSE); 4498 ok( ret, "SetScrollRange(%d) error %d\n", ctl, GetLastError()); 4499 if ((style & (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME)) || (exstyle & WS_EX_DLGMODALFRAME)) 4500 ok_sequence(WmSetScrollRangeHV_NC_Seq, "SetScrollRange(SB_HORZ/SB_VERT) NC", FALSE); 4501 else 4502 ok_sequence(WmSetScrollRangeHVSeq, "SetScrollRange(SB_HORZ/SB_VERT)", FALSE); 4503 4504 style = GetWindowLongA(hwnd, GWL_STYLE); 4505 if (set) ok(style & set, "style %08x should be set\n", set); 4506 if (clear) ok(!(style & clear), "style %08x should not be set\n", clear); 4507 4508 /* a subsequent call should do nothing */ 4509 ret = SetScrollRange(hwnd, ctl, min, max, FALSE); 4510 ok( ret, "SetScrollRange(%d) error %d\n", ctl, GetLastError()); 4511 ok_sequence(WmEmptySeq, "SetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE); 4512 4513 xmin = 0xdeadbeef; 4514 xmax = 0xdeadbeef; 4515 ret = GetScrollRange(hwnd, ctl, &xmin, &xmax); 4516 ok( ret, "GetScrollRange(%d) error %d\n", ctl, GetLastError()); 4517 ok_sequence(WmEmptySeq, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE); 4518 ok(xmin == min, "unexpected min scroll value %d\n", xmin); 4519 ok(xmax == max, "unexpected max scroll value %d\n", xmax); 4520 } 4521 4522 static void test_hv_scroll_2(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max) 4523 { 4524 DWORD style, exstyle; 4525 SCROLLINFO si; 4526 BOOL ret; 4527 4528 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE); 4529 style = GetWindowLongA(hwnd, GWL_STYLE); 4530 /* do not be confused by WS_DLGFRAME set */ 4531 if ((style & WS_CAPTION) == WS_CAPTION) style &= ~WS_CAPTION; 4532 4533 if (clear) ok(style & clear, "style %08x should be set\n", clear); 4534 if (set) ok(!(style & set), "style %08x should not be set\n", set); 4535 4536 si.cbSize = sizeof(si); 4537 si.fMask = SIF_RANGE; 4538 si.nMin = min; 4539 si.nMax = max; 4540 SetScrollInfo(hwnd, ctl, &si, TRUE); 4541 if ((style & (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME)) || (exstyle & WS_EX_DLGMODALFRAME)) 4542 ok_sequence(WmSetScrollRangeHV_NC_Seq, "SetScrollInfo(SB_HORZ/SB_VERT) NC", FALSE); 4543 else 4544 ok_sequence(WmSetScrollRangeHVSeq, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE); 4545 4546 style = GetWindowLongA(hwnd, GWL_STYLE); 4547 if (set) ok(style & set, "style %08x should be set\n", set); 4548 if (clear) ok(!(style & clear), "style %08x should not be set\n", clear); 4549 4550 /* a subsequent call should do nothing */ 4551 SetScrollInfo(hwnd, ctl, &si, TRUE); 4552 if (style & WS_HSCROLL) 4553 ok_sequence(WmSetScrollRangeHSeq_empty, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE); 4554 else if (style & WS_VSCROLL) 4555 ok_sequence(WmSetScrollRangeVSeq_empty, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE); 4556 else 4557 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE); 4558 4559 si.fMask = SIF_PAGE; 4560 si.nPage = 5; 4561 SetScrollInfo(hwnd, ctl, &si, FALSE); 4562 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE); 4563 4564 si.fMask = SIF_POS; 4565 si.nPos = max - 1; 4566 SetScrollInfo(hwnd, ctl, &si, FALSE); 4567 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE); 4568 4569 si.fMask = SIF_RANGE; 4570 si.nMin = 0xdeadbeef; 4571 si.nMax = 0xdeadbeef; 4572 ret = GetScrollInfo(hwnd, ctl, &si); 4573 ok( ret, "GetScrollInfo error %d\n", GetLastError()); 4574 ok_sequence(WmEmptySeq, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE); 4575 ok(si.nMin == min, "unexpected min scroll value %d\n", si.nMin); 4576 ok(si.nMax == max, "unexpected max scroll value %d\n", si.nMax); 4577 } 4578 4579 /* Win9x sends WM_USER+xxx while and NT versions send SBM_xxx messages */ 4580 static void test_scroll_messages(HWND hwnd) 4581 { 4582 SCROLLINFO si; 4583 INT min, max; 4584 BOOL ret; 4585 4586 flush_events(); 4587 flush_sequence(); 4588 4589 min = 0xdeadbeef; 4590 max = 0xdeadbeef; 4591 ret = GetScrollRange(hwnd, SB_CTL, &min, &max); 4592 ok( ret, "GetScrollRange error %d\n", GetLastError()); 4593 if (sequence->message != WmGetScrollRangeSeq[0].message) 4594 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message); 4595 /* values of min and max are undefined */ 4596 flush_sequence(); 4597 4598 ret = SetScrollRange(hwnd, SB_CTL, 10, 150, FALSE); 4599 ok( ret, "SetScrollRange error %d\n", GetLastError()); 4600 if (sequence->message != WmSetScrollRangeSeq[0].message) 4601 trace("SetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message); 4602 flush_sequence(); 4603 4604 min = 0xdeadbeef; 4605 max = 0xdeadbeef; 4606 ret = GetScrollRange(hwnd, SB_CTL, &min, &max); 4607 ok( ret, "GetScrollRange error %d\n", GetLastError()); 4608 if (sequence->message != WmGetScrollRangeSeq[0].message) 4609 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message); 4610 /* values of min and max are undefined */ 4611 flush_sequence(); 4612 4613 si.cbSize = sizeof(si); 4614 si.fMask = SIF_RANGE; 4615 si.nMin = 20; 4616 si.nMax = 160; 4617 SetScrollInfo(hwnd, SB_CTL, &si, FALSE); 4618 if (sequence->message != WmSetScrollRangeSeq[0].message) 4619 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message); 4620 flush_sequence(); 4621 4622 si.fMask = SIF_PAGE; 4623 si.nPage = 10; 4624 SetScrollInfo(hwnd, SB_CTL, &si, FALSE); 4625 if (sequence->message != WmSetScrollRangeSeq[0].message) 4626 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message); 4627 flush_sequence(); 4628 4629 si.fMask = SIF_POS; 4630 si.nPos = 20; 4631 SetScrollInfo(hwnd, SB_CTL, &si, FALSE); 4632 if (sequence->message != WmSetScrollRangeSeq[0].message) 4633 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message); 4634 flush_sequence(); 4635 4636 si.fMask = SIF_RANGE; 4637 si.nMin = 0xdeadbeef; 4638 si.nMax = 0xdeadbeef; 4639 ret = GetScrollInfo(hwnd, SB_CTL, &si); 4640 ok( ret, "GetScrollInfo error %d\n", GetLastError()); 4641 if (sequence->message != WmGetScrollInfoSeq[0].message) 4642 trace("GetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message); 4643 /* values of min and max are undefined */ 4644 flush_sequence(); 4645 4646 /* set WS_HSCROLL */ 4647 test_hv_scroll_1(hwnd, SB_HORZ, 0, WS_HSCROLL, 10, 150); 4648 /* clear WS_HSCROLL */ 4649 test_hv_scroll_1(hwnd, SB_HORZ, WS_HSCROLL, 0, 0, 0); 4650 4651 /* set WS_HSCROLL */ 4652 test_hv_scroll_2(hwnd, SB_HORZ, 0, WS_HSCROLL, 10, 150); 4653 /* clear WS_HSCROLL */ 4654 test_hv_scroll_2(hwnd, SB_HORZ, WS_HSCROLL, 0, 0, 0); 4655 4656 /* set WS_VSCROLL */ 4657 test_hv_scroll_1(hwnd, SB_VERT, 0, WS_VSCROLL, 10, 150); 4658 /* clear WS_VSCROLL */ 4659 test_hv_scroll_1(hwnd, SB_VERT, WS_VSCROLL, 0, 0, 0); 4660 4661 /* set WS_VSCROLL */ 4662 test_hv_scroll_2(hwnd, SB_VERT, 0, WS_VSCROLL, 10, 150); 4663 /* clear WS_VSCROLL */ 4664 test_hv_scroll_2(hwnd, SB_VERT, WS_VSCROLL, 0, 0, 0); 4665 } 4666 4667 static void test_showwindow(void) 4668 { 4669 HWND hwnd, hchild; 4670 RECT rc; 4671 4672 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW, 4673 100, 100, 200, 200, 0, 0, 0, NULL); 4674 ok (hwnd != 0, "Failed to create overlapped window\n"); 4675 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 4676 0, 0, 10, 10, hwnd, 0, 0, NULL); 4677 ok (hchild != 0, "Failed to create child\n"); 4678 flush_sequence(); 4679 4680 /* ShowWindow( SW_SHOWNA) for invisible top level window */ 4681 trace("calling ShowWindow( SW_SHOWNA) for invisible top level window\n"); 4682 ok( ShowWindow(hwnd, SW_SHOWNA) == FALSE, "ShowWindow: window was visible\n" ); 4683 ok_sequence(WmSHOWNATopInvisible, "ShowWindow(SW_SHOWNA) on invisible top level window", FALSE); 4684 4685 /* ShowWindow( SW_SHOWNA) for now visible top level window */ 4686 trace("calling ShowWindow( SW_SHOWNA) for now visible top level window\n"); 4687 ok( ShowWindow(hwnd, SW_SHOWNA) != FALSE, "ShowWindow: window was invisible\n" ); 4688 ok_sequence(WmSHOWNATopVisible, "ShowWindow(SW_SHOWNA) on visible top level window", FALSE); 4689 /* back to invisible */ 4690 ShowWindow(hchild, SW_HIDE); 4691 ShowWindow(hwnd, SW_HIDE); 4692 flush_sequence(); 4693 /* ShowWindow(SW_SHOWNA) with child and parent invisible */ 4694 trace("calling ShowWindow( SW_SHOWNA) for invisible child with invisible parent\n"); 4695 ok( ShowWindow(hchild, SW_SHOWNA) == FALSE, "ShowWindow: window was visible\n" ); 4696 ok_sequence(WmSHOWNAChildInvisParInvis, "ShowWindow(SW_SHOWNA) invisible child and parent", FALSE); 4697 /* ShowWindow(SW_SHOWNA) with child visible and parent invisible */ 4698 ok( ShowWindow(hchild, SW_SHOW) != FALSE, "ShowWindow: window was invisible\n" ); 4699 flush_sequence(); 4700 trace("calling ShowWindow( SW_SHOWNA) for the visible child and invisible parent\n"); 4701 ok( ShowWindow(hchild, SW_SHOWNA) != FALSE, "ShowWindow: window was invisible\n" ); 4702 ok_sequence(WmSHOWNAChildVisParInvis, "ShowWindow(SW_SHOWNA) visible child and invisible parent", FALSE); 4703 /* ShowWindow(SW_SHOWNA) with child visible and parent visible */ 4704 ShowWindow( hwnd, SW_SHOW); 4705 flush_sequence(); 4706 trace("calling ShowWindow( SW_SHOWNA) for the visible child and parent\n"); 4707 ok( ShowWindow(hchild, SW_SHOWNA) != FALSE, "ShowWindow: window was invisible\n" ); 4708 ok_sequence(WmSHOWNAChildVisParVis, "ShowWindow(SW_SHOWNA) for the visible child and parent", FALSE); 4709 4710 /* ShowWindow(SW_SHOWNA) with child invisible and parent visible */ 4711 ShowWindow( hchild, SW_HIDE); 4712 flush_sequence(); 4713 trace("calling ShowWindow( SW_SHOWNA) for the invisible child and visible parent\n"); 4714 ok( ShowWindow(hchild, SW_SHOWNA) == FALSE, "ShowWindow: window was visible\n" ); 4715 ok_sequence(WmSHOWNAChildInvisParVis, "ShowWindow(SW_SHOWNA) for the invisible child and visible parent", FALSE); 4716 4717 SetCapture(hchild); 4718 ok(GetCapture() == hchild, "wrong capture window %p\n", GetCapture()); 4719 DestroyWindow(hchild); 4720 ok(!GetCapture(), "wrong capture window %p\n", GetCapture()); 4721 4722 DestroyWindow(hwnd); 4723 flush_sequence(); 4724 4725 /* Popup windows */ 4726 /* Test 1: 4727 * 1. Create invisible maximized popup window. 4728 * 2. Move and resize it. 4729 * 3. Show it maximized. 4730 */ 4731 trace("calling CreateWindowExA( WS_MAXIMIZE ) for invisible maximized popup window\n"); 4732 hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_MAXIMIZE, 4733 100, 100, 200, 200, 0, 0, 0, NULL); 4734 ok (hwnd != 0, "Failed to create popup window\n"); 4735 ok(IsZoomed(hwnd), "window should be maximized\n"); 4736 ok_sequence(WmCreateInvisibleMaxPopupSeq, "CreateWindow(WS_MAXIMIZED):popup", FALSE); 4737 4738 GetWindowRect(hwnd, &rc); 4739 ok( rc.right-rc.left == GetSystemMetrics(SM_CXSCREEN) && 4740 rc.bottom-rc.top == GetSystemMetrics(SM_CYSCREEN), 4741 "Invalid maximized size before ShowWindow %s\n", wine_dbgstr_rect( &rc )); 4742 /* Reset window's size & position */ 4743 SetWindowPos(hwnd, 0, 10, 10, 200, 200, SWP_NOZORDER | SWP_NOACTIVATE); 4744 ok(IsZoomed(hwnd), "window should be maximized\n"); 4745 flush_sequence(); 4746 4747 trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible maximized popup window\n"); 4748 ShowWindow(hwnd, SW_SHOWMAXIMIZED); 4749 ok(IsZoomed(hwnd), "window should be maximized\n"); 4750 ok_sequence(WmShowMaxPopupResizedSeq, "ShowWindow(SW_SHOWMAXIMIZED):invisible maximized and resized popup", FALSE); 4751 4752 GetWindowRect(hwnd, &rc); 4753 ok( rc.right-rc.left == GetSystemMetrics(SM_CXSCREEN) && 4754 rc.bottom-rc.top == GetSystemMetrics(SM_CYSCREEN), 4755 "Invalid maximized size after ShowWindow %s\n", wine_dbgstr_rect( &rc )); 4756 DestroyWindow(hwnd); 4757 flush_sequence(); 4758 4759 /* Test again, this time the NC_PAINT message */ 4760 hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_MAXIMIZE, 4761 100, 100, 200, 200, 0, 0, 0, NULL); 4762 ok (hwnd != 0, "Failed to create popup window\n"); 4763 SetWindowPos(hwnd, 0, 10, 10, 200, 200, SWP_NOZORDER | SWP_NOACTIVATE); 4764 flush_sequence(); 4765 ShowWindow(hwnd, SW_SHOWMAXIMIZED); 4766 ok_sequence(WmShowMaxPopupResizedSeq_todo, 4767 "ShowWindow(SW_SHOWMAXIMIZED):invisible maximized and resized popup TODO", TRUE); 4768 DestroyWindow(hwnd); 4769 flush_sequence(); 4770 4771 /* Test 2: 4772 * 1. Create invisible maximized popup window. 4773 * 2. Show it maximized. 4774 */ 4775 trace("calling CreateWindowExA( WS_MAXIMIZE ) for invisible maximized popup window\n"); 4776 hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_MAXIMIZE, 4777 100, 100, 200, 200, 0, 0, 0, NULL); 4778 ok (hwnd != 0, "Failed to create popup window\n"); 4779 ok(IsZoomed(hwnd), "window should be maximized\n"); 4780 ok_sequence(WmCreateInvisibleMaxPopupSeq, "CreateWindow(WS_MAXIMIZED):popup", FALSE); 4781 4782 trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible maximized popup window\n"); 4783 ShowWindow(hwnd, SW_SHOWMAXIMIZED); 4784 ok(IsZoomed(hwnd), "window should be maximized\n"); 4785 ok_sequence(WmShowMaxPopupSeq, "ShowWindow(SW_SHOWMAXIMIZED):invisible maximized popup", FALSE); 4786 DestroyWindow(hwnd); 4787 flush_sequence(); 4788 4789 /* Test 3: 4790 * 1. Create visible maximized popup window. 4791 */ 4792 trace("calling CreateWindowExA( WS_MAXIMIZE ) for maximized popup window\n"); 4793 hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_MAXIMIZE | WS_VISIBLE, 4794 100, 100, 200, 200, 0, 0, 0, NULL); 4795 ok (hwnd != 0, "Failed to create popup window\n"); 4796 ok(IsZoomed(hwnd), "window should be maximized\n"); 4797 ok_sequence(WmCreateMaxPopupSeq, "CreateWindow(WS_MAXIMIZED):popup", FALSE); 4798 DestroyWindow(hwnd); 4799 flush_sequence(); 4800 4801 /* Test 4: 4802 * 1. Create visible popup window. 4803 * 2. Maximize it. 4804 */ 4805 trace("calling CreateWindowExA( WS_VISIBLE ) for popup window\n"); 4806 hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_VISIBLE, 4807 100, 100, 200, 200, 0, 0, 0, NULL); 4808 ok (hwnd != 0, "Failed to create popup window\n"); 4809 ok(!IsZoomed(hwnd), "window should NOT be maximized\n"); 4810 ok_sequence(WmCreatePopupSeq, "CreateWindow(WS_VISIBLE):popup", FALSE); 4811 4812 trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for visible popup window\n"); 4813 ShowWindow(hwnd, SW_SHOWMAXIMIZED); 4814 ok(IsZoomed(hwnd), "window should be maximized\n"); 4815 ok_sequence(WmShowVisMaxPopupSeq, "ShowWindow(SW_SHOWMAXIMIZED):popup", FALSE); 4816 DestroyWindow(hwnd); 4817 flush_sequence(); 4818 } 4819 4820 static void test_sys_menu(void) 4821 { 4822 HWND hwnd; 4823 HMENU hmenu; 4824 UINT state; 4825 4826 hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, 4827 100, 100, 200, 200, 0, 0, 0, NULL); 4828 ok (hwnd != 0, "Failed to create overlapped window\n"); 4829 4830 flush_sequence(); 4831 4832 /* test existing window without CS_NOCLOSE style */ 4833 hmenu = GetSystemMenu(hwnd, FALSE); 4834 ok(hmenu != 0, "GetSystemMenu error %d\n", GetLastError()); 4835 4836 state = GetMenuState(hmenu, SC_CLOSE, MF_BYCOMMAND); 4837 ok(state != 0xffffffff, "wrong SC_CLOSE state %x\n", state); 4838 ok(!(state & (MF_DISABLED | MF_GRAYED)), "wrong SC_CLOSE state %x\n", state); 4839 4840 EnableMenuItem(hmenu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED); 4841 ok_sequence(WmEmptySeq, "WmEnableMenuItem", FALSE); 4842 4843 state = GetMenuState(hmenu, SC_CLOSE, MF_BYCOMMAND); 4844 ok(state != 0xffffffff, "wrong SC_CLOSE state %x\n", state); 4845 ok((state & (MF_DISABLED | MF_GRAYED)) == MF_GRAYED, "wrong SC_CLOSE state %x\n", state); 4846 4847 EnableMenuItem(hmenu, SC_CLOSE, 0); 4848 ok_sequence(WmEmptySeq, "WmEnableMenuItem", FALSE); 4849 4850 state = GetMenuState(hmenu, SC_CLOSE, MF_BYCOMMAND); 4851 ok(state != 0xffffffff, "wrong SC_CLOSE state %x\n", state); 4852 ok(!(state & (MF_DISABLED | MF_GRAYED)), "wrong SC_CLOSE state %x\n", state); 4853 4854 /* test whether removing WS_SYSMENU destroys a system menu */ 4855 SetWindowLongW(hwnd, GWL_STYLE, WS_POPUP); 4856 SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_FRAMECHANGED); 4857 flush_sequence(); 4858 hmenu = GetSystemMenu(hwnd, FALSE); 4859 ok(hmenu != 0, "GetSystemMenu error %d\n", GetLastError()); 4860 4861 DestroyWindow(hwnd); 4862 4863 /* test new window with CS_NOCLOSE style */ 4864 hwnd = CreateWindowExA(0, "NoCloseWindowClass", NULL, WS_OVERLAPPEDWINDOW, 4865 100, 100, 200, 200, 0, 0, 0, NULL); 4866 ok (hwnd != 0, "Failed to create overlapped window\n"); 4867 4868 hmenu = GetSystemMenu(hwnd, FALSE); 4869 ok(hmenu != 0, "GetSystemMenu error %d\n", GetLastError()); 4870 4871 state = GetMenuState(hmenu, SC_CLOSE, MF_BYCOMMAND); 4872 ok(state == 0xffffffff, "wrong SC_CLOSE state %x\n", state); 4873 4874 DestroyWindow(hwnd); 4875 4876 /* test new window without WS_SYSMENU style */ 4877 hwnd = CreateWindowExA(0, "NoCloseWindowClass", NULL, WS_OVERLAPPEDWINDOW & ~WS_SYSMENU, 4878 100, 100, 200, 200, 0, 0, 0, NULL); 4879 ok(hwnd != 0, "Failed to create overlapped window\n"); 4880 4881 hmenu = GetSystemMenu(hwnd, FALSE); 4882 ok(!hmenu, "GetSystemMenu error %d\n", GetLastError()); 4883 4884 DestroyWindow(hwnd); 4885 } 4886 4887 /* For shown WS_OVERLAPPEDWINDOW */ 4888 static const struct message WmSetIcon_1[] = { 4889 { WM_SETICON, sent }, 4890 { 0x00AE, sent|defwinproc|optional }, /* XP */ 4891 { WM_GETTEXT, sent|defwinproc|optional }, 4892 { WM_GETTEXT, sent|defwinproc|optional }, /* XP sends a duplicate */ 4893 { 0 } 4894 }; 4895 4896 /* For WS_POPUP and hidden WS_OVERLAPPEDWINDOW */ 4897 static const struct message WmSetIcon_2[] = { 4898 { WM_SETICON, sent }, 4899 { 0 } 4900 }; 4901 4902 /* Sending undocumented 0x3B message with wparam = 0x8000000b */ 4903 static const struct message WmInitEndSession[] = { 4904 { 0x003B, sent }, 4905 { WM_QUERYENDSESSION, sent|defwinproc|wparam|lparam, 0, ENDSESSION_LOGOFF }, 4906 { 0 } 4907 }; 4908 4909 /* Sending undocumented 0x3B message with wparam = 0x0000000b */ 4910 static const struct message WmInitEndSession_2[] = { 4911 { 0x003B, sent }, 4912 { WM_QUERYENDSESSION, sent|defwinproc|wparam|lparam, 0, 0 }, 4913 { 0 } 4914 }; 4915 4916 /* Sending undocumented 0x3B message with wparam = 0x80000008 */ 4917 static const struct message WmInitEndSession_3[] = { 4918 { 0x003B, sent }, 4919 { WM_ENDSESSION, sent|defwinproc|wparam|lparam, 0, ENDSESSION_LOGOFF }, 4920 { 0 } 4921 }; 4922 4923 /* Sending undocumented 0x3B message with wparam = 0x00000008 */ 4924 static const struct message WmInitEndSession_4[] = { 4925 { 0x003B, sent }, 4926 { WM_ENDSESSION, sent|defwinproc|wparam|lparam, 0, 0 }, 4927 { 0 } 4928 }; 4929 4930 /* Sending undocumented 0x3B message with wparam = 0x80000001 */ 4931 static const struct message WmInitEndSession_5[] = { 4932 { 0x003B, sent }, 4933 { WM_ENDSESSION, sent|defwinproc/*|wparam*/|lparam, 1, ENDSESSION_LOGOFF }, 4934 { 0 } 4935 }; 4936 4937 static const struct message WmOptionalPaint[] = { 4938 { WM_PAINT, sent|optional }, 4939 { WM_NCPAINT, sent|beginpaint|optional }, 4940 { WM_GETTEXT, sent|beginpaint|defwinproc|optional }, 4941 { WM_ERASEBKGND, sent|beginpaint|optional }, 4942 { 0 } 4943 }; 4944 4945 static const struct message WmZOrder[] = { 4946 { WM_WINDOWPOSCHANGING, sent|wparam, 0, 0 }, 4947 { WM_GETMINMAXINFO, sent|defwinproc|wparam, 0, 0 }, 4948 { HCBT_ACTIVATE, hook }, 4949 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 4950 { WM_WINDOWPOSCHANGING, sent|wparam, 3, 0 }, 4951 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOREDRAW|SWP_NOMOVE|SWP_NOSIZE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE, 0 }, 4952 { WM_GETTEXT, sent|optional }, 4953 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, 4954 { WM_ACTIVATEAPP, sent|wparam, 1, 0 }, 4955 { WM_NCACTIVATE, sent|lparam, 1, 0 }, 4956 { WM_GETTEXT, sent|defwinproc|optional }, 4957 { WM_GETTEXT, sent|defwinproc|optional }, 4958 { WM_ACTIVATE, sent|wparam|lparam, 1, 0 }, 4959 { HCBT_SETFOCUS, hook }, 4960 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 4961 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 4962 { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, 4963 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 4964 { WM_GETTEXT, sent|optional }, 4965 { WM_NCCALCSIZE, sent|optional }, 4966 { 0 } 4967 }; 4968 4969 static void CALLBACK apc_test_proc(ULONG_PTR param) 4970 { 4971 /* nothing */ 4972 } 4973 4974 static void test_MsgWaitForMultipleObjects(HWND hwnd) 4975 { 4976 DWORD ret; 4977 MSG msg; 4978 4979 ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE); 4980 ok(ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjects returned %x\n", ret); 4981 4982 PostMessageA(hwnd, WM_USER, 0, 0); 4983 4984 ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE); 4985 ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjects returned %x\n", ret); 4986 4987 ok(PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n"); 4988 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message); 4989 4990 ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE); 4991 ok(ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjects returned %x\n", ret); 4992 4993 PostMessageA(hwnd, WM_USER, 0, 0); 4994 4995 ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE); 4996 ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjects returned %x\n", ret); 4997 4998 ok(PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ), "PeekMessage should succeed\n"); 4999 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message); 5000 5001 /* shows QS_POSTMESSAGE flag is cleared in the PeekMessage call */ 5002 ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE); 5003 ok(ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjects returned %x\n", ret); 5004 5005 PostMessageA(hwnd, WM_USER, 0, 0); 5006 5007 /* new incoming message causes it to become signaled again */ 5008 ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE); 5009 ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjects returned %x\n", ret); 5010 5011 ok(PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n"); 5012 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message); 5013 ok(PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n"); 5014 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message); 5015 5016 /* MWMO_INPUTAVAILABLE should succeed even if the message was already seen */ 5017 PostMessageA( hwnd, WM_USER, 0, 0 ); 5018 ok(PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ), "PeekMessage should succeed\n"); 5019 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message); 5020 5021 ret = MsgWaitForMultipleObjectsEx( 0, NULL, 0, QS_POSTMESSAGE, MWMO_INPUTAVAILABLE ); 5022 ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjectsEx returned %x\n", ret); 5023 5024 ok(PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n"); 5025 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message); 5026 5027 /* without MWMO_ALERTABLE the result is never WAIT_IO_COMPLETION */ 5028 ret = QueueUserAPC( apc_test_proc, GetCurrentThread(), 0 ); 5029 ok(ret, "QueueUserAPC failed %u\n", GetLastError()); 5030 5031 ret = MsgWaitForMultipleObjectsEx( 0, NULL, 0, QS_POSTMESSAGE, 0 ); 5032 ok(ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjectsEx returned %x\n", ret); 5033 5034 /* but even with MWMO_ALERTABLE window events are preferred */ 5035 PostMessageA( hwnd, WM_USER, 0, 0 ); 5036 5037 ret = MsgWaitForMultipleObjectsEx( 0, NULL, 0, QS_POSTMESSAGE, MWMO_ALERTABLE ); 5038 ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjectsEx returned %x\n", ret); 5039 5040 ok(PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n"); 5041 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message); 5042 5043 /* the APC call is still queued */ 5044 ret = MsgWaitForMultipleObjectsEx( 0, NULL, 0, QS_POSTMESSAGE, MWMO_ALERTABLE ); 5045 ok(ret == WAIT_IO_COMPLETION, "MsgWaitForMultipleObjectsEx returned %x\n", ret); 5046 } 5047 5048 static void test_WM_DEVICECHANGE(HWND hwnd) 5049 { 5050 DWORD ret; 5051 MSG msg; 5052 int i; 5053 static const WPARAM wparams[] = {0, 5054 DBT_DEVNODES_CHANGED, 5055 DBT_QUERYCHANGECONFIG, 5056 DBT_CONFIGCHANGED, 5057 DBT_CONFIGCHANGECANCELED, 5058 DBT_NO_DISK_SPACE, 5059 DBT_LOW_DISK_SPACE, 5060 DBT_CONFIGMGPRIVATE, /* 0x7fff */ 5061 DBT_DEVICEARRIVAL, /* 0x8000 */ 5062 DBT_DEVICEQUERYREMOVE, 5063 DBT_DEVICEQUERYREMOVEFAILED, 5064 DBT_DEVICEREMOVEPENDING, 5065 DBT_DEVICEREMOVECOMPLETE, 5066 DBT_DEVICETYPESPECIFIC, 5067 DBT_CUSTOMEVENT}; 5068 5069 for (i = 0; i < sizeof(wparams)/sizeof(wparams[0]); i++) 5070 { 5071 SetLastError(0xdeadbeef); 5072 ret = PostMessageA(hwnd, WM_DEVICECHANGE, wparams[i], 0); 5073 if (wparams[i] & 0x8000) 5074 { 5075 ok(ret == FALSE, "PostMessage should returned %d\n", ret); 5076 ok(GetLastError() == ERROR_MESSAGE_SYNC_ONLY, "PostMessage error %08x\n", GetLastError()); 5077 } 5078 else 5079 { 5080 ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE); 5081 ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjects returned %x\n", ret); 5082 memset(&msg, 0, sizeof(msg)); 5083 ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "PeekMessage should succeed\n"); 5084 ok(msg.message == WM_DEVICECHANGE, "got %04x instead of WM_DEVICECHANGE\n", msg.message); 5085 } 5086 } 5087 } 5088 5089 static DWORD CALLBACK show_window_thread(LPVOID arg) 5090 { 5091 HWND hwnd = arg; 5092 5093 /* function will not return if ShowWindow(SW_HIDE) calls SendMessage() */ 5094 ok(ShowWindow(hwnd, SW_HIDE) == FALSE, "ShowWindow(SW_HIDE) expected FALSE\n"); 5095 5096 return 0; 5097 } 5098 5099 /* Helper function to easier test SetWindowPos messages */ 5100 #define test_msg_setpos( expected_list, flags, todo ) \ 5101 test_msg_setpos_( (expected_list), (flags), (todo), __FILE__, __LINE__) 5102 static void test_msg_setpos_(const struct message *expected_list, UINT flags, BOOL todo, const char *file, int line) 5103 { 5104 HWND hwnd; 5105 5106 flush_events(); 5107 flush_sequence(); 5108 hwnd = CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP, 5109 10, 10, 100, 100, NULL, 0, 0, NULL ); 5110 ok (hwnd != 0, "Failed to create popup window\n"); 5111 SetWindowPos(hwnd, NULL, 0, 0, 100, 100, flags); 5112 ok_sequence_(expected_list, "SetWindowPos:show_popup_first_show_window", todo, file, line); 5113 DestroyWindow(hwnd); 5114 } 5115 5116 /* test if we receive the right sequence of messages */ 5117 static void test_messages(void) 5118 { 5119 DWORD tid; 5120 HANDLE hthread; 5121 HWND hwnd, hparent, hchild; 5122 HWND hchild2, hbutton; 5123 HMENU hmenu; 5124 MSG msg; 5125 LRESULT res; 5126 POINT pos; 5127 BOOL ret; 5128 5129 flush_sequence(); 5130 5131 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW, 5132 100, 100, 200, 200, 0, 0, 0, NULL); 5133 ok (hwnd != 0, "Failed to create overlapped window\n"); 5134 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped", FALSE); 5135 5136 /* test ShowWindow(SW_HIDE) on a newly created invisible window */ 5137 ok( ShowWindow(hwnd, SW_HIDE) == FALSE, "ShowWindow: window was visible\n" ); 5138 ok_sequence(WmEmptySeq, "ShowWindow(SW_HIDE):overlapped, invisible", FALSE); 5139 5140 /* test WM_SETREDRAW on a not visible top level window */ 5141 test_WM_SETREDRAW(hwnd); 5142 5143 SetWindowPos(hwnd, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE); 5144 flush_events(); 5145 ok_sequence(WmSWP_ShowOverlappedSeq, "SetWindowPos:SWP_SHOWWINDOW:overlapped", FALSE); 5146 ok(IsWindowVisible(hwnd), "window should be visible at this point\n"); 5147 5148 ok(GetActiveWindow() == hwnd, "window should be active\n"); 5149 ok(GetFocus() == hwnd, "window should have input focus\n"); 5150 ShowWindow(hwnd, SW_HIDE); 5151 flush_events(); 5152 ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped", FALSE); 5153 5154 /* test ShowWindow(SW_HIDE) on a hidden window - single threaded */ 5155 ok(ShowWindow(hwnd, SW_HIDE) == FALSE, "ShowWindow(SW_HIDE) expected FALSE\n"); 5156 flush_events(); 5157 ok_sequence(WmEmptySeq, "ShowWindow(SW_HIDE):overlapped", FALSE); 5158 5159 /* test ShowWindow(SW_HIDE) on a hidden window - multi-threaded */ 5160 hthread = CreateThread(NULL, 0, show_window_thread, hwnd, 0, &tid); 5161 ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError()); 5162 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 5163 CloseHandle(hthread); 5164 flush_events(); 5165 ok_sequence(WmEmptySeq, "ShowWindow(SW_HIDE):overlapped", FALSE); 5166 5167 ShowWindow(hwnd, SW_SHOW); 5168 flush_events(); 5169 ok_sequence(WmShowOverlappedSeq, "ShowWindow(SW_SHOW):overlapped", TRUE); 5170 5171 ShowWindow(hwnd, SW_HIDE); 5172 flush_events(); 5173 ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped", FALSE); 5174 5175 ShowWindow(hwnd, SW_SHOWMAXIMIZED); 5176 flush_events(); 5177 ok_sequence(WmShowMaxOverlappedSeq, "ShowWindow(SW_SHOWMAXIMIZED):overlapped", TRUE); 5178 flush_sequence(); 5179 5180 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_MAXIMIZE) 5181 { 5182 ShowWindow(hwnd, SW_RESTORE); 5183 flush_events(); 5184 ok_sequence(WmShowRestoreMaxOverlappedSeq, "ShowWindow(SW_RESTORE):overlapped", TRUE); 5185 flush_sequence(); 5186 } 5187 5188 ShowWindow(hwnd, SW_MINIMIZE); 5189 flush_events(); 5190 ok_sequence(WmShowMinOverlappedSeq, "ShowWindow(SW_SHOWMINIMIZED):overlapped", TRUE); 5191 flush_sequence(); 5192 5193 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_MINIMIZE) 5194 { 5195 ShowWindow(hwnd, SW_RESTORE); 5196 flush_events(); 5197 ok_sequence(WmShowRestoreMinOverlappedSeq, "ShowWindow(SW_RESTORE):overlapped", TRUE); 5198 flush_sequence(); 5199 } 5200 5201 ShowWindow(hwnd, SW_SHOW); 5202 flush_events(); 5203 ok_sequence(WmOptionalPaint, "ShowWindow(SW_SHOW):overlapped already visible", FALSE); 5204 5205 SetWindowPos(hwnd, 0,0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE); 5206 ok_sequence(WmSWP_HideOverlappedSeq, "SetWindowPos:SWP_HIDEWINDOW:overlapped", FALSE); 5207 ok(!IsWindowVisible(hwnd), "window should not be visible at this point\n"); 5208 ok(GetActiveWindow() == hwnd, "window should still be active\n"); 5209 5210 /* test WM_SETREDRAW on a visible top level window */ 5211 ShowWindow(hwnd, SW_SHOW); 5212 flush_events(); 5213 test_WM_SETREDRAW(hwnd); 5214 5215 trace("testing scroll APIs on a visible top level window %p\n", hwnd); 5216 test_scroll_messages(hwnd); 5217 5218 /* test resizing and moving */ 5219 SetWindowPos( hwnd, 0, 0, 0, 300, 300, SWP_NOMOVE|SWP_NOACTIVATE ); 5220 ok_sequence(WmSWP_ResizeSeq, "SetWindowPos:Resize", FALSE ); 5221 flush_events(); 5222 flush_sequence(); 5223 SetWindowPos( hwnd, 0, 200, 200, 0, 0, SWP_NOSIZE|SWP_NOACTIVATE ); 5224 ok_sequence(WmSWP_MoveSeq, "SetWindowPos:Move", FALSE ); 5225 flush_events(); 5226 flush_sequence(); 5227 SetWindowPos( hwnd, 0, 200, 200, 250, 250, SWP_NOZORDER|SWP_NOACTIVATE ); 5228 ok_sequence(WmSWP_ResizeNoZOrder, "SetWindowPos:WmSWP_ResizeNoZOrder", FALSE ); 5229 flush_events(); 5230 flush_sequence(); 5231 5232 /* popups don't get WM_GETMINMAXINFO */ 5233 SetWindowLongW( hwnd, GWL_STYLE, WS_VISIBLE|WS_POPUP ); 5234 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_FRAMECHANGED); 5235 flush_sequence(); 5236 SetWindowPos( hwnd, 0, 0, 0, 200, 200, SWP_NOMOVE|SWP_NOACTIVATE ); 5237 ok_sequence(WmSWP_ResizePopupSeq, "SetWindowPos:ResizePopup", FALSE ); 5238 5239 DestroyWindow(hwnd); 5240 ok_sequence(WmDestroyOverlappedSeq, "DestroyWindow:overlapped", FALSE); 5241 5242 /* Test if windows are correctly drawn when first shown */ 5243 5244 /* Visible, redraw */ 5245 flush_events(); 5246 flush_sequence(); 5247 hwnd = CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP | WS_VISIBLE, 5248 10, 10, 100, 100, NULL, 0, 0, NULL ); 5249 ok (hwnd != 0, "Failed to create popup window\n"); 5250 RedrawWindow(hwnd, NULL, NULL, RDW_UPDATENOW); 5251 ok_sequence(WmShowPopupFirstDrawSeq_1, "RedrawWindow:show_popup_first_draw_visible", FALSE); 5252 DestroyWindow(hwnd); 5253 5254 /* Invisible, show, message */ 5255 flush_events(); 5256 flush_sequence(); 5257 hwnd = CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP, 5258 10, 10, 100, 100, NULL, 0, 0, NULL ); 5259 ok (hwnd != 0, "Failed to create popup window\n"); 5260 ShowWindow(hwnd, SW_SHOW); 5261 SendMessageW(hwnd, WM_PAINT, 0, 0); 5262 ok_sequence(WmShowPopupFirstDrawSeq_1, "RedrawWindow:show_popup_first_draw_show", FALSE); 5263 DestroyWindow(hwnd); 5264 5265 /* Invisible, show maximized, redraw */ 5266 flush_events(); 5267 flush_sequence(); 5268 hwnd = CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP, 5269 10, 10, 100, 100, NULL, 0, 0, NULL ); 5270 ok (hwnd != 0, "Failed to create popup window\n"); 5271 ShowWindow(hwnd, SW_SHOWMAXIMIZED); 5272 RedrawWindow(hwnd, NULL, NULL, RDW_UPDATENOW); 5273 ok_sequence(WmShowPopupFirstDrawSeq_2, "RedrawWindow:show_popup_first_draw_show_maximized", FALSE); 5274 DestroyWindow(hwnd); 5275 5276 /* Test SetWindowPos */ 5277 test_msg_setpos(WmFirstDrawSetWindowPosSeq1, SWP_SHOWWINDOW, FALSE); 5278 test_msg_setpos(WmFirstDrawSetWindowPosSeq2, 0, FALSE); 5279 test_msg_setpos(WmFirstDrawSetWindowPosSeq3, 5280 SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE | SWP_NOZORDER, FALSE); 5281 5282 test_msg_setpos(WmFirstDrawSetWindowPosSeq1, SWP_SHOWWINDOW | SWP_NOSIZE, FALSE); 5283 test_msg_setpos(WmFirstDrawSetWindowPosSeq4, SWP_SHOWWINDOW | SWP_NOMOVE, FALSE); 5284 test_msg_setpos(WmFirstDrawSetWindowPosSeq3, SWP_SHOWWINDOW | SWP_NOCLIENTSIZE, FALSE); 5285 test_msg_setpos(WmFirstDrawSetWindowPosSeq3, SWP_SHOWWINDOW | SWP_NOCLIENTMOVE, FALSE); 5286 test_msg_setpos(WmFirstDrawSetWindowPosSeq1, SWP_SHOWWINDOW | SWP_NOZORDER, FALSE); 5287 5288 test_msg_setpos(WmFirstDrawSetWindowPosSeq2, SWP_SHOWWINDOW | SWP_DEFERERASE, FALSE); 5289 test_msg_setpos(WmFirstDrawSetWindowPosSeq3, SWP_SHOWWINDOW | SWP_DEFERERASE | SWP_NOCLIENTMOVE, FALSE); 5290 test_msg_setpos(WmFirstDrawSetWindowPosSeq3, SWP_SHOWWINDOW | SWP_DEFERERASE | SWP_NOCLIENTSIZE, FALSE); 5291 test_msg_setpos(WmFirstDrawSetWindowPosSeq5, SWP_SHOWWINDOW | SWP_DEFERERASE | SWP_NOMOVE, FALSE); 5292 test_msg_setpos(WmFirstDrawSetWindowPosSeq2, SWP_SHOWWINDOW | SWP_DEFERERASE | SWP_NOSIZE, FALSE); 5293 test_msg_setpos(WmFirstDrawSetWindowPosSeq2, SWP_SHOWWINDOW | SWP_DEFERERASE | SWP_NOZORDER, FALSE); 5294 5295 test_msg_setpos(WmFirstDrawSetWindowPosSeq1, SWP_SHOWWINDOW | SWP_NOCOPYBITS, FALSE); 5296 test_msg_setpos(WmFirstDrawSetWindowPosSeq3, SWP_SHOWWINDOW | SWP_NOCOPYBITS | SWP_NOCLIENTMOVE, FALSE); 5297 test_msg_setpos(WmFirstDrawSetWindowPosSeq3, SWP_SHOWWINDOW | SWP_NOCOPYBITS | SWP_NOCLIENTSIZE, FALSE); 5298 test_msg_setpos(WmFirstDrawSetWindowPosSeq4, SWP_SHOWWINDOW | SWP_NOCOPYBITS | SWP_NOMOVE, FALSE); 5299 test_msg_setpos(WmFirstDrawSetWindowPosSeq1, SWP_SHOWWINDOW | SWP_NOCOPYBITS | SWP_NOSIZE, FALSE); 5300 test_msg_setpos(WmFirstDrawSetWindowPosSeq1, SWP_SHOWWINDOW | SWP_NOCOPYBITS | SWP_NOZORDER, FALSE); 5301 5302 test_msg_setpos(WmFirstDrawSetWindowPosSeq2, SWP_SHOWWINDOW | SWP_NOREDRAW, FALSE); 5303 test_msg_setpos(WmFirstDrawSetWindowPosSeq3, SWP_SHOWWINDOW | SWP_NOREDRAW | SWP_NOCLIENTMOVE, FALSE); 5304 test_msg_setpos(WmFirstDrawSetWindowPosSeq3, SWP_SHOWWINDOW | SWP_NOREDRAW | SWP_NOCLIENTSIZE, FALSE); 5305 test_msg_setpos(WmFirstDrawSetWindowPosSeq5, SWP_SHOWWINDOW | SWP_NOREDRAW | SWP_NOMOVE, FALSE); 5306 test_msg_setpos(WmFirstDrawSetWindowPosSeq2, SWP_SHOWWINDOW | SWP_NOREDRAW | SWP_NOSIZE, FALSE); 5307 test_msg_setpos(WmFirstDrawSetWindowPosSeq2, SWP_SHOWWINDOW | SWP_NOREDRAW | SWP_NOZORDER, FALSE); 5308 5309 /* Test SetWindowPos with child windows */ 5310 flush_events(); 5311 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 5312 100, 100, 200, 200, 0, 0, 0, NULL); 5313 ok (hparent != 0, "Failed to create parent window\n"); 5314 5315 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE, 5316 0, 0, 10, 10, hparent, 0, 0, NULL); 5317 ok (hchild != 0, "Failed to create child window\n"); 5318 flush_sequence(); 5319 SetWindowPos(hparent, NULL, 0, 0, 100, 100, SWP_SHOWWINDOW); 5320 ok_sequence(WmFirstDrawChildSeq1, /* Expect no messages for the child */ 5321 "SetWindowPos:show_popup_first_show_window_child1", FALSE); 5322 DestroyWindow(hchild); 5323 DestroyWindow(hparent); 5324 5325 flush_events(); 5326 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN, 5327 100, 100, 200, 200, 0, 0, 0, NULL); 5328 ok (hparent != 0, "Failed to create parent window\n"); 5329 5330 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE, 5331 0, 0, 10, 10, hparent, 0, 0, NULL); 5332 ok (hchild != 0, "Failed to create child window\n"); 5333 flush_sequence(); 5334 SetWindowPos(hparent, NULL, 0, 0, 100, 100, SWP_SHOWWINDOW); 5335 ok_sequence(WmFirstDrawChildSeq2, /* Expect child to be redrawn */ 5336 "SetWindowPos:show_popup_first_show_window_child2", FALSE); 5337 DestroyWindow(hchild); 5338 DestroyWindow(hparent); 5339 5340 /* Test message sequence for extreme position and size */ 5341 5342 flush_sequence(); 5343 hwnd = CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP | WS_VISIBLE, 5344 -10, -10, 10000, 10000, NULL, 0, 0, NULL ); 5345 ok (hwnd != 0, "Failed to create popup window\n"); 5346 ok_sequence(WmShowPopupExtremeLocationSeq, "RedrawWindow:show_popup_extreme_location", TRUE); 5347 DestroyWindow(hwnd); 5348 5349 5350 /* Test child windows */ 5351 5352 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 5353 100, 100, 200, 200, 0, 0, 0, NULL); 5354 ok (hparent != 0, "Failed to create parent window\n"); 5355 flush_sequence(); 5356 5357 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_MAXIMIZE, 5358 0, 0, 10, 10, hparent, 0, 0, NULL); 5359 ok (hchild != 0, "Failed to create child window\n"); 5360 ok_sequence(WmCreateMaximizedChildSeq, "CreateWindow:maximized child", FALSE); 5361 DestroyWindow(hchild); 5362 flush_sequence(); 5363 5364 /* visible child window with a caption */ 5365 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", 5366 WS_CHILD | WS_VISIBLE | WS_CAPTION, 5367 0, 0, 10, 10, hparent, 0, 0, NULL); 5368 ok (hchild != 0, "Failed to create child window\n"); 5369 ok_sequence(WmCreateVisibleChildSeq, "CreateWindow:visible child", FALSE); 5370 5371 trace("testing scroll APIs on a visible child window %p\n", hchild); 5372 test_scroll_messages(hchild); 5373 5374 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE); 5375 ok_sequence(WmShowChildSeq_4, "SetWindowPos(SWP_SHOWWINDOW):child with a caption", FALSE); 5376 5377 DestroyWindow(hchild); 5378 flush_sequence(); 5379 5380 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 5381 0, 0, 10, 10, hparent, 0, 0, NULL); 5382 ok (hchild != 0, "Failed to create child window\n"); 5383 ok_sequence(WmCreateChildSeq, "CreateWindow:child", FALSE); 5384 5385 hchild2 = CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_CHILD, 5386 100, 100, 50, 50, hparent, 0, 0, NULL); 5387 ok (hchild2 != 0, "Failed to create child2 window\n"); 5388 flush_sequence(); 5389 5390 hbutton = CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILD, 5391 0, 100, 50, 50, hchild, 0, 0, NULL); 5392 ok (hbutton != 0, "Failed to create button window\n"); 5393 5394 /* test WM_SETREDRAW on a not visible child window */ 5395 test_WM_SETREDRAW(hchild); 5396 5397 ShowWindow(hchild, SW_SHOW); 5398 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):child", FALSE); 5399 5400 /* check parent messages too */ 5401 log_all_parent_messages++; 5402 ShowWindow(hchild, SW_HIDE); 5403 ok_sequence(WmHideChildSeq2, "ShowWindow(SW_HIDE):child", FALSE); 5404 log_all_parent_messages--; 5405 5406 ShowWindow(hchild, SW_SHOW); 5407 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):child", FALSE); 5408 5409 ShowWindow(hchild, SW_HIDE); 5410 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):child", FALSE); 5411 5412 ShowWindow(hchild, SW_SHOW); 5413 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):child", FALSE); 5414 5415 /* test WM_SETREDRAW on a visible child window */ 5416 test_WM_SETREDRAW(hchild); 5417 5418 log_all_parent_messages++; 5419 MoveWindow(hchild, 10, 10, 20, 20, TRUE); 5420 ok_sequence(WmResizingChildWithMoveWindowSeq, "MoveWindow:child", FALSE); 5421 log_all_parent_messages--; 5422 5423 ShowWindow(hchild, SW_HIDE); 5424 flush_sequence(); 5425 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE); 5426 ok_sequence(WmShowChildSeq_2, "SetWindowPos:show_child_2", FALSE); 5427 5428 ShowWindow(hchild, SW_HIDE); 5429 flush_sequence(); 5430 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE); 5431 ok_sequence(WmShowChildSeq_3, "SetWindowPos:show_child_3", FALSE); 5432 5433 /* DestroyWindow sequence below expects that a child has focus */ 5434 SetFocus(hchild); 5435 flush_sequence(); 5436 5437 DestroyWindow(hchild); 5438 ok_sequence(WmDestroyChildSeq, "DestroyWindow:child", FALSE); 5439 DestroyWindow(hchild2); 5440 DestroyWindow(hbutton); 5441 5442 flush_sequence(); 5443 hchild = CreateWindowExA(0, "TestWindowClass", "Test Child Popup", WS_CHILD | WS_POPUP, 5444 0, 0, 100, 100, hparent, 0, 0, NULL); 5445 ok (hchild != 0, "Failed to create child popup window\n"); 5446 ok_sequence(WmCreateChildPopupSeq, "CreateWindow:child_popup", FALSE); 5447 DestroyWindow(hchild); 5448 5449 /* test what happens to a window which sets WS_VISIBLE in WM_CREATE */ 5450 flush_sequence(); 5451 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP, 5452 0, 0, 100, 100, hparent, 0, 0, NULL); 5453 ok (hchild != 0, "Failed to create popup window\n"); 5454 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup", FALSE); 5455 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 5456 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n"); 5457 flush_sequence(); 5458 ShowWindow(hchild, SW_SHOW); 5459 ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup", FALSE); 5460 flush_sequence(); 5461 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER); 5462 ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2", FALSE); 5463 flush_sequence(); 5464 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE); 5465 ok_sequence(WmShowVisiblePopupSeq_3, "SetWindowPos:show_visible_popup_3", FALSE); 5466 DestroyWindow(hchild); 5467 5468 /* this time add WS_VISIBLE for CreateWindowEx, but this fact actually 5469 * changes nothing in message sequences. 5470 */ 5471 flush_sequence(); 5472 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP | WS_VISIBLE, 5473 0, 0, 100, 100, hparent, 0, 0, NULL); 5474 ok (hchild != 0, "Failed to create popup window\n"); 5475 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup", FALSE); 5476 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 5477 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n"); 5478 flush_sequence(); 5479 ShowWindow(hchild, SW_SHOW); 5480 ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup", FALSE); 5481 flush_sequence(); 5482 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER); 5483 ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2", FALSE); 5484 DestroyWindow(hchild); 5485 5486 flush_sequence(); 5487 hwnd = CreateWindowExA(WS_EX_DLGMODALFRAME, "TestDialogClass", NULL, WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_DLGFRAME, 5488 0, 0, 100, 100, hparent, 0, 0, NULL); 5489 ok(hwnd != 0, "Failed to create custom dialog window\n"); 5490 ok_sequence(WmCreateCustomDialogSeq, "CreateCustomDialog", TRUE); 5491 5492 if(0) { 5493 trace("testing scroll APIs on a visible dialog %p\n", hwnd); 5494 test_scroll_messages(hwnd); 5495 } 5496 5497 flush_sequence(); 5498 5499 test_def_id = TRUE; 5500 SendMessageA(hwnd, WM_NULL, 0, 0); 5501 5502 flush_sequence(); 5503 after_end_dialog = TRUE; 5504 EndDialog( hwnd, 0 ); 5505 ok_sequence(WmEndCustomDialogSeq, "EndCustomDialog", FALSE); 5506 5507 DestroyWindow(hwnd); 5508 after_end_dialog = FALSE; 5509 test_def_id = FALSE; 5510 5511 ok(GetCursorPos(&pos), "GetCursorPos failed\n"); 5512 ok(SetCursorPos(109, 109), "SetCursorPos failed\n"); 5513 5514 hwnd = CreateWindowExA(0, "TestDialogClass", NULL, WS_POPUP|WS_CHILD, 5515 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL); 5516 ok(hwnd != 0, "Failed to create custom dialog window\n"); 5517 flush_sequence(); 5518 trace("call ShowWindow(%p, SW_SHOW)\n", hwnd); 5519 ShowWindow(hwnd, SW_SHOW); 5520 ok_sequence(WmShowCustomDialogSeq, "ShowCustomDialog", TRUE); 5521 5522 flush_events(); 5523 flush_sequence(); 5524 ret = DrawMenuBar(hwnd); 5525 ok(ret, "DrawMenuBar failed: %d\n", GetLastError()); 5526 flush_events(); 5527 ok_sequence(WmDrawMenuBarSeq, "DrawMenuBar", FALSE); 5528 ok(SetCursorPos(pos.x, pos.y), "SetCursorPos failed\n"); 5529 5530 DestroyWindow(hwnd); 5531 5532 hwnd = CreateWindowExA(0, "TestDialogClass", NULL, WS_CHILD|WS_VISIBLE, 5533 0, 0, 100, 100, hparent, 0, GetModuleHandleA(0), NULL); 5534 ok(hwnd != 0, "Failed to create custom dialog window\n"); 5535 flush_events(); 5536 flush_sequence(); 5537 ret = DrawMenuBar(hwnd); 5538 ok(ret, "DrawMenuBar failed: %d\n", GetLastError()); 5539 flush_events(); 5540 ok_sequence(WmEmptySeq, "DrawMenuBar for a child window", FALSE); 5541 5542 DestroyWindow(hwnd); 5543 5544 flush_sequence(); 5545 DialogBoxA( 0, "TEST_DIALOG", hparent, TestModalDlgProcA ); 5546 ok_sequence(WmModalDialogSeq, "ModalDialog", TRUE); 5547 5548 DestroyWindow(hparent); 5549 flush_sequence(); 5550 5551 /* Message sequence for SetMenu */ 5552 ok(!DrawMenuBar(hwnd), "DrawMenuBar should return FALSE for a destroyed window\n"); 5553 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "last error is %d\n", GetLastError()); 5554 ok_sequence(WmEmptySeq, "DrawMenuBar for a window without a menu", FALSE); 5555 5556 hmenu = CreateMenu(); 5557 ok (hmenu != 0, "Failed to create menu\n"); 5558 ok (InsertMenuA(hmenu, -1, MF_BYPOSITION, 0x1000, "foo"), "InsertMenu failed\n"); 5559 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW, 5560 100, 100, 200, 200, 0, hmenu, 0, NULL); 5561 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped", FALSE); 5562 ok (SetMenu(hwnd, 0), "SetMenu\n"); 5563 ok_sequence(WmSetMenuNonVisibleSizeChangeSeq, "SetMenu:NonVisibleSizeChange", FALSE); 5564 ok (SetMenu(hwnd, 0), "SetMenu\n"); 5565 ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq, "SetMenu:NonVisibleNoSizeChange", FALSE); 5566 ShowWindow(hwnd, SW_SHOW); 5567 UpdateWindow( hwnd ); 5568 flush_events(); 5569 flush_sequence(); 5570 ok (SetMenu(hwnd, 0), "SetMenu\n"); 5571 ok_sequence(WmSetMenuVisibleNoSizeChangeSeq, "SetMenu:VisibleNoSizeChange", FALSE); 5572 ok (SetMenu(hwnd, hmenu), "SetMenu\n"); 5573 ok_sequence(WmSetMenuVisibleSizeChangeSeq, "SetMenu:VisibleSizeChange", FALSE); 5574 5575 UpdateWindow( hwnd ); 5576 flush_events(); 5577 flush_sequence(); 5578 ok(DrawMenuBar(hwnd), "DrawMenuBar\n"); 5579 flush_events(); 5580 ok_sequence(WmDrawMenuBarSeq, "DrawMenuBar", FALSE); 5581 5582 DestroyWindow(hwnd); 5583 flush_sequence(); 5584 5585 /* Message sequence for EnableWindow */ 5586 hparent = CreateWindowExA(0, "TestWindowClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 5587 100, 100, 200, 200, 0, 0, 0, NULL); 5588 ok (hparent != 0, "Failed to create parent window\n"); 5589 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE, 5590 0, 0, 10, 10, hparent, 0, 0, NULL); 5591 ok (hchild != 0, "Failed to create child window\n"); 5592 5593 SetFocus(hchild); 5594 flush_events(); 5595 flush_sequence(); 5596 5597 EnableWindow(hparent, FALSE); 5598 ok_sequence(WmEnableWindowSeq_1, "EnableWindow(FALSE)", FALSE); 5599 5600 EnableWindow(hparent, FALSE); 5601 ok_sequence(WmEnableWindowSeq_2, "EnableWindow(FALSE)", FALSE); 5602 5603 EnableWindow(hparent, TRUE); 5604 ok_sequence(WmEnableWindowSeq_3, "EnableWindow(TRUE)", FALSE); 5605 5606 EnableWindow(hparent, TRUE); 5607 ok_sequence(WmEnableWindowSeq_4, "EnableWindow(TRUE)", FALSE); 5608 5609 flush_events(); 5610 flush_sequence(); 5611 5612 test_MsgWaitForMultipleObjects(hparent); 5613 test_WM_DEVICECHANGE(hparent); 5614 5615 /* the following test causes an exception in user.exe under win9x */ 5616 if (!PostMessageW( hparent, WM_USER, 0, 0 )) 5617 { 5618 DestroyWindow(hparent); 5619 flush_sequence(); 5620 return; 5621 } 5622 PostMessageW( hparent, WM_USER+1, 0, 0 ); 5623 /* PeekMessage(NULL) fails, but still removes the message */ 5624 SetLastError(0xdeadbeef); 5625 ok( !PeekMessageW( NULL, 0, 0, 0, PM_REMOVE ), "PeekMessage(NULL) should fail\n" ); 5626 ok( GetLastError() == ERROR_NOACCESS || /* Win2k */ 5627 GetLastError() == 0xdeadbeef, /* NT4 */ 5628 "last error is %d\n", GetLastError() ); 5629 ok( PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n" ); 5630 ok( msg.message == WM_USER+1, "got %x instead of WM_USER+1\n", msg.message ); 5631 5632 DestroyWindow(hchild); 5633 DestroyWindow(hparent); 5634 flush_sequence(); 5635 5636 /* Message sequences for WM_SETICON */ 5637 trace("testing WM_SETICON\n"); 5638 hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, 5639 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0, 5640 NULL, NULL, 0); 5641 ShowWindow(hwnd, SW_SHOW); 5642 UpdateWindow(hwnd); 5643 flush_events(); 5644 flush_sequence(); 5645 SendMessageA(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)LoadIconA(0, (LPCSTR)IDI_APPLICATION)); 5646 ok_sequence(WmSetIcon_1, "WM_SETICON for shown window with caption", FALSE); 5647 5648 ShowWindow(hwnd, SW_HIDE); 5649 flush_events(); 5650 flush_sequence(); 5651 SendMessageA(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)LoadIconA(0, (LPCSTR)IDI_APPLICATION)); 5652 ok_sequence(WmSetIcon_2, "WM_SETICON for hidden window with caption", FALSE); 5653 DestroyWindow(hwnd); 5654 flush_sequence(); 5655 5656 hwnd = CreateWindowExA(0, "TestPopupClass", NULL, WS_POPUP, 5657 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0, 5658 NULL, NULL, 0); 5659 ShowWindow(hwnd, SW_SHOW); 5660 UpdateWindow(hwnd); 5661 flush_events(); 5662 flush_sequence(); 5663 SendMessageA(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)LoadIconA(0, (LPCSTR)IDI_APPLICATION)); 5664 ok_sequence(WmSetIcon_2, "WM_SETICON for shown window without caption", FALSE); 5665 5666 ShowWindow(hwnd, SW_HIDE); 5667 flush_events(); 5668 flush_sequence(); 5669 SendMessageA(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)LoadIconA(0, (LPCSTR)IDI_APPLICATION)); 5670 ok_sequence(WmSetIcon_2, "WM_SETICON for hidden window without caption", FALSE); 5671 5672 flush_sequence(); 5673 res = SendMessageA(hwnd, 0x3B, 0x8000000b, 0); 5674 if (!res) 5675 { 5676 todo_wine win_skip( "Message 0x3b not supported\n" ); 5677 goto done; 5678 } 5679 ok_sequence(WmInitEndSession, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x8000000b", TRUE); 5680 ok(res == 1, "SendMessage(hwnd, 0x3B, 0x8000000b, 0) should have returned 1 instead of %ld\n", res); 5681 res = SendMessageA(hwnd, 0x3B, 0x0000000b, 0); 5682 ok_sequence(WmInitEndSession_2, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x0000000b", TRUE); 5683 ok(res == 1, "SendMessage(hwnd, 0x3B, 0x0000000b, 0) should have returned 1 instead of %ld\n", res); 5684 res = SendMessageA(hwnd, 0x3B, 0x0000000f, 0); 5685 ok_sequence(WmInitEndSession_2, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x0000000f", TRUE); 5686 ok(res == 1, "SendMessage(hwnd, 0x3B, 0x0000000f, 0) should have returned 1 instead of %ld\n", res); 5687 5688 flush_sequence(); 5689 res = SendMessageA(hwnd, 0x3B, 0x80000008, 0); 5690 ok_sequence(WmInitEndSession_3, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000008", TRUE); 5691 ok(res == 2, "SendMessage(hwnd, 0x3B, 0x80000008, 0) should have returned 2 instead of %ld\n", res); 5692 res = SendMessageA(hwnd, 0x3B, 0x00000008, 0); 5693 ok_sequence(WmInitEndSession_4, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x00000008", TRUE); 5694 ok(res == 2, "SendMessage(hwnd, 0x3B, 0x00000008, 0) should have returned 2 instead of %ld\n", res); 5695 5696 res = SendMessageA(hwnd, 0x3B, 0x80000004, 0); 5697 ok_sequence(WmInitEndSession_3, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000004", TRUE); 5698 ok(res == 2, "SendMessage(hwnd, 0x3B, 0x80000004, 0) should have returned 2 instead of %ld\n", res); 5699 5700 res = SendMessageA(hwnd, 0x3B, 0x80000001, 0); 5701 ok_sequence(WmInitEndSession_5, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000001", TRUE); 5702 ok(res == 2, "SendMessage(hwnd, 0x3B, 0x80000001, 0) should have returned 2 instead of %ld\n", res); 5703 5704 done: 5705 DestroyWindow(hwnd); 5706 flush_sequence(); 5707 } 5708 5709 static void test_setwindowpos(void) 5710 { 5711 HWND hwnd; 5712 RECT rc; 5713 LRESULT res; 5714 const INT winX = 100; 5715 const INT winY = 100; 5716 const INT sysX = GetSystemMetrics(SM_CXMINTRACK); 5717 5718 hwnd = CreateWindowExA(0, "TestWindowClass", NULL, 0, 5719 0, 0, winX, winY, 0, 5720 NULL, NULL, 0); 5721 5722 GetWindowRect(hwnd, &rc); 5723 expect(sysX, rc.right); 5724 expect(winY, rc.bottom); 5725 5726 flush_events(); 5727 flush_sequence(); 5728 res = SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, winX, winY, 0); 5729 ok_sequence(WmZOrder, "Z-Order", TRUE); 5730 ok(res == TRUE, "SetWindowPos expected TRUE, got %ld\n", res); 5731 5732 GetWindowRect(hwnd, &rc); 5733 expect(sysX, rc.right); 5734 expect(winY, rc.bottom); 5735 DestroyWindow(hwnd); 5736 } 5737 5738 static void invisible_parent_tests(void) 5739 { 5740 HWND hparent, hchild; 5741 5742 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW, 5743 100, 100, 200, 200, 0, 0, 0, NULL); 5744 ok (hparent != 0, "Failed to create parent window\n"); 5745 flush_sequence(); 5746 5747 /* test showing child with hidden parent */ 5748 5749 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 5750 0, 0, 10, 10, hparent, 0, 0, NULL); 5751 ok (hchild != 0, "Failed to create child window\n"); 5752 ok_sequence(WmCreateChildSeq, "CreateWindow:child", FALSE); 5753 5754 ShowWindow( hchild, SW_MINIMIZE ); 5755 ok_sequence(WmShowChildInvisibleParentSeq_1, "ShowWindow(SW_MINIMIZE) child with invisible parent", FALSE); 5756 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 5757 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n"); 5758 5759 /* repeat */ 5760 flush_events(); 5761 flush_sequence(); 5762 ShowWindow( hchild, SW_MINIMIZE ); 5763 ok_sequence(WmShowChildInvisibleParentSeq_1r, "ShowWindow(SW_MINIMIZE) child with invisible parent", FALSE); 5764 5765 DestroyWindow(hchild); 5766 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 5767 0, 0, 10, 10, hparent, 0, 0, NULL); 5768 flush_sequence(); 5769 5770 ShowWindow( hchild, SW_MAXIMIZE ); 5771 ok_sequence(WmShowChildInvisibleParentSeq_2, "ShowWindow(SW_MAXIMIZE) child with invisible parent", FALSE); 5772 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 5773 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n"); 5774 5775 /* repeat */ 5776 flush_events(); 5777 flush_sequence(); 5778 ShowWindow( hchild, SW_MAXIMIZE ); 5779 ok_sequence(WmShowChildInvisibleParentSeq_2r, "ShowWindow(SW_MAXIMIZE) child with invisible parent", FALSE); 5780 5781 DestroyWindow(hchild); 5782 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 5783 0, 0, 10, 10, hparent, 0, 0, NULL); 5784 flush_sequence(); 5785 5786 ShowWindow( hchild, SW_RESTORE ); 5787 ok_sequence(WmShowChildInvisibleParentSeq_5, "ShowWindow(SW_RESTORE) child with invisible parent", FALSE); 5788 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 5789 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n"); 5790 5791 DestroyWindow(hchild); 5792 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 5793 0, 0, 10, 10, hparent, 0, 0, NULL); 5794 flush_sequence(); 5795 5796 ShowWindow( hchild, SW_SHOWMINIMIZED ); 5797 ok_sequence(WmShowChildInvisibleParentSeq_3, "ShowWindow(SW_SHOWMINIMIZED) child with invisible parent", FALSE); 5798 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 5799 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n"); 5800 5801 /* repeat */ 5802 flush_events(); 5803 flush_sequence(); 5804 ShowWindow( hchild, SW_SHOWMINIMIZED ); 5805 ok_sequence(WmShowChildInvisibleParentSeq_3r, "ShowWindow(SW_SHOWMINIMIZED) child with invisible parent", FALSE); 5806 5807 DestroyWindow(hchild); 5808 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 5809 0, 0, 10, 10, hparent, 0, 0, NULL); 5810 flush_sequence(); 5811 5812 /* same as ShowWindow( hchild, SW_MAXIMIZE ); */ 5813 ShowWindow( hchild, SW_SHOWMAXIMIZED ); 5814 ok_sequence(WmShowChildInvisibleParentSeq_2, "ShowWindow(SW_SHOWMAXIMIZED) child with invisible parent", FALSE); 5815 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 5816 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n"); 5817 5818 DestroyWindow(hchild); 5819 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 5820 0, 0, 10, 10, hparent, 0, 0, NULL); 5821 flush_sequence(); 5822 5823 ShowWindow( hchild, SW_SHOWMINNOACTIVE ); 5824 ok_sequence(WmShowChildInvisibleParentSeq_4, "ShowWindow(SW_SHOWMINNOACTIVE) child with invisible parent", FALSE); 5825 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 5826 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n"); 5827 5828 /* repeat */ 5829 flush_events(); 5830 flush_sequence(); 5831 ShowWindow( hchild, SW_SHOWMINNOACTIVE ); 5832 ok_sequence(WmShowChildInvisibleParentSeq_4r, "ShowWindow(SW_SHOWMINNOACTIVE) child with invisible parent", FALSE); 5833 5834 DestroyWindow(hchild); 5835 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 5836 0, 0, 10, 10, hparent, 0, 0, NULL); 5837 flush_sequence(); 5838 5839 /* FIXME: looks like XP SP2 doesn't know about SW_FORCEMINIMIZE at all */ 5840 ShowWindow( hchild, SW_FORCEMINIMIZE ); 5841 ok_sequence(WmEmptySeq, "ShowWindow(SW_FORCEMINIMIZE) child with invisible parent", TRUE); 5842 todo_wine { 5843 ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should be not set\n"); 5844 } 5845 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n"); 5846 5847 DestroyWindow(hchild); 5848 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 5849 0, 0, 10, 10, hparent, 0, 0, NULL); 5850 flush_sequence(); 5851 5852 ShowWindow( hchild, SW_SHOWNA ); 5853 ok_sequence(WmShowChildInvisibleParentSeq_5, "ShowWindow(SW_SHOWNA) child with invisible parent", FALSE); 5854 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 5855 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n"); 5856 5857 /* repeat */ 5858 flush_events(); 5859 flush_sequence(); 5860 ShowWindow( hchild, SW_SHOWNA ); 5861 ok_sequence(WmShowChildInvisibleParentSeq_5, "ShowWindow(SW_SHOWNA) child with invisible parent", FALSE); 5862 5863 DestroyWindow(hchild); 5864 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 5865 0, 0, 10, 10, hparent, 0, 0, NULL); 5866 flush_sequence(); 5867 5868 ShowWindow( hchild, SW_SHOW ); 5869 ok_sequence(WmShowChildInvisibleParentSeq_5, "ShowWindow(SW_SHOW) child with invisible parent", FALSE); 5870 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 5871 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n"); 5872 5873 /* repeat */ 5874 flush_events(); 5875 flush_sequence(); 5876 ShowWindow( hchild, SW_SHOW ); 5877 ok_sequence(WmEmptySeq, "ShowWindow(SW_SHOW) child with invisible parent", FALSE); 5878 5879 ShowWindow( hchild, SW_HIDE ); 5880 ok_sequence(WmHideChildInvisibleParentSeq, "ShowWindow:hide child with invisible parent", FALSE); 5881 ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should be not set\n"); 5882 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n"); 5883 5884 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER); 5885 ok_sequence(WmShowChildInvisibleParentSeq_6, "SetWindowPos:show child with invisible parent", FALSE); 5886 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 5887 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n"); 5888 5889 SetWindowPos(hchild, 0,0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER); 5890 ok_sequence(WmHideChildInvisibleParentSeq_2, "SetWindowPos:hide child with invisible parent", FALSE); 5891 ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should not be set\n"); 5892 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n"); 5893 5894 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER); 5895 flush_sequence(); 5896 DestroyWindow(hchild); 5897 ok_sequence(WmDestroyInvisibleChildSeq, "DestroyInvisibleChildSeq", FALSE); 5898 5899 DestroyWindow(hparent); 5900 flush_sequence(); 5901 } 5902 5903 /****************** button message test *************************/ 5904 #define ID_BUTTON 0x000e 5905 5906 static const struct message WmSetFocusButtonSeq[] = 5907 { 5908 { HCBT_SETFOCUS, hook }, 5909 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 5910 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 5911 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 5912 { WM_SETFOCUS, sent|wparam, 0 }, 5913 { WM_CTLCOLORBTN, sent|parent }, 5914 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_SETFOCUS) }, 5915 { WM_APP, sent|wparam|lparam, 0, 0 }, 5916 { 0 } 5917 }; 5918 static const struct message WmKillFocusButtonSeq[] = 5919 { 5920 { HCBT_SETFOCUS, hook }, 5921 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 5922 { WM_KILLFOCUS, sent|wparam, 0 }, 5923 { WM_CTLCOLORBTN, sent|parent }, 5924 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_KILLFOCUS) }, 5925 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 5926 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, 5927 { WM_APP, sent|wparam|lparam, 0, 0 }, 5928 { WM_PAINT, sent }, 5929 { WM_CTLCOLORBTN, sent|parent }, 5930 { 0 } 5931 }; 5932 static const struct message WmSetFocusStaticSeq[] = 5933 { 5934 { HCBT_SETFOCUS, hook }, 5935 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 5936 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 5937 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 5938 { WM_SETFOCUS, sent|wparam, 0 }, 5939 { WM_CTLCOLORSTATIC, sent|parent }, 5940 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_SETFOCUS) }, 5941 { WM_COMMAND, sent|wparam|parent|optional, MAKEWPARAM(ID_BUTTON, BN_CLICKED) }, /* radio button */ 5942 { WM_APP, sent|wparam|lparam, 0, 0 }, 5943 { 0 } 5944 }; 5945 static const struct message WmKillFocusStaticSeq[] = 5946 { 5947 { HCBT_SETFOCUS, hook }, 5948 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 5949 { WM_KILLFOCUS, sent|wparam, 0 }, 5950 { WM_CTLCOLORSTATIC, sent|parent }, 5951 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_KILLFOCUS) }, 5952 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 5953 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, 5954 { WM_APP, sent|wparam|lparam, 0, 0 }, 5955 { WM_PAINT, sent }, 5956 { WM_CTLCOLORSTATIC, sent|parent }, 5957 { 0 } 5958 }; 5959 static const struct message WmSetFocusOwnerdrawSeq[] = 5960 { 5961 { HCBT_SETFOCUS, hook }, 5962 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 5963 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 5964 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 5965 { WM_SETFOCUS, sent|wparam, 0 }, 5966 { WM_CTLCOLORBTN, sent|parent }, 5967 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x001040e4 }, 5968 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_SETFOCUS) }, 5969 { WM_APP, sent|wparam|lparam, 0, 0 }, 5970 { 0 } 5971 }; 5972 static const struct message WmKillFocusOwnerdrawSeq[] = 5973 { 5974 { HCBT_SETFOCUS, hook }, 5975 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 5976 { WM_KILLFOCUS, sent|wparam, 0 }, 5977 { WM_CTLCOLORBTN, sent|parent }, 5978 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x000040e4 }, 5979 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_KILLFOCUS) }, 5980 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 5981 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, 5982 { WM_APP, sent|wparam|lparam, 0, 0 }, 5983 { WM_PAINT, sent }, 5984 { WM_CTLCOLORBTN, sent|parent }, 5985 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x000010e4 }, 5986 { 0 } 5987 }; 5988 static const struct message WmLButtonDownSeq[] = 5989 { 5990 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 }, 5991 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, 5992 { HCBT_SETFOCUS, hook }, 5993 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 5994 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 5995 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 5996 { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, 5997 { WM_CTLCOLORBTN, sent|defwinproc }, 5998 { BM_SETSTATE, sent|wparam|defwinproc, TRUE }, 5999 { WM_CTLCOLORBTN, sent|defwinproc }, 6000 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6001 { 0 } 6002 }; 6003 static const struct message WmLButtonDownStaticSeq[] = 6004 { 6005 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 }, 6006 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, 6007 { HCBT_SETFOCUS, hook }, 6008 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 6009 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 6010 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6011 { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, 6012 { WM_CTLCOLORSTATIC, sent|defwinproc }, 6013 { BM_SETSTATE, sent|wparam|defwinproc, TRUE }, 6014 { WM_CTLCOLORSTATIC, sent|defwinproc }, 6015 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6016 { 0 } 6017 }; 6018 static const struct message WmLButtonUpSeq[] = 6019 { 6020 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 }, 6021 { BM_SETSTATE, sent|wparam|defwinproc, FALSE }, 6022 { WM_CTLCOLORBTN, sent|defwinproc }, 6023 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6024 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, 6025 { WM_CAPTURECHANGED, sent|wparam|defwinproc, 0 }, 6026 { 0 } 6027 }; 6028 static const struct message WmLButtonUpStaticSeq[] = 6029 { 6030 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 }, 6031 { BM_SETSTATE, sent|wparam|defwinproc, FALSE }, 6032 { WM_CTLCOLORSTATIC, sent|defwinproc }, 6033 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6034 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, 6035 { WM_CAPTURECHANGED, sent|wparam|defwinproc, 0 }, 6036 { 0 } 6037 }; 6038 static const struct message WmLButtonUpAutoSeq[] = 6039 { 6040 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 }, 6041 { BM_SETSTATE, sent|wparam|defwinproc, FALSE }, 6042 { WM_CTLCOLORSTATIC, sent|defwinproc }, 6043 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6044 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, 6045 { BM_SETCHECK, sent|defwinproc }, 6046 { WM_CTLCOLORSTATIC, sent|defwinproc, 0, 0 }, 6047 { WM_CAPTURECHANGED, sent|wparam|defwinproc, 0 }, 6048 { 0 } 6049 }; 6050 static const struct message WmLButtonUpBrokenSeq[] = 6051 { 6052 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 }, 6053 { 0 } 6054 }; 6055 static const struct message WmSetFontButtonSeq[] = 6056 { 6057 { WM_SETFONT, sent }, 6058 { WM_PAINT, sent }, 6059 { WM_ERASEBKGND, sent|defwinproc|optional }, 6060 { WM_CTLCOLORBTN, sent|defwinproc }, 6061 { WM_CTLCOLORBTN, sent|defwinproc|optional }, /* FIXME: Wine sends it twice for BS_OWNERDRAW */ 6062 { 0 } 6063 }; 6064 static const struct message WmSetFontStaticSeq[] = 6065 { 6066 { WM_SETFONT, sent }, 6067 { WM_PAINT, sent }, 6068 { WM_ERASEBKGND, sent|defwinproc|optional }, 6069 { WM_CTLCOLORSTATIC, sent|defwinproc }, 6070 { 0 } 6071 }; 6072 static const struct message WmSetTextButtonSeq[] = 6073 { 6074 { WM_SETTEXT, sent }, 6075 { WM_CTLCOLORBTN, sent|parent }, 6076 { WM_CTLCOLORBTN, sent|parent }, 6077 { WM_COMMAND, sent|parent|optional }, 6078 { WM_DRAWITEM, sent|parent|optional }, 6079 { 0 } 6080 }; 6081 static const struct message WmSetTextStaticSeq[] = 6082 { 6083 { WM_SETTEXT, sent }, 6084 { WM_CTLCOLORSTATIC, sent|parent }, 6085 { WM_CTLCOLORSTATIC, sent|parent }, 6086 { 0 } 6087 }; 6088 static const struct message WmSetTextGroupSeq[] = 6089 { 6090 { WM_SETTEXT, sent }, 6091 { WM_CTLCOLORSTATIC, sent|parent }, 6092 { WM_CTLCOLORSTATIC, sent|parent|optional }, /* FIXME: Missing in Wine */ 6093 { WM_CTLCOLORSTATIC, sent|parent|optional }, /* FIXME: Missing in Wine */ 6094 { 0 } 6095 }; 6096 static const struct message WmSetTextInvisibleSeq[] = 6097 { 6098 { WM_SETTEXT, sent }, 6099 { 0 } 6100 }; 6101 static const struct message WmSetStyleButtonSeq[] = 6102 { 6103 { BM_SETSTYLE, sent }, 6104 { WM_APP, sent|wparam|lparam, 0, 0 }, 6105 { WM_PAINT, sent }, 6106 { WM_NCPAINT, sent|defwinproc|optional }, /* FIXME: Wine sends it */ 6107 { WM_ERASEBKGND, sent|defwinproc|optional }, /* Win9x doesn't send it */ 6108 { WM_CTLCOLORBTN, sent|parent }, 6109 { 0 } 6110 }; 6111 static const struct message WmSetStyleStaticSeq[] = 6112 { 6113 { BM_SETSTYLE, sent }, 6114 { WM_APP, sent|wparam|lparam, 0, 0 }, 6115 { WM_PAINT, sent }, 6116 { WM_NCPAINT, sent|defwinproc|optional }, /* FIXME: Wine sends it */ 6117 { WM_ERASEBKGND, sent|defwinproc|optional }, /* Win9x doesn't send it */ 6118 { WM_CTLCOLORSTATIC, sent|parent }, 6119 { 0 } 6120 }; 6121 static const struct message WmSetStyleUserSeq[] = 6122 { 6123 { BM_SETSTYLE, sent }, 6124 { WM_APP, sent|wparam|lparam, 0, 0 }, 6125 { WM_PAINT, sent }, 6126 { WM_NCPAINT, sent|defwinproc|optional }, /* FIXME: Wine sends it */ 6127 { WM_ERASEBKGND, sent|defwinproc|optional }, /* Win9x doesn't send it */ 6128 { WM_CTLCOLORBTN, sent|parent }, 6129 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_PAINT) }, 6130 { 0 } 6131 }; 6132 static const struct message WmSetStyleOwnerdrawSeq[] = 6133 { 6134 { BM_SETSTYLE, sent }, 6135 { WM_APP, sent|wparam|lparam, 0, 0 }, 6136 { WM_PAINT, sent }, 6137 { WM_NCPAINT, sent|optional }, /* FIXME: Wine sends it */ 6138 { WM_ERASEBKGND, sent|defwinproc|optional }, /* Win9x doesn't send it */ 6139 { WM_CTLCOLORBTN, sent|parent }, 6140 { WM_CTLCOLORBTN, sent|parent|optional }, /* Win9x doesn't send it */ 6141 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x000010e4 }, 6142 { 0 } 6143 }; 6144 static const struct message WmSetStateButtonSeq[] = 6145 { 6146 { BM_SETSTATE, sent }, 6147 { WM_CTLCOLORBTN, sent|parent }, 6148 { WM_APP, sent|wparam|lparam, 0, 0 }, 6149 { 0 } 6150 }; 6151 static const struct message WmSetStateStaticSeq[] = 6152 { 6153 { BM_SETSTATE, sent }, 6154 { WM_CTLCOLORSTATIC, sent|parent }, 6155 { WM_APP, sent|wparam|lparam, 0, 0 }, 6156 { 0 } 6157 }; 6158 static const struct message WmSetStateUserSeq[] = 6159 { 6160 { BM_SETSTATE, sent }, 6161 { WM_CTLCOLORBTN, sent|parent }, 6162 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_HILITE) }, 6163 { WM_APP, sent|wparam|lparam, 0, 0 }, 6164 { 0 } 6165 }; 6166 static const struct message WmSetStateOwnerdrawSeq[] = 6167 { 6168 { BM_SETSTATE, sent }, 6169 { WM_CTLCOLORBTN, sent|parent }, 6170 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x000120e4 }, 6171 { WM_APP, sent|wparam|lparam, 0, 0 }, 6172 { 0 } 6173 }; 6174 static const struct message WmClearStateButtonSeq[] = 6175 { 6176 { BM_SETSTATE, sent }, 6177 { WM_CTLCOLORBTN, sent|parent }, 6178 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_UNHILITE) }, 6179 { WM_APP, sent|wparam|lparam, 0, 0 }, 6180 { 0 } 6181 }; 6182 static const struct message WmDisableButtonSeq[] = 6183 { 6184 { WM_LBUTTONDOWN, sent }, 6185 { BM_SETSTATE, sent|defwinproc }, 6186 { WM_CTLCOLORSTATIC, sent|defwinproc|optional }, 6187 { WM_CTLCOLORBTN, sent|optional }, 6188 { WM_LBUTTONUP, sent }, 6189 { BM_SETSTATE, sent|defwinproc }, 6190 { WM_CTLCOLORBTN, sent|defwinproc|optional }, 6191 { WM_CTLCOLORSTATIC, sent|defwinproc|optional }, 6192 { BM_SETCHECK, sent|defwinproc|optional }, 6193 { WM_CTLCOLORBTN, sent|optional }, 6194 { WM_CTLCOLORSTATIC, sent|defwinproc|optional }, 6195 { WM_CAPTURECHANGED, sent|defwinproc }, 6196 { WM_COMMAND, sent }, 6197 { 0 } 6198 }; 6199 static const struct message WmClearStateOwnerdrawSeq[] = 6200 { 6201 { BM_SETSTATE, sent }, 6202 { WM_CTLCOLORBTN, sent|parent }, 6203 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x000020e4 }, 6204 { WM_APP, sent|wparam|lparam, 0, 0 }, 6205 { 0 } 6206 }; 6207 static const struct message WmSetCheckIgnoredSeq[] = 6208 { 6209 { BM_SETCHECK, sent }, 6210 { WM_APP, sent|wparam|lparam, 0, 0 }, 6211 { 0 } 6212 }; 6213 static const struct message WmSetCheckStaticSeq[] = 6214 { 6215 { BM_SETCHECK, sent }, 6216 { WM_CTLCOLORSTATIC, sent|parent }, 6217 { WM_APP, sent|wparam|lparam, 0, 0 }, 6218 { 0 } 6219 }; 6220 6221 static WNDPROC old_button_proc; 6222 6223 static LRESULT CALLBACK button_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 6224 { 6225 static LONG defwndproc_counter = 0; 6226 LRESULT ret; 6227 struct recvd_message msg; 6228 6229 if (ignore_message( message )) return 0; 6230 6231 switch (message) 6232 { 6233 case WM_SYNCPAINT: 6234 break; 6235 case BM_SETSTATE: 6236 if (GetCapture()) 6237 ok(GetCapture() == hwnd, "GetCapture() = %p\n", GetCapture()); 6238 6239 lParam = (ULONG_PTR)GetMenu(hwnd); 6240 goto log_it; 6241 6242 case WM_GETDLGCODE: 6243 if (lParam) 6244 { 6245 MSG *msg = (MSG *)lParam; 6246 lParam = MAKELPARAM(msg->message, msg->wParam); 6247 } 6248 wParam = (ULONG_PTR)GetMenu(hwnd); 6249 goto log_it; 6250 6251 case BM_SETCHECK: 6252 case BM_GETCHECK: 6253 lParam = (ULONG_PTR)GetMenu(hwnd); 6254 /* fall through */ 6255 log_it: 6256 default: 6257 msg.hwnd = hwnd; 6258 msg.message = message; 6259 msg.flags = sent|wparam|lparam; 6260 if (defwndproc_counter) msg.flags |= defwinproc; 6261 msg.wParam = wParam; 6262 msg.lParam = lParam; 6263 msg.descr = "button"; 6264 add_message(&msg); 6265 } 6266 6267 defwndproc_counter++; 6268 ret = CallWindowProcA(old_button_proc, hwnd, message, wParam, lParam); 6269 defwndproc_counter--; 6270 6271 return ret; 6272 } 6273 6274 static void subclass_button(void) 6275 { 6276 WNDCLASSA cls; 6277 6278 if (!GetClassInfoA(0, "button", &cls)) assert(0); 6279 6280 old_button_proc = cls.lpfnWndProc; 6281 6282 cls.hInstance = GetModuleHandleA(NULL); 6283 cls.lpfnWndProc = button_hook_proc; 6284 cls.lpszClassName = "my_button_class"; 6285 UnregisterClassA(cls.lpszClassName, cls.hInstance); 6286 if (!RegisterClassA(&cls)) assert(0); 6287 } 6288 6289 static void test_button_messages(void) 6290 { 6291 static const struct 6292 { 6293 DWORD style; 6294 DWORD dlg_code; 6295 const struct message *setfocus; 6296 const struct message *killfocus; 6297 const struct message *setstyle; 6298 const struct message *setstate; 6299 const struct message *clearstate; 6300 const struct message *setcheck; 6301 const struct message *lbuttondown; 6302 const struct message *lbuttonup; 6303 const struct message *setfont; 6304 const struct message *settext; 6305 } button[] = { 6306 { BS_PUSHBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON, 6307 WmSetFocusButtonSeq, WmKillFocusButtonSeq, WmSetStyleButtonSeq, 6308 WmSetStateButtonSeq, WmSetStateButtonSeq, WmSetCheckIgnoredSeq, 6309 WmLButtonDownSeq, WmLButtonUpSeq, WmSetFontButtonSeq, 6310 WmSetTextButtonSeq }, 6311 { BS_DEFPUSHBUTTON, DLGC_BUTTON | DLGC_DEFPUSHBUTTON, 6312 WmSetFocusButtonSeq, WmKillFocusButtonSeq, WmSetStyleButtonSeq, 6313 WmSetStateButtonSeq, WmSetStateButtonSeq, WmSetCheckIgnoredSeq, 6314 WmLButtonDownSeq, WmLButtonUpSeq, WmSetFontButtonSeq, 6315 WmSetTextButtonSeq }, 6316 { BS_CHECKBOX, DLGC_BUTTON, 6317 WmSetFocusStaticSeq, WmKillFocusStaticSeq, WmSetStyleStaticSeq, 6318 WmSetStateStaticSeq, WmSetStateStaticSeq, WmSetCheckStaticSeq, 6319 WmLButtonDownStaticSeq, WmLButtonUpStaticSeq, WmSetFontStaticSeq, 6320 WmSetTextStaticSeq }, 6321 { BS_AUTOCHECKBOX, DLGC_BUTTON, 6322 WmSetFocusStaticSeq, WmKillFocusStaticSeq, WmSetStyleStaticSeq, 6323 WmSetStateStaticSeq, WmSetStateStaticSeq, WmSetCheckStaticSeq, 6324 WmLButtonDownStaticSeq, WmLButtonUpAutoSeq, WmSetFontStaticSeq, 6325 WmSetTextStaticSeq }, 6326 { BS_RADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON, 6327 WmSetFocusStaticSeq, WmKillFocusStaticSeq, WmSetStyleStaticSeq, 6328 WmSetStateStaticSeq, WmSetStateStaticSeq, WmSetCheckStaticSeq, 6329 WmLButtonDownStaticSeq, WmLButtonUpStaticSeq, WmSetFontStaticSeq, 6330 WmSetTextStaticSeq }, 6331 { BS_3STATE, DLGC_BUTTON, 6332 WmSetFocusStaticSeq, WmKillFocusStaticSeq, WmSetStyleStaticSeq, 6333 WmSetStateStaticSeq, WmSetStateStaticSeq, WmSetCheckStaticSeq, 6334 WmLButtonDownStaticSeq, WmLButtonUpStaticSeq, WmSetFontStaticSeq, 6335 WmSetTextStaticSeq }, 6336 { BS_AUTO3STATE, DLGC_BUTTON, 6337 WmSetFocusStaticSeq, WmKillFocusStaticSeq, WmSetStyleStaticSeq, 6338 WmSetStateStaticSeq, WmSetStateStaticSeq, WmSetCheckStaticSeq, 6339 WmLButtonDownStaticSeq, WmLButtonUpAutoSeq, WmSetFontStaticSeq, 6340 WmSetTextStaticSeq }, 6341 { BS_GROUPBOX, DLGC_STATIC, 6342 WmSetFocusStaticSeq, WmKillFocusStaticSeq, WmSetStyleStaticSeq, 6343 WmSetStateStaticSeq, WmSetStateStaticSeq, WmSetCheckIgnoredSeq, 6344 WmLButtonDownStaticSeq, WmLButtonUpStaticSeq, WmSetFontStaticSeq, 6345 WmSetTextGroupSeq }, 6346 { BS_USERBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON, 6347 WmSetFocusButtonSeq, WmKillFocusButtonSeq, WmSetStyleUserSeq, 6348 WmSetStateUserSeq, WmClearStateButtonSeq, WmSetCheckIgnoredSeq, 6349 WmLButtonDownSeq, WmLButtonUpSeq, WmSetFontButtonSeq, 6350 WmSetTextButtonSeq }, 6351 { BS_AUTORADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON, 6352 WmSetFocusStaticSeq, WmKillFocusStaticSeq, WmSetStyleStaticSeq, 6353 WmSetStateStaticSeq, WmSetStateStaticSeq, WmSetCheckStaticSeq, 6354 NULL /* avoid infinite loop */, WmLButtonUpBrokenSeq, WmSetFontStaticSeq, 6355 WmSetTextStaticSeq }, 6356 { BS_OWNERDRAW, DLGC_BUTTON, 6357 WmSetFocusOwnerdrawSeq, WmKillFocusOwnerdrawSeq, WmSetStyleOwnerdrawSeq, 6358 WmSetStateOwnerdrawSeq, WmClearStateOwnerdrawSeq, WmSetCheckIgnoredSeq, 6359 WmLButtonDownSeq, WmLButtonUpSeq, WmSetFontButtonSeq, 6360 WmSetTextButtonSeq }, 6361 }; 6362 LOGFONTA logfont = { 0 }; 6363 HFONT zfont, hfont2; 6364 unsigned int i; 6365 HWND hwnd, parent; 6366 DWORD dlg_code; 6367 6368 /* selection with VK_SPACE should capture button window */ 6369 hwnd = CreateWindowExA(0, "button", "test", BS_CHECKBOX | WS_VISIBLE | WS_POPUP, 6370 0, 0, 50, 14, 0, 0, 0, NULL); 6371 ok(hwnd != 0, "Failed to create button window\n"); 6372 ReleaseCapture(); 6373 SetFocus(hwnd); 6374 SendMessageA(hwnd, WM_KEYDOWN, VK_SPACE, 0); 6375 ok(GetCapture() == hwnd, "Should be captured on VK_SPACE WM_KEYDOWN\n"); 6376 SendMessageA(hwnd, WM_KEYUP, VK_SPACE, 0); 6377 DestroyWindow(hwnd); 6378 6379 subclass_button(); 6380 6381 parent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 6382 100, 100, 200, 200, 0, 0, 0, NULL); 6383 ok(parent != 0, "Failed to create parent window\n"); 6384 6385 memset(&logfont, 0, sizeof(logfont)); 6386 logfont.lfHeight = -12; 6387 logfont.lfWeight = FW_NORMAL; 6388 strcpy(logfont.lfFaceName, "Tahoma"); 6389 6390 hfont2 = CreateFontIndirectA(&logfont); 6391 ok(hfont2 != NULL, "Failed to create Tahoma font\n"); 6392 6393 for (i = 0; i < sizeof(button)/sizeof(button[0]); i++) 6394 { 6395 MSG msg; 6396 DWORD style, state; 6397 HFONT prevfont; 6398 char desc[64]; 6399 HDC hdc; 6400 6401 trace("button style %08x\n", button[i].style); 6402 6403 hwnd = CreateWindowExA(0, "my_button_class", "test", button[i].style | WS_CHILD | BS_NOTIFY, 6404 0, 0, 50, 14, parent, (HMENU)ID_BUTTON, 0, NULL); 6405 ok(hwnd != 0, "Failed to create button window\n"); 6406 6407 style = GetWindowLongA(hwnd, GWL_STYLE); 6408 style &= ~(WS_CHILD | BS_NOTIFY); 6409 /* XP turns a BS_USERBUTTON into BS_PUSHBUTTON */ 6410 if (button[i].style == BS_USERBUTTON) 6411 ok(style == BS_PUSHBUTTON, "expected style BS_PUSHBUTTON got %x\n", style); 6412 else 6413 ok(style == button[i].style, "expected style %x got %x\n", button[i].style, style); 6414 6415 dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0); 6416 ok(dlg_code == button[i].dlg_code, "%u: wrong dlg_code %08x\n", i, dlg_code); 6417 6418 ShowWindow(hwnd, SW_SHOW); 6419 UpdateWindow(hwnd); 6420 SetFocus(0); 6421 flush_events(); 6422 SetFocus(0); 6423 flush_sequence(); 6424 6425 log_all_parent_messages++; 6426 6427 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus()); 6428 SetFocus(hwnd); 6429 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ 6430 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 6431 ok_sequence(button[i].setfocus, "SetFocus(hwnd) on a button", FALSE); 6432 6433 SetFocus(0); 6434 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ 6435 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 6436 ok_sequence(button[i].killfocus, "SetFocus(0) on a button", FALSE); 6437 6438 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus()); 6439 6440 SendMessageA(hwnd, BM_SETSTYLE, button[i].style | BS_BOTTOM, TRUE); 6441 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ 6442 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 6443 ok_sequence(button[i].setstyle, "BM_SETSTYLE on a button", FALSE); 6444 6445 style = GetWindowLongA(hwnd, GWL_STYLE); 6446 style &= ~(WS_VISIBLE | WS_CHILD | BS_NOTIFY); 6447 /* XP doesn't turn a BS_USERBUTTON into BS_PUSHBUTTON here! */ 6448 ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style); 6449 6450 state = SendMessageA(hwnd, BM_GETSTATE, 0, 0); 6451 ok(state == 0, "expected state 0, got %04x\n", state); 6452 6453 flush_sequence(); 6454 6455 SendMessageA(hwnd, BM_SETSTATE, TRUE, 0); 6456 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ 6457 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 6458 ok_sequence(button[i].setstate, "BM_SETSTATE/TRUE on a button", FALSE); 6459 6460 state = SendMessageA(hwnd, BM_GETSTATE, 0, 0); 6461 ok(state == 0x0004, "expected state 0x0004, got %04x\n", state); 6462 6463 style = GetWindowLongA(hwnd, GWL_STYLE); 6464 style &= ~(WS_CHILD | BS_NOTIFY | WS_VISIBLE); 6465 ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style); 6466 6467 flush_sequence(); 6468 6469 SendMessageA(hwnd, BM_SETSTATE, FALSE, 0); 6470 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ 6471 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 6472 ok_sequence(button[i].clearstate, "BM_SETSTATE/FALSE on a button", FALSE); 6473 6474 state = SendMessageA(hwnd, BM_GETSTATE, 0, 0); 6475 ok(state == 0, "expected state 0, got %04x\n", state); 6476 6477 style = GetWindowLongA(hwnd, GWL_STYLE); 6478 style &= ~(WS_CHILD | BS_NOTIFY | WS_VISIBLE); 6479 ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style); 6480 6481 state = SendMessageA(hwnd, BM_GETCHECK, 0, 0); 6482 ok(state == BST_UNCHECKED, "expected BST_UNCHECKED, got %04x\n", state); 6483 6484 flush_sequence(); 6485 6486 SendMessageA(hwnd, BM_SETCHECK, BST_UNCHECKED, 0); 6487 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ 6488 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 6489 ok_sequence(WmSetCheckIgnoredSeq, "BM_SETCHECK on a button", FALSE); 6490 6491 state = SendMessageA(hwnd, BM_GETCHECK, 0, 0); 6492 ok(state == BST_UNCHECKED, "expected BST_UNCHECKED, got %04x\n", state); 6493 6494 style = GetWindowLongA(hwnd, GWL_STYLE); 6495 style &= ~(WS_CHILD | BS_NOTIFY | WS_VISIBLE); 6496 ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style); 6497 6498 flush_sequence(); 6499 6500 SendMessageA(hwnd, BM_SETCHECK, BST_CHECKED, 0); 6501 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ 6502 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 6503 ok_sequence(button[i].setcheck, "BM_SETCHECK on a button", FALSE); 6504 6505 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"Text 1"); 6506 sprintf(desc, "button[%i]: WM_SETTEXT on a visible button", i); 6507 ok_sequence(button[i].settext, desc, FALSE); 6508 6509 ShowWindow(hwnd, SW_HIDE); 6510 flush_events(); 6511 flush_sequence(); 6512 6513 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"Text 2"); 6514 sprintf(desc, "button[%i]: WM_SETTEXT on an invisible button", i); 6515 ok_sequence(WmSetTextInvisibleSeq, desc, FALSE); 6516 6517 ShowWindow(hwnd, SW_SHOW); 6518 ShowWindow(parent, SW_HIDE); 6519 flush_events(); 6520 flush_sequence(); 6521 6522 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"Text 3"); 6523 sprintf(desc, "button[%i]: WM_SETTEXT on an invisible button", i); 6524 ok_sequence(WmSetTextInvisibleSeq, desc, FALSE); 6525 6526 ShowWindow(parent, SW_SHOW); 6527 flush_events(); 6528 6529 state = SendMessageA(hwnd, BM_GETCHECK, 0, 0); 6530 if (button[i].style == BS_PUSHBUTTON || 6531 button[i].style == BS_DEFPUSHBUTTON || 6532 button[i].style == BS_GROUPBOX || 6533 button[i].style == BS_USERBUTTON || 6534 button[i].style == BS_OWNERDRAW) 6535 ok(state == BST_UNCHECKED, "expected check 0, got %04x\n", state); 6536 else 6537 ok(state == BST_CHECKED, "expected check 1, got %04x\n", state); 6538 6539 style = GetWindowLongA(hwnd, GWL_STYLE); 6540 style &= ~(WS_CHILD | BS_NOTIFY | WS_VISIBLE); 6541 if (button[i].style == BS_RADIOBUTTON || 6542 button[i].style == BS_AUTORADIOBUTTON) 6543 ok(style == (button[i].style | WS_TABSTOP), "expected style %04x | WS_TABSTOP got %04x\n", button[i].style, style); 6544 else 6545 ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style); 6546 6547 log_all_parent_messages--; 6548 6549 DestroyWindow(hwnd); 6550 6551 hwnd = CreateWindowExA(0, "my_button_class", "test", button[i].style | WS_POPUP | WS_VISIBLE, 6552 0, 0, 50, 14, 0, 0, 0, NULL); 6553 ok(hwnd != 0, "Failed to create button window\n"); 6554 6555 SetForegroundWindow(hwnd); 6556 flush_events(); 6557 6558 SetActiveWindow(hwnd); 6559 SetFocus(0); 6560 flush_sequence(); 6561 6562 if (button[i].lbuttondown) 6563 { 6564 SendMessageA(hwnd, WM_LBUTTONDOWN, 0, 0); 6565 sprintf(desc, "button[%i]: WM_LBUTTONDOWN on a button", i); 6566 ok_sequence(button[i].lbuttondown, desc, FALSE); 6567 } 6568 6569 SendMessageA(hwnd, WM_LBUTTONUP, 0, 0); 6570 sprintf(desc, "button[%i]: WM_LBUTTONUP on a button", i); 6571 ok_sequence(button[i].lbuttonup, desc, FALSE); 6572 6573 flush_sequence(); 6574 zfont = GetStockObject(DEFAULT_GUI_FONT); 6575 SendMessageA(hwnd, WM_SETFONT, (WPARAM)zfont, TRUE); 6576 UpdateWindow(hwnd); 6577 sprintf(desc, "button[%i]: WM_SETFONT on a button", i); 6578 ok_sequence(button[i].setfont, desc, FALSE); 6579 6580 /* Test that original font is not selected back after painting */ 6581 hdc = CreateCompatibleDC(0); 6582 6583 prevfont = SelectObject(hdc, hfont2); 6584 ok(prevfont == GetStockObject(SYSTEM_FONT), "Unexpected default font\n"); 6585 SendMessageA(hwnd, WM_PRINTCLIENT, (WPARAM)hdc, 0); 6586 ok(hfont2 != GetCurrentObject(hdc, OBJ_FONT), "button[%u]: unexpected font selected after WM_PRINTCLIENT\n", i); 6587 SelectObject(hdc, prevfont); 6588 6589 prevfont = SelectObject(hdc, hfont2); 6590 ok(prevfont == GetStockObject(SYSTEM_FONT), "Unexpected default font\n"); 6591 SendMessageA(hwnd, WM_PAINT, (WPARAM)hdc, 0); 6592 ok(hfont2 != GetCurrentObject(hdc, OBJ_FONT), "button[%u]: unexpected font selected after WM_PAINT\n", i); 6593 SelectObject(hdc, prevfont); 6594 6595 DeleteDC(hdc); 6596 6597 DestroyWindow(hwnd); 6598 } 6599 6600 DeleteObject(hfont2); 6601 DestroyWindow(parent); 6602 6603 /* Test if WM_LBUTTONDOWN and WM_LBUTTONUP to a disabled button leads to a WM_COMMAND for the parent */ 6604 6605 parent = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 6606 100, 100, 200, 200, 0, 0, 0, NULL); 6607 ok (hwnd != 0, "Failed to create overlapped window\n"); 6608 6609 hwnd = CreateWindowExA(0, "my_button_class", "test", BS_DEFPUSHBUTTON | WS_VISIBLE | WS_CHILD, 6610 0, 0, 50, 14, parent, 0, 0, NULL); 6611 6612 EnableWindow(hwnd, FALSE); 6613 flush_sequence(); 6614 SendMessageA(hwnd, WM_LBUTTONDOWN, MK_LBUTTON, 0); 6615 SendMessageA(hwnd, WM_LBUTTONUP, 0, 0); 6616 ok_sequence(WmDisableButtonSeq, "Mouseclick on a disabled button", FALSE); 6617 6618 DestroyWindow(hwnd); 6619 DestroyWindow(parent); 6620 } 6621 6622 #define ID_RADIO1 501 6623 #define ID_RADIO2 502 6624 #define ID_RADIO3 503 6625 #define ID_TEXT 504 6626 6627 static const struct message auto_radio_button_BM_CLICK[] = 6628 { 6629 { BM_CLICK, sent|wparam|lparam, 0, 0 }, 6630 { WM_LBUTTONDOWN, sent|wparam|lparam|defwinproc, 0, 0 }, 6631 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, 6632 { BM_SETSTATE, sent|wparam|lparam|defwinproc, BST_CHECKED, ID_RADIO2 }, 6633 { WM_CTLCOLORSTATIC, sent|parent }, 6634 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6635 { WM_LBUTTONUP, sent|wparam|lparam|defwinproc, 0, 0 }, 6636 { BM_SETSTATE, sent|wparam|lparam|defwinproc, BST_UNCHECKED, ID_RADIO2 }, 6637 { WM_CTLCOLORSTATIC, sent|parent }, 6638 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6639 { WM_GETDLGCODE, sent|wparam|lparam|defwinproc, ID_RADIO2, 0 }, 6640 { BM_SETCHECK, sent|wparam|lparam|defwinproc, BST_CHECKED, ID_RADIO2 }, 6641 { WM_GETDLGCODE, sent|wparam|lparam|defwinproc, ID_RADIO1, 0 }, 6642 { BM_SETCHECK, sent|wparam|lparam|defwinproc, 0, ID_RADIO1 }, 6643 { WM_CTLCOLORSTATIC, sent|parent }, 6644 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6645 { WM_GETDLGCODE, sent|wparam|lparam|defwinproc, ID_RADIO3, 0 }, 6646 { BM_SETCHECK, sent|wparam|lparam|defwinproc, 0, ID_RADIO3 }, 6647 { WM_CTLCOLORSTATIC, sent|parent }, 6648 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6649 { WM_GETDLGCODE, sent|wparam|lparam|defwinproc, ID_TEXT, 0 }, 6650 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, 6651 { WM_CAPTURECHANGED, sent|wparam|lparam|defwinproc, 0, 0 }, 6652 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_RADIO2, BN_CLICKED) }, 6653 { WM_NCHITTEST, sent|optional, 0, 0 }, /* FIXME: Wine doesn't send it */ 6654 { WM_SETCURSOR, sent|optional, 0, 0 }, /* FIXME: Wine doesn't send it */ 6655 { WM_MOUSEMOVE, sent|optional, 0, 0 }, /* FIXME: Wine doesn't send it */ 6656 { 0 } 6657 }; 6658 6659 static const struct message auto_radio_button_VK_UP_child[] = 6660 { 6661 { WM_KEYDOWN, sent|wparam|lparam, VK_UP, 0 }, 6662 { WM_KEYUP, sent|wparam|lparam, VK_UP, 0 }, 6663 { 0 } 6664 }; 6665 6666 static const struct message auto_radio_button_VK_UP_parent[] = 6667 { 6668 { WM_KEYDOWN, sent|wparam|lparam|parent, VK_UP, 0 }, 6669 { WM_KEYUP, sent|wparam|lparam|parent, VK_UP, 0 }, 6670 { 0 } 6671 }; 6672 6673 static const struct message auto_radio_button_VK_UP_dialog[] = 6674 { 6675 { WM_GETDLGCODE, sent|parent, 0, 0 }, 6676 6677 /* optional trailer seen on some windows setups */ 6678 { WM_CHANGEUISTATE, sent|optional }, 6679 { WM_UPDATEUISTATE, sent|optional }, 6680 { WM_UPDATEUISTATE, sent|optional }, 6681 { WM_UPDATEUISTATE, sent|optional }, 6682 { WM_UPDATEUISTATE, sent|optional }, 6683 { WM_UPDATEUISTATE, sent|optional }, 6684 { WM_UPDATEUISTATE, sent|optional }, 6685 { WM_UPDATEUISTATE, sent|optional }, 6686 { WM_UPDATEUISTATE, sent|optional }, 6687 { WM_UPDATEUISTATE, sent|optional }, 6688 { WM_UPDATEUISTATE, sent|optional }, 6689 { WM_UPDATEUISTATE, sent|optional }, 6690 { WM_UPDATEUISTATE, sent|optional }, 6691 { WM_UPDATEUISTATE, sent|optional }, 6692 { WM_UPDATEUISTATE, sent|optional }, 6693 { WM_UPDATEUISTATE, sent|optional }, 6694 { WM_UPDATEUISTATE, sent|optional }, 6695 { WM_UPDATEUISTATE, sent|optional }, 6696 { WM_UPDATEUISTATE, sent|optional }, 6697 { WM_CTLCOLORSTATIC, sent|parent|optional }, 6698 { WM_CTLCOLORSTATIC, sent|parent|optional }, 6699 { WM_CTLCOLORSTATIC, sent|parent|optional }, 6700 { WM_UPDATEUISTATE, sent|optional }, 6701 { WM_CTLCOLORSTATIC, sent|parent|optional }, 6702 { WM_CTLCOLORSTATIC, sent|parent|optional }, 6703 { WM_UPDATEUISTATE, sent|optional }, 6704 { WM_CTLCOLORBTN, sent|parent|optional }, 6705 { WM_CTLCOLORBTN, sent|parent|optional }, 6706 { WM_UPDATEUISTATE, sent|optional }, 6707 { WM_CTLCOLORSTATIC, sent|parent|optional }, 6708 { WM_CTLCOLORSTATIC, sent|parent|optional }, 6709 { 0 } 6710 }; 6711 6712 static const struct message auto_radio_button_VK_DOWN_dialog[] = 6713 { 6714 { WM_GETDLGCODE, sent|parent, 0, 0 }, 6715 { WM_GETDLGCODE, sent|wparam|lparam, ID_RADIO1, MAKELPARAM(WM_KEYDOWN, VK_DOWN) }, 6716 { WM_GETDLGCODE, sent|wparam|lparam, ID_RADIO1, 0 }, 6717 { HCBT_SETFOCUS, hook }, 6718 { WM_KILLFOCUS, sent, 0, 0 }, 6719 { WM_CTLCOLORSTATIC, sent|parent }, 6720 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_RADIO3, BN_KILLFOCUS) }, 6721 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6722 { WM_SETFOCUS, sent, 0, 0 }, 6723 { WM_CTLCOLORSTATIC, sent|parent }, 6724 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_RADIO1, BN_SETFOCUS) }, 6725 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_RADIO1, BN_CLICKED) }, 6726 { WM_GETDLGCODE, sent|wparam|lparam, ID_RADIO1, 0 }, 6727 { WM_GETDLGCODE, sent|parent, 0, 0 }, 6728 { DM_GETDEFID, sent|parent, 0, 0 }, 6729 { BM_GETCHECK, sent|wparam|lparam, 0, ID_RADIO1 }, 6730 { BM_CLICK, sent|wparam|lparam, 1, 0 }, 6731 { WM_LBUTTONDOWN, sent|wparam|lparam|defwinproc, 0, 0 }, 6732 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, 6733 { BM_SETSTATE, sent|wparam|lparam|defwinproc, BST_CHECKED, ID_RADIO1 }, 6734 { WM_CTLCOLORSTATIC, sent|parent }, 6735 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6736 { WM_LBUTTONUP, sent|wparam|lparam|defwinproc, 0, 0 }, 6737 { BM_SETSTATE, sent|wparam|lparam|defwinproc, BST_UNCHECKED, ID_RADIO1 }, 6738 { WM_CTLCOLORSTATIC, sent|parent }, 6739 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6740 { WM_GETDLGCODE, sent|wparam|lparam|defwinproc, ID_RADIO1, 0 }, 6741 { BM_SETCHECK, sent|wparam|lparam|defwinproc, BST_CHECKED, ID_RADIO1 }, 6742 { WM_CTLCOLORSTATIC, sent|parent }, 6743 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6744 { WM_GETDLGCODE, sent|wparam|lparam|defwinproc, ID_RADIO3, 0 }, 6745 { BM_SETCHECK, sent|wparam|lparam|defwinproc, BST_UNCHECKED, ID_RADIO3 }, 6746 { WM_CTLCOLORSTATIC, sent|parent }, 6747 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6748 { WM_GETDLGCODE, sent|wparam|lparam|defwinproc, ID_TEXT, 0 }, 6749 { WM_GETDLGCODE, sent|wparam|lparam|defwinproc, ID_RADIO2, 0 }, 6750 { BM_SETCHECK, sent|wparam|lparam|defwinproc, BST_UNCHECKED, ID_RADIO2 }, 6751 { WM_CTLCOLORSTATIC, sent|parent }, 6752 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6753 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, 6754 { WM_CAPTURECHANGED, sent|wparam|lparam|defwinproc, 0, 0 }, 6755 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_RADIO1, BN_CLICKED) }, 6756 { WM_NCHITTEST, sent|optional, 0, 0 }, /* FIXME: Wine doesn't send it */ 6757 { WM_SETCURSOR, sent|optional, 0, 0 }, /* FIXME: Wine doesn't send it */ 6758 { WM_MOUSEMOVE, sent|optional, 0, 0 }, /* FIXME: Wine doesn't send it */ 6759 { WM_PAINT, sent }, 6760 { WM_CTLCOLORSTATIC, sent|parent }, 6761 { 0 } 6762 }; 6763 6764 static const struct message auto_radio_button_VK_DOWN_radio3[] = 6765 { 6766 { BM_GETCHECK, sent|wparam|lparam, 0, ID_RADIO1 }, 6767 { BM_GETCHECK, sent|wparam|lparam, 0, ID_RADIO2 }, 6768 { BM_GETCHECK, sent|wparam|lparam, 0, ID_RADIO3 }, 6769 { WM_GETDLGCODE, sent|parent, 0, 0 }, 6770 { WM_GETDLGCODE, sent|wparam|lparam, ID_RADIO1, MAKELPARAM(WM_KEYDOWN, VK_DOWN) }, 6771 { WM_GETDLGCODE, sent|wparam|lparam, ID_RADIO1, 0 }, 6772 { WM_GETDLGCODE, sent|wparam|lparam, ID_RADIO1, 0 }, 6773 { WM_GETDLGCODE, sent|wparam|lparam|parent, 0, 0 }, 6774 { WM_USER, sent|parent, 0, 0 }, 6775 { BM_GETCHECK, sent|wparam|lparam, 0, ID_RADIO1 }, 6776 { 0 } 6777 }; 6778 6779 static const struct message auto_radio_button_VK_UP_radio1[] = 6780 { 6781 { WM_GETDLGCODE, sent|parent, 0, 0 }, 6782 { 0 } 6783 }; 6784 6785 static INT_PTR WINAPI radio_test_dlg_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) 6786 { 6787 ParentMsgCheckProcA(hwnd, msg, wp, lp); 6788 return 1; 6789 } 6790 6791 static void test_autoradio_BM_CLICK(void) 6792 { 6793 HWND parent, radio1, radio2, radio3; 6794 RECT rc; 6795 MSG msg; 6796 DWORD ret; 6797 6798 subclass_button(); 6799 6800 parent = CreateDialogParamA(0, "AUTORADIO_TEST_DIALOG_1", 0, radio_test_dlg_proc, 0); 6801 ok(parent != 0, "failed to create parent window\n"); 6802 6803 radio1 = GetDlgItem(parent, ID_RADIO1); 6804 radio2 = GetDlgItem(parent, ID_RADIO2); 6805 radio3 = GetDlgItem(parent, ID_RADIO3); 6806 6807 /* this avoids focus messages in the generated sequence */ 6808 SetFocus(radio2); 6809 6810 flush_events(); 6811 flush_sequence(); 6812 6813 ret = SendMessageA(radio1, BM_GETCHECK, 0, 0); 6814 ok(ret == BST_UNCHECKED, "got %08x\n", ret); 6815 ret = SendMessageA(radio2, BM_GETCHECK, 0, 0); 6816 ok(ret == BST_UNCHECKED, "got %08x\n", ret); 6817 ret = SendMessageA(radio3, BM_GETCHECK, 0, 0); 6818 ok(ret == BST_UNCHECKED, "got %08x\n", ret); 6819 6820 SendMessageA(radio1, BM_SETCHECK, BST_CHECKED, 0); 6821 6822 ret = SendMessageA(radio1, BM_GETCHECK, 0, 0); 6823 ok(ret == BST_CHECKED, "got %08x\n", ret); 6824 ret = SendMessageA(radio2, BM_GETCHECK, 0, 0); 6825 ok(ret == BST_UNCHECKED, "got %08x\n", ret); 6826 ret = SendMessageA(radio3, BM_GETCHECK, 0, 0); 6827 ok(ret == BST_UNCHECKED, "got %08x\n", ret); 6828 6829 SendMessageA(radio2, BM_SETCHECK, BST_CHECKED, 0); 6830 6831 ret = SendMessageA(radio1, BM_GETCHECK, 0, 0); 6832 ok(ret == BST_CHECKED, "got %08x\n", ret); 6833 ret = SendMessageA(radio2, BM_GETCHECK, 0, 0); 6834 ok(ret == BST_CHECKED, "got %08x\n", ret); 6835 ret = SendMessageA(radio3, BM_GETCHECK, 0, 0); 6836 ok(ret == BST_UNCHECKED, "got %08x\n", ret); 6837 6838 SendMessageA(radio3, BM_SETCHECK, BST_CHECKED, 0); 6839 6840 ret = SendMessageA(radio1, BM_GETCHECK, 0, 0); 6841 ok(ret == BST_CHECKED, "got %08x\n", ret); 6842 ret = SendMessageA(radio2, BM_GETCHECK, 0, 0); 6843 ok(ret == BST_CHECKED, "got %08x\n", ret); 6844 ret = SendMessageA(radio3, BM_GETCHECK, 0, 0); 6845 ok(ret == BST_CHECKED, "got %08x\n", ret); 6846 6847 GetWindowRect(radio2, &rc); 6848 SetCursorPos(rc.left+1, rc.top+1); 6849 6850 flush_events(); 6851 flush_sequence(); 6852 6853 log_all_parent_messages++; 6854 6855 SendMessageA(radio2, BM_CLICK, 0, 0); 6856 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 6857 ok_sequence(auto_radio_button_BM_CLICK, "BM_CLICK on auto-radio button", FALSE); 6858 6859 log_all_parent_messages--; 6860 6861 ret = SendMessageA(radio1, BM_GETCHECK, 0, 0); 6862 ok(ret == BST_UNCHECKED, "got %08x\n", ret); 6863 ret = SendMessageA(radio2, BM_GETCHECK, 0, 0); 6864 ok(ret == BST_CHECKED, "got %08x\n", ret); 6865 ret = SendMessageA(radio3, BM_GETCHECK, 0, 0); 6866 ok(ret == BST_UNCHECKED, "got %08x\n", ret); 6867 6868 DestroyWindow(parent); 6869 } 6870 6871 #define test_radio(r1, s1, r2, s2, r3, s3) test_radio_dbg(r1, s1, r2, s2, r3, s3, __LINE__) 6872 static void test_radio_dbg(HWND radio1, int state1, HWND radio2, int state2, HWND radio3, int state3, int line) 6873 { 6874 DWORD ret; 6875 6876 ret = SendMessageA(radio1, BM_GETCHECK, 0, 0); 6877 ok_(__FILE__,line)(ret == state1 ? BST_CHECKED : BST_UNCHECKED, "got %08x\n", ret); 6878 ret = SendMessageA(radio2, BM_GETCHECK, 0, 0); 6879 ok_(__FILE__,line)(ret == state2 ? BST_CHECKED : BST_UNCHECKED, "got %08x\n", ret); 6880 ret = SendMessageA(radio3, BM_GETCHECK, 0, 0); 6881 ok_(__FILE__,line)(ret == state3 ? BST_CHECKED : BST_UNCHECKED, "got %08x\n", ret); 6882 } 6883 6884 static void set_radio(HWND radio1, int state1, HWND radio2, int state2, HWND radio3, int state3) 6885 { 6886 SendMessageA(radio1, BM_SETCHECK, state1 ? BST_CHECKED : BST_UNCHECKED, 0); 6887 SendMessageA(radio2, BM_SETCHECK, state2 ? BST_CHECKED : BST_UNCHECKED, 0); 6888 SendMessageA(radio3, BM_SETCHECK, state3 ? BST_CHECKED : BST_UNCHECKED, 0); 6889 } 6890 6891 static void test_autoradio_kbd_move(void) 6892 { 6893 HWND parent, radio1, radio2, radio3, hwnd; 6894 RECT rc; 6895 MSG msg; 6896 DWORD ret; 6897 6898 subclass_button(); 6899 6900 parent = CreateDialogParamA(0, "AUTORADIO_TEST_DIALOG_2", 0, radio_test_dlg_proc, 0); 6901 ok(parent != 0, "failed to create parent window\n"); 6902 6903 radio1 = GetDlgItem(parent, ID_RADIO1); 6904 radio2 = GetDlgItem(parent, ID_RADIO2); 6905 radio3 = GetDlgItem(parent, ID_RADIO3); 6906 6907 flush_events(); 6908 flush_sequence(); 6909 6910 test_radio(radio1, 0, radio2, 0, radio3, 0); 6911 set_radio(radio1, 1, radio2, 1, radio3, 1); 6912 test_radio(radio1, 1, radio2, 1, radio3, 1); 6913 6914 SetFocus(radio3); 6915 6916 flush_events(); 6917 flush_sequence(); 6918 6919 log_all_parent_messages++; 6920 6921 SendMessageA(radio3, WM_KEYDOWN, VK_UP, 0); 6922 SendMessageA(radio3, WM_KEYUP, VK_UP, 0); 6923 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 6924 ok_sequence(auto_radio_button_VK_UP_child, "press/release VK_UP on auto-radio button", FALSE); 6925 6926 test_radio(radio1, 1, radio2, 1, radio3, 1); 6927 6928 flush_events(); 6929 flush_sequence(); 6930 6931 DefDlgProcA(parent, WM_KEYDOWN, VK_UP, 0); 6932 DefDlgProcA(parent, WM_KEYUP, VK_UP, 0); 6933 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 6934 ok_sequence(auto_radio_button_VK_UP_parent, "press/release VK_UP on dialog", FALSE); 6935 6936 test_radio(radio1, 1, radio2, 1, radio3, 1); 6937 6938 SetFocus(radio3); 6939 GetWindowRect(radio3, &rc); 6940 6941 flush_events(); 6942 flush_sequence(); 6943 6944 msg.hwnd = parent; 6945 msg.message = WM_KEYDOWN; 6946 msg.wParam = VK_UP; 6947 msg.lParam = 0; 6948 msg.pt.x = rc.left + 1; 6949 msg.pt.y = rc.top + 1; 6950 ret = IsDialogMessageA(parent, &msg); 6951 ok(ret, "IsDialogMessage should return TRUE\n"); 6952 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 6953 if (0) /* actual message sequence is different on every run in some Windows setups */ 6954 ok_sequence(auto_radio_button_VK_UP_dialog, "IsDialogMessage(VK_UP) #1", FALSE); 6955 /* what really matters is that nothing has changed */ 6956 test_radio(radio1, 1, radio2, 1, radio3, 1); 6957 6958 set_radio(radio1, 0, radio2, 1, radio3, 1); 6959 test_radio(radio1, 0, radio2, 1, radio3, 1); 6960 6961 flush_events(); 6962 flush_sequence(); 6963 6964 ret = IsDialogMessageA(parent, &msg); 6965 ok(ret, "IsDialogMessage should return TRUE\n"); 6966 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 6967 if (0) /* actual message sequence is different on every run in some Windows setups */ 6968 ok_sequence(auto_radio_button_VK_UP_dialog, "IsDialogMessage(VK_UP) #2", FALSE); 6969 /* what really matters is that nothing has changed */ 6970 test_radio(radio1, 0, radio2, 1, radio3, 1); 6971 6972 /* switch from radio3 ro radio1 */ 6973 SetFocus(radio3); 6974 GetWindowRect(radio3, &rc); 6975 6976 flush_events(); 6977 flush_sequence(); 6978 6979 msg.hwnd = parent; 6980 msg.message = WM_KEYDOWN; 6981 msg.wParam = VK_DOWN; 6982 msg.lParam = 0; 6983 msg.pt.x = rc.left + 1; 6984 msg.pt.y = rc.top + 1; 6985 ret = IsDialogMessageA(parent, &msg); 6986 ok(ret, "IsDialogMessage should return TRUE\n"); 6987 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 6988 ok_sequence(auto_radio_button_VK_DOWN_dialog, "IsDialogMessage(VK_DOWN)", TRUE); 6989 6990 test_radio(radio1, 1, radio2, 0, radio3, 0); 6991 6992 hwnd = GetFocus(); 6993 ok(hwnd == radio1, "focus should be on radio1, not on %p\n", hwnd); 6994 GetWindowRect(radio1, &rc); 6995 6996 msg.hwnd = parent; 6997 msg.message = WM_KEYDOWN; 6998 msg.wParam = VK_DOWN; 6999 msg.lParam = 0; 7000 msg.pt.x = rc.left + 1; 7001 msg.pt.y = rc.top + 1; 7002 ret = IsDialogMessageA(parent, &msg); 7003 ok(ret, "IsDialogMessage should return TRUE\n"); 7004 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 7005 ok_sequence(auto_radio_button_VK_DOWN_radio3, "down to radio3", TRUE); 7006 7007 test_radio(radio1, 1, radio2, 0, radio3, 0); 7008 7009 hwnd = GetFocus(); 7010 ok(hwnd == radio1, "focus should be on radio1, not on %p\n", hwnd); 7011 7012 flush_events(); 7013 flush_sequence(); 7014 7015 msg.hwnd = parent; 7016 msg.message = WM_KEYDOWN; 7017 msg.wParam = VK_UP; 7018 msg.lParam = 0; 7019 msg.pt.x = rc.left + 1; 7020 msg.pt.y = rc.top + 1; 7021 ret = IsDialogMessageA(parent, &msg); 7022 ok(ret, "IsDialogMessage should return TRUE\n"); 7023 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 7024 ok_sequence(auto_radio_button_VK_UP_radio1, "up to radio1", TRUE); 7025 7026 test_radio(radio1, 1, radio2, 0, radio3, 0); 7027 7028 hwnd = GetFocus(); 7029 ok(hwnd == radio1, "focus should be on radio1, not on %p\n", hwnd); 7030 7031 flush_events(); 7032 flush_sequence(); 7033 7034 msg.hwnd = parent; 7035 msg.message = WM_KEYDOWN; 7036 msg.wParam = VK_UP; 7037 msg.lParam = 0; 7038 msg.pt.x = rc.left + 1; 7039 msg.pt.y = rc.top + 1; 7040 ret = IsDialogMessageA(parent, &msg); 7041 ok(ret, "IsDialogMessage should return TRUE\n"); 7042 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 7043 if (0) /* actual message sequence is different on every run in some Windows setups */ 7044 ok_sequence(auto_radio_button_VK_UP_dialog, "IsDialogMessage(VK_UP) #3", FALSE); 7045 /* what really matters is that nothing has changed */ 7046 test_radio(radio1, 1, radio2, 0, radio3, 0); 7047 7048 log_all_parent_messages--; 7049 7050 DestroyWindow(parent); 7051 } 7052 7053 /****************** static message test *************************/ 7054 static const struct message WmSetFontStaticSeq2[] = 7055 { 7056 { WM_SETFONT, sent }, 7057 { WM_PAINT, sent|defwinproc|optional }, 7058 { WM_ERASEBKGND, sent|defwinproc|optional }, 7059 { WM_CTLCOLORSTATIC, sent|defwinproc|optional }, 7060 { 0 } 7061 }; 7062 7063 static WNDPROC old_static_proc; 7064 7065 static LRESULT CALLBACK static_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 7066 { 7067 static LONG defwndproc_counter = 0; 7068 LRESULT ret; 7069 struct recvd_message msg; 7070 7071 if (ignore_message( message )) return 0; 7072 7073 msg.hwnd = hwnd; 7074 msg.message = message; 7075 msg.flags = sent|wparam|lparam; 7076 if (defwndproc_counter) msg.flags |= defwinproc; 7077 msg.wParam = wParam; 7078 msg.lParam = lParam; 7079 msg.descr = "static"; 7080 add_message(&msg); 7081 7082 defwndproc_counter++; 7083 ret = CallWindowProcA(old_static_proc, hwnd, message, wParam, lParam); 7084 defwndproc_counter--; 7085 7086 return ret; 7087 } 7088 7089 static void subclass_static(void) 7090 { 7091 WNDCLASSA cls; 7092 7093 if (!GetClassInfoA(0, "static", &cls)) assert(0); 7094 7095 old_static_proc = cls.lpfnWndProc; 7096 7097 cls.hInstance = GetModuleHandleA(NULL); 7098 cls.lpfnWndProc = static_hook_proc; 7099 cls.lpszClassName = "my_static_class"; 7100 UnregisterClassA(cls.lpszClassName, cls.hInstance); 7101 if (!RegisterClassA(&cls)) assert(0); 7102 } 7103 7104 static void test_static_messages(void) 7105 { 7106 /* FIXME: make as comprehensive as the button message test */ 7107 static const struct 7108 { 7109 DWORD style; 7110 DWORD dlg_code; 7111 const struct message *setfont; 7112 } static_ctrl[] = { 7113 { SS_LEFT, DLGC_STATIC, 7114 WmSetFontStaticSeq2 } 7115 }; 7116 unsigned int i; 7117 HWND hwnd; 7118 DWORD dlg_code; 7119 7120 subclass_static(); 7121 7122 for (i = 0; i < sizeof(static_ctrl)/sizeof(static_ctrl[0]); i++) 7123 { 7124 hwnd = CreateWindowExA(0, "my_static_class", "test", static_ctrl[i].style | WS_POPUP, 7125 0, 0, 50, 14, 0, 0, 0, NULL); 7126 ok(hwnd != 0, "Failed to create static window\n"); 7127 7128 dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0); 7129 ok(dlg_code == static_ctrl[i].dlg_code, "%u: wrong dlg_code %08x\n", i, dlg_code); 7130 7131 ShowWindow(hwnd, SW_SHOW); 7132 UpdateWindow(hwnd); 7133 SetFocus(0); 7134 flush_sequence(); 7135 7136 trace("static style %08x\n", static_ctrl[i].style); 7137 SendMessageA(hwnd, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), TRUE); 7138 ok_sequence(static_ctrl[i].setfont, "WM_SETFONT on a static", FALSE); 7139 7140 DestroyWindow(hwnd); 7141 } 7142 } 7143 7144 /****************** ComboBox message test *************************/ 7145 #define ID_COMBOBOX 0x000f 7146 7147 static const struct message SetCurSelComboSeq[] = 7148 { 7149 { CB_SETCURSEL, sent|wparam|lparam, 0, 0 }, 7150 { LB_SETCURSEL, sent|wparam|lparam, 0, 0 }, 7151 { LB_SETTOPINDEX, sent|wparam|lparam, 0, 0 }, 7152 { LB_GETCURSEL, sent|wparam|lparam, 0, 0 }, 7153 { LB_GETTEXTLEN, sent|wparam|lparam, 0, 0 }, 7154 { LB_GETTEXTLEN, sent|wparam|lparam|optional, 0, 0 }, /* TODO: it's sent on all Windows versions */ 7155 { LB_GETTEXT, sent|wparam, 0 }, 7156 { WM_CTLCOLOREDIT, sent|parent }, 7157 { LB_GETITEMDATA, sent|wparam|lparam, 0, 0 }, 7158 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_COMBOBOX, 0x100010f3 }, 7159 { 0 } 7160 }; 7161 7162 static const struct message SetCurSelComboSeq2[] = 7163 { 7164 { CB_SETCURSEL, sent|wparam|lparam, 0, 0 }, 7165 { LB_SETCURSEL, sent|wparam|lparam, 0, 0 }, 7166 { LB_SETTOPINDEX, sent|wparam|lparam, 0, 0 }, 7167 { LB_GETCURSEL, sent|wparam|lparam, 0, 0 }, 7168 { LB_GETTEXTLEN, sent|wparam|lparam, 0, 0 }, 7169 { LB_GETTEXTLEN, sent|wparam|lparam|optional, 0, 0 }, /* TODO: it's sent on all Windows versions */ 7170 { LB_GETTEXT, sent|wparam, 0 }, 7171 { 0 } 7172 }; 7173 7174 static const struct message SetCurSelComboSeq_edit[] = 7175 { 7176 { CB_SETCURSEL, sent|wparam|lparam, 0, 0 }, 7177 { WM_SETTEXT, sent|wparam, 0 }, 7178 { EM_SETSEL, sent|wparam|lparam, 0, INT_MAX }, 7179 { 0 } 7180 }; 7181 7182 static const struct message WmKeyDownComboSeq[] = 7183 { 7184 { WM_KEYDOWN, sent|wparam|lparam, VK_DOWN, 0 }, 7185 { WM_COMMAND, sent|wparam|defwinproc, MAKEWPARAM(1000, LBN_SELCHANGE) }, 7186 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_COMBOBOX, CBN_SELENDOK) }, 7187 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_COMBOBOX, CBN_SELCHANGE) }, 7188 { WM_CTLCOLOREDIT, sent|parent }, 7189 { WM_KEYUP, sent|wparam|lparam, VK_DOWN, 0 }, 7190 { 0 } 7191 }; 7192 7193 static const struct message WmSetPosComboSeq[] = 7194 { 7195 { WM_WINDOWPOSCHANGING, sent }, 7196 { WM_NCCALCSIZE, sent|wparam, TRUE }, 7197 { WM_CHILDACTIVATE, sent }, 7198 { WM_WINDOWPOSCHANGED, sent }, 7199 { WM_MOVE, sent|defwinproc }, 7200 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 7201 { WM_WINDOWPOSCHANGING, sent|defwinproc }, 7202 { WM_NCCALCSIZE, sent|defwinproc|wparam, TRUE }, 7203 { WM_WINDOWPOSCHANGED, sent|defwinproc }, 7204 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 7205 { 0 } 7206 }; 7207 7208 static const struct message WMSetFocusComboBoxSeq[] = 7209 { 7210 { WM_SETFOCUS, sent }, 7211 { WM_KILLFOCUS, sent|parent }, 7212 { WM_SETFOCUS, sent }, 7213 { WM_COMMAND, sent|defwinproc|wparam, MAKEWPARAM(1001, EN_SETFOCUS) }, 7214 { EM_SETSEL, sent|defwinproc|wparam|lparam, 0, INT_MAX }, 7215 { WM_CTLCOLOREDIT, sent|defwinproc|optional },/* Not sent on W2000, XP or Server 2003 */ 7216 { WM_CTLCOLOREDIT, sent|parent|optional },/* Not sent on W2000, XP or Server 2003 */ 7217 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_COMBOBOX, CBN_SETFOCUS) }, 7218 { 0 } 7219 }; 7220 7221 static const struct message SetFocusButtonSeq[] = 7222 { 7223 { WM_KILLFOCUS, sent }, 7224 { CB_GETCOMBOBOXINFO, sent|optional },/* Windows 2000 */ 7225 { 0x0167, sent|optional },/* Undocumented message. Sent on all versions except Windows 2000 */ 7226 { WM_LBUTTONUP, sent|defwinproc }, 7227 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_COMBOBOX, CBN_SELENDCANCEL) }, 7228 { EM_SETSEL, sent|defwinproc|wparam|lparam, 0, 0 }, 7229 { WM_CTLCOLOREDIT, sent|defwinproc|optional },/* Not sent on W2000, XP or Server 2003 */ 7230 { WM_CTLCOLOREDIT, sent|parent|optional },/* Not sent on W2000, XP or Server 2003 */ 7231 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_COMBOBOX, CBN_KILLFOCUS) }, 7232 { WM_CTLCOLORBTN, sent|parent }, 7233 { 0 } 7234 }; 7235 7236 static const struct message SetFocusComboBoxSeq[] = 7237 { 7238 { WM_CTLCOLORBTN, sent|parent }, 7239 { WM_SETFOCUS, sent }, 7240 { WM_KILLFOCUS, sent|defwinproc }, 7241 { WM_SETFOCUS, sent }, 7242 { WM_COMMAND, sent|defwinproc|wparam, MAKEWPARAM(1001, EN_SETFOCUS) }, 7243 { EM_SETSEL, sent|defwinproc|wparam|lparam, 0, INT_MAX }, 7244 { WM_CTLCOLOREDIT, sent|defwinproc|optional },/* Not sent on W2000, XP or Server 2003 */ 7245 { WM_CTLCOLOREDIT, sent|parent|optional },/* Not sent on W2000, XP or Server 2003 */ 7246 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_COMBOBOX, CBN_SETFOCUS) }, 7247 { 0 } 7248 }; 7249 7250 static const struct message SetFocusButtonSeq2[] = 7251 { 7252 { WM_KILLFOCUS, sent }, 7253 { CB_GETCOMBOBOXINFO, sent|optional },/* Windows 2000 */ 7254 { 0x0167, sent|optional },/* Undocumented message. Sent on all versions except Windows 2000 */ 7255 { WM_LBUTTONUP, sent|defwinproc }, 7256 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_COMBOBOX, CBN_SELENDCANCEL) }, 7257 { EM_SETSEL, sent|defwinproc|wparam|lparam, 0, 0 }, 7258 { WM_CTLCOLOREDIT, sent|defwinproc }, 7259 { WM_CTLCOLOREDIT, sent|parent }, 7260 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_COMBOBOX, CBN_KILLFOCUS) }, 7261 { WM_CTLCOLORBTN, sent|parent }, 7262 { 0 } 7263 }; 7264 7265 static WNDPROC old_combobox_proc, edit_window_proc, lbox_window_proc; 7266 7267 static LRESULT CALLBACK combobox_edit_subclass_proc(HWND hwnd, UINT message, 7268 WPARAM wParam, LPARAM lParam) 7269 { 7270 static LONG defwndproc_counter = 0; 7271 LRESULT ret; 7272 struct recvd_message msg; 7273 7274 /* do not log painting messages */ 7275 if (message != WM_PAINT && 7276 message != WM_NCPAINT && 7277 message != WM_SYNCPAINT && 7278 message != WM_ERASEBKGND && 7279 message != WM_NCHITTEST && 7280 message != WM_GETTEXT && 7281 !ignore_message( message )) 7282 { 7283 msg.hwnd = hwnd; 7284 msg.message = message; 7285 msg.flags = sent|wparam|lparam; 7286 if (defwndproc_counter) msg.flags |= defwinproc; 7287 msg.wParam = wParam; 7288 msg.lParam = lParam; 7289 msg.descr = "combo edit"; 7290 add_message(&msg); 7291 } 7292 7293 defwndproc_counter++; 7294 ret = CallWindowProcA(edit_window_proc, hwnd, message, wParam, lParam); 7295 defwndproc_counter--; 7296 7297 return ret; 7298 } 7299 7300 static LRESULT CALLBACK combobox_lbox_subclass_proc(HWND hwnd, UINT message, 7301 WPARAM wParam, LPARAM lParam) 7302 { 7303 static LONG defwndproc_counter = 0; 7304 LRESULT ret; 7305 struct recvd_message msg; 7306 7307 /* do not log painting messages */ 7308 if (message != WM_PAINT && 7309 message != WM_NCPAINT && 7310 message != WM_SYNCPAINT && 7311 message != WM_ERASEBKGND && 7312 message != WM_NCHITTEST && 7313 !ignore_message( message )) 7314 { 7315 msg.hwnd = hwnd; 7316 msg.message = message; 7317 msg.flags = sent|wparam|lparam; 7318 if (defwndproc_counter) msg.flags |= defwinproc; 7319 msg.wParam = wParam; 7320 msg.lParam = lParam; 7321 msg.descr = "combo lbox"; 7322 add_message(&msg); 7323 } 7324 7325 defwndproc_counter++; 7326 ret = CallWindowProcA(lbox_window_proc, hwnd, message, wParam, lParam); 7327 defwndproc_counter--; 7328 7329 return ret; 7330 } 7331 7332 static LRESULT CALLBACK combobox_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 7333 { 7334 static LONG defwndproc_counter = 0; 7335 LRESULT ret; 7336 struct recvd_message msg; 7337 7338 /* do not log painting messages */ 7339 if (message != WM_PAINT && 7340 message != WM_NCPAINT && 7341 message != WM_SYNCPAINT && 7342 message != WM_ERASEBKGND && 7343 message != WM_NCHITTEST && 7344 message != WM_GETTEXT && 7345 !ignore_message( message )) 7346 { 7347 msg.hwnd = hwnd; 7348 msg.message = message; 7349 msg.flags = sent|wparam|lparam; 7350 if (defwndproc_counter) msg.flags |= defwinproc; 7351 msg.wParam = wParam; 7352 msg.lParam = lParam; 7353 msg.descr = "combo"; 7354 add_message(&msg); 7355 } 7356 7357 defwndproc_counter++; 7358 ret = CallWindowProcA(old_combobox_proc, hwnd, message, wParam, lParam); 7359 defwndproc_counter--; 7360 7361 return ret; 7362 } 7363 7364 static void subclass_combobox(void) 7365 { 7366 WNDCLASSA cls; 7367 7368 if (!GetClassInfoA(0, "ComboBox", &cls)) assert(0); 7369 7370 old_combobox_proc = cls.lpfnWndProc; 7371 7372 cls.hInstance = GetModuleHandleA(NULL); 7373 cls.lpfnWndProc = combobox_hook_proc; 7374 cls.lpszClassName = "my_combobox_class"; 7375 UnregisterClassA(cls.lpszClassName, cls.hInstance); 7376 if (!RegisterClassA(&cls)) assert(0); 7377 } 7378 7379 static void test_combobox_messages(void) 7380 { 7381 HWND parent, combo, button, edit, lbox; 7382 LRESULT ret; 7383 COMBOBOXINFO cbInfo; 7384 BOOL res; 7385 7386 subclass_combobox(); 7387 7388 parent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 7389 100, 100, 200, 200, 0, 0, 0, NULL); 7390 ok(parent != 0, "Failed to create parent window\n"); 7391 flush_sequence(); 7392 7393 combo = CreateWindowExA(0, "my_combobox_class", "test", WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | CBS_HASSTRINGS, 7394 0, 0, 100, 150, parent, (HMENU)ID_COMBOBOX, 0, NULL); 7395 ok(combo != 0, "Failed to create combobox window\n"); 7396 7397 UpdateWindow(combo); 7398 7399 ret = SendMessageA(combo, WM_GETDLGCODE, 0, 0); 7400 ok(ret == (DLGC_WANTCHARS | DLGC_WANTARROWS), "wrong dlg_code %08lx\n", ret); 7401 7402 ret = SendMessageA(combo, CB_ADDSTRING, 0, (LPARAM)"item 0"); 7403 ok(ret == 0, "expected 0, got %ld\n", ret); 7404 ret = SendMessageA(combo, CB_ADDSTRING, 0, (LPARAM)"item 1"); 7405 ok(ret == 1, "expected 1, got %ld\n", ret); 7406 ret = SendMessageA(combo, CB_ADDSTRING, 0, (LPARAM)"item 2"); 7407 ok(ret == 2, "expected 2, got %ld\n", ret); 7408 7409 SendMessageA(combo, CB_SETCURSEL, 0, 0); 7410 SetFocus(combo); 7411 flush_sequence(); 7412 7413 log_all_parent_messages++; 7414 SendMessageA(combo, WM_KEYDOWN, VK_DOWN, 0); 7415 SendMessageA(combo, WM_KEYUP, VK_DOWN, 0); 7416 log_all_parent_messages--; 7417 ok_sequence(WmKeyDownComboSeq, "WM_KEYDOWN/VK_DOWN on a ComboBox", FALSE); 7418 7419 flush_sequence(); 7420 SetWindowPos(combo, 0, 10, 10, 120, 130, SWP_NOZORDER); 7421 ok_sequence(WmSetPosComboSeq, "repositioning messages on a ComboBox", FALSE); 7422 7423 DestroyWindow(combo); 7424 DestroyWindow(parent); 7425 7426 /* Start again. Test combobox text selection when getting and losing focus */ 7427 parent = CreateWindowExA(0, "TestParentClass", "Parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 7428 10, 10, 300, 300, NULL, NULL, NULL, NULL); 7429 ok(parent != 0, "Failed to create parent window\n"); 7430 7431 combo = CreateWindowExA(0, "my_combobox_class", "test", WS_CHILD | WS_VISIBLE | CBS_DROPDOWN, 7432 5, 5, 100, 100, parent, (HMENU)ID_COMBOBOX, NULL, NULL); 7433 ok(combo != 0, "Failed to create combobox window\n"); 7434 7435 cbInfo.cbSize = sizeof(COMBOBOXINFO); 7436 SetLastError(0xdeadbeef); 7437 res = GetComboBoxInfo(combo, &cbInfo); 7438 ok(res, "Failed to get COMBOBOXINFO structure; LastError: %u\n", GetLastError()); 7439 edit = cbInfo.hwndItem; 7440 7441 edit_window_proc = (WNDPROC)SetWindowLongPtrA(edit, GWLP_WNDPROC, 7442 (ULONG_PTR)combobox_edit_subclass_proc); 7443 7444 button = CreateWindowExA(0, "Button", "OK", WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 7445 5, 50, 100, 20, parent, NULL, 7446 (HINSTANCE)GetWindowLongPtrA(parent, GWLP_HINSTANCE), NULL); 7447 ok(button != 0, "Failed to create button window\n"); 7448 7449 flush_sequence(); 7450 log_all_parent_messages++; 7451 SendMessageA(combo, WM_SETFOCUS, 0, (LPARAM)edit); 7452 log_all_parent_messages--; 7453 ok_sequence(WMSetFocusComboBoxSeq, "WM_SETFOCUS on a ComboBox", TRUE); 7454 7455 flush_sequence(); 7456 log_all_parent_messages++; 7457 SetFocus(button); 7458 log_all_parent_messages--; 7459 ok_sequence(SetFocusButtonSeq, "SetFocus on a Button", TRUE); 7460 7461 SendMessageA(combo, WM_SETTEXT, 0, (LPARAM)"Wine Test"); 7462 7463 flush_sequence(); 7464 log_all_parent_messages++; 7465 SetFocus(combo); 7466 log_all_parent_messages--; 7467 ok_sequence(SetFocusComboBoxSeq, "SetFocus on a ComboBox", TRUE); 7468 7469 flush_sequence(); 7470 log_all_parent_messages++; 7471 SetFocus(button); 7472 log_all_parent_messages--; 7473 ok_sequence(SetFocusButtonSeq2, "SetFocus on a Button (2)", TRUE); 7474 7475 SetFocus(combo); 7476 SendMessageA(combo, WM_SETREDRAW, FALSE, 0); 7477 flush_sequence(); 7478 log_all_parent_messages++; 7479 SendMessageA(combo, CB_SETCURSEL, 0, 0); 7480 log_all_parent_messages--; 7481 ok_sequence(SetCurSelComboSeq_edit, "CB_SETCURSEL on a ComboBox with edit control", FALSE); 7482 7483 DestroyWindow(button); 7484 DestroyWindow(combo); 7485 7486 combo = CreateWindowExA(0, "my_combobox_class", "test", 7487 WS_CHILD | WS_VISIBLE | CBS_OWNERDRAWFIXED | CBS_DROPDOWNLIST, 7488 5, 5, 100, 100, parent, (HMENU)ID_COMBOBOX, NULL, NULL); 7489 ok(combo != 0, "Failed to create combobox window\n"); 7490 7491 ret = SendMessageA(combo, CB_ADDSTRING, 0, (LPARAM)"item 0"); 7492 ok(ret == 0, "expected 0, got %ld\n", ret); 7493 7494 cbInfo.cbSize = sizeof(COMBOBOXINFO); 7495 SetLastError(0xdeadbeef); 7496 res = GetComboBoxInfo(combo, &cbInfo); 7497 ok(res, "Failed to get COMBOBOXINFO structure; LastError: %u\n", GetLastError()); 7498 lbox = cbInfo.hwndList; 7499 lbox_window_proc = (WNDPROC)SetWindowLongPtrA(lbox, GWLP_WNDPROC, 7500 (ULONG_PTR)combobox_lbox_subclass_proc); 7501 flush_sequence(); 7502 7503 log_all_parent_messages++; 7504 SendMessageA(combo, CB_SETCURSEL, 0, 0); 7505 log_all_parent_messages--; 7506 ok_sequence(SetCurSelComboSeq, "CB_SETCURSEL on a ComboBox", FALSE); 7507 7508 ShowWindow(combo, SW_HIDE); 7509 flush_sequence(); 7510 log_all_parent_messages++; 7511 SendMessageA(combo, CB_SETCURSEL, 0, 0); 7512 log_all_parent_messages--; 7513 ok_sequence(SetCurSelComboSeq2, "CB_SETCURSEL on a ComboBox", FALSE); 7514 7515 DestroyWindow(combo); 7516 DestroyWindow(parent); 7517 } 7518 7519 /****************** WM_IME_KEYDOWN message test *******************/ 7520 7521 static const struct message WmImeKeydownMsgSeq_0[] = 7522 { 7523 { WM_IME_KEYDOWN, wparam, VK_RETURN }, 7524 { WM_CHAR, wparam, 'A' }, 7525 { 0 } 7526 }; 7527 7528 static const struct message WmImeKeydownMsgSeq_1[] = 7529 { 7530 { WM_KEYDOWN, optional|wparam, VK_RETURN }, 7531 { WM_CHAR, optional|wparam, VK_RETURN }, 7532 { 0 } 7533 }; 7534 7535 static LRESULT WINAPI wmime_keydown_procA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 7536 { 7537 struct recvd_message msg; 7538 7539 msg.hwnd = hwnd; 7540 msg.message = message; 7541 msg.flags = wparam|lparam; 7542 msg.wParam = wParam; 7543 msg.lParam = lParam; 7544 msg.descr = "wmime_keydown"; 7545 add_message(&msg); 7546 7547 return DefWindowProcA(hwnd, message, wParam, lParam); 7548 } 7549 7550 static void register_wmime_keydown_class(void) 7551 { 7552 WNDCLASSA cls; 7553 7554 ZeroMemory(&cls, sizeof(WNDCLASSA)); 7555 cls.lpfnWndProc = wmime_keydown_procA; 7556 cls.hInstance = GetModuleHandleA(0); 7557 cls.lpszClassName = "wmime_keydown_class"; 7558 if (!RegisterClassA(&cls)) assert(0); 7559 } 7560 7561 static void test_wmime_keydown_message(void) 7562 { 7563 HWND hwnd; 7564 MSG msg; 7565 7566 trace("Message sequences by WM_IME_KEYDOWN\n"); 7567 7568 register_wmime_keydown_class(); 7569 hwnd = CreateWindowExA(0, "wmime_keydown_class", NULL, WS_OVERLAPPEDWINDOW, 7570 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0, 7571 NULL, NULL, 0); 7572 flush_events(); 7573 flush_sequence(); 7574 7575 SendMessageA(hwnd, WM_IME_KEYDOWN, VK_RETURN, 0x1c0001); 7576 SendMessageA(hwnd, WM_CHAR, 'A', 1); 7577 ok_sequence(WmImeKeydownMsgSeq_0, "WM_IME_KEYDOWN 0", FALSE); 7578 7579 while ( PeekMessageA(&msg, 0, 0, 0, PM_REMOVE) ) 7580 { 7581 TranslateMessage(&msg); 7582 DispatchMessageA(&msg); 7583 } 7584 ok_sequence(WmImeKeydownMsgSeq_1, "WM_IME_KEYDOWN 1", FALSE); 7585 7586 DestroyWindow(hwnd); 7587 } 7588 7589 /************* painting message test ********************/ 7590 7591 void dump_region(HRGN hrgn) 7592 { 7593 DWORD i, size; 7594 RGNDATA *data = NULL; 7595 RECT *rect; 7596 7597 if (!hrgn) 7598 { 7599 printf( "null region\n" ); 7600 return; 7601 } 7602 if (!(size = GetRegionData( hrgn, 0, NULL ))) return; 7603 if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return; 7604 GetRegionData( hrgn, size, data ); 7605 printf("%d rects:", data->rdh.nCount ); 7606 for (i = 0, rect = (RECT *)data->Buffer; i < data->rdh.nCount; i++, rect++) 7607 printf( " %s", wine_dbgstr_rect( rect )); 7608 printf("\n"); 7609 HeapFree( GetProcessHeap(), 0, data ); 7610 } 7611 7612 static void check_update_rgn( HWND hwnd, HRGN hrgn ) 7613 { 7614 INT ret; 7615 RECT r1, r2; 7616 HRGN tmp = CreateRectRgn( 0, 0, 0, 0 ); 7617 HRGN update = CreateRectRgn( 0, 0, 0, 0 ); 7618 7619 ret = GetUpdateRgn( hwnd, update, FALSE ); 7620 ok( ret != ERROR, "GetUpdateRgn failed\n" ); 7621 if (ret == NULLREGION) 7622 { 7623 ok( !hrgn, "Update region shouldn't be empty\n" ); 7624 } 7625 else 7626 { 7627 if (CombineRgn( tmp, hrgn, update, RGN_XOR ) != NULLREGION) 7628 { 7629 ok( 0, "Regions are different\n" ); 7630 if (winetest_debug > 0) 7631 { 7632 printf( "Update region: " ); 7633 dump_region( update ); 7634 printf( "Wanted region: " ); 7635 dump_region( hrgn ); 7636 } 7637 } 7638 } 7639 GetRgnBox( update, &r1 ); 7640 GetUpdateRect( hwnd, &r2, FALSE ); 7641 ok( EqualRect( &r1, &r2 ), "Rectangles are different: %s / %s\n", wine_dbgstr_rect( &r1 ), 7642 wine_dbgstr_rect( &r2 )); 7643 7644 DeleteObject( tmp ); 7645 DeleteObject( update ); 7646 } 7647 7648 static const struct message WmInvalidateRgn[] = { 7649 { WM_NCPAINT, sent }, 7650 { WM_GETTEXT, sent|defwinproc|optional }, 7651 { 0 } 7652 }; 7653 7654 static const struct message WmGetUpdateRect[] = { 7655 { WM_NCPAINT, sent }, 7656 { WM_GETTEXT, sent|defwinproc|optional }, 7657 { WM_PAINT, sent }, 7658 { 0 } 7659 }; 7660 7661 static const struct message WmInvalidateFull[] = { 7662 { WM_NCPAINT, sent|wparam, 1 }, 7663 { WM_GETTEXT, sent|defwinproc|optional }, 7664 { 0 } 7665 }; 7666 7667 static const struct message WmInvalidateErase[] = { 7668 { WM_NCPAINT, sent|wparam, 1 }, 7669 { WM_GETTEXT, sent|defwinproc|optional }, 7670 { WM_ERASEBKGND, sent }, 7671 { 0 } 7672 }; 7673 7674 static const struct message WmInvalidatePaint[] = { 7675 { WM_PAINT, sent }, 7676 { WM_NCPAINT, sent|wparam|beginpaint, 1 }, 7677 { WM_GETTEXT, sent|beginpaint|defwinproc|optional }, 7678 { 0 } 7679 }; 7680 7681 static const struct message WmInvalidateErasePaint[] = { 7682 { WM_PAINT, sent }, 7683 { WM_NCPAINT, sent|wparam|beginpaint, 1 }, 7684 { WM_GETTEXT, sent|beginpaint|defwinproc|optional }, 7685 { WM_ERASEBKGND, sent|beginpaint|optional }, 7686 { 0 } 7687 }; 7688 7689 static const struct message WmInvalidateErasePaint2[] = { 7690 { WM_PAINT, sent }, 7691 { WM_NCPAINT, sent|beginpaint }, 7692 { WM_GETTEXT, sent|beginpaint|defwinproc|optional }, 7693 { WM_ERASEBKGND, sent|beginpaint|optional }, 7694 { 0 } 7695 }; 7696 7697 static const struct message WmErase[] = { 7698 { WM_ERASEBKGND, sent }, 7699 { 0 } 7700 }; 7701 7702 static const struct message WmPaint[] = { 7703 { WM_PAINT, sent }, 7704 { 0 } 7705 }; 7706 7707 static const struct message WmParentOnlyPaint[] = { 7708 { WM_PAINT, sent|parent }, 7709 { 0 } 7710 }; 7711 7712 static const struct message WmInvalidateParent[] = { 7713 { WM_NCPAINT, sent|parent }, 7714 { WM_GETTEXT, sent|defwinproc|parent|optional }, 7715 { WM_ERASEBKGND, sent|parent }, 7716 { 0 } 7717 }; 7718 7719 static const struct message WmInvalidateParentChild[] = { 7720 { WM_NCPAINT, sent|parent }, 7721 { WM_GETTEXT, sent|defwinproc|parent|optional }, 7722 { WM_ERASEBKGND, sent|parent }, 7723 { WM_NCPAINT, sent }, 7724 { WM_GETTEXT, sent|defwinproc|optional }, 7725 { WM_ERASEBKGND, sent }, 7726 { 0 } 7727 }; 7728 7729 static const struct message WmInvalidateParentChild2[] = { 7730 { WM_ERASEBKGND, sent|parent }, 7731 { WM_NCPAINT, sent }, 7732 { WM_GETTEXT, sent|defwinproc|optional }, 7733 { WM_ERASEBKGND, sent }, 7734 { 0 } 7735 }; 7736 7737 static const struct message WmParentPaint[] = { 7738 { WM_PAINT, sent|parent }, 7739 { WM_PAINT, sent }, 7740 { 0 } 7741 }; 7742 7743 static const struct message WmParentPaintNc[] = { 7744 { WM_PAINT, sent|parent }, 7745 { WM_PAINT, sent }, 7746 { WM_NCPAINT, sent|beginpaint }, 7747 { WM_GETTEXT, sent|beginpaint|defwinproc|optional }, 7748 { WM_ERASEBKGND, sent|beginpaint|optional }, 7749 { 0 } 7750 }; 7751 7752 static const struct message WmChildPaintNc[] = { 7753 { WM_PAINT, sent }, 7754 { WM_NCPAINT, sent|beginpaint }, 7755 { WM_GETTEXT, sent|beginpaint|defwinproc|optional }, 7756 { WM_ERASEBKGND, sent|beginpaint|optional }, 7757 { 0 } 7758 }; 7759 7760 static const struct message WmParentErasePaint[] = { 7761 { WM_PAINT, sent|parent }, 7762 { WM_NCPAINT, sent|parent|beginpaint }, 7763 { WM_GETTEXT, sent|parent|beginpaint|defwinproc|optional }, 7764 { WM_ERASEBKGND, sent|parent|beginpaint|optional }, 7765 { WM_PAINT, sent }, 7766 { WM_NCPAINT, sent|beginpaint }, 7767 { WM_GETTEXT, sent|beginpaint|defwinproc|optional }, 7768 { WM_ERASEBKGND, sent|beginpaint|optional }, 7769 { 0 } 7770 }; 7771 7772 static const struct message WmParentOnlyNcPaint[] = { 7773 { WM_PAINT, sent|parent }, 7774 { WM_NCPAINT, sent|parent|beginpaint }, 7775 { WM_GETTEXT, sent|parent|beginpaint|defwinproc|optional }, 7776 { 0 } 7777 }; 7778 7779 static const struct message WmSetParentStyle[] = { 7780 { WM_STYLECHANGING, sent|parent }, 7781 { WM_STYLECHANGED, sent|parent }, 7782 { 0 } 7783 }; 7784 7785 static void test_paint_messages(void) 7786 { 7787 BOOL ret; 7788 RECT rect, rect2; 7789 POINT pt; 7790 MSG msg; 7791 HWND hparent, hchild; 7792 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 ); 7793 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 ); 7794 HWND hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW, 7795 100, 100, 200, 200, 0, 0, 0, NULL); 7796 ok (hwnd != 0, "Failed to create overlapped window\n"); 7797 7798 ShowWindow( hwnd, SW_SHOW ); 7799 UpdateWindow( hwnd ); 7800 flush_events(); 7801 flush_sequence(); 7802 7803 check_update_rgn( hwnd, 0 ); 7804 SetRectRgn( hrgn, 10, 10, 20, 20 ); 7805 ret = RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE ); 7806 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret); 7807 check_update_rgn( hwnd, hrgn ); 7808 SetRectRgn( hrgn2, 20, 20, 30, 30 ); 7809 ret = RedrawWindow( hwnd, NULL, hrgn2, RDW_INVALIDATE ); 7810 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret); 7811 CombineRgn( hrgn, hrgn, hrgn2, RGN_OR ); 7812 check_update_rgn( hwnd, hrgn ); 7813 /* validate everything */ 7814 ret = RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE ); 7815 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret); 7816 check_update_rgn( hwnd, 0 ); 7817 7818 /* test empty region */ 7819 SetRectRgn( hrgn, 10, 10, 10, 15 ); 7820 ret = RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE ); 7821 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret); 7822 check_update_rgn( hwnd, 0 ); 7823 /* test empty rect */ 7824 SetRect( &rect, 10, 10, 10, 15 ); 7825 ret = RedrawWindow( hwnd, &rect, NULL, RDW_INVALIDATE ); 7826 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret); 7827 check_update_rgn( hwnd, 0 ); 7828 7829 /* flush pending messages */ 7830 flush_events(); 7831 flush_sequence(); 7832 7833 GetClientRect( hwnd, &rect ); 7834 SetRectRgn( hrgn, 0, 0, rect.right - rect.left, rect.bottom - rect.top ); 7835 /* MSDN: if hwnd parameter is NULL, InvalidateRect invalidates and redraws 7836 * all windows and sends WM_ERASEBKGND and WM_NCPAINT. 7837 */ 7838 trace("testing InvalidateRect(0, NULL, FALSE)\n"); 7839 SetRectEmpty( &rect ); 7840 ok(InvalidateRect(0, &rect, FALSE), "InvalidateRect(0, &rc, FALSE) should fail\n"); 7841 check_update_rgn( hwnd, hrgn ); 7842 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE ); 7843 flush_events(); 7844 ok_sequence( WmPaint, "Paint", FALSE ); 7845 RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE ); 7846 check_update_rgn( hwnd, 0 ); 7847 7848 /* MSDN: if hwnd parameter is NULL, ValidateRect invalidates and redraws 7849 * all windows and sends WM_ERASEBKGND and WM_NCPAINT. 7850 */ 7851 trace("testing ValidateRect(0, NULL)\n"); 7852 SetRectEmpty( &rect ); 7853 if (ValidateRect(0, &rect) && /* not supported on Win9x */ 7854 GetUpdateRect(hwnd, NULL, FALSE)) /* or >= Win 8 */ 7855 { 7856 check_update_rgn( hwnd, hrgn ); 7857 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE ); 7858 flush_events(); 7859 ok_sequence( WmPaint, "Paint", FALSE ); 7860 RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE ); 7861 check_update_rgn( hwnd, 0 ); 7862 } 7863 7864 trace("testing InvalidateRgn(0, NULL, FALSE)\n"); 7865 SetLastError(0xdeadbeef); 7866 ok(!InvalidateRgn(0, NULL, FALSE), "InvalidateRgn(0, NULL, FALSE) should fail\n"); 7867 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || GetLastError() == 0xdeadbeef, 7868 "wrong error code %d\n", GetLastError()); 7869 check_update_rgn( hwnd, 0 ); 7870 flush_events(); 7871 ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE ); 7872 7873 trace("testing ValidateRgn(0, NULL)\n"); 7874 SetLastError(0xdeadbeef); 7875 ok(!ValidateRgn(0, NULL), "ValidateRgn(0, NULL) should fail\n"); 7876 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || 7877 broken( GetLastError() == 0xdeadbeef ) /* win9x */, 7878 "wrong error code %d\n", GetLastError()); 7879 check_update_rgn( hwnd, 0 ); 7880 flush_events(); 7881 ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE ); 7882 7883 trace("testing UpdateWindow(NULL)\n"); 7884 SetLastError(0xdeadbeef); 7885 ok(!UpdateWindow(NULL), "UpdateWindow(NULL) should fail\n"); 7886 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || 7887 broken( GetLastError() == 0xdeadbeef ) /* win9x */, 7888 "wrong error code %d\n", GetLastError()); 7889 check_update_rgn( hwnd, 0 ); 7890 flush_events(); 7891 ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE ); 7892 7893 /* now with frame */ 7894 SetRectRgn( hrgn, -5, -5, 20, 20 ); 7895 7896 /* flush pending messages */ 7897 flush_events(); 7898 flush_sequence(); 7899 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME ); 7900 ok_sequence( WmEmptySeq, "EmptySeq", FALSE ); 7901 7902 SetRectRgn( hrgn, 0, 0, 20, 20 ); /* GetUpdateRgn clips to client area */ 7903 check_update_rgn( hwnd, hrgn ); 7904 7905 flush_sequence(); 7906 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW ); 7907 ok_sequence( WmInvalidateRgn, "InvalidateRgn", FALSE ); 7908 7909 flush_sequence(); 7910 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW ); 7911 ok_sequence( WmInvalidateFull, "InvalidateFull", FALSE ); 7912 7913 GetClientRect( hwnd, &rect ); 7914 SetRectRgn( hrgn, rect.left, rect.top, rect.right, rect.bottom ); 7915 check_update_rgn( hwnd, hrgn ); 7916 7917 flush_sequence(); 7918 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW ); 7919 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE ); 7920 7921 flush_sequence(); 7922 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW | RDW_UPDATENOW ); 7923 ok_sequence( WmInvalidatePaint, "InvalidatePaint", FALSE ); 7924 check_update_rgn( hwnd, 0 ); 7925 7926 flush_sequence(); 7927 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_UPDATENOW ); 7928 ok_sequence( WmInvalidateErasePaint, "InvalidateErasePaint", FALSE ); 7929 check_update_rgn( hwnd, 0 ); 7930 7931 flush_sequence(); 7932 SetRectRgn( hrgn, 0, 0, 100, 100 ); 7933 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE ); 7934 SetRectRgn( hrgn, 0, 0, 50, 100 ); 7935 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE ); 7936 SetRectRgn( hrgn, 50, 0, 100, 100 ); 7937 check_update_rgn( hwnd, hrgn ); 7938 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_ERASENOW ); 7939 ok_sequence( WmEmptySeq, "EmptySeq", FALSE ); /* must not generate messages, everything is valid */ 7940 check_update_rgn( hwnd, 0 ); 7941 7942 flush_sequence(); 7943 SetRectRgn( hrgn, 0, 0, 100, 100 ); 7944 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE ); 7945 SetRectRgn( hrgn, 0, 0, 100, 50 ); 7946 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_ERASENOW ); 7947 ok_sequence( WmErase, "Erase", FALSE ); 7948 SetRectRgn( hrgn, 0, 50, 100, 100 ); 7949 check_update_rgn( hwnd, hrgn ); 7950 7951 flush_sequence(); 7952 SetRectRgn( hrgn, 0, 0, 100, 100 ); 7953 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE ); 7954 SetRectRgn( hrgn, 0, 0, 50, 50 ); 7955 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOERASE | RDW_UPDATENOW ); 7956 ok_sequence( WmPaint, "Paint", FALSE ); 7957 7958 flush_sequence(); 7959 SetRectRgn( hrgn, -4, -4, -2, -2 ); 7960 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME ); 7961 SetRectRgn( hrgn, -200, -200, -198, -198 ); 7962 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOFRAME | RDW_ERASENOW ); 7963 ok_sequence( WmEmptySeq, "EmptySeq", FALSE ); 7964 7965 flush_sequence(); 7966 SetRectRgn( hrgn, -4, -4, -2, -2 ); 7967 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME ); 7968 SetRectRgn( hrgn, -4, -4, -3, -3 ); 7969 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOFRAME ); 7970 SetRectRgn( hrgn, 0, 0, 1, 1 ); 7971 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_UPDATENOW ); 7972 ok_sequence( WmPaint, "Paint", FALSE ); 7973 7974 flush_sequence(); 7975 SetRectRgn( hrgn, -4, -4, -1, -1 ); 7976 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME ); 7977 RedrawWindow( hwnd, NULL, 0, RDW_ERASENOW ); 7978 /* make sure no WM_PAINT was generated */ 7979 flush_events(); 7980 ok_sequence( WmInvalidateRgn, "InvalidateRgn", FALSE ); 7981 7982 flush_sequence(); 7983 SetRectRgn( hrgn, -4, -4, -1, -1 ); 7984 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME ); 7985 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) 7986 { 7987 if (msg.hwnd == hwnd && msg.message == WM_PAINT) 7988 { 7989 /* GetUpdateRgn must return empty region since only nonclient area is invalidated */ 7990 INT ret = GetUpdateRgn( hwnd, hrgn, FALSE ); 7991 ok( ret == NULLREGION, "Invalid GetUpdateRgn result %d\n", ret ); 7992 ret = GetUpdateRect( hwnd, &rect, FALSE ); 7993 ok( ret, "Invalid GetUpdateRect result %d\n", ret ); 7994 /* this will send WM_NCPAINT and validate the non client area */ 7995 ret = GetUpdateRect( hwnd, &rect, TRUE ); 7996 ok( !ret, "Invalid GetUpdateRect result %d\n", ret ); 7997 } 7998 DispatchMessageA( &msg ); 7999 } 8000 ok_sequence( WmGetUpdateRect, "GetUpdateRect", FALSE ); 8001 8002 DestroyWindow( hwnd ); 8003 8004 /* now test with a child window */ 8005 8006 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW, 8007 100, 100, 200, 200, 0, 0, 0, NULL); 8008 ok (hparent != 0, "Failed to create parent window\n"); 8009 8010 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE | WS_BORDER, 8011 10, 10, 100, 100, hparent, 0, 0, NULL); 8012 ok (hchild != 0, "Failed to create child window\n"); 8013 8014 ShowWindow( hparent, SW_SHOW ); 8015 UpdateWindow( hparent ); 8016 UpdateWindow( hchild ); 8017 flush_events(); 8018 flush_sequence(); 8019 log_all_parent_messages++; 8020 8021 SetRect( &rect, 0, 0, 50, 50 ); 8022 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); 8023 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW | RDW_ALLCHILDREN ); 8024 ok_sequence( WmInvalidateParentChild, "InvalidateParentChild", FALSE ); 8025 8026 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); 8027 pt.x = pt.y = 0; 8028 MapWindowPoints( hchild, hparent, &pt, 1 ); 8029 SetRectRgn( hrgn, 0, 0, 50 - pt.x, 50 - pt.y ); 8030 check_update_rgn( hchild, hrgn ); 8031 SetRectRgn( hrgn, 0, 0, 50, 50 ); 8032 check_update_rgn( hparent, hrgn ); 8033 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW ); 8034 ok_sequence( WmInvalidateParent, "InvalidateParent", FALSE ); 8035 RedrawWindow( hchild, NULL, 0, RDW_ERASENOW ); 8036 ok_sequence( WmEmptySeq, "EraseNow child", FALSE ); 8037 8038 flush_events(); 8039 ok_sequence( WmParentPaintNc, "WmParentPaintNc", FALSE ); 8040 8041 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN ); 8042 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW ); 8043 ok_sequence( WmInvalidateParent, "InvalidateParent2", FALSE ); 8044 RedrawWindow( hchild, NULL, 0, RDW_ERASENOW ); 8045 ok_sequence( WmEmptySeq, "EraseNow child", FALSE ); 8046 8047 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE ); 8048 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW | RDW_ALLCHILDREN ); 8049 ok_sequence( WmInvalidateParentChild2, "InvalidateParentChild2", FALSE ); 8050 8051 SetWindowLongA( hparent, GWL_STYLE, GetWindowLongA(hparent,GWL_STYLE) | WS_CLIPCHILDREN ); 8052 flush_sequence(); 8053 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN ); 8054 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW ); 8055 ok_sequence( WmInvalidateParentChild, "InvalidateParentChild3", FALSE ); 8056 8057 /* flush all paint messages */ 8058 flush_events(); 8059 flush_sequence(); 8060 8061 /* RDW_UPDATENOW on child with WS_CLIPCHILDREN doesn't change corresponding parent area */ 8062 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN ); 8063 SetRectRgn( hrgn, 0, 0, 50, 50 ); 8064 check_update_rgn( hparent, hrgn ); 8065 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW ); 8066 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE ); 8067 SetRectRgn( hrgn, 0, 0, 50, 50 ); 8068 check_update_rgn( hparent, hrgn ); 8069 8070 /* flush all paint messages */ 8071 flush_events(); 8072 SetWindowLongA( hparent, GWL_STYLE, GetWindowLongA(hparent,GWL_STYLE) & ~WS_CLIPCHILDREN ); 8073 flush_sequence(); 8074 8075 /* RDW_UPDATENOW on child without WS_CLIPCHILDREN will validate corresponding parent area */ 8076 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); 8077 SetRectRgn( hrgn, 0, 0, 50, 50 ); 8078 check_update_rgn( hparent, hrgn ); 8079 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW ); 8080 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE ); 8081 SetRectRgn( hrgn2, 10, 10, 50, 50 ); 8082 CombineRgn( hrgn, hrgn, hrgn2, RGN_DIFF ); 8083 check_update_rgn( hparent, hrgn ); 8084 /* flush all paint messages */ 8085 flush_events(); 8086 flush_sequence(); 8087 8088 /* same as above but parent gets completely validated */ 8089 SetRect( &rect, 20, 20, 30, 30 ); 8090 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); 8091 SetRectRgn( hrgn, 20, 20, 30, 30 ); 8092 check_update_rgn( hparent, hrgn ); 8093 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW ); 8094 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE ); 8095 check_update_rgn( hparent, 0 ); /* no update region */ 8096 flush_events(); 8097 ok_sequence( WmEmptySeq, "WmEmpty", FALSE ); /* and no paint messages */ 8098 8099 /* make sure RDW_VALIDATE on child doesn't have the same effect */ 8100 flush_sequence(); 8101 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); 8102 SetRectRgn( hrgn, 20, 20, 30, 30 ); 8103 check_update_rgn( hparent, hrgn ); 8104 RedrawWindow( hchild, NULL, 0, RDW_VALIDATE | RDW_NOERASE ); 8105 SetRectRgn( hrgn, 20, 20, 30, 30 ); 8106 check_update_rgn( hparent, hrgn ); 8107 8108 /* same as above but normal WM_PAINT doesn't validate parent */ 8109 flush_sequence(); 8110 SetRect( &rect, 20, 20, 30, 30 ); 8111 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); 8112 SetRectRgn( hrgn, 20, 20, 30, 30 ); 8113 check_update_rgn( hparent, hrgn ); 8114 /* no WM_PAINT in child while parent still pending */ 8115 while (PeekMessageA( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 8116 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE ); 8117 while (PeekMessageA( &msg, hparent, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 8118 ok_sequence( WmParentErasePaint, "WmParentErasePaint", FALSE ); 8119 8120 flush_sequence(); 8121 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); 8122 /* no WM_PAINT in child while parent still pending */ 8123 while (PeekMessageA( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 8124 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE ); 8125 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_NOERASE | RDW_NOCHILDREN ); 8126 /* now that parent is valid child should get WM_PAINT */ 8127 while (PeekMessageA( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 8128 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE ); 8129 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 8130 ok_sequence( WmEmptySeq, "No other message", FALSE ); 8131 8132 /* same thing with WS_CLIPCHILDREN in parent */ 8133 flush_sequence(); 8134 SetWindowLongA( hparent, GWL_STYLE, GetWindowLongA(hparent,GWL_STYLE) | WS_CLIPCHILDREN ); 8135 ok_sequence( WmSetParentStyle, "WmSetParentStyle", FALSE ); 8136 /* changing style invalidates non client area, but we need to invalidate something else to see it */ 8137 RedrawWindow( hparent, &rect, 0, RDW_UPDATENOW ); 8138 ok_sequence( WmEmptySeq, "No message", FALSE ); 8139 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_UPDATENOW ); 8140 ok_sequence( WmParentOnlyNcPaint, "WmParentOnlyNcPaint", FALSE ); 8141 8142 flush_sequence(); 8143 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN ); 8144 SetRectRgn( hrgn, 20, 20, 30, 30 ); 8145 check_update_rgn( hparent, hrgn ); 8146 /* no WM_PAINT in child while parent still pending */ 8147 while (PeekMessageA( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 8148 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE ); 8149 /* WM_PAINT in parent first */ 8150 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 8151 ok_sequence( WmParentPaintNc, "WmParentPaintNc2", FALSE ); 8152 8153 /* no RDW_ERASE in parent still causes RDW_ERASE and RDW_FRAME in child */ 8154 flush_sequence(); 8155 SetRect( &rect, 0, 0, 30, 30 ); 8156 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ALLCHILDREN ); 8157 SetRectRgn( hrgn, 0, 0, 30, 30 ); 8158 check_update_rgn( hparent, hrgn ); 8159 flush_events(); 8160 ok_sequence( WmParentPaintNc, "WmParentPaintNc3", FALSE ); 8161 8162 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */ 8163 flush_sequence(); 8164 SetRect( &rect, -10, 0, 30, 30 ); 8165 RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE ); 8166 SetRect( &rect, 0, 0, 20, 20 ); 8167 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_ALLCHILDREN ); 8168 RedrawWindow( hparent, NULL, 0, RDW_UPDATENOW ); 8169 ok_sequence( WmChildPaintNc, "WmChildPaintNc", FALSE ); 8170 8171 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */ 8172 flush_sequence(); 8173 SetRect( &rect, -10, 0, 30, 30 ); 8174 RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE ); 8175 SetRect( &rect, 0, 0, 100, 100 ); 8176 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_ALLCHILDREN ); 8177 RedrawWindow( hparent, NULL, 0, RDW_UPDATENOW ); 8178 ok_sequence( WmEmptySeq, "WmChildPaintNc2", FALSE ); 8179 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW ); 8180 ok_sequence( WmEmptySeq, "WmChildPaintNc3", FALSE ); 8181 8182 /* WS_CLIPCHILDREN doesn't exclude children from update region */ 8183 flush_sequence(); 8184 RedrawWindow( hparent, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_NOCHILDREN ); 8185 GetClientRect( hparent, &rect ); 8186 SetRectRgn( hrgn, rect.left, rect.top, rect.right, rect.bottom ); 8187 check_update_rgn( hparent, hrgn ); 8188 flush_events(); 8189 8190 RedrawWindow( hparent, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN ); 8191 GetClientRect( hparent, &rect ); 8192 SetRectRgn( hrgn, rect.left, rect.top, rect.right, rect.bottom ); 8193 check_update_rgn( hparent, hrgn ); 8194 flush_events(); 8195 8196 /* test RDW_INTERNALPAINT behavior */ 8197 8198 flush_sequence(); 8199 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT | RDW_NOCHILDREN ); 8200 flush_events(); 8201 ok_sequence( WmParentOnlyPaint, "WmParentOnlyPaint", FALSE ); 8202 8203 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT | RDW_ALLCHILDREN ); 8204 flush_events(); 8205 ok_sequence( WmParentPaint, "WmParentPaint", FALSE ); 8206 8207 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT ); 8208 flush_events(); 8209 ok_sequence( WmParentOnlyPaint, "WmParentOnlyPaint", FALSE ); 8210 8211 assert( GetWindowLongA(hparent, GWL_STYLE) & WS_CLIPCHILDREN ); 8212 UpdateWindow( hparent ); 8213 flush_events(); 8214 flush_sequence(); 8215 trace("testing SWP_FRAMECHANGED on parent with WS_CLIPCHILDREN\n"); 8216 RedrawWindow( hchild, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); 8217 SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | 8218 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED ); 8219 flush_events(); 8220 ok_sequence(WmSWP_FrameChanged_clip, "SetWindowPos:FrameChanged_clip", FALSE ); 8221 8222 UpdateWindow( hparent ); 8223 flush_events(); 8224 flush_sequence(); 8225 trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent with WS_CLIPCHILDREN\n"); 8226 RedrawWindow( hchild, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); 8227 SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_DEFERERASE | 8228 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED ); 8229 flush_events(); 8230 ok_sequence(WmSWP_FrameChangedDeferErase, "SetWindowPos:FrameChangedDeferErase", FALSE ); 8231 8232 SetWindowLongA( hparent, GWL_STYLE, GetWindowLongA(hparent,GWL_STYLE) & ~WS_CLIPCHILDREN ); 8233 ok_sequence( WmSetParentStyle, "WmSetParentStyle", FALSE ); 8234 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT ); 8235 flush_events(); 8236 ok_sequence( WmParentPaint, "WmParentPaint", FALSE ); 8237 8238 assert( !(GetWindowLongA(hparent, GWL_STYLE) & WS_CLIPCHILDREN) ); 8239 UpdateWindow( hparent ); 8240 flush_events(); 8241 flush_sequence(); 8242 trace("testing SWP_FRAMECHANGED on parent without WS_CLIPCHILDREN\n"); 8243 RedrawWindow( hchild, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); 8244 SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | 8245 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED ); 8246 flush_events(); 8247 ok_sequence(WmSWP_FrameChanged_noclip, "SetWindowPos:FrameChanged_noclip", FALSE ); 8248 8249 UpdateWindow( hparent ); 8250 flush_events(); 8251 flush_sequence(); 8252 trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent without WS_CLIPCHILDREN\n"); 8253 RedrawWindow( hchild, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); 8254 SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_DEFERERASE | 8255 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED ); 8256 flush_events(); 8257 ok_sequence(WmSWP_FrameChangedDeferErase, "SetWindowPos:FrameChangedDeferErase", FALSE ); 8258 8259 ok(GetWindowLongA( hparent, GWL_STYLE ) & WS_VISIBLE, "parent should be visible\n"); 8260 ok(GetWindowLongA( hchild, GWL_STYLE ) & WS_VISIBLE, "child should be visible\n"); 8261 8262 UpdateWindow( hparent ); 8263 flush_events(); 8264 flush_sequence(); 8265 trace("testing SetWindowPos(-10000, -10000) on child\n"); 8266 SetWindowPos( hchild, 0, -10000, -10000, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER ); 8267 check_update_rgn( hchild, 0 ); 8268 flush_events(); 8269 8270 #if 0 /* this one doesn't pass under Wine yet */ 8271 UpdateWindow( hparent ); 8272 flush_events(); 8273 flush_sequence(); 8274 trace("testing ShowWindow(SW_MINIMIZE) on child\n"); 8275 ShowWindow( hchild, SW_MINIMIZE ); 8276 check_update_rgn( hchild, 0 ); 8277 flush_events(); 8278 #endif 8279 8280 UpdateWindow( hparent ); 8281 flush_events(); 8282 flush_sequence(); 8283 trace("testing SetWindowPos(-10000, -10000) on parent\n"); 8284 SetWindowPos( hparent, 0, -10000, -10000, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER ); 8285 check_update_rgn( hparent, 0 ); 8286 flush_events(); 8287 8288 log_all_parent_messages--; 8289 DestroyWindow( hparent ); 8290 ok(!IsWindow(hchild), "child must be destroyed with its parent\n"); 8291 8292 /* tests for moving windows off-screen (needs simple WS_POPUP windows) */ 8293 8294 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_POPUP | WS_VISIBLE, 8295 100, 100, 200, 200, 0, 0, 0, NULL); 8296 ok (hparent != 0, "Failed to create parent window\n"); 8297 8298 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE, 8299 10, 10, 100, 100, hparent, 0, 0, NULL); 8300 ok (hchild != 0, "Failed to create child window\n"); 8301 8302 ShowWindow( hparent, SW_SHOW ); 8303 UpdateWindow( hparent ); 8304 UpdateWindow( hchild ); 8305 flush_events(); 8306 flush_sequence(); 8307 8308 /* moving child outside of parent boundaries changes update region */ 8309 SetRect( &rect, 0, 0, 40, 40 ); 8310 RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_ERASE ); 8311 SetRectRgn( hrgn, 0, 0, 40, 40 ); 8312 check_update_rgn( hchild, hrgn ); 8313 MoveWindow( hchild, -10, 10, 100, 100, FALSE ); 8314 SetRectRgn( hrgn, 10, 0, 40, 40 ); 8315 check_update_rgn( hchild, hrgn ); 8316 MoveWindow( hchild, -10, -10, 100, 100, FALSE ); 8317 SetRectRgn( hrgn, 10, 10, 40, 40 ); 8318 check_update_rgn( hchild, hrgn ); 8319 8320 /* moving parent off-screen does too */ 8321 SetRect( &rect, 0, 0, 100, 100 ); 8322 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_NOCHILDREN ); 8323 SetRectRgn( hrgn, 0, 0, 100, 100 ); 8324 check_update_rgn( hparent, hrgn ); 8325 SetRectRgn( hrgn, 10, 10, 40, 40 ); 8326 check_update_rgn( hchild, hrgn ); 8327 MoveWindow( hparent, -20, -20, 200, 200, FALSE ); 8328 GetUpdateRect( hparent, &rect2, FALSE ); 8329 if (!EqualRect( &rect2, &rect )) /* Win 8 and later don't crop update to screen */ 8330 { 8331 rect.left += 20; 8332 rect.top += 20; 8333 } 8334 SetRectRgn( hrgn, rect.left, rect.top, rect.right, rect.bottom ); 8335 check_update_rgn( hparent, hrgn ); 8336 SetRectRgn( hrgn, rect.left + 10, rect.top + 10, 40, 40 ); 8337 check_update_rgn( hchild, hrgn ); 8338 8339 /* invalidated region is cropped by the parent rects */ 8340 SetRect( &rect, 0, 0, 50, 50 ); 8341 RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_ERASE ); 8342 SetRectRgn( hrgn, rect2.left + 10, rect2.top + 10, 50, 50 ); 8343 check_update_rgn( hchild, hrgn ); 8344 8345 DestroyWindow( hparent ); 8346 ok(!IsWindow(hchild), "child must be destroyed with its parent\n"); 8347 flush_sequence(); 8348 8349 DeleteObject( hrgn ); 8350 DeleteObject( hrgn2 ); 8351 } 8352 8353 struct wnd_event 8354 { 8355 HWND hwnd; 8356 HANDLE grand_child; 8357 HANDLE start_event; 8358 HANDLE stop_event; 8359 }; 8360 8361 static DWORD WINAPI thread_proc(void *param) 8362 { 8363 MSG msg; 8364 struct wnd_event *wnd_event = param; 8365 8366 wnd_event->hwnd = CreateWindowExA(0, "TestWindowClass", "window caption text", WS_OVERLAPPEDWINDOW, 8367 100, 100, 200, 200, 0, 0, 0, NULL); 8368 ok(wnd_event->hwnd != 0, "Failed to create overlapped window\n"); 8369 8370 SetEvent(wnd_event->start_event); 8371 8372 while (GetMessageA(&msg, 0, 0, 0)) 8373 { 8374 TranslateMessage(&msg); 8375 DispatchMessageA(&msg); 8376 } 8377 8378 ok(IsWindow(wnd_event->hwnd), "window should still exist\n"); 8379 8380 return 0; 8381 } 8382 8383 static DWORD CALLBACK create_grand_child_thread( void *param ) 8384 { 8385 struct wnd_event *wnd_event = param; 8386 HWND hchild; 8387 MSG msg; 8388 8389 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", 8390 WS_CHILD | WS_VISIBLE, 0, 0, 10, 10, wnd_event->hwnd, 0, 0, NULL); 8391 ok (hchild != 0, "Failed to create child window\n"); 8392 flush_events(); 8393 flush_sequence(); 8394 SetEvent( wnd_event->start_event ); 8395 8396 for (;;) 8397 { 8398 MsgWaitForMultipleObjects(0, NULL, FALSE, 1000, QS_ALLINPUT); 8399 if (!IsWindow( hchild )) break; /* will be destroyed when parent thread exits */ 8400 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 8401 } 8402 return 0; 8403 } 8404 8405 static DWORD CALLBACK create_child_thread( void *param ) 8406 { 8407 struct wnd_event *wnd_event = param; 8408 struct wnd_event child_event; 8409 DWORD ret, tid; 8410 MSG msg; 8411 8412 child_event.hwnd = CreateWindowExA(0, "TestWindowClass", "Test child", 8413 WS_CHILD | WS_VISIBLE, 0, 0, 10, 10, wnd_event->hwnd, 0, 0, NULL); 8414 ok (child_event.hwnd != 0, "Failed to create child window\n"); 8415 SetFocus( child_event.hwnd ); 8416 flush_events(); 8417 flush_sequence(); 8418 child_event.start_event = wnd_event->start_event; 8419 wnd_event->grand_child = CreateThread(NULL, 0, create_grand_child_thread, &child_event, 0, &tid); 8420 for (;;) 8421 { 8422 DWORD ret = MsgWaitForMultipleObjects(1, &child_event.start_event, FALSE, 1000, QS_SENDMESSAGE); 8423 if (ret != 1) break; 8424 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 8425 } 8426 ret = WaitForSingleObject( wnd_event->stop_event, 5000 ); 8427 ok( !ret, "WaitForSingleObject failed %x\n", ret ); 8428 return 0; 8429 } 8430 8431 static const char manifest_dep[] = 8432 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">" 8433 "<assemblyIdentity version=\"1.2.3.4\" name=\"testdep1\" type=\"win32\" processorArchitecture=\"" ARCH "\"/>" 8434 " <file name=\"testdep.dll\" />" 8435 "</assembly>"; 8436 8437 static const char manifest_main[] = 8438 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">" 8439 "<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\" />" 8440 "<dependency>" 8441 " <dependentAssembly>" 8442 " <assemblyIdentity type=\"win32\" name=\"testdep1\" version=\"1.2.3.4\" processorArchitecture=\"" ARCH "\" />" 8443 " </dependentAssembly>" 8444 "</dependency>" 8445 "</assembly>"; 8446 8447 static void create_manifest_file(const char *filename, const char *manifest) 8448 { 8449 WCHAR path[MAX_PATH]; 8450 HANDLE file; 8451 DWORD size; 8452 8453 MultiByteToWideChar( CP_ACP, 0, filename, -1, path, MAX_PATH ); 8454 file = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 8455 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError()); 8456 WriteFile(file, manifest, strlen(manifest), &size, NULL); 8457 CloseHandle(file); 8458 } 8459 8460 static HANDLE test_create(const char *file) 8461 { 8462 WCHAR path[MAX_PATH]; 8463 ACTCTXW actctx; 8464 HANDLE handle; 8465 8466 MultiByteToWideChar(CP_ACP, 0, file, -1, path, MAX_PATH); 8467 memset(&actctx, 0, sizeof(ACTCTXW)); 8468 actctx.cbSize = sizeof(ACTCTXW); 8469 actctx.lpSource = path; 8470 8471 handle = pCreateActCtxW(&actctx); 8472 ok(handle != INVALID_HANDLE_VALUE, "failed to create context, error %u\n", GetLastError()); 8473 8474 ok(actctx.cbSize == sizeof(actctx), "cbSize=%d\n", actctx.cbSize); 8475 ok(actctx.dwFlags == 0, "dwFlags=%d\n", actctx.dwFlags); 8476 ok(actctx.lpSource == path, "lpSource=%p\n", actctx.lpSource); 8477 ok(actctx.wProcessorArchitecture == 0, "wProcessorArchitecture=%d\n", actctx.wProcessorArchitecture); 8478 ok(actctx.wLangId == 0, "wLangId=%d\n", actctx.wLangId); 8479 ok(actctx.lpAssemblyDirectory == NULL, "lpAssemblyDirectory=%p\n", actctx.lpAssemblyDirectory); 8480 ok(actctx.lpResourceName == NULL, "lpResourceName=%p\n", actctx.lpResourceName); 8481 ok(actctx.lpApplicationName == NULL, "lpApplicationName=%p\n", actctx.lpApplicationName); 8482 ok(actctx.hModule == NULL, "hModule=%p\n", actctx.hModule); 8483 8484 return handle; 8485 } 8486 8487 static void test_interthread_messages(void) 8488 { 8489 HANDLE hThread, context, handle, event; 8490 ULONG_PTR cookie; 8491 DWORD tid; 8492 WNDPROC proc; 8493 MSG msg; 8494 char buf[256]; 8495 int len, expected_len; 8496 struct wnd_event wnd_event; 8497 BOOL ret; 8498 8499 wnd_event.start_event = CreateEventW(NULL, 0, 0, NULL); 8500 if (!wnd_event.start_event) 8501 { 8502 win_skip("skipping interthread message test under win9x\n"); 8503 return; 8504 } 8505 8506 hThread = CreateThread(NULL, 0, thread_proc, &wnd_event, 0, &tid); 8507 ok(hThread != NULL, "CreateThread failed, error %d\n", GetLastError()); 8508 8509 ok(WaitForSingleObject(wnd_event.start_event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 8510 8511 CloseHandle(wnd_event.start_event); 8512 8513 SetLastError(0xdeadbeef); 8514 ok(!DestroyWindow(wnd_event.hwnd), "DestroyWindow succeeded\n"); 8515 ok(GetLastError() == ERROR_ACCESS_DENIED || GetLastError() == 0xdeadbeef, 8516 "wrong error code %d\n", GetLastError()); 8517 8518 proc = (WNDPROC)GetWindowLongPtrA(wnd_event.hwnd, GWLP_WNDPROC); 8519 ok(proc != NULL, "GetWindowLongPtrA(GWLP_WNDPROC) error %d\n", GetLastError()); 8520 8521 expected_len = lstrlenA("window caption text"); 8522 memset(buf, 0, sizeof(buf)); 8523 SetLastError(0xdeadbeef); 8524 len = CallWindowProcA(proc, wnd_event.hwnd, WM_GETTEXT, sizeof(buf), (LPARAM)buf); 8525 ok(len == expected_len, "CallWindowProcA(WM_GETTEXT) error %d, len %d, expected len %d\n", GetLastError(), len, expected_len); 8526 ok(!lstrcmpA(buf, "window caption text"), "window text mismatch\n"); 8527 8528 msg.hwnd = wnd_event.hwnd; 8529 msg.message = WM_GETTEXT; 8530 msg.wParam = sizeof(buf); 8531 msg.lParam = (LPARAM)buf; 8532 memset(buf, 0, sizeof(buf)); 8533 SetLastError(0xdeadbeef); 8534 len = DispatchMessageA(&msg); 8535 ok((!len && GetLastError() == ERROR_MESSAGE_SYNC_ONLY) || broken(len), /* nt4 */ 8536 "DispatchMessageA(WM_GETTEXT) succeeded on another thread window: ret %d, error %d\n", len, GetLastError()); 8537 8538 /* the following test causes an exception in user.exe under win9x */ 8539 msg.hwnd = wnd_event.hwnd; 8540 msg.message = WM_TIMER; 8541 msg.wParam = 0; 8542 msg.lParam = GetWindowLongPtrA(wnd_event.hwnd, GWLP_WNDPROC); 8543 SetLastError(0xdeadbeef); 8544 len = DispatchMessageA(&msg); 8545 ok(!len && GetLastError() == 0xdeadbeef, 8546 "DispatchMessageA(WM_TIMER) failed on another thread window: ret %d, error %d\n", len, GetLastError()); 8547 8548 ret = PostMessageA(wnd_event.hwnd, WM_QUIT, 0, 0); 8549 ok( ret, "PostMessageA(WM_QUIT) error %d\n", GetLastError()); 8550 8551 ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 8552 CloseHandle(hThread); 8553 8554 ok(!IsWindow(wnd_event.hwnd), "window should be destroyed on thread exit\n"); 8555 8556 wnd_event.hwnd = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 8557 100, 100, 200, 200, 0, 0, 0, NULL); 8558 ok (wnd_event.hwnd != 0, "Failed to create parent window\n"); 8559 flush_events(); 8560 flush_sequence(); 8561 log_all_parent_messages++; 8562 wnd_event.start_event = CreateEventA( NULL, TRUE, FALSE, NULL ); 8563 wnd_event.stop_event = CreateEventA( NULL, TRUE, FALSE, NULL ); 8564 hThread = CreateThread( NULL, 0, create_child_thread, &wnd_event, 0, &tid ); 8565 for (;;) 8566 { 8567 ret = MsgWaitForMultipleObjects(1, &wnd_event.start_event, FALSE, 1000, QS_SENDMESSAGE); 8568 if (ret != 1) break; 8569 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 8570 } 8571 ok( !ret, "MsgWaitForMultipleObjects failed %x\n", ret ); 8572 /* now wait for the thread without processing messages; this shouldn't deadlock */ 8573 SetEvent( wnd_event.stop_event ); 8574 ret = WaitForSingleObject( hThread, 5000 ); 8575 ok( !ret, "WaitForSingleObject failed %x\n", ret ); 8576 CloseHandle( hThread ); 8577 8578 ret = WaitForSingleObject( wnd_event.grand_child, 5000 ); 8579 ok( !ret, "WaitForSingleObject failed %x\n", ret ); 8580 CloseHandle( wnd_event.grand_child ); 8581 8582 CloseHandle( wnd_event.start_event ); 8583 CloseHandle( wnd_event.stop_event ); 8584 flush_events(); 8585 ok_sequence(WmExitThreadSeq, "destroy child on thread exit", FALSE); 8586 log_all_parent_messages--; 8587 DestroyWindow( wnd_event.hwnd ); 8588 8589 /* activation context tests */ 8590 if (!pActivateActCtx) 8591 { 8592 win_skip("Activation contexts are not supported, skipping\n"); 8593 return; 8594 } 8595 8596 create_manifest_file("testdep1.manifest", manifest_dep); 8597 create_manifest_file("main.manifest", manifest_main); 8598 8599 context = test_create("main.manifest"); 8600 DeleteFileA("testdep1.manifest"); 8601 DeleteFileA("main.manifest"); 8602 8603 handle = (void*)0xdeadbeef; 8604 ret = pGetCurrentActCtx(&handle); 8605 ok(ret, "GetCurrentActCtx failed: %u\n", GetLastError()); 8606 ok(handle == 0, "active context %p\n", handle); 8607 8608 wnd_event.start_event = CreateEventW(NULL, 0, 0, NULL); 8609 hThread = CreateThread(NULL, 0, thread_proc, &wnd_event, 0, &tid); 8610 ok(hThread != NULL, "CreateThread failed, error %d\n", GetLastError()); 8611 ok(WaitForSingleObject(wnd_event.start_event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 8612 CloseHandle(wnd_event.start_event); 8613 8614 /* context is activated after thread creation, so it doesn't inherit it by default */ 8615 ret = pActivateActCtx(context, &cookie); 8616 ok(ret, "activation failed: %u\n", GetLastError()); 8617 8618 handle = 0; 8619 ret = pGetCurrentActCtx(&handle); 8620 ok(ret, "GetCurrentActCtx failed: %u\n", GetLastError()); 8621 ok(handle != 0, "active context %p\n", handle); 8622 pReleaseActCtx(handle); 8623 8624 /* destination window will test for active context */ 8625 ret = SendMessageA(wnd_event.hwnd, WM_USER+10, 0, 0); 8626 ok(ret, "thread window returned %d\n", ret); 8627 8628 event = CreateEventW(NULL, 0, 0, NULL); 8629 ret = PostMessageA(wnd_event.hwnd, WM_USER+10, 0, (LPARAM)event); 8630 ok(ret, "thread window returned %d\n", ret); 8631 ok(WaitForSingleObject(event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 8632 CloseHandle(event); 8633 8634 ret = PostMessageA(wnd_event.hwnd, WM_QUIT, 0, 0); 8635 ok(ret, "PostMessageA(WM_QUIT) error %d\n", GetLastError()); 8636 8637 ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 8638 CloseHandle(hThread); 8639 8640 ret = pDeactivateActCtx(0, cookie); 8641 ok(ret, "DeactivateActCtx failed: %u\n", GetLastError()); 8642 pReleaseActCtx(context); 8643 } 8644 8645 8646 static const struct message WmVkN[] = { 8647 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */ 8648 { WM_KEYDOWN, wparam|lparam, 'N', 1 }, 8649 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 }, 8650 { WM_CHAR, wparam|lparam, 'n', 1 }, 8651 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1002,1), 0 }, 8652 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */ 8653 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 }, 8654 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 }, 8655 { 0 } 8656 }; 8657 static const struct message WmShiftVkN[] = { 8658 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 1 }, /* XP */ 8659 { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 1 }, 8660 { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 1 }, 8661 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */ 8662 { WM_KEYDOWN, wparam|lparam, 'N', 1 }, 8663 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 }, 8664 { WM_CHAR, wparam|lparam, 'N', 1 }, 8665 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1001,1), 0 }, 8666 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */ 8667 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 }, 8668 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 }, 8669 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0xc0000001 }, /* XP */ 8670 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xc0000001 }, 8671 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xc0000001 }, 8672 { 0 } 8673 }; 8674 static const struct message WmCtrlVkN[] = { 8675 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 1 }, /* XP */ 8676 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 }, 8677 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 }, 8678 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */ 8679 { WM_KEYDOWN, wparam|lparam, 'N', 1 }, 8680 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 }, 8681 { WM_CHAR, wparam|lparam, 0x000e, 1 }, 8682 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1000,1), 0 }, 8683 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */ 8684 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 }, 8685 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 }, 8686 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 0xc0000001 }, /* XP */ 8687 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 }, 8688 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 }, 8689 { 0 } 8690 }; 8691 static const struct message WmCtrlVkN_2[] = { 8692 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 1 }, /* XP */ 8693 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 }, 8694 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 }, 8695 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */ 8696 { WM_KEYDOWN, wparam|lparam, 'N', 1 }, 8697 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1000,1), 0 }, 8698 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */ 8699 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 }, 8700 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 }, 8701 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 0xc0000001 }, /* XP */ 8702 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 }, 8703 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 }, 8704 { 0 } 8705 }; 8706 static const struct message WmAltVkN[] = { 8707 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, /* XP */ 8708 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 }, 8709 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, 8710 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0x20000001 }, /* XP */ 8711 { WM_SYSKEYDOWN, wparam|lparam, 'N', 0x20000001 }, 8712 { WM_SYSKEYDOWN, sent|wparam|lparam, 'N', 0x20000001 }, 8713 { WM_SYSCHAR, wparam|lparam, 'n', 0x20000001 }, 8714 { WM_SYSCHAR, sent|wparam|lparam, 'n', 0x20000001 }, 8715 { WM_SYSCOMMAND, sent|defwinproc|wparam|lparam, SC_KEYMENU, 'n' }, 8716 { HCBT_SYSCOMMAND, hook }, 8717 { WM_ENTERMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 }, 8718 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, 8719 { 0x00AE, sent|defwinproc|optional }, /* XP */ 8720 { WM_GETTEXT, sent|defwinproc|optional }, /* XP */ 8721 { WM_INITMENU, sent|defwinproc }, 8722 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 }, 8723 { WM_MENUCHAR, sent|defwinproc|wparam, MAKEWPARAM('n',MF_SYSMENU) }, 8724 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, 8725 { WM_CAPTURECHANGED, sent|defwinproc }, 8726 { WM_MENUSELECT, sent|defwinproc|wparam, MAKEWPARAM(0,0xffff) }, 8727 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 }, 8728 { WM_EXITMENULOOP, sent|defwinproc }, 8729 { WM_MENUSELECT, sent|defwinproc|wparam|optional, MAKEWPARAM(0,0xffff) }, /* Win95 bug */ 8730 { WM_EXITMENULOOP, sent|defwinproc|optional }, /* Win95 bug */ 8731 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xe0000001 }, /* XP */ 8732 { WM_SYSKEYUP, wparam|lparam, 'N', 0xe0000001 }, 8733 { WM_SYSKEYUP, sent|wparam|lparam, 'N', 0xe0000001 }, 8734 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */ 8735 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 }, 8736 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 }, 8737 { 0 } 8738 }; 8739 static const struct message WmAltVkN_2[] = { 8740 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, /* XP */ 8741 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 }, 8742 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, 8743 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0x20000001 }, /* XP */ 8744 { WM_SYSKEYDOWN, wparam|lparam, 'N', 0x20000001 }, 8745 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1003,1), 0 }, 8746 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xe0000001 }, /* XP */ 8747 { WM_SYSKEYUP, wparam|lparam, 'N', 0xe0000001 }, 8748 { WM_SYSKEYUP, sent|wparam|lparam, 'N', 0xe0000001 }, 8749 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */ 8750 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 }, 8751 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 }, 8752 { 0 } 8753 }; 8754 static const struct message WmCtrlAltVkN[] = { 8755 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 1 }, /* XP */ 8756 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 }, 8757 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 }, 8758 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, /* XP */ 8759 { WM_KEYDOWN, wparam|lparam, VK_MENU, 0x20000001 }, 8760 { WM_KEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, 8761 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0x20000001 }, /* XP */ 8762 { WM_KEYDOWN, wparam|lparam, 'N', 0x20000001 }, 8763 { WM_KEYDOWN, sent|wparam|lparam, 'N', 0x20000001 }, 8764 { WM_CHAR, optional }, 8765 { WM_CHAR, sent|optional }, 8766 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xe0000001 }, /* XP */ 8767 { WM_KEYUP, wparam|lparam, 'N', 0xe0000001 }, 8768 { WM_KEYUP, sent|wparam|lparam, 'N', 0xe0000001 }, 8769 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */ 8770 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 }, 8771 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 }, 8772 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 0xc0000001 }, /* XP */ 8773 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 }, 8774 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 }, 8775 { 0 } 8776 }; 8777 static const struct message WmCtrlShiftVkN[] = { 8778 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 1 }, /* XP */ 8779 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 }, 8780 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 }, 8781 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 1 }, /* XP */ 8782 { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 1 }, 8783 { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 1 }, 8784 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */ 8785 { WM_KEYDOWN, wparam|lparam, 'N', 1 }, 8786 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1004,1), 0 }, 8787 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */ 8788 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 }, 8789 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 }, 8790 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0xc0000001 }, /* XP */ 8791 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xc0000001 }, 8792 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xc0000001 }, 8793 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 0xc0000001 }, /* XP */ 8794 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 }, 8795 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 }, 8796 { 0 } 8797 }; 8798 static const struct message WmCtrlAltShiftVkN[] = { 8799 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 1 }, /* XP */ 8800 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 }, 8801 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 }, 8802 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, /* XP */ 8803 { WM_KEYDOWN, wparam|lparam, VK_MENU, 0x20000001 }, 8804 { WM_KEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, 8805 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0x20000001 }, /* XP */ 8806 { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 0x20000001 }, 8807 { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 0x20000001 }, 8808 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0x20000001 }, /* XP */ 8809 { WM_KEYDOWN, wparam|lparam, 'N', 0x20000001 }, 8810 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1005,1), 0 }, 8811 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xe0000001 }, /* XP */ 8812 { WM_KEYUP, wparam|lparam, 'N', 0xe0000001 }, 8813 { WM_KEYUP, sent|wparam|lparam, 'N', 0xe0000001 }, 8814 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0xe0000001 }, /* XP */ 8815 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xe0000001 }, 8816 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xe0000001 }, 8817 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */ 8818 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 }, 8819 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 }, 8820 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 0xc0000001 }, /* XP */ 8821 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 }, 8822 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 }, 8823 { 0 } 8824 }; 8825 static const struct message WmAltPressRelease[] = { 8826 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, /* XP */ 8827 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 }, 8828 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, 8829 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */ 8830 { WM_SYSKEYUP, wparam|lparam, VK_MENU, 0xc0000001 }, 8831 { WM_SYSKEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 }, 8832 { WM_SYSCOMMAND, sent|defwinproc|wparam|lparam, SC_KEYMENU, 0 }, 8833 { HCBT_SYSCOMMAND, hook }, 8834 { WM_ENTERMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 }, 8835 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, 8836 { WM_INITMENU, sent|defwinproc }, 8837 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 }, 8838 { WM_MENUSELECT, sent|defwinproc|wparam, MAKEWPARAM(0,MF_SYSMENU|MF_POPUP|MF_HILITE), 0, MAKEWPARAM(0,MF_RIGHTJUSTIFY) }, 8839 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 }, 8840 8841 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x30000001 }, /* XP */ 8842 8843 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 }, 8844 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0, }, 8845 { WM_CAPTURECHANGED, sent|defwinproc }, 8846 { WM_MENUSELECT, sent|defwinproc|wparam|optional, MAKEWPARAM(0,0xffff) }, 8847 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 }, 8848 { WM_EXITMENULOOP, sent|defwinproc }, 8849 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */ 8850 { WM_SYSKEYUP, wparam|lparam, VK_MENU, 0xc0000001 }, 8851 { WM_SYSKEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 }, 8852 { 0 } 8853 }; 8854 static const struct message WmShiftMouseButton[] = { 8855 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 1 }, /* XP */ 8856 { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 1 }, 8857 { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 1 }, 8858 { WM_MOUSEMOVE, wparam|optional, 0, 0 }, 8859 { WM_MOUSEMOVE, sent|wparam|optional, 0, 0 }, 8860 { WM_LBUTTONDOWN, wparam, MK_LBUTTON|MK_SHIFT, 0 }, 8861 { WM_LBUTTONDOWN, sent|wparam, MK_LBUTTON|MK_SHIFT, 0 }, 8862 { WM_LBUTTONUP, wparam, MK_SHIFT, 0 }, 8863 { WM_LBUTTONUP, sent|wparam, MK_SHIFT, 0 }, 8864 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0xc0000001 }, /* XP */ 8865 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xc0000001 }, 8866 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xc0000001 }, 8867 { 0 } 8868 }; 8869 static const struct message WmF1Seq[] = { 8870 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F1, 1 }, /* XP */ 8871 { WM_KEYDOWN, wparam|lparam, VK_F1, 1 }, 8872 { WM_KEYDOWN, sent|wparam|lparam, VK_F1, 0x00000001 }, 8873 { WM_KEYF1, wparam|lparam, 0, 0 }, 8874 { WM_KEYF1, sent|wparam|lparam, 0, 0 }, 8875 { WM_HELP, sent|defwinproc }, 8876 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F1, 0xc0000001 }, /* XP */ 8877 { WM_KEYUP, wparam|lparam, VK_F1, 0xc0000001 }, 8878 { WM_KEYUP, sent|wparam|lparam, VK_F1, 0xc0000001 }, 8879 { 0 } 8880 }; 8881 static const struct message WmVkAppsSeq[] = { 8882 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_APPS, 1 }, /* XP */ 8883 { WM_KEYDOWN, wparam|lparam, VK_APPS, 1 }, 8884 { WM_KEYDOWN, sent|wparam|lparam, VK_APPS, 0x00000001 }, 8885 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_APPS, 0xc0000001 }, /* XP */ 8886 { WM_KEYUP, wparam|lparam, VK_APPS, 0xc0000001 }, 8887 { WM_KEYUP, sent|wparam|lparam, VK_APPS, 0xc0000001 }, 8888 { WM_CONTEXTMENU, lparam, /*hwnd*/0, -1 }, 8889 { WM_CONTEXTMENU, sent|lparam, /*hwnd*/0, -1 }, 8890 { 0 } 8891 }; 8892 static const struct message WmVkF10Seq[] = { 8893 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 1 }, /* XP */ 8894 { WM_SYSKEYDOWN, wparam|lparam, VK_F10, 1 }, 8895 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_F10, 0x00000001 }, 8896 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 0xc0000001 }, /* XP */ 8897 { WM_SYSKEYUP, wparam|lparam, VK_F10, 0xc0000001 }, 8898 { WM_SYSKEYUP, sent|wparam|lparam, VK_F10, 0xc0000001 }, 8899 { WM_SYSCOMMAND, sent|defwinproc|wparam, SC_KEYMENU }, 8900 { HCBT_SYSCOMMAND, hook }, 8901 { WM_ENTERMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 }, 8902 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, 8903 { WM_INITMENU, sent|defwinproc }, 8904 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 }, 8905 { WM_MENUSELECT, sent|defwinproc|wparam, MAKEWPARAM(0,MF_SYSMENU|MF_POPUP|MF_HILITE), 0, MAKEWPARAM(0,MF_RIGHTJUSTIFY) }, 8906 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 }, 8907 8908 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 0x10000001 }, /* XP */ 8909 8910 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 1 }, /* XP */ 8911 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 }, 8912 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0, }, 8913 { WM_CAPTURECHANGED, sent|defwinproc }, 8914 { WM_MENUSELECT, sent|defwinproc|wparam|optional, MAKEWPARAM(0,0xffff) }, 8915 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 }, 8916 { WM_EXITMENULOOP, sent|defwinproc }, 8917 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 0xc0000001 }, /* XP */ 8918 { WM_SYSKEYUP, wparam|lparam, VK_F10, 0xc0000001 }, 8919 { WM_SYSKEYUP, sent|wparam|lparam, VK_F10, 0xc0000001 }, 8920 { 0 } 8921 }; 8922 static const struct message WmShiftF10Seq[] = { 8923 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 1 }, /* XP */ 8924 { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 1 }, 8925 { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 0x00000001 }, 8926 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 1 }, /* XP */ 8927 { WM_SYSKEYDOWN, wparam|lparam, VK_F10, 1 }, 8928 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_F10, 0x00000001 }, 8929 { WM_CONTEXTMENU, sent|defwinproc|lparam, /*hwnd*/0, -1 }, 8930 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 0xc0000001 }, /* XP */ 8931 { WM_SYSKEYUP, wparam|lparam, VK_F10, 0xc0000001 }, 8932 { WM_SYSKEYUP, sent|wparam|lparam, VK_F10, 0xc0000001 }, 8933 { WM_SYSCOMMAND, sent|defwinproc|wparam, SC_KEYMENU }, 8934 { HCBT_SYSCOMMAND, hook }, 8935 { WM_ENTERMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 }, 8936 { WM_INITMENU, sent|defwinproc }, 8937 { WM_MENUSELECT, sent|defwinproc|wparam, MAKEWPARAM(0,MF_SYSMENU|MF_POPUP|MF_HILITE), 0, MAKEWPARAM(0,MF_RIGHTJUSTIFY) }, 8938 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0xd0000001 }, /* XP */ 8939 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_ESCAPE, 0x10000001 }, /* XP */ 8940 { WM_CAPTURECHANGED, sent|defwinproc|wparam|lparam, 0, 0 }, 8941 { WM_MENUSELECT, sent|defwinproc|wparam|lparam, 0xffff0000, 0 }, 8942 { WM_EXITMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 }, 8943 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_ESCAPE, 0xc0000001 }, /* XP */ 8944 { WM_KEYUP, wparam|lparam, VK_ESCAPE, 0xc0000001 }, 8945 { WM_KEYUP, sent|wparam|lparam, VK_ESCAPE, 0xc0000001 }, 8946 { 0 } 8947 }; 8948 8949 static void pump_msg_loop(HWND hwnd, HACCEL hAccel) 8950 { 8951 MSG msg; 8952 8953 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 8954 { 8955 struct recvd_message log_msg; 8956 8957 /* ignore some unwanted messages */ 8958 if (msg.message == WM_MOUSEMOVE || 8959 msg.message == WM_TIMER || 8960 ignore_message( msg.message )) 8961 continue; 8962 8963 log_msg.hwnd = msg.hwnd; 8964 log_msg.message = msg.message; 8965 log_msg.flags = wparam|lparam; 8966 log_msg.wParam = msg.wParam; 8967 log_msg.lParam = msg.lParam; 8968 log_msg.descr = "accel"; 8969 add_message(&log_msg); 8970 8971 if (!hAccel || !TranslateAcceleratorA(hwnd, hAccel, &msg)) 8972 { 8973 TranslateMessage(&msg); 8974 DispatchMessageA(&msg); 8975 } 8976 } 8977 } 8978 8979 static void test_accelerators(void) 8980 { 8981 RECT rc; 8982 POINT pt; 8983 SHORT state; 8984 HACCEL hAccel; 8985 HWND hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 8986 100, 100, 200, 200, 0, 0, 0, NULL); 8987 BOOL ret; 8988 8989 assert(hwnd != 0); 8990 UpdateWindow(hwnd); 8991 flush_events(); 8992 flush_sequence(); 8993 8994 SetFocus(hwnd); 8995 ok(GetFocus() == hwnd, "wrong focus window %p\n", GetFocus()); 8996 8997 state = GetKeyState(VK_SHIFT); 8998 ok(!(state & 0x8000), "wrong Shift state %04x\n", state); 8999 state = GetKeyState(VK_CAPITAL); 9000 ok(state == 0, "wrong CapsLock state %04x\n", state); 9001 9002 hAccel = LoadAcceleratorsA(GetModuleHandleA(NULL), MAKEINTRESOURCEA(1)); 9003 assert(hAccel != 0); 9004 9005 flush_events(); 9006 pump_msg_loop(hwnd, 0); 9007 flush_sequence(); 9008 9009 trace("testing VK_N press/release\n"); 9010 flush_sequence(); 9011 keybd_event('N', 0, 0, 0); 9012 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 9013 pump_msg_loop(hwnd, hAccel); 9014 if (!sequence_cnt) /* we didn't get any message */ 9015 { 9016 skip( "queuing key events not supported\n" ); 9017 goto done; 9018 } 9019 ok_sequence(WmVkN, "VK_N press/release", FALSE); 9020 9021 trace("testing Shift+VK_N press/release\n"); 9022 flush_sequence(); 9023 keybd_event(VK_SHIFT, 0, 0, 0); 9024 keybd_event('N', 0, 0, 0); 9025 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 9026 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0); 9027 pump_msg_loop(hwnd, hAccel); 9028 ok_sequence(WmShiftVkN, "Shift+VK_N press/release", FALSE); 9029 9030 trace("testing Ctrl+VK_N press/release\n"); 9031 flush_sequence(); 9032 keybd_event(VK_CONTROL, 0, 0, 0); 9033 keybd_event('N', 0, 0, 0); 9034 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 9035 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); 9036 pump_msg_loop(hwnd, hAccel); 9037 ok_sequence(WmCtrlVkN, "Ctrl+VK_N press/release", FALSE); 9038 9039 trace("testing Alt+VK_N press/release\n"); 9040 flush_sequence(); 9041 keybd_event(VK_MENU, 0, 0, 0); 9042 keybd_event('N', 0, 0, 0); 9043 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 9044 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); 9045 pump_msg_loop(hwnd, hAccel); 9046 ok_sequence(WmAltVkN, "Alt+VK_N press/release", FALSE); 9047 9048 trace("testing Ctrl+Alt+VK_N press/release 1\n"); 9049 flush_sequence(); 9050 keybd_event(VK_CONTROL, 0, 0, 0); 9051 keybd_event(VK_MENU, 0, 0, 0); 9052 keybd_event('N', 0, 0, 0); 9053 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 9054 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); 9055 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); 9056 pump_msg_loop(hwnd, hAccel); 9057 ok_sequence(WmCtrlAltVkN, "Ctrl+Alt+VK_N press/release 1", FALSE); 9058 9059 ret = DestroyAcceleratorTable(hAccel); 9060 ok( ret, "DestroyAcceleratorTable error %d\n", GetLastError()); 9061 9062 hAccel = LoadAcceleratorsA(GetModuleHandleA(NULL), MAKEINTRESOURCEA(2)); 9063 assert(hAccel != 0); 9064 9065 trace("testing VK_N press/release\n"); 9066 flush_sequence(); 9067 keybd_event('N', 0, 0, 0); 9068 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 9069 pump_msg_loop(hwnd, hAccel); 9070 ok_sequence(WmVkN, "VK_N press/release", FALSE); 9071 9072 trace("testing Shift+VK_N press/release\n"); 9073 flush_sequence(); 9074 keybd_event(VK_SHIFT, 0, 0, 0); 9075 keybd_event('N', 0, 0, 0); 9076 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 9077 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0); 9078 pump_msg_loop(hwnd, hAccel); 9079 ok_sequence(WmShiftVkN, "Shift+VK_N press/release", FALSE); 9080 9081 trace("testing Ctrl+VK_N press/release 2\n"); 9082 flush_sequence(); 9083 keybd_event(VK_CONTROL, 0, 0, 0); 9084 keybd_event('N', 0, 0, 0); 9085 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 9086 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); 9087 pump_msg_loop(hwnd, hAccel); 9088 ok_sequence(WmCtrlVkN_2, "Ctrl+VK_N press/release 2", FALSE); 9089 9090 trace("testing Alt+VK_N press/release 2\n"); 9091 flush_sequence(); 9092 keybd_event(VK_MENU, 0, 0, 0); 9093 keybd_event('N', 0, 0, 0); 9094 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 9095 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); 9096 pump_msg_loop(hwnd, hAccel); 9097 ok_sequence(WmAltVkN_2, "Alt+VK_N press/release 2", FALSE); 9098 9099 trace("testing Ctrl+Alt+VK_N press/release 2\n"); 9100 flush_sequence(); 9101 keybd_event(VK_CONTROL, 0, 0, 0); 9102 keybd_event(VK_MENU, 0, 0, 0); 9103 keybd_event('N', 0, 0, 0); 9104 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 9105 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); 9106 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); 9107 pump_msg_loop(hwnd, hAccel); 9108 ok_sequence(WmCtrlAltVkN, "Ctrl+Alt+VK_N press/release 2", FALSE); 9109 9110 trace("testing Ctrl+Shift+VK_N press/release\n"); 9111 flush_sequence(); 9112 keybd_event(VK_CONTROL, 0, 0, 0); 9113 keybd_event(VK_SHIFT, 0, 0, 0); 9114 keybd_event('N', 0, 0, 0); 9115 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 9116 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0); 9117 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); 9118 pump_msg_loop(hwnd, hAccel); 9119 ok_sequence(WmCtrlShiftVkN, "Ctrl+Shift+VK_N press/release", FALSE); 9120 9121 trace("testing Ctrl+Alt+Shift+VK_N press/release\n"); 9122 flush_sequence(); 9123 keybd_event(VK_CONTROL, 0, 0, 0); 9124 keybd_event(VK_MENU, 0, 0, 0); 9125 keybd_event(VK_SHIFT, 0, 0, 0); 9126 keybd_event('N', 0, 0, 0); 9127 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 9128 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0); 9129 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); 9130 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); 9131 pump_msg_loop(hwnd, hAccel); 9132 ok_sequence(WmCtrlAltShiftVkN, "Ctrl+Alt+Shift+VK_N press/release", FALSE); 9133 9134 ret = DestroyAcceleratorTable(hAccel); 9135 ok( ret, "DestroyAcceleratorTable error %d\n", GetLastError()); 9136 hAccel = 0; 9137 9138 trace("testing Alt press/release\n"); 9139 flush_sequence(); 9140 keybd_event(VK_MENU, 0, 0, 0); 9141 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); 9142 keybd_event(VK_MENU, 0, 0, 0); 9143 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); 9144 pump_msg_loop(hwnd, 0); 9145 /* this test doesn't pass in Wine for managed windows */ 9146 ok_sequence(WmAltPressRelease, "Alt press/release", TRUE); 9147 9148 trace("testing VK_F1 press/release\n"); 9149 keybd_event(VK_F1, 0, 0, 0); 9150 keybd_event(VK_F1, 0, KEYEVENTF_KEYUP, 0); 9151 pump_msg_loop(hwnd, 0); 9152 ok_sequence(WmF1Seq, "F1 press/release", FALSE); 9153 9154 trace("testing VK_APPS press/release\n"); 9155 keybd_event(VK_APPS, 0, 0, 0); 9156 keybd_event(VK_APPS, 0, KEYEVENTF_KEYUP, 0); 9157 pump_msg_loop(hwnd, 0); 9158 ok_sequence(WmVkAppsSeq, "VK_APPS press/release", FALSE); 9159 9160 trace("testing VK_F10 press/release\n"); 9161 keybd_event(VK_F10, 0, 0, 0); 9162 keybd_event(VK_F10, 0, KEYEVENTF_KEYUP, 0); 9163 keybd_event(VK_F10, 0, 0, 0); 9164 keybd_event(VK_F10, 0, KEYEVENTF_KEYUP, 0); 9165 pump_msg_loop(hwnd, 0); 9166 ok_sequence(WmVkF10Seq, "VK_F10 press/release", TRUE); 9167 9168 trace("testing SHIFT+F10 press/release\n"); 9169 keybd_event(VK_SHIFT, 0, 0, 0); 9170 keybd_event(VK_F10, 0, 0, 0); 9171 keybd_event(VK_F10, 0, KEYEVENTF_KEYUP, 0); 9172 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0); 9173 keybd_event(VK_ESCAPE, 0, 0, 0); 9174 keybd_event(VK_ESCAPE, 0, KEYEVENTF_KEYUP, 0); 9175 pump_msg_loop(hwnd, 0); 9176 ok_sequence(WmShiftF10Seq, "SHIFT+F10 press/release", TRUE); 9177 9178 trace("testing Shift+MouseButton press/release\n"); 9179 /* first, move mouse pointer inside of the window client area */ 9180 GetClientRect(hwnd, &rc); 9181 MapWindowPoints(hwnd, 0, (LPPOINT)&rc, 2); 9182 rc.left += (rc.right - rc.left)/2; 9183 rc.top += (rc.bottom - rc.top)/2; 9184 SetCursorPos(rc.left, rc.top); 9185 SetActiveWindow(hwnd); 9186 9187 flush_events(); 9188 flush_sequence(); 9189 GetCursorPos(&pt); 9190 if (pt.x == rc.left && pt.y == rc.top) 9191 { 9192 int i; 9193 keybd_event(VK_SHIFT, 0, 0, 0); 9194 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); 9195 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); 9196 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0); 9197 pump_msg_loop(hwnd, 0); 9198 for (i = 0; i < sequence_cnt; i++) if (sequence[i].message == WM_LBUTTONDOWN) break; 9199 if (i < sequence_cnt) 9200 ok_sequence(WmShiftMouseButton, "Shift+MouseButton press/release", FALSE); 9201 else 9202 skip( "Shift+MouseButton event didn't get to the window\n" ); 9203 } 9204 9205 done: 9206 if (hAccel) DestroyAcceleratorTable(hAccel); 9207 DestroyWindow(hwnd); 9208 } 9209 9210 /************* window procedures ********************/ 9211 9212 static LRESULT MsgCheckProc (BOOL unicode, HWND hwnd, UINT message, 9213 WPARAM wParam, LPARAM lParam) 9214 { 9215 static LONG defwndproc_counter = 0; 9216 static LONG beginpaint_counter = 0; 9217 LRESULT ret; 9218 struct recvd_message msg; 9219 9220 if (ignore_message( message )) return 0; 9221 9222 switch (message) 9223 { 9224 case WM_ENABLE: 9225 { 9226 LONG style = GetWindowLongA(hwnd, GWL_STYLE); 9227 ok((BOOL)wParam == !(style & WS_DISABLED), 9228 "wrong WS_DISABLED state: %ld != %d\n", wParam, !(style & WS_DISABLED)); 9229 break; 9230 } 9231 9232 case WM_CAPTURECHANGED: 9233 if (test_DestroyWindow_flag) 9234 { 9235 DWORD style = GetWindowLongA(hwnd, GWL_STYLE); 9236 if (style & WS_CHILD) 9237 lParam = GetWindowLongPtrA(hwnd, GWLP_ID); 9238 else if (style & WS_POPUP) 9239 lParam = WND_POPUP_ID; 9240 else 9241 lParam = WND_PARENT_ID; 9242 } 9243 break; 9244 9245 case WM_NCDESTROY: 9246 { 9247 HWND capture; 9248 9249 ok(!GetWindow(hwnd, GW_CHILD), "children should be unlinked at this point\n"); 9250 capture = GetCapture(); 9251 if (capture) 9252 { 9253 ok(capture == hwnd, "capture should NOT be released at this point (capture %p)\n", capture); 9254 trace("current capture %p, releasing...\n", capture); 9255 ReleaseCapture(); 9256 } 9257 } 9258 /* fall through */ 9259 case WM_DESTROY: 9260 if (pGetAncestor) 9261 ok(pGetAncestor(hwnd, GA_PARENT) != 0, "parent should NOT be unlinked at this point\n"); 9262 if (test_DestroyWindow_flag) 9263 { 9264 DWORD style = GetWindowLongA(hwnd, GWL_STYLE); 9265 if (style & WS_CHILD) 9266 lParam = GetWindowLongPtrA(hwnd, GWLP_ID); 9267 else if (style & WS_POPUP) 9268 lParam = WND_POPUP_ID; 9269 else 9270 lParam = WND_PARENT_ID; 9271 } 9272 break; 9273 9274 /* test_accelerators() depends on this */ 9275 case WM_NCHITTEST: 9276 return HTCLIENT; 9277 9278 case WM_USER+10: 9279 { 9280 ACTIVATION_CONTEXT_BASIC_INFORMATION basicinfo; 9281 HANDLE handle, event = (HANDLE)lParam; 9282 BOOL ret; 9283 9284 handle = (void*)0xdeadbeef; 9285 ret = pGetCurrentActCtx(&handle); 9286 ok(ret, "failed to get current context, %u\n", GetLastError()); 9287 ok(handle == 0, "got active context %p\n", handle); 9288 9289 memset(&basicinfo, 0xff, sizeof(basicinfo)); 9290 ret = pQueryActCtxW(QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX, handle, 0, ActivationContextBasicInformation, 9291 &basicinfo, sizeof(basicinfo), NULL); 9292 ok(ret, "got %d, error %d\n", ret, GetLastError()); 9293 ok(basicinfo.hActCtx == NULL, "got %p\n", basicinfo.hActCtx); 9294 ok(basicinfo.dwFlags == 0, "got %x\n", basicinfo.dwFlags); 9295 9296 if (event) SetEvent(event); 9297 return 1; 9298 } 9299 9300 /* ignore */ 9301 case WM_MOUSEMOVE: 9302 case WM_MOUSEACTIVATE: 9303 case WM_NCMOUSEMOVE: 9304 case WM_SETCURSOR: 9305 case WM_IME_SELECT: 9306 return 0; 9307 } 9308 9309 msg.hwnd = hwnd; 9310 msg.message = message; 9311 msg.flags = sent|wparam|lparam; 9312 if (defwndproc_counter) msg.flags |= defwinproc; 9313 if (beginpaint_counter) msg.flags |= beginpaint; 9314 msg.wParam = wParam; 9315 msg.lParam = lParam; 9316 msg.descr = "MsgCheckProc"; 9317 add_message(&msg); 9318 9319 if (message == WM_GETMINMAXINFO && (GetWindowLongA(hwnd, GWL_STYLE) & WS_CHILD)) 9320 { 9321 HWND parent = GetParent(hwnd); 9322 RECT rc; 9323 MINMAXINFO *minmax = (MINMAXINFO *)lParam; 9324 9325 GetClientRect(parent, &rc); 9326 trace("parent %p client size = (%d x %d)\n", parent, rc.right, rc.bottom); 9327 trace("Reserved=%d,%d MaxSize=%d,%d MaxPos=%d,%d MinTrack=%d,%d MaxTrack=%d,%d\n", 9328 minmax->ptReserved.x, minmax->ptReserved.y, 9329 minmax->ptMaxSize.x, minmax->ptMaxSize.y, 9330 minmax->ptMaxPosition.x, minmax->ptMaxPosition.y, 9331 minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y, 9332 minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y); 9333 9334 ok(minmax->ptMaxSize.x == rc.right, "default width of maximized child %d != %d\n", 9335 minmax->ptMaxSize.x, rc.right); 9336 ok(minmax->ptMaxSize.y == rc.bottom, "default height of maximized child %d != %d\n", 9337 minmax->ptMaxSize.y, rc.bottom); 9338 } 9339 9340 if (message == WM_PAINT) 9341 { 9342 PAINTSTRUCT ps; 9343 beginpaint_counter++; 9344 BeginPaint( hwnd, &ps ); 9345 beginpaint_counter--; 9346 EndPaint( hwnd, &ps ); 9347 return 0; 9348 } 9349 9350 if (message == WM_CONTEXTMENU) 9351 { 9352 /* don't create context menu */ 9353 return 0; 9354 } 9355 9356 defwndproc_counter++; 9357 ret = unicode ? DefWindowProcW(hwnd, message, wParam, lParam) 9358 : DefWindowProcA(hwnd, message, wParam, lParam); 9359 defwndproc_counter--; 9360 9361 return ret; 9362 } 9363 9364 static LRESULT WINAPI MsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 9365 { 9366 return MsgCheckProc (FALSE, hwnd, message, wParam, lParam); 9367 } 9368 9369 static LRESULT WINAPI MsgCheckProcW(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 9370 { 9371 return MsgCheckProc (TRUE, hwnd, message, wParam, lParam); 9372 } 9373 9374 static LRESULT WINAPI PopupMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 9375 { 9376 static LONG defwndproc_counter = 0; 9377 LRESULT ret; 9378 struct recvd_message msg; 9379 9380 if (ignore_message( message )) return 0; 9381 9382 switch (message) 9383 { 9384 case WM_QUERYENDSESSION: 9385 case WM_ENDSESSION: 9386 lParam &= ~0x01; /* Vista adds a 0x01 flag */ 9387 break; 9388 } 9389 9390 msg.hwnd = hwnd; 9391 msg.message = message; 9392 msg.flags = sent|wparam|lparam; 9393 if (defwndproc_counter) msg.flags |= defwinproc; 9394 msg.wParam = wParam; 9395 msg.lParam = lParam; 9396 msg.descr = "popup"; 9397 add_message(&msg); 9398 9399 if (message == WM_CREATE) 9400 { 9401 DWORD style = GetWindowLongA(hwnd, GWL_STYLE) | WS_VISIBLE; 9402 SetWindowLongA(hwnd, GWL_STYLE, style); 9403 } 9404 9405 defwndproc_counter++; 9406 ret = DefWindowProcA(hwnd, message, wParam, lParam); 9407 defwndproc_counter--; 9408 9409 return ret; 9410 } 9411 9412 static LRESULT WINAPI ParentMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 9413 { 9414 static LONG defwndproc_counter = 0; 9415 static LONG beginpaint_counter = 0; 9416 LRESULT ret; 9417 struct recvd_message msg; 9418 9419 if (ignore_message( message )) return 0; 9420 9421 if (log_all_parent_messages || 9422 message == WM_PARENTNOTIFY || message == WM_CANCELMODE || 9423 message == WM_SETFOCUS || message == WM_KILLFOCUS || 9424 message == WM_ENABLE || message == WM_ENTERIDLE || 9425 message == WM_DRAWITEM || message == WM_MEASUREITEM || message == WM_COMPAREITEM || 9426 message == WM_COMMAND || message == WM_IME_SETCONTEXT) 9427 { 9428 switch (message) 9429 { 9430 /* ignore */ 9431 case WM_NCHITTEST: 9432 return HTCLIENT; 9433 case WM_SETCURSOR: 9434 case WM_MOUSEMOVE: 9435 case WM_NCMOUSEMOVE: 9436 return 0; 9437 9438 case WM_ERASEBKGND: 9439 { 9440 RECT rc; 9441 INT ret = GetClipBox((HDC)wParam, &rc); 9442 9443 trace("WM_ERASEBKGND: GetClipBox()=%d, %s\n", ret, wine_dbgstr_rect(&rc)); 9444 break; 9445 } 9446 } 9447 9448 msg.hwnd = hwnd; 9449 msg.message = message; 9450 msg.flags = sent|parent|wparam|lparam; 9451 if (defwndproc_counter) msg.flags |= defwinproc; 9452 if (beginpaint_counter) msg.flags |= beginpaint; 9453 msg.wParam = wParam; 9454 msg.lParam = lParam; 9455 msg.descr = "parent"; 9456 add_message(&msg); 9457 } 9458 9459 if (message == WM_PAINT) 9460 { 9461 PAINTSTRUCT ps; 9462 beginpaint_counter++; 9463 BeginPaint( hwnd, &ps ); 9464 beginpaint_counter--; 9465 EndPaint( hwnd, &ps ); 9466 return 0; 9467 } 9468 9469 defwndproc_counter++; 9470 ret = DefWindowProcA(hwnd, message, wParam, lParam); 9471 defwndproc_counter--; 9472 9473 return message == WM_COMPAREITEM ? -1 : ret; 9474 } 9475 9476 static INT_PTR CALLBACK StopQuitMsgCheckProcA(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) 9477 { 9478 if (message == WM_CREATE) 9479 PostMessageA(hwnd, WM_CLOSE, 0, 0); 9480 else if (message == WM_CLOSE) 9481 { 9482 /* Only the first WM_QUIT will survive the window destruction */ 9483 PostMessageA(hwnd, WM_USER, 0x1234, 0x5678); 9484 PostMessageA(hwnd, WM_QUIT, 0x1234, 0x5678); 9485 PostMessageA(hwnd, WM_QUIT, 0x4321, 0x8765); 9486 } 9487 9488 return DefWindowProcA(hwnd, message, wp, lp); 9489 } 9490 9491 static LRESULT WINAPI TestDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 9492 { 9493 static LONG defwndproc_counter = 0; 9494 LRESULT ret; 9495 struct recvd_message msg; 9496 9497 if (ignore_message( message )) return 0; 9498 9499 if (test_def_id) 9500 { 9501 DefDlgProcA(hwnd, DM_SETDEFID, 1, 0); 9502 ret = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0); 9503 if (after_end_dialog) 9504 ok( ret == 0, "DM_GETDEFID should return 0 after EndDialog, got %lx\n", ret ); 9505 else 9506 ok(HIWORD(ret) == DC_HASDEFID, "DM_GETDEFID should return DC_HASDEFID, got %lx\n", ret); 9507 } 9508 9509 msg.hwnd = hwnd; 9510 msg.message = message; 9511 msg.flags = sent|wparam|lparam; 9512 if (defwndproc_counter) msg.flags |= defwinproc; 9513 msg.wParam = wParam; 9514 msg.lParam = lParam; 9515 msg.descr = "dialog"; 9516 add_message(&msg); 9517 9518 defwndproc_counter++; 9519 ret = DefDlgProcA(hwnd, message, wParam, lParam); 9520 defwndproc_counter--; 9521 9522 return ret; 9523 } 9524 9525 static LRESULT WINAPI ShowWindowProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 9526 { 9527 static LONG defwndproc_counter = 0; 9528 LRESULT ret; 9529 struct recvd_message msg; 9530 9531 /* log only specific messages we are interested in */ 9532 switch (message) 9533 { 9534 #if 0 /* probably log these as well */ 9535 case WM_ACTIVATE: 9536 case WM_SETFOCUS: 9537 case WM_KILLFOCUS: 9538 #endif 9539 case WM_SHOWWINDOW: 9540 case WM_SIZE: 9541 case WM_MOVE: 9542 case WM_GETMINMAXINFO: 9543 case WM_WINDOWPOSCHANGING: 9544 case WM_WINDOWPOSCHANGED: 9545 break; 9546 9547 default: /* ignore */ 9548 /*trace("showwindow: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);*/ 9549 return DefWindowProcA(hwnd, message, wParam, lParam); 9550 } 9551 9552 msg.hwnd = hwnd; 9553 msg.message = message; 9554 msg.flags = sent|wparam|lparam; 9555 if (defwndproc_counter) msg.flags |= defwinproc; 9556 msg.wParam = wParam; 9557 msg.lParam = lParam; 9558 msg.descr = "show"; 9559 add_message(&msg); 9560 9561 defwndproc_counter++; 9562 ret = DefWindowProcA(hwnd, message, wParam, lParam); 9563 defwndproc_counter--; 9564 9565 return ret; 9566 } 9567 9568 static LRESULT WINAPI PaintLoopProcA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) 9569 { 9570 switch (msg) 9571 { 9572 case WM_CREATE: return 0; 9573 case WM_PAINT: 9574 { 9575 MSG msg2; 9576 static int i = 0; 9577 9578 if (i < 256) 9579 { 9580 i++; 9581 if (PeekMessageA(&msg2, 0, 0, 0, 1)) 9582 { 9583 TranslateMessage(&msg2); 9584 DispatchMessageA(&msg2); 9585 } 9586 i--; 9587 } 9588 else ok(broken(1), "infinite loop\n"); 9589 if ( i == 0) 9590 paint_loop_done = TRUE; 9591 return DefWindowProcA(hWnd,msg,wParam,lParam); 9592 } 9593 } 9594 return DefWindowProcA(hWnd,msg,wParam,lParam); 9595 } 9596 9597 static LRESULT WINAPI HotkeyMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 9598 { 9599 static LONG defwndproc_counter = 0; 9600 LRESULT ret; 9601 struct recvd_message msg; 9602 DWORD queue_status; 9603 9604 if (ignore_message( message )) return 0; 9605 9606 if ((message >= WM_KEYFIRST && message <= WM_KEYLAST) || 9607 message == WM_HOTKEY || message >= WM_APP) 9608 { 9609 msg.hwnd = hwnd; 9610 msg.message = message; 9611 msg.flags = sent|wparam|lparam; 9612 if (defwndproc_counter) msg.flags |= defwinproc; 9613 msg.wParam = wParam; 9614 msg.lParam = lParam; 9615 msg.descr = "HotkeyMsgCheckProcA"; 9616 add_message(&msg); 9617 } 9618 9619 defwndproc_counter++; 9620 ret = DefWindowProcA(hwnd, message, wParam, lParam); 9621 defwndproc_counter--; 9622 9623 if (message == WM_APP) 9624 { 9625 queue_status = GetQueueStatus(QS_HOTKEY); 9626 ok((queue_status & (QS_HOTKEY << 16)) == QS_HOTKEY << 16, "expected QS_HOTKEY << 16 set, got %x\n", queue_status); 9627 queue_status = GetQueueStatus(QS_POSTMESSAGE); 9628 ok((queue_status & (QS_POSTMESSAGE << 16)) == QS_POSTMESSAGE << 16, "expected QS_POSTMESSAGE << 16 set, got %x\n", queue_status); 9629 PostMessageA(hwnd, WM_APP+1, 0, 0); 9630 } 9631 else if (message == WM_APP+1) 9632 { 9633 queue_status = GetQueueStatus(QS_HOTKEY); 9634 ok((queue_status & (QS_HOTKEY << 16)) == 0, "expected QS_HOTKEY << 16 cleared, got %x\n", queue_status); 9635 } 9636 9637 return ret; 9638 } 9639 9640 static BOOL RegisterWindowClasses(void) 9641 { 9642 WNDCLASSA cls; 9643 WNDCLASSW clsW; 9644 9645 cls.style = 0; 9646 cls.lpfnWndProc = MsgCheckProcA; 9647 cls.cbClsExtra = 0; 9648 cls.cbWndExtra = 0; 9649 cls.hInstance = GetModuleHandleA(0); 9650 cls.hIcon = 0; 9651 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 9652 cls.hbrBackground = GetStockObject(WHITE_BRUSH); 9653 cls.lpszMenuName = NULL; 9654 cls.lpszClassName = "TestWindowClass"; 9655 if(!RegisterClassA(&cls)) return FALSE; 9656 9657 cls.lpfnWndProc = HotkeyMsgCheckProcA; 9658 cls.lpszClassName = "HotkeyWindowClass"; 9659 if(!RegisterClassA(&cls)) return FALSE; 9660 9661 cls.lpfnWndProc = ShowWindowProcA; 9662 cls.lpszClassName = "ShowWindowClass"; 9663 if(!RegisterClassA(&cls)) return FALSE; 9664 9665 cls.lpfnWndProc = PopupMsgCheckProcA; 9666 cls.lpszClassName = "TestPopupClass"; 9667 if(!RegisterClassA(&cls)) return FALSE; 9668 9669 cls.lpfnWndProc = ParentMsgCheckProcA; 9670 cls.lpszClassName = "TestParentClass"; 9671 if(!RegisterClassA(&cls)) return FALSE; 9672 9673 cls.lpfnWndProc = StopQuitMsgCheckProcA; 9674 cls.lpszClassName = "StopQuitClass"; 9675 if(!RegisterClassA(&cls)) return FALSE; 9676 9677 cls.lpfnWndProc = DefWindowProcA; 9678 cls.lpszClassName = "SimpleWindowClass"; 9679 if(!RegisterClassA(&cls)) return FALSE; 9680 9681 cls.lpfnWndProc = PaintLoopProcA; 9682 cls.lpszClassName = "PaintLoopWindowClass"; 9683 if(!RegisterClassA(&cls)) return FALSE; 9684 9685 cls.style = CS_NOCLOSE; 9686 cls.lpszClassName = "NoCloseWindowClass"; 9687 if(!RegisterClassA(&cls)) return FALSE; 9688 9689 ok(GetClassInfoA(0, "#32770", &cls), "GetClassInfo failed\n"); 9690 cls.style = 0; 9691 cls.hInstance = GetModuleHandleA(0); 9692 cls.hbrBackground = 0; 9693 cls.lpfnWndProc = TestDlgProcA; 9694 cls.lpszClassName = "TestDialogClass"; 9695 if(!RegisterClassA(&cls)) return FALSE; 9696 9697 clsW.style = 0; 9698 clsW.lpfnWndProc = MsgCheckProcW; 9699 clsW.cbClsExtra = 0; 9700 clsW.cbWndExtra = 0; 9701 clsW.hInstance = GetModuleHandleW(0); 9702 clsW.hIcon = 0; 9703 clsW.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW); 9704 clsW.hbrBackground = GetStockObject(WHITE_BRUSH); 9705 clsW.lpszMenuName = NULL; 9706 clsW.lpszClassName = testWindowClassW; 9707 RegisterClassW(&clsW); /* ignore error, this fails on Win9x */ 9708 9709 return TRUE; 9710 } 9711 9712 static BOOL is_our_logged_class(HWND hwnd) 9713 { 9714 char buf[256]; 9715 9716 if (GetClassNameA(hwnd, buf, sizeof(buf))) 9717 { 9718 if (!lstrcmpiA(buf, "TestWindowClass") || 9719 !lstrcmpiA(buf, "ShowWindowClass") || 9720 !lstrcmpiA(buf, "TestParentClass") || 9721 !lstrcmpiA(buf, "TestPopupClass") || 9722 !lstrcmpiA(buf, "SimpleWindowClass") || 9723 !lstrcmpiA(buf, "TestDialogClass") || 9724 !lstrcmpiA(buf, "MDI_frame_class") || 9725 !lstrcmpiA(buf, "MDI_client_class") || 9726 !lstrcmpiA(buf, "MDI_child_class") || 9727 !lstrcmpiA(buf, "my_button_class") || 9728 !lstrcmpiA(buf, "my_edit_class") || 9729 !lstrcmpiA(buf, "static") || 9730 !lstrcmpiA(buf, "ListBox") || 9731 !lstrcmpiA(buf, "ComboBox") || 9732 !lstrcmpiA(buf, "MyDialogClass") || 9733 !lstrcmpiA(buf, "#32770") || 9734 !lstrcmpiA(buf, "#32768")) 9735 return TRUE; 9736 } 9737 return FALSE; 9738 } 9739 9740 static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam) 9741 { 9742 HWND hwnd; 9743 9744 ok(cbt_hook_thread_id == GetCurrentThreadId(), "we didn't ask for events from other threads\n"); 9745 9746 if (nCode == HCBT_CLICKSKIPPED) 9747 { 9748 /* ignore this event, XP sends it a lot when switching focus between windows */ 9749 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam); 9750 } 9751 9752 if (nCode == HCBT_SYSCOMMAND || nCode == HCBT_KEYSKIPPED) 9753 { 9754 struct recvd_message msg; 9755 9756 msg.hwnd = 0; 9757 msg.message = nCode; 9758 msg.flags = hook|wparam|lparam; 9759 msg.wParam = wParam; 9760 msg.lParam = lParam; 9761 msg.descr = "CBT"; 9762 add_message(&msg); 9763 9764 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam); 9765 } 9766 9767 if (nCode == HCBT_DESTROYWND) 9768 { 9769 if (test_DestroyWindow_flag) 9770 { 9771 DWORD style = GetWindowLongA((HWND)wParam, GWL_STYLE); 9772 if (style & WS_CHILD) 9773 lParam = GetWindowLongPtrA((HWND)wParam, GWLP_ID); 9774 else if (style & WS_POPUP) 9775 lParam = WND_POPUP_ID; 9776 else 9777 lParam = WND_PARENT_ID; 9778 } 9779 } 9780 9781 /* Log also SetFocus(0) calls */ 9782 hwnd = wParam ? (HWND)wParam : (HWND)lParam; 9783 9784 if (is_our_logged_class(hwnd)) 9785 { 9786 struct recvd_message msg; 9787 9788 msg.hwnd = hwnd; 9789 msg.message = nCode; 9790 msg.flags = hook|wparam|lparam; 9791 msg.wParam = wParam; 9792 msg.lParam = lParam; 9793 msg.descr = "CBT"; 9794 add_message(&msg); 9795 } 9796 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam); 9797 } 9798 9799 static void CALLBACK win_event_proc(HWINEVENTHOOK hevent, 9800 DWORD event, 9801 HWND hwnd, 9802 LONG object_id, 9803 LONG child_id, 9804 DWORD thread_id, 9805 DWORD event_time) 9806 { 9807 ok(thread_id == GetCurrentThreadId(), "we didn't ask for events from other threads\n"); 9808 9809 /* ignore mouse cursor events */ 9810 if (object_id == OBJID_CURSOR) return; 9811 9812 if (!hwnd || is_our_logged_class(hwnd)) 9813 { 9814 struct recvd_message msg; 9815 9816 msg.hwnd = hwnd; 9817 msg.message = event; 9818 msg.flags = winevent_hook|wparam|lparam; 9819 msg.wParam = object_id; 9820 msg.lParam = child_id; 9821 msg.descr = "WEH"; 9822 add_message(&msg); 9823 } 9824 } 9825 9826 static const WCHAR wszUnicode[] = {'U','n','i','c','o','d','e',0}; 9827 static const WCHAR wszAnsi[] = {'U',0}; 9828 9829 static LRESULT CALLBACK MsgConversionProcW(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 9830 { 9831 switch (uMsg) 9832 { 9833 case CB_FINDSTRINGEXACT: 9834 trace("String: %p\n", (LPCWSTR)lParam); 9835 if (!lstrcmpW((LPCWSTR)lParam, wszUnicode)) 9836 return 1; 9837 if (!lstrcmpW((LPCWSTR)lParam, wszAnsi)) 9838 return 0; 9839 return -1; 9840 } 9841 return DefWindowProcW(hwnd, uMsg, wParam, lParam); 9842 } 9843 9844 static const struct message WmGetTextLengthAfromW[] = { 9845 { WM_GETTEXTLENGTH, sent }, 9846 { WM_GETTEXT, sent|optional }, 9847 { 0 } 9848 }; 9849 9850 static const WCHAR dummy_window_text[] = {'d','u','m','m','y',' ','t','e','x','t',0}; 9851 9852 /* dummy window proc for WM_GETTEXTLENGTH test */ 9853 static LRESULT CALLBACK get_text_len_proc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ) 9854 { 9855 switch(msg) 9856 { 9857 case WM_GETTEXTLENGTH: 9858 return lstrlenW(dummy_window_text) + 37; /* some random length */ 9859 case WM_GETTEXT: 9860 lstrcpynW( (LPWSTR)lp, dummy_window_text, wp ); 9861 return lstrlenW( (LPWSTR)lp ); 9862 default: 9863 return DefWindowProcW( hwnd, msg, wp, lp ); 9864 } 9865 } 9866 9867 static void test_message_conversion(void) 9868 { 9869 static const WCHAR wszMsgConversionClass[] = 9870 {'M','s','g','C','o','n','v','e','r','s','i','o','n','C','l','a','s','s',0}; 9871 WNDCLASSW cls; 9872 LRESULT lRes; 9873 HWND hwnd; 9874 WNDPROC wndproc, newproc; 9875 BOOL ret; 9876 9877 cls.style = 0; 9878 cls.lpfnWndProc = MsgConversionProcW; 9879 cls.cbClsExtra = 0; 9880 cls.cbWndExtra = 0; 9881 cls.hInstance = GetModuleHandleW(NULL); 9882 cls.hIcon = NULL; 9883 cls.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW); 9884 cls.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1); 9885 cls.lpszMenuName = NULL; 9886 cls.lpszClassName = wszMsgConversionClass; 9887 /* this call will fail on Win9x, but that doesn't matter as this test is 9888 * meaningless on those platforms */ 9889 if(!RegisterClassW(&cls)) return; 9890 9891 hwnd = CreateWindowExW(0, wszMsgConversionClass, NULL, WS_OVERLAPPED, 9892 100, 100, 200, 200, 0, 0, 0, NULL); 9893 ok(hwnd != NULL, "Window creation failed\n"); 9894 9895 /* {W, A} -> A */ 9896 9897 wndproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_WNDPROC); 9898 lRes = CallWindowProcA(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); 9899 ok(lRes == 0, "String should have been converted\n"); 9900 lRes = CallWindowProcW(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); 9901 ok(lRes == 1, "String shouldn't have been converted\n"); 9902 9903 /* {W, A} -> W */ 9904 9905 wndproc = (WNDPROC)GetWindowLongPtrW(hwnd, GWLP_WNDPROC); 9906 lRes = CallWindowProcA(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); 9907 ok(lRes == 1, "String shouldn't have been converted\n"); 9908 lRes = CallWindowProcW(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); 9909 ok(lRes == 1, "String shouldn't have been converted\n"); 9910 9911 /* Synchronous messages */ 9912 9913 lRes = SendMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); 9914 ok(lRes == 0, "String should have been converted\n"); 9915 lRes = SendMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); 9916 ok(lRes == 1, "String shouldn't have been converted\n"); 9917 9918 /* Asynchronous messages */ 9919 9920 SetLastError(0); 9921 lRes = PostMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); 9922 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER), 9923 "PostMessage on sync only message returned %ld, last error %d\n", lRes, GetLastError()); 9924 SetLastError(0); 9925 lRes = PostMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); 9926 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER), 9927 "PostMessage on sync only message returned %ld, last error %d\n", lRes, GetLastError()); 9928 SetLastError(0); 9929 lRes = PostThreadMessageA(GetCurrentThreadId(), CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); 9930 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER), 9931 "PosThreadtMessage on sync only message returned %ld, last error %d\n", lRes, GetLastError()); 9932 SetLastError(0); 9933 lRes = PostThreadMessageW(GetCurrentThreadId(), CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); 9934 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER), 9935 "PosThreadtMessage on sync only message returned %ld, last error %d\n", lRes, GetLastError()); 9936 SetLastError(0); 9937 lRes = SendNotifyMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); 9938 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER), 9939 "SendNotifyMessage on sync only message returned %ld, last error %d\n", lRes, GetLastError()); 9940 SetLastError(0); 9941 lRes = SendNotifyMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); 9942 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER), 9943 "SendNotifyMessage on sync only message returned %ld, last error %d\n", lRes, GetLastError()); 9944 SetLastError(0); 9945 lRes = SendMessageCallbackA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode, NULL, 0); 9946 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER), 9947 "SendMessageCallback on sync only message returned %ld, last error %d\n", lRes, GetLastError()); 9948 SetLastError(0); 9949 lRes = SendMessageCallbackW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode, NULL, 0); 9950 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER), 9951 "SendMessageCallback on sync only message returned %ld, last error %d\n", lRes, GetLastError()); 9952 9953 /* Check WM_GETTEXTLENGTH A->W behaviour, whether WM_GETTEXT is also sent or not */ 9954 9955 hwnd = CreateWindowW (testWindowClassW, wszUnicode, 9956 WS_OVERLAPPEDWINDOW, 9957 100, 100, 200, 200, 0, 0, 0, NULL); 9958 assert(hwnd); 9959 flush_sequence(); 9960 lRes = SendMessageA (hwnd, WM_GETTEXTLENGTH, 0, 0); 9961 ok_sequence(WmGetTextLengthAfromW, "ANSI WM_GETTEXTLENGTH to Unicode window", FALSE); 9962 ok( lRes == WideCharToMultiByte( CP_ACP, 0, wszUnicode, lstrlenW(wszUnicode), NULL, 0, NULL, NULL ), 9963 "got bad length %ld\n", lRes ); 9964 9965 flush_sequence(); 9966 lRes = CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ), 9967 hwnd, WM_GETTEXTLENGTH, 0, 0); 9968 ok_sequence(WmGetTextLengthAfromW, "ANSI WM_GETTEXTLENGTH to Unicode window", FALSE); 9969 ok( lRes == WideCharToMultiByte( CP_ACP, 0, wszUnicode, lstrlenW(wszUnicode), NULL, 0, NULL, NULL ), 9970 "got bad length %ld\n", lRes ); 9971 9972 wndproc = (WNDPROC)SetWindowLongPtrW( hwnd, GWLP_WNDPROC, (LONG_PTR)get_text_len_proc ); 9973 newproc = (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ); 9974 lRes = CallWindowProcA( newproc, hwnd, WM_GETTEXTLENGTH, 0, 0 ); 9975 ok( lRes == WideCharToMultiByte( CP_ACP, 0, dummy_window_text, lstrlenW(dummy_window_text), 9976 NULL, 0, NULL, NULL ) || 9977 broken(lRes == lstrlenW(dummy_window_text) + 37), 9978 "got bad length %ld\n", lRes ); 9979 9980 SetWindowLongPtrW( hwnd, GWLP_WNDPROC, (LONG_PTR)wndproc ); /* restore old wnd proc */ 9981 lRes = CallWindowProcA( newproc, hwnd, WM_GETTEXTLENGTH, 0, 0 ); 9982 ok( lRes == WideCharToMultiByte( CP_ACP, 0, dummy_window_text, lstrlenW(dummy_window_text), 9983 NULL, 0, NULL, NULL ) || 9984 broken(lRes == lstrlenW(dummy_window_text) + 37), 9985 "got bad length %ld\n", lRes ); 9986 9987 ret = DestroyWindow(hwnd); 9988 ok( ret, "DestroyWindow() error %d\n", GetLastError()); 9989 } 9990 9991 struct timer_info 9992 { 9993 HWND hWnd; 9994 HANDLE handles[2]; 9995 DWORD id; 9996 }; 9997 9998 static VOID CALLBACK tfunc(HWND hwnd, UINT uMsg, UINT_PTR id, DWORD dwTime) 9999 { 10000 } 10001 10002 #define TIMER_ID 0x19 10003 #define TIMER_COUNT_EXPECTED 100 10004 #define TIMER_COUNT_TOLERANCE 10 10005 10006 static int count = 0; 10007 static void CALLBACK callback_count(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) 10008 { 10009 count++; 10010 } 10011 10012 static DWORD exception; 10013 static void CALLBACK callback_exception(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) 10014 { 10015 count++; 10016 RaiseException(exception, 0, 0, NULL); 10017 } 10018 10019 static DWORD WINAPI timer_thread_proc(LPVOID x) 10020 { 10021 struct timer_info *info = x; 10022 DWORD r; 10023 10024 r = KillTimer(info->hWnd, 0x19); 10025 ok(r,"KillTimer failed in thread\n"); 10026 r = SetTimer(info->hWnd,TIMER_ID,10000,tfunc); 10027 ok(r,"SetTimer failed in thread\n"); 10028 ok(r==TIMER_ID,"SetTimer id different\n"); 10029 r = SetEvent(info->handles[0]); 10030 ok(r,"SetEvent failed in thread\n"); 10031 return 0; 10032 } 10033 10034 static void test_timers(void) 10035 { 10036 struct timer_info info; 10037 DWORD start; 10038 DWORD id; 10039 MSG msg; 10040 10041 info.hWnd = CreateWindowA("TestWindowClass", NULL, 10042 WS_OVERLAPPEDWINDOW , 10043 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0, 10044 NULL, NULL, 0); 10045 10046 info.id = SetTimer(info.hWnd,TIMER_ID,10000,tfunc); 10047 ok(info.id, "SetTimer failed\n"); 10048 ok(info.id==TIMER_ID, "SetTimer timer ID different\n"); 10049 info.handles[0] = CreateEventW(NULL,0,0,NULL); 10050 info.handles[1] = CreateThread(NULL,0,timer_thread_proc,&info,0,&id); 10051 10052 WaitForMultipleObjects(2, info.handles, FALSE, INFINITE); 10053 10054 WaitForSingleObject(info.handles[1], INFINITE); 10055 10056 CloseHandle(info.handles[0]); 10057 CloseHandle(info.handles[1]); 10058 10059 ok( KillTimer(info.hWnd, TIMER_ID), "KillTimer failed\n"); 10060 10061 /* Check the minimum allowed timeout for a timer. MSDN indicates that it should be 10.0 ms, 10062 * which occurs sometimes, but most testing on the VMs indicates a minimum timeout closer to 10063 * 15.6 ms. Since there is some measurement error between test runs we are allowing for 10064 * ±9 counts (~4 ms) around the expected value. 10065 */ 10066 count = 0; 10067 id = SetTimer(info.hWnd, TIMER_ID, 0, callback_count); 10068 ok(id != 0, "did not get id from SetTimer.\n"); 10069 ok(id==TIMER_ID, "SetTimer timer ID different\n"); 10070 start = GetTickCount(); 10071 while (GetTickCount()-start < 1001 && GetMessageA(&msg, info.hWnd, 0, 0)) 10072 DispatchMessageA(&msg); 10073 todo_wine 10074 ok(abs(count-TIMER_COUNT_EXPECTED) < TIMER_COUNT_TOLERANCE /* xp */ 10075 || broken(abs(count-64) < TIMER_COUNT_TOLERANCE) /* most common */ 10076 || broken(abs(count-43) < TIMER_COUNT_TOLERANCE) /* w2k3, win8 */, 10077 "did not get expected count for minimum timeout (%d != ~%d).\n", 10078 count, TIMER_COUNT_EXPECTED); 10079 ok(KillTimer(info.hWnd, id), "KillTimer failed\n"); 10080 /* Perform the same check on SetSystemTimer (only available on w2k3 and older) */ 10081 if (pSetSystemTimer) 10082 { 10083 int syscount = 0; 10084 10085 count = 0; 10086 id = pSetSystemTimer(info.hWnd, TIMER_ID, 0, callback_count); 10087 ok(id != 0, "did not get id from SetSystemTimer.\n"); 10088 ok(id==TIMER_ID, "SetTimer timer ID different\n"); 10089 start = GetTickCount(); 10090 while (GetTickCount()-start < 1001 && GetMessageA(&msg, info.hWnd, 0, 0)) 10091 { 10092 if (msg.message == WM_SYSTIMER) 10093 syscount++; 10094 DispatchMessageA(&msg); 10095 } 10096 ok(abs(syscount-TIMER_COUNT_EXPECTED) < TIMER_COUNT_TOLERANCE 10097 || broken(abs(syscount-64) < TIMER_COUNT_TOLERANCE) /* most common */ 10098 || broken(syscount > 4000 && syscount < 12000) /* win2k3sp0 */, 10099 "did not get expected count for minimum timeout (%d != ~%d).\n", 10100 syscount, TIMER_COUNT_EXPECTED); 10101 todo_wine ok(count == 0, "did not get expected count for callback timeout (%d != 0).\n", 10102 count); 10103 ok(pKillSystemTimer(info.hWnd, id), "KillSystemTimer failed\n"); 10104 } 10105 10106 ok(DestroyWindow(info.hWnd), "failed to destroy window\n"); 10107 } 10108 10109 static void test_timers_no_wnd(void) 10110 { 10111 static UINT_PTR ids[0xffff]; 10112 UINT_PTR id, id2; 10113 DWORD start; 10114 MSG msg; 10115 int i; 10116 10117 count = 0; 10118 id = SetTimer(NULL, 0, 100, callback_count); 10119 ok(id != 0, "did not get id from SetTimer.\n"); 10120 id2 = SetTimer(NULL, id, 200, callback_count); 10121 ok(id2 == id, "did not get same id from SetTimer when replacing (%li expected %li).\n", id2, id); 10122 Sleep(150); 10123 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 10124 ok(count == 0, "did not get zero count as expected (%i).\n", count); 10125 Sleep(150); 10126 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 10127 ok(count == 1, "did not get one count as expected (%i).\n", count); 10128 KillTimer(NULL, id); 10129 Sleep(250); 10130 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 10131 ok(count == 1, "killing replaced timer did not work (%i).\n", count); 10132 10133 /* Check the minimum allowed timeout for a timer. MSDN indicates that it should be 10.0 ms, 10134 * which occurs sometimes, but most testing on the VMs indicates a minimum timeout closer to 10135 * 15.6 ms. Since there is some measurement error between test runs we are allowing for 10136 * ±9 counts (~4 ms) around the expected value. 10137 */ 10138 count = 0; 10139 id = SetTimer(NULL, 0, 0, callback_count); 10140 ok(id != 0, "did not get id from SetTimer.\n"); 10141 start = GetTickCount(); 10142 while (GetTickCount()-start < 1001 && GetMessageA(&msg, NULL, 0, 0)) 10143 DispatchMessageA(&msg); 10144 todo_wine 10145 ok(abs(count-TIMER_COUNT_EXPECTED) < TIMER_COUNT_TOLERANCE /* xp */ 10146 || broken(abs(count-64) < TIMER_COUNT_TOLERANCE) /* most common */, 10147 "did not get expected count for minimum timeout (%d != ~%d).\n", 10148 count, TIMER_COUNT_EXPECTED); 10149 KillTimer(NULL, id); 10150 /* Note: SetSystemTimer doesn't support a NULL window, see test_timers */ 10151 10152 if (pSetCoalescableTimer) 10153 { 10154 count = 0; 10155 id = pSetCoalescableTimer(NULL, 0, 0, callback_count, 0); 10156 ok(id != 0, "SetCoalescableTimer failed with %u.\n", GetLastError()); 10157 start = GetTickCount(); 10158 while (GetTickCount()-start < 100 && GetMessageA(&msg, NULL, 0, 0)) 10159 DispatchMessageA(&msg); 10160 ok(count > 1, "expected count > 1, got %d.\n", count); 10161 KillTimer(NULL, id); 10162 } 10163 else 10164 win_skip("SetCoalescableTimer not available.\n"); 10165 10166 /* Check what happens when we're running out of timers */ 10167 for (i=0; i<sizeof(ids)/sizeof(ids[0]); i++) 10168 { 10169 SetLastError(0xdeadbeef); 10170 ids[i] = SetTimer(NULL, 0, USER_TIMER_MAXIMUM, tfunc); 10171 if (!ids[i]) break; 10172 } 10173 ok(i != sizeof(ids)/sizeof(ids[0]), "all timers were created successfully\n"); 10174 ok(GetLastError()==ERROR_NO_MORE_USER_HANDLES || broken(GetLastError()==0xdeadbeef), 10175 "GetLastError() = %d\n", GetLastError()); 10176 while (i > 0) KillTimer(NULL, ids[--i]); 10177 } 10178 10179 static void test_timers_exception(DWORD code) 10180 { 10181 UINT_PTR id; 10182 MSG msg; 10183 10184 exception = code; 10185 id = SetTimer(NULL, 0, 1000, callback_exception); 10186 ok(id != 0, "did not get id from SetTimer.\n"); 10187 10188 memset(&msg, 0, sizeof(msg)); 10189 msg.message = WM_TIMER; 10190 msg.wParam = id; 10191 msg.lParam = (LPARAM)callback_exception; 10192 10193 count = 0; 10194 DispatchMessageA(&msg); 10195 ok(count == 1, "did not get one count as expected (%i).\n", count); 10196 10197 KillTimer(NULL, id); 10198 } 10199 10200 static void test_timers_exceptions(void) 10201 { 10202 test_timers_exception(EXCEPTION_ACCESS_VIOLATION); 10203 test_timers_exception(EXCEPTION_DATATYPE_MISALIGNMENT); 10204 test_timers_exception(EXCEPTION_BREAKPOINT); 10205 test_timers_exception(EXCEPTION_SINGLE_STEP); 10206 test_timers_exception(EXCEPTION_ARRAY_BOUNDS_EXCEEDED); 10207 test_timers_exception(EXCEPTION_FLT_DENORMAL_OPERAND); 10208 test_timers_exception(EXCEPTION_FLT_DIVIDE_BY_ZERO); 10209 test_timers_exception(EXCEPTION_FLT_INEXACT_RESULT); 10210 test_timers_exception(EXCEPTION_ILLEGAL_INSTRUCTION); 10211 test_timers_exception(0xE000BEEF); /* customer exception */ 10212 } 10213 10214 /* Various win events with arbitrary parameters */ 10215 static const struct message WmWinEventsSeq[] = { 10216 { EVENT_SYSTEM_SOUND, winevent_hook|wparam|lparam, OBJID_WINDOW, 0 }, 10217 { EVENT_SYSTEM_ALERT, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 }, 10218 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, OBJID_TITLEBAR, 2 }, 10219 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_MENU, 3 }, 10220 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_CLIENT, 4 }, 10221 { EVENT_SYSTEM_MENUPOPUPSTART, winevent_hook|wparam|lparam, OBJID_VSCROLL, 5 }, 10222 { EVENT_SYSTEM_MENUPOPUPEND, winevent_hook|wparam|lparam, OBJID_HSCROLL, 6 }, 10223 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, OBJID_SIZEGRIP, 7 }, 10224 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, OBJID_CARET, 8 }, 10225 /* our win event hook ignores OBJID_CURSOR events */ 10226 /*{ EVENT_SYSTEM_MOVESIZESTART, winevent_hook|wparam|lparam, OBJID_CURSOR, 9 },*/ 10227 { EVENT_SYSTEM_MOVESIZEEND, winevent_hook|wparam|lparam, OBJID_ALERT, 10 }, 10228 { EVENT_SYSTEM_CONTEXTHELPSTART, winevent_hook|wparam|lparam, OBJID_SOUND, 11 }, 10229 { EVENT_SYSTEM_CONTEXTHELPEND, winevent_hook|wparam|lparam, OBJID_QUERYCLASSNAMEIDX, 12 }, 10230 { EVENT_SYSTEM_DRAGDROPSTART, winevent_hook|wparam|lparam, OBJID_NATIVEOM, 13 }, 10231 { EVENT_SYSTEM_DRAGDROPEND, winevent_hook|wparam|lparam, OBJID_WINDOW, 0 }, 10232 { EVENT_SYSTEM_DIALOGSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 }, 10233 { EVENT_SYSTEM_DIALOGEND, winevent_hook|wparam|lparam, OBJID_TITLEBAR, 2 }, 10234 { EVENT_SYSTEM_SCROLLINGSTART, winevent_hook|wparam|lparam, OBJID_MENU, 3 }, 10235 { EVENT_SYSTEM_SCROLLINGEND, winevent_hook|wparam|lparam, OBJID_CLIENT, 4 }, 10236 { EVENT_SYSTEM_SWITCHSTART, winevent_hook|wparam|lparam, OBJID_VSCROLL, 5 }, 10237 { EVENT_SYSTEM_SWITCHEND, winevent_hook|wparam|lparam, OBJID_HSCROLL, 6 }, 10238 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, OBJID_SIZEGRIP, 7 }, 10239 { EVENT_SYSTEM_MINIMIZEEND, winevent_hook|wparam|lparam, OBJID_CARET, 8 }, 10240 { 0 } 10241 }; 10242 static const struct message WmWinEventCaretSeq[] = { 10243 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1 */ 10244 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1 */ 10245 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 2 */ 10246 { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1 */ 10247 { 0 } 10248 }; 10249 static const struct message WmWinEventCaretSeq_2[] = { 10250 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1/2 */ 10251 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1/2 */ 10252 { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1/2 */ 10253 { 0 } 10254 }; 10255 static const struct message WmWinEventAlertSeq[] = { 10256 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_ALERT, 0 }, 10257 { 0 } 10258 }; 10259 static const struct message WmWinEventAlertSeq_2[] = { 10260 /* create window in the thread proc */ 10261 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_WINDOW, 2 }, 10262 /* our test event */ 10263 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_ALERT, 2 }, 10264 { 0 } 10265 }; 10266 static const struct message WmGlobalHookSeq_1[] = { 10267 /* create window in the thread proc */ 10268 { HCBT_CREATEWND, hook|lparam, 0, 2 }, 10269 /* our test events */ 10270 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_PREVWINDOW, 2 }, 10271 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_NEXTWINDOW, 2 }, 10272 { 0 } 10273 }; 10274 static const struct message WmGlobalHookSeq_2[] = { 10275 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_NEXTWINDOW, 0 }, /* old local hook */ 10276 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_NEXTWINDOW, 2 }, /* new global hook */ 10277 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_PREVWINDOW, 0 }, /* old local hook */ 10278 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_PREVWINDOW, 2 }, /* new global hook */ 10279 { 0 } 10280 }; 10281 10282 static const struct message WmMouseLLHookSeq[] = { 10283 { WM_MOUSEMOVE, hook }, 10284 { WM_LBUTTONUP, hook }, 10285 { WM_MOUSEMOVE, hook }, 10286 { 0 } 10287 }; 10288 10289 static void CALLBACK win_event_global_hook_proc(HWINEVENTHOOK hevent, 10290 DWORD event, 10291 HWND hwnd, 10292 LONG object_id, 10293 LONG child_id, 10294 DWORD thread_id, 10295 DWORD event_time) 10296 { 10297 char buf[256]; 10298 10299 if (GetClassNameA(hwnd, buf, sizeof(buf))) 10300 { 10301 if (!lstrcmpiA(buf, "TestWindowClass") || 10302 !lstrcmpiA(buf, "static")) 10303 { 10304 struct recvd_message msg; 10305 10306 msg.hwnd = hwnd; 10307 msg.message = event; 10308 msg.flags = winevent_hook|wparam|lparam; 10309 msg.wParam = object_id; 10310 msg.lParam = (thread_id == GetCurrentThreadId()) ? child_id : (child_id + 2); 10311 msg.descr = "WEH_2"; 10312 add_message(&msg); 10313 } 10314 } 10315 } 10316 10317 static HHOOK hCBT_global_hook; 10318 static DWORD cbt_global_hook_thread_id; 10319 10320 static LRESULT CALLBACK cbt_global_hook_proc(int nCode, WPARAM wParam, LPARAM lParam) 10321 { 10322 HWND hwnd; 10323 char buf[256]; 10324 10325 if (nCode == HCBT_SYSCOMMAND) 10326 { 10327 struct recvd_message msg; 10328 10329 msg.hwnd = 0; 10330 msg.message = nCode; 10331 msg.flags = hook|wparam|lparam; 10332 msg.wParam = wParam; 10333 msg.lParam = (cbt_global_hook_thread_id == GetCurrentThreadId()) ? 1 : 2; 10334 msg.descr = "CBT_2"; 10335 add_message(&msg); 10336 10337 return CallNextHookEx(hCBT_global_hook, nCode, wParam, lParam); 10338 } 10339 /* WH_MOUSE_LL hook */ 10340 if (nCode == HC_ACTION) 10341 { 10342 MSLLHOOKSTRUCT *mhll = (MSLLHOOKSTRUCT *)lParam; 10343 10344 /* we can't test for real mouse events */ 10345 if (mhll->flags & LLMHF_INJECTED) 10346 { 10347 struct recvd_message msg; 10348 10349 memset (&msg, 0, sizeof (msg)); 10350 msg.message = wParam; 10351 msg.flags = hook; 10352 msg.descr = "CBT_2"; 10353 add_message(&msg); 10354 } 10355 return CallNextHookEx(hCBT_global_hook, nCode, wParam, lParam); 10356 } 10357 10358 /* Log also SetFocus(0) calls */ 10359 hwnd = wParam ? (HWND)wParam : (HWND)lParam; 10360 10361 if (GetClassNameA(hwnd, buf, sizeof(buf))) 10362 { 10363 if (!lstrcmpiA(buf, "TestWindowClass") || 10364 !lstrcmpiA(buf, "static")) 10365 { 10366 struct recvd_message msg; 10367 10368 msg.hwnd = hwnd; 10369 msg.message = nCode; 10370 msg.flags = hook|wparam|lparam; 10371 msg.wParam = wParam; 10372 msg.lParam = (cbt_global_hook_thread_id == GetCurrentThreadId()) ? 1 : 2; 10373 msg.descr = "CBT_2"; 10374 add_message(&msg); 10375 } 10376 } 10377 return CallNextHookEx(hCBT_global_hook, nCode, wParam, lParam); 10378 } 10379 10380 static DWORD WINAPI win_event_global_thread_proc(void *param) 10381 { 10382 HWND hwnd; 10383 MSG msg; 10384 HANDLE hevent = *(HANDLE *)param; 10385 10386 assert(pNotifyWinEvent); 10387 10388 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL); 10389 assert(hwnd); 10390 trace("created thread window %p\n", hwnd); 10391 10392 *(HWND *)param = hwnd; 10393 10394 flush_sequence(); 10395 /* this event should be received only by our new hook proc, 10396 * an old one does not expect an event from another thread. 10397 */ 10398 pNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, hwnd, OBJID_ALERT, 0); 10399 SetEvent(hevent); 10400 10401 while (GetMessageA(&msg, 0, 0, 0)) 10402 { 10403 TranslateMessage(&msg); 10404 DispatchMessageA(&msg); 10405 } 10406 return 0; 10407 } 10408 10409 static DWORD WINAPI cbt_global_hook_thread_proc(void *param) 10410 { 10411 HWND hwnd; 10412 MSG msg; 10413 HANDLE hevent = *(HANDLE *)param; 10414 10415 flush_sequence(); 10416 /* these events should be received only by our new hook proc, 10417 * an old one does not expect an event from another thread. 10418 */ 10419 10420 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL); 10421 assert(hwnd); 10422 trace("created thread window %p\n", hwnd); 10423 10424 *(HWND *)param = hwnd; 10425 10426 /* Windows doesn't like when a thread plays games with the focus, 10427 that leads to all kinds of misbehaviours and failures to activate 10428 a window. So, better keep next lines commented out. 10429 SetFocus(0); 10430 SetFocus(hwnd);*/ 10431 10432 DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_PREVWINDOW, 0); 10433 DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_NEXTWINDOW, 0); 10434 10435 SetEvent(hevent); 10436 10437 while (GetMessageA(&msg, 0, 0, 0)) 10438 { 10439 TranslateMessage(&msg); 10440 DispatchMessageA(&msg); 10441 } 10442 return 0; 10443 } 10444 10445 static DWORD WINAPI mouse_ll_global_thread_proc(void *param) 10446 { 10447 HWND hwnd; 10448 MSG msg; 10449 HANDLE hevent = *(HANDLE *)param; 10450 10451 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL); 10452 assert(hwnd); 10453 trace("created thread window %p\n", hwnd); 10454 10455 *(HWND *)param = hwnd; 10456 10457 flush_sequence(); 10458 10459 /* Windows doesn't like when a thread plays games with the focus, 10460 * that leads to all kinds of misbehaviours and failures to activate 10461 * a window. So, better don't generate a mouse click message below. 10462 */ 10463 mouse_event(MOUSEEVENTF_MOVE, -1, 0, 0, 0); 10464 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); 10465 mouse_event(MOUSEEVENTF_MOVE, 1, 0, 0, 0); 10466 10467 SetEvent(hevent); 10468 while (GetMessageA(&msg, 0, 0, 0)) 10469 { 10470 TranslateMessage(&msg); 10471 DispatchMessageA(&msg); 10472 } 10473 return 0; 10474 } 10475 10476 static void test_winevents(void) 10477 { 10478 BOOL ret; 10479 MSG msg; 10480 HWND hwnd, hwnd2; 10481 UINT i; 10482 HANDLE hthread, hevent; 10483 DWORD tid; 10484 HWINEVENTHOOK hhook; 10485 const struct message *events = WmWinEventsSeq; 10486 10487 hwnd = CreateWindowExA(0, "TestWindowClass", NULL, 10488 WS_OVERLAPPEDWINDOW, 10489 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0, 10490 NULL, NULL, 0); 10491 assert(hwnd); 10492 10493 /****** start of global hook test *************/ 10494 hCBT_global_hook = SetWindowsHookExA(WH_CBT, cbt_global_hook_proc, GetModuleHandleA(0), 0); 10495 if (!hCBT_global_hook) 10496 { 10497 ok(DestroyWindow(hwnd), "failed to destroy window\n"); 10498 skip( "cannot set global hook\n" ); 10499 return; 10500 } 10501 10502 hevent = CreateEventA(NULL, 0, 0, NULL); 10503 assert(hevent); 10504 hwnd2 = hevent; 10505 10506 hthread = CreateThread(NULL, 0, cbt_global_hook_thread_proc, &hwnd2, 0, &tid); 10507 ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError()); 10508 10509 ok(WaitForSingleObject(hevent, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 10510 10511 ok_sequence(WmGlobalHookSeq_1, "global hook 1", FALSE); 10512 10513 flush_sequence(); 10514 /* this one should be received only by old hook proc */ 10515 DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_NEXTWINDOW, 0); 10516 /* this one should be received only by old hook proc */ 10517 DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_PREVWINDOW, 0); 10518 10519 ok_sequence(WmGlobalHookSeq_2, "global hook 2", FALSE); 10520 10521 ret = UnhookWindowsHookEx(hCBT_global_hook); 10522 ok( ret, "UnhookWindowsHookEx error %d\n", GetLastError()); 10523 10524 PostThreadMessageA(tid, WM_QUIT, 0, 0); 10525 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 10526 CloseHandle(hthread); 10527 CloseHandle(hevent); 10528 ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n"); 10529 /****** end of global hook test *************/ 10530 10531 if (!pSetWinEventHook || !pNotifyWinEvent || !pUnhookWinEvent) 10532 { 10533 ok(DestroyWindow(hwnd), "failed to destroy window\n"); 10534 return; 10535 } 10536 10537 flush_sequence(); 10538 10539 if (0) 10540 { 10541 /* this test doesn't pass under Win9x */ 10542 /* win2k ignores events with hwnd == 0 */ 10543 SetLastError(0xdeadbeef); 10544 pNotifyWinEvent(events[0].message, 0, events[0].wParam, events[0].lParam); 10545 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || /* Win2k */ 10546 GetLastError() == 0xdeadbeef, /* Win9x */ 10547 "unexpected error %d\n", GetLastError()); 10548 ok_sequence(WmEmptySeq, "empty notify winevents", FALSE); 10549 } 10550 10551 for (i = 0; i < sizeof(WmWinEventsSeq)/sizeof(WmWinEventsSeq[0]); i++) 10552 pNotifyWinEvent(events[i].message, hwnd, events[i].wParam, events[i].lParam); 10553 10554 ok_sequence(WmWinEventsSeq, "notify winevents", FALSE); 10555 10556 /****** start of event filtering test *************/ 10557 hhook = pSetWinEventHook( 10558 EVENT_OBJECT_SHOW, /* 0x8002 */ 10559 EVENT_OBJECT_LOCATIONCHANGE, /* 0x800B */ 10560 GetModuleHandleA(0), win_event_global_hook_proc, 10561 GetCurrentProcessId(), 0, 10562 WINEVENT_INCONTEXT); 10563 ok(hhook != 0, "SetWinEventHook error %d\n", GetLastError()); 10564 10565 hevent = CreateEventA(NULL, 0, 0, NULL); 10566 assert(hevent); 10567 hwnd2 = hevent; 10568 10569 hthread = CreateThread(NULL, 0, win_event_global_thread_proc, &hwnd2, 0, &tid); 10570 ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError()); 10571 10572 ok(WaitForSingleObject(hevent, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 10573 10574 ok_sequence(WmWinEventAlertSeq, "alert winevent", FALSE); 10575 10576 flush_sequence(); 10577 /* this one should be received only by old hook proc */ 10578 pNotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_CARET, 0); /* 0x8000 */ 10579 pNotifyWinEvent(EVENT_OBJECT_SHOW, hwnd, OBJID_CARET, 0); /* 0x8002 */ 10580 /* this one should be received only by old hook proc */ 10581 pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, hwnd, OBJID_CARET, 0); /* 0x800C */ 10582 10583 ok_sequence(WmWinEventCaretSeq, "caret winevent", FALSE); 10584 10585 ret = pUnhookWinEvent(hhook); 10586 ok( ret, "UnhookWinEvent error %d\n", GetLastError()); 10587 10588 PostThreadMessageA(tid, WM_QUIT, 0, 0); 10589 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 10590 CloseHandle(hthread); 10591 CloseHandle(hevent); 10592 ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n"); 10593 /****** end of event filtering test *************/ 10594 10595 /****** start of out of context event test *************/ 10596 hhook = pSetWinEventHook(EVENT_MIN, EVENT_MAX, 0, 10597 win_event_global_hook_proc, GetCurrentProcessId(), 0, 10598 WINEVENT_OUTOFCONTEXT); 10599 ok(hhook != 0, "SetWinEventHook error %d\n", GetLastError()); 10600 10601 hevent = CreateEventA(NULL, 0, 0, NULL); 10602 assert(hevent); 10603 hwnd2 = hevent; 10604 10605 flush_sequence(); 10606 10607 hthread = CreateThread(NULL, 0, win_event_global_thread_proc, &hwnd2, 0, &tid); 10608 ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError()); 10609 10610 ok(WaitForSingleObject(hevent, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 10611 10612 ok_sequence(WmEmptySeq, "empty notify winevents", FALSE); 10613 /* process pending winevent messages */ 10614 ok(!PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE), "msg queue should be empty\n"); 10615 ok_sequence(WmWinEventAlertSeq_2, "alert winevent for out of context proc", FALSE); 10616 10617 flush_sequence(); 10618 /* this one should be received only by old hook proc */ 10619 pNotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_CARET, 0); /* 0x8000 */ 10620 pNotifyWinEvent(EVENT_OBJECT_SHOW, hwnd, OBJID_CARET, 0); /* 0x8002 */ 10621 /* this one should be received only by old hook proc */ 10622 pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, hwnd, OBJID_CARET, 0); /* 0x800C */ 10623 10624 ok_sequence(WmWinEventCaretSeq_2, "caret winevent for incontext proc", FALSE); 10625 /* process pending winevent messages */ 10626 ok(!PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE), "msg queue should be empty\n"); 10627 ok_sequence(WmWinEventCaretSeq_2, "caret winevent for out of context proc", FALSE); 10628 10629 ret = pUnhookWinEvent(hhook); 10630 ok( ret, "UnhookWinEvent error %d\n", GetLastError()); 10631 10632 PostThreadMessageA(tid, WM_QUIT, 0, 0); 10633 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 10634 CloseHandle(hthread); 10635 CloseHandle(hevent); 10636 ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n"); 10637 /****** end of out of context event test *************/ 10638 10639 /****** start of MOUSE_LL hook test *************/ 10640 hCBT_global_hook = SetWindowsHookExA(WH_MOUSE_LL, cbt_global_hook_proc, GetModuleHandleA(0), 0); 10641 /* WH_MOUSE_LL is not supported on Win9x platforms */ 10642 if (!hCBT_global_hook) 10643 { 10644 win_skip("Skipping WH_MOUSE_LL test on this platform\n"); 10645 goto skip_mouse_ll_hook_test; 10646 } 10647 10648 hevent = CreateEventA(NULL, 0, 0, NULL); 10649 assert(hevent); 10650 hwnd2 = hevent; 10651 10652 hthread = CreateThread(NULL, 0, mouse_ll_global_thread_proc, &hwnd2, 0, &tid); 10653 ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError()); 10654 10655 while (WaitForSingleObject(hevent, 100) == WAIT_TIMEOUT) 10656 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 10657 10658 ok_sequence(WmMouseLLHookSeq, "MOUSE_LL hook other thread", FALSE); 10659 flush_sequence(); 10660 10661 mouse_event(MOUSEEVENTF_MOVE, -1, 0, 0, 0); 10662 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); 10663 mouse_event(MOUSEEVENTF_MOVE, 1, 0, 0, 0); 10664 10665 ok_sequence(WmMouseLLHookSeq, "MOUSE_LL hook same thread", FALSE); 10666 10667 ret = UnhookWindowsHookEx(hCBT_global_hook); 10668 ok( ret, "UnhookWindowsHookEx error %d\n", GetLastError()); 10669 10670 PostThreadMessageA(tid, WM_QUIT, 0, 0); 10671 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 10672 CloseHandle(hthread); 10673 CloseHandle(hevent); 10674 ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n"); 10675 /****** end of MOUSE_LL hook test *************/ 10676 skip_mouse_ll_hook_test: 10677 10678 ok(DestroyWindow(hwnd), "failed to destroy window\n"); 10679 } 10680 10681 static void test_set_hook(void) 10682 { 10683 BOOL ret; 10684 HHOOK hhook; 10685 HWINEVENTHOOK hwinevent_hook; 10686 10687 hhook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, GetModuleHandleA(0), GetCurrentThreadId()); 10688 ok(hhook != 0, "local hook does not require hModule set to 0\n"); 10689 UnhookWindowsHookEx(hhook); 10690 10691 if (0) 10692 { 10693 /* this test doesn't pass under Win9x: BUG! */ 10694 SetLastError(0xdeadbeef); 10695 hhook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, 0); 10696 ok(!hhook, "global hook requires hModule != 0\n"); 10697 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD, "unexpected error %d\n", GetLastError()); 10698 } 10699 10700 SetLastError(0xdeadbeef); 10701 hhook = SetWindowsHookExA(WH_CBT, 0, GetModuleHandleA(0), GetCurrentThreadId()); 10702 ok(!hhook, "SetWinEventHook with invalid proc should fail\n"); 10703 ok(GetLastError() == ERROR_INVALID_FILTER_PROC || /* Win2k */ 10704 GetLastError() == 0xdeadbeef, /* Win9x */ 10705 "unexpected error %d\n", GetLastError()); 10706 10707 SetLastError(0xdeadbeef); 10708 ok(!UnhookWindowsHookEx((HHOOK)0xdeadbeef), "UnhookWindowsHookEx succeeded\n"); 10709 ok(GetLastError() == ERROR_INVALID_HOOK_HANDLE || /* Win2k */ 10710 GetLastError() == 0xdeadbeef, /* Win9x */ 10711 "unexpected error %d\n", GetLastError()); 10712 10713 if (!pSetWinEventHook || !pUnhookWinEvent) return; 10714 10715 /* even process local incontext hooks require hmodule */ 10716 SetLastError(0xdeadbeef); 10717 hwinevent_hook = pSetWinEventHook(EVENT_MIN, EVENT_MAX, 0, win_event_proc, 10718 GetCurrentProcessId(), 0, WINEVENT_INCONTEXT); 10719 ok(!hwinevent_hook, "WINEVENT_INCONTEXT requires hModule != 0\n"); 10720 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD || /* Win2k */ 10721 GetLastError() == 0xdeadbeef, /* Win9x */ 10722 "unexpected error %d\n", GetLastError()); 10723 10724 /* even thread local incontext hooks require hmodule */ 10725 SetLastError(0xdeadbeef); 10726 hwinevent_hook = pSetWinEventHook(EVENT_MIN, EVENT_MAX, 0, win_event_proc, 10727 GetCurrentProcessId(), GetCurrentThreadId(), WINEVENT_INCONTEXT); 10728 ok(!hwinevent_hook, "WINEVENT_INCONTEXT requires hModule != 0\n"); 10729 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD || /* Win2k */ 10730 GetLastError() == 0xdeadbeef, /* Win9x */ 10731 "unexpected error %d\n", GetLastError()); 10732 10733 if (0) 10734 { 10735 /* these 3 tests don't pass under Win9x */ 10736 SetLastError(0xdeadbeef); 10737 hwinevent_hook = pSetWinEventHook(1, 0, 0, win_event_proc, 10738 GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT); 10739 ok(!hwinevent_hook, "SetWinEventHook with invalid event range should fail\n"); 10740 ok(GetLastError() == ERROR_INVALID_HOOK_FILTER, "unexpected error %d\n", GetLastError()); 10741 10742 SetLastError(0xdeadbeef); 10743 hwinevent_hook = pSetWinEventHook(-1, 1, 0, win_event_proc, 10744 GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT); 10745 ok(!hwinevent_hook, "SetWinEventHook with invalid event range should fail\n"); 10746 ok(GetLastError() == ERROR_INVALID_HOOK_FILTER, "unexpected error %d\n", GetLastError()); 10747 10748 SetLastError(0xdeadbeef); 10749 hwinevent_hook = pSetWinEventHook(EVENT_MIN, EVENT_MAX, 0, win_event_proc, 10750 0, 0xdeadbeef, WINEVENT_OUTOFCONTEXT); 10751 ok(!hwinevent_hook, "SetWinEventHook with invalid tid should fail\n"); 10752 ok(GetLastError() == ERROR_INVALID_THREAD_ID, "unexpected error %d\n", GetLastError()); 10753 } 10754 10755 SetLastError(0xdeadbeef); 10756 hwinevent_hook = pSetWinEventHook(0, 0, 0, win_event_proc, 10757 GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT); 10758 ok(hwinevent_hook != 0, "SetWinEventHook error %d\n", GetLastError()); 10759 ok(GetLastError() == 0xdeadbeef, "unexpected error %d\n", GetLastError()); 10760 ret = pUnhookWinEvent(hwinevent_hook); 10761 ok( ret, "UnhookWinEvent error %d\n", GetLastError()); 10762 10763 todo_wine { 10764 /* This call succeeds under win2k SP4, but fails under Wine. 10765 Does win2k test/use passed process id? */ 10766 SetLastError(0xdeadbeef); 10767 hwinevent_hook = pSetWinEventHook(EVENT_MIN, EVENT_MAX, 0, win_event_proc, 10768 0xdeadbeef, 0, WINEVENT_OUTOFCONTEXT); 10769 ok(hwinevent_hook != 0, "SetWinEventHook error %d\n", GetLastError()); 10770 ok(GetLastError() == 0xdeadbeef, "unexpected error %d\n", GetLastError()); 10771 ret = pUnhookWinEvent(hwinevent_hook); 10772 ok( ret, "UnhookWinEvent error %d\n", GetLastError()); 10773 } 10774 10775 SetLastError(0xdeadbeef); 10776 ok(!pUnhookWinEvent((HWINEVENTHOOK)0xdeadbeef), "UnhookWinEvent succeeded\n"); 10777 ok(GetLastError() == ERROR_INVALID_HANDLE || /* Win2k */ 10778 GetLastError() == 0xdeadbeef, /* Win9x */ 10779 "unexpected error %d\n", GetLastError()); 10780 } 10781 10782 static HWND hook_hwnd; 10783 static HHOOK recursive_hook; 10784 static int hook_depth, max_hook_depth; 10785 10786 static LRESULT WINAPI rec_get_message_hook(int code, WPARAM w, LPARAM l) 10787 { 10788 LRESULT res; 10789 MSG msg; 10790 BOOL b; 10791 10792 hook_depth++; 10793 if(hook_depth > max_hook_depth) 10794 max_hook_depth = hook_depth; 10795 10796 b = PeekMessageW(&msg, hook_hwnd, 0, 0, PM_NOREMOVE); 10797 ok(b, "PeekMessage failed\n"); 10798 10799 res = CallNextHookEx(recursive_hook, code, w, l); 10800 10801 hook_depth--; 10802 return res; 10803 } 10804 10805 static void test_recursive_hook(void) 10806 { 10807 MSG msg; 10808 BOOL b; 10809 10810 hook_hwnd = CreateWindowA("Static", NULL, WS_POPUP, 0, 0, 200, 60, NULL, NULL, NULL, NULL); 10811 ok(hook_hwnd != NULL, "CreateWindow failed\n"); 10812 10813 recursive_hook = SetWindowsHookExW(WH_GETMESSAGE, rec_get_message_hook, NULL, GetCurrentThreadId()); 10814 ok(recursive_hook != NULL, "SetWindowsHookEx failed\n"); 10815 10816 PostMessageW(hook_hwnd, WM_USER, 0, 0); 10817 PostMessageW(hook_hwnd, WM_USER+1, 0, 0); 10818 10819 hook_depth = 0; 10820 GetMessageW(&msg, hook_hwnd, 0, 0); 10821 ok(15 <= max_hook_depth && max_hook_depth < 45, "max_hook_depth = %d\n", max_hook_depth); 10822 trace("max_hook_depth = %d\n", max_hook_depth); 10823 10824 b = UnhookWindowsHookEx(recursive_hook); 10825 ok(b, "UnhokWindowsHookEx failed\n"); 10826 10827 DestroyWindow(hook_hwnd); 10828 } 10829 10830 static const struct message ScrollWindowPaint1[] = { 10831 { WM_PAINT, sent }, 10832 { WM_ERASEBKGND, sent|beginpaint }, 10833 { WM_GETTEXTLENGTH, sent|optional }, 10834 { WM_PAINT, sent|optional }, 10835 { WM_NCPAINT, sent|beginpaint|optional }, 10836 { WM_GETTEXT, sent|beginpaint|optional }, 10837 { WM_GETTEXT, sent|beginpaint|optional }, 10838 { WM_GETTEXT, sent|beginpaint|optional }, 10839 { WM_GETTEXT, sent|beginpaint|defwinproc|optional }, 10840 { WM_ERASEBKGND, sent|beginpaint|optional }, 10841 { 0 } 10842 }; 10843 10844 static const struct message ScrollWindowPaint2[] = { 10845 { WM_PAINT, sent }, 10846 { 0 } 10847 }; 10848 10849 static void test_scrollwindowex(void) 10850 { 10851 HWND hwnd, hchild; 10852 RECT rect={0,0,130,130}; 10853 10854 hwnd = CreateWindowExA(0, "TestWindowClass", "Test Scroll", 10855 WS_VISIBLE|WS_OVERLAPPEDWINDOW, 10856 100, 100, 200, 200, 0, 0, 0, NULL); 10857 ok (hwnd != 0, "Failed to create overlapped window\n"); 10858 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", 10859 WS_VISIBLE|WS_CAPTION|WS_CHILD, 10860 10, 10, 150, 150, hwnd, 0, 0, NULL); 10861 ok (hchild != 0, "Failed to create child\n"); 10862 UpdateWindow(hwnd); 10863 flush_events(); 10864 flush_sequence(); 10865 10866 /* scroll without the child window */ 10867 trace("start scroll\n"); 10868 ScrollWindowEx( hwnd, 10, 10, &rect, NULL, NULL, NULL, 10869 SW_ERASE|SW_INVALIDATE); 10870 ok_sequence(WmEmptySeq, "ScrollWindowEx", FALSE); 10871 trace("end scroll\n"); 10872 flush_sequence(); 10873 flush_events(); 10874 ok_sequence(ScrollWindowPaint1, "ScrollWindowEx", FALSE); 10875 flush_events(); 10876 flush_sequence(); 10877 10878 /* Now without the SW_ERASE flag */ 10879 trace("start scroll\n"); 10880 ScrollWindowEx( hwnd, 10, 10, &rect, NULL, NULL, NULL, SW_INVALIDATE); 10881 ok_sequence(WmEmptySeq, "ScrollWindowEx", FALSE); 10882 trace("end scroll\n"); 10883 flush_sequence(); 10884 flush_events(); 10885 ok_sequence(ScrollWindowPaint2, "ScrollWindowEx", FALSE); 10886 flush_events(); 10887 flush_sequence(); 10888 10889 /* now scroll the child window as well */ 10890 trace("start scroll\n"); 10891 ScrollWindowEx( hwnd, 10, 10, &rect, NULL, NULL, NULL, 10892 SW_SCROLLCHILDREN|SW_ERASE|SW_INVALIDATE); 10893 /* wine sends WM_POSCHANGING, WM_POSCHANGED messages */ 10894 /* windows sometimes a WM_MOVE */ 10895 ok_sequence(WmEmptySeq, "ScrollWindowEx", TRUE); 10896 trace("end scroll\n"); 10897 flush_sequence(); 10898 flush_events(); 10899 ok_sequence(ScrollWindowPaint1, "ScrollWindowEx", FALSE); 10900 flush_events(); 10901 flush_sequence(); 10902 10903 /* now scroll with ScrollWindow() */ 10904 trace("start scroll with ScrollWindow\n"); 10905 ScrollWindow( hwnd, 5, 5, NULL, NULL); 10906 trace("end scroll\n"); 10907 flush_sequence(); 10908 flush_events(); 10909 ok_sequence(ScrollWindowPaint1, "ScrollWindow", FALSE); 10910 10911 ok(DestroyWindow(hchild), "failed to destroy window\n"); 10912 ok(DestroyWindow(hwnd), "failed to destroy window\n"); 10913 flush_sequence(); 10914 } 10915 10916 static const struct message destroy_window_with_children[] = { 10917 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, /* popup */ 10918 { HCBT_DESTROYWND, hook|lparam, 0, WND_PARENT_ID }, /* parent */ 10919 { 0x0090, sent|optional }, 10920 { HCBT_DESTROYWND, hook|lparam, 0, WND_POPUP_ID }, /* popup */ 10921 { 0x0090, sent|optional }, 10922 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, /* popup */ 10923 { WM_DESTROY, sent|wparam|lparam, 0, WND_POPUP_ID }, /* popup */ 10924 { WM_CAPTURECHANGED, sent|wparam|lparam, 0, WND_POPUP_ID }, /* popup */ 10925 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_POPUP_ID }, /* popup */ 10926 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, /* parent */ 10927 { WM_DESTROY, sent|wparam|lparam, 0, WND_PARENT_ID }, /* parent */ 10928 { WM_DESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 2 }, /* child2 */ 10929 { WM_DESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 1 }, /* child1 */ 10930 { WM_DESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 3 }, /* child3 */ 10931 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 2 }, /* child2 */ 10932 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 3 }, /* child3 */ 10933 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 1 }, /* child1 */ 10934 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_PARENT_ID }, /* parent */ 10935 { 0 } 10936 }; 10937 10938 static void test_DestroyWindow(void) 10939 { 10940 BOOL ret; 10941 HWND parent, child1, child2, child3, child4, test; 10942 UINT_PTR child_id = WND_CHILD_ID + 1; 10943 10944 parent = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, 10945 100, 100, 200, 200, 0, 0, 0, NULL); 10946 assert(parent != 0); 10947 child1 = CreateWindowExA(0, "TestWindowClass", NULL, WS_CHILD, 10948 0, 0, 50, 50, parent, (HMENU)child_id++, 0, NULL); 10949 assert(child1 != 0); 10950 child2 = CreateWindowExA(0, "TestWindowClass", NULL, WS_CHILD, 10951 0, 0, 50, 50, GetDesktopWindow(), (HMENU)child_id++, 0, NULL); 10952 assert(child2 != 0); 10953 child3 = CreateWindowExA(0, "TestWindowClass", NULL, WS_CHILD, 10954 0, 0, 50, 50, child1, (HMENU)child_id++, 0, NULL); 10955 assert(child3 != 0); 10956 child4 = CreateWindowExA(0, "TestWindowClass", NULL, WS_POPUP, 10957 0, 0, 50, 50, parent, 0, 0, NULL); 10958 assert(child4 != 0); 10959 10960 /* test owner/parent of child2 */ 10961 test = GetParent(child2); 10962 ok(test == GetDesktopWindow(), "wrong parent %p\n", test); 10963 ok(!IsChild(parent, child2), "wrong parent/child %p/%p\n", parent, child2); 10964 if(pGetAncestor) { 10965 test = pGetAncestor(child2, GA_PARENT); 10966 ok(test == GetDesktopWindow(), "wrong parent %p\n", test); 10967 } 10968 test = GetWindow(child2, GW_OWNER); 10969 ok(!test, "wrong owner %p\n", test); 10970 10971 test = SetParent(child2, parent); 10972 ok(test == GetDesktopWindow(), "wrong old parent %p\n", test); 10973 10974 /* test owner/parent of the parent */ 10975 test = GetParent(parent); 10976 ok(!test, "wrong parent %p\n", test); 10977 ok(!IsChild(GetDesktopWindow(), parent), "wrong parent/child %p/%p\n", GetDesktopWindow(), parent); 10978 if(pGetAncestor) { 10979 test = pGetAncestor(parent, GA_PARENT); 10980 ok(test == GetDesktopWindow(), "wrong parent %p\n", test); 10981 } 10982 test = GetWindow(parent, GW_OWNER); 10983 ok(!test, "wrong owner %p\n", test); 10984 10985 /* test owner/parent of child1 */ 10986 test = GetParent(child1); 10987 ok(test == parent, "wrong parent %p\n", test); 10988 ok(IsChild(parent, child1), "wrong parent/child %p/%p\n", parent, child1); 10989 if(pGetAncestor) { 10990 test = pGetAncestor(child1, GA_PARENT); 10991 ok(test == parent, "wrong parent %p\n", test); 10992 } 10993 test = GetWindow(child1, GW_OWNER); 10994 ok(!test, "wrong owner %p\n", test); 10995 10996 /* test owner/parent of child2 */ 10997 test = GetParent(child2); 10998 ok(test == parent, "wrong parent %p\n", test); 10999 ok(IsChild(parent, child2), "wrong parent/child %p/%p\n", parent, child2); 11000 if(pGetAncestor) { 11001 test = pGetAncestor(child2, GA_PARENT); 11002 ok(test == parent, "wrong parent %p\n", test); 11003 } 11004 test = GetWindow(child2, GW_OWNER); 11005 ok(!test, "wrong owner %p\n", test); 11006 11007 /* test owner/parent of child3 */ 11008 test = GetParent(child3); 11009 ok(test == child1, "wrong parent %p\n", test); 11010 ok(IsChild(parent, child3), "wrong parent/child %p/%p\n", parent, child3); 11011 if(pGetAncestor) { 11012 test = pGetAncestor(child3, GA_PARENT); 11013 ok(test == child1, "wrong parent %p\n", test); 11014 } 11015 test = GetWindow(child3, GW_OWNER); 11016 ok(!test, "wrong owner %p\n", test); 11017 11018 /* test owner/parent of child4 */ 11019 test = GetParent(child4); 11020 ok(test == parent, "wrong parent %p\n", test); 11021 ok(!IsChild(parent, child4), "wrong parent/child %p/%p\n", parent, child4); 11022 if(pGetAncestor) { 11023 test = pGetAncestor(child4, GA_PARENT); 11024 ok(test == GetDesktopWindow(), "wrong parent %p\n", test); 11025 } 11026 test = GetWindow(child4, GW_OWNER); 11027 ok(test == parent, "wrong owner %p\n", test); 11028 11029 flush_sequence(); 11030 11031 trace("parent %p, child1 %p, child2 %p, child3 %p, child4 %p\n", 11032 parent, child1, child2, child3, child4); 11033 11034 SetCapture(child4); 11035 test = GetCapture(); 11036 ok(test == child4, "wrong capture window %p\n", test); 11037 11038 test_DestroyWindow_flag = TRUE; 11039 ret = DestroyWindow(parent); 11040 ok( ret, "DestroyWindow() error %d\n", GetLastError()); 11041 test_DestroyWindow_flag = FALSE; 11042 ok_sequence(destroy_window_with_children, "destroy window with children", FALSE); 11043 11044 ok(!IsWindow(parent), "parent still exists\n"); 11045 ok(!IsWindow(child1), "child1 still exists\n"); 11046 ok(!IsWindow(child2), "child2 still exists\n"); 11047 ok(!IsWindow(child3), "child3 still exists\n"); 11048 ok(!IsWindow(child4), "child4 still exists\n"); 11049 11050 test = GetCapture(); 11051 ok(!test, "wrong capture window %p\n", test); 11052 } 11053 11054 11055 static const struct message WmDispatchPaint[] = { 11056 { WM_NCPAINT, sent }, 11057 { WM_GETTEXT, sent|defwinproc|optional }, 11058 { WM_GETTEXT, sent|defwinproc|optional }, 11059 { WM_ERASEBKGND, sent }, 11060 { 0 } 11061 }; 11062 11063 static LRESULT WINAPI DispatchMessageCheckProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 11064 { 11065 if (message == WM_PAINT) return 0; 11066 return MsgCheckProcA( hwnd, message, wParam, lParam ); 11067 } 11068 11069 static void test_DispatchMessage(void) 11070 { 11071 RECT rect; 11072 MSG msg; 11073 int count; 11074 HWND hwnd = CreateWindowA( "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, 11075 100, 100, 200, 200, 0, 0, 0, NULL); 11076 ShowWindow( hwnd, SW_SHOW ); 11077 UpdateWindow( hwnd ); 11078 flush_events(); 11079 flush_sequence(); 11080 SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (LONG_PTR)DispatchMessageCheckProc ); 11081 11082 SetRect( &rect, -5, -5, 5, 5 ); 11083 RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE|RDW_ERASE|RDW_FRAME ); 11084 count = 0; 11085 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) 11086 { 11087 if (msg.message != WM_PAINT) DispatchMessageA( &msg ); 11088 else 11089 { 11090 flush_sequence(); 11091 DispatchMessageA( &msg ); 11092 /* DispatchMessage will send WM_NCPAINT if non client area is still invalid after WM_PAINT */ 11093 if (!count) ok_sequence( WmDispatchPaint, "WmDispatchPaint", FALSE ); 11094 else ok_sequence( WmEmptySeq, "WmEmpty", FALSE ); 11095 if (++count > 10) break; 11096 } 11097 } 11098 ok( msg.message == WM_PAINT && count > 10, "WM_PAINT messages stopped\n" ); 11099 11100 trace("now without DispatchMessage\n"); 11101 flush_sequence(); 11102 RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE|RDW_ERASE|RDW_FRAME ); 11103 count = 0; 11104 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) 11105 { 11106 if (msg.message != WM_PAINT) DispatchMessageA( &msg ); 11107 else 11108 { 11109 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 ); 11110 flush_sequence(); 11111 /* this will send WM_NCCPAINT just like DispatchMessage does */ 11112 GetUpdateRgn( hwnd, hrgn, TRUE ); 11113 ok_sequence( WmDispatchPaint, "WmDispatchPaint", FALSE ); 11114 DeleteObject( hrgn ); 11115 GetClientRect( hwnd, &rect ); 11116 ValidateRect( hwnd, &rect ); /* this will stop WM_PAINTs */ 11117 ok( !count, "Got multiple WM_PAINTs\n" ); 11118 if (++count > 10) break; 11119 } 11120 } 11121 11122 flush_sequence(); 11123 RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE|RDW_ERASE|RDW_FRAME ); 11124 count = 0; 11125 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) 11126 { 11127 if (msg.message != WM_PAINT) DispatchMessageA( &msg ); 11128 else 11129 { 11130 HDC hdc; 11131 11132 flush_sequence(); 11133 hdc = BeginPaint( hwnd, NULL ); 11134 ok( !hdc, "got valid hdc %p from BeginPaint\n", hdc ); 11135 ok( !EndPaint( hwnd, NULL ), "EndPaint succeeded\n" ); 11136 ok_sequence( WmDispatchPaint, "WmDispatchPaint", FALSE ); 11137 ok( !count, "Got multiple WM_PAINTs\n" ); 11138 if (++count > 10) break; 11139 } 11140 } 11141 DestroyWindow(hwnd); 11142 } 11143 11144 11145 static const struct message WmUser[] = { 11146 { WM_USER, sent }, 11147 { 0 } 11148 }; 11149 11150 struct sendmsg_info 11151 { 11152 HWND hwnd; 11153 DWORD timeout; 11154 DWORD ret; 11155 }; 11156 11157 static DWORD CALLBACK send_msg_thread( LPVOID arg ) 11158 { 11159 struct sendmsg_info *info = arg; 11160 SetLastError( 0xdeadbeef ); 11161 info->ret = SendMessageTimeoutA( info->hwnd, WM_USER, 0, 0, 0, info->timeout, NULL ); 11162 if (!info->ret) ok( GetLastError() == ERROR_TIMEOUT || 11163 broken(GetLastError() == 0), /* win9x */ 11164 "unexpected error %d\n", GetLastError()); 11165 return 0; 11166 } 11167 11168 static void wait_for_thread( HANDLE thread ) 11169 { 11170 while (MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_SENDMESSAGE) != WAIT_OBJECT_0) 11171 { 11172 MSG msg; 11173 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA(&msg); 11174 } 11175 } 11176 11177 static LRESULT WINAPI send_msg_delay_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 11178 { 11179 if (message == WM_USER) Sleep(200); 11180 return MsgCheckProcA( hwnd, message, wParam, lParam ); 11181 } 11182 11183 static void test_SendMessageTimeout(void) 11184 { 11185 HANDLE thread; 11186 struct sendmsg_info info; 11187 DWORD tid; 11188 BOOL is_win9x; 11189 11190 info.hwnd = CreateWindowA( "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, 11191 100, 100, 200, 200, 0, 0, 0, NULL); 11192 flush_events(); 11193 flush_sequence(); 11194 11195 info.timeout = 1000; 11196 info.ret = 0xdeadbeef; 11197 thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid ); 11198 wait_for_thread( thread ); 11199 CloseHandle( thread ); 11200 ok( info.ret == 1, "SendMessageTimeout failed\n" ); 11201 ok_sequence( WmUser, "WmUser", FALSE ); 11202 11203 info.timeout = 1; 11204 info.ret = 0xdeadbeef; 11205 thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid ); 11206 Sleep(100); /* SendMessageTimeout should time out here */ 11207 wait_for_thread( thread ); 11208 CloseHandle( thread ); 11209 ok( info.ret == 0, "SendMessageTimeout succeeded\n" ); 11210 ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE ); 11211 11212 /* 0 means infinite timeout (but not on win9x) */ 11213 info.timeout = 0; 11214 info.ret = 0xdeadbeef; 11215 thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid ); 11216 Sleep(100); 11217 wait_for_thread( thread ); 11218 CloseHandle( thread ); 11219 is_win9x = !info.ret; 11220 if (is_win9x) ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE ); 11221 else ok_sequence( WmUser, "WmUser", FALSE ); 11222 11223 /* timeout is treated as signed despite the prototype (but not on win9x) */ 11224 info.timeout = 0x7fffffff; 11225 info.ret = 0xdeadbeef; 11226 thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid ); 11227 Sleep(100); 11228 wait_for_thread( thread ); 11229 CloseHandle( thread ); 11230 ok( info.ret == 1, "SendMessageTimeout failed\n" ); 11231 ok_sequence( WmUser, "WmUser", FALSE ); 11232 11233 info.timeout = 0x80000000; 11234 info.ret = 0xdeadbeef; 11235 thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid ); 11236 Sleep(100); 11237 wait_for_thread( thread ); 11238 CloseHandle( thread ); 11239 if (is_win9x) 11240 { 11241 ok( info.ret == 1, "SendMessageTimeout failed\n" ); 11242 ok_sequence( WmUser, "WmUser", FALSE ); 11243 } 11244 else 11245 { 11246 ok( info.ret == 0, "SendMessageTimeout succeeded\n" ); 11247 ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE ); 11248 } 11249 11250 /* now check for timeout during message processing */ 11251 SetWindowLongPtrA( info.hwnd, GWLP_WNDPROC, (LONG_PTR)send_msg_delay_proc ); 11252 info.timeout = 100; 11253 info.ret = 0xdeadbeef; 11254 thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid ); 11255 wait_for_thread( thread ); 11256 CloseHandle( thread ); 11257 /* we should time out but still get the message */ 11258 ok( info.ret == 0, "SendMessageTimeout failed\n" ); 11259 ok_sequence( WmUser, "WmUser", FALSE ); 11260 11261 DestroyWindow( info.hwnd ); 11262 } 11263 11264 11265 /****************** edit message test *************************/ 11266 #define ID_EDIT 0x1234 11267 static const struct message sl_edit_setfocus[] = 11268 { 11269 { HCBT_SETFOCUS, hook }, 11270 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 11271 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 11272 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 11273 { WM_SETFOCUS, sent|wparam, 0 }, 11274 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 10 }, 11275 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 15 }, 11276 { WM_CTLCOLOREDIT, sent|parent }, 11277 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 11 }, 11278 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11279 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11280 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) }, 11281 { 0 } 11282 }; 11283 static const struct message sl_edit_invisible[] = 11284 { 11285 { HCBT_SETFOCUS, hook }, 11286 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 11287 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 11288 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 11289 { WM_KILLFOCUS, sent|parent }, 11290 { WM_SETFOCUS, sent }, 11291 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) }, 11292 { 0 } 11293 }; 11294 static const struct message ml_edit_setfocus[] = 11295 { 11296 { HCBT_SETFOCUS, hook }, 11297 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 11298 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 11299 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 11300 { WM_SETFOCUS, sent|wparam, 0 }, 11301 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 10 }, 11302 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 11 }, 11303 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11304 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11305 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) }, 11306 { 0 } 11307 }; 11308 static const struct message sl_edit_killfocus[] = 11309 { 11310 { HCBT_SETFOCUS, hook }, 11311 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 11312 { WM_KILLFOCUS, sent|wparam, 0 }, 11313 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11314 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11315 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_KILLFOCUS) }, 11316 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 11317 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, 11318 { 0 } 11319 }; 11320 static const struct message sl_edit_lbutton_dblclk[] = 11321 { 11322 { WM_LBUTTONDBLCLK, sent }, 11323 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, 11324 { 0 } 11325 }; 11326 static const struct message sl_edit_lbutton_down[] = 11327 { 11328 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 }, 11329 { HCBT_SETFOCUS, hook }, 11330 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 11331 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 11332 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 11333 { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, 11334 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 10 }, 11335 { WM_CTLCOLOREDIT, sent|parent }, 11336 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 11 }, 11337 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11338 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11339 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11340 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) }, 11341 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, 11342 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11343 { WM_CTLCOLOREDIT, sent|parent|optional }, 11344 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 11 }, 11345 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11346 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11347 { 0 } 11348 }; 11349 static const struct message ml_edit_lbutton_down[] = 11350 { 11351 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 }, 11352 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, 11353 { HCBT_SETFOCUS, hook }, 11354 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 11355 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 11356 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 11357 { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, 11358 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 10 }, 11359 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 11 }, 11360 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11361 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11362 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) }, 11363 { 0 } 11364 }; 11365 static const struct message sl_edit_lbutton_up[] = 11366 { 11367 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 }, 11368 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11369 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, 11370 { WM_CAPTURECHANGED, sent|defwinproc }, 11371 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11372 { 0 } 11373 }; 11374 static const struct message ml_edit_lbutton_up[] = 11375 { 11376 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 }, 11377 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, 11378 { WM_CAPTURECHANGED, sent|defwinproc }, 11379 { 0 } 11380 }; 11381 11382 static WNDPROC old_edit_proc; 11383 11384 static LRESULT CALLBACK edit_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 11385 { 11386 static LONG defwndproc_counter = 0; 11387 LRESULT ret; 11388 struct recvd_message msg; 11389 11390 if (ignore_message( message )) return 0; 11391 11392 msg.hwnd = hwnd; 11393 msg.message = message; 11394 msg.flags = sent|wparam|lparam; 11395 if (defwndproc_counter) msg.flags |= defwinproc; 11396 msg.wParam = wParam; 11397 msg.lParam = lParam; 11398 msg.descr = "edit"; 11399 add_message(&msg); 11400 11401 defwndproc_counter++; 11402 ret = CallWindowProcA(old_edit_proc, hwnd, message, wParam, lParam); 11403 defwndproc_counter--; 11404 11405 return ret; 11406 } 11407 11408 static void subclass_edit(void) 11409 { 11410 WNDCLASSA cls; 11411 11412 if (!GetClassInfoA(0, "edit", &cls)) assert(0); 11413 11414 old_edit_proc = cls.lpfnWndProc; 11415 11416 cls.hInstance = GetModuleHandleA(NULL); 11417 cls.lpfnWndProc = edit_hook_proc; 11418 cls.lpszClassName = "my_edit_class"; 11419 UnregisterClassA(cls.lpszClassName, cls.hInstance); 11420 if (!RegisterClassA(&cls)) assert(0); 11421 } 11422 11423 static void test_edit_messages(void) 11424 { 11425 HWND hwnd, parent; 11426 DWORD dlg_code; 11427 11428 subclass_edit(); 11429 log_all_parent_messages++; 11430 11431 parent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 11432 100, 100, 200, 200, 0, 0, 0, NULL); 11433 ok (parent != 0, "Failed to create parent window\n"); 11434 11435 /* test single line edit */ 11436 hwnd = CreateWindowExA(0, "my_edit_class", "test", WS_CHILD, 11437 0, 0, 80, 20, parent, (HMENU)ID_EDIT, 0, NULL); 11438 ok(hwnd != 0, "Failed to create edit window\n"); 11439 11440 dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0); 11441 ok(dlg_code == (DLGC_WANTCHARS|DLGC_HASSETSEL|DLGC_WANTARROWS), "wrong dlg_code %08x\n", dlg_code); 11442 11443 flush_sequence(); 11444 SetFocus(hwnd); 11445 ok_sequence(sl_edit_invisible, "SetFocus(hwnd) on an invisible edit", FALSE); 11446 11447 ShowWindow(hwnd, SW_SHOW); 11448 UpdateWindow(hwnd); 11449 SetFocus(0); 11450 flush_sequence(); 11451 11452 SetFocus(hwnd); 11453 ok_sequence(sl_edit_setfocus, "SetFocus(hwnd) on an edit", FALSE); 11454 11455 SetFocus(0); 11456 ok_sequence(sl_edit_killfocus, "SetFocus(0) on an edit", FALSE); 11457 11458 SetFocus(0); 11459 ReleaseCapture(); 11460 flush_sequence(); 11461 11462 SendMessageA(hwnd, WM_LBUTTONDBLCLK, 0, 0); 11463 ok_sequence(sl_edit_lbutton_dblclk, "WM_LBUTTONDBLCLK on an edit", FALSE); 11464 11465 SetFocus(0); 11466 ReleaseCapture(); 11467 flush_sequence(); 11468 11469 SendMessageA(hwnd, WM_LBUTTONDOWN, 0, 0); 11470 ok_sequence(sl_edit_lbutton_down, "WM_LBUTTONDOWN on an edit", FALSE); 11471 11472 SendMessageA(hwnd, WM_LBUTTONUP, 0, 0); 11473 ok_sequence(sl_edit_lbutton_up, "WM_LBUTTONUP on an edit", FALSE); 11474 11475 DestroyWindow(hwnd); 11476 11477 /* test multiline edit */ 11478 hwnd = CreateWindowExA(0, "my_edit_class", "test", WS_CHILD | ES_MULTILINE, 11479 0, 0, 80, 20, parent, (HMENU)ID_EDIT, 0, NULL); 11480 ok(hwnd != 0, "Failed to create edit window\n"); 11481 11482 dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0); 11483 ok(dlg_code == (DLGC_WANTCHARS|DLGC_HASSETSEL|DLGC_WANTARROWS|DLGC_WANTALLKEYS), 11484 "wrong dlg_code %08x\n", dlg_code); 11485 11486 ShowWindow(hwnd, SW_SHOW); 11487 UpdateWindow(hwnd); 11488 SetFocus(0); 11489 flush_sequence(); 11490 11491 SetFocus(hwnd); 11492 ok_sequence(ml_edit_setfocus, "SetFocus(hwnd) on multiline edit", FALSE); 11493 11494 SetFocus(0); 11495 ok_sequence(sl_edit_killfocus, "SetFocus(0) on multiline edit", FALSE); 11496 11497 SetFocus(0); 11498 ReleaseCapture(); 11499 flush_sequence(); 11500 11501 SendMessageA(hwnd, WM_LBUTTONDBLCLK, 0, 0); 11502 ok_sequence(sl_edit_lbutton_dblclk, "WM_LBUTTONDBLCLK on multiline edit", FALSE); 11503 11504 SetFocus(0); 11505 ReleaseCapture(); 11506 flush_sequence(); 11507 11508 SendMessageA(hwnd, WM_LBUTTONDOWN, 0, 0); 11509 ok_sequence(ml_edit_lbutton_down, "WM_LBUTTONDOWN on multiline edit", FALSE); 11510 11511 SendMessageA(hwnd, WM_LBUTTONUP, 0, 0); 11512 ok_sequence(ml_edit_lbutton_up, "WM_LBUTTONUP on multiline edit", FALSE); 11513 11514 DestroyWindow(hwnd); 11515 DestroyWindow(parent); 11516 11517 log_all_parent_messages--; 11518 } 11519 11520 /**************************** End of Edit test ******************************/ 11521 11522 static const struct message WmKeyDownSkippedSeq[] = 11523 { 11524 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */ 11525 { 0 } 11526 }; 11527 static const struct message WmKeyDownWasDownSkippedSeq[] = 11528 { 11529 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0x40000001 }, /* XP */ 11530 { 0 } 11531 }; 11532 static const struct message WmKeyUpSkippedSeq[] = 11533 { 11534 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */ 11535 { 0 } 11536 }; 11537 static const struct message WmUserKeyUpSkippedSeq[] = 11538 { 11539 { WM_USER, sent }, 11540 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */ 11541 { 0 } 11542 }; 11543 11544 #define EV_STOP 0 11545 #define EV_SENDMSG 1 11546 #define EV_ACK 2 11547 11548 struct peekmsg_info 11549 { 11550 HWND hwnd; 11551 HANDLE hevent[3]; /* 0 - start/stop, 1 - SendMessage, 2 - ack */ 11552 }; 11553 11554 static DWORD CALLBACK send_msg_thread_2(void *param) 11555 { 11556 DWORD ret; 11557 struct peekmsg_info *info = param; 11558 11559 trace("thread: looping\n"); 11560 SetEvent(info->hevent[EV_ACK]); 11561 11562 while (1) 11563 { 11564 ret = WaitForMultipleObjects(2, info->hevent, FALSE, INFINITE); 11565 11566 switch (ret) 11567 { 11568 case WAIT_OBJECT_0 + EV_STOP: 11569 trace("thread: exiting\n"); 11570 return 0; 11571 11572 case WAIT_OBJECT_0 + EV_SENDMSG: 11573 trace("thread: sending message\n"); 11574 ret = SendNotifyMessageA(info->hwnd, WM_USER, 0, 0); 11575 ok(ret, "SendNotifyMessageA failed error %u\n", GetLastError()); 11576 SetEvent(info->hevent[EV_ACK]); 11577 break; 11578 11579 default: 11580 trace("unexpected return: %04x\n", ret); 11581 assert(0); 11582 break; 11583 } 11584 } 11585 return 0; 11586 } 11587 11588 static void test_PeekMessage(void) 11589 { 11590 MSG msg; 11591 HANDLE hthread; 11592 DWORD tid, qstatus; 11593 UINT qs_all_input = QS_ALLINPUT; 11594 UINT qs_input = QS_INPUT; 11595 BOOL ret; 11596 struct peekmsg_info info; 11597 11598 info.hwnd = CreateWindowA("TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, 11599 100, 100, 200, 200, 0, 0, 0, NULL); 11600 assert(info.hwnd); 11601 ShowWindow(info.hwnd, SW_SHOW); 11602 UpdateWindow(info.hwnd); 11603 SetFocus(info.hwnd); 11604 11605 info.hevent[EV_STOP] = CreateEventA(NULL, 0, 0, NULL); 11606 info.hevent[EV_SENDMSG] = CreateEventA(NULL, 0, 0, NULL); 11607 info.hevent[EV_ACK] = CreateEventA(NULL, 0, 0, NULL); 11608 11609 hthread = CreateThread(NULL, 0, send_msg_thread_2, &info, 0, &tid); 11610 WaitForSingleObject(info.hevent[EV_ACK], 10000); 11611 11612 flush_events(); 11613 flush_sequence(); 11614 11615 SetLastError(0xdeadbeef); 11616 qstatus = GetQueueStatus(qs_all_input); 11617 if (GetLastError() == ERROR_INVALID_FLAGS) 11618 { 11619 trace("QS_RAWINPUT not supported on this platform\n"); 11620 qs_all_input &= ~QS_RAWINPUT; 11621 qs_input &= ~QS_RAWINPUT; 11622 } 11623 if (qstatus & QS_POSTMESSAGE) 11624 { 11625 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) /* nothing */ ; 11626 qstatus = GetQueueStatus(qs_all_input); 11627 } 11628 ok(qstatus == 0, "wrong qstatus %08x\n", qstatus); 11629 11630 trace("signalling to send message\n"); 11631 SetEvent(info.hevent[EV_SENDMSG]); 11632 WaitForSingleObject(info.hevent[EV_ACK], INFINITE); 11633 11634 /* pass invalid QS_xxxx flags */ 11635 SetLastError(0xdeadbeef); 11636 qstatus = GetQueueStatus(0xffffffff); 11637 ok(qstatus == 0 || broken(qstatus) /* win9x */, "GetQueueStatus should fail: %08x\n", qstatus); 11638 if (!qstatus) 11639 { 11640 ok(GetLastError() == ERROR_INVALID_FLAGS, "wrong error %d\n", GetLastError()); 11641 qstatus = GetQueueStatus(qs_all_input); 11642 } 11643 qstatus &= ~MAKELONG( 0x4000, 0x4000 ); /* sometimes set on Win95 */ 11644 ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE), 11645 "wrong qstatus %08x\n", qstatus); 11646 11647 msg.message = 0; 11648 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); 11649 ok(!ret, 11650 "PeekMessageA should have returned FALSE instead of msg %04x\n", 11651 msg.message); 11652 ok_sequence(WmUser, "WmUser", FALSE); 11653 11654 qstatus = GetQueueStatus(qs_all_input); 11655 ok(qstatus == 0, "wrong qstatus %08x\n", qstatus); 11656 11657 keybd_event('N', 0, 0, 0); 11658 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 11659 qstatus = GetQueueStatus(qs_all_input); 11660 if (!(qstatus & MAKELONG(QS_KEY, QS_KEY))) 11661 { 11662 skip( "queuing key events not supported\n" ); 11663 goto done; 11664 } 11665 ok(qstatus == MAKELONG(QS_KEY, QS_KEY) || 11666 /* keybd_event seems to trigger a sent message on NT4 */ 11667 qstatus == MAKELONG(QS_KEY|QS_SENDMESSAGE, QS_KEY|QS_SENDMESSAGE), 11668 "wrong qstatus %08x\n", qstatus); 11669 11670 PostMessageA(info.hwnd, WM_CHAR, 'z', 0); 11671 qstatus = GetQueueStatus(qs_all_input); 11672 ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY) || 11673 qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY|QS_SENDMESSAGE), 11674 "wrong qstatus %08x\n", qstatus); 11675 11676 InvalidateRect(info.hwnd, NULL, FALSE); 11677 qstatus = GetQueueStatus(qs_all_input); 11678 ok(qstatus == MAKELONG(QS_PAINT, QS_PAINT|QS_POSTMESSAGE|QS_KEY) || 11679 qstatus == MAKELONG(QS_PAINT, QS_PAINT|QS_POSTMESSAGE|QS_KEY|QS_SENDMESSAGE), 11680 "wrong qstatus %08x\n", qstatus); 11681 11682 trace("signalling to send message\n"); 11683 SetEvent(info.hevent[EV_SENDMSG]); 11684 WaitForSingleObject(info.hevent[EV_ACK], INFINITE); 11685 11686 qstatus = GetQueueStatus(qs_all_input); 11687 ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_PAINT|QS_POSTMESSAGE|QS_KEY), 11688 "wrong qstatus %08x\n", qstatus); 11689 11690 msg.message = 0; 11691 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | (qs_input << 16)); 11692 if (ret && msg.message == WM_CHAR) 11693 { 11694 win_skip( "PM_QS_* flags not supported in PeekMessage\n" ); 11695 goto done; 11696 } 11697 ok(!ret, 11698 "PeekMessageA should have returned FALSE instead of msg %04x\n", 11699 msg.message); 11700 if (!sequence_cnt) /* nt4 doesn't fetch anything with PM_QS_* flags */ 11701 { 11702 win_skip( "PM_QS_* flags not supported in PeekMessage\n" ); 11703 goto done; 11704 } 11705 ok_sequence(WmUser, "WmUser", FALSE); 11706 11707 qstatus = GetQueueStatus(qs_all_input); 11708 ok(qstatus == MAKELONG(0, QS_PAINT|QS_POSTMESSAGE|QS_KEY), 11709 "wrong qstatus %08x\n", qstatus); 11710 11711 trace("signalling to send message\n"); 11712 SetEvent(info.hevent[EV_SENDMSG]); 11713 WaitForSingleObject(info.hevent[EV_ACK], INFINITE); 11714 11715 qstatus = GetQueueStatus(qs_all_input); 11716 ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_PAINT|QS_POSTMESSAGE|QS_KEY), 11717 "wrong qstatus %08x\n", qstatus); 11718 11719 msg.message = 0; 11720 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_POSTMESSAGE ); 11721 ok(!ret, 11722 "PeekMessageA should have returned FALSE instead of msg %04x\n", 11723 msg.message); 11724 ok_sequence(WmUser, "WmUser", FALSE); 11725 11726 qstatus = GetQueueStatus(qs_all_input); 11727 ok(qstatus == MAKELONG(0, QS_PAINT|QS_POSTMESSAGE|QS_KEY), 11728 "wrong qstatus %08x\n", qstatus); 11729 11730 msg.message = 0; 11731 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_POSTMESSAGE); 11732 ok(ret && msg.message == WM_CHAR && msg.wParam == 'z', 11733 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n", 11734 ret, msg.message, msg.wParam); 11735 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE); 11736 11737 qstatus = GetQueueStatus(qs_all_input); 11738 ok(qstatus == MAKELONG(0, QS_PAINT|QS_KEY), 11739 "wrong qstatus %08x\n", qstatus); 11740 11741 msg.message = 0; 11742 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_POSTMESSAGE); 11743 ok(!ret, 11744 "PeekMessageA should have returned FALSE instead of msg %04x\n", 11745 msg.message); 11746 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE); 11747 11748 qstatus = GetQueueStatus(qs_all_input); 11749 ok(qstatus == MAKELONG(0, QS_PAINT|QS_KEY), 11750 "wrong qstatus %08x\n", qstatus); 11751 11752 msg.message = 0; 11753 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_PAINT); 11754 ok(ret && msg.message == WM_PAINT, 11755 "got %d and %04x instead of TRUE and WM_PAINT\n", ret, msg.message); 11756 DispatchMessageA(&msg); 11757 ok_sequence(WmPaint, "WmPaint", FALSE); 11758 11759 qstatus = GetQueueStatus(qs_all_input); 11760 ok(qstatus == MAKELONG(0, QS_KEY), 11761 "wrong qstatus %08x\n", qstatus); 11762 11763 msg.message = 0; 11764 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_PAINT); 11765 ok(!ret, 11766 "PeekMessageA should have returned FALSE instead of msg %04x\n", 11767 msg.message); 11768 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE); 11769 11770 qstatus = GetQueueStatus(qs_all_input); 11771 ok(qstatus == MAKELONG(0, QS_KEY), 11772 "wrong qstatus %08x\n", qstatus); 11773 11774 trace("signalling to send message\n"); 11775 SetEvent(info.hevent[EV_SENDMSG]); 11776 WaitForSingleObject(info.hevent[EV_ACK], INFINITE); 11777 11778 qstatus = GetQueueStatus(qs_all_input); 11779 ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_KEY), 11780 "wrong qstatus %08x\n", qstatus); 11781 11782 PostMessageA(info.hwnd, WM_CHAR, 'z', 0); 11783 11784 qstatus = GetQueueStatus(qs_all_input); 11785 ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_SENDMESSAGE|QS_POSTMESSAGE|QS_KEY), 11786 "wrong qstatus %08x\n", qstatus); 11787 11788 msg.message = 0; 11789 ret = PeekMessageA(&msg, 0, WM_CHAR, WM_CHAR, PM_REMOVE); 11790 ok(ret && msg.message == WM_CHAR && msg.wParam == 'z', 11791 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n", 11792 ret, msg.message, msg.wParam); 11793 ok_sequence(WmUser, "WmUser", FALSE); 11794 11795 qstatus = GetQueueStatus(qs_all_input); 11796 ok(qstatus == MAKELONG(0, QS_KEY), 11797 "wrong qstatus %08x\n", qstatus); 11798 11799 msg.message = 0; 11800 ret = PeekMessageA(&msg, 0, WM_CHAR, WM_CHAR, PM_REMOVE); 11801 ok(!ret, 11802 "PeekMessageA should have returned FALSE instead of msg %04x\n", 11803 msg.message); 11804 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE); 11805 11806 qstatus = GetQueueStatus(qs_all_input); 11807 ok(qstatus == MAKELONG(0, QS_KEY), 11808 "wrong qstatus %08x\n", qstatus); 11809 11810 PostMessageA(info.hwnd, WM_CHAR, 'z', 0); 11811 11812 qstatus = GetQueueStatus(qs_all_input); 11813 ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY), 11814 "wrong qstatus %08x\n", qstatus); 11815 11816 trace("signalling to send message\n"); 11817 SetEvent(info.hevent[EV_SENDMSG]); 11818 WaitForSingleObject(info.hevent[EV_ACK], INFINITE); 11819 11820 qstatus = GetQueueStatus(qs_all_input); 11821 ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_POSTMESSAGE|QS_KEY), 11822 "wrong qstatus %08x\n", qstatus); 11823 11824 msg.message = 0; 11825 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | (QS_KEY << 16)); 11826 ok(!ret, 11827 "PeekMessageA should have returned FALSE instead of msg %04x\n", 11828 msg.message); 11829 ok_sequence(WmUser, "WmUser", FALSE); 11830 11831 qstatus = GetQueueStatus(qs_all_input); 11832 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE|QS_KEY), 11833 "wrong qstatus %08x\n", qstatus); 11834 11835 msg.message = 0; 11836 if (qs_all_input & QS_RAWINPUT) /* use QS_RAWINPUT only if supported */ 11837 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | (QS_RAWINPUT << 16)); 11838 else /* workaround for a missing QS_RAWINPUT support */ 11839 ret = PeekMessageA(&msg, 0, WM_KEYDOWN, WM_KEYDOWN, PM_REMOVE); 11840 ok(ret && msg.message == WM_KEYDOWN && msg.wParam == 'N', 11841 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n", 11842 ret, msg.message, msg.wParam); 11843 ok_sequence(WmKeyDownSkippedSeq, "WmKeyDownSkippedSeq", FALSE); 11844 11845 qstatus = GetQueueStatus(qs_all_input); 11846 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE|QS_KEY), 11847 "wrong qstatus %08x\n", qstatus); 11848 11849 msg.message = 0; 11850 if (qs_all_input & QS_RAWINPUT) /* use QS_RAWINPUT only if supported */ 11851 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | (QS_RAWINPUT << 16)); 11852 else /* workaround for a missing QS_RAWINPUT support */ 11853 ret = PeekMessageA(&msg, 0, WM_KEYUP, WM_KEYUP, PM_REMOVE); 11854 ok(ret && msg.message == WM_KEYUP && msg.wParam == 'N', 11855 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYUP wParam 'N'\n", 11856 ret, msg.message, msg.wParam); 11857 ok_sequence(WmKeyUpSkippedSeq, "WmKeyUpSkippedSeq", FALSE); 11858 11859 qstatus = GetQueueStatus(qs_all_input); 11860 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE), 11861 "wrong qstatus %08x\n", qstatus); 11862 11863 msg.message = 0; 11864 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE); 11865 ok(!ret, 11866 "PeekMessageA should have returned FALSE instead of msg %04x\n", 11867 msg.message); 11868 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE); 11869 11870 qstatus = GetQueueStatus(qs_all_input); 11871 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE), 11872 "wrong qstatus %08x\n", qstatus); 11873 11874 msg.message = 0; 11875 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); 11876 ok(ret && msg.message == WM_CHAR && msg.wParam == 'z', 11877 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n", 11878 ret, msg.message, msg.wParam); 11879 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE); 11880 11881 qstatus = GetQueueStatus(qs_all_input); 11882 ok(qstatus == 0, 11883 "wrong qstatus %08x\n", qstatus); 11884 11885 msg.message = 0; 11886 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); 11887 ok(!ret, 11888 "PeekMessageA should have returned FALSE instead of msg %04x\n", 11889 msg.message); 11890 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE); 11891 11892 qstatus = GetQueueStatus(qs_all_input); 11893 ok(qstatus == 0, 11894 "wrong qstatus %08x\n", qstatus); 11895 11896 /* test whether presence of the quit flag in the queue affects 11897 * the queue state 11898 */ 11899 PostQuitMessage(0x1234abcd); 11900 11901 qstatus = GetQueueStatus(qs_all_input); 11902 ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE), 11903 "wrong qstatus %08x\n", qstatus); 11904 11905 PostMessageA(info.hwnd, WM_USER, 0, 0); 11906 11907 qstatus = GetQueueStatus(qs_all_input); 11908 ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE), 11909 "wrong qstatus %08x\n", qstatus); 11910 11911 msg.message = 0; 11912 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); 11913 ok(ret && msg.message == WM_USER, 11914 "got %d and %04x instead of TRUE and WM_USER\n", ret, msg.message); 11915 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE); 11916 11917 qstatus = GetQueueStatus(qs_all_input); 11918 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE), 11919 "wrong qstatus %08x\n", qstatus); 11920 11921 msg.message = 0; 11922 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); 11923 ok(ret && msg.message == WM_QUIT, 11924 "got %d and %04x instead of TRUE and WM_QUIT\n", ret, msg.message); 11925 ok(msg.wParam == 0x1234abcd, "got wParam %08lx instead of 0x1234abcd\n", msg.wParam); 11926 ok(msg.lParam == 0, "got lParam %08lx instead of 0\n", msg.lParam); 11927 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE); 11928 11929 qstatus = GetQueueStatus(qs_all_input); 11930 todo_wine { 11931 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE), 11932 "wrong qstatus %08x\n", qstatus); 11933 } 11934 11935 msg.message = 0; 11936 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); 11937 ok(!ret, 11938 "PeekMessageA should have returned FALSE instead of msg %04x\n", 11939 msg.message); 11940 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE); 11941 11942 qstatus = GetQueueStatus(qs_all_input); 11943 ok(qstatus == 0, 11944 "wrong qstatus %08x\n", qstatus); 11945 11946 /* some GetMessage tests */ 11947 11948 keybd_event('N', 0, 0, 0); 11949 qstatus = GetQueueStatus(qs_all_input); 11950 ok(qstatus == MAKELONG(QS_KEY, QS_KEY), "wrong qstatus %08x\n", qstatus); 11951 11952 PostMessageA(info.hwnd, WM_CHAR, 'z', 0); 11953 qstatus = GetQueueStatus(qs_all_input); 11954 ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY), "wrong qstatus %08x\n", qstatus); 11955 11956 if (qstatus) 11957 { 11958 ret = GetMessageA( &msg, 0, 0, 0 ); 11959 ok(ret && msg.message == WM_CHAR && msg.wParam == 'z', 11960 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n", 11961 ret, msg.message, msg.wParam); 11962 qstatus = GetQueueStatus(qs_all_input); 11963 ok(qstatus == MAKELONG(0, QS_KEY), "wrong qstatus %08x\n", qstatus); 11964 } 11965 11966 if (qstatus) 11967 { 11968 ret = GetMessageA( &msg, 0, 0, 0 ); 11969 ok(ret && msg.message == WM_KEYDOWN && msg.wParam == 'N', 11970 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n", 11971 ret, msg.message, msg.wParam); 11972 ok_sequence(WmKeyDownSkippedSeq, "WmKeyDownSkippedSeq", FALSE); 11973 qstatus = GetQueueStatus(qs_all_input); 11974 ok(qstatus == 0, "wrong qstatus %08x\n", qstatus); 11975 } 11976 11977 keybd_event('N', 0, 0, 0); 11978 qstatus = GetQueueStatus(qs_all_input); 11979 ok(qstatus == MAKELONG(QS_KEY, QS_KEY), "wrong qstatus %08x\n", qstatus); 11980 11981 PostMessageA(info.hwnd, WM_CHAR, 'z', 0); 11982 qstatus = GetQueueStatus(qs_all_input); 11983 ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY), "wrong qstatus %08x\n", qstatus); 11984 11985 if (qstatus & (QS_KEY << 16)) 11986 { 11987 ret = GetMessageA( &msg, 0, WM_KEYDOWN, WM_KEYUP ); 11988 ok(ret && msg.message == WM_KEYDOWN && msg.wParam == 'N', 11989 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n", 11990 ret, msg.message, msg.wParam); 11991 ok_sequence(WmKeyDownWasDownSkippedSeq, "WmKeyDownWasDownSkippedSeq", FALSE); 11992 qstatus = GetQueueStatus(qs_all_input); 11993 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE), "wrong qstatus %08x\n", qstatus); 11994 } 11995 11996 if (qstatus) 11997 { 11998 ret = GetMessageA( &msg, 0, WM_CHAR, WM_CHAR ); 11999 ok(ret && msg.message == WM_CHAR && msg.wParam == 'z', 12000 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n", 12001 ret, msg.message, msg.wParam); 12002 qstatus = GetQueueStatus(qs_all_input); 12003 ok(qstatus == 0, "wrong qstatus %08x\n", qstatus); 12004 } 12005 12006 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 12007 qstatus = GetQueueStatus(qs_all_input); 12008 ok(qstatus == MAKELONG(QS_KEY, QS_KEY), "wrong qstatus %08x\n", qstatus); 12009 12010 PostMessageA(info.hwnd, WM_CHAR, 'z', 0); 12011 qstatus = GetQueueStatus(qs_all_input); 12012 ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY), "wrong qstatus %08x\n", qstatus); 12013 12014 trace("signalling to send message\n"); 12015 SetEvent(info.hevent[EV_SENDMSG]); 12016 WaitForSingleObject(info.hevent[EV_ACK], INFINITE); 12017 qstatus = GetQueueStatus(qs_all_input); 12018 ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_POSTMESSAGE|QS_KEY), 12019 "wrong qstatus %08x\n", qstatus); 12020 12021 if (qstatus & (QS_KEY << 16)) 12022 { 12023 ret = GetMessageA( &msg, 0, WM_KEYDOWN, WM_KEYUP ); 12024 ok(ret && msg.message == WM_KEYUP && msg.wParam == 'N', 12025 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n", 12026 ret, msg.message, msg.wParam); 12027 ok_sequence(WmUserKeyUpSkippedSeq, "WmUserKeyUpSkippedSeq", FALSE); 12028 qstatus = GetQueueStatus(qs_all_input); 12029 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE), "wrong qstatus %08x\n", qstatus); 12030 } 12031 12032 if (qstatus) 12033 { 12034 ret = GetMessageA( &msg, 0, WM_CHAR, WM_CHAR ); 12035 ok(ret && msg.message == WM_CHAR && msg.wParam == 'z', 12036 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n", 12037 ret, msg.message, msg.wParam); 12038 qstatus = GetQueueStatus(qs_all_input); 12039 ok(qstatus == 0, "wrong qstatus %08x\n", qstatus); 12040 } 12041 done: 12042 trace("signalling to exit\n"); 12043 SetEvent(info.hevent[EV_STOP]); 12044 12045 WaitForSingleObject(hthread, INFINITE); 12046 12047 CloseHandle(hthread); 12048 CloseHandle(info.hevent[0]); 12049 CloseHandle(info.hevent[1]); 12050 CloseHandle(info.hevent[2]); 12051 12052 DestroyWindow(info.hwnd); 12053 } 12054 12055 static void wait_move_event(HWND hwnd, int x, int y) 12056 { 12057 MSG msg; 12058 DWORD time; 12059 BOOL ret; 12060 12061 time = GetTickCount(); 12062 while (GetTickCount() - time < 200) { 12063 ret = PeekMessageA(&msg, hwnd, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_NOREMOVE); 12064 if (ret && msg.pt.x > x && msg.pt.y > y) break; 12065 if (!ret) MsgWaitForMultipleObjects( 0, NULL, FALSE, GetTickCount() - time, QS_ALLINPUT ); 12066 else Sleep( GetTickCount() - time ); 12067 } 12068 } 12069 12070 #define STEP 5 12071 static void test_PeekMessage2(void) 12072 { 12073 HWND hwnd; 12074 BOOL ret; 12075 MSG msg; 12076 UINT message; 12077 DWORD time1, time2, time3; 12078 int x1, y1, x2, y2, x3, y3; 12079 POINT pos; 12080 12081 time1 = time2 = time3 = 0; 12082 x1 = y1 = x2 = y2 = x3 = y3 = 0; 12083 12084 /* Initialise window and make sure it is ready for events */ 12085 hwnd = CreateWindowA("TestWindowClass", "PeekMessage2", WS_OVERLAPPEDWINDOW, 12086 10, 10, 800, 800, NULL, NULL, NULL, NULL); 12087 assert(hwnd); 12088 trace("Window for test_PeekMessage2 %p\n", hwnd); 12089 ShowWindow(hwnd, SW_SHOW); 12090 UpdateWindow(hwnd); 12091 SetFocus(hwnd); 12092 GetCursorPos(&pos); 12093 SetCursorPos(100, 100); 12094 mouse_event(MOUSEEVENTF_MOVE, -STEP, -STEP, 0, 0); 12095 flush_events(); 12096 12097 /* Do initial mousemove, wait until we can see it 12098 and then do our test peek with PM_NOREMOVE. */ 12099 mouse_event(MOUSEEVENTF_MOVE, STEP, STEP, 0, 0); 12100 wait_move_event(hwnd, 100-STEP, 100-STEP); 12101 12102 ret = PeekMessageA(&msg, hwnd, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_NOREMOVE); 12103 if (!ret) 12104 { 12105 skip( "queuing mouse events not supported\n" ); 12106 goto done; 12107 } 12108 else 12109 { 12110 trace("1st move event: %04x %x %d %d\n", msg.message, msg.time, msg.pt.x, msg.pt.y); 12111 message = msg.message; 12112 time1 = msg.time; 12113 x1 = msg.pt.x; 12114 y1 = msg.pt.y; 12115 ok(message == WM_MOUSEMOVE, "message not WM_MOUSEMOVE, %04x instead\n", message); 12116 } 12117 12118 /* Allow time to advance a bit, and then simulate the user moving their 12119 * mouse around. After that we peek again with PM_NOREMOVE. 12120 * Although the previous mousemove message was never removed, the 12121 * mousemove we now peek should reflect the recent mouse movements 12122 * because the input queue will merge the move events. */ 12123 Sleep(100); 12124 mouse_event(MOUSEEVENTF_MOVE, STEP, STEP, 0, 0); 12125 wait_move_event(hwnd, x1, y1); 12126 12127 ret = PeekMessageA(&msg, hwnd, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_NOREMOVE); 12128 ok(ret, "no message available\n"); 12129 if (ret) { 12130 trace("2nd move event: %04x %x %d %d\n", msg.message, msg.time, msg.pt.x, msg.pt.y); 12131 message = msg.message; 12132 time2 = msg.time; 12133 x2 = msg.pt.x; 12134 y2 = msg.pt.y; 12135 ok(message == WM_MOUSEMOVE, "message not WM_MOUSEMOVE, %04x instead\n", message); 12136 ok(time2 > time1, "message time not advanced: %x %x\n", time1, time2); 12137 ok(x2 != x1 && y2 != y1, "coords not changed: (%d %d) (%d %d)\n", x1, y1, x2, y2); 12138 } 12139 12140 /* Have another go, to drive the point home */ 12141 Sleep(100); 12142 mouse_event(MOUSEEVENTF_MOVE, STEP, STEP, 0, 0); 12143 wait_move_event(hwnd, x2, y2); 12144 12145 ret = PeekMessageA(&msg, hwnd, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_NOREMOVE); 12146 ok(ret, "no message available\n"); 12147 if (ret) { 12148 trace("3rd move event: %04x %x %d %d\n", msg.message, msg.time, msg.pt.x, msg.pt.y); 12149 message = msg.message; 12150 time3 = msg.time; 12151 x3 = msg.pt.x; 12152 y3 = msg.pt.y; 12153 ok(message == WM_MOUSEMOVE, "message not WM_MOUSEMOVE, %04x instead\n", message); 12154 ok(time3 > time2, "message time not advanced: %x %x\n", time2, time3); 12155 ok(x3 != x2 && y3 != y2, "coords not changed: (%d %d) (%d %d)\n", x2, y2, x3, y3); 12156 } 12157 12158 done: 12159 DestroyWindow(hwnd); 12160 SetCursorPos(pos.x, pos.y); 12161 flush_events(); 12162 } 12163 12164 static void test_PeekMessage3(void) 12165 { 12166 HWND hwnd; 12167 BOOL ret; 12168 MSG msg; 12169 12170 hwnd = CreateWindowA("TestWindowClass", "PeekMessage3", WS_OVERLAPPEDWINDOW, 12171 10, 10, 800, 800, NULL, NULL, NULL, NULL); 12172 ok(hwnd != NULL, "expected hwnd != NULL\n"); 12173 flush_events(); 12174 12175 /* GetMessage() and PeekMessage(..., PM_REMOVE) should prefer messages which 12176 * were already seen. */ 12177 12178 SetTimer(hwnd, 1, 0, NULL); 12179 while (!PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE)); 12180 ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12181 PostMessageA(hwnd, WM_USER, 0, 0); 12182 ret = PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE); 12183 ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12184 ret = GetMessageA(&msg, NULL, 0, 0); 12185 ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12186 ret = GetMessageA(&msg, NULL, 0, 0); 12187 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); 12188 ret = PeekMessageA(&msg, NULL, 0, 0, 0); 12189 ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret); 12190 12191 SetTimer(hwnd, 1, 0, NULL); 12192 while (!PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE)); 12193 ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12194 PostMessageA(hwnd, WM_USER, 0, 0); 12195 ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE); 12196 ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12197 ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE); 12198 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); 12199 ret = PeekMessageA(&msg, NULL, 0, 0, 0); 12200 ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret); 12201 12202 /* It doesn't matter if a message range is specified or not. */ 12203 12204 SetTimer(hwnd, 1, 0, NULL); 12205 while (!PeekMessageA(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE)); 12206 ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12207 PostMessageA(hwnd, WM_USER, 0, 0); 12208 ret = GetMessageA(&msg, NULL, 0, 0); 12209 ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12210 ret = GetMessageA(&msg, NULL, 0, 0); 12211 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); 12212 ret = PeekMessageA(&msg, NULL, 0, 0, 0); 12213 ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret); 12214 12215 /* But not if the post messages were added before the PeekMessage() call. */ 12216 12217 PostMessageA(hwnd, WM_USER, 0, 0); 12218 SetTimer(hwnd, 1, 0, NULL); 12219 while (!PeekMessageA(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE)); 12220 ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12221 ret = GetMessageA(&msg, NULL, 0, 0); 12222 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); 12223 ret = GetMessageA(&msg, NULL, 0, 0); 12224 ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12225 ret = PeekMessageA(&msg, NULL, 0, 0, 0); 12226 ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret); 12227 12228 /* More complicated test with multiple messages. */ 12229 12230 PostMessageA(hwnd, WM_USER, 0, 0); 12231 SetTimer(hwnd, 1, 0, NULL); 12232 while (!PeekMessageA(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE)); 12233 ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12234 PostMessageA(hwnd, WM_USER + 1, 0, 0); 12235 ret = GetMessageA(&msg, NULL, 0, 0); 12236 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); 12237 ret = GetMessageA(&msg, NULL, 0, 0); 12238 ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12239 ret = GetMessageA(&msg, NULL, 0, 0); 12240 ok(ret && msg.message == WM_USER + 1, "msg.message = %u instead of WM_USER + 1\n", msg.message); 12241 ret = PeekMessageA(&msg, NULL, 0, 0, 0); 12242 ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret); 12243 12244 /* Newer messages are still returned when specifying a message range. */ 12245 12246 SetTimer(hwnd, 1, 0, NULL); 12247 while (!PeekMessageA(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE)); 12248 ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12249 PostMessageA(hwnd, WM_USER + 1, 0, 0); 12250 PostMessageA(hwnd, WM_USER, 0, 0); 12251 ret = PeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); 12252 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); 12253 ret = PeekMessageA(&msg, NULL, WM_USER, WM_USER + 1, PM_NOREMOVE); 12254 ok(ret && msg.message == WM_USER + 1, "msg.message = %u instead of WM_USER + 1\n", msg.message); 12255 ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE); 12256 ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12257 ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE); 12258 ok(ret && msg.message == WM_USER + 1, "msg.message = %u instead of WM_USER + 1\n", msg.message); 12259 ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE); 12260 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); 12261 ret = PeekMessageA(&msg, NULL, 0, 0, 0); 12262 ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret); 12263 12264 /* Also works for posted messages, but the situation is a bit different, 12265 * because both messages are in the same queue. */ 12266 12267 PostMessageA(hwnd, WM_TIMER, 0, 0); 12268 while (!PeekMessageA(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE)); 12269 ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12270 PostMessageA(hwnd, WM_USER, 0, 0); 12271 ret = GetMessageA(&msg, NULL, 0, 0); 12272 ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12273 ret = GetMessageA(&msg, NULL, 0, 0); 12274 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); 12275 ret = PeekMessageA(&msg, NULL, 0, 0, 0); 12276 ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret); 12277 12278 PostMessageA(hwnd, WM_USER, 0, 0); 12279 PostMessageA(hwnd, WM_TIMER, 0, 0); 12280 while (!PeekMessageA(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE)); 12281 ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12282 ret = GetMessageA(&msg, NULL, 0, 0); 12283 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); 12284 ret = GetMessageA(&msg, NULL, 0, 0); 12285 ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12286 ret = PeekMessageA(&msg, NULL, 0, 0, 0); 12287 ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret); 12288 12289 DestroyWindow(hwnd); 12290 flush_events(); 12291 } 12292 12293 static INT_PTR CALLBACK wm_quit_dlg_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) 12294 { 12295 struct recvd_message msg; 12296 12297 if (ignore_message( message )) return 0; 12298 12299 msg.hwnd = hwnd; 12300 msg.message = message; 12301 msg.flags = sent|wparam|lparam; 12302 msg.wParam = wp; 12303 msg.lParam = lp; 12304 msg.descr = "dialog"; 12305 add_message(&msg); 12306 12307 switch (message) 12308 { 12309 case WM_INITDIALOG: 12310 PostMessageA(hwnd, WM_QUIT, 0x1234, 0x5678); 12311 PostMessageA(hwnd, WM_USER, 0xdead, 0xbeef); 12312 return 0; 12313 12314 case WM_GETDLGCODE: 12315 return 0; 12316 12317 case WM_USER: 12318 EndDialog(hwnd, 0); 12319 break; 12320 } 12321 12322 return 1; 12323 } 12324 12325 static const struct message WmQuitDialogSeq[] = { 12326 { HCBT_CREATEWND, hook }, 12327 { WM_SETFONT, sent }, 12328 { WM_INITDIALOG, sent }, 12329 { WM_CHANGEUISTATE, sent|optional }, 12330 { HCBT_DESTROYWND, hook }, 12331 { 0x0090, sent|optional }, /* Vista */ 12332 { WM_DESTROY, sent }, 12333 { WM_NCDESTROY, sent }, 12334 { 0 } 12335 }; 12336 12337 static const struct message WmStopQuitSeq[] = { 12338 { WM_DWMNCRENDERINGCHANGED, posted|optional }, 12339 { WM_CLOSE, posted }, 12340 { WM_QUIT, posted|wparam|lparam, 0x1234, 0 }, 12341 { 0 } 12342 }; 12343 12344 static void test_quit_message(void) 12345 { 12346 MSG msg; 12347 BOOL ret; 12348 12349 /* test using PostQuitMessage */ 12350 flush_events(); 12351 PostQuitMessage(0xbeef); 12352 12353 msg.message = 0; 12354 ret = PeekMessageA(&msg, 0, 0, 0, PM_QS_SENDMESSAGE); 12355 ok(!ret, "got %x message\n", msg.message); 12356 12357 ret = PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE); 12358 ok(ret, "PeekMessage failed with error %d\n", GetLastError()); 12359 ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message); 12360 ok(msg.wParam == 0xbeef, "wParam was 0x%lx instead of 0xbeef\n", msg.wParam); 12361 12362 ret = PostThreadMessageA(GetCurrentThreadId(), WM_USER, 0, 0); 12363 ok(ret, "PostMessage failed with error %d\n", GetLastError()); 12364 12365 ret = GetMessageA(&msg, NULL, 0, 0); 12366 ok(ret > 0, "GetMessage failed with error %d\n", GetLastError()); 12367 ok(msg.message == WM_USER, "Received message 0x%04x instead of WM_USER\n", msg.message); 12368 12369 /* note: WM_QUIT message received after WM_USER message */ 12370 ret = GetMessageA(&msg, NULL, 0, 0); 12371 ok(!ret, "GetMessage return %d with error %d instead of FALSE\n", ret, GetLastError()); 12372 ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message); 12373 ok(msg.wParam == 0xbeef, "wParam was 0x%lx instead of 0xbeef\n", msg.wParam); 12374 12375 ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE); 12376 ok( !ret || msg.message != WM_QUIT, "Received WM_QUIT again\n" ); 12377 12378 /* now test with PostThreadMessage - different behaviour! */ 12379 PostThreadMessageA(GetCurrentThreadId(), WM_QUIT, 0xdead, 0); 12380 12381 ret = PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE); 12382 ok(ret, "PeekMessage failed with error %d\n", GetLastError()); 12383 ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message); 12384 ok(msg.wParam == 0xdead, "wParam was 0x%lx instead of 0xdead\n", msg.wParam); 12385 12386 ret = PostThreadMessageA(GetCurrentThreadId(), WM_USER, 0, 0); 12387 ok(ret, "PostMessage failed with error %d\n", GetLastError()); 12388 12389 /* note: we receive the WM_QUIT message first this time */ 12390 ret = GetMessageA(&msg, NULL, 0, 0); 12391 ok(!ret, "GetMessage return %d with error %d instead of FALSE\n", ret, GetLastError()); 12392 ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message); 12393 ok(msg.wParam == 0xdead, "wParam was 0x%lx instead of 0xdead\n", msg.wParam); 12394 12395 ret = GetMessageA(&msg, NULL, 0, 0); 12396 ok(ret > 0, "GetMessage failed with error %d\n", GetLastError()); 12397 ok(msg.message == WM_USER, "Received message 0x%04x instead of WM_USER\n", msg.message); 12398 12399 flush_events(); 12400 flush_sequence(); 12401 ret = DialogBoxParamA(GetModuleHandleA(NULL), "TEST_EMPTY_DIALOG", 0, wm_quit_dlg_proc, 0); 12402 ok(ret == 1, "expected 1, got %d\n", ret); 12403 ok_sequence(WmQuitDialogSeq, "WmQuitDialogSeq", FALSE); 12404 memset(&msg, 0xab, sizeof(msg)); 12405 ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE); 12406 ok(ret, "PeekMessage failed\n"); 12407 ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message); 12408 ok(msg.wParam == 0x1234, "wParam was 0x%lx instead of 0x1234\n", msg.wParam); 12409 ok(msg.lParam == 0, "lParam was 0x%lx instead of 0\n", msg.lParam); 12410 12411 /* Check what happens to a WM_QUIT message posted to a window that gets 12412 * destroyed. 12413 */ 12414 CreateWindowExA(0, "StopQuitClass", "Stop Quit Test", WS_OVERLAPPEDWINDOW, 12415 0, 0, 100, 100, NULL, NULL, NULL, NULL); 12416 flush_sequence(); 12417 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 12418 { 12419 struct recvd_message rmsg; 12420 rmsg.hwnd = msg.hwnd; 12421 rmsg.message = msg.message; 12422 rmsg.flags = posted|wparam|lparam; 12423 rmsg.wParam = msg.wParam; 12424 rmsg.lParam = msg.lParam; 12425 rmsg.descr = "stop/quit"; 12426 if (msg.message == WM_QUIT) 12427 /* The hwnd can only be checked here */ 12428 ok(!msg.hwnd, "The WM_QUIT hwnd was %p instead of NULL\n", msg.hwnd); 12429 add_message(&rmsg); 12430 DispatchMessageA(&msg); 12431 } 12432 ok_sequence(WmStopQuitSeq, "WmStopQuitSeq", FALSE); 12433 } 12434 12435 static const struct message WmNotifySeq[] = { 12436 { WM_NOTIFY, sent|wparam|lparam, 0x1234, 0xdeadbeef }, 12437 { 0 } 12438 }; 12439 12440 static void test_notify_message(void) 12441 { 12442 HWND hwnd; 12443 BOOL ret; 12444 MSG msg; 12445 12446 hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, 12447 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0, NULL, NULL, 0); 12448 ok(hwnd != 0, "Failed to create window\n"); 12449 flush_events(); 12450 flush_sequence(); 12451 12452 ret = SendNotifyMessageA(hwnd, WM_NOTIFY, 0x1234, 0xdeadbeef); 12453 ok(ret == TRUE, "SendNotifyMessageA failed with error %u\n", GetLastError()); 12454 ok_sequence(WmNotifySeq, "WmNotifySeq", FALSE); 12455 12456 ret = SendNotifyMessageW(hwnd, WM_NOTIFY, 0x1234, 0xdeadbeef); 12457 ok(ret == TRUE, "SendNotifyMessageW failed with error %u\n", GetLastError()); 12458 ok_sequence(WmNotifySeq, "WmNotifySeq", FALSE); 12459 12460 ret = SendMessageCallbackA(hwnd, WM_NOTIFY, 0x1234, 0xdeadbeef, NULL, 0); 12461 ok(ret == TRUE, "SendMessageCallbackA failed with error %u\n", GetLastError()); 12462 ok_sequence(WmNotifySeq, "WmNotifySeq", FALSE); 12463 12464 ret = SendMessageCallbackW(hwnd, WM_NOTIFY, 0x1234, 0xdeadbeef, NULL, 0); 12465 ok(ret == TRUE, "SendMessageCallbackW failed with error %u\n", GetLastError()); 12466 ok_sequence(WmNotifySeq, "WmNotifySeq", FALSE); 12467 12468 ret = PostMessageA(hwnd, WM_NOTIFY, 0x1234, 0xdeadbeef); 12469 ok(ret == TRUE, "PostMessageA failed with error %u\n", GetLastError()); 12470 flush_events(); 12471 ok_sequence(WmNotifySeq, "WmNotifySeq", FALSE); 12472 12473 ret = PostMessageW(hwnd, WM_NOTIFY, 0x1234, 0xdeadbeef); 12474 ok(ret == TRUE, "PostMessageW failed with error %u\n", GetLastError()); 12475 flush_events(); 12476 ok_sequence(WmNotifySeq, "WmNotifySeq", FALSE); 12477 12478 ret = PostThreadMessageA(GetCurrentThreadId(), WM_NOTIFY, 0x1234, 0xdeadbeef); 12479 ok(ret == TRUE, "PostThreadMessageA failed with error %u\n", GetLastError()); 12480 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 12481 { 12482 msg.hwnd = hwnd; 12483 DispatchMessageA(&msg); 12484 } 12485 ok_sequence(WmNotifySeq, "WmNotifySeq", FALSE); 12486 12487 ret = PostThreadMessageW(GetCurrentThreadId(), WM_NOTIFY, 0x1234, 0xdeadbeef); 12488 ok(ret == TRUE, "PostThreadMessageW failed with error %u\n", GetLastError()); 12489 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 12490 { 12491 msg.hwnd = hwnd; 12492 DispatchMessageA(&msg); 12493 } 12494 ok_sequence(WmNotifySeq, "WmNotifySeq", FALSE); 12495 12496 DestroyWindow(hwnd); 12497 } 12498 12499 static const struct message WmMouseHoverSeq[] = { 12500 { WM_MOUSEACTIVATE, sent|optional }, /* we can get those when moving the mouse in focus-follow-mouse mode under X11 */ 12501 { WM_MOUSEACTIVATE, sent|optional }, 12502 { WM_TIMER, sent|optional }, /* XP sends it */ 12503 { WM_SYSTIMER, sent }, 12504 { WM_MOUSEHOVER, sent|wparam, 0 }, 12505 { 0 } 12506 }; 12507 12508 static void pump_msg_loop_timeout(DWORD timeout, BOOL inject_mouse_move) 12509 { 12510 MSG msg; 12511 DWORD start_ticks, end_ticks; 12512 12513 start_ticks = GetTickCount(); 12514 /* add some deviation (50%) to cover not expected delays */ 12515 start_ticks += timeout / 2; 12516 12517 do 12518 { 12519 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 12520 { 12521 /* Timer proc messages are not dispatched to the window proc, 12522 * and therefore not logged. 12523 */ 12524 if ((msg.message == WM_TIMER || msg.message == WM_SYSTIMER) && msg.hwnd) 12525 { 12526 struct recvd_message s_msg; 12527 12528 s_msg.hwnd = msg.hwnd; 12529 s_msg.message = msg.message; 12530 s_msg.flags = sent|wparam|lparam; 12531 s_msg.wParam = msg.wParam; 12532 s_msg.lParam = msg.lParam; 12533 s_msg.descr = "msg_loop"; 12534 add_message(&s_msg); 12535 } 12536 DispatchMessageA(&msg); 12537 } 12538 12539 end_ticks = GetTickCount(); 12540 12541 /* inject WM_MOUSEMOVE to see how it changes tracking */ 12542 if (inject_mouse_move && start_ticks + timeout / 2 >= end_ticks) 12543 { 12544 mouse_event(MOUSEEVENTF_MOVE, -1, 0, 0, 0); 12545 mouse_event(MOUSEEVENTF_MOVE, 1, 0, 0, 0); 12546 12547 inject_mouse_move = FALSE; 12548 } 12549 } while (start_ticks + timeout >= end_ticks); 12550 } 12551 12552 static void test_TrackMouseEvent(void) 12553 { 12554 TRACKMOUSEEVENT tme; 12555 BOOL ret; 12556 HWND hwnd, hchild; 12557 RECT rc_parent, rc_child; 12558 UINT default_hover_time, hover_width = 0, hover_height = 0; 12559 12560 #define track_hover(track_hwnd, track_hover_time) \ 12561 tme.cbSize = sizeof(tme); \ 12562 tme.dwFlags = TME_HOVER; \ 12563 tme.hwndTrack = track_hwnd; \ 12564 tme.dwHoverTime = track_hover_time; \ 12565 SetLastError(0xdeadbeef); \ 12566 ret = pTrackMouseEvent(&tme); \ 12567 ok(ret, "TrackMouseEvent(TME_HOVER) error %d\n", GetLastError()) 12568 12569 #define track_query(expected_track_flags, expected_track_hwnd, expected_hover_time) \ 12570 tme.cbSize = sizeof(tme); \ 12571 tme.dwFlags = TME_QUERY; \ 12572 tme.hwndTrack = (HWND)0xdeadbeef; \ 12573 tme.dwHoverTime = 0xdeadbeef; \ 12574 SetLastError(0xdeadbeef); \ 12575 ret = pTrackMouseEvent(&tme); \ 12576 ok(ret, "TrackMouseEvent(TME_QUERY) error %d\n", GetLastError());\ 12577 ok(tme.cbSize == sizeof(tme), "wrong tme.cbSize %u\n", tme.cbSize); \ 12578 ok(tme.dwFlags == (expected_track_flags), \ 12579 "wrong tme.dwFlags %08x, expected %08x\n", tme.dwFlags, (expected_track_flags)); \ 12580 ok(tme.hwndTrack == (expected_track_hwnd), \ 12581 "wrong tme.hwndTrack %p, expected %p\n", tme.hwndTrack, (expected_track_hwnd)); \ 12582 ok(tme.dwHoverTime == (expected_hover_time), \ 12583 "wrong tme.dwHoverTime %u, expected %u\n", tme.dwHoverTime, (expected_hover_time)) 12584 12585 #define track_hover_cancel(track_hwnd) \ 12586 tme.cbSize = sizeof(tme); \ 12587 tme.dwFlags = TME_HOVER | TME_CANCEL; \ 12588 tme.hwndTrack = track_hwnd; \ 12589 tme.dwHoverTime = 0xdeadbeef; \ 12590 SetLastError(0xdeadbeef); \ 12591 ret = pTrackMouseEvent(&tme); \ 12592 ok(ret, "TrackMouseEvent(TME_HOVER | TME_CANCEL) error %d\n", GetLastError()) 12593 12594 default_hover_time = 0xdeadbeef; 12595 SetLastError(0xdeadbeef); 12596 ret = SystemParametersInfoA(SPI_GETMOUSEHOVERTIME, 0, &default_hover_time, 0); 12597 ok(ret || broken(GetLastError() == 0xdeadbeef), /* win9x */ 12598 "SystemParametersInfo(SPI_GETMOUSEHOVERTIME) error %u\n", GetLastError()); 12599 if (!ret) default_hover_time = 400; 12600 trace("SPI_GETMOUSEHOVERTIME returned %u ms\n", default_hover_time); 12601 12602 SetLastError(0xdeadbeef); 12603 ret = SystemParametersInfoA(SPI_GETMOUSEHOVERWIDTH, 0, &hover_width, 0); 12604 ok(ret || broken(GetLastError() == 0xdeadbeef), /* win9x */ 12605 "SystemParametersInfo(SPI_GETMOUSEHOVERWIDTH) error %u\n", GetLastError()); 12606 if (!ret) hover_width = 4; 12607 SetLastError(0xdeadbeef); 12608 ret = SystemParametersInfoA(SPI_GETMOUSEHOVERHEIGHT, 0, &hover_height, 0); 12609 ok(ret || broken(GetLastError() == 0xdeadbeef), /* win9x */ 12610 "SystemParametersInfo(SPI_GETMOUSEHOVERHEIGHT) error %u\n", GetLastError()); 12611 if (!ret) hover_height = 4; 12612 trace("hover rect is %u x %d\n", hover_width, hover_height); 12613 12614 hwnd = CreateWindowExA(0, "TestWindowClass", NULL, 12615 WS_OVERLAPPEDWINDOW | WS_VISIBLE, 12616 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0, 12617 NULL, NULL, 0); 12618 assert(hwnd); 12619 12620 hchild = CreateWindowExA(0, "TestWindowClass", NULL, 12621 WS_CHILD | WS_BORDER | WS_VISIBLE, 12622 50, 50, 200, 200, hwnd, 12623 NULL, NULL, 0); 12624 assert(hchild); 12625 12626 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE ); 12627 flush_events(); 12628 flush_sequence(); 12629 12630 tme.cbSize = 0; 12631 tme.dwFlags = TME_QUERY; 12632 tme.hwndTrack = (HWND)0xdeadbeef; 12633 tme.dwHoverTime = 0xdeadbeef; 12634 SetLastError(0xdeadbeef); 12635 ret = pTrackMouseEvent(&tme); 12636 ok(!ret, "TrackMouseEvent should fail\n"); 12637 ok(GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == 0xdeadbeef), 12638 "not expected error %u\n", GetLastError()); 12639 12640 tme.cbSize = sizeof(tme); 12641 tme.dwFlags = TME_HOVER; 12642 tme.hwndTrack = (HWND)0xdeadbeef; 12643 tme.dwHoverTime = 0xdeadbeef; 12644 SetLastError(0xdeadbeef); 12645 ret = pTrackMouseEvent(&tme); 12646 ok(!ret, "TrackMouseEvent should fail\n"); 12647 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || broken(GetLastError() == 0xdeadbeef), 12648 "not expected error %u\n", GetLastError()); 12649 12650 tme.cbSize = sizeof(tme); 12651 tme.dwFlags = TME_HOVER | TME_CANCEL; 12652 tme.hwndTrack = (HWND)0xdeadbeef; 12653 tme.dwHoverTime = 0xdeadbeef; 12654 SetLastError(0xdeadbeef); 12655 ret = pTrackMouseEvent(&tme); 12656 ok(!ret, "TrackMouseEvent should fail\n"); 12657 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || broken(GetLastError() == 0xdeadbeef), 12658 "not expected error %u\n", GetLastError()); 12659 12660 GetWindowRect(hwnd, &rc_parent); 12661 GetWindowRect(hchild, &rc_child); 12662 SetCursorPos(rc_child.left - 10, rc_child.top - 10); 12663 12664 /* Process messages so that the system updates its internal current 12665 * window and hittest, otherwise TrackMouseEvent calls don't have any 12666 * effect. 12667 */ 12668 flush_events(); 12669 flush_sequence(); 12670 12671 track_query(0, NULL, 0); 12672 track_hover(hchild, 0); 12673 track_query(0, NULL, 0); 12674 12675 flush_events(); 12676 flush_sequence(); 12677 12678 track_hover(hwnd, 0); 12679 tme.cbSize = sizeof(tme); 12680 tme.dwFlags = TME_QUERY; 12681 tme.hwndTrack = (HWND)0xdeadbeef; 12682 tme.dwHoverTime = 0xdeadbeef; 12683 SetLastError(0xdeadbeef); 12684 ret = pTrackMouseEvent(&tme); 12685 ok(ret, "TrackMouseEvent(TME_QUERY) error %d\n", GetLastError()); 12686 ok(tme.cbSize == sizeof(tme), "wrong tme.cbSize %u\n", tme.cbSize); 12687 if (!tme.dwFlags) 12688 { 12689 skip( "Cursor not inside window, skipping TrackMouseEvent tests\n" ); 12690 DestroyWindow( hwnd ); 12691 return; 12692 } 12693 ok(tme.dwFlags == TME_HOVER, "wrong tme.dwFlags %08x, expected TME_HOVER\n", tme.dwFlags); 12694 ok(tme.hwndTrack == hwnd, "wrong tme.hwndTrack %p, expected %p\n", tme.hwndTrack, hwnd); 12695 ok(tme.dwHoverTime == default_hover_time, "wrong tme.dwHoverTime %u, expected %u\n", 12696 tme.dwHoverTime, default_hover_time); 12697 12698 pump_msg_loop_timeout(default_hover_time, FALSE); 12699 ok_sequence(WmMouseHoverSeq, "WmMouseHoverSeq", FALSE); 12700 12701 track_query(0, NULL, 0); 12702 12703 track_hover(hwnd, HOVER_DEFAULT); 12704 track_query(TME_HOVER, hwnd, default_hover_time); 12705 12706 Sleep(default_hover_time / 2); 12707 mouse_event(MOUSEEVENTF_MOVE, -1, 0, 0, 0); 12708 mouse_event(MOUSEEVENTF_MOVE, 1, 0, 0, 0); 12709 12710 track_query(TME_HOVER, hwnd, default_hover_time); 12711 12712 pump_msg_loop_timeout(default_hover_time, FALSE); 12713 ok_sequence(WmMouseHoverSeq, "WmMouseHoverSeq", FALSE); 12714 12715 track_query(0, NULL, 0); 12716 12717 track_hover(hwnd, HOVER_DEFAULT); 12718 track_query(TME_HOVER, hwnd, default_hover_time); 12719 12720 pump_msg_loop_timeout(default_hover_time, TRUE); 12721 ok_sequence(WmMouseHoverSeq, "WmMouseHoverSeq", FALSE); 12722 12723 track_query(0, NULL, 0); 12724 12725 track_hover(hwnd, HOVER_DEFAULT); 12726 track_query(TME_HOVER, hwnd, default_hover_time); 12727 track_hover_cancel(hwnd); 12728 12729 DestroyWindow(hwnd); 12730 12731 #undef track_hover 12732 #undef track_query 12733 #undef track_hover_cancel 12734 } 12735 12736 12737 static const struct message WmSetWindowRgn[] = { 12738 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE }, 12739 { WM_NCCALCSIZE, sent|wparam, 1 }, 12740 { WM_NCPAINT, sent|optional }, /* wparam != 1 */ 12741 { WM_GETTEXT, sent|defwinproc|optional }, 12742 { WM_ERASEBKGND, sent|optional }, 12743 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE }, 12744 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 12745 { 0 } 12746 }; 12747 12748 static const struct message WmSetWindowRgn_no_redraw[] = { 12749 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW }, 12750 { WM_NCCALCSIZE, sent|wparam, 1 }, 12751 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW }, 12752 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 12753 { 0 } 12754 }; 12755 12756 static const struct message WmSetWindowRgn_clear[] = { 12757 { WM_WINDOWPOSCHANGING, sent/*|wparam*/, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE/*|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE only on some Windows versions */ }, 12758 { WM_NCCALCSIZE, sent|wparam, 1 }, 12759 { WM_NCPAINT, sent|optional }, 12760 { WM_GETTEXT, sent|defwinproc|optional }, 12761 { WM_ERASEBKGND, sent|optional }, /* FIXME: remove optional once Wine is fixed */ 12762 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE }, 12763 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, 12764 { WM_NCPAINT, sent|optional }, 12765 { WM_GETTEXT, sent|defwinproc|optional }, 12766 { WM_ERASEBKGND, sent|optional }, 12767 { WM_WINDOWPOSCHANGING, sent|optional }, 12768 { WM_NCCALCSIZE, sent|optional|wparam, 1 }, 12769 { WM_NCPAINT, sent|optional }, 12770 { WM_GETTEXT, sent|defwinproc|optional }, 12771 { WM_ERASEBKGND, sent|optional }, 12772 { WM_WINDOWPOSCHANGED, sent|optional|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE }, 12773 { WM_NCCALCSIZE, sent|optional|wparam, 1 }, 12774 { WM_NCPAINT, sent|optional }, 12775 { WM_GETTEXT, sent|defwinproc|optional }, 12776 { WM_ERASEBKGND, sent|optional }, 12777 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 12778 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 12779 { 0 } 12780 }; 12781 12782 static void test_SetWindowRgn(void) 12783 { 12784 HRGN hrgn; 12785 HWND hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW, 12786 100, 100, 200, 200, 0, 0, 0, NULL); 12787 ok( hwnd != 0, "Failed to create overlapped window\n" ); 12788 12789 ShowWindow( hwnd, SW_SHOW ); 12790 UpdateWindow( hwnd ); 12791 flush_events(); 12792 flush_sequence(); 12793 12794 trace("testing SetWindowRgn\n"); 12795 hrgn = CreateRectRgn( 0, 0, 150, 150 ); 12796 SetWindowRgn( hwnd, hrgn, TRUE ); 12797 ok_sequence( WmSetWindowRgn, "WmSetWindowRgn", FALSE ); 12798 12799 hrgn = CreateRectRgn( 30, 30, 160, 160 ); 12800 SetWindowRgn( hwnd, hrgn, FALSE ); 12801 ok_sequence( WmSetWindowRgn_no_redraw, "WmSetWindowRgn_no_redraw", FALSE ); 12802 12803 hrgn = CreateRectRgn( 0, 0, 180, 180 ); 12804 SetWindowRgn( hwnd, hrgn, TRUE ); 12805 ok_sequence( WmSetWindowRgn, "WmSetWindowRgn2", FALSE ); 12806 12807 SetWindowRgn( hwnd, 0, TRUE ); 12808 ok_sequence( WmSetWindowRgn_clear, "WmSetWindowRgn_clear", FALSE ); 12809 12810 DestroyWindow( hwnd ); 12811 } 12812 12813 /*************************** ShowWindow() test ******************************/ 12814 static const struct message WmShowNormal[] = { 12815 { WM_SHOWWINDOW, sent|wparam, 1 }, 12816 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 12817 { HCBT_ACTIVATE, hook }, 12818 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2003 doesn't send it */ 12819 { HCBT_SETFOCUS, hook }, 12820 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 12821 { 0 } 12822 }; 12823 static const struct message WmShow[] = { 12824 { WM_SHOWWINDOW, sent|wparam, 1 }, 12825 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 12826 { HCBT_ACTIVATE, hook|optional }, /* win2000 doesn't send it */ 12827 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2000 doesn't send it */ 12828 { HCBT_SETFOCUS, hook|optional }, /* win2000 doesn't send it */ 12829 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 12830 { 0 } 12831 }; 12832 static const struct message WmShowNoActivate_1[] = { 12833 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWNOACTIVATE }, 12834 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOMOVE }, 12835 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOMOVE }, 12836 { WM_MOVE, sent|defwinproc|optional }, 12837 { WM_SIZE, sent|wparam|defwinproc, SIZE_RESTORED }, 12838 { 0 } 12839 }; 12840 static const struct message WmShowNoActivate_2[] = { 12841 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWNOACTIVATE }, 12842 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE }, 12843 { HCBT_ACTIVATE, hook|optional }, 12844 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 12845 { HCBT_SETFOCUS, hook|optional }, 12846 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE }, 12847 { WM_MOVE, sent|defwinproc }, 12848 { WM_SIZE, sent|wparam|defwinproc, SIZE_RESTORED }, 12849 { HCBT_SETFOCUS, hook|optional }, 12850 { HCBT_ACTIVATE, hook|optional }, /* win2003 doesn't send it */ 12851 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2003 doesn't send it */ 12852 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 12853 { HCBT_SETFOCUS, hook|optional }, /* win2003 doesn't send it */ 12854 { 0 } 12855 }; 12856 static const struct message WmShowNA_1[] = { 12857 { WM_SHOWWINDOW, sent|wparam, 1 }, 12858 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 12859 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 12860 { 0 } 12861 }; 12862 static const struct message WmShowNA_2[] = { 12863 { WM_SHOWWINDOW, sent|wparam, 1 }, 12864 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 12865 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 12866 { 0 } 12867 }; 12868 static const struct message WmRestore_1[] = { 12869 { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE }, 12870 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 12871 { HCBT_ACTIVATE, hook|optional }, /* win2000 doesn't send it */ 12872 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2000 doesn't send it */ 12873 { HCBT_SETFOCUS, hook|optional }, /* win2000 doesn't send it */ 12874 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 12875 { WM_MOVE, sent|defwinproc }, 12876 { WM_SIZE, sent|wparam|defwinproc, SIZE_RESTORED }, 12877 { HCBT_SETFOCUS, hook|optional }, /* win2000 sends it */ 12878 { 0 } 12879 }; 12880 static const struct message WmRestore_2[] = { 12881 { WM_SHOWWINDOW, sent|wparam, 1 }, 12882 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 12883 { HCBT_ACTIVATE, hook|optional }, /* win2000 doesn't send it */ 12884 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2000 doesn't send it */ 12885 { HCBT_SETFOCUS, hook|optional }, /* win2000 doesn't send it */ 12886 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 12887 { 0 } 12888 }; 12889 static const struct message WmRestore_3[] = { 12890 { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE }, 12891 { WM_GETMINMAXINFO, sent }, 12892 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 12893 { HCBT_ACTIVATE, hook|optional }, /* win2003 doesn't send it */ 12894 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2003 doesn't send it */ 12895 { HCBT_SETFOCUS, hook|optional }, /* win2003 doesn't send it */ 12896 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 12897 { WM_MOVE, sent|defwinproc }, 12898 { WM_SIZE, sent|wparam|defwinproc, SIZE_MAXIMIZED }, 12899 { HCBT_SETFOCUS, hook|optional }, /* win2003 sends it */ 12900 { 0 } 12901 }; 12902 static const struct message WmRestore_4[] = { 12903 { HCBT_MINMAX, hook|lparam|optional, 0, SW_RESTORE }, 12904 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOMOVE }, 12905 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOMOVE }, 12906 { WM_MOVE, sent|defwinproc|optional }, 12907 { WM_SIZE, sent|wparam|defwinproc|optional, SIZE_RESTORED }, 12908 { 0 } 12909 }; 12910 static const struct message WmRestore_5[] = { 12911 { HCBT_MINMAX, hook|lparam|optional, 0, SW_SHOWNORMAL }, 12912 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOMOVE }, 12913 { HCBT_ACTIVATE, hook|optional }, 12914 { HCBT_SETFOCUS, hook|optional }, 12915 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOMOVE }, 12916 { WM_MOVE, sent|defwinproc|optional }, 12917 { WM_SIZE, sent|wparam|defwinproc|optional, SIZE_RESTORED }, 12918 { 0 } 12919 }; 12920 static const struct message WmHide_1[] = { 12921 { WM_SHOWWINDOW, sent|wparam, 0 }, 12922 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE, 0, SWP_NOACTIVATE }, 12923 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE, 0, SWP_NOACTIVATE }, 12924 { HCBT_ACTIVATE, hook|optional }, 12925 { HCBT_SETFOCUS, hook|optional }, /* win2000 sends it */ 12926 { 0 } 12927 }; 12928 static const struct message WmHide_2[] = { 12929 { WM_SHOWWINDOW, sent|wparam, 0 }, 12930 { WM_WINDOWPOSCHANGING, sent /*|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE*/ }, /* win2000 doesn't add SWP_NOACTIVATE */ 12931 { WM_WINDOWPOSCHANGED, sent /*|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ }, /* win2000 doesn't add SWP_NOACTIVATE */ 12932 { HCBT_ACTIVATE, hook|optional }, 12933 { 0 } 12934 }; 12935 static const struct message WmHide_3[] = { 12936 { WM_SHOWWINDOW, sent|wparam, 0 }, 12937 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 12938 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 12939 { HCBT_SETFOCUS, hook|optional }, 12940 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 12941 { 0 } 12942 }; 12943 static const struct message WmShowMinimized_1[] = { 12944 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINIMIZED }, 12945 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 12946 { HCBT_ACTIVATE, hook|optional }, /* win2000 doesn't send it */ 12947 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2000 doesn't send it */ 12948 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 12949 { WM_MOVE, sent|defwinproc }, 12950 { WM_SIZE, sent|wparam|lparam|defwinproc, SIZE_MINIMIZED, 0 }, 12951 { 0 } 12952 }; 12953 static const struct message WmMinimize_1[] = { 12954 { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, 12955 { HCBT_SETFOCUS, hook|optional }, /* win2000 doesn't send it */ 12956 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 12957 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 12958 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 12959 { WM_MOVE, sent|defwinproc }, 12960 { WM_SIZE, sent|wparam|lparam|defwinproc, SIZE_MINIMIZED, 0 }, 12961 { 0 } 12962 }; 12963 static const struct message WmMinimize_2[] = { 12964 { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, 12965 { HCBT_SETFOCUS, hook|optional }, 12966 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE }, 12967 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE }, 12968 { WM_MOVE, sent|defwinproc }, 12969 { WM_SIZE, sent|wparam|lparam|defwinproc, SIZE_MINIMIZED, 0 }, 12970 { 0 } 12971 }; 12972 static const struct message WmMinimize_3[] = { 12973 { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, 12974 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE }, 12975 { HCBT_ACTIVATE, hook|optional }, 12976 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 12977 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE }, 12978 { WM_MOVE, sent|defwinproc }, 12979 { WM_SIZE, sent|wparam|lparam|defwinproc, SIZE_MINIMIZED, 0 }, 12980 { 0 } 12981 }; 12982 static const struct message WmShowMinNoActivate[] = { 12983 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINNOACTIVE }, 12984 { WM_WINDOWPOSCHANGING, sent }, 12985 { WM_WINDOWPOSCHANGED, sent }, 12986 { WM_MOVE, sent|defwinproc|optional }, 12987 { WM_SIZE, sent|wparam|lparam|defwinproc|optional, SIZE_MINIMIZED, 0 }, 12988 { 0 } 12989 }; 12990 static const struct message WmMinMax_1[] = { 12991 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINIMIZED }, 12992 { 0 } 12993 }; 12994 static const struct message WmMinMax_2[] = { 12995 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMAXIMIZED }, 12996 { WM_GETMINMAXINFO, sent|optional }, 12997 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_FRAMECHANGED|SWP_STATECHANGED }, 12998 { HCBT_ACTIVATE, hook|optional }, 12999 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 13000 { HCBT_SETFOCUS, hook|optional }, 13001 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 13002 { WM_MOVE, sent|defwinproc|optional }, 13003 { WM_SIZE, sent|wparam|defwinproc|optional, SIZE_MAXIMIZED }, 13004 { HCBT_SETFOCUS, hook|optional }, 13005 { 0 } 13006 }; 13007 static const struct message WmMinMax_3[] = { 13008 { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, 13009 { HCBT_SETFOCUS, hook|optional }, 13010 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 13011 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 13012 { WM_MOVE, sent|defwinproc|optional }, 13013 { WM_SIZE, sent|wparam|lparam|defwinproc|optional, SIZE_MINIMIZED, 0 }, 13014 { 0 } 13015 }; 13016 static const struct message WmMinMax_4[] = { 13017 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINNOACTIVE }, 13018 { 0 } 13019 }; 13020 static const struct message WmShowMaximized_1[] = { 13021 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMAXIMIZED }, 13022 { WM_GETMINMAXINFO, sent }, 13023 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 13024 { HCBT_ACTIVATE, hook|optional }, /* win2000 doesn't send it */ 13025 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2000 doesn't send it */ 13026 { HCBT_SETFOCUS, hook|optional }, /* win2000 doesn't send it */ 13027 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 13028 { WM_MOVE, sent|defwinproc }, 13029 { WM_SIZE, sent|wparam|defwinproc, SIZE_MAXIMIZED }, 13030 { HCBT_SETFOCUS, hook|optional }, /* win2003 sends it */ 13031 { 0 } 13032 }; 13033 static const struct message WmShowMaximized_2[] = { 13034 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMAXIMIZED }, 13035 { WM_GETMINMAXINFO, sent }, 13036 { WM_WINDOWPOSCHANGING, sent|optional }, 13037 { HCBT_ACTIVATE, hook|optional }, 13038 { WM_WINDOWPOSCHANGED, sent|optional }, 13039 { WM_MOVE, sent|optional }, /* Win9x doesn't send it */ 13040 { WM_SIZE, sent|wparam|optional, SIZE_MAXIMIZED }, /* Win9x doesn't send it */ 13041 { WM_WINDOWPOSCHANGING, sent|optional }, 13042 { HCBT_SETFOCUS, hook|optional }, 13043 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 13044 { WM_MOVE, sent|defwinproc }, 13045 { WM_SIZE, sent|wparam|defwinproc, SIZE_MAXIMIZED }, 13046 { HCBT_SETFOCUS, hook|optional }, 13047 { 0 } 13048 }; 13049 static const struct message WmShowMaximized_3[] = { 13050 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMAXIMIZED }, 13051 { WM_GETMINMAXINFO, sent|optional }, 13052 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOMOVE }, 13053 { HCBT_ACTIVATE, hook|optional }, /* win2000 doesn't send it */ 13054 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2000 doesn't send it */ 13055 { HCBT_SETFOCUS, hook|optional }, /* win2000 doesn't send it */ 13056 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOMOVE }, 13057 { WM_MOVE, sent|defwinproc|optional }, 13058 { WM_SIZE, sent|wparam|defwinproc, SIZE_MAXIMIZED }, 13059 { 0 } 13060 }; 13061 13062 static void test_ShowWindow(void) 13063 { 13064 /* ShowWindow commands in random order */ 13065 static const struct 13066 { 13067 INT cmd; /* ShowWindow command */ 13068 LPARAM ret; /* ShowWindow return value */ 13069 DWORD style; /* window style after the command */ 13070 const struct message *msg; /* message sequence the command produces */ 13071 INT wp_cmd, wp_flags; /* window placement after the command */ 13072 POINT wp_min, wp_max; /* window placement after the command */ 13073 BOOL todo_msg; /* message sequence doesn't match what Wine does */ 13074 } sw[] = 13075 { 13076 /* 1 */ { SW_SHOWNORMAL, FALSE, WS_VISIBLE, WmShowNormal, 13077 SW_SHOWNORMAL, 0, {-1,-1}, {-1,-1}, FALSE }, 13078 /* 2 */ { SW_SHOWNORMAL, TRUE, WS_VISIBLE, WmEmptySeq, 13079 SW_SHOWNORMAL, 0, {-1,-1}, {-1,-1}, FALSE }, 13080 /* 3 */ { SW_HIDE, TRUE, 0, WmHide_1, 13081 SW_SHOWNORMAL, 0, {-1,-1}, {-1,-1}, FALSE }, 13082 /* 4 */ { SW_HIDE, FALSE, 0, WmEmptySeq, 13083 SW_SHOWNORMAL, 0, {-1,-1}, {-1,-1}, FALSE }, 13084 /* 5 */ { SW_SHOWMINIMIZED, FALSE, WS_VISIBLE|WS_MINIMIZE, WmShowMinimized_1, 13085 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13086 /* 6 */ { SW_SHOWMINIMIZED, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_1, 13087 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13088 /* 7 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_1, 13089 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13090 /* 8 */ { SW_HIDE, FALSE, WS_MINIMIZE, WmEmptySeq, 13091 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13092 /* 9 */ { SW_SHOWMAXIMIZED, FALSE, WS_VISIBLE|WS_MAXIMIZE, WmShowMaximized_1, 13093 SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13094 /* 10 */ { SW_SHOWMAXIMIZED, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmMinMax_2, 13095 SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13096 /* 11 */ { SW_HIDE, TRUE, WS_MAXIMIZE, WmHide_1, 13097 SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13098 /* 12 */ { SW_HIDE, FALSE, WS_MAXIMIZE, WmEmptySeq, 13099 SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13100 /* 13 */ { SW_SHOWNOACTIVATE, FALSE, WS_VISIBLE, WmShowNoActivate_1, 13101 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13102 /* 14 */ { SW_SHOWNOACTIVATE, TRUE, WS_VISIBLE, WmEmptySeq, 13103 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13104 /* 15 */ { SW_HIDE, TRUE, 0, WmHide_2, 13105 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13106 /* 16 */ { SW_HIDE, FALSE, 0, WmEmptySeq, 13107 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13108 /* 17 */ { SW_SHOW, FALSE, WS_VISIBLE, WmShow, 13109 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13110 /* 18 */ { SW_SHOW, TRUE, WS_VISIBLE, WmEmptySeq, 13111 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13112 /* 19 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinimize_1, 13113 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13114 /* 20 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_3, 13115 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13116 /* 21 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_2, 13117 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13118 /* 22 */ { SW_SHOWMINNOACTIVE, FALSE, WS_VISIBLE|WS_MINIMIZE, WmShowMinNoActivate, 13119 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, TRUE }, 13120 /* 23 */ { SW_SHOWMINNOACTIVE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_4, 13121 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13122 /* 24 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_2, 13123 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13124 /* 25 */ { SW_HIDE, FALSE, WS_MINIMIZE, WmEmptySeq, 13125 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13126 /* 26 */ { SW_SHOWNA, FALSE, WS_VISIBLE|WS_MINIMIZE, WmShowNA_1, 13127 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13128 /* 27 */ { SW_SHOWNA, TRUE, WS_VISIBLE|WS_MINIMIZE, WmShowNA_2, 13129 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13130 /* 28 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_2, 13131 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13132 /* 29 */ { SW_HIDE, FALSE, WS_MINIMIZE, WmEmptySeq, 13133 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13134 /* 30 */ { SW_RESTORE, FALSE, WS_VISIBLE, WmRestore_1, 13135 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13136 /* 31 */ { SW_RESTORE, TRUE, WS_VISIBLE, WmEmptySeq, 13137 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13138 /* 32 */ { SW_HIDE, TRUE, 0, WmHide_3, 13139 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13140 /* 33 */ { SW_HIDE, FALSE, 0, WmEmptySeq, 13141 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13142 /* 34 */ { SW_NORMALNA, FALSE, 0, WmEmptySeq, /* what does this mean?! */ 13143 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13144 /* 35 */ { SW_NORMALNA, FALSE, 0, WmEmptySeq, 13145 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13146 /* 36 */ { SW_HIDE, FALSE, 0, WmEmptySeq, 13147 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13148 /* 37 */ { SW_RESTORE, FALSE, WS_VISIBLE, WmRestore_2, 13149 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13150 /* 38 */ { SW_RESTORE, TRUE, WS_VISIBLE, WmEmptySeq, 13151 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13152 /* 39 */ { SW_SHOWNOACTIVATE, TRUE, WS_VISIBLE, WmEmptySeq, 13153 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13154 /* 40 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinimize_2, 13155 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13156 /* 41 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_3, 13157 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13158 /* 42 */ { SW_SHOWMAXIMIZED, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmShowMaximized_2, 13159 SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13160 /* 43 */ { SW_SHOWMAXIMIZED, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmMinMax_2, 13161 SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13162 /* 44 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinimize_1, 13163 SW_SHOWMINIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13164 /* 45 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_3, 13165 SW_SHOWMINIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13166 /* 46 */ { SW_RESTORE, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmRestore_3, 13167 SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13168 /* 47 */ { SW_RESTORE, TRUE, WS_VISIBLE, WmRestore_4, 13169 SW_SHOWNORMAL, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13170 /* 48 */ { SW_SHOWMAXIMIZED, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmShowMaximized_3, 13171 SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13172 /* 49 */ { SW_SHOW, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmEmptySeq, 13173 SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13174 /* 50 */ { SW_SHOWNORMAL, TRUE, WS_VISIBLE, WmRestore_5, 13175 SW_SHOWNORMAL, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13176 /* 51 */ { SW_SHOWNORMAL, TRUE, WS_VISIBLE, WmRestore_5, 13177 SW_SHOWNORMAL, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13178 /* 52 */ { SW_HIDE, TRUE, 0, WmHide_1, 13179 SW_SHOWNORMAL, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13180 /* 53 */ { SW_HIDE, FALSE, 0, WmEmptySeq, 13181 SW_SHOWNORMAL, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13182 /* 54 */ { SW_MINIMIZE, FALSE, WS_VISIBLE|WS_MINIMIZE, WmMinimize_3, 13183 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13184 /* 55 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_2, 13185 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13186 /* 56 */ { SW_SHOWNOACTIVATE, FALSE, WS_VISIBLE, WmShowNoActivate_2, 13187 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13188 /* 57 */ { SW_SHOW, TRUE, WS_VISIBLE, WmEmptySeq, 13189 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE } 13190 }; 13191 HWND hwnd; 13192 DWORD style; 13193 LPARAM ret; 13194 INT i; 13195 WINDOWPLACEMENT wp; 13196 RECT win_rc, work_rc = {0, 0, 0, 0}; 13197 13198 #define WS_BASE (WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_POPUP|WS_CLIPSIBLINGS) 13199 hwnd = CreateWindowExA(0, "ShowWindowClass", NULL, WS_BASE, 13200 120, 120, 90, 90, 13201 0, 0, 0, NULL); 13202 assert(hwnd); 13203 13204 style = GetWindowLongA(hwnd, GWL_STYLE) & ~WS_BASE; 13205 ok(style == 0, "expected style 0, got %08x\n", style); 13206 13207 flush_events(); 13208 flush_sequence(); 13209 13210 if (pGetMonitorInfoA && pMonitorFromPoint) 13211 { 13212 HMONITOR hmon; 13213 MONITORINFO mi; 13214 POINT pt = {0, 0}; 13215 13216 SetLastError(0xdeadbeef); 13217 hmon = pMonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY); 13218 ok(hmon != 0, "MonitorFromPoint error %u\n", GetLastError()); 13219 13220 mi.cbSize = sizeof(mi); 13221 SetLastError(0xdeadbeef); 13222 ret = pGetMonitorInfoA(hmon, &mi); 13223 ok(ret, "GetMonitorInfo error %u\n", GetLastError()); 13224 trace("monitor %s, work %s\n", wine_dbgstr_rect(&mi.rcMonitor), 13225 wine_dbgstr_rect(&mi.rcWork)); 13226 work_rc = mi.rcWork; 13227 } 13228 13229 GetWindowRect(hwnd, &win_rc); 13230 OffsetRect(&win_rc, -work_rc.left, -work_rc.top); 13231 13232 wp.length = sizeof(wp); 13233 SetLastError(0xdeadbeaf); 13234 ret = GetWindowPlacement(hwnd, &wp); 13235 ok(ret, "GetWindowPlacement error %u\n", GetLastError()); 13236 ok(wp.flags == 0, "expected 0, got %#x\n", wp.flags); 13237 ok(wp.showCmd == SW_SHOWNORMAL, "expected SW_SHOWNORMAL, got %d\n", wp.showCmd); 13238 ok(wp.ptMinPosition.x == -1 && wp.ptMinPosition.y == -1, 13239 "expected -1,-1 got %d,%d\n", wp.ptMinPosition.x, wp.ptMinPosition.y); 13240 ok(wp.ptMaxPosition.x == -1 && wp.ptMaxPosition.y == -1, 13241 "expected -1,-1 got %d,%d\n", wp.ptMaxPosition.x, wp.ptMaxPosition.y); 13242 todo_wine_if (work_rc.left || work_rc.top) /* FIXME: remove once Wine is fixed */ 13243 ok(EqualRect(&win_rc, &wp.rcNormalPosition), "expected %s got %s\n", wine_dbgstr_rect(&win_rc), 13244 wine_dbgstr_rect(&wp.rcNormalPosition)); 13245 13246 for (i = 0; i < sizeof(sw)/sizeof(sw[0]); i++) 13247 { 13248 static const char * const sw_cmd_name[13] = 13249 { 13250 "SW_HIDE", "SW_SHOWNORMAL", "SW_SHOWMINIMIZED", "SW_SHOWMAXIMIZED", 13251 "SW_SHOWNOACTIVATE", "SW_SHOW", "SW_MINIMIZE", "SW_SHOWMINNOACTIVE", 13252 "SW_SHOWNA", "SW_RESTORE", "SW_SHOWDEFAULT", "SW_FORCEMINIMIZE", 13253 "SW_NORMALNA" /* 0xCC */ 13254 }; 13255 char comment[64]; 13256 INT idx; /* index into the above array of names */ 13257 13258 idx = (sw[i].cmd == SW_NORMALNA) ? 12 : sw[i].cmd; 13259 13260 style = GetWindowLongA(hwnd, GWL_STYLE); 13261 trace("%d: sending %s, current window style %08x\n", i+1, sw_cmd_name[idx], style); 13262 ret = ShowWindow(hwnd, sw[i].cmd); 13263 ok(!ret == !sw[i].ret, "%d: cmd %s: expected ret %lu, got %lu\n", i+1, sw_cmd_name[idx], sw[i].ret, ret); 13264 style = GetWindowLongA(hwnd, GWL_STYLE) & ~WS_BASE; 13265 ok(style == sw[i].style, "%d: expected style %08x, got %08x\n", i+1, sw[i].style, style); 13266 13267 sprintf(comment, "%d: ShowWindow(%s)", i+1, sw_cmd_name[idx]); 13268 ok_sequence(sw[i].msg, comment, sw[i].todo_msg); 13269 13270 wp.length = sizeof(wp); 13271 SetLastError(0xdeadbeaf); 13272 ret = GetWindowPlacement(hwnd, &wp); 13273 ok(ret, "GetWindowPlacement error %u\n", GetLastError()); 13274 ok(wp.flags == sw[i].wp_flags, "expected %#x, got %#x\n", sw[i].wp_flags, wp.flags); 13275 ok(wp.showCmd == sw[i].wp_cmd, "expected %d, got %d\n", sw[i].wp_cmd, wp.showCmd); 13276 13277 /* NT moves the minimized window to -32000,-32000, win9x to 3000,3000 */ 13278 if ((wp.ptMinPosition.x + work_rc.left == -32000 && wp.ptMinPosition.y + work_rc.top == -32000) || 13279 (wp.ptMinPosition.x + work_rc.left == 3000 && wp.ptMinPosition.y + work_rc.top == 3000)) 13280 { 13281 ok((wp.ptMinPosition.x + work_rc.left == sw[i].wp_min.x && wp.ptMinPosition.y + work_rc.top == sw[i].wp_min.y) || 13282 (wp.ptMinPosition.x + work_rc.left == 3000 && wp.ptMinPosition.y + work_rc.top == 3000), 13283 "expected %d,%d got %d,%d\n", sw[i].wp_min.x, sw[i].wp_min.y, wp.ptMinPosition.x, wp.ptMinPosition.y); 13284 } 13285 else 13286 { 13287 ok(wp.ptMinPosition.x == sw[i].wp_min.x && wp.ptMinPosition.y == sw[i].wp_min.y, 13288 "expected %d,%d got %d,%d\n", sw[i].wp_min.x, sw[i].wp_min.y, wp.ptMinPosition.x, wp.ptMinPosition.y); 13289 } 13290 13291 todo_wine_if(wp.ptMaxPosition.x != sw[i].wp_max.x || wp.ptMaxPosition.y != sw[i].wp_max.y) 13292 ok(wp.ptMaxPosition.x == sw[i].wp_max.x && wp.ptMaxPosition.y == sw[i].wp_max.y, 13293 "expected %d,%d got %d,%d\n", sw[i].wp_max.x, sw[i].wp_max.y, wp.ptMaxPosition.x, wp.ptMaxPosition.y); 13294 13295 if (0) /* FIXME: Wine behaves completely different here */ 13296 ok(EqualRect(&win_rc, &wp.rcNormalPosition), "expected %s got %s\n", 13297 wine_dbgstr_rect(&win_rc), wine_dbgstr_rect(&wp.rcNormalPosition)); 13298 } 13299 DestroyWindow(hwnd); 13300 flush_events(); 13301 } 13302 13303 static INT_PTR WINAPI test_dlg_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 13304 { 13305 struct recvd_message msg; 13306 13307 if (ignore_message( message )) return 0; 13308 13309 msg.hwnd = hwnd; 13310 msg.message = message; 13311 msg.flags = sent|wparam|lparam; 13312 msg.wParam = wParam; 13313 msg.lParam = lParam; 13314 msg.descr = "dialog"; 13315 add_message(&msg); 13316 13317 /* calling DefDlgProc leads to a recursion under XP */ 13318 13319 switch (message) 13320 { 13321 case WM_INITDIALOG: 13322 return lParam; 13323 13324 case WM_GETDLGCODE: 13325 return 0; 13326 } 13327 return 1; 13328 } 13329 13330 static WNDPROC orig_edit_proc; 13331 static LRESULT WINAPI dlg_creation_edit_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) 13332 { 13333 struct recvd_message msg; 13334 13335 if (ignore_message( message )) return 0; 13336 13337 msg.hwnd = hwnd; 13338 msg.message = message; 13339 msg.flags = sent|wparam|lparam; 13340 msg.wParam = wp; 13341 msg.lParam = lp; 13342 msg.descr = "edit"; 13343 add_message(&msg); 13344 13345 return CallWindowProcW(orig_edit_proc, hwnd, message, wp, lp); 13346 } 13347 13348 static INT_PTR WINAPI test_dlg_proc2(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 13349 { 13350 struct recvd_message msg; 13351 13352 if (ignore_message( message )) return 0; 13353 13354 msg.hwnd = hwnd; 13355 msg.message = message; 13356 msg.flags = sent|wparam|lparam|parent; 13357 msg.wParam = wParam; 13358 msg.lParam = lParam; 13359 msg.descr = "dialog"; 13360 add_message(&msg); 13361 13362 if (message == WM_INITDIALOG) 13363 { 13364 orig_edit_proc = (WNDPROC)SetWindowLongPtrW(GetDlgItem(hwnd, 200), 13365 GWLP_WNDPROC, (LONG_PTR)dlg_creation_edit_proc); 13366 } 13367 13368 return 1; 13369 } 13370 13371 static INT_PTR WINAPI test_dlg_proc3(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 13372 { 13373 ok( 0, "should not be called since DefDlgProc is not used\n" ); 13374 return 0; 13375 } 13376 13377 static LRESULT WINAPI test_dlg_proc4(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 13378 { 13379 struct recvd_message msg; 13380 13381 if (!ignore_message( message )) 13382 { 13383 msg.hwnd = hwnd; 13384 msg.message = message; 13385 msg.flags = sent|wparam|lparam|parent; 13386 msg.wParam = wParam; 13387 msg.lParam = lParam; 13388 msg.descr = "dialog"; 13389 add_message(&msg); 13390 } 13391 if (message == WM_INITDIALOG) 13392 { 13393 orig_edit_proc = (WNDPROC)SetWindowLongPtrW(GetDlgItem(hwnd, 200), 13394 GWLP_WNDPROC, (LONG_PTR)dlg_creation_edit_proc); 13395 return 1; 13396 } 13397 return DefWindowProcW( hwnd, message, wParam, lParam ); 13398 } 13399 13400 static const struct message WmDefDlgSetFocus_1[] = { 13401 { WM_GETDLGCODE, sent|wparam|lparam, 0, 0 }, 13402 { WM_GETTEXTLENGTH, sent|wparam|lparam|optional, 0, 0 }, /* XP */ 13403 { WM_GETTEXT, sent|wparam|optional, 6 }, /* XP */ 13404 { WM_GETTEXT, sent|wparam|optional, 12 }, /* XP */ 13405 { EM_SETSEL, sent|wparam, 0 }, /* XP sets lparam to text length, Win9x to -2 */ 13406 { HCBT_SETFOCUS, hook }, 13407 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 13408 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 13409 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 13410 { WM_SETFOCUS, sent|wparam, 0 }, 13411 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 10 }, 13412 { WM_CTLCOLOREDIT, sent }, 13413 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 11 }, 13414 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 13415 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 13416 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 13417 { WM_COMMAND, sent|wparam, MAKEWPARAM(1, EN_SETFOCUS) }, 13418 { 0 } 13419 }; 13420 static const struct message WmDefDlgSetFocus_2[] = { 13421 { WM_GETDLGCODE, sent|wparam|lparam, 0, 0 }, 13422 { WM_GETTEXTLENGTH, sent|wparam|lparam|optional, 0, 0 }, /* XP */ 13423 { WM_GETTEXT, sent|wparam|optional, 6 }, /* XP */ 13424 { WM_GETTEXT, sent|wparam|optional, 12 }, /* XP */ 13425 { EM_SETSEL, sent|wparam, 0 }, /* XP sets lparam to text length, Win9x to -2 */ 13426 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 13427 { WM_CTLCOLOREDIT, sent|optional }, /* XP */ 13428 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 13429 { 0 } 13430 }; 13431 /* Creation of a dialog */ 13432 static const struct message WmCreateDialogParamSeq_0[] = { 13433 { HCBT_CREATEWND, hook }, 13434 { WM_NCCREATE, sent }, 13435 { WM_NCCALCSIZE, sent|wparam, 0 }, 13436 { WM_CREATE, sent }, 13437 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 13438 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 13439 { WM_MOVE, sent }, 13440 { WM_SETFONT, sent }, 13441 { WM_INITDIALOG, sent }, 13442 { WM_CHANGEUISTATE, sent|optional }, 13443 { 0 } 13444 }; 13445 /* Creation of a dialog */ 13446 static const struct message WmCreateDialogParamSeq_1[] = { 13447 { HCBT_CREATEWND, hook }, 13448 { WM_NCCREATE, sent }, 13449 { WM_NCCALCSIZE, sent|wparam, 0 }, 13450 { WM_CREATE, sent }, 13451 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 13452 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 13453 { WM_MOVE, sent }, 13454 { WM_SETFONT, sent }, 13455 { WM_INITDIALOG, sent }, 13456 { WM_GETDLGCODE, sent|wparam|lparam|optional, 0, 0 }, /* FIXME: Wine doesn't send it */ 13457 { HCBT_SETFOCUS, hook }, 13458 { HCBT_ACTIVATE, hook }, 13459 { WM_QUERYNEWPALETTE, sent|optional }, 13460 { WM_PALETTEISCHANGING, sent|optional }, 13461 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 13462 { WM_ACTIVATEAPP, sent|wparam, 1 }, 13463 { WM_NCACTIVATE, sent }, 13464 { WM_ACTIVATE, sent|wparam, 1 }, 13465 { WM_SETFOCUS, sent }, 13466 { WM_CHANGEUISTATE, sent|optional }, 13467 { 0 } 13468 }; 13469 /* Creation of a dialog */ 13470 static const struct message WmCreateDialogParamSeq_2[] = { 13471 { HCBT_CREATEWND, hook }, 13472 { WM_NCCREATE, sent }, 13473 { WM_NCCALCSIZE, sent|wparam, 0 }, 13474 { WM_CREATE, sent }, 13475 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 13476 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 13477 { WM_MOVE, sent }, 13478 { WM_CHANGEUISTATE, sent|optional }, 13479 { 0 } 13480 }; 13481 13482 static const struct message WmCreateDialogParamSeq_3[] = { 13483 { HCBT_CREATEWND, hook }, 13484 { WM_SETFONT, sent|parent }, 13485 { WM_INITDIALOG, sent|parent }, 13486 { WM_GETDLGCODE, sent|wparam|lparam, 0, 0 }, 13487 { EM_SETSEL, sent|wparam|lparam, 0, INT_MAX }, 13488 { EM_SETSEL, sent|wparam|lparam|optional, 0, INT_MAX }, 13489 { EM_SETSEL, sent|wparam|lparam|optional, 0, INT_MAX }, 13490 { EM_SETSEL, sent|wparam|lparam|optional, 0, INT_MAX }, 13491 { HCBT_ACTIVATE, hook }, 13492 { WM_QUERYNEWPALETTE, sent|parent|optional }, /* TODO: this message should not be sent */ 13493 { WM_WINDOWPOSCHANGING, sent|parent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 13494 { WM_WINDOWPOSCHANGING, sent|parent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 13495 { WM_ACTIVATEAPP, sent|parent|wparam, 1 }, 13496 { WM_NCACTIVATE, sent|parent }, 13497 { WM_ACTIVATE, sent|parent|wparam, 1 }, 13498 { WM_SETFOCUS, sent }, 13499 { WM_COMMAND, sent|parent|wparam, MAKELONG(200, EN_SETFOCUS) }, 13500 { WM_GETDLGCODE, sent|wparam|lparam, 0, 0 }, 13501 { WM_USER, sent|parent }, 13502 { WM_CHANGEUISTATE, sent|parent|optional }, 13503 { 0 } 13504 }; 13505 13506 static const struct message WmCreateDialogParamSeq_4[] = { 13507 { HCBT_CREATEWND, hook }, 13508 { WM_NCCREATE, sent|parent }, 13509 { WM_NCCALCSIZE, sent|parent|wparam, 0 }, 13510 { WM_CREATE, sent|parent }, 13511 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 13512 { WM_SIZE, sent|parent|wparam, SIZE_RESTORED }, 13513 { WM_MOVE, sent|parent }, 13514 { WM_SETFONT, sent|parent }, 13515 { WM_INITDIALOG, sent|parent }, 13516 { WM_GETDLGCODE, sent|wparam|lparam, 0, 0 }, 13517 { EM_SETSEL, sent|wparam|lparam, 0, INT_MAX }, 13518 { EM_SETSEL, sent|wparam|lparam|optional, 0, INT_MAX }, 13519 { EM_SETSEL, sent|wparam|lparam|optional, 0, INT_MAX }, 13520 { EM_SETSEL, sent|wparam|lparam|optional, 0, INT_MAX }, 13521 { HCBT_ACTIVATE, hook }, 13522 { WM_QUERYNEWPALETTE, sent|parent|optional }, /* TODO: this message should not be sent */ 13523 { WM_WINDOWPOSCHANGING, sent|parent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 13524 { WM_WINDOWPOSCHANGING, sent|parent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 13525 { WM_ACTIVATEAPP, sent|parent|wparam, 1 }, 13526 { WM_NCACTIVATE, sent|parent }, 13527 { WM_ACTIVATE, sent|parent|wparam, 1 }, 13528 { HCBT_SETFOCUS, hook }, 13529 { WM_SETFOCUS, sent|parent }, 13530 { WM_KILLFOCUS, sent|parent }, 13531 { WM_SETFOCUS, sent }, 13532 { WM_COMMAND, sent|parent|wparam, MAKELONG(200, EN_SETFOCUS) }, 13533 { WM_GETDLGCODE, sent|wparam|lparam, 0, 0 }, 13534 { WM_USER, sent|parent }, 13535 { WM_CHANGEUISTATE, sent|parent|optional }, 13536 { WM_UPDATEUISTATE, sent|parent|optional }, 13537 { WM_UPDATEUISTATE, sent|optional }, 13538 { 0 } 13539 }; 13540 13541 static void test_dialog_messages(void) 13542 { 13543 WNDCLASSA cls; 13544 HWND hdlg, hedit1, hedit2, hfocus, parent, child, child2; 13545 LRESULT ret; 13546 13547 #define set_selection(hctl, start, end) \ 13548 ret = SendMessageA(hctl, EM_SETSEL, start, end); \ 13549 ok(ret == 1, "EM_SETSEL returned %ld\n", ret); 13550 13551 #define check_selection(hctl, start, end) \ 13552 ret = SendMessageA(hctl, EM_GETSEL, 0, 0); \ 13553 ok(ret == MAKELRESULT(start, end), "wrong selection (%d - %d)\n", LOWORD(ret), HIWORD(ret)); 13554 13555 subclass_edit(); 13556 13557 hdlg = CreateWindowExA(WS_EX_DLGMODALFRAME, "TestDialogClass", NULL, 13558 WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_DLGFRAME, 13559 0, 0, 100, 100, 0, 0, 0, NULL); 13560 ok(hdlg != 0, "Failed to create custom dialog window\n"); 13561 13562 hedit1 = CreateWindowExA(0, "my_edit_class", NULL, 13563 WS_CHILD|WS_BORDER|WS_VISIBLE|WS_TABSTOP, 13564 0, 0, 80, 20, hdlg, (HMENU)1, 0, NULL); 13565 ok(hedit1 != 0, "Failed to create edit control\n"); 13566 hedit2 = CreateWindowExA(0, "my_edit_class", NULL, 13567 WS_CHILD|WS_BORDER|WS_VISIBLE|WS_TABSTOP, 13568 0, 40, 80, 20, hdlg, (HMENU)2, 0, NULL); 13569 ok(hedit2 != 0, "Failed to create edit control\n"); 13570 13571 SendMessageA(hedit1, WM_SETTEXT, 0, (LPARAM)"hello"); 13572 SendMessageA(hedit2, WM_SETTEXT, 0, (LPARAM)"bye"); 13573 13574 hfocus = GetFocus(); 13575 ok(hfocus == hdlg, "wrong focus %p\n", hfocus); 13576 13577 SetFocus(hedit2); 13578 hfocus = GetFocus(); 13579 ok(hfocus == hedit2, "wrong focus %p\n", hfocus); 13580 13581 check_selection(hedit1, 0, 0); 13582 check_selection(hedit2, 0, 0); 13583 13584 set_selection(hedit2, 0, -1); 13585 check_selection(hedit2, 0, 3); 13586 13587 SetFocus(0); 13588 hfocus = GetFocus(); 13589 ok(hfocus == 0, "wrong focus %p\n", hfocus); 13590 13591 flush_sequence(); 13592 ret = DefDlgProcA(hdlg, WM_SETFOCUS, 0, 0); 13593 ok(ret == 0, "WM_SETFOCUS returned %ld\n", ret); 13594 ok_sequence(WmDefDlgSetFocus_1, "DefDlgProc(WM_SETFOCUS) 1", FALSE); 13595 13596 hfocus = GetFocus(); 13597 ok(hfocus == hedit1, "wrong focus %p\n", hfocus); 13598 13599 check_selection(hedit1, 0, 5); 13600 check_selection(hedit2, 0, 3); 13601 13602 flush_sequence(); 13603 ret = DefDlgProcA(hdlg, WM_SETFOCUS, 0, 0); 13604 ok(ret == 0, "WM_SETFOCUS returned %ld\n", ret); 13605 ok_sequence(WmDefDlgSetFocus_2, "DefDlgProc(WM_SETFOCUS) 2", FALSE); 13606 13607 hfocus = GetFocus(); 13608 ok(hfocus == hedit1, "wrong focus %p\n", hfocus); 13609 13610 check_selection(hedit1, 0, 5); 13611 check_selection(hedit2, 0, 3); 13612 13613 EndDialog(hdlg, 0); 13614 DestroyWindow(hedit1); 13615 DestroyWindow(hedit2); 13616 DestroyWindow(hdlg); 13617 flush_sequence(); 13618 13619 #undef set_selection 13620 #undef check_selection 13621 13622 ok(GetClassInfoA(0, "#32770", &cls), "GetClassInfo failed\n"); 13623 cls.lpszClassName = "MyDialogClass"; 13624 cls.hInstance = GetModuleHandleA(NULL); 13625 /* need a cast since a dlgproc is used as a wndproc */ 13626 cls.lpfnWndProc = test_dlg_proc; 13627 if (!RegisterClassA(&cls)) assert(0); 13628 13629 SetFocus(0); 13630 flush_sequence(); 13631 hdlg = CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", 0, test_dlg_proc, 0); 13632 ok(IsWindow(hdlg), "CreateDialogParam failed\n"); 13633 ok_sequence(WmCreateDialogParamSeq_0, "CreateDialogParam_0", FALSE); 13634 hfocus = GetFocus(); 13635 ok(hfocus == 0, "wrong focus %p\n", hfocus); 13636 EndDialog(hdlg, 0); 13637 DestroyWindow(hdlg); 13638 flush_sequence(); 13639 13640 SetFocus(0); 13641 flush_sequence(); 13642 hdlg = CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", 0, test_dlg_proc, 1); 13643 ok(IsWindow(hdlg), "CreateDialogParam failed\n"); 13644 ok_sequence(WmCreateDialogParamSeq_1, "CreateDialogParam_1", FALSE); 13645 hfocus = GetFocus(); 13646 ok(hfocus == hdlg, "wrong focus %p\n", hfocus); 13647 EndDialog(hdlg, 0); 13648 DestroyWindow(hdlg); 13649 flush_sequence(); 13650 13651 hdlg = CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", 0, NULL, 0); 13652 ok(IsWindow(hdlg), "CreateDialogParam failed\n"); 13653 ok_sequence(WmCreateDialogParamSeq_2, "CreateDialogParam_2", FALSE); 13654 EndDialog(hdlg, 0); 13655 DestroyWindow(hdlg); 13656 flush_sequence(); 13657 13658 hdlg = CreateDialogParamA(0, "FOCUS_TEST_DIALOG_3", 0, test_dlg_proc2, 0); 13659 ok(IsWindow(hdlg), "CreateDialogParam failed\n"); 13660 ok_sequence(WmCreateDialogParamSeq_3, "CreateDialogParam_3", TRUE); 13661 EndDialog(hdlg, 0); 13662 DestroyWindow(hdlg); 13663 flush_sequence(); 13664 13665 UnregisterClassA( cls.lpszClassName, cls.hInstance ); 13666 cls.lpfnWndProc = test_dlg_proc4; 13667 ok( RegisterClassA(&cls), "failed to register class again\n" ); 13668 hdlg = CreateDialogParamA(0, "FOCUS_TEST_DIALOG_4", 0, test_dlg_proc3, 0); 13669 ok(IsWindow(hdlg), "CreateDialogParam failed\n"); 13670 ok_sequence(WmCreateDialogParamSeq_4, "CreateDialogParam_4", TRUE); 13671 EndDialog(hdlg, 0); 13672 DestroyWindow(hdlg); 13673 flush_sequence(); 13674 13675 UnregisterClassA(cls.lpszClassName, cls.hInstance); 13676 13677 parent = CreateWindowExA(0, "TestParentClass", "Test parent", 13678 WS_OVERLAPPEDWINDOW | WS_VISIBLE, 13679 100, 100, 200, 200, 0, 0, 0, NULL); 13680 ok (parent != 0, "Failed to create parent window\n"); 13681 13682 /* This child has no parent set. We will later call SetParent on it, 13683 * so that it will have a parent set, but no WS_CHILD style. */ 13684 child = CreateWindowExA(0, "TestWindowClass", "Test child", 13685 WS_OVERLAPPEDWINDOW | WS_VISIBLE, 13686 100, 100, 200, 200, 0, 0, 0, NULL); 13687 ok (child != 0, "Failed to create child window\n"); 13688 13689 /* This is a regular child window. When used as an owner, the other 13690 * child window will be used. */ 13691 child2 = CreateWindowExA(0, "SimpleWindowClass", "Test child2", 13692 WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CHILD, 13693 100, 100, 200, 200, child, 0, 0, NULL); 13694 ok (child2 != 0, "Failed to create child window\n"); 13695 13696 SetParent(child, parent); 13697 SetFocus(child); 13698 13699 flush_sequence(); 13700 DialogBoxA( 0, "TEST_DIALOG", child2, TestModalDlgProc2 ); 13701 ok_sequence(WmModalDialogSeq_2, "ModalDialog2", TRUE); 13702 13703 DestroyWindow(child2); 13704 DestroyWindow(child); 13705 DestroyWindow(parent); 13706 flush_sequence(); 13707 } 13708 13709 static void test_enddialog_seq(HWND dialog, HWND owner) 13710 { 13711 const struct message seq[] = { 13712 { WM_ENABLE, sent }, 13713 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 13714 { HCBT_ACTIVATE, hook|wparam, (WPARAM)owner }, 13715 { WM_NCACTIVATE, sent|wparam|lparam, WA_INACTIVE, (LPARAM)owner }, 13716 { WM_ACTIVATE, sent|wparam|lparam, WA_INACTIVE, (LPARAM)owner }, 13717 /* FIXME: Following two are optional because Wine sends WM_QUERYNEWPALETTE instead of WM_WINDOWPOSCHANGING */ 13718 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 13719 { WM_QUERYNEWPALETTE, sent|optional }, 13720 { WM_NCACTIVATE, sent|wparam|lparam, WA_ACTIVE, (LPARAM)dialog }, 13721 { WM_GETTEXT, sent|optional|defwinproc }, 13722 { WM_ACTIVATE, sent|wparam|lparam, WA_ACTIVE, (LPARAM)dialog }, 13723 { HCBT_SETFOCUS, hook|wparam, (WPARAM)owner }, 13724 { WM_KILLFOCUS, sent|wparam, (WPARAM)owner }, 13725 { WM_SETFOCUS, sent|defwinproc|wparam, (WPARAM)dialog }, 13726 { 0 } 13727 }; 13728 13729 flush_sequence(); 13730 EndDialog(dialog, 0); 13731 ok_sequence(seq, "EndDialog", FALSE); 13732 } 13733 13734 static void test_enddialog_seq2(HWND dialog, HWND owner) 13735 { 13736 const struct message seq[] = { 13737 { WM_ENABLE, parent|sent }, 13738 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 13739 { HCBT_ACTIVATE, hook|wparam, (WPARAM)owner }, 13740 { WM_NCACTIVATE, sent|wparam|lparam, WA_INACTIVE, (LPARAM)owner }, 13741 { WM_ACTIVATE, sent|wparam|lparam, WA_INACTIVE, (LPARAM)owner }, 13742 { WM_WINDOWPOSCHANGING, sent|optional|wparam, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 13743 { WM_WINDOWPOSCHANGING, sent|optional|wparam, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 13744 { HCBT_SETFOCUS, hook|wparam, (WPARAM)owner }, 13745 { WM_KILLFOCUS, sent|wparam, (WPARAM)owner }, 13746 { WM_SETFOCUS, sent|parent|defwinproc|wparam, (WPARAM)dialog }, 13747 { 0 } 13748 }; 13749 13750 flush_sequence(); 13751 EndDialog(dialog, 0); 13752 ok_sequence(seq, "EndDialog2", FALSE); 13753 } 13754 13755 static void test_EndDialog(void) 13756 { 13757 HWND hparent, hother, hactive, hdlg, hchild; 13758 WNDCLASSA cls; 13759 13760 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", 13761 WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_DISABLED, 13762 100, 100, 200, 200, 0, 0, 0, NULL); 13763 ok (hparent != 0, "Failed to create parent window\n"); 13764 13765 hother = CreateWindowExA(0, "TestParentClass", "Test parent 2", 13766 WS_OVERLAPPEDWINDOW | WS_VISIBLE, 13767 200, 100, 200, 200, 0, 0, 0, NULL); 13768 ok (hother != 0, "Failed to create parent window\n"); 13769 13770 ok(GetClassInfoA(0, "#32770", &cls), "GetClassInfo failed\n"); 13771 cls.lpszClassName = "MyDialogClass"; 13772 cls.hInstance = GetModuleHandleA(NULL); 13773 cls.lpfnWndProc = test_dlg_proc; 13774 if (!RegisterClassA(&cls)) assert(0); 13775 13776 flush_sequence(); 13777 SetForegroundWindow(hother); 13778 hactive = GetForegroundWindow(); 13779 ok(hother == hactive, "Wrong window has focus (%p != %p)\n", hother, hactive); 13780 13781 /* create a dialog where the parent is disabled, this parent should be 13782 * enabled and receive focus when dialog exits */ 13783 hdlg = CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", hparent, test_dlg_proc, 0); 13784 ok(IsWindow(hdlg), "CreateDialogParam failed\n"); 13785 SetForegroundWindow(hdlg); 13786 hactive = GetForegroundWindow(); 13787 ok(hdlg == hactive, "Wrong window has focus (%p != %p)\n", hdlg, hactive); 13788 EndDialog(hdlg, 0); 13789 ok(IsWindowEnabled(hparent), "parent is not enabled\n"); 13790 hactive = GetForegroundWindow(); 13791 ok(hparent == hactive, "Wrong window has focus (parent != active) (active: %p, parent: %p, dlg: %p, other: %p)\n", hactive, hparent, hdlg, hother); 13792 DestroyWindow(hdlg); 13793 flush_sequence(); 13794 13795 /* create a dialog where the parent is disabled and set active window to other window before calling EndDialog */ 13796 EnableWindow(hparent, FALSE); 13797 hdlg = CreateWindowExA(0, "TestDialogClass", NULL, 13798 WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_DLGFRAME, 13799 0, 0, 100, 100, hparent, 0, 0, NULL); 13800 ok(IsWindow(hdlg), "CreateDialogParam failed\n"); 13801 flush_sequence(); 13802 SetForegroundWindow(hother); 13803 flush_sequence(); 13804 hactive = GetForegroundWindow(); 13805 ok(hactive == hother, "Wrong foreground (%p != %p)\n", hactive, hother); 13806 hactive = GetActiveWindow(); 13807 ok(hactive == hother, "Wrong active window (%p != %p)\n", hactive, hother); 13808 EndDialog(hdlg, 0); 13809 ok(IsWindowEnabled(hparent), "parent is not enabled\n"); 13810 hactive = GetForegroundWindow(); 13811 ok(hother == hactive, "Wrong window has focus (other != active) (active: %p, parent: %p, dlg: %p, other: %p)\n", hactive, hparent, hdlg, hother); 13812 DestroyWindow(hdlg); 13813 flush_sequence(); 13814 13815 DestroyWindow( hparent ); 13816 13817 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", 13818 WS_POPUP | WS_VISIBLE | WS_DISABLED, 13819 100, 100, 200, 200, 0, 0, 0, NULL); 13820 ok (hparent != 0, "Failed to create parent window\n"); 13821 13822 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", 13823 WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_DISABLED, 13824 0, 0, 0, 0, 0, 0, 0, NULL); 13825 ok (hchild != 0, "Failed to create child window\n"); 13826 13827 SetParent(hchild, hparent); 13828 13829 flush_sequence(); 13830 SetForegroundWindow(hother); 13831 hactive = GetForegroundWindow(); 13832 ok(hother == hactive, "Wrong foreground window (%p != %p)\n", hother, hactive); 13833 13834 hdlg = CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", hchild, test_dlg_proc, 0); 13835 ok(IsWindow(hdlg), "CreateDialogParam failed\n"); 13836 13837 SetForegroundWindow(hdlg); 13838 test_enddialog_seq(hdlg, hchild); 13839 13840 hactive = GetForegroundWindow(); 13841 ok(hactive == hchild, "Wrong foreground window (active: %p, parent: %p, dlg: %p, other: %p child: %p)\n", hactive, hparent, hdlg, hother, hchild); 13842 13843 DestroyWindow(hdlg); 13844 13845 /* Now set WS_CHILD style flag so that it's a real child and its parent will be dialog's owner. */ 13846 SetWindowLongW(hchild, GWL_STYLE, GetWindowLongW(hchild, GWL_STYLE) | WS_CHILD); 13847 13848 SetForegroundWindow(hother); 13849 hactive = GetForegroundWindow(); 13850 ok(hother == hactive, "Wrong foreground window (%p != %p)\n", hother, hactive); 13851 13852 hdlg = CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", hchild, test_dlg_proc, 0); 13853 ok(IsWindow(hdlg), "CreateDialogParam failed\n"); 13854 13855 SetForegroundWindow(hdlg); 13856 test_enddialog_seq2(hdlg, hparent); 13857 13858 hactive = GetForegroundWindow(); 13859 ok(hactive == hparent, "Wrong foreground window (active: %p, parent: %p, dlg: %p, other: %p child: %p)\n", hactive, hparent, hdlg, hother, hchild); 13860 DestroyWindow(hdlg); 13861 DestroyWindow(hchild); 13862 DestroyWindow(hparent); 13863 DestroyWindow(hother); 13864 flush_sequence(); 13865 13866 UnregisterClassA(cls.lpszClassName, cls.hInstance); 13867 } 13868 13869 static void test_nullCallback(void) 13870 { 13871 HWND hwnd; 13872 13873 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW, 13874 100, 100, 200, 200, 0, 0, 0, NULL); 13875 ok (hwnd != 0, "Failed to create overlapped window\n"); 13876 13877 SendMessageCallbackA(hwnd,WM_NULL,0,0,NULL,0); 13878 flush_events(); 13879 DestroyWindow(hwnd); 13880 } 13881 13882 /* SetActiveWindow( 0 ) hwnd visible */ 13883 static const struct message SetActiveWindowSeq0[] = 13884 { 13885 { HCBT_ACTIVATE, hook|optional }, 13886 { WM_NCACTIVATE, sent|wparam, 0 }, 13887 { WM_GETTEXT, sent|defwinproc|optional }, 13888 { WM_ACTIVATE, sent|wparam, 0 }, 13889 { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, 13890 { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, 13891 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 13892 { WM_KILLFOCUS, sent|optional }, 13893 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, 13894 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 13895 { WM_NCACTIVATE, sent|wparam|optional, 1 }, 13896 { WM_GETTEXT, sent|defwinproc|optional }, 13897 { WM_ACTIVATE, sent|wparam|optional, 1 }, 13898 { HCBT_SETFOCUS, hook|optional }, 13899 { WM_KILLFOCUS, sent|defwinproc|optional }, 13900 { WM_IME_SETCONTEXT, sent|defwinproc|optional }, 13901 { WM_IME_SETCONTEXT, sent|defwinproc|optional }, 13902 { WM_IME_SETCONTEXT, sent|optional }, 13903 { WM_IME_SETCONTEXT, sent|optional }, 13904 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, 13905 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 13906 { WM_SETFOCUS, sent|defwinproc|optional }, 13907 { WM_GETTEXT, sent|optional }, 13908 { 0 } 13909 }; 13910 /* SetActiveWindow( hwnd ) hwnd visible */ 13911 static const struct message SetActiveWindowSeq1[] = 13912 { 13913 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 13914 { 0 } 13915 }; 13916 /* SetActiveWindow( popup ) hwnd visible, popup visible */ 13917 static const struct message SetActiveWindowSeq2[] = 13918 { 13919 { HCBT_ACTIVATE, hook }, 13920 { WM_NCACTIVATE, sent|wparam, 0 }, 13921 { WM_GETTEXT, sent|defwinproc|optional }, 13922 { WM_ACTIVATE, sent|wparam, 0 }, 13923 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 13924 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 13925 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, 13926 { WM_NCPAINT, sent|optional }, 13927 { WM_GETTEXT, sent|defwinproc|optional }, 13928 { WM_ERASEBKGND, sent|optional }, 13929 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 13930 { WM_NCACTIVATE, sent|wparam, 1 }, 13931 { WM_GETTEXT, sent|defwinproc|optional }, 13932 { WM_ACTIVATE, sent|wparam, 1 }, 13933 { HCBT_SETFOCUS, hook }, 13934 { WM_KILLFOCUS, sent|defwinproc }, 13935 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 }, 13936 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 13937 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, 13938 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 13939 { WM_SETFOCUS, sent|defwinproc }, 13940 { WM_GETTEXT, sent|optional }, 13941 { 0 } 13942 }; 13943 13944 /* SetActiveWindow( hwnd ) hwnd not visible */ 13945 static const struct message SetActiveWindowSeq3[] = 13946 { 13947 { HCBT_ACTIVATE, hook }, 13948 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 13949 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, 13950 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE }, 13951 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOACTIVATE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 13952 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 13953 { WM_ACTIVATEAPP, sent|wparam, 1 }, 13954 { WM_ACTIVATEAPP, sent|wparam, 1 }, 13955 { WM_NCACTIVATE, sent|wparam, 1 }, 13956 { WM_ACTIVATE, sent|wparam, 1 }, 13957 { HCBT_SETFOCUS, hook }, 13958 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 13959 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 13960 { WM_SETFOCUS, sent|defwinproc }, 13961 { 0 } 13962 }; 13963 /* SetActiveWindow( popup ) hwnd not visible, popup not visible */ 13964 static const struct message SetActiveWindowSeq4[] = 13965 { 13966 { HCBT_ACTIVATE, hook }, 13967 { WM_NCACTIVATE, sent|wparam, 0 }, 13968 { WM_GETTEXT, sent|defwinproc|optional }, 13969 { WM_ACTIVATE, sent|wparam, 0 }, 13970 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 13971 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE }, 13972 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, 13973 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 13974 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 13975 { WM_NCACTIVATE, sent|wparam, 1 }, 13976 { WM_GETTEXT, sent|defwinproc|optional }, 13977 { WM_ACTIVATE, sent|wparam, 1 }, 13978 { HCBT_SETFOCUS, hook }, 13979 { WM_KILLFOCUS, sent|defwinproc }, 13980 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 }, 13981 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 13982 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, 13983 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 13984 { WM_SETFOCUS, sent|defwinproc }, 13985 { 0 } 13986 }; 13987 13988 13989 static void test_SetActiveWindow(void) 13990 { 13991 HWND hwnd, popup, ret; 13992 13993 hwnd = CreateWindowExA(0, "TestWindowClass", "Test SetActiveWindow", 13994 WS_OVERLAPPEDWINDOW | WS_VISIBLE, 13995 100, 100, 200, 200, 0, 0, 0, NULL); 13996 13997 popup = CreateWindowExA(0, "TestWindowClass", "Test SetActiveWindow", 13998 WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_POPUP, 13999 100, 100, 200, 200, hwnd, 0, 0, NULL); 14000 14001 ok(hwnd != 0, "Failed to create overlapped window\n"); 14002 ok(popup != 0, "Failed to create popup window\n"); 14003 SetForegroundWindow( popup ); 14004 flush_sequence(); 14005 14006 trace("SetActiveWindow(0)\n"); 14007 ret = SetActiveWindow(0); 14008 ok( ret == popup, "Failed to SetActiveWindow(0)\n"); 14009 ok_sequence(SetActiveWindowSeq0, "SetActiveWindow(0)", FALSE); 14010 flush_sequence(); 14011 14012 trace("SetActiveWindow(hwnd), hwnd visible\n"); 14013 ret = SetActiveWindow(hwnd); 14014 if (ret == hwnd) ok_sequence(SetActiveWindowSeq1, "SetActiveWindow(hwnd), hwnd visible", TRUE); 14015 flush_sequence(); 14016 14017 trace("SetActiveWindow(popup), hwnd visible, popup visible\n"); 14018 ret = SetActiveWindow(popup); 14019 ok( ret == hwnd, "Failed to SetActiveWindow(popup), popup visible\n"); 14020 ok_sequence(SetActiveWindowSeq2, "SetActiveWindow(popup), hwnd visible, popup visible", FALSE); 14021 flush_sequence(); 14022 14023 ShowWindow(hwnd, SW_HIDE); 14024 ShowWindow(popup, SW_HIDE); 14025 flush_sequence(); 14026 14027 trace("SetActiveWindow(hwnd), hwnd not visible\n"); 14028 ret = SetActiveWindow(hwnd); 14029 ok( ret == NULL, "SetActiveWindow(hwnd), hwnd not visible, previous is %p\n", ret ); 14030 ok_sequence(SetActiveWindowSeq3, "SetActiveWindow(hwnd), hwnd not visible", TRUE); 14031 flush_sequence(); 14032 14033 trace("SetActiveWindow(popup), hwnd not visible, popup not visible\n"); 14034 ret = SetActiveWindow(popup); 14035 ok( ret == hwnd, "Failed to SetActiveWindow(popup)\n"); 14036 ok_sequence(SetActiveWindowSeq4, "SetActiveWindow(popup), hwnd not visible, popup not visible", TRUE); 14037 flush_sequence(); 14038 14039 trace("done\n"); 14040 14041 DestroyWindow(hwnd); 14042 } 14043 14044 static const struct message SetForegroundWindowSeq[] = 14045 { 14046 { WM_NCACTIVATE, sent|wparam, 0 }, 14047 { WM_GETTEXT, sent|defwinproc|optional }, 14048 { WM_ACTIVATE, sent|wparam, 0 }, 14049 { WM_ACTIVATEAPP, sent|wparam, 0 }, 14050 { WM_KILLFOCUS, sent }, 14051 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 14052 { WM_IME_NOTIFY, sent|wparam|optional|defwinproc, 1 }, 14053 { 0 } 14054 }; 14055 14056 static void test_SetForegroundWindow(void) 14057 { 14058 HWND hwnd; 14059 14060 hwnd = CreateWindowExA(0, "TestWindowClass", "Test SetForegroundWindow", 14061 WS_OVERLAPPEDWINDOW | WS_VISIBLE, 14062 100, 100, 200, 200, 0, 0, 0, NULL); 14063 ok (hwnd != 0, "Failed to create overlapped window\n"); 14064 SetForegroundWindow( hwnd ); 14065 flush_sequence(); 14066 14067 trace("SetForegroundWindow( 0 )\n"); 14068 SetForegroundWindow( 0 ); 14069 ok_sequence(WmEmptySeq, "SetForegroundWindow( 0 ) away from foreground top level window", FALSE); 14070 trace("SetForegroundWindow( GetDesktopWindow() )\n"); 14071 SetForegroundWindow( GetDesktopWindow() ); 14072 ok_sequence(SetForegroundWindowSeq, "SetForegroundWindow( desktop ) away from " 14073 "foreground top level window", FALSE); 14074 trace("done\n"); 14075 14076 DestroyWindow(hwnd); 14077 } 14078 14079 static DWORD get_input_codepage( void ) 14080 { 14081 DWORD cp; 14082 int ret; 14083 HKL hkl = GetKeyboardLayout( 0 ); 14084 14085 ret = GetLocaleInfoW( LOWORD(hkl), LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER, 14086 (WCHAR *)&cp, sizeof(cp) / sizeof(WCHAR) ); 14087 if (!ret) cp = CP_ACP; 14088 return cp; 14089 } 14090 14091 static void test_dbcs_wm_char(void) 14092 { 14093 BYTE dbch[2]; 14094 WCHAR wch, bad_wch; 14095 HWND hwnd, hwnd2; 14096 MSG msg; 14097 DWORD time; 14098 POINT pt; 14099 DWORD_PTR res; 14100 CPINFOEXA cpinfo; 14101 UINT i, j, k; 14102 struct message wmCharSeq[2]; 14103 BOOL ret; 14104 DWORD cp = get_input_codepage(); 14105 14106 if (!pGetCPInfoExA) 14107 { 14108 win_skip("GetCPInfoExA is not available\n"); 14109 return; 14110 } 14111 14112 pGetCPInfoExA( cp, 0, &cpinfo ); 14113 if (cpinfo.MaxCharSize != 2) 14114 { 14115 skip( "Skipping DBCS WM_CHAR test in SBCS codepage '%s'\n", cpinfo.CodePageName ); 14116 return; 14117 } 14118 14119 dbch[0] = dbch[1] = 0; 14120 wch = 0; 14121 bad_wch = cpinfo.UnicodeDefaultChar; 14122 for (i = 0; !wch && i < MAX_LEADBYTES && cpinfo.LeadByte[i]; i += 2) 14123 for (j = cpinfo.LeadByte[i]; !wch && j <= cpinfo.LeadByte[i+1]; j++) 14124 for (k = 128; k <= 255; k++) 14125 { 14126 char str[2]; 14127 WCHAR wstr[2]; 14128 str[0] = j; 14129 str[1] = k; 14130 if (MultiByteToWideChar( cp, 0, str, 2, wstr, 2 ) == 1 && 14131 WideCharToMultiByte( cp, 0, wstr, 1, str, 2, NULL, NULL ) == 2 && 14132 (BYTE)str[0] == j && (BYTE)str[1] == k && 14133 HIBYTE(wstr[0]) && HIBYTE(wstr[0]) != 0xff) 14134 { 14135 dbch[0] = j; 14136 dbch[1] = k; 14137 wch = wstr[0]; 14138 break; 14139 } 14140 } 14141 14142 if (!wch) 14143 { 14144 skip( "Skipping DBCS WM_CHAR test, no appropriate char found\n" ); 14145 return; 14146 } 14147 trace( "using dbcs char %02x,%02x wchar %04x bad wchar %04x codepage '%s'\n", 14148 dbch[0], dbch[1], wch, bad_wch, cpinfo.CodePageName ); 14149 14150 hwnd = CreateWindowExW(0, testWindowClassW, NULL, 14151 WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, 0, 0, 0, NULL); 14152 hwnd2 = CreateWindowExW(0, testWindowClassW, NULL, 14153 WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, 0, 0, 0, NULL); 14154 ok (hwnd != 0, "Failed to create overlapped window\n"); 14155 ok (hwnd2 != 0, "Failed to create overlapped window\n"); 14156 flush_sequence(); 14157 14158 memset( wmCharSeq, 0, sizeof(wmCharSeq) ); 14159 wmCharSeq[0].message = WM_CHAR; 14160 wmCharSeq[0].flags = sent|wparam; 14161 wmCharSeq[0].wParam = wch; 14162 14163 /* posted message */ 14164 PostMessageA( hwnd, WM_CHAR, dbch[0], 0 ); 14165 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14166 ok( !ret, "got message %x\n", msg.message ); 14167 PostMessageA( hwnd, WM_CHAR, dbch[1], 0 ); 14168 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14169 ok( ret, "no message\n" ); 14170 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14171 ok( msg.wParam == wch, "bad wparam %lx/%x\n", msg.wParam, wch ); 14172 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14173 ok( !ret, "got message %x\n", msg.message ); 14174 14175 /* posted thread message */ 14176 PostThreadMessageA( GetCurrentThreadId(), WM_CHAR, dbch[0], 0 ); 14177 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14178 ok( !ret, "got message %x\n", msg.message ); 14179 PostMessageA( hwnd, WM_CHAR, dbch[1], 0 ); 14180 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14181 ok( ret, "no message\n" ); 14182 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14183 ok( msg.wParam == wch, "bad wparam %lx/%x\n", msg.wParam, wch ); 14184 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14185 ok( !ret, "got message %x\n", msg.message ); 14186 14187 /* sent message */ 14188 flush_sequence(); 14189 SendMessageA( hwnd, WM_CHAR, dbch[0], 0 ); 14190 ok_sequence( WmEmptySeq, "no messages", FALSE ); 14191 SendMessageA( hwnd, WM_CHAR, dbch[1], 0 ); 14192 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14193 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14194 ok( !ret, "got message %x\n", msg.message ); 14195 14196 /* sent message with timeout */ 14197 flush_sequence(); 14198 SendMessageTimeoutA( hwnd, WM_CHAR, dbch[0], 0, SMTO_NORMAL, 0, &res ); 14199 ok_sequence( WmEmptySeq, "no messages", FALSE ); 14200 SendMessageTimeoutA( hwnd, WM_CHAR, dbch[1], 0, SMTO_NORMAL, 0, &res ); 14201 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14202 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14203 ok( !ret, "got message %x\n", msg.message ); 14204 14205 /* sent message with timeout and callback */ 14206 flush_sequence(); 14207 SendMessageTimeoutA( hwnd, WM_CHAR, dbch[0], 0, SMTO_NORMAL, 0, &res ); 14208 ok_sequence( WmEmptySeq, "no messages", FALSE ); 14209 SendMessageCallbackA( hwnd, WM_CHAR, dbch[1], 0, NULL, 0 ); 14210 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14211 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14212 ok( !ret, "got message %x\n", msg.message ); 14213 14214 /* sent message with callback */ 14215 flush_sequence(); 14216 SendNotifyMessageA( hwnd, WM_CHAR, dbch[0], 0 ); 14217 ok_sequence( WmEmptySeq, "no messages", FALSE ); 14218 SendMessageCallbackA( hwnd, WM_CHAR, dbch[1], 0, NULL, 0 ); 14219 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14220 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14221 ok( !ret, "got message %x\n", msg.message ); 14222 14223 /* direct window proc call */ 14224 flush_sequence(); 14225 CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ), hwnd, WM_CHAR, dbch[0], 0 ); 14226 ok_sequence( WmEmptySeq, "no messages", FALSE ); 14227 CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ), hwnd, WM_CHAR, dbch[1], 0 ); 14228 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14229 14230 /* dispatch message */ 14231 msg.hwnd = hwnd; 14232 msg.message = WM_CHAR; 14233 msg.wParam = dbch[0]; 14234 msg.lParam = 0; 14235 DispatchMessageA( &msg ); 14236 ok_sequence( WmEmptySeq, "no messages", FALSE ); 14237 msg.wParam = dbch[1]; 14238 DispatchMessageA( &msg ); 14239 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14240 14241 /* window handle is irrelevant */ 14242 flush_sequence(); 14243 SendMessageA( hwnd2, WM_CHAR, dbch[0], 0 ); 14244 ok_sequence( WmEmptySeq, "no messages", FALSE ); 14245 SendMessageA( hwnd, WM_CHAR, dbch[1], 0 ); 14246 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14247 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14248 ok( !ret, "got message %x\n", msg.message ); 14249 14250 /* interleaved post and send */ 14251 flush_sequence(); 14252 PostMessageA( hwnd2, WM_CHAR, dbch[0], 0 ); 14253 SendMessageA( hwnd2, WM_CHAR, dbch[0], 0 ); 14254 ok_sequence( WmEmptySeq, "no messages", FALSE ); 14255 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14256 ok( !ret, "got message %x\n", msg.message ); 14257 PostMessageA( hwnd, WM_CHAR, dbch[1], 0 ); 14258 ok_sequence( WmEmptySeq, "no messages", FALSE ); 14259 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14260 ok( ret, "no message\n" ); 14261 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14262 ok( msg.wParam == wch, "bad wparam %lx/%x\n", msg.wParam, wch ); 14263 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14264 ok( !ret, "got message %x\n", msg.message ); 14265 SendMessageA( hwnd, WM_CHAR, dbch[1], 0 ); 14266 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14267 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14268 ok( !ret, "got message %x\n", msg.message ); 14269 14270 /* interleaved sent message and winproc */ 14271 flush_sequence(); 14272 SendMessageA( hwnd, WM_CHAR, dbch[0], 0 ); 14273 CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ), hwnd, WM_CHAR, dbch[0], 0 ); 14274 ok_sequence( WmEmptySeq, "no messages", FALSE ); 14275 SendMessageA( hwnd, WM_CHAR, dbch[1], 0 ); 14276 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14277 CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ), hwnd, WM_CHAR, dbch[1], 0 ); 14278 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14279 14280 /* interleaved winproc and dispatch */ 14281 msg.hwnd = hwnd; 14282 msg.message = WM_CHAR; 14283 msg.wParam = dbch[0]; 14284 msg.lParam = 0; 14285 CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ), hwnd, WM_CHAR, dbch[0], 0 ); 14286 DispatchMessageA( &msg ); 14287 ok_sequence( WmEmptySeq, "no messages", FALSE ); 14288 msg.wParam = dbch[1]; 14289 DispatchMessageA( &msg ); 14290 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14291 CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ), hwnd, WM_CHAR, dbch[1], 0 ); 14292 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14293 14294 /* interleaved sends */ 14295 flush_sequence(); 14296 SendMessageA( hwnd, WM_CHAR, dbch[0], 0 ); 14297 SendMessageCallbackA( hwnd, WM_CHAR, dbch[0], 0, NULL, 0 ); 14298 ok_sequence( WmEmptySeq, "no messages", FALSE ); 14299 SendMessageTimeoutA( hwnd, WM_CHAR, dbch[1], 0, SMTO_NORMAL, 0, &res ); 14300 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14301 SendMessageA( hwnd, WM_CHAR, dbch[1], 0 ); 14302 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14303 14304 /* dbcs WM_CHAR */ 14305 flush_sequence(); 14306 SendMessageA( hwnd2, WM_CHAR, (dbch[1] << 8) | dbch[0], 0 ); 14307 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14308 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14309 ok( !ret, "got message %x\n", msg.message ); 14310 14311 /* other char messages are not magic */ 14312 PostMessageA( hwnd, WM_SYSCHAR, dbch[0], 0 ); 14313 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14314 ok( ret, "no message\n" ); 14315 ok( msg.message == WM_SYSCHAR, "unexpected message %x\n", msg.message ); 14316 ok( msg.wParam == bad_wch, "bad wparam %lx/%x\n", msg.wParam, bad_wch ); 14317 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14318 ok( !ret, "got message %x\n", msg.message ); 14319 PostMessageA( hwnd, WM_DEADCHAR, dbch[0], 0 ); 14320 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14321 ok( ret, "no message\n" ); 14322 ok( msg.message == WM_DEADCHAR, "unexpected message %x\n", msg.message ); 14323 ok( msg.wParam == bad_wch, "bad wparam %lx/%x\n", msg.wParam, bad_wch ); 14324 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14325 ok( !ret, "got message %x\n", msg.message ); 14326 14327 /* test retrieving messages */ 14328 14329 PostMessageW( hwnd, WM_CHAR, wch, 0 ); 14330 ret = PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ); 14331 ok( ret, "no message\n" ); 14332 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14333 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14334 ok( msg.wParam == dbch[0], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); 14335 ret = PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ); 14336 ok( ret, "no message\n" ); 14337 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14338 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14339 ok( msg.wParam == dbch[1], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); 14340 ret = PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ); 14341 ok( !ret, "got message %x\n", msg.message ); 14342 14343 /* message filters */ 14344 PostMessageW( hwnd, WM_CHAR, wch, 0 ); 14345 ret = PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ); 14346 ok( ret, "no message\n" ); 14347 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14348 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14349 ok( msg.wParam == dbch[0], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); 14350 /* message id is filtered, hwnd is not */ 14351 ret = PeekMessageA( &msg, hwnd, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ); 14352 ok( !ret, "no message\n" ); 14353 ret = PeekMessageA( &msg, hwnd2, 0, 0, PM_REMOVE ); 14354 ok( ret, "no message\n" ); 14355 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14356 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14357 ok( msg.wParam == dbch[1], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); 14358 ret = PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ); 14359 ok( !ret, "got message %x\n", msg.message ); 14360 14361 /* mixing GetMessage and PostMessage */ 14362 PostMessageW( hwnd, WM_CHAR, wch, 0xbeef ); 14363 ok( GetMessageA( &msg, hwnd, 0, 0 ), "no message\n" ); 14364 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14365 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14366 ok( msg.wParam == dbch[0], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); 14367 ok( msg.lParam == 0xbeef, "bad lparam %lx\n", msg.lParam ); 14368 time = msg.time; 14369 pt = msg.pt; 14370 ok( time - GetTickCount() <= 100, "bad time %x\n", msg.time ); 14371 ret = PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ); 14372 ok( ret, "no message\n" ); 14373 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14374 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14375 ok( msg.wParam == dbch[1], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); 14376 ok( msg.lParam == 0xbeef, "bad lparam %lx\n", msg.lParam ); 14377 ok( msg.time == time, "bad time %x/%x\n", msg.time, time ); 14378 ok( msg.pt.x == pt.x && msg.pt.y == pt.y, "bad point %u,%u/%u,%u\n", msg.pt.x, msg.pt.y, pt.x, pt.y ); 14379 ret = PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ); 14380 ok( !ret, "got message %x\n", msg.message ); 14381 14382 /* without PM_REMOVE */ 14383 PostMessageW( hwnd, WM_CHAR, wch, 0 ); 14384 ret = PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ); 14385 ok( ret, "no message\n" ); 14386 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14387 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14388 ok( msg.wParam == dbch[0], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); 14389 ret = PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ); 14390 ok( ret, "no message\n" ); 14391 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14392 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14393 ok( msg.wParam == dbch[0], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); 14394 ret = PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ); 14395 ok( ret, "no message\n" ); 14396 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14397 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14398 ok( msg.wParam == dbch[1], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); 14399 ret = PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ); 14400 ok( ret, "no message\n" ); 14401 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14402 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14403 ok( msg.wParam == dbch[1], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); 14404 ret = PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ); 14405 ok( !ret, "got message %x\n", msg.message ); 14406 14407 DestroyWindow(hwnd); 14408 DestroyWindow(hwnd2); 14409 } 14410 14411 static void test_unicode_wm_char(void) 14412 { 14413 HWND hwnd; 14414 MSG msg; 14415 struct message seq[2]; 14416 HKL hkl_orig, hkl_greek; 14417 DWORD cp; 14418 LCID thread_locale; 14419 14420 hkl_orig = GetKeyboardLayout( 0 ); 14421 GetLocaleInfoW( LOWORD( hkl_orig ), LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER, (WCHAR*)&cp, sizeof(cp) / sizeof(WCHAR) ); 14422 if (cp != 1252) 14423 { 14424 skip( "Default codepage %d\n", cp ); 14425 return; 14426 } 14427 14428 hkl_greek = LoadKeyboardLayoutA( "00000408", 0 ); 14429 if (!hkl_greek || hkl_greek == hkl_orig /* win2k */) 14430 { 14431 skip( "Unable to load Greek keyboard layout\n" ); 14432 return; 14433 } 14434 14435 hwnd = CreateWindowExW( 0, testWindowClassW, NULL, WS_OVERLAPPEDWINDOW, 14436 100, 100, 200, 200, 0, 0, 0, NULL ); 14437 flush_sequence(); 14438 14439 PostMessageW( hwnd, WM_CHAR, 0x3b1, 0 ); 14440 14441 while (GetMessageW( &msg, hwnd, 0, 0 )) 14442 { 14443 if (!ignore_message( msg.message )) break; 14444 } 14445 14446 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14447 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14448 ok( msg.wParam == 0x3b1, "bad wparam %lx\n", msg.wParam ); 14449 ok( msg.lParam == 0, "bad lparam %lx\n", msg.lParam ); 14450 14451 DispatchMessageW( &msg ); 14452 14453 memset( seq, 0, sizeof(seq) ); 14454 seq[0].message = WM_CHAR; 14455 seq[0].flags = sent|wparam; 14456 seq[0].wParam = 0x3b1; 14457 14458 ok_sequence( seq, "unicode WM_CHAR", FALSE ); 14459 14460 flush_sequence(); 14461 14462 /* greek alpha -> 'a' in cp1252 */ 14463 PostMessageW( hwnd, WM_CHAR, 0x3b1, 0 ); 14464 14465 ok( GetMessageA( &msg, hwnd, 0, 0 ), "no message\n" ); 14466 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14467 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14468 ok( msg.wParam == 0x61, "bad wparam %lx\n", msg.wParam ); 14469 ok( msg.lParam == 0, "bad lparam %lx\n", msg.lParam ); 14470 14471 DispatchMessageA( &msg ); 14472 14473 seq[0].wParam = 0x61; 14474 ok_sequence( seq, "unicode WM_CHAR", FALSE ); 14475 14476 thread_locale = GetThreadLocale(); 14477 ActivateKeyboardLayout( hkl_greek, 0 ); 14478 ok( GetThreadLocale() == thread_locale, "locale changed from %08x to %08x\n", 14479 thread_locale, GetThreadLocale() ); 14480 14481 flush_sequence(); 14482 14483 /* greek alpha -> 0xe1 in cp1253 */ 14484 PostMessageW( hwnd, WM_CHAR, 0x3b1, 0 ); 14485 14486 ok( GetMessageA( &msg, hwnd, 0, 0 ), "no message\n" ); 14487 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14488 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14489 ok( msg.wParam == 0xe1, "bad wparam %lx\n", msg.wParam ); 14490 ok( msg.lParam == 0, "bad lparam %lx\n", msg.lParam ); 14491 14492 DispatchMessageA( &msg ); 14493 14494 seq[0].wParam = 0x3b1; 14495 ok_sequence( seq, "unicode WM_CHAR", FALSE ); 14496 14497 DestroyWindow( hwnd ); 14498 ActivateKeyboardLayout( hkl_orig, 0 ); 14499 UnloadKeyboardLayout( hkl_greek ); 14500 } 14501 14502 #define ID_LISTBOX 0x000f 14503 14504 static const struct message wm_lb_setcursel_0[] = 14505 { 14506 { LB_SETCURSEL, sent|wparam|lparam, 0, 0 }, 14507 { WM_CTLCOLORLISTBOX, sent|parent }, 14508 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000120f2 }, 14509 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 1 }, 14510 { EVENT_OBJECT_SELECTION, winevent_hook|wparam|lparam, OBJID_CLIENT, 1 }, 14511 { 0 } 14512 }; 14513 static const struct message wm_lb_setcursel_1[] = 14514 { 14515 { LB_SETCURSEL, sent|wparam|lparam, 1, 0 }, 14516 { WM_CTLCOLORLISTBOX, sent|parent }, 14517 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000020f2 }, 14518 { WM_CTLCOLORLISTBOX, sent|parent }, 14519 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000121f2 }, 14520 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 2 }, 14521 { EVENT_OBJECT_SELECTION, winevent_hook|wparam|lparam, OBJID_CLIENT, 2 }, 14522 { 0 } 14523 }; 14524 static const struct message wm_lb_setcursel_2[] = 14525 { 14526 { LB_SETCURSEL, sent|wparam|lparam, 2, 0 }, 14527 { WM_CTLCOLORLISTBOX, sent|parent }, 14528 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000021f2 }, 14529 { WM_CTLCOLORLISTBOX, sent|parent }, 14530 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000122f2 }, 14531 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 3 }, 14532 { EVENT_OBJECT_SELECTION, winevent_hook|wparam|lparam, OBJID_CLIENT, 3 }, 14533 { 0 } 14534 }; 14535 static const struct message wm_lb_click_0[] = 14536 { 14537 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, MAKELPARAM(1,1) }, 14538 { HCBT_SETFOCUS, hook }, 14539 { WM_KILLFOCUS, sent|parent }, 14540 { WM_IME_SETCONTEXT, sent|wparam|optional|parent, 0 }, 14541 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 14542 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 14543 { WM_SETFOCUS, sent|defwinproc }, 14544 14545 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x001142f2 }, 14546 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_LISTBOX, LBN_SETFOCUS) }, 14547 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 3 }, 14548 { WM_LBTRACKPOINT, sent|wparam|lparam|parent, 0, MAKELPARAM(1,1) }, 14549 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, 14550 14551 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000142f2 }, 14552 { WM_CTLCOLORLISTBOX, sent|parent }, 14553 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000022f2 }, 14554 { WM_CTLCOLORLISTBOX, sent|parent }, 14555 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000120f2 }, 14556 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x001140f2 }, 14557 14558 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 1 }, 14559 { EVENT_OBJECT_SELECTION, winevent_hook|wparam|lparam, OBJID_CLIENT, 1 }, 14560 14561 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 }, 14562 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, 14563 { WM_CAPTURECHANGED, sent|wparam|lparam|defwinproc, 0, 0 }, 14564 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_LISTBOX, LBN_SELCHANGE) }, 14565 { 0 } 14566 }; 14567 static const struct message wm_lb_deletestring[] = 14568 { 14569 { LB_DELETESTRING, sent|wparam|lparam, 0, 0 }, 14570 { WM_DELETEITEM, sent|wparam|parent|optional, ID_LISTBOX, 0 }, 14571 { WM_DRAWITEM, sent|wparam|parent|optional, ID_LISTBOX }, 14572 { WM_DRAWITEM, sent|wparam|parent|optional, ID_LISTBOX }, 14573 { 0 } 14574 }; 14575 static const struct message wm_lb_deletestring_reset[] = 14576 { 14577 { LB_DELETESTRING, sent|wparam|lparam, 0, 0 }, 14578 { LB_RESETCONTENT, sent|wparam|lparam|defwinproc|optional, 0, 0 }, 14579 { WM_DELETEITEM, sent|wparam|parent|optional, ID_LISTBOX, 0 }, 14580 { WM_DRAWITEM, sent|wparam|parent|optional, ID_LISTBOX }, 14581 { WM_DRAWITEM, sent|wparam|parent|optional, ID_LISTBOX }, 14582 { 0 } 14583 }; 14584 static const struct message wm_lb_addstring[] = 14585 { 14586 { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ef }, 14587 { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ed }, 14588 { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ee }, 14589 { 0 } 14590 }; 14591 static const struct message wm_lb_addstring_ownerdraw[] = 14592 { 14593 { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ed }, 14594 { WM_MEASUREITEM, sent|wparam|lparam|parent, 0xf0f2, 0xf30604ed }, 14595 { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ee }, 14596 { WM_MEASUREITEM, sent|wparam|lparam|parent, 0xf1f2, 0xf30604ee }, 14597 { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ef }, 14598 { WM_MEASUREITEM, sent|wparam|lparam|parent, 0xf2f2, 0xf30604ef }, 14599 { 0 } 14600 }; 14601 static const struct message wm_lb_addstring_sort_ownerdraw[] = 14602 { 14603 { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ed }, 14604 { WM_MEASUREITEM, sent|wparam|lparam|parent, 0xf0f2, 0xf30604ed }, 14605 { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ee }, 14606 { WM_COMPAREITEM, sent|wparam|lparam|parent, 0xf30604ed, 0xf30604ee }, 14607 { WM_MEASUREITEM, sent|wparam|lparam|parent, 0xf1f2, 0xf30604ee }, 14608 { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ef }, 14609 { WM_COMPAREITEM, sent|wparam|lparam|parent, 0xf30604ed, 0xf30604ef }, 14610 { WM_COMPAREITEM, sent|wparam|lparam|parent, 0xf30604ee, 0xf30604ef }, 14611 { WM_MEASUREITEM, sent|wparam|lparam|parent, 0xf2f2, 0xf30604ef }, 14612 { 0 } 14613 }; 14614 14615 #define check_lb_state(a1, a2, a3, a4, a5) check_lb_state_dbg(a1, a2, a3, a4, a5, __LINE__) 14616 14617 static LRESULT (WINAPI *listbox_orig_proc)(HWND, UINT, WPARAM, LPARAM); 14618 14619 static LRESULT WINAPI listbox_hook_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) 14620 { 14621 static LONG defwndproc_counter = 0; 14622 LRESULT ret; 14623 struct recvd_message msg; 14624 14625 /* do not log painting messages */ 14626 if (message != WM_PAINT && 14627 message != WM_NCPAINT && 14628 message != WM_SYNCPAINT && 14629 message != WM_ERASEBKGND && 14630 message != WM_NCHITTEST && 14631 message != WM_GETTEXT && 14632 !ignore_message( message )) 14633 { 14634 msg.hwnd = hwnd; 14635 msg.message = message; 14636 msg.flags = sent|wparam|lparam; 14637 if (defwndproc_counter) msg.flags |= defwinproc; 14638 msg.wParam = wp; 14639 if (message == LB_ADDSTRING) 14640 msg.lParam = lp ? hash_Ly((const char *)lp) : 0; 14641 else 14642 msg.lParam = lp; 14643 msg.descr = "listbox"; 14644 add_message(&msg); 14645 } 14646 14647 defwndproc_counter++; 14648 ret = CallWindowProcA(listbox_orig_proc, hwnd, message, wp, lp); 14649 defwndproc_counter--; 14650 14651 return ret; 14652 } 14653 14654 static void check_lb_state_dbg(HWND listbox, int count, int cur_sel, 14655 int caret_index, int top_index, int line) 14656 { 14657 LRESULT ret; 14658 14659 /* calling an orig proc helps to avoid unnecessary message logging */ 14660 ret = CallWindowProcA(listbox_orig_proc, listbox, LB_GETCOUNT, 0, 0); 14661 ok_(__FILE__, line)(ret == count, "expected count %d, got %ld\n", count, ret); 14662 ret = CallWindowProcA(listbox_orig_proc, listbox, LB_GETCURSEL, 0, 0); 14663 ok_(__FILE__, line)(ret == cur_sel, "expected cur sel %d, got %ld\n", cur_sel, ret); 14664 ret = CallWindowProcA(listbox_orig_proc, listbox, LB_GETCARETINDEX, 0, 0); 14665 ok_(__FILE__, line)(ret == caret_index || 14666 broken(cur_sel == -1 && caret_index == 0 && ret == -1), /* nt4 */ 14667 "expected caret index %d, got %ld\n", caret_index, ret); 14668 ret = CallWindowProcA(listbox_orig_proc, listbox, LB_GETTOPINDEX, 0, 0); 14669 ok_(__FILE__, line)(ret == top_index, "expected top index %d, got %ld\n", top_index, ret); 14670 } 14671 14672 static void test_listbox_messages(void) 14673 { 14674 HWND parent, listbox; 14675 LRESULT ret; 14676 14677 parent = CreateWindowExA(0, "TestParentClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 14678 100, 100, 200, 200, 0, 0, 0, NULL); 14679 /* with LBS_HASSTRINGS */ 14680 listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, "ListBox", NULL, 14681 WS_CHILD | LBS_NOTIFY | LBS_OWNERDRAWVARIABLE | LBS_HASSTRINGS | WS_VISIBLE, 14682 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL); 14683 listbox_orig_proc = (WNDPROC)SetWindowLongPtrA(listbox, GWLP_WNDPROC, (ULONG_PTR)listbox_hook_proc); 14684 14685 check_lb_state(listbox, 0, LB_ERR, 0, 0); 14686 14687 flush_sequence(); 14688 14689 log_all_parent_messages++; 14690 14691 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0"); 14692 ok(ret == 0, "expected 0, got %ld\n", ret); 14693 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1"); 14694 ok(ret == 1, "expected 1, got %ld\n", ret); 14695 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2"); 14696 ok(ret == 2, "expected 2, got %ld\n", ret); 14697 14698 ok_sequence(wm_lb_addstring_ownerdraw, "LB_ADDSTRING", FALSE); 14699 check_lb_state(listbox, 3, LB_ERR, 0, 0); 14700 14701 flush_sequence(); 14702 14703 trace("selecting item 0\n"); 14704 ret = SendMessageA(listbox, LB_SETCURSEL, 0, 0); 14705 ok(ret == 0, "expected 0, got %ld\n", ret); 14706 ok_sequence(wm_lb_setcursel_0, "LB_SETCURSEL 0", FALSE ); 14707 check_lb_state(listbox, 3, 0, 0, 0); 14708 flush_sequence(); 14709 14710 trace("selecting item 1\n"); 14711 ret = SendMessageA(listbox, LB_SETCURSEL, 1, 0); 14712 ok(ret == 1, "expected 1, got %ld\n", ret); 14713 ok_sequence(wm_lb_setcursel_1, "LB_SETCURSEL 1", FALSE ); 14714 check_lb_state(listbox, 3, 1, 1, 0); 14715 14716 trace("selecting item 2\n"); 14717 ret = SendMessageA(listbox, LB_SETCURSEL, 2, 0); 14718 ok(ret == 2, "expected 2, got %ld\n", ret); 14719 ok_sequence(wm_lb_setcursel_2, "LB_SETCURSEL 2", FALSE ); 14720 check_lb_state(listbox, 3, 2, 2, 0); 14721 14722 trace("clicking on item 0\n"); 14723 ret = SendMessageA(listbox, WM_LBUTTONDOWN, 0, MAKELPARAM(1, 1)); 14724 ok(ret == LB_OKAY, "expected LB_OKAY, got %ld\n", ret); 14725 ret = SendMessageA(listbox, WM_LBUTTONUP, 0, 0); 14726 ok(ret == LB_OKAY, "expected LB_OKAY, got %ld\n", ret); 14727 ok_sequence(wm_lb_click_0, "WM_LBUTTONDOWN 0", FALSE ); 14728 check_lb_state(listbox, 3, 0, 0, 0); 14729 flush_sequence(); 14730 14731 trace("deleting item 0\n"); 14732 ret = SendMessageA(listbox, LB_DELETESTRING, 0, 0); 14733 ok(ret == 2, "expected 2, got %ld\n", ret); 14734 ok_sequence(wm_lb_deletestring, "LB_DELETESTRING 0", FALSE ); 14735 check_lb_state(listbox, 2, -1, 0, 0); 14736 flush_sequence(); 14737 14738 trace("deleting item 0\n"); 14739 ret = SendMessageA(listbox, LB_DELETESTRING, 0, 0); 14740 ok(ret == 1, "expected 1, got %ld\n", ret); 14741 ok_sequence(wm_lb_deletestring, "LB_DELETESTRING 0", FALSE ); 14742 check_lb_state(listbox, 1, -1, 0, 0); 14743 flush_sequence(); 14744 14745 trace("deleting item 0\n"); 14746 ret = SendMessageA(listbox, LB_DELETESTRING, 0, 0); 14747 ok(ret == 0, "expected 0, got %ld\n", ret); 14748 ok_sequence(wm_lb_deletestring_reset, "LB_DELETESTRING 0", FALSE ); 14749 check_lb_state(listbox, 0, -1, 0, 0); 14750 flush_sequence(); 14751 14752 trace("deleting item 0\n"); 14753 ret = SendMessageA(listbox, LB_DELETESTRING, 0, 0); 14754 ok(ret == LB_ERR, "expected LB_ERR, got %ld\n", ret); 14755 check_lb_state(listbox, 0, -1, 0, 0); 14756 flush_sequence(); 14757 14758 log_all_parent_messages--; 14759 14760 DestroyWindow(listbox); 14761 14762 /* with LBS_SORT and without LBS_HASSTRINGS */ 14763 listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, "ListBox", NULL, 14764 WS_CHILD | LBS_NOTIFY | LBS_OWNERDRAWVARIABLE | LBS_SORT | WS_VISIBLE, 14765 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL); 14766 listbox_orig_proc = (WNDPROC)SetWindowLongPtrA(listbox, GWLP_WNDPROC, (ULONG_PTR)listbox_hook_proc); 14767 14768 check_lb_state(listbox, 0, LB_ERR, 0, 0); 14769 14770 flush_sequence(); 14771 14772 log_all_parent_messages++; 14773 14774 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0"); 14775 ok(ret == 0, "expected 0, got %ld\n", ret); 14776 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1"); 14777 ok(ret == 1, "expected 1, got %ld\n", ret); 14778 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2"); 14779 ok(ret == 2, "expected 2, got %ld\n", ret); 14780 14781 ok_sequence(wm_lb_addstring_sort_ownerdraw, "LB_ADDSTRING", FALSE); 14782 check_lb_state(listbox, 3, LB_ERR, 0, 0); 14783 14784 log_all_parent_messages--; 14785 14786 DestroyWindow(listbox); 14787 14788 /* with LBS_HASSTRINGS */ 14789 listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, "ListBox", NULL, 14790 WS_CHILD | LBS_NOTIFY | LBS_HASSTRINGS | WS_VISIBLE, 14791 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL); 14792 listbox_orig_proc = (WNDPROC)SetWindowLongPtrA(listbox, GWLP_WNDPROC, (ULONG_PTR)listbox_hook_proc); 14793 14794 check_lb_state(listbox, 0, LB_ERR, 0, 0); 14795 14796 flush_sequence(); 14797 14798 log_all_parent_messages++; 14799 14800 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2"); 14801 ok(ret == 0, "expected 0, got %ld\n", ret); 14802 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0"); 14803 ok(ret == 1, "expected 1, got %ld\n", ret); 14804 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1"); 14805 ok(ret == 2, "expected 2, got %ld\n", ret); 14806 14807 ok_sequence(wm_lb_addstring, "LB_ADDSTRING", FALSE); 14808 check_lb_state(listbox, 3, LB_ERR, 0, 0); 14809 14810 log_all_parent_messages--; 14811 14812 DestroyWindow(listbox); 14813 14814 /* with LBS_HASSTRINGS and LBS_SORT */ 14815 listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, "ListBox", NULL, 14816 WS_CHILD | LBS_NOTIFY | LBS_HASSTRINGS | LBS_SORT | WS_VISIBLE, 14817 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL); 14818 listbox_orig_proc = (WNDPROC)SetWindowLongPtrA(listbox, GWLP_WNDPROC, (ULONG_PTR)listbox_hook_proc); 14819 14820 check_lb_state(listbox, 0, LB_ERR, 0, 0); 14821 14822 flush_sequence(); 14823 14824 log_all_parent_messages++; 14825 14826 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2"); 14827 ok(ret == 0, "expected 0, got %ld\n", ret); 14828 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0"); 14829 ok(ret == 0, "expected 0, got %ld\n", ret); 14830 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1"); 14831 ok(ret == 1, "expected 1, got %ld\n", ret); 14832 14833 ok_sequence(wm_lb_addstring, "LB_ADDSTRING", FALSE); 14834 check_lb_state(listbox, 3, LB_ERR, 0, 0); 14835 14836 log_all_parent_messages--; 14837 14838 DestroyWindow(listbox); 14839 DestroyWindow(parent); 14840 } 14841 14842 /*************************** Menu test ******************************/ 14843 static const struct message wm_popup_menu_1[] = 14844 { 14845 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, 14846 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, 14847 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'E', 0x20000001 }, 14848 { WM_SYSKEYDOWN, sent|wparam|lparam, 'E', 0x20000001 }, 14849 { WM_SYSCHAR, sent|wparam|lparam, 'e', 0x20000001 }, 14850 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_KEYMENU, 'e' }, 14851 { WM_ENTERMENULOOP, sent|wparam|lparam, 0, 0 }, 14852 { WM_INITMENU, sent|lparam, 0, 0 }, 14853 { WM_MENUSELECT, sent|wparam, MAKEWPARAM(1,MF_HILITE|MF_POPUP) }, 14854 { WM_INITMENUPOPUP, sent|lparam, 0, 1 }, 14855 { HCBT_CREATEWND, hook|optional }, /* Win9x doesn't create a window */ 14856 { WM_MENUSELECT, sent|wparam, MAKEWPARAM(200,MF_HILITE) }, 14857 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'E', 0xf0000001 }, 14858 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xd0000001 }, 14859 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RETURN, 0x10000001, 0, 0x40000000 }, 14860 { HCBT_DESTROYWND, hook|optional }, /* Win9x doesn't create a window */ 14861 { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, 14862 { WM_MENUSELECT, sent|wparam|lparam, MAKEWPARAM(0,0xffff), 0 }, 14863 { WM_EXITMENULOOP, sent|wparam|lparam, 0, 0 }, 14864 { WM_MENUCOMMAND, sent }, /* |wparam, 200 - Win9x */ 14865 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RETURN, 0xc0000001 }, 14866 { WM_KEYUP, sent|wparam|lparam, VK_RETURN, 0xc0000001 }, 14867 { 0 } 14868 }; 14869 static const struct message wm_popup_menu_2[] = 14870 { 14871 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, 14872 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, 14873 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'F', 0x20000001 }, 14874 { WM_SYSKEYDOWN, sent|wparam|lparam, 'F', 0x20000001 }, 14875 { WM_SYSCHAR, sent|wparam|lparam, 'f', 0x20000001 }, 14876 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_KEYMENU, 'f' }, 14877 { WM_ENTERMENULOOP, sent|wparam|lparam, 0, 0 }, 14878 { WM_INITMENU, sent|lparam, 0, 0 }, 14879 { WM_MENUSELECT, sent|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) }, 14880 { WM_INITMENUPOPUP, sent|lparam, 0, 0 }, 14881 { WM_MENUSELECT, sent|wparam|optional, MAKEWPARAM(0,MF_HILITE|MF_POPUP) }, /* Win9x */ 14882 { WM_INITMENUPOPUP, sent|lparam|optional, 0, 0 }, /* Win9x */ 14883 { HCBT_CREATEWND, hook }, 14884 { WM_MENUSELECT, sent }, /*|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) - XP 14885 |wparam, MAKEWPARAM(100,MF_HILITE) - Win9x */ 14886 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'F', 0xf0000001 }, 14887 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xd0000001 }, 14888 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RIGHT, 0x10000001 }, 14889 { WM_INITMENUPOPUP, sent|lparam|optional, 0, 0 }, /* Win9x doesn't send it */ 14890 { HCBT_CREATEWND, hook|optional }, /* Win9x doesn't send it */ 14891 { WM_MENUSELECT, sent|wparam|optional, MAKEWPARAM(100,MF_HILITE) }, 14892 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RIGHT, 0xd0000001 }, 14893 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RETURN, 0x10000001 }, 14894 { HCBT_DESTROYWND, hook }, 14895 { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, 14896 { HCBT_DESTROYWND, hook|optional }, /* Win9x doesn't send it */ 14897 { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, 14898 { WM_MENUSELECT, sent|wparam|lparam, MAKEWPARAM(0,0xffff), 0 }, 14899 { WM_EXITMENULOOP, sent|wparam|lparam, 0, 0 }, 14900 { WM_MENUCOMMAND, sent }, /* |wparam, 100 - Win9x */ 14901 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RETURN, 0xc0000001 }, 14902 { WM_KEYUP, sent|wparam|lparam, VK_RETURN, 0xc0000001 }, 14903 { 0 } 14904 }; 14905 static const struct message wm_popup_menu_3[] = 14906 { 14907 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, 14908 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, 14909 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'F', 0x20000001 }, 14910 { WM_SYSKEYDOWN, sent|wparam|lparam, 'F', 0x20000001 }, 14911 { WM_SYSCHAR, sent|wparam|lparam, 'f', 0x20000001 }, 14912 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_KEYMENU, 'f' }, 14913 { WM_ENTERMENULOOP, sent|wparam|lparam, 0, 0 }, 14914 { WM_INITMENU, sent|lparam, 0, 0 }, 14915 { WM_MENUSELECT, sent|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) }, 14916 { WM_INITMENUPOPUP, sent|lparam, 0, 0 }, 14917 { WM_MENUSELECT, sent|wparam|optional, MAKEWPARAM(0,MF_HILITE|MF_POPUP) }, /* Win9x */ 14918 { WM_INITMENUPOPUP, sent|lparam|optional, 0, 0 }, /* Win9x */ 14919 { HCBT_CREATEWND, hook }, 14920 { WM_MENUSELECT, sent }, /*|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) - XP 14921 |wparam, MAKEWPARAM(100,MF_HILITE) - Win9x */ 14922 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'F', 0xf0000001 }, 14923 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xd0000001 }, 14924 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RIGHT, 0x10000001 }, 14925 { WM_INITMENUPOPUP, sent|lparam|optional, 0, 0 }, /* Win9x doesn't send it */ 14926 { HCBT_CREATEWND, hook|optional }, /* Win9x doesn't send it */ 14927 { WM_MENUSELECT, sent|wparam|optional, MAKEWPARAM(100,MF_HILITE) }, 14928 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RIGHT, 0xd0000001 }, 14929 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RETURN, 0x10000001 }, 14930 { HCBT_DESTROYWND, hook }, 14931 { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, 14932 { HCBT_DESTROYWND, hook|optional }, /* Win9x doesn't send it */ 14933 { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, 14934 { WM_MENUSELECT, sent|wparam|lparam, MAKEWPARAM(0,0xffff), 0 }, 14935 { WM_EXITMENULOOP, sent|wparam|lparam, 0, 0 }, 14936 { WM_COMMAND, sent|wparam|lparam, 100, 0 }, 14937 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RETURN, 0xc0000001 }, 14938 { WM_KEYUP, sent|wparam|lparam, VK_RETURN, 0xc0000001 }, 14939 { 0 } 14940 }; 14941 14942 static const struct message wm_single_menu_item[] = 14943 { 14944 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, 14945 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, 14946 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'Q', 0x20000001 }, 14947 { WM_SYSKEYDOWN, sent|wparam|lparam, 'Q', 0x20000001 }, 14948 { WM_SYSCHAR, sent|wparam|lparam, 'q', 0x20000001 }, 14949 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_KEYMENU, 'q' }, 14950 { WM_ENTERMENULOOP, sent|wparam|lparam, 0, 0 }, 14951 { WM_INITMENU, sent|lparam, 0, 0 }, 14952 { WM_MENUSELECT, sent|wparam|optional, MAKEWPARAM(300,MF_HILITE) }, 14953 { WM_MENUSELECT, sent|wparam|lparam, MAKEWPARAM(0,0xffff), 0 }, 14954 { WM_EXITMENULOOP, sent|wparam|lparam, 0, 0 }, 14955 { WM_MENUCOMMAND, sent }, 14956 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'Q', 0xe0000001 }, 14957 { WM_SYSKEYUP, sent|wparam|lparam, 'Q', 0xe0000001 }, 14958 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, 14959 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 }, 14960 14961 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_ESCAPE, 1 }, 14962 { WM_KEYDOWN, sent|wparam|lparam, VK_ESCAPE, 1 }, 14963 { WM_CHAR, sent|wparam|lparam, VK_ESCAPE, 0x00000001 }, 14964 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_ESCAPE, 0xc0000001 }, 14965 { WM_KEYUP, sent|wparam|lparam, VK_ESCAPE, 0xc0000001 }, 14966 { 0 } 14967 }; 14968 14969 static LRESULT WINAPI parent_menu_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) 14970 { 14971 if (message == WM_ENTERIDLE || 14972 message == WM_INITMENU || 14973 message == WM_INITMENUPOPUP || 14974 message == WM_MENUSELECT || 14975 message == WM_PARENTNOTIFY || 14976 message == WM_ENTERMENULOOP || 14977 message == WM_EXITMENULOOP || 14978 message == WM_UNINITMENUPOPUP || 14979 message == WM_KEYDOWN || 14980 message == WM_KEYUP || 14981 message == WM_CHAR || 14982 message == WM_SYSKEYDOWN || 14983 message == WM_SYSKEYUP || 14984 message == WM_SYSCHAR || 14985 message == WM_COMMAND || 14986 message == WM_MENUCOMMAND) 14987 { 14988 struct recvd_message msg; 14989 14990 msg.hwnd = hwnd; 14991 msg.message = message; 14992 msg.flags = sent|wparam|lparam; 14993 msg.wParam = wp; 14994 msg.lParam = lp; 14995 msg.descr = "parent_menu_proc"; 14996 add_message(&msg); 14997 } 14998 14999 return DefWindowProcA(hwnd, message, wp, lp); 15000 } 15001 15002 static void set_menu_style(HMENU hmenu, DWORD style) 15003 { 15004 MENUINFO mi; 15005 BOOL ret; 15006 15007 mi.cbSize = sizeof(mi); 15008 mi.fMask = MIM_STYLE; 15009 mi.dwStyle = style; 15010 SetLastError(0xdeadbeef); 15011 ret = pSetMenuInfo(hmenu, &mi); 15012 ok(ret, "SetMenuInfo error %u\n", GetLastError()); 15013 } 15014 15015 static DWORD get_menu_style(HMENU hmenu) 15016 { 15017 MENUINFO mi; 15018 BOOL ret; 15019 15020 mi.cbSize = sizeof(mi); 15021 mi.fMask = MIM_STYLE; 15022 mi.dwStyle = 0; 15023 SetLastError(0xdeadbeef); 15024 ret = pGetMenuInfo(hmenu, &mi); 15025 ok(ret, "GetMenuInfo error %u\n", GetLastError()); 15026 15027 return mi.dwStyle; 15028 } 15029 15030 static void test_menu_messages(void) 15031 { 15032 MSG msg; 15033 WNDCLASSA cls; 15034 HMENU hmenu, hmenu_popup; 15035 HWND hwnd; 15036 DWORD style; 15037 15038 if (!pGetMenuInfo || !pSetMenuInfo) 15039 { 15040 win_skip("GetMenuInfo and/or SetMenuInfo are not available\n"); 15041 return; 15042 } 15043 cls.style = 0; 15044 cls.lpfnWndProc = parent_menu_proc; 15045 cls.cbClsExtra = 0; 15046 cls.cbWndExtra = 0; 15047 cls.hInstance = GetModuleHandleA(0); 15048 cls.hIcon = 0; 15049 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 15050 cls.hbrBackground = GetStockObject(WHITE_BRUSH); 15051 cls.lpszMenuName = NULL; 15052 cls.lpszClassName = "TestMenuClass"; 15053 UnregisterClassA(cls.lpszClassName, cls.hInstance); 15054 if (!RegisterClassA(&cls)) assert(0); 15055 15056 SetLastError(0xdeadbeef); 15057 hwnd = CreateWindowExA(0, "TestMenuClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 15058 100, 100, 200, 200, 0, 0, 0, NULL); 15059 ok(hwnd != 0, "LoadMenuA error %u\n", GetLastError()); 15060 15061 SetLastError(0xdeadbeef); 15062 hmenu = LoadMenuA(GetModuleHandleA(NULL), MAKEINTRESOURCEA(1)); 15063 ok(hmenu != 0, "LoadMenuA error %u\n", GetLastError()); 15064 15065 SetMenu(hwnd, hmenu); 15066 SetForegroundWindow( hwnd ); 15067 flush_events(); 15068 15069 set_menu_style(hmenu, MNS_NOTIFYBYPOS); 15070 style = get_menu_style(hmenu); 15071 ok(style == MNS_NOTIFYBYPOS, "expected MNS_NOTIFYBYPOS, got %u\n", style); 15072 15073 hmenu_popup = GetSubMenu(hmenu, 0); 15074 ok(hmenu_popup != 0, "GetSubMenu returned 0 for submenu 0\n"); 15075 style = get_menu_style(hmenu_popup); 15076 ok(style == 0, "expected 0, got %u\n", style); 15077 15078 hmenu_popup = GetSubMenu(hmenu_popup, 0); 15079 ok(hmenu_popup != 0, "GetSubMenu returned 0 for submenu 0\n"); 15080 style = get_menu_style(hmenu_popup); 15081 ok(style == 0, "expected 0, got %u\n", style); 15082 15083 /* Alt+E, Enter */ 15084 trace("testing a popup menu command\n"); 15085 flush_sequence(); 15086 keybd_event(VK_MENU, 0, 0, 0); 15087 keybd_event('E', 0, 0, 0); 15088 keybd_event('E', 0, KEYEVENTF_KEYUP, 0); 15089 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); 15090 keybd_event(VK_RETURN, 0, 0, 0); 15091 keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0); 15092 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 15093 { 15094 TranslateMessage(&msg); 15095 DispatchMessageA(&msg); 15096 } 15097 if (!sequence_cnt) /* we didn't get any message */ 15098 { 15099 skip( "queuing key events not supported\n" ); 15100 goto done; 15101 } 15102 /* win98 queues only a WM_KEYUP and doesn't start menu tracking */ 15103 if (sequence[0].message == WM_KEYUP && sequence[0].wParam == VK_MENU) 15104 { 15105 win_skip( "menu tracking through VK_MENU not supported\n" ); 15106 goto done; 15107 } 15108 ok_sequence(wm_popup_menu_1, "popup menu command", FALSE); 15109 15110 /* Alt+F, Right, Enter */ 15111 trace("testing submenu of a popup menu command\n"); 15112 flush_sequence(); 15113 keybd_event(VK_MENU, 0, 0, 0); 15114 keybd_event('F', 0, 0, 0); 15115 keybd_event('F', 0, KEYEVENTF_KEYUP, 0); 15116 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); 15117 keybd_event(VK_RIGHT, 0, 0, 0); 15118 keybd_event(VK_RIGHT, 0, KEYEVENTF_KEYUP, 0); 15119 keybd_event(VK_RETURN, 0, 0, 0); 15120 keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0); 15121 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 15122 { 15123 TranslateMessage(&msg); 15124 DispatchMessageA(&msg); 15125 } 15126 ok_sequence(wm_popup_menu_2, "submenu of a popup menu command", FALSE); 15127 15128 trace("testing single menu item command\n"); 15129 flush_sequence(); 15130 keybd_event(VK_MENU, 0, 0, 0); 15131 keybd_event('Q', 0, 0, 0); 15132 keybd_event('Q', 0, KEYEVENTF_KEYUP, 0); 15133 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); 15134 keybd_event(VK_ESCAPE, 0, 0, 0); 15135 keybd_event(VK_ESCAPE, 0, KEYEVENTF_KEYUP, 0); 15136 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 15137 { 15138 TranslateMessage(&msg); 15139 DispatchMessageA(&msg); 15140 } 15141 ok_sequence(wm_single_menu_item, "single menu item command", FALSE); 15142 15143 set_menu_style(hmenu, 0); 15144 style = get_menu_style(hmenu); 15145 ok(style == 0, "expected 0, got %u\n", style); 15146 15147 hmenu_popup = GetSubMenu(hmenu, 0); 15148 ok(hmenu_popup != 0, "GetSubMenu returned 0 for submenu 0\n"); 15149 set_menu_style(hmenu_popup, MNS_NOTIFYBYPOS); 15150 style = get_menu_style(hmenu_popup); 15151 ok(style == MNS_NOTIFYBYPOS, "expected MNS_NOTIFYBYPOS, got %u\n", style); 15152 15153 hmenu_popup = GetSubMenu(hmenu_popup, 0); 15154 ok(hmenu_popup != 0, "GetSubMenu returned 0 for submenu 0\n"); 15155 style = get_menu_style(hmenu_popup); 15156 ok(style == 0, "expected 0, got %u\n", style); 15157 15158 /* Alt+F, Right, Enter */ 15159 trace("testing submenu of a popup menu command\n"); 15160 flush_sequence(); 15161 keybd_event(VK_MENU, 0, 0, 0); 15162 keybd_event('F', 0, 0, 0); 15163 keybd_event('F', 0, KEYEVENTF_KEYUP, 0); 15164 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); 15165 keybd_event(VK_RIGHT, 0, 0, 0); 15166 keybd_event(VK_RIGHT, 0, KEYEVENTF_KEYUP, 0); 15167 keybd_event(VK_RETURN, 0, 0, 0); 15168 keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0); 15169 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 15170 { 15171 TranslateMessage(&msg); 15172 DispatchMessageA(&msg); 15173 } 15174 ok_sequence(wm_popup_menu_3, "submenu of a popup menu command", FALSE); 15175 15176 done: 15177 DestroyWindow(hwnd); 15178 DestroyMenu(hmenu); 15179 } 15180 15181 15182 static void test_paintingloop(void) 15183 { 15184 HWND hwnd; 15185 15186 paint_loop_done = FALSE; 15187 hwnd = CreateWindowExA(0x0,"PaintLoopWindowClass", 15188 "PaintLoopWindowClass",WS_OVERLAPPEDWINDOW, 15189 100, 100, 100, 100, 0, 0, 0, NULL ); 15190 ok(hwnd != 0, "PaintLoop window error %u\n", GetLastError()); 15191 ShowWindow(hwnd,SW_NORMAL); 15192 SetFocus(hwnd); 15193 15194 while (!paint_loop_done) 15195 { 15196 MSG msg; 15197 if (PeekMessageA(&msg, 0, 0, 0, 1)) 15198 { 15199 TranslateMessage(&msg); 15200 DispatchMessageA(&msg); 15201 } 15202 } 15203 DestroyWindow(hwnd); 15204 } 15205 15206 static const struct message NCRBUTTONDOWNSeq[] = 15207 { 15208 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, 15209 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, 15210 { WM_CAPTURECHANGED, sent }, 15211 { WM_CONTEXTMENU, sent, /*hwnd*/0, -1 }, 15212 { 0 } 15213 }; 15214 15215 static const struct message NCXBUTTONUPSeq1[] = 15216 { 15217 { WM_APPCOMMAND, sent|lparam, /*hwnd*/0, MAKELPARAM(0, FAPPCOMMAND_MOUSE | APPCOMMAND_BROWSER_BACKWARD) }, 15218 { 0 } 15219 }; 15220 15221 static const struct message NCXBUTTONUPSeq2[] = 15222 { 15223 { WM_APPCOMMAND, sent|lparam, /*hwnd*/0, MAKELPARAM(0, FAPPCOMMAND_MOUSE | APPCOMMAND_BROWSER_FORWARD) }, 15224 { 0 } 15225 }; 15226 15227 struct rbuttonup_thread_data 15228 { 15229 HWND hwnd; 15230 HANDLE wndproc_finished; 15231 }; 15232 15233 static DWORD CALLBACK post_rbuttonup_msg( void *arg ) 15234 { 15235 struct rbuttonup_thread_data *data = arg; 15236 DWORD ret; 15237 15238 ret = WaitForSingleObject( data->wndproc_finished, 500 ); 15239 todo_wine ok( ret == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", ret ); 15240 if( ret == WAIT_OBJECT_0 ) return 0; 15241 15242 PostMessageA( data->hwnd, WM_RBUTTONUP, 0, 0 ); 15243 return 0; 15244 } 15245 15246 static void test_defwinproc(void) 15247 { 15248 HWND hwnd; 15249 MSG msg; 15250 BOOL gotwmquit = FALSE; 15251 POINT pos; 15252 RECT rect; 15253 INT x, y; 15254 LRESULT res; 15255 struct rbuttonup_thread_data data; 15256 char buffA[64]; 15257 HANDLE thread; 15258 15259 hwnd = CreateWindowExA(0, "TestWindowClass", "test_defwndproc", 15260 WS_VISIBLE | WS_CAPTION | WS_OVERLAPPEDWINDOW, 0,0,500,100,0,0,0, NULL); 15261 assert(hwnd); 15262 flush_events(); 15263 15264 buffA[0] = 0; 15265 GetWindowTextA(hwnd, buffA, sizeof(buffA)/sizeof(*buffA)); 15266 ok(!strcmp(buffA, "test_defwndproc"), "unexpected window text, %s\n", buffA); 15267 15268 /* Zero high word of the lParam */ 15269 res = DefWindowProcA(hwnd, WM_SETTEXT, 0, 0x1234); 15270 ok(res == 0, "WM_SETTEXT was expected to fail, %ld\n", res); 15271 15272 GetWindowTextA(hwnd, buffA, sizeof(buffA)/sizeof(*buffA)); 15273 ok(!strcmp(buffA, "test_defwndproc"), "unexpected window text, %s\n", buffA); 15274 15275 res = DefWindowProcW(hwnd, WM_SETTEXT, 0, 0x1234); 15276 ok(res == 0, "WM_SETTEXT was expected to fail, %ld\n", res); 15277 15278 GetWindowTextA(hwnd, buffA, sizeof(buffA)/sizeof(*buffA)); 15279 ok(!strcmp(buffA, "test_defwndproc"), "unexpected window text, %s\n", buffA); 15280 15281 GetCursorPos(&pos); 15282 GetWindowRect(hwnd, &rect); 15283 x = (rect.left+rect.right) / 2; 15284 y = rect.top + GetSystemMetrics(SM_CYFRAME) + 1; 15285 SetCursorPos(x, y); 15286 flush_events(); 15287 res = DefWindowProcA( hwnd, WM_NCHITTEST, 0, MAKELPARAM(x, y)); 15288 ok(res == HTCAPTION, "WM_NCHITTEST returned %ld\n", res); 15289 15290 mouse_event( MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0 ); 15291 mouse_event( MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 ); 15292 flush_events(); 15293 15294 flush_sequence(); 15295 mouse_event( MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0 ); 15296 /* workaround for missing support for clicking on window frame */ 15297 data.hwnd = hwnd; 15298 data.wndproc_finished = CreateEventA( NULL, FALSE, FALSE, NULL ); 15299 thread = CreateThread( NULL, 0, post_rbuttonup_msg, (void*)&data, 0, NULL ); 15300 15301 DefWindowProcA( hwnd, WM_NCRBUTTONDOWN, HTCAPTION, MAKELPARAM(x, y)); 15302 ok_sequence(NCRBUTTONDOWNSeq, "WM_NCRBUTTONDOWN on caption", FALSE); 15303 15304 res = DefWindowProcA(hwnd, WM_NCXBUTTONUP, 0, MAKELPARAM(x, y)); 15305 ok(!res, "WM_NCXBUTTONUP returned %ld\n", res); 15306 ok_sequence(WmEmptySeq, "WM_NCXBUTTONUP without button", FALSE); 15307 15308 res = DefWindowProcA(hwnd, WM_NCXBUTTONUP, MAKEWPARAM(0, XBUTTON1), MAKELPARAM(x, y)); 15309 ok(!res, "WM_NCXBUTTONUP returned %ld\n", res); 15310 ok_sequence(NCXBUTTONUPSeq1, "WM_NCXBUTTONUP with XBUTTON1", FALSE); 15311 15312 res = DefWindowProcA(hwnd, WM_NCXBUTTONUP, MAKEWPARAM(0, XBUTTON2), MAKELPARAM(x, y)); 15313 ok(!res, "WM_NCXBUTTONUP returned %ld\n", res); 15314 ok_sequence(NCXBUTTONUPSeq2, "WM_NCXBUTTONUP with XBUTTON2", FALSE); 15315 15316 res = DefWindowProcA(hwnd, WM_NCXBUTTONUP, MAKEWPARAM(0, 3), MAKELPARAM(x, y)); 15317 ok(!res, "WM_NCXBUTTONUP returned %ld\n", res); 15318 ok_sequence(WmEmptySeq, "WM_NCXBUTTONUP with invalid button", FALSE); 15319 15320 SetEvent( data.wndproc_finished ); 15321 WaitForSingleObject( thread, 1000 ); 15322 CloseHandle( data.wndproc_finished ); 15323 CloseHandle( thread ); 15324 15325 SetCursorPos(pos.x, pos.y); 15326 15327 DefWindowProcA( hwnd, WM_ENDSESSION, 1, 0); 15328 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) { 15329 if( msg.message == WM_QUIT) gotwmquit = TRUE; 15330 DispatchMessageA( &msg ); 15331 } 15332 ok(!gotwmquit, "Unexpected WM_QUIT message!\n"); 15333 DestroyWindow( hwnd); 15334 } 15335 15336 #define clear_clipboard(hwnd) clear_clipboard_(__LINE__, (hwnd)) 15337 static void clear_clipboard_(int line, HWND hWnd) 15338 { 15339 BOOL succ; 15340 succ = OpenClipboard(hWnd); 15341 ok_(__FILE__, line)(succ, "OpenClipboard failed, err=%u\n", GetLastError()); 15342 succ = EmptyClipboard(); 15343 ok_(__FILE__, line)(succ, "EmptyClipboard failed, err=%u\n", GetLastError()); 15344 succ = CloseClipboard(); 15345 ok_(__FILE__, line)(succ, "CloseClipboard failed, err=%u\n", GetLastError()); 15346 } 15347 15348 #define expect_HWND(expected, got) expect_HWND_(__LINE__, (expected), (got)) 15349 static void expect_HWND_(int line, HWND expected, HWND got) 15350 { 15351 ok_(__FILE__, line)(got==expected, "Expected %p, got %p\n", expected, got); 15352 } 15353 15354 static WNDPROC pOldViewerProc; 15355 15356 static LRESULT CALLBACK recursive_viewer_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 15357 { 15358 static BOOL recursion_guard; 15359 15360 if (message == WM_DRAWCLIPBOARD && !recursion_guard) 15361 { 15362 recursion_guard = TRUE; 15363 clear_clipboard(hWnd); 15364 recursion_guard = FALSE; 15365 } 15366 return CallWindowProcA(pOldViewerProc, hWnd, message, wParam, lParam); 15367 } 15368 15369 static void test_clipboard_viewers(void) 15370 { 15371 static struct message wm_change_cb_chain[] = 15372 { 15373 { WM_CHANGECBCHAIN, sent|wparam|lparam, 0, 0 }, 15374 { 0 } 15375 }; 15376 static const struct message wm_clipboard_destroyed[] = 15377 { 15378 { WM_DESTROYCLIPBOARD, sent|wparam|lparam, 0, 0 }, 15379 { 0 } 15380 }; 15381 static struct message wm_clipboard_changed[] = 15382 { 15383 { WM_DRAWCLIPBOARD, sent|wparam|lparam, 0, 0 }, 15384 { 0 } 15385 }; 15386 static struct message wm_clipboard_changed_and_owned[] = 15387 { 15388 { WM_DESTROYCLIPBOARD, sent|wparam|lparam, 0, 0 }, 15389 { WM_DRAWCLIPBOARD, sent|wparam|lparam, 0, 0 }, 15390 { 0 } 15391 }; 15392 15393 HINSTANCE hInst = GetModuleHandleA(NULL); 15394 HWND hWnd1, hWnd2, hWnd3; 15395 HWND hOrigViewer; 15396 HWND hRet; 15397 15398 hWnd1 = CreateWindowExA(0, "TestWindowClass", "Clipboard viewer test wnd 1", 15399 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX, 15400 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 15401 GetDesktopWindow(), NULL, hInst, NULL); 15402 hWnd2 = CreateWindowExA(0, "SimpleWindowClass", "Clipboard viewer test wnd 2", 15403 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX, 15404 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 15405 GetDesktopWindow(), NULL, hInst, NULL); 15406 hWnd3 = CreateWindowExA(0, "SimpleWindowClass", "Clipboard viewer test wnd 3", 15407 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX, 15408 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 15409 GetDesktopWindow(), NULL, hInst, NULL); 15410 trace("clipbd viewers: hWnd1=%p, hWnd2=%p, hWnd3=%p\n", hWnd1, hWnd2, hWnd3); 15411 assert(hWnd1 && hWnd2 && hWnd3); 15412 15413 CountClipboardFormats(); /* Ensure that we do not have an X11 update to the clipboard */ 15414 flush_sequence(); 15415 15416 /* Test getting the clipboard viewer and setting the viewer to NULL. */ 15417 hOrigViewer = GetClipboardViewer(); 15418 hRet = SetClipboardViewer(NULL); 15419 ok_sequence(WmEmptySeq, "set viewer to NULL", FALSE); 15420 expect_HWND(hOrigViewer, hRet); 15421 expect_HWND(NULL, GetClipboardViewer()); 15422 15423 /* Test registering hWnd1 as a viewer. */ 15424 hRet = SetClipboardViewer(hWnd1); 15425 wm_clipboard_changed[0].wParam = (WPARAM) GetClipboardOwner(); 15426 ok_sequence(wm_clipboard_changed, "set viewer NULL->1", FALSE); 15427 expect_HWND(NULL, hRet); 15428 expect_HWND(hWnd1, GetClipboardViewer()); 15429 15430 /* Test that changing the clipboard actually refreshes the registered viewer. */ 15431 clear_clipboard(hWnd1); 15432 wm_clipboard_changed[0].wParam = (WPARAM) GetClipboardOwner(); 15433 ok_sequence(wm_clipboard_changed, "clear clipbd (viewer=owner=1)", FALSE); 15434 15435 /* Again, but with different owner. */ 15436 clear_clipboard(hWnd2); 15437 wm_clipboard_changed_and_owned[1].wParam = (WPARAM) GetClipboardOwner(); 15438 ok_sequence(wm_clipboard_changed_and_owned, "clear clipbd (viewer=1, owner=2)", FALSE); 15439 15440 /* Test re-registering same window. */ 15441 hRet = SetClipboardViewer(hWnd1); 15442 wm_clipboard_changed[0].wParam = (WPARAM) GetClipboardOwner(); 15443 ok_sequence(wm_clipboard_changed, "set viewer 1->1", FALSE); 15444 expect_HWND(hWnd1, hRet); 15445 expect_HWND(hWnd1, GetClipboardViewer()); 15446 15447 /* Test ChangeClipboardChain. */ 15448 ChangeClipboardChain(hWnd2, hWnd3); 15449 wm_change_cb_chain[0].wParam = (WPARAM) hWnd2; 15450 wm_change_cb_chain[0].lParam = (LPARAM) hWnd3; 15451 ok_sequence(wm_change_cb_chain, "change chain (viewer=1, remove=2, next=3)", FALSE); 15452 expect_HWND(hWnd1, GetClipboardViewer()); 15453 15454 ChangeClipboardChain(hWnd2, NULL); 15455 wm_change_cb_chain[0].wParam = (WPARAM) hWnd2; 15456 wm_change_cb_chain[0].lParam = 0; 15457 ok_sequence(wm_change_cb_chain, "change chain (viewer=1, remove=2, next=NULL)", FALSE); 15458 expect_HWND(hWnd1, GetClipboardViewer()); 15459 15460 ChangeClipboardChain(NULL, hWnd2); 15461 ok_sequence(WmEmptySeq, "change chain (viewer=1, remove=NULL, next=2)", FALSE); 15462 expect_HWND(hWnd1, GetClipboardViewer()); 15463 15464 /* Actually change clipboard viewer with ChangeClipboardChain. */ 15465 ChangeClipboardChain(hWnd1, hWnd2); 15466 ok_sequence(WmEmptySeq, "change chain (viewer=remove=1, next=2)", FALSE); 15467 expect_HWND(hWnd2, GetClipboardViewer()); 15468 15469 /* Test that no refresh messages are sent when viewer has unregistered. */ 15470 clear_clipboard(hWnd2); 15471 ok_sequence(WmEmptySeq, "clear clipd (viewer=2, owner=1)", FALSE); 15472 15473 /* Register hWnd1 again. */ 15474 ChangeClipboardChain(hWnd2, hWnd1); 15475 ok_sequence(WmEmptySeq, "change chain (viewer=remove=2, next=1)", FALSE); 15476 expect_HWND(hWnd1, GetClipboardViewer()); 15477 15478 /* Subclass hWnd1 so that when it receives a WM_DRAWCLIPBOARD message, it 15479 * changes the clipboard. When this happens, the system shouldn't send 15480 * another WM_DRAWCLIPBOARD (as this could cause an infinite loop). 15481 */ 15482 pOldViewerProc = (WNDPROC) SetWindowLongPtrA(hWnd1, GWLP_WNDPROC, (LONG_PTR) recursive_viewer_proc); 15483 clear_clipboard(hWnd2); 15484 /* The clipboard owner is changed in recursive_viewer_proc: */ 15485 wm_clipboard_changed[0].wParam = (WPARAM) hWnd2; 15486 ok_sequence(wm_clipboard_changed, "recursive clear clipbd (viewer=1, owner=2)", TRUE); 15487 15488 /* Test unregistering. */ 15489 ChangeClipboardChain(hWnd1, NULL); 15490 ok_sequence(WmEmptySeq, "change chain (viewer=remove=1, next=NULL)", FALSE); 15491 expect_HWND(NULL, GetClipboardViewer()); 15492 15493 clear_clipboard(hWnd1); 15494 ok_sequence(wm_clipboard_destroyed, "clear clipbd (no viewer, owner=1)", FALSE); 15495 15496 DestroyWindow(hWnd1); 15497 DestroyWindow(hWnd2); 15498 DestroyWindow(hWnd3); 15499 SetClipboardViewer(hOrigViewer); 15500 } 15501 15502 static void test_PostMessage(void) 15503 { 15504 static const struct 15505 { 15506 HWND hwnd; 15507 BOOL ret; 15508 } data[] = 15509 { 15510 { HWND_TOP /* 0 */, TRUE }, 15511 { HWND_BROADCAST, TRUE }, 15512 { HWND_BOTTOM, TRUE }, 15513 { HWND_TOPMOST, TRUE }, 15514 { HWND_NOTOPMOST, FALSE }, 15515 { HWND_MESSAGE, FALSE }, 15516 { (HWND)0xdeadbeef, FALSE } 15517 }; 15518 int i; 15519 HWND hwnd; 15520 BOOL ret; 15521 MSG msg; 15522 static const WCHAR staticW[] = {'s','t','a','t','i','c',0}; 15523 15524 SetLastError(0xdeadbeef); 15525 hwnd = CreateWindowExW(0, staticW, NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL); 15526 if (!hwnd && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) 15527 { 15528 win_skip("Skipping some PostMessage tests on Win9x/WinMe\n"); 15529 return; 15530 } 15531 assert(hwnd); 15532 15533 flush_events(); 15534 15535 PostMessageA(hwnd, WM_USER+1, 0x1234, 0x5678); 15536 PostMessageA(0, WM_USER+2, 0x5678, 0x1234); 15537 15538 for (i = 0; i < sizeof(data)/sizeof(data[0]); i++) 15539 { 15540 memset(&msg, 0xab, sizeof(msg)); 15541 ret = PeekMessageA(&msg, data[i].hwnd, 0, 0, PM_NOREMOVE); 15542 ok(ret == data[i].ret, "%d: hwnd %p expected %d, got %d\n", i, data[i].hwnd, data[i].ret, ret); 15543 if (data[i].ret) 15544 { 15545 if (data[i].hwnd) 15546 ok(ret && msg.hwnd == 0 && msg.message == WM_USER+2 && 15547 msg.wParam == 0x5678 && msg.lParam == 0x1234, 15548 "%d: got ret %d hwnd %p msg %04x wParam %08lx lParam %08lx instead of TRUE/0/WM_USER+2/0x5678/0x1234\n", 15549 i, ret, msg.hwnd, msg.message, msg.wParam, msg.lParam); 15550 else 15551 ok(ret && msg.hwnd == hwnd && msg.message == WM_USER+1 && 15552 msg.wParam == 0x1234 && msg.lParam == 0x5678, 15553 "%d: got ret %d hwnd %p msg %04x wParam %08lx lParam %08lx instead of TRUE/%p/WM_USER+1/0x1234/0x5678\n", 15554 i, ret, msg.hwnd, msg.message, msg.wParam, msg.lParam, msg.hwnd); 15555 } 15556 } 15557 15558 DestroyWindow(hwnd); 15559 flush_events(); 15560 } 15561 15562 static LPARAM g_broadcast_lparam; 15563 static LRESULT WINAPI broadcast_test_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 15564 { 15565 WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA); 15566 15567 if (wParam == 0xbaadbeef) 15568 g_broadcast_lparam = wParam; 15569 else 15570 g_broadcast_lparam = 0; 15571 15572 return CallWindowProcA(oldproc, hwnd, message, wParam, lParam); 15573 } 15574 15575 static void test_broadcast(void) 15576 { 15577 static const UINT messages[] = 15578 { 15579 WM_USER-1, 15580 WM_USER, 15581 WM_USER+1, 15582 0xc000-1, 15583 0xc000, /* lowest possible atom returned by RegisterWindowMessage */ 15584 0xffff, 15585 }; 15586 WNDPROC oldproc; 15587 unsigned int i; 15588 HWND hwnd; 15589 15590 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0, 0, 0, 0, 0, 0, 0, NULL); 15591 ok(hwnd != NULL, "got %p\n", hwnd); 15592 15593 oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)broadcast_test_proc); 15594 SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc); 15595 15596 for (i = 0; i < sizeof(messages)/sizeof(messages[0]); i++) 15597 { 15598 BOOL ret; 15599 MSG msg; 15600 15601 flush_events(); 15602 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 15603 ; 15604 15605 /* post, broadcast */ 15606 ret = PostMessageA(HWND_BROADCAST, messages[i], 0, 0); 15607 ok(ret, "%d: got %d, error %d\n", i, ret, GetLastError()); 15608 15609 memset(&msg, 0xab, sizeof(msg)); 15610 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); 15611 if (messages[i] < WM_USER || messages[i] >= 0xc000) 15612 { 15613 ok(ret, "%d: message %04x, got %d, error %d\n", i, messages[i], ret, GetLastError()); 15614 ok(msg.hwnd == hwnd, "%d: got %p\n", i, msg.hwnd); 15615 } 15616 else 15617 { 15618 ok(!ret, "%d: message %04x, got %d, error %d\n", i, messages[i], ret, GetLastError()); 15619 } 15620 15621 /* post, topmost */ 15622 ret = PostMessageA(HWND_TOPMOST, messages[i], 0, 0); 15623 ok(ret, "%d: got %d, error %d\n", i, ret, GetLastError()); 15624 15625 memset(&msg, 0xab, sizeof(msg)); 15626 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); 15627 if (messages[i] < WM_USER || messages[i] >= 0xc000) 15628 { 15629 ok(ret, "%d: message %04x, got %d, error %d\n", i, messages[i], ret, GetLastError()); 15630 ok(msg.hwnd == hwnd, "%d: got %p\n", i, msg.hwnd); 15631 } 15632 else 15633 { 15634 ok(!ret, "%d: got %d, error %d\n", i, ret, GetLastError()); 15635 } 15636 15637 /* send, broadcast */ 15638 g_broadcast_lparam = 0xdead; 15639 ret = SendMessageTimeoutA(HWND_BROADCAST, messages[i], 0xbaadbeef, 0, SMTO_NORMAL, 2000, NULL); 15640 if (!ret && GetLastError() == ERROR_TIMEOUT) 15641 win_skip("broadcasting test %d, timeout\n", i); 15642 else 15643 { 15644 if (messages[i] < WM_USER || messages[i] >= 0xc000) 15645 { 15646 ok(g_broadcast_lparam == 0xbaadbeef, "%d: message %04x, got %#lx, error %d\n", i, messages[i], 15647 g_broadcast_lparam, GetLastError()); 15648 } 15649 else 15650 { 15651 ok(g_broadcast_lparam == 0xdead, "%d: message %04x, got %#lx, error %d\n", i, messages[i], 15652 g_broadcast_lparam, GetLastError()); 15653 } 15654 } 15655 15656 /* send, topmost */ 15657 g_broadcast_lparam = 0xdead; 15658 ret = SendMessageTimeoutA(HWND_TOPMOST, messages[i], 0xbaadbeef, 0, SMTO_NORMAL, 2000, NULL); 15659 if (!ret && GetLastError() == ERROR_TIMEOUT) 15660 win_skip("broadcasting test %d, timeout\n", i); 15661 else 15662 { 15663 if (messages[i] < WM_USER || messages[i] >= 0xc000) 15664 { 15665 ok(g_broadcast_lparam == 0xbaadbeef, "%d: message %04x, got %#lx, error %d\n", i, messages[i], 15666 g_broadcast_lparam, GetLastError()); 15667 } 15668 else 15669 { 15670 ok(g_broadcast_lparam == 0xdead, "%d: message %04x, got %#lx, error %d\n", i, messages[i], 15671 g_broadcast_lparam, GetLastError()); 15672 } 15673 } 15674 } 15675 15676 DestroyWindow(hwnd); 15677 } 15678 15679 static const struct 15680 { 15681 DWORD exp, broken; 15682 BOOL todo; 15683 } wait_idle_expect[] = 15684 { 15685 /* 0 */ { WAIT_TIMEOUT, WAIT_TIMEOUT, FALSE }, 15686 { WAIT_TIMEOUT, 0, FALSE }, 15687 { WAIT_TIMEOUT, 0, FALSE }, 15688 { WAIT_TIMEOUT, WAIT_TIMEOUT, FALSE }, 15689 { WAIT_TIMEOUT, WAIT_TIMEOUT, FALSE }, 15690 /* 5 */ { WAIT_TIMEOUT, 0, FALSE }, 15691 { WAIT_TIMEOUT, 0, FALSE }, 15692 { WAIT_TIMEOUT, WAIT_TIMEOUT, FALSE }, 15693 { 0, 0, FALSE }, 15694 { 0, 0, FALSE }, 15695 /* 10 */ { 0, 0, FALSE }, 15696 { 0, 0, FALSE }, 15697 { 0, WAIT_TIMEOUT, FALSE }, 15698 { 0, 0, FALSE }, 15699 { 0, 0, FALSE }, 15700 /* 15 */ { 0, 0, FALSE }, 15701 { WAIT_TIMEOUT, 0, FALSE }, 15702 { WAIT_TIMEOUT, 0, FALSE }, 15703 { WAIT_TIMEOUT, 0, FALSE }, 15704 { WAIT_TIMEOUT, 0, FALSE }, 15705 /* 20 */ { WAIT_TIMEOUT, 0, FALSE }, 15706 }; 15707 15708 static DWORD CALLBACK do_wait_idle_child_thread( void *arg ) 15709 { 15710 MSG msg; 15711 15712 PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ); 15713 Sleep( 200 ); 15714 MsgWaitForMultipleObjects( 0, NULL, FALSE, 100, QS_ALLINPUT ); 15715 return 0; 15716 } 15717 15718 static void do_wait_idle_child( int arg ) 15719 { 15720 WNDCLASSA cls; 15721 MSG msg; 15722 HWND hwnd = 0; 15723 HANDLE thread; 15724 DWORD id; 15725 HANDLE start_event = OpenEventA( EVENT_ALL_ACCESS, FALSE, "test_WaitForInputIdle_start" ); 15726 HANDLE end_event = OpenEventA( EVENT_ALL_ACCESS, FALSE, "test_WaitForInputIdle_end" ); 15727 15728 memset( &cls, 0, sizeof(cls) ); 15729 cls.lpfnWndProc = DefWindowProcA; 15730 cls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); 15731 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 15732 cls.lpszClassName = "TestClass"; 15733 RegisterClassA( &cls ); 15734 15735 PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ); /* create the msg queue */ 15736 15737 ok( start_event != 0, "failed to create start event, error %u\n", GetLastError() ); 15738 ok( end_event != 0, "failed to create end event, error %u\n", GetLastError() ); 15739 15740 switch (arg) 15741 { 15742 case 0: 15743 SetEvent( start_event ); 15744 break; 15745 case 1: 15746 SetEvent( start_event ); 15747 Sleep( 200 ); 15748 PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ); 15749 break; 15750 case 2: 15751 SetEvent( start_event ); 15752 Sleep( 200 ); 15753 PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ); 15754 PostThreadMessageA( GetCurrentThreadId(), WM_COMMAND, 0x1234, 0xabcd ); 15755 PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ); 15756 break; 15757 case 3: 15758 SetEvent( start_event ); 15759 Sleep( 200 ); 15760 SendMessageA( HWND_BROADCAST, WM_WININICHANGE, 0, 0 ); 15761 break; 15762 case 4: 15763 SetEvent( start_event ); 15764 Sleep( 200 ); 15765 hwnd = CreateWindowExA(0, "TestClass", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL); 15766 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE|PM_NOYIELD )) DispatchMessageA( &msg ); 15767 break; 15768 case 5: 15769 SetEvent( start_event ); 15770 Sleep( 200 ); 15771 hwnd = CreateWindowExA(0, "TestClass", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL); 15772 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 15773 break; 15774 case 6: 15775 SetEvent( start_event ); 15776 Sleep( 200 ); 15777 hwnd = CreateWindowExA(0, "TestClass", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL); 15778 while (PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE )) 15779 { 15780 GetMessageA( &msg, 0, 0, 0 ); 15781 DispatchMessageA( &msg ); 15782 } 15783 break; 15784 case 7: 15785 SetEvent( start_event ); 15786 Sleep( 200 ); 15787 hwnd = CreateWindowExA(0, "TestClass", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL); 15788 SetTimer( hwnd, 3, 1, NULL ); 15789 Sleep( 200 ); 15790 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE|PM_NOYIELD )) DispatchMessageA( &msg ); 15791 break; 15792 case 8: 15793 SetEvent( start_event ); 15794 Sleep( 200 ); 15795 PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ); 15796 MsgWaitForMultipleObjects( 0, NULL, FALSE, 100, QS_ALLINPUT ); 15797 break; 15798 case 9: 15799 SetEvent( start_event ); 15800 Sleep( 200 ); 15801 hwnd = CreateWindowExA(0, "TestClass", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL); 15802 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 15803 for (;;) GetMessageA( &msg, 0, 0, 0 ); 15804 break; 15805 case 10: 15806 SetEvent( start_event ); 15807 Sleep( 200 ); 15808 hwnd = CreateWindowExA(0, "TestClass", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL); 15809 SetTimer( hwnd, 3, 1, NULL ); 15810 Sleep( 200 ); 15811 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 15812 break; 15813 case 11: 15814 SetEvent( start_event ); 15815 Sleep( 200 ); 15816 return; /* exiting the process makes WaitForInputIdle return success too */ 15817 case 12: 15818 PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ); 15819 Sleep( 200 ); 15820 MsgWaitForMultipleObjects( 0, NULL, FALSE, 100, QS_ALLINPUT ); 15821 SetEvent( start_event ); 15822 break; 15823 case 13: 15824 SetEvent( start_event ); 15825 PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ); 15826 Sleep( 200 ); 15827 thread = CreateThread( NULL, 0, do_wait_idle_child_thread, NULL, 0, &id ); 15828 WaitForSingleObject( thread, 10000 ); 15829 CloseHandle( thread ); 15830 break; 15831 case 14: 15832 SetEvent( start_event ); 15833 Sleep( 200 ); 15834 PeekMessageA( &msg, HWND_TOPMOST, 0, 0, PM_NOREMOVE ); 15835 break; 15836 case 15: 15837 SetEvent( start_event ); 15838 Sleep( 200 ); 15839 PeekMessageA( &msg, HWND_BROADCAST, 0, 0, PM_NOREMOVE ); 15840 break; 15841 case 16: 15842 SetEvent( start_event ); 15843 Sleep( 200 ); 15844 PeekMessageA( &msg, HWND_BOTTOM, 0, 0, PM_NOREMOVE ); 15845 break; 15846 case 17: 15847 SetEvent( start_event ); 15848 Sleep( 200 ); 15849 PeekMessageA( &msg, (HWND)0xdeadbeef, 0, 0, PM_NOREMOVE ); 15850 break; 15851 case 18: 15852 SetEvent( start_event ); 15853 Sleep( 200 ); 15854 PeekMessageA( &msg, HWND_NOTOPMOST, 0, 0, PM_NOREMOVE ); 15855 break; 15856 case 19: 15857 SetEvent( start_event ); 15858 Sleep( 200 ); 15859 PeekMessageA( &msg, HWND_MESSAGE, 0, 0, PM_NOREMOVE ); 15860 break; 15861 case 20: 15862 SetEvent( start_event ); 15863 Sleep( 200 ); 15864 PeekMessageA( &msg, GetDesktopWindow(), 0, 0, PM_NOREMOVE ); 15865 break; 15866 } 15867 WaitForSingleObject( end_event, 2000 ); 15868 CloseHandle( start_event ); 15869 CloseHandle( end_event ); 15870 if (hwnd) DestroyWindow( hwnd ); 15871 } 15872 15873 static LRESULT CALLBACK wait_idle_proc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ) 15874 { 15875 if (msg == WM_WININICHANGE) Sleep( 200 ); /* make sure the child waits */ 15876 return DefWindowProcA( hwnd, msg, wp, lp ); 15877 } 15878 15879 static DWORD CALLBACK wait_idle_thread( void *arg ) 15880 { 15881 WNDCLASSA cls; 15882 MSG msg; 15883 HWND hwnd; 15884 15885 memset( &cls, 0, sizeof(cls) ); 15886 cls.lpfnWndProc = wait_idle_proc; 15887 cls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); 15888 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 15889 cls.lpszClassName = "TestClass"; 15890 RegisterClassA( &cls ); 15891 15892 hwnd = CreateWindowExA(0, "TestClass", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL); 15893 while (GetMessageA( &msg, 0, 0, 0 )) DispatchMessageA( &msg ); 15894 DestroyWindow(hwnd); 15895 return 0; 15896 } 15897 15898 static void test_WaitForInputIdle( char *argv0 ) 15899 { 15900 char path[MAX_PATH]; 15901 PROCESS_INFORMATION pi; 15902 STARTUPINFOA startup; 15903 BOOL ret; 15904 HANDLE start_event, end_event, thread; 15905 unsigned int i; 15906 DWORD id; 15907 const IMAGE_DOS_HEADER *dos = (const IMAGE_DOS_HEADER *)GetModuleHandleA(0); 15908 const IMAGE_NT_HEADERS *nt = (const IMAGE_NT_HEADERS *)((const char *)dos + dos->e_lfanew); 15909 BOOL console_app = (nt->OptionalHeader.Subsystem != IMAGE_SUBSYSTEM_WINDOWS_GUI); 15910 15911 if (console_app) /* build the test with -mwindows for better coverage */ 15912 trace( "not built as a GUI app, WaitForInputIdle may not be fully tested\n" ); 15913 15914 start_event = CreateEventA(NULL, 0, 0, "test_WaitForInputIdle_start"); 15915 end_event = CreateEventA(NULL, 0, 0, "test_WaitForInputIdle_end"); 15916 ok(start_event != 0, "failed to create start event, error %u\n", GetLastError()); 15917 ok(end_event != 0, "failed to create end event, error %u\n", GetLastError()); 15918 15919 memset( &startup, 0, sizeof(startup) ); 15920 startup.cb = sizeof(startup); 15921 startup.dwFlags = STARTF_USESHOWWINDOW; 15922 startup.wShowWindow = SW_SHOWNORMAL; 15923 15924 thread = CreateThread( NULL, 0, wait_idle_thread, NULL, 0, &id ); 15925 15926 for (i = 0; i < sizeof(wait_idle_expect)/sizeof(wait_idle_expect[0]); i++) 15927 { 15928 ResetEvent( start_event ); 15929 ResetEvent( end_event ); 15930 #ifndef __REACTOS__ 15931 sprintf( path, "%s msg %u", argv0, i ); 15932 #else 15933 sprintf( path, "%s msg_queue %u", argv0, i ); 15934 #endif 15935 ret = CreateProcessA( NULL, path, NULL, NULL, TRUE, 0, NULL, NULL, &startup, &pi ); 15936 ok( ret, "CreateProcess '%s' failed err %u.\n", path, GetLastError() ); 15937 if (ret) 15938 { 15939 ret = WaitForSingleObject( start_event, 5000 ); 15940 ok( ret == WAIT_OBJECT_0, "%u: WaitForSingleObject failed\n", i ); 15941 if (ret == WAIT_OBJECT_0) 15942 { 15943 ret = WaitForInputIdle( pi.hProcess, 1000 ); 15944 if (ret == WAIT_FAILED) 15945 ok( console_app || 15946 ret == wait_idle_expect[i].exp || 15947 broken(ret == wait_idle_expect[i].broken), 15948 "%u: WaitForInputIdle error %08x expected %08x\n", 15949 i, ret, wait_idle_expect[i].exp ); 15950 else todo_wine_if (wait_idle_expect[i].todo) 15951 ok( ret == wait_idle_expect[i].exp || broken(ret == wait_idle_expect[i].broken), 15952 "%u: WaitForInputIdle error %08x expected %08x\n", 15953 i, ret, wait_idle_expect[i].exp ); 15954 SetEvent( end_event ); 15955 WaitForSingleObject( pi.hProcess, 1000 ); /* give it a chance to exit on its own */ 15956 } 15957 TerminateProcess( pi.hProcess, 0 ); /* just in case */ 15958 winetest_wait_child_process( pi.hProcess ); 15959 ret = WaitForInputIdle( pi.hProcess, 100 ); 15960 ok( ret == WAIT_FAILED, "%u: WaitForInputIdle after exit error %08x\n", i, ret ); 15961 CloseHandle( pi.hProcess ); 15962 CloseHandle( pi.hThread ); 15963 } 15964 } 15965 CloseHandle( start_event ); 15966 PostThreadMessageA( id, WM_QUIT, 0, 0 ); 15967 WaitForSingleObject( thread, 10000 ); 15968 CloseHandle( thread ); 15969 } 15970 15971 static const struct message WmSetParentSeq_1[] = { 15972 { WM_SHOWWINDOW, sent|wparam, 0 }, 15973 { EVENT_OBJECT_PARENTCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 15974 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE }, 15975 { WM_CHILDACTIVATE, sent }, 15976 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOREDRAW|SWP_NOCLIENTSIZE }, 15977 { WM_MOVE, sent|defwinproc|wparam, 0 }, 15978 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 15979 { WM_SHOWWINDOW, sent|wparam, 1 }, 15980 { 0 } 15981 }; 15982 15983 static const struct message WmSetParentSeq_2[] = { 15984 { WM_SHOWWINDOW, sent|wparam, 0 }, 15985 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 15986 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 15987 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 15988 { HCBT_SETFOCUS, hook|optional }, 15989 { WM_NCACTIVATE, sent|wparam|optional, 0 }, 15990 { WM_ACTIVATE, sent|wparam|optional, 0 }, 15991 { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, 15992 { WM_KILLFOCUS, sent|wparam, 0 }, 15993 { EVENT_OBJECT_PARENTCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 15994 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE }, 15995 { HCBT_ACTIVATE, hook|optional }, 15996 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 15997 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 15998 { WM_NCACTIVATE, sent|wparam|optional, 1 }, 15999 { WM_ACTIVATE, sent|wparam|optional, 1 }, 16000 { HCBT_SETFOCUS, hook|optional }, 16001 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 16002 { WM_SETFOCUS, sent|optional|defwinproc }, 16003 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOREDRAW|SWP_NOSIZE|SWP_NOCLIENTSIZE }, 16004 { WM_MOVE, sent|defwinproc|wparam, 0 }, 16005 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 16006 { WM_SHOWWINDOW, sent|wparam, 1 }, 16007 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 16008 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 16009 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 16010 { 0 } 16011 }; 16012 16013 16014 static void test_SetParent(void) 16015 { 16016 HWND parent1, parent2, child, popup; 16017 RECT rc, rc_old; 16018 16019 parent1 = CreateWindowExA(0, "TestParentClass", NULL, WS_OVERLAPPEDWINDOW, 16020 100, 100, 200, 200, 0, 0, 0, NULL); 16021 ok(parent1 != 0, "Failed to create parent1 window\n"); 16022 16023 parent2 = CreateWindowExA(0, "TestParentClass", NULL, WS_OVERLAPPEDWINDOW, 16024 400, 100, 200, 200, 0, 0, 0, NULL); 16025 ok(parent2 != 0, "Failed to create parent2 window\n"); 16026 16027 /* WS_CHILD window */ 16028 child = CreateWindowExA(0, "TestWindowClass", NULL, WS_CHILD | WS_VISIBLE, 16029 10, 10, 150, 150, parent1, 0, 0, NULL); 16030 ok(child != 0, "Failed to create child window\n"); 16031 16032 GetWindowRect(parent1, &rc); 16033 trace("parent1 %s\n", wine_dbgstr_rect(&rc)); 16034 GetWindowRect(child, &rc_old); 16035 MapWindowPoints(0, parent1, (POINT *)&rc_old, 2); 16036 trace("child %s\n", wine_dbgstr_rect(&rc_old)); 16037 16038 flush_sequence(); 16039 16040 SetParent(child, parent2); 16041 flush_events(); 16042 ok_sequence(WmSetParentSeq_1, "SetParent() visible WS_CHILD", TRUE); 16043 16044 ok(GetWindowLongA(child, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 16045 ok(!IsWindowVisible(child), "IsWindowVisible() should return FALSE\n"); 16046 16047 GetWindowRect(parent2, &rc); 16048 trace("parent2 %s\n", wine_dbgstr_rect(&rc)); 16049 GetWindowRect(child, &rc); 16050 MapWindowPoints(0, parent2, (POINT *)&rc, 2); 16051 trace("child %s\n", wine_dbgstr_rect(&rc)); 16052 16053 ok(EqualRect(&rc_old, &rc), "rects do not match %s / %s\n", wine_dbgstr_rect(&rc_old), 16054 wine_dbgstr_rect(&rc)); 16055 16056 /* WS_POPUP window */ 16057 popup = CreateWindowExA(0, "TestWindowClass", NULL, WS_POPUP | WS_VISIBLE, 16058 20, 20, 100, 100, 0, 0, 0, NULL); 16059 ok(popup != 0, "Failed to create popup window\n"); 16060 16061 GetWindowRect(popup, &rc_old); 16062 trace("popup %s\n", wine_dbgstr_rect(&rc_old)); 16063 16064 flush_sequence(); 16065 16066 SetParent(popup, child); 16067 flush_events(); 16068 ok_sequence(WmSetParentSeq_2, "SetParent() visible WS_POPUP", TRUE); 16069 16070 ok(GetWindowLongA(popup, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 16071 ok(!IsWindowVisible(popup), "IsWindowVisible() should return FALSE\n"); 16072 16073 GetWindowRect(child, &rc); 16074 trace("parent2 %s\n", wine_dbgstr_rect(&rc)); 16075 GetWindowRect(popup, &rc); 16076 MapWindowPoints(0, child, (POINT *)&rc, 2); 16077 trace("popup %s\n", wine_dbgstr_rect(&rc)); 16078 16079 ok(EqualRect(&rc_old, &rc), "rects do not match %s / %s\n", wine_dbgstr_rect(&rc_old), 16080 wine_dbgstr_rect(&rc)); 16081 16082 DestroyWindow(popup); 16083 DestroyWindow(child); 16084 DestroyWindow(parent1); 16085 DestroyWindow(parent2); 16086 16087 flush_sequence(); 16088 } 16089 16090 static const struct message WmKeyReleaseOnly[] = { 16091 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 0x41, 0x80000001 }, 16092 { WM_KEYUP, sent|wparam|lparam, 0x41, 0x80000001 }, 16093 { 0 } 16094 }; 16095 static const struct message WmKeyPressNormal[] = { 16096 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 0x41, 0x1 }, 16097 { WM_KEYDOWN, sent|wparam|lparam, 0x41, 0x1 }, 16098 { 0 } 16099 }; 16100 static const struct message WmKeyPressRepeat[] = { 16101 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 0x41, 0x40000001 }, 16102 { WM_KEYDOWN, sent|wparam|lparam, 0x41, 0x40000001 }, 16103 { 0 } 16104 }; 16105 static const struct message WmKeyReleaseNormal[] = { 16106 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 0x41, 0xc0000001 }, 16107 { WM_KEYUP, sent|wparam|lparam, 0x41, 0xc0000001 }, 16108 { 0 } 16109 }; 16110 16111 static void test_keyflags(void) 16112 { 16113 HWND test_window; 16114 SHORT key_state; 16115 BYTE keyboard_state[256]; 16116 MSG msg; 16117 16118 test_window = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 16119 100, 100, 200, 200, 0, 0, 0, NULL); 16120 16121 flush_events(); 16122 flush_sequence(); 16123 16124 /* keyup without a keydown */ 16125 keybd_event(0x41, 0, KEYEVENTF_KEYUP, 0); 16126 while (PeekMessageA(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) 16127 DispatchMessageA(&msg); 16128 ok_sequence(WmKeyReleaseOnly, "key release only", TRUE); 16129 16130 key_state = GetAsyncKeyState(0x41); 16131 ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state); 16132 16133 key_state = GetKeyState(0x41); 16134 ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state); 16135 16136 /* keydown */ 16137 keybd_event(0x41, 0, 0, 0); 16138 while (PeekMessageA(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) 16139 DispatchMessageA(&msg); 16140 ok_sequence(WmKeyPressNormal, "key press only", FALSE); 16141 16142 key_state = GetAsyncKeyState(0x41); 16143 ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); 16144 16145 key_state = GetKeyState(0x41); 16146 ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); 16147 16148 /* keydown repeat */ 16149 keybd_event(0x41, 0, 0, 0); 16150 while (PeekMessageA(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) 16151 DispatchMessageA(&msg); 16152 ok_sequence(WmKeyPressRepeat, "key press repeat", FALSE); 16153 16154 key_state = GetAsyncKeyState(0x41); 16155 ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); 16156 16157 key_state = GetKeyState(0x41); 16158 ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); 16159 16160 /* keyup */ 16161 keybd_event(0x41, 0, KEYEVENTF_KEYUP, 0); 16162 while (PeekMessageA(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) 16163 DispatchMessageA(&msg); 16164 ok_sequence(WmKeyReleaseNormal, "key release repeat", FALSE); 16165 16166 key_state = GetAsyncKeyState(0x41); 16167 ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state); 16168 16169 key_state = GetKeyState(0x41); 16170 ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state); 16171 16172 /* set the key state in this thread */ 16173 GetKeyboardState(keyboard_state); 16174 keyboard_state[0x41] = 0x80; 16175 SetKeyboardState(keyboard_state); 16176 16177 key_state = GetAsyncKeyState(0x41); 16178 ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state); 16179 16180 /* keydown */ 16181 keybd_event(0x41, 0, 0, 0); 16182 while (PeekMessageA(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) 16183 DispatchMessageA(&msg); 16184 ok_sequence(WmKeyPressRepeat, "key press after setkeyboardstate", TRUE); 16185 16186 key_state = GetAsyncKeyState(0x41); 16187 ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); 16188 16189 key_state = GetKeyState(0x41); 16190 ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); 16191 16192 /* clear the key state in this thread */ 16193 GetKeyboardState(keyboard_state); 16194 keyboard_state[0x41] = 0; 16195 SetKeyboardState(keyboard_state); 16196 16197 key_state = GetAsyncKeyState(0x41); 16198 ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); 16199 16200 /* keyup */ 16201 keybd_event(0x41, 0, KEYEVENTF_KEYUP, 0); 16202 while (PeekMessageA(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) 16203 DispatchMessageA(&msg); 16204 ok_sequence(WmKeyReleaseOnly, "key release after setkeyboardstate", TRUE); 16205 16206 key_state = GetAsyncKeyState(0x41); 16207 ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state); 16208 16209 key_state = GetKeyState(0x41); 16210 ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state); 16211 16212 DestroyWindow(test_window); 16213 flush_sequence(); 16214 } 16215 16216 static const struct message WmHotkeyPressLWIN[] = { 16217 { WM_KEYDOWN, kbd_hook|wparam|lparam, VK_LWIN, LLKHF_INJECTED }, 16218 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_LWIN, 1 }, 16219 { WM_KEYDOWN, sent|wparam|lparam, VK_LWIN, 1 }, 16220 { 0 } 16221 }; 16222 static const struct message WmHotkeyPress[] = { 16223 { WM_KEYDOWN, kbd_hook|lparam, 0, LLKHF_INJECTED }, 16224 { WM_HOTKEY, sent|wparam, 5 }, 16225 { 0 } 16226 }; 16227 static const struct message WmHotkeyRelease[] = { 16228 { WM_KEYUP, kbd_hook|lparam, 0, LLKHF_INJECTED|LLKHF_UP }, 16229 { HCBT_KEYSKIPPED, hook|lparam|optional, 0, 0x80000001 }, 16230 { WM_KEYUP, sent|lparam, 0, 0x80000001 }, 16231 { 0 } 16232 }; 16233 static const struct message WmHotkeyReleaseLWIN[] = { 16234 { WM_KEYUP, kbd_hook|wparam|lparam, VK_LWIN, LLKHF_INJECTED|LLKHF_UP }, 16235 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_LWIN, 0xc0000001 }, 16236 { WM_KEYUP, sent|wparam|lparam, VK_LWIN, 0xc0000001 }, 16237 { 0 } 16238 }; 16239 static const struct message WmHotkeyCombined[] = { 16240 { WM_KEYDOWN, kbd_hook|wparam|lparam, VK_LWIN, LLKHF_INJECTED }, 16241 { WM_KEYDOWN, kbd_hook|lparam, 0, LLKHF_INJECTED }, 16242 { WM_KEYUP, kbd_hook|lparam, 0, LLKHF_INJECTED|LLKHF_UP }, 16243 { WM_KEYUP, kbd_hook|wparam|lparam, VK_LWIN, LLKHF_INJECTED|LLKHF_UP }, 16244 { WM_APP, sent, 0, 0 }, 16245 { WM_HOTKEY, sent|wparam, 5 }, 16246 { WM_APP+1, sent, 0, 0 }, 16247 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_LWIN, 1 }, 16248 { WM_KEYDOWN, sent|wparam|lparam, VK_LWIN, 1 }, 16249 { HCBT_KEYSKIPPED, hook|optional, 0, 0x80000001 }, 16250 { WM_KEYUP, sent, 0, 0x80000001 }, /* lparam not checked so the sequence isn't a todo */ 16251 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_LWIN, 0xc0000001 }, 16252 { WM_KEYUP, sent|wparam|lparam, VK_LWIN, 0xc0000001 }, 16253 { 0 } 16254 }; 16255 static const struct message WmHotkeyPrevious[] = { 16256 { WM_KEYDOWN, kbd_hook|wparam|lparam, VK_LWIN, LLKHF_INJECTED }, 16257 { WM_KEYDOWN, kbd_hook|lparam, 0, LLKHF_INJECTED }, 16258 { WM_KEYUP, kbd_hook|lparam, 0, LLKHF_INJECTED|LLKHF_UP }, 16259 { WM_KEYUP, kbd_hook|wparam|lparam, VK_LWIN, LLKHF_INJECTED|LLKHF_UP }, 16260 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_LWIN, 1 }, 16261 { WM_KEYDOWN, sent|wparam|lparam, VK_LWIN, 1 }, 16262 { HCBT_KEYSKIPPED, hook|lparam|optional, 0, 1 }, 16263 { WM_KEYDOWN, sent|lparam, 0, 1 }, 16264 { HCBT_KEYSKIPPED, hook|optional|lparam, 0, 0xc0000001 }, 16265 { WM_KEYUP, sent|lparam, 0, 0xc0000001 }, 16266 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_LWIN, 0xc0000001 }, 16267 { WM_KEYUP, sent|wparam|lparam, VK_LWIN, 0xc0000001 }, 16268 { 0 } 16269 }; 16270 static const struct message WmHotkeyNew[] = { 16271 { WM_KEYDOWN, kbd_hook|lparam, 0, LLKHF_INJECTED }, 16272 { WM_KEYUP, kbd_hook|lparam, 0, LLKHF_INJECTED|LLKHF_UP }, 16273 { WM_HOTKEY, sent|wparam, 5 }, 16274 { HCBT_KEYSKIPPED, hook|optional, 0, 0x80000001 }, 16275 { WM_KEYUP, sent, 0, 0x80000001 }, /* lparam not checked so the sequence isn't a todo */ 16276 { 0 } 16277 }; 16278 16279 static int hotkey_letter; 16280 16281 static LRESULT CALLBACK KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam) 16282 { 16283 struct recvd_message msg; 16284 16285 if (nCode == HC_ACTION) 16286 { 16287 KBDLLHOOKSTRUCT *kdbhookstruct = (KBDLLHOOKSTRUCT*)lParam; 16288 16289 msg.hwnd = 0; 16290 msg.message = wParam; 16291 msg.flags = kbd_hook|wparam|lparam; 16292 msg.wParam = kdbhookstruct->vkCode; 16293 msg.lParam = kdbhookstruct->flags; 16294 msg.descr = "KeyboardHookProc"; 16295 add_message(&msg); 16296 16297 if (wParam == WM_KEYUP || wParam == WM_KEYDOWN) 16298 { 16299 ok(kdbhookstruct->vkCode == VK_LWIN || kdbhookstruct->vkCode == hotkey_letter, 16300 "unexpected keycode %x\n", kdbhookstruct->vkCode); 16301 } 16302 } 16303 16304 return CallNextHookEx(hKBD_hook, nCode, wParam, lParam); 16305 } 16306 16307 static void test_hotkey(void) 16308 { 16309 HWND test_window, taskbar_window; 16310 BOOL ret; 16311 MSG msg; 16312 DWORD queue_status; 16313 SHORT key_state; 16314 16315 SetLastError(0xdeadbeef); 16316 ret = UnregisterHotKey(NULL, 0); 16317 ok(ret == FALSE, "expected FALSE, got %i\n", ret); 16318 ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED || broken(GetLastError() == 0xdeadbeef), 16319 "unexpected error %d\n", GetLastError()); 16320 16321 if (ret == TRUE) 16322 { 16323 skip("hotkeys not supported\n"); 16324 return; 16325 } 16326 16327 test_window = CreateWindowExA(0, "HotkeyWindowClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 16328 100, 100, 200, 200, 0, 0, 0, NULL); 16329 16330 flush_sequence(); 16331 16332 SetLastError(0xdeadbeef); 16333 ret = UnregisterHotKey(test_window, 0); 16334 ok(ret == FALSE, "expected FALSE, got %i\n", ret); 16335 ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED || broken(GetLastError() == 0xdeadbeef), 16336 "unexpected error %d\n", GetLastError()); 16337 16338 /* Search for a Windows Key + letter combination that hasn't been registered */ 16339 for (hotkey_letter = 0x41; hotkey_letter <= 0x51; hotkey_letter ++) 16340 { 16341 SetLastError(0xdeadbeef); 16342 ret = RegisterHotKey(test_window, 5, MOD_WIN, hotkey_letter); 16343 16344 if (ret == TRUE) 16345 { 16346 break; 16347 } 16348 else 16349 { 16350 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED || broken(GetLastError() == 0xdeadbeef), 16351 "unexpected error %d\n", GetLastError()); 16352 } 16353 } 16354 16355 if (hotkey_letter == 0x52) 16356 { 16357 ok(0, "Couldn't find any free Windows Key + letter combination\n"); 16358 goto end; 16359 } 16360 16361 hKBD_hook = SetWindowsHookExA(WH_KEYBOARD_LL, KeyboardHookProc, GetModuleHandleA(NULL), 0); 16362 if (!hKBD_hook) win_skip("WH_KEYBOARD_LL is not supported\n"); 16363 16364 /* Same key combination, different id */ 16365 SetLastError(0xdeadbeef); 16366 ret = RegisterHotKey(test_window, 4, MOD_WIN, hotkey_letter); 16367 ok(ret == FALSE, "expected FALSE, got %i\n", ret); 16368 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED || broken(GetLastError() == 0xdeadbeef), 16369 "unexpected error %d\n", GetLastError()); 16370 16371 /* Same key combination, different window */ 16372 SetLastError(0xdeadbeef); 16373 ret = RegisterHotKey(NULL, 5, MOD_WIN, hotkey_letter); 16374 ok(ret == FALSE, "expected FALSE, got %i\n", ret); 16375 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED || broken(GetLastError() == 0xdeadbeef), 16376 "unexpected error %d\n", GetLastError()); 16377 16378 /* Register the same hotkey twice */ 16379 SetLastError(0xdeadbeef); 16380 ret = RegisterHotKey(test_window, 5, MOD_WIN, hotkey_letter); 16381 ok(ret == FALSE, "expected FALSE, got %i\n", ret); 16382 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED || broken(GetLastError() == 0xdeadbeef), 16383 "unexpected error %d\n", GetLastError()); 16384 16385 /* Window on another thread */ 16386 taskbar_window = FindWindowA("Shell_TrayWnd", NULL); 16387 if (!taskbar_window) 16388 { 16389 skip("no taskbar?\n"); 16390 } 16391 else 16392 { 16393 SetLastError(0xdeadbeef); 16394 ret = RegisterHotKey(taskbar_window, 5, 0, hotkey_letter); 16395 ok(ret == FALSE, "expected FALSE, got %i\n", ret); 16396 ok(GetLastError() == ERROR_WINDOW_OF_OTHER_THREAD || broken(GetLastError() == 0xdeadbeef), 16397 "unexpected error %d\n", GetLastError()); 16398 } 16399 16400 /* Inject the appropriate key sequence */ 16401 keybd_event(VK_LWIN, 0, 0, 0); 16402 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 16403 DispatchMessageA(&msg); 16404 ok_sequence(WmHotkeyPressLWIN, "window hotkey press LWIN", FALSE); 16405 16406 keybd_event(hotkey_letter, 0, 0, 0); 16407 queue_status = GetQueueStatus(QS_HOTKEY); 16408 ok((queue_status & (QS_HOTKEY << 16)) == QS_HOTKEY << 16, "expected QS_HOTKEY << 16 set, got %x\n", queue_status); 16409 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 16410 { 16411 if (msg.message == WM_HOTKEY) 16412 { 16413 ok(msg.hwnd == test_window, "unexpected hwnd %p\n", msg.hwnd); 16414 ok(msg.lParam == MAKELPARAM(MOD_WIN, hotkey_letter), "unexpected WM_HOTKEY lparam %lx\n", msg.lParam); 16415 } 16416 DispatchMessageA(&msg); 16417 } 16418 ok_sequence(WmHotkeyPress, "window hotkey press", FALSE); 16419 16420 queue_status = GetQueueStatus(QS_HOTKEY); 16421 ok((queue_status & (QS_HOTKEY << 16)) == 0, "expected QS_HOTKEY << 16 cleared, got %x\n", queue_status); 16422 16423 key_state = GetAsyncKeyState(hotkey_letter); 16424 ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); 16425 16426 keybd_event(hotkey_letter, 0, KEYEVENTF_KEYUP, 0); 16427 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 16428 DispatchMessageA(&msg); 16429 ok_sequence(WmHotkeyRelease, "window hotkey release", TRUE); 16430 16431 keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP, 0); 16432 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 16433 DispatchMessageA(&msg); 16434 ok_sequence(WmHotkeyReleaseLWIN, "window hotkey release LWIN", FALSE); 16435 16436 /* normal posted WM_HOTKEY messages set QS_HOTKEY */ 16437 PostMessageA(test_window, WM_HOTKEY, 0, 0); 16438 queue_status = GetQueueStatus(QS_HOTKEY); 16439 ok((queue_status & (QS_HOTKEY << 16)) == QS_HOTKEY << 16, "expected QS_HOTKEY << 16 set, got %x\n", queue_status); 16440 queue_status = GetQueueStatus(QS_POSTMESSAGE); 16441 ok((queue_status & (QS_POSTMESSAGE << 16)) == QS_POSTMESSAGE << 16, "expected QS_POSTMESSAGE << 16 set, got %x\n", queue_status); 16442 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 16443 DispatchMessageA(&msg); 16444 flush_sequence(); 16445 16446 /* Send and process all messages at once */ 16447 PostMessageA(test_window, WM_APP, 0, 0); 16448 keybd_event(VK_LWIN, 0, 0, 0); 16449 keybd_event(hotkey_letter, 0, 0, 0); 16450 keybd_event(hotkey_letter, 0, KEYEVENTF_KEYUP, 0); 16451 keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP, 0); 16452 16453 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 16454 { 16455 if (msg.message == WM_HOTKEY) 16456 { 16457 ok(msg.hwnd == test_window, "unexpected hwnd %p\n", msg.hwnd); 16458 ok(msg.lParam == MAKELPARAM(MOD_WIN, hotkey_letter), "unexpected WM_HOTKEY lparam %lx\n", msg.lParam); 16459 } 16460 DispatchMessageA(&msg); 16461 } 16462 ok_sequence(WmHotkeyCombined, "window hotkey combined", FALSE); 16463 16464 /* Register same hwnd/id with different key combination */ 16465 ret = RegisterHotKey(test_window, 5, 0, hotkey_letter); 16466 ok(ret == TRUE, "expected TRUE, got %i, err=%d\n", ret, GetLastError()); 16467 16468 /* Previous key combination does not work */ 16469 keybd_event(VK_LWIN, 0, 0, 0); 16470 keybd_event(hotkey_letter, 0, 0, 0); 16471 keybd_event(hotkey_letter, 0, KEYEVENTF_KEYUP, 0); 16472 keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP, 0); 16473 16474 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 16475 DispatchMessageA(&msg); 16476 ok_sequence(WmHotkeyPrevious, "window hotkey previous", FALSE); 16477 16478 /* New key combination works */ 16479 keybd_event(hotkey_letter, 0, 0, 0); 16480 keybd_event(hotkey_letter, 0, KEYEVENTF_KEYUP, 0); 16481 16482 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 16483 { 16484 if (msg.message == WM_HOTKEY) 16485 { 16486 ok(msg.hwnd == test_window, "unexpected hwnd %p\n", msg.hwnd); 16487 ok(msg.lParam == MAKELPARAM(0, hotkey_letter), "unexpected WM_HOTKEY lparam %lx\n", msg.lParam); 16488 } 16489 DispatchMessageA(&msg); 16490 } 16491 ok_sequence(WmHotkeyNew, "window hotkey new", FALSE); 16492 16493 /* Unregister hotkey properly */ 16494 ret = UnregisterHotKey(test_window, 5); 16495 ok(ret == TRUE, "expected TRUE, got %i, err=%d\n", ret, GetLastError()); 16496 16497 /* Unregister hotkey again */ 16498 SetLastError(0xdeadbeef); 16499 ret = UnregisterHotKey(test_window, 5); 16500 ok(ret == FALSE, "expected FALSE, got %i\n", ret); 16501 ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED || broken(GetLastError() == 0xdeadbeef), 16502 "unexpected error %d\n", GetLastError()); 16503 16504 /* Register thread hotkey */ 16505 ret = RegisterHotKey(NULL, 5, MOD_WIN, hotkey_letter); 16506 ok(ret == TRUE, "expected TRUE, got %i, err=%d\n", ret, GetLastError()); 16507 16508 /* Inject the appropriate key sequence */ 16509 keybd_event(VK_LWIN, 0, 0, 0); 16510 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 16511 { 16512 ok(msg.hwnd != NULL, "unexpected thread message %x\n", msg.message); 16513 DispatchMessageA(&msg); 16514 } 16515 ok_sequence(WmHotkeyPressLWIN, "thread hotkey press LWIN", FALSE); 16516 16517 keybd_event(hotkey_letter, 0, 0, 0); 16518 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 16519 { 16520 if (msg.message == WM_HOTKEY) 16521 { 16522 struct recvd_message message; 16523 ok(msg.hwnd == NULL, "unexpected hwnd %p\n", msg.hwnd); 16524 ok(msg.lParam == MAKELPARAM(MOD_WIN, hotkey_letter), "unexpected WM_HOTKEY lparam %lx\n", msg.lParam); 16525 message.message = msg.message; 16526 message.flags = sent|wparam|lparam; 16527 message.wParam = msg.wParam; 16528 message.lParam = msg.lParam; 16529 message.descr = "test_hotkey thread message"; 16530 add_message(&message); 16531 } 16532 else 16533 ok(msg.hwnd != NULL, "unexpected thread message %x\n", msg.message); 16534 DispatchMessageA(&msg); 16535 } 16536 ok_sequence(WmHotkeyPress, "thread hotkey press", FALSE); 16537 16538 keybd_event(hotkey_letter, 0, KEYEVENTF_KEYUP, 0); 16539 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 16540 { 16541 ok(msg.hwnd != NULL, "unexpected thread message %x\n", msg.message); 16542 DispatchMessageA(&msg); 16543 } 16544 ok_sequence(WmHotkeyRelease, "thread hotkey release", TRUE); 16545 16546 keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP, 0); 16547 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 16548 { 16549 ok(msg.hwnd != NULL, "unexpected thread message %x\n", msg.message); 16550 DispatchMessageA(&msg); 16551 } 16552 ok_sequence(WmHotkeyReleaseLWIN, "thread hotkey release LWIN", FALSE); 16553 16554 /* Unregister thread hotkey */ 16555 ret = UnregisterHotKey(NULL, 5); 16556 ok(ret == TRUE, "expected TRUE, got %i, err=%d\n", ret, GetLastError()); 16557 16558 if (hKBD_hook) UnhookWindowsHookEx(hKBD_hook); 16559 hKBD_hook = NULL; 16560 16561 end: 16562 UnregisterHotKey(NULL, 5); 16563 UnregisterHotKey(test_window, 5); 16564 DestroyWindow(test_window); 16565 flush_sequence(); 16566 } 16567 16568 16569 static const struct message WmSetFocus_1[] = { 16570 { HCBT_SETFOCUS, hook }, /* child */ 16571 { HCBT_ACTIVATE, hook }, /* parent */ 16572 { WM_QUERYNEWPALETTE, sent|wparam|lparam|parent|optional, 0, 0 }, 16573 { WM_WINDOWPOSCHANGING, sent|parent, 0, SWP_NOSIZE|SWP_NOMOVE }, 16574 { WM_ACTIVATEAPP, sent|wparam|parent, 1 }, 16575 { WM_NCACTIVATE, sent|parent }, 16576 { WM_GETTEXT, sent|defwinproc|parent|optional }, 16577 { WM_GETTEXT, sent|defwinproc|parent|optional }, 16578 { WM_ACTIVATE, sent|wparam|parent, 1 }, 16579 { HCBT_SETFOCUS, hook }, /* parent */ 16580 { WM_SETFOCUS, sent|defwinproc|parent }, 16581 { WM_KILLFOCUS, sent|parent }, 16582 { WM_SETFOCUS, sent }, 16583 { 0 } 16584 }; 16585 static const struct message WmSetFocus_2[] = { 16586 { HCBT_SETFOCUS, hook }, /* parent */ 16587 { WM_KILLFOCUS, sent }, 16588 { WM_SETFOCUS, sent|parent }, 16589 { 0 } 16590 }; 16591 static const struct message WmSetFocus_3[] = { 16592 { HCBT_SETFOCUS, hook }, /* child */ 16593 { 0 } 16594 }; 16595 16596 static void test_SetFocus(void) 16597 { 16598 HWND parent, old_parent, child, old_focus, old_active; 16599 MSG msg; 16600 struct wnd_event wnd_event; 16601 HANDLE hthread; 16602 DWORD ret, tid; 16603 16604 wnd_event.start_event = CreateEventW(NULL, 0, 0, NULL); 16605 ok(wnd_event.start_event != 0, "CreateEvent error %d\n", GetLastError()); 16606 hthread = CreateThread(NULL, 0, thread_proc, &wnd_event, 0, &tid); 16607 ok(hthread != 0, "CreateThread error %d\n", GetLastError()); 16608 ret = WaitForSingleObject(wnd_event.start_event, INFINITE); 16609 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 16610 CloseHandle(wnd_event.start_event); 16611 16612 parent = CreateWindowExA(0, "TestParentClass", NULL, WS_OVERLAPPEDWINDOW, 16613 0, 0, 0, 0, 0, 0, 0, NULL); 16614 ok(parent != 0, "failed to create parent window\n"); 16615 child = CreateWindowExA(0, "TestWindowClass", NULL, WS_CHILD, 16616 0, 0, 0, 0, parent, 0, 0, NULL); 16617 ok(child != 0, "failed to create child window\n"); 16618 16619 trace("parent %p, child %p, thread window %p\n", parent, child, wnd_event.hwnd); 16620 16621 SetFocus(0); 16622 SetActiveWindow(0); 16623 16624 flush_events(); 16625 flush_sequence(); 16626 16627 ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow()); 16628 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus()); 16629 16630 log_all_parent_messages++; 16631 16632 old_focus = SetFocus(child); 16633 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 16634 ok_sequence(WmSetFocus_1, "SetFocus on a child window", TRUE); 16635 ok(old_focus == parent, "expected old focus %p, got %p\n", parent, old_focus); 16636 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 16637 ok(GetFocus() == child, "expected focus %p, got %p\n", child, GetFocus()); 16638 16639 old_focus = SetFocus(parent); 16640 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 16641 ok_sequence(WmSetFocus_2, "SetFocus on a parent window", FALSE); 16642 ok(old_focus == child, "expected old focus %p, got %p\n", child, old_focus); 16643 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 16644 ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); 16645 16646 SetLastError(0xdeadbeef); 16647 old_focus = SetFocus((HWND)0xdeadbeef); 16648 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || broken(GetLastError() == 0xdeadbeef), 16649 "expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError()); 16650 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 16651 ok_sequence(WmEmptySeq, "SetFocus on an invalid window", FALSE); 16652 ok(old_focus == 0, "expected old focus 0, got %p\n", old_focus); 16653 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 16654 ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); 16655 16656 SetLastError(0xdeadbeef); 16657 old_focus = SetFocus(GetDesktopWindow()); 16658 ok(GetLastError() == ERROR_ACCESS_DENIED /* Vista+ */ || 16659 broken(GetLastError() == 0xdeadbeef), "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); 16660 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 16661 ok_sequence(WmEmptySeq, "SetFocus on a desktop window", TRUE); 16662 ok(old_focus == 0, "expected old focus 0, got %p\n", old_focus); 16663 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 16664 ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); 16665 16666 SetLastError(0xdeadbeef); 16667 old_focus = SetFocus(wnd_event.hwnd); 16668 ok(GetLastError() == ERROR_ACCESS_DENIED /* Vista+ */ || 16669 broken(GetLastError() == 0xdeadbeef), "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); 16670 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 16671 ok_sequence(WmEmptySeq, "SetFocus on another thread window", TRUE); 16672 ok(old_focus == 0, "expected old focus 0, got %p\n", old_focus); 16673 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 16674 ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); 16675 16676 SetLastError(0xdeadbeef); 16677 old_active = SetActiveWindow((HWND)0xdeadbeef); 16678 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || broken(GetLastError() == 0xdeadbeef), 16679 "expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError()); 16680 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 16681 ok_sequence(WmEmptySeq, "SetActiveWindow on an invalid window", FALSE); 16682 ok(old_active == 0, "expected old focus 0, got %p\n", old_active); 16683 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 16684 ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); 16685 16686 SetLastError(0xdeadbeef); 16687 old_active = SetActiveWindow(GetDesktopWindow()); 16688 todo_wine 16689 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError()); 16690 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 16691 ok_sequence(WmEmptySeq, "SetActiveWindow on a desktop window", TRUE); 16692 ok(old_active == 0, "expected old focus 0, got %p\n", old_focus); 16693 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 16694 ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); 16695 16696 SetLastError(0xdeadbeef); 16697 old_active = SetActiveWindow(wnd_event.hwnd); 16698 todo_wine 16699 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError()); 16700 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 16701 ok_sequence(WmEmptySeq, "SetActiveWindow on another thread window", TRUE); 16702 ok(old_active == 0, "expected old focus 0, got %p\n", old_active); 16703 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 16704 ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); 16705 16706 SetLastError(0xdeadbeef); 16707 ret = AttachThreadInput(GetCurrentThreadId(), tid, TRUE); 16708 ok(ret, "AttachThreadInput error %d\n", GetLastError()); 16709 16710 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 16711 ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); 16712 16713 flush_events(); 16714 flush_sequence(); 16715 16716 old_focus = SetFocus(wnd_event.hwnd); 16717 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 16718 ok(old_focus == wnd_event.hwnd, "expected old focus %p, got %p\n", wnd_event.hwnd, old_focus); 16719 ok(GetActiveWindow() == wnd_event.hwnd, "expected active %p, got %p\n", wnd_event.hwnd, GetActiveWindow()); 16720 ok(GetFocus() == wnd_event.hwnd, "expected focus %p, got %p\n", wnd_event.hwnd, GetFocus()); 16721 16722 old_focus = SetFocus(parent); 16723 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 16724 ok(old_focus == parent, "expected old focus %p, got %p\n", parent, old_focus); 16725 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 16726 ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); 16727 16728 flush_events(); 16729 flush_sequence(); 16730 16731 old_active = SetActiveWindow(wnd_event.hwnd); 16732 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 16733 ok(old_active == parent, "expected old focus %p, got %p\n", parent, old_active); 16734 ok(GetActiveWindow() == wnd_event.hwnd, "expected active %p, got %p\n", wnd_event.hwnd, GetActiveWindow()); 16735 ok(GetFocus() == wnd_event.hwnd, "expected focus %p, got %p\n", wnd_event.hwnd, GetFocus()); 16736 16737 SetLastError(0xdeadbeef); 16738 ret = AttachThreadInput(GetCurrentThreadId(), tid, FALSE); 16739 ok(ret, "AttachThreadInput error %d\n", GetLastError()); 16740 16741 ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow()); 16742 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus()); 16743 16744 old_parent = SetParent(child, GetDesktopWindow()); 16745 ok(old_parent == parent, "expected old parent %p, got %p\n", parent, old_parent); 16746 16747 ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow()); 16748 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus()); 16749 16750 old_focus = SetFocus(parent); 16751 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 16752 ok(old_focus == parent, "expected old focus %p, got %p\n", parent, old_focus); 16753 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 16754 ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); 16755 16756 flush_events(); 16757 flush_sequence(); 16758 16759 SetLastError(0xdeadbeef); 16760 old_focus = SetFocus(child); 16761 todo_wine 16762 ok(GetLastError() == ERROR_INVALID_PARAMETER /* Vista+ */ || 16763 broken(GetLastError() == 0) /* XP */ || 16764 broken(GetLastError() == 0xdeadbeef), "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 16765 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 16766 ok_sequence(WmSetFocus_3, "SetFocus on a child window", TRUE); 16767 ok(old_focus == 0, "expected old focus 0, got %p\n", old_focus); 16768 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 16769 ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); 16770 16771 SetLastError(0xdeadbeef); 16772 old_active = SetActiveWindow(child); 16773 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError()); 16774 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 16775 ok_sequence(WmEmptySeq, "SetActiveWindow on a child window", FALSE); 16776 ok(old_active == parent, "expected old active %p, got %p\n", parent, old_active); 16777 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 16778 ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); 16779 16780 log_all_parent_messages--; 16781 16782 DestroyWindow(child); 16783 DestroyWindow(parent); 16784 16785 ret = PostMessageA(wnd_event.hwnd, WM_QUIT, 0, 0); 16786 ok(ret, "PostMessage(WM_QUIT) error %d\n", GetLastError()); 16787 ret = WaitForSingleObject(hthread, INFINITE); 16788 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 16789 CloseHandle(hthread); 16790 } 16791 16792 static const struct message WmSetLayeredStyle[] = { 16793 { WM_STYLECHANGING, sent }, 16794 { WM_STYLECHANGED, sent }, 16795 { WM_GETTEXT, sent|defwinproc|optional }, 16796 { 0 } 16797 }; 16798 16799 static const struct message WmSetLayeredStyle2[] = { 16800 { WM_STYLECHANGING, sent }, 16801 { WM_STYLECHANGED, sent }, 16802 { WM_WINDOWPOSCHANGING, sent|optional|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 16803 { WM_NCCALCSIZE, sent|optional|wparam|defwinproc, 1 }, 16804 { WM_WINDOWPOSCHANGED, sent|optional|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 16805 { WM_MOVE, sent|optional|defwinproc|wparam, 0 }, 16806 { WM_SIZE, sent|optional|defwinproc|wparam, SIZE_RESTORED }, 16807 { 0 } 16808 }; 16809 16810 struct layered_window_info 16811 { 16812 HWND hwnd; 16813 HDC hdc; 16814 SIZE size; 16815 HANDLE event; 16816 BOOL ret; 16817 }; 16818 16819 static DWORD CALLBACK update_layered_proc( void *param ) 16820 { 16821 struct layered_window_info *info = param; 16822 POINT src = { 0, 0 }; 16823 16824 info->ret = pUpdateLayeredWindow( info->hwnd, 0, NULL, &info->size, 16825 info->hdc, &src, 0, NULL, ULW_OPAQUE ); 16826 ok( info->ret, "failed\n"); 16827 SetEvent( info->event ); 16828 return 0; 16829 } 16830 16831 static void test_layered_window(void) 16832 { 16833 HWND hwnd; 16834 HDC hdc; 16835 HBITMAP bmp; 16836 BOOL ret; 16837 SIZE size; 16838 POINT pos, src; 16839 RECT rect, client; 16840 HANDLE thread; 16841 DWORD tid; 16842 struct layered_window_info info; 16843 16844 if (!pUpdateLayeredWindow) 16845 { 16846 win_skip( "UpdateLayeredWindow not supported\n" ); 16847 return; 16848 } 16849 16850 hdc = CreateCompatibleDC( 0 ); 16851 bmp = CreateCompatibleBitmap( hdc, 300, 300 ); 16852 SelectObject( hdc, bmp ); 16853 16854 hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_CAPTION | WS_THICKFRAME | WS_SYSMENU, 16855 100, 100, 300, 300, 0, 0, 0, NULL); 16856 ok( hwnd != 0, "failed to create window\n" ); 16857 ShowWindow( hwnd, SW_SHOWNORMAL ); 16858 UpdateWindow( hwnd ); 16859 flush_events(); 16860 flush_sequence(); 16861 16862 GetWindowRect( hwnd, &rect ); 16863 GetClientRect( hwnd, &client ); 16864 ok( client.right < rect.right - rect.left, "wrong client area\n" ); 16865 ok( client.bottom < rect.bottom - rect.top, "wrong client area\n" ); 16866 16867 src.x = src.y = 0; 16868 pos.x = pos.y = 300; 16869 size.cx = size.cy = 250; 16870 ret = pUpdateLayeredWindow( hwnd, 0, &pos, &size, hdc, &src, 0, NULL, ULW_OPAQUE ); 16871 ok( !ret, "UpdateLayeredWindow should fail on non-layered window\n" ); 16872 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() ); 16873 SetWindowLongA( hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED ); 16874 ok_sequence( WmSetLayeredStyle, "WmSetLayeredStyle", FALSE ); 16875 16876 ret = pUpdateLayeredWindow( hwnd, 0, &pos, &size, hdc, &src, 0, NULL, ULW_OPAQUE ); 16877 ok( ret, "UpdateLayeredWindow failed err %u\n", GetLastError() ); 16878 ok_sequence( WmEmptySeq, "UpdateLayeredWindow", FALSE ); 16879 GetWindowRect( hwnd, &rect ); 16880 ok( rect.left == 300 && rect.top == 300 && rect.right == 550 && rect.bottom == 550, 16881 "wrong window rect %s\n", wine_dbgstr_rect( &rect )); 16882 GetClientRect( hwnd, &rect ); 16883 ok( rect.right == client.right - 50 && rect.bottom == client.bottom - 50, 16884 "wrong client rect %s\n", wine_dbgstr_rect( &rect )); 16885 16886 size.cx = 150; 16887 pos.y = 200; 16888 ret = pUpdateLayeredWindow( hwnd, 0, &pos, &size, hdc, &src, 0, NULL, ULW_OPAQUE ); 16889 ok( ret, "UpdateLayeredWindow failed err %u\n", GetLastError() ); 16890 ok_sequence( WmEmptySeq, "UpdateLayeredWindow", FALSE ); 16891 GetWindowRect( hwnd, &rect ); 16892 ok( rect.left == 300 && rect.top == 200 && rect.right == 450 && rect.bottom == 450, 16893 "wrong window rect %s\n", wine_dbgstr_rect( &rect )); 16894 GetClientRect( hwnd, &rect ); 16895 ok( rect.right == client.right - 150 && rect.bottom == client.bottom - 50, 16896 "wrong client rect %s\n", wine_dbgstr_rect( &rect )); 16897 16898 SetWindowLongA( hwnd, GWL_STYLE, 16899 GetWindowLongA(hwnd, GWL_STYLE) & ~(WS_CAPTION | WS_THICKFRAME | WS_SYSMENU) ); 16900 ok_sequence( WmSetLayeredStyle2, "WmSetLayeredStyle2", FALSE ); 16901 16902 size.cx = 200; 16903 pos.x = 200; 16904 ret = pUpdateLayeredWindow( hwnd, 0, &pos, &size, hdc, &src, 0, NULL, ULW_OPAQUE ); 16905 ok( ret, "UpdateLayeredWindow failed err %u\n", GetLastError() ); 16906 ok_sequence( WmEmptySeq, "UpdateLayeredWindow", FALSE ); 16907 GetWindowRect( hwnd, &rect ); 16908 ok( rect.left == 200 && rect.top == 200 && rect.right == 400 && rect.bottom == 450, 16909 "wrong window rect %s\n", wine_dbgstr_rect( &rect )); 16910 GetClientRect( hwnd, &rect ); 16911 ok( (rect.right == 200 && rect.bottom == 250) || 16912 broken(rect.right == client.right - 100 && rect.bottom == client.bottom - 50), 16913 "wrong client rect %s\n", wine_dbgstr_rect( &rect )); 16914 16915 size.cx = 0; 16916 ret = pUpdateLayeredWindow( hwnd, 0, &pos, &size, hdc, &src, 0, NULL, ULW_OPAQUE ); 16917 ok( !ret, "UpdateLayeredWindow should fail on non-layered window\n" ); 16918 ok( GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == ERROR_MR_MID_NOT_FOUND) || 16919 broken(GetLastError() == ERROR_GEN_FAILURE) /* win7 */, "wrong error %u\n", GetLastError() ); 16920 size.cx = 1; 16921 size.cy = -1; 16922 ret = pUpdateLayeredWindow( hwnd, 0, &pos, &size, hdc, &src, 0, NULL, ULW_OPAQUE ); 16923 ok( !ret, "UpdateLayeredWindow should fail on non-layered window\n" ); 16924 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() ); 16925 16926 SetWindowLongA( hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) & ~WS_EX_LAYERED ); 16927 ok_sequence( WmSetLayeredStyle, "WmSetLayeredStyle", FALSE ); 16928 GetWindowRect( hwnd, &rect ); 16929 ok( rect.left == 200 && rect.top == 200 && rect.right == 400 && rect.bottom == 450, 16930 "wrong window rect %s\n", wine_dbgstr_rect( &rect )); 16931 GetClientRect( hwnd, &rect ); 16932 ok( (rect.right == 200 && rect.bottom == 250) || 16933 broken(rect.right == client.right - 100 && rect.bottom == client.bottom - 50), 16934 "wrong client rect %s\n", wine_dbgstr_rect( &rect )); 16935 16936 SetWindowLongA( hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED ); 16937 info.hwnd = hwnd; 16938 info.hdc = hdc; 16939 info.size.cx = 250; 16940 info.size.cy = 300; 16941 info.event = CreateEventA( NULL, TRUE, FALSE, NULL ); 16942 info.ret = FALSE; 16943 thread = CreateThread( NULL, 0, update_layered_proc, &info, 0, &tid ); 16944 ok( WaitForSingleObject( info.event, 1000 ) == 0, "wait failed\n" ); 16945 ok( info.ret, "UpdateLayeredWindow failed in other thread\n" ); 16946 WaitForSingleObject( thread, 1000 ); 16947 CloseHandle( thread ); 16948 GetWindowRect( hwnd, &rect ); 16949 ok( rect.left == 200 && rect.top == 200 && rect.right == 450 && rect.bottom == 500, 16950 "wrong window rect %s\n", wine_dbgstr_rect( &rect )); 16951 GetClientRect( hwnd, &rect ); 16952 ok( (rect.right == 250 && rect.bottom == 300) || 16953 broken(rect.right == client.right - 50 && rect.bottom == client.bottom), 16954 "wrong client rect %s\n", wine_dbgstr_rect( &rect )); 16955 16956 DestroyWindow( hwnd ); 16957 DeleteDC( hdc ); 16958 DeleteObject( bmp ); 16959 } 16960 16961 static HMENU hpopupmenu; 16962 16963 static LRESULT WINAPI cancel_popup_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 16964 { 16965 if (ignore_message( message )) return 0; 16966 16967 switch (message) { 16968 case WM_ENTERIDLE: 16969 todo_wine ok(GetCapture() == hwnd, "expected %p, got %p\n", hwnd, GetCapture()); 16970 EndMenu(); 16971 break; 16972 case WM_INITMENU: 16973 case WM_INITMENUPOPUP: 16974 case WM_UNINITMENUPOPUP: 16975 ok((HMENU)wParam == hpopupmenu, "expected %p, got %lx\n", hpopupmenu, wParam); 16976 break; 16977 case WM_CAPTURECHANGED: 16978 todo_wine ok(!lParam || (HWND)lParam == hwnd, "lost capture to %lx\n", lParam); 16979 break; 16980 } 16981 16982 return MsgCheckProc (FALSE, hwnd, message, wParam, lParam); 16983 } 16984 16985 static LRESULT WINAPI cancel_init_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 16986 { 16987 if (ignore_message( message )) return 0; 16988 16989 switch (message) { 16990 case WM_ENTERMENULOOP: 16991 ok(EndMenu() == TRUE, "EndMenu() failed\n"); 16992 break; 16993 } 16994 16995 return MsgCheckProc (FALSE, hwnd, message, wParam, lParam); 16996 } 16997 16998 static void test_TrackPopupMenu(void) 16999 { 17000 MSG msg; 17001 HWND hwnd; 17002 BOOL ret; 17003 17004 hwnd = CreateWindowExA(0, "TestWindowClass", NULL, 0, 17005 0, 0, 1, 1, 0, 17006 NULL, NULL, 0); 17007 ok(hwnd != NULL, "CreateWindowEx failed with error %d\n", GetLastError()); 17008 17009 SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (LONG_PTR)cancel_popup_proc); 17010 17011 hpopupmenu = CreatePopupMenu(); 17012 ok(hpopupmenu != NULL, "CreateMenu failed with error %d\n", GetLastError()); 17013 17014 AppendMenuA(hpopupmenu, MF_STRING, 100, "item 1"); 17015 AppendMenuA(hpopupmenu, MF_STRING, 100, "item 2"); 17016 17017 flush_events(); 17018 flush_sequence(); 17019 ret = TrackPopupMenu(hpopupmenu, 0, 100,100, 0, hwnd, NULL); 17020 ok_sequence(WmTrackPopupMenu, "TrackPopupMenu", TRUE); 17021 ok(ret == 1, "TrackPopupMenu failed with error %i\n", GetLastError()); 17022 17023 /* Test popup closing with an ESC-press */ 17024 flush_events(); 17025 PostMessageW(hwnd, WM_KEYDOWN, VK_ESCAPE, 0); 17026 ret = TrackPopupMenu(hpopupmenu, 0, 100,100, 0, hwnd, NULL); 17027 ok(ret == 1, "TrackPopupMenu failed with error %i\n", GetLastError()); 17028 PostQuitMessage(0); 17029 flush_sequence(); 17030 while ( PeekMessageA(&msg, 0, 0, 0, PM_REMOVE) ) 17031 { 17032 TranslateMessage(&msg); 17033 DispatchMessageA(&msg); 17034 } 17035 ok_sequence(WmTrackPopupMenuEsc, "TrackPopupMenuEsc", FALSE); /* Shouldn't get any message */ 17036 17037 SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (LONG_PTR)cancel_init_proc); 17038 17039 flush_events(); 17040 flush_sequence(); 17041 ret = TrackPopupMenu(hpopupmenu, 0, 100,100, 0, hwnd, NULL); 17042 ok_sequence(WmTrackPopupMenuAbort, "WmTrackPopupMenuAbort", TRUE); 17043 ok(ret == TRUE, "TrackPopupMenu failed\n"); 17044 17045 SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (LONG_PTR)cancel_popup_proc); 17046 17047 SetCapture(hwnd); 17048 17049 flush_events(); 17050 flush_sequence(); 17051 ret = TrackPopupMenu(hpopupmenu, 0, 100,100, 0, hwnd, NULL); 17052 ok_sequence(WmTrackPopupMenuCapture, "TrackPopupMenuCapture", TRUE); 17053 ok(ret == 1, "TrackPopupMenuCapture failed with error %i\n", GetLastError()); 17054 17055 DestroyMenu(hpopupmenu); 17056 DestroyWindow(hwnd); 17057 } 17058 17059 static void test_TrackPopupMenuEmpty(void) 17060 { 17061 HWND hwnd; 17062 BOOL ret; 17063 17064 hwnd = CreateWindowExA(0, "TestWindowClass", NULL, 0, 17065 0, 0, 1, 1, 0, 17066 NULL, NULL, 0); 17067 ok(hwnd != NULL, "CreateWindowEx failed with error %d\n", GetLastError()); 17068 17069 SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (LONG_PTR)cancel_popup_proc); 17070 17071 hpopupmenu = CreatePopupMenu(); 17072 ok(hpopupmenu != NULL, "CreateMenu failed with error %d\n", GetLastError()); 17073 17074 flush_events(); 17075 flush_sequence(); 17076 ret = TrackPopupMenu(hpopupmenu, 0, 100,100, 0, hwnd, NULL); 17077 ok_sequence(WmTrackPopupMenuEmpty, "TrackPopupMenuEmpty", TRUE); 17078 ok(ret == 0, "TrackPopupMenu succeeded\n"); 17079 17080 DestroyMenu(hpopupmenu); 17081 DestroyWindow(hwnd); 17082 } 17083 17084 static const struct message send_message_1[] = { 17085 { WM_USER+2, sent|wparam|lparam, 0, 0 }, 17086 { WM_USER, sent|wparam|lparam, 0, 0 }, 17087 { 0 } 17088 }; 17089 static const struct message send_message_2[] = { 17090 { WM_USER+4, sent|wparam|lparam, 0, 0 }, 17091 { 0 } 17092 }; 17093 static const struct message send_message_3[] = { 17094 { WM_USER+3, sent|wparam|lparam, 0, 0 }, 17095 { WM_USER+1, sent|wparam|lparam, 0, 0 }, 17096 { 0 } 17097 }; 17098 17099 static DWORD WINAPI SendMessage_thread_1(void *param) 17100 { 17101 struct wnd_event *wnd_event = param; 17102 17103 trace("thread: starting\n"); 17104 WaitForSingleObject(wnd_event->start_event, INFINITE); 17105 17106 trace("thread: call PostMessage\n"); 17107 PostMessageA(wnd_event->hwnd, WM_USER, 0, 0); 17108 17109 trace("thread: call PostMessage\n"); 17110 PostMessageA(wnd_event->hwnd, WM_USER+1, 0, 0); 17111 17112 trace("thread: call SendMessage\n"); 17113 SendMessageA(wnd_event->hwnd, WM_USER+2, 0, 0); 17114 17115 trace("thread: call SendMessage\n"); 17116 SendMessageA(wnd_event->hwnd, WM_USER+3, 0, 0); 17117 17118 return 0; 17119 } 17120 17121 static DWORD WINAPI SendMessage_thread_2(void *param) 17122 { 17123 struct wnd_event *wnd_event = param; 17124 17125 trace("thread: starting\n"); 17126 WaitForSingleObject(wnd_event->start_event, INFINITE); 17127 17128 trace("thread: call PostMessage\n"); 17129 PostMessageA(wnd_event->hwnd, WM_USER, 0, 0); 17130 17131 trace("thread: call PostMessage\n"); 17132 PostMessageA(wnd_event->hwnd, WM_USER+1, 0, 0); 17133 17134 /* this leads to sending an internal message under Wine */ 17135 trace("thread: call SetParent\n"); 17136 SetParent(wnd_event->hwnd, wnd_event->hwnd); 17137 17138 trace("thread: call SendMessage\n"); 17139 SendMessageA(wnd_event->hwnd, WM_USER+2, 0, 0); 17140 17141 trace("thread: call SendMessage\n"); 17142 SendMessageA(wnd_event->hwnd, WM_USER+3, 0, 0); 17143 17144 return 0; 17145 } 17146 17147 static void test_SendMessage_other_thread(int thread_n) 17148 { 17149 DWORD qs_all_input = QS_ALLINPUT & ~QS_RAWINPUT; 17150 HANDLE hthread; 17151 struct wnd_event wnd_event; 17152 DWORD tid, ret; 17153 MSG msg; 17154 17155 wnd_event.start_event = CreateEventA(NULL, 0, 0, NULL); 17156 17157 wnd_event.hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, 17158 100, 100, 200, 200, 0, 0, 0, NULL); 17159 ok(wnd_event.hwnd != 0, "CreateWindowEx failed\n"); 17160 17161 hthread = CreateThread(NULL, 0, thread_n == 1 ? SendMessage_thread_1 : SendMessage_thread_2, &wnd_event, 0, &tid); 17162 ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError()); 17163 CloseHandle(hthread); 17164 17165 flush_events(); 17166 flush_sequence(); 17167 17168 ret = GetQueueStatus(QS_SENDMESSAGE); 17169 ok(ret == 0, "wrong status %08x\n", ret); 17170 17171 SetEvent(wnd_event.start_event); 17172 17173 /* wait for other thread's SendMessage */ 17174 for (;;) 17175 { 17176 ret = GetQueueStatus(QS_SENDMESSAGE); 17177 if (ret == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE)) break; 17178 Sleep(50); 17179 } 17180 17181 ret = GetQueueStatus(QS_SENDMESSAGE|QS_POSTMESSAGE); 17182 ok(ret == MAKELONG(QS_POSTMESSAGE, QS_SENDMESSAGE|QS_POSTMESSAGE), "wrong status %08x\n", ret); 17183 17184 trace("main: call GetMessage\n"); 17185 GetMessageA(&msg, 0, 0, 0); 17186 ok(msg.message == WM_USER, "expected WM_USER, got %04x\n", msg.message); 17187 DispatchMessageA(&msg); 17188 ok_sequence(send_message_1, "SendMessage from other thread 1", thread_n == 2); 17189 17190 /* intentionally yield */ 17191 MsgWaitForMultipleObjects(0, NULL, FALSE, 100, qs_all_input); 17192 17193 trace("main: call SendMessage\n"); 17194 SendMessageA(wnd_event.hwnd, WM_USER+4, 0, 0); 17195 ok_sequence(send_message_2, "SendMessage from other thread 2", FALSE); 17196 17197 ret = GetQueueStatus(QS_SENDMESSAGE|QS_POSTMESSAGE); 17198 ok(ret == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_POSTMESSAGE), "wrong status %08x\n", ret); 17199 17200 trace("main: call PeekMessage\n"); 17201 ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "PeekMessage should not fail\n"); 17202 ok(msg.message == WM_USER+1, "expected WM_USER+1, got %04x\n", msg.message); 17203 DispatchMessageA(&msg); 17204 ok_sequence(send_message_3, "SendMessage from other thread 3", thread_n == 2); 17205 17206 /* intentionally yield */ 17207 MsgWaitForMultipleObjects(0, NULL, FALSE, 100, qs_all_input); 17208 17209 ret = GetQueueStatus(QS_SENDMESSAGE|QS_POSTMESSAGE); 17210 /* FIXME: remove once Wine is fixed */ 17211 todo_wine_if (thread_n == 2) 17212 ok(ret == 0, "wrong status %08x\n", ret); 17213 17214 trace("main: call PeekMessage\n"); 17215 ok(!PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "PeekMessage should fail\n"); 17216 ok_sequence(WmEmptySeq, "SendMessage from other thread 5", thread_n == 2); 17217 17218 ret = GetQueueStatus(QS_SENDMESSAGE|QS_POSTMESSAGE); 17219 ok(ret == 0, "wrong status %08x\n", ret); 17220 17221 trace("main: call DestroyWindow\n"); 17222 DestroyWindow(msg.hwnd); 17223 17224 flush_events(); 17225 flush_sequence(); 17226 } 17227 17228 static LRESULT CALLBACK insendmessage_wnd_proc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ) 17229 { 17230 DWORD flags = InSendMessageEx( NULL ); 17231 BOOL ret; 17232 17233 switch (msg) 17234 { 17235 case WM_USER: 17236 ok( flags == ISMEX_SEND, "wrong flags %x\n", flags ); 17237 ok( InSendMessage(), "InSendMessage returned false\n" ); 17238 ret = ReplyMessage( msg ); 17239 ok( ret, "ReplyMessage failed err %u\n", GetLastError() ); 17240 flags = InSendMessageEx( NULL ); 17241 ok( flags == (ISMEX_SEND | ISMEX_REPLIED), "wrong flags %x\n", flags ); 17242 ok( InSendMessage(), "InSendMessage returned false\n" ); 17243 break; 17244 case WM_USER + 1: 17245 ok( flags == ISMEX_NOTIFY, "wrong flags %x\n", flags ); 17246 ok( InSendMessage(), "InSendMessage returned false\n" ); 17247 ret = ReplyMessage( msg ); 17248 ok( ret, "ReplyMessage failed err %u\n", GetLastError() ); 17249 flags = InSendMessageEx( NULL ); 17250 ok( flags == ISMEX_NOTIFY, "wrong flags %x\n", flags ); 17251 ok( InSendMessage(), "InSendMessage returned false\n" ); 17252 break; 17253 case WM_USER + 2: 17254 ok( flags == ISMEX_CALLBACK, "wrong flags %x\n", flags ); 17255 ok( InSendMessage(), "InSendMessage returned false\n" ); 17256 ret = ReplyMessage( msg ); 17257 ok( ret, "ReplyMessage failed err %u\n", GetLastError() ); 17258 flags = InSendMessageEx( NULL ); 17259 ok( flags == (ISMEX_CALLBACK | ISMEX_REPLIED) || flags == ISMEX_SEND, "wrong flags %x\n", flags ); 17260 ok( InSendMessage(), "InSendMessage returned false\n" ); 17261 break; 17262 case WM_USER + 3: 17263 ok( flags == ISMEX_NOSEND, "wrong flags %x\n", flags ); 17264 ok( !InSendMessage(), "InSendMessage returned true\n" ); 17265 ret = ReplyMessage( msg ); 17266 ok( !ret, "ReplyMessage succeeded\n" ); 17267 break; 17268 } 17269 17270 return DefWindowProcA( hwnd, msg, wp, lp ); 17271 } 17272 17273 static void CALLBACK msg_callback( HWND hwnd, UINT msg, ULONG_PTR arg, LRESULT result ) 17274 { 17275 ok( msg == WM_USER + 2, "wrong msg %x\n", msg ); 17276 ok( result == WM_USER + 2, "wrong result %lx\n", result ); 17277 } 17278 17279 static DWORD WINAPI send_message_thread( void *arg ) 17280 { 17281 HWND win = arg; 17282 17283 SendMessageA( win, WM_USER, 0, 0 ); 17284 SendNotifyMessageA( win, WM_USER + 1, 0, 0 ); 17285 SendMessageCallbackA( win, WM_USER + 2, 0, 0, msg_callback, 0 ); 17286 PostMessageA( win, WM_USER + 3, 0, 0 ); 17287 PostMessageA( win, WM_QUIT, 0, 0 ); 17288 return 0; 17289 } 17290 17291 static void test_InSendMessage(void) 17292 { 17293 WNDCLASSA cls; 17294 HWND win; 17295 MSG msg; 17296 HANDLE thread; 17297 DWORD tid; 17298 17299 memset(&cls, 0, sizeof(cls)); 17300 cls.lpfnWndProc = insendmessage_wnd_proc; 17301 cls.hInstance = GetModuleHandleA(NULL); 17302 cls.lpszClassName = "InSendMessage_test"; 17303 RegisterClassA(&cls); 17304 17305 win = CreateWindowA( "InSendMessage_test", NULL, 0, 0, 0, 0, 0, NULL, 0, NULL, 0 ); 17306 ok( win != NULL, "CreateWindow failed: %d\n", GetLastError() ); 17307 17308 thread = CreateThread( NULL, 0, send_message_thread, win, 0, &tid ); 17309 ok( thread != NULL, "CreateThread failed: %d\n", GetLastError() ); 17310 17311 while (GetMessageA(&msg, NULL, 0, 0)) DispatchMessageA( &msg ); 17312 17313 ok( WaitForSingleObject( thread, 30000 ) == WAIT_OBJECT_0, "WaitForSingleObject failed\n" ); 17314 CloseHandle( thread ); 17315 17316 DestroyWindow( win ); 17317 UnregisterClassA( "InSendMessage_test", GetModuleHandleA(NULL) ); 17318 } 17319 17320 static const struct message DoubleSetCaptureSeq[] = 17321 { 17322 { WM_CAPTURECHANGED, sent }, 17323 { 0 } 17324 }; 17325 17326 static void test_DoubleSetCapture(void) 17327 { 17328 HWND hwnd; 17329 17330 hwnd = CreateWindowExA(0, "TestWindowClass", "Test DoubleSetCapture", 17331 WS_OVERLAPPEDWINDOW | WS_VISIBLE, 17332 100, 100, 200, 200, 0, 0, 0, NULL); 17333 ok (hwnd != 0, "Failed to create overlapped window\n"); 17334 17335 ShowWindow( hwnd, SW_SHOW ); 17336 UpdateWindow( hwnd ); 17337 flush_events(); 17338 flush_sequence(); 17339 17340 SetCapture( hwnd ); 17341 SetCapture( hwnd ); 17342 ok_sequence(DoubleSetCaptureSeq, "SetCapture( hwnd ) twice", FALSE); 17343 17344 DestroyWindow(hwnd); 17345 } 17346 17347 static void init_funcs(void) 17348 { 17349 HMODULE hKernel32 = GetModuleHandleA("kernel32.dll"); 17350 17351 #define X(f) p##f = (void*)GetProcAddress(hKernel32, #f) 17352 X(ActivateActCtx); 17353 X(CreateActCtxW); 17354 X(DeactivateActCtx); 17355 X(GetCurrentActCtx); 17356 X(QueryActCtxW); 17357 X(ReleaseActCtx); 17358 #undef X 17359 } 17360 17361 #ifndef __REACTOS__ 17362 START_TEST(msg) 17363 { 17364 char **test_argv; 17365 BOOL ret; 17366 BOOL (WINAPI *pIsWinEventHookInstalled)(DWORD)= 0;/*GetProcAddress(user32, "IsWinEventHookInstalled");*/ 17367 HMODULE hModuleImm32; 17368 BOOL (WINAPI *pImmDisableIME)(DWORD); 17369 int argc; 17370 17371 init_funcs(); 17372 17373 argc = winetest_get_mainargs( &test_argv ); 17374 if (argc >= 3) 17375 { 17376 unsigned int arg; 17377 /* Child process. */ 17378 sscanf (test_argv[2], "%d", (unsigned int *) &arg); 17379 do_wait_idle_child( arg ); 17380 return; 17381 } 17382 17383 InitializeCriticalSection( &sequence_cs ); 17384 init_procs(); 17385 17386 hModuleImm32 = LoadLibraryA("imm32.dll"); 17387 if (hModuleImm32) { 17388 pImmDisableIME = (void *)GetProcAddress(hModuleImm32, "ImmDisableIME"); 17389 if (pImmDisableIME) 17390 pImmDisableIME(0); 17391 } 17392 pImmDisableIME = NULL; 17393 FreeLibrary(hModuleImm32); 17394 17395 if (!RegisterWindowClasses()) assert(0); 17396 17397 if (pSetWinEventHook) 17398 { 17399 hEvent_hook = pSetWinEventHook(EVENT_MIN, EVENT_MAX, 17400 GetModuleHandleA(0), win_event_proc, 17401 0, GetCurrentThreadId(), 17402 WINEVENT_INCONTEXT); 17403 if (pIsWinEventHookInstalled && hEvent_hook) 17404 { 17405 UINT event; 17406 for (event = EVENT_MIN; event <= EVENT_MAX; event++) 17407 ok(pIsWinEventHookInstalled(event), "IsWinEventHookInstalled(%u) failed\n", event); 17408 } 17409 } 17410 if (!hEvent_hook) win_skip( "no win event hook support\n" ); 17411 17412 cbt_hook_thread_id = GetCurrentThreadId(); 17413 hCBT_hook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId()); 17414 if (!hCBT_hook) win_skip( "cannot set global hook, will skip hook tests\n" ); 17415 17416 test_winevents(); 17417 17418 /* Fix message sequences before removing 4 lines below */ 17419 if (pUnhookWinEvent && hEvent_hook) 17420 { 17421 ret = pUnhookWinEvent(hEvent_hook); 17422 ok( ret, "UnhookWinEvent error %d\n", GetLastError()); 17423 pUnhookWinEvent = 0; 17424 } 17425 hEvent_hook = 0; 17426 17427 test_SendMessage_other_thread(1); 17428 test_SendMessage_other_thread(2); 17429 test_InSendMessage(); 17430 test_SetFocus(); 17431 test_SetParent(); 17432 test_PostMessage(); 17433 test_broadcast(); 17434 test_ShowWindow(); 17435 test_PeekMessage(); 17436 test_PeekMessage2(); 17437 test_PeekMessage3(); 17438 test_WaitForInputIdle( test_argv[0] ); 17439 test_scrollwindowex(); 17440 test_messages(); 17441 test_setwindowpos(); 17442 test_showwindow(); 17443 invisible_parent_tests(); 17444 test_mdi_messages(); 17445 test_button_messages(); 17446 test_autoradio_BM_CLICK(); 17447 test_autoradio_kbd_move(); 17448 test_static_messages(); 17449 test_listbox_messages(); 17450 test_combobox_messages(); 17451 test_wmime_keydown_message(); 17452 test_paint_messages(); 17453 test_interthread_messages(); 17454 test_message_conversion(); 17455 test_accelerators(); 17456 test_timers(); 17457 test_timers_no_wnd(); 17458 test_timers_exceptions(); 17459 if (hCBT_hook) 17460 { 17461 test_set_hook(); 17462 test_recursive_hook(); 17463 } 17464 test_DestroyWindow(); 17465 test_DispatchMessage(); 17466 test_SendMessageTimeout(); 17467 test_edit_messages(); 17468 test_quit_message(); 17469 test_notify_message(); 17470 test_SetActiveWindow(); 17471 17472 if (!pTrackMouseEvent) 17473 win_skip("TrackMouseEvent is not available\n"); 17474 else 17475 test_TrackMouseEvent(); 17476 17477 test_SetWindowRgn(); 17478 test_sys_menu(); 17479 test_dialog_messages(); 17480 test_EndDialog(); 17481 test_nullCallback(); 17482 test_dbcs_wm_char(); 17483 test_unicode_wm_char(); 17484 test_menu_messages(); 17485 test_paintingloop(); 17486 test_defwinproc(); 17487 test_clipboard_viewers(); 17488 test_keyflags(); 17489 test_hotkey(); 17490 test_layered_window(); 17491 test_TrackPopupMenu(); 17492 test_TrackPopupMenuEmpty(); 17493 test_DoubleSetCapture(); 17494 /* keep it the last test, under Windows it tends to break the tests 17495 * which rely on active/foreground windows being correct. 17496 */ 17497 test_SetForegroundWindow(); 17498 17499 UnhookWindowsHookEx(hCBT_hook); 17500 if (pUnhookWinEvent && hEvent_hook) 17501 { 17502 ret = pUnhookWinEvent(hEvent_hook); 17503 ok( ret, "UnhookWinEvent error %d\n", GetLastError()); 17504 SetLastError(0xdeadbeef); 17505 ok(!pUnhookWinEvent(hEvent_hook), "UnhookWinEvent succeeded\n"); 17506 ok(GetLastError() == ERROR_INVALID_HANDLE || /* Win2k */ 17507 GetLastError() == 0xdeadbeef, /* Win9x */ 17508 "unexpected error %d\n", GetLastError()); 17509 } 17510 DeleteCriticalSection( &sequence_cs ); 17511 } 17512 #endif /* __REACTOS__ */ 17513 17514 static void init_tests() 17515 { 17516 HMODULE hModuleImm32; 17517 BOOL (WINAPI *pImmDisableIME)(DWORD); 17518 17519 init_funcs(); 17520 17521 InitializeCriticalSection( &sequence_cs ); 17522 init_procs(); 17523 17524 hModuleImm32 = LoadLibraryA("imm32.dll"); 17525 if (hModuleImm32) { 17526 pImmDisableIME = (void *)GetProcAddress(hModuleImm32, "ImmDisableIME"); 17527 if (pImmDisableIME) 17528 pImmDisableIME(0); 17529 } 17530 pImmDisableIME = NULL; 17531 FreeLibrary(hModuleImm32); 17532 17533 if (!RegisterWindowClasses()) assert(0); 17534 17535 cbt_hook_thread_id = GetCurrentThreadId(); 17536 hCBT_hook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId()); 17537 if (!hCBT_hook) win_skip( "cannot set global hook, will skip hook tests\n" ); 17538 } 17539 17540 static void cleanup_tests() 17541 { 17542 BOOL ret; 17543 UnhookWindowsHookEx(hCBT_hook); 17544 if (pUnhookWinEvent && hEvent_hook) 17545 { 17546 ret = pUnhookWinEvent(hEvent_hook); 17547 ok( ret, "UnhookWinEvent error %d\n", GetLastError()); 17548 SetLastError(0xdeadbeef); 17549 ok(!pUnhookWinEvent(hEvent_hook), "UnhookWinEvent succeeded\n"); 17550 ok(GetLastError() == ERROR_INVALID_HANDLE || /* Win2k */ 17551 GetLastError() == 0xdeadbeef, /* Win9x */ 17552 "unexpected error %d\n", GetLastError()); 17553 } 17554 DeleteCriticalSection( &sequence_cs ); 17555 17556 } 17557 17558 START_TEST(msg_queue) 17559 { 17560 int argc; 17561 char **test_argv; 17562 argc = winetest_get_mainargs( &test_argv ); 17563 if (argc >= 3) 17564 { 17565 unsigned int arg; 17566 /* Child process. */ 17567 sscanf (test_argv[2], "%d", (unsigned int *) &arg); 17568 do_wait_idle_child( arg ); 17569 return; 17570 } 17571 17572 init_tests(); 17573 test_SendMessage_other_thread(1); 17574 test_SendMessage_other_thread(2); 17575 test_InSendMessage(); 17576 test_PostMessage(); 17577 test_broadcast(); 17578 test_PeekMessage(); 17579 test_PeekMessage2(); 17580 test_PeekMessage3(); 17581 test_interthread_messages(); 17582 test_DispatchMessage(); 17583 test_SendMessageTimeout(); 17584 test_quit_message(); 17585 test_notify_message(); 17586 test_WaitForInputIdle( test_argv[0] ); 17587 test_DestroyWindow(); 17588 cleanup_tests(); 17589 } 17590 17591 START_TEST(msg_messages) 17592 { 17593 init_tests(); 17594 test_message_conversion(); 17595 test_messages(); 17596 test_wmime_keydown_message(); 17597 test_nullCallback(); 17598 test_dbcs_wm_char(); 17599 test_unicode_wm_char(); 17600 test_defwinproc(); 17601 cleanup_tests(); 17602 } 17603 17604 START_TEST(msg_focus) 17605 { 17606 init_tests(); 17607 17608 test_SetFocus(); 17609 17610 /* HACK: For some reason the tests fail on Windows if run consecutively. 17611 * Putting these in between helps, and is essentially what happens in the 17612 * "normal" msg test. */ 17613 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); 17614 flush_events(); 17615 17616 test_SetActiveWindow(); 17617 17618 /* HACK */ 17619 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); 17620 flush_events(); 17621 17622 test_DoubleSetCapture(); 17623 17624 /* keep it the last test, under Windows it tends to break the tests 17625 * which rely on active/foreground windows being correct. 17626 */ 17627 test_SetForegroundWindow(); 17628 cleanup_tests(); 17629 } 17630 17631 START_TEST(msg_winpos) 17632 { 17633 init_tests(); 17634 test_SetParent(); 17635 test_ShowWindow(); 17636 test_setwindowpos(); 17637 test_showwindow(); 17638 test_SetWindowRgn(); 17639 invisible_parent_tests(); 17640 cleanup_tests(); 17641 } 17642 17643 START_TEST(msg_paint) 17644 { 17645 init_tests(); 17646 test_scrollwindowex(); 17647 test_paint_messages(); 17648 #ifdef __REACTOS__ 17649 if (!winetest_interactive && 17650 !strcmp(winetest_platform, "windows")) 17651 { 17652 skip("ROSTESTS-185: Skipping user32_winetest:msg_paint test_paintingloop because it hangs on WHS-Testbot. Set winetest_interactive to run it anyway.\n"); 17653 } 17654 else 17655 #endif 17656 test_paintingloop(); 17657 cleanup_tests(); 17658 } 17659 17660 START_TEST(msg_input) 17661 { 17662 init_tests(); 17663 test_accelerators(); 17664 if (!pTrackMouseEvent) 17665 win_skip("TrackMouseEvent is not available\n"); 17666 else 17667 test_TrackMouseEvent(); 17668 17669 test_keyflags(); 17670 test_hotkey(); 17671 cleanup_tests(); 17672 } 17673 17674 START_TEST(msg_timer) 17675 { 17676 init_tests(); 17677 test_timers(); 17678 test_timers_no_wnd(); 17679 test_timers_exceptions(); 17680 cleanup_tests(); 17681 } 17682 17683 typedef BOOL (WINAPI *IS_WINEVENT_HOOK_INSTALLED)(DWORD); 17684 17685 START_TEST(msg_hook) 17686 { 17687 // HMODULE user32 = GetModuleHandleA("user32.dll"); 17688 // IS_WINEVENT_HOOK_INSTALLED pIsWinEventHookInstalled = (IS_WINEVENT_HOOK_INSTALLED)GetProcAddress(user32, "IsWinEventHookInstalled"); 17689 BOOL (WINAPI *pIsWinEventHookInstalled)(DWORD)= 0;/*GetProcAddress(user32, "IsWinEventHookInstalled");*/ 17690 17691 init_tests(); 17692 17693 if (pSetWinEventHook) 17694 { 17695 hEvent_hook = pSetWinEventHook(EVENT_MIN, EVENT_MAX, 17696 GetModuleHandleA(0), win_event_proc, 17697 0, GetCurrentThreadId(), 17698 WINEVENT_INCONTEXT); 17699 if (pIsWinEventHookInstalled && hEvent_hook) 17700 { 17701 UINT event; 17702 for (event = EVENT_MIN; event <= EVENT_MAX; event++) 17703 ok(pIsWinEventHookInstalled(event), "IsWinEventHookInstalled(%u) failed\n", event); 17704 } 17705 } 17706 if (!hEvent_hook) win_skip( "no win event hook support\n" ); 17707 17708 test_winevents(); 17709 17710 /* Fix message sequences before removing 4 lines below */ 17711 if (pUnhookWinEvent && hEvent_hook) 17712 { 17713 BOOL ret; 17714 ret = pUnhookWinEvent(hEvent_hook); 17715 ok( ret, "UnhookWinEvent error %d\n", GetLastError()); 17716 pUnhookWinEvent = 0; 17717 } 17718 hEvent_hook = 0; 17719 if (hCBT_hook) 17720 { 17721 test_set_hook(); 17722 test_recursive_hook(); 17723 } 17724 cleanup_tests(); 17725 } 17726 17727 START_TEST(msg_menu) 17728 { 17729 init_tests(); 17730 test_sys_menu(); 17731 test_menu_messages(); 17732 test_TrackPopupMenu(); 17733 test_TrackPopupMenuEmpty(); 17734 cleanup_tests(); 17735 } 17736 17737 START_TEST(msg_mdi) 17738 { 17739 init_tests(); 17740 test_mdi_messages(); 17741 cleanup_tests(); 17742 } 17743 17744 START_TEST(msg_controls) 17745 { 17746 init_tests(); 17747 test_button_messages(); 17748 test_autoradio_BM_CLICK(); 17749 test_autoradio_kbd_move(); 17750 test_static_messages(); 17751 test_listbox_messages(); 17752 test_combobox_messages(); 17753 test_edit_messages(); 17754 cleanup_tests(); 17755 } 17756 17757 START_TEST(msg_layered_window) 17758 { 17759 init_tests(); 17760 test_layered_window(); 17761 cleanup_tests(); 17762 } 17763 17764 START_TEST(msg_dialog) 17765 { 17766 init_tests(); 17767 test_dialog_messages(); 17768 test_EndDialog(); 17769 cleanup_tests(); 17770 } 17771 17772 START_TEST(msg_clipboard) 17773 { 17774 init_tests(); 17775 test_clipboard_viewers(); 17776 cleanup_tests(); 17777 } 17778