Release 990226.
[wine/gsoc-2012-control.git] / windows / win.c
blobe86e0175d5234c2266e834eecfbd2ee2ade7e8f6
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 #include "config.h"
9 #include <stdlib.h>
10 #include <string.h>
11 #include "wine/winbase16.h"
12 #include "options.h"
13 #include "class.h"
14 #include "win.h"
15 #include "heap.h"
16 #include "user.h"
17 #include "dce.h"
18 #include "sysmetrics.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 "shm_main_blk.h"
27 #include "dde_proc.h"
28 #include "clipboard.h"
29 #include "winproc.h"
30 #include "task.h"
31 #include "thread.h"
32 #include "process.h"
33 #include "debug.h"
34 #include "winerror.h"
35 #include "mdi.h"
36 #include "local.h"
37 #include "desktop.h"
39 #ifndef X_DISPLAY_MISSING
40 extern DESKTOP_DRIVER X11DRV_DESKTOP_Driver;
41 extern WND_DRIVER X11DRV_WND_Driver;
42 #else /* X_DISPLAY_MISSING */
43 extern DESKTOP_DRIVER TTYDRV_DESKTOP_Driver;
44 extern WND_DRIVER TTYDRV_WND_Driver;
45 #endif /* X_DISPLAY_MISSING */
47 /* Desktop window */
48 static WND *pWndDesktop = NULL;
50 static HWND hwndSysModal = 0;
52 static WORD wDragWidth = 4;
53 static WORD wDragHeight= 3;
55 /* thread safeness */
56 static CRITICAL_SECTION WIN_CritSection;
57 static int ilockCounter = 0;
59 /***********************************************************************
60 * WIN_LockWnds
62 * Locks access to all WND structures for thread safeness
64 void WIN_LockWnds()
66 EnterCriticalSection(&WIN_CritSection);
67 ilockCounter++;
68 TRACE(win,"All windows hinstances have been locked (lock #%i)\n",ilockCounter);
71 /***********************************************************************
72 * WIN_UnlockWnds
74 * Unlocks access to all WND structures
76 void WIN_UnlockWnds()
79 TRACE(win,"Lock #%i been unlocked\n",ilockCounter+1);
80 ilockCounter--;
81 if(ilockCounter == 0)
83 LeaveCriticalSection(&WIN_CritSection);
84 TRACE(win,"All windows hinstances have been unlocked\n");
86 else if(ilockCounter < 0)
88 ERR(win,"Negative lock reference ==> missing call to WIN_Lock!\n");
91 /***********************************************************************
92 * WIN_SuspendWndsLock
94 * Suspend the lock on WND structures.
95 * Returns the number of locks suspended
97 int WIN_SuspendWndsLock()
99 int isuspendedLocks = ilockCounter;
100 ilockCounter = 0;
101 LeaveCriticalSection(&WIN_CritSection);
102 TRACE(win,"All windows hinstances locks have been suspended\n");
103 return isuspendedLocks;
107 /***********************************************************************
108 * WIN_RestoreWndsLock
110 * Restore the suspended locks on WND structures
112 void WIN_Unlock(int ipreviousLocks)
114 EnterCriticalSection(&WIN_CritSection);
115 ilockCounter = ipreviousLocks;
117 /***********************************************************************
118 * WIN_FindWndPtr
120 * Return a pointer to the WND structure corresponding to a HWND.
122 WND * WIN_FindWndPtr( HWND hwnd )
124 WND * ptr;
126 if (!hwnd || HIWORD(hwnd)) goto error2;
127 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
128 /* Lock all WND structures for thread safeness
129 WIN_LockWnds();
130 and increment destruction monitoring value
131 ptr->irefCount++;
133 if (ptr->dwMagic != WND_MAGIC) goto error;
134 if (ptr->hwndSelf != hwnd)
136 ERR( win, "Can't happen: hwnd %04x self pointer is %04x\n",
137 hwnd, ptr->hwndSelf );
138 goto error;
140 return ptr;
141 error:
142 /* Unlock all WND structures for thread safeness
143 WIN_UnlockWnds();
144 and decrement destruction monitoring value
145 ptr->irefCount--;
147 error2:
148 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
149 return NULL;
152 /***********************************************************************
153 * WIN_ReleaseWndPtr
155 * Release the pointer to the WND structure.
157 void WIN_ReleaseWndPtr(WND *wndPtr)
160 /*Decrement destruction monitoring value
161 wndPtr->irefCount--;
162 Check if it's time to release the memory
163 if(wndPtr->irefCount == 0)
165 Add memory releasing code here
167 unlock all WND structures for thread safeness
168 WIN_UnlockWnds();
174 /***********************************************************************
175 * WIN_DumpWindow
177 * Dump the content of a window structure to stderr.
179 void WIN_DumpWindow( HWND hwnd )
181 WND *ptr;
182 char className[80];
183 int i;
185 if (!(ptr = WIN_FindWndPtr( hwnd )))
187 WARN( win, "%04x is not a window handle\n", hwnd );
188 return;
191 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
192 strcpy( className, "#NULL#" );
194 TRACE( win, "Window %04x (%p):\n", hwnd, ptr );
195 DUMP( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
196 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
197 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
198 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
199 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
200 ptr->next, ptr->child, ptr->parent, ptr->owner,
201 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
202 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
203 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
204 ptr->text ? ptr->text : "",
205 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
206 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
207 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
208 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
210 if (ptr->class->cbWndExtra)
212 DUMP( "extra bytes:" );
213 for (i = 0; i < ptr->class->cbWndExtra; i++)
214 DUMP( " %02x", *((BYTE*)ptr->wExtra+i) );
215 DUMP( "\n" );
217 DUMP( "\n" );
221 /***********************************************************************
222 * WIN_WalkWindows
224 * Walk the windows tree and print each window on stderr.
226 void WIN_WalkWindows( HWND hwnd, int indent )
228 WND *ptr;
229 char className[80];
231 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop;
232 if (!ptr)
234 WARN( win, "Invalid window handle %04x\n", hwnd );
235 return;
238 if (!indent) /* first time around */
239 DUMP( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
240 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
241 " Text");
243 while (ptr)
245 DUMP( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
247 GlobalGetAtomName16(ptr->class->atomName,className,sizeof(className));
249 DUMP( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
250 (DWORD)ptr, ptr->hmemTaskQ, className,
251 (UINT)ptr->dwStyle, (UINT)ptr->winproc,
252 ptr->text?ptr->text:"<null>");
254 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
255 ptr = ptr->next;
259 /***********************************************************************
260 * WIN_UnlinkWindow
262 * Remove a window from the siblings linked list.
264 BOOL WIN_UnlinkWindow( HWND hwnd )
266 WND *wndPtr, **ppWnd;
268 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
269 ppWnd = &wndPtr->parent->child;
270 while (*ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
271 *ppWnd = wndPtr->next;
272 return TRUE;
276 /***********************************************************************
277 * WIN_LinkWindow
279 * Insert a window into the siblings linked list.
280 * The window is inserted after the specified window, which can also
281 * be specified as HWND_TOP or HWND_BOTTOM.
283 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
285 WND *wndPtr, **ppWnd;
287 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
289 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
291 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
292 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
293 while (*ppWnd) ppWnd = &(*ppWnd)->next;
295 else /* Normal case */
297 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
298 if (!afterPtr) return FALSE;
299 ppWnd = &afterPtr->next;
301 wndPtr->next = *ppWnd;
302 *ppWnd = wndPtr;
303 return TRUE;
307 /***********************************************************************
308 * WIN_FindWinToRepaint
310 * Find a window that needs repaint.
312 HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE16 hQueue )
314 HWND hwndRet;
315 WND *pWnd = pWndDesktop;
317 /* Note: the desktop window never gets WM_PAINT messages
318 * The real reason why is because Windows DesktopWndProc
319 * does ValidateRgn inside WM_ERASEBKGND handler.
322 pWnd = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop->child;
324 for ( ; pWnd ; pWnd = pWnd->next )
326 if (!(pWnd->dwStyle & WS_VISIBLE))
328 TRACE(win, "skipping window %04x\n",
329 pWnd->hwndSelf );
330 continue;
332 if ((pWnd->hmemTaskQ == hQueue) &&
333 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))) break;
335 if (pWnd->child )
336 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
337 return hwndRet;
340 if (!pWnd) return 0;
342 hwndRet = pWnd->hwndSelf;
344 /* look among siblings if we got a transparent window */
345 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
346 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
348 pWnd = pWnd->next;
350 if (pWnd) hwndRet = pWnd->hwndSelf;
351 TRACE(win,"found %04x\n",hwndRet);
352 return hwndRet;
356 /***********************************************************************
357 * WIN_DestroyWindow
359 * Destroy storage associated to a window. "Internals" p.358
361 static WND* WIN_DestroyWindow( WND* wndPtr )
363 HWND hwnd = wndPtr->hwndSelf;
364 WND *pWnd;
366 TRACE(win, "%04x\n", wndPtr->hwndSelf );
368 #ifdef CONFIG_IPC
369 if (main_block)
370 DDE_DestroyWindow(wndPtr->hwndSelf);
371 #endif /* CONFIG_IPC */
373 /* free child windows */
375 while ((pWnd = wndPtr->child))
376 wndPtr->child = WIN_DestroyWindow( pWnd );
378 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
380 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
382 WINPOS_CheckInternalPos( wndPtr );
383 if( hwnd == GetCapture()) ReleaseCapture();
385 /* free resources associated with the window */
387 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
388 PROPERTY_RemoveWindowProps( wndPtr );
390 wndPtr->dwMagic = 0; /* Mark it as invalid */
392 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
394 if (wndPtr->hrgnUpdate > 1) DeleteObject( wndPtr->hrgnUpdate );
395 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
398 /* toss stale messages from the queue */
400 if( wndPtr->hmemTaskQ )
402 BOOL bPostQuit = FALSE;
403 WPARAM wQuitParam = 0;
404 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) QUEUE_Lock(wndPtr->hmemTaskQ);
405 QMSG *qmsg;
407 while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
409 if( qmsg->msg.message == WM_QUIT )
411 bPostQuit = TRUE;
412 wQuitParam = qmsg->msg.wParam;
414 QUEUE_RemoveMsg(msgQ, qmsg);
417 QUEUE_Unlock(msgQ);
419 /* repost WM_QUIT to make sure this app exits its message loop */
420 if( bPostQuit ) PostQuitMessage(wQuitParam);
421 wndPtr->hmemTaskQ = 0;
424 if (!(wndPtr->dwStyle & WS_CHILD))
425 if (wndPtr->wIDmenu) DestroyMenu( (HMENU)wndPtr->wIDmenu );
426 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
427 wndPtr->pDriver->pDestroyWindow( wndPtr );
428 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
429 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
430 wndPtr->hwndSelf = 0;
431 wndPtr->class->cWindows--;
432 wndPtr->class = NULL;
433 pWnd = wndPtr->next;
435 wndPtr->pDriver->pFinalize(wndPtr);
436 USER_HEAP_FREE( hwnd );
437 return pWnd;
440 /***********************************************************************
441 * WIN_ResetQueueWindows
443 * Reset the queue of all the children of a given window.
444 * Return TRUE if something was done.
446 BOOL WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
448 BOOL ret = FALSE;
450 if (hNew) /* Set a new queue */
452 for (wnd = wnd->child; (wnd); wnd = wnd->next)
454 if (wnd->hmemTaskQ == hQueue)
456 wnd->hmemTaskQ = hNew;
457 ret = TRUE;
459 if (wnd->child)
460 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
463 else /* Queue is being destroyed */
465 while (wnd->child)
467 WND *tmp = wnd->child;
468 ret = FALSE;
469 while (tmp)
471 if (tmp->hmemTaskQ == hQueue)
473 DestroyWindow( tmp->hwndSelf );
474 ret = TRUE;
475 break;
477 if (tmp->child && WIN_ResetQueueWindows(tmp->child,hQueue,0))
478 ret = TRUE;
479 else
480 tmp = tmp->next;
482 if (!ret) break;
485 return ret;
488 /***********************************************************************
489 * WIN_CreateDesktopWindow
491 * Create the desktop window.
493 BOOL WIN_CreateDesktopWindow(void)
495 CLASS *class;
496 HWND hwndDesktop;
497 DESKTOP *pDesktop;
499 TRACE(win,"Creating desktop window\n");
501 if (!ICONTITLE_Init() ||
502 !WINPOS_CreateInternalPosAtom() ||
503 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
504 return FALSE;
506 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
507 if (!hwndDesktop) return FALSE;
508 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
510 pDesktop = (DESKTOP *) pWndDesktop->wExtra;
511 #ifndef X_DISPLAY_MISSING
512 pDesktop->pDriver = &X11DRV_DESKTOP_Driver;
513 pWndDesktop->pDriver = &X11DRV_WND_Driver;
514 #else /* X_DISPLAY_MISSING */
515 pDesktop->pDriver = &TTYDRV_DESKTOP_Driver;
516 pWndDesktop->pDriver = &TTYDRV_WND_Driver;
517 #endif /* X_DISPLAY_MISSING */
519 pDesktop->pDriver->pInitialize(pDesktop);
520 pWndDesktop->pDriver->pInitialize(pWndDesktop);
522 pWndDesktop->next = NULL;
523 pWndDesktop->child = NULL;
524 pWndDesktop->parent = NULL;
525 pWndDesktop->owner = NULL;
526 pWndDesktop->class = class;
527 pWndDesktop->dwMagic = WND_MAGIC;
528 pWndDesktop->hwndSelf = hwndDesktop;
529 pWndDesktop->hInstance = 0;
530 pWndDesktop->rectWindow.left = 0;
531 pWndDesktop->rectWindow.top = 0;
532 pWndDesktop->rectWindow.right = SYSMETRICS_CXSCREEN;
533 pWndDesktop->rectWindow.bottom = SYSMETRICS_CYSCREEN;
534 pWndDesktop->rectClient = pWndDesktop->rectWindow;
535 pWndDesktop->text = NULL;
536 pWndDesktop->hmemTaskQ = GetFastQueue16();
537 pWndDesktop->hrgnUpdate = 0;
538 pWndDesktop->hwndLastActive = hwndDesktop;
539 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
540 WS_CLIPSIBLINGS;
541 pWndDesktop->dwExStyle = 0;
542 pWndDesktop->dce = NULL;
543 pWndDesktop->pVScroll = NULL;
544 pWndDesktop->pHScroll = NULL;
545 pWndDesktop->pProp = NULL;
546 pWndDesktop->wIDmenu = 0;
547 pWndDesktop->helpContext = 0;
548 pWndDesktop->flags = 0;
549 pWndDesktop->hSysMenu = 0;
550 pWndDesktop->userdata = 0;
551 pWndDesktop->winproc = (WNDPROC16)class->winproc;
553 /* FIXME: How do we know if it should be Unicode or not */
554 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop, class, FALSE))
555 return FALSE;
557 SendMessageA( hwndDesktop, WM_NCCREATE, 0, 0 );
558 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
559 return TRUE;
563 /***********************************************************************
564 * WIN_CreateWindowEx
566 * Implementation of CreateWindowEx().
568 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
569 BOOL win32, BOOL unicode )
571 CLASS *classPtr;
572 WND *wndPtr;
573 HWND16 hwnd, hwndLinkAfter;
574 POINT maxSize, maxPos, minTrack, maxTrack;
575 LRESULT (CALLBACK *localSend32)(HWND, UINT, WPARAM, LPARAM);
577 TRACE(win, "%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
578 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
579 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
580 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
581 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
583 /* Find the parent window */
585 if (cs->hwndParent)
587 /* Make sure parent is valid */
588 if (!IsWindow( cs->hwndParent ))
590 WARN( win, "Bad parent %04x\n", cs->hwndParent );
591 return 0;
593 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
594 WARN( win, "No parent for child window\n" );
595 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
598 /* Find the window class */
599 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
601 char buffer[256];
602 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
603 WARN( win, "Bad class '%s'\n", buffer );
604 return 0;
607 /* Fix the coordinates */
609 if (cs->x == CW_USEDEFAULT)
611 PDB *pdb = PROCESS_Current();
612 if ( !(cs->style & (WS_CHILD | WS_POPUP))
613 && (pdb->env_db->startup_info->dwFlags & STARTF_USEPOSITION) )
615 cs->x = pdb->env_db->startup_info->dwX;
616 cs->y = pdb->env_db->startup_info->dwY;
618 else
620 cs->x = 0;
621 cs->y = 0;
624 if (cs->cx == CW_USEDEFAULT)
626 PDB *pdb = PROCESS_Current();
627 if ( !(cs->style & (WS_CHILD | WS_POPUP))
628 && (pdb->env_db->startup_info->dwFlags & STARTF_USESIZE) )
630 cs->cx = pdb->env_db->startup_info->dwXSize;
631 cs->cy = pdb->env_db->startup_info->dwYSize;
633 else
635 cs->cx = 600; /* FIXME */
636 cs->cy = 400;
640 /* Create the window structure */
642 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
643 - sizeof(wndPtr->wExtra) )))
645 TRACE(win, "out of memory\n" );
646 return 0;
649 /* Fill the window structure */
651 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
652 wndPtr->next = NULL;
653 wndPtr->child = NULL;
655 if ((cs->style & WS_CHILD) && cs->hwndParent)
657 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
658 wndPtr->owner = NULL;
660 else
662 wndPtr->parent = pWndDesktop;
663 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
664 wndPtr->owner = NULL;
665 else
666 wndPtr->owner = WIN_GetTopParentPtr(WIN_FindWndPtr(cs->hwndParent));
669 wndPtr->pDriver = wndPtr->parent->pDriver;
670 wndPtr->pDriver->pInitialize(wndPtr);
672 wndPtr->class = classPtr;
673 wndPtr->winproc = classPtr->winproc;
674 wndPtr->dwMagic = WND_MAGIC;
675 wndPtr->hwndSelf = hwnd;
676 wndPtr->hInstance = cs->hInstance;
677 wndPtr->text = NULL;
678 wndPtr->hmemTaskQ = GetFastQueue16();
679 wndPtr->hrgnUpdate = 0;
680 wndPtr->hwndLastActive = hwnd;
681 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
682 wndPtr->dwExStyle = cs->dwExStyle;
683 wndPtr->wIDmenu = 0;
684 wndPtr->helpContext = 0;
685 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
686 wndPtr->pVScroll = NULL;
687 wndPtr->pHScroll = NULL;
688 wndPtr->pProp = NULL;
689 wndPtr->userdata = 0;
690 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
691 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
693 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
695 /* Call the WH_CBT hook */
697 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
698 ? HWND_BOTTOM : HWND_TOP;
700 if (HOOK_IsHooked( WH_CBT ))
702 CBT_CREATEWNDA cbtc;
703 LRESULT ret;
705 cbtc.lpcs = cs;
706 cbtc.hwndInsertAfter = hwndLinkAfter;
707 ret = unicode ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
708 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
709 if (ret)
711 TRACE(win, "CBT-hook returned 0\n");
712 wndPtr->pDriver->pFinalize(wndPtr);
713 USER_HEAP_FREE( hwnd );
714 return 0;
718 /* Increment class window counter */
720 classPtr->cWindows++;
722 /* Correct the window style */
724 if (!(cs->style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
726 wndPtr->dwStyle |= WS_CAPTION | WS_CLIPSIBLINGS;
727 wndPtr->flags |= WIN_NEED_SIZE;
729 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
731 /* Get class or window DC if needed */
733 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
734 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
735 else wndPtr->dce = NULL;
737 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
739 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
741 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
742 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
743 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
744 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
745 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
748 if(cs->style & WS_CHILD)
750 if(cs->cx < 0) cs->cx = 0;
751 if(cs->cy < 0) cs->cy = 0;
753 else
755 if (cs->cx <= 0) cs->cx = 1;
756 if (cs->cy <= 0) cs->cy = 1;
759 wndPtr->rectWindow.left = cs->x;
760 wndPtr->rectWindow.top = cs->y;
761 wndPtr->rectWindow.right = cs->x + cs->cx;
762 wndPtr->rectWindow.bottom = cs->y + cs->cy;
763 wndPtr->rectClient = wndPtr->rectWindow;
765 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
766 return FALSE;
768 /* Set the window menu */
770 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
772 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
773 else
775 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
776 if (classPtr->menuNameA)
777 cs->hMenu = HIWORD(classPtr->menuNameA) ?
778 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
779 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
780 #else
781 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
782 if (menuName)
784 if (HIWORD(cs->hInstance))
785 cs->hMenu = LoadMenuA(cs->hInstance,PTR_SEG_TO_LIN(menuName));
786 else
787 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
789 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
791 #endif
794 else wndPtr->wIDmenu = (UINT)cs->hMenu;
796 /* Send the WM_CREATE message
797 * Perhaps we shouldn't allow width/height changes as well.
798 * See p327 in "Internals".
801 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
803 localSend32 = unicode ? SendMessageW : SendMessageA;
804 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
806 /* Insert the window in the linked list */
808 WIN_LinkWindow( hwnd, hwndLinkAfter );
810 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
811 NULL, NULL, 0, &wndPtr->rectClient );
812 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
813 maxPos.y - wndPtr->rectWindow.top);
814 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
816 /* Send the size messages */
818 if (!(wndPtr->flags & WIN_NEED_SIZE))
820 /* send it anyway */
821 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
822 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
823 WARN(win,"sending bogus WM_SIZE message 0x%08lx\n",
824 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
825 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
826 SendMessageA( hwnd, WM_SIZE, SIZE_RESTORED,
827 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
828 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
829 SendMessageA( hwnd, WM_MOVE, 0,
830 MAKELONG( wndPtr->rectClient.left,
831 wndPtr->rectClient.top ) );
834 /* Show the window, maximizing or minimizing if needed */
836 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
838 RECT16 newPos;
839 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
840 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
841 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
842 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
843 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
844 : SWP_NOZORDER | SWP_FRAMECHANGED;
845 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
846 newPos.right, newPos.bottom, swFlag );
849 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
851 /* Notify the parent window only */
853 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
854 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
855 if( !IsWindow(hwnd) ) return 0;
858 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
860 /* Call WH_SHELL hook */
862 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
863 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
865 TRACE(win, "created window %04x\n", hwnd);
866 return hwnd;
868 WIN_UnlinkWindow( hwnd );
871 /* Abort window creation */
873 WARN(win, "aborted by WM_xxCREATE!\n");
874 WIN_DestroyWindow( wndPtr );
875 return 0;
879 /***********************************************************************
880 * CreateWindow16 (USER.41)
882 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
883 DWORD style, INT16 x, INT16 y, INT16 width,
884 INT16 height, HWND16 parent, HMENU16 menu,
885 HINSTANCE16 instance, LPVOID data )
887 return CreateWindowEx16( 0, className, windowName, style,
888 x, y, width, height, parent, menu, instance, data );
892 /***********************************************************************
893 * CreateWindowEx16 (USER.452)
895 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
896 LPCSTR windowName, DWORD style, INT16 x,
897 INT16 y, INT16 width, INT16 height,
898 HWND16 parent, HMENU16 menu,
899 HINSTANCE16 instance, LPVOID data )
901 ATOM classAtom;
902 CREATESTRUCTA cs;
904 /* Find the class atom */
906 if (!(classAtom = GlobalFindAtomA( className )))
908 fprintf( stderr, "CreateWindowEx16: bad class name " );
909 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
910 else fprintf( stderr, "'%s'\n", className );
911 return 0;
914 /* Fix the coordinates */
916 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
917 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
918 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
919 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
921 /* Create the window */
923 cs.lpCreateParams = data;
924 cs.hInstance = (HINSTANCE)instance;
925 cs.hMenu = (HMENU)menu;
926 cs.hwndParent = (HWND)parent;
927 cs.style = style;
928 cs.lpszName = windowName;
929 cs.lpszClass = className;
930 cs.dwExStyle = exStyle;
931 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
935 /***********************************************************************
936 * CreateWindowEx32A (USER32.83)
938 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
939 LPCSTR windowName, DWORD style, INT x,
940 INT y, INT width, INT height,
941 HWND parent, HMENU menu,
942 HINSTANCE instance, LPVOID data )
944 ATOM classAtom;
945 CREATESTRUCTA cs;
947 if(exStyle & WS_EX_MDICHILD)
948 return MDI_CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
949 /* Find the class atom */
951 if (!(classAtom = GlobalFindAtomA( className )))
953 fprintf( stderr, "CreateWindowEx32A: bad class name " );
954 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
955 else fprintf( stderr, "'%s'\n", className );
956 return 0;
959 /* Create the window */
961 cs.lpCreateParams = data;
962 cs.hInstance = instance;
963 cs.hMenu = menu;
964 cs.hwndParent = parent;
965 cs.x = x;
966 cs.y = y;
967 cs.cx = width;
968 cs.cy = height;
969 cs.style = style;
970 cs.lpszName = windowName;
971 cs.lpszClass = className;
972 cs.dwExStyle = exStyle;
973 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
977 /***********************************************************************
978 * CreateWindowEx32W (USER32.84)
980 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
981 LPCWSTR windowName, DWORD style, INT x,
982 INT y, INT width, INT height,
983 HWND parent, HMENU menu,
984 HINSTANCE instance, LPVOID data )
986 ATOM classAtom;
987 CREATESTRUCTW cs;
989 if(exStyle & WS_EX_MDICHILD)
990 return MDI_CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
992 /* Find the class atom */
994 if (!(classAtom = GlobalFindAtomW( className )))
996 if (HIWORD(className))
998 LPSTR cn = HEAP_strdupWtoA( GetProcessHeap(), 0, className );
999 WARN( win, "Bad class name '%s'\n",cn);
1000 HeapFree( GetProcessHeap(), 0, cn );
1002 else
1003 WARN( win, "Bad class name %p\n", className );
1004 return 0;
1007 /* Create the window */
1009 cs.lpCreateParams = data;
1010 cs.hInstance = instance;
1011 cs.hMenu = menu;
1012 cs.hwndParent = parent;
1013 cs.x = x;
1014 cs.y = y;
1015 cs.cx = width;
1016 cs.cy = height;
1017 cs.style = style;
1018 cs.lpszName = windowName;
1019 cs.lpszClass = className;
1020 cs.dwExStyle = exStyle;
1021 /* Note: we rely on the fact that CREATESTRUCT32A and */
1022 /* CREATESTRUCT32W have the same layout. */
1023 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, TRUE, TRUE );
1027 /***********************************************************************
1028 * WIN_CheckFocus
1030 static void WIN_CheckFocus( WND* pWnd )
1032 if( GetFocus16() == pWnd->hwndSelf )
1033 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
1036 /***********************************************************************
1037 * WIN_SendDestroyMsg
1039 static void WIN_SendDestroyMsg( WND* pWnd )
1041 WIN_CheckFocus(pWnd);
1043 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1044 CLIPBOARD_GetDriver()->pResetOwner( pWnd, TRUE );
1046 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1048 if( IsWindow(pWnd->hwndSelf) )
1050 WND* pChild = pWnd->child;
1051 while( pChild )
1053 WIN_SendDestroyMsg( pChild );
1054 pChild = pChild->next;
1056 WIN_CheckFocus(pWnd);
1058 else
1059 WARN(win, "\tdestroyed itself while in WM_DESTROY!\n");
1063 /***********************************************************************
1064 * DestroyWindow16 (USER.53)
1066 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1068 return DestroyWindow(hwnd);
1072 /***********************************************************************
1073 * DestroyWindow32 (USER32.135)
1075 BOOL WINAPI DestroyWindow( HWND hwnd )
1077 WND * wndPtr;
1079 TRACE(win, "(%04x)\n", hwnd);
1081 /* Initialization */
1083 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1084 if (wndPtr == pWndDesktop) return FALSE; /* Can't destroy desktop */
1086 /* Call hooks */
1088 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1089 return FALSE;
1091 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1093 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1094 /* FIXME: clean up palette - see "Internals" p.352 */
1097 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1098 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1100 /* Notify the parent window only */
1101 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1102 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1103 if( !IsWindow(hwnd) ) return TRUE;
1106 CLIPBOARD_GetDriver()->pResetOwner( wndPtr, FALSE ); /* before the window is unmapped */
1108 /* Hide the window */
1110 if (wndPtr->dwStyle & WS_VISIBLE)
1112 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1113 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1114 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1115 if (!IsWindow(hwnd)) return TRUE;
1118 /* Recursively destroy owned windows */
1120 if( !(wndPtr->dwStyle & WS_CHILD) )
1122 /* make sure top menu popup doesn't get destroyed */
1123 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1125 for (;;)
1127 WND *siblingPtr = wndPtr->parent->child; /* First sibling */
1128 while (siblingPtr)
1130 if (siblingPtr->owner == wndPtr)
1132 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1133 break;
1134 else
1135 siblingPtr->owner = NULL;
1137 siblingPtr = siblingPtr->next;
1139 if (siblingPtr) DestroyWindow( siblingPtr->hwndSelf );
1140 else break;
1143 if( !Options.managed || EVENT_CheckFocus() )
1144 WINPOS_ActivateOtherWindow(wndPtr);
1146 if( wndPtr->owner &&
1147 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1148 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1151 /* Send destroy messages */
1153 WIN_SendDestroyMsg( wndPtr );
1154 if (!IsWindow(hwnd)) return TRUE;
1156 /* Unlink now so we won't bother with the children later on */
1158 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1160 /* Destroy the window storage */
1162 WIN_DestroyWindow( wndPtr );
1163 return TRUE;
1167 /***********************************************************************
1168 * CloseWindow16 (USER.43)
1170 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1172 return CloseWindow( hwnd );
1176 /***********************************************************************
1177 * CloseWindow32 (USER32.56)
1179 BOOL WINAPI CloseWindow( HWND hwnd )
1181 WND * wndPtr = WIN_FindWndPtr( hwnd );
1182 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD)) return FALSE;
1183 ShowWindow( hwnd, SW_MINIMIZE );
1184 return TRUE;
1188 /***********************************************************************
1189 * OpenIcon16 (USER.44)
1191 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1193 return OpenIcon( hwnd );
1197 /***********************************************************************
1198 * OpenIcon32 (USER32.410)
1200 BOOL WINAPI OpenIcon( HWND hwnd )
1202 if (!IsIconic( hwnd )) return FALSE;
1203 ShowWindow( hwnd, SW_SHOWNORMAL );
1204 return TRUE;
1208 /***********************************************************************
1209 * WIN_FindWindow
1211 * Implementation of FindWindow() and FindWindowEx().
1213 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1214 LPCSTR title )
1216 WND *pWnd;
1217 CLASS *pClass = NULL;
1219 if (child)
1221 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1222 if (parent)
1224 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent)) return 0;
1226 else if (pWnd->parent != pWndDesktop) return 0;
1227 pWnd = pWnd->next;
1229 else
1231 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : pWndDesktop)) return 0;
1232 pWnd = pWnd->child;
1234 if (!pWnd) return 0;
1236 /* For a child window, all siblings will have the same hInstance, */
1237 /* so we can look for the class once and for all. */
1239 if (className && (pWnd->dwStyle & WS_CHILD))
1241 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1242 return 0;
1246 for ( ; pWnd; pWnd = pWnd->next)
1248 if (className && !(pWnd->dwStyle & WS_CHILD))
1250 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance)))
1251 continue; /* Skip this window */
1254 if (pClass && (pWnd->class != pClass))
1255 continue; /* Not the right class */
1257 /* Now check the title */
1259 if (!title) return pWnd->hwndSelf;
1260 if (pWnd->text && !strcmp( pWnd->text, title )) return pWnd->hwndSelf;
1262 return 0;
1267 /***********************************************************************
1268 * FindWindow16 (USER.50)
1270 HWND16 WINAPI FindWindow16( SEGPTR className, LPCSTR title )
1272 return FindWindowEx16( 0, 0, className, title );
1276 /***********************************************************************
1277 * FindWindowEx16 (USER.427)
1279 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child,
1280 SEGPTR className, LPCSTR title )
1282 ATOM atom = 0;
1284 TRACE(win, "%04x %04x '%s' '%s'\n", parent,
1285 child, HIWORD(className)?(char *)PTR_SEG_TO_LIN(className):"",
1286 title ? title : "");
1288 if (className)
1290 /* If the atom doesn't exist, then no class */
1291 /* with this name exists either. */
1292 if (!(atom = GlobalFindAtom16( className ))) return 0;
1294 return WIN_FindWindow( parent, child, atom, title );
1298 /***********************************************************************
1299 * FindWindow32A (USER32.198)
1301 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1303 HWND ret = FindWindowExA( 0, 0, className, title );
1304 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1305 return ret;
1309 /***********************************************************************
1310 * FindWindowEx32A (USER32.199)
1312 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1313 LPCSTR className, LPCSTR title )
1315 ATOM atom = 0;
1317 if (className)
1319 /* If the atom doesn't exist, then no class */
1320 /* with this name exists either. */
1321 if (!(atom = GlobalFindAtomA( className )))
1323 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1324 return 0;
1327 return WIN_FindWindow( parent, child, atom, title );
1331 /***********************************************************************
1332 * FindWindowEx32W (USER32.200)
1334 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1335 LPCWSTR className, LPCWSTR title )
1337 ATOM atom = 0;
1338 char *buffer;
1339 HWND hwnd;
1341 if (className)
1343 /* If the atom doesn't exist, then no class */
1344 /* with this name exists either. */
1345 if (!(atom = GlobalFindAtomW( className )))
1347 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1348 return 0;
1351 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1352 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1353 HeapFree( GetProcessHeap(), 0, buffer );
1354 return hwnd;
1358 /***********************************************************************
1359 * FindWindow32W (USER32.201)
1361 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1363 return FindWindowExW( 0, 0, className, title );
1367 /**********************************************************************
1368 * WIN_GetDesktop
1370 WND *WIN_GetDesktop(void)
1372 return pWndDesktop;
1376 /**********************************************************************
1377 * GetDesktopWindow16 (USER.286)
1379 HWND16 WINAPI GetDesktopWindow16(void)
1381 return (HWND16)pWndDesktop->hwndSelf;
1385 /**********************************************************************
1386 * GetDesktopWindow32 (USER32.232)
1388 HWND WINAPI GetDesktopWindow(void)
1390 return pWndDesktop->hwndSelf;
1394 /**********************************************************************
1395 * GetDesktopHwnd (USER.278)
1397 * Exactly the same thing as GetDesktopWindow(), but not documented.
1398 * Don't ask me why...
1400 HWND16 WINAPI GetDesktopHwnd16(void)
1402 return (HWND16)pWndDesktop->hwndSelf;
1406 /*******************************************************************
1407 * EnableWindow16 (USER.34)
1409 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1411 return EnableWindow( hwnd, enable );
1415 /*******************************************************************
1416 * EnableWindow32 (USER32.172)
1418 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1420 WND *wndPtr;
1422 TRACE(win,"EnableWindow32: ( %x, %d )\n", hwnd, enable);
1424 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1425 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1427 /* Enable window */
1428 wndPtr->dwStyle &= ~WS_DISABLED;
1429 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1430 return TRUE;
1432 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1434 /* Disable window */
1435 wndPtr->dwStyle |= WS_DISABLED;
1436 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus() ))
1438 SetFocus( 0 ); /* A disabled window can't have the focus */
1440 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
1442 ReleaseCapture(); /* A disabled window can't capture the mouse */
1444 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1445 return FALSE;
1447 return ((wndPtr->dwStyle & WS_DISABLED) != 0);
1451 /***********************************************************************
1452 * IsWindowEnabled16 (USER.35)
1454 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1456 return IsWindowEnabled(hWnd);
1460 /***********************************************************************
1461 * IsWindowEnabled32 (USER32.349)
1463 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1465 WND * wndPtr;
1467 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1468 return !(wndPtr->dwStyle & WS_DISABLED);
1472 /***********************************************************************
1473 * IsWindowUnicode (USER32.350)
1475 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1477 WND * wndPtr;
1479 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1480 return (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1484 /**********************************************************************
1485 * GetWindowWord16 (USER.133)
1487 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1489 return GetWindowWord( hwnd, offset );
1493 /**********************************************************************
1494 * GetWindowWord32 (USER32.314)
1496 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1498 WND * wndPtr = WIN_FindWndPtr( hwnd );
1499 if (!wndPtr) return 0;
1500 if (offset >= 0)
1502 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1504 WARN( win, "Invalid offset %d\n", offset );
1505 return 0;
1507 return *(WORD *)(((char *)wndPtr->wExtra) + offset);
1509 switch(offset)
1511 case GWW_ID:
1512 if (HIWORD(wndPtr->wIDmenu))
1513 WARN( win,"GWW_ID: discards high bits of 0x%08x!\n",
1514 wndPtr->wIDmenu);
1515 return (WORD)wndPtr->wIDmenu;
1516 case GWW_HWNDPARENT:
1517 return GetParent( hwnd );
1518 case GWW_HINSTANCE:
1519 if (HIWORD(wndPtr->hInstance))
1520 WARN(win,"GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1521 wndPtr->hInstance);
1522 return (WORD)wndPtr->hInstance;
1523 default:
1524 WARN( win, "Invalid offset %d\n", offset );
1525 return 0;
1530 /**********************************************************************
1531 * WIN_GetWindowInstance
1533 HINSTANCE WIN_GetWindowInstance( HWND hwnd )
1535 WND * wndPtr = WIN_FindWndPtr( hwnd );
1536 if (!wndPtr) return (HINSTANCE)0;
1537 return wndPtr->hInstance;
1541 /**********************************************************************
1542 * SetWindowWord16 (USER.134)
1544 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1546 return SetWindowWord( hwnd, offset, newval );
1550 /**********************************************************************
1551 * SetWindowWord32 (USER32.524)
1553 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1555 WORD *ptr, retval;
1556 WND * wndPtr = WIN_FindWndPtr( hwnd );
1557 if (!wndPtr) return 0;
1558 if (offset >= 0)
1560 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1562 WARN( win, "Invalid offset %d\n", offset );
1563 return 0;
1565 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1567 else switch(offset)
1569 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1570 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1571 case GWW_HWNDPARENT: return SetParent( hwnd, newval );
1572 default:
1573 WARN( win, "Invalid offset %d\n", offset );
1574 return 0;
1576 retval = *ptr;
1577 *ptr = newval;
1578 return retval;
1582 /**********************************************************************
1583 * WIN_GetWindowLong
1585 * Helper function for GetWindowLong().
1587 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1589 LONG retval;
1590 WND * wndPtr = WIN_FindWndPtr( hwnd );
1591 if (!wndPtr) return 0;
1592 if (offset >= 0)
1594 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1596 WARN( win, "Invalid offset %d\n", offset );
1597 return 0;
1599 retval = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1600 /* Special case for dialog window procedure */
1601 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1602 return (LONG)WINPROC_GetProc( (HWINDOWPROC)retval, type );
1603 return retval;
1605 switch(offset)
1607 case GWL_USERDATA: return wndPtr->userdata;
1608 case GWL_STYLE: return wndPtr->dwStyle;
1609 case GWL_EXSTYLE: return wndPtr->dwExStyle;
1610 case GWL_ID: return (LONG)wndPtr->wIDmenu;
1611 case GWL_WNDPROC: return (LONG)WINPROC_GetProc( wndPtr->winproc,
1612 type );
1613 case GWL_HWNDPARENT: return GetParent(hwnd);
1614 case GWL_HINSTANCE: return wndPtr->hInstance;
1615 default:
1616 WARN( win, "Unknown offset %d\n", offset );
1618 return 0;
1622 /**********************************************************************
1623 * WIN_SetWindowLong
1625 * Helper function for SetWindowLong().
1627 * 0 is the failure code. However, in the case of failure SetLastError
1628 * must be set to distinguish between a 0 return value and a failure.
1630 * FIXME: The error values for SetLastError may not be right. Can
1631 * someone check with the real thing?
1633 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1634 WINDOWPROCTYPE type )
1636 LONG *ptr, retval;
1637 WND * wndPtr = WIN_FindWndPtr( hwnd );
1638 STYLESTRUCT style;
1640 TRACE(win,"%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1642 if (!wndPtr)
1644 /* Is this the right error? */
1645 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1646 return 0;
1649 if (offset >= 0)
1651 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1653 WARN( win, "Invalid offset %d\n", offset );
1655 /* Is this the right error? */
1656 SetLastError( ERROR_OUTOFMEMORY );
1658 return 0;
1660 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1661 /* Special case for dialog window procedure */
1662 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1664 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1665 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1666 type, WIN_PROC_WINDOW );
1667 return retval;
1670 else switch(offset)
1672 case GWL_ID:
1673 ptr = (DWORD*)&wndPtr->wIDmenu;
1674 break;
1675 case GWL_HINSTANCE:
1676 return SetWindowWord( hwnd, offset, newval );
1677 case GWL_WNDPROC:
1678 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1679 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1680 type, WIN_PROC_WINDOW );
1681 return retval;
1682 case GWL_STYLE:
1683 style.styleOld = wndPtr->dwStyle;
1684 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
1685 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
1687 if (wndPtr->flags & WIN_ISWIN32)
1688 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1689 wndPtr->dwStyle = style.styleNew;
1690 if (wndPtr->flags & WIN_ISWIN32)
1691 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1692 return style.styleOld;
1694 case GWL_USERDATA:
1695 ptr = &wndPtr->userdata;
1696 break;
1697 case GWL_EXSTYLE:
1698 style.styleOld = wndPtr->dwExStyle;
1699 style.styleNew = newval;
1700 if (wndPtr->flags & WIN_ISWIN32)
1701 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1702 wndPtr->dwExStyle = newval;
1703 if (wndPtr->flags & WIN_ISWIN32)
1704 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1705 return style.styleOld;
1707 default:
1708 WARN( win, "Invalid offset %d\n", offset );
1710 /* Don't think this is right error but it should do */
1711 SetLastError( ERROR_OUTOFMEMORY );
1713 return 0;
1715 retval = *ptr;
1716 *ptr = newval;
1717 return retval;
1721 /**********************************************************************
1722 * GetWindowLong16 (USER.135)
1724 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1726 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
1730 /**********************************************************************
1731 * GetWindowLong32A (USER32.305)
1733 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
1735 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1739 /**********************************************************************
1740 * GetWindowLong32W (USER32.306)
1742 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
1744 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1748 /**********************************************************************
1749 * SetWindowLong16 (USER.136)
1751 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1753 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1757 /**********************************************************************
1758 * SetWindowLong32A (USER32.517)
1760 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
1762 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1766 /**********************************************************************
1767 * SetWindowLong32W (USER32.518) Set window attribute
1769 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
1770 * value in a window's extra memory.
1772 * The _hwnd_ parameter specifies the window. is the handle to a
1773 * window that has extra memory. The _newval_ parameter contains the
1774 * new attribute or extra memory value. If positive, the _offset_
1775 * parameter is the byte-addressed location in the window's extra
1776 * memory to set. If negative, _offset_ specifies the window
1777 * attribute to set, and should be one of the following values:
1779 * GWL_EXSTYLE The window's extended window style
1781 * GWL_STYLE The window's window style.
1783 * GWL_WNDPROC Pointer to the window's window procedure.
1785 * GWL_HINSTANCE The window's pplication instance handle.
1787 * GWL_ID The window's identifier.
1789 * GWL_USERDATA The window's user-specified data.
1791 * If the window is a dialog box, the _offset_ parameter can be one of
1792 * the following values:
1794 * DWL_DLGPROC The address of the window's dialog box procedure.
1796 * DWL_MSGRESULT The return value of a message
1797 * that the dialog box procedure processed.
1799 * DWL_USER Application specific information.
1801 * RETURNS
1803 * If successful, returns the previous value located at _offset_. Otherwise,
1804 * returns 0.
1806 * NOTES
1808 * Extra memory for a window class is specified by a nonzero cbWndExtra
1809 * parameter of the WNDCLASS structure passed to RegisterClass() at the
1810 * time of class creation.
1812 * Using GWL_WNDPROC to set a new window procedure effectively creates
1813 * a window subclass. Use CallWindowProc() in the new windows procedure
1814 * to pass messages to the superclass's window procedure.
1816 * The user data is reserved for use by the application which created
1817 * the window.
1819 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
1820 * instead, call the EnableWindow() function to change the window's
1821 * disabled state.
1823 * Do not use GWL_HWNDPARENT to reset the window's parent, use
1824 * SetParent() instead.
1826 * Win95:
1827 * When offset is GWL_STYLE and the calling app's ver is 4.0,
1828 * it sends WM_STYLECHANGING before changing the settings
1829 * and WM_STYLECHANGED afterwards.
1830 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
1832 * BUGS
1834 * GWL_STYLE does not dispatch WM_STYLE... messages.
1836 * CONFORMANCE
1838 * ECMA-234, Win32
1841 LONG WINAPI SetWindowLongW(
1842 HWND hwnd, /* window to alter */
1843 INT offset, /* offset, in bytes, of location to alter */
1844 LONG newval /* new value of location */
1846 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1850 /*******************************************************************
1851 * GetWindowText16 (USER.36)
1853 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
1855 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1859 /*******************************************************************
1860 * GetWindowText32A (USER32.309)
1862 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
1864 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
1865 (LPARAM)lpString );
1868 /*******************************************************************
1869 * InternalGetWindowText (USER32.326)
1871 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
1873 FIXME(win,"(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
1874 return GetWindowTextW(hwnd,lpString,nMaxCount);
1878 /*******************************************************************
1879 * GetWindowText32W (USER32.312)
1881 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
1883 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
1884 (LPARAM)lpString );
1888 /*******************************************************************
1889 * SetWindowText16 (USER.37)
1891 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
1893 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1897 /*******************************************************************
1898 * SetWindowText32A (USER32.521)
1900 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
1902 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1906 /*******************************************************************
1907 * SetWindowText32W (USER32.523)
1909 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
1911 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1915 /*******************************************************************
1916 * GetWindowTextLength16 (USER.38)
1918 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
1920 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1924 /*******************************************************************
1925 * GetWindowTextLength32A (USER32.310)
1927 INT WINAPI GetWindowTextLengthA( HWND hwnd )
1929 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1932 /*******************************************************************
1933 * GetWindowTextLength32W (USER32.311)
1935 INT WINAPI GetWindowTextLengthW( HWND hwnd )
1937 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1941 /*******************************************************************
1942 * IsWindow16 (USER.47)
1944 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
1946 return IsWindow( hwnd );
1949 void WINAPI WIN16_IsWindow16( CONTEXT *context )
1951 WORD *stack = PTR_SEG_OFF_TO_LIN(SS_reg(context), SP_reg(context));
1952 HWND16 hwnd = (HWND16)stack[2];
1954 AX_reg(context) = IsWindow( hwnd );
1955 ES_reg(context) = USER_HeapSel;
1959 /*******************************************************************
1960 * IsWindow32 (USER32.348)
1962 BOOL WINAPI IsWindow( HWND hwnd )
1964 WND * wndPtr = WIN_FindWndPtr( hwnd );
1965 return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
1969 /*****************************************************************
1970 * GetParent16 (USER.46)
1972 HWND16 WINAPI GetParent16( HWND16 hwnd )
1974 return (HWND16)GetParent( hwnd );
1978 /*****************************************************************
1979 * GetParent32 (USER32.278)
1981 HWND WINAPI GetParent( HWND hwnd )
1983 WND *wndPtr = WIN_FindWndPtr(hwnd);
1984 if ((!wndPtr) || (!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD)))) return 0;
1985 wndPtr = (wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner;
1986 return wndPtr ? wndPtr->hwndSelf : 0;
1989 /*****************************************************************
1990 * WIN_GetTopParent
1992 * Get the top-level parent for a child window.
1994 WND* WIN_GetTopParentPtr( WND* pWnd )
1996 while( pWnd && (pWnd->dwStyle & WS_CHILD)) pWnd = pWnd->parent;
1997 return pWnd;
2000 /*****************************************************************
2001 * WIN_GetTopParent
2003 * Get the top-level parent for a child window.
2005 HWND WIN_GetTopParent( HWND hwnd )
2007 WND *wndPtr = WIN_GetTopParentPtr ( WIN_FindWndPtr( hwnd ) );
2008 return wndPtr ? wndPtr->hwndSelf : 0;
2012 /*****************************************************************
2013 * SetParent16 (USER.233)
2015 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2017 return SetParent( hwndChild, hwndNewParent );
2021 /*****************************************************************
2022 * SetParent32 (USER32.495)
2024 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2026 WND *wndPtr = WIN_FindWndPtr( hwndChild );
2027 DWORD dwStyle = (wndPtr)?(wndPtr->dwStyle):0;
2028 WND *pWndNewParent =
2029 (hwndNewParent) ? WIN_FindWndPtr( hwndNewParent ) : pWndDesktop;
2030 WND *pWndOldParent;
2032 /* Windows hides the window first, then shows it again
2033 * including the WM_SHOWWINDOW messages and all */
2034 if (dwStyle & WS_VISIBLE)
2035 ShowWindow( hwndChild, SW_HIDE );
2037 pWndOldParent = (wndPtr)?(*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent):NULL;
2039 /* SetParent32 additionally needs to make hwndChild the topmost window
2040 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2041 WM_WINDOWPOSCHANGED notification messages.
2043 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2044 SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2045 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2046 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2048 return pWndOldParent?pWndOldParent->hwndSelf:0;
2051 /*******************************************************************
2052 * IsChild16 (USER.48)
2054 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2056 return IsChild(parent,child);
2060 /*******************************************************************
2061 * IsChild32 (USER32.339)
2063 BOOL WINAPI IsChild( HWND parent, HWND child )
2065 WND * wndPtr = WIN_FindWndPtr( child );
2066 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2068 wndPtr = wndPtr->parent;
2069 if (wndPtr->hwndSelf == parent) return TRUE;
2071 return FALSE;
2075 /***********************************************************************
2076 * IsWindowVisible16 (USER.49)
2078 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2080 return IsWindowVisible(hwnd);
2084 /***********************************************************************
2085 * IsWindowVisible32 (USER32.351)
2087 BOOL WINAPI IsWindowVisible( HWND hwnd )
2089 WND *wndPtr = WIN_FindWndPtr( hwnd );
2090 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2092 if (!(wndPtr->dwStyle & WS_VISIBLE)) return FALSE;
2093 wndPtr = wndPtr->parent;
2095 return (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2099 /***********************************************************************
2100 * WIN_IsWindowDrawable
2102 * hwnd is drawable when it is visible, all parents are not
2103 * minimized, and it is itself not minimized unless we are
2104 * trying to draw its default class icon.
2106 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2108 if( (wnd->dwStyle & WS_MINIMIZE &&
2109 icon && wnd->class->hIcon) ||
2110 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2111 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2112 if( wnd->dwStyle & WS_MINIMIZE ||
2113 !(wnd->dwStyle & WS_VISIBLE) ) break;
2114 return (wnd == NULL);
2118 /*******************************************************************
2119 * GetTopWindow16 (USER.229)
2121 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2123 return GetTopWindow(hwnd);
2127 /*******************************************************************
2128 * GetTopWindow32 (USER.229)
2130 HWND WINAPI GetTopWindow( HWND hwnd )
2132 WND * wndPtr = WIN_FindWndPtr( hwnd );
2133 if (wndPtr && wndPtr->child) return wndPtr->child->hwndSelf;
2134 else return 0;
2138 /*******************************************************************
2139 * GetWindow16 (USER.262)
2141 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2143 return GetWindow( hwnd,rel );
2147 /*******************************************************************
2148 * GetWindow32 (USER32.302)
2150 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2152 WND * wndPtr = WIN_FindWndPtr( hwnd );
2153 if (!wndPtr) return 0;
2154 switch(rel)
2156 case GW_HWNDFIRST:
2157 if (wndPtr->parent) return wndPtr->parent->child->hwndSelf;
2158 else return 0;
2160 case GW_HWNDLAST:
2161 if (!wndPtr->parent) return 0; /* Desktop window */
2162 while (wndPtr->next) wndPtr = wndPtr->next;
2163 return wndPtr->hwndSelf;
2165 case GW_HWNDNEXT:
2166 if (!wndPtr->next) return 0;
2167 return wndPtr->next->hwndSelf;
2169 case GW_HWNDPREV:
2170 if (!wndPtr->parent) return 0; /* Desktop window */
2171 wndPtr = wndPtr->parent->child; /* First sibling */
2172 if (wndPtr->hwndSelf == hwnd) return 0; /* First in list */
2173 while (wndPtr->next)
2175 if (wndPtr->next->hwndSelf == hwnd) return wndPtr->hwndSelf;
2176 wndPtr = wndPtr->next;
2178 return 0;
2180 case GW_OWNER:
2181 return wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2183 case GW_CHILD:
2184 return wndPtr->child ? wndPtr->child->hwndSelf : 0;
2186 return 0;
2190 /*******************************************************************
2191 * GetNextWindow16 (USER.230)
2193 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2195 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2196 return GetWindow16( hwnd, flag );
2199 /*******************************************************************
2200 * ShowOwnedPopups16 (USER.265)
2202 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2204 ShowOwnedPopups( owner, fShow );
2208 /*******************************************************************
2209 * ShowOwnedPopups32 (USER32.531)
2211 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2213 WND *pWnd = pWndDesktop->child;
2214 while (pWnd)
2216 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
2217 (pWnd->dwStyle & WS_POPUP))
2218 ShowWindow( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
2219 pWnd = pWnd->next;
2221 return TRUE;
2225 /*******************************************************************
2226 * GetLastActivePopup16 (USER.287)
2228 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2230 return GetLastActivePopup( hwnd );
2233 /*******************************************************************
2234 * GetLastActivePopup32 (USER32.256)
2236 HWND WINAPI GetLastActivePopup( HWND hwnd )
2238 WND *wndPtr;
2239 wndPtr = WIN_FindWndPtr(hwnd);
2240 if (wndPtr == NULL) return hwnd;
2241 return wndPtr->hwndLastActive;
2245 /*******************************************************************
2246 * WIN_BuildWinArray
2248 * Build an array of pointers to the children of a given window.
2249 * The array must be freed with HeapFree(SystemHeap). Return NULL
2250 * when no windows are found.
2252 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2254 WND **list, **ppWnd;
2255 WND *pWnd;
2256 UINT count, skipOwned, skipHidden;
2257 DWORD skipFlags;
2259 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2260 skipOwned = bwaFlags & BWA_SKIPOWNED;
2261 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2262 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2264 /* First count the windows */
2266 if (!wndPtr) wndPtr = pWndDesktop;
2267 for (pWnd = wndPtr->child, count = 0; pWnd; pWnd = pWnd->next)
2269 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
2270 if( !skipHidden || pWnd->dwStyle & WS_VISIBLE ) count++;
2273 if( count )
2275 /* Now build the list of all windows */
2277 if ((list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * (count + 1))))
2279 for (pWnd = wndPtr->child, ppWnd = list, count = 0; pWnd; pWnd = pWnd->next)
2281 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
2282 if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2284 *ppWnd++ = pWnd;
2285 count++;
2288 *ppWnd = NULL;
2290 else count = 0;
2291 } else list = NULL;
2293 if( pTotal ) *pTotal = count;
2294 return list;
2298 /*******************************************************************
2299 * EnumWindows16 (USER.54)
2301 BOOL16 WINAPI EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
2303 WND **list, **ppWnd;
2305 /* We have to build a list of all windows first, to avoid */
2306 /* unpleasant side-effects, for instance if the callback */
2307 /* function changes the Z-order of the windows. */
2309 if (!(list = WIN_BuildWinArray( pWndDesktop, 0, NULL ))) return FALSE;
2311 /* Now call the callback function for every window */
2313 for (ppWnd = list; *ppWnd; ppWnd++)
2315 /* Make sure that the window still exists */
2316 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2317 if (!lpEnumFunc( (*ppWnd)->hwndSelf, lParam )) break;
2319 HeapFree( SystemHeap, 0, list );
2320 return TRUE;
2324 /*******************************************************************
2325 * EnumWindows32 (USER32.193)
2327 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2329 return (BOOL)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2333 /**********************************************************************
2334 * EnumTaskWindows16 (USER.225)
2336 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2337 LPARAM lParam )
2339 WND **list, **ppWnd;
2341 /* This function is the same as EnumWindows(), */
2342 /* except for an added check on the window's task. */
2344 if (!(list = WIN_BuildWinArray( pWndDesktop, 0, NULL ))) return FALSE;
2346 /* Now call the callback function for every window */
2348 for (ppWnd = list; *ppWnd; ppWnd++)
2350 /* Make sure that the window still exists */
2351 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2352 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2353 if (!func( (*ppWnd)->hwndSelf, lParam )) break;
2355 HeapFree( SystemHeap, 0, list );
2356 return TRUE;
2360 /**********************************************************************
2361 * EnumThreadWindows (USER32.190)
2363 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2365 THDB *tdb = THREAD_ID_TO_THDB(id);
2367 return (BOOL16)EnumTaskWindows16(tdb->teb.htask16, (WNDENUMPROC16)func, lParam);
2371 /**********************************************************************
2372 * WIN_EnumChildWindows
2374 * Helper function for EnumChildWindows().
2376 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2377 LPARAM lParam )
2379 WND **childList;
2380 BOOL16 ret = FALSE;
2382 for ( ; *ppWnd; ppWnd++)
2384 /* Make sure that the window still exists */
2385 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2386 /* Build children list first */
2387 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2388 ret = func( (*ppWnd)->hwndSelf, lParam );
2389 if (childList)
2391 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2392 HeapFree( SystemHeap, 0, childList );
2394 if (!ret) return FALSE;
2396 return TRUE;
2400 /**********************************************************************
2401 * EnumChildWindows16 (USER.55)
2403 BOOL16 WINAPI EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
2404 LPARAM lParam )
2406 WND **list, *pParent;
2408 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2409 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL ))) return FALSE;
2410 WIN_EnumChildWindows( list, func, lParam );
2411 HeapFree( SystemHeap, 0, list );
2412 return TRUE;
2416 /**********************************************************************
2417 * EnumChildWindows32 (USER32.178)
2419 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2420 LPARAM lParam )
2422 return (BOOL)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2423 lParam );
2427 /*******************************************************************
2428 * AnyPopup16 (USER.52)
2430 BOOL16 WINAPI AnyPopup16(void)
2432 return AnyPopup();
2436 /*******************************************************************
2437 * AnyPopup32 (USER32.4)
2439 BOOL WINAPI AnyPopup(void)
2441 WND *wndPtr;
2442 for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next)
2443 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE)) return TRUE;
2444 return FALSE;
2448 /*******************************************************************
2449 * FlashWindow16 (USER.105)
2451 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2453 return FlashWindow( hWnd, bInvert );
2457 /*******************************************************************
2458 * FlashWindow32 (USER32.202)
2460 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2462 WND *wndPtr = WIN_FindWndPtr(hWnd);
2464 TRACE(win,"%04x\n", hWnd);
2466 if (!wndPtr) return FALSE;
2468 if (wndPtr->dwStyle & WS_MINIMIZE)
2470 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2472 HDC hDC = GetDC(hWnd);
2474 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2475 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2477 ReleaseDC( hWnd, hDC );
2478 wndPtr->flags |= WIN_NCACTIVATED;
2480 else
2482 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2483 RDW_UPDATENOW | RDW_FRAME, 0 );
2484 wndPtr->flags &= ~WIN_NCACTIVATED;
2486 return TRUE;
2488 else
2490 WPARAM16 wparam;
2491 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2492 else wparam = (hWnd == GetActiveWindow());
2494 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2495 return wparam;
2500 /*******************************************************************
2501 * SetSysModalWindow16 (USER.188)
2503 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
2505 HWND hWndOldModal = hwndSysModal;
2506 hwndSysModal = hWnd;
2507 FIXME(win, "EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2508 return hWndOldModal;
2512 /*******************************************************************
2513 * GetSysModalWindow16 (USER.52)
2515 HWND16 WINAPI GetSysModalWindow16(void)
2517 return hwndSysModal;
2521 /*******************************************************************
2522 * GetWindowContextHelpId (USER32.303)
2524 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2526 WND *wnd = WIN_FindWndPtr( hwnd );
2527 if (!wnd) return 0;
2528 return wnd->helpContext;
2532 /*******************************************************************
2533 * SetWindowContextHelpId (USER32.515)
2535 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
2537 WND *wnd = WIN_FindWndPtr( hwnd );
2538 if (!wnd) return FALSE;
2539 wnd->helpContext = id;
2540 return TRUE;
2544 /*******************************************************************
2545 * DRAG_QueryUpdate
2547 * recursively find a child that contains spDragInfo->pt point
2548 * and send WM_QUERYDROPOBJECT
2550 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
2552 BOOL16 wParam,bResult = 0;
2553 POINT pt;
2554 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
2555 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
2556 RECT tempRect;
2558 if( !ptrQueryWnd || !ptrDragInfo ) return 0;
2560 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
2562 GetWindowRect(hQueryWnd,&tempRect);
2564 if( !PtInRect(&tempRect,pt) ||
2565 (ptrQueryWnd->dwStyle & WS_DISABLED) )
2566 return 0;
2568 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
2570 tempRect = ptrQueryWnd->rectClient;
2571 if(ptrQueryWnd->dwStyle & WS_CHILD)
2572 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
2573 (LPPOINT)&tempRect, 2 );
2575 if (PtInRect( &tempRect, pt))
2577 wParam = 0;
2579 for (ptrWnd = ptrQueryWnd->child; ptrWnd ;ptrWnd = ptrWnd->next)
2580 if( ptrWnd->dwStyle & WS_VISIBLE )
2582 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
2583 if (PtInRect( &tempRect, pt )) break;
2586 if(ptrWnd)
2588 TRACE(msg,"hwnd = %04x, %d %d - %d %d\n",
2589 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
2590 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
2591 if( !(ptrWnd->dwStyle & WS_DISABLED) )
2592 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
2595 if(bResult) return bResult;
2597 else wParam = 1;
2599 else wParam = 1;
2601 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
2603 ptrDragInfo->hScope = hQueryWnd;
2605 bResult = ( bNoSend )
2606 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
2607 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
2608 (WPARAM16)wParam ,(LPARAM) spDragInfo );
2609 if( !bResult )
2610 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
2612 return bResult;
2616 /*******************************************************************
2617 * DragDetect (USER.465)
2619 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
2621 POINT pt32;
2622 CONV_POINT16TO32( &pt, &pt32 );
2623 return DragDetect( hWnd, pt32 );
2626 /*******************************************************************
2627 * DragDetect32 (USER32.151)
2629 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
2631 MSG16 msg;
2632 RECT16 rect;
2634 rect.left = pt.x - wDragWidth;
2635 rect.right = pt.x + wDragWidth;
2637 rect.top = pt.y - wDragHeight;
2638 rect.bottom = pt.y + wDragHeight;
2640 SetCapture(hWnd);
2642 while(1)
2644 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
2646 if( msg.message == WM_LBUTTONUP )
2648 ReleaseCapture();
2649 return 0;
2651 if( msg.message == WM_MOUSEMOVE )
2653 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
2655 ReleaseCapture();
2656 return 1;
2660 WaitMessage();
2662 return 0;
2665 /******************************************************************************
2666 * DragObject16 (USER.464)
2668 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
2669 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
2671 MSG16 msg;
2672 LPDRAGINFO lpDragInfo;
2673 SEGPTR spDragInfo;
2674 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
2675 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
2676 WND *wndPtr = WIN_FindWndPtr(hWnd);
2677 HCURSOR16 hCurrentCursor = 0;
2678 HWND16 hCurrentWnd = 0;
2680 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
2681 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
2683 if( !lpDragInfo || !spDragInfo ) return 0L;
2685 hBummer = LoadCursor16(0, IDC_BUMMER16);
2687 if( !hBummer || !wndPtr )
2689 GlobalFree16(hDragInfo);
2690 return 0L;
2693 if(hCursor)
2695 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
2697 GlobalFree16(hDragInfo);
2698 return 0L;
2701 if( hDragCursor == hCursor ) hDragCursor = 0;
2702 else hCursor = hDragCursor;
2704 hOldCursor = SetCursor(hDragCursor);
2707 lpDragInfo->hWnd = hWnd;
2708 lpDragInfo->hScope = 0;
2709 lpDragInfo->wFlags = wObj;
2710 lpDragInfo->hList = szList; /* near pointer! */
2711 lpDragInfo->hOfStruct = hOfStruct;
2712 lpDragInfo->l = 0L;
2714 SetCapture(hWnd);
2715 ShowCursor( TRUE );
2719 do{ WaitMessage(); }
2720 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
2722 *(lpDragInfo+1) = *lpDragInfo;
2724 lpDragInfo->pt = msg.pt;
2726 /* update DRAGINFO struct */
2727 TRACE(msg,"lpDI->hScope = %04x\n",lpDragInfo->hScope);
2729 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
2730 hCurrentCursor = hCursor;
2731 else
2733 hCurrentCursor = hBummer;
2734 lpDragInfo->hScope = 0;
2736 if( hCurrentCursor )
2737 SetCursor(hCurrentCursor);
2739 /* send WM_DRAGLOOP */
2740 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
2741 (LPARAM) spDragInfo );
2742 /* send WM_DRAGSELECT or WM_DRAGMOVE */
2743 if( hCurrentWnd != lpDragInfo->hScope )
2745 if( hCurrentWnd )
2746 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
2747 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
2748 HIWORD(spDragInfo)) );
2749 hCurrentWnd = lpDragInfo->hScope;
2750 if( hCurrentWnd )
2751 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
2753 else
2754 if( hCurrentWnd )
2755 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
2757 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
2759 ReleaseCapture();
2760 ShowCursor( FALSE );
2762 if( hCursor )
2764 SetCursor( hOldCursor );
2765 if (hDragCursor) DestroyCursor( hDragCursor );
2768 if( hCurrentCursor != hBummer )
2769 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
2770 (WPARAM16)hWnd, (LPARAM)spDragInfo );
2771 else
2772 msg.lParam = 0;
2773 GlobalFree16(hDragInfo);
2775 return (DWORD)(msg.lParam);