2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
11 #include "wine/winbase16.h"
18 #include "sysmetrics.h"
19 #include "cursoricon.h"
23 #include "nonclient.h"
26 #include "shm_main_blk.h"
28 #include "clipboard.h"
39 #ifndef X_DISPLAY_MISSING
40 extern DESKTOP_DRIVER X11DRV_DESKTOP_Driver;
41 extern WND_DRIVER X11DRV_WND_Driver;
42 #else /* X_DISPLAY_MISSING */
43 extern DESKTOP_DRIVER TTYDRV_DESKTOP_Driver;
44 extern WND_DRIVER TTYDRV_WND_Driver;
45 #endif /* X_DISPLAY_MISSING */
48 static WND *pWndDesktop = NULL;
50 static HWND hwndSysModal = 0;
52 static WORD wDragWidth = 4;
53 static WORD wDragHeight= 3;
56 static CRITICAL_SECTION WIN_CritSection;
57 static int ilockCounter = 0;
59 /***********************************************************************
62 * Locks access to all WND structures for thread safeness
67 EnterCriticalSection(&WIN_CritSection);
71 /***********************************************************************
74 * Unlocks access to all WND structures
79 LeaveCriticalSection(&WIN_CritSection);
82 /***********************************************************************
85 * Suspend the lock on WND structures.
86 * Returns the number of locks suspended
88 int WIN_SuspendWndsLock()
91 int isuspendedLocks = WIN_CritSection.RecursionCount;
92 WIN_CritSection.RecursionCount = 0;
93 LeaveCriticalSection(&WIN_CritSection);
94 return isuspendedLocks;
98 /***********************************************************************
101 * Restore the suspended locks on WND structures
103 void WIN_RestoreWndslock(int ipreviousLocks)
106 EnterCriticalSection(&WIN_CritSection);
107 WIN_CritSection.RecursionCount = ipreviousLocks;
110 /***********************************************************************
113 * Return a pointer to the WND structure corresponding to a HWND.
115 WND * WIN_FindWndPtr( HWND hwnd )
119 if (!hwnd || HIWORD(hwnd)) goto error2;
120 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
121 /* Lock all WND structures for thread safeness
123 and increment destruction monitoring
126 if (ptr->dwMagic != WND_MAGIC) goto error;
127 if (ptr->hwndSelf != hwnd)
129 ERR( win, "Can't happen: hwnd %04x self pointer is %04x\n",
130 hwnd, ptr->hwndSelf );
135 /* Unlock all WND structures for thread safeness
137 and decrement destruction monitoring value
142 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
146 /***********************************************************************
149 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
151 * Returns the locked initialisation pointer
153 WND *WIN_LockWndPtr(WND *initWndPtr)
156 if(!initWndPtr) return 0;
159 initWndPtr->irefCount++;
165 /***********************************************************************
168 * Release the pointer to the WND structure.
170 void WIN_ReleaseWndPtr(WND *wndPtr)
174 /*Decrement destruction monitoring value
176 Check if it's time to release the memory
177 if(wndPtr->irefCount == 0)
179 Add memory releasing code here
181 unlock all WND structures for thread safeness
186 /***********************************************************************
189 * Updates the value of oldPtr to newPtr.
191 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
195 tmpWnd = WIN_LockWndPtr(newPtr);
196 WIN_ReleaseWndPtr(*oldPtr);
201 /***********************************************************************
204 * Dump the content of a window structure to stderr.
206 void WIN_DumpWindow( HWND hwnd )
212 if (!(ptr = WIN_FindWndPtr( hwnd )))
214 WARN( win, "%04x is not a window handle\n", hwnd );
218 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
219 strcpy( className, "#NULL#" );
221 TRACE( win, "Window %04x (%p):\n", hwnd, ptr );
222 DUMP( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
223 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
224 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
225 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
226 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
227 ptr->next, ptr->child, ptr->parent, ptr->owner,
228 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
229 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
230 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
231 ptr->text ? ptr->text : "",
232 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
233 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
234 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
235 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
237 if (ptr->class->cbWndExtra)
239 DUMP( "extra bytes:" );
240 for (i = 0; i < ptr->class->cbWndExtra; i++)
241 DUMP( " %02x", *((BYTE*)ptr->wExtra+i) );
245 WIN_ReleaseWndPtr(ptr);
249 /***********************************************************************
252 * Walk the windows tree and print each window on stderr.
254 void WIN_WalkWindows( HWND hwnd, int indent )
259 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
263 WARN( win, "Invalid window handle %04x\n", hwnd );
267 if (!indent) /* first time around */
268 DUMP( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
269 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
274 DUMP( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
276 GlobalGetAtomName16(ptr->class->atomName,className,sizeof(className));
278 DUMP( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
279 (DWORD)ptr, ptr->hmemTaskQ, className,
280 (UINT)ptr->dwStyle, (UINT)ptr->winproc,
281 ptr->text?ptr->text:"<null>");
283 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
284 WIN_UpdateWndPtr(&ptr,ptr->next);
290 /***********************************************************************
293 * Remove a window from the siblings linked list.
295 BOOL WIN_UnlinkWindow( HWND hwnd )
297 WND *wndPtr, **ppWnd;
299 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
300 else if(!wndPtr->parent)
302 WIN_ReleaseWndPtr(wndPtr);
305 ppWnd = &wndPtr->parent->child;
306 while (*ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
307 *ppWnd = wndPtr->next;
308 WIN_ReleaseWndPtr(wndPtr);
313 /***********************************************************************
316 * Insert a window into the siblings linked list.
317 * The window is inserted after the specified window, which can also
318 * be specified as HWND_TOP or HWND_BOTTOM.
320 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
322 WND *wndPtr, **ppWnd;
324 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
325 else if(!wndPtr->parent)
327 WIN_ReleaseWndPtr(wndPtr);
330 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
332 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
333 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
334 while (*ppWnd) ppWnd = &(*ppWnd)->next;
336 else /* Normal case */
338 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
341 WIN_ReleaseWndPtr(wndPtr);
344 ppWnd = &afterPtr->next;
345 WIN_ReleaseWndPtr(afterPtr);
347 wndPtr->next = *ppWnd;
349 WIN_ReleaseWndPtr(wndPtr);
354 /***********************************************************************
355 * WIN_FindWinToRepaint
357 * Find a window that needs repaint.
359 HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE16 hQueue )
364 /* Note: the desktop window never gets WM_PAINT messages
365 * The real reason why is because Windows DesktopWndProc
366 * does ValidateRgn inside WM_ERASEBKGND handler.
369 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
371 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
373 if (!(pWnd->dwStyle & WS_VISIBLE))
375 TRACE(win, "skipping window %04x\n",
378 else if ((pWnd->hmemTaskQ == hQueue) &&
379 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))) break;
381 else if (pWnd->child )
382 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
392 hwndRet = pWnd->hwndSelf;
394 /* look among siblings if we got a transparent window */
395 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
396 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
398 WIN_UpdateWndPtr(&pWnd,pWnd->next);
400 if (pWnd) hwndRet = pWnd->hwndSelf;
401 TRACE(win,"found %04x\n",hwndRet);
403 WIN_ReleaseWndPtr(pWnd);
408 /***********************************************************************
411 * Destroy storage associated to a window. "Internals" p.358
412 * returns a locked wndPtr->next
414 static WND* WIN_DestroyWindow( WND* wndPtr )
416 HWND hwnd = wndPtr->hwndSelf;
419 TRACE(win, "%04x\n", wndPtr->hwndSelf );
423 DDE_DestroyWindow(wndPtr->hwndSelf);
424 #endif /* CONFIG_IPC */
426 /* free child windows */
427 WIN_LockWndPtr(wndPtr->child);
428 while ((pWnd = wndPtr->child))
430 wndPtr->child = WIN_DestroyWindow( pWnd );
431 WIN_ReleaseWndPtr(pWnd);
435 * Clear the update region to make sure no WM_PAINT messages will be
436 * generated for this window while processing the WM_NCDESTROY.
438 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
440 if (wndPtr->hrgnUpdate > 1)
441 DeleteObject( wndPtr->hrgnUpdate );
443 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
445 wndPtr->hrgnUpdate = 0;
449 * Send the WM_NCDESTROY to the window being destroyed.
451 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
453 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
455 WINPOS_CheckInternalPos( wndPtr );
456 if( hwnd == GetCapture()) ReleaseCapture();
458 /* free resources associated with the window */
460 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
461 PROPERTY_RemoveWindowProps( wndPtr );
463 wndPtr->dwMagic = 0; /* Mark it as invalid */
465 /* toss stale messages from the queue */
467 if( wndPtr->hmemTaskQ )
469 BOOL bPostQuit = FALSE;
470 WPARAM wQuitParam = 0;
471 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) QUEUE_Lock(wndPtr->hmemTaskQ);
474 while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
476 if( qmsg->msg.message == WM_QUIT )
479 wQuitParam = qmsg->msg.wParam;
481 QUEUE_RemoveMsg(msgQ, qmsg);
486 /* repost WM_QUIT to make sure this app exits its message loop */
487 if( bPostQuit ) PostQuitMessage(wQuitParam);
488 wndPtr->hmemTaskQ = 0;
491 if (!(wndPtr->dwStyle & WS_CHILD))
492 if (wndPtr->wIDmenu) DestroyMenu( (HMENU)wndPtr->wIDmenu );
493 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
494 wndPtr->pDriver->pDestroyWindow( wndPtr );
495 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
496 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
497 wndPtr->hwndSelf = 0;
498 wndPtr->class->cWindows--;
499 wndPtr->class = NULL;
501 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
503 wndPtr->pDriver->pFinalize(wndPtr);
504 USER_HEAP_FREE( hwnd );
508 /***********************************************************************
509 * WIN_ResetQueueWindows
511 * Reset the queue of all the children of a given window.
512 * Return TRUE if something was done.
514 BOOL WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
518 if (hNew) /* Set a new queue */
520 for (wnd = WIN_LockWndPtr(wnd->child); (wnd);WIN_UpdateWndPtr(&wnd,wnd->next))
522 if (wnd->hmemTaskQ == hQueue)
524 wnd->hmemTaskQ = hNew;
529 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
533 else /* Queue is being destroyed */
537 WND *tmp = WIN_LockWndPtr(wnd->child);
542 if (tmp->hmemTaskQ == hQueue)
544 DestroyWindow( tmp->hwndSelf );
548 tmp2 = WIN_LockWndPtr(tmp->child);
549 if (tmp2 && WIN_ResetQueueWindows(tmp2,hQueue,0))
553 WIN_UpdateWndPtr(&tmp,tmp->next);
555 WIN_ReleaseWndPtr(tmp2);
557 WIN_ReleaseWndPtr(tmp);
564 /***********************************************************************
565 * WIN_CreateDesktopWindow
567 * Create the desktop window.
569 BOOL WIN_CreateDesktopWindow(void)
575 TRACE(win,"Creating desktop window\n");
577 if (!ICONTITLE_Init() ||
578 !WINPOS_CreateInternalPosAtom() ||
579 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
582 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
583 if (!hwndDesktop) return FALSE;
584 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
586 pDesktop = (DESKTOP *) pWndDesktop->wExtra;
587 #ifndef X_DISPLAY_MISSING
588 pDesktop->pDriver = &X11DRV_DESKTOP_Driver;
589 pWndDesktop->pDriver = &X11DRV_WND_Driver;
590 #else /* X_DISPLAY_MISSING */
591 pDesktop->pDriver = &TTYDRV_DESKTOP_Driver;
592 pWndDesktop->pDriver = &TTYDRV_WND_Driver;
593 #endif /* X_DISPLAY_MISSING */
595 pDesktop->pDriver->pInitialize(pDesktop);
596 pWndDesktop->pDriver->pInitialize(pWndDesktop);
598 pWndDesktop->next = NULL;
599 pWndDesktop->child = NULL;
600 pWndDesktop->parent = NULL;
601 pWndDesktop->owner = NULL;
602 pWndDesktop->class = class;
603 pWndDesktop->dwMagic = WND_MAGIC;
604 pWndDesktop->hwndSelf = hwndDesktop;
605 pWndDesktop->hInstance = 0;
606 pWndDesktop->rectWindow.left = 0;
607 pWndDesktop->rectWindow.top = 0;
608 pWndDesktop->rectWindow.right = SYSMETRICS_CXSCREEN;
609 pWndDesktop->rectWindow.bottom = SYSMETRICS_CYSCREEN;
610 pWndDesktop->rectClient = pWndDesktop->rectWindow;
611 pWndDesktop->text = NULL;
612 pWndDesktop->hmemTaskQ = GetFastQueue16();
613 pWndDesktop->hrgnUpdate = 0;
614 pWndDesktop->hwndLastActive = hwndDesktop;
615 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
617 pWndDesktop->dwExStyle = 0;
618 pWndDesktop->dce = NULL;
619 pWndDesktop->pVScroll = NULL;
620 pWndDesktop->pHScroll = NULL;
621 pWndDesktop->pProp = NULL;
622 pWndDesktop->wIDmenu = 0;
623 pWndDesktop->helpContext = 0;
624 pWndDesktop->flags = 0;
625 pWndDesktop->hSysMenu = 0;
626 pWndDesktop->userdata = 0;
627 pWndDesktop->winproc = (WNDPROC16)class->winproc;
628 pWndDesktop->irefCount = 0;
630 /* FIXME: How do we know if it should be Unicode or not */
631 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop, class, FALSE))
634 SendMessageA( hwndDesktop, WM_NCCREATE, 0, 0 );
636 /* Initialisation of the critical section for thread safeness
637 InitializeCriticalSection(&WIN_CritSection);
638 MakeCriticalSectionGlobal(&WIN_CritSection);
640 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
645 /***********************************************************************
648 * Implementation of CreateWindowEx().
650 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
651 BOOL win32, BOOL unicode )
656 HWND16 hwnd, hwndLinkAfter;
657 POINT maxSize, maxPos, minTrack, maxTrack;
658 LRESULT (CALLBACK *localSend32)(HWND, UINT, WPARAM, LPARAM);
660 TRACE(win, "%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
661 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
662 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
663 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
664 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
666 /* Find the parent window */
670 /* Make sure parent is valid */
671 if (!IsWindow( cs->hwndParent ))
673 WARN( win, "Bad parent %04x\n", cs->hwndParent );
676 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
677 WARN( win, "No parent for child window\n" );
678 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
681 /* Find the window class */
682 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
685 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
686 WARN( win, "Bad class '%s'\n", buffer );
690 /* Fix the coordinates */
692 if (cs->x == CW_USEDEFAULT)
694 PDB *pdb = PROCESS_Current();
695 if ( !(cs->style & (WS_CHILD | WS_POPUP))
696 && (pdb->env_db->startup_info->dwFlags & STARTF_USEPOSITION) )
698 cs->x = pdb->env_db->startup_info->dwX;
699 cs->y = pdb->env_db->startup_info->dwY;
707 if (cs->cx == CW_USEDEFAULT)
709 PDB *pdb = PROCESS_Current();
710 if ( !(cs->style & (WS_CHILD | WS_POPUP))
711 && (pdb->env_db->startup_info->dwFlags & STARTF_USESIZE) )
713 cs->cx = pdb->env_db->startup_info->dwXSize;
714 cs->cy = pdb->env_db->startup_info->dwYSize;
718 cs->cx = 600; /* FIXME */
723 /* Create the window structure */
725 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
726 - sizeof(wndPtr->wExtra) )))
728 TRACE(win, "out of memory\n" );
732 /* Fill the window structure */
734 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
736 wndPtr->child = NULL;
738 if ((cs->style & WS_CHILD) && cs->hwndParent)
740 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
741 wndPtr->owner = NULL;
742 WIN_ReleaseWndPtr(wndPtr->parent);
746 wndPtr->parent = pWndDesktop;
747 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
748 wndPtr->owner = NULL;
751 wndPtr->owner = WIN_GetTopParentPtr(WIN_FindWndPtr(cs->hwndParent));
752 WIN_ReleaseWndPtr(wndPtr->owner);
756 wndPtr->pDriver = wndPtr->parent->pDriver;
757 wndPtr->pDriver->pInitialize(wndPtr);
759 wndPtr->class = classPtr;
760 wndPtr->winproc = classPtr->winproc;
761 wndPtr->dwMagic = WND_MAGIC;
762 wndPtr->hwndSelf = hwnd;
763 wndPtr->hInstance = cs->hInstance;
765 wndPtr->hmemTaskQ = GetFastQueue16();
766 wndPtr->hrgnUpdate = 0;
767 wndPtr->hwndLastActive = hwnd;
768 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
769 wndPtr->dwExStyle = cs->dwExStyle;
771 wndPtr->helpContext = 0;
772 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
773 wndPtr->pVScroll = NULL;
774 wndPtr->pHScroll = NULL;
775 wndPtr->pProp = NULL;
776 wndPtr->userdata = 0;
777 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
778 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
780 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
782 /* Call the WH_CBT hook */
784 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
785 ? HWND_BOTTOM : HWND_TOP;
787 if (HOOK_IsHooked( WH_CBT ))
793 cbtc.hwndInsertAfter = hwndLinkAfter;
794 ret = unicode ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
795 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
798 TRACE(win, "CBT-hook returned 0\n");
799 wndPtr->pDriver->pFinalize(wndPtr);
800 USER_HEAP_FREE( hwnd );
806 /* Increment class window counter */
808 classPtr->cWindows++;
810 /* Correct the window style */
812 if (!(cs->style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
814 wndPtr->dwStyle |= WS_CAPTION | WS_CLIPSIBLINGS;
815 wndPtr->flags |= WIN_NEED_SIZE;
817 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
819 /* Get class or window DC if needed */
821 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
822 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
823 else wndPtr->dce = NULL;
825 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
827 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
829 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
830 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
831 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
832 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
833 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
836 if(cs->style & WS_CHILD)
838 if(cs->cx < 0) cs->cx = 0;
839 if(cs->cy < 0) cs->cy = 0;
843 if (cs->cx <= 0) cs->cx = 1;
844 if (cs->cy <= 0) cs->cy = 1;
847 wndPtr->rectWindow.left = cs->x;
848 wndPtr->rectWindow.top = cs->y;
849 wndPtr->rectWindow.right = cs->x + cs->cx;
850 wndPtr->rectWindow.bottom = cs->y + cs->cy;
851 wndPtr->rectClient = wndPtr->rectWindow;
853 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
859 /* Set the window menu */
861 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
863 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
866 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
867 if (classPtr->menuNameA)
868 cs->hMenu = HIWORD(classPtr->menuNameA) ?
869 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
870 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
872 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
875 if (HIWORD(cs->hInstance))
876 cs->hMenu = LoadMenuA(cs->hInstance,PTR_SEG_TO_LIN(menuName));
878 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
880 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
885 else wndPtr->wIDmenu = (UINT)cs->hMenu;
887 /* Send the WM_CREATE message
888 * Perhaps we shouldn't allow width/height changes as well.
889 * See p327 in "Internals".
892 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
894 localSend32 = unicode ? SendMessageW : SendMessageA;
895 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
897 /* Insert the window in the linked list */
899 WIN_LinkWindow( hwnd, hwndLinkAfter );
901 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
902 NULL, NULL, 0, &wndPtr->rectClient );
903 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
904 maxPos.y - wndPtr->rectWindow.top);
905 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
907 /* Send the size messages */
909 if (!(wndPtr->flags & WIN_NEED_SIZE))
912 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
913 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
914 WARN(win,"sending bogus WM_SIZE message 0x%08lx\n",
915 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
916 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
917 SendMessageA( hwnd, WM_SIZE, SIZE_RESTORED,
918 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
919 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
920 SendMessageA( hwnd, WM_MOVE, 0,
921 MAKELONG( wndPtr->rectClient.left,
922 wndPtr->rectClient.top ) );
925 /* Show the window, maximizing or minimizing if needed */
927 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
930 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
931 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
932 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
933 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
934 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
935 : SWP_NOZORDER | SWP_FRAMECHANGED;
936 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
937 newPos.right, newPos.bottom, swFlag );
940 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
942 /* Notify the parent window only */
944 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
945 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
946 if( !IsWindow(hwnd) )
953 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
955 /* Call WH_SHELL hook */
957 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
958 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
960 TRACE(win, "created window %04x\n", hwnd);
964 WIN_UnlinkWindow( hwnd );
967 /* Abort window creation */
969 WARN(win, "aborted by WM_xxCREATE!\n");
970 WIN_DestroyWindow( wndPtr );
973 WIN_ReleaseWndPtr(wndPtr);
978 /***********************************************************************
979 * CreateWindow16 (USER.41)
981 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
982 DWORD style, INT16 x, INT16 y, INT16 width,
983 INT16 height, HWND16 parent, HMENU16 menu,
984 HINSTANCE16 instance, LPVOID data )
986 return CreateWindowEx16( 0, className, windowName, style,
987 x, y, width, height, parent, menu, instance, data );
991 /***********************************************************************
992 * CreateWindowEx16 (USER.452)
994 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
995 LPCSTR windowName, DWORD style, INT16 x,
996 INT16 y, INT16 width, INT16 height,
997 HWND16 parent, HMENU16 menu,
998 HINSTANCE16 instance, LPVOID data )
1003 /* Find the class atom */
1005 if (!(classAtom = GlobalFindAtomA( className )))
1007 fprintf( stderr, "CreateWindowEx16: bad class name " );
1008 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
1009 else fprintf( stderr, "'%s'\n", className );
1013 /* Fix the coordinates */
1015 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1016 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1017 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1018 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1020 /* Create the window */
1022 cs.lpCreateParams = data;
1023 cs.hInstance = (HINSTANCE)instance;
1024 cs.hMenu = (HMENU)menu;
1025 cs.hwndParent = (HWND)parent;
1027 cs.lpszName = windowName;
1028 cs.lpszClass = className;
1029 cs.dwExStyle = exStyle;
1030 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
1034 /***********************************************************************
1035 * CreateWindowEx32A (USER32.83)
1037 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1038 LPCSTR windowName, DWORD style, INT x,
1039 INT y, INT width, INT height,
1040 HWND parent, HMENU menu,
1041 HINSTANCE instance, LPVOID data )
1046 if(exStyle & WS_EX_MDICHILD)
1047 return MDI_CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1048 /* Find the class atom */
1050 if (!(classAtom = GlobalFindAtomA( className )))
1052 fprintf( stderr, "CreateWindowEx32A: bad class name " );
1053 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
1054 else fprintf( stderr, "'%s'\n", className );
1058 /* Create the window */
1060 cs.lpCreateParams = data;
1061 cs.hInstance = instance;
1063 cs.hwndParent = parent;
1069 cs.lpszName = windowName;
1070 cs.lpszClass = className;
1071 cs.dwExStyle = exStyle;
1072 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
1076 /***********************************************************************
1077 * CreateWindowEx32W (USER32.84)
1079 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1080 LPCWSTR windowName, DWORD style, INT x,
1081 INT y, INT width, INT height,
1082 HWND parent, HMENU menu,
1083 HINSTANCE instance, LPVOID data )
1088 if(exStyle & WS_EX_MDICHILD)
1089 return MDI_CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1091 /* Find the class atom */
1093 if (!(classAtom = GlobalFindAtomW( className )))
1095 if (HIWORD(className))
1097 LPSTR cn = HEAP_strdupWtoA( GetProcessHeap(), 0, className );
1098 WARN( win, "Bad class name '%s'\n",cn);
1099 HeapFree( GetProcessHeap(), 0, cn );
1102 WARN( win, "Bad class name %p\n", className );
1106 /* Create the window */
1108 cs.lpCreateParams = data;
1109 cs.hInstance = instance;
1111 cs.hwndParent = parent;
1117 cs.lpszName = windowName;
1118 cs.lpszClass = className;
1119 cs.dwExStyle = exStyle;
1120 /* Note: we rely on the fact that CREATESTRUCT32A and */
1121 /* CREATESTRUCT32W have the same layout. */
1122 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, TRUE, TRUE );
1126 /***********************************************************************
1129 static void WIN_CheckFocus( WND* pWnd )
1131 if( GetFocus16() == pWnd->hwndSelf )
1132 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
1135 /***********************************************************************
1136 * WIN_SendDestroyMsg
1138 static void WIN_SendDestroyMsg( WND* pWnd )
1140 WIN_CheckFocus(pWnd);
1142 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1143 CLIPBOARD_GetDriver()->pResetOwner( pWnd, TRUE );
1146 * Send the WM_DESTROY to the window.
1148 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1151 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1152 * make sure that the window still exists when we come back.
1154 if (IsWindow(pWnd->hwndSelf))
1156 HWND* pWndArray = NULL;
1161 * Now, if the window has kids, we have to send WM_DESTROY messages
1162 * recursively to it's kids. It seems that those calls can also
1163 * trigger re-entrant calls to DestroyWindow for the kids so we must
1164 * protect against corruption of the list of siblings. We first build
1165 * a list of HWNDs representing all the kids.
1167 pChild = WIN_LockWndPtr(pWnd->child);
1171 WIN_UpdateWndPtr(&pChild,pChild->next);
1175 * If there are no kids, we're done.
1180 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1185 if (pWndArray==NULL)
1189 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1190 * call, our linked list of siblings should be safe.
1193 pChild = WIN_LockWndPtr(pWnd->child);
1196 pWndArray[nKidCount] = pChild->hwndSelf;
1198 WIN_UpdateWndPtr(&pChild,pChild->next);
1202 * Now that we have a list, go through that list again and send the destroy
1203 * message to those windows. We are using the HWND to retrieve the
1204 * WND pointer so we are effectively checking that all the kid windows are
1205 * still valid before sending the message.
1209 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1213 WIN_SendDestroyMsg( pChild );
1214 WIN_ReleaseWndPtr(pChild);
1221 HeapFree(GetProcessHeap(), 0, pWndArray);
1222 WIN_CheckFocus(pWnd);
1225 WARN(win, "\tdestroyed itself while in WM_DESTROY!\n");
1229 /***********************************************************************
1230 * DestroyWindow16 (USER.53)
1232 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1234 return DestroyWindow(hwnd);
1238 /***********************************************************************
1239 * DestroyWindow32 (USER32.135)
1241 BOOL WINAPI DestroyWindow( HWND hwnd )
1246 TRACE(win, "(%04x)\n", hwnd);
1248 /* Initialization */
1250 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1251 if (wndPtr == pWndDesktop)
1253 WIN_ReleaseWndPtr(wndPtr);
1254 return FALSE; /* Can't destroy desktop */
1259 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1265 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1267 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1268 /* FIXME: clean up palette - see "Internals" p.352 */
1271 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1272 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1274 /* Notify the parent window only */
1275 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1276 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1277 if( !IsWindow(hwnd) )
1284 CLIPBOARD_GetDriver()->pResetOwner( wndPtr, FALSE ); /* before the window is unmapped */
1286 /* Hide the window */
1288 if (wndPtr->dwStyle & WS_VISIBLE)
1290 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1291 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1292 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1293 if (!IsWindow(hwnd))
1300 /* Recursively destroy owned windows */
1302 if( !(wndPtr->dwStyle & WS_CHILD) )
1304 /* make sure top menu popup doesn't get destroyed */
1305 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1309 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1312 if (siblingPtr->owner == wndPtr)
1314 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1317 siblingPtr->owner = NULL;
1319 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1321 if (siblingPtr) DestroyWindow( siblingPtr->hwndSelf );
1325 if( !Options.managed || EVENT_CheckFocus() )
1326 WINPOS_ActivateOtherWindow(wndPtr);
1328 if( wndPtr->owner &&
1329 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1330 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1333 /* Send destroy messages */
1335 WIN_SendDestroyMsg( wndPtr );
1336 if (!IsWindow(hwnd))
1342 /* Unlink now so we won't bother with the children later on */
1344 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1346 /* Destroy the window storage */
1348 WIN_DestroyWindow( wndPtr );
1351 WIN_ReleaseWndPtr(wndPtr);
1356 /***********************************************************************
1357 * CloseWindow16 (USER.43)
1359 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1361 return CloseWindow( hwnd );
1365 /***********************************************************************
1366 * CloseWindow32 (USER32.56)
1368 BOOL WINAPI CloseWindow( HWND hwnd )
1370 WND * wndPtr = WIN_FindWndPtr( hwnd );
1373 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1378 ShowWindow( hwnd, SW_MINIMIZE );
1381 WIN_ReleaseWndPtr(wndPtr);
1387 /***********************************************************************
1388 * OpenIcon16 (USER.44)
1390 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1392 return OpenIcon( hwnd );
1396 /***********************************************************************
1397 * OpenIcon32 (USER32.410)
1399 BOOL WINAPI OpenIcon( HWND hwnd )
1401 if (!IsIconic( hwnd )) return FALSE;
1402 ShowWindow( hwnd, SW_SHOWNORMAL );
1407 /***********************************************************************
1410 * Implementation of FindWindow() and FindWindowEx().
1412 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1417 CLASS *pClass = NULL;
1421 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1424 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1430 else if (pWnd->parent != pWndDesktop)
1435 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1439 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1444 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1452 /* For a child window, all siblings will have the same hInstance, */
1453 /* so we can look for the class once and for all. */
1455 if (className && (pWnd->dwStyle & WS_CHILD))
1457 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1465 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1467 if (className && !(pWnd->dwStyle & WS_CHILD))
1469 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance)))
1470 continue; /* Skip this window */
1473 if (pClass && (pWnd->class != pClass))
1474 continue; /* Not the right class */
1476 /* Now check the title */
1480 retvalue = pWnd->hwndSelf;
1483 if (pWnd->text && !strcmp( pWnd->text, title ))
1485 retvalue = pWnd->hwndSelf;
1491 WIN_ReleaseWndPtr(pWnd);
1497 /***********************************************************************
1498 * FindWindow16 (USER.50)
1500 HWND16 WINAPI FindWindow16( SEGPTR className, LPCSTR title )
1502 return FindWindowEx16( 0, 0, className, title );
1506 /***********************************************************************
1507 * FindWindowEx16 (USER.427)
1509 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child,
1510 SEGPTR className, LPCSTR title )
1514 TRACE(win, "%04x %04x '%s' '%s'\n", parent,
1515 child, HIWORD(className)?(char *)PTR_SEG_TO_LIN(className):"",
1516 title ? title : "");
1520 /* If the atom doesn't exist, then no class */
1521 /* with this name exists either. */
1522 if (!(atom = GlobalFindAtom16( className ))) return 0;
1524 return WIN_FindWindow( parent, child, atom, title );
1528 /***********************************************************************
1529 * FindWindow32A (USER32.198)
1531 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1533 HWND ret = FindWindowExA( 0, 0, className, title );
1534 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1539 /***********************************************************************
1540 * FindWindowEx32A (USER32.199)
1542 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1543 LPCSTR className, LPCSTR title )
1549 /* If the atom doesn't exist, then no class */
1550 /* with this name exists either. */
1551 if (!(atom = GlobalFindAtomA( className )))
1553 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1557 return WIN_FindWindow( parent, child, atom, title );
1561 /***********************************************************************
1562 * FindWindowEx32W (USER32.200)
1564 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1565 LPCWSTR className, LPCWSTR title )
1573 /* If the atom doesn't exist, then no class */
1574 /* with this name exists either. */
1575 if (!(atom = GlobalFindAtomW( className )))
1577 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1581 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1582 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1583 HeapFree( GetProcessHeap(), 0, buffer );
1588 /***********************************************************************
1589 * FindWindow32W (USER32.201)
1591 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1593 return FindWindowExW( 0, 0, className, title );
1597 /**********************************************************************
1599 * returns a locked pointer
1601 WND *WIN_GetDesktop(void)
1603 return WIN_LockWndPtr(pWndDesktop);
1605 /**********************************************************************
1606 * WIN_ReleaseDesktop
1607 * unlock the desktop pointer
1609 void WIN_ReleaseDesktop(void)
1611 WIN_ReleaseWndPtr(pWndDesktop);
1615 /**********************************************************************
1616 * GetDesktopWindow16 (USER.286)
1618 HWND16 WINAPI GetDesktopWindow16(void)
1620 return (HWND16)pWndDesktop->hwndSelf;
1624 /**********************************************************************
1625 * GetDesktopWindow32 (USER32.232)
1627 HWND WINAPI GetDesktopWindow(void)
1629 return pWndDesktop->hwndSelf;
1633 /**********************************************************************
1634 * GetDesktopHwnd (USER.278)
1636 * Exactly the same thing as GetDesktopWindow(), but not documented.
1637 * Don't ask me why...
1639 HWND16 WINAPI GetDesktopHwnd16(void)
1641 return (HWND16)pWndDesktop->hwndSelf;
1645 /*******************************************************************
1646 * EnableWindow16 (USER.34)
1648 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1650 return EnableWindow( hwnd, enable );
1654 /*******************************************************************
1655 * EnableWindow32 (USER32.172)
1657 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1662 TRACE(win,"EnableWindow32: ( %x, %d )\n", hwnd, enable);
1664 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1665 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1668 wndPtr->dwStyle &= ~WS_DISABLED;
1669 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1673 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1675 /* Disable window */
1676 wndPtr->dwStyle |= WS_DISABLED;
1677 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus() ))
1679 SetFocus( 0 ); /* A disabled window can't have the focus */
1681 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
1683 ReleaseCapture(); /* A disabled window can't capture the mouse */
1685 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1689 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1691 WIN_ReleaseWndPtr(wndPtr);
1696 /***********************************************************************
1697 * IsWindowEnabled16 (USER.35)
1699 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1701 return IsWindowEnabled(hWnd);
1705 /***********************************************************************
1706 * IsWindowEnabled32 (USER32.349)
1708 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1713 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1714 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1715 WIN_ReleaseWndPtr(wndPtr);
1721 /***********************************************************************
1722 * IsWindowUnicode (USER32.350)
1724 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1729 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1730 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1731 WIN_ReleaseWndPtr(wndPtr);
1736 /**********************************************************************
1737 * GetWindowWord16 (USER.133)
1739 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1741 return GetWindowWord( hwnd, offset );
1745 /**********************************************************************
1746 * GetWindowWord32 (USER32.314)
1748 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1751 WND * wndPtr = WIN_FindWndPtr( hwnd );
1752 if (!wndPtr) return 0;
1755 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1757 WARN( win, "Invalid offset %d\n", offset );
1761 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1767 if (HIWORD(wndPtr->wIDmenu))
1768 WARN( win,"GWW_ID: discards high bits of 0x%08x!\n",
1770 retvalue = (WORD)wndPtr->wIDmenu;
1772 case GWW_HWNDPARENT:
1773 retvalue = GetParent(hwnd);
1776 if (HIWORD(wndPtr->hInstance))
1777 WARN(win,"GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1779 retvalue = (WORD)wndPtr->hInstance;
1782 WARN( win, "Invalid offset %d\n", offset );
1787 WIN_ReleaseWndPtr(wndPtr);
1792 /**********************************************************************
1793 * WIN_GetWindowInstance
1795 HINSTANCE WIN_GetWindowInstance( HWND hwnd )
1798 WND * wndPtr = WIN_FindWndPtr( hwnd );
1799 if (!wndPtr) return (HINSTANCE)0;
1800 WIN_ReleaseWndPtr(wndPtr);
1801 return wndPtr->hInstance;
1806 /**********************************************************************
1807 * SetWindowWord16 (USER.134)
1809 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1811 return SetWindowWord( hwnd, offset, newval );
1815 /**********************************************************************
1816 * SetWindowWord32 (USER32.524)
1818 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1821 WND * wndPtr = WIN_FindWndPtr( hwnd );
1822 if (!wndPtr) return 0;
1825 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1827 WARN( win, "Invalid offset %d\n", offset );
1831 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1835 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1836 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1837 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1840 WARN( win, "Invalid offset %d\n", offset );
1847 WIN_ReleaseWndPtr(wndPtr);
1852 /**********************************************************************
1855 * Helper function for GetWindowLong().
1857 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1860 WND * wndPtr = WIN_FindWndPtr( hwnd );
1861 if (!wndPtr) return 0;
1864 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1866 WARN( win, "Invalid offset %d\n", offset );
1870 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1871 /* Special case for dialog window procedure */
1872 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1874 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1881 case GWL_USERDATA: retvalue = wndPtr->userdata;
1883 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1885 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1887 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1889 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1892 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1894 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1897 WARN( win, "Unknown offset %d\n", offset );
1901 WIN_ReleaseWndPtr(wndPtr);
1906 /**********************************************************************
1909 * Helper function for SetWindowLong().
1911 * 0 is the failure code. However, in the case of failure SetLastError
1912 * must be set to distinguish between a 0 return value and a failure.
1914 * FIXME: The error values for SetLastError may not be right. Can
1915 * someone check with the real thing?
1917 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1918 WINDOWPROCTYPE type )
1921 WND * wndPtr = WIN_FindWndPtr( hwnd );
1924 TRACE(win,"%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1928 /* Is this the right error? */
1929 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1935 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1937 WARN( win, "Invalid offset %d\n", offset );
1939 /* Is this the right error? */
1940 SetLastError( ERROR_OUTOFMEMORY );
1945 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1946 /* Special case for dialog window procedure */
1947 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1949 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1950 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1951 type, WIN_PROC_WINDOW );
1958 ptr = (DWORD*)&wndPtr->wIDmenu;
1961 retval = SetWindowWord( hwnd, offset, newval );
1964 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1965 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1966 type, WIN_PROC_WINDOW );
1969 style.styleOld = wndPtr->dwStyle;
1970 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
1971 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
1973 if (wndPtr->flags & WIN_ISWIN32)
1974 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1975 wndPtr->dwStyle = style.styleNew;
1976 if (wndPtr->flags & WIN_ISWIN32)
1977 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1978 retval = style.styleOld;
1982 ptr = &wndPtr->userdata;
1985 style.styleOld = wndPtr->dwExStyle;
1986 style.styleNew = newval;
1987 if (wndPtr->flags & WIN_ISWIN32)
1988 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1989 wndPtr->dwExStyle = newval;
1990 if (wndPtr->flags & WIN_ISWIN32)
1991 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1992 retval = style.styleOld;
1996 WARN( win, "Invalid offset %d\n", offset );
1998 /* Don't think this is right error but it should do */
1999 SetLastError( ERROR_OUTOFMEMORY );
2007 WIN_ReleaseWndPtr(wndPtr);
2012 /**********************************************************************
2013 * GetWindowLong16 (USER.135)
2015 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2017 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2021 /**********************************************************************
2022 * GetWindowLong32A (USER32.305)
2024 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2026 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2030 /**********************************************************************
2031 * GetWindowLong32W (USER32.306)
2033 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2035 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2039 /**********************************************************************
2040 * SetWindowLong16 (USER.136)
2042 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2044 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2048 /**********************************************************************
2049 * SetWindowLong32A (USER32.517)
2051 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2053 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2057 /**********************************************************************
2058 * SetWindowLong32W (USER32.518) Set window attribute
2060 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2061 * value in a window's extra memory.
2063 * The _hwnd_ parameter specifies the window. is the handle to a
2064 * window that has extra memory. The _newval_ parameter contains the
2065 * new attribute or extra memory value. If positive, the _offset_
2066 * parameter is the byte-addressed location in the window's extra
2067 * memory to set. If negative, _offset_ specifies the window
2068 * attribute to set, and should be one of the following values:
2070 * GWL_EXSTYLE The window's extended window style
2072 * GWL_STYLE The window's window style.
2074 * GWL_WNDPROC Pointer to the window's window procedure.
2076 * GWL_HINSTANCE The window's pplication instance handle.
2078 * GWL_ID The window's identifier.
2080 * GWL_USERDATA The window's user-specified data.
2082 * If the window is a dialog box, the _offset_ parameter can be one of
2083 * the following values:
2085 * DWL_DLGPROC The address of the window's dialog box procedure.
2087 * DWL_MSGRESULT The return value of a message
2088 * that the dialog box procedure processed.
2090 * DWL_USER Application specific information.
2094 * If successful, returns the previous value located at _offset_. Otherwise,
2099 * Extra memory for a window class is specified by a nonzero cbWndExtra
2100 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2101 * time of class creation.
2103 * Using GWL_WNDPROC to set a new window procedure effectively creates
2104 * a window subclass. Use CallWindowProc() in the new windows procedure
2105 * to pass messages to the superclass's window procedure.
2107 * The user data is reserved for use by the application which created
2110 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2111 * instead, call the EnableWindow() function to change the window's
2114 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2115 * SetParent() instead.
2118 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2119 * it sends WM_STYLECHANGING before changing the settings
2120 * and WM_STYLECHANGED afterwards.
2121 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2125 * GWL_STYLE does not dispatch WM_STYLE... messages.
2132 LONG WINAPI SetWindowLongW(
2133 HWND hwnd, /* window to alter */
2134 INT offset, /* offset, in bytes, of location to alter */
2135 LONG newval /* new value of location */
2137 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2141 /*******************************************************************
2142 * GetWindowText16 (USER.36)
2144 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2146 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2150 /*******************************************************************
2151 * GetWindowText32A (USER32.309)
2153 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2155 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2159 /*******************************************************************
2160 * InternalGetWindowText (USER32.326)
2162 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2164 FIXME(win,"(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2165 return GetWindowTextW(hwnd,lpString,nMaxCount);
2169 /*******************************************************************
2170 * GetWindowText32W (USER32.312)
2172 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2174 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2179 /*******************************************************************
2180 * SetWindowText16 (USER.37)
2182 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2184 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2188 /*******************************************************************
2189 * SetWindowText32A (USER32.521)
2191 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2193 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2197 /*******************************************************************
2198 * SetWindowText32W (USER32.523)
2200 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2202 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2206 /*******************************************************************
2207 * GetWindowTextLength16 (USER.38)
2209 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2211 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2215 /*******************************************************************
2216 * GetWindowTextLength32A (USER32.310)
2218 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2220 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2223 /*******************************************************************
2224 * GetWindowTextLength32W (USER32.311)
2226 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2228 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2232 /*******************************************************************
2233 * IsWindow16 (USER.47)
2235 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2237 return IsWindow( hwnd );
2240 void WINAPI WIN16_IsWindow16( CONTEXT *context )
2242 WORD *stack = PTR_SEG_OFF_TO_LIN(SS_reg(context), SP_reg(context));
2243 HWND16 hwnd = (HWND16)stack[2];
2245 AX_reg(context) = IsWindow( hwnd );
2246 ES_reg(context) = USER_HeapSel;
2250 /*******************************************************************
2251 * IsWindow32 (USER32.348)
2253 BOOL WINAPI IsWindow( HWND hwnd )
2258 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2259 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2260 WIN_ReleaseWndPtr(wndPtr);
2266 /*****************************************************************
2267 * GetParent16 (USER.46)
2269 HWND16 WINAPI GetParent16( HWND16 hwnd )
2271 return (HWND16)GetParent( hwnd );
2275 /*****************************************************************
2276 * GetParent32 (USER32.278)
2278 HWND WINAPI GetParent( HWND hwnd )
2283 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2284 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2286 WIN_ReleaseWndPtr(wndPtr);
2289 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2290 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2292 WIN_ReleaseWndPtr(wndPtr);
2297 /*****************************************************************
2300 * Get the top-level parent for a child window.
2301 * returns a locked pointer
2303 WND* WIN_GetTopParentPtr( WND* pWnd )
2305 while( pWnd && (pWnd->dwStyle & WS_CHILD))
2307 WIN_UpdateWndPtr(&pWnd,pWnd->parent);
2312 /*****************************************************************
2315 * Get the top-level parent for a child window.
2317 HWND WIN_GetTopParent( HWND hwnd )
2320 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2321 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2323 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2324 WIN_ReleaseWndPtr(tmpPtr);
2325 WIN_ReleaseWndPtr(wndPtr);
2330 /*****************************************************************
2331 * SetParent16 (USER.233)
2333 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2335 return SetParent( hwndChild, hwndNewParent );
2339 /*****************************************************************
2340 * SetParent32 (USER32.495)
2342 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2351 if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
2353 dwStyle = wndPtr->dwStyle;
2355 pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
2356 : WIN_LockWndPtr(pWndDesktop);
2358 /* Windows hides the window first, then shows it again
2359 * including the WM_SHOWWINDOW messages and all */
2360 if (dwStyle & WS_VISIBLE)
2361 ShowWindow( hwndChild, SW_HIDE );
2363 pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
2365 /* SetParent32 additionally needs to make hwndChild the topmost window
2366 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2367 WM_WINDOWPOSCHANGED notification messages.
2369 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2370 SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2371 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2372 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2374 retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
2376 WIN_ReleaseWndPtr(pWndOldParent);
2377 WIN_ReleaseWndPtr(pWndNewParent);
2378 WIN_ReleaseWndPtr(wndPtr);
2384 /*******************************************************************
2385 * IsChild16 (USER.48)
2387 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2389 return IsChild(parent,child);
2393 /*******************************************************************
2394 * IsChild32 (USER32.339)
2396 BOOL WINAPI IsChild( HWND parent, HWND child )
2398 WND * wndPtr = WIN_FindWndPtr( child );
2399 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2401 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2402 if (wndPtr->hwndSelf == parent)
2404 WIN_ReleaseWndPtr(wndPtr);
2408 WIN_ReleaseWndPtr(wndPtr);
2413 /***********************************************************************
2414 * IsWindowVisible16 (USER.49)
2416 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2418 return IsWindowVisible(hwnd);
2422 /***********************************************************************
2423 * IsWindowVisible32 (USER32.351)
2425 BOOL WINAPI IsWindowVisible( HWND hwnd )
2428 WND *wndPtr = WIN_FindWndPtr( hwnd );
2429 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2431 if (!(wndPtr->dwStyle & WS_VISIBLE))
2433 WIN_ReleaseWndPtr(wndPtr);
2436 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2438 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2439 WIN_ReleaseWndPtr(wndPtr);
2445 /***********************************************************************
2446 * WIN_IsWindowDrawable
2448 * hwnd is drawable when it is visible, all parents are not
2449 * minimized, and it is itself not minimized unless we are
2450 * trying to draw its default class icon.
2452 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2454 if( (wnd->dwStyle & WS_MINIMIZE &&
2455 icon && wnd->class->hIcon) ||
2456 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2457 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2458 if( wnd->dwStyle & WS_MINIMIZE ||
2459 !(wnd->dwStyle & WS_VISIBLE) ) break;
2460 return (wnd == NULL);
2464 /*******************************************************************
2465 * GetTopWindow16 (USER.229)
2467 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2469 return GetTopWindow(hwnd);
2473 /*******************************************************************
2474 * GetTopWindow32 (USER.229)
2476 HWND WINAPI GetTopWindow( HWND hwnd )
2479 WND * wndPtr = WIN_FindWndPtr( hwnd );
2480 if (wndPtr && wndPtr->child)
2482 retval = wndPtr->child->hwndSelf;
2485 WIN_ReleaseWndPtr(wndPtr);
2490 /*******************************************************************
2491 * GetWindow16 (USER.262)
2493 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2495 return GetWindow( hwnd,rel );
2499 /*******************************************************************
2500 * GetWindow32 (USER32.302)
2502 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2506 WND * wndPtr = WIN_FindWndPtr( hwnd );
2507 if (!wndPtr) return 0;
2511 if (wndPtr->parent) retval = wndPtr->parent->child->hwndSelf;
2516 if (!wndPtr->parent)
2518 retval = 0; /* Desktop window */
2521 while (wndPtr->next)
2523 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2525 retval = wndPtr->hwndSelf;
2529 if (!wndPtr->next) retval = 0;
2530 else retval = wndPtr->next->hwndSelf;
2534 if (!wndPtr->parent)
2536 retval = 0; /* Desktop window */
2539 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2540 if (wndPtr->hwndSelf == hwnd)
2542 retval = 0; /* First in list */
2545 while (wndPtr->next)
2547 if (wndPtr->next->hwndSelf == hwnd)
2549 retval = wndPtr->hwndSelf;
2552 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2558 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2562 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2567 WIN_ReleaseWndPtr(wndPtr);
2572 /*******************************************************************
2573 * GetNextWindow16 (USER.230)
2575 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2577 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2578 return GetWindow16( hwnd, flag );
2581 /*******************************************************************
2582 * ShowOwnedPopups16 (USER.265)
2584 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2586 ShowOwnedPopups( owner, fShow );
2590 /*******************************************************************
2591 * ShowOwnedPopups32 (USER32.531)
2593 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2596 pWnd = WIN_LockWndPtr(pWndDesktop->child);
2599 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
2600 (pWnd->dwStyle & WS_POPUP))
2601 ShowWindow( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
2602 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2608 /*******************************************************************
2609 * GetLastActivePopup16 (USER.287)
2611 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2613 return GetLastActivePopup( hwnd );
2616 /*******************************************************************
2617 * GetLastActivePopup32 (USER32.256)
2619 HWND WINAPI GetLastActivePopup( HWND hwnd )
2623 wndPtr = WIN_FindWndPtr(hwnd);
2624 if (!wndPtr) return hwnd;
2625 retval = wndPtr->hwndLastActive;
2626 WIN_ReleaseWndPtr(wndPtr);
2631 /*******************************************************************
2634 * Build an array of pointers to the children of a given window.
2635 * The array must be freed with HeapFree(SystemHeap). Return NULL
2636 * when no windows are found.
2638 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2640 /* Future : this function will lock all windows associated with this array */
2642 WND **list, **ppWnd;
2644 UINT count = 0, skipOwned, skipHidden;
2647 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2648 skipOwned = bwaFlags & BWA_SKIPOWNED;
2649 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2650 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2652 /* First count the windows */
2655 wndPtr = WIN_GetDesktop();
2657 pWnd = WIN_LockWndPtr(wndPtr->child);
2660 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
2661 if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2664 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2671 /* Now build the list of all windows */
2673 if ((list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * (count + 1))))
2675 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2677 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2678 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2684 WIN_ReleaseWndPtr(pWnd);
2690 if( pTotal ) *pTotal = count;
2693 /*******************************************************************
2694 * WIN_ReleaseWinArray
2696 void WIN_ReleaseWinArray(WND **wndArray)
2698 /* Future : this function will also unlock all windows associated with wndArray */
2699 HeapFree( SystemHeap, 0, wndArray );
2703 /*******************************************************************
2704 * EnumWindows16 (USER.54)
2706 BOOL16 WINAPI EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
2708 WND **list, **ppWnd;
2710 /* We have to build a list of all windows first, to avoid */
2711 /* unpleasant side-effects, for instance if the callback */
2712 /* function changes the Z-order of the windows. */
2714 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2716 WIN_ReleaseDesktop();
2720 /* Now call the callback function for every window */
2722 for (ppWnd = list; *ppWnd; ppWnd++)
2724 /* Make sure that the window still exists */
2725 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2726 if (!lpEnumFunc( (*ppWnd)->hwndSelf, lParam )) break;
2728 WIN_ReleaseWinArray(list);
2729 WIN_ReleaseDesktop();
2734 /*******************************************************************
2735 * EnumWindows32 (USER32.193)
2737 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2739 return (BOOL)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2743 /**********************************************************************
2744 * EnumTaskWindows16 (USER.225)
2746 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2749 WND **list, **ppWnd;
2751 /* This function is the same as EnumWindows(), */
2752 /* except for an added check on the window's task. */
2754 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2756 WIN_ReleaseDesktop();
2760 /* Now call the callback function for every window */
2762 for (ppWnd = list; *ppWnd; ppWnd++)
2764 /* Make sure that the window still exists */
2765 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2766 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2767 if (!func( (*ppWnd)->hwndSelf, lParam )) break;
2769 WIN_ReleaseWinArray(list);
2770 WIN_ReleaseDesktop();
2775 /**********************************************************************
2776 * EnumThreadWindows (USER32.190)
2778 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2780 THDB *tdb = THREAD_IdToTHDB(id);
2782 return (BOOL16)EnumTaskWindows16(tdb->teb.htask16, (WNDENUMPROC16)func, lParam);
2786 /**********************************************************************
2787 * WIN_EnumChildWindows
2789 * Helper function for EnumChildWindows().
2791 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2797 for ( ; *ppWnd; ppWnd++)
2799 /* Make sure that the window still exists */
2800 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2801 /* Build children list first */
2802 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2803 ret = func( (*ppWnd)->hwndSelf, lParam );
2806 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2807 WIN_ReleaseWinArray(childList);
2809 if (!ret) return FALSE;
2815 /**********************************************************************
2816 * EnumChildWindows16 (USER.55)
2818 BOOL16 WINAPI EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
2821 WND **list, *pParent;
2823 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2824 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2826 WIN_ReleaseWndPtr(pParent);
2829 WIN_EnumChildWindows( list, func, lParam );
2830 WIN_ReleaseWinArray(list);
2831 WIN_ReleaseWndPtr(pParent);
2836 /**********************************************************************
2837 * EnumChildWindows32 (USER32.178)
2839 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2842 return (BOOL)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2847 /*******************************************************************
2848 * AnyPopup16 (USER.52)
2850 BOOL16 WINAPI AnyPopup16(void)
2856 /*******************************************************************
2857 * AnyPopup32 (USER32.4)
2859 BOOL WINAPI AnyPopup(void)
2861 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2866 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2871 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2875 WIN_ReleaseWndPtr(wndPtr);
2880 /*******************************************************************
2881 * FlashWindow16 (USER.105)
2883 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2885 return FlashWindow( hWnd, bInvert );
2889 /*******************************************************************
2890 * FlashWindow32 (USER32.202)
2892 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2894 WND *wndPtr = WIN_FindWndPtr(hWnd);
2896 TRACE(win,"%04x\n", hWnd);
2898 if (!wndPtr) return FALSE;
2900 if (wndPtr->dwStyle & WS_MINIMIZE)
2902 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2904 HDC hDC = GetDC(hWnd);
2906 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2907 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2909 ReleaseDC( hWnd, hDC );
2910 wndPtr->flags |= WIN_NCACTIVATED;
2914 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2915 RDW_UPDATENOW | RDW_FRAME, 0 );
2916 wndPtr->flags &= ~WIN_NCACTIVATED;
2918 WIN_ReleaseWndPtr(wndPtr);
2924 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2925 else wparam = (hWnd == GetActiveWindow());
2927 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2928 WIN_ReleaseWndPtr(wndPtr);
2934 /*******************************************************************
2935 * SetSysModalWindow16 (USER.188)
2937 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
2939 HWND hWndOldModal = hwndSysModal;
2940 hwndSysModal = hWnd;
2941 FIXME(win, "EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2942 return hWndOldModal;
2946 /*******************************************************************
2947 * GetSysModalWindow16 (USER.52)
2949 HWND16 WINAPI GetSysModalWindow16(void)
2951 return hwndSysModal;
2955 /*******************************************************************
2956 * GetWindowContextHelpId (USER32.303)
2958 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2961 WND *wnd = WIN_FindWndPtr( hwnd );
2963 retval = wnd->helpContext;
2964 WIN_ReleaseWndPtr(wnd);
2969 /*******************************************************************
2970 * SetWindowContextHelpId (USER32.515)
2972 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
2974 WND *wnd = WIN_FindWndPtr( hwnd );
2975 if (!wnd) return FALSE;
2976 wnd->helpContext = id;
2977 WIN_ReleaseWndPtr(wnd);
2982 /*******************************************************************
2985 * recursively find a child that contains spDragInfo->pt point
2986 * and send WM_QUERYDROPOBJECT
2988 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
2990 BOOL16 wParam,bResult = 0;
2992 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
2993 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
2996 if( !ptrQueryWnd || !ptrDragInfo )
2998 WIN_ReleaseWndPtr(ptrQueryWnd);
3002 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3004 GetWindowRect(hQueryWnd,&tempRect);
3006 if( !PtInRect(&tempRect,pt) ||
3007 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3009 WIN_ReleaseWndPtr(ptrQueryWnd);
3013 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3015 tempRect = ptrQueryWnd->rectClient;
3016 if(ptrQueryWnd->dwStyle & WS_CHILD)
3017 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3018 (LPPOINT)&tempRect, 2 );
3020 if (PtInRect( &tempRect, pt))
3024 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3026 if( ptrWnd->dwStyle & WS_VISIBLE )
3028 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3029 if (PtInRect( &tempRect, pt )) break;
3035 TRACE(msg,"hwnd = %04x, %d %d - %d %d\n",
3036 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3037 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3038 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3039 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3041 WIN_ReleaseWndPtr(ptrWnd);
3046 WIN_ReleaseWndPtr(ptrQueryWnd);
3054 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3056 ptrDragInfo->hScope = hQueryWnd;
3058 bResult = ( bNoSend )
3059 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3060 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3061 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3063 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3065 WIN_ReleaseWndPtr(ptrQueryWnd);
3070 /*******************************************************************
3071 * DragDetect (USER.465)
3073 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3076 CONV_POINT16TO32( &pt, &pt32 );
3077 return DragDetect( hWnd, pt32 );
3080 /*******************************************************************
3081 * DragDetect32 (USER32.151)
3083 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3088 rect.left = pt.x - wDragWidth;
3089 rect.right = pt.x + wDragWidth;
3091 rect.top = pt.y - wDragHeight;
3092 rect.bottom = pt.y + wDragHeight;
3098 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3100 if( msg.message == WM_LBUTTONUP )
3105 if( msg.message == WM_MOUSEMOVE )
3107 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
3119 /******************************************************************************
3120 * DragObject16 (USER.464)
3122 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3123 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3126 LPDRAGINFO lpDragInfo;
3128 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3129 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
3130 WND *wndPtr = WIN_FindWndPtr(hWnd);
3131 HCURSOR16 hCurrentCursor = 0;
3132 HWND16 hCurrentWnd = 0;
3134 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
3135 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
3137 if( !lpDragInfo || !spDragInfo )
3139 WIN_ReleaseWndPtr(wndPtr);
3143 hBummer = LoadCursor16(0, IDC_BUMMER16);
3145 if( !hBummer || !wndPtr )
3147 GlobalFree16(hDragInfo);
3148 WIN_ReleaseWndPtr(wndPtr);
3154 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3156 GlobalFree16(hDragInfo);
3157 WIN_ReleaseWndPtr(wndPtr);
3161 if( hDragCursor == hCursor ) hDragCursor = 0;
3162 else hCursor = hDragCursor;
3164 hOldCursor = SetCursor(hDragCursor);
3167 lpDragInfo->hWnd = hWnd;
3168 lpDragInfo->hScope = 0;
3169 lpDragInfo->wFlags = wObj;
3170 lpDragInfo->hList = szList; /* near pointer! */
3171 lpDragInfo->hOfStruct = hOfStruct;
3179 do{ WaitMessage(); }
3180 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3182 *(lpDragInfo+1) = *lpDragInfo;
3184 lpDragInfo->pt = msg.pt;
3186 /* update DRAGINFO struct */
3187 TRACE(msg,"lpDI->hScope = %04x\n",lpDragInfo->hScope);
3189 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3190 hCurrentCursor = hCursor;
3193 hCurrentCursor = hBummer;
3194 lpDragInfo->hScope = 0;
3196 if( hCurrentCursor )
3197 SetCursor(hCurrentCursor);
3199 /* send WM_DRAGLOOP */
3200 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3201 (LPARAM) spDragInfo );
3202 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3203 if( hCurrentWnd != lpDragInfo->hScope )
3206 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3207 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
3208 HIWORD(spDragInfo)) );
3209 hCurrentWnd = lpDragInfo->hScope;
3211 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3215 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3217 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3220 ShowCursor( FALSE );
3224 SetCursor( hOldCursor );
3225 if (hDragCursor) DestroyCursor( hDragCursor );
3228 if( hCurrentCursor != hBummer )
3229 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3230 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3233 GlobalFree16(hDragInfo);
3234 WIN_ReleaseWndPtr(wndPtr);
3236 return (DWORD)(msg.lParam);