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 BOOL test_context_menu; 116 static HWINEVENTHOOK hEvent_hook; 117 static HHOOK hKBD_hook; 118 static HHOOK hCBT_hook; 119 static DWORD cbt_hook_thread_id; 120 121 static const WCHAR testWindowClassW[] = 122 { 'T','e','s','t','W','i','n','d','o','w','C','l','a','s','s','W',0 }; 123 124 static LRESULT WINAPI ParentMsgCheckProcA(HWND, UINT, WPARAM, LPARAM); 125 126 /* 127 FIXME: add tests for these 128 Window Edge Styles (Win31/Win95/98 look), in order of precedence: 129 WS_EX_DLGMODALFRAME: double border, WS_CAPTION allowed 130 WS_THICKFRAME: thick border 131 WS_DLGFRAME: double border, WS_CAPTION not allowed (but possibly shown anyway) 132 WS_BORDER (default for overlapped windows): single black border 133 none (default for child (and popup?) windows): no border 134 */ 135 136 typedef enum { 137 sent=0x1, 138 posted=0x2, 139 parent=0x4, 140 wparam=0x8, 141 lparam=0x10, 142 defwinproc=0x20, 143 beginpaint=0x40, 144 optional=0x80, 145 hook=0x100, 146 winevent_hook=0x200, 147 kbd_hook=0x400 148 } msg_flags_t; 149 150 struct message { 151 UINT message; /* the WM_* code */ 152 msg_flags_t flags; /* message props */ 153 WPARAM wParam; /* expected value of wParam */ 154 LPARAM lParam; /* expected value of lParam */ 155 WPARAM wp_mask; /* mask for wParam checks */ 156 LPARAM lp_mask; /* mask for lParam checks */ 157 }; 158 159 struct recvd_message { 160 UINT message; /* the WM_* code */ 161 msg_flags_t flags; /* message props */ 162 HWND hwnd; /* window that received the message */ 163 WPARAM wParam; /* expected value of wParam */ 164 LPARAM lParam; /* expected value of lParam */ 165 int line; /* source line where logged */ 166 const char *descr; /* description for trace output */ 167 char output[512]; /* trace output */ 168 }; 169 170 /* Empty message sequence */ 171 static const struct message WmEmptySeq[] = 172 { 173 { 0 } 174 }; 175 /* CreateWindow (for overlapped window, not initially visible) (16/32) */ 176 static const struct message WmCreateOverlappedSeq[] = { 177 { HCBT_CREATEWND, hook }, 178 { WM_GETMINMAXINFO, sent }, 179 { WM_NCCREATE, sent }, 180 { WM_NCCALCSIZE, sent|wparam, 0 }, 181 { 0x0093, sent|defwinproc|optional }, 182 { 0x0094, sent|defwinproc|optional }, 183 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, 184 { WM_CREATE, sent }, 185 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 186 { 0 } 187 }; 188 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE) 189 * for a not visible overlapped window. 190 */ 191 static const struct message WmSWP_ShowOverlappedSeq[] = { 192 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 193 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 194 { WM_NCPAINT, sent|wparam|optional, 1 }, 195 { WM_GETTEXT, sent|defwinproc|optional }, 196 { WM_ERASEBKGND, sent|optional }, 197 { HCBT_ACTIVATE, hook }, 198 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 199 { WM_NOTIFYFORMAT, sent|optional }, 200 { WM_QUERYUISTATE, sent|optional }, 201 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 202 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* Win9x: SWP_NOSENDCHANGING */ 203 { WM_ACTIVATEAPP, sent|wparam, 1 }, 204 { WM_NCACTIVATE, sent }, 205 { WM_GETTEXT, sent|defwinproc|optional }, 206 { WM_ACTIVATE, sent|wparam, 1 }, 207 { HCBT_SETFOCUS, hook }, 208 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 209 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 210 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 211 { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, 212 { WM_GETTEXT, sent|optional }, 213 { WM_NCPAINT, sent|wparam|optional, 1 }, 214 { WM_GETTEXT, sent|defwinproc|optional }, 215 { WM_ERASEBKGND, sent|optional }, 216 /* Win9x adds SWP_NOZORDER below */ 217 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 218 { WM_GETTEXT, sent|optional }, 219 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, 220 { WM_NCPAINT, sent|wparam|optional, 1 }, 221 { WM_ERASEBKGND, sent|optional }, 222 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 223 { WM_SYNCPAINT, sent|optional }, 224 { WM_GETTITLEBARINFOEX, sent|optional }, 225 { WM_PAINT, sent|optional }, 226 { WM_NCPAINT, sent|beginpaint|optional }, 227 { WM_GETTEXT, sent|beginpaint|defwinproc|optional }, 228 { WM_ERASEBKGND, sent|beginpaint|optional }, 229 { 0 } 230 }; 231 /* SetWindowPos(SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE) 232 * for a visible overlapped window. 233 */ 234 static const struct message WmSWP_HideOverlappedSeq[] = { 235 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 236 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 237 { HCBT_ACTIVATE, hook|optional }, 238 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 239 { WM_ACTIVATEAPP, sent|wparam|optional, 1 }, 240 { WM_NCACTIVATE, sent|optional }, 241 { WM_ACTIVATE, sent|optional }, 242 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 243 { 0 } 244 }; 245 246 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE) 247 * for a visible overlapped window. 248 */ 249 static const struct message WmSWP_ResizeSeq[] = { 250 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE }, 251 { WM_GETMINMAXINFO, sent|defwinproc }, 252 { WM_NCCALCSIZE, sent|wparam|optional, TRUE }, 253 { WM_NCPAINT, sent|optional }, 254 { WM_GETTEXT, sent|defwinproc|optional }, 255 { WM_ERASEBKGND, sent|optional }, 256 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOCLIENTMOVE }, 257 { WM_SIZE, sent|defwinproc|optional }, 258 { WM_NCCALCSIZE, sent|wparam|optional, TRUE }, 259 { WM_NCPAINT, sent|optional }, 260 { WM_GETTEXT, sent|defwinproc|optional }, 261 { WM_ERASEBKGND, sent|optional }, 262 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 263 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP sends a duplicate */ 264 { 0 } 265 }; 266 267 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE) 268 * for a visible popup window. 269 */ 270 static const struct message WmSWP_ResizePopupSeq[] = { 271 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE }, 272 { WM_GETMINMAXINFO, sent|defwinproc|optional }, /* Win9x */ 273 { WM_NCCALCSIZE, sent|wparam|optional, TRUE }, 274 { WM_NCPAINT, sent|optional }, 275 { WM_GETTEXT, sent|defwinproc|optional }, 276 { WM_ERASEBKGND, sent|optional }, 277 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOCLIENTMOVE }, 278 { WM_SIZE, sent|defwinproc|wparam|optional, SIZE_RESTORED }, 279 { WM_NCCALCSIZE, sent|wparam|optional, TRUE }, 280 { WM_NCPAINT, sent|optional }, 281 { WM_GETTEXT, sent|defwinproc|optional }, 282 { WM_ERASEBKGND, sent|optional }, 283 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 284 { 0 } 285 }; 286 287 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE) 288 * for a visible overlapped window. 289 */ 290 static const struct message WmSWP_MoveSeq[] = { 291 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOSIZE }, 292 { WM_NCPAINT, sent|optional }, 293 { WM_GETTEXT, sent|defwinproc|optional }, 294 { WM_ERASEBKGND, sent|optional }, 295 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOCLIENTSIZE }, 296 { WM_MOVE, sent|defwinproc|wparam, 0 }, 297 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 298 { 0 } 299 }; 300 /* Resize with SetWindowPos(SWP_NOZORDER) 301 * for a visible overlapped window 302 * SWP_NOZORDER is stripped by the logging code 303 */ 304 static const struct message WmSWP_ResizeNoZOrder[] = { 305 { WM_WINDOWPOSCHANGING, sent|wparam, /*SWP_NOZORDER|*/SWP_NOACTIVATE }, 306 { WM_GETMINMAXINFO, sent|defwinproc }, 307 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, 308 { WM_NCPAINT, sent|optional }, 309 { WM_GETTEXT, sent|defwinproc|optional }, 310 { WM_ERASEBKGND, sent|optional }, 311 { WM_WINDOWPOSCHANGED, sent|wparam|optional, /*SWP_NOZORDER|*/SWP_NOACTIVATE, 0, 312 SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOCLIENTSIZE }, 313 { WM_MOVE, sent|defwinproc|optional }, 314 { WM_SIZE, sent|defwinproc|optional }, 315 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* Win9x doesn't send it */ 316 { WM_NCPAINT, sent|optional }, /* Win9x doesn't send it */ 317 { WM_GETTEXT, sent|defwinproc|optional }, /* Win9x doesn't send it */ 318 { WM_ERASEBKGND, sent|optional }, /* Win9x doesn't send it */ 319 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 320 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 321 { 0 } 322 }; 323 324 /* Switch visible mdi children */ 325 static const struct message WmSwitchChild[] = { 326 /* Switch MDI child */ 327 { WM_MDIACTIVATE, sent },/* in the MDI client */ 328 { WM_WINDOWPOSCHANGING, sent|wparam,SWP_NOSIZE|SWP_NOMOVE },/* in the 1st MDI child */ 329 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 330 { WM_CHILDACTIVATE, sent },/* in the 1st MDI child */ 331 /* Deactivate 2nd MDI child */ 332 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 2nd MDI child */ 333 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 2nd MDI child */ 334 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 335 /* Preparing for maximize and maximize the 1st MDI child */ 336 { WM_GETMINMAXINFO, sent|defwinproc }, /* in the 1st MDI child */ 337 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_STATECHANGED }, /* in the 1st MDI child */ 338 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, /* in the 1st MDI child */ 339 { WM_CHILDACTIVATE, sent|defwinproc }, /* in the 1st MDI child */ 340 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, /* in the 1st MDI child */ 341 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, /* in the 1st MDI child */ 342 /* Lock redraw 2nd MDI child */ 343 { WM_SETREDRAW, sent|wparam|defwinproc, 0 }, /* in the 2nd MDI child */ 344 { HCBT_MINMAX, hook|lparam, 0, SW_NORMALNA }, 345 /* Restore 2nd MDI child */ 346 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_STATECHANGED },/* in the 2nd MDI child */ 347 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },/* in the 2nd MDI child */ 348 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, /* in the 2nd MDI child */ 349 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, /* in the 2nd MDI child */ 350 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, /* in the 2nd MDI child */ 351 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* in the 2nd MDI child */ 352 /* Redraw 2nd MDI child */ 353 { WM_SETREDRAW, sent|wparam|defwinproc, 1 },/* in the 2nd MDI child */ 354 /* Redraw MDI frame */ 355 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE },/* in MDI frame */ 356 { WM_NCCALCSIZE, sent|wparam, 1 },/* in MDI frame */ 357 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE}, /* in MDI frame */ 358 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* in MDI frame */ 359 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* in the 1st MDI child */ 360 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, /* in the 1st MDI child */ 361 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, /* in the 1st MDI child */ 362 { HCBT_SETFOCUS, hook }, 363 { WM_KILLFOCUS, sent|defwinproc }, /* in the 2nd MDI child */ 364 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 },/* in the 1st MDI child */ 365 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 366 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 367 { WM_SETFOCUS, sent },/* in the MDI client */ 368 { HCBT_SETFOCUS, hook }, 369 { WM_KILLFOCUS, sent },/* in the MDI client */ 370 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 371 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, /* in the 1st MDI child */ 372 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 373 { WM_SETFOCUS, sent|defwinproc }, /* in the 1st MDI child */ 374 { WM_MDIACTIVATE, sent|defwinproc },/* in the 1st MDI child */ 375 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, /* in the 1st MDI child */ 376 { 0 } 377 }; 378 379 /* Switch visible not maximized mdi children */ 380 static const struct message WmSwitchNotMaximizedChild[] = { 381 /* Switch not maximized MDI child */ 382 { WM_MDIACTIVATE, sent },/* in the MDI client */ 383 { WM_WINDOWPOSCHANGING, sent|wparam,SWP_NOSIZE|SWP_NOMOVE },/* in the 2nd MDI child */ 384 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 385 { WM_CHILDACTIVATE, sent },/* in the 2nd MDI child */ 386 /* Deactivate 1st MDI child */ 387 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 1st MDI child */ 388 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 1st MDI child */ 389 /* Activate 2nd MDI child */ 390 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE}, /* in the 2nd MDI child */ 391 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, /* in the 2nd MDI child */ 392 { HCBT_SETFOCUS, hook }, /* in the 1st MDI child */ 393 { WM_KILLFOCUS, sent|defwinproc }, /* in the 1st MDI child */ 394 { WM_IME_SETCONTEXT, sent|defwinproc|optional }, /* in the 1st MDI child */ 395 { WM_IME_SETCONTEXT, sent|optional }, /* in the MDI client */ 396 { WM_SETFOCUS, sent, 0 }, /* in the MDI client */ 397 { HCBT_SETFOCUS, hook }, 398 { WM_KILLFOCUS, sent }, /* in the MDI client */ 399 { WM_IME_SETCONTEXT, sent|optional }, /* in the MDI client */ 400 { WM_IME_SETCONTEXT, sent|defwinproc|optional }, /* in the 1st MDI child */ 401 { WM_SETFOCUS, sent|defwinproc }, /* in the 2nd MDI child */ 402 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 2nd MDI child */ 403 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE}, /* in the 2nd MDI child */ 404 { 0 } 405 }; 406 407 408 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE| 409 SWP_NOZORDER|SWP_FRAMECHANGED) 410 * for a visible overlapped window with WS_CLIPCHILDREN style set. 411 */ 412 static const struct message WmSWP_FrameChanged_clip[] = { 413 { WM_WINDOWPOSCHANGING, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED }, 414 { WM_NCCALCSIZE, sent|wparam|parent, 1 }, 415 { WM_NCPAINT, sent|parent|optional }, /* wparam != 1 */ 416 { WM_GETTEXT, sent|parent|defwinproc|optional }, 417 { WM_ERASEBKGND, sent|parent|optional }, /* FIXME: remove optional once Wine is fixed */ 418 { WM_NCPAINT, sent }, /* wparam != 1 */ 419 { WM_ERASEBKGND, sent }, 420 { WM_WINDOWPOSCHANGED, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 421 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 422 { WM_PAINT, sent }, 423 { 0 } 424 }; 425 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_DEFERERASE|SWP_NOACTIVATE| 426 SWP_NOZORDER|SWP_FRAMECHANGED) 427 * for a visible overlapped window. 428 */ 429 static const struct message WmSWP_FrameChangedDeferErase[] = { 430 { WM_WINDOWPOSCHANGING, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_DEFERERASE|SWP_NOACTIVATE|SWP_FRAMECHANGED }, 431 { WM_NCCALCSIZE, sent|wparam|parent, 1 }, 432 { WM_WINDOWPOSCHANGED, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_DEFERERASE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 433 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 434 { WM_PAINT, sent|parent|optional }, 435 { WM_NCPAINT, sent|beginpaint|parent|optional }, /* wparam != 1 */ 436 { WM_GETTEXT, sent|beginpaint|parent|defwinproc|optional }, 437 { WM_PAINT, sent }, 438 { WM_NCPAINT, sent|beginpaint }, /* wparam != 1 */ 439 { WM_ERASEBKGND, sent|beginpaint|optional }, 440 { 0 } 441 }; 442 443 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE| 444 SWP_NOZORDER|SWP_FRAMECHANGED) 445 * for a visible overlapped window without WS_CLIPCHILDREN style set. 446 */ 447 static const struct message WmSWP_FrameChanged_noclip[] = { 448 { WM_WINDOWPOSCHANGING, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED }, 449 { WM_NCCALCSIZE, sent|wparam|parent, 1 }, 450 { WM_NCPAINT, sent|parent|optional }, /* wparam != 1 */ 451 { WM_GETTEXT, sent|parent|defwinproc|optional }, 452 { WM_ERASEBKGND, sent|parent|optional }, 453 { WM_WINDOWPOSCHANGED, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 454 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 455 { WM_PAINT, sent }, 456 { WM_NCPAINT, sent|beginpaint }, /* wparam != 1 */ 457 { WM_ERASEBKGND, sent|beginpaint|optional }, 458 { 0 } 459 }; 460 461 /* ShowWindow(SW_SHOW) for a not visible overlapped window */ 462 static const struct message WmShowOverlappedSeq[] = { 463 { WM_SHOWWINDOW, sent|wparam, 1 }, 464 { WM_NCPAINT, sent|wparam|optional, 1 }, 465 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 466 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 467 { WM_NCPAINT, sent|wparam|optional, 1 }, 468 { WM_GETTEXT, sent|defwinproc|optional }, 469 { WM_ERASEBKGND, sent|optional }, 470 { HCBT_ACTIVATE, hook|optional }, 471 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 472 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 473 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 474 { WM_NCPAINT, sent|wparam|optional, 1 }, 475 { WM_ACTIVATEAPP, sent|wparam|optional, 1 }, 476 { WM_NCACTIVATE, sent|wparam|optional, 1 }, 477 { WM_GETTEXT, sent|defwinproc|optional }, 478 { WM_ACTIVATE, sent|wparam|optional, 1 }, 479 { HCBT_SETFOCUS, hook|optional }, 480 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 481 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 482 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 483 { WM_SETFOCUS, sent|wparam|defwinproc|optional, 0 }, 484 { WM_GETTEXT, sent|optional }, 485 { WM_NCPAINT, sent|wparam|optional, 1 }, 486 { WM_GETTEXT, sent|defwinproc|optional }, 487 { WM_ERASEBKGND, sent|optional }, 488 /* Win9x adds SWP_NOZORDER below */ 489 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 490 { WM_NCCALCSIZE, sent|optional }, 491 { WM_GETTEXT, sent|optional }, 492 { WM_NCPAINT, sent|optional }, 493 { WM_ERASEBKGND, sent|optional }, 494 { WM_SYNCPAINT, sent|optional }, 495 #if 0 /* CreateWindow/ShowWindow(SW_SHOW) also generates WM_SIZE/WM_MOVE 496 * messages. Does that mean that CreateWindow doesn't set initial 497 * window dimensions for overlapped windows? 498 */ 499 { WM_SIZE, sent }, 500 { WM_MOVE, sent }, 501 #endif 502 { WM_PAINT, sent|optional }, 503 { WM_NCPAINT, sent|beginpaint|optional }, 504 { 0 } 505 }; 506 /* ShowWindow(SW_SHOWMAXIMIZED) for a not visible overlapped window */ 507 static const struct message WmShowMaxOverlappedSeq[] = { 508 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 509 { WM_GETMINMAXINFO, sent }, 510 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_STATECHANGED }, 511 { WM_GETMINMAXINFO, sent|defwinproc }, 512 { WM_NCCALCSIZE, sent|wparam, TRUE }, 513 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 514 { HCBT_ACTIVATE, hook|optional }, 515 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 516 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 517 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 518 { WM_ACTIVATEAPP, sent|wparam|optional, 1 }, 519 { WM_NCACTIVATE, sent|wparam|optional, 1 }, 520 { WM_GETTEXT, sent|defwinproc|optional }, 521 { WM_ACTIVATE, sent|wparam|optional, 1 }, 522 { HCBT_SETFOCUS, hook|optional }, 523 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 524 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 525 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 526 { WM_SETFOCUS, sent|wparam|defwinproc|optional, 0 }, 527 { WM_GETTEXT, sent|optional }, 528 { WM_NCPAINT, sent|wparam|optional, 1 }, 529 { WM_GETTEXT, sent|defwinproc|optional }, 530 { WM_ERASEBKGND, sent|optional }, 531 /* Win9x adds SWP_NOZORDER below */ 532 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_STATECHANGED }, 533 { WM_MOVE, sent|defwinproc }, 534 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 535 { WM_GETTEXT, sent|optional }, 536 { WM_NCCALCSIZE, sent|optional }, 537 { WM_NCPAINT, sent|optional }, 538 { WM_ERASEBKGND, sent|optional }, 539 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 540 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 541 { WM_SYNCPAINT, sent|optional }, 542 { WM_GETTITLEBARINFOEX, sent|optional }, 543 { WM_PAINT, sent|optional }, 544 { WM_NCPAINT, sent|beginpaint|optional }, 545 { WM_ERASEBKGND, sent|beginpaint|optional }, 546 { 0 } 547 }; 548 /* ShowWindow(SW_RESTORE) for a not visible maximized overlapped window */ 549 static const struct message WmShowRestoreMaxOverlappedSeq[] = { 550 { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE }, 551 { WM_GETTEXT, sent|optional }, 552 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, 553 { WM_GETMINMAXINFO, sent|defwinproc }, 554 { WM_NCCALCSIZE, sent|wparam, TRUE }, 555 { WM_NCPAINT, sent|optional }, 556 { WM_GETTEXT, sent|defwinproc|optional }, 557 { WM_ERASEBKGND, sent|optional }, 558 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOMOVE }, 559 { WM_MOVE, sent|defwinproc|optional }, 560 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 561 { WM_NCCALCSIZE, sent|wparam|optional, TRUE }, 562 { WM_NCPAINT, sent|optional }, 563 { WM_ERASEBKGND, sent|optional }, 564 { WM_PAINT, sent|optional }, 565 { WM_GETTITLEBARINFOEX, sent|optional }, 566 { WM_NCPAINT, sent|beginpaint|optional }, 567 { WM_ERASEBKGND, sent|beginpaint|optional }, 568 { WM_SYNCPAINT, sent|optional }, 569 { 0 } 570 }; 571 /* ShowWindow(SW_RESTORE) for a not visible minimized overlapped window */ 572 static const struct message WmShowRestoreMinOverlappedSeq[] = { 573 { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE }, 574 { WM_QUERYOPEN, sent|optional }, 575 { WM_GETTEXT, sent|optional }, 576 { WM_NCACTIVATE, sent|wparam|optional, 1 }, 577 { WM_WINDOWPOSCHANGING, sent|optional }, /* SWP_NOSIZE|SWP_NOMOVE */ 578 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 579 { WM_NCCALCSIZE, sent|wparam|optional, TRUE }, 580 { WM_MOVE, sent|optional }, 581 { WM_SIZE, sent|wparam|optional, SIZE_RESTORED }, 582 { WM_GETTEXT, sent|optional }, 583 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_FRAMECHANGED|SWP_STATECHANGED|SWP_NOCOPYBITS }, 584 { WM_GETMINMAXINFO, sent|defwinproc|optional }, 585 { WM_NCCALCSIZE, sent|wparam|optional, TRUE }, 586 { HCBT_ACTIVATE, hook|optional }, 587 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 588 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 589 { WM_ACTIVATEAPP, sent|wparam|optional, 1 }, 590 { WM_NCACTIVATE, sent|wparam|optional, 1 }, 591 { WM_GETTEXT, sent|defwinproc|optional }, 592 { WM_ACTIVATE, sent|wparam|optional, 1 }, 593 { HCBT_SETFOCUS, hook|optional }, 594 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 595 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 596 { WM_SETFOCUS, sent|wparam|defwinproc|optional, 0 }, 597 { WM_GETTEXT, sent|optional }, 598 { WM_NCPAINT, sent|wparam|optional, 1 }, 599 { WM_GETTEXT, sent|defwinproc|optional }, 600 { WM_ERASEBKGND, sent }, 601 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_STATECHANGED|SWP_FRAMECHANGED|SWP_NOCOPYBITS }, 602 { WM_MOVE, sent|defwinproc }, 603 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 604 { HCBT_SETFOCUS, hook|optional }, 605 { WM_SETFOCUS, sent|wparam|optional, 0 }, 606 { WM_NCCALCSIZE, sent|wparam|optional, TRUE }, 607 { WM_NCPAINT, sent|wparam|optional, 1 }, 608 { WM_ERASEBKGND, sent|optional }, 609 { HCBT_SETFOCUS, hook|optional }, 610 { WM_SETFOCUS, sent|wparam|optional, 0 }, 611 { WM_ACTIVATE, sent|wparam, 1 }, 612 { WM_GETTEXT, sent|optional }, 613 { WM_PAINT, sent|optional }, 614 { WM_GETTITLEBARINFOEX, sent|optional }, 615 { WM_NCPAINT, sent|beginpaint|optional }, 616 { WM_ERASEBKGND, sent|beginpaint|optional }, 617 { 0 } 618 }; 619 /* ShowWindow(SW_SHOWMINIMIZED) for a not visible overlapped window */ 620 static const struct message WmShowMinOverlappedSeq[] = { 621 { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, 622 { HCBT_SETFOCUS, hook|optional }, 623 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 624 { WM_KILLFOCUS, sent|optional }, 625 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 626 { WM_IME_NOTIFY, sent|wparam|optional|defwinproc, 1 }, 627 { WM_GETTEXT, sent|optional }, 628 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOCOPYBITS|SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_STATECHANGED }, 629 { WM_GETMINMAXINFO, sent|defwinproc }, 630 { WM_NCCALCSIZE, sent|wparam, TRUE }, 631 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, 632 { WM_NCPAINT, sent|optional }, 633 { WM_GETTEXT, sent|defwinproc|optional }, 634 { WM_WINDOWPOSCHANGED, sent }, 635 { WM_MOVE, sent|defwinproc }, 636 { WM_SIZE, sent|defwinproc|wparam|lparam, SIZE_MINIMIZED, 0 }, 637 { WM_NCCALCSIZE, sent|optional }, 638 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 639 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 640 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 }, 641 { WM_NCACTIVATE, sent|wparam|optional, 0 }, 642 { WM_GETTEXT, sent|defwinproc|optional }, 643 { WM_ACTIVATE, sent|optional }, 644 { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, 645 646 /* Vista sometimes restores the window right away... */ 647 { WM_SYSCOMMAND, sent|optional|wparam, SC_RESTORE }, 648 { HCBT_SYSCOMMAND, hook|optional|wparam, SC_RESTORE }, 649 { HCBT_MINMAX, hook|optional|lparam, 0, SW_RESTORE }, 650 { WM_QUERYOPEN, sent|optional }, 651 { WM_WINDOWPOSCHANGING, sent|optional|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, 652 { WM_GETMINMAXINFO, sent|optional|defwinproc }, 653 { WM_NCCALCSIZE, sent|optional|wparam, TRUE }, 654 { HCBT_ACTIVATE, hook|optional }, 655 { WM_ACTIVATEAPP, sent|optional|wparam, 1 }, 656 { WM_NCACTIVATE, sent|optional }, 657 { WM_GETTEXT, sent|optional }, 658 { WM_ACTIVATE, sent|optional|wparam, 1 }, 659 { HCBT_SETFOCUS, hook|optional }, 660 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 661 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 662 { WM_SETFOCUS, sent|optional }, 663 { WM_NCPAINT, sent|optional }, 664 { WM_GETTEXT, sent|defwinproc|optional }, 665 { WM_ERASEBKGND, sent|optional }, 666 { WM_WINDOWPOSCHANGED, sent|optional|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, 667 { WM_MOVE, sent|defwinproc|optional }, 668 { WM_SIZE, sent|defwinproc|optional|wparam, SIZE_RESTORED }, 669 { WM_ACTIVATE, sent|optional|wparam, 1 }, 670 { WM_SYSCOMMAND, sent|optional|wparam, SC_RESTORE }, 671 { HCBT_SYSCOMMAND, hook|optional|wparam, SC_RESTORE }, 672 673 { WM_PAINT, sent|optional }, 674 { WM_NCPAINT, sent|beginpaint|optional }, 675 { WM_ERASEBKGND, sent|beginpaint|optional }, 676 { 0 } 677 }; 678 /* ShowWindow(SW_HIDE) for a visible overlapped window */ 679 static const struct message WmHideOverlappedSeq[] = { 680 { WM_SHOWWINDOW, sent|wparam, 0 }, 681 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 682 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 683 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 684 { WM_SIZE, sent|optional }, /* XP doesn't send it */ 685 { WM_MOVE, sent|optional }, /* XP doesn't send it */ 686 { WM_NCACTIVATE, sent|wparam|optional, 0 }, 687 { WM_ACTIVATE, sent|wparam|optional, 0 }, 688 { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, 689 { HCBT_SETFOCUS, hook|optional }, 690 { WM_KILLFOCUS, sent|wparam|optional, 0 }, 691 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 692 { WM_IME_NOTIFY, sent|wparam|optional|defwinproc, 1 }, 693 { 0 } 694 }; 695 /* DestroyWindow for a visible overlapped window */ 696 static const struct message WmDestroyOverlappedSeq[] = { 697 { HCBT_DESTROYWND, hook }, 698 { 0x0090, sent|optional }, 699 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 700 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 701 { 0x0090, sent|optional }, 702 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 703 { WM_NCACTIVATE, sent|optional|wparam, 0 }, 704 { WM_ACTIVATE, sent|optional }, 705 { WM_ACTIVATEAPP, sent|optional|wparam, 0 }, 706 { WM_KILLFOCUS, sent|optional|wparam, 0 }, 707 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 708 { WM_IME_NOTIFY, sent|wparam|optional|defwinproc, 1 }, 709 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, 710 { WM_DESTROY, sent }, 711 { WM_NCDESTROY, sent }, 712 { 0 } 713 }; 714 /* CreateWindow(WS_MAXIMIZE|WS_VISIBLE) for popup window */ 715 static const struct message WmCreateMaxPopupSeq[] = { 716 { HCBT_CREATEWND, hook }, 717 { WM_NCCREATE, sent }, 718 { WM_NCCALCSIZE, sent|wparam, 0 }, 719 { WM_CREATE, sent }, 720 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 721 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 722 { WM_MOVE, sent }, 723 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 724 { WM_GETMINMAXINFO, sent }, 725 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_STATECHANGED }, 726 { WM_NCCALCSIZE, sent|wparam, TRUE }, 727 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOREDRAW|SWP_STATECHANGED }, 728 { WM_MOVE, sent|defwinproc }, 729 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 730 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 731 { WM_SHOWWINDOW, sent|wparam, 1 }, 732 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 733 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 734 { HCBT_ACTIVATE, hook }, 735 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 736 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 737 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 738 { WM_NCPAINT, sent|wparam|optional, 1 }, 739 { WM_ERASEBKGND, sent|optional }, 740 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOCLIENTMOVE|SWP_NOCLIENTSIZE|SWP_NOMOVE|SWP_NOSIZE }, 741 { WM_ACTIVATEAPP, sent|wparam, 1 }, 742 { WM_NCACTIVATE, sent }, 743 { WM_ACTIVATE, sent|wparam, 1 }, 744 { HCBT_SETFOCUS, hook }, 745 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 746 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 747 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 748 { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, 749 { WM_GETTEXT, sent|optional }, 750 { WM_SYNCPAINT, sent|wparam|optional, 4 }, 751 { WM_NCPAINT, sent|wparam|optional, 1 }, 752 { WM_ERASEBKGND, sent|optional }, 753 { WM_NCPAINT, sent|wparam|defwinproc|optional, 1 }, 754 { WM_ERASEBKGND, sent|defwinproc|optional }, 755 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTMOVE|SWP_NOCLIENTSIZE|SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOSIZE }, 756 { 0 } 757 }; 758 /* CreateWindow(WS_MAXIMIZE) for popup window, not initially visible */ 759 static const struct message WmCreateInvisibleMaxPopupSeq[] = { 760 { HCBT_CREATEWND, hook }, 761 { WM_NCCREATE, sent }, 762 { WM_NCCALCSIZE, sent|wparam, 0 }, 763 { WM_CREATE, sent }, 764 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 765 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 766 { WM_MOVE, sent }, 767 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 768 { WM_GETMINMAXINFO, sent }, 769 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_STATECHANGED }, 770 { WM_NCCALCSIZE, sent|wparam, TRUE }, 771 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOREDRAW|SWP_STATECHANGED }, 772 { WM_MOVE, sent|defwinproc }, 773 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 774 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 775 { 0 } 776 }; 777 /* ShowWindow(SW_SHOWMAXIMIZED) for a resized not visible popup window */ 778 static const struct message WmShowMaxPopupResizedSeq[] = { 779 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 780 { WM_GETMINMAXINFO, sent }, 781 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED }, 782 { WM_NCCALCSIZE, sent|wparam, TRUE }, 783 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 784 { HCBT_ACTIVATE, hook }, 785 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 786 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 787 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 788 { WM_NCPAINT, sent|wparam|optional, 1 }, 789 { WM_ERASEBKGND, sent|optional }, 790 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 791 { WM_ACTIVATEAPP, sent|wparam, 1 }, 792 { WM_NCACTIVATE, sent }, 793 { WM_ACTIVATE, sent|wparam, 1 }, 794 { HCBT_SETFOCUS, hook }, 795 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 796 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 797 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 798 { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, 799 { WM_GETTEXT, sent|optional }, 800 { WM_NCPAINT, sent|wparam|optional, 1 }, 801 { WM_ERASEBKGND, sent|optional }, 802 { WM_WINDOWPOSCHANGED, sent }, 803 /* WinNT4.0 sends WM_MOVE */ 804 { WM_MOVE, sent|defwinproc|optional }, 805 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 806 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 807 { 0 } 808 }; 809 /* ShowWindow(SW_SHOWMAXIMIZED) for a not visible popup window */ 810 static const struct message WmShowMaxPopupSeq[] = { 811 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 812 { WM_GETMINMAXINFO, sent }, 813 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED }, 814 { WM_NCCALCSIZE, sent|wparam, TRUE }, 815 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 816 { HCBT_ACTIVATE, hook }, 817 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 818 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 819 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 820 { WM_NCPAINT, sent|wparam|optional, 1 }, 821 { WM_ERASEBKGND, sent|optional }, 822 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOMOVE|SWP_NOSIZE }, 823 { WM_ACTIVATEAPP, sent|wparam, 1 }, 824 { WM_NCACTIVATE, sent }, 825 { WM_ACTIVATE, sent|wparam, 1 }, 826 { HCBT_SETFOCUS, hook }, 827 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 828 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 829 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 830 { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, 831 { WM_GETTEXT, sent|optional }, 832 { WM_SYNCPAINT, sent|wparam|optional, 4 }, 833 { WM_NCPAINT, sent|wparam|optional, 1 }, 834 { WM_ERASEBKGND, sent|optional }, 835 { WM_NCPAINT, sent|wparam|defwinproc|optional, 1 }, 836 { WM_ERASEBKGND, sent|defwinproc|optional }, 837 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOSIZE }, 838 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 839 { WM_SIZE, sent|defwinproc|optional }, 840 { 0 } 841 }; 842 /* CreateWindow(WS_VISIBLE) for popup window */ 843 static const struct message WmCreatePopupSeq[] = { 844 { HCBT_CREATEWND, hook }, 845 { WM_NCCREATE, sent }, 846 { WM_NCCALCSIZE, sent|wparam, 0 }, 847 { WM_CREATE, sent }, 848 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 849 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 850 { WM_MOVE, sent }, 851 { WM_SHOWWINDOW, sent|wparam, 1 }, 852 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 853 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 854 { HCBT_ACTIVATE, hook }, 855 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 856 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 857 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 858 { WM_NCPAINT, sent|wparam|optional, 1 }, 859 { WM_ERASEBKGND, sent|optional }, 860 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 861 { WM_ACTIVATEAPP, sent|wparam, 1 }, 862 { WM_NCACTIVATE, sent }, 863 { WM_ACTIVATE, sent|wparam, 1 }, 864 { HCBT_SETFOCUS, hook }, 865 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 866 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 867 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 868 { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, 869 { WM_GETTEXT, sent|optional }, 870 { WM_SYNCPAINT, sent|wparam|optional, 4 }, 871 { WM_NCPAINT, sent|wparam|optional, 1 }, 872 { WM_ERASEBKGND, sent|optional }, 873 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTMOVE|SWP_NOCLIENTSIZE|SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOSIZE }, 874 { 0 } 875 }; 876 /* ShowWindow(SW_SHOWMAXIMIZED) for a visible popup window */ 877 static const struct message WmShowVisMaxPopupSeq[] = { 878 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 879 { WM_GETMINMAXINFO, sent }, 880 { WM_GETTEXT, sent|optional }, 881 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, 882 { WM_GETTEXT, sent|optional }, 883 { WM_NCCALCSIZE, sent|wparam, TRUE }, 884 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 885 { WM_NCPAINT, sent|wparam|optional, 1 }, 886 { WM_ERASEBKGND, sent|optional }, 887 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, 888 { WM_MOVE, sent|defwinproc }, 889 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 890 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 891 { 0 } 892 }; 893 /* CreateWindow (for a child popup window, not initially visible) */ 894 static const struct message WmCreateChildPopupSeq[] = { 895 { HCBT_CREATEWND, hook }, 896 { WM_NCCREATE, sent }, 897 { WM_NCCALCSIZE, sent|wparam, 0 }, 898 { WM_CREATE, sent }, 899 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 900 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 901 { WM_MOVE, sent }, 902 { 0 } 903 }; 904 /* CreateWindow (for a popup window, not initially visible, 905 * which sets WS_VISIBLE in WM_CREATE handler) 906 */ 907 static const struct message WmCreateInvisiblePopupSeq[] = { 908 { HCBT_CREATEWND, hook }, 909 { WM_NCCREATE, sent }, 910 { WM_NCCALCSIZE, sent|wparam, 0 }, 911 { WM_CREATE, sent }, 912 { WM_STYLECHANGING, sent }, 913 { WM_STYLECHANGED, sent }, 914 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 915 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 916 { WM_MOVE, sent }, 917 { 0 } 918 }; 919 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER) 920 * for a popup window with WS_VISIBLE style set 921 */ 922 static const struct message WmShowVisiblePopupSeq_2[] = { 923 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 924 { 0 } 925 }; 926 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE) 927 * for a popup window with WS_VISIBLE style set 928 */ 929 static const struct message WmShowVisiblePopupSeq_3[] = { 930 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 931 { HCBT_ACTIVATE, hook }, 932 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 933 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 934 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 935 { WM_NCACTIVATE, sent }, 936 { WM_ACTIVATE, sent|wparam, 1 }, 937 { HCBT_SETFOCUS, hook }, 938 { WM_KILLFOCUS, sent|parent }, 939 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, 940 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 941 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 942 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 943 { WM_SETFOCUS, sent|defwinproc }, 944 { WM_GETTEXT, sent|optional }, 945 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE, 0, SWP_SHOWWINDOW }, 946 { 0 } 947 }; 948 /* CreateWindow (for a popup window with WS_VISIBLE style set and extreme location) 949 */ 950 static const struct message WmShowPopupExtremeLocationSeq[] = { 951 { HCBT_CREATEWND, hook }, 952 { WM_NCCREATE, sent }, 953 { WM_NCCALCSIZE, sent|wparam, 0 }, 954 { WM_CREATE, sent }, 955 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 956 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 957 { WM_MOVE, sent }, 958 { WM_SHOWWINDOW, sent|wparam, 1 }, 959 { WM_WINDOWPOSCHANGING, sent }, 960 { HCBT_ACTIVATE, hook }, 961 { WM_WINDOWPOSCHANGING, sent|optional }, 962 { WM_QUERYNEWPALETTE, sent|optional }, 963 { WM_ACTIVATEAPP, sent }, 964 { WM_NCACTIVATE, sent }, 965 { WM_ACTIVATE, sent }, 966 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, 967 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 968 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 969 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 970 { HCBT_SETFOCUS, hook }, 971 { WM_SETFOCUS, sent|defwinproc }, 972 { WM_NCPAINT, sent|wparam, 1 }, 973 { WM_ERASEBKGND, sent }, 974 { WM_WINDOWPOSCHANGED, sent }, 975 /* occasionally received on test machines */ 976 { WM_NCPAINT, sent|optional }, 977 { WM_ERASEBKGND, sent|optional }, 978 { 0 } 979 }; 980 /* CreateWindow (for a popup window with WS_VISIBLE style set) 981 */ 982 static const struct message WmShowPopupFirstDrawSeq_1[] = { 983 { HCBT_CREATEWND, hook }, 984 { WM_NCCREATE, sent }, 985 { WM_NCCALCSIZE, sent|wparam, 0 }, 986 { WM_CREATE, sent }, 987 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 988 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 989 { WM_MOVE, sent }, 990 { WM_SHOWWINDOW, sent|wparam, 1 }, 991 { WM_WINDOWPOSCHANGING, sent }, 992 { HCBT_ACTIVATE, hook }, 993 { WM_WINDOWPOSCHANGING, sent|optional }, 994 { WM_QUERYNEWPALETTE, sent|optional }, 995 { WM_ACTIVATEAPP, sent }, 996 { WM_NCACTIVATE, sent }, 997 { WM_ACTIVATE, sent }, 998 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, 999 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 1000 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 1001 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1002 { HCBT_SETFOCUS, hook }, 1003 { WM_SETFOCUS, sent|defwinproc }, 1004 { WM_NCPAINT, sent|wparam, 1 }, 1005 { WM_ERASEBKGND, sent }, 1006 { WM_WINDOWPOSCHANGED, sent }, 1007 { WM_PAINT, sent }, 1008 /* occasionally received on test machines */ 1009 { WM_NCPAINT, sent|beginpaint|optional }, 1010 { WM_ERASEBKGND, sent|beginpaint|optional }, 1011 { 0 } 1012 }; 1013 /* CreateWindow (for a popup window that is shown with ShowWindow(SW_SHOWMAXIMIZED)) 1014 */ 1015 static const struct message WmShowPopupFirstDrawSeq_2[] = { 1016 { HCBT_CREATEWND, hook }, 1017 { WM_NCCREATE, sent }, 1018 { WM_NCCALCSIZE, sent|wparam, 0 }, 1019 { WM_CREATE, sent }, 1020 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1021 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 1022 { WM_MOVE, sent }, 1023 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 1024 { WM_GETMINMAXINFO, sent }, 1025 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_STATECHANGED|SWP_SHOWWINDOW|SWP_FRAMECHANGED }, 1026 { WM_NCCALCSIZE, sent|wparam, TRUE }, 1027 { HCBT_ACTIVATE, hook }, 1028 { WM_WINDOWPOSCHANGING, sent|optional }, 1029 { WM_NCPAINT, sent|optional|wparam, 1 }, 1030 { WM_ERASEBKGND, sent|optional }, 1031 { WM_WINDOWPOSCHANGED, sent|optional }, 1032 { WM_QUERYNEWPALETTE, sent|optional }, 1033 { WM_ACTIVATEAPP, sent }, 1034 { WM_NCACTIVATE, sent }, 1035 { WM_ACTIVATE, sent }, 1036 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, 1037 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 1038 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 1039 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1040 { HCBT_SETFOCUS, hook }, 1041 { WM_SETFOCUS, sent|defwinproc }, 1042 { WM_NCPAINT, sent|wparam, 1 }, 1043 { WM_ERASEBKGND, sent }, 1044 { WM_WINDOWPOSCHANGED, sent|optional }, 1045 { WM_MOVE, sent|defwinproc }, 1046 { WM_SIZE, sent|defwinproc, 0 }, 1047 { WM_PAINT, sent}, 1048 /* occasionally received on test machines */ 1049 { WM_NCPAINT, sent|beginpaint|optional }, 1050 { WM_ERASEBKGND, sent|beginpaint|optional }, 1051 { 0 } 1052 }; 1053 static const struct message WmFirstDrawSetWindowPosSeq1[] = { 1054 { HCBT_CREATEWND, hook }, 1055 { WM_NCCREATE, sent }, 1056 { WM_NCCALCSIZE, sent|wparam, 0 }, 1057 { WM_CREATE, sent }, 1058 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1059 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 1060 { WM_MOVE, sent }, 1061 { WM_WINDOWPOSCHANGING, sent }, 1062 { HCBT_ACTIVATE, hook }, 1063 { WM_WINDOWPOSCHANGING, sent|optional }, 1064 { WM_QUERYNEWPALETTE, sent|optional }, 1065 { WM_ACTIVATEAPP, sent }, 1066 { WM_NCACTIVATE, sent }, 1067 { WM_ACTIVATE, sent }, 1068 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, 1069 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 1070 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 1071 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1072 { HCBT_SETFOCUS, hook }, 1073 { WM_SETFOCUS, sent|defwinproc }, 1074 { WM_NCPAINT, sent|wparam, 1 }, 1075 { WM_ERASEBKGND, sent }, 1076 { WM_WINDOWPOSCHANGED, sent }, 1077 { WM_MOVE, sent|defwinproc }, 1078 { 0 } 1079 }; 1080 static const struct message WmFirstDrawSetWindowPosSeq2[] = { 1081 { HCBT_CREATEWND, hook }, 1082 { WM_NCCREATE, sent }, 1083 { WM_NCCALCSIZE, sent|wparam, 0 }, 1084 { WM_CREATE, sent }, 1085 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1086 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 1087 { WM_MOVE, sent }, 1088 { WM_WINDOWPOSCHANGING, sent }, 1089 { HCBT_ACTIVATE, hook }, 1090 { WM_QUERYNEWPALETTE, sent|optional }, 1091 { WM_WINDOWPOSCHANGING, sent|optional }, 1092 { WM_ACTIVATEAPP, sent }, 1093 { WM_NCACTIVATE, sent }, 1094 { WM_ACTIVATE, sent }, 1095 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, 1096 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 1097 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 1098 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1099 { HCBT_SETFOCUS, hook }, 1100 { WM_SETFOCUS, sent|defwinproc }, 1101 { WM_WINDOWPOSCHANGED, sent }, 1102 { WM_MOVE, sent|defwinproc }, 1103 { 0 } 1104 }; 1105 static const struct message WmFirstDrawSetWindowPosSeq3[] = { 1106 { HCBT_CREATEWND, hook }, 1107 { WM_NCCREATE, sent }, 1108 { WM_NCCALCSIZE, sent|wparam, 0 }, 1109 { WM_CREATE, sent }, 1110 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1111 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 1112 { WM_MOVE, sent }, 1113 { HCBT_ACTIVATE, hook|optional }, 1114 /* Probably shouldn't happen, but not part of this test */ 1115 { WM_QUERYNEWPALETTE, sent|optional }, 1116 { WM_ACTIVATEAPP, sent|optional }, 1117 { WM_NCACTIVATE, sent|optional }, 1118 { WM_ACTIVATE, sent|optional }, 1119 { HCBT_SETFOCUS, hook|optional }, 1120 { WM_SETFOCUS, sent|defwinproc|optional }, 1121 { 0 } 1122 }; 1123 static const struct message WmFirstDrawSetWindowPosSeq4[] = { 1124 { HCBT_CREATEWND, hook }, 1125 { WM_NCCREATE, sent }, 1126 { WM_NCCALCSIZE, sent|wparam, 0 }, 1127 { WM_CREATE, sent }, 1128 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1129 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 1130 { WM_MOVE, sent }, 1131 { WM_WINDOWPOSCHANGING, sent }, 1132 { HCBT_ACTIVATE, hook }, 1133 { WM_WINDOWPOSCHANGING, sent|optional }, 1134 { WM_QUERYNEWPALETTE, sent|optional }, 1135 { WM_ACTIVATEAPP, sent }, 1136 { WM_NCACTIVATE, sent }, 1137 { WM_ACTIVATE, sent }, 1138 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, 1139 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 1140 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 1141 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1142 { HCBT_SETFOCUS, hook }, 1143 { WM_SETFOCUS, sent|defwinproc }, 1144 { WM_NCPAINT, sent|wparam, 1 }, 1145 { WM_ERASEBKGND, sent }, 1146 { WM_WINDOWPOSCHANGED, sent }, 1147 { 0 } 1148 }; 1149 static const struct message WmFirstDrawSetWindowPosSeq5[] = { 1150 { HCBT_CREATEWND, hook }, 1151 { WM_NCCREATE, sent }, 1152 { WM_NCCALCSIZE, sent|wparam, 0 }, 1153 { WM_CREATE, sent }, 1154 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1155 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 1156 { WM_MOVE, sent }, 1157 { WM_WINDOWPOSCHANGING, sent }, 1158 { HCBT_ACTIVATE, hook }, 1159 { WM_WINDOWPOSCHANGING, sent|optional }, 1160 { WM_QUERYNEWPALETTE, sent|optional }, 1161 { WM_ACTIVATEAPP, sent }, 1162 { WM_NCACTIVATE, sent }, 1163 { WM_ACTIVATE, sent }, 1164 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, 1165 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 1166 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 1167 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1168 { HCBT_SETFOCUS, hook }, 1169 { WM_SETFOCUS, sent|defwinproc }, 1170 { WM_WINDOWPOSCHANGED, sent }, 1171 { 0 } 1172 }; 1173 static const struct message WmFirstDrawChildSeq1[] = { 1174 { 0 } 1175 }; 1176 static const struct message WmFirstDrawChildSeq2[] = { 1177 { WM_NCPAINT, sent|wparam, 1 }, 1178 { WM_ERASEBKGND, sent }, 1179 /* occasionally received on test machines */ 1180 { WM_NCPAINT, sent|optional }, 1181 { WM_ERASEBKGND, sent|optional }, 1182 { 0 } 1183 }; 1184 /* CreateWindow (for child window, not initially visible) */ 1185 static const struct message WmCreateChildSeq[] = { 1186 { HCBT_CREATEWND, hook }, 1187 { WM_NCCREATE, sent }, 1188 /* child is inserted into parent's child list after WM_NCCREATE returns */ 1189 { WM_NCCALCSIZE, sent|wparam, 0 }, 1190 { WM_CREATE, sent }, 1191 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1192 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 1193 { WM_MOVE, sent }, 1194 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE }, 1195 { 0 } 1196 }; 1197 /* CreateWindow (for maximized child window, not initially visible) */ 1198 static const struct message WmCreateMaximizedChildSeq[] = { 1199 { HCBT_CREATEWND, hook }, 1200 { WM_NCCREATE, sent }, 1201 { WM_NCCALCSIZE, sent|wparam, 0 }, 1202 { WM_CREATE, sent }, 1203 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1204 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 1205 { WM_MOVE, sent }, 1206 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 1207 { WM_GETMINMAXINFO, sent }, 1208 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_STATECHANGED }, 1209 { WM_NCCALCSIZE, sent|wparam, 1 }, 1210 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 1211 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 1212 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1213 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE }, 1214 { 0 } 1215 }; 1216 /* CreateWindow (for a child window, initially visible) */ 1217 static const struct message WmCreateVisibleChildSeq[] = { 1218 { HCBT_CREATEWND, hook }, 1219 { WM_NCCREATE, sent }, 1220 /* child is inserted into parent's child list after WM_NCCREATE returns */ 1221 { WM_NCCALCSIZE, sent|wparam, 0 }, 1222 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, 1223 { WM_CREATE, sent }, 1224 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1225 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 1226 { WM_MOVE, sent }, 1227 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE }, 1228 { WM_SHOWWINDOW, sent|wparam, 1 }, 1229 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, 1230 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1231 { WM_ERASEBKGND, sent|parent|optional }, 1232 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1233 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* WinXP */ 1234 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1235 { 0 } 1236 }; 1237 /* ShowWindow(SW_SHOW) for a not visible child window */ 1238 static const struct message WmShowChildSeq[] = { 1239 { WM_SHOWWINDOW, sent|wparam, 1 }, 1240 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1241 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1242 { WM_ERASEBKGND, sent|parent|optional }, 1243 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1244 { 0 } 1245 }; 1246 /* ShowWindow(SW_HIDE) for a visible child window */ 1247 static const struct message WmHideChildSeq[] = { 1248 { WM_SHOWWINDOW, sent|wparam, 0 }, 1249 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1250 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 1251 { WM_ERASEBKGND, sent|parent|optional }, 1252 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1253 { 0 } 1254 }; 1255 /* ShowWindow(SW_HIDE) for a visible child window checking all parent events*/ 1256 static const struct message WmHideChildSeq2[] = { 1257 { WM_SHOWWINDOW, sent|wparam, 0 }, 1258 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1259 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 1260 { WM_ERASEBKGND, sent|parent|optional }, 1261 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1262 { 0 } 1263 }; 1264 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE) 1265 * for a not visible child window 1266 */ 1267 static const struct message WmShowChildSeq_2[] = { 1268 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 1269 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1270 { WM_CHILDACTIVATE, sent }, 1271 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1272 { 0 } 1273 }; 1274 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE) 1275 * for a not visible child window 1276 */ 1277 static const struct message WmShowChildSeq_3[] = { 1278 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, 1279 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1280 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1281 { 0 } 1282 }; 1283 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE) 1284 * for a visible child window with a caption 1285 */ 1286 static const struct message WmShowChildSeq_4[] = { 1287 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 1288 { WM_CHILDACTIVATE, sent }, 1289 { 0 } 1290 }; 1291 /* ShowWindow(SW_MINIMIZE) for child with invisible parent */ 1292 static const struct message WmShowChildInvisibleParentSeq_1[] = { 1293 { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, 1294 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE }, 1295 { WM_NCCALCSIZE, sent|wparam, 1 }, 1296 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1297 { WM_CHILDACTIVATE, sent|optional }, 1298 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOREDRAW|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE }, 1299 { WM_MOVE, sent|defwinproc }, 1300 { WM_SIZE, sent|defwinproc|wparam|lparam, SIZE_MINIMIZED, 0 }, 1301 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1302 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 }, 1303 /* FIXME: Wine creates an icon/title window while Windows doesn't */ 1304 { WM_PARENTNOTIFY, sent|parent|wparam|optional, WM_CREATE }, 1305 { WM_GETTEXT, sent|optional }, 1306 { 0 } 1307 }; 1308 /* repeated ShowWindow(SW_MINIMIZE) for child with invisible parent */ 1309 static const struct message WmShowChildInvisibleParentSeq_1r[] = { 1310 { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, 1311 { 0 } 1312 }; 1313 /* ShowWindow(SW_MAXIMIZE) for child with invisible parent */ 1314 static const struct message WmShowChildInvisibleParentSeq_2[] = { 1315 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 1316 { WM_GETMINMAXINFO, sent }, 1317 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_STATECHANGED }, 1318 { WM_NCCALCSIZE, sent|wparam, 1 }, 1319 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1320 { WM_CHILDACTIVATE, sent }, 1321 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 1322 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 1323 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1324 { 0 } 1325 }; 1326 /* repeated ShowWindow(SW_MAXIMIZE) for child with invisible parent */ 1327 static const struct message WmShowChildInvisibleParentSeq_2r[] = { 1328 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 1329 { 0 } 1330 }; 1331 /* ShowWindow(SW_SHOWMINIMIZED) for child with invisible parent */ 1332 static const struct message WmShowChildInvisibleParentSeq_3[] = { 1333 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINIMIZED }, 1334 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 1335 { WM_NCCALCSIZE, sent|wparam, 1 }, 1336 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1337 { WM_CHILDACTIVATE, sent }, 1338 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOREDRAW|SWP_NOCOPYBITS|SWP_STATECHANGED }, 1339 { WM_MOVE, sent|defwinproc }, 1340 { WM_SIZE, sent|defwinproc|wparam|lparam, SIZE_MINIMIZED, 0 }, 1341 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1342 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 }, 1343 /* FIXME: Wine creates an icon/title window while Windows doesn't */ 1344 { WM_PARENTNOTIFY, sent|parent|wparam|optional, WM_CREATE }, 1345 { WM_GETTEXT, sent|optional }, 1346 { 0 } 1347 }; 1348 /* repeated ShowWindow(SW_SHOWMINIMIZED) for child with invisible parent */ 1349 static const struct message WmShowChildInvisibleParentSeq_3r[] = { 1350 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINIMIZED }, 1351 { 0 } 1352 }; 1353 /* ShowWindow(SW_SHOWMINNOACTIVE) for child with invisible parent */ 1354 static const struct message WmShowChildInvisibleParentSeq_4[] = { 1355 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINNOACTIVE }, 1356 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_STATECHANGED }, 1357 { WM_NCCALCSIZE, sent|wparam, 1 }, 1358 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1359 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOCOPYBITS|SWP_STATECHANGED }, 1360 { WM_MOVE, sent|defwinproc }, 1361 { WM_SIZE, sent|defwinproc|wparam|lparam, SIZE_MINIMIZED, 0 }, 1362 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1363 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 }, 1364 /* FIXME: Wine creates an icon/title window while Windows doesn't */ 1365 { WM_PARENTNOTIFY, sent|parent|wparam|optional, WM_CREATE }, 1366 { WM_GETTEXT, sent|optional }, 1367 { 0 } 1368 }; 1369 /* repeated ShowWindow(SW_SHOWMINNOACTIVE) for child with invisible parent */ 1370 static const struct message WmShowChildInvisibleParentSeq_4r[] = { 1371 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINNOACTIVE }, 1372 { 0 } 1373 }; 1374 /* ShowWindow(SW_SHOW) for child with invisible parent */ 1375 static const struct message WmShowChildInvisibleParentSeq_5[] = { 1376 { WM_SHOWWINDOW, sent|wparam, 1 }, 1377 { 0 } 1378 }; 1379 /* ShowWindow(SW_HIDE) for child with invisible parent */ 1380 static const struct message WmHideChildInvisibleParentSeq[] = { 1381 { WM_SHOWWINDOW, sent|wparam, 0 }, 1382 { 0 } 1383 }; 1384 /* SetWindowPos(SWP_SHOWWINDOW) for child with invisible parent */ 1385 static const struct message WmShowChildInvisibleParentSeq_6[] = { 1386 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, 1387 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1388 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1389 { 0 } 1390 }; 1391 /* SetWindowPos(SWP_HIDEWINDOW) for child with invisible parent */ 1392 static const struct message WmHideChildInvisibleParentSeq_2[] = { 1393 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1394 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 1395 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1396 { 0 } 1397 }; 1398 /* DestroyWindow for a visible child window */ 1399 static const struct message WmDestroyChildSeq[] = { 1400 { HCBT_DESTROYWND, hook }, 1401 { 0x0090, sent|optional }, 1402 { WM_PARENTNOTIFY, sent|parent|wparam, WM_DESTROY }, 1403 { WM_SHOWWINDOW, sent|wparam, 0 }, 1404 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1405 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 1406 { WM_ERASEBKGND, sent|parent|optional }, 1407 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1408 { HCBT_SETFOCUS, hook }, /* set focus to a parent */ 1409 { WM_KILLFOCUS, sent }, 1410 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 1411 { WM_IME_SETCONTEXT, sent|wparam|parent|optional, 1 }, 1412 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1413 { WM_SETFOCUS, sent|parent }, 1414 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, 1415 { WM_DESTROY, sent }, 1416 { WM_DESTROY, sent|optional }, /* some other (IME?) window */ 1417 { WM_NCDESTROY, sent|optional }, /* some other (IME?) window */ 1418 { WM_NCDESTROY, sent }, 1419 { 0 } 1420 }; 1421 /* visible child window destroyed by thread exit */ 1422 static const struct message WmExitThreadSeq[] = { 1423 { WM_NCDESTROY, sent }, /* actually in grandchild */ 1424 { WM_PAINT, sent|parent }, 1425 { WM_ERASEBKGND, sent|parent|beginpaint }, 1426 { 0 } 1427 }; 1428 /* DestroyWindow for a visible child window with invisible parent */ 1429 static const struct message WmDestroyInvisibleChildSeq[] = { 1430 { HCBT_DESTROYWND, hook }, 1431 { 0x0090, sent|optional }, 1432 { WM_PARENTNOTIFY, sent|parent|wparam, WM_DESTROY }, 1433 { WM_SHOWWINDOW, sent|wparam, 0 }, 1434 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, 1435 { WM_DESTROY, sent }, 1436 { WM_NCDESTROY, sent }, 1437 { 0 } 1438 }; 1439 /* Resizing child window with MoveWindow (32) */ 1440 static const struct message WmResizingChildWithMoveWindowSeq[] = { 1441 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE }, 1442 { WM_NCCALCSIZE, sent|wparam, 1 }, 1443 { WM_ERASEBKGND, sent|parent|optional }, 1444 { WM_ERASEBKGND, sent|optional }, 1445 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE }, 1446 { WM_MOVE, sent|defwinproc }, 1447 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 1448 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1449 { 0 } 1450 }; 1451 /* Creation of a custom dialog (32) */ 1452 static const struct message WmCreateCustomDialogSeq[] = { 1453 { HCBT_CREATEWND, hook }, 1454 { WM_GETMINMAXINFO, sent }, 1455 { WM_NCCREATE, sent }, 1456 { WM_NCCALCSIZE, sent|wparam, 0 }, 1457 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, 1458 { WM_CREATE, sent }, 1459 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1460 { WM_NOTIFYFORMAT, sent|optional }, 1461 { WM_QUERYUISTATE, sent|optional }, 1462 { WM_WINDOWPOSCHANGING, sent|optional }, 1463 { WM_GETMINMAXINFO, sent|optional }, 1464 { WM_NCCALCSIZE, sent|optional }, 1465 { WM_WINDOWPOSCHANGED, sent|optional }, 1466 { WM_SHOWWINDOW, sent|wparam, 1 }, 1467 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 1468 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1469 { HCBT_ACTIVATE, hook }, 1470 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 1471 1472 1473 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 1474 1475 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 1476 1477 { WM_NCACTIVATE, sent }, 1478 { WM_GETTEXT, sent|optional|defwinproc }, 1479 { WM_GETTEXT, sent|optional|defwinproc }, 1480 { WM_GETTEXT, sent|optional|defwinproc }, 1481 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 }, 1482 { WM_ACTIVATE, sent|wparam, 1 }, 1483 { WM_GETTEXT, sent|optional }, 1484 { WM_KILLFOCUS, sent|parent }, 1485 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, 1486 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 1487 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 1488 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1489 { WM_SETFOCUS, sent }, 1490 { WM_GETDLGCODE, sent|defwinproc|wparam, 0 }, 1491 { WM_NCPAINT, sent|wparam, 1 }, 1492 { WM_GETTEXT, sent|optional|defwinproc }, 1493 { WM_GETTEXT, sent|optional|defwinproc }, 1494 { WM_ERASEBKGND, sent }, 1495 { WM_CTLCOLORDLG, sent|optional|defwinproc }, 1496 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1497 { WM_GETTEXT, sent|optional }, 1498 { WM_GETTEXT, sent|optional }, 1499 { WM_NCCALCSIZE, sent|optional }, 1500 { WM_NCPAINT, sent|optional }, 1501 { WM_GETTEXT, sent|optional|defwinproc }, 1502 { WM_GETTEXT, sent|optional|defwinproc }, 1503 { WM_ERASEBKGND, sent|optional }, 1504 { WM_CTLCOLORDLG, sent|optional|defwinproc }, 1505 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1506 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 1507 { WM_MOVE, sent }, 1508 { 0 } 1509 }; 1510 /* Calling EndDialog for a custom dialog (32) */ 1511 static const struct message WmEndCustomDialogSeq[] = { 1512 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1513 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 1514 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1515 { WM_GETTEXT, sent|optional }, 1516 { HCBT_ACTIVATE, hook }, 1517 { WM_NCACTIVATE, sent|wparam, 0 }, 1518 { WM_GETTEXT, sent|optional|defwinproc }, 1519 { WM_GETTEXT, sent|optional|defwinproc }, 1520 { WM_ACTIVATE, sent|wparam, 0 }, 1521 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 1522 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1523 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1524 { WM_GETTEXT, sent|optional|defwinproc }, 1525 { WM_GETTEXT, sent|optional|defwinproc }, 1526 { HCBT_SETFOCUS, hook }, 1527 { WM_KILLFOCUS, sent }, 1528 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 1529 { WM_IME_SETCONTEXT, sent|parent|wparam|defwinproc|optional, 1 }, 1530 { WM_IME_NOTIFY, sent|wparam|optional, 1 }, 1531 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1532 { WM_SETFOCUS, sent|parent|defwinproc }, 1533 { 0 } 1534 }; 1535 /* ShowWindow(SW_SHOW) for a custom dialog (initially invisible) */ 1536 static const struct message WmShowCustomDialogSeq[] = { 1537 { WM_SHOWWINDOW, sent|wparam, 1 }, 1538 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 1539 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1540 { HCBT_ACTIVATE, hook }, 1541 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 1542 1543 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 1544 1545 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 1546 { WM_ACTIVATEAPP, sent|wparam|optional, 1 }, 1547 { WM_NCACTIVATE, sent }, 1548 { WM_ACTIVATE, sent|wparam, 1 }, 1549 { WM_GETTEXT, sent|optional }, 1550 1551 { WM_KILLFOCUS, sent|parent }, 1552 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, 1553 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 1554 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 1555 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1556 { WM_SETFOCUS, sent }, 1557 { WM_GETDLGCODE, sent|defwinproc|wparam, 0 }, 1558 { WM_NCPAINT, sent|wparam, 1 }, 1559 { WM_ERASEBKGND, sent }, 1560 { WM_CTLCOLORDLG, sent|defwinproc }, 1561 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1562 { 0 } 1563 }; 1564 /* Creation and destruction of a modal dialog (32) */ 1565 static const struct message WmModalDialogSeq[] = { 1566 { WM_CANCELMODE, sent|parent }, 1567 { HCBT_SETFOCUS, hook }, 1568 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1569 { WM_KILLFOCUS, sent|parent }, 1570 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, 1571 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1572 { WM_ENABLE, sent|parent|wparam, 0 }, 1573 { HCBT_CREATEWND, hook }, 1574 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, 1575 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1576 { WM_SETFONT, sent }, 1577 { WM_INITDIALOG, sent }, 1578 { WM_CHANGEUISTATE, sent|optional }, 1579 { WM_UPDATEUISTATE, sent|optional }, 1580 { WM_SHOWWINDOW, sent }, 1581 { HCBT_ACTIVATE, hook }, 1582 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 1583 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 1584 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE }, 1585 { WM_NCACTIVATE, sent }, 1586 { WM_GETTEXT, sent|optional }, 1587 { WM_ACTIVATE, sent|wparam, 1 }, 1588 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, 1589 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1590 { WM_NCPAINT, sent|optional }, 1591 { WM_GETTEXT, sent|optional }, 1592 { WM_ERASEBKGND, sent|optional }, 1593 { WM_CTLCOLORDLG, sent|optional }, 1594 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1595 { WM_GETTEXT, sent|optional }, 1596 { WM_NCCALCSIZE, sent|optional }, 1597 { WM_NCPAINT, sent|optional }, 1598 { WM_GETTEXT, sent|optional }, 1599 { WM_ERASEBKGND, sent|optional }, 1600 { WM_CTLCOLORDLG, sent|optional }, 1601 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1602 { WM_PAINT, sent|optional }, 1603 { WM_CTLCOLORBTN, sent|optional }, 1604 { WM_GETTITLEBARINFOEX, sent|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_ENTERIDLE, sent|parent|optional }, 1625 { WM_TIMER, sent }, 1626 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1627 { WM_ENABLE, sent|parent|wparam, 1 }, 1628 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, 1629 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 1630 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1631 { WM_GETTEXT, sent|optional }, 1632 { HCBT_ACTIVATE, hook }, 1633 { WM_NCACTIVATE, sent|wparam, 0 }, 1634 { WM_GETTEXT, sent|optional }, 1635 { WM_ACTIVATE, sent|wparam, 0 }, 1636 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 1637 { WM_WINDOWPOSCHANGING, sent|optional }, 1638 { WM_WINDOWPOSCHANGED, sent|optional }, 1639 { HCBT_SETFOCUS, hook }, 1640 { WM_IME_SETCONTEXT, sent|parent|wparam|defwinproc|optional, 1 }, 1641 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1642 { WM_SETFOCUS, sent|parent|defwinproc }, 1643 { EVENT_SYSTEM_DIALOGEND, winevent_hook|wparam|lparam, 0, 0 }, 1644 { HCBT_DESTROYWND, hook }, 1645 { 0x0090, sent|optional }, 1646 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, 1647 { WM_DESTROY, sent }, 1648 { WM_NCDESTROY, sent }, 1649 { 0 } 1650 }; 1651 static const struct message WmModalDialogSeq_2[] = { 1652 { WM_CANCELMODE, sent }, 1653 { HCBT_SETFOCUS, hook }, 1654 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 1655 { WM_KILLFOCUS, sent }, 1656 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, 1657 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1658 { WM_ENABLE, sent|wparam, 0 }, 1659 { HCBT_CREATEWND, hook }, 1660 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, 1661 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 1662 { WM_SETFONT, sent }, 1663 { WM_INITDIALOG, sent }, 1664 { WM_CHANGEUISTATE, sent|optional }, 1665 { WM_UPDATEUISTATE, sent|optional }, 1666 { WM_ENABLE, sent|wparam, 1 }, 1667 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, 1668 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 1669 { WM_CHANGEUISTATE, sent|optional }, 1670 { WM_UPDATEUISTATE, sent|optional }, 1671 { HCBT_DESTROYWND, hook }, 1672 { 0x0090, sent|optional }, 1673 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, 1674 { WM_DESTROY, sent }, 1675 { WM_NCDESTROY, sent }, 1676 { 0 } 1677 }; 1678 /* SetMenu for NonVisible windows with size change*/ 1679 static const struct message WmSetMenuNonVisibleSizeChangeSeq[] = { 1680 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1681 { WM_NCCALCSIZE, sent|wparam, 1 }, 1682 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, 1683 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW }, 1684 { WM_MOVE, sent|defwinproc }, 1685 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 1686 { WM_NCCALCSIZE,sent|wparam|optional, 1 }, /* XP */ 1687 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1688 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP sends a duplicate */ 1689 { WM_GETTEXT, sent|optional }, 1690 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, 1691 { 0 } 1692 }; 1693 /* SetMenu for NonVisible windows with no size change */ 1694 static const struct message WmSetMenuNonVisibleNoSizeChangeSeq[] = { 1695 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1696 { WM_NCCALCSIZE, sent|wparam, 1 }, 1697 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1698 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1699 { 0 } 1700 }; 1701 /* SetMenu for Visible windows with size change */ 1702 static const struct message WmSetMenuVisibleSizeChangeSeq[] = { 1703 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1704 { WM_NCCALCSIZE, sent|wparam, 1 }, 1705 { 0x0093, sent|defwinproc|optional }, 1706 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, 1707 { WM_NCPAINT, sent|optional }, /* wparam != 1 */ 1708 { 0x0093, sent|defwinproc|optional }, 1709 { 0x0093, sent|defwinproc|optional }, 1710 { 0x0091, sent|defwinproc|optional }, 1711 { 0x0092, sent|defwinproc|optional }, 1712 { WM_GETTEXT, sent|defwinproc|optional }, 1713 { WM_ERASEBKGND, sent|optional }, 1714 { WM_ACTIVATE, sent|optional }, 1715 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1716 { WM_MOVE, sent|defwinproc }, 1717 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 1718 { 0x0093, sent|optional }, 1719 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, 1720 { 0x0093, sent|defwinproc|optional }, 1721 { WM_NCPAINT, sent|optional }, /* wparam != 1 */ 1722 { 0x0093, sent|defwinproc|optional }, 1723 { 0x0093, sent|defwinproc|optional }, 1724 { 0x0091, sent|defwinproc|optional }, 1725 { 0x0092, sent|defwinproc|optional }, 1726 { WM_ERASEBKGND, sent|optional }, 1727 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1728 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP sends a duplicate */ 1729 { 0 } 1730 }; 1731 /* SetMenu for Visible windows with no size change */ 1732 static const struct message WmSetMenuVisibleNoSizeChangeSeq[] = { 1733 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1734 { WM_NCCALCSIZE, sent|wparam, 1 }, 1735 { WM_NCPAINT, sent|optional }, /* wparam != 1 */ 1736 { WM_GETTEXT, sent|defwinproc|optional }, 1737 { WM_ERASEBKGND, sent|optional }, 1738 { WM_ACTIVATE, sent|optional }, 1739 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1740 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1741 { 0 } 1742 }; 1743 /* DrawMenuBar for a visible window */ 1744 static const struct message WmDrawMenuBarSeq[] = 1745 { 1746 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1747 { WM_NCCALCSIZE, sent|wparam, 1 }, 1748 { 0x0093, sent|defwinproc|optional }, 1749 { WM_NCPAINT, sent|optional }, /* wparam != 1 */ 1750 { 0x0093, sent|defwinproc|optional }, 1751 { 0x0093, sent|defwinproc|optional }, 1752 { 0x0091, sent|defwinproc|optional }, 1753 { 0x0092, sent|defwinproc|optional }, 1754 { WM_GETTEXT, sent|defwinproc|optional }, 1755 { WM_ERASEBKGND, sent|optional }, 1756 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1757 { 0x0093, sent|optional }, 1758 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1759 { 0 } 1760 }; 1761 1762 static const struct message WmSetRedrawFalseSeq[] = 1763 { 1764 { WM_SETREDRAW, sent|wparam, 0 }, 1765 { 0 } 1766 }; 1767 1768 static const struct message WmSetRedrawTrueSeq[] = 1769 { 1770 { WM_SETREDRAW, sent|wparam, 1 }, 1771 { 0 } 1772 }; 1773 1774 static const struct message WmEnableWindowSeq_1[] = 1775 { 1776 { WM_CANCELMODE, sent|wparam|lparam, 0, 0 }, 1777 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1778 { HCBT_SETFOCUS, hook|optional }, 1779 { WM_KILLFOCUS, sent|optional }, 1780 { WM_ENABLE, sent|wparam|lparam, FALSE, 0 }, 1781 { 0 } 1782 }; 1783 1784 static const struct message WmEnableWindowSeq_2[] = 1785 { 1786 { WM_CANCELMODE, sent|wparam|lparam, 0, 0 }, 1787 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1788 { 0 } 1789 }; 1790 1791 static const struct message WmEnableWindowSeq_3[] = 1792 { 1793 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1794 { WM_ENABLE, sent|wparam|lparam, TRUE, 0 }, 1795 { 0 } 1796 }; 1797 1798 static const struct message WmEnableWindowSeq_4[] = 1799 { 1800 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1801 { 0 } 1802 }; 1803 1804 static const struct message WmGetScrollRangeSeq[] = 1805 { 1806 { SBM_GETRANGE, sent }, 1807 { 0 } 1808 }; 1809 static const struct message WmGetScrollInfoSeq[] = 1810 { 1811 { SBM_GETSCROLLINFO, sent }, 1812 { 0 } 1813 }; 1814 static const struct message WmSetScrollRangeSeq[] = 1815 { 1816 /* MSDN claims that Windows sends SBM_SETRANGE message, but win2k SP4 1817 sends SBM_SETSCROLLINFO. 1818 */ 1819 { SBM_SETSCROLLINFO, sent }, 1820 { 0 } 1821 }; 1822 /* SetScrollRange for a window without a non-client area */ 1823 static const struct message WmSetScrollRangeHSeq_empty[] = 1824 { 1825 { EVENT_OBJECT_VALUECHANGE, winevent_hook|wparam|lparam, OBJID_HSCROLL, 0 }, 1826 { 0 } 1827 }; 1828 static const struct message WmSetScrollRangeVSeq_empty[] = 1829 { 1830 { EVENT_OBJECT_VALUECHANGE, winevent_hook|wparam|lparam, OBJID_VSCROLL, 0 }, 1831 { 0 } 1832 }; 1833 static const struct message WmSetScrollRangeHVSeq[] = 1834 { 1835 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE }, 1836 { WM_NCCALCSIZE, sent|wparam, 1 }, 1837 { WM_GETTEXT, sent|defwinproc|optional }, 1838 { WM_ERASEBKGND, sent|optional }, 1839 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1840 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1841 { EVENT_OBJECT_VALUECHANGE, winevent_hook|lparam|optional, 0/*OBJID_HSCROLL or OBJID_VSCROLL*/, 0 }, 1842 { 0 } 1843 }; 1844 /* SetScrollRange for a window with a non-client area */ 1845 static const struct message WmSetScrollRangeHV_NC_Seq[] = 1846 { 1847 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE }, 1848 { WM_NCCALCSIZE, sent|wparam, 1 }, 1849 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, 1850 { WM_NCPAINT, sent|optional }, 1851 { WM_STYLECHANGING, sent|defwinproc|optional }, 1852 { WM_STYLECHANGED, sent|defwinproc|optional }, 1853 { WM_STYLECHANGING, sent|defwinproc|optional }, 1854 { WM_STYLECHANGED, sent|defwinproc|optional }, 1855 { WM_STYLECHANGING, sent|defwinproc|optional }, 1856 { WM_STYLECHANGED, sent|defwinproc|optional }, 1857 { WM_STYLECHANGING, sent|defwinproc|optional }, 1858 { WM_STYLECHANGED, sent|defwinproc|optional }, 1859 { WM_GETTEXT, sent|defwinproc|optional }, 1860 { WM_GETTEXT, sent|defwinproc|optional }, 1861 { WM_ERASEBKGND, sent|optional }, 1862 { WM_CTLCOLORDLG, sent|defwinproc|optional }, /* sent to a parent of the dialog */ 1863 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOCLIENTMOVE, 0, SWP_NOCLIENTSIZE }, 1864 { WM_SIZE, sent|defwinproc|optional }, 1865 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1866 { EVENT_OBJECT_VALUECHANGE, winevent_hook|lparam|optional, 0/*OBJID_HSCROLL or OBJID_VSCROLL*/, 0 }, 1867 { WM_GETTEXT, sent|optional }, 1868 { WM_GETTEXT, sent|optional }, 1869 { WM_GETTEXT, sent|optional }, 1870 { WM_GETTEXT, sent|optional }, 1871 { 0 } 1872 }; 1873 /* test if we receive the right sequence of messages */ 1874 /* after calling ShowWindow( SW_SHOWNA) */ 1875 static const struct message WmSHOWNAChildInvisParInvis[] = { 1876 { WM_SHOWWINDOW, sent|wparam, 1 }, 1877 { 0 } 1878 }; 1879 static const struct message WmSHOWNAChildVisParInvis[] = { 1880 { WM_SHOWWINDOW, sent|wparam, 1 }, 1881 { 0 } 1882 }; 1883 static const struct message WmSHOWNAChildVisParVis[] = { 1884 { WM_SHOWWINDOW, sent|wparam, 1 }, 1885 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, 1886 { 0 } 1887 }; 1888 static const struct message WmSHOWNAChildInvisParVis[] = { 1889 { WM_SHOWWINDOW, sent|wparam, 1 }, 1890 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1891 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1892 { WM_ERASEBKGND, sent|optional }, 1893 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOACTIVATE|SWP_NOCLIENTMOVE }, 1894 { 0 } 1895 }; 1896 static const struct message WmSHOWNATopVisible[] = { 1897 { WM_SHOWWINDOW, sent|wparam, 1 }, 1898 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, 1899 { WM_NCPAINT, sent|wparam|optional, 1 }, 1900 { WM_GETTEXT, sent|defwinproc|optional }, 1901 { WM_ERASEBKGND, sent|optional }, 1902 { WM_WINDOWPOSCHANGED, sent|optional }, 1903 { 0 } 1904 }; 1905 static const struct message WmSHOWNATopInvisible[] = { 1906 { WM_NOTIFYFORMAT, sent|optional }, 1907 { WM_QUERYUISTATE, sent|optional }, 1908 { WM_WINDOWPOSCHANGING, sent|optional }, 1909 { WM_GETMINMAXINFO, sent|optional }, 1910 { WM_NCCALCSIZE, sent|optional }, 1911 { WM_WINDOWPOSCHANGED, sent|optional }, 1912 { WM_SHOWWINDOW, sent|wparam, 1 }, 1913 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 1914 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 1915 { WM_NCPAINT, sent|wparam|optional, 1 }, 1916 { WM_GETTEXT, sent|defwinproc|optional }, 1917 { WM_ERASEBKGND, sent|optional }, 1918 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 1919 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, 1920 { WM_NCPAINT, sent|wparam|optional, 1 }, 1921 { WM_ERASEBKGND, sent|optional }, 1922 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 1923 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 1924 { WM_MOVE, sent }, 1925 { 0 } 1926 }; 1927 1928 static const struct message WmTrackPopupMenu[] = { 1929 { HCBT_CREATEWND, hook }, 1930 { WM_ENTERMENULOOP, sent|wparam|lparam, TRUE, 0 }, 1931 { WM_INITMENU, sent|lparam, 0, 0 }, 1932 { WM_INITMENUPOPUP, sent|lparam, 0, 0 }, 1933 { 0x0093, sent|optional }, 1934 { 0x0094, sent|optional }, 1935 { 0x0094, sent|optional }, 1936 { WM_ENTERIDLE, sent|wparam, 2 }, 1937 { WM_CAPTURECHANGED, sent }, 1938 { HCBT_DESTROYWND, hook }, 1939 { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, 1940 { WM_MENUSELECT, sent|wparam|lparam, 0xffff0000, 0 }, 1941 { WM_EXITMENULOOP, sent|wparam|lparam, 1, 0 }, 1942 { 0 } 1943 }; 1944 1945 static const struct message WmTrackPopupMenuEsc[] = { 1946 { 0 } 1947 }; 1948 1949 static const struct message WmTrackPopupMenuCapture[] = { 1950 { HCBT_CREATEWND, hook }, 1951 { WM_ENTERMENULOOP, sent|wparam|lparam, TRUE, 0 }, 1952 { WM_CAPTURECHANGED, sent }, 1953 { WM_INITMENU, sent|lparam, 0, 0 }, 1954 { WM_INITMENUPOPUP, sent|lparam, 0, 0 }, 1955 { 0x0093, sent|optional }, 1956 { 0x0094, sent|optional }, 1957 { 0x0094, sent|optional }, 1958 { WM_ENTERIDLE, sent|wparam, 2 }, 1959 { WM_CAPTURECHANGED, sent }, 1960 { HCBT_DESTROYWND, hook }, 1961 { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, 1962 { WM_MENUSELECT, sent|wparam|lparam, 0xffff0000, 0 }, 1963 { WM_EXITMENULOOP, sent|wparam|lparam, 1, 0 }, 1964 { 0 } 1965 }; 1966 1967 static const struct message WmTrackPopupMenuEmpty[] = { 1968 { HCBT_CREATEWND, hook }, 1969 { WM_ENTERMENULOOP, sent|wparam|lparam, TRUE, 0 }, 1970 { WM_INITMENU, sent|lparam, 0, 0 }, 1971 { WM_INITMENUPOPUP, sent|lparam, 0, 0 }, 1972 { 0x0093, sent|optional }, 1973 { 0x0094, sent|optional }, 1974 { 0x0094, sent|optional }, 1975 { WM_CAPTURECHANGED, sent }, 1976 { WM_EXITMENULOOP, sent|wparam|lparam, 1, 0 }, 1977 { HCBT_DESTROYWND, hook }, 1978 { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, 1979 { 0 } 1980 }; 1981 1982 static const struct message WmTrackPopupMenuAbort[] = { 1983 { HCBT_CREATEWND, hook }, 1984 { WM_ENTERMENULOOP, sent|wparam|lparam, TRUE, 0 }, 1985 { WM_INITMENU, sent|lparam, 0, 0 }, 1986 { WM_INITMENUPOPUP, sent|lparam, 0, 0 }, 1987 { 0x0093, sent|optional }, 1988 { 0x0094, sent|optional }, 1989 { 0x0094, sent|optional }, 1990 { WM_CAPTURECHANGED, sent }, 1991 { HCBT_DESTROYWND, hook }, 1992 { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, 1993 { WM_MENUSELECT, sent|wparam|lparam, 0xffff0000, 0 }, 1994 { WM_EXITMENULOOP, sent|wparam|lparam, 1, 0 }, 1995 { 0 } 1996 }; 1997 1998 static BOOL after_end_dialog, test_def_id, paint_loop_done; 1999 static int sequence_cnt, sequence_size; 2000 static struct recvd_message* sequence; 2001 static int log_all_parent_messages; 2002 static CRITICAL_SECTION sequence_cs; 2003 2004 /* user32 functions */ 2005 static HWND (WINAPI *pGetAncestor)(HWND,UINT); 2006 static BOOL (WINAPI *pGetMenuInfo)(HMENU,LPCMENUINFO); 2007 static void (WINAPI *pNotifyWinEvent)(DWORD, HWND, LONG, LONG); 2008 static BOOL (WINAPI *pSetMenuInfo)(HMENU,LPCMENUINFO); 2009 static HWINEVENTHOOK (WINAPI *pSetWinEventHook)(DWORD, DWORD, HMODULE, WINEVENTPROC, DWORD, DWORD, DWORD); 2010 static BOOL (WINAPI *pTrackMouseEvent)(TRACKMOUSEEVENT*); 2011 static BOOL (WINAPI *pUnhookWinEvent)(HWINEVENTHOOK); 2012 static BOOL (WINAPI *pGetMonitorInfoA)(HMONITOR,LPMONITORINFO); 2013 static HMONITOR (WINAPI *pMonitorFromPoint)(POINT,DWORD); 2014 static BOOL (WINAPI *pUpdateLayeredWindow)(HWND,HDC,POINT*,SIZE*,HDC,POINT*,COLORREF,BLENDFUNCTION*,DWORD); 2015 static UINT_PTR (WINAPI *pSetSystemTimer)(HWND, UINT_PTR, UINT, TIMERPROC); 2016 static UINT_PTR (WINAPI *pKillSystemTimer)(HWND, UINT_PTR); 2017 static UINT_PTR (WINAPI *pSetCoalescableTimer)(HWND, UINT_PTR, UINT, TIMERPROC, ULONG); 2018 /* kernel32 functions */ 2019 static BOOL (WINAPI *pGetCPInfoExA)(UINT, DWORD, LPCPINFOEXA); 2020 2021 static void init_procs(void) 2022 { 2023 HMODULE user32 = GetModuleHandleA("user32.dll"); 2024 HMODULE kernel32 = GetModuleHandleA("kernel32.dll"); 2025 2026 #define GET_PROC(dll, func) \ 2027 p ## func = (void*)GetProcAddress(dll, #func); \ 2028 if(!p ## func) { \ 2029 trace("GetProcAddress(%s) failed\n", #func); \ 2030 } 2031 2032 GET_PROC(user32, GetAncestor) 2033 GET_PROC(user32, GetMenuInfo) 2034 GET_PROC(user32, NotifyWinEvent) 2035 GET_PROC(user32, SetMenuInfo) 2036 GET_PROC(user32, SetWinEventHook) 2037 GET_PROC(user32, TrackMouseEvent) 2038 GET_PROC(user32, UnhookWinEvent) 2039 GET_PROC(user32, GetMonitorInfoA) 2040 GET_PROC(user32, MonitorFromPoint) 2041 GET_PROC(user32, UpdateLayeredWindow) 2042 GET_PROC(user32, SetSystemTimer) 2043 GET_PROC(user32, KillSystemTimer) 2044 GET_PROC(user32, SetCoalescableTimer) 2045 2046 GET_PROC(kernel32, GetCPInfoExA) 2047 2048 #undef GET_PROC 2049 } 2050 2051 static const char *get_winpos_flags(UINT flags) 2052 { 2053 static char buffer[300]; 2054 2055 buffer[0] = 0; 2056 #define DUMP(flag) do { if (flags & flag) { strcat( buffer, "|" #flag ); flags &= ~flag; } } while(0) 2057 DUMP( SWP_SHOWWINDOW ); 2058 DUMP( SWP_HIDEWINDOW ); 2059 DUMP( SWP_NOACTIVATE ); 2060 DUMP( SWP_FRAMECHANGED ); 2061 DUMP( SWP_NOCOPYBITS ); 2062 DUMP( SWP_NOOWNERZORDER ); 2063 DUMP( SWP_NOSENDCHANGING ); 2064 DUMP( SWP_DEFERERASE ); 2065 DUMP( SWP_ASYNCWINDOWPOS ); 2066 DUMP( SWP_NOZORDER ); 2067 DUMP( SWP_NOREDRAW ); 2068 DUMP( SWP_NOSIZE ); 2069 DUMP( SWP_NOMOVE ); 2070 DUMP( SWP_NOCLIENTSIZE ); 2071 DUMP( SWP_NOCLIENTMOVE ); 2072 if (flags) sprintf(buffer + strlen(buffer),"|0x%04x", flags); 2073 return buffer + 1; 2074 #undef DUMP 2075 } 2076 2077 static BOOL ignore_message( UINT message ) 2078 { 2079 /* these are always ignored */ 2080 return (message >= 0xc000 || 2081 message == WM_GETICON || 2082 message == WM_GETOBJECT || 2083 message == WM_TIMECHANGE || 2084 message == WM_DISPLAYCHANGE || 2085 message == WM_DEVICECHANGE || 2086 message == WM_DWMNCRENDERINGCHANGED); 2087 } 2088 2089 static unsigned hash_Ly_W(const WCHAR *str) 2090 { 2091 unsigned hash = 0; 2092 2093 for (; *str; str++) 2094 hash = hash * 1664525u + (unsigned char)(*str) + 1013904223u; 2095 2096 return hash; 2097 } 2098 2099 static unsigned hash_Ly(const char *str) 2100 { 2101 unsigned hash = 0; 2102 2103 for (; *str; str++) 2104 hash = hash * 1664525u + (unsigned char)(*str) + 1013904223u; 2105 2106 return hash; 2107 } 2108 2109 #define add_message(msg) add_message_(__LINE__,msg); 2110 static void add_message_(int line, const struct recvd_message *msg) 2111 { 2112 struct recvd_message *seq; 2113 2114 EnterCriticalSection( &sequence_cs ); 2115 if (!sequence) 2116 { 2117 sequence_size = 10; 2118 sequence = HeapAlloc( GetProcessHeap(), 0, sequence_size * sizeof(*sequence) ); 2119 } 2120 if (sequence_cnt == sequence_size) 2121 { 2122 sequence_size *= 2; 2123 sequence = HeapReAlloc( GetProcessHeap(), 0, sequence, sequence_size * sizeof(*sequence) ); 2124 } 2125 assert(sequence); 2126 2127 seq = &sequence[sequence_cnt++]; 2128 seq->hwnd = msg->hwnd; 2129 seq->message = msg->message; 2130 seq->flags = msg->flags; 2131 seq->wParam = msg->wParam; 2132 seq->lParam = msg->lParam; 2133 seq->line = line; 2134 seq->descr = msg->descr; 2135 seq->output[0] = 0; 2136 LeaveCriticalSection( &sequence_cs ); 2137 2138 if (msg->descr) 2139 { 2140 if (msg->flags & hook) 2141 { 2142 static const char * const CBT_code_name[10] = 2143 { 2144 "HCBT_MOVESIZE", 2145 "HCBT_MINMAX", 2146 "HCBT_QS", 2147 "HCBT_CREATEWND", 2148 "HCBT_DESTROYWND", 2149 "HCBT_ACTIVATE", 2150 "HCBT_CLICKSKIPPED", 2151 "HCBT_KEYSKIPPED", 2152 "HCBT_SYSCOMMAND", 2153 "HCBT_SETFOCUS" 2154 }; 2155 const char *code_name = (msg->message <= HCBT_SETFOCUS) ? CBT_code_name[msg->message] : "Unknown"; 2156 2157 sprintf( seq->output, "%s: hook %d (%s) wp %08lx lp %08lx", 2158 msg->descr, msg->message, code_name, msg->wParam, msg->lParam ); 2159 } 2160 else if (msg->flags & winevent_hook) 2161 { 2162 sprintf( seq->output, "%s: winevent %p %08x %08lx %08lx", 2163 msg->descr, msg->hwnd, msg->message, msg->wParam, msg->lParam ); 2164 } 2165 else 2166 { 2167 switch (msg->message) 2168 { 2169 case WM_WINDOWPOSCHANGING: 2170 case WM_WINDOWPOSCHANGED: 2171 { 2172 WINDOWPOS *winpos = (WINDOWPOS *)msg->lParam; 2173 2174 sprintf( seq->output, "%s: %p WM_WINDOWPOS%s wp %08lx lp %08lx after %p x %d y %d cx %d cy %d flags %s", 2175 msg->descr, msg->hwnd, 2176 (msg->message == WM_WINDOWPOSCHANGING) ? "CHANGING" : "CHANGED", 2177 msg->wParam, msg->lParam, winpos->hwndInsertAfter, 2178 winpos->x, winpos->y, winpos->cx, winpos->cy, 2179 get_winpos_flags(winpos->flags) ); 2180 2181 /* Log only documented flags, win2k uses 0x1000 and 0x2000 2182 * in the high word for internal purposes 2183 */ 2184 seq->wParam = winpos->flags & 0xffff; 2185 /* We are not interested in the flags that don't match under XP and Win9x */ 2186 seq->wParam &= ~SWP_NOZORDER; 2187 break; 2188 } 2189 2190 case WM_DRAWITEM: 2191 { 2192 DRAW_ITEM_STRUCT di; 2193 DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)msg->lParam; 2194 2195 sprintf( seq->output, "%s: %p WM_DRAWITEM: type %x, ctl_id %x, item_id %x, action %x, state %x", 2196 msg->descr, msg->hwnd, dis->CtlType, dis->CtlID, 2197 dis->itemID, dis->itemAction, dis->itemState); 2198 2199 di.u.lp = 0; 2200 di.u.item.type = dis->CtlType; 2201 di.u.item.ctl_id = dis->CtlID; 2202 if (dis->CtlType == ODT_LISTBOX || 2203 dis->CtlType == ODT_COMBOBOX || 2204 dis->CtlType == ODT_MENU) 2205 di.u.item.item_id = dis->itemID; 2206 di.u.item.action = dis->itemAction; 2207 di.u.item.state = dis->itemState; 2208 2209 seq->lParam = di.u.lp; 2210 break; 2211 } 2212 2213 case WM_MEASUREITEM: 2214 { 2215 MEASURE_ITEM_STRUCT mi; 2216 MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *)msg->lParam; 2217 BOOL is_unicode_data = TRUE; 2218 2219 sprintf( seq->output, "%s: %p WM_MEASUREITEM: CtlType %#x, CtlID %#x, itemID %#x, itemData %#lx", 2220 msg->descr, msg->hwnd, mis->CtlType, mis->CtlID, 2221 mis->itemID, mis->itemData); 2222 2223 if (mis->CtlType == ODT_LISTBOX) 2224 { 2225 HWND ctrl = GetDlgItem(msg->hwnd, mis->CtlID); 2226 is_unicode_data = GetWindowLongA(ctrl, GWL_STYLE) & LBS_HASSTRINGS; 2227 } 2228 2229 mi.u.wp = 0; 2230 mi.u.item.CtlType = mis->CtlType; 2231 mi.u.item.CtlID = mis->CtlID; 2232 mi.u.item.itemID = mis->itemID; 2233 mi.u.item.wParam = msg->wParam; 2234 seq->wParam = mi.u.wp; 2235 if (is_unicode_data) 2236 seq->lParam = mis->itemData ? hash_Ly_W((const WCHAR *)mis->itemData) : 0; 2237 else 2238 seq->lParam = mis->itemData ? hash_Ly((const char *)mis->itemData) : 0; 2239 break; 2240 } 2241 2242 case WM_COMPAREITEM: 2243 { 2244 COMPAREITEMSTRUCT *cis = (COMPAREITEMSTRUCT *)msg->lParam; 2245 HWND ctrl = GetDlgItem(msg->hwnd, cis->CtlID); 2246 BOOL is_unicode_data = TRUE; 2247 2248 ok(msg->wParam == cis->CtlID, "expected %#x, got %#lx\n", cis->CtlID, msg->wParam); 2249 ok(cis->hwndItem == ctrl, "expected %p, got %p\n", ctrl, cis->hwndItem); 2250 ok((int)cis->itemID1 >= 0, "expected >= 0, got %d\n", cis->itemID1); 2251 ok((int)cis->itemID2 == -1, "expected -1, got %d\n", cis->itemID2); 2252 2253 sprintf( seq->output, "%s: %p WM_COMPAREITEM: CtlType %#x, CtlID %#x, itemID1 %#x, itemData1 %#lx, itemID2 %#x, itemData2 %#lx", 2254 msg->descr, msg->hwnd, cis->CtlType, cis->CtlID, 2255 cis->itemID1, cis->itemData1, cis->itemID2, cis->itemData2); 2256 2257 if (cis->CtlType == ODT_LISTBOX) 2258 is_unicode_data = GetWindowLongA(ctrl, GWL_STYLE) & LBS_HASSTRINGS; 2259 2260 if (is_unicode_data) 2261 { 2262 seq->wParam = cis->itemData1 ? hash_Ly_W((const WCHAR *)cis->itemData1) : 0; 2263 seq->lParam = cis->itemData2 ? hash_Ly_W((const WCHAR *)cis->itemData2) : 0; 2264 } 2265 else 2266 { 2267 seq->wParam = cis->itemData1 ? hash_Ly((const char *)cis->itemData1) : 0; 2268 seq->lParam = cis->itemData2 ? hash_Ly((const char *)cis->itemData2) : 0; 2269 } 2270 break; 2271 } 2272 2273 default: 2274 if (msg->message >= 0xc000) return; /* ignore registered messages */ 2275 sprintf( seq->output, "%s: %p %04x wp %08lx lp %08lx", 2276 msg->descr, msg->hwnd, msg->message, msg->wParam, msg->lParam ); 2277 } 2278 if (msg->flags & (sent|posted|parent|defwinproc|beginpaint)) 2279 sprintf( seq->output + strlen(seq->output), " (flags %x)", msg->flags ); 2280 } 2281 } 2282 } 2283 2284 /* try to make sure pending X events have been processed before continuing */ 2285 static void flush_events(void) 2286 { 2287 MSG msg; 2288 int diff = 200; 2289 int min_timeout = 100; 2290 DWORD time = GetTickCount() + diff; 2291 2292 while (diff > 0) 2293 { 2294 if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break; 2295 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 2296 diff = time - GetTickCount(); 2297 } 2298 } 2299 2300 static void flush_sequence(void) 2301 { 2302 EnterCriticalSection( &sequence_cs ); 2303 HeapFree(GetProcessHeap(), 0, sequence); 2304 sequence = 0; 2305 sequence_cnt = sequence_size = 0; 2306 LeaveCriticalSection( &sequence_cs ); 2307 } 2308 2309 static void dump_sequence(const struct message *expected, const char *context, const char *file, int line) 2310 { 2311 const struct recvd_message *actual = sequence; 2312 unsigned int count = 0; 2313 2314 trace_(file, line)("Failed sequence %s:\n", context ); 2315 while (expected->message && actual->message) 2316 { 2317 if (actual->output[0]) 2318 { 2319 if (expected->flags & hook) 2320 { 2321 trace_(file, line)( " %u: expected: hook %04x - actual: %s\n", 2322 count, expected->message, actual->output ); 2323 } 2324 else if (expected->flags & winevent_hook) 2325 { 2326 trace_(file, line)( " %u: expected: winevent %04x - actual: %s\n", 2327 count, expected->message, actual->output ); 2328 } 2329 else if (expected->flags & kbd_hook) 2330 { 2331 trace_(file, line)( " %u: expected: kbd %04x - actual: %s\n", 2332 count, expected->message, actual->output ); 2333 } 2334 else 2335 { 2336 trace_(file, line)( " %u: expected: msg %04x - actual: %s\n", 2337 count, expected->message, actual->output ); 2338 } 2339 } 2340 2341 if (expected->message == actual->message) 2342 { 2343 if ((expected->flags & defwinproc) != (actual->flags & defwinproc) && 2344 (expected->flags & optional)) 2345 { 2346 /* don't match messages if their defwinproc status differs */ 2347 expected++; 2348 } 2349 else 2350 { 2351 expected++; 2352 actual++; 2353 } 2354 } 2355 /* silently drop winevent messages if there is no support for them */ 2356 else if ((expected->flags & optional) || ((expected->flags & winevent_hook) && !hEvent_hook)) 2357 expected++; 2358 else 2359 { 2360 expected++; 2361 actual++; 2362 } 2363 count++; 2364 } 2365 2366 /* optional trailing messages */ 2367 while (expected->message && ((expected->flags & optional) || 2368 ((expected->flags & winevent_hook) && !hEvent_hook))) 2369 { 2370 trace_(file, line)( " %u: expected: msg %04x - actual: nothing\n", count, expected->message ); 2371 expected++; 2372 count++; 2373 } 2374 2375 if (expected->message) 2376 { 2377 trace_(file, line)( " %u: expected: msg %04x - actual: nothing\n", count, expected->message ); 2378 return; 2379 } 2380 2381 while (actual->message && actual->output[0]) 2382 { 2383 trace_(file, line)( " %u: expected: nothing - actual: %s\n", count, actual->output ); 2384 actual++; 2385 count++; 2386 } 2387 } 2388 2389 #define ok_sequence( exp, contx, todo) \ 2390 ok_sequence_( (exp), (contx), (todo), __FILE__, __LINE__) 2391 2392 2393 static void ok_sequence_(const struct message *expected_list, const char *context, BOOL todo, 2394 const char *file, int line) 2395 { 2396 static const struct recvd_message end_of_sequence; 2397 const struct message *expected = expected_list; 2398 const struct recvd_message *actual; 2399 int failcount = 0, dump = 0; 2400 unsigned int count = 0; 2401 2402 add_message(&end_of_sequence); 2403 2404 actual = sequence; 2405 2406 while (expected->message && actual->message) 2407 { 2408 if (expected->message == actual->message && 2409 !((expected->flags ^ actual->flags) & (hook|winevent_hook|kbd_hook))) 2410 { 2411 if (expected->flags & wparam) 2412 { 2413 if (((expected->wParam ^ actual->wParam) & ~expected->wp_mask) && todo) 2414 { 2415 todo_wine { 2416 failcount ++; 2417 if (strcmp(winetest_platform, "wine")) dump++; 2418 ok_( file, line) (FALSE, 2419 "%s: %u: in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n", 2420 context, count, expected->message, expected->wParam, actual->wParam); 2421 } 2422 } 2423 else 2424 { 2425 ok_( file, line)( ((expected->wParam ^ actual->wParam) & ~expected->wp_mask) == 0, 2426 "%s: %u: in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n", 2427 context, count, expected->message, expected->wParam, actual->wParam); 2428 if ((expected->wParam ^ actual->wParam) & ~expected->wp_mask) dump++; 2429 } 2430 2431 } 2432 if (expected->flags & lparam) 2433 { 2434 if (((expected->lParam ^ actual->lParam) & ~expected->lp_mask) && todo) 2435 { 2436 todo_wine { 2437 failcount ++; 2438 if (strcmp(winetest_platform, "wine")) dump++; 2439 ok_( file, line) (FALSE, 2440 "%s: %u: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n", 2441 context, count, expected->message, expected->lParam, actual->lParam); 2442 } 2443 } 2444 else 2445 { 2446 ok_( file, line)(((expected->lParam ^ actual->lParam) & ~expected->lp_mask) == 0, 2447 "%s: %u: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n", 2448 context, count, expected->message, expected->lParam, actual->lParam); 2449 if ((expected->lParam ^ actual->lParam) & ~expected->lp_mask) dump++; 2450 } 2451 } 2452 if ((expected->flags & optional) && 2453 ((expected->flags ^ actual->flags) & (defwinproc|parent))) 2454 { 2455 /* don't match optional messages if their defwinproc or parent status differs */ 2456 expected++; 2457 count++; 2458 continue; 2459 } 2460 if ((expected->flags & defwinproc) != (actual->flags & defwinproc) && todo) 2461 { 2462 todo_wine { 2463 failcount ++; 2464 if (strcmp(winetest_platform, "wine")) dump++; 2465 ok_( file, line) (FALSE, 2466 "%s: %u: the msg 0x%04x should %shave been sent by DefWindowProc\n", 2467 context, count, expected->message, (expected->flags & defwinproc) ? "" : "NOT "); 2468 } 2469 } 2470 else 2471 { 2472 ok_( file, line) ((expected->flags & defwinproc) == (actual->flags & defwinproc), 2473 "%s: %u: the msg 0x%04x should %shave been sent by DefWindowProc\n", 2474 context, count, expected->message, (expected->flags & defwinproc) ? "" : "NOT "); 2475 if ((expected->flags & defwinproc) != (actual->flags & defwinproc)) dump++; 2476 } 2477 2478 ok_( file, line) ((expected->flags & beginpaint) == (actual->flags & beginpaint), 2479 "%s: %u: the msg 0x%04x should %shave been sent by BeginPaint\n", 2480 context, count, expected->message, (expected->flags & beginpaint) ? "" : "NOT "); 2481 if ((expected->flags & beginpaint) != (actual->flags & beginpaint)) dump++; 2482 2483 ok_( file, line) ((expected->flags & (sent|posted)) == (actual->flags & (sent|posted)), 2484 "%s: %u: the msg 0x%04x should have been %s\n", 2485 context, count, expected->message, (expected->flags & posted) ? "posted" : "sent"); 2486 if ((expected->flags & (sent|posted)) != (actual->flags & (sent|posted))) dump++; 2487 2488 ok_( file, line) ((expected->flags & parent) == (actual->flags & parent), 2489 "%s: %u: the msg 0x%04x was expected in %s\n", 2490 context, count, expected->message, (expected->flags & parent) ? "parent" : "child"); 2491 if ((expected->flags & parent) != (actual->flags & parent)) dump++; 2492 2493 ok_( file, line) ((expected->flags & hook) == (actual->flags & hook), 2494 "%s: %u: the msg 0x%04x should have been sent by a hook\n", 2495 context, count, expected->message); 2496 if ((expected->flags & hook) != (actual->flags & hook)) dump++; 2497 2498 ok_( file, line) ((expected->flags & winevent_hook) == (actual->flags & winevent_hook), 2499 "%s: %u: the msg 0x%04x should have been sent by a winevent hook\n", 2500 context, count, expected->message); 2501 if ((expected->flags & winevent_hook) != (actual->flags & winevent_hook)) dump++; 2502 2503 ok_( file, line) ((expected->flags & kbd_hook) == (actual->flags & kbd_hook), 2504 "%s: %u: the msg 0x%04x should have been sent by a keyboard hook\n", 2505 context, count, expected->message); 2506 if ((expected->flags & kbd_hook) != (actual->flags & kbd_hook)) dump++; 2507 2508 expected++; 2509 actual++; 2510 } 2511 /* silently drop hook messages if there is no support for them */ 2512 else if ((expected->flags & optional) || 2513 ((expected->flags & hook) && !hCBT_hook) || 2514 ((expected->flags & winevent_hook) && !hEvent_hook) || 2515 ((expected->flags & kbd_hook) && !hKBD_hook)) 2516 expected++; 2517 else if (todo) 2518 { 2519 failcount++; 2520 todo_wine { 2521 if (strcmp(winetest_platform, "wine")) dump++; 2522 ok_( file, line) (FALSE, "%s: %u: the msg 0x%04x was expected, but got msg 0x%04x instead\n", 2523 context, count, expected->message, actual->message); 2524 } 2525 goto done; 2526 } 2527 else 2528 { 2529 ok_( file, line) (FALSE, "%s: %u: the msg 0x%04x was expected, but got msg 0x%04x instead\n", 2530 context, count, expected->message, actual->message); 2531 dump++; 2532 expected++; 2533 actual++; 2534 } 2535 count++; 2536 } 2537 2538 /* skip all optional trailing messages */ 2539 while (expected->message && ((expected->flags & optional) || 2540 ((expected->flags & hook) && !hCBT_hook) || 2541 ((expected->flags & winevent_hook) && !hEvent_hook))) 2542 expected++; 2543 2544 if (todo) 2545 { 2546 todo_wine { 2547 if (expected->message || actual->message) { 2548 failcount++; 2549 if (strcmp(winetest_platform, "wine")) dump++; 2550 ok_( file, line) (FALSE, "%s: %u: the msg sequence is not complete: expected %04x - actual %04x\n", 2551 context, count, expected->message, actual->message); 2552 } 2553 } 2554 } 2555 else 2556 { 2557 if (expected->message || actual->message) 2558 { 2559 dump++; 2560 ok_( file, line) (FALSE, "%s: %u: the msg sequence is not complete: expected %04x - actual %04x\n", 2561 context, count, expected->message, actual->message); 2562 } 2563 } 2564 if( todo && !failcount) /* succeeded yet marked todo */ 2565 todo_wine { 2566 if (!strcmp(winetest_platform, "wine")) dump++; 2567 ok_( file, line)( TRUE, "%s: marked \"todo_wine\" but succeeds\n", context); 2568 } 2569 2570 done: 2571 if (dump) dump_sequence(expected_list, context, file, line); 2572 flush_sequence(); 2573 } 2574 2575 #define expect(EXPECTED,GOT) ok((GOT)==(EXPECTED), "Expected %d, got %d\n", (EXPECTED), (GOT)) 2576 2577 /******************************** MDI test **********************************/ 2578 2579 /* CreateWindow for MDI frame window, initially visible */ 2580 static const struct message WmCreateMDIframeSeq[] = { 2581 { HCBT_CREATEWND, hook }, 2582 { WM_GETMINMAXINFO, sent }, 2583 { WM_NCCREATE, sent }, 2584 { WM_NCCALCSIZE, sent|wparam, 0 }, 2585 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, 2586 { WM_CREATE, sent }, 2587 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 2588 { WM_NOTIFYFORMAT, sent|optional }, 2589 { WM_QUERYUISTATE, sent|optional }, 2590 { WM_WINDOWPOSCHANGING, sent|optional }, 2591 { WM_GETMINMAXINFO, sent|optional }, 2592 { WM_NCCALCSIZE, sent|optional }, 2593 { WM_WINDOWPOSCHANGED, sent|optional }, 2594 { WM_SHOWWINDOW, sent|wparam, 1 }, 2595 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 2596 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 2597 { HCBT_ACTIVATE, hook }, 2598 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 2599 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 2600 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* XP */ 2601 { WM_ACTIVATEAPP, sent|wparam|optional, 1 }, /* Win9x doesn't send it */ 2602 { WM_NCACTIVATE, sent }, 2603 { WM_GETTEXT, sent|defwinproc|optional }, 2604 { WM_ACTIVATE, sent|wparam, 1 }, 2605 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* Win9x */ 2606 { HCBT_SETFOCUS, hook }, 2607 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 2608 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 2609 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2610 { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, 2611 /* Win9x adds SWP_NOZORDER below */ 2612 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2613 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* XP */ 2614 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 2615 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 2616 { WM_MOVE, sent }, 2617 { 0 } 2618 }; 2619 /* DestroyWindow for MDI frame window, initially visible */ 2620 static const struct message WmDestroyMDIframeSeq[] = { 2621 { HCBT_DESTROYWND, hook }, 2622 { 0x0090, sent|optional }, 2623 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2624 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 2625 { WM_NCACTIVATE, sent|wparam|optional, 0 }, /* Win9x */ 2626 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2627 { WM_NCACTIVATE, sent|wparam|optional, 0 }, /* XP */ 2628 { WM_ACTIVATE, sent|wparam|optional, 0 }, /* Win9x */ 2629 { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, /* Win9x */ 2630 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 2631 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, 2632 { WM_DESTROY, sent }, 2633 { WM_NCDESTROY, sent }, 2634 { 0 } 2635 }; 2636 /* CreateWindow for MDI client window, initially visible */ 2637 static const struct message WmCreateMDIclientSeq[] = { 2638 { HCBT_CREATEWND, hook }, 2639 { WM_NCCREATE, sent }, 2640 { WM_NCCALCSIZE, sent|wparam, 0 }, 2641 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|optional, 0, 0 }, 2642 { WM_CREATE, sent }, 2643 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|optional, 0, 0 }, 2644 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 2645 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 2646 { WM_MOVE, sent }, 2647 { WM_PARENTNOTIFY, sent|wparam, WM_CREATE }, /* in MDI frame */ 2648 { WM_SHOWWINDOW, sent|wparam, 1 }, 2649 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2650 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 2651 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2652 { 0 } 2653 }; 2654 /* ShowWindow(SW_SHOW) for MDI client window */ 2655 static const struct message WmShowMDIclientSeq[] = { 2656 { WM_SHOWWINDOW, sent|wparam, 1 }, 2657 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2658 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 2659 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2660 { 0 } 2661 }; 2662 /* ShowWindow(SW_HIDE) for MDI client window */ 2663 static const struct message WmHideMDIclientSeq[] = { 2664 { WM_SHOWWINDOW, sent|wparam, 0 }, 2665 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2666 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam|optional, 0, 0 }, /* win2000 */ 2667 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP */ 2668 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2669 { 0 } 2670 }; 2671 /* DestroyWindow for MDI client window, initially visible */ 2672 static const struct message WmDestroyMDIclientSeq[] = { 2673 { HCBT_DESTROYWND, hook }, 2674 { 0x0090, sent|optional }, 2675 { WM_PARENTNOTIFY, sent|wparam, WM_DESTROY }, /* in MDI frame */ 2676 { WM_SHOWWINDOW, sent|wparam, 0 }, 2677 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2678 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 2679 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2680 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, 2681 { WM_DESTROY, sent }, 2682 { WM_NCDESTROY, sent }, 2683 { 0 } 2684 }; 2685 /* CreateWindow for MDI child window, initially visible */ 2686 static const struct message WmCreateMDIchildVisibleSeq[] = { 2687 { HCBT_CREATEWND, hook }, 2688 { WM_NCCREATE, sent }, 2689 { WM_NCCALCSIZE, sent|wparam, 0 }, 2690 { WM_CREATE, sent }, 2691 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 2692 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 2693 { WM_MOVE, sent }, 2694 /* Win2k sends wparam set to 2695 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated), 2696 * while Win9x doesn't bother to set child window id according to 2697 * CLIENTCREATESTRUCT.idFirstChild 2698 */ 2699 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */ 2700 { WM_SHOWWINDOW, sent|wparam, 1 }, 2701 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2702 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 2703 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2704 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ }, 2705 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 2706 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 2707 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2708 2709 /* Win9x: message sequence terminates here. */ 2710 2711 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, 2712 { HCBT_SETFOCUS, hook }, /* in MDI client */ 2713 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 2714 { WM_IME_NOTIFY, sent|wparam|optional, 2 }, /* in MDI client */ 2715 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2716 { WM_SETFOCUS, sent }, /* in MDI client */ 2717 { HCBT_SETFOCUS, hook }, 2718 { WM_KILLFOCUS, sent }, /* in MDI client */ 2719 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 2720 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 2721 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2722 { WM_SETFOCUS, sent|defwinproc }, 2723 { WM_MDIACTIVATE, sent|defwinproc }, 2724 { 0 } 2725 }; 2726 /* WM_CHILDACTIVATE sent to disabled window */ 2727 static const struct message WmChildActivateDisabledWindowSeq[] = { 2728 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 2729 { 0 } 2730 }; 2731 /* WM_CHILDACTIVATE sent to enabled window */ 2732 static const struct message WmChildActivateWindowSeq[] = { 2733 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 2734 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, 2735 { WM_MDIACTIVATE, sent|defwinproc }, 2736 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2737 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2738 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, 2739 { HCBT_SETFOCUS, hook }, 2740 { WM_KILLFOCUS, sent|defwinproc }, 2741 { WM_SETFOCUS, sent }, 2742 { HCBT_SETFOCUS, hook }, 2743 { WM_KILLFOCUS, sent }, 2744 { WM_SETFOCUS, sent|defwinproc }, 2745 { WM_MDIACTIVATE, sent|defwinproc }, 2746 { 0 } 2747 }; 2748 /* CreateWindow for MDI child window with invisible parent */ 2749 static const struct message WmCreateMDIchildInvisibleParentSeq[] = { 2750 { HCBT_CREATEWND, hook }, 2751 { WM_GETMINMAXINFO, sent }, 2752 { WM_NCCREATE, sent }, 2753 { WM_NCCALCSIZE, sent|wparam, 0 }, 2754 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|optional, 0, 0 }, 2755 { WM_CREATE, sent }, 2756 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 2757 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 2758 { WM_MOVE, sent }, 2759 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */ 2760 { WM_SHOWWINDOW, sent|wparam, 1 }, 2761 { WM_MDIREFRESHMENU, sent }, /* in MDI client */ 2762 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 2763 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 2764 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2765 2766 /* Win9x: message sequence terminates here. */ 2767 2768 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, 2769 { HCBT_SETFOCUS, hook }, /* in MDI client */ 2770 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 2771 { WM_IME_NOTIFY, sent|wparam|optional, 2 }, /* in MDI client */ 2772 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2773 { WM_SETFOCUS, sent }, /* in MDI client */ 2774 { HCBT_SETFOCUS, hook }, 2775 { WM_KILLFOCUS, sent }, /* in MDI client */ 2776 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 2777 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 2778 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2779 { WM_SETFOCUS, sent|defwinproc }, 2780 { WM_MDIACTIVATE, sent|defwinproc }, 2781 { 0 } 2782 }; 2783 /* DestroyWindow for MDI child window, initially visible */ 2784 static const struct message WmDestroyMDIchildVisibleSeq[] = { 2785 { HCBT_DESTROYWND, hook }, 2786 /* Win2k sends wparam set to 2787 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated), 2788 * while Win9x doesn't bother to set child window id according to 2789 * CLIENTCREATESTRUCT.idFirstChild 2790 */ 2791 { 0x0090, sent|optional }, 2792 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */ 2793 { WM_SHOWWINDOW, sent|wparam, 0 }, 2794 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2795 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 2796 { WM_ERASEBKGND, sent|parent|optional }, 2797 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2798 2799 /* { WM_DESTROY, sent } 2800 * Win9x: message sequence terminates here. 2801 */ 2802 2803 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */ 2804 { WM_KILLFOCUS, sent }, 2805 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 2806 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 2807 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2808 { WM_SETFOCUS, sent }, /* in MDI client */ 2809 2810 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */ 2811 { WM_KILLFOCUS, sent }, /* in MDI client */ 2812 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 2813 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 2814 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2815 { WM_SETFOCUS, sent }, /* in MDI client */ 2816 2817 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, 2818 2819 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */ 2820 { WM_KILLFOCUS, sent }, 2821 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 2822 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 2823 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2824 { WM_SETFOCUS, sent }, /* in MDI client */ 2825 2826 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */ 2827 { WM_KILLFOCUS, sent }, /* in MDI client */ 2828 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 2829 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 2830 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2831 { WM_SETFOCUS, sent }, /* in MDI client */ 2832 2833 { WM_DESTROY, sent }, 2834 2835 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */ 2836 { WM_KILLFOCUS, sent }, 2837 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 2838 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 2839 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2840 { WM_SETFOCUS, sent }, /* in MDI client */ 2841 2842 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */ 2843 { WM_KILLFOCUS, sent }, /* in MDI client */ 2844 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 2845 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 2846 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2847 { WM_SETFOCUS, sent }, /* in MDI client */ 2848 2849 { WM_NCDESTROY, sent }, 2850 { 0 } 2851 }; 2852 /* CreateWindow for MDI child window, initially invisible */ 2853 static const struct message WmCreateMDIchildInvisibleSeq[] = { 2854 { HCBT_CREATEWND, hook }, 2855 { WM_NCCREATE, sent }, 2856 { WM_NCCALCSIZE, sent|wparam, 0 }, 2857 { WM_CREATE, sent }, 2858 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 2859 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 2860 { WM_MOVE, sent }, 2861 /* Win2k sends wparam set to 2862 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated), 2863 * while Win9x doesn't bother to set child window id according to 2864 * CLIENTCREATESTRUCT.idFirstChild 2865 */ 2866 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */ 2867 { 0 } 2868 }; 2869 /* DestroyWindow for MDI child window, initially invisible */ 2870 static const struct message WmDestroyMDIchildInvisibleSeq[] = { 2871 { HCBT_DESTROYWND, hook }, 2872 /* Win2k sends wparam set to 2873 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated), 2874 * while Win9x doesn't bother to set child window id according to 2875 * CLIENTCREATESTRUCT.idFirstChild 2876 */ 2877 { 0x0090, sent|optional }, 2878 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */ 2879 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, 2880 { WM_DESTROY, sent }, 2881 { WM_NCDESTROY, sent }, 2882 /* FIXME: Wine destroys an icon/title window while Windows doesn't */ 2883 { WM_PARENTNOTIFY, sent|wparam|optional, WM_DESTROY }, /* MDI client */ 2884 { 0 } 2885 }; 2886 /* CreateWindow for the 1st MDI child window, initially visible and maximized */ 2887 static const struct message WmCreateMDIchildVisibleMaxSeq1[] = { 2888 { HCBT_CREATEWND, hook }, 2889 { WM_NCCREATE, sent }, 2890 { WM_NCCALCSIZE, sent|wparam, 0 }, 2891 { WM_CREATE, sent }, 2892 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 2893 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 2894 { WM_MOVE, sent }, 2895 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 2896 { WM_GETMINMAXINFO, sent }, 2897 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_STATECHANGED }, 2898 { WM_NCCALCSIZE, sent|wparam, 1 }, 2899 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 2900 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 2901 /* in MDI frame */ 2902 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2903 { WM_NCCALCSIZE, sent|wparam, 1 }, 2904 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2905 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 2906 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 2907 /* Win2k sends wparam set to 2908 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated), 2909 * while Win9x doesn't bother to set child window id according to 2910 * CLIENTCREATESTRUCT.idFirstChild 2911 */ 2912 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */ 2913 { WM_SHOWWINDOW, sent|wparam, 1 }, 2914 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2915 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 2916 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2917 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ }, 2918 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 2919 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 2920 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc|optional, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE, 0, SWP_FRAMECHANGED }, 2921 2922 /* Win9x: message sequence terminates here. */ 2923 2924 { WM_NCACTIVATE, sent|wparam|defwinproc|optional, 1 }, 2925 { HCBT_SETFOCUS, hook|optional }, /* in MDI client */ 2926 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 2927 { WM_IME_NOTIFY, sent|wparam|optional, 2 }, /* in MDI client */ 2928 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2929 { WM_SETFOCUS, sent|optional }, /* in MDI client */ 2930 { HCBT_SETFOCUS, hook|optional }, 2931 { WM_KILLFOCUS, sent|optional }, /* in MDI client */ 2932 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 2933 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 2934 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2935 { WM_SETFOCUS, sent|defwinproc|optional }, 2936 { WM_MDIACTIVATE, sent|defwinproc|optional }, 2937 /* in MDI frame */ 2938 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2939 { WM_NCCALCSIZE, sent|wparam, 1 }, 2940 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2941 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 2942 { 0 } 2943 }; 2944 /* CreateWindow for the 2nd MDI child window, initially visible and maximized */ 2945 static const struct message WmCreateMDIchildVisibleMaxSeq2[] = { 2946 /* restore the 1st MDI child */ 2947 { WM_SETREDRAW, sent|wparam, 0 }, 2948 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWNORMAL }, 2949 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, 2950 { WM_NCCALCSIZE, sent|wparam, 1 }, 2951 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 2952 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 2953 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 2954 /* in MDI frame */ 2955 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2956 { WM_NCCALCSIZE, sent|wparam, 1 }, 2957 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2958 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 2959 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 2960 { WM_SETREDRAW, sent|wparam, 1 }, /* in the 1st MDI child */ 2961 /* create the 2nd MDI child */ 2962 { HCBT_CREATEWND, hook }, 2963 { WM_NCCREATE, sent }, 2964 { WM_NCCALCSIZE, sent|wparam, 0 }, 2965 { WM_CREATE, sent }, 2966 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 2967 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 2968 { WM_MOVE, sent }, 2969 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 2970 { WM_GETMINMAXINFO, sent }, 2971 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_STATECHANGED }, 2972 { WM_NCCALCSIZE, sent|wparam, 1 }, 2973 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 2974 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 2975 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 2976 /* in MDI frame */ 2977 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2978 { WM_NCCALCSIZE, sent|wparam, 1 }, 2979 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2980 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 2981 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 2982 /* Win2k sends wparam set to 2983 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated), 2984 * while Win9x doesn't bother to set child window id according to 2985 * CLIENTCREATESTRUCT.idFirstChild 2986 */ 2987 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */ 2988 { WM_SHOWWINDOW, sent|wparam, 1 }, 2989 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 2990 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 2991 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 2992 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ }, 2993 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 2994 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 2995 2996 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 1st MDI child */ 2997 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 1st MDI child */ 2998 2999 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3000 3001 /* Win9x: message sequence terminates here. */ 3002 3003 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, 3004 { HCBT_SETFOCUS, hook }, 3005 { WM_KILLFOCUS, sent|defwinproc|optional }, /* in the 1st MDI child */ 3006 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 }, /* in the 1st MDI child */ 3007 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 3008 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3009 { WM_SETFOCUS, sent }, /* in MDI client */ 3010 { HCBT_SETFOCUS, hook }, 3011 { WM_KILLFOCUS, sent }, /* in MDI client */ 3012 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 3013 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 3014 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3015 { WM_SETFOCUS, sent|defwinproc }, 3016 3017 { WM_MDIACTIVATE, sent|defwinproc }, 3018 /* in MDI frame */ 3019 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3020 { WM_NCCALCSIZE, sent|wparam, 1 }, 3021 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3022 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3023 { 0 } 3024 }; 3025 /* WM_MDICREATE MDI child window, initially visible and maximized */ 3026 static const struct message WmCreateMDIchildVisibleMaxSeq3[] = { 3027 { WM_MDICREATE, sent }, 3028 { HCBT_CREATEWND, hook }, 3029 { WM_NCCREATE, sent }, 3030 { WM_NCCALCSIZE, sent|wparam, 0 }, 3031 { WM_CREATE, sent }, 3032 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 3033 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 3034 { WM_MOVE, sent }, 3035 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 3036 { WM_GETMINMAXINFO, sent }, 3037 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_STATECHANGED }, 3038 { WM_NCCALCSIZE, sent|wparam, 1 }, 3039 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 3040 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 3041 3042 /* in MDI frame */ 3043 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3044 { WM_NCCALCSIZE, sent|wparam, 1 }, 3045 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3046 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3047 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3048 3049 /* Win2k sends wparam set to 3050 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated), 3051 * while Win9x doesn't bother to set child window id according to 3052 * CLIENTCREATESTRUCT.idFirstChild 3053 */ 3054 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */ 3055 { WM_SHOWWINDOW, sent|wparam, 1 }, 3056 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3057 3058 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 3059 3060 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3061 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ }, 3062 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 3063 3064 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 3065 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3066 3067 /* Win9x: message sequence terminates here. */ 3068 3069 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, 3070 { WM_SETFOCUS, sent|optional }, /* in MDI client */ 3071 { HCBT_SETFOCUS, hook }, /* in MDI client */ 3072 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 3073 { WM_IME_NOTIFY, sent|wparam|optional, 2 }, 3074 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 }, 3075 { WM_SETFOCUS, sent|optional }, /* in MDI client */ 3076 { HCBT_SETFOCUS, hook|optional }, 3077 { WM_KILLFOCUS, sent }, /* in MDI client */ 3078 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 3079 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 3080 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3081 { WM_SETFOCUS, sent|defwinproc }, 3082 3083 { WM_MDIACTIVATE, sent|defwinproc }, 3084 3085 /* in MDI child */ 3086 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3087 { WM_NCCALCSIZE, sent|wparam, 1 }, 3088 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3089 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 3090 3091 /* in MDI frame */ 3092 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3093 { WM_NCCALCSIZE, sent|wparam, 1 }, 3094 { 0x0093, sent|defwinproc|optional }, 3095 { 0x0093, sent|defwinproc|optional }, 3096 { 0x0093, sent|defwinproc|optional }, 3097 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3098 { WM_MOVE, sent|defwinproc }, 3099 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 3100 3101 /* in MDI client */ 3102 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE }, 3103 { WM_NCCALCSIZE, sent|wparam, 1 }, 3104 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOCLIENTMOVE }, 3105 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 3106 3107 /* in MDI child */ 3108 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE }, 3109 { WM_NCCALCSIZE, sent|wparam, 1 }, 3110 { 0x0093, sent|optional }, 3111 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOCLIENTMOVE }, 3112 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 3113 3114 { 0x0093, sent|optional }, 3115 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3116 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */ 3117 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* XP sends it to MDI frame */ 3118 { 0x0093, sent|defwinproc|optional }, 3119 { 0x0093, sent|defwinproc|optional }, 3120 { 0x0093, sent|defwinproc|optional }, 3121 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3122 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* XP sends a duplicate */ 3123 3124 { 0 } 3125 }; 3126 /* CreateWindow for the 1st MDI child window, initially invisible and maximized */ 3127 static const struct message WmCreateMDIchildInvisibleMaxSeq4[] = { 3128 { HCBT_CREATEWND, hook }, 3129 { WM_GETMINMAXINFO, sent }, 3130 { WM_NCCREATE, sent }, 3131 { WM_NCCALCSIZE, sent|wparam, 0 }, 3132 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, 3133 { WM_CREATE, sent }, 3134 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 3135 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 3136 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE, 0, SWP_NOZORDER }, /* MDI frame */ 3137 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* MDI frame */ 3138 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE, 0, SWP_NOZORDER }, /* MDI frame */ 3139 { WM_MOVE, sent }, 3140 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 3141 { WM_GETMINMAXINFO, sent }, 3142 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_STATECHANGED }, 3143 { WM_GETMINMAXINFO, sent|defwinproc }, 3144 { WM_NCCALCSIZE, sent|wparam, 1 }, 3145 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOREDRAW|SWP_STATECHANGED }, 3146 { WM_MOVE, sent|defwinproc }, 3147 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 3148 /* in MDI frame */ 3149 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3150 { WM_NCCALCSIZE, sent|wparam, 1 }, 3151 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3152 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3153 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* MDI child */ 3154 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3155 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3156 /* Win2k sends wparam set to 3157 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated), 3158 * while Win9x doesn't bother to set child window id according to 3159 * CLIENTCREATESTRUCT.idFirstChild 3160 */ 3161 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */ 3162 { 0 } 3163 }; 3164 /* WM_SYSCOMMAND/SC_CLOSE for the 2nd MDI child window, initially visible and maximized */ 3165 static const struct message WmDestroyMDIchildVisibleMaxSeq2[] = { 3166 { WM_SYSCOMMAND, sent|wparam, SC_CLOSE }, 3167 { HCBT_SYSCOMMAND, hook }, 3168 { WM_CLOSE, sent|defwinproc }, 3169 { WM_MDIDESTROY, sent }, /* in MDI client */ 3170 3171 /* bring the 1st MDI child to top */ 3172 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOSIZE|SWP_NOMOVE }, /* in the 1st MDI child */ 3173 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, /* in the 2nd MDI child */ 3174 3175 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3176 3177 { WM_CHILDACTIVATE, sent|defwinproc|wparam|lparam, 0, 0 }, /* in the 1st MDI child */ 3178 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 1st MDI child */ 3179 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 1st MDI child */ 3180 3181 /* maximize the 1st MDI child */ 3182 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 3183 { WM_GETMINMAXINFO, sent|defwinproc }, 3184 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_STATECHANGED }, 3185 { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 }, 3186 { WM_CHILDACTIVATE, sent|defwinproc|wparam|lparam, 0, 0 }, 3187 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 3188 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 3189 3190 /* restore the 2nd MDI child */ 3191 { WM_SETREDRAW, sent|defwinproc|wparam, 0 }, 3192 { HCBT_MINMAX, hook|lparam, 0, SW_NORMALNA }, 3193 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_STATECHANGED }, 3194 { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 }, 3195 3196 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 3197 3198 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 3199 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 3200 3201 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3202 3203 { WM_SETREDRAW, sent|defwinproc|wparam, 1 }, 3204 /* in MDI frame */ 3205 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3206 { WM_NCCALCSIZE, sent|wparam, 1 }, 3207 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3208 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3209 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3210 3211 /* bring the 1st MDI child to top */ 3212 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3213 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, 3214 { HCBT_SETFOCUS, hook }, 3215 { WM_KILLFOCUS, sent|defwinproc }, 3216 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 }, 3217 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 3218 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3219 { WM_SETFOCUS, sent }, /* in MDI client */ 3220 { HCBT_SETFOCUS, hook }, 3221 { WM_KILLFOCUS, sent }, /* in MDI client */ 3222 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 3223 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 3224 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3225 { WM_SETFOCUS, sent|defwinproc }, 3226 { WM_MDIACTIVATE, sent|defwinproc }, 3227 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3228 3229 /* apparently ShowWindow(SW_SHOW) on an MDI client */ 3230 { WM_SHOWWINDOW, sent|wparam, 1 }, 3231 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3232 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 3233 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3234 { WM_MDIREFRESHMENU, sent }, 3235 3236 { HCBT_DESTROYWND, hook }, 3237 /* Win2k sends wparam set to 3238 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated), 3239 * while Win9x doesn't bother to set child window id according to 3240 * CLIENTCREATESTRUCT.idFirstChild 3241 */ 3242 { 0x0090, sent|defwinproc|optional }, 3243 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */ 3244 { WM_SHOWWINDOW, sent|defwinproc|wparam, 0 }, 3245 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3246 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 3247 { WM_ERASEBKGND, sent|parent|optional }, 3248 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3249 3250 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, 3251 { WM_DESTROY, sent|defwinproc }, 3252 { WM_NCDESTROY, sent|defwinproc }, 3253 { 0 } 3254 }; 3255 /* WM_MDIDESTROY for the single MDI child window, initially visible and maximized */ 3256 static const struct message WmDestroyMDIchildVisibleMaxSeq1[] = { 3257 { WM_MDIDESTROY, sent }, /* in MDI client */ 3258 { WM_SHOWWINDOW, sent|wparam, 0 }, 3259 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3260 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 3261 { WM_ERASEBKGND, sent|parent|optional }, 3262 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3263 3264 { HCBT_SETFOCUS, hook }, 3265 { WM_KILLFOCUS, sent }, 3266 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 3267 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 3268 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3269 { WM_SETFOCUS, sent }, /* in MDI client */ 3270 { HCBT_SETFOCUS, hook }, 3271 { WM_KILLFOCUS, sent }, /* in MDI client */ 3272 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 3273 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 3274 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3275 { WM_SETFOCUS, sent }, 3276 3277 /* in MDI child */ 3278 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3279 { WM_NCCALCSIZE, sent|wparam, 1 }, 3280 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3281 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3282 3283 /* in MDI frame */ 3284 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3285 { WM_NCCALCSIZE, sent|wparam, 1 }, 3286 { 0x0093, sent|defwinproc|optional }, 3287 { 0x0093, sent|defwinproc|optional }, 3288 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3289 { WM_MOVE, sent|defwinproc }, 3290 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 3291 3292 /* in MDI client */ 3293 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE }, 3294 { WM_NCCALCSIZE, sent|wparam, 1 }, 3295 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOCLIENTMOVE }, 3296 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 3297 3298 /* in MDI child */ 3299 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE }, 3300 { WM_NCCALCSIZE, sent|wparam, 1 }, 3301 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE }, 3302 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 3303 3304 /* in MDI child */ 3305 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3306 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, 3307 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3308 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3309 3310 /* in MDI frame */ 3311 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3312 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, 3313 { 0x0093, sent|defwinproc|optional }, 3314 { 0x0093, sent|defwinproc|optional }, 3315 { 0x0093, sent|defwinproc|optional }, 3316 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3317 { WM_MOVE, sent|defwinproc }, 3318 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 3319 3320 /* in MDI client */ 3321 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE }, 3322 { WM_NCCALCSIZE, sent|wparam, 1 }, 3323 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOCLIENTMOVE }, 3324 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 3325 3326 /* in MDI child */ 3327 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE }, 3328 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, 3329 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE }, 3330 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 3331 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3332 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */ 3333 3334 { 0x0093, sent|defwinproc|optional }, 3335 { WM_NCCALCSIZE, sent|wparam|defwinproc|optional, 1 }, /* XP sends it to MDI frame */ 3336 { 0x0093, sent|defwinproc|optional }, 3337 { 0x0093, sent|defwinproc|optional }, 3338 { 0x0093, sent|defwinproc|optional }, 3339 { 0x0093, sent|optional }, 3340 3341 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3342 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3343 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */ 3344 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3345 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* XP sends a duplicate */ 3346 3347 /* in MDI frame */ 3348 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3349 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, 3350 { 0x0093, sent|defwinproc|optional }, 3351 { 0x0093, sent|defwinproc|optional }, 3352 { 0x0093, sent|defwinproc|optional }, 3353 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3354 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3355 { 0x0093, sent|optional }, 3356 3357 { WM_NCACTIVATE, sent|wparam, 0 }, 3358 { WM_MDIACTIVATE, sent }, 3359 3360 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWNORMAL }, 3361 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_STATECHANGED }, 3362 { WM_NCCALCSIZE, sent|wparam, 1 }, 3363 3364 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 3365 3366 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 3367 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 3368 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 3369 3370 /* in MDI child */ 3371 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3372 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, 3373 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3374 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3375 3376 /* in MDI frame */ 3377 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3378 { WM_NCCALCSIZE, sent|wparam, 1 }, 3379 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3380 { WM_MOVE, sent|defwinproc }, 3381 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 3382 3383 /* in MDI client */ 3384 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE }, 3385 { WM_NCCALCSIZE, sent|wparam, 1 }, 3386 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOCLIENTMOVE }, 3387 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 3388 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3389 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* XP */ 3390 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */ 3391 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3392 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* XP sends a duplicate */ 3393 3394 { HCBT_SETFOCUS, hook }, 3395 { WM_KILLFOCUS, sent }, 3396 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 3397 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 3398 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3399 { WM_SETFOCUS, sent }, /* in MDI client */ 3400 3401 { WM_MDIREFRESHMENU, sent }, /* in MDI client */ 3402 3403 { HCBT_DESTROYWND, hook }, 3404 /* Win2k sends wparam set to 3405 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated), 3406 * while Win9x doesn't bother to set child window id according to 3407 * CLIENTCREATESTRUCT.idFirstChild 3408 */ 3409 { 0x0090, sent|optional }, 3410 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */ 3411 3412 { WM_SHOWWINDOW, sent|wparam, 0 }, 3413 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3414 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 3415 { WM_ERASEBKGND, sent|parent|optional }, 3416 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3417 3418 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, 3419 { WM_DESTROY, sent }, 3420 { WM_NCDESTROY, sent }, 3421 { 0 } 3422 }; 3423 /* ShowWindow(SW_MAXIMIZE) for a not visible MDI child window */ 3424 static const struct message WmMaximizeMDIchildInvisibleSeq[] = { 3425 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 3426 { WM_GETMINMAXINFO, sent }, 3427 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_STATECHANGED }, 3428 { WM_NCCALCSIZE, sent|wparam, 1 }, 3429 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 3430 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 3431 3432 { WM_WINDOWPOSCHANGING, sent|wparam|optional|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3433 { WM_NCACTIVATE, sent|wparam|optional|defwinproc, 1 }, 3434 { HCBT_SETFOCUS, hook|optional }, 3435 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 3436 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3437 { WM_SETFOCUS, sent|optional }, /* in MDI client */ 3438 { HCBT_SETFOCUS, hook|optional }, 3439 { WM_KILLFOCUS, sent|optional }, /* in MDI client */ 3440 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 3441 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 3442 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3443 { WM_SETFOCUS, sent|optional|defwinproc }, 3444 { WM_MDIACTIVATE, sent|optional|defwinproc }, 3445 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 3446 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 3447 /* in MDI frame */ 3448 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3449 { WM_NCCALCSIZE, sent|wparam, 1 }, 3450 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3451 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3452 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3453 { 0 } 3454 }; 3455 /* ShowWindow(SW_MAXIMIZE) for a not visible maximized MDI child window */ 3456 static const struct message WmMaximizeMDIchildInvisibleSeq2[] = { 3457 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 3458 { WM_GETMINMAXINFO, sent }, 3459 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED }, 3460 { WM_GETMINMAXINFO, sent|defwinproc }, 3461 { WM_NCCALCSIZE, sent|wparam, 1 }, 3462 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 3463 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 3464 3465 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc|optional, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3466 { WM_NCACTIVATE, sent|wparam|defwinproc|optional, 1 }, 3467 { HCBT_SETFOCUS, hook|optional }, 3468 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ 3469 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3470 { WM_SETFOCUS, sent|optional }, /* in MDI client */ 3471 { HCBT_SETFOCUS, hook|optional }, 3472 { WM_KILLFOCUS, sent|optional }, /* in MDI client */ 3473 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ 3474 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 3475 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3476 { WM_SETFOCUS, sent|defwinproc|optional }, 3477 { WM_MDIACTIVATE, sent|defwinproc|optional }, 3478 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3479 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3480 { WM_SIZE, sent|defwinproc|optional }, 3481 { 0 } 3482 }; 3483 /* WM_MDIMAXIMIZE for an MDI child window with invisible parent */ 3484 static const struct message WmMaximizeMDIchildInvisibleParentSeq[] = { 3485 { WM_MDIMAXIMIZE, sent }, /* in MDI client */ 3486 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 3487 { WM_GETMINMAXINFO, sent }, 3488 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, 3489 { WM_GETMINMAXINFO, sent|defwinproc }, 3490 { WM_NCCALCSIZE, sent|wparam, 1 }, 3491 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP doesn't send it */ 3492 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 3493 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOREDRAW|SWP_STATECHANGED }, 3494 { WM_MOVE, sent|defwinproc }, 3495 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 3496 3497 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3498 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, 3499 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3500 { WM_NCCALCSIZE, sent|wparam|defwinproc|optional, 1 }, 3501 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI child XP */ 3502 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI client XP */ 3503 /* in MDI frame */ 3504 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3505 { WM_NCCALCSIZE, sent|wparam, 1 }, 3506 { 0x0093, sent|defwinproc|optional }, 3507 { 0x0094, sent|defwinproc|optional }, 3508 { 0x0094, sent|defwinproc|optional }, 3509 { 0x0094, sent|defwinproc|optional }, 3510 { 0x0094, sent|defwinproc|optional }, 3511 { 0x0093, sent|defwinproc|optional }, 3512 { 0x0093, sent|defwinproc|optional }, 3513 { 0x0091, sent|defwinproc|optional }, 3514 { 0x0092, sent|defwinproc|optional }, 3515 { 0x0092, sent|defwinproc|optional }, 3516 { 0x0092, sent|defwinproc|optional }, 3517 { 0x0092, sent|defwinproc|optional }, 3518 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3519 { WM_MOVE, sent|defwinproc }, 3520 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 3521 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI frame win2000 */ 3522 /* in MDI client */ 3523 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE }, 3524 { WM_NCCALCSIZE, sent|wparam, 1 }, 3525 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE }, 3526 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 3527 /* in MDI child */ 3528 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE }, 3529 { WM_GETMINMAXINFO, sent|defwinproc }, 3530 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, 3531 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE }, 3532 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 3533 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI child win2000 */ 3534 { WM_NCCALCSIZE, sent|wparam|defwinproc|optional, 1 }, 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 child XP */ 3537 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI client XP */ 3538 /* in MDI frame */ 3539 { 0x0093, sent|optional }, 3540 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, 3541 { 0x0093, sent|defwinproc|optional }, 3542 { 0x0093, sent|defwinproc|optional }, 3543 { 0x0093, sent|defwinproc|optional }, 3544 { 0x0091, sent|defwinproc|optional }, 3545 { 0x0092, sent|defwinproc|optional }, 3546 { 0x0092, sent|defwinproc|optional }, 3547 { 0x0092, sent|defwinproc|optional }, 3548 { 0x0092, sent|defwinproc|optional }, 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 frame XP */ 3551 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI child XP */ 3552 { 0 } 3553 }; 3554 /* ShowWindow(SW_MAXIMIZE) for a visible MDI child window */ 3555 static const struct message WmMaximizeMDIchildVisibleSeq[] = { 3556 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, 3557 { WM_GETMINMAXINFO, sent }, 3558 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, 3559 { WM_NCCALCSIZE, sent|wparam, 1 }, 3560 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 3561 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 3562 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, 3563 /* in MDI frame */ 3564 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3565 { WM_NCCALCSIZE, sent|wparam, 1 }, 3566 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3567 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3568 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3569 { 0 } 3570 }; 3571 /* ShowWindow(SW_RESTORE) for a visible maximized MDI child window */ 3572 static const struct message WmRestoreMDIchildVisibleSeq[] = { 3573 { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE }, 3574 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, 3575 { WM_NCCALCSIZE, sent|wparam, 1 }, 3576 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 3577 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 3578 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 3579 /* in MDI frame */ 3580 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3581 { WM_NCCALCSIZE, sent|wparam, 1 }, 3582 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3583 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3584 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3585 { 0 } 3586 }; 3587 /* ShowWindow(SW_RESTORE) for a visible minimized MDI child window */ 3588 static const struct message WmRestoreMDIchildVisibleSeq_2[] = { 3589 { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE }, 3590 { WM_QUERYOPEN, sent|wparam|lparam, 0, 0 }, 3591 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 3592 { WM_NCCALCSIZE, sent|wparam, 1 }, 3593 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 3594 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 3595 { WM_MOVE, sent|defwinproc }, 3596 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 3597 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3598 { EVENT_SYSTEM_MINIMIZEEND, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3599 { HCBT_SETFOCUS, hook }, 3600 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 3601 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 3602 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 3603 { WM_SETFOCUS, sent }, 3604 { 0 } 3605 }; 3606 /* ShowWindow(SW_MINIMIZE) for a visible restored MDI child window */ 3607 static const struct message WmMinimizeMDIchildVisibleSeq[] = { 3608 { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, 3609 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_STATECHANGED }, 3610 { WM_NCCALCSIZE, sent|wparam, 1 }, 3611 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_STATECHANGED }, 3612 { WM_MOVE, sent|defwinproc }, 3613 { WM_SIZE, sent|defwinproc|wparam|lparam, SIZE_MINIMIZED, 0 }, 3614 { WM_CHILDACTIVATE, sent|wparam|lparam|defwinproc, 0, 0 }, 3615 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3616 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3617 /* FIXME: Wine creates an icon/title window while Windows doesn't */ 3618 { WM_PARENTNOTIFY, sent|parent|wparam|optional, WM_CREATE }, /* MDI client */ 3619 { 0 } 3620 }; 3621 /* ShowWindow(SW_RESTORE) for a not visible MDI child window */ 3622 static const struct message WmRestoreMDIchildInvisibleSeq[] = { 3623 { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE }, 3624 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_STATECHANGED }, 3625 { WM_NCCALCSIZE, sent|wparam, 1 }, 3626 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 3627 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, 3628 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, 3629 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 3630 /* in MDI frame */ 3631 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 3632 { WM_NCCALCSIZE, sent|wparam, 1 }, 3633 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 3634 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ 3635 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ 3636 { 0 } 3637 }; 3638 3639 static HWND mdi_client; 3640 static WNDPROC old_mdi_client_proc; 3641 3642 static LRESULT WINAPI mdi_client_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 3643 { 3644 struct recvd_message msg; 3645 3646 /* do not log painting messages */ 3647 if (message != WM_PAINT && 3648 message != WM_NCPAINT && 3649 message != WM_SYNCPAINT && 3650 message != WM_ERASEBKGND && 3651 message != WM_NCHITTEST && 3652 message != WM_GETTEXT && 3653 message != WM_MDIGETACTIVE && 3654 !ignore_message( message )) 3655 { 3656 msg.hwnd = hwnd; 3657 msg.message = message; 3658 msg.flags = sent|wparam|lparam; 3659 msg.wParam = wParam; 3660 msg.lParam = lParam; 3661 msg.descr = "mdi client"; 3662 add_message(&msg); 3663 } 3664 3665 return CallWindowProcA(old_mdi_client_proc, hwnd, message, wParam, lParam); 3666 } 3667 3668 static LRESULT WINAPI mdi_child_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 3669 { 3670 static LONG defwndproc_counter = 0; 3671 LRESULT ret; 3672 struct recvd_message msg; 3673 3674 /* do not log painting messages */ 3675 if (message != WM_PAINT && 3676 message != WM_NCPAINT && 3677 message != WM_SYNCPAINT && 3678 message != WM_ERASEBKGND && 3679 message != WM_NCHITTEST && 3680 message != WM_GETTEXT && 3681 !ignore_message( message )) 3682 { 3683 switch (message) 3684 { 3685 case WM_MDIACTIVATE: 3686 { 3687 HWND active, client = GetParent(hwnd); 3688 3689 active = (HWND)SendMessageA(client, WM_MDIGETACTIVE, 0, 0); 3690 3691 if (hwnd == (HWND)lParam) /* if we are being activated */ 3692 ok (active == (HWND)lParam, "new active %p != active %p\n", (HWND)lParam, active); 3693 else 3694 ok (active == (HWND)wParam, "old active %p != active %p\n", (HWND)wParam, active); 3695 break; 3696 } 3697 } 3698 3699 msg.hwnd = hwnd; 3700 msg.message = message; 3701 msg.flags = sent|wparam|lparam; 3702 if (defwndproc_counter) msg.flags |= defwinproc; 3703 msg.wParam = wParam; 3704 msg.lParam = lParam; 3705 msg.descr = "mdi child"; 3706 add_message(&msg); 3707 } 3708 3709 defwndproc_counter++; 3710 ret = DefMDIChildProcA(hwnd, message, wParam, lParam); 3711 defwndproc_counter--; 3712 3713 return ret; 3714 } 3715 3716 static LRESULT WINAPI mdi_frame_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 3717 { 3718 static LONG defwndproc_counter = 0; 3719 LRESULT ret; 3720 struct recvd_message msg; 3721 3722 /* do not log painting messages */ 3723 if (message != WM_PAINT && 3724 message != WM_NCPAINT && 3725 message != WM_SYNCPAINT && 3726 message != WM_ERASEBKGND && 3727 message != WM_NCHITTEST && 3728 message != WM_GETTEXT && 3729 !ignore_message( message )) 3730 { 3731 msg.hwnd = hwnd; 3732 msg.message = message; 3733 msg.flags = sent|wparam|lparam; 3734 if (defwndproc_counter) msg.flags |= defwinproc; 3735 msg.wParam = wParam; 3736 msg.lParam = lParam; 3737 msg.descr = "mdi frame"; 3738 add_message(&msg); 3739 } 3740 3741 defwndproc_counter++; 3742 ret = DefFrameProcA(hwnd, mdi_client, message, wParam, lParam); 3743 defwndproc_counter--; 3744 3745 return ret; 3746 } 3747 3748 static BOOL mdi_RegisterWindowClasses(void) 3749 { 3750 WNDCLASSA cls; 3751 3752 cls.style = 0; 3753 cls.lpfnWndProc = mdi_frame_wnd_proc; 3754 cls.cbClsExtra = 0; 3755 cls.cbWndExtra = 0; 3756 cls.hInstance = GetModuleHandleA(0); 3757 cls.hIcon = 0; 3758 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 3759 cls.hbrBackground = GetStockObject(WHITE_BRUSH); 3760 cls.lpszMenuName = NULL; 3761 cls.lpszClassName = "MDI_frame_class"; 3762 if (!RegisterClassA(&cls)) return FALSE; 3763 3764 cls.lpfnWndProc = mdi_child_wnd_proc; 3765 cls.lpszClassName = "MDI_child_class"; 3766 if (!RegisterClassA(&cls)) return FALSE; 3767 3768 if (!GetClassInfoA(0, "MDIClient", &cls)) assert(0); 3769 old_mdi_client_proc = cls.lpfnWndProc; 3770 cls.hInstance = GetModuleHandleA(0); 3771 cls.lpfnWndProc = mdi_client_hook_proc; 3772 cls.lpszClassName = "MDI_client_class"; 3773 if (!RegisterClassA(&cls)) assert(0); 3774 3775 return TRUE; 3776 } 3777 3778 static void test_mdi_messages(void) 3779 { 3780 MDICREATESTRUCTA mdi_cs; 3781 CLIENTCREATESTRUCT client_cs; 3782 HWND mdi_frame, mdi_child, mdi_child2, active_child; 3783 BOOL zoomed; 3784 RECT rc; 3785 HMENU hMenu = CreateMenu(); 3786 LONG val; 3787 3788 if (!mdi_RegisterWindowClasses()) assert(0); 3789 3790 flush_sequence(); 3791 3792 trace("creating MDI frame window\n"); 3793 mdi_frame = CreateWindowExA(0, "MDI_frame_class", "MDI frame window", 3794 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | 3795 WS_MAXIMIZEBOX | WS_VISIBLE, 3796 100, 100, CW_USEDEFAULT, CW_USEDEFAULT, 3797 GetDesktopWindow(), hMenu, 3798 GetModuleHandleA(0), NULL); 3799 assert(mdi_frame); 3800 ok_sequence(WmCreateMDIframeSeq, "Create MDI frame window", FALSE); 3801 3802 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 3803 ok(GetFocus() == mdi_frame, "wrong focus window %p\n", GetFocus()); 3804 3805 trace("creating MDI client window\n"); 3806 GetClientRect(mdi_frame, &rc); 3807 client_cs.hWindowMenu = 0; 3808 client_cs.idFirstChild = MDI_FIRST_CHILD_ID; 3809 mdi_client = CreateWindowExA(0, "MDI_client_class", 3810 NULL, 3811 WS_CHILD | WS_VISIBLE | MDIS_ALLCHILDSTYLES, 3812 rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, 3813 mdi_frame, 0, GetModuleHandleA(0), &client_cs); 3814 assert(mdi_client); 3815 SetWindowLongA(mdi_client, 0, 0xdeadbeef); 3816 3817 ok_sequence(WmCreateMDIclientSeq, "Create visible MDI client window", FALSE); 3818 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 3819 ok(GetFocus() == mdi_frame, "input focus should be on MDI frame not on %p\n", GetFocus()); 3820 3821 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 3822 ok(!active_child, "wrong active MDI child %p\n", active_child); 3823 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 3824 3825 SetFocus(0); 3826 flush_sequence(); 3827 3828 trace("creating invisible MDI child window\n"); 3829 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", 3830 WS_CHILD, 3831 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 3832 mdi_client, 0, GetModuleHandleA(0), NULL); 3833 assert(mdi_child); 3834 3835 flush_sequence(); 3836 ShowWindow(mdi_child, SW_SHOWNORMAL); 3837 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOWNORMAL) MDI child window", FALSE); 3838 3839 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n"); 3840 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n"); 3841 3842 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 3843 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 3844 3845 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 3846 ok(!active_child, "wrong active MDI child %p\n", active_child); 3847 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 3848 3849 ShowWindow(mdi_child, SW_HIDE); 3850 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE) MDI child window", FALSE); 3851 flush_sequence(); 3852 3853 ShowWindow(mdi_child, SW_SHOW); 3854 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW) MDI child window", FALSE); 3855 3856 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n"); 3857 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n"); 3858 3859 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 3860 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 3861 3862 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 3863 ok(!active_child, "wrong active MDI child %p\n", active_child); 3864 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 3865 3866 DestroyWindow(mdi_child); 3867 flush_sequence(); 3868 3869 trace("creating visible MDI child window\n"); 3870 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", 3871 WS_CHILD | WS_VISIBLE, 3872 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 3873 mdi_client, 0, GetModuleHandleA(0), NULL); 3874 assert(mdi_child); 3875 ok_sequence(WmCreateMDIchildVisibleSeq, "Create visible MDI child window", FALSE); 3876 3877 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n"); 3878 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n"); 3879 3880 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 3881 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus()); 3882 3883 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 3884 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child); 3885 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 3886 flush_sequence(); 3887 3888 DestroyWindow(mdi_child); 3889 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE); 3890 3891 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 3892 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 3893 3894 /* Win2k: MDI client still returns a just destroyed child as active 3895 * Win9x: MDI client returns 0 3896 */ 3897 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 3898 ok(active_child == mdi_child || /* win2k */ 3899 !active_child, /* win9x */ 3900 "wrong active MDI child %p\n", active_child); 3901 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 3902 3903 flush_sequence(); 3904 3905 trace("creating invisible MDI child window\n"); 3906 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", 3907 WS_CHILD, 3908 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 3909 mdi_client, 0, GetModuleHandleA(0), NULL); 3910 assert(mdi_child2); 3911 ok_sequence(WmCreateMDIchildInvisibleSeq, "Create invisible MDI child window", FALSE); 3912 3913 ok(!(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE), "MDI child should not be visible\n"); 3914 ok(!IsWindowVisible(mdi_child2), "MDI child should not be visible\n"); 3915 3916 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 3917 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 3918 3919 /* Win2k: MDI client still returns a just destroyed child as active 3920 * Win9x: MDI client returns mdi_child2 3921 */ 3922 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 3923 ok(active_child == mdi_child || /* win2k */ 3924 active_child == mdi_child2, /* win9x */ 3925 "wrong active MDI child %p\n", active_child); 3926 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 3927 flush_sequence(); 3928 3929 ShowWindow(mdi_child2, SW_MAXIMIZE); 3930 ok_sequence(WmMaximizeMDIchildInvisibleSeq, "ShowWindow(SW_MAXIMIZE):invisible MDI child", FALSE); 3931 3932 ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n"); 3933 ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n"); 3934 3935 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 3936 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); 3937 ok(zoomed, "wrong zoomed state %d\n", zoomed); 3938 flush_sequence(); 3939 3940 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 3941 ok(GetFocus() == mdi_child2 || /* win2k */ 3942 GetFocus() == 0, /* win9x */ 3943 "wrong focus window %p\n", GetFocus()); 3944 3945 SetFocus(0); 3946 flush_sequence(); 3947 3948 ShowWindow(mdi_child2, SW_HIDE); 3949 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE); 3950 3951 ShowWindow(mdi_child2, SW_RESTORE); 3952 ok_sequence(WmRestoreMDIchildInvisibleSeq, "ShowWindow(SW_RESTORE):invisible MDI child", FALSE); 3953 flush_sequence(); 3954 3955 ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n"); 3956 ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n"); 3957 3958 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 3959 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); 3960 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 3961 flush_sequence(); 3962 3963 SetFocus(0); 3964 flush_sequence(); 3965 3966 ShowWindow(mdi_child2, SW_HIDE); 3967 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE); 3968 3969 ShowWindow(mdi_child2, SW_SHOW); 3970 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):MDI child", FALSE); 3971 3972 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 3973 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 3974 3975 ShowWindow(mdi_child2, SW_MAXIMIZE); 3976 ok_sequence(WmMaximizeMDIchildVisibleSeq, "ShowWindow(SW_MAXIMIZE):MDI child", FALSE); 3977 3978 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 3979 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 3980 3981 ShowWindow(mdi_child2, SW_RESTORE); 3982 ok_sequence(WmRestoreMDIchildVisibleSeq, "ShowWindow(SW_RESTORE):maximized MDI child", FALSE); 3983 3984 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 3985 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 3986 3987 ShowWindow(mdi_child2, SW_MINIMIZE); 3988 ok_sequence(WmMinimizeMDIchildVisibleSeq, "ShowWindow(SW_MINIMIZE):MDI child", FALSE); 3989 3990 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 3991 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 3992 3993 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 3994 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); 3995 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 3996 flush_sequence(); 3997 3998 ShowWindow(mdi_child2, SW_RESTORE); 3999 ok_sequence(WmRestoreMDIchildVisibleSeq_2, "ShowWindow(SW_RESTORE):minimized MDI child", FALSE); 4000 4001 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4002 ok(GetFocus() == mdi_child2, "wrong focus window %p\n", GetFocus()); 4003 4004 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4005 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); 4006 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 4007 flush_sequence(); 4008 4009 SetFocus(0); 4010 flush_sequence(); 4011 4012 ShowWindow(mdi_child2, SW_HIDE); 4013 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE); 4014 4015 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4016 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 4017 4018 DestroyWindow(mdi_child2); 4019 ok_sequence(WmDestroyMDIchildInvisibleSeq, "Destroy invisible MDI child window", FALSE); 4020 4021 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4022 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 4023 4024 trace("Testing WM_CHILDACTIVATE\n"); 4025 4026 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", 4027 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_DISABLED, 4028 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 4029 mdi_client, 0, GetModuleHandleA(0), NULL); 4030 4031 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", 4032 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX, 4033 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 4034 mdi_client, 0, GetModuleHandleA(0), NULL); 4035 4036 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4037 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); 4038 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 4039 4040 flush_sequence(); 4041 SendMessageW(mdi_child, WM_CHILDACTIVATE, 0, 0); 4042 ok_sequence(WmChildActivateDisabledWindowSeq, "WM_CHILDACTIVATE sent to disabled window", FALSE); 4043 4044 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4045 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); 4046 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 4047 flush_sequence(); 4048 4049 EnableWindow(mdi_child, TRUE); 4050 4051 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4052 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); 4053 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 4054 4055 flush_sequence(); 4056 SendMessageW(mdi_child, WM_CHILDACTIVATE, 0, 0); 4057 ok_sequence(WmChildActivateWindowSeq, "WM_CHILDACTIVATE sent to enabled window", FALSE); 4058 4059 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4060 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child); 4061 ok(!zoomed, "wrong zoomed state %d\n", zoomed); 4062 flush_sequence(); 4063 4064 DestroyWindow(mdi_child); 4065 DestroyWindow(mdi_child2); 4066 flush_sequence(); 4067 4068 /* test for maximized MDI children */ 4069 trace("creating maximized visible MDI child window 1\n"); 4070 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", 4071 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE, 4072 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 4073 mdi_client, 0, GetModuleHandleA(0), NULL); 4074 assert(mdi_child); 4075 ok_sequence(WmCreateMDIchildVisibleMaxSeq1, "Create maximized visible 1st MDI child window", TRUE); 4076 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n"); 4077 4078 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4079 ok(GetFocus() == mdi_child || /* win2k */ 4080 GetFocus() == 0, /* win9x */ 4081 "wrong focus window %p\n", GetFocus()); 4082 4083 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4084 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child); 4085 ok(zoomed, "wrong zoomed state %d\n", zoomed); 4086 flush_sequence(); 4087 4088 trace("creating maximized visible MDI child window 2\n"); 4089 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", 4090 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE, 4091 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 4092 mdi_client, 0, GetModuleHandleA(0), NULL); 4093 assert(mdi_child2); 4094 ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child 2 window", TRUE); 4095 ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized\n"); 4096 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n"); 4097 4098 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4099 ok(GetFocus() == mdi_child2, "wrong focus window %p\n", GetFocus()); 4100 4101 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4102 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); 4103 ok(zoomed, "wrong zoomed state %d\n", zoomed); 4104 flush_sequence(); 4105 4106 trace("destroying maximized visible MDI child window 2\n"); 4107 DestroyWindow(mdi_child2); 4108 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE); 4109 4110 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n"); 4111 4112 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4113 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 4114 4115 /* Win2k: MDI client still returns a just destroyed child as active 4116 * Win9x: MDI client returns 0 4117 */ 4118 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4119 ok(active_child == mdi_child2 || /* win2k */ 4120 !active_child, /* win9x */ 4121 "wrong active MDI child %p\n", active_child); 4122 flush_sequence(); 4123 4124 ShowWindow(mdi_child, SW_MAXIMIZE); 4125 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n"); 4126 flush_sequence(); 4127 4128 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4129 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus()); 4130 4131 trace("re-creating maximized visible MDI child window 2\n"); 4132 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", 4133 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE, 4134 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 4135 mdi_client, 0, GetModuleHandleA(0), NULL); 4136 assert(mdi_child2); 4137 ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child 2 window", TRUE); 4138 ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized\n"); 4139 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n"); 4140 4141 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4142 ok(GetFocus() == mdi_child2, "wrong focus window %p\n", GetFocus()); 4143 4144 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4145 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); 4146 ok(zoomed, "wrong zoomed state %d\n", zoomed); 4147 flush_sequence(); 4148 4149 SendMessageA(mdi_child2, WM_SYSCOMMAND, SC_CLOSE, 0); 4150 ok_sequence(WmDestroyMDIchildVisibleMaxSeq2, "WM_SYSCOMMAND/SC_CLOSE on a visible maximized MDI child window", TRUE); 4151 ok(!IsWindow(mdi_child2), "MDI child 2 should be destroyed\n"); 4152 4153 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n"); 4154 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4155 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus()); 4156 4157 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4158 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child); 4159 ok(zoomed, "wrong zoomed state %d\n", zoomed); 4160 flush_sequence(); 4161 4162 DestroyWindow(mdi_child); 4163 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE); 4164 4165 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4166 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 4167 4168 /* Win2k: MDI client still returns a just destroyed child as active 4169 * Win9x: MDI client returns 0 4170 */ 4171 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4172 ok(active_child == mdi_child || /* win2k */ 4173 !active_child, /* win9x */ 4174 "wrong active MDI child %p\n", active_child); 4175 flush_sequence(); 4176 4177 trace("creating maximized invisible MDI child window\n"); 4178 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", 4179 WS_CHILD | WS_MAXIMIZE | WS_CAPTION | WS_THICKFRAME, 4180 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 4181 mdi_client, 0, GetModuleHandleA(0), NULL); 4182 assert(mdi_child2); 4183 ok_sequence(WmCreateMDIchildInvisibleMaxSeq4, "Create maximized invisible MDI child window", FALSE); 4184 ok(IsZoomed(mdi_child2), "MDI child should be maximized\n"); 4185 ok(!(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE), "MDI child should be not visible\n"); 4186 ok(!IsWindowVisible(mdi_child2), "MDI child should be not visible\n"); 4187 4188 /* Win2k: MDI client still returns a just destroyed child as active 4189 * Win9x: MDI client returns 0 4190 */ 4191 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4192 ok(active_child == mdi_child || /* win2k */ 4193 !active_child || active_child == mdi_child2, /* win9x */ 4194 "wrong active MDI child %p\n", active_child); 4195 flush_sequence(); 4196 4197 trace("call ShowWindow(mdi_child, SW_MAXIMIZE)\n"); 4198 ShowWindow(mdi_child2, SW_MAXIMIZE); 4199 ok_sequence(WmMaximizeMDIchildInvisibleSeq2, "ShowWindow(SW_MAXIMIZE):invisible maximized MDI child", FALSE); 4200 ok(IsZoomed(mdi_child2), "MDI child should be maximized\n"); 4201 ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n"); 4202 ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n"); 4203 4204 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4205 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); 4206 ok(zoomed, "wrong zoomed state %d\n", zoomed); 4207 flush_sequence(); 4208 4209 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child2, 0); 4210 flush_sequence(); 4211 4212 /* end of test for maximized MDI children */ 4213 SetFocus(0); 4214 flush_sequence(); 4215 trace("creating maximized visible MDI child window 1(Switch test)\n"); 4216 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", 4217 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE, 4218 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 4219 mdi_client, 0, GetModuleHandleA(0), NULL); 4220 assert(mdi_child); 4221 ok_sequence(WmCreateMDIchildVisibleMaxSeq1, "Create maximized visible 1st MDI child window(Switch test)", TRUE); 4222 ok(IsZoomed(mdi_child), "1st MDI child should be maximized(Switch test)\n"); 4223 4224 ok(GetActiveWindow() == mdi_frame, "wrong active window %p(Switch test)\n", GetActiveWindow()); 4225 ok(GetFocus() == mdi_child || /* win2k */ 4226 GetFocus() == 0, /* win9x */ 4227 "wrong focus window %p(Switch test)\n", GetFocus()); 4228 4229 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4230 ok(active_child == mdi_child, "wrong active MDI child %p(Switch test)\n", active_child); 4231 ok(zoomed, "wrong zoomed state %d(Switch test)\n", zoomed); 4232 flush_sequence(); 4233 4234 trace("creating maximized visible MDI child window 2(Switch test)\n"); 4235 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", 4236 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE, 4237 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 4238 mdi_client, 0, GetModuleHandleA(0), NULL); 4239 assert(mdi_child2); 4240 ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child window (Switch test)", TRUE); 4241 4242 ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized(Switch test)\n"); 4243 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized(Switch test)\n"); 4244 4245 ok(GetActiveWindow() == mdi_frame, "wrong active window %p(Switch test)\n", GetActiveWindow()); 4246 ok(GetFocus() == mdi_child2, "wrong focus window %p(Switch test)\n", GetFocus()); 4247 4248 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4249 ok(active_child == mdi_child2, "wrong active MDI child %p(Switch test)\n", active_child); 4250 ok(zoomed, "wrong zoomed state %d(Switch test)\n", zoomed); 4251 flush_sequence(); 4252 4253 trace("Switch child window.\n"); 4254 SendMessageA(mdi_client, WM_MDIACTIVATE, (WPARAM)mdi_child, 0); 4255 ok_sequence(WmSwitchChild, "Child did not switch correctly", TRUE); 4256 trace("end of test for switch maximized MDI children\n"); 4257 flush_sequence(); 4258 4259 /* Prepare for switching test of not maximized MDI children */ 4260 ShowWindow( mdi_child, SW_NORMAL ); 4261 ok(!IsZoomed(mdi_child), "wrong zoomed state for %p(Switch test)\n", mdi_child); 4262 ok(!IsZoomed(mdi_child2), "wrong zoomed state for %p(Switch test)\n", mdi_child2); 4263 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0); 4264 ok(active_child == mdi_child, "wrong active MDI child %p(Switch test)\n", active_child); 4265 flush_sequence(); 4266 4267 SendMessageA(mdi_client, WM_MDIACTIVATE, (WPARAM)mdi_child2, 0); 4268 ok_sequence(WmSwitchNotMaximizedChild, "Not maximized child did not switch correctly", FALSE); 4269 trace("end of test for switch not maximized MDI children\n"); 4270 flush_sequence(); 4271 4272 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0); 4273 flush_sequence(); 4274 4275 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child2, 0); 4276 flush_sequence(); 4277 4278 SetFocus(0); 4279 flush_sequence(); 4280 /* end of tests for switch maximized/not maximized MDI children */ 4281 4282 mdi_cs.szClass = "MDI_child_Class"; 4283 mdi_cs.szTitle = "MDI child"; 4284 mdi_cs.hOwner = GetModuleHandleA(0); 4285 mdi_cs.x = 0; 4286 mdi_cs.y = 0; 4287 mdi_cs.cx = CW_USEDEFAULT; 4288 mdi_cs.cy = CW_USEDEFAULT; 4289 mdi_cs.style = WS_CHILD | WS_SYSMENU | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE; 4290 mdi_cs.lParam = 0; 4291 mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs); 4292 ok(mdi_child != 0, "MDI child creation failed\n"); 4293 ok_sequence(WmCreateMDIchildVisibleMaxSeq3, "WM_MDICREATE for maximized visible MDI child window", TRUE); 4294 4295 ok(GetMenuItemID(hMenu, GetMenuItemCount(hMenu) - 1) == SC_CLOSE, "SC_CLOSE menu item not found\n"); 4296 4297 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4298 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child); 4299 4300 ok(IsZoomed(mdi_child), "MDI child should be maximized\n"); 4301 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); 4302 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus()); 4303 4304 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4305 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child); 4306 ok(zoomed, "wrong zoomed state %d\n", zoomed); 4307 flush_sequence(); 4308 4309 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0); 4310 ok_sequence(WmDestroyMDIchildVisibleMaxSeq1, "Destroy visible maximized MDI child window", TRUE); 4311 4312 ok(!IsWindow(mdi_child), "MDI child should be destroyed\n"); 4313 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); 4314 ok(!active_child, "wrong active MDI child %p\n", active_child); 4315 4316 SetFocus(0); 4317 flush_sequence(); 4318 4319 val = GetWindowLongA(mdi_client, 0); 4320 ok(val == 0xdeadbeef || broken(val == 0) /* >= Win Vista */, "Expected 0xdeadbeef, got 0x%x\n", val); 4321 DestroyWindow(mdi_client); 4322 ok_sequence(WmDestroyMDIclientSeq, "Destroy MDI client window", FALSE); 4323 4324 /* test maximization of MDI child with invisible parent */ 4325 client_cs.hWindowMenu = 0; 4326 mdi_client = CreateWindowA("MDI_client_class", 4327 NULL, 4328 WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL | WS_VISIBLE, 4329 0, 0, 660, 430, 4330 mdi_frame, 0, GetModuleHandleA(0), &client_cs); 4331 ok_sequence(WmCreateMDIclientSeq, "Create MDI client window", FALSE); 4332 4333 ShowWindow(mdi_client, SW_HIDE); 4334 ok_sequence(WmHideMDIclientSeq, "Hide MDI client window", FALSE); 4335 4336 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", 4337 WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL, 4338 0, 0, 650, 440, 4339 mdi_client, 0, GetModuleHandleA(0), NULL); 4340 ok_sequence(WmCreateMDIchildInvisibleParentSeq, "Create MDI child window with invisible parent", FALSE); 4341 4342 SendMessageA(mdi_client, WM_MDIMAXIMIZE, (WPARAM) mdi_child, 0); 4343 ok_sequence(WmMaximizeMDIchildInvisibleParentSeq, "Maximize MDI child window with invisible parent", TRUE); 4344 zoomed = IsZoomed(mdi_child); 4345 ok(zoomed, "wrong zoomed state %d\n", zoomed); 4346 4347 ShowWindow(mdi_client, SW_SHOW); 4348 ok_sequence(WmShowMDIclientSeq, "Show MDI client window", FALSE); 4349 4350 DestroyWindow(mdi_child); 4351 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible maximized MDI child window", TRUE); 4352 4353 /* end of test for maximization of MDI child with invisible parent */ 4354 4355 DestroyWindow(mdi_client); 4356 ok_sequence(WmDestroyMDIclientSeq, "Destroy MDI client window", FALSE); 4357 4358 DestroyWindow(mdi_frame); 4359 ok_sequence(WmDestroyMDIframeSeq, "Destroy MDI frame window", FALSE); 4360 } 4361 /************************* End of MDI test **********************************/ 4362 4363 static void test_WM_SETREDRAW(HWND hwnd) 4364 { 4365 DWORD style = GetWindowLongA(hwnd, GWL_STYLE); 4366 4367 flush_events(); 4368 flush_sequence(); 4369 4370 SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0); 4371 ok_sequence(WmSetRedrawFalseSeq, "SetRedraw:FALSE", FALSE); 4372 4373 ok(!(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should NOT be set\n"); 4374 ok(!IsWindowVisible(hwnd), "IsWindowVisible() should return FALSE\n"); 4375 4376 flush_sequence(); 4377 SendMessageA(hwnd, WM_SETREDRAW, TRUE, 0); 4378 ok_sequence(WmSetRedrawTrueSeq, "SetRedraw:TRUE", FALSE); 4379 4380 ok(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 4381 ok(IsWindowVisible(hwnd), "IsWindowVisible() should return TRUE\n"); 4382 4383 /* restore original WS_VISIBLE state */ 4384 SetWindowLongA(hwnd, GWL_STYLE, style); 4385 4386 flush_events(); 4387 flush_sequence(); 4388 } 4389 4390 static INT_PTR CALLBACK TestModalDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 4391 { 4392 struct recvd_message msg; 4393 4394 if (ignore_message( message )) return 0; 4395 4396 switch (message) 4397 { 4398 /* ignore */ 4399 case WM_MOUSEMOVE: 4400 case WM_NCMOUSEMOVE: 4401 case WM_NCMOUSELEAVE: 4402 case WM_SETCURSOR: 4403 return 0; 4404 case WM_NCHITTEST: 4405 return HTCLIENT; 4406 } 4407 4408 msg.hwnd = hwnd; 4409 msg.message = message; 4410 msg.flags = sent|wparam|lparam; 4411 msg.wParam = wParam; 4412 msg.lParam = lParam; 4413 msg.descr = "dialog"; 4414 add_message(&msg); 4415 4416 if (message == WM_INITDIALOG) SetTimer( hwnd, 1, 100, NULL ); 4417 if (message == WM_TIMER) EndDialog( hwnd, 0 ); 4418 return 0; 4419 } 4420 4421 static INT_PTR CALLBACK TestModalDlgProc2(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 4422 { 4423 struct recvd_message msg; 4424 4425 if (ignore_message( message )) return 0; 4426 4427 switch (message) 4428 { 4429 /* ignore */ 4430 case WM_MOUSEMOVE: 4431 case WM_NCMOUSEMOVE: 4432 case WM_NCMOUSELEAVE: 4433 case WM_SETCURSOR: 4434 return 0; 4435 case WM_NCHITTEST: 4436 return HTCLIENT; 4437 } 4438 4439 msg.hwnd = hwnd; 4440 msg.message = message; 4441 msg.flags = sent|wparam|lparam; 4442 msg.wParam = wParam; 4443 msg.lParam = lParam; 4444 msg.descr = "dialog"; 4445 add_message(&msg); 4446 4447 if (message == WM_INITDIALOG) EndDialog( hwnd, 0 ); 4448 return 0; 4449 } 4450 4451 static void test_hv_scroll_1(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max) 4452 { 4453 DWORD style, exstyle; 4454 INT xmin, xmax; 4455 BOOL ret; 4456 4457 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE); 4458 style = GetWindowLongA(hwnd, GWL_STYLE); 4459 /* do not be confused by WS_DLGFRAME set */ 4460 if ((style & WS_CAPTION) == WS_CAPTION) style &= ~WS_CAPTION; 4461 4462 if (clear) ok(style & clear, "style %08x should be set\n", clear); 4463 if (set) ok(!(style & set), "style %08x should not be set\n", set); 4464 4465 ret = SetScrollRange(hwnd, ctl, min, max, FALSE); 4466 ok( ret, "SetScrollRange(%d) error %d\n", ctl, GetLastError()); 4467 if ((style & (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME)) || (exstyle & WS_EX_DLGMODALFRAME)) 4468 ok_sequence(WmSetScrollRangeHV_NC_Seq, "SetScrollRange(SB_HORZ/SB_VERT) NC", FALSE); 4469 else 4470 ok_sequence(WmSetScrollRangeHVSeq, "SetScrollRange(SB_HORZ/SB_VERT)", FALSE); 4471 4472 style = GetWindowLongA(hwnd, GWL_STYLE); 4473 if (set) ok(style & set, "style %08x should be set\n", set); 4474 if (clear) ok(!(style & clear), "style %08x should not be set\n", clear); 4475 4476 /* a subsequent call should do nothing */ 4477 ret = SetScrollRange(hwnd, ctl, min, max, FALSE); 4478 ok( ret, "SetScrollRange(%d) error %d\n", ctl, GetLastError()); 4479 ok_sequence(WmEmptySeq, "SetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE); 4480 4481 xmin = 0xdeadbeef; 4482 xmax = 0xdeadbeef; 4483 ret = GetScrollRange(hwnd, ctl, &xmin, &xmax); 4484 ok( ret, "GetScrollRange(%d) error %d\n", ctl, GetLastError()); 4485 ok_sequence(WmEmptySeq, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE); 4486 ok(xmin == min, "unexpected min scroll value %d\n", xmin); 4487 ok(xmax == max, "unexpected max scroll value %d\n", xmax); 4488 } 4489 4490 static void test_hv_scroll_2(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max) 4491 { 4492 DWORD style, exstyle; 4493 SCROLLINFO si; 4494 BOOL ret; 4495 4496 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE); 4497 style = GetWindowLongA(hwnd, GWL_STYLE); 4498 /* do not be confused by WS_DLGFRAME set */ 4499 if ((style & WS_CAPTION) == WS_CAPTION) style &= ~WS_CAPTION; 4500 4501 if (clear) ok(style & clear, "style %08x should be set\n", clear); 4502 if (set) ok(!(style & set), "style %08x should not be set\n", set); 4503 4504 si.cbSize = sizeof(si); 4505 si.fMask = SIF_RANGE; 4506 si.nMin = min; 4507 si.nMax = max; 4508 SetScrollInfo(hwnd, ctl, &si, TRUE); 4509 if ((style & (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME)) || (exstyle & WS_EX_DLGMODALFRAME)) 4510 ok_sequence(WmSetScrollRangeHV_NC_Seq, "SetScrollInfo(SB_HORZ/SB_VERT) NC", FALSE); 4511 else 4512 ok_sequence(WmSetScrollRangeHVSeq, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE); 4513 4514 style = GetWindowLongA(hwnd, GWL_STYLE); 4515 if (set) ok(style & set, "style %08x should be set\n", set); 4516 if (clear) ok(!(style & clear), "style %08x should not be set\n", clear); 4517 4518 /* a subsequent call should do nothing */ 4519 SetScrollInfo(hwnd, ctl, &si, TRUE); 4520 if (style & WS_HSCROLL) 4521 ok_sequence(WmSetScrollRangeHSeq_empty, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE); 4522 else if (style & WS_VSCROLL) 4523 ok_sequence(WmSetScrollRangeVSeq_empty, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE); 4524 else 4525 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE); 4526 4527 si.fMask = SIF_PAGE; 4528 si.nPage = 5; 4529 SetScrollInfo(hwnd, ctl, &si, FALSE); 4530 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE); 4531 4532 si.fMask = SIF_POS; 4533 si.nPos = max - 1; 4534 SetScrollInfo(hwnd, ctl, &si, FALSE); 4535 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE); 4536 4537 si.fMask = SIF_RANGE; 4538 si.nMin = 0xdeadbeef; 4539 si.nMax = 0xdeadbeef; 4540 ret = GetScrollInfo(hwnd, ctl, &si); 4541 ok( ret, "GetScrollInfo error %d\n", GetLastError()); 4542 ok_sequence(WmEmptySeq, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE); 4543 ok(si.nMin == min, "unexpected min scroll value %d\n", si.nMin); 4544 ok(si.nMax == max, "unexpected max scroll value %d\n", si.nMax); 4545 } 4546 4547 /* Win9x sends WM_USER+xxx while and NT versions send SBM_xxx messages */ 4548 static void test_scroll_messages(HWND hwnd) 4549 { 4550 SCROLLINFO si; 4551 INT min, max; 4552 BOOL ret; 4553 4554 flush_events(); 4555 flush_sequence(); 4556 4557 min = 0xdeadbeef; 4558 max = 0xdeadbeef; 4559 ret = GetScrollRange(hwnd, SB_CTL, &min, &max); 4560 ok( ret, "GetScrollRange error %d\n", GetLastError()); 4561 if (sequence->message != WmGetScrollRangeSeq[0].message) 4562 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message); 4563 /* values of min and max are undefined */ 4564 flush_sequence(); 4565 4566 ret = SetScrollRange(hwnd, SB_CTL, 10, 150, FALSE); 4567 ok( ret, "SetScrollRange error %d\n", GetLastError()); 4568 if (sequence->message != WmSetScrollRangeSeq[0].message) 4569 trace("SetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message); 4570 flush_sequence(); 4571 4572 min = 0xdeadbeef; 4573 max = 0xdeadbeef; 4574 ret = GetScrollRange(hwnd, SB_CTL, &min, &max); 4575 ok( ret, "GetScrollRange error %d\n", GetLastError()); 4576 if (sequence->message != WmGetScrollRangeSeq[0].message) 4577 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message); 4578 /* values of min and max are undefined */ 4579 flush_sequence(); 4580 4581 si.cbSize = sizeof(si); 4582 si.fMask = SIF_RANGE; 4583 si.nMin = 20; 4584 si.nMax = 160; 4585 SetScrollInfo(hwnd, SB_CTL, &si, FALSE); 4586 if (sequence->message != WmSetScrollRangeSeq[0].message) 4587 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message); 4588 flush_sequence(); 4589 4590 si.fMask = SIF_PAGE; 4591 si.nPage = 10; 4592 SetScrollInfo(hwnd, SB_CTL, &si, FALSE); 4593 if (sequence->message != WmSetScrollRangeSeq[0].message) 4594 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message); 4595 flush_sequence(); 4596 4597 si.fMask = SIF_POS; 4598 si.nPos = 20; 4599 SetScrollInfo(hwnd, SB_CTL, &si, FALSE); 4600 if (sequence->message != WmSetScrollRangeSeq[0].message) 4601 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message); 4602 flush_sequence(); 4603 4604 si.fMask = SIF_RANGE; 4605 si.nMin = 0xdeadbeef; 4606 si.nMax = 0xdeadbeef; 4607 ret = GetScrollInfo(hwnd, SB_CTL, &si); 4608 ok( ret, "GetScrollInfo error %d\n", GetLastError()); 4609 if (sequence->message != WmGetScrollInfoSeq[0].message) 4610 trace("GetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message); 4611 /* values of min and max are undefined */ 4612 flush_sequence(); 4613 4614 /* set WS_HSCROLL */ 4615 test_hv_scroll_1(hwnd, SB_HORZ, 0, WS_HSCROLL, 10, 150); 4616 /* clear WS_HSCROLL */ 4617 test_hv_scroll_1(hwnd, SB_HORZ, WS_HSCROLL, 0, 0, 0); 4618 4619 /* set WS_HSCROLL */ 4620 test_hv_scroll_2(hwnd, SB_HORZ, 0, WS_HSCROLL, 10, 150); 4621 /* clear WS_HSCROLL */ 4622 test_hv_scroll_2(hwnd, SB_HORZ, WS_HSCROLL, 0, 0, 0); 4623 4624 /* set WS_VSCROLL */ 4625 test_hv_scroll_1(hwnd, SB_VERT, 0, WS_VSCROLL, 10, 150); 4626 /* clear WS_VSCROLL */ 4627 test_hv_scroll_1(hwnd, SB_VERT, WS_VSCROLL, 0, 0, 0); 4628 4629 /* set WS_VSCROLL */ 4630 test_hv_scroll_2(hwnd, SB_VERT, 0, WS_VSCROLL, 10, 150); 4631 /* clear WS_VSCROLL */ 4632 test_hv_scroll_2(hwnd, SB_VERT, WS_VSCROLL, 0, 0, 0); 4633 } 4634 4635 static void test_showwindow(void) 4636 { 4637 HWND hwnd, hchild; 4638 RECT rc; 4639 4640 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW, 4641 100, 100, 200, 200, 0, 0, 0, NULL); 4642 ok (hwnd != 0, "Failed to create overlapped window\n"); 4643 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 4644 0, 0, 10, 10, hwnd, 0, 0, NULL); 4645 ok (hchild != 0, "Failed to create child\n"); 4646 flush_sequence(); 4647 4648 /* ShowWindow( SW_SHOWNA) for invisible top level window */ 4649 trace("calling ShowWindow( SW_SHOWNA) for invisible top level window\n"); 4650 ok( ShowWindow(hwnd, SW_SHOWNA) == FALSE, "ShowWindow: window was visible\n" ); 4651 ok_sequence(WmSHOWNATopInvisible, "ShowWindow(SW_SHOWNA) on invisible top level window", FALSE); 4652 4653 /* ShowWindow( SW_SHOWNA) for now visible top level window */ 4654 trace("calling ShowWindow( SW_SHOWNA) for now visible top level window\n"); 4655 ok( ShowWindow(hwnd, SW_SHOWNA) != FALSE, "ShowWindow: window was invisible\n" ); 4656 ok_sequence(WmSHOWNATopVisible, "ShowWindow(SW_SHOWNA) on visible top level window", FALSE); 4657 /* back to invisible */ 4658 ShowWindow(hchild, SW_HIDE); 4659 ShowWindow(hwnd, SW_HIDE); 4660 flush_sequence(); 4661 /* ShowWindow(SW_SHOWNA) with child and parent invisible */ 4662 trace("calling ShowWindow( SW_SHOWNA) for invisible child with invisible parent\n"); 4663 ok( ShowWindow(hchild, SW_SHOWNA) == FALSE, "ShowWindow: window was visible\n" ); 4664 ok_sequence(WmSHOWNAChildInvisParInvis, "ShowWindow(SW_SHOWNA) invisible child and parent", FALSE); 4665 /* ShowWindow(SW_SHOWNA) with child visible and parent invisible */ 4666 ok( ShowWindow(hchild, SW_SHOW) != FALSE, "ShowWindow: window was invisible\n" ); 4667 flush_sequence(); 4668 trace("calling ShowWindow( SW_SHOWNA) for the visible child and invisible parent\n"); 4669 ok( ShowWindow(hchild, SW_SHOWNA) != FALSE, "ShowWindow: window was invisible\n" ); 4670 ok_sequence(WmSHOWNAChildVisParInvis, "ShowWindow(SW_SHOWNA) visible child and invisible parent", FALSE); 4671 /* ShowWindow(SW_SHOWNA) with child visible and parent visible */ 4672 ShowWindow( hwnd, SW_SHOW); 4673 flush_sequence(); 4674 trace("calling ShowWindow( SW_SHOWNA) for the visible child and parent\n"); 4675 ok( ShowWindow(hchild, SW_SHOWNA) != FALSE, "ShowWindow: window was invisible\n" ); 4676 ok_sequence(WmSHOWNAChildVisParVis, "ShowWindow(SW_SHOWNA) for the visible child and parent", FALSE); 4677 4678 /* ShowWindow(SW_SHOWNA) with child invisible and parent visible */ 4679 ShowWindow( hchild, SW_HIDE); 4680 flush_sequence(); 4681 trace("calling ShowWindow( SW_SHOWNA) for the invisible child and visible parent\n"); 4682 ok( ShowWindow(hchild, SW_SHOWNA) == FALSE, "ShowWindow: window was visible\n" ); 4683 ok_sequence(WmSHOWNAChildInvisParVis, "ShowWindow(SW_SHOWNA) for the invisible child and visible parent", FALSE); 4684 4685 SetCapture(hchild); 4686 ok(GetCapture() == hchild, "wrong capture window %p\n", GetCapture()); 4687 DestroyWindow(hchild); 4688 ok(!GetCapture(), "wrong capture window %p\n", GetCapture()); 4689 4690 DestroyWindow(hwnd); 4691 flush_sequence(); 4692 4693 /* Popup windows */ 4694 /* Test 1: 4695 * 1. Create invisible maximized popup window. 4696 * 2. Move and resize it. 4697 * 3. Show it maximized. 4698 */ 4699 trace("calling CreateWindowExA( WS_MAXIMIZE ) for invisible maximized popup window\n"); 4700 hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_MAXIMIZE, 4701 100, 100, 200, 200, 0, 0, 0, NULL); 4702 ok (hwnd != 0, "Failed to create popup window\n"); 4703 ok(IsZoomed(hwnd), "window should be maximized\n"); 4704 ok_sequence(WmCreateInvisibleMaxPopupSeq, "CreateWindow(WS_MAXIMIZED):popup", FALSE); 4705 4706 GetWindowRect(hwnd, &rc); 4707 ok( rc.right-rc.left == GetSystemMetrics(SM_CXSCREEN) && 4708 rc.bottom-rc.top == GetSystemMetrics(SM_CYSCREEN), 4709 "Invalid maximized size before ShowWindow %s\n", wine_dbgstr_rect( &rc )); 4710 /* Reset window's size & position */ 4711 SetWindowPos(hwnd, 0, 10, 10, 200, 200, SWP_NOZORDER | SWP_NOACTIVATE); 4712 ok(IsZoomed(hwnd), "window should be maximized\n"); 4713 flush_sequence(); 4714 4715 trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible maximized popup window\n"); 4716 ShowWindow(hwnd, SW_SHOWMAXIMIZED); 4717 ok(IsZoomed(hwnd), "window should be maximized\n"); 4718 ok_sequence(WmShowMaxPopupResizedSeq, "ShowWindow(SW_SHOWMAXIMIZED):invisible maximized and resized popup", FALSE); 4719 4720 GetWindowRect(hwnd, &rc); 4721 ok( rc.right-rc.left == GetSystemMetrics(SM_CXSCREEN) && 4722 rc.bottom-rc.top == GetSystemMetrics(SM_CYSCREEN), 4723 "Invalid maximized size after ShowWindow %s\n", wine_dbgstr_rect( &rc )); 4724 DestroyWindow(hwnd); 4725 flush_sequence(); 4726 4727 /* Test 2: 4728 * 1. Create invisible maximized popup window. 4729 * 2. Show it maximized. 4730 */ 4731 trace("calling CreateWindowExA( WS_MAXIMIZE ) for invisible maximized popup window\n"); 4732 hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_MAXIMIZE, 4733 100, 100, 200, 200, 0, 0, 0, NULL); 4734 ok (hwnd != 0, "Failed to create popup window\n"); 4735 ok(IsZoomed(hwnd), "window should be maximized\n"); 4736 ok_sequence(WmCreateInvisibleMaxPopupSeq, "CreateWindow(WS_MAXIMIZED):popup", FALSE); 4737 4738 trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible maximized popup window\n"); 4739 ShowWindow(hwnd, SW_SHOWMAXIMIZED); 4740 ok(IsZoomed(hwnd), "window should be maximized\n"); 4741 ok_sequence(WmShowMaxPopupSeq, "ShowWindow(SW_SHOWMAXIMIZED):invisible maximized popup", FALSE); 4742 DestroyWindow(hwnd); 4743 flush_sequence(); 4744 4745 /* Test 3: 4746 * 1. Create visible maximized popup window. 4747 */ 4748 trace("calling CreateWindowExA( WS_MAXIMIZE ) for maximized popup window\n"); 4749 hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_MAXIMIZE | WS_VISIBLE, 4750 100, 100, 200, 200, 0, 0, 0, NULL); 4751 ok (hwnd != 0, "Failed to create popup window\n"); 4752 ok(IsZoomed(hwnd), "window should be maximized\n"); 4753 ok_sequence(WmCreateMaxPopupSeq, "CreateWindow(WS_MAXIMIZED):popup", FALSE); 4754 DestroyWindow(hwnd); 4755 flush_sequence(); 4756 4757 /* Test 4: 4758 * 1. Create visible popup window. 4759 * 2. Maximize it. 4760 */ 4761 trace("calling CreateWindowExA( WS_VISIBLE ) for popup window\n"); 4762 hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_VISIBLE, 4763 100, 100, 200, 200, 0, 0, 0, NULL); 4764 ok (hwnd != 0, "Failed to create popup window\n"); 4765 ok(!IsZoomed(hwnd), "window should NOT be maximized\n"); 4766 ok_sequence(WmCreatePopupSeq, "CreateWindow(WS_VISIBLE):popup", FALSE); 4767 4768 trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for visible popup window\n"); 4769 ShowWindow(hwnd, SW_SHOWMAXIMIZED); 4770 ok(IsZoomed(hwnd), "window should be maximized\n"); 4771 ok_sequence(WmShowVisMaxPopupSeq, "ShowWindow(SW_SHOWMAXIMIZED):popup", FALSE); 4772 DestroyWindow(hwnd); 4773 flush_sequence(); 4774 } 4775 4776 static void test_recursive_activation(void) 4777 { 4778 static const struct message seq[] = 4779 { 4780 { HCBT_ACTIVATE, hook }, 4781 { WM_NCACTIVATE, sent|wparam, TRUE }, 4782 { WM_ACTIVATE, sent|wparam, WA_ACTIVE }, 4783 { HCBT_ACTIVATE, hook }, 4784 { WM_NCACTIVATE, sent|wparam, FALSE }, 4785 { WM_ACTIVATE, sent|wparam, WA_INACTIVE }, 4786 { WM_SETFOCUS, sent|optional }, 4787 { 0 } 4788 }; 4789 HWND hwnd, recursive; 4790 4791 hwnd = CreateWindowExA(0, "SimpleWindowClass", NULL, WS_OVERLAPPED|WS_VISIBLE, 4792 100, 100, 200, 200, 0, 0, 0, NULL); 4793 ok(hwnd != 0, "Failed to create simple window\n"); 4794 4795 recursive = CreateWindowExA(0, "RecursiveActivationClass", NULL, WS_OVERLAPPED|WS_VISIBLE, 4796 10, 10, 50, 50, hwnd, 0, 0, NULL); 4797 ok(recursive != 0, "Failed to create recursive activation window\n"); 4798 SetActiveWindow(hwnd); 4799 4800 flush_sequence(); 4801 SetActiveWindow(recursive); 4802 ok_sequence(seq, "Recursive Activation", FALSE); 4803 4804 DestroyWindow(recursive); 4805 DestroyWindow(hwnd); 4806 flush_sequence(); 4807 } 4808 4809 static void test_sys_menu(void) 4810 { 4811 HWND hwnd; 4812 HMENU hmenu; 4813 UINT state; 4814 4815 hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, 4816 100, 100, 200, 200, 0, 0, 0, NULL); 4817 ok (hwnd != 0, "Failed to create overlapped window\n"); 4818 4819 flush_sequence(); 4820 4821 /* test existing window without CS_NOCLOSE style */ 4822 hmenu = GetSystemMenu(hwnd, FALSE); 4823 ok(hmenu != 0, "GetSystemMenu error %d\n", GetLastError()); 4824 4825 state = GetMenuState(hmenu, SC_CLOSE, MF_BYCOMMAND); 4826 ok(state != 0xffffffff, "wrong SC_CLOSE state %x\n", state); 4827 ok(!(state & (MF_DISABLED | MF_GRAYED)), "wrong SC_CLOSE state %x\n", state); 4828 4829 EnableMenuItem(hmenu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED); 4830 ok_sequence(WmEmptySeq, "WmEnableMenuItem", FALSE); 4831 4832 state = GetMenuState(hmenu, SC_CLOSE, MF_BYCOMMAND); 4833 ok(state != 0xffffffff, "wrong SC_CLOSE state %x\n", state); 4834 ok((state & (MF_DISABLED | MF_GRAYED)) == MF_GRAYED, "wrong SC_CLOSE state %x\n", state); 4835 4836 EnableMenuItem(hmenu, SC_CLOSE, 0); 4837 ok_sequence(WmEmptySeq, "WmEnableMenuItem", FALSE); 4838 4839 state = GetMenuState(hmenu, SC_CLOSE, MF_BYCOMMAND); 4840 ok(state != 0xffffffff, "wrong SC_CLOSE state %x\n", state); 4841 ok(!(state & (MF_DISABLED | MF_GRAYED)), "wrong SC_CLOSE state %x\n", state); 4842 4843 /* test whether removing WS_SYSMENU destroys a system menu */ 4844 SetWindowLongW(hwnd, GWL_STYLE, WS_POPUP); 4845 SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_FRAMECHANGED); 4846 flush_sequence(); 4847 hmenu = GetSystemMenu(hwnd, FALSE); 4848 ok(hmenu != 0, "GetSystemMenu error %d\n", GetLastError()); 4849 4850 DestroyWindow(hwnd); 4851 4852 /* test new window with CS_NOCLOSE style */ 4853 hwnd = CreateWindowExA(0, "NoCloseWindowClass", NULL, WS_OVERLAPPEDWINDOW, 4854 100, 100, 200, 200, 0, 0, 0, NULL); 4855 ok (hwnd != 0, "Failed to create overlapped window\n"); 4856 4857 hmenu = GetSystemMenu(hwnd, FALSE); 4858 ok(hmenu != 0, "GetSystemMenu error %d\n", GetLastError()); 4859 4860 state = GetMenuState(hmenu, SC_CLOSE, MF_BYCOMMAND); 4861 ok(state == 0xffffffff, "wrong SC_CLOSE state %x\n", state); 4862 4863 DestroyWindow(hwnd); 4864 4865 /* test new window without WS_SYSMENU style */ 4866 hwnd = CreateWindowExA(0, "NoCloseWindowClass", NULL, WS_OVERLAPPEDWINDOW & ~WS_SYSMENU, 4867 100, 100, 200, 200, 0, 0, 0, NULL); 4868 ok(hwnd != 0, "Failed to create overlapped window\n"); 4869 4870 hmenu = GetSystemMenu(hwnd, FALSE); 4871 ok(!hmenu, "GetSystemMenu error %d\n", GetLastError()); 4872 4873 DestroyWindow(hwnd); 4874 } 4875 4876 /* For shown WS_OVERLAPPEDWINDOW */ 4877 static const struct message WmSetIcon_1[] = { 4878 { WM_SETICON, sent }, 4879 { 0x00AE, sent|defwinproc|optional }, /* XP */ 4880 { WM_GETTEXT, sent|defwinproc|optional }, 4881 { WM_GETTEXT, sent|defwinproc|optional }, /* XP sends a duplicate */ 4882 { 0 } 4883 }; 4884 4885 /* For WS_POPUP and hidden WS_OVERLAPPEDWINDOW */ 4886 static const struct message WmSetIcon_2[] = { 4887 { WM_SETICON, sent }, 4888 { 0 } 4889 }; 4890 4891 /* Sending undocumented 0x3B message with wparam = 0x8000000b */ 4892 static const struct message WmInitEndSession[] = { 4893 { 0x003B, sent }, 4894 { WM_QUERYENDSESSION, sent|defwinproc|wparam|lparam, 0, ENDSESSION_LOGOFF }, 4895 { 0 } 4896 }; 4897 4898 /* Sending undocumented 0x3B message with wparam = 0x0000000b */ 4899 static const struct message WmInitEndSession_2[] = { 4900 { 0x003B, sent }, 4901 { WM_QUERYENDSESSION, sent|defwinproc|wparam|lparam, 0, 0 }, 4902 { 0 } 4903 }; 4904 4905 /* Sending undocumented 0x3B message with wparam = 0x80000008 */ 4906 static const struct message WmInitEndSession_3[] = { 4907 { 0x003B, sent }, 4908 { WM_ENDSESSION, sent|defwinproc|wparam|lparam, 0, ENDSESSION_LOGOFF }, 4909 { 0 } 4910 }; 4911 4912 /* Sending undocumented 0x3B message with wparam = 0x00000008 */ 4913 static const struct message WmInitEndSession_4[] = { 4914 { 0x003B, sent }, 4915 { WM_ENDSESSION, sent|defwinproc|wparam|lparam, 0, 0 }, 4916 { 0 } 4917 }; 4918 4919 /* Sending undocumented 0x3B message with wparam = 0x80000001 */ 4920 static const struct message WmInitEndSession_5[] = { 4921 { 0x003B, sent }, 4922 { WM_ENDSESSION, sent|defwinproc/*|wparam*/|lparam, 1, ENDSESSION_LOGOFF }, 4923 { 0 } 4924 }; 4925 4926 static const struct message WmOptionalPaint[] = { 4927 { WM_PAINT, sent|optional }, 4928 { WM_NCPAINT, sent|beginpaint|optional }, 4929 { WM_GETTEXT, sent|beginpaint|defwinproc|optional }, 4930 { WM_ERASEBKGND, sent|beginpaint|optional }, 4931 { 0 } 4932 }; 4933 4934 static const struct message WmZOrder[] = { 4935 { WM_WINDOWPOSCHANGING, sent|wparam, 0, 0 }, 4936 { WM_GETMINMAXINFO, sent|defwinproc|wparam, 0, 0 }, 4937 { HCBT_ACTIVATE, hook }, 4938 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 4939 { WM_WINDOWPOSCHANGING, sent|wparam, 3, 0 }, 4940 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOREDRAW|SWP_NOMOVE|SWP_NOSIZE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE, 0 }, 4941 { WM_GETTEXT, sent|optional }, 4942 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, 4943 { WM_ACTIVATEAPP, sent|wparam, 1, 0 }, 4944 { WM_NCACTIVATE, sent|lparam, 1, 0 }, 4945 { WM_GETTEXT, sent|defwinproc|optional }, 4946 { WM_GETTEXT, sent|defwinproc|optional }, 4947 { WM_ACTIVATE, sent|wparam|lparam, 1, 0 }, 4948 { HCBT_SETFOCUS, hook }, 4949 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 4950 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 4951 { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, 4952 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 4953 { WM_GETTEXT, sent|optional }, 4954 { WM_NCCALCSIZE, sent|optional }, 4955 { 0 } 4956 }; 4957 4958 static void CALLBACK apc_test_proc(ULONG_PTR param) 4959 { 4960 /* nothing */ 4961 } 4962 4963 static void test_MsgWaitForMultipleObjects(HWND hwnd) 4964 { 4965 DWORD ret; 4966 MSG msg; 4967 4968 ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE); 4969 ok(ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjects returned %x\n", ret); 4970 4971 PostMessageA(hwnd, WM_USER, 0, 0); 4972 4973 ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE); 4974 ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjects returned %x\n", ret); 4975 4976 ok(PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n"); 4977 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message); 4978 4979 ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE); 4980 ok(ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjects returned %x\n", ret); 4981 4982 PostMessageA(hwnd, WM_USER, 0, 0); 4983 4984 ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE); 4985 ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjects returned %x\n", ret); 4986 4987 ok(PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ), "PeekMessage should succeed\n"); 4988 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message); 4989 4990 /* shows QS_POSTMESSAGE flag is cleared in the PeekMessage call */ 4991 ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE); 4992 ok(ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjects returned %x\n", ret); 4993 4994 PostMessageA(hwnd, WM_USER, 0, 0); 4995 4996 /* new incoming message causes it to become signaled again */ 4997 ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE); 4998 ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjects returned %x\n", ret); 4999 5000 ok(PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n"); 5001 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message); 5002 ok(PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n"); 5003 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message); 5004 5005 /* MWMO_INPUTAVAILABLE should succeed even if the message was already seen */ 5006 PostMessageA( hwnd, WM_USER, 0, 0 ); 5007 ok(PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ), "PeekMessage should succeed\n"); 5008 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message); 5009 5010 ret = MsgWaitForMultipleObjectsEx( 0, NULL, 0, QS_POSTMESSAGE, MWMO_INPUTAVAILABLE ); 5011 ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjectsEx returned %x\n", ret); 5012 5013 ok(PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n"); 5014 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message); 5015 5016 /* without MWMO_ALERTABLE the result is never WAIT_IO_COMPLETION */ 5017 ret = QueueUserAPC( apc_test_proc, GetCurrentThread(), 0 ); 5018 ok(ret, "QueueUserAPC failed %u\n", GetLastError()); 5019 5020 ret = MsgWaitForMultipleObjectsEx( 0, NULL, 0, QS_POSTMESSAGE, 0 ); 5021 ok(ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjectsEx returned %x\n", ret); 5022 5023 /* but even with MWMO_ALERTABLE window events are preferred */ 5024 PostMessageA( hwnd, WM_USER, 0, 0 ); 5025 5026 ret = MsgWaitForMultipleObjectsEx( 0, NULL, 0, QS_POSTMESSAGE, MWMO_ALERTABLE ); 5027 ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjectsEx returned %x\n", ret); 5028 5029 ok(PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n"); 5030 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message); 5031 5032 /* the APC call is still queued */ 5033 ret = MsgWaitForMultipleObjectsEx( 0, NULL, 0, QS_POSTMESSAGE, MWMO_ALERTABLE ); 5034 ok(ret == WAIT_IO_COMPLETION, "MsgWaitForMultipleObjectsEx returned %x\n", ret); 5035 } 5036 5037 static void test_WM_DEVICECHANGE(HWND hwnd) 5038 { 5039 DWORD ret; 5040 MSG msg; 5041 int i; 5042 static const WPARAM wparams[] = {0, 5043 DBT_DEVNODES_CHANGED, 5044 DBT_QUERYCHANGECONFIG, 5045 DBT_CONFIGCHANGED, 5046 DBT_CONFIGCHANGECANCELED, 5047 DBT_NO_DISK_SPACE, 5048 DBT_LOW_DISK_SPACE, 5049 DBT_CONFIGMGPRIVATE, /* 0x7fff */ 5050 DBT_DEVICEARRIVAL, /* 0x8000 */ 5051 DBT_DEVICEQUERYREMOVE, 5052 DBT_DEVICEQUERYREMOVEFAILED, 5053 DBT_DEVICEREMOVEPENDING, 5054 DBT_DEVICEREMOVECOMPLETE, 5055 DBT_DEVICETYPESPECIFIC, 5056 DBT_CUSTOMEVENT}; 5057 5058 for (i = 0; i < ARRAY_SIZE(wparams); i++) 5059 { 5060 SetLastError(0xdeadbeef); 5061 ret = PostMessageA(hwnd, WM_DEVICECHANGE, wparams[i], 0); 5062 if (wparams[i] & 0x8000) 5063 { 5064 ok(ret == FALSE, "PostMessage should returned %d\n", ret); 5065 ok(GetLastError() == ERROR_MESSAGE_SYNC_ONLY, "PostMessage error %08x\n", GetLastError()); 5066 } 5067 else 5068 { 5069 ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE); 5070 ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjects returned %x\n", ret); 5071 memset(&msg, 0, sizeof(msg)); 5072 ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "PeekMessage should succeed\n"); 5073 ok(msg.message == WM_DEVICECHANGE, "got %04x instead of WM_DEVICECHANGE\n", msg.message); 5074 } 5075 } 5076 } 5077 5078 static DWORD CALLBACK show_window_thread(LPVOID arg) 5079 { 5080 HWND hwnd = arg; 5081 5082 /* function will not return if ShowWindow(SW_HIDE) calls SendMessage() */ 5083 ok(ShowWindow(hwnd, SW_HIDE) == FALSE, "ShowWindow(SW_HIDE) expected FALSE\n"); 5084 5085 return 0; 5086 } 5087 5088 /* Helper function to easier test SetWindowPos messages */ 5089 #define test_msg_setpos( expected_list, flags, todo ) \ 5090 test_msg_setpos_( (expected_list), (flags), (todo), __FILE__, __LINE__) 5091 static void test_msg_setpos_(const struct message *expected_list, UINT flags, BOOL todo, const char *file, int line) 5092 { 5093 HWND hwnd; 5094 5095 flush_events(); 5096 flush_sequence(); 5097 hwnd = CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP, 5098 10, 10, 100, 100, NULL, 0, 0, NULL ); 5099 ok (hwnd != 0, "Failed to create popup window\n"); 5100 SetWindowPos(hwnd, NULL, 0, 0, 100, 100, flags); 5101 ok_sequence_(expected_list, "SetWindowPos:show_popup_first_show_window", todo, file, line); 5102 DestroyWindow(hwnd); 5103 } 5104 5105 /* test if we receive the right sequence of messages */ 5106 static void test_messages(void) 5107 { 5108 DWORD tid; 5109 HANDLE hthread; 5110 HWND hwnd, hparent, hchild; 5111 HWND hchild2, hbutton; 5112 HMENU hmenu; 5113 MSG msg; 5114 LRESULT res; 5115 POINT pos; 5116 BOOL ret; 5117 5118 flush_sequence(); 5119 5120 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW, 5121 100, 100, 200, 200, 0, 0, 0, NULL); 5122 ok (hwnd != 0, "Failed to create overlapped window\n"); 5123 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped", FALSE); 5124 5125 /* test ShowWindow(SW_HIDE) on a newly created invisible window */ 5126 ok( ShowWindow(hwnd, SW_HIDE) == FALSE, "ShowWindow: window was visible\n" ); 5127 ok_sequence(WmEmptySeq, "ShowWindow(SW_HIDE):overlapped, invisible", FALSE); 5128 5129 /* test WM_SETREDRAW on a not visible top level window */ 5130 test_WM_SETREDRAW(hwnd); 5131 5132 SetWindowPos(hwnd, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE); 5133 flush_events(); 5134 ok_sequence(WmSWP_ShowOverlappedSeq, "SetWindowPos:SWP_SHOWWINDOW:overlapped", FALSE); 5135 ok(IsWindowVisible(hwnd), "window should be visible at this point\n"); 5136 5137 ok(GetActiveWindow() == hwnd, "window should be active\n"); 5138 ok(GetFocus() == hwnd, "window should have input focus\n"); 5139 ShowWindow(hwnd, SW_HIDE); 5140 flush_events(); 5141 ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped", FALSE); 5142 5143 /* test ShowWindow(SW_HIDE) on a hidden window - single threaded */ 5144 ok(ShowWindow(hwnd, SW_HIDE) == FALSE, "ShowWindow(SW_HIDE) expected FALSE\n"); 5145 flush_events(); 5146 ok_sequence(WmEmptySeq, "ShowWindow(SW_HIDE):overlapped", FALSE); 5147 5148 /* test ShowWindow(SW_HIDE) on a hidden window - multi-threaded */ 5149 hthread = CreateThread(NULL, 0, show_window_thread, hwnd, 0, &tid); 5150 ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError()); 5151 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 5152 CloseHandle(hthread); 5153 flush_events(); 5154 ok_sequence(WmEmptySeq, "ShowWindow(SW_HIDE):overlapped", FALSE); 5155 5156 ShowWindow(hwnd, SW_SHOW); 5157 flush_events(); 5158 ok_sequence(WmShowOverlappedSeq, "ShowWindow(SW_SHOW):overlapped", TRUE); 5159 5160 ShowWindow(hwnd, SW_HIDE); 5161 flush_events(); 5162 ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped", FALSE); 5163 5164 ShowWindow(hwnd, SW_SHOWMAXIMIZED); 5165 flush_events(); 5166 ok_sequence(WmShowMaxOverlappedSeq, "ShowWindow(SW_SHOWMAXIMIZED):overlapped", TRUE); 5167 flush_sequence(); 5168 5169 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_MAXIMIZE) 5170 { 5171 ShowWindow(hwnd, SW_RESTORE); 5172 flush_events(); 5173 ok_sequence(WmShowRestoreMaxOverlappedSeq, "ShowWindow(SW_RESTORE):overlapped", TRUE); 5174 flush_sequence(); 5175 } 5176 5177 ShowWindow(hwnd, SW_MINIMIZE); 5178 flush_events(); 5179 ok_sequence(WmShowMinOverlappedSeq, "ShowWindow(SW_SHOWMINIMIZED):overlapped", FALSE); 5180 flush_sequence(); 5181 5182 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_MINIMIZE) 5183 { 5184 ShowWindow(hwnd, SW_RESTORE); 5185 flush_events(); 5186 ok_sequence(WmShowRestoreMinOverlappedSeq, "ShowWindow(SW_RESTORE):overlapped", TRUE); 5187 flush_sequence(); 5188 } 5189 5190 ShowWindow(hwnd, SW_SHOW); 5191 flush_events(); 5192 ok_sequence(WmOptionalPaint, "ShowWindow(SW_SHOW):overlapped already visible", FALSE); 5193 5194 SetWindowPos(hwnd, 0,0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE); 5195 ok_sequence(WmSWP_HideOverlappedSeq, "SetWindowPos:SWP_HIDEWINDOW:overlapped", FALSE); 5196 ok(!IsWindowVisible(hwnd), "window should not be visible at this point\n"); 5197 ok(GetActiveWindow() == hwnd, "window should still be active\n"); 5198 5199 /* test WM_SETREDRAW on a visible top level window */ 5200 ShowWindow(hwnd, SW_SHOW); 5201 flush_events(); 5202 test_WM_SETREDRAW(hwnd); 5203 5204 trace("testing scroll APIs on a visible top level window %p\n", hwnd); 5205 test_scroll_messages(hwnd); 5206 5207 /* test resizing and moving */ 5208 SetWindowPos( hwnd, 0, 0, 0, 300, 300, SWP_NOMOVE|SWP_NOACTIVATE ); 5209 ok_sequence(WmSWP_ResizeSeq, "SetWindowPos:Resize", FALSE ); 5210 flush_events(); 5211 flush_sequence(); 5212 SetWindowPos( hwnd, 0, 200, 200, 0, 0, SWP_NOSIZE|SWP_NOACTIVATE ); 5213 ok_sequence(WmSWP_MoveSeq, "SetWindowPos:Move", FALSE ); 5214 flush_events(); 5215 flush_sequence(); 5216 SetWindowPos( hwnd, 0, 200, 200, 250, 250, SWP_NOZORDER|SWP_NOACTIVATE ); 5217 ok_sequence(WmSWP_ResizeNoZOrder, "SetWindowPos:WmSWP_ResizeNoZOrder", FALSE ); 5218 flush_events(); 5219 flush_sequence(); 5220 5221 /* popups don't get WM_GETMINMAXINFO */ 5222 SetWindowLongW( hwnd, GWL_STYLE, WS_VISIBLE|WS_POPUP ); 5223 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_FRAMECHANGED); 5224 flush_sequence(); 5225 SetWindowPos( hwnd, 0, 0, 0, 200, 200, SWP_NOMOVE|SWP_NOACTIVATE ); 5226 ok_sequence(WmSWP_ResizePopupSeq, "SetWindowPos:ResizePopup", FALSE ); 5227 5228 DestroyWindow(hwnd); 5229 ok_sequence(WmDestroyOverlappedSeq, "DestroyWindow:overlapped", FALSE); 5230 5231 /* Test if windows are correctly drawn when first shown */ 5232 5233 /* Visible, redraw */ 5234 flush_events(); 5235 flush_sequence(); 5236 hwnd = CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP | WS_VISIBLE, 5237 10, 10, 100, 100, NULL, 0, 0, NULL ); 5238 ok (hwnd != 0, "Failed to create popup window\n"); 5239 RedrawWindow(hwnd, NULL, NULL, RDW_UPDATENOW); 5240 ok_sequence(WmShowPopupFirstDrawSeq_1, "RedrawWindow:show_popup_first_draw_visible", FALSE); 5241 DestroyWindow(hwnd); 5242 5243 /* Invisible, show, message */ 5244 flush_events(); 5245 flush_sequence(); 5246 hwnd = CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP, 5247 10, 10, 100, 100, NULL, 0, 0, NULL ); 5248 ok (hwnd != 0, "Failed to create popup window\n"); 5249 ShowWindow(hwnd, SW_SHOW); 5250 SendMessageW(hwnd, WM_PAINT, 0, 0); 5251 ok_sequence(WmShowPopupFirstDrawSeq_1, "RedrawWindow:show_popup_first_draw_show", FALSE); 5252 DestroyWindow(hwnd); 5253 5254 /* Invisible, show maximized, redraw */ 5255 flush_events(); 5256 flush_sequence(); 5257 hwnd = CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP, 5258 10, 10, 100, 100, NULL, 0, 0, NULL ); 5259 ok (hwnd != 0, "Failed to create popup window\n"); 5260 ShowWindow(hwnd, SW_SHOWMAXIMIZED); 5261 RedrawWindow(hwnd, NULL, NULL, RDW_UPDATENOW); 5262 ok_sequence(WmShowPopupFirstDrawSeq_2, "RedrawWindow:show_popup_first_draw_show_maximized", FALSE); 5263 DestroyWindow(hwnd); 5264 5265 /* Test SetWindowPos */ 5266 test_msg_setpos(WmFirstDrawSetWindowPosSeq1, SWP_SHOWWINDOW, FALSE); 5267 test_msg_setpos(WmFirstDrawSetWindowPosSeq2, 0, FALSE); 5268 test_msg_setpos(WmFirstDrawSetWindowPosSeq3, 5269 SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE | SWP_NOZORDER, FALSE); 5270 5271 test_msg_setpos(WmFirstDrawSetWindowPosSeq1, SWP_SHOWWINDOW | SWP_NOSIZE, FALSE); 5272 test_msg_setpos(WmFirstDrawSetWindowPosSeq4, SWP_SHOWWINDOW | SWP_NOMOVE, FALSE); 5273 test_msg_setpos(WmFirstDrawSetWindowPosSeq3, SWP_SHOWWINDOW | SWP_NOCLIENTSIZE, FALSE); 5274 test_msg_setpos(WmFirstDrawSetWindowPosSeq3, SWP_SHOWWINDOW | SWP_NOCLIENTMOVE, FALSE); 5275 test_msg_setpos(WmFirstDrawSetWindowPosSeq1, SWP_SHOWWINDOW | SWP_NOZORDER, FALSE); 5276 5277 test_msg_setpos(WmFirstDrawSetWindowPosSeq2, SWP_SHOWWINDOW | SWP_DEFERERASE, FALSE); 5278 test_msg_setpos(WmFirstDrawSetWindowPosSeq3, SWP_SHOWWINDOW | SWP_DEFERERASE | SWP_NOCLIENTMOVE, FALSE); 5279 test_msg_setpos(WmFirstDrawSetWindowPosSeq3, SWP_SHOWWINDOW | SWP_DEFERERASE | SWP_NOCLIENTSIZE, FALSE); 5280 test_msg_setpos(WmFirstDrawSetWindowPosSeq5, SWP_SHOWWINDOW | SWP_DEFERERASE | SWP_NOMOVE, FALSE); 5281 test_msg_setpos(WmFirstDrawSetWindowPosSeq2, SWP_SHOWWINDOW | SWP_DEFERERASE | SWP_NOSIZE, FALSE); 5282 test_msg_setpos(WmFirstDrawSetWindowPosSeq2, SWP_SHOWWINDOW | SWP_DEFERERASE | SWP_NOZORDER, FALSE); 5283 5284 test_msg_setpos(WmFirstDrawSetWindowPosSeq1, SWP_SHOWWINDOW | SWP_NOCOPYBITS, FALSE); 5285 test_msg_setpos(WmFirstDrawSetWindowPosSeq3, SWP_SHOWWINDOW | SWP_NOCOPYBITS | SWP_NOCLIENTMOVE, FALSE); 5286 test_msg_setpos(WmFirstDrawSetWindowPosSeq3, SWP_SHOWWINDOW | SWP_NOCOPYBITS | SWP_NOCLIENTSIZE, FALSE); 5287 test_msg_setpos(WmFirstDrawSetWindowPosSeq4, SWP_SHOWWINDOW | SWP_NOCOPYBITS | SWP_NOMOVE, FALSE); 5288 test_msg_setpos(WmFirstDrawSetWindowPosSeq1, SWP_SHOWWINDOW | SWP_NOCOPYBITS | SWP_NOSIZE, FALSE); 5289 test_msg_setpos(WmFirstDrawSetWindowPosSeq1, SWP_SHOWWINDOW | SWP_NOCOPYBITS | SWP_NOZORDER, FALSE); 5290 5291 test_msg_setpos(WmFirstDrawSetWindowPosSeq2, SWP_SHOWWINDOW | SWP_NOREDRAW, FALSE); 5292 test_msg_setpos(WmFirstDrawSetWindowPosSeq3, SWP_SHOWWINDOW | SWP_NOREDRAW | SWP_NOCLIENTMOVE, FALSE); 5293 test_msg_setpos(WmFirstDrawSetWindowPosSeq3, SWP_SHOWWINDOW | SWP_NOREDRAW | SWP_NOCLIENTSIZE, FALSE); 5294 test_msg_setpos(WmFirstDrawSetWindowPosSeq5, SWP_SHOWWINDOW | SWP_NOREDRAW | SWP_NOMOVE, FALSE); 5295 test_msg_setpos(WmFirstDrawSetWindowPosSeq2, SWP_SHOWWINDOW | SWP_NOREDRAW | SWP_NOSIZE, FALSE); 5296 test_msg_setpos(WmFirstDrawSetWindowPosSeq2, SWP_SHOWWINDOW | SWP_NOREDRAW | SWP_NOZORDER, FALSE); 5297 5298 /* Test SetWindowPos with child windows */ 5299 flush_events(); 5300 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 5301 100, 100, 200, 200, 0, 0, 0, NULL); 5302 ok (hparent != 0, "Failed to create parent window\n"); 5303 5304 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE, 5305 0, 0, 10, 10, hparent, 0, 0, NULL); 5306 ok (hchild != 0, "Failed to create child window\n"); 5307 flush_sequence(); 5308 SetWindowPos(hparent, NULL, 0, 0, 100, 100, SWP_SHOWWINDOW); 5309 ok_sequence(WmFirstDrawChildSeq1, /* Expect no messages for the child */ 5310 "SetWindowPos:show_popup_first_show_window_child1", FALSE); 5311 DestroyWindow(hchild); 5312 DestroyWindow(hparent); 5313 5314 flush_events(); 5315 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN, 5316 100, 100, 200, 200, 0, 0, 0, NULL); 5317 ok (hparent != 0, "Failed to create parent window\n"); 5318 5319 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE, 5320 0, 0, 10, 10, hparent, 0, 0, NULL); 5321 ok (hchild != 0, "Failed to create child window\n"); 5322 flush_sequence(); 5323 SetWindowPos(hparent, NULL, 0, 0, 100, 100, SWP_SHOWWINDOW); 5324 ok_sequence(WmFirstDrawChildSeq2, /* Expect child to be redrawn */ 5325 "SetWindowPos:show_popup_first_show_window_child2", FALSE); 5326 DestroyWindow(hchild); 5327 DestroyWindow(hparent); 5328 5329 /* Test message sequence for extreme position and size */ 5330 5331 flush_sequence(); 5332 hwnd = CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP | WS_VISIBLE, 5333 -10, -10, 10000, 10000, NULL, 0, 0, NULL ); 5334 ok (hwnd != 0, "Failed to create popup window\n"); 5335 ok_sequence(WmShowPopupExtremeLocationSeq, "RedrawWindow:show_popup_extreme_location", FALSE); 5336 DestroyWindow(hwnd); 5337 5338 5339 /* Test child windows */ 5340 5341 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 5342 100, 100, 200, 200, 0, 0, 0, NULL); 5343 ok (hparent != 0, "Failed to create parent window\n"); 5344 flush_sequence(); 5345 5346 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_MAXIMIZE, 5347 0, 0, 10, 10, hparent, 0, 0, NULL); 5348 ok (hchild != 0, "Failed to create child window\n"); 5349 ok_sequence(WmCreateMaximizedChildSeq, "CreateWindow:maximized child", FALSE); 5350 DestroyWindow(hchild); 5351 flush_sequence(); 5352 5353 /* visible child window with a caption */ 5354 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", 5355 WS_CHILD | WS_VISIBLE | WS_CAPTION, 5356 0, 0, 10, 10, hparent, 0, 0, NULL); 5357 ok (hchild != 0, "Failed to create child window\n"); 5358 ok_sequence(WmCreateVisibleChildSeq, "CreateWindow:visible child", FALSE); 5359 5360 trace("testing scroll APIs on a visible child window %p\n", hchild); 5361 test_scroll_messages(hchild); 5362 5363 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE); 5364 ok_sequence(WmShowChildSeq_4, "SetWindowPos(SWP_SHOWWINDOW):child with a caption", FALSE); 5365 5366 DestroyWindow(hchild); 5367 flush_sequence(); 5368 5369 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 5370 0, 0, 10, 10, hparent, 0, 0, NULL); 5371 ok (hchild != 0, "Failed to create child window\n"); 5372 ok_sequence(WmCreateChildSeq, "CreateWindow:child", FALSE); 5373 5374 hchild2 = CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_CHILD, 5375 100, 100, 50, 50, hparent, 0, 0, NULL); 5376 ok (hchild2 != 0, "Failed to create child2 window\n"); 5377 flush_sequence(); 5378 5379 hbutton = CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILD, 5380 0, 100, 50, 50, hchild, 0, 0, NULL); 5381 ok (hbutton != 0, "Failed to create button window\n"); 5382 5383 /* test WM_SETREDRAW on a not visible child window */ 5384 test_WM_SETREDRAW(hchild); 5385 5386 ShowWindow(hchild, SW_SHOW); 5387 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):child", FALSE); 5388 5389 /* check parent messages too */ 5390 log_all_parent_messages++; 5391 ShowWindow(hchild, SW_HIDE); 5392 ok_sequence(WmHideChildSeq2, "ShowWindow(SW_HIDE):child", FALSE); 5393 log_all_parent_messages--; 5394 5395 ShowWindow(hchild, SW_SHOW); 5396 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):child", FALSE); 5397 5398 ShowWindow(hchild, SW_HIDE); 5399 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):child", FALSE); 5400 5401 ShowWindow(hchild, SW_SHOW); 5402 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):child", FALSE); 5403 5404 /* test WM_SETREDRAW on a visible child window */ 5405 test_WM_SETREDRAW(hchild); 5406 5407 log_all_parent_messages++; 5408 MoveWindow(hchild, 10, 10, 20, 20, TRUE); 5409 ok_sequence(WmResizingChildWithMoveWindowSeq, "MoveWindow:child", FALSE); 5410 log_all_parent_messages--; 5411 5412 ShowWindow(hchild, SW_HIDE); 5413 flush_sequence(); 5414 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE); 5415 ok_sequence(WmShowChildSeq_2, "SetWindowPos:show_child_2", FALSE); 5416 5417 ShowWindow(hchild, SW_HIDE); 5418 flush_sequence(); 5419 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE); 5420 ok_sequence(WmShowChildSeq_3, "SetWindowPos:show_child_3", FALSE); 5421 5422 /* DestroyWindow sequence below expects that a child has focus */ 5423 SetFocus(hchild); 5424 flush_sequence(); 5425 5426 DestroyWindow(hchild); 5427 ok_sequence(WmDestroyChildSeq, "DestroyWindow:child", FALSE); 5428 DestroyWindow(hchild2); 5429 DestroyWindow(hbutton); 5430 5431 flush_sequence(); 5432 hchild = CreateWindowExA(0, "TestWindowClass", "Test Child Popup", WS_CHILD | WS_POPUP, 5433 0, 0, 100, 100, hparent, 0, 0, NULL); 5434 ok (hchild != 0, "Failed to create child popup window\n"); 5435 ok_sequence(WmCreateChildPopupSeq, "CreateWindow:child_popup", FALSE); 5436 DestroyWindow(hchild); 5437 5438 /* test what happens to a window which sets WS_VISIBLE in WM_CREATE */ 5439 flush_sequence(); 5440 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP, 5441 0, 0, 100, 100, hparent, 0, 0, NULL); 5442 ok (hchild != 0, "Failed to create popup window\n"); 5443 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup", FALSE); 5444 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 5445 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n"); 5446 flush_sequence(); 5447 ShowWindow(hchild, SW_SHOW); 5448 ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup", FALSE); 5449 flush_sequence(); 5450 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER); 5451 ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2", FALSE); 5452 flush_sequence(); 5453 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE); 5454 ok_sequence(WmShowVisiblePopupSeq_3, "SetWindowPos:show_visible_popup_3", FALSE); 5455 DestroyWindow(hchild); 5456 5457 /* this time add WS_VISIBLE for CreateWindowEx, but this fact actually 5458 * changes nothing in message sequences. 5459 */ 5460 flush_sequence(); 5461 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP | WS_VISIBLE, 5462 0, 0, 100, 100, hparent, 0, 0, NULL); 5463 ok (hchild != 0, "Failed to create popup window\n"); 5464 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup", FALSE); 5465 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 5466 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n"); 5467 flush_sequence(); 5468 ShowWindow(hchild, SW_SHOW); 5469 ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup", FALSE); 5470 flush_sequence(); 5471 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER); 5472 ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2", FALSE); 5473 DestroyWindow(hchild); 5474 5475 flush_sequence(); 5476 hwnd = CreateWindowExA(WS_EX_DLGMODALFRAME, "TestDialogClass", NULL, WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_DLGFRAME, 5477 0, 0, 100, 100, hparent, 0, 0, NULL); 5478 ok(hwnd != 0, "Failed to create custom dialog window\n"); 5479 ok_sequence(WmCreateCustomDialogSeq, "CreateCustomDialog", TRUE); 5480 5481 if(0) { 5482 trace("testing scroll APIs on a visible dialog %p\n", hwnd); 5483 test_scroll_messages(hwnd); 5484 } 5485 5486 flush_sequence(); 5487 5488 test_def_id = TRUE; 5489 SendMessageA(hwnd, WM_NULL, 0, 0); 5490 5491 flush_sequence(); 5492 after_end_dialog = TRUE; 5493 EndDialog( hwnd, 0 ); 5494 ok_sequence(WmEndCustomDialogSeq, "EndCustomDialog", FALSE); 5495 5496 DestroyWindow(hwnd); 5497 after_end_dialog = FALSE; 5498 test_def_id = FALSE; 5499 5500 ok(GetCursorPos(&pos), "GetCursorPos failed\n"); 5501 ok(SetCursorPos(109, 109), "SetCursorPos failed\n"); 5502 5503 hwnd = CreateWindowExA(0, "TestDialogClass", NULL, WS_POPUP|WS_CHILD, 5504 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL); 5505 ok(hwnd != 0, "Failed to create custom dialog window\n"); 5506 flush_sequence(); 5507 trace("call ShowWindow(%p, SW_SHOW)\n", hwnd); 5508 ShowWindow(hwnd, SW_SHOW); 5509 ok_sequence(WmShowCustomDialogSeq, "ShowCustomDialog", TRUE); 5510 5511 flush_events(); 5512 flush_sequence(); 5513 ret = DrawMenuBar(hwnd); 5514 ok(ret, "DrawMenuBar failed: %d\n", GetLastError()); 5515 flush_events(); 5516 ok_sequence(WmDrawMenuBarSeq, "DrawMenuBar", FALSE); 5517 ok(SetCursorPos(pos.x, pos.y), "SetCursorPos failed\n"); 5518 5519 DestroyWindow(hwnd); 5520 5521 hwnd = CreateWindowExA(0, "TestDialogClass", NULL, WS_CHILD|WS_VISIBLE, 5522 0, 0, 100, 100, hparent, 0, GetModuleHandleA(0), NULL); 5523 ok(hwnd != 0, "Failed to create custom dialog window\n"); 5524 flush_events(); 5525 flush_sequence(); 5526 ret = DrawMenuBar(hwnd); 5527 ok(ret, "DrawMenuBar failed: %d\n", GetLastError()); 5528 flush_events(); 5529 ok_sequence(WmEmptySeq, "DrawMenuBar for a child window", FALSE); 5530 5531 DestroyWindow(hwnd); 5532 5533 flush_sequence(); 5534 DialogBoxA( 0, "TEST_DIALOG", hparent, TestModalDlgProcA ); 5535 ok_sequence(WmModalDialogSeq, "ModalDialog", TRUE); 5536 5537 DestroyWindow(hparent); 5538 flush_sequence(); 5539 5540 /* Message sequence for SetMenu */ 5541 ok(!DrawMenuBar(hwnd), "DrawMenuBar should return FALSE for a destroyed window\n"); 5542 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "last error is %d\n", GetLastError()); 5543 ok_sequence(WmEmptySeq, "DrawMenuBar for a window without a menu", FALSE); 5544 5545 hmenu = CreateMenu(); 5546 ok (hmenu != 0, "Failed to create menu\n"); 5547 ok (InsertMenuA(hmenu, -1, MF_BYPOSITION, 0x1000, "foo"), "InsertMenu failed\n"); 5548 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW, 5549 100, 100, 200, 200, 0, hmenu, 0, NULL); 5550 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped", FALSE); 5551 ok (SetMenu(hwnd, 0), "SetMenu\n"); 5552 ok_sequence(WmSetMenuNonVisibleSizeChangeSeq, "SetMenu:NonVisibleSizeChange", FALSE); 5553 ok (SetMenu(hwnd, 0), "SetMenu\n"); 5554 ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq, "SetMenu:NonVisibleNoSizeChange", FALSE); 5555 ShowWindow(hwnd, SW_SHOW); 5556 UpdateWindow( hwnd ); 5557 flush_events(); 5558 flush_sequence(); 5559 ok (SetMenu(hwnd, 0), "SetMenu\n"); 5560 ok_sequence(WmSetMenuVisibleNoSizeChangeSeq, "SetMenu:VisibleNoSizeChange", FALSE); 5561 ok (SetMenu(hwnd, hmenu), "SetMenu\n"); 5562 ok_sequence(WmSetMenuVisibleSizeChangeSeq, "SetMenu:VisibleSizeChange", FALSE); 5563 5564 UpdateWindow( hwnd ); 5565 flush_events(); 5566 flush_sequence(); 5567 ok(DrawMenuBar(hwnd), "DrawMenuBar\n"); 5568 flush_events(); 5569 ok_sequence(WmDrawMenuBarSeq, "DrawMenuBar", FALSE); 5570 5571 DestroyWindow(hwnd); 5572 flush_sequence(); 5573 5574 /* Message sequence for EnableWindow */ 5575 hparent = CreateWindowExA(0, "TestWindowClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 5576 100, 100, 200, 200, 0, 0, 0, NULL); 5577 ok (hparent != 0, "Failed to create parent window\n"); 5578 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE, 5579 0, 0, 10, 10, hparent, 0, 0, NULL); 5580 ok (hchild != 0, "Failed to create child window\n"); 5581 5582 SetFocus(hchild); 5583 flush_events(); 5584 flush_sequence(); 5585 5586 EnableWindow(hparent, FALSE); 5587 ok_sequence(WmEnableWindowSeq_1, "EnableWindow(FALSE)", FALSE); 5588 5589 EnableWindow(hparent, FALSE); 5590 ok_sequence(WmEnableWindowSeq_2, "EnableWindow(FALSE)", FALSE); 5591 5592 EnableWindow(hparent, TRUE); 5593 ok_sequence(WmEnableWindowSeq_3, "EnableWindow(TRUE)", FALSE); 5594 5595 EnableWindow(hparent, TRUE); 5596 ok_sequence(WmEnableWindowSeq_4, "EnableWindow(TRUE)", FALSE); 5597 5598 flush_events(); 5599 flush_sequence(); 5600 5601 test_MsgWaitForMultipleObjects(hparent); 5602 test_WM_DEVICECHANGE(hparent); 5603 5604 /* the following test causes an exception in user.exe under win9x */ 5605 if (!PostMessageW( hparent, WM_USER, 0, 0 )) 5606 { 5607 DestroyWindow(hparent); 5608 flush_sequence(); 5609 return; 5610 } 5611 PostMessageW( hparent, WM_USER+1, 0, 0 ); 5612 /* PeekMessage(NULL) fails, but still removes the message */ 5613 SetLastError(0xdeadbeef); 5614 ok( !PeekMessageW( NULL, 0, 0, 0, PM_REMOVE ), "PeekMessage(NULL) should fail\n" ); 5615 ok( GetLastError() == ERROR_NOACCESS || /* Win2k */ 5616 GetLastError() == 0xdeadbeef, /* NT4 */ 5617 "last error is %d\n", GetLastError() ); 5618 ok( PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n" ); 5619 ok( msg.message == WM_USER+1, "got %x instead of WM_USER+1\n", msg.message ); 5620 5621 DestroyWindow(hchild); 5622 DestroyWindow(hparent); 5623 flush_sequence(); 5624 5625 /* Message sequences for WM_SETICON */ 5626 trace("testing WM_SETICON\n"); 5627 hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, 5628 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0, 5629 NULL, NULL, 0); 5630 ShowWindow(hwnd, SW_SHOW); 5631 UpdateWindow(hwnd); 5632 flush_events(); 5633 flush_sequence(); 5634 SendMessageA(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)LoadIconA(0, (LPCSTR)IDI_APPLICATION)); 5635 ok_sequence(WmSetIcon_1, "WM_SETICON for shown window with caption", FALSE); 5636 5637 ShowWindow(hwnd, SW_HIDE); 5638 flush_events(); 5639 flush_sequence(); 5640 SendMessageA(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)LoadIconA(0, (LPCSTR)IDI_APPLICATION)); 5641 ok_sequence(WmSetIcon_2, "WM_SETICON for hidden window with caption", FALSE); 5642 DestroyWindow(hwnd); 5643 flush_sequence(); 5644 5645 hwnd = CreateWindowExA(0, "TestPopupClass", NULL, WS_POPUP, 5646 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0, 5647 NULL, NULL, 0); 5648 ShowWindow(hwnd, SW_SHOW); 5649 UpdateWindow(hwnd); 5650 flush_events(); 5651 flush_sequence(); 5652 SendMessageA(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)LoadIconA(0, (LPCSTR)IDI_APPLICATION)); 5653 ok_sequence(WmSetIcon_2, "WM_SETICON for shown window without caption", FALSE); 5654 5655 ShowWindow(hwnd, SW_HIDE); 5656 flush_events(); 5657 flush_sequence(); 5658 SendMessageA(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)LoadIconA(0, (LPCSTR)IDI_APPLICATION)); 5659 ok_sequence(WmSetIcon_2, "WM_SETICON for hidden window without caption", FALSE); 5660 5661 flush_sequence(); 5662 res = SendMessageA(hwnd, 0x3B, 0x8000000b, 0); 5663 if (!res) 5664 { 5665 todo_wine win_skip( "Message 0x3b not supported\n" ); 5666 goto done; 5667 } 5668 ok_sequence(WmInitEndSession, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x8000000b", TRUE); 5669 ok(res == 1, "SendMessage(hwnd, 0x3B, 0x8000000b, 0) should have returned 1 instead of %ld\n", res); 5670 res = SendMessageA(hwnd, 0x3B, 0x0000000b, 0); 5671 ok_sequence(WmInitEndSession_2, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x0000000b", TRUE); 5672 ok(res == 1, "SendMessage(hwnd, 0x3B, 0x0000000b, 0) should have returned 1 instead of %ld\n", res); 5673 res = SendMessageA(hwnd, 0x3B, 0x0000000f, 0); 5674 ok_sequence(WmInitEndSession_2, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x0000000f", TRUE); 5675 ok(res == 1, "SendMessage(hwnd, 0x3B, 0x0000000f, 0) should have returned 1 instead of %ld\n", res); 5676 5677 flush_sequence(); 5678 res = SendMessageA(hwnd, 0x3B, 0x80000008, 0); 5679 ok_sequence(WmInitEndSession_3, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000008", TRUE); 5680 ok(res == 2, "SendMessage(hwnd, 0x3B, 0x80000008, 0) should have returned 2 instead of %ld\n", res); 5681 res = SendMessageA(hwnd, 0x3B, 0x00000008, 0); 5682 ok_sequence(WmInitEndSession_4, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x00000008", TRUE); 5683 ok(res == 2, "SendMessage(hwnd, 0x3B, 0x00000008, 0) should have returned 2 instead of %ld\n", res); 5684 5685 res = SendMessageA(hwnd, 0x3B, 0x80000004, 0); 5686 ok_sequence(WmInitEndSession_3, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000004", TRUE); 5687 ok(res == 2, "SendMessage(hwnd, 0x3B, 0x80000004, 0) should have returned 2 instead of %ld\n", res); 5688 5689 res = SendMessageA(hwnd, 0x3B, 0x80000001, 0); 5690 ok_sequence(WmInitEndSession_5, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000001", TRUE); 5691 ok(res == 2, "SendMessage(hwnd, 0x3B, 0x80000001, 0) should have returned 2 instead of %ld\n", res); 5692 5693 done: 5694 DestroyWindow(hwnd); 5695 flush_sequence(); 5696 } 5697 5698 static void test_setwindowpos(void) 5699 { 5700 HWND hwnd; 5701 RECT rc; 5702 LRESULT res; 5703 const INT winX = 100; 5704 const INT winY = 100; 5705 const INT sysX = GetSystemMetrics(SM_CXMINTRACK); 5706 5707 hwnd = CreateWindowExA(0, "TestWindowClass", NULL, 0, 5708 0, 0, winX, winY, 0, 5709 NULL, NULL, 0); 5710 5711 GetWindowRect(hwnd, &rc); 5712 expect(sysX, rc.right); 5713 expect(winY, rc.bottom); 5714 5715 flush_events(); 5716 flush_sequence(); 5717 res = SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, winX, winY, 0); 5718 ok_sequence(WmZOrder, "Z-Order", TRUE); 5719 ok(res == TRUE, "SetWindowPos expected TRUE, got %ld\n", res); 5720 5721 GetWindowRect(hwnd, &rc); 5722 expect(sysX, rc.right); 5723 expect(winY, rc.bottom); 5724 DestroyWindow(hwnd); 5725 } 5726 5727 static void invisible_parent_tests(void) 5728 { 5729 HWND hparent, hchild; 5730 5731 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW, 5732 100, 100, 200, 200, 0, 0, 0, NULL); 5733 ok (hparent != 0, "Failed to create parent window\n"); 5734 flush_sequence(); 5735 5736 /* test showing child with hidden parent */ 5737 5738 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 5739 0, 0, 10, 10, hparent, 0, 0, NULL); 5740 ok (hchild != 0, "Failed to create child window\n"); 5741 ok_sequence(WmCreateChildSeq, "CreateWindow:child", FALSE); 5742 5743 ShowWindow( hchild, SW_MINIMIZE ); 5744 ok_sequence(WmShowChildInvisibleParentSeq_1, "ShowWindow(SW_MINIMIZE) child with invisible parent", FALSE); 5745 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 5746 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n"); 5747 5748 /* repeat */ 5749 flush_events(); 5750 flush_sequence(); 5751 ShowWindow( hchild, SW_MINIMIZE ); 5752 ok_sequence(WmShowChildInvisibleParentSeq_1r, "ShowWindow(SW_MINIMIZE) child with invisible parent", FALSE); 5753 5754 DestroyWindow(hchild); 5755 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 5756 0, 0, 10, 10, hparent, 0, 0, NULL); 5757 flush_sequence(); 5758 5759 ShowWindow( hchild, SW_MAXIMIZE ); 5760 ok_sequence(WmShowChildInvisibleParentSeq_2, "ShowWindow(SW_MAXIMIZE) child with invisible parent", FALSE); 5761 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 5762 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n"); 5763 5764 /* repeat */ 5765 flush_events(); 5766 flush_sequence(); 5767 ShowWindow( hchild, SW_MAXIMIZE ); 5768 ok_sequence(WmShowChildInvisibleParentSeq_2r, "ShowWindow(SW_MAXIMIZE) child with invisible parent", FALSE); 5769 5770 DestroyWindow(hchild); 5771 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 5772 0, 0, 10, 10, hparent, 0, 0, NULL); 5773 flush_sequence(); 5774 5775 ShowWindow( hchild, SW_RESTORE ); 5776 ok_sequence(WmShowChildInvisibleParentSeq_5, "ShowWindow(SW_RESTORE) child with invisible parent", FALSE); 5777 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 5778 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n"); 5779 5780 DestroyWindow(hchild); 5781 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 5782 0, 0, 10, 10, hparent, 0, 0, NULL); 5783 flush_sequence(); 5784 5785 ShowWindow( hchild, SW_SHOWMINIMIZED ); 5786 ok_sequence(WmShowChildInvisibleParentSeq_3, "ShowWindow(SW_SHOWMINIMIZED) child with invisible parent", FALSE); 5787 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 5788 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n"); 5789 5790 /* repeat */ 5791 flush_events(); 5792 flush_sequence(); 5793 ShowWindow( hchild, SW_SHOWMINIMIZED ); 5794 ok_sequence(WmShowChildInvisibleParentSeq_3r, "ShowWindow(SW_SHOWMINIMIZED) child with invisible parent", FALSE); 5795 5796 DestroyWindow(hchild); 5797 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 5798 0, 0, 10, 10, hparent, 0, 0, NULL); 5799 flush_sequence(); 5800 5801 /* same as ShowWindow( hchild, SW_MAXIMIZE ); */ 5802 ShowWindow( hchild, SW_SHOWMAXIMIZED ); 5803 ok_sequence(WmShowChildInvisibleParentSeq_2, "ShowWindow(SW_SHOWMAXIMIZED) child with invisible parent", FALSE); 5804 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 5805 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n"); 5806 5807 DestroyWindow(hchild); 5808 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 5809 0, 0, 10, 10, hparent, 0, 0, NULL); 5810 flush_sequence(); 5811 5812 ShowWindow( hchild, SW_SHOWMINNOACTIVE ); 5813 ok_sequence(WmShowChildInvisibleParentSeq_4, "ShowWindow(SW_SHOWMINNOACTIVE) child with invisible parent", FALSE); 5814 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 5815 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n"); 5816 5817 /* repeat */ 5818 flush_events(); 5819 flush_sequence(); 5820 ShowWindow( hchild, SW_SHOWMINNOACTIVE ); 5821 ok_sequence(WmShowChildInvisibleParentSeq_4r, "ShowWindow(SW_SHOWMINNOACTIVE) child with invisible parent", FALSE); 5822 5823 DestroyWindow(hchild); 5824 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 5825 0, 0, 10, 10, hparent, 0, 0, NULL); 5826 flush_sequence(); 5827 5828 /* FIXME: looks like XP SP2 doesn't know about SW_FORCEMINIMIZE at all */ 5829 ShowWindow( hchild, SW_FORCEMINIMIZE ); 5830 ok_sequence(WmEmptySeq, "ShowWindow(SW_FORCEMINIMIZE) child with invisible parent", TRUE); 5831 todo_wine { 5832 ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should be not set\n"); 5833 } 5834 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n"); 5835 5836 DestroyWindow(hchild); 5837 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 5838 0, 0, 10, 10, hparent, 0, 0, NULL); 5839 flush_sequence(); 5840 5841 ShowWindow( hchild, SW_SHOWNA ); 5842 ok_sequence(WmShowChildInvisibleParentSeq_5, "ShowWindow(SW_SHOWNA) child with invisible parent", FALSE); 5843 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 5844 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n"); 5845 5846 /* repeat */ 5847 flush_events(); 5848 flush_sequence(); 5849 ShowWindow( hchild, SW_SHOWNA ); 5850 ok_sequence(WmShowChildInvisibleParentSeq_5, "ShowWindow(SW_SHOWNA) child with invisible parent", FALSE); 5851 5852 DestroyWindow(hchild); 5853 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 5854 0, 0, 10, 10, hparent, 0, 0, NULL); 5855 flush_sequence(); 5856 5857 ShowWindow( hchild, SW_SHOW ); 5858 ok_sequence(WmShowChildInvisibleParentSeq_5, "ShowWindow(SW_SHOW) child with invisible parent", FALSE); 5859 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 5860 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n"); 5861 5862 /* repeat */ 5863 flush_events(); 5864 flush_sequence(); 5865 ShowWindow( hchild, SW_SHOW ); 5866 ok_sequence(WmEmptySeq, "ShowWindow(SW_SHOW) child with invisible parent", FALSE); 5867 5868 ShowWindow( hchild, SW_HIDE ); 5869 ok_sequence(WmHideChildInvisibleParentSeq, "ShowWindow:hide child with invisible parent", FALSE); 5870 ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should be not set\n"); 5871 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n"); 5872 5873 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER); 5874 ok_sequence(WmShowChildInvisibleParentSeq_6, "SetWindowPos:show child with invisible parent", FALSE); 5875 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 5876 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n"); 5877 5878 SetWindowPos(hchild, 0,0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER); 5879 ok_sequence(WmHideChildInvisibleParentSeq_2, "SetWindowPos:hide child with invisible parent", FALSE); 5880 ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should not be set\n"); 5881 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n"); 5882 5883 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER); 5884 flush_sequence(); 5885 DestroyWindow(hchild); 5886 ok_sequence(WmDestroyInvisibleChildSeq, "DestroyInvisibleChildSeq", FALSE); 5887 5888 DestroyWindow(hparent); 5889 flush_sequence(); 5890 } 5891 5892 /****************** button message test *************************/ 5893 #define ID_BUTTON 0x000e 5894 5895 static const struct message WmSetFocusButtonSeq[] = 5896 { 5897 { HCBT_SETFOCUS, hook }, 5898 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 5899 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 5900 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 5901 { WM_SETFOCUS, sent|wparam, 0 }, 5902 { WM_CTLCOLORBTN, sent|parent }, 5903 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_SETFOCUS) }, 5904 { WM_APP, sent|wparam|lparam, 0, 0 }, 5905 { 0 } 5906 }; 5907 static const struct message WmKillFocusButtonSeq[] = 5908 { 5909 { HCBT_SETFOCUS, hook }, 5910 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 5911 { WM_KILLFOCUS, sent|wparam, 0 }, 5912 { WM_CTLCOLORBTN, sent|parent }, 5913 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_KILLFOCUS) }, 5914 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 5915 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, 5916 { WM_APP, sent|wparam|lparam, 0, 0 }, 5917 { WM_PAINT, sent }, 5918 { WM_CTLCOLORBTN, sent|parent }, 5919 { 0 } 5920 }; 5921 static const struct message WmSetFocusStaticSeq[] = 5922 { 5923 { HCBT_SETFOCUS, hook }, 5924 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 5925 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 5926 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 5927 { WM_SETFOCUS, sent|wparam, 0 }, 5928 { WM_CTLCOLORSTATIC, sent|parent }, 5929 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_SETFOCUS) }, 5930 { WM_COMMAND, sent|wparam|parent|optional, MAKEWPARAM(ID_BUTTON, BN_CLICKED) }, /* radio button */ 5931 { WM_APP, sent|wparam|lparam, 0, 0 }, 5932 { 0 } 5933 }; 5934 static const struct message WmKillFocusStaticSeq[] = 5935 { 5936 { HCBT_SETFOCUS, hook }, 5937 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 5938 { WM_KILLFOCUS, sent|wparam, 0 }, 5939 { WM_CTLCOLORSTATIC, sent|parent }, 5940 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_KILLFOCUS) }, 5941 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 5942 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, 5943 { WM_APP, sent|wparam|lparam, 0, 0 }, 5944 { WM_PAINT, sent }, 5945 { WM_CTLCOLORSTATIC, sent|parent }, 5946 { 0 } 5947 }; 5948 static const struct message WmSetFocusOwnerdrawSeq[] = 5949 { 5950 { HCBT_SETFOCUS, hook }, 5951 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 5952 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 5953 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 5954 { WM_SETFOCUS, sent|wparam, 0 }, 5955 { WM_CTLCOLORBTN, sent|parent }, 5956 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x001040e4 }, 5957 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_SETFOCUS) }, 5958 { WM_APP, sent|wparam|lparam, 0, 0 }, 5959 { 0 } 5960 }; 5961 static const struct message WmKillFocusOwnerdrawSeq[] = 5962 { 5963 { HCBT_SETFOCUS, hook }, 5964 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 5965 { WM_KILLFOCUS, sent|wparam, 0 }, 5966 { WM_CTLCOLORBTN, sent|parent }, 5967 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x000040e4 }, 5968 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_KILLFOCUS) }, 5969 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 5970 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, 5971 { WM_APP, sent|wparam|lparam, 0, 0 }, 5972 { WM_PAINT, sent }, 5973 { WM_CTLCOLORBTN, sent|parent }, 5974 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x000010e4 }, 5975 { 0 } 5976 }; 5977 static const struct message WmLButtonDownSeq[] = 5978 { 5979 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 }, 5980 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, 5981 { HCBT_SETFOCUS, hook }, 5982 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 5983 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 5984 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 5985 { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, 5986 { WM_CTLCOLORBTN, sent|defwinproc }, 5987 { BM_SETSTATE, sent|wparam|defwinproc, TRUE }, 5988 { WM_CTLCOLORBTN, sent|defwinproc }, 5989 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 5990 { 0 } 5991 }; 5992 static const struct message WmLButtonDownStaticSeq[] = 5993 { 5994 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 }, 5995 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, 5996 { HCBT_SETFOCUS, hook }, 5997 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 5998 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 5999 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6000 { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, 6001 { WM_CTLCOLORSTATIC, sent|defwinproc }, 6002 { BM_SETSTATE, sent|wparam|defwinproc, TRUE }, 6003 { WM_CTLCOLORSTATIC, sent|defwinproc }, 6004 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6005 { 0 } 6006 }; 6007 static const struct message WmLButtonUpSeq[] = 6008 { 6009 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 }, 6010 { BM_SETSTATE, sent|wparam|defwinproc, FALSE }, 6011 { WM_CTLCOLORBTN, sent|defwinproc }, 6012 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6013 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, 6014 { WM_CAPTURECHANGED, sent|wparam|defwinproc, 0 }, 6015 { 0 } 6016 }; 6017 static const struct message WmLButtonUpStaticSeq[] = 6018 { 6019 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 }, 6020 { BM_SETSTATE, sent|wparam|defwinproc, FALSE }, 6021 { WM_CTLCOLORSTATIC, sent|defwinproc }, 6022 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6023 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, 6024 { WM_CAPTURECHANGED, sent|wparam|defwinproc, 0 }, 6025 { 0 } 6026 }; 6027 static const struct message WmLButtonUpAutoSeq[] = 6028 { 6029 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 }, 6030 { BM_SETSTATE, sent|wparam|defwinproc, FALSE }, 6031 { WM_CTLCOLORSTATIC, sent|defwinproc }, 6032 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6033 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, 6034 { BM_SETCHECK, sent|defwinproc }, 6035 { WM_CTLCOLORSTATIC, sent|defwinproc, 0, 0 }, 6036 { WM_CAPTURECHANGED, sent|wparam|defwinproc, 0 }, 6037 { 0 } 6038 }; 6039 static const struct message WmLButtonUpBrokenSeq[] = 6040 { 6041 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 }, 6042 { 0 } 6043 }; 6044 static const struct message WmSetFontButtonSeq[] = 6045 { 6046 { WM_SETFONT, sent }, 6047 { WM_PAINT, sent }, 6048 { WM_ERASEBKGND, sent|defwinproc|optional }, 6049 { WM_CTLCOLORBTN, sent|defwinproc }, 6050 { WM_CTLCOLORBTN, sent|defwinproc|optional }, /* FIXME: Wine sends it twice for BS_OWNERDRAW */ 6051 { 0 } 6052 }; 6053 static const struct message WmSetFontStaticSeq[] = 6054 { 6055 { WM_SETFONT, sent }, 6056 { WM_PAINT, sent }, 6057 { WM_ERASEBKGND, sent|defwinproc|optional }, 6058 { WM_CTLCOLORSTATIC, sent|defwinproc }, 6059 { 0 } 6060 }; 6061 static const struct message WmSetTextButtonSeq[] = 6062 { 6063 { WM_SETTEXT, sent }, 6064 { WM_CTLCOLORBTN, sent|parent }, 6065 { WM_CTLCOLORBTN, sent|parent }, 6066 { WM_COMMAND, sent|parent|optional }, 6067 { WM_DRAWITEM, sent|parent|optional }, 6068 { 0 } 6069 }; 6070 static const struct message WmSetTextStaticSeq[] = 6071 { 6072 { WM_SETTEXT, sent }, 6073 { WM_CTLCOLORSTATIC, sent|parent }, 6074 { WM_CTLCOLORSTATIC, sent|parent }, 6075 { 0 } 6076 }; 6077 static const struct message WmSetTextGroupSeq[] = 6078 { 6079 { WM_SETTEXT, sent }, 6080 { WM_CTLCOLORSTATIC, sent|parent }, 6081 { WM_CTLCOLORSTATIC, sent|parent|optional }, /* FIXME: Missing in Wine */ 6082 { WM_CTLCOLORSTATIC, sent|parent|optional }, /* FIXME: Missing in Wine */ 6083 { 0 } 6084 }; 6085 static const struct message WmSetTextInvisibleSeq[] = 6086 { 6087 { WM_SETTEXT, sent }, 6088 { 0 } 6089 }; 6090 static const struct message WmSetStyleButtonSeq[] = 6091 { 6092 { BM_SETSTYLE, sent }, 6093 { WM_APP, sent|wparam|lparam, 0, 0 }, 6094 { WM_PAINT, sent }, 6095 { WM_NCPAINT, sent|defwinproc|optional }, /* FIXME: Wine sends it */ 6096 { WM_ERASEBKGND, sent|defwinproc|optional }, /* Win9x doesn't send it */ 6097 { WM_CTLCOLORBTN, sent|parent }, 6098 { 0 } 6099 }; 6100 static const struct message WmSetStyleStaticSeq[] = 6101 { 6102 { BM_SETSTYLE, sent }, 6103 { WM_APP, sent|wparam|lparam, 0, 0 }, 6104 { WM_PAINT, sent }, 6105 { WM_NCPAINT, sent|defwinproc|optional }, /* FIXME: Wine sends it */ 6106 { WM_ERASEBKGND, sent|defwinproc|optional }, /* Win9x doesn't send it */ 6107 { WM_CTLCOLORSTATIC, sent|parent }, 6108 { 0 } 6109 }; 6110 static const struct message WmSetStyleUserSeq[] = 6111 { 6112 { BM_SETSTYLE, sent }, 6113 { WM_APP, sent|wparam|lparam, 0, 0 }, 6114 { WM_PAINT, sent }, 6115 { WM_NCPAINT, sent|defwinproc|optional }, /* FIXME: Wine sends it */ 6116 { WM_ERASEBKGND, sent|defwinproc|optional }, /* Win9x doesn't send it */ 6117 { WM_CTLCOLORBTN, sent|parent }, 6118 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_PAINT) }, 6119 { 0 } 6120 }; 6121 static const struct message WmSetStyleOwnerdrawSeq[] = 6122 { 6123 { BM_SETSTYLE, sent }, 6124 { WM_APP, sent|wparam|lparam, 0, 0 }, 6125 { WM_PAINT, sent }, 6126 { WM_NCPAINT, sent|optional }, /* FIXME: Wine sends it */ 6127 { WM_ERASEBKGND, sent|defwinproc|optional }, /* Win9x doesn't send it */ 6128 { WM_CTLCOLORBTN, sent|parent }, 6129 { WM_CTLCOLORBTN, sent|parent|optional }, /* Win9x doesn't send it */ 6130 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x000010e4 }, 6131 { 0 } 6132 }; 6133 static const struct message WmSetStateButtonSeq[] = 6134 { 6135 { BM_SETSTATE, sent }, 6136 { WM_CTLCOLORBTN, sent|parent }, 6137 { WM_APP, sent|wparam|lparam, 0, 0 }, 6138 { 0 } 6139 }; 6140 static const struct message WmSetStateStaticSeq[] = 6141 { 6142 { BM_SETSTATE, sent }, 6143 { WM_CTLCOLORSTATIC, sent|parent }, 6144 { WM_APP, sent|wparam|lparam, 0, 0 }, 6145 { 0 } 6146 }; 6147 static const struct message WmSetStateUserSeq[] = 6148 { 6149 { BM_SETSTATE, sent }, 6150 { WM_CTLCOLORBTN, sent|parent }, 6151 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_HILITE) }, 6152 { WM_APP, sent|wparam|lparam, 0, 0 }, 6153 { 0 } 6154 }; 6155 static const struct message WmSetStateOwnerdrawSeq[] = 6156 { 6157 { BM_SETSTATE, sent }, 6158 { WM_CTLCOLORBTN, sent|parent }, 6159 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x000120e4 }, 6160 { WM_APP, sent|wparam|lparam, 0, 0 }, 6161 { 0 } 6162 }; 6163 static const struct message WmClearStateButtonSeq[] = 6164 { 6165 { BM_SETSTATE, sent }, 6166 { WM_CTLCOLORBTN, sent|parent }, 6167 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_UNHILITE) }, 6168 { WM_APP, sent|wparam|lparam, 0, 0 }, 6169 { 0 } 6170 }; 6171 static const struct message WmDisableButtonSeq[] = 6172 { 6173 { WM_LBUTTONDOWN, sent }, 6174 { BM_SETSTATE, sent|defwinproc }, 6175 { WM_CTLCOLORSTATIC, sent|defwinproc|optional }, 6176 { WM_CTLCOLORBTN, sent|optional }, 6177 { WM_LBUTTONUP, sent }, 6178 { BM_SETSTATE, sent|defwinproc }, 6179 { WM_CTLCOLORBTN, sent|defwinproc|optional }, 6180 { WM_CTLCOLORSTATIC, sent|defwinproc|optional }, 6181 { BM_SETCHECK, sent|defwinproc|optional }, 6182 { WM_CTLCOLORBTN, sent|optional }, 6183 { WM_CTLCOLORSTATIC, sent|defwinproc|optional }, 6184 { WM_CAPTURECHANGED, sent|defwinproc }, 6185 { WM_COMMAND, sent }, 6186 { 0 } 6187 }; 6188 static const struct message WmClearStateOwnerdrawSeq[] = 6189 { 6190 { BM_SETSTATE, sent }, 6191 { WM_CTLCOLORBTN, sent|parent }, 6192 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x000020e4 }, 6193 { WM_APP, sent|wparam|lparam, 0, 0 }, 6194 { 0 } 6195 }; 6196 static const struct message WmSetCheckIgnoredSeq[] = 6197 { 6198 { BM_SETCHECK, sent }, 6199 { WM_APP, sent|wparam|lparam, 0, 0 }, 6200 { 0 } 6201 }; 6202 static const struct message WmSetCheckStaticSeq[] = 6203 { 6204 { BM_SETCHECK, sent }, 6205 { WM_CTLCOLORSTATIC, sent|parent }, 6206 { WM_APP, sent|wparam|lparam, 0, 0 }, 6207 { 0 } 6208 }; 6209 6210 static WNDPROC old_button_proc; 6211 6212 static LRESULT CALLBACK button_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 6213 { 6214 static LONG defwndproc_counter = 0; 6215 LRESULT ret; 6216 struct recvd_message msg; 6217 6218 if (ignore_message( message )) return 0; 6219 6220 switch (message) 6221 { 6222 case WM_SYNCPAINT: 6223 break; 6224 case BM_SETSTATE: 6225 if (GetCapture()) 6226 ok(GetCapture() == hwnd, "GetCapture() = %p\n", GetCapture()); 6227 6228 lParam = (ULONG_PTR)GetMenu(hwnd); 6229 goto log_it; 6230 6231 case WM_GETDLGCODE: 6232 if (lParam) 6233 { 6234 MSG *msg = (MSG *)lParam; 6235 lParam = MAKELPARAM(msg->message, msg->wParam); 6236 } 6237 wParam = (ULONG_PTR)GetMenu(hwnd); 6238 goto log_it; 6239 6240 case BM_SETCHECK: 6241 case BM_GETCHECK: 6242 lParam = (ULONG_PTR)GetMenu(hwnd); 6243 /* fall through */ 6244 log_it: 6245 default: 6246 msg.hwnd = hwnd; 6247 msg.message = message; 6248 msg.flags = sent|wparam|lparam; 6249 if (defwndproc_counter) msg.flags |= defwinproc; 6250 msg.wParam = wParam; 6251 msg.lParam = lParam; 6252 msg.descr = "button"; 6253 add_message(&msg); 6254 } 6255 6256 defwndproc_counter++; 6257 ret = CallWindowProcA(old_button_proc, hwnd, message, wParam, lParam); 6258 defwndproc_counter--; 6259 6260 return ret; 6261 } 6262 6263 static void subclass_button(void) 6264 { 6265 WNDCLASSA cls; 6266 6267 if (!GetClassInfoA(0, "button", &cls)) assert(0); 6268 6269 old_button_proc = cls.lpfnWndProc; 6270 6271 cls.hInstance = GetModuleHandleA(NULL); 6272 cls.lpfnWndProc = button_hook_proc; 6273 cls.lpszClassName = "my_button_class"; 6274 UnregisterClassA(cls.lpszClassName, cls.hInstance); 6275 if (!RegisterClassA(&cls)) assert(0); 6276 } 6277 6278 static void test_button_messages(void) 6279 { 6280 static const struct 6281 { 6282 DWORD style; 6283 DWORD dlg_code; 6284 const struct message *setfocus; 6285 const struct message *killfocus; 6286 const struct message *setstyle; 6287 const struct message *setstate; 6288 const struct message *clearstate; 6289 const struct message *setcheck; 6290 const struct message *lbuttondown; 6291 const struct message *lbuttonup; 6292 const struct message *setfont; 6293 const struct message *settext; 6294 } button[] = { 6295 { BS_PUSHBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON, 6296 WmSetFocusButtonSeq, WmKillFocusButtonSeq, WmSetStyleButtonSeq, 6297 WmSetStateButtonSeq, WmSetStateButtonSeq, WmSetCheckIgnoredSeq, 6298 WmLButtonDownSeq, WmLButtonUpSeq, WmSetFontButtonSeq, 6299 WmSetTextButtonSeq }, 6300 { BS_DEFPUSHBUTTON, DLGC_BUTTON | DLGC_DEFPUSHBUTTON, 6301 WmSetFocusButtonSeq, WmKillFocusButtonSeq, WmSetStyleButtonSeq, 6302 WmSetStateButtonSeq, WmSetStateButtonSeq, WmSetCheckIgnoredSeq, 6303 WmLButtonDownSeq, WmLButtonUpSeq, WmSetFontButtonSeq, 6304 WmSetTextButtonSeq }, 6305 { BS_CHECKBOX, DLGC_BUTTON, 6306 WmSetFocusStaticSeq, WmKillFocusStaticSeq, WmSetStyleStaticSeq, 6307 WmSetStateStaticSeq, WmSetStateStaticSeq, WmSetCheckStaticSeq, 6308 WmLButtonDownStaticSeq, WmLButtonUpStaticSeq, WmSetFontStaticSeq, 6309 WmSetTextStaticSeq }, 6310 { BS_AUTOCHECKBOX, DLGC_BUTTON, 6311 WmSetFocusStaticSeq, WmKillFocusStaticSeq, WmSetStyleStaticSeq, 6312 WmSetStateStaticSeq, WmSetStateStaticSeq, WmSetCheckStaticSeq, 6313 WmLButtonDownStaticSeq, WmLButtonUpAutoSeq, WmSetFontStaticSeq, 6314 WmSetTextStaticSeq }, 6315 { BS_RADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON, 6316 WmSetFocusStaticSeq, WmKillFocusStaticSeq, WmSetStyleStaticSeq, 6317 WmSetStateStaticSeq, WmSetStateStaticSeq, WmSetCheckStaticSeq, 6318 WmLButtonDownStaticSeq, WmLButtonUpStaticSeq, WmSetFontStaticSeq, 6319 WmSetTextStaticSeq }, 6320 { BS_3STATE, DLGC_BUTTON, 6321 WmSetFocusStaticSeq, WmKillFocusStaticSeq, WmSetStyleStaticSeq, 6322 WmSetStateStaticSeq, WmSetStateStaticSeq, WmSetCheckStaticSeq, 6323 WmLButtonDownStaticSeq, WmLButtonUpStaticSeq, WmSetFontStaticSeq, 6324 WmSetTextStaticSeq }, 6325 { BS_AUTO3STATE, DLGC_BUTTON, 6326 WmSetFocusStaticSeq, WmKillFocusStaticSeq, WmSetStyleStaticSeq, 6327 WmSetStateStaticSeq, WmSetStateStaticSeq, WmSetCheckStaticSeq, 6328 WmLButtonDownStaticSeq, WmLButtonUpAutoSeq, WmSetFontStaticSeq, 6329 WmSetTextStaticSeq }, 6330 { BS_GROUPBOX, DLGC_STATIC, 6331 WmSetFocusStaticSeq, WmKillFocusStaticSeq, WmSetStyleStaticSeq, 6332 WmSetStateStaticSeq, WmSetStateStaticSeq, WmSetCheckIgnoredSeq, 6333 WmLButtonDownStaticSeq, WmLButtonUpStaticSeq, WmSetFontStaticSeq, 6334 WmSetTextGroupSeq }, 6335 { BS_USERBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON, 6336 WmSetFocusButtonSeq, WmKillFocusButtonSeq, WmSetStyleUserSeq, 6337 WmSetStateUserSeq, WmClearStateButtonSeq, WmSetCheckIgnoredSeq, 6338 WmLButtonDownSeq, WmLButtonUpSeq, WmSetFontButtonSeq, 6339 WmSetTextButtonSeq }, 6340 { BS_AUTORADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON, 6341 WmSetFocusStaticSeq, WmKillFocusStaticSeq, WmSetStyleStaticSeq, 6342 WmSetStateStaticSeq, WmSetStateStaticSeq, WmSetCheckStaticSeq, 6343 NULL /* avoid infinite loop */, WmLButtonUpBrokenSeq, WmSetFontStaticSeq, 6344 WmSetTextStaticSeq }, 6345 { BS_OWNERDRAW, DLGC_BUTTON, 6346 WmSetFocusOwnerdrawSeq, WmKillFocusOwnerdrawSeq, WmSetStyleOwnerdrawSeq, 6347 WmSetStateOwnerdrawSeq, WmClearStateOwnerdrawSeq, WmSetCheckIgnoredSeq, 6348 WmLButtonDownSeq, WmLButtonUpSeq, WmSetFontButtonSeq, 6349 WmSetTextButtonSeq }, 6350 }; 6351 LOGFONTA logfont = { 0 }; 6352 HFONT zfont, hfont2; 6353 unsigned int i; 6354 HWND hwnd, parent; 6355 DWORD dlg_code; 6356 6357 /* selection with VK_SPACE should capture button window */ 6358 hwnd = CreateWindowExA(0, "button", "test", BS_CHECKBOX | WS_VISIBLE | WS_POPUP, 6359 0, 0, 50, 14, 0, 0, 0, NULL); 6360 ok(hwnd != 0, "Failed to create button window\n"); 6361 ReleaseCapture(); 6362 SetFocus(hwnd); 6363 SendMessageA(hwnd, WM_KEYDOWN, VK_SPACE, 0); 6364 ok(GetCapture() == hwnd, "Should be captured on VK_SPACE WM_KEYDOWN\n"); 6365 SendMessageA(hwnd, WM_KEYUP, VK_SPACE, 0); 6366 DestroyWindow(hwnd); 6367 6368 subclass_button(); 6369 6370 parent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 6371 100, 100, 200, 200, 0, 0, 0, NULL); 6372 ok(parent != 0, "Failed to create parent window\n"); 6373 6374 memset(&logfont, 0, sizeof(logfont)); 6375 logfont.lfHeight = -12; 6376 logfont.lfWeight = FW_NORMAL; 6377 strcpy(logfont.lfFaceName, "Tahoma"); 6378 6379 hfont2 = CreateFontIndirectA(&logfont); 6380 ok(hfont2 != NULL, "Failed to create Tahoma font\n"); 6381 6382 for (i = 0; i < ARRAY_SIZE(button); i++) 6383 { 6384 MSG msg; 6385 DWORD style, state; 6386 HFONT prevfont; 6387 char desc[64]; 6388 HDC hdc; 6389 6390 trace("button style %08x\n", button[i].style); 6391 6392 hwnd = CreateWindowExA(0, "my_button_class", "test", button[i].style | WS_CHILD | BS_NOTIFY, 6393 0, 0, 50, 14, parent, (HMENU)ID_BUTTON, 0, NULL); 6394 ok(hwnd != 0, "Failed to create button window\n"); 6395 6396 style = GetWindowLongA(hwnd, GWL_STYLE); 6397 style &= ~(WS_CHILD | BS_NOTIFY); 6398 /* XP turns a BS_USERBUTTON into BS_PUSHBUTTON */ 6399 if (button[i].style == BS_USERBUTTON) 6400 ok(style == BS_PUSHBUTTON, "expected style BS_PUSHBUTTON got %x\n", style); 6401 else 6402 ok(style == button[i].style, "expected style %x got %x\n", button[i].style, style); 6403 6404 dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0); 6405 ok(dlg_code == button[i].dlg_code, "%u: wrong dlg_code %08x\n", i, dlg_code); 6406 6407 ShowWindow(hwnd, SW_SHOW); 6408 UpdateWindow(hwnd); 6409 SetFocus(0); 6410 flush_events(); 6411 SetFocus(0); 6412 flush_sequence(); 6413 6414 log_all_parent_messages++; 6415 6416 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus()); 6417 SetFocus(hwnd); 6418 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ 6419 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 6420 ok_sequence(button[i].setfocus, "SetFocus(hwnd) on a button", FALSE); 6421 6422 SetFocus(0); 6423 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ 6424 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 6425 ok_sequence(button[i].killfocus, "SetFocus(0) on a button", FALSE); 6426 6427 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus()); 6428 6429 SendMessageA(hwnd, BM_SETSTYLE, button[i].style | BS_BOTTOM, TRUE); 6430 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ 6431 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 6432 ok_sequence(button[i].setstyle, "BM_SETSTYLE on a button", FALSE); 6433 6434 style = GetWindowLongA(hwnd, GWL_STYLE); 6435 style &= ~(WS_VISIBLE | WS_CHILD | BS_NOTIFY); 6436 /* XP doesn't turn a BS_USERBUTTON into BS_PUSHBUTTON here! */ 6437 ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style); 6438 6439 state = SendMessageA(hwnd, BM_GETSTATE, 0, 0); 6440 ok(state == 0, "expected state 0, got %04x\n", state); 6441 6442 flush_sequence(); 6443 6444 SendMessageA(hwnd, BM_SETSTATE, TRUE, 0); 6445 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ 6446 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 6447 ok_sequence(button[i].setstate, "BM_SETSTATE/TRUE on a button", FALSE); 6448 6449 state = SendMessageA(hwnd, BM_GETSTATE, 0, 0); 6450 ok(state == 0x0004, "expected state 0x0004, got %04x\n", state); 6451 6452 style = GetWindowLongA(hwnd, GWL_STYLE); 6453 style &= ~(WS_CHILD | BS_NOTIFY | WS_VISIBLE); 6454 ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style); 6455 6456 flush_sequence(); 6457 6458 SendMessageA(hwnd, BM_SETSTATE, FALSE, 0); 6459 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ 6460 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 6461 ok_sequence(button[i].clearstate, "BM_SETSTATE/FALSE on a button", FALSE); 6462 6463 state = SendMessageA(hwnd, BM_GETSTATE, 0, 0); 6464 ok(state == 0, "expected state 0, got %04x\n", state); 6465 6466 style = GetWindowLongA(hwnd, GWL_STYLE); 6467 style &= ~(WS_CHILD | BS_NOTIFY | WS_VISIBLE); 6468 ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style); 6469 6470 state = SendMessageA(hwnd, BM_GETCHECK, 0, 0); 6471 ok(state == BST_UNCHECKED, "expected BST_UNCHECKED, got %04x\n", state); 6472 6473 flush_sequence(); 6474 6475 SendMessageA(hwnd, BM_SETCHECK, BST_UNCHECKED, 0); 6476 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ 6477 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 6478 ok_sequence(WmSetCheckIgnoredSeq, "BM_SETCHECK on a button", FALSE); 6479 6480 state = SendMessageA(hwnd, BM_GETCHECK, 0, 0); 6481 ok(state == BST_UNCHECKED, "expected BST_UNCHECKED, got %04x\n", state); 6482 6483 style = GetWindowLongA(hwnd, GWL_STYLE); 6484 style &= ~(WS_CHILD | BS_NOTIFY | WS_VISIBLE); 6485 ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style); 6486 6487 flush_sequence(); 6488 6489 SendMessageA(hwnd, BM_SETCHECK, BST_CHECKED, 0); 6490 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ 6491 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 6492 ok_sequence(button[i].setcheck, "BM_SETCHECK on a button", FALSE); 6493 6494 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"Text 1"); 6495 sprintf(desc, "button[%i]: WM_SETTEXT on a visible button", i); 6496 ok_sequence(button[i].settext, desc, FALSE); 6497 6498 ShowWindow(hwnd, SW_HIDE); 6499 flush_events(); 6500 flush_sequence(); 6501 6502 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"Text 2"); 6503 sprintf(desc, "button[%i]: WM_SETTEXT on an invisible button", i); 6504 ok_sequence(WmSetTextInvisibleSeq, desc, FALSE); 6505 6506 ShowWindow(hwnd, SW_SHOW); 6507 ShowWindow(parent, SW_HIDE); 6508 flush_events(); 6509 flush_sequence(); 6510 6511 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"Text 3"); 6512 sprintf(desc, "button[%i]: WM_SETTEXT on an invisible button", i); 6513 ok_sequence(WmSetTextInvisibleSeq, desc, FALSE); 6514 6515 ShowWindow(parent, SW_SHOW); 6516 flush_events(); 6517 6518 state = SendMessageA(hwnd, BM_GETCHECK, 0, 0); 6519 if (button[i].style == BS_PUSHBUTTON || 6520 button[i].style == BS_DEFPUSHBUTTON || 6521 button[i].style == BS_GROUPBOX || 6522 button[i].style == BS_USERBUTTON || 6523 button[i].style == BS_OWNERDRAW) 6524 ok(state == BST_UNCHECKED, "expected check 0, got %04x\n", state); 6525 else 6526 ok(state == BST_CHECKED, "expected check 1, got %04x\n", state); 6527 6528 style = GetWindowLongA(hwnd, GWL_STYLE); 6529 style &= ~(WS_CHILD | BS_NOTIFY | WS_VISIBLE); 6530 if (button[i].style == BS_RADIOBUTTON || 6531 button[i].style == BS_AUTORADIOBUTTON) 6532 ok(style == (button[i].style | WS_TABSTOP), "expected style %04x | WS_TABSTOP got %04x\n", button[i].style, style); 6533 else 6534 ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style); 6535 6536 log_all_parent_messages--; 6537 6538 DestroyWindow(hwnd); 6539 6540 hwnd = CreateWindowExA(0, "my_button_class", "test", button[i].style | WS_POPUP | WS_VISIBLE, 6541 0, 0, 50, 14, 0, 0, 0, NULL); 6542 ok(hwnd != 0, "Failed to create button window\n"); 6543 6544 SetForegroundWindow(hwnd); 6545 flush_events(); 6546 6547 SetActiveWindow(hwnd); 6548 SetFocus(0); 6549 flush_sequence(); 6550 6551 if (button[i].lbuttondown) 6552 { 6553 SendMessageA(hwnd, WM_LBUTTONDOWN, 0, 0); 6554 sprintf(desc, "button[%i]: WM_LBUTTONDOWN on a button", i); 6555 ok_sequence(button[i].lbuttondown, desc, FALSE); 6556 } 6557 6558 SendMessageA(hwnd, WM_LBUTTONUP, 0, 0); 6559 sprintf(desc, "button[%i]: WM_LBUTTONUP on a button", i); 6560 ok_sequence(button[i].lbuttonup, desc, FALSE); 6561 6562 flush_sequence(); 6563 zfont = GetStockObject(DEFAULT_GUI_FONT); 6564 SendMessageA(hwnd, WM_SETFONT, (WPARAM)zfont, TRUE); 6565 UpdateWindow(hwnd); 6566 sprintf(desc, "button[%i]: WM_SETFONT on a button", i); 6567 ok_sequence(button[i].setfont, desc, FALSE); 6568 6569 /* Test that original font is not selected back after painting */ 6570 hdc = CreateCompatibleDC(0); 6571 6572 prevfont = SelectObject(hdc, hfont2); 6573 ok(prevfont == GetStockObject(SYSTEM_FONT), "Unexpected default font\n"); 6574 SendMessageA(hwnd, WM_PRINTCLIENT, (WPARAM)hdc, 0); 6575 ok(hfont2 != GetCurrentObject(hdc, OBJ_FONT), "button[%u]: unexpected font selected after WM_PRINTCLIENT\n", i); 6576 SelectObject(hdc, prevfont); 6577 6578 prevfont = SelectObject(hdc, hfont2); 6579 ok(prevfont == GetStockObject(SYSTEM_FONT), "Unexpected default font\n"); 6580 SendMessageA(hwnd, WM_PAINT, (WPARAM)hdc, 0); 6581 ok(hfont2 != GetCurrentObject(hdc, OBJ_FONT), "button[%u]: unexpected font selected after WM_PAINT\n", i); 6582 SelectObject(hdc, prevfont); 6583 6584 DeleteDC(hdc); 6585 6586 DestroyWindow(hwnd); 6587 } 6588 6589 DeleteObject(hfont2); 6590 DestroyWindow(parent); 6591 6592 /* Test if WM_LBUTTONDOWN and WM_LBUTTONUP to a disabled button leads to a WM_COMMAND for the parent */ 6593 6594 parent = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 6595 100, 100, 200, 200, 0, 0, 0, NULL); 6596 ok (hwnd != 0, "Failed to create overlapped window\n"); 6597 6598 hwnd = CreateWindowExA(0, "my_button_class", "test", BS_DEFPUSHBUTTON | WS_VISIBLE | WS_CHILD, 6599 0, 0, 50, 14, parent, 0, 0, NULL); 6600 6601 EnableWindow(hwnd, FALSE); 6602 flush_sequence(); 6603 SendMessageA(hwnd, WM_LBUTTONDOWN, MK_LBUTTON, 0); 6604 SendMessageA(hwnd, WM_LBUTTONUP, 0, 0); 6605 ok_sequence(WmDisableButtonSeq, "Mouseclick on a disabled button", FALSE); 6606 6607 DestroyWindow(hwnd); 6608 DestroyWindow(parent); 6609 } 6610 6611 static void test_button_bm_get_set_image(void) 6612 { 6613 HWND hwnd; 6614 HDC hdc; 6615 HBITMAP hbmp1x1; 6616 HBITMAP hbmp2x2; 6617 HBITMAP hmask2x2; 6618 ICONINFO icon_info2x2; 6619 HICON hicon2x2; 6620 HBITMAP hbmp; 6621 HICON hicon; 6622 ICONINFO icon_info; 6623 BITMAP bm; 6624 DWORD default_style = BS_PUSHBUTTON | WS_TABSTOP | WS_POPUP | WS_VISIBLE; 6625 LRESULT ret; 6626 6627 hdc = GetDC(0); 6628 hbmp1x1 = CreateCompatibleBitmap(hdc, 1, 1); 6629 hbmp2x2 = CreateCompatibleBitmap(hdc, 2, 2); 6630 ZeroMemory(&bm, sizeof(bm)); 6631 ok(GetObjectW(hbmp1x1, sizeof(bm), &bm), "Expect GetObjectW() success\n"); 6632 ok(bm.bmWidth == 1 && bm.bmHeight == 1, "Expect bitmap size: %d,%d, got: %d,%d\n", 1, 1, 6633 bm.bmWidth, bm.bmHeight); 6634 ZeroMemory(&bm, sizeof(bm)); 6635 ok(GetObjectW(hbmp2x2, sizeof(bm), &bm), "Expect GetObjectW() success\n"); 6636 ok(bm.bmWidth == 2 && bm.bmHeight == 2, "Expect bitmap size: %d,%d, got: %d,%d\n", 2, 2, 6637 bm.bmWidth, bm.bmHeight); 6638 6639 hmask2x2 = CreateCompatibleBitmap(hdc, 2, 2); 6640 ZeroMemory(&icon_info2x2, sizeof(icon_info2x2)); 6641 icon_info2x2.fIcon = TRUE; 6642 icon_info2x2.hbmMask = hmask2x2; 6643 icon_info2x2.hbmColor = hbmp2x2; 6644 hicon2x2 = CreateIconIndirect(&icon_info2x2); 6645 6646 ZeroMemory(&icon_info, sizeof(icon_info)); 6647 ok(GetIconInfo(hicon2x2, &icon_info), "Expect GetIconInfo() success\n"); 6648 ZeroMemory(&bm, sizeof(bm)); 6649 ok(GetObjectW(icon_info.hbmColor, sizeof(bm), &bm), "Expect GetObjectW() success\n"); 6650 ok(bm.bmWidth == 2 && bm.bmHeight == 2, "Expect bitmap size: %d,%d, got: %d,%d\n", 2, 2, 6651 bm.bmWidth, bm.bmHeight); 6652 DeleteObject(icon_info.hbmColor); 6653 DeleteObject(icon_info.hbmMask); 6654 6655 /* Set bitmap with BS_BITMAP */ 6656 hwnd = CreateWindowA("Button", "test", default_style | BS_BITMAP, 0, 0, 100, 100, 0, 0, 0, 0); 6657 ok(hwnd != NULL, "Expect hwnd not NULL\n"); 6658 SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hbmp1x1); 6659 hbmp = (HBITMAP)SendMessageA(hwnd, BM_GETIMAGE, (WPARAM)IMAGE_BITMAP, 0); 6660 ok(hbmp != 0, "Expect hbmp not 0\n"); 6661 ZeroMemory(&bm, sizeof(bm)); 6662 ok(GetObjectW(hbmp, sizeof(bm), &bm), "Expect GetObjectW() success\n"); 6663 ok(bm.bmWidth == 1 && bm.bmHeight == 1, "Expect bitmap size: %d,%d, got: %d,%d\n", 1, 1, 6664 bm.bmWidth, bm.bmHeight); 6665 DestroyWindow(hwnd); 6666 6667 /* Set bitmap without BS_BITMAP */ 6668 hwnd = CreateWindowA("Button", "test", default_style, 0, 0, 100, 100, 0, 0, 0, 0); 6669 ok(hwnd != NULL, "Expect hwnd not NULL\n"); 6670 ret = SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hbmp1x1); 6671 ok(ret == 0, "Expect ret to be 0\n"); 6672 hbmp = (HBITMAP)SendMessageA(hwnd, BM_GETIMAGE, (WPARAM)IMAGE_BITMAP, 0); 6673 ok(hbmp == NULL, "Expect hbmp to be NULL\n"); 6674 DestroyWindow(hwnd); 6675 6676 /* Set icon with BS_ICON */ 6677 hwnd = CreateWindowA("Button", "test", default_style | BS_ICON, 0, 0, 100, 100, 0, 0, 0, 0); 6678 ok(hwnd != NULL, "Expect hwnd not NULL\n"); 6679 SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hicon2x2); 6680 hicon = (HICON)SendMessageA(hwnd, BM_GETIMAGE, (WPARAM)IMAGE_ICON, 0); 6681 ok(hicon != NULL, "Expect hicon not NULL\n"); 6682 ZeroMemory(&icon_info, sizeof(icon_info)); 6683 ok(GetIconInfo(hicon, &icon_info), "Expect GetIconInfo() success\n"); 6684 ZeroMemory(&bm, sizeof(bm)); 6685 ok(GetObjectW(icon_info.hbmColor, sizeof(bm), &bm), "Expect GetObjectW() success\n"); 6686 ok(bm.bmWidth == 2 && bm.bmHeight == 2, "Expect bitmap size: %d,%d, got: %d,%d\n", 2, 2, 6687 bm.bmWidth, bm.bmHeight); 6688 DeleteObject(icon_info.hbmColor); 6689 DeleteObject(icon_info.hbmMask); 6690 DestroyWindow(hwnd); 6691 6692 /* Set icon without BS_ICON */ 6693 hwnd = CreateWindowA("Button", "test", default_style, 0, 0, 100, 100, 0, 0, 0, 0); 6694 ok(hwnd != NULL, "Expect hwnd not NULL\n"); 6695 ret = SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hicon2x2); 6696 ok(ret == 0, "Expect ret to be 0\n"); 6697 hicon = (HICON)SendMessageA(hwnd, BM_GETIMAGE, (WPARAM)IMAGE_ICON, 0); 6698 ok(hicon == NULL, "Expect hicon to be NULL\n"); 6699 DestroyWindow(hwnd); 6700 6701 /* Set icon with BS_BITMAP */ 6702 hwnd = CreateWindowA("Button", "test", default_style | BS_BITMAP, 0, 0, 100, 100, 0, 0, 0, 0); 6703 ok(hwnd != NULL, "Expect hwnd to be not NULL\n"); 6704 ret = SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hicon2x2); 6705 ok(ret == 0, "Expect ret to be 0\n"); 6706 hicon = (HICON)SendMessageA(hwnd, BM_GETIMAGE, (WPARAM)IMAGE_ICON, 0); 6707 ok(hicon == NULL, "Expect hicon to be NULL\n"); 6708 DestroyWindow(hwnd); 6709 6710 /* Set bitmap with BS_ICON */ 6711 hwnd = CreateWindowA("Button", "test", default_style | BS_ICON, 0, 0, 100, 100, 0, 0, 0, 0); 6712 ok(hwnd != NULL, "Expect hwnd to be not NULL\n"); 6713 ret = SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hbmp1x1); 6714 ok(ret == 0, "Expect ret to be 0\n"); 6715 hbmp = (HBITMAP)SendMessageA(hwnd, BM_GETIMAGE, (WPARAM)IMAGE_BITMAP, 0); 6716 ok(hbmp == NULL, "Expect hbmp to be NULL\n"); 6717 DestroyWindow(hwnd); 6718 6719 DestroyIcon(hicon2x2); 6720 DeleteObject(hmask2x2); 6721 DeleteObject(hbmp2x2); 6722 DeleteObject(hbmp1x1); 6723 ReleaseDC(0, hdc); 6724 } 6725 6726 #define ID_RADIO1 501 6727 #define ID_RADIO2 502 6728 #define ID_RADIO3 503 6729 #define ID_TEXT 504 6730 6731 static const struct message auto_radio_button_BM_CLICK[] = 6732 { 6733 { BM_CLICK, sent|wparam|lparam, 0, 0 }, 6734 { WM_LBUTTONDOWN, sent|wparam|lparam|defwinproc, 0, 0 }, 6735 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, 6736 { BM_SETSTATE, sent|wparam|lparam|defwinproc, BST_CHECKED, ID_RADIO2 }, 6737 { WM_CTLCOLORSTATIC, sent|parent }, 6738 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6739 { WM_LBUTTONUP, sent|wparam|lparam|defwinproc, 0, 0 }, 6740 { BM_SETSTATE, sent|wparam|lparam|defwinproc, BST_UNCHECKED, ID_RADIO2 }, 6741 { WM_CTLCOLORSTATIC, sent|parent }, 6742 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6743 { WM_GETDLGCODE, sent|wparam|lparam|defwinproc, ID_RADIO2, 0 }, 6744 { BM_SETCHECK, sent|wparam|lparam|defwinproc, BST_CHECKED, ID_RADIO2 }, 6745 { WM_GETDLGCODE, sent|wparam|lparam|defwinproc, ID_RADIO1, 0 }, 6746 { BM_SETCHECK, sent|wparam|lparam|defwinproc, 0, ID_RADIO1 }, 6747 { WM_CTLCOLORSTATIC, sent|parent }, 6748 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6749 { WM_GETDLGCODE, sent|wparam|lparam|defwinproc, ID_RADIO3, 0 }, 6750 { BM_SETCHECK, sent|wparam|lparam|defwinproc, 0, ID_RADIO3 }, 6751 { WM_CTLCOLORSTATIC, sent|parent }, 6752 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6753 { WM_GETDLGCODE, sent|wparam|lparam|defwinproc, ID_TEXT, 0 }, 6754 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, 6755 { WM_CAPTURECHANGED, sent|wparam|lparam|defwinproc, 0, 0 }, 6756 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_RADIO2, BN_CLICKED) }, 6757 { WM_NCHITTEST, sent|optional, 0, 0 }, /* FIXME: Wine doesn't send it */ 6758 { WM_SETCURSOR, sent|optional, 0, 0 }, /* FIXME: Wine doesn't send it */ 6759 { WM_MOUSEMOVE, sent|optional, 0, 0 }, /* FIXME: Wine doesn't send it */ 6760 { 0 } 6761 }; 6762 6763 static const struct message auto_radio_button_VK_UP_child[] = 6764 { 6765 { WM_KEYDOWN, sent|wparam|lparam, VK_UP, 0 }, 6766 { WM_KEYUP, sent|wparam|lparam, VK_UP, 0 }, 6767 { 0 } 6768 }; 6769 6770 static const struct message auto_radio_button_VK_UP_parent[] = 6771 { 6772 { WM_KEYDOWN, sent|wparam|lparam|parent, VK_UP, 0 }, 6773 { WM_KEYUP, sent|wparam|lparam|parent, VK_UP, 0 }, 6774 { 0 } 6775 }; 6776 6777 static const struct message auto_radio_button_VK_UP_dialog[] = 6778 { 6779 { WM_GETDLGCODE, sent|parent, 0, 0 }, 6780 6781 /* optional trailer seen on some windows setups */ 6782 { WM_CHANGEUISTATE, 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_UPDATEUISTATE, sent|optional }, 6801 { WM_CTLCOLORSTATIC, sent|parent|optional }, 6802 { WM_CTLCOLORSTATIC, sent|parent|optional }, 6803 { WM_CTLCOLORSTATIC, sent|parent|optional }, 6804 { WM_UPDATEUISTATE, sent|optional }, 6805 { WM_CTLCOLORSTATIC, sent|parent|optional }, 6806 { WM_CTLCOLORSTATIC, sent|parent|optional }, 6807 { WM_UPDATEUISTATE, sent|optional }, 6808 { WM_CTLCOLORBTN, sent|parent|optional }, 6809 { WM_CTLCOLORBTN, sent|parent|optional }, 6810 { WM_UPDATEUISTATE, sent|optional }, 6811 { WM_CTLCOLORSTATIC, sent|parent|optional }, 6812 { WM_CTLCOLORSTATIC, sent|parent|optional }, 6813 { 0 } 6814 }; 6815 6816 static const struct message auto_radio_button_VK_DOWN_dialog[] = 6817 { 6818 { WM_GETDLGCODE, sent|parent, 0, 0 }, 6819 { WM_GETDLGCODE, sent|wparam|lparam, ID_RADIO1, MAKELPARAM(WM_KEYDOWN, VK_DOWN) }, 6820 { WM_GETDLGCODE, sent|wparam|lparam, ID_RADIO1, 0 }, 6821 { HCBT_SETFOCUS, hook }, 6822 { WM_KILLFOCUS, sent, 0, 0 }, 6823 { WM_CTLCOLORSTATIC, sent|parent }, 6824 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_RADIO3, BN_KILLFOCUS) }, 6825 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6826 { WM_SETFOCUS, sent, 0, 0 }, 6827 { WM_CTLCOLORSTATIC, sent|parent }, 6828 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_RADIO1, BN_SETFOCUS) }, 6829 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_RADIO1, BN_CLICKED) }, 6830 { WM_GETDLGCODE, sent|wparam|lparam, ID_RADIO1, 0 }, 6831 { WM_GETDLGCODE, sent|parent, 0, 0 }, 6832 { DM_GETDEFID, sent|parent, 0, 0 }, 6833 { BM_GETCHECK, sent|wparam|lparam, 0, ID_RADIO1 }, 6834 { BM_CLICK, sent|wparam|lparam, 1, 0 }, 6835 { WM_LBUTTONDOWN, sent|wparam|lparam|defwinproc, 0, 0 }, 6836 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, 6837 { BM_SETSTATE, sent|wparam|lparam|defwinproc, BST_CHECKED, ID_RADIO1 }, 6838 { WM_CTLCOLORSTATIC, sent|parent }, 6839 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6840 { WM_LBUTTONUP, sent|wparam|lparam|defwinproc, 0, 0 }, 6841 { BM_SETSTATE, sent|wparam|lparam|defwinproc, BST_UNCHECKED, ID_RADIO1 }, 6842 { WM_CTLCOLORSTATIC, sent|parent }, 6843 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6844 { WM_GETDLGCODE, sent|wparam|lparam|defwinproc, ID_RADIO1, 0 }, 6845 { BM_SETCHECK, sent|wparam|lparam|defwinproc, BST_CHECKED, ID_RADIO1 }, 6846 { WM_CTLCOLORSTATIC, sent|parent }, 6847 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6848 { WM_GETDLGCODE, sent|wparam|lparam|defwinproc, ID_RADIO3, 0 }, 6849 { BM_SETCHECK, sent|wparam|lparam|defwinproc, BST_UNCHECKED, ID_RADIO3 }, 6850 { WM_CTLCOLORSTATIC, sent|parent }, 6851 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6852 { WM_GETDLGCODE, sent|wparam|lparam|defwinproc, ID_TEXT, 0 }, 6853 { WM_GETDLGCODE, sent|wparam|lparam|defwinproc, ID_RADIO2, 0 }, 6854 { BM_SETCHECK, sent|wparam|lparam|defwinproc, BST_UNCHECKED, ID_RADIO2 }, 6855 { WM_CTLCOLORSTATIC, sent|parent }, 6856 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 6857 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, 6858 { WM_CAPTURECHANGED, sent|wparam|lparam|defwinproc, 0, 0 }, 6859 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_RADIO1, BN_CLICKED) }, 6860 { WM_NCHITTEST, sent|optional, 0, 0 }, /* FIXME: Wine doesn't send it */ 6861 { WM_SETCURSOR, sent|optional, 0, 0 }, /* FIXME: Wine doesn't send it */ 6862 { WM_MOUSEMOVE, sent|optional, 0, 0 }, /* FIXME: Wine doesn't send it */ 6863 { WM_PAINT, sent }, 6864 { WM_CTLCOLORSTATIC, sent|parent }, 6865 { 0 } 6866 }; 6867 6868 static const struct message auto_radio_button_VK_DOWN_radio3[] = 6869 { 6870 { BM_GETCHECK, sent|wparam|lparam, 0, ID_RADIO1 }, 6871 { BM_GETCHECK, sent|wparam|lparam, 0, ID_RADIO2 }, 6872 { BM_GETCHECK, sent|wparam|lparam, 0, ID_RADIO3 }, 6873 { WM_GETDLGCODE, sent|parent, 0, 0 }, 6874 { WM_GETDLGCODE, sent|wparam|lparam, ID_RADIO1, MAKELPARAM(WM_KEYDOWN, VK_DOWN) }, 6875 { WM_GETDLGCODE, sent|wparam|lparam, ID_RADIO1, 0 }, 6876 { WM_GETDLGCODE, sent|wparam|lparam, ID_RADIO1, 0 }, 6877 { WM_GETDLGCODE, sent|wparam|lparam|parent, 0, 0 }, 6878 { WM_USER, sent|parent, 0, 0 }, 6879 { BM_GETCHECK, sent|wparam|lparam, 0, ID_RADIO1 }, 6880 { 0 } 6881 }; 6882 6883 static const struct message auto_radio_button_VK_UP_radio1[] = 6884 { 6885 { WM_GETDLGCODE, sent|parent, 0, 0 }, 6886 { 0 } 6887 }; 6888 6889 static INT_PTR WINAPI radio_test_dlg_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) 6890 { 6891 ParentMsgCheckProcA(hwnd, msg, wp, lp); 6892 return 1; 6893 } 6894 6895 static void test_autoradio_BM_CLICK(void) 6896 { 6897 HWND parent, radio1, radio2, radio3; 6898 RECT rc; 6899 MSG msg; 6900 DWORD ret; 6901 6902 subclass_button(); 6903 6904 parent = CreateDialogParamA(0, "AUTORADIO_TEST_DIALOG_1", 0, radio_test_dlg_proc, 0); 6905 ok(parent != 0, "failed to create parent window\n"); 6906 6907 radio1 = GetDlgItem(parent, ID_RADIO1); 6908 radio2 = GetDlgItem(parent, ID_RADIO2); 6909 radio3 = GetDlgItem(parent, ID_RADIO3); 6910 6911 /* this avoids focus messages in the generated sequence */ 6912 SetFocus(radio2); 6913 6914 flush_events(); 6915 flush_sequence(); 6916 6917 ret = SendMessageA(radio1, BM_GETCHECK, 0, 0); 6918 ok(ret == BST_UNCHECKED, "got %08x\n", ret); 6919 ret = SendMessageA(radio2, BM_GETCHECK, 0, 0); 6920 ok(ret == BST_UNCHECKED, "got %08x\n", ret); 6921 ret = SendMessageA(radio3, BM_GETCHECK, 0, 0); 6922 ok(ret == BST_UNCHECKED, "got %08x\n", ret); 6923 6924 SendMessageA(radio1, BM_SETCHECK, BST_CHECKED, 0); 6925 6926 ret = SendMessageA(radio1, BM_GETCHECK, 0, 0); 6927 ok(ret == BST_CHECKED, "got %08x\n", ret); 6928 ret = SendMessageA(radio2, BM_GETCHECK, 0, 0); 6929 ok(ret == BST_UNCHECKED, "got %08x\n", ret); 6930 ret = SendMessageA(radio3, BM_GETCHECK, 0, 0); 6931 ok(ret == BST_UNCHECKED, "got %08x\n", ret); 6932 6933 SendMessageA(radio2, BM_SETCHECK, BST_CHECKED, 0); 6934 6935 ret = SendMessageA(radio1, BM_GETCHECK, 0, 0); 6936 ok(ret == BST_CHECKED, "got %08x\n", ret); 6937 ret = SendMessageA(radio2, BM_GETCHECK, 0, 0); 6938 ok(ret == BST_CHECKED, "got %08x\n", ret); 6939 ret = SendMessageA(radio3, BM_GETCHECK, 0, 0); 6940 ok(ret == BST_UNCHECKED, "got %08x\n", ret); 6941 6942 SendMessageA(radio3, BM_SETCHECK, BST_CHECKED, 0); 6943 6944 ret = SendMessageA(radio1, BM_GETCHECK, 0, 0); 6945 ok(ret == BST_CHECKED, "got %08x\n", ret); 6946 ret = SendMessageA(radio2, BM_GETCHECK, 0, 0); 6947 ok(ret == BST_CHECKED, "got %08x\n", ret); 6948 ret = SendMessageA(radio3, BM_GETCHECK, 0, 0); 6949 ok(ret == BST_CHECKED, "got %08x\n", ret); 6950 6951 GetWindowRect(radio2, &rc); 6952 SetCursorPos(rc.left+1, rc.top+1); 6953 6954 flush_events(); 6955 flush_sequence(); 6956 6957 log_all_parent_messages++; 6958 6959 SendMessageA(radio2, BM_CLICK, 0, 0); 6960 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 6961 ok_sequence(auto_radio_button_BM_CLICK, "BM_CLICK on auto-radio button", FALSE); 6962 6963 log_all_parent_messages--; 6964 6965 ret = SendMessageA(radio1, BM_GETCHECK, 0, 0); 6966 ok(ret == BST_UNCHECKED, "got %08x\n", ret); 6967 ret = SendMessageA(radio2, BM_GETCHECK, 0, 0); 6968 ok(ret == BST_CHECKED, "got %08x\n", ret); 6969 ret = SendMessageA(radio3, BM_GETCHECK, 0, 0); 6970 ok(ret == BST_UNCHECKED, "got %08x\n", ret); 6971 6972 DestroyWindow(parent); 6973 } 6974 6975 #define test_radio(r1, s1, r2, s2, r3, s3) test_radio_dbg(r1, s1, r2, s2, r3, s3, __LINE__) 6976 static void test_radio_dbg(HWND radio1, int state1, HWND radio2, int state2, HWND radio3, int state3, int line) 6977 { 6978 DWORD ret; 6979 6980 ret = SendMessageA(radio1, BM_GETCHECK, 0, 0); 6981 ok_(__FILE__,line)(ret == state1 ? BST_CHECKED : BST_UNCHECKED, "got %08x\n", ret); 6982 ret = SendMessageA(radio2, BM_GETCHECK, 0, 0); 6983 ok_(__FILE__,line)(ret == state2 ? BST_CHECKED : BST_UNCHECKED, "got %08x\n", ret); 6984 ret = SendMessageA(radio3, BM_GETCHECK, 0, 0); 6985 ok_(__FILE__,line)(ret == state3 ? BST_CHECKED : BST_UNCHECKED, "got %08x\n", ret); 6986 } 6987 6988 static void set_radio(HWND radio1, int state1, HWND radio2, int state2, HWND radio3, int state3) 6989 { 6990 SendMessageA(radio1, BM_SETCHECK, state1 ? BST_CHECKED : BST_UNCHECKED, 0); 6991 SendMessageA(radio2, BM_SETCHECK, state2 ? BST_CHECKED : BST_UNCHECKED, 0); 6992 SendMessageA(radio3, BM_SETCHECK, state3 ? BST_CHECKED : BST_UNCHECKED, 0); 6993 } 6994 6995 static void test_autoradio_kbd_move(void) 6996 { 6997 HWND parent, radio1, radio2, radio3, hwnd; 6998 RECT rc; 6999 MSG msg; 7000 DWORD ret; 7001 7002 subclass_button(); 7003 7004 parent = CreateDialogParamA(0, "AUTORADIO_TEST_DIALOG_2", 0, radio_test_dlg_proc, 0); 7005 ok(parent != 0, "failed to create parent window\n"); 7006 7007 radio1 = GetDlgItem(parent, ID_RADIO1); 7008 radio2 = GetDlgItem(parent, ID_RADIO2); 7009 radio3 = GetDlgItem(parent, ID_RADIO3); 7010 7011 flush_events(); 7012 flush_sequence(); 7013 7014 test_radio(radio1, 0, radio2, 0, radio3, 0); 7015 set_radio(radio1, 1, radio2, 1, radio3, 1); 7016 test_radio(radio1, 1, radio2, 1, radio3, 1); 7017 7018 SetFocus(radio3); 7019 7020 flush_events(); 7021 flush_sequence(); 7022 7023 log_all_parent_messages++; 7024 7025 SendMessageA(radio3, WM_KEYDOWN, VK_UP, 0); 7026 SendMessageA(radio3, WM_KEYUP, VK_UP, 0); 7027 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 7028 ok_sequence(auto_radio_button_VK_UP_child, "press/release VK_UP on auto-radio button", FALSE); 7029 7030 test_radio(radio1, 1, radio2, 1, radio3, 1); 7031 7032 flush_events(); 7033 flush_sequence(); 7034 7035 DefDlgProcA(parent, WM_KEYDOWN, VK_UP, 0); 7036 DefDlgProcA(parent, WM_KEYUP, VK_UP, 0); 7037 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 7038 ok_sequence(auto_radio_button_VK_UP_parent, "press/release VK_UP on dialog", FALSE); 7039 7040 test_radio(radio1, 1, radio2, 1, radio3, 1); 7041 7042 SetFocus(radio3); 7043 GetWindowRect(radio3, &rc); 7044 7045 flush_events(); 7046 flush_sequence(); 7047 7048 msg.hwnd = parent; 7049 msg.message = WM_KEYDOWN; 7050 msg.wParam = VK_UP; 7051 msg.lParam = 0; 7052 msg.pt.x = rc.left + 1; 7053 msg.pt.y = rc.top + 1; 7054 ret = IsDialogMessageA(parent, &msg); 7055 ok(ret, "IsDialogMessage should return TRUE\n"); 7056 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 7057 if (0) /* actual message sequence is different on every run in some Windows setups */ 7058 ok_sequence(auto_radio_button_VK_UP_dialog, "IsDialogMessage(VK_UP) #1", FALSE); 7059 /* what really matters is that nothing has changed */ 7060 test_radio(radio1, 1, radio2, 1, radio3, 1); 7061 7062 set_radio(radio1, 0, radio2, 1, radio3, 1); 7063 test_radio(radio1, 0, radio2, 1, radio3, 1); 7064 7065 flush_events(); 7066 flush_sequence(); 7067 7068 ret = IsDialogMessageA(parent, &msg); 7069 ok(ret, "IsDialogMessage should return TRUE\n"); 7070 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 7071 if (0) /* actual message sequence is different on every run in some Windows setups */ 7072 ok_sequence(auto_radio_button_VK_UP_dialog, "IsDialogMessage(VK_UP) #2", FALSE); 7073 /* what really matters is that nothing has changed */ 7074 test_radio(radio1, 0, radio2, 1, radio3, 1); 7075 7076 /* switch from radio3 ro radio1 */ 7077 SetFocus(radio3); 7078 GetWindowRect(radio3, &rc); 7079 7080 flush_events(); 7081 flush_sequence(); 7082 7083 msg.hwnd = parent; 7084 msg.message = WM_KEYDOWN; 7085 msg.wParam = VK_DOWN; 7086 msg.lParam = 0; 7087 msg.pt.x = rc.left + 1; 7088 msg.pt.y = rc.top + 1; 7089 ret = IsDialogMessageA(parent, &msg); 7090 ok(ret, "IsDialogMessage should return TRUE\n"); 7091 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 7092 ok_sequence(auto_radio_button_VK_DOWN_dialog, "IsDialogMessage(VK_DOWN)", TRUE); 7093 7094 test_radio(radio1, 1, radio2, 0, radio3, 0); 7095 7096 hwnd = GetFocus(); 7097 ok(hwnd == radio1, "focus should be on radio1, not on %p\n", hwnd); 7098 GetWindowRect(radio1, &rc); 7099 7100 msg.hwnd = parent; 7101 msg.message = WM_KEYDOWN; 7102 msg.wParam = VK_DOWN; 7103 msg.lParam = 0; 7104 msg.pt.x = rc.left + 1; 7105 msg.pt.y = rc.top + 1; 7106 ret = IsDialogMessageA(parent, &msg); 7107 ok(ret, "IsDialogMessage should return TRUE\n"); 7108 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 7109 ok_sequence(auto_radio_button_VK_DOWN_radio3, "down to radio3", TRUE); 7110 7111 test_radio(radio1, 1, radio2, 0, radio3, 0); 7112 7113 hwnd = GetFocus(); 7114 ok(hwnd == radio1, "focus should be on radio1, not on %p\n", hwnd); 7115 7116 flush_events(); 7117 flush_sequence(); 7118 7119 msg.hwnd = parent; 7120 msg.message = WM_KEYDOWN; 7121 msg.wParam = VK_UP; 7122 msg.lParam = 0; 7123 msg.pt.x = rc.left + 1; 7124 msg.pt.y = rc.top + 1; 7125 ret = IsDialogMessageA(parent, &msg); 7126 ok(ret, "IsDialogMessage should return TRUE\n"); 7127 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 7128 ok_sequence(auto_radio_button_VK_UP_radio1, "up to radio1", TRUE); 7129 7130 test_radio(radio1, 1, radio2, 0, radio3, 0); 7131 7132 hwnd = GetFocus(); 7133 ok(hwnd == radio1, "focus should be on radio1, not on %p\n", hwnd); 7134 7135 flush_events(); 7136 flush_sequence(); 7137 7138 msg.hwnd = parent; 7139 msg.message = WM_KEYDOWN; 7140 msg.wParam = VK_UP; 7141 msg.lParam = 0; 7142 msg.pt.x = rc.left + 1; 7143 msg.pt.y = rc.top + 1; 7144 ret = IsDialogMessageA(parent, &msg); 7145 ok(ret, "IsDialogMessage should return TRUE\n"); 7146 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 7147 if (0) /* actual message sequence is different on every run in some Windows setups */ 7148 ok_sequence(auto_radio_button_VK_UP_dialog, "IsDialogMessage(VK_UP) #3", FALSE); 7149 /* what really matters is that nothing has changed */ 7150 test_radio(radio1, 1, radio2, 0, radio3, 0); 7151 7152 log_all_parent_messages--; 7153 7154 DestroyWindow(parent); 7155 } 7156 7157 /****************** static message test *************************/ 7158 static const struct message WmSetFontStaticSeq2[] = 7159 { 7160 { WM_SETFONT, sent }, 7161 { WM_PAINT, sent|defwinproc|optional }, 7162 { WM_ERASEBKGND, sent|defwinproc|optional }, 7163 { WM_CTLCOLORSTATIC, sent|defwinproc|optional }, 7164 { 0 } 7165 }; 7166 7167 static WNDPROC old_static_proc; 7168 7169 static LRESULT CALLBACK static_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 7170 { 7171 static LONG defwndproc_counter = 0; 7172 LRESULT ret; 7173 struct recvd_message msg; 7174 7175 if (ignore_message( message )) return 0; 7176 7177 msg.hwnd = hwnd; 7178 msg.message = message; 7179 msg.flags = sent|wparam|lparam; 7180 if (defwndproc_counter) msg.flags |= defwinproc; 7181 msg.wParam = wParam; 7182 msg.lParam = lParam; 7183 msg.descr = "static"; 7184 add_message(&msg); 7185 7186 defwndproc_counter++; 7187 ret = CallWindowProcA(old_static_proc, hwnd, message, wParam, lParam); 7188 defwndproc_counter--; 7189 7190 return ret; 7191 } 7192 7193 static void subclass_static(void) 7194 { 7195 WNDCLASSA cls; 7196 7197 if (!GetClassInfoA(0, "static", &cls)) assert(0); 7198 7199 old_static_proc = cls.lpfnWndProc; 7200 7201 cls.hInstance = GetModuleHandleA(NULL); 7202 cls.lpfnWndProc = static_hook_proc; 7203 cls.lpszClassName = "my_static_class"; 7204 UnregisterClassA(cls.lpszClassName, cls.hInstance); 7205 if (!RegisterClassA(&cls)) assert(0); 7206 } 7207 7208 static void test_static_messages(void) 7209 { 7210 /* FIXME: make as comprehensive as the button message test */ 7211 static const struct 7212 { 7213 DWORD style; 7214 DWORD dlg_code; 7215 const struct message *setfont; 7216 } static_ctrl[] = { 7217 { SS_LEFT, DLGC_STATIC, 7218 WmSetFontStaticSeq2 } 7219 }; 7220 unsigned int i; 7221 HWND hwnd; 7222 DWORD dlg_code; 7223 7224 subclass_static(); 7225 7226 for (i = 0; i < ARRAY_SIZE(static_ctrl); i++) 7227 { 7228 hwnd = CreateWindowExA(0, "my_static_class", "test", static_ctrl[i].style | WS_POPUP, 7229 0, 0, 50, 14, 0, 0, 0, NULL); 7230 ok(hwnd != 0, "Failed to create static window\n"); 7231 7232 dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0); 7233 ok(dlg_code == static_ctrl[i].dlg_code, "%u: wrong dlg_code %08x\n", i, dlg_code); 7234 7235 ShowWindow(hwnd, SW_SHOW); 7236 UpdateWindow(hwnd); 7237 SetFocus(0); 7238 flush_sequence(); 7239 7240 trace("static style %08x\n", static_ctrl[i].style); 7241 SendMessageA(hwnd, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), TRUE); 7242 ok_sequence(static_ctrl[i].setfont, "WM_SETFONT on a static", FALSE); 7243 7244 DestroyWindow(hwnd); 7245 } 7246 } 7247 7248 /****************** ComboBox message test *************************/ 7249 #define ID_COMBOBOX 0x000f 7250 7251 static const struct message SetCurSelComboSeq[] = 7252 { 7253 { CB_SETCURSEL, sent|wparam|lparam, 0, 0 }, 7254 { LB_SETCURSEL, sent|wparam|lparam, 0, 0 }, 7255 { LB_SETTOPINDEX, sent|wparam|lparam, 0, 0 }, 7256 { LB_GETCURSEL, sent|wparam|lparam, 0, 0 }, 7257 { LB_GETTEXTLEN, sent|wparam|lparam, 0, 0 }, 7258 { LB_GETTEXTLEN, sent|wparam|lparam|optional, 0, 0 }, /* TODO: it's sent on all Windows versions */ 7259 { LB_GETTEXT, sent|wparam, 0 }, 7260 { WM_CTLCOLOREDIT, sent|parent }, 7261 { LB_GETITEMDATA, sent|wparam|lparam, 0, 0 }, 7262 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_COMBOBOX, 0x100010f3 }, 7263 { 0 } 7264 }; 7265 7266 static const struct message SetCurSelComboSeq2[] = 7267 { 7268 { CB_SETCURSEL, sent|wparam|lparam, 0, 0 }, 7269 { LB_SETCURSEL, sent|wparam|lparam, 0, 0 }, 7270 { LB_SETTOPINDEX, sent|wparam|lparam, 0, 0 }, 7271 { LB_GETCURSEL, sent|wparam|lparam, 0, 0 }, 7272 { LB_GETTEXTLEN, sent|wparam|lparam, 0, 0 }, 7273 { LB_GETTEXTLEN, sent|wparam|lparam|optional, 0, 0 }, /* TODO: it's sent on all Windows versions */ 7274 { LB_GETTEXT, sent|wparam, 0 }, 7275 { 0 } 7276 }; 7277 7278 static const struct message SetCurSelComboSeq_edit[] = 7279 { 7280 { CB_SETCURSEL, sent|wparam|lparam, 0, 0 }, 7281 { WM_SETTEXT, sent|wparam, 0 }, 7282 { EM_SETSEL, sent|wparam|lparam, 0, INT_MAX }, 7283 { 0 } 7284 }; 7285 7286 static const struct message WmKeyDownComboSeq[] = 7287 { 7288 { WM_KEYDOWN, sent|wparam|lparam, VK_DOWN, 0 }, 7289 { WM_COMMAND, sent|wparam|defwinproc, MAKEWPARAM(1000, LBN_SELCHANGE) }, 7290 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_COMBOBOX, CBN_SELENDOK) }, 7291 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_COMBOBOX, CBN_SELCHANGE) }, 7292 { WM_CTLCOLOREDIT, sent|parent }, 7293 { WM_KEYUP, sent|wparam|lparam, VK_DOWN, 0 }, 7294 { 0 } 7295 }; 7296 7297 static const struct message WmSetPosComboSeq[] = 7298 { 7299 { WM_WINDOWPOSCHANGING, sent }, 7300 { WM_NCCALCSIZE, sent|wparam, TRUE }, 7301 { WM_CHILDACTIVATE, sent }, 7302 { WM_WINDOWPOSCHANGED, sent }, 7303 { WM_MOVE, sent|defwinproc }, 7304 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 7305 { WM_WINDOWPOSCHANGING, sent|defwinproc }, 7306 { WM_NCCALCSIZE, sent|defwinproc|wparam, TRUE }, 7307 { WM_WINDOWPOSCHANGED, sent|defwinproc }, 7308 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, 7309 { 0 } 7310 }; 7311 7312 static const struct message WMSetFocusComboBoxSeq[] = 7313 { 7314 { WM_SETFOCUS, sent }, 7315 { WM_KILLFOCUS, sent|parent }, 7316 { WM_SETFOCUS, sent }, 7317 { WM_COMMAND, sent|defwinproc|wparam, MAKEWPARAM(1001, EN_SETFOCUS) }, 7318 { EM_SETSEL, sent|defwinproc|wparam|lparam, 0, INT_MAX }, 7319 { WM_CTLCOLOREDIT, sent|defwinproc|optional },/* Not sent on W2000, XP or Server 2003 */ 7320 { WM_CTLCOLOREDIT, sent|parent|optional },/* Not sent on W2000, XP or Server 2003 */ 7321 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_COMBOBOX, CBN_SETFOCUS) }, 7322 { 0 } 7323 }; 7324 7325 static const struct message SetFocusButtonSeq[] = 7326 { 7327 { WM_KILLFOCUS, sent }, 7328 { CB_GETCOMBOBOXINFO, sent|optional },/* Windows 2000 */ 7329 { 0x0167, sent|optional },/* Undocumented message. Sent on all versions except Windows 2000 */ 7330 { WM_LBUTTONUP, sent|defwinproc }, 7331 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_COMBOBOX, CBN_SELENDCANCEL) }, 7332 { EM_SETSEL, sent|defwinproc|wparam|lparam, 0, 0 }, 7333 { WM_CTLCOLOREDIT, sent|defwinproc|optional },/* Not sent on W2000, XP or Server 2003 */ 7334 { WM_CTLCOLOREDIT, sent|parent|optional },/* Not sent on W2000, XP or Server 2003 */ 7335 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_COMBOBOX, CBN_KILLFOCUS) }, 7336 { WM_CTLCOLORBTN, sent|parent }, 7337 { 0 } 7338 }; 7339 7340 static const struct message SetFocusComboBoxSeq[] = 7341 { 7342 { WM_CTLCOLORBTN, sent|parent }, 7343 { WM_SETFOCUS, sent }, 7344 { WM_KILLFOCUS, sent|defwinproc }, 7345 { WM_SETFOCUS, sent }, 7346 { WM_COMMAND, sent|defwinproc|wparam, MAKEWPARAM(1001, EN_SETFOCUS) }, 7347 { EM_SETSEL, sent|defwinproc|wparam|lparam, 0, INT_MAX }, 7348 { WM_CTLCOLOREDIT, sent|defwinproc|optional },/* Not sent on W2000, XP or Server 2003 */ 7349 { WM_CTLCOLOREDIT, sent|parent|optional },/* Not sent on W2000, XP or Server 2003 */ 7350 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_COMBOBOX, CBN_SETFOCUS) }, 7351 { 0 } 7352 }; 7353 7354 static const struct message SetFocusButtonSeq2[] = 7355 { 7356 { WM_KILLFOCUS, sent }, 7357 { CB_GETCOMBOBOXINFO, sent|optional },/* Windows 2000 */ 7358 { 0x0167, sent|optional },/* Undocumented message. Sent on all versions except Windows 2000 */ 7359 { WM_LBUTTONUP, sent|defwinproc }, 7360 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_COMBOBOX, CBN_SELENDCANCEL) }, 7361 { EM_SETSEL, sent|defwinproc|wparam|lparam, 0, 0 }, 7362 { WM_CTLCOLOREDIT, sent|defwinproc }, 7363 { WM_CTLCOLOREDIT, sent|parent }, 7364 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_COMBOBOX, CBN_KILLFOCUS) }, 7365 { WM_CTLCOLORBTN, sent|parent }, 7366 { 0 } 7367 }; 7368 7369 static WNDPROC old_combobox_proc, edit_window_proc, lbox_window_proc; 7370 7371 static LRESULT CALLBACK combobox_edit_subclass_proc(HWND hwnd, UINT message, 7372 WPARAM wParam, LPARAM lParam) 7373 { 7374 static LONG defwndproc_counter = 0; 7375 LRESULT ret; 7376 struct recvd_message msg; 7377 7378 /* do not log painting messages */ 7379 if (message != WM_PAINT && 7380 message != WM_NCPAINT && 7381 message != WM_SYNCPAINT && 7382 message != WM_ERASEBKGND && 7383 message != WM_NCHITTEST && 7384 message != WM_GETTEXT && 7385 !ignore_message( message )) 7386 { 7387 msg.hwnd = hwnd; 7388 msg.message = message; 7389 msg.flags = sent|wparam|lparam; 7390 if (defwndproc_counter) msg.flags |= defwinproc; 7391 msg.wParam = wParam; 7392 msg.lParam = lParam; 7393 msg.descr = "combo edit"; 7394 add_message(&msg); 7395 } 7396 7397 defwndproc_counter++; 7398 ret = CallWindowProcA(edit_window_proc, hwnd, message, wParam, lParam); 7399 defwndproc_counter--; 7400 7401 return ret; 7402 } 7403 7404 static LRESULT CALLBACK combobox_lbox_subclass_proc(HWND hwnd, UINT message, 7405 WPARAM wParam, LPARAM lParam) 7406 { 7407 static LONG defwndproc_counter = 0; 7408 LRESULT ret; 7409 struct recvd_message msg; 7410 7411 /* do not log painting messages */ 7412 if (message != WM_PAINT && 7413 message != WM_NCPAINT && 7414 message != WM_SYNCPAINT && 7415 message != WM_ERASEBKGND && 7416 message != WM_NCHITTEST && 7417 !ignore_message( message )) 7418 { 7419 msg.hwnd = hwnd; 7420 msg.message = message; 7421 msg.flags = sent|wparam|lparam; 7422 if (defwndproc_counter) msg.flags |= defwinproc; 7423 msg.wParam = wParam; 7424 msg.lParam = lParam; 7425 msg.descr = "combo lbox"; 7426 add_message(&msg); 7427 } 7428 7429 defwndproc_counter++; 7430 ret = CallWindowProcA(lbox_window_proc, hwnd, message, wParam, lParam); 7431 defwndproc_counter--; 7432 7433 return ret; 7434 } 7435 7436 static LRESULT CALLBACK combobox_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 7437 { 7438 static LONG defwndproc_counter = 0; 7439 LRESULT ret; 7440 struct recvd_message msg; 7441 7442 /* do not log painting messages */ 7443 if (message != WM_PAINT && 7444 message != WM_NCPAINT && 7445 message != WM_SYNCPAINT && 7446 message != WM_ERASEBKGND && 7447 message != WM_NCHITTEST && 7448 message != WM_GETTEXT && 7449 !ignore_message( message )) 7450 { 7451 msg.hwnd = hwnd; 7452 msg.message = message; 7453 msg.flags = sent|wparam|lparam; 7454 if (defwndproc_counter) msg.flags |= defwinproc; 7455 msg.wParam = wParam; 7456 msg.lParam = lParam; 7457 msg.descr = "combo"; 7458 add_message(&msg); 7459 } 7460 7461 defwndproc_counter++; 7462 ret = CallWindowProcA(old_combobox_proc, hwnd, message, wParam, lParam); 7463 defwndproc_counter--; 7464 7465 return ret; 7466 } 7467 7468 static void subclass_combobox(void) 7469 { 7470 WNDCLASSA cls; 7471 7472 if (!GetClassInfoA(0, "ComboBox", &cls)) assert(0); 7473 7474 old_combobox_proc = cls.lpfnWndProc; 7475 7476 cls.hInstance = GetModuleHandleA(NULL); 7477 cls.lpfnWndProc = combobox_hook_proc; 7478 cls.lpszClassName = "my_combobox_class"; 7479 UnregisterClassA(cls.lpszClassName, cls.hInstance); 7480 if (!RegisterClassA(&cls)) assert(0); 7481 } 7482 7483 static void test_combobox_messages(void) 7484 { 7485 HWND parent, combo, button, edit, lbox; 7486 LRESULT ret; 7487 COMBOBOXINFO cbInfo; 7488 BOOL res; 7489 7490 subclass_combobox(); 7491 7492 parent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 7493 100, 100, 200, 200, 0, 0, 0, NULL); 7494 ok(parent != 0, "Failed to create parent window\n"); 7495 flush_sequence(); 7496 7497 combo = CreateWindowExA(0, "my_combobox_class", "test", WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | CBS_HASSTRINGS, 7498 0, 0, 100, 150, parent, (HMENU)ID_COMBOBOX, 0, NULL); 7499 ok(combo != 0, "Failed to create combobox window\n"); 7500 7501 UpdateWindow(combo); 7502 7503 ret = SendMessageA(combo, WM_GETDLGCODE, 0, 0); 7504 ok(ret == (DLGC_WANTCHARS | DLGC_WANTARROWS), "wrong dlg_code %08lx\n", ret); 7505 7506 ret = SendMessageA(combo, CB_ADDSTRING, 0, (LPARAM)"item 0"); 7507 ok(ret == 0, "expected 0, got %ld\n", ret); 7508 ret = SendMessageA(combo, CB_ADDSTRING, 0, (LPARAM)"item 1"); 7509 ok(ret == 1, "expected 1, got %ld\n", ret); 7510 ret = SendMessageA(combo, CB_ADDSTRING, 0, (LPARAM)"item 2"); 7511 ok(ret == 2, "expected 2, got %ld\n", ret); 7512 7513 SendMessageA(combo, CB_SETCURSEL, 0, 0); 7514 SetFocus(combo); 7515 flush_sequence(); 7516 7517 log_all_parent_messages++; 7518 SendMessageA(combo, WM_KEYDOWN, VK_DOWN, 0); 7519 SendMessageA(combo, WM_KEYUP, VK_DOWN, 0); 7520 log_all_parent_messages--; 7521 ok_sequence(WmKeyDownComboSeq, "WM_KEYDOWN/VK_DOWN on a ComboBox", FALSE); 7522 7523 flush_sequence(); 7524 SetWindowPos(combo, 0, 10, 10, 120, 130, SWP_NOZORDER); 7525 ok_sequence(WmSetPosComboSeq, "repositioning messages on a ComboBox", FALSE); 7526 7527 DestroyWindow(combo); 7528 DestroyWindow(parent); 7529 7530 /* Start again. Test combobox text selection when getting and losing focus */ 7531 parent = CreateWindowExA(0, "TestParentClass", "Parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 7532 10, 10, 300, 300, NULL, NULL, NULL, NULL); 7533 ok(parent != 0, "Failed to create parent window\n"); 7534 7535 combo = CreateWindowExA(0, "my_combobox_class", "test", WS_CHILD | WS_VISIBLE | CBS_DROPDOWN, 7536 5, 5, 100, 100, parent, (HMENU)ID_COMBOBOX, NULL, NULL); 7537 ok(combo != 0, "Failed to create combobox window\n"); 7538 7539 cbInfo.cbSize = sizeof(COMBOBOXINFO); 7540 SetLastError(0xdeadbeef); 7541 res = GetComboBoxInfo(combo, &cbInfo); 7542 ok(res, "Failed to get COMBOBOXINFO structure; LastError: %u\n", GetLastError()); 7543 edit = cbInfo.hwndItem; 7544 7545 edit_window_proc = (WNDPROC)SetWindowLongPtrA(edit, GWLP_WNDPROC, 7546 (ULONG_PTR)combobox_edit_subclass_proc); 7547 7548 button = CreateWindowExA(0, "Button", "OK", WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 7549 5, 50, 100, 20, parent, NULL, 7550 (HINSTANCE)GetWindowLongPtrA(parent, GWLP_HINSTANCE), NULL); 7551 ok(button != 0, "Failed to create button window\n"); 7552 7553 flush_sequence(); 7554 log_all_parent_messages++; 7555 SendMessageA(combo, WM_SETFOCUS, 0, (LPARAM)edit); 7556 log_all_parent_messages--; 7557 ok_sequence(WMSetFocusComboBoxSeq, "WM_SETFOCUS on a ComboBox", TRUE); 7558 7559 flush_sequence(); 7560 log_all_parent_messages++; 7561 SetFocus(button); 7562 log_all_parent_messages--; 7563 ok_sequence(SetFocusButtonSeq, "SetFocus on a Button", TRUE); 7564 7565 SendMessageA(combo, WM_SETTEXT, 0, (LPARAM)"Wine Test"); 7566 7567 flush_sequence(); 7568 log_all_parent_messages++; 7569 SetFocus(combo); 7570 log_all_parent_messages--; 7571 ok_sequence(SetFocusComboBoxSeq, "SetFocus on a ComboBox", TRUE); 7572 7573 flush_sequence(); 7574 log_all_parent_messages++; 7575 SetFocus(button); 7576 log_all_parent_messages--; 7577 ok_sequence(SetFocusButtonSeq2, "SetFocus on a Button (2)", TRUE); 7578 7579 SetFocus(combo); 7580 SendMessageA(combo, WM_SETREDRAW, FALSE, 0); 7581 flush_sequence(); 7582 log_all_parent_messages++; 7583 SendMessageA(combo, CB_SETCURSEL, 0, 0); 7584 log_all_parent_messages--; 7585 ok_sequence(SetCurSelComboSeq_edit, "CB_SETCURSEL on a ComboBox with edit control", FALSE); 7586 7587 DestroyWindow(button); 7588 DestroyWindow(combo); 7589 7590 combo = CreateWindowExA(0, "my_combobox_class", "test", 7591 WS_CHILD | WS_VISIBLE | CBS_OWNERDRAWFIXED | CBS_DROPDOWNLIST, 7592 5, 5, 100, 100, parent, (HMENU)ID_COMBOBOX, NULL, NULL); 7593 ok(combo != 0, "Failed to create combobox window\n"); 7594 7595 ret = SendMessageA(combo, CB_ADDSTRING, 0, (LPARAM)"item 0"); 7596 ok(ret == 0, "expected 0, got %ld\n", ret); 7597 7598 cbInfo.cbSize = sizeof(COMBOBOXINFO); 7599 SetLastError(0xdeadbeef); 7600 res = GetComboBoxInfo(combo, &cbInfo); 7601 ok(res, "Failed to get COMBOBOXINFO structure; LastError: %u\n", GetLastError()); 7602 lbox = cbInfo.hwndList; 7603 lbox_window_proc = (WNDPROC)SetWindowLongPtrA(lbox, GWLP_WNDPROC, 7604 (ULONG_PTR)combobox_lbox_subclass_proc); 7605 flush_sequence(); 7606 7607 log_all_parent_messages++; 7608 SendMessageA(combo, CB_SETCURSEL, 0, 0); 7609 log_all_parent_messages--; 7610 ok_sequence(SetCurSelComboSeq, "CB_SETCURSEL on a ComboBox", FALSE); 7611 7612 ShowWindow(combo, SW_HIDE); 7613 flush_sequence(); 7614 log_all_parent_messages++; 7615 SendMessageA(combo, CB_SETCURSEL, 0, 0); 7616 log_all_parent_messages--; 7617 ok_sequence(SetCurSelComboSeq2, "CB_SETCURSEL on a ComboBox", FALSE); 7618 7619 DestroyWindow(combo); 7620 DestroyWindow(parent); 7621 } 7622 7623 /****************** WM_IME_KEYDOWN message test *******************/ 7624 7625 static const struct message WmImeKeydownMsgSeq_0[] = 7626 { 7627 { WM_IME_KEYDOWN, wparam, VK_RETURN }, 7628 { WM_CHAR, wparam, 'A' }, 7629 { 0 } 7630 }; 7631 7632 static const struct message WmImeKeydownMsgSeq_1[] = 7633 { 7634 { WM_KEYDOWN, optional|wparam, VK_RETURN }, 7635 { WM_CHAR, optional|wparam, VK_RETURN }, 7636 { 0 } 7637 }; 7638 7639 static LRESULT WINAPI wmime_keydown_procA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 7640 { 7641 struct recvd_message msg; 7642 7643 msg.hwnd = hwnd; 7644 msg.message = message; 7645 msg.flags = wparam|lparam; 7646 msg.wParam = wParam; 7647 msg.lParam = lParam; 7648 msg.descr = "wmime_keydown"; 7649 add_message(&msg); 7650 7651 return DefWindowProcA(hwnd, message, wParam, lParam); 7652 } 7653 7654 static void register_wmime_keydown_class(void) 7655 { 7656 WNDCLASSA cls; 7657 7658 ZeroMemory(&cls, sizeof(WNDCLASSA)); 7659 cls.lpfnWndProc = wmime_keydown_procA; 7660 cls.hInstance = GetModuleHandleA(0); 7661 cls.lpszClassName = "wmime_keydown_class"; 7662 if (!RegisterClassA(&cls)) assert(0); 7663 } 7664 7665 static void test_wmime_keydown_message(void) 7666 { 7667 HWND hwnd; 7668 MSG msg; 7669 7670 trace("Message sequences by WM_IME_KEYDOWN\n"); 7671 7672 register_wmime_keydown_class(); 7673 hwnd = CreateWindowExA(0, "wmime_keydown_class", NULL, WS_OVERLAPPEDWINDOW, 7674 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0, 7675 NULL, NULL, 0); 7676 flush_events(); 7677 flush_sequence(); 7678 7679 SendMessageA(hwnd, WM_IME_KEYDOWN, VK_RETURN, 0x1c0001); 7680 SendMessageA(hwnd, WM_CHAR, 'A', 1); 7681 ok_sequence(WmImeKeydownMsgSeq_0, "WM_IME_KEYDOWN 0", FALSE); 7682 7683 while ( PeekMessageA(&msg, 0, 0, 0, PM_REMOVE) ) 7684 { 7685 TranslateMessage(&msg); 7686 DispatchMessageA(&msg); 7687 } 7688 ok_sequence(WmImeKeydownMsgSeq_1, "WM_IME_KEYDOWN 1", FALSE); 7689 7690 DestroyWindow(hwnd); 7691 } 7692 7693 /************* painting message test ********************/ 7694 7695 void dump_region(HRGN hrgn) 7696 { 7697 DWORD i, size; 7698 RGNDATA *data = NULL; 7699 RECT *rect; 7700 7701 if (!hrgn) 7702 { 7703 printf( "null region\n" ); 7704 return; 7705 } 7706 if (!(size = GetRegionData( hrgn, 0, NULL ))) return; 7707 if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return; 7708 GetRegionData( hrgn, size, data ); 7709 printf("%d rects:", data->rdh.nCount ); 7710 for (i = 0, rect = (RECT *)data->Buffer; i < data->rdh.nCount; i++, rect++) 7711 printf( " %s", wine_dbgstr_rect( rect )); 7712 printf("\n"); 7713 HeapFree( GetProcessHeap(), 0, data ); 7714 } 7715 7716 #define check_update_rgn( hwnd, hrgn ) check_update_rgn_( __LINE__, hwnd, hrgn ) 7717 static void check_update_rgn_( int line, HWND hwnd, HRGN hrgn ) 7718 { 7719 INT ret; 7720 RECT r1, r2; 7721 HRGN tmp = CreateRectRgn( 0, 0, 0, 0 ); 7722 HRGN update = CreateRectRgn( 0, 0, 0, 0 ); 7723 7724 ret = GetUpdateRgn( hwnd, update, FALSE ); 7725 ok( ret != ERROR, "GetUpdateRgn failed\n" ); 7726 if (ret == NULLREGION) 7727 { 7728 ok_(__FILE__,line)( !hrgn, "Update region shouldn't be empty\n" ); 7729 } 7730 else 7731 { 7732 if (CombineRgn( tmp, hrgn, update, RGN_XOR ) != NULLREGION) 7733 { 7734 ok_(__FILE__,line)( 0, "Regions are different\n" ); 7735 if (winetest_debug > 0) 7736 { 7737 printf( "Update region: " ); 7738 dump_region( update ); 7739 printf( "Wanted region: " ); 7740 dump_region( hrgn ); 7741 } 7742 } 7743 } 7744 GetRgnBox( update, &r1 ); 7745 GetUpdateRect( hwnd, &r2, FALSE ); 7746 ok_(__FILE__,line)( EqualRect( &r1, &r2 ), "Rectangles are different: %s / %s\n", 7747 wine_dbgstr_rect( &r1 ), wine_dbgstr_rect( &r2 )); 7748 7749 DeleteObject( tmp ); 7750 DeleteObject( update ); 7751 } 7752 7753 static const struct message WmInvalidateRgn[] = { 7754 { WM_NCPAINT, sent }, 7755 { WM_GETTEXT, sent|defwinproc|optional }, 7756 { 0 } 7757 }; 7758 7759 static const struct message WmGetUpdateRect[] = { 7760 { WM_NCPAINT, sent }, 7761 { WM_GETTEXT, sent|defwinproc|optional }, 7762 { WM_PAINT, sent }, 7763 { 0 } 7764 }; 7765 7766 static const struct message WmInvalidateFull[] = { 7767 { WM_NCPAINT, sent|wparam, 1 }, 7768 { WM_GETTEXT, sent|defwinproc|optional }, 7769 { 0 } 7770 }; 7771 7772 static const struct message WmInvalidateErase[] = { 7773 { WM_NCPAINT, sent|wparam, 1 }, 7774 { WM_GETTEXT, sent|defwinproc|optional }, 7775 { WM_ERASEBKGND, sent }, 7776 { 0 } 7777 }; 7778 7779 static const struct message WmInvalidatePaint[] = { 7780 { WM_PAINT, sent }, 7781 { WM_NCPAINT, sent|wparam|beginpaint, 1 }, 7782 { WM_GETTEXT, sent|beginpaint|defwinproc|optional }, 7783 { 0 } 7784 }; 7785 7786 static const struct message WmInvalidateErasePaint[] = { 7787 { WM_PAINT, sent }, 7788 { WM_NCPAINT, sent|wparam|beginpaint, 1 }, 7789 { WM_GETTEXT, sent|beginpaint|defwinproc|optional }, 7790 { WM_ERASEBKGND, sent|beginpaint|optional }, 7791 { 0 } 7792 }; 7793 7794 static const struct message WmInvalidateErasePaint2[] = { 7795 { WM_PAINT, sent }, 7796 { WM_NCPAINT, sent|beginpaint }, 7797 { WM_GETTEXT, sent|beginpaint|defwinproc|optional }, 7798 { WM_ERASEBKGND, sent|beginpaint|optional }, 7799 { 0 } 7800 }; 7801 7802 static const struct message WmErase[] = { 7803 { WM_ERASEBKGND, sent }, 7804 { 0 } 7805 }; 7806 7807 static const struct message WmPaint[] = { 7808 { WM_PAINT, sent }, 7809 { 0 } 7810 }; 7811 7812 static const struct message WmParentOnlyPaint[] = { 7813 { WM_PAINT, sent|parent }, 7814 { 0 } 7815 }; 7816 7817 static const struct message WmInvalidateParent[] = { 7818 { WM_NCPAINT, sent|parent }, 7819 { WM_GETTEXT, sent|defwinproc|parent|optional }, 7820 { WM_ERASEBKGND, sent|parent }, 7821 { 0 } 7822 }; 7823 7824 static const struct message WmInvalidateParentChild[] = { 7825 { WM_NCPAINT, sent|parent }, 7826 { WM_GETTEXT, sent|defwinproc|parent|optional }, 7827 { WM_ERASEBKGND, sent|parent }, 7828 { WM_NCPAINT, sent }, 7829 { WM_GETTEXT, sent|defwinproc|optional }, 7830 { WM_ERASEBKGND, sent }, 7831 { 0 } 7832 }; 7833 7834 static const struct message WmInvalidateParentChild2[] = { 7835 { WM_ERASEBKGND, sent|parent }, 7836 { WM_NCPAINT, sent }, 7837 { WM_GETTEXT, sent|defwinproc|optional }, 7838 { WM_ERASEBKGND, sent }, 7839 { 0 } 7840 }; 7841 7842 static const struct message WmParentPaint[] = { 7843 { WM_PAINT, sent|parent }, 7844 { WM_PAINT, sent }, 7845 { 0 } 7846 }; 7847 7848 static const struct message WmParentPaintNc[] = { 7849 { WM_PAINT, sent|parent }, 7850 { WM_PAINT, sent }, 7851 { WM_NCPAINT, sent|beginpaint }, 7852 { WM_GETTEXT, sent|beginpaint|defwinproc|optional }, 7853 { WM_ERASEBKGND, sent|beginpaint|optional }, 7854 { 0 } 7855 }; 7856 7857 static const struct message WmChildPaintNc[] = { 7858 { WM_PAINT, sent }, 7859 { WM_NCPAINT, sent|beginpaint }, 7860 { WM_GETTEXT, sent|beginpaint|defwinproc|optional }, 7861 { WM_ERASEBKGND, sent|beginpaint|optional }, 7862 { 0 } 7863 }; 7864 7865 static const struct message WmParentErasePaint[] = { 7866 { WM_PAINT, sent|parent }, 7867 { WM_NCPAINT, sent|parent|beginpaint }, 7868 { WM_GETTEXT, sent|parent|beginpaint|defwinproc|optional }, 7869 { WM_ERASEBKGND, sent|parent|beginpaint|optional }, 7870 { WM_PAINT, sent }, 7871 { WM_NCPAINT, sent|beginpaint }, 7872 { WM_GETTEXT, sent|beginpaint|defwinproc|optional }, 7873 { WM_ERASEBKGND, sent|beginpaint|optional }, 7874 { 0 } 7875 }; 7876 7877 static const struct message WmParentOnlyNcPaint[] = { 7878 { WM_PAINT, sent|parent }, 7879 { WM_NCPAINT, sent|parent|beginpaint }, 7880 { WM_GETTEXT, sent|parent|beginpaint|defwinproc|optional }, 7881 { 0 } 7882 }; 7883 7884 static const struct message WmSetParentStyle[] = { 7885 { WM_STYLECHANGING, sent|parent }, 7886 { WM_STYLECHANGED, sent|parent }, 7887 { 0 } 7888 }; 7889 7890 static void test_paint_messages(void) 7891 { 7892 BOOL ret; 7893 RECT rect, rect2; 7894 POINT pt; 7895 MSG msg; 7896 HWND hparent, hchild; 7897 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 ); 7898 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 ); 7899 HWND hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW, 7900 100, 100, 200, 200, 0, 0, 0, NULL); 7901 ok (hwnd != 0, "Failed to create overlapped window\n"); 7902 7903 ShowWindow( hwnd, SW_SHOW ); 7904 UpdateWindow( hwnd ); 7905 flush_events(); 7906 flush_sequence(); 7907 7908 check_update_rgn( hwnd, 0 ); 7909 SetRectRgn( hrgn, 10, 10, 20, 20 ); 7910 ret = RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE ); 7911 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret); 7912 check_update_rgn( hwnd, hrgn ); 7913 SetRectRgn( hrgn2, 20, 20, 30, 30 ); 7914 ret = RedrawWindow( hwnd, NULL, hrgn2, RDW_INVALIDATE ); 7915 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret); 7916 CombineRgn( hrgn, hrgn, hrgn2, RGN_OR ); 7917 check_update_rgn( hwnd, hrgn ); 7918 /* validate everything */ 7919 ret = RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE ); 7920 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret); 7921 check_update_rgn( hwnd, 0 ); 7922 7923 /* test empty region */ 7924 SetRectRgn( hrgn, 10, 10, 10, 15 ); 7925 ret = RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE ); 7926 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret); 7927 check_update_rgn( hwnd, 0 ); 7928 /* test empty rect */ 7929 SetRect( &rect, 10, 10, 10, 15 ); 7930 ret = RedrawWindow( hwnd, &rect, NULL, RDW_INVALIDATE ); 7931 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret); 7932 check_update_rgn( hwnd, 0 ); 7933 7934 /* flush pending messages */ 7935 flush_events(); 7936 flush_sequence(); 7937 7938 GetClientRect( hwnd, &rect ); 7939 SetRectRgn( hrgn, 0, 0, rect.right - rect.left, rect.bottom - rect.top ); 7940 /* MSDN: if hwnd parameter is NULL, InvalidateRect invalidates and redraws 7941 * all windows and sends WM_ERASEBKGND and WM_NCPAINT. 7942 */ 7943 SetRectEmpty( &rect ); 7944 ok(InvalidateRect(0, &rect, FALSE), "InvalidateRect(0, &rc, FALSE) failed\n"); 7945 check_update_rgn( hwnd, hrgn ); 7946 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE ); 7947 flush_events(); 7948 ok_sequence( WmPaint, "Paint", FALSE ); 7949 RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE ); 7950 check_update_rgn( hwnd, 0 ); 7951 7952 SetRectEmpty( &rect ); 7953 ok(RedrawWindow(0, &rect, 0, RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW ), 7954 "RedrawWindow failed\n"); 7955 check_update_rgn( hwnd, 0 ); 7956 7957 SetRectEmpty( &rect ); 7958 ok(RedrawWindow(0, &rect, 0, RDW_ALLCHILDREN | RDW_VALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW ), 7959 "RedrawWindow failed\n"); 7960 check_update_rgn( hwnd, 0 ); 7961 7962 GetWindowRect( hwnd, &rect ); 7963 ok(RedrawWindow(0, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW ), 7964 "RedrawWindow failed\n"); 7965 check_update_rgn( hwnd, 0 ); 7966 7967 flush_events(); 7968 ok(RedrawWindow(0, &rect, 0, RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW ), 7969 "RedrawWindow failed\n"); 7970 check_update_rgn( hwnd, hrgn ); 7971 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE ); 7972 flush_events(); 7973 ok_sequence( WmPaint, "Paint", FALSE ); 7974 RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE ); 7975 check_update_rgn( hwnd, 0 ); 7976 7977 ok(RedrawWindow(GetDesktopWindow(), &rect, 0, 7978 RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW ), 7979 "RedrawWindow failed\n"); 7980 ret = GetUpdateRgn( hwnd, hrgn2, FALSE ); 7981 ok( ret == NULLREGION || broken(ret == SIMPLEREGION), /* <= win7 */ 7982 "region should be null (%d)\n", ret ); 7983 if (ret == SIMPLEREGION) ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE ); 7984 RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE ); 7985 flush_events(); 7986 7987 ok(RedrawWindow(GetDesktopWindow(), NULL, 0, 7988 RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW ), 7989 "RedrawWindow failed\n"); 7990 ret = GetUpdateRgn( hwnd, hrgn2, FALSE ); 7991 ok( ret == NULLREGION || broken(ret == SIMPLEREGION), /* <= win7 */ 7992 "region should be null (%d)\n", ret ); 7993 if (ret == SIMPLEREGION) ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE ); 7994 RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE ); 7995 flush_events(); 7996 7997 SetRectRgn( hrgn2, rect.left, rect.top, rect.right, rect.bottom ); 7998 ok(RedrawWindow(0, NULL, hrgn2, RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW ), 7999 "RedrawWindow failed\n"); 8000 check_update_rgn( hwnd, hrgn ); 8001 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE ); 8002 flush_events(); 8003 ok_sequence( WmPaint, "Paint", FALSE ); 8004 RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE ); 8005 check_update_rgn( hwnd, 0 ); 8006 8007 ok(RedrawWindow(0, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW ), 8008 "RedrawWindow failed\n"); 8009 check_update_rgn( hwnd, 0 ); 8010 8011 ok(RedrawWindow(0, NULL, 0, RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW ), 8012 "RedrawWindow failed\n"); 8013 check_update_rgn( hwnd, hrgn ); 8014 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE ); 8015 flush_events(); 8016 ok_sequence( WmPaint, "Paint", FALSE ); 8017 RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE ); 8018 check_update_rgn( hwnd, 0 ); 8019 8020 /* MSDN: if hwnd parameter is NULL, ValidateRect invalidates and redraws 8021 * all windows and sends WM_ERASEBKGND and WM_NCPAINT. 8022 */ 8023 SetRectEmpty( &rect ); 8024 if (ValidateRect(0, &rect) && /* not supported on Win9x */ 8025 GetUpdateRect(hwnd, NULL, FALSE)) /* or >= Win 8 */ 8026 { 8027 check_update_rgn( hwnd, hrgn ); 8028 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE ); 8029 flush_events(); 8030 ok_sequence( WmPaint, "Paint", FALSE ); 8031 RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE ); 8032 check_update_rgn( hwnd, 0 ); 8033 } 8034 8035 SetLastError(0xdeadbeef); 8036 ok(!InvalidateRgn(0, NULL, FALSE), "InvalidateRgn(0, NULL, FALSE) should fail\n"); 8037 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || GetLastError() == 0xdeadbeef, 8038 "wrong error code %d\n", GetLastError()); 8039 check_update_rgn( hwnd, 0 ); 8040 flush_events(); 8041 ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE ); 8042 8043 SetLastError(0xdeadbeef); 8044 ok(!ValidateRgn(0, NULL), "ValidateRgn(0, NULL) should fail\n"); 8045 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || 8046 broken( GetLastError() == 0xdeadbeef ) /* win9x */, 8047 "wrong error code %d\n", GetLastError()); 8048 check_update_rgn( hwnd, 0 ); 8049 flush_events(); 8050 ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE ); 8051 8052 SetLastError(0xdeadbeef); 8053 ok(!UpdateWindow(NULL), "UpdateWindow(NULL) should fail\n"); 8054 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || 8055 broken( GetLastError() == 0xdeadbeef ) /* win9x */, 8056 "wrong error code %d\n", GetLastError()); 8057 check_update_rgn( hwnd, 0 ); 8058 flush_events(); 8059 ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE ); 8060 8061 /* now with frame */ 8062 SetRectRgn( hrgn, -5, -5, 20, 20 ); 8063 8064 /* flush pending messages */ 8065 flush_events(); 8066 flush_sequence(); 8067 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME ); 8068 ok_sequence( WmEmptySeq, "EmptySeq", FALSE ); 8069 8070 SetRectRgn( hrgn, 0, 0, 20, 20 ); /* GetUpdateRgn clips to client area */ 8071 check_update_rgn( hwnd, hrgn ); 8072 8073 flush_sequence(); 8074 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW ); 8075 ok_sequence( WmInvalidateRgn, "InvalidateRgn", FALSE ); 8076 8077 flush_sequence(); 8078 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW ); 8079 ok_sequence( WmInvalidateFull, "InvalidateFull", FALSE ); 8080 8081 GetClientRect( hwnd, &rect ); 8082 SetRectRgn( hrgn, rect.left, rect.top, rect.right, rect.bottom ); 8083 check_update_rgn( hwnd, hrgn ); 8084 8085 flush_sequence(); 8086 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW ); 8087 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE ); 8088 8089 flush_sequence(); 8090 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW | RDW_UPDATENOW ); 8091 ok_sequence( WmInvalidatePaint, "InvalidatePaint", FALSE ); 8092 check_update_rgn( hwnd, 0 ); 8093 8094 flush_sequence(); 8095 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_UPDATENOW ); 8096 ok_sequence( WmInvalidateErasePaint, "InvalidateErasePaint", FALSE ); 8097 check_update_rgn( hwnd, 0 ); 8098 8099 flush_sequence(); 8100 SetRectRgn( hrgn, 0, 0, 100, 100 ); 8101 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE ); 8102 SetRectRgn( hrgn, 0, 0, 50, 100 ); 8103 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE ); 8104 SetRectRgn( hrgn, 50, 0, 100, 100 ); 8105 check_update_rgn( hwnd, hrgn ); 8106 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_ERASENOW ); 8107 ok_sequence( WmEmptySeq, "EmptySeq", FALSE ); /* must not generate messages, everything is valid */ 8108 check_update_rgn( hwnd, 0 ); 8109 8110 flush_sequence(); 8111 SetRectRgn( hrgn, 0, 0, 100, 100 ); 8112 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE ); 8113 SetRectRgn( hrgn, 0, 0, 100, 50 ); 8114 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_ERASENOW ); 8115 ok_sequence( WmErase, "Erase", FALSE ); 8116 SetRectRgn( hrgn, 0, 50, 100, 100 ); 8117 check_update_rgn( hwnd, hrgn ); 8118 8119 flush_sequence(); 8120 SetRectRgn( hrgn, 0, 0, 100, 100 ); 8121 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE ); 8122 SetRectRgn( hrgn, 0, 0, 50, 50 ); 8123 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOERASE | RDW_UPDATENOW ); 8124 ok_sequence( WmPaint, "Paint", FALSE ); 8125 8126 flush_sequence(); 8127 SetRectRgn( hrgn, -4, -4, -2, -2 ); 8128 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME ); 8129 SetRectRgn( hrgn, -200, -200, -198, -198 ); 8130 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOFRAME | RDW_ERASENOW ); 8131 ok_sequence( WmEmptySeq, "EmptySeq", FALSE ); 8132 8133 flush_sequence(); 8134 SetRectRgn( hrgn, -4, -4, -2, -2 ); 8135 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME ); 8136 SetRectRgn( hrgn, -4, -4, -3, -3 ); 8137 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOFRAME ); 8138 SetRectRgn( hrgn, 0, 0, 1, 1 ); 8139 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_UPDATENOW ); 8140 ok_sequence( WmPaint, "Paint", FALSE ); 8141 8142 flush_sequence(); 8143 SetRectRgn( hrgn, -4, -4, -1, -1 ); 8144 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME ); 8145 RedrawWindow( hwnd, NULL, 0, RDW_ERASENOW ); 8146 /* make sure no WM_PAINT was generated */ 8147 flush_events(); 8148 ok_sequence( WmInvalidateRgn, "InvalidateRgn", FALSE ); 8149 8150 flush_sequence(); 8151 SetRectRgn( hrgn, -4, -4, -1, -1 ); 8152 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME ); 8153 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) 8154 { 8155 if (msg.hwnd == hwnd && msg.message == WM_PAINT) 8156 { 8157 /* GetUpdateRgn must return empty region since only nonclient area is invalidated */ 8158 INT ret = GetUpdateRgn( hwnd, hrgn, FALSE ); 8159 ok( ret == NULLREGION, "Invalid GetUpdateRgn result %d\n", ret ); 8160 ret = GetUpdateRect( hwnd, &rect, FALSE ); 8161 ok( ret, "Invalid GetUpdateRect result %d\n", ret ); 8162 /* this will send WM_NCPAINT and validate the non client area */ 8163 ret = GetUpdateRect( hwnd, &rect, TRUE ); 8164 ok( !ret, "Invalid GetUpdateRect result %d\n", ret ); 8165 } 8166 DispatchMessageA( &msg ); 8167 } 8168 ok_sequence( WmGetUpdateRect, "GetUpdateRect", FALSE ); 8169 8170 DestroyWindow( hwnd ); 8171 8172 /* now test with a child window */ 8173 8174 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW, 8175 100, 100, 200, 200, 0, 0, 0, NULL); 8176 ok (hparent != 0, "Failed to create parent window\n"); 8177 8178 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE | WS_BORDER, 8179 10, 10, 100, 100, hparent, 0, 0, NULL); 8180 ok (hchild != 0, "Failed to create child window\n"); 8181 8182 ShowWindow( hparent, SW_SHOW ); 8183 UpdateWindow( hparent ); 8184 UpdateWindow( hchild ); 8185 flush_events(); 8186 flush_sequence(); 8187 log_all_parent_messages++; 8188 8189 SetRect( &rect, 0, 0, 50, 50 ); 8190 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); 8191 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW | RDW_ALLCHILDREN ); 8192 ok_sequence( WmInvalidateParentChild, "InvalidateParentChild", FALSE ); 8193 8194 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); 8195 pt.x = pt.y = 0; 8196 MapWindowPoints( hchild, hparent, &pt, 1 ); 8197 SetRectRgn( hrgn, 0, 0, 50 - pt.x, 50 - pt.y ); 8198 check_update_rgn( hchild, hrgn ); 8199 SetRectRgn( hrgn, 0, 0, 50, 50 ); 8200 check_update_rgn( hparent, hrgn ); 8201 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW ); 8202 ok_sequence( WmInvalidateParent, "InvalidateParent", FALSE ); 8203 RedrawWindow( hchild, NULL, 0, RDW_ERASENOW ); 8204 ok_sequence( WmEmptySeq, "EraseNow child", FALSE ); 8205 8206 flush_events(); 8207 ok_sequence( WmParentPaintNc, "WmParentPaintNc", FALSE ); 8208 8209 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN ); 8210 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW ); 8211 ok_sequence( WmInvalidateParent, "InvalidateParent2", FALSE ); 8212 RedrawWindow( hchild, NULL, 0, RDW_ERASENOW ); 8213 ok_sequence( WmEmptySeq, "EraseNow child", FALSE ); 8214 8215 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE ); 8216 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW | RDW_ALLCHILDREN ); 8217 ok_sequence( WmInvalidateParentChild2, "InvalidateParentChild2", FALSE ); 8218 8219 SetWindowLongA( hparent, GWL_STYLE, GetWindowLongA(hparent,GWL_STYLE) | WS_CLIPCHILDREN ); 8220 flush_sequence(); 8221 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN ); 8222 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW ); 8223 ok_sequence( WmInvalidateParentChild, "InvalidateParentChild3", FALSE ); 8224 8225 /* flush all paint messages */ 8226 flush_events(); 8227 flush_sequence(); 8228 8229 /* RDW_UPDATENOW on child with WS_CLIPCHILDREN doesn't change corresponding parent area */ 8230 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN ); 8231 SetRectRgn( hrgn, 0, 0, 50, 50 ); 8232 check_update_rgn( hparent, hrgn ); 8233 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW ); 8234 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE ); 8235 SetRectRgn( hrgn, 0, 0, 50, 50 ); 8236 check_update_rgn( hparent, hrgn ); 8237 8238 /* flush all paint messages */ 8239 flush_events(); 8240 SetWindowLongA( hparent, GWL_STYLE, GetWindowLongA(hparent,GWL_STYLE) & ~WS_CLIPCHILDREN ); 8241 flush_sequence(); 8242 8243 /* RDW_UPDATENOW on child without WS_CLIPCHILDREN will validate corresponding parent area */ 8244 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); 8245 SetRectRgn( hrgn, 0, 0, 50, 50 ); 8246 check_update_rgn( hparent, hrgn ); 8247 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW ); 8248 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE ); 8249 SetRectRgn( hrgn2, 10, 10, 50, 50 ); 8250 CombineRgn( hrgn, hrgn, hrgn2, RGN_DIFF ); 8251 check_update_rgn( hparent, hrgn ); 8252 /* flush all paint messages */ 8253 flush_events(); 8254 flush_sequence(); 8255 8256 /* same as above but parent gets completely validated */ 8257 SetRect( &rect, 20, 20, 30, 30 ); 8258 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); 8259 SetRectRgn( hrgn, 20, 20, 30, 30 ); 8260 check_update_rgn( hparent, hrgn ); 8261 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW ); 8262 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE ); 8263 check_update_rgn( hparent, 0 ); /* no update region */ 8264 flush_events(); 8265 ok_sequence( WmEmptySeq, "WmEmpty", FALSE ); /* and no paint messages */ 8266 8267 /* make sure RDW_VALIDATE on child doesn't have the same effect */ 8268 flush_sequence(); 8269 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); 8270 SetRectRgn( hrgn, 20, 20, 30, 30 ); 8271 check_update_rgn( hparent, hrgn ); 8272 RedrawWindow( hchild, NULL, 0, RDW_VALIDATE | RDW_NOERASE ); 8273 SetRectRgn( hrgn, 20, 20, 30, 30 ); 8274 check_update_rgn( hparent, hrgn ); 8275 8276 /* same as above but normal WM_PAINT doesn't validate parent */ 8277 flush_sequence(); 8278 SetRect( &rect, 20, 20, 30, 30 ); 8279 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); 8280 SetRectRgn( hrgn, 20, 20, 30, 30 ); 8281 check_update_rgn( hparent, hrgn ); 8282 /* no WM_PAINT in child while parent still pending */ 8283 while (PeekMessageA( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 8284 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE ); 8285 while (PeekMessageA( &msg, hparent, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 8286 ok_sequence( WmParentErasePaint, "WmParentErasePaint", FALSE ); 8287 8288 flush_sequence(); 8289 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); 8290 /* no WM_PAINT in child while parent still pending */ 8291 while (PeekMessageA( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 8292 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE ); 8293 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_NOERASE | RDW_NOCHILDREN ); 8294 /* now that parent is valid child should get WM_PAINT */ 8295 while (PeekMessageA( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 8296 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE ); 8297 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 8298 ok_sequence( WmEmptySeq, "No other message", FALSE ); 8299 8300 /* same thing with WS_CLIPCHILDREN in parent */ 8301 flush_sequence(); 8302 SetWindowLongA( hparent, GWL_STYLE, GetWindowLongA(hparent,GWL_STYLE) | WS_CLIPCHILDREN ); 8303 ok_sequence( WmSetParentStyle, "WmSetParentStyle", FALSE ); 8304 /* changing style invalidates non client area, but we need to invalidate something else to see it */ 8305 RedrawWindow( hparent, &rect, 0, RDW_UPDATENOW ); 8306 ok_sequence( WmEmptySeq, "No message", FALSE ); 8307 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_UPDATENOW ); 8308 ok_sequence( WmParentOnlyNcPaint, "WmParentOnlyNcPaint", FALSE ); 8309 8310 flush_sequence(); 8311 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN ); 8312 SetRectRgn( hrgn, 20, 20, 30, 30 ); 8313 check_update_rgn( hparent, hrgn ); 8314 /* no WM_PAINT in child while parent still pending */ 8315 while (PeekMessageA( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 8316 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE ); 8317 /* WM_PAINT in parent first */ 8318 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 8319 ok_sequence( WmParentPaintNc, "WmParentPaintNc2", FALSE ); 8320 8321 /* no RDW_ERASE in parent still causes RDW_ERASE and RDW_FRAME in child */ 8322 flush_sequence(); 8323 SetRect( &rect, 0, 0, 30, 30 ); 8324 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ALLCHILDREN ); 8325 SetRectRgn( hrgn, 0, 0, 30, 30 ); 8326 check_update_rgn( hparent, hrgn ); 8327 flush_events(); 8328 ok_sequence( WmParentPaintNc, "WmParentPaintNc3", FALSE ); 8329 8330 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */ 8331 flush_sequence(); 8332 SetRect( &rect, -10, 0, 30, 30 ); 8333 RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE ); 8334 SetRect( &rect, 0, 0, 20, 20 ); 8335 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_ALLCHILDREN ); 8336 RedrawWindow( hparent, NULL, 0, RDW_UPDATENOW ); 8337 ok_sequence( WmChildPaintNc, "WmChildPaintNc", FALSE ); 8338 8339 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */ 8340 flush_sequence(); 8341 SetRect( &rect, -10, 0, 30, 30 ); 8342 RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE ); 8343 SetRect( &rect, 0, 0, 100, 100 ); 8344 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_ALLCHILDREN ); 8345 RedrawWindow( hparent, NULL, 0, RDW_UPDATENOW ); 8346 ok_sequence( WmEmptySeq, "WmChildPaintNc2", FALSE ); 8347 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW ); 8348 ok_sequence( WmEmptySeq, "WmChildPaintNc3", FALSE ); 8349 8350 /* WS_CLIPCHILDREN doesn't exclude children from update region */ 8351 flush_sequence(); 8352 RedrawWindow( hparent, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_NOCHILDREN ); 8353 GetClientRect( hparent, &rect ); 8354 SetRectRgn( hrgn, rect.left, rect.top, rect.right, rect.bottom ); 8355 check_update_rgn( hparent, hrgn ); 8356 flush_events(); 8357 8358 RedrawWindow( hparent, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN ); 8359 GetClientRect( hparent, &rect ); 8360 SetRectRgn( hrgn, rect.left, rect.top, rect.right, rect.bottom ); 8361 check_update_rgn( hparent, hrgn ); 8362 flush_events(); 8363 8364 /* test RDW_INTERNALPAINT behavior */ 8365 8366 flush_sequence(); 8367 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT | RDW_NOCHILDREN ); 8368 flush_events(); 8369 ok_sequence( WmParentOnlyPaint, "WmParentOnlyPaint", FALSE ); 8370 8371 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT | RDW_ALLCHILDREN ); 8372 flush_events(); 8373 ok_sequence( WmParentPaint, "WmParentPaint", FALSE ); 8374 8375 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT ); 8376 flush_events(); 8377 ok_sequence( WmParentOnlyPaint, "WmParentOnlyPaint", FALSE ); 8378 8379 assert( GetWindowLongA(hparent, GWL_STYLE) & WS_CLIPCHILDREN ); 8380 UpdateWindow( hparent ); 8381 flush_events(); 8382 flush_sequence(); 8383 trace("testing SWP_FRAMECHANGED on parent with WS_CLIPCHILDREN\n"); 8384 RedrawWindow( hchild, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); 8385 SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | 8386 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED ); 8387 flush_events(); 8388 ok_sequence(WmSWP_FrameChanged_clip, "SetWindowPos:FrameChanged_clip", FALSE ); 8389 8390 UpdateWindow( hparent ); 8391 flush_events(); 8392 flush_sequence(); 8393 trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent with WS_CLIPCHILDREN\n"); 8394 RedrawWindow( hchild, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); 8395 SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_DEFERERASE | 8396 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED ); 8397 flush_events(); 8398 ok_sequence(WmSWP_FrameChangedDeferErase, "SetWindowPos:FrameChangedDeferErase", FALSE ); 8399 8400 SetWindowLongA( hparent, GWL_STYLE, GetWindowLongA(hparent,GWL_STYLE) & ~WS_CLIPCHILDREN ); 8401 ok_sequence( WmSetParentStyle, "WmSetParentStyle", FALSE ); 8402 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT ); 8403 flush_events(); 8404 ok_sequence( WmParentPaint, "WmParentPaint", FALSE ); 8405 8406 assert( !(GetWindowLongA(hparent, GWL_STYLE) & WS_CLIPCHILDREN) ); 8407 UpdateWindow( hparent ); 8408 flush_events(); 8409 flush_sequence(); 8410 trace("testing SWP_FRAMECHANGED on parent without WS_CLIPCHILDREN\n"); 8411 RedrawWindow( hchild, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); 8412 SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | 8413 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED ); 8414 flush_events(); 8415 ok_sequence(WmSWP_FrameChanged_noclip, "SetWindowPos:FrameChanged_noclip", FALSE ); 8416 8417 UpdateWindow( hparent ); 8418 flush_events(); 8419 flush_sequence(); 8420 trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent without WS_CLIPCHILDREN\n"); 8421 RedrawWindow( hchild, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); 8422 SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_DEFERERASE | 8423 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED ); 8424 flush_events(); 8425 ok_sequence(WmSWP_FrameChangedDeferErase, "SetWindowPos:FrameChangedDeferErase", FALSE ); 8426 8427 ok(GetWindowLongA( hparent, GWL_STYLE ) & WS_VISIBLE, "parent should be visible\n"); 8428 ok(GetWindowLongA( hchild, GWL_STYLE ) & WS_VISIBLE, "child should be visible\n"); 8429 8430 UpdateWindow( hparent ); 8431 flush_events(); 8432 flush_sequence(); 8433 trace("testing SetWindowPos(-10000, -10000) on child\n"); 8434 SetWindowPos( hchild, 0, -10000, -10000, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER ); 8435 check_update_rgn( hchild, 0 ); 8436 flush_events(); 8437 8438 #if 0 /* this one doesn't pass under Wine yet */ 8439 UpdateWindow( hparent ); 8440 flush_events(); 8441 flush_sequence(); 8442 trace("testing ShowWindow(SW_MINIMIZE) on child\n"); 8443 ShowWindow( hchild, SW_MINIMIZE ); 8444 check_update_rgn( hchild, 0 ); 8445 flush_events(); 8446 #endif 8447 8448 UpdateWindow( hparent ); 8449 flush_events(); 8450 flush_sequence(); 8451 trace("testing SetWindowPos(-10000, -10000) on parent\n"); 8452 SetWindowPos( hparent, 0, -10000, -10000, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER ); 8453 check_update_rgn( hparent, 0 ); 8454 flush_events(); 8455 8456 log_all_parent_messages--; 8457 DestroyWindow( hparent ); 8458 ok(!IsWindow(hchild), "child must be destroyed with its parent\n"); 8459 8460 /* tests for moving windows off-screen (needs simple WS_POPUP windows) */ 8461 8462 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_POPUP | WS_VISIBLE, 8463 100, 100, 200, 200, 0, 0, 0, NULL); 8464 ok (hparent != 0, "Failed to create parent window\n"); 8465 8466 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE, 8467 10, 10, 100, 100, hparent, 0, 0, NULL); 8468 ok (hchild != 0, "Failed to create child window\n"); 8469 8470 ShowWindow( hparent, SW_SHOW ); 8471 UpdateWindow( hparent ); 8472 UpdateWindow( hchild ); 8473 flush_events(); 8474 flush_sequence(); 8475 8476 /* moving child outside of parent boundaries changes update region */ 8477 SetRect( &rect, 0, 0, 40, 40 ); 8478 RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_ERASE ); 8479 SetRectRgn( hrgn, 0, 0, 40, 40 ); 8480 check_update_rgn( hchild, hrgn ); 8481 MoveWindow( hchild, -10, 10, 100, 100, FALSE ); 8482 SetRectRgn( hrgn, 10, 0, 40, 40 ); 8483 check_update_rgn( hchild, hrgn ); 8484 MoveWindow( hchild, -10, -10, 100, 100, FALSE ); 8485 SetRectRgn( hrgn, 10, 10, 40, 40 ); 8486 check_update_rgn( hchild, hrgn ); 8487 8488 /* moving parent off-screen does too */ 8489 SetRect( &rect, 0, 0, 100, 100 ); 8490 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_NOCHILDREN ); 8491 SetRectRgn( hrgn, 0, 0, 100, 100 ); 8492 check_update_rgn( hparent, hrgn ); 8493 SetRectRgn( hrgn, 10, 10, 40, 40 ); 8494 check_update_rgn( hchild, hrgn ); 8495 MoveWindow( hparent, -20, -20, 200, 200, FALSE ); 8496 GetUpdateRect( hparent, &rect2, FALSE ); 8497 if (!EqualRect( &rect2, &rect )) /* Win 8 and later don't crop update to screen */ 8498 { 8499 rect.left += 20; 8500 rect.top += 20; 8501 } 8502 SetRectRgn( hrgn, rect.left, rect.top, rect.right, rect.bottom ); 8503 check_update_rgn( hparent, hrgn ); 8504 SetRectRgn( hrgn, rect.left + 10, rect.top + 10, 40, 40 ); 8505 check_update_rgn( hchild, hrgn ); 8506 8507 /* invalidated region is cropped by the parent rects */ 8508 SetRect( &rect, 0, 0, 50, 50 ); 8509 RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_ERASE ); 8510 SetRectRgn( hrgn, rect2.left + 10, rect2.top + 10, 50, 50 ); 8511 check_update_rgn( hchild, hrgn ); 8512 8513 DestroyWindow( hparent ); 8514 ok(!IsWindow(hchild), "child must be destroyed with its parent\n"); 8515 flush_sequence(); 8516 8517 DeleteObject( hrgn ); 8518 DeleteObject( hrgn2 ); 8519 } 8520 8521 struct wnd_event 8522 { 8523 HWND hwnd; 8524 HANDLE grand_child; 8525 HANDLE start_event; 8526 HANDLE stop_event; 8527 }; 8528 8529 static DWORD WINAPI thread_proc(void *param) 8530 { 8531 MSG msg; 8532 struct wnd_event *wnd_event = param; 8533 8534 wnd_event->hwnd = CreateWindowExA(0, "TestWindowClass", "window caption text", WS_OVERLAPPEDWINDOW, 8535 100, 100, 200, 200, 0, 0, 0, NULL); 8536 ok(wnd_event->hwnd != 0, "Failed to create overlapped window\n"); 8537 8538 SetEvent(wnd_event->start_event); 8539 8540 while (GetMessageA(&msg, 0, 0, 0)) 8541 { 8542 TranslateMessage(&msg); 8543 DispatchMessageA(&msg); 8544 } 8545 8546 ok(IsWindow(wnd_event->hwnd), "window should still exist\n"); 8547 8548 return 0; 8549 } 8550 8551 static DWORD CALLBACK create_grand_child_thread( void *param ) 8552 { 8553 struct wnd_event *wnd_event = param; 8554 HWND hchild; 8555 MSG msg; 8556 8557 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", 8558 WS_CHILD | WS_VISIBLE, 0, 0, 10, 10, wnd_event->hwnd, 0, 0, NULL); 8559 ok (hchild != 0, "Failed to create child window\n"); 8560 flush_events(); 8561 flush_sequence(); 8562 SetEvent( wnd_event->start_event ); 8563 8564 for (;;) 8565 { 8566 MsgWaitForMultipleObjects(0, NULL, FALSE, 1000, QS_ALLINPUT); 8567 if (!IsWindow( hchild )) break; /* will be destroyed when parent thread exits */ 8568 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 8569 } 8570 return 0; 8571 } 8572 8573 static DWORD CALLBACK create_child_thread( void *param ) 8574 { 8575 struct wnd_event *wnd_event = param; 8576 struct wnd_event child_event; 8577 DWORD ret, tid; 8578 MSG msg; 8579 8580 child_event.hwnd = CreateWindowExA(0, "TestWindowClass", "Test child", 8581 WS_CHILD | WS_VISIBLE, 0, 0, 10, 10, wnd_event->hwnd, 0, 0, NULL); 8582 ok (child_event.hwnd != 0, "Failed to create child window\n"); 8583 SetFocus( child_event.hwnd ); 8584 flush_events(); 8585 flush_sequence(); 8586 child_event.start_event = wnd_event->start_event; 8587 wnd_event->grand_child = CreateThread(NULL, 0, create_grand_child_thread, &child_event, 0, &tid); 8588 for (;;) 8589 { 8590 DWORD ret = MsgWaitForMultipleObjects(1, &child_event.start_event, FALSE, 1000, QS_SENDMESSAGE); 8591 if (ret != 1) break; 8592 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 8593 } 8594 ret = WaitForSingleObject( wnd_event->stop_event, 5000 ); 8595 ok( !ret, "WaitForSingleObject failed %x\n", ret ); 8596 return 0; 8597 } 8598 8599 static const char manifest_dep[] = 8600 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">" 8601 "<assemblyIdentity version=\"1.2.3.4\" name=\"testdep1\" type=\"win32\" processorArchitecture=\"" ARCH "\"/>" 8602 " <file name=\"testdep.dll\" />" 8603 "</assembly>"; 8604 8605 static const char manifest_main[] = 8606 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">" 8607 "<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\" />" 8608 "<dependency>" 8609 " <dependentAssembly>" 8610 " <assemblyIdentity type=\"win32\" name=\"testdep1\" version=\"1.2.3.4\" processorArchitecture=\"" ARCH "\" />" 8611 " </dependentAssembly>" 8612 "</dependency>" 8613 "</assembly>"; 8614 8615 static void create_manifest_file(const char *filename, const char *manifest) 8616 { 8617 WCHAR path[MAX_PATH]; 8618 HANDLE file; 8619 DWORD size; 8620 8621 MultiByteToWideChar( CP_ACP, 0, filename, -1, path, MAX_PATH ); 8622 file = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 8623 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError()); 8624 WriteFile(file, manifest, strlen(manifest), &size, NULL); 8625 CloseHandle(file); 8626 } 8627 8628 static HANDLE test_create(const char *file) 8629 { 8630 WCHAR path[MAX_PATH]; 8631 ACTCTXW actctx; 8632 HANDLE handle; 8633 8634 MultiByteToWideChar(CP_ACP, 0, file, -1, path, MAX_PATH); 8635 memset(&actctx, 0, sizeof(ACTCTXW)); 8636 actctx.cbSize = sizeof(ACTCTXW); 8637 actctx.lpSource = path; 8638 8639 handle = pCreateActCtxW(&actctx); 8640 ok(handle != INVALID_HANDLE_VALUE, "failed to create context, error %u\n", GetLastError()); 8641 8642 ok(actctx.cbSize == sizeof(actctx), "cbSize=%d\n", actctx.cbSize); 8643 ok(actctx.dwFlags == 0, "dwFlags=%d\n", actctx.dwFlags); 8644 ok(actctx.lpSource == path, "lpSource=%p\n", actctx.lpSource); 8645 ok(actctx.wProcessorArchitecture == 0, "wProcessorArchitecture=%d\n", actctx.wProcessorArchitecture); 8646 ok(actctx.wLangId == 0, "wLangId=%d\n", actctx.wLangId); 8647 ok(actctx.lpAssemblyDirectory == NULL, "lpAssemblyDirectory=%p\n", actctx.lpAssemblyDirectory); 8648 ok(actctx.lpResourceName == NULL, "lpResourceName=%p\n", actctx.lpResourceName); 8649 ok(actctx.lpApplicationName == NULL, "lpApplicationName=%p\n", actctx.lpApplicationName); 8650 ok(actctx.hModule == NULL, "hModule=%p\n", actctx.hModule); 8651 8652 return handle; 8653 } 8654 8655 static void test_interthread_messages(void) 8656 { 8657 HANDLE hThread, context, handle, event; 8658 ULONG_PTR cookie; 8659 DWORD tid; 8660 WNDPROC proc; 8661 MSG msg; 8662 char buf[256]; 8663 int len, expected_len; 8664 struct wnd_event wnd_event; 8665 BOOL ret; 8666 8667 wnd_event.start_event = CreateEventW(NULL, 0, 0, NULL); 8668 if (!wnd_event.start_event) 8669 { 8670 win_skip("skipping interthread message test under win9x\n"); 8671 return; 8672 } 8673 8674 hThread = CreateThread(NULL, 0, thread_proc, &wnd_event, 0, &tid); 8675 ok(hThread != NULL, "CreateThread failed, error %d\n", GetLastError()); 8676 8677 ok(WaitForSingleObject(wnd_event.start_event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 8678 8679 CloseHandle(wnd_event.start_event); 8680 8681 SetLastError(0xdeadbeef); 8682 ok(!DestroyWindow(wnd_event.hwnd), "DestroyWindow succeeded\n"); 8683 ok(GetLastError() == ERROR_ACCESS_DENIED || GetLastError() == 0xdeadbeef, 8684 "wrong error code %d\n", GetLastError()); 8685 8686 proc = (WNDPROC)GetWindowLongPtrA(wnd_event.hwnd, GWLP_WNDPROC); 8687 ok(proc != NULL, "GetWindowLongPtrA(GWLP_WNDPROC) error %d\n", GetLastError()); 8688 8689 expected_len = lstrlenA("window caption text"); 8690 memset(buf, 0, sizeof(buf)); 8691 SetLastError(0xdeadbeef); 8692 len = CallWindowProcA(proc, wnd_event.hwnd, WM_GETTEXT, sizeof(buf), (LPARAM)buf); 8693 ok(len == expected_len, "CallWindowProcA(WM_GETTEXT) error %d, len %d, expected len %d\n", GetLastError(), len, expected_len); 8694 ok(!lstrcmpA(buf, "window caption text"), "window text mismatch\n"); 8695 8696 msg.hwnd = wnd_event.hwnd; 8697 msg.message = WM_GETTEXT; 8698 msg.wParam = sizeof(buf); 8699 msg.lParam = (LPARAM)buf; 8700 memset(buf, 0, sizeof(buf)); 8701 SetLastError(0xdeadbeef); 8702 len = DispatchMessageA(&msg); 8703 ok((!len && GetLastError() == ERROR_MESSAGE_SYNC_ONLY) || broken(len), /* nt4 */ 8704 "DispatchMessageA(WM_GETTEXT) succeeded on another thread window: ret %d, error %d\n", len, GetLastError()); 8705 8706 /* the following test causes an exception in user.exe under win9x */ 8707 msg.hwnd = wnd_event.hwnd; 8708 msg.message = WM_TIMER; 8709 msg.wParam = 0; 8710 msg.lParam = GetWindowLongPtrA(wnd_event.hwnd, GWLP_WNDPROC); 8711 SetLastError(0xdeadbeef); 8712 len = DispatchMessageA(&msg); 8713 ok(!len && GetLastError() == 0xdeadbeef, 8714 "DispatchMessageA(WM_TIMER) failed on another thread window: ret %d, error %d\n", len, GetLastError()); 8715 8716 ret = PostMessageA(wnd_event.hwnd, WM_QUIT, 0, 0); 8717 ok( ret, "PostMessageA(WM_QUIT) error %d\n", GetLastError()); 8718 8719 ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 8720 CloseHandle(hThread); 8721 8722 ok(!IsWindow(wnd_event.hwnd), "window should be destroyed on thread exit\n"); 8723 8724 wnd_event.hwnd = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 8725 100, 100, 200, 200, 0, 0, 0, NULL); 8726 ok (wnd_event.hwnd != 0, "Failed to create parent window\n"); 8727 flush_events(); 8728 flush_sequence(); 8729 log_all_parent_messages++; 8730 wnd_event.start_event = CreateEventA( NULL, TRUE, FALSE, NULL ); 8731 wnd_event.stop_event = CreateEventA( NULL, TRUE, FALSE, NULL ); 8732 hThread = CreateThread( NULL, 0, create_child_thread, &wnd_event, 0, &tid ); 8733 for (;;) 8734 { 8735 ret = MsgWaitForMultipleObjects(1, &wnd_event.start_event, FALSE, 1000, QS_SENDMESSAGE); 8736 if (ret != 1) break; 8737 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 8738 } 8739 ok( !ret, "MsgWaitForMultipleObjects failed %x\n", ret ); 8740 /* now wait for the thread without processing messages; this shouldn't deadlock */ 8741 SetEvent( wnd_event.stop_event ); 8742 ret = WaitForSingleObject( hThread, 5000 ); 8743 ok( !ret, "WaitForSingleObject failed %x\n", ret ); 8744 CloseHandle( hThread ); 8745 8746 ret = WaitForSingleObject( wnd_event.grand_child, 5000 ); 8747 ok( !ret, "WaitForSingleObject failed %x\n", ret ); 8748 CloseHandle( wnd_event.grand_child ); 8749 8750 CloseHandle( wnd_event.start_event ); 8751 CloseHandle( wnd_event.stop_event ); 8752 flush_events(); 8753 ok_sequence(WmExitThreadSeq, "destroy child on thread exit", FALSE); 8754 log_all_parent_messages--; 8755 DestroyWindow( wnd_event.hwnd ); 8756 8757 /* activation context tests */ 8758 if (!pActivateActCtx) 8759 { 8760 win_skip("Activation contexts are not supported, skipping\n"); 8761 return; 8762 } 8763 8764 create_manifest_file("testdep1.manifest", manifest_dep); 8765 create_manifest_file("main.manifest", manifest_main); 8766 8767 context = test_create("main.manifest"); 8768 DeleteFileA("testdep1.manifest"); 8769 DeleteFileA("main.manifest"); 8770 8771 handle = (void*)0xdeadbeef; 8772 ret = pGetCurrentActCtx(&handle); 8773 ok(ret, "GetCurrentActCtx failed: %u\n", GetLastError()); 8774 ok(handle == 0, "active context %p\n", handle); 8775 8776 wnd_event.start_event = CreateEventW(NULL, 0, 0, NULL); 8777 hThread = CreateThread(NULL, 0, thread_proc, &wnd_event, 0, &tid); 8778 ok(hThread != NULL, "CreateThread failed, error %d\n", GetLastError()); 8779 ok(WaitForSingleObject(wnd_event.start_event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 8780 CloseHandle(wnd_event.start_event); 8781 8782 /* context is activated after thread creation, so it doesn't inherit it by default */ 8783 ret = pActivateActCtx(context, &cookie); 8784 ok(ret, "activation failed: %u\n", GetLastError()); 8785 8786 handle = 0; 8787 ret = pGetCurrentActCtx(&handle); 8788 ok(ret, "GetCurrentActCtx failed: %u\n", GetLastError()); 8789 ok(handle != 0, "active context %p\n", handle); 8790 pReleaseActCtx(handle); 8791 8792 /* destination window will test for active context */ 8793 ret = SendMessageA(wnd_event.hwnd, WM_USER+10, 0, 0); 8794 ok(ret, "thread window returned %d\n", ret); 8795 8796 event = CreateEventW(NULL, 0, 0, NULL); 8797 ret = PostMessageA(wnd_event.hwnd, WM_USER+10, 0, (LPARAM)event); 8798 ok(ret, "thread window returned %d\n", ret); 8799 ok(WaitForSingleObject(event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 8800 CloseHandle(event); 8801 8802 ret = PostMessageA(wnd_event.hwnd, WM_QUIT, 0, 0); 8803 ok(ret, "PostMessageA(WM_QUIT) error %d\n", GetLastError()); 8804 8805 ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 8806 CloseHandle(hThread); 8807 8808 ret = pDeactivateActCtx(0, cookie); 8809 ok(ret, "DeactivateActCtx failed: %u\n", GetLastError()); 8810 pReleaseActCtx(context); 8811 } 8812 8813 8814 static const struct message WmVkN[] = { 8815 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */ 8816 { WM_KEYDOWN, wparam|lparam, 'N', 1 }, 8817 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 }, 8818 { WM_CHAR, wparam|lparam, 'n', 1 }, 8819 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1002,1), 0 }, 8820 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */ 8821 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 }, 8822 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 }, 8823 { 0 } 8824 }; 8825 static const struct message WmShiftVkN[] = { 8826 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 1 }, /* XP */ 8827 { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 1 }, 8828 { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 1 }, 8829 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */ 8830 { WM_KEYDOWN, wparam|lparam, 'N', 1 }, 8831 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 }, 8832 { WM_CHAR, wparam|lparam, 'N', 1 }, 8833 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1001,1), 0 }, 8834 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */ 8835 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 }, 8836 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 }, 8837 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0xc0000001 }, /* XP */ 8838 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xc0000001 }, 8839 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xc0000001 }, 8840 { 0 } 8841 }; 8842 static const struct message WmCtrlVkN[] = { 8843 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 1 }, /* XP */ 8844 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 }, 8845 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 }, 8846 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */ 8847 { WM_KEYDOWN, wparam|lparam, 'N', 1 }, 8848 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 }, 8849 { WM_CHAR, wparam|lparam, 0x000e, 1 }, 8850 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1000,1), 0 }, 8851 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */ 8852 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 }, 8853 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 }, 8854 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 0xc0000001 }, /* XP */ 8855 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 }, 8856 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 }, 8857 { 0 } 8858 }; 8859 static const struct message WmCtrlVkN_2[] = { 8860 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 1 }, /* XP */ 8861 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 }, 8862 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 }, 8863 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */ 8864 { WM_KEYDOWN, wparam|lparam, 'N', 1 }, 8865 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1000,1), 0 }, 8866 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */ 8867 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 }, 8868 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 }, 8869 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 0xc0000001 }, /* XP */ 8870 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 }, 8871 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 }, 8872 { 0 } 8873 }; 8874 static const struct message WmAltVkN[] = { 8875 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, /* XP */ 8876 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 }, 8877 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, 8878 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0x20000001 }, /* XP */ 8879 { WM_SYSKEYDOWN, wparam|lparam, 'N', 0x20000001 }, 8880 { WM_SYSKEYDOWN, sent|wparam|lparam, 'N', 0x20000001 }, 8881 { WM_SYSCHAR, wparam|lparam, 'n', 0x20000001 }, 8882 { WM_SYSCHAR, sent|wparam|lparam, 'n', 0x20000001 }, 8883 { WM_SYSCOMMAND, sent|defwinproc|wparam|lparam, SC_KEYMENU, 'n' }, 8884 { HCBT_SYSCOMMAND, hook }, 8885 { WM_ENTERMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 }, 8886 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, 8887 { 0x00AE, sent|defwinproc|optional }, /* XP */ 8888 { WM_GETTEXT, sent|defwinproc|optional }, /* XP */ 8889 { WM_INITMENU, sent|defwinproc }, 8890 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 }, 8891 { WM_MENUCHAR, sent|defwinproc|wparam, MAKEWPARAM('n',MF_SYSMENU) }, 8892 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, 8893 { WM_CAPTURECHANGED, sent|defwinproc }, 8894 { WM_MENUSELECT, sent|defwinproc|wparam, MAKEWPARAM(0,0xffff) }, 8895 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 }, 8896 { WM_EXITMENULOOP, sent|defwinproc }, 8897 { WM_MENUSELECT, sent|defwinproc|wparam|optional, MAKEWPARAM(0,0xffff) }, /* Win95 bug */ 8898 { WM_EXITMENULOOP, sent|defwinproc|optional }, /* Win95 bug */ 8899 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xe0000001 }, /* XP */ 8900 { WM_SYSKEYUP, wparam|lparam, 'N', 0xe0000001 }, 8901 { WM_SYSKEYUP, sent|wparam|lparam, 'N', 0xe0000001 }, 8902 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */ 8903 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 }, 8904 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 }, 8905 { 0 } 8906 }; 8907 static const struct message WmAltVkN_2[] = { 8908 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, /* XP */ 8909 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 }, 8910 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, 8911 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0x20000001 }, /* XP */ 8912 { WM_SYSKEYDOWN, wparam|lparam, 'N', 0x20000001 }, 8913 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1003,1), 0 }, 8914 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xe0000001 }, /* XP */ 8915 { WM_SYSKEYUP, wparam|lparam, 'N', 0xe0000001 }, 8916 { WM_SYSKEYUP, sent|wparam|lparam, 'N', 0xe0000001 }, 8917 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */ 8918 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 }, 8919 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 }, 8920 { 0 } 8921 }; 8922 static const struct message WmCtrlAltVkN[] = { 8923 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 1 }, /* XP */ 8924 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 }, 8925 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 }, 8926 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, /* XP */ 8927 { WM_KEYDOWN, wparam|lparam, VK_MENU, 0x20000001 }, 8928 { WM_KEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, 8929 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0x20000001 }, /* XP */ 8930 { WM_KEYDOWN, wparam|lparam, 'N', 0x20000001 }, 8931 { WM_KEYDOWN, sent|wparam|lparam, 'N', 0x20000001 }, 8932 { WM_CHAR, optional }, 8933 { WM_CHAR, sent|optional }, 8934 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xe0000001 }, /* XP */ 8935 { WM_KEYUP, wparam|lparam, 'N', 0xe0000001 }, 8936 { WM_KEYUP, sent|wparam|lparam, 'N', 0xe0000001 }, 8937 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */ 8938 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 }, 8939 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 }, 8940 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 0xc0000001 }, /* XP */ 8941 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 }, 8942 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 }, 8943 { 0 } 8944 }; 8945 static const struct message WmCtrlShiftVkN[] = { 8946 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 1 }, /* XP */ 8947 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 }, 8948 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 }, 8949 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 1 }, /* XP */ 8950 { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 1 }, 8951 { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 1 }, 8952 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */ 8953 { WM_KEYDOWN, wparam|lparam, 'N', 1 }, 8954 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1004,1), 0 }, 8955 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */ 8956 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 }, 8957 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 }, 8958 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0xc0000001 }, /* XP */ 8959 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xc0000001 }, 8960 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xc0000001 }, 8961 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 0xc0000001 }, /* XP */ 8962 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 }, 8963 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 }, 8964 { 0 } 8965 }; 8966 static const struct message WmCtrlAltShiftVkN[] = { 8967 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 1 }, /* XP */ 8968 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 }, 8969 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 }, 8970 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, /* XP */ 8971 { WM_KEYDOWN, wparam|lparam, VK_MENU, 0x20000001 }, 8972 { WM_KEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, 8973 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0x20000001 }, /* XP */ 8974 { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 0x20000001 }, 8975 { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 0x20000001 }, 8976 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0x20000001 }, /* XP */ 8977 { WM_KEYDOWN, wparam|lparam, 'N', 0x20000001 }, 8978 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1005,1), 0 }, 8979 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xe0000001 }, /* XP */ 8980 { WM_KEYUP, wparam|lparam, 'N', 0xe0000001 }, 8981 { WM_KEYUP, sent|wparam|lparam, 'N', 0xe0000001 }, 8982 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0xe0000001 }, /* XP */ 8983 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xe0000001 }, 8984 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xe0000001 }, 8985 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */ 8986 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 }, 8987 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 }, 8988 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 0xc0000001 }, /* XP */ 8989 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 }, 8990 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 }, 8991 { 0 } 8992 }; 8993 static const struct message WmAltPressRelease[] = { 8994 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, /* XP */ 8995 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 }, 8996 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, 8997 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */ 8998 { WM_SYSKEYUP, wparam|lparam, VK_MENU, 0xc0000001 }, 8999 { WM_SYSKEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 }, 9000 { WM_SYSCOMMAND, sent|defwinproc|wparam|lparam, SC_KEYMENU, 0 }, 9001 { HCBT_SYSCOMMAND, hook }, 9002 { WM_ENTERMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 }, 9003 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, 9004 { WM_INITMENU, sent|defwinproc }, 9005 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 }, 9006 { WM_MENUSELECT, sent|defwinproc|wparam, MAKEWPARAM(0,MF_SYSMENU|MF_POPUP|MF_HILITE), 0, MAKEWPARAM(0,MF_RIGHTJUSTIFY) }, 9007 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 }, 9008 9009 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x30000001 }, /* XP */ 9010 9011 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 }, 9012 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0, }, 9013 { WM_CAPTURECHANGED, sent|defwinproc }, 9014 { WM_MENUSELECT, sent|defwinproc|wparam|optional, MAKEWPARAM(0,0xffff) }, 9015 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 }, 9016 { WM_EXITMENULOOP, sent|defwinproc }, 9017 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */ 9018 { WM_SYSKEYUP, wparam|lparam, VK_MENU, 0xc0000001 }, 9019 { WM_SYSKEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 }, 9020 { 0 } 9021 }; 9022 static const struct message WmShiftMouseButton[] = { 9023 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 1 }, /* XP */ 9024 { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 1 }, 9025 { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 1 }, 9026 { WM_MOUSEMOVE, wparam|optional, 0, 0 }, 9027 { WM_MOUSEMOVE, sent|wparam|optional, 0, 0 }, 9028 { WM_LBUTTONDOWN, wparam, MK_LBUTTON|MK_SHIFT, 0 }, 9029 { WM_LBUTTONDOWN, sent|wparam, MK_LBUTTON|MK_SHIFT, 0 }, 9030 { WM_LBUTTONUP, wparam, MK_SHIFT, 0 }, 9031 { WM_LBUTTONUP, sent|wparam, MK_SHIFT, 0 }, 9032 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0xc0000001 }, /* XP */ 9033 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xc0000001 }, 9034 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xc0000001 }, 9035 { 0 } 9036 }; 9037 static const struct message WmF1Seq[] = { 9038 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F1, 1 }, /* XP */ 9039 { WM_KEYDOWN, wparam|lparam, VK_F1, 1 }, 9040 { WM_KEYDOWN, sent|wparam|lparam, VK_F1, 0x00000001 }, 9041 { WM_KEYF1, wparam|lparam, 0, 0 }, 9042 { WM_KEYF1, sent|wparam|lparam, 0, 0 }, 9043 { WM_HELP, sent|defwinproc }, 9044 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F1, 0xc0000001 }, /* XP */ 9045 { WM_KEYUP, wparam|lparam, VK_F1, 0xc0000001 }, 9046 { WM_KEYUP, sent|wparam|lparam, VK_F1, 0xc0000001 }, 9047 { 0 } 9048 }; 9049 static const struct message WmVkAppsSeq[] = { 9050 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_APPS, 1 }, /* XP */ 9051 { WM_KEYDOWN, wparam|lparam, VK_APPS, 1 }, 9052 { WM_KEYDOWN, sent|wparam|lparam, VK_APPS, 0x00000001 }, 9053 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_APPS, 0xc0000001 }, /* XP */ 9054 { WM_KEYUP, wparam|lparam, VK_APPS, 0xc0000001 }, 9055 { WM_KEYUP, sent|wparam|lparam, VK_APPS, 0xc0000001 }, 9056 { WM_CONTEXTMENU, lparam, /*hwnd*/0, -1 }, 9057 { WM_CONTEXTMENU, sent|lparam, /*hwnd*/0, -1 }, 9058 { 0 } 9059 }; 9060 static const struct message WmVkF10Seq[] = { 9061 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 1 }, /* XP */ 9062 { WM_SYSKEYDOWN, wparam|lparam, VK_F10, 1 }, 9063 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_F10, 0x00000001 }, 9064 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 0xc0000001 }, /* XP */ 9065 { WM_SYSKEYUP, wparam|lparam, VK_F10, 0xc0000001 }, 9066 { WM_SYSKEYUP, sent|wparam|lparam, VK_F10, 0xc0000001 }, 9067 { WM_SYSCOMMAND, sent|defwinproc|wparam, SC_KEYMENU }, 9068 { HCBT_SYSCOMMAND, hook }, 9069 { WM_ENTERMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 }, 9070 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, 9071 { WM_INITMENU, sent|defwinproc }, 9072 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 }, 9073 { WM_MENUSELECT, sent|defwinproc|wparam, MAKEWPARAM(0,MF_SYSMENU|MF_POPUP|MF_HILITE), 0, MAKEWPARAM(0,MF_RIGHTJUSTIFY) }, 9074 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 }, 9075 9076 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 0x10000001 }, /* XP */ 9077 9078 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 1 }, /* XP */ 9079 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 }, 9080 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0, }, 9081 { WM_CAPTURECHANGED, sent|defwinproc }, 9082 { WM_MENUSELECT, sent|defwinproc|wparam|optional, MAKEWPARAM(0,0xffff) }, 9083 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 }, 9084 { WM_EXITMENULOOP, sent|defwinproc }, 9085 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 0xc0000001 }, /* XP */ 9086 { WM_SYSKEYUP, wparam|lparam, VK_F10, 0xc0000001 }, 9087 { WM_SYSKEYUP, sent|wparam|lparam, VK_F10, 0xc0000001 }, 9088 { 0 } 9089 }; 9090 static const struct message WmShiftF10Seq[] = { 9091 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 1 }, /* XP */ 9092 { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 1 }, 9093 { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 0x00000001 }, 9094 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 1 }, /* XP */ 9095 { WM_SYSKEYDOWN, wparam|lparam, VK_F10, 1 }, 9096 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_F10, 0x00000001 }, 9097 { WM_CONTEXTMENU, sent|defwinproc|lparam, /*hwnd*/0, -1 }, 9098 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 0xc0000001 }, /* XP */ 9099 { WM_SYSKEYUP, wparam|lparam, VK_F10, 0xc0000001 }, 9100 { WM_SYSKEYUP, sent|wparam|lparam, VK_F10, 0xc0000001 }, 9101 { WM_SYSCOMMAND, sent|defwinproc|wparam, SC_KEYMENU }, 9102 { HCBT_SYSCOMMAND, hook }, 9103 { WM_ENTERMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 }, 9104 { WM_INITMENU, sent|defwinproc }, 9105 { WM_MENUSELECT, sent|defwinproc|wparam, MAKEWPARAM(0,MF_SYSMENU|MF_POPUP|MF_HILITE), 0, MAKEWPARAM(0,MF_RIGHTJUSTIFY) }, 9106 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0xd0000001 }, /* XP */ 9107 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_ESCAPE, 0x10000001 }, /* XP */ 9108 { WM_CAPTURECHANGED, sent|defwinproc|wparam|lparam, 0, 0 }, 9109 { WM_MENUSELECT, sent|defwinproc|wparam|lparam, 0xffff0000, 0 }, 9110 { WM_EXITMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 }, 9111 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_ESCAPE, 0xc0000001 }, /* XP */ 9112 { WM_KEYUP, wparam|lparam, VK_ESCAPE, 0xc0000001 }, 9113 { WM_KEYUP, sent|wparam|lparam, VK_ESCAPE, 0xc0000001 }, 9114 { 0 } 9115 }; 9116 9117 static void pump_msg_loop(HWND hwnd, HACCEL hAccel) 9118 { 9119 MSG msg; 9120 9121 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 9122 { 9123 struct recvd_message log_msg; 9124 9125 /* ignore some unwanted messages */ 9126 if (msg.message == WM_MOUSEMOVE || 9127 msg.message == WM_TIMER || 9128 ignore_message( msg.message )) 9129 continue; 9130 9131 log_msg.hwnd = msg.hwnd; 9132 log_msg.message = msg.message; 9133 log_msg.flags = wparam|lparam; 9134 log_msg.wParam = msg.wParam; 9135 log_msg.lParam = msg.lParam; 9136 log_msg.descr = "accel"; 9137 add_message(&log_msg); 9138 9139 if (!hAccel || !TranslateAcceleratorA(hwnd, hAccel, &msg)) 9140 { 9141 TranslateMessage(&msg); 9142 DispatchMessageA(&msg); 9143 } 9144 } 9145 } 9146 9147 static void test_accelerators(void) 9148 { 9149 RECT rc; 9150 POINT pt; 9151 SHORT state; 9152 HACCEL hAccel; 9153 HWND hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 9154 100, 100, 200, 200, 0, 0, 0, NULL); 9155 BOOL ret; 9156 9157 assert(hwnd != 0); 9158 UpdateWindow(hwnd); 9159 flush_events(); 9160 flush_sequence(); 9161 9162 SetFocus(hwnd); 9163 ok(GetFocus() == hwnd, "wrong focus window %p\n", GetFocus()); 9164 9165 state = GetKeyState(VK_SHIFT); 9166 ok(!(state & 0x8000), "wrong Shift state %04x\n", state); 9167 state = GetKeyState(VK_CAPITAL); 9168 ok(state == 0, "wrong CapsLock state %04x\n", state); 9169 9170 hAccel = LoadAcceleratorsA(GetModuleHandleA(NULL), MAKEINTRESOURCEA(1)); 9171 assert(hAccel != 0); 9172 9173 flush_events(); 9174 pump_msg_loop(hwnd, 0); 9175 flush_sequence(); 9176 9177 trace("testing VK_N press/release\n"); 9178 flush_sequence(); 9179 keybd_event('N', 0, 0, 0); 9180 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 9181 pump_msg_loop(hwnd, hAccel); 9182 if (!sequence_cnt) /* we didn't get any message */ 9183 { 9184 skip( "queuing key events not supported\n" ); 9185 goto done; 9186 } 9187 ok_sequence(WmVkN, "VK_N press/release", FALSE); 9188 9189 trace("testing Shift+VK_N press/release\n"); 9190 flush_sequence(); 9191 keybd_event(VK_SHIFT, 0, 0, 0); 9192 keybd_event('N', 0, 0, 0); 9193 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 9194 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0); 9195 pump_msg_loop(hwnd, hAccel); 9196 ok_sequence(WmShiftVkN, "Shift+VK_N press/release", FALSE); 9197 9198 trace("testing Ctrl+VK_N press/release\n"); 9199 flush_sequence(); 9200 keybd_event(VK_CONTROL, 0, 0, 0); 9201 keybd_event('N', 0, 0, 0); 9202 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 9203 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); 9204 pump_msg_loop(hwnd, hAccel); 9205 ok_sequence(WmCtrlVkN, "Ctrl+VK_N press/release", FALSE); 9206 9207 trace("testing Alt+VK_N press/release\n"); 9208 flush_sequence(); 9209 keybd_event(VK_MENU, 0, 0, 0); 9210 keybd_event('N', 0, 0, 0); 9211 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 9212 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); 9213 pump_msg_loop(hwnd, hAccel); 9214 ok_sequence(WmAltVkN, "Alt+VK_N press/release", FALSE); 9215 9216 trace("testing Ctrl+Alt+VK_N press/release 1\n"); 9217 flush_sequence(); 9218 keybd_event(VK_CONTROL, 0, 0, 0); 9219 keybd_event(VK_MENU, 0, 0, 0); 9220 keybd_event('N', 0, 0, 0); 9221 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 9222 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); 9223 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); 9224 pump_msg_loop(hwnd, hAccel); 9225 ok_sequence(WmCtrlAltVkN, "Ctrl+Alt+VK_N press/release 1", FALSE); 9226 9227 ret = DestroyAcceleratorTable(hAccel); 9228 ok( ret, "DestroyAcceleratorTable error %d\n", GetLastError()); 9229 9230 hAccel = LoadAcceleratorsA(GetModuleHandleA(NULL), MAKEINTRESOURCEA(2)); 9231 assert(hAccel != 0); 9232 9233 trace("testing VK_N press/release\n"); 9234 flush_sequence(); 9235 keybd_event('N', 0, 0, 0); 9236 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 9237 pump_msg_loop(hwnd, hAccel); 9238 ok_sequence(WmVkN, "VK_N press/release", FALSE); 9239 9240 trace("testing Shift+VK_N press/release\n"); 9241 flush_sequence(); 9242 keybd_event(VK_SHIFT, 0, 0, 0); 9243 keybd_event('N', 0, 0, 0); 9244 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 9245 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0); 9246 pump_msg_loop(hwnd, hAccel); 9247 ok_sequence(WmShiftVkN, "Shift+VK_N press/release", FALSE); 9248 9249 trace("testing Ctrl+VK_N press/release 2\n"); 9250 flush_sequence(); 9251 keybd_event(VK_CONTROL, 0, 0, 0); 9252 keybd_event('N', 0, 0, 0); 9253 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 9254 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); 9255 pump_msg_loop(hwnd, hAccel); 9256 ok_sequence(WmCtrlVkN_2, "Ctrl+VK_N press/release 2", FALSE); 9257 9258 trace("testing Alt+VK_N press/release 2\n"); 9259 flush_sequence(); 9260 keybd_event(VK_MENU, 0, 0, 0); 9261 keybd_event('N', 0, 0, 0); 9262 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 9263 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); 9264 pump_msg_loop(hwnd, hAccel); 9265 ok_sequence(WmAltVkN_2, "Alt+VK_N press/release 2", FALSE); 9266 9267 trace("testing Ctrl+Alt+VK_N press/release 2\n"); 9268 flush_sequence(); 9269 keybd_event(VK_CONTROL, 0, 0, 0); 9270 keybd_event(VK_MENU, 0, 0, 0); 9271 keybd_event('N', 0, 0, 0); 9272 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 9273 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); 9274 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); 9275 pump_msg_loop(hwnd, hAccel); 9276 ok_sequence(WmCtrlAltVkN, "Ctrl+Alt+VK_N press/release 2", FALSE); 9277 9278 trace("testing Ctrl+Shift+VK_N press/release\n"); 9279 flush_sequence(); 9280 keybd_event(VK_CONTROL, 0, 0, 0); 9281 keybd_event(VK_SHIFT, 0, 0, 0); 9282 keybd_event('N', 0, 0, 0); 9283 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 9284 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0); 9285 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); 9286 pump_msg_loop(hwnd, hAccel); 9287 ok_sequence(WmCtrlShiftVkN, "Ctrl+Shift+VK_N press/release", FALSE); 9288 9289 trace("testing Ctrl+Alt+Shift+VK_N press/release\n"); 9290 flush_sequence(); 9291 keybd_event(VK_CONTROL, 0, 0, 0); 9292 keybd_event(VK_MENU, 0, 0, 0); 9293 keybd_event(VK_SHIFT, 0, 0, 0); 9294 keybd_event('N', 0, 0, 0); 9295 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 9296 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0); 9297 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); 9298 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); 9299 pump_msg_loop(hwnd, hAccel); 9300 ok_sequence(WmCtrlAltShiftVkN, "Ctrl+Alt+Shift+VK_N press/release", FALSE); 9301 9302 ret = DestroyAcceleratorTable(hAccel); 9303 ok( ret, "DestroyAcceleratorTable error %d\n", GetLastError()); 9304 hAccel = 0; 9305 9306 trace("testing Alt press/release\n"); 9307 flush_sequence(); 9308 keybd_event(VK_MENU, 0, 0, 0); 9309 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); 9310 keybd_event(VK_MENU, 0, 0, 0); 9311 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); 9312 pump_msg_loop(hwnd, 0); 9313 /* this test doesn't pass in Wine for managed windows */ 9314 ok_sequence(WmAltPressRelease, "Alt press/release", TRUE); 9315 9316 trace("testing VK_F1 press/release\n"); 9317 keybd_event(VK_F1, 0, 0, 0); 9318 keybd_event(VK_F1, 0, KEYEVENTF_KEYUP, 0); 9319 pump_msg_loop(hwnd, 0); 9320 ok_sequence(WmF1Seq, "F1 press/release", FALSE); 9321 9322 trace("testing VK_APPS press/release\n"); 9323 keybd_event(VK_APPS, 0, 0, 0); 9324 keybd_event(VK_APPS, 0, KEYEVENTF_KEYUP, 0); 9325 pump_msg_loop(hwnd, 0); 9326 ok_sequence(WmVkAppsSeq, "VK_APPS press/release", FALSE); 9327 9328 trace("testing VK_F10 press/release\n"); 9329 keybd_event(VK_F10, 0, 0, 0); 9330 keybd_event(VK_F10, 0, KEYEVENTF_KEYUP, 0); 9331 keybd_event(VK_F10, 0, 0, 0); 9332 keybd_event(VK_F10, 0, KEYEVENTF_KEYUP, 0); 9333 pump_msg_loop(hwnd, 0); 9334 ok_sequence(WmVkF10Seq, "VK_F10 press/release", TRUE); 9335 9336 trace("testing SHIFT+F10 press/release\n"); 9337 keybd_event(VK_SHIFT, 0, 0, 0); 9338 keybd_event(VK_F10, 0, 0, 0); 9339 keybd_event(VK_F10, 0, KEYEVENTF_KEYUP, 0); 9340 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0); 9341 keybd_event(VK_ESCAPE, 0, 0, 0); 9342 keybd_event(VK_ESCAPE, 0, KEYEVENTF_KEYUP, 0); 9343 pump_msg_loop(hwnd, 0); 9344 ok_sequence(WmShiftF10Seq, "SHIFT+F10 press/release", TRUE); 9345 9346 trace("testing Shift+MouseButton press/release\n"); 9347 /* first, move mouse pointer inside of the window client area */ 9348 GetClientRect(hwnd, &rc); 9349 MapWindowPoints(hwnd, 0, (LPPOINT)&rc, 2); 9350 rc.left += (rc.right - rc.left)/2; 9351 rc.top += (rc.bottom - rc.top)/2; 9352 SetCursorPos(rc.left, rc.top); 9353 SetActiveWindow(hwnd); 9354 9355 flush_events(); 9356 flush_sequence(); 9357 GetCursorPos(&pt); 9358 if (pt.x == rc.left && pt.y == rc.top) 9359 { 9360 int i; 9361 keybd_event(VK_SHIFT, 0, 0, 0); 9362 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); 9363 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); 9364 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0); 9365 pump_msg_loop(hwnd, 0); 9366 for (i = 0; i < sequence_cnt; i++) if (sequence[i].message == WM_LBUTTONDOWN) break; 9367 if (i < sequence_cnt) 9368 ok_sequence(WmShiftMouseButton, "Shift+MouseButton press/release", FALSE); 9369 else 9370 skip( "Shift+MouseButton event didn't get to the window\n" ); 9371 } 9372 9373 done: 9374 if (hAccel) DestroyAcceleratorTable(hAccel); 9375 DestroyWindow(hwnd); 9376 } 9377 9378 /************* window procedures ********************/ 9379 9380 static LRESULT MsgCheckProc (BOOL unicode, HWND hwnd, UINT message, 9381 WPARAM wParam, LPARAM lParam) 9382 { 9383 static LONG defwndproc_counter = 0; 9384 static LONG beginpaint_counter = 0; 9385 LRESULT ret; 9386 struct recvd_message msg; 9387 9388 if (ignore_message( message )) return 0; 9389 9390 switch (message) 9391 { 9392 case WM_ENABLE: 9393 { 9394 LONG style = GetWindowLongA(hwnd, GWL_STYLE); 9395 ok((BOOL)wParam == !(style & WS_DISABLED), 9396 "wrong WS_DISABLED state: %ld != %d\n", wParam, !(style & WS_DISABLED)); 9397 break; 9398 } 9399 9400 case WM_CAPTURECHANGED: 9401 if (test_DestroyWindow_flag) 9402 { 9403 DWORD style = GetWindowLongA(hwnd, GWL_STYLE); 9404 if (style & WS_CHILD) 9405 lParam = GetWindowLongPtrA(hwnd, GWLP_ID); 9406 else if (style & WS_POPUP) 9407 lParam = WND_POPUP_ID; 9408 else 9409 lParam = WND_PARENT_ID; 9410 } 9411 break; 9412 9413 case WM_NCDESTROY: 9414 { 9415 HWND capture; 9416 9417 ok(!GetWindow(hwnd, GW_CHILD), "children should be unlinked at this point\n"); 9418 capture = GetCapture(); 9419 if (capture) 9420 { 9421 ok(capture == hwnd, "capture should NOT be released at this point (capture %p)\n", capture); 9422 trace("current capture %p, releasing...\n", capture); 9423 ReleaseCapture(); 9424 } 9425 } 9426 /* fall through */ 9427 case WM_DESTROY: 9428 if (pGetAncestor) 9429 ok(pGetAncestor(hwnd, GA_PARENT) != 0, "parent should NOT be unlinked at this point\n"); 9430 if (test_DestroyWindow_flag) 9431 { 9432 DWORD style = GetWindowLongA(hwnd, GWL_STYLE); 9433 if (style & WS_CHILD) 9434 lParam = GetWindowLongPtrA(hwnd, GWLP_ID); 9435 else if (style & WS_POPUP) 9436 lParam = WND_POPUP_ID; 9437 else 9438 lParam = WND_PARENT_ID; 9439 } 9440 break; 9441 9442 /* test_accelerators() depends on this */ 9443 case WM_NCHITTEST: 9444 return HTCLIENT; 9445 9446 case WM_USER+10: 9447 { 9448 ACTIVATION_CONTEXT_BASIC_INFORMATION basicinfo; 9449 HANDLE handle, event = (HANDLE)lParam; 9450 BOOL ret; 9451 9452 handle = (void*)0xdeadbeef; 9453 ret = pGetCurrentActCtx(&handle); 9454 ok(ret, "failed to get current context, %u\n", GetLastError()); 9455 ok(handle == 0, "got active context %p\n", handle); 9456 9457 memset(&basicinfo, 0xff, sizeof(basicinfo)); 9458 ret = pQueryActCtxW(QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX, handle, 0, ActivationContextBasicInformation, 9459 &basicinfo, sizeof(basicinfo), NULL); 9460 ok(ret, "got %d, error %d\n", ret, GetLastError()); 9461 ok(basicinfo.hActCtx == NULL, "got %p\n", basicinfo.hActCtx); 9462 ok(basicinfo.dwFlags == 0, "got %x\n", basicinfo.dwFlags); 9463 9464 if (event) SetEvent(event); 9465 return 1; 9466 } 9467 9468 /* ignore */ 9469 case WM_MOUSEMOVE: 9470 case WM_MOUSEACTIVATE: 9471 case WM_NCMOUSEMOVE: 9472 case WM_SETCURSOR: 9473 case WM_IME_SELECT: 9474 return 0; 9475 } 9476 9477 msg.hwnd = hwnd; 9478 msg.message = message; 9479 msg.flags = sent|wparam|lparam; 9480 if (defwndproc_counter) msg.flags |= defwinproc; 9481 if (beginpaint_counter) msg.flags |= beginpaint; 9482 msg.wParam = wParam; 9483 msg.lParam = lParam; 9484 msg.descr = "MsgCheckProc"; 9485 add_message(&msg); 9486 9487 if (message == WM_GETMINMAXINFO && (GetWindowLongA(hwnd, GWL_STYLE) & WS_CHILD)) 9488 { 9489 HWND parent = GetParent(hwnd); 9490 RECT rc; 9491 MINMAXINFO *minmax = (MINMAXINFO *)lParam; 9492 9493 GetClientRect(parent, &rc); 9494 trace("parent %p client size = (%d x %d)\n", parent, rc.right, rc.bottom); 9495 trace("Reserved=%d,%d MaxSize=%d,%d MaxPos=%d,%d MinTrack=%d,%d MaxTrack=%d,%d\n", 9496 minmax->ptReserved.x, minmax->ptReserved.y, 9497 minmax->ptMaxSize.x, minmax->ptMaxSize.y, 9498 minmax->ptMaxPosition.x, minmax->ptMaxPosition.y, 9499 minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y, 9500 minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y); 9501 9502 ok(minmax->ptMaxSize.x == rc.right, "default width of maximized child %d != %d\n", 9503 minmax->ptMaxSize.x, rc.right); 9504 ok(minmax->ptMaxSize.y == rc.bottom, "default height of maximized child %d != %d\n", 9505 minmax->ptMaxSize.y, rc.bottom); 9506 } 9507 9508 if (message == WM_PAINT) 9509 { 9510 PAINTSTRUCT ps; 9511 beginpaint_counter++; 9512 BeginPaint( hwnd, &ps ); 9513 beginpaint_counter--; 9514 EndPaint( hwnd, &ps ); 9515 return 0; 9516 } 9517 9518 if (!test_context_menu && message == WM_CONTEXTMENU) 9519 { 9520 /* don't create context menu */ 9521 return 0; 9522 } 9523 9524 defwndproc_counter++; 9525 ret = unicode ? DefWindowProcW(hwnd, message, wParam, lParam) 9526 : DefWindowProcA(hwnd, message, wParam, lParam); 9527 defwndproc_counter--; 9528 9529 return ret; 9530 } 9531 9532 static LRESULT WINAPI MsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 9533 { 9534 return MsgCheckProc (FALSE, hwnd, message, wParam, lParam); 9535 } 9536 9537 static LRESULT WINAPI MsgCheckProcW(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 9538 { 9539 return MsgCheckProc (TRUE, hwnd, message, wParam, lParam); 9540 } 9541 9542 static LRESULT WINAPI PopupMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 9543 { 9544 static LONG defwndproc_counter = 0; 9545 LRESULT ret; 9546 struct recvd_message msg; 9547 9548 if (ignore_message( message )) return 0; 9549 9550 switch (message) 9551 { 9552 case WM_QUERYENDSESSION: 9553 case WM_ENDSESSION: 9554 lParam &= ~0x01; /* Vista adds a 0x01 flag */ 9555 break; 9556 } 9557 9558 msg.hwnd = hwnd; 9559 msg.message = message; 9560 msg.flags = sent|wparam|lparam; 9561 if (defwndproc_counter) msg.flags |= defwinproc; 9562 msg.wParam = wParam; 9563 msg.lParam = lParam; 9564 msg.descr = "popup"; 9565 add_message(&msg); 9566 9567 if (message == WM_CREATE) 9568 { 9569 DWORD style = GetWindowLongA(hwnd, GWL_STYLE) | WS_VISIBLE; 9570 SetWindowLongA(hwnd, GWL_STYLE, style); 9571 } 9572 9573 defwndproc_counter++; 9574 ret = DefWindowProcA(hwnd, message, wParam, lParam); 9575 defwndproc_counter--; 9576 9577 return ret; 9578 } 9579 9580 static LRESULT WINAPI ParentMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 9581 { 9582 static LONG defwndproc_counter = 0; 9583 static LONG beginpaint_counter = 0; 9584 LRESULT ret; 9585 struct recvd_message msg; 9586 9587 if (ignore_message( message )) return 0; 9588 9589 if (log_all_parent_messages || 9590 message == WM_PARENTNOTIFY || message == WM_CANCELMODE || 9591 message == WM_SETFOCUS || message == WM_KILLFOCUS || 9592 message == WM_ENABLE || message == WM_ENTERIDLE || 9593 message == WM_DRAWITEM || message == WM_MEASUREITEM || message == WM_COMPAREITEM || 9594 message == WM_COMMAND || message == WM_IME_SETCONTEXT) 9595 { 9596 switch (message) 9597 { 9598 /* ignore */ 9599 case WM_NCHITTEST: 9600 return HTCLIENT; 9601 case WM_SETCURSOR: 9602 case WM_MOUSEMOVE: 9603 case WM_NCMOUSEMOVE: 9604 return 0; 9605 9606 case WM_ERASEBKGND: 9607 { 9608 RECT rc; 9609 INT ret = GetClipBox((HDC)wParam, &rc); 9610 9611 trace("WM_ERASEBKGND: GetClipBox()=%d, %s\n", ret, wine_dbgstr_rect(&rc)); 9612 break; 9613 } 9614 } 9615 9616 msg.hwnd = hwnd; 9617 msg.message = message; 9618 msg.flags = sent|parent|wparam|lparam; 9619 if (defwndproc_counter) msg.flags |= defwinproc; 9620 if (beginpaint_counter) msg.flags |= beginpaint; 9621 msg.wParam = wParam; 9622 msg.lParam = lParam; 9623 msg.descr = "parent"; 9624 add_message(&msg); 9625 } 9626 9627 if (message == WM_PAINT) 9628 { 9629 PAINTSTRUCT ps; 9630 beginpaint_counter++; 9631 BeginPaint( hwnd, &ps ); 9632 beginpaint_counter--; 9633 EndPaint( hwnd, &ps ); 9634 return 0; 9635 } 9636 9637 defwndproc_counter++; 9638 ret = DefWindowProcA(hwnd, message, wParam, lParam); 9639 defwndproc_counter--; 9640 9641 return message == WM_COMPAREITEM ? -1 : ret; 9642 } 9643 9644 static INT_PTR CALLBACK StopQuitMsgCheckProcA(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) 9645 { 9646 if (message == WM_CREATE) 9647 PostMessageA(hwnd, WM_CLOSE, 0, 0); 9648 else if (message == WM_CLOSE) 9649 { 9650 /* Only the first WM_QUIT will survive the window destruction */ 9651 PostMessageA(hwnd, WM_USER, 0x1234, 0x5678); 9652 PostMessageA(hwnd, WM_QUIT, 0x1234, 0x5678); 9653 PostMessageA(hwnd, WM_QUIT, 0x4321, 0x8765); 9654 } 9655 9656 return DefWindowProcA(hwnd, message, wp, lp); 9657 } 9658 9659 static LRESULT WINAPI TestDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 9660 { 9661 static LONG defwndproc_counter = 0; 9662 LRESULT ret; 9663 struct recvd_message msg; 9664 9665 if (ignore_message( message )) return 0; 9666 9667 if (test_def_id) 9668 { 9669 DefDlgProcA(hwnd, DM_SETDEFID, 1, 0); 9670 ret = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0); 9671 if (after_end_dialog) 9672 ok( ret == 0, "DM_GETDEFID should return 0 after EndDialog, got %lx\n", ret ); 9673 else 9674 ok(HIWORD(ret) == DC_HASDEFID, "DM_GETDEFID should return DC_HASDEFID, got %lx\n", ret); 9675 } 9676 9677 msg.hwnd = hwnd; 9678 msg.message = message; 9679 msg.flags = sent|wparam|lparam; 9680 if (defwndproc_counter) msg.flags |= defwinproc; 9681 msg.wParam = wParam; 9682 msg.lParam = lParam; 9683 msg.descr = "dialog"; 9684 add_message(&msg); 9685 9686 defwndproc_counter++; 9687 ret = DefDlgProcA(hwnd, message, wParam, lParam); 9688 defwndproc_counter--; 9689 9690 return ret; 9691 } 9692 9693 static LRESULT WINAPI ShowWindowProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 9694 { 9695 static LONG defwndproc_counter = 0; 9696 LRESULT ret; 9697 struct recvd_message msg; 9698 9699 /* log only specific messages we are interested in */ 9700 switch (message) 9701 { 9702 #if 0 /* probably log these as well */ 9703 case WM_ACTIVATE: 9704 case WM_SETFOCUS: 9705 case WM_KILLFOCUS: 9706 #endif 9707 case WM_SHOWWINDOW: 9708 case WM_SIZE: 9709 case WM_MOVE: 9710 case WM_GETMINMAXINFO: 9711 case WM_WINDOWPOSCHANGING: 9712 case WM_WINDOWPOSCHANGED: 9713 break; 9714 9715 default: /* ignore */ 9716 /*trace("showwindow: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);*/ 9717 return DefWindowProcA(hwnd, message, wParam, lParam); 9718 } 9719 9720 msg.hwnd = hwnd; 9721 msg.message = message; 9722 msg.flags = sent|wparam|lparam; 9723 if (defwndproc_counter) msg.flags |= defwinproc; 9724 msg.wParam = wParam; 9725 msg.lParam = lParam; 9726 msg.descr = "show"; 9727 add_message(&msg); 9728 9729 defwndproc_counter++; 9730 ret = DefWindowProcA(hwnd, message, wParam, lParam); 9731 defwndproc_counter--; 9732 9733 return ret; 9734 } 9735 9736 static LRESULT WINAPI recursive_activation_wndprocA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 9737 { 9738 static LONG defwndproc_counter = 0; 9739 struct recvd_message msg; 9740 LRESULT ret; 9741 9742 switch (message) 9743 { 9744 /* log only specific messages we are interested in */ 9745 case WM_NCACTIVATE: 9746 case WM_ACTIVATE: 9747 case WM_SETFOCUS: 9748 case WM_KILLFOCUS: 9749 break; 9750 default: 9751 return DefWindowProcA(hwnd, message, wParam, lParam); 9752 } 9753 9754 msg.hwnd = hwnd; 9755 msg.message = message; 9756 msg.flags = sent|wparam|lparam; 9757 if (defwndproc_counter) msg.flags |= defwinproc; 9758 msg.wParam = wParam; 9759 msg.lParam = lParam; 9760 msg.descr = "recursive_activation"; 9761 add_message(&msg); 9762 9763 /* recursively activate ourselves by first losing activation and changing it back */ 9764 if (message == WM_ACTIVATE && LOWORD(wParam) != WA_INACTIVE) 9765 { 9766 SetActiveWindow((HWND)lParam); 9767 SetActiveWindow(hwnd); 9768 return 0; 9769 } 9770 9771 defwndproc_counter++; 9772 ret = DefWindowProcA(hwnd, message, wParam, lParam); 9773 defwndproc_counter--; 9774 9775 return ret; 9776 } 9777 9778 static LRESULT WINAPI PaintLoopProcA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) 9779 { 9780 switch (msg) 9781 { 9782 case WM_CREATE: return 0; 9783 case WM_PAINT: 9784 { 9785 MSG msg2; 9786 static int i = 0; 9787 9788 if (i < 256) 9789 { 9790 i++; 9791 if (PeekMessageA(&msg2, 0, 0, 0, 1)) 9792 { 9793 TranslateMessage(&msg2); 9794 DispatchMessageA(&msg2); 9795 } 9796 i--; 9797 } 9798 else ok(broken(1), "infinite loop\n"); 9799 if ( i == 0) 9800 paint_loop_done = TRUE; 9801 return DefWindowProcA(hWnd,msg,wParam,lParam); 9802 } 9803 } 9804 return DefWindowProcA(hWnd,msg,wParam,lParam); 9805 } 9806 9807 static LRESULT WINAPI HotkeyMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 9808 { 9809 static LONG defwndproc_counter = 0; 9810 LRESULT ret; 9811 struct recvd_message msg; 9812 DWORD queue_status; 9813 9814 if (ignore_message( message )) return 0; 9815 9816 if ((message >= WM_KEYFIRST && message <= WM_KEYLAST) || 9817 message == WM_HOTKEY || message >= WM_APP) 9818 { 9819 msg.hwnd = hwnd; 9820 msg.message = message; 9821 msg.flags = sent|wparam|lparam; 9822 if (defwndproc_counter) msg.flags |= defwinproc; 9823 msg.wParam = wParam; 9824 msg.lParam = lParam; 9825 msg.descr = "HotkeyMsgCheckProcA"; 9826 add_message(&msg); 9827 } 9828 9829 defwndproc_counter++; 9830 ret = DefWindowProcA(hwnd, message, wParam, lParam); 9831 defwndproc_counter--; 9832 9833 if (message == WM_APP) 9834 { 9835 queue_status = GetQueueStatus(QS_HOTKEY); 9836 ok((queue_status & (QS_HOTKEY << 16)) == QS_HOTKEY << 16, "expected QS_HOTKEY << 16 set, got %x\n", queue_status); 9837 queue_status = GetQueueStatus(QS_POSTMESSAGE); 9838 ok((queue_status & (QS_POSTMESSAGE << 16)) == QS_POSTMESSAGE << 16, "expected QS_POSTMESSAGE << 16 set, got %x\n", queue_status); 9839 PostMessageA(hwnd, WM_APP+1, 0, 0); 9840 } 9841 else if (message == WM_APP+1) 9842 { 9843 queue_status = GetQueueStatus(QS_HOTKEY); 9844 ok((queue_status & (QS_HOTKEY << 16)) == 0, "expected QS_HOTKEY << 16 cleared, got %x\n", queue_status); 9845 } 9846 9847 return ret; 9848 } 9849 9850 static BOOL RegisterWindowClasses(void) 9851 { 9852 WNDCLASSA cls; 9853 WNDCLASSW clsW; 9854 9855 cls.style = 0; 9856 cls.lpfnWndProc = MsgCheckProcA; 9857 cls.cbClsExtra = 0; 9858 cls.cbWndExtra = 0; 9859 cls.hInstance = GetModuleHandleA(0); 9860 cls.hIcon = 0; 9861 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 9862 cls.hbrBackground = GetStockObject(WHITE_BRUSH); 9863 cls.lpszMenuName = NULL; 9864 cls.lpszClassName = "TestWindowClass"; 9865 if(!RegisterClassA(&cls)) return FALSE; 9866 9867 cls.lpfnWndProc = HotkeyMsgCheckProcA; 9868 cls.lpszClassName = "HotkeyWindowClass"; 9869 if(!RegisterClassA(&cls)) return FALSE; 9870 9871 cls.lpfnWndProc = ShowWindowProcA; 9872 cls.lpszClassName = "ShowWindowClass"; 9873 if(!RegisterClassA(&cls)) return FALSE; 9874 9875 cls.lpfnWndProc = recursive_activation_wndprocA; 9876 cls.lpszClassName = "RecursiveActivationClass"; 9877 if(!RegisterClassA(&cls)) return FALSE; 9878 9879 cls.lpfnWndProc = PopupMsgCheckProcA; 9880 cls.lpszClassName = "TestPopupClass"; 9881 if(!RegisterClassA(&cls)) return FALSE; 9882 9883 cls.lpfnWndProc = ParentMsgCheckProcA; 9884 cls.lpszClassName = "TestParentClass"; 9885 if(!RegisterClassA(&cls)) return FALSE; 9886 9887 cls.lpfnWndProc = StopQuitMsgCheckProcA; 9888 cls.lpszClassName = "StopQuitClass"; 9889 if(!RegisterClassA(&cls)) return FALSE; 9890 9891 cls.lpfnWndProc = DefWindowProcA; 9892 cls.lpszClassName = "SimpleWindowClass"; 9893 if(!RegisterClassA(&cls)) return FALSE; 9894 9895 cls.lpfnWndProc = PaintLoopProcA; 9896 cls.lpszClassName = "PaintLoopWindowClass"; 9897 if(!RegisterClassA(&cls)) return FALSE; 9898 9899 cls.style = CS_NOCLOSE; 9900 cls.lpszClassName = "NoCloseWindowClass"; 9901 if(!RegisterClassA(&cls)) return FALSE; 9902 9903 ok(GetClassInfoA(0, "#32770", &cls), "GetClassInfo failed\n"); 9904 cls.style = 0; 9905 cls.hInstance = GetModuleHandleA(0); 9906 cls.hbrBackground = 0; 9907 cls.lpfnWndProc = TestDlgProcA; 9908 cls.lpszClassName = "TestDialogClass"; 9909 if(!RegisterClassA(&cls)) return FALSE; 9910 9911 clsW.style = 0; 9912 clsW.lpfnWndProc = MsgCheckProcW; 9913 clsW.cbClsExtra = 0; 9914 clsW.cbWndExtra = 0; 9915 clsW.hInstance = GetModuleHandleW(0); 9916 clsW.hIcon = 0; 9917 clsW.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW); 9918 clsW.hbrBackground = GetStockObject(WHITE_BRUSH); 9919 clsW.lpszMenuName = NULL; 9920 clsW.lpszClassName = testWindowClassW; 9921 RegisterClassW(&clsW); /* ignore error, this fails on Win9x */ 9922 9923 return TRUE; 9924 } 9925 9926 static BOOL is_our_logged_class(HWND hwnd) 9927 { 9928 char buf[256]; 9929 9930 if (GetClassNameA(hwnd, buf, sizeof(buf))) 9931 { 9932 if (!lstrcmpiA(buf, "TestWindowClass") || 9933 !lstrcmpiA(buf, "ShowWindowClass") || 9934 !lstrcmpiA(buf, "RecursiveActivationClass") || 9935 !lstrcmpiA(buf, "TestParentClass") || 9936 !lstrcmpiA(buf, "TestPopupClass") || 9937 !lstrcmpiA(buf, "SimpleWindowClass") || 9938 !lstrcmpiA(buf, "TestDialogClass") || 9939 !lstrcmpiA(buf, "MDI_frame_class") || 9940 !lstrcmpiA(buf, "MDI_client_class") || 9941 !lstrcmpiA(buf, "MDI_child_class") || 9942 !lstrcmpiA(buf, "my_button_class") || 9943 !lstrcmpiA(buf, "my_edit_class") || 9944 !lstrcmpiA(buf, "static") || 9945 !lstrcmpiA(buf, "ListBox") || 9946 !lstrcmpiA(buf, "ComboBox") || 9947 !lstrcmpiA(buf, "MyDialogClass") || 9948 !lstrcmpiA(buf, "#32770") || 9949 !lstrcmpiA(buf, "#32768")) 9950 return TRUE; 9951 } 9952 return FALSE; 9953 } 9954 9955 static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam) 9956 { 9957 HWND hwnd; 9958 9959 ok(cbt_hook_thread_id == GetCurrentThreadId(), "we didn't ask for events from other threads\n"); 9960 9961 if (nCode == HCBT_CLICKSKIPPED) 9962 { 9963 /* ignore this event, XP sends it a lot when switching focus between windows */ 9964 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam); 9965 } 9966 9967 if (nCode == HCBT_SYSCOMMAND || nCode == HCBT_KEYSKIPPED) 9968 { 9969 struct recvd_message msg; 9970 9971 msg.hwnd = 0; 9972 msg.message = nCode; 9973 msg.flags = hook|wparam|lparam; 9974 msg.wParam = wParam; 9975 msg.lParam = lParam; 9976 msg.descr = "CBT"; 9977 add_message(&msg); 9978 9979 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam); 9980 } 9981 9982 if (nCode == HCBT_DESTROYWND) 9983 { 9984 if (test_DestroyWindow_flag) 9985 { 9986 DWORD style = GetWindowLongA((HWND)wParam, GWL_STYLE); 9987 if (style & WS_CHILD) 9988 lParam = GetWindowLongPtrA((HWND)wParam, GWLP_ID); 9989 else if (style & WS_POPUP) 9990 lParam = WND_POPUP_ID; 9991 else 9992 lParam = WND_PARENT_ID; 9993 } 9994 } 9995 9996 /* Log also SetFocus(0) calls */ 9997 hwnd = wParam ? (HWND)wParam : (HWND)lParam; 9998 9999 if (is_our_logged_class(hwnd)) 10000 { 10001 struct recvd_message msg; 10002 10003 msg.hwnd = hwnd; 10004 msg.message = nCode; 10005 msg.flags = hook|wparam|lparam; 10006 msg.wParam = wParam; 10007 msg.lParam = lParam; 10008 msg.descr = "CBT"; 10009 add_message(&msg); 10010 } 10011 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam); 10012 } 10013 10014 static void CALLBACK win_event_proc(HWINEVENTHOOK hevent, 10015 DWORD event, 10016 HWND hwnd, 10017 LONG object_id, 10018 LONG child_id, 10019 DWORD thread_id, 10020 DWORD event_time) 10021 { 10022 ok(thread_id == GetCurrentThreadId(), "we didn't ask for events from other threads\n"); 10023 10024 /* ignore mouse cursor events */ 10025 if (object_id == OBJID_CURSOR) return; 10026 10027 if (!hwnd || is_our_logged_class(hwnd)) 10028 { 10029 struct recvd_message msg; 10030 10031 msg.hwnd = hwnd; 10032 msg.message = event; 10033 msg.flags = winevent_hook|wparam|lparam; 10034 msg.wParam = object_id; 10035 msg.lParam = child_id; 10036 msg.descr = "WEH"; 10037 add_message(&msg); 10038 } 10039 } 10040 10041 static const WCHAR wszUnicode[] = {'U','n','i','c','o','d','e',0}; 10042 static const WCHAR wszAnsi[] = {'U',0}; 10043 10044 static LRESULT CALLBACK MsgConversionProcW(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 10045 { 10046 switch (uMsg) 10047 { 10048 case CB_FINDSTRINGEXACT: 10049 trace("String: %p\n", (LPCWSTR)lParam); 10050 if (!lstrcmpW((LPCWSTR)lParam, wszUnicode)) 10051 return 1; 10052 if (!lstrcmpW((LPCWSTR)lParam, wszAnsi)) 10053 return 0; 10054 return -1; 10055 } 10056 return DefWindowProcW(hwnd, uMsg, wParam, lParam); 10057 } 10058 10059 static const struct message WmGetTextLengthAfromW[] = { 10060 { WM_GETTEXTLENGTH, sent }, 10061 { WM_GETTEXT, sent|optional }, 10062 { 0 } 10063 }; 10064 10065 static const WCHAR dummy_window_text[] = {'d','u','m','m','y',' ','t','e','x','t',0}; 10066 10067 /* dummy window proc for WM_GETTEXTLENGTH test */ 10068 static LRESULT CALLBACK get_text_len_proc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ) 10069 { 10070 switch(msg) 10071 { 10072 case WM_GETTEXTLENGTH: 10073 return lstrlenW(dummy_window_text) + 37; /* some random length */ 10074 case WM_GETTEXT: 10075 lstrcpynW( (LPWSTR)lp, dummy_window_text, wp ); 10076 return lstrlenW( (LPWSTR)lp ); 10077 default: 10078 return DefWindowProcW( hwnd, msg, wp, lp ); 10079 } 10080 } 10081 10082 static void test_message_conversion(void) 10083 { 10084 static const WCHAR wszMsgConversionClass[] = 10085 {'M','s','g','C','o','n','v','e','r','s','i','o','n','C','l','a','s','s',0}; 10086 WNDCLASSW cls; 10087 LRESULT lRes; 10088 HWND hwnd; 10089 WNDPROC wndproc, newproc; 10090 BOOL ret; 10091 10092 cls.style = 0; 10093 cls.lpfnWndProc = MsgConversionProcW; 10094 cls.cbClsExtra = 0; 10095 cls.cbWndExtra = 0; 10096 cls.hInstance = GetModuleHandleW(NULL); 10097 cls.hIcon = NULL; 10098 cls.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW); 10099 cls.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1); 10100 cls.lpszMenuName = NULL; 10101 cls.lpszClassName = wszMsgConversionClass; 10102 /* this call will fail on Win9x, but that doesn't matter as this test is 10103 * meaningless on those platforms */ 10104 if(!RegisterClassW(&cls)) return; 10105 10106 hwnd = CreateWindowExW(0, wszMsgConversionClass, NULL, WS_OVERLAPPED, 10107 100, 100, 200, 200, 0, 0, 0, NULL); 10108 ok(hwnd != NULL, "Window creation failed\n"); 10109 10110 /* {W, A} -> A */ 10111 10112 wndproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_WNDPROC); 10113 lRes = CallWindowProcA(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); 10114 ok(lRes == 0, "String should have been converted\n"); 10115 lRes = CallWindowProcW(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); 10116 ok(lRes == 1, "String shouldn't have been converted\n"); 10117 10118 /* {W, A} -> W */ 10119 10120 wndproc = (WNDPROC)GetWindowLongPtrW(hwnd, GWLP_WNDPROC); 10121 lRes = CallWindowProcA(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); 10122 ok(lRes == 1, "String shouldn't have been converted\n"); 10123 lRes = CallWindowProcW(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); 10124 ok(lRes == 1, "String shouldn't have been converted\n"); 10125 10126 /* Synchronous messages */ 10127 10128 lRes = SendMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); 10129 ok(lRes == 0, "String should have been converted\n"); 10130 lRes = SendMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); 10131 ok(lRes == 1, "String shouldn't have been converted\n"); 10132 10133 /* Asynchronous messages */ 10134 10135 SetLastError(0); 10136 lRes = PostMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); 10137 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER), 10138 "PostMessage on sync only message returned %ld, last error %d\n", lRes, GetLastError()); 10139 SetLastError(0); 10140 lRes = PostMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); 10141 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER), 10142 "PostMessage on sync only message returned %ld, last error %d\n", lRes, GetLastError()); 10143 SetLastError(0); 10144 lRes = PostThreadMessageA(GetCurrentThreadId(), CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); 10145 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER), 10146 "PosThreadtMessage on sync only message returned %ld, last error %d\n", lRes, GetLastError()); 10147 SetLastError(0); 10148 lRes = PostThreadMessageW(GetCurrentThreadId(), CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); 10149 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER), 10150 "PosThreadtMessage on sync only message returned %ld, last error %d\n", lRes, GetLastError()); 10151 SetLastError(0); 10152 lRes = SendNotifyMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); 10153 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER), 10154 "SendNotifyMessage on sync only message returned %ld, last error %d\n", lRes, GetLastError()); 10155 SetLastError(0); 10156 lRes = SendNotifyMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); 10157 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER), 10158 "SendNotifyMessage on sync only message returned %ld, last error %d\n", lRes, GetLastError()); 10159 SetLastError(0); 10160 lRes = SendMessageCallbackA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode, NULL, 0); 10161 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER), 10162 "SendMessageCallback on sync only message returned %ld, last error %d\n", lRes, GetLastError()); 10163 SetLastError(0); 10164 lRes = SendMessageCallbackW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode, NULL, 0); 10165 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER), 10166 "SendMessageCallback on sync only message returned %ld, last error %d\n", lRes, GetLastError()); 10167 10168 /* Check WM_GETTEXTLENGTH A->W behaviour, whether WM_GETTEXT is also sent or not */ 10169 10170 hwnd = CreateWindowW (testWindowClassW, wszUnicode, 10171 WS_OVERLAPPEDWINDOW, 10172 100, 100, 200, 200, 0, 0, 0, NULL); 10173 assert(hwnd); 10174 flush_sequence(); 10175 lRes = SendMessageA (hwnd, WM_GETTEXTLENGTH, 0, 0); 10176 ok_sequence(WmGetTextLengthAfromW, "ANSI WM_GETTEXTLENGTH to Unicode window", FALSE); 10177 ok( lRes == WideCharToMultiByte( CP_ACP, 0, wszUnicode, lstrlenW(wszUnicode), NULL, 0, NULL, NULL ), 10178 "got bad length %ld\n", lRes ); 10179 10180 flush_sequence(); 10181 lRes = CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ), 10182 hwnd, WM_GETTEXTLENGTH, 0, 0); 10183 ok_sequence(WmGetTextLengthAfromW, "ANSI WM_GETTEXTLENGTH to Unicode window", FALSE); 10184 ok( lRes == WideCharToMultiByte( CP_ACP, 0, wszUnicode, lstrlenW(wszUnicode), NULL, 0, NULL, NULL ), 10185 "got bad length %ld\n", lRes ); 10186 10187 wndproc = (WNDPROC)SetWindowLongPtrW( hwnd, GWLP_WNDPROC, (LONG_PTR)get_text_len_proc ); 10188 newproc = (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ); 10189 lRes = CallWindowProcA( newproc, hwnd, WM_GETTEXTLENGTH, 0, 0 ); 10190 ok( lRes == WideCharToMultiByte( CP_ACP, 0, dummy_window_text, lstrlenW(dummy_window_text), 10191 NULL, 0, NULL, NULL ) || 10192 broken(lRes == lstrlenW(dummy_window_text) + 37), 10193 "got bad length %ld\n", lRes ); 10194 10195 SetWindowLongPtrW( hwnd, GWLP_WNDPROC, (LONG_PTR)wndproc ); /* restore old wnd proc */ 10196 lRes = CallWindowProcA( newproc, hwnd, WM_GETTEXTLENGTH, 0, 0 ); 10197 ok( lRes == WideCharToMultiByte( CP_ACP, 0, dummy_window_text, lstrlenW(dummy_window_text), 10198 NULL, 0, NULL, NULL ) || 10199 broken(lRes == lstrlenW(dummy_window_text) + 37), 10200 "got bad length %ld\n", lRes ); 10201 10202 ret = DestroyWindow(hwnd); 10203 ok( ret, "DestroyWindow() error %d\n", GetLastError()); 10204 } 10205 10206 struct timer_info 10207 { 10208 HWND hWnd; 10209 HANDLE handles[2]; 10210 DWORD id; 10211 }; 10212 10213 static VOID CALLBACK tfunc(HWND hwnd, UINT uMsg, UINT_PTR id, DWORD dwTime) 10214 { 10215 } 10216 10217 #define TIMER_ID 0x19 10218 #define TIMER_COUNT_EXPECTED 100 10219 #define TIMER_COUNT_TOLERANCE 10 10220 10221 static int count = 0; 10222 static void CALLBACK callback_count(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) 10223 { 10224 count++; 10225 } 10226 10227 static DWORD exception; 10228 static void CALLBACK callback_exception(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) 10229 { 10230 count++; 10231 RaiseException(exception, 0, 0, NULL); 10232 } 10233 10234 static DWORD WINAPI timer_thread_proc(LPVOID x) 10235 { 10236 struct timer_info *info = x; 10237 DWORD r; 10238 10239 r = KillTimer(info->hWnd, 0x19); 10240 ok(r,"KillTimer failed in thread\n"); 10241 r = SetTimer(info->hWnd,TIMER_ID,10000,tfunc); 10242 ok(r,"SetTimer failed in thread\n"); 10243 ok(r==TIMER_ID,"SetTimer id different\n"); 10244 r = SetEvent(info->handles[0]); 10245 ok(r,"SetEvent failed in thread\n"); 10246 return 0; 10247 } 10248 10249 static void test_timers(void) 10250 { 10251 struct timer_info info; 10252 DWORD start; 10253 DWORD id; 10254 MSG msg; 10255 10256 info.hWnd = CreateWindowA("TestWindowClass", NULL, 10257 WS_OVERLAPPEDWINDOW , 10258 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0, 10259 NULL, NULL, 0); 10260 10261 info.id = SetTimer(info.hWnd,TIMER_ID,10000,tfunc); 10262 ok(info.id, "SetTimer failed\n"); 10263 ok(info.id==TIMER_ID, "SetTimer timer ID different\n"); 10264 info.handles[0] = CreateEventW(NULL,0,0,NULL); 10265 info.handles[1] = CreateThread(NULL,0,timer_thread_proc,&info,0,&id); 10266 10267 WaitForMultipleObjects(2, info.handles, FALSE, INFINITE); 10268 10269 WaitForSingleObject(info.handles[1], INFINITE); 10270 10271 CloseHandle(info.handles[0]); 10272 CloseHandle(info.handles[1]); 10273 10274 ok( KillTimer(info.hWnd, TIMER_ID), "KillTimer failed\n"); 10275 10276 /* Check the minimum allowed timeout for a timer. MSDN indicates that it should be 10.0 ms, 10277 * which occurs sometimes, but most testing on the VMs indicates a minimum timeout closer to 10278 * 15.6 ms. Since there is some measurement error between test runs we are allowing for 10279 * ±9 counts (~4 ms) around the expected value. 10280 */ 10281 count = 0; 10282 id = SetTimer(info.hWnd, TIMER_ID, 0, callback_count); 10283 ok(id != 0, "did not get id from SetTimer.\n"); 10284 ok(id==TIMER_ID, "SetTimer timer ID different\n"); 10285 start = GetTickCount(); 10286 while (GetTickCount()-start < 1001 && GetMessageA(&msg, info.hWnd, 0, 0)) 10287 DispatchMessageA(&msg); 10288 ros_skip_flaky 10289 todo_wine 10290 ok(abs(count-TIMER_COUNT_EXPECTED) < TIMER_COUNT_TOLERANCE /* xp */ 10291 || broken(abs(count-64) < TIMER_COUNT_TOLERANCE) /* most common */ 10292 || broken(abs(count-43) < TIMER_COUNT_TOLERANCE) /* w2k3, win8 */, 10293 "did not get expected count for minimum timeout (%d != ~%d).\n", 10294 count, TIMER_COUNT_EXPECTED); 10295 ok(KillTimer(info.hWnd, id), "KillTimer failed\n"); 10296 /* Perform the same check on SetSystemTimer (only available on w2k3 and older) */ 10297 if (pSetSystemTimer) 10298 { 10299 int syscount = 0; 10300 10301 count = 0; 10302 id = pSetSystemTimer(info.hWnd, TIMER_ID, 0, callback_count); 10303 ok(id != 0, "did not get id from SetSystemTimer.\n"); 10304 ok(id==TIMER_ID, "SetTimer timer ID different\n"); 10305 start = GetTickCount(); 10306 while (GetTickCount()-start < 1001 && GetMessageA(&msg, info.hWnd, 0, 0)) 10307 { 10308 if (msg.message == WM_SYSTIMER) 10309 syscount++; 10310 DispatchMessageA(&msg); 10311 } 10312 ok(abs(syscount-TIMER_COUNT_EXPECTED) < TIMER_COUNT_TOLERANCE 10313 || broken(abs(syscount-64) < TIMER_COUNT_TOLERANCE) /* most common */ 10314 || broken(syscount > 4000 && syscount < 12000) /* win2k3sp0 */, 10315 "did not get expected count for minimum timeout (%d != ~%d).\n", 10316 syscount, TIMER_COUNT_EXPECTED); 10317 todo_wine ok(count == 0, "did not get expected count for callback timeout (%d != 0).\n", 10318 count); 10319 ok(pKillSystemTimer(info.hWnd, id), "KillSystemTimer failed\n"); 10320 } 10321 10322 ok(DestroyWindow(info.hWnd), "failed to destroy window\n"); 10323 } 10324 10325 static void test_timers_no_wnd(void) 10326 { 10327 static UINT_PTR ids[0xffff]; 10328 UINT_PTR id, id2; 10329 DWORD start; 10330 MSG msg; 10331 int i; 10332 10333 count = 0; 10334 id = SetTimer(NULL, 0, 100, callback_count); 10335 ok(id != 0, "did not get id from SetTimer.\n"); 10336 id2 = SetTimer(NULL, id, 200, callback_count); 10337 ok(id2 == id, "did not get same id from SetTimer when replacing (%li expected %li).\n", id2, id); 10338 Sleep(150); 10339 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 10340 ok(count == 0, "did not get zero count as expected (%i).\n", count); 10341 Sleep(150); 10342 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 10343 ok(count == 1, "did not get one count as expected (%i).\n", count); 10344 KillTimer(NULL, id); 10345 Sleep(250); 10346 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 10347 ok(count == 1, "killing replaced timer did not work (%i).\n", count); 10348 10349 /* Check the minimum allowed timeout for a timer. MSDN indicates that it should be 10.0 ms, 10350 * which occurs sometimes, but most testing on the VMs indicates a minimum timeout closer to 10351 * 15.6 ms. Since there is some measurement error between test runs we are allowing for 10352 * ±9 counts (~4 ms) around the expected value. 10353 */ 10354 count = 0; 10355 id = SetTimer(NULL, 0, 0, callback_count); 10356 ok(id != 0, "did not get id from SetTimer.\n"); 10357 start = GetTickCount(); 10358 while (GetTickCount()-start < 1001 && GetMessageA(&msg, NULL, 0, 0)) 10359 DispatchMessageA(&msg); 10360 todo_wine 10361 ok(abs(count-TIMER_COUNT_EXPECTED) < TIMER_COUNT_TOLERANCE /* xp */ 10362 || broken(abs(count-64) < TIMER_COUNT_TOLERANCE) /* most common */, 10363 "did not get expected count for minimum timeout (%d != ~%d).\n", 10364 count, TIMER_COUNT_EXPECTED); 10365 KillTimer(NULL, id); 10366 /* Note: SetSystemTimer doesn't support a NULL window, see test_timers */ 10367 10368 if (pSetCoalescableTimer) 10369 { 10370 count = 0; 10371 id = pSetCoalescableTimer(NULL, 0, 0, callback_count, 0); 10372 ok(id != 0, "SetCoalescableTimer failed with %u.\n", GetLastError()); 10373 start = GetTickCount(); 10374 while (GetTickCount()-start < 100 && GetMessageA(&msg, NULL, 0, 0)) 10375 DispatchMessageA(&msg); 10376 ok(count > 1, "expected count > 1, got %d.\n", count); 10377 KillTimer(NULL, id); 10378 } 10379 else 10380 win_skip("SetCoalescableTimer not available.\n"); 10381 10382 /* Check what happens when we're running out of timers */ 10383 for (i = 0; i < ARRAY_SIZE(ids); i++) 10384 { 10385 SetLastError(0xdeadbeef); 10386 ids[i] = SetTimer(NULL, 0, USER_TIMER_MAXIMUM, tfunc); 10387 if (!ids[i]) break; 10388 } 10389 ok(i != ARRAY_SIZE(ids), "all timers were created successfully\n"); 10390 ok(GetLastError()==ERROR_NO_MORE_USER_HANDLES || broken(GetLastError()==0xdeadbeef), 10391 "GetLastError() = %d\n", GetLastError()); 10392 while (i > 0) KillTimer(NULL, ids[--i]); 10393 } 10394 10395 static void test_timers_exception(DWORD code) 10396 { 10397 UINT_PTR id; 10398 MSG msg; 10399 10400 exception = code; 10401 id = SetTimer(NULL, 0, 1000, callback_exception); 10402 ok(id != 0, "did not get id from SetTimer.\n"); 10403 10404 memset(&msg, 0, sizeof(msg)); 10405 msg.message = WM_TIMER; 10406 msg.wParam = id; 10407 msg.lParam = (LPARAM)callback_exception; 10408 10409 count = 0; 10410 DispatchMessageA(&msg); 10411 ok(count == 1, "did not get one count as expected (%i).\n", count); 10412 10413 KillTimer(NULL, id); 10414 } 10415 10416 static void test_timers_exceptions(void) 10417 { 10418 test_timers_exception(EXCEPTION_ACCESS_VIOLATION); 10419 test_timers_exception(EXCEPTION_DATATYPE_MISALIGNMENT); 10420 test_timers_exception(EXCEPTION_BREAKPOINT); 10421 test_timers_exception(EXCEPTION_SINGLE_STEP); 10422 test_timers_exception(EXCEPTION_ARRAY_BOUNDS_EXCEEDED); 10423 test_timers_exception(EXCEPTION_FLT_DENORMAL_OPERAND); 10424 test_timers_exception(EXCEPTION_FLT_DIVIDE_BY_ZERO); 10425 test_timers_exception(EXCEPTION_FLT_INEXACT_RESULT); 10426 test_timers_exception(EXCEPTION_ILLEGAL_INSTRUCTION); 10427 test_timers_exception(0xE000BEEF); /* customer exception */ 10428 } 10429 10430 /* Various win events with arbitrary parameters */ 10431 static const struct message WmWinEventsSeq[] = { 10432 { EVENT_SYSTEM_SOUND, winevent_hook|wparam|lparam, OBJID_WINDOW, 0 }, 10433 { EVENT_SYSTEM_ALERT, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 }, 10434 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, OBJID_TITLEBAR, 2 }, 10435 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_MENU, 3 }, 10436 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_CLIENT, 4 }, 10437 { EVENT_SYSTEM_MENUPOPUPSTART, winevent_hook|wparam|lparam, OBJID_VSCROLL, 5 }, 10438 { EVENT_SYSTEM_MENUPOPUPEND, winevent_hook|wparam|lparam, OBJID_HSCROLL, 6 }, 10439 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, OBJID_SIZEGRIP, 7 }, 10440 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, OBJID_CARET, 8 }, 10441 /* our win event hook ignores OBJID_CURSOR events */ 10442 /*{ EVENT_SYSTEM_MOVESIZESTART, winevent_hook|wparam|lparam, OBJID_CURSOR, 9 },*/ 10443 { EVENT_SYSTEM_MOVESIZEEND, winevent_hook|wparam|lparam, OBJID_ALERT, 10 }, 10444 { EVENT_SYSTEM_CONTEXTHELPSTART, winevent_hook|wparam|lparam, OBJID_SOUND, 11 }, 10445 { EVENT_SYSTEM_CONTEXTHELPEND, winevent_hook|wparam|lparam, OBJID_QUERYCLASSNAMEIDX, 12 }, 10446 { EVENT_SYSTEM_DRAGDROPSTART, winevent_hook|wparam|lparam, OBJID_NATIVEOM, 13 }, 10447 { EVENT_SYSTEM_DRAGDROPEND, winevent_hook|wparam|lparam, OBJID_WINDOW, 0 }, 10448 { EVENT_SYSTEM_DIALOGSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 }, 10449 { EVENT_SYSTEM_DIALOGEND, winevent_hook|wparam|lparam, OBJID_TITLEBAR, 2 }, 10450 { EVENT_SYSTEM_SCROLLINGSTART, winevent_hook|wparam|lparam, OBJID_MENU, 3 }, 10451 { EVENT_SYSTEM_SCROLLINGEND, winevent_hook|wparam|lparam, OBJID_CLIENT, 4 }, 10452 { EVENT_SYSTEM_SWITCHSTART, winevent_hook|wparam|lparam, OBJID_VSCROLL, 5 }, 10453 { EVENT_SYSTEM_SWITCHEND, winevent_hook|wparam|lparam, OBJID_HSCROLL, 6 }, 10454 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, OBJID_SIZEGRIP, 7 }, 10455 { EVENT_SYSTEM_MINIMIZEEND, winevent_hook|wparam|lparam, OBJID_CARET, 8 }, 10456 { 0 } 10457 }; 10458 static const struct message WmWinEventCaretSeq[] = { 10459 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1 */ 10460 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1 */ 10461 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 2 */ 10462 { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1 */ 10463 { 0 } 10464 }; 10465 static const struct message WmWinEventCaretSeq_2[] = { 10466 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1/2 */ 10467 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1/2 */ 10468 { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1/2 */ 10469 { 0 } 10470 }; 10471 static const struct message WmWinEventAlertSeq[] = { 10472 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_ALERT, 0 }, 10473 { 0 } 10474 }; 10475 static const struct message WmWinEventAlertSeq_2[] = { 10476 /* create window in the thread proc */ 10477 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_WINDOW, 2 }, 10478 /* our test event */ 10479 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_ALERT, 2 }, 10480 { 0 } 10481 }; 10482 static const struct message WmGlobalHookSeq_1[] = { 10483 /* create window in the thread proc */ 10484 { HCBT_CREATEWND, hook|lparam, 0, 2 }, 10485 /* our test events */ 10486 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_PREVWINDOW, 2 }, 10487 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_NEXTWINDOW, 2 }, 10488 { 0 } 10489 }; 10490 static const struct message WmGlobalHookSeq_2[] = { 10491 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_NEXTWINDOW, 0 }, /* old local hook */ 10492 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_NEXTWINDOW, 2 }, /* new global hook */ 10493 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_PREVWINDOW, 0 }, /* old local hook */ 10494 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_PREVWINDOW, 2 }, /* new global hook */ 10495 { 0 } 10496 }; 10497 10498 static const struct message WmMouseLLHookSeq[] = { 10499 { WM_MOUSEMOVE, hook }, 10500 { WM_LBUTTONUP, hook }, 10501 { WM_MOUSEMOVE, hook }, 10502 { 0 } 10503 }; 10504 10505 static void CALLBACK win_event_global_hook_proc(HWINEVENTHOOK hevent, 10506 DWORD event, 10507 HWND hwnd, 10508 LONG object_id, 10509 LONG child_id, 10510 DWORD thread_id, 10511 DWORD event_time) 10512 { 10513 char buf[256]; 10514 10515 if (GetClassNameA(hwnd, buf, sizeof(buf))) 10516 { 10517 if (!lstrcmpiA(buf, "TestWindowClass") || 10518 !lstrcmpiA(buf, "static")) 10519 { 10520 struct recvd_message msg; 10521 10522 msg.hwnd = hwnd; 10523 msg.message = event; 10524 msg.flags = winevent_hook|wparam|lparam; 10525 msg.wParam = object_id; 10526 msg.lParam = (thread_id == GetCurrentThreadId()) ? child_id : (child_id + 2); 10527 msg.descr = "WEH_2"; 10528 add_message(&msg); 10529 } 10530 } 10531 } 10532 10533 static HHOOK hCBT_global_hook; 10534 static DWORD cbt_global_hook_thread_id; 10535 10536 static LRESULT CALLBACK cbt_global_hook_proc(int nCode, WPARAM wParam, LPARAM lParam) 10537 { 10538 HWND hwnd; 10539 char buf[256]; 10540 10541 if (nCode == HCBT_SYSCOMMAND) 10542 { 10543 struct recvd_message msg; 10544 10545 msg.hwnd = 0; 10546 msg.message = nCode; 10547 msg.flags = hook|wparam|lparam; 10548 msg.wParam = wParam; 10549 msg.lParam = (cbt_global_hook_thread_id == GetCurrentThreadId()) ? 1 : 2; 10550 msg.descr = "CBT_2"; 10551 add_message(&msg); 10552 10553 return CallNextHookEx(hCBT_global_hook, nCode, wParam, lParam); 10554 } 10555 /* WH_MOUSE_LL hook */ 10556 if (nCode == HC_ACTION) 10557 { 10558 MSLLHOOKSTRUCT *mhll = (MSLLHOOKSTRUCT *)lParam; 10559 10560 /* we can't test for real mouse events */ 10561 if (mhll->flags & LLMHF_INJECTED) 10562 { 10563 struct recvd_message msg; 10564 10565 memset (&msg, 0, sizeof (msg)); 10566 msg.message = wParam; 10567 msg.flags = hook; 10568 msg.descr = "CBT_2"; 10569 add_message(&msg); 10570 } 10571 return CallNextHookEx(hCBT_global_hook, nCode, wParam, lParam); 10572 } 10573 10574 /* Log also SetFocus(0) calls */ 10575 hwnd = wParam ? (HWND)wParam : (HWND)lParam; 10576 10577 if (GetClassNameA(hwnd, buf, sizeof(buf))) 10578 { 10579 if (!lstrcmpiA(buf, "TestWindowClass") || 10580 !lstrcmpiA(buf, "static")) 10581 { 10582 struct recvd_message msg; 10583 10584 msg.hwnd = hwnd; 10585 msg.message = nCode; 10586 msg.flags = hook|wparam|lparam; 10587 msg.wParam = wParam; 10588 msg.lParam = (cbt_global_hook_thread_id == GetCurrentThreadId()) ? 1 : 2; 10589 msg.descr = "CBT_2"; 10590 add_message(&msg); 10591 } 10592 } 10593 return CallNextHookEx(hCBT_global_hook, nCode, wParam, lParam); 10594 } 10595 10596 static DWORD WINAPI win_event_global_thread_proc(void *param) 10597 { 10598 HWND hwnd; 10599 MSG msg; 10600 HANDLE hevent = *(HANDLE *)param; 10601 10602 assert(pNotifyWinEvent); 10603 10604 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL); 10605 assert(hwnd); 10606 trace("created thread window %p\n", hwnd); 10607 10608 *(HWND *)param = hwnd; 10609 10610 flush_sequence(); 10611 /* this event should be received only by our new hook proc, 10612 * an old one does not expect an event from another thread. 10613 */ 10614 pNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, hwnd, OBJID_ALERT, 0); 10615 SetEvent(hevent); 10616 10617 while (GetMessageA(&msg, 0, 0, 0)) 10618 { 10619 TranslateMessage(&msg); 10620 DispatchMessageA(&msg); 10621 } 10622 return 0; 10623 } 10624 10625 static DWORD WINAPI cbt_global_hook_thread_proc(void *param) 10626 { 10627 HWND hwnd; 10628 MSG msg; 10629 HANDLE hevent = *(HANDLE *)param; 10630 10631 flush_sequence(); 10632 /* these events should be received only by our new hook proc, 10633 * an old one does not expect an event from another thread. 10634 */ 10635 10636 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL); 10637 assert(hwnd); 10638 trace("created thread window %p\n", hwnd); 10639 10640 *(HWND *)param = hwnd; 10641 10642 /* Windows doesn't like when a thread plays games with the focus, 10643 that leads to all kinds of misbehaviours and failures to activate 10644 a window. So, better keep next lines commented out. 10645 SetFocus(0); 10646 SetFocus(hwnd);*/ 10647 10648 DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_PREVWINDOW, 0); 10649 DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_NEXTWINDOW, 0); 10650 10651 SetEvent(hevent); 10652 10653 while (GetMessageA(&msg, 0, 0, 0)) 10654 { 10655 TranslateMessage(&msg); 10656 DispatchMessageA(&msg); 10657 } 10658 return 0; 10659 } 10660 10661 static DWORD WINAPI mouse_ll_global_thread_proc(void *param) 10662 { 10663 HWND hwnd; 10664 MSG msg; 10665 HANDLE hevent = *(HANDLE *)param; 10666 10667 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL); 10668 assert(hwnd); 10669 trace("created thread window %p\n", hwnd); 10670 10671 *(HWND *)param = hwnd; 10672 10673 flush_sequence(); 10674 10675 /* Windows doesn't like when a thread plays games with the focus, 10676 * that leads to all kinds of misbehaviours and failures to activate 10677 * a window. So, better don't generate a mouse click message below. 10678 */ 10679 mouse_event(MOUSEEVENTF_MOVE, -1, 0, 0, 0); 10680 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); 10681 mouse_event(MOUSEEVENTF_MOVE, 1, 0, 0, 0); 10682 10683 SetEvent(hevent); 10684 while (GetMessageA(&msg, 0, 0, 0)) 10685 { 10686 TranslateMessage(&msg); 10687 DispatchMessageA(&msg); 10688 } 10689 return 0; 10690 } 10691 10692 static void test_winevents(void) 10693 { 10694 BOOL ret; 10695 MSG msg; 10696 HWND hwnd, hwnd2; 10697 UINT i; 10698 HANDLE hthread, hevent; 10699 DWORD tid; 10700 HWINEVENTHOOK hhook; 10701 const struct message *events = WmWinEventsSeq; 10702 10703 hwnd = CreateWindowExA(0, "TestWindowClass", NULL, 10704 WS_OVERLAPPEDWINDOW, 10705 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0, 10706 NULL, NULL, 0); 10707 assert(hwnd); 10708 10709 /****** start of global hook test *************/ 10710 hCBT_global_hook = SetWindowsHookExA(WH_CBT, cbt_global_hook_proc, GetModuleHandleA(0), 0); 10711 if (!hCBT_global_hook) 10712 { 10713 ok(DestroyWindow(hwnd), "failed to destroy window\n"); 10714 skip( "cannot set global hook\n" ); 10715 return; 10716 } 10717 10718 hevent = CreateEventA(NULL, 0, 0, NULL); 10719 assert(hevent); 10720 hwnd2 = hevent; 10721 10722 hthread = CreateThread(NULL, 0, cbt_global_hook_thread_proc, &hwnd2, 0, &tid); 10723 ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError()); 10724 10725 ok(WaitForSingleObject(hevent, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 10726 10727 ok_sequence(WmGlobalHookSeq_1, "global hook 1", FALSE); 10728 10729 flush_sequence(); 10730 /* this one should be received only by old hook proc */ 10731 DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_NEXTWINDOW, 0); 10732 /* this one should be received only by old hook proc */ 10733 DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_PREVWINDOW, 0); 10734 10735 ok_sequence(WmGlobalHookSeq_2, "global hook 2", FALSE); 10736 10737 ret = UnhookWindowsHookEx(hCBT_global_hook); 10738 ok( ret, "UnhookWindowsHookEx error %d\n", GetLastError()); 10739 10740 PostThreadMessageA(tid, WM_QUIT, 0, 0); 10741 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 10742 CloseHandle(hthread); 10743 CloseHandle(hevent); 10744 ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n"); 10745 /****** end of global hook test *************/ 10746 10747 if (!pSetWinEventHook || !pNotifyWinEvent || !pUnhookWinEvent) 10748 { 10749 ok(DestroyWindow(hwnd), "failed to destroy window\n"); 10750 return; 10751 } 10752 10753 flush_sequence(); 10754 10755 if (0) 10756 { 10757 /* this test doesn't pass under Win9x */ 10758 /* win2k ignores events with hwnd == 0 */ 10759 SetLastError(0xdeadbeef); 10760 pNotifyWinEvent(events[0].message, 0, events[0].wParam, events[0].lParam); 10761 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || /* Win2k */ 10762 GetLastError() == 0xdeadbeef, /* Win9x */ 10763 "unexpected error %d\n", GetLastError()); 10764 ok_sequence(WmEmptySeq, "empty notify winevents", FALSE); 10765 } 10766 10767 for (i = 0; i < ARRAY_SIZE(WmWinEventsSeq); i++) 10768 pNotifyWinEvent(events[i].message, hwnd, events[i].wParam, events[i].lParam); 10769 10770 ok_sequence(WmWinEventsSeq, "notify winevents", FALSE); 10771 10772 /****** start of event filtering test *************/ 10773 hhook = pSetWinEventHook( 10774 EVENT_OBJECT_SHOW, /* 0x8002 */ 10775 EVENT_OBJECT_LOCATIONCHANGE, /* 0x800B */ 10776 GetModuleHandleA(0), win_event_global_hook_proc, 10777 GetCurrentProcessId(), 0, 10778 WINEVENT_INCONTEXT); 10779 ok(hhook != 0, "SetWinEventHook error %d\n", GetLastError()); 10780 10781 hevent = CreateEventA(NULL, 0, 0, NULL); 10782 assert(hevent); 10783 hwnd2 = hevent; 10784 10785 hthread = CreateThread(NULL, 0, win_event_global_thread_proc, &hwnd2, 0, &tid); 10786 ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError()); 10787 10788 ok(WaitForSingleObject(hevent, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 10789 10790 ok_sequence(WmWinEventAlertSeq, "alert winevent", FALSE); 10791 10792 flush_sequence(); 10793 /* this one should be received only by old hook proc */ 10794 pNotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_CARET, 0); /* 0x8000 */ 10795 pNotifyWinEvent(EVENT_OBJECT_SHOW, hwnd, OBJID_CARET, 0); /* 0x8002 */ 10796 /* this one should be received only by old hook proc */ 10797 pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, hwnd, OBJID_CARET, 0); /* 0x800C */ 10798 10799 ok_sequence(WmWinEventCaretSeq, "caret winevent", FALSE); 10800 10801 ret = pUnhookWinEvent(hhook); 10802 ok( ret, "UnhookWinEvent error %d\n", GetLastError()); 10803 10804 PostThreadMessageA(tid, WM_QUIT, 0, 0); 10805 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 10806 CloseHandle(hthread); 10807 CloseHandle(hevent); 10808 ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n"); 10809 /****** end of event filtering test *************/ 10810 10811 /****** start of out of context event test *************/ 10812 hhook = pSetWinEventHook(EVENT_MIN, EVENT_MAX, 0, 10813 win_event_global_hook_proc, GetCurrentProcessId(), 0, 10814 WINEVENT_OUTOFCONTEXT); 10815 ok(hhook != 0, "SetWinEventHook error %d\n", GetLastError()); 10816 10817 hevent = CreateEventA(NULL, 0, 0, NULL); 10818 assert(hevent); 10819 hwnd2 = hevent; 10820 10821 flush_sequence(); 10822 10823 hthread = CreateThread(NULL, 0, win_event_global_thread_proc, &hwnd2, 0, &tid); 10824 ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError()); 10825 10826 ok(WaitForSingleObject(hevent, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 10827 10828 ok_sequence(WmEmptySeq, "empty notify winevents", FALSE); 10829 /* process pending winevent messages */ 10830 ok(!PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE), "msg queue should be empty\n"); 10831 ok_sequence(WmWinEventAlertSeq_2, "alert winevent for out of context proc", FALSE); 10832 10833 flush_sequence(); 10834 /* this one should be received only by old hook proc */ 10835 pNotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_CARET, 0); /* 0x8000 */ 10836 pNotifyWinEvent(EVENT_OBJECT_SHOW, hwnd, OBJID_CARET, 0); /* 0x8002 */ 10837 /* this one should be received only by old hook proc */ 10838 pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, hwnd, OBJID_CARET, 0); /* 0x800C */ 10839 10840 ok_sequence(WmWinEventCaretSeq_2, "caret winevent for incontext proc", FALSE); 10841 /* process pending winevent messages */ 10842 ok(!PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE), "msg queue should be empty\n"); 10843 ok_sequence(WmWinEventCaretSeq_2, "caret winevent for out of context proc", FALSE); 10844 10845 ret = pUnhookWinEvent(hhook); 10846 ok( ret, "UnhookWinEvent error %d\n", GetLastError()); 10847 10848 PostThreadMessageA(tid, WM_QUIT, 0, 0); 10849 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 10850 CloseHandle(hthread); 10851 CloseHandle(hevent); 10852 ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n"); 10853 /****** end of out of context event test *************/ 10854 10855 /****** start of MOUSE_LL hook test *************/ 10856 hCBT_global_hook = SetWindowsHookExA(WH_MOUSE_LL, cbt_global_hook_proc, GetModuleHandleA(0), 0); 10857 /* WH_MOUSE_LL is not supported on Win9x platforms */ 10858 if (!hCBT_global_hook) 10859 { 10860 win_skip("Skipping WH_MOUSE_LL test on this platform\n"); 10861 goto skip_mouse_ll_hook_test; 10862 } 10863 10864 hevent = CreateEventA(NULL, 0, 0, NULL); 10865 assert(hevent); 10866 hwnd2 = hevent; 10867 10868 hthread = CreateThread(NULL, 0, mouse_ll_global_thread_proc, &hwnd2, 0, &tid); 10869 ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError()); 10870 10871 while (WaitForSingleObject(hevent, 100) == WAIT_TIMEOUT) 10872 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 10873 10874 ok_sequence(WmMouseLLHookSeq, "MOUSE_LL hook other thread", FALSE); 10875 flush_sequence(); 10876 10877 mouse_event(MOUSEEVENTF_MOVE, -1, 0, 0, 0); 10878 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); 10879 mouse_event(MOUSEEVENTF_MOVE, 1, 0, 0, 0); 10880 10881 ok_sequence(WmMouseLLHookSeq, "MOUSE_LL hook same thread", FALSE); 10882 10883 ret = UnhookWindowsHookEx(hCBT_global_hook); 10884 ok( ret, "UnhookWindowsHookEx error %d\n", GetLastError()); 10885 10886 PostThreadMessageA(tid, WM_QUIT, 0, 0); 10887 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 10888 CloseHandle(hthread); 10889 CloseHandle(hevent); 10890 ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n"); 10891 /****** end of MOUSE_LL hook test *************/ 10892 skip_mouse_ll_hook_test: 10893 10894 ok(DestroyWindow(hwnd), "failed to destroy window\n"); 10895 } 10896 10897 static void test_set_hook(void) 10898 { 10899 BOOL ret; 10900 HHOOK hhook; 10901 HWINEVENTHOOK hwinevent_hook; 10902 10903 hhook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, GetModuleHandleA(0), GetCurrentThreadId()); 10904 ok(hhook != 0, "local hook does not require hModule set to 0\n"); 10905 UnhookWindowsHookEx(hhook); 10906 10907 if (0) 10908 { 10909 /* this test doesn't pass under Win9x: BUG! */ 10910 SetLastError(0xdeadbeef); 10911 hhook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, 0); 10912 ok(!hhook, "global hook requires hModule != 0\n"); 10913 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD, "unexpected error %d\n", GetLastError()); 10914 } 10915 10916 SetLastError(0xdeadbeef); 10917 hhook = SetWindowsHookExA(WH_CBT, 0, GetModuleHandleA(0), GetCurrentThreadId()); 10918 ok(!hhook, "SetWinEventHook with invalid proc should fail\n"); 10919 ok(GetLastError() == ERROR_INVALID_FILTER_PROC || /* Win2k */ 10920 GetLastError() == 0xdeadbeef, /* Win9x */ 10921 "unexpected error %d\n", GetLastError()); 10922 10923 SetLastError(0xdeadbeef); 10924 ok(!UnhookWindowsHookEx((HHOOK)0xdeadbeef), "UnhookWindowsHookEx succeeded\n"); 10925 ok(GetLastError() == ERROR_INVALID_HOOK_HANDLE || /* Win2k */ 10926 GetLastError() == 0xdeadbeef, /* Win9x */ 10927 "unexpected error %d\n", GetLastError()); 10928 10929 if (!pSetWinEventHook || !pUnhookWinEvent) return; 10930 10931 /* even process local incontext hooks require hmodule */ 10932 SetLastError(0xdeadbeef); 10933 hwinevent_hook = pSetWinEventHook(EVENT_MIN, EVENT_MAX, 0, win_event_proc, 10934 GetCurrentProcessId(), 0, WINEVENT_INCONTEXT); 10935 ok(!hwinevent_hook, "WINEVENT_INCONTEXT requires hModule != 0\n"); 10936 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD || /* Win2k */ 10937 GetLastError() == 0xdeadbeef, /* Win9x */ 10938 "unexpected error %d\n", GetLastError()); 10939 10940 /* even thread local incontext hooks require hmodule */ 10941 SetLastError(0xdeadbeef); 10942 hwinevent_hook = pSetWinEventHook(EVENT_MIN, EVENT_MAX, 0, win_event_proc, 10943 GetCurrentProcessId(), GetCurrentThreadId(), WINEVENT_INCONTEXT); 10944 ok(!hwinevent_hook, "WINEVENT_INCONTEXT requires hModule != 0\n"); 10945 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD || /* Win2k */ 10946 GetLastError() == 0xdeadbeef, /* Win9x */ 10947 "unexpected error %d\n", GetLastError()); 10948 10949 if (0) 10950 { 10951 /* these 3 tests don't pass under Win9x */ 10952 SetLastError(0xdeadbeef); 10953 hwinevent_hook = pSetWinEventHook(1, 0, 0, win_event_proc, 10954 GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT); 10955 ok(!hwinevent_hook, "SetWinEventHook with invalid event range should fail\n"); 10956 ok(GetLastError() == ERROR_INVALID_HOOK_FILTER, "unexpected error %d\n", GetLastError()); 10957 10958 SetLastError(0xdeadbeef); 10959 hwinevent_hook = pSetWinEventHook(-1, 1, 0, win_event_proc, 10960 GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT); 10961 ok(!hwinevent_hook, "SetWinEventHook with invalid event range should fail\n"); 10962 ok(GetLastError() == ERROR_INVALID_HOOK_FILTER, "unexpected error %d\n", GetLastError()); 10963 10964 SetLastError(0xdeadbeef); 10965 hwinevent_hook = pSetWinEventHook(EVENT_MIN, EVENT_MAX, 0, win_event_proc, 10966 0, 0xdeadbeef, WINEVENT_OUTOFCONTEXT); 10967 ok(!hwinevent_hook, "SetWinEventHook with invalid tid should fail\n"); 10968 ok(GetLastError() == ERROR_INVALID_THREAD_ID, "unexpected error %d\n", GetLastError()); 10969 } 10970 10971 SetLastError(0xdeadbeef); 10972 hwinevent_hook = pSetWinEventHook(0, 0, 0, win_event_proc, 10973 GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT); 10974 ok(hwinevent_hook != 0, "SetWinEventHook error %d\n", GetLastError()); 10975 ok(GetLastError() == 0xdeadbeef, "unexpected error %d\n", GetLastError()); 10976 ret = pUnhookWinEvent(hwinevent_hook); 10977 ok( ret, "UnhookWinEvent error %d\n", GetLastError()); 10978 10979 todo_wine { 10980 /* This call succeeds under win2k SP4, but fails under Wine. 10981 Does win2k test/use passed process id? */ 10982 SetLastError(0xdeadbeef); 10983 hwinevent_hook = pSetWinEventHook(EVENT_MIN, EVENT_MAX, 0, win_event_proc, 10984 0xdeadbeef, 0, WINEVENT_OUTOFCONTEXT); 10985 ok(hwinevent_hook != 0, "SetWinEventHook error %d\n", GetLastError()); 10986 ok(GetLastError() == 0xdeadbeef, "unexpected error %d\n", GetLastError()); 10987 ret = pUnhookWinEvent(hwinevent_hook); 10988 ok( ret, "UnhookWinEvent error %d\n", GetLastError()); 10989 } 10990 10991 SetLastError(0xdeadbeef); 10992 ok(!pUnhookWinEvent((HWINEVENTHOOK)0xdeadbeef), "UnhookWinEvent succeeded\n"); 10993 ok(GetLastError() == ERROR_INVALID_HANDLE || /* Win2k */ 10994 GetLastError() == 0xdeadbeef, /* Win9x */ 10995 "unexpected error %d\n", GetLastError()); 10996 } 10997 10998 static HWND hook_hwnd; 10999 static HHOOK recursive_hook; 11000 static int hook_depth, max_hook_depth; 11001 11002 static LRESULT WINAPI rec_get_message_hook(int code, WPARAM w, LPARAM l) 11003 { 11004 LRESULT res; 11005 MSG msg; 11006 BOOL b; 11007 11008 hook_depth++; 11009 if(hook_depth > max_hook_depth) 11010 max_hook_depth = hook_depth; 11011 11012 b = PeekMessageW(&msg, hook_hwnd, 0, 0, PM_NOREMOVE); 11013 ok(b, "PeekMessage failed\n"); 11014 11015 res = CallNextHookEx(recursive_hook, code, w, l); 11016 11017 hook_depth--; 11018 return res; 11019 } 11020 11021 static void test_recursive_hook(void) 11022 { 11023 MSG msg; 11024 BOOL b; 11025 11026 hook_hwnd = CreateWindowA("Static", NULL, WS_POPUP, 0, 0, 200, 60, NULL, NULL, NULL, NULL); 11027 ok(hook_hwnd != NULL, "CreateWindow failed\n"); 11028 11029 recursive_hook = SetWindowsHookExW(WH_GETMESSAGE, rec_get_message_hook, NULL, GetCurrentThreadId()); 11030 ok(recursive_hook != NULL, "SetWindowsHookEx failed\n"); 11031 11032 PostMessageW(hook_hwnd, WM_USER, 0, 0); 11033 PostMessageW(hook_hwnd, WM_USER+1, 0, 0); 11034 11035 hook_depth = 0; 11036 GetMessageW(&msg, hook_hwnd, 0, 0); 11037 ok(15 <= max_hook_depth && max_hook_depth < 45, "max_hook_depth = %d\n", max_hook_depth); 11038 trace("max_hook_depth = %d\n", max_hook_depth); 11039 11040 b = UnhookWindowsHookEx(recursive_hook); 11041 ok(b, "UnhokWindowsHookEx failed\n"); 11042 11043 DestroyWindow(hook_hwnd); 11044 } 11045 11046 static const struct message ScrollWindowPaint1[] = { 11047 { WM_PAINT, sent }, 11048 { WM_ERASEBKGND, sent|beginpaint }, 11049 { WM_GETTEXTLENGTH, sent|optional }, 11050 { WM_PAINT, sent|optional }, 11051 { WM_NCPAINT, sent|beginpaint|optional }, 11052 { WM_GETTEXT, sent|beginpaint|optional }, 11053 { WM_GETTEXT, sent|beginpaint|optional }, 11054 { WM_GETTEXT, sent|beginpaint|optional }, 11055 { WM_GETTEXT, sent|beginpaint|defwinproc|optional }, 11056 { WM_ERASEBKGND, sent|beginpaint|optional }, 11057 { 0 } 11058 }; 11059 11060 static const struct message ScrollWindowPaint2[] = { 11061 { WM_PAINT, sent }, 11062 { 0 } 11063 }; 11064 11065 static void test_scrollwindowex(void) 11066 { 11067 HWND hwnd, hchild; 11068 RECT rect={0,0,130,130}; 11069 11070 hwnd = CreateWindowExA(0, "TestWindowClass", "Test Scroll", 11071 WS_VISIBLE|WS_OVERLAPPEDWINDOW, 11072 100, 100, 200, 200, 0, 0, 0, NULL); 11073 ok (hwnd != 0, "Failed to create overlapped window\n"); 11074 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", 11075 WS_VISIBLE|WS_CAPTION|WS_CHILD, 11076 10, 10, 150, 150, hwnd, 0, 0, NULL); 11077 ok (hchild != 0, "Failed to create child\n"); 11078 UpdateWindow(hwnd); 11079 flush_events(); 11080 flush_sequence(); 11081 11082 /* scroll without the child window */ 11083 trace("start scroll\n"); 11084 ScrollWindowEx( hwnd, 10, 10, &rect, NULL, NULL, NULL, 11085 SW_ERASE|SW_INVALIDATE); 11086 ok_sequence(WmEmptySeq, "ScrollWindowEx", FALSE); 11087 trace("end scroll\n"); 11088 flush_sequence(); 11089 flush_events(); 11090 ok_sequence(ScrollWindowPaint1, "ScrollWindowEx", FALSE); 11091 flush_events(); 11092 flush_sequence(); 11093 11094 /* Now without the SW_ERASE flag */ 11095 trace("start scroll\n"); 11096 ScrollWindowEx( hwnd, 10, 10, &rect, NULL, NULL, NULL, SW_INVALIDATE); 11097 ok_sequence(WmEmptySeq, "ScrollWindowEx", FALSE); 11098 trace("end scroll\n"); 11099 flush_sequence(); 11100 flush_events(); 11101 ok_sequence(ScrollWindowPaint2, "ScrollWindowEx", FALSE); 11102 flush_events(); 11103 flush_sequence(); 11104 11105 /* now scroll the child window as well */ 11106 trace("start scroll\n"); 11107 ScrollWindowEx( hwnd, 10, 10, &rect, NULL, NULL, NULL, 11108 SW_SCROLLCHILDREN|SW_ERASE|SW_INVALIDATE); 11109 /* wine sends WM_POSCHANGING, WM_POSCHANGED messages */ 11110 /* windows sometimes a WM_MOVE */ 11111 ok_sequence(WmEmptySeq, "ScrollWindowEx", TRUE); 11112 trace("end scroll\n"); 11113 flush_sequence(); 11114 flush_events(); 11115 ok_sequence(ScrollWindowPaint1, "ScrollWindowEx", FALSE); 11116 flush_events(); 11117 flush_sequence(); 11118 11119 /* now scroll with ScrollWindow() */ 11120 trace("start scroll with ScrollWindow\n"); 11121 ScrollWindow( hwnd, 5, 5, NULL, NULL); 11122 trace("end scroll\n"); 11123 flush_sequence(); 11124 flush_events(); 11125 ok_sequence(ScrollWindowPaint1, "ScrollWindow", FALSE); 11126 11127 ok(DestroyWindow(hchild), "failed to destroy window\n"); 11128 ok(DestroyWindow(hwnd), "failed to destroy window\n"); 11129 flush_sequence(); 11130 } 11131 11132 static const struct message destroy_window_with_children[] = { 11133 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, /* popup */ 11134 { HCBT_DESTROYWND, hook|lparam, 0, WND_PARENT_ID }, /* parent */ 11135 { 0x0090, sent|optional }, 11136 { HCBT_DESTROYWND, hook|lparam, 0, WND_POPUP_ID }, /* popup */ 11137 { 0x0090, sent|optional }, 11138 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, /* popup */ 11139 { WM_DESTROY, sent|wparam|lparam, 0, WND_POPUP_ID }, /* popup */ 11140 { WM_CAPTURECHANGED, sent|wparam|lparam, 0, WND_POPUP_ID }, /* popup */ 11141 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_POPUP_ID }, /* popup */ 11142 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, /* parent */ 11143 { WM_DESTROY, sent|wparam|lparam, 0, WND_PARENT_ID }, /* parent */ 11144 { WM_DESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 2 }, /* child2 */ 11145 { WM_DESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 1 }, /* child1 */ 11146 { WM_DESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 3 }, /* child3 */ 11147 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 2 }, /* child2 */ 11148 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 3 }, /* child3 */ 11149 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 1 }, /* child1 */ 11150 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_PARENT_ID }, /* parent */ 11151 { 0 } 11152 }; 11153 11154 static void test_DestroyWindow(void) 11155 { 11156 BOOL ret; 11157 HWND parent, child1, child2, child3, child4, test; 11158 UINT_PTR child_id = WND_CHILD_ID + 1; 11159 11160 parent = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, 11161 100, 100, 200, 200, 0, 0, 0, NULL); 11162 assert(parent != 0); 11163 child1 = CreateWindowExA(0, "TestWindowClass", NULL, WS_CHILD, 11164 0, 0, 50, 50, parent, (HMENU)child_id++, 0, NULL); 11165 assert(child1 != 0); 11166 child2 = CreateWindowExA(0, "TestWindowClass", NULL, WS_CHILD, 11167 0, 0, 50, 50, GetDesktopWindow(), (HMENU)child_id++, 0, NULL); 11168 assert(child2 != 0); 11169 child3 = CreateWindowExA(0, "TestWindowClass", NULL, WS_CHILD, 11170 0, 0, 50, 50, child1, (HMENU)child_id++, 0, NULL); 11171 assert(child3 != 0); 11172 child4 = CreateWindowExA(0, "TestWindowClass", NULL, WS_POPUP, 11173 0, 0, 50, 50, parent, 0, 0, NULL); 11174 assert(child4 != 0); 11175 11176 /* test owner/parent of child2 */ 11177 test = GetParent(child2); 11178 ok(test == GetDesktopWindow(), "wrong parent %p\n", test); 11179 ok(!IsChild(parent, child2), "wrong parent/child %p/%p\n", parent, child2); 11180 if(pGetAncestor) { 11181 test = pGetAncestor(child2, GA_PARENT); 11182 ok(test == GetDesktopWindow(), "wrong parent %p\n", test); 11183 } 11184 test = GetWindow(child2, GW_OWNER); 11185 ok(!test, "wrong owner %p\n", test); 11186 11187 test = SetParent(child2, parent); 11188 ok(test == GetDesktopWindow(), "wrong old parent %p\n", test); 11189 11190 /* test owner/parent of the parent */ 11191 test = GetParent(parent); 11192 ok(!test, "wrong parent %p\n", test); 11193 ok(!IsChild(GetDesktopWindow(), parent), "wrong parent/child %p/%p\n", GetDesktopWindow(), parent); 11194 if(pGetAncestor) { 11195 test = pGetAncestor(parent, GA_PARENT); 11196 ok(test == GetDesktopWindow(), "wrong parent %p\n", test); 11197 } 11198 test = GetWindow(parent, GW_OWNER); 11199 ok(!test, "wrong owner %p\n", test); 11200 11201 /* test owner/parent of child1 */ 11202 test = GetParent(child1); 11203 ok(test == parent, "wrong parent %p\n", test); 11204 ok(IsChild(parent, child1), "wrong parent/child %p/%p\n", parent, child1); 11205 if(pGetAncestor) { 11206 test = pGetAncestor(child1, GA_PARENT); 11207 ok(test == parent, "wrong parent %p\n", test); 11208 } 11209 test = GetWindow(child1, GW_OWNER); 11210 ok(!test, "wrong owner %p\n", test); 11211 11212 /* test owner/parent of child2 */ 11213 test = GetParent(child2); 11214 ok(test == parent, "wrong parent %p\n", test); 11215 ok(IsChild(parent, child2), "wrong parent/child %p/%p\n", parent, child2); 11216 if(pGetAncestor) { 11217 test = pGetAncestor(child2, GA_PARENT); 11218 ok(test == parent, "wrong parent %p\n", test); 11219 } 11220 test = GetWindow(child2, GW_OWNER); 11221 ok(!test, "wrong owner %p\n", test); 11222 11223 /* test owner/parent of child3 */ 11224 test = GetParent(child3); 11225 ok(test == child1, "wrong parent %p\n", test); 11226 ok(IsChild(parent, child3), "wrong parent/child %p/%p\n", parent, child3); 11227 if(pGetAncestor) { 11228 test = pGetAncestor(child3, GA_PARENT); 11229 ok(test == child1, "wrong parent %p\n", test); 11230 } 11231 test = GetWindow(child3, GW_OWNER); 11232 ok(!test, "wrong owner %p\n", test); 11233 11234 /* test owner/parent of child4 */ 11235 test = GetParent(child4); 11236 ok(test == parent, "wrong parent %p\n", test); 11237 ok(!IsChild(parent, child4), "wrong parent/child %p/%p\n", parent, child4); 11238 if(pGetAncestor) { 11239 test = pGetAncestor(child4, GA_PARENT); 11240 ok(test == GetDesktopWindow(), "wrong parent %p\n", test); 11241 } 11242 test = GetWindow(child4, GW_OWNER); 11243 ok(test == parent, "wrong owner %p\n", test); 11244 11245 flush_sequence(); 11246 11247 trace("parent %p, child1 %p, child2 %p, child3 %p, child4 %p\n", 11248 parent, child1, child2, child3, child4); 11249 11250 SetCapture(child4); 11251 test = GetCapture(); 11252 ok(test == child4, "wrong capture window %p\n", test); 11253 11254 test_DestroyWindow_flag = TRUE; 11255 ret = DestroyWindow(parent); 11256 ok( ret, "DestroyWindow() error %d\n", GetLastError()); 11257 test_DestroyWindow_flag = FALSE; 11258 ok_sequence(destroy_window_with_children, "destroy window with children", FALSE); 11259 11260 ok(!IsWindow(parent), "parent still exists\n"); 11261 ok(!IsWindow(child1), "child1 still exists\n"); 11262 ok(!IsWindow(child2), "child2 still exists\n"); 11263 ok(!IsWindow(child3), "child3 still exists\n"); 11264 ok(!IsWindow(child4), "child4 still exists\n"); 11265 11266 test = GetCapture(); 11267 ok(!test, "wrong capture window %p\n", test); 11268 } 11269 11270 11271 static const struct message WmDispatchPaint[] = { 11272 { WM_NCPAINT, sent }, 11273 { WM_GETTEXT, sent|defwinproc|optional }, 11274 { WM_GETTEXT, sent|defwinproc|optional }, 11275 { WM_ERASEBKGND, sent }, 11276 { 0 } 11277 }; 11278 11279 static LRESULT WINAPI DispatchMessageCheckProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 11280 { 11281 if (message == WM_PAINT) return 0; 11282 return MsgCheckProcA( hwnd, message, wParam, lParam ); 11283 } 11284 11285 static void test_DispatchMessage(void) 11286 { 11287 RECT rect; 11288 MSG msg; 11289 int count; 11290 HWND hwnd = CreateWindowA( "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, 11291 100, 100, 200, 200, 0, 0, 0, NULL); 11292 ShowWindow( hwnd, SW_SHOW ); 11293 UpdateWindow( hwnd ); 11294 flush_events(); 11295 flush_sequence(); 11296 SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (LONG_PTR)DispatchMessageCheckProc ); 11297 11298 SetRect( &rect, -5, -5, 5, 5 ); 11299 RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE|RDW_ERASE|RDW_FRAME ); 11300 count = 0; 11301 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) 11302 { 11303 if (msg.message != WM_PAINT) DispatchMessageA( &msg ); 11304 else 11305 { 11306 flush_sequence(); 11307 DispatchMessageA( &msg ); 11308 /* DispatchMessage will send WM_NCPAINT if non client area is still invalid after WM_PAINT */ 11309 if (!count) ok_sequence( WmDispatchPaint, "WmDispatchPaint", FALSE ); 11310 else ok_sequence( WmEmptySeq, "WmEmpty", FALSE ); 11311 if (++count > 10) break; 11312 } 11313 } 11314 ok( msg.message == WM_PAINT && count > 10, "WM_PAINT messages stopped\n" ); 11315 11316 trace("now without DispatchMessage\n"); 11317 flush_sequence(); 11318 RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE|RDW_ERASE|RDW_FRAME ); 11319 count = 0; 11320 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) 11321 { 11322 if (msg.message != WM_PAINT) DispatchMessageA( &msg ); 11323 else 11324 { 11325 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 ); 11326 flush_sequence(); 11327 /* this will send WM_NCCPAINT just like DispatchMessage does */ 11328 GetUpdateRgn( hwnd, hrgn, TRUE ); 11329 ok_sequence( WmDispatchPaint, "WmDispatchPaint", FALSE ); 11330 DeleteObject( hrgn ); 11331 GetClientRect( hwnd, &rect ); 11332 ValidateRect( hwnd, &rect ); /* this will stop WM_PAINTs */ 11333 ok( !count, "Got multiple WM_PAINTs\n" ); 11334 if (++count > 10) break; 11335 } 11336 } 11337 11338 flush_sequence(); 11339 RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE|RDW_ERASE|RDW_FRAME ); 11340 count = 0; 11341 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) 11342 { 11343 if (msg.message != WM_PAINT) DispatchMessageA( &msg ); 11344 else 11345 { 11346 HDC hdc; 11347 11348 flush_sequence(); 11349 hdc = BeginPaint( hwnd, NULL ); 11350 ok( !hdc, "got valid hdc %p from BeginPaint\n", hdc ); 11351 ok( !EndPaint( hwnd, NULL ), "EndPaint succeeded\n" ); 11352 ok_sequence( WmDispatchPaint, "WmDispatchPaint", FALSE ); 11353 ok( !count, "Got multiple WM_PAINTs\n" ); 11354 if (++count > 10) break; 11355 } 11356 } 11357 DestroyWindow(hwnd); 11358 } 11359 11360 11361 static const struct message WmUser[] = { 11362 { WM_USER, sent }, 11363 { 0 } 11364 }; 11365 11366 struct sendmsg_info 11367 { 11368 HWND hwnd; 11369 DWORD timeout; 11370 DWORD ret; 11371 }; 11372 11373 static DWORD CALLBACK send_msg_thread( LPVOID arg ) 11374 { 11375 struct sendmsg_info *info = arg; 11376 SetLastError( 0xdeadbeef ); 11377 info->ret = SendMessageTimeoutA( info->hwnd, WM_USER, 0, 0, 0, info->timeout, NULL ); 11378 if (!info->ret) ok( GetLastError() == ERROR_TIMEOUT || 11379 broken(GetLastError() == 0), /* win9x */ 11380 "unexpected error %d\n", GetLastError()); 11381 return 0; 11382 } 11383 11384 static void wait_for_thread( HANDLE thread ) 11385 { 11386 while (MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_SENDMESSAGE) != WAIT_OBJECT_0) 11387 { 11388 MSG msg; 11389 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA(&msg); 11390 } 11391 } 11392 11393 static LRESULT WINAPI send_msg_delay_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 11394 { 11395 if (message == WM_USER) Sleep(200); 11396 return MsgCheckProcA( hwnd, message, wParam, lParam ); 11397 } 11398 11399 static void test_SendMessageTimeout(void) 11400 { 11401 HANDLE thread; 11402 struct sendmsg_info info; 11403 DWORD tid; 11404 BOOL is_win9x; 11405 11406 info.hwnd = CreateWindowA( "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, 11407 100, 100, 200, 200, 0, 0, 0, NULL); 11408 flush_events(); 11409 flush_sequence(); 11410 11411 info.timeout = 1000; 11412 info.ret = 0xdeadbeef; 11413 thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid ); 11414 wait_for_thread( thread ); 11415 CloseHandle( thread ); 11416 ok( info.ret == 1, "SendMessageTimeout failed\n" ); 11417 ok_sequence( WmUser, "WmUser", FALSE ); 11418 11419 info.timeout = 1; 11420 info.ret = 0xdeadbeef; 11421 thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid ); 11422 Sleep(100); /* SendMessageTimeout should time out here */ 11423 wait_for_thread( thread ); 11424 CloseHandle( thread ); 11425 ok( info.ret == 0, "SendMessageTimeout succeeded\n" ); 11426 ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE ); 11427 11428 /* 0 means infinite timeout (but not on win9x) */ 11429 info.timeout = 0; 11430 info.ret = 0xdeadbeef; 11431 thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid ); 11432 Sleep(100); 11433 wait_for_thread( thread ); 11434 CloseHandle( thread ); 11435 is_win9x = !info.ret; 11436 if (is_win9x) ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE ); 11437 else ok_sequence( WmUser, "WmUser", FALSE ); 11438 11439 /* timeout is treated as signed despite the prototype (but not on win9x) */ 11440 info.timeout = 0x7fffffff; 11441 info.ret = 0xdeadbeef; 11442 thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid ); 11443 Sleep(100); 11444 wait_for_thread( thread ); 11445 CloseHandle( thread ); 11446 ok( info.ret == 1, "SendMessageTimeout failed\n" ); 11447 ok_sequence( WmUser, "WmUser", FALSE ); 11448 11449 info.timeout = 0x80000000; 11450 info.ret = 0xdeadbeef; 11451 thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid ); 11452 Sleep(100); 11453 wait_for_thread( thread ); 11454 CloseHandle( thread ); 11455 if (is_win9x) 11456 { 11457 ok( info.ret == 1, "SendMessageTimeout failed\n" ); 11458 ok_sequence( WmUser, "WmUser", FALSE ); 11459 } 11460 else 11461 { 11462 ok( info.ret == 0, "SendMessageTimeout succeeded\n" ); 11463 ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE ); 11464 } 11465 11466 /* now check for timeout during message processing */ 11467 SetWindowLongPtrA( info.hwnd, GWLP_WNDPROC, (LONG_PTR)send_msg_delay_proc ); 11468 info.timeout = 100; 11469 info.ret = 0xdeadbeef; 11470 thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid ); 11471 wait_for_thread( thread ); 11472 CloseHandle( thread ); 11473 /* we should time out but still get the message */ 11474 ok( info.ret == 0, "SendMessageTimeout failed\n" ); 11475 ok_sequence( WmUser, "WmUser", FALSE ); 11476 11477 DestroyWindow( info.hwnd ); 11478 } 11479 11480 11481 /****************** edit message test *************************/ 11482 #define ID_EDIT 0x1234 11483 static const struct message sl_edit_setfocus[] = 11484 { 11485 { HCBT_SETFOCUS, hook }, 11486 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 11487 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 11488 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 11489 { WM_SETFOCUS, sent|wparam, 0 }, 11490 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 10 }, 11491 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 15 }, 11492 { WM_CTLCOLOREDIT, sent|parent }, 11493 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 11 }, 11494 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11495 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11496 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) }, 11497 { 0 } 11498 }; 11499 static const struct message sl_edit_invisible[] = 11500 { 11501 { HCBT_SETFOCUS, hook }, 11502 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 11503 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 11504 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 11505 { WM_KILLFOCUS, sent|parent }, 11506 { WM_SETFOCUS, sent }, 11507 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) }, 11508 { 0 } 11509 }; 11510 static const struct message ml_edit_setfocus[] = 11511 { 11512 { HCBT_SETFOCUS, hook }, 11513 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 11514 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 11515 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 11516 { WM_SETFOCUS, sent|wparam, 0 }, 11517 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 10 }, 11518 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 11 }, 11519 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11520 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11521 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) }, 11522 { 0 } 11523 }; 11524 static const struct message sl_edit_killfocus[] = 11525 { 11526 { HCBT_SETFOCUS, hook }, 11527 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 11528 { WM_KILLFOCUS, sent|wparam, 0 }, 11529 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11530 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11531 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_KILLFOCUS) }, 11532 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 11533 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, 11534 { 0 } 11535 }; 11536 static const struct message sl_edit_lbutton_dblclk[] = 11537 { 11538 { WM_LBUTTONDBLCLK, sent }, 11539 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, 11540 { 0 } 11541 }; 11542 static const struct message sl_edit_lbutton_down[] = 11543 { 11544 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 }, 11545 { HCBT_SETFOCUS, hook }, 11546 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 11547 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 11548 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 11549 { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, 11550 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 10 }, 11551 { WM_CTLCOLOREDIT, sent|parent }, 11552 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 11 }, 11553 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11554 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11555 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11556 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) }, 11557 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, 11558 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11559 { WM_CTLCOLOREDIT, sent|parent|optional }, 11560 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 11 }, 11561 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11562 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11563 { 0 } 11564 }; 11565 static const struct message ml_edit_lbutton_down[] = 11566 { 11567 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 }, 11568 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, 11569 { HCBT_SETFOCUS, hook }, 11570 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 11571 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 11572 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 11573 { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, 11574 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 10 }, 11575 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 11 }, 11576 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11577 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11578 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) }, 11579 { 0 } 11580 }; 11581 static const struct message sl_edit_lbutton_up[] = 11582 { 11583 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 }, 11584 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11585 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, 11586 { WM_CAPTURECHANGED, sent|defwinproc }, 11587 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 11588 { 0 } 11589 }; 11590 static const struct message ml_edit_lbutton_up[] = 11591 { 11592 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 }, 11593 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, 11594 { WM_CAPTURECHANGED, sent|defwinproc }, 11595 { 0 } 11596 }; 11597 11598 static WNDPROC old_edit_proc; 11599 11600 static LRESULT CALLBACK edit_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 11601 { 11602 static LONG defwndproc_counter = 0; 11603 LRESULT ret; 11604 struct recvd_message msg; 11605 11606 if (ignore_message( message )) return 0; 11607 11608 msg.hwnd = hwnd; 11609 msg.message = message; 11610 msg.flags = sent|wparam|lparam; 11611 if (defwndproc_counter) msg.flags |= defwinproc; 11612 msg.wParam = wParam; 11613 msg.lParam = lParam; 11614 msg.descr = "edit"; 11615 add_message(&msg); 11616 11617 defwndproc_counter++; 11618 ret = CallWindowProcA(old_edit_proc, hwnd, message, wParam, lParam); 11619 defwndproc_counter--; 11620 11621 return ret; 11622 } 11623 11624 static void subclass_edit(void) 11625 { 11626 WNDCLASSA cls; 11627 11628 if (!GetClassInfoA(0, "edit", &cls)) assert(0); 11629 11630 old_edit_proc = cls.lpfnWndProc; 11631 11632 cls.hInstance = GetModuleHandleA(NULL); 11633 cls.lpfnWndProc = edit_hook_proc; 11634 cls.lpszClassName = "my_edit_class"; 11635 UnregisterClassA(cls.lpszClassName, cls.hInstance); 11636 if (!RegisterClassA(&cls)) assert(0); 11637 } 11638 11639 static void test_edit_messages(void) 11640 { 11641 HWND hwnd, parent; 11642 DWORD dlg_code; 11643 11644 subclass_edit(); 11645 log_all_parent_messages++; 11646 11647 parent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 11648 100, 100, 200, 200, 0, 0, 0, NULL); 11649 ok (parent != 0, "Failed to create parent window\n"); 11650 11651 /* test single line edit */ 11652 hwnd = CreateWindowExA(0, "my_edit_class", "test", WS_CHILD, 11653 0, 0, 80, 20, parent, (HMENU)ID_EDIT, 0, NULL); 11654 ok(hwnd != 0, "Failed to create edit window\n"); 11655 11656 dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0); 11657 ok(dlg_code == (DLGC_WANTCHARS|DLGC_HASSETSEL|DLGC_WANTARROWS), "wrong dlg_code %08x\n", dlg_code); 11658 11659 flush_sequence(); 11660 SetFocus(hwnd); 11661 ok_sequence(sl_edit_invisible, "SetFocus(hwnd) on an invisible edit", FALSE); 11662 11663 ShowWindow(hwnd, SW_SHOW); 11664 UpdateWindow(hwnd); 11665 SetFocus(0); 11666 flush_sequence(); 11667 11668 SetFocus(hwnd); 11669 ok_sequence(sl_edit_setfocus, "SetFocus(hwnd) on an edit", FALSE); 11670 11671 SetFocus(0); 11672 ok_sequence(sl_edit_killfocus, "SetFocus(0) on an edit", FALSE); 11673 11674 SetFocus(0); 11675 ReleaseCapture(); 11676 flush_sequence(); 11677 11678 SendMessageA(hwnd, WM_LBUTTONDBLCLK, 0, 0); 11679 ok_sequence(sl_edit_lbutton_dblclk, "WM_LBUTTONDBLCLK on an edit", FALSE); 11680 11681 SetFocus(0); 11682 ReleaseCapture(); 11683 flush_sequence(); 11684 11685 SendMessageA(hwnd, WM_LBUTTONDOWN, 0, 0); 11686 ok_sequence(sl_edit_lbutton_down, "WM_LBUTTONDOWN on an edit", FALSE); 11687 11688 SendMessageA(hwnd, WM_LBUTTONUP, 0, 0); 11689 ok_sequence(sl_edit_lbutton_up, "WM_LBUTTONUP on an edit", FALSE); 11690 11691 DestroyWindow(hwnd); 11692 11693 /* test multiline edit */ 11694 hwnd = CreateWindowExA(0, "my_edit_class", "test", WS_CHILD | ES_MULTILINE, 11695 0, 0, 80, 20, parent, (HMENU)ID_EDIT, 0, NULL); 11696 ok(hwnd != 0, "Failed to create edit window\n"); 11697 11698 dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0); 11699 ok(dlg_code == (DLGC_WANTCHARS|DLGC_HASSETSEL|DLGC_WANTARROWS|DLGC_WANTALLKEYS), 11700 "wrong dlg_code %08x\n", dlg_code); 11701 11702 ShowWindow(hwnd, SW_SHOW); 11703 UpdateWindow(hwnd); 11704 SetFocus(0); 11705 flush_sequence(); 11706 11707 SetFocus(hwnd); 11708 ok_sequence(ml_edit_setfocus, "SetFocus(hwnd) on multiline edit", FALSE); 11709 11710 SetFocus(0); 11711 ok_sequence(sl_edit_killfocus, "SetFocus(0) on multiline edit", FALSE); 11712 11713 SetFocus(0); 11714 ReleaseCapture(); 11715 flush_sequence(); 11716 11717 SendMessageA(hwnd, WM_LBUTTONDBLCLK, 0, 0); 11718 ok_sequence(sl_edit_lbutton_dblclk, "WM_LBUTTONDBLCLK on multiline edit", FALSE); 11719 11720 SetFocus(0); 11721 ReleaseCapture(); 11722 flush_sequence(); 11723 11724 SendMessageA(hwnd, WM_LBUTTONDOWN, 0, 0); 11725 ok_sequence(ml_edit_lbutton_down, "WM_LBUTTONDOWN on multiline edit", FALSE); 11726 11727 SendMessageA(hwnd, WM_LBUTTONUP, 0, 0); 11728 ok_sequence(ml_edit_lbutton_up, "WM_LBUTTONUP on multiline edit", FALSE); 11729 11730 DestroyWindow(hwnd); 11731 DestroyWindow(parent); 11732 11733 log_all_parent_messages--; 11734 } 11735 11736 /**************************** End of Edit test ******************************/ 11737 11738 static const struct message WmKeyDownSkippedSeq[] = 11739 { 11740 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */ 11741 { 0 } 11742 }; 11743 static const struct message WmKeyDownWasDownSkippedSeq[] = 11744 { 11745 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0x40000001 }, /* XP */ 11746 { 0 } 11747 }; 11748 static const struct message WmKeyUpSkippedSeq[] = 11749 { 11750 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */ 11751 { 0 } 11752 }; 11753 static const struct message WmUserKeyUpSkippedSeq[] = 11754 { 11755 { WM_USER, sent }, 11756 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */ 11757 { 0 } 11758 }; 11759 11760 #define EV_STOP 0 11761 #define EV_SENDMSG 1 11762 #define EV_ACK 2 11763 11764 struct peekmsg_info 11765 { 11766 HWND hwnd; 11767 HANDLE hevent[3]; /* 0 - start/stop, 1 - SendMessage, 2 - ack */ 11768 }; 11769 11770 static DWORD CALLBACK send_msg_thread_2(void *param) 11771 { 11772 DWORD ret; 11773 struct peekmsg_info *info = param; 11774 11775 trace("thread: looping\n"); 11776 SetEvent(info->hevent[EV_ACK]); 11777 11778 while (1) 11779 { 11780 ret = WaitForMultipleObjects(2, info->hevent, FALSE, INFINITE); 11781 11782 switch (ret) 11783 { 11784 case WAIT_OBJECT_0 + EV_STOP: 11785 trace("thread: exiting\n"); 11786 return 0; 11787 11788 case WAIT_OBJECT_0 + EV_SENDMSG: 11789 trace("thread: sending message\n"); 11790 ret = SendNotifyMessageA(info->hwnd, WM_USER, 0, 0); 11791 ok(ret, "SendNotifyMessageA failed error %u\n", GetLastError()); 11792 SetEvent(info->hevent[EV_ACK]); 11793 break; 11794 11795 default: 11796 trace("unexpected return: %04x\n", ret); 11797 assert(0); 11798 break; 11799 } 11800 } 11801 return 0; 11802 } 11803 11804 static void test_PeekMessage(void) 11805 { 11806 MSG msg; 11807 HANDLE hthread; 11808 DWORD tid, qstatus; 11809 UINT qs_all_input = QS_ALLINPUT; 11810 UINT qs_input = QS_INPUT; 11811 BOOL ret; 11812 struct peekmsg_info info; 11813 11814 info.hwnd = CreateWindowA("TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, 11815 100, 100, 200, 200, 0, 0, 0, NULL); 11816 assert(info.hwnd); 11817 ShowWindow(info.hwnd, SW_SHOW); 11818 UpdateWindow(info.hwnd); 11819 SetFocus(info.hwnd); 11820 11821 info.hevent[EV_STOP] = CreateEventA(NULL, 0, 0, NULL); 11822 info.hevent[EV_SENDMSG] = CreateEventA(NULL, 0, 0, NULL); 11823 info.hevent[EV_ACK] = CreateEventA(NULL, 0, 0, NULL); 11824 11825 hthread = CreateThread(NULL, 0, send_msg_thread_2, &info, 0, &tid); 11826 WaitForSingleObject(info.hevent[EV_ACK], 10000); 11827 11828 flush_events(); 11829 flush_sequence(); 11830 11831 SetLastError(0xdeadbeef); 11832 qstatus = GetQueueStatus(qs_all_input); 11833 if (GetLastError() == ERROR_INVALID_FLAGS) 11834 { 11835 trace("QS_RAWINPUT not supported on this platform\n"); 11836 qs_all_input &= ~QS_RAWINPUT; 11837 qs_input &= ~QS_RAWINPUT; 11838 } 11839 if (qstatus & QS_POSTMESSAGE) 11840 { 11841 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) /* nothing */ ; 11842 qstatus = GetQueueStatus(qs_all_input); 11843 } 11844 ok(qstatus == 0, "wrong qstatus %08x\n", qstatus); 11845 11846 trace("signalling to send message\n"); 11847 SetEvent(info.hevent[EV_SENDMSG]); 11848 WaitForSingleObject(info.hevent[EV_ACK], INFINITE); 11849 11850 /* pass invalid QS_xxxx flags */ 11851 SetLastError(0xdeadbeef); 11852 qstatus = GetQueueStatus(0xffffffff); 11853 ok(qstatus == 0 || broken(qstatus) /* win9x */, "GetQueueStatus should fail: %08x\n", qstatus); 11854 if (!qstatus) 11855 { 11856 ok(GetLastError() == ERROR_INVALID_FLAGS, "wrong error %d\n", GetLastError()); 11857 qstatus = GetQueueStatus(qs_all_input); 11858 } 11859 qstatus &= ~MAKELONG( 0x4000, 0x4000 ); /* sometimes set on Win95 */ 11860 ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE), 11861 "wrong qstatus %08x\n", qstatus); 11862 11863 msg.message = 0; 11864 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); 11865 ok(!ret, 11866 "PeekMessageA should have returned FALSE instead of msg %04x\n", 11867 msg.message); 11868 ok_sequence(WmUser, "WmUser", FALSE); 11869 11870 qstatus = GetQueueStatus(qs_all_input); 11871 ok(qstatus == 0, "wrong qstatus %08x\n", qstatus); 11872 11873 keybd_event('N', 0, 0, 0); 11874 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 11875 qstatus = GetQueueStatus(qs_all_input); 11876 if (!(qstatus & MAKELONG(QS_KEY, QS_KEY))) 11877 { 11878 skip( "queuing key events not supported\n" ); 11879 goto done; 11880 } 11881 ok(qstatus == MAKELONG(QS_KEY, QS_KEY) || 11882 /* keybd_event seems to trigger a sent message on NT4 */ 11883 qstatus == MAKELONG(QS_KEY|QS_SENDMESSAGE, QS_KEY|QS_SENDMESSAGE), 11884 "wrong qstatus %08x\n", qstatus); 11885 11886 PostMessageA(info.hwnd, WM_CHAR, 'z', 0); 11887 qstatus = GetQueueStatus(qs_all_input); 11888 ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY) || 11889 qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY|QS_SENDMESSAGE), 11890 "wrong qstatus %08x\n", qstatus); 11891 11892 InvalidateRect(info.hwnd, NULL, FALSE); 11893 qstatus = GetQueueStatus(qs_all_input); 11894 ok(qstatus == MAKELONG(QS_PAINT, QS_PAINT|QS_POSTMESSAGE|QS_KEY) || 11895 qstatus == MAKELONG(QS_PAINT, QS_PAINT|QS_POSTMESSAGE|QS_KEY|QS_SENDMESSAGE), 11896 "wrong qstatus %08x\n", qstatus); 11897 11898 trace("signalling to send message\n"); 11899 SetEvent(info.hevent[EV_SENDMSG]); 11900 WaitForSingleObject(info.hevent[EV_ACK], INFINITE); 11901 11902 qstatus = GetQueueStatus(qs_all_input); 11903 ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_PAINT|QS_POSTMESSAGE|QS_KEY), 11904 "wrong qstatus %08x\n", qstatus); 11905 11906 msg.message = 0; 11907 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | (qs_input << 16)); 11908 if (ret && msg.message == WM_CHAR) 11909 { 11910 win_skip( "PM_QS_* flags not supported in PeekMessage\n" ); 11911 goto done; 11912 } 11913 ok(!ret, 11914 "PeekMessageA should have returned FALSE instead of msg %04x\n", 11915 msg.message); 11916 if (!sequence_cnt) /* nt4 doesn't fetch anything with PM_QS_* flags */ 11917 { 11918 win_skip( "PM_QS_* flags not supported in PeekMessage\n" ); 11919 goto done; 11920 } 11921 ok_sequence(WmUser, "WmUser", FALSE); 11922 11923 qstatus = GetQueueStatus(qs_all_input); 11924 ok(qstatus == MAKELONG(0, QS_PAINT|QS_POSTMESSAGE|QS_KEY), 11925 "wrong qstatus %08x\n", qstatus); 11926 11927 trace("signalling to send message\n"); 11928 SetEvent(info.hevent[EV_SENDMSG]); 11929 WaitForSingleObject(info.hevent[EV_ACK], INFINITE); 11930 11931 qstatus = GetQueueStatus(qs_all_input); 11932 ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_PAINT|QS_POSTMESSAGE|QS_KEY), 11933 "wrong qstatus %08x\n", qstatus); 11934 11935 msg.message = 0; 11936 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_POSTMESSAGE ); 11937 ok(!ret, 11938 "PeekMessageA should have returned FALSE instead of msg %04x\n", 11939 msg.message); 11940 ok_sequence(WmUser, "WmUser", FALSE); 11941 11942 qstatus = GetQueueStatus(qs_all_input); 11943 ok(qstatus == MAKELONG(0, QS_PAINT|QS_POSTMESSAGE|QS_KEY), 11944 "wrong qstatus %08x\n", qstatus); 11945 11946 msg.message = 0; 11947 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_POSTMESSAGE); 11948 ok(ret && msg.message == WM_CHAR && msg.wParam == 'z', 11949 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n", 11950 ret, msg.message, msg.wParam); 11951 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE); 11952 11953 qstatus = GetQueueStatus(qs_all_input); 11954 ok(qstatus == MAKELONG(0, QS_PAINT|QS_KEY), 11955 "wrong qstatus %08x\n", qstatus); 11956 11957 msg.message = 0; 11958 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_POSTMESSAGE); 11959 ok(!ret, 11960 "PeekMessageA should have returned FALSE instead of msg %04x\n", 11961 msg.message); 11962 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE); 11963 11964 qstatus = GetQueueStatus(qs_all_input); 11965 ok(qstatus == MAKELONG(0, QS_PAINT|QS_KEY), 11966 "wrong qstatus %08x\n", qstatus); 11967 11968 msg.message = 0; 11969 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_PAINT); 11970 ok(ret && msg.message == WM_PAINT, 11971 "got %d and %04x instead of TRUE and WM_PAINT\n", ret, msg.message); 11972 DispatchMessageA(&msg); 11973 ok_sequence(WmPaint, "WmPaint", FALSE); 11974 11975 qstatus = GetQueueStatus(qs_all_input); 11976 ok(qstatus == MAKELONG(0, QS_KEY), 11977 "wrong qstatus %08x\n", qstatus); 11978 11979 msg.message = 0; 11980 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_PAINT); 11981 ok(!ret, 11982 "PeekMessageA should have returned FALSE instead of msg %04x\n", 11983 msg.message); 11984 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE); 11985 11986 qstatus = GetQueueStatus(qs_all_input); 11987 ok(qstatus == MAKELONG(0, QS_KEY), 11988 "wrong qstatus %08x\n", qstatus); 11989 11990 trace("signalling to send message\n"); 11991 SetEvent(info.hevent[EV_SENDMSG]); 11992 WaitForSingleObject(info.hevent[EV_ACK], INFINITE); 11993 11994 qstatus = GetQueueStatus(qs_all_input); 11995 ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_KEY), 11996 "wrong qstatus %08x\n", qstatus); 11997 11998 PostMessageA(info.hwnd, WM_CHAR, 'z', 0); 11999 12000 qstatus = GetQueueStatus(qs_all_input); 12001 ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_SENDMESSAGE|QS_POSTMESSAGE|QS_KEY), 12002 "wrong qstatus %08x\n", qstatus); 12003 12004 msg.message = 0; 12005 ret = PeekMessageA(&msg, 0, WM_CHAR, WM_CHAR, PM_REMOVE); 12006 ok(ret && msg.message == WM_CHAR && msg.wParam == 'z', 12007 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n", 12008 ret, msg.message, msg.wParam); 12009 ok_sequence(WmUser, "WmUser", FALSE); 12010 12011 qstatus = GetQueueStatus(qs_all_input); 12012 ok(qstatus == MAKELONG(0, QS_KEY), 12013 "wrong qstatus %08x\n", qstatus); 12014 12015 msg.message = 0; 12016 ret = PeekMessageA(&msg, 0, WM_CHAR, WM_CHAR, PM_REMOVE); 12017 ok(!ret, 12018 "PeekMessageA should have returned FALSE instead of msg %04x\n", 12019 msg.message); 12020 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE); 12021 12022 qstatus = GetQueueStatus(qs_all_input); 12023 ok(qstatus == MAKELONG(0, QS_KEY), 12024 "wrong qstatus %08x\n", qstatus); 12025 12026 PostMessageA(info.hwnd, WM_CHAR, 'z', 0); 12027 12028 qstatus = GetQueueStatus(qs_all_input); 12029 ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY), 12030 "wrong qstatus %08x\n", qstatus); 12031 12032 trace("signalling to send message\n"); 12033 SetEvent(info.hevent[EV_SENDMSG]); 12034 WaitForSingleObject(info.hevent[EV_ACK], INFINITE); 12035 12036 qstatus = GetQueueStatus(qs_all_input); 12037 ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_POSTMESSAGE|QS_KEY), 12038 "wrong qstatus %08x\n", qstatus); 12039 12040 msg.message = 0; 12041 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | (QS_KEY << 16)); 12042 ok(!ret, 12043 "PeekMessageA should have returned FALSE instead of msg %04x\n", 12044 msg.message); 12045 ok_sequence(WmUser, "WmUser", FALSE); 12046 12047 qstatus = GetQueueStatus(qs_all_input); 12048 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE|QS_KEY), 12049 "wrong qstatus %08x\n", qstatus); 12050 12051 msg.message = 0; 12052 if (qs_all_input & QS_RAWINPUT) /* use QS_RAWINPUT only if supported */ 12053 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | (QS_RAWINPUT << 16)); 12054 else /* workaround for a missing QS_RAWINPUT support */ 12055 ret = PeekMessageA(&msg, 0, WM_KEYDOWN, WM_KEYDOWN, PM_REMOVE); 12056 ok(ret && msg.message == WM_KEYDOWN && msg.wParam == 'N', 12057 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n", 12058 ret, msg.message, msg.wParam); 12059 ok_sequence(WmKeyDownSkippedSeq, "WmKeyDownSkippedSeq", FALSE); 12060 12061 qstatus = GetQueueStatus(qs_all_input); 12062 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE|QS_KEY), 12063 "wrong qstatus %08x\n", qstatus); 12064 12065 msg.message = 0; 12066 if (qs_all_input & QS_RAWINPUT) /* use QS_RAWINPUT only if supported */ 12067 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | (QS_RAWINPUT << 16)); 12068 else /* workaround for a missing QS_RAWINPUT support */ 12069 ret = PeekMessageA(&msg, 0, WM_KEYUP, WM_KEYUP, PM_REMOVE); 12070 ok(ret && msg.message == WM_KEYUP && msg.wParam == 'N', 12071 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYUP wParam 'N'\n", 12072 ret, msg.message, msg.wParam); 12073 ok_sequence(WmKeyUpSkippedSeq, "WmKeyUpSkippedSeq", FALSE); 12074 12075 qstatus = GetQueueStatus(qs_all_input); 12076 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE), 12077 "wrong qstatus %08x\n", qstatus); 12078 12079 msg.message = 0; 12080 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE); 12081 ok(!ret, 12082 "PeekMessageA should have returned FALSE instead of msg %04x\n", 12083 msg.message); 12084 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE); 12085 12086 qstatus = GetQueueStatus(qs_all_input); 12087 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE), 12088 "wrong qstatus %08x\n", qstatus); 12089 12090 msg.message = 0; 12091 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); 12092 ok(ret && msg.message == WM_CHAR && msg.wParam == 'z', 12093 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n", 12094 ret, msg.message, msg.wParam); 12095 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE); 12096 12097 qstatus = GetQueueStatus(qs_all_input); 12098 ok(qstatus == 0, 12099 "wrong qstatus %08x\n", qstatus); 12100 12101 msg.message = 0; 12102 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); 12103 ok(!ret, 12104 "PeekMessageA should have returned FALSE instead of msg %04x\n", 12105 msg.message); 12106 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE); 12107 12108 qstatus = GetQueueStatus(qs_all_input); 12109 ok(qstatus == 0, 12110 "wrong qstatus %08x\n", qstatus); 12111 12112 /* test whether presence of the quit flag in the queue affects 12113 * the queue state 12114 */ 12115 PostQuitMessage(0x1234abcd); 12116 12117 qstatus = GetQueueStatus(qs_all_input); 12118 ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE), 12119 "wrong qstatus %08x\n", qstatus); 12120 12121 PostMessageA(info.hwnd, WM_USER, 0, 0); 12122 12123 qstatus = GetQueueStatus(qs_all_input); 12124 ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE), 12125 "wrong qstatus %08x\n", qstatus); 12126 12127 msg.message = 0; 12128 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); 12129 ok(ret && msg.message == WM_USER, 12130 "got %d and %04x instead of TRUE and WM_USER\n", ret, msg.message); 12131 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE); 12132 12133 qstatus = GetQueueStatus(qs_all_input); 12134 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE), 12135 "wrong qstatus %08x\n", qstatus); 12136 12137 msg.message = 0; 12138 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); 12139 ok(ret && msg.message == WM_QUIT, 12140 "got %d and %04x instead of TRUE and WM_QUIT\n", ret, msg.message); 12141 ok(msg.wParam == 0x1234abcd, "got wParam %08lx instead of 0x1234abcd\n", msg.wParam); 12142 ok(msg.lParam == 0, "got lParam %08lx instead of 0\n", msg.lParam); 12143 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE); 12144 12145 qstatus = GetQueueStatus(qs_all_input); 12146 todo_wine { 12147 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE), 12148 "wrong qstatus %08x\n", qstatus); 12149 } 12150 12151 msg.message = 0; 12152 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); 12153 ok(!ret, 12154 "PeekMessageA should have returned FALSE instead of msg %04x\n", 12155 msg.message); 12156 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE); 12157 12158 qstatus = GetQueueStatus(qs_all_input); 12159 ok(qstatus == 0, 12160 "wrong qstatus %08x\n", qstatus); 12161 12162 /* some GetMessage tests */ 12163 12164 keybd_event('N', 0, 0, 0); 12165 qstatus = GetQueueStatus(qs_all_input); 12166 ok(qstatus == MAKELONG(QS_KEY, QS_KEY), "wrong qstatus %08x\n", qstatus); 12167 12168 PostMessageA(info.hwnd, WM_CHAR, 'z', 0); 12169 qstatus = GetQueueStatus(qs_all_input); 12170 ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY), "wrong qstatus %08x\n", qstatus); 12171 12172 if (qstatus) 12173 { 12174 ret = GetMessageA( &msg, 0, 0, 0 ); 12175 ok(ret && msg.message == WM_CHAR && msg.wParam == 'z', 12176 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n", 12177 ret, msg.message, msg.wParam); 12178 qstatus = GetQueueStatus(qs_all_input); 12179 ok(qstatus == MAKELONG(0, QS_KEY), "wrong qstatus %08x\n", qstatus); 12180 } 12181 12182 if (qstatus) 12183 { 12184 ret = GetMessageA( &msg, 0, 0, 0 ); 12185 ok(ret && msg.message == WM_KEYDOWN && msg.wParam == 'N', 12186 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n", 12187 ret, msg.message, msg.wParam); 12188 ok_sequence(WmKeyDownSkippedSeq, "WmKeyDownSkippedSeq", FALSE); 12189 qstatus = GetQueueStatus(qs_all_input); 12190 ok(qstatus == 0, "wrong qstatus %08x\n", qstatus); 12191 } 12192 12193 keybd_event('N', 0, 0, 0); 12194 qstatus = GetQueueStatus(qs_all_input); 12195 ok(qstatus == MAKELONG(QS_KEY, QS_KEY), "wrong qstatus %08x\n", qstatus); 12196 12197 PostMessageA(info.hwnd, WM_CHAR, 'z', 0); 12198 qstatus = GetQueueStatus(qs_all_input); 12199 ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY), "wrong qstatus %08x\n", qstatus); 12200 12201 if (qstatus & (QS_KEY << 16)) 12202 { 12203 ret = GetMessageA( &msg, 0, WM_KEYDOWN, WM_KEYUP ); 12204 ok(ret && msg.message == WM_KEYDOWN && msg.wParam == 'N', 12205 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n", 12206 ret, msg.message, msg.wParam); 12207 ok_sequence(WmKeyDownWasDownSkippedSeq, "WmKeyDownWasDownSkippedSeq", FALSE); 12208 qstatus = GetQueueStatus(qs_all_input); 12209 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE), "wrong qstatus %08x\n", qstatus); 12210 } 12211 12212 if (qstatus) 12213 { 12214 ret = GetMessageA( &msg, 0, WM_CHAR, WM_CHAR ); 12215 ok(ret && msg.message == WM_CHAR && msg.wParam == 'z', 12216 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n", 12217 ret, msg.message, msg.wParam); 12218 qstatus = GetQueueStatus(qs_all_input); 12219 ok(qstatus == 0, "wrong qstatus %08x\n", qstatus); 12220 } 12221 12222 keybd_event('N', 0, KEYEVENTF_KEYUP, 0); 12223 qstatus = GetQueueStatus(qs_all_input); 12224 ok(qstatus == MAKELONG(QS_KEY, QS_KEY), "wrong qstatus %08x\n", qstatus); 12225 12226 PostMessageA(info.hwnd, WM_CHAR, 'z', 0); 12227 qstatus = GetQueueStatus(qs_all_input); 12228 ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY), "wrong qstatus %08x\n", qstatus); 12229 12230 trace("signalling to send message\n"); 12231 SetEvent(info.hevent[EV_SENDMSG]); 12232 WaitForSingleObject(info.hevent[EV_ACK], INFINITE); 12233 qstatus = GetQueueStatus(qs_all_input); 12234 ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_POSTMESSAGE|QS_KEY), 12235 "wrong qstatus %08x\n", qstatus); 12236 12237 if (qstatus & (QS_KEY << 16)) 12238 { 12239 ret = GetMessageA( &msg, 0, WM_KEYDOWN, WM_KEYUP ); 12240 ok(ret && msg.message == WM_KEYUP && msg.wParam == 'N', 12241 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n", 12242 ret, msg.message, msg.wParam); 12243 ok_sequence(WmUserKeyUpSkippedSeq, "WmUserKeyUpSkippedSeq", FALSE); 12244 qstatus = GetQueueStatus(qs_all_input); 12245 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE), "wrong qstatus %08x\n", qstatus); 12246 } 12247 12248 if (qstatus) 12249 { 12250 ret = GetMessageA( &msg, 0, WM_CHAR, WM_CHAR ); 12251 ok(ret && msg.message == WM_CHAR && msg.wParam == 'z', 12252 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n", 12253 ret, msg.message, msg.wParam); 12254 qstatus = GetQueueStatus(qs_all_input); 12255 ok(qstatus == 0, "wrong qstatus %08x\n", qstatus); 12256 } 12257 12258 PostThreadMessageA(GetCurrentThreadId(), WM_USER, 0, 0); 12259 ret = PeekMessageA(&msg, (HWND)-1, 0, 0, PM_NOREMOVE); 12260 ok(ret == TRUE, "wrong ret %d\n", ret); 12261 ok(msg.message == WM_USER, "wrong message %u\n", msg.message); 12262 ret = GetMessageA(&msg, (HWND)-1, 0, 0); 12263 ok(ret == TRUE, "wrong ret %d\n", ret); 12264 ok(msg.message == WM_USER, "wrong message %u\n", msg.message); 12265 12266 PostThreadMessageA(GetCurrentThreadId(), WM_USER, 0, 0); 12267 ret = PeekMessageA(&msg, (HWND)1, 0, 0, PM_NOREMOVE); 12268 ok(ret == TRUE, "wrong ret %d\n", ret); 12269 ok(msg.message == WM_USER, "wrong message %u\n", msg.message); 12270 ret = GetMessageA(&msg, (HWND)1, 0, 0); 12271 ok(ret == TRUE, "wrong ret %d\n", ret); 12272 ok(msg.message == WM_USER, "wrong message %u\n", msg.message); 12273 12274 PostThreadMessageA(GetCurrentThreadId(), WM_USER, 0, 0); 12275 ret = PeekMessageA(&msg, (HWND)0xffff, 0, 0, PM_NOREMOVE); 12276 ok(ret == TRUE, "wrong ret %d\n", ret); 12277 ok(msg.message == WM_USER, "wrong message %u\n", msg.message); 12278 ret = GetMessageA(&msg, (HWND)0xffff, 0, 0); 12279 ok(ret == TRUE, "wrong ret %d\n", ret); 12280 ok(msg.message == WM_USER, "wrong message %u\n", msg.message); 12281 12282 done: 12283 trace("signalling to exit\n"); 12284 SetEvent(info.hevent[EV_STOP]); 12285 12286 WaitForSingleObject(hthread, INFINITE); 12287 12288 CloseHandle(hthread); 12289 CloseHandle(info.hevent[0]); 12290 CloseHandle(info.hevent[1]); 12291 CloseHandle(info.hevent[2]); 12292 12293 DestroyWindow(info.hwnd); 12294 } 12295 12296 static void wait_move_event(HWND hwnd, int x, int y) 12297 { 12298 MSG msg; 12299 DWORD time; 12300 BOOL ret; 12301 12302 time = GetTickCount(); 12303 while (GetTickCount() - time < 200) { 12304 ret = PeekMessageA(&msg, hwnd, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_NOREMOVE); 12305 if (ret && msg.pt.x > x && msg.pt.y > y) break; 12306 if (!ret) MsgWaitForMultipleObjects( 0, NULL, FALSE, GetTickCount() - time, QS_ALLINPUT ); 12307 else Sleep( GetTickCount() - time ); 12308 } 12309 } 12310 12311 #define STEP 5 12312 static void test_PeekMessage2(void) 12313 { 12314 HWND hwnd; 12315 BOOL ret; 12316 MSG msg; 12317 UINT message; 12318 DWORD time1, time2, time3; 12319 int x1, y1, x2, y2, x3, y3; 12320 POINT pos; 12321 12322 time1 = time2 = time3 = 0; 12323 x1 = y1 = x2 = y2 = x3 = y3 = 0; 12324 12325 /* Initialise window and make sure it is ready for events */ 12326 hwnd = CreateWindowA("TestWindowClass", "PeekMessage2", WS_OVERLAPPEDWINDOW, 12327 10, 10, 800, 800, NULL, NULL, NULL, NULL); 12328 assert(hwnd); 12329 trace("Window for test_PeekMessage2 %p\n", hwnd); 12330 ShowWindow(hwnd, SW_SHOW); 12331 UpdateWindow(hwnd); 12332 SetFocus(hwnd); 12333 GetCursorPos(&pos); 12334 SetCursorPos(100, 100); 12335 mouse_event(MOUSEEVENTF_MOVE, -STEP, -STEP, 0, 0); 12336 flush_events(); 12337 12338 /* Do initial mousemove, wait until we can see it 12339 and then do our test peek with PM_NOREMOVE. */ 12340 mouse_event(MOUSEEVENTF_MOVE, STEP, STEP, 0, 0); 12341 wait_move_event(hwnd, 100-STEP, 100-STEP); 12342 12343 ret = PeekMessageA(&msg, hwnd, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_NOREMOVE); 12344 if (!ret) 12345 { 12346 skip( "queuing mouse events not supported\n" ); 12347 goto done; 12348 } 12349 else 12350 { 12351 trace("1st move event: %04x %x %d %d\n", msg.message, msg.time, msg.pt.x, msg.pt.y); 12352 message = msg.message; 12353 time1 = msg.time; 12354 x1 = msg.pt.x; 12355 y1 = msg.pt.y; 12356 ok(message == WM_MOUSEMOVE, "message not WM_MOUSEMOVE, %04x instead\n", message); 12357 } 12358 12359 /* Allow time to advance a bit, and then simulate the user moving their 12360 * mouse around. After that we peek again with PM_NOREMOVE. 12361 * Although the previous mousemove message was never removed, the 12362 * mousemove we now peek should reflect the recent mouse movements 12363 * because the input queue will merge the move events. */ 12364 Sleep(100); 12365 mouse_event(MOUSEEVENTF_MOVE, STEP, STEP, 0, 0); 12366 wait_move_event(hwnd, x1, y1); 12367 12368 ret = PeekMessageA(&msg, hwnd, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_NOREMOVE); 12369 ok(ret, "no message available\n"); 12370 if (ret) { 12371 trace("2nd move event: %04x %x %d %d\n", msg.message, msg.time, msg.pt.x, msg.pt.y); 12372 message = msg.message; 12373 time2 = msg.time; 12374 x2 = msg.pt.x; 12375 y2 = msg.pt.y; 12376 ok(message == WM_MOUSEMOVE, "message not WM_MOUSEMOVE, %04x instead\n", message); 12377 ok(time2 > time1, "message time not advanced: %x %x\n", time1, time2); 12378 ok(x2 != x1 && y2 != y1, "coords not changed: (%d %d) (%d %d)\n", x1, y1, x2, y2); 12379 } 12380 12381 /* Have another go, to drive the point home */ 12382 Sleep(100); 12383 mouse_event(MOUSEEVENTF_MOVE, STEP, STEP, 0, 0); 12384 wait_move_event(hwnd, x2, y2); 12385 12386 ret = PeekMessageA(&msg, hwnd, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_NOREMOVE); 12387 ok(ret, "no message available\n"); 12388 if (ret) { 12389 trace("3rd move event: %04x %x %d %d\n", msg.message, msg.time, msg.pt.x, msg.pt.y); 12390 message = msg.message; 12391 time3 = msg.time; 12392 x3 = msg.pt.x; 12393 y3 = msg.pt.y; 12394 ok(message == WM_MOUSEMOVE, "message not WM_MOUSEMOVE, %04x instead\n", message); 12395 ok(time3 > time2, "message time not advanced: %x %x\n", time2, time3); 12396 ok(x3 != x2 && y3 != y2, "coords not changed: (%d %d) (%d %d)\n", x2, y2, x3, y3); 12397 } 12398 12399 done: 12400 DestroyWindow(hwnd); 12401 SetCursorPos(pos.x, pos.y); 12402 flush_events(); 12403 } 12404 12405 static void test_PeekMessage3(void) 12406 { 12407 HWND hwnd; 12408 BOOL ret; 12409 MSG msg; 12410 12411 hwnd = CreateWindowA("TestWindowClass", "PeekMessage3", WS_OVERLAPPEDWINDOW, 12412 10, 10, 800, 800, NULL, NULL, NULL, NULL); 12413 ok(hwnd != NULL, "expected hwnd != NULL\n"); 12414 flush_events(); 12415 12416 /* GetMessage() and PeekMessage(..., PM_REMOVE) should prefer messages which 12417 * were already seen. */ 12418 12419 SetTimer(hwnd, 1, 0, NULL); 12420 while (!PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE)); 12421 ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12422 PostMessageA(hwnd, WM_USER, 0, 0); 12423 ret = PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE); 12424 ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12425 ret = GetMessageA(&msg, NULL, 0, 0); 12426 ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12427 ret = GetMessageA(&msg, NULL, 0, 0); 12428 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); 12429 ret = PeekMessageA(&msg, NULL, 0, 0, 0); 12430 ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret); 12431 12432 SetTimer(hwnd, 1, 0, NULL); 12433 while (!PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE)); 12434 ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12435 PostMessageA(hwnd, WM_USER, 0, 0); 12436 ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE); 12437 ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12438 ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE); 12439 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); 12440 ret = PeekMessageA(&msg, NULL, 0, 0, 0); 12441 ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret); 12442 12443 /* It doesn't matter if a message range is specified or not. */ 12444 12445 SetTimer(hwnd, 1, 0, NULL); 12446 while (!PeekMessageA(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE)); 12447 ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12448 PostMessageA(hwnd, WM_USER, 0, 0); 12449 ret = GetMessageA(&msg, NULL, 0, 0); 12450 ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12451 ret = GetMessageA(&msg, NULL, 0, 0); 12452 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); 12453 ret = PeekMessageA(&msg, NULL, 0, 0, 0); 12454 ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret); 12455 12456 /* But not if the post messages were added before the PeekMessage() call. */ 12457 12458 PostMessageA(hwnd, WM_USER, 0, 0); 12459 SetTimer(hwnd, 1, 0, NULL); 12460 while (!PeekMessageA(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE)); 12461 ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12462 ret = GetMessageA(&msg, NULL, 0, 0); 12463 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); 12464 ret = GetMessageA(&msg, NULL, 0, 0); 12465 ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12466 ret = PeekMessageA(&msg, NULL, 0, 0, 0); 12467 ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret); 12468 12469 /* More complicated test with multiple messages. */ 12470 12471 PostMessageA(hwnd, WM_USER, 0, 0); 12472 SetTimer(hwnd, 1, 0, NULL); 12473 while (!PeekMessageA(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE)); 12474 ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12475 PostMessageA(hwnd, WM_USER + 1, 0, 0); 12476 ret = GetMessageA(&msg, NULL, 0, 0); 12477 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); 12478 ret = GetMessageA(&msg, NULL, 0, 0); 12479 ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12480 ret = GetMessageA(&msg, NULL, 0, 0); 12481 ok(ret && msg.message == WM_USER + 1, "msg.message = %u instead of WM_USER + 1\n", msg.message); 12482 ret = PeekMessageA(&msg, NULL, 0, 0, 0); 12483 ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret); 12484 12485 /* Newer messages are still returned when specifying a message range. */ 12486 12487 SetTimer(hwnd, 1, 0, NULL); 12488 while (!PeekMessageA(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE)); 12489 ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12490 PostMessageA(hwnd, WM_USER + 1, 0, 0); 12491 PostMessageA(hwnd, WM_USER, 0, 0); 12492 ret = PeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); 12493 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); 12494 ret = PeekMessageA(&msg, NULL, WM_USER, WM_USER + 1, PM_NOREMOVE); 12495 ok(ret && msg.message == WM_USER + 1, "msg.message = %u instead of WM_USER + 1\n", msg.message); 12496 ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE); 12497 ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12498 ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE); 12499 ok(ret && msg.message == WM_USER + 1, "msg.message = %u instead of WM_USER + 1\n", msg.message); 12500 ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE); 12501 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); 12502 ret = PeekMessageA(&msg, NULL, 0, 0, 0); 12503 ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret); 12504 12505 /* Also works for posted messages, but the situation is a bit different, 12506 * because both messages are in the same queue. */ 12507 12508 PostMessageA(hwnd, WM_TIMER, 0, 0); 12509 while (!PeekMessageA(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE)); 12510 ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12511 PostMessageA(hwnd, WM_USER, 0, 0); 12512 ret = GetMessageA(&msg, NULL, 0, 0); 12513 ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12514 ret = GetMessageA(&msg, NULL, 0, 0); 12515 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); 12516 ret = PeekMessageA(&msg, NULL, 0, 0, 0); 12517 ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret); 12518 12519 PostMessageA(hwnd, WM_USER, 0, 0); 12520 PostMessageA(hwnd, WM_TIMER, 0, 0); 12521 while (!PeekMessageA(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE)); 12522 ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12523 ret = GetMessageA(&msg, NULL, 0, 0); 12524 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); 12525 ret = GetMessageA(&msg, NULL, 0, 0); 12526 ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); 12527 ret = PeekMessageA(&msg, NULL, 0, 0, 0); 12528 ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret); 12529 12530 DestroyWindow(hwnd); 12531 flush_events(); 12532 } 12533 12534 static INT_PTR CALLBACK wm_quit_dlg_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) 12535 { 12536 struct recvd_message msg; 12537 12538 if (ignore_message( message )) return 0; 12539 12540 msg.hwnd = hwnd; 12541 msg.message = message; 12542 msg.flags = sent|wparam|lparam; 12543 msg.wParam = wp; 12544 msg.lParam = lp; 12545 msg.descr = "dialog"; 12546 add_message(&msg); 12547 12548 switch (message) 12549 { 12550 case WM_INITDIALOG: 12551 PostMessageA(hwnd, WM_QUIT, 0x1234, 0x5678); 12552 PostMessageA(hwnd, WM_USER, 0xdead, 0xbeef); 12553 return 0; 12554 12555 case WM_GETDLGCODE: 12556 return 0; 12557 12558 case WM_USER: 12559 EndDialog(hwnd, 0); 12560 break; 12561 } 12562 12563 return 1; 12564 } 12565 12566 static const struct message WmQuitDialogSeq[] = { 12567 { HCBT_CREATEWND, hook }, 12568 { WM_SETFONT, sent }, 12569 { WM_INITDIALOG, sent }, 12570 { WM_CHANGEUISTATE, sent|optional }, 12571 { HCBT_DESTROYWND, hook }, 12572 { 0x0090, sent|optional }, /* Vista */ 12573 { WM_DESTROY, sent }, 12574 { WM_NCDESTROY, sent }, 12575 { 0 } 12576 }; 12577 12578 static const struct message WmStopQuitSeq[] = { 12579 { WM_DWMNCRENDERINGCHANGED, posted|optional }, 12580 { WM_CLOSE, posted }, 12581 { WM_QUIT, posted|wparam|lparam, 0x1234, 0 }, 12582 { 0 } 12583 }; 12584 12585 static void test_quit_message(void) 12586 { 12587 MSG msg; 12588 BOOL ret; 12589 12590 /* test using PostQuitMessage */ 12591 flush_events(); 12592 PostQuitMessage(0xbeef); 12593 12594 msg.message = 0; 12595 ret = PeekMessageA(&msg, 0, 0, 0, PM_QS_SENDMESSAGE); 12596 ok(!ret, "got %x message\n", msg.message); 12597 12598 ret = PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE); 12599 ok(ret, "PeekMessage failed with error %d\n", GetLastError()); 12600 ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message); 12601 ok(msg.wParam == 0xbeef, "wParam was 0x%lx instead of 0xbeef\n", msg.wParam); 12602 12603 ret = PostThreadMessageA(GetCurrentThreadId(), WM_USER, 0, 0); 12604 ok(ret, "PostMessage failed with error %d\n", GetLastError()); 12605 12606 ret = GetMessageA(&msg, NULL, 0, 0); 12607 ok(ret > 0, "GetMessage failed with error %d\n", GetLastError()); 12608 ok(msg.message == WM_USER, "Received message 0x%04x instead of WM_USER\n", msg.message); 12609 12610 /* note: WM_QUIT message received after WM_USER message */ 12611 ret = GetMessageA(&msg, NULL, 0, 0); 12612 ok(!ret, "GetMessage return %d with error %d instead of FALSE\n", ret, GetLastError()); 12613 ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message); 12614 ok(msg.wParam == 0xbeef, "wParam was 0x%lx instead of 0xbeef\n", msg.wParam); 12615 12616 ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE); 12617 ok( !ret || msg.message != WM_QUIT, "Received WM_QUIT again\n" ); 12618 12619 /* now test with PostThreadMessage - different behaviour! */ 12620 PostThreadMessageA(GetCurrentThreadId(), WM_QUIT, 0xdead, 0); 12621 12622 ret = PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE); 12623 ok(ret, "PeekMessage failed with error %d\n", GetLastError()); 12624 ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message); 12625 ok(msg.wParam == 0xdead, "wParam was 0x%lx instead of 0xdead\n", msg.wParam); 12626 12627 ret = PostThreadMessageA(GetCurrentThreadId(), WM_USER, 0, 0); 12628 ok(ret, "PostMessage failed with error %d\n", GetLastError()); 12629 12630 /* note: we receive the WM_QUIT message first this time */ 12631 ret = GetMessageA(&msg, NULL, 0, 0); 12632 ok(!ret, "GetMessage return %d with error %d instead of FALSE\n", ret, GetLastError()); 12633 ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message); 12634 ok(msg.wParam == 0xdead, "wParam was 0x%lx instead of 0xdead\n", msg.wParam); 12635 12636 ret = GetMessageA(&msg, NULL, 0, 0); 12637 ok(ret > 0, "GetMessage failed with error %d\n", GetLastError()); 12638 ok(msg.message == WM_USER, "Received message 0x%04x instead of WM_USER\n", msg.message); 12639 12640 flush_events(); 12641 flush_sequence(); 12642 ret = DialogBoxParamA(GetModuleHandleA(NULL), "TEST_EMPTY_DIALOG", 0, wm_quit_dlg_proc, 0); 12643 ok(ret == 1, "expected 1, got %d\n", ret); 12644 ok_sequence(WmQuitDialogSeq, "WmQuitDialogSeq", FALSE); 12645 memset(&msg, 0xab, sizeof(msg)); 12646 ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE); 12647 ok(ret, "PeekMessage failed\n"); 12648 ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message); 12649 ok(msg.wParam == 0x1234, "wParam was 0x%lx instead of 0x1234\n", msg.wParam); 12650 ok(msg.lParam == 0, "lParam was 0x%lx instead of 0\n", msg.lParam); 12651 12652 /* Check what happens to a WM_QUIT message posted to a window that gets 12653 * destroyed. 12654 */ 12655 CreateWindowExA(0, "StopQuitClass", "Stop Quit Test", WS_OVERLAPPEDWINDOW, 12656 0, 0, 100, 100, NULL, NULL, NULL, NULL); 12657 flush_sequence(); 12658 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 12659 { 12660 struct recvd_message rmsg; 12661 rmsg.hwnd = msg.hwnd; 12662 rmsg.message = msg.message; 12663 rmsg.flags = posted|wparam|lparam; 12664 rmsg.wParam = msg.wParam; 12665 rmsg.lParam = msg.lParam; 12666 rmsg.descr = "stop/quit"; 12667 if (msg.message == WM_QUIT) 12668 /* The hwnd can only be checked here */ 12669 ok(!msg.hwnd, "The WM_QUIT hwnd was %p instead of NULL\n", msg.hwnd); 12670 add_message(&rmsg); 12671 DispatchMessageA(&msg); 12672 } 12673 ok_sequence(WmStopQuitSeq, "WmStopQuitSeq", FALSE); 12674 } 12675 12676 static const struct message WmNotifySeq[] = { 12677 { WM_NOTIFY, sent|wparam|lparam, 0x1234, 0xdeadbeef }, 12678 { 0 } 12679 }; 12680 12681 static void test_notify_message(void) 12682 { 12683 HWND hwnd; 12684 BOOL ret; 12685 MSG msg; 12686 12687 hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, 12688 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0, NULL, NULL, 0); 12689 ok(hwnd != 0, "Failed to create window\n"); 12690 flush_events(); 12691 flush_sequence(); 12692 12693 ret = SendNotifyMessageA(hwnd, WM_NOTIFY, 0x1234, 0xdeadbeef); 12694 ok(ret == TRUE, "SendNotifyMessageA failed with error %u\n", GetLastError()); 12695 ok_sequence(WmNotifySeq, "WmNotifySeq", FALSE); 12696 12697 ret = SendNotifyMessageW(hwnd, WM_NOTIFY, 0x1234, 0xdeadbeef); 12698 ok(ret == TRUE, "SendNotifyMessageW failed with error %u\n", GetLastError()); 12699 ok_sequence(WmNotifySeq, "WmNotifySeq", FALSE); 12700 12701 ret = SendMessageCallbackA(hwnd, WM_NOTIFY, 0x1234, 0xdeadbeef, NULL, 0); 12702 ok(ret == TRUE, "SendMessageCallbackA failed with error %u\n", GetLastError()); 12703 ok_sequence(WmNotifySeq, "WmNotifySeq", FALSE); 12704 12705 ret = SendMessageCallbackW(hwnd, WM_NOTIFY, 0x1234, 0xdeadbeef, NULL, 0); 12706 ok(ret == TRUE, "SendMessageCallbackW failed with error %u\n", GetLastError()); 12707 ok_sequence(WmNotifySeq, "WmNotifySeq", FALSE); 12708 12709 ret = PostMessageA(hwnd, WM_NOTIFY, 0x1234, 0xdeadbeef); 12710 ok(ret == TRUE, "PostMessageA failed with error %u\n", GetLastError()); 12711 flush_events(); 12712 ok_sequence(WmNotifySeq, "WmNotifySeq", FALSE); 12713 12714 ret = PostMessageW(hwnd, WM_NOTIFY, 0x1234, 0xdeadbeef); 12715 ok(ret == TRUE, "PostMessageW failed with error %u\n", GetLastError()); 12716 flush_events(); 12717 ok_sequence(WmNotifySeq, "WmNotifySeq", FALSE); 12718 12719 ret = PostThreadMessageA(GetCurrentThreadId(), WM_NOTIFY, 0x1234, 0xdeadbeef); 12720 ok(ret == TRUE, "PostThreadMessageA failed with error %u\n", GetLastError()); 12721 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 12722 { 12723 msg.hwnd = hwnd; 12724 DispatchMessageA(&msg); 12725 } 12726 ok_sequence(WmNotifySeq, "WmNotifySeq", FALSE); 12727 12728 ret = PostThreadMessageW(GetCurrentThreadId(), WM_NOTIFY, 0x1234, 0xdeadbeef); 12729 ok(ret == TRUE, "PostThreadMessageW failed with error %u\n", GetLastError()); 12730 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 12731 { 12732 msg.hwnd = hwnd; 12733 DispatchMessageA(&msg); 12734 } 12735 ok_sequence(WmNotifySeq, "WmNotifySeq", FALSE); 12736 12737 DestroyWindow(hwnd); 12738 } 12739 12740 static const struct message WmMouseHoverSeq[] = { 12741 { WM_MOUSEACTIVATE, sent|optional }, /* we can get those when moving the mouse in focus-follow-mouse mode under X11 */ 12742 { WM_MOUSEACTIVATE, sent|optional }, 12743 { WM_TIMER, sent|optional }, /* XP sends it */ 12744 { WM_SYSTIMER, sent }, 12745 { WM_MOUSEHOVER, sent|wparam, 0 }, 12746 { 0 } 12747 }; 12748 12749 static void pump_msg_loop_timeout(DWORD timeout, BOOL inject_mouse_move) 12750 { 12751 MSG msg; 12752 DWORD start_ticks, end_ticks; 12753 12754 start_ticks = GetTickCount(); 12755 /* add some deviation (50%) to cover not expected delays */ 12756 start_ticks += timeout / 2; 12757 12758 do 12759 { 12760 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 12761 { 12762 /* Timer proc messages are not dispatched to the window proc, 12763 * and therefore not logged. 12764 */ 12765 if ((msg.message == WM_TIMER || msg.message == WM_SYSTIMER) && msg.hwnd) 12766 { 12767 struct recvd_message s_msg; 12768 12769 s_msg.hwnd = msg.hwnd; 12770 s_msg.message = msg.message; 12771 s_msg.flags = sent|wparam|lparam; 12772 s_msg.wParam = msg.wParam; 12773 s_msg.lParam = msg.lParam; 12774 s_msg.descr = "msg_loop"; 12775 add_message(&s_msg); 12776 } 12777 DispatchMessageA(&msg); 12778 } 12779 12780 end_ticks = GetTickCount(); 12781 12782 /* inject WM_MOUSEMOVE to see how it changes tracking */ 12783 if (inject_mouse_move && start_ticks + timeout / 2 >= end_ticks) 12784 { 12785 mouse_event(MOUSEEVENTF_MOVE, -1, 0, 0, 0); 12786 mouse_event(MOUSEEVENTF_MOVE, 1, 0, 0, 0); 12787 12788 inject_mouse_move = FALSE; 12789 } 12790 } while (start_ticks + timeout >= end_ticks); 12791 } 12792 12793 static void test_TrackMouseEvent(void) 12794 { 12795 TRACKMOUSEEVENT tme; 12796 BOOL ret; 12797 HWND hwnd, hchild; 12798 RECT rc_parent, rc_child; 12799 UINT default_hover_time, hover_width = 0, hover_height = 0; 12800 12801 #define track_hover(track_hwnd, track_hover_time) \ 12802 tme.cbSize = sizeof(tme); \ 12803 tme.dwFlags = TME_HOVER; \ 12804 tme.hwndTrack = track_hwnd; \ 12805 tme.dwHoverTime = track_hover_time; \ 12806 SetLastError(0xdeadbeef); \ 12807 ret = pTrackMouseEvent(&tme); \ 12808 ok(ret, "TrackMouseEvent(TME_HOVER) error %d\n", GetLastError()) 12809 12810 #define track_query(expected_track_flags, expected_track_hwnd, expected_hover_time) \ 12811 tme.cbSize = sizeof(tme); \ 12812 tme.dwFlags = TME_QUERY; \ 12813 tme.hwndTrack = (HWND)0xdeadbeef; \ 12814 tme.dwHoverTime = 0xdeadbeef; \ 12815 SetLastError(0xdeadbeef); \ 12816 ret = pTrackMouseEvent(&tme); \ 12817 ok(ret, "TrackMouseEvent(TME_QUERY) error %d\n", GetLastError());\ 12818 ok(tme.cbSize == sizeof(tme), "wrong tme.cbSize %u\n", tme.cbSize); \ 12819 ok(tme.dwFlags == (expected_track_flags), \ 12820 "wrong tme.dwFlags %08x, expected %08x\n", tme.dwFlags, (expected_track_flags)); \ 12821 ok(tme.hwndTrack == (expected_track_hwnd), \ 12822 "wrong tme.hwndTrack %p, expected %p\n", tme.hwndTrack, (expected_track_hwnd)); \ 12823 ok(tme.dwHoverTime == (expected_hover_time), \ 12824 "wrong tme.dwHoverTime %u, expected %u\n", tme.dwHoverTime, (expected_hover_time)) 12825 12826 #define track_hover_cancel(track_hwnd) \ 12827 tme.cbSize = sizeof(tme); \ 12828 tme.dwFlags = TME_HOVER | TME_CANCEL; \ 12829 tme.hwndTrack = track_hwnd; \ 12830 tme.dwHoverTime = 0xdeadbeef; \ 12831 SetLastError(0xdeadbeef); \ 12832 ret = pTrackMouseEvent(&tme); \ 12833 ok(ret, "TrackMouseEvent(TME_HOVER | TME_CANCEL) error %d\n", GetLastError()) 12834 12835 default_hover_time = 0xdeadbeef; 12836 SetLastError(0xdeadbeef); 12837 ret = SystemParametersInfoA(SPI_GETMOUSEHOVERTIME, 0, &default_hover_time, 0); 12838 ok(ret || broken(GetLastError() == 0xdeadbeef), /* win9x */ 12839 "SystemParametersInfo(SPI_GETMOUSEHOVERTIME) error %u\n", GetLastError()); 12840 if (!ret) default_hover_time = 400; 12841 trace("SPI_GETMOUSEHOVERTIME returned %u ms\n", default_hover_time); 12842 12843 SetLastError(0xdeadbeef); 12844 ret = SystemParametersInfoA(SPI_GETMOUSEHOVERWIDTH, 0, &hover_width, 0); 12845 ok(ret || broken(GetLastError() == 0xdeadbeef), /* win9x */ 12846 "SystemParametersInfo(SPI_GETMOUSEHOVERWIDTH) error %u\n", GetLastError()); 12847 if (!ret) hover_width = 4; 12848 SetLastError(0xdeadbeef); 12849 ret = SystemParametersInfoA(SPI_GETMOUSEHOVERHEIGHT, 0, &hover_height, 0); 12850 ok(ret || broken(GetLastError() == 0xdeadbeef), /* win9x */ 12851 "SystemParametersInfo(SPI_GETMOUSEHOVERHEIGHT) error %u\n", GetLastError()); 12852 if (!ret) hover_height = 4; 12853 trace("hover rect is %u x %d\n", hover_width, hover_height); 12854 12855 hwnd = CreateWindowExA(0, "TestWindowClass", NULL, 12856 WS_OVERLAPPEDWINDOW | WS_VISIBLE, 12857 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0, 12858 NULL, NULL, 0); 12859 assert(hwnd); 12860 12861 hchild = CreateWindowExA(0, "TestWindowClass", NULL, 12862 WS_CHILD | WS_BORDER | WS_VISIBLE, 12863 50, 50, 200, 200, hwnd, 12864 NULL, NULL, 0); 12865 assert(hchild); 12866 12867 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE ); 12868 flush_events(); 12869 flush_sequence(); 12870 12871 tme.cbSize = 0; 12872 tme.dwFlags = TME_QUERY; 12873 tme.hwndTrack = (HWND)0xdeadbeef; 12874 tme.dwHoverTime = 0xdeadbeef; 12875 SetLastError(0xdeadbeef); 12876 ret = pTrackMouseEvent(&tme); 12877 ok(!ret, "TrackMouseEvent should fail\n"); 12878 ok(GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == 0xdeadbeef), 12879 "not expected error %u\n", GetLastError()); 12880 12881 tme.cbSize = sizeof(tme); 12882 tme.dwFlags = TME_HOVER; 12883 tme.hwndTrack = (HWND)0xdeadbeef; 12884 tme.dwHoverTime = 0xdeadbeef; 12885 SetLastError(0xdeadbeef); 12886 ret = pTrackMouseEvent(&tme); 12887 ok(!ret, "TrackMouseEvent should fail\n"); 12888 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || broken(GetLastError() == 0xdeadbeef), 12889 "not expected error %u\n", GetLastError()); 12890 12891 tme.cbSize = sizeof(tme); 12892 tme.dwFlags = TME_HOVER | TME_CANCEL; 12893 tme.hwndTrack = (HWND)0xdeadbeef; 12894 tme.dwHoverTime = 0xdeadbeef; 12895 SetLastError(0xdeadbeef); 12896 ret = pTrackMouseEvent(&tme); 12897 ok(!ret, "TrackMouseEvent should fail\n"); 12898 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || broken(GetLastError() == 0xdeadbeef), 12899 "not expected error %u\n", GetLastError()); 12900 12901 GetWindowRect(hwnd, &rc_parent); 12902 GetWindowRect(hchild, &rc_child); 12903 SetCursorPos(rc_child.left - 10, rc_child.top - 10); 12904 12905 /* Process messages so that the system updates its internal current 12906 * window and hittest, otherwise TrackMouseEvent calls don't have any 12907 * effect. 12908 */ 12909 flush_events(); 12910 flush_sequence(); 12911 12912 track_query(0, NULL, 0); 12913 track_hover(hchild, 0); 12914 track_query(0, NULL, 0); 12915 12916 flush_events(); 12917 flush_sequence(); 12918 12919 track_hover(hwnd, 0); 12920 tme.cbSize = sizeof(tme); 12921 tme.dwFlags = TME_QUERY; 12922 tme.hwndTrack = (HWND)0xdeadbeef; 12923 tme.dwHoverTime = 0xdeadbeef; 12924 SetLastError(0xdeadbeef); 12925 ret = pTrackMouseEvent(&tme); 12926 ok(ret, "TrackMouseEvent(TME_QUERY) error %d\n", GetLastError()); 12927 ok(tme.cbSize == sizeof(tme), "wrong tme.cbSize %u\n", tme.cbSize); 12928 if (!tme.dwFlags) 12929 { 12930 skip( "Cursor not inside window, skipping TrackMouseEvent tests\n" ); 12931 DestroyWindow( hwnd ); 12932 return; 12933 } 12934 ok(tme.dwFlags == TME_HOVER, "wrong tme.dwFlags %08x, expected TME_HOVER\n", tme.dwFlags); 12935 ok(tme.hwndTrack == hwnd, "wrong tme.hwndTrack %p, expected %p\n", tme.hwndTrack, hwnd); 12936 ok(tme.dwHoverTime == default_hover_time, "wrong tme.dwHoverTime %u, expected %u\n", 12937 tme.dwHoverTime, default_hover_time); 12938 12939 pump_msg_loop_timeout(default_hover_time, FALSE); 12940 ok_sequence(WmMouseHoverSeq, "WmMouseHoverSeq", FALSE); 12941 12942 track_query(0, NULL, 0); 12943 12944 track_hover(hwnd, HOVER_DEFAULT); 12945 track_query(TME_HOVER, hwnd, default_hover_time); 12946 12947 Sleep(default_hover_time / 2); 12948 mouse_event(MOUSEEVENTF_MOVE, -1, 0, 0, 0); 12949 mouse_event(MOUSEEVENTF_MOVE, 1, 0, 0, 0); 12950 12951 track_query(TME_HOVER, hwnd, default_hover_time); 12952 12953 pump_msg_loop_timeout(default_hover_time, FALSE); 12954 ok_sequence(WmMouseHoverSeq, "WmMouseHoverSeq", FALSE); 12955 12956 track_query(0, NULL, 0); 12957 12958 track_hover(hwnd, HOVER_DEFAULT); 12959 track_query(TME_HOVER, hwnd, default_hover_time); 12960 12961 pump_msg_loop_timeout(default_hover_time, TRUE); 12962 ok_sequence(WmMouseHoverSeq, "WmMouseHoverSeq", FALSE); 12963 12964 track_query(0, NULL, 0); 12965 12966 track_hover(hwnd, HOVER_DEFAULT); 12967 track_query(TME_HOVER, hwnd, default_hover_time); 12968 track_hover_cancel(hwnd); 12969 12970 DestroyWindow(hwnd); 12971 12972 #undef track_hover 12973 #undef track_query 12974 #undef track_hover_cancel 12975 } 12976 12977 12978 static const struct message WmSetWindowRgn[] = { 12979 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE }, 12980 { WM_NCCALCSIZE, sent|wparam, 1 }, 12981 { WM_NCPAINT, sent|optional }, /* wparam != 1 */ 12982 { WM_GETTEXT, sent|defwinproc|optional }, 12983 { WM_ERASEBKGND, sent|optional }, 12984 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE }, 12985 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 12986 { 0 } 12987 }; 12988 12989 static const struct message WmSetWindowRgn_no_redraw[] = { 12990 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW }, 12991 { WM_NCCALCSIZE, sent|wparam, 1 }, 12992 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW }, 12993 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 12994 { 0 } 12995 }; 12996 12997 static const struct message WmSetWindowRgn_clear[] = { 12998 { WM_WINDOWPOSCHANGING, sent/*|wparam*/, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE/*|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE only on some Windows versions */ }, 12999 { WM_NCCALCSIZE, sent|wparam, 1 }, 13000 { WM_NCPAINT, sent|optional }, 13001 { WM_GETTEXT, sent|defwinproc|optional }, 13002 { WM_ERASEBKGND, sent|optional }, /* FIXME: remove optional once Wine is fixed */ 13003 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE }, 13004 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, 13005 { WM_NCPAINT, sent|optional }, 13006 { WM_GETTEXT, sent|defwinproc|optional }, 13007 { WM_ERASEBKGND, sent|optional }, 13008 { WM_WINDOWPOSCHANGING, sent|optional }, 13009 { WM_NCCALCSIZE, sent|optional|wparam, 1 }, 13010 { WM_NCPAINT, sent|optional }, 13011 { WM_GETTEXT, sent|defwinproc|optional }, 13012 { WM_ERASEBKGND, sent|optional }, 13013 { WM_WINDOWPOSCHANGED, sent|optional|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE }, 13014 { WM_NCCALCSIZE, sent|optional|wparam, 1 }, 13015 { WM_NCPAINT, sent|optional }, 13016 { WM_GETTEXT, sent|defwinproc|optional }, 13017 { WM_ERASEBKGND, sent|optional }, 13018 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 13019 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 13020 { 0 } 13021 }; 13022 13023 static void test_SetWindowRgn(void) 13024 { 13025 HRGN hrgn; 13026 HWND hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW, 13027 100, 100, 200, 200, 0, 0, 0, NULL); 13028 ok( hwnd != 0, "Failed to create overlapped window\n" ); 13029 13030 ShowWindow( hwnd, SW_SHOW ); 13031 UpdateWindow( hwnd ); 13032 flush_events(); 13033 flush_sequence(); 13034 13035 trace("testing SetWindowRgn\n"); 13036 hrgn = CreateRectRgn( 0, 0, 150, 150 ); 13037 SetWindowRgn( hwnd, hrgn, TRUE ); 13038 ok_sequence( WmSetWindowRgn, "WmSetWindowRgn", FALSE ); 13039 13040 hrgn = CreateRectRgn( 30, 30, 160, 160 ); 13041 SetWindowRgn( hwnd, hrgn, FALSE ); 13042 ok_sequence( WmSetWindowRgn_no_redraw, "WmSetWindowRgn_no_redraw", FALSE ); 13043 13044 hrgn = CreateRectRgn( 0, 0, 180, 180 ); 13045 SetWindowRgn( hwnd, hrgn, TRUE ); 13046 ok_sequence( WmSetWindowRgn, "WmSetWindowRgn2", FALSE ); 13047 13048 SetWindowRgn( hwnd, 0, TRUE ); 13049 ok_sequence( WmSetWindowRgn_clear, "WmSetWindowRgn_clear", FALSE ); 13050 13051 DestroyWindow( hwnd ); 13052 } 13053 13054 /*************************** ShowWindow() test ******************************/ 13055 static const struct message WmShowNormal[] = { 13056 { WM_SHOWWINDOW, sent|wparam, 1 }, 13057 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 13058 { HCBT_ACTIVATE, hook }, 13059 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2003 doesn't send it */ 13060 { HCBT_SETFOCUS, hook }, 13061 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 13062 { 0 } 13063 }; 13064 static const struct message WmShow[] = { 13065 { WM_SHOWWINDOW, sent|wparam, 1 }, 13066 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 13067 { HCBT_ACTIVATE, hook|optional }, /* win2000 doesn't send it */ 13068 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2000 doesn't send it */ 13069 { HCBT_SETFOCUS, hook|optional }, /* win2000 doesn't send it */ 13070 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 13071 { 0 } 13072 }; 13073 static const struct message WmShowNoActivate_1[] = { 13074 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWNOACTIVATE }, 13075 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOMOVE }, 13076 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOMOVE }, 13077 { WM_MOVE, sent|defwinproc|optional }, 13078 { WM_SIZE, sent|wparam|defwinproc, SIZE_RESTORED }, 13079 { 0 } 13080 }; 13081 static const struct message WmShowNoActivate_2[] = { 13082 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWNOACTIVATE }, 13083 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE }, 13084 { HCBT_ACTIVATE, hook|optional }, 13085 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 13086 { HCBT_SETFOCUS, hook|optional }, 13087 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE }, 13088 { WM_MOVE, sent|defwinproc }, 13089 { WM_SIZE, sent|wparam|defwinproc, SIZE_RESTORED }, 13090 { HCBT_SETFOCUS, hook|optional }, 13091 { HCBT_ACTIVATE, hook|optional }, /* win2003 doesn't send it */ 13092 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2003 doesn't send it */ 13093 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 13094 { HCBT_SETFOCUS, hook|optional }, /* win2003 doesn't send it */ 13095 { 0 } 13096 }; 13097 static const struct message WmShowNA_1[] = { 13098 { WM_SHOWWINDOW, sent|wparam, 1 }, 13099 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 13100 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 13101 { 0 } 13102 }; 13103 static const struct message WmShowNA_2[] = { 13104 { WM_SHOWWINDOW, sent|wparam, 1 }, 13105 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 13106 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 13107 { 0 } 13108 }; 13109 static const struct message WmRestore_1[] = { 13110 { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE }, 13111 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 13112 { HCBT_ACTIVATE, hook|optional }, /* win2000 doesn't send it */ 13113 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2000 doesn't send it */ 13114 { HCBT_SETFOCUS, hook|optional }, /* win2000 doesn't send it */ 13115 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 13116 { WM_MOVE, sent|defwinproc }, 13117 { WM_SIZE, sent|wparam|defwinproc, SIZE_RESTORED }, 13118 { HCBT_SETFOCUS, hook|optional }, /* win2000 sends it */ 13119 { 0 } 13120 }; 13121 static const struct message WmRestore_2[] = { 13122 { WM_SHOWWINDOW, sent|wparam, 1 }, 13123 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 13124 { HCBT_ACTIVATE, hook|optional }, /* win2000 doesn't send it */ 13125 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2000 doesn't send it */ 13126 { HCBT_SETFOCUS, hook|optional }, /* win2000 doesn't send it */ 13127 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 13128 { 0 } 13129 }; 13130 static const struct message WmRestore_3[] = { 13131 { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE }, 13132 { WM_GETMINMAXINFO, sent }, 13133 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 13134 { HCBT_ACTIVATE, hook|optional }, /* win2003 doesn't send it */ 13135 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2003 doesn't send it */ 13136 { HCBT_SETFOCUS, hook|optional }, /* win2003 doesn't send it */ 13137 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 13138 { WM_MOVE, sent|defwinproc }, 13139 { WM_SIZE, sent|wparam|defwinproc, SIZE_MAXIMIZED }, 13140 { HCBT_SETFOCUS, hook|optional }, /* win2003 sends it */ 13141 { 0 } 13142 }; 13143 static const struct message WmRestore_4[] = { 13144 { HCBT_MINMAX, hook|lparam|optional, 0, SW_RESTORE }, 13145 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOMOVE }, 13146 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOMOVE }, 13147 { WM_MOVE, sent|defwinproc|optional }, 13148 { WM_SIZE, sent|wparam|defwinproc|optional, SIZE_RESTORED }, 13149 { 0 } 13150 }; 13151 static const struct message WmRestore_5[] = { 13152 { HCBT_MINMAX, hook|lparam|optional, 0, SW_SHOWNORMAL }, 13153 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOMOVE }, 13154 { HCBT_ACTIVATE, hook|optional }, 13155 { HCBT_SETFOCUS, hook|optional }, 13156 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOMOVE }, 13157 { WM_MOVE, sent|defwinproc|optional }, 13158 { WM_SIZE, sent|wparam|defwinproc|optional, SIZE_RESTORED }, 13159 { 0 } 13160 }; 13161 static const struct message WmHide_1[] = { 13162 { WM_SHOWWINDOW, sent|wparam, 0 }, 13163 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE, 0, SWP_NOACTIVATE }, 13164 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE, 0, SWP_NOACTIVATE }, 13165 { HCBT_ACTIVATE, hook|optional }, 13166 { HCBT_SETFOCUS, hook|optional }, /* win2000 sends it */ 13167 { 0 } 13168 }; 13169 static const struct message WmHide_2[] = { 13170 { WM_SHOWWINDOW, sent|wparam, 0 }, 13171 { WM_WINDOWPOSCHANGING, sent /*|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE*/ }, /* win2000 doesn't add SWP_NOACTIVATE */ 13172 { WM_WINDOWPOSCHANGED, sent /*|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ }, /* win2000 doesn't add SWP_NOACTIVATE */ 13173 { HCBT_ACTIVATE, hook|optional }, 13174 { 0 } 13175 }; 13176 static const struct message WmHide_3[] = { 13177 { WM_SHOWWINDOW, sent|wparam, 0 }, 13178 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 13179 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 13180 { HCBT_SETFOCUS, hook|optional }, 13181 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 13182 { 0 } 13183 }; 13184 static const struct message WmShowMinimized_1[] = { 13185 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINIMIZED }, 13186 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 13187 { HCBT_ACTIVATE, hook|optional }, /* win2000 doesn't send it */ 13188 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2000 doesn't send it */ 13189 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 13190 { WM_MOVE, sent|defwinproc }, 13191 { WM_SIZE, sent|wparam|lparam|defwinproc, SIZE_MINIMIZED, 0 }, 13192 { 0 } 13193 }; 13194 static const struct message WmMinimize_1[] = { 13195 { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, 13196 { HCBT_SETFOCUS, hook|optional }, /* win2000 doesn't send it */ 13197 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 13198 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 13199 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 13200 { WM_MOVE, sent|defwinproc }, 13201 { WM_SIZE, sent|wparam|lparam|defwinproc, SIZE_MINIMIZED, 0 }, 13202 { 0 } 13203 }; 13204 static const struct message WmMinimize_2[] = { 13205 { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, 13206 { HCBT_SETFOCUS, hook|optional }, 13207 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE }, 13208 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE }, 13209 { WM_MOVE, sent|defwinproc }, 13210 { WM_SIZE, sent|wparam|lparam|defwinproc, SIZE_MINIMIZED, 0 }, 13211 { 0 } 13212 }; 13213 static const struct message WmMinimize_3[] = { 13214 { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, 13215 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE }, 13216 { HCBT_ACTIVATE, hook|optional }, 13217 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 13218 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE }, 13219 { WM_MOVE, sent|defwinproc }, 13220 { WM_SIZE, sent|wparam|lparam|defwinproc, SIZE_MINIMIZED, 0 }, 13221 { 0 } 13222 }; 13223 static const struct message WmShowMinNoActivate[] = { 13224 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINNOACTIVE }, 13225 { WM_WINDOWPOSCHANGING, sent }, 13226 { WM_WINDOWPOSCHANGED, sent }, 13227 { WM_MOVE, sent|defwinproc|optional }, 13228 { WM_SIZE, sent|wparam|lparam|defwinproc|optional, SIZE_MINIMIZED, 0 }, 13229 { 0 } 13230 }; 13231 static const struct message WmMinMax_1[] = { 13232 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINIMIZED }, 13233 { 0 } 13234 }; 13235 static const struct message WmMinMax_2[] = { 13236 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMAXIMIZED }, 13237 { WM_GETMINMAXINFO, sent|optional }, 13238 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_FRAMECHANGED|SWP_STATECHANGED }, 13239 { HCBT_ACTIVATE, hook|optional }, 13240 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 13241 { HCBT_SETFOCUS, hook|optional }, 13242 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 13243 { WM_MOVE, sent|defwinproc|optional }, 13244 { WM_SIZE, sent|wparam|defwinproc|optional, SIZE_MAXIMIZED }, 13245 { HCBT_SETFOCUS, hook|optional }, 13246 { 0 } 13247 }; 13248 static const struct message WmMinMax_3[] = { 13249 { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, 13250 { HCBT_SETFOCUS, hook|optional }, 13251 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 13252 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 13253 { WM_MOVE, sent|defwinproc|optional }, 13254 { WM_SIZE, sent|wparam|lparam|defwinproc|optional, SIZE_MINIMIZED, 0 }, 13255 { 0 } 13256 }; 13257 static const struct message WmMinMax_4[] = { 13258 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINNOACTIVE }, 13259 { 0 } 13260 }; 13261 static const struct message WmShowMaximized_1[] = { 13262 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMAXIMIZED }, 13263 { WM_GETMINMAXINFO, sent }, 13264 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 13265 { HCBT_ACTIVATE, hook|optional }, /* win2000 doesn't send it */ 13266 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2000 doesn't send it */ 13267 { HCBT_SETFOCUS, hook|optional }, /* win2000 doesn't send it */ 13268 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 13269 { WM_MOVE, sent|defwinproc }, 13270 { WM_SIZE, sent|wparam|defwinproc, SIZE_MAXIMIZED }, 13271 { HCBT_SETFOCUS, hook|optional }, /* win2003 sends it */ 13272 { 0 } 13273 }; 13274 static const struct message WmShowMaximized_2[] = { 13275 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMAXIMIZED }, 13276 { WM_GETMINMAXINFO, sent }, 13277 { WM_WINDOWPOSCHANGING, sent|optional }, 13278 { HCBT_ACTIVATE, hook|optional }, 13279 { WM_WINDOWPOSCHANGED, sent|optional }, 13280 { WM_MOVE, sent|optional }, /* Win9x doesn't send it */ 13281 { WM_SIZE, sent|wparam|optional, SIZE_MAXIMIZED }, /* Win9x doesn't send it */ 13282 { WM_WINDOWPOSCHANGING, sent|optional }, 13283 { HCBT_SETFOCUS, hook|optional }, 13284 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 13285 { WM_MOVE, sent|defwinproc }, 13286 { WM_SIZE, sent|wparam|defwinproc, SIZE_MAXIMIZED }, 13287 { HCBT_SETFOCUS, hook|optional }, 13288 { 0 } 13289 }; 13290 static const struct message WmShowMaximized_3[] = { 13291 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMAXIMIZED }, 13292 { WM_GETMINMAXINFO, sent|optional }, 13293 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOMOVE }, 13294 { HCBT_ACTIVATE, hook|optional }, /* win2000 doesn't send it */ 13295 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2000 doesn't send it */ 13296 { HCBT_SETFOCUS, hook|optional }, /* win2000 doesn't send it */ 13297 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOMOVE }, 13298 { WM_MOVE, sent|defwinproc|optional }, 13299 { WM_SIZE, sent|wparam|defwinproc, SIZE_MAXIMIZED }, 13300 { 0 } 13301 }; 13302 13303 static void test_ShowWindow(void) 13304 { 13305 /* ShowWindow commands in random order */ 13306 static const struct 13307 { 13308 INT cmd; /* ShowWindow command */ 13309 LPARAM ret; /* ShowWindow return value */ 13310 DWORD style; /* window style after the command */ 13311 const struct message *msg; /* message sequence the command produces */ 13312 INT wp_cmd, wp_flags; /* window placement after the command */ 13313 POINT wp_min, wp_max; /* window placement after the command */ 13314 BOOL todo_msg; /* message sequence doesn't match what Wine does */ 13315 } sw[] = 13316 { 13317 /* 1 */ { SW_SHOWNORMAL, FALSE, WS_VISIBLE, WmShowNormal, 13318 SW_SHOWNORMAL, 0, {-1,-1}, {-1,-1}, FALSE }, 13319 /* 2 */ { SW_SHOWNORMAL, TRUE, WS_VISIBLE, WmEmptySeq, 13320 SW_SHOWNORMAL, 0, {-1,-1}, {-1,-1}, FALSE }, 13321 /* 3 */ { SW_HIDE, TRUE, 0, WmHide_1, 13322 SW_SHOWNORMAL, 0, {-1,-1}, {-1,-1}, FALSE }, 13323 /* 4 */ { SW_HIDE, FALSE, 0, WmEmptySeq, 13324 SW_SHOWNORMAL, 0, {-1,-1}, {-1,-1}, FALSE }, 13325 /* 5 */ { SW_SHOWMINIMIZED, FALSE, WS_VISIBLE|WS_MINIMIZE, WmShowMinimized_1, 13326 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13327 /* 6 */ { SW_SHOWMINIMIZED, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_1, 13328 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13329 /* 7 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_1, 13330 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13331 /* 8 */ { SW_HIDE, FALSE, WS_MINIMIZE, WmEmptySeq, 13332 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13333 /* 9 */ { SW_SHOWMAXIMIZED, FALSE, WS_VISIBLE|WS_MAXIMIZE, WmShowMaximized_1, 13334 SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13335 /* 10 */ { SW_SHOWMAXIMIZED, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmMinMax_2, 13336 SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13337 /* 11 */ { SW_HIDE, TRUE, WS_MAXIMIZE, WmHide_1, 13338 SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13339 /* 12 */ { SW_HIDE, FALSE, WS_MAXIMIZE, WmEmptySeq, 13340 SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13341 /* 13 */ { SW_SHOWNOACTIVATE, FALSE, WS_VISIBLE, WmShowNoActivate_1, 13342 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13343 /* 14 */ { SW_SHOWNOACTIVATE, TRUE, WS_VISIBLE, WmEmptySeq, 13344 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13345 /* 15 */ { SW_HIDE, TRUE, 0, WmHide_2, 13346 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13347 /* 16 */ { SW_HIDE, FALSE, 0, WmEmptySeq, 13348 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13349 /* 17 */ { SW_SHOW, FALSE, WS_VISIBLE, WmShow, 13350 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13351 /* 18 */ { SW_SHOW, TRUE, WS_VISIBLE, WmEmptySeq, 13352 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13353 /* 19 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinimize_1, 13354 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13355 /* 20 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_3, 13356 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13357 /* 21 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_2, 13358 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13359 /* 22 */ { SW_SHOWMINNOACTIVE, FALSE, WS_VISIBLE|WS_MINIMIZE, WmShowMinNoActivate, 13360 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, TRUE }, 13361 /* 23 */ { SW_SHOWMINNOACTIVE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_4, 13362 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13363 /* 24 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_2, 13364 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13365 /* 25 */ { SW_HIDE, FALSE, WS_MINIMIZE, WmEmptySeq, 13366 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13367 /* 26 */ { SW_SHOWNA, FALSE, WS_VISIBLE|WS_MINIMIZE, WmShowNA_1, 13368 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13369 /* 27 */ { SW_SHOWNA, TRUE, WS_VISIBLE|WS_MINIMIZE, WmShowNA_2, 13370 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13371 /* 28 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_2, 13372 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13373 /* 29 */ { SW_HIDE, FALSE, WS_MINIMIZE, WmEmptySeq, 13374 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13375 /* 30 */ { SW_RESTORE, FALSE, WS_VISIBLE, WmRestore_1, 13376 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13377 /* 31 */ { SW_RESTORE, TRUE, WS_VISIBLE, WmEmptySeq, 13378 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13379 /* 32 */ { SW_HIDE, TRUE, 0, WmHide_3, 13380 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13381 /* 33 */ { SW_HIDE, FALSE, 0, WmEmptySeq, 13382 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13383 /* 34 */ { SW_NORMALNA, FALSE, 0, WmEmptySeq, /* what does this mean?! */ 13384 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13385 /* 35 */ { SW_NORMALNA, FALSE, 0, WmEmptySeq, 13386 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13387 /* 36 */ { SW_HIDE, FALSE, 0, WmEmptySeq, 13388 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13389 /* 37 */ { SW_RESTORE, FALSE, WS_VISIBLE, WmRestore_2, 13390 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13391 /* 38 */ { SW_RESTORE, TRUE, WS_VISIBLE, WmEmptySeq, 13392 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13393 /* 39 */ { SW_SHOWNOACTIVATE, TRUE, WS_VISIBLE, WmEmptySeq, 13394 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13395 /* 40 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinimize_2, 13396 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13397 /* 41 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_3, 13398 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13399 /* 42 */ { SW_SHOWMAXIMIZED, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmShowMaximized_2, 13400 SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13401 /* 43 */ { SW_SHOWMAXIMIZED, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmMinMax_2, 13402 SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13403 /* 44 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinimize_1, 13404 SW_SHOWMINIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13405 /* 45 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_3, 13406 SW_SHOWMINIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13407 /* 46 */ { SW_RESTORE, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmRestore_3, 13408 SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13409 /* 47 */ { SW_RESTORE, TRUE, WS_VISIBLE, WmRestore_4, 13410 SW_SHOWNORMAL, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13411 /* 48 */ { SW_SHOWMAXIMIZED, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmShowMaximized_3, 13412 SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13413 /* 49 */ { SW_SHOW, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmEmptySeq, 13414 SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13415 /* 50 */ { SW_SHOWNORMAL, TRUE, WS_VISIBLE, WmRestore_5, 13416 SW_SHOWNORMAL, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13417 /* 51 */ { SW_SHOWNORMAL, TRUE, WS_VISIBLE, WmRestore_5, 13418 SW_SHOWNORMAL, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13419 /* 52 */ { SW_HIDE, TRUE, 0, WmHide_1, 13420 SW_SHOWNORMAL, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13421 /* 53 */ { SW_HIDE, FALSE, 0, WmEmptySeq, 13422 SW_SHOWNORMAL, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, 13423 /* 54 */ { SW_MINIMIZE, FALSE, WS_VISIBLE|WS_MINIMIZE, WmMinimize_3, 13424 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13425 /* 55 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_2, 13426 SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13427 /* 56 */ { SW_SHOWNOACTIVATE, FALSE, WS_VISIBLE, WmShowNoActivate_2, 13428 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, 13429 /* 57 */ { SW_SHOW, TRUE, WS_VISIBLE, WmEmptySeq, 13430 SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE } 13431 }; 13432 HWND hwnd; 13433 DWORD style; 13434 LPARAM ret; 13435 INT i; 13436 WINDOWPLACEMENT wp; 13437 RECT win_rc, work_rc = {0, 0, 0, 0}; 13438 13439 #define WS_BASE (WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_POPUP|WS_CLIPSIBLINGS) 13440 hwnd = CreateWindowExA(0, "ShowWindowClass", NULL, WS_BASE, 13441 120, 120, 90, 90, 13442 0, 0, 0, NULL); 13443 assert(hwnd); 13444 13445 style = GetWindowLongA(hwnd, GWL_STYLE) & ~WS_BASE; 13446 ok(style == 0, "expected style 0, got %08x\n", style); 13447 13448 flush_events(); 13449 flush_sequence(); 13450 13451 if (pGetMonitorInfoA && pMonitorFromPoint) 13452 { 13453 HMONITOR hmon; 13454 MONITORINFO mi; 13455 POINT pt = {0, 0}; 13456 13457 SetLastError(0xdeadbeef); 13458 hmon = pMonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY); 13459 ok(hmon != 0, "MonitorFromPoint error %u\n", GetLastError()); 13460 13461 mi.cbSize = sizeof(mi); 13462 SetLastError(0xdeadbeef); 13463 ret = pGetMonitorInfoA(hmon, &mi); 13464 ok(ret, "GetMonitorInfo error %u\n", GetLastError()); 13465 trace("monitor %s, work %s\n", wine_dbgstr_rect(&mi.rcMonitor), 13466 wine_dbgstr_rect(&mi.rcWork)); 13467 work_rc = mi.rcWork; 13468 } 13469 13470 GetWindowRect(hwnd, &win_rc); 13471 OffsetRect(&win_rc, -work_rc.left, -work_rc.top); 13472 13473 wp.length = sizeof(wp); 13474 SetLastError(0xdeadbeaf); 13475 ret = GetWindowPlacement(hwnd, &wp); 13476 ok(ret, "GetWindowPlacement error %u\n", GetLastError()); 13477 ok(wp.flags == 0, "expected 0, got %#x\n", wp.flags); 13478 ok(wp.showCmd == SW_SHOWNORMAL, "expected SW_SHOWNORMAL, got %d\n", wp.showCmd); 13479 ok(wp.ptMinPosition.x == -1 && wp.ptMinPosition.y == -1, 13480 "expected -1,-1 got %d,%d\n", wp.ptMinPosition.x, wp.ptMinPosition.y); 13481 ok(wp.ptMaxPosition.x == -1 && wp.ptMaxPosition.y == -1, 13482 "expected -1,-1 got %d,%d\n", wp.ptMaxPosition.x, wp.ptMaxPosition.y); 13483 todo_wine_if (work_rc.left || work_rc.top) /* FIXME: remove once Wine is fixed */ 13484 ok(EqualRect(&win_rc, &wp.rcNormalPosition), "expected %s got %s\n", wine_dbgstr_rect(&win_rc), 13485 wine_dbgstr_rect(&wp.rcNormalPosition)); 13486 13487 for (i = 0; i < ARRAY_SIZE(sw); i++) 13488 { 13489 static const char * const sw_cmd_name[13] = 13490 { 13491 "SW_HIDE", "SW_SHOWNORMAL", "SW_SHOWMINIMIZED", "SW_SHOWMAXIMIZED", 13492 "SW_SHOWNOACTIVATE", "SW_SHOW", "SW_MINIMIZE", "SW_SHOWMINNOACTIVE", 13493 "SW_SHOWNA", "SW_RESTORE", "SW_SHOWDEFAULT", "SW_FORCEMINIMIZE", 13494 "SW_NORMALNA" /* 0xCC */ 13495 }; 13496 char comment[64]; 13497 INT idx; /* index into the above array of names */ 13498 13499 idx = (sw[i].cmd == SW_NORMALNA) ? 12 : sw[i].cmd; 13500 13501 style = GetWindowLongA(hwnd, GWL_STYLE); 13502 trace("%d: sending %s, current window style %08x\n", i+1, sw_cmd_name[idx], style); 13503 ret = ShowWindow(hwnd, sw[i].cmd); 13504 ok(!ret == !sw[i].ret, "%d: cmd %s: expected ret %lu, got %lu\n", i+1, sw_cmd_name[idx], sw[i].ret, ret); 13505 style = GetWindowLongA(hwnd, GWL_STYLE) & ~WS_BASE; 13506 ok(style == sw[i].style, "%d: expected style %08x, got %08x\n", i+1, sw[i].style, style); 13507 13508 sprintf(comment, "%d: ShowWindow(%s)", i+1, sw_cmd_name[idx]); 13509 ok_sequence(sw[i].msg, comment, sw[i].todo_msg); 13510 13511 wp.length = sizeof(wp); 13512 SetLastError(0xdeadbeaf); 13513 ret = GetWindowPlacement(hwnd, &wp); 13514 ok(ret, "GetWindowPlacement error %u\n", GetLastError()); 13515 ok(wp.flags == sw[i].wp_flags, "expected %#x, got %#x\n", sw[i].wp_flags, wp.flags); 13516 ok(wp.showCmd == sw[i].wp_cmd, "expected %d, got %d\n", sw[i].wp_cmd, wp.showCmd); 13517 13518 /* NT moves the minimized window to -32000,-32000, win9x to 3000,3000 */ 13519 if ((wp.ptMinPosition.x + work_rc.left == -32000 && wp.ptMinPosition.y + work_rc.top == -32000) || 13520 (wp.ptMinPosition.x + work_rc.left == 3000 && wp.ptMinPosition.y + work_rc.top == 3000)) 13521 { 13522 ok((wp.ptMinPosition.x + work_rc.left == sw[i].wp_min.x && wp.ptMinPosition.y + work_rc.top == sw[i].wp_min.y) || 13523 (wp.ptMinPosition.x + work_rc.left == 3000 && wp.ptMinPosition.y + work_rc.top == 3000), 13524 "expected %d,%d got %d,%d\n", sw[i].wp_min.x, sw[i].wp_min.y, wp.ptMinPosition.x, wp.ptMinPosition.y); 13525 } 13526 else 13527 { 13528 ok(wp.ptMinPosition.x == sw[i].wp_min.x && wp.ptMinPosition.y == sw[i].wp_min.y, 13529 "expected %d,%d got %d,%d\n", sw[i].wp_min.x, sw[i].wp_min.y, wp.ptMinPosition.x, wp.ptMinPosition.y); 13530 } 13531 13532 todo_wine_if(wp.ptMaxPosition.x != sw[i].wp_max.x || wp.ptMaxPosition.y != sw[i].wp_max.y) 13533 ok(wp.ptMaxPosition.x == sw[i].wp_max.x && wp.ptMaxPosition.y == sw[i].wp_max.y, 13534 "expected %d,%d got %d,%d\n", sw[i].wp_max.x, sw[i].wp_max.y, wp.ptMaxPosition.x, wp.ptMaxPosition.y); 13535 13536 if (0) /* FIXME: Wine behaves completely different here */ 13537 ok(EqualRect(&win_rc, &wp.rcNormalPosition), "expected %s got %s\n", 13538 wine_dbgstr_rect(&win_rc), wine_dbgstr_rect(&wp.rcNormalPosition)); 13539 } 13540 DestroyWindow(hwnd); 13541 flush_events(); 13542 } 13543 13544 static INT_PTR WINAPI test_dlg_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 13545 { 13546 struct recvd_message msg; 13547 13548 if (ignore_message( message )) return 0; 13549 13550 msg.hwnd = hwnd; 13551 msg.message = message; 13552 msg.flags = sent|wparam|lparam; 13553 msg.wParam = wParam; 13554 msg.lParam = lParam; 13555 msg.descr = "dialog"; 13556 add_message(&msg); 13557 13558 /* calling DefDlgProc leads to a recursion under XP */ 13559 13560 switch (message) 13561 { 13562 case WM_INITDIALOG: 13563 return lParam; 13564 13565 case WM_GETDLGCODE: 13566 return 0; 13567 } 13568 return 1; 13569 } 13570 13571 static WNDPROC orig_edit_proc; 13572 static LRESULT WINAPI dlg_creation_edit_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) 13573 { 13574 struct recvd_message msg; 13575 13576 if (ignore_message( message )) return 0; 13577 13578 msg.hwnd = hwnd; 13579 msg.message = message; 13580 msg.flags = sent|wparam|lparam; 13581 msg.wParam = wp; 13582 msg.lParam = lp; 13583 msg.descr = "edit"; 13584 add_message(&msg); 13585 13586 return CallWindowProcW(orig_edit_proc, hwnd, message, wp, lp); 13587 } 13588 13589 static INT_PTR WINAPI test_dlg_proc2(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 13590 { 13591 struct recvd_message msg; 13592 13593 if (ignore_message( message )) return 0; 13594 13595 msg.hwnd = hwnd; 13596 msg.message = message; 13597 msg.flags = sent|wparam|lparam|parent; 13598 msg.wParam = wParam; 13599 msg.lParam = lParam; 13600 msg.descr = "dialog"; 13601 add_message(&msg); 13602 13603 if (message == WM_INITDIALOG) 13604 { 13605 orig_edit_proc = (WNDPROC)SetWindowLongPtrW(GetDlgItem(hwnd, 200), 13606 GWLP_WNDPROC, (LONG_PTR)dlg_creation_edit_proc); 13607 } 13608 13609 return 1; 13610 } 13611 13612 static INT_PTR WINAPI test_dlg_proc3(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 13613 { 13614 ok( 0, "should not be called since DefDlgProc is not used\n" ); 13615 return 0; 13616 } 13617 13618 static LRESULT WINAPI test_dlg_proc4(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 13619 { 13620 struct recvd_message msg; 13621 13622 if (!ignore_message( message )) 13623 { 13624 msg.hwnd = hwnd; 13625 msg.message = message; 13626 msg.flags = sent|wparam|lparam|parent; 13627 msg.wParam = wParam; 13628 msg.lParam = lParam; 13629 msg.descr = "dialog"; 13630 add_message(&msg); 13631 } 13632 if (message == WM_INITDIALOG) 13633 { 13634 orig_edit_proc = (WNDPROC)SetWindowLongPtrW(GetDlgItem(hwnd, 200), 13635 GWLP_WNDPROC, (LONG_PTR)dlg_creation_edit_proc); 13636 return 1; 13637 } 13638 return DefWindowProcW( hwnd, message, wParam, lParam ); 13639 } 13640 13641 static const struct message WmDefDlgSetFocus_1[] = { 13642 { WM_GETDLGCODE, sent|wparam|lparam, 0, 0 }, 13643 { WM_GETTEXTLENGTH, sent|wparam|lparam|optional, 0, 0 }, /* XP */ 13644 { WM_GETTEXT, sent|wparam|optional, 6 }, /* XP */ 13645 { WM_GETTEXT, sent|wparam|optional, 12 }, /* XP */ 13646 { EM_SETSEL, sent|wparam, 0 }, /* XP sets lparam to text length, Win9x to -2 */ 13647 { HCBT_SETFOCUS, hook }, 13648 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, 13649 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 13650 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 13651 { WM_SETFOCUS, sent|wparam, 0 }, 13652 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 10 }, 13653 { WM_CTLCOLOREDIT, sent }, 13654 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 11 }, 13655 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 13656 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 13657 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 13658 { WM_COMMAND, sent|wparam, MAKEWPARAM(1, EN_SETFOCUS) }, 13659 { 0 } 13660 }; 13661 static const struct message WmDefDlgSetFocus_2[] = { 13662 { WM_GETDLGCODE, sent|wparam|lparam, 0, 0 }, 13663 { WM_GETTEXTLENGTH, sent|wparam|lparam|optional, 0, 0 }, /* XP */ 13664 { WM_GETTEXT, sent|wparam|optional, 6 }, /* XP */ 13665 { WM_GETTEXT, sent|wparam|optional, 12 }, /* XP */ 13666 { EM_SETSEL, sent|wparam, 0 }, /* XP sets lparam to text length, Win9x to -2 */ 13667 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 13668 { WM_CTLCOLOREDIT, sent|optional }, /* XP */ 13669 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, 13670 { 0 } 13671 }; 13672 /* Creation of a dialog */ 13673 static const struct message WmCreateDialogParamSeq_0[] = { 13674 { HCBT_CREATEWND, hook }, 13675 { WM_NCCREATE, sent }, 13676 { WM_NCCALCSIZE, sent|wparam, 0 }, 13677 { WM_CREATE, sent }, 13678 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 13679 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 13680 { WM_MOVE, sent }, 13681 { WM_SETFONT, sent }, 13682 { WM_INITDIALOG, sent }, 13683 { WM_CHANGEUISTATE, sent|optional }, 13684 { 0 } 13685 }; 13686 /* Creation of a dialog */ 13687 static const struct message WmCreateDialogParamSeq_1[] = { 13688 { HCBT_CREATEWND, hook }, 13689 { WM_NCCREATE, sent }, 13690 { WM_NCCALCSIZE, sent|wparam, 0 }, 13691 { WM_CREATE, sent }, 13692 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 13693 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 13694 { WM_MOVE, sent }, 13695 { WM_SETFONT, sent }, 13696 { WM_INITDIALOG, sent }, 13697 { WM_GETDLGCODE, sent|wparam|lparam|optional, 0, 0 }, /* FIXME: Wine doesn't send it */ 13698 { HCBT_SETFOCUS, hook }, 13699 { HCBT_ACTIVATE, hook }, 13700 { WM_QUERYNEWPALETTE, sent|optional }, 13701 { WM_PALETTEISCHANGING, sent|optional }, 13702 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 13703 { WM_ACTIVATEAPP, sent|wparam, 1 }, 13704 { WM_NCACTIVATE, sent }, 13705 { WM_ACTIVATE, sent|wparam, 1 }, 13706 { WM_SETFOCUS, sent }, 13707 { WM_CHANGEUISTATE, sent|optional }, 13708 { 0 } 13709 }; 13710 /* Creation of a dialog */ 13711 static const struct message WmCreateDialogParamSeq_2[] = { 13712 { HCBT_CREATEWND, hook }, 13713 { WM_NCCREATE, sent }, 13714 { WM_NCCALCSIZE, sent|wparam, 0 }, 13715 { WM_CREATE, sent }, 13716 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 13717 { WM_SIZE, sent|wparam, SIZE_RESTORED }, 13718 { WM_MOVE, sent }, 13719 { WM_CHANGEUISTATE, sent|optional }, 13720 { 0 } 13721 }; 13722 13723 static const struct message WmCreateDialogParamSeq_3[] = { 13724 { HCBT_CREATEWND, hook }, 13725 { WM_SETFONT, sent|parent }, 13726 { WM_INITDIALOG, sent|parent }, 13727 { WM_GETDLGCODE, sent|wparam|lparam, 0, 0 }, 13728 { EM_SETSEL, sent|wparam|lparam, 0, INT_MAX }, 13729 { EM_SETSEL, sent|wparam|lparam|optional, 0, INT_MAX }, 13730 { EM_SETSEL, sent|wparam|lparam|optional, 0, INT_MAX }, 13731 { EM_SETSEL, sent|wparam|lparam|optional, 0, INT_MAX }, 13732 { HCBT_ACTIVATE, hook }, 13733 { WM_QUERYNEWPALETTE, sent|parent|optional }, /* TODO: this message should not be sent */ 13734 { WM_WINDOWPOSCHANGING, sent|parent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 13735 { WM_WINDOWPOSCHANGING, sent|parent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 13736 { WM_WINDOWPOSCHANGED, sent|parent|wparam|optional, SWP_NOREDRAW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 13737 { WM_WINDOWPOSCHANGED, sent|parent|wparam|optional, SWP_NOREDRAW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 13738 { WM_ACTIVATEAPP, sent|parent|wparam, 1 }, 13739 { WM_NCACTIVATE, sent|parent }, 13740 { WM_ACTIVATE, sent|parent|wparam, 1 }, 13741 { WM_SETFOCUS, sent }, 13742 { WM_COMMAND, sent|parent|wparam, MAKELONG(200, EN_SETFOCUS) }, 13743 { WM_GETDLGCODE, sent|wparam|lparam, 0, 0 }, 13744 { WM_USER, sent|parent }, 13745 { WM_CHANGEUISTATE, sent|parent|optional }, 13746 { 0 } 13747 }; 13748 13749 static const struct message WmCreateDialogParamSeq_4[] = { 13750 { HCBT_CREATEWND, hook }, 13751 { WM_NCCREATE, sent|parent }, 13752 { WM_NCCALCSIZE, sent|parent|wparam, 0 }, 13753 { WM_CREATE, sent|parent }, 13754 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, 13755 { WM_SIZE, sent|parent|wparam, SIZE_RESTORED }, 13756 { WM_MOVE, sent|parent }, 13757 { WM_SETFONT, sent|parent }, 13758 { WM_INITDIALOG, sent|parent }, 13759 { WM_GETDLGCODE, sent|wparam|lparam, 0, 0 }, 13760 { EM_SETSEL, sent|wparam|lparam, 0, INT_MAX }, 13761 { EM_SETSEL, sent|wparam|lparam|optional, 0, INT_MAX }, 13762 { EM_SETSEL, sent|wparam|lparam|optional, 0, INT_MAX }, 13763 { EM_SETSEL, sent|wparam|lparam|optional, 0, INT_MAX }, 13764 { HCBT_ACTIVATE, hook }, 13765 { WM_QUERYNEWPALETTE, sent|parent|optional }, /* TODO: this message should not be sent */ 13766 { WM_WINDOWPOSCHANGING, sent|parent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 13767 { WM_WINDOWPOSCHANGING, sent|parent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 13768 { WM_ACTIVATEAPP, sent|parent|wparam, 1 }, 13769 { WM_NCACTIVATE, sent|parent }, 13770 { WM_ACTIVATE, sent|parent|wparam, 1 }, 13771 { HCBT_SETFOCUS, hook }, 13772 { WM_SETFOCUS, sent|parent }, 13773 { WM_KILLFOCUS, sent|parent }, 13774 { WM_SETFOCUS, sent }, 13775 { WM_COMMAND, sent|parent|wparam, MAKELONG(200, EN_SETFOCUS) }, 13776 { WM_GETDLGCODE, sent|wparam|lparam, 0, 0 }, 13777 { WM_USER, sent|parent }, 13778 { WM_CHANGEUISTATE, sent|parent|optional }, 13779 { WM_UPDATEUISTATE, sent|parent|optional }, 13780 { WM_UPDATEUISTATE, sent|optional }, 13781 { 0 } 13782 }; 13783 13784 static void test_dialog_messages(void) 13785 { 13786 WNDCLASSA cls; 13787 HWND hdlg, hedit1, hedit2, hfocus, parent, child, child2; 13788 LRESULT ret; 13789 13790 #define set_selection(hctl, start, end) \ 13791 ret = SendMessageA(hctl, EM_SETSEL, start, end); \ 13792 ok(ret == 1, "EM_SETSEL returned %ld\n", ret); 13793 13794 #define check_selection(hctl, start, end) \ 13795 ret = SendMessageA(hctl, EM_GETSEL, 0, 0); \ 13796 ok(ret == MAKELRESULT(start, end), "wrong selection (%d - %d)\n", LOWORD(ret), HIWORD(ret)); 13797 13798 subclass_edit(); 13799 13800 hdlg = CreateWindowExA(WS_EX_DLGMODALFRAME, "TestDialogClass", NULL, 13801 WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_DLGFRAME, 13802 0, 0, 100, 100, 0, 0, 0, NULL); 13803 ok(hdlg != 0, "Failed to create custom dialog window\n"); 13804 13805 hedit1 = CreateWindowExA(0, "my_edit_class", NULL, 13806 WS_CHILD|WS_BORDER|WS_VISIBLE|WS_TABSTOP, 13807 0, 0, 80, 20, hdlg, (HMENU)1, 0, NULL); 13808 ok(hedit1 != 0, "Failed to create edit control\n"); 13809 hedit2 = CreateWindowExA(0, "my_edit_class", NULL, 13810 WS_CHILD|WS_BORDER|WS_VISIBLE|WS_TABSTOP, 13811 0, 40, 80, 20, hdlg, (HMENU)2, 0, NULL); 13812 ok(hedit2 != 0, "Failed to create edit control\n"); 13813 13814 SendMessageA(hedit1, WM_SETTEXT, 0, (LPARAM)"hello"); 13815 SendMessageA(hedit2, WM_SETTEXT, 0, (LPARAM)"bye"); 13816 13817 hfocus = GetFocus(); 13818 ok(hfocus == hdlg, "wrong focus %p\n", hfocus); 13819 13820 SetFocus(hedit2); 13821 hfocus = GetFocus(); 13822 ok(hfocus == hedit2, "wrong focus %p\n", hfocus); 13823 13824 check_selection(hedit1, 0, 0); 13825 check_selection(hedit2, 0, 0); 13826 13827 set_selection(hedit2, 0, -1); 13828 check_selection(hedit2, 0, 3); 13829 13830 SetFocus(0); 13831 hfocus = GetFocus(); 13832 ok(hfocus == 0, "wrong focus %p\n", hfocus); 13833 13834 flush_sequence(); 13835 ret = DefDlgProcA(hdlg, WM_SETFOCUS, 0, 0); 13836 ok(ret == 0, "WM_SETFOCUS returned %ld\n", ret); 13837 ok_sequence(WmDefDlgSetFocus_1, "DefDlgProc(WM_SETFOCUS) 1", FALSE); 13838 13839 hfocus = GetFocus(); 13840 ok(hfocus == hedit1, "wrong focus %p\n", hfocus); 13841 13842 check_selection(hedit1, 0, 5); 13843 check_selection(hedit2, 0, 3); 13844 13845 flush_sequence(); 13846 ret = DefDlgProcA(hdlg, WM_SETFOCUS, 0, 0); 13847 ok(ret == 0, "WM_SETFOCUS returned %ld\n", ret); 13848 ok_sequence(WmDefDlgSetFocus_2, "DefDlgProc(WM_SETFOCUS) 2", FALSE); 13849 13850 hfocus = GetFocus(); 13851 ok(hfocus == hedit1, "wrong focus %p\n", hfocus); 13852 13853 check_selection(hedit1, 0, 5); 13854 check_selection(hedit2, 0, 3); 13855 13856 EndDialog(hdlg, 0); 13857 DestroyWindow(hedit1); 13858 DestroyWindow(hedit2); 13859 DestroyWindow(hdlg); 13860 flush_sequence(); 13861 13862 #undef set_selection 13863 #undef check_selection 13864 13865 ok(GetClassInfoA(0, "#32770", &cls), "GetClassInfo failed\n"); 13866 cls.lpszClassName = "MyDialogClass"; 13867 cls.hInstance = GetModuleHandleA(NULL); 13868 /* need a cast since a dlgproc is used as a wndproc */ 13869 cls.lpfnWndProc = test_dlg_proc; 13870 if (!RegisterClassA(&cls)) assert(0); 13871 13872 SetFocus(0); 13873 flush_sequence(); 13874 hdlg = CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", 0, test_dlg_proc, 0); 13875 ok(IsWindow(hdlg), "CreateDialogParam failed\n"); 13876 ok_sequence(WmCreateDialogParamSeq_0, "CreateDialogParam_0", FALSE); 13877 hfocus = GetFocus(); 13878 ok(hfocus == 0, "wrong focus %p\n", hfocus); 13879 EndDialog(hdlg, 0); 13880 DestroyWindow(hdlg); 13881 flush_sequence(); 13882 13883 SetFocus(0); 13884 flush_sequence(); 13885 hdlg = CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", 0, test_dlg_proc, 1); 13886 ok(IsWindow(hdlg), "CreateDialogParam failed\n"); 13887 ok_sequence(WmCreateDialogParamSeq_1, "CreateDialogParam_1", FALSE); 13888 hfocus = GetFocus(); 13889 ok(hfocus == hdlg, "wrong focus %p\n", hfocus); 13890 EndDialog(hdlg, 0); 13891 DestroyWindow(hdlg); 13892 flush_sequence(); 13893 13894 hdlg = CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", 0, NULL, 0); 13895 ok(IsWindow(hdlg), "CreateDialogParam failed\n"); 13896 ok_sequence(WmCreateDialogParamSeq_2, "CreateDialogParam_2", FALSE); 13897 EndDialog(hdlg, 0); 13898 DestroyWindow(hdlg); 13899 flush_sequence(); 13900 13901 hdlg = CreateDialogParamA(0, "FOCUS_TEST_DIALOG_3", 0, test_dlg_proc2, 0); 13902 ok(IsWindow(hdlg), "CreateDialogParam failed\n"); 13903 ok_sequence(WmCreateDialogParamSeq_3, "CreateDialogParam_3", TRUE); 13904 EndDialog(hdlg, 0); 13905 DestroyWindow(hdlg); 13906 flush_sequence(); 13907 13908 UnregisterClassA( cls.lpszClassName, cls.hInstance ); 13909 cls.lpfnWndProc = test_dlg_proc4; 13910 ok( RegisterClassA(&cls), "failed to register class again\n" ); 13911 hdlg = CreateDialogParamA(0, "FOCUS_TEST_DIALOG_4", 0, test_dlg_proc3, 0); 13912 ok(IsWindow(hdlg), "CreateDialogParam failed\n"); 13913 ok_sequence(WmCreateDialogParamSeq_4, "CreateDialogParam_4", TRUE); 13914 EndDialog(hdlg, 0); 13915 DestroyWindow(hdlg); 13916 flush_sequence(); 13917 13918 UnregisterClassA(cls.lpszClassName, cls.hInstance); 13919 13920 parent = CreateWindowExA(0, "TestParentClass", "Test parent", 13921 WS_OVERLAPPEDWINDOW | WS_VISIBLE, 13922 100, 100, 200, 200, 0, 0, 0, NULL); 13923 ok (parent != 0, "Failed to create parent window\n"); 13924 13925 /* This child has no parent set. We will later call SetParent on it, 13926 * so that it will have a parent set, but no WS_CHILD style. */ 13927 child = CreateWindowExA(0, "TestWindowClass", "Test child", 13928 WS_OVERLAPPEDWINDOW | WS_VISIBLE, 13929 100, 100, 200, 200, 0, 0, 0, NULL); 13930 ok (child != 0, "Failed to create child window\n"); 13931 13932 /* This is a regular child window. When used as an owner, the other 13933 * child window will be used. */ 13934 child2 = CreateWindowExA(0, "SimpleWindowClass", "Test child2", 13935 WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CHILD, 13936 100, 100, 200, 200, child, 0, 0, NULL); 13937 ok (child2 != 0, "Failed to create child window\n"); 13938 13939 SetParent(child, parent); 13940 SetFocus(child); 13941 13942 flush_sequence(); 13943 DialogBoxA( 0, "TEST_DIALOG", child2, TestModalDlgProc2 ); 13944 ok_sequence(WmModalDialogSeq_2, "ModalDialog2", TRUE); 13945 13946 DestroyWindow(child2); 13947 DestroyWindow(child); 13948 DestroyWindow(parent); 13949 flush_sequence(); 13950 } 13951 13952 static void test_enddialog_seq(HWND dialog, HWND owner) 13953 { 13954 const struct message seq[] = { 13955 { WM_ENABLE, sent }, 13956 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 13957 { HCBT_ACTIVATE, hook|wparam, (WPARAM)owner }, 13958 { WM_NCACTIVATE, sent|wparam|lparam, WA_INACTIVE, (LPARAM)owner }, 13959 { WM_ACTIVATE, sent|wparam|lparam, WA_INACTIVE, (LPARAM)owner }, 13960 /* FIXME: Following two are optional because Wine sends WM_QUERYNEWPALETTE instead of WM_WINDOWPOSCHANGING */ 13961 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 13962 { WM_QUERYNEWPALETTE, sent|optional }, 13963 { WM_NCACTIVATE, sent|wparam|lparam, WA_ACTIVE, (LPARAM)dialog }, 13964 { WM_GETTEXT, sent|optional|defwinproc }, 13965 { WM_ACTIVATE, sent|wparam|lparam, WA_ACTIVE, (LPARAM)dialog }, 13966 { HCBT_SETFOCUS, hook|wparam, (WPARAM)owner }, 13967 { WM_KILLFOCUS, sent|wparam, (WPARAM)owner }, 13968 { WM_SETFOCUS, sent|defwinproc|wparam, (WPARAM)dialog }, 13969 { 0 } 13970 }; 13971 13972 flush_sequence(); 13973 EndDialog(dialog, 0); 13974 ok_sequence(seq, "EndDialog", FALSE); 13975 } 13976 13977 static void test_enddialog_seq2(HWND dialog, HWND owner) 13978 { 13979 const struct message seq[] = { 13980 { WM_ENABLE, parent|sent }, 13981 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 13982 { HCBT_ACTIVATE, hook|wparam, (WPARAM)owner }, 13983 { WM_NCACTIVATE, sent|wparam|lparam, WA_INACTIVE, (LPARAM)owner }, 13984 { WM_ACTIVATE, sent|wparam|lparam, WA_INACTIVE, (LPARAM)owner }, 13985 { WM_WINDOWPOSCHANGING, sent|optional|wparam, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 13986 { WM_WINDOWPOSCHANGING, sent|optional|wparam, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 13987 { HCBT_SETFOCUS, hook|wparam, (WPARAM)owner }, 13988 { WM_KILLFOCUS, sent|wparam, (WPARAM)owner }, 13989 { WM_SETFOCUS, sent|parent|defwinproc|wparam, (WPARAM)dialog }, 13990 { 0 } 13991 }; 13992 13993 flush_sequence(); 13994 EndDialog(dialog, 0); 13995 ok_sequence(seq, "EndDialog2", FALSE); 13996 } 13997 13998 static void test_EndDialog(void) 13999 { 14000 HWND hparent, hother, hactive, hdlg, hchild; 14001 WNDCLASSA cls; 14002 14003 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", 14004 WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_DISABLED, 14005 100, 100, 200, 200, 0, 0, 0, NULL); 14006 ok (hparent != 0, "Failed to create parent window\n"); 14007 14008 hother = CreateWindowExA(0, "TestParentClass", "Test parent 2", 14009 WS_OVERLAPPEDWINDOW | WS_VISIBLE, 14010 200, 100, 200, 200, 0, 0, 0, NULL); 14011 ok (hother != 0, "Failed to create parent window\n"); 14012 14013 ok(GetClassInfoA(0, "#32770", &cls), "GetClassInfo failed\n"); 14014 cls.lpszClassName = "MyDialogClass"; 14015 cls.hInstance = GetModuleHandleA(NULL); 14016 cls.lpfnWndProc = test_dlg_proc; 14017 if (!RegisterClassA(&cls)) assert(0); 14018 14019 flush_sequence(); 14020 SetForegroundWindow(hother); 14021 hactive = GetForegroundWindow(); 14022 ok(hother == hactive, "Wrong window has focus (%p != %p)\n", hother, hactive); 14023 14024 /* create a dialog where the parent is disabled, this parent should be 14025 * enabled and receive focus when dialog exits */ 14026 hdlg = CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", hparent, test_dlg_proc, 0); 14027 ok(IsWindow(hdlg), "CreateDialogParam failed\n"); 14028 SetForegroundWindow(hdlg); 14029 hactive = GetForegroundWindow(); 14030 ok(hdlg == hactive, "Wrong window has focus (%p != %p)\n", hdlg, hactive); 14031 EndDialog(hdlg, 0); 14032 ok(IsWindowEnabled(hparent), "parent is not enabled\n"); 14033 hactive = GetForegroundWindow(); 14034 ok(hparent == hactive, "Wrong window has focus (parent != active) (active: %p, parent: %p, dlg: %p, other: %p)\n", hactive, hparent, hdlg, hother); 14035 DestroyWindow(hdlg); 14036 flush_sequence(); 14037 14038 /* create a dialog where the parent is disabled and set active window to other window before calling EndDialog */ 14039 EnableWindow(hparent, FALSE); 14040 hdlg = CreateWindowExA(0, "TestDialogClass", NULL, 14041 WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_DLGFRAME, 14042 0, 0, 100, 100, hparent, 0, 0, NULL); 14043 ok(IsWindow(hdlg), "CreateDialogParam failed\n"); 14044 flush_sequence(); 14045 SetForegroundWindow(hother); 14046 flush_sequence(); 14047 hactive = GetForegroundWindow(); 14048 ok(hactive == hother, "Wrong foreground (%p != %p)\n", hactive, hother); 14049 hactive = GetActiveWindow(); 14050 ok(hactive == hother, "Wrong active window (%p != %p)\n", hactive, hother); 14051 EndDialog(hdlg, 0); 14052 ok(IsWindowEnabled(hparent), "parent is not enabled\n"); 14053 hactive = GetForegroundWindow(); 14054 ok(hother == hactive, "Wrong window has focus (other != active) (active: %p, parent: %p, dlg: %p, other: %p)\n", hactive, hparent, hdlg, hother); 14055 DestroyWindow(hdlg); 14056 flush_sequence(); 14057 14058 DestroyWindow( hparent ); 14059 14060 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", 14061 WS_POPUP | WS_VISIBLE | WS_DISABLED, 14062 100, 100, 200, 200, 0, 0, 0, NULL); 14063 ok (hparent != 0, "Failed to create parent window\n"); 14064 14065 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", 14066 WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_DISABLED, 14067 0, 0, 0, 0, 0, 0, 0, NULL); 14068 ok (hchild != 0, "Failed to create child window\n"); 14069 14070 SetParent(hchild, hparent); 14071 14072 flush_sequence(); 14073 SetForegroundWindow(hother); 14074 hactive = GetForegroundWindow(); 14075 ok(hother == hactive, "Wrong foreground window (%p != %p)\n", hother, hactive); 14076 14077 hdlg = CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", hchild, test_dlg_proc, 0); 14078 ok(IsWindow(hdlg), "CreateDialogParam failed\n"); 14079 14080 SetForegroundWindow(hdlg); 14081 test_enddialog_seq(hdlg, hchild); 14082 14083 hactive = GetForegroundWindow(); 14084 ok(hactive == hchild, "Wrong foreground window (active: %p, parent: %p, dlg: %p, other: %p child: %p)\n", hactive, hparent, hdlg, hother, hchild); 14085 14086 DestroyWindow(hdlg); 14087 14088 /* Now set WS_CHILD style flag so that it's a real child and its parent will be dialog's owner. */ 14089 SetWindowLongW(hchild, GWL_STYLE, GetWindowLongW(hchild, GWL_STYLE) | WS_CHILD); 14090 14091 SetForegroundWindow(hother); 14092 hactive = GetForegroundWindow(); 14093 ok(hother == hactive, "Wrong foreground window (%p != %p)\n", hother, hactive); 14094 14095 hdlg = CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", hchild, test_dlg_proc, 0); 14096 ok(IsWindow(hdlg), "CreateDialogParam failed\n"); 14097 14098 SetForegroundWindow(hdlg); 14099 test_enddialog_seq2(hdlg, hparent); 14100 14101 hactive = GetForegroundWindow(); 14102 ok(hactive == hparent, "Wrong foreground window (active: %p, parent: %p, dlg: %p, other: %p child: %p)\n", hactive, hparent, hdlg, hother, hchild); 14103 DestroyWindow(hdlg); 14104 DestroyWindow(hchild); 14105 DestroyWindow(hparent); 14106 DestroyWindow(hother); 14107 flush_sequence(); 14108 14109 UnregisterClassA(cls.lpszClassName, cls.hInstance); 14110 } 14111 14112 static void test_nullCallback(void) 14113 { 14114 HWND hwnd; 14115 14116 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW, 14117 100, 100, 200, 200, 0, 0, 0, NULL); 14118 ok (hwnd != 0, "Failed to create overlapped window\n"); 14119 14120 SendMessageCallbackA(hwnd,WM_NULL,0,0,NULL,0); 14121 flush_events(); 14122 DestroyWindow(hwnd); 14123 } 14124 14125 /* SetActiveWindow( 0 ) hwnd visible */ 14126 static const struct message SetActiveWindowSeq0[] = 14127 { 14128 { HCBT_ACTIVATE, hook|optional }, 14129 { WM_NCACTIVATE, sent|wparam, 0 }, 14130 { WM_GETTEXT, sent|defwinproc|optional }, 14131 { WM_ACTIVATE, sent|wparam, 0 }, 14132 { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, 14133 { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, 14134 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 14135 { WM_KILLFOCUS, sent|optional }, 14136 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, 14137 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 14138 { WM_NCACTIVATE, sent|wparam|optional, 1 }, 14139 { WM_GETTEXT, sent|defwinproc|optional }, 14140 { WM_ACTIVATE, sent|wparam|optional, 1 }, 14141 { HCBT_SETFOCUS, hook|optional }, 14142 { WM_KILLFOCUS, sent|defwinproc|optional }, 14143 { WM_IME_SETCONTEXT, sent|defwinproc|optional }, 14144 { WM_IME_SETCONTEXT, sent|defwinproc|optional }, 14145 { WM_IME_SETCONTEXT, sent|optional }, 14146 { WM_IME_SETCONTEXT, sent|optional }, 14147 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, 14148 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 14149 { WM_SETFOCUS, sent|defwinproc|optional }, 14150 { WM_GETTEXT, sent|optional }, 14151 { 0 } 14152 }; 14153 /* SetActiveWindow( hwnd ) hwnd visible */ 14154 static const struct message SetActiveWindowSeq1[] = 14155 { 14156 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 14157 { 0 } 14158 }; 14159 /* SetActiveWindow( popup ) hwnd visible, popup visible */ 14160 static const struct message SetActiveWindowSeq2[] = 14161 { 14162 { HCBT_ACTIVATE, hook }, 14163 { WM_NCACTIVATE, sent|wparam, 0 }, 14164 { WM_GETTEXT, sent|defwinproc|optional }, 14165 { WM_ACTIVATE, sent|wparam, 0 }, 14166 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 14167 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 14168 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, 14169 { WM_NCPAINT, sent|optional }, 14170 { WM_GETTEXT, sent|defwinproc|optional }, 14171 { WM_ERASEBKGND, sent|optional }, 14172 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 14173 { WM_NCACTIVATE, sent|wparam, 1 }, 14174 { WM_GETTEXT, sent|defwinproc|optional }, 14175 { WM_ACTIVATE, sent|wparam, 1 }, 14176 { HCBT_SETFOCUS, hook }, 14177 { WM_KILLFOCUS, sent|defwinproc }, 14178 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 }, 14179 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 14180 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, 14181 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 14182 { WM_SETFOCUS, sent|defwinproc }, 14183 { WM_GETTEXT, sent|optional }, 14184 { 0 } 14185 }; 14186 14187 /* SetActiveWindow( hwnd ) hwnd not visible */ 14188 static const struct message SetActiveWindowSeq3[] = 14189 { 14190 { HCBT_ACTIVATE, hook }, 14191 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 14192 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, 14193 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE }, 14194 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOACTIVATE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 14195 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 14196 { WM_ACTIVATEAPP, sent|wparam, 1 }, 14197 { WM_ACTIVATEAPP, sent|wparam, 1 }, 14198 { WM_NCACTIVATE, sent|wparam, 1 }, 14199 { WM_ACTIVATE, sent|wparam, 1 }, 14200 { HCBT_SETFOCUS, hook }, 14201 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 14202 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 14203 { WM_SETFOCUS, sent|defwinproc }, 14204 { 0 } 14205 }; 14206 /* SetActiveWindow( popup ) hwnd not visible, popup not visible */ 14207 static const struct message SetActiveWindowSeq4[] = 14208 { 14209 { HCBT_ACTIVATE, hook }, 14210 { WM_NCACTIVATE, sent|wparam, 0 }, 14211 { WM_GETTEXT, sent|defwinproc|optional }, 14212 { WM_ACTIVATE, sent|wparam, 0 }, 14213 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, 14214 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE }, 14215 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, 14216 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 14217 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 14218 { WM_NCACTIVATE, sent|wparam, 1 }, 14219 { WM_GETTEXT, sent|defwinproc|optional }, 14220 { WM_ACTIVATE, sent|wparam, 1 }, 14221 { HCBT_SETFOCUS, hook }, 14222 { WM_KILLFOCUS, sent|defwinproc }, 14223 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 }, 14224 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 14225 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, 14226 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, 14227 { WM_SETFOCUS, sent|defwinproc }, 14228 { 0 } 14229 }; 14230 14231 14232 static void test_SetActiveWindow(void) 14233 { 14234 HWND hwnd, popup, ret; 14235 14236 hwnd = CreateWindowExA(0, "TestWindowClass", "Test SetActiveWindow", 14237 WS_OVERLAPPEDWINDOW | WS_VISIBLE, 14238 100, 100, 200, 200, 0, 0, 0, NULL); 14239 14240 popup = CreateWindowExA(0, "TestWindowClass", "Test SetActiveWindow", 14241 WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_POPUP, 14242 100, 100, 200, 200, hwnd, 0, 0, NULL); 14243 14244 ok(hwnd != 0, "Failed to create overlapped window\n"); 14245 ok(popup != 0, "Failed to create popup window\n"); 14246 SetForegroundWindow( popup ); 14247 flush_sequence(); 14248 14249 trace("SetActiveWindow(0)\n"); 14250 ret = SetActiveWindow(0); 14251 ok( ret == popup, "Failed to SetActiveWindow(0)\n"); 14252 ok_sequence(SetActiveWindowSeq0, "SetActiveWindow(0)", FALSE); 14253 flush_sequence(); 14254 14255 trace("SetActiveWindow(hwnd), hwnd visible\n"); 14256 ret = SetActiveWindow(hwnd); 14257 if (ret == hwnd) ok_sequence(SetActiveWindowSeq1, "SetActiveWindow(hwnd), hwnd visible", TRUE); 14258 flush_sequence(); 14259 14260 trace("SetActiveWindow(popup), hwnd visible, popup visible\n"); 14261 ret = SetActiveWindow(popup); 14262 ok( ret == hwnd, "Failed to SetActiveWindow(popup), popup visible\n"); 14263 ok_sequence(SetActiveWindowSeq2, "SetActiveWindow(popup), hwnd visible, popup visible", FALSE); 14264 flush_sequence(); 14265 14266 ShowWindow(hwnd, SW_HIDE); 14267 ShowWindow(popup, SW_HIDE); 14268 flush_sequence(); 14269 14270 trace("SetActiveWindow(hwnd), hwnd not visible\n"); 14271 ret = SetActiveWindow(hwnd); 14272 ok( ret == NULL, "SetActiveWindow(hwnd), hwnd not visible, previous is %p\n", ret ); 14273 ok_sequence(SetActiveWindowSeq3, "SetActiveWindow(hwnd), hwnd not visible", TRUE); 14274 flush_sequence(); 14275 14276 trace("SetActiveWindow(popup), hwnd not visible, popup not visible\n"); 14277 ret = SetActiveWindow(popup); 14278 ok( ret == hwnd, "Failed to SetActiveWindow(popup)\n"); 14279 ok_sequence(SetActiveWindowSeq4, "SetActiveWindow(popup), hwnd not visible, popup not visible", TRUE); 14280 flush_sequence(); 14281 14282 trace("done\n"); 14283 14284 DestroyWindow(hwnd); 14285 } 14286 14287 static const struct message SetForegroundWindowSeq[] = 14288 { 14289 { WM_NCACTIVATE, sent|wparam, 0 }, 14290 { WM_GETTEXT, sent|defwinproc|optional }, 14291 { WM_ACTIVATE, sent|wparam, 0 }, 14292 { WM_ACTIVATEAPP, sent|wparam, 0 }, 14293 { WM_KILLFOCUS, sent }, 14294 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, 14295 { WM_IME_NOTIFY, sent|wparam|optional|defwinproc, 1 }, 14296 { 0 } 14297 }; 14298 14299 static void test_SetForegroundWindow(void) 14300 { 14301 HWND hwnd; 14302 14303 hwnd = CreateWindowExA(0, "TestWindowClass", "Test SetForegroundWindow", 14304 WS_OVERLAPPEDWINDOW | WS_VISIBLE, 14305 100, 100, 200, 200, 0, 0, 0, NULL); 14306 ok (hwnd != 0, "Failed to create overlapped window\n"); 14307 SetForegroundWindow( hwnd ); 14308 flush_sequence(); 14309 14310 trace("SetForegroundWindow( 0 )\n"); 14311 SetForegroundWindow( 0 ); 14312 ok_sequence(WmEmptySeq, "SetForegroundWindow( 0 ) away from foreground top level window", FALSE); 14313 trace("SetForegroundWindow( GetDesktopWindow() )\n"); 14314 SetForegroundWindow( GetDesktopWindow() ); 14315 ok_sequence(SetForegroundWindowSeq, "SetForegroundWindow( desktop ) away from " 14316 "foreground top level window", FALSE); 14317 trace("done\n"); 14318 14319 DestroyWindow(hwnd); 14320 } 14321 14322 static DWORD get_input_codepage( void ) 14323 { 14324 DWORD cp; 14325 int ret; 14326 HKL hkl = GetKeyboardLayout( 0 ); 14327 14328 ret = GetLocaleInfoW( LOWORD(hkl), LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER, 14329 (WCHAR *)&cp, sizeof(cp) / sizeof(WCHAR) ); 14330 if (!ret) cp = CP_ACP; 14331 return cp; 14332 } 14333 14334 static void test_dbcs_wm_char(void) 14335 { 14336 BYTE dbch[2]; 14337 WCHAR wch, bad_wch; 14338 HWND hwnd, hwnd2; 14339 MSG msg; 14340 DWORD time; 14341 POINT pt; 14342 DWORD_PTR res; 14343 CPINFOEXA cpinfo; 14344 UINT i, j, k; 14345 struct message wmCharSeq[2]; 14346 BOOL ret; 14347 DWORD cp = get_input_codepage(); 14348 14349 if (!pGetCPInfoExA) 14350 { 14351 win_skip("GetCPInfoExA is not available\n"); 14352 return; 14353 } 14354 14355 pGetCPInfoExA( cp, 0, &cpinfo ); 14356 if (cpinfo.MaxCharSize != 2) 14357 { 14358 skip( "Skipping DBCS WM_CHAR test in SBCS codepage '%s'\n", cpinfo.CodePageName ); 14359 return; 14360 } 14361 14362 dbch[0] = dbch[1] = 0; 14363 wch = 0; 14364 bad_wch = cpinfo.UnicodeDefaultChar; 14365 for (i = 0; !wch && i < MAX_LEADBYTES && cpinfo.LeadByte[i]; i += 2) 14366 for (j = cpinfo.LeadByte[i]; !wch && j <= cpinfo.LeadByte[i+1]; j++) 14367 for (k = 128; k <= 255; k++) 14368 { 14369 char str[2]; 14370 WCHAR wstr[2]; 14371 str[0] = j; 14372 str[1] = k; 14373 if (MultiByteToWideChar( cp, 0, str, 2, wstr, 2 ) == 1 && 14374 WideCharToMultiByte( cp, 0, wstr, 1, str, 2, NULL, NULL ) == 2 && 14375 (BYTE)str[0] == j && (BYTE)str[1] == k && 14376 HIBYTE(wstr[0]) && HIBYTE(wstr[0]) != 0xff) 14377 { 14378 dbch[0] = j; 14379 dbch[1] = k; 14380 wch = wstr[0]; 14381 break; 14382 } 14383 } 14384 14385 if (!wch) 14386 { 14387 skip( "Skipping DBCS WM_CHAR test, no appropriate char found\n" ); 14388 return; 14389 } 14390 trace( "using dbcs char %02x,%02x wchar %04x bad wchar %04x codepage '%s'\n", 14391 dbch[0], dbch[1], wch, bad_wch, cpinfo.CodePageName ); 14392 14393 hwnd = CreateWindowExW(0, testWindowClassW, NULL, 14394 WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, 0, 0, 0, NULL); 14395 hwnd2 = CreateWindowExW(0, testWindowClassW, NULL, 14396 WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, 0, 0, 0, NULL); 14397 ok (hwnd != 0, "Failed to create overlapped window\n"); 14398 ok (hwnd2 != 0, "Failed to create overlapped window\n"); 14399 flush_sequence(); 14400 14401 memset( wmCharSeq, 0, sizeof(wmCharSeq) ); 14402 wmCharSeq[0].message = WM_CHAR; 14403 wmCharSeq[0].flags = sent|wparam; 14404 wmCharSeq[0].wParam = wch; 14405 14406 /* posted message */ 14407 PostMessageA( hwnd, WM_CHAR, dbch[0], 0 ); 14408 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14409 ok( !ret, "got message %x\n", msg.message ); 14410 PostMessageA( hwnd, WM_CHAR, dbch[1], 0 ); 14411 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14412 ok( ret, "no message\n" ); 14413 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14414 ok( msg.wParam == wch, "bad wparam %lx/%x\n", msg.wParam, wch ); 14415 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14416 ok( !ret, "got message %x\n", msg.message ); 14417 14418 /* posted thread message */ 14419 PostThreadMessageA( GetCurrentThreadId(), WM_CHAR, dbch[0], 0 ); 14420 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14421 ok( !ret, "got message %x\n", msg.message ); 14422 PostMessageA( hwnd, WM_CHAR, dbch[1], 0 ); 14423 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14424 ok( ret, "no message\n" ); 14425 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14426 ok( msg.wParam == wch, "bad wparam %lx/%x\n", msg.wParam, wch ); 14427 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14428 ok( !ret, "got message %x\n", msg.message ); 14429 14430 /* sent message */ 14431 flush_sequence(); 14432 SendMessageA( hwnd, WM_CHAR, dbch[0], 0 ); 14433 ok_sequence( WmEmptySeq, "no messages", FALSE ); 14434 SendMessageA( hwnd, WM_CHAR, dbch[1], 0 ); 14435 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14436 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14437 ok( !ret, "got message %x\n", msg.message ); 14438 14439 /* sent message with timeout */ 14440 flush_sequence(); 14441 SendMessageTimeoutA( hwnd, WM_CHAR, dbch[0], 0, SMTO_NORMAL, 0, &res ); 14442 ok_sequence( WmEmptySeq, "no messages", FALSE ); 14443 SendMessageTimeoutA( hwnd, WM_CHAR, dbch[1], 0, SMTO_NORMAL, 0, &res ); 14444 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14445 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14446 ok( !ret, "got message %x\n", msg.message ); 14447 14448 /* sent message with timeout and callback */ 14449 flush_sequence(); 14450 SendMessageTimeoutA( hwnd, WM_CHAR, dbch[0], 0, SMTO_NORMAL, 0, &res ); 14451 ok_sequence( WmEmptySeq, "no messages", FALSE ); 14452 SendMessageCallbackA( hwnd, WM_CHAR, dbch[1], 0, NULL, 0 ); 14453 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14454 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14455 ok( !ret, "got message %x\n", msg.message ); 14456 14457 /* sent message with callback */ 14458 flush_sequence(); 14459 SendNotifyMessageA( hwnd, WM_CHAR, dbch[0], 0 ); 14460 ok_sequence( WmEmptySeq, "no messages", FALSE ); 14461 SendMessageCallbackA( hwnd, WM_CHAR, dbch[1], 0, NULL, 0 ); 14462 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14463 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14464 ok( !ret, "got message %x\n", msg.message ); 14465 14466 /* direct window proc call */ 14467 flush_sequence(); 14468 CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ), hwnd, WM_CHAR, dbch[0], 0 ); 14469 ok_sequence( WmEmptySeq, "no messages", FALSE ); 14470 CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ), hwnd, WM_CHAR, dbch[1], 0 ); 14471 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14472 14473 /* dispatch message */ 14474 msg.hwnd = hwnd; 14475 msg.message = WM_CHAR; 14476 msg.wParam = dbch[0]; 14477 msg.lParam = 0; 14478 DispatchMessageA( &msg ); 14479 ok_sequence( WmEmptySeq, "no messages", FALSE ); 14480 msg.wParam = dbch[1]; 14481 DispatchMessageA( &msg ); 14482 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14483 14484 /* window handle is irrelevant */ 14485 flush_sequence(); 14486 SendMessageA( hwnd2, WM_CHAR, dbch[0], 0 ); 14487 ok_sequence( WmEmptySeq, "no messages", FALSE ); 14488 SendMessageA( hwnd, WM_CHAR, dbch[1], 0 ); 14489 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14490 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14491 ok( !ret, "got message %x\n", msg.message ); 14492 14493 /* interleaved post and send */ 14494 flush_sequence(); 14495 PostMessageA( hwnd2, WM_CHAR, dbch[0], 0 ); 14496 SendMessageA( hwnd2, WM_CHAR, dbch[0], 0 ); 14497 ok_sequence( WmEmptySeq, "no messages", FALSE ); 14498 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14499 ok( !ret, "got message %x\n", msg.message ); 14500 PostMessageA( hwnd, WM_CHAR, dbch[1], 0 ); 14501 ok_sequence( WmEmptySeq, "no messages", FALSE ); 14502 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14503 ok( ret, "no message\n" ); 14504 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14505 ok( msg.wParam == wch, "bad wparam %lx/%x\n", msg.wParam, wch ); 14506 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14507 ok( !ret, "got message %x\n", msg.message ); 14508 SendMessageA( hwnd, WM_CHAR, dbch[1], 0 ); 14509 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14510 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14511 ok( !ret, "got message %x\n", msg.message ); 14512 14513 /* interleaved sent message and winproc */ 14514 flush_sequence(); 14515 SendMessageA( hwnd, WM_CHAR, dbch[0], 0 ); 14516 CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ), hwnd, WM_CHAR, dbch[0], 0 ); 14517 ok_sequence( WmEmptySeq, "no messages", FALSE ); 14518 SendMessageA( hwnd, WM_CHAR, dbch[1], 0 ); 14519 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14520 CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ), hwnd, WM_CHAR, dbch[1], 0 ); 14521 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14522 14523 /* interleaved winproc and dispatch */ 14524 msg.hwnd = hwnd; 14525 msg.message = WM_CHAR; 14526 msg.wParam = dbch[0]; 14527 msg.lParam = 0; 14528 CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ), hwnd, WM_CHAR, dbch[0], 0 ); 14529 DispatchMessageA( &msg ); 14530 ok_sequence( WmEmptySeq, "no messages", FALSE ); 14531 msg.wParam = dbch[1]; 14532 DispatchMessageA( &msg ); 14533 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14534 CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ), hwnd, WM_CHAR, dbch[1], 0 ); 14535 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14536 14537 /* interleaved sends */ 14538 flush_sequence(); 14539 SendMessageA( hwnd, WM_CHAR, dbch[0], 0 ); 14540 SendMessageCallbackA( hwnd, WM_CHAR, dbch[0], 0, NULL, 0 ); 14541 ok_sequence( WmEmptySeq, "no messages", FALSE ); 14542 SendMessageTimeoutA( hwnd, WM_CHAR, dbch[1], 0, SMTO_NORMAL, 0, &res ); 14543 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14544 SendMessageA( hwnd, WM_CHAR, dbch[1], 0 ); 14545 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14546 14547 /* dbcs WM_CHAR */ 14548 flush_sequence(); 14549 SendMessageA( hwnd2, WM_CHAR, (dbch[1] << 8) | dbch[0], 0 ); 14550 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); 14551 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14552 ok( !ret, "got message %x\n", msg.message ); 14553 14554 /* other char messages are not magic */ 14555 PostMessageA( hwnd, WM_SYSCHAR, dbch[0], 0 ); 14556 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14557 ok( ret, "no message\n" ); 14558 ok( msg.message == WM_SYSCHAR, "unexpected message %x\n", msg.message ); 14559 ok( msg.wParam == bad_wch, "bad wparam %lx/%x\n", msg.wParam, bad_wch ); 14560 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14561 ok( !ret, "got message %x\n", msg.message ); 14562 PostMessageA( hwnd, WM_DEADCHAR, dbch[0], 0 ); 14563 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14564 ok( ret, "no message\n" ); 14565 ok( msg.message == WM_DEADCHAR, "unexpected message %x\n", msg.message ); 14566 ok( msg.wParam == bad_wch, "bad wparam %lx/%x\n", msg.wParam, bad_wch ); 14567 ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); 14568 ok( !ret, "got message %x\n", msg.message ); 14569 14570 /* test retrieving messages */ 14571 14572 PostMessageW( hwnd, WM_CHAR, wch, 0 ); 14573 ret = PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ); 14574 ok( ret, "no message\n" ); 14575 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14576 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14577 ok( msg.wParam == dbch[0], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); 14578 ret = PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ); 14579 ok( ret, "no message\n" ); 14580 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14581 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14582 ok( msg.wParam == dbch[1], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); 14583 ret = PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ); 14584 ok( !ret, "got message %x\n", msg.message ); 14585 14586 /* message filters */ 14587 PostMessageW( hwnd, WM_CHAR, wch, 0 ); 14588 ret = PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ); 14589 ok( ret, "no message\n" ); 14590 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14591 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14592 ok( msg.wParam == dbch[0], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); 14593 /* message id is filtered, hwnd is not */ 14594 ret = PeekMessageA( &msg, hwnd, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ); 14595 ok( !ret, "no message\n" ); 14596 ret = PeekMessageA( &msg, hwnd2, 0, 0, PM_REMOVE ); 14597 ok( ret, "no message\n" ); 14598 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14599 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14600 ok( msg.wParam == dbch[1], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); 14601 ret = PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ); 14602 ok( !ret, "got message %x\n", msg.message ); 14603 14604 /* mixing GetMessage and PostMessage */ 14605 PostMessageW( hwnd, WM_CHAR, wch, 0xbeef ); 14606 ok( GetMessageA( &msg, hwnd, 0, 0 ), "no message\n" ); 14607 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14608 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14609 ok( msg.wParam == dbch[0], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); 14610 ok( msg.lParam == 0xbeef, "bad lparam %lx\n", msg.lParam ); 14611 time = msg.time; 14612 pt = msg.pt; 14613 ok( time - GetTickCount() <= 100, "bad time %x\n", msg.time ); 14614 ret = PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ); 14615 ok( ret, "no message\n" ); 14616 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14617 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14618 ok( msg.wParam == dbch[1], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); 14619 ok( msg.lParam == 0xbeef, "bad lparam %lx\n", msg.lParam ); 14620 ok( msg.time == time, "bad time %x/%x\n", msg.time, time ); 14621 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 ); 14622 ret = PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ); 14623 ok( !ret, "got message %x\n", msg.message ); 14624 14625 /* without PM_REMOVE */ 14626 PostMessageW( hwnd, WM_CHAR, wch, 0 ); 14627 ret = PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ); 14628 ok( ret, "no message\n" ); 14629 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14630 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14631 ok( msg.wParam == dbch[0], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); 14632 ret = PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ); 14633 ok( ret, "no message\n" ); 14634 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14635 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14636 ok( msg.wParam == dbch[0], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); 14637 ret = PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ); 14638 ok( ret, "no message\n" ); 14639 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14640 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14641 ok( msg.wParam == dbch[1], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); 14642 ret = PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ); 14643 ok( ret, "no message\n" ); 14644 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14645 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14646 ok( msg.wParam == dbch[1], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); 14647 ret = PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ); 14648 ok( !ret, "got message %x\n", msg.message ); 14649 14650 DestroyWindow(hwnd); 14651 DestroyWindow(hwnd2); 14652 } 14653 14654 static void test_unicode_wm_char(void) 14655 { 14656 HWND hwnd; 14657 MSG msg; 14658 struct message seq[2]; 14659 HKL hkl_orig, hkl_greek; 14660 DWORD cp; 14661 LCID thread_locale; 14662 14663 hkl_orig = GetKeyboardLayout( 0 ); 14664 GetLocaleInfoW( LOWORD( hkl_orig ), LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER, (WCHAR*)&cp, sizeof(cp) / sizeof(WCHAR) ); 14665 if (cp != 1252) 14666 { 14667 skip( "Default codepage %d\n", cp ); 14668 return; 14669 } 14670 14671 hkl_greek = LoadKeyboardLayoutA( "00000408", 0 ); 14672 if (!hkl_greek || hkl_greek == hkl_orig /* win2k */) 14673 { 14674 skip( "Unable to load Greek keyboard layout\n" ); 14675 return; 14676 } 14677 14678 hwnd = CreateWindowExW( 0, testWindowClassW, NULL, WS_OVERLAPPEDWINDOW, 14679 100, 100, 200, 200, 0, 0, 0, NULL ); 14680 flush_sequence(); 14681 14682 PostMessageW( hwnd, WM_CHAR, 0x3b1, 0 ); 14683 14684 while (GetMessageW( &msg, hwnd, 0, 0 )) 14685 { 14686 if (!ignore_message( msg.message )) break; 14687 } 14688 14689 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14690 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14691 ok( msg.wParam == 0x3b1, "bad wparam %lx\n", msg.wParam ); 14692 ok( msg.lParam == 0, "bad lparam %lx\n", msg.lParam ); 14693 14694 DispatchMessageW( &msg ); 14695 14696 memset( seq, 0, sizeof(seq) ); 14697 seq[0].message = WM_CHAR; 14698 seq[0].flags = sent|wparam; 14699 seq[0].wParam = 0x3b1; 14700 14701 ok_sequence( seq, "unicode WM_CHAR", FALSE ); 14702 14703 flush_sequence(); 14704 14705 /* greek alpha -> 'a' in cp1252 */ 14706 PostMessageW( hwnd, WM_CHAR, 0x3b1, 0 ); 14707 14708 ok( GetMessageA( &msg, hwnd, 0, 0 ), "no message\n" ); 14709 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14710 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14711 ok( msg.wParam == 0x61, "bad wparam %lx\n", msg.wParam ); 14712 ok( msg.lParam == 0, "bad lparam %lx\n", msg.lParam ); 14713 14714 DispatchMessageA( &msg ); 14715 14716 seq[0].wParam = 0x61; 14717 ok_sequence( seq, "unicode WM_CHAR", FALSE ); 14718 14719 thread_locale = GetThreadLocale(); 14720 ActivateKeyboardLayout( hkl_greek, 0 ); 14721 ok( GetThreadLocale() == thread_locale, "locale changed from %08x to %08x\n", 14722 thread_locale, GetThreadLocale() ); 14723 14724 flush_sequence(); 14725 14726 /* greek alpha -> 0xe1 in cp1253 */ 14727 PostMessageW( hwnd, WM_CHAR, 0x3b1, 0 ); 14728 14729 ok( GetMessageA( &msg, hwnd, 0, 0 ), "no message\n" ); 14730 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); 14731 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); 14732 ok( msg.wParam == 0xe1, "bad wparam %lx\n", msg.wParam ); 14733 ok( msg.lParam == 0, "bad lparam %lx\n", msg.lParam ); 14734 14735 DispatchMessageA( &msg ); 14736 14737 seq[0].wParam = 0x3b1; 14738 ok_sequence( seq, "unicode WM_CHAR", FALSE ); 14739 14740 DestroyWindow( hwnd ); 14741 ActivateKeyboardLayout( hkl_orig, 0 ); 14742 UnloadKeyboardLayout( hkl_greek ); 14743 } 14744 14745 #define ID_LISTBOX 0x000f 14746 14747 static const struct message wm_lb_setcursel_0[] = 14748 { 14749 { LB_SETCURSEL, sent|wparam|lparam, 0, 0 }, 14750 { WM_CTLCOLORLISTBOX, sent|parent }, 14751 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000120f2 }, 14752 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 1 }, 14753 { EVENT_OBJECT_SELECTION, winevent_hook|wparam|lparam, OBJID_CLIENT, 1 }, 14754 { 0 } 14755 }; 14756 static const struct message wm_lb_setcursel_1[] = 14757 { 14758 { LB_SETCURSEL, sent|wparam|lparam, 1, 0 }, 14759 { WM_CTLCOLORLISTBOX, sent|parent }, 14760 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000020f2 }, 14761 { WM_CTLCOLORLISTBOX, sent|parent }, 14762 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000121f2 }, 14763 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 2 }, 14764 { EVENT_OBJECT_SELECTION, winevent_hook|wparam|lparam, OBJID_CLIENT, 2 }, 14765 { 0 } 14766 }; 14767 static const struct message wm_lb_setcursel_2[] = 14768 { 14769 { LB_SETCURSEL, sent|wparam|lparam, 2, 0 }, 14770 { WM_CTLCOLORLISTBOX, sent|parent }, 14771 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000021f2 }, 14772 { WM_CTLCOLORLISTBOX, sent|parent }, 14773 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000122f2 }, 14774 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 3 }, 14775 { EVENT_OBJECT_SELECTION, winevent_hook|wparam|lparam, OBJID_CLIENT, 3 }, 14776 { 0 } 14777 }; 14778 static const struct message wm_lb_click_0[] = 14779 { 14780 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, MAKELPARAM(1,1) }, 14781 { HCBT_SETFOCUS, hook }, 14782 { WM_KILLFOCUS, sent|parent }, 14783 { WM_IME_SETCONTEXT, sent|wparam|optional|parent, 0 }, 14784 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 14785 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 14786 { WM_SETFOCUS, sent|defwinproc }, 14787 14788 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x001142f2 }, 14789 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_LISTBOX, LBN_SETFOCUS) }, 14790 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 3 }, 14791 { WM_LBTRACKPOINT, sent|wparam|lparam|parent, 0, MAKELPARAM(1,1) }, 14792 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, 14793 14794 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000142f2 }, 14795 { WM_CTLCOLORLISTBOX, sent|parent }, 14796 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000022f2 }, 14797 { WM_CTLCOLORLISTBOX, sent|parent }, 14798 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000120f2 }, 14799 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x001140f2 }, 14800 14801 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 1 }, 14802 { EVENT_OBJECT_SELECTION, winevent_hook|wparam|lparam, OBJID_CLIENT, 1 }, 14803 14804 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 }, 14805 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, 14806 { WM_CAPTURECHANGED, sent|wparam|lparam|defwinproc, 0, 0 }, 14807 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_LISTBOX, LBN_SELCHANGE) }, 14808 { 0 } 14809 }; 14810 static const struct message wm_lb_deletestring[] = 14811 { 14812 { LB_DELETESTRING, sent|wparam|lparam, 0, 0 }, 14813 { WM_DELETEITEM, sent|wparam|parent|optional, ID_LISTBOX, 0 }, 14814 { WM_DRAWITEM, sent|wparam|parent|optional, ID_LISTBOX }, 14815 { WM_DRAWITEM, sent|wparam|parent|optional, ID_LISTBOX }, 14816 { 0 } 14817 }; 14818 static const struct message wm_lb_deletestring_reset[] = 14819 { 14820 { LB_DELETESTRING, sent|wparam|lparam, 0, 0 }, 14821 { LB_RESETCONTENT, sent|wparam|lparam|defwinproc|optional, 0, 0 }, 14822 { WM_DELETEITEM, sent|wparam|parent|optional, ID_LISTBOX, 0 }, 14823 { WM_DRAWITEM, sent|wparam|parent|optional, ID_LISTBOX }, 14824 { WM_DRAWITEM, sent|wparam|parent|optional, ID_LISTBOX }, 14825 { 0 } 14826 }; 14827 static const struct message wm_lb_addstring[] = 14828 { 14829 { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ef }, 14830 { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ed }, 14831 { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ee }, 14832 { 0 } 14833 }; 14834 static const struct message wm_lb_addstring_ownerdraw[] = 14835 { 14836 { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ed }, 14837 { WM_MEASUREITEM, sent|wparam|lparam|parent, 0xf0f2, 0xf30604ed }, 14838 { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ee }, 14839 { WM_MEASUREITEM, sent|wparam|lparam|parent, 0xf1f2, 0xf30604ee }, 14840 { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ef }, 14841 { WM_MEASUREITEM, sent|wparam|lparam|parent, 0xf2f2, 0xf30604ef }, 14842 { 0 } 14843 }; 14844 static const struct message wm_lb_addstring_sort_ownerdraw[] = 14845 { 14846 { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ed }, 14847 { WM_MEASUREITEM, sent|wparam|lparam|parent, 0xf0f2, 0xf30604ed }, 14848 { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ee }, 14849 { WM_COMPAREITEM, sent|wparam|lparam|parent, 0xf30604ed, 0xf30604ee }, 14850 { WM_MEASUREITEM, sent|wparam|lparam|parent, 0xf1f2, 0xf30604ee }, 14851 { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ef }, 14852 { WM_COMPAREITEM, sent|wparam|lparam|parent, 0xf30604ed, 0xf30604ef }, 14853 { WM_COMPAREITEM, sent|wparam|lparam|parent, 0xf30604ee, 0xf30604ef }, 14854 { WM_MEASUREITEM, sent|wparam|lparam|parent, 0xf2f2, 0xf30604ef }, 14855 { 0 } 14856 }; 14857 14858 #define check_lb_state(a1, a2, a3, a4, a5) check_lb_state_dbg(a1, a2, a3, a4, a5, __LINE__) 14859 14860 static LRESULT (WINAPI *listbox_orig_proc)(HWND, UINT, WPARAM, LPARAM); 14861 14862 static LRESULT WINAPI listbox_hook_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) 14863 { 14864 static LONG defwndproc_counter = 0; 14865 LRESULT ret; 14866 struct recvd_message msg; 14867 14868 /* do not log painting messages */ 14869 if (message != WM_PAINT && 14870 message != WM_NCPAINT && 14871 message != WM_SYNCPAINT && 14872 message != WM_ERASEBKGND && 14873 message != WM_NCHITTEST && 14874 message != WM_GETTEXT && 14875 !ignore_message( message )) 14876 { 14877 msg.hwnd = hwnd; 14878 msg.message = message; 14879 msg.flags = sent|wparam|lparam; 14880 if (defwndproc_counter) msg.flags |= defwinproc; 14881 msg.wParam = wp; 14882 if (message == LB_ADDSTRING) 14883 msg.lParam = lp ? hash_Ly((const char *)lp) : 0; 14884 else 14885 msg.lParam = lp; 14886 msg.descr = "listbox"; 14887 add_message(&msg); 14888 } 14889 14890 defwndproc_counter++; 14891 ret = CallWindowProcA(listbox_orig_proc, hwnd, message, wp, lp); 14892 defwndproc_counter--; 14893 14894 return ret; 14895 } 14896 14897 static void check_lb_state_dbg(HWND listbox, int count, int cur_sel, 14898 int caret_index, int top_index, int line) 14899 { 14900 LRESULT ret; 14901 14902 /* calling an orig proc helps to avoid unnecessary message logging */ 14903 ret = CallWindowProcA(listbox_orig_proc, listbox, LB_GETCOUNT, 0, 0); 14904 ok_(__FILE__, line)(ret == count, "expected count %d, got %ld\n", count, ret); 14905 ret = CallWindowProcA(listbox_orig_proc, listbox, LB_GETCURSEL, 0, 0); 14906 ok_(__FILE__, line)(ret == cur_sel, "expected cur sel %d, got %ld\n", cur_sel, ret); 14907 ret = CallWindowProcA(listbox_orig_proc, listbox, LB_GETCARETINDEX, 0, 0); 14908 ok_(__FILE__, line)(ret == caret_index || 14909 broken(cur_sel == -1 && caret_index == 0 && ret == -1), /* nt4 */ 14910 "expected caret index %d, got %ld\n", caret_index, ret); 14911 ret = CallWindowProcA(listbox_orig_proc, listbox, LB_GETTOPINDEX, 0, 0); 14912 ok_(__FILE__, line)(ret == top_index, "expected top index %d, got %ld\n", top_index, ret); 14913 } 14914 14915 static void test_listbox_messages(void) 14916 { 14917 HWND parent, listbox; 14918 LRESULT ret; 14919 14920 parent = CreateWindowExA(0, "TestParentClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 14921 100, 100, 200, 200, 0, 0, 0, NULL); 14922 /* with LBS_HASSTRINGS */ 14923 listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, "ListBox", NULL, 14924 WS_CHILD | LBS_NOTIFY | LBS_OWNERDRAWVARIABLE | LBS_HASSTRINGS | WS_VISIBLE, 14925 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL); 14926 listbox_orig_proc = (WNDPROC)SetWindowLongPtrA(listbox, GWLP_WNDPROC, (ULONG_PTR)listbox_hook_proc); 14927 14928 check_lb_state(listbox, 0, LB_ERR, 0, 0); 14929 14930 flush_sequence(); 14931 14932 log_all_parent_messages++; 14933 14934 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0"); 14935 ok(ret == 0, "expected 0, got %ld\n", ret); 14936 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1"); 14937 ok(ret == 1, "expected 1, got %ld\n", ret); 14938 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2"); 14939 ok(ret == 2, "expected 2, got %ld\n", ret); 14940 14941 ok_sequence(wm_lb_addstring_ownerdraw, "LB_ADDSTRING", FALSE); 14942 check_lb_state(listbox, 3, LB_ERR, 0, 0); 14943 14944 flush_sequence(); 14945 14946 trace("selecting item 0\n"); 14947 ret = SendMessageA(listbox, LB_SETCURSEL, 0, 0); 14948 ok(ret == 0, "expected 0, got %ld\n", ret); 14949 ok_sequence(wm_lb_setcursel_0, "LB_SETCURSEL 0", FALSE ); 14950 check_lb_state(listbox, 3, 0, 0, 0); 14951 flush_sequence(); 14952 14953 trace("selecting item 1\n"); 14954 ret = SendMessageA(listbox, LB_SETCURSEL, 1, 0); 14955 ok(ret == 1, "expected 1, got %ld\n", ret); 14956 ok_sequence(wm_lb_setcursel_1, "LB_SETCURSEL 1", FALSE ); 14957 check_lb_state(listbox, 3, 1, 1, 0); 14958 14959 trace("selecting item 2\n"); 14960 ret = SendMessageA(listbox, LB_SETCURSEL, 2, 0); 14961 ok(ret == 2, "expected 2, got %ld\n", ret); 14962 ok_sequence(wm_lb_setcursel_2, "LB_SETCURSEL 2", FALSE ); 14963 check_lb_state(listbox, 3, 2, 2, 0); 14964 14965 trace("clicking on item 0\n"); 14966 ret = SendMessageA(listbox, WM_LBUTTONDOWN, 0, MAKELPARAM(1, 1)); 14967 ok(ret == LB_OKAY, "expected LB_OKAY, got %ld\n", ret); 14968 ret = SendMessageA(listbox, WM_LBUTTONUP, 0, 0); 14969 ok(ret == LB_OKAY, "expected LB_OKAY, got %ld\n", ret); 14970 ok_sequence(wm_lb_click_0, "WM_LBUTTONDOWN 0", FALSE ); 14971 check_lb_state(listbox, 3, 0, 0, 0); 14972 flush_sequence(); 14973 14974 trace("deleting item 0\n"); 14975 ret = SendMessageA(listbox, LB_DELETESTRING, 0, 0); 14976 ok(ret == 2, "expected 2, got %ld\n", ret); 14977 ok_sequence(wm_lb_deletestring, "LB_DELETESTRING 0", FALSE ); 14978 check_lb_state(listbox, 2, -1, 0, 0); 14979 flush_sequence(); 14980 14981 trace("deleting item 0\n"); 14982 ret = SendMessageA(listbox, LB_DELETESTRING, 0, 0); 14983 ok(ret == 1, "expected 1, got %ld\n", ret); 14984 ok_sequence(wm_lb_deletestring, "LB_DELETESTRING 0", FALSE ); 14985 check_lb_state(listbox, 1, -1, 0, 0); 14986 flush_sequence(); 14987 14988 trace("deleting item 0\n"); 14989 ret = SendMessageA(listbox, LB_DELETESTRING, 0, 0); 14990 ok(ret == 0, "expected 0, got %ld\n", ret); 14991 ok_sequence(wm_lb_deletestring_reset, "LB_DELETESTRING 0", FALSE ); 14992 check_lb_state(listbox, 0, -1, 0, 0); 14993 flush_sequence(); 14994 14995 trace("deleting item 0\n"); 14996 ret = SendMessageA(listbox, LB_DELETESTRING, 0, 0); 14997 ok(ret == LB_ERR, "expected LB_ERR, got %ld\n", ret); 14998 check_lb_state(listbox, 0, -1, 0, 0); 14999 flush_sequence(); 15000 15001 log_all_parent_messages--; 15002 15003 DestroyWindow(listbox); 15004 15005 /* with LBS_SORT and without LBS_HASSTRINGS */ 15006 listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, "ListBox", NULL, 15007 WS_CHILD | LBS_NOTIFY | LBS_OWNERDRAWVARIABLE | LBS_SORT | WS_VISIBLE, 15008 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL); 15009 listbox_orig_proc = (WNDPROC)SetWindowLongPtrA(listbox, GWLP_WNDPROC, (ULONG_PTR)listbox_hook_proc); 15010 15011 check_lb_state(listbox, 0, LB_ERR, 0, 0); 15012 15013 flush_sequence(); 15014 15015 log_all_parent_messages++; 15016 15017 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0"); 15018 ok(ret == 0, "expected 0, got %ld\n", ret); 15019 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1"); 15020 ok(ret == 1, "expected 1, got %ld\n", ret); 15021 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2"); 15022 ok(ret == 2, "expected 2, got %ld\n", ret); 15023 15024 ok_sequence(wm_lb_addstring_sort_ownerdraw, "LB_ADDSTRING", FALSE); 15025 check_lb_state(listbox, 3, LB_ERR, 0, 0); 15026 15027 log_all_parent_messages--; 15028 15029 DestroyWindow(listbox); 15030 15031 /* with LBS_HASSTRINGS */ 15032 listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, "ListBox", NULL, 15033 WS_CHILD | LBS_NOTIFY | LBS_HASSTRINGS | WS_VISIBLE, 15034 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL); 15035 listbox_orig_proc = (WNDPROC)SetWindowLongPtrA(listbox, GWLP_WNDPROC, (ULONG_PTR)listbox_hook_proc); 15036 15037 check_lb_state(listbox, 0, LB_ERR, 0, 0); 15038 15039 flush_sequence(); 15040 15041 log_all_parent_messages++; 15042 15043 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2"); 15044 ok(ret == 0, "expected 0, got %ld\n", ret); 15045 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0"); 15046 ok(ret == 1, "expected 1, got %ld\n", ret); 15047 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1"); 15048 ok(ret == 2, "expected 2, got %ld\n", ret); 15049 15050 ok_sequence(wm_lb_addstring, "LB_ADDSTRING", FALSE); 15051 check_lb_state(listbox, 3, LB_ERR, 0, 0); 15052 15053 log_all_parent_messages--; 15054 15055 DestroyWindow(listbox); 15056 15057 /* with LBS_HASSTRINGS and LBS_SORT */ 15058 listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, "ListBox", NULL, 15059 WS_CHILD | LBS_NOTIFY | LBS_HASSTRINGS | LBS_SORT | WS_VISIBLE, 15060 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL); 15061 listbox_orig_proc = (WNDPROC)SetWindowLongPtrA(listbox, GWLP_WNDPROC, (ULONG_PTR)listbox_hook_proc); 15062 15063 check_lb_state(listbox, 0, LB_ERR, 0, 0); 15064 15065 flush_sequence(); 15066 15067 log_all_parent_messages++; 15068 15069 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2"); 15070 ok(ret == 0, "expected 0, got %ld\n", ret); 15071 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0"); 15072 ok(ret == 0, "expected 0, got %ld\n", ret); 15073 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1"); 15074 ok(ret == 1, "expected 1, got %ld\n", ret); 15075 15076 ok_sequence(wm_lb_addstring, "LB_ADDSTRING", FALSE); 15077 check_lb_state(listbox, 3, LB_ERR, 0, 0); 15078 15079 log_all_parent_messages--; 15080 15081 DestroyWindow(listbox); 15082 DestroyWindow(parent); 15083 } 15084 15085 /*************************** Menu test ******************************/ 15086 static const struct message wm_popup_menu_1[] = 15087 { 15088 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, 15089 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, 15090 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'E', 0x20000001 }, 15091 { WM_SYSKEYDOWN, sent|wparam|lparam, 'E', 0x20000001 }, 15092 { WM_SYSCHAR, sent|wparam|lparam, 'e', 0x20000001 }, 15093 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_KEYMENU, 'e' }, 15094 { WM_ENTERMENULOOP, sent|wparam|lparam, 0, 0 }, 15095 { WM_INITMENU, sent|lparam, 0, 0 }, 15096 { WM_MENUSELECT, sent|wparam, MAKEWPARAM(1,MF_HILITE|MF_POPUP) }, 15097 { WM_INITMENUPOPUP, sent|lparam, 0, 1 }, 15098 { HCBT_CREATEWND, hook|optional }, /* Win9x doesn't create a window */ 15099 { WM_MENUSELECT, sent|wparam, MAKEWPARAM(200,MF_HILITE) }, 15100 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'E', 0xf0000001 }, 15101 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xd0000001 }, 15102 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RETURN, 0x10000001, 0, 0x40000000 }, 15103 { HCBT_DESTROYWND, hook|optional }, /* Win9x doesn't create a window */ 15104 { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, 15105 { WM_MENUSELECT, sent|wparam|lparam, MAKEWPARAM(0,0xffff), 0 }, 15106 { WM_EXITMENULOOP, sent|wparam|lparam, 0, 0 }, 15107 { WM_MENUCOMMAND, sent }, /* |wparam, 200 - Win9x */ 15108 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RETURN, 0xc0000001 }, 15109 { WM_KEYUP, sent|wparam|lparam, VK_RETURN, 0xc0000001 }, 15110 { 0 } 15111 }; 15112 static const struct message wm_popup_menu_2[] = 15113 { 15114 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, 15115 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, 15116 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'F', 0x20000001 }, 15117 { WM_SYSKEYDOWN, sent|wparam|lparam, 'F', 0x20000001 }, 15118 { WM_SYSCHAR, sent|wparam|lparam, 'f', 0x20000001 }, 15119 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_KEYMENU, 'f' }, 15120 { WM_ENTERMENULOOP, sent|wparam|lparam, 0, 0 }, 15121 { WM_INITMENU, sent|lparam, 0, 0 }, 15122 { WM_MENUSELECT, sent|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) }, 15123 { WM_INITMENUPOPUP, sent|lparam, 0, 0 }, 15124 { WM_MENUSELECT, sent|wparam|optional, MAKEWPARAM(0,MF_HILITE|MF_POPUP) }, /* Win9x */ 15125 { WM_INITMENUPOPUP, sent|lparam|optional, 0, 0 }, /* Win9x */ 15126 { HCBT_CREATEWND, hook }, 15127 { WM_MENUSELECT, sent }, /*|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) - XP 15128 |wparam, MAKEWPARAM(100,MF_HILITE) - Win9x */ 15129 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'F', 0xf0000001 }, 15130 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xd0000001 }, 15131 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RIGHT, 0x10000001 }, 15132 { WM_INITMENUPOPUP, sent|lparam|optional, 0, 0 }, /* Win9x doesn't send it */ 15133 { HCBT_CREATEWND, hook|optional }, /* Win9x doesn't send it */ 15134 { WM_MENUSELECT, sent|wparam|optional, MAKEWPARAM(100,MF_HILITE) }, 15135 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RIGHT, 0xd0000001 }, 15136 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RETURN, 0x10000001 }, 15137 { HCBT_DESTROYWND, hook }, 15138 { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, 15139 { HCBT_DESTROYWND, hook|optional }, /* Win9x doesn't send it */ 15140 { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, 15141 { WM_MENUSELECT, sent|wparam|lparam, MAKEWPARAM(0,0xffff), 0 }, 15142 { WM_EXITMENULOOP, sent|wparam|lparam, 0, 0 }, 15143 { WM_MENUCOMMAND, sent }, /* |wparam, 100 - Win9x */ 15144 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RETURN, 0xc0000001 }, 15145 { WM_KEYUP, sent|wparam|lparam, VK_RETURN, 0xc0000001 }, 15146 { 0 } 15147 }; 15148 static const struct message wm_popup_menu_3[] = 15149 { 15150 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, 15151 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, 15152 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'F', 0x20000001 }, 15153 { WM_SYSKEYDOWN, sent|wparam|lparam, 'F', 0x20000001 }, 15154 { WM_SYSCHAR, sent|wparam|lparam, 'f', 0x20000001 }, 15155 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_KEYMENU, 'f' }, 15156 { WM_ENTERMENULOOP, sent|wparam|lparam, 0, 0 }, 15157 { WM_INITMENU, sent|lparam, 0, 0 }, 15158 { WM_MENUSELECT, sent|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) }, 15159 { WM_INITMENUPOPUP, sent|lparam, 0, 0 }, 15160 { WM_MENUSELECT, sent|wparam|optional, MAKEWPARAM(0,MF_HILITE|MF_POPUP) }, /* Win9x */ 15161 { WM_INITMENUPOPUP, sent|lparam|optional, 0, 0 }, /* Win9x */ 15162 { HCBT_CREATEWND, hook }, 15163 { WM_MENUSELECT, sent }, /*|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) - XP 15164 |wparam, MAKEWPARAM(100,MF_HILITE) - Win9x */ 15165 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'F', 0xf0000001 }, 15166 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xd0000001 }, 15167 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RIGHT, 0x10000001 }, 15168 { WM_INITMENUPOPUP, sent|lparam|optional, 0, 0 }, /* Win9x doesn't send it */ 15169 { HCBT_CREATEWND, hook|optional }, /* Win9x doesn't send it */ 15170 { WM_MENUSELECT, sent|wparam|optional, MAKEWPARAM(100,MF_HILITE) }, 15171 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RIGHT, 0xd0000001 }, 15172 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RETURN, 0x10000001 }, 15173 { HCBT_DESTROYWND, hook }, 15174 { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, 15175 { HCBT_DESTROYWND, hook|optional }, /* Win9x doesn't send it */ 15176 { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, 15177 { WM_MENUSELECT, sent|wparam|lparam, MAKEWPARAM(0,0xffff), 0 }, 15178 { WM_EXITMENULOOP, sent|wparam|lparam, 0, 0 }, 15179 { WM_COMMAND, sent|wparam|lparam, 100, 0 }, 15180 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RETURN, 0xc0000001 }, 15181 { WM_KEYUP, sent|wparam|lparam, VK_RETURN, 0xc0000001 }, 15182 { 0 } 15183 }; 15184 15185 static const struct message wm_single_menu_item[] = 15186 { 15187 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, 15188 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, 15189 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'Q', 0x20000001 }, 15190 { WM_SYSKEYDOWN, sent|wparam|lparam, 'Q', 0x20000001 }, 15191 { WM_SYSCHAR, sent|wparam|lparam, 'q', 0x20000001 }, 15192 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_KEYMENU, 'q' }, 15193 { WM_ENTERMENULOOP, sent|wparam|lparam, 0, 0 }, 15194 { WM_INITMENU, sent|lparam, 0, 0 }, 15195 { WM_MENUSELECT, sent|wparam|optional, MAKEWPARAM(300,MF_HILITE) }, 15196 { WM_MENUSELECT, sent|wparam|lparam, MAKEWPARAM(0,0xffff), 0 }, 15197 { WM_EXITMENULOOP, sent|wparam|lparam, 0, 0 }, 15198 { WM_MENUCOMMAND, sent }, 15199 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'Q', 0xe0000001 }, 15200 { WM_SYSKEYUP, sent|wparam|lparam, 'Q', 0xe0000001 }, 15201 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, 15202 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 }, 15203 15204 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_ESCAPE, 1 }, 15205 { WM_KEYDOWN, sent|wparam|lparam, VK_ESCAPE, 1 }, 15206 { WM_CHAR, sent|wparam|lparam, VK_ESCAPE, 0x00000001 }, 15207 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_ESCAPE, 0xc0000001 }, 15208 { WM_KEYUP, sent|wparam|lparam, VK_ESCAPE, 0xc0000001 }, 15209 { 0 } 15210 }; 15211 15212 static LRESULT WINAPI parent_menu_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) 15213 { 15214 if (message == WM_ENTERIDLE || 15215 message == WM_INITMENU || 15216 message == WM_INITMENUPOPUP || 15217 message == WM_MENUSELECT || 15218 message == WM_PARENTNOTIFY || 15219 message == WM_ENTERMENULOOP || 15220 message == WM_EXITMENULOOP || 15221 message == WM_UNINITMENUPOPUP || 15222 message == WM_KEYDOWN || 15223 message == WM_KEYUP || 15224 message == WM_CHAR || 15225 message == WM_SYSKEYDOWN || 15226 message == WM_SYSKEYUP || 15227 message == WM_SYSCHAR || 15228 message == WM_COMMAND || 15229 message == WM_MENUCOMMAND) 15230 { 15231 struct recvd_message msg; 15232 15233 msg.hwnd = hwnd; 15234 msg.message = message; 15235 msg.flags = sent|wparam|lparam; 15236 msg.wParam = wp; 15237 msg.lParam = lp; 15238 msg.descr = "parent_menu_proc"; 15239 add_message(&msg); 15240 } 15241 15242 return DefWindowProcA(hwnd, message, wp, lp); 15243 } 15244 15245 static void set_menu_style(HMENU hmenu, DWORD style) 15246 { 15247 MENUINFO mi; 15248 BOOL ret; 15249 15250 mi.cbSize = sizeof(mi); 15251 mi.fMask = MIM_STYLE; 15252 mi.dwStyle = style; 15253 SetLastError(0xdeadbeef); 15254 ret = pSetMenuInfo(hmenu, &mi); 15255 ok(ret, "SetMenuInfo error %u\n", GetLastError()); 15256 } 15257 15258 static DWORD get_menu_style(HMENU hmenu) 15259 { 15260 MENUINFO mi; 15261 BOOL ret; 15262 15263 mi.cbSize = sizeof(mi); 15264 mi.fMask = MIM_STYLE; 15265 mi.dwStyle = 0; 15266 SetLastError(0xdeadbeef); 15267 ret = pGetMenuInfo(hmenu, &mi); 15268 ok(ret, "GetMenuInfo error %u\n", GetLastError()); 15269 15270 return mi.dwStyle; 15271 } 15272 15273 static void test_menu_messages(void) 15274 { 15275 MSG msg; 15276 WNDCLASSA cls; 15277 HMENU hmenu, hmenu_popup; 15278 HWND hwnd; 15279 DWORD style; 15280 15281 if (!pGetMenuInfo || !pSetMenuInfo) 15282 { 15283 win_skip("GetMenuInfo and/or SetMenuInfo are not available\n"); 15284 return; 15285 } 15286 cls.style = 0; 15287 cls.lpfnWndProc = parent_menu_proc; 15288 cls.cbClsExtra = 0; 15289 cls.cbWndExtra = 0; 15290 cls.hInstance = GetModuleHandleA(0); 15291 cls.hIcon = 0; 15292 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 15293 cls.hbrBackground = GetStockObject(WHITE_BRUSH); 15294 cls.lpszMenuName = NULL; 15295 cls.lpszClassName = "TestMenuClass"; 15296 UnregisterClassA(cls.lpszClassName, cls.hInstance); 15297 if (!RegisterClassA(&cls)) assert(0); 15298 15299 SetLastError(0xdeadbeef); 15300 hwnd = CreateWindowExA(0, "TestMenuClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 15301 100, 100, 200, 200, 0, 0, 0, NULL); 15302 ok(hwnd != 0, "LoadMenuA error %u\n", GetLastError()); 15303 15304 SetLastError(0xdeadbeef); 15305 hmenu = LoadMenuA(GetModuleHandleA(NULL), MAKEINTRESOURCEA(1)); 15306 ok(hmenu != 0, "LoadMenuA error %u\n", GetLastError()); 15307 15308 SetMenu(hwnd, hmenu); 15309 SetForegroundWindow( hwnd ); 15310 flush_events(); 15311 15312 set_menu_style(hmenu, MNS_NOTIFYBYPOS); 15313 style = get_menu_style(hmenu); 15314 ok(style == MNS_NOTIFYBYPOS, "expected MNS_NOTIFYBYPOS, got %u\n", style); 15315 15316 hmenu_popup = GetSubMenu(hmenu, 0); 15317 ok(hmenu_popup != 0, "GetSubMenu returned 0 for submenu 0\n"); 15318 style = get_menu_style(hmenu_popup); 15319 ok(style == 0, "expected 0, got %u\n", style); 15320 15321 hmenu_popup = GetSubMenu(hmenu_popup, 0); 15322 ok(hmenu_popup != 0, "GetSubMenu returned 0 for submenu 0\n"); 15323 style = get_menu_style(hmenu_popup); 15324 ok(style == 0, "expected 0, got %u\n", style); 15325 15326 /* Alt+E, Enter */ 15327 trace("testing a popup menu command\n"); 15328 flush_sequence(); 15329 keybd_event(VK_MENU, 0, 0, 0); 15330 keybd_event('E', 0, 0, 0); 15331 keybd_event('E', 0, KEYEVENTF_KEYUP, 0); 15332 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); 15333 keybd_event(VK_RETURN, 0, 0, 0); 15334 keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0); 15335 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 15336 { 15337 TranslateMessage(&msg); 15338 DispatchMessageA(&msg); 15339 } 15340 if (!sequence_cnt) /* we didn't get any message */ 15341 { 15342 skip( "queuing key events not supported\n" ); 15343 goto done; 15344 } 15345 /* win98 queues only a WM_KEYUP and doesn't start menu tracking */ 15346 if (sequence[0].message == WM_KEYUP && sequence[0].wParam == VK_MENU) 15347 { 15348 win_skip( "menu tracking through VK_MENU not supported\n" ); 15349 goto done; 15350 } 15351 ok_sequence(wm_popup_menu_1, "popup menu command", FALSE); 15352 15353 /* Alt+F, Right, Enter */ 15354 trace("testing submenu of a popup menu command\n"); 15355 flush_sequence(); 15356 keybd_event(VK_MENU, 0, 0, 0); 15357 keybd_event('F', 0, 0, 0); 15358 keybd_event('F', 0, KEYEVENTF_KEYUP, 0); 15359 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); 15360 keybd_event(VK_RIGHT, 0, 0, 0); 15361 keybd_event(VK_RIGHT, 0, KEYEVENTF_KEYUP, 0); 15362 keybd_event(VK_RETURN, 0, 0, 0); 15363 keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0); 15364 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 15365 { 15366 TranslateMessage(&msg); 15367 DispatchMessageA(&msg); 15368 } 15369 ok_sequence(wm_popup_menu_2, "submenu of a popup menu command", FALSE); 15370 15371 trace("testing single menu item command\n"); 15372 flush_sequence(); 15373 keybd_event(VK_MENU, 0, 0, 0); 15374 keybd_event('Q', 0, 0, 0); 15375 keybd_event('Q', 0, KEYEVENTF_KEYUP, 0); 15376 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); 15377 keybd_event(VK_ESCAPE, 0, 0, 0); 15378 keybd_event(VK_ESCAPE, 0, KEYEVENTF_KEYUP, 0); 15379 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 15380 { 15381 TranslateMessage(&msg); 15382 DispatchMessageA(&msg); 15383 } 15384 ok_sequence(wm_single_menu_item, "single menu item command", FALSE); 15385 15386 set_menu_style(hmenu, 0); 15387 style = get_menu_style(hmenu); 15388 ok(style == 0, "expected 0, got %u\n", style); 15389 15390 hmenu_popup = GetSubMenu(hmenu, 0); 15391 ok(hmenu_popup != 0, "GetSubMenu returned 0 for submenu 0\n"); 15392 set_menu_style(hmenu_popup, MNS_NOTIFYBYPOS); 15393 style = get_menu_style(hmenu_popup); 15394 ok(style == MNS_NOTIFYBYPOS, "expected MNS_NOTIFYBYPOS, got %u\n", style); 15395 15396 hmenu_popup = GetSubMenu(hmenu_popup, 0); 15397 ok(hmenu_popup != 0, "GetSubMenu returned 0 for submenu 0\n"); 15398 style = get_menu_style(hmenu_popup); 15399 ok(style == 0, "expected 0, got %u\n", style); 15400 15401 /* Alt+F, Right, Enter */ 15402 trace("testing submenu of a popup menu command\n"); 15403 flush_sequence(); 15404 keybd_event(VK_MENU, 0, 0, 0); 15405 keybd_event('F', 0, 0, 0); 15406 keybd_event('F', 0, KEYEVENTF_KEYUP, 0); 15407 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); 15408 keybd_event(VK_RIGHT, 0, 0, 0); 15409 keybd_event(VK_RIGHT, 0, KEYEVENTF_KEYUP, 0); 15410 keybd_event(VK_RETURN, 0, 0, 0); 15411 keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0); 15412 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 15413 { 15414 TranslateMessage(&msg); 15415 DispatchMessageA(&msg); 15416 } 15417 ok_sequence(wm_popup_menu_3, "submenu of a popup menu command", FALSE); 15418 15419 done: 15420 DestroyWindow(hwnd); 15421 DestroyMenu(hmenu); 15422 } 15423 15424 15425 static void test_paintingloop(void) 15426 { 15427 HWND hwnd; 15428 15429 paint_loop_done = FALSE; 15430 hwnd = CreateWindowExA(0x0,"PaintLoopWindowClass", 15431 "PaintLoopWindowClass",WS_OVERLAPPEDWINDOW, 15432 100, 100, 100, 100, 0, 0, 0, NULL ); 15433 ok(hwnd != 0, "PaintLoop window error %u\n", GetLastError()); 15434 ShowWindow(hwnd,SW_NORMAL); 15435 SetFocus(hwnd); 15436 15437 while (!paint_loop_done) 15438 { 15439 MSG msg; 15440 if (PeekMessageA(&msg, 0, 0, 0, 1)) 15441 { 15442 TranslateMessage(&msg); 15443 DispatchMessageA(&msg); 15444 } 15445 } 15446 DestroyWindow(hwnd); 15447 } 15448 15449 static const struct message NCRBUTTONDOWNSeq[] = 15450 { 15451 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, 15452 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, 15453 { WM_CAPTURECHANGED, sent }, 15454 { WM_CONTEXTMENU, sent, /*hwnd*/0, -1 }, 15455 { 0 } 15456 }; 15457 15458 static const struct message NCXBUTTONUPSeq1[] = 15459 { 15460 { WM_APPCOMMAND, sent|lparam, /*hwnd*/0, MAKELPARAM(0, FAPPCOMMAND_MOUSE | APPCOMMAND_BROWSER_BACKWARD) }, 15461 { 0 } 15462 }; 15463 15464 static const struct message NCXBUTTONUPSeq2[] = 15465 { 15466 { WM_APPCOMMAND, sent|lparam, /*hwnd*/0, MAKELPARAM(0, FAPPCOMMAND_MOUSE | APPCOMMAND_BROWSER_FORWARD) }, 15467 { 0 } 15468 }; 15469 15470 /* DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0) to minimized visible window */ 15471 static const struct message WmRestoreMinimizedOverlappedSeq[] = 15472 { 15473 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_RESTORE, 0 }, 15474 { HCBT_MINMAX, hook }, 15475 { WM_QUERYOPEN, sent }, 15476 { WM_GETTEXT, sent|optional }, 15477 { WM_NCACTIVATE, sent|optional }, 15478 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 15479 { WM_WINDOWPOSCHANGED, sent|optional }, 15480 { WM_WINDOWPOSCHANGING, sent|optional }, 15481 { WM_GETMINMAXINFO, sent|defwinproc }, 15482 { WM_NCCALCSIZE, sent|optional }, 15483 { WM_NCPAINT, sent|optional }, 15484 { WM_GETTEXT, sent|defwinproc|optional }, 15485 { WM_ERASEBKGND, sent|optional }, 15486 { WM_WINDOWPOSCHANGED, sent|optional }, 15487 { HCBT_ACTIVATE, hook }, 15488 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE }, 15489 { WM_ACTIVATEAPP, sent|wparam, TRUE }, 15490 { WM_NCACTIVATE, sent|wparam, TRUE }, 15491 { WM_GETTEXT, sent|defwinproc|optional }, 15492 { WM_ACTIVATE, sent|wparam, TRUE }, 15493 { HCBT_SETFOCUS, hook }, 15494 { WM_SETFOCUS, sent|defwinproc }, 15495 { WM_NCPAINT, sent }, 15496 { WM_GETTEXT, sent|defwinproc|optional }, 15497 { WM_ERASEBKGND, sent }, 15498 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_FRAMECHANGED|SWP_STATECHANGED }, 15499 { WM_MOVE, sent|defwinproc }, 15500 { WM_SIZE, sent|defwinproc }, 15501 { WM_NCCALCSIZE, sent|optional }, 15502 { WM_NCPAINT, sent|optional }, 15503 { WM_ERASEBKGND, sent|optional }, 15504 { WM_ACTIVATE, sent|wparam, TRUE }, 15505 { WM_SYNCPAINT, sent|optional }, 15506 { WM_PAINT, sent }, 15507 { 0 } 15508 }; 15509 15510 static struct message WmContextMenuSeq[] = { 15511 { WM_CONTEXTMENU, sent|wparam, 0 }, /* wparams set in the code */ 15512 { WM_CONTEXTMENU, sent|wparam|defwinproc, 0 }, 15513 { WM_CONTEXTMENU, sent|wparam|defwinproc, 0 }, 15514 { 0 } 15515 }; 15516 15517 struct rbuttonup_thread_data 15518 { 15519 HWND hwnd; 15520 HANDLE wndproc_finished; 15521 }; 15522 15523 static DWORD CALLBACK post_rbuttonup_msg( void *arg ) 15524 { 15525 struct rbuttonup_thread_data *data = arg; 15526 DWORD ret; 15527 15528 ret = WaitForSingleObject( data->wndproc_finished, 500 ); 15529 todo_wine ok( ret == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", ret ); 15530 if( ret == WAIT_OBJECT_0 ) return 0; 15531 15532 PostMessageA( data->hwnd, WM_RBUTTONUP, 0, 0 ); 15533 return 0; 15534 } 15535 15536 static void test_defwinproc(void) 15537 { 15538 HWND hwnd, child[3]; 15539 MSG msg; 15540 BOOL gotwmquit = FALSE; 15541 POINT pos; 15542 RECT rect; 15543 INT x, y; 15544 LRESULT res; 15545 struct rbuttonup_thread_data data; 15546 char buffA[64]; 15547 HANDLE thread; 15548 15549 hwnd = CreateWindowExA(0, "TestWindowClass", "test_defwndproc", 15550 WS_VISIBLE | WS_CAPTION | WS_OVERLAPPEDWINDOW, 0,0,500,100,0,0,0, NULL); 15551 assert(hwnd); 15552 flush_events(); 15553 15554 buffA[0] = 0; 15555 GetWindowTextA(hwnd, buffA, ARRAY_SIZE(buffA)); 15556 ok(!strcmp(buffA, "test_defwndproc"), "unexpected window text, %s\n", buffA); 15557 15558 /* Zero high word of the lParam */ 15559 res = DefWindowProcA(hwnd, WM_SETTEXT, 0, 0x1234); 15560 ok(res == 0, "WM_SETTEXT was expected to fail, %ld\n", res); 15561 15562 GetWindowTextA(hwnd, buffA, ARRAY_SIZE(buffA)); 15563 ok(!strcmp(buffA, "test_defwndproc"), "unexpected window text, %s\n", buffA); 15564 15565 res = DefWindowProcW(hwnd, WM_SETTEXT, 0, 0x1234); 15566 ok(res == 0, "WM_SETTEXT was expected to fail, %ld\n", res); 15567 15568 GetWindowTextA(hwnd, buffA, ARRAY_SIZE(buffA)); 15569 ok(!strcmp(buffA, "test_defwndproc"), "unexpected window text, %s\n", buffA); 15570 15571 ShowWindow(hwnd, SW_MINIMIZE); 15572 flush_events(); 15573 flush_sequence(); 15574 15575 DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0); 15576 flush_events(); 15577 ok_sequence(WmRestoreMinimizedOverlappedSeq, "DefWindowProcA(SC_RESTORE):overlapped", TRUE); 15578 flush_sequence(); 15579 15580 child[0] = CreateWindowExA(0, "TestWindowClass", "1st child", 15581 WS_VISIBLE | WS_CHILD, 0,0,500,100, hwnd, 0, 0, NULL); 15582 child[1] = CreateWindowExA(0, "TestWindowClass", "2nd child", 15583 WS_VISIBLE | WS_CHILD, 0,0,500,100, child[0], 0, 0, NULL); 15584 child[2] = CreateWindowExA(0, "TestWindowClass", "3rd child", 15585 WS_VISIBLE | WS_CHILD, 0,0,500,100, child[1], 0, 0, NULL); 15586 flush_events(); 15587 flush_sequence(); 15588 test_context_menu = TRUE; 15589 DefWindowProcA(child[2], WM_CONTEXTMENU, 0xcafe, 0); 15590 test_context_menu = FALSE; 15591 WmContextMenuSeq[0].wParam = (WPARAM)child[2]; 15592 WmContextMenuSeq[1].wParam = (WPARAM)child[1]; 15593 WmContextMenuSeq[2].wParam = (WPARAM)child[0]; 15594 ok_sequence(WmContextMenuSeq, "DefWindowProcA(WM_CONTEXTMENU)", FALSE); 15595 DestroyWindow(child[0]); 15596 15597 GetCursorPos(&pos); 15598 GetWindowRect(hwnd, &rect); 15599 x = (rect.left+rect.right) / 2; 15600 y = rect.top + GetSystemMetrics(SM_CYFRAME) + 1; 15601 SetCursorPos(x, y); 15602 flush_events(); 15603 res = DefWindowProcA( hwnd, WM_NCHITTEST, 0, MAKELPARAM(x, y)); 15604 ok(res == HTCAPTION, "WM_NCHITTEST returned %ld\n", res); 15605 15606 mouse_event( MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0 ); 15607 mouse_event( MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 ); 15608 flush_events(); 15609 15610 flush_sequence(); 15611 mouse_event( MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0 ); 15612 /* workaround for missing support for clicking on window frame */ 15613 data.hwnd = hwnd; 15614 data.wndproc_finished = CreateEventA( NULL, FALSE, FALSE, NULL ); 15615 thread = CreateThread( NULL, 0, post_rbuttonup_msg, (void*)&data, 0, NULL ); 15616 15617 DefWindowProcA( hwnd, WM_NCRBUTTONDOWN, HTCAPTION, MAKELPARAM(x, y)); 15618 ok_sequence(NCRBUTTONDOWNSeq, "WM_NCRBUTTONDOWN on caption", FALSE); 15619 15620 res = DefWindowProcA(hwnd, WM_NCXBUTTONUP, 0, MAKELPARAM(x, y)); 15621 ok(!res, "WM_NCXBUTTONUP returned %ld\n", res); 15622 ok_sequence(WmEmptySeq, "WM_NCXBUTTONUP without button", FALSE); 15623 15624 res = DefWindowProcA(hwnd, WM_NCXBUTTONUP, MAKEWPARAM(0, XBUTTON1), MAKELPARAM(x, y)); 15625 ok(!res, "WM_NCXBUTTONUP returned %ld\n", res); 15626 ok_sequence(NCXBUTTONUPSeq1, "WM_NCXBUTTONUP with XBUTTON1", FALSE); 15627 15628 res = DefWindowProcA(hwnd, WM_NCXBUTTONUP, MAKEWPARAM(0, XBUTTON2), MAKELPARAM(x, y)); 15629 ok(!res, "WM_NCXBUTTONUP returned %ld\n", res); 15630 ok_sequence(NCXBUTTONUPSeq2, "WM_NCXBUTTONUP with XBUTTON2", FALSE); 15631 15632 res = DefWindowProcA(hwnd, WM_NCXBUTTONUP, MAKEWPARAM(0, 3), MAKELPARAM(x, y)); 15633 ok(!res, "WM_NCXBUTTONUP returned %ld\n", res); 15634 ok_sequence(WmEmptySeq, "WM_NCXBUTTONUP with invalid button", FALSE); 15635 15636 SetEvent( data.wndproc_finished ); 15637 WaitForSingleObject( thread, 1000 ); 15638 CloseHandle( data.wndproc_finished ); 15639 CloseHandle( thread ); 15640 15641 SetCursorPos(pos.x, pos.y); 15642 15643 DefWindowProcA( hwnd, WM_ENDSESSION, 1, 0); 15644 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) { 15645 if( msg.message == WM_QUIT) gotwmquit = TRUE; 15646 DispatchMessageA( &msg ); 15647 } 15648 ok(!gotwmquit, "Unexpected WM_QUIT message!\n"); 15649 DestroyWindow( hwnd); 15650 } 15651 15652 static void test_desktop_winproc(void) 15653 { 15654 HINSTANCE instance = GetModuleHandleA(NULL); 15655 RECT rect, default_rect; 15656 WNDPROC desktop_proc; 15657 char buffer[256]; 15658 WNDCLASSA cls; 15659 LRESULT res; 15660 HWND hwnd; 15661 BOOL ret; 15662 15663 ret = GetClassInfoA(instance, (const CHAR *)MAKEINTATOM(32769), &cls); 15664 ok(ret, "Failed to get desktop class.\n"); 15665 desktop_proc = cls.lpfnWndProc; 15666 15667 memset(&cls, 0, sizeof(cls)); 15668 cls.lpfnWndProc = desktop_proc; 15669 cls.hInstance = instance; 15670 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 15671 cls.hbrBackground = GetStockObject(WHITE_BRUSH); 15672 cls.lpszClassName = "TestDesktopClass"; 15673 ret = !!RegisterClassA(&cls); 15674 ok(ret, "Failed to register class.\n"); 15675 15676 hwnd = CreateWindowExA(0, cls.lpszClassName, "test_desktop_wndproc", 15677 WS_VISIBLE | WS_CAPTION | WS_OVERLAPPEDWINDOW, 0, 0, 500, 100, 0, 0, 0, NULL); 15678 if (!hwnd) /* win2003 */ 15679 { 15680 skip("Failed to create window with desktop window procedure.\n"); 15681 goto out_unregister; 15682 } 15683 15684 memset(&cls, 0, sizeof(cls)); 15685 ret = GetClassInfoA(instance, "TestDesktopClass", &cls); 15686 ok(ret, "Failed to get class info.\n"); 15687 ok(cls.lpfnWndProc == desktop_proc, "Got %p, expected %p.\n", cls.lpfnWndProc, desktop_proc); 15688 15689 GetWindowTextA(hwnd, buffer, ARRAY_SIZE(buffer)); 15690 todo_wine ok(!strcmp(buffer, "test_desktop_wndproc"), "Got unexpected window text: %s.\n", buffer); 15691 15692 res = CallWindowProcA(desktop_proc, hwnd, WM_SETTEXT, 0, (LPARAM)"test"); 15693 ok(res == TRUE, "Failed to set text, %ld.\n", res); 15694 GetWindowTextA(hwnd, buffer, ARRAY_SIZE(buffer)); 15695 ok(!strcmp(buffer, "test"), "Got unexpected window text: %s.\n", buffer); 15696 15697 SetRect(&default_rect, 0, 0, 100, 100); 15698 res = DefWindowProcW(hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&default_rect); 15699 ok(!res, "Got unexpected result %ld.\n", res); 15700 15701 SetRect(&rect, 0, 0, 100, 100); 15702 res = CallWindowProcA(desktop_proc, hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&rect); 15703 ok(!res, "Got unexpected result %ld.\n", res); 15704 todo_wine ok(EqualRect(&rect, &default_rect), "rect Got %s, expected %s.\n", 15705 wine_dbgstr_rect(&rect), wine_dbgstr_rect(&default_rect)); 15706 15707 DestroyWindow(hwnd); 15708 15709 out_unregister: 15710 UnregisterClassA("TestDesktopClass", instance); 15711 } 15712 15713 #define clear_clipboard(hwnd) clear_clipboard_(__LINE__, (hwnd)) 15714 static void clear_clipboard_(int line, HWND hWnd) 15715 { 15716 BOOL succ; 15717 succ = OpenClipboard(hWnd); 15718 ok_(__FILE__, line)(succ, "OpenClipboard failed, err=%u\n", GetLastError()); 15719 succ = EmptyClipboard(); 15720 ok_(__FILE__, line)(succ, "EmptyClipboard failed, err=%u\n", GetLastError()); 15721 succ = CloseClipboard(); 15722 ok_(__FILE__, line)(succ, "CloseClipboard failed, err=%u\n", GetLastError()); 15723 } 15724 15725 #define expect_HWND(expected, got) expect_HWND_(__LINE__, (expected), (got)) 15726 static void expect_HWND_(int line, HWND expected, HWND got) 15727 { 15728 ok_(__FILE__, line)(got==expected, "Expected %p, got %p\n", expected, got); 15729 } 15730 15731 static WNDPROC pOldViewerProc; 15732 15733 static LRESULT CALLBACK recursive_viewer_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 15734 { 15735 static BOOL recursion_guard; 15736 15737 if (message == WM_DRAWCLIPBOARD && !recursion_guard) 15738 { 15739 recursion_guard = TRUE; 15740 clear_clipboard(hWnd); 15741 recursion_guard = FALSE; 15742 } 15743 return CallWindowProcA(pOldViewerProc, hWnd, message, wParam, lParam); 15744 } 15745 15746 static void test_clipboard_viewers(void) 15747 { 15748 static struct message wm_change_cb_chain[] = 15749 { 15750 { WM_CHANGECBCHAIN, sent|wparam|lparam, 0, 0 }, 15751 { 0 } 15752 }; 15753 static const struct message wm_clipboard_destroyed[] = 15754 { 15755 { WM_DESTROYCLIPBOARD, sent|wparam|lparam, 0, 0 }, 15756 { 0 } 15757 }; 15758 static struct message wm_clipboard_changed[] = 15759 { 15760 { WM_DRAWCLIPBOARD, sent|wparam|lparam, 0, 0 }, 15761 { 0 } 15762 }; 15763 static struct message wm_clipboard_changed_and_owned[] = 15764 { 15765 { WM_DESTROYCLIPBOARD, sent|wparam|lparam, 0, 0 }, 15766 { WM_DRAWCLIPBOARD, sent|wparam|lparam, 0, 0 }, 15767 { 0 } 15768 }; 15769 15770 HINSTANCE hInst = GetModuleHandleA(NULL); 15771 HWND hWnd1, hWnd2, hWnd3; 15772 HWND hOrigViewer; 15773 HWND hRet; 15774 15775 hWnd1 = CreateWindowExA(0, "TestWindowClass", "Clipboard viewer test wnd 1", 15776 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX, 15777 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 15778 GetDesktopWindow(), NULL, hInst, NULL); 15779 hWnd2 = CreateWindowExA(0, "SimpleWindowClass", "Clipboard viewer test wnd 2", 15780 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX, 15781 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 15782 GetDesktopWindow(), NULL, hInst, NULL); 15783 hWnd3 = CreateWindowExA(0, "SimpleWindowClass", "Clipboard viewer test wnd 3", 15784 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX, 15785 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 15786 GetDesktopWindow(), NULL, hInst, NULL); 15787 trace("clipbd viewers: hWnd1=%p, hWnd2=%p, hWnd3=%p\n", hWnd1, hWnd2, hWnd3); 15788 assert(hWnd1 && hWnd2 && hWnd3); 15789 15790 CountClipboardFormats(); /* Ensure that we do not have an X11 update to the clipboard */ 15791 flush_sequence(); 15792 15793 /* Test getting the clipboard viewer and setting the viewer to NULL. */ 15794 hOrigViewer = GetClipboardViewer(); 15795 hRet = SetClipboardViewer(NULL); 15796 ok_sequence(WmEmptySeq, "set viewer to NULL", FALSE); 15797 expect_HWND(hOrigViewer, hRet); 15798 expect_HWND(NULL, GetClipboardViewer()); 15799 15800 /* Test registering hWnd1 as a viewer. */ 15801 hRet = SetClipboardViewer(hWnd1); 15802 wm_clipboard_changed[0].wParam = (WPARAM) GetClipboardOwner(); 15803 ok_sequence(wm_clipboard_changed, "set viewer NULL->1", FALSE); 15804 expect_HWND(NULL, hRet); 15805 expect_HWND(hWnd1, GetClipboardViewer()); 15806 15807 /* Test that changing the clipboard actually refreshes the registered viewer. */ 15808 clear_clipboard(hWnd1); 15809 wm_clipboard_changed[0].wParam = (WPARAM) GetClipboardOwner(); 15810 ok_sequence(wm_clipboard_changed, "clear clipbd (viewer=owner=1)", FALSE); 15811 15812 /* Again, but with different owner. */ 15813 clear_clipboard(hWnd2); 15814 wm_clipboard_changed_and_owned[1].wParam = (WPARAM) GetClipboardOwner(); 15815 ok_sequence(wm_clipboard_changed_and_owned, "clear clipbd (viewer=1, owner=2)", FALSE); 15816 15817 /* Test re-registering same window. */ 15818 hRet = SetClipboardViewer(hWnd1); 15819 wm_clipboard_changed[0].wParam = (WPARAM) GetClipboardOwner(); 15820 ok_sequence(wm_clipboard_changed, "set viewer 1->1", FALSE); 15821 expect_HWND(hWnd1, hRet); 15822 expect_HWND(hWnd1, GetClipboardViewer()); 15823 15824 /* Test ChangeClipboardChain. */ 15825 ChangeClipboardChain(hWnd2, hWnd3); 15826 wm_change_cb_chain[0].wParam = (WPARAM) hWnd2; 15827 wm_change_cb_chain[0].lParam = (LPARAM) hWnd3; 15828 ok_sequence(wm_change_cb_chain, "change chain (viewer=1, remove=2, next=3)", FALSE); 15829 expect_HWND(hWnd1, GetClipboardViewer()); 15830 15831 ChangeClipboardChain(hWnd2, NULL); 15832 wm_change_cb_chain[0].wParam = (WPARAM) hWnd2; 15833 wm_change_cb_chain[0].lParam = 0; 15834 ok_sequence(wm_change_cb_chain, "change chain (viewer=1, remove=2, next=NULL)", FALSE); 15835 expect_HWND(hWnd1, GetClipboardViewer()); 15836 15837 ChangeClipboardChain(NULL, hWnd2); 15838 ok_sequence(WmEmptySeq, "change chain (viewer=1, remove=NULL, next=2)", FALSE); 15839 expect_HWND(hWnd1, GetClipboardViewer()); 15840 15841 /* Actually change clipboard viewer with ChangeClipboardChain. */ 15842 ChangeClipboardChain(hWnd1, hWnd2); 15843 ok_sequence(WmEmptySeq, "change chain (viewer=remove=1, next=2)", FALSE); 15844 expect_HWND(hWnd2, GetClipboardViewer()); 15845 15846 /* Test that no refresh messages are sent when viewer has unregistered. */ 15847 clear_clipboard(hWnd2); 15848 ok_sequence(WmEmptySeq, "clear clipd (viewer=2, owner=1)", FALSE); 15849 15850 /* Register hWnd1 again. */ 15851 ChangeClipboardChain(hWnd2, hWnd1); 15852 ok_sequence(WmEmptySeq, "change chain (viewer=remove=2, next=1)", FALSE); 15853 expect_HWND(hWnd1, GetClipboardViewer()); 15854 15855 /* Subclass hWnd1 so that when it receives a WM_DRAWCLIPBOARD message, it 15856 * changes the clipboard. When this happens, the system shouldn't send 15857 * another WM_DRAWCLIPBOARD (as this could cause an infinite loop). 15858 */ 15859 pOldViewerProc = (WNDPROC) SetWindowLongPtrA(hWnd1, GWLP_WNDPROC, (LONG_PTR) recursive_viewer_proc); 15860 clear_clipboard(hWnd2); 15861 /* The clipboard owner is changed in recursive_viewer_proc: */ 15862 wm_clipboard_changed[0].wParam = (WPARAM) hWnd2; 15863 ok_sequence(wm_clipboard_changed, "recursive clear clipbd (viewer=1, owner=2)", TRUE); 15864 15865 /* Test unregistering. */ 15866 ChangeClipboardChain(hWnd1, NULL); 15867 ok_sequence(WmEmptySeq, "change chain (viewer=remove=1, next=NULL)", FALSE); 15868 expect_HWND(NULL, GetClipboardViewer()); 15869 15870 clear_clipboard(hWnd1); 15871 ok_sequence(wm_clipboard_destroyed, "clear clipbd (no viewer, owner=1)", FALSE); 15872 15873 DestroyWindow(hWnd1); 15874 DestroyWindow(hWnd2); 15875 DestroyWindow(hWnd3); 15876 SetClipboardViewer(hOrigViewer); 15877 } 15878 15879 static void test_PostMessage(void) 15880 { 15881 static const struct 15882 { 15883 HWND hwnd; 15884 BOOL ret; 15885 } data[] = 15886 { 15887 { HWND_TOP /* 0 */, TRUE }, 15888 { HWND_BROADCAST, TRUE }, 15889 { HWND_BOTTOM, TRUE }, 15890 { HWND_TOPMOST, TRUE }, 15891 { HWND_NOTOPMOST, FALSE }, 15892 { HWND_MESSAGE, FALSE }, 15893 { (HWND)0xdeadbeef, FALSE } 15894 }; 15895 int i; 15896 HWND hwnd; 15897 BOOL ret; 15898 MSG msg; 15899 static const WCHAR staticW[] = {'s','t','a','t','i','c',0}; 15900 15901 SetLastError(0xdeadbeef); 15902 hwnd = CreateWindowExW(0, staticW, NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL); 15903 if (!hwnd && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) 15904 { 15905 win_skip("Skipping some PostMessage tests on Win9x/WinMe\n"); 15906 return; 15907 } 15908 assert(hwnd); 15909 15910 flush_events(); 15911 15912 PostMessageA(hwnd, WM_USER+1, 0x1234, 0x5678); 15913 PostMessageA(0, WM_USER+2, 0x5678, 0x1234); 15914 15915 for (i = 0; i < ARRAY_SIZE(data); i++) 15916 { 15917 memset(&msg, 0xab, sizeof(msg)); 15918 ret = PeekMessageA(&msg, data[i].hwnd, 0, 0, PM_NOREMOVE); 15919 ok(ret == data[i].ret, "%d: hwnd %p expected %d, got %d\n", i, data[i].hwnd, data[i].ret, ret); 15920 if (data[i].ret) 15921 { 15922 if (data[i].hwnd) 15923 ok(ret && msg.hwnd == 0 && msg.message == WM_USER+2 && 15924 msg.wParam == 0x5678 && msg.lParam == 0x1234, 15925 "%d: got ret %d hwnd %p msg %04x wParam %08lx lParam %08lx instead of TRUE/0/WM_USER+2/0x5678/0x1234\n", 15926 i, ret, msg.hwnd, msg.message, msg.wParam, msg.lParam); 15927 else 15928 ok(ret && msg.hwnd == hwnd && msg.message == WM_USER+1 && 15929 msg.wParam == 0x1234 && msg.lParam == 0x5678, 15930 "%d: got ret %d hwnd %p msg %04x wParam %08lx lParam %08lx instead of TRUE/%p/WM_USER+1/0x1234/0x5678\n", 15931 i, ret, msg.hwnd, msg.message, msg.wParam, msg.lParam, msg.hwnd); 15932 } 15933 } 15934 15935 DestroyWindow(hwnd); 15936 flush_events(); 15937 } 15938 15939 static LPARAM g_broadcast_lparam; 15940 static LRESULT WINAPI broadcast_test_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 15941 { 15942 WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA); 15943 15944 if (wParam == 0xbaadbeef) 15945 g_broadcast_lparam = wParam; 15946 else 15947 g_broadcast_lparam = 0; 15948 15949 return CallWindowProcA(oldproc, hwnd, message, wParam, lParam); 15950 } 15951 15952 static void test_broadcast(void) 15953 { 15954 static const UINT messages[] = 15955 { 15956 WM_USER-1, 15957 WM_USER, 15958 WM_USER+1, 15959 0xc000-1, 15960 0xc000, /* lowest possible atom returned by RegisterWindowMessage */ 15961 0xffff, 15962 }; 15963 WNDPROC oldproc; 15964 unsigned int i; 15965 HWND hwnd; 15966 15967 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0, 0, 0, 0, 0, 0, 0, NULL); 15968 ok(hwnd != NULL, "got %p\n", hwnd); 15969 15970 oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)broadcast_test_proc); 15971 SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc); 15972 15973 for (i = 0; i < ARRAY_SIZE(messages); i++) 15974 { 15975 BOOL ret; 15976 MSG msg; 15977 15978 flush_events(); 15979 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 15980 ; 15981 15982 /* post, broadcast */ 15983 ret = PostMessageA(HWND_BROADCAST, messages[i], 0, 0); 15984 ok(ret, "%d: got %d, error %d\n", i, ret, GetLastError()); 15985 15986 memset(&msg, 0xab, sizeof(msg)); 15987 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); 15988 if (messages[i] < WM_USER || messages[i] >= 0xc000) 15989 { 15990 ok(ret, "%d: message %04x, got %d, error %d\n", i, messages[i], ret, GetLastError()); 15991 ok(msg.hwnd == hwnd, "%d: got %p\n", i, msg.hwnd); 15992 } 15993 else 15994 { 15995 ok(!ret, "%d: message %04x, got %d, error %d\n", i, messages[i], ret, GetLastError()); 15996 } 15997 15998 /* post, topmost */ 15999 ret = PostMessageA(HWND_TOPMOST, messages[i], 0, 0); 16000 ok(ret, "%d: got %d, error %d\n", i, ret, GetLastError()); 16001 16002 memset(&msg, 0xab, sizeof(msg)); 16003 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); 16004 if (messages[i] < WM_USER || messages[i] >= 0xc000) 16005 { 16006 ok(ret, "%d: message %04x, got %d, error %d\n", i, messages[i], ret, GetLastError()); 16007 ok(msg.hwnd == hwnd, "%d: got %p\n", i, msg.hwnd); 16008 } 16009 else 16010 { 16011 ok(!ret, "%d: got %d, error %d\n", i, ret, GetLastError()); 16012 } 16013 16014 /* send, broadcast */ 16015 g_broadcast_lparam = 0xdead; 16016 ret = SendMessageTimeoutA(HWND_BROADCAST, messages[i], 0xbaadbeef, 0, SMTO_NORMAL, 2000, NULL); 16017 if (!ret && GetLastError() == ERROR_TIMEOUT) 16018 win_skip("broadcasting test %d, timeout\n", i); 16019 else 16020 { 16021 if (messages[i] < WM_USER || messages[i] >= 0xc000) 16022 { 16023 ok(g_broadcast_lparam == 0xbaadbeef, "%d: message %04x, got %#lx, error %d\n", i, messages[i], 16024 g_broadcast_lparam, GetLastError()); 16025 } 16026 else 16027 { 16028 ok(g_broadcast_lparam == 0xdead, "%d: message %04x, got %#lx, error %d\n", i, messages[i], 16029 g_broadcast_lparam, GetLastError()); 16030 } 16031 } 16032 16033 /* send, topmost */ 16034 g_broadcast_lparam = 0xdead; 16035 ret = SendMessageTimeoutA(HWND_TOPMOST, messages[i], 0xbaadbeef, 0, SMTO_NORMAL, 2000, NULL); 16036 if (!ret && GetLastError() == ERROR_TIMEOUT) 16037 win_skip("broadcasting test %d, timeout\n", i); 16038 else 16039 { 16040 if (messages[i] < WM_USER || messages[i] >= 0xc000) 16041 { 16042 ok(g_broadcast_lparam == 0xbaadbeef, "%d: message %04x, got %#lx, error %d\n", i, messages[i], 16043 g_broadcast_lparam, GetLastError()); 16044 } 16045 else 16046 { 16047 ok(g_broadcast_lparam == 0xdead, "%d: message %04x, got %#lx, error %d\n", i, messages[i], 16048 g_broadcast_lparam, GetLastError()); 16049 } 16050 } 16051 } 16052 16053 DestroyWindow(hwnd); 16054 } 16055 16056 static const struct 16057 { 16058 DWORD exp, broken; 16059 BOOL todo; 16060 } wait_idle_expect[] = 16061 { 16062 /* 0 */ { WAIT_TIMEOUT, WAIT_TIMEOUT, FALSE }, 16063 { WAIT_TIMEOUT, 0, FALSE }, 16064 { WAIT_TIMEOUT, 0, FALSE }, 16065 { WAIT_TIMEOUT, WAIT_TIMEOUT, FALSE }, 16066 { WAIT_TIMEOUT, WAIT_TIMEOUT, FALSE }, 16067 /* 5 */ { WAIT_TIMEOUT, 0, FALSE }, 16068 { WAIT_TIMEOUT, 0, FALSE }, 16069 { WAIT_TIMEOUT, WAIT_TIMEOUT, FALSE }, 16070 { 0, 0, FALSE }, 16071 { 0, 0, FALSE }, 16072 /* 10 */ { 0, 0, FALSE }, 16073 { 0, 0, FALSE }, 16074 { 0, WAIT_TIMEOUT, FALSE }, 16075 { 0, 0, FALSE }, 16076 { 0, 0, FALSE }, 16077 /* 15 */ { 0, 0, FALSE }, 16078 { WAIT_TIMEOUT, 0, FALSE }, 16079 { WAIT_TIMEOUT, 0, FALSE }, 16080 { WAIT_TIMEOUT, 0, FALSE }, 16081 { WAIT_TIMEOUT, 0, FALSE }, 16082 /* 20 */ { WAIT_TIMEOUT, 0, FALSE }, 16083 }; 16084 16085 static DWORD CALLBACK do_wait_idle_child_thread( void *arg ) 16086 { 16087 MSG msg; 16088 16089 PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ); 16090 Sleep( 200 ); 16091 MsgWaitForMultipleObjects( 0, NULL, FALSE, 100, QS_ALLINPUT ); 16092 return 0; 16093 } 16094 16095 static void do_wait_idle_child( int arg ) 16096 { 16097 WNDCLASSA cls; 16098 MSG msg; 16099 HWND hwnd = 0; 16100 HANDLE thread; 16101 DWORD id; 16102 HANDLE start_event = OpenEventA( EVENT_ALL_ACCESS, FALSE, "test_WaitForInputIdle_start" ); 16103 HANDLE end_event = OpenEventA( EVENT_ALL_ACCESS, FALSE, "test_WaitForInputIdle_end" ); 16104 16105 memset( &cls, 0, sizeof(cls) ); 16106 cls.lpfnWndProc = DefWindowProcA; 16107 cls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); 16108 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 16109 cls.lpszClassName = "TestClass"; 16110 RegisterClassA( &cls ); 16111 16112 PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ); /* create the msg queue */ 16113 16114 ok( start_event != 0, "failed to create start event, error %u\n", GetLastError() ); 16115 ok( end_event != 0, "failed to create end event, error %u\n", GetLastError() ); 16116 16117 switch (arg) 16118 { 16119 case 0: 16120 SetEvent( start_event ); 16121 break; 16122 case 1: 16123 SetEvent( start_event ); 16124 Sleep( 200 ); 16125 PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ); 16126 break; 16127 case 2: 16128 SetEvent( start_event ); 16129 Sleep( 200 ); 16130 PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ); 16131 PostThreadMessageA( GetCurrentThreadId(), WM_COMMAND, 0x1234, 0xabcd ); 16132 PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ); 16133 break; 16134 case 3: 16135 SetEvent( start_event ); 16136 Sleep( 200 ); 16137 SendMessageA( HWND_BROADCAST, WM_WININICHANGE, 0, 0 ); 16138 break; 16139 case 4: 16140 SetEvent( start_event ); 16141 Sleep( 200 ); 16142 hwnd = CreateWindowExA(0, "TestClass", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL); 16143 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE|PM_NOYIELD )) DispatchMessageA( &msg ); 16144 break; 16145 case 5: 16146 SetEvent( start_event ); 16147 Sleep( 200 ); 16148 hwnd = CreateWindowExA(0, "TestClass", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL); 16149 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 16150 break; 16151 case 6: 16152 SetEvent( start_event ); 16153 Sleep( 200 ); 16154 hwnd = CreateWindowExA(0, "TestClass", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL); 16155 while (PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE )) 16156 { 16157 GetMessageA( &msg, 0, 0, 0 ); 16158 DispatchMessageA( &msg ); 16159 } 16160 break; 16161 case 7: 16162 SetEvent( start_event ); 16163 Sleep( 200 ); 16164 hwnd = CreateWindowExA(0, "TestClass", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL); 16165 SetTimer( hwnd, 3, 1, NULL ); 16166 Sleep( 200 ); 16167 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE|PM_NOYIELD )) DispatchMessageA( &msg ); 16168 break; 16169 case 8: 16170 SetEvent( start_event ); 16171 Sleep( 200 ); 16172 PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ); 16173 MsgWaitForMultipleObjects( 0, NULL, FALSE, 100, QS_ALLINPUT ); 16174 break; 16175 case 9: 16176 SetEvent( start_event ); 16177 Sleep( 200 ); 16178 hwnd = CreateWindowExA(0, "TestClass", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL); 16179 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 16180 for (;;) GetMessageA( &msg, 0, 0, 0 ); 16181 break; 16182 case 10: 16183 SetEvent( start_event ); 16184 Sleep( 200 ); 16185 hwnd = CreateWindowExA(0, "TestClass", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL); 16186 SetTimer( hwnd, 3, 1, NULL ); 16187 Sleep( 200 ); 16188 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 16189 break; 16190 case 11: 16191 SetEvent( start_event ); 16192 Sleep( 200 ); 16193 return; /* exiting the process makes WaitForInputIdle return success too */ 16194 case 12: 16195 PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ); 16196 Sleep( 200 ); 16197 MsgWaitForMultipleObjects( 0, NULL, FALSE, 100, QS_ALLINPUT ); 16198 SetEvent( start_event ); 16199 break; 16200 case 13: 16201 SetEvent( start_event ); 16202 PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ); 16203 Sleep( 200 ); 16204 thread = CreateThread( NULL, 0, do_wait_idle_child_thread, NULL, 0, &id ); 16205 WaitForSingleObject( thread, 10000 ); 16206 CloseHandle( thread ); 16207 break; 16208 case 14: 16209 SetEvent( start_event ); 16210 Sleep( 200 ); 16211 PeekMessageA( &msg, HWND_TOPMOST, 0, 0, PM_NOREMOVE ); 16212 break; 16213 case 15: 16214 SetEvent( start_event ); 16215 Sleep( 200 ); 16216 PeekMessageA( &msg, HWND_BROADCAST, 0, 0, PM_NOREMOVE ); 16217 break; 16218 case 16: 16219 SetEvent( start_event ); 16220 Sleep( 200 ); 16221 PeekMessageA( &msg, HWND_BOTTOM, 0, 0, PM_NOREMOVE ); 16222 break; 16223 case 17: 16224 SetEvent( start_event ); 16225 Sleep( 200 ); 16226 PeekMessageA( &msg, (HWND)0xdeadbeef, 0, 0, PM_NOREMOVE ); 16227 break; 16228 case 18: 16229 SetEvent( start_event ); 16230 Sleep( 200 ); 16231 PeekMessageA( &msg, HWND_NOTOPMOST, 0, 0, PM_NOREMOVE ); 16232 break; 16233 case 19: 16234 SetEvent( start_event ); 16235 Sleep( 200 ); 16236 PeekMessageA( &msg, HWND_MESSAGE, 0, 0, PM_NOREMOVE ); 16237 break; 16238 case 20: 16239 SetEvent( start_event ); 16240 Sleep( 200 ); 16241 PeekMessageA( &msg, GetDesktopWindow(), 0, 0, PM_NOREMOVE ); 16242 break; 16243 } 16244 WaitForSingleObject( end_event, 2000 ); 16245 CloseHandle( start_event ); 16246 CloseHandle( end_event ); 16247 if (hwnd) DestroyWindow( hwnd ); 16248 } 16249 16250 static LRESULT CALLBACK wait_idle_proc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ) 16251 { 16252 if (msg == WM_WININICHANGE) Sleep( 200 ); /* make sure the child waits */ 16253 return DefWindowProcA( hwnd, msg, wp, lp ); 16254 } 16255 16256 static DWORD CALLBACK wait_idle_thread( void *arg ) 16257 { 16258 WNDCLASSA cls; 16259 MSG msg; 16260 HWND hwnd; 16261 16262 memset( &cls, 0, sizeof(cls) ); 16263 cls.lpfnWndProc = wait_idle_proc; 16264 cls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); 16265 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 16266 cls.lpszClassName = "TestClass"; 16267 RegisterClassA( &cls ); 16268 16269 hwnd = CreateWindowExA(0, "TestClass", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL); 16270 while (GetMessageA( &msg, 0, 0, 0 )) DispatchMessageA( &msg ); 16271 DestroyWindow(hwnd); 16272 return 0; 16273 } 16274 16275 static void test_WaitForInputIdle( char *argv0 ) 16276 { 16277 char path[MAX_PATH]; 16278 PROCESS_INFORMATION pi; 16279 STARTUPINFOA startup; 16280 BOOL ret; 16281 HANDLE start_event, end_event, thread; 16282 unsigned int i; 16283 DWORD id; 16284 const IMAGE_DOS_HEADER *dos = (const IMAGE_DOS_HEADER *)GetModuleHandleA(0); 16285 const IMAGE_NT_HEADERS *nt = (const IMAGE_NT_HEADERS *)((const char *)dos + dos->e_lfanew); 16286 BOOL console_app = (nt->OptionalHeader.Subsystem != IMAGE_SUBSYSTEM_WINDOWS_GUI); 16287 16288 if (console_app) /* build the test with -mwindows for better coverage */ 16289 trace( "not built as a GUI app, WaitForInputIdle may not be fully tested\n" ); 16290 16291 start_event = CreateEventA(NULL, 0, 0, "test_WaitForInputIdle_start"); 16292 end_event = CreateEventA(NULL, 0, 0, "test_WaitForInputIdle_end"); 16293 ok(start_event != 0, "failed to create start event, error %u\n", GetLastError()); 16294 ok(end_event != 0, "failed to create end event, error %u\n", GetLastError()); 16295 16296 memset( &startup, 0, sizeof(startup) ); 16297 startup.cb = sizeof(startup); 16298 startup.dwFlags = STARTF_USESHOWWINDOW; 16299 startup.wShowWindow = SW_SHOWNORMAL; 16300 16301 thread = CreateThread( NULL, 0, wait_idle_thread, NULL, 0, &id ); 16302 16303 for (i = 0; i < ARRAY_SIZE(wait_idle_expect); i++) 16304 { 16305 ResetEvent( start_event ); 16306 ResetEvent( end_event ); 16307 #ifdef __REACTOS__ 16308 sprintf( path, "%s msg_queue %u", argv0, i ); 16309 #else 16310 sprintf( path, "%s msg %u", argv0, i ); 16311 #endif 16312 ret = CreateProcessA( NULL, path, NULL, NULL, TRUE, 0, NULL, NULL, &startup, &pi ); 16313 ok( ret, "CreateProcess '%s' failed err %u.\n", path, GetLastError() ); 16314 if (ret) 16315 { 16316 ret = WaitForSingleObject( start_event, 5000 ); 16317 ok( ret == WAIT_OBJECT_0, "%u: WaitForSingleObject failed\n", i ); 16318 if (ret == WAIT_OBJECT_0) 16319 { 16320 ret = WaitForInputIdle( pi.hProcess, 1000 ); 16321 if (ret == WAIT_FAILED) 16322 ok( console_app || 16323 ret == wait_idle_expect[i].exp || 16324 broken(ret == wait_idle_expect[i].broken), 16325 "%u: WaitForInputIdle error %08x expected %08x\n", 16326 i, ret, wait_idle_expect[i].exp ); 16327 else todo_wine_if (wait_idle_expect[i].todo) 16328 ok( ret == wait_idle_expect[i].exp || broken(ret == wait_idle_expect[i].broken), 16329 "%u: WaitForInputIdle error %08x expected %08x\n", 16330 i, ret, wait_idle_expect[i].exp ); 16331 SetEvent( end_event ); 16332 WaitForSingleObject( pi.hProcess, 1000 ); /* give it a chance to exit on its own */ 16333 } 16334 TerminateProcess( pi.hProcess, 0 ); /* just in case */ 16335 winetest_wait_child_process( pi.hProcess ); 16336 ret = WaitForInputIdle( pi.hProcess, 100 ); 16337 ok( ret == WAIT_FAILED, "%u: WaitForInputIdle after exit error %08x\n", i, ret ); 16338 CloseHandle( pi.hProcess ); 16339 CloseHandle( pi.hThread ); 16340 } 16341 } 16342 CloseHandle( start_event ); 16343 PostThreadMessageA( id, WM_QUIT, 0, 0 ); 16344 WaitForSingleObject( thread, 10000 ); 16345 CloseHandle( thread ); 16346 } 16347 16348 static const struct message WmSetParentSeq_1[] = { 16349 { WM_SHOWWINDOW, sent|wparam, 0 }, 16350 { EVENT_OBJECT_PARENTCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 16351 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE }, 16352 { WM_CHILDACTIVATE, sent }, 16353 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOREDRAW|SWP_NOCLIENTSIZE }, 16354 { WM_MOVE, sent|defwinproc|wparam, 0 }, 16355 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 16356 { WM_SHOWWINDOW, sent|wparam, 1 }, 16357 { 0 } 16358 }; 16359 16360 static const struct message WmSetParentSeq_2[] = { 16361 { WM_SHOWWINDOW, sent|wparam, 0 }, 16362 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 16363 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, 16364 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 16365 { HCBT_SETFOCUS, hook|optional }, 16366 { WM_NCACTIVATE, sent|wparam|optional, 0 }, 16367 { WM_ACTIVATE, sent|wparam|optional, 0 }, 16368 { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, 16369 { WM_KILLFOCUS, sent|wparam, 0 }, 16370 { EVENT_OBJECT_PARENTCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 16371 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE }, 16372 { HCBT_ACTIVATE, hook|optional }, 16373 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, 16374 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, 16375 { WM_NCACTIVATE, sent|wparam|optional, 1 }, 16376 { WM_ACTIVATE, sent|wparam|optional, 1 }, 16377 { HCBT_SETFOCUS, hook|optional }, 16378 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, 16379 { WM_SETFOCUS, sent|optional|defwinproc }, 16380 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOREDRAW|SWP_NOSIZE|SWP_NOCLIENTSIZE }, 16381 { WM_MOVE, sent|defwinproc|wparam, 0 }, 16382 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, 16383 { WM_SHOWWINDOW, sent|wparam, 1 }, 16384 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, 16385 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, 16386 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 16387 { 0 } 16388 }; 16389 16390 16391 static void test_SetParent(void) 16392 { 16393 HWND parent1, parent2, child, popup; 16394 RECT rc, rc_old; 16395 16396 parent1 = CreateWindowExA(0, "TestParentClass", NULL, WS_OVERLAPPEDWINDOW, 16397 100, 100, 200, 200, 0, 0, 0, NULL); 16398 ok(parent1 != 0, "Failed to create parent1 window\n"); 16399 16400 parent2 = CreateWindowExA(0, "TestParentClass", NULL, WS_OVERLAPPEDWINDOW, 16401 400, 100, 200, 200, 0, 0, 0, NULL); 16402 ok(parent2 != 0, "Failed to create parent2 window\n"); 16403 16404 /* WS_CHILD window */ 16405 child = CreateWindowExA(0, "TestWindowClass", NULL, WS_CHILD | WS_VISIBLE, 16406 10, 10, 150, 150, parent1, 0, 0, NULL); 16407 ok(child != 0, "Failed to create child window\n"); 16408 16409 GetWindowRect(parent1, &rc); 16410 trace("parent1 %s\n", wine_dbgstr_rect(&rc)); 16411 GetWindowRect(child, &rc_old); 16412 MapWindowPoints(0, parent1, (POINT *)&rc_old, 2); 16413 trace("child %s\n", wine_dbgstr_rect(&rc_old)); 16414 16415 flush_sequence(); 16416 16417 SetParent(child, parent2); 16418 flush_events(); 16419 ok_sequence(WmSetParentSeq_1, "SetParent() visible WS_CHILD", FALSE); 16420 16421 ok(GetWindowLongA(child, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 16422 ok(!IsWindowVisible(child), "IsWindowVisible() should return FALSE\n"); 16423 16424 GetWindowRect(parent2, &rc); 16425 trace("parent2 %s\n", wine_dbgstr_rect(&rc)); 16426 GetWindowRect(child, &rc); 16427 MapWindowPoints(0, parent2, (POINT *)&rc, 2); 16428 trace("child %s\n", wine_dbgstr_rect(&rc)); 16429 16430 ok(EqualRect(&rc_old, &rc), "rects do not match %s / %s\n", wine_dbgstr_rect(&rc_old), 16431 wine_dbgstr_rect(&rc)); 16432 16433 /* WS_POPUP window */ 16434 popup = CreateWindowExA(0, "TestWindowClass", NULL, WS_POPUP | WS_VISIBLE, 16435 20, 20, 100, 100, 0, 0, 0, NULL); 16436 ok(popup != 0, "Failed to create popup window\n"); 16437 16438 GetWindowRect(popup, &rc_old); 16439 trace("popup %s\n", wine_dbgstr_rect(&rc_old)); 16440 16441 flush_sequence(); 16442 16443 SetParent(popup, child); 16444 flush_events(); 16445 ok_sequence(WmSetParentSeq_2, "SetParent() visible WS_POPUP", TRUE); 16446 16447 ok(GetWindowLongA(popup, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); 16448 ok(!IsWindowVisible(popup), "IsWindowVisible() should return FALSE\n"); 16449 16450 GetWindowRect(child, &rc); 16451 trace("parent2 %s\n", wine_dbgstr_rect(&rc)); 16452 GetWindowRect(popup, &rc); 16453 MapWindowPoints(0, child, (POINT *)&rc, 2); 16454 trace("popup %s\n", wine_dbgstr_rect(&rc)); 16455 16456 ok(EqualRect(&rc_old, &rc), "rects do not match %s / %s\n", wine_dbgstr_rect(&rc_old), 16457 wine_dbgstr_rect(&rc)); 16458 16459 DestroyWindow(popup); 16460 DestroyWindow(child); 16461 DestroyWindow(parent1); 16462 DestroyWindow(parent2); 16463 16464 flush_sequence(); 16465 } 16466 16467 static const struct message WmKeyReleaseOnly[] = { 16468 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 0x41, 0x80000001 }, 16469 { WM_KEYUP, sent|wparam|lparam, 0x41, 0x80000001 }, 16470 { 0 } 16471 }; 16472 static const struct message WmKeyPressNormal[] = { 16473 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 0x41, 0x1 }, 16474 { WM_KEYDOWN, sent|wparam|lparam, 0x41, 0x1 }, 16475 { 0 } 16476 }; 16477 static const struct message WmKeyPressRepeat[] = { 16478 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 0x41, 0x40000001 }, 16479 { WM_KEYDOWN, sent|wparam|lparam, 0x41, 0x40000001 }, 16480 { 0 } 16481 }; 16482 static const struct message WmKeyReleaseNormal[] = { 16483 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 0x41, 0xc0000001 }, 16484 { WM_KEYUP, sent|wparam|lparam, 0x41, 0xc0000001 }, 16485 { 0 } 16486 }; 16487 16488 static void test_keyflags(void) 16489 { 16490 HWND test_window; 16491 SHORT key_state; 16492 BYTE keyboard_state[256]; 16493 MSG msg; 16494 16495 test_window = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 16496 100, 100, 200, 200, 0, 0, 0, NULL); 16497 16498 flush_events(); 16499 flush_sequence(); 16500 16501 /* keyup without a keydown */ 16502 keybd_event(0x41, 0, KEYEVENTF_KEYUP, 0); 16503 while (PeekMessageA(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) 16504 DispatchMessageA(&msg); 16505 ok_sequence(WmKeyReleaseOnly, "key release only", TRUE); 16506 16507 key_state = GetAsyncKeyState(0x41); 16508 ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state); 16509 16510 key_state = GetKeyState(0x41); 16511 ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state); 16512 16513 /* keydown */ 16514 keybd_event(0x41, 0, 0, 0); 16515 while (PeekMessageA(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) 16516 DispatchMessageA(&msg); 16517 ok_sequence(WmKeyPressNormal, "key press only", FALSE); 16518 16519 key_state = GetAsyncKeyState(0x41); 16520 ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); 16521 16522 key_state = GetKeyState(0x41); 16523 ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); 16524 16525 /* keydown repeat */ 16526 keybd_event(0x41, 0, 0, 0); 16527 while (PeekMessageA(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) 16528 DispatchMessageA(&msg); 16529 ok_sequence(WmKeyPressRepeat, "key press repeat", FALSE); 16530 16531 key_state = GetAsyncKeyState(0x41); 16532 ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); 16533 16534 key_state = GetKeyState(0x41); 16535 ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); 16536 16537 /* keyup */ 16538 keybd_event(0x41, 0, KEYEVENTF_KEYUP, 0); 16539 while (PeekMessageA(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) 16540 DispatchMessageA(&msg); 16541 ok_sequence(WmKeyReleaseNormal, "key release repeat", FALSE); 16542 16543 key_state = GetAsyncKeyState(0x41); 16544 ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state); 16545 16546 key_state = GetKeyState(0x41); 16547 ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state); 16548 16549 /* set the key state in this thread */ 16550 GetKeyboardState(keyboard_state); 16551 keyboard_state[0x41] = 0x80; 16552 SetKeyboardState(keyboard_state); 16553 16554 key_state = GetAsyncKeyState(0x41); 16555 ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state); 16556 16557 /* keydown */ 16558 keybd_event(0x41, 0, 0, 0); 16559 while (PeekMessageA(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) 16560 DispatchMessageA(&msg); 16561 ok_sequence(WmKeyPressRepeat, "key press after setkeyboardstate", TRUE); 16562 16563 key_state = GetAsyncKeyState(0x41); 16564 ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); 16565 16566 key_state = GetKeyState(0x41); 16567 ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); 16568 16569 /* clear the key state in this thread */ 16570 GetKeyboardState(keyboard_state); 16571 keyboard_state[0x41] = 0; 16572 SetKeyboardState(keyboard_state); 16573 16574 key_state = GetAsyncKeyState(0x41); 16575 ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); 16576 16577 /* keyup */ 16578 keybd_event(0x41, 0, KEYEVENTF_KEYUP, 0); 16579 while (PeekMessageA(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) 16580 DispatchMessageA(&msg); 16581 ok_sequence(WmKeyReleaseOnly, "key release after setkeyboardstate", TRUE); 16582 16583 key_state = GetAsyncKeyState(0x41); 16584 ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state); 16585 16586 key_state = GetKeyState(0x41); 16587 ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state); 16588 16589 DestroyWindow(test_window); 16590 flush_sequence(); 16591 } 16592 16593 static const struct message WmHotkeyPressLWIN[] = { 16594 { WM_KEYDOWN, kbd_hook|wparam|lparam, VK_LWIN, LLKHF_INJECTED }, 16595 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_LWIN, 1 }, 16596 { WM_KEYDOWN, sent|wparam|lparam, VK_LWIN, 1 }, 16597 { 0 } 16598 }; 16599 static const struct message WmHotkeyPress[] = { 16600 { WM_KEYDOWN, kbd_hook|lparam, 0, LLKHF_INJECTED }, 16601 { WM_HOTKEY, sent|wparam, 5 }, 16602 { 0 } 16603 }; 16604 static const struct message WmHotkeyRelease[] = { 16605 { WM_KEYUP, kbd_hook|lparam, 0, LLKHF_INJECTED|LLKHF_UP }, 16606 { HCBT_KEYSKIPPED, hook|lparam|optional, 0, 0x80000001 }, 16607 { WM_KEYUP, sent|lparam, 0, 0x80000001 }, 16608 { 0 } 16609 }; 16610 static const struct message WmHotkeyReleaseLWIN[] = { 16611 { WM_KEYUP, kbd_hook|wparam|lparam, VK_LWIN, LLKHF_INJECTED|LLKHF_UP }, 16612 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_LWIN, 0xc0000001 }, 16613 { WM_KEYUP, sent|wparam|lparam, VK_LWIN, 0xc0000001 }, 16614 { 0 } 16615 }; 16616 static const struct message WmHotkeyCombined[] = { 16617 { WM_KEYDOWN, kbd_hook|wparam|lparam, VK_LWIN, LLKHF_INJECTED }, 16618 { WM_KEYDOWN, kbd_hook|lparam, 0, LLKHF_INJECTED }, 16619 { WM_KEYUP, kbd_hook|lparam, 0, LLKHF_INJECTED|LLKHF_UP }, 16620 { WM_KEYUP, kbd_hook|wparam|lparam, VK_LWIN, LLKHF_INJECTED|LLKHF_UP }, 16621 { WM_APP, sent, 0, 0 }, 16622 { WM_HOTKEY, sent|wparam, 5 }, 16623 { WM_APP+1, sent, 0, 0 }, 16624 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_LWIN, 1 }, 16625 { WM_KEYDOWN, sent|wparam|lparam, VK_LWIN, 1 }, 16626 { HCBT_KEYSKIPPED, hook|optional, 0, 0x80000001 }, 16627 { WM_KEYUP, sent, 0, 0x80000001 }, /* lparam not checked so the sequence isn't a todo */ 16628 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_LWIN, 0xc0000001 }, 16629 { WM_KEYUP, sent|wparam|lparam, VK_LWIN, 0xc0000001 }, 16630 { 0 } 16631 }; 16632 static const struct message WmHotkeyPrevious[] = { 16633 { WM_KEYDOWN, kbd_hook|wparam|lparam, VK_LWIN, LLKHF_INJECTED }, 16634 { WM_KEYDOWN, kbd_hook|lparam, 0, LLKHF_INJECTED }, 16635 { WM_KEYUP, kbd_hook|lparam, 0, LLKHF_INJECTED|LLKHF_UP }, 16636 { WM_KEYUP, kbd_hook|wparam|lparam, VK_LWIN, LLKHF_INJECTED|LLKHF_UP }, 16637 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_LWIN, 1 }, 16638 { WM_KEYDOWN, sent|wparam|lparam, VK_LWIN, 1 }, 16639 { HCBT_KEYSKIPPED, hook|lparam|optional, 0, 1 }, 16640 { WM_KEYDOWN, sent|lparam, 0, 1 }, 16641 { HCBT_KEYSKIPPED, hook|optional|lparam, 0, 0xc0000001 }, 16642 { WM_KEYUP, sent|lparam, 0, 0xc0000001 }, 16643 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_LWIN, 0xc0000001 }, 16644 { WM_KEYUP, sent|wparam|lparam, VK_LWIN, 0xc0000001 }, 16645 { 0 } 16646 }; 16647 static const struct message WmHotkeyNew[] = { 16648 { WM_KEYDOWN, kbd_hook|lparam, 0, LLKHF_INJECTED }, 16649 { WM_KEYUP, kbd_hook|lparam, 0, LLKHF_INJECTED|LLKHF_UP }, 16650 { WM_HOTKEY, sent|wparam, 5 }, 16651 { HCBT_KEYSKIPPED, hook|optional, 0, 0x80000001 }, 16652 { WM_KEYUP, sent, 0, 0x80000001 }, /* lparam not checked so the sequence isn't a todo */ 16653 { 0 } 16654 }; 16655 16656 static int hotkey_letter; 16657 16658 static LRESULT CALLBACK KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam) 16659 { 16660 struct recvd_message msg; 16661 16662 if (nCode == HC_ACTION) 16663 { 16664 KBDLLHOOKSTRUCT *kdbhookstruct = (KBDLLHOOKSTRUCT*)lParam; 16665 16666 msg.hwnd = 0; 16667 msg.message = wParam; 16668 msg.flags = kbd_hook|wparam|lparam; 16669 msg.wParam = kdbhookstruct->vkCode; 16670 msg.lParam = kdbhookstruct->flags; 16671 msg.descr = "KeyboardHookProc"; 16672 add_message(&msg); 16673 16674 if (wParam == WM_KEYUP || wParam == WM_KEYDOWN) 16675 { 16676 ok(kdbhookstruct->vkCode == VK_LWIN || kdbhookstruct->vkCode == hotkey_letter, 16677 "unexpected keycode %x\n", kdbhookstruct->vkCode); 16678 } 16679 } 16680 16681 return CallNextHookEx(hKBD_hook, nCode, wParam, lParam); 16682 } 16683 16684 static void test_hotkey(void) 16685 { 16686 HWND test_window, taskbar_window; 16687 BOOL ret; 16688 MSG msg; 16689 DWORD queue_status; 16690 SHORT key_state; 16691 16692 SetLastError(0xdeadbeef); 16693 ret = UnregisterHotKey(NULL, 0); 16694 if (ret == TRUE) 16695 { 16696 skip("hotkeys not supported\n"); 16697 return; 16698 } 16699 16700 ok(ret == FALSE, "expected FALSE, got %i\n", ret); 16701 ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED || broken(GetLastError() == 0xdeadbeef), 16702 "unexpected error %d\n", GetLastError()); 16703 16704 test_window = CreateWindowExA(0, "HotkeyWindowClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 16705 100, 100, 200, 200, 0, 0, 0, NULL); 16706 16707 flush_sequence(); 16708 16709 SetLastError(0xdeadbeef); 16710 ret = UnregisterHotKey(test_window, 0); 16711 ok(ret == FALSE, "expected FALSE, got %i\n", ret); 16712 ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED || broken(GetLastError() == 0xdeadbeef), 16713 "unexpected error %d\n", GetLastError()); 16714 16715 /* Search for a Windows Key + letter combination that hasn't been registered */ 16716 for (hotkey_letter = 0x41; hotkey_letter <= 0x51; hotkey_letter ++) 16717 { 16718 SetLastError(0xdeadbeef); 16719 ret = RegisterHotKey(test_window, 5, MOD_WIN, hotkey_letter); 16720 16721 if (ret == TRUE) 16722 { 16723 break; 16724 } 16725 else 16726 { 16727 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED || broken(GetLastError() == 0xdeadbeef), 16728 "unexpected error %d\n", GetLastError()); 16729 } 16730 } 16731 16732 if (hotkey_letter == 0x52) 16733 { 16734 ok(0, "Couldn't find any free Windows Key + letter combination\n"); 16735 goto end; 16736 } 16737 16738 hKBD_hook = SetWindowsHookExA(WH_KEYBOARD_LL, KeyboardHookProc, GetModuleHandleA(NULL), 0); 16739 if (!hKBD_hook) win_skip("WH_KEYBOARD_LL is not supported\n"); 16740 16741 /* Same key combination, different id */ 16742 SetLastError(0xdeadbeef); 16743 ret = RegisterHotKey(test_window, 4, MOD_WIN, hotkey_letter); 16744 ok(ret == FALSE, "expected FALSE, got %i\n", ret); 16745 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED || broken(GetLastError() == 0xdeadbeef), 16746 "unexpected error %d\n", GetLastError()); 16747 16748 /* Same key combination, different window */ 16749 SetLastError(0xdeadbeef); 16750 ret = RegisterHotKey(NULL, 5, MOD_WIN, hotkey_letter); 16751 ok(ret == FALSE, "expected FALSE, got %i\n", ret); 16752 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED || broken(GetLastError() == 0xdeadbeef), 16753 "unexpected error %d\n", GetLastError()); 16754 16755 /* Register the same hotkey twice */ 16756 SetLastError(0xdeadbeef); 16757 ret = RegisterHotKey(test_window, 5, MOD_WIN, hotkey_letter); 16758 ok(ret == FALSE, "expected FALSE, got %i\n", ret); 16759 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED || broken(GetLastError() == 0xdeadbeef), 16760 "unexpected error %d\n", GetLastError()); 16761 16762 /* Window on another thread */ 16763 taskbar_window = FindWindowA("Shell_TrayWnd", NULL); 16764 if (!taskbar_window) 16765 { 16766 skip("no taskbar?\n"); 16767 } 16768 else 16769 { 16770 SetLastError(0xdeadbeef); 16771 ret = RegisterHotKey(taskbar_window, 5, 0, hotkey_letter); 16772 ok(ret == FALSE, "expected FALSE, got %i\n", ret); 16773 ok(GetLastError() == ERROR_WINDOW_OF_OTHER_THREAD || broken(GetLastError() == 0xdeadbeef), 16774 "unexpected error %d\n", GetLastError()); 16775 } 16776 16777 /* Inject the appropriate key sequence */ 16778 keybd_event(VK_LWIN, 0, 0, 0); 16779 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 16780 DispatchMessageA(&msg); 16781 ok_sequence(WmHotkeyPressLWIN, "window hotkey press LWIN", FALSE); 16782 16783 keybd_event(hotkey_letter, 0, 0, 0); 16784 queue_status = GetQueueStatus(QS_HOTKEY); 16785 ok((queue_status & (QS_HOTKEY << 16)) == QS_HOTKEY << 16, "expected QS_HOTKEY << 16 set, got %x\n", queue_status); 16786 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 16787 { 16788 if (msg.message == WM_HOTKEY) 16789 { 16790 ok(msg.hwnd == test_window, "unexpected hwnd %p\n", msg.hwnd); 16791 ok(msg.lParam == MAKELPARAM(MOD_WIN, hotkey_letter), "unexpected WM_HOTKEY lparam %lx\n", msg.lParam); 16792 } 16793 DispatchMessageA(&msg); 16794 } 16795 ok_sequence(WmHotkeyPress, "window hotkey press", FALSE); 16796 16797 queue_status = GetQueueStatus(QS_HOTKEY); 16798 ok((queue_status & (QS_HOTKEY << 16)) == 0, "expected QS_HOTKEY << 16 cleared, got %x\n", queue_status); 16799 16800 key_state = GetAsyncKeyState(hotkey_letter); 16801 ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); 16802 16803 keybd_event(hotkey_letter, 0, KEYEVENTF_KEYUP, 0); 16804 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 16805 DispatchMessageA(&msg); 16806 ok_sequence(WmHotkeyRelease, "window hotkey release", TRUE); 16807 16808 keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP, 0); 16809 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 16810 DispatchMessageA(&msg); 16811 ok_sequence(WmHotkeyReleaseLWIN, "window hotkey release LWIN", FALSE); 16812 16813 /* normal posted WM_HOTKEY messages set QS_HOTKEY */ 16814 PostMessageA(test_window, WM_HOTKEY, 0, 0); 16815 queue_status = GetQueueStatus(QS_HOTKEY); 16816 ok((queue_status & (QS_HOTKEY << 16)) == QS_HOTKEY << 16, "expected QS_HOTKEY << 16 set, got %x\n", queue_status); 16817 queue_status = GetQueueStatus(QS_POSTMESSAGE); 16818 ok((queue_status & (QS_POSTMESSAGE << 16)) == QS_POSTMESSAGE << 16, "expected QS_POSTMESSAGE << 16 set, got %x\n", queue_status); 16819 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 16820 DispatchMessageA(&msg); 16821 flush_sequence(); 16822 16823 /* Send and process all messages at once */ 16824 PostMessageA(test_window, WM_APP, 0, 0); 16825 keybd_event(VK_LWIN, 0, 0, 0); 16826 keybd_event(hotkey_letter, 0, 0, 0); 16827 keybd_event(hotkey_letter, 0, KEYEVENTF_KEYUP, 0); 16828 keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP, 0); 16829 16830 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 16831 { 16832 if (msg.message == WM_HOTKEY) 16833 { 16834 ok(msg.hwnd == test_window, "unexpected hwnd %p\n", msg.hwnd); 16835 ok(msg.lParam == MAKELPARAM(MOD_WIN, hotkey_letter), "unexpected WM_HOTKEY lparam %lx\n", msg.lParam); 16836 } 16837 DispatchMessageA(&msg); 16838 } 16839 ok_sequence(WmHotkeyCombined, "window hotkey combined", FALSE); 16840 16841 /* Register same hwnd/id with different key combination */ 16842 ret = RegisterHotKey(test_window, 5, 0, hotkey_letter); 16843 ok(ret == TRUE, "expected TRUE, got %i, err=%d\n", ret, GetLastError()); 16844 16845 /* Previous key combination does not work */ 16846 keybd_event(VK_LWIN, 0, 0, 0); 16847 keybd_event(hotkey_letter, 0, 0, 0); 16848 keybd_event(hotkey_letter, 0, KEYEVENTF_KEYUP, 0); 16849 keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP, 0); 16850 16851 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 16852 DispatchMessageA(&msg); 16853 ok_sequence(WmHotkeyPrevious, "window hotkey previous", FALSE); 16854 16855 /* New key combination works */ 16856 keybd_event(hotkey_letter, 0, 0, 0); 16857 keybd_event(hotkey_letter, 0, KEYEVENTF_KEYUP, 0); 16858 16859 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 16860 { 16861 if (msg.message == WM_HOTKEY) 16862 { 16863 ok(msg.hwnd == test_window, "unexpected hwnd %p\n", msg.hwnd); 16864 ok(msg.lParam == MAKELPARAM(0, hotkey_letter), "unexpected WM_HOTKEY lparam %lx\n", msg.lParam); 16865 } 16866 DispatchMessageA(&msg); 16867 } 16868 ok_sequence(WmHotkeyNew, "window hotkey new", FALSE); 16869 16870 /* Unregister hotkey properly */ 16871 ret = UnregisterHotKey(test_window, 5); 16872 ok(ret == TRUE, "expected TRUE, got %i, err=%d\n", ret, GetLastError()); 16873 16874 /* Unregister hotkey again */ 16875 SetLastError(0xdeadbeef); 16876 ret = UnregisterHotKey(test_window, 5); 16877 ok(ret == FALSE, "expected FALSE, got %i\n", ret); 16878 ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED || broken(GetLastError() == 0xdeadbeef), 16879 "unexpected error %d\n", GetLastError()); 16880 16881 /* Register thread hotkey */ 16882 ret = RegisterHotKey(NULL, 5, MOD_WIN, hotkey_letter); 16883 ok(ret == TRUE, "expected TRUE, got %i, err=%d\n", ret, GetLastError()); 16884 16885 /* Inject the appropriate key sequence */ 16886 keybd_event(VK_LWIN, 0, 0, 0); 16887 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 16888 { 16889 ok(msg.hwnd != NULL, "unexpected thread message %x\n", msg.message); 16890 DispatchMessageA(&msg); 16891 } 16892 ok_sequence(WmHotkeyPressLWIN, "thread hotkey press LWIN", FALSE); 16893 16894 keybd_event(hotkey_letter, 0, 0, 0); 16895 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 16896 { 16897 if (msg.message == WM_HOTKEY) 16898 { 16899 struct recvd_message message; 16900 ok(msg.hwnd == NULL, "unexpected hwnd %p\n", msg.hwnd); 16901 ok(msg.lParam == MAKELPARAM(MOD_WIN, hotkey_letter), "unexpected WM_HOTKEY lparam %lx\n", msg.lParam); 16902 message.message = msg.message; 16903 message.flags = sent|wparam|lparam; 16904 message.wParam = msg.wParam; 16905 message.lParam = msg.lParam; 16906 message.descr = "test_hotkey thread message"; 16907 add_message(&message); 16908 } 16909 else 16910 ok(msg.hwnd != NULL, "unexpected thread message %x\n", msg.message); 16911 DispatchMessageA(&msg); 16912 } 16913 ok_sequence(WmHotkeyPress, "thread hotkey press", FALSE); 16914 16915 keybd_event(hotkey_letter, 0, KEYEVENTF_KEYUP, 0); 16916 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 16917 { 16918 ok(msg.hwnd != NULL, "unexpected thread message %x\n", msg.message); 16919 DispatchMessageA(&msg); 16920 } 16921 ok_sequence(WmHotkeyRelease, "thread hotkey release", TRUE); 16922 16923 keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP, 0); 16924 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 16925 { 16926 ros_skip_flaky 16927 ok(msg.hwnd != NULL, "unexpected thread message %x\n", msg.message); 16928 DispatchMessageA(&msg); 16929 } 16930 ok_sequence(WmHotkeyReleaseLWIN, "thread hotkey release LWIN", FALSE); 16931 16932 /* Unregister thread hotkey */ 16933 ret = UnregisterHotKey(NULL, 5); 16934 ok(ret == TRUE, "expected TRUE, got %i, err=%d\n", ret, GetLastError()); 16935 16936 if (hKBD_hook) UnhookWindowsHookEx(hKBD_hook); 16937 hKBD_hook = NULL; 16938 16939 end: 16940 UnregisterHotKey(NULL, 5); 16941 UnregisterHotKey(test_window, 5); 16942 DestroyWindow(test_window); 16943 flush_sequence(); 16944 } 16945 16946 16947 static const struct message WmSetFocus_1[] = { 16948 { HCBT_SETFOCUS, hook }, /* child */ 16949 { HCBT_ACTIVATE, hook }, /* parent */ 16950 { WM_QUERYNEWPALETTE, sent|wparam|lparam|parent|optional, 0, 0 }, 16951 { WM_WINDOWPOSCHANGING, sent|parent, 0, SWP_NOSIZE|SWP_NOMOVE }, 16952 { WM_ACTIVATEAPP, sent|wparam|parent, 1 }, 16953 { WM_NCACTIVATE, sent|parent }, 16954 { WM_GETTEXT, sent|defwinproc|parent|optional }, 16955 { WM_GETTEXT, sent|defwinproc|parent|optional }, 16956 { WM_ACTIVATE, sent|wparam|parent, 1 }, 16957 { HCBT_SETFOCUS, hook }, /* parent */ 16958 { WM_SETFOCUS, sent|defwinproc|parent }, 16959 { WM_KILLFOCUS, sent|parent }, 16960 { WM_SETFOCUS, sent }, 16961 { 0 } 16962 }; 16963 static const struct message WmSetFocus_2[] = { 16964 { HCBT_SETFOCUS, hook }, /* parent */ 16965 { WM_KILLFOCUS, sent }, 16966 { WM_SETFOCUS, sent|parent }, 16967 { 0 } 16968 }; 16969 static const struct message WmSetFocus_3[] = { 16970 { HCBT_SETFOCUS, hook }, /* child */ 16971 { 0 } 16972 }; 16973 16974 static void test_SetFocus(void) 16975 { 16976 HWND parent, old_parent, child, old_focus, old_active; 16977 MSG msg; 16978 struct wnd_event wnd_event; 16979 HANDLE hthread; 16980 DWORD ret, tid; 16981 16982 wnd_event.start_event = CreateEventW(NULL, 0, 0, NULL); 16983 ok(wnd_event.start_event != 0, "CreateEvent error %d\n", GetLastError()); 16984 hthread = CreateThread(NULL, 0, thread_proc, &wnd_event, 0, &tid); 16985 ok(hthread != 0, "CreateThread error %d\n", GetLastError()); 16986 ret = WaitForSingleObject(wnd_event.start_event, INFINITE); 16987 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 16988 CloseHandle(wnd_event.start_event); 16989 16990 parent = CreateWindowExA(0, "TestParentClass", NULL, WS_OVERLAPPEDWINDOW, 16991 0, 0, 0, 0, 0, 0, 0, NULL); 16992 ok(parent != 0, "failed to create parent window\n"); 16993 child = CreateWindowExA(0, "TestWindowClass", NULL, WS_CHILD, 16994 0, 0, 0, 0, parent, 0, 0, NULL); 16995 ok(child != 0, "failed to create child window\n"); 16996 16997 trace("parent %p, child %p, thread window %p\n", parent, child, wnd_event.hwnd); 16998 16999 SetFocus(0); 17000 SetActiveWindow(0); 17001 17002 flush_events(); 17003 flush_sequence(); 17004 17005 ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow()); 17006 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus()); 17007 17008 log_all_parent_messages++; 17009 17010 old_focus = SetFocus(child); 17011 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 17012 ok_sequence(WmSetFocus_1, "SetFocus on a child window", TRUE); 17013 ok(old_focus == parent, "expected old focus %p, got %p\n", parent, old_focus); 17014 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 17015 ok(GetFocus() == child, "expected focus %p, got %p\n", child, GetFocus()); 17016 17017 old_focus = SetFocus(parent); 17018 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 17019 ok_sequence(WmSetFocus_2, "SetFocus on a parent window", FALSE); 17020 ok(old_focus == child, "expected old focus %p, got %p\n", child, old_focus); 17021 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 17022 ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); 17023 17024 SetLastError(0xdeadbeef); 17025 old_focus = SetFocus((HWND)0xdeadbeef); 17026 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || broken(GetLastError() == 0xdeadbeef), 17027 "expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError()); 17028 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 17029 ok_sequence(WmEmptySeq, "SetFocus on an invalid window", FALSE); 17030 ok(old_focus == 0, "expected old focus 0, got %p\n", old_focus); 17031 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 17032 ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); 17033 17034 SetLastError(0xdeadbeef); 17035 old_focus = SetFocus(GetDesktopWindow()); 17036 ok(GetLastError() == ERROR_ACCESS_DENIED /* Vista+ */ || 17037 broken(GetLastError() == 0xdeadbeef), "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); 17038 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 17039 ok_sequence(WmEmptySeq, "SetFocus on a desktop window", TRUE); 17040 ok(old_focus == 0, "expected old focus 0, got %p\n", old_focus); 17041 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 17042 ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); 17043 17044 SetLastError(0xdeadbeef); 17045 old_focus = SetFocus(wnd_event.hwnd); 17046 ok(GetLastError() == ERROR_ACCESS_DENIED /* Vista+ */ || 17047 broken(GetLastError() == 0xdeadbeef), "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); 17048 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 17049 ok_sequence(WmEmptySeq, "SetFocus on another thread window", TRUE); 17050 ok(old_focus == 0, "expected old focus 0, got %p\n", old_focus); 17051 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 17052 ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); 17053 17054 SetLastError(0xdeadbeef); 17055 old_active = SetActiveWindow((HWND)0xdeadbeef); 17056 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || broken(GetLastError() == 0xdeadbeef), 17057 "expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError()); 17058 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 17059 ok_sequence(WmEmptySeq, "SetActiveWindow on an invalid window", FALSE); 17060 ok(old_active == 0, "expected old focus 0, got %p\n", old_active); 17061 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 17062 ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); 17063 17064 SetLastError(0xdeadbeef); 17065 old_active = SetActiveWindow(GetDesktopWindow()); 17066 todo_wine 17067 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError()); 17068 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 17069 ok_sequence(WmEmptySeq, "SetActiveWindow on a desktop window", TRUE); 17070 ok(old_active == 0, "expected old focus 0, got %p\n", old_focus); 17071 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 17072 ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); 17073 17074 SetLastError(0xdeadbeef); 17075 old_active = SetActiveWindow(wnd_event.hwnd); 17076 todo_wine 17077 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError()); 17078 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 17079 ok_sequence(WmEmptySeq, "SetActiveWindow on another thread window", TRUE); 17080 ok(old_active == 0, "expected old focus 0, got %p\n", old_active); 17081 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 17082 ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); 17083 17084 SetLastError(0xdeadbeef); 17085 ret = AttachThreadInput(GetCurrentThreadId(), tid, TRUE); 17086 ok(ret, "AttachThreadInput error %d\n", GetLastError()); 17087 17088 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 17089 ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); 17090 17091 flush_events(); 17092 flush_sequence(); 17093 17094 old_focus = SetFocus(wnd_event.hwnd); 17095 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 17096 ok(old_focus == wnd_event.hwnd, "expected old focus %p, got %p\n", wnd_event.hwnd, old_focus); 17097 ok(GetActiveWindow() == wnd_event.hwnd, "expected active %p, got %p\n", wnd_event.hwnd, GetActiveWindow()); 17098 ok(GetFocus() == wnd_event.hwnd, "expected focus %p, got %p\n", wnd_event.hwnd, GetFocus()); 17099 17100 old_focus = SetFocus(parent); 17101 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 17102 ok(old_focus == parent, "expected old focus %p, got %p\n", parent, old_focus); 17103 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 17104 ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); 17105 17106 flush_events(); 17107 flush_sequence(); 17108 17109 old_active = SetActiveWindow(wnd_event.hwnd); 17110 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 17111 ok(old_active == parent, "expected old focus %p, got %p\n", parent, old_active); 17112 ok(GetActiveWindow() == wnd_event.hwnd, "expected active %p, got %p\n", wnd_event.hwnd, GetActiveWindow()); 17113 ok(GetFocus() == wnd_event.hwnd, "expected focus %p, got %p\n", wnd_event.hwnd, GetFocus()); 17114 17115 SetLastError(0xdeadbeef); 17116 ret = AttachThreadInput(GetCurrentThreadId(), tid, FALSE); 17117 ok(ret, "AttachThreadInput error %d\n", GetLastError()); 17118 17119 ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow()); 17120 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus()); 17121 17122 old_parent = SetParent(child, GetDesktopWindow()); 17123 ok(old_parent == parent, "expected old parent %p, got %p\n", parent, old_parent); 17124 17125 ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow()); 17126 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus()); 17127 17128 old_focus = SetFocus(parent); 17129 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 17130 ok(old_focus == parent, "expected old focus %p, got %p\n", parent, old_focus); 17131 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 17132 ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); 17133 17134 flush_events(); 17135 flush_sequence(); 17136 17137 SetLastError(0xdeadbeef); 17138 old_focus = SetFocus(child); 17139 todo_wine 17140 ok(GetLastError() == ERROR_INVALID_PARAMETER /* Vista+ */ || 17141 broken(GetLastError() == 0) /* XP */ || 17142 broken(GetLastError() == 0xdeadbeef), "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 17143 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 17144 ok_sequence(WmSetFocus_3, "SetFocus on a child window", TRUE); 17145 ok(old_focus == 0, "expected old focus 0, got %p\n", old_focus); 17146 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 17147 ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); 17148 17149 SetLastError(0xdeadbeef); 17150 old_active = SetActiveWindow(child); 17151 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError()); 17152 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 17153 ok_sequence(WmEmptySeq, "SetActiveWindow on a child window", FALSE); 17154 ok(old_active == parent, "expected old active %p, got %p\n", parent, old_active); 17155 ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); 17156 ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); 17157 17158 log_all_parent_messages--; 17159 17160 DestroyWindow(child); 17161 DestroyWindow(parent); 17162 17163 ret = PostMessageA(wnd_event.hwnd, WM_QUIT, 0, 0); 17164 ok(ret, "PostMessage(WM_QUIT) error %d\n", GetLastError()); 17165 ret = WaitForSingleObject(hthread, INFINITE); 17166 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 17167 CloseHandle(hthread); 17168 } 17169 17170 static const struct message WmSetLayeredStyle[] = { 17171 { WM_STYLECHANGING, sent }, 17172 { WM_STYLECHANGED, sent }, 17173 { WM_GETTEXT, sent|defwinproc|optional }, 17174 { 0 } 17175 }; 17176 17177 static const struct message WmSetLayeredStyle2[] = { 17178 { WM_STYLECHANGING, sent }, 17179 { WM_STYLECHANGED, sent }, 17180 { WM_WINDOWPOSCHANGING, sent|optional|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 17181 { WM_NCCALCSIZE, sent|optional|wparam|defwinproc, 1 }, 17182 { WM_WINDOWPOSCHANGED, sent|optional|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, 17183 { WM_MOVE, sent|optional|defwinproc|wparam, 0 }, 17184 { WM_SIZE, sent|optional|defwinproc|wparam, SIZE_RESTORED }, 17185 { 0 } 17186 }; 17187 17188 struct layered_window_info 17189 { 17190 HWND hwnd; 17191 HDC hdc; 17192 SIZE size; 17193 HANDLE event; 17194 BOOL ret; 17195 }; 17196 17197 static DWORD CALLBACK update_layered_proc( void *param ) 17198 { 17199 struct layered_window_info *info = param; 17200 POINT src = { 0, 0 }; 17201 17202 info->ret = pUpdateLayeredWindow( info->hwnd, 0, NULL, &info->size, 17203 info->hdc, &src, 0, NULL, ULW_OPAQUE ); 17204 ok( info->ret, "failed\n"); 17205 SetEvent( info->event ); 17206 return 0; 17207 } 17208 17209 static void test_layered_window(void) 17210 { 17211 HWND hwnd; 17212 HDC hdc; 17213 HBITMAP bmp; 17214 BOOL ret; 17215 SIZE size; 17216 POINT pos, src; 17217 RECT rect, client; 17218 HANDLE thread; 17219 DWORD tid; 17220 struct layered_window_info info; 17221 17222 if (!pUpdateLayeredWindow) 17223 { 17224 win_skip( "UpdateLayeredWindow not supported\n" ); 17225 return; 17226 } 17227 17228 hdc = CreateCompatibleDC( 0 ); 17229 bmp = CreateCompatibleBitmap( hdc, 300, 300 ); 17230 SelectObject( hdc, bmp ); 17231 17232 hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_CAPTION | WS_THICKFRAME | WS_SYSMENU, 17233 100, 100, 300, 300, 0, 0, 0, NULL); 17234 ok( hwnd != 0, "failed to create window\n" ); 17235 ShowWindow( hwnd, SW_SHOWNORMAL ); 17236 UpdateWindow( hwnd ); 17237 flush_events(); 17238 flush_sequence(); 17239 17240 GetWindowRect( hwnd, &rect ); 17241 GetClientRect( hwnd, &client ); 17242 ok( client.right < rect.right - rect.left, "wrong client area\n" ); 17243 ok( client.bottom < rect.bottom - rect.top, "wrong client area\n" ); 17244 17245 src.x = src.y = 0; 17246 pos.x = pos.y = 300; 17247 size.cx = size.cy = 250; 17248 ret = pUpdateLayeredWindow( hwnd, 0, &pos, &size, hdc, &src, 0, NULL, ULW_OPAQUE ); 17249 ok( !ret, "UpdateLayeredWindow should fail on non-layered window\n" ); 17250 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() ); 17251 SetWindowLongA( hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED ); 17252 ok_sequence( WmSetLayeredStyle, "WmSetLayeredStyle", FALSE ); 17253 17254 ret = pUpdateLayeredWindow( hwnd, 0, &pos, &size, hdc, &src, 0, NULL, ULW_OPAQUE ); 17255 ok( ret, "UpdateLayeredWindow failed err %u\n", GetLastError() ); 17256 ok_sequence( WmEmptySeq, "UpdateLayeredWindow", FALSE ); 17257 GetWindowRect( hwnd, &rect ); 17258 ok( rect.left == 300 && rect.top == 300 && rect.right == 550 && rect.bottom == 550, 17259 "wrong window rect %s\n", wine_dbgstr_rect( &rect )); 17260 GetClientRect( hwnd, &rect ); 17261 ok( rect.right == client.right - 50 && rect.bottom == client.bottom - 50, 17262 "wrong client rect %s\n", wine_dbgstr_rect( &rect )); 17263 17264 size.cx = 150; 17265 pos.y = 200; 17266 ret = pUpdateLayeredWindow( hwnd, 0, &pos, &size, hdc, &src, 0, NULL, ULW_OPAQUE ); 17267 ok( ret, "UpdateLayeredWindow failed err %u\n", GetLastError() ); 17268 ok_sequence( WmEmptySeq, "UpdateLayeredWindow", FALSE ); 17269 GetWindowRect( hwnd, &rect ); 17270 ok( rect.left == 300 && rect.top == 200 && rect.right == 450 && rect.bottom == 450, 17271 "wrong window rect %s\n", wine_dbgstr_rect( &rect )); 17272 GetClientRect( hwnd, &rect ); 17273 ok( rect.right == client.right - 150 && rect.bottom == client.bottom - 50, 17274 "wrong client rect %s\n", wine_dbgstr_rect( &rect )); 17275 17276 SetWindowLongA( hwnd, GWL_STYLE, 17277 GetWindowLongA(hwnd, GWL_STYLE) & ~(WS_CAPTION | WS_THICKFRAME | WS_SYSMENU) ); 17278 ok_sequence( WmSetLayeredStyle2, "WmSetLayeredStyle2", FALSE ); 17279 17280 size.cx = 200; 17281 pos.x = 200; 17282 ret = pUpdateLayeredWindow( hwnd, 0, &pos, &size, hdc, &src, 0, NULL, ULW_OPAQUE ); 17283 ok( ret, "UpdateLayeredWindow failed err %u\n", GetLastError() ); 17284 ok_sequence( WmEmptySeq, "UpdateLayeredWindow", FALSE ); 17285 GetWindowRect( hwnd, &rect ); 17286 ok( rect.left == 200 && rect.top == 200 && rect.right == 400 && rect.bottom == 450, 17287 "wrong window rect %s\n", wine_dbgstr_rect( &rect )); 17288 GetClientRect( hwnd, &rect ); 17289 ok( (rect.right == 200 && rect.bottom == 250) || 17290 broken(rect.right == client.right - 100 && rect.bottom == client.bottom - 50), 17291 "wrong client rect %s\n", wine_dbgstr_rect( &rect )); 17292 17293 size.cx = 0; 17294 ret = pUpdateLayeredWindow( hwnd, 0, &pos, &size, hdc, &src, 0, NULL, ULW_OPAQUE ); 17295 ok( !ret, "UpdateLayeredWindow should fail on non-layered window\n" ); 17296 ok( GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == ERROR_MR_MID_NOT_FOUND) || 17297 broken(GetLastError() == ERROR_GEN_FAILURE) /* win7 */, "wrong error %u\n", GetLastError() ); 17298 size.cx = 1; 17299 size.cy = -1; 17300 ret = pUpdateLayeredWindow( hwnd, 0, &pos, &size, hdc, &src, 0, NULL, ULW_OPAQUE ); 17301 ok( !ret, "UpdateLayeredWindow should fail on non-layered window\n" ); 17302 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() ); 17303 17304 SetWindowLongA( hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) & ~WS_EX_LAYERED ); 17305 ok_sequence( WmSetLayeredStyle, "WmSetLayeredStyle", FALSE ); 17306 GetWindowRect( hwnd, &rect ); 17307 ok( rect.left == 200 && rect.top == 200 && rect.right == 400 && rect.bottom == 450, 17308 "wrong window rect %s\n", wine_dbgstr_rect( &rect )); 17309 GetClientRect( hwnd, &rect ); 17310 ok( (rect.right == 200 && rect.bottom == 250) || 17311 broken(rect.right == client.right - 100 && rect.bottom == client.bottom - 50), 17312 "wrong client rect %s\n", wine_dbgstr_rect( &rect )); 17313 17314 SetWindowLongA( hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED ); 17315 info.hwnd = hwnd; 17316 info.hdc = hdc; 17317 info.size.cx = 250; 17318 info.size.cy = 300; 17319 info.event = CreateEventA( NULL, TRUE, FALSE, NULL ); 17320 info.ret = FALSE; 17321 thread = CreateThread( NULL, 0, update_layered_proc, &info, 0, &tid ); 17322 ok( WaitForSingleObject( info.event, 1000 ) == 0, "wait failed\n" ); 17323 ok( info.ret, "UpdateLayeredWindow failed in other thread\n" ); 17324 WaitForSingleObject( thread, 1000 ); 17325 CloseHandle( thread ); 17326 GetWindowRect( hwnd, &rect ); 17327 ok( rect.left == 200 && rect.top == 200 && rect.right == 450 && rect.bottom == 500, 17328 "wrong window rect %s\n", wine_dbgstr_rect( &rect )); 17329 GetClientRect( hwnd, &rect ); 17330 ok( (rect.right == 250 && rect.bottom == 300) || 17331 broken(rect.right == client.right - 50 && rect.bottom == client.bottom), 17332 "wrong client rect %s\n", wine_dbgstr_rect( &rect )); 17333 17334 DestroyWindow( hwnd ); 17335 DeleteDC( hdc ); 17336 DeleteObject( bmp ); 17337 } 17338 17339 static HMENU hpopupmenu; 17340 17341 static LRESULT WINAPI cancel_popup_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 17342 { 17343 if (ignore_message( message )) return 0; 17344 17345 switch (message) { 17346 case WM_ENTERIDLE: 17347 todo_wine ok(GetCapture() == hwnd, "expected %p, got %p\n", hwnd, GetCapture()); 17348 EndMenu(); 17349 break; 17350 case WM_INITMENU: 17351 case WM_INITMENUPOPUP: 17352 case WM_UNINITMENUPOPUP: 17353 ok((HMENU)wParam == hpopupmenu, "expected %p, got %lx\n", hpopupmenu, wParam); 17354 break; 17355 case WM_CAPTURECHANGED: 17356 todo_wine ok(!lParam || (HWND)lParam == hwnd, "lost capture to %lx\n", lParam); 17357 break; 17358 } 17359 17360 return MsgCheckProc (FALSE, hwnd, message, wParam, lParam); 17361 } 17362 17363 static LRESULT WINAPI cancel_init_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 17364 { 17365 if (ignore_message( message )) return 0; 17366 17367 switch (message) { 17368 case WM_ENTERMENULOOP: 17369 ok(EndMenu() == TRUE, "EndMenu() failed\n"); 17370 break; 17371 } 17372 17373 return MsgCheckProc (FALSE, hwnd, message, wParam, lParam); 17374 } 17375 17376 static void test_TrackPopupMenu(void) 17377 { 17378 MSG msg; 17379 HWND hwnd; 17380 BOOL ret; 17381 17382 hwnd = CreateWindowExA(0, "TestWindowClass", NULL, 0, 17383 0, 0, 1, 1, 0, 17384 NULL, NULL, 0); 17385 ok(hwnd != NULL, "CreateWindowEx failed with error %d\n", GetLastError()); 17386 17387 SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (LONG_PTR)cancel_popup_proc); 17388 17389 hpopupmenu = CreatePopupMenu(); 17390 ok(hpopupmenu != NULL, "CreateMenu failed with error %d\n", GetLastError()); 17391 17392 AppendMenuA(hpopupmenu, MF_STRING, 100, "item 1"); 17393 AppendMenuA(hpopupmenu, MF_STRING, 100, "item 2"); 17394 17395 flush_events(); 17396 flush_sequence(); 17397 ret = TrackPopupMenu(hpopupmenu, 0, 100,100, 0, hwnd, NULL); 17398 ok_sequence(WmTrackPopupMenu, "TrackPopupMenu", TRUE); 17399 ok(ret == 1, "TrackPopupMenu failed with error %i\n", GetLastError()); 17400 17401 /* Test popup closing with an ESC-press */ 17402 flush_events(); 17403 PostMessageW(hwnd, WM_KEYDOWN, VK_ESCAPE, 0); 17404 ret = TrackPopupMenu(hpopupmenu, 0, 100,100, 0, hwnd, NULL); 17405 ok(ret == 1, "TrackPopupMenu failed with error %i\n", GetLastError()); 17406 PostQuitMessage(0); 17407 flush_sequence(); 17408 while ( PeekMessageA(&msg, 0, 0, 0, PM_REMOVE) ) 17409 { 17410 TranslateMessage(&msg); 17411 DispatchMessageA(&msg); 17412 } 17413 ok_sequence(WmTrackPopupMenuEsc, "TrackPopupMenuEsc", FALSE); /* Shouldn't get any message */ 17414 17415 SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (LONG_PTR)cancel_init_proc); 17416 17417 flush_events(); 17418 flush_sequence(); 17419 ret = TrackPopupMenu(hpopupmenu, 0, 100,100, 0, hwnd, NULL); 17420 ok_sequence(WmTrackPopupMenuAbort, "WmTrackPopupMenuAbort", TRUE); 17421 ok(ret == TRUE, "TrackPopupMenu failed\n"); 17422 17423 SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (LONG_PTR)cancel_popup_proc); 17424 17425 SetCapture(hwnd); 17426 17427 flush_events(); 17428 flush_sequence(); 17429 ret = TrackPopupMenu(hpopupmenu, 0, 100,100, 0, hwnd, NULL); 17430 ok_sequence(WmTrackPopupMenuCapture, "TrackPopupMenuCapture", TRUE); 17431 ok(ret == 1, "TrackPopupMenuCapture failed with error %i\n", GetLastError()); 17432 17433 DestroyMenu(hpopupmenu); 17434 DestroyWindow(hwnd); 17435 } 17436 17437 static void test_TrackPopupMenuEmpty(void) 17438 { 17439 HWND hwnd; 17440 BOOL ret; 17441 17442 hwnd = CreateWindowExA(0, "TestWindowClass", NULL, 0, 17443 0, 0, 1, 1, 0, 17444 NULL, NULL, 0); 17445 ok(hwnd != NULL, "CreateWindowEx failed with error %d\n", GetLastError()); 17446 17447 SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (LONG_PTR)cancel_popup_proc); 17448 17449 hpopupmenu = CreatePopupMenu(); 17450 ok(hpopupmenu != NULL, "CreateMenu failed with error %d\n", GetLastError()); 17451 17452 flush_events(); 17453 flush_sequence(); 17454 ret = TrackPopupMenu(hpopupmenu, 0, 100,100, 0, hwnd, NULL); 17455 ok_sequence(WmTrackPopupMenuEmpty, "TrackPopupMenuEmpty", TRUE); 17456 ok(ret == 0, "TrackPopupMenu succeeded\n"); 17457 17458 DestroyMenu(hpopupmenu); 17459 DestroyWindow(hwnd); 17460 } 17461 17462 static const struct message send_message_1[] = { 17463 { WM_USER+2, sent|wparam|lparam, 0, 0 }, 17464 { WM_USER, sent|wparam|lparam, 0, 0 }, 17465 { 0 } 17466 }; 17467 static const struct message send_message_2[] = { 17468 { WM_USER+4, sent|wparam|lparam, 0, 0 }, 17469 { 0 } 17470 }; 17471 static const struct message send_message_3[] = { 17472 { WM_USER+3, sent|wparam|lparam, 0, 0 }, 17473 { WM_USER+1, sent|wparam|lparam, 0, 0 }, 17474 { 0 } 17475 }; 17476 17477 static DWORD WINAPI SendMessage_thread_1(void *param) 17478 { 17479 struct wnd_event *wnd_event = param; 17480 17481 trace("thread: starting\n"); 17482 WaitForSingleObject(wnd_event->start_event, INFINITE); 17483 17484 trace("thread: call PostMessage\n"); 17485 PostMessageA(wnd_event->hwnd, WM_USER, 0, 0); 17486 17487 trace("thread: call PostMessage\n"); 17488 PostMessageA(wnd_event->hwnd, WM_USER+1, 0, 0); 17489 17490 trace("thread: call SendMessage\n"); 17491 SendMessageA(wnd_event->hwnd, WM_USER+2, 0, 0); 17492 17493 trace("thread: call SendMessage\n"); 17494 SendMessageA(wnd_event->hwnd, WM_USER+3, 0, 0); 17495 17496 return 0; 17497 } 17498 17499 static DWORD WINAPI SendMessage_thread_2(void *param) 17500 { 17501 struct wnd_event *wnd_event = param; 17502 17503 trace("thread: starting\n"); 17504 WaitForSingleObject(wnd_event->start_event, INFINITE); 17505 17506 trace("thread: call PostMessage\n"); 17507 PostMessageA(wnd_event->hwnd, WM_USER, 0, 0); 17508 17509 trace("thread: call PostMessage\n"); 17510 PostMessageA(wnd_event->hwnd, WM_USER+1, 0, 0); 17511 17512 /* this leads to sending an internal message under Wine */ 17513 trace("thread: call SetParent\n"); 17514 SetParent(wnd_event->hwnd, wnd_event->hwnd); 17515 17516 trace("thread: call SendMessage\n"); 17517 SendMessageA(wnd_event->hwnd, WM_USER+2, 0, 0); 17518 17519 trace("thread: call SendMessage\n"); 17520 SendMessageA(wnd_event->hwnd, WM_USER+3, 0, 0); 17521 17522 return 0; 17523 } 17524 17525 static void test_SendMessage_other_thread(int thread_n) 17526 { 17527 DWORD qs_all_input = QS_ALLINPUT & ~QS_RAWINPUT; 17528 HANDLE hthread; 17529 struct wnd_event wnd_event; 17530 DWORD tid, ret; 17531 MSG msg; 17532 17533 wnd_event.start_event = CreateEventA(NULL, 0, 0, NULL); 17534 17535 wnd_event.hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, 17536 100, 100, 200, 200, 0, 0, 0, NULL); 17537 ok(wnd_event.hwnd != 0, "CreateWindowEx failed\n"); 17538 17539 hthread = CreateThread(NULL, 0, thread_n == 1 ? SendMessage_thread_1 : SendMessage_thread_2, &wnd_event, 0, &tid); 17540 ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError()); 17541 CloseHandle(hthread); 17542 17543 flush_events(); 17544 flush_sequence(); 17545 17546 ret = GetQueueStatus(QS_SENDMESSAGE); 17547 ok(ret == 0, "wrong status %08x\n", ret); 17548 17549 SetEvent(wnd_event.start_event); 17550 17551 /* wait for other thread's SendMessage */ 17552 for (;;) 17553 { 17554 ret = GetQueueStatus(QS_SENDMESSAGE); 17555 if (ret == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE)) break; 17556 Sleep(50); 17557 } 17558 17559 ret = GetQueueStatus(QS_SENDMESSAGE|QS_POSTMESSAGE); 17560 ok(ret == MAKELONG(QS_POSTMESSAGE, QS_SENDMESSAGE|QS_POSTMESSAGE), "wrong status %08x\n", ret); 17561 17562 trace("main: call GetMessage\n"); 17563 GetMessageA(&msg, 0, 0, 0); 17564 ok(msg.message == WM_USER, "expected WM_USER, got %04x\n", msg.message); 17565 DispatchMessageA(&msg); 17566 ok_sequence(send_message_1, "SendMessage from other thread 1", thread_n == 2); 17567 17568 /* intentionally yield */ 17569 MsgWaitForMultipleObjects(0, NULL, FALSE, 100, qs_all_input); 17570 17571 trace("main: call SendMessage\n"); 17572 SendMessageA(wnd_event.hwnd, WM_USER+4, 0, 0); 17573 ok_sequence(send_message_2, "SendMessage from other thread 2", FALSE); 17574 17575 ret = GetQueueStatus(QS_SENDMESSAGE|QS_POSTMESSAGE); 17576 ok(ret == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_POSTMESSAGE), "wrong status %08x\n", ret); 17577 17578 trace("main: call PeekMessage\n"); 17579 ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "PeekMessage should not fail\n"); 17580 ok(msg.message == WM_USER+1, "expected WM_USER+1, got %04x\n", msg.message); 17581 DispatchMessageA(&msg); 17582 ok_sequence(send_message_3, "SendMessage from other thread 3", thread_n == 2); 17583 17584 /* intentionally yield */ 17585 MsgWaitForMultipleObjects(0, NULL, FALSE, 100, qs_all_input); 17586 17587 ret = GetQueueStatus(QS_SENDMESSAGE|QS_POSTMESSAGE); 17588 /* FIXME: remove once Wine is fixed */ 17589 todo_wine_if (thread_n == 2) 17590 ok(ret == 0, "wrong status %08x\n", ret); 17591 17592 trace("main: call PeekMessage\n"); 17593 ok(!PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "PeekMessage should fail\n"); 17594 ok_sequence(WmEmptySeq, "SendMessage from other thread 5", thread_n == 2); 17595 17596 ret = GetQueueStatus(QS_SENDMESSAGE|QS_POSTMESSAGE); 17597 ok(ret == 0, "wrong status %08x\n", ret); 17598 17599 trace("main: call DestroyWindow\n"); 17600 DestroyWindow(msg.hwnd); 17601 17602 flush_events(); 17603 flush_sequence(); 17604 } 17605 17606 static LRESULT CALLBACK insendmessage_wnd_proc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ) 17607 { 17608 DWORD flags = InSendMessageEx( NULL ); 17609 BOOL ret; 17610 17611 switch (msg) 17612 { 17613 case WM_USER: 17614 ok( flags == ISMEX_SEND, "wrong flags %x\n", flags ); 17615 ok( InSendMessage(), "InSendMessage returned false\n" ); 17616 ret = ReplyMessage( msg ); 17617 ok( ret, "ReplyMessage failed err %u\n", GetLastError() ); 17618 flags = InSendMessageEx( NULL ); 17619 ok( flags == (ISMEX_SEND | ISMEX_REPLIED), "wrong flags %x\n", flags ); 17620 ok( InSendMessage(), "InSendMessage returned false\n" ); 17621 break; 17622 case WM_USER + 1: 17623 ok( flags == ISMEX_NOTIFY, "wrong flags %x\n", flags ); 17624 ok( InSendMessage(), "InSendMessage returned false\n" ); 17625 ret = ReplyMessage( msg ); 17626 ok( ret, "ReplyMessage failed err %u\n", GetLastError() ); 17627 flags = InSendMessageEx( NULL ); 17628 ok( flags == ISMEX_NOTIFY, "wrong flags %x\n", flags ); 17629 ok( InSendMessage(), "InSendMessage returned false\n" ); 17630 break; 17631 case WM_USER + 2: 17632 ok( flags == ISMEX_CALLBACK, "wrong flags %x\n", flags ); 17633 ok( InSendMessage(), "InSendMessage returned false\n" ); 17634 ret = ReplyMessage( msg ); 17635 ok( ret, "ReplyMessage failed err %u\n", GetLastError() ); 17636 flags = InSendMessageEx( NULL ); 17637 ok( flags == (ISMEX_CALLBACK | ISMEX_REPLIED) || flags == ISMEX_SEND, "wrong flags %x\n", flags ); 17638 ok( InSendMessage(), "InSendMessage returned false\n" ); 17639 break; 17640 case WM_USER + 3: 17641 ok( flags == ISMEX_NOSEND, "wrong flags %x\n", flags ); 17642 ok( !InSendMessage(), "InSendMessage returned true\n" ); 17643 ret = ReplyMessage( msg ); 17644 ok( !ret, "ReplyMessage succeeded\n" ); 17645 break; 17646 } 17647 17648 return DefWindowProcA( hwnd, msg, wp, lp ); 17649 } 17650 17651 static void CALLBACK msg_callback( HWND hwnd, UINT msg, ULONG_PTR arg, LRESULT result ) 17652 { 17653 ok( msg == WM_USER + 2, "wrong msg %x\n", msg ); 17654 ok( result == WM_USER + 2, "wrong result %lx\n", result ); 17655 } 17656 17657 static DWORD WINAPI send_message_thread( void *arg ) 17658 { 17659 HWND win = arg; 17660 17661 SendMessageA( win, WM_USER, 0, 0 ); 17662 SendNotifyMessageA( win, WM_USER + 1, 0, 0 ); 17663 SendMessageCallbackA( win, WM_USER + 2, 0, 0, msg_callback, 0 ); 17664 PostMessageA( win, WM_USER + 3, 0, 0 ); 17665 PostMessageA( win, WM_QUIT, 0, 0 ); 17666 return 0; 17667 } 17668 17669 static void test_InSendMessage(void) 17670 { 17671 WNDCLASSA cls; 17672 HWND win; 17673 MSG msg; 17674 HANDLE thread; 17675 DWORD tid; 17676 17677 memset(&cls, 0, sizeof(cls)); 17678 cls.lpfnWndProc = insendmessage_wnd_proc; 17679 cls.hInstance = GetModuleHandleA(NULL); 17680 cls.lpszClassName = "InSendMessage_test"; 17681 RegisterClassA(&cls); 17682 17683 win = CreateWindowA( "InSendMessage_test", NULL, 0, 0, 0, 0, 0, NULL, 0, NULL, 0 ); 17684 ok( win != NULL, "CreateWindow failed: %d\n", GetLastError() ); 17685 17686 thread = CreateThread( NULL, 0, send_message_thread, win, 0, &tid ); 17687 ok( thread != NULL, "CreateThread failed: %d\n", GetLastError() ); 17688 17689 while (GetMessageA(&msg, NULL, 0, 0)) DispatchMessageA( &msg ); 17690 17691 ok( WaitForSingleObject( thread, 30000 ) == WAIT_OBJECT_0, "WaitForSingleObject failed\n" ); 17692 CloseHandle( thread ); 17693 17694 DestroyWindow( win ); 17695 UnregisterClassA( "InSendMessage_test", GetModuleHandleA(NULL) ); 17696 } 17697 17698 static const struct message DoubleSetCaptureSeq[] = 17699 { 17700 { WM_CAPTURECHANGED, sent }, 17701 { 0 } 17702 }; 17703 17704 static void test_DoubleSetCapture(void) 17705 { 17706 HWND hwnd; 17707 17708 hwnd = CreateWindowExA(0, "TestWindowClass", "Test DoubleSetCapture", 17709 WS_OVERLAPPEDWINDOW | WS_VISIBLE, 17710 100, 100, 200, 200, 0, 0, 0, NULL); 17711 ok (hwnd != 0, "Failed to create overlapped window\n"); 17712 17713 ShowWindow( hwnd, SW_SHOW ); 17714 UpdateWindow( hwnd ); 17715 flush_events(); 17716 flush_sequence(); 17717 17718 SetCapture( hwnd ); 17719 SetCapture( hwnd ); 17720 ok_sequence(DoubleSetCaptureSeq, "SetCapture( hwnd ) twice", FALSE); 17721 17722 DestroyWindow(hwnd); 17723 } 17724 17725 static const struct message WmRestoreMinimizedSeq[] = 17726 { 17727 { HCBT_ACTIVATE, hook }, 17728 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE }, 17729 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, 17730 { WM_ACTIVATEAPP, sent|wparam, 1 }, 17731 { WM_NCACTIVATE, sent|wparam, 0x200001 }, 17732 { WM_GETTEXT, sent|defwinproc|optional }, 17733 { WM_ACTIVATE, sent|wparam, 0x200001 }, /* Note that activate messages are after WM_WINDOWPOSCHANGED and before WM_SYSCOMMAND */ 17734 { HCBT_KEYSKIPPED, hook|optional }, 17735 { WM_SYSKEYUP, sent|optional }, 17736 { WM_SYSCOMMAND, sent|wparam, SC_RESTORE }, 17737 { HCBT_SYSCOMMAND, hook|wparam, SC_RESTORE }, 17738 { HCBT_SYSCOMMAND, hook|wparam|optional, SC_RESTORE }, 17739 { HCBT_MINMAX, hook }, 17740 { HCBT_MINMAX, hook|optional }, 17741 { WM_QUERYOPEN, sent|defwinproc }, 17742 { WM_QUERYOPEN, sent|optional }, 17743 { WM_GETTEXT, sent|defwinproc|optional }, 17744 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 17745 { WM_GETMINMAXINFO, sent|defwinproc }, 17746 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, 17747 { WM_NCPAINT, sent|wparam|defwinproc|optional, 1 }, 17748 { WM_GETTEXT, sent|defwinproc|optional }, 17749 { WM_ERASEBKGND, sent|defwinproc }, 17750 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, 17751 { WM_MOVE, sent|defwinproc }, 17752 { WM_SIZE, sent|defwinproc }, 17753 { WM_NCCALCSIZE, sent|wparam|defwinproc|optional, 1 }, 17754 { WM_NCPAINT, sent|wparam|defwinproc|optional, 1 }, 17755 { WM_ERASEBKGND, sent|defwinproc|optional }, 17756 { HCBT_SETFOCUS, hook }, 17757 { WM_SETFOCUS, sent|defwinproc }, 17758 { WM_ACTIVATE, sent|wparam|defwinproc, 1 }, 17759 { WM_PAINT, sent| optional }, 17760 { WM_SETFOCUS, sent|defwinproc|optional }, 17761 { HCBT_KEYSKIPPED, hook|optional }, 17762 { WM_KEYUP, sent|optional }, 17763 { HCBT_KEYSKIPPED, hook|optional }, 17764 { WM_SYSKEYUP, sent|optional }, 17765 { HCBT_KEYSKIPPED, hook|optional }, 17766 { WM_KEYUP, sent|optional }, 17767 { WM_PAINT, sent| optional }, 17768 { 0 } 17769 }; 17770 17771 static void test_restore_messages(void) 17772 { 17773 INPUT ip = {0}; 17774 HWND hwnd; 17775 INT i; 17776 17777 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 17778 100, 200, 200, 0, 0, 0, NULL); 17779 ok (hwnd != 0, "Failed to create overlapped window\n"); 17780 SetForegroundWindow(hwnd); 17781 ShowWindow(hwnd, SW_MINIMIZE); 17782 flush_events(); 17783 flush_sequence(); 17784 17785 for (i = 0; i < 5; i++) 17786 { 17787 /* Send Alt+Tab to restore test window from minimized state */ 17788 ip.type = INPUT_KEYBOARD; 17789 ip.ki.wVk = VK_MENU; 17790 SendInput(1, &ip, sizeof(INPUT)); 17791 ip.ki.wVk = VK_TAB; 17792 SendInput(1, &ip, sizeof(INPUT)); 17793 ip.ki.wVk = VK_MENU; 17794 ip.ki.dwFlags = KEYEVENTF_KEYUP; 17795 SendInput(1, &ip, sizeof(INPUT)); 17796 ip.ki.wVk = VK_TAB; 17797 ip.ki.dwFlags = KEYEVENTF_KEYUP; 17798 SendInput(1, &ip, sizeof(INPUT)); 17799 flush_events(); 17800 if (!IsIconic(hwnd)) 17801 break; 17802 } 17803 17804 if (IsIconic(hwnd)) 17805 { 17806 skip("Alt+Tab failed to bring up test window.\n"); 17807 goto done; 17808 } 17809 ok_sequence(WmRestoreMinimizedSeq, "Restore minimized window", TRUE); 17810 17811 done: 17812 DestroyWindow(hwnd); 17813 } 17814 17815 static void test_invalid_window(void) 17816 { 17817 MSG msg; 17818 BOOL ret; 17819 17820 SetLastError(0xdeadbeef); 17821 ret = GetMessageA(&msg, (HWND)0xdeadbeef, 0, 0); 17822 ok(ret == -1, "wrong ret %d\n", ret); 17823 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError()); 17824 17825 SetLastError(0xdeadbeef); 17826 ret = PeekMessageA(&msg, (HWND)0xdeadbeef, 0, 0, PM_REMOVE); 17827 ok(!ret, "wrong ret %d\n", ret); 17828 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError()); 17829 } 17830 17831 static void init_funcs(void) 17832 { 17833 HMODULE hKernel32 = GetModuleHandleA("kernel32.dll"); 17834 17835 #define X(f) p##f = (void*)GetProcAddress(hKernel32, #f) 17836 X(ActivateActCtx); 17837 X(CreateActCtxW); 17838 X(DeactivateActCtx); 17839 X(GetCurrentActCtx); 17840 X(QueryActCtxW); 17841 X(ReleaseActCtx); 17842 #undef X 17843 } 17844 17845 #ifndef __REACTOS__ 17846 START_TEST(msg) 17847 { 17848 char **test_argv; 17849 BOOL ret; 17850 BOOL (WINAPI *pIsWinEventHookInstalled)(DWORD)= 0;/*GetProcAddress(user32, "IsWinEventHookInstalled");*/ 17851 HMODULE hModuleImm32; 17852 BOOL (WINAPI *pImmDisableIME)(DWORD); 17853 int argc; 17854 17855 init_funcs(); 17856 17857 argc = winetest_get_mainargs( &test_argv ); 17858 if (argc >= 3) 17859 { 17860 unsigned int arg; 17861 /* Child process. */ 17862 sscanf (test_argv[2], "%d", (unsigned int *) &arg); 17863 do_wait_idle_child( arg ); 17864 return; 17865 } 17866 17867 InitializeCriticalSection( &sequence_cs ); 17868 init_procs(); 17869 17870 hModuleImm32 = LoadLibraryA("imm32.dll"); 17871 if (hModuleImm32) { 17872 pImmDisableIME = (void *)GetProcAddress(hModuleImm32, "ImmDisableIME"); 17873 if (pImmDisableIME) 17874 pImmDisableIME(0); 17875 } 17876 pImmDisableIME = NULL; 17877 FreeLibrary(hModuleImm32); 17878 17879 if (!RegisterWindowClasses()) assert(0); 17880 17881 if (pSetWinEventHook) 17882 { 17883 hEvent_hook = pSetWinEventHook(EVENT_MIN, EVENT_MAX, 17884 GetModuleHandleA(0), win_event_proc, 17885 0, GetCurrentThreadId(), 17886 WINEVENT_INCONTEXT); 17887 if (pIsWinEventHookInstalled && hEvent_hook) 17888 { 17889 UINT event; 17890 for (event = EVENT_MIN; event <= EVENT_MAX; event++) 17891 ok(pIsWinEventHookInstalled(event), "IsWinEventHookInstalled(%u) failed\n", event); 17892 } 17893 } 17894 if (!hEvent_hook) win_skip( "no win event hook support\n" ); 17895 17896 cbt_hook_thread_id = GetCurrentThreadId(); 17897 hCBT_hook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId()); 17898 if (!hCBT_hook) win_skip( "cannot set global hook, will skip hook tests\n" ); 17899 17900 test_winevents(); 17901 17902 /* Fix message sequences before removing 4 lines below */ 17903 if (pUnhookWinEvent && hEvent_hook) 17904 { 17905 ret = pUnhookWinEvent(hEvent_hook); 17906 ok( ret, "UnhookWinEvent error %d\n", GetLastError()); 17907 pUnhookWinEvent = 0; 17908 } 17909 hEvent_hook = 0; 17910 17911 test_SendMessage_other_thread(1); 17912 test_SendMessage_other_thread(2); 17913 test_InSendMessage(); 17914 test_SetFocus(); 17915 test_SetParent(); 17916 test_PostMessage(); 17917 test_broadcast(); 17918 test_ShowWindow(); 17919 test_PeekMessage(); 17920 test_PeekMessage2(); 17921 test_PeekMessage3(); 17922 test_WaitForInputIdle( test_argv[0] ); 17923 test_scrollwindowex(); 17924 test_messages(); 17925 test_setwindowpos(); 17926 test_showwindow(); 17927 test_recursive_activation(); 17928 invisible_parent_tests(); 17929 test_mdi_messages(); 17930 test_button_messages(); 17931 test_button_bm_get_set_image(); 17932 test_autoradio_BM_CLICK(); 17933 test_autoradio_kbd_move(); 17934 test_static_messages(); 17935 test_listbox_messages(); 17936 test_combobox_messages(); 17937 test_wmime_keydown_message(); 17938 test_paint_messages(); 17939 test_interthread_messages(); 17940 test_message_conversion(); 17941 test_accelerators(); 17942 test_timers(); 17943 test_timers_no_wnd(); 17944 test_timers_exceptions(); 17945 if (hCBT_hook) 17946 { 17947 test_set_hook(); 17948 test_recursive_hook(); 17949 } 17950 test_DestroyWindow(); 17951 test_DispatchMessage(); 17952 test_SendMessageTimeout(); 17953 test_edit_messages(); 17954 test_quit_message(); 17955 test_notify_message(); 17956 test_SetActiveWindow(); 17957 test_restore_messages(); 17958 test_invalid_window(); 17959 17960 if (!pTrackMouseEvent) 17961 win_skip("TrackMouseEvent is not available\n"); 17962 else 17963 test_TrackMouseEvent(); 17964 17965 test_SetWindowRgn(); 17966 test_sys_menu(); 17967 test_dialog_messages(); 17968 test_EndDialog(); 17969 test_nullCallback(); 17970 test_dbcs_wm_char(); 17971 test_unicode_wm_char(); 17972 test_menu_messages(); 17973 test_paintingloop(); 17974 test_defwinproc(); 17975 test_desktop_winproc(); 17976 test_clipboard_viewers(); 17977 test_keyflags(); 17978 test_hotkey(); 17979 test_layered_window(); 17980 test_TrackPopupMenu(); 17981 test_TrackPopupMenuEmpty(); 17982 test_DoubleSetCapture(); 17983 /* keep it the last test, under Windows it tends to break the tests 17984 * which rely on active/foreground windows being correct. 17985 */ 17986 test_SetForegroundWindow(); 17987 17988 UnhookWindowsHookEx(hCBT_hook); 17989 if (pUnhookWinEvent && hEvent_hook) 17990 { 17991 ret = pUnhookWinEvent(hEvent_hook); 17992 ok( ret, "UnhookWinEvent error %d\n", GetLastError()); 17993 SetLastError(0xdeadbeef); 17994 ok(!pUnhookWinEvent(hEvent_hook), "UnhookWinEvent succeeded\n"); 17995 ok(GetLastError() == ERROR_INVALID_HANDLE || /* Win2k */ 17996 GetLastError() == 0xdeadbeef, /* Win9x */ 17997 "unexpected error %d\n", GetLastError()); 17998 } 17999 DeleteCriticalSection( &sequence_cs ); 18000 } 18001 #endif /* __REACTOS__ */ 18002 18003 static void init_tests() 18004 { 18005 HMODULE hModuleImm32; 18006 BOOL (WINAPI *pImmDisableIME)(DWORD); 18007 18008 init_funcs(); 18009 18010 InitializeCriticalSection( &sequence_cs ); 18011 init_procs(); 18012 18013 hModuleImm32 = LoadLibraryA("imm32.dll"); 18014 if (hModuleImm32) { 18015 pImmDisableIME = (void *)GetProcAddress(hModuleImm32, "ImmDisableIME"); 18016 if (pImmDisableIME) 18017 pImmDisableIME(0); 18018 } 18019 pImmDisableIME = NULL; 18020 FreeLibrary(hModuleImm32); 18021 18022 if (!RegisterWindowClasses()) assert(0); 18023 18024 cbt_hook_thread_id = GetCurrentThreadId(); 18025 hCBT_hook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId()); 18026 if (!hCBT_hook) win_skip( "cannot set global hook, will skip hook tests\n" ); 18027 } 18028 18029 static void cleanup_tests() 18030 { 18031 BOOL ret; 18032 UnhookWindowsHookEx(hCBT_hook); 18033 if (pUnhookWinEvent && hEvent_hook) 18034 { 18035 ret = pUnhookWinEvent(hEvent_hook); 18036 ok( ret, "UnhookWinEvent error %d\n", GetLastError()); 18037 SetLastError(0xdeadbeef); 18038 ok(!pUnhookWinEvent(hEvent_hook), "UnhookWinEvent succeeded\n"); 18039 ok(GetLastError() == ERROR_INVALID_HANDLE || /* Win2k */ 18040 GetLastError() == 0xdeadbeef, /* Win9x */ 18041 "unexpected error %d\n", GetLastError()); 18042 } 18043 DeleteCriticalSection( &sequence_cs ); 18044 18045 } 18046 18047 START_TEST(msg_queue) 18048 { 18049 int argc; 18050 char **test_argv; 18051 argc = winetest_get_mainargs( &test_argv ); 18052 if (argc >= 3) 18053 { 18054 unsigned int arg; 18055 /* Child process. */ 18056 sscanf (test_argv[2], "%d", (unsigned int *) &arg); 18057 do_wait_idle_child( arg ); 18058 return; 18059 } 18060 18061 init_tests(); 18062 test_SendMessage_other_thread(1); 18063 test_SendMessage_other_thread(2); 18064 test_InSendMessage(); 18065 test_PostMessage(); 18066 test_broadcast(); 18067 test_PeekMessage(); 18068 test_PeekMessage2(); 18069 test_PeekMessage3(); 18070 test_interthread_messages(); 18071 test_DispatchMessage(); 18072 test_SendMessageTimeout(); 18073 test_quit_message(); 18074 test_notify_message(); 18075 test_WaitForInputIdle( test_argv[0] ); 18076 test_DestroyWindow(); 18077 cleanup_tests(); 18078 } 18079 18080 START_TEST(msg_messages) 18081 { 18082 init_tests(); 18083 test_message_conversion(); 18084 test_messages(); 18085 test_wmime_keydown_message(); 18086 test_nullCallback(); 18087 test_dbcs_wm_char(); 18088 test_unicode_wm_char(); 18089 test_defwinproc(); 18090 test_desktop_winproc(); 18091 cleanup_tests(); 18092 } 18093 18094 START_TEST(msg_focus) 18095 { 18096 init_tests(); 18097 18098 test_SetFocus(); 18099 18100 /* HACK: For some reason the tests fail on Windows if run consecutively. 18101 * Putting these in between helps, and is essentially what happens in the 18102 * "normal" msg test. */ 18103 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); 18104 flush_events(); 18105 18106 test_SetActiveWindow(); 18107 18108 /* HACK */ 18109 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); 18110 flush_events(); 18111 18112 test_restore_messages(); 18113 test_invalid_window(); 18114 18115 test_DoubleSetCapture(); 18116 18117 /* keep it the last test, under Windows it tends to break the tests 18118 * which rely on active/foreground windows being correct. 18119 */ 18120 test_SetForegroundWindow(); 18121 cleanup_tests(); 18122 } 18123 18124 START_TEST(msg_winpos) 18125 { 18126 init_tests(); 18127 test_SetParent(); 18128 test_ShowWindow(); 18129 test_setwindowpos(); 18130 test_showwindow(); 18131 test_recursive_activation(); 18132 test_SetWindowRgn(); 18133 invisible_parent_tests(); 18134 cleanup_tests(); 18135 } 18136 18137 START_TEST(msg_paint) 18138 { 18139 init_tests(); 18140 test_scrollwindowex(); 18141 test_paint_messages(); 18142 #ifdef __REACTOS__ 18143 if (!winetest_interactive && 18144 !strcmp(winetest_platform, "windows")) 18145 { 18146 skip("ROSTESTS-185: Skipping user32_winetest:msg_paint test_paintingloop because it hangs on WHS-Testbot. Set winetest_interactive to run it anyway.\n"); 18147 } 18148 else 18149 #endif 18150 test_paintingloop(); 18151 cleanup_tests(); 18152 } 18153 18154 START_TEST(msg_input) 18155 { 18156 init_tests(); 18157 test_accelerators(); 18158 if (!pTrackMouseEvent) 18159 win_skip("TrackMouseEvent is not available\n"); 18160 else 18161 test_TrackMouseEvent(); 18162 18163 test_keyflags(); 18164 test_hotkey(); 18165 cleanup_tests(); 18166 } 18167 18168 START_TEST(msg_timer) 18169 { 18170 init_tests(); 18171 test_timers(); 18172 test_timers_no_wnd(); 18173 test_timers_exceptions(); 18174 cleanup_tests(); 18175 } 18176 18177 typedef BOOL (WINAPI *IS_WINEVENT_HOOK_INSTALLED)(DWORD); 18178 18179 START_TEST(msg_hook) 18180 { 18181 // HMODULE user32 = GetModuleHandleA("user32.dll"); 18182 // IS_WINEVENT_HOOK_INSTALLED pIsWinEventHookInstalled = (IS_WINEVENT_HOOK_INSTALLED)GetProcAddress(user32, "IsWinEventHookInstalled"); 18183 BOOL (WINAPI *pIsWinEventHookInstalled)(DWORD)= 0;/*GetProcAddress(user32, "IsWinEventHookInstalled");*/ 18184 18185 init_tests(); 18186 18187 if (pSetWinEventHook) 18188 { 18189 hEvent_hook = pSetWinEventHook(EVENT_MIN, EVENT_MAX, 18190 GetModuleHandleA(0), win_event_proc, 18191 0, GetCurrentThreadId(), 18192 WINEVENT_INCONTEXT); 18193 if (pIsWinEventHookInstalled && hEvent_hook) 18194 { 18195 UINT event; 18196 for (event = EVENT_MIN; event <= EVENT_MAX; event++) 18197 ok(pIsWinEventHookInstalled(event), "IsWinEventHookInstalled(%u) failed\n", event); 18198 } 18199 } 18200 if (!hEvent_hook) win_skip( "no win event hook support\n" ); 18201 18202 test_winevents(); 18203 18204 /* Fix message sequences before removing 4 lines below */ 18205 if (pUnhookWinEvent && hEvent_hook) 18206 { 18207 BOOL ret; 18208 ret = pUnhookWinEvent(hEvent_hook); 18209 ok( ret, "UnhookWinEvent error %d\n", GetLastError()); 18210 pUnhookWinEvent = 0; 18211 } 18212 hEvent_hook = 0; 18213 if (hCBT_hook) 18214 { 18215 test_set_hook(); 18216 test_recursive_hook(); 18217 } 18218 cleanup_tests(); 18219 } 18220 18221 START_TEST(msg_menu) 18222 { 18223 init_tests(); 18224 test_sys_menu(); 18225 test_menu_messages(); 18226 test_TrackPopupMenu(); 18227 test_TrackPopupMenuEmpty(); 18228 cleanup_tests(); 18229 } 18230 18231 START_TEST(msg_mdi) 18232 { 18233 init_tests(); 18234 test_mdi_messages(); 18235 cleanup_tests(); 18236 } 18237 18238 START_TEST(msg_controls) 18239 { 18240 init_tests(); 18241 test_button_messages(); 18242 test_button_bm_get_set_image(); 18243 test_autoradio_BM_CLICK(); 18244 test_autoradio_kbd_move(); 18245 test_static_messages(); 18246 test_listbox_messages(); 18247 test_combobox_messages(); 18248 test_edit_messages(); 18249 cleanup_tests(); 18250 } 18251 18252 START_TEST(msg_layered_window) 18253 { 18254 init_tests(); 18255 test_layered_window(); 18256 cleanup_tests(); 18257 } 18258 18259 START_TEST(msg_dialog) 18260 { 18261 init_tests(); 18262 test_dialog_messages(); 18263 test_EndDialog(); 18264 cleanup_tests(); 18265 } 18266 18267 START_TEST(msg_clipboard) 18268 { 18269 init_tests(); 18270 test_clipboard_viewers(); 18271 cleanup_tests(); 18272 } 18273