Jean-Claude Batista
[wine.git] / windows / win.c
bloba2fa889e51169ed0ba57e2ae5095d56521cc9968
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include <string.h>
9 #include "windef.h"
10 #include "wingdi.h"
11 #include "wine/winbase16.h"
12 #include "wine/winuser16.h"
13 #include "options.h"
14 #include "class.h"
15 #include "win.h"
16 #include "heap.h"
17 #include "user.h"
18 #include "dce.h"
19 #include "cursoricon.h"
20 #include "hook.h"
21 #include "menu.h"
22 #include "message.h"
23 #include "monitor.h"
24 #include "nonclient.h"
25 #include "queue.h"
26 #include "winpos.h"
27 #include "clipboard.h"
28 #include "winproc.h"
29 #include "task.h"
30 #include "thread.h"
31 #include "process.h"
32 #include "winerror.h"
33 #include "mdi.h"
34 #include "local.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;
591 TRACE("Creating desktop window\n");
594 if (!ICONTITLE_Init() ||
595 !WINPOS_CreateInternalPosAtom() ||
596 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
597 return FALSE;
599 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
600 if (!hwndDesktop) return FALSE;
601 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
603 pWndDesktop->pDriver = WND_Driver;
604 pWndDesktop->pDriver->pInitialize(pWndDesktop);
606 pWndDesktop->next = NULL;
607 pWndDesktop->child = NULL;
608 pWndDesktop->parent = NULL;
609 pWndDesktop->owner = NULL;
610 pWndDesktop->class = class;
611 pWndDesktop->dwMagic = WND_MAGIC;
612 pWndDesktop->hwndSelf = hwndDesktop;
613 pWndDesktop->hInstance = 0;
614 pWndDesktop->rectWindow.left = 0;
615 pWndDesktop->rectWindow.top = 0;
616 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
617 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
618 pWndDesktop->rectClient = pWndDesktop->rectWindow;
619 pWndDesktop->text = NULL;
620 pWndDesktop->hmemTaskQ = GetFastQueue16();
621 pWndDesktop->hrgnUpdate = 0;
622 pWndDesktop->hwndLastActive = hwndDesktop;
623 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
624 WS_CLIPSIBLINGS;
625 pWndDesktop->dwExStyle = 0;
626 pWndDesktop->dce = NULL;
627 pWndDesktop->pVScroll = NULL;
628 pWndDesktop->pHScroll = NULL;
629 pWndDesktop->pProp = NULL;
630 pWndDesktop->wIDmenu = 0;
631 pWndDesktop->helpContext = 0;
632 pWndDesktop->flags = Options.desktopGeometry ? WIN_NATIVE : 0;
633 pWndDesktop->hSysMenu = 0;
634 pWndDesktop->userdata = 0;
635 pWndDesktop->winproc = (WNDPROC16)class->winproc;
636 pWndDesktop->irefCount = 0;
638 /* FIXME: How do we know if it should be Unicode or not */
639 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop, class, FALSE))
640 return FALSE;
642 SendMessageA( hwndDesktop, WM_NCCREATE, 0, 0 );
643 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
644 return TRUE;
648 /***********************************************************************
649 * WIN_CreateWindowEx
651 * Implementation of CreateWindowEx().
653 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
654 BOOL win32, BOOL unicode )
656 INT sw = SW_SHOW;
657 CLASS *classPtr;
658 WND *wndPtr;
659 HWND retvalue;
660 HWND16 hwnd, hwndLinkAfter;
661 POINT maxSize, maxPos, minTrack, maxTrack;
662 LRESULT (CALLBACK *localSend32)(HWND, UINT, WPARAM, LPARAM);
664 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
665 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
666 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
667 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
668 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
670 /* Find the parent window */
672 if (cs->hwndParent)
674 /* Make sure parent is valid */
675 if (!IsWindow( cs->hwndParent ))
677 WARN("Bad parent %04x\n", cs->hwndParent );
678 return 0;
680 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
681 WARN("No parent for child window\n" );
682 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
685 /* Find the window class */
686 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
688 WARN("Bad class '%s'\n", cs->lpszClass );
689 return 0;
692 /* Fix the coordinates */
694 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
696 PDB *pdb = PROCESS_Current();
698 /* Never believe Microsoft's documentation... CreateWindowEx doc says
699 * that if an overlapped window is created with WS_VISIBLE style bit
700 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
701 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
702 * reveals that
704 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
705 * 2) it does not ignore the y parameter as the docs claim; instead, it
706 * uses it as second parameter to ShowWindow() unless y is either
707 * CW_USEDEFAULT or CW_USEDEFAULT16.
709 * The fact that we didn't do 2) caused bogus windows pop up when wine
710 * was running apps that were using this obscure feature. Example -
711 * calc.exe that comes with Win98 (only Win98, it's different from
712 * the one that comes with Win95 and NT)
714 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) sw = cs->y;
716 /* We have saved cs->y, now we can trash it */
717 if ( !(cs->style & (WS_CHILD | WS_POPUP))
718 && (pdb->env_db->startup_info->dwFlags & STARTF_USEPOSITION) )
720 cs->x = pdb->env_db->startup_info->dwX;
721 cs->y = pdb->env_db->startup_info->dwY;
723 else
725 cs->x = 0;
726 cs->y = 0;
729 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
731 PDB *pdb = PROCESS_Current();
732 if ( !(cs->style & (WS_CHILD | WS_POPUP))
733 && (pdb->env_db->startup_info->dwFlags & STARTF_USESIZE) )
735 cs->cx = pdb->env_db->startup_info->dwXSize;
736 cs->cy = pdb->env_db->startup_info->dwYSize;
738 else
740 cs->cx = 600; /* FIXME */
741 cs->cy = 400;
745 /* Create the window structure */
747 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
748 - sizeof(wndPtr->wExtra) )))
750 TRACE("out of memory\n" );
751 return 0;
754 /* Fill the window structure */
756 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
757 wndPtr->next = NULL;
758 wndPtr->child = NULL;
760 if ((cs->style & WS_CHILD) && cs->hwndParent)
762 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
763 wndPtr->owner = NULL;
764 WIN_ReleaseWndPtr(wndPtr->parent);
766 else
768 wndPtr->parent = pWndDesktop;
769 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
770 wndPtr->owner = NULL;
771 else
773 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
774 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
775 WIN_ReleaseWndPtr(wndPtr->owner);
776 WIN_ReleaseWndPtr(tmpWnd);
781 wndPtr->pDriver = wndPtr->parent->pDriver;
782 wndPtr->pDriver->pInitialize(wndPtr);
784 wndPtr->class = classPtr;
785 wndPtr->winproc = classPtr->winproc;
786 wndPtr->dwMagic = WND_MAGIC;
787 wndPtr->hwndSelf = hwnd;
788 wndPtr->hInstance = cs->hInstance;
789 wndPtr->text = NULL;
790 wndPtr->hmemTaskQ = GetFastQueue16();
791 wndPtr->hrgnUpdate = 0;
792 wndPtr->hwndLastActive = hwnd;
793 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
794 wndPtr->dwExStyle = cs->dwExStyle;
795 wndPtr->wIDmenu = 0;
796 wndPtr->helpContext = 0;
797 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
798 wndPtr->pVScroll = NULL;
799 wndPtr->pHScroll = NULL;
800 wndPtr->pProp = NULL;
801 wndPtr->userdata = 0;
802 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
803 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
804 wndPtr->irefCount = 1;
806 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
808 /* Call the WH_CBT hook */
810 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
811 ? HWND_BOTTOM : HWND_TOP;
813 if (HOOK_IsHooked( WH_CBT ))
815 CBT_CREATEWNDA cbtc;
816 LRESULT ret;
818 cbtc.lpcs = cs;
819 cbtc.hwndInsertAfter = hwndLinkAfter;
820 ret = unicode ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
821 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
822 if (ret)
824 TRACE("CBT-hook returned 0\n");
825 wndPtr->pDriver->pFinalize(wndPtr);
826 USER_HEAP_FREE( hwnd );
827 retvalue = 0;
828 goto end;
832 /* Increment class window counter */
834 classPtr->cWindows++;
836 /* Correct the window style */
838 if (!(cs->style & WS_CHILD))
840 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
841 if (!(cs->style & WS_POPUP))
843 wndPtr->dwStyle |= WS_CAPTION;
844 wndPtr->flags |= WIN_NEED_SIZE;
848 /* Get class or window DC if needed */
850 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
851 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
852 else wndPtr->dce = NULL;
854 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
856 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
858 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
859 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
860 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
861 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
862 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
865 if(cs->style & WS_CHILD)
867 if(cs->cx < 0) cs->cx = 0;
868 if(cs->cy < 0) cs->cy = 0;
870 else
872 if (cs->cx <= 0) cs->cx = 1;
873 if (cs->cy <= 0) cs->cy = 1;
876 wndPtr->rectWindow.left = cs->x;
877 wndPtr->rectWindow.top = cs->y;
878 wndPtr->rectWindow.right = cs->x + cs->cx;
879 wndPtr->rectWindow.bottom = cs->y + cs->cy;
880 wndPtr->rectClient = wndPtr->rectWindow;
882 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
884 retvalue = FALSE;
885 goto end;
888 /* Set the window menu */
890 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
892 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
893 else
895 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
896 if (classPtr->menuNameA)
897 cs->hMenu = HIWORD(classPtr->menuNameA) ?
898 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
899 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
900 #else
901 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
902 if (menuName)
904 if (HIWORD(cs->hInstance))
905 cs->hMenu = LoadMenuA(cs->hInstance,PTR_SEG_TO_LIN(menuName));
906 else
907 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
909 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
911 #endif
914 else wndPtr->wIDmenu = (UINT)cs->hMenu;
916 /* Send the WM_CREATE message
917 * Perhaps we shouldn't allow width/height changes as well.
918 * See p327 in "Internals".
921 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
923 localSend32 = unicode ? SendMessageW : SendMessageA;
924 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
926 /* Insert the window in the linked list */
928 WIN_LinkWindow( hwnd, hwndLinkAfter );
930 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
931 NULL, NULL, 0, &wndPtr->rectClient );
932 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
933 maxPos.y - wndPtr->rectWindow.top);
934 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
936 /* Send the size messages */
938 if (!(wndPtr->flags & WIN_NEED_SIZE))
940 /* send it anyway */
941 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
942 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
943 WARN("sending bogus WM_SIZE message 0x%08lx\n",
944 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
945 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
946 SendMessageA( hwnd, WM_SIZE, SIZE_RESTORED,
947 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
948 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
949 SendMessageA( hwnd, WM_MOVE, 0,
950 MAKELONG( wndPtr->rectClient.left,
951 wndPtr->rectClient.top ) );
954 /* Show the window, maximizing or minimizing if needed */
956 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
958 RECT16 newPos;
959 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
960 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
961 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
962 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
963 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
964 : SWP_NOZORDER | SWP_FRAMECHANGED;
965 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
966 newPos.right, newPos.bottom, swFlag );
969 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
971 /* Notify the parent window only */
973 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
974 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
975 if( !IsWindow(hwnd) )
977 retvalue = 0;
978 goto end;
982 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, sw );
984 /* Call WH_SHELL hook */
986 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
987 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
989 TRACE("created window %04x\n", hwnd);
990 retvalue = hwnd;
991 goto end;
993 WIN_UnlinkWindow( hwnd );
996 /* Abort window creation */
998 WARN("aborted by WM_xxCREATE!\n");
999 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1000 retvalue = 0;
1001 end:
1002 WIN_ReleaseWndPtr(wndPtr);
1004 return retvalue;
1008 /***********************************************************************
1009 * CreateWindow16 (USER.41)
1011 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1012 DWORD style, INT16 x, INT16 y, INT16 width,
1013 INT16 height, HWND16 parent, HMENU16 menu,
1014 HINSTANCE16 instance, LPVOID data )
1016 return CreateWindowEx16( 0, className, windowName, style,
1017 x, y, width, height, parent, menu, instance, data );
1021 /***********************************************************************
1022 * CreateWindowEx16 (USER.452)
1024 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1025 LPCSTR windowName, DWORD style, INT16 x,
1026 INT16 y, INT16 width, INT16 height,
1027 HWND16 parent, HMENU16 menu,
1028 HINSTANCE16 instance, LPVOID data )
1030 ATOM classAtom;
1031 CREATESTRUCTA cs;
1032 char buffer[256];
1034 /* Find the class atom */
1036 if (HIWORD(className))
1038 if (!(classAtom = GlobalFindAtomA( className )))
1040 ERR( "bad class name %s\n", debugres_a(className) );
1041 return 0;
1044 else
1046 classAtom = LOWORD(className);
1047 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1049 ERR( "bad atom %x\n", classAtom);
1050 return 0;
1052 className = buffer;
1055 /* Fix the coordinates */
1057 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1058 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1059 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1060 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1062 /* Create the window */
1064 cs.lpCreateParams = data;
1065 cs.hInstance = (HINSTANCE)instance;
1066 cs.hMenu = (HMENU)menu;
1067 cs.hwndParent = (HWND)parent;
1068 cs.style = style;
1069 cs.lpszName = windowName;
1070 cs.lpszClass = className;
1071 cs.dwExStyle = exStyle;
1073 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
1077 /***********************************************************************
1078 * CreateWindowExA (USER32.83)
1080 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1081 LPCSTR windowName, DWORD style, INT x,
1082 INT y, INT width, INT height,
1083 HWND parent, HMENU menu,
1084 HINSTANCE instance, LPVOID data )
1086 ATOM classAtom;
1087 CREATESTRUCTA cs;
1088 char buffer[256];
1090 if(!instance)
1091 instance=GetModuleHandleA(NULL);
1093 if(exStyle & WS_EX_MDICHILD)
1094 return MDI_CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1096 /* Find the class atom */
1098 if (HIWORD(className))
1100 if (!(classAtom = GlobalFindAtomA( className )))
1102 ERR( "bad class name %s\n", debugres_a(className) );
1103 return 0;
1106 else
1108 classAtom = LOWORD(className);
1109 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1111 ERR( "bad atom %x\n", classAtom);
1112 return 0;
1114 className = buffer;
1117 /* Create the window */
1119 cs.lpCreateParams = data;
1120 cs.hInstance = instance;
1121 cs.hMenu = menu;
1122 cs.hwndParent = parent;
1123 cs.x = x;
1124 cs.y = y;
1125 cs.cx = width;
1126 cs.cy = height;
1127 cs.style = style;
1128 cs.lpszName = windowName;
1129 cs.lpszClass = className;
1130 cs.dwExStyle = exStyle;
1132 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
1136 /***********************************************************************
1137 * CreateWindowExW (USER32.84)
1139 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1140 LPCWSTR windowName, DWORD style, INT x,
1141 INT y, INT width, INT height,
1142 HWND parent, HMENU menu,
1143 HINSTANCE instance, LPVOID data )
1145 ATOM classAtom;
1146 CREATESTRUCTW cs;
1147 WCHAR buffer[256];
1149 if(!instance)
1150 instance=GetModuleHandleA(NULL);
1152 if(exStyle & WS_EX_MDICHILD)
1153 return MDI_CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1155 /* Find the class atom */
1157 if (HIWORD(className))
1159 if (!(classAtom = GlobalFindAtomW( className )))
1161 ERR( "bad class name %s\n", debugres_w(className) );
1162 return 0;
1165 else
1167 classAtom = LOWORD(className);
1168 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1170 ERR( "bad atom %x\n", classAtom);
1171 return 0;
1173 className = buffer;
1176 /* Create the window */
1178 cs.lpCreateParams = data;
1179 cs.hInstance = instance;
1180 cs.hMenu = menu;
1181 cs.hwndParent = parent;
1182 cs.x = x;
1183 cs.y = y;
1184 cs.cx = width;
1185 cs.cy = height;
1186 cs.style = style;
1187 cs.lpszName = windowName;
1188 cs.lpszClass = className;
1189 cs.dwExStyle = exStyle;
1191 /* Note: we rely on the fact that CREATESTRUCTA and */
1192 /* CREATESTRUCTW have the same layout. */
1193 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, TRUE, TRUE );
1197 /***********************************************************************
1198 * WIN_CheckFocus
1200 static void WIN_CheckFocus( WND* pWnd )
1202 if( GetFocus16() == pWnd->hwndSelf )
1203 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
1206 /***********************************************************************
1207 * WIN_SendDestroyMsg
1209 static void WIN_SendDestroyMsg( WND* pWnd )
1211 WIN_CheckFocus(pWnd);
1213 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1214 CLIPBOARD_Driver->pResetOwner( pWnd, TRUE );
1217 * Send the WM_DESTROY to the window.
1219 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1222 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1223 * make sure that the window still exists when we come back.
1225 if (IsWindow(pWnd->hwndSelf))
1227 HWND* pWndArray = NULL;
1228 WND* pChild = NULL;
1229 int nKidCount = 0;
1232 * Now, if the window has kids, we have to send WM_DESTROY messages
1233 * recursively to it's kids. It seems that those calls can also
1234 * trigger re-entrant calls to DestroyWindow for the kids so we must
1235 * protect against corruption of the list of siblings. We first build
1236 * a list of HWNDs representing all the kids.
1238 pChild = WIN_LockWndPtr(pWnd->child);
1239 while( pChild )
1241 nKidCount++;
1242 WIN_UpdateWndPtr(&pChild,pChild->next);
1246 * If there are no kids, we're done.
1248 if (nKidCount==0)
1249 return;
1251 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1254 * Sanity check
1256 if (pWndArray==NULL)
1257 return;
1260 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1261 * call, our linked list of siblings should be safe.
1263 nKidCount = 0;
1264 pChild = WIN_LockWndPtr(pWnd->child);
1265 while( pChild )
1267 pWndArray[nKidCount] = pChild->hwndSelf;
1268 nKidCount++;
1269 WIN_UpdateWndPtr(&pChild,pChild->next);
1273 * Now that we have a list, go through that list again and send the destroy
1274 * message to those windows. We are using the HWND to retrieve the
1275 * WND pointer so we are effectively checking that all the kid windows are
1276 * still valid before sending the message.
1278 while (nKidCount>0)
1280 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1282 if (pChild!=NULL)
1284 WIN_SendDestroyMsg( pChild );
1285 WIN_ReleaseWndPtr(pChild);
1290 * Cleanup
1292 HeapFree(GetProcessHeap(), 0, pWndArray);
1293 WIN_CheckFocus(pWnd);
1295 else
1296 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1300 /***********************************************************************
1301 * DestroyWindow16 (USER.53)
1303 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1305 return DestroyWindow(hwnd);
1309 /***********************************************************************
1310 * DestroyWindow (USER32.135)
1312 BOOL WINAPI DestroyWindow( HWND hwnd )
1314 WND * wndPtr;
1315 BOOL retvalue;
1317 TRACE("(%04x)\n", hwnd);
1319 /* Initialization */
1321 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1322 if (wndPtr == pWndDesktop)
1324 retvalue = FALSE; /* Can't destroy desktop */
1325 goto end;
1328 /* Call hooks */
1330 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1332 retvalue = FALSE;
1333 goto end;
1336 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1338 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1339 /* FIXME: clean up palette - see "Internals" p.352 */
1342 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1343 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1345 /* Notify the parent window only */
1346 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1347 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1348 if( !IsWindow(hwnd) )
1350 retvalue = TRUE;
1351 goto end;
1355 CLIPBOARD_Driver->pResetOwner( wndPtr, FALSE ); /* before the window is unmapped */
1357 /* Hide the window */
1359 if (wndPtr->dwStyle & WS_VISIBLE)
1361 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1362 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1363 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1364 if (!IsWindow(hwnd))
1366 retvalue = TRUE;
1367 goto end;
1371 /* Recursively destroy owned windows */
1373 if( !(wndPtr->dwStyle & WS_CHILD) )
1375 /* make sure top menu popup doesn't get destroyed */
1376 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1378 for (;;)
1380 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1381 while (siblingPtr)
1383 if (siblingPtr->owner == wndPtr)
1385 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1386 break;
1387 else
1388 siblingPtr->owner = NULL;
1390 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1392 if (siblingPtr)
1394 DestroyWindow( siblingPtr->hwndSelf );
1395 WIN_ReleaseWndPtr(siblingPtr);
1397 else break;
1400 if( !Options.managed || EVENT_CheckFocus() )
1401 WINPOS_ActivateOtherWindow(wndPtr);
1403 if( wndPtr->owner &&
1404 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1405 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1408 /* Send destroy messages */
1410 WIN_SendDestroyMsg( wndPtr );
1411 if (!IsWindow(hwnd))
1413 retvalue = TRUE;
1414 goto end;
1417 /* Unlink now so we won't bother with the children later on */
1419 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1421 /* Destroy the window storage */
1423 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1424 retvalue = TRUE;
1425 end:
1426 WIN_ReleaseWndPtr(wndPtr);
1427 return retvalue;
1431 /***********************************************************************
1432 * CloseWindow16 (USER.43)
1434 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1436 return CloseWindow( hwnd );
1440 /***********************************************************************
1441 * CloseWindow (USER32.56)
1443 BOOL WINAPI CloseWindow( HWND hwnd )
1445 WND * wndPtr = WIN_FindWndPtr( hwnd );
1446 BOOL retvalue;
1448 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1450 retvalue = FALSE;
1451 goto end;
1453 ShowWindow( hwnd, SW_MINIMIZE );
1454 retvalue = TRUE;
1455 end:
1456 WIN_ReleaseWndPtr(wndPtr);
1457 return retvalue;
1462 /***********************************************************************
1463 * OpenIcon16 (USER.44)
1465 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1467 return OpenIcon( hwnd );
1471 /***********************************************************************
1472 * OpenIcon (USER32.410)
1474 BOOL WINAPI OpenIcon( HWND hwnd )
1476 if (!IsIconic( hwnd )) return FALSE;
1477 ShowWindow( hwnd, SW_SHOWNORMAL );
1478 return TRUE;
1482 /***********************************************************************
1483 * WIN_FindWindow
1485 * Implementation of FindWindow() and FindWindowEx().
1487 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1488 LPCSTR title )
1490 WND *pWnd;
1491 HWND retvalue;
1493 if (child)
1495 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1496 if (parent)
1498 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1500 retvalue = 0;
1501 goto end;
1504 else if (pWnd->parent != pWndDesktop)
1506 retvalue = 0;
1507 goto end;
1509 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1511 else
1513 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1515 retvalue = 0;
1516 goto end;
1518 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1520 if (!pWnd)
1522 retvalue = 0;
1523 goto end;
1526 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1528 if (className && (pWnd->class->atomName != className))
1529 continue; /* Not the right class */
1531 /* Now check the title */
1533 if (!title)
1535 retvalue = pWnd->hwndSelf;
1536 goto end;
1538 if (pWnd->text && !strcmp( pWnd->text, title ))
1540 retvalue = pWnd->hwndSelf;
1541 goto end;
1544 retvalue = 0;
1545 end:
1546 WIN_ReleaseWndPtr(pWnd);
1547 return retvalue;
1552 /***********************************************************************
1553 * FindWindow16 (USER.50)
1555 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1557 return FindWindowA( className, title );
1561 /***********************************************************************
1562 * FindWindowEx16 (USER.427)
1564 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1566 return FindWindowExA( parent, child, className, title );
1570 /***********************************************************************
1571 * FindWindowA (USER32.198)
1573 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1575 HWND ret = FindWindowExA( 0, 0, className, title );
1576 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1577 return ret;
1581 /***********************************************************************
1582 * FindWindowExA (USER32.199)
1584 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1585 LPCSTR className, LPCSTR title )
1587 ATOM atom = 0;
1589 if (className)
1591 /* If the atom doesn't exist, then no class */
1592 /* with this name exists either. */
1593 if (!(atom = GlobalFindAtomA( className )))
1595 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1596 return 0;
1599 return WIN_FindWindow( parent, child, atom, title );
1603 /***********************************************************************
1604 * FindWindowExW (USER32.200)
1606 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1607 LPCWSTR className, LPCWSTR title )
1609 ATOM atom = 0;
1610 char *buffer;
1611 HWND hwnd;
1613 if (className)
1615 /* If the atom doesn't exist, then no class */
1616 /* with this name exists either. */
1617 if (!(atom = GlobalFindAtomW( className )))
1619 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1620 return 0;
1623 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1624 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1625 HeapFree( GetProcessHeap(), 0, buffer );
1626 return hwnd;
1630 /***********************************************************************
1631 * FindWindowW (USER32.201)
1633 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1635 return FindWindowExW( 0, 0, className, title );
1639 /**********************************************************************
1640 * WIN_GetDesktop
1641 * returns a locked pointer
1643 WND *WIN_GetDesktop(void)
1645 return WIN_LockWndPtr(pWndDesktop);
1647 /**********************************************************************
1648 * WIN_ReleaseDesktop
1649 * unlock the desktop pointer
1651 void WIN_ReleaseDesktop(void)
1653 WIN_ReleaseWndPtr(pWndDesktop);
1657 /**********************************************************************
1658 * GetDesktopWindow16 (USER.286)
1660 HWND16 WINAPI GetDesktopWindow16(void)
1662 return (HWND16)pWndDesktop->hwndSelf;
1666 /**********************************************************************
1667 * GetDesktopWindow (USER32.232)
1669 HWND WINAPI GetDesktopWindow(void)
1671 if (pWndDesktop) return pWndDesktop->hwndSelf;
1672 ERR( "You need the -desktop option when running with native USER\n" );
1673 ExitProcess(1);
1674 return 0;
1678 /**********************************************************************
1679 * GetDesktopHwnd (USER.278)
1681 * Exactly the same thing as GetDesktopWindow(), but not documented.
1682 * Don't ask me why...
1684 HWND16 WINAPI GetDesktopHwnd16(void)
1686 return (HWND16)pWndDesktop->hwndSelf;
1690 /*******************************************************************
1691 * EnableWindow16 (USER.34)
1693 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1695 return EnableWindow( hwnd, enable );
1699 /*******************************************************************
1700 * EnableWindow (USER32.172)
1702 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1704 WND *wndPtr;
1705 BOOL retvalue;
1707 TRACE("EnableWindow32: ( %x, %d )\n", hwnd, enable);
1709 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1710 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1712 /* Enable window */
1713 wndPtr->dwStyle &= ~WS_DISABLED;
1715 if( wndPtr->flags & WIN_NATIVE )
1716 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
1718 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1719 retvalue = TRUE;
1720 goto end;
1722 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1724 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1726 /* Disable window */
1727 wndPtr->dwStyle |= WS_DISABLED;
1729 if( wndPtr->flags & WIN_NATIVE )
1730 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
1732 if (hwnd == GetFocus())
1734 SetFocus( 0 ); /* A disabled window can't have the focus */
1736 if (hwnd == GetCapture())
1738 ReleaseCapture(); /* A disabled window can't capture the mouse */
1740 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1741 retvalue = FALSE;
1742 goto end;
1744 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1745 end:
1746 WIN_ReleaseWndPtr(wndPtr);
1747 return retvalue;
1751 /***********************************************************************
1752 * IsWindowEnabled16 (USER.35)
1754 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1756 return IsWindowEnabled(hWnd);
1760 /***********************************************************************
1761 * IsWindowEnabled (USER32.349)
1763 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1765 WND * wndPtr;
1766 BOOL retvalue;
1768 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1769 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1770 WIN_ReleaseWndPtr(wndPtr);
1771 return retvalue;
1776 /***********************************************************************
1777 * IsWindowUnicode (USER32.350)
1779 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1781 WND * wndPtr;
1782 BOOL retvalue;
1784 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1785 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1786 WIN_ReleaseWndPtr(wndPtr);
1787 return retvalue;
1791 /**********************************************************************
1792 * GetWindowWord16 (USER.133)
1794 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1796 return GetWindowWord( hwnd, offset );
1800 /**********************************************************************
1801 * GetWindowWord (USER32.314)
1803 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1805 WORD retvalue;
1806 WND * wndPtr = WIN_FindWndPtr( hwnd );
1807 if (!wndPtr) return 0;
1808 if (offset >= 0)
1810 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1812 WARN("Invalid offset %d\n", offset );
1813 retvalue = 0;
1814 goto end;
1816 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1817 goto end;
1819 switch(offset)
1821 case GWW_ID:
1822 if (HIWORD(wndPtr->wIDmenu))
1823 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1824 wndPtr->wIDmenu);
1825 retvalue = (WORD)wndPtr->wIDmenu;
1826 goto end;
1827 case GWW_HWNDPARENT:
1828 retvalue = GetParent(hwnd);
1829 goto end;
1830 case GWW_HINSTANCE:
1831 if (HIWORD(wndPtr->hInstance))
1832 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1833 wndPtr->hInstance);
1834 retvalue = (WORD)wndPtr->hInstance;
1835 goto end;
1836 default:
1837 WARN("Invalid offset %d\n", offset );
1838 retvalue = 0;
1839 goto end;
1841 end:
1842 WIN_ReleaseWndPtr(wndPtr);
1843 return retvalue;
1846 /**********************************************************************
1847 * SetWindowWord16 (USER.134)
1849 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1851 return SetWindowWord( hwnd, offset, newval );
1855 /**********************************************************************
1856 * SetWindowWord (USER32.524)
1858 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1860 WORD *ptr, retval;
1861 WND * wndPtr = WIN_FindWndPtr( hwnd );
1862 if (!wndPtr) return 0;
1863 if (offset >= 0)
1865 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1867 WARN("Invalid offset %d\n", offset );
1868 retval = 0;
1869 goto end;
1871 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1873 else switch(offset)
1875 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1876 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1877 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1878 goto end;
1879 default:
1880 WARN("Invalid offset %d\n", offset );
1881 retval = 0;
1882 goto end;
1884 retval = *ptr;
1885 *ptr = newval;
1886 end:
1887 WIN_ReleaseWndPtr(wndPtr);
1888 return retval;
1892 /**********************************************************************
1893 * WIN_GetWindowLong
1895 * Helper function for GetWindowLong().
1897 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1899 LONG retvalue;
1900 WND * wndPtr = WIN_FindWndPtr( hwnd );
1901 if (!wndPtr) return 0;
1902 if (offset >= 0)
1904 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1906 WARN("Invalid offset %d\n", offset );
1907 retvalue = 0;
1908 goto end;
1910 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1911 /* Special case for dialog window procedure */
1912 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1914 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1915 goto end;
1917 goto end;
1919 switch(offset)
1921 case GWL_USERDATA: retvalue = wndPtr->userdata;
1922 goto end;
1923 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1924 goto end;
1925 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1926 goto end;
1927 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1928 goto end;
1929 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1930 type );
1931 goto end;
1932 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1933 goto end;
1934 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1935 goto end;
1936 default:
1937 WARN("Unknown offset %d\n", offset );
1939 retvalue = 0;
1940 end:
1941 WIN_ReleaseWndPtr(wndPtr);
1942 return retvalue;
1946 /**********************************************************************
1947 * WIN_SetWindowLong
1949 * Helper function for SetWindowLong().
1951 * 0 is the failure code. However, in the case of failure SetLastError
1952 * must be set to distinguish between a 0 return value and a failure.
1954 * FIXME: The error values for SetLastError may not be right. Can
1955 * someone check with the real thing?
1957 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1958 WINDOWPROCTYPE type )
1960 LONG *ptr, retval;
1961 WND * wndPtr = WIN_FindWndPtr( hwnd );
1962 STYLESTRUCT style;
1964 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1966 if (!wndPtr)
1968 /* Is this the right error? */
1969 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1970 return 0;
1973 if (offset >= 0)
1975 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1977 WARN("Invalid offset %d\n", offset );
1979 /* Is this the right error? */
1980 SetLastError( ERROR_OUTOFMEMORY );
1982 retval = 0;
1983 goto end;
1985 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1986 /* Special case for dialog window procedure */
1987 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1989 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1990 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1991 type, WIN_PROC_WINDOW );
1992 goto end;
1995 else switch(offset)
1997 case GWL_ID:
1998 ptr = (DWORD*)&wndPtr->wIDmenu;
1999 break;
2000 case GWL_HINSTANCE:
2001 retval = SetWindowWord( hwnd, offset, newval );
2002 goto end;
2003 case GWL_WNDPROC:
2004 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2005 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2006 type, WIN_PROC_WINDOW );
2007 goto end;
2008 case GWL_STYLE:
2009 style.styleOld = wndPtr->dwStyle;
2010 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
2011 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
2013 if (wndPtr->flags & WIN_ISWIN32)
2014 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
2015 wndPtr->dwStyle = style.styleNew;
2016 if (wndPtr->flags & WIN_ISWIN32)
2017 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
2018 retval = style.styleOld;
2019 goto end;
2021 case GWL_USERDATA:
2022 ptr = &wndPtr->userdata;
2023 break;
2024 case GWL_EXSTYLE:
2025 style.styleOld = wndPtr->dwExStyle;
2026 style.styleNew = newval;
2027 if (wndPtr->flags & WIN_ISWIN32)
2028 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
2029 wndPtr->dwExStyle = newval;
2030 if (wndPtr->flags & WIN_ISWIN32)
2031 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
2032 retval = style.styleOld;
2033 goto end;
2035 default:
2036 WARN("Invalid offset %d\n", offset );
2038 /* Don't think this is right error but it should do */
2039 SetLastError( ERROR_OUTOFMEMORY );
2041 retval = 0;
2042 goto end;
2044 retval = *ptr;
2045 *ptr = newval;
2046 end:
2047 WIN_ReleaseWndPtr(wndPtr);
2048 return retval;
2052 /**********************************************************************
2053 * GetWindowLong16 (USER.135)
2055 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2057 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2061 /**********************************************************************
2062 * GetWindowLongA (USER32.305)
2064 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2066 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2070 /**********************************************************************
2071 * GetWindowLongW (USER32.306)
2073 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2075 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2079 /**********************************************************************
2080 * SetWindowLong16 (USER.136)
2082 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2084 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2088 /**********************************************************************
2089 * SetWindowLongA (USER32.517)
2091 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2093 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2097 /**********************************************************************
2098 * SetWindowLongW (USER32.518) Set window attribute
2100 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2101 * value in a window's extra memory.
2103 * The _hwnd_ parameter specifies the window. is the handle to a
2104 * window that has extra memory. The _newval_ parameter contains the
2105 * new attribute or extra memory value. If positive, the _offset_
2106 * parameter is the byte-addressed location in the window's extra
2107 * memory to set. If negative, _offset_ specifies the window
2108 * attribute to set, and should be one of the following values:
2110 * GWL_EXSTYLE The window's extended window style
2112 * GWL_STYLE The window's window style.
2114 * GWL_WNDPROC Pointer to the window's window procedure.
2116 * GWL_HINSTANCE The window's pplication instance handle.
2118 * GWL_ID The window's identifier.
2120 * GWL_USERDATA The window's user-specified data.
2122 * If the window is a dialog box, the _offset_ parameter can be one of
2123 * the following values:
2125 * DWL_DLGPROC The address of the window's dialog box procedure.
2127 * DWL_MSGRESULT The return value of a message
2128 * that the dialog box procedure processed.
2130 * DWL_USER Application specific information.
2132 * RETURNS
2134 * If successful, returns the previous value located at _offset_. Otherwise,
2135 * returns 0.
2137 * NOTES
2139 * Extra memory for a window class is specified by a nonzero cbWndExtra
2140 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2141 * time of class creation.
2143 * Using GWL_WNDPROC to set a new window procedure effectively creates
2144 * a window subclass. Use CallWindowProc() in the new windows procedure
2145 * to pass messages to the superclass's window procedure.
2147 * The user data is reserved for use by the application which created
2148 * the window.
2150 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2151 * instead, call the EnableWindow() function to change the window's
2152 * disabled state.
2154 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2155 * SetParent() instead.
2157 * Win95:
2158 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2159 * it sends WM_STYLECHANGING before changing the settings
2160 * and WM_STYLECHANGED afterwards.
2161 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2163 * BUGS
2165 * GWL_STYLE does not dispatch WM_STYLE... messages.
2167 * CONFORMANCE
2169 * ECMA-234, Win32
2172 LONG WINAPI SetWindowLongW(
2173 HWND hwnd, /* window to alter */
2174 INT offset, /* offset, in bytes, of location to alter */
2175 LONG newval /* new value of location */
2177 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2181 /*******************************************************************
2182 * GetWindowText16 (USER.36)
2184 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2186 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2190 /*******************************************************************
2191 * GetWindowTextA (USER32.309)
2193 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2195 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2196 (LPARAM)lpString );
2199 /*******************************************************************
2200 * InternalGetWindowText (USER32.326)
2202 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2204 FIXME("(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2205 return GetWindowTextW(hwnd,lpString,nMaxCount);
2209 /*******************************************************************
2210 * GetWindowTextW (USER32.312)
2212 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2214 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2215 (LPARAM)lpString );
2219 /*******************************************************************
2220 * SetWindowText16 (USER.37)
2222 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2224 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2228 /*******************************************************************
2229 * SetWindowTextA (USER32.521)
2231 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2233 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2237 /*******************************************************************
2238 * SetWindowTextW (USER32.523)
2240 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2242 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2246 /*******************************************************************
2247 * GetWindowTextLength16 (USER.38)
2249 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2251 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2255 /*******************************************************************
2256 * GetWindowTextLengthA (USER32.310)
2258 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2260 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2263 /*******************************************************************
2264 * GetWindowTextLengthW (USER32.311)
2266 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2268 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2272 /*******************************************************************
2273 * IsWindow16 (USER.47)
2275 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2277 CURRENT_STACK16->es = USER_HeapSel;
2278 return IsWindow( hwnd );
2282 /*******************************************************************
2283 * IsWindow (USER32.348)
2285 BOOL WINAPI IsWindow( HWND hwnd )
2287 WND * wndPtr;
2288 BOOL retvalue;
2290 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2291 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2292 WIN_ReleaseWndPtr(wndPtr);
2293 return retvalue;
2298 /*****************************************************************
2299 * GetParent16 (USER.46)
2301 HWND16 WINAPI GetParent16( HWND16 hwnd )
2303 return (HWND16)GetParent( hwnd );
2307 /*****************************************************************
2308 * GetParent (USER32.278)
2310 HWND WINAPI GetParent( HWND hwnd )
2312 WND *wndPtr;
2313 HWND retvalue = 0;
2315 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2316 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2317 goto end;
2319 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2320 if (wndPtr)
2321 retvalue = wndPtr->hwndSelf;
2323 end:
2324 WIN_ReleaseWndPtr(wndPtr);
2325 return retvalue;
2329 /*****************************************************************
2330 * WIN_GetTopParent
2332 * Get the top-level parent for a child window.
2333 * returns a locked pointer
2335 WND* WIN_GetTopParentPtr( WND* pWnd )
2337 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2339 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2341 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2343 return tmpWnd;
2346 /*****************************************************************
2347 * WIN_GetTopParent
2349 * Get the top-level parent for a child window.
2351 HWND WIN_GetTopParent( HWND hwnd )
2353 HWND retvalue;
2354 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2355 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2357 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2358 WIN_ReleaseWndPtr(tmpPtr);
2359 WIN_ReleaseWndPtr(wndPtr);
2360 return retvalue;
2364 /*****************************************************************
2365 * SetParent16 (USER.233)
2367 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2369 return SetParent( hwndChild, hwndNewParent );
2373 /*****************************************************************
2374 * SetParent (USER32.495)
2376 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2378 WND *wndPtr;
2379 DWORD dwStyle;
2380 WND *pWndNewParent;
2381 WND *pWndOldParent;
2382 HWND retvalue;
2385 if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
2387 dwStyle = wndPtr->dwStyle;
2389 pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
2390 : WIN_LockWndPtr(pWndDesktop);
2392 /* Windows hides the window first, then shows it again
2393 * including the WM_SHOWWINDOW messages and all */
2394 if (dwStyle & WS_VISIBLE)
2395 ShowWindow( hwndChild, SW_HIDE );
2397 pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
2399 /* SetParent additionally needs to make hwndChild the topmost window
2400 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2401 WM_WINDOWPOSCHANGED notification messages.
2403 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2404 SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2405 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2406 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2408 retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
2410 WIN_ReleaseWndPtr(pWndOldParent);
2411 WIN_ReleaseWndPtr(pWndNewParent);
2412 WIN_ReleaseWndPtr(wndPtr);
2414 return retvalue;
2418 /*******************************************************************
2419 * IsChild16 (USER.48)
2421 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2423 return IsChild(parent,child);
2427 /*******************************************************************
2428 * IsChild (USER32.339)
2430 BOOL WINAPI IsChild( HWND parent, HWND child )
2432 WND * wndPtr = WIN_FindWndPtr( child );
2433 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2435 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2436 if (wndPtr->hwndSelf == parent)
2438 WIN_ReleaseWndPtr(wndPtr);
2439 return TRUE;
2442 WIN_ReleaseWndPtr(wndPtr);
2443 return FALSE;
2447 /***********************************************************************
2448 * IsWindowVisible16 (USER.49)
2450 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2452 return IsWindowVisible(hwnd);
2456 /***********************************************************************
2457 * IsWindowVisible (USER32.351)
2459 BOOL WINAPI IsWindowVisible( HWND hwnd )
2461 BOOL retval;
2462 WND *wndPtr = WIN_FindWndPtr( hwnd );
2463 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2465 if (!(wndPtr->dwStyle & WS_VISIBLE))
2467 WIN_ReleaseWndPtr(wndPtr);
2468 return FALSE;
2470 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2472 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2473 WIN_ReleaseWndPtr(wndPtr);
2474 return retval;
2479 /***********************************************************************
2480 * WIN_IsWindowDrawable
2482 * hwnd is drawable when it is visible, all parents are not
2483 * minimized, and it is itself not minimized unless we are
2484 * trying to draw its default class icon.
2486 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2488 if( (wnd->dwStyle & WS_MINIMIZE &&
2489 icon && wnd->class->hIcon) ||
2490 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2491 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2492 if( wnd->dwStyle & WS_MINIMIZE ||
2493 !(wnd->dwStyle & WS_VISIBLE) ) break;
2494 return (wnd == NULL);
2498 /*******************************************************************
2499 * GetTopWindow16 (USER.229)
2501 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2503 return GetTopWindow(hwnd);
2507 /*******************************************************************
2508 * GetTopWindow (USER.229)
2510 HWND WINAPI GetTopWindow( HWND hwnd )
2512 HWND retval = 0;
2513 WND * wndPtr = (hwnd) ?
2514 WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
2516 if (wndPtr && wndPtr->child)
2517 retval = wndPtr->child->hwndSelf;
2519 WIN_ReleaseWndPtr(wndPtr);
2520 return retval;
2524 /*******************************************************************
2525 * GetWindow16 (USER.262)
2527 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2529 return GetWindow( hwnd,rel );
2533 /*******************************************************************
2534 * GetWindow (USER32.302)
2536 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2538 HWND retval;
2540 WND * wndPtr = WIN_FindWndPtr( hwnd );
2541 if (!wndPtr) return 0;
2542 switch(rel)
2544 case GW_HWNDFIRST:
2545 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2546 goto end;
2548 case GW_HWNDLAST:
2549 if (!wndPtr->parent)
2551 retval = 0; /* Desktop window */
2552 goto end;
2554 while (wndPtr->next)
2556 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2558 retval = wndPtr->hwndSelf;
2559 goto end;
2561 case GW_HWNDNEXT:
2562 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2563 goto end;
2565 case GW_HWNDPREV:
2566 if (!wndPtr->parent)
2568 retval = 0; /* Desktop window */
2569 goto end;
2571 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2572 if (wndPtr->hwndSelf == hwnd)
2574 retval = 0; /* First in list */
2575 goto end;
2577 while (wndPtr->next)
2579 if (wndPtr->next->hwndSelf == hwnd)
2581 retval = wndPtr->hwndSelf;
2582 goto end;
2584 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2586 retval = 0;
2587 goto end;
2589 case GW_OWNER:
2590 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2591 goto end;
2593 case GW_CHILD:
2594 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2595 goto end;
2597 retval = 0;
2598 end:
2599 WIN_ReleaseWndPtr(wndPtr);
2600 return retval;
2604 /*******************************************************************
2605 * GetNextWindow16 (USER.230)
2607 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2609 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2610 return GetWindow16( hwnd, flag );
2613 /*******************************************************************
2614 * ShowOwnedPopups16 (USER.265)
2616 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2618 ShowOwnedPopups( owner, fShow );
2622 /*******************************************************************
2623 * ShowOwnedPopups (USER32.531)
2625 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2627 UINT totalChild=0, count=0;
2629 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2631 if (!pWnd) return TRUE;
2633 for (; count < totalChild; count++)
2635 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2637 if (fShow)
2639 if (pWnd[count]->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2641 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_SHOW, IsIconic(owner) ? SW_PARENTOPENING : SW_PARENTCLOSING);
2642 pWnd[count]->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2645 else
2647 if (IsWindowVisible(pWnd[count]->hwndSelf))
2649 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_HIDE, IsIconic(owner) ? SW_PARENTOPENING : SW_PARENTCLOSING);
2650 pWnd[count]->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2656 WIN_ReleaseDesktop();
2657 WIN_ReleaseWinArray(pWnd);
2658 return TRUE;
2662 /*******************************************************************
2663 * GetLastActivePopup16 (USER.287)
2665 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2667 return GetLastActivePopup( hwnd );
2670 /*******************************************************************
2671 * GetLastActivePopup (USER32.256)
2673 HWND WINAPI GetLastActivePopup( HWND hwnd )
2675 HWND retval;
2676 WND *wndPtr =WIN_FindWndPtr(hwnd);
2677 if (!wndPtr) return hwnd;
2678 retval = wndPtr->hwndLastActive;
2679 WIN_ReleaseWndPtr(wndPtr);
2680 return retval;
2684 /*******************************************************************
2685 * WIN_BuildWinArray
2687 * Build an array of pointers to the children of a given window.
2688 * The array must be freed with WIN_ReleaseWinArray. Return NULL
2689 * when no windows are found.
2691 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2693 /* Future: this function will lock all windows associated with this array */
2695 WND **list, **ppWnd;
2696 WND *pWnd;
2697 UINT count = 0, skipOwned, skipHidden;
2698 DWORD skipFlags;
2700 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2701 skipOwned = bwaFlags & BWA_SKIPOWNED;
2702 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2703 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2705 /* First count the windows */
2707 if (!wndPtr)
2708 wndPtr = WIN_GetDesktop();
2710 pWnd = WIN_LockWndPtr(wndPtr->child);
2711 while (pWnd)
2713 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2714 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2715 count++;
2716 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2719 if( count )
2721 /* Now build the list of all windows */
2723 if ((list = (WND **)HeapAlloc( GetProcessHeap(), 0, sizeof(WND *) * (count + 1))))
2725 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2727 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2728 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2730 *ppWnd++ = pWnd;
2731 count++;
2734 WIN_ReleaseWndPtr(pWnd);
2735 *ppWnd = NULL;
2737 else count = 0;
2738 } else list = NULL;
2740 if( pTotal ) *pTotal = count;
2741 return list;
2743 /*******************************************************************
2744 * WIN_ReleaseWinArray
2746 void WIN_ReleaseWinArray(WND **wndArray)
2748 /* Future: this function will also unlock all windows associated with wndArray */
2749 HeapFree( GetProcessHeap(), 0, wndArray );
2753 /*******************************************************************
2754 * EnumWindows (USER32.193)
2756 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2758 WND **list, **ppWnd;
2760 /* We have to build a list of all windows first, to avoid */
2761 /* unpleasant side-effects, for instance if the callback */
2762 /* function changes the Z-order of the windows. */
2764 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2766 WIN_ReleaseDesktop();
2767 return FALSE;
2770 /* Now call the callback function for every window */
2772 for (ppWnd = list; *ppWnd; ppWnd++)
2774 LRESULT lpEnumFuncRetval;
2775 int iWndsLocks = 0;
2776 /* Make sure that the window still exists */
2777 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2779 /* To avoid any deadlocks, all the locks on the windows
2780 structures must be suspended before the control
2781 is passed to the application */
2782 iWndsLocks = WIN_SuspendWndsLock();
2783 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2784 WIN_RestoreWndsLock(iWndsLocks);
2786 if (!lpEnumFuncRetval) break;
2788 WIN_ReleaseWinArray(list);
2789 WIN_ReleaseDesktop();
2790 return TRUE;
2794 /**********************************************************************
2795 * EnumTaskWindows16 (USER.225)
2797 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2798 LPARAM lParam )
2800 WND **list, **ppWnd;
2802 /* This function is the same as EnumWindows(), */
2803 /* except for an added check on the window's task. */
2805 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2807 WIN_ReleaseDesktop();
2808 return FALSE;
2811 /* Now call the callback function for every window */
2813 for (ppWnd = list; *ppWnd; ppWnd++)
2815 LRESULT funcRetval;
2816 int iWndsLocks = 0;
2817 /* Make sure that the window still exists */
2818 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2819 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2821 /* To avoid any deadlocks, all the locks on the windows
2822 structures must be suspended before the control
2823 is passed to the application */
2824 iWndsLocks = WIN_SuspendWndsLock();
2825 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2826 WIN_RestoreWndsLock(iWndsLocks);
2828 if (!funcRetval) break;
2830 WIN_ReleaseWinArray(list);
2831 WIN_ReleaseDesktop();
2832 return TRUE;
2836 /**********************************************************************
2837 * EnumThreadWindows (USER32.190)
2839 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2841 TEB *teb = THREAD_IdToTEB(id);
2843 return (BOOL16)EnumTaskWindows16(teb->htask16, (WNDENUMPROC16)func, lParam);
2847 /**********************************************************************
2848 * WIN_EnumChildWindows
2850 * Helper function for EnumChildWindows().
2852 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC func, LPARAM lParam )
2854 WND **childList;
2855 BOOL16 ret = FALSE;
2857 for ( ; *ppWnd; ppWnd++)
2859 int iWndsLocks = 0;
2861 /* Make sure that the window still exists */
2862 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2863 /* Build children list first */
2864 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2866 /* To avoid any deadlocks, all the locks on the windows
2867 structures must be suspended before the control
2868 is passed to the application */
2869 iWndsLocks = WIN_SuspendWndsLock();
2870 ret = func( (*ppWnd)->hwndSelf, lParam );
2871 WIN_RestoreWndsLock(iWndsLocks);
2873 if (childList)
2875 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2876 WIN_ReleaseWinArray(childList);
2878 if (!ret) return FALSE;
2880 return TRUE;
2884 /**********************************************************************
2885 * EnumChildWindows (USER32.178)
2887 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2888 LPARAM lParam )
2890 WND **list, *pParent;
2892 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2893 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2895 WIN_ReleaseWndPtr(pParent);
2896 return FALSE;
2898 WIN_EnumChildWindows( list, func, lParam );
2899 WIN_ReleaseWinArray(list);
2900 WIN_ReleaseWndPtr(pParent);
2901 return TRUE;
2905 /*******************************************************************
2906 * AnyPopup16 (USER.52)
2908 BOOL16 WINAPI AnyPopup16(void)
2910 return AnyPopup();
2914 /*******************************************************************
2915 * AnyPopup (USER32.4)
2917 BOOL WINAPI AnyPopup(void)
2919 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2920 BOOL retvalue;
2922 while (wndPtr)
2924 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2926 retvalue = TRUE;
2927 goto end;
2929 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2931 retvalue = FALSE;
2932 end:
2933 WIN_ReleaseWndPtr(wndPtr);
2934 return retvalue;
2938 /*******************************************************************
2939 * FlashWindow16 (USER.105)
2941 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2943 return FlashWindow( hWnd, bInvert );
2947 /*******************************************************************
2948 * FlashWindow (USER32.202)
2950 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2952 WND *wndPtr = WIN_FindWndPtr(hWnd);
2954 TRACE("%04x\n", hWnd);
2956 if (!wndPtr) return FALSE;
2958 if (wndPtr->dwStyle & WS_MINIMIZE)
2960 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2962 HDC hDC = GetDC(hWnd);
2964 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2965 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2967 ReleaseDC( hWnd, hDC );
2968 wndPtr->flags |= WIN_NCACTIVATED;
2970 else
2972 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2973 RDW_UPDATENOW | RDW_FRAME, 0 );
2974 wndPtr->flags &= ~WIN_NCACTIVATED;
2976 WIN_ReleaseWndPtr(wndPtr);
2977 return TRUE;
2979 else
2981 WPARAM16 wparam;
2982 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2983 else wparam = (hWnd == GetActiveWindow());
2985 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2986 WIN_ReleaseWndPtr(wndPtr);
2987 return wparam;
2992 /*******************************************************************
2993 * SetSysModalWindow16 (USER.188)
2995 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
2997 HWND hWndOldModal = hwndSysModal;
2998 hwndSysModal = hWnd;
2999 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3000 return hWndOldModal;
3004 /*******************************************************************
3005 * GetSysModalWindow16 (USER.52)
3007 HWND16 WINAPI GetSysModalWindow16(void)
3009 return hwndSysModal;
3013 /*******************************************************************
3014 * GetWindowContextHelpId (USER32.303)
3016 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3018 DWORD retval;
3019 WND *wnd = WIN_FindWndPtr( hwnd );
3020 if (!wnd) return 0;
3021 retval = wnd->helpContext;
3022 WIN_ReleaseWndPtr(wnd);
3023 return retval;
3027 /*******************************************************************
3028 * SetWindowContextHelpId (USER32.515)
3030 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3032 WND *wnd = WIN_FindWndPtr( hwnd );
3033 if (!wnd) return FALSE;
3034 wnd->helpContext = id;
3035 WIN_ReleaseWndPtr(wnd);
3036 return TRUE;
3040 /*******************************************************************
3041 * DRAG_QueryUpdate
3043 * recursively find a child that contains spDragInfo->pt point
3044 * and send WM_QUERYDROPOBJECT
3046 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3048 BOOL16 wParam, bResult = 0;
3049 POINT pt;
3050 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
3051 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3052 RECT tempRect;
3054 if( !ptrQueryWnd || !ptrDragInfo )
3055 goto end;
3057 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3059 GetWindowRect(hQueryWnd,&tempRect);
3061 if( !PtInRect(&tempRect,pt) ||
3062 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3063 goto end;
3065 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3067 tempRect = ptrQueryWnd->rectClient;
3068 if(ptrQueryWnd->dwStyle & WS_CHILD)
3069 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3070 (LPPOINT)&tempRect, 2 );
3072 if (PtInRect( &tempRect, pt))
3074 wParam = 0;
3076 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3078 if( ptrWnd->dwStyle & WS_VISIBLE )
3080 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3081 if (PtInRect( &tempRect, pt )) break;
3085 if(ptrWnd)
3087 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3088 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3089 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3090 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3091 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3093 WIN_ReleaseWndPtr(ptrWnd);
3096 if(bResult)
3097 goto end;
3099 else wParam = 1;
3101 else wParam = 1;
3103 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3105 ptrDragInfo->hScope = hQueryWnd;
3107 bResult = ( bNoSend )
3108 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3109 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3110 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3111 if( !bResult )
3112 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3114 end:
3115 WIN_ReleaseWndPtr(ptrQueryWnd);
3116 return bResult;
3120 /*******************************************************************
3121 * DragDetect (USER.465)
3123 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3125 POINT pt32;
3126 CONV_POINT16TO32( &pt, &pt32 );
3127 return DragDetect( hWnd, pt32 );
3130 /*******************************************************************
3131 * DragDetect (USER32.151)
3133 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3135 MSG16 msg;
3136 RECT16 rect;
3138 rect.left = pt.x - wDragWidth;
3139 rect.right = pt.x + wDragWidth;
3141 rect.top = pt.y - wDragHeight;
3142 rect.bottom = pt.y + wDragHeight;
3144 SetCapture(hWnd);
3146 while(1)
3148 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3150 if( msg.message == WM_LBUTTONUP )
3152 ReleaseCapture();
3153 return 0;
3155 if( msg.message == WM_MOUSEMOVE )
3157 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
3159 ReleaseCapture();
3160 return 1;
3164 WaitMessage();
3166 return 0;
3169 /******************************************************************************
3170 * DragObject16 (USER.464)
3172 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3173 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3175 MSG16 msg;
3176 LPDRAGINFO lpDragInfo;
3177 SEGPTR spDragInfo;
3178 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3179 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
3180 WND *wndPtr = WIN_FindWndPtr(hWnd);
3181 HCURSOR16 hCurrentCursor = 0;
3182 HWND16 hCurrentWnd = 0;
3184 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
3185 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
3187 if( !lpDragInfo || !spDragInfo )
3189 WIN_ReleaseWndPtr(wndPtr);
3190 return 0L;
3193 hBummer = LoadCursor16(0, IDC_BUMMER16);
3195 if( !hBummer || !wndPtr )
3197 GlobalFree16(hDragInfo);
3198 WIN_ReleaseWndPtr(wndPtr);
3199 return 0L;
3202 if(hCursor)
3204 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3206 GlobalFree16(hDragInfo);
3207 WIN_ReleaseWndPtr(wndPtr);
3208 return 0L;
3211 if( hDragCursor == hCursor ) hDragCursor = 0;
3212 else hCursor = hDragCursor;
3214 hOldCursor = SetCursor(hDragCursor);
3217 lpDragInfo->hWnd = hWnd;
3218 lpDragInfo->hScope = 0;
3219 lpDragInfo->wFlags = wObj;
3220 lpDragInfo->hList = szList; /* near pointer! */
3221 lpDragInfo->hOfStruct = hOfStruct;
3222 lpDragInfo->l = 0L;
3224 SetCapture(hWnd);
3225 ShowCursor( TRUE );
3229 do{ WaitMessage(); }
3230 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3232 *(lpDragInfo+1) = *lpDragInfo;
3234 lpDragInfo->pt = msg.pt;
3236 /* update DRAGINFO struct */
3237 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3239 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3240 hCurrentCursor = hCursor;
3241 else
3243 hCurrentCursor = hBummer;
3244 lpDragInfo->hScope = 0;
3246 if( hCurrentCursor )
3247 SetCursor(hCurrentCursor);
3249 /* send WM_DRAGLOOP */
3250 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3251 (LPARAM) spDragInfo );
3252 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3253 if( hCurrentWnd != lpDragInfo->hScope )
3255 if( hCurrentWnd )
3256 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3257 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
3258 HIWORD(spDragInfo)) );
3259 hCurrentWnd = lpDragInfo->hScope;
3260 if( hCurrentWnd )
3261 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3263 else
3264 if( hCurrentWnd )
3265 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3267 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3269 ReleaseCapture();
3270 ShowCursor( FALSE );
3272 if( hCursor )
3274 SetCursor( hOldCursor );
3275 if (hDragCursor) DestroyCursor( hDragCursor );
3278 if( hCurrentCursor != hBummer )
3279 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3280 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3281 else
3282 msg.lParam = 0;
3283 GlobalFree16(hDragInfo);
3284 WIN_ReleaseWndPtr(wndPtr);
3286 return (DWORD)(msg.lParam);