Fixes for C++ Winelib compilation.
[wine.git] / windows / win.c
blobc73ef1d829530a388a97ddb690b8f4fc0c0c8aca
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 /* Desktop window */
35 static WND *pWndDesktop = NULL;
37 static HWND32 hwndSysModal = 0;
39 static WORD wDragWidth = 4;
40 static WORD wDragHeight= 3;
42 /***********************************************************************
43 * WIN_FindWndPtr
45 * Return a pointer to the WND structure corresponding to a HWND.
47 WND * WIN_FindWndPtr( HWND32 hwnd )
49 WND * ptr;
51 if (!hwnd || HIWORD(hwnd)) return NULL;
52 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
53 if (ptr->dwMagic != WND_MAGIC) return NULL;
54 if (ptr->hwndSelf != hwnd)
56 ERR( win, "Can't happen: hwnd %04x self pointer is %04x\n",
57 hwnd, ptr->hwndSelf );
58 return NULL;
60 return ptr;
64 /***********************************************************************
65 * WIN_DumpWindow
67 * Dump the content of a window structure to stderr.
69 void WIN_DumpWindow( HWND32 hwnd )
71 WND *ptr;
72 char className[80];
73 int i;
75 if (!(ptr = WIN_FindWndPtr( hwnd )))
77 WARN( win, "%04x is not a window handle\n", hwnd );
78 return;
81 if (!GetClassName32A( hwnd, className, sizeof(className ) ))
82 strcpy( className, "#NULL#" );
84 TRACE( win, "Window %04x (%p):\n", hwnd, ptr );
85 DUMP( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
86 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
87 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
88 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
89 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
90 ptr->next, ptr->child, ptr->parent, ptr->owner,
91 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
92 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
93 ptr->dwStyle, ptr->dwExStyle, (UINT32)ptr->winproc,
94 ptr->text ? ptr->text : "",
95 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
96 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
97 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
98 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
100 if (ptr->class->cbWndExtra)
102 DUMP( "extra bytes:" );
103 for (i = 0; i < ptr->class->cbWndExtra; i++)
104 DUMP( " %02x", *((BYTE*)ptr->wExtra+i) );
105 DUMP( "\n" );
107 DUMP( "\n" );
111 /***********************************************************************
112 * WIN_WalkWindows
114 * Walk the windows tree and print each window on stderr.
116 void WIN_WalkWindows( HWND32 hwnd, int indent )
118 WND *ptr;
119 char className[80];
121 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop;
122 if (!ptr)
124 WARN( win, "Invalid window handle %04x\n", hwnd );
125 return;
128 if (!indent) /* first time around */
129 DUMP( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
130 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
131 " Text");
133 while (ptr)
135 DUMP( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
137 GlobalGetAtomName16(ptr->class->atomName,className,sizeof(className));
139 DUMP( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
140 (DWORD)ptr, ptr->hmemTaskQ, className,
141 (UINT32)ptr->dwStyle, (UINT32)ptr->winproc,
142 ptr->text?ptr->text:"<null>");
144 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
145 ptr = ptr->next;
150 /***********************************************************************
151 * WIN_GetXWindow
153 * Return the X window associated to a window.
155 Window WIN_GetXWindow( HWND32 hwnd )
157 WND *wndPtr = WIN_FindWndPtr( hwnd );
158 while (wndPtr && !wndPtr->window) wndPtr = wndPtr->parent;
159 return wndPtr ? wndPtr->window : 0;
163 /***********************************************************************
164 * WIN_UnlinkWindow
166 * Remove a window from the siblings linked list.
168 BOOL32 WIN_UnlinkWindow( HWND32 hwnd )
170 WND *wndPtr, **ppWnd;
172 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
173 ppWnd = &wndPtr->parent->child;
174 while (*ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
175 *ppWnd = wndPtr->next;
176 return TRUE;
180 /***********************************************************************
181 * WIN_LinkWindow
183 * Insert a window into the siblings linked list.
184 * The window is inserted after the specified window, which can also
185 * be specified as HWND_TOP or HWND_BOTTOM.
187 BOOL32 WIN_LinkWindow( HWND32 hwnd, HWND32 hwndInsertAfter )
189 WND *wndPtr, **ppWnd;
191 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
193 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
195 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
196 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
197 while (*ppWnd) ppWnd = &(*ppWnd)->next;
199 else /* Normal case */
201 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
202 if (!afterPtr) return FALSE;
203 ppWnd = &afterPtr->next;
205 wndPtr->next = *ppWnd;
206 *ppWnd = wndPtr;
207 return TRUE;
211 /***********************************************************************
212 * WIN_FindWinToRepaint
214 * Find a window that needs repaint.
216 HWND32 WIN_FindWinToRepaint( HWND32 hwnd, HQUEUE16 hQueue )
218 HWND32 hwndRet;
219 WND *pWnd = pWndDesktop;
221 /* Note: the desktop window never gets WM_PAINT messages
222 * The real reason why is because Windows DesktopWndProc
223 * does ValidateRgn inside WM_ERASEBKGND handler.
226 pWnd = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop->child;
228 for ( ; pWnd ; pWnd = pWnd->next )
230 if (!(pWnd->dwStyle & WS_VISIBLE))
232 TRACE(win, "skipping window %04x\n",
233 pWnd->hwndSelf );
234 continue;
236 if ((pWnd->hmemTaskQ == hQueue) &&
237 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))) break;
239 if (pWnd->child )
240 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
241 return hwndRet;
244 if (!pWnd) return 0;
246 hwndRet = pWnd->hwndSelf;
248 /* look among siblings if we got a transparent window */
249 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
250 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
252 pWnd = pWnd->next;
254 if (pWnd) hwndRet = pWnd->hwndSelf;
255 TRACE(win,"found %04x\n",hwndRet);
256 return hwndRet;
260 /***********************************************************************
261 * WIN_DestroyWindow
263 * Destroy storage associated to a window. "Internals" p.358
265 static WND* WIN_DestroyWindow( WND* wndPtr )
267 HWND32 hwnd = wndPtr->hwndSelf;
268 WND *pWnd;
270 TRACE(win, "%04x\n", wndPtr->hwndSelf );
272 #ifdef CONFIG_IPC
273 if (main_block)
274 DDE_DestroyWindow(wndPtr->hwndSelf);
275 #endif /* CONFIG_IPC */
277 /* free child windows */
279 while ((pWnd = wndPtr->child))
280 wndPtr->child = WIN_DestroyWindow( pWnd );
282 SendMessage32A( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
284 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
286 WINPOS_CheckInternalPos( hwnd );
287 if( hwnd == GetCapture32()) ReleaseCapture();
289 /* free resources associated with the window */
291 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
292 PROPERTY_RemoveWindowProps( wndPtr );
294 wndPtr->dwMagic = 0; /* Mark it as invalid */
296 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
298 if (wndPtr->hrgnUpdate > 1) DeleteObject32( wndPtr->hrgnUpdate );
299 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
302 /* toss stale messages from the queue */
304 if( wndPtr->hmemTaskQ )
306 int pos;
307 BOOL32 bPostQuit = FALSE;
308 WPARAM32 wQuitParam = 0;
309 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) GlobalLock16(wndPtr->hmemTaskQ);
311 while( (pos = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != -1 )
313 if( msgQ->messages[pos].msg.message == WM_QUIT )
315 bPostQuit = TRUE;
316 wQuitParam = msgQ->messages[pos].msg.wParam;
318 QUEUE_RemoveMsg(msgQ, pos);
320 /* repost WM_QUIT to make sure this app exits its message loop */
321 if( bPostQuit ) PostQuitMessage32(wQuitParam);
322 wndPtr->hmemTaskQ = 0;
325 if (!(wndPtr->dwStyle & WS_CHILD))
326 if (wndPtr->wIDmenu) DestroyMenu32( (HMENU32)wndPtr->wIDmenu );
327 if (wndPtr->hSysMenu) DestroyMenu32( wndPtr->hSysMenu );
328 if (wndPtr->window) EVENT_DestroyWindow( wndPtr );
329 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
330 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
331 wndPtr->hwndSelf = 0;
332 wndPtr->class->cWindows--;
333 wndPtr->class = NULL;
334 pWnd = wndPtr->next;
336 USER_HEAP_FREE( hwnd );
337 return pWnd;
340 /***********************************************************************
341 * WIN_ResetQueueWindows
343 * Reset the queue of all the children of a given window.
344 * Return TRUE if something was done.
346 BOOL32 WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
348 BOOL32 ret = FALSE;
350 if (hNew) /* Set a new queue */
352 for (wnd = wnd->child; (wnd); wnd = wnd->next)
354 if (wnd->hmemTaskQ == hQueue)
356 wnd->hmemTaskQ = hNew;
357 ret = TRUE;
359 if (wnd->child)
360 ret |= WIN_ResetQueueWindows( wnd->child, hQueue, hNew );
363 else /* Queue is being destroyed */
365 while (wnd->child)
367 WND *tmp = wnd->child;
368 ret = FALSE;
369 while (tmp)
371 if (tmp->hmemTaskQ == hQueue)
373 DestroyWindow32( tmp->hwndSelf );
374 ret = TRUE;
375 break;
377 if (tmp->child && WIN_ResetQueueWindows(tmp->child,hQueue,0))
378 ret = TRUE;
379 else
380 tmp = tmp->next;
382 if (!ret) break;
385 return ret;
388 /***********************************************************************
389 * WIN_CreateDesktopWindow
391 * Create the desktop window.
393 BOOL32 WIN_CreateDesktopWindow(void)
395 CLASS *class;
396 HWND32 hwndDesktop;
398 TRACE(win,"Creating desktop window\n");
400 if (!ICONTITLE_Init() ||
401 !WINPOS_CreateInternalPosAtom() ||
402 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
403 return FALSE;
405 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
406 if (!hwndDesktop) return FALSE;
407 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
409 pWndDesktop->next = NULL;
410 pWndDesktop->child = NULL;
411 pWndDesktop->parent = NULL;
412 pWndDesktop->owner = NULL;
413 pWndDesktop->class = class;
414 pWndDesktop->dwMagic = WND_MAGIC;
415 pWndDesktop->hwndSelf = hwndDesktop;
416 pWndDesktop->hInstance = 0;
417 pWndDesktop->rectWindow.left = 0;
418 pWndDesktop->rectWindow.top = 0;
419 pWndDesktop->rectWindow.right = SYSMETRICS_CXSCREEN;
420 pWndDesktop->rectWindow.bottom = SYSMETRICS_CYSCREEN;
421 pWndDesktop->rectClient = pWndDesktop->rectWindow;
422 pWndDesktop->text = NULL;
423 pWndDesktop->hmemTaskQ = 0; /* Desktop does not belong to a task */
424 pWndDesktop->hrgnUpdate = 0;
425 pWndDesktop->hwndLastActive = hwndDesktop;
426 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
427 WS_CLIPSIBLINGS;
428 pWndDesktop->dwExStyle = 0;
429 pWndDesktop->dce = NULL;
430 pWndDesktop->pVScroll = NULL;
431 pWndDesktop->pHScroll = NULL;
432 pWndDesktop->pProp = NULL;
433 pWndDesktop->wIDmenu = 0;
434 pWndDesktop->helpContext = 0;
435 pWndDesktop->flags = 0;
436 pWndDesktop->window = rootWindow;
437 pWndDesktop->hSysMenu = 0;
438 pWndDesktop->userdata = 0;
439 pWndDesktop->pDriver = &X11DRV_WND_Driver;
440 pWndDesktop->expose_event = NULL;
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->expose_event = NULL;
578 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
579 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
581 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
583 /* Call the WH_CBT hook */
585 hwndLinkAfter = (cs->style & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
587 if (HOOK_IsHooked( WH_CBT ))
589 CBT_CREATEWND32A cbtc;
590 LRESULT ret;
592 cbtc.lpcs = cs;
593 cbtc.hwndInsertAfter = hwndLinkAfter;
594 ret = unicode ? HOOK_CallHooks32W(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
595 : HOOK_CallHooks32A(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
596 if (ret)
598 TRACE(win, "CBT-hook returned 0\n");
599 USER_HEAP_FREE( hwnd );
600 return 0;
604 /* Increment class window counter */
606 classPtr->cWindows++;
608 /* Correct the window style */
610 if (!(cs->style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
612 wndPtr->dwStyle |= WS_CAPTION | WS_CLIPSIBLINGS;
613 wndPtr->flags |= WIN_NEED_SIZE;
615 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
617 /* Get class or window DC if needed */
619 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
620 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
621 else wndPtr->dce = NULL;
623 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
625 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
627 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
628 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
629 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
630 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
631 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
634 if(cs->style & WS_CHILD)
636 if(cs->cx < 0) cs->cx = 0;
637 if(cs->cy < 0) cs->cy = 0;
639 else
641 if (cs->cx <= 0) cs->cx = 1;
642 if (cs->cy <= 0) cs->cy = 1;
645 wndPtr->rectWindow.left = cs->x;
646 wndPtr->rectWindow.top = cs->y;
647 wndPtr->rectWindow.right = cs->x + cs->cx;
648 wndPtr->rectWindow.bottom = cs->y + cs->cy;
649 wndPtr->rectClient = wndPtr->rectWindow;
651 (*wndPtr->pDriver->pCreateWindow)(wndPtr, classPtr, cs, unicode);
653 /* Set the window menu */
655 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
657 if (cs->hMenu) SetMenu32(hwnd, cs->hMenu);
658 else
660 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
661 if (classPtr->menuNameA)
662 cs->hMenu = HIWORD(classPtr->menuNameA) ?
663 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
664 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
665 #else
666 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
667 if (menuName)
669 if (HIWORD(cs->hInstance))
670 cs->hMenu = LoadMenu32A(cs->hInstance,PTR_SEG_TO_LIN(menuName));
671 else
672 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
674 if (cs->hMenu) SetMenu32( hwnd, cs->hMenu );
676 #endif
679 else wndPtr->wIDmenu = (UINT32)cs->hMenu;
681 /* Send the WM_CREATE message
682 * Perhaps we shouldn't allow width/height changes as well.
683 * See p327 in "Internals".
686 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
688 localSend32 = unicode ? SendMessage32W : SendMessage32A;
689 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
691 /* Insert the window in the linked list */
693 WIN_LinkWindow( hwnd, hwndLinkAfter );
695 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
696 NULL, NULL, 0, &wndPtr->rectClient );
697 OffsetRect32(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
698 maxPos.y - wndPtr->rectWindow.top);
699 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
701 /* Send the size messages */
703 if (!(wndPtr->flags & WIN_NEED_SIZE))
705 /* send it anyway */
706 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
707 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
708 WARN(win,"sending bogus WM_SIZE message 0x%08lx\n",
709 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
710 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
711 SendMessage32A( hwnd, WM_SIZE, SIZE_RESTORED,
712 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
713 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
714 SendMessage32A( hwnd, WM_MOVE, 0,
715 MAKELONG( wndPtr->rectClient.left,
716 wndPtr->rectClient.top ) );
719 /* Show the window, maximizing or minimizing if needed */
721 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
723 RECT16 newPos;
724 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
725 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
726 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
727 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow32()) ? SWP_NOACTIVATE : 0;
728 SetWindowPos32( hwnd, 0, newPos.left, newPos.top,
729 newPos.right, newPos.bottom, SWP_FRAMECHANGED | swFlag );
732 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
734 /* Notify the parent window only */
736 SendMessage32A( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
737 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
738 if( !IsWindow32(hwnd) ) return 0;
741 if (cs->style & WS_VISIBLE) ShowWindow32( hwnd, SW_SHOW );
743 /* Call WH_SHELL hook */
745 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
746 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
748 TRACE(win, "created window %04x\n", hwnd);
749 return hwnd;
751 WIN_UnlinkWindow( hwnd );
754 /* Abort window creation */
756 WARN(win, "aborted by WM_xxCREATE!\n");
757 WIN_DestroyWindow( wndPtr );
758 return 0;
762 /***********************************************************************
763 * CreateWindow16 (USER.41)
765 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
766 DWORD style, INT16 x, INT16 y, INT16 width,
767 INT16 height, HWND16 parent, HMENU16 menu,
768 HINSTANCE16 instance, LPVOID data )
770 return CreateWindowEx16( 0, className, windowName, style,
771 x, y, width, height, parent, menu, instance, data );
775 /***********************************************************************
776 * CreateWindowEx16 (USER.452)
778 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
779 LPCSTR windowName, DWORD style, INT16 x,
780 INT16 y, INT16 width, INT16 height,
781 HWND16 parent, HMENU16 menu,
782 HINSTANCE16 instance, LPVOID data )
784 ATOM classAtom;
785 CREATESTRUCT32A cs;
787 /* Find the class atom */
789 if (!(classAtom = GlobalFindAtom32A( className )))
791 fprintf( stderr, "CreateWindowEx16: bad class name " );
792 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
793 else fprintf( stderr, "'%s'\n", className );
794 return 0;
797 /* Fix the coordinates */
799 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)x;
800 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)y;
801 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)width;
802 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)height;
804 /* Create the window */
806 cs.lpCreateParams = data;
807 cs.hInstance = (HINSTANCE32)instance;
808 cs.hMenu = (HMENU32)menu;
809 cs.hwndParent = (HWND32)parent;
810 cs.style = style;
811 cs.lpszName = windowName;
812 cs.lpszClass = className;
813 cs.dwExStyle = exStyle;
814 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
818 /***********************************************************************
819 * CreateWindowEx32A (USER32.83)
821 HWND32 WINAPI CreateWindowEx32A( DWORD exStyle, LPCSTR className,
822 LPCSTR windowName, DWORD style, INT32 x,
823 INT32 y, INT32 width, INT32 height,
824 HWND32 parent, HMENU32 menu,
825 HINSTANCE32 instance, LPVOID data )
827 ATOM classAtom;
828 CREATESTRUCT32A cs;
830 if(exStyle & WS_EX_MDICHILD)
831 return MDI_CreateMDIWindow32A(className, windowName, style, x, y, width, height, parent, instance, data);
832 /* Find the class atom */
834 if (!(classAtom = GlobalFindAtom32A( className )))
836 fprintf( stderr, "CreateWindowEx32A: bad class name " );
837 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
838 else fprintf( stderr, "'%s'\n", className );
839 return 0;
842 /* Create the window */
844 cs.lpCreateParams = data;
845 cs.hInstance = instance;
846 cs.hMenu = menu;
847 cs.hwndParent = parent;
848 cs.x = x;
849 cs.y = y;
850 cs.cx = width;
851 cs.cy = height;
852 cs.style = style;
853 cs.lpszName = windowName;
854 cs.lpszClass = className;
855 cs.dwExStyle = exStyle;
856 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
860 /***********************************************************************
861 * CreateWindowEx32W (USER32.84)
863 HWND32 WINAPI CreateWindowEx32W( DWORD exStyle, LPCWSTR className,
864 LPCWSTR windowName, DWORD style, INT32 x,
865 INT32 y, INT32 width, INT32 height,
866 HWND32 parent, HMENU32 menu,
867 HINSTANCE32 instance, LPVOID data )
869 ATOM classAtom;
870 CREATESTRUCT32W cs;
872 if(exStyle & WS_EX_MDICHILD)
873 return MDI_CreateMDIWindow32W(className, windowName, style, x, y, width, height, parent, instance, data);
875 /* Find the class atom */
877 if (!(classAtom = GlobalFindAtom32W( className )))
879 if (HIWORD(className))
881 LPSTR cn = HEAP_strdupWtoA( GetProcessHeap(), 0, className );
882 WARN( win, "Bad class name '%s'\n",cn);
883 HeapFree( GetProcessHeap(), 0, cn );
885 else
886 WARN( win, "Bad class name %p\n", className );
887 return 0;
890 /* Create the window */
892 cs.lpCreateParams = data;
893 cs.hInstance = instance;
894 cs.hMenu = menu;
895 cs.hwndParent = parent;
896 cs.x = x;
897 cs.y = y;
898 cs.cx = width;
899 cs.cy = height;
900 cs.style = style;
901 cs.lpszName = windowName;
902 cs.lpszClass = className;
903 cs.dwExStyle = exStyle;
904 /* Note: we rely on the fact that CREATESTRUCT32A and */
905 /* CREATESTRUCT32W have the same layout. */
906 return WIN_CreateWindowEx( (CREATESTRUCT32A *)&cs, classAtom, TRUE, TRUE );
910 /***********************************************************************
911 * WIN_CheckFocus
913 static void WIN_CheckFocus( WND* pWnd )
915 if( GetFocus16() == pWnd->hwndSelf )
916 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
919 /***********************************************************************
920 * WIN_SendDestroyMsg
922 static void WIN_SendDestroyMsg( WND* pWnd )
924 WIN_CheckFocus(pWnd);
926 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret32();
927 if( !pWnd->window ) CLIPBOARD_ResetOwner( pWnd );
929 SendMessage32A( pWnd->hwndSelf, WM_DESTROY, 0, 0);
931 if( IsWindow32(pWnd->hwndSelf) )
933 WND* pChild = pWnd->child;
934 while( pChild )
936 WIN_SendDestroyMsg( pChild );
937 pChild = pChild->next;
939 WIN_CheckFocus(pWnd);
941 else
942 WARN(win, "\tdestroyed itself while in WM_DESTROY!\n");
946 /***********************************************************************
947 * DestroyWindow16 (USER.53)
949 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
951 return DestroyWindow32(hwnd);
955 /***********************************************************************
956 * DestroyWindow32 (USER32.135)
958 BOOL32 WINAPI DestroyWindow32( HWND32 hwnd )
960 WND * wndPtr;
962 TRACE(win, "(%04x)\n", hwnd);
964 /* Initialization */
966 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
967 if (wndPtr == pWndDesktop) return FALSE; /* Can't destroy desktop */
969 /* Call hooks */
971 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
972 return FALSE;
974 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
976 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
977 /* FIXME: clean up palette - see "Internals" p.352 */
980 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
981 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
983 /* Notify the parent window only */
984 SendMessage32A( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
985 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
986 if( !IsWindow32(hwnd) ) return TRUE;
989 if( wndPtr->window ) CLIPBOARD_ResetOwner( wndPtr ); /* before the window is unmapped */
991 /* Hide the window */
993 if (wndPtr->dwStyle & WS_VISIBLE)
995 SetWindowPos32( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
996 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
997 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
998 if (!IsWindow32(hwnd)) return TRUE;
1001 /* Recursively destroy owned windows */
1003 if( !(wndPtr->dwStyle & WS_CHILD) )
1005 /* make sure top menu popup doesn't get destroyed */
1006 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1008 for (;;)
1010 WND *siblingPtr = wndPtr->parent->child; /* First sibling */
1011 while (siblingPtr)
1013 if (siblingPtr->owner == wndPtr)
1015 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1016 break;
1017 else
1018 siblingPtr->owner = NULL;
1020 siblingPtr = siblingPtr->next;
1022 if (siblingPtr) DestroyWindow32( siblingPtr->hwndSelf );
1023 else break;
1026 if( !Options.managed || EVENT_CheckFocus() )
1027 WINPOS_ActivateOtherWindow(wndPtr);
1029 if( wndPtr->owner &&
1030 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1031 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1034 /* Send destroy messages */
1036 WIN_SendDestroyMsg( wndPtr );
1037 if (!IsWindow32(hwnd)) return TRUE;
1039 /* Unlink now so we won't bother with the children later on */
1041 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1043 /* Destroy the window storage */
1045 WIN_DestroyWindow( wndPtr );
1046 return TRUE;
1050 /***********************************************************************
1051 * CloseWindow16 (USER.43)
1053 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1055 return CloseWindow32( hwnd );
1059 /***********************************************************************
1060 * CloseWindow32 (USER32.56)
1062 BOOL32 WINAPI CloseWindow32( HWND32 hwnd )
1064 WND * wndPtr = WIN_FindWndPtr( hwnd );
1065 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD)) return FALSE;
1066 ShowWindow32( hwnd, SW_MINIMIZE );
1067 return TRUE;
1071 /***********************************************************************
1072 * OpenIcon16 (USER.44)
1074 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1076 return OpenIcon32( hwnd );
1080 /***********************************************************************
1081 * OpenIcon32 (USER32.410)
1083 BOOL32 WINAPI OpenIcon32( HWND32 hwnd )
1085 if (!IsIconic32( hwnd )) return FALSE;
1086 ShowWindow32( hwnd, SW_SHOWNORMAL );
1087 return TRUE;
1091 /***********************************************************************
1092 * WIN_FindWindow
1094 * Implementation of FindWindow() and FindWindowEx().
1096 static HWND32 WIN_FindWindow( HWND32 parent, HWND32 child, ATOM className,
1097 LPCSTR title )
1099 WND *pWnd;
1100 CLASS *pClass = NULL;
1102 if (child)
1104 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1105 if (parent)
1107 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent)) return 0;
1109 else if (pWnd->parent != pWndDesktop) return 0;
1110 pWnd = pWnd->next;
1112 else
1114 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : pWndDesktop)) return 0;
1115 pWnd = pWnd->child;
1117 if (!pWnd) return 0;
1119 /* For a child window, all siblings will have the same hInstance, */
1120 /* so we can look for the class once and for all. */
1122 if (className && (pWnd->dwStyle & WS_CHILD))
1124 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1125 return 0;
1129 for ( ; pWnd; pWnd = pWnd->next)
1131 if (className && !(pWnd->dwStyle & WS_CHILD))
1133 if (!(pClass = CLASS_FindClassByAtom( className, GetExePtr(pWnd->hInstance))))
1134 continue; /* Skip this window */
1137 if (pClass && (pWnd->class != pClass))
1138 continue; /* Not the right class */
1140 /* Now check the title */
1142 if (!title) return pWnd->hwndSelf;
1143 if (pWnd->text && !strcmp( pWnd->text, title )) return pWnd->hwndSelf;
1145 return 0;
1150 /***********************************************************************
1151 * FindWindow16 (USER.50)
1153 HWND16 WINAPI FindWindow16( SEGPTR className, LPCSTR title )
1155 return FindWindowEx16( 0, 0, className, title );
1159 /***********************************************************************
1160 * FindWindowEx16 (USER.427)
1162 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child,
1163 SEGPTR className, LPCSTR title )
1165 ATOM atom = 0;
1167 TRACE(win, "%04x %04x '%s' '%s'\n", parent,
1168 child, HIWORD(className)?(char *)PTR_SEG_TO_LIN(className):"",
1169 title ? title : "");
1171 if (className)
1173 /* If the atom doesn't exist, then no class */
1174 /* with this name exists either. */
1175 if (!(atom = GlobalFindAtom16( className ))) return 0;
1177 return WIN_FindWindow( parent, child, atom, title );
1181 /***********************************************************************
1182 * FindWindow32A (USER32.198)
1184 HWND32 WINAPI FindWindow32A( LPCSTR className, LPCSTR title )
1186 HWND32 ret = FindWindowEx32A( 0, 0, className, title );
1187 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1188 return ret;
1192 /***********************************************************************
1193 * FindWindowEx32A (USER32.199)
1195 HWND32 WINAPI FindWindowEx32A( HWND32 parent, HWND32 child,
1196 LPCSTR className, LPCSTR title )
1198 ATOM atom = 0;
1200 if (className)
1202 /* If the atom doesn't exist, then no class */
1203 /* with this name exists either. */
1204 if (!(atom = GlobalFindAtom32A( className )))
1206 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1207 return 0;
1210 return WIN_FindWindow( parent, child, atom, title );
1214 /***********************************************************************
1215 * FindWindowEx32W (USER32.200)
1217 HWND32 WINAPI FindWindowEx32W( HWND32 parent, HWND32 child,
1218 LPCWSTR className, LPCWSTR title )
1220 ATOM atom = 0;
1221 char *buffer;
1222 HWND32 hwnd;
1224 if (className)
1226 /* If the atom doesn't exist, then no class */
1227 /* with this name exists either. */
1228 if (!(atom = GlobalFindAtom32W( className )))
1230 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1231 return 0;
1234 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1235 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1236 HeapFree( GetProcessHeap(), 0, buffer );
1237 return hwnd;
1241 /***********************************************************************
1242 * FindWindow32W (USER32.201)
1244 HWND32 WINAPI FindWindow32W( LPCWSTR className, LPCWSTR title )
1246 return FindWindowEx32W( 0, 0, className, title );
1250 /**********************************************************************
1251 * WIN_GetDesktop
1253 WND *WIN_GetDesktop(void)
1255 return pWndDesktop;
1259 /**********************************************************************
1260 * GetDesktopWindow16 (USER.286)
1262 HWND16 WINAPI GetDesktopWindow16(void)
1264 return (HWND16)pWndDesktop->hwndSelf;
1268 /**********************************************************************
1269 * GetDesktopWindow32 (USER32.232)
1271 HWND32 WINAPI GetDesktopWindow32(void)
1273 return pWndDesktop->hwndSelf;
1277 /**********************************************************************
1278 * GetDesktopHwnd (USER.278)
1280 * Exactly the same thing as GetDesktopWindow(), but not documented.
1281 * Don't ask me why...
1283 HWND16 WINAPI GetDesktopHwnd(void)
1285 return (HWND16)pWndDesktop->hwndSelf;
1289 /*******************************************************************
1290 * EnableWindow16 (USER.34)
1292 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1294 return EnableWindow32( hwnd, enable );
1298 /*******************************************************************
1299 * EnableWindow32 (USER32.172)
1301 BOOL32 WINAPI EnableWindow32( HWND32 hwnd, BOOL32 enable )
1303 WND *wndPtr;
1305 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1306 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1308 /* Enable window */
1309 wndPtr->dwStyle &= ~WS_DISABLED;
1310 SendMessage32A( hwnd, WM_ENABLE, TRUE, 0 );
1311 return TRUE;
1313 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1315 /* Disable window */
1316 wndPtr->dwStyle |= WS_DISABLED;
1317 if ((hwnd == GetFocus32()) || IsChild32( hwnd, GetFocus32() ))
1318 SetFocus32( 0 ); /* A disabled window can't have the focus */
1319 if ((hwnd == GetCapture32()) || IsChild32( hwnd, GetCapture32() ))
1320 ReleaseCapture(); /* A disabled window can't capture the mouse */
1321 SendMessage32A( hwnd, WM_ENABLE, FALSE, 0 );
1322 return FALSE;
1324 return ((wndPtr->dwStyle & WS_DISABLED) != 0);
1328 /***********************************************************************
1329 * IsWindowEnabled16 (USER.35)
1331 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1333 return IsWindowEnabled32(hWnd);
1337 /***********************************************************************
1338 * IsWindowEnabled32 (USER32.349)
1340 BOOL32 WINAPI IsWindowEnabled32(HWND32 hWnd)
1342 WND * wndPtr;
1344 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1345 return !(wndPtr->dwStyle & WS_DISABLED);
1349 /***********************************************************************
1350 * IsWindowUnicode (USER32.350)
1352 BOOL32 WINAPI IsWindowUnicode( HWND32 hwnd )
1354 WND * wndPtr;
1356 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1357 return (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1361 /**********************************************************************
1362 * GetWindowWord16 (USER.133)
1364 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1366 return GetWindowWord32( hwnd, offset );
1370 /**********************************************************************
1371 * GetWindowWord32 (USER32.314)
1373 WORD WINAPI GetWindowWord32( HWND32 hwnd, INT32 offset )
1375 WND * wndPtr = WIN_FindWndPtr( hwnd );
1376 if (!wndPtr) return 0;
1377 if (offset >= 0)
1379 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1381 WARN( win, "Invalid offset %d\n", offset );
1382 return 0;
1384 return *(WORD *)(((char *)wndPtr->wExtra) + offset);
1386 switch(offset)
1388 case GWW_ID:
1389 if (HIWORD(wndPtr->wIDmenu))
1390 WARN( win,"GWW_ID: discards high bits of 0x%08x!\n",
1391 wndPtr->wIDmenu);
1392 return (WORD)wndPtr->wIDmenu;
1393 case GWW_HWNDPARENT:
1394 return wndPtr->parent ?
1395 wndPtr->parent->hwndSelf : (
1396 wndPtr->owner ?
1397 wndPtr->owner->hwndSelf :
1399 case GWW_HINSTANCE:
1400 if (HIWORD(wndPtr->hInstance))
1401 WARN(win,"GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1402 wndPtr->hInstance);
1403 return (WORD)wndPtr->hInstance;
1404 default:
1405 WARN( win, "Invalid offset %d\n", offset );
1406 return 0;
1411 /**********************************************************************
1412 * WIN_GetWindowInstance
1414 HINSTANCE32 WIN_GetWindowInstance( HWND32 hwnd )
1416 WND * wndPtr = WIN_FindWndPtr( hwnd );
1417 if (!wndPtr) return (HINSTANCE32)0;
1418 return wndPtr->hInstance;
1422 /**********************************************************************
1423 * SetWindowWord16 (USER.134)
1425 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1427 return SetWindowWord32( hwnd, offset, newval );
1431 /**********************************************************************
1432 * SetWindowWord32 (USER32.524)
1434 WORD WINAPI SetWindowWord32( HWND32 hwnd, INT32 offset, WORD newval )
1436 WORD *ptr, retval;
1437 WND * wndPtr = WIN_FindWndPtr( hwnd );
1438 if (!wndPtr) return 0;
1439 if (offset >= 0)
1441 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1443 WARN( win, "Invalid offset %d\n", offset );
1444 return 0;
1446 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1448 else switch(offset)
1450 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1451 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1452 case GWW_HWNDPARENT: return SetParent32( hwnd, newval );
1453 default:
1454 WARN( win, "Invalid offset %d\n", offset );
1455 return 0;
1457 retval = *ptr;
1458 *ptr = newval;
1459 return retval;
1463 /**********************************************************************
1464 * WIN_GetWindowLong
1466 * Helper function for GetWindowLong().
1468 static LONG WIN_GetWindowLong( HWND32 hwnd, INT32 offset, WINDOWPROCTYPE type )
1470 LONG retval;
1471 WND * wndPtr = WIN_FindWndPtr( hwnd );
1472 if (!wndPtr) return 0;
1473 if (offset >= 0)
1475 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1477 WARN( win, "Invalid offset %d\n", offset );
1478 return 0;
1480 retval = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1481 /* Special case for dialog window procedure */
1482 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1483 return (LONG)WINPROC_GetProc( (HWINDOWPROC)retval, type );
1484 return retval;
1486 switch(offset)
1488 case GWL_USERDATA: return wndPtr->userdata;
1489 case GWL_STYLE: return wndPtr->dwStyle;
1490 case GWL_EXSTYLE: return wndPtr->dwExStyle;
1491 case GWL_ID: return (LONG)wndPtr->wIDmenu;
1492 case GWL_WNDPROC: return (LONG)WINPROC_GetProc( wndPtr->winproc,
1493 type );
1494 case GWL_HWNDPARENT: return wndPtr->parent ?
1495 (HWND32)wndPtr->parent->hwndSelf : 0;
1496 case GWL_HINSTANCE: return wndPtr->hInstance;
1497 default:
1498 WARN( win, "Unknown offset %d\n", offset );
1500 return 0;
1504 /**********************************************************************
1505 * WIN_SetWindowLong
1507 * Helper function for SetWindowLong().
1509 * 0 is the failure code. However, in the case of failure SetLastError
1510 * must be set to distinguish between a 0 return value and a failure.
1512 * FIXME: The error values for SetLastError may not be right. Can
1513 * someone check with the real thing?
1515 static LONG WIN_SetWindowLong( HWND32 hwnd, INT32 offset, LONG newval,
1516 WINDOWPROCTYPE type )
1518 LONG *ptr, retval;
1519 WND * wndPtr = WIN_FindWndPtr( hwnd );
1520 STYLESTRUCT style;
1522 TRACE(win,"%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1524 if (!wndPtr)
1526 /* Is this the right error? */
1527 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1528 return 0;
1531 if (offset >= 0)
1533 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1535 WARN( win, "Invalid offset %d\n", offset );
1537 /* Is this the right error? */
1538 SetLastError( ERROR_OUTOFMEMORY );
1540 return 0;
1542 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1543 /* Special case for dialog window procedure */
1544 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1546 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1547 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1548 type, WIN_PROC_WINDOW );
1549 return retval;
1552 else switch(offset)
1554 case GWL_ID:
1555 ptr = (DWORD*)&wndPtr->wIDmenu;
1556 break;
1557 case GWL_HINSTANCE:
1558 return SetWindowWord32( hwnd, offset, newval );
1559 case GWL_WNDPROC:
1560 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1561 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1562 type, WIN_PROC_WINDOW );
1563 return retval;
1564 case GWL_STYLE:
1565 style.styleOld = wndPtr->dwStyle;
1566 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
1567 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
1569 if (wndPtr->flags & WIN_ISWIN32)
1570 SendMessage32A(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1571 wndPtr->dwStyle = style.styleNew;
1572 if (wndPtr->flags & WIN_ISWIN32)
1573 SendMessage32A(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1574 return style.styleOld;
1576 case GWL_USERDATA:
1577 ptr = &wndPtr->userdata;
1578 break;
1579 case GWL_EXSTYLE:
1580 style.styleOld = wndPtr->dwExStyle;
1581 style.styleNew = newval;
1582 if (wndPtr->flags & WIN_ISWIN32)
1583 SendMessage32A(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1584 wndPtr->dwExStyle = newval;
1585 if (wndPtr->flags & WIN_ISWIN32)
1586 SendMessage32A(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1587 return style.styleOld;
1589 default:
1590 WARN( win, "Invalid offset %d\n", offset );
1592 /* Don't think this is right error but it should do */
1593 SetLastError( ERROR_OUTOFMEMORY );
1595 return 0;
1597 retval = *ptr;
1598 *ptr = newval;
1599 return retval;
1603 /**********************************************************************
1604 * GetWindowLong16 (USER.135)
1606 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1608 return WIN_GetWindowLong( (HWND32)hwnd, offset, WIN_PROC_16 );
1612 /**********************************************************************
1613 * GetWindowLong32A (USER32.305)
1615 LONG WINAPI GetWindowLong32A( HWND32 hwnd, INT32 offset )
1617 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1621 /**********************************************************************
1622 * GetWindowLong32W (USER32.306)
1624 LONG WINAPI GetWindowLong32W( HWND32 hwnd, INT32 offset )
1626 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1630 /**********************************************************************
1631 * SetWindowLong16 (USER.136)
1633 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1635 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1639 /**********************************************************************
1640 * SetWindowLong32A (USER32.517)
1642 LONG WINAPI SetWindowLong32A( HWND32 hwnd, INT32 offset, LONG newval )
1644 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1648 /**********************************************************************
1649 * SetWindowLong32W (USER32.518) Set window attribute
1651 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
1652 * value in a window's extra memory.
1654 * The _hwnd_ parameter specifies the window. is the handle to a
1655 * window that has extra memory. The _newval_ parameter contains the
1656 * new attribute or extra memory value. If positive, the _offset_
1657 * parameter is the byte-addressed location in the window's extra
1658 * memory to set. If negative, _offset_ specifies the window
1659 * attribute to set, and should be one of the following values:
1661 * GWL_EXSTYLE The window's extended window style
1663 * GWL_STYLE The window's window style.
1665 * GWL_WNDPROC Pointer to the window's window procedure.
1667 * GWL_HINSTANCE The window's pplication instance handle.
1669 * GWL_ID The window's identifier.
1671 * GWL_USERDATA The window's user-specified data.
1673 * If the window is a dialog box, the _offset_ parameter can be one of
1674 * the following values:
1676 * DWL_DLGPROC The address of the window's dialog box procedure.
1678 * DWL_MSGRESULT The return value of a message
1679 * that the dialog box procedure processed.
1681 * DWL_USER Application specific information.
1683 * RETURNS
1685 * If successful, returns the previous value located at _offset_. Otherwise,
1686 * returns 0.
1688 * NOTES
1690 * Extra memory for a window class is specified by a nonzero cbWndExtra
1691 * parameter of the WNDCLASS structure passed to RegisterClass() at the
1692 * time of class creation.
1694 * Using GWL_WNDPROC to set a new window procedure effectively creates
1695 * a window subclass. Use CallWindowProc() in the new windows procedure
1696 * to pass messages to the superclass's window procedure.
1698 * The user data is reserved for use by the application which created
1699 * the window.
1701 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
1702 * instead, call the EnableWindow() function to change the window's
1703 * disabled state.
1705 * Do not use GWL_HWNDPARENT to reset the window's parent, use
1706 * SetParent() instead.
1708 * BUGS
1710 * GWL_STYLE does not dispatch WM_STYLE_... messages.
1712 * CONFORMANCE
1714 * ECMA-234, Win32
1717 LONG WINAPI SetWindowLong32W(
1718 HWND32 hwnd, /* window to alter */
1719 INT32 offset, /* offset, in bytes, of location to alter */
1720 LONG newval /* new value of location */
1722 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1726 /*******************************************************************
1727 * GetWindowText16 (USER.36)
1729 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
1731 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1735 /*******************************************************************
1736 * GetWindowText32A (USER32.309)
1738 INT32 WINAPI GetWindowText32A( HWND32 hwnd, LPSTR lpString, INT32 nMaxCount )
1740 return (INT32)SendMessage32A( hwnd, WM_GETTEXT, nMaxCount,
1741 (LPARAM)lpString );
1744 /*******************************************************************
1745 * InternalGetWindowText (USER32.326)
1747 INT32 WINAPI InternalGetWindowText(HWND32 hwnd,LPWSTR lpString,INT32 nMaxCount )
1749 FIXME(win,"(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
1750 return GetWindowText32W(hwnd,lpString,nMaxCount);
1754 /*******************************************************************
1755 * GetWindowText32W (USER32.312)
1757 INT32 WINAPI GetWindowText32W( HWND32 hwnd, LPWSTR lpString, INT32 nMaxCount )
1759 return (INT32)SendMessage32W( hwnd, WM_GETTEXT, nMaxCount,
1760 (LPARAM)lpString );
1764 /*******************************************************************
1765 * SetWindowText16 (USER.37)
1767 void WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
1769 SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1773 /*******************************************************************
1774 * SetWindowText32A (USER32.521)
1776 void WINAPI SetWindowText32A( HWND32 hwnd, LPCSTR lpString )
1778 SendMessage32A( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1782 /*******************************************************************
1783 * SetWindowText32W (USER32.523)
1785 void WINAPI SetWindowText32W( HWND32 hwnd, LPCWSTR lpString )
1787 SendMessage32W( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1791 /*******************************************************************
1792 * GetWindowTextLength16 (USER.38)
1794 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
1796 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1800 /*******************************************************************
1801 * GetWindowTextLength32A (USER32.310)
1803 INT32 WINAPI GetWindowTextLength32A( HWND32 hwnd )
1805 return SendMessage32A( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1808 /*******************************************************************
1809 * GetWindowTextLength32W (USER32.311)
1811 INT32 WINAPI GetWindowTextLength32W( HWND32 hwnd )
1813 return SendMessage32W( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1817 /*******************************************************************
1818 * IsWindow16 (USER.47)
1820 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
1822 return IsWindow32( hwnd );
1825 void WINAPI WIN16_IsWindow16( CONTEXT *context )
1827 WORD *stack = PTR_SEG_OFF_TO_LIN(SS_reg(context), SP_reg(context));
1828 HWND16 hwnd = (HWND16)stack[2];
1830 AX_reg(context) = IsWindow32( hwnd );
1831 ES_reg(context) = USER_HeapSel;
1835 /*******************************************************************
1836 * IsWindow32 (USER32.348)
1838 BOOL32 WINAPI IsWindow32( HWND32 hwnd )
1840 WND * wndPtr = WIN_FindWndPtr( hwnd );
1841 return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
1845 /*****************************************************************
1846 * GetParent16 (USER.46)
1848 HWND16 WINAPI GetParent16( HWND16 hwnd )
1850 return (HWND16)GetParent32( hwnd );
1854 /*****************************************************************
1855 * GetParent32 (USER32.278)
1857 HWND32 WINAPI GetParent32( HWND32 hwnd )
1859 WND *wndPtr = WIN_FindWndPtr(hwnd);
1860 if ((!wndPtr) || (!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD)))) return 0;
1861 wndPtr = (wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner;
1862 return wndPtr ? wndPtr->hwndSelf : 0;
1865 /*****************************************************************
1866 * WIN_GetTopParent
1868 * Get the top-level parent for a child window.
1870 WND* WIN_GetTopParentPtr( WND* pWnd )
1872 while( pWnd && (pWnd->dwStyle & WS_CHILD)) pWnd = pWnd->parent;
1873 return pWnd;
1876 /*****************************************************************
1877 * WIN_GetTopParent
1879 * Get the top-level parent for a child window.
1881 HWND32 WIN_GetTopParent( HWND32 hwnd )
1883 WND *wndPtr = WIN_GetTopParentPtr ( WIN_FindWndPtr( hwnd ) );
1884 return wndPtr ? wndPtr->hwndSelf : 0;
1888 /*****************************************************************
1889 * SetParent16 (USER.233)
1891 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
1893 return SetParent32( hwndChild, hwndNewParent );
1897 /*****************************************************************
1898 * SetParent32 (USER32.495)
1900 HWND32 WINAPI SetParent32( HWND32 hwndChild, HWND32 hwndNewParent )
1902 WND *wndPtr = WIN_FindWndPtr( hwndChild );
1903 WND *pWndNewParent =
1904 (hwndNewParent) ? WIN_FindWndPtr( hwndNewParent ) : pWndDesktop;
1905 WND *pWndOldParent =
1906 (wndPtr)?(*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent):NULL;
1908 return pWndOldParent?pWndOldParent->hwndSelf:0;
1911 /*******************************************************************
1912 * IsChild16 (USER.48)
1914 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
1916 return IsChild32(parent,child);
1920 /*******************************************************************
1921 * IsChild32 (USER32.339)
1923 BOOL32 WINAPI IsChild32( HWND32 parent, HWND32 child )
1925 WND * wndPtr = WIN_FindWndPtr( child );
1926 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1928 wndPtr = wndPtr->parent;
1929 if (wndPtr->hwndSelf == parent) return TRUE;
1931 return FALSE;
1935 /***********************************************************************
1936 * IsWindowVisible16 (USER.49)
1938 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
1940 return IsWindowVisible32(hwnd);
1944 /***********************************************************************
1945 * IsWindowVisible32 (USER32.351)
1947 BOOL32 WINAPI IsWindowVisible32( HWND32 hwnd )
1949 WND *wndPtr = WIN_FindWndPtr( hwnd );
1950 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1952 if (!(wndPtr->dwStyle & WS_VISIBLE)) return FALSE;
1953 wndPtr = wndPtr->parent;
1955 return (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
1959 /***********************************************************************
1960 * WIN_IsWindowDrawable
1962 * hwnd is drawable when it is visible, all parents are not
1963 * minimized, and it is itself not minimized unless we are
1964 * trying to draw its default class icon.
1966 BOOL32 WIN_IsWindowDrawable( WND* wnd, BOOL32 icon )
1968 if( (wnd->dwStyle & WS_MINIMIZE &&
1969 icon && wnd->class->hIcon) ||
1970 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
1971 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
1972 if( wnd->dwStyle & WS_MINIMIZE ||
1973 !(wnd->dwStyle & WS_VISIBLE) ) break;
1974 return (wnd == NULL);
1978 /*******************************************************************
1979 * GetTopWindow16 (USER.229)
1981 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
1983 return GetTopWindow32(hwnd);
1987 /*******************************************************************
1988 * GetTopWindow32 (USER.229)
1990 HWND32 WINAPI GetTopWindow32( HWND32 hwnd )
1992 WND * wndPtr = WIN_FindWndPtr( hwnd );
1993 if (wndPtr && wndPtr->child) return wndPtr->child->hwndSelf;
1994 else return 0;
1998 /*******************************************************************
1999 * GetWindow16 (USER.262)
2001 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2003 return GetWindow32( hwnd,rel );
2007 /*******************************************************************
2008 * GetWindow32 (USER32.302)
2010 HWND32 WINAPI GetWindow32( HWND32 hwnd, WORD rel )
2012 WND * wndPtr = WIN_FindWndPtr( hwnd );
2013 if (!wndPtr) return 0;
2014 switch(rel)
2016 case GW_HWNDFIRST:
2017 if (wndPtr->parent) return wndPtr->parent->child->hwndSelf;
2018 else return 0;
2020 case GW_HWNDLAST:
2021 if (!wndPtr->parent) return 0; /* Desktop window */
2022 while (wndPtr->next) wndPtr = wndPtr->next;
2023 return wndPtr->hwndSelf;
2025 case GW_HWNDNEXT:
2026 if (!wndPtr->next) return 0;
2027 return wndPtr->next->hwndSelf;
2029 case GW_HWNDPREV:
2030 if (!wndPtr->parent) return 0; /* Desktop window */
2031 wndPtr = wndPtr->parent->child; /* First sibling */
2032 if (wndPtr->hwndSelf == hwnd) return 0; /* First in list */
2033 while (wndPtr->next)
2035 if (wndPtr->next->hwndSelf == hwnd) return wndPtr->hwndSelf;
2036 wndPtr = wndPtr->next;
2038 return 0;
2040 case GW_OWNER:
2041 return wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2043 case GW_CHILD:
2044 return wndPtr->child ? wndPtr->child->hwndSelf : 0;
2046 return 0;
2050 /*******************************************************************
2051 * GetNextWindow16 (USER.230)
2053 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2055 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2056 return GetWindow16( hwnd, flag );
2059 /*******************************************************************
2060 * ShowOwnedPopups16 (USER.265)
2062 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2064 ShowOwnedPopups32( owner, fShow );
2068 /*******************************************************************
2069 * ShowOwnedPopups32 (USER32.531)
2071 BOOL32 WINAPI ShowOwnedPopups32( HWND32 owner, BOOL32 fShow )
2073 WND *pWnd = pWndDesktop->child;
2074 while (pWnd)
2076 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
2077 (pWnd->dwStyle & WS_POPUP))
2078 ShowWindow32( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
2079 pWnd = pWnd->next;
2081 return TRUE;
2085 /*******************************************************************
2086 * GetLastActivePopup16 (USER.287)
2088 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2090 return GetLastActivePopup32( hwnd );
2093 /*******************************************************************
2094 * GetLastActivePopup32 (USER32.256)
2096 HWND32 WINAPI GetLastActivePopup32( HWND32 hwnd )
2098 WND *wndPtr;
2099 wndPtr = WIN_FindWndPtr(hwnd);
2100 if (wndPtr == NULL) return hwnd;
2101 return wndPtr->hwndLastActive;
2105 /*******************************************************************
2106 * WIN_BuildWinArray
2108 * Build an array of pointers to the children of a given window.
2109 * The array must be freed with HeapFree(SystemHeap). Return NULL
2110 * when no windows are found.
2112 WND **WIN_BuildWinArray( WND *wndPtr, UINT32 bwaFlags, UINT32* pTotal )
2114 WND **list, **ppWnd;
2115 WND *pWnd;
2116 UINT32 count, skipOwned, skipHidden;
2117 DWORD skipFlags;
2119 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2120 skipOwned = bwaFlags & BWA_SKIPOWNED;
2121 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2122 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2124 /* First count the windows */
2126 if (!wndPtr) wndPtr = pWndDesktop;
2127 for (pWnd = wndPtr->child, count = 0; pWnd; pWnd = pWnd->next)
2129 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
2130 if( !skipHidden || pWnd->dwStyle & WS_VISIBLE ) count++;
2133 if( count )
2135 /* Now build the list of all windows */
2137 if ((list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * (count + 1))))
2139 for (pWnd = wndPtr->child, ppWnd = list, count = 0; pWnd; pWnd = pWnd->next)
2141 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
2142 if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2144 *ppWnd++ = pWnd;
2145 count++;
2148 *ppWnd = NULL;
2150 else count = 0;
2151 } else list = NULL;
2153 if( pTotal ) *pTotal = count;
2154 return list;
2158 /*******************************************************************
2159 * EnumWindows16 (USER.54)
2161 BOOL16 WINAPI EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
2163 WND **list, **ppWnd;
2165 /* We have to build a list of all windows first, to avoid */
2166 /* unpleasant side-effects, for instance if the callback */
2167 /* function changes the Z-order of the windows. */
2169 if (!(list = WIN_BuildWinArray( pWndDesktop, 0, NULL ))) return FALSE;
2171 /* Now call the callback function for every window */
2173 for (ppWnd = list; *ppWnd; ppWnd++)
2175 /* Make sure that the window still exists */
2176 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2177 if (!lpEnumFunc( (*ppWnd)->hwndSelf, lParam )) break;
2179 HeapFree( SystemHeap, 0, list );
2180 return TRUE;
2184 /*******************************************************************
2185 * EnumWindows32 (USER32.193)
2187 BOOL32 WINAPI EnumWindows32( WNDENUMPROC32 lpEnumFunc, LPARAM lParam )
2189 return (BOOL32)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2193 /**********************************************************************
2194 * EnumTaskWindows16 (USER.225)
2196 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2197 LPARAM lParam )
2199 WND **list, **ppWnd;
2201 /* This function is the same as EnumWindows(), */
2202 /* except for an added check on the window's task. */
2204 if (!(list = WIN_BuildWinArray( pWndDesktop, 0, NULL ))) return FALSE;
2206 /* Now call the callback function for every window */
2208 for (ppWnd = list; *ppWnd; ppWnd++)
2210 /* Make sure that the window still exists */
2211 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2212 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2213 if (!func( (*ppWnd)->hwndSelf, lParam )) break;
2215 HeapFree( SystemHeap, 0, list );
2216 return TRUE;
2220 /**********************************************************************
2221 * EnumThreadWindows (USER32.190)
2223 BOOL32 WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC32 func, LPARAM lParam )
2225 THDB *tdb = THREAD_ID_TO_THDB(id);
2227 return (BOOL16)EnumTaskWindows16(tdb->teb.htask16, (WNDENUMPROC16)func, lParam);
2231 /**********************************************************************
2232 * WIN_EnumChildWindows
2234 * Helper function for EnumChildWindows().
2236 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2237 LPARAM lParam )
2239 WND **childList;
2240 BOOL16 ret = FALSE;
2242 for ( ; *ppWnd; ppWnd++)
2244 /* Make sure that the window still exists */
2245 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2246 /* Build children list first */
2247 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2248 ret = func( (*ppWnd)->hwndSelf, lParam );
2249 if (childList)
2251 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2252 HeapFree( SystemHeap, 0, childList );
2254 if (!ret) return FALSE;
2256 return TRUE;
2260 /**********************************************************************
2261 * EnumChildWindows16 (USER.55)
2263 BOOL16 WINAPI EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
2264 LPARAM lParam )
2266 WND **list, *pParent;
2268 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2269 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL ))) return FALSE;
2270 WIN_EnumChildWindows( list, func, lParam );
2271 HeapFree( SystemHeap, 0, list );
2272 return TRUE;
2276 /**********************************************************************
2277 * EnumChildWindows32 (USER32.178)
2279 BOOL32 WINAPI EnumChildWindows32( HWND32 parent, WNDENUMPROC32 func,
2280 LPARAM lParam )
2282 return (BOOL32)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2283 lParam );
2287 /*******************************************************************
2288 * AnyPopup16 (USER.52)
2290 BOOL16 WINAPI AnyPopup16(void)
2292 return AnyPopup32();
2296 /*******************************************************************
2297 * AnyPopup32 (USER32.4)
2299 BOOL32 WINAPI AnyPopup32(void)
2301 WND *wndPtr;
2302 for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next)
2303 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE)) return TRUE;
2304 return FALSE;
2308 /*******************************************************************
2309 * FlashWindow16 (USER.105)
2311 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2313 return FlashWindow32( hWnd, bInvert );
2317 /*******************************************************************
2318 * FlashWindow32 (USER32.202)
2320 BOOL32 WINAPI FlashWindow32( HWND32 hWnd, BOOL32 bInvert )
2322 WND *wndPtr = WIN_FindWndPtr(hWnd);
2324 TRACE(win,"%04x\n", hWnd);
2326 if (!wndPtr) return FALSE;
2328 if (wndPtr->dwStyle & WS_MINIMIZE)
2330 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2332 HDC32 hDC = GetDC32(hWnd);
2334 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2335 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2337 ReleaseDC32( hWnd, hDC );
2338 wndPtr->flags |= WIN_NCACTIVATED;
2340 else
2342 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2343 RDW_UPDATENOW | RDW_FRAME, 0 );
2344 wndPtr->flags &= ~WIN_NCACTIVATED;
2346 return TRUE;
2348 else
2350 WPARAM16 wparam;
2351 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2352 else wparam = (hWnd == GetActiveWindow32());
2354 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2355 return wparam;
2360 /*******************************************************************
2361 * SetSysModalWindow16 (USER.188)
2363 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
2365 HWND32 hWndOldModal = hwndSysModal;
2366 hwndSysModal = hWnd;
2367 FIXME(win, "EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2368 return hWndOldModal;
2372 /*******************************************************************
2373 * GetSysModalWindow16 (USER.52)
2375 HWND16 WINAPI GetSysModalWindow16(void)
2377 return hwndSysModal;
2381 /*******************************************************************
2382 * GetWindowContextHelpId (USER32.303)
2384 DWORD WINAPI GetWindowContextHelpId( HWND32 hwnd )
2386 WND *wnd = WIN_FindWndPtr( hwnd );
2387 if (!wnd) return 0;
2388 return wnd->helpContext;
2392 /*******************************************************************
2393 * SetWindowContextHelpId (USER32.515)
2395 BOOL32 WINAPI SetWindowContextHelpId( HWND32 hwnd, DWORD id )
2397 WND *wnd = WIN_FindWndPtr( hwnd );
2398 if (!wnd) return FALSE;
2399 wnd->helpContext = id;
2400 return TRUE;
2404 /*******************************************************************
2405 * DRAG_QueryUpdate
2407 * recursively find a child that contains spDragInfo->pt point
2408 * and send WM_QUERYDROPOBJECT
2410 BOOL16 DRAG_QueryUpdate( HWND32 hQueryWnd, SEGPTR spDragInfo, BOOL32 bNoSend )
2412 BOOL16 wParam,bResult = 0;
2413 POINT32 pt;
2414 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
2415 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
2416 RECT32 tempRect;
2418 if( !ptrQueryWnd || !ptrDragInfo ) return 0;
2420 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
2422 GetWindowRect32(hQueryWnd,&tempRect);
2424 if( !PtInRect32(&tempRect,pt) ||
2425 (ptrQueryWnd->dwStyle & WS_DISABLED) )
2426 return 0;
2428 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
2430 tempRect = ptrQueryWnd->rectClient;
2431 if(ptrQueryWnd->dwStyle & WS_CHILD)
2432 MapWindowPoints32( ptrQueryWnd->parent->hwndSelf, 0,
2433 (LPPOINT32)&tempRect, 2 );
2435 if (PtInRect32( &tempRect, pt))
2437 wParam = 0;
2439 for (ptrWnd = ptrQueryWnd->child; ptrWnd ;ptrWnd = ptrWnd->next)
2440 if( ptrWnd->dwStyle & WS_VISIBLE )
2442 GetWindowRect32( ptrWnd->hwndSelf, &tempRect );
2443 if (PtInRect32( &tempRect, pt )) break;
2446 if(ptrWnd)
2448 TRACE(msg,"hwnd = %04x, %d %d - %d %d\n",
2449 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
2450 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
2451 if( !(ptrWnd->dwStyle & WS_DISABLED) )
2452 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
2455 if(bResult) return bResult;
2457 else wParam = 1;
2459 else wParam = 1;
2461 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
2463 ptrDragInfo->hScope = hQueryWnd;
2465 bResult = ( bNoSend )
2466 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
2467 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
2468 (WPARAM16)wParam ,(LPARAM) spDragInfo );
2469 if( !bResult )
2470 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
2472 return bResult;
2476 /*******************************************************************
2477 * DragDetect (USER.465)
2479 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
2481 POINT32 pt32;
2482 CONV_POINT16TO32( &pt, &pt32 );
2483 return DragDetect32( hWnd, pt32 );
2486 /*******************************************************************
2487 * DragDetect32 (USER32.151)
2489 BOOL32 WINAPI DragDetect32( HWND32 hWnd, POINT32 pt )
2491 MSG16 msg;
2492 RECT16 rect;
2494 rect.left = pt.x - wDragWidth;
2495 rect.right = pt.x + wDragWidth;
2497 rect.top = pt.y - wDragHeight;
2498 rect.bottom = pt.y + wDragHeight;
2500 SetCapture32(hWnd);
2502 while(1)
2504 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
2506 if( msg.message == WM_LBUTTONUP )
2508 ReleaseCapture();
2509 return 0;
2511 if( msg.message == WM_MOUSEMOVE )
2513 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
2515 ReleaseCapture();
2516 return 1;
2520 WaitMessage();
2522 return 0;
2525 /******************************************************************************
2526 * DragObject16 (USER.464)
2528 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
2529 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
2531 MSG16 msg;
2532 LPDRAGINFO lpDragInfo;
2533 SEGPTR spDragInfo;
2534 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
2535 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
2536 WND *wndPtr = WIN_FindWndPtr(hWnd);
2537 HCURSOR16 hCurrentCursor = 0;
2538 HWND16 hCurrentWnd = 0;
2540 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
2541 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
2543 if( !lpDragInfo || !spDragInfo ) return 0L;
2545 hBummer = LoadCursor16(0, IDC_BUMMER16);
2547 if( !hBummer || !wndPtr )
2549 GlobalFree16(hDragInfo);
2550 return 0L;
2553 if(hCursor)
2555 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
2557 GlobalFree16(hDragInfo);
2558 return 0L;
2561 if( hDragCursor == hCursor ) hDragCursor = 0;
2562 else hCursor = hDragCursor;
2564 hOldCursor = SetCursor32(hDragCursor);
2567 lpDragInfo->hWnd = hWnd;
2568 lpDragInfo->hScope = 0;
2569 lpDragInfo->wFlags = wObj;
2570 lpDragInfo->hList = szList; /* near pointer! */
2571 lpDragInfo->hOfStruct = hOfStruct;
2572 lpDragInfo->l = 0L;
2574 SetCapture32(hWnd);
2575 ShowCursor32( TRUE );
2579 do{ WaitMessage(); }
2580 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
2582 *(lpDragInfo+1) = *lpDragInfo;
2584 lpDragInfo->pt = msg.pt;
2586 /* update DRAGINFO struct */
2587 TRACE(msg,"lpDI->hScope = %04x\n",lpDragInfo->hScope);
2589 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
2590 hCurrentCursor = hCursor;
2591 else
2593 hCurrentCursor = hBummer;
2594 lpDragInfo->hScope = 0;
2596 if( hCurrentCursor )
2597 SetCursor32(hCurrentCursor);
2599 /* send WM_DRAGLOOP */
2600 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
2601 (LPARAM) spDragInfo );
2602 /* send WM_DRAGSELECT or WM_DRAGMOVE */
2603 if( hCurrentWnd != lpDragInfo->hScope )
2605 if( hCurrentWnd )
2606 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
2607 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
2608 HIWORD(spDragInfo)) );
2609 hCurrentWnd = lpDragInfo->hScope;
2610 if( hCurrentWnd )
2611 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
2613 else
2614 if( hCurrentWnd )
2615 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
2617 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
2619 ReleaseCapture();
2620 ShowCursor32( FALSE );
2622 if( hCursor )
2624 SetCursor32( hOldCursor );
2625 if (hDragCursor) DestroyCursor32( hDragCursor );
2628 if( hCurrentCursor != hBummer )
2629 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
2630 (WPARAM16)hWnd, (LPARAM)spDragInfo );
2631 else
2632 msg.lParam = 0;
2633 GlobalFree16(hDragInfo);
2635 return (DWORD)(msg.lParam);