2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
11 #include "wine/winbase16.h"
12 #include "wine/winuser16.h"
19 #include "cursoricon.h"
24 #include "nonclient.h"
27 #include "clipboard.h"
35 #include "stackframe.h"
36 #include "debugtools.h"
38 DEFAULT_DEBUG_CHANNEL(win);
39 DECLARE_DEBUG_CHANNEL(msg);
41 /**********************************************************************/
43 WND_DRIVER *WND_Driver = NULL;
46 static WND *pWndDesktop = NULL;
48 static HWND hwndSysModal = 0;
50 static WORD wDragWidth = 4;
51 static WORD wDragHeight= 3;
54 static SYSLEVEL WIN_SysLevel;
56 /***********************************************************************
61 /* Initialisation of the critical section for thread safeness */
62 _CreateSysLevel( &WIN_SysLevel, 2 );
65 /***********************************************************************
68 * Locks access to all WND structures for thread safeness
70 void WIN_LockWnds( void )
72 _EnterSysLevel( &WIN_SysLevel );
75 /***********************************************************************
78 * Unlocks access to all WND structures
80 void WIN_UnlockWnds( void )
82 _LeaveSysLevel( &WIN_SysLevel );
85 /***********************************************************************
88 * Suspend the lock on WND structures.
89 * Returns the number of locks suspended
91 int WIN_SuspendWndsLock( void )
93 int isuspendedLocks = _ConfirmSysLevel( &WIN_SysLevel );
94 int count = isuspendedLocks;
97 _LeaveSysLevel( &WIN_SysLevel );
99 return isuspendedLocks;
102 /***********************************************************************
103 * WIN_RestoreWndsLock
105 * Restore the suspended locks on WND structures
107 void WIN_RestoreWndsLock( int ipreviousLocks )
109 while ( ipreviousLocks-- > 0 )
110 _EnterSysLevel( &WIN_SysLevel );
113 /***********************************************************************
116 * Return a pointer to the WND structure corresponding to a HWND.
118 WND * WIN_FindWndPtr( HWND hwnd )
122 if (!hwnd || HIWORD(hwnd)) goto error2;
123 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
124 /* Lock all WND structures for thread safeness*/
126 /*and increment destruction monitoring*/
129 if (ptr->dwMagic != WND_MAGIC) goto error;
130 if (ptr->hwndSelf != hwnd)
132 ERR("Can't happen: hwnd %04x self pointer is %04x\n",hwnd, ptr->hwndSelf );
135 /* returns a locked pointer */
138 /* Unlock all WND structures for thread safeness*/
140 /* and decrement destruction monitoring value */
145 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
149 /***********************************************************************
152 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
154 * Returns the locked initialisation pointer
156 WND *WIN_LockWndPtr(WND *initWndPtr)
158 if(!initWndPtr) return 0;
160 /* Lock all WND structures for thread safeness*/
162 /*and increment destruction monitoring*/
163 initWndPtr->irefCount++;
169 /***********************************************************************
172 * Release the pointer to the WND structure.
174 void WIN_ReleaseWndPtr(WND *wndPtr)
178 /*Decrement destruction monitoring value*/
180 /* Check if it's time to release the memory*/
181 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
184 USER_HEAP_FREE( wndPtr->hwndSelf);
185 wndPtr->hwndSelf = 0;
187 else if(wndPtr->irefCount < 0)
189 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
190 ERR("forgot a Lock on %p somewhere\n",wndPtr);
192 /*unlock all WND structures for thread safeness*/
196 /***********************************************************************
199 * Updates the value of oldPtr to newPtr.
201 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
205 tmpWnd = WIN_LockWndPtr(newPtr);
206 WIN_ReleaseWndPtr(*oldPtr);
211 /***********************************************************************
214 * Dump the content of a window structure to stderr.
216 void WIN_DumpWindow( HWND hwnd )
222 if (!(ptr = WIN_FindWndPtr( hwnd )))
224 WARN("%04x is not a window handle\n", hwnd );
228 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
229 strcpy( className, "#NULL#" );
231 TRACE("Window %04x (%p):\n", hwnd, ptr );
232 DPRINTF( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
233 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
234 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
235 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
236 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
237 ptr->next, ptr->child, ptr->parent, ptr->owner,
238 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
239 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
240 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
241 ptr->text ? ptr->text : "",
242 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
243 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
244 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
245 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
247 if (ptr->class->cbWndExtra)
249 DPRINTF( "extra bytes:" );
250 for (i = 0; i < ptr->class->cbWndExtra; i++)
251 DPRINTF( " %02x", *((BYTE*)ptr->wExtra+i) );
255 WIN_ReleaseWndPtr(ptr);
259 /***********************************************************************
262 * Walk the windows tree and print each window on stderr.
264 void WIN_WalkWindows( HWND hwnd, int indent )
269 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
273 WARN("Invalid window handle %04x\n", hwnd );
277 if (!indent) /* first time around */
278 DPRINTF( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
279 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
284 DPRINTF( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
286 GlobalGetAtomNameA(ptr->class->atomName,className,sizeof(className));
288 DPRINTF( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
289 (DWORD)ptr, ptr->hmemTaskQ, className,
290 (UINT)ptr->dwStyle, (UINT)ptr->winproc,
291 ptr->text?ptr->text:"<null>");
293 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
294 WIN_UpdateWndPtr(&ptr,ptr->next);
300 /***********************************************************************
303 * Remove a window from the siblings linked list.
305 BOOL WIN_UnlinkWindow( HWND hwnd )
307 WND *wndPtr, **ppWnd;
310 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
311 else if(!wndPtr->parent)
313 WIN_ReleaseWndPtr(wndPtr);
317 ppWnd = &wndPtr->parent->child;
318 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
321 *ppWnd = wndPtr->next;
324 WIN_ReleaseWndPtr(wndPtr);
329 /***********************************************************************
332 * Insert a window into the siblings linked list.
333 * The window is inserted after the specified window, which can also
334 * be specified as HWND_TOP or HWND_BOTTOM.
336 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
338 WND *wndPtr, **ppWnd;
340 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
341 else if(!wndPtr->parent)
343 WIN_ReleaseWndPtr(wndPtr);
346 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
348 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
349 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
350 while (*ppWnd) ppWnd = &(*ppWnd)->next;
352 else /* Normal case */
354 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
357 WIN_ReleaseWndPtr(wndPtr);
360 ppWnd = &afterPtr->next;
361 WIN_ReleaseWndPtr(afterPtr);
363 wndPtr->next = *ppWnd;
365 WIN_ReleaseWndPtr(wndPtr);
370 /***********************************************************************
371 * WIN_FindWinToRepaint
373 * Find a window that needs repaint.
375 HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE16 hQueue )
380 /* Note: the desktop window never gets WM_PAINT messages
381 * The real reason why is because Windows DesktopWndProc
382 * does ValidateRgn inside WM_ERASEBKGND handler.
385 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
387 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
389 if (!(pWnd->dwStyle & WS_VISIBLE))
391 TRACE("skipping window %04x\n",
394 else if ((pWnd->hmemTaskQ == hQueue) &&
395 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)))
398 else if (pWnd->child )
399 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
401 WIN_ReleaseWndPtr(pWnd);
412 hwndRet = pWnd->hwndSelf;
414 /* look among siblings if we got a transparent window */
415 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
416 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
418 WIN_UpdateWndPtr(&pWnd,pWnd->next);
422 hwndRet = pWnd->hwndSelf;
423 WIN_ReleaseWndPtr(pWnd);
425 TRACE("found %04x\n",hwndRet);
430 /***********************************************************************
433 * Destroy storage associated to a window. "Internals" p.358
434 * returns a locked wndPtr->next
436 static WND* WIN_DestroyWindow( WND* wndPtr )
438 HWND hwnd = wndPtr->hwndSelf;
441 TRACE("%04x\n", wndPtr->hwndSelf );
443 /* free child windows */
444 WIN_LockWndPtr(wndPtr->child);
445 while ((pWnd = wndPtr->child))
447 wndPtr->child = WIN_DestroyWindow( pWnd );
448 WIN_ReleaseWndPtr(pWnd);
452 * Clear the update region to make sure no WM_PAINT messages will be
453 * generated for this window while processing the WM_NCDESTROY.
455 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
457 if (wndPtr->hrgnUpdate > 1)
458 DeleteObject( wndPtr->hrgnUpdate );
460 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
462 wndPtr->hrgnUpdate = 0;
466 * Send the WM_NCDESTROY to the window being destroyed.
468 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
470 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
472 WINPOS_CheckInternalPos( wndPtr );
473 if( hwnd == GetCapture()) ReleaseCapture();
475 /* free resources associated with the window */
477 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
478 PROPERTY_RemoveWindowProps( wndPtr );
480 wndPtr->dwMagic = 0; /* Mark it as invalid */
482 /* toss stale messages from the queue */
484 if( wndPtr->hmemTaskQ )
486 BOOL bPostQuit = FALSE;
487 WPARAM wQuitParam = 0;
488 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) QUEUE_Lock(wndPtr->hmemTaskQ);
491 while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
493 if( qmsg->msg.message == WM_QUIT )
496 wQuitParam = qmsg->msg.wParam;
498 QUEUE_RemoveMsg(msgQ, qmsg);
503 /* repost WM_QUIT to make sure this app exits its message loop */
504 if( bPostQuit ) PostQuitMessage(wQuitParam);
505 wndPtr->hmemTaskQ = 0;
508 if (!(wndPtr->dwStyle & WS_CHILD))
511 DestroyMenu( wndPtr->wIDmenu );
514 if (wndPtr->hSysMenu)
516 DestroyMenu( wndPtr->hSysMenu );
517 wndPtr->hSysMenu = 0;
519 wndPtr->pDriver->pDestroyWindow( wndPtr );
520 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
521 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
522 wndPtr->class->cWindows--;
523 wndPtr->class = NULL;
525 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
527 wndPtr->pDriver->pFinalize(wndPtr);
532 /***********************************************************************
533 * WIN_ResetQueueWindows
535 * Reset the queue of all the children of a given window.
536 * Return TRUE if something was done.
538 BOOL WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
542 if (hNew) /* Set a new queue */
544 for (wnd = WIN_LockWndPtr(wnd->child); (wnd);WIN_UpdateWndPtr(&wnd,wnd->next))
546 if (wnd->hmemTaskQ == hQueue)
548 wnd->hmemTaskQ = hNew;
553 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
557 else /* Queue is being destroyed */
561 WND *tmp = WIN_LockWndPtr(wnd->child);
566 if (tmp->hmemTaskQ == hQueue)
568 DestroyWindow( tmp->hwndSelf );
572 tmp2 = WIN_LockWndPtr(tmp->child);
573 if (tmp2 && WIN_ResetQueueWindows(tmp2,hQueue,0))
577 WIN_UpdateWndPtr(&tmp,tmp->next);
579 WIN_ReleaseWndPtr(tmp2);
581 WIN_ReleaseWndPtr(tmp);
588 /***********************************************************************
589 * WIN_CreateDesktopWindow
591 * Create the desktop window.
593 BOOL WIN_CreateDesktopWindow(void)
598 TRACE("Creating desktop window\n");
601 if (!ICONTITLE_Init() ||
602 !WINPOS_CreateInternalPosAtom() ||
603 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
606 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
607 if (!hwndDesktop) return FALSE;
608 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
610 pWndDesktop->pDriver = WND_Driver;
611 pWndDesktop->pDriver->pInitialize(pWndDesktop);
613 pWndDesktop->next = NULL;
614 pWndDesktop->child = NULL;
615 pWndDesktop->parent = NULL;
616 pWndDesktop->owner = NULL;
617 pWndDesktop->class = class;
618 pWndDesktop->dwMagic = WND_MAGIC;
619 pWndDesktop->hwndSelf = hwndDesktop;
620 pWndDesktop->hInstance = 0;
621 pWndDesktop->rectWindow.left = 0;
622 pWndDesktop->rectWindow.top = 0;
623 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
624 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
625 pWndDesktop->rectClient = pWndDesktop->rectWindow;
626 pWndDesktop->text = NULL;
627 pWndDesktop->hmemTaskQ = GetFastQueue16();
628 pWndDesktop->hrgnUpdate = 0;
629 pWndDesktop->hwndLastActive = hwndDesktop;
630 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
632 pWndDesktop->dwExStyle = 0;
633 pWndDesktop->dce = NULL;
634 pWndDesktop->pVScroll = NULL;
635 pWndDesktop->pHScroll = NULL;
636 pWndDesktop->pProp = NULL;
637 pWndDesktop->wIDmenu = 0;
638 pWndDesktop->helpContext = 0;
639 pWndDesktop->flags = Options.desktopGeometry ? WIN_NATIVE : 0;
640 pWndDesktop->hSysMenu = 0;
641 pWndDesktop->userdata = 0;
642 pWndDesktop->winproc = (WNDPROC16)class->winproc;
643 pWndDesktop->irefCount = 0;
645 /* FIXME: How do we know if it should be Unicode or not */
646 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop, class, FALSE))
649 SendMessageA( hwndDesktop, WM_NCCREATE, 0, 0 );
650 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
655 /***********************************************************************
658 * Implementation of CreateWindowEx().
660 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
661 BOOL win32, BOOL unicode )
667 HWND16 hwnd, hwndLinkAfter;
668 POINT maxSize, maxPos, minTrack, maxTrack;
669 LRESULT (CALLBACK *localSend32)(HWND, UINT, WPARAM, LPARAM);
671 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
672 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
673 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
674 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
675 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
677 /* Find the parent window */
681 /* Make sure parent is valid */
682 if (!IsWindow( cs->hwndParent ))
684 WARN("Bad parent %04x\n", cs->hwndParent );
687 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
688 WARN("No parent for child window\n" );
689 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
692 /* Find the window class */
693 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
695 WARN("Bad class '%s'\n", cs->lpszClass );
699 /* Fix the coordinates */
701 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
702 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
706 if (!(cs->style & (WS_CHILD | WS_POPUP))) GetStartupInfoA( &info );
708 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
710 /* Never believe Microsoft's documentation... CreateWindowEx doc says
711 * that if an overlapped window is created with WS_VISIBLE style bit
712 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
713 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
716 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
717 * 2) it does not ignore the y parameter as the docs claim; instead, it
718 * uses it as second parameter to ShowWindow() unless y is either
719 * CW_USEDEFAULT or CW_USEDEFAULT16.
721 * The fact that we didn't do 2) caused bogus windows pop up when wine
722 * was running apps that were using this obscure feature. Example -
723 * calc.exe that comes with Win98 (only Win98, it's different from
724 * the one that comes with Win95 and NT)
726 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) sw = cs->y;
727 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
728 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
730 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
732 cs->cx = (info.dwFlags & STARTF_USESIZE) ? info.dwXSize : 0;
733 cs->cy = (info.dwFlags & STARTF_USESIZE) ? info.dwYSize : 0;
737 /* Create the window structure */
739 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
740 - sizeof(wndPtr->wExtra) )))
742 TRACE("out of memory\n" );
746 /* Fill the window structure */
748 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
750 wndPtr->child = NULL;
752 if ((cs->style & WS_CHILD) && cs->hwndParent)
754 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
755 wndPtr->owner = NULL;
756 WIN_ReleaseWndPtr(wndPtr->parent);
760 wndPtr->parent = pWndDesktop;
761 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
762 wndPtr->owner = NULL;
765 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
766 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
767 WIN_ReleaseWndPtr(wndPtr->owner);
768 WIN_ReleaseWndPtr(tmpWnd);
773 wndPtr->pDriver = wndPtr->parent->pDriver;
774 wndPtr->pDriver->pInitialize(wndPtr);
776 wndPtr->class = classPtr;
777 wndPtr->winproc = classPtr->winproc;
778 wndPtr->dwMagic = WND_MAGIC;
779 wndPtr->hwndSelf = hwnd;
780 wndPtr->hInstance = cs->hInstance;
782 wndPtr->hmemTaskQ = GetFastQueue16();
783 wndPtr->hrgnUpdate = 0;
784 wndPtr->hwndLastActive = hwnd;
785 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
786 wndPtr->dwExStyle = cs->dwExStyle;
788 wndPtr->helpContext = 0;
789 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
790 wndPtr->pVScroll = NULL;
791 wndPtr->pHScroll = NULL;
792 wndPtr->pProp = NULL;
793 wndPtr->userdata = 0;
794 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
795 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
796 wndPtr->irefCount = 1;
798 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
800 /* Call the WH_CBT hook */
802 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
803 ? HWND_BOTTOM : HWND_TOP;
805 if (HOOK_IsHooked( WH_CBT ))
811 cbtc.hwndInsertAfter = hwndLinkAfter;
812 ret = unicode ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
813 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
816 TRACE("CBT-hook returned 0\n");
817 wndPtr->pDriver->pFinalize(wndPtr);
818 USER_HEAP_FREE( hwnd );
824 /* Increment class window counter */
826 classPtr->cWindows++;
828 /* Correct the window style */
830 if (!(cs->style & WS_CHILD))
832 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
833 if (!(cs->style & WS_POPUP))
835 wndPtr->dwStyle |= WS_CAPTION;
836 wndPtr->flags |= WIN_NEED_SIZE;
840 /* Get class or window DC if needed */
842 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
843 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
844 else wndPtr->dce = NULL;
846 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
848 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
850 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
851 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
852 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
853 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
854 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
857 if(cs->style & WS_CHILD)
859 if(cs->cx < 0) cs->cx = 0;
860 if(cs->cy < 0) cs->cy = 0;
864 if (cs->cx <= 0) cs->cx = 1;
865 if (cs->cy <= 0) cs->cy = 1;
868 wndPtr->rectWindow.left = cs->x;
869 wndPtr->rectWindow.top = cs->y;
870 wndPtr->rectWindow.right = cs->x + cs->cx;
871 wndPtr->rectWindow.bottom = cs->y + cs->cy;
872 wndPtr->rectClient = wndPtr->rectWindow;
874 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
880 /* Set the window menu */
882 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
884 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
887 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
888 if (classPtr->menuNameA)
889 cs->hMenu = HIWORD(classPtr->menuNameA) ?
890 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
891 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
893 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
896 if (HIWORD(cs->hInstance))
897 cs->hMenu = LoadMenuA(cs->hInstance,PTR_SEG_TO_LIN(menuName));
899 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
901 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
906 else wndPtr->wIDmenu = (UINT)cs->hMenu;
908 /* Send the WM_CREATE message
909 * Perhaps we shouldn't allow width/height changes as well.
910 * See p327 in "Internals".
913 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
915 localSend32 = unicode ? SendMessageW : SendMessageA;
916 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
918 /* Insert the window in the linked list */
920 WIN_LinkWindow( hwnd, hwndLinkAfter );
922 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
923 NULL, NULL, 0, &wndPtr->rectClient );
924 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
925 maxPos.y - wndPtr->rectWindow.top);
926 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
928 /* Send the size messages */
930 if (!(wndPtr->flags & WIN_NEED_SIZE))
933 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
934 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
935 WARN("sending bogus WM_SIZE message 0x%08lx\n",
936 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
937 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
938 SendMessageA( hwnd, WM_SIZE, SIZE_RESTORED,
939 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
940 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
941 SendMessageA( hwnd, WM_MOVE, 0,
942 MAKELONG( wndPtr->rectClient.left,
943 wndPtr->rectClient.top ) );
946 /* Show the window, maximizing or minimizing if needed */
948 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
951 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
952 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
953 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
954 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
955 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
956 : SWP_NOZORDER | SWP_FRAMECHANGED;
957 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
958 newPos.right, newPos.bottom, swFlag );
961 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
963 /* Notify the parent window only */
965 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
966 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
967 if( !IsWindow(hwnd) )
974 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, sw );
976 /* Call WH_SHELL hook */
978 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
979 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
981 TRACE("created window %04x\n", hwnd);
985 WIN_UnlinkWindow( hwnd );
988 /* Abort window creation */
990 WARN("aborted by WM_xxCREATE!\n");
991 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
994 WIN_ReleaseWndPtr(wndPtr);
1000 /***********************************************************************
1001 * CreateWindow16 (USER.41)
1003 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1004 DWORD style, INT16 x, INT16 y, INT16 width,
1005 INT16 height, HWND16 parent, HMENU16 menu,
1006 HINSTANCE16 instance, LPVOID data )
1008 return CreateWindowEx16( 0, className, windowName, style,
1009 x, y, width, height, parent, menu, instance, data );
1013 /***********************************************************************
1014 * CreateWindowEx16 (USER.452)
1016 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1017 LPCSTR windowName, DWORD style, INT16 x,
1018 INT16 y, INT16 width, INT16 height,
1019 HWND16 parent, HMENU16 menu,
1020 HINSTANCE16 instance, LPVOID data )
1026 /* Find the class atom */
1028 if (HIWORD(className))
1030 if (!(classAtom = GlobalFindAtomA( className )))
1032 ERR( "bad class name %s\n", debugres_a(className) );
1038 classAtom = LOWORD(className);
1039 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1041 ERR( "bad atom %x\n", classAtom);
1047 /* Fix the coordinates */
1049 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1050 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1051 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1052 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1054 /* Create the window */
1056 cs.lpCreateParams = data;
1057 cs.hInstance = (HINSTANCE)instance;
1058 cs.hMenu = (HMENU)menu;
1059 cs.hwndParent = (HWND)parent;
1061 cs.lpszName = windowName;
1062 cs.lpszClass = className;
1063 cs.dwExStyle = exStyle;
1065 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
1069 /***********************************************************************
1070 * CreateWindowExA (USER32.83)
1072 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1073 LPCSTR windowName, DWORD style, INT x,
1074 INT y, INT width, INT height,
1075 HWND parent, HMENU menu,
1076 HINSTANCE instance, LPVOID data )
1083 instance=GetModuleHandleA(NULL);
1085 if(exStyle & WS_EX_MDICHILD)
1086 return MDI_CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1088 /* Find the class atom */
1090 if (HIWORD(className))
1092 if (!(classAtom = GlobalFindAtomA( className )))
1094 ERR( "bad class name %s\n", debugres_a(className) );
1100 classAtom = LOWORD(className);
1101 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1103 ERR( "bad atom %x\n", classAtom);
1109 /* Create the window */
1111 cs.lpCreateParams = data;
1112 cs.hInstance = instance;
1114 cs.hwndParent = parent;
1120 cs.lpszName = windowName;
1121 cs.lpszClass = className;
1122 cs.dwExStyle = exStyle;
1124 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
1128 /***********************************************************************
1129 * CreateWindowExW (USER32.84)
1131 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1132 LPCWSTR windowName, DWORD style, INT x,
1133 INT y, INT width, INT height,
1134 HWND parent, HMENU menu,
1135 HINSTANCE instance, LPVOID data )
1142 instance=GetModuleHandleA(NULL);
1144 if(exStyle & WS_EX_MDICHILD)
1145 return MDI_CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1147 /* Find the class atom */
1149 if (HIWORD(className))
1151 if (!(classAtom = GlobalFindAtomW( className )))
1153 ERR( "bad class name %s\n", debugres_w(className) );
1159 classAtom = LOWORD(className);
1160 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1162 ERR( "bad atom %x\n", classAtom);
1168 /* Create the window */
1170 cs.lpCreateParams = data;
1171 cs.hInstance = instance;
1173 cs.hwndParent = parent;
1179 cs.lpszName = windowName;
1180 cs.lpszClass = className;
1181 cs.dwExStyle = exStyle;
1183 /* Note: we rely on the fact that CREATESTRUCTA and */
1184 /* CREATESTRUCTW have the same layout. */
1185 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, TRUE, TRUE );
1189 /***********************************************************************
1192 static void WIN_CheckFocus( WND* pWnd )
1194 if( GetFocus16() == pWnd->hwndSelf )
1195 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
1198 /***********************************************************************
1199 * WIN_SendDestroyMsg
1201 static void WIN_SendDestroyMsg( WND* pWnd )
1203 WIN_CheckFocus(pWnd);
1205 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1206 CLIPBOARD_Driver->pResetOwner( pWnd, TRUE );
1209 * Send the WM_DESTROY to the window.
1211 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1214 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1215 * make sure that the window still exists when we come back.
1217 if (IsWindow(pWnd->hwndSelf))
1219 HWND* pWndArray = NULL;
1224 * Now, if the window has kids, we have to send WM_DESTROY messages
1225 * recursively to it's kids. It seems that those calls can also
1226 * trigger re-entrant calls to DestroyWindow for the kids so we must
1227 * protect against corruption of the list of siblings. We first build
1228 * a list of HWNDs representing all the kids.
1230 pChild = WIN_LockWndPtr(pWnd->child);
1234 WIN_UpdateWndPtr(&pChild,pChild->next);
1238 * If there are no kids, we're done.
1243 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1248 if (pWndArray==NULL)
1252 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1253 * call, our linked list of siblings should be safe.
1256 pChild = WIN_LockWndPtr(pWnd->child);
1259 pWndArray[nKidCount] = pChild->hwndSelf;
1261 WIN_UpdateWndPtr(&pChild,pChild->next);
1265 * Now that we have a list, go through that list again and send the destroy
1266 * message to those windows. We are using the HWND to retrieve the
1267 * WND pointer so we are effectively checking that all the kid windows are
1268 * still valid before sending the message.
1272 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1276 WIN_SendDestroyMsg( pChild );
1277 WIN_ReleaseWndPtr(pChild);
1284 HeapFree(GetProcessHeap(), 0, pWndArray);
1285 WIN_CheckFocus(pWnd);
1288 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1292 /***********************************************************************
1293 * DestroyWindow16 (USER.53)
1295 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1297 return DestroyWindow(hwnd);
1301 /***********************************************************************
1302 * DestroyWindow (USER32.135)
1304 BOOL WINAPI DestroyWindow( HWND hwnd )
1309 TRACE("(%04x)\n", hwnd);
1311 /* Initialization */
1313 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1314 if (wndPtr == pWndDesktop)
1316 retvalue = FALSE; /* Can't destroy desktop */
1322 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1328 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1330 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1331 /* FIXME: clean up palette - see "Internals" p.352 */
1334 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1335 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1337 /* Notify the parent window only */
1338 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1339 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1340 if( !IsWindow(hwnd) )
1347 CLIPBOARD_Driver->pResetOwner( wndPtr, FALSE ); /* before the window is unmapped */
1349 /* Hide the window */
1351 if (wndPtr->dwStyle & WS_VISIBLE)
1353 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1354 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1355 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1356 if (!IsWindow(hwnd))
1363 /* Recursively destroy owned windows */
1365 if( !(wndPtr->dwStyle & WS_CHILD) )
1367 /* make sure top menu popup doesn't get destroyed */
1368 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1372 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1375 if (siblingPtr->owner == wndPtr)
1377 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1380 siblingPtr->owner = NULL;
1382 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1386 DestroyWindow( siblingPtr->hwndSelf );
1387 WIN_ReleaseWndPtr(siblingPtr);
1392 if( !Options.managed || EVENT_CheckFocus() )
1393 WINPOS_ActivateOtherWindow(wndPtr);
1395 if( wndPtr->owner &&
1396 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1397 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1400 /* Send destroy messages */
1402 WIN_SendDestroyMsg( wndPtr );
1403 if (!IsWindow(hwnd))
1409 /* Unlink now so we won't bother with the children later on */
1411 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1413 /* Destroy the window storage */
1415 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1418 WIN_ReleaseWndPtr(wndPtr);
1423 /***********************************************************************
1424 * CloseWindow16 (USER.43)
1426 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1428 return CloseWindow( hwnd );
1432 /***********************************************************************
1433 * CloseWindow (USER32.56)
1435 BOOL WINAPI CloseWindow( HWND hwnd )
1437 WND * wndPtr = WIN_FindWndPtr( hwnd );
1440 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1445 ShowWindow( hwnd, SW_MINIMIZE );
1448 WIN_ReleaseWndPtr(wndPtr);
1454 /***********************************************************************
1455 * OpenIcon16 (USER.44)
1457 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1459 return OpenIcon( hwnd );
1463 /***********************************************************************
1464 * OpenIcon (USER32.410)
1466 BOOL WINAPI OpenIcon( HWND hwnd )
1468 if (!IsIconic( hwnd )) return FALSE;
1469 ShowWindow( hwnd, SW_SHOWNORMAL );
1474 /***********************************************************************
1477 * Implementation of FindWindow() and FindWindowEx().
1479 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1487 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1490 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1496 else if (pWnd->parent != pWndDesktop)
1501 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1505 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1510 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1518 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1520 if (className && (pWnd->class->atomName != className))
1521 continue; /* Not the right class */
1523 /* Now check the title */
1527 retvalue = pWnd->hwndSelf;
1530 if (pWnd->text && !strcmp( pWnd->text, title ))
1532 retvalue = pWnd->hwndSelf;
1538 WIN_ReleaseWndPtr(pWnd);
1544 /***********************************************************************
1545 * FindWindow16 (USER.50)
1547 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1549 return FindWindowA( className, title );
1553 /***********************************************************************
1554 * FindWindowEx16 (USER.427)
1556 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1558 return FindWindowExA( parent, child, className, title );
1562 /***********************************************************************
1563 * FindWindowA (USER32.198)
1565 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1567 HWND ret = FindWindowExA( 0, 0, className, title );
1568 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1573 /***********************************************************************
1574 * FindWindowExA (USER32.199)
1576 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1577 LPCSTR className, LPCSTR title )
1583 /* If the atom doesn't exist, then no class */
1584 /* with this name exists either. */
1585 if (!(atom = GlobalFindAtomA( className )))
1587 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1591 return WIN_FindWindow( parent, child, atom, title );
1595 /***********************************************************************
1596 * FindWindowExW (USER32.200)
1598 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1599 LPCWSTR className, LPCWSTR title )
1607 /* If the atom doesn't exist, then no class */
1608 /* with this name exists either. */
1609 if (!(atom = GlobalFindAtomW( className )))
1611 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1615 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1616 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1617 HeapFree( GetProcessHeap(), 0, buffer );
1622 /***********************************************************************
1623 * FindWindowW (USER32.201)
1625 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1627 return FindWindowExW( 0, 0, className, title );
1631 /**********************************************************************
1633 * returns a locked pointer
1635 WND *WIN_GetDesktop(void)
1637 return WIN_LockWndPtr(pWndDesktop);
1639 /**********************************************************************
1640 * WIN_ReleaseDesktop
1641 * unlock the desktop pointer
1643 void WIN_ReleaseDesktop(void)
1645 WIN_ReleaseWndPtr(pWndDesktop);
1649 /**********************************************************************
1650 * GetDesktopWindow16 (USER.286)
1652 HWND16 WINAPI GetDesktopWindow16(void)
1654 return (HWND16)pWndDesktop->hwndSelf;
1658 /**********************************************************************
1659 * GetDesktopWindow (USER32.232)
1661 HWND WINAPI GetDesktopWindow(void)
1663 if (pWndDesktop) return pWndDesktop->hwndSelf;
1664 ERR( "You need the -desktop option when running with native USER\n" );
1670 /**********************************************************************
1671 * GetDesktopHwnd (USER.278)
1673 * Exactly the same thing as GetDesktopWindow(), but not documented.
1674 * Don't ask me why...
1676 HWND16 WINAPI GetDesktopHwnd16(void)
1678 return (HWND16)pWndDesktop->hwndSelf;
1682 /*******************************************************************
1683 * EnableWindow16 (USER.34)
1685 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1687 return EnableWindow( hwnd, enable );
1691 /*******************************************************************
1692 * EnableWindow (USER32.172)
1694 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1699 TRACE("EnableWindow32: ( %x, %d )\n", hwnd, enable);
1701 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1702 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1705 wndPtr->dwStyle &= ~WS_DISABLED;
1707 if( wndPtr->flags & WIN_NATIVE )
1708 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
1710 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1714 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1716 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1718 /* Disable window */
1719 wndPtr->dwStyle |= WS_DISABLED;
1721 if( wndPtr->flags & WIN_NATIVE )
1722 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
1724 if (hwnd == GetFocus())
1726 SetFocus( 0 ); /* A disabled window can't have the focus */
1728 if (hwnd == GetCapture())
1730 ReleaseCapture(); /* A disabled window can't capture the mouse */
1732 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1736 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1738 WIN_ReleaseWndPtr(wndPtr);
1743 /***********************************************************************
1744 * IsWindowEnabled16 (USER.35)
1746 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1748 return IsWindowEnabled(hWnd);
1752 /***********************************************************************
1753 * IsWindowEnabled (USER32.349)
1755 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1760 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1761 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1762 WIN_ReleaseWndPtr(wndPtr);
1768 /***********************************************************************
1769 * IsWindowUnicode (USER32.350)
1771 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1776 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1777 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1778 WIN_ReleaseWndPtr(wndPtr);
1783 /**********************************************************************
1784 * GetWindowWord16 (USER.133)
1786 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1788 return GetWindowWord( hwnd, offset );
1792 /**********************************************************************
1793 * GetWindowWord (USER32.314)
1795 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1798 WND * wndPtr = WIN_FindWndPtr( hwnd );
1799 if (!wndPtr) return 0;
1802 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1804 WARN("Invalid offset %d\n", offset );
1808 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1814 if (HIWORD(wndPtr->wIDmenu))
1815 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1817 retvalue = (WORD)wndPtr->wIDmenu;
1819 case GWW_HWNDPARENT:
1820 retvalue = GetParent(hwnd);
1823 if (HIWORD(wndPtr->hInstance))
1824 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1826 retvalue = (WORD)wndPtr->hInstance;
1829 WARN("Invalid offset %d\n", offset );
1834 WIN_ReleaseWndPtr(wndPtr);
1838 /**********************************************************************
1839 * SetWindowWord16 (USER.134)
1841 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1843 return SetWindowWord( hwnd, offset, newval );
1847 /**********************************************************************
1848 * SetWindowWord (USER32.524)
1850 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1853 WND * wndPtr = WIN_FindWndPtr( hwnd );
1854 if (!wndPtr) return 0;
1857 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1859 WARN("Invalid offset %d\n", offset );
1863 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1867 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1868 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1869 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1872 WARN("Invalid offset %d\n", offset );
1879 WIN_ReleaseWndPtr(wndPtr);
1884 /**********************************************************************
1887 * Helper function for GetWindowLong().
1889 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1892 WND * wndPtr = WIN_FindWndPtr( hwnd );
1893 if (!wndPtr) return 0;
1896 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1898 WARN("Invalid offset %d\n", offset );
1902 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1903 /* Special case for dialog window procedure */
1904 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1906 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1913 case GWL_USERDATA: retvalue = wndPtr->userdata;
1915 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1917 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1919 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1921 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1924 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1926 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1929 WARN("Unknown offset %d\n", offset );
1933 WIN_ReleaseWndPtr(wndPtr);
1938 /**********************************************************************
1941 * Helper function for SetWindowLong().
1943 * 0 is the failure code. However, in the case of failure SetLastError
1944 * must be set to distinguish between a 0 return value and a failure.
1946 * FIXME: The error values for SetLastError may not be right. Can
1947 * someone check with the real thing?
1949 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1950 WINDOWPROCTYPE type )
1953 WND * wndPtr = WIN_FindWndPtr( hwnd );
1956 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1960 /* Is this the right error? */
1961 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1967 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1969 WARN("Invalid offset %d\n", offset );
1971 /* Is this the right error? */
1972 SetLastError( ERROR_OUTOFMEMORY );
1977 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1978 /* Special case for dialog window procedure */
1979 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1981 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1982 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1983 type, WIN_PROC_WINDOW );
1990 ptr = (DWORD*)&wndPtr->wIDmenu;
1993 retval = SetWindowWord( hwnd, offset, newval );
1996 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1997 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1998 type, WIN_PROC_WINDOW );
2001 style.styleOld = wndPtr->dwStyle;
2002 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
2003 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
2005 if (wndPtr->flags & WIN_ISWIN32)
2006 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
2007 wndPtr->dwStyle = style.styleNew;
2008 if (wndPtr->flags & WIN_ISWIN32)
2009 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
2010 retval = style.styleOld;
2014 ptr = &wndPtr->userdata;
2017 style.styleOld = wndPtr->dwExStyle;
2018 style.styleNew = newval;
2019 if (wndPtr->flags & WIN_ISWIN32)
2020 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
2021 wndPtr->dwExStyle = newval;
2022 if (wndPtr->flags & WIN_ISWIN32)
2023 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
2024 retval = style.styleOld;
2028 WARN("Invalid offset %d\n", offset );
2030 /* Don't think this is right error but it should do */
2031 SetLastError( ERROR_OUTOFMEMORY );
2039 WIN_ReleaseWndPtr(wndPtr);
2044 /**********************************************************************
2045 * GetWindowLong16 (USER.135)
2047 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2049 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2053 /**********************************************************************
2054 * GetWindowLongA (USER32.305)
2056 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2058 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2062 /**********************************************************************
2063 * GetWindowLongW (USER32.306)
2065 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2067 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2071 /**********************************************************************
2072 * SetWindowLong16 (USER.136)
2074 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2076 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2080 /**********************************************************************
2081 * SetWindowLongA (USER32.517)
2083 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2085 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2089 /**********************************************************************
2090 * SetWindowLongW (USER32.518) Set window attribute
2092 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2093 * value in a window's extra memory.
2095 * The _hwnd_ parameter specifies the window. is the handle to a
2096 * window that has extra memory. The _newval_ parameter contains the
2097 * new attribute or extra memory value. If positive, the _offset_
2098 * parameter is the byte-addressed location in the window's extra
2099 * memory to set. If negative, _offset_ specifies the window
2100 * attribute to set, and should be one of the following values:
2102 * GWL_EXSTYLE The window's extended window style
2104 * GWL_STYLE The window's window style.
2106 * GWL_WNDPROC Pointer to the window's window procedure.
2108 * GWL_HINSTANCE The window's pplication instance handle.
2110 * GWL_ID The window's identifier.
2112 * GWL_USERDATA The window's user-specified data.
2114 * If the window is a dialog box, the _offset_ parameter can be one of
2115 * the following values:
2117 * DWL_DLGPROC The address of the window's dialog box procedure.
2119 * DWL_MSGRESULT The return value of a message
2120 * that the dialog box procedure processed.
2122 * DWL_USER Application specific information.
2126 * If successful, returns the previous value located at _offset_. Otherwise,
2131 * Extra memory for a window class is specified by a nonzero cbWndExtra
2132 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2133 * time of class creation.
2135 * Using GWL_WNDPROC to set a new window procedure effectively creates
2136 * a window subclass. Use CallWindowProc() in the new windows procedure
2137 * to pass messages to the superclass's window procedure.
2139 * The user data is reserved for use by the application which created
2142 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2143 * instead, call the EnableWindow() function to change the window's
2146 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2147 * SetParent() instead.
2150 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2151 * it sends WM_STYLECHANGING before changing the settings
2152 * and WM_STYLECHANGED afterwards.
2153 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2157 * GWL_STYLE does not dispatch WM_STYLE... messages.
2164 LONG WINAPI SetWindowLongW(
2165 HWND hwnd, /* window to alter */
2166 INT offset, /* offset, in bytes, of location to alter */
2167 LONG newval /* new value of location */
2169 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2173 /*******************************************************************
2174 * GetWindowText16 (USER.36)
2176 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2178 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2182 /*******************************************************************
2183 * GetWindowTextA (USER32.309)
2185 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2187 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2191 /*******************************************************************
2192 * InternalGetWindowText (USER32.326)
2194 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2196 FIXME("(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2197 return GetWindowTextW(hwnd,lpString,nMaxCount);
2201 /*******************************************************************
2202 * GetWindowTextW (USER32.312)
2204 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2206 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2211 /*******************************************************************
2212 * SetWindowText16 (USER.37)
2214 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2216 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2220 /*******************************************************************
2221 * SetWindowTextA (USER32.521)
2223 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2225 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2229 /*******************************************************************
2230 * SetWindowTextW (USER32.523)
2232 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2234 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2238 /*******************************************************************
2239 * GetWindowTextLength16 (USER.38)
2241 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2243 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2247 /*******************************************************************
2248 * GetWindowTextLengthA (USER32.310)
2250 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2252 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2255 /*******************************************************************
2256 * GetWindowTextLengthW (USER32.311)
2258 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2260 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2264 /*******************************************************************
2265 * IsWindow16 (USER.47)
2267 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2269 CURRENT_STACK16->es = USER_HeapSel;
2270 return IsWindow( hwnd );
2274 /*******************************************************************
2275 * IsWindow (USER32.348)
2277 BOOL WINAPI IsWindow( HWND hwnd )
2282 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2283 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2284 WIN_ReleaseWndPtr(wndPtr);
2290 /*****************************************************************
2291 * GetParent16 (USER.46)
2293 HWND16 WINAPI GetParent16( HWND16 hwnd )
2295 return (HWND16)GetParent( hwnd );
2299 /*****************************************************************
2300 * GetParent (USER32.278)
2302 HWND WINAPI GetParent( HWND hwnd )
2307 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2308 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2311 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2313 retvalue = wndPtr->hwndSelf;
2316 WIN_ReleaseWndPtr(wndPtr);
2321 /*****************************************************************
2324 * Get the top-level parent for a child window.
2325 * returns a locked pointer
2327 WND* WIN_GetTopParentPtr( WND* pWnd )
2329 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2331 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2333 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2338 /*****************************************************************
2341 * Get the top-level parent for a child window.
2343 HWND WIN_GetTopParent( HWND hwnd )
2346 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2347 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2349 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2350 WIN_ReleaseWndPtr(tmpPtr);
2351 WIN_ReleaseWndPtr(wndPtr);
2356 /*****************************************************************
2357 * SetParent16 (USER.233)
2359 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2361 return SetParent( hwndChild, hwndNewParent );
2365 /*****************************************************************
2366 * SetParent (USER32.495)
2368 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2377 if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
2379 dwStyle = wndPtr->dwStyle;
2381 pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
2382 : WIN_LockWndPtr(pWndDesktop);
2384 /* Windows hides the window first, then shows it again
2385 * including the WM_SHOWWINDOW messages and all */
2386 if (dwStyle & WS_VISIBLE)
2387 ShowWindow( hwndChild, SW_HIDE );
2389 pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
2391 /* SetParent additionally needs to make hwndChild the topmost window
2392 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2393 WM_WINDOWPOSCHANGED notification messages.
2395 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2396 SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2397 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2398 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2400 retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
2402 WIN_ReleaseWndPtr(pWndOldParent);
2403 WIN_ReleaseWndPtr(pWndNewParent);
2404 WIN_ReleaseWndPtr(wndPtr);
2410 /*******************************************************************
2411 * IsChild16 (USER.48)
2413 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2415 return IsChild(parent,child);
2419 /*******************************************************************
2420 * IsChild (USER32.339)
2422 BOOL WINAPI IsChild( HWND parent, HWND child )
2424 WND * wndPtr = WIN_FindWndPtr( child );
2425 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2427 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2428 if (wndPtr->hwndSelf == parent)
2430 WIN_ReleaseWndPtr(wndPtr);
2434 WIN_ReleaseWndPtr(wndPtr);
2439 /***********************************************************************
2440 * IsWindowVisible16 (USER.49)
2442 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2444 return IsWindowVisible(hwnd);
2448 /***********************************************************************
2449 * IsWindowVisible (USER32.351)
2451 BOOL WINAPI IsWindowVisible( HWND hwnd )
2454 WND *wndPtr = WIN_FindWndPtr( hwnd );
2455 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2457 if (!(wndPtr->dwStyle & WS_VISIBLE))
2459 WIN_ReleaseWndPtr(wndPtr);
2462 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2464 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2465 WIN_ReleaseWndPtr(wndPtr);
2471 /***********************************************************************
2472 * WIN_IsWindowDrawable
2474 * hwnd is drawable when it is visible, all parents are not
2475 * minimized, and it is itself not minimized unless we are
2476 * trying to draw its default class icon.
2478 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2480 if( (wnd->dwStyle & WS_MINIMIZE &&
2481 icon && wnd->class->hIcon) ||
2482 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2483 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2484 if( wnd->dwStyle & WS_MINIMIZE ||
2485 !(wnd->dwStyle & WS_VISIBLE) ) break;
2486 return (wnd == NULL);
2490 /*******************************************************************
2491 * GetTopWindow16 (USER.229)
2493 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2495 return GetTopWindow(hwnd);
2499 /*******************************************************************
2500 * GetTopWindow (USER.229)
2502 HWND WINAPI GetTopWindow( HWND hwnd )
2505 WND * wndPtr = (hwnd) ?
2506 WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
2508 if (wndPtr && wndPtr->child)
2509 retval = wndPtr->child->hwndSelf;
2511 WIN_ReleaseWndPtr(wndPtr);
2516 /*******************************************************************
2517 * GetWindow16 (USER.262)
2519 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2521 return GetWindow( hwnd,rel );
2525 /*******************************************************************
2526 * GetWindow (USER32.302)
2528 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2532 WND * wndPtr = WIN_FindWndPtr( hwnd );
2533 if (!wndPtr) return 0;
2537 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2541 if (!wndPtr->parent)
2543 retval = 0; /* Desktop window */
2546 while (wndPtr->next)
2548 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2550 retval = wndPtr->hwndSelf;
2554 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2558 if (!wndPtr->parent)
2560 retval = 0; /* Desktop window */
2563 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2564 if (wndPtr->hwndSelf == hwnd)
2566 retval = 0; /* First in list */
2569 while (wndPtr->next)
2571 if (wndPtr->next->hwndSelf == hwnd)
2573 retval = wndPtr->hwndSelf;
2576 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2582 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2586 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2591 WIN_ReleaseWndPtr(wndPtr);
2596 /*******************************************************************
2597 * GetNextWindow16 (USER.230)
2599 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2601 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2602 return GetWindow16( hwnd, flag );
2605 /*******************************************************************
2606 * ShowOwnedPopups16 (USER.265)
2608 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2610 ShowOwnedPopups( owner, fShow );
2614 /*******************************************************************
2615 * ShowOwnedPopups (USER32.531)
2617 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2619 UINT totalChild=0, count=0;
2621 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2623 if (!pWnd) return TRUE;
2625 for (; count < totalChild; count++)
2627 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2631 if (pWnd[count]->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2633 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_SHOW, IsIconic(owner) ? SW_PARENTOPENING : SW_PARENTCLOSING);
2634 pWnd[count]->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2639 if (IsWindowVisible(pWnd[count]->hwndSelf))
2641 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_HIDE, IsIconic(owner) ? SW_PARENTOPENING : SW_PARENTCLOSING);
2642 pWnd[count]->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2648 WIN_ReleaseDesktop();
2649 WIN_ReleaseWinArray(pWnd);
2654 /*******************************************************************
2655 * GetLastActivePopup16 (USER.287)
2657 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2659 return GetLastActivePopup( hwnd );
2662 /*******************************************************************
2663 * GetLastActivePopup (USER32.256)
2665 HWND WINAPI GetLastActivePopup( HWND hwnd )
2668 WND *wndPtr =WIN_FindWndPtr(hwnd);
2669 if (!wndPtr) return hwnd;
2670 retval = wndPtr->hwndLastActive;
2671 WIN_ReleaseWndPtr(wndPtr);
2676 /*******************************************************************
2679 * Build an array of pointers to the children of a given window.
2680 * The array must be freed with WIN_ReleaseWinArray. Return NULL
2681 * when no windows are found.
2683 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2685 /* Future: this function will lock all windows associated with this array */
2687 WND **list, **ppWnd;
2689 UINT count = 0, skipOwned, skipHidden;
2692 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2693 skipOwned = bwaFlags & BWA_SKIPOWNED;
2694 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2695 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2697 /* First count the windows */
2700 wndPtr = WIN_GetDesktop();
2702 pWnd = WIN_LockWndPtr(wndPtr->child);
2705 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2706 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2708 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2713 /* Now build the list of all windows */
2715 if ((list = (WND **)HeapAlloc( GetProcessHeap(), 0, sizeof(WND *) * (count + 1))))
2717 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2719 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2720 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2726 WIN_ReleaseWndPtr(pWnd);
2732 if( pTotal ) *pTotal = count;
2735 /*******************************************************************
2736 * WIN_ReleaseWinArray
2738 void WIN_ReleaseWinArray(WND **wndArray)
2740 /* Future: this function will also unlock all windows associated with wndArray */
2741 HeapFree( GetProcessHeap(), 0, wndArray );
2745 /*******************************************************************
2746 * EnumWindows (USER32.193)
2748 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2750 WND **list, **ppWnd;
2752 /* We have to build a list of all windows first, to avoid */
2753 /* unpleasant side-effects, for instance if the callback */
2754 /* function changes the Z-order of the windows. */
2756 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2758 WIN_ReleaseDesktop();
2762 /* Now call the callback function for every window */
2764 for (ppWnd = list; *ppWnd; ppWnd++)
2766 LRESULT lpEnumFuncRetval;
2768 /* Make sure that the window still exists */
2769 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2771 /* To avoid any deadlocks, all the locks on the windows
2772 structures must be suspended before the control
2773 is passed to the application */
2774 iWndsLocks = WIN_SuspendWndsLock();
2775 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2776 WIN_RestoreWndsLock(iWndsLocks);
2778 if (!lpEnumFuncRetval) break;
2780 WIN_ReleaseWinArray(list);
2781 WIN_ReleaseDesktop();
2786 /**********************************************************************
2787 * EnumTaskWindows16 (USER.225)
2789 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2792 WND **list, **ppWnd;
2794 /* This function is the same as EnumWindows(), */
2795 /* except for an added check on the window's task. */
2797 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2799 WIN_ReleaseDesktop();
2803 /* Now call the callback function for every window */
2805 for (ppWnd = list; *ppWnd; ppWnd++)
2809 /* Make sure that the window still exists */
2810 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2811 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2813 /* To avoid any deadlocks, all the locks on the windows
2814 structures must be suspended before the control
2815 is passed to the application */
2816 iWndsLocks = WIN_SuspendWndsLock();
2817 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2818 WIN_RestoreWndsLock(iWndsLocks);
2820 if (!funcRetval) break;
2822 WIN_ReleaseWinArray(list);
2823 WIN_ReleaseDesktop();
2828 /**********************************************************************
2829 * EnumThreadWindows (USER32.190)
2831 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2833 TEB *teb = THREAD_IdToTEB(id);
2835 return (BOOL16)EnumTaskWindows16(teb->htask16, (WNDENUMPROC16)func, lParam);
2839 /**********************************************************************
2840 * WIN_EnumChildWindows
2842 * Helper function for EnumChildWindows().
2844 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC func, LPARAM lParam )
2849 for ( ; *ppWnd; ppWnd++)
2853 /* Make sure that the window still exists */
2854 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2855 /* Build children list first */
2856 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2858 /* To avoid any deadlocks, all the locks on the windows
2859 structures must be suspended before the control
2860 is passed to the application */
2861 iWndsLocks = WIN_SuspendWndsLock();
2862 ret = func( (*ppWnd)->hwndSelf, lParam );
2863 WIN_RestoreWndsLock(iWndsLocks);
2867 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2868 WIN_ReleaseWinArray(childList);
2870 if (!ret) return FALSE;
2876 /**********************************************************************
2877 * EnumChildWindows (USER32.178)
2879 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2882 WND **list, *pParent;
2884 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2885 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2887 WIN_ReleaseWndPtr(pParent);
2890 WIN_EnumChildWindows( list, func, lParam );
2891 WIN_ReleaseWinArray(list);
2892 WIN_ReleaseWndPtr(pParent);
2897 /*******************************************************************
2898 * AnyPopup16 (USER.52)
2900 BOOL16 WINAPI AnyPopup16(void)
2906 /*******************************************************************
2907 * AnyPopup (USER32.4)
2909 BOOL WINAPI AnyPopup(void)
2911 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2916 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2921 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2925 WIN_ReleaseWndPtr(wndPtr);
2930 /*******************************************************************
2931 * FlashWindow16 (USER.105)
2933 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2935 return FlashWindow( hWnd, bInvert );
2939 /*******************************************************************
2940 * FlashWindow (USER32.202)
2942 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2944 WND *wndPtr = WIN_FindWndPtr(hWnd);
2946 TRACE("%04x\n", hWnd);
2948 if (!wndPtr) return FALSE;
2950 if (wndPtr->dwStyle & WS_MINIMIZE)
2952 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2954 HDC hDC = GetDC(hWnd);
2956 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2957 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2959 ReleaseDC( hWnd, hDC );
2960 wndPtr->flags |= WIN_NCACTIVATED;
2964 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2965 RDW_UPDATENOW | RDW_FRAME, 0 );
2966 wndPtr->flags &= ~WIN_NCACTIVATED;
2968 WIN_ReleaseWndPtr(wndPtr);
2974 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2975 else wparam = (hWnd == GetActiveWindow());
2977 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2978 WIN_ReleaseWndPtr(wndPtr);
2984 /*******************************************************************
2985 * SetSysModalWindow16 (USER.188)
2987 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
2989 HWND hWndOldModal = hwndSysModal;
2990 hwndSysModal = hWnd;
2991 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2992 return hWndOldModal;
2996 /*******************************************************************
2997 * GetSysModalWindow16 (USER.52)
2999 HWND16 WINAPI GetSysModalWindow16(void)
3001 return hwndSysModal;
3005 /*******************************************************************
3006 * GetWindowContextHelpId (USER32.303)
3008 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3011 WND *wnd = WIN_FindWndPtr( hwnd );
3013 retval = wnd->helpContext;
3014 WIN_ReleaseWndPtr(wnd);
3019 /*******************************************************************
3020 * SetWindowContextHelpId (USER32.515)
3022 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3024 WND *wnd = WIN_FindWndPtr( hwnd );
3025 if (!wnd) return FALSE;
3026 wnd->helpContext = id;
3027 WIN_ReleaseWndPtr(wnd);
3032 /*******************************************************************
3035 * recursively find a child that contains spDragInfo->pt point
3036 * and send WM_QUERYDROPOBJECT
3038 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3040 BOOL16 wParam, bResult = 0;
3042 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
3043 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3046 if( !ptrQueryWnd || !ptrDragInfo )
3049 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3051 GetWindowRect(hQueryWnd,&tempRect);
3053 if( !PtInRect(&tempRect,pt) ||
3054 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3057 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3059 tempRect = ptrQueryWnd->rectClient;
3060 if(ptrQueryWnd->dwStyle & WS_CHILD)
3061 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3062 (LPPOINT)&tempRect, 2 );
3064 if (PtInRect( &tempRect, pt))
3068 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3070 if( ptrWnd->dwStyle & WS_VISIBLE )
3072 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3073 if (PtInRect( &tempRect, pt )) break;
3079 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3080 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3081 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3082 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3083 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3085 WIN_ReleaseWndPtr(ptrWnd);
3095 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3097 ptrDragInfo->hScope = hQueryWnd;
3099 bResult = ( bNoSend )
3100 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3101 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3102 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3104 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3107 WIN_ReleaseWndPtr(ptrQueryWnd);
3112 /*******************************************************************
3113 * DragDetect (USER.465)
3115 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3118 CONV_POINT16TO32( &pt, &pt32 );
3119 return DragDetect( hWnd, pt32 );
3122 /*******************************************************************
3123 * DragDetect (USER32.151)
3125 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3130 rect.left = pt.x - wDragWidth;
3131 rect.right = pt.x + wDragWidth;
3133 rect.top = pt.y - wDragHeight;
3134 rect.bottom = pt.y + wDragHeight;
3140 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3142 if( msg.message == WM_LBUTTONUP )
3147 if( msg.message == WM_MOUSEMOVE )
3149 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
3161 /******************************************************************************
3162 * DragObject16 (USER.464)
3164 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3165 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3168 LPDRAGINFO lpDragInfo;
3170 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3171 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
3172 WND *wndPtr = WIN_FindWndPtr(hWnd);
3173 HCURSOR16 hCurrentCursor = 0;
3174 HWND16 hCurrentWnd = 0;
3176 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
3177 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
3179 if( !lpDragInfo || !spDragInfo )
3181 WIN_ReleaseWndPtr(wndPtr);
3185 hBummer = LoadCursor16(0, IDC_BUMMER16);
3187 if( !hBummer || !wndPtr )
3189 GlobalFree16(hDragInfo);
3190 WIN_ReleaseWndPtr(wndPtr);
3196 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3198 GlobalFree16(hDragInfo);
3199 WIN_ReleaseWndPtr(wndPtr);
3203 if( hDragCursor == hCursor ) hDragCursor = 0;
3204 else hCursor = hDragCursor;
3206 hOldCursor = SetCursor(hDragCursor);
3209 lpDragInfo->hWnd = hWnd;
3210 lpDragInfo->hScope = 0;
3211 lpDragInfo->wFlags = wObj;
3212 lpDragInfo->hList = szList; /* near pointer! */
3213 lpDragInfo->hOfStruct = hOfStruct;
3221 do{ WaitMessage(); }
3222 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3224 *(lpDragInfo+1) = *lpDragInfo;
3226 lpDragInfo->pt = msg.pt;
3228 /* update DRAGINFO struct */
3229 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3231 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3232 hCurrentCursor = hCursor;
3235 hCurrentCursor = hBummer;
3236 lpDragInfo->hScope = 0;
3238 if( hCurrentCursor )
3239 SetCursor(hCurrentCursor);
3241 /* send WM_DRAGLOOP */
3242 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3243 (LPARAM) spDragInfo );
3244 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3245 if( hCurrentWnd != lpDragInfo->hScope )
3248 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3249 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
3250 HIWORD(spDragInfo)) );
3251 hCurrentWnd = lpDragInfo->hScope;
3253 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3257 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3259 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3262 ShowCursor( FALSE );
3266 SetCursor( hOldCursor );
3267 if (hDragCursor) DestroyCursor( hDragCursor );
3270 if( hCurrentCursor != hBummer )
3271 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3272 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3275 GlobalFree16(hDragInfo);
3276 WIN_ReleaseWndPtr(wndPtr);
3278 return (DWORD)(msg.lParam);