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 #include <assert.h> 24 #include <limits.h> 25 #include <stdarg.h> 26 #include <stdio.h> 27 28 #include "windef.h" 29 #include "winbase.h" 30 #include "wingdi.h" 31 #include "winuser.h" 32 #include "winnls.h" 33 #include "dbt.h" 34 35 #include "wine/test.h" 36 37 #define MDI_FIRST_CHILD_ID 2004 38 39 /* undocumented SWP flags - from SDK 3.1 */ 40 #define SWP_NOCLIENTSIZE 0x0800 41 #define SWP_NOCLIENTMOVE 0x1000 42 #define SWP_STATECHANGED 0x8000 43 44 #define SW_NORMALNA 0xCC /* undoc. flag in MinMaximize */ 45 46 #ifndef WM_KEYF1 47 #define WM_KEYF1 0x004d 48 #endif 49 50 #ifndef WM_SYSTIMER 51 #define WM_SYSTIMER 0x0118 52 #endif 53 54 #define WND_PARENT_ID 1 55 #define WND_POPUP_ID 2 56 #define WND_CHILD_ID 3 57 58 #ifndef WM_LBTRACKPOINT 59 #define WM_LBTRACKPOINT 0x0131 60 #endif 61 62 #ifdef __i386__ 63 #define ARCH "x86" 64 #elif defined __x86_64__ 65 #define ARCH "amd64" 66 #elif defined __arm__ 67 #define ARCH "arm" 68 #elif defined __aarch64__ 69 #define ARCH "arm64" 70 #else 71 #define ARCH "none" 72 #endif 73 74 static BOOL (WINAPI *pActivateActCtx)(HANDLE,ULONG_PTR*); 75 static HANDLE (WINAPI *pCreateActCtxW)(PCACTCTXW); 76 static BOOL (WINAPI *pDeactivateActCtx)(DWORD,ULONG_PTR); 77 static BOOL (WINAPI *pGetCurrentActCtx)(HANDLE *); 78 static BOOL (WINAPI *pQueryActCtxW)(DWORD,HANDLE,void*,ULONG,void*,SIZE_T,SIZE_T*); 79 static void (WINAPI *pReleaseActCtx)(HANDLE); 80 81 /* encoded DRAWITEMSTRUCT into an LPARAM */ 82 typedef struct 83 { 84 union 85 { 86 struct 87 { 88 UINT type : 4; /* ODT_* flags */ 89 UINT ctl_id : 4; /* Control ID */ 90 UINT item_id : 4; /* Menu item ID */ 91 UINT action : 4; /* ODA_* flags */ 92 UINT state : 16; /* ODS_* flags */ 93 } item; 94 LPARAM lp; 95 } u; 96 } DRAW_ITEM_STRUCT; 97 98 /* encoded MEASUREITEMSTRUCT into a WPARAM */ 99 typedef struct 100 { 101 union 102 { 103 struct 104 { 105 UINT CtlType : 4; 106 UINT CtlID : 4; 107 UINT itemID : 4; 108 UINT wParam : 20; 109 } item; 110 WPARAM wp; 111 } u; 112 } MEASURE_ITEM_STRUCT; 113 114 static BOOL test_DestroyWindow_flag; 115 static HWINEVENTHOOK hEvent_hook; 116 static HHOOK hKBD_hook; 117 static HHOOK hCBT_hook; 118 static DWORD cbt_hook_thread_id; 119 120 static const WCHAR testWindowClassW[] = 121 { 'T','e','s','t','W','i','n','d','o','w','C','l','a','s','s','W',0 }; 122 123 static LRESULT WINAPI ParentMsgCheckProcA(HWND, UINT, WPARAM, LPARAM); 124 125 /* 126 FIXME: add tests for these 127 Window Edge Styles (Win31/Win95/98 look), in order of precedence: 128 WS_EX_DLGMODALFRAME: double border, WS_CAPTION allowed 129 WS_THICKFRAME: thick border 130 WS_DLGFRAME: double border, WS_CAPTION not allowed (but possibly shown anyway) 131 WS_BORDER (default for overlapped windows): single black border 132 none (default for child (and popup?) windows): no border 133 */ 134 135 typedef enum { 136 sent=0x1, 137 posted=0x2, 138 parent=0x4, 139 wparam=0x8, 140 lparam=0x10, 141 defwinproc=0x20, 142 beginpaint=0x40, 143 optional=0x80, 144 hook=0x100, 145 winevent_hook=0x200, 146 kbd_hook=0x400 147 } msg_flags_t; 148 149 struct message { 150 UINT message; /* the WM_* code */ 151 msg_flags_t flags; /* message props */ 152 WPARAM wParam; /* expected value of wParam */ 153 LPARAM lParam; /* expected value of lParam */ 154 WPARAM wp_mask; /* mask for wParam checks */ 155 LPARAM lp_mask; /* mask for lParam checks */ 156 }; 157 158 struct recvd_message { 159 UINT message; /* the WM_* code */ 160 msg_flags_t flags; /* message props */ 161 HWND hwnd; /* window that received the message */ 162 WPARAM wParam; /* expected value of wParam */ 163 LPARAM lParam; /* expected value of lParam */ 164 int line; /* source line where logged */ 165 const char *descr; /* description for trace output */ 166 char output[512]; /* trace output */ 167 }; 168 169 /* Empty message sequence */ 170 static const struct message WmEmptySeq[] = 171 { 172 { 0 } 173 }; 174 /* CreateWindow (for overlapped window, not initially visible) (16/32) */ 175 static const struct message WmCreateOverlappedSeq[] = { 176 { HCBT_CREATEWND, hook }, 177 { WM_GETMINMAXINFO, sent }, 178 { WM_NCCREATE, sent }, 179 { WM_NCCALCSIZE, sent|wparam, 0 }, 180 { 0x0093, sent|defwinproc|optional }, 181 { 0x0094, sent|defwinproc|optional }, 182 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, 183 { WM_CREATE, sent }, 184 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 185 { 0 } 186 }; 187 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE) 188 * for a not visible overlapped window. 189 */ 190 static const struct message WmSWP_ShowOverlappedSeq[] = { 191 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 192 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 193 { WM_NCPAINT, sent|wparam|optional, 1 }, 194 { WM_GETTEXT, sent|defwinproc|optional }, 195 { WM_ERASEBKGND, sent|optional }, 196 { HCBT_ACTIVATE, hook }, 197 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 198 { WM_NOTIFYFORMAT, sent|optional }, 199 { WM_QUERYUISTATE, sent|optional }, 200 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 201 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* Win9x: SWP_NOSENDCHANGING */ 202 { WM_ACTIVATEAPP, sent|wparam, 1 }, 203 { WM_NCACTIVATE, sent }, 204 { WM_GETTEXT, sent|defwinproc|optional }, 205 { WM_ACTIVATE, sent|wparam, 1 }, 206 { HCBT_SETFOCUS, hook }, 207 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 208 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 209 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 210 { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, 211 { WM_GETTEXT, sent|optional }, 212 { WM_NCPAINT, sent|wparam|optional, 1 }, 213 { WM_GETTEXT, sent|defwinproc|optional }, 214 { WM_ERASEBKGND, sent|optional }, 215 /* Win9x adds SWP_NOZORDER below */ 216 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 217 { WM_GETTEXT, sent|optional }, 218 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, 219 { WM_NCPAINT, sent|wparam|optional, 1 }, 220 { WM_ERASEBKGND, sent|optional }, 221 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 222 { WM_SYNCPAINT, sent|optional }, 223 { WM_GETTITLEBARINFOEX, sent|optional }, 224 { WM_PAINT, sent|optional }, 225 { WM_NCPAINT, sent|beginpaint|optional }, 226 { WM_GETTEXT, sent|beginpaint|defwinproc|optional }, 227 { WM_ERASEBKGND, sent|beginpaint|optional }, 228 { 0 } 229 }; 230 /* SetWindowPos(SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE) 231 * for a visible overlapped window. 232 */ 233 static const struct message WmSWP_HideOverlappedSeq[] = { 234 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 235 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 236 { HCBT_ACTIVATE, hook|optional }, 237 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 238 { WM_ACTIVATEAPP, sent|wparam|optional, 1 }, 239 { WM_NCACTIVATE, sent|optional }, 240 { WM_ACTIVATE, sent|optional }, 241 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 242 { 0 } 243 }; 244 245 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE) 246 * for a visible overlapped window. 247 */ 248 static const struct message WmSWP_ResizeSeq[] = { 249 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE }, 250 { WM_GETMINMAXINFO, sent|defwinproc }, 251 { WM_NCCALCSIZE, sent|wparam|optional, TRUE }, 252 { WM_NCPAINT, sent|optional }, 253 { WM_GETTEXT, sent|defwinproc|optional }, 254 { WM_ERASEBKGND, sent|optional }, 255 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOCLIENTMOVE }, 256 { WM_SIZE, sent|defwinproc|optional }, 257 { WM_NCCALCSIZE, sent|wparam|optional, TRUE }, 258 { WM_NCPAINT, sent|optional }, 259 { WM_GETTEXT, sent|defwinproc|optional }, 260 { WM_ERASEBKGND, sent|optional }, 261 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 262 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP sends a duplicate */ 263 { 0 } 264 }; 265 266 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE) 267 * for a visible popup window. 268 */ 269 static const struct message WmSWP_ResizePopupSeq[] = { 270 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE }, 271 { WM_GETMINMAXINFO, sent|defwinproc|optional }, /* Win9x */ 272 { WM_NCCALCSIZE, sent|wparam|optional, TRUE }, 273 { WM_NCPAINT, sent|optional }, 274 { WM_GETTEXT, sent|defwinproc|optional }, 275 { WM_ERASEBKGND, sent|optional }, 276 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOCLIENTMOVE }, 277 { WM_SIZE, sent|defwinproc|wparam|optional, SIZE_RESTORED }, 278 { WM_NCCALCSIZE, sent|wparam|optional, TRUE }, 279 { WM_NCPAINT, sent|optional }, 280 { WM_GETTEXT, sent|defwinproc|optional }, 281 { WM_ERASEBKGND, sent|optional }, 282 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 283 { 0 } 284 }; 285 286 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE) 287 * for a visible overlapped window. 288 */ 289 static const struct message WmSWP_MoveSeq[] = { 290 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOSIZE }, 291 { WM_NCPAINT, sent|optional }, 292 { WM_GETTEXT, sent|defwinproc|optional }, 293 { WM_ERASEBKGND, sent|optional }, 294 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOCLIENTSIZE }, 295 { WM_MOVE, sent|defwinproc|wparam, 0 }, 296 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 297 { 0 } 298 }; 299 /* Resize with SetWindowPos(SWP_NOZORDER) 300 * for a visible overlapped window 301 * SWP_NOZORDER is stripped by the logging code 302 */ 303 static const struct message WmSWP_ResizeNoZOrder[] = { 304 { WM_WINDOWPOSCHANGING, sent|wparam, /*SWP_NOZORDER|*/SWP_NOACTIVATE }, 305 { WM_GETMINMAXINFO, sent|defwinproc }, 306 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, 307 { WM_NCPAINT, sent|optional }, 308 { WM_GETTEXT, sent|defwinproc|optional }, 309 { WM_ERASEBKGND, sent|optional }, 310 { WM_WINDOWPOSCHANGED, sent|wparam|optional, /*SWP_NOZORDER|*/SWP_NOACTIVATE, 0, 311 SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOCLIENTSIZE }, 312 { WM_MOVE, sent|defwinproc|optional }, 313 { WM_SIZE, sent|defwinproc|optional }, 314 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* Win9x doesn't send it */ 315 { WM_NCPAINT, sent|optional }, /* Win9x doesn't send it */ 316 { WM_GETTEXT, sent|defwinproc|optional }, /* Win9x doesn't send it */ 317 { WM_ERASEBKGND, sent|optional }, /* Win9x doesn't send it */ 318 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 319 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 320 { 0 } 321 }; 322 323 /* Switch visible mdi children */ 324 static const struct message WmSwitchChild[] = { 325 /* Switch MDI child */ 326 { WM_MDIACTIVATE, sent },/* in the MDI client */ 327 { WM_WINDOWPOSCHANGING, sent|wparam,SWP_NOSIZE|SWP_NOMOVE },/* in the 1st MDI child */ 328 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 329 { WM_CHILDACTIVATE, sent },/* in the 1st MDI child */ 330 /* Deactivate 2nd MDI child */ 331 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 2nd MDI child */ 332 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 2nd MDI child */ 333 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 334 /* Preparing for maximize and maximize the 1st MDI child */ 335 { WM_GETMINMAXINFO, sent|defwinproc }, /* in the 1st MDI child */ 336 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_STATECHANGED }, /* in the 1st MDI child */ 337 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, /* in the 1st MDI child */ 338 { WM_CHILDACTIVATE, sent|defwinproc }, /* in the 1st MDI child */ 339 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, /* in the 1st MDI child */ 340 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, /* in the 1st MDI child */ 341 /* Lock redraw 2nd MDI child */ 342 { WM_SETREDRAW, sent|wparam|defwinproc, 0 }, /* in the 2nd MDI child */ 343 { HCBT_MINMAX, hook|lparam, 0, SW_NORMALNA }, 344 /* Restore 2nd MDI child */ 345 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_STATECHANGED },/* in the 2nd MDI child */ 346 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },/* in the 2nd MDI child */ 347 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, /* in the 2nd MDI child */ 348 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, /* in the 2nd MDI child */ 349 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, /* in the 2nd MDI child */ 350 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* in the 2nd MDI child */ 351 /* Redraw 2nd MDI child */ 352 { WM_SETREDRAW, sent|wparam|defwinproc, 1 },/* in the 2nd MDI child */ 353 /* Redraw MDI frame */ 354 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE },/* in MDI frame */ 355 { WM_NCCALCSIZE, sent|wparam, 1 },/* in MDI frame */ 356 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE}, /* in MDI frame */ 357 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* in MDI frame */ 358 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* in the 1st MDI child */ 359 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, /* in the 1st MDI child */ 360 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, /* in the 1st MDI child */ 361 { HCBT_SETFOCUS, hook }, 362 { WM_KILLFOCUS, sent|defwinproc }, /* in the 2nd MDI child */ 363 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 },/* in the 1st MDI child */ 364 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 365 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 366 { WM_SETFOCUS, sent },/* in the MDI client */ 367 { HCBT_SETFOCUS, hook }, 368 { WM_KILLFOCUS, sent },/* in the MDI client */ 369 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 370 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, /* in the 1st MDI child */ 371 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 372 { WM_SETFOCUS, sent|defwinproc }, /* in the 1st MDI child */ 373 { WM_MDIACTIVATE, sent|defwinproc },/* in the 1st MDI child */ 374 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, /* in the 1st MDI child */ 375 { 0 } 376 }; 377 378 /* Switch visible not maximized mdi children */ 379 static const struct message WmSwitchNotMaximizedChild[] = { 380 /* Switch not maximized MDI child */ 381 { WM_MDIACTIVATE, sent },/* in the MDI client */ 382 { WM_WINDOWPOSCHANGING, sent|wparam,SWP_NOSIZE|SWP_NOMOVE },/* in the 2nd MDI child */ 383 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 384 { WM_CHILDACTIVATE, sent },/* in the 2nd MDI child */ 385 /* Deactivate 1st MDI child */ 386 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 1st MDI child */ 387 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 1st MDI child */ 388 /* Activate 2nd MDI child */ 389 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE}, /* in the 2nd MDI child */ 390 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, /* in the 2nd MDI child */ 391 { HCBT_SETFOCUS, hook }, /* in the 1st MDI child */ 392 { WM_KILLFOCUS, sent|defwinproc }, /* in the 1st MDI child */ 393 { WM_IME_SETCONTEXT, sent|defwinproc|optional }, /* in the 1st MDI child */ 394 { WM_IME_SETCONTEXT, sent|optional }, /* in the MDI client */ 395 { WM_SETFOCUS, sent, 0 }, /* in the MDI client */ 396 { HCBT_SETFOCUS, hook }, 397 { WM_KILLFOCUS, sent }, /* in the MDI client */ 398 { WM_IME_SETCONTEXT, sent|optional }, /* in the MDI client */ 399 { WM_IME_SETCONTEXT, sent|defwinproc|optional }, /* in the 1st MDI child */ 400 { WM_SETFOCUS, sent|defwinproc }, /* in the 2nd MDI child */ 401 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 2nd MDI child */ 402 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE}, /* in the 2nd MDI child */ 403 { 0 } 404 }; 405 406 407 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE| 408 SWP_NOZORDER|SWP_FRAMECHANGED) 409 * for a visible overlapped window with WS_CLIPCHILDREN style set. 410 */ 411 static const struct message WmSWP_FrameChanged_clip[] = { 412 { WM_WINDOWPOSCHANGING, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED }, 413 { WM_NCCALCSIZE, sent|wparam|parent, 1 }, 414 { WM_NCPAINT, sent|parent|optional }, /* wparam != 1 */ 415 { WM_GETTEXT, sent|parent|defwinproc|optional }, 416 { WM_ERASEBKGND, sent|parent|optional }, /* FIXME: remove optional once Wine is fixed */ 417 { WM_NCPAINT, sent }, /* wparam != 1 */ 418 { WM_ERASEBKGND, sent }, 419 { WM_WINDOWPOSCHANGED, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 420 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 421 { WM_PAINT, sent }, 422 { 0 } 423 }; 424 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_DEFERERASE|SWP_NOACTIVATE| 425 SWP_NOZORDER|SWP_FRAMECHANGED) 426 * for a visible overlapped window. 427 */ 428 static const struct message WmSWP_FrameChangedDeferErase[] = { 429 { WM_WINDOWPOSCHANGING, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_DEFERERASE|SWP_NOACTIVATE|SWP_FRAMECHANGED }, 430 { WM_NCCALCSIZE, sent|wparam|parent, 1 }, 431 { WM_WINDOWPOSCHANGED, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_DEFERERASE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 432 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 433 { WM_PAINT, sent|parent|optional }, 434 { WM_NCPAINT, sent|beginpaint|parent|optional }, /* wparam != 1 */ 435 { WM_GETTEXT, sent|beginpaint|parent|defwinproc|optional }, 436 { WM_PAINT, sent }, 437 { WM_NCPAINT, sent|beginpaint }, /* wparam != 1 */ 438 { WM_ERASEBKGND, sent|beginpaint|optional }, 439 { 0 } 440 }; 441 442 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE| 443 SWP_NOZORDER|SWP_FRAMECHANGED) 444 * for a visible overlapped window without WS_CLIPCHILDREN style set. 445 */ 446 static const struct message WmSWP_FrameChanged_noclip[] = { 447 { WM_WINDOWPOSCHANGING, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED }, 448 { WM_NCCALCSIZE, sent|wparam|parent, 1 }, 449 { WM_NCPAINT, sent|parent|optional }, /* wparam != 1 */ 450 { WM_GETTEXT, sent|parent|defwinproc|optional }, 451 { WM_ERASEBKGND, sent|parent|optional }, 452 { WM_WINDOWPOSCHANGED, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 453 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 454 { WM_PAINT, sent }, 455 { WM_NCPAINT, sent|beginpaint }, /* wparam != 1 */ 456 { WM_ERASEBKGND, sent|beginpaint|optional }, 457 { 0 } 458 }; 459 460 /* ShowWindow(SW_SHOW) for a not visible overlapped window */ 461 static const struct message WmShowOverlappedSeq[] = { 462 { WM_SHOWWINDOW, sent|wparam, 1 }, 463 { WM_NCPAINT, sent|wparam|optional, 1 }, 464 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 465 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 466 { WM_NCPAINT, sent|wparam|optional, 1 }, 467 { WM_GETTEXT, sent|defwinproc|optional }, 468 { WM_ERASEBKGND, sent|optional }, 469 { HCBT_ACTIVATE, hook|optional }, 470 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 471 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 472 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 473 { WM_NCPAINT, sent|wparam|optional, 1 }, 474 { WM_ACTIVATEAPP, sent|wparam|optional, 1 }, 475 { WM_NCACTIVATE, sent|wparam|optional, 1 }, 476 { WM_GETTEXT, sent|defwinproc|optional }, 477 { WM_ACTIVATE, sent|wparam|optional, 1 }, 478 { HCBT_SETFOCUS, hook|optional }, 479 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 480 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 481 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 482 { WM_SETFOCUS, sent|wparam|defwinproc|optional, 0 }, 483 { WM_GETTEXT, sent|optional }, 484 { WM_NCPAINT, sent|wparam|optional, 1 }, 485 { WM_GETTEXT, sent|defwinproc|optional }, 486 { WM_ERASEBKGND, sent|optional }, 487 /* Win9x adds SWP_NOZORDER below */ 488 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 489 { WM_NCCALCSIZE, sent|optional }, 490 { WM_GETTEXT, sent|optional }, 491 { WM_NCPAINT, sent|optional }, 492 { WM_ERASEBKGND, sent|optional }, 493 { WM_SYNCPAINT, sent|optional }, 494 #if 0 /* CreateWindow/ShowWindow(SW_SHOW) also generates WM_SIZE/WM_MOVE 495 * messages. Does that mean that CreateWindow doesn't set initial 496 * window dimensions for overlapped windows? 497 */ 498 { WM_SIZE, sent }, 499 { WM_MOVE, sent }, 500 #endif 501 { WM_PAINT, sent|optional }, 502 { WM_NCPAINT, sent|beginpaint|optional }, 503 { 0 } 504 }; 505 /* ShowWindow(SW_SHOWMAXIMIZED) for a not visible overlapped window */ 506 static const struct message WmShowMaxOverlappedSeq[] = { 507 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 508 { WM_GETMINMAXINFO, sent }, 509 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_STATECHANGED }, 510 { WM_GETMINMAXINFO, sent|defwinproc }, 511 { WM_NCCALCSIZE, sent|wparam, TRUE }, 512 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 513 { HCBT_ACTIVATE, hook|optional }, 514 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 515 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 516 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 517 { WM_ACTIVATEAPP, sent|wparam|optional, 1 }, 518 { WM_NCACTIVATE, sent|wparam|optional, 1 }, 519 { WM_GETTEXT, sent|defwinproc|optional }, 520 { WM_ACTIVATE, sent|wparam|optional, 1 }, 521 { HCBT_SETFOCUS, hook|optional }, 522 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 523 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 524 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 525 { WM_SETFOCUS, sent|wparam|defwinproc|optional, 0 }, 526 { WM_GETTEXT, sent|optional }, 527 { WM_NCPAINT, sent|wparam|optional, 1 }, 528 { WM_GETTEXT, sent|defwinproc|optional }, 529 { WM_ERASEBKGND, sent|optional }, 530 /* Win9x adds SWP_NOZORDER below */ 531 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_STATECHANGED }, 532 { WM_MOVE, sent|defwinproc }, 533 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 534 { WM_GETTEXT, sent|optional }, 535 { WM_NCCALCSIZE, sent|optional }, 536 { WM_NCPAINT, sent|optional }, 537 { WM_ERASEBKGND, sent|optional }, 538 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 539 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 540 { WM_SYNCPAINT, sent|optional }, 541 { WM_GETTITLEBARINFOEX, sent|optional }, 542 { WM_PAINT, sent|optional }, 543 { WM_NCPAINT, sent|beginpaint|optional }, 544 { WM_ERASEBKGND, sent|beginpaint|optional }, 545 { 0 } 546 }; 547 /* ShowWindow(SW_RESTORE) for a not visible maximized overlapped window */ 548 static const struct message WmShowRestoreMaxOverlappedSeq[] = { 549 { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE }, 550 { WM_GETTEXT, sent|optional }, 551 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, 552 { WM_GETMINMAXINFO, sent|defwinproc }, 553 { WM_NCCALCSIZE, sent|wparam, TRUE }, 554 { WM_NCPAINT, sent|optional }, 555 { WM_GETTEXT, sent|defwinproc|optional }, 556 { WM_ERASEBKGND, sent|optional }, 557 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOMOVE }, 558 { WM_MOVE, sent|defwinproc|optional }, 559 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 560 { WM_NCCALCSIZE, sent|wparam|optional, TRUE }, 561 { WM_NCPAINT, sent|optional }, 562 { WM_ERASEBKGND, sent|optional }, 563 { WM_PAINT, sent|optional }, 564 { WM_GETTITLEBARINFOEX, sent|optional }, 565 { WM_NCPAINT, sent|beginpaint|optional }, 566 { WM_ERASEBKGND, sent|beginpaint|optional }, 567 { WM_SYNCPAINT, sent|optional }, 568 { 0 } 569 }; 570 /* ShowWindow(SW_RESTORE) for a not visible minimized overlapped window */ 571 static const struct message WmShowRestoreMinOverlappedSeq[] = { 572 { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE }, 573 { WM_QUERYOPEN, sent|optional }, 574 { WM_GETTEXT, sent|optional }, 575 { WM_NCACTIVATE, sent|wparam|optional, 1 }, 576 { WM_WINDOWPOSCHANGING, sent|optional }, /* SWP_NOSIZE|SWP_NOMOVE */ 577 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 578 { WM_NCCALCSIZE, sent|wparam|optional, TRUE }, 579 { WM_MOVE, sent|optional }, 580 { WM_SIZE, sent|wparam|optional, SIZE_RESTORED }, 581 { WM_GETTEXT, sent|optional }, 582 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_FRAMECHANGED|SWP_STATECHANGED|SWP_NOCOPYBITS }, 583 { WM_GETMINMAXINFO, sent|defwinproc|optional }, 584 { WM_NCCALCSIZE, sent|wparam|optional, TRUE }, 585 { HCBT_ACTIVATE, hook|optional }, 586 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 587 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 588 { WM_ACTIVATEAPP, sent|wparam|optional, 1 }, 589 { WM_NCACTIVATE, sent|wparam|optional, 1 }, 590 { WM_GETTEXT, sent|defwinproc|optional }, 591 { WM_ACTIVATE, sent|wparam|optional, 1 }, 592 { HCBT_SETFOCUS, hook|optional }, 593 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 594 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 595 { WM_SETFOCUS, sent|wparam|defwinproc|optional, 0 }, 596 { WM_GETTEXT, sent|optional }, 597 { WM_NCPAINT, sent|wparam|optional, 1 }, 598 { WM_GETTEXT, sent|defwinproc|optional }, 599 { WM_ERASEBKGND, sent }, 600 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_STATECHANGED|SWP_FRAMECHANGED|SWP_NOCOPYBITS }, 601 { WM_MOVE, sent|defwinproc }, 602 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 603 { HCBT_SETFOCUS, hook|optional }, 604 { WM_SETFOCUS, sent|wparam|optional, 0 }, 605 { WM_NCCALCSIZE, sent|wparam|optional, TRUE }, 606 { WM_NCPAINT, sent|wparam|optional, 1 }, 607 { WM_ERASEBKGND, sent|optional }, 608 { HCBT_SETFOCUS, hook|optional }, 609 { WM_SETFOCUS, sent|wparam|optional, 0 }, 610 { WM_ACTIVATE, sent|wparam, 1 }, 611 { WM_GETTEXT, sent|optional }, 612 { WM_PAINT, sent|optional }, 613 { WM_GETTITLEBARINFOEX, sent|optional }, 614 { WM_NCPAINT, sent|beginpaint|optional }, 615 { WM_ERASEBKGND, sent|beginpaint|optional }, 616 { 0 } 617 }; 618 /* ShowWindow(SW_SHOWMINIMIZED) for a not visible overlapped window */ 619 static const struct message WmShowMinOverlappedSeq[] = { 620 { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, 621 { HCBT_SETFOCUS, hook|optional }, 622 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 623 { WM_KILLFOCUS, sent|optional }, 624 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 625 { WM_IME_NOTIFY, sent|wparam|optional|defwinproc, 1 }, 626 { WM_GETTEXT, sent|optional }, 627 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOCOPYBITS|SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_STATECHANGED }, 628 { WM_GETMINMAXINFO, sent|defwinproc }, 629 { WM_NCCALCSIZE, sent|wparam, TRUE }, 630 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, 631 { WM_NCPAINT, sent|optional }, 632 { WM_GETTEXT, sent|defwinproc|optional }, 633 { WM_WINDOWPOSCHANGED, sent }, 634 { WM_MOVE, sent|defwinproc }, 635 { WM_SIZE, sent|defwinproc|wparam|lparam, SIZE_MINIMIZED, 0 }, 636 { WM_NCCALCSIZE, sent|optional }, 637 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 638 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 639 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 }, 640 { WM_NCACTIVATE, sent|wparam|optional, 0 }, 641 { WM_GETTEXT, sent|defwinproc|optional }, 642 { WM_ACTIVATE, sent|optional }, 643 { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, 644 645 /* Vista sometimes restores the window right away... */ 646 { WM_SYSCOMMAND, sent|optional|wparam, SC_RESTORE }, 647 { HCBT_SYSCOMMAND, hook|optional|wparam, SC_RESTORE }, 648 { HCBT_MINMAX, hook|optional|lparam, 0, SW_RESTORE }, 649 { WM_QUERYOPEN, sent|optional }, 650 { WM_WINDOWPOSCHANGING, sent|optional|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, 651 { WM_GETMINMAXINFO, sent|optional|defwinproc }, 652 { WM_NCCALCSIZE, sent|optional|wparam, TRUE }, 653 { HCBT_ACTIVATE, hook|optional }, 654 { WM_ACTIVATEAPP, sent|optional|wparam, 1 }, 655 { WM_NCACTIVATE, sent|optional }, 656 { WM_GETTEXT, sent|optional }, 657 { WM_ACTIVATE, sent|optional|wparam, 1 }, 658 { HCBT_SETFOCUS, hook|optional }, 659 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 660 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 661 { WM_SETFOCUS, sent|optional }, 662 { WM_NCPAINT, sent|optional }, 663 { WM_GETTEXT, sent|defwinproc|optional }, 664 { WM_ERASEBKGND, sent|optional }, 665 { WM_WINDOWPOSCHANGED, sent|optional|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, 666 { WM_MOVE, sent|defwinproc|optional }, 667 { WM_SIZE, sent|defwinproc|optional|wparam, SIZE_RESTORED }, 668 { WM_ACTIVATE, sent|optional|wparam, 1 }, 669 { WM_SYSCOMMAND, sent|optional|wparam, SC_RESTORE }, 670 { HCBT_SYSCOMMAND, hook|optional|wparam, SC_RESTORE }, 671 672 { WM_PAINT, sent|optional }, 673 { WM_NCPAINT, sent|beginpaint|optional }, 674 { WM_ERASEBKGND, sent|beginpaint|optional }, 675 { 0 } 676 }; 677 /* ShowWindow(SW_HIDE) for a visible overlapped window */ 678 static const struct message WmHideOverlappedSeq[] = { 679 { WM_SHOWWINDOW, sent|wparam, 0 }, 680 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 681 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 682 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 683 { WM_SIZE, sent|optional }, /* XP doesn't send it */ 684 { WM_MOVE, sent|optional }, /* XP doesn't send it */ 685 { WM_NCACTIVATE, sent|wparam|optional, 0 }, 686 { WM_ACTIVATE, sent|wparam|optional, 0 }, 687 { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, 688 { HCBT_SETFOCUS, hook|optional }, 689 { WM_KILLFOCUS, sent|wparam|optional, 0 }, 690 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 691 { WM_IME_NOTIFY, sent|wparam|optional|defwinproc, 1 }, 692 { 0 } 693 }; 694 /* DestroyWindow for a visible overlapped window */ 695 static const struct message WmDestroyOverlappedSeq[] = { 696 { HCBT_DESTROYWND, hook }, 697 { 0x0090, sent|optional }, 698 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 699 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 700 { 0x0090, sent|optional }, 701 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 702 { WM_NCACTIVATE, sent|optional|wparam, 0 }, 703 { WM_ACTIVATE, sent|optional }, 704 { WM_ACTIVATEAPP, sent|optional|wparam, 0 }, 705 { WM_KILLFOCUS, sent|optional|wparam, 0 }, 706 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 707 { WM_IME_NOTIFY, sent|wparam|optional|defwinproc, 1 }, 708 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, 709 { WM_DESTROY, sent }, 710 { WM_NCDESTROY, sent }, 711 { 0 } 712 }; 713 /* CreateWindow(WS_MAXIMIZE|WS_VISIBLE) for popup window */ 714 static const struct message WmCreateMaxPopupSeq[] = { 715 { HCBT_CREATEWND, hook }, 716 { WM_NCCREATE, sent }, 717 { WM_NCCALCSIZE, sent|wparam, 0 }, 718 { WM_CREATE, sent }, 719 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 720 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 721 { WM_MOVE, sent }, 722 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 723 { WM_GETMINMAXINFO, sent }, 724 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_STATECHANGED }, 725 { WM_NCCALCSIZE, sent|wparam, TRUE }, 726 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOREDRAW|SWP_STATECHANGED }, 727 { WM_MOVE, sent|defwinproc }, 728 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 729 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 730 { WM_SHOWWINDOW, sent|wparam, 1 }, 731 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 732 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 733 { HCBT_ACTIVATE, hook }, 734 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 735 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 736 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 737 { WM_NCPAINT, sent|wparam|optional, 1 }, 738 { WM_ERASEBKGND, sent|optional }, 739 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOCLIENTMOVE|SWP_NOCLIENTSIZE|SWP_NOMOVE|SWP_NOSIZE }, 740 { WM_ACTIVATEAPP, sent|wparam, 1 }, 741 { WM_NCACTIVATE, sent }, 742 { WM_ACTIVATE, sent|wparam, 1 }, 743 { HCBT_SETFOCUS, hook }, 744 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 745 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 746 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 747 { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, 748 { WM_GETTEXT, sent|optional }, 749 { WM_SYNCPAINT, sent|wparam|optional, 4 }, 750 { WM_NCPAINT, sent|wparam|optional, 1 }, 751 { WM_ERASEBKGND, sent|optional }, 752 { WM_NCPAINT, sent|wparam|defwinproc|optional, 1 }, 753 { WM_ERASEBKGND, sent|defwinproc|optional }, 754 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTMOVE|SWP_NOCLIENTSIZE|SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOSIZE }, 755 { 0 } 756 }; 757 /* CreateWindow(WS_MAXIMIZE) for popup window, not initially visible */ 758 static const struct message WmCreateInvisibleMaxPopupSeq[] = { 759 { HCBT_CREATEWND, hook }, 760 { WM_NCCREATE, sent }, 761 { WM_NCCALCSIZE, sent|wparam, 0 }, 762 { WM_CREATE, sent }, 763 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 764 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 765 { WM_MOVE, sent }, 766 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 767 { WM_GETMINMAXINFO, sent }, 768 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_STATECHANGED }, 769 { WM_NCCALCSIZE, sent|wparam, TRUE }, 770 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOREDRAW|SWP_STATECHANGED }, 771 { WM_MOVE, sent|defwinproc }, 772 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 773 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 774 { 0 } 775 }; 776 /* ShowWindow(SW_SHOWMAXIMIZED) for a resized not visible popup window */ 777 static const struct message WmShowMaxPopupResizedSeq[] = { 778 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 779 { WM_GETMINMAXINFO, sent }, 780 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED }, 781 { WM_NCCALCSIZE, sent|wparam, TRUE }, 782 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 783 { HCBT_ACTIVATE, hook }, 784 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 785 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 786 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 787 { WM_NCPAINT, sent|wparam|optional, 1 }, 788 { WM_ERASEBKGND, sent|optional }, 789 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 790 { WM_ACTIVATEAPP, sent|wparam, 1 }, 791 { WM_NCACTIVATE, sent }, 792 { WM_ACTIVATE, sent|wparam, 1 }, 793 { HCBT_SETFOCUS, hook }, 794 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 795 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 796 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 797 { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, 798 { WM_GETTEXT, sent|optional }, 799 { WM_NCPAINT, sent|wparam|optional, 1 }, 800 { WM_ERASEBKGND, sent|optional }, 801 { WM_WINDOWPOSCHANGED, sent }, 802 /* WinNT4.0 sends WM_MOVE */ 803 { WM_MOVE, sent|defwinproc|optional }, 804 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 805 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 806 { 0 } 807 }; 808 /* ShowWindow(SW_SHOWMAXIMIZED) for a not visible popup window */ 809 static const struct message WmShowMaxPopupSeq[] = { 810 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 811 { WM_GETMINMAXINFO, sent }, 812 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED }, 813 { WM_NCCALCSIZE, sent|wparam, TRUE }, 814 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 815 { HCBT_ACTIVATE, hook }, 816 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 817 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 818 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 819 { WM_NCPAINT, sent|wparam|optional, 1 }, 820 { WM_ERASEBKGND, sent|optional }, 821 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOMOVE|SWP_NOSIZE }, 822 { WM_ACTIVATEAPP, sent|wparam, 1 }, 823 { WM_NCACTIVATE, sent }, 824 { WM_ACTIVATE, sent|wparam, 1 }, 825 { HCBT_SETFOCUS, hook }, 826 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 827 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 828 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 829 { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, 830 { WM_GETTEXT, sent|optional }, 831 { WM_SYNCPAINT, sent|wparam|optional, 4 }, 832 { WM_NCPAINT, sent|wparam|optional, 1 }, 833 { WM_ERASEBKGND, sent|optional }, 834 { WM_NCPAINT, sent|wparam|defwinproc|optional, 1 }, 835 { WM_ERASEBKGND, sent|defwinproc|optional }, 836 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOSIZE }, 837 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 838 { WM_SIZE, sent|defwinproc|optional }, 839 { 0 } 840 }; 841 /* CreateWindow(WS_VISIBLE) for popup window */ 842 static const struct message WmCreatePopupSeq[] = { 843 { HCBT_CREATEWND, hook }, 844 { WM_NCCREATE, sent }, 845 { WM_NCCALCSIZE, sent|wparam, 0 }, 846 { WM_CREATE, sent }, 847 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 848 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 849 { WM_MOVE, sent }, 850 { WM_SHOWWINDOW, sent|wparam, 1 }, 851 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 852 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 853 { HCBT_ACTIVATE, hook }, 854 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 855 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 856 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 857 { WM_NCPAINT, sent|wparam|optional, 1 }, 858 { WM_ERASEBKGND, sent|optional }, 859 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 860 { WM_ACTIVATEAPP, sent|wparam, 1 }, 861 { WM_NCACTIVATE, sent }, 862 { WM_ACTIVATE, sent|wparam, 1 }, 863 { HCBT_SETFOCUS, hook }, 864 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 865 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 866 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 867 { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, 868 { WM_GETTEXT, sent|optional }, 869 { WM_SYNCPAINT, sent|wparam|optional, 4 }, 870 { WM_NCPAINT, sent|wparam|optional, 1 }, 871 { WM_ERASEBKGND, sent|optional }, 872 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTMOVE|SWP_NOCLIENTSIZE|SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOSIZE }, 873 { 0 } 874 }; 875 /* ShowWindow(SW_SHOWMAXIMIZED) for a visible popup window */ 876 static const struct message WmShowVisMaxPopupSeq[] = { 877 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 878 { WM_GETMINMAXINFO, sent }, 879 { WM_GETTEXT, sent|optional }, 880 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, 881 { WM_GETTEXT, sent|optional }, 882 { WM_NCCALCSIZE, sent|wparam, TRUE }, 883 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 884 { WM_NCPAINT, sent|wparam|optional, 1 }, 885 { WM_ERASEBKGND, sent|optional }, 886 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, 887 { WM_MOVE, sent|defwinproc }, 888 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 889 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 890 { 0 } 891 }; 892 /* CreateWindow (for a child popup window, not initially visible) */ 893 static const struct message WmCreateChildPopupSeq[] = { 894 { HCBT_CREATEWND, hook }, 895 { WM_NCCREATE, sent }, 896 { WM_NCCALCSIZE, sent|wparam, 0 }, 897 { WM_CREATE, sent }, 898 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 899 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 900 { WM_MOVE, sent }, 901 { 0 } 902 }; 903 /* CreateWindow (for a popup window, not initially visible, 904 * which sets WS_VISIBLE in WM_CREATE handler) 905 */ 906 static const struct message WmCreateInvisiblePopupSeq[] = { 907 { HCBT_CREATEWND, hook }, 908 { WM_NCCREATE, sent }, 909 { WM_NCCALCSIZE, sent|wparam, 0 }, 910 { WM_CREATE, sent }, 911 { WM_STYLECHANGING, sent }, 912 { WM_STYLECHANGED, sent }, 913 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 914 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 915 { WM_MOVE, sent }, 916 { 0 } 917 }; 918 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER) 919 * for a popup window with WS_VISIBLE style set 920 */ 921 static const struct message WmShowVisiblePopupSeq_2[] = { 922 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 923 { 0 } 924 }; 925 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE) 926 * for a popup window with WS_VISIBLE style set 927 */ 928 static const struct message WmShowVisiblePopupSeq_3[] = { 929 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 930 { HCBT_ACTIVATE, hook }, 931 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 932 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 933 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 934 { WM_NCACTIVATE, sent }, 935 { WM_ACTIVATE, sent|wparam, 1 }, 936 { HCBT_SETFOCUS, hook }, 937 { WM_KILLFOCUS, sent|parent }, 938 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, 939 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 940 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 941 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 942 { WM_SETFOCUS, sent|defwinproc }, 943 { WM_GETTEXT, sent|optional }, 944 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE, 0, SWP_SHOWWINDOW }, 945 { 0 } 946 }; 947 /* CreateWindow (for a popup window with WS_VISIBLE style set and extreme location) 948 */ 949 static const struct message WmShowPopupExtremeLocationSeq[] = { 950 { HCBT_CREATEWND, hook }, 951 { WM_NCCREATE, sent }, 952 { WM_NCCALCSIZE, sent|wparam, 0 }, 953 { WM_CREATE, sent }, 954 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 955 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 956 { WM_MOVE, sent }, 957 { WM_SHOWWINDOW, sent|wparam, 1 }, 958 { WM_WINDOWPOSCHANGING, sent }, 959 { HCBT_ACTIVATE, hook }, 960 { WM_WINDOWPOSCHANGING, sent|optional }, 961 { WM_QUERYNEWPALETTE, sent|optional }, 962 { WM_ACTIVATEAPP, sent }, 963 { WM_NCACTIVATE, sent }, 964 { WM_ACTIVATE, sent }, 965 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, 966 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 967 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 968 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 969 { HCBT_SETFOCUS, hook }, 970 { WM_SETFOCUS, sent|defwinproc }, 971 { WM_NCPAINT, sent|wparam, 1 }, 972 { WM_ERASEBKGND, sent }, 973 { WM_WINDOWPOSCHANGED, sent }, 974 /* occasionally received on test machines */ 975 { WM_NCPAINT, sent|optional }, 976 { WM_ERASEBKGND, sent|optional }, 977 { 0 } 978 }; 979 /* CreateWindow (for a popup window with WS_VISIBLE style set) 980 */ 981 static const struct message WmShowPopupFirstDrawSeq_1[] = { 982 { HCBT_CREATEWND, hook }, 983 { WM_NCCREATE, sent }, 984 { WM_NCCALCSIZE, sent|wparam, 0 }, 985 { WM_CREATE, sent }, 986 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 987 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 988 { WM_MOVE, sent }, 989 { WM_SHOWWINDOW, sent|wparam, 1 }, 990 { WM_WINDOWPOSCHANGING, sent }, 991 { HCBT_ACTIVATE, hook }, 992 { WM_WINDOWPOSCHANGING, sent|optional }, 993 { WM_QUERYNEWPALETTE, sent|optional }, 994 { WM_ACTIVATEAPP, sent }, 995 { WM_NCACTIVATE, sent }, 996 { WM_ACTIVATE, sent }, 997 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, 998 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 999 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 1000 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1001 { HCBT_SETFOCUS, hook }, 1002 { WM_SETFOCUS, sent|defwinproc }, 1003 { WM_NCPAINT, sent|wparam, 1 }, 1004 { WM_ERASEBKGND, sent }, 1005 { WM_WINDOWPOSCHANGED, sent }, 1006 { WM_PAINT, sent }, 1007 /* occasionally received on test machines */ 1008 { WM_NCPAINT, sent|beginpaint|optional }, 1009 { WM_ERASEBKGND, sent|beginpaint|optional }, 1010 { 0 } 1011 }; 1012 /* CreateWindow (for a popup window that is shown with ShowWindow(SW_SHOWMAXIMIZED)) 1013 */ 1014 static const struct message WmShowPopupFirstDrawSeq_2[] = { 1015 { HCBT_CREATEWND, hook }, 1016 { WM_NCCREATE, sent }, 1017 { WM_NCCALCSIZE, sent|wparam, 0 }, 1018 { WM_CREATE, sent }, 1019 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1020 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 1021 { WM_MOVE, sent }, 1022 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 1023 { WM_GETMINMAXINFO, sent }, 1024 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_STATECHANGED|SWP_SHOWWINDOW|SWP_FRAMECHANGED }, 1025 { WM_NCCALCSIZE, sent|wparam, TRUE }, 1026 { HCBT_ACTIVATE, hook }, 1027 { WM_WINDOWPOSCHANGING, sent|optional }, 1028 { WM_NCPAINT, sent|optional|wparam, 1 }, 1029 { WM_ERASEBKGND, sent|optional }, 1030 { WM_WINDOWPOSCHANGED, sent|optional }, 1031 { WM_QUERYNEWPALETTE, sent|optional }, 1032 { WM_ACTIVATEAPP, sent }, 1033 { WM_NCACTIVATE, sent }, 1034 { WM_ACTIVATE, sent }, 1035 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, 1036 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 1037 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 1038 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1039 { HCBT_SETFOCUS, hook }, 1040 { WM_SETFOCUS, sent|defwinproc }, 1041 { WM_NCPAINT, sent|wparam, 1 }, 1042 { WM_ERASEBKGND, sent }, 1043 { WM_WINDOWPOSCHANGED, sent|optional }, 1044 { WM_MOVE, sent|defwinproc }, 1045 { WM_SIZE, sent|defwinproc, 0 }, 1046 { WM_PAINT, sent}, 1047 /* occasionally received on test machines */ 1048 { WM_NCPAINT, sent|beginpaint|optional }, 1049 { WM_ERASEBKGND, sent|beginpaint|optional }, 1050 { 0 } 1051 }; 1052 static const struct message WmFirstDrawSetWindowPosSeq1[] = { 1053 { HCBT_CREATEWND, hook }, 1054 { WM_NCCREATE, sent }, 1055 { WM_NCCALCSIZE, sent|wparam, 0 }, 1056 { WM_CREATE, sent }, 1057 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1058 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 1059 { WM_MOVE, sent }, 1060 { WM_WINDOWPOSCHANGING, sent }, 1061 { HCBT_ACTIVATE, hook }, 1062 { WM_WINDOWPOSCHANGING, sent|optional }, 1063 { WM_QUERYNEWPALETTE, sent|optional }, 1064 { WM_ACTIVATEAPP, sent }, 1065 { WM_NCACTIVATE, sent }, 1066 { WM_ACTIVATE, sent }, 1067 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, 1068 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 1069 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 1070 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1071 { HCBT_SETFOCUS, hook }, 1072 { WM_SETFOCUS, sent|defwinproc }, 1073 { WM_NCPAINT, sent|wparam, 1 }, 1074 { WM_ERASEBKGND, sent }, 1075 { WM_WINDOWPOSCHANGED, sent }, 1076 { WM_MOVE, sent|defwinproc }, 1077 { 0 } 1078 }; 1079 static const struct message WmFirstDrawSetWindowPosSeq2[] = { 1080 { HCBT_CREATEWND, hook }, 1081 { WM_NCCREATE, sent }, 1082 { WM_NCCALCSIZE, sent|wparam, 0 }, 1083 { WM_CREATE, sent }, 1084 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1085 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 1086 { WM_MOVE, sent }, 1087 { WM_WINDOWPOSCHANGING, sent }, 1088 { HCBT_ACTIVATE, hook }, 1089 { WM_QUERYNEWPALETTE, sent|optional }, 1090 { WM_WINDOWPOSCHANGING, sent|optional }, 1091 { WM_ACTIVATEAPP, sent }, 1092 { WM_NCACTIVATE, sent }, 1093 { WM_ACTIVATE, sent }, 1094 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, 1095 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 1096 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 1097 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1098 { HCBT_SETFOCUS, hook }, 1099 { WM_SETFOCUS, sent|defwinproc }, 1100 { WM_WINDOWPOSCHANGED, sent }, 1101 { WM_MOVE, sent|defwinproc }, 1102 { 0 } 1103 }; 1104 static const struct message WmFirstDrawSetWindowPosSeq3[] = { 1105 { HCBT_CREATEWND, hook }, 1106 { WM_NCCREATE, sent }, 1107 { WM_NCCALCSIZE, sent|wparam, 0 }, 1108 { WM_CREATE, sent }, 1109 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1110 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 1111 { WM_MOVE, sent }, 1112 { HCBT_ACTIVATE, hook|optional }, 1113 /* Probably shouldn't happen, but not part of this test */ 1114 { WM_QUERYNEWPALETTE, sent|optional }, 1115 { WM_ACTIVATEAPP, sent|optional }, 1116 { WM_NCACTIVATE, sent|optional }, 1117 { WM_ACTIVATE, sent|optional }, 1118 { HCBT_SETFOCUS, hook|optional }, 1119 { WM_SETFOCUS, sent|defwinproc|optional }, 1120 { 0 } 1121 }; 1122 static const struct message WmFirstDrawSetWindowPosSeq4[] = { 1123 { HCBT_CREATEWND, hook }, 1124 { WM_NCCREATE, sent }, 1125 { WM_NCCALCSIZE, sent|wparam, 0 }, 1126 { WM_CREATE, sent }, 1127 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1128 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 1129 { WM_MOVE, sent }, 1130 { WM_WINDOWPOSCHANGING, sent }, 1131 { HCBT_ACTIVATE, hook }, 1132 { WM_WINDOWPOSCHANGING, sent|optional }, 1133 { WM_QUERYNEWPALETTE, sent|optional }, 1134 { WM_ACTIVATEAPP, sent }, 1135 { WM_NCACTIVATE, sent }, 1136 { WM_ACTIVATE, sent }, 1137 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, 1138 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 1139 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 1140 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1141 { HCBT_SETFOCUS, hook }, 1142 { WM_SETFOCUS, sent|defwinproc }, 1143 { WM_NCPAINT, sent|wparam, 1 }, 1144 { WM_ERASEBKGND, sent }, 1145 { WM_WINDOWPOSCHANGED, sent }, 1146 { 0 } 1147 }; 1148 static const struct message WmFirstDrawSetWindowPosSeq5[] = { 1149 { HCBT_CREATEWND, hook }, 1150 { WM_NCCREATE, sent }, 1151 { WM_NCCALCSIZE, sent|wparam, 0 }, 1152 { WM_CREATE, sent }, 1153 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1154 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 1155 { WM_MOVE, sent }, 1156 { WM_WINDOWPOSCHANGING, sent }, 1157 { HCBT_ACTIVATE, hook }, 1158 { WM_WINDOWPOSCHANGING, sent|optional }, 1159 { WM_QUERYNEWPALETTE, sent|optional }, 1160 { WM_ACTIVATEAPP, sent }, 1161 { WM_NCACTIVATE, sent }, 1162 { WM_ACTIVATE, sent }, 1163 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, 1164 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 1165 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 1166 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1167 { HCBT_SETFOCUS, hook }, 1168 { WM_SETFOCUS, sent|defwinproc }, 1169 { WM_WINDOWPOSCHANGED, sent }, 1170 { 0 } 1171 }; 1172 static const struct message WmFirstDrawChildSeq1[] = { 1173 { 0 } 1174 }; 1175 static const struct message WmFirstDrawChildSeq2[] = { 1176 { WM_NCPAINT, sent|wparam, 1 }, 1177 { WM_ERASEBKGND, sent }, 1178 /* occasionally received on test machines */ 1179 { WM_NCPAINT, sent|optional }, 1180 { WM_ERASEBKGND, sent|optional }, 1181 { 0 } 1182 }; 1183 /* CreateWindow (for child window, not initially visible) */ 1184 static const struct message WmCreateChildSeq[] = { 1185 { HCBT_CREATEWND, hook }, 1186 { WM_NCCREATE, sent }, 1187 /* child is inserted into parent's child list after WM_NCCREATE returns */ 1188 { WM_NCCALCSIZE, sent|wparam, 0 }, 1189 { WM_CREATE, sent }, 1190 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1191 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 1192 { WM_MOVE, sent }, 1193 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE }, 1194 { 0 } 1195 }; 1196 /* CreateWindow (for maximized child window, not initially visible) */ 1197 static const struct message WmCreateMaximizedChildSeq[] = { 1198 { HCBT_CREATEWND, hook }, 1199 { WM_NCCREATE, sent }, 1200 { WM_NCCALCSIZE, sent|wparam, 0 }, 1201 { WM_CREATE, sent }, 1202 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1203 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 1204 { WM_MOVE, sent }, 1205 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 1206 { WM_GETMINMAXINFO, sent }, 1207 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_STATECHANGED }, 1208 { WM_NCCALCSIZE, sent|wparam, 1 }, 1209 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 1210 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 1211 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1212 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE }, 1213 { 0 } 1214 }; 1215 /* CreateWindow (for a child window, initially visible) */ 1216 static const struct message WmCreateVisibleChildSeq[] = { 1217 { HCBT_CREATEWND, hook }, 1218 { WM_NCCREATE, sent }, 1219 /* child is inserted into parent's child list after WM_NCCREATE returns */ 1220 { WM_NCCALCSIZE, sent|wparam, 0 }, 1221 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, 1222 { WM_CREATE, sent }, 1223 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1224 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 1225 { WM_MOVE, sent }, 1226 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE }, 1227 { WM_SHOWWINDOW, sent|wparam, 1 }, 1228 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, 1229 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1230 { WM_ERASEBKGND, sent|parent|optional }, 1231 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1232 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* WinXP */ 1233 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1234 { 0 } 1235 }; 1236 /* ShowWindow(SW_SHOW) for a not visible child window */ 1237 static const struct message WmShowChildSeq[] = { 1238 { WM_SHOWWINDOW, sent|wparam, 1 }, 1239 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1240 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1241 { WM_ERASEBKGND, sent|parent|optional }, 1242 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1243 { 0 } 1244 }; 1245 /* ShowWindow(SW_HIDE) for a visible child window */ 1246 static const struct message WmHideChildSeq[] = { 1247 { WM_SHOWWINDOW, sent|wparam, 0 }, 1248 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1249 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 1250 { WM_ERASEBKGND, sent|parent|optional }, 1251 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1252 { 0 } 1253 }; 1254 /* ShowWindow(SW_HIDE) for a visible child window checking all parent events*/ 1255 static const struct message WmHideChildSeq2[] = { 1256 { WM_SHOWWINDOW, sent|wparam, 0 }, 1257 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1258 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 1259 { WM_ERASEBKGND, sent|parent|optional }, 1260 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1261 { 0 } 1262 }; 1263 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE) 1264 * for a not visible child window 1265 */ 1266 static const struct message WmShowChildSeq_2[] = { 1267 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 1268 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1269 { WM_CHILDACTIVATE, sent }, 1270 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1271 { 0 } 1272 }; 1273 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE) 1274 * for a not visible child window 1275 */ 1276 static const struct message WmShowChildSeq_3[] = { 1277 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, 1278 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1279 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1280 { 0 } 1281 }; 1282 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE) 1283 * for a visible child window with a caption 1284 */ 1285 static const struct message WmShowChildSeq_4[] = { 1286 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 1287 { WM_CHILDACTIVATE, sent }, 1288 { 0 } 1289 }; 1290 /* ShowWindow(SW_MINIMIZE) for child with invisible parent */ 1291 static const struct message WmShowChildInvisibleParentSeq_1[] = { 1292 { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, 1293 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE }, 1294 { WM_NCCALCSIZE, sent|wparam, 1 }, 1295 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1296 { WM_CHILDACTIVATE, sent|optional }, 1297 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOREDRAW|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE }, 1298 { WM_MOVE, sent|defwinproc }, 1299 { WM_SIZE, sent|defwinproc|wparam|lparam, SIZE_MINIMIZED, 0 }, 1300 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1301 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 }, 1302 /* FIXME: Wine creates an icon/title window while Windows doesn't */ 1303 { WM_PARENTNOTIFY, sent|parent|wparam|optional, WM_CREATE }, 1304 { WM_GETTEXT, sent|optional }, 1305 { 0 } 1306 }; 1307 /* repeated ShowWindow(SW_MINIMIZE) for child with invisible parent */ 1308 static const struct message WmShowChildInvisibleParentSeq_1r[] = { 1309 { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, 1310 { 0 } 1311 }; 1312 /* ShowWindow(SW_MAXIMIZE) for child with invisible parent */ 1313 static const struct message WmShowChildInvisibleParentSeq_2[] = { 1314 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 1315 { WM_GETMINMAXINFO, sent }, 1316 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_STATECHANGED }, 1317 { WM_NCCALCSIZE, sent|wparam, 1 }, 1318 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1319 { WM_CHILDACTIVATE, sent }, 1320 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 1321 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 1322 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1323 { 0 } 1324 }; 1325 /* repeated ShowWindow(SW_MAXIMIZE) for child with invisible parent */ 1326 static const struct message WmShowChildInvisibleParentSeq_2r[] = { 1327 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 1328 { 0 } 1329 }; 1330 /* ShowWindow(SW_SHOWMINIMIZED) for child with invisible parent */ 1331 static const struct message WmShowChildInvisibleParentSeq_3[] = { 1332 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINIMIZED }, 1333 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 1334 { WM_NCCALCSIZE, sent|wparam, 1 }, 1335 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1336 { WM_CHILDACTIVATE, sent }, 1337 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOREDRAW|SWP_NOCOPYBITS|SWP_STATECHANGED }, 1338 { WM_MOVE, sent|defwinproc }, 1339 { WM_SIZE, sent|defwinproc|wparam|lparam, SIZE_MINIMIZED, 0 }, 1340 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1341 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 }, 1342 /* FIXME: Wine creates an icon/title window while Windows doesn't */ 1343 { WM_PARENTNOTIFY, sent|parent|wparam|optional, WM_CREATE }, 1344 { WM_GETTEXT, sent|optional }, 1345 { 0 } 1346 }; 1347 /* repeated ShowWindow(SW_SHOWMINIMIZED) for child with invisible parent */ 1348 static const struct message WmShowChildInvisibleParentSeq_3r[] = { 1349 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINIMIZED }, 1350 { 0 } 1351 }; 1352 /* ShowWindow(SW_SHOWMINNOACTIVE) for child with invisible parent */ 1353 static const struct message WmShowChildInvisibleParentSeq_4[] = { 1354 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINNOACTIVE }, 1355 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_STATECHANGED }, 1356 { WM_NCCALCSIZE, sent|wparam, 1 }, 1357 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1358 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOCOPYBITS|SWP_STATECHANGED }, 1359 { WM_MOVE, sent|defwinproc }, 1360 { WM_SIZE, sent|defwinproc|wparam|lparam, SIZE_MINIMIZED, 0 }, 1361 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1362 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 }, 1363 /* FIXME: Wine creates an icon/title window while Windows doesn't */ 1364 { WM_PARENTNOTIFY, sent|parent|wparam|optional, WM_CREATE }, 1365 { WM_GETTEXT, sent|optional }, 1366 { 0 } 1367 }; 1368 /* repeated ShowWindow(SW_SHOWMINNOACTIVE) for child with invisible parent */ 1369 static const struct message WmShowChildInvisibleParentSeq_4r[] = { 1370 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINNOACTIVE }, 1371 { 0 } 1372 }; 1373 /* ShowWindow(SW_SHOW) for child with invisible parent */ 1374 static const struct message WmShowChildInvisibleParentSeq_5[] = { 1375 { WM_SHOWWINDOW, sent|wparam, 1 }, 1376 { 0 } 1377 }; 1378 /* ShowWindow(SW_HIDE) for child with invisible parent */ 1379 static const struct message WmHideChildInvisibleParentSeq[] = { 1380 { WM_SHOWWINDOW, sent|wparam, 0 }, 1381 { 0 } 1382 }; 1383 /* SetWindowPos(SWP_SHOWWINDOW) for child with invisible parent */ 1384 static const struct message WmShowChildInvisibleParentSeq_6[] = { 1385 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, 1386 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1387 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1388 { 0 } 1389 }; 1390 /* SetWindowPos(SWP_HIDEWINDOW) for child with invisible parent */ 1391 static const struct message WmHideChildInvisibleParentSeq_2[] = { 1392 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1393 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 1394 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1395 { 0 } 1396 }; 1397 /* DestroyWindow for a visible child window */ 1398 static const struct message WmDestroyChildSeq[] = { 1399 { HCBT_DESTROYWND, hook }, 1400 { 0x0090, sent|optional }, 1401 { WM_PARENTNOTIFY, sent|parent|wparam, WM_DESTROY }, 1402 { WM_SHOWWINDOW, sent|wparam, 0 }, 1403 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1404 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 1405 { WM_ERASEBKGND, sent|parent|optional }, 1406 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1407 { HCBT_SETFOCUS, hook }, /* set focus to a parent */ 1408 { WM_KILLFOCUS, sent }, 1409 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 1410 { WM_IME_SETCONTEXT, sent|wparam|parent|optional, 1 }, 1411 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1412 { WM_SETFOCUS, sent|parent }, 1413 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, 1414 { WM_DESTROY, sent }, 1415 { WM_DESTROY, sent|optional }, /* some other (IME?) window */ 1416 { WM_NCDESTROY, sent|optional }, /* some other (IME?) window */ 1417 { WM_NCDESTROY, sent }, 1418 { 0 } 1419 }; 1420 /* visible child window destroyed by thread exit */ 1421 static const struct message WmExitThreadSeq[] = { 1422 { WM_NCDESTROY, sent }, /* actually in grandchild */ 1423 { WM_PAINT, sent|parent }, 1424 { WM_ERASEBKGND, sent|parent|beginpaint }, 1425 { 0 } 1426 }; 1427 /* DestroyWindow for a visible child window with invisible parent */ 1428 static const struct message WmDestroyInvisibleChildSeq[] = { 1429 { HCBT_DESTROYWND, hook }, 1430 { 0x0090, sent|optional }, 1431 { WM_PARENTNOTIFY, sent|parent|wparam, WM_DESTROY }, 1432 { WM_SHOWWINDOW, sent|wparam, 0 }, 1433 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, 1434 { WM_DESTROY, sent }, 1435 { WM_NCDESTROY, sent }, 1436 { 0 } 1437 }; 1438 /* Resizing child window with MoveWindow (32) */ 1439 static const struct message WmResizingChildWithMoveWindowSeq[] = { 1440 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE }, 1441 { WM_NCCALCSIZE, sent|wparam, 1 }, 1442 { WM_ERASEBKGND, sent|parent|optional }, 1443 { WM_ERASEBKGND, sent|optional }, 1444 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE }, 1445 { WM_MOVE, sent|defwinproc }, 1446 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 1447 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1448 { 0 } 1449 }; 1450 /* Creation of a custom dialog (32) */ 1451 static const struct message WmCreateCustomDialogSeq[] = { 1452 { HCBT_CREATEWND, hook }, 1453 { WM_GETMINMAXINFO, sent }, 1454 { WM_NCCREATE, sent }, 1455 { WM_NCCALCSIZE, sent|wparam, 0 }, 1456 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, 1457 { WM_CREATE, sent }, 1458 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1459 { WM_NOTIFYFORMAT, sent|optional }, 1460 { WM_QUERYUISTATE, sent|optional }, 1461 { WM_WINDOWPOSCHANGING, sent|optional }, 1462 { WM_GETMINMAXINFO, sent|optional }, 1463 { WM_NCCALCSIZE, sent|optional }, 1464 { WM_WINDOWPOSCHANGED, sent|optional }, 1465 { WM_SHOWWINDOW, sent|wparam, 1 }, 1466 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 1467 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1468 { HCBT_ACTIVATE, hook }, 1469 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 1470 1471 1472 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 1473 1474 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 1475 1476 { WM_NCACTIVATE, sent }, 1477 { WM_GETTEXT, sent|optional|defwinproc }, 1478 { WM_GETTEXT, sent|optional|defwinproc }, 1479 { WM_GETTEXT, sent|optional|defwinproc }, 1480 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 }, 1481 { WM_ACTIVATE, sent|wparam, 1 }, 1482 { WM_GETTEXT, sent|optional }, 1483 { WM_KILLFOCUS, sent|parent }, 1484 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, 1485 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 1486 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 1487 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1488 { WM_SETFOCUS, sent }, 1489 { WM_GETDLGCODE, sent|defwinproc|wparam, 0 }, 1490 { WM_NCPAINT, sent|wparam, 1 }, 1491 { WM_GETTEXT, sent|optional|defwinproc }, 1492 { WM_GETTEXT, sent|optional|defwinproc }, 1493 { WM_ERASEBKGND, sent }, 1494 { WM_CTLCOLORDLG, sent|optional|defwinproc }, 1495 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1496 { WM_GETTEXT, sent|optional }, 1497 { WM_GETTEXT, sent|optional }, 1498 { WM_NCCALCSIZE, sent|optional }, 1499 { WM_NCPAINT, sent|optional }, 1500 { WM_GETTEXT, sent|optional|defwinproc }, 1501 { WM_GETTEXT, sent|optional|defwinproc }, 1502 { WM_ERASEBKGND, sent|optional }, 1503 { WM_CTLCOLORDLG, sent|optional|defwinproc }, 1504 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1505 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 1506 { WM_MOVE, sent }, 1507 { 0 } 1508 }; 1509 /* Calling EndDialog for a custom dialog (32) */ 1510 static const struct message WmEndCustomDialogSeq[] = { 1511 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1512 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 1513 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1514 { WM_GETTEXT, sent|optional }, 1515 { HCBT_ACTIVATE, hook }, 1516 { WM_NCACTIVATE, sent|wparam, 0 }, 1517 { WM_GETTEXT, sent|optional|defwinproc }, 1518 { WM_GETTEXT, sent|optional|defwinproc }, 1519 { WM_ACTIVATE, sent|wparam, 0 }, 1520 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 1521 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1522 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1523 { WM_GETTEXT, sent|optional|defwinproc }, 1524 { WM_GETTEXT, sent|optional|defwinproc }, 1525 { HCBT_SETFOCUS, hook }, 1526 { WM_KILLFOCUS, sent }, 1527 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 1528 { WM_IME_SETCONTEXT, sent|parent|wparam|defwinproc|optional, 1 }, 1529 { WM_IME_NOTIFY, sent|wparam|optional, 1 }, 1530 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1531 { WM_SETFOCUS, sent|parent|defwinproc }, 1532 { 0 } 1533 }; 1534 /* ShowWindow(SW_SHOW) for a custom dialog (initially invisible) */ 1535 static const struct message WmShowCustomDialogSeq[] = { 1536 { WM_SHOWWINDOW, sent|wparam, 1 }, 1537 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 1538 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1539 { HCBT_ACTIVATE, hook }, 1540 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 1541 1542 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 1543 1544 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 1545 { WM_ACTIVATEAPP, sent|wparam|optional, 1 }, 1546 { WM_NCACTIVATE, sent }, 1547 { WM_ACTIVATE, sent|wparam, 1 }, 1548 { WM_GETTEXT, sent|optional }, 1549 1550 { WM_KILLFOCUS, sent|parent }, 1551 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, 1552 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 1553 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 1554 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1555 { WM_SETFOCUS, sent }, 1556 { WM_GETDLGCODE, sent|defwinproc|wparam, 0 }, 1557 { WM_NCPAINT, sent|wparam, 1 }, 1558 { WM_ERASEBKGND, sent }, 1559 { WM_CTLCOLORDLG, sent|defwinproc }, 1560 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1561 { 0 } 1562 }; 1563 /* Creation and destruction of a modal dialog (32) */ 1564 static const struct message WmModalDialogSeq[] = { 1565 { WM_CANCELMODE, sent|parent }, 1566 { HCBT_SETFOCUS, hook }, 1567 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1568 { WM_KILLFOCUS, sent|parent }, 1569 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, 1570 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1571 { WM_ENABLE, sent|parent|wparam, 0 }, 1572 { HCBT_CREATEWND, hook }, 1573 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, 1574 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1575 { WM_SETFONT, sent }, 1576 { WM_INITDIALOG, sent }, 1577 { WM_CHANGEUISTATE, sent|optional }, 1578 { WM_UPDATEUISTATE, sent|optional }, 1579 { WM_SHOWWINDOW, sent }, 1580 { HCBT_ACTIVATE, hook }, 1581 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 1582 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 1583 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE }, 1584 { WM_NCACTIVATE, sent }, 1585 { WM_GETTEXT, sent|optional }, 1586 { WM_ACTIVATE, sent|wparam, 1 }, 1587 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, 1588 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1589 { WM_NCPAINT, sent|optional }, 1590 { WM_GETTEXT, sent|optional }, 1591 { WM_ERASEBKGND, sent|optional }, 1592 { WM_CTLCOLORDLG, sent|optional }, 1593 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1594 { WM_GETTEXT, sent|optional }, 1595 { WM_NCCALCSIZE, sent|optional }, 1596 { WM_NCPAINT, sent|optional }, 1597 { WM_GETTEXT, sent|optional }, 1598 { WM_ERASEBKGND, sent|optional }, 1599 { WM_CTLCOLORDLG, sent|optional }, 1600 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1601 { WM_PAINT, sent|optional }, 1602 { WM_CTLCOLORBTN, sent|optional }, 1603 { WM_GETTITLEBARINFOEX, sent|optional }, 1604 { WM_ENTERIDLE, sent|parent|optional }, 1605 { WM_ENTERIDLE, sent|parent|optional }, 1606 { WM_ENTERIDLE, sent|parent|optional }, 1607 { WM_ENTERIDLE, sent|parent|optional }, 1608 { WM_ENTERIDLE, sent|parent|optional }, 1609 { WM_ENTERIDLE, sent|parent|optional }, 1610 { WM_ENTERIDLE, sent|parent|optional }, 1611 { WM_ENTERIDLE, sent|parent|optional }, 1612 { WM_ENTERIDLE, sent|parent|optional }, 1613 { WM_ENTERIDLE, sent|parent|optional }, 1614 { WM_ENTERIDLE, sent|parent|optional }, 1615 { WM_ENTERIDLE, sent|parent|optional }, 1616 { WM_ENTERIDLE, sent|parent|optional }, 1617 { WM_ENTERIDLE, sent|parent|optional }, 1618 { WM_ENTERIDLE, sent|parent|optional }, 1619 { WM_ENTERIDLE, sent|parent|optional }, 1620 { WM_ENTERIDLE, sent|parent|optional }, 1621 { WM_ENTERIDLE, sent|parent|optional }, 1622 { WM_ENTERIDLE, sent|parent|optional }, 1623 { WM_ENTERIDLE, sent|parent|optional }, 1624 { WM_TIMER, sent }, 1625 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1626 { WM_ENABLE, sent|parent|wparam, 1 }, 1627 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, 1628 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 1629 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1630 { WM_GETTEXT, sent|optional }, 1631 { HCBT_ACTIVATE, hook }, 1632 { WM_NCACTIVATE, sent|wparam, 0 }, 1633 { WM_GETTEXT, sent|optional }, 1634 { WM_ACTIVATE, sent|wparam, 0 }, 1635 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 1636 { WM_WINDOWPOSCHANGING, sent|optional }, 1637 { WM_WINDOWPOSCHANGED, sent|optional }, 1638 { HCBT_SETFOCUS, hook }, 1639 { WM_IME_SETCONTEXT, sent|parent|wparam|defwinproc|optional, 1 }, 1640 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1641 { WM_SETFOCUS, sent|parent|defwinproc }, 1642 { EVENT_SYSTEM_DIALOGEND, winevent_hook|wparam|lparam, 0, 0 }, 1643 { HCBT_DESTROYWND, hook }, 1644 { 0x0090, sent|optional }, 1645 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, 1646 { WM_DESTROY, sent }, 1647 { WM_NCDESTROY, sent }, 1648 { 0 } 1649 }; 1650 static const struct message WmModalDialogSeq_2[] = { 1651 { WM_CANCELMODE, sent }, 1652 { HCBT_SETFOCUS, hook }, 1653 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1654 { WM_KILLFOCUS, sent }, 1655 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, 1656 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1657 { WM_ENABLE, sent|wparam, 0 }, 1658 { HCBT_CREATEWND, hook }, 1659 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, 1660 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1661 { WM_SETFONT, sent }, 1662 { WM_INITDIALOG, sent }, 1663 { WM_CHANGEUISTATE, sent|optional }, 1664 { WM_UPDATEUISTATE, sent|optional }, 1665 { WM_ENABLE, sent|wparam, 1 }, 1666 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, 1667 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 1668 { WM_CHANGEUISTATE, sent|optional }, 1669 { WM_UPDATEUISTATE, sent|optional }, 1670 { HCBT_DESTROYWND, hook }, 1671 { 0x0090, sent|optional }, 1672 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, 1673 { WM_DESTROY, sent }, 1674 { WM_NCDESTROY, sent }, 1675 { 0 } 1676 }; 1677 /* SetMenu for NonVisible windows with size change*/ 1678 static const struct message WmSetMenuNonVisibleSizeChangeSeq[] = { 1679 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1680 { WM_NCCALCSIZE, sent|wparam, 1 }, 1681 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, 1682 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW }, 1683 { WM_MOVE, sent|defwinproc }, 1684 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 1685 { WM_NCCALCSIZE,sent|wparam|optional, 1 }, /* XP */ 1686 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1687 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP sends a duplicate */ 1688 { WM_GETTEXT, sent|optional }, 1689 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, 1690 { 0 } 1691 }; 1692 /* SetMenu for NonVisible windows with no size change */ 1693 static const struct message WmSetMenuNonVisibleNoSizeChangeSeq[] = { 1694 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1695 { WM_NCCALCSIZE, sent|wparam, 1 }, 1696 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1697 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1698 { 0 } 1699 }; 1700 /* SetMenu for Visible windows with size change */ 1701 static const struct message WmSetMenuVisibleSizeChangeSeq[] = { 1702 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1703 { WM_NCCALCSIZE, sent|wparam, 1 }, 1704 { 0x0093, sent|defwinproc|optional }, 1705 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, 1706 { WM_NCPAINT, sent|optional }, /* wparam != 1 */ 1707 { 0x0093, sent|defwinproc|optional }, 1708 { 0x0093, sent|defwinproc|optional }, 1709 { 0x0091, sent|defwinproc|optional }, 1710 { 0x0092, sent|defwinproc|optional }, 1711 { WM_GETTEXT, sent|defwinproc|optional }, 1712 { WM_ERASEBKGND, sent|optional }, 1713 { WM_ACTIVATE, sent|optional }, 1714 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1715 { WM_MOVE, sent|defwinproc }, 1716 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 1717 { 0x0093, sent|optional }, 1718 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, 1719 { 0x0093, sent|defwinproc|optional }, 1720 { WM_NCPAINT, sent|optional }, /* wparam != 1 */ 1721 { 0x0093, sent|defwinproc|optional }, 1722 { 0x0093, sent|defwinproc|optional }, 1723 { 0x0091, sent|defwinproc|optional }, 1724 { 0x0092, sent|defwinproc|optional }, 1725 { WM_ERASEBKGND, sent|optional }, 1726 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1727 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP sends a duplicate */ 1728 { 0 } 1729 }; 1730 /* SetMenu for Visible windows with no size change */ 1731 static const struct message WmSetMenuVisibleNoSizeChangeSeq[] = { 1732 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1733 { WM_NCCALCSIZE, sent|wparam, 1 }, 1734 { WM_NCPAINT, sent|optional }, /* wparam != 1 */ 1735 { WM_GETTEXT, sent|defwinproc|optional }, 1736 { WM_ERASEBKGND, sent|optional }, 1737 { WM_ACTIVATE, sent|optional }, 1738 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1739 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1740 { 0 } 1741 }; 1742 /* DrawMenuBar for a visible window */ 1743 static const struct message WmDrawMenuBarSeq[] = 1744 { 1745 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1746 { WM_NCCALCSIZE, sent|wparam, 1 }, 1747 { 0x0093, sent|defwinproc|optional }, 1748 { WM_NCPAINT, sent|optional }, /* wparam != 1 */ 1749 { 0x0093, sent|defwinproc|optional }, 1750 { 0x0093, sent|defwinproc|optional }, 1751 { 0x0091, sent|defwinproc|optional }, 1752 { 0x0092, sent|defwinproc|optional }, 1753 { WM_GETTEXT, sent|defwinproc|optional }, 1754 { WM_ERASEBKGND, sent|optional }, 1755 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1756 { 0x0093, sent|optional }, 1757 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1758 { 0 } 1759 }; 1760 1761 static const struct message WmSetRedrawFalseSeq[] = 1762 { 1763 { WM_SETREDRAW, sent|wparam, 0 }, 1764 { 0 } 1765 }; 1766 1767 static const struct message WmSetRedrawTrueSeq[] = 1768 { 1769 { WM_SETREDRAW, sent|wparam, 1 }, 1770 { 0 } 1771 }; 1772 1773 static const struct message WmEnableWindowSeq_1[] = 1774 { 1775 { WM_CANCELMODE, sent|wparam|lparam, 0, 0 }, 1776 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1777 { HCBT_SETFOCUS, hook|optional }, 1778 { WM_KILLFOCUS, sent|optional }, 1779 { WM_ENABLE, sent|wparam|lparam, FALSE, 0 }, 1780 { 0 } 1781 }; 1782 1783 static const struct message WmEnableWindowSeq_2[] = 1784 { 1785 { WM_CANCELMODE, sent|wparam|lparam, 0, 0 }, 1786 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1787 { 0 } 1788 }; 1789 1790 static const struct message WmEnableWindowSeq_3[] = 1791 { 1792 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1793 { WM_ENABLE, sent|wparam|lparam, TRUE, 0 }, 1794 { 0 } 1795 }; 1796 1797 static const struct message WmEnableWindowSeq_4[] = 1798 { 1799 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1800 { 0 } 1801 }; 1802 1803 static const struct message WmGetScrollRangeSeq[] = 1804 { 1805 { SBM_GETRANGE, sent }, 1806 { 0 } 1807 }; 1808 static const struct message WmGetScrollInfoSeq[] = 1809 { 1810 { SBM_GETSCROLLINFO, sent }, 1811 { 0 } 1812 }; 1813 static const struct message WmSetScrollRangeSeq[] = 1814 { 1815 /* MSDN claims that Windows sends SBM_SETRANGE message, but win2k SP4 1816 sends SBM_SETSCROLLINFO. 1817 */ 1818 { SBM_SETSCROLLINFO, sent }, 1819 { 0 } 1820 }; 1821 /* SetScrollRange for a window without a non-client area */ 1822 static const struct message WmSetScrollRangeHSeq_empty[] = 1823 { 1824 { EVENT_OBJECT_VALUECHANGE, winevent_hook|wparam|lparam, OBJID_HSCROLL, 0 }, 1825 { 0 } 1826 }; 1827 static const struct message WmSetScrollRangeVSeq_empty[] = 1828 { 1829 { EVENT_OBJECT_VALUECHANGE, winevent_hook|wparam|lparam, OBJID_VSCROLL, 0 }, 1830 { 0 } 1831 }; 1832 static const struct message WmSetScrollRangeHVSeq[] = 1833 { 1834 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE }, 1835 { WM_NCCALCSIZE, sent|wparam, 1 }, 1836 { WM_GETTEXT, sent|defwinproc|optional }, 1837 { WM_ERASEBKGND, sent|optional }, 1838 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1839 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1840 { EVENT_OBJECT_VALUECHANGE, winevent_hook|lparam|optional, 0/*OBJID_HSCROLL or OBJID_VSCROLL*/, 0 }, 1841 { 0 } 1842 }; 1843 /* SetScrollRange for a window with a non-client area */ 1844 static const struct message WmSetScrollRangeHV_NC_Seq[] = 1845 { 1846 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE }, 1847 { WM_NCCALCSIZE, sent|wparam, 1 }, 1848 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, 1849 { WM_NCPAINT, sent|optional }, 1850 { WM_STYLECHANGING, sent|defwinproc|optional }, 1851 { WM_STYLECHANGED, sent|defwinproc|optional }, 1852 { WM_STYLECHANGING, sent|defwinproc|optional }, 1853 { WM_STYLECHANGED, sent|defwinproc|optional }, 1854 { WM_STYLECHANGING, sent|defwinproc|optional }, 1855 { WM_STYLECHANGED, sent|defwinproc|optional }, 1856 { WM_STYLECHANGING, sent|defwinproc|optional }, 1857 { WM_STYLECHANGED, sent|defwinproc|optional }, 1858 { WM_GETTEXT, sent|defwinproc|optional }, 1859 { WM_GETTEXT, sent|defwinproc|optional }, 1860 { WM_ERASEBKGND, sent|optional }, 1861 { WM_CTLCOLORDLG, sent|defwinproc|optional }, /* sent to a parent of the dialog */ 1862 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOCLIENTMOVE, 0, SWP_NOCLIENTSIZE }, 1863 { WM_SIZE, sent|defwinproc|optional }, 1864 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1865 { EVENT_OBJECT_VALUECHANGE, winevent_hook|lparam|optional, 0/*OBJID_HSCROLL or OBJID_VSCROLL*/, 0 }, 1866 { WM_GETTEXT, sent|optional }, 1867 { WM_GETTEXT, sent|optional }, 1868 { WM_GETTEXT, sent|optional }, 1869 { WM_GETTEXT, sent|optional }, 1870 { 0 } 1871 }; 1872 /* test if we receive the right sequence of messages */ 1873 /* after calling ShowWindow( SW_SHOWNA) */ 1874 static const struct message WmSHOWNAChildInvisParInvis[] = { 1875 { WM_SHOWWINDOW, sent|wparam, 1 }, 1876 { 0 } 1877 }; 1878 static const struct message WmSHOWNAChildVisParInvis[] = { 1879 { WM_SHOWWINDOW, sent|wparam, 1 }, 1880 { 0 } 1881 }; 1882 static const struct message WmSHOWNAChildVisParVis[] = { 1883 { WM_SHOWWINDOW, sent|wparam, 1 }, 1884 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, 1885 { 0 } 1886 }; 1887 static const struct message WmSHOWNAChildInvisParVis[] = { 1888 { WM_SHOWWINDOW, sent|wparam, 1 }, 1889 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1890 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1891 { WM_ERASEBKGND, sent|optional }, 1892 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOACTIVATE|SWP_NOCLIENTMOVE }, 1893 { 0 } 1894 }; 1895 static const struct message WmSHOWNATopVisible[] = { 1896 { WM_SHOWWINDOW, sent|wparam, 1 }, 1897 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, 1898 { WM_NCPAINT, sent|wparam|optional, 1 }, 1899 { WM_GETTEXT, sent|defwinproc|optional }, 1900 { WM_ERASEBKGND, sent|optional }, 1901 { WM_WINDOWPOSCHANGED, sent|optional }, 1902 { 0 } 1903 }; 1904 static const struct message WmSHOWNATopInvisible[] = { 1905 { WM_NOTIFYFORMAT, sent|optional }, 1906 { WM_QUERYUISTATE, sent|optional }, 1907 { WM_WINDOWPOSCHANGING, sent|optional }, 1908 { WM_GETMINMAXINFO, sent|optional }, 1909 { WM_NCCALCSIZE, sent|optional }, 1910 { WM_WINDOWPOSCHANGED, sent|optional }, 1911 { WM_SHOWWINDOW, sent|wparam, 1 }, 1912 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1913 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1914 { WM_NCPAINT, sent|wparam|optional, 1 }, 1915 { WM_GETTEXT, sent|defwinproc|optional }, 1916 { WM_ERASEBKGND, sent|optional }, 1917 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1918 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, 1919 { WM_NCPAINT, sent|wparam|optional, 1 }, 1920 { WM_ERASEBKGND, sent|optional }, 1921 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1922 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 1923 { WM_MOVE, sent }, 1924 { 0 } 1925 }; 1926 1927 static const struct message WmTrackPopupMenu[] = { 1928 { HCBT_CREATEWND, hook }, 1929 { WM_ENTERMENULOOP, sent|wparam|lparam, TRUE, 0 }, 1930 { WM_INITMENU, sent|lparam, 0, 0 }, 1931 { WM_INITMENUPOPUP, sent|lparam, 0, 0 }, 1932 { 0x0093, sent|optional }, 1933 { 0x0094, sent|optional }, 1934 { 0x0094, sent|optional }, 1935 { WM_ENTERIDLE, sent|wparam, 2 }, 1936 { WM_CAPTURECHANGED, sent }, 1937 { HCBT_DESTROYWND, hook }, 1938 { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, 1939 { WM_MENUSELECT, sent|wparam|lparam, 0xffff0000, 0 }, 1940 { WM_EXITMENULOOP, sent|wparam|lparam, 1, 0 }, 1941 { 0 } 1942 }; 1943 1944 static const struct message WmTrackPopupMenuEsc[] = { 1945 { 0 } 1946 }; 1947 1948 static const struct message WmTrackPopupMenuCapture[] = { 1949 { HCBT_CREATEWND, hook }, 1950 { WM_ENTERMENULOOP, sent|wparam|lparam, TRUE, 0 }, 1951 { WM_CAPTURECHANGED, sent }, 1952 { WM_INITMENU, sent|lparam, 0, 0 }, 1953 { WM_INITMENUPOPUP, sent|lparam, 0, 0 }, 1954 { 0x0093, sent|optional }, 1955 { 0x0094, sent|optional }, 1956 { 0x0094, sent|optional }, 1957 { WM_ENTERIDLE, sent|wparam, 2 }, 1958 { WM_CAPTURECHANGED, sent }, 1959 { HCBT_DESTROYWND, hook }, 1960 { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, 1961 { WM_MENUSELECT, sent|wparam|lparam, 0xffff0000, 0 }, 1962 { WM_EXITMENULOOP, sent|wparam|lparam, 1, 0 }, 1963 { 0 } 1964 }; 1965 1966 static const struct message WmTrackPopupMenuEmpty[] = { 1967 { HCBT_CREATEWND, hook }, 1968 { WM_ENTERMENULOOP, sent|wparam|lparam, TRUE, 0 }, 1969 { WM_INITMENU, sent|lparam, 0, 0 }, 1970 { WM_INITMENUPOPUP, sent|lparam, 0, 0 }, 1971 { 0x0093, sent|optional }, 1972 { 0x0094, sent|optional }, 1973 { 0x0094, sent|optional }, 1974 { WM_CAPTURECHANGED, sent }, 1975 { WM_EXITMENULOOP, sent|wparam|lparam, 1, 0 }, 1976 { HCBT_DESTROYWND, hook }, 1977 { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, 1978 { 0 } 1979 }; 1980 1981 static const struct message WmTrackPopupMenuAbort[] = { 1982 { HCBT_CREATEWND, hook }, 1983 { WM_ENTERMENULOOP, sent|wparam|lparam, TRUE, 0 }, 1984 { WM_INITMENU, sent|lparam, 0, 0 }, 1985 { WM_INITMENUPOPUP, sent|lparam, 0, 0 }, 1986 { 0x0093, sent|optional }, 1987 { 0x0094, sent|optional }, 1988 { 0x0094, sent|optional }, 1989 { WM_CAPTURECHANGED, sent }, 1990 { HCBT_DESTROYWND, hook }, 1991 { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, 1992 { WM_MENUSELECT, sent|wparam|lparam, 0xffff0000, 0 }, 1993 { WM_EXITMENULOOP, sent|wparam|lparam, 1, 0 }, 1994 { 0 } 1995 }; 1996 1997 static BOOL after_end_dialog, test_def_id, paint_loop_done; 1998 static int sequence_cnt, sequence_size; 1999 static struct recvd_message* sequence; 2000 static int log_all_parent_messages; 2001 static CRITICAL_SECTION sequence_cs; 2002 2003 /* user32 functions */ 2004 static HWND (WINAPI *pGetAncestor)(HWND,UINT); 2005 static BOOL (WINAPI *pGetMenuInfo)(HMENU,LPCMENUINFO); 2006 static void (WINAPI *pNotifyWinEvent)(DWORD, HWND, LONG, LONG); 2007 static BOOL (WINAPI *pSetMenuInfo)(HMENU,LPCMENUINFO); 2008 static HWINEVENTHOOK (WINAPI *pSetWinEventHook)(DWORD, DWORD, HMODULE, WINEVENTPROC, DWORD, DWORD, DWORD); 2009 static BOOL (WINAPI *pTrackMouseEvent)(TRACKMOUSEEVENT*); 2010 static BOOL (WINAPI *pUnhookWinEvent)(HWINEVENTHOOK); 2011 static BOOL (WINAPI *pGetMonitorInfoA)(HMONITOR,LPMONITORINFO); 2012 static HMONITOR (WINAPI *pMonitorFromPoint)(POINT,DWORD); 2013 static BOOL (WINAPI *pUpdateLayeredWindow)(HWND,HDC,POINT*,SIZE*,HDC,POINT*,COLORREF,BLENDFUNCTION*,DWORD); 2014 static UINT_PTR (WINAPI *pSetSystemTimer)(HWND, UINT_PTR, UINT, TIMERPROC); 2015 static UINT_PTR (WINAPI *pKillSystemTimer)(HWND, UINT_PTR); 2016 static UINT_PTR (WINAPI *pSetCoalescableTimer)(HWND, UINT_PTR, UINT, TIMERPROC, ULONG); 2017 /* kernel32 functions */ 2018 static BOOL (WINAPI *pGetCPInfoExA)(UINT, DWORD, LPCPINFOEXA); 2019 2020 static void init_procs(void) 2021 { 2022 HMODULE user32 = GetModuleHandleA("user32.dll"); 2023 HMODULE kernel32 = GetModuleHandleA("kernel32.dll"); 2024 2025 #define GET_PROC(dll, func) \ 2026 p ## func = (void*)GetProcAddress(dll, #func); \ 2027 if(!p ## func) { \ 2028 trace("GetProcAddress(%s) failed\n", #func); \ 2029 } 2030 2031 GET_PROC(user32, GetAncestor) 2032 GET_PROC(user32, GetMenuInfo) 2033 GET_PROC(user32, NotifyWinEvent) 2034 GET_PROC(user32, SetMenuInfo) 2035 GET_PROC(user32, SetWinEventHook) 2036 GET_PROC(user32, TrackMouseEvent) 2037 GET_PROC(user32, UnhookWinEvent) 2038 GET_PROC(user32, GetMonitorInfoA) 2039 GET_PROC(user32, MonitorFromPoint) 2040 GET_PROC(user32, UpdateLayeredWindow) 2041 GET_PROC(user32, SetSystemTimer) 2042 GET_PROC(user32, KillSystemTimer) 2043 GET_PROC(user32, SetCoalescableTimer) 2044 2045 GET_PROC(kernel32, GetCPInfoExA) 2046 2047 #undef GET_PROC 2048 } 2049 2050 static const char *get_winpos_flags(UINT flags) 2051 { 2052 static char buffer[300]; 2053 2054 buffer[0] = 0; 2055 #define DUMP(flag) do { if (flags & flag) { strcat( buffer, "|" #flag ); flags &= ~flag; } } while(0) 2056 DUMP( SWP_SHOWWINDOW ); 2057 DUMP( SWP_HIDEWINDOW ); 2058 DUMP( SWP_NOACTIVATE ); 2059 DUMP( SWP_FRAMECHANGED ); 2060 DUMP( SWP_NOCOPYBITS ); 2061 DUMP( SWP_NOOWNERZORDER ); 2062 DUMP( SWP_NOSENDCHANGING ); 2063 DUMP( SWP_DEFERERASE ); 2064 DUMP( SWP_ASYNCWINDOWPOS ); 2065 DUMP( SWP_NOZORDER ); 2066 DUMP( SWP_NOREDRAW ); 2067 DUMP( SWP_NOSIZE ); 2068 DUMP( SWP_NOMOVE ); 2069 DUMP( SWP_NOCLIENTSIZE ); 2070 DUMP( SWP_NOCLIENTMOVE ); 2071 if (flags) sprintf(buffer + strlen(buffer),"|0x%04x", flags); 2072 return buffer + 1; 2073 #undef DUMP 2074 } 2075 2076 static BOOL ignore_message( UINT message ) 2077 { 2078 /* these are always ignored */ 2079 return (message >= 0xc000 || 2080 message == WM_GETICON || 2081 message == WM_GETOBJECT || 2082 message == WM_TIMECHANGE || 2083 message == WM_DISPLAYCHANGE || 2084 message == WM_DEVICECHANGE || 2085 message == WM_DWMNCRENDERINGCHANGED); 2086 } 2087 2088 static unsigned hash_Ly_W(const WCHAR *str) 2089 { 2090 unsigned hash = 0; 2091 2092 for (; *str; str++) 2093 hash = hash * 1664525u + (unsigned char)(*str) + 1013904223u; 2094 2095 return hash; 2096 } 2097 2098 static unsigned hash_Ly(const char *str) 2099 { 2100 unsigned hash = 0; 2101 2102 for (; *str; str++) 2103 hash = hash * 1664525u + (unsigned char)(*str) + 1013904223u; 2104 2105 return hash; 2106 } 2107 2108 #define add_message(msg) add_message_(__LINE__,msg); 2109 static void add_message_(int line, const struct recvd_message *msg) 2110 { 2111 struct recvd_message *seq; 2112 2113 EnterCriticalSection( &sequence_cs ); 2114 if (!sequence) 2115 { 2116 sequence_size = 10; 2117 sequence = HeapAlloc( GetProcessHeap(), 0, sequence_size * sizeof(*sequence) ); 2118 } 2119 if (sequence_cnt == sequence_size) 2120 { 2121 sequence_size *= 2; 2122 sequence = HeapReAlloc( GetProcessHeap(), 0, sequence, sequence_size * sizeof(*sequence) ); 2123 } 2124 assert(sequence); 2125 2126 seq = &sequence[sequence_cnt++]; 2127 seq->hwnd = msg->hwnd; 2128 seq->message = msg->message; 2129 seq->flags = msg->flags; 2130 seq->wParam = msg->wParam; 2131 seq->lParam = msg->lParam; 2132 seq->line = line; 2133 seq->descr = msg->descr; 2134 seq->output[0] = 0; 2135 LeaveCriticalSection( &sequence_cs ); 2136 2137 if (msg->descr) 2138 { 2139 if (msg->flags & hook) 2140 { 2141 static const char * const CBT_code_name[10] = 2142 { 2143 "HCBT_MOVESIZE", 2144 "HCBT_MINMAX", 2145 "HCBT_QS", 2146 "HCBT_CREATEWND", 2147 "HCBT_DESTROYWND", 2148 "HCBT_ACTIVATE", 2149 "HCBT_CLICKSKIPPED", 2150 "HCBT_KEYSKIPPED", 2151 "HCBT_SYSCOMMAND", 2152 "HCBT_SETFOCUS" 2153 }; 2154 const char *code_name = (msg->message <= HCBT_SETFOCUS) ? CBT_code_name[msg->message] : "Unknown"; 2155 2156 sprintf( seq->output, "%s: hook %d (%s) wp %08lx lp %08lx", 2157 msg->descr, msg->message, code_name, msg->wParam, msg->lParam ); 2158 } 2159 else if (msg->flags & winevent_hook) 2160 { 2161 sprintf( seq->output, "%s: winevent %p %08x %08lx %08lx", 2162 msg->descr, msg->hwnd, msg->message, msg->wParam, msg->lParam ); 2163 } 2164 else 2165 { 2166 switch (msg->message) 2167 { 2168 case WM_WINDOWPOSCHANGING: 2169 case WM_WINDOWPOSCHANGED: 2170 { 2171 WINDOWPOS *winpos = (WINDOWPOS *)msg->lParam; 2172 2173 sprintf( seq->output, "%s: %p WM_WINDOWPOS%s wp %08lx lp %08lx after %p x %d y %d cx %d cy %d flags %s", 2174 msg->descr, msg->hwnd, 2175 (msg->message == WM_WINDOWPOSCHANGING) ? "CHANGING" : "CHANGED", 2176 msg->wParam, msg->lParam, winpos->hwndInsertAfter, 2177 winpos->x, winpos->y, winpos->cx, winpos->cy, 2178 get_winpos_flags(winpos->flags) ); 2179 2180 /* Log only documented flags, win2k uses 0x1000 and 0x2000 2181 * in the high word for internal purposes 2182 */ 2183 seq->wParam = winpos->flags & 0xffff; 2184 /* We are not interested in the flags that don't match under XP and Win9x */ 2185 seq->wParam &= ~SWP_NOZORDER; 2186 break; 2187 } 2188 2189 case WM_DRAWITEM: 2190 { 2191 DRAW_ITEM_STRUCT di; 2192 DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)msg->lParam; 2193 2194 sprintf( seq->output, "%s: %p WM_DRAWITEM: type %x, ctl_id %x, item_id %x, action %x, state %x", 2195 msg->descr, msg->hwnd, dis->CtlType, dis->CtlID, 2196 dis->itemID, dis->itemAction, dis->itemState); 2197 2198 di.u.lp = 0; 2199 di.u.item.type = dis->CtlType; 2200 di.u.item.ctl_id = dis->CtlID; 2201 if (dis->CtlType == ODT_LISTBOX || 2202 dis->CtlType == ODT_COMBOBOX || 2203 dis->CtlType == ODT_MENU) 2204 di.u.item.item_id = dis->itemID; 2205 di.u.item.action = dis->itemAction; 2206 di.u.item.state = dis->itemState; 2207 2208 seq->lParam = di.u.lp; 2209 break; 2210 } 2211 2212 case WM_MEASUREITEM: 2213 { 2214 MEASURE_ITEM_STRUCT mi; 2215 MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *)msg->lParam; 2216 BOOL is_unicode_data = TRUE; 2217 2218 sprintf( seq->output, "%s: %p WM_MEASUREITEM: CtlType %#x, CtlID %#x, itemID %#x, itemData %#lx", 2219 msg->descr, msg->hwnd, mis->CtlType, mis->CtlID, 2220 mis->itemID, mis->itemData); 2221 2222 if (mis->CtlType == ODT_LISTBOX) 2223 { 2224 HWND ctrl = GetDlgItem(msg->hwnd, mis->CtlID); 2225 is_unicode_data = GetWindowLongA(ctrl, GWL_STYLE) & LBS_HASSTRINGS; 2226 } 2227 2228 mi.u.wp = 0; 2229 mi.u.item.CtlType = mis->CtlType; 2230 mi.u.item.CtlID = mis->CtlID; 2231 mi.u.item.itemID = mis->itemID; 2232 mi.u.item.wParam = msg->wParam; 2233 seq->wParam = mi.u.wp; 2234 if (is_unicode_data) 2235 seq->lParam = mis->itemData ? hash_Ly_W((const WCHAR *)mis->itemData) : 0; 2236 else 2237 seq->lParam = mis->itemData ? hash_Ly((const char *)mis->itemData) : 0; 2238 break; 2239 } 2240 2241 case WM_COMPAREITEM: 2242 { 2243 COMPAREITEMSTRUCT *cis = (COMPAREITEMSTRUCT *)msg->lParam; 2244 HWND ctrl = GetDlgItem(msg->hwnd, cis->CtlID); 2245 BOOL is_unicode_data = TRUE; 2246 2247 ok(msg->wParam == cis->CtlID, "expected %#x, got %#lx\n", cis->CtlID, msg->wParam); 2248 ok(cis->hwndItem == ctrl, "expected %p, got %p\n", ctrl, cis->hwndItem); 2249 ok((int)cis->itemID1 >= 0, "expected >= 0, got %d\n", cis->itemID1); 2250 ok((int)cis->itemID2 == -1, "expected -1, got %d\n", cis->itemID2); 2251 2252 sprintf( seq->output, "%s: %p WM_COMPAREITEM: CtlType %#x, CtlID %#x, itemID1 %#x, itemData1 %#lx, itemID2 %#x, itemData2 %#lx", 2253 msg->descr, msg->hwnd, cis->CtlType, cis->CtlID, 2254 cis->itemID1, cis->itemData1, cis->itemID2, cis->itemData2); 2255 2256 if (cis->CtlType == ODT_LISTBOX) 2257 is_unicode_data = GetWindowLongA(ctrl, GWL_STYLE) & LBS_HASSTRINGS; 2258 2259 if (is_unicode_data) 2260 { 2261 seq->wParam = cis->itemData1 ? hash_Ly_W((const WCHAR *)cis->itemData1) : 0; 2262 seq->lParam = cis->itemData2 ? hash_Ly_W((const WCHAR *)cis->itemData2) : 0; 2263 } 2264 else 2265 { 2266 seq->wParam = cis->itemData1 ? hash_Ly((const char *)cis->itemData1) : 0; 2267 seq->lParam = cis->itemData2 ? hash_Ly((const char *)cis->itemData2) : 0; 2268 } 2269 break; 2270 } 2271 2272 default: 2273 if (msg->message >= 0xc000) return; /* ignore registered messages */ 2274 sprintf( seq->output, "%s: %p %04x wp %08lx lp %08lx", 2275 msg->descr, msg->hwnd, msg->message, msg->wParam, msg->lParam ); 2276 } 2277 if (msg->flags & (sent|posted|parent|defwinproc|beginpaint)) 2278 sprintf( seq->output + strlen(seq->output), " (flags %x)", msg->flags ); 2279 } 2280 } 2281 } 2282 2283 /* try to make sure pending X events have been processed before continuing */ 2284 static void flush_events(void) 2285 { 2286 MSG msg; 2287 int diff = 200; 2288 int min_timeout = 100; 2289 DWORD time = GetTickCount() + diff; 2290 2291 while (diff > 0) 2292 { 2293 if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break; 2294 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 2295 diff = time - GetTickCount(); 2296 } 2297 } 2298 2299 static void flush_sequence(void) 2300 { 2301 EnterCriticalSection( &sequence_cs ); 2302 HeapFree(GetProcessHeap(), 0, sequence); 2303 sequence = 0; 2304 sequence_cnt = sequence_size = 0; 2305 LeaveCriticalSection( &sequence_cs ); 2306 } 2307 2308 static void dump_sequence(const struct message *expected, const char *context, const char *file, int line) 2309 { 2310 const struct recvd_message *actual = sequence; 2311 unsigned int count = 0; 2312 2313 trace_(file, line)("Failed sequence %s:\n", context ); 2314 while (expected->message && actual->message) 2315 { 2316 if (actual->output[0]) 2317 { 2318 if (expected->flags & hook) 2319 { 2320 trace_(file, line)( " %u: expected: hook %04x - actual: %s\n", 2321 count, expected->message, actual->output ); 2322 } 2323 else if (expected->flags & winevent_hook) 2324 { 2325 trace_(file, line)( " %u: expected: winevent %04x - actual: %s\n", 2326 count, expected->message, actual->output ); 2327 } 2328 else if (expected->flags & kbd_hook) 2329 { 2330 trace_(file, line)( " %u: expected: kbd %04x - actual: %s\n", 2331 count, expected->message, actual->output ); 2332 } 2333 else 2334 { 2335 trace_(file, line)( " %u: expected: msg %04x - actual: %s\n", 2336 count, expected->message, actual->output ); 2337 } 2338 } 2339 2340 if (expected->message == actual->message) 2341 { 2342 if ((expected->flags & defwinproc) != (actual->flags & defwinproc) && 2343 (expected->flags & optional)) 2344 { 2345 /* don't match messages if their defwinproc status differs */ 2346 expected++; 2347 } 2348 else 2349 { 2350 expected++; 2351 actual++; 2352 } 2353 } 2354 /* silently drop winevent messages if there is no support for them */ 2355 else if ((expected->flags & optional) || ((expected->flags & winevent_hook) && !hEvent_hook)) 2356 expected++; 2357 else 2358 { 2359 expected++; 2360 actual++; 2361 } 2362 count++; 2363 } 2364 2365 /* optional trailing messages */ 2366 while (expected->message && ((expected->flags & optional) || 2367 ((expected->flags & winevent_hook) && !hEvent_hook))) 2368 { 2369 trace_(file, line)( " %u: expected: msg %04x - actual: nothing\n", count, expected->message ); 2370 expected++; 2371 count++; 2372 } 2373 2374 if (expected->message) 2375 { 2376 trace_(file, line)( " %u: expected: msg %04x - actual: nothing\n", count, expected->message ); 2377 return; 2378 } 2379 2380 while (actual->message && actual->output[0]) 2381 { 2382 trace_(file, line)( " %u: expected: nothing - actual: %s\n", count, actual->output ); 2383 actual++; 2384 count++; 2385 } 2386 } 2387 2388 #define ok_sequence( exp, contx, todo) \ 2389 ok_sequence_( (exp), (contx), (todo), __FILE__, __LINE__) 2390 2391 2392 static void ok_sequence_(const struct message *expected_list, const char *context, BOOL todo, 2393 const char *file, int line) 2394 { 2395 static const struct recvd_message end_of_sequence; 2396 const struct message *expected = expected_list; 2397 const struct recvd_message *actual; 2398 int failcount = 0, dump = 0; 2399 unsigned int count = 0; 2400 2401 add_message(&end_of_sequence); 2402 2403 actual = sequence; 2404 2405 while (expected->message && actual->message) 2406 { 2407 if (expected->message == actual->message && 2408 !((expected->flags ^ actual->flags) & (hook|winevent_hook|kbd_hook))) 2409 { 2410 if (expected->flags & wparam) 2411 { 2412 if (((expected->wParam ^ actual->wParam) & ~expected->wp_mask) && todo) 2413 { 2414 todo_wine { 2415 failcount ++; 2416 if (strcmp(winetest_platform, "wine")) dump++; 2417 ok_( file, line) (FALSE, 2418 "%s: %u: in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n", 2419 context, count, expected->message, expected->wParam, actual->wParam); 2420 } 2421 } 2422 else 2423 { 2424 ok_( file, line)( ((expected->wParam ^ actual->wParam) & ~expected->wp_mask) == 0, 2425 "%s: %u: in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n", 2426 context, count, expected->message, expected->wParam, actual->wParam); 2427 if ((expected->wParam ^ actual->wParam) & ~expected->wp_mask) dump++; 2428 } 2429 2430 } 2431 if (expected->flags & lparam) 2432 { 2433 if (((expected->lParam ^ actual->lParam) & ~expected->lp_mask) && todo) 2434 { 2435 todo_wine { 2436 failcount ++; 2437 if (strcmp(winetest_platform, "wine")) dump++; 2438 ok_( file, line) (FALSE, 2439 "%s: %u: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n", 2440 context, count, expected->message, expected->lParam, actual->lParam); 2441 } 2442 } 2443 else 2444 { 2445 ok_( file, line)(((expected->lParam ^ actual->lParam) & ~expected->lp_mask) == 0, 2446 "%s: %u: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n", 2447 context, count, expected->message, expected->lParam, actual->lParam); 2448 if ((expected->lParam ^ actual->lParam) & ~expected->lp_mask) dump++; 2449 } 2450 } 2451 if ((expected->flags & optional) && 2452 ((expected->flags ^ actual->flags) & (defwinproc|parent))) 2453 { 2454 /* don't match optional messages if their defwinproc or parent status differs */ 2455 expected++; 2456 count++; 2457 continue; 2458 } 2459 if ((expected->flags & defwinproc) != (actual->flags & defwinproc) && todo) 2460 { 2461 todo_wine { 2462 failcount ++; 2463 if (strcmp(winetest_platform, "wine")) dump++; 2464 ok_( file, line) (FALSE, 2465 "%s: %u: the msg 0x%04x should %shave been sent by DefWindowProc\n", 2466 context, count, expected->message, (expected->flags & defwinproc) ? "" : "NOT "); 2467 } 2468 } 2469 else 2470 { 2471 ok_( file, line) ((expected->flags & defwinproc) == (actual->flags & defwinproc), 2472 "%s: %u: the msg 0x%04x should %shave been sent by DefWindowProc\n", 2473 context, count, expected->message, (expected->flags & defwinproc) ? "" : "NOT "); 2474 if ((expected->flags & defwinproc) != (actual->flags & defwinproc)) dump++; 2475 } 2476 2477 ok_( file, line) ((expected->flags & beginpaint) == (actual->flags & beginpaint), 2478 "%s: %u: the msg 0x%04x should %shave been sent by BeginPaint\n", 2479 context, count, expected->message, (expected->flags & beginpaint) ? "" : "NOT "); 2480 if ((expected->flags & beginpaint) != (actual->flags & beginpaint)) dump++; 2481 2482 ok_( file, line) ((expected->flags & (sent|posted)) == (actual->flags & (sent|posted)), 2483 "%s: %u: the msg 0x%04x should have been %s\n", 2484 context, count, expected->message, (expected->flags & posted) ? "posted" : "sent"); 2485 if ((expected->flags & (sent|posted)) != (actual->flags & (sent|posted))) dump++; 2486 2487 ok_( file, line) ((expected->flags & parent) == (actual->flags & parent), 2488 "%s: %u: the msg 0x%04x was expected in %s\n", 2489 context, count, expected->message, (expected->flags & parent) ? "parent" : "child"); 2490 if ((expected->flags & parent) != (actual->flags & parent)) dump++; 2491 2492 ok_( file, line) ((expected->flags & hook) == (actual->flags & hook), 2493 "%s: %u: the msg 0x%04x should have been sent by a hook\n", 2494 context, count, expected->message); 2495 if ((expected->flags & hook) != (actual->flags & hook)) dump++; 2496 2497 ok_( file, line) ((expected->flags & winevent_hook) == (actual->flags & winevent_hook), 2498 "%s: %u: the msg 0x%04x should have been sent by a winevent hook\n", 2499 context, count, expected->message); 2500 if ((expected->flags & winevent_hook) != (actual->flags & winevent_hook)) dump++; 2501 2502 ok_( file, line) ((expected->flags & kbd_hook) == (actual->flags & kbd_hook), 2503 "%s: %u: the msg 0x%04x should have been sent by a keyboard hook\n", 2504 context, count, expected->message); 2505 if ((expected->flags & kbd_hook) != (actual->flags & kbd_hook)) dump++; 2506 2507 expected++; 2508 actual++; 2509 } 2510 /* silently drop hook messages if there is no support for them */ 2511 else if ((expected->flags & optional) || 2512 ((expected->flags & hook) && !hCBT_hook) || 2513 ((expected->flags & winevent_hook) && !hEvent_hook) || 2514 ((expected->flags & kbd_hook) && !hKBD_hook)) 2515 expected++; 2516 else if (todo) 2517 { 2518 failcount++; 2519 todo_wine { 2520 if (strcmp(winetest_platform, "wine")) dump++; 2521 ok_( file, line) (FALSE, "%s: %u: the msg 0x%04x was expected, but got msg 0x%04x instead\n", 2522 context, count, expected->message, actual->message); 2523 } 2524 goto done; 2525 } 2526 else 2527 { 2528 ok_( file, line) (FALSE, "%s: %u: the msg 0x%04x was expected, but got msg 0x%04x instead\n", 2529 context, count, expected->message, actual->message); 2530 dump++; 2531 expected++; 2532 actual++; 2533 } 2534 count++; 2535 } 2536 2537 /* skip all optional trailing messages */ 2538 while (expected->message && ((expected->flags & optional) || 2539 ((expected->flags & hook) && !hCBT_hook) || 2540 ((expected->flags & winevent_hook) && !hEvent_hook))) 2541 expected++; 2542 2543 if (todo) 2544 { 2545 todo_wine { 2546 if (expected->message || actual->message) { 2547 failcount++; 2548 if (strcmp(winetest_platform, "wine")) dump++; 2549 ok_( file, line) (FALSE, "%s: %u: the msg sequence is not complete: expected %04x - actual %04x\n", 2550 context, count, expected->message, actual->message); 2551 } 2552 } 2553 } 2554 else 2555 { 2556 if (expected->message || actual->message) 2557 { 2558 dump++; 2559 ok_( file, line) (FALSE, "%s: %u: the msg sequence is not complete: expected %04x - actual %04x\n", 2560 context, count, expected->message, actual->message); 2561 } 2562 } 2563 if( todo && !failcount) /* succeeded yet marked todo */ 2564 todo_wine { 2565 if (!strcmp(winetest_platform, "wine")) dump++; 2566 ok_( file, line)( TRUE, "%s: marked \"todo_wine\" but succeeds\n", context); 2567 } 2568 2569 done: 2570 if (dump) dump_sequence(expected_list, context, file, line); 2571 flush_sequence(); 2572 } 2573 2574 #define expect(EXPECTED,GOT) ok((GOT)==(EXPECTED), "Expected %d, got %d\n", (EXPECTED), (GOT)) 2575 2576 /******************************** MDI test **********************************/ 2577 2578 /* CreateWindow for MDI frame window, initially visible */ 2579 static const struct message WmCreateMDIframeSeq[] = { 2580 { HCBT_CREATEWND, hook }, 2581 { WM_GETMINMAXINFO, sent }, 2582 { WM_NCCREATE, sent }, 2583 { WM_NCCALCSIZE, sent|wparam, 0 }, 2584 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, 2585 { WM_CREATE, sent }, 2586 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 2587 { WM_NOTIFYFORMAT, sent|optional }, 2588 { WM_QUERYUISTATE, sent|optional }, 2589 { WM_WINDOWPOSCHANGING, sent|optional }, 2590 { WM_GETMINMAXINFO, sent|optional }, 2591 { WM_NCCALCSIZE, sent|optional }, 2592 { WM_WINDOWPOSCHANGED, sent|optional }, 2593 { WM_SHOWWINDOW, sent|wparam, 1 }, 2594 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 2595 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 2596 { HCBT_ACTIVATE, hook }, 2597 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 2598 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 2599 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* XP */ 2600 { WM_ACTIVATEAPP, sent|wparam|optional, 1 }, /* Win9x doesn't send it */ 2601 { WM_NCACTIVATE, sent }, 2602 { WM_GETTEXT, sent|defwinproc|optional }, 2603 { WM_ACTIVATE, sent|wparam, 1 }, 2604 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* Win9x */ 2605 { HCBT_SETFOCUS, hook }, 2606 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 2607 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 2608 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2609 { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, 2610 /* Win9x adds SWP_NOZORDER below */ 2611 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2612 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* XP */ 2613 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 2614 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 2615 { WM_MOVE, sent }, 2616 { 0 } 2617 }; 2618 /* DestroyWindow for MDI frame window, initially visible */ 2619 static const struct message WmDestroyMDIframeSeq[] = { 2620 { HCBT_DESTROYWND, hook }, 2621 { 0x0090, sent|optional }, 2622 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2623 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 2624 { WM_NCACTIVATE, sent|wparam|optional, 0 }, /* Win9x */ 2625 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2626 { WM_NCACTIVATE, sent|wparam|optional, 0 }, /* XP */ 2627 { WM_ACTIVATE, sent|wparam|optional, 0 }, /* Win9x */ 2628 { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, /* Win9x */ 2629 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 2630 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, 2631 { WM_DESTROY, sent }, 2632 { WM_NCDESTROY, sent }, 2633 { 0 } 2634 }; 2635 /* CreateWindow for MDI client window, initially visible */ 2636 static const struct message WmCreateMDIclientSeq[] = { 2637 { HCBT_CREATEWND, hook }, 2638 { WM_NCCREATE, sent }, 2639 { WM_NCCALCSIZE, sent|wparam, 0 }, 2640 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|optional, 0, 0 }, 2641 { WM_CREATE, sent }, 2642 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|optional, 0, 0 }, 2643 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 2644 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 2645 { WM_MOVE, sent }, 2646 { WM_PARENTNOTIFY, sent|wparam, WM_CREATE }, /* in MDI frame */ 2647 { WM_SHOWWINDOW, sent|wparam, 1 }, 2648 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2649 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 2650 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2651 { 0 } 2652 }; 2653 /* ShowWindow(SW_SHOW) for MDI client window */ 2654 static const struct message WmShowMDIclientSeq[] = { 2655 { WM_SHOWWINDOW, sent|wparam, 1 }, 2656 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2657 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 2658 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2659 { 0 } 2660 }; 2661 /* ShowWindow(SW_HIDE) for MDI client window */ 2662 static const struct message WmHideMDIclientSeq[] = { 2663 { WM_SHOWWINDOW, sent|wparam, 0 }, 2664 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2665 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam|optional, 0, 0 }, /* win2000 */ 2666 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP */ 2667 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2668 { 0 } 2669 }; 2670 /* DestroyWindow for MDI client window, initially visible */ 2671 static const struct message WmDestroyMDIclientSeq[] = { 2672 { HCBT_DESTROYWND, hook }, 2673 { 0x0090, sent|optional }, 2674 { WM_PARENTNOTIFY, sent|wparam, WM_DESTROY }, /* in MDI frame */ 2675 { WM_SHOWWINDOW, sent|wparam, 0 }, 2676 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2677 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 2678 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2679 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, 2680 { WM_DESTROY, sent }, 2681 { WM_NCDESTROY, sent }, 2682 { 0 } 2683 }; 2684 /* CreateWindow for MDI child window, initially visible */ 2685 static const struct message WmCreateMDIchildVisibleSeq[] = { 2686 { HCBT_CREATEWND, hook }, 2687 { WM_NCCREATE, sent }, 2688 { WM_NCCALCSIZE, sent|wparam, 0 }, 2689 { WM_CREATE, sent }, 2690 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 2691 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 2692 { WM_MOVE, sent }, 2693 /* Win2k sends wparam set to 2694 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated), 2695 * while Win9x doesn't bother to set child window id according to 2696 * CLIENTCREATESTRUCT.idFirstChild 2697 */ 2698 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */ 2699 { WM_SHOWWINDOW, sent|wparam, 1 }, 2700 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2701 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 2702 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2703 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ }, 2704 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 2705 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 2706 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2707 2708 /* Win9x: message sequence terminates here. */ 2709 2710 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, 2711 { HCBT_SETFOCUS, hook }, /* in MDI client */ 2712 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 2713 { WM_IME_NOTIFY, sent|wparam|optional, 2 }, /* in MDI client */ 2714 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2715 { WM_SETFOCUS, sent }, /* in MDI client */ 2716 { HCBT_SETFOCUS, hook }, 2717 { WM_KILLFOCUS, sent }, /* in MDI client */ 2718 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 2719 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 2720 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2721 { WM_SETFOCUS, sent|defwinproc }, 2722 { WM_MDIACTIVATE, sent|defwinproc }, 2723 { 0 } 2724 }; 2725 /* WM_CHILDACTIVATE sent to disabled window */ 2726 static const struct message WmChildActivateDisabledWindowSeq[] = { 2727 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 2728 { 0 } 2729 }; 2730 /* WM_CHILDACTIVATE sent to enabled window */ 2731 static const struct message WmChildActivateWindowSeq[] = { 2732 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 2733 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, 2734 { WM_MDIACTIVATE, sent|defwinproc }, 2735 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2736 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2737 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, 2738 { HCBT_SETFOCUS, hook }, 2739 { WM_KILLFOCUS, sent|defwinproc }, 2740 { WM_SETFOCUS, sent }, 2741 { HCBT_SETFOCUS, hook }, 2742 { WM_KILLFOCUS, sent }, 2743 { WM_SETFOCUS, sent|defwinproc }, 2744 { WM_MDIACTIVATE, sent|defwinproc }, 2745 { 0 } 2746 }; 2747 /* CreateWindow for MDI child window with invisible parent */ 2748 static const struct message WmCreateMDIchildInvisibleParentSeq[] = { 2749 { HCBT_CREATEWND, hook }, 2750 { WM_GETMINMAXINFO, sent }, 2751 { WM_NCCREATE, sent }, 2752 { WM_NCCALCSIZE, sent|wparam, 0 }, 2753 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|optional, 0, 0 }, 2754 { WM_CREATE, sent }, 2755 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 2756 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 2757 { WM_MOVE, sent }, 2758 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */ 2759 { WM_SHOWWINDOW, sent|wparam, 1 }, 2760 { WM_MDIREFRESHMENU, sent }, /* in MDI client */ 2761 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 2762 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 2763 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2764 2765 /* Win9x: message sequence terminates here. */ 2766 2767 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, 2768 { HCBT_SETFOCUS, hook }, /* in MDI client */ 2769 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 2770 { WM_IME_NOTIFY, sent|wparam|optional, 2 }, /* in MDI client */ 2771 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2772 { WM_SETFOCUS, sent }, /* in MDI client */ 2773 { HCBT_SETFOCUS, hook }, 2774 { WM_KILLFOCUS, sent }, /* in MDI client */ 2775 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 2776 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 2777 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2778 { WM_SETFOCUS, sent|defwinproc }, 2779 { WM_MDIACTIVATE, sent|defwinproc }, 2780 { 0 } 2781 }; 2782 /* DestroyWindow for MDI child window, initially visible */ 2783 static const struct message WmDestroyMDIchildVisibleSeq[] = { 2784 { HCBT_DESTROYWND, hook }, 2785 /* Win2k sends wparam set to 2786 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated), 2787 * while Win9x doesn't bother to set child window id according to 2788 * CLIENTCREATESTRUCT.idFirstChild 2789 */ 2790 { 0x0090, sent|optional }, 2791 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */ 2792 { WM_SHOWWINDOW, sent|wparam, 0 }, 2793 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2794 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 2795 { WM_ERASEBKGND, sent|parent|optional }, 2796 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2797 2798 /* { WM_DESTROY, sent } 2799 * Win9x: message sequence terminates here. 2800 */ 2801 2802 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */ 2803 { WM_KILLFOCUS, sent }, 2804 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 2805 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 2806 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2807 { WM_SETFOCUS, sent }, /* in MDI client */ 2808 2809 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */ 2810 { WM_KILLFOCUS, sent }, /* in MDI client */ 2811 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 2812 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 2813 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2814 { WM_SETFOCUS, sent }, /* in MDI client */ 2815 2816 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, 2817 2818 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */ 2819 { WM_KILLFOCUS, sent }, 2820 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 2821 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 2822 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2823 { WM_SETFOCUS, sent }, /* in MDI client */ 2824 2825 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */ 2826 { WM_KILLFOCUS, sent }, /* in MDI client */ 2827 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 2828 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 2829 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2830 { WM_SETFOCUS, sent }, /* in MDI client */ 2831 2832 { WM_DESTROY, sent }, 2833 2834 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */ 2835 { WM_KILLFOCUS, sent }, 2836 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 2837 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 2838 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2839 { WM_SETFOCUS, sent }, /* in MDI client */ 2840 2841 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */ 2842 { WM_KILLFOCUS, sent }, /* in MDI client */ 2843 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 2844 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 2845 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2846 { WM_SETFOCUS, sent }, /* in MDI client */ 2847 2848 { WM_NCDESTROY, sent }, 2849 { 0 } 2850 }; 2851 /* CreateWindow for MDI child window, initially invisible */ 2852 static const struct message WmCreateMDIchildInvisibleSeq[] = { 2853 { HCBT_CREATEWND, hook }, 2854 { WM_NCCREATE, sent }, 2855 { WM_NCCALCSIZE, sent|wparam, 0 }, 2856 { WM_CREATE, sent }, 2857 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 2858 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 2859 { WM_MOVE, sent }, 2860 /* Win2k sends wparam set to 2861 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated), 2862 * while Win9x doesn't bother to set child window id according to 2863 * CLIENTCREATESTRUCT.idFirstChild 2864 */ 2865 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */ 2866 { 0 } 2867 }; 2868 /* DestroyWindow for MDI child window, initially invisible */ 2869 static const struct message WmDestroyMDIchildInvisibleSeq[] = { 2870 { HCBT_DESTROYWND, hook }, 2871 /* Win2k sends wparam set to 2872 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated), 2873 * while Win9x doesn't bother to set child window id according to 2874 * CLIENTCREATESTRUCT.idFirstChild 2875 */ 2876 { 0x0090, sent|optional }, 2877 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */ 2878 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, 2879 { WM_DESTROY, sent }, 2880 { WM_NCDESTROY, sent }, 2881 /* FIXME: Wine destroys an icon/title window while Windows doesn't */ 2882 { WM_PARENTNOTIFY, sent|wparam|optional, WM_DESTROY }, /* MDI client */ 2883 { 0 } 2884 }; 2885 /* CreateWindow for the 1st MDI child window, initially visible and maximized */ 2886 static const struct message WmCreateMDIchildVisibleMaxSeq1[] = { 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 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 2895 { WM_GETMINMAXINFO, sent }, 2896 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_STATECHANGED }, 2897 { WM_NCCALCSIZE, sent|wparam, 1 }, 2898 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 2899 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 2900 /* in MDI frame */ 2901 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2902 { WM_NCCALCSIZE, sent|wparam, 1 }, 2903 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2904 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 2905 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 2906 /* Win2k sends wparam set to 2907 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated), 2908 * while Win9x doesn't bother to set child window id according to 2909 * CLIENTCREATESTRUCT.idFirstChild 2910 */ 2911 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */ 2912 { WM_SHOWWINDOW, sent|wparam, 1 }, 2913 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2914 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 2915 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2916 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ }, 2917 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 2918 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 2919 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc|optional, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE, 0, SWP_FRAMECHANGED }, 2920 2921 /* Win9x: message sequence terminates here. */ 2922 2923 { WM_NCACTIVATE, sent|wparam|defwinproc|optional, 1 }, 2924 { HCBT_SETFOCUS, hook|optional }, /* in MDI client */ 2925 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 2926 { WM_IME_NOTIFY, sent|wparam|optional, 2 }, /* in MDI client */ 2927 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2928 { WM_SETFOCUS, sent|optional }, /* in MDI client */ 2929 { HCBT_SETFOCUS, hook|optional }, 2930 { WM_KILLFOCUS, sent|optional }, /* in MDI client */ 2931 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 2932 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 2933 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2934 { WM_SETFOCUS, sent|defwinproc|optional }, 2935 { WM_MDIACTIVATE, sent|defwinproc|optional }, 2936 /* in MDI frame */ 2937 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2938 { WM_NCCALCSIZE, sent|wparam, 1 }, 2939 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2940 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 2941 { 0 } 2942 }; 2943 /* CreateWindow for the 2nd MDI child window, initially visible and maximized */ 2944 static const struct message WmCreateMDIchildVisibleMaxSeq2[] = { 2945 /* restore the 1st MDI child */ 2946 { WM_SETREDRAW, sent|wparam, 0 }, 2947 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWNORMAL }, 2948 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, 2949 { WM_NCCALCSIZE, sent|wparam, 1 }, 2950 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 2951 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 2952 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 2953 /* in MDI frame */ 2954 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2955 { WM_NCCALCSIZE, sent|wparam, 1 }, 2956 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2957 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 2958 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 2959 { WM_SETREDRAW, sent|wparam, 1 }, /* in the 1st MDI child */ 2960 /* create the 2nd MDI child */ 2961 { HCBT_CREATEWND, hook }, 2962 { WM_NCCREATE, sent }, 2963 { WM_NCCALCSIZE, sent|wparam, 0 }, 2964 { WM_CREATE, sent }, 2965 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 2966 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 2967 { WM_MOVE, sent }, 2968 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 2969 { WM_GETMINMAXINFO, sent }, 2970 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_STATECHANGED }, 2971 { WM_NCCALCSIZE, sent|wparam, 1 }, 2972 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2973 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 2974 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 2975 /* in MDI frame */ 2976 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2977 { WM_NCCALCSIZE, sent|wparam, 1 }, 2978 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2979 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 2980 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 2981 /* Win2k sends wparam set to 2982 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated), 2983 * while Win9x doesn't bother to set child window id according to 2984 * CLIENTCREATESTRUCT.idFirstChild 2985 */ 2986 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */ 2987 { WM_SHOWWINDOW, sent|wparam, 1 }, 2988 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2989 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 2990 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2991 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ }, 2992 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 2993 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 2994 2995 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 1st MDI child */ 2996 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 1st MDI child */ 2997 2998 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2999 3000 /* Win9x: message sequence terminates here. */ 3001 3002 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, 3003 { HCBT_SETFOCUS, hook }, 3004 { WM_KILLFOCUS, sent|defwinproc|optional }, /* in the 1st MDI child */ 3005 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 }, /* in the 1st MDI child */ 3006 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 3007 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3008 { WM_SETFOCUS, sent }, /* in MDI client */ 3009 { HCBT_SETFOCUS, hook }, 3010 { WM_KILLFOCUS, sent }, /* in MDI client */ 3011 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 3012 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 3013 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3014 { WM_SETFOCUS, sent|defwinproc }, 3015 3016 { WM_MDIACTIVATE, sent|defwinproc }, 3017 /* in MDI frame */ 3018 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3019 { WM_NCCALCSIZE, sent|wparam, 1 }, 3020 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3021 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3022 { 0 } 3023 }; 3024 /* WM_MDICREATE MDI child window, initially visible and maximized */ 3025 static const struct message WmCreateMDIchildVisibleMaxSeq3[] = { 3026 { WM_MDICREATE, sent }, 3027 { HCBT_CREATEWND, hook }, 3028 { WM_NCCREATE, sent }, 3029 { WM_NCCALCSIZE, sent|wparam, 0 }, 3030 { WM_CREATE, sent }, 3031 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 3032 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 3033 { WM_MOVE, sent }, 3034 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 3035 { WM_GETMINMAXINFO, sent }, 3036 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_STATECHANGED }, 3037 { WM_NCCALCSIZE, sent|wparam, 1 }, 3038 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 3039 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 3040 3041 /* in MDI frame */ 3042 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3043 { WM_NCCALCSIZE, sent|wparam, 1 }, 3044 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3045 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3046 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3047 3048 /* Win2k sends wparam set to 3049 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated), 3050 * while Win9x doesn't bother to set child window id according to 3051 * CLIENTCREATESTRUCT.idFirstChild 3052 */ 3053 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */ 3054 { WM_SHOWWINDOW, sent|wparam, 1 }, 3055 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3056 3057 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 3058 3059 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3060 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ }, 3061 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 3062 3063 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 3064 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3065 3066 /* Win9x: message sequence terminates here. */ 3067 3068 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, 3069 { WM_SETFOCUS, sent|optional }, /* in MDI client */ 3070 { HCBT_SETFOCUS, hook }, /* in MDI client */ 3071 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 3072 { WM_IME_NOTIFY, sent|wparam|optional, 2 }, 3073 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 }, 3074 { WM_SETFOCUS, sent|optional }, /* in MDI client */ 3075 { HCBT_SETFOCUS, hook|optional }, 3076 { WM_KILLFOCUS, sent }, /* in MDI client */ 3077 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 3078 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 3079 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3080 { WM_SETFOCUS, sent|defwinproc }, 3081 3082 { WM_MDIACTIVATE, sent|defwinproc }, 3083 3084 /* in MDI child */ 3085 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3086 { WM_NCCALCSIZE, sent|wparam, 1 }, 3087 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3088 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 3089 3090 /* in MDI frame */ 3091 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3092 { WM_NCCALCSIZE, sent|wparam, 1 }, 3093 { 0x0093, sent|defwinproc|optional }, 3094 { 0x0093, sent|defwinproc|optional }, 3095 { 0x0093, sent|defwinproc|optional }, 3096 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3097 { WM_MOVE, sent|defwinproc }, 3098 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 3099 3100 /* in MDI client */ 3101 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE }, 3102 { WM_NCCALCSIZE, sent|wparam, 1 }, 3103 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOCLIENTMOVE }, 3104 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 3105 3106 /* in MDI child */ 3107 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE }, 3108 { WM_NCCALCSIZE, sent|wparam, 1 }, 3109 { 0x0093, sent|optional }, 3110 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOCLIENTMOVE }, 3111 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 3112 3113 { 0x0093, sent|optional }, 3114 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3115 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */ 3116 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* XP sends it to MDI frame */ 3117 { 0x0093, sent|defwinproc|optional }, 3118 { 0x0093, sent|defwinproc|optional }, 3119 { 0x0093, sent|defwinproc|optional }, 3120 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3121 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* XP sends a duplicate */ 3122 3123 { 0 } 3124 }; 3125 /* CreateWindow for the 1st MDI child window, initially invisible and maximized */ 3126 static const struct message WmCreateMDIchildInvisibleMaxSeq4[] = { 3127 { HCBT_CREATEWND, hook }, 3128 { WM_GETMINMAXINFO, sent }, 3129 { WM_NCCREATE, sent }, 3130 { WM_NCCALCSIZE, sent|wparam, 0 }, 3131 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, 3132 { WM_CREATE, sent }, 3133 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 3134 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 3135 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE, 0, SWP_NOZORDER }, /* MDI frame */ 3136 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* MDI frame */ 3137 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE, 0, SWP_NOZORDER }, /* MDI frame */ 3138 { WM_MOVE, sent }, 3139 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 3140 { WM_GETMINMAXINFO, sent }, 3141 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_STATECHANGED }, 3142 { WM_GETMINMAXINFO, sent|defwinproc }, 3143 { WM_NCCALCSIZE, sent|wparam, 1 }, 3144 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOREDRAW|SWP_STATECHANGED }, 3145 { WM_MOVE, sent|defwinproc }, 3146 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 3147 /* in MDI frame */ 3148 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3149 { WM_NCCALCSIZE, sent|wparam, 1 }, 3150 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3151 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3152 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* MDI child */ 3153 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3154 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3155 /* Win2k sends wparam set to 3156 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated), 3157 * while Win9x doesn't bother to set child window id according to 3158 * CLIENTCREATESTRUCT.idFirstChild 3159 */ 3160 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */ 3161 { 0 } 3162 }; 3163 /* WM_SYSCOMMAND/SC_CLOSE for the 2nd MDI child window, initially visible and maximized */ 3164 static const struct message WmDestroyMDIchildVisibleMaxSeq2[] = { 3165 { WM_SYSCOMMAND, sent|wparam, SC_CLOSE }, 3166 { HCBT_SYSCOMMAND, hook }, 3167 { WM_CLOSE, sent|defwinproc }, 3168 { WM_MDIDESTROY, sent }, /* in MDI client */ 3169 3170 /* bring the 1st MDI child to top */ 3171 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOSIZE|SWP_NOMOVE }, /* in the 1st MDI child */ 3172 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, /* in the 2nd MDI child */ 3173 3174 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3175 3176 { WM_CHILDACTIVATE, sent|defwinproc|wparam|lparam, 0, 0 }, /* in the 1st MDI child */ 3177 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 1st MDI child */ 3178 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 1st MDI child */ 3179 3180 /* maximize the 1st MDI child */ 3181 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 3182 { WM_GETMINMAXINFO, sent|defwinproc }, 3183 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_STATECHANGED }, 3184 { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 }, 3185 { WM_CHILDACTIVATE, sent|defwinproc|wparam|lparam, 0, 0 }, 3186 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 3187 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 3188 3189 /* restore the 2nd MDI child */ 3190 { WM_SETREDRAW, sent|defwinproc|wparam, 0 }, 3191 { HCBT_MINMAX, hook|lparam, 0, SW_NORMALNA }, 3192 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_STATECHANGED }, 3193 { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 }, 3194 3195 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 3196 3197 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 3198 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 3199 3200 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3201 3202 { WM_SETREDRAW, sent|defwinproc|wparam, 1 }, 3203 /* in MDI frame */ 3204 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3205 { WM_NCCALCSIZE, sent|wparam, 1 }, 3206 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3207 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3208 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3209 3210 /* bring the 1st MDI child to top */ 3211 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3212 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, 3213 { HCBT_SETFOCUS, hook }, 3214 { WM_KILLFOCUS, sent|defwinproc }, 3215 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 }, 3216 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 3217 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3218 { WM_SETFOCUS, sent }, /* in MDI client */ 3219 { HCBT_SETFOCUS, hook }, 3220 { WM_KILLFOCUS, sent }, /* in MDI client */ 3221 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 3222 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 3223 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3224 { WM_SETFOCUS, sent|defwinproc }, 3225 { WM_MDIACTIVATE, sent|defwinproc }, 3226 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3227 3228 /* apparently ShowWindow(SW_SHOW) on an MDI client */ 3229 { WM_SHOWWINDOW, sent|wparam, 1 }, 3230 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3231 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 3232 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3233 { WM_MDIREFRESHMENU, sent }, 3234 3235 { HCBT_DESTROYWND, hook }, 3236 /* Win2k sends wparam set to 3237 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated), 3238 * while Win9x doesn't bother to set child window id according to 3239 * CLIENTCREATESTRUCT.idFirstChild 3240 */ 3241 { 0x0090, sent|defwinproc|optional }, 3242 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */ 3243 { WM_SHOWWINDOW, sent|defwinproc|wparam, 0 }, 3244 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3245 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 3246 { WM_ERASEBKGND, sent|parent|optional }, 3247 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3248 3249 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, 3250 { WM_DESTROY, sent|defwinproc }, 3251 { WM_NCDESTROY, sent|defwinproc }, 3252 { 0 } 3253 }; 3254 /* WM_MDIDESTROY for the single MDI child window, initially visible and maximized */ 3255 static const struct message WmDestroyMDIchildVisibleMaxSeq1[] = { 3256 { WM_MDIDESTROY, sent }, /* in MDI client */ 3257 { WM_SHOWWINDOW, sent|wparam, 0 }, 3258 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3259 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 3260 { WM_ERASEBKGND, sent|parent|optional }, 3261 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3262 3263 { HCBT_SETFOCUS, hook }, 3264 { WM_KILLFOCUS, sent }, 3265 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 3266 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 3267 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3268 { WM_SETFOCUS, sent }, /* in MDI client */ 3269 { HCBT_SETFOCUS, hook }, 3270 { WM_KILLFOCUS, sent }, /* in MDI client */ 3271 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 3272 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 3273 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3274 { WM_SETFOCUS, sent }, 3275 3276 /* in MDI child */ 3277 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3278 { WM_NCCALCSIZE, sent|wparam, 1 }, 3279 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3280 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3281 3282 /* in MDI frame */ 3283 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3284 { WM_NCCALCSIZE, sent|wparam, 1 }, 3285 { 0x0093, sent|defwinproc|optional }, 3286 { 0x0093, sent|defwinproc|optional }, 3287 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3288 { WM_MOVE, sent|defwinproc }, 3289 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 3290 3291 /* in MDI client */ 3292 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE }, 3293 { WM_NCCALCSIZE, sent|wparam, 1 }, 3294 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOCLIENTMOVE }, 3295 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 3296 3297 /* in MDI child */ 3298 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE }, 3299 { WM_NCCALCSIZE, sent|wparam, 1 }, 3300 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE }, 3301 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 3302 3303 /* in MDI child */ 3304 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3305 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, 3306 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3307 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3308 3309 /* in MDI frame */ 3310 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3311 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, 3312 { 0x0093, sent|defwinproc|optional }, 3313 { 0x0093, sent|defwinproc|optional }, 3314 { 0x0093, sent|defwinproc|optional }, 3315 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3316 { WM_MOVE, sent|defwinproc }, 3317 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 3318 3319 /* in MDI client */ 3320 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE }, 3321 { WM_NCCALCSIZE, sent|wparam, 1 }, 3322 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOCLIENTMOVE }, 3323 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 3324 3325 /* in MDI child */ 3326 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE }, 3327 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, 3328 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE }, 3329 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 3330 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3331 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */ 3332 3333 { 0x0093, sent|defwinproc|optional }, 3334 { WM_NCCALCSIZE, sent|wparam|defwinproc|optional, 1 }, /* XP sends it to MDI frame */ 3335 { 0x0093, sent|defwinproc|optional }, 3336 { 0x0093, sent|defwinproc|optional }, 3337 { 0x0093, sent|defwinproc|optional }, 3338 { 0x0093, sent|optional }, 3339 3340 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3341 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3342 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */ 3343 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3344 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* XP sends a duplicate */ 3345 3346 /* in MDI frame */ 3347 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3348 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, 3349 { 0x0093, sent|defwinproc|optional }, 3350 { 0x0093, sent|defwinproc|optional }, 3351 { 0x0093, sent|defwinproc|optional }, 3352 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3353 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3354 { 0x0093, sent|optional }, 3355 3356 { WM_NCACTIVATE, sent|wparam, 0 }, 3357 { WM_MDIACTIVATE, sent }, 3358 3359 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWNORMAL }, 3360 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_STATECHANGED }, 3361 { WM_NCCALCSIZE, sent|wparam, 1 }, 3362 3363 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 3364 3365 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 3366 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 3367 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 3368 3369 /* in MDI child */ 3370 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3371 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, 3372 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3373 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3374 3375 /* in MDI frame */ 3376 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3377 { WM_NCCALCSIZE, sent|wparam, 1 }, 3378 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3379 { WM_MOVE, sent|defwinproc }, 3380 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 3381 3382 /* in MDI client */ 3383 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE }, 3384 { WM_NCCALCSIZE, sent|wparam, 1 }, 3385 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOCLIENTMOVE }, 3386 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 3387 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3388 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* XP */ 3389 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */ 3390 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3391 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* XP sends a duplicate */ 3392 3393 { HCBT_SETFOCUS, hook }, 3394 { WM_KILLFOCUS, sent }, 3395 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 3396 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 3397 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3398 { WM_SETFOCUS, sent }, /* in MDI client */ 3399 3400 { WM_MDIREFRESHMENU, sent }, /* in MDI client */ 3401 3402 { HCBT_DESTROYWND, hook }, 3403 /* Win2k sends wparam set to 3404 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated), 3405 * while Win9x doesn't bother to set child window id according to 3406 * CLIENTCREATESTRUCT.idFirstChild 3407 */ 3408 { 0x0090, sent|optional }, 3409 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */ 3410 3411 { WM_SHOWWINDOW, sent|wparam, 0 }, 3412 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3413 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 3414 { WM_ERASEBKGND, sent|parent|optional }, 3415 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3416 3417 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, 3418 { WM_DESTROY, sent }, 3419 { WM_NCDESTROY, sent }, 3420 { 0 } 3421 }; 3422 /* ShowWindow(SW_MAXIMIZE) for a not visible MDI child window */ 3423 static const struct message WmMaximizeMDIchildInvisibleSeq[] = { 3424 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 3425 { WM_GETMINMAXINFO, sent }, 3426 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_STATECHANGED }, 3427 { WM_NCCALCSIZE, sent|wparam, 1 }, 3428 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 3429 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 3430 3431 { WM_WINDOWPOSCHANGING, sent|wparam|optional|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3432 { WM_NCACTIVATE, sent|wparam|optional|defwinproc, 1 }, 3433 { HCBT_SETFOCUS, hook|optional }, 3434 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 3435 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3436 { WM_SETFOCUS, sent|optional }, /* in MDI client */ 3437 { HCBT_SETFOCUS, hook|optional }, 3438 { WM_KILLFOCUS, sent|optional }, /* in MDI client */ 3439 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 3440 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 3441 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3442 { WM_SETFOCUS, sent|optional|defwinproc }, 3443 { WM_MDIACTIVATE, sent|optional|defwinproc }, 3444 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 3445 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 3446 /* in MDI frame */ 3447 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3448 { WM_NCCALCSIZE, sent|wparam, 1 }, 3449 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3450 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3451 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3452 { 0 } 3453 }; 3454 /* ShowWindow(SW_MAXIMIZE) for a not visible maximized MDI child window */ 3455 static const struct message WmMaximizeMDIchildInvisibleSeq2[] = { 3456 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 3457 { WM_GETMINMAXINFO, sent }, 3458 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED }, 3459 { WM_GETMINMAXINFO, sent|defwinproc }, 3460 { WM_NCCALCSIZE, sent|wparam, 1 }, 3461 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 3462 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 3463 3464 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc|optional, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3465 { WM_NCACTIVATE, sent|wparam|defwinproc|optional, 1 }, 3466 { HCBT_SETFOCUS, hook|optional }, 3467 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 3468 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3469 { WM_SETFOCUS, sent|optional }, /* in MDI client */ 3470 { HCBT_SETFOCUS, hook|optional }, 3471 { WM_KILLFOCUS, sent|optional }, /* in MDI client */ 3472 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 3473 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 3474 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3475 { WM_SETFOCUS, sent|defwinproc|optional }, 3476 { WM_MDIACTIVATE, sent|defwinproc|optional }, 3477 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3478 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3479 { WM_SIZE, sent|defwinproc|optional }, 3480 { 0 } 3481 }; 3482 /* WM_MDIMAXIMIZE for an MDI child window with invisible parent */ 3483 static const struct message WmMaximizeMDIchildInvisibleParentSeq[] = { 3484 { WM_MDIMAXIMIZE, sent }, /* in MDI client */ 3485 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 3486 { WM_GETMINMAXINFO, sent }, 3487 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, 3488 { WM_GETMINMAXINFO, sent|defwinproc }, 3489 { WM_NCCALCSIZE, sent|wparam, 1 }, 3490 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP doesn't send it */ 3491 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 3492 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOREDRAW|SWP_STATECHANGED }, 3493 { WM_MOVE, sent|defwinproc }, 3494 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 3495 3496 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3497 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, 3498 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3499 { WM_NCCALCSIZE, sent|wparam|defwinproc|optional, 1 }, 3500 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI child XP */ 3501 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI client XP */ 3502 /* in MDI frame */ 3503 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3504 { WM_NCCALCSIZE, sent|wparam, 1 }, 3505 { 0x0093, sent|defwinproc|optional }, 3506 { 0x0094, sent|defwinproc|optional }, 3507 { 0x0094, sent|defwinproc|optional }, 3508 { 0x0094, sent|defwinproc|optional }, 3509 { 0x0094, sent|defwinproc|optional }, 3510 { 0x0093, sent|defwinproc|optional }, 3511 { 0x0093, sent|defwinproc|optional }, 3512 { 0x0091, sent|defwinproc|optional }, 3513 { 0x0092, sent|defwinproc|optional }, 3514 { 0x0092, sent|defwinproc|optional }, 3515 { 0x0092, sent|defwinproc|optional }, 3516 { 0x0092, sent|defwinproc|optional }, 3517 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3518 { WM_MOVE, sent|defwinproc }, 3519 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 3520 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI frame win2000 */ 3521 /* in MDI client */ 3522 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE }, 3523 { WM_NCCALCSIZE, sent|wparam, 1 }, 3524 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE }, 3525 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 3526 /* in MDI child */ 3527 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE }, 3528 { WM_GETMINMAXINFO, sent|defwinproc }, 3529 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, 3530 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE }, 3531 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 3532 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI child win2000 */ 3533 { WM_NCCALCSIZE, sent|wparam|defwinproc|optional, 1 }, 3534 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI child XP */ 3535 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI child XP */ 3536 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI client XP */ 3537 /* in MDI frame */ 3538 { 0x0093, sent|optional }, 3539 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, 3540 { 0x0093, sent|defwinproc|optional }, 3541 { 0x0093, sent|defwinproc|optional }, 3542 { 0x0093, sent|defwinproc|optional }, 3543 { 0x0091, sent|defwinproc|optional }, 3544 { 0x0092, sent|defwinproc|optional }, 3545 { 0x0092, sent|defwinproc|optional }, 3546 { 0x0092, sent|defwinproc|optional }, 3547 { 0x0092, sent|defwinproc|optional }, 3548 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI frame XP */ 3549 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI frame XP */ 3550 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI child XP */ 3551 { 0 } 3552 }; 3553 /* ShowWindow(SW_MAXIMIZE) for a visible MDI child window */ 3554 static const struct message WmMaximizeMDIchildVisibleSeq[] = { 3555 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 3556 { WM_GETMINMAXINFO, sent }, 3557 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, 3558 { WM_NCCALCSIZE, sent|wparam, 1 }, 3559 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 3560 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 3561 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 3562 /* in MDI frame */ 3563 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3564 { WM_NCCALCSIZE, sent|wparam, 1 }, 3565 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3566 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3567 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3568 { 0 } 3569 }; 3570 /* ShowWindow(SW_RESTORE) for a visible maximized MDI child window */ 3571 static const struct message WmRestoreMDIchildVisibleSeq[] = { 3572 { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE }, 3573 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, 3574 { WM_NCCALCSIZE, sent|wparam, 1 }, 3575 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 3576 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 3577 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 3578 /* in MDI frame */ 3579 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3580 { WM_NCCALCSIZE, sent|wparam, 1 }, 3581 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3582 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3583 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3584 { 0 } 3585 }; 3586 /* ShowWindow(SW_RESTORE) for a visible minimized MDI child window */ 3587 static const struct message WmRestoreMDIchildVisibleSeq_2[] = { 3588 { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE }, 3589 { WM_QUERYOPEN, sent|wparam|lparam, 0, 0 }, 3590 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 3591 { WM_NCCALCSIZE, sent|wparam, 1 }, 3592 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 3593 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 3594 { WM_MOVE, sent|defwinproc }, 3595 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 3596 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3597 { EVENT_SYSTEM_MINIMIZEEND, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3598 { HCBT_SETFOCUS, hook }, 3599 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 3600 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 3601 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3602 { WM_SETFOCUS, sent }, 3603 { 0 } 3604 }; 3605 /* ShowWindow(SW_MINIMIZE) for a visible restored MDI child window */ 3606 static const struct message WmMinimizeMDIchildVisibleSeq[] = { 3607 { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, 3608 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_STATECHANGED }, 3609 { WM_NCCALCSIZE, sent|wparam, 1 }, 3610 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_STATECHANGED }, 3611 { WM_MOVE, sent|defwinproc }, 3612 { WM_SIZE, sent|defwinproc|wparam|lparam, SIZE_MINIMIZED, 0 }, 3613 { WM_CHILDACTIVATE, sent|wparam|lparam|defwinproc, 0, 0 }, 3614 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3615 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3616 /* FIXME: Wine creates an icon/title window while Windows doesn't */ 3617 { WM_PARENTNOTIFY, sent|parent|wparam|optional, WM_CREATE }, /* MDI client */ 3618 { 0 } 3619 }; 3620 /* ShowWindow(SW_RESTORE) for a not visible MDI child window */ 3621 static const struct message WmRestoreMDIchildInvisibleSeq[] = { 3622 { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE }, 3623 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_STATECHANGED }, 3624 { WM_NCCALCSIZE, sent|wparam, 1 }, 3625 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 3626 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 3627 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 3628 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 3629 /* in MDI frame */ 3630 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3631 { WM_NCCALCSIZE, sent|wparam, 1 }, 3632 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3633 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3634 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3635 { 0 } 3636 }; 3637 3638 static HWND mdi_client; 3639 static WNDPROC old_mdi_client_proc; 3640 3641 static LRESULT WINAPI mdi_client_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 3642 { 3643 struct recvd_message msg; 3644 3645 /* do not log painting messages */ 3646 if (message != WM_PAINT && 3647 message != WM_NCPAINT && 3648 message != WM_SYNCPAINT && 3649 message != WM_ERASEBKGND && 3650 message != WM_NCHITTEST && 3651 message != WM_GETTEXT && 3652 message != WM_MDIGETACTIVE && 3653 !ignore_message( message )) 3654 { 3655 msg.hwnd = hwnd; 3656 msg.message = message; 3657 msg.flags = sent|wparam|lparam; 3658 msg.wParam = wParam; 3659 msg.lParam = lParam; 3660 msg.descr = "mdi client"; 3661 add_message(&msg); 3662 } 3663 3664 return CallWindowProcA(old_mdi_client_proc, hwnd, message, wParam, lParam); 3665 } 3666 3667 static LRESULT WINAPI mdi_child_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 3668 { 3669 static LONG defwndproc_counter = 0; 3670 LRESULT ret; 3671 struct recvd_message msg; 3672 3673 /* do not log painting messages */ 3674 if (message != WM_PAINT && 3675 message != WM_NCPAINT && 3676 message != WM_SYNCPAINT && 3677 message != WM_ERASEBKGND && 3678 message != WM_NCHITTEST && 3679 message != WM_GETTEXT && 3680 !ignore_message( message )) 3681 { 3682 switch (message) 3683 { 3684 case WM_MDIACTIVATE: 3685 { 3686 HWND active, client = GetParent(hwnd); 3687 3688 active = (HWND)SendMessageA(client, WM_MDIGETACTIVE, 0, 0); 3689 3690 if (hwnd == (HWND)lParam) /* if we are being activated */ 3691 ok (active == (HWND)lParam, "new active %p != active %p\n", (HWND)lParam, active); 3692 else 3693 ok (active == (HWND)wParam, "old active %p != active %p\n", (HWND)wParam, active); 3694 break; 3695 } 3696 } 3697 3698 msg.hwnd = hwnd; 3699 msg.message = message; 3700 msg.flags = sent|wparam|lparam; 3701 if (defwndproc_counter) msg.flags |= defwinproc; 3702 msg.wParam = wParam; 3703 msg.lParam = lParam; 3704 msg.descr = "mdi child"; 3705 add_message(&msg); 3706 } 3707 3708 defwndproc_counter++; 3709 ret = DefMDIChildProcA(hwnd, message, wParam, lParam); 3710 defwndproc_counter--; 3711 3712 return ret; 3713 } 3714 3715 static LRESULT WINAPI mdi_frame_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 3716 { 3717 static LONG defwndproc_counter = 0; 3718 LRESULT ret; 3719 struct recvd_message msg; 3720 3721 /* do not log painting messages */ 3722 if (message != WM_PAINT && 3723 message != WM_NCPAINT && 3724 message != WM_SYNCPAINT && 3725 message != WM_ERASEBKGND && 3726 message != WM_NCHITTEST && 3727 message != WM_GETTEXT && 3728 !ignore_message( message )) 3729 { 3730 msg.hwnd = hwnd; 3731 msg.message = message; 3732 msg.flags = sent|wparam|lparam; 3733 if (defwndproc_counter) msg.flags |= defwinproc; 3734 msg.wParam = wParam; 3735 msg.lParam = lParam; 3736 msg.descr = "mdi frame"; 3737 add_message(&msg); 3738 } 3739 3740 defwndproc_counter++; 3741 ret = DefFrameProcA(hwnd, mdi_client, message, wParam, lParam); 3742 defwndproc_counter--; 3743 3744 return ret; 3745 } 3746 3747 static BOOL mdi_RegisterWindowClasses(void) 3748 { 3749 WNDCLASSA cls; 3750 3751 cls.style = 0; 3752 cls.lpfnWndProc = mdi_frame_wnd_proc; 3753 cls.cbClsExtra = 0; 3754 cls.cbWndExtra = 0; 3755 cls.hInstance = GetModuleHandleA(0); 3756 cls.hIcon = 0; 3757 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 3758 cls.hbrBackground = GetStockObject(WHITE_BRUSH); 3759 cls.lpszMenuName = NULL; 3760 cls.lpszClassName = "MDI_frame_class"; 3761 if (!RegisterClassA(&cls)) return FALSE; 3762 3763 cls.lpfnWndProc = mdi_child_wnd_proc; 3764 cls.lpszClassName = "MDI_child_class"; 3765 if (!RegisterClassA(&cls)) return FALSE; 3766 3767 if (!GetClassInfoA(0, "MDIClient", &cls)) assert(0); 3768 old_mdi_client_proc = cls.lpfnWndProc; 3769 cls.hInstance = GetModuleHandleA(0); 3770 cls.lpfnWndProc = mdi_client_hook_proc; 3771 cls.lpszClassName = "MDI_client_class"; 3772 if (!RegisterClassA(&cls)) assert(0); 3773 3774 return TRUE; 3775 } 3776 3777 static void test_mdi_messages(void) 3778 { 3779 MDICREATESTRUCTA mdi_cs; 3780 CLIENTCREATESTRUCT client_cs; 3781 HWND mdi_frame, mdi_child, mdi_child2, active_child; 3782 BOOL zoomed; 3783 RECT rc; 3784 HMENU hMenu = CreateMenu(); 3785 LONG val; 3786 3787 if (!mdi_RegisterWindowClasses()) assert(0); 3788 3789 flush_sequence(); 3790 3791 trace("creating MDI frame window\n"); 3792 mdi_frame = CreateWindowExA(0, "MDI_frame_class", "MDI frame window", 3793 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | 3794 WS_MAXIMIZEBOX | WS_VISIBLE, 3795 100, 100, CW_USEDEFAULT, CW_USEDEFAULT, 3796 GetDesktopWindow(), hMenu, 3797 GetModuleHandleA(0), NULL); 3798 assert(mdi_frame); 3799 ok_sequence(WmCreateMDIframeSeq, "Create MDI frame window", FALSE); 3800 3801 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 3802 ok(GetFocus() == mdi_frame, "wrong focus window %p\n", GetFocus()); 3803 3804 trace("creating MDI client window\n"); 3805 GetClientRect(mdi_frame, &rc); 3806 client_cs.hWindowMenu = 0; 3807 client_cs.idFirstChild = MDI_FIRST_CHILD_ID; 3808 mdi_client = CreateWindowExA(0, "MDI_client_class", 3809 NULL, 3810 WS_CHILD | WS_VISIBLE | MDIS_ALLCHILDSTYLES, 3811 rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, 3812 mdi_frame, 0, GetModuleHandleA(0), &client_cs); 3813 assert(mdi_client); 3814 SetWindowLongA(mdi_client, 0, 0xdeadbeef); 3815 3816 ok_sequence(WmCreateMDIclientSeq, "Create visible MDI client window", FALSE); 3817 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 3818 ok(GetFocus() == mdi_frame, "input focus should be on MDI frame not on %p\n", GetFocus()); 3819 3820 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 3821 ok(!active_child, "wrong active MDI child %p\n", active_child); 3822 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 3823 3824 SetFocus(0); 3825 flush_sequence(); 3826 3827 trace("creating invisible MDI child window\n"); 3828 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", 3829 WS_CHILD, 3830 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 3831 mdi_client, 0, GetModuleHandleA(0), NULL); 3832 assert(mdi_child); 3833 3834 flush_sequence(); 3835 ShowWindow(mdi_child, SW_SHOWNORMAL); 3836 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOWNORMAL) MDI child window", FALSE); 3837 3838 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n"); 3839 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n"); 3840 3841 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 3842 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 3843 3844 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 3845 ok(!active_child, "wrong active MDI child %p\n", active_child); 3846 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 3847 3848 ShowWindow(mdi_child, SW_HIDE); 3849 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE) MDI child window", FALSE); 3850 flush_sequence(); 3851 3852 ShowWindow(mdi_child, SW_SHOW); 3853 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW) MDI child window", FALSE); 3854 3855 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n"); 3856 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n"); 3857 3858 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 3859 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 3860 3861 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 3862 ok(!active_child, "wrong active MDI child %p\n", active_child); 3863 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 3864 3865 DestroyWindow(mdi_child); 3866 flush_sequence(); 3867 3868 trace("creating visible MDI child window\n"); 3869 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", 3870 WS_CHILD | WS_VISIBLE, 3871 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 3872 mdi_client, 0, GetModuleHandleA(0), NULL); 3873 assert(mdi_child); 3874 ok_sequence(WmCreateMDIchildVisibleSeq, "Create visible MDI child window", FALSE); 3875 3876 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n"); 3877 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n"); 3878 3879 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 3880 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus()); 3881 3882 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 3883 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child); 3884 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 3885 flush_sequence(); 3886 3887 DestroyWindow(mdi_child); 3888 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE); 3889 3890 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 3891 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 3892 3893 /* Win2k: MDI client still returns a just destroyed child as active 3894 * Win9x: MDI client returns 0 3895 */ 3896 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 3897 ok(active_child == mdi_child || /* win2k */ 3898 !active_child, /* win9x */ 3899 "wrong active MDI child %p\n", active_child); 3900 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 3901 3902 flush_sequence(); 3903 3904 trace("creating invisible MDI child window\n"); 3905 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", 3906 WS_CHILD, 3907 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 3908 mdi_client, 0, GetModuleHandleA(0), NULL); 3909 assert(mdi_child2); 3910 ok_sequence(WmCreateMDIchildInvisibleSeq, "Create invisible MDI child window", FALSE); 3911 3912 ok(!(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE), "MDI child should not be visible\n"); 3913 ok(!IsWindowVisible(mdi_child2), "MDI child should not be visible\n"); 3914 3915 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 3916 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 3917 3918 /* Win2k: MDI client still returns a just destroyed child as active 3919 * Win9x: MDI client returns mdi_child2 3920 */ 3921 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 3922 ok(active_child == mdi_child || /* win2k */ 3923 active_child == mdi_child2, /* win9x */ 3924 "wrong active MDI child %p\n", active_child); 3925 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 3926 flush_sequence(); 3927 3928 ShowWindow(mdi_child2, SW_MAXIMIZE); 3929 ok_sequence(WmMaximizeMDIchildInvisibleSeq, "ShowWindow(SW_MAXIMIZE):invisible MDI child", FALSE); 3930 3931 ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n"); 3932 ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n"); 3933 3934 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 3935 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); 3936 ok(zoomed, "wrong zoomed state %d\n", zoomed); 3937 flush_sequence(); 3938 3939 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 3940 ok(GetFocus() == mdi_child2 || /* win2k */ 3941 GetFocus() == 0, /* win9x */ 3942 "wrong focus window %p\n", GetFocus()); 3943 3944 SetFocus(0); 3945 flush_sequence(); 3946 3947 ShowWindow(mdi_child2, SW_HIDE); 3948 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE); 3949 3950 ShowWindow(mdi_child2, SW_RESTORE); 3951 ok_sequence(WmRestoreMDIchildInvisibleSeq, "ShowWindow(SW_RESTORE):invisible MDI child", FALSE); 3952 flush_sequence(); 3953 3954 ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n"); 3955 ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n"); 3956 3957 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 3958 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); 3959 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 3960 flush_sequence(); 3961 3962 SetFocus(0); 3963 flush_sequence(); 3964 3965 ShowWindow(mdi_child2, SW_HIDE); 3966 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE); 3967 3968 ShowWindow(mdi_child2, SW_SHOW); 3969 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):MDI child", FALSE); 3970 3971 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 3972 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 3973 3974 ShowWindow(mdi_child2, SW_MAXIMIZE); 3975 ok_sequence(WmMaximizeMDIchildVisibleSeq, "ShowWindow(SW_MAXIMIZE):MDI child", FALSE); 3976 3977 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 3978 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 3979 3980 ShowWindow(mdi_child2, SW_RESTORE); 3981 ok_sequence(WmRestoreMDIchildVisibleSeq, "ShowWindow(SW_RESTORE):maximized MDI child", FALSE); 3982 3983 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 3984 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 3985 3986 ShowWindow(mdi_child2, SW_MINIMIZE); 3987 ok_sequence(WmMinimizeMDIchildVisibleSeq, "ShowWindow(SW_MINIMIZE):MDI child", FALSE); 3988 3989 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 3990 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 3991 3992 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 3993 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); 3994 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 3995 flush_sequence(); 3996 3997 ShowWindow(mdi_child2, SW_RESTORE); 3998 ok_sequence(WmRestoreMDIchildVisibleSeq_2, "ShowWindow(SW_RESTORE):minimized MDI child", FALSE); 3999 4000 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4001 ok(GetFocus() == mdi_child2, "wrong focus window %p\n", GetFocus()); 4002 4003 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4004 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); 4005 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 4006 flush_sequence(); 4007 4008 SetFocus(0); 4009 flush_sequence(); 4010 4011 ShowWindow(mdi_child2, SW_HIDE); 4012 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE); 4013 4014 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4015 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 4016 4017 DestroyWindow(mdi_child2); 4018 ok_sequence(WmDestroyMDIchildInvisibleSeq, "Destroy invisible MDI child window", FALSE); 4019 4020 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4021 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 4022 4023 trace("Testing WM_CHILDACTIVATE\n"); 4024 4025 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", 4026 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_DISABLED, 4027 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 4028 mdi_client, 0, GetModuleHandleA(0), NULL); 4029 4030 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", 4031 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX, 4032 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 4033 mdi_client, 0, GetModuleHandleA(0), NULL); 4034 4035 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4036 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); 4037 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 4038 4039 flush_sequence(); 4040 SendMessageW(mdi_child, WM_CHILDACTIVATE, 0, 0); 4041 ok_sequence(WmChildActivateDisabledWindowSeq, "WM_CHILDACTIVATE sent to disabled window", FALSE); 4042 4043 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4044 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); 4045 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 4046 flush_sequence(); 4047 4048 EnableWindow(mdi_child, TRUE); 4049 4050 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4051 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); 4052 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 4053 4054 flush_sequence(); 4055 SendMessageW(mdi_child, WM_CHILDACTIVATE, 0, 0); 4056 ok_sequence(WmChildActivateWindowSeq, "WM_CHILDACTIVATE sent to enabled window", FALSE); 4057 4058 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4059 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child); 4060 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 4061 flush_sequence(); 4062 4063 DestroyWindow(mdi_child); 4064 DestroyWindow(mdi_child2); 4065 flush_sequence(); 4066 4067 /* test for maximized MDI children */ 4068 trace("creating maximized visible MDI child window 1\n"); 4069 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", 4070 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE, 4071 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 4072 mdi_client, 0, GetModuleHandleA(0), NULL); 4073 assert(mdi_child); 4074 ok_sequence(WmCreateMDIchildVisibleMaxSeq1, "Create maximized visible 1st MDI child window", TRUE); 4075 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n"); 4076 4077 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4078 ok(GetFocus() == mdi_child || /* win2k */ 4079 GetFocus() == 0, /* win9x */ 4080 "wrong focus window %p\n", GetFocus()); 4081 4082 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4083 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child); 4084 ok(zoomed, "wrong zoomed state %d\n", zoomed); 4085 flush_sequence(); 4086 4087 trace("creating maximized visible MDI child window 2\n"); 4088 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", 4089 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE, 4090 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 4091 mdi_client, 0, GetModuleHandleA(0), NULL); 4092 assert(mdi_child2); 4093 ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child 2 window", TRUE); 4094 ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized\n"); 4095 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n"); 4096 4097 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4098 ok(GetFocus() == mdi_child2, "wrong focus window %p\n", GetFocus()); 4099 4100 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4101 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); 4102 ok(zoomed, "wrong zoomed state %d\n", zoomed); 4103 flush_sequence(); 4104 4105 trace("destroying maximized visible MDI child window 2\n"); 4106 DestroyWindow(mdi_child2); 4107 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE); 4108 4109 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n"); 4110 4111 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4112 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 4113 4114 /* Win2k: MDI client still returns a just destroyed child as active 4115 * Win9x: MDI client returns 0 4116 */ 4117 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4118 ok(active_child == mdi_child2 || /* win2k */ 4119 !active_child, /* win9x */ 4120 "wrong active MDI child %p\n", active_child); 4121 flush_sequence(); 4122 4123 ShowWindow(mdi_child, SW_MAXIMIZE); 4124 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n"); 4125 flush_sequence(); 4126 4127 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4128 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus()); 4129 4130 trace("re-creating maximized visible MDI child window 2\n"); 4131 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", 4132 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE, 4133 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 4134 mdi_client, 0, GetModuleHandleA(0), NULL); 4135 assert(mdi_child2); 4136 ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child 2 window", TRUE); 4137 ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized\n"); 4138 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n"); 4139 4140 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4141 ok(GetFocus() == mdi_child2, "wrong focus window %p\n", GetFocus()); 4142 4143 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4144 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); 4145 ok(zoomed, "wrong zoomed state %d\n", zoomed); 4146 flush_sequence(); 4147 4148 SendMessageA(mdi_child2, WM_SYSCOMMAND, SC_CLOSE, 0); 4149 ok_sequence(WmDestroyMDIchildVisibleMaxSeq2, "WM_SYSCOMMAND/SC_CLOSE on a visible maximized MDI child window", TRUE); 4150 ok(!IsWindow(mdi_child2), "MDI child 2 should be destroyed\n"); 4151 4152 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n"); 4153 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4154 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus()); 4155 4156 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4157 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child); 4158 ok(zoomed, "wrong zoomed state %d\n", zoomed); 4159 flush_sequence(); 4160 4161 DestroyWindow(mdi_child); 4162 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE); 4163 4164 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4165 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 4166 4167 /* Win2k: MDI client still returns a just destroyed child as active 4168 * Win9x: MDI client returns 0 4169 */ 4170 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4171 ok(active_child == mdi_child || /* win2k */ 4172 !active_child, /* win9x */ 4173 "wrong active MDI child %p\n", active_child); 4174 flush_sequence(); 4175 4176 trace("creating maximized invisible MDI child window\n"); 4177 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", 4178 WS_CHILD | WS_MAXIMIZE | WS_CAPTION | WS_THICKFRAME, 4179 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 4180 mdi_client, 0, GetModuleHandleA(0), NULL); 4181 assert(mdi_child2); 4182 ok_sequence(WmCreateMDIchildInvisibleMaxSeq4, "Create maximized invisible MDI child window", FALSE); 4183 ok(IsZoomed(mdi_child2), "MDI child should be maximized\n"); 4184 ok(!(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE), "MDI child should be not visible\n"); 4185 ok(!IsWindowVisible(mdi_child2), "MDI child should be not visible\n"); 4186 4187 /* Win2k: MDI client still returns a just destroyed child as active 4188 * Win9x: MDI client returns 0 4189 */ 4190 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4191 ok(active_child == mdi_child || /* win2k */ 4192 !active_child || active_child == mdi_child2, /* win9x */ 4193 "wrong active MDI child %p\n", active_child); 4194 flush_sequence(); 4195 4196 trace("call ShowWindow(mdi_child, SW_MAXIMIZE)\n"); 4197 ShowWindow(mdi_child2, SW_MAXIMIZE); 4198 ok_sequence(WmMaximizeMDIchildInvisibleSeq2, "ShowWindow(SW_MAXIMIZE):invisible maximized MDI child", FALSE); 4199 ok(IsZoomed(mdi_child2), "MDI child should be maximized\n"); 4200 ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n"); 4201 ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n"); 4202 4203 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4204 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); 4205 ok(zoomed, "wrong zoomed state %d\n", zoomed); 4206 flush_sequence(); 4207 4208 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child2, 0); 4209 flush_sequence(); 4210 4211 /* end of test for maximized MDI children */ 4212 SetFocus(0); 4213 flush_sequence(); 4214 trace("creating maximized visible MDI child window 1(Switch test)\n"); 4215 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", 4216 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE, 4217 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 4218 mdi_client, 0, GetModuleHandleA(0), NULL); 4219 assert(mdi_child); 4220 ok_sequence(WmCreateMDIchildVisibleMaxSeq1, "Create maximized visible 1st MDI child window(Switch test)", TRUE); 4221 ok(IsZoomed(mdi_child), "1st MDI child should be maximized(Switch test)\n"); 4222 4223 ok(GetActiveWindow() == mdi_frame, "wrong active window %p(Switch test)\n", GetActiveWindow()); 4224 ok(GetFocus() == mdi_child || /* win2k */ 4225 GetFocus() == 0, /* win9x */ 4226 "wrong focus window %p(Switch test)\n", GetFocus()); 4227 4228 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4229 ok(active_child == mdi_child, "wrong active MDI child %p(Switch test)\n", active_child); 4230 ok(zoomed, "wrong zoomed state %d(Switch test)\n", zoomed); 4231 flush_sequence(); 4232 4233 trace("creating maximized visible MDI child window 2(Switch test)\n"); 4234 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", 4235 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE, 4236 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 4237 mdi_client, 0, GetModuleHandleA(0), NULL); 4238 assert(mdi_child2); 4239 ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child window (Switch test)", TRUE); 4240 4241 ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized(Switch test)\n"); 4242 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized(Switch test)\n"); 4243 4244 ok(GetActiveWindow() == mdi_frame, "wrong active window %p(Switch test)\n", GetActiveWindow()); 4245 ok(GetFocus() == mdi_child2, "wrong focus window %p(Switch test)\n", GetFocus()); 4246 4247 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4248 ok(active_child == mdi_child2, "wrong active MDI child %p(Switch test)\n", active_child); 4249 ok(zoomed, "wrong zoomed state %d(Switch test)\n", zoomed); 4250 flush_sequence(); 4251 4252 trace("Switch child window.\n"); 4253 SendMessageA(mdi_client, WM_MDIACTIVATE, (WPARAM)mdi_child, 0); 4254 ok_sequence(WmSwitchChild, "Child did not switch correctly", TRUE); 4255 trace("end of test for switch maximized MDI children\n"); 4256 flush_sequence(); 4257 4258 /* Prepare for switching test of not maximized MDI children */ 4259 ShowWindow( mdi_child, SW_NORMAL ); 4260 ok(!IsZoomed(mdi_child), "wrong zoomed state for %p(Switch test)\n", mdi_child); 4261 ok(!IsZoomed(mdi_child2), "wrong zoomed state for %p(Switch test)\n", mdi_child2); 4262 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0); 4263 ok(active_child == mdi_child, "wrong active MDI child %p(Switch test)\n", active_child); 4264 flush_sequence(); 4265 4266 SendMessageA(mdi_client, WM_MDIACTIVATE, (WPARAM)mdi_child2, 0); 4267 ok_sequence(WmSwitchNotMaximizedChild, "Not maximized child did not switch correctly", FALSE); 4268 trace("end of test for switch not maximized MDI children\n"); 4269 flush_sequence(); 4270 4271 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0); 4272 flush_sequence(); 4273 4274 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child2, 0); 4275 flush_sequence(); 4276 4277 SetFocus(0); 4278 flush_sequence(); 4279 /* end of tests for switch maximized/not maximized MDI children */ 4280 4281 mdi_cs.szClass = "MDI_child_Class"; 4282 mdi_cs.szTitle = "MDI child"; 4283 mdi_cs.hOwner = GetModuleHandleA(0); 4284 mdi_cs.x = 0; 4285 mdi_cs.y = 0; 4286 mdi_cs.cx = CW_USEDEFAULT; 4287 mdi_cs.cy = CW_USEDEFAULT; 4288 mdi_cs.style = WS_CHILD | WS_SYSMENU | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE; 4289 mdi_cs.lParam = 0; 4290 mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs); 4291 ok(mdi_child != 0, "MDI child creation failed\n"); 4292 ok_sequence(WmCreateMDIchildVisibleMaxSeq3, "WM_MDICREATE for maximized visible MDI child window", TRUE); 4293 4294 ok(GetMenuItemID(hMenu, GetMenuItemCount(hMenu) - 1) == SC_CLOSE, "SC_CLOSE menu item not found\n"); 4295 4296 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4297 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child); 4298 4299 ok(IsZoomed(mdi_child), "MDI child should be maximized\n"); 4300 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4301 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus()); 4302 4303 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4304 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child); 4305 ok(zoomed, "wrong zoomed state %d\n", zoomed); 4306 flush_sequence(); 4307 4308 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0); 4309 ok_sequence(WmDestroyMDIchildVisibleMaxSeq1, "Destroy visible maximized MDI child window", TRUE); 4310 4311 ok(!IsWindow(mdi_child), "MDI child should be destroyed\n"); 4312 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4313 ok(!active_child, "wrong active MDI child %p\n", active_child); 4314 4315 SetFocus(0); 4316 flush_sequence(); 4317 4318 val = GetWindowLongA(mdi_client, 0); 4319 ok(val == 0xdeadbeef || broken(val == 0) /* >= Win Vista */, "Expected 0xdeadbeef, got 0x%x\n", val); 4320 DestroyWindow(mdi_client); 4321 ok_sequence(WmDestroyMDIclientSeq, "Destroy MDI client window", FALSE); 4322 4323 /* test maximization of MDI child with invisible parent */ 4324 client_cs.hWindowMenu = 0; 4325 mdi_client = CreateWindowA("MDI_client_class", 4326 NULL, 4327 WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL | WS_VISIBLE, 4328 0, 0, 660, 430, 4329 mdi_frame, 0, GetModuleHandleA(0), &client_cs); 4330 ok_sequence(WmCreateMDIclientSeq, "Create MDI client window", FALSE); 4331 4332 ShowWindow(mdi_client, SW_HIDE); 4333 ok_sequence(WmHideMDIclientSeq, "Hide MDI client window", FALSE); 4334 4335 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", 4336 WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL, 4337 0, 0, 650, 440, 4338 mdi_client, 0, GetModuleHandleA(0), NULL); 4339 ok_sequence(WmCreateMDIchildInvisibleParentSeq, "Create MDI child window with invisible parent", FALSE); 4340 4341 SendMessageA(mdi_client, WM_MDIMAXIMIZE, (WPARAM) mdi_child, 0); 4342 ok_sequence(WmMaximizeMDIchildInvisibleParentSeq, "Maximize MDI child window with invisible parent", TRUE); 4343 zoomed = IsZoomed(mdi_child); 4344 ok(zoomed, "wrong zoomed state %d\n", zoomed); 4345 4346 ShowWindow(mdi_client, SW_SHOW); 4347 ok_sequence(WmShowMDIclientSeq, "Show MDI client window", FALSE); 4348 4349 DestroyWindow(mdi_child); 4350 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible maximized MDI child window", TRUE); 4351 4352 /* end of test for maximization of MDI child with invisible parent */ 4353 4354 DestroyWindow(mdi_client); 4355 ok_sequence(WmDestroyMDIclientSeq, "Destroy MDI client window", FALSE); 4356 4357 DestroyWindow(mdi_frame); 4358 ok_sequence(WmDestroyMDIframeSeq, "Destroy MDI frame window", FALSE); 4359 } 4360 /************************* End of MDI test **********************************/ 4361 4362 static void test_WM_SETREDRAW(HWND hwnd) 4363 { 4364 DWORD style = GetWindowLongA(hwnd, GWL_STYLE); 4365 4366 flush_events(); 4367 flush_sequence(); 4368 4369 SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0); 4370 ok_sequence(WmSetRedrawFalseSeq, "SetRedraw:FALSE", FALSE); 4371 4372 ok(!(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should NOT be set\n"); 4373 ok(!IsWindowVisible(hwnd), "IsWindowVisible() should return FALSE\n"); 4374 4375 flush_sequence(); 4376 SendMessageA(hwnd, WM_SETREDRAW, TRUE, 0); 4377 ok_sequence(WmSetRedrawTrueSeq, "SetRedraw:TRUE", FALSE); 4378 4379 ok(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 4380 ok(IsWindowVisible(hwnd), "IsWindowVisible() should return TRUE\n"); 4381 4382 /* restore original WS_VISIBLE state */ 4383 SetWindowLongA(hwnd, GWL_STYLE, style); 4384 4385 flush_events(); 4386 flush_sequence(); 4387 } 4388 4389 static INT_PTR CALLBACK TestModalDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 4390 { 4391 struct recvd_message msg; 4392 4393 if (ignore_message( message )) return 0; 4394 4395 switch (message) 4396 { 4397 /* ignore */ 4398 case WM_MOUSEMOVE: 4399 case WM_NCMOUSEMOVE: 4400 case WM_NCMOUSELEAVE: 4401 case WM_SETCURSOR: 4402 return 0; 4403 case WM_NCHITTEST: 4404 return HTCLIENT; 4405 } 4406 4407 msg.hwnd = hwnd; 4408 msg.message = message; 4409 msg.flags = sent|wparam|lparam; 4410 msg.wParam = wParam; 4411 msg.lParam = lParam; 4412 msg.descr = "dialog"; 4413 add_message(&msg); 4414 4415 if (message == WM_INITDIALOG) SetTimer( hwnd, 1, 100, NULL ); 4416 if (message == WM_TIMER) EndDialog( hwnd, 0 ); 4417 return 0; 4418 } 4419 4420 static INT_PTR CALLBACK TestModalDlgProc2(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 4421 { 4422 struct recvd_message msg; 4423 4424 if (ignore_message( message )) return 0; 4425 4426 switch (message) 4427 { 4428 /* ignore */ 4429 case WM_MOUSEMOVE: 4430 case WM_NCMOUSEMOVE: 4431 case WM_NCMOUSELEAVE: 4432 case WM_SETCURSOR: 4433 return 0; 4434 case WM_NCHITTEST: 4435 return HTCLIENT; 4436 } 4437 4438 msg.hwnd = hwnd; 4439 msg.message = message; 4440 msg.flags = sent|wparam|lparam; 4441 msg.wParam = wParam; 4442 msg.lParam = lParam; 4443 msg.descr = "dialog"; 4444 add_message(&msg); 4445 4446 if (message == WM_INITDIALOG) EndDialog( hwnd, 0 ); 4447 return 0; 4448 } 4449 4450 static void test_hv_scroll_1(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max) 4451 { 4452 DWORD style, exstyle; 4453 INT xmin, xmax; 4454 BOOL ret; 4455 4456 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE); 4457 style = GetWindowLongA(hwnd, GWL_STYLE); 4458 /* do not be confused by WS_DLGFRAME set */ 4459 if ((style & WS_CAPTION) == WS_CAPTION) style &= ~WS_CAPTION; 4460 4461 if (clear) ok(style & clear, "style %08x should be set\n", clear); 4462 if (set) ok(!(style & set), "style %08x should not be set\n", set); 4463 4464 ret = SetScrollRange(hwnd, ctl, min, max, FALSE); 4465 ok( ret, "SetScrollRange(%d) error %d\n", ctl, GetLastError()); 4466 if ((style & (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME)) || (exstyle & WS_EX_DLGMODALFRAME)) 4467 ok_sequence(WmSetScrollRangeHV_NC_Seq, "SetScrollRange(SB_HORZ/SB_VERT) NC", FALSE); 4468 else 4469 ok_sequence(WmSetScrollRangeHVSeq, "SetScrollRange(SB_HORZ/SB_VERT)", FALSE); 4470 4471 style = GetWindowLongA(hwnd, GWL_STYLE); 4472 if (set) ok(style & set, "style %08x should be set\n", set); 4473 if (clear) ok(!(style & clear), "style %08x should not be set\n", clear); 4474 4475 /* a subsequent call should do nothing */ 4476 ret = SetScrollRange(hwnd, ctl, min, max, FALSE); 4477 ok( ret, "SetScrollRange(%d) error %d\n", ctl, GetLastError()); 4478 ok_sequence(WmEmptySeq, "SetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE); 4479 4480 xmin = 0xdeadbeef; 4481 xmax = 0xdeadbeef; 4482 ret = GetScrollRange(hwnd, ctl, &xmin, &xmax); 4483 ok( ret, "GetScrollRange(%d) error %d\n", ctl, GetLastError()); 4484 ok_sequence(WmEmptySeq, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE); 4485 ok(xmin == min, "unexpected min scroll value %d\n", xmin); 4486 ok(xmax == max, "unexpected max scroll value %d\n", xmax); 4487 } 4488 4489 static void test_hv_scroll_2(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max) 4490 { 4491 DWORD style, exstyle; 4492 SCROLLINFO si; 4493 BOOL ret; 4494 4495 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE); 4496 style = GetWindowLongA(hwnd, GWL_STYLE); 4497 /* do not be confused by WS_DLGFRAME set */ 4498 if ((style & WS_CAPTION) == WS_CAPTION) style &= ~WS_CAPTION; 4499 4500 if (clear) ok(style & clear, "style %08x should be set\n", clear); 4501 if (set) ok(!(style & set), "style %08x should not be set\n", set); 4502 4503 si.cbSize = sizeof(si); 4504 si.fMask = SIF_RANGE; 4505 si.nMin = min; 4506 si.nMax = max; 4507 SetScrollInfo(hwnd, ctl, &si, TRUE); 4508 if ((style & (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME)) || (exstyle & WS_EX_DLGMODALFRAME)) 4509 ok_sequence(WmSetScrollRangeHV_NC_Seq, "SetScrollInfo(SB_HORZ/SB_VERT) NC", FALSE); 4510 else 4511 ok_sequence(WmSetScrollRangeHVSeq, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE); 4512 4513 style = GetWindowLongA(hwnd, GWL_STYLE); 4514 if (set) ok(style & set, "style %08x should be set\n", set); 4515 if (clear) ok(!(style & clear), "style %08x should not be set\n", clear); 4516 4517 /* a subsequent call should do nothing */ 4518 SetScrollInfo(hwnd, ctl, &si, TRUE); 4519 if (style & WS_HSCROLL) 4520 ok_sequence(WmSetScrollRangeHSeq_empty, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE); 4521 else if (style & WS_VSCROLL) 4522 ok_sequence(WmSetScrollRangeVSeq_empty, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE); 4523 else 4524 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE); 4525 4526 si.fMask = SIF_PAGE; 4527 si.nPage = 5; 4528 SetScrollInfo(hwnd, ctl, &si, FALSE); 4529 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE); 4530 4531 si.fMask = SIF_POS; 4532 si.nPos = max - 1; 4533 SetScrollInfo(hwnd, ctl, &si, FALSE); 4534 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE); 4535 4536 si.fMask = SIF_RANGE; 4537 si.nMin = 0xdeadbeef; 4538 si.nMax = 0xdeadbeef; 4539 ret = GetScrollInfo(hwnd, ctl, &si); 4540 ok( ret, "GetScrollInfo error %d\n", GetLastError()); 4541 ok_sequence(WmEmptySeq, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE); 4542 ok(si.nMin == min, "unexpected min scroll value %d\n", si.nMin); 4543 ok(si.nMax == max, "unexpected max scroll value %d\n", si.nMax); 4544 } 4545 4546 /* Win9x sends WM_USER+xxx while and NT versions send SBM_xxx messages */ 4547 static void test_scroll_messages(HWND hwnd) 4548 { 4549 SCROLLINFO si; 4550 INT min, max; 4551 BOOL ret; 4552 4553 flush_events(); 4554 flush_sequence(); 4555 4556 min = 0xdeadbeef; 4557 max = 0xdeadbeef; 4558 ret = GetScrollRange(hwnd, SB_CTL, &min, &max); 4559 ok( ret, "GetScrollRange error %d\n", GetLastError()); 4560 if (sequence->message != WmGetScrollRangeSeq[0].message) 4561 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message); 4562 /* values of min and max are undefined */ 4563 flush_sequence(); 4564 4565 ret = SetScrollRange(hwnd, SB_CTL, 10, 150, FALSE); 4566 ok( ret, "SetScrollRange error %d\n", GetLastError()); 4567 if (sequence->message != WmSetScrollRangeSeq[0].message) 4568 trace("SetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message); 4569 flush_sequence(); 4570 4571 min = 0xdeadbeef; 4572 max = 0xdeadbeef; 4573 ret = GetScrollRange(hwnd, SB_CTL, &min, &max); 4574 ok( ret, "GetScrollRange error %d\n", GetLastError()); 4575 if (sequence->message != WmGetScrollRangeSeq[0].message) 4576 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message); 4577 /* values of min and max are undefined */ 4578 flush_sequence(); 4579 4580 si.cbSize = sizeof(si); 4581 si.fMask = SIF_RANGE; 4582 si.nMin = 20; 4583 si.nMax = 160; 4584 SetScrollInfo(hwnd, SB_CTL, &si, FALSE); 4585 if (sequence->message != WmSetScrollRangeSeq[0].message) 4586 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message); 4587 flush_sequence(); 4588 4589 si.fMask = SIF_PAGE; 4590 si.nPage = 10; 4591 SetScrollInfo(hwnd, SB_CTL, &si, FALSE); 4592 if (sequence->message != WmSetScrollRangeSeq[0].message) 4593 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message); 4594 flush_sequence(); 4595 4596 si.fMask = SIF_POS; 4597 si.nPos = 20; 4598 SetScrollInfo(hwnd, SB_CTL, &si, FALSE); 4599 if (sequence->message != WmSetScrollRangeSeq[0].message) 4600 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message); 4601 flush_sequence(); 4602 4603 si.fMask = SIF_RANGE; 4604 si.nMin = 0xdeadbeef; 4605 si.nMax = 0xdeadbeef; 4606 ret = GetScrollInfo(hwnd, SB_CTL, &si); 4607 ok( ret, "GetScrollInfo error %d\n", GetLastError()); 4608 if (sequence->message != WmGetScrollInfoSeq[0].message) 4609 trace("GetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message); 4610 /* values of min and max are undefined */ 4611 flush_sequence(); 4612 4613 /* set WS_HSCROLL */ 4614 test_hv_scroll_1(hwnd, SB_HORZ, 0, WS_HSCROLL, 10, 150); 4615 /* clear WS_HSCROLL */ 4616 test_hv_scroll_1(hwnd, SB_HORZ, WS_HSCROLL, 0, 0, 0); 4617 4618 /* set WS_HSCROLL */ 4619 test_hv_scroll_2(hwnd, SB_HORZ, 0, WS_HSCROLL, 10, 150); 4620 /* clear WS_HSCROLL */ 4621 test_hv_scroll_2(hwnd, SB_HORZ, WS_HSCROLL, 0, 0, 0); 4622 4623 /* set WS_VSCROLL */ 4624 test_hv_scroll_1(hwnd, SB_VERT, 0, WS_VSCROLL, 10, 150); 4625 /* clear WS_VSCROLL */ 4626 test_hv_scroll_1(hwnd, SB_VERT, WS_VSCROLL, 0, 0, 0); 4627 4628 /* set WS_VSCROLL */ 4629 test_hv_scroll_2(hwnd, SB_VERT, 0, WS_VSCROLL, 10, 150); 4630 /* clear WS_VSCROLL */ 4631 test_hv_scroll_2(hwnd, SB_VERT, WS_VSCROLL, 0, 0, 0); 4632 } 4633 4634 static void test_showwindow(void) 4635 { 4636 HWND hwnd, hchild; 4637 RECT rc; 4638 4639 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW, 4640 100, 100, 200, 200, 0, 0, 0, NULL); 4641 ok (hwnd != 0, "Failed to create overlapped window\n"); 4642 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 4643 0, 0, 10, 10, hwnd, 0, 0, NULL); 4644 ok (hchild != 0, "Failed to create child\n"); 4645 flush_sequence(); 4646 4647 /* ShowWindow( SW_SHOWNA) for invisible top level window */ 4648 trace("calling ShowWindow( SW_SHOWNA) for invisible top level window\n"); 4649 ok( ShowWindow(hwnd, SW_SHOWNA) == FALSE, "ShowWindow: window was visible\n" ); 4650 ok_sequence(WmSHOWNATopInvisible, "ShowWindow(SW_SHOWNA) on invisible top level window", FALSE); 4651 4652 /* ShowWindow( SW_SHOWNA) for now visible top level window */ 4653 trace("calling ShowWindow( SW_SHOWNA) for now visible top level window\n"); 4654 ok( ShowWindow(hwnd, SW_SHOWNA) != FALSE, "ShowWindow: window was invisible\n" ); 4655 ok_sequence(WmSHOWNATopVisible, "ShowWindow(SW_SHOWNA) on visible top level window", FALSE); 4656 /* back to invisible */ 4657 ShowWindow(hchild, SW_HIDE); 4658 ShowWindow(hwnd, SW_HIDE); 4659 flush_sequence(); 4660 /* ShowWindow(SW_SHOWNA) with child and parent invisible */ 4661 trace("calling ShowWindow( SW_SHOWNA) for invisible child with invisible parent\n"); 4662 ok( ShowWindow(hchild, SW_SHOWNA) == FALSE, "ShowWindow: window was visible\n" ); 4663 ok_sequence(WmSHOWNAChildInvisParInvis, "ShowWindow(SW_SHOWNA) invisible child and parent", FALSE); 4664 /* ShowWindow(SW_SHOWNA) with child visible and parent invisible */ 4665 ok( ShowWindow(hchild, SW_SHOW) != FALSE, "ShowWindow: window was invisible\n" ); 4666 flush_sequence(); 4667 trace("calling ShowWindow( SW_SHOWNA) for the visible child and invisible parent\n"); 4668 ok( ShowWindow(hchild, SW_SHOWNA) != FALSE, "ShowWindow: window was invisible\n" ); 4669 ok_sequence(WmSHOWNAChildVisParInvis, "ShowWindow(SW_SHOWNA) visible child and invisible parent", FALSE); 4670 /* ShowWindow(SW_SHOWNA) with child visible and parent visible */ 4671 ShowWindow( hwnd, SW_SHOW); 4672 flush_sequence(); 4673 trace("calling ShowWindow( SW_SHOWNA) for the visible child and parent\n"); 4674 ok( ShowWindow(hchild, SW_SHOWNA) != FALSE, "ShowWindow: window was invisible\n" ); 4675 ok_sequence(WmSHOWNAChildVisParVis, "ShowWindow(SW_SHOWNA) for the visible child and parent", FALSE); 4676 4677 /* ShowWindow(SW_SHOWNA) with child invisible and parent visible */ 4678 ShowWindow( hchild, SW_HIDE); 4679 flush_sequence(); 4680 trace("calling ShowWindow( SW_SHOWNA) for the invisible child and visible parent\n"); 4681 ok( ShowWindow(hchild, SW_SHOWNA) == FALSE, "ShowWindow: window was visible\n" ); 4682 ok_sequence(WmSHOWNAChildInvisParVis, "ShowWindow(SW_SHOWNA) for the invisible child and visible parent", FALSE); 4683 4684 SetCapture(hchild); 4685 ok(GetCapture() == hchild, "wrong capture window %p\n", GetCapture()); 4686 DestroyWindow(hchild); 4687 ok(!GetCapture(), "wrong capture window %p\n", GetCapture()); 4688 4689 DestroyWindow(hwnd); 4690 flush_sequence(); 4691 4692 /* Popup windows */ 4693 /* Test 1: 4694 * 1. Create invisible maximized popup window. 4695 * 2. Move and resize it. 4696 * 3. Show it maximized. 4697 */ 4698 trace("calling CreateWindowExA( WS_MAXIMIZE ) for invisible maximized popup window\n"); 4699 hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_MAXIMIZE, 4700 100, 100, 200, 200, 0, 0, 0, NULL); 4701 ok (hwnd != 0, "Failed to create popup window\n"); 4702 ok(IsZoomed(hwnd), "window should be maximized\n"); 4703 ok_sequence(WmCreateInvisibleMaxPopupSeq, "CreateWindow(WS_MAXIMIZED):popup", FALSE); 4704 4705 GetWindowRect(hwnd, &rc); 4706 ok( rc.right-rc.left == GetSystemMetrics(SM_CXSCREEN) && 4707 rc.bottom-rc.top == GetSystemMetrics(SM_CYSCREEN), 4708 "Invalid maximized size before ShowWindow %s\n", wine_dbgstr_rect( &rc )); 4709 /* Reset window's size & position */ 4710 SetWindowPos(hwnd, 0, 10, 10, 200, 200, SWP_NOZORDER | SWP_NOACTIVATE); 4711 ok(IsZoomed(hwnd), "window should be maximized\n"); 4712 flush_sequence(); 4713 4714 trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible maximized popup window\n"); 4715 ShowWindow(hwnd, SW_SHOWMAXIMIZED); 4716 ok(IsZoomed(hwnd), "window should be maximized\n"); 4717 ok_sequence(WmShowMaxPopupResizedSeq, "ShowWindow(SW_SHOWMAXIMIZED):invisible maximized and resized popup", FALSE); 4718 4719 GetWindowRect(hwnd, &rc); 4720 ok( rc.right-rc.left == GetSystemMetrics(SM_CXSCREEN) && 4721 rc.bottom-rc.top == GetSystemMetrics(SM_CYSCREEN), 4722 "Invalid maximized size after ShowWindow %s\n", wine_dbgstr_rect( &rc )); 4723 DestroyWindow(hwnd); 4724 flush_sequence(); 4725 4726 /* Test 2: 4727 * 1. Create invisible maximized popup window. 4728 * 2. Show it maximized. 4729 */ 4730 trace("calling CreateWindowExA( WS_MAXIMIZE ) for invisible maximized popup window\n"); 4731 hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_MAXIMIZE, 4732 100, 100, 200, 200, 0, 0, 0, NULL); 4733 ok (hwnd != 0, "Failed to create popup window\n"); 4734 ok(IsZoomed(hwnd), "window should be maximized\n"); 4735 ok_sequence(WmCreateInvisibleMaxPopupSeq, "CreateWindow(WS_MAXIMIZED):popup", FALSE); 4736 4737 trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible maximized popup window\n"); 4738 ShowWindow(hwnd, SW_SHOWMAXIMIZED); 4739 ok(IsZoomed(hwnd), "window should be maximized\n"); 4740 ok_sequence(WmShowMaxPopupSeq, "ShowWindow(SW_SHOWMAXIMIZED):invisible maximized popup", FALSE); 4741 DestroyWindow(hwnd); 4742 flush_sequence(); 4743 4744 /* Test 3: 4745 * 1. Create visible maximized popup window. 4746 */ 4747 trace("calling CreateWindowExA( WS_MAXIMIZE ) for maximized popup window\n"); 4748 hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_MAXIMIZE | WS_VISIBLE, 4749 100, 100, 200, 200, 0, 0, 0, NULL); 4750 ok (hwnd != 0, "Failed to create popup window\n"); 4751 ok(IsZoomed(hwnd), "window should be maximized\n"); 4752 ok_sequence(WmCreateMaxPopupSeq, "CreateWindow(WS_MAXIMIZED):popup", FALSE); 4753 DestroyWindow(hwnd); 4754 flush_sequence(); 4755 4756 /* Test 4: 4757 * 1. Create visible popup window. 4758 * 2. Maximize it. 4759 */ 4760 trace("calling CreateWindowExA( WS_VISIBLE ) for popup window\n"); 4761 hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_VISIBLE, 4762 100, 100, 200, 200, 0, 0, 0, NULL); 4763 ok (hwnd != 0, "Failed to create popup window\n"); 4764 ok(!IsZoomed(hwnd), "window should NOT be maximized\n"); 4765 ok_sequence(WmCreatePopupSeq, "CreateWindow(WS_VISIBLE):popup", FALSE); 4766 4767 trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for visible popup window\n"); 4768 ShowWindow(hwnd, SW_SHOWMAXIMIZED); 4769 ok(IsZoomed(hwnd), "window should be maximized\n"); 4770 ok_sequence(WmShowVisMaxPopupSeq, "ShowWindow(SW_SHOWMAXIMIZED):popup", FALSE); 4771 DestroyWindow(hwnd); 4772 flush_sequence(); 4773 } 4774 4775 static void test_recursive_activation(void) 4776 { 4777 static const struct message seq[] = 4778 { 4779 { HCBT_ACTIVATE, hook }, 4780 { WM_NCACTIVATE, sent|wparam, TRUE }, 4781 { WM_ACTIVATE, sent|wparam, WA_ACTIVE }, 4782 { HCBT_ACTIVATE, hook }, 4783 { WM_NCACTIVATE, sent|wparam, FALSE }, 4784 { WM_ACTIVATE, sent|wparam, WA_INACTIVE }, 4785 { WM_SETFOCUS, sent|optional }, 4786 { 0 } 4787 }; 4788 HWND hwnd, recursive; 4789 4790 hwnd = CreateWindowExA(0, "SimpleWindowClass", NULL, WS_OVERLAPPED|WS_VISIBLE, 4791 100, 100, 200, 200, 0, 0, 0, NULL); 4792 ok(hwnd != 0, "Failed to create simple window\n"); 4793 4794 recursive = CreateWindowExA(0, "RecursiveActivationClass", NULL, WS_OVERLAPPED|WS_VISIBLE, 4795 10, 10, 50, 50, hwnd, 0, 0, NULL); 4796 ok(recursive != 0, "Failed to create recursive activation window\n"); 4797 SetActiveWindow(hwnd); 4798 4799 flush_sequence(); 4800 SetActiveWindow(recursive); 4801 ok_sequence(seq, "Recursive Activation", FALSE); 4802 4803 DestroyWindow(recursive); 4804 DestroyWindow(hwnd); 4805 flush_sequence(); 4806 } 4807 4808 static void test_sys_menu(void) 4809 { 4810 HWND hwnd; 4811 HMENU hmenu; 4812 UINT state; 4813 4814 hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, 4815 100, 100, 200, 200, 0, 0, 0, NULL); 4816 ok (hwnd != 0, "Failed to create overlapped window\n"); 4817 4818 flush_sequence(); 4819 4820 /* test existing window without CS_NOCLOSE style */ 4821 hmenu = GetSystemMenu(hwnd, FALSE); 4822 ok(hmenu != 0, "GetSystemMenu error %d\n", GetLastError()); 4823 4824 state = GetMenuState(hmenu, SC_CLOSE, MF_BYCOMMAND); 4825 ok(state != 0xffffffff, "wrong SC_CLOSE state %x\n", state); 4826 ok(!(state & (MF_DISABLED | MF_GRAYED)), "wrong SC_CLOSE state %x\n", state); 4827 4828 EnableMenuItem(hmenu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED); 4829 ok_sequence(WmEmptySeq, "WmEnableMenuItem", FALSE); 4830 4831 state = GetMenuState(hmenu, SC_CLOSE, MF_BYCOMMAND); 4832 ok(state != 0xffffffff, "wrong SC_CLOSE state %x\n", state); 4833 ok((state & (MF_DISABLED | MF_GRAYED)) == MF_GRAYED, "wrong SC_CLOSE state %x\n", state); 4834 4835 EnableMenuItem(hmenu, SC_CLOSE, 0); 4836 ok_sequence(WmEmptySeq, "WmEnableMenuItem", FALSE); 4837 4838 state = GetMenuState(hmenu, SC_CLOSE, MF_BYCOMMAND); 4839 ok(state != 0xffffffff, "wrong SC_CLOSE state %x\n", state); 4840 ok(!(state & (MF_DISABLED | MF_GRAYED)), "wrong SC_CLOSE state %x\n", state); 4841 4842 /* test whether removing WS_SYSMENU destroys a system menu */ 4843 SetWindowLongW(hwnd, GWL_STYLE, WS_POPUP); 4844 SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_FRAMECHANGED); 4845 flush_sequence(); 4846 hmenu = GetSystemMenu(hwnd, FALSE); 4847 ok(hmenu != 0, "GetSystemMenu error %d\n", GetLastError()); 4848 4849 DestroyWindow(hwnd); 4850 4851 /* test new window with CS_NOCLOSE style */ 4852 hwnd = CreateWindowExA(0, "NoCloseWindowClass", NULL, WS_OVERLAPPEDWINDOW, 4853 100, 100, 200, 200, 0, 0, 0, NULL); 4854 ok (hwnd != 0, "Failed to create overlapped window\n"); 4855 4856 hmenu = GetSystemMenu(hwnd, FALSE); 4857 ok(hmenu != 0, "GetSystemMenu error %d\n", GetLastError()); 4858 4859 state = GetMenuState(hmenu, SC_CLOSE, MF_BYCOMMAND); 4860 ok(state == 0xffffffff, "wrong SC_CLOSE state %x\n", state); 4861 4862 DestroyWindow(hwnd); 4863 4864 /* test new window without WS_SYSMENU style */ 4865 hwnd = CreateWindowExA(0, "NoCloseWindowClass", NULL, WS_OVERLAPPEDWINDOW & ~WS_SYSMENU, 4866 100, 100, 200, 200, 0, 0, 0, NULL); 4867 ok(hwnd != 0, "Failed to create overlapped window\n"); 4868 4869 hmenu = GetSystemMenu(hwnd, FALSE); 4870 ok(!hmenu, "GetSystemMenu error %d\n", GetLastError()); 4871 4872 DestroyWindow(hwnd); 4873 } 4874 4875 /* For shown WS_OVERLAPPEDWINDOW */ 4876 static const struct message WmSetIcon_1[] = { 4877 { WM_SETICON, sent }, 4878 { 0x00AE, sent|defwinproc|optional }, /* XP */ 4879 { WM_GETTEXT, sent|defwinproc|optional }, 4880 { WM_GETTEXT, sent|defwinproc|optional }, /* XP sends a duplicate */ 4881 { 0 } 4882 }; 4883 4884 /* For WS_POPUP and hidden WS_OVERLAPPEDWINDOW */ 4885 static const struct message WmSetIcon_2[] = { 4886 { WM_SETICON, sent }, 4887 { 0 } 4888 }; 4889 4890 /* Sending undocumented 0x3B message with wparam = 0x8000000b */ 4891 static const struct message WmInitEndSession[] = { 4892 { 0x003B, sent }, 4893 { WM_QUERYENDSESSION, sent|defwinproc|wparam|lparam, 0, ENDSESSION_LOGOFF }, 4894 { 0 } 4895 }; 4896 4897 /* Sending undocumented 0x3B message with wparam = 0x0000000b */ 4898 static const struct message WmInitEndSession_2[] = { 4899 { 0x003B, sent }, 4900 { WM_QUERYENDSESSION, sent|defwinproc|wparam|lparam, 0, 0 }, 4901 { 0 } 4902 }; 4903 4904 /* Sending undocumented 0x3B message with wparam = 0x80000008 */ 4905 static const struct message WmInitEndSession_3[] = { 4906 { 0x003B, sent }, 4907 { WM_ENDSESSION, sent|defwinproc|wparam|lparam, 0, ENDSESSION_LOGOFF }, 4908 { 0 } 4909 }; 4910 4911 /* Sending undocumented 0x3B message with wparam = 0x00000008 */ 4912 static const struct message WmInitEndSession_4[] = { 4913 { 0x003B, sent }, 4914 { WM_ENDSESSION, sent|defwinproc|wparam|lparam, 0, 0 }, 4915 { 0 } 4916 }; 4917 4918 /* Sending undocumented 0x3B message with wparam = 0x80000001 */ 4919 static const struct message WmInitEndSession_5[] = { 4920 { 0x003B, sent }, 4921 { WM_ENDSESSION, sent|defwinproc/*|wparam*/|lparam, 1, ENDSESSION_LOGOFF }, 4922 { 0 } 4923 }; 4924 4925 static const struct message WmOptionalPaint[] = { 4926 { WM_PAINT, sent|optional }, 4927 { WM_NCPAINT, sent|beginpaint|optional }, 4928 { WM_GETTEXT, sent|beginpaint|defwinproc|optional }, 4929 { WM_ERASEBKGND, sent|beginpaint|optional }, 4930 { 0 } 4931 }; 4932 4933 static const struct message WmZOrder[] = { 4934 { WM_WINDOWPOSCHANGING, sent|wparam, 0, 0 }, 4935 { WM_GETMINMAXINFO, sent|defwinproc|wparam, 0, 0 }, 4936 { HCBT_ACTIVATE, hook }, 4937 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 4938 { WM_WINDOWPOSCHANGING, sent|wparam, 3, 0 }, 4939 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOREDRAW|SWP_NOMOVE|SWP_NOSIZE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE, 0 }, 4940 { WM_GETTEXT, sent|optional }, 4941 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, 4942 { WM_ACTIVATEAPP, sent|wparam, 1, 0 }, 4943 { WM_NCACTIVATE, sent|lparam, 1, 0 }, 4944 { WM_GETTEXT, sent|defwinproc|optional }, 4945 { WM_GETTEXT, sent|defwinproc|optional }, 4946 { WM_ACTIVATE, sent|wparam|lparam, 1, 0 }, 4947 { HCBT_SETFOCUS, hook }, 4948 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 4949 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 4950 { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, 4951 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 4952 { WM_GETTEXT, sent|optional }, 4953 { WM_NCCALCSIZE, sent|optional }, 4954 { 0 } 4955 }; 4956 4957 static void CALLBACK apc_test_proc(ULONG_PTR param) 4958 { 4959 /* nothing */ 4960 } 4961 4962 static void test_MsgWaitForMultipleObjects(HWND hwnd) 4963 { 4964 DWORD ret; 4965 MSG msg; 4966 4967 ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE); 4968 ok(ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjects returned %x\n", ret); 4969 4970 PostMessageA(hwnd, WM_USER, 0, 0); 4971 4972 ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE); 4973 ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjects returned %x\n", ret); 4974 4975 ok(PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n"); 4976 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message); 4977 4978 ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE); 4979 ok(ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjects returned %x\n", ret); 4980 4981 PostMessageA(hwnd, WM_USER, 0, 0); 4982 4983 ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE); 4984 ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjects returned %x\n", ret); 4985 4986 ok(PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ), "PeekMessage should succeed\n"); 4987 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message); 4988 4989 /* shows QS_POSTMESSAGE flag is cleared in the PeekMessage call */ 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 /* new incoming message causes it to become signaled again */ 4996 ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE); 4997 ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjects returned %x\n", ret); 4998 4999 ok(PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n"); 5000 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message); 5001 ok(PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n"); 5002 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message); 5003 5004 /* MWMO_INPUTAVAILABLE should succeed even if the message was already seen */ 5005 PostMessageA( hwnd, WM_USER, 0, 0 ); 5006 ok(PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ), "PeekMessage should succeed\n"); 5007 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message); 5008 5009 ret = MsgWaitForMultipleObjectsEx( 0, NULL, 0, QS_POSTMESSAGE, MWMO_INPUTAVAILABLE ); 5010 ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjectsEx returned %x\n", ret); 5011 5012 ok(PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n"); 5013 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message); 5014 5015 /* without MWMO_ALERTABLE the result is never WAIT_IO_COMPLETION */ 5016 ret = QueueUserAPC( apc_test_proc, GetCurrentThread(), 0 ); 5017 ok(ret, "QueueUserAPC failed %u\n", GetLastError()); 5018 5019 ret = MsgWaitForMultipleObjectsEx( 0, NULL, 0, QS_POSTMESSAGE, 0 ); 5020 ok(ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjectsEx returned %x\n", ret); 5021 5022 /* but even with MWMO_ALERTABLE window events are preferred */ 5023 PostMessageA( hwnd, WM_USER, 0, 0 ); 5024 5025 ret = MsgWaitForMultipleObjectsEx( 0, NULL, 0, QS_POSTMESSAGE, MWMO_ALERTABLE ); 5026 ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjectsEx returned %x\n", ret); 5027 5028 ok(PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n"); 5029 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message); 5030 5031 /* the APC call is still queued */ 5032 ret = MsgWaitForMultipleObjectsEx( 0, NULL, 0, QS_POSTMESSAGE, MWMO_ALERTABLE ); 5033 ok(ret == WAIT_IO_COMPLETION, "MsgWaitForMultipleObjectsEx returned %x\n", ret); 5034 } 5035 5036 static void test_WM_DEVICECHANGE(HWND hwnd) 5037 { 5038 DWORD ret; 5039 MSG msg; 5040 int i; 5041 static const WPARAM wparams[] = {0, 5042 DBT_DEVNODES_CHANGED, 5043 DBT_QUERYCHANGECONFIG, 5044 DBT_CONFIGCHANGED, 5045 DBT_CONFIGCHANGECANCELED, 5046 DBT_NO_DISK_SPACE, 5047 DBT_LOW_DISK_SPACE, 5048 DBT_CONFIGMGPRIVATE, /* 0x7fff */ 5049 DBT_DEVICEARRIVAL, /* 0x8000 */ 5050 DBT_DEVICEQUERYREMOVE, 5051 DBT_DEVICEQUERYREMOVEFAILED, 5052 DBT_DEVICEREMOVEPENDING, 5053 DBT_DEVICEREMOVECOMPLETE, 5054 DBT_DEVICETYPESPECIFIC, 5055 DBT_CUSTOMEVENT}; 5056 5057 for (i = 0; i < ARRAY_SIZE(wparams); i++) 5058 { 5059 SetLastError(0xdeadbeef); 5060 ret = PostMessageA(hwnd, WM_DEVICECHANGE, wparams[i], 0); 5061 if (wparams[i] & 0x8000) 5062 { 5063 ok(ret == FALSE, "PostMessage should returned %d\n", ret); 5064 ok(GetLastError() == ERROR_MESSAGE_SYNC_ONLY, "PostMessage error %08x\n", GetLastError()); 5065 } 5066 else 5067 { 5068 ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE); 5069 ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjects returned %x\n", ret); 5070 memset(&msg, 0, sizeof(msg)); 5071 ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "PeekMessage should succeed\n"); 5072 ok(msg.message == WM_DEVICECHANGE, "got %04x instead of WM_DEVICECHANGE\n", msg.message); 5073 } 5074 } 5075 } 5076 5077 static DWORD CALLBACK show_window_thread(LPVOID arg) 5078 { 5079 HWND hwnd = arg; 5080 5081 /* function will not return if ShowWindow(SW_HIDE) calls SendMessage() */ 5082 ok(ShowWindow(hwnd, SW_HIDE) == FALSE, "ShowWindow(SW_HIDE) expected FALSE\n"); 5083 5084 return 0; 5085 } 5086 5087 /* Helper function to easier test SetWindowPos messages */ 5088 #define test_msg_setpos( expected_list, flags, todo ) \ 5089 test_msg_setpos_( (expected_list), (flags), (todo), __FILE__, __LINE__) 5090 static void test_msg_setpos_(const struct message *expected_list, UINT flags, BOOL todo, const char *file, int line) 5091 { 5092 HWND hwnd; 5093 5094 flush_events(); 5095 flush_sequence(); 5096 hwnd = CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP, 5097 10, 10, 100, 100, NULL, 0, 0, NULL ); 5098 ok (hwnd != 0, "Failed to create popup window\n"); 5099 SetWindowPos(hwnd, NULL, 0, 0, 100, 100, flags); 5100 ok_sequence_(expected_list, "SetWindowPos:show_popup_first_show_window", todo, file, line); 5101 DestroyWindow(hwnd); 5102 } 5103 5104 /* test if we receive the right sequence of messages */ 5105 static void test_messages(void) 5106 { 5107 DWORD tid; 5108 HANDLE hthread; 5109 HWND hwnd, hparent, hchild; 5110 HWND hchild2, hbutton; 5111 HMENU hmenu; 5112 MSG msg; 5113 LRESULT res; 5114 POINT pos; 5115 BOOL ret; 5116 5117 flush_sequence(); 5118 5119 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW, 5120 100, 100, 200, 200, 0, 0, 0, NULL); 5121 ok (hwnd != 0, "Failed to create overlapped window\n"); 5122 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped", FALSE); 5123 5124 /* test ShowWindow(SW_HIDE) on a newly created invisible window */ 5125 ok( ShowWindow(hwnd, SW_HIDE) == FALSE, "ShowWindow: window was visible\n" ); 5126 ok_sequence(WmEmptySeq, "ShowWindow(SW_HIDE):overlapped, invisible", FALSE); 5127 5128 /* test WM_SETREDRAW on a not visible top level window */ 5129 test_WM_SETREDRAW(hwnd); 5130 5131 SetWindowPos(hwnd, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE); 5132 flush_events(); 5133 ok_sequence(WmSWP_ShowOverlappedSeq, "SetWindowPos:SWP_SHOWWINDOW:overlapped", FALSE); 5134 ok(IsWindowVisible(hwnd), "window should be visible at this point\n"); 5135 5136 ok(GetActiveWindow() == hwnd, "window should be active\n"); 5137 ok(GetFocus() == hwnd, "window should have input focus\n"); 5138 ShowWindow(hwnd, SW_HIDE); 5139 flush_events(); 5140 ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped", FALSE); 5141 5142 /* test ShowWindow(SW_HIDE) on a hidden window - single threaded */ 5143 ok(ShowWindow(hwnd, SW_HIDE) == FALSE, "ShowWindow(SW_HIDE) expected FALSE\n"); 5144 flush_events(); 5145 ok_sequence(WmEmptySeq, "ShowWindow(SW_HIDE):overlapped", FALSE); 5146 5147 /* test ShowWindow(SW_HIDE) on a hidden window - multi-threaded */ 5148 hthread = CreateThread(NULL, 0, show_window_thread, hwnd, 0, &tid); 5149 ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError()); 5150 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 5151 CloseHandle(hthread); 5152 flush_events(); 5153 ok_sequence(WmEmptySeq, "ShowWindow(SW_HIDE):overlapped", FALSE); 5154 5155 ShowWindow(hwnd, SW_SHOW); 5156 flush_events(); 5157 ok_sequence(WmShowOverlappedSeq, "ShowWindow(SW_SHOW):overlapped", TRUE); 5158 5159 ShowWindow(hwnd, SW_HIDE); 5160 flush_events(); 5161 ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped", FALSE); 5162 5163 ShowWindow(hwnd, SW_SHOWMAXIMIZED); 5164 flush_events(); 5165 ok_sequence(WmShowMaxOverlappedSeq, "ShowWindow(SW_SHOWMAXIMIZED):overlapped", TRUE); 5166 flush_sequence(); 5167 5168 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_MAXIMIZE) 5169 { 5170 ShowWindow(hwnd, SW_RESTORE); 5171 flush_events(); 5172 ok_sequence(WmShowRestoreMaxOverlappedSeq, "ShowWindow(SW_RESTORE):overlapped", TRUE); 5173 flush_sequence(); 5174 } 5175 5176 ShowWindow(hwnd, SW_MINIMIZE); 5177 flush_events(); 5178 ok_sequence(WmShowMinOverlappedSeq, "ShowWindow(SW_SHOWMINIMIZED):overlapped", FALSE); 5179 flush_sequence(); 5180 5181 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_MINIMIZE) 5182 { 5183 ShowWindow(hwnd, SW_RESTORE); 5184 flush_events(); 5185 ok_sequence(WmShowRestoreMinOverlappedSeq, "ShowWindow(SW_RESTORE):overlapped", TRUE); 5186 flush_sequence(); 5187 } 5188 5189 ShowWindow(hwnd, SW_SHOW); 5190 flush_events(); 5191 ok_sequence(WmOptionalPaint, "ShowWindow(SW_SHOW):overlapped already visible", FALSE); 5192 5193 SetWindowPos(hwnd, 0,0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE); 5194 ok_sequence(WmSWP_HideOverlappedSeq, "SetWindowPos:SWP_HIDEWINDOW:overlapped", FALSE); 5195 ok(!IsWindowVisible(hwnd), "window should not be visible at this point\n"); 5196 ok(GetActiveWindow() == hwnd, "window should still be active\n"); 5197 5198 /* test WM_SETREDRAW on a visible top level window */ 5199 ShowWindow(hwnd, SW_SHOW); 5200 flush_events(); 5201 test_WM_SETREDRAW(hwnd); 5202 5203 trace("testing scroll APIs on a visible top level window %p\n", hwnd); 5204 test_scroll_messages(hwnd); 5205 5206 /* test resizing and moving */ 5207 SetWindowPos( hwnd, 0, 0, 0, 300, 300, SWP_NOMOVE|SWP_NOACTIVATE ); 5208 ok_sequence(WmSWP_ResizeSeq, "SetWindowPos:Resize", FALSE ); 5209 flush_events(); 5210 flush_sequence(); 5211 SetWindowPos( hwnd, 0, 200, 200, 0, 0, SWP_NOSIZE|SWP_NOACTIVATE ); 5212 ok_sequence(WmSWP_MoveSeq, "SetWindowPos:Move", FALSE ); 5213 flush_events(); 5214 flush_sequence(); 5215 SetWindowPos( hwnd, 0, 200, 200, 250, 250, SWP_NOZORDER|SWP_NOACTIVATE ); 5216 ok_sequence(WmSWP_ResizeNoZOrder, "SetWindowPos:WmSWP_ResizeNoZOrder", FALSE ); 5217 flush_events(); 5218 flush_sequence(); 5219 5220 /* popups don't get WM_GETMINMAXINFO */ 5221 SetWindowLongW( hwnd, GWL_STYLE, WS_VISIBLE|WS_POPUP ); 5222 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_FRAMECHANGED); 5223 flush_sequence(); 5224 SetWindowPos( hwnd, 0, 0, 0, 200, 200, SWP_NOMOVE|SWP_NOACTIVATE ); 5225 ok_sequence(WmSWP_ResizePopupSeq, "SetWindowPos:ResizePopup", FALSE ); 5226 5227 DestroyWindow(hwnd); 5228 ok_sequence(WmDestroyOverlappedSeq, "DestroyWindow:overlapped", FALSE); 5229 5230 /* Test if windows are correctly drawn when first shown */ 5231 5232 /* Visible, redraw */ 5233 flush_events(); 5234 flush_sequence(); 5235 hwnd = CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP | WS_VISIBLE, 5236 10, 10, 100, 100, NULL, 0, 0, NULL ); 5237 ok (hwnd != 0, "Failed to create popup window\n"); 5238 RedrawWindow(hwnd, NULL, NULL, RDW_UPDATENOW); 5239 ok_sequence(WmShowPopupFirstDrawSeq_1, "RedrawWindow:show_popup_first_draw_visible", FALSE); 5240 DestroyWindow(hwnd); 5241 5242 /* Invisible, show, message */ 5243 flush_events(); 5244 flush_sequence(); 5245 hwnd = CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP, 5246 10, 10, 100, 100, NULL, 0, 0, NULL ); 5247 ok (hwnd != 0, "Failed to create popup window\n"); 5248 ShowWindow(hwnd, SW_SHOW); 5249 SendMessageW(hwnd, WM_PAINT, 0, 0); 5250 ok_sequence(WmShowPopupFirstDrawSeq_1, "RedrawWindow:show_popup_first_draw_show", FALSE); 5251 DestroyWindow(hwnd); 5252 5253 /* Invisible, show maximized, redraw */ 5254 flush_events(); 5255 flush_sequence(); 5256 hwnd = CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP, 5257 10, 10, 100, 100, NULL, 0, 0, NULL ); 5258 ok (hwnd != 0, "Failed to create popup window\n"); 5259 ShowWindow(hwnd, SW_SHOWMAXIMIZED); 5260 RedrawWindow(hwnd, NULL, NULL, RDW_UPDATENOW); 5261 ok_sequence(WmShowPopupFirstDrawSeq_2, "RedrawWindow:show_popup_first_draw_show_maximized", FALSE); 5262 DestroyWindow(hwnd); 5263 5264 /* Test SetWindowPos */ 5265 test_msg_setpos(WmFirstDrawSetWindowPosSeq1, SWP_SHOWWINDOW, FALSE); 5266 test_msg_setpos(WmFirstDrawSetWindowPosSeq2, 0, FALSE); 5267 test_msg_setpos(WmFirstDrawSetWindowPosSeq3, 5268 SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE | SWP_NOZORDER, FALSE); 5269 5270 test_msg_setpos(WmFirstDrawSetWindowPosSeq1, SWP_SHOWWINDOW | SWP_NOSIZE, FALSE); 5271 test_msg_setpos(WmFirstDrawSetWindowPosSeq4, SWP_SHOWWINDOW | SWP_NOMOVE, FALSE); 5272 test_msg_setpos(WmFirstDrawSetWindowPosSeq3, SWP_SHOWWINDOW | SWP_NOCLIENTSIZE, FALSE); 5273 test_msg_setpos(WmFirstDrawSetWindowPosSeq3, SWP_SHOWWINDOW | SWP_NOCLIENTMOVE, FALSE); 5274 test_msg_setpos(WmFirstDrawSetWindowPosSeq1, SWP_SHOWWINDOW | SWP_NOZORDER, FALSE); 5275 5276 test_msg_setpos(WmFirstDrawSetWindowPosSeq2, SWP_SHOWWINDOW | SWP_DEFERERASE, FALSE); 5277 test_msg_setpos(WmFirstDrawSetWindowPosSeq3, SWP_SHOWWINDOW | SWP_DEFERERASE | SWP_NOCLIENTMOVE, FALSE); 5278 test_msg_setpos(WmFirstDrawSetWindowPosSeq3, SWP_SHOWWINDOW | SWP_DEFERERASE | SWP_NOCLIENTSIZE, FALSE); 5279 test_msg_setpos(WmFirstDrawSetWindowPosSeq5, SWP_SHOWWINDOW | SWP_DEFERERASE | SWP_NOMOVE, FALSE); 5280 test_msg_setpos(WmFirstDrawSetWindowPosSeq2, SWP_SHOWWINDOW | SWP_DEFERERASE | SWP_NOSIZE, FALSE); 5281 test_msg_setpos(WmFirstDrawSetWindowPosSeq2, SWP_SHOWWINDOW | SWP_DEFERERASE | SWP_NOZORDER, FALSE); 5282 5283 test_msg_setpos(WmFirstDrawSetWindowPosSeq1, SWP_SHOWWINDOW | SWP_NOCOPYBITS, FALSE); 5284 test_msg_setpos(WmFirstDrawSetWindowPosSeq3, SWP_SHOWWINDOW | SWP_NOCOPYBITS | SWP_NOCLIENTMOVE, FALSE); 5285 test_msg_setpos(WmFirstDrawSetWindowPosSeq3, SWP_SHOWWINDOW | SWP_NOCOPYBITS | SWP_NOCLIENTSIZE, FALSE); 5286 test_msg_setpos(WmFirstDrawSetWindowPosSeq4, SWP_SHOWWINDOW | SWP_NOCOPYBITS | SWP_NOMOVE, FALSE); 5287 test_msg_setpos(WmFirstDrawSetWindowPosSeq1, SWP_SHOWWINDOW | SWP_NOCOPYBITS | SWP_NOSIZE, FALSE); 5288 test_msg_setpos(WmFirstDrawSetWindowPosSeq1, SWP_SHOWWINDOW | SWP_NOCOPYBITS | SWP_NOZORDER, FALSE); 5289 5290 test_msg_setpos(WmFirstDrawSetWindowPosSeq2, SWP_SHOWWINDOW | SWP_NOREDRAW, FALSE); 5291 test_msg_setpos(WmFirstDrawSetWindowPosSeq3, SWP_SHOWWINDOW | SWP_NOREDRAW | SWP_NOCLIENTMOVE, FALSE); 5292 test_msg_setpos(WmFirstDrawSetWindowPosSeq3, SWP_SHOWWINDOW | SWP_NOREDRAW | SWP_NOCLIENTSIZE, FALSE); 5293 test_msg_setpos(WmFirstDrawSetWindowPosSeq5, SWP_SHOWWINDOW | SWP_NOREDRAW | SWP_NOMOVE, FALSE); 5294 test_msg_setpos(WmFirstDrawSetWindowPosSeq2, SWP_SHOWWINDOW | SWP_NOREDRAW | SWP_NOSIZE, FALSE); 5295 test_msg_setpos(WmFirstDrawSetWindowPosSeq2, SWP_SHOWWINDOW | SWP_NOREDRAW | SWP_NOZORDER, FALSE); 5296 5297 /* Test SetWindowPos with child windows */ 5298 flush_events(); 5299 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 5300 100, 100, 200, 200, 0, 0, 0, NULL); 5301 ok (hparent != 0, "Failed to create parent window\n"); 5302 5303 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE, 5304 0, 0, 10, 10, hparent, 0, 0, NULL); 5305 ok (hchild != 0, "Failed to create child window\n"); 5306 flush_sequence(); 5307 SetWindowPos(hparent, NULL, 0, 0, 100, 100, SWP_SHOWWINDOW); 5308 ok_sequence(WmFirstDrawChildSeq1, /* Expect no messages for the child */ 5309 "SetWindowPos:show_popup_first_show_window_child1", FALSE); 5310 DestroyWindow(hchild); 5311 DestroyWindow(hparent); 5312 5313 flush_events(); 5314 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN, 5315 100, 100, 200, 200, 0, 0, 0, NULL); 5316 ok (hparent != 0, "Failed to create parent window\n"); 5317 5318 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE, 5319 0, 0, 10, 10, hparent, 0, 0, NULL); 5320 ok (hchild != 0, "Failed to create child window\n"); 5321 flush_sequence(); 5322 SetWindowPos(hparent, NULL, 0, 0, 100, 100, SWP_SHOWWINDOW); 5323 ok_sequence(WmFirstDrawChildSeq2, /* Expect child to be redrawn */ 5324 "SetWindowPos:show_popup_first_show_window_child2", FALSE); 5325 DestroyWindow(hchild); 5326 DestroyWindow(hparent); 5327 5328 /* Test message sequence for extreme position and size */ 5329 5330 flush_sequence(); 5331 hwnd = CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP | WS_VISIBLE, 5332 -10, -10, 10000, 10000, NULL, 0, 0, NULL ); 5333 ok (hwnd != 0, "Failed to create popup window\n"); 5334 ok_sequence(WmShowPopupExtremeLocationSeq, "RedrawWindow:show_popup_extreme_location", FALSE); 5335 DestroyWindow(hwnd); 5336 5337 5338 /* Test child windows */ 5339 5340 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 5341 100, 100, 200, 200, 0, 0, 0, NULL); 5342 ok (hparent != 0, "Failed to create parent window\n"); 5343 flush_sequence(); 5344 5345 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_MAXIMIZE, 5346 0, 0, 10, 10, hparent, 0, 0, NULL); 5347 ok (hchild != 0, "Failed to create child window\n"); 5348 ok_sequence(WmCreateMaximizedChildSeq, "CreateWindow:maximized child", FALSE); 5349 DestroyWindow(hchild); 5350 flush_sequence(); 5351 5352 /* visible child window with a caption */ 5353 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", 5354 WS_CHILD | WS_VISIBLE | WS_CAPTION, 5355 0, 0, 10, 10, hparent, 0, 0, NULL); 5356 ok (hchild != 0, "Failed to create child window\n"); 5357 ok_sequence(WmCreateVisibleChildSeq, "CreateWindow:visible child", FALSE); 5358 5359 trace("testing scroll APIs on a visible child window %p\n", hchild); 5360 test_scroll_messages(hchild); 5361 5362 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE); 5363 ok_sequence(WmShowChildSeq_4, "SetWindowPos(SWP_SHOWWINDOW):child with a caption", FALSE); 5364 5365 DestroyWindow(hchild); 5366 flush_sequence(); 5367 5368 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 5369 0, 0, 10, 10, hparent, 0, 0, NULL); 5370 ok (hchild != 0, "Failed to create child window\n"); 5371 ok_sequence(WmCreateChildSeq, "CreateWindow:child", FALSE); 5372 5373 hchild2 = CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_CHILD, 5374 100, 100, 50, 50, hparent, 0, 0, NULL); 5375 ok (hchild2 != 0, "Failed to create child2 window\n"); 5376 flush_sequence(); 5377 5378 hbutton = CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILD, 5379 0, 100, 50, 50, hchild, 0, 0, NULL); 5380 ok (hbutton != 0, "Failed to create button window\n"); 5381 5382 /* test WM_SETREDRAW on a not visible child window */ 5383 test_WM_SETREDRAW(hchild); 5384 5385 ShowWindow(hchild, SW_SHOW); 5386 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):child", FALSE); 5387 5388 /* check parent messages too */ 5389 log_all_parent_messages++; 5390 ShowWindow(hchild, SW_HIDE); 5391 ok_sequence(WmHideChildSeq2, "ShowWindow(SW_HIDE):child", FALSE); 5392 log_all_parent_messages--; 5393 5394 ShowWindow(hchild, SW_SHOW); 5395 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):child", FALSE); 5396 5397 ShowWindow(hchild, SW_HIDE); 5398 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):child", FALSE); 5399 5400 ShowWindow(hchild, SW_SHOW); 5401 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):child", FALSE); 5402 5403 /* test WM_SETREDRAW on a visible child window */ 5404 test_WM_SETREDRAW(hchild); 5405 5406 log_all_parent_messages++; 5407 MoveWindow(hchild, 10, 10, 20, 20, TRUE); 5408 ok_sequence(WmResizingChildWithMoveWindowSeq, "MoveWindow:child", FALSE); 5409 log_all_parent_messages--; 5410 5411 ShowWindow(hchild, SW_HIDE); 5412 flush_sequence(); 5413 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE); 5414 ok_sequence(WmShowChildSeq_2, "SetWindowPos:show_child_2", FALSE); 5415 5416 ShowWindow(hchild, SW_HIDE); 5417 flush_sequence(); 5418 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE); 5419 ok_sequence(WmShowChildSeq_3, "SetWindowPos:show_child_3", FALSE); 5420 5421 /* DestroyWindow sequence below expects that a child has focus */ 5422 SetFocus(hchild); 5423 flush_sequence(); 5424 5425 DestroyWindow(hchild); 5426 ok_sequence(WmDestroyChildSeq, "DestroyWindow:child", FALSE); 5427 DestroyWindow(hchild2); 5428 DestroyWindow(hbutton); 5429 5430 flush_sequence(); 5431 hchild = CreateWindowExA(0, "TestWindowClass", "Test Child Popup", WS_CHILD | WS_POPUP, 5432 0, 0, 100, 100, hparent, 0, 0, NULL); 5433 ok (hchild != 0, "Failed to create child popup window\n"); 5434 ok_sequence(WmCreateChildPopupSeq, "CreateWindow:child_popup", FALSE); 5435 DestroyWindow(hchild); 5436 5437 /* test what happens to a window which sets WS_VISIBLE in WM_CREATE */ 5438 flush_sequence(); 5439 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP, 5440 0, 0, 100, 100, hparent, 0, 0, NULL); 5441 ok (hchild != 0, "Failed to create popup window\n"); 5442 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup", FALSE); 5443 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 5444 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n"); 5445 flush_sequence(); 5446 ShowWindow(hchild, SW_SHOW); 5447 ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup", FALSE); 5448 flush_sequence(); 5449 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER); 5450 ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2", FALSE); 5451 flush_sequence(); 5452 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE); 5453 ok_sequence(WmShowVisiblePopupSeq_3, "SetWindowPos:show_visible_popup_3", FALSE); 5454 DestroyWindow(hchild); 5455 5456 /* this time add WS_VISIBLE for CreateWindowEx, but this fact actually 5457 * changes nothing in message sequences. 5458 */ 5459 flush_sequence(); 5460 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP | WS_VISIBLE, 5461 0, 0, 100, 100, hparent, 0, 0, NULL); 5462 ok (hchild != 0, "Failed to create popup window\n"); 5463 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup", FALSE); 5464 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 5465 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n"); 5466 flush_sequence(); 5467 ShowWindow(hchild, SW_SHOW); 5468 ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup", FALSE); 5469 flush_sequence(); 5470 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER); 5471 ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2", FALSE); 5472 DestroyWindow(hchild); 5473 5474 flush_sequence(); 5475 hwnd = CreateWindowExA(WS_EX_DLGMODALFRAME, "TestDialogClass", NULL, WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_DLGFRAME, 5476 0, 0, 100, 100, hparent, 0, 0, NULL); 5477 ok(hwnd != 0, "Failed to create custom dialog window\n"); 5478 ok_sequence(WmCreateCustomDialogSeq, "CreateCustomDialog", TRUE); 5479 5480 if(0) { 5481 trace("testing scroll APIs on a visible dialog %p\n", hwnd); 5482 test_scroll_messages(hwnd); 5483 } 5484 5485 flush_sequence(); 5486 5487 test_def_id = TRUE; 5488 SendMessageA(hwnd, WM_NULL, 0, 0); 5489 5490 flush_sequence(); 5491 after_end_dialog = TRUE; 5492 EndDialog( hwnd, 0 ); 5493 ok_sequence(WmEndCustomDialogSeq, "EndCustomDialog", FALSE); 5494 5495 DestroyWindow(hwnd); 5496 after_end_dialog = FALSE; 5497 test_def_id = FALSE; 5498 5499 ok(GetCursorPos(&pos), "GetCursorPos failed\n"); 5500 ok(SetCursorPos(109, 109), "SetCursorPos failed\n"); 5501 5502 hwnd = CreateWindowExA(0, "TestDialogClass", NULL, WS_POPUP|WS_CHILD, 5503 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL); 5504 ok(hwnd != 0, "Failed to create custom dialog window\n"); 5505 flush_sequence(); 5506 trace("call ShowWindow(%p, SW_SHOW)\n", hwnd); 5507 ShowWindow(hwnd, SW_SHOW); 5508 ok_sequence(WmShowCustomDialogSeq, "ShowCustomDialog", TRUE); 5509 5510 flush_events(); 5511 flush_sequence(); 5512 ret = DrawMenuBar(hwnd); 5513 ok(ret, "DrawMenuBar failed: %d\n", GetLastError()); 5514 flush_events(); 5515 ok_sequence(WmDrawMenuBarSeq, "DrawMenuBar", FALSE); 5516 ok(SetCursorPos(pos.x, pos.y), "SetCursorPos failed\n"); 5517 5518 DestroyWindow(hwnd); 5519 5520 hwnd = CreateWindowExA(0, "TestDialogClass", NULL, WS_CHILD|WS_VISIBLE, 5521 0, 0, 100, 100, hparent, 0, GetModuleHandleA(0), NULL); 5522 ok(hwnd != 0, "Failed to create custom dialog window\n"); 5523 flush_events(); 5524 flush_sequence(); 5525 ret = DrawMenuBar(hwnd); 5526 ok(ret, "DrawMenuBar failed: %d\n", GetLastError()); 5527 flush_events(); 5528 ok_sequence(WmEmptySeq, "DrawMenuBar for a child window", FALSE); 5529 5530 DestroyWindow(hwnd); 5531 5532 flush_sequence(); 5533 DialogBoxA( 0, "TEST_DIALOG", hparent, TestModalDlgProcA ); 5534 ok_sequence(WmModalDialogSeq, "ModalDialog", TRUE); 5535 5536 DestroyWindow(hparent); 5537 flush_sequence(); 5538 5539 /* Message sequence for SetMenu */ 5540 ok(!DrawMenuBar(hwnd), "DrawMenuBar should return FALSE for a destroyed window\n"); 5541 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "last error is %d\n", GetLastError()); 5542 ok_sequence(WmEmptySeq, "DrawMenuBar for a window without a menu", FALSE); 5543 5544 hmenu = CreateMenu(); 5545 ok (hmenu != 0, "Failed to create menu\n"); 5546 ok (InsertMenuA(hmenu, -1, MF_BYPOSITION, 0x1000, "foo"), "InsertMenu failed\n"); 5547 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW, 5548 100, 100, 200, 200, 0, hmenu, 0, NULL); 5549 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped", FALSE); 5550 ok (SetMenu(hwnd, 0), "SetMenu\n"); 5551 ok_sequence(WmSetMenuNonVisibleSizeChangeSeq, "SetMenu:NonVisibleSizeChange", FALSE); 5552 ok (SetMenu(hwnd, 0), "SetMenu\n"); 5553 ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq, "SetMenu:NonVisibleNoSizeChange", FALSE); 5554 ShowWindow(hwnd, SW_SHOW); 5555 UpdateWindow( hwnd ); 5556 flush_events(); 5557 flush_sequence(); 5558 ok (SetMenu(hwnd, 0), "SetMenu\n"); 5559 ok_sequence(WmSetMenuVisibleNoSizeChangeSeq, "SetMenu:VisibleNoSizeChange", FALSE); 5560 ok (SetMenu(hwnd, hmenu), "SetMenu\n"); 5561 ok_sequence(WmSetMenuVisibleSizeChangeSeq, "SetMenu:VisibleSizeChange", FALSE); 5562 5563 UpdateWindow( hwnd ); 5564 flush_events(); 5565 flush_sequence(); 5566 ok(DrawMenuBar(hwnd), "DrawMenuBar\n"); 5567 flush_events(); 5568 ok_sequence(WmDrawMenuBarSeq, "DrawMenuBar", FALSE); 5569 5570 DestroyWindow(hwnd); 5571 flush_sequence(); 5572 5573 /* Message sequence for EnableWindow */ 5574 hparent = CreateWindowExA(0, "TestWindowClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 5575 100, 100, 200, 200, 0, 0, 0, NULL); 5576 ok (hparent != 0, "Failed to create parent window\n"); 5577 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE, 5578 0, 0, 10, 10, hparent, 0, 0, NULL); 5579 ok (hchild != 0, "Failed to create child window\n"); 5580 5581 SetFocus(hchild); 5582 flush_events(); 5583 flush_sequence(); 5584 5585 EnableWindow(hparent, FALSE); 5586 ok_sequence(WmEnableWindowSeq_1, "EnableWindow(FALSE)", FALSE); 5587 5588 EnableWindow(hparent, FALSE); 5589 ok_sequence(WmEnableWindowSeq_2, "EnableWindow(FALSE)", FALSE); 5590 5591 EnableWindow(hparent, TRUE); 5592 ok_sequence(WmEnableWindowSeq_3, "EnableWindow(TRUE)", FALSE); 5593 5594 EnableWindow(hparent, TRUE); 5595 ok_sequence(WmEnableWindowSeq_4, "EnableWindow(TRUE)", FALSE); 5596 5597 flush_events(); 5598 flush_sequence(); 5599 5600 test_MsgWaitForMultipleObjects(hparent); 5601 test_WM_DEVICECHANGE(hparent); 5602 5603 /* the following test causes an exception in user.exe under win9x */ 5604 if (!PostMessageW( hparent, WM_USER, 0, 0 )) 5605 { 5606 DestroyWindow(hparent); 5607 flush_sequence(); 5608 return; 5609 } 5610 PostMessageW( hparent, WM_USER+1, 0, 0 ); 5611 /* PeekMessage(NULL) fails, but still removes the message */ 5612 SetLastError(0xdeadbeef); 5613 ok( !PeekMessageW( NULL, 0, 0, 0, PM_REMOVE ), "PeekMessage(NULL) should fail\n" ); 5614 ok( GetLastError() == ERROR_NOACCESS || /* Win2k */ 5615 GetLastError() == 0xdeadbeef, /* NT4 */ 5616 "last error is %d\n", GetLastError() ); 5617 ok( PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n" ); 5618 ok( msg.message == WM_USER+1, "got %x instead of WM_USER+1\n", msg.message ); 5619 5620 DestroyWindow(hchild); 5621 DestroyWindow(hparent); 5622 flush_sequence(); 5623 5624 /* Message sequences for WM_SETICON */ 5625 trace("testing WM_SETICON\n"); 5626 hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, 5627 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0, 5628 NULL, NULL, 0); 5629 ShowWindow(hwnd, SW_SHOW); 5630 UpdateWindow(hwnd); 5631 flush_events(); 5632 flush_sequence(); 5633 SendMessageA(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)LoadIconA(0, (LPCSTR)IDI_APPLICATION)); 5634 ok_sequence(WmSetIcon_1, "WM_SETICON for shown window with caption", FALSE); 5635 5636 ShowWindow(hwnd, SW_HIDE); 5637 flush_events(); 5638 flush_sequence(); 5639 SendMessageA(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)LoadIconA(0, (LPCSTR)IDI_APPLICATION)); 5640 ok_sequence(WmSetIcon_2, "WM_SETICON for hidden window with caption", FALSE); 5641 DestroyWindow(hwnd); 5642 flush_sequence(); 5643 5644 hwnd = CreateWindowExA(0, "TestPopupClass", NULL, WS_POPUP, 5645 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0, 5646 NULL, NULL, 0); 5647 ShowWindow(hwnd, SW_SHOW); 5648 UpdateWindow(hwnd); 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 shown window without caption", FALSE); 5653 5654 ShowWindow(hwnd, SW_HIDE); 5655 flush_events(); 5656 flush_sequence(); 5657 SendMessageA(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)LoadIconA(0, (LPCSTR)IDI_APPLICATION)); 5658 ok_sequence(WmSetIcon_2, "WM_SETICON for hidden window without caption", FALSE); 5659 5660 flush_sequence(); 5661 res = SendMessageA(hwnd, 0x3B, 0x8000000b, 0); 5662 if (!res) 5663 { 5664 todo_wine win_skip( "Message 0x3b not supported\n" ); 5665 goto done; 5666 } 5667 ok_sequence(WmInitEndSession, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x8000000b", TRUE); 5668 ok(res == 1, "SendMessage(hwnd, 0x3B, 0x8000000b, 0) should have returned 1 instead of %ld\n", res); 5669 res = SendMessageA(hwnd, 0x3B, 0x0000000b, 0); 5670 ok_sequence(WmInitEndSession_2, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x0000000b", TRUE); 5671 ok(res == 1, "SendMessage(hwnd, 0x3B, 0x0000000b, 0) should have returned 1 instead of %ld\n", res); 5672 res = SendMessageA(hwnd, 0x3B, 0x0000000f, 0); 5673 ok_sequence(WmInitEndSession_2, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x0000000f", TRUE); 5674 ok(res == 1, "SendMessage(hwnd, 0x3B, 0x0000000f, 0) should have returned 1 instead of %ld\n", res); 5675 5676 flush_sequence(); 5677 res = SendMessageA(hwnd, 0x3B, 0x80000008, 0); 5678 ok_sequence(WmInitEndSession_3, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000008", TRUE); 5679 ok(res == 2, "SendMessage(hwnd, 0x3B, 0x80000008, 0) should have returned 2 instead of %ld\n", res); 5680 res = SendMessageA(hwnd, 0x3B, 0x00000008, 0); 5681 ok_sequence(WmInitEndSession_4, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x00000008", TRUE); 5682 ok(res == 2, "SendMessage(hwnd, 0x3B, 0x00000008, 0) should have returned 2 instead of %ld\n", res); 5683 5684 res = SendMessageA(hwnd, 0x3B, 0x80000004, 0); 5685 ok_sequence(WmInitEndSession_3, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000004", TRUE); 5686 ok(res == 2, "SendMessage(hwnd, 0x3B, 0x80000004, 0) should have returned 2 instead of %ld\n", res); 5687 5688 res = SendMessageA(hwnd, 0x3B, 0x80000001, 0); 5689 ok_sequence(WmInitEndSession_5, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000001", TRUE); 5690 ok(res == 2, "SendMessage(hwnd, 0x3B, 0x80000001, 0) should have returned 2 instead of %ld\n", res); 5691 5692 done: 5693 DestroyWindow(hwnd); 5694 flush_sequence(); 5695 } 5696 5697 static void test_setwindowpos(void) 5698 { 5699 HWND hwnd; 5700 RECT rc; 5701 LRESULT res; 5702 const INT winX = 100; 5703 const INT winY = 100; 5704 const INT sysX = GetSystemMetrics(SM_CXMINTRACK); 5705 5706 hwnd = CreateWindowExA(0, "TestWindowClass", NULL, 0, 5707 0, 0, winX, winY, 0, 5708 NULL, NULL, 0); 5709 5710 GetWindowRect(hwnd, &rc); 5711 expect(sysX, rc.right); 5712 expect(winY, rc.bottom); 5713 5714 flush_events(); 5715 flush_sequence(); 5716 res = SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, winX, winY, 0); 5717 ok_sequence(WmZOrder, "Z-Order", TRUE); 5718 ok(res == TRUE, "SetWindowPos expected TRUE, got %ld\n", res); 5719 5720 GetWindowRect(hwnd, &rc); 5721 expect(sysX, rc.right); 5722 expect(winY, rc.bottom); 5723 DestroyWindow(hwnd); 5724 } 5725 5726 static void invisible_parent_tests(void) 5727 { 5728 HWND hparent, hchild; 5729 5730 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW, 5731 100, 100, 200, 200, 0, 0, 0, NULL); 5732 ok (hparent != 0, "Failed to create parent window\n"); 5733 flush_sequence(); 5734 5735 /* test showing child with hidden parent */ 5736 5737 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 5738 0, 0, 10, 10, hparent, 0, 0, NULL); 5739 ok (hchild != 0, "Failed to create child window\n"); 5740 ok_sequence(WmCreateChildSeq, "CreateWindow:child", FALSE); 5741 5742 ShowWindow( hchild, SW_MINIMIZE ); 5743 ok_sequence(WmShowChildInvisibleParentSeq_1, "ShowWindow(SW_MINIMIZE) child with invisible parent", FALSE); 5744 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 5745 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n"); 5746 5747 /* repeat */ 5748 flush_events(); 5749 flush_sequence(); 5750 ShowWindow( hchild, SW_MINIMIZE ); 5751 ok_sequence(WmShowChildInvisibleParentSeq_1r, "ShowWindow(SW_MINIMIZE) child with invisible parent", FALSE); 5752 5753 DestroyWindow(hchild); 5754 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 5755 0, 0, 10, 10, hparent, 0, 0, NULL); 5756 flush_sequence(); 5757 5758 ShowWindow( hchild, SW_MAXIMIZE ); 5759 ok_sequence(WmShowChildInvisibleParentSeq_2, "ShowWindow(SW_MAXIMIZE) child with invisible parent", FALSE); 5760 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 5761 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n"); 5762 5763 /* repeat */ 5764 flush_events(); 5765 flush_sequence(); 5766 ShowWindow( hchild, SW_MAXIMIZE ); 5767 ok_sequence(WmShowChildInvisibleParentSeq_2r, "ShowWindow(SW_MAXIMIZE) child with invisible parent", FALSE); 5768 5769 DestroyWindow(hchild); 5770 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 5771 0, 0, 10, 10, hparent, 0, 0, NULL); 5772 flush_sequence(); 5773 5774 ShowWindow( hchild, SW_RESTORE ); 5775 ok_sequence(WmShowChildInvisibleParentSeq_5, "ShowWindow(SW_RESTORE) child with invisible parent", FALSE); 5776 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 5777 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n"); 5778 5779 DestroyWindow(hchild); 5780 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 5781 0, 0, 10, 10, hparent, 0, 0, NULL); 5782 flush_sequence(); 5783 5784 ShowWindow( hchild, SW_SHOWMINIMIZED ); 5785 ok_sequence(WmShowChildInvisibleParentSeq_3, "ShowWindow(SW_SHOWMINIMIZED) child with invisible parent", FALSE); 5786 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 5787 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n"); 5788 5789 /* repeat */ 5790 flush_events(); 5791 flush_sequence(); 5792 ShowWindow( hchild, SW_SHOWMINIMIZED ); 5793 ok_sequence(WmShowChildInvisibleParentSeq_3r, "ShowWindow(SW_SHOWMINIMIZED) child with invisible parent", FALSE); 5794 5795 DestroyWindow(hchild); 5796 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 5797 0, 0, 10, 10, hparent, 0, 0, NULL); 5798 flush_sequence(); 5799 5800 /* same as ShowWindow( hchild, SW_MAXIMIZE ); */ 5801 ShowWindow( hchild, SW_SHOWMAXIMIZED ); 5802 ok_sequence(WmShowChildInvisibleParentSeq_2, "ShowWindow(SW_SHOWMAXIMIZED) child with invisible parent", FALSE); 5803 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 5804 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n"); 5805 5806 DestroyWindow(hchild); 5807 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 5808 0, 0, 10, 10, hparent, 0, 0, NULL); 5809 flush_sequence(); 5810 5811 ShowWindow( hchild, SW_SHOWMINNOACTIVE ); 5812 ok_sequence(WmShowChildInvisibleParentSeq_4, "ShowWindow(SW_SHOWMINNOACTIVE) child with invisible parent", FALSE); 5813 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 5814 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n"); 5815 5816 /* repeat */ 5817 flush_events(); 5818 flush_sequence(); 5819 ShowWindow( hchild, SW_SHOWMINNOACTIVE ); 5820 ok_sequence(WmShowChildInvisibleParentSeq_4r, "ShowWindow(SW_SHOWMINNOACTIVE) child with invisible parent", FALSE); 5821 5822 DestroyWindow(hchild); 5823 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 5824 0, 0, 10, 10, hparent, 0, 0, NULL); 5825 flush_sequence(); 5826 5827 /* FIXME: looks like XP SP2 doesn't know about SW_FORCEMINIMIZE at all */ 5828 ShowWindow( hchild, SW_FORCEMINIMIZE ); 5829 ok_sequence(WmEmptySeq, "ShowWindow(SW_FORCEMINIMIZE) child with invisible parent", TRUE); 5830 todo_wine { 5831 ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should be not set\n"); 5832 } 5833 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n"); 5834 5835 DestroyWindow(hchild); 5836 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 5837 0, 0, 10, 10, hparent, 0, 0, NULL); 5838 flush_sequence(); 5839 5840 ShowWindow( hchild, SW_SHOWNA ); 5841 ok_sequence(WmShowChildInvisibleParentSeq_5, "ShowWindow(SW_SHOWNA) child with invisible parent", FALSE); 5842 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 5843 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n"); 5844 5845 /* repeat */ 5846 flush_events(); 5847 flush_sequence(); 5848 ShowWindow( hchild, SW_SHOWNA ); 5849 ok_sequence(WmShowChildInvisibleParentSeq_5, "ShowWindow(SW_SHOWNA) child with invisible parent", FALSE); 5850 5851 DestroyWindow(hchild); 5852 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 5853 0, 0, 10, 10, hparent, 0, 0, NULL); 5854 flush_sequence(); 5855 5856 ShowWindow( hchild, SW_SHOW ); 5857 ok_sequence(WmShowChildInvisibleParentSeq_5, "ShowWindow(SW_SHOW) child with invisible parent", FALSE); 5858 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 5859 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n"); 5860 5861 /* repeat */ 5862 flush_events(); 5863 flush_sequence(); 5864 ShowWindow( hchild, SW_SHOW ); 5865 ok_sequence(WmEmptySeq, "ShowWindow(SW_SHOW) child with invisible parent", FALSE); 5866 5867 ShowWindow( hchild, SW_HIDE ); 5868 ok_sequence(WmHideChildInvisibleParentSeq, "ShowWindow:hide child with invisible parent", FALSE); 5869 ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should be not set\n"); 5870 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n"); 5871 5872 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER); 5873 ok_sequence(WmShowChildInvisibleParentSeq_6, "SetWindowPos:show child with invisible parent", FALSE); 5874 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 5875 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n"); 5876 5877 SetWindowPos(hchild, 0,0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER); 5878 ok_sequence(WmHideChildInvisibleParentSeq_2, "SetWindowPos:hide child with invisible parent", FALSE); 5879 ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should not be set\n"); 5880 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n"); 5881 5882 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER); 5883 flush_sequence(); 5884 DestroyWindow(hchild); 5885 ok_sequence(WmDestroyInvisibleChildSeq, "DestroyInvisibleChildSeq", FALSE); 5886 5887 DestroyWindow(hparent); 5888 flush_sequence(); 5889 } 5890 5891 /****************** button message test *************************/ 5892 #define ID_BUTTON 0x000e 5893 5894 static const struct message WmSetFocusButtonSeq[] = 5895 { 5896 { HCBT_SETFOCUS, hook }, 5897 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 5898 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 5899 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 5900 { WM_SETFOCUS, sent|wparam, 0 }, 5901 { WM_CTLCOLORBTN, sent|parent }, 5902 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_SETFOCUS) }, 5903 { WM_APP, sent|wparam|lparam, 0, 0 }, 5904 { 0 } 5905 }; 5906 static const struct message WmKillFocusButtonSeq[] = 5907 { 5908 { HCBT_SETFOCUS, hook }, 5909 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 5910 { WM_KILLFOCUS, sent|wparam, 0 }, 5911 { WM_CTLCOLORBTN, sent|parent }, 5912 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_KILLFOCUS) }, 5913 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 5914 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, 5915 { WM_APP, sent|wparam|lparam, 0, 0 }, 5916 { WM_PAINT, sent }, 5917 { WM_CTLCOLORBTN, sent|parent }, 5918 { 0 } 5919 }; 5920 static const struct message WmSetFocusStaticSeq[] = 5921 { 5922 { HCBT_SETFOCUS, hook }, 5923 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 5924 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 5925 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 5926 { WM_SETFOCUS, sent|wparam, 0 }, 5927 { WM_CTLCOLORSTATIC, sent|parent }, 5928 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_SETFOCUS) }, 5929 { WM_COMMAND, sent|wparam|parent|optional, MAKEWPARAM(ID_BUTTON, BN_CLICKED) }, /* radio button */ 5930 { WM_APP, sent|wparam|lparam, 0, 0 }, 5931 { 0 } 5932 }; 5933 static const struct message WmKillFocusStaticSeq[] = 5934 { 5935 { HCBT_SETFOCUS, hook }, 5936 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 5937 { WM_KILLFOCUS, sent|wparam, 0 }, 5938 { WM_CTLCOLORSTATIC, sent|parent }, 5939 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_KILLFOCUS) }, 5940 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 5941 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, 5942 { WM_APP, sent|wparam|lparam, 0, 0 }, 5943 { WM_PAINT, sent }, 5944 { WM_CTLCOLORSTATIC, sent|parent }, 5945 { 0 } 5946 }; 5947 static const struct message WmSetFocusOwnerdrawSeq[] = 5948 { 5949 { HCBT_SETFOCUS, hook }, 5950 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 5951 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 5952 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 5953 { WM_SETFOCUS, sent|wparam, 0 }, 5954 { WM_CTLCOLORBTN, sent|parent }, 5955 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x001040e4 }, 5956 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_SETFOCUS) }, 5957 { WM_APP, sent|wparam|lparam, 0, 0 }, 5958 { 0 } 5959 }; 5960 static const struct message WmKillFocusOwnerdrawSeq[] = 5961 { 5962 { HCBT_SETFOCUS, hook }, 5963 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 5964 { WM_KILLFOCUS, sent|wparam, 0 }, 5965 { WM_CTLCOLORBTN, sent|parent }, 5966 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x000040e4 }, 5967 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_KILLFOCUS) }, 5968 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 5969 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, 5970 { WM_APP, sent|wparam|lparam, 0, 0 }, 5971 { WM_PAINT, sent }, 5972 { WM_CTLCOLORBTN, sent|parent }, 5973 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x000010e4 }, 5974 { 0 } 5975 }; 5976 static const struct message WmLButtonDownSeq[] = 5977 { 5978 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 }, 5979 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, 5980 { HCBT_SETFOCUS, hook }, 5981 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 5982 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 5983 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 5984 { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, 5985 { WM_CTLCOLORBTN, sent|defwinproc }, 5986 { BM_SETSTATE, sent|wparam|defwinproc, TRUE }, 5987 { WM_CTLCOLORBTN, sent|defwinproc }, 5988 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 5989 { 0 } 5990 }; 5991 static const struct message WmLButtonDownStaticSeq[] = 5992 { 5993 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 }, 5994 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, 5995 { HCBT_SETFOCUS, hook }, 5996 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 5997 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 5998 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 5999 { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, 6000 { WM_CTLCOLORSTATIC, sent|defwinproc }, 6001 { BM_SETSTATE, sent|wparam|defwinproc, TRUE }, 6002 { WM_CTLCOLORSTATIC, sent|defwinproc }, 6003 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6004 { 0 } 6005 }; 6006 static const struct message WmLButtonUpSeq[] = 6007 { 6008 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 }, 6009 { BM_SETSTATE, sent|wparam|defwinproc, FALSE }, 6010 { WM_CTLCOLORBTN, sent|defwinproc }, 6011 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6012 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, 6013 { WM_CAPTURECHANGED, sent|wparam|defwinproc, 0 }, 6014 { 0 } 6015 }; 6016 static const struct message WmLButtonUpStaticSeq[] = 6017 { 6018 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 }, 6019 { BM_SETSTATE, sent|wparam|defwinproc, FALSE }, 6020 { WM_CTLCOLORSTATIC, sent|defwinproc }, 6021 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6022 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, 6023 { WM_CAPTURECHANGED, sent|wparam|defwinproc, 0 }, 6024 { 0 } 6025 }; 6026 static const struct message WmLButtonUpAutoSeq[] = 6027 { 6028 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 }, 6029 { BM_SETSTATE, sent|wparam|defwinproc, FALSE }, 6030 { WM_CTLCOLORSTATIC, sent|defwinproc }, 6031 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6032 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, 6033 { BM_SETCHECK, sent|defwinproc }, 6034 { WM_CTLCOLORSTATIC, sent|defwinproc, 0, 0 }, 6035 { WM_CAPTURECHANGED, sent|wparam|defwinproc, 0 }, 6036 { 0 } 6037 }; 6038 static const struct message WmLButtonUpBrokenSeq[] = 6039 { 6040 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 }, 6041 { 0 } 6042 }; 6043 static const struct message WmSetFontButtonSeq[] = 6044 { 6045 { WM_SETFONT, sent }, 6046 { WM_PAINT, sent }, 6047 { WM_ERASEBKGND, sent|defwinproc|optional }, 6048 { WM_CTLCOLORBTN, sent|defwinproc }, 6049 { WM_CTLCOLORBTN, sent|defwinproc|optional }, /* FIXME: Wine sends it twice for BS_OWNERDRAW */ 6050 { 0 } 6051 }; 6052 static const struct message WmSetFontStaticSeq[] = 6053 { 6054 { WM_SETFONT, sent }, 6055 { WM_PAINT, sent }, 6056 { WM_ERASEBKGND, sent|defwinproc|optional }, 6057 { WM_CTLCOLORSTATIC, sent|defwinproc }, 6058 { 0 } 6059 }; 6060 static const struct message WmSetTextButtonSeq[] = 6061 { 6062 { WM_SETTEXT, sent }, 6063 { WM_CTLCOLORBTN, sent|parent }, 6064 { WM_CTLCOLORBTN, sent|parent }, 6065 { WM_COMMAND, sent|parent|optional }, 6066 { WM_DRAWITEM, sent|parent|optional }, 6067 { 0 } 6068 }; 6069 static const struct message WmSetTextStaticSeq[] = 6070 { 6071 { WM_SETTEXT, sent }, 6072 { WM_CTLCOLORSTATIC, sent|parent }, 6073 { WM_CTLCOLORSTATIC, sent|parent }, 6074 { 0 } 6075 }; 6076 static const struct message WmSetTextGroupSeq[] = 6077 { 6078 { WM_SETTEXT, sent }, 6079 { WM_CTLCOLORSTATIC, sent|parent }, 6080 { WM_CTLCOLORSTATIC, sent|parent|optional }, /* FIXME: Missing in Wine */ 6081 { WM_CTLCOLORSTATIC, sent|parent|optional }, /* FIXME: Missing in Wine */ 6082 { 0 } 6083 }; 6084 static const struct message WmSetTextInvisibleSeq[] = 6085 { 6086 { WM_SETTEXT, sent }, 6087 { 0 } 6088 }; 6089 static const struct message WmSetStyleButtonSeq[] = 6090 { 6091 { BM_SETSTYLE, sent }, 6092 { WM_APP, sent|wparam|lparam, 0, 0 }, 6093 { WM_PAINT, sent }, 6094 { WM_NCPAINT, sent|defwinproc|optional }, /* FIXME: Wine sends it */ 6095 { WM_ERASEBKGND, sent|defwinproc|optional }, /* Win9x doesn't send it */ 6096 { WM_CTLCOLORBTN, sent|parent }, 6097 { 0 } 6098 }; 6099 static const struct message WmSetStyleStaticSeq[] = 6100 { 6101 { BM_SETSTYLE, sent }, 6102 { WM_APP, sent|wparam|lparam, 0, 0 }, 6103 { WM_PAINT, sent }, 6104 { WM_NCPAINT, sent|defwinproc|optional }, /* FIXME: Wine sends it */ 6105 { WM_ERASEBKGND, sent|defwinproc|optional }, /* Win9x doesn't send it */ 6106 { WM_CTLCOLORSTATIC, sent|parent }, 6107 { 0 } 6108 }; 6109 static const struct message WmSetStyleUserSeq[] = 6110 { 6111 { BM_SETSTYLE, sent }, 6112 { WM_APP, sent|wparam|lparam, 0, 0 }, 6113 { WM_PAINT, sent }, 6114 { WM_NCPAINT, sent|defwinproc|optional }, /* FIXME: Wine sends it */ 6115 { WM_ERASEBKGND, sent|defwinproc|optional }, /* Win9x doesn't send it */ 6116 { WM_CTLCOLORBTN, sent|parent }, 6117 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_PAINT) }, 6118 { 0 } 6119 }; 6120 static const struct message WmSetStyleOwnerdrawSeq[] = 6121 { 6122 { BM_SETSTYLE, sent }, 6123 { WM_APP, sent|wparam|lparam, 0, 0 }, 6124 { WM_PAINT, sent }, 6125 { WM_NCPAINT, sent|optional }, /* FIXME: Wine sends it */ 6126 { WM_ERASEBKGND, sent|defwinproc|optional }, /* Win9x doesn't send it */ 6127 { WM_CTLCOLORBTN, sent|parent }, 6128 { WM_CTLCOLORBTN, sent|parent|optional }, /* Win9x doesn't send it */ 6129 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x000010e4 }, 6130 { 0 } 6131 }; 6132 static const struct message WmSetStateButtonSeq[] = 6133 { 6134 { BM_SETSTATE, sent }, 6135 { WM_CTLCOLORBTN, sent|parent }, 6136 { WM_APP, sent|wparam|lparam, 0, 0 }, 6137 { 0 } 6138 }; 6139 static const struct message WmSetStateStaticSeq[] = 6140 { 6141 { BM_SETSTATE, sent }, 6142 { WM_CTLCOLORSTATIC, sent|parent }, 6143 { WM_APP, sent|wparam|lparam, 0, 0 }, 6144 { 0 } 6145 }; 6146 static const struct message WmSetStateUserSeq[] = 6147 { 6148 { BM_SETSTATE, sent }, 6149 { WM_CTLCOLORBTN, sent|parent }, 6150 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_HILITE) }, 6151 { WM_APP, sent|wparam|lparam, 0, 0 }, 6152 { 0 } 6153 }; 6154 static const struct message WmSetStateOwnerdrawSeq[] = 6155 { 6156 { BM_SETSTATE, sent }, 6157 { WM_CTLCOLORBTN, sent|parent }, 6158 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x000120e4 }, 6159 { WM_APP, sent|wparam|lparam, 0, 0 }, 6160 { 0 } 6161 }; 6162 static const struct message WmClearStateButtonSeq[] = 6163 { 6164 { BM_SETSTATE, sent }, 6165 { WM_CTLCOLORBTN, sent|parent }, 6166 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_UNHILITE) }, 6167 { WM_APP, sent|wparam|lparam, 0, 0 }, 6168 { 0 } 6169 }; 6170 static const struct message WmDisableButtonSeq[] = 6171 { 6172 { WM_LBUTTONDOWN, sent }, 6173 { BM_SETSTATE, sent|defwinproc }, 6174 { WM_CTLCOLORSTATIC, sent|defwinproc|optional }, 6175 { WM_CTLCOLORBTN, sent|optional }, 6176 { WM_LBUTTONUP, sent }, 6177 { BM_SETSTATE, sent|defwinproc }, 6178 { WM_CTLCOLORBTN, sent|defwinproc|optional }, 6179 { WM_CTLCOLORSTATIC, sent|defwinproc|optional }, 6180 { BM_SETCHECK, sent|defwinproc|optional }, 6181 { WM_CTLCOLORBTN, sent|optional }, 6182 { WM_CTLCOLORSTATIC, sent|defwinproc|optional }, 6183 { WM_CAPTURECHANGED, sent|defwinproc }, 6184 { WM_COMMAND, sent }, 6185 { 0 } 6186 }; 6187 static const struct message WmClearStateOwnerdrawSeq[] = 6188 { 6189 { BM_SETSTATE, sent }, 6190 { WM_CTLCOLORBTN, sent|parent }, 6191 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x000020e4 }, 6192 { WM_APP, sent|wparam|lparam, 0, 0 }, 6193 { 0 } 6194 }; 6195 static const struct message WmSetCheckIgnoredSeq[] = 6196 { 6197 { BM_SETCHECK, sent }, 6198 { WM_APP, sent|wparam|lparam, 0, 0 }, 6199 { 0 } 6200 }; 6201 static const struct message WmSetCheckStaticSeq[] = 6202 { 6203 { BM_SETCHECK, sent }, 6204 { WM_CTLCOLORSTATIC, sent|parent }, 6205 { WM_APP, sent|wparam|lparam, 0, 0 }, 6206 { 0 } 6207 }; 6208 6209 static WNDPROC old_button_proc; 6210 6211 static LRESULT CALLBACK button_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 6212 { 6213 static LONG defwndproc_counter = 0; 6214 LRESULT ret; 6215 struct recvd_message msg; 6216 6217 if (ignore_message( message )) return 0; 6218 6219 switch (message) 6220 { 6221 case WM_SYNCPAINT: 6222 break; 6223 case BM_SETSTATE: 6224 if (GetCapture()) 6225 ok(GetCapture() == hwnd, "GetCapture() = %p\n", GetCapture()); 6226 6227 lParam = (ULONG_PTR)GetMenu(hwnd); 6228 goto log_it; 6229 6230 case WM_GETDLGCODE: 6231 if (lParam) 6232 { 6233 MSG *msg = (MSG *)lParam; 6234 lParam = MAKELPARAM(msg->message, msg->wParam); 6235 } 6236 wParam = (ULONG_PTR)GetMenu(hwnd); 6237 goto log_it; 6238 6239 case BM_SETCHECK: 6240 case BM_GETCHECK: 6241 lParam = (ULONG_PTR)GetMenu(hwnd); 6242 /* fall through */ 6243 log_it: 6244 default: 6245 msg.hwnd = hwnd; 6246 msg.message = message; 6247 msg.flags = sent|wparam|lparam; 6248 if (defwndproc_counter) msg.flags |= defwinproc; 6249 msg.wParam = wParam; 6250 msg.lParam = lParam; 6251 msg.descr = "button"; 6252 add_message(&msg); 6253 } 6254 6255 defwndproc_counter++; 6256 ret = CallWindowProcA(old_button_proc, hwnd, message, wParam, lParam); 6257 defwndproc_counter--; 6258 6259 return ret; 6260 } 6261 6262 static void subclass_button(void) 6263 { 6264 WNDCLASSA cls; 6265 6266 if (!GetClassInfoA(0, "button", &cls)) assert(0); 6267 6268 old_button_proc = cls.lpfnWndProc; 6269 6270 cls.hInstance = GetModuleHandleA(NULL); 6271 cls.lpfnWndProc = button_hook_proc; 6272 cls.lpszClassName = "my_button_class"; 6273 UnregisterClassA(cls.lpszClassName, cls.hInstance); 6274 if (!RegisterClassA(&cls)) assert(0); 6275 } 6276 6277 static void test_button_messages(void) 6278 { 6279 static const struct 6280 { 6281 DWORD style; 6282 DWORD dlg_code; 6283 const struct message *setfocus; 6284 const struct message *killfocus; 6285 const struct message *setstyle; 6286 const struct message *setstate; 6287 const struct message *clearstate; 6288 const struct message *setcheck; 6289 const struct message *lbuttondown; 6290 const struct message *lbuttonup; 6291 const struct message *setfont; 6292 const struct message *settext; 6293 } button[] = { 6294 { BS_PUSHBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON, 6295 WmSetFocusButtonSeq, WmKillFocusButtonSeq, WmSetStyleButtonSeq, 6296 WmSetStateButtonSeq, WmSetStateButtonSeq, WmSetCheckIgnoredSeq, 6297 WmLButtonDownSeq, WmLButtonUpSeq, WmSetFontButtonSeq, 6298 WmSetTextButtonSeq }, 6299 { BS_DEFPUSHBUTTON, DLGC_BUTTON | DLGC_DEFPUSHBUTTON, 6300 WmSetFocusButtonSeq, WmKillFocusButtonSeq, WmSetStyleButtonSeq, 6301 WmSetStateButtonSeq, WmSetStateButtonSeq, WmSetCheckIgnoredSeq, 6302 WmLButtonDownSeq, WmLButtonUpSeq, WmSetFontButtonSeq, 6303 WmSetTextButtonSeq }, 6304 { BS_CHECKBOX, DLGC_BUTTON, 6305 WmSetFocusStaticSeq, WmKillFocusStaticSeq, WmSetStyleStaticSeq, 6306 WmSetStateStaticSeq, WmSetStateStaticSeq, WmSetCheckStaticSeq, 6307 WmLButtonDownStaticSeq, WmLButtonUpStaticSeq, WmSetFontStaticSeq, 6308 WmSetTextStaticSeq }, 6309 { BS_AUTOCHECKBOX, DLGC_BUTTON, 6310 WmSetFocusStaticSeq, WmKillFocusStaticSeq, WmSetStyleStaticSeq, 6311 WmSetStateStaticSeq, WmSetStateStaticSeq, WmSetCheckStaticSeq, 6312 WmLButtonDownStaticSeq, WmLButtonUpAutoSeq, WmSetFontStaticSeq, 6313 WmSetTextStaticSeq }, 6314 { BS_RADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON, 6315 WmSetFocusStaticSeq, WmKillFocusStaticSeq, WmSetStyleStaticSeq, 6316 WmSetStateStaticSeq, WmSetStateStaticSeq, WmSetCheckStaticSeq, 6317 WmLButtonDownStaticSeq, WmLButtonUpStaticSeq, WmSetFontStaticSeq, 6318 WmSetTextStaticSeq }, 6319 { BS_3STATE, DLGC_BUTTON, 6320 WmSetFocusStaticSeq, WmKillFocusStaticSeq, WmSetStyleStaticSeq, 6321 WmSetStateStaticSeq, WmSetStateStaticSeq, WmSetCheckStaticSeq, 6322 WmLButtonDownStaticSeq, WmLButtonUpStaticSeq, WmSetFontStaticSeq, 6323 WmSetTextStaticSeq }, 6324 { BS_AUTO3STATE, DLGC_BUTTON, 6325 WmSetFocusStaticSeq, WmKillFocusStaticSeq, WmSetStyleStaticSeq, 6326 WmSetStateStaticSeq, WmSetStateStaticSeq, WmSetCheckStaticSeq, 6327 WmLButtonDownStaticSeq, WmLButtonUpAutoSeq, WmSetFontStaticSeq, 6328 WmSetTextStaticSeq }, 6329 { BS_GROUPBOX, DLGC_STATIC, 6330 WmSetFocusStaticSeq, WmKillFocusStaticSeq, WmSetStyleStaticSeq, 6331 WmSetStateStaticSeq, WmSetStateStaticSeq, WmSetCheckIgnoredSeq, 6332 WmLButtonDownStaticSeq, WmLButtonUpStaticSeq, WmSetFontStaticSeq, 6333 WmSetTextGroupSeq }, 6334 { BS_USERBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON, 6335 WmSetFocusButtonSeq, WmKillFocusButtonSeq, WmSetStyleUserSeq, 6336 WmSetStateUserSeq, WmClearStateButtonSeq, WmSetCheckIgnoredSeq, 6337 WmLButtonDownSeq, WmLButtonUpSeq, WmSetFontButtonSeq, 6338 WmSetTextButtonSeq }, 6339 { BS_AUTORADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON, 6340 WmSetFocusStaticSeq, WmKillFocusStaticSeq, WmSetStyleStaticSeq, 6341 WmSetStateStaticSeq, WmSetStateStaticSeq, WmSetCheckStaticSeq, 6342 NULL /* avoid infinite loop */, WmLButtonUpBrokenSeq, WmSetFontStaticSeq, 6343 WmSetTextStaticSeq }, 6344 { BS_OWNERDRAW, DLGC_BUTTON, 6345 WmSetFocusOwnerdrawSeq, WmKillFocusOwnerdrawSeq, WmSetStyleOwnerdrawSeq, 6346 WmSetStateOwnerdrawSeq, WmClearStateOwnerdrawSeq, WmSetCheckIgnoredSeq, 6347 WmLButtonDownSeq, WmLButtonUpSeq, WmSetFontButtonSeq, 6348 WmSetTextButtonSeq }, 6349 }; 6350 LOGFONTA logfont = { 0 }; 6351 HFONT zfont, hfont2; 6352 unsigned int i; 6353 HWND hwnd, parent; 6354 DWORD dlg_code; 6355 6356 /* selection with VK_SPACE should capture button window */ 6357 hwnd = CreateWindowExA(0, "button", "test", BS_CHECKBOX | WS_VISIBLE | WS_POPUP, 6358 0, 0, 50, 14, 0, 0, 0, NULL); 6359 ok(hwnd != 0, "Failed to create button window\n"); 6360 ReleaseCapture(); 6361 SetFocus(hwnd); 6362 SendMessageA(hwnd, WM_KEYDOWN, VK_SPACE, 0); 6363 ok(GetCapture() == hwnd, "Should be captured on VK_SPACE WM_KEYDOWN\n"); 6364 SendMessageA(hwnd, WM_KEYUP, VK_SPACE, 0); 6365 DestroyWindow(hwnd); 6366 6367 subclass_button(); 6368 6369 parent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 6370 100, 100, 200, 200, 0, 0, 0, NULL); 6371 ok(parent != 0, "Failed to create parent window\n"); 6372 6373 memset(&logfont, 0, sizeof(logfont)); 6374 logfont.lfHeight = -12; 6375 logfont.lfWeight = FW_NORMAL; 6376 strcpy(logfont.lfFaceName, "Tahoma"); 6377 6378 hfont2 = CreateFontIndirectA(&logfont); 6379 ok(hfont2 != NULL, "Failed to create Tahoma font\n"); 6380 6381 for (i = 0; i < ARRAY_SIZE(button); i++) 6382 { 6383 MSG msg; 6384 DWORD style, state; 6385 HFONT prevfont; 6386 char desc[64]; 6387 HDC hdc; 6388 6389 trace("button style %08x\n", button[i].style); 6390 6391 hwnd = CreateWindowExA(0, "my_button_class", "test", button[i].style | WS_CHILD | BS_NOTIFY, 6392 0, 0, 50, 14, parent, (HMENU)ID_BUTTON, 0, NULL); 6393 ok(hwnd != 0, "Failed to create button window\n"); 6394 6395 style = GetWindowLongA(hwnd, GWL_STYLE); 6396 style &= ~(WS_CHILD | BS_NOTIFY); 6397 /* XP turns a BS_USERBUTTON into BS_PUSHBUTTON */ 6398 if (button[i].style == BS_USERBUTTON) 6399 ok(style == BS_PUSHBUTTON, "expected style BS_PUSHBUTTON got %x\n", style); 6400 else 6401 ok(style == button[i].style, "expected style %x got %x\n", button[i].style, style); 6402 6403 dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0); 6404 ok(dlg_code == button[i].dlg_code, "%u: wrong dlg_code %08x\n", i, dlg_code); 6405 6406 ShowWindow(hwnd, SW_SHOW); 6407 UpdateWindow(hwnd); 6408 SetFocus(0); 6409 flush_events(); 6410 SetFocus(0); 6411 flush_sequence(); 6412 6413 log_all_parent_messages++; 6414 6415 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus()); 6416 SetFocus(hwnd); 6417 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ 6418 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 6419 ok_sequence(button[i].setfocus, "SetFocus(hwnd) on a button", FALSE); 6420 6421 SetFocus(0); 6422 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ 6423 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 6424 ok_sequence(button[i].killfocus, "SetFocus(0) on a button", FALSE); 6425 6426 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus()); 6427 6428 SendMessageA(hwnd, BM_SETSTYLE, button[i].style | BS_BOTTOM, TRUE); 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].setstyle, "BM_SETSTYLE on a button", FALSE); 6432 6433 style = GetWindowLongA(hwnd, GWL_STYLE); 6434 style &= ~(WS_VISIBLE | WS_CHILD | BS_NOTIFY); 6435 /* XP doesn't turn a BS_USERBUTTON into BS_PUSHBUTTON here! */ 6436 ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style); 6437 6438 state = SendMessageA(hwnd, BM_GETSTATE, 0, 0); 6439 ok(state == 0, "expected state 0, got %04x\n", state); 6440 6441 flush_sequence(); 6442 6443 SendMessageA(hwnd, BM_SETSTATE, TRUE, 0); 6444 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ 6445 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 6446 ok_sequence(button[i].setstate, "BM_SETSTATE/TRUE on a button", FALSE); 6447 6448 state = SendMessageA(hwnd, BM_GETSTATE, 0, 0); 6449 ok(state == 0x0004, "expected state 0x0004, got %04x\n", state); 6450 6451 style = GetWindowLongA(hwnd, GWL_STYLE); 6452 style &= ~(WS_CHILD | BS_NOTIFY | WS_VISIBLE); 6453 ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style); 6454 6455 flush_sequence(); 6456 6457 SendMessageA(hwnd, BM_SETSTATE, FALSE, 0); 6458 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ 6459 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 6460 ok_sequence(button[i].clearstate, "BM_SETSTATE/FALSE on a button", FALSE); 6461 6462 state = SendMessageA(hwnd, BM_GETSTATE, 0, 0); 6463 ok(state == 0, "expected state 0, got %04x\n", state); 6464 6465 style = GetWindowLongA(hwnd, GWL_STYLE); 6466 style &= ~(WS_CHILD | BS_NOTIFY | WS_VISIBLE); 6467 ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style); 6468 6469 state = SendMessageA(hwnd, BM_GETCHECK, 0, 0); 6470 ok(state == BST_UNCHECKED, "expected BST_UNCHECKED, got %04x\n", state); 6471 6472 flush_sequence(); 6473 6474 SendMessageA(hwnd, BM_SETCHECK, BST_UNCHECKED, 0); 6475 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ 6476 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 6477 ok_sequence(WmSetCheckIgnoredSeq, "BM_SETCHECK on a button", FALSE); 6478 6479 state = SendMessageA(hwnd, BM_GETCHECK, 0, 0); 6480 ok(state == BST_UNCHECKED, "expected BST_UNCHECKED, got %04x\n", state); 6481 6482 style = GetWindowLongA(hwnd, GWL_STYLE); 6483 style &= ~(WS_CHILD | BS_NOTIFY | WS_VISIBLE); 6484 ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style); 6485 6486 flush_sequence(); 6487 6488 SendMessageA(hwnd, BM_SETCHECK, BST_CHECKED, 0); 6489 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ 6490 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 6491 ok_sequence(button[i].setcheck, "BM_SETCHECK on a button", FALSE); 6492 6493 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"Text 1"); 6494 sprintf(desc, "button[%i]: WM_SETTEXT on a visible button", i); 6495 ok_sequence(button[i].settext, desc, FALSE); 6496 6497 ShowWindow(hwnd, SW_HIDE); 6498 flush_events(); 6499 flush_sequence(); 6500 6501 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"Text 2"); 6502 sprintf(desc, "button[%i]: WM_SETTEXT on an invisible button", i); 6503 ok_sequence(WmSetTextInvisibleSeq, desc, FALSE); 6504 6505 ShowWindow(hwnd, SW_SHOW); 6506 ShowWindow(parent, SW_HIDE); 6507 flush_events(); 6508 flush_sequence(); 6509 6510 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"Text 3"); 6511 sprintf(desc, "button[%i]: WM_SETTEXT on an invisible button", i); 6512 ok_sequence(WmSetTextInvisibleSeq, desc, FALSE); 6513 6514 ShowWindow(parent, SW_SHOW); 6515 flush_events(); 6516 6517 state = SendMessageA(hwnd, BM_GETCHECK, 0, 0); 6518 if (button[i].style == BS_PUSHBUTTON || 6519 button[i].style == BS_DEFPUSHBUTTON || 6520 button[i].style == BS_GROUPBOX || 6521 button[i].style == BS_USERBUTTON || 6522 button[i].style == BS_OWNERDRAW) 6523 ok(state == BST_UNCHECKED, "expected check 0, got %04x\n", state); 6524 else 6525 ok(state == BST_CHECKED, "expected check 1, got %04x\n", state); 6526 6527 style = GetWindowLongA(hwnd, GWL_STYLE); 6528 style &= ~(WS_CHILD | BS_NOTIFY | WS_VISIBLE); 6529 if (button[i].style == BS_RADIOBUTTON || 6530 button[i].style == BS_AUTORADIOBUTTON) 6531 ok(style == (button[i].style | WS_TABSTOP), "expected style %04x | WS_TABSTOP got %04x\n", button[i].style, style); 6532 else 6533 ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style); 6534 6535 log_all_parent_messages--; 6536 6537 DestroyWindow(hwnd); 6538 6539 hwnd = CreateWindowExA(0, "my_button_class", "test", button[i].style | WS_POPUP | WS_VISIBLE, 6540 0, 0, 50, 14, 0, 0, 0, NULL); 6541 ok(hwnd != 0, "Failed to create button window\n"); 6542 6543 SetForegroundWindow(hwnd); 6544 flush_events(); 6545 6546 SetActiveWindow(hwnd); 6547 SetFocus(0); 6548 flush_sequence(); 6549 6550 if (button[i].lbuttondown) 6551 { 6552 SendMessageA(hwnd, WM_LBUTTONDOWN, 0, 0); 6553 sprintf(desc, "button[%i]: WM_LBUTTONDOWN on a button", i); 6554 ok_sequence(button[i].lbuttondown, desc, FALSE); 6555 } 6556 6557 SendMessageA(hwnd, WM_LBUTTONUP, 0, 0); 6558 sprintf(desc, "button[%i]: WM_LBUTTONUP on a button", i); 6559 ok_sequence(button[i].lbuttonup, desc, FALSE); 6560 6561 flush_sequence(); 6562 zfont = GetStockObject(DEFAULT_GUI_FONT); 6563 SendMessageA(hwnd, WM_SETFONT, (WPARAM)zfont, TRUE); 6564 UpdateWindow(hwnd); 6565 sprintf(desc, "button[%i]: WM_SETFONT on a button", i); 6566 ok_sequence(button[i].setfont, desc, FALSE); 6567 6568 /* Test that original font is not selected back after painting */ 6569 hdc = CreateCompatibleDC(0); 6570 6571 prevfont = SelectObject(hdc, hfont2); 6572 ok(prevfont == GetStockObject(SYSTEM_FONT), "Unexpected default font\n"); 6573 SendMessageA(hwnd, WM_PRINTCLIENT, (WPARAM)hdc, 0); 6574 ok(hfont2 != GetCurrentObject(hdc, OBJ_FONT), "button[%u]: unexpected font selected after WM_PRINTCLIENT\n", i); 6575 SelectObject(hdc, prevfont); 6576 6577 prevfont = SelectObject(hdc, hfont2); 6578 ok(prevfont == GetStockObject(SYSTEM_FONT), "Unexpected default font\n"); 6579 SendMessageA(hwnd, WM_PAINT, (WPARAM)hdc, 0); 6580 ok(hfont2 != GetCurrentObject(hdc, OBJ_FONT), "button[%u]: unexpected font selected after WM_PAINT\n", i); 6581 SelectObject(hdc, prevfont); 6582 6583 DeleteDC(hdc); 6584 6585 DestroyWindow(hwnd); 6586 } 6587 6588 DeleteObject(hfont2); 6589 DestroyWindow(parent); 6590 6591 /* Test if WM_LBUTTONDOWN and WM_LBUTTONUP to a disabled button leads to a WM_COMMAND for the parent */ 6592 6593 parent = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 6594 100, 100, 200, 200, 0, 0, 0, NULL); 6595 ok (hwnd != 0, "Failed to create overlapped window\n"); 6596 6597 hwnd = CreateWindowExA(0, "my_button_class", "test", BS_DEFPUSHBUTTON | WS_VISIBLE | WS_CHILD, 6598 0, 0, 50, 14, parent, 0, 0, NULL); 6599 6600 EnableWindow(hwnd, FALSE); 6601 flush_sequence(); 6602 SendMessageA(hwnd, WM_LBUTTONDOWN, MK_LBUTTON, 0); 6603 SendMessageA(hwnd, WM_LBUTTONUP, 0, 0); 6604 ok_sequence(WmDisableButtonSeq, "Mouseclick on a disabled button", FALSE); 6605 6606 DestroyWindow(hwnd); 6607 DestroyWindow(parent); 6608 } 6609 6610 static void test_button_bm_get_set_image(void) 6611 { 6612 HWND hwnd; 6613 HDC hdc; 6614 HBITMAP hbmp1x1; 6615 HBITMAP hbmp2x2; 6616 HBITMAP hmask2x2; 6617 ICONINFO icon_info2x2; 6618 HICON hicon2x2; 6619 HBITMAP hbmp; 6620 HICON hicon; 6621 ICONINFO icon_info; 6622 BITMAP bm; 6623 DWORD default_style = BS_PUSHBUTTON | WS_TABSTOP | WS_POPUP | WS_VISIBLE; 6624 LRESULT ret; 6625 6626 hdc = GetDC(0); 6627 hbmp1x1 = CreateCompatibleBitmap(hdc, 1, 1); 6628 hbmp2x2 = CreateCompatibleBitmap(hdc, 2, 2); 6629 ZeroMemory(&bm, sizeof(bm)); 6630 ok(GetObjectW(hbmp1x1, sizeof(bm), &bm), "Expect GetObjectW() success\n"); 6631 ok(bm.bmWidth == 1 && bm.bmHeight == 1, "Expect bitmap size: %d,%d, got: %d,%d\n", 1, 1, 6632 bm.bmWidth, bm.bmHeight); 6633 ZeroMemory(&bm, sizeof(bm)); 6634 ok(GetObjectW(hbmp2x2, sizeof(bm), &bm), "Expect GetObjectW() success\n"); 6635 ok(bm.bmWidth == 2 && bm.bmHeight == 2, "Expect bitmap size: %d,%d, got: %d,%d\n", 2, 2, 6636 bm.bmWidth, bm.bmHeight); 6637 6638 hmask2x2 = CreateCompatibleBitmap(hdc, 2, 2); 6639 ZeroMemory(&icon_info2x2, sizeof(icon_info2x2)); 6640 icon_info2x2.fIcon = TRUE; 6641 icon_info2x2.hbmMask = hmask2x2; 6642 icon_info2x2.hbmColor = hbmp2x2; 6643 hicon2x2 = CreateIconIndirect(&icon_info2x2); 6644 6645 ZeroMemory(&icon_info, sizeof(icon_info)); 6646 ok(GetIconInfo(hicon2x2, &icon_info), "Expect GetIconInfo() success\n"); 6647 ZeroMemory(&bm, sizeof(bm)); 6648 ok(GetObjectW(icon_info.hbmColor, sizeof(bm), &bm), "Expect GetObjectW() success\n"); 6649 ok(bm.bmWidth == 2 && bm.bmHeight == 2, "Expect bitmap size: %d,%d, got: %d,%d\n", 2, 2, 6650 bm.bmWidth, bm.bmHeight); 6651 DeleteObject(icon_info.hbmColor); 6652 DeleteObject(icon_info.hbmMask); 6653 6654 /* Set bitmap with BS_BITMAP */ 6655 hwnd = CreateWindowA("Button", "test", default_style | BS_BITMAP, 0, 0, 100, 100, 0, 0, 0, 0); 6656 ok(hwnd != NULL, "Expect hwnd not NULL\n"); 6657 SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hbmp1x1); 6658 hbmp = (HBITMAP)SendMessageA(hwnd, BM_GETIMAGE, (WPARAM)IMAGE_BITMAP, 0); 6659 ok(hbmp != 0, "Expect hbmp not 0\n"); 6660 ZeroMemory(&bm, sizeof(bm)); 6661 ok(GetObjectW(hbmp, sizeof(bm), &bm), "Expect GetObjectW() success\n"); 6662 ok(bm.bmWidth == 1 && bm.bmHeight == 1, "Expect bitmap size: %d,%d, got: %d,%d\n", 1, 1, 6663 bm.bmWidth, bm.bmHeight); 6664 DestroyWindow(hwnd); 6665 6666 /* Set bitmap without BS_BITMAP */ 6667 hwnd = CreateWindowA("Button", "test", default_style, 0, 0, 100, 100, 0, 0, 0, 0); 6668 ok(hwnd != NULL, "Expect hwnd not NULL\n"); 6669 ret = SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hbmp1x1); 6670 ok(ret == 0, "Expect ret to be 0\n"); 6671 hbmp = (HBITMAP)SendMessageA(hwnd, BM_GETIMAGE, (WPARAM)IMAGE_BITMAP, 0); 6672 ok(hbmp == NULL, "Expect hbmp to be NULL\n"); 6673 DestroyWindow(hwnd); 6674 6675 /* Set icon with BS_ICON */ 6676 hwnd = CreateWindowA("Button", "test", default_style | BS_ICON, 0, 0, 100, 100, 0, 0, 0, 0); 6677 ok(hwnd != NULL, "Expect hwnd not NULL\n"); 6678 SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hicon2x2); 6679 hicon = (HICON)SendMessageA(hwnd, BM_GETIMAGE, (WPARAM)IMAGE_ICON, 0); 6680 ok(hicon != NULL, "Expect hicon not NULL\n"); 6681 ZeroMemory(&icon_info, sizeof(icon_info)); 6682 ok(GetIconInfo(hicon, &icon_info), "Expect GetIconInfo() success\n"); 6683 ZeroMemory(&bm, sizeof(bm)); 6684 ok(GetObjectW(icon_info.hbmColor, sizeof(bm), &bm), "Expect GetObjectW() success\n"); 6685 ok(bm.bmWidth == 2 && bm.bmHeight == 2, "Expect bitmap size: %d,%d, got: %d,%d\n", 2, 2, 6686 bm.bmWidth, bm.bmHeight); 6687 DeleteObject(icon_info.hbmColor); 6688 DeleteObject(icon_info.hbmMask); 6689 DestroyWindow(hwnd); 6690 6691 /* Set icon without BS_ICON */ 6692 hwnd = CreateWindowA("Button", "test", default_style, 0, 0, 100, 100, 0, 0, 0, 0); 6693 ok(hwnd != NULL, "Expect hwnd not NULL\n"); 6694 ret = SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hicon2x2); 6695 ok(ret == 0, "Expect ret to be 0\n"); 6696 hicon = (HICON)SendMessageA(hwnd, BM_GETIMAGE, (WPARAM)IMAGE_ICON, 0); 6697 ok(hicon == NULL, "Expect hicon to be NULL\n"); 6698 DestroyWindow(hwnd); 6699 6700 /* Set icon with BS_BITMAP */ 6701 hwnd = CreateWindowA("Button", "test", default_style | BS_BITMAP, 0, 0, 100, 100, 0, 0, 0, 0); 6702 ok(hwnd != NULL, "Expect hwnd to be not NULL\n"); 6703 ret = SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hicon2x2); 6704 ok(ret == 0, "Expect ret to be 0\n"); 6705 hicon = (HICON)SendMessageA(hwnd, BM_GETIMAGE, (WPARAM)IMAGE_ICON, 0); 6706 ok(hicon == NULL, "Expect hicon to be NULL\n"); 6707 DestroyWindow(hwnd); 6708 6709 /* Set bitmap with BS_ICON */ 6710 hwnd = CreateWindowA("Button", "test", default_style | BS_ICON, 0, 0, 100, 100, 0, 0, 0, 0); 6711 ok(hwnd != NULL, "Expect hwnd to be not NULL\n"); 6712 ret = SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hbmp1x1); 6713 ok(ret == 0, "Expect ret to be 0\n"); 6714 hbmp = (HBITMAP)SendMessageA(hwnd, BM_GETIMAGE, (WPARAM)IMAGE_BITMAP, 0); 6715 ok(hbmp == NULL, "Expect hbmp to be NULL\n"); 6716 DestroyWindow(hwnd); 6717 6718 DestroyIcon(hicon2x2); 6719 DeleteObject(hmask2x2); 6720 DeleteObject(hbmp2x2); 6721 DeleteObject(hbmp1x1); 6722 ReleaseDC(0, hdc); 6723 } 6724 6725 #define ID_RADIO1 501 6726 #define ID_RADIO2 502 6727 #define ID_RADIO3 503 6728 #define ID_TEXT 504 6729 6730 static const struct message auto_radio_button_BM_CLICK[] = 6731 { 6732 { BM_CLICK, sent|wparam|lparam, 0, 0 }, 6733 { WM_LBUTTONDOWN, sent|wparam|lparam|defwinproc, 0, 0 }, 6734 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, 6735 { BM_SETSTATE, sent|wparam|lparam|defwinproc, BST_CHECKED, ID_RADIO2 }, 6736 { WM_CTLCOLORSTATIC, sent|parent }, 6737 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6738 { WM_LBUTTONUP, sent|wparam|lparam|defwinproc, 0, 0 }, 6739 { BM_SETSTATE, sent|wparam|lparam|defwinproc, BST_UNCHECKED, ID_RADIO2 }, 6740 { WM_CTLCOLORSTATIC, sent|parent }, 6741 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6742 { WM_GETDLGCODE, sent|wparam|lparam|defwinproc, ID_RADIO2, 0 }, 6743 { BM_SETCHECK, sent|wparam|lparam|defwinproc, BST_CHECKED, ID_RADIO2 }, 6744 { WM_GETDLGCODE, sent|wparam|lparam|defwinproc, ID_RADIO1, 0 }, 6745 { BM_SETCHECK, sent|wparam|lparam|defwinproc, 0, ID_RADIO1 }, 6746 { WM_CTLCOLORSTATIC, sent|parent }, 6747 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6748 { WM_GETDLGCODE, sent|wparam|lparam|defwinproc, ID_RADIO3, 0 }, 6749 { BM_SETCHECK, sent|wparam|lparam|defwinproc, 0, ID_RADIO3 }, 6750 { WM_CTLCOLORSTATIC, sent|parent }, 6751 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6752 { WM_GETDLGCODE, sent|wparam|lparam|defwinproc, ID_TEXT, 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_RADIO2, 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 { 0 } 6760 }; 6761 6762 static const struct message auto_radio_button_VK_UP_child[] = 6763 { 6764 { WM_KEYDOWN, sent|wparam|lparam, VK_UP, 0 }, 6765 { WM_KEYUP, sent|wparam|lparam, VK_UP, 0 }, 6766 { 0 } 6767 }; 6768 6769 static const struct message auto_radio_button_VK_UP_parent[] = 6770 { 6771 { WM_KEYDOWN, sent|wparam|lparam|parent, VK_UP, 0 }, 6772 { WM_KEYUP, sent|wparam|lparam|parent, VK_UP, 0 }, 6773 { 0 } 6774 }; 6775 6776 static const struct message auto_radio_button_VK_UP_dialog[] = 6777 { 6778 { WM_GETDLGCODE, sent|parent, 0, 0 }, 6779 6780 /* optional trailer seen on some windows setups */ 6781 { WM_CHANGEUISTATE, sent|optional }, 6782 { WM_UPDATEUISTATE, sent|optional }, 6783 { WM_UPDATEUISTATE, sent|optional }, 6784 { WM_UPDATEUISTATE, sent|optional }, 6785 { WM_UPDATEUISTATE, sent|optional }, 6786 { WM_UPDATEUISTATE, sent|optional }, 6787 { WM_UPDATEUISTATE, sent|optional }, 6788 { WM_UPDATEUISTATE, sent|optional }, 6789 { WM_UPDATEUISTATE, sent|optional }, 6790 { WM_UPDATEUISTATE, sent|optional }, 6791 { WM_UPDATEUISTATE, sent|optional }, 6792 { WM_UPDATEUISTATE, sent|optional }, 6793 { WM_UPDATEUISTATE, sent|optional }, 6794 { WM_UPDATEUISTATE, sent|optional }, 6795 { WM_UPDATEUISTATE, sent|optional }, 6796 { WM_UPDATEUISTATE, sent|optional }, 6797 { WM_UPDATEUISTATE, sent|optional }, 6798 { WM_UPDATEUISTATE, sent|optional }, 6799 { WM_UPDATEUISTATE, sent|optional }, 6800 { WM_CTLCOLORSTATIC, sent|parent|optional }, 6801 { WM_CTLCOLORSTATIC, sent|parent|optional }, 6802 { WM_CTLCOLORSTATIC, sent|parent|optional }, 6803 { WM_UPDATEUISTATE, sent|optional }, 6804 { WM_CTLCOLORSTATIC, sent|parent|optional }, 6805 { WM_CTLCOLORSTATIC, sent|parent|optional }, 6806 { WM_UPDATEUISTATE, sent|optional }, 6807 { WM_CTLCOLORBTN, sent|parent|optional }, 6808 { WM_CTLCOLORBTN, sent|parent|optional }, 6809 { WM_UPDATEUISTATE, sent|optional }, 6810 { WM_CTLCOLORSTATIC, sent|parent|optional }, 6811 { WM_CTLCOLORSTATIC, sent|parent|optional }, 6812 { 0 } 6813 }; 6814 6815 static const struct message auto_radio_button_VK_DOWN_dialog[] = 6816 { 6817 { WM_GETDLGCODE, sent|parent, 0, 0 }, 6818 { WM_GETDLGCODE, sent|wparam|lparam, ID_RADIO1, MAKELPARAM(WM_KEYDOWN, VK_DOWN) }, 6819 { WM_GETDLGCODE, sent|wparam|lparam, ID_RADIO1, 0 }, 6820 { HCBT_SETFOCUS, hook }, 6821 { WM_KILLFOCUS, sent, 0, 0 }, 6822 { WM_CTLCOLORSTATIC, sent|parent }, 6823 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_RADIO3, BN_KILLFOCUS) }, 6824 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6825 { WM_SETFOCUS, sent, 0, 0 }, 6826 { WM_CTLCOLORSTATIC, sent|parent }, 6827 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_RADIO1, BN_SETFOCUS) }, 6828 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_RADIO1, BN_CLICKED) }, 6829 { WM_GETDLGCODE, sent|wparam|lparam, ID_RADIO1, 0 }, 6830 { WM_GETDLGCODE, sent|parent, 0, 0 }, 6831 { DM_GETDEFID, sent|parent, 0, 0 }, 6832 { BM_GETCHECK, sent|wparam|lparam, 0, ID_RADIO1 }, 6833 { BM_CLICK, sent|wparam|lparam, 1, 0 }, 6834 { WM_LBUTTONDOWN, sent|wparam|lparam|defwinproc, 0, 0 }, 6835 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, 6836 { BM_SETSTATE, sent|wparam|lparam|defwinproc, BST_CHECKED, ID_RADIO1 }, 6837 { WM_CTLCOLORSTATIC, sent|parent }, 6838 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6839 { WM_LBUTTONUP, sent|wparam|lparam|defwinproc, 0, 0 }, 6840 { BM_SETSTATE, sent|wparam|lparam|defwinproc, BST_UNCHECKED, ID_RADIO1 }, 6841 { WM_CTLCOLORSTATIC, sent|parent }, 6842 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6843 { WM_GETDLGCODE, sent|wparam|lparam|defwinproc, ID_RADIO1, 0 }, 6844 { BM_SETCHECK, sent|wparam|lparam|defwinproc, BST_CHECKED, ID_RADIO1 }, 6845 { WM_CTLCOLORSTATIC, sent|parent }, 6846 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6847 { WM_GETDLGCODE, sent|wparam|lparam|defwinproc, ID_RADIO3, 0 }, 6848 { BM_SETCHECK, sent|wparam|lparam|defwinproc, BST_UNCHECKED, ID_RADIO3 }, 6849 { WM_CTLCOLORSTATIC, sent|parent }, 6850 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6851 { WM_GETDLGCODE, sent|wparam|lparam|defwinproc, ID_TEXT, 0 }, 6852 { WM_GETDLGCODE, sent|wparam|lparam|defwinproc, ID_RADIO2, 0 }, 6853 { BM_SETCHECK, sent|wparam|lparam|defwinproc, BST_UNCHECKED, ID_RADIO2 }, 6854 { WM_CTLCOLORSTATIC, sent|parent }, 6855 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6856 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, 6857 { WM_CAPTURECHANGED, sent|wparam|lparam|defwinproc, 0, 0 }, 6858 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_RADIO1, BN_CLICKED) }, 6859 { WM_NCHITTEST, sent|optional, 0, 0 }, /* FIXME: Wine doesn't send it */ 6860 { WM_SETCURSOR, sent|optional, 0, 0 }, /* FIXME: Wine doesn't send it */ 6861 { WM_MOUSEMOVE, sent|optional, 0, 0 }, /* FIXME: Wine doesn't send it */ 6862 { WM_PAINT, sent }, 6863 { WM_CTLCOLORSTATIC, sent|parent }, 6864 { 0 } 6865 }; 6866 6867 static const struct message auto_radio_button_VK_DOWN_radio3[] = 6868 { 6869 { BM_GETCHECK, sent|wparam|lparam, 0, ID_RADIO1 }, 6870 { BM_GETCHECK, sent|wparam|lparam, 0, ID_RADIO2 }, 6871 { BM_GETCHECK, sent|wparam|lparam, 0, ID_RADIO3 }, 6872 { WM_GETDLGCODE, sent|parent, 0, 0 }, 6873 { WM_GETDLGCODE, sent|wparam|lparam, ID_RADIO1, MAKELPARAM(WM_KEYDOWN, VK_DOWN) }, 6874 { WM_GETDLGCODE, sent|wparam|lparam, ID_RADIO1, 0 }, 6875 { WM_GETDLGCODE, sent|wparam|lparam, ID_RADIO1, 0 }, 6876 { WM_GETDLGCODE, sent|wparam|lparam|parent, 0, 0 }, 6877 { WM_USER, sent|parent, 0, 0 }, 6878 { BM_GETCHECK, sent|wparam|lparam, 0, ID_RADIO1 }, 6879 { 0 } 6880 }; 6881 6882 static const struct message auto_radio_button_VK_UP_radio1[] = 6883 { 6884 { WM_GETDLGCODE, sent|parent, 0, 0 }, 6885 { 0 } 6886 }; 6887 6888 static INT_PTR WINAPI radio_test_dlg_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) 6889 { 6890 ParentMsgCheckProcA(hwnd, msg, wp, lp); 6891 return 1; 6892 } 6893 6894 static void test_autoradio_BM_CLICK(void) 6895 { 6896 HWND parent, radio1, radio2, radio3; 6897 RECT rc; 6898 MSG msg; 6899 DWORD ret; 6900 6901 subclass_button(); 6902 6903 parent = CreateDialogParamA(0, "AUTORADIO_TEST_DIALOG_1", 0, radio_test_dlg_proc, 0); 6904 ok(parent != 0, "failed to create parent window\n"); 6905 6906 radio1 = GetDlgItem(parent, ID_RADIO1); 6907 radio2 = GetDlgItem(parent, ID_RADIO2); 6908 radio3 = GetDlgItem(parent, ID_RADIO3); 6909 6910 /* this avoids focus messages in the generated sequence */ 6911 SetFocus(radio2); 6912 6913 flush_events(); 6914 flush_sequence(); 6915 6916 ret = SendMessageA(radio1, BM_GETCHECK, 0, 0); 6917 ok(ret == BST_UNCHECKED, "got %08x\n", ret); 6918 ret = SendMessageA(radio2, BM_GETCHECK, 0, 0); 6919 ok(ret == BST_UNCHECKED, "got %08x\n", ret); 6920 ret = SendMessageA(radio3, BM_GETCHECK, 0, 0); 6921 ok(ret == BST_UNCHECKED, "got %08x\n", ret); 6922 6923 SendMessageA(radio1, BM_SETCHECK, BST_CHECKED, 0); 6924 6925 ret = SendMessageA(radio1, BM_GETCHECK, 0, 0); 6926 ok(ret == BST_CHECKED, "got %08x\n", ret); 6927 ret = SendMessageA(radio2, BM_GETCHECK, 0, 0); 6928 ok(ret == BST_UNCHECKED, "got %08x\n", ret); 6929 ret = SendMessageA(radio3, BM_GETCHECK, 0, 0); 6930 ok(ret == BST_UNCHECKED, "got %08x\n", ret); 6931 6932 SendMessageA(radio2, BM_SETCHECK, BST_CHECKED, 0); 6933 6934 ret = SendMessageA(radio1, BM_GETCHECK, 0, 0); 6935 ok(ret == BST_CHECKED, "got %08x\n", ret); 6936 ret = SendMessageA(radio2, BM_GETCHECK, 0, 0); 6937 ok(ret == BST_CHECKED, "got %08x\n", ret); 6938 ret = SendMessageA(radio3, BM_GETCHECK, 0, 0); 6939 ok(ret == BST_UNCHECKED, "got %08x\n", ret); 6940 6941 SendMessageA(radio3, BM_SETCHECK, BST_CHECKED, 0); 6942 6943 ret = SendMessageA(radio1, BM_GETCHECK, 0, 0); 6944 ok(ret == BST_CHECKED, "got %08x\n", ret); 6945 ret = SendMessageA(radio2, BM_GETCHECK, 0, 0); 6946 ok(ret == BST_CHECKED, "got %08x\n", ret); 6947 ret = SendMessageA(radio3, BM_GETCHECK, 0, 0); 6948 ok(ret == BST_CHECKED, "got %08x\n", ret); 6949 6950 GetWindowRect(radio2, &rc); 6951 SetCursorPos(rc.left+1, rc.top+1); 6952 6953 flush_events(); 6954 flush_sequence(); 6955 6956 log_all_parent_messages++; 6957 6958 SendMessageA(radio2, BM_CLICK, 0, 0); 6959 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 6960 ok_sequence(auto_radio_button_BM_CLICK, "BM_CLICK on auto-radio button", FALSE); 6961 6962 log_all_parent_messages--; 6963 6964 ret = SendMessageA(radio1, BM_GETCHECK, 0, 0); 6965 ok(ret == BST_UNCHECKED, "got %08x\n", ret); 6966 ret = SendMessageA(radio2, BM_GETCHECK, 0, 0); 6967 ok(ret == BST_CHECKED, "got %08x\n", ret); 6968 ret = SendMessageA(radio3, BM_GETCHECK, 0, 0); 6969 ok(ret == BST_UNCHECKED, "got %08x\n", ret); 6970 6971 DestroyWindow(parent); 6972 } 6973 6974 #define test_radio(r1, s1, r2, s2, r3, s3) test_radio_dbg(r1, s1, r2, s2, r3, s3, __LINE__) 6975 static void test_radio_dbg(HWND radio1, int state1, HWND radio2, int state2, HWND radio3, int state3, int line) 6976 { 6977 DWORD ret; 6978 6979 ret = SendMessageA(radio1, BM_GETCHECK, 0, 0); 6980 ok_(__FILE__,line)(ret == state1 ? BST_CHECKED : BST_UNCHECKED, "got %08x\n", ret); 6981 ret = SendMessageA(radio2, BM_GETCHECK, 0, 0); 6982 ok_(__FILE__,line)(ret == state2 ? BST_CHECKED : BST_UNCHECKED, "got %08x\n", ret); 6983 ret = SendMessageA(radio3, BM_GETCHECK, 0, 0); 6984 ok_(__FILE__,line)(ret == state3 ? BST_CHECKED : BST_UNCHECKED, "got %08x\n", ret); 6985 } 6986 6987 static void set_radio(HWND radio1, int state1, HWND radio2, int state2, HWND radio3, int state3) 6988 { 6989 SendMessageA(radio1, BM_SETCHECK, state1 ? BST_CHECKED : BST_UNCHECKED, 0); 6990 SendMessageA(radio2, BM_SETCHECK, state2 ? BST_CHECKED : BST_UNCHECKED, 0); 6991 SendMessageA(radio3, BM_SETCHECK, state3 ? BST_CHECKED : BST_UNCHECKED, 0); 6992 } 6993 6994 static void test_autoradio_kbd_move(void) 6995 { 6996 HWND parent, radio1, radio2, radio3, hwnd; 6997 RECT rc; 6998 MSG msg; 6999 DWORD ret; 7000 7001 subclass_button(); 7002 7003 parent = CreateDialogParamA(0, "AUTORADIO_TEST_DIALOG_2", 0, radio_test_dlg_proc, 0); 7004 ok(parent != 0, "failed to create parent window\n"); 7005 7006 radio1 = GetDlgItem(parent, ID_RADIO1); 7007 radio2 = GetDlgItem(parent, ID_RADIO2); 7008 radio3 = GetDlgItem(parent, ID_RADIO3); 7009 7010 flush_events(); 7011 flush_sequence(); 7012 7013 test_radio(radio1, 0, radio2, 0, radio3, 0); 7014 set_radio(radio1, 1, radio2, 1, radio3, 1); 7015 test_radio(radio1, 1, radio2, 1, radio3, 1); 7016 7017 SetFocus(radio3); 7018 7019 flush_events(); 7020 flush_sequence(); 7021 7022 log_all_parent_messages++; 7023 7024 SendMessageA(radio3, WM_KEYDOWN, VK_UP, 0); 7025 SendMessageA(radio3, WM_KEYUP, VK_UP, 0); 7026 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 7027 ok_sequence(auto_radio_button_VK_UP_child, "press/release VK_UP on auto-radio button", FALSE); 7028 7029 test_radio(radio1, 1, radio2, 1, radio3, 1); 7030 7031 flush_events(); 7032 flush_sequence(); 7033 7034 DefDlgProcA(parent, WM_KEYDOWN, VK_UP, 0); 7035 DefDlgProcA(parent, WM_KEYUP, VK_UP, 0); 7036 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 7037 ok_sequence(auto_radio_button_VK_UP_parent, "press/release VK_UP on dialog", FALSE); 7038 7039 test_radio(radio1, 1, radio2, 1, radio3, 1); 7040 7041 SetFocus(radio3); 7042 GetWindowRect(radio3, &rc); 7043 7044 flush_events(); 7045 flush_sequence(); 7046 7047 msg.hwnd = parent; 7048 msg.message = WM_KEYDOWN; 7049 msg.wParam = VK_UP; 7050 msg.lParam = 0; 7051 msg.pt.x = rc.left + 1; 7052 msg.pt.y = rc.top + 1; 7053 ret = IsDialogMessageA(parent, &msg); 7054 ok(ret, "IsDialogMessage should return TRUE\n"); 7055 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 7056 if (0) /* actual message sequence is different on every run in some Windows setups */ 7057 ok_sequence(auto_radio_button_VK_UP_dialog, "IsDialogMessage(VK_UP) #1", FALSE); 7058 /* what really matters is that nothing has changed */ 7059 test_radio(radio1, 1, radio2, 1, radio3, 1); 7060 7061 set_radio(radio1, 0, radio2, 1, radio3, 1); 7062 test_radio(radio1, 0, radio2, 1, radio3, 1); 7063 7064 flush_events(); 7065 flush_sequence(); 7066 7067 ret = IsDialogMessageA(parent, &msg); 7068 ok(ret, "IsDialogMessage should return TRUE\n"); 7069 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 7070 if (0) /* actual message sequence is different on every run in some Windows setups */ 7071 ok_sequence(auto_radio_button_VK_UP_dialog, "IsDialogMessage(VK_UP) #2", FALSE); 7072 /* what really matters is that nothing has changed */ 7073 test_radio(radio1, 0, radio2, 1, radio3, 1); 7074 7075 /* switch from radio3 ro radio1 */ 7076 SetFocus(radio3); 7077 GetWindowRect(radio3, &rc); 7078 7079 flush_events(); 7080 flush_sequence(); 7081 7082 msg.hwnd = parent; 7083 msg.message = WM_KEYDOWN; 7084 msg.wParam = VK_DOWN; 7085 msg.lParam = 0; 7086 msg.pt.x = rc.left + 1; 7087 msg.pt.y = rc.top + 1; 7088 ret = IsDialogMessageA(parent, &msg); 7089 ok(ret, "IsDialogMessage should return TRUE\n"); 7090 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 7091 ok_sequence(auto_radio_button_VK_DOWN_dialog, "IsDialogMessage(VK_DOWN)", TRUE); 7092 7093 test_radio(radio1, 1, radio2, 0, radio3, 0); 7094 7095 hwnd = GetFocus(); 7096 ok(hwnd == radio1, "focus should be on radio1, not on %p\n", hwnd); 7097 GetWindowRect(radio1, &rc); 7098 7099 msg.hwnd = parent; 7100 msg.message = WM_KEYDOWN; 7101 msg.wParam = VK_DOWN; 7102 msg.lParam = 0; 7103 msg.pt.x = rc.left + 1; 7104 msg.pt.y = rc.top + 1; 7105 ret = IsDialogMessageA(parent, &msg); 7106 ok(ret, "IsDialogMessage should return TRUE\n"); 7107 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 7108 ok_sequence(auto_radio_button_VK_DOWN_radio3, "down to radio3", TRUE); 7109 7110 test_radio(radio1, 1, radio2, 0, radio3, 0); 7111 7112 hwnd = GetFocus(); 7113 ok(hwnd == radio1, "focus should be on radio1, not on %p\n", hwnd); 7114 7115 flush_events(); 7116 flush_sequence(); 7117 7118 msg.hwnd = parent; 7119 msg.message = WM_KEYDOWN; 7120 msg.wParam = VK_UP; 7121 msg.lParam = 0; 7122 msg.pt.x = rc.left + 1; 7123 msg.pt.y = rc.top + 1; 7124 ret = IsDialogMessageA(parent, &msg); 7125 ok(ret, "IsDialogMessage should return TRUE\n"); 7126 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 7127 ok_sequence(auto_radio_button_VK_UP_radio1, "up to radio1", TRUE); 7128 7129 test_radio(radio1, 1, radio2, 0, radio3, 0); 7130 7131 hwnd = GetFocus(); 7132 ok(hwnd == radio1, "focus should be on radio1, not on %p\n", hwnd); 7133 7134 flush_events(); 7135 flush_sequence(); 7136 7137 msg.hwnd = parent; 7138 msg.message = WM_KEYDOWN; 7139 msg.wParam = VK_UP; 7140 msg.lParam = 0; 7141 msg.pt.x = rc.left + 1; 7142 msg.pt.y = rc.top + 1; 7143 ret = IsDialogMessageA(parent, &msg); 7144 ok(ret, "IsDialogMessage should return TRUE\n"); 7145 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 7146 if (0) /* actual message sequence is different on every run in some Windows setups */ 7147 ok_sequence(auto_radio_button_VK_UP_dialog, "IsDialogMessage(VK_UP) #3", FALSE); 7148 /* what really matters is that nothing has changed */ 7149 test_radio(radio1, 1, radio2, 0, radio3, 0); 7150 7151 log_all_parent_messages--; 7152 7153 DestroyWindow(parent); 7154 } 7155 7156 /****************** static message test *************************/ 7157 static const struct message WmSetFontStaticSeq2[] = 7158 { 7159 { WM_SETFONT, sent }, 7160 { WM_PAINT, sent|defwinproc|optional }, 7161 { WM_ERASEBKGND, sent|defwinproc|optional }, 7162 { WM_CTLCOLORSTATIC, sent|defwinproc|optional }, 7163 { 0 } 7164 }; 7165 7166 static WNDPROC old_static_proc; 7167 7168 static LRESULT CALLBACK static_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 7169 { 7170 static LONG defwndproc_counter = 0; 7171 LRESULT ret; 7172 struct recvd_message msg; 7173 7174 if (ignore_message( message )) return 0; 7175 7176 msg.hwnd = hwnd; 7177 msg.message = message; 7178 msg.flags = sent|wparam|lparam; 7179 if (defwndproc_counter) msg.flags |= defwinproc; 7180 msg.wParam = wParam; 7181 msg.lParam = lParam; 7182 msg.descr = "static"; 7183 add_message(&msg); 7184 7185 defwndproc_counter++; 7186 ret = CallWindowProcA(old_static_proc, hwnd, message, wParam, lParam); 7187 defwndproc_counter--; 7188 7189 return ret; 7190 } 7191 7192 static void subclass_static(void) 7193 { 7194 WNDCLASSA cls; 7195 7196 if (!GetClassInfoA(0, "static", &cls)) assert(0); 7197 7198 old_static_proc = cls.lpfnWndProc; 7199 7200 cls.hInstance = GetModuleHandleA(NULL); 7201 cls.lpfnWndProc = static_hook_proc; 7202 cls.lpszClassName = "my_static_class"; 7203 UnregisterClassA(cls.lpszClassName, cls.hInstance); 7204 if (!RegisterClassA(&cls)) assert(0); 7205 } 7206 7207 static void test_static_messages(void) 7208 { 7209 /* FIXME: make as comprehensive as the button message test */ 7210 static const struct 7211 { 7212 DWORD style; 7213 DWORD dlg_code; 7214 const struct message *setfont; 7215 } static_ctrl[] = { 7216 { SS_LEFT, DLGC_STATIC, 7217 WmSetFontStaticSeq2 } 7218 }; 7219 unsigned int i; 7220 HWND hwnd; 7221 DWORD dlg_code; 7222 7223 subclass_static(); 7224 7225 for (i = 0; i < ARRAY_SIZE(static_ctrl); i++) 7226 { 7227 hwnd = CreateWindowExA(0, "my_static_class", "test", static_ctrl[i].style | WS_POPUP, 7228 0, 0, 50, 14, 0, 0, 0, NULL); 7229 ok(hwnd != 0, "Failed to create static window\n"); 7230 7231 dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0); 7232 ok(dlg_code == static_ctrl[i].dlg_code, "%u: wrong dlg_code %08x\n", i, dlg_code); 7233 7234 ShowWindow(hwnd, SW_SHOW); 7235 UpdateWindow(hwnd); 7236 SetFocus(0); 7237 flush_sequence(); 7238 7239 trace("static style %08x\n", static_ctrl[i].style); 7240 SendMessageA(hwnd, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), TRUE); 7241 ok_sequence(static_ctrl[i].setfont, "WM_SETFONT on a static", FALSE); 7242 7243 DestroyWindow(hwnd); 7244 } 7245 } 7246 7247 /****************** ComboBox message test *************************/ 7248 #define ID_COMBOBOX 0x000f 7249 7250 static const struct message SetCurSelComboSeq[] = 7251 { 7252 { CB_SETCURSEL, sent|wparam|lparam, 0, 0 }, 7253 { LB_SETCURSEL, sent|wparam|lparam, 0, 0 }, 7254 { LB_SETTOPINDEX, sent|wparam|lparam, 0, 0 }, 7255 { LB_GETCURSEL, sent|wparam|lparam, 0, 0 }, 7256 { LB_GETTEXTLEN, sent|wparam|lparam, 0, 0 }, 7257 { LB_GETTEXTLEN, sent|wparam|lparam|optional, 0, 0 }, /* TODO: it's sent on all Windows versions */ 7258 { LB_GETTEXT, sent|wparam, 0 }, 7259 { WM_CTLCOLOREDIT, sent|parent }, 7260 { LB_GETITEMDATA, sent|wparam|lparam, 0, 0 }, 7261 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_COMBOBOX, 0x100010f3 }, 7262 { 0 } 7263 }; 7264 7265 static const struct message SetCurSelComboSeq2[] = 7266 { 7267 { CB_SETCURSEL, sent|wparam|lparam, 0, 0 }, 7268 { LB_SETCURSEL, sent|wparam|lparam, 0, 0 }, 7269 { LB_SETTOPINDEX, sent|wparam|lparam, 0, 0 }, 7270 { LB_GETCURSEL, sent|wparam|lparam, 0, 0 }, 7271 { LB_GETTEXTLEN, sent|wparam|lparam, 0, 0 }, 7272 { LB_GETTEXTLEN, sent|wparam|lparam|optional, 0, 0 }, /* TODO: it's sent on all Windows versions */ 7273 { LB_GETTEXT, sent|wparam, 0 }, 7274 { 0 } 7275 }; 7276 7277 static const struct message SetCurSelComboSeq_edit[] = 7278 { 7279 { CB_SETCURSEL, sent|wparam|lparam, 0, 0 }, 7280 { WM_SETTEXT, sent|wparam, 0 }, 7281 { EM_SETSEL, sent|wparam|lparam, 0, INT_MAX }, 7282 { 0 } 7283 }; 7284 7285 static const struct message WmKeyDownComboSeq[] = 7286 { 7287 { WM_KEYDOWN, sent|wparam|lparam, VK_DOWN, 0 }, 7288 { WM_COMMAND, sent|wparam|defwinproc, MAKEWPARAM(1000, LBN_SELCHANGE) }, 7289 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_COMBOBOX, CBN_SELENDOK) }, 7290 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_COMBOBOX, CBN_SELCHANGE) }, 7291 { WM_CTLCOLOREDIT, sent|parent }, 7292 { WM_KEYUP, sent|wparam|lparam, VK_DOWN, 0 }, 7293 { 0 } 7294 }; 7295 7296 static const struct message WmSetPosComboSeq[] = 7297 { 7298 { WM_WINDOWPOSCHANGING, sent }, 7299 { WM_NCCALCSIZE, sent|wparam, TRUE }, 7300 { WM_CHILDACTIVATE, sent }, 7301 { WM_WINDOWPOSCHANGED, sent }, 7302 { WM_MOVE, sent|defwinproc }, 7303 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 7304 { WM_WINDOWPOSCHANGING, sent|defwinproc }, 7305 { WM_NCCALCSIZE, sent|defwinproc|wparam, TRUE }, 7306 { WM_WINDOWPOSCHANGED, sent|defwinproc }, 7307 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 7308 { 0 } 7309 }; 7310 7311 static const struct message WMSetFocusComboBoxSeq[] = 7312 { 7313 { WM_SETFOCUS, sent }, 7314 { WM_KILLFOCUS, sent|parent }, 7315 { WM_SETFOCUS, sent }, 7316 { WM_COMMAND, sent|defwinproc|wparam, MAKEWPARAM(1001, EN_SETFOCUS) }, 7317 { EM_SETSEL, sent|defwinproc|wparam|lparam, 0, INT_MAX }, 7318 { WM_CTLCOLOREDIT, sent|defwinproc|optional },/* Not sent on W2000, XP or Server 2003 */ 7319 { WM_CTLCOLOREDIT, sent|parent|optional },/* Not sent on W2000, XP or Server 2003 */ 7320 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_COMBOBOX, CBN_SETFOCUS) }, 7321 { 0 } 7322 }; 7323 7324 static const struct message SetFocusButtonSeq[] = 7325 { 7326 { WM_KILLFOCUS, sent }, 7327 { CB_GETCOMBOBOXINFO, sent|optional },/* Windows 2000 */ 7328 { 0x0167, sent|optional },/* Undocumented message. Sent on all versions except Windows 2000 */ 7329 { WM_LBUTTONUP, sent|defwinproc }, 7330 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_COMBOBOX, CBN_SELENDCANCEL) }, 7331 { EM_SETSEL, sent|defwinproc|wparam|lparam, 0, 0 }, 7332 { WM_CTLCOLOREDIT, sent|defwinproc|optional },/* Not sent on W2000, XP or Server 2003 */ 7333 { WM_CTLCOLOREDIT, sent|parent|optional },/* Not sent on W2000, XP or Server 2003 */ 7334 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_COMBOBOX, CBN_KILLFOCUS) }, 7335 { WM_CTLCOLORBTN, sent|parent }, 7336 { 0 } 7337 }; 7338 7339 static const struct message SetFocusComboBoxSeq[] = 7340 { 7341 { WM_CTLCOLORBTN, sent|parent }, 7342 { WM_SETFOCUS, sent }, 7343 { WM_KILLFOCUS, sent|defwinproc }, 7344 { WM_SETFOCUS, sent }, 7345 { WM_COMMAND, sent|defwinproc|wparam, MAKEWPARAM(1001, EN_SETFOCUS) }, 7346 { EM_SETSEL, sent|defwinproc|wparam|lparam, 0, INT_MAX }, 7347 { WM_CTLCOLOREDIT, sent|defwinproc|optional },/* Not sent on W2000, XP or Server 2003 */ 7348 { WM_CTLCOLOREDIT, sent|parent|optional },/* Not sent on W2000, XP or Server 2003 */ 7349 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_COMBOBOX, CBN_SETFOCUS) }, 7350 { 0 } 7351 }; 7352 7353 static const struct message SetFocusButtonSeq2[] = 7354 { 7355 { WM_KILLFOCUS, sent }, 7356 { CB_GETCOMBOBOXINFO, sent|optional },/* Windows 2000 */ 7357 { 0x0167, sent|optional },/* Undocumented message. Sent on all versions except Windows 2000 */ 7358 { WM_LBUTTONUP, sent|defwinproc }, 7359 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_COMBOBOX, CBN_SELENDCANCEL) }, 7360 { EM_SETSEL, sent|defwinproc|wparam|lparam, 0, 0 }, 7361 { WM_CTLCOLOREDIT, sent|defwinproc }, 7362 { WM_CTLCOLOREDIT, sent|parent }, 7363 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_COMBOBOX, CBN_KILLFOCUS) }, 7364 { WM_CTLCOLORBTN, sent|parent }, 7365 { 0 } 7366 }; 7367 7368 static WNDPROC old_combobox_proc, edit_window_proc, lbox_window_proc; 7369 7370 static LRESULT CALLBACK combobox_edit_subclass_proc(HWND hwnd, UINT message, 7371 WPARAM wParam, LPARAM lParam) 7372 { 7373 static LONG defwndproc_counter = 0; 7374 LRESULT ret; 7375 struct recvd_message msg; 7376 7377 /* do not log painting messages */ 7378 if (message != WM_PAINT && 7379 message != WM_NCPAINT && 7380 message != WM_SYNCPAINT && 7381 message != WM_ERASEBKGND && 7382 message != WM_NCHITTEST && 7383 message != WM_GETTEXT && 7384 !ignore_message( message )) 7385 { 7386 msg.hwnd = hwnd; 7387 msg.message = message; 7388 msg.flags = sent|wparam|lparam; 7389 if (defwndproc_counter) msg.flags |= defwinproc; 7390 msg.wParam = wParam; 7391 msg.lParam = lParam; 7392 msg.descr = "combo edit"; 7393 add_message(&msg); 7394 } 7395 7396 defwndproc_counter++; 7397 ret = CallWindowProcA(edit_window_proc, hwnd, message, wParam, lParam); 7398 defwndproc_counter--; 7399 7400 return ret; 7401 } 7402 7403 static LRESULT CALLBACK combobox_lbox_subclass_proc(HWND hwnd, UINT message, 7404 WPARAM wParam, LPARAM lParam) 7405 { 7406 static LONG defwndproc_counter = 0; 7407 LRESULT ret; 7408 struct recvd_message msg; 7409 7410 /* do not log painting messages */ 7411 if (message != WM_PAINT && 7412 message != WM_NCPAINT && 7413 message != WM_SYNCPAINT && 7414 message != WM_ERASEBKGND && 7415 message != WM_NCHITTEST && 7416 !ignore_message( message )) 7417 { 7418 msg.hwnd = hwnd; 7419 msg.message = message; 7420 msg.flags = sent|wparam|lparam; 7421 if (defwndproc_counter) msg.flags |= defwinproc; 7422 msg.wParam = wParam; 7423 msg.lParam = lParam; 7424 msg.descr = "combo lbox"; 7425 add_message(&msg); 7426 } 7427 7428 defwndproc_counter++; 7429 ret = CallWindowProcA(lbox_window_proc, hwnd, message, wParam, lParam); 7430 defwndproc_counter--; 7431 7432 return ret; 7433 } 7434 7435 static LRESULT CALLBACK combobox_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 7436 { 7437 static LONG defwndproc_counter = 0; 7438 LRESULT ret; 7439 struct recvd_message msg; 7440 7441 /* do not log painting messages */ 7442 if (message != WM_PAINT && 7443 message != WM_NCPAINT && 7444 message != WM_SYNCPAINT && 7445 message != WM_ERASEBKGND && 7446 message != WM_NCHITTEST && 7447 message != WM_GETTEXT && 7448 !ignore_message( message )) 7449 { 7450 msg.hwnd = hwnd; 7451 msg.message = message; 7452 msg.flags = sent|wparam|lparam; 7453 if (defwndproc_counter) msg.flags |= defwinproc; 7454 msg.wParam = wParam; 7455 msg.lParam = lParam; 7456 msg.descr = "combo"; 7457 add_message(&msg); 7458 } 7459 7460 defwndproc_counter++; 7461 ret = CallWindowProcA(old_combobox_proc, hwnd, message, wParam, lParam); 7462 defwndproc_counter--; 7463 7464 return ret; 7465 } 7466 7467 static void subclass_combobox(void) 7468 { 7469 WNDCLASSA cls; 7470 7471 if (!GetClassInfoA(0, "ComboBox", &cls)) assert(0); 7472 7473 old_combobox_proc = cls.lpfnWndProc; 7474 7475 cls.hInstance = GetModuleHandleA(NULL); 7476 cls.lpfnWndProc = combobox_hook_proc; 7477 cls.lpszClassName = "my_combobox_class"; 7478 UnregisterClassA(cls.lpszClassName, cls.hInstance); 7479 if (!RegisterClassA(&cls)) assert(0); 7480 } 7481 7482 static void test_combobox_messages(void) 7483 { 7484 HWND parent, combo, button, edit, lbox; 7485 LRESULT ret; 7486 COMBOBOXINFO cbInfo; 7487 BOOL res; 7488 7489 subclass_combobox(); 7490 7491 parent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 7492 100, 100, 200, 200, 0, 0, 0, NULL); 7493 ok(parent != 0, "Failed to create parent window\n"); 7494 flush_sequence(); 7495 7496 combo = CreateWindowExA(0, "my_combobox_class", "test", WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | CBS_HASSTRINGS, 7497 0, 0, 100, 150, parent, (HMENU)ID_COMBOBOX, 0, NULL); 7498 ok(combo != 0, "Failed to create combobox window\n"); 7499 7500 UpdateWindow(combo); 7501 7502 ret = SendMessageA(combo, WM_GETDLGCODE, 0, 0); 7503 ok(ret == (DLGC_WANTCHARS | DLGC_WANTARROWS), "wrong dlg_code %08lx\n", ret); 7504 7505 ret = SendMessageA(combo, CB_ADDSTRING, 0, (LPARAM)"item 0"); 7506 ok(ret == 0, "expected 0, got %ld\n", ret); 7507 ret = SendMessageA(combo, CB_ADDSTRING, 0, (LPARAM)"item 1"); 7508 ok(ret == 1, "expected 1, got %ld\n", ret); 7509 ret = SendMessageA(combo, CB_ADDSTRING, 0, (LPARAM)"item 2"); 7510 ok(ret == 2, "expected 2, got %ld\n", ret); 7511 7512 SendMessageA(combo, CB_SETCURSEL, 0, 0); 7513 SetFocus(combo); 7514 flush_sequence(); 7515 7516 log_all_parent_messages++; 7517 SendMessageA(combo, WM_KEYDOWN, VK_DOWN, 0); 7518 SendMessageA(combo, WM_KEYUP, VK_DOWN, 0); 7519 log_all_parent_messages--; 7520 ok_sequence(WmKeyDownComboSeq, "WM_KEYDOWN/VK_DOWN on a ComboBox", FALSE); 7521 7522 flush_sequence(); 7523 SetWindowPos(combo, 0, 10, 10, 120, 130, SWP_NOZORDER); 7524 ok_sequence(WmSetPosComboSeq, "repositioning messages on a ComboBox", FALSE); 7525 7526 DestroyWindow(combo); 7527 DestroyWindow(parent); 7528 7529 /* Start again. Test combobox text selection when getting and losing focus */ 7530 parent = CreateWindowExA(0, "TestParentClass", "Parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 7531 10, 10, 300, 300, NULL, NULL, NULL, NULL); 7532 ok(parent != 0, "Failed to create parent window\n"); 7533 7534 combo = CreateWindowExA(0, "my_combobox_class", "test", WS_CHILD | WS_VISIBLE | CBS_DROPDOWN, 7535 5, 5, 100, 100, parent, (HMENU)ID_COMBOBOX, NULL, NULL); 7536 ok(combo != 0, "Failed to create combobox window\n"); 7537 7538 cbInfo.cbSize = sizeof(COMBOBOXINFO); 7539 SetLastError(0xdeadbeef); 7540 res = GetComboBoxInfo(combo, &cbInfo); 7541 ok(res, "Failed to get COMBOBOXINFO structure; LastError: %u\n", GetLastError()); 7542 edit = cbInfo.hwndItem; 7543 7544 edit_window_proc = (WNDPROC)SetWindowLongPtrA(edit, GWLP_WNDPROC, 7545 (ULONG_PTR)combobox_edit_subclass_proc); 7546 7547 button = CreateWindowExA(0, "Button", "OK", WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 7548 5, 50, 100, 20, parent, NULL, 7549 (HINSTANCE)GetWindowLongPtrA(parent, GWLP_HINSTANCE), NULL); 7550 ok(button != 0, "Failed to create button window\n"); 7551 7552 flush_sequence(); 7553 log_all_parent_messages++; 7554 SendMessageA(combo, WM_SETFOCUS, 0, (LPARAM)edit); 7555 log_all_parent_messages--; 7556 ok_sequence(WMSetFocusComboBoxSeq, "WM_SETFOCUS on a ComboBox", TRUE); 7557 7558 flush_sequence(); 7559 log_all_parent_messages++; 7560 SetFocus(button); 7561 log_all_parent_messages--; 7562 ok_sequence(SetFocusButtonSeq, "SetFocus on a Button", TRUE); 7563 7564 SendMessageA(combo, WM_SETTEXT, 0, (LPARAM)"Wine Test"); 7565 7566 flush_sequence(); 7567 log_all_parent_messages++; 7568 SetFocus(combo); 7569 log_all_parent_messages--; 7570 ok_sequence(SetFocusComboBoxSeq, "SetFocus on a ComboBox", TRUE); 7571 7572 flush_sequence(); 7573 log_all_parent_messages++; 7574 SetFocus(button); 7575 log_all_parent_messages--; 7576 ok_sequence(SetFocusButtonSeq2, "SetFocus on a Button (2)", TRUE); 7577 7578 SetFocus(combo); 7579 SendMessageA(combo, WM_SETREDRAW, FALSE, 0); 7580 flush_sequence(); 7581 log_all_parent_messages++; 7582 SendMessageA(combo, CB_SETCURSEL, 0, 0); 7583 log_all_parent_messages--; 7584 ok_sequence(SetCurSelComboSeq_edit, "CB_SETCURSEL on a ComboBox with edit control", FALSE); 7585 7586 DestroyWindow(button); 7587 DestroyWindow(combo); 7588 7589 combo = CreateWindowExA(0, "my_combobox_class", "test", 7590 WS_CHILD | WS_VISIBLE | CBS_OWNERDRAWFIXED | CBS_DROPDOWNLIST, 7591 5, 5, 100, 100, parent, (HMENU)ID_COMBOBOX, NULL, NULL); 7592 ok(combo != 0, "Failed to create combobox window\n"); 7593 7594 ret = SendMessageA(combo, CB_ADDSTRING, 0, (LPARAM)"item 0"); 7595 ok(ret == 0, "expected 0, got %ld\n", ret); 7596 7597 cbInfo.cbSize = sizeof(COMBOBOXINFO); 7598 SetLastError(0xdeadbeef); 7599 res = GetComboBoxInfo(combo, &cbInfo); 7600 ok(res, "Failed to get COMBOBOXINFO structure; LastError: %u\n", GetLastError()); 7601 lbox = cbInfo.hwndList; 7602 lbox_window_proc = (WNDPROC)SetWindowLongPtrA(lbox, GWLP_WNDPROC, 7603 (ULONG_PTR)combobox_lbox_subclass_proc); 7604 flush_sequence(); 7605 7606 log_all_parent_messages++; 7607 SendMessageA(combo, CB_SETCURSEL, 0, 0); 7608 log_all_parent_messages--; 7609 ok_sequence(SetCurSelComboSeq, "CB_SETCURSEL on a ComboBox", FALSE); 7610 7611 ShowWindow(combo, SW_HIDE); 7612 flush_sequence(); 7613 log_all_parent_messages++; 7614 SendMessageA(combo, CB_SETCURSEL, 0, 0); 7615 log_all_parent_messages--; 7616 ok_sequence(SetCurSelComboSeq2, "CB_SETCURSEL on a ComboBox", FALSE); 7617 7618 DestroyWindow(combo); 7619 DestroyWindow(parent); 7620 } 7621 7622 /****************** WM_IME_KEYDOWN message test *******************/ 7623 7624 static const struct message WmImeKeydownMsgSeq_0[] = 7625 { 7626 { WM_IME_KEYDOWN, wparam, VK_RETURN }, 7627 { WM_CHAR, wparam, 'A' }, 7628 { 0 } 7629 }; 7630 7631 static const struct message WmImeKeydownMsgSeq_1[] = 7632 { 7633 { WM_KEYDOWN, optional|wparam, VK_RETURN }, 7634 { WM_CHAR, optional|wparam, VK_RETURN }, 7635 { 0 } 7636 }; 7637 7638 static LRESULT WINAPI wmime_keydown_procA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 7639 { 7640 struct recvd_message msg; 7641 7642 msg.hwnd = hwnd; 7643 msg.message = message; 7644 msg.flags = wparam|lparam; 7645 msg.wParam = wParam; 7646 msg.lParam = lParam; 7647 msg.descr = "wmime_keydown"; 7648 add_message(&msg); 7649 7650 return DefWindowProcA(hwnd, message, wParam, lParam); 7651 } 7652 7653 static void register_wmime_keydown_class(void) 7654 { 7655 WNDCLASSA cls; 7656 7657 ZeroMemory(&cls, sizeof(WNDCLASSA)); 7658 cls.lpfnWndProc = wmime_keydown_procA; 7659 cls.hInstance = GetModuleHandleA(0); 7660 cls.lpszClassName = "wmime_keydown_class"; 7661 if (!RegisterClassA(&cls)) assert(0); 7662 } 7663 7664 static void test_wmime_keydown_message(void) 7665 { 7666 HWND hwnd; 7667 MSG msg; 7668 7669 trace("Message sequences by WM_IME_KEYDOWN\n"); 7670 7671 register_wmime_keydown_class(); 7672 hwnd = CreateWindowExA(0, "wmime_keydown_class", NULL, WS_OVERLAPPEDWINDOW, 7673 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0, 7674 NULL, NULL, 0); 7675 flush_events(); 7676 flush_sequence(); 7677 7678 SendMessageA(hwnd, WM_IME_KEYDOWN, VK_RETURN, 0x1c0001); 7679 SendMessageA(hwnd, WM_CHAR, 'A', 1); 7680 ok_sequence(WmImeKeydownMsgSeq_0, "WM_IME_KEYDOWN 0", FALSE); 7681 7682 while ( PeekMessageA(&msg, 0, 0, 0, PM_REMOVE) ) 7683 { 7684 TranslateMessage(&msg); 7685 DispatchMessageA(&msg); 7686 } 7687 ok_sequence(WmImeKeydownMsgSeq_1, "WM_IME_KEYDOWN 1", FALSE); 7688 7689 DestroyWindow(hwnd); 7690 } 7691 7692 /************* painting message test ********************/ 7693 7694 void dump_region(HRGN hrgn) 7695 { 7696 DWORD i, size; 7697 RGNDATA *data = NULL; 7698 RECT *rect; 7699 7700 if (!hrgn) 7701 { 7702 printf( "null region\n" ); 7703 return; 7704 } 7705 if (!(size = GetRegionData( hrgn, 0, NULL ))) return; 7706 if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return; 7707 GetRegionData( hrgn, size, data ); 7708 printf("%d rects:", data->rdh.nCount ); 7709 for (i = 0, rect = (RECT *)data->Buffer; i < data->rdh.nCount; i++, rect++) 7710 printf( " %s", wine_dbgstr_rect( rect )); 7711 printf("\n"); 7712 HeapFree( GetProcessHeap(), 0, data ); 7713 } 7714 7715 #define check_update_rgn( hwnd, hrgn ) check_update_rgn_( __LINE__, hwnd, hrgn ) 7716 static void check_update_rgn_( int line, HWND hwnd, HRGN hrgn ) 7717 { 7718 INT ret; 7719 RECT r1, r2; 7720 HRGN tmp = CreateRectRgn( 0, 0, 0, 0 ); 7721 HRGN update = CreateRectRgn( 0, 0, 0, 0 ); 7722 7723 ret = GetUpdateRgn( hwnd, update, FALSE ); 7724 ok( ret != ERROR, "GetUpdateRgn failed\n" ); 7725 if (ret == NULLREGION) 7726 { 7727 ok_(__FILE__,line)( !hrgn, "Update region shouldn't be empty\n" ); 7728 } 7729 else 7730 { 7731 if (CombineRgn( tmp, hrgn, update, RGN_XOR ) != NULLREGION) 7732 { 7733 ok_(__FILE__,line)( 0, "Regions are different\n" ); 7734 if (winetest_debug > 0) 7735 { 7736 printf( "Update region: " ); 7737 dump_region( update ); 7738 printf( "Wanted region: " ); 7739 dump_region( hrgn ); 7740 } 7741 } 7742 } 7743 GetRgnBox( update, &r1 ); 7744 GetUpdateRect( hwnd, &r2, FALSE ); 7745 ok_(__FILE__,line)( EqualRect( &r1, &r2 ), "Rectangles are different: %s / %s\n", 7746 wine_dbgstr_rect( &r1 ), wine_dbgstr_rect( &r2 )); 7747 7748 DeleteObject( tmp ); 7749 DeleteObject( update ); 7750 } 7751 7752 static const struct message WmInvalidateRgn[] = { 7753 { WM_NCPAINT, sent }, 7754 { WM_GETTEXT, sent|defwinproc|optional }, 7755 { 0 } 7756 }; 7757 7758 static const struct message WmGetUpdateRect[] = { 7759 { WM_NCPAINT, sent }, 7760 { WM_GETTEXT, sent|defwinproc|optional }, 7761 { WM_PAINT, sent }, 7762 { 0 } 7763 }; 7764 7765 static const struct message WmInvalidateFull[] = { 7766 { WM_NCPAINT, sent|wparam, 1 }, 7767 { WM_GETTEXT, sent|defwinproc|optional }, 7768 { 0 } 7769 }; 7770 7771 static const struct message WmInvalidateErase[] = { 7772 { WM_NCPAINT, sent|wparam, 1 }, 7773 { WM_GETTEXT, sent|defwinproc|optional }, 7774 { WM_ERASEBKGND, sent }, 7775 { 0 } 7776 }; 7777 7778 static const struct message WmInvalidatePaint[] = { 7779 { WM_PAINT, sent }, 7780 { WM_NCPAINT, sent|wparam|beginpaint, 1 }, 7781 { WM_GETTEXT, sent|beginpaint|defwinproc|optional }, 7782 { 0 } 7783 }; 7784 7785 static const struct message WmInvalidateErasePaint[] = { 7786 { WM_PAINT, sent }, 7787 { WM_NCPAINT, sent|wparam|beginpaint, 1 }, 7788 { WM_GETTEXT, sent|beginpaint|defwinproc|optional }, 7789 { WM_ERASEBKGND, sent|beginpaint|optional }, 7790 { 0 } 7791 }; 7792 7793 static const struct message WmInvalidateErasePaint2[] = { 7794 { WM_PAINT, sent }, 7795 { WM_NCPAINT, sent|beginpaint }, 7796 { WM_GETTEXT, sent|beginpaint|defwinproc|optional }, 7797 { WM_ERASEBKGND, sent|beginpaint|optional }, 7798 { 0 } 7799 }; 7800 7801 static const struct message WmErase[] = { 7802 { WM_ERASEBKGND, sent }, 7803 { 0 } 7804 }; 7805 7806 static const struct message WmPaint[] = { 7807 { WM_PAINT, sent }, 7808 { 0 } 7809 }; 7810 7811 static const struct message WmParentOnlyPaint[] = { 7812 { WM_PAINT, sent|parent }, 7813 { 0 } 7814 }; 7815 7816 static const struct message WmInvalidateParent[] = { 7817 { WM_NCPAINT, sent|parent }, 7818 { WM_GETTEXT, sent|defwinproc|parent|optional }, 7819 { WM_ERASEBKGND, sent|parent }, 7820 { 0 } 7821 }; 7822 7823 static const struct message WmInvalidateParentChild[] = { 7824 { WM_NCPAINT, sent|parent }, 7825 { WM_GETTEXT, sent|defwinproc|parent|optional }, 7826 { WM_ERASEBKGND, sent|parent }, 7827 { WM_NCPAINT, sent }, 7828 { WM_GETTEXT, sent|defwinproc|optional }, 7829 { WM_ERASEBKGND, sent }, 7830 { 0 } 7831 }; 7832 7833 static const struct message WmInvalidateParentChild2[] = { 7834 { WM_ERASEBKGND, sent|parent }, 7835 { WM_NCPAINT, sent }, 7836 { WM_GETTEXT, sent|defwinproc|optional }, 7837 { WM_ERASEBKGND, sent }, 7838 { 0 } 7839 }; 7840 7841 static const struct message WmParentPaint[] = { 7842 { WM_PAINT, sent|parent }, 7843 { WM_PAINT, sent }, 7844 { 0 } 7845 }; 7846 7847 static const struct message WmParentPaintNc[] = { 7848 { WM_PAINT, sent|parent }, 7849 { WM_PAINT, sent }, 7850 { WM_NCPAINT, sent|beginpaint }, 7851 { WM_GETTEXT, sent|beginpaint|defwinproc|optional }, 7852 { WM_ERASEBKGND, sent|beginpaint|optional }, 7853 { 0 } 7854 }; 7855 7856 static const struct message WmChildPaintNc[] = { 7857 { WM_PAINT, sent }, 7858 { WM_NCPAINT, sent|beginpaint }, 7859 { WM_GETTEXT, sent|beginpaint|defwinproc|optional }, 7860 { WM_ERASEBKGND, sent|beginpaint|optional }, 7861 { 0 } 7862 }; 7863 7864 static const struct message WmParentErasePaint[] = { 7865 { WM_PAINT, sent|parent }, 7866 { WM_NCPAINT, sent|parent|beginpaint }, 7867 { WM_GETTEXT, sent|parent|beginpaint|defwinproc|optional }, 7868 { WM_ERASEBKGND, sent|parent|beginpaint|optional }, 7869 { WM_PAINT, sent }, 7870 { WM_NCPAINT, sent|beginpaint }, 7871 { WM_GETTEXT, sent|beginpaint|defwinproc|optional }, 7872 { WM_ERASEBKGND, sent|beginpaint|optional }, 7873 { 0 } 7874 }; 7875 7876 static const struct message WmParentOnlyNcPaint[] = { 7877 { WM_PAINT, sent|parent }, 7878 { WM_NCPAINT, sent|parent|beginpaint }, 7879 { WM_GETTEXT, sent|parent|beginpaint|defwinproc|optional }, 7880 { 0 } 7881 }; 7882 7883 static const struct message WmSetParentStyle[] = { 7884 { WM_STYLECHANGING, sent|parent }, 7885 { WM_STYLECHANGED, sent|parent }, 7886 { 0 } 7887 }; 7888 7889 static void test_paint_messages(void) 7890 { 7891 BOOL ret; 7892 RECT rect, rect2; 7893 POINT pt; 7894 MSG msg; 7895 HWND hparent, hchild; 7896 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 ); 7897 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 ); 7898 HWND hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW, 7899 100, 100, 200, 200, 0, 0, 0, NULL); 7900 ok (hwnd != 0, "Failed to create overlapped window\n"); 7901 7902 ShowWindow( hwnd, SW_SHOW ); 7903 UpdateWindow( hwnd ); 7904 flush_events(); 7905 flush_sequence(); 7906 7907 check_update_rgn( hwnd, 0 ); 7908 SetRectRgn( hrgn, 10, 10, 20, 20 ); 7909 ret = RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE ); 7910 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret); 7911 check_update_rgn( hwnd, hrgn ); 7912 SetRectRgn( hrgn2, 20, 20, 30, 30 ); 7913 ret = RedrawWindow( hwnd, NULL, hrgn2, RDW_INVALIDATE ); 7914 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret); 7915 CombineRgn( hrgn, hrgn, hrgn2, RGN_OR ); 7916 check_update_rgn( hwnd, hrgn ); 7917 /* validate everything */ 7918 ret = RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE ); 7919 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret); 7920 check_update_rgn( hwnd, 0 ); 7921 7922 /* test empty region */ 7923 SetRectRgn( hrgn, 10, 10, 10, 15 ); 7924 ret = RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE ); 7925 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret); 7926 check_update_rgn( hwnd, 0 ); 7927 /* test empty rect */ 7928 SetRect( &rect, 10, 10, 10, 15 ); 7929 ret = RedrawWindow( hwnd, &rect, NULL, RDW_INVALIDATE ); 7930 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret); 7931 check_update_rgn( hwnd, 0 ); 7932 7933 /* flush pending messages */ 7934 flush_events(); 7935 flush_sequence(); 7936 7937 GetClientRect( hwnd, &rect ); 7938 SetRectRgn( hrgn, 0, 0, rect.right - rect.left, rect.bottom - rect.top ); 7939 /* MSDN: if hwnd parameter is NULL, InvalidateRect invalidates and redraws 7940 * all windows and sends WM_ERASEBKGND and WM_NCPAINT. 7941 */ 7942 SetRectEmpty( &rect ); 7943 ok(InvalidateRect(0, &rect, FALSE), "InvalidateRect(0, &rc, FALSE) failed\n"); 7944 check_update_rgn( hwnd, hrgn ); 7945 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE ); 7946 flush_events(); 7947 ok_sequence( WmPaint, "Paint", FALSE ); 7948 RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE ); 7949 check_update_rgn( hwnd, 0 ); 7950 7951 SetRectEmpty( &rect ); 7952 ok(RedrawWindow(0, &rect, 0, RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW ), 7953 "RedrawWindow failed\n"); 7954 check_update_rgn( hwnd, 0 ); 7955 7956 SetRectEmpty( &rect ); 7957 ok(RedrawWindow(0, &rect, 0, RDW_ALLCHILDREN | RDW_VALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW ), 7958 "RedrawWindow failed\n"); 7959 check_update_rgn( hwnd, 0 ); 7960 7961 GetWindowRect( hwnd, &rect ); 7962 ok(RedrawWindow(0, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW ), 7963 "RedrawWindow failed\n"); 7964 check_update_rgn( hwnd, 0 ); 7965 7966 flush_events(); 7967 ok(RedrawWindow(0, &rect, 0, RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW ), 7968 "RedrawWindow failed\n"); 7969 check_update_rgn( hwnd, hrgn ); 7970 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE ); 7971 flush_events(); 7972 ok_sequence( WmPaint, "Paint", FALSE ); 7973 RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE ); 7974 check_update_rgn( hwnd, 0 ); 7975 7976 ok(RedrawWindow(GetDesktopWindow(), &rect, 0, 7977 RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW ), 7978 "RedrawWindow failed\n"); 7979 ret = GetUpdateRgn( hwnd, hrgn2, FALSE ); 7980 ok( ret == NULLREGION || broken(ret == SIMPLEREGION), /* <= win7 */ 7981 "region should be null (%d)\n", ret ); 7982 if (ret == SIMPLEREGION) ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE ); 7983 RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE ); 7984 flush_events(); 7985 7986 ok(RedrawWindow(GetDesktopWindow(), NULL, 0, 7987 RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW ), 7988 "RedrawWindow failed\n"); 7989 ret = GetUpdateRgn( hwnd, hrgn2, FALSE ); 7990 ok( ret == NULLREGION || broken(ret == SIMPLEREGION), /* <= win7 */ 7991 "region should be null (%d)\n", ret ); 7992 if (ret == SIMPLEREGION) ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE ); 7993 RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE ); 7994 flush_events(); 7995 7996 SetRectRgn( hrgn2, rect.left, rect.top, rect.right, rect.bottom ); 7997 ok(RedrawWindow(0, NULL, hrgn2, RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW ), 7998 "RedrawWindow failed\n"); 7999 check_update_rgn( hwnd, hrgn ); 8000 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE ); 8001 flush_events(); 8002 ok_sequence( WmPaint, "Paint", FALSE ); 8003 RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE ); 8004 check_update_rgn( hwnd, 0 ); 8005 8006 ok(RedrawWindow(0, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW ), 8007 "RedrawWindow failed\n"); 8008 check_update_rgn( hwnd, 0 ); 8009 8010 ok(RedrawWindow(0, NULL, 0, RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW ), 8011 "RedrawWindow failed\n"); 8012 check_update_rgn( hwnd, hrgn ); 8013 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE ); 8014 flush_events(); 8015 ok_sequence( WmPaint, "Paint", FALSE ); 8016 RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE ); 8017 check_update_rgn( hwnd, 0 ); 8018 8019 /* MSDN: if hwnd parameter is NULL, ValidateRect invalidates and redraws 8020 * all windows and sends WM_ERASEBKGND and WM_NCPAINT. 8021 */ 8022 SetRectEmpty( &rect ); 8023 if (ValidateRect(0, &rect) && /* not supported on Win9x */ 8024 GetUpdateRect(hwnd, NULL, FALSE)) /* or >= Win 8 */ 8025 { 8026 check_update_rgn( hwnd, hrgn ); 8027 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE ); 8028 flush_events(); 8029 ok_sequence( WmPaint, "Paint", FALSE ); 8030 RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE ); 8031 check_update_rgn( hwnd, 0 ); 8032 } 8033 8034 SetLastError(0xdeadbeef); 8035 ok(!InvalidateRgn(0, NULL, FALSE), "InvalidateRgn(0, NULL, FALSE) should fail\n"); 8036 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || GetLastError() == 0xdeadbeef, 8037 "wrong error code %d\n", GetLastError()); 8038 check_update_rgn( hwnd, 0 ); 8039 flush_events(); 8040 ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE ); 8041 8042 SetLastError(0xdeadbeef); 8043 ok(!ValidateRgn(0, NULL), "ValidateRgn(0, NULL) should fail\n"); 8044 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || 8045 broken( GetLastError() == 0xdeadbeef ) /* win9x */, 8046 "wrong error code %d\n", GetLastError()); 8047 check_update_rgn( hwnd, 0 ); 8048 flush_events(); 8049 ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE ); 8050 8051 SetLastError(0xdeadbeef); 8052 ok(!UpdateWindow(NULL), "UpdateWindow(NULL) should fail\n"); 8053 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || 8054 broken( GetLastError() == 0xdeadbeef ) /* win9x */, 8055 "wrong error code %d\n", GetLastError()); 8056 check_update_rgn( hwnd, 0 ); 8057 flush_events(); 8058 ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE ); 8059 8060 /* now with frame */ 8061 SetRectRgn( hrgn, -5, -5, 20, 20 ); 8062 8063 /* flush pending messages */ 8064 flush_events(); 8065 flush_sequence(); 8066 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME ); 8067 ok_sequence( WmEmptySeq, "EmptySeq", FALSE ); 8068 8069 SetRectRgn( hrgn, 0, 0, 20, 20 ); /* GetUpdateRgn clips to client area */ 8070 check_update_rgn( hwnd, hrgn ); 8071 8072 flush_sequence(); 8073 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW ); 8074 ok_sequence( WmInvalidateRgn, "InvalidateRgn", FALSE ); 8075 8076 flush_sequence(); 8077 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW ); 8078 ok_sequence( WmInvalidateFull, "InvalidateFull", FALSE ); 8079 8080 GetClientRect( hwnd, &rect ); 8081 SetRectRgn( hrgn, rect.left, rect.top, rect.right, rect.bottom ); 8082 check_update_rgn( hwnd, hrgn ); 8083 8084 flush_sequence(); 8085 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW ); 8086 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE ); 8087 8088 flush_sequence(); 8089 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW | RDW_UPDATENOW ); 8090 ok_sequence( WmInvalidatePaint, "InvalidatePaint", FALSE ); 8091 check_update_rgn( hwnd, 0 ); 8092 8093 flush_sequence(); 8094 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_UPDATENOW ); 8095 ok_sequence( WmInvalidateErasePaint, "InvalidateErasePaint", FALSE ); 8096 check_update_rgn( hwnd, 0 ); 8097 8098 flush_sequence(); 8099 SetRectRgn( hrgn, 0, 0, 100, 100 ); 8100 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE ); 8101 SetRectRgn( hrgn, 0, 0, 50, 100 ); 8102 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE ); 8103 SetRectRgn( hrgn, 50, 0, 100, 100 ); 8104 check_update_rgn( hwnd, hrgn ); 8105 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_ERASENOW ); 8106 ok_sequence( WmEmptySeq, "EmptySeq", FALSE ); /* must not generate messages, everything is valid */ 8107 check_update_rgn( hwnd, 0 ); 8108 8109 flush_sequence(); 8110 SetRectRgn( hrgn, 0, 0, 100, 100 ); 8111 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE ); 8112 SetRectRgn( hrgn, 0, 0, 100, 50 ); 8113 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_ERASENOW ); 8114 ok_sequence( WmErase, "Erase", FALSE ); 8115 SetRectRgn( hrgn, 0, 50, 100, 100 ); 8116 check_update_rgn( hwnd, hrgn ); 8117 8118 flush_sequence(); 8119 SetRectRgn( hrgn, 0, 0, 100, 100 ); 8120 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE ); 8121 SetRectRgn( hrgn, 0, 0, 50, 50 ); 8122 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOERASE | RDW_UPDATENOW ); 8123 ok_sequence( WmPaint, "Paint", FALSE ); 8124 8125 flush_sequence(); 8126 SetRectRgn( hrgn, -4, -4, -2, -2 ); 8127 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME ); 8128 SetRectRgn( hrgn, -200, -200, -198, -198 ); 8129 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOFRAME | RDW_ERASENOW ); 8130 ok_sequence( WmEmptySeq, "EmptySeq", FALSE ); 8131 8132 flush_sequence(); 8133 SetRectRgn( hrgn, -4, -4, -2, -2 ); 8134 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME ); 8135 SetRectRgn( hrgn, -4, -4, -3, -3 ); 8136 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOFRAME ); 8137 SetRectRgn( hrgn, 0, 0, 1, 1 ); 8138 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_UPDATENOW ); 8139 ok_sequence( WmPaint, "Paint", FALSE ); 8140 8141 flush_sequence(); 8142 SetRectRgn( hrgn, -4, -4, -1, -1 ); 8143 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME ); 8144 RedrawWindow( hwnd, NULL, 0, RDW_ERASENOW ); 8145 /* make sure no WM_PAINT was generated */ 8146 flush_events(); 8147 ok_sequence( WmInvalidateRgn, "InvalidateRgn", FALSE ); 8148 8149 flush_sequence(); 8150 SetRectRgn( hrgn, -4, -4, -1, -1 ); 8151 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME ); 8152 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) 8153 { 8154 if (msg.hwnd == hwnd && msg.message == WM_PAINT) 8155 { 8156 /* GetUpdateRgn must return empty region since only nonclient area is invalidated */ 8157 INT ret = GetUpdateRgn( hwnd, hrgn, FALSE ); 8158 ok( ret == NULLREGION, "Invalid GetUpdateRgn result %d\n", ret ); 8159 ret = GetUpdateRect( hwnd, &rect, FALSE ); 8160 ok( ret, "Invalid GetUpdateRect result %d\n", ret ); 8161 /* this will send WM_NCPAINT and validate the non client area */ 8162 ret = GetUpdateRect( hwnd, &rect, TRUE ); 8163 ok( !ret, "Invalid GetUpdateRect result %d\n", ret ); 8164 } 8165 DispatchMessageA( &msg ); 8166 } 8167 ok_sequence( WmGetUpdateRect, "GetUpdateRect", FALSE ); 8168 8169 DestroyWindow( hwnd ); 8170 8171 /* now test with a child window */ 8172 8173 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW, 8174 100, 100, 200, 200, 0, 0, 0, NULL); 8175 ok (hparent != 0, "Failed to create parent window\n"); 8176 8177 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE | WS_BORDER, 8178 10, 10, 100, 100, hparent, 0, 0, NULL); 8179 ok (hchild != 0, "Failed to create child window\n"); 8180 8181 ShowWindow( hparent, SW_SHOW ); 8182 UpdateWindow( hparent ); 8183 UpdateWindow( hchild ); 8184 flush_events(); 8185 flush_sequence(); 8186 log_all_parent_messages++; 8187 8188 SetRect( &rect, 0, 0, 50, 50 ); 8189 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); 8190 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW | RDW_ALLCHILDREN ); 8191 ok_sequence( WmInvalidateParentChild, "InvalidateParentChild", FALSE ); 8192 8193 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); 8194 pt.x = pt.y = 0; 8195 MapWindowPoints( hchild, hparent, &pt, 1 ); 8196 SetRectRgn( hrgn, 0, 0, 50 - pt.x, 50 - pt.y ); 8197 check_update_rgn( hchild, hrgn ); 8198 SetRectRgn( hrgn, 0, 0, 50, 50 ); 8199 check_update_rgn( hparent, hrgn ); 8200 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW ); 8201 ok_sequence( WmInvalidateParent, "InvalidateParent", FALSE ); 8202 RedrawWindow( hchild, NULL, 0, RDW_ERASENOW ); 8203 ok_sequence( WmEmptySeq, "EraseNow child", FALSE ); 8204 8205 flush_events(); 8206 ok_sequence( WmParentPaintNc, "WmParentPaintNc", FALSE ); 8207 8208 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN ); 8209 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW ); 8210 ok_sequence( WmInvalidateParent, "InvalidateParent2", FALSE ); 8211 RedrawWindow( hchild, NULL, 0, RDW_ERASENOW ); 8212 ok_sequence( WmEmptySeq, "EraseNow child", FALSE ); 8213 8214 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE ); 8215 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW | RDW_ALLCHILDREN ); 8216 ok_sequence( WmInvalidateParentChild2, "InvalidateParentChild2", FALSE ); 8217 8218 SetWindowLongA( hparent, GWL_STYLE, GetWindowLongA(hparent,GWL_STYLE) | WS_CLIPCHILDREN ); 8219 flush_sequence(); 8220 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN ); 8221 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW ); 8222 ok_sequence( WmInvalidateParentChild, "InvalidateParentChild3", FALSE ); 8223 8224 /* flush all paint messages */ 8225 flush_events(); 8226 flush_sequence(); 8227 8228 /* RDW_UPDATENOW on child with WS_CLIPCHILDREN doesn't change corresponding parent area */ 8229 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN ); 8230 SetRectRgn( hrgn, 0, 0, 50, 50 ); 8231 check_update_rgn( hparent, hrgn ); 8232 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW ); 8233 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE ); 8234 SetRectRgn( hrgn, 0, 0, 50, 50 ); 8235 check_update_rgn( hparent, hrgn ); 8236 8237 /* flush all paint messages */ 8238 flush_events(); 8239 SetWindowLongA( hparent, GWL_STYLE, GetWindowLongA(hparent,GWL_STYLE) & ~WS_CLIPCHILDREN ); 8240 flush_sequence(); 8241 8242 /* RDW_UPDATENOW on child without WS_CLIPCHILDREN will validate corresponding parent area */ 8243 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); 8244 SetRectRgn( hrgn, 0, 0, 50, 50 ); 8245 check_update_rgn( hparent, hrgn ); 8246 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW ); 8247 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE ); 8248 SetRectRgn( hrgn2, 10, 10, 50, 50 ); 8249 CombineRgn( hrgn, hrgn, hrgn2, RGN_DIFF ); 8250 check_update_rgn( hparent, hrgn ); 8251 /* flush all paint messages */ 8252 flush_events(); 8253 flush_sequence(); 8254 8255 /* same as above but parent gets completely validated */ 8256 SetRect( &rect, 20, 20, 30, 30 ); 8257 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); 8258 SetRectRgn( hrgn, 20, 20, 30, 30 ); 8259 check_update_rgn( hparent, hrgn ); 8260 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW ); 8261 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE ); 8262 check_update_rgn( hparent, 0 ); /* no update region */ 8263 flush_events(); 8264 ok_sequence( WmEmptySeq, "WmEmpty", FALSE ); /* and no paint messages */ 8265 8266 /* make sure RDW_VALIDATE on child doesn't have the same effect */ 8267 flush_sequence(); 8268 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); 8269 SetRectRgn( hrgn, 20, 20, 30, 30 ); 8270 check_update_rgn( hparent, hrgn ); 8271 RedrawWindow( hchild, NULL, 0, RDW_VALIDATE | RDW_NOERASE ); 8272 SetRectRgn( hrgn, 20, 20, 30, 30 ); 8273 check_update_rgn( hparent, hrgn ); 8274 8275 /* same as above but normal WM_PAINT doesn't validate parent */ 8276 flush_sequence(); 8277 SetRect( &rect, 20, 20, 30, 30 ); 8278 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); 8279 SetRectRgn( hrgn, 20, 20, 30, 30 ); 8280 check_update_rgn( hparent, hrgn ); 8281 /* no WM_PAINT in child while parent still pending */ 8282 while (PeekMessageA( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 8283 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE ); 8284 while (PeekMessageA( &msg, hparent, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 8285 ok_sequence( WmParentErasePaint, "WmParentErasePaint", FALSE ); 8286 8287 flush_sequence(); 8288 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); 8289 /* no WM_PAINT in child while parent still pending */ 8290 while (PeekMessageA( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 8291 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE ); 8292 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_NOERASE | RDW_NOCHILDREN ); 8293 /* now that parent is valid child should get WM_PAINT */ 8294 while (PeekMessageA( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 8295 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE ); 8296 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 8297 ok_sequence( WmEmptySeq, "No other message", FALSE ); 8298 8299 /* same thing with WS_CLIPCHILDREN in parent */ 8300 flush_sequence(); 8301 SetWindowLongA( hparent, GWL_STYLE, GetWindowLongA(hparent,GWL_STYLE) | WS_CLIPCHILDREN ); 8302 ok_sequence( WmSetParentStyle, "WmSetParentStyle", FALSE ); 8303 /* changing style invalidates non client area, but we need to invalidate something else to see it */ 8304 RedrawWindow( hparent, &rect, 0, RDW_UPDATENOW ); 8305 ok_sequence( WmEmptySeq, "No message", FALSE ); 8306 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_UPDATENOW ); 8307 ok_sequence( WmParentOnlyNcPaint, "WmParentOnlyNcPaint", FALSE ); 8308 8309 flush_sequence(); 8310 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN ); 8311 SetRectRgn( hrgn, 20, 20, 30, 30 ); 8312 check_update_rgn( hparent, hrgn ); 8313 /* no WM_PAINT in child while parent still pending */ 8314 while (PeekMessageA( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 8315 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE ); 8316 /* WM_PAINT in parent first */ 8317 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 8318 ok_sequence( WmParentPaintNc, "WmParentPaintNc2", FALSE ); 8319 8320 /* no RDW_ERASE in parent still causes RDW_ERASE and RDW_FRAME in child */ 8321 flush_sequence(); 8322 SetRect( &rect, 0, 0, 30, 30 ); 8323 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ALLCHILDREN ); 8324 SetRectRgn( hrgn, 0, 0, 30, 30 ); 8325 check_update_rgn( hparent, hrgn ); 8326 flush_events(); 8327 ok_sequence( WmParentPaintNc, "WmParentPaintNc3", FALSE ); 8328 8329 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */ 8330 flush_sequence(); 8331 SetRect( &rect, -10, 0, 30, 30 ); 8332 RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE ); 8333 SetRect( &rect, 0, 0, 20, 20 ); 8334 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_ALLCHILDREN ); 8335 RedrawWindow( hparent, NULL, 0, RDW_UPDATENOW ); 8336 ok_sequence( WmChildPaintNc, "WmChildPaintNc", FALSE ); 8337 8338 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */ 8339 flush_sequence(); 8340 SetRect( &rect, -10, 0, 30, 30 ); 8341 RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE ); 8342 SetRect( &rect, 0, 0, 100, 100 ); 8343 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_ALLCHILDREN ); 8344 RedrawWindow( hparent, NULL, 0, RDW_UPDATENOW ); 8345 ok_sequence( WmEmptySeq, "WmChildPaintNc2", FALSE ); 8346 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW ); 8347 ok_sequence( WmEmptySeq, "WmChildPaintNc3", FALSE ); 8348 8349 /* WS_CLIPCHILDREN doesn't exclude children from update region */ 8350 flush_sequence(); 8351 RedrawWindow( hparent, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_NOCHILDREN ); 8352 GetClientRect( hparent, &rect ); 8353 SetRectRgn( hrgn, rect.left, rect.top, rect.right, rect.bottom ); 8354 check_update_rgn( hparent, hrgn ); 8355 flush_events(); 8356 8357 RedrawWindow( hparent, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN ); 8358 GetClientRect( hparent, &rect ); 8359 SetRectRgn( hrgn, rect.left, rect.top, rect.right, rect.bottom ); 8360 check_update_rgn( hparent, hrgn ); 8361 flush_events(); 8362 8363 /* test RDW_INTERNALPAINT behavior */ 8364 8365 flush_sequence(); 8366 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT | RDW_NOCHILDREN ); 8367 flush_events(); 8368 ok_sequence( WmParentOnlyPaint, "WmParentOnlyPaint", FALSE ); 8369 8370 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT | RDW_ALLCHILDREN ); 8371 flush_events(); 8372 ok_sequence( WmParentPaint, "WmParentPaint", FALSE ); 8373 8374 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT ); 8375 flush_events(); 8376 ok_sequence( WmParentOnlyPaint, "WmParentOnlyPaint", FALSE ); 8377 8378 assert( GetWindowLongA(hparent, GWL_STYLE) & WS_CLIPCHILDREN ); 8379 UpdateWindow( hparent ); 8380 flush_events(); 8381 flush_sequence(); 8382 trace("testing SWP_FRAMECHANGED on parent with WS_CLIPCHILDREN\n"); 8383 RedrawWindow( hchild, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); 8384 SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | 8385 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED ); 8386 flush_events(); 8387 ok_sequence(WmSWP_FrameChanged_clip, "SetWindowPos:FrameChanged_clip", FALSE ); 8388 8389 UpdateWindow( hparent ); 8390 flush_events(); 8391 flush_sequence(); 8392 trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent with WS_CLIPCHILDREN\n"); 8393 RedrawWindow( hchild, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); 8394 SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_DEFERERASE | 8395 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED ); 8396 flush_events(); 8397 ok_sequence(WmSWP_FrameChangedDeferErase, "SetWindowPos:FrameChangedDeferErase", FALSE ); 8398 8399 SetWindowLongA( hparent, GWL_STYLE, GetWindowLongA(hparent,GWL_STYLE) & ~WS_CLIPCHILDREN ); 8400 ok_sequence( WmSetParentStyle, "WmSetParentStyle", FALSE ); 8401 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT ); 8402 flush_events(); 8403 ok_sequence( WmParentPaint, "WmParentPaint", FALSE ); 8404 8405 assert( !(GetWindowLongA(hparent, GWL_STYLE) & WS_CLIPCHILDREN) ); 8406 UpdateWindow( hparent ); 8407 flush_events(); 8408 flush_sequence(); 8409 trace("testing SWP_FRAMECHANGED on parent without WS_CLIPCHILDREN\n"); 8410 RedrawWindow( hchild, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); 8411 SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | 8412 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED ); 8413 flush_events(); 8414 ok_sequence(WmSWP_FrameChanged_noclip, "SetWindowPos:FrameChanged_noclip", FALSE ); 8415 8416 UpdateWindow( hparent ); 8417 flush_events(); 8418 flush_sequence(); 8419 trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent without WS_CLIPCHILDREN\n"); 8420 RedrawWindow( hchild, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); 8421 SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_DEFERERASE | 8422 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED ); 8423 flush_events(); 8424 ok_sequence(WmSWP_FrameChangedDeferErase, "SetWindowPos:FrameChangedDeferErase", FALSE ); 8425 8426 ok(GetWindowLongA( hparent, GWL_STYLE ) & WS_VISIBLE, "parent should be visible\n"); 8427 ok(GetWindowLongA( hchild, GWL_STYLE ) & WS_VISIBLE, "child should be visible\n"); 8428 8429 UpdateWindow( hparent ); 8430 flush_events(); 8431 flush_sequence(); 8432 trace("testing SetWindowPos(-10000, -10000) on child\n"); 8433 SetWindowPos( hchild, 0, -10000, -10000, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER ); 8434 check_update_rgn( hchild, 0 ); 8435 flush_events(); 8436 8437 #if 0 /* this one doesn't pass under Wine yet */ 8438 UpdateWindow( hparent ); 8439 flush_events(); 8440 flush_sequence(); 8441 trace("testing ShowWindow(SW_MINIMIZE) on child\n"); 8442 ShowWindow( hchild, SW_MINIMIZE ); 8443 check_update_rgn( hchild, 0 ); 8444 flush_events(); 8445 #endif 8446 8447 UpdateWindow( hparent ); 8448 flush_events(); 8449 flush_sequence(); 8450 trace("testing SetWindowPos(-10000, -10000) on parent\n"); 8451 SetWindowPos( hparent, 0, -10000, -10000, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER ); 8452 check_update_rgn( hparent, 0 ); 8453 flush_events(); 8454 8455 log_all_parent_messages--; 8456 DestroyWindow( hparent ); 8457 ok(!IsWindow(hchild), "child must be destroyed with its parent\n"); 8458 8459 /* tests for moving windows off-screen (needs simple WS_POPUP windows) */ 8460 8461 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_POPUP | WS_VISIBLE, 8462 100, 100, 200, 200, 0, 0, 0, NULL); 8463 ok (hparent != 0, "Failed to create parent window\n"); 8464 8465 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE, 8466 10, 10, 100, 100, hparent, 0, 0, NULL); 8467 ok (hchild != 0, "Failed to create child window\n"); 8468 8469 ShowWindow( hparent, SW_SHOW ); 8470 UpdateWindow( hparent ); 8471 UpdateWindow( hchild ); 8472 flush_events(); 8473 flush_sequence(); 8474 8475 /* moving child outside of parent boundaries changes update region */ 8476 SetRect( &rect, 0, 0, 40, 40 ); 8477 RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_ERASE ); 8478 SetRectRgn( hrgn, 0, 0, 40, 40 ); 8479 check_update_rgn( hchild, hrgn ); 8480 MoveWindow( hchild, -10, 10, 100, 100, FALSE ); 8481 SetRectRgn( hrgn, 10, 0, 40, 40 ); 8482 check_update_rgn( hchild, hrgn ); 8483 MoveWindow( hchild, -10, -10, 100, 100, FALSE ); 8484 SetRectRgn( hrgn, 10, 10, 40, 40 ); 8485 check_update_rgn( hchild, hrgn ); 8486 8487 /* moving parent off-screen does too */ 8488 SetRect( &rect, 0, 0, 100, 100 ); 8489 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_NOCHILDREN ); 8490 SetRectRgn( hrgn, 0, 0, 100, 100 ); 8491 check_update_rgn( hparent, hrgn ); 8492 SetRectRgn( hrgn, 10, 10, 40, 40 ); 8493 check_update_rgn( hchild, hrgn ); 8494 MoveWindow( hparent, -20, -20, 200, 200, FALSE ); 8495 GetUpdateRect( hparent, &rect2, FALSE ); 8496 if (!EqualRect( &rect2, &rect )) /* Win 8 and later don't crop update to screen */ 8497 { 8498 rect.left += 20; 8499 rect.top += 20; 8500 } 8501 SetRectRgn( hrgn, rect.left, rect.top, rect.right, rect.bottom ); 8502 check_update_rgn( hparent, hrgn ); 8503 SetRectRgn( hrgn, rect.left + 10, rect.top + 10, 40, 40 ); 8504 check_update_rgn( hchild, hrgn ); 8505 8506 /* invalidated region is cropped by the parent rects */ 8507 SetRect( &rect, 0, 0, 50, 50 ); 8508 RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_ERASE ); 8509 SetRectRgn( hrgn, rect2.left + 10, rect2.top + 10, 50, 50 ); 8510 check_update_rgn( hchild, hrgn ); 8511 8512 DestroyWindow( hparent ); 8513 ok(!IsWindow(hchild), "child must be destroyed with its parent\n"); 8514 flush_sequence(); 8515 8516 DeleteObject( hrgn ); 8517 DeleteObject( hrgn2 ); 8518 } 8519 8520 struct wnd_event 8521 { 8522 HWND hwnd; 8523 HANDLE grand_child; 8524 HANDLE start_event; 8525 HANDLE stop_event; 8526 }; 8527 8528 static DWORD WINAPI thread_proc(void *param) 8529 { 8530 MSG msg; 8531 struct wnd_event *wnd_event = param; 8532 8533 wnd_event->hwnd = CreateWindowExA(0, "TestWindowClass", "window caption text", WS_OVERLAPPEDWINDOW, 8534 100, 100, 200, 200, 0, 0, 0, NULL); 8535 ok(wnd_event->hwnd != 0, "Failed to create overlapped window\n"); 8536 8537 SetEvent(wnd_event->start_event); 8538 8539 while (GetMessageA(&msg, 0, 0, 0)) 8540 { 8541 TranslateMessage(&msg); 8542 DispatchMessageA(&msg); 8543 } 8544 8545 ok(IsWindow(wnd_event->hwnd), "window should still exist\n"); 8546 8547 return 0; 8548 } 8549 8550 static DWORD CALLBACK create_grand_child_thread( void *param ) 8551 { 8552 struct wnd_event *wnd_event = param; 8553 HWND hchild; 8554 MSG msg; 8555 8556 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", 8557 WS_CHILD | WS_VISIBLE, 0, 0, 10, 10, wnd_event->hwnd, 0, 0, NULL); 8558 ok (hchild != 0, "Failed to create child window\n"); 8559 flush_events(); 8560 flush_sequence(); 8561 SetEvent( wnd_event->start_event ); 8562 8563 for (;;) 8564 { 8565 MsgWaitForMultipleObjects(0, NULL, FALSE, 1000, QS_ALLINPUT); 8566 if (!IsWindow( hchild )) break; /* will be destroyed when parent thread exits */ 8567 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 8568 } 8569 return 0; 8570 } 8571 8572 static DWORD CALLBACK create_child_thread( void *param ) 8573 { 8574 struct wnd_event *wnd_event = param; 8575 struct wnd_event child_event; 8576 DWORD ret, tid; 8577 MSG msg; 8578 8579 child_event.hwnd = CreateWindowExA(0, "TestWindowClass", "Test child", 8580 WS_CHILD | WS_VISIBLE, 0, 0, 10, 10, wnd_event->hwnd, 0, 0, NULL); 8581 ok (child_event.hwnd != 0, "Failed to create child window\n"); 8582 SetFocus( child_event.hwnd ); 8583 flush_events(); 8584 flush_sequence(); 8585 child_event.start_event = wnd_event->start_event; 8586 wnd_event->grand_child = CreateThread(NULL, 0, create_grand_child_thread, &child_event, 0, &tid); 8587 for (;;) 8588 { 8589 DWORD ret = MsgWaitForMultipleObjects(1, &child_event.start_event, FALSE, 1000, QS_SENDMESSAGE); 8590 if (ret != 1) break; 8591 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 8592 } 8593 ret = WaitForSingleObject( wnd_event->stop_event, 5000 ); 8594 ok( !ret, "WaitForSingleObject failed %x\n", ret ); 8595 return 0; 8596 } 8597 8598 static const char manifest_dep[] = 8599 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">" 8600 "<assemblyIdentity version=\"1.2.3.4\" name=\"testdep1\" type=\"win32\" processorArchitecture=\"" ARCH "\"/>" 8601 " <file name=\"testdep.dll\" />" 8602 "</assembly>"; 8603 8604 static const char manifest_main[] = 8605 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">" 8606 "<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\" />" 8607 "<dependency>" 8608 " <dependentAssembly>" 8609 " <assemblyIdentity type=\"win32\" name=\"testdep1\" version=\"1.2.3.4\" processorArchitecture=\"" ARCH "\" />" 8610 " </dependentAssembly>" 8611 "</dependency>" 8612 "</assembly>"; 8613 8614 static void create_manifest_file(const char *filename, const char *manifest) 8615 { 8616 WCHAR path[MAX_PATH]; 8617 HANDLE file; 8618 DWORD size; 8619 8620 MultiByteToWideChar( CP_ACP, 0, filename, -1, path, MAX_PATH ); 8621 file = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 8622 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError()); 8623 WriteFile(file, manifest, strlen(manifest), &size, NULL); 8624 CloseHandle(file); 8625 } 8626 8627 static HANDLE test_create(const char *file) 8628 { 8629 WCHAR path[MAX_PATH]; 8630 ACTCTXW actctx; 8631 HANDLE handle; 8632 8633 MultiByteToWideChar(CP_ACP, 0, file, -1, path, MAX_PATH); 8634 memset(&actctx, 0, sizeof(ACTCTXW)); 8635 actctx.cbSize = sizeof(ACTCTXW); 8636 actctx.lpSource = path; 8637 8638 handle = pCreateActCtxW(&actctx); 8639 ok(handle != INVALID_HANDLE_VALUE, "failed to create context, error %u\n", GetLastError()); 8640 8641 ok(actctx.cbSize == sizeof(actctx), "cbSize=%d\n", actctx.cbSize); 8642 ok(actctx.dwFlags == 0, "dwFlags=%d\n", actctx.dwFlags); 8643 ok(actctx.lpSource == path, "lpSource=%p\n", actctx.lpSource); 8644 ok(actctx.wProcessorArchitecture == 0, "wProcessorArchitecture=%d\n", actctx.wProcessorArchitecture); 8645 ok(actctx.wLangId == 0, "wLangId=%d\n", actctx.wLangId); 8646 ok(actctx.lpAssemblyDirectory == NULL, "lpAssemblyDirectory=%p\n", actctx.lpAssemblyDirectory); 8647 ok(actctx.lpResourceName == NULL, "lpResourceName=%p\n", actctx.lpResourceName); 8648 ok(actctx.lpApplicationName == NULL, "lpApplicationName=%p\n", actctx.lpApplicationName); 8649 ok(actctx.hModule == NULL, "hModule=%p\n", actctx.hModule); 8650 8651 return handle; 8652 } 8653 8654 static void test_interthread_messages(void) 8655 { 8656 HANDLE hThread, context, handle, event; 8657 ULONG_PTR cookie; 8658 DWORD tid; 8659 WNDPROC proc; 8660 MSG msg; 8661 char buf[256]; 8662 int len, expected_len; 8663 struct wnd_event wnd_event; 8664 BOOL ret; 8665 8666 wnd_event.start_event = CreateEventW(NULL, 0, 0, NULL); 8667 if (!wnd_event.start_event) 8668 { 8669 win_skip("skipping interthread message test under win9x\n"); 8670 return; 8671 } 8672 8673 hThread = CreateThread(NULL, 0, thread_proc, &wnd_event, 0, &tid); 8674 ok(hThread != NULL, "CreateThread failed, error %d\n", GetLastError()); 8675 8676 ok(WaitForSingleObject(wnd_event.start_event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 8677 8678 CloseHandle(wnd_event.start_event); 8679 8680 SetLastError(0xdeadbeef); 8681 ok(!DestroyWindow(wnd_event.hwnd), "DestroyWindow succeeded\n"); 8682 ok(GetLastError() == ERROR_ACCESS_DENIED || GetLastError() == 0xdeadbeef, 8683 "wrong error code %d\n", GetLastError()); 8684 8685 proc = (WNDPROC)GetWindowLongPtrA(wnd_event.hwnd, GWLP_WNDPROC); 8686 ok(proc != NULL, "GetWindowLongPtrA(GWLP_WNDPROC) error %d\n", GetLastError()); 8687 8688 expected_len = lstrlenA("window caption text"); 8689 memset(buf, 0, sizeof(buf)); 8690 SetLastError(0xdeadbeef); 8691 len = CallWindowProcA(proc, wnd_event.hwnd, WM_GETTEXT, sizeof(buf), (LPARAM)buf); 8692 ok(len == expected_len, "CallWindowProcA(WM_GETTEXT) error %d, len %d, expected len %d\n", GetLastError(), len, expected_len); 8693 ok(!lstrcmpA(buf, "window caption text"), "window text mismatch\n"); 8694 8695 msg.hwnd = wnd_event.hwnd; 8696 msg.message = WM_GETTEXT; 8697 msg.wParam = sizeof(buf); 8698 msg.lParam = (LPARAM)buf; 8699 memset(buf, 0, sizeof(buf)); 8700 SetLastError(0xdeadbeef); 8701 len = DispatchMessageA(&msg); 8702 ok((!len && GetLastError() == ERROR_MESSAGE_SYNC_ONLY) || broken(len), /* nt4 */ 8703 "DispatchMessageA(WM_GETTEXT) succeeded on another thread window: ret %d, error %d\n", len, GetLastError()); 8704 8705 /* the following test causes an exception in user.exe under win9x */ 8706 msg.hwnd = wnd_event.hwnd; 8707 msg.message = WM_TIMER; 8708 msg.wParam = 0; 8709 msg.lParam = GetWindowLongPtrA(wnd_event.hwnd, GWLP_WNDPROC); 8710 SetLastError(0xdeadbeef); 8711 len = DispatchMessageA(&msg); 8712 ok(!len && GetLastError() == 0xdeadbeef, 8713 "DispatchMessageA(WM_TIMER) failed on another thread window: ret %d, error %d\n", len, GetLastError()); 8714 8715 ret = PostMessageA(wnd_event.hwnd, WM_QUIT, 0, 0); 8716 ok( ret, "PostMessageA(WM_QUIT) error %d\n", GetLastError()); 8717 8718 ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 8719 CloseHandle(hThread); 8720 8721 ok(!IsWindow(wnd_event.hwnd), "window should be destroyed on thread exit\n"); 8722 8723 wnd_event.hwnd = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 8724 100, 100, 200, 200, 0, 0, 0, NULL); 8725 ok (wnd_event.hwnd != 0, "Failed to create parent window\n"); 8726 flush_events(); 8727 flush_sequence(); 8728 log_all_parent_messages++; 8729 wnd_event.start_event = CreateEventA( NULL, TRUE, FALSE, NULL ); 8730 wnd_event.stop_event = CreateEventA( NULL, TRUE, FALSE, NULL ); 8731 hThread = CreateThread( NULL, 0, create_child_thread, &wnd_event, 0, &tid ); 8732 for (;;) 8733 { 8734 ret = MsgWaitForMultipleObjects(1, &wnd_event.start_event, FALSE, 1000, QS_SENDMESSAGE); 8735 if (ret != 1) break; 8736 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 8737 } 8738 ok( !ret, "MsgWaitForMultipleObjects failed %x\n", ret ); 8739 /* now wait for the thread without processing messages; this shouldn't deadlock */ 8740 SetEvent( wnd_event.stop_event ); 8741 ret = WaitForSingleObject( hThread, 5000 ); 8742 ok( !ret, "WaitForSingleObject failed %x\n", ret ); 8743 CloseHandle( hThread ); 8744 8745 ret = WaitForSingleObject( wnd_event.grand_child, 5000 ); 8746 ok( !ret, "WaitForSingleObject failed %x\n", ret ); 8747 CloseHandle( wnd_event.grand_child ); 8748 8749 CloseHandle( wnd_event.start_event ); 8750 CloseHandle( wnd_event.stop_event ); 8751 flush_events(); 8752 ok_sequence(WmExitThreadSeq, "destroy child on thread exit", FALSE); 8753 log_all_parent_messages--; 8754 DestroyWindow( wnd_event.hwnd ); 8755 8756 /* activation context tests */ 8757 if (!pActivateActCtx) 8758 { 8759 win_skip("Activation contexts are not supported, skipping\n"); 8760 return; 8761 } 8762 8763 create_manifest_file("testdep1.manifest", manifest_dep); 8764 create_manifest_file("main.manifest", manifest_main); 8765 8766 context = test_create("main.manifest"); 8767 DeleteFileA("testdep1.manifest"); 8768 DeleteFileA("main.manifest"); 8769 8770 handle = (void*)0xdeadbeef; 8771 ret = pGetCurrentActCtx(&handle); 8772 ok(ret, "GetCurrentActCtx failed: %u\n", GetLastError()); 8773 ok(handle == 0, "active context %p\n", handle); 8774 8775 wnd_event.start_event = CreateEventW(NULL, 0, 0, NULL); 8776 hThread = CreateThread(NULL, 0, thread_proc, &wnd_event, 0, &tid); 8777 ok(hThread != NULL, "CreateThread failed, error %d\n", GetLastError()); 8778 ok(WaitForSingleObject(wnd_event.start_event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 8779 CloseHandle(wnd_event.start_event); 8780 8781 /* context is activated after thread creation, so it doesn't inherit it by default */ 8782 ret = pActivateActCtx(context, &cookie); 8783 ok(ret, "activation failed: %u\n", GetLastError()); 8784 8785 handle = 0; 8786 ret = pGetCurrentActCtx(&handle); 8787 ok(ret, "GetCurrentActCtx failed: %u\n", GetLastError()); 8788 ok(handle != 0, "active context %p\n", handle); 8789 pReleaseActCtx(handle); 8790 8791 /* destination window will test for active context */ 8792 ret = SendMessageA(wnd_event.hwnd, WM_USER+10, 0, 0); 8793 ok(ret, "thread window returned %d\n", ret); 8794 8795 event = CreateEventW(NULL, 0, 0, NULL); 8796 ret = PostMessageA(wnd_event.hwnd, WM_USER+10, 0, (LPARAM)event); 8797 ok(ret, "thread window returned %d\n", ret); 8798 ok(WaitForSingleObject(event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 8799 CloseHandle(event); 8800 8801 ret = PostMessageA(wnd_event.hwnd, WM_QUIT, 0, 0); 8802 ok(ret, "PostMessageA(WM_QUIT) error %d\n", GetLastError()); 8803 8804 ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 8805 CloseHandle(hThread); 8806 8807 ret = pDeactivateActCtx(0, cookie); 8808 ok(ret, "DeactivateActCtx failed: %u\n", GetLastError()); 8809 pReleaseActCtx(context); 8810 } 8811 8812 8813 static const struct message WmVkN[] = { 8814 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */ 8815 { WM_KEYDOWN, wparam|lparam, 'N', 1 }, 8816 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 }, 8817 { WM_CHAR, wparam|lparam, 'n', 1 }, 8818 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1002,1), 0 }, 8819 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */ 8820 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 }, 8821 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 }, 8822 { 0 } 8823 }; 8824 static const struct message WmShiftVkN[] = { 8825 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 1 }, /* XP */ 8826 { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 1 }, 8827 { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 1 }, 8828 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */ 8829 { WM_KEYDOWN, wparam|lparam, 'N', 1 }, 8830 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 }, 8831 { WM_CHAR, wparam|lparam, 'N', 1 }, 8832 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1001,1), 0 }, 8833 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */ 8834 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 }, 8835 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 }, 8836 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0xc0000001 }, /* XP */ 8837 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xc0000001 }, 8838 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xc0000001 }, 8839 { 0 } 8840 }; 8841 static const struct message WmCtrlVkN[] = { 8842 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 1 }, /* XP */ 8843 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 }, 8844 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 }, 8845 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */ 8846 { WM_KEYDOWN, wparam|lparam, 'N', 1 }, 8847 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 }, 8848 { WM_CHAR, wparam|lparam, 0x000e, 1 }, 8849 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1000,1), 0 }, 8850 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */ 8851 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 }, 8852 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 }, 8853 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 0xc0000001 }, /* XP */ 8854 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 }, 8855 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 }, 8856 { 0 } 8857 }; 8858 static const struct message WmCtrlVkN_2[] = { 8859 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 1 }, /* XP */ 8860 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 }, 8861 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 }, 8862 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */ 8863 { WM_KEYDOWN, wparam|lparam, 'N', 1 }, 8864 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1000,1), 0 }, 8865 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */ 8866 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 }, 8867 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 }, 8868 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 0xc0000001 }, /* XP */ 8869 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 }, 8870 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 }, 8871 { 0 } 8872 }; 8873 static const struct message WmAltVkN[] = { 8874 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, /* XP */ 8875 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 }, 8876 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, 8877 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0x20000001 }, /* XP */ 8878 { WM_SYSKEYDOWN, wparam|lparam, 'N', 0x20000001 }, 8879 { WM_SYSKEYDOWN, sent|wparam|lparam, 'N', 0x20000001 }, 8880 { WM_SYSCHAR, wparam|lparam, 'n', 0x20000001 }, 8881 { WM_SYSCHAR, sent|wparam|lparam, 'n', 0x20000001 }, 8882 { WM_SYSCOMMAND, sent|defwinproc|wparam|lparam, SC_KEYMENU, 'n' }, 8883 { HCBT_SYSCOMMAND, hook }, 8884 { WM_ENTERMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 }, 8885 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, 8886 { 0x00AE, sent|defwinproc|optional }, /* XP */ 8887 { WM_GETTEXT, sent|defwinproc|optional }, /* XP */ 8888 { WM_INITMENU, sent|defwinproc }, 8889 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 }, 8890 { WM_MENUCHAR, sent|defwinproc|wparam, MAKEWPARAM('n',MF_SYSMENU) }, 8891 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, 8892 { WM_CAPTURECHANGED, sent|defwinproc }, 8893 { WM_MENUSELECT, sent|defwinproc|wparam, MAKEWPARAM(0,0xffff) }, 8894 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 }, 8895 { WM_EXITMENULOOP, sent|defwinproc }, 8896 { WM_MENUSELECT, sent|defwinproc|wparam|optional, MAKEWPARAM(0,0xffff) }, /* Win95 bug */ 8897 { WM_EXITMENULOOP, sent|defwinproc|optional }, /* Win95 bug */ 8898 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xe0000001 }, /* XP */ 8899 { WM_SYSKEYUP, wparam|lparam, 'N', 0xe0000001 }, 8900 { WM_SYSKEYUP, sent|wparam|lparam, 'N', 0xe0000001 }, 8901 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */ 8902 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 }, 8903 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 }, 8904 { 0 } 8905 }; 8906 static const struct message WmAltVkN_2[] = { 8907 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, /* XP */ 8908 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 }, 8909 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, 8910 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0x20000001 }, /* XP */ 8911 { WM_SYSKEYDOWN, wparam|lparam, 'N', 0x20000001 }, 8912 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1003,1), 0 }, 8913 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xe0000001 }, /* XP */ 8914 { WM_SYSKEYUP, wparam|lparam, 'N', 0xe0000001 }, 8915 { WM_SYSKEYUP, sent|wparam|lparam, 'N', 0xe0000001 }, 8916 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */ 8917 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 }, 8918 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 }, 8919 { 0 } 8920 }; 8921 static const struct message WmCtrlAltVkN[] = { 8922 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 1 }, /* XP */ 8923 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 }, 8924 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 }, 8925 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, /* XP */ 8926 { WM_KEYDOWN, wparam|lparam, VK_MENU, 0x20000001 }, 8927 { WM_KEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, 8928 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0x20000001 }, /* XP */ 8929 { WM_KEYDOWN, wparam|lparam, 'N', 0x20000001 }, 8930 { WM_KEYDOWN, sent|wparam|lparam, 'N', 0x20000001 }, 8931 { WM_CHAR, optional }, 8932 { WM_CHAR, sent|optional }, 8933 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xe0000001 }, /* XP */ 8934 { WM_KEYUP, wparam|lparam, 'N', 0xe0000001 }, 8935 { WM_KEYUP, sent|wparam|lparam, 'N', 0xe0000001 }, 8936 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */ 8937 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 }, 8938 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 }, 8939 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 0xc0000001 }, /* XP */ 8940 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 }, 8941 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 }, 8942 { 0 } 8943 }; 8944 static const struct message WmCtrlShiftVkN[] = { 8945 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 1 }, /* XP */ 8946 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 }, 8947 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 }, 8948 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 1 }, /* XP */ 8949 { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 1 }, 8950 { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 1 }, 8951 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */ 8952 { WM_KEYDOWN, wparam|lparam, 'N', 1 }, 8953 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1004,1), 0 }, 8954 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */ 8955 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 }, 8956 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 }, 8957 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0xc0000001 }, /* XP */ 8958 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xc0000001 }, 8959 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xc0000001 }, 8960 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 0xc0000001 }, /* XP */ 8961 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 }, 8962 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 }, 8963 { 0 } 8964 }; 8965 static const struct message WmCtrlAltShiftVkN[] = { 8966 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 1 }, /* XP */ 8967 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 }, 8968 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 }, 8969 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, /* XP */ 8970 { WM_KEYDOWN, wparam|lparam, VK_MENU, 0x20000001 }, 8971 { WM_KEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, 8972 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0x20000001 }, /* XP */ 8973 { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 0x20000001 }, 8974 { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 0x20000001 }, 8975 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0x20000001 }, /* XP */ 8976 { WM_KEYDOWN, wparam|lparam, 'N', 0x20000001 }, 8977 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1005,1), 0 }, 8978 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xe0000001 }, /* XP */ 8979 { WM_KEYUP, wparam|lparam, 'N', 0xe0000001 }, 8980 { WM_KEYUP, sent|wparam|lparam, 'N', 0xe0000001 }, 8981 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0xe0000001 }, /* XP */ 8982 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xe0000001 }, 8983 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xe0000001 }, 8984 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */ 8985 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 }, 8986 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 }, 8987 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 0xc0000001 }, /* XP */ 8988 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 }, 8989 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 }, 8990 { 0 } 8991 }; 8992 static const struct message WmAltPressRelease[] = { 8993 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, /* XP */ 8994 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 }, 8995 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, 8996 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */ 8997 { WM_SYSKEYUP, wparam|lparam, VK_MENU, 0xc0000001 }, 8998 { WM_SYSKEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 }, 8999 { WM_SYSCOMMAND, sent|defwinproc|wparam|lparam, SC_KEYMENU, 0 }, 9000 { HCBT_SYSCOMMAND, hook }, 9001 { WM_ENTERMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 }, 9002 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, 9003 { WM_INITMENU, sent|defwinproc }, 9004 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 }, 9005 { WM_MENUSELECT, sent|defwinproc|wparam, MAKEWPARAM(0,MF_SYSMENU|MF_POPUP|MF_HILITE), 0, MAKEWPARAM(0,MF_RIGHTJUSTIFY) }, 9006 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 }, 9007 9008 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x30000001 }, /* XP */ 9009 9010 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 }, 9011 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0, }, 9012 { WM_CAPTURECHANGED, sent|defwinproc }, 9013 { WM_MENUSELECT, sent|defwinproc|wparam|optional, MAKEWPARAM(0,0xffff) }, 9014 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 }, 9015 { WM_EXITMENULOOP, sent|defwinproc }, 9016 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */ 9017 { WM_SYSKEYUP, wparam|lparam, VK_MENU, 0xc0000001 }, 9018 { WM_SYSKEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 }, 9019 { 0 } 9020 }; 9021 static const struct message WmShiftMouseButton[] = { 9022 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 1 }, /* XP */ 9023 { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 1 }, 9024 { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 1 }, 9025 { WM_MOUSEMOVE, wparam|optional, 0, 0 }, 9026 { WM_MOUSEMOVE, sent|wparam|optional, 0, 0 }, 9027 { WM_LBUTTONDOWN, wparam, MK_LBUTTON|MK_SHIFT, 0 }, 9028 { WM_LBUTTONDOWN, sent|wparam, MK_LBUTTON|MK_SHIFT, 0 }, 9029 { WM_LBUTTONUP, wparam, MK_SHIFT, 0 }, 9030 { WM_LBUTTONUP, sent|wparam, MK_SHIFT, 0 }, 9031 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0xc0000001 }, /* XP */ 9032 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xc0000001 }, 9033 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xc0000001 }, 9034 { 0 } 9035 }; 9036 static const struct message WmF1Seq[] = { 9037 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F1, 1 }, /* XP */ 9038 { WM_KEYDOWN, wparam|lparam, VK_F1, 1 }, 9039 { WM_KEYDOWN, sent|wparam|lparam, VK_F1, 0x00000001 }, 9040 { WM_KEYF1, wparam|lparam, 0, 0 }, 9041 { WM_KEYF1, sent|wparam|lparam, 0, 0 }, 9042 { WM_HELP, sent|defwinproc }, 9043 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F1, 0xc0000001 }, /* XP */ 9044 { WM_KEYUP, wparam|lparam, VK_F1, 0xc0000001 }, 9045 { WM_KEYUP, sent|wparam|lparam, VK_F1, 0xc0000001 }, 9046 { 0 } 9047 }; 9048 static const struct message WmVkAppsSeq[] = { 9049 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_APPS, 1 }, /* XP */ 9050 { WM_KEYDOWN, wparam|lparam, VK_APPS, 1 }, 9051 { WM_KEYDOWN, sent|wparam|lparam, VK_APPS, 0x00000001 }, 9052 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_APPS, 0xc0000001 }, /* XP */ 9053 { WM_KEYUP, wparam|lparam, VK_APPS, 0xc0000001 }, 9054 { WM_KEYUP, sent|wparam|lparam, VK_APPS, 0xc0000001 }, 9055 { WM_CONTEXTMENU, lparam, /*hwnd*/0, -1 }, 9056 { WM_CONTEXTMENU, sent|lparam, /*hwnd*/0, -1 }, 9057 { 0 } 9058 }; 9059 static const struct message WmVkF10Seq[] = { 9060 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 1 }, /* XP */ 9061 { WM_SYSKEYDOWN, wparam|lparam, VK_F10, 1 }, 9062 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_F10, 0x00000001 }, 9063 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 0xc0000001 }, /* XP */ 9064 { WM_SYSKEYUP, wparam|lparam, VK_F10, 0xc0000001 }, 9065 { WM_SYSKEYUP, sent|wparam|lparam, VK_F10, 0xc0000001 }, 9066 { WM_SYSCOMMAND, sent|defwinproc|wparam, SC_KEYMENU }, 9067 { HCBT_SYSCOMMAND, hook }, 9068 { WM_ENTERMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 }, 9069 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, 9070 { WM_INITMENU, sent|defwinproc }, 9071 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 }, 9072 { WM_MENUSELECT, sent|defwinproc|wparam, MAKEWPARAM(0,MF_SYSMENU|MF_POPUP|MF_HILITE), 0, MAKEWPARAM(0,MF_RIGHTJUSTIFY) }, 9073 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 }, 9074 9075 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 0x10000001 }, /* XP */ 9076 9077 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 1 }, /* XP */ 9078 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 }, 9079 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0, }, 9080 { WM_CAPTURECHANGED, sent|defwinproc }, 9081 { WM_MENUSELECT, sent|defwinproc|wparam|optional, MAKEWPARAM(0,0xffff) }, 9082 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 }, 9083 { WM_EXITMENULOOP, sent|defwinproc }, 9084 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 0xc0000001 }, /* XP */ 9085 { WM_SYSKEYUP, wparam|lparam, VK_F10, 0xc0000001 }, 9086 { WM_SYSKEYUP, sent|wparam|lparam, VK_F10, 0xc0000001 }, 9087 { 0 } 9088 }; 9089 static const struct message WmShiftF10Seq[] = { 9090 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 1 }, /* XP */ 9091 { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 1 }, 9092 { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 0x00000001 }, 9093 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 1 }, /* XP */ 9094 { WM_SYSKEYDOWN, wparam|lparam, VK_F10, 1 }, 9095 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_F10, 0x00000001 }, 9096 { WM_CONTEXTMENU, sent|defwinproc|lparam, /*hwnd*/0, -1 }, 9097 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 0xc0000001 }, /* XP */ 9098 { WM_SYSKEYUP, wparam|lparam, VK_F10, 0xc0000001 }, 9099 { WM_SYSKEYUP, sent|wparam|lparam, VK_F10, 0xc0000001 }, 9100 { WM_SYSCOMMAND, sent|defwinproc|wparam, SC_KEYMENU }, 9101 { HCBT_SYSCOMMAND, hook }, 9102 { WM_ENTERMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 }, 9103 { WM_INITMENU, sent|defwinproc }, 9104 { WM_MENUSELECT, sent|defwinproc|wparam, MAKEWPARAM(0,MF_SYSMENU|MF_POPUP|MF_HILITE), 0, MAKEWPARAM(0,MF_RIGHTJUSTIFY) }, 9105 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0xd0000001 }, /* XP */ 9106 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_ESCAPE, 0x10000001 }, /* XP */ 9107 { WM_CAPTURECHANGED, sent|defwinproc|wparam|lparam, 0, 0 }, 9108 { WM_MENUSELECT, sent|defwinproc|wparam|lparam, 0xffff0000, 0 }, 9109 { WM_EXITMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 }, 9110 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_ESCAPE, 0xc0000001 }, /* XP */ 9111 { WM_KEYUP, wparam|lparam, VK_ESCAPE, 0xc0000001 }, 9112 { WM_KEYUP, sent|wparam|lparam, VK_ESCAPE, 0xc0000001 }, 9113 { 0 } 9114 }; 9115 9116 static void pump_msg_loop(HWND hwnd, HACCEL hAccel) 9117 { 9118 MSG msg; 9119 9120 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 9121 { 9122 struct recvd_message log_msg; 9123 9124 /* ignore some unwanted messages */ 9125 if (msg.message == WM_MOUSEMOVE || 9126 msg.message == WM_TIMER || 9127 ignore_message( msg.message )) 9128 continue; 9129 9130 log_msg.hwnd = msg.hwnd; 9131 log_msg.message = msg.message; 9132 log_msg.flags = wparam|lparam; 9133 log_msg.wParam = msg.wParam; 9134 log_msg.lParam = msg.lParam; 9135 log_msg.descr = "accel"; 9136 add_message(&log_msg); 9137 9138 if (!hAccel || !TranslateAcceleratorA(hwnd, hAccel, &msg)) 9139 { 9140 TranslateMessage(&msg); 9141 DispatchMessageA(&msg); 9142 } 9143 } 9144 } 9145 9146 static void test_accelerators(void) 9147 { 9148 RECT rc; 9149 POINT pt; 9150 SHORT state; 9151 HACCEL hAccel; 9152 HWND hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 9153 100, 100, 200, 200, 0, 0, 0, NULL); 9154 BOOL ret; 9155 9156 assert(hwnd != 0); 9157 UpdateWindow(hwnd); 9158 flush_events(); 9159 flush_sequence(); 9160 9161 SetFocus(hwnd); 9162 ok(GetFocus() == hwnd, "wrong focus window %p\n", GetFocus()); 9163 9164 state = GetKeyState(VK_SHIFT); 9165 ok(!(state & 0x8000), "wrong Shift state %04x\n", state); 9166 state = GetKeyState(VK_CAPITAL); 9167 ok(state == 0, "wrong CapsLock state %04x\n", state); 9168 9169 hAccel = LoadAcceleratorsA(GetModuleHandleA(NULL), MAKEINTRESOURCEA(1)); 9170 assert(hAccel != 0); 9171 9172 flush_events(); 9173 pump_msg_loop(hwnd, 0); 9174 flush_sequence(); 9175 9176 trace("testing VK_N press/release\n"); 9177 flush_sequence(); 9178 keybd_event('N', 0, 0, 0); 9179 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 9180 pump_msg_loop(hwnd, hAccel); 9181 if (!sequence_cnt) /* we didn't get any message */ 9182 { 9183 skip( "queuing key events not supported\n" ); 9184 goto done; 9185 } 9186 ok_sequence(WmVkN, "VK_N press/release", FALSE); 9187 9188 trace("testing Shift+VK_N press/release\n"); 9189 flush_sequence(); 9190 keybd_event(VK_SHIFT, 0, 0, 0); 9191 keybd_event('N', 0, 0, 0); 9192 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 9193 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0); 9194 pump_msg_loop(hwnd, hAccel); 9195 ok_sequence(WmShiftVkN, "Shift+VK_N press/release", FALSE); 9196 9197 trace("testing Ctrl+VK_N press/release\n"); 9198 flush_sequence(); 9199 keybd_event(VK_CONTROL, 0, 0, 0); 9200 keybd_event('N', 0, 0, 0); 9201 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 9202 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); 9203 pump_msg_loop(hwnd, hAccel); 9204 ok_sequence(WmCtrlVkN, "Ctrl+VK_N press/release", FALSE); 9205 9206 trace("testing Alt+VK_N press/release\n"); 9207 flush_sequence(); 9208 keybd_event(VK_MENU, 0, 0, 0); 9209 keybd_event('N', 0, 0, 0); 9210 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 9211 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); 9212 pump_msg_loop(hwnd, hAccel); 9213 ok_sequence(WmAltVkN, "Alt+VK_N press/release", FALSE); 9214 9215 trace("testing Ctrl+Alt+VK_N press/release 1\n"); 9216 flush_sequence(); 9217 keybd_event(VK_CONTROL, 0, 0, 0); 9218 keybd_event(VK_MENU, 0, 0, 0); 9219 keybd_event('N', 0, 0, 0); 9220 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 9221 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); 9222 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); 9223 pump_msg_loop(hwnd, hAccel); 9224 ok_sequence(WmCtrlAltVkN, "Ctrl+Alt+VK_N press/release 1", FALSE); 9225 9226 ret = DestroyAcceleratorTable(hAccel); 9227 ok( ret, "DestroyAcceleratorTable error %d\n", GetLastError()); 9228 9229 hAccel = LoadAcceleratorsA(GetModuleHandleA(NULL), MAKEINTRESOURCEA(2)); 9230 assert(hAccel != 0); 9231 9232 trace("testing VK_N press/release\n"); 9233 flush_sequence(); 9234 keybd_event('N', 0, 0, 0); 9235 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 9236 pump_msg_loop(hwnd, hAccel); 9237 ok_sequence(WmVkN, "VK_N press/release", FALSE); 9238 9239 trace("testing Shift+VK_N press/release\n"); 9240 flush_sequence(); 9241 keybd_event(VK_SHIFT, 0, 0, 0); 9242 keybd_event('N', 0, 0, 0); 9243 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 9244 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0); 9245 pump_msg_loop(hwnd, hAccel); 9246 ok_sequence(WmShiftVkN, "Shift+VK_N press/release", FALSE); 9247 9248 trace("testing Ctrl+VK_N press/release 2\n"); 9249 flush_sequence(); 9250 keybd_event(VK_CONTROL, 0, 0, 0); 9251 keybd_event('N', 0, 0, 0); 9252 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 9253 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); 9254 pump_msg_loop(hwnd, hAccel); 9255 ok_sequence(WmCtrlVkN_2, "Ctrl+VK_N press/release 2", FALSE); 9256 9257 trace("testing Alt+VK_N press/release 2\n"); 9258 flush_sequence(); 9259 keybd_event(VK_MENU, 0, 0, 0); 9260 keybd_event('N', 0, 0, 0); 9261 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 9262 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); 9263 pump_msg_loop(hwnd, hAccel); 9264 ok_sequence(WmAltVkN_2, "Alt+VK_N press/release 2", FALSE); 9265 9266 trace("testing Ctrl+Alt+VK_N press/release 2\n"); 9267 flush_sequence(); 9268 keybd_event(VK_CONTROL, 0, 0, 0); 9269 keybd_event(VK_MENU, 0, 0, 0); 9270 keybd_event('N', 0, 0, 0); 9271 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 9272 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); 9273 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); 9274 pump_msg_loop(hwnd, hAccel); 9275 ok_sequence(WmCtrlAltVkN, "Ctrl+Alt+VK_N press/release 2", FALSE); 9276 9277 trace("testing Ctrl+Shift+VK_N press/release\n"); 9278 flush_sequence(); 9279 keybd_event(VK_CONTROL, 0, 0, 0); 9280 keybd_event(VK_SHIFT, 0, 0, 0); 9281 keybd_event('N', 0, 0, 0); 9282 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 9283 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0); 9284 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); 9285 pump_msg_loop(hwnd, hAccel); 9286 ok_sequence(WmCtrlShiftVkN, "Ctrl+Shift+VK_N press/release", FALSE); 9287 9288 trace("testing Ctrl+Alt+Shift+VK_N press/release\n"); 9289 flush_sequence(); 9290 keybd_event(VK_CONTROL, 0, 0, 0); 9291 keybd_event(VK_MENU, 0, 0, 0); 9292 keybd_event(VK_SHIFT, 0, 0, 0); 9293 keybd_event('N', 0, 0, 0); 9294 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 9295 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0); 9296 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); 9297 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); 9298 pump_msg_loop(hwnd, hAccel); 9299 ok_sequence(WmCtrlAltShiftVkN, "Ctrl+Alt+Shift+VK_N press/release", FALSE); 9300 9301 ret = DestroyAcceleratorTable(hAccel); 9302 ok( ret, "DestroyAcceleratorTable error %d\n", GetLastError()); 9303 hAccel = 0; 9304 9305 trace("testing Alt press/release\n"); 9306 flush_sequence(); 9307 keybd_event(VK_MENU, 0, 0, 0); 9308 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); 9309 keybd_event(VK_MENU, 0, 0, 0); 9310 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); 9311 pump_msg_loop(hwnd, 0); 9312 /* this test doesn't pass in Wine for managed windows */ 9313 ok_sequence(WmAltPressRelease, "Alt press/release", TRUE); 9314 9315 trace("testing VK_F1 press/release\n"); 9316 keybd_event(VK_F1, 0, 0, 0); 9317 keybd_event(VK_F1, 0, KEYEVENTF_KEYUP, 0); 9318 pump_msg_loop(hwnd, 0); 9319 ok_sequence(WmF1Seq, "F1 press/release", FALSE); 9320 9321 trace("testing VK_APPS press/release\n"); 9322 keybd_event(VK_APPS, 0, 0, 0); 9323 keybd_event(VK_APPS, 0, KEYEVENTF_KEYUP, 0); 9324 pump_msg_loop(hwnd, 0); 9325 ok_sequence(WmVkAppsSeq, "VK_APPS press/release", FALSE); 9326 9327 trace("testing VK_F10 press/release\n"); 9328 keybd_event(VK_F10, 0, 0, 0); 9329 keybd_event(VK_F10, 0, KEYEVENTF_KEYUP, 0); 9330 keybd_event(VK_F10, 0, 0, 0); 9331 keybd_event(VK_F10, 0, KEYEVENTF_KEYUP, 0); 9332 pump_msg_loop(hwnd, 0); 9333 ok_sequence(WmVkF10Seq, "VK_F10 press/release", TRUE); 9334 9335 trace("testing SHIFT+F10 press/release\n"); 9336 keybd_event(VK_SHIFT, 0, 0, 0); 9337 keybd_event(VK_F10, 0, 0, 0); 9338 keybd_event(VK_F10, 0, KEYEVENTF_KEYUP, 0); 9339 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0); 9340 keybd_event(VK_ESCAPE, 0, 0, 0); 9341 keybd_event(VK_ESCAPE, 0, KEYEVENTF_KEYUP, 0); 9342 pump_msg_loop(hwnd, 0); 9343 ok_sequence(WmShiftF10Seq, "SHIFT+F10 press/release", TRUE); 9344 9345 trace("testing Shift+MouseButton press/release\n"); 9346 /* first, move mouse pointer inside of the window client area */ 9347 GetClientRect(hwnd, &rc); 9348 MapWindowPoints(hwnd, 0, (LPPOINT)&rc, 2); 9349 rc.left += (rc.right - rc.left)/2; 9350 rc.top += (rc.bottom - rc.top)/2; 9351 SetCursorPos(rc.left, rc.top); 9352 SetActiveWindow(hwnd); 9353 9354 flush_events(); 9355 flush_sequence(); 9356 GetCursorPos(&pt); 9357 if (pt.x == rc.left && pt.y == rc.top) 9358 { 9359 int i; 9360 keybd_event(VK_SHIFT, 0, 0, 0); 9361 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); 9362 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); 9363 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0); 9364 pump_msg_loop(hwnd, 0); 9365 for (i = 0; i < sequence_cnt; i++) if (sequence[i].message == WM_LBUTTONDOWN) break; 9366 if (i < sequence_cnt) 9367 ok_sequence(WmShiftMouseButton, "Shift+MouseButton press/release", FALSE); 9368 else 9369 skip( "Shift+MouseButton event didn't get to the window\n" ); 9370 } 9371 9372 done: 9373 if (hAccel) DestroyAcceleratorTable(hAccel); 9374 DestroyWindow(hwnd); 9375 } 9376 9377 /************* window procedures ********************/ 9378 9379 static LRESULT MsgCheckProc (BOOL unicode, HWND hwnd, UINT message, 9380 WPARAM wParam, LPARAM lParam) 9381 { 9382 static LONG defwndproc_counter = 0; 9383 static LONG beginpaint_counter = 0; 9384 LRESULT ret; 9385 struct recvd_message msg; 9386 9387 if (ignore_message( message )) return 0; 9388 9389 switch (message) 9390 { 9391 case WM_ENABLE: 9392 { 9393 LONG style = GetWindowLongA(hwnd, GWL_STYLE); 9394 ok((BOOL)wParam == !(style & WS_DISABLED), 9395 "wrong WS_DISABLED state: %ld != %d\n", wParam, !(style & WS_DISABLED)); 9396 break; 9397 } 9398 9399 case WM_CAPTURECHANGED: 9400 if (test_DestroyWindow_flag) 9401 { 9402 DWORD style = GetWindowLongA(hwnd, GWL_STYLE); 9403 if (style & WS_CHILD) 9404 lParam = GetWindowLongPtrA(hwnd, GWLP_ID); 9405 else if (style & WS_POPUP) 9406 lParam = WND_POPUP_ID; 9407 else 9408 lParam = WND_PARENT_ID; 9409 } 9410 break; 9411 9412 case WM_NCDESTROY: 9413 { 9414 HWND capture; 9415 9416 ok(!GetWindow(hwnd, GW_CHILD), "children should be unlinked at this point\n"); 9417 capture = GetCapture(); 9418 if (capture) 9419 { 9420 ok(capture == hwnd, "capture should NOT be released at this point (capture %p)\n", capture); 9421 trace("current capture %p, releasing...\n", capture); 9422 ReleaseCapture(); 9423 } 9424 } 9425 /* fall through */ 9426 case WM_DESTROY: 9427 if (pGetAncestor) 9428 ok(pGetAncestor(hwnd, GA_PARENT) != 0, "parent should NOT be unlinked at this point\n"); 9429 if (test_DestroyWindow_flag) 9430 { 9431 DWORD style = GetWindowLongA(hwnd, GWL_STYLE); 9432 if (style & WS_CHILD) 9433 lParam = GetWindowLongPtrA(hwnd, GWLP_ID); 9434 else if (style & WS_POPUP) 9435 lParam = WND_POPUP_ID; 9436 else 9437 lParam = WND_PARENT_ID; 9438 } 9439 break; 9440 9441 /* test_accelerators() depends on this */ 9442 case WM_NCHITTEST: 9443 return HTCLIENT; 9444 9445 case WM_USER+10: 9446 { 9447 ACTIVATION_CONTEXT_BASIC_INFORMATION basicinfo; 9448 HANDLE handle, event = (HANDLE)lParam; 9449 BOOL ret; 9450 9451 handle = (void*)0xdeadbeef; 9452 ret = pGetCurrentActCtx(&handle); 9453 ok(ret, "failed to get current context, %u\n", GetLastError()); 9454 ok(handle == 0, "got active context %p\n", handle); 9455 9456 memset(&basicinfo, 0xff, sizeof(basicinfo)); 9457 ret = pQueryActCtxW(QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX, handle, 0, ActivationContextBasicInformation, 9458 &basicinfo, sizeof(basicinfo), NULL); 9459 ok(ret, "got %d, error %d\n", ret, GetLastError()); 9460 ok(basicinfo.hActCtx == NULL, "got %p\n", basicinfo.hActCtx); 9461 ok(basicinfo.dwFlags == 0, "got %x\n", basicinfo.dwFlags); 9462 9463 if (event) SetEvent(event); 9464 return 1; 9465 } 9466 9467 /* ignore */ 9468 case WM_MOUSEMOVE: 9469 case WM_MOUSEACTIVATE: 9470 case WM_NCMOUSEMOVE: 9471 case WM_SETCURSOR: 9472 case WM_IME_SELECT: 9473 return 0; 9474 } 9475 9476 msg.hwnd = hwnd; 9477 msg.message = message; 9478 msg.flags = sent|wparam|lparam; 9479 if (defwndproc_counter) msg.flags |= defwinproc; 9480 if (beginpaint_counter) msg.flags |= beginpaint; 9481 msg.wParam = wParam; 9482 msg.lParam = lParam; 9483 msg.descr = "MsgCheckProc"; 9484 add_message(&msg); 9485 9486 if (message == WM_GETMINMAXINFO && (GetWindowLongA(hwnd, GWL_STYLE) & WS_CHILD)) 9487 { 9488 HWND parent = GetParent(hwnd); 9489 RECT rc; 9490 MINMAXINFO *minmax = (MINMAXINFO *)lParam; 9491 9492 GetClientRect(parent, &rc); 9493 trace("parent %p client size = (%d x %d)\n", parent, rc.right, rc.bottom); 9494 trace("Reserved=%d,%d MaxSize=%d,%d MaxPos=%d,%d MinTrack=%d,%d MaxTrack=%d,%d\n", 9495 minmax->ptReserved.x, minmax->ptReserved.y, 9496 minmax->ptMaxSize.x, minmax->ptMaxSize.y, 9497 minmax->ptMaxPosition.x, minmax->ptMaxPosition.y, 9498 minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y, 9499 minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y); 9500 9501 ok(minmax->ptMaxSize.x == rc.right, "default width of maximized child %d != %d\n", 9502 minmax->ptMaxSize.x, rc.right); 9503 ok(minmax->ptMaxSize.y == rc.bottom, "default height of maximized child %d != %d\n", 9504 minmax->ptMaxSize.y, rc.bottom); 9505 } 9506 9507 if (message == WM_PAINT) 9508 { 9509 PAINTSTRUCT ps; 9510 beginpaint_counter++; 9511 BeginPaint( hwnd, &ps ); 9512 beginpaint_counter--; 9513 EndPaint( hwnd, &ps ); 9514 return 0; 9515 } 9516 9517 if (message == WM_CONTEXTMENU) 9518 { 9519 /* don't create context menu */ 9520 return 0; 9521 } 9522 9523 defwndproc_counter++; 9524 ret = unicode ? DefWindowProcW(hwnd, message, wParam, lParam) 9525 : DefWindowProcA(hwnd, message, wParam, lParam); 9526 defwndproc_counter--; 9527 9528 return ret; 9529 } 9530 9531 static LRESULT WINAPI MsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 9532 { 9533 return MsgCheckProc (FALSE, hwnd, message, wParam, lParam); 9534 } 9535 9536 static LRESULT WINAPI MsgCheckProcW(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 9537 { 9538 return MsgCheckProc (TRUE, hwnd, message, wParam, lParam); 9539 } 9540 9541 static LRESULT WINAPI PopupMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 9542 { 9543 static LONG defwndproc_counter = 0; 9544 LRESULT ret; 9545 struct recvd_message msg; 9546 9547 if (ignore_message( message )) return 0; 9548 9549 switch (message) 9550 { 9551 case WM_QUERYENDSESSION: 9552 case WM_ENDSESSION: 9553 lParam &= ~0x01; /* Vista adds a 0x01 flag */ 9554 break; 9555 } 9556 9557 msg.hwnd = hwnd; 9558 msg.message = message; 9559 msg.flags = sent|wparam|lparam; 9560 if (defwndproc_counter) msg.flags |= defwinproc; 9561 msg.wParam = wParam; 9562 msg.lParam = lParam; 9563 msg.descr = "popup"; 9564 add_message(&msg); 9565 9566 if (message == WM_CREATE) 9567 { 9568 DWORD style = GetWindowLongA(hwnd, GWL_STYLE) | WS_VISIBLE; 9569 SetWindowLongA(hwnd, GWL_STYLE, style); 9570 } 9571 9572 defwndproc_counter++; 9573 ret = DefWindowProcA(hwnd, message, wParam, lParam); 9574 defwndproc_counter--; 9575 9576 return ret; 9577 } 9578 9579 static LRESULT WINAPI ParentMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 9580 { 9581 static LONG defwndproc_counter = 0; 9582 static LONG beginpaint_counter = 0; 9583 LRESULT ret; 9584 struct recvd_message msg; 9585 9586 if (ignore_message( message )) return 0; 9587 9588 if (log_all_parent_messages || 9589 message == WM_PARENTNOTIFY || message == WM_CANCELMODE || 9590 message == WM_SETFOCUS || message == WM_KILLFOCUS || 9591 message == WM_ENABLE || message == WM_ENTERIDLE || 9592 message == WM_DRAWITEM || message == WM_MEASUREITEM || message == WM_COMPAREITEM || 9593 message == WM_COMMAND || message == WM_IME_SETCONTEXT) 9594 { 9595 switch (message) 9596 { 9597 /* ignore */ 9598 case WM_NCHITTEST: 9599 return HTCLIENT; 9600 case WM_SETCURSOR: 9601 case WM_MOUSEMOVE: 9602 case WM_NCMOUSEMOVE: 9603 return 0; 9604 9605 case WM_ERASEBKGND: 9606 { 9607 RECT rc; 9608 INT ret = GetClipBox((HDC)wParam, &rc); 9609 9610 trace("WM_ERASEBKGND: GetClipBox()=%d, %s\n", ret, wine_dbgstr_rect(&rc)); 9611 break; 9612 } 9613 } 9614 9615 msg.hwnd = hwnd; 9616 msg.message = message; 9617 msg.flags = sent|parent|wparam|lparam; 9618 if (defwndproc_counter) msg.flags |= defwinproc; 9619 if (beginpaint_counter) msg.flags |= beginpaint; 9620 msg.wParam = wParam; 9621 msg.lParam = lParam; 9622 msg.descr = "parent"; 9623 add_message(&msg); 9624 } 9625 9626 if (message == WM_PAINT) 9627 { 9628 PAINTSTRUCT ps; 9629 beginpaint_counter++; 9630 BeginPaint( hwnd, &ps ); 9631 beginpaint_counter--; 9632 EndPaint( hwnd, &ps ); 9633 return 0; 9634 } 9635 9636 defwndproc_counter++; 9637 ret = DefWindowProcA(hwnd, message, wParam, lParam); 9638 defwndproc_counter--; 9639 9640 return message == WM_COMPAREITEM ? -1 : ret; 9641 } 9642 9643 static INT_PTR CALLBACK StopQuitMsgCheckProcA(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) 9644 { 9645 if (message == WM_CREATE) 9646 PostMessageA(hwnd, WM_CLOSE, 0, 0); 9647 else if (message == WM_CLOSE) 9648 { 9649 /* Only the first WM_QUIT will survive the window destruction */ 9650 PostMessageA(hwnd, WM_USER, 0x1234, 0x5678); 9651 PostMessageA(hwnd, WM_QUIT, 0x1234, 0x5678); 9652 PostMessageA(hwnd, WM_QUIT, 0x4321, 0x8765); 9653 } 9654 9655 return DefWindowProcA(hwnd, message, wp, lp); 9656 } 9657 9658 static LRESULT WINAPI TestDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 9659 { 9660 static LONG defwndproc_counter = 0; 9661 LRESULT ret; 9662 struct recvd_message msg; 9663 9664 if (ignore_message( message )) return 0; 9665 9666 if (test_def_id) 9667 { 9668 DefDlgProcA(hwnd, DM_SETDEFID, 1, 0); 9669 ret = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0); 9670 if (after_end_dialog) 9671 ok( ret == 0, "DM_GETDEFID should return 0 after EndDialog, got %lx\n", ret ); 9672 else 9673 ok(HIWORD(ret) == DC_HASDEFID, "DM_GETDEFID should return DC_HASDEFID, got %lx\n", ret); 9674 } 9675 9676 msg.hwnd = hwnd; 9677 msg.message = message; 9678 msg.flags = sent|wparam|lparam; 9679 if (defwndproc_counter) msg.flags |= defwinproc; 9680 msg.wParam = wParam; 9681 msg.lParam = lParam; 9682 msg.descr = "dialog"; 9683 add_message(&msg); 9684 9685 defwndproc_counter++; 9686 ret = DefDlgProcA(hwnd, message, wParam, lParam); 9687 defwndproc_counter--; 9688 9689 return ret; 9690 } 9691 9692 static LRESULT WINAPI ShowWindowProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 9693 { 9694 static LONG defwndproc_counter = 0; 9695 LRESULT ret; 9696 struct recvd_message msg; 9697 9698 /* log only specific messages we are interested in */ 9699 switch (message) 9700 { 9701 #if 0 /* probably log these as well */ 9702 case WM_ACTIVATE: 9703 case WM_SETFOCUS: 9704 case WM_KILLFOCUS: 9705 #endif 9706 case WM_SHOWWINDOW: 9707 case WM_SIZE: 9708 case WM_MOVE: 9709 case WM_GETMINMAXINFO: 9710 case WM_WINDOWPOSCHANGING: 9711 case WM_WINDOWPOSCHANGED: 9712 break; 9713 9714 default: /* ignore */ 9715 /*trace("showwindow: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);*/ 9716 return DefWindowProcA(hwnd, message, wParam, lParam); 9717 } 9718 9719 msg.hwnd = hwnd; 9720 msg.message = message; 9721 msg.flags = sent|wparam|lparam; 9722 if (defwndproc_counter) msg.flags |= defwinproc; 9723 msg.wParam = wParam; 9724 msg.lParam = lParam; 9725 msg.descr = "show"; 9726 add_message(&msg); 9727 9728 defwndproc_counter++; 9729 ret = DefWindowProcA(hwnd, message, wParam, lParam); 9730 defwndproc_counter--; 9731 9732 return ret; 9733 } 9734 9735 static LRESULT WINAPI recursive_activation_wndprocA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 9736 { 9737 static LONG defwndproc_counter = 0; 9738 struct recvd_message msg; 9739 LRESULT ret; 9740 9741 switch (message) 9742 { 9743 /* log only specific messages we are interested in */ 9744 case WM_NCACTIVATE: 9745 case WM_ACTIVATE: 9746 case WM_SETFOCUS: 9747 case WM_KILLFOCUS: 9748 break; 9749 default: 9750 return DefWindowProcA(hwnd, message, wParam, lParam); 9751 } 9752 9753 msg.hwnd = hwnd; 9754 msg.message = message; 9755 msg.flags = sent|wparam|lparam; 9756 if (defwndproc_counter) msg.flags |= defwinproc; 9757 msg.wParam = wParam; 9758 msg.lParam = lParam; 9759 msg.descr = "recursive_activation"; 9760 add_message(&msg); 9761 9762 /* recursively activate ourselves by first losing activation and changing it back */ 9763 if (message == WM_ACTIVATE && LOWORD(wParam) != WA_INACTIVE) 9764 { 9765 SetActiveWindow((HWND)lParam); 9766 SetActiveWindow(hwnd); 9767 return 0; 9768 } 9769 9770 defwndproc_counter++; 9771 ret = DefWindowProcA(hwnd, message, wParam, lParam); 9772 defwndproc_counter--; 9773 9774 return ret; 9775 } 9776 9777 static LRESULT WINAPI PaintLoopProcA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) 9778 { 9779 switch (msg) 9780 { 9781 case WM_CREATE: return 0; 9782 case WM_PAINT: 9783 { 9784 MSG msg2; 9785 static int i = 0; 9786 9787 if (i < 256) 9788 { 9789 i++; 9790 if (PeekMessageA(&msg2, 0, 0, 0, 1)) 9791 { 9792 TranslateMessage(&msg2); 9793 DispatchMessageA(&msg2); 9794 } 9795 i--; 9796 } 9797 else ok(broken(1), "infinite loop\n"); 9798 if ( i == 0) 9799 paint_loop_done = TRUE; 9800 return DefWindowProcA(hWnd,msg,wParam,lParam); 9801 } 9802 } 9803 return DefWindowProcA(hWnd,msg,wParam,lParam); 9804 } 9805 9806 static LRESULT WINAPI HotkeyMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 9807 { 9808 static LONG defwndproc_counter = 0; 9809 LRESULT ret; 9810 struct recvd_message msg; 9811 DWORD queue_status; 9812 9813 if (ignore_message( message )) return 0; 9814 9815 if ((message >= WM_KEYFIRST && message <= WM_KEYLAST) || 9816 message == WM_HOTKEY || message >= WM_APP) 9817 { 9818 msg.hwnd = hwnd; 9819 msg.message = message; 9820 msg.flags = sent|wparam|lparam; 9821 if (defwndproc_counter) msg.flags |= defwinproc; 9822 msg.wParam = wParam; 9823 msg.lParam = lParam; 9824 msg.descr = "HotkeyMsgCheckProcA"; 9825 add_message(&msg); 9826 } 9827 9828 defwndproc_counter++; 9829 ret = DefWindowProcA(hwnd, message, wParam, lParam); 9830 defwndproc_counter--; 9831 9832 if (message == WM_APP) 9833 { 9834 queue_status = GetQueueStatus(QS_HOTKEY); 9835 ok((queue_status & (QS_HOTKEY << 16)) == QS_HOTKEY << 16, "expected QS_HOTKEY << 16 set, got %x\n", queue_status); 9836 queue_status = GetQueueStatus(QS_POSTMESSAGE); 9837 ok((queue_status & (QS_POSTMESSAGE << 16)) == QS_POSTMESSAGE << 16, "expected QS_POSTMESSAGE << 16 set, got %x\n", queue_status); 9838 PostMessageA(hwnd, WM_APP+1, 0, 0); 9839 } 9840 else if (message == WM_APP+1) 9841 { 9842 queue_status = GetQueueStatus(QS_HOTKEY); 9843 ok((queue_status & (QS_HOTKEY << 16)) == 0, "expected QS_HOTKEY << 16 cleared, got %x\n", queue_status); 9844 } 9845 9846 return ret; 9847 } 9848 9849 static BOOL RegisterWindowClasses(void) 9850 { 9851 WNDCLASSA cls; 9852 WNDCLASSW clsW; 9853 9854 cls.style = 0; 9855 cls.lpfnWndProc = MsgCheckProcA; 9856 cls.cbClsExtra = 0; 9857 cls.cbWndExtra = 0; 9858 cls.hInstance = GetModuleHandleA(0); 9859 cls.hIcon = 0; 9860 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 9861 cls.hbrBackground = GetStockObject(WHITE_BRUSH); 9862 cls.lpszMenuName = NULL; 9863 cls.lpszClassName = "TestWindowClass"; 9864 if(!RegisterClassA(&cls)) return FALSE; 9865 9866 cls.lpfnWndProc = HotkeyMsgCheckProcA; 9867 cls.lpszClassName = "HotkeyWindowClass"; 9868 if(!RegisterClassA(&cls)) return FALSE; 9869 9870 cls.lpfnWndProc = ShowWindowProcA; 9871 cls.lpszClassName = "ShowWindowClass"; 9872 if(!RegisterClassA(&cls)) return FALSE; 9873 9874 cls.lpfnWndProc = recursive_activation_wndprocA; 9875 cls.lpszClassName = "RecursiveActivationClass"; 9876 if(!RegisterClassA(&cls)) return FALSE; 9877 9878 cls.lpfnWndProc = PopupMsgCheckProcA; 9879 cls.lpszClassName = "TestPopupClass"; 9880 if(!RegisterClassA(&cls)) return FALSE; 9881 9882 cls.lpfnWndProc = ParentMsgCheckProcA; 9883 cls.lpszClassName = "TestParentClass"; 9884 if(!RegisterClassA(&cls)) return FALSE; 9885 9886 cls.lpfnWndProc = StopQuitMsgCheckProcA; 9887 cls.lpszClassName = "StopQuitClass"; 9888 if(!RegisterClassA(&cls)) return FALSE; 9889 9890 cls.lpfnWndProc = DefWindowProcA; 9891 cls.lpszClassName = "SimpleWindowClass"; 9892 if(!RegisterClassA(&cls)) return FALSE; 9893 9894 cls.lpfnWndProc = PaintLoopProcA; 9895 cls.lpszClassName = "PaintLoopWindowClass"; 9896 if(!RegisterClassA(&cls)) return FALSE; 9897 9898 cls.style = CS_NOCLOSE; 9899 cls.lpszClassName = "NoCloseWindowClass"; 9900 if(!RegisterClassA(&cls)) return FALSE; 9901 9902 ok(GetClassInfoA(0, "#32770", &cls), "GetClassInfo failed\n"); 9903 cls.style = 0; 9904 cls.hInstance = GetModuleHandleA(0); 9905 cls.hbrBackground = 0; 9906 cls.lpfnWndProc = TestDlgProcA; 9907 cls.lpszClassName = "TestDialogClass"; 9908 if(!RegisterClassA(&cls)) return FALSE; 9909 9910 clsW.style = 0; 9911 clsW.lpfnWndProc = MsgCheckProcW; 9912 clsW.cbClsExtra = 0; 9913 clsW.cbWndExtra = 0; 9914 clsW.hInstance = GetModuleHandleW(0); 9915 clsW.hIcon = 0; 9916 clsW.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW); 9917 clsW.hbrBackground = GetStockObject(WHITE_BRUSH); 9918 clsW.lpszMenuName = NULL; 9919 clsW.lpszClassName = testWindowClassW; 9920 RegisterClassW(&clsW); /* ignore error, this fails on Win9x */ 9921 9922 return TRUE; 9923 } 9924 9925 static BOOL is_our_logged_class(HWND hwnd) 9926 { 9927 char buf[256]; 9928 9929 if (GetClassNameA(hwnd, buf, sizeof(buf))) 9930 { 9931 if (!lstrcmpiA(buf, "TestWindowClass") || 9932 !lstrcmpiA(buf, "ShowWindowClass") || 9933 !lstrcmpiA(buf, "RecursiveActivationClass") || 9934 !lstrcmpiA(buf, "TestParentClass") || 9935 !lstrcmpiA(buf, "TestPopupClass") || 9936 !lstrcmpiA(buf, "SimpleWindowClass") || 9937 !lstrcmpiA(buf, "TestDialogClass") || 9938 !lstrcmpiA(buf, "MDI_frame_class") || 9939 !lstrcmpiA(buf, "MDI_client_class") || 9940 !lstrcmpiA(buf, "MDI_child_class") || 9941 !lstrcmpiA(buf, "my_button_class") || 9942 !lstrcmpiA(buf, "my_edit_class") || 9943 !lstrcmpiA(buf, "static") || 9944 !lstrcmpiA(buf, "ListBox") || 9945 !lstrcmpiA(buf, "ComboBox") || 9946 !lstrcmpiA(buf, "MyDialogClass") || 9947 !lstrcmpiA(buf, "#32770") || 9948 !lstrcmpiA(buf, "#32768")) 9949 return TRUE; 9950 } 9951 return FALSE; 9952 } 9953 9954 static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam) 9955 { 9956 HWND hwnd; 9957 9958 ok(cbt_hook_thread_id == GetCurrentThreadId(), "we didn't ask for events from other threads\n"); 9959 9960 if (nCode == HCBT_CLICKSKIPPED) 9961 { 9962 /* ignore this event, XP sends it a lot when switching focus between windows */ 9963 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam); 9964 } 9965 9966 if (nCode == HCBT_SYSCOMMAND || nCode == HCBT_KEYSKIPPED) 9967 { 9968 struct recvd_message msg; 9969 9970 msg.hwnd = 0; 9971 msg.message = nCode; 9972 msg.flags = hook|wparam|lparam; 9973 msg.wParam = wParam; 9974 msg.lParam = lParam; 9975 msg.descr = "CBT"; 9976 add_message(&msg); 9977 9978 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam); 9979 } 9980 9981 if (nCode == HCBT_DESTROYWND) 9982 { 9983 if (test_DestroyWindow_flag) 9984 { 9985 DWORD style = GetWindowLongA((HWND)wParam, GWL_STYLE); 9986 if (style & WS_CHILD) 9987 lParam = GetWindowLongPtrA((HWND)wParam, GWLP_ID); 9988 else if (style & WS_POPUP) 9989 lParam = WND_POPUP_ID; 9990 else 9991 lParam = WND_PARENT_ID; 9992 } 9993 } 9994 9995 /* Log also SetFocus(0) calls */ 9996 hwnd = wParam ? (HWND)wParam : (HWND)lParam; 9997 9998 if (is_our_logged_class(hwnd)) 9999 { 10000 struct recvd_message msg; 10001 10002 msg.hwnd = hwnd; 10003 msg.message = nCode; 10004 msg.flags = hook|wparam|lparam; 10005 msg.wParam = wParam; 10006 msg.lParam = lParam; 10007 msg.descr = "CBT"; 10008 add_message(&msg); 10009 } 10010 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam); 10011 } 10012 10013 static void CALLBACK win_event_proc(HWINEVENTHOOK hevent, 10014 DWORD event, 10015 HWND hwnd, 10016 LONG object_id, 10017 LONG child_id, 10018 DWORD thread_id, 10019 DWORD event_time) 10020 { 10021 ok(thread_id == GetCurrentThreadId(), "we didn't ask for events from other threads\n"); 10022 10023 /* ignore mouse cursor events */ 10024 if (object_id == OBJID_CURSOR) return; 10025 10026 if (!hwnd || is_our_logged_class(hwnd)) 10027 { 10028 struct recvd_message msg; 10029 10030 msg.hwnd = hwnd; 10031 msg.message = event; 10032 msg.flags = winevent_hook|wparam|lparam; 10033 msg.wParam = object_id; 10034 msg.lParam = child_id; 10035 msg.descr = "WEH"; 10036 add_message(&msg); 10037 } 10038 } 10039 10040 static const WCHAR wszUnicode[] = {'U','n','i','c','o','d','e',0}; 10041 static const WCHAR wszAnsi[] = {'U',0}; 10042 10043 static LRESULT CALLBACK MsgConversionProcW(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 10044 { 10045 switch (uMsg) 10046 { 10047 case CB_FINDSTRINGEXACT: 10048 trace("String: %p\n", (LPCWSTR)lParam); 10049 if (!lstrcmpW((LPCWSTR)lParam, wszUnicode)) 10050 return 1; 10051 if (!lstrcmpW((LPCWSTR)lParam, wszAnsi)) 10052 return 0; 10053 return -1; 10054 } 10055 return DefWindowProcW(hwnd, uMsg, wParam, lParam); 10056 } 10057 10058 static const struct message WmGetTextLengthAfromW[] = { 10059 { WM_GETTEXTLENGTH, sent }, 10060 { WM_GETTEXT, sent|optional }, 10061 { 0 } 10062 }; 10063 10064 static const WCHAR dummy_window_text[] = {'d','u','m','m','y',' ','t','e','x','t',0}; 10065 10066 /* dummy window proc for WM_GETTEXTLENGTH test */ 10067 static LRESULT CALLBACK get_text_len_proc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ) 10068 { 10069 switch(msg) 10070 { 10071 case WM_GETTEXTLENGTH: 10072 return lstrlenW(dummy_window_text) + 37; /* some random length */ 10073 case WM_GETTEXT: 10074 lstrcpynW( (LPWSTR)lp, dummy_window_text, wp ); 10075 return lstrlenW( (LPWSTR)lp ); 10076 default: 10077 return DefWindowProcW( hwnd, msg, wp, lp ); 10078 } 10079 } 10080 10081 static void test_message_conversion(void) 10082 { 10083 static const WCHAR wszMsgConversionClass[] = 10084 {'M','s','g','C','o','n','v','e','r','s','i','o','n','C','l','a','s','s',0}; 10085 WNDCLASSW cls; 10086 LRESULT lRes; 10087 HWND hwnd; 10088 WNDPROC wndproc, newproc; 10089 BOOL ret; 10090 10091 cls.style = 0; 10092 cls.lpfnWndProc = MsgConversionProcW; 10093 cls.cbClsExtra = 0; 10094 cls.cbWndExtra = 0; 10095 cls.hInstance = GetModuleHandleW(NULL); 10096 cls.hIcon = NULL; 10097 cls.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW); 10098 cls.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1); 10099 cls.lpszMenuName = NULL; 10100 cls.lpszClassName = wszMsgConversionClass; 10101 /* this call will fail on Win9x, but that doesn't matter as this test is 10102 * meaningless on those platforms */ 10103 if(!RegisterClassW(&cls)) return; 10104 10105 hwnd = CreateWindowExW(0, wszMsgConversionClass, NULL, WS_OVERLAPPED, 10106 100, 100, 200, 200, 0, 0, 0, NULL); 10107 ok(hwnd != NULL, "Window creation failed\n"); 10108 10109 /* {W, A} -> A */ 10110 10111 wndproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_WNDPROC); 10112 lRes = CallWindowProcA(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); 10113 ok(lRes == 0, "String should have been converted\n"); 10114 lRes = CallWindowProcW(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); 10115 ok(lRes == 1, "String shouldn't have been converted\n"); 10116 10117 /* {W, A} -> W */ 10118 10119 wndproc = (WNDPROC)GetWindowLongPtrW(hwnd, GWLP_WNDPROC); 10120 lRes = CallWindowProcA(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); 10121 ok(lRes == 1, "String shouldn't have been converted\n"); 10122 lRes = CallWindowProcW(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); 10123 ok(lRes == 1, "String shouldn't have been converted\n"); 10124 10125 /* Synchronous messages */ 10126 10127 lRes = SendMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); 10128 ok(lRes == 0, "String should have been converted\n"); 10129 lRes = SendMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); 10130 ok(lRes == 1, "String shouldn't have been converted\n"); 10131 10132 /* Asynchronous messages */ 10133 10134 SetLastError(0); 10135 lRes = PostMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); 10136 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER), 10137 "PostMessage on sync only message returned %ld, last error %d\n", lRes, GetLastError()); 10138 SetLastError(0); 10139 lRes = PostMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); 10140 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER), 10141 "PostMessage on sync only message returned %ld, last error %d\n", lRes, GetLastError()); 10142 SetLastError(0); 10143 lRes = PostThreadMessageA(GetCurrentThreadId(), CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); 10144 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER), 10145 "PosThreadtMessage on sync only message returned %ld, last error %d\n", lRes, GetLastError()); 10146 SetLastError(0); 10147 lRes = PostThreadMessageW(GetCurrentThreadId(), CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); 10148 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER), 10149 "PosThreadtMessage on sync only message returned %ld, last error %d\n", lRes, GetLastError()); 10150 SetLastError(0); 10151 lRes = SendNotifyMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); 10152 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER), 10153 "SendNotifyMessage on sync only message returned %ld, last error %d\n", lRes, GetLastError()); 10154 SetLastError(0); 10155 lRes = SendNotifyMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); 10156 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER), 10157 "SendNotifyMessage on sync only message returned %ld, last error %d\n", lRes, GetLastError()); 10158 SetLastError(0); 10159 lRes = SendMessageCallbackA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode, NULL, 0); 10160 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER), 10161 "SendMessageCallback on sync only message returned %ld, last error %d\n", lRes, GetLastError()); 10162 SetLastError(0); 10163 lRes = SendMessageCallbackW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode, NULL, 0); 10164 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER), 10165 "SendMessageCallback on sync only message returned %ld, last error %d\n", lRes, GetLastError()); 10166 10167 /* Check WM_GETTEXTLENGTH A->W behaviour, whether WM_GETTEXT is also sent or not */ 10168 10169 hwnd = CreateWindowW (testWindowClassW, wszUnicode, 10170 WS_OVERLAPPEDWINDOW, 10171 100, 100, 200, 200, 0, 0, 0, NULL); 10172 assert(hwnd); 10173 flush_sequence(); 10174 lRes = SendMessageA (hwnd, WM_GETTEXTLENGTH, 0, 0); 10175 ok_sequence(WmGetTextLengthAfromW, "ANSI WM_GETTEXTLENGTH to Unicode window", FALSE); 10176 ok( lRes == WideCharToMultiByte( CP_ACP, 0, wszUnicode, lstrlenW(wszUnicode), NULL, 0, NULL, NULL ), 10177 "got bad length %ld\n", lRes ); 10178 10179 flush_sequence(); 10180 lRes = CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ), 10181 hwnd, WM_GETTEXTLENGTH, 0, 0); 10182 ok_sequence(WmGetTextLengthAfromW, "ANSI WM_GETTEXTLENGTH to Unicode window", FALSE); 10183 ok( lRes == WideCharToMultiByte( CP_ACP, 0, wszUnicode, lstrlenW(wszUnicode), NULL, 0, NULL, NULL ), 10184 "got bad length %ld\n", lRes ); 10185 10186 wndproc = (WNDPROC)SetWindowLongPtrW( hwnd, GWLP_WNDPROC, (LONG_PTR)get_text_len_proc ); 10187 newproc = (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ); 10188 lRes = CallWindowProcA( newproc, hwnd, WM_GETTEXTLENGTH, 0, 0 ); 10189 ok( lRes == WideCharToMultiByte( CP_ACP, 0, dummy_window_text, lstrlenW(dummy_window_text), 10190 NULL, 0, NULL, NULL ) || 10191 broken(lRes == lstrlenW(dummy_window_text) + 37), 10192 "got bad length %ld\n", lRes ); 10193 10194 SetWindowLongPtrW( hwnd, GWLP_WNDPROC, (LONG_PTR)wndproc ); /* restore old wnd proc */ 10195 lRes = CallWindowProcA( newproc, hwnd, WM_GETTEXTLENGTH, 0, 0 ); 10196 ok( lRes == WideCharToMultiByte( CP_ACP, 0, dummy_window_text, lstrlenW(dummy_window_text), 10197 NULL, 0, NULL, NULL ) || 10198 broken(lRes == lstrlenW(dummy_window_text) + 37), 10199 "got bad length %ld\n", lRes ); 10200 10201 ret = DestroyWindow(hwnd); 10202 ok( ret, "DestroyWindow() error %d\n", GetLastError()); 10203 } 10204 10205 struct timer_info 10206 { 10207 HWND hWnd; 10208 HANDLE handles[2]; 10209 DWORD id; 10210 }; 10211 10212 static VOID CALLBACK tfunc(HWND hwnd, UINT uMsg, UINT_PTR id, DWORD dwTime) 10213 { 10214 } 10215 10216 #define TIMER_ID 0x19 10217 #define TIMER_COUNT_EXPECTED 100 10218 #define TIMER_COUNT_TOLERANCE 10 10219 10220 static int count = 0; 10221 static void CALLBACK callback_count(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) 10222 { 10223 count++; 10224 } 10225 10226 static DWORD exception; 10227 static void CALLBACK callback_exception(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) 10228 { 10229 count++; 10230 RaiseException(exception, 0, 0, NULL); 10231 } 10232 10233 static DWORD WINAPI timer_thread_proc(LPVOID x) 10234 { 10235 struct timer_info *info = x; 10236 DWORD r; 10237 10238 r = KillTimer(info->hWnd, 0x19); 10239 ok(r,"KillTimer failed in thread\n"); 10240 r = SetTimer(info->hWnd,TIMER_ID,10000,tfunc); 10241 ok(r,"SetTimer failed in thread\n"); 10242 ok(r==TIMER_ID,"SetTimer id different\n"); 10243 r = SetEvent(info->handles[0]); 10244 ok(r,"SetEvent failed in thread\n"); 10245 return 0; 10246 } 10247 10248 static void test_timers(void) 10249 { 10250 struct timer_info info; 10251 DWORD start; 10252 DWORD id; 10253 MSG msg; 10254 10255 info.hWnd = CreateWindowA("TestWindowClass", NULL, 10256 WS_OVERLAPPEDWINDOW , 10257 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0, 10258 NULL, NULL, 0); 10259 10260 info.id = SetTimer(info.hWnd,TIMER_ID,10000,tfunc); 10261 ok(info.id, "SetTimer failed\n"); 10262 ok(info.id==TIMER_ID, "SetTimer timer ID different\n"); 10263 info.handles[0] = CreateEventW(NULL,0,0,NULL); 10264 info.handles[1] = CreateThread(NULL,0,timer_thread_proc,&info,0,&id); 10265 10266 WaitForMultipleObjects(2, info.handles, FALSE, INFINITE); 10267 10268 WaitForSingleObject(info.handles[1], INFINITE); 10269 10270 CloseHandle(info.handles[0]); 10271 CloseHandle(info.handles[1]); 10272 10273 ok( KillTimer(info.hWnd, TIMER_ID), "KillTimer failed\n"); 10274 10275 /* Check the minimum allowed timeout for a timer. MSDN indicates that it should be 10.0 ms, 10276 * which occurs sometimes, but most testing on the VMs indicates a minimum timeout closer to 10277 * 15.6 ms. Since there is some measurement error between test runs we are allowing for 10278 * ±9 counts (~4 ms) around the expected value. 10279 */ 10280 count = 0; 10281 id = SetTimer(info.hWnd, TIMER_ID, 0, callback_count); 10282 ok(id != 0, "did not get id from SetTimer.\n"); 10283 ok(id==TIMER_ID, "SetTimer timer ID different\n"); 10284 start = GetTickCount(); 10285 while (GetTickCount()-start < 1001 && GetMessageA(&msg, info.hWnd, 0, 0)) 10286 DispatchMessageA(&msg); 10287 ros_skip_flaky 10288 todo_wine 10289 ok(abs(count-TIMER_COUNT_EXPECTED) < TIMER_COUNT_TOLERANCE /* xp */ 10290 || broken(abs(count-64) < TIMER_COUNT_TOLERANCE) /* most common */ 10291 || broken(abs(count-43) < TIMER_COUNT_TOLERANCE) /* w2k3, win8 */, 10292 "did not get expected count for minimum timeout (%d != ~%d).\n", 10293 count, TIMER_COUNT_EXPECTED); 10294 ok(KillTimer(info.hWnd, id), "KillTimer failed\n"); 10295 /* Perform the same check on SetSystemTimer (only available on w2k3 and older) */ 10296 if (pSetSystemTimer) 10297 { 10298 int syscount = 0; 10299 10300 count = 0; 10301 id = pSetSystemTimer(info.hWnd, TIMER_ID, 0, callback_count); 10302 ok(id != 0, "did not get id from SetSystemTimer.\n"); 10303 ok(id==TIMER_ID, "SetTimer timer ID different\n"); 10304 start = GetTickCount(); 10305 while (GetTickCount()-start < 1001 && GetMessageA(&msg, info.hWnd, 0, 0)) 10306 { 10307 if (msg.message == WM_SYSTIMER) 10308 syscount++; 10309 DispatchMessageA(&msg); 10310 } 10311 ok(abs(syscount-TIMER_COUNT_EXPECTED) < TIMER_COUNT_TOLERANCE 10312 || broken(abs(syscount-64) < TIMER_COUNT_TOLERANCE) /* most common */ 10313 || broken(syscount > 4000 && syscount < 12000) /* win2k3sp0 */, 10314 "did not get expected count for minimum timeout (%d != ~%d).\n", 10315 syscount, TIMER_COUNT_EXPECTED); 10316 todo_wine ok(count == 0, "did not get expected count for callback timeout (%d != 0).\n", 10317 count); 10318 ok(pKillSystemTimer(info.hWnd, id), "KillSystemTimer failed\n"); 10319 } 10320 10321 ok(DestroyWindow(info.hWnd), "failed to destroy window\n"); 10322 } 10323 10324 static void test_timers_no_wnd(void) 10325 { 10326 static UINT_PTR ids[0xffff]; 10327 UINT_PTR id, id2; 10328 DWORD start; 10329 MSG msg; 10330 int i; 10331 10332 count = 0; 10333 id = SetTimer(NULL, 0, 100, callback_count); 10334 ok(id != 0, "did not get id from SetTimer.\n"); 10335 id2 = SetTimer(NULL, id, 200, callback_count); 10336 ok(id2 == id, "did not get same id from SetTimer when replacing (%li expected %li).\n", id2, id); 10337 Sleep(150); 10338 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 10339 ok(count == 0, "did not get zero count as expected (%i).\n", count); 10340 Sleep(150); 10341 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 10342 ok(count == 1, "did not get one count as expected (%i).\n", count); 10343 KillTimer(NULL, id); 10344 Sleep(250); 10345 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 10346 ok(count == 1, "killing replaced timer did not work (%i).\n", count); 10347 10348 /* Check the minimum allowed timeout for a timer. MSDN indicates that it should be 10.0 ms, 10349 * which occurs sometimes, but most testing on the VMs indicates a minimum timeout closer to 10350 * 15.6 ms. Since there is some measurement error between test runs we are allowing for 10351 * ±9 counts (~4 ms) around the expected value. 10352 */ 10353 count = 0; 10354 id = SetTimer(NULL, 0, 0, callback_count); 10355 ok(id != 0, "did not get id from SetTimer.\n"); 10356 start = GetTickCount(); 10357 while (GetTickCount()-start < 1001 && GetMessageA(&msg, NULL, 0, 0)) 10358 DispatchMessageA(&msg); 10359 todo_wine 10360 ok(abs(count-TIMER_COUNT_EXPECTED) < TIMER_COUNT_TOLERANCE /* xp */ 10361 || broken(abs(count-64) < TIMER_COUNT_TOLERANCE) /* most common */, 10362 "did not get expected count for minimum timeout (%d != ~%d).\n", 10363 count, TIMER_COUNT_EXPECTED); 10364 KillTimer(NULL, id); 10365 /* Note: SetSystemTimer doesn't support a NULL window, see test_timers */ 10366 10367 if (pSetCoalescableTimer) 10368 { 10369 count = 0; 10370 id = pSetCoalescableTimer(NULL, 0, 0, callback_count, 0); 10371 ok(id != 0, "SetCoalescableTimer failed with %u.\n", GetLastError()); 10372 start = GetTickCount(); 10373 while (GetTickCount()-start < 100 && GetMessageA(&msg, NULL, 0, 0)) 10374 DispatchMessageA(&msg); 10375 ok(count > 1, "expected count > 1, got %d.\n", count); 10376 KillTimer(NULL, id); 10377 } 10378 else 10379 win_skip("SetCoalescableTimer not available.\n"); 10380 10381 /* Check what happens when we're running out of timers */ 10382 for (i = 0; i < ARRAY_SIZE(ids); i++) 10383 { 10384 SetLastError(0xdeadbeef); 10385 ids[i] = SetTimer(NULL, 0, USER_TIMER_MAXIMUM, tfunc); 10386 if (!ids[i]) break; 10387 } 10388 ok(i != ARRAY_SIZE(ids), "all timers were created successfully\n"); 10389 ok(GetLastError()==ERROR_NO_MORE_USER_HANDLES || broken(GetLastError()==0xdeadbeef), 10390 "GetLastError() = %d\n", GetLastError()); 10391 while (i > 0) KillTimer(NULL, ids[--i]); 10392 } 10393 10394 static void test_timers_exception(DWORD code) 10395 { 10396 UINT_PTR id; 10397 MSG msg; 10398 10399 exception = code; 10400 id = SetTimer(NULL, 0, 1000, callback_exception); 10401 ok(id != 0, "did not get id from SetTimer.\n"); 10402 10403 memset(&msg, 0, sizeof(msg)); 10404 msg.message = WM_TIMER; 10405 msg.wParam = id; 10406 msg.lParam = (LPARAM)callback_exception; 10407 10408 count = 0; 10409 DispatchMessageA(&msg); 10410 ok(count == 1, "did not get one count as expected (%i).\n", count); 10411 10412 KillTimer(NULL, id); 10413 } 10414 10415 static void test_timers_exceptions(void) 10416 { 10417 test_timers_exception(EXCEPTION_ACCESS_VIOLATION); 10418 test_timers_exception(EXCEPTION_DATATYPE_MISALIGNMENT); 10419 test_timers_exception(EXCEPTION_BREAKPOINT); 10420 test_timers_exception(EXCEPTION_SINGLE_STEP); 10421 test_timers_exception(EXCEPTION_ARRAY_BOUNDS_EXCEEDED); 10422 test_timers_exception(EXCEPTION_FLT_DENORMAL_OPERAND); 10423 test_timers_exception(EXCEPTION_FLT_DIVIDE_BY_ZERO); 10424 test_timers_exception(EXCEPTION_FLT_INEXACT_RESULT); 10425 test_timers_exception(EXCEPTION_ILLEGAL_INSTRUCTION); 10426 test_timers_exception(0xE000BEEF); /* customer exception */ 10427 } 10428 10429 /* Various win events with arbitrary parameters */ 10430 static const struct message WmWinEventsSeq[] = { 10431 { EVENT_SYSTEM_SOUND, winevent_hook|wparam|lparam, OBJID_WINDOW, 0 }, 10432 { EVENT_SYSTEM_ALERT, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 }, 10433 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, OBJID_TITLEBAR, 2 }, 10434 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_MENU, 3 }, 10435 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_CLIENT, 4 }, 10436 { EVENT_SYSTEM_MENUPOPUPSTART, winevent_hook|wparam|lparam, OBJID_VSCROLL, 5 }, 10437 { EVENT_SYSTEM_MENUPOPUPEND, winevent_hook|wparam|lparam, OBJID_HSCROLL, 6 }, 10438 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, OBJID_SIZEGRIP, 7 }, 10439 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, OBJID_CARET, 8 }, 10440 /* our win event hook ignores OBJID_CURSOR events */ 10441 /*{ EVENT_SYSTEM_MOVESIZESTART, winevent_hook|wparam|lparam, OBJID_CURSOR, 9 },*/ 10442 { EVENT_SYSTEM_MOVESIZEEND, winevent_hook|wparam|lparam, OBJID_ALERT, 10 }, 10443 { EVENT_SYSTEM_CONTEXTHELPSTART, winevent_hook|wparam|lparam, OBJID_SOUND, 11 }, 10444 { EVENT_SYSTEM_CONTEXTHELPEND, winevent_hook|wparam|lparam, OBJID_QUERYCLASSNAMEIDX, 12 }, 10445 { EVENT_SYSTEM_DRAGDROPSTART, winevent_hook|wparam|lparam, OBJID_NATIVEOM, 13 }, 10446 { EVENT_SYSTEM_DRAGDROPEND, winevent_hook|wparam|lparam, OBJID_WINDOW, 0 }, 10447 { EVENT_SYSTEM_DIALOGSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 }, 10448 { EVENT_SYSTEM_DIALOGEND, winevent_hook|wparam|lparam, OBJID_TITLEBAR, 2 }, 10449 { EVENT_SYSTEM_SCROLLINGSTART, winevent_hook|wparam|lparam, OBJID_MENU, 3 }, 10450 { EVENT_SYSTEM_SCROLLINGEND, winevent_hook|wparam|lparam, OBJID_CLIENT, 4 }, 10451 { EVENT_SYSTEM_SWITCHSTART, winevent_hook|wparam|lparam, OBJID_VSCROLL, 5 }, 10452 { EVENT_SYSTEM_SWITCHEND, winevent_hook|wparam|lparam, OBJID_HSCROLL, 6 }, 10453 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, OBJID_SIZEGRIP, 7 }, 10454 { EVENT_SYSTEM_MINIMIZEEND, winevent_hook|wparam|lparam, OBJID_CARET, 8 }, 10455 { 0 } 10456 }; 10457 static const struct message WmWinEventCaretSeq[] = { 10458 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1 */ 10459 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1 */ 10460 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 2 */ 10461 { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1 */ 10462 { 0 } 10463 }; 10464 static const struct message WmWinEventCaretSeq_2[] = { 10465 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1/2 */ 10466 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1/2 */ 10467 { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1/2 */ 10468 { 0 } 10469 }; 10470 static const struct message WmWinEventAlertSeq[] = { 10471 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_ALERT, 0 }, 10472 { 0 } 10473 }; 10474 static const struct message WmWinEventAlertSeq_2[] = { 10475 /* create window in the thread proc */ 10476 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_WINDOW, 2 }, 10477 /* our test event */ 10478 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_ALERT, 2 }, 10479 { 0 } 10480 }; 10481 static const struct message WmGlobalHookSeq_1[] = { 10482 /* create window in the thread proc */ 10483 { HCBT_CREATEWND, hook|lparam, 0, 2 }, 10484 /* our test events */ 10485 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_PREVWINDOW, 2 }, 10486 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_NEXTWINDOW, 2 }, 10487 { 0 } 10488 }; 10489 static const struct message WmGlobalHookSeq_2[] = { 10490 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_NEXTWINDOW, 0 }, /* old local hook */ 10491 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_NEXTWINDOW, 2 }, /* new global hook */ 10492 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_PREVWINDOW, 0 }, /* old local hook */ 10493 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_PREVWINDOW, 2 }, /* new global hook */ 10494 { 0 } 10495 }; 10496 10497 static const struct message WmMouseLLHookSeq[] = { 10498 { WM_MOUSEMOVE, hook }, 10499 { WM_LBUTTONUP, hook }, 10500 { WM_MOUSEMOVE, hook }, 10501 { 0 } 10502 }; 10503 10504 static void CALLBACK win_event_global_hook_proc(HWINEVENTHOOK hevent, 10505 DWORD event, 10506 HWND hwnd, 10507 LONG object_id, 10508 LONG child_id, 10509 DWORD thread_id, 10510 DWORD event_time) 10511 { 10512 char buf[256]; 10513 10514 if (GetClassNameA(hwnd, buf, sizeof(buf))) 10515 { 10516 if (!lstrcmpiA(buf, "TestWindowClass") || 10517 !lstrcmpiA(buf, "static")) 10518 { 10519 struct recvd_message msg; 10520 10521 msg.hwnd = hwnd; 10522 msg.message = event; 10523 msg.flags = winevent_hook|wparam|lparam; 10524 msg.wParam = object_id; 10525 msg.lParam = (thread_id == GetCurrentThreadId()) ? child_id : (child_id + 2); 10526 msg.descr = "WEH_2"; 10527 add_message(&msg); 10528 } 10529 } 10530 } 10531 10532 static HHOOK hCBT_global_hook; 10533 static DWORD cbt_global_hook_thread_id; 10534 10535 static LRESULT CALLBACK cbt_global_hook_proc(int nCode, WPARAM wParam, LPARAM lParam) 10536 { 10537 HWND hwnd; 10538 char buf[256]; 10539 10540 if (nCode == HCBT_SYSCOMMAND) 10541 { 10542 struct recvd_message msg; 10543 10544 msg.hwnd = 0; 10545 msg.message = nCode; 10546 msg.flags = hook|wparam|lparam; 10547 msg.wParam = wParam; 10548 msg.lParam = (cbt_global_hook_thread_id == GetCurrentThreadId()) ? 1 : 2; 10549 msg.descr = "CBT_2"; 10550 add_message(&msg); 10551 10552 return CallNextHookEx(hCBT_global_hook, nCode, wParam, lParam); 10553 } 10554 /* WH_MOUSE_LL hook */ 10555 if (nCode == HC_ACTION) 10556 { 10557 MSLLHOOKSTRUCT *mhll = (MSLLHOOKSTRUCT *)lParam; 10558 10559 /* we can't test for real mouse events */ 10560 if (mhll->flags & LLMHF_INJECTED) 10561 { 10562 struct recvd_message msg; 10563 10564 memset (&msg, 0, sizeof (msg)); 10565 msg.message = wParam; 10566 msg.flags = hook; 10567 msg.descr = "CBT_2"; 10568 add_message(&msg); 10569 } 10570 return CallNextHookEx(hCBT_global_hook, nCode, wParam, lParam); 10571 } 10572 10573 /* Log also SetFocus(0) calls */ 10574 hwnd = wParam ? (HWND)wParam : (HWND)lParam; 10575 10576 if (GetClassNameA(hwnd, buf, sizeof(buf))) 10577 { 10578 if (!lstrcmpiA(buf, "TestWindowClass") || 10579 !lstrcmpiA(buf, "static")) 10580 { 10581 struct recvd_message msg; 10582 10583 msg.hwnd = hwnd; 10584 msg.message = nCode; 10585 msg.flags = hook|wparam|lparam; 10586 msg.wParam = wParam; 10587 msg.lParam = (cbt_global_hook_thread_id == GetCurrentThreadId()) ? 1 : 2; 10588 msg.descr = "CBT_2"; 10589 add_message(&msg); 10590 } 10591 } 10592 return CallNextHookEx(hCBT_global_hook, nCode, wParam, lParam); 10593 } 10594 10595 static DWORD WINAPI win_event_global_thread_proc(void *param) 10596 { 10597 HWND hwnd; 10598 MSG msg; 10599 HANDLE hevent = *(HANDLE *)param; 10600 10601 assert(pNotifyWinEvent); 10602 10603 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL); 10604 assert(hwnd); 10605 trace("created thread window %p\n", hwnd); 10606 10607 *(HWND *)param = hwnd; 10608 10609 flush_sequence(); 10610 /* this event should be received only by our new hook proc, 10611 * an old one does not expect an event from another thread. 10612 */ 10613 pNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, hwnd, OBJID_ALERT, 0); 10614 SetEvent(hevent); 10615 10616 while (GetMessageA(&msg, 0, 0, 0)) 10617 { 10618 TranslateMessage(&msg); 10619 DispatchMessageA(&msg); 10620 } 10621 return 0; 10622 } 10623 10624 static DWORD WINAPI cbt_global_hook_thread_proc(void *param) 10625 { 10626 HWND hwnd; 10627 MSG msg; 10628 HANDLE hevent = *(HANDLE *)param; 10629 10630 flush_sequence(); 10631 /* these events should be received only by our new hook proc, 10632 * an old one does not expect an event from another thread. 10633 */ 10634 10635 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL); 10636 assert(hwnd); 10637 trace("created thread window %p\n", hwnd); 10638 10639 *(HWND *)param = hwnd; 10640 10641 /* Windows doesn't like when a thread plays games with the focus, 10642 that leads to all kinds of misbehaviours and failures to activate 10643 a window. So, better keep next lines commented out. 10644 SetFocus(0); 10645 SetFocus(hwnd);*/ 10646 10647 DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_PREVWINDOW, 0); 10648 DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_NEXTWINDOW, 0); 10649 10650 SetEvent(hevent); 10651 10652 while (GetMessageA(&msg, 0, 0, 0)) 10653 { 10654 TranslateMessage(&msg); 10655 DispatchMessageA(&msg); 10656 } 10657 return 0; 10658 } 10659 10660 static DWORD WINAPI mouse_ll_global_thread_proc(void *param) 10661 { 10662 HWND hwnd; 10663 MSG msg; 10664 HANDLE hevent = *(HANDLE *)param; 10665 10666 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL); 10667 assert(hwnd); 10668 trace("created thread window %p\n", hwnd); 10669 10670 *(HWND *)param = hwnd; 10671 10672 flush_sequence(); 10673 10674 /* Windows doesn't like when a thread plays games with the focus, 10675 * that leads to all kinds of misbehaviours and failures to activate 10676 * a window. So, better don't generate a mouse click message below. 10677 */ 10678 mouse_event(MOUSEEVENTF_MOVE, -1, 0, 0, 0); 10679 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); 10680 mouse_event(MOUSEEVENTF_MOVE, 1, 0, 0, 0); 10681 10682 SetEvent(hevent); 10683 while (GetMessageA(&msg, 0, 0, 0)) 10684 { 10685 TranslateMessage(&msg); 10686 DispatchMessageA(&msg); 10687 } 10688 return 0; 10689 } 10690 10691 static void test_winevents(void) 10692 { 10693 BOOL ret; 10694 MSG msg; 10695 HWND hwnd, hwnd2; 10696 UINT i; 10697 HANDLE hthread, hevent; 10698 DWORD tid; 10699 HWINEVENTHOOK hhook; 10700 const struct message *events = WmWinEventsSeq; 10701 10702 hwnd = CreateWindowExA(0, "TestWindowClass", NULL, 10703 WS_OVERLAPPEDWINDOW, 10704 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0, 10705 NULL, NULL, 0); 10706 assert(hwnd); 10707 10708 /****** start of global hook test *************/ 10709 hCBT_global_hook = SetWindowsHookExA(WH_CBT, cbt_global_hook_proc, GetModuleHandleA(0), 0); 10710 if (!hCBT_global_hook) 10711 { 10712 ok(DestroyWindow(hwnd), "failed to destroy window\n"); 10713 skip( "cannot set global hook\n" ); 10714 return; 10715 } 10716 10717 hevent = CreateEventA(NULL, 0, 0, NULL); 10718 assert(hevent); 10719 hwnd2 = hevent; 10720 10721 hthread = CreateThread(NULL, 0, cbt_global_hook_thread_proc, &hwnd2, 0, &tid); 10722 ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError()); 10723 10724 ok(WaitForSingleObject(hevent, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 10725 10726 ok_sequence(WmGlobalHookSeq_1, "global hook 1", FALSE); 10727 10728 flush_sequence(); 10729 /* this one should be received only by old hook proc */ 10730 DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_NEXTWINDOW, 0); 10731 /* this one should be received only by old hook proc */ 10732 DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_PREVWINDOW, 0); 10733 10734 ok_sequence(WmGlobalHookSeq_2, "global hook 2", FALSE); 10735 10736 ret = UnhookWindowsHookEx(hCBT_global_hook); 10737 ok( ret, "UnhookWindowsHookEx error %d\n", GetLastError()); 10738 10739 PostThreadMessageA(tid, WM_QUIT, 0, 0); 10740 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 10741 CloseHandle(hthread); 10742 CloseHandle(hevent); 10743 ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n"); 10744 /****** end of global hook test *************/ 10745 10746 if (!pSetWinEventHook || !pNotifyWinEvent || !pUnhookWinEvent) 10747 { 10748 ok(DestroyWindow(hwnd), "failed to destroy window\n"); 10749 return; 10750 } 10751 10752 flush_sequence(); 10753 10754 if (0) 10755 { 10756 /* this test doesn't pass under Win9x */ 10757 /* win2k ignores events with hwnd == 0 */ 10758 SetLastError(0xdeadbeef); 10759 pNotifyWinEvent(events[0].message, 0, events[0].wParam, events[0].lParam); 10760 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || /* Win2k */ 10761 GetLastError() == 0xdeadbeef, /* Win9x */ 10762 "unexpected error %d\n", GetLastError()); 10763 ok_sequence(WmEmptySeq, "empty notify winevents", FALSE); 10764 } 10765 10766 for (i = 0; i < ARRAY_SIZE(WmWinEventsSeq); i++) 10767 pNotifyWinEvent(events[i].message, hwnd, events[i].wParam, events[i].lParam); 10768 10769 ok_sequence(WmWinEventsSeq, "notify winevents", FALSE); 10770 10771 /****** start of event filtering test *************/ 10772 hhook = pSetWinEventHook( 10773 EVENT_OBJECT_SHOW, /* 0x8002 */ 10774 EVENT_OBJECT_LOCATIONCHANGE, /* 0x800B */ 10775 GetModuleHandleA(0), win_event_global_hook_proc, 10776 GetCurrentProcessId(), 0, 10777 WINEVENT_INCONTEXT); 10778 ok(hhook != 0, "SetWinEventHook error %d\n", GetLastError()); 10779 10780 hevent = CreateEventA(NULL, 0, 0, NULL); 10781 assert(hevent); 10782 hwnd2 = hevent; 10783 10784 hthread = CreateThread(NULL, 0, win_event_global_thread_proc, &hwnd2, 0, &tid); 10785 ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError()); 10786 10787 ok(WaitForSingleObject(hevent, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 10788 10789 ok_sequence(WmWinEventAlertSeq, "alert winevent", FALSE); 10790 10791 flush_sequence(); 10792 /* this one should be received only by old hook proc */ 10793 pNotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_CARET, 0); /* 0x8000 */ 10794 pNotifyWinEvent(EVENT_OBJECT_SHOW, hwnd, OBJID_CARET, 0); /* 0x8002 */ 10795 /* this one should be received only by old hook proc */ 10796 pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, hwnd, OBJID_CARET, 0); /* 0x800C */ 10797 10798 ok_sequence(WmWinEventCaretSeq, "caret winevent", FALSE); 10799 10800 ret = pUnhookWinEvent(hhook); 10801 ok( ret, "UnhookWinEvent error %d\n", GetLastError()); 10802 10803 PostThreadMessageA(tid, WM_QUIT, 0, 0); 10804 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 10805 CloseHandle(hthread); 10806 CloseHandle(hevent); 10807 ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n"); 10808 /****** end of event filtering test *************/ 10809 10810 /****** start of out of context event test *************/ 10811 hhook = pSetWinEventHook(EVENT_MIN, EVENT_MAX, 0, 10812 win_event_global_hook_proc, GetCurrentProcessId(), 0, 10813 WINEVENT_OUTOFCONTEXT); 10814 ok(hhook != 0, "SetWinEventHook error %d\n", GetLastError()); 10815 10816 hevent = CreateEventA(NULL, 0, 0, NULL); 10817 assert(hevent); 10818 hwnd2 = hevent; 10819 10820 flush_sequence(); 10821 10822 hthread = CreateThread(NULL, 0, win_event_global_thread_proc, &hwnd2, 0, &tid); 10823 ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError()); 10824 10825 ok(WaitForSingleObject(hevent, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 10826 10827 ok_sequence(WmEmptySeq, "empty notify winevents", FALSE); 10828 /* process pending winevent messages */ 10829 ok(!PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE), "msg queue should be empty\n"); 10830 ok_sequence(WmWinEventAlertSeq_2, "alert winevent for out of context proc", FALSE); 10831 10832 flush_sequence(); 10833 /* this one should be received only by old hook proc */ 10834 pNotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_CARET, 0); /* 0x8000 */ 10835 pNotifyWinEvent(EVENT_OBJECT_SHOW, hwnd, OBJID_CARET, 0); /* 0x8002 */ 10836 /* this one should be received only by old hook proc */ 10837 pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, hwnd, OBJID_CARET, 0); /* 0x800C */ 10838 10839 ok_sequence(WmWinEventCaretSeq_2, "caret winevent for incontext proc", FALSE); 10840 /* process pending winevent messages */ 10841 ok(!PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE), "msg queue should be empty\n"); 10842 ok_sequence(WmWinEventCaretSeq_2, "caret winevent for out of context proc", FALSE); 10843 10844 ret = pUnhookWinEvent(hhook); 10845 ok( ret, "UnhookWinEvent error %d\n", GetLastError()); 10846 10847 PostThreadMessageA(tid, WM_QUIT, 0, 0); 10848 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 10849 CloseHandle(hthread); 10850 CloseHandle(hevent); 10851 ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n"); 10852 /****** end of out of context event test *************/ 10853 10854 /****** start of MOUSE_LL hook test *************/ 10855 hCBT_global_hook = SetWindowsHookExA(WH_MOUSE_LL, cbt_global_hook_proc, GetModuleHandleA(0), 0); 10856 /* WH_MOUSE_LL is not supported on Win9x platforms */ 10857 if (!hCBT_global_hook) 10858 { 10859 win_skip("Skipping WH_MOUSE_LL test on this platform\n"); 10860 goto skip_mouse_ll_hook_test; 10861 } 10862 10863 hevent = CreateEventA(NULL, 0, 0, NULL); 10864 assert(hevent); 10865 hwnd2 = hevent; 10866 10867 hthread = CreateThread(NULL, 0, mouse_ll_global_thread_proc, &hwnd2, 0, &tid); 10868 ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError()); 10869 10870 while (WaitForSingleObject(hevent, 100) == WAIT_TIMEOUT) 10871 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 10872 10873 ok_sequence(WmMouseLLHookSeq, "MOUSE_LL hook other thread", FALSE); 10874 flush_sequence(); 10875 10876 mouse_event(MOUSEEVENTF_MOVE, -1, 0, 0, 0); 10877 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); 10878 mouse_event(MOUSEEVENTF_MOVE, 1, 0, 0, 0); 10879 10880 ok_sequence(WmMouseLLHookSeq, "MOUSE_LL hook same thread", FALSE); 10881 10882 ret = UnhookWindowsHookEx(hCBT_global_hook); 10883 ok( ret, "UnhookWindowsHookEx error %d\n", GetLastError()); 10884 10885 PostThreadMessageA(tid, WM_QUIT, 0, 0); 10886 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 10887 CloseHandle(hthread); 10888 CloseHandle(hevent); 10889 ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n"); 10890 /****** end of MOUSE_LL hook test *************/ 10891 skip_mouse_ll_hook_test: 10892 10893 ok(DestroyWindow(hwnd), "failed to destroy window\n"); 10894 } 10895 10896 static void test_set_hook(void) 10897 { 10898 BOOL ret; 10899 HHOOK hhook; 10900 HWINEVENTHOOK hwinevent_hook; 10901 10902 hhook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, GetModuleHandleA(0), GetCurrentThreadId()); 10903 ok(hhook != 0, "local hook does not require hModule set to 0\n"); 10904 UnhookWindowsHookEx(hhook); 10905 10906 if (0) 10907 { 10908 /* this test doesn't pass under Win9x: BUG! */ 10909 SetLastError(0xdeadbeef); 10910 hhook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, 0); 10911 ok(!hhook, "global hook requires hModule != 0\n"); 10912 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD, "unexpected error %d\n", GetLastError()); 10913 } 10914 10915 SetLastError(0xdeadbeef); 10916 hhook = SetWindowsHookExA(WH_CBT, 0, GetModuleHandleA(0), GetCurrentThreadId()); 10917 ok(!hhook, "SetWinEventHook with invalid proc should fail\n"); 10918 ok(GetLastError() == ERROR_INVALID_FILTER_PROC || /* Win2k */ 10919 GetLastError() == 0xdeadbeef, /* Win9x */ 10920 "unexpected error %d\n", GetLastError()); 10921 10922 SetLastError(0xdeadbeef); 10923 ok(!UnhookWindowsHookEx((HHOOK)0xdeadbeef), "UnhookWindowsHookEx succeeded\n"); 10924 ok(GetLastError() == ERROR_INVALID_HOOK_HANDLE || /* Win2k */ 10925 GetLastError() == 0xdeadbeef, /* Win9x */ 10926 "unexpected error %d\n", GetLastError()); 10927 10928 if (!pSetWinEventHook || !pUnhookWinEvent) return; 10929 10930 /* even process local incontext hooks require hmodule */ 10931 SetLastError(0xdeadbeef); 10932 hwinevent_hook = pSetWinEventHook(EVENT_MIN, EVENT_MAX, 0, win_event_proc, 10933 GetCurrentProcessId(), 0, WINEVENT_INCONTEXT); 10934 ok(!hwinevent_hook, "WINEVENT_INCONTEXT requires hModule != 0\n"); 10935 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD || /* Win2k */ 10936 GetLastError() == 0xdeadbeef, /* Win9x */ 10937 "unexpected error %d\n", GetLastError()); 10938 10939 /* even thread local incontext hooks require hmodule */ 10940 SetLastError(0xdeadbeef); 10941 hwinevent_hook = pSetWinEventHook(EVENT_MIN, EVENT_MAX, 0, win_event_proc, 10942 GetCurrentProcessId(), GetCurrentThreadId(), WINEVENT_INCONTEXT); 10943 ok(!hwinevent_hook, "WINEVENT_INCONTEXT requires hModule != 0\n"); 10944 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD || /* Win2k */ 10945 GetLastError() == 0xdeadbeef, /* Win9x */ 10946 "unexpected error %d\n", GetLastError()); 10947 10948 if (0) 10949 { 10950 /* these 3 tests don't pass under Win9x */ 10951 SetLastError(0xdeadbeef); 10952 hwinevent_hook = pSetWinEventHook(1, 0, 0, win_event_proc, 10953 GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT); 10954 ok(!hwinevent_hook, "SetWinEventHook with invalid event range should fail\n"); 10955 ok(GetLastError() == ERROR_INVALID_HOOK_FILTER, "unexpected error %d\n", GetLastError()); 10956 10957 SetLastError(0xdeadbeef); 10958 hwinevent_hook = pSetWinEventHook(-1, 1, 0, win_event_proc, 10959 GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT); 10960 ok(!hwinevent_hook, "SetWinEventHook with invalid event range should fail\n"); 10961 ok(GetLastError() == ERROR_INVALID_HOOK_FILTER, "unexpected error %d\n", GetLastError()); 10962 10963 SetLastError(0xdeadbeef); 10964 hwinevent_hook = pSetWinEventHook(EVENT_MIN, EVENT_MAX, 0, win_event_proc, 10965 0, 0xdeadbeef, WINEVENT_OUTOFCONTEXT); 10966 ok(!hwinevent_hook, "SetWinEventHook with invalid tid should fail\n"); 10967 ok(GetLastError() == ERROR_INVALID_THREAD_ID, "unexpected error %d\n", GetLastError()); 10968 } 10969 10970 SetLastError(0xdeadbeef); 10971 hwinevent_hook = pSetWinEventHook(0, 0, 0, win_event_proc, 10972 GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT); 10973 ok(hwinevent_hook != 0, "SetWinEventHook error %d\n", GetLastError()); 10974 ok(GetLastError() == 0xdeadbeef, "unexpected error %d\n", GetLastError()); 10975 ret = pUnhookWinEvent(hwinevent_hook); 10976 ok( ret, "UnhookWinEvent error %d\n", GetLastError()); 10977 10978 todo_wine { 10979 /* This call succeeds under win2k SP4, but fails under Wine. 10980 Does win2k test/use passed process id? */ 10981 SetLastError(0xdeadbeef); 10982 hwinevent_hook = pSetWinEventHook(EVENT_MIN, EVENT_MAX, 0, win_event_proc, 10983 0xdeadbeef, 0, WINEVENT_OUTOFCONTEXT); 10984 ok(hwinevent_hook != 0, "SetWinEventHook error %d\n", GetLastError()); 10985 ok(GetLastError() == 0xdeadbeef, "unexpected error %d\n", GetLastError()); 10986 ret = pUnhookWinEvent(hwinevent_hook); 10987 ok( ret, "UnhookWinEvent error %d\n", GetLastError()); 10988 } 10989 10990 SetLastError(0xdeadbeef); 10991 ok(!pUnhookWinEvent((HWINEVENTHOOK)0xdeadbeef), "UnhookWinEvent succeeded\n"); 10992 ok(GetLastError() == ERROR_INVALID_HANDLE || /* Win2k */ 10993 GetLastError() == 0xdeadbeef, /* Win9x */ 10994 "unexpected error %d\n", GetLastError()); 10995 } 10996 10997 static HWND hook_hwnd; 10998 static HHOOK recursive_hook; 10999 static int hook_depth, max_hook_depth; 11000 11001 static LRESULT WINAPI rec_get_message_hook(int code, WPARAM w, LPARAM l) 11002 { 11003 LRESULT res; 11004 MSG msg; 11005 BOOL b; 11006 11007 hook_depth++; 11008 if(hook_depth > max_hook_depth) 11009 max_hook_depth = hook_depth; 11010 11011 b = PeekMessageW(&msg, hook_hwnd, 0, 0, PM_NOREMOVE); 11012 ok(b, "PeekMessage failed\n"); 11013 11014 res = CallNextHookEx(recursive_hook, code, w, l); 11015 11016 hook_depth--; 11017 return res; 11018 } 11019 11020 static void test_recursive_hook(void) 11021 { 11022 MSG msg; 11023 BOOL b; 11024 11025 hook_hwnd = CreateWindowA("Static", NULL, WS_POPUP, 0, 0, 200, 60, NULL, NULL, NULL, NULL); 11026 ok(hook_hwnd != NULL, "CreateWindow failed\n"); 11027 11028 recursive_hook = SetWindowsHookExW(WH_GETMESSAGE, rec_get_message_hook, NULL, GetCurrentThreadId()); 11029 ok(recursive_hook != NULL, "SetWindowsHookEx failed\n"); 11030 11031 PostMessageW(hook_hwnd, WM_USER, 0, 0); 11032 PostMessageW(hook_hwnd, WM_USER+1, 0, 0); 11033 11034 hook_depth = 0; 11035 GetMessageW(&msg, hook_hwnd, 0, 0); 11036 ok(15 <= max_hook_depth && max_hook_depth < 45, "max_hook_depth = %d\n", max_hook_depth); 11037 trace("max_hook_depth = %d\n", max_hook_depth); 11038 11039 b = UnhookWindowsHookEx(recursive_hook); 11040 ok(b, "UnhokWindowsHookEx failed\n"); 11041 11042 DestroyWindow(hook_hwnd); 11043 } 11044 11045 static const struct message ScrollWindowPaint1[] = { 11046 { WM_PAINT, sent }, 11047 { WM_ERASEBKGND, sent|beginpaint }, 11048 { WM_GETTEXTLENGTH, sent|optional }, 11049 { WM_PAINT, sent|optional }, 11050 { WM_NCPAINT, sent|beginpaint|optional }, 11051 { WM_GETTEXT, sent|beginpaint|optional }, 11052 { WM_GETTEXT, sent|beginpaint|optional }, 11053 { WM_GETTEXT, sent|beginpaint|optional }, 11054 { WM_GETTEXT, sent|beginpaint|defwinproc|optional }, 11055 { WM_ERASEBKGND, sent|beginpaint|optional }, 11056 { 0 } 11057 }; 11058 11059 static const struct message ScrollWindowPaint2[] = { 11060 { WM_PAINT, sent }, 11061 { 0 } 11062 }; 11063 11064 static void test_scrollwindowex(void) 11065 { 11066 HWND hwnd, hchild; 11067 RECT rect={0,0,130,130}; 11068 11069 hwnd = CreateWindowExA(0, "TestWindowClass", "Test Scroll", 11070 WS_VISIBLE|WS_OVERLAPPEDWINDOW, 11071 100, 100, 200, 200, 0, 0, 0, NULL); 11072 ok (hwnd != 0, "Failed to create overlapped window\n"); 11073 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", 11074 WS_VISIBLE|WS_CAPTION|WS_CHILD, 11075 10, 10, 150, 150, hwnd, 0, 0, NULL); 11076 ok (hchild != 0, "Failed to create child\n"); 11077 UpdateWindow(hwnd); 11078 flush_events(); 11079 flush_sequence(); 11080 11081 /* scroll without the child window */ 11082 trace("start scroll\n"); 11083 ScrollWindowEx( hwnd, 10, 10, &rect, NULL, NULL, NULL, 11084 SW_ERASE|SW_INVALIDATE); 11085 ok_sequence(WmEmptySeq, "ScrollWindowEx", FALSE); 11086 trace("end scroll\n"); 11087 flush_sequence(); 11088 flush_events(); 11089 ok_sequence(ScrollWindowPaint1, "ScrollWindowEx", FALSE); 11090 flush_events(); 11091 flush_sequence(); 11092 11093 /* Now without the SW_ERASE flag */ 11094 trace("start scroll\n"); 11095 ScrollWindowEx( hwnd, 10, 10, &rect, NULL, NULL, NULL, SW_INVALIDATE); 11096 ok_sequence(WmEmptySeq, "ScrollWindowEx", FALSE); 11097 trace("end scroll\n"); 11098 flush_sequence(); 11099 flush_events(); 11100 ok_sequence(ScrollWindowPaint2, "ScrollWindowEx", FALSE); 11101 flush_events(); 11102 flush_sequence(); 11103 11104 /* now scroll the child window as well */ 11105 trace("start scroll\n"); 11106 ScrollWindowEx( hwnd, 10, 10, &rect, NULL, NULL, NULL, 11107 SW_SCROLLCHILDREN|SW_ERASE|SW_INVALIDATE); 11108 /* wine sends WM_POSCHANGING, WM_POSCHANGED messages */ 11109 /* windows sometimes a WM_MOVE */ 11110 ok_sequence(WmEmptySeq, "ScrollWindowEx", TRUE); 11111 trace("end scroll\n"); 11112 flush_sequence(); 11113 flush_events(); 11114 ok_sequence(ScrollWindowPaint1, "ScrollWindowEx", FALSE); 11115 flush_events(); 11116 flush_sequence(); 11117 11118 /* now scroll with ScrollWindow() */ 11119 trace("start scroll with ScrollWindow\n"); 11120 ScrollWindow( hwnd, 5, 5, NULL, NULL); 11121 trace("end scroll\n"); 11122 flush_sequence(); 11123 flush_events(); 11124 ok_sequence(ScrollWindowPaint1, "ScrollWindow", FALSE); 11125 11126 ok(DestroyWindow(hchild), "failed to destroy window\n"); 11127 ok(DestroyWindow(hwnd), "failed to destroy window\n"); 11128 flush_sequence(); 11129 } 11130 11131 static const struct message destroy_window_with_children[] = { 11132 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, /* popup */ 11133 { HCBT_DESTROYWND, hook|lparam, 0, WND_PARENT_ID }, /* parent */ 11134 { 0x0090, sent|optional }, 11135 { HCBT_DESTROYWND, hook|lparam, 0, WND_POPUP_ID }, /* popup */ 11136 { 0x0090, sent|optional }, 11137 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, /* popup */ 11138 { WM_DESTROY, sent|wparam|lparam, 0, WND_POPUP_ID }, /* popup */ 11139 { WM_CAPTURECHANGED, sent|wparam|lparam, 0, WND_POPUP_ID }, /* popup */ 11140 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_POPUP_ID }, /* popup */ 11141 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, /* parent */ 11142 { WM_DESTROY, sent|wparam|lparam, 0, WND_PARENT_ID }, /* parent */ 11143 { WM_DESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 2 }, /* child2 */ 11144 { WM_DESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 1 }, /* child1 */ 11145 { WM_DESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 3 }, /* child3 */ 11146 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 2 }, /* child2 */ 11147 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 3 }, /* child3 */ 11148 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 1 }, /* child1 */ 11149 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_PARENT_ID }, /* parent */ 11150 { 0 } 11151 }; 11152 11153 static void test_DestroyWindow(void) 11154 { 11155 BOOL ret; 11156 HWND parent, child1, child2, child3, child4, test; 11157 UINT_PTR child_id = WND_CHILD_ID + 1; 11158 11159 parent = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, 11160 100, 100, 200, 200, 0, 0, 0, NULL); 11161 assert(parent != 0); 11162 child1 = CreateWindowExA(0, "TestWindowClass", NULL, WS_CHILD, 11163 0, 0, 50, 50, parent, (HMENU)child_id++, 0, NULL); 11164 assert(child1 != 0); 11165 child2 = CreateWindowExA(0, "TestWindowClass", NULL, WS_CHILD, 11166 0, 0, 50, 50, GetDesktopWindow(), (HMENU)child_id++, 0, NULL); 11167 assert(child2 != 0); 11168 child3 = CreateWindowExA(0, "TestWindowClass", NULL, WS_CHILD, 11169 0, 0, 50, 50, child1, (HMENU)child_id++, 0, NULL); 11170 assert(child3 != 0); 11171 child4 = CreateWindowExA(0, "TestWindowClass", NULL, WS_POPUP, 11172 0, 0, 50, 50, parent, 0, 0, NULL); 11173 assert(child4 != 0); 11174 11175 /* test owner/parent of child2 */ 11176 test = GetParent(child2); 11177 ok(test == GetDesktopWindow(), "wrong parent %p\n", test); 11178 ok(!IsChild(parent, child2), "wrong parent/child %p/%p\n", parent, child2); 11179 if(pGetAncestor) { 11180 test = pGetAncestor(child2, GA_PARENT); 11181 ok(test == GetDesktopWindow(), "wrong parent %p\n", test); 11182 } 11183 test = GetWindow(child2, GW_OWNER); 11184 ok(!test, "wrong owner %p\n", test); 11185 11186 test = SetParent(child2, parent); 11187 ok(test == GetDesktopWindow(), "wrong old parent %p\n", test); 11188 11189 /* test owner/parent of the parent */ 11190 test = GetParent(parent); 11191 ok(!test, "wrong parent %p\n", test); 11192 ok(!IsChild(GetDesktopWindow(), parent), "wrong parent/child %p/%p\n", GetDesktopWindow(), parent); 11193 if(pGetAncestor) { 11194 test = pGetAncestor(parent, GA_PARENT); 11195 ok(test == GetDesktopWindow(), "wrong parent %p\n", test); 11196 } 11197 test = GetWindow(parent, GW_OWNER); 11198 ok(!test, "wrong owner %p\n", test); 11199 11200 /* test owner/parent of child1 */ 11201 test = GetParent(child1); 11202 ok(test == parent, "wrong parent %p\n", test); 11203 ok(IsChild(parent, child1), "wrong parent/child %p/%p\n", parent, child1); 11204 if(pGetAncestor) { 11205 test = pGetAncestor(child1, GA_PARENT); 11206 ok(test == parent, "wrong parent %p\n", test); 11207 } 11208 test = GetWindow(child1, GW_OWNER); 11209 ok(!test, "wrong owner %p\n", test); 11210 11211 /* test owner/parent of child2 */ 11212 test = GetParent(child2); 11213 ok(test == parent, "wrong parent %p\n", test); 11214 ok(IsChild(parent, child2), "wrong parent/child %p/%p\n", parent, child2); 11215 if(pGetAncestor) { 11216 test = pGetAncestor(child2, GA_PARENT); 11217 ok(test == parent, "wrong parent %p\n", test); 11218 } 11219 test = GetWindow(child2, GW_OWNER); 11220 ok(!test, "wrong owner %p\n", test); 11221 11222 /* test owner/parent of child3 */ 11223 test = GetParent(child3); 11224 ok(test == child1, "wrong parent %p\n", test); 11225 ok(IsChild(parent, child3), "wrong parent/child %p/%p\n", parent, child3); 11226 if(pGetAncestor) { 11227 test = pGetAncestor(child3, GA_PARENT); 11228 ok(test == child1, "wrong parent %p\n", test); 11229 } 11230 test = GetWindow(child3, GW_OWNER); 11231 ok(!test, "wrong owner %p\n", test); 11232 11233 /* test owner/parent of child4 */ 11234 test = GetParent(child4); 11235 ok(test == parent, "wrong parent %p\n", test); 11236 ok(!IsChild(parent, child4), "wrong parent/child %p/%p\n", parent, child4); 11237 if(pGetAncestor) { 11238 test = pGetAncestor(child4, GA_PARENT); 11239 ok(test == GetDesktopWindow(), "wrong parent %p\n", test); 11240 } 11241 test = GetWindow(child4, GW_OWNER); 11242 ok(test == parent, "wrong owner %p\n", test); 11243 11244 flush_sequence(); 11245 11246 trace("parent %p, child1 %p, child2 %p, child3 %p, child4 %p\n", 11247 parent, child1, child2, child3, child4); 11248 11249 SetCapture(child4); 11250 test = GetCapture(); 11251 ok(test == child4, "wrong capture window %p\n", test); 11252 11253 test_DestroyWindow_flag = TRUE; 11254 ret = DestroyWindow(parent); 11255 ok( ret, "DestroyWindow() error %d\n", GetLastError()); 11256 test_DestroyWindow_flag = FALSE; 11257 ok_sequence(destroy_window_with_children, "destroy window with children", FALSE); 11258 11259 ok(!IsWindow(parent), "parent still exists\n"); 11260 ok(!IsWindow(child1), "child1 still exists\n"); 11261 ok(!IsWindow(child2), "child2 still exists\n"); 11262 ok(!IsWindow(child3), "child3 still exists\n"); 11263 ok(!IsWindow(child4), "child4 still exists\n"); 11264 11265 test = GetCapture(); 11266 ok(!test, "wrong capture window %p\n", test); 11267 } 11268 11269 11270 static const struct message WmDispatchPaint[] = { 11271 { WM_NCPAINT, sent }, 11272 { WM_GETTEXT, sent|defwinproc|optional }, 11273 { WM_GETTEXT, sent|defwinproc|optional }, 11274 { WM_ERASEBKGND, sent }, 11275 { 0 } 11276 }; 11277 11278 static LRESULT WINAPI DispatchMessageCheckProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 11279 { 11280 if (message == WM_PAINT) return 0; 11281 return MsgCheckProcA( hwnd, message, wParam, lParam ); 11282 } 11283 11284 static void test_DispatchMessage(void) 11285 { 11286 RECT rect; 11287 MSG msg; 11288 int count; 11289 HWND hwnd = CreateWindowA( "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, 11290 100, 100, 200, 200, 0, 0, 0, NULL); 11291 ShowWindow( hwnd, SW_SHOW ); 11292 UpdateWindow( hwnd ); 11293 flush_events(); 11294 flush_sequence(); 11295 SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (LONG_PTR)DispatchMessageCheckProc ); 11296 11297 SetRect( &rect, -5, -5, 5, 5 ); 11298 RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE|RDW_ERASE|RDW_FRAME ); 11299 count = 0; 11300 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) 11301 { 11302 if (msg.message != WM_PAINT) DispatchMessageA( &msg ); 11303 else 11304 { 11305 flush_sequence(); 11306 DispatchMessageA( &msg ); 11307 /* DispatchMessage will send WM_NCPAINT if non client area is still invalid after WM_PAINT */ 11308 if (!count) ok_sequence( WmDispatchPaint, "WmDispatchPaint", FALSE ); 11309 else ok_sequence( WmEmptySeq, "WmEmpty", FALSE ); 11310 if (++count > 10) break; 11311 } 11312 } 11313 ok( msg.message == WM_PAINT && count > 10, "WM_PAINT messages stopped\n" ); 11314 11315 trace("now without DispatchMessage\n"); 11316 flush_sequence(); 11317 RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE|RDW_ERASE|RDW_FRAME ); 11318 count = 0; 11319 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) 11320 { 11321 if (msg.message != WM_PAINT) DispatchMessageA( &msg ); 11322 else 11323 { 11324 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 ); 11325 flush_sequence(); 11326 /* this will send WM_NCCPAINT just like DispatchMessage does */ 11327 GetUpdateRgn( hwnd, hrgn, TRUE ); 11328 ok_sequence( WmDispatchPaint, "WmDispatchPaint", FALSE ); 11329 DeleteObject( hrgn ); 11330 GetClientRect( hwnd, &rect ); 11331 ValidateRect( hwnd, &rect ); /* this will stop WM_PAINTs */ 11332 ok( !count, "Got multiple WM_PAINTs\n" ); 11333 if (++count > 10) break; 11334 } 11335 } 11336 11337 flush_sequence(); 11338 RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE|RDW_ERASE|RDW_FRAME ); 11339 count = 0; 11340 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) 11341 { 11342 if (msg.message != WM_PAINT) DispatchMessageA( &msg ); 11343 else 11344 { 11345 HDC hdc; 11346 11347 flush_sequence(); 11348 hdc = BeginPaint( hwnd, NULL ); 11349 ok( !hdc, "got valid hdc %p from BeginPaint\n", hdc ); 11350 ok( !EndPaint( hwnd, NULL ), "EndPaint succeeded\n" ); 11351 ok_sequence( WmDispatchPaint, "WmDispatchPaint", FALSE ); 11352 ok( !count, "Got multiple WM_PAINTs\n" ); 11353 if (++count > 10) break; 11354 } 11355 } 11356 DestroyWindow(hwnd); 11357 } 11358 11359 11360 static const struct message WmUser[] = { 11361 { WM_USER, sent }, 11362 { 0 } 11363 }; 11364 11365 struct sendmsg_info 11366 { 11367 HWND hwnd; 11368 DWORD timeout; 11369 DWORD ret; 11370 }; 11371 11372 static DWORD CALLBACK send_msg_thread( LPVOID arg ) 11373 { 11374 struct sendmsg_info *info = arg; 11375 SetLastError( 0xdeadbeef ); 11376 info->ret = SendMessageTimeoutA( info->hwnd, WM_USER, 0, 0, 0, info->timeout, NULL ); 11377 if (!info->ret) ok( GetLastError() == ERROR_TIMEOUT || 11378 broken(GetLastError() == 0), /* win9x */ 11379 "unexpected error %d\n", GetLastError()); 11380 return 0; 11381 } 11382 11383 static void wait_for_thread( HANDLE thread ) 11384 { 11385 while (MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_SENDMESSAGE) != WAIT_OBJECT_0) 11386 { 11387 MSG msg; 11388 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA(&msg); 11389 } 11390 } 11391 11392 static LRESULT WINAPI send_msg_delay_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 11393 { 11394 if (message == WM_USER) Sleep(200); 11395 return MsgCheckProcA( hwnd, message, wParam, lParam ); 11396 } 11397 11398 static void test_SendMessageTimeout(void) 11399 { 11400 HANDLE thread; 11401 struct sendmsg_info info; 11402 DWORD tid; 11403 BOOL is_win9x; 11404 11405 info.hwnd = CreateWindowA( "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, 11406 100, 100, 200, 200, 0, 0, 0, NULL); 11407 flush_events(); 11408 flush_sequence(); 11409 11410 info.timeout = 1000; 11411 info.ret = 0xdeadbeef; 11412 thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid ); 11413 wait_for_thread( thread ); 11414 CloseHandle( thread ); 11415 ok( info.ret == 1, "SendMessageTimeout failed\n" ); 11416 ok_sequence( WmUser, "WmUser", FALSE ); 11417 11418 info.timeout = 1; 11419 info.ret = 0xdeadbeef; 11420 thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid ); 11421 Sleep(100); /* SendMessageTimeout should time out here */ 11422 wait_for_thread( thread ); 11423 CloseHandle( thread ); 11424 ok( info.ret == 0, "SendMessageTimeout succeeded\n" ); 11425 ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE ); 11426 11427 /* 0 means infinite timeout (but not on win9x) */ 11428 info.timeout = 0; 11429 info.ret = 0xdeadbeef; 11430 thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid ); 11431 Sleep(100); 11432 wait_for_thread( thread ); 11433 CloseHandle( thread ); 11434 is_win9x = !info.ret; 11435 if (is_win9x) ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE ); 11436 else ok_sequence( WmUser, "WmUser", FALSE ); 11437 11438 /* timeout is treated as signed despite the prototype (but not on win9x) */ 11439 info.timeout = 0x7fffffff; 11440 info.ret = 0xdeadbeef; 11441 thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid ); 11442 Sleep(100); 11443 wait_for_thread( thread ); 11444 CloseHandle( thread ); 11445 ok( info.ret == 1, "SendMessageTimeout failed\n" ); 11446 ok_sequence( WmUser, "WmUser", FALSE ); 11447 11448 info.timeout = 0x80000000; 11449 info.ret = 0xdeadbeef; 11450 thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid ); 11451 Sleep(100); 11452 wait_for_thread( thread ); 11453 CloseHandle( thread ); 11454 if (is_win9x) 11455 { 11456 ok( info.ret == 1, "SendMessageTimeout failed\n" ); 11457 ok_sequence( WmUser, "WmUser", FALSE ); 11458 } 11459 else 11460 { 11461 ok( info.ret == 0, "SendMessageTimeout succeeded\n" ); 11462 ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE ); 11463 } 11464 11465 /* now check for timeout during message processing */ 11466 SetWindowLongPtrA( info.hwnd, GWLP_WNDPROC, (LONG_PTR)send_msg_delay_proc ); 11467 info.timeout = 100; 11468 info.ret = 0xdeadbeef; 11469 thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid ); 11470 wait_for_thread( thread ); 11471 CloseHandle( thread ); 11472 /* we should time out but still get the message */ 11473 ok( info.ret == 0, "SendMessageTimeout failed\n" ); 11474 ok_sequence( WmUser, "WmUser", FALSE ); 11475 11476 DestroyWindow( info.hwnd ); 11477 } 11478 11479 11480 /****************** edit message test *************************/ 11481 #define ID_EDIT 0x1234 11482 static const struct message sl_edit_setfocus[] = 11483 { 11484 { HCBT_SETFOCUS, hook }, 11485 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 11486 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 11487 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 11488 { WM_SETFOCUS, sent|wparam, 0 }, 11489 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 10 }, 11490 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 15 }, 11491 { WM_CTLCOLOREDIT, sent|parent }, 11492 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 11 }, 11493 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11494 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11495 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) }, 11496 { 0 } 11497 }; 11498 static const struct message sl_edit_invisible[] = 11499 { 11500 { HCBT_SETFOCUS, hook }, 11501 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 11502 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 11503 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 11504 { WM_KILLFOCUS, sent|parent }, 11505 { WM_SETFOCUS, sent }, 11506 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) }, 11507 { 0 } 11508 }; 11509 static const struct message ml_edit_setfocus[] = 11510 { 11511 { HCBT_SETFOCUS, hook }, 11512 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 11513 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 11514 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 11515 { WM_SETFOCUS, sent|wparam, 0 }, 11516 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 10 }, 11517 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 11 }, 11518 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11519 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11520 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) }, 11521 { 0 } 11522 }; 11523 static const struct message sl_edit_killfocus[] = 11524 { 11525 { HCBT_SETFOCUS, hook }, 11526 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 11527 { WM_KILLFOCUS, sent|wparam, 0 }, 11528 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11529 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11530 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_KILLFOCUS) }, 11531 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 11532 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, 11533 { 0 } 11534 }; 11535 static const struct message sl_edit_lbutton_dblclk[] = 11536 { 11537 { WM_LBUTTONDBLCLK, sent }, 11538 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, 11539 { 0 } 11540 }; 11541 static const struct message sl_edit_lbutton_down[] = 11542 { 11543 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 }, 11544 { HCBT_SETFOCUS, hook }, 11545 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 11546 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 11547 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 11548 { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, 11549 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 10 }, 11550 { WM_CTLCOLOREDIT, sent|parent }, 11551 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 11 }, 11552 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11553 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11554 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11555 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) }, 11556 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, 11557 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11558 { WM_CTLCOLOREDIT, sent|parent|optional }, 11559 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 11 }, 11560 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11561 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11562 { 0 } 11563 }; 11564 static const struct message ml_edit_lbutton_down[] = 11565 { 11566 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 }, 11567 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, 11568 { HCBT_SETFOCUS, hook }, 11569 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 11570 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 11571 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 11572 { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, 11573 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 10 }, 11574 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 11 }, 11575 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11576 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11577 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) }, 11578 { 0 } 11579 }; 11580 static const struct message sl_edit_lbutton_up[] = 11581 { 11582 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 }, 11583 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11584 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, 11585 { WM_CAPTURECHANGED, sent|defwinproc }, 11586 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11587 { 0 } 11588 }; 11589 static const struct message ml_edit_lbutton_up[] = 11590 { 11591 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 }, 11592 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, 11593 { WM_CAPTURECHANGED, sent|defwinproc }, 11594 { 0 } 11595 }; 11596 11597 static WNDPROC old_edit_proc; 11598 11599 static LRESULT CALLBACK edit_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 11600 { 11601 static LONG defwndproc_counter = 0; 11602 LRESULT ret; 11603 struct recvd_message msg; 11604 11605 if (ignore_message( message )) return 0; 11606 11607 msg.hwnd = hwnd; 11608 msg.message = message; 11609 msg.flags = sent|wparam|lparam; 11610 if (defwndproc_counter) msg.flags |= defwinproc; 11611 msg.wParam = wParam; 11612 msg.lParam = lParam; 11613 msg.descr = "edit"; 11614 add_message(&msg); 11615 11616 defwndproc_counter++; 11617 ret = CallWindowProcA(old_edit_proc, hwnd, message, wParam, lParam); 11618 defwndproc_counter--; 11619 11620 return ret; 11621 } 11622 11623 static void subclass_edit(void) 11624 { 11625 WNDCLASSA cls; 11626 11627 if (!GetClassInfoA(0, "edit", &cls)) assert(0); 11628 11629 old_edit_proc = cls.lpfnWndProc; 11630 11631 cls.hInstance = GetModuleHandleA(NULL); 11632 cls.lpfnWndProc = edit_hook_proc; 11633 cls.lpszClassName = "my_edit_class"; 11634 UnregisterClassA(cls.lpszClassName, cls.hInstance); 11635 if (!RegisterClassA(&cls)) assert(0); 11636 } 11637 11638 static void test_edit_messages(void) 11639 { 11640 HWND hwnd, parent; 11641 DWORD dlg_code; 11642 11643 subclass_edit(); 11644 log_all_parent_messages++; 11645 11646 parent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 11647 100, 100, 200, 200, 0, 0, 0, NULL); 11648 ok (parent != 0, "Failed to create parent window\n"); 11649 11650 /* test single line edit */ 11651 hwnd = CreateWindowExA(0, "my_edit_class", "test", WS_CHILD, 11652 0, 0, 80, 20, parent, (HMENU)ID_EDIT, 0, NULL); 11653 ok(hwnd != 0, "Failed to create edit window\n"); 11654 11655 dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0); 11656 ok(dlg_code == (DLGC_WANTCHARS|DLGC_HASSETSEL|DLGC_WANTARROWS), "wrong dlg_code %08x\n", dlg_code); 11657 11658 flush_sequence(); 11659 SetFocus(hwnd); 11660 ok_sequence(sl_edit_invisible, "SetFocus(hwnd) on an invisible edit", FALSE); 11661 11662 ShowWindow(hwnd, SW_SHOW); 11663 UpdateWindow(hwnd); 11664 SetFocus(0); 11665 flush_sequence(); 11666 11667 SetFocus(hwnd); 11668 ok_sequence(sl_edit_setfocus, "SetFocus(hwnd) on an edit", FALSE); 11669 11670 SetFocus(0); 11671 ok_sequence(sl_edit_killfocus, "SetFocus(0) on an edit", FALSE); 11672 11673 SetFocus(0); 11674 ReleaseCapture(); 11675 flush_sequence(); 11676 11677 SendMessageA(hwnd, WM_LBUTTONDBLCLK, 0, 0); 11678 ok_sequence(sl_edit_lbutton_dblclk, "WM_LBUTTONDBLCLK on an edit", FALSE); 11679 11680 SetFocus(0); 11681 ReleaseCapture(); 11682 flush_sequence(); 11683 11684 SendMessageA(hwnd, WM_LBUTTONDOWN, 0, 0); 11685 ok_sequence(sl_edit_lbutton_down, "WM_LBUTTONDOWN on an edit", FALSE); 11686 11687 SendMessageA(hwnd, WM_LBUTTONUP, 0, 0); 11688 ok_sequence(sl_edit_lbutton_up, "WM_LBUTTONUP on an edit", FALSE); 11689 11690 DestroyWindow(hwnd); 11691 11692 /* test multiline edit */ 11693 hwnd = CreateWindowExA(0, "my_edit_class", "test", WS_CHILD | ES_MULTILINE, 11694 0, 0, 80, 20, parent, (HMENU)ID_EDIT, 0, NULL); 11695 ok(hwnd != 0, "Failed to create edit window\n"); 11696 11697 dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0); 11698 ok(dlg_code == (DLGC_WANTCHARS|DLGC_HASSETSEL|DLGC_WANTARROWS|DLGC_WANTALLKEYS), 11699 "wrong dlg_code %08x\n", dlg_code); 11700 11701 ShowWindow(hwnd, SW_SHOW); 11702 UpdateWindow(hwnd); 11703 SetFocus(0); 11704 flush_sequence(); 11705 11706 SetFocus(hwnd); 11707 ok_sequence(ml_edit_setfocus, "SetFocus(hwnd) on multiline edit", FALSE); 11708 11709 SetFocus(0); 11710 ok_sequence(sl_edit_killfocus, "SetFocus(0) on multiline edit", FALSE); 11711 11712 SetFocus(0); 11713 ReleaseCapture(); 11714 flush_sequence(); 11715 11716 SendMessageA(hwnd, WM_LBUTTONDBLCLK, 0, 0); 11717 ok_sequence(sl_edit_lbutton_dblclk, "WM_LBUTTONDBLCLK on multiline edit", FALSE); 11718 11719 SetFocus(0); 11720 ReleaseCapture(); 11721 flush_sequence(); 11722 11723 SendMessageA(hwnd, WM_LBUTTONDOWN, 0, 0); 11724 ok_sequence(ml_edit_lbutton_down, "WM_LBUTTONDOWN on multiline edit", FALSE); 11725 11726 SendMessageA(hwnd, WM_LBUTTONUP, 0, 0); 11727 ok_sequence(ml_edit_lbutton_up, "WM_LBUTTONUP on multiline edit", FALSE); 11728 11729 DestroyWindow(hwnd); 11730 DestroyWindow(parent); 11731 11732 log_all_parent_messages--; 11733 } 11734 11735 /**************************** End of Edit test ******************************/ 11736 11737 static const struct message WmKeyDownSkippedSeq[] = 11738 { 11739 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */ 11740 { 0 } 11741 }; 11742 static const struct message WmKeyDownWasDownSkippedSeq[] = 11743 { 11744 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0x40000001 }, /* XP */ 11745 { 0 } 11746 }; 11747 static const struct message WmKeyUpSkippedSeq[] = 11748 { 11749 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */ 11750 { 0 } 11751 }; 11752 static const struct message WmUserKeyUpSkippedSeq[] = 11753 { 11754 { WM_USER, sent }, 11755 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */ 11756 { 0 } 11757 }; 11758 11759 #define EV_STOP 0 11760 #define EV_SENDMSG 1 11761 #define EV_ACK 2 11762 11763 struct peekmsg_info 11764 { 11765 HWND hwnd; 11766 HANDLE hevent[3]; /* 0 - start/stop, 1 - SendMessage, 2 - ack */ 11767 }; 11768 11769 static DWORD CALLBACK send_msg_thread_2(void *param) 11770 { 11771 DWORD ret; 11772 struct peekmsg_info *info = param; 11773 11774 trace("thread: looping\n"); 11775 SetEvent(info->hevent[EV_ACK]); 11776 11777 while (1) 11778 { 11779 ret = WaitForMultipleObjects(2, info->hevent, FALSE, INFINITE); 11780 11781 switch (ret) 11782 { 11783 case WAIT_OBJECT_0 + EV_STOP: 11784 trace("thread: exiting\n"); 11785 return 0; 11786 11787 case WAIT_OBJECT_0 + EV_SENDMSG: 11788 trace("thread: sending message\n"); 11789 ret = SendNotifyMessageA(info->hwnd, WM_USER, 0, 0); 11790 ok(ret, "SendNotifyMessageA failed error %u\n", GetLastError()); 11791 SetEvent(info->hevent[EV_ACK]); 11792 break; 11793 11794 default: 11795 trace("unexpected return: %04x\n", ret); 11796 assert(0); 11797 break; 11798 } 11799 } 11800 return 0; 11801 } 11802 11803 static void test_PeekMessage(void) 11804 { 11805 MSG msg; 11806 HANDLE hthread; 11807 DWORD tid, qstatus; 11808 UINT qs_all_input = QS_ALLINPUT; 11809 UINT qs_input = QS_INPUT; 11810 BOOL ret; 11811 struct peekmsg_info info; 11812 11813 info.hwnd = CreateWindowA("TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, 11814 100, 100, 200, 200, 0, 0, 0, NULL); 11815 assert(info.hwnd); 11816 ShowWindow(info.hwnd, SW_SHOW); 11817 UpdateWindow(info.hwnd); 11818 SetFocus(info.hwnd); 11819 11820 info.hevent[EV_STOP] = CreateEventA(NULL, 0, 0, NULL); 11821 info.hevent[EV_SENDMSG] = CreateEventA(NULL, 0, 0, NULL); 11822 info.hevent[EV_ACK] = CreateEventA(NULL, 0, 0, NULL); 11823 11824 hthread = CreateThread(NULL, 0, send_msg_thread_2, &info, 0, &tid); 11825 WaitForSingleObject(info.hevent[EV_ACK], 10000); 11826 11827 flush_events(); 11828 flush_sequence(); 11829 11830 SetLastError(0xdeadbeef); 11831 qstatus = GetQueueStatus(qs_all_input); 11832 if (GetLastError() == ERROR_INVALID_FLAGS) 11833 { 11834 trace("QS_RAWINPUT not supported on this platform\n"); 11835 qs_all_input &= ~QS_RAWINPUT; 11836 qs_input &= ~QS_RAWINPUT; 11837 } 11838 if (qstatus & QS_POSTMESSAGE) 11839 { 11840 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) /* nothing */ ; 11841 qstatus = GetQueueStatus(qs_all_input); 11842 } 11843 ok(qstatus == 0, "wrong qstatus %08x\n", qstatus); 11844 11845 trace("signalling to send message\n"); 11846 SetEvent(info.hevent[EV_SENDMSG]); 11847 WaitForSingleObject(info.hevent[EV_ACK], INFINITE); 11848 11849 /* pass invalid QS_xxxx flags */ 11850 SetLastError(0xdeadbeef); 11851 qstatus = GetQueueStatus(0xffffffff); 11852 ok(qstatus == 0 || broken(qstatus) /* win9x */, "GetQueueStatus should fail: %08x\n", qstatus); 11853 if (!qstatus) 11854 { 11855 ok(GetLastError() == ERROR_INVALID_FLAGS, "wrong error %d\n", GetLastError()); 11856 qstatus = GetQueueStatus(qs_all_input); 11857 } 11858 qstatus &= ~MAKELONG( 0x4000, 0x4000 ); /* sometimes set on Win95 */ 11859 ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE), 11860 "wrong qstatus %08x\n", qstatus); 11861 11862 msg.message = 0; 11863 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); 11864 ok(!ret, 11865 "PeekMessageA should have returned FALSE instead of msg %04x\n", 11866 msg.message); 11867 ok_sequence(WmUser, "WmUser", FALSE); 11868 11869 qstatus = GetQueueStatus(qs_all_input); 11870 ok(qstatus == 0, "wrong qstatus %08x\n", qstatus); 11871 11872 keybd_event('N', 0, 0, 0); 11873 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 11874 qstatus = GetQueueStatus(qs_all_input); 11875 if (!(qstatus & MAKELONG(QS_KEY, QS_KEY))) 11876 { 11877 skip( "queuing key events not supported\n" ); 11878 goto done; 11879 } 11880 ok(qstatus == MAKELONG(QS_KEY, QS_KEY) || 11881 /* keybd_event seems to trigger a sent message on NT4 */ 11882 qstatus == MAKELONG(QS_KEY|QS_SENDMESSAGE, QS_KEY|QS_SENDMESSAGE), 11883 "wrong qstatus %08x\n", qstatus); 11884 11885 PostMessageA(info.hwnd, WM_CHAR, 'z', 0); 11886 qstatus = GetQueueStatus(qs_all_input); 11887 ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY) || 11888 qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY|QS_SENDMESSAGE), 11889 "wrong qstatus %08x\n", qstatus); 11890 11891 InvalidateRect(info.hwnd, NULL, FALSE); 11892 qstatus = GetQueueStatus(qs_all_input); 11893 ok(qstatus == MAKELONG(QS_PAINT, QS_PAINT|QS_POSTMESSAGE|QS_KEY) || 11894 qstatus == MAKELONG(QS_PAINT, QS_PAINT|QS_POSTMESSAGE|QS_KEY|QS_SENDMESSAGE), 11895 "wrong qstatus %08x\n", qstatus); 11896 11897 trace("signalling to send message\n"); 11898 SetEvent(info.hevent[EV_SENDMSG]); 11899 WaitForSingleObject(info.hevent[EV_ACK], INFINITE); 11900 11901 qstatus = GetQueueStatus(qs_all_input); 11902 ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_PAINT|QS_POSTMESSAGE|QS_KEY), 11903 "wrong qstatus %08x\n", qstatus); 11904 11905 msg.message = 0; 11906 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | (qs_input << 16)); 11907 if (ret && msg.message == WM_CHAR) 11908 { 11909 win_skip( "PM_QS_* flags not supported in PeekMessage\n" ); 11910 goto done; 11911 } 11912 ok(!ret, 11913 "PeekMessageA should have returned FALSE instead of msg %04x\n", 11914 msg.message); 11915 if (!sequence_cnt) /* nt4 doesn't fetch anything with PM_QS_* flags */ 11916 { 11917 win_skip( "PM_QS_* flags not supported in PeekMessage\n" ); 11918 goto done; 11919 } 11920 ok_sequence(WmUser, "WmUser", FALSE); 11921 11922 qstatus = GetQueueStatus(qs_all_input); 11923 ok(qstatus == MAKELONG(0, QS_PAINT|QS_POSTMESSAGE|QS_KEY), 11924 "wrong qstatus %08x\n", qstatus); 11925 11926 trace("signalling to send message\n"); 11927 SetEvent(info.hevent[EV_SENDMSG]); 11928 WaitForSingleObject(info.hevent[EV_ACK], INFINITE); 11929 11930 qstatus = GetQueueStatus(qs_all_input); 11931 ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_PAINT|QS_POSTMESSAGE|QS_KEY), 11932 "wrong qstatus %08x\n", qstatus); 11933 11934 msg.message = 0; 11935 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_POSTMESSAGE ); 11936 ok(!ret, 11937 "PeekMessageA should have returned FALSE instead of msg %04x\n", 11938 msg.message); 11939 ok_sequence(WmUser, "WmUser", FALSE); 11940 11941 qstatus = GetQueueStatus(qs_all_input); 11942 ok(qstatus == MAKELONG(0, QS_PAINT|QS_POSTMESSAGE|QS_KEY), 11943 "wrong qstatus %08x\n", qstatus); 11944 11945 msg.message = 0; 11946 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_POSTMESSAGE); 11947 ok(ret && msg.message == WM_CHAR && msg.wParam == 'z', 11948 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n", 11949 ret, msg.message, msg.wParam); 11950 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE); 11951 11952 qstatus = GetQueueStatus(qs_all_input); 11953 ok(qstatus == MAKELONG(0, QS_PAINT|QS_KEY), 11954 "wrong qstatus %08x\n", qstatus); 11955 11956 msg.message = 0; 11957 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_POSTMESSAGE); 11958 ok(!ret, 11959 "PeekMessageA should have returned FALSE instead of msg %04x\n", 11960 msg.message); 11961 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE); 11962 11963 qstatus = GetQueueStatus(qs_all_input); 11964 ok(qstatus == MAKELONG(0, QS_PAINT|QS_KEY), 11965 "wrong qstatus %08x\n", qstatus); 11966 11967 msg.message = 0; 11968 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_PAINT); 11969 ok(ret && msg.message == WM_PAINT, 11970 "got %d and %04x instead of TRUE and WM_PAINT\n", ret, msg.message); 11971 DispatchMessageA(&msg); 11972 ok_sequence(WmPaint, "WmPaint", FALSE); 11973 11974 qstatus = GetQueueStatus(qs_all_input); 11975 ok(qstatus == MAKELONG(0, QS_KEY), 11976 "wrong qstatus %08x\n", qstatus); 11977 11978 msg.message = 0; 11979 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_PAINT); 11980 ok(!ret, 11981 "PeekMessageA should have returned FALSE instead of msg %04x\n", 11982 msg.message); 11983 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE); 11984 11985 qstatus = GetQueueStatus(qs_all_input); 11986 ok(qstatus == MAKELONG(0, QS_KEY), 11987 "wrong qstatus %08x\n", qstatus); 11988 11989 trace("signalling to send message\n"); 11990 SetEvent(info.hevent[EV_SENDMSG]); 11991 WaitForSingleObject(info.hevent[EV_ACK], INFINITE); 11992 11993 qstatus = GetQueueStatus(qs_all_input); 11994 ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_KEY), 11995 "wrong qstatus %08x\n", qstatus); 11996 11997 PostMessageA(info.hwnd, WM_CHAR, 'z', 0); 11998 11999 qstatus = GetQueueStatus(qs_all_input); 12000 ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_SENDMESSAGE|QS_POSTMESSAGE|QS_KEY), 12001 "wrong qstatus %08x\n", qstatus); 12002 12003 msg.message = 0; 12004 ret = PeekMessageA(&msg, 0, WM_CHAR, WM_CHAR, PM_REMOVE); 12005 ok(ret && msg.message == WM_CHAR && msg.wParam == 'z', 12006 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n", 12007 ret, msg.message, msg.wParam); 12008 ok_sequence(WmUser, "WmUser", FALSE); 12009 12010 qstatus = GetQueueStatus(qs_all_input); 12011 ok(qstatus == MAKELONG(0, QS_KEY), 12012 "wrong qstatus %08x\n", qstatus); 12013 12014 msg.message = 0; 12015 ret = PeekMessageA(&msg, 0, WM_CHAR, WM_CHAR, PM_REMOVE); 12016 ok(!ret, 12017 "PeekMessageA should have returned FALSE instead of msg %04x\n", 12018 msg.message); 12019 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE); 12020 12021 qstatus = GetQueueStatus(qs_all_input); 12022 ok(qstatus == MAKELONG(0, QS_KEY), 12023 "wrong qstatus %08x\n", qstatus); 12024 12025 PostMessageA(info.hwnd, WM_CHAR, 'z', 0); 12026 12027 qstatus = GetQueueStatus(qs_all_input); 12028 ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY), 12029 "wrong qstatus %08x\n", qstatus); 12030 12031 trace("signalling to send message\n"); 12032 SetEvent(info.hevent[EV_SENDMSG]); 12033 WaitForSingleObject(info.hevent[EV_ACK], INFINITE); 12034 12035 qstatus = GetQueueStatus(qs_all_input); 12036 ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_POSTMESSAGE|QS_KEY), 12037 "wrong qstatus %08x\n", qstatus); 12038 12039 msg.message = 0; 12040 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | (QS_KEY << 16)); 12041 ok(!ret, 12042 "PeekMessageA should have returned FALSE instead of msg %04x\n", 12043 msg.message); 12044 ok_sequence(WmUser, "WmUser", FALSE); 12045 12046 qstatus = GetQueueStatus(qs_all_input); 12047 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE|QS_KEY), 12048 "wrong qstatus %08x\n", qstatus); 12049 12050 msg.message = 0; 12051 if (qs_all_input & QS_RAWINPUT) /* use QS_RAWINPUT only if supported */ 12052 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | (QS_RAWINPUT << 16)); 12053 else /* workaround for a missing QS_RAWINPUT support */ 12054 ret = PeekMessageA(&msg, 0, WM_KEYDOWN, WM_KEYDOWN, PM_REMOVE); 12055 ok(ret && msg.message == WM_KEYDOWN && msg.wParam == 'N', 12056 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n", 12057 ret, msg.message, msg.wParam); 12058 ok_sequence(WmKeyDownSkippedSeq, "WmKeyDownSkippedSeq", FALSE); 12059 12060 qstatus = GetQueueStatus(qs_all_input); 12061 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE|QS_KEY), 12062 "wrong qstatus %08x\n", qstatus); 12063 12064 msg.message = 0; 12065 if (qs_all_input & QS_RAWINPUT) /* use QS_RAWINPUT only if supported */ 12066 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | (QS_RAWINPUT << 16)); 12067 else /* workaround for a missing QS_RAWINPUT support */ 12068 ret = PeekMessageA(&msg, 0, WM_KEYUP, WM_KEYUP, PM_REMOVE); 12069 ok(ret && msg.message == WM_KEYUP && msg.wParam == 'N', 12070 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYUP wParam 'N'\n", 12071 ret, msg.message, msg.wParam); 12072 ok_sequence(WmKeyUpSkippedSeq, "WmKeyUpSkippedSeq", FALSE); 12073 12074 qstatus = GetQueueStatus(qs_all_input); 12075 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE), 12076 "wrong qstatus %08x\n", qstatus); 12077 12078 msg.message = 0; 12079 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE); 12080 ok(!ret, 12081 "PeekMessageA should have returned FALSE instead of msg %04x\n", 12082 msg.message); 12083 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE); 12084 12085 qstatus = GetQueueStatus(qs_all_input); 12086 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE), 12087 "wrong qstatus %08x\n", qstatus); 12088 12089 msg.message = 0; 12090 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); 12091 ok(ret && msg.message == WM_CHAR && msg.wParam == 'z', 12092 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n", 12093 ret, msg.message, msg.wParam); 12094 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE); 12095 12096 qstatus = GetQueueStatus(qs_all_input); 12097 ok(qstatus == 0, 12098 "wrong qstatus %08x\n", qstatus); 12099 12100 msg.message = 0; 12101 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); 12102 ok(!ret, 12103 "PeekMessageA should have returned FALSE instead of msg %04x\n", 12104 msg.message); 12105 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE); 12106 12107 qstatus = GetQueueStatus(qs_all_input); 12108 ok(qstatus == 0, 12109 "wrong qstatus %08x\n", qstatus); 12110 12111 /* test whether presence of the quit flag in the queue affects 12112 * the queue state 12113 */ 12114 PostQuitMessage(0x1234abcd); 12115 12116 qstatus = GetQueueStatus(qs_all_input); 12117 ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE), 12118 "wrong qstatus %08x\n", qstatus); 12119 12120 PostMessageA(info.hwnd, WM_USER, 0, 0); 12121 12122 qstatus = GetQueueStatus(qs_all_input); 12123 ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE), 12124 "wrong qstatus %08x\n", qstatus); 12125 12126 msg.message = 0; 12127 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); 12128 ok(ret && msg.message == WM_USER, 12129 "got %d and %04x instead of TRUE and WM_USER\n", ret, msg.message); 12130 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE); 12131 12132 qstatus = GetQueueStatus(qs_all_input); 12133 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE), 12134 "wrong qstatus %08x\n", qstatus); 12135 12136 msg.message = 0; 12137 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); 12138 ok(ret && msg.message == WM_QUIT, 12139 "got %d and %04x instead of TRUE and WM_QUIT\n", ret, msg.message); 12140 ok(msg.wParam == 0x1234abcd, "got wParam %08lx instead of 0x1234abcd\n", msg.wParam); 12141 ok(msg.lParam == 0, "got lParam %08lx instead of 0\n", msg.lParam); 12142 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE); 12143 12144 qstatus = GetQueueStatus(qs_all_input); 12145 todo_wine { 12146 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE), 12147 "wrong qstatus %08x\n", qstatus); 12148 } 12149 12150 msg.message = 0; 12151 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); 12152 ok(!ret, 12153 "PeekMessageA should have returned FALSE instead of msg %04x\n", 12154 msg.message); 12155 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE); 12156 12157 qstatus = GetQueueStatus(qs_all_input); 12158 ok(qstatus == 0, 12159 "wrong qstatus %08x\n", qstatus); 12160 12161 /* some GetMessage tests */ 12162 12163 keybd_event('N', 0, 0, 0); 12164 qstatus = GetQueueStatus(qs_all_input); 12165 ok(qstatus == MAKELONG(QS_KEY, QS_KEY), "wrong qstatus %08x\n", qstatus); 12166 12167 PostMessageA(info.hwnd, WM_CHAR, 'z', 0); 12168 qstatus = GetQueueStatus(qs_all_input); 12169 ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY), "wrong qstatus %08x\n", qstatus); 12170 12171 if (qstatus) 12172 { 12173 ret = GetMessageA( &msg, 0, 0, 0 ); 12174 ok(ret && msg.message == WM_CHAR && msg.wParam == 'z', 12175 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n", 12176 ret, msg.message, msg.wParam); 12177 qstatus = GetQueueStatus(qs_all_input); 12178 ok(qstatus == MAKELONG(0, QS_KEY), "wrong qstatus %08x\n", qstatus); 12179 } 12180 12181 if (qstatus) 12182 { 12183 ret = GetMessageA( &msg, 0, 0, 0 ); 12184 ok(ret && msg.message == WM_KEYDOWN && msg.wParam == 'N', 12185 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n", 12186 ret, msg.message, msg.wParam); 12187 ok_sequence(WmKeyDownSkippedSeq, "WmKeyDownSkippedSeq", FALSE); 12188 qstatus = GetQueueStatus(qs_all_input); 12189 ok(qstatus == 0, "wrong qstatus %08x\n", qstatus); 12190 } 12191 12192 keybd_event('N', 0, 0, 0); 12193 qstatus = GetQueueStatus(qs_all_input); 12194 ok(qstatus == MAKELONG(QS_KEY, QS_KEY), "wrong qstatus %08x\n", qstatus); 12195 12196 PostMessageA(info.hwnd, WM_CHAR, 'z', 0); 12197 qstatus = GetQueueStatus(qs_all_input); 12198 ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY), "wrong qstatus %08x\n", qstatus); 12199 12200 if (qstatus & (QS_KEY << 16)) 12201 { 12202 ret = GetMessageA( &msg, 0, WM_KEYDOWN, WM_KEYUP ); 12203 ok(ret && msg.message == WM_KEYDOWN && msg.wParam == 'N', 12204 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n", 12205 ret, msg.message, msg.wParam); 12206 ok_sequence(WmKeyDownWasDownSkippedSeq, "WmKeyDownWasDownSkippedSeq", FALSE); 12207 qstatus = GetQueueStatus(qs_all_input); 12208 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE), "wrong qstatus %08x\n", qstatus); 12209 } 12210 12211 if (qstatus) 12212 { 12213 ret = GetMessageA( &msg, 0, WM_CHAR, WM_CHAR ); 12214 ok(ret && msg.message == WM_CHAR && msg.wParam == 'z', 12215 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n", 12216 ret, msg.message, msg.wParam); 12217 qstatus = GetQueueStatus(qs_all_input); 12218 ok(qstatus == 0, "wrong qstatus %08x\n", qstatus); 12219 } 12220 12221 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 12222 qstatus = GetQueueStatus(qs_all_input); 12223 ok(qstatus == MAKELONG(QS_KEY, QS_KEY), "wrong qstatus %08x\n", qstatus); 12224 12225 PostMessageA(info.hwnd, WM_CHAR, 'z', 0); 12226 qstatus = GetQueueStatus(qs_all_input); 12227 ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY), "wrong qstatus %08x\n", qstatus); 12228 12229 trace("signalling to send message\n"); 12230 SetEvent(info.hevent[EV_SENDMSG]); 12231 WaitForSingleObject(info.hevent[EV_ACK], INFINITE); 12232 qstatus = GetQueueStatus(qs_all_input); 12233 ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_POSTMESSAGE|QS_KEY), 12234 "wrong qstatus %08x\n", qstatus); 12235 12236 if (qstatus & (QS_KEY << 16)) 12237 { 12238 ret = GetMessageA( &msg, 0, WM_KEYDOWN, WM_KEYUP ); 12239 ok(ret && msg.message == WM_KEYUP && msg.wParam == 'N', 12240 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n", 12241 ret, msg.message, msg.wParam); 12242 ok_sequence(WmUserKeyUpSkippedSeq, "WmUserKeyUpSkippedSeq", FALSE); 12243 qstatus = GetQueueStatus(qs_all_input); 12244 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE), "wrong qstatus %08x\n", qstatus); 12245 } 12246 12247 if (qstatus) 12248 { 12249 ret = GetMessageA( &msg, 0, WM_CHAR, WM_CHAR ); 12250 ok(ret && msg.message == WM_CHAR && msg.wParam == 'z', 12251 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n", 12252 ret, msg.message, msg.wParam); 12253 qstatus = GetQueueStatus(qs_all_input); 12254 ok(qstatus == 0, "wrong qstatus %08x\n", qstatus); 12255 } 12256 12257 PostThreadMessageA(GetCurrentThreadId(), WM_USER, 0, 0); 12258 ret = PeekMessageA(&msg, (HWND)-1, 0, 0, PM_NOREMOVE); 12259 ok(ret == TRUE, "wrong ret %d\n", ret); 12260 ok(msg.message == WM_USER, "wrong message %u\n", msg.message); 12261 ret = GetMessageA(&msg, (HWND)-1, 0, 0); 12262 ok(ret == TRUE, "wrong ret %d\n", ret); 12263 ok(msg.message == WM_USER, "wrong message %u\n", msg.message); 12264 12265 PostThreadMessageA(GetCurrentThreadId(), WM_USER, 0, 0); 12266 ret = PeekMessageA(&msg, (HWND)1, 0, 0, PM_NOREMOVE); 12267 ok(ret == TRUE, "wrong ret %d\n", ret); 12268 ok(msg.message == WM_USER, "wrong message %u\n", msg.message); 12269 ret = GetMessageA(&msg, (HWND)1, 0, 0); 12270 ok(ret == TRUE, "wrong ret %d\n", ret); 12271 ok(msg.message == WM_USER, "wrong message %u\n", msg.message); 12272 12273 PostThreadMessageA(GetCurrentThreadId(), WM_USER, 0, 0); 12274 ret = PeekMessageA(&msg, (HWND)0xffff, 0, 0, PM_NOREMOVE); 12275 ok(ret == TRUE, "wrong ret %d\n", ret); 12276 ok(msg.message == WM_USER, "wrong message %u\n", msg.message); 12277 ret = GetMessageA(&msg, (HWND)0xffff, 0, 0); 12278 ok(ret == TRUE, "wrong ret %d\n", ret); 12279 ok(msg.message == WM_USER, "wrong message %u\n", msg.message); 12280 12281 done: 12282 trace("signalling to exit\n"); 12283 SetEvent(info.hevent[EV_STOP]); 12284 12285 WaitForSingleObject(hthread, INFINITE); 12286 12287 CloseHandle(hthread); 12288 CloseHandle(info.hevent[0]); 12289 CloseHandle(info.hevent[1]); 12290 CloseHandle(info.hevent[2]); 12291 12292 DestroyWindow(info.hwnd); 12293 } 12294 12295 static void wait_move_event(HWND hwnd, int x, int y) 12296 { 12297 MSG msg; 12298 DWORD time; 12299 BOOL ret; 12300 12301 time = GetTickCount(); 12302 while (GetTickCount() - time < 200) { 12303 ret = PeekMessageA(&msg, hwnd, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_NOREMOVE); 12304 if (ret && msg.pt.x > x && msg.pt.y > y) break; 12305 if (!ret) MsgWaitForMultipleObjects( 0, NULL, FALSE, GetTickCount() - time, QS_ALLINPUT ); 12306 else Sleep( GetTickCount() - time ); 12307 } 12308 } 12309 12310 #define STEP 5 12311 static void test_PeekMessage2(void) 12312 { 12313 HWND hwnd; 12314 BOOL ret; 12315 MSG msg; 12316 UINT message; 12317 DWORD time1, time2, time3; 12318 int x1, y1, x2, y2, x3, y3; 12319 POINT pos; 12320 12321 time1 = time2 = time3 = 0; 12322 x1 = y1 = x2 = y2 = x3 = y3 = 0; 12323 12324 /* Initialise window and make sure it is ready for events */ 12325 hwnd = CreateWindowA("TestWindowClass", "PeekMessage2", WS_OVERLAPPEDWINDOW, 12326 10, 10, 800, 800, NULL, NULL, NULL, NULL); 12327 assert(hwnd); 12328 trace("Window for test_PeekMessage2 %p\n", hwnd); 12329 ShowWindow(hwnd, SW_SHOW); 12330 UpdateWindow(hwnd); 12331 SetFocus(hwnd); 12332 GetCursorPos(&pos); 12333 SetCursorPos(100, 100); 12334 mouse_event(MOUSEEVENTF_MOVE, -STEP, -STEP, 0, 0); 12335 flush_events(); 12336 12337 /* Do initial mousemove, wait until we can see it 12338 and then do our test peek with PM_NOREMOVE. */ 12339 mouse_event(MOUSEEVENTF_MOVE, STEP, STEP, 0, 0); 12340 wait_move_event(hwnd, 100-STEP, 100-STEP); 12341 12342 ret = PeekMessageA(&msg, hwnd, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_NOREMOVE); 12343 if (!ret) 12344 { 12345 skip( "queuing mouse events not supported\n" ); 12346 goto done; 12347 } 12348 else 12349 { 12350 trace("1st move event: %04x %x %d %d\n", msg.message, msg.time, msg.pt.x, msg.pt.y); 12351 message = msg.message; 12352 time1 = msg.time; 12353 x1 = msg.pt.x; 12354 y1 = msg.pt.y; 12355 ok(message == WM_MOUSEMOVE, "message not WM_MOUSEMOVE, %04x instead\n", message); 12356 } 12357 12358 /* Allow time to advance a bit, and then simulate the user moving their 12359 * mouse around. After that we peek again with PM_NOREMOVE. 12360 * Although the previous mousemove message was never removed, the 12361 * mousemove we now peek should reflect the recent mouse movements 12362 * because the input queue will merge the move events. */ 12363 Sleep(100); 12364 mouse_event(MOUSEEVENTF_MOVE, STEP, STEP, 0, 0); 12365 wait_move_event(hwnd, x1, y1); 12366 12367 ret = PeekMessageA(&msg, hwnd, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_NOREMOVE); 12368 ok(ret, "no message available\n"); 12369 if (ret) { 12370 trace("2nd move event: %04x %x %d %d\n", msg.message, msg.time, msg.pt.x, msg.pt.y); 12371 message = msg.message; 12372 time2 = msg.time; 12373 x2 = msg.pt.x; 12374 y2 = msg.pt.y; 12375 ok(message == WM_MOUSEMOVE, "message not WM_MOUSEMOVE, %04x instead\n", message); 12376 ok(time2 > time1, "message time not advanced: %x %x\n", time1, time2); 12377 ok(x2 != x1 && y2 != y1, "coords not changed: (%d %d) (%d %d)\n", x1, y1, x2, y2); 12378 } 12379 12380 /* Have another go, to drive the point home */ 12381 Sleep(100); 12382 mouse_event(MOUSEEVENTF_MOVE, STEP, STEP, 0, 0); 12383 wait_move_event(hwnd, x2, y2); 12384 12385 ret = PeekMessageA(&msg, hwnd, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_NOREMOVE); 12386 ok(ret, "no message available\n"); 12387 if (ret) { 12388 trace("3rd move event: %04x %x %d %d\n", msg.message, msg.time, msg.pt.x, msg.pt.y); 12389 message = msg.message; 12390 time3 = msg.time; 12391 x3 = msg.pt.x; 12392 y3 = msg.pt.y; 12393 ok(message == WM_MOUSEMOVE, "message not WM_MOUSEMOVE, %04x instead\n", message); 12394 ok(time3 > time2, "message time not advanced: %x %x\n", time2, time3); 12395 ok(x3 != x2 && y3 != y2, "coords not changed: (%d %d) (%d %d)\n", x2, y2, x3, y3); 12396 } 12397 12398 done: 12399 DestroyWindow(hwnd); 12400 SetCursorPos(pos.x, pos.y); 12401 flush_events(); 12402 } 12403 12404 static void test_PeekMessage3(void) 12405 { 12406 HWND hwnd; 12407 BOOL ret; 12408 MSG msg; 12409 12410 hwnd = CreateWindowA("TestWindowClass", "PeekMessage3", WS_OVERLAPPEDWINDOW, 12411 10, 10, 800, 800, NULL, NULL, NULL, NULL); 12412 ok(hwnd != NULL, "expected hwnd != NULL\n"); 12413 flush_events(); 12414 12415 /* GetMessage() and PeekMessage(..., PM_REMOVE) should prefer messages which 12416 * were already seen. */ 12417 12418 SetTimer(hwnd, 1, 0, NULL); 12419 while (!PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE)); 12420 ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12421 PostMessageA(hwnd, WM_USER, 0, 0); 12422 ret = PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE); 12423 ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12424 ret = GetMessageA(&msg, NULL, 0, 0); 12425 ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12426 ret = GetMessageA(&msg, NULL, 0, 0); 12427 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); 12428 ret = PeekMessageA(&msg, NULL, 0, 0, 0); 12429 ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret); 12430 12431 SetTimer(hwnd, 1, 0, NULL); 12432 while (!PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE)); 12433 ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12434 PostMessageA(hwnd, WM_USER, 0, 0); 12435 ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE); 12436 ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12437 ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE); 12438 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); 12439 ret = PeekMessageA(&msg, NULL, 0, 0, 0); 12440 ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret); 12441 12442 /* It doesn't matter if a message range is specified or not. */ 12443 12444 SetTimer(hwnd, 1, 0, NULL); 12445 while (!PeekMessageA(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE)); 12446 ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12447 PostMessageA(hwnd, WM_USER, 0, 0); 12448 ret = GetMessageA(&msg, NULL, 0, 0); 12449 ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12450 ret = GetMessageA(&msg, NULL, 0, 0); 12451 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); 12452 ret = PeekMessageA(&msg, NULL, 0, 0, 0); 12453 ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret); 12454 12455 /* But not if the post messages were added before the PeekMessage() call. */ 12456 12457 PostMessageA(hwnd, WM_USER, 0, 0); 12458 SetTimer(hwnd, 1, 0, NULL); 12459 while (!PeekMessageA(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE)); 12460 ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12461 ret = GetMessageA(&msg, NULL, 0, 0); 12462 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); 12463 ret = GetMessageA(&msg, NULL, 0, 0); 12464 ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12465 ret = PeekMessageA(&msg, NULL, 0, 0, 0); 12466 ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret); 12467 12468 /* More complicated test with multiple messages. */ 12469 12470 PostMessageA(hwnd, WM_USER, 0, 0); 12471 SetTimer(hwnd, 1, 0, NULL); 12472 while (!PeekMessageA(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE)); 12473 ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12474 PostMessageA(hwnd, WM_USER + 1, 0, 0); 12475 ret = GetMessageA(&msg, NULL, 0, 0); 12476 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); 12477 ret = GetMessageA(&msg, NULL, 0, 0); 12478 ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12479 ret = GetMessageA(&msg, NULL, 0, 0); 12480 ok(ret && msg.message == WM_USER + 1, "msg.message = %u instead of WM_USER + 1\n", msg.message); 12481 ret = PeekMessageA(&msg, NULL, 0, 0, 0); 12482 ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret); 12483 12484 /* Newer messages are still returned when specifying a message range. */ 12485 12486 SetTimer(hwnd, 1, 0, NULL); 12487 while (!PeekMessageA(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE)); 12488 ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12489 PostMessageA(hwnd, WM_USER + 1, 0, 0); 12490 PostMessageA(hwnd, WM_USER, 0, 0); 12491 ret = PeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); 12492 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); 12493 ret = PeekMessageA(&msg, NULL, WM_USER, WM_USER + 1, PM_NOREMOVE); 12494 ok(ret && msg.message == WM_USER + 1, "msg.message = %u instead of WM_USER + 1\n", msg.message); 12495 ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE); 12496 ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12497 ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE); 12498 ok(ret && msg.message == WM_USER + 1, "msg.message = %u instead of WM_USER + 1\n", msg.message); 12499 ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE); 12500 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); 12501 ret = PeekMessageA(&msg, NULL, 0, 0, 0); 12502 ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret); 12503 12504 /* Also works for posted messages, but the situation is a bit different, 12505 * because both messages are in the same queue. */ 12506 12507 PostMessageA(hwnd, WM_TIMER, 0, 0); 12508 while (!PeekMessageA(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE)); 12509 ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12510 PostMessageA(hwnd, WM_USER, 0, 0); 12511 ret = GetMessageA(&msg, NULL, 0, 0); 12512 ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12513 ret = GetMessageA(&msg, NULL, 0, 0); 12514 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); 12515 ret = PeekMessageA(&msg, NULL, 0, 0, 0); 12516 ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret); 12517 12518 PostMessageA(hwnd, WM_USER, 0, 0); 12519 PostMessageA(hwnd, WM_TIMER, 0, 0); 12520 while (!PeekMessageA(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE)); 12521 ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12522 ret = GetMessageA(&msg, NULL, 0, 0); 12523 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); 12524 ret = GetMessageA(&msg, NULL, 0, 0); 12525 ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12526 ret = PeekMessageA(&msg, NULL, 0, 0, 0); 12527 ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret); 12528 12529 DestroyWindow(hwnd); 12530 flush_events(); 12531 } 12532 12533 static INT_PTR CALLBACK wm_quit_dlg_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) 12534 { 12535 struct recvd_message msg; 12536 12537 if (ignore_message( message )) return 0; 12538 12539 msg.hwnd = hwnd; 12540 msg.message = message; 12541 msg.flags = sent|wparam|lparam; 12542 msg.wParam = wp; 12543 msg.lParam = lp; 12544 msg.descr = "dialog"; 12545 add_message(&msg); 12546 12547 switch (message) 12548 { 12549 case WM_INITDIALOG: 12550 PostMessageA(hwnd, WM_QUIT, 0x1234, 0x5678); 12551 PostMessageA(hwnd, WM_USER, 0xdead, 0xbeef); 12552 return 0; 12553 12554 case WM_GETDLGCODE: 12555 return 0; 12556 12557 case WM_USER: 12558 EndDialog(hwnd, 0); 12559 break; 12560 } 12561 12562 return 1; 12563 } 12564 12565 static const struct message WmQuitDialogSeq[] = { 12566 { HCBT_CREATEWND, hook }, 12567 { WM_SETFONT, sent }, 12568 { WM_INITDIALOG, sent }, 12569 { WM_CHANGEUISTATE, sent|optional }, 12570 { HCBT_DESTROYWND, hook }, 12571 { 0x0090, sent|optional }, /* Vista */ 12572 { WM_DESTROY, sent }, 12573 { WM_NCDESTROY, sent }, 12574 { 0 } 12575 }; 12576 12577 static const struct message WmStopQuitSeq[] = { 12578 { WM_DWMNCRENDERINGCHANGED, posted|optional }, 12579 { WM_CLOSE, posted }, 12580 { WM_QUIT, posted|wparam|lparam, 0x1234, 0 }, 12581 { 0 } 12582 }; 12583 12584 static void test_quit_message(void) 12585 { 12586 MSG msg; 12587 BOOL ret; 12588 12589 /* test using PostQuitMessage */ 12590 flush_events(); 12591 PostQuitMessage(0xbeef); 12592 12593 msg.message = 0; 12594 ret = PeekMessageA(&msg, 0, 0, 0, PM_QS_SENDMESSAGE); 12595 ok(!ret, "got %x message\n", msg.message); 12596 12597 ret = PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE); 12598 ok(ret, "PeekMessage failed with error %d\n", GetLastError()); 12599 ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message); 12600 ok(msg.wParam == 0xbeef, "wParam was 0x%lx instead of 0xbeef\n", msg.wParam); 12601 12602 ret = PostThreadMessageA(GetCurrentThreadId(), WM_USER, 0, 0); 12603 ok(ret, "PostMessage failed with error %d\n", GetLastError()); 12604 12605 ret = GetMessageA(&msg, NULL, 0, 0); 12606 ok(ret > 0, "GetMessage failed with error %d\n", GetLastError()); 12607 ok(msg.message == WM_USER, "Received message 0x%04x instead of WM_USER\n", msg.message); 12608 12609 /* note: WM_QUIT message received after WM_USER message */ 12610 ret = GetMessageA(&msg, NULL, 0, 0); 12611 ok(!ret, "GetMessage return %d with error %d instead of FALSE\n", ret, GetLastError()); 12612 ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message); 12613 ok(msg.wParam == 0xbeef, "wParam was 0x%lx instead of 0xbeef\n", msg.wParam); 12614 12615 ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE); 12616 ok( !ret || msg.message != WM_QUIT, "Received WM_QUIT again\n" ); 12617 12618 /* now test with PostThreadMessage - different behaviour! */ 12619 PostThreadMessageA(GetCurrentThreadId(), WM_QUIT, 0xdead, 0); 12620 12621 ret = PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE); 12622 ok(ret, "PeekMessage failed with error %d\n", GetLastError()); 12623 ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message); 12624 ok(msg.wParam == 0xdead, "wParam was 0x%lx instead of 0xdead\n", msg.wParam); 12625 12626 ret = PostThreadMessageA(GetCurrentThreadId(), WM_USER, 0, 0); 12627 ok(ret, "PostMessage failed with error %d\n", GetLastError()); 12628 12629 /* note: we receive the WM_QUIT message first this time */ 12630 ret = GetMessageA(&msg, NULL, 0, 0); 12631 ok(!ret, "GetMessage return %d with error %d instead of FALSE\n", ret, GetLastError()); 12632 ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message); 12633 ok(msg.wParam == 0xdead, "wParam was 0x%lx instead of 0xdead\n", msg.wParam); 12634 12635 ret = GetMessageA(&msg, NULL, 0, 0); 12636 ok(ret > 0, "GetMessage failed with error %d\n", GetLastError()); 12637 ok(msg.message == WM_USER, "Received message 0x%04x instead of WM_USER\n", msg.message); 12638 12639 flush_events(); 12640 flush_sequence(); 12641 ret = DialogBoxParamA(GetModuleHandleA(NULL), "TEST_EMPTY_DIALOG", 0, wm_quit_dlg_proc, 0); 12642 ok(ret == 1, "expected 1, got %d\n", ret); 12643 ok_sequence(WmQuitDialogSeq, "WmQuitDialogSeq", FALSE); 12644 memset(&msg, 0xab, sizeof(msg)); 12645 ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE); 12646 ok(ret, "PeekMessage failed\n"); 12647 ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message); 12648 ok(msg.wParam == 0x1234, "wParam was 0x%lx instead of 0x1234\n", msg.wParam); 12649 ok(msg.lParam == 0, "lParam was 0x%lx instead of 0\n", msg.lParam); 12650 12651 /* Check what happens to a WM_QUIT message posted to a window that gets 12652 * destroyed. 12653 */ 12654 CreateWindowExA(0, "StopQuitClass", "Stop Quit Test", WS_OVERLAPPEDWINDOW, 12655 0, 0, 100, 100, NULL, NULL, NULL, NULL); 12656 flush_sequence(); 12657 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 12658 { 12659 struct recvd_message rmsg; 12660 rmsg.hwnd = msg.hwnd; 12661 rmsg.message = msg.message; 12662 rmsg.flags = posted|wparam|lparam; 12663 rmsg.wParam = msg.wParam; 12664 rmsg.lParam = msg.lParam; 12665 rmsg.descr = "stop/quit"; 12666 if (msg.message == WM_QUIT) 12667 /* The hwnd can only be checked here */ 12668 ok(!msg.hwnd, "The WM_QUIT hwnd was %p instead of NULL\n", msg.hwnd); 12669 add_message(&rmsg); 12670 DispatchMessageA(&msg); 12671 } 12672 ok_sequence(WmStopQuitSeq, "WmStopQuitSeq", FALSE); 12673 } 12674 12675 static const struct message WmNotifySeq[] = { 12676 { WM_NOTIFY, sent|wparam|lparam, 0x1234, 0xdeadbeef }, 12677 { 0 } 12678 }; 12679 12680 static void test_notify_message(void) 12681 { 12682 HWND hwnd; 12683 BOOL ret; 12684 MSG msg; 12685 12686 hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, 12687 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0, NULL, NULL, 0); 12688 ok(hwnd != 0, "Failed to create window\n"); 12689 flush_events(); 12690 flush_sequence(); 12691 12692 ret = SendNotifyMessageA(hwnd, WM_NOTIFY, 0x1234, 0xdeadbeef); 12693 ok(ret == TRUE, "SendNotifyMessageA failed with error %u\n", GetLastError()); 12694 ok_sequence(WmNotifySeq, "WmNotifySeq", FALSE); 12695 12696 ret = SendNotifyMessageW(hwnd, WM_NOTIFY, 0x1234, 0xdeadbeef); 12697 ok(ret == TRUE, "SendNotifyMessageW failed with error %u\n", GetLastError()); 12698 ok_sequence(WmNotifySeq, "WmNotifySeq", FALSE); 12699 12700 ret = SendMessageCallbackA(hwnd, WM_NOTIFY, 0x1234, 0xdeadbeef, NULL, 0); 12701 ok(ret == TRUE, "SendMessageCallbackA failed with error %u\n", GetLastError()); 12702 ok_sequence(WmNotifySeq, "WmNotifySeq", FALSE); 12703 12704 ret = SendMessageCallbackW(hwnd, WM_NOTIFY, 0x1234, 0xdeadbeef, NULL, 0); 12705 ok(ret == TRUE, "SendMessageCallbackW failed with error %u\n", GetLastError()); 12706 ok_sequence(WmNotifySeq, "WmNotifySeq", FALSE); 12707 12708 ret = PostMessageA(hwnd, WM_NOTIFY, 0x1234, 0xdeadbeef); 12709 ok(ret == TRUE, "PostMessageA failed with error %u\n", GetLastError()); 12710 flush_events(); 12711 ok_sequence(WmNotifySeq, "WmNotifySeq", FALSE); 12712 12713 ret = PostMessageW(hwnd, WM_NOTIFY, 0x1234, 0xdeadbeef); 12714 ok(ret == TRUE, "PostMessageW failed with error %u\n", GetLastError()); 12715 flush_events(); 12716 ok_sequence(WmNotifySeq, "WmNotifySeq", FALSE); 12717 12718 ret = PostThreadMessageA(GetCurrentThreadId(), WM_NOTIFY, 0x1234, 0xdeadbeef); 12719 ok(ret == TRUE, "PostThreadMessageA failed with error %u\n", GetLastError()); 12720 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 12721 { 12722 msg.hwnd = hwnd; 12723 DispatchMessageA(&msg); 12724 } 12725 ok_sequence(WmNotifySeq, "WmNotifySeq", FALSE); 12726 12727 ret = PostThreadMessageW(GetCurrentThreadId(), WM_NOTIFY, 0x1234, 0xdeadbeef); 12728 ok(ret == TRUE, "PostThreadMessageW failed with error %u\n", GetLastError()); 12729 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 12730 { 12731 msg.hwnd = hwnd; 12732 DispatchMessageA(&msg); 12733 } 12734 ok_sequence(WmNotifySeq, "WmNotifySeq", FALSE); 12735 12736 DestroyWindow(hwnd); 12737 } 12738 12739 static const struct message WmMouseHoverSeq[] = { 12740 { WM_MOUSEACTIVATE, sent|optional }, /* we can get those when moving the mouse in focus-follow-mouse mode under X11 */ 12741 { WM_MOUSEACTIVATE, sent|optional }, 12742 { WM_TIMER, sent|optional }, /* XP sends it */ 12743 { WM_SYSTIMER, sent }, 12744 { WM_MOUSEHOVER, sent|wparam, 0 }, 12745 { 0 } 12746 }; 12747 12748 static void pump_msg_loop_timeout(DWORD timeout, BOOL inject_mouse_move) 12749 { 12750 MSG msg; 12751 DWORD start_ticks, end_ticks; 12752 12753 start_ticks = GetTickCount(); 12754 /* add some deviation (50%) to cover not expected delays */ 12755 start_ticks += timeout / 2; 12756 12757 do 12758 { 12759 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 12760 { 12761 /* Timer proc messages are not dispatched to the window proc, 12762 * and therefore not logged. 12763 */ 12764 if ((msg.message == WM_TIMER || msg.message == WM_SYSTIMER) && msg.hwnd) 12765 { 12766 struct recvd_message s_msg; 12767 12768 s_msg.hwnd = msg.hwnd; 12769 s_msg.message = msg.message; 12770 s_msg.flags = sent|wparam|lparam; 12771 s_msg.wParam = msg.wParam; 12772 s_msg.lParam = msg.lParam; 12773 s_msg.descr = "msg_loop"; 12774 add_message(&s_msg); 12775 } 12776 DispatchMessageA(&msg); 12777 } 12778 12779 end_ticks = GetTickCount(); 12780 12781 /* inject WM_MOUSEMOVE to see how it changes tracking */ 12782 if (inject_mouse_move && start_ticks + timeout / 2 >= end_ticks) 12783 { 12784 mouse_event(MOUSEEVENTF_MOVE, -1, 0, 0, 0); 12785 mouse_event(MOUSEEVENTF_MOVE, 1, 0, 0, 0); 12786 12787 inject_mouse_move = FALSE; 12788 } 12789 } while (start_ticks + timeout >= end_ticks); 12790 } 12791 12792 static void test_TrackMouseEvent(void) 12793 { 12794 TRACKMOUSEEVENT tme; 12795 BOOL ret; 12796 HWND hwnd, hchild; 12797 RECT rc_parent, rc_child; 12798 UINT default_hover_time, hover_width = 0, hover_height = 0; 12799 12800 #define track_hover(track_hwnd, track_hover_time) \ 12801 tme.cbSize = sizeof(tme); \ 12802 tme.dwFlags = TME_HOVER; \ 12803 tme.hwndTrack = track_hwnd; \ 12804 tme.dwHoverTime = track_hover_time; \ 12805 SetLastError(0xdeadbeef); \ 12806 ret = pTrackMouseEvent(&tme); \ 12807 ok(ret, "TrackMouseEvent(TME_HOVER) error %d\n", GetLastError()) 12808 12809 #define track_query(expected_track_flags, expected_track_hwnd, expected_hover_time) \ 12810 tme.cbSize = sizeof(tme); \ 12811 tme.dwFlags = TME_QUERY; \ 12812 tme.hwndTrack = (HWND)0xdeadbeef; \ 12813 tme.dwHoverTime = 0xdeadbeef; \ 12814 SetLastError(0xdeadbeef); \ 12815 ret = pTrackMouseEvent(&tme); \ 12816 ok(ret, "TrackMouseEvent(TME_QUERY) error %d\n", GetLastError());\ 12817 ok(tme.cbSize == sizeof(tme), "wrong tme.cbSize %u\n", tme.cbSize); \ 12818 ok(tme.dwFlags == (expected_track_flags), \ 12819 "wrong tme.dwFlags %08x, expected %08x\n", tme.dwFlags, (expected_track_flags)); \ 12820 ok(tme.hwndTrack == (expected_track_hwnd), \ 12821 "wrong tme.hwndTrack %p, expected %p\n", tme.hwndTrack, (expected_track_hwnd)); \ 12822 ok(tme.dwHoverTime == (expected_hover_time), \ 12823 "wrong tme.dwHoverTime %u, expected %u\n", tme.dwHoverTime, (expected_hover_time)) 12824 12825 #define track_hover_cancel(track_hwnd) \ 12826 tme.cbSize = sizeof(tme); \ 12827 tme.dwFlags = TME_HOVER | TME_CANCEL; \ 12828 tme.hwndTrack = track_hwnd; \ 12829 tme.dwHoverTime = 0xdeadbeef; \ 12830 SetLastError(0xdeadbeef); \ 12831 ret = pTrackMouseEvent(&tme); \ 12832 ok(ret, "TrackMouseEvent(TME_HOVER | TME_CANCEL) error %d\n", GetLastError()) 12833 12834 default_hover_time = 0xdeadbeef; 12835 SetLastError(0xdeadbeef); 12836 ret = SystemParametersInfoA(SPI_GETMOUSEHOVERTIME, 0, &default_hover_time, 0); 12837 ok(ret || broken(GetLastError() == 0xdeadbeef), /* win9x */ 12838 "SystemParametersInfo(SPI_GETMOUSEHOVERTIME) error %u\n", GetLastError()); 12839 if (!ret) default_hover_time = 400; 12840 trace("SPI_GETMOUSEHOVERTIME returned %u ms\n", default_hover_time); 12841 12842 SetLastError(0xdeadbeef); 12843 ret = SystemParametersInfoA(SPI_GETMOUSEHOVERWIDTH, 0, &hover_width, 0); 12844 ok(ret || broken(GetLastError() == 0xdeadbeef), /* win9x */ 12845 "SystemParametersInfo(SPI_GETMOUSEHOVERWIDTH) error %u\n", GetLastError()); 12846 if (!ret) hover_width = 4; 12847 SetLastError(0xdeadbeef); 12848 ret = SystemParametersInfoA(SPI_GETMOUSEHOVERHEIGHT, 0, &hover_height, 0); 12849 ok(ret || broken(GetLastError() == 0xdeadbeef), /* win9x */ 12850 "SystemParametersInfo(SPI_GETMOUSEHOVERHEIGHT) error %u\n", GetLastError()); 12851 if (!ret) hover_height = 4; 12852 trace("hover rect is %u x %d\n", hover_width, hover_height); 12853 12854 hwnd = CreateWindowExA(0, "TestWindowClass", NULL, 12855 WS_OVERLAPPEDWINDOW | WS_VISIBLE, 12856 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0, 12857 NULL, NULL, 0); 12858 assert(hwnd); 12859 12860 hchild = CreateWindowExA(0, "TestWindowClass", NULL, 12861 WS_CHILD | WS_BORDER | WS_VISIBLE, 12862 50, 50, 200, 200, hwnd, 12863 NULL, NULL, 0); 12864 assert(hchild); 12865 12866 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE ); 12867 flush_events(); 12868 flush_sequence(); 12869 12870 tme.cbSize = 0; 12871 tme.dwFlags = TME_QUERY; 12872 tme.hwndTrack = (HWND)0xdeadbeef; 12873 tme.dwHoverTime = 0xdeadbeef; 12874 SetLastError(0xdeadbeef); 12875 ret = pTrackMouseEvent(&tme); 12876 ok(!ret, "TrackMouseEvent should fail\n"); 12877 ok(GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == 0xdeadbeef), 12878 "not expected error %u\n", GetLastError()); 12879 12880 tme.cbSize = sizeof(tme); 12881 tme.dwFlags = TME_HOVER; 12882 tme.hwndTrack = (HWND)0xdeadbeef; 12883 tme.dwHoverTime = 0xdeadbeef; 12884 SetLastError(0xdeadbeef); 12885 ret = pTrackMouseEvent(&tme); 12886 ok(!ret, "TrackMouseEvent should fail\n"); 12887 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || broken(GetLastError() == 0xdeadbeef), 12888 "not expected error %u\n", GetLastError()); 12889 12890 tme.cbSize = sizeof(tme); 12891 tme.dwFlags = TME_HOVER | TME_CANCEL; 12892 tme.hwndTrack = (HWND)0xdeadbeef; 12893 tme.dwHoverTime = 0xdeadbeef; 12894 SetLastError(0xdeadbeef); 12895 ret = pTrackMouseEvent(&tme); 12896 ok(!ret, "TrackMouseEvent should fail\n"); 12897 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || broken(GetLastError() == 0xdeadbeef), 12898 "not expected error %u\n", GetLastError()); 12899 12900 GetWindowRect(hwnd, &rc_parent); 12901 GetWindowRect(hchild, &rc_child); 12902 SetCursorPos(rc_child.left - 10, rc_child.top - 10); 12903 12904 /* Process messages so that the system updates its internal current 12905 * window and hittest, otherwise TrackMouseEvent calls don't have any 12906 * effect. 12907 */ 12908 flush_events(); 12909 flush_sequence(); 12910 12911 track_query(0, NULL, 0); 12912 track_hover(hchild, 0); 12913 track_query(0, NULL, 0); 12914 12915 flush_events(); 12916 flush_sequence(); 12917 12918 track_hover(hwnd, 0); 12919 tme.cbSize = sizeof(tme); 12920 tme.dwFlags = TME_QUERY; 12921 tme.hwndTrack = (HWND)0xdeadbeef; 12922 tme.dwHoverTime = 0xdeadbeef; 12923 SetLastError(0xdeadbeef); 12924 ret = pTrackMouseEvent(&tme); 12925 ok(ret, "TrackMouseEvent(TME_QUERY) error %d\n", GetLastError()); 12926 ok(tme.cbSize == sizeof(tme), "wrong tme.cbSize %u\n", tme.cbSize); 12927 if (!tme.dwFlags) 12928 { 12929 skip( "Cursor not inside window, skipping TrackMouseEvent tests\n" ); 12930 DestroyWindow( hwnd ); 12931 return; 12932 } 12933 ok(tme.dwFlags == TME_HOVER, "wrong tme.dwFlags %08x, expected TME_HOVER\n", tme.dwFlags); 12934 ok(tme.hwndTrack == hwnd, "wrong tme.hwndTrack %p, expected %p\n", tme.hwndTrack, hwnd); 12935 ok(tme.dwHoverTime == default_hover_time, "wrong tme.dwHoverTime %u, expected %u\n", 12936 tme.dwHoverTime, default_hover_time); 12937 12938 pump_msg_loop_timeout(default_hover_time, FALSE); 12939 ok_sequence(WmMouseHoverSeq, "WmMouseHoverSeq", FALSE); 12940 12941 track_query(0, NULL, 0); 12942 12943 track_hover(hwnd, HOVER_DEFAULT); 12944 track_query(TME_HOVER, hwnd, default_hover_time); 12945 12946 Sleep(default_hover_time / 2); 12947 mouse_event(MOUSEEVENTF_MOVE, -1, 0, 0, 0); 12948 mouse_event(MOUSEEVENTF_MOVE, 1, 0, 0, 0); 12949 12950 track_query(TME_HOVER, hwnd, default_hover_time); 12951 12952 pump_msg_loop_timeout(default_hover_time, FALSE); 12953 ok_sequence(WmMouseHoverSeq, "WmMouseHoverSeq", FALSE); 12954 12955 track_query(0, NULL, 0); 12956 12957 track_hover(hwnd, HOVER_DEFAULT); 12958 track_query(TME_HOVER, hwnd, default_hover_time); 12959 12960 pump_msg_loop_timeout(default_hover_time, TRUE); 12961 ok_sequence(WmMouseHoverSeq, "WmMouseHoverSeq", FALSE); 12962 12963 track_query(0, NULL, 0); 12964 12965 track_hover(hwnd, HOVER_DEFAULT); 12966 track_query(TME_HOVER, hwnd, default_hover_time); 12967 track_hover_cancel(hwnd); 12968 12969 DestroyWindow(hwnd); 12970 12971 #undef track_hover 12972 #undef track_query 12973 #undef track_hover_cancel 12974 } 12975 12976 12977 static const struct message WmSetWindowRgn[] = { 12978 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE }, 12979 { WM_NCCALCSIZE, sent|wparam, 1 }, 12980 { WM_NCPAINT, sent|optional }, /* wparam != 1 */ 12981 { WM_GETTEXT, sent|defwinproc|optional }, 12982 { WM_ERASEBKGND, sent|optional }, 12983 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE }, 12984 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 12985 { 0 } 12986 }; 12987 12988 static const struct message WmSetWindowRgn_no_redraw[] = { 12989 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW }, 12990 { WM_NCCALCSIZE, sent|wparam, 1 }, 12991 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW }, 12992 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 12993 { 0 } 12994 }; 12995 12996 static const struct message WmSetWindowRgn_clear[] = { 12997 { WM_WINDOWPOSCHANGING, sent/*|wparam*/, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE/*|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE only on some Windows versions */ }, 12998 { WM_NCCALCSIZE, sent|wparam, 1 }, 12999 { WM_NCPAINT, sent|optional }, 13000 { WM_GETTEXT, sent|defwinproc|optional }, 13001 { WM_ERASEBKGND, sent|optional }, /* FIXME: remove optional once Wine is fixed */ 13002 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE }, 13003 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, 13004 { WM_NCPAINT, sent|optional }, 13005 { WM_GETTEXT, sent|defwinproc|optional }, 13006 { WM_ERASEBKGND, sent|optional }, 13007 { WM_WINDOWPOSCHANGING, sent|optional }, 13008 { WM_NCCALCSIZE, sent|optional|wparam, 1 }, 13009 { WM_NCPAINT, sent|optional }, 13010 { WM_GETTEXT, sent|defwinproc|optional }, 13011 { WM_ERASEBKGND, sent|optional }, 13012 { WM_WINDOWPOSCHANGED, sent|optional|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE }, 13013 { WM_NCCALCSIZE, sent|optional|wparam, 1 }, 13014 { WM_NCPAINT, sent|optional }, 13015 { WM_GETTEXT, sent|defwinproc|optional }, 13016 { WM_ERASEBKGND, sent|optional }, 13017 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 13018 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 13019 { 0 } 13020 }; 13021 13022 static void test_SetWindowRgn(void) 13023 { 13024 HRGN hrgn; 13025 HWND hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW, 13026 100, 100, 200, 200, 0, 0, 0, NULL); 13027 ok( hwnd != 0, "Failed to create overlapped window\n" ); 13028 13029 ShowWindow( hwnd, SW_SHOW ); 13030 UpdateWindow( hwnd ); 13031 flush_events(); 13032 flush_sequence(); 13033 13034 trace("testing SetWindowRgn\n"); 13035 hrgn = CreateRectRgn( 0, 0, 150, 150 ); 13036 SetWindowRgn( hwnd, hrgn, TRUE ); 13037 ok_sequence( WmSetWindowRgn, "WmSetWindowRgn", FALSE ); 13038 13039 hrgn = CreateRectRgn( 30, 30, 160, 160 ); 13040 SetWindowRgn( hwnd, hrgn, FALSE ); 13041 ok_sequence( WmSetWindowRgn_no_redraw, "WmSetWindowRgn_no_redraw", FALSE ); 13042 13043 hrgn = CreateRectRgn( 0, 0, 180, 180 ); 13044 SetWindowRgn( hwnd, hrgn, TRUE ); 13045 ok_sequence( WmSetWindowRgn, "WmSetWindowRgn2", FALSE ); 13046 13047 SetWindowRgn( hwnd, 0, TRUE ); 13048 ok_sequence( WmSetWindowRgn_clear, "WmSetWindowRgn_clear", FALSE ); 13049 13050 DestroyWindow( hwnd ); 13051 } 13052 13053 /*************************** ShowWindow() test ******************************/ 13054 static const struct message WmShowNormal[] = { 13055 { WM_SHOWWINDOW, sent|wparam, 1 }, 13056 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 13057 { HCBT_ACTIVATE, hook }, 13058 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2003 doesn't send it */ 13059 { HCBT_SETFOCUS, hook }, 13060 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 13061 { 0 } 13062 }; 13063 static const struct message WmShow[] = { 13064 { WM_SHOWWINDOW, sent|wparam, 1 }, 13065 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 13066 { HCBT_ACTIVATE, hook|optional }, /* win2000 doesn't send it */ 13067 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2000 doesn't send it */ 13068 { HCBT_SETFOCUS, hook|optional }, /* win2000 doesn't send it */ 13069 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 13070 { 0 } 13071 }; 13072 static const struct message WmShowNoActivate_1[] = { 13073 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWNOACTIVATE }, 13074 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOMOVE }, 13075 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOMOVE }, 13076 { WM_MOVE, sent|defwinproc|optional }, 13077 { WM_SIZE, sent|wparam|defwinproc, SIZE_RESTORED }, 13078 { 0 } 13079 }; 13080 static const struct message WmShowNoActivate_2[] = { 13081 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWNOACTIVATE }, 13082 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE }, 13083 { HCBT_ACTIVATE, hook|optional }, 13084 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 13085 { HCBT_SETFOCUS, hook|optional }, 13086 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE }, 13087 { WM_MOVE, sent|defwinproc }, 13088 { WM_SIZE, sent|wparam|defwinproc, SIZE_RESTORED }, 13089 { HCBT_SETFOCUS, hook|optional }, 13090 { HCBT_ACTIVATE, hook|optional }, /* win2003 doesn't send it */ 13091 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2003 doesn't send it */ 13092 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 13093 { HCBT_SETFOCUS, hook|optional }, /* win2003 doesn't send it */ 13094 { 0 } 13095 }; 13096 static const struct message WmShowNA_1[] = { 13097 { WM_SHOWWINDOW, sent|wparam, 1 }, 13098 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 13099 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 13100 { 0 } 13101 }; 13102 static const struct message WmShowNA_2[] = { 13103 { WM_SHOWWINDOW, sent|wparam, 1 }, 13104 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 13105 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 13106 { 0 } 13107 }; 13108 static const struct message WmRestore_1[] = { 13109 { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE }, 13110 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 13111 { HCBT_ACTIVATE, hook|optional }, /* win2000 doesn't send it */ 13112 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2000 doesn't send it */ 13113 { HCBT_SETFOCUS, hook|optional }, /* win2000 doesn't send it */ 13114 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 13115 { WM_MOVE, sent|defwinproc }, 13116 { WM_SIZE, sent|wparam|defwinproc, SIZE_RESTORED }, 13117 { HCBT_SETFOCUS, hook|optional }, /* win2000 sends it */ 13118 { 0 } 13119 }; 13120 static const struct message WmRestore_2[] = { 13121 { WM_SHOWWINDOW, sent|wparam, 1 }, 13122 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 13123 { HCBT_ACTIVATE, hook|optional }, /* win2000 doesn't send it */ 13124 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2000 doesn't send it */ 13125 { HCBT_SETFOCUS, hook|optional }, /* win2000 doesn't send it */ 13126 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 13127 { 0 } 13128 }; 13129 static const struct message WmRestore_3[] = { 13130 { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE }, 13131 { WM_GETMINMAXINFO, sent }, 13132 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 13133 { HCBT_ACTIVATE, hook|optional }, /* win2003 doesn't send it */ 13134 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2003 doesn't send it */ 13135 { HCBT_SETFOCUS, hook|optional }, /* win2003 doesn't send it */ 13136 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 13137 { WM_MOVE, sent|defwinproc }, 13138 { WM_SIZE, sent|wparam|defwinproc, SIZE_MAXIMIZED }, 13139 { HCBT_SETFOCUS, hook|optional }, /* win2003 sends it */ 13140 { 0 } 13141 }; 13142 static const struct message WmRestore_4[] = { 13143 { HCBT_MINMAX, hook|lparam|optional, 0, SW_RESTORE }, 13144 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOMOVE }, 13145 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOMOVE }, 13146 { WM_MOVE, sent|defwinproc|optional }, 13147 { WM_SIZE, sent|wparam|defwinproc|optional, SIZE_RESTORED }, 13148 { 0 } 13149 }; 13150 static const struct message WmRestore_5[] = { 13151 { HCBT_MINMAX, hook|lparam|optional, 0, SW_SHOWNORMAL }, 13152 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOMOVE }, 13153 { HCBT_ACTIVATE, hook|optional }, 13154 { HCBT_SETFOCUS, hook|optional }, 13155 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOMOVE }, 13156 { WM_MOVE, sent|defwinproc|optional }, 13157 { WM_SIZE, sent|wparam|defwinproc|optional, SIZE_RESTORED }, 13158 { 0 } 13159 }; 13160 static const struct message WmHide_1[] = { 13161 { WM_SHOWWINDOW, sent|wparam, 0 }, 13162 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE, 0, SWP_NOACTIVATE }, 13163 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE, 0, SWP_NOACTIVATE }, 13164 { HCBT_ACTIVATE, hook|optional }, 13165 { HCBT_SETFOCUS, hook|optional }, /* win2000 sends it */ 13166 { 0 } 13167 }; 13168 static const struct message WmHide_2[] = { 13169 { WM_SHOWWINDOW, sent|wparam, 0 }, 13170 { WM_WINDOWPOSCHANGING, sent /*|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE*/ }, /* win2000 doesn't add SWP_NOACTIVATE */ 13171 { WM_WINDOWPOSCHANGED, sent /*|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ }, /* win2000 doesn't add SWP_NOACTIVATE */ 13172 { HCBT_ACTIVATE, hook|optional }, 13173 { 0 } 13174 }; 13175 static const struct message WmHide_3[] = { 13176 { WM_SHOWWINDOW, sent|wparam, 0 }, 13177 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 13178 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 13179 { HCBT_SETFOCUS, hook|optional }, 13180 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 13181 { 0 } 13182 }; 13183 static const struct message WmShowMinimized_1[] = { 13184 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINIMIZED }, 13185 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 13186 { HCBT_ACTIVATE, hook|optional }, /* win2000 doesn't send it */ 13187 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2000 doesn't send it */ 13188 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 13189 { WM_MOVE, sent|defwinproc }, 13190 { WM_SIZE, sent|wparam|lparam|defwinproc, SIZE_MINIMIZED, 0 }, 13191 { 0 } 13192 }; 13193 static const struct message WmMinimize_1[] = { 13194 { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, 13195 { HCBT_SETFOCUS, hook|optional }, /* win2000 doesn't send it */ 13196 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 13197 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 13198 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 13199 { WM_MOVE, sent|defwinproc }, 13200 { WM_SIZE, sent|wparam|lparam|defwinproc, SIZE_MINIMIZED, 0 }, 13201 { 0 } 13202 }; 13203 static const struct message WmMinimize_2[] = { 13204 { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, 13205 { HCBT_SETFOCUS, hook|optional }, 13206 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE }, 13207 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE }, 13208 { WM_MOVE, sent|defwinproc }, 13209 { WM_SIZE, sent|wparam|lparam|defwinproc, SIZE_MINIMIZED, 0 }, 13210 { 0 } 13211 }; 13212 static const struct message WmMinimize_3[] = { 13213 { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, 13214 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE }, 13215 { HCBT_ACTIVATE, hook|optional }, 13216 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 13217 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE }, 13218 { WM_MOVE, sent|defwinproc }, 13219 { WM_SIZE, sent|wparam|lparam|defwinproc, SIZE_MINIMIZED, 0 }, 13220 { 0 } 13221 }; 13222 static const struct message WmShowMinNoActivate[] = { 13223 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINNOACTIVE }, 13224 { WM_WINDOWPOSCHANGING, sent }, 13225 { WM_WINDOWPOSCHANGED, sent }, 13226 { WM_MOVE, sent|defwinproc|optional }, 13227 { WM_SIZE, sent|wparam|lparam|defwinproc|optional, SIZE_MINIMIZED, 0 }, 13228 { 0 } 13229 }; 13230 static const struct message WmMinMax_1[] = { 13231 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINIMIZED }, 13232 { 0 } 13233 }; 13234 static const struct message WmMinMax_2[] = { 13235 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMAXIMIZED }, 13236 { WM_GETMINMAXINFO, sent|optional }, 13237 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_FRAMECHANGED|SWP_STATECHANGED }, 13238 { HCBT_ACTIVATE, hook|optional }, 13239 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 13240 { HCBT_SETFOCUS, hook|optional }, 13241 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 13242 { WM_MOVE, sent|defwinproc|optional }, 13243 { WM_SIZE, sent|wparam|defwinproc|optional, SIZE_MAXIMIZED }, 13244 { HCBT_SETFOCUS, hook|optional }, 13245 { 0 } 13246 }; 13247 static const struct message WmMinMax_3[] = { 13248 { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, 13249 { HCBT_SETFOCUS, hook|optional }, 13250 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 13251 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 13252 { WM_MOVE, sent|defwinproc|optional }, 13253 { WM_SIZE, sent|wparam|lparam|defwinproc|optional, SIZE_MINIMIZED, 0 }, 13254 { 0 } 13255 }; 13256 static const struct message WmMinMax_4[] = { 13257 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINNOACTIVE }, 13258 { 0 } 13259 }; 13260 static const struct message WmShowMaximized_1[] = { 13261 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMAXIMIZED }, 13262 { WM_GETMINMAXINFO, sent }, 13263 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 13264 { HCBT_ACTIVATE, hook|optional }, /* win2000 doesn't send it */ 13265 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2000 doesn't send it */ 13266 { HCBT_SETFOCUS, hook|optional }, /* win2000 doesn't send it */ 13267 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 13268 { WM_MOVE, sent|defwinproc }, 13269 { WM_SIZE, sent|wparam|defwinproc, SIZE_MAXIMIZED }, 13270 { HCBT_SETFOCUS, hook|optional }, /* win2003 sends it */ 13271 { 0 } 13272 }; 13273 static const struct message WmShowMaximized_2[] = { 13274 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMAXIMIZED }, 13275 { WM_GETMINMAXINFO, sent }, 13276 { WM_WINDOWPOSCHANGING, sent|optional }, 13277 { HCBT_ACTIVATE, hook|optional }, 13278 { WM_WINDOWPOSCHANGED, sent|optional }, 13279 { WM_MOVE, sent|optional }, /* Win9x doesn't send it */ 13280 { WM_SIZE, sent|wparam|optional, SIZE_MAXIMIZED }, /* Win9x doesn't send it */ 13281 { WM_WINDOWPOSCHANGING, sent|optional }, 13282 { HCBT_SETFOCUS, hook|optional }, 13283 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 13284 { WM_MOVE, sent|defwinproc }, 13285 { WM_SIZE, sent|wparam|defwinproc, SIZE_MAXIMIZED }, 13286 { HCBT_SETFOCUS, hook|optional }, 13287 { 0 } 13288 }; 13289 static const struct message WmShowMaximized_3[] = { 13290 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMAXIMIZED }, 13291 { WM_GETMINMAXINFO, sent|optional }, 13292 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOMOVE }, 13293 { HCBT_ACTIVATE, hook|optional }, /* win2000 doesn't send it */ 13294 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2000 doesn't send it */ 13295 { HCBT_SETFOCUS, hook|optional }, /* win2000 doesn't send it */ 13296 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOMOVE }, 13297 { WM_MOVE, sent|defwinproc|optional }, 13298 { WM_SIZE, sent|wparam|defwinproc, SIZE_MAXIMIZED }, 13299 { 0 } 13300 }; 13301 13302 static void test_ShowWindow(void) 13303 { 13304 /* ShowWindow commands in random order */ 13305 static const struct 13306 { 13307 INT cmd; /* ShowWindow command */ 13308 LPARAM ret; /* ShowWindow return value */ 13309 DWORD style; /* window style after the command */ 13310 const struct message *msg; /* message sequence the command produces */ 13311 INT wp_cmd, wp_flags; /* window placement after the command */ 13312 POINT wp_min, wp_max; /* window placement after the command */ 13313 BOOL todo_msg; /* message sequence doesn't match what Wine does */ 13314 } sw[] = 13315 { 13316 /* 1 */ { SW_SHOWNORMAL, FALSE, WS_VISIBLE, WmShowNormal, 13317 SW_SHOWNORMAL, 0, {-1,-1}, {-1,-1}, FALSE }, 13318 /* 2 */ { SW_SHOWNORMAL, TRUE, WS_VISIBLE, WmEmptySeq, 13319 SW_SHOWNORMAL, 0, {-1,-1}, {-1,-1}, FALSE }, 13320 /* 3 */ { SW_HIDE, TRUE, 0, WmHide_1, 13321 SW_SHOWNORMAL, 0, {-1,-1}, {-1,-1}, FALSE }, 13322 /* 4 */ { SW_HIDE, FALSE, 0, WmEmptySeq, 13323 SW_SHOWNORMAL, 0, {-1,-1}, {-1,-1}, FALSE }, 13324 /* 5 */ { SW_SHOWMINIMIZED, FALSE, WS_VISIBLE|WS_MINIMIZE, WmShowMinimized_1, 13325 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13326 /* 6 */ { SW_SHOWMINIMIZED, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_1, 13327 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13328 /* 7 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_1, 13329 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13330 /* 8 */ { SW_HIDE, FALSE, WS_MINIMIZE, WmEmptySeq, 13331 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13332 /* 9 */ { SW_SHOWMAXIMIZED, FALSE, WS_VISIBLE|WS_MAXIMIZE, WmShowMaximized_1, 13333 SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13334 /* 10 */ { SW_SHOWMAXIMIZED, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmMinMax_2, 13335 SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13336 /* 11 */ { SW_HIDE, TRUE, WS_MAXIMIZE, WmHide_1, 13337 SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13338 /* 12 */ { SW_HIDE, FALSE, WS_MAXIMIZE, WmEmptySeq, 13339 SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13340 /* 13 */ { SW_SHOWNOACTIVATE, FALSE, WS_VISIBLE, WmShowNoActivate_1, 13341 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13342 /* 14 */ { SW_SHOWNOACTIVATE, TRUE, WS_VISIBLE, WmEmptySeq, 13343 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13344 /* 15 */ { SW_HIDE, TRUE, 0, WmHide_2, 13345 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13346 /* 16 */ { SW_HIDE, FALSE, 0, WmEmptySeq, 13347 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13348 /* 17 */ { SW_SHOW, FALSE, WS_VISIBLE, WmShow, 13349 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13350 /* 18 */ { SW_SHOW, TRUE, WS_VISIBLE, WmEmptySeq, 13351 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13352 /* 19 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinimize_1, 13353 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13354 /* 20 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_3, 13355 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13356 /* 21 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_2, 13357 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13358 /* 22 */ { SW_SHOWMINNOACTIVE, FALSE, WS_VISIBLE|WS_MINIMIZE, WmShowMinNoActivate, 13359 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, TRUE }, 13360 /* 23 */ { SW_SHOWMINNOACTIVE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_4, 13361 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13362 /* 24 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_2, 13363 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13364 /* 25 */ { SW_HIDE, FALSE, WS_MINIMIZE, WmEmptySeq, 13365 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13366 /* 26 */ { SW_SHOWNA, FALSE, WS_VISIBLE|WS_MINIMIZE, WmShowNA_1, 13367 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13368 /* 27 */ { SW_SHOWNA, TRUE, WS_VISIBLE|WS_MINIMIZE, WmShowNA_2, 13369 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13370 /* 28 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_2, 13371 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13372 /* 29 */ { SW_HIDE, FALSE, WS_MINIMIZE, WmEmptySeq, 13373 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13374 /* 30 */ { SW_RESTORE, FALSE, WS_VISIBLE, WmRestore_1, 13375 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13376 /* 31 */ { SW_RESTORE, TRUE, WS_VISIBLE, WmEmptySeq, 13377 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13378 /* 32 */ { SW_HIDE, TRUE, 0, WmHide_3, 13379 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13380 /* 33 */ { SW_HIDE, FALSE, 0, WmEmptySeq, 13381 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13382 /* 34 */ { SW_NORMALNA, FALSE, 0, WmEmptySeq, /* what does this mean?! */ 13383 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13384 /* 35 */ { SW_NORMALNA, FALSE, 0, WmEmptySeq, 13385 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13386 /* 36 */ { SW_HIDE, FALSE, 0, WmEmptySeq, 13387 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13388 /* 37 */ { SW_RESTORE, FALSE, WS_VISIBLE, WmRestore_2, 13389 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13390 /* 38 */ { SW_RESTORE, TRUE, WS_VISIBLE, WmEmptySeq, 13391 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13392 /* 39 */ { SW_SHOWNOACTIVATE, TRUE, WS_VISIBLE, WmEmptySeq, 13393 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13394 /* 40 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinimize_2, 13395 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13396 /* 41 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_3, 13397 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13398 /* 42 */ { SW_SHOWMAXIMIZED, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmShowMaximized_2, 13399 SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13400 /* 43 */ { SW_SHOWMAXIMIZED, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmMinMax_2, 13401 SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13402 /* 44 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinimize_1, 13403 SW_SHOWMINIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13404 /* 45 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_3, 13405 SW_SHOWMINIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13406 /* 46 */ { SW_RESTORE, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmRestore_3, 13407 SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13408 /* 47 */ { SW_RESTORE, TRUE, WS_VISIBLE, WmRestore_4, 13409 SW_SHOWNORMAL, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13410 /* 48 */ { SW_SHOWMAXIMIZED, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmShowMaximized_3, 13411 SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13412 /* 49 */ { SW_SHOW, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmEmptySeq, 13413 SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13414 /* 50 */ { SW_SHOWNORMAL, TRUE, WS_VISIBLE, WmRestore_5, 13415 SW_SHOWNORMAL, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13416 /* 51 */ { SW_SHOWNORMAL, TRUE, WS_VISIBLE, WmRestore_5, 13417 SW_SHOWNORMAL, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13418 /* 52 */ { SW_HIDE, TRUE, 0, WmHide_1, 13419 SW_SHOWNORMAL, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13420 /* 53 */ { SW_HIDE, FALSE, 0, WmEmptySeq, 13421 SW_SHOWNORMAL, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13422 /* 54 */ { SW_MINIMIZE, FALSE, WS_VISIBLE|WS_MINIMIZE, WmMinimize_3, 13423 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13424 /* 55 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_2, 13425 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13426 /* 56 */ { SW_SHOWNOACTIVATE, FALSE, WS_VISIBLE, WmShowNoActivate_2, 13427 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13428 /* 57 */ { SW_SHOW, TRUE, WS_VISIBLE, WmEmptySeq, 13429 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE } 13430 }; 13431 HWND hwnd; 13432 DWORD style; 13433 LPARAM ret; 13434 INT i; 13435 WINDOWPLACEMENT wp; 13436 RECT win_rc, work_rc = {0, 0, 0, 0}; 13437 13438 #define WS_BASE (WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_POPUP|WS_CLIPSIBLINGS) 13439 hwnd = CreateWindowExA(0, "ShowWindowClass", NULL, WS_BASE, 13440 120, 120, 90, 90, 13441 0, 0, 0, NULL); 13442 assert(hwnd); 13443 13444 style = GetWindowLongA(hwnd, GWL_STYLE) & ~WS_BASE; 13445 ok(style == 0, "expected style 0, got %08x\n", style); 13446 13447 flush_events(); 13448 flush_sequence(); 13449 13450 if (pGetMonitorInfoA && pMonitorFromPoint) 13451 { 13452 HMONITOR hmon; 13453 MONITORINFO mi; 13454 POINT pt = {0, 0}; 13455 13456 SetLastError(0xdeadbeef); 13457 hmon = pMonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY); 13458 ok(hmon != 0, "MonitorFromPoint error %u\n", GetLastError()); 13459 13460 mi.cbSize = sizeof(mi); 13461 SetLastError(0xdeadbeef); 13462 ret = pGetMonitorInfoA(hmon, &mi); 13463 ok(ret, "GetMonitorInfo error %u\n", GetLastError()); 13464 trace("monitor %s, work %s\n", wine_dbgstr_rect(&mi.rcMonitor), 13465 wine_dbgstr_rect(&mi.rcWork)); 13466 work_rc = mi.rcWork; 13467 } 13468 13469 GetWindowRect(hwnd, &win_rc); 13470 OffsetRect(&win_rc, -work_rc.left, -work_rc.top); 13471 13472 wp.length = sizeof(wp); 13473 SetLastError(0xdeadbeaf); 13474 ret = GetWindowPlacement(hwnd, &wp); 13475 ok(ret, "GetWindowPlacement error %u\n", GetLastError()); 13476 ok(wp.flags == 0, "expected 0, got %#x\n", wp.flags); 13477 ok(wp.showCmd == SW_SHOWNORMAL, "expected SW_SHOWNORMAL, got %d\n", wp.showCmd); 13478 ok(wp.ptMinPosition.x == -1 && wp.ptMinPosition.y == -1, 13479 "expected -1,-1 got %d,%d\n", wp.ptMinPosition.x, wp.ptMinPosition.y); 13480 ok(wp.ptMaxPosition.x == -1 && wp.ptMaxPosition.y == -1, 13481 "expected -1,-1 got %d,%d\n", wp.ptMaxPosition.x, wp.ptMaxPosition.y); 13482 todo_wine_if (work_rc.left || work_rc.top) /* FIXME: remove once Wine is fixed */ 13483 ok(EqualRect(&win_rc, &wp.rcNormalPosition), "expected %s got %s\n", wine_dbgstr_rect(&win_rc), 13484 wine_dbgstr_rect(&wp.rcNormalPosition)); 13485 13486 for (i = 0; i < ARRAY_SIZE(sw); i++) 13487 { 13488 static const char * const sw_cmd_name[13] = 13489 { 13490 "SW_HIDE", "SW_SHOWNORMAL", "SW_SHOWMINIMIZED", "SW_SHOWMAXIMIZED", 13491 "SW_SHOWNOACTIVATE", "SW_SHOW", "SW_MINIMIZE", "SW_SHOWMINNOACTIVE", 13492 "SW_SHOWNA", "SW_RESTORE", "SW_SHOWDEFAULT", "SW_FORCEMINIMIZE", 13493 "SW_NORMALNA" /* 0xCC */ 13494 }; 13495 char comment[64]; 13496 INT idx; /* index into the above array of names */ 13497 13498 idx = (sw[i].cmd == SW_NORMALNA) ? 12 : sw[i].cmd; 13499 13500 style = GetWindowLongA(hwnd, GWL_STYLE); 13501 trace("%d: sending %s, current window style %08x\n", i+1, sw_cmd_name[idx], style); 13502 ret = ShowWindow(hwnd, sw[i].cmd); 13503 ok(!ret == !sw[i].ret, "%d: cmd %s: expected ret %lu, got %lu\n", i+1, sw_cmd_name[idx], sw[i].ret, ret); 13504 style = GetWindowLongA(hwnd, GWL_STYLE) & ~WS_BASE; 13505 ok(style == sw[i].style, "%d: expected style %08x, got %08x\n", i+1, sw[i].style, style); 13506 13507 sprintf(comment, "%d: ShowWindow(%s)", i+1, sw_cmd_name[idx]); 13508 ok_sequence(sw[i].msg, comment, sw[i].todo_msg); 13509 13510 wp.length = sizeof(wp); 13511 SetLastError(0xdeadbeaf); 13512 ret = GetWindowPlacement(hwnd, &wp); 13513 ok(ret, "GetWindowPlacement error %u\n", GetLastError()); 13514 ok(wp.flags == sw[i].wp_flags, "expected %#x, got %#x\n", sw[i].wp_flags, wp.flags); 13515 ok(wp.showCmd == sw[i].wp_cmd, "expected %d, got %d\n", sw[i].wp_cmd, wp.showCmd); 13516 13517 /* NT moves the minimized window to -32000,-32000, win9x to 3000,3000 */ 13518 if ((wp.ptMinPosition.x + work_rc.left == -32000 && wp.ptMinPosition.y + work_rc.top == -32000) || 13519 (wp.ptMinPosition.x + work_rc.left == 3000 && wp.ptMinPosition.y + work_rc.top == 3000)) 13520 { 13521 ok((wp.ptMinPosition.x + work_rc.left == sw[i].wp_min.x && wp.ptMinPosition.y + work_rc.top == sw[i].wp_min.y) || 13522 (wp.ptMinPosition.x + work_rc.left == 3000 && wp.ptMinPosition.y + work_rc.top == 3000), 13523 "expected %d,%d got %d,%d\n", sw[i].wp_min.x, sw[i].wp_min.y, wp.ptMinPosition.x, wp.ptMinPosition.y); 13524 } 13525 else 13526 { 13527 ok(wp.ptMinPosition.x == sw[i].wp_min.x && wp.ptMinPosition.y == sw[i].wp_min.y, 13528 "expected %d,%d got %d,%d\n", sw[i].wp_min.x, sw[i].wp_min.y, wp.ptMinPosition.x, wp.ptMinPosition.y); 13529 } 13530 13531 todo_wine_if(wp.ptMaxPosition.x != sw[i].wp_max.x || wp.ptMaxPosition.y != sw[i].wp_max.y) 13532 ok(wp.ptMaxPosition.x == sw[i].wp_max.x && wp.ptMaxPosition.y == sw[i].wp_max.y, 13533 "expected %d,%d got %d,%d\n", sw[i].wp_max.x, sw[i].wp_max.y, wp.ptMaxPosition.x, wp.ptMaxPosition.y); 13534 13535 if (0) /* FIXME: Wine behaves completely different here */ 13536 ok(EqualRect(&win_rc, &wp.rcNormalPosition), "expected %s got %s\n", 13537 wine_dbgstr_rect(&win_rc), wine_dbgstr_rect(&wp.rcNormalPosition)); 13538 } 13539 DestroyWindow(hwnd); 13540 flush_events(); 13541 } 13542 13543 static INT_PTR WINAPI test_dlg_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 13544 { 13545 struct recvd_message msg; 13546 13547 if (ignore_message( message )) return 0; 13548 13549 msg.hwnd = hwnd; 13550 msg.message = message; 13551 msg.flags = sent|wparam|lparam; 13552 msg.wParam = wParam; 13553 msg.lParam = lParam; 13554 msg.descr = "dialog"; 13555 add_message(&msg); 13556 13557 /* calling DefDlgProc leads to a recursion under XP */ 13558 13559 switch (message) 13560 { 13561 case WM_INITDIALOG: 13562 return lParam; 13563 13564 case WM_GETDLGCODE: 13565 return 0; 13566 } 13567 return 1; 13568 } 13569 13570 static WNDPROC orig_edit_proc; 13571 static LRESULT WINAPI dlg_creation_edit_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) 13572 { 13573 struct recvd_message msg; 13574 13575 if (ignore_message( message )) return 0; 13576 13577 msg.hwnd = hwnd; 13578 msg.message = message; 13579 msg.flags = sent|wparam|lparam; 13580 msg.wParam = wp; 13581 msg.lParam = lp; 13582 msg.descr = "edit"; 13583 add_message(&msg); 13584 13585 return CallWindowProcW(orig_edit_proc, hwnd, message, wp, lp); 13586 } 13587 13588 static INT_PTR WINAPI test_dlg_proc2(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 13589 { 13590 struct recvd_message msg; 13591 13592 if (ignore_message( message )) return 0; 13593 13594 msg.hwnd = hwnd; 13595 msg.message = message; 13596 msg.flags = sent|wparam|lparam|parent; 13597 msg.wParam = wParam; 13598 msg.lParam = lParam; 13599 msg.descr = "dialog"; 13600 add_message(&msg); 13601 13602 if (message == WM_INITDIALOG) 13603 { 13604 orig_edit_proc = (WNDPROC)SetWindowLongPtrW(GetDlgItem(hwnd, 200), 13605 GWLP_WNDPROC, (LONG_PTR)dlg_creation_edit_proc); 13606 } 13607 13608 return 1; 13609 } 13610 13611 static INT_PTR WINAPI test_dlg_proc3(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 13612 { 13613 ok( 0, "should not be called since DefDlgProc is not used\n" ); 13614 return 0; 13615 } 13616 13617 static LRESULT WINAPI test_dlg_proc4(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 13618 { 13619 struct recvd_message msg; 13620 13621 if (!ignore_message( message )) 13622 { 13623 msg.hwnd = hwnd; 13624 msg.message = message; 13625 msg.flags = sent|wparam|lparam|parent; 13626 msg.wParam = wParam; 13627 msg.lParam = lParam; 13628 msg.descr = "dialog"; 13629 add_message(&msg); 13630 } 13631 if (message == WM_INITDIALOG) 13632 { 13633 orig_edit_proc = (WNDPROC)SetWindowLongPtrW(GetDlgItem(hwnd, 200), 13634 GWLP_WNDPROC, (LONG_PTR)dlg_creation_edit_proc); 13635 return 1; 13636 } 13637 return DefWindowProcW( hwnd, message, wParam, lParam ); 13638 } 13639 13640 static const struct message WmDefDlgSetFocus_1[] = { 13641 { WM_GETDLGCODE, sent|wparam|lparam, 0, 0 }, 13642 { WM_GETTEXTLENGTH, sent|wparam|lparam|optional, 0, 0 }, /* XP */ 13643 { WM_GETTEXT, sent|wparam|optional, 6 }, /* XP */ 13644 { WM_GETTEXT, sent|wparam|optional, 12 }, /* XP */ 13645 { EM_SETSEL, sent|wparam, 0 }, /* XP sets lparam to text length, Win9x to -2 */ 13646 { HCBT_SETFOCUS, hook }, 13647 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 13648 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 13649 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 13650 { WM_SETFOCUS, sent|wparam, 0 }, 13651 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 10 }, 13652 { WM_CTLCOLOREDIT, sent }, 13653 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 11 }, 13654 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 13655 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 13656 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 13657 { WM_COMMAND, sent|wparam, MAKEWPARAM(1, EN_SETFOCUS) }, 13658 { 0 } 13659 }; 13660 static const struct message WmDefDlgSetFocus_2[] = { 13661 { WM_GETDLGCODE, sent|wparam|lparam, 0, 0 }, 13662 { WM_GETTEXTLENGTH, sent|wparam|lparam|optional, 0, 0 }, /* XP */ 13663 { WM_GETTEXT, sent|wparam|optional, 6 }, /* XP */ 13664 { WM_GETTEXT, sent|wparam|optional, 12 }, /* XP */ 13665 { EM_SETSEL, sent|wparam, 0 }, /* XP sets lparam to text length, Win9x to -2 */ 13666 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 13667 { WM_CTLCOLOREDIT, sent|optional }, /* XP */ 13668 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 13669 { 0 } 13670 }; 13671 /* Creation of a dialog */ 13672 static const struct message WmCreateDialogParamSeq_0[] = { 13673 { HCBT_CREATEWND, hook }, 13674 { WM_NCCREATE, sent }, 13675 { WM_NCCALCSIZE, sent|wparam, 0 }, 13676 { WM_CREATE, sent }, 13677 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 13678 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 13679 { WM_MOVE, sent }, 13680 { WM_SETFONT, sent }, 13681 { WM_INITDIALOG, sent }, 13682 { WM_CHANGEUISTATE, sent|optional }, 13683 { 0 } 13684 }; 13685 /* Creation of a dialog */ 13686 static const struct message WmCreateDialogParamSeq_1[] = { 13687 { HCBT_CREATEWND, hook }, 13688 { WM_NCCREATE, sent }, 13689 { WM_NCCALCSIZE, sent|wparam, 0 }, 13690 { WM_CREATE, sent }, 13691 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 13692 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 13693 { WM_MOVE, sent }, 13694 { WM_SETFONT, sent }, 13695 { WM_INITDIALOG, sent }, 13696 { WM_GETDLGCODE, sent|wparam|lparam|optional, 0, 0 }, /* FIXME: Wine doesn't send it */ 13697 { HCBT_SETFOCUS, hook }, 13698 { HCBT_ACTIVATE, hook }, 13699 { WM_QUERYNEWPALETTE, sent|optional }, 13700 { WM_PALETTEISCHANGING, sent|optional }, 13701 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 13702 { WM_ACTIVATEAPP, sent|wparam, 1 }, 13703 { WM_NCACTIVATE, sent }, 13704 { WM_ACTIVATE, sent|wparam, 1 }, 13705 { WM_SETFOCUS, sent }, 13706 { WM_CHANGEUISTATE, sent|optional }, 13707 { 0 } 13708 }; 13709 /* Creation of a dialog */ 13710 static const struct message WmCreateDialogParamSeq_2[] = { 13711 { HCBT_CREATEWND, hook }, 13712 { WM_NCCREATE, sent }, 13713 { WM_NCCALCSIZE, sent|wparam, 0 }, 13714 { WM_CREATE, sent }, 13715 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 13716 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 13717 { WM_MOVE, sent }, 13718 { WM_CHANGEUISTATE, sent|optional }, 13719 { 0 } 13720 }; 13721 13722 static const struct message WmCreateDialogParamSeq_3[] = { 13723 { HCBT_CREATEWND, hook }, 13724 { WM_SETFONT, sent|parent }, 13725 { WM_INITDIALOG, sent|parent }, 13726 { WM_GETDLGCODE, sent|wparam|lparam, 0, 0 }, 13727 { EM_SETSEL, sent|wparam|lparam, 0, INT_MAX }, 13728 { EM_SETSEL, sent|wparam|lparam|optional, 0, INT_MAX }, 13729 { EM_SETSEL, sent|wparam|lparam|optional, 0, INT_MAX }, 13730 { EM_SETSEL, sent|wparam|lparam|optional, 0, INT_MAX }, 13731 { HCBT_ACTIVATE, hook }, 13732 { WM_QUERYNEWPALETTE, sent|parent|optional }, /* TODO: this message should not be sent */ 13733 { WM_WINDOWPOSCHANGING, sent|parent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 13734 { WM_WINDOWPOSCHANGING, sent|parent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 13735 { WM_WINDOWPOSCHANGED, sent|parent|wparam|optional, SWP_NOREDRAW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 13736 { WM_WINDOWPOSCHANGED, sent|parent|wparam|optional, SWP_NOREDRAW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 13737 { WM_ACTIVATEAPP, sent|parent|wparam, 1 }, 13738 { WM_NCACTIVATE, sent|parent }, 13739 { WM_ACTIVATE, sent|parent|wparam, 1 }, 13740 { WM_SETFOCUS, sent }, 13741 { WM_COMMAND, sent|parent|wparam, MAKELONG(200, EN_SETFOCUS) }, 13742 { WM_GETDLGCODE, sent|wparam|lparam, 0, 0 }, 13743 { WM_USER, sent|parent }, 13744 { WM_CHANGEUISTATE, sent|parent|optional }, 13745 { 0 } 13746 }; 13747 13748 static const struct message WmCreateDialogParamSeq_4[] = { 13749 { HCBT_CREATEWND, hook }, 13750 { WM_NCCREATE, sent|parent }, 13751 { WM_NCCALCSIZE, sent|parent|wparam, 0 }, 13752 { WM_CREATE, sent|parent }, 13753 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 13754 { WM_SIZE, sent|parent|wparam, SIZE_RESTORED }, 13755 { WM_MOVE, sent|parent }, 13756 { WM_SETFONT, sent|parent }, 13757 { WM_INITDIALOG, sent|parent }, 13758 { WM_GETDLGCODE, sent|wparam|lparam, 0, 0 }, 13759 { EM_SETSEL, sent|wparam|lparam, 0, INT_MAX }, 13760 { EM_SETSEL, sent|wparam|lparam|optional, 0, INT_MAX }, 13761 { EM_SETSEL, sent|wparam|lparam|optional, 0, INT_MAX }, 13762 { EM_SETSEL, sent|wparam|lparam|optional, 0, INT_MAX }, 13763 { HCBT_ACTIVATE, hook }, 13764 { WM_QUERYNEWPALETTE, sent|parent|optional }, /* TODO: this message should not be sent */ 13765 { WM_WINDOWPOSCHANGING, sent|parent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 13766 { WM_WINDOWPOSCHANGING, sent|parent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 13767 { WM_ACTIVATEAPP, sent|parent|wparam, 1 }, 13768 { WM_NCACTIVATE, sent|parent }, 13769 { WM_ACTIVATE, sent|parent|wparam, 1 }, 13770 { HCBT_SETFOCUS, hook }, 13771 { WM_SETFOCUS, sent|parent }, 13772 { WM_KILLFOCUS, sent|parent }, 13773 { WM_SETFOCUS, sent }, 13774 { WM_COMMAND, sent|parent|wparam, MAKELONG(200, EN_SETFOCUS) }, 13775 { WM_GETDLGCODE, sent|wparam|lparam, 0, 0 }, 13776 { WM_USER, sent|parent }, 13777 { WM_CHANGEUISTATE, sent|parent|optional }, 13778 { WM_UPDATEUISTATE, sent|parent|optional }, 13779 { WM_UPDATEUISTATE, sent|optional }, 13780 { 0 } 13781 }; 13782 13783 static void test_dialog_messages(void) 13784 { 13785 WNDCLASSA cls; 13786 HWND hdlg, hedit1, hedit2, hfocus, parent, child, child2; 13787 LRESULT ret; 13788 13789 #define set_selection(hctl, start, end) \ 13790 ret = SendMessageA(hctl, EM_SETSEL, start, end); \ 13791 ok(ret == 1, "EM_SETSEL returned %ld\n", ret); 13792 13793 #define check_selection(hctl, start, end) \ 13794 ret = SendMessageA(hctl, EM_GETSEL, 0, 0); \ 13795 ok(ret == MAKELRESULT(start, end), "wrong selection (%d - %d)\n", LOWORD(ret), HIWORD(ret)); 13796 13797 subclass_edit(); 13798 13799 hdlg = CreateWindowExA(WS_EX_DLGMODALFRAME, "TestDialogClass", NULL, 13800 WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_DLGFRAME, 13801 0, 0, 100, 100, 0, 0, 0, NULL); 13802 ok(hdlg != 0, "Failed to create custom dialog window\n"); 13803 13804 hedit1 = CreateWindowExA(0, "my_edit_class", NULL, 13805 WS_CHILD|WS_BORDER|WS_VISIBLE|WS_TABSTOP, 13806 0, 0, 80, 20, hdlg, (HMENU)1, 0, NULL); 13807 ok(hedit1 != 0, "Failed to create edit control\n"); 13808 hedit2 = CreateWindowExA(0, "my_edit_class", NULL, 13809 WS_CHILD|WS_BORDER|WS_VISIBLE|WS_TABSTOP, 13810 0, 40, 80, 20, hdlg, (HMENU)2, 0, NULL); 13811 ok(hedit2 != 0, "Failed to create edit control\n"); 13812 13813 SendMessageA(hedit1, WM_SETTEXT, 0, (LPARAM)"hello"); 13814 SendMessageA(hedit2, WM_SETTEXT, 0, (LPARAM)"bye"); 13815 13816 hfocus = GetFocus(); 13817 ok(hfocus == hdlg, "wrong focus %p\n", hfocus); 13818 13819 SetFocus(hedit2); 13820 hfocus = GetFocus(); 13821 ok(hfocus == hedit2, "wrong focus %p\n", hfocus); 13822 13823 check_selection(hedit1, 0, 0); 13824 check_selection(hedit2, 0, 0); 13825 13826 set_selection(hedit2, 0, -1); 13827 check_selection(hedit2, 0, 3); 13828 13829 SetFocus(0); 13830 hfocus = GetFocus(); 13831 ok(hfocus == 0, "wrong focus %p\n", hfocus); 13832 13833 flush_sequence(); 13834 ret = DefDlgProcA(hdlg, WM_SETFOCUS, 0, 0); 13835 ok(ret == 0, "WM_SETFOCUS returned %ld\n", ret); 13836 ok_sequence(WmDefDlgSetFocus_1, "DefDlgProc(WM_SETFOCUS) 1", FALSE); 13837 13838 hfocus = GetFocus(); 13839 ok(hfocus == hedit1, "wrong focus %p\n", hfocus); 13840 13841 check_selection(hedit1, 0, 5); 13842 check_selection(hedit2, 0, 3); 13843 13844 flush_sequence(); 13845 ret = DefDlgProcA(hdlg, WM_SETFOCUS, 0, 0); 13846 ok(ret == 0, "WM_SETFOCUS returned %ld\n", ret); 13847 ok_sequence(WmDefDlgSetFocus_2, "DefDlgProc(WM_SETFOCUS) 2", FALSE); 13848 13849 hfocus = GetFocus(); 13850 ok(hfocus == hedit1, "wrong focus %p\n", hfocus); 13851 13852 check_selection(hedit1, 0, 5); 13853 check_selection(hedit2, 0, 3); 13854 13855 EndDialog(hdlg, 0); 13856 DestroyWindow(hedit1); 13857 DestroyWindow(hedit2); 13858 DestroyWindow(hdlg); 13859 flush_sequence(); 13860 13861 #undef set_selection 13862 #undef check_selection 13863 13864 ok(GetClassInfoA(0, "#32770", &cls), "GetClassInfo failed\n"); 13865 cls.lpszClassName = "MyDialogClass"; 13866 cls.hInstance = GetModuleHandleA(NULL); 13867 /* need a cast since a dlgproc is used as a wndproc */ 13868 cls.lpfnWndProc = test_dlg_proc; 13869 if (!RegisterClassA(&cls)) assert(0); 13870 13871 SetFocus(0); 13872 flush_sequence(); 13873 hdlg = CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", 0, test_dlg_proc, 0); 13874 ok(IsWindow(hdlg), "CreateDialogParam failed\n"); 13875 ok_sequence(WmCreateDialogParamSeq_0, "CreateDialogParam_0", FALSE); 13876 hfocus = GetFocus(); 13877 ok(hfocus == 0, "wrong focus %p\n", hfocus); 13878 EndDialog(hdlg, 0); 13879 DestroyWindow(hdlg); 13880 flush_sequence(); 13881 13882 SetFocus(0); 13883 flush_sequence(); 13884 hdlg = CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", 0, test_dlg_proc, 1); 13885 ok(IsWindow(hdlg), "CreateDialogParam failed\n"); 13886 ok_sequence(WmCreateDialogParamSeq_1, "CreateDialogParam_1", FALSE); 13887 hfocus = GetFocus(); 13888 ok(hfocus == hdlg, "wrong focus %p\n", hfocus); 13889 EndDialog(hdlg, 0); 13890 DestroyWindow(hdlg); 13891 flush_sequence(); 13892 13893 hdlg = CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", 0, NULL, 0); 13894 ok(IsWindow(hdlg), "CreateDialogParam failed\n"); 13895 ok_sequence(WmCreateDialogParamSeq_2, "CreateDialogParam_2", FALSE); 13896 EndDialog(hdlg, 0); 13897 DestroyWindow(hdlg); 13898 flush_sequence(); 13899 13900 hdlg = CreateDialogParamA(0, "FOCUS_TEST_DIALOG_3", 0, test_dlg_proc2, 0); 13901 ok(IsWindow(hdlg), "CreateDialogParam failed\n"); 13902 ok_sequence(WmCreateDialogParamSeq_3, "CreateDialogParam_3", TRUE); 13903 EndDialog(hdlg, 0); 13904 DestroyWindow(hdlg); 13905 flush_sequence(); 13906 13907 UnregisterClassA( cls.lpszClassName, cls.hInstance ); 13908 cls.lpfnWndProc = test_dlg_proc4; 13909 ok( RegisterClassA(&cls), "failed to register class again\n" ); 13910 hdlg = CreateDialogParamA(0, "FOCUS_TEST_DIALOG_4", 0, test_dlg_proc3, 0); 13911 ok(IsWindow(hdlg), "CreateDialogParam failed\n"); 13912 ok_sequence(WmCreateDialogParamSeq_4, "CreateDialogParam_4", TRUE); 13913 EndDialog(hdlg, 0); 13914 DestroyWindow(hdlg); 13915 flush_sequence(); 13916 13917 UnregisterClassA(cls.lpszClassName, cls.hInstance); 13918 13919 parent = CreateWindowExA(0, "TestParentClass", "Test parent", 13920 WS_OVERLAPPEDWINDOW | WS_VISIBLE, 13921 100, 100, 200, 200, 0, 0, 0, NULL); 13922 ok (parent != 0, "Failed to create parent window\n"); 13923 13924 /* This child has no parent set. We will later call SetParent on it, 13925 * so that it will have a parent set, but no WS_CHILD style. */ 13926 child = CreateWindowExA(0, "TestWindowClass", "Test child", 13927 WS_OVERLAPPEDWINDOW | WS_VISIBLE, 13928 100, 100, 200, 200, 0, 0, 0, NULL); 13929 ok (child != 0, "Failed to create child window\n"); 13930 13931 /* This is a regular child window. When used as an owner, the other 13932 * child window will be used. */ 13933 child2 = CreateWindowExA(0, "SimpleWindowClass", "Test child2", 13934 WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CHILD, 13935 100, 100, 200, 200, child, 0, 0, NULL); 13936 ok (child2 != 0, "Failed to create child window\n"); 13937 13938 SetParent(child, parent); 13939 SetFocus(child); 13940 13941 flush_sequence(); 13942 DialogBoxA( 0, "TEST_DIALOG", child2, TestModalDlgProc2 ); 13943 ok_sequence(WmModalDialogSeq_2, "ModalDialog2", TRUE); 13944 13945 DestroyWindow(child2); 13946 DestroyWindow(child); 13947 DestroyWindow(parent); 13948 flush_sequence(); 13949 } 13950 13951 static void test_enddialog_seq(HWND dialog, HWND owner) 13952 { 13953 const struct message seq[] = { 13954 { WM_ENABLE, sent }, 13955 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 13956 { HCBT_ACTIVATE, hook|wparam, (WPARAM)owner }, 13957 { WM_NCACTIVATE, sent|wparam|lparam, WA_INACTIVE, (LPARAM)owner }, 13958 { WM_ACTIVATE, sent|wparam|lparam, WA_INACTIVE, (LPARAM)owner }, 13959 /* FIXME: Following two are optional because Wine sends WM_QUERYNEWPALETTE instead of WM_WINDOWPOSCHANGING */ 13960 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 13961 { WM_QUERYNEWPALETTE, sent|optional }, 13962 { WM_NCACTIVATE, sent|wparam|lparam, WA_ACTIVE, (LPARAM)dialog }, 13963 { WM_GETTEXT, sent|optional|defwinproc }, 13964 { WM_ACTIVATE, sent|wparam|lparam, WA_ACTIVE, (LPARAM)dialog }, 13965 { HCBT_SETFOCUS, hook|wparam, (WPARAM)owner }, 13966 { WM_KILLFOCUS, sent|wparam, (WPARAM)owner }, 13967 { WM_SETFOCUS, sent|defwinproc|wparam, (WPARAM)dialog }, 13968 { 0 } 13969 }; 13970 13971 flush_sequence(); 13972 EndDialog(dialog, 0); 13973 ok_sequence(seq, "EndDialog", FALSE); 13974 } 13975 13976 static void test_enddialog_seq2(HWND dialog, HWND owner) 13977 { 13978 const struct message seq[] = { 13979 { WM_ENABLE, parent|sent }, 13980 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 13981 { HCBT_ACTIVATE, hook|wparam, (WPARAM)owner }, 13982 { WM_NCACTIVATE, sent|wparam|lparam, WA_INACTIVE, (LPARAM)owner }, 13983 { WM_ACTIVATE, sent|wparam|lparam, WA_INACTIVE, (LPARAM)owner }, 13984 { WM_WINDOWPOSCHANGING, sent|optional|wparam, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 13985 { WM_WINDOWPOSCHANGING, sent|optional|wparam, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 13986 { HCBT_SETFOCUS, hook|wparam, (WPARAM)owner }, 13987 { WM_KILLFOCUS, sent|wparam, (WPARAM)owner }, 13988 { WM_SETFOCUS, sent|parent|defwinproc|wparam, (WPARAM)dialog }, 13989 { 0 } 13990 }; 13991 13992 flush_sequence(); 13993 EndDialog(dialog, 0); 13994 ok_sequence(seq, "EndDialog2", FALSE); 13995 } 13996 13997 static void test_EndDialog(void) 13998 { 13999 HWND hparent, hother, hactive, hdlg, hchild; 14000 WNDCLASSA cls; 14001 14002 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", 14003 WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_DISABLED, 14004 100, 100, 200, 200, 0, 0, 0, NULL); 14005 ok (hparent != 0, "Failed to create parent window\n"); 14006 14007 hother = CreateWindowExA(0, "TestParentClass", "Test parent 2", 14008 WS_OVERLAPPEDWINDOW | WS_VISIBLE, 14009 200, 100, 200, 200, 0, 0, 0, NULL); 14010 ok (hother != 0, "Failed to create parent window\n"); 14011 14012 ok(GetClassInfoA(0, "#32770", &cls), "GetClassInfo failed\n"); 14013 cls.lpszClassName = "MyDialogClass"; 14014 cls.hInstance = GetModuleHandleA(NULL); 14015 cls.lpfnWndProc = test_dlg_proc; 14016 if (!RegisterClassA(&cls)) assert(0); 14017 14018 flush_sequence(); 14019 SetForegroundWindow(hother); 14020 hactive = GetForegroundWindow(); 14021 ok(hother == hactive, "Wrong window has focus (%p != %p)\n", hother, hactive); 14022 14023 /* create a dialog where the parent is disabled, this parent should be 14024 * enabled and receive focus when dialog exits */ 14025 hdlg = CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", hparent, test_dlg_proc, 0); 14026 ok(IsWindow(hdlg), "CreateDialogParam failed\n"); 14027 SetForegroundWindow(hdlg); 14028 hactive = GetForegroundWindow(); 14029 ok(hdlg == hactive, "Wrong window has focus (%p != %p)\n", hdlg, hactive); 14030 EndDialog(hdlg, 0); 14031 ok(IsWindowEnabled(hparent), "parent is not enabled\n"); 14032 hactive = GetForegroundWindow(); 14033 ok(hparent == hactive, "Wrong window has focus (parent != active) (active: %p, parent: %p, dlg: %p, other: %p)\n", hactive, hparent, hdlg, hother); 14034 DestroyWindow(hdlg); 14035 flush_sequence(); 14036 14037 /* create a dialog where the parent is disabled and set active window to other window before calling EndDialog */ 14038 EnableWindow(hparent, FALSE); 14039 hdlg = CreateWindowExA(0, "TestDialogClass", NULL, 14040 WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_DLGFRAME, 14041 0, 0, 100, 100, hparent, 0, 0, NULL); 14042 ok(IsWindow(hdlg), "CreateDialogParam failed\n"); 14043 flush_sequence(); 14044 SetForegroundWindow(hother); 14045 flush_sequence(); 14046 hactive = GetForegroundWindow(); 14047 ok(hactive == hother, "Wrong foreground (%p != %p)\n", hactive, hother); 14048 hactive = GetActiveWindow(); 14049 ok(hactive == hother, "Wrong active window (%p != %p)\n", hactive, hother); 14050 EndDialog(hdlg, 0); 14051 ok(IsWindowEnabled(hparent), "parent is not enabled\n"); 14052 hactive = GetForegroundWindow(); 14053 ok(hother == hactive, "Wrong window has focus (other != active) (active: %p, parent: %p, dlg: %p, other: %p)\n", hactive, hparent, hdlg, hother); 14054 DestroyWindow(hdlg); 14055 flush_sequence(); 14056 14057 DestroyWindow( hparent ); 14058 14059 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", 14060 WS_POPUP | WS_VISIBLE | WS_DISABLED, 14061 100, 100, 200, 200, 0, 0, 0, NULL); 14062 ok (hparent != 0, "Failed to create parent window\n"); 14063 14064 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", 14065 WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_DISABLED, 14066 0, 0, 0, 0, 0, 0, 0, NULL); 14067 ok (hchild != 0, "Failed to create child window\n"); 14068 14069 SetParent(hchild, hparent); 14070 14071 flush_sequence(); 14072 SetForegroundWindow(hother); 14073 hactive = GetForegroundWindow(); 14074 ok(hother == hactive, "Wrong foreground window (%p != %p)\n", hother, hactive); 14075 14076 hdlg = CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", hchild, test_dlg_proc, 0); 14077 ok(IsWindow(hdlg), "CreateDialogParam failed\n"); 14078 14079 SetForegroundWindow(hdlg); 14080 test_enddialog_seq(hdlg, hchild); 14081 14082 hactive = GetForegroundWindow(); 14083 ok(hactive == hchild, "Wrong foreground window (active: %p, parent: %p, dlg: %p, other: %p child: %p)\n", hactive, hparent, hdlg, hother, hchild); 14084 14085 DestroyWindow(hdlg); 14086 14087 /* Now set WS_CHILD style flag so that it's a real child and its parent will be dialog's owner. */ 14088 SetWindowLongW(hchild, GWL_STYLE, GetWindowLongW(hchild, GWL_STYLE) | WS_CHILD); 14089 14090 SetForegroundWindow(hother); 14091 hactive = GetForegroundWindow(); 14092 ok(hother == hactive, "Wrong foreground window (%p != %p)\n", hother, hactive); 14093 14094 hdlg = CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", hchild, test_dlg_proc, 0); 14095 ok(IsWindow(hdlg), "CreateDialogParam failed\n"); 14096 14097 SetForegroundWindow(hdlg); 14098 test_enddialog_seq2(hdlg, hparent); 14099 14100 hactive = GetForegroundWindow(); 14101 ok(hactive == hparent, "Wrong foreground window (active: %p, parent: %p, dlg: %p, other: %p child: %p)\n", hactive, hparent, hdlg, hother, hchild); 14102 DestroyWindow(hdlg); 14103 DestroyWindow(hchild); 14104 DestroyWindow(hparent); 14105 DestroyWindow(hother); 14106 flush_sequence(); 14107 14108 UnregisterClassA(cls.lpszClassName, cls.hInstance); 14109 } 14110 14111 static void test_nullCallback(void) 14112 { 14113 HWND hwnd; 14114 14115 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW, 14116 100, 100, 200, 200, 0, 0, 0, NULL); 14117 ok (hwnd != 0, "Failed to create overlapped window\n"); 14118 14119 SendMessageCallbackA(hwnd,WM_NULL,0,0,NULL,0); 14120 flush_events(); 14121 DestroyWindow(hwnd); 14122 } 14123 14124 /* SetActiveWindow( 0 ) hwnd visible */ 14125 static const struct message SetActiveWindowSeq0[] = 14126 { 14127 { HCBT_ACTIVATE, hook|optional }, 14128 { WM_NCACTIVATE, sent|wparam, 0 }, 14129 { WM_GETTEXT, sent|defwinproc|optional }, 14130 { WM_ACTIVATE, sent|wparam, 0 }, 14131 { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, 14132 { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, 14133 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 14134 { WM_KILLFOCUS, sent|optional }, 14135 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, 14136 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 14137 { WM_NCACTIVATE, sent|wparam|optional, 1 }, 14138 { WM_GETTEXT, sent|defwinproc|optional }, 14139 { WM_ACTIVATE, sent|wparam|optional, 1 }, 14140 { HCBT_SETFOCUS, hook|optional }, 14141 { WM_KILLFOCUS, sent|defwinproc|optional }, 14142 { WM_IME_SETCONTEXT, sent|defwinproc|optional }, 14143 { WM_IME_SETCONTEXT, sent|defwinproc|optional }, 14144 { WM_IME_SETCONTEXT, sent|optional }, 14145 { WM_IME_SETCONTEXT, sent|optional }, 14146 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, 14147 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 14148 { WM_SETFOCUS, sent|defwinproc|optional }, 14149 { WM_GETTEXT, sent|optional }, 14150 { 0 } 14151 }; 14152 /* SetActiveWindow( hwnd ) hwnd visible */ 14153 static const struct message SetActiveWindowSeq1[] = 14154 { 14155 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 14156 { 0 } 14157 }; 14158 /* SetActiveWindow( popup ) hwnd visible, popup visible */ 14159 static const struct message SetActiveWindowSeq2[] = 14160 { 14161 { HCBT_ACTIVATE, hook }, 14162 { WM_NCACTIVATE, sent|wparam, 0 }, 14163 { WM_GETTEXT, sent|defwinproc|optional }, 14164 { WM_ACTIVATE, sent|wparam, 0 }, 14165 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 14166 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 14167 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, 14168 { WM_NCPAINT, sent|optional }, 14169 { WM_GETTEXT, sent|defwinproc|optional }, 14170 { WM_ERASEBKGND, sent|optional }, 14171 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 14172 { WM_NCACTIVATE, sent|wparam, 1 }, 14173 { WM_GETTEXT, sent|defwinproc|optional }, 14174 { WM_ACTIVATE, sent|wparam, 1 }, 14175 { HCBT_SETFOCUS, hook }, 14176 { WM_KILLFOCUS, sent|defwinproc }, 14177 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 }, 14178 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 14179 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, 14180 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 14181 { WM_SETFOCUS, sent|defwinproc }, 14182 { WM_GETTEXT, sent|optional }, 14183 { 0 } 14184 }; 14185 14186 /* SetActiveWindow( hwnd ) hwnd not visible */ 14187 static const struct message SetActiveWindowSeq3[] = 14188 { 14189 { HCBT_ACTIVATE, hook }, 14190 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 14191 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, 14192 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE }, 14193 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOACTIVATE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 14194 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 14195 { WM_ACTIVATEAPP, sent|wparam, 1 }, 14196 { WM_ACTIVATEAPP, sent|wparam, 1 }, 14197 { WM_NCACTIVATE, sent|wparam, 1 }, 14198 { WM_ACTIVATE, sent|wparam, 1 }, 14199 { HCBT_SETFOCUS, hook }, 14200 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 14201 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 14202 { WM_SETFOCUS, sent|defwinproc }, 14203 { 0 } 14204 }; 14205 /* SetActiveWindow( popup ) hwnd not visible, popup not visible */ 14206 static const struct message SetActiveWindowSeq4[] = 14207 { 14208 { HCBT_ACTIVATE, hook }, 14209 { WM_NCACTIVATE, sent|wparam, 0 }, 14210 { WM_GETTEXT, sent|defwinproc|optional }, 14211 { WM_ACTIVATE, sent|wparam, 0 }, 14212 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 14213 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE }, 14214 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, 14215 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 14216 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 14217 { WM_NCACTIVATE, sent|wparam, 1 }, 14218 { WM_GETTEXT, sent|defwinproc|optional }, 14219 { WM_ACTIVATE, sent|wparam, 1 }, 14220 { HCBT_SETFOCUS, hook }, 14221 { WM_KILLFOCUS, sent|defwinproc }, 14222 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 }, 14223 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 14224 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, 14225 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 14226 { WM_SETFOCUS, sent|defwinproc }, 14227 { 0 } 14228 }; 14229 14230 14231 static void test_SetActiveWindow(void) 14232 { 14233 HWND hwnd, popup, ret; 14234 14235 hwnd = CreateWindowExA(0, "TestWindowClass", "Test SetActiveWindow", 14236 WS_OVERLAPPEDWINDOW | WS_VISIBLE, 14237 100, 100, 200, 200, 0, 0, 0, NULL); 14238 14239 popup = CreateWindowExA(0, "TestWindowClass", "Test SetActiveWindow", 14240 WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_POPUP, 14241 100, 100, 200, 200, hwnd, 0, 0, NULL); 14242 14243 ok(hwnd != 0, "Failed to create overlapped window\n"); 14244 ok(popup != 0, "Failed to create popup window\n"); 14245 SetForegroundWindow( popup ); 14246 flush_sequence(); 14247 14248 trace("SetActiveWindow(0)\n"); 14249 ret = SetActiveWindow(0); 14250 ok( ret == popup, "Failed to SetActiveWindow(0)\n"); 14251 ok_sequence(SetActiveWindowSeq0, "SetActiveWindow(0)", FALSE); 14252 flush_sequence(); 14253 14254 trace("SetActiveWindow(hwnd), hwnd visible\n"); 14255 ret = SetActiveWindow(hwnd); 14256 if (ret == hwnd) ok_sequence(SetActiveWindowSeq1, "SetActiveWindow(hwnd), hwnd visible", TRUE); 14257 flush_sequence(); 14258 14259 trace("SetActiveWindow(popup), hwnd visible, popup visible\n"); 14260 ret = SetActiveWindow(popup); 14261 ok( ret == hwnd, "Failed to SetActiveWindow(popup), popup visible\n"); 14262 ok_sequence(SetActiveWindowSeq2, "SetActiveWindow(popup), hwnd visible, popup visible", FALSE); 14263 flush_sequence(); 14264 14265 ShowWindow(hwnd, SW_HIDE); 14266 ShowWindow(popup, SW_HIDE); 14267 flush_sequence(); 14268 14269 trace("SetActiveWindow(hwnd), hwnd not visible\n"); 14270 ret = SetActiveWindow(hwnd); 14271 ok( ret == NULL, "SetActiveWindow(hwnd), hwnd not visible, previous is %p\n", ret ); 14272 ok_sequence(SetActiveWindowSeq3, "SetActiveWindow(hwnd), hwnd not visible", TRUE); 14273 flush_sequence(); 14274 14275 trace("SetActiveWindow(popup), hwnd not visible, popup not visible\n"); 14276 ret = SetActiveWindow(popup); 14277 ok( ret == hwnd, "Failed to SetActiveWindow(popup)\n"); 14278 ok_sequence(SetActiveWindowSeq4, "SetActiveWindow(popup), hwnd not visible, popup not visible", TRUE); 14279 flush_sequence(); 14280 14281 trace("done\n"); 14282 14283 DestroyWindow(hwnd); 14284 } 14285 14286 static const struct message SetForegroundWindowSeq[] = 14287 { 14288 { WM_NCACTIVATE, sent|wparam, 0 }, 14289 { WM_GETTEXT, sent|defwinproc|optional }, 14290 { WM_ACTIVATE, sent|wparam, 0 }, 14291 { WM_ACTIVATEAPP, sent|wparam, 0 }, 14292 { WM_KILLFOCUS, sent }, 14293 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 14294 { WM_IME_NOTIFY, sent|wparam|optional|defwinproc, 1 }, 14295 { 0 } 14296 }; 14297 14298 static void test_SetForegroundWindow(void) 14299 { 14300 HWND hwnd; 14301 14302 hwnd = CreateWindowExA(0, "TestWindowClass", "Test SetForegroundWindow", 14303 WS_OVERLAPPEDWINDOW | WS_VISIBLE, 14304 100, 100, 200, 200, 0, 0, 0, NULL); 14305 ok (hwnd != 0, "Failed to create overlapped window\n"); 14306 SetForegroundWindow( hwnd ); 14307 flush_sequence(); 14308 14309 trace("SetForegroundWindow( 0 )\n"); 14310 SetForegroundWindow( 0 ); 14311 ok_sequence(WmEmptySeq, "SetForegroundWindow( 0 ) away from foreground top level window", FALSE); 14312 trace("SetForegroundWindow( GetDesktopWindow() )\n"); 14313 SetForegroundWindow( GetDesktopWindow() ); 14314 ok_sequence(SetForegroundWindowSeq, "SetForegroundWindow( desktop ) away from " 14315 "foreground top level window", FALSE); 14316 trace("done\n"); 14317 14318 DestroyWindow(hwnd); 14319 } 14320 14321 static DWORD get_input_codepage( void ) 14322 { 14323 DWORD cp; 14324 int ret; 14325 HKL hkl = GetKeyboardLayout( 0 ); 14326 14327 ret = GetLocaleInfoW( LOWORD(hkl), LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER, 14328 (WCHAR *)&cp, sizeof(cp) / sizeof(WCHAR) ); 14329 if (!ret) cp = CP_ACP; 14330 return cp; 14331 } 14332 14333 static void test_dbcs_wm_char(void) 14334 { 14335 BYTE dbch[2]; 14336 WCHAR wch, bad_wch; 14337 HWND hwnd, hwnd2; 14338 MSG msg; 14339 DWORD time; 14340 POINT pt; 14341 DWORD_PTR res; 14342 CPINFOEXA cpinfo; 14343 UINT i, j, k; 14344 struct message wmCharSeq[2]; 14345 BOOL ret; 14346 DWORD cp = get_input_codepage(); 14347 14348 if (!pGetCPInfoExA) 14349 { 14350 win_skip("GetCPInfoExA is not available\n"); 14351 return; 14352 } 14353 14354 pGetCPInfoExA( cp, 0, &cpinfo ); 14355 if (cpinfo.MaxCharSize != 2) 14356 { 14357 skip( "Skipping DBCS WM_CHAR test in SBCS codepage '%s'\n", cpinfo.CodePageName ); 14358 return; 14359 } 14360 14361 dbch[0] = dbch[1] = 0; 14362 wch = 0; 14363 bad_wch = cpinfo.UnicodeDefaultChar; 14364 for (i = 0; !wch && i < MAX_LEADBYTES && cpinfo.LeadByte[i]; i += 2) 14365 for (j = cpinfo.LeadByte[i]; !wch && j <= cpinfo.LeadByte[i+1]; j++) 14366 for (k = 128; k <= 255; k++) 14367 { 14368 char str[2]; 14369 WCHAR wstr[2]; 14370 str[0] = j; 14371 str[1] = k; 14372 if (MultiByteToWideChar( cp, 0, str, 2, wstr, 2 ) == 1 && 14373 WideCharToMultiByte( cp, 0, wstr, 1, str, 2, NULL, NULL ) == 2 && 14374 (BYTE)str[0] == j && (BYTE)str[1] == k && 14375 HIBYTE(wstr[0]) && HIBYTE(wstr[0]) != 0xff) 14376 { 14377 dbch[0] = j; 14378 dbch[1] = k; 14379 wch = wstr[0]; 14380 break; 14381 } 14382 } 14383 14384 if (!wch) 14385 { 14386 skip( "Skipping DBCS WM_CHAR test, no appropriate char found\n" ); 14387 return; 14388 } 14389 trace( "using dbcs char %02x,%02x wchar %04x bad wchar %04x codepage '%s'\n", 14390 dbch[0], dbch[1], wch, bad_wch, cpinfo.CodePageName ); 14391 14392 hwnd = CreateWindowExW(0, testWindowClassW, NULL, 14393 WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, 0, 0, 0, NULL); 14394 hwnd2 = CreateWindowExW(0, testWindowClassW, NULL, 14395 WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, 0, 0, 0, NULL); 14396 ok (hwnd != 0, "Failed to create overlapped window\n"); 14397 ok (hwnd2 != 0, "Failed to create overlapped window\n"); 14398 flush_sequence(); 14399 14400 memset( wmCharSeq, 0, sizeof(wmCharSeq) ); 14401 wmCharSeq[0].message = WM_CHAR; 14402 wmCharSeq[0].flags = sent|wparam; 14403 wmCharSeq[0].wParam = wch; 14404 14405 /* posted message */ 14406 PostMessageA( hwnd, WM_CHAR, dbch[0], 0 ); 14407 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14408 ok( !ret, "got message %x\n", msg.message ); 14409 PostMessageA( hwnd, WM_CHAR, dbch[1], 0 ); 14410 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14411 ok( ret, "no message\n" ); 14412 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14413 ok( msg.wParam == wch, "bad wparam %lx/%x\n", msg.wParam, wch ); 14414 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14415 ok( !ret, "got message %x\n", msg.message ); 14416 14417 /* posted thread message */ 14418 PostThreadMessageA( GetCurrentThreadId(), WM_CHAR, dbch[0], 0 ); 14419 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14420 ok( !ret, "got message %x\n", msg.message ); 14421 PostMessageA( hwnd, WM_CHAR, dbch[1], 0 ); 14422 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14423 ok( ret, "no message\n" ); 14424 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14425 ok( msg.wParam == wch, "bad wparam %lx/%x\n", msg.wParam, wch ); 14426 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14427 ok( !ret, "got message %x\n", msg.message ); 14428 14429 /* sent message */ 14430 flush_sequence(); 14431 SendMessageA( hwnd, WM_CHAR, dbch[0], 0 ); 14432 ok_sequence( WmEmptySeq, "no messages", FALSE ); 14433 SendMessageA( hwnd, WM_CHAR, dbch[1], 0 ); 14434 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14435 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14436 ok( !ret, "got message %x\n", msg.message ); 14437 14438 /* sent message with timeout */ 14439 flush_sequence(); 14440 SendMessageTimeoutA( hwnd, WM_CHAR, dbch[0], 0, SMTO_NORMAL, 0, &res ); 14441 ok_sequence( WmEmptySeq, "no messages", FALSE ); 14442 SendMessageTimeoutA( hwnd, WM_CHAR, dbch[1], 0, SMTO_NORMAL, 0, &res ); 14443 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14444 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14445 ok( !ret, "got message %x\n", msg.message ); 14446 14447 /* sent message with timeout and callback */ 14448 flush_sequence(); 14449 SendMessageTimeoutA( hwnd, WM_CHAR, dbch[0], 0, SMTO_NORMAL, 0, &res ); 14450 ok_sequence( WmEmptySeq, "no messages", FALSE ); 14451 SendMessageCallbackA( hwnd, WM_CHAR, dbch[1], 0, NULL, 0 ); 14452 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14453 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14454 ok( !ret, "got message %x\n", msg.message ); 14455 14456 /* sent message with callback */ 14457 flush_sequence(); 14458 SendNotifyMessageA( hwnd, WM_CHAR, dbch[0], 0 ); 14459 ok_sequence( WmEmptySeq, "no messages", FALSE ); 14460 SendMessageCallbackA( hwnd, WM_CHAR, dbch[1], 0, NULL, 0 ); 14461 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14462 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14463 ok( !ret, "got message %x\n", msg.message ); 14464 14465 /* direct window proc call */ 14466 flush_sequence(); 14467 CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ), hwnd, WM_CHAR, dbch[0], 0 ); 14468 ok_sequence( WmEmptySeq, "no messages", FALSE ); 14469 CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ), hwnd, WM_CHAR, dbch[1], 0 ); 14470 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14471 14472 /* dispatch message */ 14473 msg.hwnd = hwnd; 14474 msg.message = WM_CHAR; 14475 msg.wParam = dbch[0]; 14476 msg.lParam = 0; 14477 DispatchMessageA( &msg ); 14478 ok_sequence( WmEmptySeq, "no messages", FALSE ); 14479 msg.wParam = dbch[1]; 14480 DispatchMessageA( &msg ); 14481 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14482 14483 /* window handle is irrelevant */ 14484 flush_sequence(); 14485 SendMessageA( hwnd2, WM_CHAR, dbch[0], 0 ); 14486 ok_sequence( WmEmptySeq, "no messages", FALSE ); 14487 SendMessageA( hwnd, WM_CHAR, dbch[1], 0 ); 14488 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14489 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14490 ok( !ret, "got message %x\n", msg.message ); 14491 14492 /* interleaved post and send */ 14493 flush_sequence(); 14494 PostMessageA( hwnd2, WM_CHAR, dbch[0], 0 ); 14495 SendMessageA( hwnd2, WM_CHAR, dbch[0], 0 ); 14496 ok_sequence( WmEmptySeq, "no messages", FALSE ); 14497 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14498 ok( !ret, "got message %x\n", msg.message ); 14499 PostMessageA( hwnd, WM_CHAR, dbch[1], 0 ); 14500 ok_sequence( WmEmptySeq, "no messages", FALSE ); 14501 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14502 ok( ret, "no message\n" ); 14503 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14504 ok( msg.wParam == wch, "bad wparam %lx/%x\n", msg.wParam, wch ); 14505 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14506 ok( !ret, "got message %x\n", msg.message ); 14507 SendMessageA( hwnd, WM_CHAR, dbch[1], 0 ); 14508 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14509 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14510 ok( !ret, "got message %x\n", msg.message ); 14511 14512 /* interleaved sent message and winproc */ 14513 flush_sequence(); 14514 SendMessageA( hwnd, WM_CHAR, dbch[0], 0 ); 14515 CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ), hwnd, WM_CHAR, dbch[0], 0 ); 14516 ok_sequence( WmEmptySeq, "no messages", FALSE ); 14517 SendMessageA( hwnd, WM_CHAR, dbch[1], 0 ); 14518 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14519 CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ), hwnd, WM_CHAR, dbch[1], 0 ); 14520 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14521 14522 /* interleaved winproc and dispatch */ 14523 msg.hwnd = hwnd; 14524 msg.message = WM_CHAR; 14525 msg.wParam = dbch[0]; 14526 msg.lParam = 0; 14527 CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ), hwnd, WM_CHAR, dbch[0], 0 ); 14528 DispatchMessageA( &msg ); 14529 ok_sequence( WmEmptySeq, "no messages", FALSE ); 14530 msg.wParam = dbch[1]; 14531 DispatchMessageA( &msg ); 14532 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14533 CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ), hwnd, WM_CHAR, dbch[1], 0 ); 14534 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14535 14536 /* interleaved sends */ 14537 flush_sequence(); 14538 SendMessageA( hwnd, WM_CHAR, dbch[0], 0 ); 14539 SendMessageCallbackA( hwnd, WM_CHAR, dbch[0], 0, NULL, 0 ); 14540 ok_sequence( WmEmptySeq, "no messages", FALSE ); 14541 SendMessageTimeoutA( hwnd, WM_CHAR, dbch[1], 0, SMTO_NORMAL, 0, &res ); 14542 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14543 SendMessageA( hwnd, WM_CHAR, dbch[1], 0 ); 14544 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14545 14546 /* dbcs WM_CHAR */ 14547 flush_sequence(); 14548 SendMessageA( hwnd2, WM_CHAR, (dbch[1] << 8) | dbch[0], 0 ); 14549 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14550 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14551 ok( !ret, "got message %x\n", msg.message ); 14552 14553 /* other char messages are not magic */ 14554 PostMessageA( hwnd, WM_SYSCHAR, dbch[0], 0 ); 14555 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14556 ok( ret, "no message\n" ); 14557 ok( msg.message == WM_SYSCHAR, "unexpected message %x\n", msg.message ); 14558 ok( msg.wParam == bad_wch, "bad wparam %lx/%x\n", msg.wParam, bad_wch ); 14559 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14560 ok( !ret, "got message %x\n", msg.message ); 14561 PostMessageA( hwnd, WM_DEADCHAR, dbch[0], 0 ); 14562 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14563 ok( ret, "no message\n" ); 14564 ok( msg.message == WM_DEADCHAR, "unexpected message %x\n", msg.message ); 14565 ok( msg.wParam == bad_wch, "bad wparam %lx/%x\n", msg.wParam, bad_wch ); 14566 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14567 ok( !ret, "got message %x\n", msg.message ); 14568 14569 /* test retrieving messages */ 14570 14571 PostMessageW( hwnd, WM_CHAR, wch, 0 ); 14572 ret = PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ); 14573 ok( ret, "no message\n" ); 14574 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14575 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14576 ok( msg.wParam == dbch[0], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); 14577 ret = PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ); 14578 ok( ret, "no message\n" ); 14579 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14580 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14581 ok( msg.wParam == dbch[1], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); 14582 ret = PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ); 14583 ok( !ret, "got message %x\n", msg.message ); 14584 14585 /* message filters */ 14586 PostMessageW( hwnd, WM_CHAR, wch, 0 ); 14587 ret = PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ); 14588 ok( ret, "no message\n" ); 14589 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14590 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14591 ok( msg.wParam == dbch[0], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); 14592 /* message id is filtered, hwnd is not */ 14593 ret = PeekMessageA( &msg, hwnd, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ); 14594 ok( !ret, "no message\n" ); 14595 ret = PeekMessageA( &msg, hwnd2, 0, 0, PM_REMOVE ); 14596 ok( ret, "no message\n" ); 14597 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14598 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14599 ok( msg.wParam == dbch[1], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); 14600 ret = PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ); 14601 ok( !ret, "got message %x\n", msg.message ); 14602 14603 /* mixing GetMessage and PostMessage */ 14604 PostMessageW( hwnd, WM_CHAR, wch, 0xbeef ); 14605 ok( GetMessageA( &msg, hwnd, 0, 0 ), "no message\n" ); 14606 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14607 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14608 ok( msg.wParam == dbch[0], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); 14609 ok( msg.lParam == 0xbeef, "bad lparam %lx\n", msg.lParam ); 14610 time = msg.time; 14611 pt = msg.pt; 14612 ok( time - GetTickCount() <= 100, "bad time %x\n", msg.time ); 14613 ret = PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ); 14614 ok( ret, "no message\n" ); 14615 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14616 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14617 ok( msg.wParam == dbch[1], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); 14618 ok( msg.lParam == 0xbeef, "bad lparam %lx\n", msg.lParam ); 14619 ok( msg.time == time, "bad time %x/%x\n", msg.time, time ); 14620 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 ); 14621 ret = PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ); 14622 ok( !ret, "got message %x\n", msg.message ); 14623 14624 /* without PM_REMOVE */ 14625 PostMessageW( hwnd, WM_CHAR, wch, 0 ); 14626 ret = PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ); 14627 ok( ret, "no message\n" ); 14628 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14629 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14630 ok( msg.wParam == dbch[0], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); 14631 ret = PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ); 14632 ok( ret, "no message\n" ); 14633 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14634 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14635 ok( msg.wParam == dbch[0], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); 14636 ret = PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ); 14637 ok( ret, "no message\n" ); 14638 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14639 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14640 ok( msg.wParam == dbch[1], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); 14641 ret = PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ); 14642 ok( ret, "no message\n" ); 14643 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14644 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14645 ok( msg.wParam == dbch[1], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); 14646 ret = PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ); 14647 ok( !ret, "got message %x\n", msg.message ); 14648 14649 DestroyWindow(hwnd); 14650 DestroyWindow(hwnd2); 14651 } 14652 14653 static void test_unicode_wm_char(void) 14654 { 14655 HWND hwnd; 14656 MSG msg; 14657 struct message seq[2]; 14658 HKL hkl_orig, hkl_greek; 14659 DWORD cp; 14660 LCID thread_locale; 14661 14662 hkl_orig = GetKeyboardLayout( 0 ); 14663 GetLocaleInfoW( LOWORD( hkl_orig ), LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER, (WCHAR*)&cp, sizeof(cp) / sizeof(WCHAR) ); 14664 if (cp != 1252) 14665 { 14666 skip( "Default codepage %d\n", cp ); 14667 return; 14668 } 14669 14670 hkl_greek = LoadKeyboardLayoutA( "00000408", 0 ); 14671 if (!hkl_greek || hkl_greek == hkl_orig /* win2k */) 14672 { 14673 skip( "Unable to load Greek keyboard layout\n" ); 14674 return; 14675 } 14676 14677 hwnd = CreateWindowExW( 0, testWindowClassW, NULL, WS_OVERLAPPEDWINDOW, 14678 100, 100, 200, 200, 0, 0, 0, NULL ); 14679 flush_sequence(); 14680 14681 PostMessageW( hwnd, WM_CHAR, 0x3b1, 0 ); 14682 14683 while (GetMessageW( &msg, hwnd, 0, 0 )) 14684 { 14685 if (!ignore_message( msg.message )) break; 14686 } 14687 14688 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14689 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14690 ok( msg.wParam == 0x3b1, "bad wparam %lx\n", msg.wParam ); 14691 ok( msg.lParam == 0, "bad lparam %lx\n", msg.lParam ); 14692 14693 DispatchMessageW( &msg ); 14694 14695 memset( seq, 0, sizeof(seq) ); 14696 seq[0].message = WM_CHAR; 14697 seq[0].flags = sent|wparam; 14698 seq[0].wParam = 0x3b1; 14699 14700 ok_sequence( seq, "unicode WM_CHAR", FALSE ); 14701 14702 flush_sequence(); 14703 14704 /* greek alpha -> 'a' in cp1252 */ 14705 PostMessageW( hwnd, WM_CHAR, 0x3b1, 0 ); 14706 14707 ok( GetMessageA( &msg, hwnd, 0, 0 ), "no message\n" ); 14708 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14709 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14710 ok( msg.wParam == 0x61, "bad wparam %lx\n", msg.wParam ); 14711 ok( msg.lParam == 0, "bad lparam %lx\n", msg.lParam ); 14712 14713 DispatchMessageA( &msg ); 14714 14715 seq[0].wParam = 0x61; 14716 ok_sequence( seq, "unicode WM_CHAR", FALSE ); 14717 14718 thread_locale = GetThreadLocale(); 14719 ActivateKeyboardLayout( hkl_greek, 0 ); 14720 ok( GetThreadLocale() == thread_locale, "locale changed from %08x to %08x\n", 14721 thread_locale, GetThreadLocale() ); 14722 14723 flush_sequence(); 14724 14725 /* greek alpha -> 0xe1 in cp1253 */ 14726 PostMessageW( hwnd, WM_CHAR, 0x3b1, 0 ); 14727 14728 ok( GetMessageA( &msg, hwnd, 0, 0 ), "no message\n" ); 14729 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14730 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14731 ok( msg.wParam == 0xe1, "bad wparam %lx\n", msg.wParam ); 14732 ok( msg.lParam == 0, "bad lparam %lx\n", msg.lParam ); 14733 14734 DispatchMessageA( &msg ); 14735 14736 seq[0].wParam = 0x3b1; 14737 ok_sequence( seq, "unicode WM_CHAR", FALSE ); 14738 14739 DestroyWindow( hwnd ); 14740 ActivateKeyboardLayout( hkl_orig, 0 ); 14741 UnloadKeyboardLayout( hkl_greek ); 14742 } 14743 14744 #define ID_LISTBOX 0x000f 14745 14746 static const struct message wm_lb_setcursel_0[] = 14747 { 14748 { LB_SETCURSEL, sent|wparam|lparam, 0, 0 }, 14749 { WM_CTLCOLORLISTBOX, sent|parent }, 14750 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000120f2 }, 14751 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 1 }, 14752 { EVENT_OBJECT_SELECTION, winevent_hook|wparam|lparam, OBJID_CLIENT, 1 }, 14753 { 0 } 14754 }; 14755 static const struct message wm_lb_setcursel_1[] = 14756 { 14757 { LB_SETCURSEL, sent|wparam|lparam, 1, 0 }, 14758 { WM_CTLCOLORLISTBOX, sent|parent }, 14759 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000020f2 }, 14760 { WM_CTLCOLORLISTBOX, sent|parent }, 14761 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000121f2 }, 14762 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 2 }, 14763 { EVENT_OBJECT_SELECTION, winevent_hook|wparam|lparam, OBJID_CLIENT, 2 }, 14764 { 0 } 14765 }; 14766 static const struct message wm_lb_setcursel_2[] = 14767 { 14768 { LB_SETCURSEL, sent|wparam|lparam, 2, 0 }, 14769 { WM_CTLCOLORLISTBOX, sent|parent }, 14770 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000021f2 }, 14771 { WM_CTLCOLORLISTBOX, sent|parent }, 14772 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000122f2 }, 14773 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 3 }, 14774 { EVENT_OBJECT_SELECTION, winevent_hook|wparam|lparam, OBJID_CLIENT, 3 }, 14775 { 0 } 14776 }; 14777 static const struct message wm_lb_click_0[] = 14778 { 14779 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, MAKELPARAM(1,1) }, 14780 { HCBT_SETFOCUS, hook }, 14781 { WM_KILLFOCUS, sent|parent }, 14782 { WM_IME_SETCONTEXT, sent|wparam|optional|parent, 0 }, 14783 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 14784 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 14785 { WM_SETFOCUS, sent|defwinproc }, 14786 14787 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x001142f2 }, 14788 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_LISTBOX, LBN_SETFOCUS) }, 14789 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 3 }, 14790 { WM_LBTRACKPOINT, sent|wparam|lparam|parent, 0, MAKELPARAM(1,1) }, 14791 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, 14792 14793 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000142f2 }, 14794 { WM_CTLCOLORLISTBOX, sent|parent }, 14795 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000022f2 }, 14796 { WM_CTLCOLORLISTBOX, sent|parent }, 14797 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000120f2 }, 14798 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x001140f2 }, 14799 14800 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 1 }, 14801 { EVENT_OBJECT_SELECTION, winevent_hook|wparam|lparam, OBJID_CLIENT, 1 }, 14802 14803 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 }, 14804 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, 14805 { WM_CAPTURECHANGED, sent|wparam|lparam|defwinproc, 0, 0 }, 14806 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_LISTBOX, LBN_SELCHANGE) }, 14807 { 0 } 14808 }; 14809 static const struct message wm_lb_deletestring[] = 14810 { 14811 { LB_DELETESTRING, sent|wparam|lparam, 0, 0 }, 14812 { WM_DELETEITEM, sent|wparam|parent|optional, ID_LISTBOX, 0 }, 14813 { WM_DRAWITEM, sent|wparam|parent|optional, ID_LISTBOX }, 14814 { WM_DRAWITEM, sent|wparam|parent|optional, ID_LISTBOX }, 14815 { 0 } 14816 }; 14817 static const struct message wm_lb_deletestring_reset[] = 14818 { 14819 { LB_DELETESTRING, sent|wparam|lparam, 0, 0 }, 14820 { LB_RESETCONTENT, sent|wparam|lparam|defwinproc|optional, 0, 0 }, 14821 { WM_DELETEITEM, sent|wparam|parent|optional, ID_LISTBOX, 0 }, 14822 { WM_DRAWITEM, sent|wparam|parent|optional, ID_LISTBOX }, 14823 { WM_DRAWITEM, sent|wparam|parent|optional, ID_LISTBOX }, 14824 { 0 } 14825 }; 14826 static const struct message wm_lb_addstring[] = 14827 { 14828 { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ef }, 14829 { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ed }, 14830 { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ee }, 14831 { 0 } 14832 }; 14833 static const struct message wm_lb_addstring_ownerdraw[] = 14834 { 14835 { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ed }, 14836 { WM_MEASUREITEM, sent|wparam|lparam|parent, 0xf0f2, 0xf30604ed }, 14837 { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ee }, 14838 { WM_MEASUREITEM, sent|wparam|lparam|parent, 0xf1f2, 0xf30604ee }, 14839 { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ef }, 14840 { WM_MEASUREITEM, sent|wparam|lparam|parent, 0xf2f2, 0xf30604ef }, 14841 { 0 } 14842 }; 14843 static const struct message wm_lb_addstring_sort_ownerdraw[] = 14844 { 14845 { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ed }, 14846 { WM_MEASUREITEM, sent|wparam|lparam|parent, 0xf0f2, 0xf30604ed }, 14847 { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ee }, 14848 { WM_COMPAREITEM, sent|wparam|lparam|parent, 0xf30604ed, 0xf30604ee }, 14849 { WM_MEASUREITEM, sent|wparam|lparam|parent, 0xf1f2, 0xf30604ee }, 14850 { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ef }, 14851 { WM_COMPAREITEM, sent|wparam|lparam|parent, 0xf30604ed, 0xf30604ef }, 14852 { WM_COMPAREITEM, sent|wparam|lparam|parent, 0xf30604ee, 0xf30604ef }, 14853 { WM_MEASUREITEM, sent|wparam|lparam|parent, 0xf2f2, 0xf30604ef }, 14854 { 0 } 14855 }; 14856 14857 #define check_lb_state(a1, a2, a3, a4, a5) check_lb_state_dbg(a1, a2, a3, a4, a5, __LINE__) 14858 14859 static LRESULT (WINAPI *listbox_orig_proc)(HWND, UINT, WPARAM, LPARAM); 14860 14861 static LRESULT WINAPI listbox_hook_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) 14862 { 14863 static LONG defwndproc_counter = 0; 14864 LRESULT ret; 14865 struct recvd_message msg; 14866 14867 /* do not log painting messages */ 14868 if (message != WM_PAINT && 14869 message != WM_NCPAINT && 14870 message != WM_SYNCPAINT && 14871 message != WM_ERASEBKGND && 14872 message != WM_NCHITTEST && 14873 message != WM_GETTEXT && 14874 !ignore_message( message )) 14875 { 14876 msg.hwnd = hwnd; 14877 msg.message = message; 14878 msg.flags = sent|wparam|lparam; 14879 if (defwndproc_counter) msg.flags |= defwinproc; 14880 msg.wParam = wp; 14881 if (message == LB_ADDSTRING) 14882 msg.lParam = lp ? hash_Ly((const char *)lp) : 0; 14883 else 14884 msg.lParam = lp; 14885 msg.descr = "listbox"; 14886 add_message(&msg); 14887 } 14888 14889 defwndproc_counter++; 14890 ret = CallWindowProcA(listbox_orig_proc, hwnd, message, wp, lp); 14891 defwndproc_counter--; 14892 14893 return ret; 14894 } 14895 14896 static void check_lb_state_dbg(HWND listbox, int count, int cur_sel, 14897 int caret_index, int top_index, int line) 14898 { 14899 LRESULT ret; 14900 14901 /* calling an orig proc helps to avoid unnecessary message logging */ 14902 ret = CallWindowProcA(listbox_orig_proc, listbox, LB_GETCOUNT, 0, 0); 14903 ok_(__FILE__, line)(ret == count, "expected count %d, got %ld\n", count, ret); 14904 ret = CallWindowProcA(listbox_orig_proc, listbox, LB_GETCURSEL, 0, 0); 14905 ok_(__FILE__, line)(ret == cur_sel, "expected cur sel %d, got %ld\n", cur_sel, ret); 14906 ret = CallWindowProcA(listbox_orig_proc, listbox, LB_GETCARETINDEX, 0, 0); 14907 ok_(__FILE__, line)(ret == caret_index || 14908 broken(cur_sel == -1 && caret_index == 0 && ret == -1), /* nt4 */ 14909 "expected caret index %d, got %ld\n", caret_index, ret); 14910 ret = CallWindowProcA(listbox_orig_proc, listbox, LB_GETTOPINDEX, 0, 0); 14911 ok_(__FILE__, line)(ret == top_index, "expected top index %d, got %ld\n", top_index, ret); 14912 } 14913 14914 static void test_listbox_messages(void) 14915 { 14916 HWND parent, listbox; 14917 LRESULT ret; 14918 14919 parent = CreateWindowExA(0, "TestParentClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 14920 100, 100, 200, 200, 0, 0, 0, NULL); 14921 /* with LBS_HASSTRINGS */ 14922 listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, "ListBox", NULL, 14923 WS_CHILD | LBS_NOTIFY | LBS_OWNERDRAWVARIABLE | LBS_HASSTRINGS | WS_VISIBLE, 14924 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL); 14925 listbox_orig_proc = (WNDPROC)SetWindowLongPtrA(listbox, GWLP_WNDPROC, (ULONG_PTR)listbox_hook_proc); 14926 14927 check_lb_state(listbox, 0, LB_ERR, 0, 0); 14928 14929 flush_sequence(); 14930 14931 log_all_parent_messages++; 14932 14933 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0"); 14934 ok(ret == 0, "expected 0, got %ld\n", ret); 14935 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1"); 14936 ok(ret == 1, "expected 1, got %ld\n", ret); 14937 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2"); 14938 ok(ret == 2, "expected 2, got %ld\n", ret); 14939 14940 ok_sequence(wm_lb_addstring_ownerdraw, "LB_ADDSTRING", FALSE); 14941 check_lb_state(listbox, 3, LB_ERR, 0, 0); 14942 14943 flush_sequence(); 14944 14945 trace("selecting item 0\n"); 14946 ret = SendMessageA(listbox, LB_SETCURSEL, 0, 0); 14947 ok(ret == 0, "expected 0, got %ld\n", ret); 14948 ok_sequence(wm_lb_setcursel_0, "LB_SETCURSEL 0", FALSE ); 14949 check_lb_state(listbox, 3, 0, 0, 0); 14950 flush_sequence(); 14951 14952 trace("selecting item 1\n"); 14953 ret = SendMessageA(listbox, LB_SETCURSEL, 1, 0); 14954 ok(ret == 1, "expected 1, got %ld\n", ret); 14955 ok_sequence(wm_lb_setcursel_1, "LB_SETCURSEL 1", FALSE ); 14956 check_lb_state(listbox, 3, 1, 1, 0); 14957 14958 trace("selecting item 2\n"); 14959 ret = SendMessageA(listbox, LB_SETCURSEL, 2, 0); 14960 ok(ret == 2, "expected 2, got %ld\n", ret); 14961 ok_sequence(wm_lb_setcursel_2, "LB_SETCURSEL 2", FALSE ); 14962 check_lb_state(listbox, 3, 2, 2, 0); 14963 14964 trace("clicking on item 0\n"); 14965 ret = SendMessageA(listbox, WM_LBUTTONDOWN, 0, MAKELPARAM(1, 1)); 14966 ok(ret == LB_OKAY, "expected LB_OKAY, got %ld\n", ret); 14967 ret = SendMessageA(listbox, WM_LBUTTONUP, 0, 0); 14968 ok(ret == LB_OKAY, "expected LB_OKAY, got %ld\n", ret); 14969 ok_sequence(wm_lb_click_0, "WM_LBUTTONDOWN 0", FALSE ); 14970 check_lb_state(listbox, 3, 0, 0, 0); 14971 flush_sequence(); 14972 14973 trace("deleting item 0\n"); 14974 ret = SendMessageA(listbox, LB_DELETESTRING, 0, 0); 14975 ok(ret == 2, "expected 2, got %ld\n", ret); 14976 ok_sequence(wm_lb_deletestring, "LB_DELETESTRING 0", FALSE ); 14977 check_lb_state(listbox, 2, -1, 0, 0); 14978 flush_sequence(); 14979 14980 trace("deleting item 0\n"); 14981 ret = SendMessageA(listbox, LB_DELETESTRING, 0, 0); 14982 ok(ret == 1, "expected 1, got %ld\n", ret); 14983 ok_sequence(wm_lb_deletestring, "LB_DELETESTRING 0", FALSE ); 14984 check_lb_state(listbox, 1, -1, 0, 0); 14985 flush_sequence(); 14986 14987 trace("deleting item 0\n"); 14988 ret = SendMessageA(listbox, LB_DELETESTRING, 0, 0); 14989 ok(ret == 0, "expected 0, got %ld\n", ret); 14990 ok_sequence(wm_lb_deletestring_reset, "LB_DELETESTRING 0", FALSE ); 14991 check_lb_state(listbox, 0, -1, 0, 0); 14992 flush_sequence(); 14993 14994 trace("deleting item 0\n"); 14995 ret = SendMessageA(listbox, LB_DELETESTRING, 0, 0); 14996 ok(ret == LB_ERR, "expected LB_ERR, got %ld\n", ret); 14997 check_lb_state(listbox, 0, -1, 0, 0); 14998 flush_sequence(); 14999 15000 log_all_parent_messages--; 15001 15002 DestroyWindow(listbox); 15003 15004 /* with LBS_SORT and without LBS_HASSTRINGS */ 15005 listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, "ListBox", NULL, 15006 WS_CHILD | LBS_NOTIFY | LBS_OWNERDRAWVARIABLE | LBS_SORT | WS_VISIBLE, 15007 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL); 15008 listbox_orig_proc = (WNDPROC)SetWindowLongPtrA(listbox, GWLP_WNDPROC, (ULONG_PTR)listbox_hook_proc); 15009 15010 check_lb_state(listbox, 0, LB_ERR, 0, 0); 15011 15012 flush_sequence(); 15013 15014 log_all_parent_messages++; 15015 15016 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0"); 15017 ok(ret == 0, "expected 0, got %ld\n", ret); 15018 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1"); 15019 ok(ret == 1, "expected 1, got %ld\n", ret); 15020 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2"); 15021 ok(ret == 2, "expected 2, got %ld\n", ret); 15022 15023 ok_sequence(wm_lb_addstring_sort_ownerdraw, "LB_ADDSTRING", FALSE); 15024 check_lb_state(listbox, 3, LB_ERR, 0, 0); 15025 15026 log_all_parent_messages--; 15027 15028 DestroyWindow(listbox); 15029 15030 /* with LBS_HASSTRINGS */ 15031 listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, "ListBox", NULL, 15032 WS_CHILD | LBS_NOTIFY | LBS_HASSTRINGS | WS_VISIBLE, 15033 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL); 15034 listbox_orig_proc = (WNDPROC)SetWindowLongPtrA(listbox, GWLP_WNDPROC, (ULONG_PTR)listbox_hook_proc); 15035 15036 check_lb_state(listbox, 0, LB_ERR, 0, 0); 15037 15038 flush_sequence(); 15039 15040 log_all_parent_messages++; 15041 15042 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2"); 15043 ok(ret == 0, "expected 0, got %ld\n", ret); 15044 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0"); 15045 ok(ret == 1, "expected 1, got %ld\n", ret); 15046 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1"); 15047 ok(ret == 2, "expected 2, got %ld\n", ret); 15048 15049 ok_sequence(wm_lb_addstring, "LB_ADDSTRING", FALSE); 15050 check_lb_state(listbox, 3, LB_ERR, 0, 0); 15051 15052 log_all_parent_messages--; 15053 15054 DestroyWindow(listbox); 15055 15056 /* with LBS_HASSTRINGS and LBS_SORT */ 15057 listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, "ListBox", NULL, 15058 WS_CHILD | LBS_NOTIFY | LBS_HASSTRINGS | LBS_SORT | WS_VISIBLE, 15059 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL); 15060 listbox_orig_proc = (WNDPROC)SetWindowLongPtrA(listbox, GWLP_WNDPROC, (ULONG_PTR)listbox_hook_proc); 15061 15062 check_lb_state(listbox, 0, LB_ERR, 0, 0); 15063 15064 flush_sequence(); 15065 15066 log_all_parent_messages++; 15067 15068 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2"); 15069 ok(ret == 0, "expected 0, got %ld\n", ret); 15070 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0"); 15071 ok(ret == 0, "expected 0, got %ld\n", ret); 15072 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1"); 15073 ok(ret == 1, "expected 1, got %ld\n", ret); 15074 15075 ok_sequence(wm_lb_addstring, "LB_ADDSTRING", FALSE); 15076 check_lb_state(listbox, 3, LB_ERR, 0, 0); 15077 15078 log_all_parent_messages--; 15079 15080 DestroyWindow(listbox); 15081 DestroyWindow(parent); 15082 } 15083 15084 /*************************** Menu test ******************************/ 15085 static const struct message wm_popup_menu_1[] = 15086 { 15087 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, 15088 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, 15089 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'E', 0x20000001 }, 15090 { WM_SYSKEYDOWN, sent|wparam|lparam, 'E', 0x20000001 }, 15091 { WM_SYSCHAR, sent|wparam|lparam, 'e', 0x20000001 }, 15092 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_KEYMENU, 'e' }, 15093 { WM_ENTERMENULOOP, sent|wparam|lparam, 0, 0 }, 15094 { WM_INITMENU, sent|lparam, 0, 0 }, 15095 { WM_MENUSELECT, sent|wparam, MAKEWPARAM(1,MF_HILITE|MF_POPUP) }, 15096 { WM_INITMENUPOPUP, sent|lparam, 0, 1 }, 15097 { HCBT_CREATEWND, hook|optional }, /* Win9x doesn't create a window */ 15098 { WM_MENUSELECT, sent|wparam, MAKEWPARAM(200,MF_HILITE) }, 15099 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'E', 0xf0000001 }, 15100 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xd0000001 }, 15101 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RETURN, 0x10000001, 0, 0x40000000 }, 15102 { HCBT_DESTROYWND, hook|optional }, /* Win9x doesn't create a window */ 15103 { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, 15104 { WM_MENUSELECT, sent|wparam|lparam, MAKEWPARAM(0,0xffff), 0 }, 15105 { WM_EXITMENULOOP, sent|wparam|lparam, 0, 0 }, 15106 { WM_MENUCOMMAND, sent }, /* |wparam, 200 - Win9x */ 15107 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RETURN, 0xc0000001 }, 15108 { WM_KEYUP, sent|wparam|lparam, VK_RETURN, 0xc0000001 }, 15109 { 0 } 15110 }; 15111 static const struct message wm_popup_menu_2[] = 15112 { 15113 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, 15114 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, 15115 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'F', 0x20000001 }, 15116 { WM_SYSKEYDOWN, sent|wparam|lparam, 'F', 0x20000001 }, 15117 { WM_SYSCHAR, sent|wparam|lparam, 'f', 0x20000001 }, 15118 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_KEYMENU, 'f' }, 15119 { WM_ENTERMENULOOP, sent|wparam|lparam, 0, 0 }, 15120 { WM_INITMENU, sent|lparam, 0, 0 }, 15121 { WM_MENUSELECT, sent|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) }, 15122 { WM_INITMENUPOPUP, sent|lparam, 0, 0 }, 15123 { WM_MENUSELECT, sent|wparam|optional, MAKEWPARAM(0,MF_HILITE|MF_POPUP) }, /* Win9x */ 15124 { WM_INITMENUPOPUP, sent|lparam|optional, 0, 0 }, /* Win9x */ 15125 { HCBT_CREATEWND, hook }, 15126 { WM_MENUSELECT, sent }, /*|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) - XP 15127 |wparam, MAKEWPARAM(100,MF_HILITE) - Win9x */ 15128 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'F', 0xf0000001 }, 15129 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xd0000001 }, 15130 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RIGHT, 0x10000001 }, 15131 { WM_INITMENUPOPUP, sent|lparam|optional, 0, 0 }, /* Win9x doesn't send it */ 15132 { HCBT_CREATEWND, hook|optional }, /* Win9x doesn't send it */ 15133 { WM_MENUSELECT, sent|wparam|optional, MAKEWPARAM(100,MF_HILITE) }, 15134 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RIGHT, 0xd0000001 }, 15135 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RETURN, 0x10000001 }, 15136 { HCBT_DESTROYWND, hook }, 15137 { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, 15138 { HCBT_DESTROYWND, hook|optional }, /* Win9x doesn't send it */ 15139 { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, 15140 { WM_MENUSELECT, sent|wparam|lparam, MAKEWPARAM(0,0xffff), 0 }, 15141 { WM_EXITMENULOOP, sent|wparam|lparam, 0, 0 }, 15142 { WM_MENUCOMMAND, sent }, /* |wparam, 100 - Win9x */ 15143 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RETURN, 0xc0000001 }, 15144 { WM_KEYUP, sent|wparam|lparam, VK_RETURN, 0xc0000001 }, 15145 { 0 } 15146 }; 15147 static const struct message wm_popup_menu_3[] = 15148 { 15149 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, 15150 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, 15151 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'F', 0x20000001 }, 15152 { WM_SYSKEYDOWN, sent|wparam|lparam, 'F', 0x20000001 }, 15153 { WM_SYSCHAR, sent|wparam|lparam, 'f', 0x20000001 }, 15154 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_KEYMENU, 'f' }, 15155 { WM_ENTERMENULOOP, sent|wparam|lparam, 0, 0 }, 15156 { WM_INITMENU, sent|lparam, 0, 0 }, 15157 { WM_MENUSELECT, sent|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) }, 15158 { WM_INITMENUPOPUP, sent|lparam, 0, 0 }, 15159 { WM_MENUSELECT, sent|wparam|optional, MAKEWPARAM(0,MF_HILITE|MF_POPUP) }, /* Win9x */ 15160 { WM_INITMENUPOPUP, sent|lparam|optional, 0, 0 }, /* Win9x */ 15161 { HCBT_CREATEWND, hook }, 15162 { WM_MENUSELECT, sent }, /*|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) - XP 15163 |wparam, MAKEWPARAM(100,MF_HILITE) - Win9x */ 15164 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'F', 0xf0000001 }, 15165 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xd0000001 }, 15166 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RIGHT, 0x10000001 }, 15167 { WM_INITMENUPOPUP, sent|lparam|optional, 0, 0 }, /* Win9x doesn't send it */ 15168 { HCBT_CREATEWND, hook|optional }, /* Win9x doesn't send it */ 15169 { WM_MENUSELECT, sent|wparam|optional, MAKEWPARAM(100,MF_HILITE) }, 15170 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RIGHT, 0xd0000001 }, 15171 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RETURN, 0x10000001 }, 15172 { HCBT_DESTROYWND, hook }, 15173 { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, 15174 { HCBT_DESTROYWND, hook|optional }, /* Win9x doesn't send it */ 15175 { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, 15176 { WM_MENUSELECT, sent|wparam|lparam, MAKEWPARAM(0,0xffff), 0 }, 15177 { WM_EXITMENULOOP, sent|wparam|lparam, 0, 0 }, 15178 { WM_COMMAND, sent|wparam|lparam, 100, 0 }, 15179 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RETURN, 0xc0000001 }, 15180 { WM_KEYUP, sent|wparam|lparam, VK_RETURN, 0xc0000001 }, 15181 { 0 } 15182 }; 15183 15184 static const struct message wm_single_menu_item[] = 15185 { 15186 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, 15187 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, 15188 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'Q', 0x20000001 }, 15189 { WM_SYSKEYDOWN, sent|wparam|lparam, 'Q', 0x20000001 }, 15190 { WM_SYSCHAR, sent|wparam|lparam, 'q', 0x20000001 }, 15191 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_KEYMENU, 'q' }, 15192 { WM_ENTERMENULOOP, sent|wparam|lparam, 0, 0 }, 15193 { WM_INITMENU, sent|lparam, 0, 0 }, 15194 { WM_MENUSELECT, sent|wparam|optional, MAKEWPARAM(300,MF_HILITE) }, 15195 { WM_MENUSELECT, sent|wparam|lparam, MAKEWPARAM(0,0xffff), 0 }, 15196 { WM_EXITMENULOOP, sent|wparam|lparam, 0, 0 }, 15197 { WM_MENUCOMMAND, sent }, 15198 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'Q', 0xe0000001 }, 15199 { WM_SYSKEYUP, sent|wparam|lparam, 'Q', 0xe0000001 }, 15200 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, 15201 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 }, 15202 15203 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_ESCAPE, 1 }, 15204 { WM_KEYDOWN, sent|wparam|lparam, VK_ESCAPE, 1 }, 15205 { WM_CHAR, sent|wparam|lparam, VK_ESCAPE, 0x00000001 }, 15206 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_ESCAPE, 0xc0000001 }, 15207 { WM_KEYUP, sent|wparam|lparam, VK_ESCAPE, 0xc0000001 }, 15208 { 0 } 15209 }; 15210 15211 static LRESULT WINAPI parent_menu_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) 15212 { 15213 if (message == WM_ENTERIDLE || 15214 message == WM_INITMENU || 15215 message == WM_INITMENUPOPUP || 15216 message == WM_MENUSELECT || 15217 message == WM_PARENTNOTIFY || 15218 message == WM_ENTERMENULOOP || 15219 message == WM_EXITMENULOOP || 15220 message == WM_UNINITMENUPOPUP || 15221 message == WM_KEYDOWN || 15222 message == WM_KEYUP || 15223 message == WM_CHAR || 15224 message == WM_SYSKEYDOWN || 15225 message == WM_SYSKEYUP || 15226 message == WM_SYSCHAR || 15227 message == WM_COMMAND || 15228 message == WM_MENUCOMMAND) 15229 { 15230 struct recvd_message msg; 15231 15232 msg.hwnd = hwnd; 15233 msg.message = message; 15234 msg.flags = sent|wparam|lparam; 15235 msg.wParam = wp; 15236 msg.lParam = lp; 15237 msg.descr = "parent_menu_proc"; 15238 add_message(&msg); 15239 } 15240 15241 return DefWindowProcA(hwnd, message, wp, lp); 15242 } 15243 15244 static void set_menu_style(HMENU hmenu, DWORD style) 15245 { 15246 MENUINFO mi; 15247 BOOL ret; 15248 15249 mi.cbSize = sizeof(mi); 15250 mi.fMask = MIM_STYLE; 15251 mi.dwStyle = style; 15252 SetLastError(0xdeadbeef); 15253 ret = pSetMenuInfo(hmenu, &mi); 15254 ok(ret, "SetMenuInfo error %u\n", GetLastError()); 15255 } 15256 15257 static DWORD get_menu_style(HMENU hmenu) 15258 { 15259 MENUINFO mi; 15260 BOOL ret; 15261 15262 mi.cbSize = sizeof(mi); 15263 mi.fMask = MIM_STYLE; 15264 mi.dwStyle = 0; 15265 SetLastError(0xdeadbeef); 15266 ret = pGetMenuInfo(hmenu, &mi); 15267 ok(ret, "GetMenuInfo error %u\n", GetLastError()); 15268 15269 return mi.dwStyle; 15270 } 15271 15272 static void test_menu_messages(void) 15273 { 15274 MSG msg; 15275 WNDCLASSA cls; 15276 HMENU hmenu, hmenu_popup; 15277 HWND hwnd; 15278 DWORD style; 15279 15280 if (!pGetMenuInfo || !pSetMenuInfo) 15281 { 15282 win_skip("GetMenuInfo and/or SetMenuInfo are not available\n"); 15283 return; 15284 } 15285 cls.style = 0; 15286 cls.lpfnWndProc = parent_menu_proc; 15287 cls.cbClsExtra = 0; 15288 cls.cbWndExtra = 0; 15289 cls.hInstance = GetModuleHandleA(0); 15290 cls.hIcon = 0; 15291 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 15292 cls.hbrBackground = GetStockObject(WHITE_BRUSH); 15293 cls.lpszMenuName = NULL; 15294 cls.lpszClassName = "TestMenuClass"; 15295 UnregisterClassA(cls.lpszClassName, cls.hInstance); 15296 if (!RegisterClassA(&cls)) assert(0); 15297 15298 SetLastError(0xdeadbeef); 15299 hwnd = CreateWindowExA(0, "TestMenuClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 15300 100, 100, 200, 200, 0, 0, 0, NULL); 15301 ok(hwnd != 0, "LoadMenuA error %u\n", GetLastError()); 15302 15303 SetLastError(0xdeadbeef); 15304 hmenu = LoadMenuA(GetModuleHandleA(NULL), MAKEINTRESOURCEA(1)); 15305 ok(hmenu != 0, "LoadMenuA error %u\n", GetLastError()); 15306 15307 SetMenu(hwnd, hmenu); 15308 SetForegroundWindow( hwnd ); 15309 flush_events(); 15310 15311 set_menu_style(hmenu, MNS_NOTIFYBYPOS); 15312 style = get_menu_style(hmenu); 15313 ok(style == MNS_NOTIFYBYPOS, "expected MNS_NOTIFYBYPOS, got %u\n", style); 15314 15315 hmenu_popup = GetSubMenu(hmenu, 0); 15316 ok(hmenu_popup != 0, "GetSubMenu returned 0 for submenu 0\n"); 15317 style = get_menu_style(hmenu_popup); 15318 ok(style == 0, "expected 0, got %u\n", style); 15319 15320 hmenu_popup = GetSubMenu(hmenu_popup, 0); 15321 ok(hmenu_popup != 0, "GetSubMenu returned 0 for submenu 0\n"); 15322 style = get_menu_style(hmenu_popup); 15323 ok(style == 0, "expected 0, got %u\n", style); 15324 15325 /* Alt+E, Enter */ 15326 trace("testing a popup menu command\n"); 15327 flush_sequence(); 15328 keybd_event(VK_MENU, 0, 0, 0); 15329 keybd_event('E', 0, 0, 0); 15330 keybd_event('E', 0, KEYEVENTF_KEYUP, 0); 15331 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); 15332 keybd_event(VK_RETURN, 0, 0, 0); 15333 keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0); 15334 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 15335 { 15336 TranslateMessage(&msg); 15337 DispatchMessageA(&msg); 15338 } 15339 if (!sequence_cnt) /* we didn't get any message */ 15340 { 15341 skip( "queuing key events not supported\n" ); 15342 goto done; 15343 } 15344 /* win98 queues only a WM_KEYUP and doesn't start menu tracking */ 15345 if (sequence[0].message == WM_KEYUP && sequence[0].wParam == VK_MENU) 15346 { 15347 win_skip( "menu tracking through VK_MENU not supported\n" ); 15348 goto done; 15349 } 15350 ok_sequence(wm_popup_menu_1, "popup menu command", FALSE); 15351 15352 /* Alt+F, Right, Enter */ 15353 trace("testing submenu of a popup menu command\n"); 15354 flush_sequence(); 15355 keybd_event(VK_MENU, 0, 0, 0); 15356 keybd_event('F', 0, 0, 0); 15357 keybd_event('F', 0, KEYEVENTF_KEYUP, 0); 15358 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); 15359 keybd_event(VK_RIGHT, 0, 0, 0); 15360 keybd_event(VK_RIGHT, 0, KEYEVENTF_KEYUP, 0); 15361 keybd_event(VK_RETURN, 0, 0, 0); 15362 keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0); 15363 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 15364 { 15365 TranslateMessage(&msg); 15366 DispatchMessageA(&msg); 15367 } 15368 ok_sequence(wm_popup_menu_2, "submenu of a popup menu command", FALSE); 15369 15370 trace("testing single menu item command\n"); 15371 flush_sequence(); 15372 keybd_event(VK_MENU, 0, 0, 0); 15373 keybd_event('Q', 0, 0, 0); 15374 keybd_event('Q', 0, KEYEVENTF_KEYUP, 0); 15375 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); 15376 keybd_event(VK_ESCAPE, 0, 0, 0); 15377 keybd_event(VK_ESCAPE, 0, KEYEVENTF_KEYUP, 0); 15378 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 15379 { 15380 TranslateMessage(&msg); 15381 DispatchMessageA(&msg); 15382 } 15383 ok_sequence(wm_single_menu_item, "single menu item command", FALSE); 15384 15385 set_menu_style(hmenu, 0); 15386 style = get_menu_style(hmenu); 15387 ok(style == 0, "expected 0, got %u\n", style); 15388 15389 hmenu_popup = GetSubMenu(hmenu, 0); 15390 ok(hmenu_popup != 0, "GetSubMenu returned 0 for submenu 0\n"); 15391 set_menu_style(hmenu_popup, MNS_NOTIFYBYPOS); 15392 style = get_menu_style(hmenu_popup); 15393 ok(style == MNS_NOTIFYBYPOS, "expected MNS_NOTIFYBYPOS, got %u\n", style); 15394 15395 hmenu_popup = GetSubMenu(hmenu_popup, 0); 15396 ok(hmenu_popup != 0, "GetSubMenu returned 0 for submenu 0\n"); 15397 style = get_menu_style(hmenu_popup); 15398 ok(style == 0, "expected 0, got %u\n", style); 15399 15400 /* Alt+F, Right, Enter */ 15401 trace("testing submenu of a popup menu command\n"); 15402 flush_sequence(); 15403 keybd_event(VK_MENU, 0, 0, 0); 15404 keybd_event('F', 0, 0, 0); 15405 keybd_event('F', 0, KEYEVENTF_KEYUP, 0); 15406 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); 15407 keybd_event(VK_RIGHT, 0, 0, 0); 15408 keybd_event(VK_RIGHT, 0, KEYEVENTF_KEYUP, 0); 15409 keybd_event(VK_RETURN, 0, 0, 0); 15410 keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0); 15411 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 15412 { 15413 TranslateMessage(&msg); 15414 DispatchMessageA(&msg); 15415 } 15416 ok_sequence(wm_popup_menu_3, "submenu of a popup menu command", FALSE); 15417 15418 done: 15419 DestroyWindow(hwnd); 15420 DestroyMenu(hmenu); 15421 } 15422 15423 15424 static void test_paintingloop(void) 15425 { 15426 HWND hwnd; 15427 15428 paint_loop_done = FALSE; 15429 hwnd = CreateWindowExA(0x0,"PaintLoopWindowClass", 15430 "PaintLoopWindowClass",WS_OVERLAPPEDWINDOW, 15431 100, 100, 100, 100, 0, 0, 0, NULL ); 15432 ok(hwnd != 0, "PaintLoop window error %u\n", GetLastError()); 15433 ShowWindow(hwnd,SW_NORMAL); 15434 SetFocus(hwnd); 15435 15436 while (!paint_loop_done) 15437 { 15438 MSG msg; 15439 if (PeekMessageA(&msg, 0, 0, 0, 1)) 15440 { 15441 TranslateMessage(&msg); 15442 DispatchMessageA(&msg); 15443 } 15444 } 15445 DestroyWindow(hwnd); 15446 } 15447 15448 static const struct message NCRBUTTONDOWNSeq[] = 15449 { 15450 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, 15451 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, 15452 { WM_CAPTURECHANGED, sent }, 15453 { WM_CONTEXTMENU, sent, /*hwnd*/0, -1 }, 15454 { 0 } 15455 }; 15456 15457 static const struct message NCXBUTTONUPSeq1[] = 15458 { 15459 { WM_APPCOMMAND, sent|lparam, /*hwnd*/0, MAKELPARAM(0, FAPPCOMMAND_MOUSE | APPCOMMAND_BROWSER_BACKWARD) }, 15460 { 0 } 15461 }; 15462 15463 static const struct message NCXBUTTONUPSeq2[] = 15464 { 15465 { WM_APPCOMMAND, sent|lparam, /*hwnd*/0, MAKELPARAM(0, FAPPCOMMAND_MOUSE | APPCOMMAND_BROWSER_FORWARD) }, 15466 { 0 } 15467 }; 15468 15469 /* DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0) to minimized visible window */ 15470 static const struct message WmRestoreMinimizedOverlappedSeq[] = 15471 { 15472 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_RESTORE, 0 }, 15473 { HCBT_MINMAX, hook }, 15474 { WM_QUERYOPEN, sent }, 15475 { WM_GETTEXT, sent|optional }, 15476 { WM_NCACTIVATE, sent|optional }, 15477 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 15478 { WM_WINDOWPOSCHANGED, sent|optional }, 15479 { WM_WINDOWPOSCHANGING, sent|optional }, 15480 { WM_GETMINMAXINFO, sent|defwinproc }, 15481 { WM_NCCALCSIZE, sent|optional }, 15482 { WM_NCPAINT, sent|optional }, 15483 { WM_GETTEXT, sent|defwinproc|optional }, 15484 { WM_ERASEBKGND, sent|optional }, 15485 { WM_WINDOWPOSCHANGED, sent|optional }, 15486 { HCBT_ACTIVATE, hook }, 15487 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE }, 15488 { WM_ACTIVATEAPP, sent|wparam, TRUE }, 15489 { WM_NCACTIVATE, sent|wparam, TRUE }, 15490 { WM_GETTEXT, sent|defwinproc|optional }, 15491 { WM_ACTIVATE, sent|wparam, TRUE }, 15492 { HCBT_SETFOCUS, hook }, 15493 { WM_SETFOCUS, sent|defwinproc }, 15494 { WM_NCPAINT, sent }, 15495 { WM_GETTEXT, sent|defwinproc|optional }, 15496 { WM_ERASEBKGND, sent }, 15497 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_FRAMECHANGED|SWP_STATECHANGED }, 15498 { WM_MOVE, sent|defwinproc }, 15499 { WM_SIZE, sent|defwinproc }, 15500 { WM_NCCALCSIZE, sent|optional }, 15501 { WM_NCPAINT, sent|optional }, 15502 { WM_ERASEBKGND, sent|optional }, 15503 { WM_ACTIVATE, sent|wparam, TRUE }, 15504 { WM_SYNCPAINT, sent|optional }, 15505 { WM_PAINT, sent }, 15506 { 0 } 15507 }; 15508 15509 struct rbuttonup_thread_data 15510 { 15511 HWND hwnd; 15512 HANDLE wndproc_finished; 15513 }; 15514 15515 static DWORD CALLBACK post_rbuttonup_msg( void *arg ) 15516 { 15517 struct rbuttonup_thread_data *data = arg; 15518 DWORD ret; 15519 15520 ret = WaitForSingleObject( data->wndproc_finished, 500 ); 15521 todo_wine ok( ret == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", ret ); 15522 if( ret == WAIT_OBJECT_0 ) return 0; 15523 15524 PostMessageA( data->hwnd, WM_RBUTTONUP, 0, 0 ); 15525 return 0; 15526 } 15527 15528 static void test_defwinproc(void) 15529 { 15530 HWND hwnd; 15531 MSG msg; 15532 BOOL gotwmquit = FALSE; 15533 POINT pos; 15534 RECT rect; 15535 INT x, y; 15536 LRESULT res; 15537 struct rbuttonup_thread_data data; 15538 char buffA[64]; 15539 HANDLE thread; 15540 15541 hwnd = CreateWindowExA(0, "TestWindowClass", "test_defwndproc", 15542 WS_VISIBLE | WS_CAPTION | WS_OVERLAPPEDWINDOW, 0,0,500,100,0,0,0, NULL); 15543 assert(hwnd); 15544 flush_events(); 15545 15546 buffA[0] = 0; 15547 GetWindowTextA(hwnd, buffA, ARRAY_SIZE(buffA)); 15548 ok(!strcmp(buffA, "test_defwndproc"), "unexpected window text, %s\n", buffA); 15549 15550 /* Zero high word of the lParam */ 15551 res = DefWindowProcA(hwnd, WM_SETTEXT, 0, 0x1234); 15552 ok(res == 0, "WM_SETTEXT was expected to fail, %ld\n", res); 15553 15554 GetWindowTextA(hwnd, buffA, ARRAY_SIZE(buffA)); 15555 ok(!strcmp(buffA, "test_defwndproc"), "unexpected window text, %s\n", buffA); 15556 15557 res = DefWindowProcW(hwnd, WM_SETTEXT, 0, 0x1234); 15558 ok(res == 0, "WM_SETTEXT was expected to fail, %ld\n", res); 15559 15560 GetWindowTextA(hwnd, buffA, ARRAY_SIZE(buffA)); 15561 ok(!strcmp(buffA, "test_defwndproc"), "unexpected window text, %s\n", buffA); 15562 15563 ShowWindow(hwnd, SW_MINIMIZE); 15564 flush_events(); 15565 flush_sequence(); 15566 15567 DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0); 15568 flush_events(); 15569 ok_sequence(WmRestoreMinimizedOverlappedSeq, "DefWindowProcA(SC_RESTORE):overlapped", TRUE); 15570 flush_sequence(); 15571 15572 GetCursorPos(&pos); 15573 GetWindowRect(hwnd, &rect); 15574 x = (rect.left+rect.right) / 2; 15575 y = rect.top + GetSystemMetrics(SM_CYFRAME) + 1; 15576 SetCursorPos(x, y); 15577 flush_events(); 15578 res = DefWindowProcA( hwnd, WM_NCHITTEST, 0, MAKELPARAM(x, y)); 15579 ok(res == HTCAPTION, "WM_NCHITTEST returned %ld\n", res); 15580 15581 mouse_event( MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0 ); 15582 mouse_event( MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 ); 15583 flush_events(); 15584 15585 flush_sequence(); 15586 mouse_event( MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0 ); 15587 /* workaround for missing support for clicking on window frame */ 15588 data.hwnd = hwnd; 15589 data.wndproc_finished = CreateEventA( NULL, FALSE, FALSE, NULL ); 15590 thread = CreateThread( NULL, 0, post_rbuttonup_msg, (void*)&data, 0, NULL ); 15591 15592 DefWindowProcA( hwnd, WM_NCRBUTTONDOWN, HTCAPTION, MAKELPARAM(x, y)); 15593 ok_sequence(NCRBUTTONDOWNSeq, "WM_NCRBUTTONDOWN on caption", FALSE); 15594 15595 res = DefWindowProcA(hwnd, WM_NCXBUTTONUP, 0, MAKELPARAM(x, y)); 15596 ok(!res, "WM_NCXBUTTONUP returned %ld\n", res); 15597 ok_sequence(WmEmptySeq, "WM_NCXBUTTONUP without button", FALSE); 15598 15599 res = DefWindowProcA(hwnd, WM_NCXBUTTONUP, MAKEWPARAM(0, XBUTTON1), MAKELPARAM(x, y)); 15600 ok(!res, "WM_NCXBUTTONUP returned %ld\n", res); 15601 ok_sequence(NCXBUTTONUPSeq1, "WM_NCXBUTTONUP with XBUTTON1", FALSE); 15602 15603 res = DefWindowProcA(hwnd, WM_NCXBUTTONUP, MAKEWPARAM(0, XBUTTON2), MAKELPARAM(x, y)); 15604 ok(!res, "WM_NCXBUTTONUP returned %ld\n", res); 15605 ok_sequence(NCXBUTTONUPSeq2, "WM_NCXBUTTONUP with XBUTTON2", FALSE); 15606 15607 res = DefWindowProcA(hwnd, WM_NCXBUTTONUP, MAKEWPARAM(0, 3), MAKELPARAM(x, y)); 15608 ok(!res, "WM_NCXBUTTONUP returned %ld\n", res); 15609 ok_sequence(WmEmptySeq, "WM_NCXBUTTONUP with invalid button", FALSE); 15610 15611 SetEvent( data.wndproc_finished ); 15612 WaitForSingleObject( thread, 1000 ); 15613 CloseHandle( data.wndproc_finished ); 15614 CloseHandle( thread ); 15615 15616 SetCursorPos(pos.x, pos.y); 15617 15618 DefWindowProcA( hwnd, WM_ENDSESSION, 1, 0); 15619 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) { 15620 if( msg.message == WM_QUIT) gotwmquit = TRUE; 15621 DispatchMessageA( &msg ); 15622 } 15623 ok(!gotwmquit, "Unexpected WM_QUIT message!\n"); 15624 DestroyWindow( hwnd); 15625 } 15626 15627 static void test_desktop_winproc(void) 15628 { 15629 HINSTANCE instance = GetModuleHandleA(NULL); 15630 RECT rect, default_rect; 15631 WNDPROC desktop_proc; 15632 char buffer[256]; 15633 WNDCLASSA cls; 15634 LRESULT res; 15635 HWND hwnd; 15636 BOOL ret; 15637 15638 ret = GetClassInfoA(instance, (const CHAR *)MAKEINTATOM(32769), &cls); 15639 ok(ret, "Failed to get desktop class.\n"); 15640 desktop_proc = cls.lpfnWndProc; 15641 15642 memset(&cls, 0, sizeof(cls)); 15643 cls.lpfnWndProc = desktop_proc; 15644 cls.hInstance = instance; 15645 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 15646 cls.hbrBackground = GetStockObject(WHITE_BRUSH); 15647 cls.lpszClassName = "TestDesktopClass"; 15648 ret = !!RegisterClassA(&cls); 15649 ok(ret, "Failed to register class.\n"); 15650 15651 hwnd = CreateWindowExA(0, cls.lpszClassName, "test_desktop_wndproc", 15652 WS_VISIBLE | WS_CAPTION | WS_OVERLAPPEDWINDOW, 0, 0, 500, 100, 0, 0, 0, NULL); 15653 if (!hwnd) /* win2003 */ 15654 { 15655 skip("Failed to create window with desktop window procedure.\n"); 15656 goto out_unregister; 15657 } 15658 15659 memset(&cls, 0, sizeof(cls)); 15660 ret = GetClassInfoA(instance, "TestDesktopClass", &cls); 15661 ok(ret, "Failed to get class info.\n"); 15662 ok(cls.lpfnWndProc == desktop_proc, "Got %p, expected %p.\n", cls.lpfnWndProc, desktop_proc); 15663 15664 GetWindowTextA(hwnd, buffer, ARRAY_SIZE(buffer)); 15665 todo_wine ok(!strcmp(buffer, "test_desktop_wndproc"), "Got unexpected window text: %s.\n", buffer); 15666 15667 res = CallWindowProcA(desktop_proc, hwnd, WM_SETTEXT, 0, (LPARAM)"test"); 15668 ok(res == TRUE, "Failed to set text, %ld.\n", res); 15669 GetWindowTextA(hwnd, buffer, ARRAY_SIZE(buffer)); 15670 ok(!strcmp(buffer, "test"), "Got unexpected window text: %s.\n", buffer); 15671 15672 SetRect(&default_rect, 0, 0, 100, 100); 15673 res = DefWindowProcW(hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&default_rect); 15674 ok(!res, "Got unexpected result %ld.\n", res); 15675 15676 SetRect(&rect, 0, 0, 100, 100); 15677 res = CallWindowProcA(desktop_proc, hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&rect); 15678 ok(!res, "Got unexpected result %ld.\n", res); 15679 todo_wine ok(EqualRect(&rect, &default_rect), "rect Got %s, expected %s.\n", 15680 wine_dbgstr_rect(&rect), wine_dbgstr_rect(&default_rect)); 15681 15682 DestroyWindow(hwnd); 15683 15684 out_unregister: 15685 UnregisterClassA("TestDesktopClass", instance); 15686 } 15687 15688 #define clear_clipboard(hwnd) clear_clipboard_(__LINE__, (hwnd)) 15689 static void clear_clipboard_(int line, HWND hWnd) 15690 { 15691 BOOL succ; 15692 succ = OpenClipboard(hWnd); 15693 ok_(__FILE__, line)(succ, "OpenClipboard failed, err=%u\n", GetLastError()); 15694 succ = EmptyClipboard(); 15695 ok_(__FILE__, line)(succ, "EmptyClipboard failed, err=%u\n", GetLastError()); 15696 succ = CloseClipboard(); 15697 ok_(__FILE__, line)(succ, "CloseClipboard failed, err=%u\n", GetLastError()); 15698 } 15699 15700 #define expect_HWND(expected, got) expect_HWND_(__LINE__, (expected), (got)) 15701 static void expect_HWND_(int line, HWND expected, HWND got) 15702 { 15703 ok_(__FILE__, line)(got==expected, "Expected %p, got %p\n", expected, got); 15704 } 15705 15706 static WNDPROC pOldViewerProc; 15707 15708 static LRESULT CALLBACK recursive_viewer_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 15709 { 15710 static BOOL recursion_guard; 15711 15712 if (message == WM_DRAWCLIPBOARD && !recursion_guard) 15713 { 15714 recursion_guard = TRUE; 15715 clear_clipboard(hWnd); 15716 recursion_guard = FALSE; 15717 } 15718 return CallWindowProcA(pOldViewerProc, hWnd, message, wParam, lParam); 15719 } 15720 15721 static void test_clipboard_viewers(void) 15722 { 15723 static struct message wm_change_cb_chain[] = 15724 { 15725 { WM_CHANGECBCHAIN, sent|wparam|lparam, 0, 0 }, 15726 { 0 } 15727 }; 15728 static const struct message wm_clipboard_destroyed[] = 15729 { 15730 { WM_DESTROYCLIPBOARD, sent|wparam|lparam, 0, 0 }, 15731 { 0 } 15732 }; 15733 static struct message wm_clipboard_changed[] = 15734 { 15735 { WM_DRAWCLIPBOARD, sent|wparam|lparam, 0, 0 }, 15736 { 0 } 15737 }; 15738 static struct message wm_clipboard_changed_and_owned[] = 15739 { 15740 { WM_DESTROYCLIPBOARD, sent|wparam|lparam, 0, 0 }, 15741 { WM_DRAWCLIPBOARD, sent|wparam|lparam, 0, 0 }, 15742 { 0 } 15743 }; 15744 15745 HINSTANCE hInst = GetModuleHandleA(NULL); 15746 HWND hWnd1, hWnd2, hWnd3; 15747 HWND hOrigViewer; 15748 HWND hRet; 15749 15750 hWnd1 = CreateWindowExA(0, "TestWindowClass", "Clipboard viewer test wnd 1", 15751 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX, 15752 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 15753 GetDesktopWindow(), NULL, hInst, NULL); 15754 hWnd2 = CreateWindowExA(0, "SimpleWindowClass", "Clipboard viewer test wnd 2", 15755 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX, 15756 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 15757 GetDesktopWindow(), NULL, hInst, NULL); 15758 hWnd3 = CreateWindowExA(0, "SimpleWindowClass", "Clipboard viewer test wnd 3", 15759 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX, 15760 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 15761 GetDesktopWindow(), NULL, hInst, NULL); 15762 trace("clipbd viewers: hWnd1=%p, hWnd2=%p, hWnd3=%p\n", hWnd1, hWnd2, hWnd3); 15763 assert(hWnd1 && hWnd2 && hWnd3); 15764 15765 CountClipboardFormats(); /* Ensure that we do not have an X11 update to the clipboard */ 15766 flush_sequence(); 15767 15768 /* Test getting the clipboard viewer and setting the viewer to NULL. */ 15769 hOrigViewer = GetClipboardViewer(); 15770 hRet = SetClipboardViewer(NULL); 15771 ok_sequence(WmEmptySeq, "set viewer to NULL", FALSE); 15772 expect_HWND(hOrigViewer, hRet); 15773 expect_HWND(NULL, GetClipboardViewer()); 15774 15775 /* Test registering hWnd1 as a viewer. */ 15776 hRet = SetClipboardViewer(hWnd1); 15777 wm_clipboard_changed[0].wParam = (WPARAM) GetClipboardOwner(); 15778 ok_sequence(wm_clipboard_changed, "set viewer NULL->1", FALSE); 15779 expect_HWND(NULL, hRet); 15780 expect_HWND(hWnd1, GetClipboardViewer()); 15781 15782 /* Test that changing the clipboard actually refreshes the registered viewer. */ 15783 clear_clipboard(hWnd1); 15784 wm_clipboard_changed[0].wParam = (WPARAM) GetClipboardOwner(); 15785 ok_sequence(wm_clipboard_changed, "clear clipbd (viewer=owner=1)", FALSE); 15786 15787 /* Again, but with different owner. */ 15788 clear_clipboard(hWnd2); 15789 wm_clipboard_changed_and_owned[1].wParam = (WPARAM) GetClipboardOwner(); 15790 ok_sequence(wm_clipboard_changed_and_owned, "clear clipbd (viewer=1, owner=2)", FALSE); 15791 15792 /* Test re-registering same window. */ 15793 hRet = SetClipboardViewer(hWnd1); 15794 wm_clipboard_changed[0].wParam = (WPARAM) GetClipboardOwner(); 15795 ok_sequence(wm_clipboard_changed, "set viewer 1->1", FALSE); 15796 expect_HWND(hWnd1, hRet); 15797 expect_HWND(hWnd1, GetClipboardViewer()); 15798 15799 /* Test ChangeClipboardChain. */ 15800 ChangeClipboardChain(hWnd2, hWnd3); 15801 wm_change_cb_chain[0].wParam = (WPARAM) hWnd2; 15802 wm_change_cb_chain[0].lParam = (LPARAM) hWnd3; 15803 ok_sequence(wm_change_cb_chain, "change chain (viewer=1, remove=2, next=3)", FALSE); 15804 expect_HWND(hWnd1, GetClipboardViewer()); 15805 15806 ChangeClipboardChain(hWnd2, NULL); 15807 wm_change_cb_chain[0].wParam = (WPARAM) hWnd2; 15808 wm_change_cb_chain[0].lParam = 0; 15809 ok_sequence(wm_change_cb_chain, "change chain (viewer=1, remove=2, next=NULL)", FALSE); 15810 expect_HWND(hWnd1, GetClipboardViewer()); 15811 15812 ChangeClipboardChain(NULL, hWnd2); 15813 ok_sequence(WmEmptySeq, "change chain (viewer=1, remove=NULL, next=2)", FALSE); 15814 expect_HWND(hWnd1, GetClipboardViewer()); 15815 15816 /* Actually change clipboard viewer with ChangeClipboardChain. */ 15817 ChangeClipboardChain(hWnd1, hWnd2); 15818 ok_sequence(WmEmptySeq, "change chain (viewer=remove=1, next=2)", FALSE); 15819 expect_HWND(hWnd2, GetClipboardViewer()); 15820 15821 /* Test that no refresh messages are sent when viewer has unregistered. */ 15822 clear_clipboard(hWnd2); 15823 ok_sequence(WmEmptySeq, "clear clipd (viewer=2, owner=1)", FALSE); 15824 15825 /* Register hWnd1 again. */ 15826 ChangeClipboardChain(hWnd2, hWnd1); 15827 ok_sequence(WmEmptySeq, "change chain (viewer=remove=2, next=1)", FALSE); 15828 expect_HWND(hWnd1, GetClipboardViewer()); 15829 15830 /* Subclass hWnd1 so that when it receives a WM_DRAWCLIPBOARD message, it 15831 * changes the clipboard. When this happens, the system shouldn't send 15832 * another WM_DRAWCLIPBOARD (as this could cause an infinite loop). 15833 */ 15834 pOldViewerProc = (WNDPROC) SetWindowLongPtrA(hWnd1, GWLP_WNDPROC, (LONG_PTR) recursive_viewer_proc); 15835 clear_clipboard(hWnd2); 15836 /* The clipboard owner is changed in recursive_viewer_proc: */ 15837 wm_clipboard_changed[0].wParam = (WPARAM) hWnd2; 15838 ok_sequence(wm_clipboard_changed, "recursive clear clipbd (viewer=1, owner=2)", TRUE); 15839 15840 /* Test unregistering. */ 15841 ChangeClipboardChain(hWnd1, NULL); 15842 ok_sequence(WmEmptySeq, "change chain (viewer=remove=1, next=NULL)", FALSE); 15843 expect_HWND(NULL, GetClipboardViewer()); 15844 15845 clear_clipboard(hWnd1); 15846 ok_sequence(wm_clipboard_destroyed, "clear clipbd (no viewer, owner=1)", FALSE); 15847 15848 DestroyWindow(hWnd1); 15849 DestroyWindow(hWnd2); 15850 DestroyWindow(hWnd3); 15851 SetClipboardViewer(hOrigViewer); 15852 } 15853 15854 static void test_PostMessage(void) 15855 { 15856 static const struct 15857 { 15858 HWND hwnd; 15859 BOOL ret; 15860 } data[] = 15861 { 15862 { HWND_TOP /* 0 */, TRUE }, 15863 { HWND_BROADCAST, TRUE }, 15864 { HWND_BOTTOM, TRUE }, 15865 { HWND_TOPMOST, TRUE }, 15866 { HWND_NOTOPMOST, FALSE }, 15867 { HWND_MESSAGE, FALSE }, 15868 { (HWND)0xdeadbeef, FALSE } 15869 }; 15870 int i; 15871 HWND hwnd; 15872 BOOL ret; 15873 MSG msg; 15874 static const WCHAR staticW[] = {'s','t','a','t','i','c',0}; 15875 15876 SetLastError(0xdeadbeef); 15877 hwnd = CreateWindowExW(0, staticW, NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL); 15878 if (!hwnd && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) 15879 { 15880 win_skip("Skipping some PostMessage tests on Win9x/WinMe\n"); 15881 return; 15882 } 15883 assert(hwnd); 15884 15885 flush_events(); 15886 15887 PostMessageA(hwnd, WM_USER+1, 0x1234, 0x5678); 15888 PostMessageA(0, WM_USER+2, 0x5678, 0x1234); 15889 15890 for (i = 0; i < ARRAY_SIZE(data); i++) 15891 { 15892 memset(&msg, 0xab, sizeof(msg)); 15893 ret = PeekMessageA(&msg, data[i].hwnd, 0, 0, PM_NOREMOVE); 15894 ok(ret == data[i].ret, "%d: hwnd %p expected %d, got %d\n", i, data[i].hwnd, data[i].ret, ret); 15895 if (data[i].ret) 15896 { 15897 if (data[i].hwnd) 15898 ok(ret && msg.hwnd == 0 && msg.message == WM_USER+2 && 15899 msg.wParam == 0x5678 && msg.lParam == 0x1234, 15900 "%d: got ret %d hwnd %p msg %04x wParam %08lx lParam %08lx instead of TRUE/0/WM_USER+2/0x5678/0x1234\n", 15901 i, ret, msg.hwnd, msg.message, msg.wParam, msg.lParam); 15902 else 15903 ok(ret && msg.hwnd == hwnd && msg.message == WM_USER+1 && 15904 msg.wParam == 0x1234 && msg.lParam == 0x5678, 15905 "%d: got ret %d hwnd %p msg %04x wParam %08lx lParam %08lx instead of TRUE/%p/WM_USER+1/0x1234/0x5678\n", 15906 i, ret, msg.hwnd, msg.message, msg.wParam, msg.lParam, msg.hwnd); 15907 } 15908 } 15909 15910 DestroyWindow(hwnd); 15911 flush_events(); 15912 } 15913 15914 static LPARAM g_broadcast_lparam; 15915 static LRESULT WINAPI broadcast_test_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 15916 { 15917 WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA); 15918 15919 if (wParam == 0xbaadbeef) 15920 g_broadcast_lparam = wParam; 15921 else 15922 g_broadcast_lparam = 0; 15923 15924 return CallWindowProcA(oldproc, hwnd, message, wParam, lParam); 15925 } 15926 15927 static void test_broadcast(void) 15928 { 15929 static const UINT messages[] = 15930 { 15931 WM_USER-1, 15932 WM_USER, 15933 WM_USER+1, 15934 0xc000-1, 15935 0xc000, /* lowest possible atom returned by RegisterWindowMessage */ 15936 0xffff, 15937 }; 15938 WNDPROC oldproc; 15939 unsigned int i; 15940 HWND hwnd; 15941 15942 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0, 0, 0, 0, 0, 0, 0, NULL); 15943 ok(hwnd != NULL, "got %p\n", hwnd); 15944 15945 oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)broadcast_test_proc); 15946 SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc); 15947 15948 for (i = 0; i < ARRAY_SIZE(messages); i++) 15949 { 15950 BOOL ret; 15951 MSG msg; 15952 15953 flush_events(); 15954 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 15955 ; 15956 15957 /* post, broadcast */ 15958 ret = PostMessageA(HWND_BROADCAST, messages[i], 0, 0); 15959 ok(ret, "%d: got %d, error %d\n", i, ret, GetLastError()); 15960 15961 memset(&msg, 0xab, sizeof(msg)); 15962 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); 15963 if (messages[i] < WM_USER || messages[i] >= 0xc000) 15964 { 15965 ok(ret, "%d: message %04x, got %d, error %d\n", i, messages[i], ret, GetLastError()); 15966 ok(msg.hwnd == hwnd, "%d: got %p\n", i, msg.hwnd); 15967 } 15968 else 15969 { 15970 ok(!ret, "%d: message %04x, got %d, error %d\n", i, messages[i], ret, GetLastError()); 15971 } 15972 15973 /* post, topmost */ 15974 ret = PostMessageA(HWND_TOPMOST, messages[i], 0, 0); 15975 ok(ret, "%d: got %d, error %d\n", i, ret, GetLastError()); 15976 15977 memset(&msg, 0xab, sizeof(msg)); 15978 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); 15979 if (messages[i] < WM_USER || messages[i] >= 0xc000) 15980 { 15981 ok(ret, "%d: message %04x, got %d, error %d\n", i, messages[i], ret, GetLastError()); 15982 ok(msg.hwnd == hwnd, "%d: got %p\n", i, msg.hwnd); 15983 } 15984 else 15985 { 15986 ok(!ret, "%d: got %d, error %d\n", i, ret, GetLastError()); 15987 } 15988 15989 /* send, broadcast */ 15990 g_broadcast_lparam = 0xdead; 15991 ret = SendMessageTimeoutA(HWND_BROADCAST, messages[i], 0xbaadbeef, 0, SMTO_NORMAL, 2000, NULL); 15992 if (!ret && GetLastError() == ERROR_TIMEOUT) 15993 win_skip("broadcasting test %d, timeout\n", i); 15994 else 15995 { 15996 if (messages[i] < WM_USER || messages[i] >= 0xc000) 15997 { 15998 ok(g_broadcast_lparam == 0xbaadbeef, "%d: message %04x, got %#lx, error %d\n", i, messages[i], 15999 g_broadcast_lparam, GetLastError()); 16000 } 16001 else 16002 { 16003 ok(g_broadcast_lparam == 0xdead, "%d: message %04x, got %#lx, error %d\n", i, messages[i], 16004 g_broadcast_lparam, GetLastError()); 16005 } 16006 } 16007 16008 /* send, topmost */ 16009 g_broadcast_lparam = 0xdead; 16010 ret = SendMessageTimeoutA(HWND_TOPMOST, messages[i], 0xbaadbeef, 0, SMTO_NORMAL, 2000, NULL); 16011 if (!ret && GetLastError() == ERROR_TIMEOUT) 16012 win_skip("broadcasting test %d, timeout\n", i); 16013 else 16014 { 16015 if (messages[i] < WM_USER || messages[i] >= 0xc000) 16016 { 16017 ok(g_broadcast_lparam == 0xbaadbeef, "%d: message %04x, got %#lx, error %d\n", i, messages[i], 16018 g_broadcast_lparam, GetLastError()); 16019 } 16020 else 16021 { 16022 ok(g_broadcast_lparam == 0xdead, "%d: message %04x, got %#lx, error %d\n", i, messages[i], 16023 g_broadcast_lparam, GetLastError()); 16024 } 16025 } 16026 } 16027 16028 DestroyWindow(hwnd); 16029 } 16030 16031 static const struct 16032 { 16033 DWORD exp, broken; 16034 BOOL todo; 16035 } wait_idle_expect[] = 16036 { 16037 /* 0 */ { WAIT_TIMEOUT, WAIT_TIMEOUT, FALSE }, 16038 { WAIT_TIMEOUT, 0, FALSE }, 16039 { WAIT_TIMEOUT, 0, FALSE }, 16040 { WAIT_TIMEOUT, WAIT_TIMEOUT, FALSE }, 16041 { WAIT_TIMEOUT, WAIT_TIMEOUT, FALSE }, 16042 /* 5 */ { WAIT_TIMEOUT, 0, FALSE }, 16043 { WAIT_TIMEOUT, 0, FALSE }, 16044 { WAIT_TIMEOUT, WAIT_TIMEOUT, FALSE }, 16045 { 0, 0, FALSE }, 16046 { 0, 0, FALSE }, 16047 /* 10 */ { 0, 0, FALSE }, 16048 { 0, 0, FALSE }, 16049 { 0, WAIT_TIMEOUT, FALSE }, 16050 { 0, 0, FALSE }, 16051 { 0, 0, FALSE }, 16052 /* 15 */ { 0, 0, FALSE }, 16053 { WAIT_TIMEOUT, 0, FALSE }, 16054 { WAIT_TIMEOUT, 0, FALSE }, 16055 { WAIT_TIMEOUT, 0, FALSE }, 16056 { WAIT_TIMEOUT, 0, FALSE }, 16057 /* 20 */ { WAIT_TIMEOUT, 0, FALSE }, 16058 }; 16059 16060 static DWORD CALLBACK do_wait_idle_child_thread( void *arg ) 16061 { 16062 MSG msg; 16063 16064 PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ); 16065 Sleep( 200 ); 16066 MsgWaitForMultipleObjects( 0, NULL, FALSE, 100, QS_ALLINPUT ); 16067 return 0; 16068 } 16069 16070 static void do_wait_idle_child( int arg ) 16071 { 16072 WNDCLASSA cls; 16073 MSG msg; 16074 HWND hwnd = 0; 16075 HANDLE thread; 16076 DWORD id; 16077 HANDLE start_event = OpenEventA( EVENT_ALL_ACCESS, FALSE, "test_WaitForInputIdle_start" ); 16078 HANDLE end_event = OpenEventA( EVENT_ALL_ACCESS, FALSE, "test_WaitForInputIdle_end" ); 16079 16080 memset( &cls, 0, sizeof(cls) ); 16081 cls.lpfnWndProc = DefWindowProcA; 16082 cls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); 16083 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 16084 cls.lpszClassName = "TestClass"; 16085 RegisterClassA( &cls ); 16086 16087 PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ); /* create the msg queue */ 16088 16089 ok( start_event != 0, "failed to create start event, error %u\n", GetLastError() ); 16090 ok( end_event != 0, "failed to create end event, error %u\n", GetLastError() ); 16091 16092 switch (arg) 16093 { 16094 case 0: 16095 SetEvent( start_event ); 16096 break; 16097 case 1: 16098 SetEvent( start_event ); 16099 Sleep( 200 ); 16100 PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ); 16101 break; 16102 case 2: 16103 SetEvent( start_event ); 16104 Sleep( 200 ); 16105 PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ); 16106 PostThreadMessageA( GetCurrentThreadId(), WM_COMMAND, 0x1234, 0xabcd ); 16107 PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ); 16108 break; 16109 case 3: 16110 SetEvent( start_event ); 16111 Sleep( 200 ); 16112 SendMessageA( HWND_BROADCAST, WM_WININICHANGE, 0, 0 ); 16113 break; 16114 case 4: 16115 SetEvent( start_event ); 16116 Sleep( 200 ); 16117 hwnd = CreateWindowExA(0, "TestClass", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL); 16118 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE|PM_NOYIELD )) DispatchMessageA( &msg ); 16119 break; 16120 case 5: 16121 SetEvent( start_event ); 16122 Sleep( 200 ); 16123 hwnd = CreateWindowExA(0, "TestClass", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL); 16124 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 16125 break; 16126 case 6: 16127 SetEvent( start_event ); 16128 Sleep( 200 ); 16129 hwnd = CreateWindowExA(0, "TestClass", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL); 16130 while (PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE )) 16131 { 16132 GetMessageA( &msg, 0, 0, 0 ); 16133 DispatchMessageA( &msg ); 16134 } 16135 break; 16136 case 7: 16137 SetEvent( start_event ); 16138 Sleep( 200 ); 16139 hwnd = CreateWindowExA(0, "TestClass", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL); 16140 SetTimer( hwnd, 3, 1, NULL ); 16141 Sleep( 200 ); 16142 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE|PM_NOYIELD )) DispatchMessageA( &msg ); 16143 break; 16144 case 8: 16145 SetEvent( start_event ); 16146 Sleep( 200 ); 16147 PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ); 16148 MsgWaitForMultipleObjects( 0, NULL, FALSE, 100, QS_ALLINPUT ); 16149 break; 16150 case 9: 16151 SetEvent( start_event ); 16152 Sleep( 200 ); 16153 hwnd = CreateWindowExA(0, "TestClass", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL); 16154 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 16155 for (;;) GetMessageA( &msg, 0, 0, 0 ); 16156 break; 16157 case 10: 16158 SetEvent( start_event ); 16159 Sleep( 200 ); 16160 hwnd = CreateWindowExA(0, "TestClass", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL); 16161 SetTimer( hwnd, 3, 1, NULL ); 16162 Sleep( 200 ); 16163 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 16164 break; 16165 case 11: 16166 SetEvent( start_event ); 16167 Sleep( 200 ); 16168 return; /* exiting the process makes WaitForInputIdle return success too */ 16169 case 12: 16170 PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ); 16171 Sleep( 200 ); 16172 MsgWaitForMultipleObjects( 0, NULL, FALSE, 100, QS_ALLINPUT ); 16173 SetEvent( start_event ); 16174 break; 16175 case 13: 16176 SetEvent( start_event ); 16177 PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ); 16178 Sleep( 200 ); 16179 thread = CreateThread( NULL, 0, do_wait_idle_child_thread, NULL, 0, &id ); 16180 WaitForSingleObject( thread, 10000 ); 16181 CloseHandle( thread ); 16182 break; 16183 case 14: 16184 SetEvent( start_event ); 16185 Sleep( 200 ); 16186 PeekMessageA( &msg, HWND_TOPMOST, 0, 0, PM_NOREMOVE ); 16187 break; 16188 case 15: 16189 SetEvent( start_event ); 16190 Sleep( 200 ); 16191 PeekMessageA( &msg, HWND_BROADCAST, 0, 0, PM_NOREMOVE ); 16192 break; 16193 case 16: 16194 SetEvent( start_event ); 16195 Sleep( 200 ); 16196 PeekMessageA( &msg, HWND_BOTTOM, 0, 0, PM_NOREMOVE ); 16197 break; 16198 case 17: 16199 SetEvent( start_event ); 16200 Sleep( 200 ); 16201 PeekMessageA( &msg, (HWND)0xdeadbeef, 0, 0, PM_NOREMOVE ); 16202 break; 16203 case 18: 16204 SetEvent( start_event ); 16205 Sleep( 200 ); 16206 PeekMessageA( &msg, HWND_NOTOPMOST, 0, 0, PM_NOREMOVE ); 16207 break; 16208 case 19: 16209 SetEvent( start_event ); 16210 Sleep( 200 ); 16211 PeekMessageA( &msg, HWND_MESSAGE, 0, 0, PM_NOREMOVE ); 16212 break; 16213 case 20: 16214 SetEvent( start_event ); 16215 Sleep( 200 ); 16216 PeekMessageA( &msg, GetDesktopWindow(), 0, 0, PM_NOREMOVE ); 16217 break; 16218 } 16219 WaitForSingleObject( end_event, 2000 ); 16220 CloseHandle( start_event ); 16221 CloseHandle( end_event ); 16222 if (hwnd) DestroyWindow( hwnd ); 16223 } 16224 16225 static LRESULT CALLBACK wait_idle_proc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ) 16226 { 16227 if (msg == WM_WININICHANGE) Sleep( 200 ); /* make sure the child waits */ 16228 return DefWindowProcA( hwnd, msg, wp, lp ); 16229 } 16230 16231 static DWORD CALLBACK wait_idle_thread( void *arg ) 16232 { 16233 WNDCLASSA cls; 16234 MSG msg; 16235 HWND hwnd; 16236 16237 memset( &cls, 0, sizeof(cls) ); 16238 cls.lpfnWndProc = wait_idle_proc; 16239 cls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); 16240 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 16241 cls.lpszClassName = "TestClass"; 16242 RegisterClassA( &cls ); 16243 16244 hwnd = CreateWindowExA(0, "TestClass", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL); 16245 while (GetMessageA( &msg, 0, 0, 0 )) DispatchMessageA( &msg ); 16246 DestroyWindow(hwnd); 16247 return 0; 16248 } 16249 16250 static void test_WaitForInputIdle( char *argv0 ) 16251 { 16252 char path[MAX_PATH]; 16253 PROCESS_INFORMATION pi; 16254 STARTUPINFOA startup; 16255 BOOL ret; 16256 HANDLE start_event, end_event, thread; 16257 unsigned int i; 16258 DWORD id; 16259 const IMAGE_DOS_HEADER *dos = (const IMAGE_DOS_HEADER *)GetModuleHandleA(0); 16260 const IMAGE_NT_HEADERS *nt = (const IMAGE_NT_HEADERS *)((const char *)dos + dos->e_lfanew); 16261 BOOL console_app = (nt->OptionalHeader.Subsystem != IMAGE_SUBSYSTEM_WINDOWS_GUI); 16262 16263 if (console_app) /* build the test with -mwindows for better coverage */ 16264 trace( "not built as a GUI app, WaitForInputIdle may not be fully tested\n" ); 16265 16266 start_event = CreateEventA(NULL, 0, 0, "test_WaitForInputIdle_start"); 16267 end_event = CreateEventA(NULL, 0, 0, "test_WaitForInputIdle_end"); 16268 ok(start_event != 0, "failed to create start event, error %u\n", GetLastError()); 16269 ok(end_event != 0, "failed to create end event, error %u\n", GetLastError()); 16270 16271 memset( &startup, 0, sizeof(startup) ); 16272 startup.cb = sizeof(startup); 16273 startup.dwFlags = STARTF_USESHOWWINDOW; 16274 startup.wShowWindow = SW_SHOWNORMAL; 16275 16276 thread = CreateThread( NULL, 0, wait_idle_thread, NULL, 0, &id ); 16277 16278 for (i = 0; i < ARRAY_SIZE(wait_idle_expect); i++) 16279 { 16280 ResetEvent( start_event ); 16281 ResetEvent( end_event ); 16282 #ifdef __REACTOS__ 16283 sprintf( path, "%s msg_queue %u", argv0, i ); 16284 #else 16285 sprintf( path, "%s msg %u", argv0, i ); 16286 #endif 16287 ret = CreateProcessA( NULL, path, NULL, NULL, TRUE, 0, NULL, NULL, &startup, &pi ); 16288 ok( ret, "CreateProcess '%s' failed err %u.\n", path, GetLastError() ); 16289 if (ret) 16290 { 16291 ret = WaitForSingleObject( start_event, 5000 ); 16292 ok( ret == WAIT_OBJECT_0, "%u: WaitForSingleObject failed\n", i ); 16293 if (ret == WAIT_OBJECT_0) 16294 { 16295 ret = WaitForInputIdle( pi.hProcess, 1000 ); 16296 if (ret == WAIT_FAILED) 16297 ok( console_app || 16298 ret == wait_idle_expect[i].exp || 16299 broken(ret == wait_idle_expect[i].broken), 16300 "%u: WaitForInputIdle error %08x expected %08x\n", 16301 i, ret, wait_idle_expect[i].exp ); 16302 else todo_wine_if (wait_idle_expect[i].todo) 16303 ok( ret == wait_idle_expect[i].exp || broken(ret == wait_idle_expect[i].broken), 16304 "%u: WaitForInputIdle error %08x expected %08x\n", 16305 i, ret, wait_idle_expect[i].exp ); 16306 SetEvent( end_event ); 16307 WaitForSingleObject( pi.hProcess, 1000 ); /* give it a chance to exit on its own */ 16308 } 16309 TerminateProcess( pi.hProcess, 0 ); /* just in case */ 16310 winetest_wait_child_process( pi.hProcess ); 16311 ret = WaitForInputIdle( pi.hProcess, 100 ); 16312 ok( ret == WAIT_FAILED, "%u: WaitForInputIdle after exit error %08x\n", i, ret ); 16313 CloseHandle( pi.hProcess ); 16314 CloseHandle( pi.hThread ); 16315 } 16316 } 16317 CloseHandle( start_event ); 16318 PostThreadMessageA( id, WM_QUIT, 0, 0 ); 16319 WaitForSingleObject( thread, 10000 ); 16320 CloseHandle( thread ); 16321 } 16322 16323 static const struct message WmSetParentSeq_1[] = { 16324 { WM_SHOWWINDOW, sent|wparam, 0 }, 16325 { EVENT_OBJECT_PARENTCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 16326 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE }, 16327 { WM_CHILDACTIVATE, sent }, 16328 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOREDRAW|SWP_NOCLIENTSIZE }, 16329 { WM_MOVE, sent|defwinproc|wparam, 0 }, 16330 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 16331 { WM_SHOWWINDOW, sent|wparam, 1 }, 16332 { 0 } 16333 }; 16334 16335 static const struct message WmSetParentSeq_2[] = { 16336 { WM_SHOWWINDOW, sent|wparam, 0 }, 16337 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 16338 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 16339 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 16340 { HCBT_SETFOCUS, hook|optional }, 16341 { WM_NCACTIVATE, sent|wparam|optional, 0 }, 16342 { WM_ACTIVATE, sent|wparam|optional, 0 }, 16343 { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, 16344 { WM_KILLFOCUS, sent|wparam, 0 }, 16345 { EVENT_OBJECT_PARENTCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 16346 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE }, 16347 { HCBT_ACTIVATE, hook|optional }, 16348 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 16349 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 16350 { WM_NCACTIVATE, sent|wparam|optional, 1 }, 16351 { WM_ACTIVATE, sent|wparam|optional, 1 }, 16352 { HCBT_SETFOCUS, hook|optional }, 16353 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 16354 { WM_SETFOCUS, sent|optional|defwinproc }, 16355 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOREDRAW|SWP_NOSIZE|SWP_NOCLIENTSIZE }, 16356 { WM_MOVE, sent|defwinproc|wparam, 0 }, 16357 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 16358 { WM_SHOWWINDOW, sent|wparam, 1 }, 16359 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 16360 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 16361 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 16362 { 0 } 16363 }; 16364 16365 16366 static void test_SetParent(void) 16367 { 16368 HWND parent1, parent2, child, popup; 16369 RECT rc, rc_old; 16370 16371 parent1 = CreateWindowExA(0, "TestParentClass", NULL, WS_OVERLAPPEDWINDOW, 16372 100, 100, 200, 200, 0, 0, 0, NULL); 16373 ok(parent1 != 0, "Failed to create parent1 window\n"); 16374 16375 parent2 = CreateWindowExA(0, "TestParentClass", NULL, WS_OVERLAPPEDWINDOW, 16376 400, 100, 200, 200, 0, 0, 0, NULL); 16377 ok(parent2 != 0, "Failed to create parent2 window\n"); 16378 16379 /* WS_CHILD window */ 16380 child = CreateWindowExA(0, "TestWindowClass", NULL, WS_CHILD | WS_VISIBLE, 16381 10, 10, 150, 150, parent1, 0, 0, NULL); 16382 ok(child != 0, "Failed to create child window\n"); 16383 16384 GetWindowRect(parent1, &rc); 16385 trace("parent1 %s\n", wine_dbgstr_rect(&rc)); 16386 GetWindowRect(child, &rc_old); 16387 MapWindowPoints(0, parent1, (POINT *)&rc_old, 2); 16388 trace("child %s\n", wine_dbgstr_rect(&rc_old)); 16389 16390 flush_sequence(); 16391 16392 SetParent(child, parent2); 16393 flush_events(); 16394 ok_sequence(WmSetParentSeq_1, "SetParent() visible WS_CHILD", FALSE); 16395 16396 ok(GetWindowLongA(child, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 16397 ok(!IsWindowVisible(child), "IsWindowVisible() should return FALSE\n"); 16398 16399 GetWindowRect(parent2, &rc); 16400 trace("parent2 %s\n", wine_dbgstr_rect(&rc)); 16401 GetWindowRect(child, &rc); 16402 MapWindowPoints(0, parent2, (POINT *)&rc, 2); 16403 trace("child %s\n", wine_dbgstr_rect(&rc)); 16404 16405 ok(EqualRect(&rc_old, &rc), "rects do not match %s / %s\n", wine_dbgstr_rect(&rc_old), 16406 wine_dbgstr_rect(&rc)); 16407 16408 /* WS_POPUP window */ 16409 popup = CreateWindowExA(0, "TestWindowClass", NULL, WS_POPUP | WS_VISIBLE, 16410 20, 20, 100, 100, 0, 0, 0, NULL); 16411 ok(popup != 0, "Failed to create popup window\n"); 16412 16413 GetWindowRect(popup, &rc_old); 16414 trace("popup %s\n", wine_dbgstr_rect(&rc_old)); 16415 16416 flush_sequence(); 16417 16418 SetParent(popup, child); 16419 flush_events(); 16420 ok_sequence(WmSetParentSeq_2, "SetParent() visible WS_POPUP", TRUE); 16421 16422 ok(GetWindowLongA(popup, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 16423 ok(!IsWindowVisible(popup), "IsWindowVisible() should return FALSE\n"); 16424 16425 GetWindowRect(child, &rc); 16426 trace("parent2 %s\n", wine_dbgstr_rect(&rc)); 16427 GetWindowRect(popup, &rc); 16428 MapWindowPoints(0, child, (POINT *)&rc, 2); 16429 trace("popup %s\n", wine_dbgstr_rect(&rc)); 16430 16431 ok(EqualRect(&rc_old, &rc), "rects do not match %s / %s\n", wine_dbgstr_rect(&rc_old), 16432 wine_dbgstr_rect(&rc)); 16433 16434 DestroyWindow(popup); 16435 DestroyWindow(child); 16436 DestroyWindow(parent1); 16437 DestroyWindow(parent2); 16438 16439 flush_sequence(); 16440 } 16441 16442 static const struct message WmKeyReleaseOnly[] = { 16443 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 0x41, 0x80000001 }, 16444 { WM_KEYUP, sent|wparam|lparam, 0x41, 0x80000001 }, 16445 { 0 } 16446 }; 16447 static const struct message WmKeyPressNormal[] = { 16448 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 0x41, 0x1 }, 16449 { WM_KEYDOWN, sent|wparam|lparam, 0x41, 0x1 }, 16450 { 0 } 16451 }; 16452 static const struct message WmKeyPressRepeat[] = { 16453 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 0x41, 0x40000001 }, 16454 { WM_KEYDOWN, sent|wparam|lparam, 0x41, 0x40000001 }, 16455 { 0 } 16456 }; 16457 static const struct message WmKeyReleaseNormal[] = { 16458 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 0x41, 0xc0000001 }, 16459 { WM_KEYUP, sent|wparam|lparam, 0x41, 0xc0000001 }, 16460 { 0 } 16461 }; 16462 16463 static void test_keyflags(void) 16464 { 16465 HWND test_window; 16466 SHORT key_state; 16467 BYTE keyboard_state[256]; 16468 MSG msg; 16469 16470 test_window = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 16471 100, 100, 200, 200, 0, 0, 0, NULL); 16472 16473 flush_events(); 16474 flush_sequence(); 16475 16476 /* keyup without a keydown */ 16477 keybd_event(0x41, 0, KEYEVENTF_KEYUP, 0); 16478 while (PeekMessageA(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) 16479 DispatchMessageA(&msg); 16480 ok_sequence(WmKeyReleaseOnly, "key release only", TRUE); 16481 16482 key_state = GetAsyncKeyState(0x41); 16483 ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state); 16484 16485 key_state = GetKeyState(0x41); 16486 ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state); 16487 16488 /* keydown */ 16489 keybd_event(0x41, 0, 0, 0); 16490 while (PeekMessageA(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) 16491 DispatchMessageA(&msg); 16492 ok_sequence(WmKeyPressNormal, "key press only", FALSE); 16493 16494 key_state = GetAsyncKeyState(0x41); 16495 ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); 16496 16497 key_state = GetKeyState(0x41); 16498 ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); 16499 16500 /* keydown repeat */ 16501 keybd_event(0x41, 0, 0, 0); 16502 while (PeekMessageA(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) 16503 DispatchMessageA(&msg); 16504 ok_sequence(WmKeyPressRepeat, "key press repeat", FALSE); 16505 16506 key_state = GetAsyncKeyState(0x41); 16507 ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); 16508 16509 key_state = GetKeyState(0x41); 16510 ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); 16511 16512 /* keyup */ 16513 keybd_event(0x41, 0, KEYEVENTF_KEYUP, 0); 16514 while (PeekMessageA(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) 16515 DispatchMessageA(&msg); 16516 ok_sequence(WmKeyReleaseNormal, "key release repeat", FALSE); 16517 16518 key_state = GetAsyncKeyState(0x41); 16519 ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state); 16520 16521 key_state = GetKeyState(0x41); 16522 ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state); 16523 16524 /* set the key state in this thread */ 16525 GetKeyboardState(keyboard_state); 16526 keyboard_state[0x41] = 0x80; 16527 SetKeyboardState(keyboard_state); 16528 16529 key_state = GetAsyncKeyState(0x41); 16530 ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state); 16531 16532 /* keydown */ 16533 keybd_event(0x41, 0, 0, 0); 16534 while (PeekMessageA(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) 16535 DispatchMessageA(&msg); 16536 ok_sequence(WmKeyPressRepeat, "key press after setkeyboardstate", TRUE); 16537 16538 key_state = GetAsyncKeyState(0x41); 16539 ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); 16540 16541 key_state = GetKeyState(0x41); 16542 ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); 16543 16544 /* clear the key state in this thread */ 16545 GetKeyboardState(keyboard_state); 16546 keyboard_state[0x41] = 0; 16547 SetKeyboardState(keyboard_state); 16548 16549 key_state = GetAsyncKeyState(0x41); 16550 ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); 16551 16552 /* keyup */ 16553 keybd_event(0x41, 0, KEYEVENTF_KEYUP, 0); 16554 while (PeekMessageA(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) 16555 DispatchMessageA(&msg); 16556 ok_sequence(WmKeyReleaseOnly, "key release after setkeyboardstate", TRUE); 16557 16558 key_state = GetAsyncKeyState(0x41); 16559 ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state); 16560 16561 key_state = GetKeyState(0x41); 16562 ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state); 16563 16564 DestroyWindow(test_window); 16565 flush_sequence(); 16566 } 16567 16568 static const struct message WmHotkeyPressLWIN[] = { 16569 { WM_KEYDOWN, kbd_hook|wparam|lparam, VK_LWIN, LLKHF_INJECTED }, 16570 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_LWIN, 1 }, 16571 { WM_KEYDOWN, sent|wparam|lparam, VK_LWIN, 1 }, 16572 { 0 } 16573 }; 16574 static const struct message WmHotkeyPress[] = { 16575 { WM_KEYDOWN, kbd_hook|lparam, 0, LLKHF_INJECTED }, 16576 { WM_HOTKEY, sent|wparam, 5 }, 16577 { 0 } 16578 }; 16579 static const struct message WmHotkeyRelease[] = { 16580 { WM_KEYUP, kbd_hook|lparam, 0, LLKHF_INJECTED|LLKHF_UP }, 16581 { HCBT_KEYSKIPPED, hook|lparam|optional, 0, 0x80000001 }, 16582 { WM_KEYUP, sent|lparam, 0, 0x80000001 }, 16583 { 0 } 16584 }; 16585 static const struct message WmHotkeyReleaseLWIN[] = { 16586 { WM_KEYUP, kbd_hook|wparam|lparam, VK_LWIN, LLKHF_INJECTED|LLKHF_UP }, 16587 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_LWIN, 0xc0000001 }, 16588 { WM_KEYUP, sent|wparam|lparam, VK_LWIN, 0xc0000001 }, 16589 { 0 } 16590 }; 16591 static const struct message WmHotkeyCombined[] = { 16592 { WM_KEYDOWN, kbd_hook|wparam|lparam, VK_LWIN, LLKHF_INJECTED }, 16593 { WM_KEYDOWN, kbd_hook|lparam, 0, LLKHF_INJECTED }, 16594 { WM_KEYUP, kbd_hook|lparam, 0, LLKHF_INJECTED|LLKHF_UP }, 16595 { WM_KEYUP, kbd_hook|wparam|lparam, VK_LWIN, LLKHF_INJECTED|LLKHF_UP }, 16596 { WM_APP, sent, 0, 0 }, 16597 { WM_HOTKEY, sent|wparam, 5 }, 16598 { WM_APP+1, sent, 0, 0 }, 16599 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_LWIN, 1 }, 16600 { WM_KEYDOWN, sent|wparam|lparam, VK_LWIN, 1 }, 16601 { HCBT_KEYSKIPPED, hook|optional, 0, 0x80000001 }, 16602 { WM_KEYUP, sent, 0, 0x80000001 }, /* lparam not checked so the sequence isn't a todo */ 16603 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_LWIN, 0xc0000001 }, 16604 { WM_KEYUP, sent|wparam|lparam, VK_LWIN, 0xc0000001 }, 16605 { 0 } 16606 }; 16607 static const struct message WmHotkeyPrevious[] = { 16608 { WM_KEYDOWN, kbd_hook|wparam|lparam, VK_LWIN, LLKHF_INJECTED }, 16609 { WM_KEYDOWN, kbd_hook|lparam, 0, LLKHF_INJECTED }, 16610 { WM_KEYUP, kbd_hook|lparam, 0, LLKHF_INJECTED|LLKHF_UP }, 16611 { WM_KEYUP, kbd_hook|wparam|lparam, VK_LWIN, LLKHF_INJECTED|LLKHF_UP }, 16612 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_LWIN, 1 }, 16613 { WM_KEYDOWN, sent|wparam|lparam, VK_LWIN, 1 }, 16614 { HCBT_KEYSKIPPED, hook|lparam|optional, 0, 1 }, 16615 { WM_KEYDOWN, sent|lparam, 0, 1 }, 16616 { HCBT_KEYSKIPPED, hook|optional|lparam, 0, 0xc0000001 }, 16617 { WM_KEYUP, sent|lparam, 0, 0xc0000001 }, 16618 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_LWIN, 0xc0000001 }, 16619 { WM_KEYUP, sent|wparam|lparam, VK_LWIN, 0xc0000001 }, 16620 { 0 } 16621 }; 16622 static const struct message WmHotkeyNew[] = { 16623 { WM_KEYDOWN, kbd_hook|lparam, 0, LLKHF_INJECTED }, 16624 { WM_KEYUP, kbd_hook|lparam, 0, LLKHF_INJECTED|LLKHF_UP }, 16625 { WM_HOTKEY, sent|wparam, 5 }, 16626 { HCBT_KEYSKIPPED, hook|optional, 0, 0x80000001 }, 16627 { WM_KEYUP, sent, 0, 0x80000001 }, /* lparam not checked so the sequence isn't a todo */ 16628 { 0 } 16629 }; 16630 16631 static int hotkey_letter; 16632 16633 static LRESULT CALLBACK KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam) 16634 { 16635 struct recvd_message msg; 16636 16637 if (nCode == HC_ACTION) 16638 { 16639 KBDLLHOOKSTRUCT *kdbhookstruct = (KBDLLHOOKSTRUCT*)lParam; 16640 16641 msg.hwnd = 0; 16642 msg.message = wParam; 16643 msg.flags = kbd_hook|wparam|lparam; 16644 msg.wParam = kdbhookstruct->vkCode; 16645 msg.lParam = kdbhookstruct->flags; 16646 msg.descr = "KeyboardHookProc"; 16647 add_message(&msg); 16648 16649 if (wParam == WM_KEYUP || wParam == WM_KEYDOWN) 16650 { 16651 ok(kdbhookstruct->vkCode == VK_LWIN || kdbhookstruct->vkCode == hotkey_letter, 16652 "unexpected keycode %x\n", kdbhookstruct->vkCode); 16653 } 16654 } 16655 16656 return CallNextHookEx(hKBD_hook, nCode, wParam, lParam); 16657 } 16658 16659 static void test_hotkey(void) 16660 { 16661 HWND test_window, taskbar_window; 16662 BOOL ret; 16663 MSG msg; 16664 DWORD queue_status; 16665 SHORT key_state; 16666 16667 SetLastError(0xdeadbeef); 16668 ret = UnregisterHotKey(NULL, 0); 16669 if (ret == TRUE) 16670 { 16671 skip("hotkeys not supported\n"); 16672 return; 16673 } 16674 16675 ok(ret == FALSE, "expected FALSE, got %i\n", ret); 16676 ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED || broken(GetLastError() == 0xdeadbeef), 16677 "unexpected error %d\n", GetLastError()); 16678 16679 test_window = CreateWindowExA(0, "HotkeyWindowClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 16680 100, 100, 200, 200, 0, 0, 0, NULL); 16681 16682 flush_sequence(); 16683 16684 SetLastError(0xdeadbeef); 16685 ret = UnregisterHotKey(test_window, 0); 16686 ok(ret == FALSE, "expected FALSE, got %i\n", ret); 16687 ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED || broken(GetLastError() == 0xdeadbeef), 16688 "unexpected error %d\n", GetLastError()); 16689 16690 /* Search for a Windows Key + letter combination that hasn't been registered */ 16691 for (hotkey_letter = 0x41; hotkey_letter <= 0x51; hotkey_letter ++) 16692 { 16693 SetLastError(0xdeadbeef); 16694 ret = RegisterHotKey(test_window, 5, MOD_WIN, hotkey_letter); 16695 16696 if (ret == TRUE) 16697 { 16698 break; 16699 } 16700 else 16701 { 16702 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED || broken(GetLastError() == 0xdeadbeef), 16703 "unexpected error %d\n", GetLastError()); 16704 } 16705 } 16706 16707 if (hotkey_letter == 0x52) 16708 { 16709 ok(0, "Couldn't find any free Windows Key + letter combination\n"); 16710 goto end; 16711 } 16712 16713 hKBD_hook = SetWindowsHookExA(WH_KEYBOARD_LL, KeyboardHookProc, GetModuleHandleA(NULL), 0); 16714 if (!hKBD_hook) win_skip("WH_KEYBOARD_LL is not supported\n"); 16715 16716 /* Same key combination, different id */ 16717 SetLastError(0xdeadbeef); 16718 ret = RegisterHotKey(test_window, 4, MOD_WIN, hotkey_letter); 16719 ok(ret == FALSE, "expected FALSE, got %i\n", ret); 16720 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED || broken(GetLastError() == 0xdeadbeef), 16721 "unexpected error %d\n", GetLastError()); 16722 16723 /* Same key combination, different window */ 16724 SetLastError(0xdeadbeef); 16725 ret = RegisterHotKey(NULL, 5, MOD_WIN, hotkey_letter); 16726 ok(ret == FALSE, "expected FALSE, got %i\n", ret); 16727 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED || broken(GetLastError() == 0xdeadbeef), 16728 "unexpected error %d\n", GetLastError()); 16729 16730 /* Register the same hotkey twice */ 16731 SetLastError(0xdeadbeef); 16732 ret = RegisterHotKey(test_window, 5, MOD_WIN, hotkey_letter); 16733 ok(ret == FALSE, "expected FALSE, got %i\n", ret); 16734 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED || broken(GetLastError() == 0xdeadbeef), 16735 "unexpected error %d\n", GetLastError()); 16736 16737 /* Window on another thread */ 16738 taskbar_window = FindWindowA("Shell_TrayWnd", NULL); 16739 if (!taskbar_window) 16740 { 16741 skip("no taskbar?\n"); 16742 } 16743 else 16744 { 16745 SetLastError(0xdeadbeef); 16746 ret = RegisterHotKey(taskbar_window, 5, 0, hotkey_letter); 16747 ok(ret == FALSE, "expected FALSE, got %i\n", ret); 16748 ok(GetLastError() == ERROR_WINDOW_OF_OTHER_THREAD || broken(GetLastError() == 0xdeadbeef), 16749 "unexpected error %d\n", GetLastError()); 16750 } 16751 16752 /* Inject the appropriate key sequence */ 16753 keybd_event(VK_LWIN, 0, 0, 0); 16754 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 16755 DispatchMessageA(&msg); 16756 ok_sequence(WmHotkeyPressLWIN, "window hotkey press LWIN", FALSE); 16757 16758 keybd_event(hotkey_letter, 0, 0, 0); 16759 queue_status = GetQueueStatus(QS_HOTKEY); 16760 ok((queue_status & (QS_HOTKEY << 16)) == QS_HOTKEY << 16, "expected QS_HOTKEY << 16 set, got %x\n", queue_status); 16761 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 16762 { 16763 if (msg.message == WM_HOTKEY) 16764 { 16765 ok(msg.hwnd == test_window, "unexpected hwnd %p\n", msg.hwnd); 16766 ok(msg.lParam == MAKELPARAM(MOD_WIN, hotkey_letter), "unexpected WM_HOTKEY lparam %lx\n", msg.lParam); 16767 } 16768 DispatchMessageA(&msg); 16769 } 16770 ok_sequence(WmHotkeyPress, "window hotkey press", FALSE); 16771 16772 queue_status = GetQueueStatus(QS_HOTKEY); 16773 ok((queue_status & (QS_HOTKEY << 16)) == 0, "expected QS_HOTKEY << 16 cleared, got %x\n", queue_status); 16774 16775 key_state = GetAsyncKeyState(hotkey_letter); 16776 ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); 16777 16778 keybd_event(hotkey_letter, 0, KEYEVENTF_KEYUP, 0); 16779 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 16780 DispatchMessageA(&msg); 16781 ok_sequence(WmHotkeyRelease, "window hotkey release", TRUE); 16782 16783 keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP, 0); 16784 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 16785 DispatchMessageA(&msg); 16786 ok_sequence(WmHotkeyReleaseLWIN, "window hotkey release LWIN", FALSE); 16787 16788 /* normal posted WM_HOTKEY messages set QS_HOTKEY */ 16789 PostMessageA(test_window, WM_HOTKEY, 0, 0); 16790 queue_status = GetQueueStatus(QS_HOTKEY); 16791 ok((queue_status & (QS_HOTKEY << 16)) == QS_HOTKEY << 16, "expected QS_HOTKEY << 16 set, got %x\n", queue_status); 16792 queue_status = GetQueueStatus(QS_POSTMESSAGE); 16793 ok((queue_status & (QS_POSTMESSAGE << 16)) == QS_POSTMESSAGE << 16, "expected QS_POSTMESSAGE << 16 set, got %x\n", queue_status); 16794 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 16795 DispatchMessageA(&msg); 16796 flush_sequence(); 16797 16798 /* Send and process all messages at once */ 16799 PostMessageA(test_window, WM_APP, 0, 0); 16800 keybd_event(VK_LWIN, 0, 0, 0); 16801 keybd_event(hotkey_letter, 0, 0, 0); 16802 keybd_event(hotkey_letter, 0, KEYEVENTF_KEYUP, 0); 16803 keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP, 0); 16804 16805 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 16806 { 16807 if (msg.message == WM_HOTKEY) 16808 { 16809 ok(msg.hwnd == test_window, "unexpected hwnd %p\n", msg.hwnd); 16810 ok(msg.lParam == MAKELPARAM(MOD_WIN, hotkey_letter), "unexpected WM_HOTKEY lparam %lx\n", msg.lParam); 16811 } 16812 DispatchMessageA(&msg); 16813 } 16814 ok_sequence(WmHotkeyCombined, "window hotkey combined", FALSE); 16815 16816 /* Register same hwnd/id with different key combination */ 16817 ret = RegisterHotKey(test_window, 5, 0, hotkey_letter); 16818 ok(ret == TRUE, "expected TRUE, got %i, err=%d\n", ret, GetLastError()); 16819 16820 /* Previous key combination does not work */ 16821 keybd_event(VK_LWIN, 0, 0, 0); 16822 keybd_event(hotkey_letter, 0, 0, 0); 16823 keybd_event(hotkey_letter, 0, KEYEVENTF_KEYUP, 0); 16824 keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP, 0); 16825 16826 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 16827 DispatchMessageA(&msg); 16828 ok_sequence(WmHotkeyPrevious, "window hotkey previous", FALSE); 16829 16830 /* New key combination works */ 16831 keybd_event(hotkey_letter, 0, 0, 0); 16832 keybd_event(hotkey_letter, 0, KEYEVENTF_KEYUP, 0); 16833 16834 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 16835 { 16836 if (msg.message == WM_HOTKEY) 16837 { 16838 ok(msg.hwnd == test_window, "unexpected hwnd %p\n", msg.hwnd); 16839 ok(msg.lParam == MAKELPARAM(0, hotkey_letter), "unexpected WM_HOTKEY lparam %lx\n", msg.lParam); 16840 } 16841 DispatchMessageA(&msg); 16842 } 16843 ok_sequence(WmHotkeyNew, "window hotkey new", FALSE); 16844 16845 /* Unregister hotkey properly */ 16846 ret = UnregisterHotKey(test_window, 5); 16847 ok(ret == TRUE, "expected TRUE, got %i, err=%d\n", ret, GetLastError()); 16848 16849 /* Unregister hotkey again */ 16850 SetLastError(0xdeadbeef); 16851 ret = UnregisterHotKey(test_window, 5); 16852 ok(ret == FALSE, "expected FALSE, got %i\n", ret); 16853 ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED || broken(GetLastError() == 0xdeadbeef), 16854 "unexpected error %d\n", GetLastError()); 16855 16856 /* Register thread hotkey */ 16857 ret = RegisterHotKey(NULL, 5, MOD_WIN, hotkey_letter); 16858 ok(ret == TRUE, "expected TRUE, got %i, err=%d\n", ret, GetLastError()); 16859 16860 /* Inject the appropriate key sequence */ 16861 keybd_event(VK_LWIN, 0, 0, 0); 16862 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 16863 { 16864 ok(msg.hwnd != NULL, "unexpected thread message %x\n", msg.message); 16865 DispatchMessageA(&msg); 16866 } 16867 ok_sequence(WmHotkeyPressLWIN, "thread hotkey press LWIN", FALSE); 16868 16869 keybd_event(hotkey_letter, 0, 0, 0); 16870 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 16871 { 16872 if (msg.message == WM_HOTKEY) 16873 { 16874 struct recvd_message message; 16875 ok(msg.hwnd == NULL, "unexpected hwnd %p\n", msg.hwnd); 16876 ok(msg.lParam == MAKELPARAM(MOD_WIN, hotkey_letter), "unexpected WM_HOTKEY lparam %lx\n", msg.lParam); 16877 message.message = msg.message; 16878 message.flags = sent|wparam|lparam; 16879 message.wParam = msg.wParam; 16880 message.lParam = msg.lParam; 16881 message.descr = "test_hotkey thread message"; 16882 add_message(&message); 16883 } 16884 else 16885 ok(msg.hwnd != NULL, "unexpected thread message %x\n", msg.message); 16886 DispatchMessageA(&msg); 16887 } 16888 ok_sequence(WmHotkeyPress, "thread hotkey press", FALSE); 16889 16890 keybd_event(hotkey_letter, 0, KEYEVENTF_KEYUP, 0); 16891 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 16892 { 16893 ok(msg.hwnd != NULL, "unexpected thread message %x\n", msg.message); 16894 DispatchMessageA(&msg); 16895 } 16896 ok_sequence(WmHotkeyRelease, "thread hotkey release", TRUE); 16897 16898 keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP, 0); 16899 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 16900 { 16901 ros_skip_flaky 16902 ok(msg.hwnd != NULL, "unexpected thread message %x\n", msg.message); 16903 DispatchMessageA(&msg); 16904 } 16905 ok_sequence(WmHotkeyReleaseLWIN, "thread hotkey release LWIN", FALSE); 16906 16907 /* Unregister thread hotkey */ 16908 ret = UnregisterHotKey(NULL, 5); 16909 ok(ret == TRUE, "expected TRUE, got %i, err=%d\n", ret, GetLastError()); 16910 16911 if (hKBD_hook) UnhookWindowsHookEx(hKBD_hook); 16912 hKBD_hook = NULL; 16913 16914 end: 16915 UnregisterHotKey(NULL, 5); 16916 UnregisterHotKey(test_window, 5); 16917 DestroyWindow(test_window); 16918 flush_sequence(); 16919 } 16920 16921 16922 static const struct message WmSetFocus_1[] = { 16923 { HCBT_SETFOCUS, hook }, /* child */ 16924 { HCBT_ACTIVATE, hook }, /* parent */ 16925 { WM_QUERYNEWPALETTE, sent|wparam|lparam|parent|optional, 0, 0 }, 16926 { WM_WINDOWPOSCHANGING, sent|parent, 0, SWP_NOSIZE|SWP_NOMOVE }, 16927 { WM_ACTIVATEAPP, sent|wparam|parent, 1 }, 16928 { WM_NCACTIVATE, sent|parent }, 16929 { WM_GETTEXT, sent|defwinproc|parent|optional }, 16930 { WM_GETTEXT, sent|defwinproc|parent|optional }, 16931 { WM_ACTIVATE, sent|wparam|parent, 1 }, 16932 { HCBT_SETFOCUS, hook }, /* parent */ 16933 { WM_SETFOCUS, sent|defwinproc|parent }, 16934 { WM_KILLFOCUS, sent|parent }, 16935 { WM_SETFOCUS, sent }, 16936 { 0 } 16937 }; 16938 static const struct message WmSetFocus_2[] = { 16939 { HCBT_SETFOCUS, hook }, /* parent */ 16940 { WM_KILLFOCUS, sent }, 16941 { WM_SETFOCUS, sent|parent }, 16942 { 0 } 16943 }; 16944 static const struct message WmSetFocus_3[] = { 16945 { HCBT_SETFOCUS, hook }, /* child */ 16946 { 0 } 16947 }; 16948 16949 static void test_SetFocus(void) 16950 { 16951 HWND parent, old_parent, child, old_focus, old_active; 16952 MSG msg; 16953 struct wnd_event wnd_event; 16954 HANDLE hthread; 16955 DWORD ret, tid; 16956 16957 wnd_event.start_event = CreateEventW(NULL, 0, 0, NULL); 16958 ok(wnd_event.start_event != 0, "CreateEvent error %d\n", GetLastError()); 16959 hthread = CreateThread(NULL, 0, thread_proc, &wnd_event, 0, &tid); 16960 ok(hthread != 0, "CreateThread error %d\n", GetLastError()); 16961 ret = WaitForSingleObject(wnd_event.start_event, INFINITE); 16962 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 16963 CloseHandle(wnd_event.start_event); 16964 16965 parent = CreateWindowExA(0, "TestParentClass", NULL, WS_OVERLAPPEDWINDOW, 16966 0, 0, 0, 0, 0, 0, 0, NULL); 16967 ok(parent != 0, "failed to create parent window\n"); 16968 child = CreateWindowExA(0, "TestWindowClass", NULL, WS_CHILD, 16969 0, 0, 0, 0, parent, 0, 0, NULL); 16970 ok(child != 0, "failed to create child window\n"); 16971 16972 trace("parent %p, child %p, thread window %p\n", parent, child, wnd_event.hwnd); 16973 16974 SetFocus(0); 16975 SetActiveWindow(0); 16976 16977 flush_events(); 16978 flush_sequence(); 16979 16980 ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow()); 16981 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus()); 16982 16983 log_all_parent_messages++; 16984 16985 old_focus = SetFocus(child); 16986 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 16987 ok_sequence(WmSetFocus_1, "SetFocus on a child window", TRUE); 16988 ok(old_focus == parent, "expected old focus %p, got %p\n", parent, old_focus); 16989 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 16990 ok(GetFocus() == child, "expected focus %p, got %p\n", child, GetFocus()); 16991 16992 old_focus = SetFocus(parent); 16993 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 16994 ok_sequence(WmSetFocus_2, "SetFocus on a parent window", FALSE); 16995 ok(old_focus == child, "expected old focus %p, got %p\n", child, old_focus); 16996 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 16997 ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); 16998 16999 SetLastError(0xdeadbeef); 17000 old_focus = SetFocus((HWND)0xdeadbeef); 17001 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || broken(GetLastError() == 0xdeadbeef), 17002 "expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError()); 17003 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 17004 ok_sequence(WmEmptySeq, "SetFocus on an invalid window", FALSE); 17005 ok(old_focus == 0, "expected old focus 0, got %p\n", old_focus); 17006 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 17007 ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); 17008 17009 SetLastError(0xdeadbeef); 17010 old_focus = SetFocus(GetDesktopWindow()); 17011 ok(GetLastError() == ERROR_ACCESS_DENIED /* Vista+ */ || 17012 broken(GetLastError() == 0xdeadbeef), "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); 17013 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 17014 ok_sequence(WmEmptySeq, "SetFocus on a desktop window", TRUE); 17015 ok(old_focus == 0, "expected old focus 0, got %p\n", old_focus); 17016 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 17017 ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); 17018 17019 SetLastError(0xdeadbeef); 17020 old_focus = SetFocus(wnd_event.hwnd); 17021 ok(GetLastError() == ERROR_ACCESS_DENIED /* Vista+ */ || 17022 broken(GetLastError() == 0xdeadbeef), "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); 17023 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 17024 ok_sequence(WmEmptySeq, "SetFocus on another thread window", TRUE); 17025 ok(old_focus == 0, "expected old focus 0, got %p\n", old_focus); 17026 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 17027 ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); 17028 17029 SetLastError(0xdeadbeef); 17030 old_active = SetActiveWindow((HWND)0xdeadbeef); 17031 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || broken(GetLastError() == 0xdeadbeef), 17032 "expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError()); 17033 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 17034 ok_sequence(WmEmptySeq, "SetActiveWindow on an invalid window", FALSE); 17035 ok(old_active == 0, "expected old focus 0, got %p\n", old_active); 17036 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 17037 ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); 17038 17039 SetLastError(0xdeadbeef); 17040 old_active = SetActiveWindow(GetDesktopWindow()); 17041 todo_wine 17042 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError()); 17043 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 17044 ok_sequence(WmEmptySeq, "SetActiveWindow on a desktop window", TRUE); 17045 ok(old_active == 0, "expected old focus 0, got %p\n", old_focus); 17046 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 17047 ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); 17048 17049 SetLastError(0xdeadbeef); 17050 old_active = SetActiveWindow(wnd_event.hwnd); 17051 todo_wine 17052 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError()); 17053 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 17054 ok_sequence(WmEmptySeq, "SetActiveWindow on another thread window", TRUE); 17055 ok(old_active == 0, "expected old focus 0, got %p\n", old_active); 17056 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 17057 ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); 17058 17059 SetLastError(0xdeadbeef); 17060 ret = AttachThreadInput(GetCurrentThreadId(), tid, TRUE); 17061 ok(ret, "AttachThreadInput error %d\n", GetLastError()); 17062 17063 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 17064 ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); 17065 17066 flush_events(); 17067 flush_sequence(); 17068 17069 old_focus = SetFocus(wnd_event.hwnd); 17070 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 17071 ok(old_focus == wnd_event.hwnd, "expected old focus %p, got %p\n", wnd_event.hwnd, old_focus); 17072 ok(GetActiveWindow() == wnd_event.hwnd, "expected active %p, got %p\n", wnd_event.hwnd, GetActiveWindow()); 17073 ok(GetFocus() == wnd_event.hwnd, "expected focus %p, got %p\n", wnd_event.hwnd, GetFocus()); 17074 17075 old_focus = SetFocus(parent); 17076 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 17077 ok(old_focus == parent, "expected old focus %p, got %p\n", parent, old_focus); 17078 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 17079 ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); 17080 17081 flush_events(); 17082 flush_sequence(); 17083 17084 old_active = SetActiveWindow(wnd_event.hwnd); 17085 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 17086 ok(old_active == parent, "expected old focus %p, got %p\n", parent, old_active); 17087 ok(GetActiveWindow() == wnd_event.hwnd, "expected active %p, got %p\n", wnd_event.hwnd, GetActiveWindow()); 17088 ok(GetFocus() == wnd_event.hwnd, "expected focus %p, got %p\n", wnd_event.hwnd, GetFocus()); 17089 17090 SetLastError(0xdeadbeef); 17091 ret = AttachThreadInput(GetCurrentThreadId(), tid, FALSE); 17092 ok(ret, "AttachThreadInput error %d\n", GetLastError()); 17093 17094 ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow()); 17095 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus()); 17096 17097 old_parent = SetParent(child, GetDesktopWindow()); 17098 ok(old_parent == parent, "expected old parent %p, got %p\n", parent, old_parent); 17099 17100 ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow()); 17101 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus()); 17102 17103 old_focus = SetFocus(parent); 17104 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 17105 ok(old_focus == parent, "expected old focus %p, got %p\n", parent, old_focus); 17106 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 17107 ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); 17108 17109 flush_events(); 17110 flush_sequence(); 17111 17112 SetLastError(0xdeadbeef); 17113 old_focus = SetFocus(child); 17114 todo_wine 17115 ok(GetLastError() == ERROR_INVALID_PARAMETER /* Vista+ */ || 17116 broken(GetLastError() == 0) /* XP */ || 17117 broken(GetLastError() == 0xdeadbeef), "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 17118 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 17119 ok_sequence(WmSetFocus_3, "SetFocus on a child window", TRUE); 17120 ok(old_focus == 0, "expected old focus 0, got %p\n", old_focus); 17121 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 17122 ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); 17123 17124 SetLastError(0xdeadbeef); 17125 old_active = SetActiveWindow(child); 17126 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError()); 17127 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 17128 ok_sequence(WmEmptySeq, "SetActiveWindow on a child window", FALSE); 17129 ok(old_active == parent, "expected old active %p, got %p\n", parent, old_active); 17130 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 17131 ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); 17132 17133 log_all_parent_messages--; 17134 17135 DestroyWindow(child); 17136 DestroyWindow(parent); 17137 17138 ret = PostMessageA(wnd_event.hwnd, WM_QUIT, 0, 0); 17139 ok(ret, "PostMessage(WM_QUIT) error %d\n", GetLastError()); 17140 ret = WaitForSingleObject(hthread, INFINITE); 17141 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 17142 CloseHandle(hthread); 17143 } 17144 17145 static const struct message WmSetLayeredStyle[] = { 17146 { WM_STYLECHANGING, sent }, 17147 { WM_STYLECHANGED, sent }, 17148 { WM_GETTEXT, sent|defwinproc|optional }, 17149 { 0 } 17150 }; 17151 17152 static const struct message WmSetLayeredStyle2[] = { 17153 { WM_STYLECHANGING, sent }, 17154 { WM_STYLECHANGED, sent }, 17155 { WM_WINDOWPOSCHANGING, sent|optional|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 17156 { WM_NCCALCSIZE, sent|optional|wparam|defwinproc, 1 }, 17157 { WM_WINDOWPOSCHANGED, sent|optional|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 17158 { WM_MOVE, sent|optional|defwinproc|wparam, 0 }, 17159 { WM_SIZE, sent|optional|defwinproc|wparam, SIZE_RESTORED }, 17160 { 0 } 17161 }; 17162 17163 struct layered_window_info 17164 { 17165 HWND hwnd; 17166 HDC hdc; 17167 SIZE size; 17168 HANDLE event; 17169 BOOL ret; 17170 }; 17171 17172 static DWORD CALLBACK update_layered_proc( void *param ) 17173 { 17174 struct layered_window_info *info = param; 17175 POINT src = { 0, 0 }; 17176 17177 info->ret = pUpdateLayeredWindow( info->hwnd, 0, NULL, &info->size, 17178 info->hdc, &src, 0, NULL, ULW_OPAQUE ); 17179 ok( info->ret, "failed\n"); 17180 SetEvent( info->event ); 17181 return 0; 17182 } 17183 17184 static void test_layered_window(void) 17185 { 17186 HWND hwnd; 17187 HDC hdc; 17188 HBITMAP bmp; 17189 BOOL ret; 17190 SIZE size; 17191 POINT pos, src; 17192 RECT rect, client; 17193 HANDLE thread; 17194 DWORD tid; 17195 struct layered_window_info info; 17196 17197 if (!pUpdateLayeredWindow) 17198 { 17199 win_skip( "UpdateLayeredWindow not supported\n" ); 17200 return; 17201 } 17202 17203 hdc = CreateCompatibleDC( 0 ); 17204 bmp = CreateCompatibleBitmap( hdc, 300, 300 ); 17205 SelectObject( hdc, bmp ); 17206 17207 hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_CAPTION | WS_THICKFRAME | WS_SYSMENU, 17208 100, 100, 300, 300, 0, 0, 0, NULL); 17209 ok( hwnd != 0, "failed to create window\n" ); 17210 ShowWindow( hwnd, SW_SHOWNORMAL ); 17211 UpdateWindow( hwnd ); 17212 flush_events(); 17213 flush_sequence(); 17214 17215 GetWindowRect( hwnd, &rect ); 17216 GetClientRect( hwnd, &client ); 17217 ok( client.right < rect.right - rect.left, "wrong client area\n" ); 17218 ok( client.bottom < rect.bottom - rect.top, "wrong client area\n" ); 17219 17220 src.x = src.y = 0; 17221 pos.x = pos.y = 300; 17222 size.cx = size.cy = 250; 17223 ret = pUpdateLayeredWindow( hwnd, 0, &pos, &size, hdc, &src, 0, NULL, ULW_OPAQUE ); 17224 ok( !ret, "UpdateLayeredWindow should fail on non-layered window\n" ); 17225 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() ); 17226 SetWindowLongA( hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED ); 17227 ok_sequence( WmSetLayeredStyle, "WmSetLayeredStyle", FALSE ); 17228 17229 ret = pUpdateLayeredWindow( hwnd, 0, &pos, &size, hdc, &src, 0, NULL, ULW_OPAQUE ); 17230 ok( ret, "UpdateLayeredWindow failed err %u\n", GetLastError() ); 17231 ok_sequence( WmEmptySeq, "UpdateLayeredWindow", FALSE ); 17232 GetWindowRect( hwnd, &rect ); 17233 ok( rect.left == 300 && rect.top == 300 && rect.right == 550 && rect.bottom == 550, 17234 "wrong window rect %s\n", wine_dbgstr_rect( &rect )); 17235 GetClientRect( hwnd, &rect ); 17236 ok( rect.right == client.right - 50 && rect.bottom == client.bottom - 50, 17237 "wrong client rect %s\n", wine_dbgstr_rect( &rect )); 17238 17239 size.cx = 150; 17240 pos.y = 200; 17241 ret = pUpdateLayeredWindow( hwnd, 0, &pos, &size, hdc, &src, 0, NULL, ULW_OPAQUE ); 17242 ok( ret, "UpdateLayeredWindow failed err %u\n", GetLastError() ); 17243 ok_sequence( WmEmptySeq, "UpdateLayeredWindow", FALSE ); 17244 GetWindowRect( hwnd, &rect ); 17245 ok( rect.left == 300 && rect.top == 200 && rect.right == 450 && rect.bottom == 450, 17246 "wrong window rect %s\n", wine_dbgstr_rect( &rect )); 17247 GetClientRect( hwnd, &rect ); 17248 ok( rect.right == client.right - 150 && rect.bottom == client.bottom - 50, 17249 "wrong client rect %s\n", wine_dbgstr_rect( &rect )); 17250 17251 SetWindowLongA( hwnd, GWL_STYLE, 17252 GetWindowLongA(hwnd, GWL_STYLE) & ~(WS_CAPTION | WS_THICKFRAME | WS_SYSMENU) ); 17253 ok_sequence( WmSetLayeredStyle2, "WmSetLayeredStyle2", FALSE ); 17254 17255 size.cx = 200; 17256 pos.x = 200; 17257 ret = pUpdateLayeredWindow( hwnd, 0, &pos, &size, hdc, &src, 0, NULL, ULW_OPAQUE ); 17258 ok( ret, "UpdateLayeredWindow failed err %u\n", GetLastError() ); 17259 ok_sequence( WmEmptySeq, "UpdateLayeredWindow", FALSE ); 17260 GetWindowRect( hwnd, &rect ); 17261 ok( rect.left == 200 && rect.top == 200 && rect.right == 400 && rect.bottom == 450, 17262 "wrong window rect %s\n", wine_dbgstr_rect( &rect )); 17263 GetClientRect( hwnd, &rect ); 17264 ok( (rect.right == 200 && rect.bottom == 250) || 17265 broken(rect.right == client.right - 100 && rect.bottom == client.bottom - 50), 17266 "wrong client rect %s\n", wine_dbgstr_rect( &rect )); 17267 17268 size.cx = 0; 17269 ret = pUpdateLayeredWindow( hwnd, 0, &pos, &size, hdc, &src, 0, NULL, ULW_OPAQUE ); 17270 ok( !ret, "UpdateLayeredWindow should fail on non-layered window\n" ); 17271 ok( GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == ERROR_MR_MID_NOT_FOUND) || 17272 broken(GetLastError() == ERROR_GEN_FAILURE) /* win7 */, "wrong error %u\n", GetLastError() ); 17273 size.cx = 1; 17274 size.cy = -1; 17275 ret = pUpdateLayeredWindow( hwnd, 0, &pos, &size, hdc, &src, 0, NULL, ULW_OPAQUE ); 17276 ok( !ret, "UpdateLayeredWindow should fail on non-layered window\n" ); 17277 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() ); 17278 17279 SetWindowLongA( hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) & ~WS_EX_LAYERED ); 17280 ok_sequence( WmSetLayeredStyle, "WmSetLayeredStyle", FALSE ); 17281 GetWindowRect( hwnd, &rect ); 17282 ok( rect.left == 200 && rect.top == 200 && rect.right == 400 && rect.bottom == 450, 17283 "wrong window rect %s\n", wine_dbgstr_rect( &rect )); 17284 GetClientRect( hwnd, &rect ); 17285 ok( (rect.right == 200 && rect.bottom == 250) || 17286 broken(rect.right == client.right - 100 && rect.bottom == client.bottom - 50), 17287 "wrong client rect %s\n", wine_dbgstr_rect( &rect )); 17288 17289 SetWindowLongA( hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED ); 17290 info.hwnd = hwnd; 17291 info.hdc = hdc; 17292 info.size.cx = 250; 17293 info.size.cy = 300; 17294 info.event = CreateEventA( NULL, TRUE, FALSE, NULL ); 17295 info.ret = FALSE; 17296 thread = CreateThread( NULL, 0, update_layered_proc, &info, 0, &tid ); 17297 ok( WaitForSingleObject( info.event, 1000 ) == 0, "wait failed\n" ); 17298 ok( info.ret, "UpdateLayeredWindow failed in other thread\n" ); 17299 WaitForSingleObject( thread, 1000 ); 17300 CloseHandle( thread ); 17301 GetWindowRect( hwnd, &rect ); 17302 ok( rect.left == 200 && rect.top == 200 && rect.right == 450 && rect.bottom == 500, 17303 "wrong window rect %s\n", wine_dbgstr_rect( &rect )); 17304 GetClientRect( hwnd, &rect ); 17305 ok( (rect.right == 250 && rect.bottom == 300) || 17306 broken(rect.right == client.right - 50 && rect.bottom == client.bottom), 17307 "wrong client rect %s\n", wine_dbgstr_rect( &rect )); 17308 17309 DestroyWindow( hwnd ); 17310 DeleteDC( hdc ); 17311 DeleteObject( bmp ); 17312 } 17313 17314 static HMENU hpopupmenu; 17315 17316 static LRESULT WINAPI cancel_popup_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 17317 { 17318 if (ignore_message( message )) return 0; 17319 17320 switch (message) { 17321 case WM_ENTERIDLE: 17322 todo_wine ok(GetCapture() == hwnd, "expected %p, got %p\n", hwnd, GetCapture()); 17323 EndMenu(); 17324 break; 17325 case WM_INITMENU: 17326 case WM_INITMENUPOPUP: 17327 case WM_UNINITMENUPOPUP: 17328 ok((HMENU)wParam == hpopupmenu, "expected %p, got %lx\n", hpopupmenu, wParam); 17329 break; 17330 case WM_CAPTURECHANGED: 17331 todo_wine ok(!lParam || (HWND)lParam == hwnd, "lost capture to %lx\n", lParam); 17332 break; 17333 } 17334 17335 return MsgCheckProc (FALSE, hwnd, message, wParam, lParam); 17336 } 17337 17338 static LRESULT WINAPI cancel_init_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 17339 { 17340 if (ignore_message( message )) return 0; 17341 17342 switch (message) { 17343 case WM_ENTERMENULOOP: 17344 ok(EndMenu() == TRUE, "EndMenu() failed\n"); 17345 break; 17346 } 17347 17348 return MsgCheckProc (FALSE, hwnd, message, wParam, lParam); 17349 } 17350 17351 static void test_TrackPopupMenu(void) 17352 { 17353 MSG msg; 17354 HWND hwnd; 17355 BOOL ret; 17356 17357 hwnd = CreateWindowExA(0, "TestWindowClass", NULL, 0, 17358 0, 0, 1, 1, 0, 17359 NULL, NULL, 0); 17360 ok(hwnd != NULL, "CreateWindowEx failed with error %d\n", GetLastError()); 17361 17362 SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (LONG_PTR)cancel_popup_proc); 17363 17364 hpopupmenu = CreatePopupMenu(); 17365 ok(hpopupmenu != NULL, "CreateMenu failed with error %d\n", GetLastError()); 17366 17367 AppendMenuA(hpopupmenu, MF_STRING, 100, "item 1"); 17368 AppendMenuA(hpopupmenu, MF_STRING, 100, "item 2"); 17369 17370 flush_events(); 17371 flush_sequence(); 17372 ret = TrackPopupMenu(hpopupmenu, 0, 100,100, 0, hwnd, NULL); 17373 ok_sequence(WmTrackPopupMenu, "TrackPopupMenu", TRUE); 17374 ok(ret == 1, "TrackPopupMenu failed with error %i\n", GetLastError()); 17375 17376 /* Test popup closing with an ESC-press */ 17377 flush_events(); 17378 PostMessageW(hwnd, WM_KEYDOWN, VK_ESCAPE, 0); 17379 ret = TrackPopupMenu(hpopupmenu, 0, 100,100, 0, hwnd, NULL); 17380 ok(ret == 1, "TrackPopupMenu failed with error %i\n", GetLastError()); 17381 PostQuitMessage(0); 17382 flush_sequence(); 17383 while ( PeekMessageA(&msg, 0, 0, 0, PM_REMOVE) ) 17384 { 17385 TranslateMessage(&msg); 17386 DispatchMessageA(&msg); 17387 } 17388 ok_sequence(WmTrackPopupMenuEsc, "TrackPopupMenuEsc", FALSE); /* Shouldn't get any message */ 17389 17390 SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (LONG_PTR)cancel_init_proc); 17391 17392 flush_events(); 17393 flush_sequence(); 17394 ret = TrackPopupMenu(hpopupmenu, 0, 100,100, 0, hwnd, NULL); 17395 ok_sequence(WmTrackPopupMenuAbort, "WmTrackPopupMenuAbort", TRUE); 17396 ok(ret == TRUE, "TrackPopupMenu failed\n"); 17397 17398 SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (LONG_PTR)cancel_popup_proc); 17399 17400 SetCapture(hwnd); 17401 17402 flush_events(); 17403 flush_sequence(); 17404 ret = TrackPopupMenu(hpopupmenu, 0, 100,100, 0, hwnd, NULL); 17405 ok_sequence(WmTrackPopupMenuCapture, "TrackPopupMenuCapture", TRUE); 17406 ok(ret == 1, "TrackPopupMenuCapture failed with error %i\n", GetLastError()); 17407 17408 DestroyMenu(hpopupmenu); 17409 DestroyWindow(hwnd); 17410 } 17411 17412 static void test_TrackPopupMenuEmpty(void) 17413 { 17414 HWND hwnd; 17415 BOOL ret; 17416 17417 hwnd = CreateWindowExA(0, "TestWindowClass", NULL, 0, 17418 0, 0, 1, 1, 0, 17419 NULL, NULL, 0); 17420 ok(hwnd != NULL, "CreateWindowEx failed with error %d\n", GetLastError()); 17421 17422 SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (LONG_PTR)cancel_popup_proc); 17423 17424 hpopupmenu = CreatePopupMenu(); 17425 ok(hpopupmenu != NULL, "CreateMenu failed with error %d\n", GetLastError()); 17426 17427 flush_events(); 17428 flush_sequence(); 17429 ret = TrackPopupMenu(hpopupmenu, 0, 100,100, 0, hwnd, NULL); 17430 ok_sequence(WmTrackPopupMenuEmpty, "TrackPopupMenuEmpty", TRUE); 17431 ok(ret == 0, "TrackPopupMenu succeeded\n"); 17432 17433 DestroyMenu(hpopupmenu); 17434 DestroyWindow(hwnd); 17435 } 17436 17437 static const struct message send_message_1[] = { 17438 { WM_USER+2, sent|wparam|lparam, 0, 0 }, 17439 { WM_USER, sent|wparam|lparam, 0, 0 }, 17440 { 0 } 17441 }; 17442 static const struct message send_message_2[] = { 17443 { WM_USER+4, sent|wparam|lparam, 0, 0 }, 17444 { 0 } 17445 }; 17446 static const struct message send_message_3[] = { 17447 { WM_USER+3, sent|wparam|lparam, 0, 0 }, 17448 { WM_USER+1, sent|wparam|lparam, 0, 0 }, 17449 { 0 } 17450 }; 17451 17452 static DWORD WINAPI SendMessage_thread_1(void *param) 17453 { 17454 struct wnd_event *wnd_event = param; 17455 17456 trace("thread: starting\n"); 17457 WaitForSingleObject(wnd_event->start_event, INFINITE); 17458 17459 trace("thread: call PostMessage\n"); 17460 PostMessageA(wnd_event->hwnd, WM_USER, 0, 0); 17461 17462 trace("thread: call PostMessage\n"); 17463 PostMessageA(wnd_event->hwnd, WM_USER+1, 0, 0); 17464 17465 trace("thread: call SendMessage\n"); 17466 SendMessageA(wnd_event->hwnd, WM_USER+2, 0, 0); 17467 17468 trace("thread: call SendMessage\n"); 17469 SendMessageA(wnd_event->hwnd, WM_USER+3, 0, 0); 17470 17471 return 0; 17472 } 17473 17474 static DWORD WINAPI SendMessage_thread_2(void *param) 17475 { 17476 struct wnd_event *wnd_event = param; 17477 17478 trace("thread: starting\n"); 17479 WaitForSingleObject(wnd_event->start_event, INFINITE); 17480 17481 trace("thread: call PostMessage\n"); 17482 PostMessageA(wnd_event->hwnd, WM_USER, 0, 0); 17483 17484 trace("thread: call PostMessage\n"); 17485 PostMessageA(wnd_event->hwnd, WM_USER+1, 0, 0); 17486 17487 /* this leads to sending an internal message under Wine */ 17488 trace("thread: call SetParent\n"); 17489 SetParent(wnd_event->hwnd, wnd_event->hwnd); 17490 17491 trace("thread: call SendMessage\n"); 17492 SendMessageA(wnd_event->hwnd, WM_USER+2, 0, 0); 17493 17494 trace("thread: call SendMessage\n"); 17495 SendMessageA(wnd_event->hwnd, WM_USER+3, 0, 0); 17496 17497 return 0; 17498 } 17499 17500 static void test_SendMessage_other_thread(int thread_n) 17501 { 17502 DWORD qs_all_input = QS_ALLINPUT & ~QS_RAWINPUT; 17503 HANDLE hthread; 17504 struct wnd_event wnd_event; 17505 DWORD tid, ret; 17506 MSG msg; 17507 17508 wnd_event.start_event = CreateEventA(NULL, 0, 0, NULL); 17509 17510 wnd_event.hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, 17511 100, 100, 200, 200, 0, 0, 0, NULL); 17512 ok(wnd_event.hwnd != 0, "CreateWindowEx failed\n"); 17513 17514 hthread = CreateThread(NULL, 0, thread_n == 1 ? SendMessage_thread_1 : SendMessage_thread_2, &wnd_event, 0, &tid); 17515 ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError()); 17516 CloseHandle(hthread); 17517 17518 flush_events(); 17519 flush_sequence(); 17520 17521 ret = GetQueueStatus(QS_SENDMESSAGE); 17522 ok(ret == 0, "wrong status %08x\n", ret); 17523 17524 SetEvent(wnd_event.start_event); 17525 17526 /* wait for other thread's SendMessage */ 17527 for (;;) 17528 { 17529 ret = GetQueueStatus(QS_SENDMESSAGE); 17530 if (ret == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE)) break; 17531 Sleep(50); 17532 } 17533 17534 ret = GetQueueStatus(QS_SENDMESSAGE|QS_POSTMESSAGE); 17535 ok(ret == MAKELONG(QS_POSTMESSAGE, QS_SENDMESSAGE|QS_POSTMESSAGE), "wrong status %08x\n", ret); 17536 17537 trace("main: call GetMessage\n"); 17538 GetMessageA(&msg, 0, 0, 0); 17539 ok(msg.message == WM_USER, "expected WM_USER, got %04x\n", msg.message); 17540 DispatchMessageA(&msg); 17541 ok_sequence(send_message_1, "SendMessage from other thread 1", thread_n == 2); 17542 17543 /* intentionally yield */ 17544 MsgWaitForMultipleObjects(0, NULL, FALSE, 100, qs_all_input); 17545 17546 trace("main: call SendMessage\n"); 17547 SendMessageA(wnd_event.hwnd, WM_USER+4, 0, 0); 17548 ok_sequence(send_message_2, "SendMessage from other thread 2", FALSE); 17549 17550 ret = GetQueueStatus(QS_SENDMESSAGE|QS_POSTMESSAGE); 17551 ok(ret == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_POSTMESSAGE), "wrong status %08x\n", ret); 17552 17553 trace("main: call PeekMessage\n"); 17554 ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "PeekMessage should not fail\n"); 17555 ok(msg.message == WM_USER+1, "expected WM_USER+1, got %04x\n", msg.message); 17556 DispatchMessageA(&msg); 17557 ok_sequence(send_message_3, "SendMessage from other thread 3", thread_n == 2); 17558 17559 /* intentionally yield */ 17560 MsgWaitForMultipleObjects(0, NULL, FALSE, 100, qs_all_input); 17561 17562 ret = GetQueueStatus(QS_SENDMESSAGE|QS_POSTMESSAGE); 17563 /* FIXME: remove once Wine is fixed */ 17564 todo_wine_if (thread_n == 2) 17565 ok(ret == 0, "wrong status %08x\n", ret); 17566 17567 trace("main: call PeekMessage\n"); 17568 ok(!PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "PeekMessage should fail\n"); 17569 ok_sequence(WmEmptySeq, "SendMessage from other thread 5", thread_n == 2); 17570 17571 ret = GetQueueStatus(QS_SENDMESSAGE|QS_POSTMESSAGE); 17572 ok(ret == 0, "wrong status %08x\n", ret); 17573 17574 trace("main: call DestroyWindow\n"); 17575 DestroyWindow(msg.hwnd); 17576 17577 flush_events(); 17578 flush_sequence(); 17579 } 17580 17581 static LRESULT CALLBACK insendmessage_wnd_proc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ) 17582 { 17583 DWORD flags = InSendMessageEx( NULL ); 17584 BOOL ret; 17585 17586 switch (msg) 17587 { 17588 case WM_USER: 17589 ok( flags == ISMEX_SEND, "wrong flags %x\n", flags ); 17590 ok( InSendMessage(), "InSendMessage returned false\n" ); 17591 ret = ReplyMessage( msg ); 17592 ok( ret, "ReplyMessage failed err %u\n", GetLastError() ); 17593 flags = InSendMessageEx( NULL ); 17594 ok( flags == (ISMEX_SEND | ISMEX_REPLIED), "wrong flags %x\n", flags ); 17595 ok( InSendMessage(), "InSendMessage returned false\n" ); 17596 break; 17597 case WM_USER + 1: 17598 ok( flags == ISMEX_NOTIFY, "wrong flags %x\n", flags ); 17599 ok( InSendMessage(), "InSendMessage returned false\n" ); 17600 ret = ReplyMessage( msg ); 17601 ok( ret, "ReplyMessage failed err %u\n", GetLastError() ); 17602 flags = InSendMessageEx( NULL ); 17603 ok( flags == ISMEX_NOTIFY, "wrong flags %x\n", flags ); 17604 ok( InSendMessage(), "InSendMessage returned false\n" ); 17605 break; 17606 case WM_USER + 2: 17607 ok( flags == ISMEX_CALLBACK, "wrong flags %x\n", flags ); 17608 ok( InSendMessage(), "InSendMessage returned false\n" ); 17609 ret = ReplyMessage( msg ); 17610 ok( ret, "ReplyMessage failed err %u\n", GetLastError() ); 17611 flags = InSendMessageEx( NULL ); 17612 ok( flags == (ISMEX_CALLBACK | ISMEX_REPLIED) || flags == ISMEX_SEND, "wrong flags %x\n", flags ); 17613 ok( InSendMessage(), "InSendMessage returned false\n" ); 17614 break; 17615 case WM_USER + 3: 17616 ok( flags == ISMEX_NOSEND, "wrong flags %x\n", flags ); 17617 ok( !InSendMessage(), "InSendMessage returned true\n" ); 17618 ret = ReplyMessage( msg ); 17619 ok( !ret, "ReplyMessage succeeded\n" ); 17620 break; 17621 } 17622 17623 return DefWindowProcA( hwnd, msg, wp, lp ); 17624 } 17625 17626 static void CALLBACK msg_callback( HWND hwnd, UINT msg, ULONG_PTR arg, LRESULT result ) 17627 { 17628 ok( msg == WM_USER + 2, "wrong msg %x\n", msg ); 17629 ok( result == WM_USER + 2, "wrong result %lx\n", result ); 17630 } 17631 17632 static DWORD WINAPI send_message_thread( void *arg ) 17633 { 17634 HWND win = arg; 17635 17636 SendMessageA( win, WM_USER, 0, 0 ); 17637 SendNotifyMessageA( win, WM_USER + 1, 0, 0 ); 17638 SendMessageCallbackA( win, WM_USER + 2, 0, 0, msg_callback, 0 ); 17639 PostMessageA( win, WM_USER + 3, 0, 0 ); 17640 PostMessageA( win, WM_QUIT, 0, 0 ); 17641 return 0; 17642 } 17643 17644 static void test_InSendMessage(void) 17645 { 17646 WNDCLASSA cls; 17647 HWND win; 17648 MSG msg; 17649 HANDLE thread; 17650 DWORD tid; 17651 17652 memset(&cls, 0, sizeof(cls)); 17653 cls.lpfnWndProc = insendmessage_wnd_proc; 17654 cls.hInstance = GetModuleHandleA(NULL); 17655 cls.lpszClassName = "InSendMessage_test"; 17656 RegisterClassA(&cls); 17657 17658 win = CreateWindowA( "InSendMessage_test", NULL, 0, 0, 0, 0, 0, NULL, 0, NULL, 0 ); 17659 ok( win != NULL, "CreateWindow failed: %d\n", GetLastError() ); 17660 17661 thread = CreateThread( NULL, 0, send_message_thread, win, 0, &tid ); 17662 ok( thread != NULL, "CreateThread failed: %d\n", GetLastError() ); 17663 17664 while (GetMessageA(&msg, NULL, 0, 0)) DispatchMessageA( &msg ); 17665 17666 ok( WaitForSingleObject( thread, 30000 ) == WAIT_OBJECT_0, "WaitForSingleObject failed\n" ); 17667 CloseHandle( thread ); 17668 17669 DestroyWindow( win ); 17670 UnregisterClassA( "InSendMessage_test", GetModuleHandleA(NULL) ); 17671 } 17672 17673 static const struct message DoubleSetCaptureSeq[] = 17674 { 17675 { WM_CAPTURECHANGED, sent }, 17676 { 0 } 17677 }; 17678 17679 static void test_DoubleSetCapture(void) 17680 { 17681 HWND hwnd; 17682 17683 hwnd = CreateWindowExA(0, "TestWindowClass", "Test DoubleSetCapture", 17684 WS_OVERLAPPEDWINDOW | WS_VISIBLE, 17685 100, 100, 200, 200, 0, 0, 0, NULL); 17686 ok (hwnd != 0, "Failed to create overlapped window\n"); 17687 17688 ShowWindow( hwnd, SW_SHOW ); 17689 UpdateWindow( hwnd ); 17690 flush_events(); 17691 flush_sequence(); 17692 17693 SetCapture( hwnd ); 17694 SetCapture( hwnd ); 17695 ok_sequence(DoubleSetCaptureSeq, "SetCapture( hwnd ) twice", FALSE); 17696 17697 DestroyWindow(hwnd); 17698 } 17699 17700 static const struct message WmRestoreMinimizedSeq[] = 17701 { 17702 { HCBT_ACTIVATE, hook }, 17703 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE }, 17704 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 17705 { WM_ACTIVATEAPP, sent|wparam, 1 }, 17706 { WM_NCACTIVATE, sent|wparam, 0x200001 }, 17707 { WM_GETTEXT, sent|defwinproc|optional }, 17708 { WM_ACTIVATE, sent|wparam, 0x200001 }, /* Note that activate messages are after WM_WINDOWPOSCHANGED and before WM_SYSCOMMAND */ 17709 { HCBT_KEYSKIPPED, hook|optional }, 17710 { WM_SYSKEYUP, sent|optional }, 17711 { WM_SYSCOMMAND, sent|wparam, SC_RESTORE }, 17712 { HCBT_SYSCOMMAND, hook|wparam, SC_RESTORE }, 17713 { HCBT_SYSCOMMAND, hook|wparam|optional, SC_RESTORE }, 17714 { HCBT_MINMAX, hook }, 17715 { HCBT_MINMAX, hook|optional }, 17716 { WM_QUERYOPEN, sent|defwinproc }, 17717 { WM_QUERYOPEN, sent|optional }, 17718 { WM_GETTEXT, sent|defwinproc|optional }, 17719 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 17720 { WM_GETMINMAXINFO, sent|defwinproc }, 17721 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, 17722 { WM_NCPAINT, sent|wparam|defwinproc|optional, 1 }, 17723 { WM_GETTEXT, sent|defwinproc|optional }, 17724 { WM_ERASEBKGND, sent|defwinproc }, 17725 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 17726 { WM_MOVE, sent|defwinproc }, 17727 { WM_SIZE, sent|defwinproc }, 17728 { WM_NCCALCSIZE, sent|wparam|defwinproc|optional, 1 }, 17729 { WM_NCPAINT, sent|wparam|defwinproc|optional, 1 }, 17730 { WM_ERASEBKGND, sent|defwinproc|optional }, 17731 { HCBT_SETFOCUS, hook }, 17732 { WM_SETFOCUS, sent|defwinproc }, 17733 { WM_ACTIVATE, sent|wparam|defwinproc, 1 }, 17734 { WM_PAINT, sent| optional }, 17735 { WM_SETFOCUS, sent|defwinproc|optional }, 17736 { HCBT_KEYSKIPPED, hook|optional }, 17737 { WM_KEYUP, sent|optional }, 17738 { HCBT_KEYSKIPPED, hook|optional }, 17739 { WM_SYSKEYUP, sent|optional }, 17740 { HCBT_KEYSKIPPED, hook|optional }, 17741 { WM_KEYUP, sent|optional }, 17742 { WM_PAINT, sent| optional }, 17743 { 0 } 17744 }; 17745 17746 static void test_restore_messages(void) 17747 { 17748 INPUT ip = {0}; 17749 HWND hwnd; 17750 INT i; 17751 17752 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 17753 100, 200, 200, 0, 0, 0, NULL); 17754 ok (hwnd != 0, "Failed to create overlapped window\n"); 17755 SetForegroundWindow(hwnd); 17756 ShowWindow(hwnd, SW_MINIMIZE); 17757 flush_events(); 17758 flush_sequence(); 17759 17760 for (i = 0; i < 5; i++) 17761 { 17762 /* Send Alt+Tab to restore test window from minimized state */ 17763 ip.type = INPUT_KEYBOARD; 17764 ip.ki.wVk = VK_MENU; 17765 SendInput(1, &ip, sizeof(INPUT)); 17766 ip.ki.wVk = VK_TAB; 17767 SendInput(1, &ip, sizeof(INPUT)); 17768 ip.ki.wVk = VK_MENU; 17769 ip.ki.dwFlags = KEYEVENTF_KEYUP; 17770 SendInput(1, &ip, sizeof(INPUT)); 17771 ip.ki.wVk = VK_TAB; 17772 ip.ki.dwFlags = KEYEVENTF_KEYUP; 17773 SendInput(1, &ip, sizeof(INPUT)); 17774 flush_events(); 17775 if (!IsIconic(hwnd)) 17776 break; 17777 } 17778 17779 if (IsIconic(hwnd)) 17780 { 17781 skip("Alt+Tab failed to bring up test window.\n"); 17782 goto done; 17783 } 17784 ok_sequence(WmRestoreMinimizedSeq, "Restore minimized window", TRUE); 17785 17786 done: 17787 DestroyWindow(hwnd); 17788 } 17789 17790 static void test_invalid_window(void) 17791 { 17792 MSG msg; 17793 BOOL ret; 17794 17795 SetLastError(0xdeadbeef); 17796 ret = GetMessageA(&msg, (HWND)0xdeadbeef, 0, 0); 17797 ok(ret == -1, "wrong ret %d\n", ret); 17798 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError()); 17799 17800 SetLastError(0xdeadbeef); 17801 ret = PeekMessageA(&msg, (HWND)0xdeadbeef, 0, 0, PM_REMOVE); 17802 ok(!ret, "wrong ret %d\n", ret); 17803 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError()); 17804 } 17805 17806 static void init_funcs(void) 17807 { 17808 HMODULE hKernel32 = GetModuleHandleA("kernel32.dll"); 17809 17810 #define X(f) p##f = (void*)GetProcAddress(hKernel32, #f) 17811 X(ActivateActCtx); 17812 X(CreateActCtxW); 17813 X(DeactivateActCtx); 17814 X(GetCurrentActCtx); 17815 X(QueryActCtxW); 17816 X(ReleaseActCtx); 17817 #undef X 17818 } 17819 17820 #ifndef __REACTOS__ 17821 START_TEST(msg) 17822 { 17823 char **test_argv; 17824 BOOL ret; 17825 BOOL (WINAPI *pIsWinEventHookInstalled)(DWORD)= 0;/*GetProcAddress(user32, "IsWinEventHookInstalled");*/ 17826 HMODULE hModuleImm32; 17827 BOOL (WINAPI *pImmDisableIME)(DWORD); 17828 int argc; 17829 17830 init_funcs(); 17831 17832 argc = winetest_get_mainargs( &test_argv ); 17833 if (argc >= 3) 17834 { 17835 unsigned int arg; 17836 /* Child process. */ 17837 sscanf (test_argv[2], "%d", (unsigned int *) &arg); 17838 do_wait_idle_child( arg ); 17839 return; 17840 } 17841 17842 InitializeCriticalSection( &sequence_cs ); 17843 init_procs(); 17844 17845 hModuleImm32 = LoadLibraryA("imm32.dll"); 17846 if (hModuleImm32) { 17847 pImmDisableIME = (void *)GetProcAddress(hModuleImm32, "ImmDisableIME"); 17848 if (pImmDisableIME) 17849 pImmDisableIME(0); 17850 } 17851 pImmDisableIME = NULL; 17852 FreeLibrary(hModuleImm32); 17853 17854 if (!RegisterWindowClasses()) assert(0); 17855 17856 if (pSetWinEventHook) 17857 { 17858 hEvent_hook = pSetWinEventHook(EVENT_MIN, EVENT_MAX, 17859 GetModuleHandleA(0), win_event_proc, 17860 0, GetCurrentThreadId(), 17861 WINEVENT_INCONTEXT); 17862 if (pIsWinEventHookInstalled && hEvent_hook) 17863 { 17864 UINT event; 17865 for (event = EVENT_MIN; event <= EVENT_MAX; event++) 17866 ok(pIsWinEventHookInstalled(event), "IsWinEventHookInstalled(%u) failed\n", event); 17867 } 17868 } 17869 if (!hEvent_hook) win_skip( "no win event hook support\n" ); 17870 17871 cbt_hook_thread_id = GetCurrentThreadId(); 17872 hCBT_hook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId()); 17873 if (!hCBT_hook) win_skip( "cannot set global hook, will skip hook tests\n" ); 17874 17875 test_winevents(); 17876 17877 /* Fix message sequences before removing 4 lines below */ 17878 if (pUnhookWinEvent && hEvent_hook) 17879 { 17880 ret = pUnhookWinEvent(hEvent_hook); 17881 ok( ret, "UnhookWinEvent error %d\n", GetLastError()); 17882 pUnhookWinEvent = 0; 17883 } 17884 hEvent_hook = 0; 17885 17886 test_SendMessage_other_thread(1); 17887 test_SendMessage_other_thread(2); 17888 test_InSendMessage(); 17889 test_SetFocus(); 17890 test_SetParent(); 17891 test_PostMessage(); 17892 test_broadcast(); 17893 test_ShowWindow(); 17894 test_PeekMessage(); 17895 test_PeekMessage2(); 17896 test_PeekMessage3(); 17897 test_WaitForInputIdle( test_argv[0] ); 17898 test_scrollwindowex(); 17899 test_messages(); 17900 test_setwindowpos(); 17901 test_showwindow(); 17902 test_recursive_activation(); 17903 invisible_parent_tests(); 17904 test_mdi_messages(); 17905 test_button_messages(); 17906 test_button_bm_get_set_image(); 17907 test_autoradio_BM_CLICK(); 17908 test_autoradio_kbd_move(); 17909 test_static_messages(); 17910 test_listbox_messages(); 17911 test_combobox_messages(); 17912 test_wmime_keydown_message(); 17913 test_paint_messages(); 17914 test_interthread_messages(); 17915 test_message_conversion(); 17916 test_accelerators(); 17917 test_timers(); 17918 test_timers_no_wnd(); 17919 test_timers_exceptions(); 17920 if (hCBT_hook) 17921 { 17922 test_set_hook(); 17923 test_recursive_hook(); 17924 } 17925 test_DestroyWindow(); 17926 test_DispatchMessage(); 17927 test_SendMessageTimeout(); 17928 test_edit_messages(); 17929 test_quit_message(); 17930 test_notify_message(); 17931 test_SetActiveWindow(); 17932 test_restore_messages(); 17933 test_invalid_window(); 17934 17935 if (!pTrackMouseEvent) 17936 win_skip("TrackMouseEvent is not available\n"); 17937 else 17938 test_TrackMouseEvent(); 17939 17940 test_SetWindowRgn(); 17941 test_sys_menu(); 17942 test_dialog_messages(); 17943 test_EndDialog(); 17944 test_nullCallback(); 17945 test_dbcs_wm_char(); 17946 test_unicode_wm_char(); 17947 test_menu_messages(); 17948 test_paintingloop(); 17949 test_defwinproc(); 17950 test_desktop_winproc(); 17951 test_clipboard_viewers(); 17952 test_keyflags(); 17953 test_hotkey(); 17954 test_layered_window(); 17955 test_TrackPopupMenu(); 17956 test_TrackPopupMenuEmpty(); 17957 test_DoubleSetCapture(); 17958 /* keep it the last test, under Windows it tends to break the tests 17959 * which rely on active/foreground windows being correct. 17960 */ 17961 test_SetForegroundWindow(); 17962 17963 UnhookWindowsHookEx(hCBT_hook); 17964 if (pUnhookWinEvent && hEvent_hook) 17965 { 17966 ret = pUnhookWinEvent(hEvent_hook); 17967 ok( ret, "UnhookWinEvent error %d\n", GetLastError()); 17968 SetLastError(0xdeadbeef); 17969 ok(!pUnhookWinEvent(hEvent_hook), "UnhookWinEvent succeeded\n"); 17970 ok(GetLastError() == ERROR_INVALID_HANDLE || /* Win2k */ 17971 GetLastError() == 0xdeadbeef, /* Win9x */ 17972 "unexpected error %d\n", GetLastError()); 17973 } 17974 DeleteCriticalSection( &sequence_cs ); 17975 } 17976 #endif /* __REACTOS__ */ 17977 17978 static void init_tests() 17979 { 17980 HMODULE hModuleImm32; 17981 BOOL (WINAPI *pImmDisableIME)(DWORD); 17982 17983 init_funcs(); 17984 17985 InitializeCriticalSection( &sequence_cs ); 17986 init_procs(); 17987 17988 hModuleImm32 = LoadLibraryA("imm32.dll"); 17989 if (hModuleImm32) { 17990 pImmDisableIME = (void *)GetProcAddress(hModuleImm32, "ImmDisableIME"); 17991 if (pImmDisableIME) 17992 pImmDisableIME(0); 17993 } 17994 pImmDisableIME = NULL; 17995 FreeLibrary(hModuleImm32); 17996 17997 if (!RegisterWindowClasses()) assert(0); 17998 17999 cbt_hook_thread_id = GetCurrentThreadId(); 18000 hCBT_hook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId()); 18001 if (!hCBT_hook) win_skip( "cannot set global hook, will skip hook tests\n" ); 18002 } 18003 18004 static void cleanup_tests() 18005 { 18006 BOOL ret; 18007 UnhookWindowsHookEx(hCBT_hook); 18008 if (pUnhookWinEvent && hEvent_hook) 18009 { 18010 ret = pUnhookWinEvent(hEvent_hook); 18011 ok( ret, "UnhookWinEvent error %d\n", GetLastError()); 18012 SetLastError(0xdeadbeef); 18013 ok(!pUnhookWinEvent(hEvent_hook), "UnhookWinEvent succeeded\n"); 18014 ok(GetLastError() == ERROR_INVALID_HANDLE || /* Win2k */ 18015 GetLastError() == 0xdeadbeef, /* Win9x */ 18016 "unexpected error %d\n", GetLastError()); 18017 } 18018 DeleteCriticalSection( &sequence_cs ); 18019 18020 } 18021 18022 START_TEST(msg_queue) 18023 { 18024 int argc; 18025 char **test_argv; 18026 argc = winetest_get_mainargs( &test_argv ); 18027 if (argc >= 3) 18028 { 18029 unsigned int arg; 18030 /* Child process. */ 18031 sscanf (test_argv[2], "%d", (unsigned int *) &arg); 18032 do_wait_idle_child( arg ); 18033 return; 18034 } 18035 18036 init_tests(); 18037 test_SendMessage_other_thread(1); 18038 test_SendMessage_other_thread(2); 18039 test_InSendMessage(); 18040 test_PostMessage(); 18041 test_broadcast(); 18042 test_PeekMessage(); 18043 test_PeekMessage2(); 18044 test_PeekMessage3(); 18045 test_interthread_messages(); 18046 test_DispatchMessage(); 18047 test_SendMessageTimeout(); 18048 test_quit_message(); 18049 test_notify_message(); 18050 test_WaitForInputIdle( test_argv[0] ); 18051 test_DestroyWindow(); 18052 cleanup_tests(); 18053 } 18054 18055 START_TEST(msg_messages) 18056 { 18057 init_tests(); 18058 test_message_conversion(); 18059 test_messages(); 18060 test_wmime_keydown_message(); 18061 test_nullCallback(); 18062 test_dbcs_wm_char(); 18063 test_unicode_wm_char(); 18064 test_defwinproc(); 18065 test_desktop_winproc(); 18066 cleanup_tests(); 18067 } 18068 18069 START_TEST(msg_focus) 18070 { 18071 init_tests(); 18072 18073 test_SetFocus(); 18074 18075 /* HACK: For some reason the tests fail on Windows if run consecutively. 18076 * Putting these in between helps, and is essentially what happens in the 18077 * "normal" msg test. */ 18078 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); 18079 flush_events(); 18080 18081 test_SetActiveWindow(); 18082 18083 /* HACK */ 18084 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); 18085 flush_events(); 18086 18087 test_restore_messages(); 18088 test_invalid_window(); 18089 18090 test_DoubleSetCapture(); 18091 18092 /* keep it the last test, under Windows it tends to break the tests 18093 * which rely on active/foreground windows being correct. 18094 */ 18095 test_SetForegroundWindow(); 18096 cleanup_tests(); 18097 } 18098 18099 START_TEST(msg_winpos) 18100 { 18101 init_tests(); 18102 test_SetParent(); 18103 test_ShowWindow(); 18104 test_setwindowpos(); 18105 test_showwindow(); 18106 test_recursive_activation(); 18107 test_SetWindowRgn(); 18108 invisible_parent_tests(); 18109 cleanup_tests(); 18110 } 18111 18112 START_TEST(msg_paint) 18113 { 18114 init_tests(); 18115 test_scrollwindowex(); 18116 test_paint_messages(); 18117 #ifdef __REACTOS__ 18118 if (!winetest_interactive && 18119 !strcmp(winetest_platform, "windows")) 18120 { 18121 skip("ROSTESTS-185: Skipping user32_winetest:msg_paint test_paintingloop because it hangs on WHS-Testbot. Set winetest_interactive to run it anyway.\n"); 18122 } 18123 else 18124 #endif 18125 test_paintingloop(); 18126 cleanup_tests(); 18127 } 18128 18129 START_TEST(msg_input) 18130 { 18131 init_tests(); 18132 test_accelerators(); 18133 if (!pTrackMouseEvent) 18134 win_skip("TrackMouseEvent is not available\n"); 18135 else 18136 test_TrackMouseEvent(); 18137 18138 test_keyflags(); 18139 test_hotkey(); 18140 cleanup_tests(); 18141 } 18142 18143 START_TEST(msg_timer) 18144 { 18145 init_tests(); 18146 test_timers(); 18147 test_timers_no_wnd(); 18148 test_timers_exceptions(); 18149 cleanup_tests(); 18150 } 18151 18152 typedef BOOL (WINAPI *IS_WINEVENT_HOOK_INSTALLED)(DWORD); 18153 18154 START_TEST(msg_hook) 18155 { 18156 // HMODULE user32 = GetModuleHandleA("user32.dll"); 18157 // IS_WINEVENT_HOOK_INSTALLED pIsWinEventHookInstalled = (IS_WINEVENT_HOOK_INSTALLED)GetProcAddress(user32, "IsWinEventHookInstalled"); 18158 BOOL (WINAPI *pIsWinEventHookInstalled)(DWORD)= 0;/*GetProcAddress(user32, "IsWinEventHookInstalled");*/ 18159 18160 init_tests(); 18161 18162 if (pSetWinEventHook) 18163 { 18164 hEvent_hook = pSetWinEventHook(EVENT_MIN, EVENT_MAX, 18165 GetModuleHandleA(0), win_event_proc, 18166 0, GetCurrentThreadId(), 18167 WINEVENT_INCONTEXT); 18168 if (pIsWinEventHookInstalled && hEvent_hook) 18169 { 18170 UINT event; 18171 for (event = EVENT_MIN; event <= EVENT_MAX; event++) 18172 ok(pIsWinEventHookInstalled(event), "IsWinEventHookInstalled(%u) failed\n", event); 18173 } 18174 } 18175 if (!hEvent_hook) win_skip( "no win event hook support\n" ); 18176 18177 test_winevents(); 18178 18179 /* Fix message sequences before removing 4 lines below */ 18180 if (pUnhookWinEvent && hEvent_hook) 18181 { 18182 BOOL ret; 18183 ret = pUnhookWinEvent(hEvent_hook); 18184 ok( ret, "UnhookWinEvent error %d\n", GetLastError()); 18185 pUnhookWinEvent = 0; 18186 } 18187 hEvent_hook = 0; 18188 if (hCBT_hook) 18189 { 18190 test_set_hook(); 18191 test_recursive_hook(); 18192 } 18193 cleanup_tests(); 18194 } 18195 18196 START_TEST(msg_menu) 18197 { 18198 init_tests(); 18199 test_sys_menu(); 18200 test_menu_messages(); 18201 test_TrackPopupMenu(); 18202 test_TrackPopupMenuEmpty(); 18203 cleanup_tests(); 18204 } 18205 18206 START_TEST(msg_mdi) 18207 { 18208 init_tests(); 18209 test_mdi_messages(); 18210 cleanup_tests(); 18211 } 18212 18213 START_TEST(msg_controls) 18214 { 18215 init_tests(); 18216 test_button_messages(); 18217 test_button_bm_get_set_image(); 18218 test_autoradio_BM_CLICK(); 18219 test_autoradio_kbd_move(); 18220 test_static_messages(); 18221 test_listbox_messages(); 18222 test_combobox_messages(); 18223 test_edit_messages(); 18224 cleanup_tests(); 18225 } 18226 18227 START_TEST(msg_layered_window) 18228 { 18229 init_tests(); 18230 test_layered_window(); 18231 cleanup_tests(); 18232 } 18233 18234 START_TEST(msg_dialog) 18235 { 18236 init_tests(); 18237 test_dialog_messages(); 18238 test_EndDialog(); 18239 cleanup_tests(); 18240 } 18241 18242 START_TEST(msg_clipboard) 18243 { 18244 init_tests(); 18245 test_clipboard_viewers(); 18246 cleanup_tests(); 18247 } 18248