Handle non-hardware X events correctly with native USER
[wine/multimedia.git] / windows / win.c
blob3f87d5fbc12f93f624d0eb120134c510de7a68e0
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include <string.h>
9 #include "options.h"
10 #include "class.h"
11 #include "win.h"
12 #include "heap.h"
13 #include "user.h"
14 #include "dce.h"
15 #include "sysmetrics.h"
16 #include "cursoricon.h"
17 #include "heap.h"
18 #include "hook.h"
19 #include "menu.h"
20 #include "message.h"
21 #include "nonclient.h"
22 #include "queue.h"
23 #include "winpos.h"
24 #include "shm_main_blk.h"
25 #include "dde_proc.h"
26 #include "clipboard.h"
27 #include "winproc.h"
28 #include "thread.h"
29 #include "process.h"
30 #include "debug.h"
31 #include "winerror.h"
32 #include "mdi.h"
34 extern WND_DRIVER X11DRV_WND_Driver;
36 /* Desktop window */
37 static WND *pWndDesktop = NULL;
39 static HWND32 hwndSysModal = 0;
41 static WORD wDragWidth = 4;
42 static WORD wDragHeight= 3;
44 /***********************************************************************
45 * WIN_FindWndPtr
47 * Return a pointer to the WND structure corresponding to a HWND.
49 WND * WIN_FindWndPtr( HWND32 hwnd )
51 WND * ptr;
53 if (!hwnd || HIWORD(hwnd)) return NULL;
54 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
55 if (ptr->dwMagic != WND_MAGIC) return NULL;
56 if (ptr->hwndSelf != hwnd)
58 ERR( win, "Can't happen: hwnd %04x self pointer is %04x\n",
59 hwnd, ptr->hwndSelf );
60 return NULL;
62 return ptr;
66 /***********************************************************************
67 * WIN_DumpWindow
69 * Dump the content of a window structure to stderr.
71 void WIN_DumpWindow( HWND32 hwnd )
73 WND *ptr;
74 char className[80];
75 int i;
77 if (!(ptr = WIN_FindWndPtr( hwnd )))
79 WARN( win, "%04x is not a window handle\n", hwnd );
80 return;
83 if (!GetClassName32A( hwnd, className, sizeof(className ) ))
84 strcpy( className, "#NULL#" );
86 TRACE( win, "Window %04x (%p):\n", hwnd, ptr );
87 DUMP( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
88 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
89 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
90 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
91 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
92 ptr->next, ptr->child, ptr->parent, ptr->owner,
93 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
94 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
95 ptr->dwStyle, ptr->dwExStyle, (UINT32)ptr->winproc,
96 ptr->text ? ptr->text : "",
97 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
98 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
99 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
100 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
102 if (ptr->class->cbWndExtra)
104 DUMP( "extra bytes:" );
105 for (i = 0; i < ptr->class->cbWndExtra; i++)
106 DUMP( " %02x", *((BYTE*)ptr->wExtra+i) );
107 DUMP( "\n" );
109 DUMP( "\n" );
113 /***********************************************************************
114 * WIN_WalkWindows
116 * Walk the windows tree and print each window on stderr.
118 void WIN_WalkWindows( HWND32 hwnd, int indent )
120 WND *ptr;
121 char className[80];
123 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop;
124 if (!ptr)
126 WARN( win, "Invalid window handle %04x\n", hwnd );
127 return;
130 if (!indent) /* first time around */
131 DUMP( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
132 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
133 " Text");
135 while (ptr)
137 DUMP( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
139 GlobalGetAtomName16(ptr->class->atomName,className,sizeof(className));
141 DUMP( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
142 (DWORD)ptr, ptr->hmemTaskQ, className,
143 (UINT32)ptr->dwStyle, (UINT32)ptr->winproc,
144 ptr->text?ptr->text:"<null>");
146 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
147 ptr = ptr->next;
151 /***********************************************************************
152 * WIN_UnlinkWindow
154 * Remove a window from the siblings linked list.
156 BOOL32 WIN_UnlinkWindow( HWND32 hwnd )
158 WND *wndPtr, **ppWnd;
160 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
161 ppWnd = &wndPtr->parent->child;
162 while (*ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
163 *ppWnd = wndPtr->next;
164 return TRUE;
168 /***********************************************************************
169 * WIN_LinkWindow
171 * Insert a window into the siblings linked list.
172 * The window is inserted after the specified window, which can also
173 * be specified as HWND_TOP or HWND_BOTTOM.
175 BOOL32 WIN_LinkWindow( HWND32 hwnd, HWND32 hwndInsertAfter )
177 WND *wndPtr, **ppWnd;
179 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
181 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
183 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
184 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
185 while (*ppWnd) ppWnd = &(*ppWnd)->next;
187 else /* Normal case */
189 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
190 if (!afterPtr) return FALSE;
191 ppWnd = &afterPtr->next;
193 wndPtr->next = *ppWnd;
194 *ppWnd = wndPtr;
195 return TRUE;
199 /***********************************************************************
200 * WIN_FindWinToRepaint
202 * Find a window that needs repaint.
204 HWND32 WIN_FindWinToRepaint( HWND32 hwnd, HQUEUE16 hQueue )
206 HWND32 hwndRet;
207 WND *pWnd = pWndDesktop;
209 /* Note: the desktop window never gets WM_PAINT messages
210 * The real reason why is because Windows DesktopWndProc
211 * does ValidateRgn inside WM_ERASEBKGND handler.
214 pWnd = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop->child;
216 for ( ; pWnd ; pWnd = pWnd->next )
218 if (!(pWnd->dwStyle & WS_VISIBLE))
220 TRACE(win, "skipping window %04x\n",
221 pWnd->hwndSelf );
222 continue;
224 if ((pWnd->hmemTaskQ == hQueue) &&
225 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))) break;
227 if (pWnd->child )
228 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
229 return hwndRet;
232 if (!pWnd) return 0;
234 hwndRet = pWnd->hwndSelf;
236 /* look among siblings if we got a transparent window */
237 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
238 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
240 pWnd = pWnd->next;
242 if (pWnd) hwndRet = pWnd->hwndSelf;
243 TRACE(win,"found %04x\n",hwndRet);
244 return hwndRet;
248 /***********************************************************************
249 * WIN_DestroyWindow
251 * Destroy storage associated to a window. "Internals" p.358
253 static WND* WIN_DestroyWindow( WND* wndPtr )
255 HWND32 hwnd = wndPtr->hwndSelf;
256 WND *pWnd;
258 TRACE(win, "%04x\n", wndPtr->hwndSelf );
260 #ifdef CONFIG_IPC
261 if (main_block)
262 DDE_DestroyWindow(wndPtr->hwndSelf);
263 #endif /* CONFIG_IPC */
265 /* free child windows */
267 while ((pWnd = wndPtr->child))
268 wndPtr->child = WIN_DestroyWindow( pWnd );
270 SendMessage32A( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
272 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
274 WINPOS_CheckInternalPos( hwnd );
275 if( hwnd == GetCapture32()) ReleaseCapture();
277 /* free resources associated with the window */
279 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
280 PROPERTY_RemoveWindowProps( wndPtr );
282 wndPtr->dwMagic = 0; /* Mark it as invalid */
284 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
286 if (wndPtr->hrgnUpdate > 1) DeleteObject32( wndPtr->hrgnUpdate );
287 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
290 /* toss stale messages from the queue */
292 if( wndPtr->hmemTaskQ )
294 int pos;
295 BOOL32 bPostQuit = FALSE;
296 WPARAM32 wQuitParam = 0;
297 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) GlobalLock16(wndPtr->hmemTaskQ);
299 while( (pos = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != -1 )
301 if( msgQ->messages[pos].msg.message == WM_QUIT )
303 bPostQuit = TRUE;
304 wQuitParam = msgQ->messages[pos].msg.wParam;
306 QUEUE_RemoveMsg(msgQ, pos);
308 /* repost WM_QUIT to make sure this app exits its message loop */
309 if( bPostQuit ) PostQuitMessage32(wQuitParam);
310 wndPtr->hmemTaskQ = 0;
313 if (!(wndPtr->dwStyle & WS_CHILD))
314 if (wndPtr->wIDmenu) DestroyMenu32( (HMENU32)wndPtr->wIDmenu );
315 if (wndPtr->hSysMenu) DestroyMenu32( wndPtr->hSysMenu );
316 wndPtr->pDriver->pDestroyWindow( wndPtr );
317 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
318 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
319 wndPtr->hwndSelf = 0;
320 wndPtr->class->cWindows--;
321 wndPtr->class = NULL;
322 pWnd = wndPtr->next;
324 USER_HEAP_FREE( hwnd );
325 return pWnd;
328 /***********************************************************************
329 * WIN_ResetQueueWindows
331 * Reset the queue of all the children of a given window.
332 * Return TRUE if something was done.
334 BOOL32 WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
336 BOOL32 ret = FALSE;
338 if (hNew) /* Set a new queue */
340 for (wnd = wnd->child; (wnd); wnd = wnd->next)
342 if (wnd->hmemTaskQ == hQueue)
344 wnd->hmemTaskQ = hNew;
345 ret = TRUE;
347 if (wnd->child)
348 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
351 else /* Queue is being destroyed */
353 while (wnd->child)
355 WND *tmp = wnd->child;
356 ret = FALSE;
357 while (tmp)
359 if (tmp->hmemTaskQ == hQueue)
361 DestroyWindow32( tmp->hwndSelf );
362 ret = TRUE;
363 break;
365 if (tmp->child && WIN_ResetQueueWindows(tmp->child,hQueue,0))
366 ret = TRUE;
367 else
368 tmp = tmp->next;
370 if (!ret) break;
373 return ret;
376 /***********************************************************************
377 * WIN_CreateDesktopWindow
379 * Create the desktop window.
381 BOOL32 WIN_CreateDesktopWindow(void)
383 CLASS *class;
384 HWND32 hwndDesktop;
386 TRACE(win,"Creating desktop window\n");
388 if (!ICONTITLE_Init() ||
389 !WINPOS_CreateInternalPosAtom() ||
390 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
391 return FALSE;
393 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
394 if (!hwndDesktop) return FALSE;
395 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
397 pWndDesktop->next = NULL;
398 pWndDesktop->child = NULL;
399 pWndDesktop->parent = NULL;
400 pWndDesktop->owner = NULL;
401 pWndDesktop->class = class;
402 pWndDesktop->dwMagic = WND_MAGIC;
403 pWndDesktop->hwndSelf = hwndDesktop;
404 pWndDesktop->hInstance = 0;
405 pWndDesktop->rectWindow.left = 0;
406 pWndDesktop->rectWindow.top = 0;
407 pWndDesktop->rectWindow.right = SYSMETRICS_CXSCREEN;
408 pWndDesktop->rectWindow.bottom = SYSMETRICS_CYSCREEN;
409 pWndDesktop->rectClient = pWndDesktop->rectWindow;
410 pWndDesktop->text = NULL;
411 pWndDesktop->hmemTaskQ = 0; /* Desktop does not belong to a task */
412 pWndDesktop->hrgnUpdate = 0;
413 pWndDesktop->hwndLastActive = hwndDesktop;
414 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
415 WS_CLIPSIBLINGS;
416 pWndDesktop->dwExStyle = 0;
417 pWndDesktop->dce = NULL;
418 pWndDesktop->pVScroll = NULL;
419 pWndDesktop->pHScroll = NULL;
420 pWndDesktop->pProp = NULL;
421 pWndDesktop->wIDmenu = 0;
422 pWndDesktop->helpContext = 0;
423 pWndDesktop->flags = 0;
424 pWndDesktop->hSysMenu = 0;
425 pWndDesktop->userdata = 0;
426 pWndDesktop->pDriver = &X11DRV_WND_Driver;
427 pWndDesktop->winproc = (WNDPROC16)class->winproc;
429 /* FIXME: How do we know if it should be Unicode or not */
430 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop, class, FALSE))
431 return FALSE;
433 SendMessage32A( hwndDesktop, WM_NCCREATE, 0, 0 );
434 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
435 return TRUE;
439 /***********************************************************************
440 * WIN_CreateWindowEx
442 * Implementation of CreateWindowEx().
444 static HWND32 WIN_CreateWindowEx( CREATESTRUCT32A *cs, ATOM classAtom,
445 BOOL32 win32, BOOL32 unicode )
447 CLASS *classPtr;
448 WND *wndPtr;
449 HWND16 hwnd, hwndLinkAfter;
450 POINT32 maxSize, maxPos, minTrack, maxTrack;
451 LRESULT (CALLBACK *localSend32)(HWND32, UINT32, WPARAM32, LPARAM);
453 TRACE(win, "%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
454 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
455 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
456 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
457 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
459 /* Find the parent window */
461 if (cs->hwndParent)
463 /* Make sure parent is valid */
464 if (!IsWindow32( cs->hwndParent ))
466 WARN( win, "Bad parent %04x\n", cs->hwndParent );
467 return 0;
469 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
470 WARN( win, "No parent for child window\n" );
471 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
474 /* Find the window class */
475 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
477 char buffer[256];
478 GlobalGetAtomName32A( classAtom, buffer, sizeof(buffer) );
479 WARN( win, "Bad class '%s'\n", buffer );
480 return 0;
483 /* Fix the coordinates */
485 if (cs->x == CW_USEDEFAULT32)
487 PDB32 *pdb = PROCESS_Current();
488 if ( !(cs->style & (WS_CHILD | WS_POPUP))
489 && (pdb->env_db->startup_info->dwFlags & STARTF_USEPOSITION) )
491 cs->x = pdb->env_db->startup_info->dwX;
492 cs->y = pdb->env_db->startup_info->dwY;
494 else
496 cs->x = 0;
497 cs->y = 0;
500 if (cs->cx == CW_USEDEFAULT32)
502 PDB32 *pdb = PROCESS_Current();
503 if ( !(cs->style & (WS_CHILD | WS_POPUP))
504 && (pdb->env_db->startup_info->dwFlags & STARTF_USESIZE) )
506 cs->cx = pdb->env_db->startup_info->dwXSize;
507 cs->cy = pdb->env_db->startup_info->dwYSize;
509 else
511 cs->cx = 600; /* FIXME */
512 cs->cy = 400;
516 /* Create the window structure */
518 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
519 - sizeof(wndPtr->wExtra) )))
521 TRACE(win, "out of memory\n" );
522 return 0;
525 /* Fill the window structure */
527 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
528 wndPtr->next = NULL;
529 wndPtr->child = NULL;
531 if ((cs->style & WS_CHILD) && cs->hwndParent)
533 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
534 wndPtr->owner = NULL;
536 else
538 wndPtr->parent = pWndDesktop;
539 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
540 wndPtr->owner = NULL;
541 else
542 wndPtr->owner = WIN_GetTopParentPtr(WIN_FindWndPtr(cs->hwndParent));
545 wndPtr->pDriver = &X11DRV_WND_Driver;
546 wndPtr->window = 0;
547 wndPtr->class = classPtr;
548 wndPtr->winproc = classPtr->winproc;
549 wndPtr->dwMagic = WND_MAGIC;
550 wndPtr->hwndSelf = hwnd;
551 wndPtr->hInstance = cs->hInstance;
552 wndPtr->text = NULL;
553 wndPtr->hmemTaskQ = GetTaskQueue(0);
554 wndPtr->hrgnUpdate = 0;
555 wndPtr->hwndLastActive = hwnd;
556 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
557 wndPtr->dwExStyle = cs->dwExStyle;
558 wndPtr->wIDmenu = 0;
559 wndPtr->helpContext = 0;
560 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
561 wndPtr->pVScroll = NULL;
562 wndPtr->pHScroll = NULL;
563 wndPtr->pProp = NULL;
564 wndPtr->userdata = 0;
565 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
566 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
568 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
570 /* Call the WH_CBT hook */
572 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
573 ? HWND_BOTTOM : HWND_TOP;
575 if (HOOK_IsHooked( WH_CBT ))
577 CBT_CREATEWND32A cbtc;
578 LRESULT ret;
580 cbtc.lpcs = cs;
581 cbtc.hwndInsertAfter = hwndLinkAfter;
582 ret = unicode ? HOOK_CallHooks32W(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
583 : HOOK_CallHooks32A(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
584 if (ret)
586 TRACE(win, "CBT-hook returned 0\n");
587 USER_HEAP_FREE( hwnd );
588 return 0;
592 /* Increment class window counter */
594 classPtr->cWindows++;
596 /* Correct the window style */
598 if (!(cs->style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
600 wndPtr->dwStyle |= WS_CAPTION | WS_CLIPSIBLINGS;
601 wndPtr->flags |= WIN_NEED_SIZE;
603 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
605 /* Get class or window DC if needed */
607 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
608 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
609 else wndPtr->dce = NULL;
611 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
613 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
615 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
616 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
617 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
618 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
619 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
622 if(cs->style & WS_CHILD)
624 if(cs->cx < 0) cs->cx = 0;
625 if(cs->cy < 0) cs->cy = 0;
627 else
629 if (cs->cx <= 0) cs->cx = 1;
630 if (cs->cy <= 0) cs->cy = 1;
633 wndPtr->rectWindow.left = cs->x;
634 wndPtr->rectWindow.top = cs->y;
635 wndPtr->rectWindow.right = cs->x + cs->cx;
636 wndPtr->rectWindow.bottom = cs->y + cs->cy;
637 wndPtr->rectClient = wndPtr->rectWindow;
639 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
640 return FALSE;
642 /* Set the window menu */
644 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
646 if (cs->hMenu) SetMenu32(hwnd, cs->hMenu);
647 else
649 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
650 if (classPtr->menuNameA)
651 cs->hMenu = HIWORD(classPtr->menuNameA) ?
652 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
653 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
654 #else
655 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
656 if (menuName)
658 if (HIWORD(cs->hInstance))
659 cs->hMenu = LoadMenu32A(cs->hInstance,PTR_SEG_TO_LIN(menuName));
660 else
661 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
663 if (cs->hMenu) SetMenu32( hwnd, cs->hMenu );
665 #endif
668 else wndPtr->wIDmenu = (UINT32)cs->hMenu;
670 /* Send the WM_CREATE message
671 * Perhaps we shouldn't allow width/height changes as well.
672 * See p327 in "Internals".
675 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
677 localSend32 = unicode ? SendMessage32W : SendMessage32A;
678 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
680 /* Insert the window in the linked list */
682 WIN_LinkWindow( hwnd, hwndLinkAfter );
684 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
685 NULL, NULL, 0, &wndPtr->rectClient );
686 OffsetRect32(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
687 maxPos.y - wndPtr->rectWindow.top);
688 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
690 /* Send the size messages */
692 if (!(wndPtr->flags & WIN_NEED_SIZE))
694 /* send it anyway */
695 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
696 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
697 WARN(win,"sending bogus WM_SIZE message 0x%08lx\n",
698 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
699 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
700 SendMessage32A( hwnd, WM_SIZE, SIZE_RESTORED,
701 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
702 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
703 SendMessage32A( hwnd, WM_MOVE, 0,
704 MAKELONG( wndPtr->rectClient.left,
705 wndPtr->rectClient.top ) );
708 /* Show the window, maximizing or minimizing if needed */
710 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
712 RECT16 newPos;
713 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
714 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
715 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
716 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow32())
717 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
718 : SWP_NOZORDER | SWP_FRAMECHANGED;
719 SetWindowPos32( hwnd, 0, newPos.left, newPos.top,
720 newPos.right, newPos.bottom, swFlag );
723 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
725 /* Notify the parent window only */
727 SendMessage32A( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
728 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
729 if( !IsWindow32(hwnd) ) return 0;
732 if (cs->style & WS_VISIBLE) ShowWindow32( hwnd, SW_SHOW );
734 /* Call WH_SHELL hook */
736 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
737 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
739 TRACE(win, "created window %04x\n", hwnd);
740 return hwnd;
742 WIN_UnlinkWindow( hwnd );
745 /* Abort window creation */
747 WARN(win, "aborted by WM_xxCREATE!\n");
748 WIN_DestroyWindow( wndPtr );
749 return 0;
753 /***********************************************************************
754 * CreateWindow16 (USER.41)
756 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
757 DWORD style, INT16 x, INT16 y, INT16 width,
758 INT16 height, HWND16 parent, HMENU16 menu,
759 HINSTANCE16 instance, LPVOID data )
761 return CreateWindowEx16( 0, className, windowName, style,
762 x, y, width, height, parent, menu, instance, data );
766 /***********************************************************************
767 * CreateWindowEx16 (USER.452)
769 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
770 LPCSTR windowName, DWORD style, INT16 x,
771 INT16 y, INT16 width, INT16 height,
772 HWND16 parent, HMENU16 menu,
773 HINSTANCE16 instance, LPVOID data )
775 ATOM classAtom;
776 CREATESTRUCT32A cs;
778 /* Find the class atom */
780 if (!(classAtom = GlobalFindAtom32A( className )))
782 fprintf( stderr, "CreateWindowEx16: bad class name " );
783 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
784 else fprintf( stderr, "'%s'\n", className );
785 return 0;
788 /* Fix the coordinates */
790 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)x;
791 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)y;
792 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)width;
793 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)height;
795 /* Create the window */
797 cs.lpCreateParams = data;
798 cs.hInstance = (HINSTANCE32)instance;
799 cs.hMenu = (HMENU32)menu;
800 cs.hwndParent = (HWND32)parent;
801 cs.style = style;
802 cs.lpszName = windowName;
803 cs.lpszClass = className;
804 cs.dwExStyle = exStyle;
805 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
809 /***********************************************************************
810 * CreateWindowEx32A (USER32.83)
812 HWND32 WINAPI CreateWindowEx32A( DWORD exStyle, LPCSTR className,
813 LPCSTR windowName, DWORD style, INT32 x,
814 INT32 y, INT32 width, INT32 height,
815 HWND32 parent, HMENU32 menu,
816 HINSTANCE32 instance, LPVOID data )
818 ATOM classAtom;
819 CREATESTRUCT32A cs;
821 if(exStyle & WS_EX_MDICHILD)
822 return MDI_CreateMDIWindow32A(className, windowName, style, x, y, width, height, parent, instance, data);
823 /* Find the class atom */
825 if (!(classAtom = GlobalFindAtom32A( className )))
827 fprintf( stderr, "CreateWindowEx32A: bad class name " );
828 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
829 else fprintf( stderr, "'%s'\n", className );
830 return 0;
833 /* Create the window */
835 cs.lpCreateParams = data;
836 cs.hInstance = instance;
837 cs.hMenu = menu;
838 cs.hwndParent = parent;
839 cs.x = x;
840 cs.y = y;
841 cs.cx = width;
842 cs.cy = height;
843 cs.style = style;
844 cs.lpszName = windowName;
845 cs.lpszClass = className;
846 cs.dwExStyle = exStyle;
847 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
851 /***********************************************************************
852 * CreateWindowEx32W (USER32.84)
854 HWND32 WINAPI CreateWindowEx32W( DWORD exStyle, LPCWSTR className,
855 LPCWSTR windowName, DWORD style, INT32 x,
856 INT32 y, INT32 width, INT32 height,
857 HWND32 parent, HMENU32 menu,
858 HINSTANCE32 instance, LPVOID data )
860 ATOM classAtom;
861 CREATESTRUCT32W cs;
863 if(exStyle & WS_EX_MDICHILD)
864 return MDI_CreateMDIWindow32W(className, windowName, style, x, y, width, height, parent, instance, data);
866 /* Find the class atom */
868 if (!(classAtom = GlobalFindAtom32W( className )))
870 if (HIWORD(className))
872 LPSTR cn = HEAP_strdupWtoA( GetProcessHeap(), 0, className );
873 WARN( win, "Bad class name '%s'\n",cn);
874 HeapFree( GetProcessHeap(), 0, cn );
876 else
877 WARN( win, "Bad class name %p\n", className );
878 return 0;
881 /* Create the window */
883 cs.lpCreateParams = data;
884 cs.hInstance = instance;
885 cs.hMenu = menu;
886 cs.hwndParent = parent;
887 cs.x = x;
888 cs.y = y;
889 cs.cx = width;
890 cs.cy = height;
891 cs.style = style;
892 cs.lpszName = windowName;
893 cs.lpszClass = className;
894 cs.dwExStyle = exStyle;
895 /* Note: we rely on the fact that CREATESTRUCT32A and */
896 /* CREATESTRUCT32W have the same layout. */
897 return WIN_CreateWindowEx( (CREATESTRUCT32A *)&cs, classAtom, TRUE, TRUE );
901 /***********************************************************************
902 * WIN_CheckFocus
904 static void WIN_CheckFocus( WND* pWnd )
906 if( GetFocus16() == pWnd->hwndSelf )
907 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
910 /***********************************************************************
911 * WIN_SendDestroyMsg
913 static void WIN_SendDestroyMsg( WND* pWnd )
915 WIN_CheckFocus(pWnd);
917 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret32();
918 if( !pWnd->window ) CLIPBOARD_GetDriver()->pResetOwner( pWnd );
920 SendMessage32A( pWnd->hwndSelf, WM_DESTROY, 0, 0);
922 if( IsWindow32(pWnd->hwndSelf) )
924 WND* pChild = pWnd->child;
925 while( pChild )
927 WIN_SendDestroyMsg( pChild );
928 pChild = pChild->next;
930 WIN_CheckFocus(pWnd);
932 else
933 WARN(win, "\tdestroyed itself while in WM_DESTROY!\n");
937 /***********************************************************************
938 * DestroyWindow16 (USER.53)
940 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
942 return DestroyWindow32(hwnd);
946 /***********************************************************************
947 * DestroyWindow32 (USER32.135)
949 BOOL32 WINAPI DestroyWindow32( HWND32 hwnd )
951 WND * wndPtr;
953 TRACE(win, "(%04x)\n", hwnd);
955 /* Initialization */
957 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
958 if (wndPtr == pWndDesktop) return FALSE; /* Can't destroy desktop */
960 /* Call hooks */
962 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
963 return FALSE;
965 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
967 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
968 /* FIXME: clean up palette - see "Internals" p.352 */
971 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
972 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
974 /* Notify the parent window only */
975 SendMessage32A( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
976 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
977 if( !IsWindow32(hwnd) ) return TRUE;
980 if( wndPtr->window ) CLIPBOARD_GetDriver()->pResetOwner( wndPtr ); /* before the window is unmapped */
982 /* Hide the window */
984 if (wndPtr->dwStyle & WS_VISIBLE)
986 SetWindowPos32( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
987 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
988 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
989 if (!IsWindow32(hwnd)) return TRUE;
992 /* Recursively destroy owned windows */
994 if( !(wndPtr->dwStyle & WS_CHILD) )
996 /* make sure top menu popup doesn't get destroyed */
997 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
999 for (;;)
1001 WND *siblingPtr = wndPtr->parent->child; /* First sibling */
1002 while (siblingPtr)
1004 if (siblingPtr->owner == wndPtr)
1006 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1007 break;
1008 else
1009 siblingPtr->owner = NULL;
1011 siblingPtr = siblingPtr->next;
1013 if (siblingPtr) DestroyWindow32( siblingPtr->hwndSelf );
1014 else break;
1017 if( !Options.managed || EVENT_CheckFocus() )
1018 WINPOS_ActivateOtherWindow(wndPtr);
1020 if( wndPtr->owner &&
1021 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1022 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1025 /* Send destroy messages */
1027 WIN_SendDestroyMsg( wndPtr );
1028 if (!IsWindow32(hwnd)) return TRUE;
1030 /* Unlink now so we won't bother with the children later on */
1032 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1034 /* Destroy the window storage */
1036 WIN_DestroyWindow( wndPtr );
1037 return TRUE;
1041 /***********************************************************************
1042 * CloseWindow16 (USER.43)
1044 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1046 return CloseWindow32( hwnd );
1050 /***********************************************************************
1051 * CloseWindow32 (USER32.56)
1053 BOOL32 WINAPI CloseWindow32( HWND32 hwnd )
1055 WND * wndPtr = WIN_FindWndPtr( hwnd );
1056 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD)) return FALSE;
1057 ShowWindow32( hwnd, SW_MINIMIZE );
1058 return TRUE;
1062 /***********************************************************************
1063 * OpenIcon16 (USER.44)
1065 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1067 return OpenIcon32( hwnd );
1071 /***********************************************************************
1072 * OpenIcon32 (USER32.410)
1074 BOOL32 WINAPI OpenIcon32( HWND32 hwnd )
1076 if (!IsIconic32( hwnd )) return FALSE;
1077 ShowWindow32( hwnd, SW_SHOWNORMAL );
1078 return TRUE;
1082 /***********************************************************************
1083 * WIN_FindWindow
1085 * Implementation of FindWindow() and FindWindowEx().
1087 static HWND32 WIN_FindWindow( HWND32 parent, HWND32 child, ATOM className,
1088 LPCSTR title )
1090 WND *pWnd;
1091 CLASS *pClass = NULL;
1093 if (child)
1095 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1096 if (parent)
1098 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent)) return 0;
1100 else if (pWnd->parent != pWndDesktop) return 0;
1101 pWnd = pWnd->next;
1103 else
1105 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : pWndDesktop)) return 0;
1106 pWnd = pWnd->child;
1108 if (!pWnd) return 0;
1110 /* For a child window, all siblings will have the same hInstance, */
1111 /* so we can look for the class once and for all. */
1113 if (className && (pWnd->dwStyle & WS_CHILD))
1115 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1116 return 0;
1120 for ( ; pWnd; pWnd = pWnd->next)
1122 if (className && !(pWnd->dwStyle & WS_CHILD))
1124 if (!(pClass = CLASS_FindClassByAtom( className, GetExePtr(pWnd->hInstance))))
1125 continue; /* Skip this window */
1128 if (pClass && (pWnd->class != pClass))
1129 continue; /* Not the right class */
1131 /* Now check the title */
1133 if (!title) return pWnd->hwndSelf;
1134 if (pWnd->text && !strcmp( pWnd->text, title )) return pWnd->hwndSelf;
1136 return 0;
1141 /***********************************************************************
1142 * FindWindow16 (USER.50)
1144 HWND16 WINAPI FindWindow16( SEGPTR className, LPCSTR title )
1146 return FindWindowEx16( 0, 0, className, title );
1150 /***********************************************************************
1151 * FindWindowEx16 (USER.427)
1153 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child,
1154 SEGPTR className, LPCSTR title )
1156 ATOM atom = 0;
1158 TRACE(win, "%04x %04x '%s' '%s'\n", parent,
1159 child, HIWORD(className)?(char *)PTR_SEG_TO_LIN(className):"",
1160 title ? title : "");
1162 if (className)
1164 /* If the atom doesn't exist, then no class */
1165 /* with this name exists either. */
1166 if (!(atom = GlobalFindAtom16( className ))) return 0;
1168 return WIN_FindWindow( parent, child, atom, title );
1172 /***********************************************************************
1173 * FindWindow32A (USER32.198)
1175 HWND32 WINAPI FindWindow32A( LPCSTR className, LPCSTR title )
1177 HWND32 ret = FindWindowEx32A( 0, 0, className, title );
1178 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1179 return ret;
1183 /***********************************************************************
1184 * FindWindowEx32A (USER32.199)
1186 HWND32 WINAPI FindWindowEx32A( HWND32 parent, HWND32 child,
1187 LPCSTR className, LPCSTR title )
1189 ATOM atom = 0;
1191 if (className)
1193 /* If the atom doesn't exist, then no class */
1194 /* with this name exists either. */
1195 if (!(atom = GlobalFindAtom32A( className )))
1197 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1198 return 0;
1201 return WIN_FindWindow( parent, child, atom, title );
1205 /***********************************************************************
1206 * FindWindowEx32W (USER32.200)
1208 HWND32 WINAPI FindWindowEx32W( HWND32 parent, HWND32 child,
1209 LPCWSTR className, LPCWSTR title )
1211 ATOM atom = 0;
1212 char *buffer;
1213 HWND32 hwnd;
1215 if (className)
1217 /* If the atom doesn't exist, then no class */
1218 /* with this name exists either. */
1219 if (!(atom = GlobalFindAtom32W( className )))
1221 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1222 return 0;
1225 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1226 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1227 HeapFree( GetProcessHeap(), 0, buffer );
1228 return hwnd;
1232 /***********************************************************************
1233 * FindWindow32W (USER32.201)
1235 HWND32 WINAPI FindWindow32W( LPCWSTR className, LPCWSTR title )
1237 return FindWindowEx32W( 0, 0, className, title );
1241 /**********************************************************************
1242 * WIN_GetDesktop
1244 WND *WIN_GetDesktop(void)
1246 return pWndDesktop;
1250 /**********************************************************************
1251 * GetDesktopWindow16 (USER.286)
1253 HWND16 WINAPI GetDesktopWindow16(void)
1255 return (HWND16)pWndDesktop->hwndSelf;
1259 /**********************************************************************
1260 * GetDesktopWindow32 (USER32.232)
1262 HWND32 WINAPI GetDesktopWindow32(void)
1264 return pWndDesktop->hwndSelf;
1268 /**********************************************************************
1269 * GetDesktopHwnd (USER.278)
1271 * Exactly the same thing as GetDesktopWindow(), but not documented.
1272 * Don't ask me why...
1274 HWND16 WINAPI GetDesktopHwnd(void)
1276 return (HWND16)pWndDesktop->hwndSelf;
1280 /*******************************************************************
1281 * EnableWindow16 (USER.34)
1283 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1285 return EnableWindow32( hwnd, enable );
1289 /*******************************************************************
1290 * EnableWindow32 (USER32.172)
1292 BOOL32 WINAPI EnableWindow32( HWND32 hwnd, BOOL32 enable )
1294 WND *wndPtr;
1296 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1297 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1299 /* Enable window */
1300 wndPtr->dwStyle &= ~WS_DISABLED;
1301 SendMessage32A( hwnd, WM_ENABLE, TRUE, 0 );
1302 return TRUE;
1304 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1306 /* Disable window */
1307 wndPtr->dwStyle |= WS_DISABLED;
1308 if ((hwnd == GetFocus32()) || IsChild32( hwnd, GetFocus32() ))
1309 SetFocus32( 0 ); /* A disabled window can't have the focus */
1310 if ((hwnd == GetCapture32()) || IsChild32( hwnd, GetCapture32() ))
1311 ReleaseCapture(); /* A disabled window can't capture the mouse */
1312 SendMessage32A( hwnd, WM_ENABLE, FALSE, 0 );
1313 return FALSE;
1315 return ((wndPtr->dwStyle & WS_DISABLED) != 0);
1319 /***********************************************************************
1320 * IsWindowEnabled16 (USER.35)
1322 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1324 return IsWindowEnabled32(hWnd);
1328 /***********************************************************************
1329 * IsWindowEnabled32 (USER32.349)
1331 BOOL32 WINAPI IsWindowEnabled32(HWND32 hWnd)
1333 WND * wndPtr;
1335 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1336 return !(wndPtr->dwStyle & WS_DISABLED);
1340 /***********************************************************************
1341 * IsWindowUnicode (USER32.350)
1343 BOOL32 WINAPI IsWindowUnicode( HWND32 hwnd )
1345 WND * wndPtr;
1347 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1348 return (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1352 /**********************************************************************
1353 * GetWindowWord16 (USER.133)
1355 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1357 return GetWindowWord32( hwnd, offset );
1361 /**********************************************************************
1362 * GetWindowWord32 (USER32.314)
1364 WORD WINAPI GetWindowWord32( HWND32 hwnd, INT32 offset )
1366 WND * wndPtr = WIN_FindWndPtr( hwnd );
1367 if (!wndPtr) return 0;
1368 if (offset >= 0)
1370 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1372 WARN( win, "Invalid offset %d\n", offset );
1373 return 0;
1375 return *(WORD *)(((char *)wndPtr->wExtra) + offset);
1377 switch(offset)
1379 case GWW_ID:
1380 if (HIWORD(wndPtr->wIDmenu))
1381 WARN( win,"GWW_ID: discards high bits of 0x%08x!\n",
1382 wndPtr->wIDmenu);
1383 return (WORD)wndPtr->wIDmenu;
1384 case GWW_HWNDPARENT:
1385 return wndPtr->parent ?
1386 wndPtr->parent->hwndSelf : (
1387 wndPtr->owner ?
1388 wndPtr->owner->hwndSelf :
1390 case GWW_HINSTANCE:
1391 if (HIWORD(wndPtr->hInstance))
1392 WARN(win,"GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1393 wndPtr->hInstance);
1394 return (WORD)wndPtr->hInstance;
1395 default:
1396 WARN( win, "Invalid offset %d\n", offset );
1397 return 0;
1402 /**********************************************************************
1403 * WIN_GetWindowInstance
1405 HINSTANCE32 WIN_GetWindowInstance( HWND32 hwnd )
1407 WND * wndPtr = WIN_FindWndPtr( hwnd );
1408 if (!wndPtr) return (HINSTANCE32)0;
1409 return wndPtr->hInstance;
1413 /**********************************************************************
1414 * SetWindowWord16 (USER.134)
1416 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1418 return SetWindowWord32( hwnd, offset, newval );
1422 /**********************************************************************
1423 * SetWindowWord32 (USER32.524)
1425 WORD WINAPI SetWindowWord32( HWND32 hwnd, INT32 offset, WORD newval )
1427 WORD *ptr, retval;
1428 WND * wndPtr = WIN_FindWndPtr( hwnd );
1429 if (!wndPtr) return 0;
1430 if (offset >= 0)
1432 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1434 WARN( win, "Invalid offset %d\n", offset );
1435 return 0;
1437 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1439 else switch(offset)
1441 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1442 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1443 case GWW_HWNDPARENT: return SetParent32( hwnd, newval );
1444 default:
1445 WARN( win, "Invalid offset %d\n", offset );
1446 return 0;
1448 retval = *ptr;
1449 *ptr = newval;
1450 return retval;
1454 /**********************************************************************
1455 * WIN_GetWindowLong
1457 * Helper function for GetWindowLong().
1459 static LONG WIN_GetWindowLong( HWND32 hwnd, INT32 offset, WINDOWPROCTYPE type )
1461 LONG retval;
1462 WND * wndPtr = WIN_FindWndPtr( hwnd );
1463 if (!wndPtr) return 0;
1464 if (offset >= 0)
1466 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1468 WARN( win, "Invalid offset %d\n", offset );
1469 return 0;
1471 retval = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1472 /* Special case for dialog window procedure */
1473 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1474 return (LONG)WINPROC_GetProc( (HWINDOWPROC)retval, type );
1475 return retval;
1477 switch(offset)
1479 case GWL_USERDATA: return wndPtr->userdata;
1480 case GWL_STYLE: return wndPtr->dwStyle;
1481 case GWL_EXSTYLE: return wndPtr->dwExStyle;
1482 case GWL_ID: return (LONG)wndPtr->wIDmenu;
1483 case GWL_WNDPROC: return (LONG)WINPROC_GetProc( wndPtr->winproc,
1484 type );
1485 case GWL_HWNDPARENT: return wndPtr->parent ?
1486 (HWND32)wndPtr->parent->hwndSelf : 0;
1487 case GWL_HINSTANCE: return wndPtr->hInstance;
1488 default:
1489 WARN( win, "Unknown offset %d\n", offset );
1491 return 0;
1495 /**********************************************************************
1496 * WIN_SetWindowLong
1498 * Helper function for SetWindowLong().
1500 * 0 is the failure code. However, in the case of failure SetLastError
1501 * must be set to distinguish between a 0 return value and a failure.
1503 * FIXME: The error values for SetLastError may not be right. Can
1504 * someone check with the real thing?
1506 static LONG WIN_SetWindowLong( HWND32 hwnd, INT32 offset, LONG newval,
1507 WINDOWPROCTYPE type )
1509 LONG *ptr, retval;
1510 WND * wndPtr = WIN_FindWndPtr( hwnd );
1511 STYLESTRUCT style;
1513 TRACE(win,"%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1515 if (!wndPtr)
1517 /* Is this the right error? */
1518 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1519 return 0;
1522 if (offset >= 0)
1524 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1526 WARN( win, "Invalid offset %d\n", offset );
1528 /* Is this the right error? */
1529 SetLastError( ERROR_OUTOFMEMORY );
1531 return 0;
1533 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1534 /* Special case for dialog window procedure */
1535 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1537 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1538 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1539 type, WIN_PROC_WINDOW );
1540 return retval;
1543 else switch(offset)
1545 case GWL_ID:
1546 ptr = (DWORD*)&wndPtr->wIDmenu;
1547 break;
1548 case GWL_HINSTANCE:
1549 return SetWindowWord32( hwnd, offset, newval );
1550 case GWL_WNDPROC:
1551 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1552 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1553 type, WIN_PROC_WINDOW );
1554 return retval;
1555 case GWL_STYLE:
1556 style.styleOld = wndPtr->dwStyle;
1557 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
1558 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
1560 if (wndPtr->flags & WIN_ISWIN32)
1561 SendMessage32A(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1562 wndPtr->dwStyle = style.styleNew;
1563 if (wndPtr->flags & WIN_ISWIN32)
1564 SendMessage32A(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1565 return style.styleOld;
1567 case GWL_USERDATA:
1568 ptr = &wndPtr->userdata;
1569 break;
1570 case GWL_EXSTYLE:
1571 style.styleOld = wndPtr->dwExStyle;
1572 style.styleNew = newval;
1573 if (wndPtr->flags & WIN_ISWIN32)
1574 SendMessage32A(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1575 wndPtr->dwExStyle = newval;
1576 if (wndPtr->flags & WIN_ISWIN32)
1577 SendMessage32A(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1578 return style.styleOld;
1580 default:
1581 WARN( win, "Invalid offset %d\n", offset );
1583 /* Don't think this is right error but it should do */
1584 SetLastError( ERROR_OUTOFMEMORY );
1586 return 0;
1588 retval = *ptr;
1589 *ptr = newval;
1590 return retval;
1594 /**********************************************************************
1595 * GetWindowLong16 (USER.135)
1597 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1599 return WIN_GetWindowLong( (HWND32)hwnd, offset, WIN_PROC_16 );
1603 /**********************************************************************
1604 * GetWindowLong32A (USER32.305)
1606 LONG WINAPI GetWindowLong32A( HWND32 hwnd, INT32 offset )
1608 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1612 /**********************************************************************
1613 * GetWindowLong32W (USER32.306)
1615 LONG WINAPI GetWindowLong32W( HWND32 hwnd, INT32 offset )
1617 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1621 /**********************************************************************
1622 * SetWindowLong16 (USER.136)
1624 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1626 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1630 /**********************************************************************
1631 * SetWindowLong32A (USER32.517)
1633 LONG WINAPI SetWindowLong32A( HWND32 hwnd, INT32 offset, LONG newval )
1635 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1639 /**********************************************************************
1640 * SetWindowLong32W (USER32.518) Set window attribute
1642 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
1643 * value in a window's extra memory.
1645 * The _hwnd_ parameter specifies the window. is the handle to a
1646 * window that has extra memory. The _newval_ parameter contains the
1647 * new attribute or extra memory value. If positive, the _offset_
1648 * parameter is the byte-addressed location in the window's extra
1649 * memory to set. If negative, _offset_ specifies the window
1650 * attribute to set, and should be one of the following values:
1652 * GWL_EXSTYLE The window's extended window style
1654 * GWL_STYLE The window's window style.
1656 * GWL_WNDPROC Pointer to the window's window procedure.
1658 * GWL_HINSTANCE The window's pplication instance handle.
1660 * GWL_ID The window's identifier.
1662 * GWL_USERDATA The window's user-specified data.
1664 * If the window is a dialog box, the _offset_ parameter can be one of
1665 * the following values:
1667 * DWL_DLGPROC The address of the window's dialog box procedure.
1669 * DWL_MSGRESULT The return value of a message
1670 * that the dialog box procedure processed.
1672 * DWL_USER Application specific information.
1674 * RETURNS
1676 * If successful, returns the previous value located at _offset_. Otherwise,
1677 * returns 0.
1679 * NOTES
1681 * Extra memory for a window class is specified by a nonzero cbWndExtra
1682 * parameter of the WNDCLASS structure passed to RegisterClass() at the
1683 * time of class creation.
1685 * Using GWL_WNDPROC to set a new window procedure effectively creates
1686 * a window subclass. Use CallWindowProc() in the new windows procedure
1687 * to pass messages to the superclass's window procedure.
1689 * The user data is reserved for use by the application which created
1690 * the window.
1692 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
1693 * instead, call the EnableWindow() function to change the window's
1694 * disabled state.
1696 * Do not use GWL_HWNDPARENT to reset the window's parent, use
1697 * SetParent() instead.
1699 * BUGS
1701 * GWL_STYLE does not dispatch WM_STYLE_... messages.
1703 * CONFORMANCE
1705 * ECMA-234, Win32
1708 LONG WINAPI SetWindowLong32W(
1709 HWND32 hwnd, /* window to alter */
1710 INT32 offset, /* offset, in bytes, of location to alter */
1711 LONG newval /* new value of location */
1713 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1717 /*******************************************************************
1718 * GetWindowText16 (USER.36)
1720 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
1722 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1726 /*******************************************************************
1727 * GetWindowText32A (USER32.309)
1729 INT32 WINAPI GetWindowText32A( HWND32 hwnd, LPSTR lpString, INT32 nMaxCount )
1731 return (INT32)SendMessage32A( hwnd, WM_GETTEXT, nMaxCount,
1732 (LPARAM)lpString );
1735 /*******************************************************************
1736 * InternalGetWindowText (USER32.326)
1738 INT32 WINAPI InternalGetWindowText(HWND32 hwnd,LPWSTR lpString,INT32 nMaxCount )
1740 FIXME(win,"(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
1741 return GetWindowText32W(hwnd,lpString,nMaxCount);
1745 /*******************************************************************
1746 * GetWindowText32W (USER32.312)
1748 INT32 WINAPI GetWindowText32W( HWND32 hwnd, LPWSTR lpString, INT32 nMaxCount )
1750 return (INT32)SendMessage32W( hwnd, WM_GETTEXT, nMaxCount,
1751 (LPARAM)lpString );
1755 /*******************************************************************
1756 * SetWindowText16 (USER.37)
1758 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
1760 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1764 /*******************************************************************
1765 * SetWindowText32A (USER32.521)
1767 BOOL32 WINAPI SetWindowText32A( HWND32 hwnd, LPCSTR lpString )
1769 return (BOOL32)SendMessage32A( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1773 /*******************************************************************
1774 * SetWindowText32W (USER32.523)
1776 BOOL32 WINAPI SetWindowText32W( HWND32 hwnd, LPCWSTR lpString )
1778 return (BOOL32)SendMessage32W( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1782 /*******************************************************************
1783 * GetWindowTextLength16 (USER.38)
1785 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
1787 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1791 /*******************************************************************
1792 * GetWindowTextLength32A (USER32.310)
1794 INT32 WINAPI GetWindowTextLength32A( HWND32 hwnd )
1796 return SendMessage32A( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1799 /*******************************************************************
1800 * GetWindowTextLength32W (USER32.311)
1802 INT32 WINAPI GetWindowTextLength32W( HWND32 hwnd )
1804 return SendMessage32W( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1808 /*******************************************************************
1809 * IsWindow16 (USER.47)
1811 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
1813 return IsWindow32( hwnd );
1816 void WINAPI WIN16_IsWindow16( CONTEXT *context )
1818 WORD *stack = PTR_SEG_OFF_TO_LIN(SS_reg(context), SP_reg(context));
1819 HWND16 hwnd = (HWND16)stack[2];
1821 AX_reg(context) = IsWindow32( hwnd );
1822 ES_reg(context) = USER_HeapSel;
1826 /*******************************************************************
1827 * IsWindow32 (USER32.348)
1829 BOOL32 WINAPI IsWindow32( HWND32 hwnd )
1831 WND * wndPtr = WIN_FindWndPtr( hwnd );
1832 return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
1836 /*****************************************************************
1837 * GetParent16 (USER.46)
1839 HWND16 WINAPI GetParent16( HWND16 hwnd )
1841 return (HWND16)GetParent32( hwnd );
1845 /*****************************************************************
1846 * GetParent32 (USER32.278)
1848 HWND32 WINAPI GetParent32( HWND32 hwnd )
1850 WND *wndPtr = WIN_FindWndPtr(hwnd);
1851 if ((!wndPtr) || (!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD)))) return 0;
1852 wndPtr = (wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner;
1853 return wndPtr ? wndPtr->hwndSelf : 0;
1856 /*****************************************************************
1857 * WIN_GetTopParent
1859 * Get the top-level parent for a child window.
1861 WND* WIN_GetTopParentPtr( WND* pWnd )
1863 while( pWnd && (pWnd->dwStyle & WS_CHILD)) pWnd = pWnd->parent;
1864 return pWnd;
1867 /*****************************************************************
1868 * WIN_GetTopParent
1870 * Get the top-level parent for a child window.
1872 HWND32 WIN_GetTopParent( HWND32 hwnd )
1874 WND *wndPtr = WIN_GetTopParentPtr ( WIN_FindWndPtr( hwnd ) );
1875 return wndPtr ? wndPtr->hwndSelf : 0;
1879 /*****************************************************************
1880 * SetParent16 (USER.233)
1882 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
1884 return SetParent32( hwndChild, hwndNewParent );
1888 /*****************************************************************
1889 * SetParent32 (USER32.495)
1891 HWND32 WINAPI SetParent32( HWND32 hwndChild, HWND32 hwndNewParent )
1893 WND *wndPtr = WIN_FindWndPtr( hwndChild );
1894 WND *pWndNewParent =
1895 (hwndNewParent) ? WIN_FindWndPtr( hwndNewParent ) : pWndDesktop;
1896 WND *pWndOldParent =
1897 (wndPtr)?(*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent):NULL;
1899 return pWndOldParent?pWndOldParent->hwndSelf:0;
1902 /*******************************************************************
1903 * IsChild16 (USER.48)
1905 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
1907 return IsChild32(parent,child);
1911 /*******************************************************************
1912 * IsChild32 (USER32.339)
1914 BOOL32 WINAPI IsChild32( HWND32 parent, HWND32 child )
1916 WND * wndPtr = WIN_FindWndPtr( child );
1917 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1919 wndPtr = wndPtr->parent;
1920 if (wndPtr->hwndSelf == parent) return TRUE;
1922 return FALSE;
1926 /***********************************************************************
1927 * IsWindowVisible16 (USER.49)
1929 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
1931 return IsWindowVisible32(hwnd);
1935 /***********************************************************************
1936 * IsWindowVisible32 (USER32.351)
1938 BOOL32 WINAPI IsWindowVisible32( HWND32 hwnd )
1940 WND *wndPtr = WIN_FindWndPtr( hwnd );
1941 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1943 if (!(wndPtr->dwStyle & WS_VISIBLE)) return FALSE;
1944 wndPtr = wndPtr->parent;
1946 return (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
1950 /***********************************************************************
1951 * WIN_IsWindowDrawable
1953 * hwnd is drawable when it is visible, all parents are not
1954 * minimized, and it is itself not minimized unless we are
1955 * trying to draw its default class icon.
1957 BOOL32 WIN_IsWindowDrawable( WND* wnd, BOOL32 icon )
1959 if( (wnd->dwStyle & WS_MINIMIZE &&
1960 icon && wnd->class->hIcon) ||
1961 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
1962 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
1963 if( wnd->dwStyle & WS_MINIMIZE ||
1964 !(wnd->dwStyle & WS_VISIBLE) ) break;
1965 return (wnd == NULL);
1969 /*******************************************************************
1970 * GetTopWindow16 (USER.229)
1972 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
1974 return GetTopWindow32(hwnd);
1978 /*******************************************************************
1979 * GetTopWindow32 (USER.229)
1981 HWND32 WINAPI GetTopWindow32( HWND32 hwnd )
1983 WND * wndPtr = WIN_FindWndPtr( hwnd );
1984 if (wndPtr && wndPtr->child) return wndPtr->child->hwndSelf;
1985 else return 0;
1989 /*******************************************************************
1990 * GetWindow16 (USER.262)
1992 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
1994 return GetWindow32( hwnd,rel );
1998 /*******************************************************************
1999 * GetWindow32 (USER32.302)
2001 HWND32 WINAPI GetWindow32( HWND32 hwnd, WORD rel )
2003 WND * wndPtr = WIN_FindWndPtr( hwnd );
2004 if (!wndPtr) return 0;
2005 switch(rel)
2007 case GW_HWNDFIRST:
2008 if (wndPtr->parent) return wndPtr->parent->child->hwndSelf;
2009 else return 0;
2011 case GW_HWNDLAST:
2012 if (!wndPtr->parent) return 0; /* Desktop window */
2013 while (wndPtr->next) wndPtr = wndPtr->next;
2014 return wndPtr->hwndSelf;
2016 case GW_HWNDNEXT:
2017 if (!wndPtr->next) return 0;
2018 return wndPtr->next->hwndSelf;
2020 case GW_HWNDPREV:
2021 if (!wndPtr->parent) return 0; /* Desktop window */
2022 wndPtr = wndPtr->parent->child; /* First sibling */
2023 if (wndPtr->hwndSelf == hwnd) return 0; /* First in list */
2024 while (wndPtr->next)
2026 if (wndPtr->next->hwndSelf == hwnd) return wndPtr->hwndSelf;
2027 wndPtr = wndPtr->next;
2029 return 0;
2031 case GW_OWNER:
2032 return wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2034 case GW_CHILD:
2035 return wndPtr->child ? wndPtr->child->hwndSelf : 0;
2037 return 0;
2041 /*******************************************************************
2042 * GetNextWindow16 (USER.230)
2044 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2046 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2047 return GetWindow16( hwnd, flag );
2050 /*******************************************************************
2051 * ShowOwnedPopups16 (USER.265)
2053 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2055 ShowOwnedPopups32( owner, fShow );
2059 /*******************************************************************
2060 * ShowOwnedPopups32 (USER32.531)
2062 BOOL32 WINAPI ShowOwnedPopups32( HWND32 owner, BOOL32 fShow )
2064 WND *pWnd = pWndDesktop->child;
2065 while (pWnd)
2067 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
2068 (pWnd->dwStyle & WS_POPUP))
2069 ShowWindow32( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
2070 pWnd = pWnd->next;
2072 return TRUE;
2076 /*******************************************************************
2077 * GetLastActivePopup16 (USER.287)
2079 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2081 return GetLastActivePopup32( hwnd );
2084 /*******************************************************************
2085 * GetLastActivePopup32 (USER32.256)
2087 HWND32 WINAPI GetLastActivePopup32( HWND32 hwnd )
2089 WND *wndPtr;
2090 wndPtr = WIN_FindWndPtr(hwnd);
2091 if (wndPtr == NULL) return hwnd;
2092 return wndPtr->hwndLastActive;
2096 /*******************************************************************
2097 * WIN_BuildWinArray
2099 * Build an array of pointers to the children of a given window.
2100 * The array must be freed with HeapFree(SystemHeap). Return NULL
2101 * when no windows are found.
2103 WND **WIN_BuildWinArray( WND *wndPtr, UINT32 bwaFlags, UINT32* pTotal )
2105 WND **list, **ppWnd;
2106 WND *pWnd;
2107 UINT32 count, skipOwned, skipHidden;
2108 DWORD skipFlags;
2110 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2111 skipOwned = bwaFlags & BWA_SKIPOWNED;
2112 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2113 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2115 /* First count the windows */
2117 if (!wndPtr) wndPtr = pWndDesktop;
2118 for (pWnd = wndPtr->child, count = 0; pWnd; pWnd = pWnd->next)
2120 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
2121 if( !skipHidden || pWnd->dwStyle & WS_VISIBLE ) count++;
2124 if( count )
2126 /* Now build the list of all windows */
2128 if ((list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * (count + 1))))
2130 for (pWnd = wndPtr->child, ppWnd = list, count = 0; pWnd; pWnd = pWnd->next)
2132 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
2133 if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2135 *ppWnd++ = pWnd;
2136 count++;
2139 *ppWnd = NULL;
2141 else count = 0;
2142 } else list = NULL;
2144 if( pTotal ) *pTotal = count;
2145 return list;
2149 /*******************************************************************
2150 * EnumWindows16 (USER.54)
2152 BOOL16 WINAPI EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
2154 WND **list, **ppWnd;
2156 /* We have to build a list of all windows first, to avoid */
2157 /* unpleasant side-effects, for instance if the callback */
2158 /* function changes the Z-order of the windows. */
2160 if (!(list = WIN_BuildWinArray( pWndDesktop, 0, NULL ))) return FALSE;
2162 /* Now call the callback function for every window */
2164 for (ppWnd = list; *ppWnd; ppWnd++)
2166 /* Make sure that the window still exists */
2167 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2168 if (!lpEnumFunc( (*ppWnd)->hwndSelf, lParam )) break;
2170 HeapFree( SystemHeap, 0, list );
2171 return TRUE;
2175 /*******************************************************************
2176 * EnumWindows32 (USER32.193)
2178 BOOL32 WINAPI EnumWindows32( WNDENUMPROC32 lpEnumFunc, LPARAM lParam )
2180 return (BOOL32)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2184 /**********************************************************************
2185 * EnumTaskWindows16 (USER.225)
2187 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2188 LPARAM lParam )
2190 WND **list, **ppWnd;
2192 /* This function is the same as EnumWindows(), */
2193 /* except for an added check on the window's task. */
2195 if (!(list = WIN_BuildWinArray( pWndDesktop, 0, NULL ))) return FALSE;
2197 /* Now call the callback function for every window */
2199 for (ppWnd = list; *ppWnd; ppWnd++)
2201 /* Make sure that the window still exists */
2202 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2203 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2204 if (!func( (*ppWnd)->hwndSelf, lParam )) break;
2206 HeapFree( SystemHeap, 0, list );
2207 return TRUE;
2211 /**********************************************************************
2212 * EnumThreadWindows (USER32.190)
2214 BOOL32 WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC32 func, LPARAM lParam )
2216 THDB *tdb = THREAD_ID_TO_THDB(id);
2218 return (BOOL16)EnumTaskWindows16(tdb->teb.htask16, (WNDENUMPROC16)func, lParam);
2222 /**********************************************************************
2223 * WIN_EnumChildWindows
2225 * Helper function for EnumChildWindows().
2227 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2228 LPARAM lParam )
2230 WND **childList;
2231 BOOL16 ret = FALSE;
2233 for ( ; *ppWnd; ppWnd++)
2235 /* Make sure that the window still exists */
2236 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2237 /* Build children list first */
2238 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2239 ret = func( (*ppWnd)->hwndSelf, lParam );
2240 if (childList)
2242 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2243 HeapFree( SystemHeap, 0, childList );
2245 if (!ret) return FALSE;
2247 return TRUE;
2251 /**********************************************************************
2252 * EnumChildWindows16 (USER.55)
2254 BOOL16 WINAPI EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
2255 LPARAM lParam )
2257 WND **list, *pParent;
2259 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2260 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL ))) return FALSE;
2261 WIN_EnumChildWindows( list, func, lParam );
2262 HeapFree( SystemHeap, 0, list );
2263 return TRUE;
2267 /**********************************************************************
2268 * EnumChildWindows32 (USER32.178)
2270 BOOL32 WINAPI EnumChildWindows32( HWND32 parent, WNDENUMPROC32 func,
2271 LPARAM lParam )
2273 return (BOOL32)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2274 lParam );
2278 /*******************************************************************
2279 * AnyPopup16 (USER.52)
2281 BOOL16 WINAPI AnyPopup16(void)
2283 return AnyPopup32();
2287 /*******************************************************************
2288 * AnyPopup32 (USER32.4)
2290 BOOL32 WINAPI AnyPopup32(void)
2292 WND *wndPtr;
2293 for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next)
2294 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE)) return TRUE;
2295 return FALSE;
2299 /*******************************************************************
2300 * FlashWindow16 (USER.105)
2302 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2304 return FlashWindow32( hWnd, bInvert );
2308 /*******************************************************************
2309 * FlashWindow32 (USER32.202)
2311 BOOL32 WINAPI FlashWindow32( HWND32 hWnd, BOOL32 bInvert )
2313 WND *wndPtr = WIN_FindWndPtr(hWnd);
2315 TRACE(win,"%04x\n", hWnd);
2317 if (!wndPtr) return FALSE;
2319 if (wndPtr->dwStyle & WS_MINIMIZE)
2321 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2323 HDC32 hDC = GetDC32(hWnd);
2325 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2326 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2328 ReleaseDC32( hWnd, hDC );
2329 wndPtr->flags |= WIN_NCACTIVATED;
2331 else
2333 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2334 RDW_UPDATENOW | RDW_FRAME, 0 );
2335 wndPtr->flags &= ~WIN_NCACTIVATED;
2337 return TRUE;
2339 else
2341 WPARAM16 wparam;
2342 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2343 else wparam = (hWnd == GetActiveWindow32());
2345 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2346 return wparam;
2351 /*******************************************************************
2352 * SetSysModalWindow16 (USER.188)
2354 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
2356 HWND32 hWndOldModal = hwndSysModal;
2357 hwndSysModal = hWnd;
2358 FIXME(win, "EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2359 return hWndOldModal;
2363 /*******************************************************************
2364 * GetSysModalWindow16 (USER.52)
2366 HWND16 WINAPI GetSysModalWindow16(void)
2368 return hwndSysModal;
2372 /*******************************************************************
2373 * GetWindowContextHelpId (USER32.303)
2375 DWORD WINAPI GetWindowContextHelpId( HWND32 hwnd )
2377 WND *wnd = WIN_FindWndPtr( hwnd );
2378 if (!wnd) return 0;
2379 return wnd->helpContext;
2383 /*******************************************************************
2384 * SetWindowContextHelpId (USER32.515)
2386 BOOL32 WINAPI SetWindowContextHelpId( HWND32 hwnd, DWORD id )
2388 WND *wnd = WIN_FindWndPtr( hwnd );
2389 if (!wnd) return FALSE;
2390 wnd->helpContext = id;
2391 return TRUE;
2395 /*******************************************************************
2396 * DRAG_QueryUpdate
2398 * recursively find a child that contains spDragInfo->pt point
2399 * and send WM_QUERYDROPOBJECT
2401 BOOL16 DRAG_QueryUpdate( HWND32 hQueryWnd, SEGPTR spDragInfo, BOOL32 bNoSend )
2403 BOOL16 wParam,bResult = 0;
2404 POINT32 pt;
2405 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
2406 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
2407 RECT32 tempRect;
2409 if( !ptrQueryWnd || !ptrDragInfo ) return 0;
2411 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
2413 GetWindowRect32(hQueryWnd,&tempRect);
2415 if( !PtInRect32(&tempRect,pt) ||
2416 (ptrQueryWnd->dwStyle & WS_DISABLED) )
2417 return 0;
2419 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
2421 tempRect = ptrQueryWnd->rectClient;
2422 if(ptrQueryWnd->dwStyle & WS_CHILD)
2423 MapWindowPoints32( ptrQueryWnd->parent->hwndSelf, 0,
2424 (LPPOINT32)&tempRect, 2 );
2426 if (PtInRect32( &tempRect, pt))
2428 wParam = 0;
2430 for (ptrWnd = ptrQueryWnd->child; ptrWnd ;ptrWnd = ptrWnd->next)
2431 if( ptrWnd->dwStyle & WS_VISIBLE )
2433 GetWindowRect32( ptrWnd->hwndSelf, &tempRect );
2434 if (PtInRect32( &tempRect, pt )) break;
2437 if(ptrWnd)
2439 TRACE(msg,"hwnd = %04x, %d %d - %d %d\n",
2440 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
2441 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
2442 if( !(ptrWnd->dwStyle & WS_DISABLED) )
2443 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
2446 if(bResult) return bResult;
2448 else wParam = 1;
2450 else wParam = 1;
2452 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
2454 ptrDragInfo->hScope = hQueryWnd;
2456 bResult = ( bNoSend )
2457 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
2458 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
2459 (WPARAM16)wParam ,(LPARAM) spDragInfo );
2460 if( !bResult )
2461 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
2463 return bResult;
2467 /*******************************************************************
2468 * DragDetect (USER.465)
2470 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
2472 POINT32 pt32;
2473 CONV_POINT16TO32( &pt, &pt32 );
2474 return DragDetect32( hWnd, pt32 );
2477 /*******************************************************************
2478 * DragDetect32 (USER32.151)
2480 BOOL32 WINAPI DragDetect32( HWND32 hWnd, POINT32 pt )
2482 MSG16 msg;
2483 RECT16 rect;
2485 rect.left = pt.x - wDragWidth;
2486 rect.right = pt.x + wDragWidth;
2488 rect.top = pt.y - wDragHeight;
2489 rect.bottom = pt.y + wDragHeight;
2491 SetCapture32(hWnd);
2493 while(1)
2495 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
2497 if( msg.message == WM_LBUTTONUP )
2499 ReleaseCapture();
2500 return 0;
2502 if( msg.message == WM_MOUSEMOVE )
2504 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
2506 ReleaseCapture();
2507 return 1;
2511 WaitMessage();
2513 return 0;
2516 /******************************************************************************
2517 * DragObject16 (USER.464)
2519 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
2520 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
2522 MSG16 msg;
2523 LPDRAGINFO lpDragInfo;
2524 SEGPTR spDragInfo;
2525 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
2526 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
2527 WND *wndPtr = WIN_FindWndPtr(hWnd);
2528 HCURSOR16 hCurrentCursor = 0;
2529 HWND16 hCurrentWnd = 0;
2531 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
2532 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
2534 if( !lpDragInfo || !spDragInfo ) return 0L;
2536 hBummer = LoadCursor16(0, IDC_BUMMER16);
2538 if( !hBummer || !wndPtr )
2540 GlobalFree16(hDragInfo);
2541 return 0L;
2544 if(hCursor)
2546 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
2548 GlobalFree16(hDragInfo);
2549 return 0L;
2552 if( hDragCursor == hCursor ) hDragCursor = 0;
2553 else hCursor = hDragCursor;
2555 hOldCursor = SetCursor32(hDragCursor);
2558 lpDragInfo->hWnd = hWnd;
2559 lpDragInfo->hScope = 0;
2560 lpDragInfo->wFlags = wObj;
2561 lpDragInfo->hList = szList; /* near pointer! */
2562 lpDragInfo->hOfStruct = hOfStruct;
2563 lpDragInfo->l = 0L;
2565 SetCapture32(hWnd);
2566 ShowCursor32( TRUE );
2570 do{ WaitMessage(); }
2571 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
2573 *(lpDragInfo+1) = *lpDragInfo;
2575 lpDragInfo->pt = msg.pt;
2577 /* update DRAGINFO struct */
2578 TRACE(msg,"lpDI->hScope = %04x\n",lpDragInfo->hScope);
2580 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
2581 hCurrentCursor = hCursor;
2582 else
2584 hCurrentCursor = hBummer;
2585 lpDragInfo->hScope = 0;
2587 if( hCurrentCursor )
2588 SetCursor32(hCurrentCursor);
2590 /* send WM_DRAGLOOP */
2591 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
2592 (LPARAM) spDragInfo );
2593 /* send WM_DRAGSELECT or WM_DRAGMOVE */
2594 if( hCurrentWnd != lpDragInfo->hScope )
2596 if( hCurrentWnd )
2597 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
2598 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
2599 HIWORD(spDragInfo)) );
2600 hCurrentWnd = lpDragInfo->hScope;
2601 if( hCurrentWnd )
2602 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
2604 else
2605 if( hCurrentWnd )
2606 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
2608 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
2610 ReleaseCapture();
2611 ShowCursor32( FALSE );
2613 if( hCursor )
2615 SetCursor32( hOldCursor );
2616 if (hDragCursor) DestroyCursor32( hDragCursor );
2619 if( hCurrentCursor != hBummer )
2620 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
2621 (WPARAM16)hWnd, (LPARAM)spDragInfo );
2622 else
2623 msg.lParam = 0;
2624 GlobalFree16(hDragInfo);
2626 return (DWORD)(msg.lParam);