Made some local functions static.
[wine.git] / windows / win.c
blobab364d7edf22b2c456b7118629ab410afea2cb23
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include <string.h>
9 #include "windef.h"
10 #include "wingdi.h"
11 #include "wine/winbase16.h"
12 #include "wine/winuser16.h"
13 #include "options.h"
14 #include "class.h"
15 #include "win.h"
16 #include "heap.h"
17 #include "user.h"
18 #include "dce.h"
19 #include "cursoricon.h"
20 #include "hook.h"
21 #include "menu.h"
22 #include "message.h"
23 #include "nonclient.h"
24 #include "queue.h"
25 #include "winpos.h"
26 #include "clipboard.h"
27 #include "winproc.h"
28 #include "task.h"
29 #include "thread.h"
30 #include "process.h"
31 #include "winerror.h"
32 #include "mdi.h"
33 #include "local.h"
34 #include "desktop.h"
35 #include "syslevel.h"
36 #include "stackframe.h"
37 #include "debugtools.h"
39 DEFAULT_DEBUG_CHANNEL(win)
40 DECLARE_DEBUG_CHANNEL(msg)
42 /**********************************************************************/
44 WND_DRIVER *WND_Driver = NULL;
46 /* Desktop window */
47 static WND *pWndDesktop = NULL;
49 static HWND hwndSysModal = 0;
51 static WORD wDragWidth = 4;
52 static WORD wDragHeight= 3;
54 /* thread safeness */
55 static SYSLEVEL WIN_SysLevel;
57 /***********************************************************************
58 * WIN_Init
59 */
60 void WIN_Init( void )
62 /* Initialisation of the critical section for thread safeness */
63 _CreateSysLevel( &WIN_SysLevel, 2 );
66 /***********************************************************************
67 * WIN_LockWnds
69 * Locks access to all WND structures for thread safeness
71 void WIN_LockWnds( void )
73 _EnterSysLevel( &WIN_SysLevel );
76 /***********************************************************************
77 * WIN_UnlockWnds
79 * Unlocks access to all WND structures
81 void WIN_UnlockWnds( void )
83 _LeaveSysLevel( &WIN_SysLevel );
86 /***********************************************************************
87 * WIN_SuspendWndsLock
89 * Suspend the lock on WND structures.
90 * Returns the number of locks suspended
92 int WIN_SuspendWndsLock( void )
94 int isuspendedLocks = _ConfirmSysLevel( &WIN_SysLevel );
95 int count = isuspendedLocks;
97 while ( count-- > 0 )
98 _LeaveSysLevel( &WIN_SysLevel );
100 return isuspendedLocks;
103 /***********************************************************************
104 * WIN_RestoreWndsLock
106 * Restore the suspended locks on WND structures
108 void WIN_RestoreWndsLock( int ipreviousLocks )
110 while ( ipreviousLocks-- > 0 )
111 _EnterSysLevel( &WIN_SysLevel );
114 /***********************************************************************
115 * WIN_FindWndPtr
117 * Return a pointer to the WND structure corresponding to a HWND.
119 WND * WIN_FindWndPtr( HWND hwnd )
121 WND * ptr;
123 if (!hwnd || HIWORD(hwnd)) goto error2;
124 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
125 /* Lock all WND structures for thread safeness*/
126 WIN_LockWnds();
127 /*and increment destruction monitoring*/
128 ptr->irefCount++;
130 if (ptr->dwMagic != WND_MAGIC) goto error;
131 if (ptr->hwndSelf != hwnd)
133 ERR("Can't happen: hwnd %04x self pointer is %04x\n",hwnd, ptr->hwndSelf );
134 goto error;
136 /* returns a locked pointer */
137 return ptr;
138 error:
139 /* Unlock all WND structures for thread safeness*/
140 WIN_UnlockWnds();
141 /* and decrement destruction monitoring value */
142 ptr->irefCount--;
144 error2:
145 if ( hwnd!=0 )
146 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
147 return NULL;
150 /***********************************************************************
151 * WIN_LockWndPtr
153 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
154 * but by initWndPtr;
155 * Returns the locked initialisation pointer
157 WND *WIN_LockWndPtr(WND *initWndPtr)
159 if(!initWndPtr) return 0;
161 /* Lock all WND structures for thread safeness*/
162 WIN_LockWnds();
163 /*and increment destruction monitoring*/
164 initWndPtr->irefCount++;
166 return initWndPtr;
170 /***********************************************************************
171 * WIN_ReleaseWndPtr
173 * Release the pointer to the WND structure.
175 void WIN_ReleaseWndPtr(WND *wndPtr)
177 if(!wndPtr) return;
179 /*Decrement destruction monitoring value*/
180 wndPtr->irefCount--;
181 /* Check if it's time to release the memory*/
182 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
184 /* Release memory */
185 USER_HEAP_FREE( wndPtr->hwndSelf);
186 wndPtr->hwndSelf = 0;
188 else if(wndPtr->irefCount < 0)
190 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
191 ERR("forgot a Lock on %p somewhere\n",wndPtr);
193 /*unlock all WND structures for thread safeness*/
194 WIN_UnlockWnds();
197 /***********************************************************************
198 * WIN_UpdateWndPtr
200 * Updates the value of oldPtr to newPtr.
202 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
204 WND *tmpWnd = NULL;
206 tmpWnd = WIN_LockWndPtr(newPtr);
207 WIN_ReleaseWndPtr(*oldPtr);
208 *oldPtr = tmpWnd;
212 /***********************************************************************
213 * WIN_DumpWindow
215 * Dump the content of a window structure to stderr.
217 void WIN_DumpWindow( HWND hwnd )
219 WND *ptr;
220 char className[80];
221 int i;
223 if (!(ptr = WIN_FindWndPtr( hwnd )))
225 WARN("%04x is not a window handle\n", hwnd );
226 return;
229 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
230 strcpy( className, "#NULL#" );
232 TRACE("Window %04x (%p):\n", hwnd, ptr );
233 DPRINTF( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
234 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
235 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
236 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
237 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
238 ptr->next, ptr->child, ptr->parent, ptr->owner,
239 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
240 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
241 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
242 ptr->text ? ptr->text : "",
243 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
244 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
245 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
246 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
248 if (ptr->class->cbWndExtra)
250 DPRINTF( "extra bytes:" );
251 for (i = 0; i < ptr->class->cbWndExtra; i++)
252 DPRINTF( " %02x", *((BYTE*)ptr->wExtra+i) );
253 DPRINTF( "\n" );
255 DPRINTF( "\n" );
256 WIN_ReleaseWndPtr(ptr);
260 /***********************************************************************
261 * WIN_WalkWindows
263 * Walk the windows tree and print each window on stderr.
265 void WIN_WalkWindows( HWND hwnd, int indent )
267 WND *ptr;
268 char className[80];
270 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
272 if (!ptr)
274 WARN("Invalid window handle %04x\n", hwnd );
275 return;
278 if (!indent) /* first time around */
279 DPRINTF( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
280 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
281 " Text");
283 while (ptr)
285 DPRINTF( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
287 GlobalGetAtomNameA(ptr->class->atomName,className,sizeof(className));
289 DPRINTF( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
290 (DWORD)ptr, ptr->hmemTaskQ, className,
291 (UINT)ptr->dwStyle, (UINT)ptr->winproc,
292 ptr->text?ptr->text:"<null>");
294 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
295 WIN_UpdateWndPtr(&ptr,ptr->next);
301 /***********************************************************************
302 * WIN_UnlinkWindow
304 * Remove a window from the siblings linked list.
306 BOOL WIN_UnlinkWindow( HWND hwnd )
308 WND *wndPtr, **ppWnd;
309 BOOL ret = FALSE;
311 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
312 else if(!wndPtr->parent)
314 WIN_ReleaseWndPtr(wndPtr);
315 return FALSE;
318 ppWnd = &wndPtr->parent->child;
319 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
320 if (*ppWnd)
322 *ppWnd = wndPtr->next;
323 ret = TRUE;
325 WIN_ReleaseWndPtr(wndPtr);
326 return ret;
330 /***********************************************************************
331 * WIN_LinkWindow
333 * Insert a window into the siblings linked list.
334 * The window is inserted after the specified window, which can also
335 * be specified as HWND_TOP or HWND_BOTTOM.
337 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
339 WND *wndPtr, **ppWnd;
341 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
342 else if(!wndPtr->parent)
344 WIN_ReleaseWndPtr(wndPtr);
345 return FALSE;
347 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
349 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
350 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
351 while (*ppWnd) ppWnd = &(*ppWnd)->next;
353 else /* Normal case */
355 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
356 if (!afterPtr)
358 WIN_ReleaseWndPtr(wndPtr);
359 return FALSE;
361 ppWnd = &afterPtr->next;
362 WIN_ReleaseWndPtr(afterPtr);
364 wndPtr->next = *ppWnd;
365 *ppWnd = wndPtr;
366 WIN_ReleaseWndPtr(wndPtr);
367 return TRUE;
371 /***********************************************************************
372 * WIN_FindWinToRepaint
374 * Find a window that needs repaint.
376 HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE16 hQueue )
378 HWND hwndRet;
379 WND *pWnd;
381 /* Note: the desktop window never gets WM_PAINT messages
382 * The real reason why is because Windows DesktopWndProc
383 * does ValidateRgn inside WM_ERASEBKGND handler.
386 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
388 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
390 if (!(pWnd->dwStyle & WS_VISIBLE))
392 TRACE("skipping window %04x\n",
393 pWnd->hwndSelf );
395 else if ((pWnd->hmemTaskQ == hQueue) &&
396 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)))
397 break;
399 else if (pWnd->child )
400 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
402 WIN_ReleaseWndPtr(pWnd);
403 return hwndRet;
408 if(!pWnd)
410 return 0;
413 hwndRet = pWnd->hwndSelf;
415 /* look among siblings if we got a transparent window */
416 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
417 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
419 WIN_UpdateWndPtr(&pWnd,pWnd->next);
421 if (pWnd)
423 hwndRet = pWnd->hwndSelf;
424 WIN_ReleaseWndPtr(pWnd);
426 TRACE("found %04x\n",hwndRet);
427 return hwndRet;
431 /***********************************************************************
432 * WIN_DestroyWindow
434 * Destroy storage associated to a window. "Internals" p.358
435 * returns a locked wndPtr->next
437 static WND* WIN_DestroyWindow( WND* wndPtr )
439 HWND hwnd = wndPtr->hwndSelf;
440 WND *pWnd;
442 TRACE("%04x\n", wndPtr->hwndSelf );
444 /* free child windows */
445 WIN_LockWndPtr(wndPtr->child);
446 while ((pWnd = wndPtr->child))
448 wndPtr->child = WIN_DestroyWindow( pWnd );
449 WIN_ReleaseWndPtr(pWnd);
453 * Clear the update region to make sure no WM_PAINT messages will be
454 * generated for this window while processing the WM_NCDESTROY.
456 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
458 if (wndPtr->hrgnUpdate > 1)
459 DeleteObject( wndPtr->hrgnUpdate );
461 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
463 wndPtr->hrgnUpdate = 0;
467 * Send the WM_NCDESTROY to the window being destroyed.
469 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
471 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
473 WINPOS_CheckInternalPos( wndPtr );
474 if( hwnd == GetCapture()) ReleaseCapture();
476 /* free resources associated with the window */
478 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
479 PROPERTY_RemoveWindowProps( wndPtr );
481 wndPtr->dwMagic = 0; /* Mark it as invalid */
483 /* toss stale messages from the queue */
485 if( wndPtr->hmemTaskQ )
487 BOOL bPostQuit = FALSE;
488 WPARAM wQuitParam = 0;
489 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) QUEUE_Lock(wndPtr->hmemTaskQ);
490 QMSG *qmsg;
492 while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
494 if( qmsg->msg.message == WM_QUIT )
496 bPostQuit = TRUE;
497 wQuitParam = qmsg->msg.wParam;
499 QUEUE_RemoveMsg(msgQ, qmsg);
502 QUEUE_Unlock(msgQ);
504 /* repost WM_QUIT to make sure this app exits its message loop */
505 if( bPostQuit ) PostQuitMessage(wQuitParam);
506 wndPtr->hmemTaskQ = 0;
509 if (!(wndPtr->dwStyle & WS_CHILD))
510 if (wndPtr->wIDmenu) DestroyMenu( (HMENU)wndPtr->wIDmenu );
511 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
512 wndPtr->pDriver->pDestroyWindow( wndPtr );
513 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
514 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
515 wndPtr->class->cWindows--;
516 wndPtr->class = NULL;
518 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
520 wndPtr->pDriver->pFinalize(wndPtr);
522 return pWnd;
525 /***********************************************************************
526 * WIN_ResetQueueWindows
528 * Reset the queue of all the children of a given window.
529 * Return TRUE if something was done.
531 BOOL WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
533 BOOL ret = FALSE;
535 if (hNew) /* Set a new queue */
537 for (wnd = WIN_LockWndPtr(wnd->child); (wnd);WIN_UpdateWndPtr(&wnd,wnd->next))
539 if (wnd->hmemTaskQ == hQueue)
541 wnd->hmemTaskQ = hNew;
542 ret = TRUE;
544 if (wnd->child)
546 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
550 else /* Queue is being destroyed */
552 while (wnd->child)
554 WND *tmp = WIN_LockWndPtr(wnd->child);
555 WND *tmp2;
556 ret = FALSE;
557 while (tmp)
559 if (tmp->hmemTaskQ == hQueue)
561 DestroyWindow( tmp->hwndSelf );
562 ret = TRUE;
563 break;
565 tmp2 = WIN_LockWndPtr(tmp->child);
566 if (tmp2 && WIN_ResetQueueWindows(tmp2,hQueue,0))
567 ret = TRUE;
568 else
570 WIN_UpdateWndPtr(&tmp,tmp->next);
572 WIN_ReleaseWndPtr(tmp2);
574 WIN_ReleaseWndPtr(tmp);
575 if (!ret) break;
578 return ret;
581 /***********************************************************************
582 * WIN_CreateDesktopWindow
584 * Create the desktop window.
586 BOOL WIN_CreateDesktopWindow(void)
588 CLASS *class;
589 HWND hwndDesktop;
590 DESKTOP *pDesktop;
592 TRACE("Creating desktop window\n");
595 if (!ICONTITLE_Init() ||
596 !WINPOS_CreateInternalPosAtom() ||
597 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
598 return FALSE;
600 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
601 if (!hwndDesktop) return FALSE;
602 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
604 pDesktop = (DESKTOP *) pWndDesktop->wExtra;
605 pDesktop->pDriver = DESKTOP_Driver;
606 pWndDesktop->pDriver = WND_Driver;
608 pDesktop->pDriver->pInitialize(pDesktop);
609 pWndDesktop->pDriver->pInitialize(pWndDesktop);
611 pWndDesktop->next = NULL;
612 pWndDesktop->child = NULL;
613 pWndDesktop->parent = NULL;
614 pWndDesktop->owner = NULL;
615 pWndDesktop->class = class;
616 pWndDesktop->dwMagic = WND_MAGIC;
617 pWndDesktop->hwndSelf = hwndDesktop;
618 pWndDesktop->hInstance = 0;
619 pWndDesktop->rectWindow.left = 0;
620 pWndDesktop->rectWindow.top = 0;
621 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
622 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
623 pWndDesktop->rectClient = pWndDesktop->rectWindow;
624 pWndDesktop->text = NULL;
625 pWndDesktop->hmemTaskQ = GetFastQueue16();
626 pWndDesktop->hrgnUpdate = 0;
627 pWndDesktop->hwndLastActive = hwndDesktop;
628 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
629 WS_CLIPSIBLINGS;
630 pWndDesktop->dwExStyle = 0;
631 pWndDesktop->dce = NULL;
632 pWndDesktop->pVScroll = NULL;
633 pWndDesktop->pHScroll = NULL;
634 pWndDesktop->pProp = NULL;
635 pWndDesktop->wIDmenu = 0;
636 pWndDesktop->helpContext = 0;
637 pWndDesktop->flags = Options.desktopGeometry ? WIN_NATIVE : 0;
638 pWndDesktop->hSysMenu = 0;
639 pWndDesktop->userdata = 0;
640 pWndDesktop->winproc = (WNDPROC16)class->winproc;
641 pWndDesktop->irefCount = 0;
643 /* FIXME: How do we know if it should be Unicode or not */
644 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop, class, FALSE))
645 return FALSE;
647 SendMessageA( hwndDesktop, WM_NCCREATE, 0, 0 );
648 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
649 return TRUE;
653 /***********************************************************************
654 * WIN_CreateWindowEx
656 * Implementation of CreateWindowEx().
658 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
659 BOOL win32, BOOL unicode )
661 INT sw = SW_SHOW;
662 CLASS *classPtr;
663 WND *wndPtr;
664 HWND retvalue;
665 HWND16 hwnd, hwndLinkAfter;
666 POINT maxSize, maxPos, minTrack, maxTrack;
667 LRESULT (CALLBACK *localSend32)(HWND, UINT, WPARAM, LPARAM);
669 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
670 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
671 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
672 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
673 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
675 /* Find the parent window */
677 if (cs->hwndParent)
679 /* Make sure parent is valid */
680 if (!IsWindow( cs->hwndParent ))
682 WARN("Bad parent %04x\n", cs->hwndParent );
683 return 0;
685 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
686 WARN("No parent for child window\n" );
687 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
690 /* Find the window class */
691 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
693 WARN("Bad class '%s'\n", cs->lpszClass );
694 return 0;
697 /* Fix the coordinates */
699 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
701 PDB *pdb = PROCESS_Current();
703 /* Never believe Microsoft's documentation... CreateWindowEx doc says
704 * that if an overlapped window is created with WS_VISIBLE style bit
705 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
706 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
707 * reveals that
709 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
710 * 2) it does not ignore the y parameter as the docs claim; instead, it
711 * uses it as second parameter to ShowWindow() unless y is either
712 * CW_USEDEFAULT or CW_USEDEFAULT16.
714 * The fact that we didn't do 2) caused bogus windows pop up when wine
715 * was running apps that were using this obscure feature. Example -
716 * calc.exe that comes with Win98 (only Win98, it's different from
717 * the one that comes with Win95 and NT)
719 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) sw = cs->y;
721 /* We have saved cs->y, now we can trash it */
722 if ( !(cs->style & (WS_CHILD | WS_POPUP))
723 && (pdb->env_db->startup_info->dwFlags & STARTF_USEPOSITION) )
725 cs->x = pdb->env_db->startup_info->dwX;
726 cs->y = pdb->env_db->startup_info->dwY;
728 else
730 cs->x = 0;
731 cs->y = 0;
734 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
736 PDB *pdb = PROCESS_Current();
737 if ( !(cs->style & (WS_CHILD | WS_POPUP))
738 && (pdb->env_db->startup_info->dwFlags & STARTF_USESIZE) )
740 cs->cx = pdb->env_db->startup_info->dwXSize;
741 cs->cy = pdb->env_db->startup_info->dwYSize;
743 else
745 cs->cx = 600; /* FIXME */
746 cs->cy = 400;
750 /* Create the window structure */
752 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
753 - sizeof(wndPtr->wExtra) )))
755 TRACE("out of memory\n" );
756 return 0;
759 /* Fill the window structure */
761 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
762 wndPtr->next = NULL;
763 wndPtr->child = NULL;
765 if ((cs->style & WS_CHILD) && cs->hwndParent)
767 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
768 wndPtr->owner = NULL;
769 WIN_ReleaseWndPtr(wndPtr->parent);
771 else
773 wndPtr->parent = pWndDesktop;
774 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
775 wndPtr->owner = NULL;
776 else
778 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
779 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
780 WIN_ReleaseWndPtr(wndPtr->owner);
781 WIN_ReleaseWndPtr(tmpWnd);
786 wndPtr->pDriver = wndPtr->parent->pDriver;
787 wndPtr->pDriver->pInitialize(wndPtr);
789 wndPtr->class = classPtr;
790 wndPtr->winproc = classPtr->winproc;
791 wndPtr->dwMagic = WND_MAGIC;
792 wndPtr->hwndSelf = hwnd;
793 wndPtr->hInstance = cs->hInstance;
794 wndPtr->text = NULL;
795 wndPtr->hmemTaskQ = GetFastQueue16();
796 wndPtr->hrgnUpdate = 0;
797 wndPtr->hwndLastActive = hwnd;
798 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
799 wndPtr->dwExStyle = cs->dwExStyle;
800 wndPtr->wIDmenu = 0;
801 wndPtr->helpContext = 0;
802 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
803 wndPtr->pVScroll = NULL;
804 wndPtr->pHScroll = NULL;
805 wndPtr->pProp = NULL;
806 wndPtr->userdata = 0;
807 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
808 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
809 wndPtr->irefCount = 1;
811 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
813 /* Call the WH_CBT hook */
815 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
816 ? HWND_BOTTOM : HWND_TOP;
818 if (HOOK_IsHooked( WH_CBT ))
820 CBT_CREATEWNDA cbtc;
821 LRESULT ret;
823 cbtc.lpcs = cs;
824 cbtc.hwndInsertAfter = hwndLinkAfter;
825 ret = unicode ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
826 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
827 if (ret)
829 TRACE("CBT-hook returned 0\n");
830 wndPtr->pDriver->pFinalize(wndPtr);
831 USER_HEAP_FREE( hwnd );
832 retvalue = 0;
833 goto end;
837 /* Increment class window counter */
839 classPtr->cWindows++;
841 /* Correct the window style */
843 if (!(cs->style & WS_CHILD))
845 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
846 if (!(cs->style & WS_POPUP))
848 wndPtr->dwStyle |= WS_CAPTION;
849 wndPtr->flags |= WIN_NEED_SIZE;
853 /* Get class or window DC if needed */
855 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
856 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
857 else wndPtr->dce = NULL;
859 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
861 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
863 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
864 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
865 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
866 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
867 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
870 if(cs->style & WS_CHILD)
872 if(cs->cx < 0) cs->cx = 0;
873 if(cs->cy < 0) cs->cy = 0;
875 else
877 if (cs->cx <= 0) cs->cx = 1;
878 if (cs->cy <= 0) cs->cy = 1;
881 wndPtr->rectWindow.left = cs->x;
882 wndPtr->rectWindow.top = cs->y;
883 wndPtr->rectWindow.right = cs->x + cs->cx;
884 wndPtr->rectWindow.bottom = cs->y + cs->cy;
885 wndPtr->rectClient = wndPtr->rectWindow;
887 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
889 retvalue = FALSE;
890 goto end;
893 /* Set the window menu */
895 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
897 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
898 else
900 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
901 if (classPtr->menuNameA)
902 cs->hMenu = HIWORD(classPtr->menuNameA) ?
903 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
904 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
905 #else
906 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
907 if (menuName)
909 if (HIWORD(cs->hInstance))
910 cs->hMenu = LoadMenuA(cs->hInstance,PTR_SEG_TO_LIN(menuName));
911 else
912 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
914 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
916 #endif
919 else wndPtr->wIDmenu = (UINT)cs->hMenu;
921 /* Send the WM_CREATE message
922 * Perhaps we shouldn't allow width/height changes as well.
923 * See p327 in "Internals".
926 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
928 localSend32 = unicode ? SendMessageW : SendMessageA;
929 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
931 /* Insert the window in the linked list */
933 WIN_LinkWindow( hwnd, hwndLinkAfter );
935 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
936 NULL, NULL, 0, &wndPtr->rectClient );
937 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
938 maxPos.y - wndPtr->rectWindow.top);
939 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
941 /* Send the size messages */
943 if (!(wndPtr->flags & WIN_NEED_SIZE))
945 /* send it anyway */
946 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
947 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
948 WARN("sending bogus WM_SIZE message 0x%08lx\n",
949 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
950 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
951 SendMessageA( hwnd, WM_SIZE, SIZE_RESTORED,
952 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
953 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
954 SendMessageA( hwnd, WM_MOVE, 0,
955 MAKELONG( wndPtr->rectClient.left,
956 wndPtr->rectClient.top ) );
959 /* Show the window, maximizing or minimizing if needed */
961 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
963 RECT16 newPos;
964 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
965 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
966 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
967 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
968 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
969 : SWP_NOZORDER | SWP_FRAMECHANGED;
970 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
971 newPos.right, newPos.bottom, swFlag );
974 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
976 /* Notify the parent window only */
978 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
979 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
980 if( !IsWindow(hwnd) )
982 retvalue = 0;
983 goto end;
987 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, sw );
989 /* Call WH_SHELL hook */
991 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
992 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
994 TRACE("created window %04x\n", hwnd);
995 retvalue = hwnd;
996 goto end;
998 WIN_UnlinkWindow( hwnd );
1001 /* Abort window creation */
1003 WARN("aborted by WM_xxCREATE!\n");
1004 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1005 retvalue = 0;
1006 end:
1007 WIN_ReleaseWndPtr(wndPtr);
1009 return retvalue;
1013 /***********************************************************************
1014 * CreateWindow16 (USER.41)
1016 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1017 DWORD style, INT16 x, INT16 y, INT16 width,
1018 INT16 height, HWND16 parent, HMENU16 menu,
1019 HINSTANCE16 instance, LPVOID data )
1021 return CreateWindowEx16( 0, className, windowName, style,
1022 x, y, width, height, parent, menu, instance, data );
1026 /***********************************************************************
1027 * CreateWindowEx16 (USER.452)
1029 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1030 LPCSTR windowName, DWORD style, INT16 x,
1031 INT16 y, INT16 width, INT16 height,
1032 HWND16 parent, HMENU16 menu,
1033 HINSTANCE16 instance, LPVOID data )
1035 ATOM classAtom;
1036 CREATESTRUCTA cs;
1037 char buffer[256];
1039 /* Find the class atom */
1041 if (HIWORD(className))
1043 if (!(classAtom = GlobalFindAtomA( className )))
1045 ERR( "bad class name %s\n", debugres_a(className) );
1046 return 0;
1049 else
1051 classAtom = LOWORD(className);
1052 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1054 ERR( "bad atom %x\n", classAtom);
1055 return 0;
1057 className = buffer;
1060 /* Fix the coordinates */
1062 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1063 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1064 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1065 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1067 /* Create the window */
1069 cs.lpCreateParams = data;
1070 cs.hInstance = (HINSTANCE)instance;
1071 cs.hMenu = (HMENU)menu;
1072 cs.hwndParent = (HWND)parent;
1073 cs.style = style;
1074 cs.lpszName = windowName;
1075 cs.lpszClass = className;
1076 cs.dwExStyle = exStyle;
1078 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
1082 /***********************************************************************
1083 * CreateWindowEx32A (USER32.83)
1085 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1086 LPCSTR windowName, DWORD style, INT x,
1087 INT y, INT width, INT height,
1088 HWND parent, HMENU menu,
1089 HINSTANCE instance, LPVOID data )
1091 ATOM classAtom;
1092 CREATESTRUCTA cs;
1093 char buffer[256];
1095 if(!instance)
1096 instance=GetModuleHandleA(NULL);
1098 if(exStyle & WS_EX_MDICHILD)
1099 return MDI_CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1101 /* Find the class atom */
1103 if (HIWORD(className))
1105 if (!(classAtom = GlobalFindAtomA( className )))
1107 ERR( "bad class name %s\n", debugres_a(className) );
1108 return 0;
1111 else
1113 classAtom = LOWORD(className);
1114 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1116 ERR( "bad atom %x\n", classAtom);
1117 return 0;
1119 className = buffer;
1122 /* Create the window */
1124 cs.lpCreateParams = data;
1125 cs.hInstance = instance;
1126 cs.hMenu = menu;
1127 cs.hwndParent = parent;
1128 cs.x = x;
1129 cs.y = y;
1130 cs.cx = width;
1131 cs.cy = height;
1132 cs.style = style;
1133 cs.lpszName = windowName;
1134 cs.lpszClass = className;
1135 cs.dwExStyle = exStyle;
1137 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
1141 /***********************************************************************
1142 * CreateWindowEx32W (USER32.84)
1144 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1145 LPCWSTR windowName, DWORD style, INT x,
1146 INT y, INT width, INT height,
1147 HWND parent, HMENU menu,
1148 HINSTANCE instance, LPVOID data )
1150 ATOM classAtom;
1151 CREATESTRUCTW cs;
1152 WCHAR buffer[256];
1154 if(!instance)
1155 instance=GetModuleHandleA(NULL);
1157 if(exStyle & WS_EX_MDICHILD)
1158 return MDI_CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1160 /* Find the class atom */
1162 if (HIWORD(className))
1164 if (!(classAtom = GlobalFindAtomW( className )))
1166 ERR( "bad class name %s\n", debugres_w(className) );
1167 return 0;
1170 else
1172 classAtom = LOWORD(className);
1173 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1175 ERR( "bad atom %x\n", classAtom);
1176 return 0;
1178 className = buffer;
1181 /* Create the window */
1183 cs.lpCreateParams = data;
1184 cs.hInstance = instance;
1185 cs.hMenu = menu;
1186 cs.hwndParent = parent;
1187 cs.x = x;
1188 cs.y = y;
1189 cs.cx = width;
1190 cs.cy = height;
1191 cs.style = style;
1192 cs.lpszName = windowName;
1193 cs.lpszClass = className;
1194 cs.dwExStyle = exStyle;
1196 /* Note: we rely on the fact that CREATESTRUCT32A and */
1197 /* CREATESTRUCT32W have the same layout. */
1198 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, TRUE, TRUE );
1202 /***********************************************************************
1203 * WIN_CheckFocus
1205 static void WIN_CheckFocus( WND* pWnd )
1207 if( GetFocus16() == pWnd->hwndSelf )
1208 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
1211 /***********************************************************************
1212 * WIN_SendDestroyMsg
1214 static void WIN_SendDestroyMsg( WND* pWnd )
1216 WIN_CheckFocus(pWnd);
1218 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1219 CLIPBOARD_Driver->pResetOwner( pWnd, TRUE );
1222 * Send the WM_DESTROY to the window.
1224 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1227 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1228 * make sure that the window still exists when we come back.
1230 if (IsWindow(pWnd->hwndSelf))
1232 HWND* pWndArray = NULL;
1233 WND* pChild = NULL;
1234 int nKidCount = 0;
1237 * Now, if the window has kids, we have to send WM_DESTROY messages
1238 * recursively to it's kids. It seems that those calls can also
1239 * trigger re-entrant calls to DestroyWindow for the kids so we must
1240 * protect against corruption of the list of siblings. We first build
1241 * a list of HWNDs representing all the kids.
1243 pChild = WIN_LockWndPtr(pWnd->child);
1244 while( pChild )
1246 nKidCount++;
1247 WIN_UpdateWndPtr(&pChild,pChild->next);
1251 * If there are no kids, we're done.
1253 if (nKidCount==0)
1254 return;
1256 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1259 * Sanity check
1261 if (pWndArray==NULL)
1262 return;
1265 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1266 * call, our linked list of siblings should be safe.
1268 nKidCount = 0;
1269 pChild = WIN_LockWndPtr(pWnd->child);
1270 while( pChild )
1272 pWndArray[nKidCount] = pChild->hwndSelf;
1273 nKidCount++;
1274 WIN_UpdateWndPtr(&pChild,pChild->next);
1278 * Now that we have a list, go through that list again and send the destroy
1279 * message to those windows. We are using the HWND to retrieve the
1280 * WND pointer so we are effectively checking that all the kid windows are
1281 * still valid before sending the message.
1283 while (nKidCount>0)
1285 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1287 if (pChild!=NULL)
1289 WIN_SendDestroyMsg( pChild );
1290 WIN_ReleaseWndPtr(pChild);
1295 * Cleanup
1297 HeapFree(GetProcessHeap(), 0, pWndArray);
1298 WIN_CheckFocus(pWnd);
1300 else
1301 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1305 /***********************************************************************
1306 * DestroyWindow16 (USER.53)
1308 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1310 return DestroyWindow(hwnd);
1314 /***********************************************************************
1315 * DestroyWindow32 (USER32.135)
1317 BOOL WINAPI DestroyWindow( HWND hwnd )
1319 WND * wndPtr;
1320 BOOL retvalue;
1322 TRACE("(%04x)\n", hwnd);
1324 /* Initialization */
1326 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1327 if (wndPtr == pWndDesktop)
1329 retvalue = FALSE; /* Can't destroy desktop */
1330 goto end;
1333 /* Call hooks */
1335 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1337 retvalue = FALSE;
1338 goto end;
1341 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1343 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1344 /* FIXME: clean up palette - see "Internals" p.352 */
1347 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1348 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1350 /* Notify the parent window only */
1351 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1352 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1353 if( !IsWindow(hwnd) )
1355 retvalue = TRUE;
1356 goto end;
1360 CLIPBOARD_Driver->pResetOwner( wndPtr, FALSE ); /* before the window is unmapped */
1362 /* Hide the window */
1364 if (wndPtr->dwStyle & WS_VISIBLE)
1366 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1367 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1368 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1369 if (!IsWindow(hwnd))
1371 retvalue = TRUE;
1372 goto end;
1376 /* Recursively destroy owned windows */
1378 if( !(wndPtr->dwStyle & WS_CHILD) )
1380 /* make sure top menu popup doesn't get destroyed */
1381 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1383 for (;;)
1385 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1386 while (siblingPtr)
1388 if (siblingPtr->owner == wndPtr)
1390 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1391 break;
1392 else
1393 siblingPtr->owner = NULL;
1395 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1397 if (siblingPtr)
1399 DestroyWindow( siblingPtr->hwndSelf );
1400 WIN_ReleaseWndPtr(siblingPtr);
1402 else break;
1405 if( !Options.managed || EVENT_CheckFocus() )
1406 WINPOS_ActivateOtherWindow(wndPtr);
1408 if( wndPtr->owner &&
1409 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1410 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1413 /* Send destroy messages */
1415 WIN_SendDestroyMsg( wndPtr );
1416 if (!IsWindow(hwnd))
1418 retvalue = TRUE;
1419 goto end;
1422 /* Unlink now so we won't bother with the children later on */
1424 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1426 /* Destroy the window storage */
1428 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1429 retvalue = TRUE;
1430 end:
1431 WIN_ReleaseWndPtr(wndPtr);
1432 return retvalue;
1436 /***********************************************************************
1437 * CloseWindow16 (USER.43)
1439 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1441 return CloseWindow( hwnd );
1445 /***********************************************************************
1446 * CloseWindow32 (USER32.56)
1448 BOOL WINAPI CloseWindow( HWND hwnd )
1450 WND * wndPtr = WIN_FindWndPtr( hwnd );
1451 BOOL retvalue;
1453 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1455 retvalue = FALSE;
1456 goto end;
1458 ShowWindow( hwnd, SW_MINIMIZE );
1459 retvalue = TRUE;
1460 end:
1461 WIN_ReleaseWndPtr(wndPtr);
1462 return retvalue;
1467 /***********************************************************************
1468 * OpenIcon16 (USER.44)
1470 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1472 return OpenIcon( hwnd );
1476 /***********************************************************************
1477 * OpenIcon32 (USER32.410)
1479 BOOL WINAPI OpenIcon( HWND hwnd )
1481 if (!IsIconic( hwnd )) return FALSE;
1482 ShowWindow( hwnd, SW_SHOWNORMAL );
1483 return TRUE;
1487 /***********************************************************************
1488 * WIN_FindWindow
1490 * Implementation of FindWindow() and FindWindowEx().
1492 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1493 LPCSTR title )
1495 WND *pWnd;
1496 HWND retvalue;
1498 if (child)
1500 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1501 if (parent)
1503 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1505 retvalue = 0;
1506 goto end;
1509 else if (pWnd->parent != pWndDesktop)
1511 retvalue = 0;
1512 goto end;
1514 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1516 else
1518 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1520 retvalue = 0;
1521 goto end;
1523 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1525 if (!pWnd)
1527 retvalue = 0;
1528 goto end;
1531 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1533 if (className && (pWnd->class->atomName != className))
1534 continue; /* Not the right class */
1536 /* Now check the title */
1538 if (!title)
1540 retvalue = pWnd->hwndSelf;
1541 goto end;
1543 if (pWnd->text && !strcmp( pWnd->text, title ))
1545 retvalue = pWnd->hwndSelf;
1546 goto end;
1549 retvalue = 0;
1550 end:
1551 WIN_ReleaseWndPtr(pWnd);
1552 return retvalue;
1557 /***********************************************************************
1558 * FindWindow16 (USER.50)
1560 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1562 return FindWindowA( className, title );
1566 /***********************************************************************
1567 * FindWindowEx16 (USER.427)
1569 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1571 return FindWindowExA( parent, child, className, 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 if (pWndDesktop) return pWndDesktop->hwndSelf;
1677 ERR( "You need the -desktop option when running with native USER\n" );
1678 ExitProcess(1);
1679 return 0;
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("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())
1739 SetFocus( 0 ); /* A disabled window can't have the focus */
1741 if (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("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("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("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1838 wndPtr->hInstance);
1839 retvalue = (WORD)wndPtr->hInstance;
1840 goto end;
1841 default:
1842 WARN("Invalid offset %d\n", offset );
1843 retvalue = 0;
1844 goto end;
1846 end:
1847 WIN_ReleaseWndPtr(wndPtr);
1848 return retvalue;
1851 /**********************************************************************
1852 * SetWindowWord16 (USER.134)
1854 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1856 return SetWindowWord( hwnd, offset, newval );
1860 /**********************************************************************
1861 * SetWindowWord32 (USER32.524)
1863 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1865 WORD *ptr, retval;
1866 WND * wndPtr = WIN_FindWndPtr( hwnd );
1867 if (!wndPtr) return 0;
1868 if (offset >= 0)
1870 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1872 WARN("Invalid offset %d\n", offset );
1873 retval = 0;
1874 goto end;
1876 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1878 else switch(offset)
1880 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1881 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1882 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1883 goto end;
1884 default:
1885 WARN("Invalid offset %d\n", offset );
1886 retval = 0;
1887 goto end;
1889 retval = *ptr;
1890 *ptr = newval;
1891 end:
1892 WIN_ReleaseWndPtr(wndPtr);
1893 return retval;
1897 /**********************************************************************
1898 * WIN_GetWindowLong
1900 * Helper function for GetWindowLong().
1902 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1904 LONG retvalue;
1905 WND * wndPtr = WIN_FindWndPtr( hwnd );
1906 if (!wndPtr) return 0;
1907 if (offset >= 0)
1909 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1911 WARN("Invalid offset %d\n", offset );
1912 retvalue = 0;
1913 goto end;
1915 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1916 /* Special case for dialog window procedure */
1917 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1919 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1920 goto end;
1922 goto end;
1924 switch(offset)
1926 case GWL_USERDATA: retvalue = wndPtr->userdata;
1927 goto end;
1928 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1929 goto end;
1930 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1931 goto end;
1932 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1933 goto end;
1934 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1935 type );
1936 goto end;
1937 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1938 goto end;
1939 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1940 goto end;
1941 default:
1942 WARN("Unknown offset %d\n", offset );
1944 retvalue = 0;
1945 end:
1946 WIN_ReleaseWndPtr(wndPtr);
1947 return retvalue;
1951 /**********************************************************************
1952 * WIN_SetWindowLong
1954 * Helper function for SetWindowLong().
1956 * 0 is the failure code. However, in the case of failure SetLastError
1957 * must be set to distinguish between a 0 return value and a failure.
1959 * FIXME: The error values for SetLastError may not be right. Can
1960 * someone check with the real thing?
1962 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1963 WINDOWPROCTYPE type )
1965 LONG *ptr, retval;
1966 WND * wndPtr = WIN_FindWndPtr( hwnd );
1967 STYLESTRUCT style;
1969 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1971 if (!wndPtr)
1973 /* Is this the right error? */
1974 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1975 return 0;
1978 if (offset >= 0)
1980 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1982 WARN("Invalid offset %d\n", offset );
1984 /* Is this the right error? */
1985 SetLastError( ERROR_OUTOFMEMORY );
1987 retval = 0;
1988 goto end;
1990 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1991 /* Special case for dialog window procedure */
1992 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1994 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1995 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1996 type, WIN_PROC_WINDOW );
1997 goto end;
2000 else switch(offset)
2002 case GWL_ID:
2003 ptr = (DWORD*)&wndPtr->wIDmenu;
2004 break;
2005 case GWL_HINSTANCE:
2006 retval = SetWindowWord( hwnd, offset, newval );
2007 goto end;
2008 case GWL_WNDPROC:
2009 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2010 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2011 type, WIN_PROC_WINDOW );
2012 goto end;
2013 case GWL_STYLE:
2014 style.styleOld = wndPtr->dwStyle;
2015 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
2016 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
2018 if (wndPtr->flags & WIN_ISWIN32)
2019 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
2020 wndPtr->dwStyle = style.styleNew;
2021 if (wndPtr->flags & WIN_ISWIN32)
2022 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
2023 retval = style.styleOld;
2024 goto end;
2026 case GWL_USERDATA:
2027 ptr = &wndPtr->userdata;
2028 break;
2029 case GWL_EXSTYLE:
2030 style.styleOld = wndPtr->dwExStyle;
2031 style.styleNew = newval;
2032 if (wndPtr->flags & WIN_ISWIN32)
2033 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
2034 wndPtr->dwExStyle = newval;
2035 if (wndPtr->flags & WIN_ISWIN32)
2036 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
2037 retval = style.styleOld;
2038 goto end;
2040 default:
2041 WARN("Invalid offset %d\n", offset );
2043 /* Don't think this is right error but it should do */
2044 SetLastError( ERROR_OUTOFMEMORY );
2046 retval = 0;
2047 goto end;
2049 retval = *ptr;
2050 *ptr = newval;
2051 end:
2052 WIN_ReleaseWndPtr(wndPtr);
2053 return retval;
2057 /**********************************************************************
2058 * GetWindowLong16 (USER.135)
2060 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2062 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2066 /**********************************************************************
2067 * GetWindowLong32A (USER32.305)
2069 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2071 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2075 /**********************************************************************
2076 * GetWindowLong32W (USER32.306)
2078 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2080 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2084 /**********************************************************************
2085 * SetWindowLong16 (USER.136)
2087 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2089 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2093 /**********************************************************************
2094 * SetWindowLong32A (USER32.517)
2096 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2098 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2102 /**********************************************************************
2103 * SetWindowLong32W (USER32.518) Set window attribute
2105 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2106 * value in a window's extra memory.
2108 * The _hwnd_ parameter specifies the window. is the handle to a
2109 * window that has extra memory. The _newval_ parameter contains the
2110 * new attribute or extra memory value. If positive, the _offset_
2111 * parameter is the byte-addressed location in the window's extra
2112 * memory to set. If negative, _offset_ specifies the window
2113 * attribute to set, and should be one of the following values:
2115 * GWL_EXSTYLE The window's extended window style
2117 * GWL_STYLE The window's window style.
2119 * GWL_WNDPROC Pointer to the window's window procedure.
2121 * GWL_HINSTANCE The window's pplication instance handle.
2123 * GWL_ID The window's identifier.
2125 * GWL_USERDATA The window's user-specified data.
2127 * If the window is a dialog box, the _offset_ parameter can be one of
2128 * the following values:
2130 * DWL_DLGPROC The address of the window's dialog box procedure.
2132 * DWL_MSGRESULT The return value of a message
2133 * that the dialog box procedure processed.
2135 * DWL_USER Application specific information.
2137 * RETURNS
2139 * If successful, returns the previous value located at _offset_. Otherwise,
2140 * returns 0.
2142 * NOTES
2144 * Extra memory for a window class is specified by a nonzero cbWndExtra
2145 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2146 * time of class creation.
2148 * Using GWL_WNDPROC to set a new window procedure effectively creates
2149 * a window subclass. Use CallWindowProc() in the new windows procedure
2150 * to pass messages to the superclass's window procedure.
2152 * The user data is reserved for use by the application which created
2153 * the window.
2155 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2156 * instead, call the EnableWindow() function to change the window's
2157 * disabled state.
2159 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2160 * SetParent() instead.
2162 * Win95:
2163 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2164 * it sends WM_STYLECHANGING before changing the settings
2165 * and WM_STYLECHANGED afterwards.
2166 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2168 * BUGS
2170 * GWL_STYLE does not dispatch WM_STYLE... messages.
2172 * CONFORMANCE
2174 * ECMA-234, Win32
2177 LONG WINAPI SetWindowLongW(
2178 HWND hwnd, /* window to alter */
2179 INT offset, /* offset, in bytes, of location to alter */
2180 LONG newval /* new value of location */
2182 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2186 /*******************************************************************
2187 * GetWindowText16 (USER.36)
2189 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2191 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2195 /*******************************************************************
2196 * GetWindowText32A (USER32.309)
2198 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2200 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2201 (LPARAM)lpString );
2204 /*******************************************************************
2205 * InternalGetWindowText (USER32.326)
2207 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2209 FIXME("(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2210 return GetWindowTextW(hwnd,lpString,nMaxCount);
2214 /*******************************************************************
2215 * GetWindowText32W (USER32.312)
2217 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2219 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2220 (LPARAM)lpString );
2224 /*******************************************************************
2225 * SetWindowText16 (USER.37)
2227 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2229 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2233 /*******************************************************************
2234 * SetWindowText32A (USER32.521)
2236 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2238 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2242 /*******************************************************************
2243 * SetWindowText32W (USER32.523)
2245 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2247 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2251 /*******************************************************************
2252 * GetWindowTextLength16 (USER.38)
2254 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2256 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2260 /*******************************************************************
2261 * GetWindowTextLength32A (USER32.310)
2263 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2265 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2268 /*******************************************************************
2269 * GetWindowTextLength32W (USER32.311)
2271 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2273 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2277 /*******************************************************************
2278 * IsWindow16 (USER.47)
2280 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2282 CURRENT_STACK16->es = USER_HeapSel;
2283 return IsWindow( hwnd );
2287 /*******************************************************************
2288 * IsWindow32 (USER32.348)
2290 BOOL WINAPI IsWindow( HWND hwnd )
2292 WND * wndPtr;
2293 BOOL retvalue;
2295 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2296 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2297 WIN_ReleaseWndPtr(wndPtr);
2298 return retvalue;
2303 /*****************************************************************
2304 * GetParent16 (USER.46)
2306 HWND16 WINAPI GetParent16( HWND16 hwnd )
2308 return (HWND16)GetParent( hwnd );
2312 /*****************************************************************
2313 * GetParent32 (USER32.278)
2315 HWND WINAPI GetParent( HWND hwnd )
2317 WND *wndPtr;
2318 HWND retvalue = 0;
2320 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2321 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2322 goto end;
2324 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2325 if (wndPtr)
2326 retvalue = wndPtr->hwndSelf;
2328 end:
2329 WIN_ReleaseWndPtr(wndPtr);
2330 return retvalue;
2334 /*****************************************************************
2335 * WIN_GetTopParent
2337 * Get the top-level parent for a child window.
2338 * returns a locked pointer
2340 WND* WIN_GetTopParentPtr( WND* pWnd )
2342 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2344 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2346 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2348 return tmpWnd;
2351 /*****************************************************************
2352 * WIN_GetTopParent
2354 * Get the top-level parent for a child window.
2356 HWND WIN_GetTopParent( HWND hwnd )
2358 HWND retvalue;
2359 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2360 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2362 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2363 WIN_ReleaseWndPtr(tmpPtr);
2364 WIN_ReleaseWndPtr(wndPtr);
2365 return retvalue;
2369 /*****************************************************************
2370 * SetParent16 (USER.233)
2372 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2374 return SetParent( hwndChild, hwndNewParent );
2378 /*****************************************************************
2379 * SetParent32 (USER32.495)
2381 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2383 WND *wndPtr;
2384 DWORD dwStyle;
2385 WND *pWndNewParent;
2386 WND *pWndOldParent;
2387 HWND retvalue;
2390 if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
2392 dwStyle = wndPtr->dwStyle;
2394 pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
2395 : WIN_LockWndPtr(pWndDesktop);
2397 /* Windows hides the window first, then shows it again
2398 * including the WM_SHOWWINDOW messages and all */
2399 if (dwStyle & WS_VISIBLE)
2400 ShowWindow( hwndChild, SW_HIDE );
2402 pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
2404 /* SetParent32 additionally needs to make hwndChild the topmost window
2405 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2406 WM_WINDOWPOSCHANGED notification messages.
2408 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2409 SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2410 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2411 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2413 retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
2415 WIN_ReleaseWndPtr(pWndOldParent);
2416 WIN_ReleaseWndPtr(pWndNewParent);
2417 WIN_ReleaseWndPtr(wndPtr);
2419 return retvalue;
2423 /*******************************************************************
2424 * IsChild16 (USER.48)
2426 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2428 return IsChild(parent,child);
2432 /*******************************************************************
2433 * IsChild32 (USER32.339)
2435 BOOL WINAPI IsChild( HWND parent, HWND child )
2437 WND * wndPtr = WIN_FindWndPtr( child );
2438 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2440 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2441 if (wndPtr->hwndSelf == parent)
2443 WIN_ReleaseWndPtr(wndPtr);
2444 return TRUE;
2447 WIN_ReleaseWndPtr(wndPtr);
2448 return FALSE;
2452 /***********************************************************************
2453 * IsWindowVisible16 (USER.49)
2455 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2457 return IsWindowVisible(hwnd);
2461 /***********************************************************************
2462 * IsWindowVisible32 (USER32.351)
2464 BOOL WINAPI IsWindowVisible( HWND hwnd )
2466 BOOL retval;
2467 WND *wndPtr = WIN_FindWndPtr( hwnd );
2468 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2470 if (!(wndPtr->dwStyle & WS_VISIBLE))
2472 WIN_ReleaseWndPtr(wndPtr);
2473 return FALSE;
2475 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2477 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2478 WIN_ReleaseWndPtr(wndPtr);
2479 return retval;
2484 /***********************************************************************
2485 * WIN_IsWindowDrawable
2487 * hwnd is drawable when it is visible, all parents are not
2488 * minimized, and it is itself not minimized unless we are
2489 * trying to draw its default class icon.
2491 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2493 if( (wnd->dwStyle & WS_MINIMIZE &&
2494 icon && wnd->class->hIcon) ||
2495 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2496 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2497 if( wnd->dwStyle & WS_MINIMIZE ||
2498 !(wnd->dwStyle & WS_VISIBLE) ) break;
2499 return (wnd == NULL);
2503 /*******************************************************************
2504 * GetTopWindow16 (USER.229)
2506 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2508 return GetTopWindow(hwnd);
2512 /*******************************************************************
2513 * GetTopWindow32 (USER.229)
2515 HWND WINAPI GetTopWindow( HWND hwnd )
2517 HWND retval = 0;
2518 WND * wndPtr = (hwnd) ?
2519 WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
2521 if (wndPtr && wndPtr->child)
2522 retval = wndPtr->child->hwndSelf;
2524 WIN_ReleaseWndPtr(wndPtr);
2525 return retval;
2529 /*******************************************************************
2530 * GetWindow16 (USER.262)
2532 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2534 return GetWindow( hwnd,rel );
2538 /*******************************************************************
2539 * GetWindow32 (USER32.302)
2541 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2543 HWND retval;
2545 WND * wndPtr = WIN_FindWndPtr( hwnd );
2546 if (!wndPtr) return 0;
2547 switch(rel)
2549 case GW_HWNDFIRST:
2550 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2551 goto end;
2553 case GW_HWNDLAST:
2554 if (!wndPtr->parent)
2556 retval = 0; /* Desktop window */
2557 goto end;
2559 while (wndPtr->next)
2561 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2563 retval = wndPtr->hwndSelf;
2564 goto end;
2566 case GW_HWNDNEXT:
2567 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2568 goto end;
2570 case GW_HWNDPREV:
2571 if (!wndPtr->parent)
2573 retval = 0; /* Desktop window */
2574 goto end;
2576 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2577 if (wndPtr->hwndSelf == hwnd)
2579 retval = 0; /* First in list */
2580 goto end;
2582 while (wndPtr->next)
2584 if (wndPtr->next->hwndSelf == hwnd)
2586 retval = wndPtr->hwndSelf;
2587 goto end;
2589 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2591 retval = 0;
2592 goto end;
2594 case GW_OWNER:
2595 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2596 goto end;
2598 case GW_CHILD:
2599 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2600 goto end;
2602 retval = 0;
2603 end:
2604 WIN_ReleaseWndPtr(wndPtr);
2605 return retval;
2609 /*******************************************************************
2610 * GetNextWindow16 (USER.230)
2612 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2614 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2615 return GetWindow16( hwnd, flag );
2618 /*******************************************************************
2619 * ShowOwnedPopups16 (USER.265)
2621 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2623 ShowOwnedPopups( owner, fShow );
2627 /*******************************************************************
2628 * ShowOwnedPopups32 (USER32.531)
2630 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2632 UINT totalChild=0, count=0;
2634 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2636 if (!pWnd) return TRUE;
2638 for (; count < totalChild; count++)
2640 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2642 if (fShow)
2644 if (pWnd[count]->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2646 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_SHOW, IsIconic(owner) ? SW_PARENTOPENING : SW_PARENTCLOSING);
2647 pWnd[count]->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2650 else
2652 if (IsWindowVisible(pWnd[count]->hwndSelf))
2654 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_HIDE, IsIconic(owner) ? SW_PARENTOPENING : SW_PARENTCLOSING);
2655 pWnd[count]->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2661 WIN_ReleaseDesktop();
2662 WIN_ReleaseWinArray(pWnd);
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 HWND retval;
2681 WND *wndPtr =WIN_FindWndPtr(hwnd);
2682 if (!wndPtr) return hwnd;
2683 retval = wndPtr->hwndLastActive;
2684 WIN_ReleaseWndPtr(wndPtr);
2685 return retval;
2689 /*******************************************************************
2690 * WIN_BuildWinArray
2692 * Build an array of pointers to the children of a given window.
2693 * The array must be freed with WIN_ReleaseWinArray. Return NULL
2694 * when no windows are found.
2696 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2698 /* Future: this function will lock all windows associated with this array */
2700 WND **list, **ppWnd;
2701 WND *pWnd;
2702 UINT count = 0, skipOwned, skipHidden;
2703 DWORD skipFlags;
2705 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2706 skipOwned = bwaFlags & BWA_SKIPOWNED;
2707 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2708 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2710 /* First count the windows */
2712 if (!wndPtr)
2713 wndPtr = WIN_GetDesktop();
2715 pWnd = WIN_LockWndPtr(wndPtr->child);
2716 while (pWnd)
2718 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2719 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2720 count++;
2721 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2724 if( count )
2726 /* Now build the list of all windows */
2728 if ((list = (WND **)HeapAlloc( GetProcessHeap(), 0, sizeof(WND *) * (count + 1))))
2730 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2732 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2733 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2735 *ppWnd++ = pWnd;
2736 count++;
2739 WIN_ReleaseWndPtr(pWnd);
2740 *ppWnd = NULL;
2742 else count = 0;
2743 } else list = NULL;
2745 if( pTotal ) *pTotal = count;
2746 return list;
2748 /*******************************************************************
2749 * WIN_ReleaseWinArray
2751 void WIN_ReleaseWinArray(WND **wndArray)
2753 /* Future: this function will also unlock all windows associated with wndArray */
2754 HeapFree( GetProcessHeap(), 0, wndArray );
2758 /*******************************************************************
2759 * EnumWindows16 (USER.54)
2761 BOOL16 WINAPI EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
2763 WND **list, **ppWnd;
2765 /* We have to build a list of all windows first, to avoid */
2766 /* unpleasant side-effects, for instance if the callback */
2767 /* function changes the Z-order of the windows. */
2769 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2771 WIN_ReleaseDesktop();
2772 return FALSE;
2775 /* Now call the callback function for every window */
2777 for (ppWnd = list; *ppWnd; ppWnd++)
2779 LRESULT lpEnumFuncRetval;
2780 int iWndsLocks = 0;
2781 /* Make sure that the window still exists */
2782 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2784 /* To avoid any deadlocks, all the locks on the windows
2785 structures must be suspended before the control
2786 is passed to the application */
2787 iWndsLocks = WIN_SuspendWndsLock();
2788 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2789 WIN_RestoreWndsLock(iWndsLocks);
2791 if (!lpEnumFuncRetval) break;
2793 WIN_ReleaseWinArray(list);
2794 WIN_ReleaseDesktop();
2795 return TRUE;
2799 /*******************************************************************
2800 * EnumWindows32 (USER32.193)
2802 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2804 return (BOOL)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2808 /**********************************************************************
2809 * EnumTaskWindows16 (USER.225)
2811 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2812 LPARAM lParam )
2814 WND **list, **ppWnd;
2816 /* This function is the same as EnumWindows(), */
2817 /* except for an added check on the window's task. */
2819 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2821 WIN_ReleaseDesktop();
2822 return FALSE;
2825 /* Now call the callback function for every window */
2827 for (ppWnd = list; *ppWnd; ppWnd++)
2829 LRESULT funcRetval;
2830 int iWndsLocks = 0;
2831 /* Make sure that the window still exists */
2832 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2833 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2835 /* To avoid any deadlocks, all the locks on the windows
2836 structures must be suspended before the control
2837 is passed to the application */
2838 iWndsLocks = WIN_SuspendWndsLock();
2839 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2840 WIN_RestoreWndsLock(iWndsLocks);
2842 if (!funcRetval) break;
2844 WIN_ReleaseWinArray(list);
2845 WIN_ReleaseDesktop();
2846 return TRUE;
2850 /**********************************************************************
2851 * EnumThreadWindows (USER32.190)
2853 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2855 TEB *teb = THREAD_IdToTEB(id);
2857 return (BOOL16)EnumTaskWindows16(teb->htask16, (WNDENUMPROC16)func, lParam);
2861 /**********************************************************************
2862 * WIN_EnumChildWindows
2864 * Helper function for EnumChildWindows().
2866 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2867 LPARAM lParam )
2869 WND **childList;
2870 BOOL16 ret = FALSE;
2872 for ( ; *ppWnd; ppWnd++)
2874 int iWndsLocks = 0;
2876 /* Make sure that the window still exists */
2877 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2878 /* Build children list first */
2879 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2881 /* To avoid any deadlocks, all the locks on the windows
2882 structures must be suspended before the control
2883 is passed to the application */
2884 iWndsLocks = WIN_SuspendWndsLock();
2885 ret = func( (*ppWnd)->hwndSelf, lParam );
2886 WIN_RestoreWndsLock(iWndsLocks);
2888 if (childList)
2890 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2891 WIN_ReleaseWinArray(childList);
2893 if (!ret) return FALSE;
2895 return TRUE;
2899 /**********************************************************************
2900 * EnumChildWindows16 (USER.55)
2902 BOOL16 WINAPI EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
2903 LPARAM lParam )
2905 WND **list, *pParent;
2907 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2908 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2910 WIN_ReleaseWndPtr(pParent);
2911 return FALSE;
2913 WIN_EnumChildWindows( list, func, lParam );
2914 WIN_ReleaseWinArray(list);
2915 WIN_ReleaseWndPtr(pParent);
2916 return TRUE;
2920 /**********************************************************************
2921 * EnumChildWindows32 (USER32.178)
2923 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2924 LPARAM lParam )
2926 return (BOOL)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2927 lParam );
2931 /*******************************************************************
2932 * AnyPopup16 (USER.52)
2934 BOOL16 WINAPI AnyPopup16(void)
2936 return AnyPopup();
2940 /*******************************************************************
2941 * AnyPopup32 (USER32.4)
2943 BOOL WINAPI AnyPopup(void)
2945 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2946 BOOL retvalue;
2948 while (wndPtr)
2950 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2952 retvalue = TRUE;
2953 goto end;
2955 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2957 retvalue = FALSE;
2958 end:
2959 WIN_ReleaseWndPtr(wndPtr);
2960 return retvalue;
2964 /*******************************************************************
2965 * FlashWindow16 (USER.105)
2967 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2969 return FlashWindow( hWnd, bInvert );
2973 /*******************************************************************
2974 * FlashWindow32 (USER32.202)
2976 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2978 WND *wndPtr = WIN_FindWndPtr(hWnd);
2980 TRACE("%04x\n", hWnd);
2982 if (!wndPtr) return FALSE;
2984 if (wndPtr->dwStyle & WS_MINIMIZE)
2986 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2988 HDC hDC = GetDC(hWnd);
2990 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2991 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2993 ReleaseDC( hWnd, hDC );
2994 wndPtr->flags |= WIN_NCACTIVATED;
2996 else
2998 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2999 RDW_UPDATENOW | RDW_FRAME, 0 );
3000 wndPtr->flags &= ~WIN_NCACTIVATED;
3002 WIN_ReleaseWndPtr(wndPtr);
3003 return TRUE;
3005 else
3007 WPARAM16 wparam;
3008 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3009 else wparam = (hWnd == GetActiveWindow());
3011 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3012 WIN_ReleaseWndPtr(wndPtr);
3013 return wparam;
3018 /*******************************************************************
3019 * SetSysModalWindow16 (USER.188)
3021 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3023 HWND hWndOldModal = hwndSysModal;
3024 hwndSysModal = hWnd;
3025 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3026 return hWndOldModal;
3030 /*******************************************************************
3031 * GetSysModalWindow16 (USER.52)
3033 HWND16 WINAPI GetSysModalWindow16(void)
3035 return hwndSysModal;
3039 /*******************************************************************
3040 * GetWindowContextHelpId (USER32.303)
3042 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3044 DWORD retval;
3045 WND *wnd = WIN_FindWndPtr( hwnd );
3046 if (!wnd) return 0;
3047 retval = wnd->helpContext;
3048 WIN_ReleaseWndPtr(wnd);
3049 return retval;
3053 /*******************************************************************
3054 * SetWindowContextHelpId (USER32.515)
3056 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3058 WND *wnd = WIN_FindWndPtr( hwnd );
3059 if (!wnd) return FALSE;
3060 wnd->helpContext = id;
3061 WIN_ReleaseWndPtr(wnd);
3062 return TRUE;
3066 /*******************************************************************
3067 * DRAG_QueryUpdate
3069 * recursively find a child that contains spDragInfo->pt point
3070 * and send WM_QUERYDROPOBJECT
3072 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3074 BOOL16 wParam, bResult = 0;
3075 POINT pt;
3076 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
3077 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3078 RECT tempRect;
3080 if( !ptrQueryWnd || !ptrDragInfo )
3081 goto end;
3083 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3085 GetWindowRect(hQueryWnd,&tempRect);
3087 if( !PtInRect(&tempRect,pt) ||
3088 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3089 goto end;
3091 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3093 tempRect = ptrQueryWnd->rectClient;
3094 if(ptrQueryWnd->dwStyle & WS_CHILD)
3095 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3096 (LPPOINT)&tempRect, 2 );
3098 if (PtInRect( &tempRect, pt))
3100 wParam = 0;
3102 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3104 if( ptrWnd->dwStyle & WS_VISIBLE )
3106 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3107 if (PtInRect( &tempRect, pt )) break;
3111 if(ptrWnd)
3113 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3114 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3115 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3116 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3117 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3119 WIN_ReleaseWndPtr(ptrWnd);
3122 if(bResult)
3123 goto end;
3125 else wParam = 1;
3127 else wParam = 1;
3129 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3131 ptrDragInfo->hScope = hQueryWnd;
3133 bResult = ( bNoSend )
3134 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3135 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3136 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3137 if( !bResult )
3138 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3140 end:
3141 WIN_ReleaseWndPtr(ptrQueryWnd);
3142 return bResult;
3146 /*******************************************************************
3147 * DragDetect (USER.465)
3149 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3151 POINT pt32;
3152 CONV_POINT16TO32( &pt, &pt32 );
3153 return DragDetect( hWnd, pt32 );
3156 /*******************************************************************
3157 * DragDetect32 (USER32.151)
3159 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3161 MSG16 msg;
3162 RECT16 rect;
3164 rect.left = pt.x - wDragWidth;
3165 rect.right = pt.x + wDragWidth;
3167 rect.top = pt.y - wDragHeight;
3168 rect.bottom = pt.y + wDragHeight;
3170 SetCapture(hWnd);
3172 while(1)
3174 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3176 if( msg.message == WM_LBUTTONUP )
3178 ReleaseCapture();
3179 return 0;
3181 if( msg.message == WM_MOUSEMOVE )
3183 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
3185 ReleaseCapture();
3186 return 1;
3190 WaitMessage();
3192 return 0;
3195 /******************************************************************************
3196 * DragObject16 (USER.464)
3198 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3199 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3201 MSG16 msg;
3202 LPDRAGINFO lpDragInfo;
3203 SEGPTR spDragInfo;
3204 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3205 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
3206 WND *wndPtr = WIN_FindWndPtr(hWnd);
3207 HCURSOR16 hCurrentCursor = 0;
3208 HWND16 hCurrentWnd = 0;
3210 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
3211 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
3213 if( !lpDragInfo || !spDragInfo )
3215 WIN_ReleaseWndPtr(wndPtr);
3216 return 0L;
3219 hBummer = LoadCursor16(0, IDC_BUMMER16);
3221 if( !hBummer || !wndPtr )
3223 GlobalFree16(hDragInfo);
3224 WIN_ReleaseWndPtr(wndPtr);
3225 return 0L;
3228 if(hCursor)
3230 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3232 GlobalFree16(hDragInfo);
3233 WIN_ReleaseWndPtr(wndPtr);
3234 return 0L;
3237 if( hDragCursor == hCursor ) hDragCursor = 0;
3238 else hCursor = hDragCursor;
3240 hOldCursor = SetCursor(hDragCursor);
3243 lpDragInfo->hWnd = hWnd;
3244 lpDragInfo->hScope = 0;
3245 lpDragInfo->wFlags = wObj;
3246 lpDragInfo->hList = szList; /* near pointer! */
3247 lpDragInfo->hOfStruct = hOfStruct;
3248 lpDragInfo->l = 0L;
3250 SetCapture(hWnd);
3251 ShowCursor( TRUE );
3255 do{ WaitMessage(); }
3256 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3258 *(lpDragInfo+1) = *lpDragInfo;
3260 lpDragInfo->pt = msg.pt;
3262 /* update DRAGINFO struct */
3263 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3265 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3266 hCurrentCursor = hCursor;
3267 else
3269 hCurrentCursor = hBummer;
3270 lpDragInfo->hScope = 0;
3272 if( hCurrentCursor )
3273 SetCursor(hCurrentCursor);
3275 /* send WM_DRAGLOOP */
3276 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3277 (LPARAM) spDragInfo );
3278 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3279 if( hCurrentWnd != lpDragInfo->hScope )
3281 if( hCurrentWnd )
3282 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3283 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
3284 HIWORD(spDragInfo)) );
3285 hCurrentWnd = lpDragInfo->hScope;
3286 if( hCurrentWnd )
3287 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3289 else
3290 if( hCurrentWnd )
3291 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3293 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3295 ReleaseCapture();
3296 ShowCursor( FALSE );
3298 if( hCursor )
3300 SetCursor( hOldCursor );
3301 if (hDragCursor) DestroyCursor( hDragCursor );
3304 if( hCurrentCursor != hBummer )
3305 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3306 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3307 else
3308 msg.lParam = 0;
3309 GlobalFree16(hDragInfo);
3310 WIN_ReleaseWndPtr(wndPtr);
3312 return (DWORD)(msg.lParam);