New debug scheme with explicit debug channels declaration.
[wine.git] / windows / win.c
blob79894574876f20203c461c5a881535c8c7605342
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 DECLARE_DEBUG_CHANNEL(msg)
38 DECLARE_DEBUG_CHANNEL(win)
40 /**********************************************************************/
42 WND_DRIVER *WND_Driver = NULL;
44 /* Desktop window */
45 static WND *pWndDesktop = NULL;
47 static HWND hwndSysModal = 0;
49 static WORD wDragWidth = 4;
50 static WORD wDragHeight= 3;
52 /* thread safeness */
53 static CRITICAL_SECTION WIN_CritSection;
55 /***********************************************************************
56 * WIN_LockWnds
58 * Locks access to all WND structures for thread safeness
60 void WIN_LockWnds()
62 EnterCriticalSection(&WIN_CritSection);
65 /***********************************************************************
66 * WIN_UnlockWnds
68 * Unlocks access to all WND structures
70 void WIN_UnlockWnds()
72 LeaveCriticalSection(&WIN_CritSection);
74 /***********************************************************************
75 * WIN_SuspendWndsLock
77 * Suspend the lock on WND structures.
78 * Returns the number of locks suspended
80 int WIN_SuspendWndsLock()
82 int isuspendedLocks = 0;
84 /* make sure that the lock is not suspended by different thread than
85 the owning thread */
86 if(WIN_CritSection.OwningThread != GetCurrentThreadId())
88 return 0;
90 /* set the value of isuspendedlock to the actual recursion count
91 of the critical section */
92 isuspendedLocks = WIN_CritSection.RecursionCount;
93 /* set the recursion count of the critical section to 1
94 so the owning thread will be able to leave it */
95 WIN_CritSection.RecursionCount = 1;
96 /* leave critical section*/
97 WIN_UnlockWnds();
99 return isuspendedLocks;
102 /***********************************************************************
103 * WIN_RestoreWndsLock
105 * Restore the suspended locks on WND structures
107 void WIN_RestoreWndsLock(int ipreviousLocks)
109 if(!ipreviousLocks)
111 return;
113 /* restore the lock */
114 WIN_LockWnds();
115 /* set the recursion count of the critical section to the
116 value of suspended locks (given by WIN_SuspendWndsLock())*/
117 WIN_CritSection.RecursionCount = ipreviousLocks;
121 /***********************************************************************
122 * WIN_FindWndPtr
124 * Return a pointer to the WND structure corresponding to a HWND.
126 WND * WIN_FindWndPtr( HWND hwnd )
128 WND * ptr;
130 if (!hwnd || HIWORD(hwnd)) goto error2;
131 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
132 /* Lock all WND structures for thread safeness*/
133 WIN_LockWnds();
134 /*and increment destruction monitoring*/
135 ptr->irefCount++;
137 if (ptr->dwMagic != WND_MAGIC) goto error;
138 if (ptr->hwndSelf != hwnd)
140 ERR( win, "Can't happen: hwnd %04x self pointer is %04x\n",hwnd, ptr->hwndSelf );
141 goto error;
143 /* returns a locked pointer */
144 return ptr;
145 error:
146 /* Unlock all WND structures for thread safeness*/
147 WIN_UnlockWnds();
148 /* and decrement destruction monitoring value */
149 ptr->irefCount--;
151 error2:
152 if ( hwnd!=0 )
153 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
154 return NULL;
157 /***********************************************************************
158 * WIN_LockWndPtr
160 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
161 * but by initWndPtr;
162 * Returns the locked initialisation pointer
164 WND *WIN_LockWndPtr(WND *initWndPtr)
166 if(!initWndPtr) return 0;
168 /* Lock all WND structures for thread safeness*/
169 WIN_LockWnds();
170 /*and increment destruction monitoring*/
171 initWndPtr->irefCount++;
173 return initWndPtr;
177 /***********************************************************************
178 * WIN_ReleaseWndPtr
180 * Release the pointer to the WND structure.
182 void WIN_ReleaseWndPtr(WND *wndPtr)
184 if(!wndPtr) return;
186 /*Decrement destruction monitoring value*/
187 wndPtr->irefCount--;
188 /* Check if it's time to release the memory*/
189 /* Check if it's time to release the memory*/
190 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
192 /* Release memory */
193 USER_HEAP_FREE( wndPtr->hwndSelf);
195 else if(wndPtr->irefCount < 0)
197 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
198 TRACE(win,"forgot a Lock on %p somewhere\n",wndPtr);
200 /*unlock all WND structures for thread safeness*/
201 WIN_UnlockWnds();
204 /***********************************************************************
205 * WIN_UpdateWndPtr
207 * Updates the value of oldPtr to newPtr.
209 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
211 WND *tmpWnd = NULL;
213 tmpWnd = WIN_LockWndPtr(newPtr);
214 WIN_ReleaseWndPtr(*oldPtr);
215 *oldPtr = tmpWnd;
219 /***********************************************************************
220 * WIN_DumpWindow
222 * Dump the content of a window structure to stderr.
224 void WIN_DumpWindow( HWND hwnd )
226 WND *ptr;
227 char className[80];
228 int i;
230 if (!(ptr = WIN_FindWndPtr( hwnd )))
232 WARN( win, "%04x is not a window handle\n", hwnd );
233 return;
236 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
237 strcpy( className, "#NULL#" );
239 TRACE( win, "Window %04x (%p):\n", hwnd, ptr );
240 DUMP( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
241 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
242 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
243 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
244 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
245 ptr->next, ptr->child, ptr->parent, ptr->owner,
246 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
247 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
248 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
249 ptr->text ? ptr->text : "",
250 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
251 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
252 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
253 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
255 if (ptr->class->cbWndExtra)
257 DUMP( "extra bytes:" );
258 for (i = 0; i < ptr->class->cbWndExtra; i++)
259 DUMP( " %02x", *((BYTE*)ptr->wExtra+i) );
260 DUMP( "\n" );
262 DUMP( "\n" );
263 WIN_ReleaseWndPtr(ptr);
267 /***********************************************************************
268 * WIN_WalkWindows
270 * Walk the windows tree and print each window on stderr.
272 void WIN_WalkWindows( HWND hwnd, int indent )
274 WND *ptr;
275 char className[80];
277 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
279 if (!ptr)
281 WARN( win, "Invalid window handle %04x\n", hwnd );
282 return;
285 if (!indent) /* first time around */
286 DUMP( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
287 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
288 " Text");
290 while (ptr)
292 DUMP( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
294 GlobalGetAtomName16(ptr->class->atomName,className,sizeof(className));
296 DUMP( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
297 (DWORD)ptr, ptr->hmemTaskQ, className,
298 (UINT)ptr->dwStyle, (UINT)ptr->winproc,
299 ptr->text?ptr->text:"<null>");
301 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
302 WIN_UpdateWndPtr(&ptr,ptr->next);
308 /***********************************************************************
309 * WIN_UnlinkWindow
311 * Remove a window from the siblings linked list.
313 BOOL WIN_UnlinkWindow( HWND hwnd )
315 WND *wndPtr, **ppWnd;
316 BOOL ret = FALSE;
318 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
319 else if(!wndPtr->parent)
321 WIN_ReleaseWndPtr(wndPtr);
322 return FALSE;
325 ppWnd = &wndPtr->parent->child;
326 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
327 if (*ppWnd)
329 *ppWnd = wndPtr->next;
330 ret = TRUE;
332 WIN_ReleaseWndPtr(wndPtr);
333 return ret;
337 /***********************************************************************
338 * WIN_LinkWindow
340 * Insert a window into the siblings linked list.
341 * The window is inserted after the specified window, which can also
342 * be specified as HWND_TOP or HWND_BOTTOM.
344 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
346 WND *wndPtr, **ppWnd;
348 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
349 else if(!wndPtr->parent)
351 WIN_ReleaseWndPtr(wndPtr);
352 return FALSE;
354 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
356 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
357 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
358 while (*ppWnd) ppWnd = &(*ppWnd)->next;
360 else /* Normal case */
362 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
363 if (!afterPtr)
365 WIN_ReleaseWndPtr(wndPtr);
366 return FALSE;
368 ppWnd = &afterPtr->next;
369 WIN_ReleaseWndPtr(afterPtr);
371 wndPtr->next = *ppWnd;
372 *ppWnd = wndPtr;
373 WIN_ReleaseWndPtr(wndPtr);
374 return TRUE;
378 /***********************************************************************
379 * WIN_FindWinToRepaint
381 * Find a window that needs repaint.
383 HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE16 hQueue )
385 HWND hwndRet;
386 WND *pWnd;
388 /* Note: the desktop window never gets WM_PAINT messages
389 * The real reason why is because Windows DesktopWndProc
390 * does ValidateRgn inside WM_ERASEBKGND handler.
393 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
395 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
397 if (!(pWnd->dwStyle & WS_VISIBLE))
399 TRACE(win, "skipping window %04x\n",
400 pWnd->hwndSelf );
402 else if ((pWnd->hmemTaskQ == hQueue) &&
403 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)))
404 break;
406 else if (pWnd->child )
407 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
409 WIN_ReleaseWndPtr(pWnd);
410 return hwndRet;
415 if(!pWnd)
417 return 0;
420 hwndRet = pWnd->hwndSelf;
422 /* look among siblings if we got a transparent window */
423 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
424 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
426 WIN_UpdateWndPtr(&pWnd,pWnd->next);
428 if (pWnd)
430 hwndRet = pWnd->hwndSelf;
431 WIN_ReleaseWndPtr(pWnd);
433 TRACE(win,"found %04x\n",hwndRet);
434 return hwndRet;
438 /***********************************************************************
439 * WIN_DestroyWindow
441 * Destroy storage associated to a window. "Internals" p.358
442 * returns a locked wndPtr->next
444 static WND* WIN_DestroyWindow( WND* wndPtr )
446 HWND hwnd = wndPtr->hwndSelf;
447 WND *pWnd;
449 TRACE(win, "%04x\n", wndPtr->hwndSelf );
451 #ifdef CONFIG_IPC
452 if (main_block)
453 DDE_DestroyWindow(wndPtr->hwndSelf);
454 #endif /* CONFIG_IPC */
456 /* free child windows */
457 WIN_LockWndPtr(wndPtr->child);
458 while ((pWnd = wndPtr->child))
460 wndPtr->child = WIN_DestroyWindow( pWnd );
461 WIN_ReleaseWndPtr(pWnd);
465 * Clear the update region to make sure no WM_PAINT messages will be
466 * generated for this window while processing the WM_NCDESTROY.
468 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
470 if (wndPtr->hrgnUpdate > 1)
471 DeleteObject( wndPtr->hrgnUpdate );
473 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
475 wndPtr->hrgnUpdate = 0;
479 * Send the WM_NCDESTROY to the window being destroyed.
481 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
483 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
485 WINPOS_CheckInternalPos( wndPtr );
486 if( hwnd == GetCapture()) ReleaseCapture();
488 /* free resources associated with the window */
490 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
491 PROPERTY_RemoveWindowProps( wndPtr );
493 wndPtr->dwMagic = 0; /* Mark it as invalid */
495 /* toss stale messages from the queue */
497 if( wndPtr->hmemTaskQ )
499 BOOL bPostQuit = FALSE;
500 WPARAM wQuitParam = 0;
501 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) QUEUE_Lock(wndPtr->hmemTaskQ);
502 QMSG *qmsg;
504 while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
506 if( qmsg->msg.message == WM_QUIT )
508 bPostQuit = TRUE;
509 wQuitParam = qmsg->msg.wParam;
511 QUEUE_RemoveMsg(msgQ, qmsg);
514 QUEUE_Unlock(msgQ);
516 /* repost WM_QUIT to make sure this app exits its message loop */
517 if( bPostQuit ) PostQuitMessage(wQuitParam);
518 wndPtr->hmemTaskQ = 0;
521 if (!(wndPtr->dwStyle & WS_CHILD))
522 if (wndPtr->wIDmenu) DestroyMenu( (HMENU)wndPtr->wIDmenu );
523 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
524 wndPtr->pDriver->pDestroyWindow( wndPtr );
525 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
526 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
527 wndPtr->hwndSelf = 0;
528 wndPtr->class->cWindows--;
529 wndPtr->class = NULL;
531 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
533 wndPtr->pDriver->pFinalize(wndPtr);
535 return pWnd;
538 /***********************************************************************
539 * WIN_ResetQueueWindows
541 * Reset the queue of all the children of a given window.
542 * Return TRUE if something was done.
544 BOOL WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
546 BOOL ret = FALSE;
548 if (hNew) /* Set a new queue */
550 for (wnd = WIN_LockWndPtr(wnd->child); (wnd);WIN_UpdateWndPtr(&wnd,wnd->next))
552 if (wnd->hmemTaskQ == hQueue)
554 wnd->hmemTaskQ = hNew;
555 ret = TRUE;
557 if (wnd->child)
559 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
563 else /* Queue is being destroyed */
565 while (wnd->child)
567 WND *tmp = WIN_LockWndPtr(wnd->child);
568 WND *tmp2;
569 ret = FALSE;
570 while (tmp)
572 if (tmp->hmemTaskQ == hQueue)
574 DestroyWindow( tmp->hwndSelf );
575 ret = TRUE;
576 break;
578 tmp2 = WIN_LockWndPtr(tmp->child);
579 if (tmp2 && WIN_ResetQueueWindows(tmp2,hQueue,0))
580 ret = TRUE;
581 else
583 WIN_UpdateWndPtr(&tmp,tmp->next);
585 WIN_ReleaseWndPtr(tmp2);
587 WIN_ReleaseWndPtr(tmp);
588 if (!ret) break;
591 return ret;
594 /***********************************************************************
595 * WIN_CreateDesktopWindow
597 * Create the desktop window.
599 BOOL WIN_CreateDesktopWindow(void)
601 CLASS *class;
602 HWND hwndDesktop;
603 DESKTOP *pDesktop;
605 TRACE(win,"Creating desktop window\n");
608 /* Initialisation of the critical section for thread safeness */
609 InitializeCriticalSection(&WIN_CritSection);
610 MakeCriticalSectionGlobal(&WIN_CritSection);
612 if (!ICONTITLE_Init() ||
613 !WINPOS_CreateInternalPosAtom() ||
614 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
615 return FALSE;
617 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
618 if (!hwndDesktop) return FALSE;
619 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
621 pDesktop = (DESKTOP *) pWndDesktop->wExtra;
622 pDesktop->pDriver = DESKTOP_Driver;
623 pWndDesktop->pDriver = WND_Driver;
625 pDesktop->pDriver->pInitialize(pDesktop);
626 pWndDesktop->pDriver->pInitialize(pWndDesktop);
628 pWndDesktop->next = NULL;
629 pWndDesktop->child = NULL;
630 pWndDesktop->parent = NULL;
631 pWndDesktop->owner = NULL;
632 pWndDesktop->class = class;
633 pWndDesktop->dwMagic = WND_MAGIC;
634 pWndDesktop->hwndSelf = hwndDesktop;
635 pWndDesktop->hInstance = 0;
636 pWndDesktop->rectWindow.left = 0;
637 pWndDesktop->rectWindow.top = 0;
638 pWndDesktop->rectWindow.right = SYSMETRICS_CXSCREEN;
639 pWndDesktop->rectWindow.bottom = SYSMETRICS_CYSCREEN;
640 pWndDesktop->rectClient = pWndDesktop->rectWindow;
641 pWndDesktop->text = NULL;
642 pWndDesktop->hmemTaskQ = GetFastQueue16();
643 pWndDesktop->hrgnUpdate = 0;
644 pWndDesktop->hwndLastActive = hwndDesktop;
645 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
646 WS_CLIPSIBLINGS;
647 pWndDesktop->dwExStyle = 0;
648 pWndDesktop->dce = NULL;
649 pWndDesktop->pVScroll = NULL;
650 pWndDesktop->pHScroll = NULL;
651 pWndDesktop->pProp = NULL;
652 pWndDesktop->wIDmenu = 0;
653 pWndDesktop->helpContext = 0;
654 pWndDesktop->flags = 0;
655 pWndDesktop->hSysMenu = 0;
656 pWndDesktop->userdata = 0;
657 pWndDesktop->winproc = (WNDPROC16)class->winproc;
658 pWndDesktop->irefCount = 0;
660 /* FIXME: How do we know if it should be Unicode or not */
661 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop, class, FALSE))
662 return FALSE;
664 SendMessageA( hwndDesktop, WM_NCCREATE, 0, 0 );
665 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
666 return TRUE;
670 /***********************************************************************
671 * WIN_CreateWindowEx
673 * Implementation of CreateWindowEx().
675 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
676 BOOL win32, BOOL unicode )
678 CLASS *classPtr;
679 WND *wndPtr;
680 HWND retvalue;
681 HWND16 hwnd, hwndLinkAfter;
682 POINT maxSize, maxPos, minTrack, maxTrack;
683 LRESULT (CALLBACK *localSend32)(HWND, UINT, WPARAM, LPARAM);
684 char buffer[256];
686 TRACE(win, "%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
687 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
688 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
689 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
690 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
692 /* Find the parent window */
694 if (cs->hwndParent)
696 /* Make sure parent is valid */
697 if (!IsWindow( cs->hwndParent ))
699 WARN( win, "Bad parent %04x\n", cs->hwndParent );
700 return 0;
702 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
703 WARN( win, "No parent for child window\n" );
704 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
707 /* Find the window class */
708 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
710 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
711 WARN( win, "Bad class '%s'\n", buffer );
712 return 0;
715 /* Fix the lpszClass field: from existing programs, it seems ok to call a CreateWindowXXX
716 * with an atom as the class name, put some programs expect to have a *REAL* string in
717 * lpszClass when the CREATESTRUCT is sent with WM_CREATE
719 if ( !HIWORD(cs->lpszClass) ) {
720 if (unicode) {
721 GlobalGetAtomNameW( classAtom, (LPWSTR)buffer, sizeof(buffer) );
722 } else {
723 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
725 cs->lpszClass = buffer;
728 /* Fix the coordinates */
730 if (cs->x == CW_USEDEFAULT)
732 PDB *pdb = PROCESS_Current();
733 if ( !(cs->style & (WS_CHILD | WS_POPUP))
734 && (pdb->env_db->startup_info->dwFlags & STARTF_USEPOSITION) )
736 cs->x = pdb->env_db->startup_info->dwX;
737 cs->y = pdb->env_db->startup_info->dwY;
739 else
741 cs->x = 0;
742 cs->y = 0;
745 if (cs->cx == CW_USEDEFAULT)
747 PDB *pdb = PROCESS_Current();
748 if ( !(cs->style & (WS_CHILD | WS_POPUP))
749 && (pdb->env_db->startup_info->dwFlags & STARTF_USESIZE) )
751 cs->cx = pdb->env_db->startup_info->dwXSize;
752 cs->cy = pdb->env_db->startup_info->dwYSize;
754 else
756 cs->cx = 600; /* FIXME */
757 cs->cy = 400;
761 /* Create the window structure */
763 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
764 - sizeof(wndPtr->wExtra) )))
766 TRACE(win, "out of memory\n" );
767 return 0;
770 /* Fill the window structure */
772 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
773 wndPtr->next = NULL;
774 wndPtr->child = NULL;
776 if ((cs->style & WS_CHILD) && cs->hwndParent)
778 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
779 wndPtr->owner = NULL;
780 WIN_ReleaseWndPtr(wndPtr->parent);
782 else
784 wndPtr->parent = pWndDesktop;
785 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
786 wndPtr->owner = NULL;
787 else
789 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
790 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
791 WIN_ReleaseWndPtr(wndPtr->owner);
792 WIN_ReleaseWndPtr(tmpWnd);
796 wndPtr->pDriver = wndPtr->parent->pDriver;
797 wndPtr->pDriver->pInitialize(wndPtr);
799 wndPtr->class = classPtr;
800 wndPtr->winproc = classPtr->winproc;
801 wndPtr->dwMagic = WND_MAGIC;
802 wndPtr->hwndSelf = hwnd;
803 wndPtr->hInstance = cs->hInstance;
804 wndPtr->text = NULL;
805 wndPtr->hmemTaskQ = GetFastQueue16();
806 wndPtr->hrgnUpdate = 0;
807 wndPtr->hwndLastActive = hwnd;
808 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
809 wndPtr->dwExStyle = cs->dwExStyle;
810 wndPtr->wIDmenu = 0;
811 wndPtr->helpContext = 0;
812 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
813 wndPtr->pVScroll = NULL;
814 wndPtr->pHScroll = NULL;
815 wndPtr->pProp = NULL;
816 wndPtr->userdata = 0;
817 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
818 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
819 wndPtr->irefCount = 1;
821 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
823 /* Call the WH_CBT hook */
825 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
826 ? HWND_BOTTOM : HWND_TOP;
828 if (HOOK_IsHooked( WH_CBT ))
830 CBT_CREATEWNDA cbtc;
831 LRESULT ret;
833 cbtc.lpcs = cs;
834 cbtc.hwndInsertAfter = hwndLinkAfter;
835 ret = unicode ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
836 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
837 if (ret)
839 TRACE(win, "CBT-hook returned 0\n");
840 wndPtr->pDriver->pFinalize(wndPtr);
841 USER_HEAP_FREE( hwnd );
842 retvalue = 0;
843 goto end;
847 /* Increment class window counter */
849 classPtr->cWindows++;
851 /* Correct the window style */
853 if (!(cs->style & WS_CHILD))
855 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
856 if (!(cs->style & WS_POPUP))
858 wndPtr->dwStyle |= WS_CAPTION;
859 wndPtr->flags |= WIN_NEED_SIZE;
862 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
864 /* Get class or window DC if needed */
866 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
867 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
868 else wndPtr->dce = NULL;
870 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
872 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
874 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
875 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
876 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
877 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
878 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
881 if(cs->style & WS_CHILD)
883 if(cs->cx < 0) cs->cx = 0;
884 if(cs->cy < 0) cs->cy = 0;
886 else
888 if (cs->cx <= 0) cs->cx = 1;
889 if (cs->cy <= 0) cs->cy = 1;
892 wndPtr->rectWindow.left = cs->x;
893 wndPtr->rectWindow.top = cs->y;
894 wndPtr->rectWindow.right = cs->x + cs->cx;
895 wndPtr->rectWindow.bottom = cs->y + cs->cy;
896 wndPtr->rectClient = wndPtr->rectWindow;
898 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
900 retvalue = FALSE;
901 goto end;
904 /* Set the window menu */
906 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
908 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
909 else
911 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
912 if (classPtr->menuNameA)
913 cs->hMenu = HIWORD(classPtr->menuNameA) ?
914 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
915 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
916 #else
917 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
918 if (menuName)
920 if (HIWORD(cs->hInstance))
921 cs->hMenu = LoadMenuA(cs->hInstance,PTR_SEG_TO_LIN(menuName));
922 else
923 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
925 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
927 #endif
930 else wndPtr->wIDmenu = (UINT)cs->hMenu;
932 /* Send the WM_CREATE message
933 * Perhaps we shouldn't allow width/height changes as well.
934 * See p327 in "Internals".
937 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
939 localSend32 = unicode ? SendMessageW : SendMessageA;
940 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
942 /* Insert the window in the linked list */
944 WIN_LinkWindow( hwnd, hwndLinkAfter );
946 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
947 NULL, NULL, 0, &wndPtr->rectClient );
948 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
949 maxPos.y - wndPtr->rectWindow.top);
950 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
952 /* Send the size messages */
954 if (!(wndPtr->flags & WIN_NEED_SIZE))
956 /* send it anyway */
957 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
958 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
959 WARN(win,"sending bogus WM_SIZE message 0x%08lx\n",
960 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
961 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
962 SendMessageA( hwnd, WM_SIZE, SIZE_RESTORED,
963 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
964 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
965 SendMessageA( hwnd, WM_MOVE, 0,
966 MAKELONG( wndPtr->rectClient.left,
967 wndPtr->rectClient.top ) );
970 /* Show the window, maximizing or minimizing if needed */
972 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
974 RECT16 newPos;
975 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
976 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
977 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
978 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
979 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
980 : SWP_NOZORDER | SWP_FRAMECHANGED;
981 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
982 newPos.right, newPos.bottom, swFlag );
985 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
987 /* Notify the parent window only */
989 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
990 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
991 if( !IsWindow(hwnd) )
993 retvalue = 0;
994 goto end;
998 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
1000 /* Call WH_SHELL hook */
1002 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1003 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
1005 TRACE(win, "created window %04x\n", hwnd);
1006 retvalue = hwnd;
1007 goto end;
1009 WIN_UnlinkWindow( hwnd );
1012 /* Abort window creation */
1014 WARN(win, "aborted by WM_xxCREATE!\n");
1015 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1016 retvalue = 0;
1017 end:
1018 WIN_ReleaseWndPtr(wndPtr);
1020 return retvalue;
1024 /***********************************************************************
1025 * CreateWindow16 (USER.41)
1027 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1028 DWORD style, INT16 x, INT16 y, INT16 width,
1029 INT16 height, HWND16 parent, HMENU16 menu,
1030 HINSTANCE16 instance, LPVOID data )
1032 return CreateWindowEx16( 0, className, windowName, style,
1033 x, y, width, height, parent, menu, instance, data );
1037 /***********************************************************************
1038 * CreateWindowEx16 (USER.452)
1040 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1041 LPCSTR windowName, DWORD style, INT16 x,
1042 INT16 y, INT16 width, INT16 height,
1043 HWND16 parent, HMENU16 menu,
1044 HINSTANCE16 instance, LPVOID data )
1046 ATOM classAtom;
1047 CREATESTRUCTA cs;
1049 /* Find the class atom */
1051 if (!(classAtom = GlobalFindAtomA( className )))
1053 fprintf( stderr, "CreateWindowEx16: bad class name " );
1054 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
1055 else fprintf( stderr, "'%s'\n", className );
1056 return 0;
1059 /* Fix the coordinates */
1061 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1062 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1063 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1064 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1066 /* Create the window */
1068 cs.lpCreateParams = data;
1069 cs.hInstance = (HINSTANCE)instance;
1070 cs.hMenu = (HMENU)menu;
1071 cs.hwndParent = (HWND)parent;
1072 cs.style = style;
1073 cs.lpszName = windowName;
1074 cs.lpszClass = className;
1075 cs.dwExStyle = exStyle;
1076 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
1080 /***********************************************************************
1081 * CreateWindowEx32A (USER32.83)
1083 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1084 LPCSTR windowName, DWORD style, INT x,
1085 INT y, INT width, INT height,
1086 HWND parent, HMENU menu,
1087 HINSTANCE instance, LPVOID data )
1089 ATOM classAtom;
1090 CREATESTRUCTA cs;
1092 if(exStyle & WS_EX_MDICHILD)
1093 return MDI_CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1094 /* Find the class atom */
1096 if (!(classAtom = GlobalFindAtomA( className )))
1098 fprintf( stderr, "CreateWindowEx32A: bad class name " );
1099 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
1100 else fprintf( stderr, "'%s'\n", className );
1101 return 0;
1104 /* Create the window */
1106 cs.lpCreateParams = data;
1107 cs.hInstance = instance;
1108 cs.hMenu = menu;
1109 cs.hwndParent = parent;
1110 cs.x = x;
1111 cs.y = y;
1112 cs.cx = width;
1113 cs.cy = height;
1114 cs.style = style;
1115 cs.lpszName = windowName;
1116 cs.lpszClass = className;
1117 cs.dwExStyle = exStyle;
1118 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
1122 /***********************************************************************
1123 * CreateWindowEx32W (USER32.84)
1125 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1126 LPCWSTR windowName, DWORD style, INT x,
1127 INT y, INT width, INT height,
1128 HWND parent, HMENU menu,
1129 HINSTANCE instance, LPVOID data )
1131 ATOM classAtom;
1132 CREATESTRUCTW cs;
1134 if(exStyle & WS_EX_MDICHILD)
1135 return MDI_CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1137 /* Find the class atom */
1139 if (!(classAtom = GlobalFindAtomW( className )))
1141 if (HIWORD(className))
1143 LPSTR cn = HEAP_strdupWtoA( GetProcessHeap(), 0, className );
1144 WARN( win, "Bad class name '%s'\n",cn);
1145 HeapFree( GetProcessHeap(), 0, cn );
1147 else
1148 WARN( win, "Bad class name %p\n", className );
1149 return 0;
1152 /* Create the window */
1154 cs.lpCreateParams = data;
1155 cs.hInstance = instance;
1156 cs.hMenu = menu;
1157 cs.hwndParent = parent;
1158 cs.x = x;
1159 cs.y = y;
1160 cs.cx = width;
1161 cs.cy = height;
1162 cs.style = style;
1163 cs.lpszName = windowName;
1164 cs.lpszClass = className;
1165 cs.dwExStyle = exStyle;
1166 /* Note: we rely on the fact that CREATESTRUCT32A and */
1167 /* CREATESTRUCT32W have the same layout. */
1168 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, TRUE, TRUE );
1172 /***********************************************************************
1173 * WIN_CheckFocus
1175 static void WIN_CheckFocus( WND* pWnd )
1177 if( GetFocus16() == pWnd->hwndSelf )
1178 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
1181 /***********************************************************************
1182 * WIN_SendDestroyMsg
1184 static void WIN_SendDestroyMsg( WND* pWnd )
1186 WIN_CheckFocus(pWnd);
1188 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1189 CLIPBOARD_Driver->pResetOwner( pWnd, TRUE );
1192 * Send the WM_DESTROY to the window.
1194 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1197 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1198 * make sure that the window still exists when we come back.
1200 if (IsWindow(pWnd->hwndSelf))
1202 HWND* pWndArray = NULL;
1203 WND* pChild = NULL;
1204 int nKidCount = 0;
1207 * Now, if the window has kids, we have to send WM_DESTROY messages
1208 * recursively to it's kids. It seems that those calls can also
1209 * trigger re-entrant calls to DestroyWindow for the kids so we must
1210 * protect against corruption of the list of siblings. We first build
1211 * a list of HWNDs representing all the kids.
1213 pChild = WIN_LockWndPtr(pWnd->child);
1214 while( pChild )
1216 nKidCount++;
1217 WIN_UpdateWndPtr(&pChild,pChild->next);
1221 * If there are no kids, we're done.
1223 if (nKidCount==0)
1224 return;
1226 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1229 * Sanity check
1231 if (pWndArray==NULL)
1232 return;
1235 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1236 * call, our linked list of siblings should be safe.
1238 nKidCount = 0;
1239 pChild = WIN_LockWndPtr(pWnd->child);
1240 while( pChild )
1242 pWndArray[nKidCount] = pChild->hwndSelf;
1243 nKidCount++;
1244 WIN_UpdateWndPtr(&pChild,pChild->next);
1248 * Now that we have a list, go through that list again and send the destroy
1249 * message to those windows. We are using the HWND to retrieve the
1250 * WND pointer so we are effectively checking that all the kid windows are
1251 * still valid before sending the message.
1253 while (nKidCount>0)
1255 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1257 if (pChild!=NULL)
1259 WIN_SendDestroyMsg( pChild );
1260 WIN_ReleaseWndPtr(pChild);
1265 * Cleanup
1267 HeapFree(GetProcessHeap(), 0, pWndArray);
1268 WIN_CheckFocus(pWnd);
1270 else
1271 WARN(win, "\tdestroyed itself while in WM_DESTROY!\n");
1275 /***********************************************************************
1276 * DestroyWindow16 (USER.53)
1278 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1280 return DestroyWindow(hwnd);
1284 /***********************************************************************
1285 * DestroyWindow32 (USER32.135)
1287 BOOL WINAPI DestroyWindow( HWND hwnd )
1289 WND * wndPtr;
1290 BOOL retvalue;
1292 TRACE(win, "(%04x)\n", hwnd);
1294 /* Initialization */
1296 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1297 if (wndPtr == pWndDesktop)
1299 WIN_ReleaseWndPtr(wndPtr);
1300 return FALSE; /* Can't destroy desktop */
1303 /* Call hooks */
1305 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1307 retvalue = FALSE;
1308 goto end;
1311 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1313 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1314 /* FIXME: clean up palette - see "Internals" p.352 */
1317 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1318 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1320 /* Notify the parent window only */
1321 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1322 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1323 if( !IsWindow(hwnd) )
1325 retvalue = TRUE;
1326 goto end;
1330 CLIPBOARD_Driver->pResetOwner( wndPtr, FALSE ); /* before the window is unmapped */
1332 /* Hide the window */
1334 if (wndPtr->dwStyle & WS_VISIBLE)
1336 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1337 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1338 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1339 if (!IsWindow(hwnd))
1341 retvalue = TRUE;
1342 goto end;
1346 /* Recursively destroy owned windows */
1348 if( !(wndPtr->dwStyle & WS_CHILD) )
1350 /* make sure top menu popup doesn't get destroyed */
1351 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1353 for (;;)
1355 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1356 while (siblingPtr)
1358 if (siblingPtr->owner == wndPtr)
1360 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1361 break;
1362 else
1363 siblingPtr->owner = NULL;
1365 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1367 if (siblingPtr)
1369 DestroyWindow( siblingPtr->hwndSelf );
1370 WIN_ReleaseWndPtr(siblingPtr);
1372 else break;
1375 if( !Options.managed || EVENT_CheckFocus() )
1376 WINPOS_ActivateOtherWindow(wndPtr);
1378 if( wndPtr->owner &&
1379 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1380 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1383 /* Send destroy messages */
1385 WIN_SendDestroyMsg( wndPtr );
1386 if (!IsWindow(hwnd))
1388 retvalue = TRUE;
1389 goto end;
1392 /* Unlink now so we won't bother with the children later on */
1394 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1396 /* Destroy the window storage */
1398 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1399 retvalue = TRUE;
1400 end:
1401 WIN_ReleaseWndPtr(wndPtr);
1402 return retvalue;
1406 /***********************************************************************
1407 * CloseWindow16 (USER.43)
1409 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1411 return CloseWindow( hwnd );
1415 /***********************************************************************
1416 * CloseWindow32 (USER32.56)
1418 BOOL WINAPI CloseWindow( HWND hwnd )
1420 WND * wndPtr = WIN_FindWndPtr( hwnd );
1421 BOOL retvalue;
1423 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1425 retvalue = FALSE;
1426 goto end;
1428 ShowWindow( hwnd, SW_MINIMIZE );
1429 retvalue = TRUE;
1430 end:
1431 WIN_ReleaseWndPtr(wndPtr);
1432 return retvalue;
1437 /***********************************************************************
1438 * OpenIcon16 (USER.44)
1440 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1442 return OpenIcon( hwnd );
1446 /***********************************************************************
1447 * OpenIcon32 (USER32.410)
1449 BOOL WINAPI OpenIcon( HWND hwnd )
1451 if (!IsIconic( hwnd )) return FALSE;
1452 ShowWindow( hwnd, SW_SHOWNORMAL );
1453 return TRUE;
1457 /***********************************************************************
1458 * WIN_FindWindow
1460 * Implementation of FindWindow() and FindWindowEx().
1462 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1463 LPCSTR title )
1465 WND *pWnd;
1466 HWND retvalue;
1467 CLASS *pClass = NULL;
1469 if (child)
1471 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1472 if (parent)
1474 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1476 retvalue = 0;
1477 goto end;
1480 else if (pWnd->parent != pWndDesktop)
1482 retvalue = 0;
1483 goto end;
1485 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1487 else
1489 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1491 retvalue = 0;
1492 goto end;
1494 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1496 if (!pWnd)
1498 retvalue = 0;
1499 goto end;
1502 /* For a child window, all siblings will have the same hInstance, */
1503 /* so we can look for the class once and for all. */
1505 if (className && (pWnd->dwStyle & WS_CHILD))
1507 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1509 retvalue = 0;
1510 goto end;
1515 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1517 if (className && !(pWnd->dwStyle & WS_CHILD))
1519 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance)))
1520 continue; /* Skip this window */
1523 if (pClass && (pWnd->class != pClass))
1524 continue; /* Not the right class */
1526 /* Now check the title */
1528 if (!title)
1530 retvalue = pWnd->hwndSelf;
1531 goto end;
1533 if (pWnd->text && !strcmp( pWnd->text, title ))
1535 retvalue = pWnd->hwndSelf;
1536 goto end;
1539 retvalue = 0;
1540 end:
1541 WIN_ReleaseWndPtr(pWnd);
1542 return retvalue;
1547 /***********************************************************************
1548 * FindWindow16 (USER.50)
1550 HWND16 WINAPI FindWindow16( SEGPTR className, LPCSTR title )
1552 return FindWindowEx16( 0, 0, className, title );
1556 /***********************************************************************
1557 * FindWindowEx16 (USER.427)
1559 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child,
1560 SEGPTR className, LPCSTR title )
1562 ATOM atom = 0;
1564 TRACE(win, "%04x %04x '%s' '%s'\n", parent,
1565 child, HIWORD(className)?(char *)PTR_SEG_TO_LIN(className):"",
1566 title ? title : "");
1568 if (className)
1570 /* If the atom doesn't exist, then no class */
1571 /* with this name exists either. */
1572 if (!(atom = GlobalFindAtom16( className ))) return 0;
1574 return WIN_FindWindow( parent, child, atom, title );
1578 /***********************************************************************
1579 * FindWindow32A (USER32.198)
1581 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1583 HWND ret = FindWindowExA( 0, 0, className, title );
1584 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1585 return ret;
1589 /***********************************************************************
1590 * FindWindowEx32A (USER32.199)
1592 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1593 LPCSTR className, LPCSTR title )
1595 ATOM atom = 0;
1597 if (className)
1599 /* If the atom doesn't exist, then no class */
1600 /* with this name exists either. */
1601 if (!(atom = GlobalFindAtomA( className )))
1603 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1604 return 0;
1607 return WIN_FindWindow( parent, child, atom, title );
1611 /***********************************************************************
1612 * FindWindowEx32W (USER32.200)
1614 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1615 LPCWSTR className, LPCWSTR title )
1617 ATOM atom = 0;
1618 char *buffer;
1619 HWND hwnd;
1621 if (className)
1623 /* If the atom doesn't exist, then no class */
1624 /* with this name exists either. */
1625 if (!(atom = GlobalFindAtomW( className )))
1627 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1628 return 0;
1631 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1632 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1633 HeapFree( GetProcessHeap(), 0, buffer );
1634 return hwnd;
1638 /***********************************************************************
1639 * FindWindow32W (USER32.201)
1641 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1643 return FindWindowExW( 0, 0, className, title );
1647 /**********************************************************************
1648 * WIN_GetDesktop
1649 * returns a locked pointer
1651 WND *WIN_GetDesktop(void)
1653 return WIN_LockWndPtr(pWndDesktop);
1655 /**********************************************************************
1656 * WIN_ReleaseDesktop
1657 * unlock the desktop pointer
1659 void WIN_ReleaseDesktop(void)
1661 WIN_ReleaseWndPtr(pWndDesktop);
1665 /**********************************************************************
1666 * GetDesktopWindow16 (USER.286)
1668 HWND16 WINAPI GetDesktopWindow16(void)
1670 return (HWND16)pWndDesktop->hwndSelf;
1674 /**********************************************************************
1675 * GetDesktopWindow32 (USER32.232)
1677 HWND WINAPI GetDesktopWindow(void)
1679 return pWndDesktop->hwndSelf;
1683 /**********************************************************************
1684 * GetDesktopHwnd (USER.278)
1686 * Exactly the same thing as GetDesktopWindow(), but not documented.
1687 * Don't ask me why...
1689 HWND16 WINAPI GetDesktopHwnd16(void)
1691 return (HWND16)pWndDesktop->hwndSelf;
1695 /*******************************************************************
1696 * EnableWindow16 (USER.34)
1698 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1700 return EnableWindow( hwnd, enable );
1704 /*******************************************************************
1705 * EnableWindow32 (USER32.172)
1707 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1709 WND *wndPtr;
1710 BOOL retvalue;
1712 TRACE(win,"EnableWindow32: ( %x, %d )\n", hwnd, enable);
1714 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1715 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1717 /* Enable window */
1718 wndPtr->dwStyle &= ~WS_DISABLED;
1720 if( wndPtr->flags & WIN_NATIVE )
1721 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
1723 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1724 retvalue = TRUE;
1725 goto end;
1727 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1729 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1731 /* Disable window */
1732 wndPtr->dwStyle |= WS_DISABLED;
1734 if( wndPtr->flags & WIN_NATIVE )
1735 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
1737 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus() ))
1739 SetFocus( 0 ); /* A disabled window can't have the focus */
1741 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
1743 ReleaseCapture(); /* A disabled window can't capture the mouse */
1745 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1746 retvalue = FALSE;
1747 goto end;
1749 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1750 end:
1751 WIN_ReleaseWndPtr(wndPtr);
1752 return retvalue;
1756 /***********************************************************************
1757 * IsWindowEnabled16 (USER.35)
1759 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1761 return IsWindowEnabled(hWnd);
1765 /***********************************************************************
1766 * IsWindowEnabled32 (USER32.349)
1768 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1770 WND * wndPtr;
1771 BOOL retvalue;
1773 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1774 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1775 WIN_ReleaseWndPtr(wndPtr);
1776 return retvalue;
1781 /***********************************************************************
1782 * IsWindowUnicode (USER32.350)
1784 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1786 WND * wndPtr;
1787 BOOL retvalue;
1789 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1790 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1791 WIN_ReleaseWndPtr(wndPtr);
1792 return retvalue;
1796 /**********************************************************************
1797 * GetWindowWord16 (USER.133)
1799 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1801 return GetWindowWord( hwnd, offset );
1805 /**********************************************************************
1806 * GetWindowWord32 (USER32.314)
1808 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1810 WORD retvalue;
1811 WND * wndPtr = WIN_FindWndPtr( hwnd );
1812 if (!wndPtr) return 0;
1813 if (offset >= 0)
1815 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1817 WARN( win, "Invalid offset %d\n", offset );
1818 retvalue = 0;
1819 goto end;
1821 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1822 goto end;
1824 switch(offset)
1826 case GWW_ID:
1827 if (HIWORD(wndPtr->wIDmenu))
1828 WARN( win,"GWW_ID: discards high bits of 0x%08x!\n",
1829 wndPtr->wIDmenu);
1830 retvalue = (WORD)wndPtr->wIDmenu;
1831 goto end;
1832 case GWW_HWNDPARENT:
1833 retvalue = GetParent(hwnd);
1834 goto end;
1835 case GWW_HINSTANCE:
1836 if (HIWORD(wndPtr->hInstance))
1837 WARN(win,"GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1838 wndPtr->hInstance);
1839 retvalue = (WORD)wndPtr->hInstance;
1840 goto end;
1841 default:
1842 WARN( win, "Invalid offset %d\n", offset );
1843 retvalue = 0;
1844 goto end;
1846 end:
1847 WIN_ReleaseWndPtr(wndPtr);
1848 return retvalue;
1852 /**********************************************************************
1853 * WIN_GetWindowInstance
1855 HINSTANCE WIN_GetWindowInstance( HWND hwnd )
1858 WND * wndPtr = WIN_FindWndPtr( hwnd );
1859 if (!wndPtr) return (HINSTANCE)0;
1860 WIN_ReleaseWndPtr(wndPtr);
1861 return wndPtr->hInstance;
1866 /**********************************************************************
1867 * SetWindowWord16 (USER.134)
1869 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1871 return SetWindowWord( hwnd, offset, newval );
1875 /**********************************************************************
1876 * SetWindowWord32 (USER32.524)
1878 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1880 WORD *ptr, retval;
1881 WND * wndPtr = WIN_FindWndPtr( hwnd );
1882 if (!wndPtr) return 0;
1883 if (offset >= 0)
1885 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1887 WARN( win, "Invalid offset %d\n", offset );
1888 retval = 0;
1889 goto end;
1891 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1893 else switch(offset)
1895 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1896 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1897 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1898 goto end;
1899 default:
1900 WARN( win, "Invalid offset %d\n", offset );
1901 retval = 0;
1902 goto end;
1904 retval = *ptr;
1905 *ptr = newval;
1906 end:
1907 WIN_ReleaseWndPtr(wndPtr);
1908 return retval;
1912 /**********************************************************************
1913 * WIN_GetWindowLong
1915 * Helper function for GetWindowLong().
1917 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1919 LONG retvalue;
1920 WND * wndPtr = WIN_FindWndPtr( hwnd );
1921 if (!wndPtr) return 0;
1922 if (offset >= 0)
1924 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1926 WARN( win, "Invalid offset %d\n", offset );
1927 retvalue = 0;
1928 goto end;
1930 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1931 /* Special case for dialog window procedure */
1932 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1934 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1935 goto end;
1937 goto end;
1939 switch(offset)
1941 case GWL_USERDATA: retvalue = wndPtr->userdata;
1942 goto end;
1943 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1944 goto end;
1945 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1946 goto end;
1947 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1948 goto end;
1949 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1950 type );
1951 goto end;
1952 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1953 goto end;
1954 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1955 goto end;
1956 default:
1957 WARN( win, "Unknown offset %d\n", offset );
1959 retvalue = 0;
1960 end:
1961 WIN_ReleaseWndPtr(wndPtr);
1962 return retvalue;
1966 /**********************************************************************
1967 * WIN_SetWindowLong
1969 * Helper function for SetWindowLong().
1971 * 0 is the failure code. However, in the case of failure SetLastError
1972 * must be set to distinguish between a 0 return value and a failure.
1974 * FIXME: The error values for SetLastError may not be right. Can
1975 * someone check with the real thing?
1977 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1978 WINDOWPROCTYPE type )
1980 LONG *ptr, retval;
1981 WND * wndPtr = WIN_FindWndPtr( hwnd );
1982 STYLESTRUCT style;
1984 TRACE(win,"%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1986 if (!wndPtr)
1988 /* Is this the right error? */
1989 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1990 return 0;
1993 if (offset >= 0)
1995 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1997 WARN( win, "Invalid offset %d\n", offset );
1999 /* Is this the right error? */
2000 SetLastError( ERROR_OUTOFMEMORY );
2002 retval = 0;
2003 goto end;
2005 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2006 /* Special case for dialog window procedure */
2007 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2009 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2010 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2011 type, WIN_PROC_WINDOW );
2012 goto end;
2015 else switch(offset)
2017 case GWL_ID:
2018 ptr = (DWORD*)&wndPtr->wIDmenu;
2019 break;
2020 case GWL_HINSTANCE:
2021 retval = SetWindowWord( hwnd, offset, newval );
2022 goto end;
2023 case GWL_WNDPROC:
2024 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2025 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2026 type, WIN_PROC_WINDOW );
2027 goto end;;
2028 case GWL_STYLE:
2029 style.styleOld = wndPtr->dwStyle;
2030 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
2031 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
2033 if (wndPtr->flags & WIN_ISWIN32)
2034 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
2035 wndPtr->dwStyle = style.styleNew;
2036 if (wndPtr->flags & WIN_ISWIN32)
2037 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
2038 retval = style.styleOld;
2039 goto end;
2041 case GWL_USERDATA:
2042 ptr = &wndPtr->userdata;
2043 break;
2044 case GWL_EXSTYLE:
2045 style.styleOld = wndPtr->dwExStyle;
2046 style.styleNew = newval;
2047 if (wndPtr->flags & WIN_ISWIN32)
2048 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
2049 wndPtr->dwExStyle = newval;
2050 if (wndPtr->flags & WIN_ISWIN32)
2051 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
2052 retval = style.styleOld;
2053 goto end;
2055 default:
2056 WARN( win, "Invalid offset %d\n", offset );
2058 /* Don't think this is right error but it should do */
2059 SetLastError( ERROR_OUTOFMEMORY );
2061 retval = 0;
2062 goto end;
2064 retval = *ptr;
2065 *ptr = newval;
2066 end:
2067 WIN_ReleaseWndPtr(wndPtr);
2068 return retval;
2072 /**********************************************************************
2073 * GetWindowLong16 (USER.135)
2075 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2077 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2081 /**********************************************************************
2082 * GetWindowLong32A (USER32.305)
2084 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2086 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2090 /**********************************************************************
2091 * GetWindowLong32W (USER32.306)
2093 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2095 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2099 /**********************************************************************
2100 * SetWindowLong16 (USER.136)
2102 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2104 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2108 /**********************************************************************
2109 * SetWindowLong32A (USER32.517)
2111 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2113 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2117 /**********************************************************************
2118 * SetWindowLong32W (USER32.518) Set window attribute
2120 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2121 * value in a window's extra memory.
2123 * The _hwnd_ parameter specifies the window. is the handle to a
2124 * window that has extra memory. The _newval_ parameter contains the
2125 * new attribute or extra memory value. If positive, the _offset_
2126 * parameter is the byte-addressed location in the window's extra
2127 * memory to set. If negative, _offset_ specifies the window
2128 * attribute to set, and should be one of the following values:
2130 * GWL_EXSTYLE The window's extended window style
2132 * GWL_STYLE The window's window style.
2134 * GWL_WNDPROC Pointer to the window's window procedure.
2136 * GWL_HINSTANCE The window's pplication instance handle.
2138 * GWL_ID The window's identifier.
2140 * GWL_USERDATA The window's user-specified data.
2142 * If the window is a dialog box, the _offset_ parameter can be one of
2143 * the following values:
2145 * DWL_DLGPROC The address of the window's dialog box procedure.
2147 * DWL_MSGRESULT The return value of a message
2148 * that the dialog box procedure processed.
2150 * DWL_USER Application specific information.
2152 * RETURNS
2154 * If successful, returns the previous value located at _offset_. Otherwise,
2155 * returns 0.
2157 * NOTES
2159 * Extra memory for a window class is specified by a nonzero cbWndExtra
2160 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2161 * time of class creation.
2163 * Using GWL_WNDPROC to set a new window procedure effectively creates
2164 * a window subclass. Use CallWindowProc() in the new windows procedure
2165 * to pass messages to the superclass's window procedure.
2167 * The user data is reserved for use by the application which created
2168 * the window.
2170 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2171 * instead, call the EnableWindow() function to change the window's
2172 * disabled state.
2174 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2175 * SetParent() instead.
2177 * Win95:
2178 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2179 * it sends WM_STYLECHANGING before changing the settings
2180 * and WM_STYLECHANGED afterwards.
2181 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2183 * BUGS
2185 * GWL_STYLE does not dispatch WM_STYLE... messages.
2187 * CONFORMANCE
2189 * ECMA-234, Win32
2192 LONG WINAPI SetWindowLongW(
2193 HWND hwnd, /* window to alter */
2194 INT offset, /* offset, in bytes, of location to alter */
2195 LONG newval /* new value of location */
2197 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2201 /*******************************************************************
2202 * GetWindowText16 (USER.36)
2204 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2206 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2210 /*******************************************************************
2211 * GetWindowText32A (USER32.309)
2213 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2215 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2216 (LPARAM)lpString );
2219 /*******************************************************************
2220 * InternalGetWindowText (USER32.326)
2222 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2224 FIXME(win,"(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2225 return GetWindowTextW(hwnd,lpString,nMaxCount);
2229 /*******************************************************************
2230 * GetWindowText32W (USER32.312)
2232 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2234 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2235 (LPARAM)lpString );
2239 /*******************************************************************
2240 * SetWindowText16 (USER.37)
2242 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2244 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2248 /*******************************************************************
2249 * SetWindowText32A (USER32.521)
2251 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2253 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2257 /*******************************************************************
2258 * SetWindowText32W (USER32.523)
2260 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2262 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2266 /*******************************************************************
2267 * GetWindowTextLength16 (USER.38)
2269 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2271 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2275 /*******************************************************************
2276 * GetWindowTextLength32A (USER32.310)
2278 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2280 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2283 /*******************************************************************
2284 * GetWindowTextLength32W (USER32.311)
2286 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2288 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2292 /*******************************************************************
2293 * IsWindow16 (USER.47)
2295 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2297 return IsWindow( hwnd );
2300 void WINAPI WIN16_IsWindow16( CONTEXT *context )
2302 WORD *stack = PTR_SEG_OFF_TO_LIN(SS_reg(context), SP_reg(context));
2303 HWND16 hwnd = (HWND16)stack[2];
2305 AX_reg(context) = IsWindow( hwnd );
2306 ES_reg(context) = USER_HeapSel;
2310 /*******************************************************************
2311 * IsWindow32 (USER32.348)
2313 BOOL WINAPI IsWindow( HWND hwnd )
2315 WND * wndPtr;
2316 BOOL retvalue;
2318 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2319 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2320 WIN_ReleaseWndPtr(wndPtr);
2321 return retvalue;
2326 /*****************************************************************
2327 * GetParent16 (USER.46)
2329 HWND16 WINAPI GetParent16( HWND16 hwnd )
2331 return (HWND16)GetParent( hwnd );
2335 /*****************************************************************
2336 * GetParent32 (USER32.278)
2338 HWND WINAPI GetParent( HWND hwnd )
2340 WND *wndPtr;
2341 HWND retvalue;
2343 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2344 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2346 WIN_ReleaseWndPtr(wndPtr);
2347 return 0;
2349 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2350 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2352 WIN_ReleaseWndPtr(wndPtr);
2353 return retvalue;
2357 /*****************************************************************
2358 * WIN_GetTopParent
2360 * Get the top-level parent for a child window.
2361 * returns a locked pointer
2363 WND* WIN_GetTopParentPtr( WND* pWnd )
2365 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2367 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2369 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2371 return tmpWnd;
2374 /*****************************************************************
2375 * WIN_GetTopParent
2377 * Get the top-level parent for a child window.
2379 HWND WIN_GetTopParent( HWND hwnd )
2381 HWND retvalue;
2382 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2383 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2385 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2386 WIN_ReleaseWndPtr(tmpPtr);
2387 WIN_ReleaseWndPtr(wndPtr);
2388 return retvalue;
2392 /*****************************************************************
2393 * SetParent16 (USER.233)
2395 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2397 return SetParent( hwndChild, hwndNewParent );
2401 /*****************************************************************
2402 * SetParent32 (USER32.495)
2404 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2406 WND *wndPtr;
2407 DWORD dwStyle;
2408 WND *pWndNewParent;
2409 WND *pWndOldParent;
2410 HWND retvalue;
2413 if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
2415 dwStyle = wndPtr->dwStyle;
2417 pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
2418 : WIN_LockWndPtr(pWndDesktop);
2420 /* Windows hides the window first, then shows it again
2421 * including the WM_SHOWWINDOW messages and all */
2422 if (dwStyle & WS_VISIBLE)
2423 ShowWindow( hwndChild, SW_HIDE );
2425 pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
2427 /* SetParent32 additionally needs to make hwndChild the topmost window
2428 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2429 WM_WINDOWPOSCHANGED notification messages.
2431 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2432 SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2433 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2434 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2436 retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
2438 WIN_ReleaseWndPtr(pWndOldParent);
2439 WIN_ReleaseWndPtr(pWndNewParent);
2440 WIN_ReleaseWndPtr(wndPtr);
2442 return retvalue;
2446 /*******************************************************************
2447 * IsChild16 (USER.48)
2449 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2451 return IsChild(parent,child);
2455 /*******************************************************************
2456 * IsChild32 (USER32.339)
2458 BOOL WINAPI IsChild( HWND parent, HWND child )
2460 WND * wndPtr = WIN_FindWndPtr( child );
2461 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2463 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2464 if (wndPtr->hwndSelf == parent)
2466 WIN_ReleaseWndPtr(wndPtr);
2467 return TRUE;
2470 WIN_ReleaseWndPtr(wndPtr);
2471 return FALSE;
2475 /***********************************************************************
2476 * IsWindowVisible16 (USER.49)
2478 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2480 return IsWindowVisible(hwnd);
2484 /***********************************************************************
2485 * IsWindowVisible32 (USER32.351)
2487 BOOL WINAPI IsWindowVisible( HWND hwnd )
2489 BOOL retval;
2490 WND *wndPtr = WIN_FindWndPtr( hwnd );
2491 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2493 if (!(wndPtr->dwStyle & WS_VISIBLE))
2495 WIN_ReleaseWndPtr(wndPtr);
2496 return FALSE;
2498 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2500 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2501 WIN_ReleaseWndPtr(wndPtr);
2502 return retval;
2507 /***********************************************************************
2508 * WIN_IsWindowDrawable
2510 * hwnd is drawable when it is visible, all parents are not
2511 * minimized, and it is itself not minimized unless we are
2512 * trying to draw its default class icon.
2514 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2516 if( (wnd->dwStyle & WS_MINIMIZE &&
2517 icon && wnd->class->hIcon) ||
2518 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2519 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2520 if( wnd->dwStyle & WS_MINIMIZE ||
2521 !(wnd->dwStyle & WS_VISIBLE) ) break;
2522 return (wnd == NULL);
2526 /*******************************************************************
2527 * GetTopWindow16 (USER.229)
2529 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2531 return GetTopWindow(hwnd);
2535 /*******************************************************************
2536 * GetTopWindow32 (USER.229)
2538 HWND WINAPI GetTopWindow( HWND hwnd )
2540 HWND retval;
2541 WND * wndPtr = WIN_FindWndPtr( hwnd );
2542 if (wndPtr && wndPtr->child)
2544 retval = wndPtr->child->hwndSelf;
2546 else retval = 0;
2547 WIN_ReleaseWndPtr(wndPtr);
2548 return retval;
2552 /*******************************************************************
2553 * GetWindow16 (USER.262)
2555 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2557 return GetWindow( hwnd,rel );
2561 /*******************************************************************
2562 * GetWindow32 (USER32.302)
2564 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2566 HWND retval;
2568 WND * wndPtr = WIN_FindWndPtr( hwnd );
2569 if (!wndPtr) return 0;
2570 switch(rel)
2572 case GW_HWNDFIRST:
2573 if (wndPtr->parent) retval = wndPtr->parent->child->hwndSelf;
2574 else retval = 0;
2575 goto end;
2577 case GW_HWNDLAST:
2578 if (!wndPtr->parent)
2580 retval = 0; /* Desktop window */
2581 goto end;
2583 while (wndPtr->next)
2585 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2587 retval = wndPtr->hwndSelf;
2588 goto end;
2590 case GW_HWNDNEXT:
2591 if (!wndPtr->next) retval = 0;
2592 else retval = wndPtr->next->hwndSelf;
2593 goto end;
2595 case GW_HWNDPREV:
2596 if (!wndPtr->parent)
2598 retval = 0; /* Desktop window */
2599 goto end;
2601 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2602 if (wndPtr->hwndSelf == hwnd)
2604 retval = 0; /* First in list */
2605 goto end;
2607 while (wndPtr->next)
2609 if (wndPtr->next->hwndSelf == hwnd)
2611 retval = wndPtr->hwndSelf;
2612 goto end;
2614 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2616 retval = 0;
2617 goto end;
2619 case GW_OWNER:
2620 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2621 goto end;
2623 case GW_CHILD:
2624 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2625 goto end;
2627 retval = 0;
2628 end:
2629 WIN_ReleaseWndPtr(wndPtr);
2630 return retval;
2634 /*******************************************************************
2635 * GetNextWindow16 (USER.230)
2637 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2639 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2640 return GetWindow16( hwnd, flag );
2643 /*******************************************************************
2644 * ShowOwnedPopups16 (USER.265)
2646 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2648 ShowOwnedPopups( owner, fShow );
2652 /*******************************************************************
2653 * ShowOwnedPopups32 (USER32.531)
2655 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2657 WND *pWnd;
2658 pWnd = WIN_LockWndPtr(pWndDesktop->child);
2659 while (pWnd)
2661 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
2662 (pWnd->dwStyle & WS_POPUP))
2663 ShowWindow( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
2664 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2666 return TRUE;
2670 /*******************************************************************
2671 * GetLastActivePopup16 (USER.287)
2673 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2675 return GetLastActivePopup( hwnd );
2678 /*******************************************************************
2679 * GetLastActivePopup32 (USER32.256)
2681 HWND WINAPI GetLastActivePopup( HWND hwnd )
2683 WND *wndPtr;
2684 HWND retval;
2685 wndPtr = WIN_FindWndPtr(hwnd);
2686 if (!wndPtr) return hwnd;
2687 retval = wndPtr->hwndLastActive;
2688 WIN_ReleaseWndPtr(wndPtr);
2689 return retval;
2693 /*******************************************************************
2694 * WIN_BuildWinArray
2696 * Build an array of pointers to the children of a given window.
2697 * The array must be freed with HeapFree(SystemHeap). Return NULL
2698 * when no windows are found.
2700 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2702 /* Future : this function will lock all windows associated with this array */
2704 WND **list, **ppWnd;
2705 WND *pWnd;
2706 UINT count = 0, skipOwned, skipHidden;
2707 DWORD skipFlags;
2709 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2710 skipOwned = bwaFlags & BWA_SKIPOWNED;
2711 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2712 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2714 /* First count the windows */
2716 if (!wndPtr)
2717 wndPtr = WIN_GetDesktop();
2719 pWnd = WIN_LockWndPtr(wndPtr->child);
2720 while (pWnd)
2722 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2723 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2724 count++;
2725 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2728 if( count )
2730 /* Now build the list of all windows */
2732 if ((list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * (count + 1))))
2734 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2736 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2737 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2739 *ppWnd++ = pWnd;
2740 count++;
2743 WIN_ReleaseWndPtr(pWnd);
2744 *ppWnd = NULL;
2746 else count = 0;
2747 } else list = NULL;
2749 if( pTotal ) *pTotal = count;
2750 return list;
2752 /*******************************************************************
2753 * WIN_ReleaseWinArray
2755 void WIN_ReleaseWinArray(WND **wndArray)
2757 /* Future : this function will also unlock all windows associated with wndArray */
2758 HeapFree( SystemHeap, 0, wndArray );
2762 /*******************************************************************
2763 * EnumWindows16 (USER.54)
2765 BOOL16 WINAPI EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
2767 WND **list, **ppWnd;
2769 /* We have to build a list of all windows first, to avoid */
2770 /* unpleasant side-effects, for instance if the callback */
2771 /* function changes the Z-order of the windows. */
2773 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2775 WIN_ReleaseDesktop();
2776 return FALSE;
2779 /* Now call the callback function for every window */
2781 for (ppWnd = list; *ppWnd; ppWnd++)
2783 LRESULT lpEnumFuncRetval;
2784 int iWndsLocks = 0;
2785 /* Make sure that the window still exists */
2786 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2788 /* To avoid any deadlocks, all the locks on the windows
2789 structures must be suspended before the control
2790 is passed to the application */
2791 iWndsLocks = WIN_SuspendWndsLock();
2792 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2793 WIN_RestoreWndsLock(iWndsLocks);
2795 if (!lpEnumFuncRetval) break;
2797 WIN_ReleaseWinArray(list);
2798 WIN_ReleaseDesktop();
2799 return TRUE;
2803 /*******************************************************************
2804 * EnumWindows32 (USER32.193)
2806 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2808 return (BOOL)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2812 /**********************************************************************
2813 * EnumTaskWindows16 (USER.225)
2815 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2816 LPARAM lParam )
2818 WND **list, **ppWnd;
2820 /* This function is the same as EnumWindows(), */
2821 /* except for an added check on the window's task. */
2823 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2825 WIN_ReleaseDesktop();
2826 return FALSE;
2829 /* Now call the callback function for every window */
2831 for (ppWnd = list; *ppWnd; ppWnd++)
2833 LRESULT funcRetval;
2834 int iWndsLocks = 0;
2835 /* Make sure that the window still exists */
2836 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2837 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2839 /* To avoid any deadlocks, all the locks on the windows
2840 structures must be suspended before the control
2841 is passed to the application */
2842 iWndsLocks = WIN_SuspendWndsLock();
2843 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2844 WIN_RestoreWndsLock(iWndsLocks);
2846 if (!funcRetval) break;
2848 WIN_ReleaseWinArray(list);
2849 WIN_ReleaseDesktop();
2850 return TRUE;
2854 /**********************************************************************
2855 * EnumThreadWindows (USER32.190)
2857 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2859 THDB *tdb = THREAD_IdToTHDB(id);
2861 return (BOOL16)EnumTaskWindows16(tdb->teb.htask16, (WNDENUMPROC16)func, lParam);
2865 /**********************************************************************
2866 * WIN_EnumChildWindows
2868 * Helper function for EnumChildWindows().
2870 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2871 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 * EnumChildWindows16 (USER.55)
2906 BOOL16 WINAPI EnumChildWindows16( HWND16 parent, WNDENUMPROC16 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 * EnumChildWindows32 (USER32.178)
2927 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2928 LPARAM lParam )
2930 return (BOOL)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2931 lParam );
2935 /*******************************************************************
2936 * AnyPopup16 (USER.52)
2938 BOOL16 WINAPI AnyPopup16(void)
2940 return AnyPopup();
2944 /*******************************************************************
2945 * AnyPopup32 (USER32.4)
2947 BOOL WINAPI AnyPopup(void)
2949 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2950 BOOL retvalue;
2952 while (wndPtr)
2954 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2956 retvalue = TRUE;
2957 goto end;
2959 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2961 retvalue = FALSE;
2962 end:
2963 WIN_ReleaseWndPtr(wndPtr);
2964 return retvalue;
2968 /*******************************************************************
2969 * FlashWindow16 (USER.105)
2971 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2973 return FlashWindow( hWnd, bInvert );
2977 /*******************************************************************
2978 * FlashWindow32 (USER32.202)
2980 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2982 WND *wndPtr = WIN_FindWndPtr(hWnd);
2984 TRACE(win,"%04x\n", hWnd);
2986 if (!wndPtr) return FALSE;
2988 if (wndPtr->dwStyle & WS_MINIMIZE)
2990 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2992 HDC hDC = GetDC(hWnd);
2994 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2995 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2997 ReleaseDC( hWnd, hDC );
2998 wndPtr->flags |= WIN_NCACTIVATED;
3000 else
3002 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
3003 RDW_UPDATENOW | RDW_FRAME, 0 );
3004 wndPtr->flags &= ~WIN_NCACTIVATED;
3006 WIN_ReleaseWndPtr(wndPtr);
3007 return TRUE;
3009 else
3011 WPARAM16 wparam;
3012 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3013 else wparam = (hWnd == GetActiveWindow());
3015 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3016 WIN_ReleaseWndPtr(wndPtr);
3017 return wparam;
3022 /*******************************************************************
3023 * SetSysModalWindow16 (USER.188)
3025 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3027 HWND hWndOldModal = hwndSysModal;
3028 hwndSysModal = hWnd;
3029 FIXME(win, "EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3030 return hWndOldModal;
3034 /*******************************************************************
3035 * GetSysModalWindow16 (USER.52)
3037 HWND16 WINAPI GetSysModalWindow16(void)
3039 return hwndSysModal;
3043 /*******************************************************************
3044 * GetWindowContextHelpId (USER32.303)
3046 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3048 DWORD retval;
3049 WND *wnd = WIN_FindWndPtr( hwnd );
3050 if (!wnd) return 0;
3051 retval = wnd->helpContext;
3052 WIN_ReleaseWndPtr(wnd);
3053 return retval;
3057 /*******************************************************************
3058 * SetWindowContextHelpId (USER32.515)
3060 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3062 WND *wnd = WIN_FindWndPtr( hwnd );
3063 if (!wnd) return FALSE;
3064 wnd->helpContext = id;
3065 WIN_ReleaseWndPtr(wnd);
3066 return TRUE;
3070 /*******************************************************************
3071 * DRAG_QueryUpdate
3073 * recursively find a child that contains spDragInfo->pt point
3074 * and send WM_QUERYDROPOBJECT
3076 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3078 BOOL16 wParam,bResult = 0;
3079 POINT pt;
3080 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
3081 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3082 RECT tempRect;
3084 if( !ptrQueryWnd || !ptrDragInfo )
3086 WIN_ReleaseWndPtr(ptrQueryWnd);
3087 return 0;
3090 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3092 GetWindowRect(hQueryWnd,&tempRect);
3094 if( !PtInRect(&tempRect,pt) ||
3095 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3097 WIN_ReleaseWndPtr(ptrQueryWnd);
3098 return 0;
3101 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3103 tempRect = ptrQueryWnd->rectClient;
3104 if(ptrQueryWnd->dwStyle & WS_CHILD)
3105 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3106 (LPPOINT)&tempRect, 2 );
3108 if (PtInRect( &tempRect, pt))
3110 wParam = 0;
3112 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3114 if( ptrWnd->dwStyle & WS_VISIBLE )
3116 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3117 if (PtInRect( &tempRect, pt )) break;
3121 if(ptrWnd)
3123 TRACE(msg,"hwnd = %04x, %d %d - %d %d\n",
3124 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3125 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3126 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3127 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3129 WIN_ReleaseWndPtr(ptrWnd);
3132 if(bResult)
3134 WIN_ReleaseWndPtr(ptrQueryWnd);
3135 return bResult;
3138 else wParam = 1;
3140 else wParam = 1;
3142 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3144 ptrDragInfo->hScope = hQueryWnd;
3146 bResult = ( bNoSend )
3147 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3148 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3149 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3150 if( !bResult )
3151 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3153 WIN_ReleaseWndPtr(ptrQueryWnd);
3154 return bResult;
3158 /*******************************************************************
3159 * DragDetect (USER.465)
3161 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3163 POINT pt32;
3164 CONV_POINT16TO32( &pt, &pt32 );
3165 return DragDetect( hWnd, pt32 );
3168 /*******************************************************************
3169 * DragDetect32 (USER32.151)
3171 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3173 MSG16 msg;
3174 RECT16 rect;
3176 rect.left = pt.x - wDragWidth;
3177 rect.right = pt.x + wDragWidth;
3179 rect.top = pt.y - wDragHeight;
3180 rect.bottom = pt.y + wDragHeight;
3182 SetCapture(hWnd);
3184 while(1)
3186 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3188 if( msg.message == WM_LBUTTONUP )
3190 ReleaseCapture();
3191 return 0;
3193 if( msg.message == WM_MOUSEMOVE )
3195 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
3197 ReleaseCapture();
3198 return 1;
3202 WaitMessage();
3204 return 0;
3207 /******************************************************************************
3208 * DragObject16 (USER.464)
3210 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3211 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3213 MSG16 msg;
3214 LPDRAGINFO lpDragInfo;
3215 SEGPTR spDragInfo;
3216 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3217 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
3218 WND *wndPtr = WIN_FindWndPtr(hWnd);
3219 HCURSOR16 hCurrentCursor = 0;
3220 HWND16 hCurrentWnd = 0;
3222 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
3223 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
3225 if( !lpDragInfo || !spDragInfo )
3227 WIN_ReleaseWndPtr(wndPtr);
3228 return 0L;
3231 hBummer = LoadCursor16(0, IDC_BUMMER16);
3233 if( !hBummer || !wndPtr )
3235 GlobalFree16(hDragInfo);
3236 WIN_ReleaseWndPtr(wndPtr);
3237 return 0L;
3240 if(hCursor)
3242 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3244 GlobalFree16(hDragInfo);
3245 WIN_ReleaseWndPtr(wndPtr);
3246 return 0L;
3249 if( hDragCursor == hCursor ) hDragCursor = 0;
3250 else hCursor = hDragCursor;
3252 hOldCursor = SetCursor(hDragCursor);
3255 lpDragInfo->hWnd = hWnd;
3256 lpDragInfo->hScope = 0;
3257 lpDragInfo->wFlags = wObj;
3258 lpDragInfo->hList = szList; /* near pointer! */
3259 lpDragInfo->hOfStruct = hOfStruct;
3260 lpDragInfo->l = 0L;
3262 SetCapture(hWnd);
3263 ShowCursor( TRUE );
3267 do{ WaitMessage(); }
3268 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3270 *(lpDragInfo+1) = *lpDragInfo;
3272 lpDragInfo->pt = msg.pt;
3274 /* update DRAGINFO struct */
3275 TRACE(msg,"lpDI->hScope = %04x\n",lpDragInfo->hScope);
3277 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3278 hCurrentCursor = hCursor;
3279 else
3281 hCurrentCursor = hBummer;
3282 lpDragInfo->hScope = 0;
3284 if( hCurrentCursor )
3285 SetCursor(hCurrentCursor);
3287 /* send WM_DRAGLOOP */
3288 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3289 (LPARAM) spDragInfo );
3290 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3291 if( hCurrentWnd != lpDragInfo->hScope )
3293 if( hCurrentWnd )
3294 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3295 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
3296 HIWORD(spDragInfo)) );
3297 hCurrentWnd = lpDragInfo->hScope;
3298 if( hCurrentWnd )
3299 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3301 else
3302 if( hCurrentWnd )
3303 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3305 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3307 ReleaseCapture();
3308 ShowCursor( FALSE );
3310 if( hCursor )
3312 SetCursor( hOldCursor );
3313 if (hDragCursor) DestroyCursor( hDragCursor );
3316 if( hCurrentCursor != hBummer )
3317 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3318 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3319 else
3320 msg.lParam = 0;
3321 GlobalFree16(hDragInfo);
3322 WIN_ReleaseWndPtr(wndPtr);
3324 return (DWORD)(msg.lParam);