Added to project. Currently incomplete but will update weekly.
[wine.git] / windows / win.c
blob7aacb37b60728ac8c848fc700a6e7358307c761e
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include <string.h>
9 #include "windef.h"
10 #include "wingdi.h"
11 #include "wine/winbase16.h"
12 #include "wine/winuser16.h"
13 #include "options.h"
14 #include "class.h"
15 #include "win.h"
16 #include "heap.h"
17 #include "user.h"
18 #include "dce.h"
19 #include "cursoricon.h"
20 #include "hook.h"
21 #include "menu.h"
22 #include "message.h"
23 #include "monitor.h"
24 #include "nonclient.h"
25 #include "queue.h"
26 #include "winpos.h"
27 #include "clipboard.h"
28 #include "winproc.h"
29 #include "task.h"
30 #include "thread.h"
31 #include "winerror.h"
32 #include "mdi.h"
33 #include "local.h"
34 #include "syslevel.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;
45 /* Desktop window */
46 static WND *pWndDesktop = NULL;
48 static HWND hwndSysModal = 0;
50 static WORD wDragWidth = 4;
51 static WORD wDragHeight= 3;
53 /* thread safeness */
54 static SYSLEVEL WIN_SysLevel;
56 /***********************************************************************
57 * WIN_Init
58 */
59 void WIN_Init( void )
61 /* Initialisation of the critical section for thread safeness */
62 _CreateSysLevel( &WIN_SysLevel, 2 );
65 /***********************************************************************
66 * WIN_LockWnds
68 * Locks access to all WND structures for thread safeness
70 void WIN_LockWnds( void )
72 _EnterSysLevel( &WIN_SysLevel );
75 /***********************************************************************
76 * WIN_UnlockWnds
78 * Unlocks access to all WND structures
80 void WIN_UnlockWnds( void )
82 _LeaveSysLevel( &WIN_SysLevel );
85 /***********************************************************************
86 * WIN_SuspendWndsLock
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;
96 while ( count-- > 0 )
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 /***********************************************************************
114 * WIN_FindWndPtr
116 * Return a pointer to the WND structure corresponding to a HWND.
118 WND * WIN_FindWndPtr( HWND hwnd )
120 WND * ptr;
122 if (!hwnd || HIWORD(hwnd)) goto error2;
123 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
124 /* Lock all WND structures for thread safeness*/
125 WIN_LockWnds();
126 /*and increment destruction monitoring*/
127 ptr->irefCount++;
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 );
133 goto error;
135 /* returns a locked pointer */
136 return ptr;
137 error:
138 /* Unlock all WND structures for thread safeness*/
139 WIN_UnlockWnds();
140 /* and decrement destruction monitoring value */
141 ptr->irefCount--;
143 error2:
144 if ( hwnd!=0 )
145 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
146 return NULL;
149 /***********************************************************************
150 * WIN_LockWndPtr
152 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
153 * but by initWndPtr;
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*/
161 WIN_LockWnds();
162 /*and increment destruction monitoring*/
163 initWndPtr->irefCount++;
165 return initWndPtr;
169 /***********************************************************************
170 * WIN_ReleaseWndPtr
172 * Release the pointer to the WND structure.
174 void WIN_ReleaseWndPtr(WND *wndPtr)
176 if(!wndPtr) return;
178 /*Decrement destruction monitoring value*/
179 wndPtr->irefCount--;
180 /* Check if it's time to release the memory*/
181 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
183 /* Release memory */
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*/
193 WIN_UnlockWnds();
196 /***********************************************************************
197 * WIN_UpdateWndPtr
199 * Updates the value of oldPtr to newPtr.
201 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
203 WND *tmpWnd = NULL;
205 tmpWnd = WIN_LockWndPtr(newPtr);
206 WIN_ReleaseWndPtr(*oldPtr);
207 *oldPtr = tmpWnd;
211 /***********************************************************************
212 * WIN_DumpWindow
214 * Dump the content of a window structure to stderr.
216 void WIN_DumpWindow( HWND hwnd )
218 WND *ptr;
219 char className[80];
220 int i;
222 if (!(ptr = WIN_FindWndPtr( hwnd )))
224 WARN("%04x is not a window handle\n", hwnd );
225 return;
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) );
252 DPRINTF( "\n" );
254 DPRINTF( "\n" );
255 WIN_ReleaseWndPtr(ptr);
259 /***********************************************************************
260 * WIN_WalkWindows
262 * Walk the windows tree and print each window on stderr.
264 void WIN_WalkWindows( HWND hwnd, int indent )
266 WND *ptr;
267 char className[80];
269 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
271 if (!ptr)
273 WARN("Invalid window handle %04x\n", hwnd );
274 return;
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"
280 " Text");
282 while (ptr)
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 /***********************************************************************
301 * WIN_UnlinkWindow
303 * Remove a window from the siblings linked list.
305 BOOL WIN_UnlinkWindow( HWND hwnd )
307 WND *wndPtr, **ppWnd;
308 BOOL ret = FALSE;
310 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
311 else if(!wndPtr->parent)
313 WIN_ReleaseWndPtr(wndPtr);
314 return FALSE;
317 ppWnd = &wndPtr->parent->child;
318 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
319 if (*ppWnd)
321 *ppWnd = wndPtr->next;
322 ret = TRUE;
324 WIN_ReleaseWndPtr(wndPtr);
325 return ret;
329 /***********************************************************************
330 * WIN_LinkWindow
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);
344 return FALSE;
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 );
355 if (!afterPtr)
357 WIN_ReleaseWndPtr(wndPtr);
358 return FALSE;
360 ppWnd = &afterPtr->next;
361 WIN_ReleaseWndPtr(afterPtr);
363 wndPtr->next = *ppWnd;
364 *ppWnd = wndPtr;
365 WIN_ReleaseWndPtr(wndPtr);
366 return TRUE;
370 /***********************************************************************
371 * WIN_FindWinToRepaint
373 * Find a window that needs repaint.
375 HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE16 hQueue )
377 HWND hwndRet;
378 WND *pWnd;
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",
392 pWnd->hwndSelf );
394 else if ((pWnd->hmemTaskQ == hQueue) &&
395 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)))
396 break;
398 else if (pWnd->child )
399 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
401 WIN_ReleaseWndPtr(pWnd);
402 return hwndRet;
407 if(!pWnd)
409 return 0;
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);
420 if (pWnd)
422 hwndRet = pWnd->hwndSelf;
423 WIN_ReleaseWndPtr(pWnd);
425 TRACE("found %04x\n",hwndRet);
426 return hwndRet;
430 /***********************************************************************
431 * WIN_DestroyWindow
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;
439 WND *pWnd;
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);
489 QMSG *qmsg;
491 while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
493 if( qmsg->msg.message == WM_QUIT )
495 bPostQuit = TRUE;
496 wQuitParam = qmsg->msg.wParam;
498 QUEUE_RemoveMsg(msgQ, qmsg);
501 QUEUE_Unlock(msgQ);
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))
509 if (wndPtr->wIDmenu)
511 DestroyMenu( wndPtr->wIDmenu );
512 wndPtr->wIDmenu = 0;
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);
529 return pWnd;
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 )
540 BOOL ret = FALSE;
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;
549 ret = TRUE;
551 if (wnd->child)
553 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
557 else /* Queue is being destroyed */
559 while (wnd->child)
561 WND *tmp = WIN_LockWndPtr(wnd->child);
562 WND *tmp2;
563 ret = FALSE;
564 while (tmp)
566 if (tmp->hmemTaskQ == hQueue)
568 DestroyWindow( tmp->hwndSelf );
569 ret = TRUE;
570 break;
572 tmp2 = WIN_LockWndPtr(tmp->child);
573 if (tmp2 && WIN_ResetQueueWindows(tmp2,hQueue,0))
574 ret = TRUE;
575 else
577 WIN_UpdateWndPtr(&tmp,tmp->next);
579 WIN_ReleaseWndPtr(tmp2);
581 WIN_ReleaseWndPtr(tmp);
582 if (!ret) break;
585 return ret;
588 /***********************************************************************
589 * WIN_CreateDesktopWindow
591 * Create the desktop window.
593 BOOL WIN_CreateDesktopWindow(void)
595 CLASS *class;
596 HWND hwndDesktop;
598 TRACE("Creating desktop window\n");
601 if (!ICONTITLE_Init() ||
602 !WINPOS_CreateInternalPosAtom() ||
603 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
604 return FALSE;
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 |
631 WS_CLIPSIBLINGS;
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))
647 return FALSE;
649 SendMessageA( hwndDesktop, WM_NCCREATE, 0, 0 );
650 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
651 return TRUE;
655 /***********************************************************************
656 * WIN_CreateWindowEx
658 * Fix the coordinates - Helper for WIN_CreateWindowEx.
659 * returns default show mode in sw.
660 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
662 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
664 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
665 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
667 STARTUPINFOA info;
668 int defcx = 0, defcy = 0;
669 info.dwFlags = 0;
670 if (!(cs->style & (WS_CHILD | WS_POPUP))) GetStartupInfoA( &info );
672 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
674 /* Never believe Microsoft's documentation... CreateWindowEx doc says
675 * that if an overlapped window is created with WS_VISIBLE style bit
676 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
677 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
678 * reveals that
680 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
681 * 2) it does not ignore the y parameter as the docs claim; instead, it
682 * uses it as second parameter to ShowWindow() unless y is either
683 * CW_USEDEFAULT or CW_USEDEFAULT16.
685 * The fact that we didn't do 2) caused bogus windows pop up when wine
686 * was running apps that were using this obscure feature. Example -
687 * calc.exe that comes with Win98 (only Win98, it's different from
688 * the one that comes with Win95 and NT)
690 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
691 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
692 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
695 if (!(cs->style & (WS_CHILD | WS_POPUP)))
696 { /* if no other hint from the app, pick 3/4 of the screen real estate */
697 RECT r;
698 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
699 defcx = (((r.right - r.left) * 3) / 4) - cs->x;
700 defcy = (((r.bottom - r.top) * 3) / 4) - cs->y;
702 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
704 cs->cx = (info.dwFlags & STARTF_USESIZE) ? info.dwXSize : defcx;
705 cs->cy = (info.dwFlags & STARTF_USESIZE) ? info.dwYSize : defcy;
710 /***********************************************************************
711 * WIN_CreateWindowEx
713 * Implementation of CreateWindowEx().
715 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
716 BOOL win32, BOOL unicode )
718 INT sw = SW_SHOW;
719 CLASS *classPtr;
720 WND *wndPtr;
721 HWND retvalue;
722 HWND16 hwnd, hwndLinkAfter;
723 POINT maxSize, maxPos, minTrack, maxTrack;
724 LRESULT (CALLBACK *localSend32)(HWND, UINT, WPARAM, LPARAM);
726 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
727 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
728 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
729 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
730 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
732 /* Find the parent window */
734 if (cs->hwndParent)
736 /* Make sure parent is valid */
737 if (!IsWindow( cs->hwndParent ))
739 WARN("Bad parent %04x\n", cs->hwndParent );
740 return 0;
742 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
743 WARN("No parent for child window\n" );
744 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
747 /* Find the window class */
748 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
750 WARN("Bad class '%s'\n", cs->lpszClass );
751 return 0;
754 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
756 /* Create the window structure */
758 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
759 - sizeof(wndPtr->wExtra) )))
761 TRACE("out of memory\n" );
762 return 0;
765 /* Fill the window structure */
767 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
768 wndPtr->next = NULL;
769 wndPtr->child = NULL;
771 if ((cs->style & WS_CHILD) && cs->hwndParent)
773 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
774 wndPtr->owner = NULL;
775 WIN_ReleaseWndPtr(wndPtr->parent);
777 else
779 wndPtr->parent = pWndDesktop;
780 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
781 wndPtr->owner = NULL;
782 else
784 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
785 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
786 WIN_ReleaseWndPtr(wndPtr->owner);
787 WIN_ReleaseWndPtr(tmpWnd);
792 wndPtr->pDriver = wndPtr->parent->pDriver;
793 wndPtr->pDriver->pInitialize(wndPtr);
795 wndPtr->class = classPtr;
796 wndPtr->winproc = classPtr->winproc;
797 wndPtr->dwMagic = WND_MAGIC;
798 wndPtr->hwndSelf = hwnd;
799 wndPtr->hInstance = cs->hInstance;
800 wndPtr->text = NULL;
801 wndPtr->hmemTaskQ = GetFastQueue16();
802 wndPtr->hrgnUpdate = 0;
803 wndPtr->hwndLastActive = hwnd;
804 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
805 wndPtr->dwExStyle = cs->dwExStyle;
806 wndPtr->wIDmenu = 0;
807 wndPtr->helpContext = 0;
808 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
809 wndPtr->pVScroll = NULL;
810 wndPtr->pHScroll = NULL;
811 wndPtr->pProp = NULL;
812 wndPtr->userdata = 0;
813 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
814 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
815 wndPtr->irefCount = 1;
817 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
819 /* Call the WH_CBT hook */
821 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
822 ? HWND_BOTTOM : HWND_TOP;
824 if (HOOK_IsHooked( WH_CBT ))
826 CBT_CREATEWNDA cbtc;
827 LRESULT ret;
829 cbtc.lpcs = cs;
830 cbtc.hwndInsertAfter = hwndLinkAfter;
831 ret = unicode ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
832 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
833 if (ret)
835 TRACE("CBT-hook returned 0\n");
836 wndPtr->pDriver->pFinalize(wndPtr);
837 USER_HEAP_FREE( hwnd );
838 retvalue = 0;
839 goto end;
843 /* Increment class window counter */
845 classPtr->cWindows++;
847 /* Correct the window style */
849 if (!(cs->style & WS_CHILD))
851 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
852 if (!(cs->style & WS_POPUP))
854 wndPtr->dwStyle |= WS_CAPTION;
855 wndPtr->flags |= WIN_NEED_SIZE;
859 /* Get class or window DC if needed */
861 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
862 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
863 else wndPtr->dce = NULL;
865 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
867 wndPtr->rectWindow.left = cs->x;
868 wndPtr->rectWindow.top = cs->y;
869 wndPtr->rectWindow.right = cs->x + cs->cx;
870 wndPtr->rectWindow.bottom = cs->y + cs->cy;
871 wndPtr->rectClient = wndPtr->rectWindow;
873 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
875 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
877 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
878 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
879 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
880 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
881 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
884 if(cs->style & WS_CHILD)
886 if(cs->cx < 0) cs->cx = 0;
887 if(cs->cy < 0) cs->cy = 0;
889 else
891 if (cs->cx <= 0) cs->cx = 1;
892 if (cs->cy <= 0) cs->cy = 1;
895 wndPtr->rectWindow.left = cs->x;
896 wndPtr->rectWindow.top = cs->y;
897 wndPtr->rectWindow.right = cs->x + cs->cx;
898 wndPtr->rectWindow.bottom = cs->y + cs->cy;
899 wndPtr->rectClient = wndPtr->rectWindow;
901 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
903 retvalue = FALSE;
904 goto end;
907 /* Set the window menu */
909 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
911 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
912 else
914 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
915 if (classPtr->menuNameA)
916 cs->hMenu = HIWORD(classPtr->menuNameA) ?
917 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
918 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
919 #else
920 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
921 if (menuName)
923 if (HIWORD(cs->hInstance))
924 cs->hMenu = LoadMenuA(cs->hInstance,PTR_SEG_TO_LIN(menuName));
925 else
926 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
928 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
930 #endif
933 else wndPtr->wIDmenu = (UINT)cs->hMenu;
935 /* Send the WM_CREATE message
936 * Perhaps we shouldn't allow width/height changes as well.
937 * See p327 in "Internals".
940 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
942 localSend32 = unicode ? SendMessageW : SendMessageA;
943 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
945 /* Insert the window in the linked list */
947 WIN_LinkWindow( hwnd, hwndLinkAfter );
949 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
950 NULL, NULL, 0, &wndPtr->rectClient );
951 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
952 maxPos.y - wndPtr->rectWindow.top);
953 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
955 /* Send the size messages */
957 if (!(wndPtr->flags & WIN_NEED_SIZE))
959 /* send it anyway */
960 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
961 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
962 WARN("sending bogus WM_SIZE message 0x%08lx\n",
963 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
964 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
965 SendMessageA( hwnd, WM_SIZE, SIZE_RESTORED,
966 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
967 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
968 SendMessageA( hwnd, WM_MOVE, 0,
969 MAKELONG( wndPtr->rectClient.left,
970 wndPtr->rectClient.top ) );
973 /* Show the window, maximizing or minimizing if needed */
975 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
977 RECT16 newPos;
978 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
979 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
980 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
981 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
982 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
983 : SWP_NOZORDER | SWP_FRAMECHANGED;
984 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
985 newPos.right, newPos.bottom, swFlag );
988 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
990 /* Notify the parent window only */
992 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
993 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
994 if( !IsWindow(hwnd) )
996 retvalue = 0;
997 goto end;
1001 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, sw );
1003 /* Call WH_SHELL hook */
1005 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1006 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
1008 TRACE("created window %04x\n", hwnd);
1009 retvalue = hwnd;
1010 goto end;
1012 WIN_UnlinkWindow( hwnd );
1015 /* Abort window creation */
1017 WARN("aborted by WM_xxCREATE!\n");
1018 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1019 retvalue = 0;
1020 end:
1021 WIN_ReleaseWndPtr(wndPtr);
1023 return retvalue;
1027 /***********************************************************************
1028 * CreateWindow16 (USER.41)
1030 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1031 DWORD style, INT16 x, INT16 y, INT16 width,
1032 INT16 height, HWND16 parent, HMENU16 menu,
1033 HINSTANCE16 instance, LPVOID data )
1035 return CreateWindowEx16( 0, className, windowName, style,
1036 x, y, width, height, parent, menu, instance, data );
1040 /***********************************************************************
1041 * CreateWindowEx16 (USER.452)
1043 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1044 LPCSTR windowName, DWORD style, INT16 x,
1045 INT16 y, INT16 width, INT16 height,
1046 HWND16 parent, HMENU16 menu,
1047 HINSTANCE16 instance, LPVOID data )
1049 ATOM classAtom;
1050 CREATESTRUCTA cs;
1051 char buffer[256];
1053 /* Find the class atom */
1055 if (HIWORD(className))
1057 if (!(classAtom = GlobalFindAtomA( className )))
1059 ERR( "bad class name %s\n", debugres_a(className) );
1060 return 0;
1063 else
1065 classAtom = LOWORD(className);
1066 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1068 ERR( "bad atom %x\n", classAtom);
1069 return 0;
1071 className = buffer;
1074 /* Fix the coordinates */
1076 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1077 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1078 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1079 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1081 /* Create the window */
1083 cs.lpCreateParams = data;
1084 cs.hInstance = (HINSTANCE)instance;
1085 cs.hMenu = (HMENU)menu;
1086 cs.hwndParent = (HWND)parent;
1087 cs.style = style;
1088 cs.lpszName = windowName;
1089 cs.lpszClass = className;
1090 cs.dwExStyle = exStyle;
1092 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
1096 /***********************************************************************
1097 * CreateWindowExA (USER32.83)
1099 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1100 LPCSTR windowName, DWORD style, INT x,
1101 INT y, INT width, INT height,
1102 HWND parent, HMENU menu,
1103 HINSTANCE instance, LPVOID data )
1105 ATOM classAtom;
1106 CREATESTRUCTA cs;
1107 char buffer[256];
1109 if(!instance)
1110 instance=GetModuleHandleA(NULL);
1112 if(exStyle & WS_EX_MDICHILD)
1113 return MDI_CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1115 /* Find the class atom */
1117 if (HIWORD(className))
1119 if (!(classAtom = GlobalFindAtomA( className )))
1121 ERR( "bad class name %s\n", debugres_a(className) );
1122 return 0;
1125 else
1127 classAtom = LOWORD(className);
1128 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1130 ERR( "bad atom %x\n", classAtom);
1131 return 0;
1133 className = buffer;
1136 /* Create the window */
1138 cs.lpCreateParams = data;
1139 cs.hInstance = instance;
1140 cs.hMenu = menu;
1141 cs.hwndParent = parent;
1142 cs.x = x;
1143 cs.y = y;
1144 cs.cx = width;
1145 cs.cy = height;
1146 cs.style = style;
1147 cs.lpszName = windowName;
1148 cs.lpszClass = className;
1149 cs.dwExStyle = exStyle;
1151 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
1155 /***********************************************************************
1156 * CreateWindowExW (USER32.84)
1158 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1159 LPCWSTR windowName, DWORD style, INT x,
1160 INT y, INT width, INT height,
1161 HWND parent, HMENU menu,
1162 HINSTANCE instance, LPVOID data )
1164 ATOM classAtom;
1165 CREATESTRUCTW cs;
1166 WCHAR buffer[256];
1168 if(!instance)
1169 instance=GetModuleHandleA(NULL);
1171 if(exStyle & WS_EX_MDICHILD)
1172 return MDI_CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1174 /* Find the class atom */
1176 if (HIWORD(className))
1178 if (!(classAtom = GlobalFindAtomW( className )))
1180 ERR( "bad class name %s\n", debugres_w(className) );
1181 return 0;
1184 else
1186 classAtom = LOWORD(className);
1187 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1189 ERR( "bad atom %x\n", classAtom);
1190 return 0;
1192 className = buffer;
1195 /* Create the window */
1197 cs.lpCreateParams = data;
1198 cs.hInstance = instance;
1199 cs.hMenu = menu;
1200 cs.hwndParent = parent;
1201 cs.x = x;
1202 cs.y = y;
1203 cs.cx = width;
1204 cs.cy = height;
1205 cs.style = style;
1206 cs.lpszName = windowName;
1207 cs.lpszClass = className;
1208 cs.dwExStyle = exStyle;
1210 /* Note: we rely on the fact that CREATESTRUCTA and */
1211 /* CREATESTRUCTW have the same layout. */
1212 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, TRUE, TRUE );
1216 /***********************************************************************
1217 * WIN_CheckFocus
1219 static void WIN_CheckFocus( WND* pWnd )
1221 if( GetFocus16() == pWnd->hwndSelf )
1222 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
1225 /***********************************************************************
1226 * WIN_SendDestroyMsg
1228 static void WIN_SendDestroyMsg( WND* pWnd )
1230 WIN_CheckFocus(pWnd);
1232 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1233 CLIPBOARD_Driver->pResetOwner( pWnd, TRUE );
1236 * Send the WM_DESTROY to the window.
1238 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1241 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1242 * make sure that the window still exists when we come back.
1244 if (IsWindow(pWnd->hwndSelf))
1246 HWND* pWndArray = NULL;
1247 WND* pChild = NULL;
1248 int nKidCount = 0;
1251 * Now, if the window has kids, we have to send WM_DESTROY messages
1252 * recursively to it's kids. It seems that those calls can also
1253 * trigger re-entrant calls to DestroyWindow for the kids so we must
1254 * protect against corruption of the list of siblings. We first build
1255 * a list of HWNDs representing all the kids.
1257 pChild = WIN_LockWndPtr(pWnd->child);
1258 while( pChild )
1260 nKidCount++;
1261 WIN_UpdateWndPtr(&pChild,pChild->next);
1265 * If there are no kids, we're done.
1267 if (nKidCount==0)
1268 return;
1270 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1273 * Sanity check
1275 if (pWndArray==NULL)
1276 return;
1279 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1280 * call, our linked list of siblings should be safe.
1282 nKidCount = 0;
1283 pChild = WIN_LockWndPtr(pWnd->child);
1284 while( pChild )
1286 pWndArray[nKidCount] = pChild->hwndSelf;
1287 nKidCount++;
1288 WIN_UpdateWndPtr(&pChild,pChild->next);
1292 * Now that we have a list, go through that list again and send the destroy
1293 * message to those windows. We are using the HWND to retrieve the
1294 * WND pointer so we are effectively checking that all the kid windows are
1295 * still valid before sending the message.
1297 while (nKidCount>0)
1299 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1301 if (pChild!=NULL)
1303 WIN_SendDestroyMsg( pChild );
1304 WIN_ReleaseWndPtr(pChild);
1309 * Cleanup
1311 HeapFree(GetProcessHeap(), 0, pWndArray);
1312 WIN_CheckFocus(pWnd);
1314 else
1315 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1319 /***********************************************************************
1320 * DestroyWindow16 (USER.53)
1322 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1324 return DestroyWindow(hwnd);
1328 /***********************************************************************
1329 * DestroyWindow (USER32.135)
1331 BOOL WINAPI DestroyWindow( HWND hwnd )
1333 WND * wndPtr;
1334 BOOL retvalue;
1336 TRACE("(%04x)\n", hwnd);
1338 /* Initialization */
1340 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1341 if (wndPtr == pWndDesktop)
1343 retvalue = FALSE; /* Can't destroy desktop */
1344 goto end;
1347 /* Call hooks */
1349 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1351 retvalue = FALSE;
1352 goto end;
1355 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1357 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1358 /* FIXME: clean up palette - see "Internals" p.352 */
1361 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1362 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1364 /* Notify the parent window only */
1365 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1366 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1367 if( !IsWindow(hwnd) )
1369 retvalue = TRUE;
1370 goto end;
1374 CLIPBOARD_Driver->pResetOwner( wndPtr, FALSE ); /* before the window is unmapped */
1376 /* Hide the window */
1378 if (wndPtr->dwStyle & WS_VISIBLE)
1380 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1381 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1382 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1383 if (!IsWindow(hwnd))
1385 retvalue = TRUE;
1386 goto end;
1390 /* Recursively destroy owned windows */
1392 if( !(wndPtr->dwStyle & WS_CHILD) )
1394 /* make sure top menu popup doesn't get destroyed */
1395 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1397 for (;;)
1399 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1400 while (siblingPtr)
1402 if (siblingPtr->owner == wndPtr)
1404 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1405 break;
1406 else
1407 siblingPtr->owner = NULL;
1409 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1411 if (siblingPtr)
1413 DestroyWindow( siblingPtr->hwndSelf );
1414 WIN_ReleaseWndPtr(siblingPtr);
1416 else break;
1419 if( !Options.managed || EVENT_CheckFocus() )
1420 WINPOS_ActivateOtherWindow(wndPtr);
1422 if( wndPtr->owner &&
1423 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1424 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1427 /* Send destroy messages */
1429 WIN_SendDestroyMsg( wndPtr );
1430 if (!IsWindow(hwnd))
1432 retvalue = TRUE;
1433 goto end;
1436 /* Unlink now so we won't bother with the children later on */
1438 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1440 /* Destroy the window storage */
1442 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1443 retvalue = TRUE;
1444 end:
1445 WIN_ReleaseWndPtr(wndPtr);
1446 return retvalue;
1450 /***********************************************************************
1451 * CloseWindow16 (USER.43)
1453 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1455 return CloseWindow( hwnd );
1459 /***********************************************************************
1460 * CloseWindow (USER32.56)
1462 BOOL WINAPI CloseWindow( HWND hwnd )
1464 WND * wndPtr = WIN_FindWndPtr( hwnd );
1465 BOOL retvalue;
1467 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1469 retvalue = FALSE;
1470 goto end;
1472 ShowWindow( hwnd, SW_MINIMIZE );
1473 retvalue = TRUE;
1474 end:
1475 WIN_ReleaseWndPtr(wndPtr);
1476 return retvalue;
1481 /***********************************************************************
1482 * OpenIcon16 (USER.44)
1484 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1486 return OpenIcon( hwnd );
1490 /***********************************************************************
1491 * OpenIcon (USER32.410)
1493 BOOL WINAPI OpenIcon( HWND hwnd )
1495 if (!IsIconic( hwnd )) return FALSE;
1496 ShowWindow( hwnd, SW_SHOWNORMAL );
1497 return TRUE;
1501 /***********************************************************************
1502 * WIN_FindWindow
1504 * Implementation of FindWindow() and FindWindowEx().
1506 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1507 LPCSTR title )
1509 WND *pWnd;
1510 HWND retvalue;
1512 if (child)
1514 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1515 if (parent)
1517 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1519 retvalue = 0;
1520 goto end;
1523 else if (pWnd->parent != pWndDesktop)
1525 retvalue = 0;
1526 goto end;
1528 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1530 else
1532 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1534 retvalue = 0;
1535 goto end;
1537 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1539 if (!pWnd)
1541 retvalue = 0;
1542 goto end;
1545 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1547 if (className && (pWnd->class->atomName != className))
1548 continue; /* Not the right class */
1550 /* Now check the title */
1552 if (!title)
1554 retvalue = pWnd->hwndSelf;
1555 goto end;
1557 if (pWnd->text && !strcmp( pWnd->text, title ))
1559 retvalue = pWnd->hwndSelf;
1560 goto end;
1563 retvalue = 0;
1564 end:
1565 WIN_ReleaseWndPtr(pWnd);
1566 return retvalue;
1571 /***********************************************************************
1572 * FindWindow16 (USER.50)
1574 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1576 return FindWindowA( className, title );
1580 /***********************************************************************
1581 * FindWindowEx16 (USER.427)
1583 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1585 return FindWindowExA( parent, child, className, title );
1589 /***********************************************************************
1590 * FindWindowA (USER32.198)
1592 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1594 HWND ret = FindWindowExA( 0, 0, className, title );
1595 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1596 return ret;
1600 /***********************************************************************
1601 * FindWindowExA (USER32.199)
1603 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1604 LPCSTR className, LPCSTR title )
1606 ATOM atom = 0;
1608 if (className)
1610 /* If the atom doesn't exist, then no class */
1611 /* with this name exists either. */
1612 if (!(atom = GlobalFindAtomA( className )))
1614 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1615 return 0;
1618 return WIN_FindWindow( parent, child, atom, title );
1622 /***********************************************************************
1623 * FindWindowExW (USER32.200)
1625 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1626 LPCWSTR className, LPCWSTR title )
1628 ATOM atom = 0;
1629 char *buffer;
1630 HWND hwnd;
1632 if (className)
1634 /* If the atom doesn't exist, then no class */
1635 /* with this name exists either. */
1636 if (!(atom = GlobalFindAtomW( className )))
1638 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1639 return 0;
1642 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1643 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1644 HeapFree( GetProcessHeap(), 0, buffer );
1645 return hwnd;
1649 /***********************************************************************
1650 * FindWindowW (USER32.201)
1652 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1654 return FindWindowExW( 0, 0, className, title );
1658 /**********************************************************************
1659 * WIN_GetDesktop
1660 * returns a locked pointer
1662 WND *WIN_GetDesktop(void)
1664 return WIN_LockWndPtr(pWndDesktop);
1666 /**********************************************************************
1667 * WIN_ReleaseDesktop
1668 * unlock the desktop pointer
1670 void WIN_ReleaseDesktop(void)
1672 WIN_ReleaseWndPtr(pWndDesktop);
1676 /**********************************************************************
1677 * GetDesktopWindow16 (USER.286)
1679 HWND16 WINAPI GetDesktopWindow16(void)
1681 return (HWND16)pWndDesktop->hwndSelf;
1685 /**********************************************************************
1686 * GetDesktopWindow (USER32.232)
1688 HWND WINAPI GetDesktopWindow(void)
1690 if (pWndDesktop) return pWndDesktop->hwndSelf;
1691 ERR( "You need the -desktop option when running with native USER\n" );
1692 ExitProcess(1);
1693 return 0;
1697 /**********************************************************************
1698 * GetDesktopHwnd (USER.278)
1700 * Exactly the same thing as GetDesktopWindow(), but not documented.
1701 * Don't ask me why...
1703 HWND16 WINAPI GetDesktopHwnd16(void)
1705 return (HWND16)pWndDesktop->hwndSelf;
1709 /*******************************************************************
1710 * EnableWindow16 (USER.34)
1712 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1714 return EnableWindow( hwnd, enable );
1718 /*******************************************************************
1719 * EnableWindow (USER32.172)
1721 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1723 WND *wndPtr;
1724 BOOL retvalue;
1726 TRACE("EnableWindow32: ( %x, %d )\n", hwnd, enable);
1728 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1729 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1731 /* Enable window */
1732 wndPtr->dwStyle &= ~WS_DISABLED;
1734 if( wndPtr->flags & WIN_NATIVE )
1735 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
1737 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1738 retvalue = TRUE;
1739 goto end;
1741 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1743 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1745 /* Disable window */
1746 wndPtr->dwStyle |= WS_DISABLED;
1748 if( wndPtr->flags & WIN_NATIVE )
1749 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
1751 if (hwnd == GetFocus())
1753 SetFocus( 0 ); /* A disabled window can't have the focus */
1755 if (hwnd == GetCapture())
1757 ReleaseCapture(); /* A disabled window can't capture the mouse */
1759 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1760 retvalue = FALSE;
1761 goto end;
1763 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1764 end:
1765 WIN_ReleaseWndPtr(wndPtr);
1766 return retvalue;
1770 /***********************************************************************
1771 * IsWindowEnabled16 (USER.35)
1773 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1775 return IsWindowEnabled(hWnd);
1779 /***********************************************************************
1780 * IsWindowEnabled (USER32.349)
1782 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1784 WND * wndPtr;
1785 BOOL retvalue;
1787 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1788 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1789 WIN_ReleaseWndPtr(wndPtr);
1790 return retvalue;
1795 /***********************************************************************
1796 * IsWindowUnicode (USER32.350)
1798 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1800 WND * wndPtr;
1801 BOOL retvalue;
1803 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1804 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1805 WIN_ReleaseWndPtr(wndPtr);
1806 return retvalue;
1810 /**********************************************************************
1811 * GetWindowWord16 (USER.133)
1813 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1815 return GetWindowWord( hwnd, offset );
1819 /**********************************************************************
1820 * GetWindowWord (USER32.314)
1822 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1824 WORD retvalue;
1825 WND * wndPtr = WIN_FindWndPtr( hwnd );
1826 if (!wndPtr) return 0;
1827 if (offset >= 0)
1829 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1831 WARN("Invalid offset %d\n", offset );
1832 retvalue = 0;
1833 goto end;
1835 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1836 goto end;
1838 switch(offset)
1840 case GWW_ID:
1841 if (HIWORD(wndPtr->wIDmenu))
1842 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1843 wndPtr->wIDmenu);
1844 retvalue = (WORD)wndPtr->wIDmenu;
1845 goto end;
1846 case GWW_HWNDPARENT:
1847 retvalue = GetParent(hwnd);
1848 goto end;
1849 case GWW_HINSTANCE:
1850 if (HIWORD(wndPtr->hInstance))
1851 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1852 wndPtr->hInstance);
1853 retvalue = (WORD)wndPtr->hInstance;
1854 goto end;
1855 default:
1856 WARN("Invalid offset %d\n", offset );
1857 retvalue = 0;
1858 goto end;
1860 end:
1861 WIN_ReleaseWndPtr(wndPtr);
1862 return retvalue;
1865 /**********************************************************************
1866 * SetWindowWord16 (USER.134)
1868 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1870 return SetWindowWord( hwnd, offset, newval );
1874 /**********************************************************************
1875 * SetWindowWord (USER32.524)
1877 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1879 WORD *ptr, retval;
1880 WND * wndPtr = WIN_FindWndPtr( hwnd );
1881 if (!wndPtr) return 0;
1882 if (offset >= 0)
1884 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1886 WARN("Invalid offset %d\n", offset );
1887 retval = 0;
1888 goto end;
1890 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1892 else switch(offset)
1894 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1895 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1896 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1897 goto end;
1898 default:
1899 WARN("Invalid offset %d\n", offset );
1900 retval = 0;
1901 goto end;
1903 retval = *ptr;
1904 *ptr = newval;
1905 end:
1906 WIN_ReleaseWndPtr(wndPtr);
1907 return retval;
1911 /**********************************************************************
1912 * WIN_GetWindowLong
1914 * Helper function for GetWindowLong().
1916 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1918 LONG retvalue;
1919 WND * wndPtr = WIN_FindWndPtr( hwnd );
1920 if (!wndPtr) return 0;
1921 if (offset >= 0)
1923 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1925 WARN("Invalid offset %d\n", offset );
1926 retvalue = 0;
1927 goto end;
1929 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1930 /* Special case for dialog window procedure */
1931 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1933 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1934 goto end;
1936 goto end;
1938 switch(offset)
1940 case GWL_USERDATA: retvalue = wndPtr->userdata;
1941 goto end;
1942 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1943 goto end;
1944 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1945 goto end;
1946 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1947 goto end;
1948 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1949 type );
1950 goto end;
1951 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1952 goto end;
1953 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1954 goto end;
1955 default:
1956 WARN("Unknown offset %d\n", offset );
1958 retvalue = 0;
1959 end:
1960 WIN_ReleaseWndPtr(wndPtr);
1961 return retvalue;
1965 /**********************************************************************
1966 * WIN_SetWindowLong
1968 * Helper function for SetWindowLong().
1970 * 0 is the failure code. However, in the case of failure SetLastError
1971 * must be set to distinguish between a 0 return value and a failure.
1973 * FIXME: The error values for SetLastError may not be right. Can
1974 * someone check with the real thing?
1976 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1977 WINDOWPROCTYPE type )
1979 LONG *ptr, retval;
1980 WND * wndPtr = WIN_FindWndPtr( hwnd );
1981 STYLESTRUCT style;
1983 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1985 if (!wndPtr)
1987 /* Is this the right error? */
1988 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1989 return 0;
1992 if (offset >= 0)
1994 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1996 WARN("Invalid offset %d\n", offset );
1998 /* Is this the right error? */
1999 SetLastError( ERROR_OUTOFMEMORY );
2001 retval = 0;
2002 goto end;
2004 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2005 /* Special case for dialog window procedure */
2006 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2008 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2009 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2010 type, WIN_PROC_WINDOW );
2011 goto end;
2014 else switch(offset)
2016 case GWL_ID:
2017 ptr = (DWORD*)&wndPtr->wIDmenu;
2018 break;
2019 case GWL_HINSTANCE:
2020 retval = SetWindowWord( hwnd, offset, newval );
2021 goto end;
2022 case GWL_WNDPROC:
2023 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2024 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2025 type, WIN_PROC_WINDOW );
2026 goto end;
2027 case GWL_STYLE:
2028 style.styleOld = wndPtr->dwStyle;
2029 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
2030 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
2032 if (wndPtr->flags & WIN_ISWIN32)
2033 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
2034 wndPtr->dwStyle = style.styleNew;
2035 if (wndPtr->flags & WIN_ISWIN32)
2036 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
2037 retval = style.styleOld;
2038 goto end;
2040 case GWL_USERDATA:
2041 ptr = &wndPtr->userdata;
2042 break;
2043 case GWL_EXSTYLE:
2044 style.styleOld = wndPtr->dwExStyle;
2045 style.styleNew = newval;
2046 if (wndPtr->flags & WIN_ISWIN32)
2047 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
2048 wndPtr->dwExStyle = newval;
2049 if (wndPtr->flags & WIN_ISWIN32)
2050 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
2051 retval = style.styleOld;
2052 goto end;
2054 default:
2055 WARN("Invalid offset %d\n", offset );
2057 /* Don't think this is right error but it should do */
2058 SetLastError( ERROR_OUTOFMEMORY );
2060 retval = 0;
2061 goto end;
2063 retval = *ptr;
2064 *ptr = newval;
2065 end:
2066 WIN_ReleaseWndPtr(wndPtr);
2067 return retval;
2071 /**********************************************************************
2072 * GetWindowLong16 (USER.135)
2074 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2076 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2080 /**********************************************************************
2081 * GetWindowLongA (USER32.305)
2083 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2085 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2089 /**********************************************************************
2090 * GetWindowLongW (USER32.306)
2092 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2094 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2098 /**********************************************************************
2099 * SetWindowLong16 (USER.136)
2101 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2103 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2107 /**********************************************************************
2108 * SetWindowLongA (USER32.517)
2110 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2112 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2116 /**********************************************************************
2117 * SetWindowLongW (USER32.518) Set window attribute
2119 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2120 * value in a window's extra memory.
2122 * The _hwnd_ parameter specifies the window. is the handle to a
2123 * window that has extra memory. The _newval_ parameter contains the
2124 * new attribute or extra memory value. If positive, the _offset_
2125 * parameter is the byte-addressed location in the window's extra
2126 * memory to set. If negative, _offset_ specifies the window
2127 * attribute to set, and should be one of the following values:
2129 * GWL_EXSTYLE The window's extended window style
2131 * GWL_STYLE The window's window style.
2133 * GWL_WNDPROC Pointer to the window's window procedure.
2135 * GWL_HINSTANCE The window's pplication instance handle.
2137 * GWL_ID The window's identifier.
2139 * GWL_USERDATA The window's user-specified data.
2141 * If the window is a dialog box, the _offset_ parameter can be one of
2142 * the following values:
2144 * DWL_DLGPROC The address of the window's dialog box procedure.
2146 * DWL_MSGRESULT The return value of a message
2147 * that the dialog box procedure processed.
2149 * DWL_USER Application specific information.
2151 * RETURNS
2153 * If successful, returns the previous value located at _offset_. Otherwise,
2154 * returns 0.
2156 * NOTES
2158 * Extra memory for a window class is specified by a nonzero cbWndExtra
2159 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2160 * time of class creation.
2162 * Using GWL_WNDPROC to set a new window procedure effectively creates
2163 * a window subclass. Use CallWindowProc() in the new windows procedure
2164 * to pass messages to the superclass's window procedure.
2166 * The user data is reserved for use by the application which created
2167 * the window.
2169 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2170 * instead, call the EnableWindow() function to change the window's
2171 * disabled state.
2173 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2174 * SetParent() instead.
2176 * Win95:
2177 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2178 * it sends WM_STYLECHANGING before changing the settings
2179 * and WM_STYLECHANGED afterwards.
2180 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2182 * BUGS
2184 * GWL_STYLE does not dispatch WM_STYLE... messages.
2186 * CONFORMANCE
2188 * ECMA-234, Win32
2191 LONG WINAPI SetWindowLongW(
2192 HWND hwnd, /* window to alter */
2193 INT offset, /* offset, in bytes, of location to alter */
2194 LONG newval /* new value of location */
2196 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2200 /*******************************************************************
2201 * GetWindowText16 (USER.36)
2203 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2205 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2209 /*******************************************************************
2210 * GetWindowTextA (USER32.309)
2212 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2214 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2215 (LPARAM)lpString );
2218 /*******************************************************************
2219 * InternalGetWindowText (USER32.326)
2221 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2223 FIXME("(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2224 return GetWindowTextW(hwnd,lpString,nMaxCount);
2228 /*******************************************************************
2229 * GetWindowTextW (USER32.312)
2231 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2233 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2234 (LPARAM)lpString );
2238 /*******************************************************************
2239 * SetWindowText16 (USER.37)
2241 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2243 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2247 /*******************************************************************
2248 * SetWindowTextA (USER32.521)
2250 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2252 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2256 /*******************************************************************
2257 * SetWindowTextW (USER32.523)
2259 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2261 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2265 /*******************************************************************
2266 * GetWindowTextLength16 (USER.38)
2268 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2270 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2274 /*******************************************************************
2275 * GetWindowTextLengthA (USER32.310)
2277 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2279 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2282 /*******************************************************************
2283 * GetWindowTextLengthW (USER32.311)
2285 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2287 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2291 /*******************************************************************
2292 * IsWindow16 (USER.47)
2294 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2296 CURRENT_STACK16->es = USER_HeapSel;
2297 return IsWindow( hwnd );
2301 /*******************************************************************
2302 * IsWindow (USER32.348)
2304 BOOL WINAPI IsWindow( HWND hwnd )
2306 WND * wndPtr;
2307 BOOL retvalue;
2309 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2310 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2311 WIN_ReleaseWndPtr(wndPtr);
2312 return retvalue;
2317 /*****************************************************************
2318 * GetParent16 (USER.46)
2320 HWND16 WINAPI GetParent16( HWND16 hwnd )
2322 return (HWND16)GetParent( hwnd );
2326 /*****************************************************************
2327 * GetParent (USER32.278)
2329 HWND WINAPI GetParent( HWND hwnd )
2331 WND *wndPtr;
2332 HWND retvalue = 0;
2334 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2335 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2336 goto end;
2338 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2339 if (wndPtr)
2340 retvalue = wndPtr->hwndSelf;
2342 end:
2343 WIN_ReleaseWndPtr(wndPtr);
2344 return retvalue;
2348 /*****************************************************************
2349 * WIN_GetTopParent
2351 * Get the top-level parent for a child window.
2352 * returns a locked pointer
2354 WND* WIN_GetTopParentPtr( WND* pWnd )
2356 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2358 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2360 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2362 return tmpWnd;
2365 /*****************************************************************
2366 * WIN_GetTopParent
2368 * Get the top-level parent for a child window.
2370 HWND WIN_GetTopParent( HWND hwnd )
2372 HWND retvalue;
2373 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2374 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2376 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2377 WIN_ReleaseWndPtr(tmpPtr);
2378 WIN_ReleaseWndPtr(wndPtr);
2379 return retvalue;
2383 /*****************************************************************
2384 * SetParent16 (USER.233)
2386 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2388 return SetParent( hwndChild, hwndNewParent );
2392 /*****************************************************************
2393 * SetParent (USER32.495)
2395 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2397 WND *wndPtr;
2398 DWORD dwStyle;
2399 WND *pWndNewParent;
2400 WND *pWndOldParent;
2401 HWND retvalue;
2404 if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
2406 dwStyle = wndPtr->dwStyle;
2408 pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
2409 : WIN_LockWndPtr(pWndDesktop);
2411 /* Windows hides the window first, then shows it again
2412 * including the WM_SHOWWINDOW messages and all */
2413 if (dwStyle & WS_VISIBLE)
2414 ShowWindow( hwndChild, SW_HIDE );
2416 pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
2418 /* SetParent additionally needs to make hwndChild the topmost window
2419 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2420 WM_WINDOWPOSCHANGED notification messages.
2422 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2423 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2424 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2425 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2427 retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
2429 WIN_ReleaseWndPtr(pWndOldParent);
2430 WIN_ReleaseWndPtr(pWndNewParent);
2431 WIN_ReleaseWndPtr(wndPtr);
2433 return retvalue;
2437 /*******************************************************************
2438 * IsChild16 (USER.48)
2440 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2442 return IsChild(parent,child);
2446 /*******************************************************************
2447 * IsChild (USER32.339)
2449 BOOL WINAPI IsChild( HWND parent, HWND child )
2451 WND * wndPtr = WIN_FindWndPtr( child );
2452 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2454 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2455 if (wndPtr->hwndSelf == parent)
2457 WIN_ReleaseWndPtr(wndPtr);
2458 return TRUE;
2461 WIN_ReleaseWndPtr(wndPtr);
2462 return FALSE;
2466 /***********************************************************************
2467 * IsWindowVisible16 (USER.49)
2469 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2471 return IsWindowVisible(hwnd);
2475 /***********************************************************************
2476 * IsWindowVisible (USER32.351)
2478 BOOL WINAPI IsWindowVisible( HWND hwnd )
2480 BOOL retval;
2481 WND *wndPtr = WIN_FindWndPtr( hwnd );
2482 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2484 if (!(wndPtr->dwStyle & WS_VISIBLE))
2486 WIN_ReleaseWndPtr(wndPtr);
2487 return FALSE;
2489 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2491 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2492 WIN_ReleaseWndPtr(wndPtr);
2493 return retval;
2498 /***********************************************************************
2499 * WIN_IsWindowDrawable
2501 * hwnd is drawable when it is visible, all parents are not
2502 * minimized, and it is itself not minimized unless we are
2503 * trying to draw its default class icon.
2505 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2507 if( (wnd->dwStyle & WS_MINIMIZE &&
2508 icon && wnd->class->hIcon) ||
2509 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2510 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2511 if( wnd->dwStyle & WS_MINIMIZE ||
2512 !(wnd->dwStyle & WS_VISIBLE) ) break;
2513 return (wnd == NULL);
2517 /*******************************************************************
2518 * GetTopWindow16 (USER.229)
2520 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2522 return GetTopWindow(hwnd);
2526 /*******************************************************************
2527 * GetTopWindow (USER.229)
2529 HWND WINAPI GetTopWindow( HWND hwnd )
2531 HWND retval = 0;
2532 WND * wndPtr = (hwnd) ?
2533 WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
2535 if (wndPtr && wndPtr->child)
2536 retval = wndPtr->child->hwndSelf;
2538 WIN_ReleaseWndPtr(wndPtr);
2539 return retval;
2543 /*******************************************************************
2544 * GetWindow16 (USER.262)
2546 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2548 return GetWindow( hwnd,rel );
2552 /*******************************************************************
2553 * GetWindow (USER32.302)
2555 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2557 HWND retval;
2559 WND * wndPtr = WIN_FindWndPtr( hwnd );
2560 if (!wndPtr) return 0;
2561 switch(rel)
2563 case GW_HWNDFIRST:
2564 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2565 goto end;
2567 case GW_HWNDLAST:
2568 if (!wndPtr->parent)
2570 retval = 0; /* Desktop window */
2571 goto end;
2573 while (wndPtr->next)
2575 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2577 retval = wndPtr->hwndSelf;
2578 goto end;
2580 case GW_HWNDNEXT:
2581 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2582 goto end;
2584 case GW_HWNDPREV:
2585 if (!wndPtr->parent)
2587 retval = 0; /* Desktop window */
2588 goto end;
2590 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2591 if (wndPtr->hwndSelf == hwnd)
2593 retval = 0; /* First in list */
2594 goto end;
2596 while (wndPtr->next)
2598 if (wndPtr->next->hwndSelf == hwnd)
2600 retval = wndPtr->hwndSelf;
2601 goto end;
2603 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2605 retval = 0;
2606 goto end;
2608 case GW_OWNER:
2609 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2610 goto end;
2612 case GW_CHILD:
2613 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2614 goto end;
2616 retval = 0;
2617 end:
2618 WIN_ReleaseWndPtr(wndPtr);
2619 return retval;
2623 /*******************************************************************
2624 * GetNextWindow16 (USER.230)
2626 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2628 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2629 return GetWindow16( hwnd, flag );
2632 /*******************************************************************
2633 * ShowOwnedPopups16 (USER.265)
2635 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2637 ShowOwnedPopups( owner, fShow );
2641 /*******************************************************************
2642 * ShowOwnedPopups (USER32.531)
2644 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2646 UINT totalChild=0, count=0;
2648 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2650 if (!pWnd) return TRUE;
2652 for (; count < totalChild; count++)
2654 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2656 if (fShow)
2658 if (pWnd[count]->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2660 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_SHOW, IsIconic(owner) ? SW_PARENTOPENING : SW_PARENTCLOSING);
2661 pWnd[count]->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2664 else
2666 if (IsWindowVisible(pWnd[count]->hwndSelf))
2668 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_HIDE, IsIconic(owner) ? SW_PARENTOPENING : SW_PARENTCLOSING);
2669 pWnd[count]->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2675 WIN_ReleaseDesktop();
2676 WIN_ReleaseWinArray(pWnd);
2677 return TRUE;
2681 /*******************************************************************
2682 * GetLastActivePopup16 (USER.287)
2684 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2686 return GetLastActivePopup( hwnd );
2689 /*******************************************************************
2690 * GetLastActivePopup (USER32.256)
2692 HWND WINAPI GetLastActivePopup( HWND hwnd )
2694 HWND retval;
2695 WND *wndPtr =WIN_FindWndPtr(hwnd);
2696 if (!wndPtr) return hwnd;
2697 retval = wndPtr->hwndLastActive;
2698 WIN_ReleaseWndPtr(wndPtr);
2699 return retval;
2703 /*******************************************************************
2704 * WIN_BuildWinArray
2706 * Build an array of pointers to the children of a given window.
2707 * The array must be freed with WIN_ReleaseWinArray. Return NULL
2708 * when no windows are found.
2710 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2712 /* Future: this function will lock all windows associated with this array */
2714 WND **list, **ppWnd;
2715 WND *pWnd;
2716 UINT count = 0, skipOwned, skipHidden;
2717 DWORD skipFlags;
2719 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2720 skipOwned = bwaFlags & BWA_SKIPOWNED;
2721 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2722 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2724 /* First count the windows */
2726 if (!wndPtr)
2727 wndPtr = WIN_GetDesktop();
2729 pWnd = WIN_LockWndPtr(wndPtr->child);
2730 while (pWnd)
2732 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2733 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2734 count++;
2735 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2738 if( count )
2740 /* Now build the list of all windows */
2742 if ((list = (WND **)HeapAlloc( GetProcessHeap(), 0, sizeof(WND *) * (count + 1))))
2744 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2746 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2747 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2749 *ppWnd++ = pWnd;
2750 count++;
2753 WIN_ReleaseWndPtr(pWnd);
2754 *ppWnd = NULL;
2756 else count = 0;
2757 } else list = NULL;
2759 if( pTotal ) *pTotal = count;
2760 return list;
2762 /*******************************************************************
2763 * WIN_ReleaseWinArray
2765 void WIN_ReleaseWinArray(WND **wndArray)
2767 /* Future: this function will also unlock all windows associated with wndArray */
2768 HeapFree( GetProcessHeap(), 0, wndArray );
2772 /*******************************************************************
2773 * EnumWindows (USER32.193)
2775 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2777 WND **list, **ppWnd;
2779 /* We have to build a list of all windows first, to avoid */
2780 /* unpleasant side-effects, for instance if the callback */
2781 /* function changes the Z-order of the windows. */
2783 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2785 WIN_ReleaseDesktop();
2786 return FALSE;
2789 /* Now call the callback function for every window */
2791 for (ppWnd = list; *ppWnd; ppWnd++)
2793 LRESULT lpEnumFuncRetval;
2794 int iWndsLocks = 0;
2795 /* Make sure that the window still exists */
2796 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2798 /* To avoid any deadlocks, all the locks on the windows
2799 structures must be suspended before the control
2800 is passed to the application */
2801 iWndsLocks = WIN_SuspendWndsLock();
2802 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2803 WIN_RestoreWndsLock(iWndsLocks);
2805 if (!lpEnumFuncRetval) break;
2807 WIN_ReleaseWinArray(list);
2808 WIN_ReleaseDesktop();
2809 return TRUE;
2813 /**********************************************************************
2814 * EnumTaskWindows16 (USER.225)
2816 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2817 LPARAM lParam )
2819 WND **list, **ppWnd;
2821 /* This function is the same as EnumWindows(), */
2822 /* except for an added check on the window's task. */
2824 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2826 WIN_ReleaseDesktop();
2827 return FALSE;
2830 /* Now call the callback function for every window */
2832 for (ppWnd = list; *ppWnd; ppWnd++)
2834 LRESULT funcRetval;
2835 int iWndsLocks = 0;
2836 /* Make sure that the window still exists */
2837 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2838 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2840 /* To avoid any deadlocks, all the locks on the windows
2841 structures must be suspended before the control
2842 is passed to the application */
2843 iWndsLocks = WIN_SuspendWndsLock();
2844 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2845 WIN_RestoreWndsLock(iWndsLocks);
2847 if (!funcRetval) break;
2849 WIN_ReleaseWinArray(list);
2850 WIN_ReleaseDesktop();
2851 return TRUE;
2855 /**********************************************************************
2856 * EnumThreadWindows (USER32.190)
2858 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2860 TEB *teb = THREAD_IdToTEB(id);
2862 return (BOOL16)EnumTaskWindows16(teb->htask16, (WNDENUMPROC16)func, lParam);
2866 /**********************************************************************
2867 * WIN_EnumChildWindows
2869 * Helper function for EnumChildWindows().
2871 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC func, LPARAM lParam )
2873 WND **childList;
2874 BOOL16 ret = FALSE;
2876 for ( ; *ppWnd; ppWnd++)
2878 int iWndsLocks = 0;
2880 /* Make sure that the window still exists */
2881 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2882 /* Build children list first */
2883 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2885 /* To avoid any deadlocks, all the locks on the windows
2886 structures must be suspended before the control
2887 is passed to the application */
2888 iWndsLocks = WIN_SuspendWndsLock();
2889 ret = func( (*ppWnd)->hwndSelf, lParam );
2890 WIN_RestoreWndsLock(iWndsLocks);
2892 if (childList)
2894 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2895 WIN_ReleaseWinArray(childList);
2897 if (!ret) return FALSE;
2899 return TRUE;
2903 /**********************************************************************
2904 * EnumChildWindows (USER32.178)
2906 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2907 LPARAM lParam )
2909 WND **list, *pParent;
2911 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2912 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2914 WIN_ReleaseWndPtr(pParent);
2915 return FALSE;
2917 WIN_EnumChildWindows( list, func, lParam );
2918 WIN_ReleaseWinArray(list);
2919 WIN_ReleaseWndPtr(pParent);
2920 return TRUE;
2924 /*******************************************************************
2925 * AnyPopup16 (USER.52)
2927 BOOL16 WINAPI AnyPopup16(void)
2929 return AnyPopup();
2933 /*******************************************************************
2934 * AnyPopup (USER32.4)
2936 BOOL WINAPI AnyPopup(void)
2938 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2939 BOOL retvalue;
2941 while (wndPtr)
2943 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2945 retvalue = TRUE;
2946 goto end;
2948 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2950 retvalue = FALSE;
2951 end:
2952 WIN_ReleaseWndPtr(wndPtr);
2953 return retvalue;
2957 /*******************************************************************
2958 * FlashWindow16 (USER.105)
2960 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2962 return FlashWindow( hWnd, bInvert );
2966 /*******************************************************************
2967 * FlashWindow (USER32.202)
2969 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2971 WND *wndPtr = WIN_FindWndPtr(hWnd);
2973 TRACE("%04x\n", hWnd);
2975 if (!wndPtr) return FALSE;
2977 if (wndPtr->dwStyle & WS_MINIMIZE)
2979 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2981 HDC hDC = GetDC(hWnd);
2983 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2984 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2986 ReleaseDC( hWnd, hDC );
2987 wndPtr->flags |= WIN_NCACTIVATED;
2989 else
2991 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2992 RDW_UPDATENOW | RDW_FRAME, 0 );
2993 wndPtr->flags &= ~WIN_NCACTIVATED;
2995 WIN_ReleaseWndPtr(wndPtr);
2996 return TRUE;
2998 else
3000 WPARAM16 wparam;
3001 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3002 else wparam = (hWnd == GetActiveWindow());
3004 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3005 WIN_ReleaseWndPtr(wndPtr);
3006 return wparam;
3011 /*******************************************************************
3012 * SetSysModalWindow16 (USER.188)
3014 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3016 HWND hWndOldModal = hwndSysModal;
3017 hwndSysModal = hWnd;
3018 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3019 return hWndOldModal;
3023 /*******************************************************************
3024 * GetSysModalWindow16 (USER.52)
3026 HWND16 WINAPI GetSysModalWindow16(void)
3028 return hwndSysModal;
3032 /*******************************************************************
3033 * GetWindowContextHelpId (USER32.303)
3035 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3037 DWORD retval;
3038 WND *wnd = WIN_FindWndPtr( hwnd );
3039 if (!wnd) return 0;
3040 retval = wnd->helpContext;
3041 WIN_ReleaseWndPtr(wnd);
3042 return retval;
3046 /*******************************************************************
3047 * SetWindowContextHelpId (USER32.515)
3049 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3051 WND *wnd = WIN_FindWndPtr( hwnd );
3052 if (!wnd) return FALSE;
3053 wnd->helpContext = id;
3054 WIN_ReleaseWndPtr(wnd);
3055 return TRUE;
3059 /*******************************************************************
3060 * DRAG_QueryUpdate
3062 * recursively find a child that contains spDragInfo->pt point
3063 * and send WM_QUERYDROPOBJECT
3065 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3067 BOOL16 wParam, bResult = 0;
3068 POINT pt;
3069 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
3070 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3071 RECT tempRect;
3073 if( !ptrQueryWnd || !ptrDragInfo )
3074 goto end;
3076 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3078 GetWindowRect(hQueryWnd,&tempRect);
3080 if( !PtInRect(&tempRect,pt) ||
3081 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3082 goto end;
3084 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3086 tempRect = ptrQueryWnd->rectClient;
3087 if(ptrQueryWnd->dwStyle & WS_CHILD)
3088 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3089 (LPPOINT)&tempRect, 2 );
3091 if (PtInRect( &tempRect, pt))
3093 wParam = 0;
3095 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3097 if( ptrWnd->dwStyle & WS_VISIBLE )
3099 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3100 if (PtInRect( &tempRect, pt )) break;
3104 if(ptrWnd)
3106 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3107 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3108 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3109 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3110 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3112 WIN_ReleaseWndPtr(ptrWnd);
3115 if(bResult)
3116 goto end;
3118 else wParam = 1;
3120 else wParam = 1;
3122 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3124 ptrDragInfo->hScope = hQueryWnd;
3126 bResult = ( bNoSend )
3127 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3128 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3129 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3130 if( !bResult )
3131 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3133 end:
3134 WIN_ReleaseWndPtr(ptrQueryWnd);
3135 return bResult;
3139 /*******************************************************************
3140 * DragDetect (USER.465)
3142 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3144 POINT pt32;
3145 CONV_POINT16TO32( &pt, &pt32 );
3146 return DragDetect( hWnd, pt32 );
3149 /*******************************************************************
3150 * DragDetect (USER32.151)
3152 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3154 MSG16 msg;
3155 RECT16 rect;
3157 rect.left = pt.x - wDragWidth;
3158 rect.right = pt.x + wDragWidth;
3160 rect.top = pt.y - wDragHeight;
3161 rect.bottom = pt.y + wDragHeight;
3163 SetCapture(hWnd);
3165 while(1)
3167 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3169 if( msg.message == WM_LBUTTONUP )
3171 ReleaseCapture();
3172 return 0;
3174 if( msg.message == WM_MOUSEMOVE )
3176 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
3178 ReleaseCapture();
3179 return 1;
3183 WaitMessage();
3185 return 0;
3188 /******************************************************************************
3189 * DragObject16 (USER.464)
3191 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3192 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3194 MSG16 msg;
3195 LPDRAGINFO lpDragInfo;
3196 SEGPTR spDragInfo;
3197 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3198 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
3199 WND *wndPtr = WIN_FindWndPtr(hWnd);
3200 HCURSOR16 hCurrentCursor = 0;
3201 HWND16 hCurrentWnd = 0;
3203 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
3204 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
3206 if( !lpDragInfo || !spDragInfo )
3208 WIN_ReleaseWndPtr(wndPtr);
3209 return 0L;
3212 hBummer = LoadCursor16(0, IDC_BUMMER16);
3214 if( !hBummer || !wndPtr )
3216 GlobalFree16(hDragInfo);
3217 WIN_ReleaseWndPtr(wndPtr);
3218 return 0L;
3221 if(hCursor)
3223 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3225 GlobalFree16(hDragInfo);
3226 WIN_ReleaseWndPtr(wndPtr);
3227 return 0L;
3230 if( hDragCursor == hCursor ) hDragCursor = 0;
3231 else hCursor = hDragCursor;
3233 hOldCursor = SetCursor(hDragCursor);
3236 lpDragInfo->hWnd = hWnd;
3237 lpDragInfo->hScope = 0;
3238 lpDragInfo->wFlags = wObj;
3239 lpDragInfo->hList = szList; /* near pointer! */
3240 lpDragInfo->hOfStruct = hOfStruct;
3241 lpDragInfo->l = 0L;
3243 SetCapture(hWnd);
3244 ShowCursor( TRUE );
3248 do{ WaitMessage(); }
3249 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3251 *(lpDragInfo+1) = *lpDragInfo;
3253 lpDragInfo->pt = msg.pt;
3255 /* update DRAGINFO struct */
3256 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3258 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3259 hCurrentCursor = hCursor;
3260 else
3262 hCurrentCursor = hBummer;
3263 lpDragInfo->hScope = 0;
3265 if( hCurrentCursor )
3266 SetCursor(hCurrentCursor);
3268 /* send WM_DRAGLOOP */
3269 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3270 (LPARAM) spDragInfo );
3271 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3272 if( hCurrentWnd != lpDragInfo->hScope )
3274 if( hCurrentWnd )
3275 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3276 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
3277 HIWORD(spDragInfo)) );
3278 hCurrentWnd = lpDragInfo->hScope;
3279 if( hCurrentWnd )
3280 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3282 else
3283 if( hCurrentWnd )
3284 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3286 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3288 ReleaseCapture();
3289 ShowCursor( FALSE );
3291 if( hCursor )
3293 SetCursor( hOldCursor );
3294 if (hDragCursor) DestroyCursor( hDragCursor );
3297 if( hCurrentCursor != hBummer )
3298 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3299 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3300 else
3301 msg.lParam = 0;
3302 GlobalFree16(hDragInfo);
3303 WIN_ReleaseWndPtr(wndPtr);
3305 return (DWORD)(msg.lParam);