Started moving some X11 window management code to windows/x11drv.
[wine.git] / windows / win.c
blobbacc1d1efc2fcdf2153a82b9867149cdb92ea539
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 "color.h"
25 #include "shm_main_blk.h"
26 #include "dde_proc.h"
27 #include "clipboard.h"
28 #include "winproc.h"
29 #include "thread.h"
30 #include "process.h"
31 #include "debug.h"
32 #include "winerror.h"
33 #include "mdi.h"
35 /* Desktop window */
36 static WND *pWndDesktop = NULL;
38 static HWND32 hwndSysModal = 0;
40 static WORD wDragWidth = 4;
41 static WORD wDragHeight= 3;
43 /***********************************************************************
44 * WIN_FindWndPtr
46 * Return a pointer to the WND structure corresponding to a HWND.
48 WND * WIN_FindWndPtr( HWND32 hwnd )
50 WND * ptr;
52 if (!hwnd || HIWORD(hwnd)) return NULL;
53 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
54 if (ptr->dwMagic != WND_MAGIC) return NULL;
55 if (ptr->hwndSelf != hwnd)
57 ERR( win, "Can't happen: hwnd %04x self pointer is %04x\n",
58 hwnd, ptr->hwndSelf );
59 return NULL;
61 return ptr;
65 /***********************************************************************
66 * WIN_DumpWindow
68 * Dump the content of a window structure to stderr.
70 void WIN_DumpWindow( HWND32 hwnd )
72 WND *ptr;
73 char className[80];
74 int i;
76 if (!(ptr = WIN_FindWndPtr( hwnd )))
78 WARN( win, "%04x is not a window handle\n", hwnd );
79 return;
82 if (!GetClassName32A( hwnd, className, sizeof(className ) ))
83 strcpy( className, "#NULL#" );
85 TRACE( win, "Window %04x (%p):\n", hwnd, ptr );
86 DUMP( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
87 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
88 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
89 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
90 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
91 ptr->next, ptr->child, ptr->parent, ptr->owner,
92 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
93 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
94 ptr->dwStyle, ptr->dwExStyle, (UINT32)ptr->winproc,
95 ptr->text ? ptr->text : "",
96 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
97 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
98 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
99 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
101 if (ptr->class->cbWndExtra)
103 DUMP( "extra bytes:" );
104 for (i = 0; i < ptr->class->cbWndExtra; i++)
105 DUMP( " %02x", *((BYTE*)ptr->wExtra+i) );
106 DUMP( "\n" );
108 DUMP( "\n" );
112 /***********************************************************************
113 * WIN_WalkWindows
115 * Walk the windows tree and print each window on stderr.
117 void WIN_WalkWindows( HWND32 hwnd, int indent )
119 WND *ptr;
120 char className[80];
122 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop;
123 if (!ptr)
125 WARN( win, "Invalid window handle %04x\n", hwnd );
126 return;
129 if (!indent) /* first time around */
130 DUMP( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
131 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
132 " Text");
134 while (ptr)
136 DUMP( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
138 GlobalGetAtomName16(ptr->class->atomName,className,sizeof(className));
140 DUMP( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
141 (DWORD)ptr, ptr->hmemTaskQ, className,
142 (UINT32)ptr->dwStyle, (UINT32)ptr->winproc,
143 ptr->text?ptr->text:"<null>");
145 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
146 ptr = ptr->next;
151 /***********************************************************************
152 * WIN_GetXWindow
154 * Return the X window associated to a window.
156 Window WIN_GetXWindow( HWND32 hwnd )
158 WND *wndPtr = WIN_FindWndPtr( hwnd );
159 while (wndPtr && !wndPtr->window) wndPtr = wndPtr->parent;
160 return wndPtr ? wndPtr->window : 0;
164 /***********************************************************************
165 * WIN_UnlinkWindow
167 * Remove a window from the siblings linked list.
169 BOOL32 WIN_UnlinkWindow( HWND32 hwnd )
171 WND *wndPtr, **ppWnd;
173 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
174 ppWnd = &wndPtr->parent->child;
175 while (*ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
176 *ppWnd = wndPtr->next;
177 return TRUE;
181 /***********************************************************************
182 * WIN_LinkWindow
184 * Insert a window into the siblings linked list.
185 * The window is inserted after the specified window, which can also
186 * be specified as HWND_TOP or HWND_BOTTOM.
188 BOOL32 WIN_LinkWindow( HWND32 hwnd, HWND32 hwndInsertAfter )
190 WND *wndPtr, **ppWnd;
192 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
194 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
196 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
197 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
198 while (*ppWnd) ppWnd = &(*ppWnd)->next;
200 else /* Normal case */
202 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
203 if (!afterPtr) return FALSE;
204 ppWnd = &afterPtr->next;
206 wndPtr->next = *ppWnd;
207 *ppWnd = wndPtr;
208 return TRUE;
212 /***********************************************************************
213 * WIN_FindWinToRepaint
215 * Find a window that needs repaint.
217 HWND32 WIN_FindWinToRepaint( HWND32 hwnd, HQUEUE16 hQueue )
219 HWND32 hwndRet;
220 WND *pWnd = pWndDesktop;
222 /* Note: the desktop window never gets WM_PAINT messages
223 * The real reason why is because Windows DesktopWndProc
224 * does ValidateRgn inside WM_ERASEBKGND handler.
227 pWnd = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop->child;
229 for ( ; pWnd ; pWnd = pWnd->next )
231 if (!(pWnd->dwStyle & WS_VISIBLE))
233 TRACE(win, "skipping window %04x\n",
234 pWnd->hwndSelf );
235 continue;
237 if ((pWnd->hmemTaskQ == hQueue) &&
238 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))) break;
240 if (pWnd->child )
241 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
242 return hwndRet;
245 if (!pWnd) return 0;
247 hwndRet = pWnd->hwndSelf;
249 /* look among siblings if we got a transparent window */
250 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
251 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
253 pWnd = pWnd->next;
255 if (pWnd) hwndRet = pWnd->hwndSelf;
256 TRACE(win,"found %04x\n",hwndRet);
257 return hwndRet;
261 /***********************************************************************
262 * WIN_DestroyWindow
264 * Destroy storage associated to a window. "Internals" p.358
266 static WND* WIN_DestroyWindow( WND* wndPtr )
268 HWND32 hwnd = wndPtr->hwndSelf;
269 WND *pWnd;
271 TRACE(win, "%04x\n", wndPtr->hwndSelf );
273 #ifdef CONFIG_IPC
274 if (main_block)
275 DDE_DestroyWindow(wndPtr->hwndSelf);
276 #endif /* CONFIG_IPC */
278 /* free child windows */
280 while ((pWnd = wndPtr->child))
281 wndPtr->child = WIN_DestroyWindow( pWnd );
283 SendMessage32A( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
285 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
287 WINPOS_CheckInternalPos( hwnd );
288 if( hwnd == GetCapture32()) ReleaseCapture();
290 /* free resources associated with the window */
292 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
293 PROPERTY_RemoveWindowProps( wndPtr );
295 wndPtr->dwMagic = 0; /* Mark it as invalid */
297 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
299 if (wndPtr->hrgnUpdate > 1) DeleteObject32( wndPtr->hrgnUpdate );
300 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
303 /* toss stale messages from the queue */
305 if( wndPtr->hmemTaskQ )
307 int pos;
308 BOOL32 bPostQuit = FALSE;
309 WPARAM32 wQuitParam = 0;
310 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) GlobalLock16(wndPtr->hmemTaskQ);
312 while( (pos = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != -1 )
314 if( msgQ->messages[pos].msg.message == WM_QUIT )
316 bPostQuit = TRUE;
317 wQuitParam = msgQ->messages[pos].msg.wParam;
319 QUEUE_RemoveMsg(msgQ, pos);
321 /* repost WM_QUIT to make sure this app exits its message loop */
322 if( bPostQuit ) PostQuitMessage32(wQuitParam);
323 wndPtr->hmemTaskQ = 0;
326 if (!(wndPtr->dwStyle & WS_CHILD))
327 if (wndPtr->wIDmenu) DestroyMenu32( (HMENU32)wndPtr->wIDmenu );
328 if (wndPtr->hSysMenu) DestroyMenu32( wndPtr->hSysMenu );
329 if (wndPtr->window) EVENT_DestroyWindow( wndPtr );
330 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
331 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
332 wndPtr->hwndSelf = 0;
333 wndPtr->class->cWindows--;
334 wndPtr->class = NULL;
335 pWnd = wndPtr->next;
337 USER_HEAP_FREE( hwnd );
338 return pWnd;
341 /***********************************************************************
342 * WIN_ResetQueueWindows
344 * Reset the queue of all the children of a given window.
345 * Return TRUE if something was done.
347 BOOL32 WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
349 BOOL32 ret = FALSE;
351 if (hNew) /* Set a new queue */
353 for (wnd = wnd->child; (wnd); wnd = wnd->next)
355 if (wnd->hmemTaskQ == hQueue)
357 wnd->hmemTaskQ = hNew;
358 ret = TRUE;
360 if (wnd->child)
361 ret |= WIN_ResetQueueWindows( wnd->child, hQueue, hNew );
364 else /* Queue is being destroyed */
366 while (wnd->child)
368 WND *tmp = wnd->child;
369 ret = FALSE;
370 while (tmp)
372 if (tmp->hmemTaskQ == hQueue)
374 DestroyWindow32( tmp->hwndSelf );
375 ret = TRUE;
376 break;
378 if (tmp->child && WIN_ResetQueueWindows(tmp->child,hQueue,0))
379 ret = TRUE;
380 else
381 tmp = tmp->next;
383 if (!ret) break;
386 return ret;
389 /***********************************************************************
390 * WIN_CreateDesktopWindow
392 * Create the desktop window.
394 BOOL32 WIN_CreateDesktopWindow(void)
396 CLASS *class;
397 HWND32 hwndDesktop;
399 TRACE(win,"Creating desktop window\n");
401 if (!ICONTITLE_Init() ||
402 !WINPOS_CreateInternalPosAtom() ||
403 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
404 return FALSE;
406 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
407 if (!hwndDesktop) return FALSE;
408 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
410 pWndDesktop->next = NULL;
411 pWndDesktop->child = NULL;
412 pWndDesktop->parent = NULL;
413 pWndDesktop->owner = NULL;
414 pWndDesktop->class = class;
415 pWndDesktop->dwMagic = WND_MAGIC;
416 pWndDesktop->hwndSelf = hwndDesktop;
417 pWndDesktop->hInstance = 0;
418 pWndDesktop->rectWindow.left = 0;
419 pWndDesktop->rectWindow.top = 0;
420 pWndDesktop->rectWindow.right = SYSMETRICS_CXSCREEN;
421 pWndDesktop->rectWindow.bottom = SYSMETRICS_CYSCREEN;
422 pWndDesktop->rectClient = pWndDesktop->rectWindow;
423 pWndDesktop->text = NULL;
424 pWndDesktop->hmemTaskQ = 0; /* Desktop does not belong to a task */
425 pWndDesktop->hrgnUpdate = 0;
426 pWndDesktop->hwndLastActive = hwndDesktop;
427 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
428 WS_CLIPSIBLINGS;
429 pWndDesktop->dwExStyle = 0;
430 pWndDesktop->dce = NULL;
431 pWndDesktop->pVScroll = NULL;
432 pWndDesktop->pHScroll = NULL;
433 pWndDesktop->pProp = NULL;
434 pWndDesktop->wIDmenu = 0;
435 pWndDesktop->helpContext = 0;
436 pWndDesktop->flags = 0;
437 pWndDesktop->window = rootWindow;
438 pWndDesktop->hSysMenu = 0;
439 pWndDesktop->userdata = 0;
440 pWndDesktop->pDriver = &X11DRV_WND_Driver;
442 pWndDesktop->winproc = (WNDPROC16)class->winproc;
444 EVENT_RegisterWindow( pWndDesktop );
445 SendMessage32A( hwndDesktop, WM_NCCREATE, 0, 0 );
446 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
447 return TRUE;
451 /***********************************************************************
452 * WIN_CreateWindowEx
454 * Implementation of CreateWindowEx().
456 static HWND32 WIN_CreateWindowEx( CREATESTRUCT32A *cs, ATOM classAtom,
457 BOOL32 win32, BOOL32 unicode )
459 CLASS *classPtr;
460 WND *wndPtr;
461 HWND16 hwnd, hwndLinkAfter;
462 POINT32 maxSize, maxPos, minTrack, maxTrack;
463 LRESULT (CALLBACK *localSend32)(HWND32, UINT32, WPARAM32, LPARAM);
465 TRACE(win, "%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
466 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
467 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
468 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
469 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
471 /* Find the parent window */
473 if (cs->hwndParent)
475 /* Make sure parent is valid */
476 if (!IsWindow32( cs->hwndParent ))
478 WARN( win, "Bad parent %04x\n", cs->hwndParent );
479 return 0;
481 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
482 WARN( win, "No parent for child window\n" );
483 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
486 /* Find the window class */
487 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
489 char buffer[256];
490 GlobalGetAtomName32A( classAtom, buffer, sizeof(buffer) );
491 WARN( win, "Bad class '%s'\n", buffer );
492 return 0;
495 /* Fix the coordinates */
497 if (cs->x == CW_USEDEFAULT32)
499 PDB32 *pdb = PROCESS_Current();
500 if ( !(cs->style & (WS_CHILD | WS_POPUP))
501 && (pdb->env_db->startup_info->dwFlags & STARTF_USEPOSITION) )
503 cs->x = pdb->env_db->startup_info->dwX;
504 cs->y = pdb->env_db->startup_info->dwY;
506 else
508 cs->x = 0;
509 cs->y = 0;
512 if (cs->cx == CW_USEDEFAULT32)
514 PDB32 *pdb = PROCESS_Current();
515 if ( !(cs->style & (WS_CHILD | WS_POPUP))
516 && (pdb->env_db->startup_info->dwFlags & STARTF_USESIZE) )
518 cs->cx = pdb->env_db->startup_info->dwXSize;
519 cs->cy = pdb->env_db->startup_info->dwYSize;
521 else
523 cs->cx = 600; /* FIXME */
524 cs->cy = 400;
528 /* Create the window structure */
530 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
531 - sizeof(wndPtr->wExtra) )))
533 TRACE(win, "out of memory\n" );
534 return 0;
537 /* Fill the window structure */
539 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
540 wndPtr->next = NULL;
541 wndPtr->child = NULL;
543 if ((cs->style & WS_CHILD) && cs->hwndParent)
545 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
546 wndPtr->owner = NULL;
548 else
550 wndPtr->parent = pWndDesktop;
551 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
552 wndPtr->owner = NULL;
553 else
554 wndPtr->owner = WIN_GetTopParentPtr(WIN_FindWndPtr(cs->hwndParent));
557 wndPtr->pDriver = &X11DRV_WND_Driver;
558 wndPtr->window = 0;
559 wndPtr->class = classPtr;
560 wndPtr->winproc = classPtr->winproc;
561 wndPtr->dwMagic = WND_MAGIC;
562 wndPtr->hwndSelf = hwnd;
563 wndPtr->hInstance = cs->hInstance;
564 wndPtr->text = NULL;
565 wndPtr->hmemTaskQ = GetTaskQueue(0);
566 wndPtr->hrgnUpdate = 0;
567 wndPtr->hwndLastActive = hwnd;
568 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
569 wndPtr->dwExStyle = cs->dwExStyle;
570 wndPtr->wIDmenu = 0;
571 wndPtr->helpContext = 0;
572 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
573 wndPtr->pVScroll = NULL;
574 wndPtr->pHScroll = NULL;
575 wndPtr->pProp = NULL;
576 wndPtr->userdata = 0;
577 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
578 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
580 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
582 /* Call the WH_CBT hook */
584 hwndLinkAfter = (cs->style & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
586 if (HOOK_IsHooked( WH_CBT ))
588 CBT_CREATEWND32A cbtc;
589 LRESULT ret;
591 cbtc.lpcs = cs;
592 cbtc.hwndInsertAfter = hwndLinkAfter;
593 ret = unicode ? HOOK_CallHooks32W(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
594 : HOOK_CallHooks32A(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
595 if (ret)
597 TRACE(win, "CBT-hook returned 0\n");
598 USER_HEAP_FREE( hwnd );
599 return 0;
603 /* Increment class window counter */
605 classPtr->cWindows++;
607 /* Correct the window style */
609 if (!(cs->style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
611 wndPtr->dwStyle |= WS_CAPTION | WS_CLIPSIBLINGS;
612 wndPtr->flags |= WIN_NEED_SIZE;
614 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
616 /* Get class or window DC if needed */
618 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
619 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
620 else wndPtr->dce = NULL;
622 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
624 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
626 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
627 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
628 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
629 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
630 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
633 if(cs->style & WS_CHILD)
635 if(cs->cx < 0) cs->cx = 0;
636 if(cs->cy < 0) cs->cy = 0;
638 else
640 if (cs->cx <= 0) cs->cx = 1;
641 if (cs->cy <= 0) cs->cy = 1;
644 wndPtr->rectWindow.left = cs->x;
645 wndPtr->rectWindow.top = cs->y;
646 wndPtr->rectWindow.right = cs->x + cs->cx;
647 wndPtr->rectWindow.bottom = cs->y + cs->cy;
648 wndPtr->rectClient = wndPtr->rectWindow;
650 (*wndPtr->pDriver->pCreateWindow)(wndPtr, classPtr, cs, unicode);
652 /* Set the window menu */
654 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
656 if (cs->hMenu) SetMenu32(hwnd, cs->hMenu);
657 else
659 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
660 if (classPtr->menuNameA)
661 cs->hMenu = HIWORD(classPtr->menuNameA) ?
662 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
663 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
664 #else
665 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
666 if (menuName)
668 /* hInstance is still 16-bit in 980215 winelib */
669 if (HIWORD(cs->hInstance) || __winelib)
670 cs->hMenu = LoadMenu32A(cs->hInstance,PTR_SEG_TO_LIN(menuName));
671 else
672 /* doesn't work for winelib, since resources are unicode */
673 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
675 if (cs->hMenu) SetMenu32( hwnd, cs->hMenu );
677 #endif
680 else wndPtr->wIDmenu = (UINT32)cs->hMenu;
682 /* Send the WM_CREATE message
683 * Perhaps we shouldn't allow width/height changes as well.
684 * See p327 in "Internals".
687 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
689 localSend32 = unicode ? SendMessage32W : SendMessage32A;
690 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
692 /* Insert the window in the linked list */
694 WIN_LinkWindow( hwnd, hwndLinkAfter );
696 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
697 NULL, NULL, 0, &wndPtr->rectClient );
698 OffsetRect32(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
699 maxPos.y - wndPtr->rectWindow.top);
700 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
702 /* Send the size messages */
704 if (!(wndPtr->flags & WIN_NEED_SIZE))
706 /* send it anyway */
707 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
708 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
709 WARN(win,"sending bogus WM_SIZE message 0x%08lx\n",
710 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
711 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
712 SendMessage32A( hwnd, WM_SIZE, SIZE_RESTORED,
713 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
714 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
715 SendMessage32A( hwnd, WM_MOVE, 0,
716 MAKELONG( wndPtr->rectClient.left,
717 wndPtr->rectClient.top ) );
720 /* Show the window, maximizing or minimizing if needed */
722 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
724 RECT16 newPos;
725 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
726 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
727 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
728 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow32()) ? SWP_NOACTIVATE : 0;
729 SetWindowPos32( hwnd, 0, newPos.left, newPos.top,
730 newPos.right, newPos.bottom, SWP_FRAMECHANGED | swFlag );
733 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
735 /* Notify the parent window only */
737 SendMessage32A( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
738 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
739 if( !IsWindow32(hwnd) ) return 0;
742 if (cs->style & WS_VISIBLE) ShowWindow32( hwnd, SW_SHOW );
744 /* Call WH_SHELL hook */
746 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
747 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
749 TRACE(win, "created window %04x\n", hwnd);
750 return hwnd;
752 WIN_UnlinkWindow( hwnd );
755 /* Abort window creation */
757 WARN(win, "aborted by WM_xxCREATE!\n");
758 WIN_DestroyWindow( wndPtr );
759 return 0;
763 /***********************************************************************
764 * CreateWindow16 (USER.41)
766 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
767 DWORD style, INT16 x, INT16 y, INT16 width,
768 INT16 height, HWND16 parent, HMENU16 menu,
769 HINSTANCE16 instance, LPVOID data )
771 return CreateWindowEx16( 0, className, windowName, style,
772 x, y, width, height, parent, menu, instance, data );
776 /***********************************************************************
777 * CreateWindowEx16 (USER.452)
779 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
780 LPCSTR windowName, DWORD style, INT16 x,
781 INT16 y, INT16 width, INT16 height,
782 HWND16 parent, HMENU16 menu,
783 HINSTANCE16 instance, LPVOID data )
785 ATOM classAtom;
786 CREATESTRUCT32A cs;
788 /* Find the class atom */
790 if (!(classAtom = GlobalFindAtom32A( className )))
792 fprintf( stderr, "CreateWindowEx16: bad class name " );
793 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
794 else fprintf( stderr, "'%s'\n", className );
795 return 0;
798 /* Fix the coordinates */
800 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)x;
801 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)y;
802 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)width;
803 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)height;
805 /* Create the window */
807 cs.lpCreateParams = data;
808 cs.hInstance = (HINSTANCE32)instance;
809 cs.hMenu = (HMENU32)menu;
810 cs.hwndParent = (HWND32)parent;
811 cs.style = style;
812 cs.lpszName = windowName;
813 cs.lpszClass = className;
814 cs.dwExStyle = exStyle;
815 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
819 /***********************************************************************
820 * CreateWindowEx32A (USER32.83)
822 HWND32 WINAPI CreateWindowEx32A( DWORD exStyle, LPCSTR className,
823 LPCSTR windowName, DWORD style, INT32 x,
824 INT32 y, INT32 width, INT32 height,
825 HWND32 parent, HMENU32 menu,
826 HINSTANCE32 instance, LPVOID data )
828 ATOM classAtom;
829 CREATESTRUCT32A cs;
831 if(exStyle & WS_EX_MDICHILD)
832 return MDI_CreateMDIWindow32A(className, windowName, style, x, y, width, height, parent, instance, data);
833 /* Find the class atom */
835 if (!(classAtom = GlobalFindAtom32A( className )))
837 fprintf( stderr, "CreateWindowEx32A: bad class name " );
838 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
839 else fprintf( stderr, "'%s'\n", className );
840 return 0;
843 /* Create the window */
845 cs.lpCreateParams = data;
846 cs.hInstance = instance;
847 cs.hMenu = menu;
848 cs.hwndParent = parent;
849 cs.x = x;
850 cs.y = y;
851 cs.cx = width;
852 cs.cy = height;
853 cs.style = style;
854 cs.lpszName = windowName;
855 cs.lpszClass = className;
856 cs.dwExStyle = exStyle;
857 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
861 /***********************************************************************
862 * CreateWindowEx32W (USER32.84)
864 HWND32 WINAPI CreateWindowEx32W( DWORD exStyle, LPCWSTR className,
865 LPCWSTR windowName, DWORD style, INT32 x,
866 INT32 y, INT32 width, INT32 height,
867 HWND32 parent, HMENU32 menu,
868 HINSTANCE32 instance, LPVOID data )
870 ATOM classAtom;
871 CREATESTRUCT32W cs;
873 if(exStyle & WS_EX_MDICHILD)
874 return MDI_CreateMDIWindow32W(className, windowName, style, x, y, width, height, parent, instance, data);
876 /* Find the class atom */
878 if (!(classAtom = GlobalFindAtom32W( className )))
880 if (HIWORD(className))
882 LPSTR cn = HEAP_strdupWtoA( GetProcessHeap(), 0, className );
883 WARN( win, "Bad class name '%s'\n",cn);
884 HeapFree( GetProcessHeap(), 0, cn );
886 else
887 WARN( win, "Bad class name %p\n", className );
888 return 0;
891 /* Create the window */
893 cs.lpCreateParams = data;
894 cs.hInstance = instance;
895 cs.hMenu = menu;
896 cs.hwndParent = parent;
897 cs.x = x;
898 cs.y = y;
899 cs.cx = width;
900 cs.cy = height;
901 cs.style = style;
902 cs.lpszName = windowName;
903 cs.lpszClass = className;
904 cs.dwExStyle = exStyle;
905 /* Note: we rely on the fact that CREATESTRUCT32A and */
906 /* CREATESTRUCT32W have the same layout. */
907 return WIN_CreateWindowEx( (CREATESTRUCT32A *)&cs, classAtom, TRUE, TRUE );
911 /***********************************************************************
912 * WIN_CheckFocus
914 static void WIN_CheckFocus( WND* pWnd )
916 if( GetFocus16() == pWnd->hwndSelf )
917 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
920 /***********************************************************************
921 * WIN_SendDestroyMsg
923 static void WIN_SendDestroyMsg( WND* pWnd )
925 WIN_CheckFocus(pWnd);
927 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret32();
928 if( !pWnd->window ) CLIPBOARD_ResetOwner( pWnd );
930 SendMessage32A( pWnd->hwndSelf, WM_DESTROY, 0, 0);
932 if( IsWindow32(pWnd->hwndSelf) )
934 WND* pChild = pWnd->child;
935 while( pChild )
937 WIN_SendDestroyMsg( pChild );
938 pChild = pChild->next;
940 WIN_CheckFocus(pWnd);
942 else
943 WARN(win, "\tdestroyed itself while in WM_DESTROY!\n");
947 /***********************************************************************
948 * DestroyWindow16 (USER.53)
950 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
952 return DestroyWindow32(hwnd);
956 /***********************************************************************
957 * DestroyWindow32 (USER32.135)
959 BOOL32 WINAPI DestroyWindow32( HWND32 hwnd )
961 WND * wndPtr;
963 TRACE(win, "(%04x)\n", hwnd);
965 /* Initialization */
967 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
968 if (wndPtr == pWndDesktop) return FALSE; /* Can't destroy desktop */
970 /* Call hooks */
972 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
973 return FALSE;
975 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
977 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
978 /* FIXME: clean up palette - see "Internals" p.352 */
981 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
982 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
984 /* Notify the parent window only */
985 SendMessage32A( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
986 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
987 if( !IsWindow32(hwnd) ) return TRUE;
990 if( wndPtr->window ) CLIPBOARD_ResetOwner( wndPtr ); /* before the window is unmapped */
992 /* Hide the window */
994 if (wndPtr->dwStyle & WS_VISIBLE)
996 SetWindowPos32( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
997 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
998 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
999 if (!IsWindow32(hwnd)) return TRUE;
1002 /* Recursively destroy owned windows */
1004 if( !(wndPtr->dwStyle & WS_CHILD) )
1006 /* make sure top menu popup doesn't get destroyed */
1007 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1009 for (;;)
1011 WND *siblingPtr = wndPtr->parent->child; /* First sibling */
1012 while (siblingPtr)
1014 if (siblingPtr->owner == wndPtr)
1016 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1017 break;
1018 else
1019 siblingPtr->owner = NULL;
1021 siblingPtr = siblingPtr->next;
1023 if (siblingPtr) DestroyWindow32( siblingPtr->hwndSelf );
1024 else break;
1027 if( !Options.managed || EVENT_CheckFocus() )
1028 WINPOS_ActivateOtherWindow(wndPtr);
1030 if( wndPtr->owner &&
1031 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1032 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1035 /* Send destroy messages */
1037 WIN_SendDestroyMsg( wndPtr );
1038 if (!IsWindow32(hwnd)) return TRUE;
1040 /* Unlink now so we won't bother with the children later on */
1042 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1044 /* Destroy the window storage */
1046 WIN_DestroyWindow( wndPtr );
1047 return TRUE;
1051 /***********************************************************************
1052 * CloseWindow16 (USER.43)
1054 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1056 return CloseWindow32( hwnd );
1060 /***********************************************************************
1061 * CloseWindow32 (USER32.56)
1063 BOOL32 WINAPI CloseWindow32( HWND32 hwnd )
1065 WND * wndPtr = WIN_FindWndPtr( hwnd );
1066 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD)) return FALSE;
1067 ShowWindow32( hwnd, SW_MINIMIZE );
1068 return TRUE;
1072 /***********************************************************************
1073 * OpenIcon16 (USER.44)
1075 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1077 return OpenIcon32( hwnd );
1081 /***********************************************************************
1082 * OpenIcon32 (USER32.410)
1084 BOOL32 WINAPI OpenIcon32( HWND32 hwnd )
1086 if (!IsIconic32( hwnd )) return FALSE;
1087 ShowWindow32( hwnd, SW_SHOWNORMAL );
1088 return TRUE;
1092 /***********************************************************************
1093 * WIN_FindWindow
1095 * Implementation of FindWindow() and FindWindowEx().
1097 static HWND32 WIN_FindWindow( HWND32 parent, HWND32 child, ATOM className,
1098 LPCSTR title )
1100 WND *pWnd;
1101 CLASS *pClass = NULL;
1103 if (child)
1105 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1106 if (parent)
1108 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent)) return 0;
1110 else if (pWnd->parent != pWndDesktop) return 0;
1111 pWnd = pWnd->next;
1113 else
1115 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : pWndDesktop)) return 0;
1116 pWnd = pWnd->child;
1118 if (!pWnd) return 0;
1120 /* For a child window, all siblings will have the same hInstance, */
1121 /* so we can look for the class once and for all. */
1123 if (className && (pWnd->dwStyle & WS_CHILD))
1125 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1126 return 0;
1130 for ( ; pWnd; pWnd = pWnd->next)
1132 if (className && !(pWnd->dwStyle & WS_CHILD))
1134 if (!(pClass = CLASS_FindClassByAtom( className, GetExePtr(pWnd->hInstance))))
1135 continue; /* Skip this window */
1138 if (pClass && (pWnd->class != pClass))
1139 continue; /* Not the right class */
1141 /* Now check the title */
1143 if (!title) return pWnd->hwndSelf;
1144 if (pWnd->text && !strcmp( pWnd->text, title )) return pWnd->hwndSelf;
1146 return 0;
1151 /***********************************************************************
1152 * FindWindow16 (USER.50)
1154 HWND16 WINAPI FindWindow16( SEGPTR className, LPCSTR title )
1156 return FindWindowEx16( 0, 0, className, title );
1160 /***********************************************************************
1161 * FindWindowEx16 (USER.427)
1163 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child,
1164 SEGPTR className, LPCSTR title )
1166 ATOM atom = 0;
1168 TRACE(win, "%04x %04x '%s' '%s'\n", parent,
1169 child, HIWORD(className)?(char *)PTR_SEG_TO_LIN(className):"",
1170 title ? title : "");
1172 if (className)
1174 /* If the atom doesn't exist, then no class */
1175 /* with this name exists either. */
1176 if (!(atom = GlobalFindAtom16( className ))) return 0;
1178 return WIN_FindWindow( parent, child, atom, title );
1182 /***********************************************************************
1183 * FindWindow32A (USER32.198)
1185 HWND32 WINAPI FindWindow32A( LPCSTR className, LPCSTR title )
1187 HWND32 ret = FindWindowEx32A( 0, 0, className, title );
1188 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1189 return ret;
1193 /***********************************************************************
1194 * FindWindowEx32A (USER32.199)
1196 HWND32 WINAPI FindWindowEx32A( HWND32 parent, HWND32 child,
1197 LPCSTR className, LPCSTR title )
1199 ATOM atom = 0;
1201 if (className)
1203 /* If the atom doesn't exist, then no class */
1204 /* with this name exists either. */
1205 if (!(atom = GlobalFindAtom32A( className )))
1207 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1208 return 0;
1211 return WIN_FindWindow( parent, child, atom, title );
1215 /***********************************************************************
1216 * FindWindowEx32W (USER32.200)
1218 HWND32 WINAPI FindWindowEx32W( HWND32 parent, HWND32 child,
1219 LPCWSTR className, LPCWSTR title )
1221 ATOM atom = 0;
1222 char *buffer;
1223 HWND32 hwnd;
1225 if (className)
1227 /* If the atom doesn't exist, then no class */
1228 /* with this name exists either. */
1229 if (!(atom = GlobalFindAtom32W( className )))
1231 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1232 return 0;
1235 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1236 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1237 HeapFree( GetProcessHeap(), 0, buffer );
1238 return hwnd;
1242 /***********************************************************************
1243 * FindWindow32W (USER32.201)
1245 HWND32 WINAPI FindWindow32W( LPCWSTR className, LPCWSTR title )
1247 return FindWindowEx32W( 0, 0, className, title );
1251 /**********************************************************************
1252 * WIN_GetDesktop
1254 WND *WIN_GetDesktop(void)
1256 return pWndDesktop;
1260 /**********************************************************************
1261 * GetDesktopWindow16 (USER.286)
1263 HWND16 WINAPI GetDesktopWindow16(void)
1265 return (HWND16)pWndDesktop->hwndSelf;
1269 /**********************************************************************
1270 * GetDesktopWindow32 (USER32.232)
1272 HWND32 WINAPI GetDesktopWindow32(void)
1274 return pWndDesktop->hwndSelf;
1278 /**********************************************************************
1279 * GetDesktopHwnd (USER.278)
1281 * Exactly the same thing as GetDesktopWindow(), but not documented.
1282 * Don't ask me why...
1284 HWND16 WINAPI GetDesktopHwnd(void)
1286 return (HWND16)pWndDesktop->hwndSelf;
1290 /*******************************************************************
1291 * EnableWindow16 (USER.34)
1293 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1295 return EnableWindow32( hwnd, enable );
1299 /*******************************************************************
1300 * EnableWindow32 (USER32.172)
1302 BOOL32 WINAPI EnableWindow32( HWND32 hwnd, BOOL32 enable )
1304 WND *wndPtr;
1306 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1307 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1309 /* Enable window */
1310 wndPtr->dwStyle &= ~WS_DISABLED;
1311 SendMessage32A( hwnd, WM_ENABLE, TRUE, 0 );
1312 return TRUE;
1314 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1316 /* Disable window */
1317 wndPtr->dwStyle |= WS_DISABLED;
1318 if ((hwnd == GetFocus32()) || IsChild32( hwnd, GetFocus32() ))
1319 SetFocus32( 0 ); /* A disabled window can't have the focus */
1320 if ((hwnd == GetCapture32()) || IsChild32( hwnd, GetCapture32() ))
1321 ReleaseCapture(); /* A disabled window can't capture the mouse */
1322 SendMessage32A( hwnd, WM_ENABLE, FALSE, 0 );
1323 return FALSE;
1325 return ((wndPtr->dwStyle & WS_DISABLED) != 0);
1329 /***********************************************************************
1330 * IsWindowEnabled16 (USER.35)
1332 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1334 return IsWindowEnabled32(hWnd);
1338 /***********************************************************************
1339 * IsWindowEnabled32 (USER32.349)
1341 BOOL32 WINAPI IsWindowEnabled32(HWND32 hWnd)
1343 WND * wndPtr;
1345 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1346 return !(wndPtr->dwStyle & WS_DISABLED);
1350 /***********************************************************************
1351 * IsWindowUnicode (USER32.350)
1353 BOOL32 WINAPI IsWindowUnicode( HWND32 hwnd )
1355 WND * wndPtr;
1357 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1358 return (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1362 /**********************************************************************
1363 * GetWindowWord16 (USER.133)
1365 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1367 return GetWindowWord32( hwnd, offset );
1371 /**********************************************************************
1372 * GetWindowWord32 (USER32.314)
1374 WORD WINAPI GetWindowWord32( HWND32 hwnd, INT32 offset )
1376 WND * wndPtr = WIN_FindWndPtr( hwnd );
1377 if (!wndPtr) return 0;
1378 if (offset >= 0)
1380 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1382 WARN( win, "Invalid offset %d\n", offset );
1383 return 0;
1385 return *(WORD *)(((char *)wndPtr->wExtra) + offset);
1387 switch(offset)
1389 case GWW_ID:
1390 if (HIWORD(wndPtr->wIDmenu))
1391 WARN( win,"GWW_ID: discards high bits of 0x%08x!\n",
1392 wndPtr->wIDmenu);
1393 return (WORD)wndPtr->wIDmenu;
1394 case GWW_HWNDPARENT:
1395 return wndPtr->parent ?
1396 wndPtr->parent->hwndSelf : (
1397 wndPtr->owner ?
1398 wndPtr->owner->hwndSelf :
1400 case GWW_HINSTANCE:
1401 if (HIWORD(wndPtr->hInstance))
1402 WARN(win,"GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1403 wndPtr->hInstance);
1404 return (WORD)wndPtr->hInstance;
1405 default:
1406 WARN( win, "Invalid offset %d\n", offset );
1407 return 0;
1412 /**********************************************************************
1413 * WIN_GetWindowInstance
1415 HINSTANCE32 WIN_GetWindowInstance( HWND32 hwnd )
1417 WND * wndPtr = WIN_FindWndPtr( hwnd );
1418 if (!wndPtr) return (HINSTANCE32)0;
1419 return wndPtr->hInstance;
1423 /**********************************************************************
1424 * SetWindowWord16 (USER.134)
1426 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1428 return SetWindowWord32( hwnd, offset, newval );
1432 /**********************************************************************
1433 * SetWindowWord32 (USER32.524)
1435 WORD WINAPI SetWindowWord32( HWND32 hwnd, INT32 offset, WORD newval )
1437 WORD *ptr, retval;
1438 WND * wndPtr = WIN_FindWndPtr( hwnd );
1439 if (!wndPtr) return 0;
1440 if (offset >= 0)
1442 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1444 WARN( win, "Invalid offset %d\n", offset );
1445 return 0;
1447 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1449 else switch(offset)
1451 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1452 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1453 case GWW_HWNDPARENT: return SetParent32( hwnd, newval );
1454 default:
1455 WARN( win, "Invalid offset %d\n", offset );
1456 return 0;
1458 retval = *ptr;
1459 *ptr = newval;
1460 return retval;
1464 /**********************************************************************
1465 * WIN_GetWindowLong
1467 * Helper function for GetWindowLong().
1469 static LONG WIN_GetWindowLong( HWND32 hwnd, INT32 offset, WINDOWPROCTYPE type )
1471 LONG retval;
1472 WND * wndPtr = WIN_FindWndPtr( hwnd );
1473 if (!wndPtr) return 0;
1474 if (offset >= 0)
1476 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1478 WARN( win, "Invalid offset %d\n", offset );
1479 return 0;
1481 retval = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1482 /* Special case for dialog window procedure */
1483 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1484 return (LONG)WINPROC_GetProc( (HWINDOWPROC)retval, type );
1485 return retval;
1487 switch(offset)
1489 case GWL_USERDATA: return wndPtr->userdata;
1490 case GWL_STYLE: return wndPtr->dwStyle;
1491 case GWL_EXSTYLE: return wndPtr->dwExStyle;
1492 case GWL_ID: return (LONG)wndPtr->wIDmenu;
1493 case GWL_WNDPROC: return (LONG)WINPROC_GetProc( wndPtr->winproc,
1494 type );
1495 case GWL_HWNDPARENT: return wndPtr->parent ?
1496 (HWND32)wndPtr->parent->hwndSelf : 0;
1497 case GWL_HINSTANCE: return wndPtr->hInstance;
1498 default:
1499 WARN( win, "Unknown offset %d\n", offset );
1501 return 0;
1505 /**********************************************************************
1506 * WIN_SetWindowLong
1508 * Helper function for SetWindowLong().
1510 * 0 is the failure code. However, in the case of failure SetLastError
1511 * must be set to distinguish between a 0 return value and a failure.
1513 * FIXME: The error values for SetLastError may not be right. Can
1514 * someone check with the real thing?
1516 static LONG WIN_SetWindowLong( HWND32 hwnd, INT32 offset, LONG newval,
1517 WINDOWPROCTYPE type )
1519 LONG *ptr, retval;
1520 WND * wndPtr = WIN_FindWndPtr( hwnd );
1521 STYLESTRUCT style;
1523 TRACE(win,"%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1525 if (!wndPtr)
1527 /* Is this the right error? */
1528 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1529 return 0;
1532 if (offset >= 0)
1534 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1536 WARN( win, "Invalid offset %d\n", offset );
1538 /* Is this the right error? */
1539 SetLastError( ERROR_OUTOFMEMORY );
1541 return 0;
1543 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1544 /* Special case for dialog window procedure */
1545 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1547 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1548 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1549 type, WIN_PROC_WINDOW );
1550 return retval;
1553 else switch(offset)
1555 case GWL_ID:
1556 ptr = (DWORD*)&wndPtr->wIDmenu;
1557 break;
1558 case GWL_HINSTANCE:
1559 return SetWindowWord32( hwnd, offset, newval );
1560 case GWL_WNDPROC:
1561 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1562 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1563 type, WIN_PROC_WINDOW );
1564 return retval;
1565 case GWL_STYLE:
1566 style.styleOld = wndPtr->dwStyle;
1567 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
1568 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
1570 if (wndPtr->flags & WIN_ISWIN32)
1571 SendMessage32A(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1572 wndPtr->dwStyle = style.styleNew;
1573 if (wndPtr->flags & WIN_ISWIN32)
1574 SendMessage32A(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1575 return style.styleOld;
1577 case GWL_USERDATA:
1578 ptr = &wndPtr->userdata;
1579 break;
1580 case GWL_EXSTYLE:
1581 style.styleOld = wndPtr->dwExStyle;
1582 style.styleNew = newval;
1583 if (wndPtr->flags & WIN_ISWIN32)
1584 SendMessage32A(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1585 wndPtr->dwExStyle = newval;
1586 if (wndPtr->flags & WIN_ISWIN32)
1587 SendMessage32A(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1588 return style.styleOld;
1590 default:
1591 WARN( win, "Invalid offset %d\n", offset );
1593 /* Don't think this is right error but it should do */
1594 SetLastError( ERROR_OUTOFMEMORY );
1596 return 0;
1598 retval = *ptr;
1599 *ptr = newval;
1600 return retval;
1604 /**********************************************************************
1605 * GetWindowLong16 (USER.135)
1607 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1609 return WIN_GetWindowLong( (HWND32)hwnd, offset, WIN_PROC_16 );
1613 /**********************************************************************
1614 * GetWindowLong32A (USER32.305)
1616 LONG WINAPI GetWindowLong32A( HWND32 hwnd, INT32 offset )
1618 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1622 /**********************************************************************
1623 * GetWindowLong32W (USER32.306)
1625 LONG WINAPI GetWindowLong32W( HWND32 hwnd, INT32 offset )
1627 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1631 /**********************************************************************
1632 * SetWindowLong16 (USER.136)
1634 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1636 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1640 /**********************************************************************
1641 * SetWindowLong32A (USER32.517)
1643 LONG WINAPI SetWindowLong32A( HWND32 hwnd, INT32 offset, LONG newval )
1645 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1649 /**********************************************************************
1650 * SetWindowLong32W (USER32.518) Set window attribute
1652 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
1653 * value in a window's extra memory.
1655 * The _hwnd_ parameter specifies the window. is the handle to a
1656 * window that has extra memory. The _newval_ parameter contains the
1657 * new attribute or extra memory value. If positive, the _offset_
1658 * parameter is the byte-addressed location in the window's extra
1659 * memory to set. If negative, _offset_ specifies the window
1660 * attribute to set, and should be one of the following values:
1662 * GWL_EXSTYLE The window's extended window style
1664 * GWL_STYLE The window's window style.
1666 * GWL_WNDPROC Pointer to the window's window procedure.
1668 * GWL_HINSTANCE The window's pplication instance handle.
1670 * GWL_ID The window's identifier.
1672 * GWL_USERDATA The window's user-specified data.
1674 * If the window is a dialog box, the _offset_ parameter can be one of
1675 * the following values:
1677 * DWL_DLGPROC The address of the window's dialog box procedure.
1679 * DWL_MSGRESULT The return value of a message
1680 * that the dialog box procedure processed.
1682 * DWL_USER Application specific information.
1684 * RETURNS
1686 * If successful, returns the previous value located at _offset_. Otherwise,
1687 * returns 0.
1689 * NOTES
1691 * Extra memory for a window class is specified by a nonzero cbWndExtra
1692 * parameter of the WNDCLASS structure passed to RegisterClass() at the
1693 * time of class creation.
1695 * Using GWL_WNDPROC to set a new window procedure effectively creates
1696 * a window subclass. Use CallWindowProc() in the new windows procedure
1697 * to pass messages to the superclass's window procedure.
1699 * The user data is reserved for use by the application which created
1700 * the window.
1702 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
1703 * instead, call the EnableWindow() function to change the window's
1704 * disabled state.
1706 * Do not use GWL_HWNDPARENT to reset the window's parent, use
1707 * SetParent() instead.
1709 * BUGS
1711 * GWL_STYLE does not dispatch WM_STYLE_... messages.
1713 * CONFORMANCE
1715 * ECMA-234, Win32
1718 LONG WINAPI SetWindowLong32W(
1719 HWND32 hwnd, /* window to alter */
1720 INT32 offset, /* offset, in bytes, of location to alter */
1721 LONG newval /* new value of location */
1723 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1727 /*******************************************************************
1728 * GetWindowText16 (USER.36)
1730 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
1732 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1736 /*******************************************************************
1737 * GetWindowText32A (USER32.309)
1739 INT32 WINAPI GetWindowText32A( HWND32 hwnd, LPSTR lpString, INT32 nMaxCount )
1741 return (INT32)SendMessage32A( hwnd, WM_GETTEXT, nMaxCount,
1742 (LPARAM)lpString );
1745 /*******************************************************************
1746 * InternalGetWindowText (USER32.326)
1748 INT32 WINAPI InternalGetWindowText(HWND32 hwnd,LPWSTR lpString,INT32 nMaxCount )
1750 FIXME(win,"(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
1751 return GetWindowText32W(hwnd,lpString,nMaxCount);
1755 /*******************************************************************
1756 * GetWindowText32W (USER32.312)
1758 INT32 WINAPI GetWindowText32W( HWND32 hwnd, LPWSTR lpString, INT32 nMaxCount )
1760 return (INT32)SendMessage32W( hwnd, WM_GETTEXT, nMaxCount,
1761 (LPARAM)lpString );
1765 /*******************************************************************
1766 * SetWindowText16 (USER.37)
1768 void WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
1770 SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1774 /*******************************************************************
1775 * SetWindowText32A (USER32.521)
1777 void WINAPI SetWindowText32A( HWND32 hwnd, LPCSTR lpString )
1779 SendMessage32A( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1783 /*******************************************************************
1784 * SetWindowText32W (USER32.523)
1786 void WINAPI SetWindowText32W( HWND32 hwnd, LPCWSTR lpString )
1788 SendMessage32W( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1792 /*******************************************************************
1793 * GetWindowTextLength16 (USER.38)
1795 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
1797 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1801 /*******************************************************************
1802 * GetWindowTextLength32A (USER32.310)
1804 INT32 WINAPI GetWindowTextLength32A( HWND32 hwnd )
1806 return SendMessage32A( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1809 /*******************************************************************
1810 * GetWindowTextLength32W (USER32.311)
1812 INT32 WINAPI GetWindowTextLength32W( HWND32 hwnd )
1814 return SendMessage32W( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1818 /*******************************************************************
1819 * IsWindow16 (USER.47)
1821 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
1823 return IsWindow32( hwnd );
1826 void WINAPI WIN16_IsWindow16( CONTEXT *context )
1828 WORD *stack = PTR_SEG_OFF_TO_LIN(SS_reg(context), SP_reg(context));
1829 HWND16 hwnd = (HWND16)stack[2];
1831 AX_reg(context) = IsWindow32( hwnd );
1832 ES_reg(context) = USER_HeapSel;
1836 /*******************************************************************
1837 * IsWindow32 (USER32.348)
1839 BOOL32 WINAPI IsWindow32( HWND32 hwnd )
1841 WND * wndPtr = WIN_FindWndPtr( hwnd );
1842 return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
1846 /*****************************************************************
1847 * GetParent16 (USER.46)
1849 HWND16 WINAPI GetParent16( HWND16 hwnd )
1851 return (HWND16)GetParent32( hwnd );
1855 /*****************************************************************
1856 * GetParent32 (USER32.278)
1858 HWND32 WINAPI GetParent32( HWND32 hwnd )
1860 WND *wndPtr = WIN_FindWndPtr(hwnd);
1861 if ((!wndPtr) || (!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD)))) return 0;
1862 wndPtr = (wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner;
1863 return wndPtr ? wndPtr->hwndSelf : 0;
1866 /*****************************************************************
1867 * WIN_GetTopParent
1869 * Get the top-level parent for a child window.
1871 WND* WIN_GetTopParentPtr( WND* pWnd )
1873 while( pWnd && (pWnd->dwStyle & WS_CHILD)) pWnd = pWnd->parent;
1874 return pWnd;
1877 /*****************************************************************
1878 * WIN_GetTopParent
1880 * Get the top-level parent for a child window.
1882 HWND32 WIN_GetTopParent( HWND32 hwnd )
1884 WND *wndPtr = WIN_GetTopParentPtr ( WIN_FindWndPtr( hwnd ) );
1885 return wndPtr ? wndPtr->hwndSelf : 0;
1889 /*****************************************************************
1890 * SetParent16 (USER.233)
1892 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
1894 return SetParent32( hwndChild, hwndNewParent );
1898 /*****************************************************************
1899 * SetParent32 (USER32.495)
1901 HWND32 WINAPI SetParent32( HWND32 hwndChild, HWND32 hwndNewParent )
1903 WND *wndPtr = WIN_FindWndPtr( hwndChild );
1904 WND *pWndNewParent =
1905 (hwndNewParent) ? WIN_FindWndPtr( hwndNewParent ) : pWndDesktop;
1906 WND *pWndOldParent =
1907 (*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent);
1909 return pWndOldParent?pWndOldParent->hwndSelf:0;
1912 /*******************************************************************
1913 * IsChild16 (USER.48)
1915 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
1917 return IsChild32(parent,child);
1921 /*******************************************************************
1922 * IsChild32 (USER32.339)
1924 BOOL32 WINAPI IsChild32( HWND32 parent, HWND32 child )
1926 WND * wndPtr = WIN_FindWndPtr( child );
1927 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1929 wndPtr = wndPtr->parent;
1930 if (wndPtr->hwndSelf == parent) return TRUE;
1932 return FALSE;
1936 /***********************************************************************
1937 * IsWindowVisible16 (USER.49)
1939 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
1941 return IsWindowVisible32(hwnd);
1945 /***********************************************************************
1946 * IsWindowVisible32 (USER32.351)
1948 BOOL32 WINAPI IsWindowVisible32( HWND32 hwnd )
1950 WND *wndPtr = WIN_FindWndPtr( hwnd );
1951 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1953 if (!(wndPtr->dwStyle & WS_VISIBLE)) return FALSE;
1954 wndPtr = wndPtr->parent;
1956 return (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
1960 /***********************************************************************
1961 * WIN_IsWindowDrawable
1963 * hwnd is drawable when it is visible, all parents are not
1964 * minimized, and it is itself not minimized unless we are
1965 * trying to draw its default class icon.
1967 BOOL32 WIN_IsWindowDrawable( WND* wnd, BOOL32 icon )
1969 if( (wnd->dwStyle & WS_MINIMIZE &&
1970 icon && wnd->class->hIcon) ||
1971 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
1972 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
1973 if( wnd->dwStyle & WS_MINIMIZE ||
1974 !(wnd->dwStyle & WS_VISIBLE) ) break;
1975 return (wnd == NULL);
1979 /*******************************************************************
1980 * GetTopWindow16 (USER.229)
1982 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
1984 return GetTopWindow32(hwnd);
1988 /*******************************************************************
1989 * GetTopWindow32 (USER.229)
1991 HWND32 WINAPI GetTopWindow32( HWND32 hwnd )
1993 WND * wndPtr = WIN_FindWndPtr( hwnd );
1994 if (wndPtr && wndPtr->child) return wndPtr->child->hwndSelf;
1995 else return 0;
1999 /*******************************************************************
2000 * GetWindow16 (USER.262)
2002 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2004 return GetWindow32( hwnd,rel );
2008 /*******************************************************************
2009 * GetWindow32 (USER32.302)
2011 HWND32 WINAPI GetWindow32( HWND32 hwnd, WORD rel )
2013 WND * wndPtr = WIN_FindWndPtr( hwnd );
2014 if (!wndPtr) return 0;
2015 switch(rel)
2017 case GW_HWNDFIRST:
2018 if (wndPtr->parent) return wndPtr->parent->child->hwndSelf;
2019 else return 0;
2021 case GW_HWNDLAST:
2022 if (!wndPtr->parent) return 0; /* Desktop window */
2023 while (wndPtr->next) wndPtr = wndPtr->next;
2024 return wndPtr->hwndSelf;
2026 case GW_HWNDNEXT:
2027 if (!wndPtr->next) return 0;
2028 return wndPtr->next->hwndSelf;
2030 case GW_HWNDPREV:
2031 if (!wndPtr->parent) return 0; /* Desktop window */
2032 wndPtr = wndPtr->parent->child; /* First sibling */
2033 if (wndPtr->hwndSelf == hwnd) return 0; /* First in list */
2034 while (wndPtr->next)
2036 if (wndPtr->next->hwndSelf == hwnd) return wndPtr->hwndSelf;
2037 wndPtr = wndPtr->next;
2039 return 0;
2041 case GW_OWNER:
2042 return wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2044 case GW_CHILD:
2045 return wndPtr->child ? wndPtr->child->hwndSelf : 0;
2047 return 0;
2051 /*******************************************************************
2052 * GetNextWindow16 (USER.230)
2054 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2056 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2057 return GetWindow16( hwnd, flag );
2060 /*******************************************************************
2061 * ShowOwnedPopups16 (USER.265)
2063 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2065 ShowOwnedPopups32( owner, fShow );
2069 /*******************************************************************
2070 * ShowOwnedPopups32 (USER32.531)
2072 BOOL32 WINAPI ShowOwnedPopups32( HWND32 owner, BOOL32 fShow )
2074 WND *pWnd = pWndDesktop->child;
2075 while (pWnd)
2077 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
2078 (pWnd->dwStyle & WS_POPUP))
2079 ShowWindow32( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
2080 pWnd = pWnd->next;
2082 return TRUE;
2086 /*******************************************************************
2087 * GetLastActivePopup16 (USER.287)
2089 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2091 return GetLastActivePopup32( hwnd );
2094 /*******************************************************************
2095 * GetLastActivePopup32 (USER32.256)
2097 HWND32 WINAPI GetLastActivePopup32( HWND32 hwnd )
2099 WND *wndPtr;
2100 wndPtr = WIN_FindWndPtr(hwnd);
2101 if (wndPtr == NULL) return hwnd;
2102 return wndPtr->hwndLastActive;
2106 /*******************************************************************
2107 * WIN_BuildWinArray
2109 * Build an array of pointers to the children of a given window.
2110 * The array must be freed with HeapFree(SystemHeap). Return NULL
2111 * when no windows are found.
2113 WND **WIN_BuildWinArray( WND *wndPtr, UINT32 bwaFlags, UINT32* pTotal )
2115 WND **list, **ppWnd;
2116 WND *pWnd;
2117 UINT32 count, skipOwned, skipHidden;
2118 DWORD skipFlags;
2120 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2121 skipOwned = bwaFlags & BWA_SKIPOWNED;
2122 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2123 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2125 /* First count the windows */
2127 if (!wndPtr) wndPtr = pWndDesktop;
2128 for (pWnd = wndPtr->child, count = 0; pWnd; pWnd = pWnd->next)
2130 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
2131 if( !skipHidden || pWnd->dwStyle & WS_VISIBLE ) count++;
2134 if( count )
2136 /* Now build the list of all windows */
2138 if ((list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * (count + 1))))
2140 for (pWnd = wndPtr->child, ppWnd = list, count = 0; pWnd; pWnd = pWnd->next)
2142 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
2143 if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2145 *ppWnd++ = pWnd;
2146 count++;
2149 *ppWnd = NULL;
2151 else count = 0;
2152 } else list = NULL;
2154 if( pTotal ) *pTotal = count;
2155 return list;
2159 /*******************************************************************
2160 * EnumWindows16 (USER.54)
2162 BOOL16 WINAPI EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
2164 WND **list, **ppWnd;
2166 /* We have to build a list of all windows first, to avoid */
2167 /* unpleasant side-effects, for instance if the callback */
2168 /* function changes the Z-order of the windows. */
2170 if (!(list = WIN_BuildWinArray( pWndDesktop, 0, NULL ))) return FALSE;
2172 /* Now call the callback function for every window */
2174 for (ppWnd = list; *ppWnd; ppWnd++)
2176 /* Make sure that the window still exists */
2177 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2178 if (!lpEnumFunc( (*ppWnd)->hwndSelf, lParam )) break;
2180 HeapFree( SystemHeap, 0, list );
2181 return TRUE;
2185 /*******************************************************************
2186 * EnumWindows32 (USER32.193)
2188 BOOL32 WINAPI EnumWindows32( WNDENUMPROC32 lpEnumFunc, LPARAM lParam )
2190 return (BOOL32)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2194 /**********************************************************************
2195 * EnumTaskWindows16 (USER.225)
2197 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2198 LPARAM lParam )
2200 WND **list, **ppWnd;
2201 HQUEUE16 hQueue = GetTaskQueue( hTask );
2203 /* This function is the same as EnumWindows(), */
2204 /* except for an added check on the window queue. */
2206 if (!(list = WIN_BuildWinArray( pWndDesktop, 0, NULL ))) return FALSE;
2208 /* Now call the callback function for every window */
2210 for (ppWnd = list; *ppWnd; ppWnd++)
2212 /* Make sure that the window still exists */
2213 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2214 if ((*ppWnd)->hmemTaskQ != hQueue) continue; /* Check the queue */
2215 if (!func( (*ppWnd)->hwndSelf, lParam )) break;
2217 HeapFree( SystemHeap, 0, list );
2218 return TRUE;
2222 /**********************************************************************
2223 * EnumThreadWindows (USER32.190)
2225 BOOL32 WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC32 func, LPARAM lParam )
2227 THDB *tdb = THREAD_ID_TO_THDB(id);
2229 return (BOOL16)EnumTaskWindows16(tdb->teb.htask16, (WNDENUMPROC16)func, lParam);
2233 /**********************************************************************
2234 * WIN_EnumChildWindows
2236 * Helper function for EnumChildWindows().
2238 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2239 LPARAM lParam )
2241 WND **childList;
2242 BOOL16 ret = FALSE;
2244 for ( ; *ppWnd; ppWnd++)
2246 /* Make sure that the window still exists */
2247 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2248 /* Build children list first */
2249 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2250 ret = func( (*ppWnd)->hwndSelf, lParam );
2251 if (childList)
2253 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2254 HeapFree( SystemHeap, 0, childList );
2256 if (!ret) return FALSE;
2258 return TRUE;
2262 /**********************************************************************
2263 * EnumChildWindows16 (USER.55)
2265 BOOL16 WINAPI EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
2266 LPARAM lParam )
2268 WND **list, *pParent;
2270 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2271 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL ))) return FALSE;
2272 WIN_EnumChildWindows( list, func, lParam );
2273 HeapFree( SystemHeap, 0, list );
2274 return TRUE;
2278 /**********************************************************************
2279 * EnumChildWindows32 (USER32.178)
2281 BOOL32 WINAPI EnumChildWindows32( HWND32 parent, WNDENUMPROC32 func,
2282 LPARAM lParam )
2284 return (BOOL32)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2285 lParam );
2289 /*******************************************************************
2290 * AnyPopup16 (USER.52)
2292 BOOL16 WINAPI AnyPopup16(void)
2294 return AnyPopup32();
2298 /*******************************************************************
2299 * AnyPopup32 (USER32.4)
2301 BOOL32 WINAPI AnyPopup32(void)
2303 WND *wndPtr;
2304 for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next)
2305 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE)) return TRUE;
2306 return FALSE;
2310 /*******************************************************************
2311 * FlashWindow16 (USER.105)
2313 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2315 return FlashWindow32( hWnd, bInvert );
2319 /*******************************************************************
2320 * FlashWindow32 (USER32.202)
2322 BOOL32 WINAPI FlashWindow32( HWND32 hWnd, BOOL32 bInvert )
2324 WND *wndPtr = WIN_FindWndPtr(hWnd);
2326 TRACE(win,"%04x\n", hWnd);
2328 if (!wndPtr) return FALSE;
2330 if (wndPtr->dwStyle & WS_MINIMIZE)
2332 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2334 HDC32 hDC = GetDC32(hWnd);
2336 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2337 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2339 ReleaseDC32( hWnd, hDC );
2340 wndPtr->flags |= WIN_NCACTIVATED;
2342 else
2344 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2345 RDW_UPDATENOW | RDW_FRAME, 0 );
2346 wndPtr->flags &= ~WIN_NCACTIVATED;
2348 return TRUE;
2350 else
2352 WPARAM16 wparam;
2353 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2354 else wparam = (hWnd == GetActiveWindow32());
2356 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2357 return wparam;
2362 /*******************************************************************
2363 * SetSysModalWindow16 (USER.188)
2365 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
2367 HWND32 hWndOldModal = hwndSysModal;
2368 hwndSysModal = hWnd;
2369 FIXME(win, "EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2370 return hWndOldModal;
2374 /*******************************************************************
2375 * GetSysModalWindow16 (USER.52)
2377 HWND16 WINAPI GetSysModalWindow16(void)
2379 return hwndSysModal;
2383 /*******************************************************************
2384 * GetWindowContextHelpId (USER32.303)
2386 DWORD WINAPI GetWindowContextHelpId( HWND32 hwnd )
2388 WND *wnd = WIN_FindWndPtr( hwnd );
2389 if (!wnd) return 0;
2390 return wnd->helpContext;
2394 /*******************************************************************
2395 * SetWindowContextHelpId (USER32.515)
2397 BOOL32 WINAPI SetWindowContextHelpId( HWND32 hwnd, DWORD id )
2399 WND *wnd = WIN_FindWndPtr( hwnd );
2400 if (!wnd) return FALSE;
2401 wnd->helpContext = id;
2402 return TRUE;
2406 /*******************************************************************
2407 * DRAG_QueryUpdate
2409 * recursively find a child that contains spDragInfo->pt point
2410 * and send WM_QUERYDROPOBJECT
2412 BOOL16 DRAG_QueryUpdate( HWND32 hQueryWnd, SEGPTR spDragInfo, BOOL32 bNoSend )
2414 BOOL16 wParam,bResult = 0;
2415 POINT32 pt;
2416 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
2417 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
2418 RECT32 tempRect;
2420 if( !ptrQueryWnd || !ptrDragInfo ) return 0;
2422 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
2424 GetWindowRect32(hQueryWnd,&tempRect);
2426 if( !PtInRect32(&tempRect,pt) ||
2427 (ptrQueryWnd->dwStyle & WS_DISABLED) )
2428 return 0;
2430 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
2432 tempRect = ptrQueryWnd->rectClient;
2433 if(ptrQueryWnd->dwStyle & WS_CHILD)
2434 MapWindowPoints32( ptrQueryWnd->parent->hwndSelf, 0,
2435 (LPPOINT32)&tempRect, 2 );
2437 if (PtInRect32( &tempRect, pt))
2439 wParam = 0;
2441 for (ptrWnd = ptrQueryWnd->child; ptrWnd ;ptrWnd = ptrWnd->next)
2442 if( ptrWnd->dwStyle & WS_VISIBLE )
2444 GetWindowRect32( ptrWnd->hwndSelf, &tempRect );
2445 if (PtInRect32( &tempRect, pt )) break;
2448 if(ptrWnd)
2450 TRACE(msg,"hwnd = %04x, %d %d - %d %d\n",
2451 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
2452 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
2453 if( !(ptrWnd->dwStyle & WS_DISABLED) )
2454 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
2457 if(bResult) return bResult;
2459 else wParam = 1;
2461 else wParam = 1;
2463 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
2465 ptrDragInfo->hScope = hQueryWnd;
2467 bResult = ( bNoSend )
2468 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
2469 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
2470 (WPARAM16)wParam ,(LPARAM) spDragInfo );
2471 if( !bResult )
2472 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
2474 return bResult;
2478 /*******************************************************************
2479 * DragDetect (USER.465)
2481 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
2483 POINT32 pt32;
2484 CONV_POINT16TO32( &pt, &pt32 );
2485 return DragDetect32( hWnd, pt32 );
2488 /*******************************************************************
2489 * DragDetect32 (USER32.151)
2491 BOOL32 WINAPI DragDetect32( HWND32 hWnd, POINT32 pt )
2493 MSG16 msg;
2494 RECT16 rect;
2496 rect.left = pt.x - wDragWidth;
2497 rect.right = pt.x + wDragWidth;
2499 rect.top = pt.y - wDragHeight;
2500 rect.bottom = pt.y + wDragHeight;
2502 SetCapture32(hWnd);
2504 while(1)
2506 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
2508 if( msg.message == WM_LBUTTONUP )
2510 ReleaseCapture();
2511 return 0;
2513 if( msg.message == WM_MOUSEMOVE )
2515 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
2517 ReleaseCapture();
2518 return 1;
2522 WaitMessage();
2524 return 0;
2527 /******************************************************************************
2528 * DragObject16 (USER.464)
2530 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
2531 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
2533 MSG16 msg;
2534 LPDRAGINFO lpDragInfo;
2535 SEGPTR spDragInfo;
2536 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
2537 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
2538 WND *wndPtr = WIN_FindWndPtr(hWnd);
2539 HCURSOR16 hCurrentCursor = 0;
2540 HWND16 hCurrentWnd = 0;
2542 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
2543 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
2545 if( !lpDragInfo || !spDragInfo ) return 0L;
2547 hBummer = LoadCursor16(0, IDC_BUMMER16);
2549 if( !hBummer || !wndPtr )
2551 GlobalFree16(hDragInfo);
2552 return 0L;
2555 if(hCursor)
2557 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
2559 GlobalFree16(hDragInfo);
2560 return 0L;
2563 if( hDragCursor == hCursor ) hDragCursor = 0;
2564 else hCursor = hDragCursor;
2566 hOldCursor = SetCursor32(hDragCursor);
2569 lpDragInfo->hWnd = hWnd;
2570 lpDragInfo->hScope = 0;
2571 lpDragInfo->wFlags = wObj;
2572 lpDragInfo->hList = szList; /* near pointer! */
2573 lpDragInfo->hOfStruct = hOfStruct;
2574 lpDragInfo->l = 0L;
2576 SetCapture32(hWnd);
2577 ShowCursor32( TRUE );
2581 do{ WaitMessage(); }
2582 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
2584 *(lpDragInfo+1) = *lpDragInfo;
2586 lpDragInfo->pt = msg.pt;
2588 /* update DRAGINFO struct */
2589 TRACE(msg,"lpDI->hScope = %04x\n",lpDragInfo->hScope);
2591 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
2592 hCurrentCursor = hCursor;
2593 else
2595 hCurrentCursor = hBummer;
2596 lpDragInfo->hScope = 0;
2598 if( hCurrentCursor )
2599 SetCursor32(hCurrentCursor);
2601 /* send WM_DRAGLOOP */
2602 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
2603 (LPARAM) spDragInfo );
2604 /* send WM_DRAGSELECT or WM_DRAGMOVE */
2605 if( hCurrentWnd != lpDragInfo->hScope )
2607 if( hCurrentWnd )
2608 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
2609 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
2610 HIWORD(spDragInfo)) );
2611 hCurrentWnd = lpDragInfo->hScope;
2612 if( hCurrentWnd )
2613 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
2615 else
2616 if( hCurrentWnd )
2617 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
2619 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
2621 ReleaseCapture();
2622 ShowCursor32( FALSE );
2624 if( hCursor )
2626 SetCursor32( hOldCursor );
2627 if (hDragCursor) DestroyCursor32( hDragCursor );
2630 if( hCurrentCursor != hBummer )
2631 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
2632 (WPARAM16)hWnd, (LPARAM)spDragInfo );
2633 else
2634 msg.lParam = 0;
2635 GlobalFree16(hDragInfo);
2637 return (DWORD)(msg.lParam);