Properly handling cases like calling SetWindowPos while processing
[wine/wine-kai.git] / windows / win.c
blob5dc7bea7d437a3b67cae2f6e661a24c49370b188
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include <string.h>
9 #include "wine/winbase16.h"
10 #include "options.h"
11 #include "class.h"
12 #include "win.h"
13 #include "heap.h"
14 #include "user.h"
15 #include "dce.h"
16 #include "sysmetrics.h"
17 #include "cursoricon.h"
18 #include "hook.h"
19 #include "menu.h"
20 #include "message.h"
21 #include "nonclient.h"
22 #include "queue.h"
23 #include "winpos.h"
24 #include "shm_main_blk.h"
25 #include "dde_proc.h"
26 #include "clipboard.h"
27 #include "winproc.h"
28 #include "task.h"
29 #include "thread.h"
30 #include "process.h"
31 #include "debug.h"
32 #include "winerror.h"
33 #include "mdi.h"
34 #include "local.h"
35 #include "desktop.h"
37 /**********************************************************************/
39 WND_DRIVER *WND_Driver = NULL;
41 /* Desktop window */
42 static WND *pWndDesktop = NULL;
44 static HWND hwndSysModal = 0;
46 static WORD wDragWidth = 4;
47 static WORD wDragHeight= 3;
49 /* thread safeness */
50 static CRITICAL_SECTION WIN_CritSection;
52 /***********************************************************************
53 * WIN_LockWnds
55 * Locks access to all WND structures for thread safeness
57 void WIN_LockWnds()
59 EnterCriticalSection(&WIN_CritSection);
62 /***********************************************************************
63 * WIN_UnlockWnds
65 * Unlocks access to all WND structures
67 void WIN_UnlockWnds()
69 LeaveCriticalSection(&WIN_CritSection);
71 /***********************************************************************
72 * WIN_SuspendWndsLock
74 * Suspend the lock on WND structures.
75 * Returns the number of locks suspended
77 int WIN_SuspendWndsLock()
79 int isuspendedLocks = 0;
81 /* make sure that the lock is not suspended by different thread than
82 the owning thread */
83 if(WIN_CritSection.OwningThread != GetCurrentThreadId())
85 return 0;
87 /* set the value of isuspendedlock to the actual recursion count
88 of the critical section */
89 isuspendedLocks = WIN_CritSection.RecursionCount;
90 /* set the recursion count of the critical section to 1
91 so the owning thread will be able to leave it */
92 WIN_CritSection.RecursionCount = 1;
93 /* leave critical section*/
94 WIN_UnlockWnds();
96 return isuspendedLocks;
99 /***********************************************************************
100 * WIN_RestoreWndsLock
102 * Restore the suspended locks on WND structures
104 void WIN_RestoreWndsLock(int ipreviousLocks)
106 if(!ipreviousLocks)
108 return;
110 /* restore the lock */
111 WIN_LockWnds();
112 /* set the recursion count of the critical section to the
113 value of suspended locks (given by WIN_SuspendWndsLock())*/
114 WIN_CritSection.RecursionCount = ipreviousLocks;
118 /***********************************************************************
119 * WIN_FindWndPtr
121 * Return a pointer to the WND structure corresponding to a HWND.
123 WND * WIN_FindWndPtr( HWND hwnd )
125 WND * ptr;
127 if (!hwnd || HIWORD(hwnd)) goto error2;
128 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
129 /* Lock all WND structures for thread safeness*/
130 WIN_LockWnds();
131 /*and increment destruction monitoring*/
132 ptr->irefCount++;
134 if (ptr->dwMagic != WND_MAGIC) goto error;
135 if (ptr->hwndSelf != hwnd)
137 ERR( win, "Can't happen: hwnd %04x self pointer is %04x\n",hwnd, ptr->hwndSelf );
138 goto error;
140 /* returns a locked pointer */
141 return ptr;
142 error:
143 /* Unlock all WND structures for thread safeness*/
144 WIN_UnlockWnds();
145 /* and decrement destruction monitoring value */
146 ptr->irefCount--;
148 error2:
149 if ( hwnd!=0 )
150 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
151 return NULL;
154 /***********************************************************************
155 * WIN_LockWndPtr
157 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
158 * but by initWndPtr;
159 * Returns the locked initialisation pointer
161 WND *WIN_LockWndPtr(WND *initWndPtr)
163 if(!initWndPtr) return 0;
165 /* Lock all WND structures for thread safeness*/
166 WIN_LockWnds();
167 /*and increment destruction monitoring*/
168 initWndPtr->irefCount++;
170 return initWndPtr;
174 /***********************************************************************
175 * WIN_ReleaseWndPtr
177 * Release the pointer to the WND structure.
179 void WIN_ReleaseWndPtr(WND *wndPtr)
181 if(!wndPtr) return;
183 /*Decrement destruction monitoring value*/
184 wndPtr->irefCount--;
185 /* Check if it's time to release the memory*/
186 /* Check if it's time to release the memory*/
187 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
189 /* Release memory */
190 USER_HEAP_FREE( wndPtr->hwndSelf);
192 else if(wndPtr->irefCount < 0)
194 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
195 TRACE(win,"forgot a Lock on %p somewhere\n",wndPtr);
197 /*unlock all WND structures for thread safeness*/
198 WIN_UnlockWnds();
201 /***********************************************************************
202 * WIN_UpdateWndPtr
204 * Updates the value of oldPtr to newPtr.
206 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
208 WND *tmpWnd = NULL;
210 tmpWnd = WIN_LockWndPtr(newPtr);
211 WIN_ReleaseWndPtr(*oldPtr);
212 *oldPtr = tmpWnd;
216 /***********************************************************************
217 * WIN_DumpWindow
219 * Dump the content of a window structure to stderr.
221 void WIN_DumpWindow( HWND hwnd )
223 WND *ptr;
224 char className[80];
225 int i;
227 if (!(ptr = WIN_FindWndPtr( hwnd )))
229 WARN( win, "%04x is not a window handle\n", hwnd );
230 return;
233 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
234 strcpy( className, "#NULL#" );
236 TRACE( win, "Window %04x (%p):\n", hwnd, ptr );
237 DUMP( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
238 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
239 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
240 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
241 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
242 ptr->next, ptr->child, ptr->parent, ptr->owner,
243 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
244 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
245 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
246 ptr->text ? ptr->text : "",
247 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
248 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
249 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
250 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
252 if (ptr->class->cbWndExtra)
254 DUMP( "extra bytes:" );
255 for (i = 0; i < ptr->class->cbWndExtra; i++)
256 DUMP( " %02x", *((BYTE*)ptr->wExtra+i) );
257 DUMP( "\n" );
259 DUMP( "\n" );
260 WIN_ReleaseWndPtr(ptr);
264 /***********************************************************************
265 * WIN_WalkWindows
267 * Walk the windows tree and print each window on stderr.
269 void WIN_WalkWindows( HWND hwnd, int indent )
271 WND *ptr;
272 char className[80];
274 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
276 if (!ptr)
278 WARN( win, "Invalid window handle %04x\n", hwnd );
279 return;
282 if (!indent) /* first time around */
283 DUMP( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
284 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
285 " Text");
287 while (ptr)
289 DUMP( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
291 GlobalGetAtomName16(ptr->class->atomName,className,sizeof(className));
293 DUMP( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
294 (DWORD)ptr, ptr->hmemTaskQ, className,
295 (UINT)ptr->dwStyle, (UINT)ptr->winproc,
296 ptr->text?ptr->text:"<null>");
298 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
299 WIN_UpdateWndPtr(&ptr,ptr->next);
305 /***********************************************************************
306 * WIN_UnlinkWindow
308 * Remove a window from the siblings linked list.
310 BOOL WIN_UnlinkWindow( HWND hwnd )
312 WND *wndPtr, **ppWnd;
313 BOOL ret = FALSE;
315 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
316 else if(!wndPtr->parent)
318 WIN_ReleaseWndPtr(wndPtr);
319 return FALSE;
322 ppWnd = &wndPtr->parent->child;
323 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
324 if (*ppWnd)
326 *ppWnd = wndPtr->next;
327 ret = TRUE;
329 WIN_ReleaseWndPtr(wndPtr);
330 return ret;
334 /***********************************************************************
335 * WIN_LinkWindow
337 * Insert a window into the siblings linked list.
338 * The window is inserted after the specified window, which can also
339 * be specified as HWND_TOP or HWND_BOTTOM.
341 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
343 WND *wndPtr, **ppWnd;
345 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
346 else if(!wndPtr->parent)
348 WIN_ReleaseWndPtr(wndPtr);
349 return FALSE;
351 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
353 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
354 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
355 while (*ppWnd) ppWnd = &(*ppWnd)->next;
357 else /* Normal case */
359 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
360 if (!afterPtr)
362 WIN_ReleaseWndPtr(wndPtr);
363 return FALSE;
365 ppWnd = &afterPtr->next;
366 WIN_ReleaseWndPtr(afterPtr);
368 wndPtr->next = *ppWnd;
369 *ppWnd = wndPtr;
370 WIN_ReleaseWndPtr(wndPtr);
371 return TRUE;
375 /***********************************************************************
376 * WIN_FindWinToRepaint
378 * Find a window that needs repaint.
380 HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE16 hQueue )
382 HWND hwndRet;
383 WND *pWnd;
385 /* Note: the desktop window never gets WM_PAINT messages
386 * The real reason why is because Windows DesktopWndProc
387 * does ValidateRgn inside WM_ERASEBKGND handler.
390 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
392 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
394 if (!(pWnd->dwStyle & WS_VISIBLE))
396 TRACE(win, "skipping window %04x\n",
397 pWnd->hwndSelf );
399 else if ((pWnd->hmemTaskQ == hQueue) &&
400 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)))
401 break;
403 else if (pWnd->child )
404 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
406 WIN_ReleaseWndPtr(pWnd);
407 return hwndRet;
412 if(!pWnd)
414 return 0;
417 hwndRet = pWnd->hwndSelf;
419 /* look among siblings if we got a transparent window */
420 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
421 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
423 WIN_UpdateWndPtr(&pWnd,pWnd->next);
425 if (pWnd)
427 hwndRet = pWnd->hwndSelf;
428 WIN_ReleaseWndPtr(pWnd);
430 TRACE(win,"found %04x\n",hwndRet);
431 return hwndRet;
435 /***********************************************************************
436 * WIN_DestroyWindow
438 * Destroy storage associated to a window. "Internals" p.358
439 * returns a locked wndPtr->next
441 static WND* WIN_DestroyWindow( WND* wndPtr )
443 HWND hwnd = wndPtr->hwndSelf;
444 WND *pWnd;
446 TRACE(win, "%04x\n", wndPtr->hwndSelf );
448 #ifdef CONFIG_IPC
449 if (main_block)
450 DDE_DestroyWindow(wndPtr->hwndSelf);
451 #endif /* CONFIG_IPC */
453 /* free child windows */
454 WIN_LockWndPtr(wndPtr->child);
455 while ((pWnd = wndPtr->child))
457 wndPtr->child = WIN_DestroyWindow( pWnd );
458 WIN_ReleaseWndPtr(pWnd);
462 * Clear the update region to make sure no WM_PAINT messages will be
463 * generated for this window while processing the WM_NCDESTROY.
465 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
467 if (wndPtr->hrgnUpdate > 1)
468 DeleteObject( wndPtr->hrgnUpdate );
470 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
472 wndPtr->hrgnUpdate = 0;
476 * Send the WM_NCDESTROY to the window being destroyed.
478 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
480 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
482 WINPOS_CheckInternalPos( wndPtr );
483 if( hwnd == GetCapture()) ReleaseCapture();
485 /* free resources associated with the window */
487 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
488 PROPERTY_RemoveWindowProps( wndPtr );
490 wndPtr->dwMagic = 0; /* Mark it as invalid */
492 /* toss stale messages from the queue */
494 if( wndPtr->hmemTaskQ )
496 BOOL bPostQuit = FALSE;
497 WPARAM wQuitParam = 0;
498 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) QUEUE_Lock(wndPtr->hmemTaskQ);
499 QMSG *qmsg;
501 while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
503 if( qmsg->msg.message == WM_QUIT )
505 bPostQuit = TRUE;
506 wQuitParam = qmsg->msg.wParam;
508 QUEUE_RemoveMsg(msgQ, qmsg);
511 QUEUE_Unlock(msgQ);
513 /* repost WM_QUIT to make sure this app exits its message loop */
514 if( bPostQuit ) PostQuitMessage(wQuitParam);
515 wndPtr->hmemTaskQ = 0;
518 if (!(wndPtr->dwStyle & WS_CHILD))
519 if (wndPtr->wIDmenu) DestroyMenu( (HMENU)wndPtr->wIDmenu );
520 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
521 wndPtr->pDriver->pDestroyWindow( wndPtr );
522 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
523 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
524 wndPtr->hwndSelf = 0;
525 wndPtr->class->cWindows--;
526 wndPtr->class = NULL;
528 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
530 wndPtr->pDriver->pFinalize(wndPtr);
532 return pWnd;
535 /***********************************************************************
536 * WIN_ResetQueueWindows
538 * Reset the queue of all the children of a given window.
539 * Return TRUE if something was done.
541 BOOL WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
543 BOOL ret = FALSE;
545 if (hNew) /* Set a new queue */
547 for (wnd = WIN_LockWndPtr(wnd->child); (wnd);WIN_UpdateWndPtr(&wnd,wnd->next))
549 if (wnd->hmemTaskQ == hQueue)
551 wnd->hmemTaskQ = hNew;
552 ret = TRUE;
554 if (wnd->child)
556 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
560 else /* Queue is being destroyed */
562 while (wnd->child)
564 WND *tmp = WIN_LockWndPtr(wnd->child);
565 WND *tmp2;
566 ret = FALSE;
567 while (tmp)
569 if (tmp->hmemTaskQ == hQueue)
571 DestroyWindow( tmp->hwndSelf );
572 ret = TRUE;
573 break;
575 tmp2 = WIN_LockWndPtr(tmp->child);
576 if (tmp2 && WIN_ResetQueueWindows(tmp2,hQueue,0))
577 ret = TRUE;
578 else
580 WIN_UpdateWndPtr(&tmp,tmp->next);
582 WIN_ReleaseWndPtr(tmp2);
584 WIN_ReleaseWndPtr(tmp);
585 if (!ret) break;
588 return ret;
591 /***********************************************************************
592 * WIN_CreateDesktopWindow
594 * Create the desktop window.
596 BOOL WIN_CreateDesktopWindow(void)
598 CLASS *class;
599 HWND hwndDesktop;
600 DESKTOP *pDesktop;
602 TRACE(win,"Creating desktop window\n");
605 /* Initialisation of the critical section for thread safeness */
606 InitializeCriticalSection(&WIN_CritSection);
607 MakeCriticalSectionGlobal(&WIN_CritSection);
609 if (!ICONTITLE_Init() ||
610 !WINPOS_CreateInternalPosAtom() ||
611 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
612 return FALSE;
614 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
615 if (!hwndDesktop) return FALSE;
616 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
618 pDesktop = (DESKTOP *) pWndDesktop->wExtra;
619 pDesktop->pDriver = DESKTOP_Driver;
620 pWndDesktop->pDriver = WND_Driver;
622 pDesktop->pDriver->pInitialize(pDesktop);
623 pWndDesktop->pDriver->pInitialize(pWndDesktop);
625 pWndDesktop->next = NULL;
626 pWndDesktop->child = NULL;
627 pWndDesktop->parent = NULL;
628 pWndDesktop->owner = NULL;
629 pWndDesktop->class = class;
630 pWndDesktop->dwMagic = WND_MAGIC;
631 pWndDesktop->hwndSelf = hwndDesktop;
632 pWndDesktop->hInstance = 0;
633 pWndDesktop->rectWindow.left = 0;
634 pWndDesktop->rectWindow.top = 0;
635 pWndDesktop->rectWindow.right = SYSMETRICS_CXSCREEN;
636 pWndDesktop->rectWindow.bottom = SYSMETRICS_CYSCREEN;
637 pWndDesktop->rectClient = pWndDesktop->rectWindow;
638 pWndDesktop->text = NULL;
639 pWndDesktop->hmemTaskQ = GetFastQueue16();
640 pWndDesktop->hrgnUpdate = 0;
641 pWndDesktop->hwndLastActive = hwndDesktop;
642 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
643 WS_CLIPSIBLINGS;
644 pWndDesktop->dwExStyle = 0;
645 pWndDesktop->dce = NULL;
646 pWndDesktop->pVScroll = NULL;
647 pWndDesktop->pHScroll = NULL;
648 pWndDesktop->pProp = NULL;
649 pWndDesktop->wIDmenu = 0;
650 pWndDesktop->helpContext = 0;
651 pWndDesktop->flags = 0;
652 pWndDesktop->hSysMenu = 0;
653 pWndDesktop->userdata = 0;
654 pWndDesktop->winproc = (WNDPROC16)class->winproc;
655 pWndDesktop->irefCount = 0;
657 /* FIXME: How do we know if it should be Unicode or not */
658 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop, class, FALSE))
659 return FALSE;
661 SendMessageA( hwndDesktop, WM_NCCREATE, 0, 0 );
662 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
663 return TRUE;
667 /***********************************************************************
668 * WIN_CreateWindowEx
670 * Implementation of CreateWindowEx().
672 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
673 BOOL win32, BOOL unicode )
675 CLASS *classPtr;
676 WND *wndPtr;
677 HWND retvalue;
678 HWND16 hwnd, hwndLinkAfter;
679 POINT maxSize, maxPos, minTrack, maxTrack;
680 LRESULT (CALLBACK *localSend32)(HWND, UINT, WPARAM, LPARAM);
681 char buffer[256];
683 TRACE(win, "%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
684 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
685 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
686 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
687 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
689 /* Find the parent window */
691 if (cs->hwndParent)
693 /* Make sure parent is valid */
694 if (!IsWindow( cs->hwndParent ))
696 WARN( win, "Bad parent %04x\n", cs->hwndParent );
697 return 0;
699 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
700 WARN( win, "No parent for child window\n" );
701 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
704 /* Find the window class */
705 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
707 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
708 WARN( win, "Bad class '%s'\n", buffer );
709 return 0;
712 /* Fix the lpszClass field: from existing programs, it seems ok to call a CreateWindowXXX
713 * with an atom as the class name, put some programs expect to have a *REAL* string in
714 * lpszClass when the CREATESTRUCT is sent with WM_CREATE
716 if ( !HIWORD(cs->lpszClass) ) {
717 if (unicode) {
718 GlobalGetAtomNameW( classAtom, (LPWSTR)buffer, sizeof(buffer) );
719 } else {
720 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
722 cs->lpszClass = buffer;
725 /* Fix the coordinates */
727 if (cs->x == CW_USEDEFAULT)
729 PDB *pdb = PROCESS_Current();
730 if ( !(cs->style & (WS_CHILD | WS_POPUP))
731 && (pdb->env_db->startup_info->dwFlags & STARTF_USEPOSITION) )
733 cs->x = pdb->env_db->startup_info->dwX;
734 cs->y = pdb->env_db->startup_info->dwY;
736 else
738 cs->x = 0;
739 cs->y = 0;
742 if (cs->cx == CW_USEDEFAULT)
744 PDB *pdb = PROCESS_Current();
745 if ( !(cs->style & (WS_CHILD | WS_POPUP))
746 && (pdb->env_db->startup_info->dwFlags & STARTF_USESIZE) )
748 cs->cx = pdb->env_db->startup_info->dwXSize;
749 cs->cy = pdb->env_db->startup_info->dwYSize;
751 else
753 cs->cx = 600; /* FIXME */
754 cs->cy = 400;
758 /* Create the window structure */
760 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
761 - sizeof(wndPtr->wExtra) )))
763 TRACE(win, "out of memory\n" );
764 return 0;
767 /* Fill the window structure */
769 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
770 wndPtr->next = NULL;
771 wndPtr->child = NULL;
773 if ((cs->style & WS_CHILD) && cs->hwndParent)
775 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
776 wndPtr->owner = NULL;
777 WIN_ReleaseWndPtr(wndPtr->parent);
779 else
781 wndPtr->parent = pWndDesktop;
782 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
783 wndPtr->owner = NULL;
784 else
786 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
787 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
788 WIN_ReleaseWndPtr(wndPtr->owner);
789 WIN_ReleaseWndPtr(tmpWnd);
793 wndPtr->pDriver = wndPtr->parent->pDriver;
794 wndPtr->pDriver->pInitialize(wndPtr);
796 wndPtr->class = classPtr;
797 wndPtr->winproc = classPtr->winproc;
798 wndPtr->dwMagic = WND_MAGIC;
799 wndPtr->hwndSelf = hwnd;
800 wndPtr->hInstance = cs->hInstance;
801 wndPtr->text = NULL;
802 wndPtr->hmemTaskQ = GetFastQueue16();
803 wndPtr->hrgnUpdate = 0;
804 wndPtr->hwndLastActive = hwnd;
805 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
806 wndPtr->dwExStyle = cs->dwExStyle;
807 wndPtr->wIDmenu = 0;
808 wndPtr->helpContext = 0;
809 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
810 wndPtr->pVScroll = NULL;
811 wndPtr->pHScroll = NULL;
812 wndPtr->pProp = NULL;
813 wndPtr->userdata = 0;
814 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
815 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
816 wndPtr->irefCount = 1;
818 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
820 /* Call the WH_CBT hook */
822 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
823 ? HWND_BOTTOM : HWND_TOP;
825 if (HOOK_IsHooked( WH_CBT ))
827 CBT_CREATEWNDA cbtc;
828 LRESULT ret;
830 cbtc.lpcs = cs;
831 cbtc.hwndInsertAfter = hwndLinkAfter;
832 ret = unicode ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
833 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
834 if (ret)
836 TRACE(win, "CBT-hook returned 0\n");
837 wndPtr->pDriver->pFinalize(wndPtr);
838 USER_HEAP_FREE( hwnd );
839 retvalue = 0;
840 goto end;
844 /* Increment class window counter */
846 classPtr->cWindows++;
848 /* Correct the window style */
850 if (!(cs->style & WS_CHILD))
852 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
853 if (!(cs->style & WS_POPUP))
855 wndPtr->dwStyle |= WS_CAPTION;
856 wndPtr->flags |= WIN_NEED_SIZE;
859 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
861 /* Get class or window DC if needed */
863 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
864 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
865 else wndPtr->dce = NULL;
867 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
869 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
871 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
872 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
873 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
874 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
875 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
878 if(cs->style & WS_CHILD)
880 if(cs->cx < 0) cs->cx = 0;
881 if(cs->cy < 0) cs->cy = 0;
883 else
885 if (cs->cx <= 0) cs->cx = 1;
886 if (cs->cy <= 0) cs->cy = 1;
889 wndPtr->rectWindow.left = cs->x;
890 wndPtr->rectWindow.top = cs->y;
891 wndPtr->rectWindow.right = cs->x + cs->cx;
892 wndPtr->rectWindow.bottom = cs->y + cs->cy;
893 wndPtr->rectClient = wndPtr->rectWindow;
895 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
897 retvalue = FALSE;
898 goto end;
901 /* Set the window menu */
903 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
905 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
906 else
908 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
909 if (classPtr->menuNameA)
910 cs->hMenu = HIWORD(classPtr->menuNameA) ?
911 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
912 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
913 #else
914 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
915 if (menuName)
917 if (HIWORD(cs->hInstance))
918 cs->hMenu = LoadMenuA(cs->hInstance,PTR_SEG_TO_LIN(menuName));
919 else
920 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
922 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
924 #endif
927 else wndPtr->wIDmenu = (UINT)cs->hMenu;
929 /* Send the WM_CREATE message
930 * Perhaps we shouldn't allow width/height changes as well.
931 * See p327 in "Internals".
934 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
936 localSend32 = unicode ? SendMessageW : SendMessageA;
937 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
939 /* Insert the window in the linked list */
941 WIN_LinkWindow( hwnd, hwndLinkAfter );
943 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
944 NULL, NULL, 0, &wndPtr->rectClient );
945 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
946 maxPos.y - wndPtr->rectWindow.top);
947 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
949 /* Send the size messages */
951 if (!(wndPtr->flags & WIN_NEED_SIZE))
953 /* send it anyway */
954 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
955 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
956 WARN(win,"sending bogus WM_SIZE message 0x%08lx\n",
957 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
958 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
959 SendMessageA( hwnd, WM_SIZE, SIZE_RESTORED,
960 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
961 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
962 SendMessageA( hwnd, WM_MOVE, 0,
963 MAKELONG( wndPtr->rectClient.left,
964 wndPtr->rectClient.top ) );
967 /* Show the window, maximizing or minimizing if needed */
969 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
971 RECT16 newPos;
972 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
973 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
974 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
975 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
976 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
977 : SWP_NOZORDER | SWP_FRAMECHANGED;
978 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
979 newPos.right, newPos.bottom, swFlag );
982 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
984 /* Notify the parent window only */
986 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
987 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
988 if( !IsWindow(hwnd) )
990 retvalue = 0;
991 goto end;
995 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
997 /* Call WH_SHELL hook */
999 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1000 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
1002 TRACE(win, "created window %04x\n", hwnd);
1003 retvalue = hwnd;
1004 goto end;
1006 WIN_UnlinkWindow( hwnd );
1009 /* Abort window creation */
1011 WARN(win, "aborted by WM_xxCREATE!\n");
1012 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1013 retvalue = 0;
1014 end:
1015 WIN_ReleaseWndPtr(wndPtr);
1017 return retvalue;
1021 /***********************************************************************
1022 * CreateWindow16 (USER.41)
1024 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1025 DWORD style, INT16 x, INT16 y, INT16 width,
1026 INT16 height, HWND16 parent, HMENU16 menu,
1027 HINSTANCE16 instance, LPVOID data )
1029 return CreateWindowEx16( 0, className, windowName, style,
1030 x, y, width, height, parent, menu, instance, data );
1034 /***********************************************************************
1035 * CreateWindowEx16 (USER.452)
1037 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1038 LPCSTR windowName, DWORD style, INT16 x,
1039 INT16 y, INT16 width, INT16 height,
1040 HWND16 parent, HMENU16 menu,
1041 HINSTANCE16 instance, LPVOID data )
1043 ATOM classAtom;
1044 CREATESTRUCTA cs;
1046 /* Find the class atom */
1048 if (!(classAtom = GlobalFindAtomA( className )))
1050 fprintf( stderr, "CreateWindowEx16: bad class name " );
1051 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
1052 else fprintf( stderr, "'%s'\n", className );
1053 return 0;
1056 /* Fix the coordinates */
1058 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1059 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1060 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1061 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1063 /* Create the window */
1065 cs.lpCreateParams = data;
1066 cs.hInstance = (HINSTANCE)instance;
1067 cs.hMenu = (HMENU)menu;
1068 cs.hwndParent = (HWND)parent;
1069 cs.style = style;
1070 cs.lpszName = windowName;
1071 cs.lpszClass = className;
1072 cs.dwExStyle = exStyle;
1073 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
1077 /***********************************************************************
1078 * CreateWindowEx32A (USER32.83)
1080 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1081 LPCSTR windowName, DWORD style, INT x,
1082 INT y, INT width, INT height,
1083 HWND parent, HMENU menu,
1084 HINSTANCE instance, LPVOID data )
1086 ATOM classAtom;
1087 CREATESTRUCTA cs;
1089 if(exStyle & WS_EX_MDICHILD)
1090 return MDI_CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1091 /* Find the class atom */
1093 if (!(classAtom = GlobalFindAtomA( className )))
1095 fprintf( stderr, "CreateWindowEx32A: bad class name " );
1096 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
1097 else fprintf( stderr, "'%s'\n", className );
1098 return 0;
1101 /* Create the window */
1103 cs.lpCreateParams = data;
1104 cs.hInstance = instance;
1105 cs.hMenu = menu;
1106 cs.hwndParent = parent;
1107 cs.x = x;
1108 cs.y = y;
1109 cs.cx = width;
1110 cs.cy = height;
1111 cs.style = style;
1112 cs.lpszName = windowName;
1113 cs.lpszClass = className;
1114 cs.dwExStyle = exStyle;
1115 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
1119 /***********************************************************************
1120 * CreateWindowEx32W (USER32.84)
1122 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1123 LPCWSTR windowName, DWORD style, INT x,
1124 INT y, INT width, INT height,
1125 HWND parent, HMENU menu,
1126 HINSTANCE instance, LPVOID data )
1128 ATOM classAtom;
1129 CREATESTRUCTW cs;
1131 if(exStyle & WS_EX_MDICHILD)
1132 return MDI_CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1134 /* Find the class atom */
1136 if (!(classAtom = GlobalFindAtomW( className )))
1138 if (HIWORD(className))
1140 LPSTR cn = HEAP_strdupWtoA( GetProcessHeap(), 0, className );
1141 WARN( win, "Bad class name '%s'\n",cn);
1142 HeapFree( GetProcessHeap(), 0, cn );
1144 else
1145 WARN( win, "Bad class name %p\n", className );
1146 return 0;
1149 /* Create the window */
1151 cs.lpCreateParams = data;
1152 cs.hInstance = instance;
1153 cs.hMenu = menu;
1154 cs.hwndParent = parent;
1155 cs.x = x;
1156 cs.y = y;
1157 cs.cx = width;
1158 cs.cy = height;
1159 cs.style = style;
1160 cs.lpszName = windowName;
1161 cs.lpszClass = className;
1162 cs.dwExStyle = exStyle;
1163 /* Note: we rely on the fact that CREATESTRUCT32A and */
1164 /* CREATESTRUCT32W have the same layout. */
1165 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, TRUE, TRUE );
1169 /***********************************************************************
1170 * WIN_CheckFocus
1172 static void WIN_CheckFocus( WND* pWnd )
1174 if( GetFocus16() == pWnd->hwndSelf )
1175 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
1178 /***********************************************************************
1179 * WIN_SendDestroyMsg
1181 static void WIN_SendDestroyMsg( WND* pWnd )
1183 WIN_CheckFocus(pWnd);
1185 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1186 CLIPBOARD_Driver->pResetOwner( pWnd, TRUE );
1189 * Send the WM_DESTROY to the window.
1191 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1194 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1195 * make sure that the window still exists when we come back.
1197 if (IsWindow(pWnd->hwndSelf))
1199 HWND* pWndArray = NULL;
1200 WND* pChild = NULL;
1201 int nKidCount = 0;
1204 * Now, if the window has kids, we have to send WM_DESTROY messages
1205 * recursively to it's kids. It seems that those calls can also
1206 * trigger re-entrant calls to DestroyWindow for the kids so we must
1207 * protect against corruption of the list of siblings. We first build
1208 * a list of HWNDs representing all the kids.
1210 pChild = WIN_LockWndPtr(pWnd->child);
1211 while( pChild )
1213 nKidCount++;
1214 WIN_UpdateWndPtr(&pChild,pChild->next);
1218 * If there are no kids, we're done.
1220 if (nKidCount==0)
1221 return;
1223 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1226 * Sanity check
1228 if (pWndArray==NULL)
1229 return;
1232 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1233 * call, our linked list of siblings should be safe.
1235 nKidCount = 0;
1236 pChild = WIN_LockWndPtr(pWnd->child);
1237 while( pChild )
1239 pWndArray[nKidCount] = pChild->hwndSelf;
1240 nKidCount++;
1241 WIN_UpdateWndPtr(&pChild,pChild->next);
1245 * Now that we have a list, go through that list again and send the destroy
1246 * message to those windows. We are using the HWND to retrieve the
1247 * WND pointer so we are effectively checking that all the kid windows are
1248 * still valid before sending the message.
1250 while (nKidCount>0)
1252 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1254 if (pChild!=NULL)
1256 WIN_SendDestroyMsg( pChild );
1257 WIN_ReleaseWndPtr(pChild);
1262 * Cleanup
1264 HeapFree(GetProcessHeap(), 0, pWndArray);
1265 WIN_CheckFocus(pWnd);
1267 else
1268 WARN(win, "\tdestroyed itself while in WM_DESTROY!\n");
1272 /***********************************************************************
1273 * DestroyWindow16 (USER.53)
1275 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1277 return DestroyWindow(hwnd);
1281 /***********************************************************************
1282 * DestroyWindow32 (USER32.135)
1284 BOOL WINAPI DestroyWindow( HWND hwnd )
1286 WND * wndPtr;
1287 BOOL retvalue;
1289 TRACE(win, "(%04x)\n", hwnd);
1291 /* Initialization */
1293 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1294 if (wndPtr == pWndDesktop)
1296 WIN_ReleaseWndPtr(wndPtr);
1297 return FALSE; /* Can't destroy desktop */
1300 /* Call hooks */
1302 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1304 retvalue = FALSE;
1305 goto end;
1308 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1310 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1311 /* FIXME: clean up palette - see "Internals" p.352 */
1314 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1315 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1317 /* Notify the parent window only */
1318 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1319 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1320 if( !IsWindow(hwnd) )
1322 retvalue = TRUE;
1323 goto end;
1327 CLIPBOARD_Driver->pResetOwner( wndPtr, FALSE ); /* before the window is unmapped */
1329 /* Hide the window */
1331 if (wndPtr->dwStyle & WS_VISIBLE)
1333 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1334 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1335 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1336 if (!IsWindow(hwnd))
1338 retvalue = TRUE;
1339 goto end;
1343 /* Recursively destroy owned windows */
1345 if( !(wndPtr->dwStyle & WS_CHILD) )
1347 /* make sure top menu popup doesn't get destroyed */
1348 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1350 for (;;)
1352 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1353 while (siblingPtr)
1355 if (siblingPtr->owner == wndPtr)
1357 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1358 break;
1359 else
1360 siblingPtr->owner = NULL;
1362 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1364 if (siblingPtr)
1366 DestroyWindow( siblingPtr->hwndSelf );
1367 WIN_ReleaseWndPtr(siblingPtr);
1369 else break;
1372 if( !Options.managed || EVENT_CheckFocus() )
1373 WINPOS_ActivateOtherWindow(wndPtr);
1375 if( wndPtr->owner &&
1376 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1377 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1380 /* Send destroy messages */
1382 WIN_SendDestroyMsg( wndPtr );
1383 if (!IsWindow(hwnd))
1385 retvalue = TRUE;
1386 goto end;
1389 /* Unlink now so we won't bother with the children later on */
1391 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1393 /* Destroy the window storage */
1395 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1396 retvalue = TRUE;
1397 end:
1398 WIN_ReleaseWndPtr(wndPtr);
1399 return retvalue;
1403 /***********************************************************************
1404 * CloseWindow16 (USER.43)
1406 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1408 return CloseWindow( hwnd );
1412 /***********************************************************************
1413 * CloseWindow32 (USER32.56)
1415 BOOL WINAPI CloseWindow( HWND hwnd )
1417 WND * wndPtr = WIN_FindWndPtr( hwnd );
1418 BOOL retvalue;
1420 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1422 retvalue = FALSE;
1423 goto end;
1425 ShowWindow( hwnd, SW_MINIMIZE );
1426 retvalue = TRUE;
1427 end:
1428 WIN_ReleaseWndPtr(wndPtr);
1429 return retvalue;
1434 /***********************************************************************
1435 * OpenIcon16 (USER.44)
1437 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1439 return OpenIcon( hwnd );
1443 /***********************************************************************
1444 * OpenIcon32 (USER32.410)
1446 BOOL WINAPI OpenIcon( HWND hwnd )
1448 if (!IsIconic( hwnd )) return FALSE;
1449 ShowWindow( hwnd, SW_SHOWNORMAL );
1450 return TRUE;
1454 /***********************************************************************
1455 * WIN_FindWindow
1457 * Implementation of FindWindow() and FindWindowEx().
1459 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1460 LPCSTR title )
1462 WND *pWnd;
1463 HWND retvalue;
1464 CLASS *pClass = NULL;
1466 if (child)
1468 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1469 if (parent)
1471 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1473 retvalue = 0;
1474 goto end;
1477 else if (pWnd->parent != pWndDesktop)
1479 retvalue = 0;
1480 goto end;
1482 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1484 else
1486 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1488 retvalue = 0;
1489 goto end;
1491 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1493 if (!pWnd)
1495 retvalue = 0;
1496 goto end;
1499 /* For a child window, all siblings will have the same hInstance, */
1500 /* so we can look for the class once and for all. */
1502 if (className && (pWnd->dwStyle & WS_CHILD))
1504 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1506 retvalue = 0;
1507 goto end;
1512 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1514 if (className && !(pWnd->dwStyle & WS_CHILD))
1516 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance)))
1517 continue; /* Skip this window */
1520 if (pClass && (pWnd->class != pClass))
1521 continue; /* Not the right class */
1523 /* Now check the title */
1525 if (!title)
1527 retvalue = pWnd->hwndSelf;
1528 goto end;
1530 if (pWnd->text && !strcmp( pWnd->text, title ))
1532 retvalue = pWnd->hwndSelf;
1533 goto end;
1536 retvalue = 0;
1537 end:
1538 WIN_ReleaseWndPtr(pWnd);
1539 return retvalue;
1544 /***********************************************************************
1545 * FindWindow16 (USER.50)
1547 HWND16 WINAPI FindWindow16( SEGPTR className, LPCSTR title )
1549 return FindWindowEx16( 0, 0, className, title );
1553 /***********************************************************************
1554 * FindWindowEx16 (USER.427)
1556 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child,
1557 SEGPTR className, LPCSTR title )
1559 ATOM atom = 0;
1561 TRACE(win, "%04x %04x '%s' '%s'\n", parent,
1562 child, HIWORD(className)?(char *)PTR_SEG_TO_LIN(className):"",
1563 title ? title : "");
1565 if (className)
1567 /* If the atom doesn't exist, then no class */
1568 /* with this name exists either. */
1569 if (!(atom = GlobalFindAtom16( className ))) return 0;
1571 return WIN_FindWindow( parent, child, atom, title );
1575 /***********************************************************************
1576 * FindWindow32A (USER32.198)
1578 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1580 HWND ret = FindWindowExA( 0, 0, className, title );
1581 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1582 return ret;
1586 /***********************************************************************
1587 * FindWindowEx32A (USER32.199)
1589 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1590 LPCSTR className, LPCSTR title )
1592 ATOM atom = 0;
1594 if (className)
1596 /* If the atom doesn't exist, then no class */
1597 /* with this name exists either. */
1598 if (!(atom = GlobalFindAtomA( className )))
1600 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1601 return 0;
1604 return WIN_FindWindow( parent, child, atom, title );
1608 /***********************************************************************
1609 * FindWindowEx32W (USER32.200)
1611 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1612 LPCWSTR className, LPCWSTR title )
1614 ATOM atom = 0;
1615 char *buffer;
1616 HWND hwnd;
1618 if (className)
1620 /* If the atom doesn't exist, then no class */
1621 /* with this name exists either. */
1622 if (!(atom = GlobalFindAtomW( className )))
1624 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1625 return 0;
1628 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1629 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1630 HeapFree( GetProcessHeap(), 0, buffer );
1631 return hwnd;
1635 /***********************************************************************
1636 * FindWindow32W (USER32.201)
1638 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1640 return FindWindowExW( 0, 0, className, title );
1644 /**********************************************************************
1645 * WIN_GetDesktop
1646 * returns a locked pointer
1648 WND *WIN_GetDesktop(void)
1650 return WIN_LockWndPtr(pWndDesktop);
1652 /**********************************************************************
1653 * WIN_ReleaseDesktop
1654 * unlock the desktop pointer
1656 void WIN_ReleaseDesktop(void)
1658 WIN_ReleaseWndPtr(pWndDesktop);
1662 /**********************************************************************
1663 * GetDesktopWindow16 (USER.286)
1665 HWND16 WINAPI GetDesktopWindow16(void)
1667 return (HWND16)pWndDesktop->hwndSelf;
1671 /**********************************************************************
1672 * GetDesktopWindow32 (USER32.232)
1674 HWND WINAPI GetDesktopWindow(void)
1676 return pWndDesktop->hwndSelf;
1680 /**********************************************************************
1681 * GetDesktopHwnd (USER.278)
1683 * Exactly the same thing as GetDesktopWindow(), but not documented.
1684 * Don't ask me why...
1686 HWND16 WINAPI GetDesktopHwnd16(void)
1688 return (HWND16)pWndDesktop->hwndSelf;
1692 /*******************************************************************
1693 * EnableWindow16 (USER.34)
1695 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1697 return EnableWindow( hwnd, enable );
1701 /*******************************************************************
1702 * EnableWindow32 (USER32.172)
1704 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1706 WND *wndPtr;
1707 BOOL retvalue;
1709 TRACE(win,"EnableWindow32: ( %x, %d )\n", hwnd, enable);
1711 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1712 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1714 /* Enable window */
1715 wndPtr->dwStyle &= ~WS_DISABLED;
1717 if( wndPtr->flags & WIN_NATIVE )
1718 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
1720 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1721 retvalue = TRUE;
1722 goto end;
1724 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1726 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1728 /* Disable window */
1729 wndPtr->dwStyle |= WS_DISABLED;
1731 if( wndPtr->flags & WIN_NATIVE )
1732 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
1734 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus() ))
1736 SetFocus( 0 ); /* A disabled window can't have the focus */
1738 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
1740 ReleaseCapture(); /* A disabled window can't capture the mouse */
1742 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1743 retvalue = FALSE;
1744 goto end;
1746 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1747 end:
1748 WIN_ReleaseWndPtr(wndPtr);
1749 return retvalue;
1753 /***********************************************************************
1754 * IsWindowEnabled16 (USER.35)
1756 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1758 return IsWindowEnabled(hWnd);
1762 /***********************************************************************
1763 * IsWindowEnabled32 (USER32.349)
1765 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1767 WND * wndPtr;
1768 BOOL retvalue;
1770 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1771 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1772 WIN_ReleaseWndPtr(wndPtr);
1773 return retvalue;
1778 /***********************************************************************
1779 * IsWindowUnicode (USER32.350)
1781 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1783 WND * wndPtr;
1784 BOOL retvalue;
1786 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1787 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1788 WIN_ReleaseWndPtr(wndPtr);
1789 return retvalue;
1793 /**********************************************************************
1794 * GetWindowWord16 (USER.133)
1796 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1798 return GetWindowWord( hwnd, offset );
1802 /**********************************************************************
1803 * GetWindowWord32 (USER32.314)
1805 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1807 WORD retvalue;
1808 WND * wndPtr = WIN_FindWndPtr( hwnd );
1809 if (!wndPtr) return 0;
1810 if (offset >= 0)
1812 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1814 WARN( win, "Invalid offset %d\n", offset );
1815 retvalue = 0;
1816 goto end;
1818 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1819 goto end;
1821 switch(offset)
1823 case GWW_ID:
1824 if (HIWORD(wndPtr->wIDmenu))
1825 WARN( win,"GWW_ID: discards high bits of 0x%08x!\n",
1826 wndPtr->wIDmenu);
1827 retvalue = (WORD)wndPtr->wIDmenu;
1828 goto end;
1829 case GWW_HWNDPARENT:
1830 retvalue = GetParent(hwnd);
1831 goto end;
1832 case GWW_HINSTANCE:
1833 if (HIWORD(wndPtr->hInstance))
1834 WARN(win,"GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1835 wndPtr->hInstance);
1836 retvalue = (WORD)wndPtr->hInstance;
1837 goto end;
1838 default:
1839 WARN( win, "Invalid offset %d\n", offset );
1840 retvalue = 0;
1841 goto end;
1843 end:
1844 WIN_ReleaseWndPtr(wndPtr);
1845 return retvalue;
1849 /**********************************************************************
1850 * WIN_GetWindowInstance
1852 HINSTANCE WIN_GetWindowInstance( HWND hwnd )
1855 WND * wndPtr = WIN_FindWndPtr( hwnd );
1856 if (!wndPtr) return (HINSTANCE)0;
1857 WIN_ReleaseWndPtr(wndPtr);
1858 return wndPtr->hInstance;
1863 /**********************************************************************
1864 * SetWindowWord16 (USER.134)
1866 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1868 return SetWindowWord( hwnd, offset, newval );
1872 /**********************************************************************
1873 * SetWindowWord32 (USER32.524)
1875 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1877 WORD *ptr, retval;
1878 WND * wndPtr = WIN_FindWndPtr( hwnd );
1879 if (!wndPtr) return 0;
1880 if (offset >= 0)
1882 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1884 WARN( win, "Invalid offset %d\n", offset );
1885 retval = 0;
1886 goto end;
1888 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1890 else switch(offset)
1892 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1893 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1894 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1895 goto end;
1896 default:
1897 WARN( win, "Invalid offset %d\n", offset );
1898 retval = 0;
1899 goto end;
1901 retval = *ptr;
1902 *ptr = newval;
1903 end:
1904 WIN_ReleaseWndPtr(wndPtr);
1905 return retval;
1909 /**********************************************************************
1910 * WIN_GetWindowLong
1912 * Helper function for GetWindowLong().
1914 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1916 LONG retvalue;
1917 WND * wndPtr = WIN_FindWndPtr( hwnd );
1918 if (!wndPtr) return 0;
1919 if (offset >= 0)
1921 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1923 WARN( win, "Invalid offset %d\n", offset );
1924 retvalue = 0;
1925 goto end;
1927 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1928 /* Special case for dialog window procedure */
1929 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1931 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1932 goto end;
1934 goto end;
1936 switch(offset)
1938 case GWL_USERDATA: retvalue = wndPtr->userdata;
1939 goto end;
1940 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1941 goto end;
1942 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1943 goto end;
1944 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1945 goto end;
1946 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1947 type );
1948 goto end;
1949 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1950 goto end;
1951 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1952 goto end;
1953 default:
1954 WARN( win, "Unknown offset %d\n", offset );
1956 retvalue = 0;
1957 end:
1958 WIN_ReleaseWndPtr(wndPtr);
1959 return retvalue;
1963 /**********************************************************************
1964 * WIN_SetWindowLong
1966 * Helper function for SetWindowLong().
1968 * 0 is the failure code. However, in the case of failure SetLastError
1969 * must be set to distinguish between a 0 return value and a failure.
1971 * FIXME: The error values for SetLastError may not be right. Can
1972 * someone check with the real thing?
1974 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1975 WINDOWPROCTYPE type )
1977 LONG *ptr, retval;
1978 WND * wndPtr = WIN_FindWndPtr( hwnd );
1979 STYLESTRUCT style;
1981 TRACE(win,"%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1983 if (!wndPtr)
1985 /* Is this the right error? */
1986 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1987 return 0;
1990 if (offset >= 0)
1992 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1994 WARN( win, "Invalid offset %d\n", offset );
1996 /* Is this the right error? */
1997 SetLastError( ERROR_OUTOFMEMORY );
1999 retval = 0;
2000 goto end;
2002 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2003 /* Special case for dialog window procedure */
2004 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2006 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2007 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2008 type, WIN_PROC_WINDOW );
2009 goto end;
2012 else switch(offset)
2014 case GWL_ID:
2015 ptr = (DWORD*)&wndPtr->wIDmenu;
2016 break;
2017 case GWL_HINSTANCE:
2018 retval = SetWindowWord( hwnd, offset, newval );
2019 goto end;
2020 case GWL_WNDPROC:
2021 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2022 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2023 type, WIN_PROC_WINDOW );
2024 goto end;;
2025 case GWL_STYLE:
2026 style.styleOld = wndPtr->dwStyle;
2027 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
2028 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
2030 if (wndPtr->flags & WIN_ISWIN32)
2031 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
2032 wndPtr->dwStyle = style.styleNew;
2033 if (wndPtr->flags & WIN_ISWIN32)
2034 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
2035 retval = style.styleOld;
2036 goto end;
2038 case GWL_USERDATA:
2039 ptr = &wndPtr->userdata;
2040 break;
2041 case GWL_EXSTYLE:
2042 style.styleOld = wndPtr->dwExStyle;
2043 style.styleNew = newval;
2044 if (wndPtr->flags & WIN_ISWIN32)
2045 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
2046 wndPtr->dwExStyle = newval;
2047 if (wndPtr->flags & WIN_ISWIN32)
2048 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
2049 retval = style.styleOld;
2050 goto end;
2052 default:
2053 WARN( win, "Invalid offset %d\n", offset );
2055 /* Don't think this is right error but it should do */
2056 SetLastError( ERROR_OUTOFMEMORY );
2058 retval = 0;
2059 goto end;
2061 retval = *ptr;
2062 *ptr = newval;
2063 end:
2064 WIN_ReleaseWndPtr(wndPtr);
2065 return retval;
2069 /**********************************************************************
2070 * GetWindowLong16 (USER.135)
2072 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2074 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2078 /**********************************************************************
2079 * GetWindowLong32A (USER32.305)
2081 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2083 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2087 /**********************************************************************
2088 * GetWindowLong32W (USER32.306)
2090 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2092 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2096 /**********************************************************************
2097 * SetWindowLong16 (USER.136)
2099 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2101 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2105 /**********************************************************************
2106 * SetWindowLong32A (USER32.517)
2108 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2110 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2114 /**********************************************************************
2115 * SetWindowLong32W (USER32.518) Set window attribute
2117 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2118 * value in a window's extra memory.
2120 * The _hwnd_ parameter specifies the window. is the handle to a
2121 * window that has extra memory. The _newval_ parameter contains the
2122 * new attribute or extra memory value. If positive, the _offset_
2123 * parameter is the byte-addressed location in the window's extra
2124 * memory to set. If negative, _offset_ specifies the window
2125 * attribute to set, and should be one of the following values:
2127 * GWL_EXSTYLE The window's extended window style
2129 * GWL_STYLE The window's window style.
2131 * GWL_WNDPROC Pointer to the window's window procedure.
2133 * GWL_HINSTANCE The window's pplication instance handle.
2135 * GWL_ID The window's identifier.
2137 * GWL_USERDATA The window's user-specified data.
2139 * If the window is a dialog box, the _offset_ parameter can be one of
2140 * the following values:
2142 * DWL_DLGPROC The address of the window's dialog box procedure.
2144 * DWL_MSGRESULT The return value of a message
2145 * that the dialog box procedure processed.
2147 * DWL_USER Application specific information.
2149 * RETURNS
2151 * If successful, returns the previous value located at _offset_. Otherwise,
2152 * returns 0.
2154 * NOTES
2156 * Extra memory for a window class is specified by a nonzero cbWndExtra
2157 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2158 * time of class creation.
2160 * Using GWL_WNDPROC to set a new window procedure effectively creates
2161 * a window subclass. Use CallWindowProc() in the new windows procedure
2162 * to pass messages to the superclass's window procedure.
2164 * The user data is reserved for use by the application which created
2165 * the window.
2167 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2168 * instead, call the EnableWindow() function to change the window's
2169 * disabled state.
2171 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2172 * SetParent() instead.
2174 * Win95:
2175 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2176 * it sends WM_STYLECHANGING before changing the settings
2177 * and WM_STYLECHANGED afterwards.
2178 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2180 * BUGS
2182 * GWL_STYLE does not dispatch WM_STYLE... messages.
2184 * CONFORMANCE
2186 * ECMA-234, Win32
2189 LONG WINAPI SetWindowLongW(
2190 HWND hwnd, /* window to alter */
2191 INT offset, /* offset, in bytes, of location to alter */
2192 LONG newval /* new value of location */
2194 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2198 /*******************************************************************
2199 * GetWindowText16 (USER.36)
2201 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2203 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2207 /*******************************************************************
2208 * GetWindowText32A (USER32.309)
2210 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2212 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2213 (LPARAM)lpString );
2216 /*******************************************************************
2217 * InternalGetWindowText (USER32.326)
2219 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2221 FIXME(win,"(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2222 return GetWindowTextW(hwnd,lpString,nMaxCount);
2226 /*******************************************************************
2227 * GetWindowText32W (USER32.312)
2229 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2231 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2232 (LPARAM)lpString );
2236 /*******************************************************************
2237 * SetWindowText16 (USER.37)
2239 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2241 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2245 /*******************************************************************
2246 * SetWindowText32A (USER32.521)
2248 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2250 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2254 /*******************************************************************
2255 * SetWindowText32W (USER32.523)
2257 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2259 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2263 /*******************************************************************
2264 * GetWindowTextLength16 (USER.38)
2266 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2268 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2272 /*******************************************************************
2273 * GetWindowTextLength32A (USER32.310)
2275 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2277 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2280 /*******************************************************************
2281 * GetWindowTextLength32W (USER32.311)
2283 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2285 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2289 /*******************************************************************
2290 * IsWindow16 (USER.47)
2292 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2294 return IsWindow( hwnd );
2297 void WINAPI WIN16_IsWindow16( CONTEXT *context )
2299 WORD *stack = PTR_SEG_OFF_TO_LIN(SS_reg(context), SP_reg(context));
2300 HWND16 hwnd = (HWND16)stack[2];
2302 AX_reg(context) = IsWindow( hwnd );
2303 ES_reg(context) = USER_HeapSel;
2307 /*******************************************************************
2308 * IsWindow32 (USER32.348)
2310 BOOL WINAPI IsWindow( HWND hwnd )
2312 WND * wndPtr;
2313 BOOL retvalue;
2315 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2316 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2317 WIN_ReleaseWndPtr(wndPtr);
2318 return retvalue;
2323 /*****************************************************************
2324 * GetParent16 (USER.46)
2326 HWND16 WINAPI GetParent16( HWND16 hwnd )
2328 return (HWND16)GetParent( hwnd );
2332 /*****************************************************************
2333 * GetParent32 (USER32.278)
2335 HWND WINAPI GetParent( HWND hwnd )
2337 WND *wndPtr;
2338 HWND retvalue;
2340 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2341 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2343 WIN_ReleaseWndPtr(wndPtr);
2344 return 0;
2346 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2347 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2349 WIN_ReleaseWndPtr(wndPtr);
2350 return retvalue;
2354 /*****************************************************************
2355 * WIN_GetTopParent
2357 * Get the top-level parent for a child window.
2358 * returns a locked pointer
2360 WND* WIN_GetTopParentPtr( WND* pWnd )
2362 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2364 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2366 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2368 return tmpWnd;
2371 /*****************************************************************
2372 * WIN_GetTopParent
2374 * Get the top-level parent for a child window.
2376 HWND WIN_GetTopParent( HWND hwnd )
2378 HWND retvalue;
2379 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2380 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2382 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2383 WIN_ReleaseWndPtr(tmpPtr);
2384 WIN_ReleaseWndPtr(wndPtr);
2385 return retvalue;
2389 /*****************************************************************
2390 * SetParent16 (USER.233)
2392 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2394 return SetParent( hwndChild, hwndNewParent );
2398 /*****************************************************************
2399 * SetParent32 (USER32.495)
2401 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2403 WND *wndPtr;
2404 DWORD dwStyle;
2405 WND *pWndNewParent;
2406 WND *pWndOldParent;
2407 HWND retvalue;
2410 if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
2412 dwStyle = wndPtr->dwStyle;
2414 pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
2415 : WIN_LockWndPtr(pWndDesktop);
2417 /* Windows hides the window first, then shows it again
2418 * including the WM_SHOWWINDOW messages and all */
2419 if (dwStyle & WS_VISIBLE)
2420 ShowWindow( hwndChild, SW_HIDE );
2422 pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
2424 /* SetParent32 additionally needs to make hwndChild the topmost window
2425 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2426 WM_WINDOWPOSCHANGED notification messages.
2428 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2429 SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2430 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2431 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2433 retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
2435 WIN_ReleaseWndPtr(pWndOldParent);
2436 WIN_ReleaseWndPtr(pWndNewParent);
2437 WIN_ReleaseWndPtr(wndPtr);
2439 return retvalue;
2443 /*******************************************************************
2444 * IsChild16 (USER.48)
2446 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2448 return IsChild(parent,child);
2452 /*******************************************************************
2453 * IsChild32 (USER32.339)
2455 BOOL WINAPI IsChild( HWND parent, HWND child )
2457 WND * wndPtr = WIN_FindWndPtr( child );
2458 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2460 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2461 if (wndPtr->hwndSelf == parent)
2463 WIN_ReleaseWndPtr(wndPtr);
2464 return TRUE;
2467 WIN_ReleaseWndPtr(wndPtr);
2468 return FALSE;
2472 /***********************************************************************
2473 * IsWindowVisible16 (USER.49)
2475 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2477 return IsWindowVisible(hwnd);
2481 /***********************************************************************
2482 * IsWindowVisible32 (USER32.351)
2484 BOOL WINAPI IsWindowVisible( HWND hwnd )
2486 BOOL retval;
2487 WND *wndPtr = WIN_FindWndPtr( hwnd );
2488 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2490 if (!(wndPtr->dwStyle & WS_VISIBLE))
2492 WIN_ReleaseWndPtr(wndPtr);
2493 return FALSE;
2495 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2497 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2498 WIN_ReleaseWndPtr(wndPtr);
2499 return retval;
2504 /***********************************************************************
2505 * WIN_IsWindowDrawable
2507 * hwnd is drawable when it is visible, all parents are not
2508 * minimized, and it is itself not minimized unless we are
2509 * trying to draw its default class icon.
2511 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2513 if( (wnd->dwStyle & WS_MINIMIZE &&
2514 icon && wnd->class->hIcon) ||
2515 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2516 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2517 if( wnd->dwStyle & WS_MINIMIZE ||
2518 !(wnd->dwStyle & WS_VISIBLE) ) break;
2519 return (wnd == NULL);
2523 /*******************************************************************
2524 * GetTopWindow16 (USER.229)
2526 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2528 return GetTopWindow(hwnd);
2532 /*******************************************************************
2533 * GetTopWindow32 (USER.229)
2535 HWND WINAPI GetTopWindow( HWND hwnd )
2537 HWND retval;
2538 WND * wndPtr = WIN_FindWndPtr( hwnd );
2539 if (wndPtr && wndPtr->child)
2541 retval = wndPtr->child->hwndSelf;
2543 else retval = 0;
2544 WIN_ReleaseWndPtr(wndPtr);
2545 return retval;
2549 /*******************************************************************
2550 * GetWindow16 (USER.262)
2552 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2554 return GetWindow( hwnd,rel );
2558 /*******************************************************************
2559 * GetWindow32 (USER32.302)
2561 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2563 HWND retval;
2565 WND * wndPtr = WIN_FindWndPtr( hwnd );
2566 if (!wndPtr) return 0;
2567 switch(rel)
2569 case GW_HWNDFIRST:
2570 if (wndPtr->parent) retval = wndPtr->parent->child->hwndSelf;
2571 else retval = 0;
2572 goto end;
2574 case GW_HWNDLAST:
2575 if (!wndPtr->parent)
2577 retval = 0; /* Desktop window */
2578 goto end;
2580 while (wndPtr->next)
2582 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2584 retval = wndPtr->hwndSelf;
2585 goto end;
2587 case GW_HWNDNEXT:
2588 if (!wndPtr->next) retval = 0;
2589 else retval = wndPtr->next->hwndSelf;
2590 goto end;
2592 case GW_HWNDPREV:
2593 if (!wndPtr->parent)
2595 retval = 0; /* Desktop window */
2596 goto end;
2598 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2599 if (wndPtr->hwndSelf == hwnd)
2601 retval = 0; /* First in list */
2602 goto end;
2604 while (wndPtr->next)
2606 if (wndPtr->next->hwndSelf == hwnd)
2608 retval = wndPtr->hwndSelf;
2609 goto end;
2611 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2613 retval = 0;
2614 goto end;
2616 case GW_OWNER:
2617 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2618 goto end;
2620 case GW_CHILD:
2621 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2622 goto end;
2624 retval = 0;
2625 end:
2626 WIN_ReleaseWndPtr(wndPtr);
2627 return retval;
2631 /*******************************************************************
2632 * GetNextWindow16 (USER.230)
2634 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2636 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2637 return GetWindow16( hwnd, flag );
2640 /*******************************************************************
2641 * ShowOwnedPopups16 (USER.265)
2643 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2645 ShowOwnedPopups( owner, fShow );
2649 /*******************************************************************
2650 * ShowOwnedPopups32 (USER32.531)
2652 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2654 WND *pWnd;
2655 pWnd = WIN_LockWndPtr(pWndDesktop->child);
2656 while (pWnd)
2658 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
2659 (pWnd->dwStyle & WS_POPUP))
2660 ShowWindow( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
2661 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2663 return TRUE;
2667 /*******************************************************************
2668 * GetLastActivePopup16 (USER.287)
2670 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2672 return GetLastActivePopup( hwnd );
2675 /*******************************************************************
2676 * GetLastActivePopup32 (USER32.256)
2678 HWND WINAPI GetLastActivePopup( HWND hwnd )
2680 WND *wndPtr;
2681 HWND retval;
2682 wndPtr = WIN_FindWndPtr(hwnd);
2683 if (!wndPtr) return hwnd;
2684 retval = wndPtr->hwndLastActive;
2685 WIN_ReleaseWndPtr(wndPtr);
2686 return retval;
2690 /*******************************************************************
2691 * WIN_BuildWinArray
2693 * Build an array of pointers to the children of a given window.
2694 * The array must be freed with HeapFree(SystemHeap). Return NULL
2695 * when no windows are found.
2697 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2699 /* Future : this function will lock all windows associated with this array */
2701 WND **list, **ppWnd;
2702 WND *pWnd;
2703 UINT count = 0, skipOwned, skipHidden;
2704 DWORD skipFlags;
2706 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2707 skipOwned = bwaFlags & BWA_SKIPOWNED;
2708 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2709 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2711 /* First count the windows */
2713 if (!wndPtr)
2714 wndPtr = WIN_GetDesktop();
2716 pWnd = WIN_LockWndPtr(wndPtr->child);
2717 while (pWnd)
2719 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2720 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2721 count++;
2722 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2725 if( count )
2727 /* Now build the list of all windows */
2729 if ((list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * (count + 1))))
2731 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2733 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2734 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2736 *ppWnd++ = pWnd;
2737 count++;
2740 WIN_ReleaseWndPtr(pWnd);
2741 *ppWnd = NULL;
2743 else count = 0;
2744 } else list = NULL;
2746 if( pTotal ) *pTotal = count;
2747 return list;
2749 /*******************************************************************
2750 * WIN_ReleaseWinArray
2752 void WIN_ReleaseWinArray(WND **wndArray)
2754 /* Future : this function will also unlock all windows associated with wndArray */
2755 HeapFree( SystemHeap, 0, wndArray );
2759 /*******************************************************************
2760 * EnumWindows16 (USER.54)
2762 BOOL16 WINAPI EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
2764 WND **list, **ppWnd;
2766 /* We have to build a list of all windows first, to avoid */
2767 /* unpleasant side-effects, for instance if the callback */
2768 /* function changes the Z-order of the windows. */
2770 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2772 WIN_ReleaseDesktop();
2773 return FALSE;
2776 /* Now call the callback function for every window */
2778 for (ppWnd = list; *ppWnd; ppWnd++)
2780 LRESULT lpEnumFuncRetval;
2781 int iWndsLocks = 0;
2782 /* Make sure that the window still exists */
2783 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2785 /* To avoid any deadlocks, all the locks on the windows
2786 structures must be suspended before the control
2787 is passed to the application */
2788 iWndsLocks = WIN_SuspendWndsLock();
2789 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2790 WIN_RestoreWndsLock(iWndsLocks);
2792 if (!lpEnumFuncRetval) break;
2794 WIN_ReleaseWinArray(list);
2795 WIN_ReleaseDesktop();
2796 return TRUE;
2800 /*******************************************************************
2801 * EnumWindows32 (USER32.193)
2803 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2805 return (BOOL)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2809 /**********************************************************************
2810 * EnumTaskWindows16 (USER.225)
2812 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2813 LPARAM lParam )
2815 WND **list, **ppWnd;
2817 /* This function is the same as EnumWindows(), */
2818 /* except for an added check on the window's task. */
2820 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2822 WIN_ReleaseDesktop();
2823 return FALSE;
2826 /* Now call the callback function for every window */
2828 for (ppWnd = list; *ppWnd; ppWnd++)
2830 LRESULT funcRetval;
2831 int iWndsLocks = 0;
2832 /* Make sure that the window still exists */
2833 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2834 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2836 /* To avoid any deadlocks, all the locks on the windows
2837 structures must be suspended before the control
2838 is passed to the application */
2839 iWndsLocks = WIN_SuspendWndsLock();
2840 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2841 WIN_RestoreWndsLock(iWndsLocks);
2843 if (!funcRetval) break;
2845 WIN_ReleaseWinArray(list);
2846 WIN_ReleaseDesktop();
2847 return TRUE;
2851 /**********************************************************************
2852 * EnumThreadWindows (USER32.190)
2854 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2856 THDB *tdb = THREAD_IdToTHDB(id);
2858 return (BOOL16)EnumTaskWindows16(tdb->teb.htask16, (WNDENUMPROC16)func, lParam);
2862 /**********************************************************************
2863 * WIN_EnumChildWindows
2865 * Helper function for EnumChildWindows().
2867 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2868 LPARAM lParam )
2870 WND **childList;
2871 BOOL16 ret = FALSE;
2873 for ( ; *ppWnd; ppWnd++)
2875 int iWndsLocks = 0;
2877 /* Make sure that the window still exists */
2878 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2879 /* Build children list first */
2880 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2882 /* To avoid any deadlocks, all the locks on the windows
2883 structures must be suspended before the control
2884 is passed to the application */
2885 iWndsLocks = WIN_SuspendWndsLock();
2886 ret = func( (*ppWnd)->hwndSelf, lParam );
2887 WIN_RestoreWndsLock(iWndsLocks);
2889 if (childList)
2891 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2892 WIN_ReleaseWinArray(childList);
2894 if (!ret) return FALSE;
2896 return TRUE;
2900 /**********************************************************************
2901 * EnumChildWindows16 (USER.55)
2903 BOOL16 WINAPI EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
2904 LPARAM lParam )
2906 WND **list, *pParent;
2908 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2909 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2911 WIN_ReleaseWndPtr(pParent);
2912 return FALSE;
2914 WIN_EnumChildWindows( list, func, lParam );
2915 WIN_ReleaseWinArray(list);
2916 WIN_ReleaseWndPtr(pParent);
2917 return TRUE;
2921 /**********************************************************************
2922 * EnumChildWindows32 (USER32.178)
2924 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2925 LPARAM lParam )
2927 return (BOOL)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2928 lParam );
2932 /*******************************************************************
2933 * AnyPopup16 (USER.52)
2935 BOOL16 WINAPI AnyPopup16(void)
2937 return AnyPopup();
2941 /*******************************************************************
2942 * AnyPopup32 (USER32.4)
2944 BOOL WINAPI AnyPopup(void)
2946 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2947 BOOL retvalue;
2949 while (wndPtr)
2951 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2953 retvalue = TRUE;
2954 goto end;
2956 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2958 retvalue = FALSE;
2959 end:
2960 WIN_ReleaseWndPtr(wndPtr);
2961 return retvalue;
2965 /*******************************************************************
2966 * FlashWindow16 (USER.105)
2968 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2970 return FlashWindow( hWnd, bInvert );
2974 /*******************************************************************
2975 * FlashWindow32 (USER32.202)
2977 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2979 WND *wndPtr = WIN_FindWndPtr(hWnd);
2981 TRACE(win,"%04x\n", hWnd);
2983 if (!wndPtr) return FALSE;
2985 if (wndPtr->dwStyle & WS_MINIMIZE)
2987 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2989 HDC hDC = GetDC(hWnd);
2991 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2992 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2994 ReleaseDC( hWnd, hDC );
2995 wndPtr->flags |= WIN_NCACTIVATED;
2997 else
2999 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
3000 RDW_UPDATENOW | RDW_FRAME, 0 );
3001 wndPtr->flags &= ~WIN_NCACTIVATED;
3003 WIN_ReleaseWndPtr(wndPtr);
3004 return TRUE;
3006 else
3008 WPARAM16 wparam;
3009 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3010 else wparam = (hWnd == GetActiveWindow());
3012 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3013 WIN_ReleaseWndPtr(wndPtr);
3014 return wparam;
3019 /*******************************************************************
3020 * SetSysModalWindow16 (USER.188)
3022 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3024 HWND hWndOldModal = hwndSysModal;
3025 hwndSysModal = hWnd;
3026 FIXME(win, "EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3027 return hWndOldModal;
3031 /*******************************************************************
3032 * GetSysModalWindow16 (USER.52)
3034 HWND16 WINAPI GetSysModalWindow16(void)
3036 return hwndSysModal;
3040 /*******************************************************************
3041 * GetWindowContextHelpId (USER32.303)
3043 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3045 DWORD retval;
3046 WND *wnd = WIN_FindWndPtr( hwnd );
3047 if (!wnd) return 0;
3048 retval = wnd->helpContext;
3049 WIN_ReleaseWndPtr(wnd);
3050 return retval;
3054 /*******************************************************************
3055 * SetWindowContextHelpId (USER32.515)
3057 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3059 WND *wnd = WIN_FindWndPtr( hwnd );
3060 if (!wnd) return FALSE;
3061 wnd->helpContext = id;
3062 WIN_ReleaseWndPtr(wnd);
3063 return TRUE;
3067 /*******************************************************************
3068 * DRAG_QueryUpdate
3070 * recursively find a child that contains spDragInfo->pt point
3071 * and send WM_QUERYDROPOBJECT
3073 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3075 BOOL16 wParam,bResult = 0;
3076 POINT pt;
3077 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
3078 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3079 RECT tempRect;
3081 if( !ptrQueryWnd || !ptrDragInfo )
3083 WIN_ReleaseWndPtr(ptrQueryWnd);
3084 return 0;
3087 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3089 GetWindowRect(hQueryWnd,&tempRect);
3091 if( !PtInRect(&tempRect,pt) ||
3092 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3094 WIN_ReleaseWndPtr(ptrQueryWnd);
3095 return 0;
3098 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3100 tempRect = ptrQueryWnd->rectClient;
3101 if(ptrQueryWnd->dwStyle & WS_CHILD)
3102 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3103 (LPPOINT)&tempRect, 2 );
3105 if (PtInRect( &tempRect, pt))
3107 wParam = 0;
3109 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3111 if( ptrWnd->dwStyle & WS_VISIBLE )
3113 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3114 if (PtInRect( &tempRect, pt )) break;
3118 if(ptrWnd)
3120 TRACE(msg,"hwnd = %04x, %d %d - %d %d\n",
3121 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3122 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3123 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3124 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3126 WIN_ReleaseWndPtr(ptrWnd);
3129 if(bResult)
3131 WIN_ReleaseWndPtr(ptrQueryWnd);
3132 return bResult;
3135 else wParam = 1;
3137 else wParam = 1;
3139 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3141 ptrDragInfo->hScope = hQueryWnd;
3143 bResult = ( bNoSend )
3144 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3145 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3146 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3147 if( !bResult )
3148 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3150 WIN_ReleaseWndPtr(ptrQueryWnd);
3151 return bResult;
3155 /*******************************************************************
3156 * DragDetect (USER.465)
3158 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3160 POINT pt32;
3161 CONV_POINT16TO32( &pt, &pt32 );
3162 return DragDetect( hWnd, pt32 );
3165 /*******************************************************************
3166 * DragDetect32 (USER32.151)
3168 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3170 MSG16 msg;
3171 RECT16 rect;
3173 rect.left = pt.x - wDragWidth;
3174 rect.right = pt.x + wDragWidth;
3176 rect.top = pt.y - wDragHeight;
3177 rect.bottom = pt.y + wDragHeight;
3179 SetCapture(hWnd);
3181 while(1)
3183 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3185 if( msg.message == WM_LBUTTONUP )
3187 ReleaseCapture();
3188 return 0;
3190 if( msg.message == WM_MOUSEMOVE )
3192 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
3194 ReleaseCapture();
3195 return 1;
3199 WaitMessage();
3201 return 0;
3204 /******************************************************************************
3205 * DragObject16 (USER.464)
3207 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3208 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3210 MSG16 msg;
3211 LPDRAGINFO lpDragInfo;
3212 SEGPTR spDragInfo;
3213 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3214 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
3215 WND *wndPtr = WIN_FindWndPtr(hWnd);
3216 HCURSOR16 hCurrentCursor = 0;
3217 HWND16 hCurrentWnd = 0;
3219 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
3220 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
3222 if( !lpDragInfo || !spDragInfo )
3224 WIN_ReleaseWndPtr(wndPtr);
3225 return 0L;
3228 hBummer = LoadCursor16(0, IDC_BUMMER16);
3230 if( !hBummer || !wndPtr )
3232 GlobalFree16(hDragInfo);
3233 WIN_ReleaseWndPtr(wndPtr);
3234 return 0L;
3237 if(hCursor)
3239 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3241 GlobalFree16(hDragInfo);
3242 WIN_ReleaseWndPtr(wndPtr);
3243 return 0L;
3246 if( hDragCursor == hCursor ) hDragCursor = 0;
3247 else hCursor = hDragCursor;
3249 hOldCursor = SetCursor(hDragCursor);
3252 lpDragInfo->hWnd = hWnd;
3253 lpDragInfo->hScope = 0;
3254 lpDragInfo->wFlags = wObj;
3255 lpDragInfo->hList = szList; /* near pointer! */
3256 lpDragInfo->hOfStruct = hOfStruct;
3257 lpDragInfo->l = 0L;
3259 SetCapture(hWnd);
3260 ShowCursor( TRUE );
3264 do{ WaitMessage(); }
3265 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3267 *(lpDragInfo+1) = *lpDragInfo;
3269 lpDragInfo->pt = msg.pt;
3271 /* update DRAGINFO struct */
3272 TRACE(msg,"lpDI->hScope = %04x\n",lpDragInfo->hScope);
3274 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3275 hCurrentCursor = hCursor;
3276 else
3278 hCurrentCursor = hBummer;
3279 lpDragInfo->hScope = 0;
3281 if( hCurrentCursor )
3282 SetCursor(hCurrentCursor);
3284 /* send WM_DRAGLOOP */
3285 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3286 (LPARAM) spDragInfo );
3287 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3288 if( hCurrentWnd != lpDragInfo->hScope )
3290 if( hCurrentWnd )
3291 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3292 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
3293 HIWORD(spDragInfo)) );
3294 hCurrentWnd = lpDragInfo->hScope;
3295 if( hCurrentWnd )
3296 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3298 else
3299 if( hCurrentWnd )
3300 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3302 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3304 ReleaseCapture();
3305 ShowCursor( FALSE );
3307 if( hCursor )
3309 SetCursor( hOldCursor );
3310 if (hDragCursor) DestroyCursor( hDragCursor );
3313 if( hCurrentCursor != hBummer )
3314 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3315 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3316 else
3317 msg.lParam = 0;
3318 GlobalFree16(hDragInfo);
3319 WIN_ReleaseWndPtr(wndPtr);
3321 return (DWORD)(msg.lParam);