Added "user-friendly" warning for missing X.
[wine.git] / windows / win.c
blob8dd6e3f3f3589d239e18da6a5dc06b7eb839f2b7
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include <string.h>
9 #include "options.h"
10 #include "class.h"
11 #include "win.h"
12 #include "heap.h"
13 #include "user.h"
14 #include "dce.h"
15 #include "sysmetrics.h"
16 #include "cursoricon.h"
17 #include "heap.h"
18 #include "hook.h"
19 #include "menu.h"
20 #include "message.h"
21 #include "nonclient.h"
22 #include "queue.h"
23 #include "winpos.h"
24 #include "shm_main_blk.h"
25 #include "dde_proc.h"
26 #include "clipboard.h"
27 #include "winproc.h"
28 #include "task.h"
29 #include "thread.h"
30 #include "process.h"
31 #include "debug.h"
32 #include "winerror.h"
33 #include "mdi.h"
35 extern WND_DRIVER X11DRV_WND_Driver;
37 /* Desktop window */
38 static WND *pWndDesktop = NULL;
40 static HWND32 hwndSysModal = 0;
42 static WORD wDragWidth = 4;
43 static WORD wDragHeight= 3;
45 /***********************************************************************
46 * WIN_FindWndPtr
48 * Return a pointer to the WND structure corresponding to a HWND.
50 WND * WIN_FindWndPtr( HWND32 hwnd )
52 WND * ptr;
54 if (!hwnd || HIWORD(hwnd)) return NULL;
55 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
56 if (ptr->dwMagic != WND_MAGIC) return NULL;
57 if (ptr->hwndSelf != hwnd)
59 ERR( win, "Can't happen: hwnd %04x self pointer is %04x\n",
60 hwnd, ptr->hwndSelf );
61 return NULL;
63 return ptr;
67 /***********************************************************************
68 * WIN_DumpWindow
70 * Dump the content of a window structure to stderr.
72 void WIN_DumpWindow( HWND32 hwnd )
74 WND *ptr;
75 char className[80];
76 int i;
78 if (!(ptr = WIN_FindWndPtr( hwnd )))
80 WARN( win, "%04x is not a window handle\n", hwnd );
81 return;
84 if (!GetClassName32A( hwnd, className, sizeof(className ) ))
85 strcpy( className, "#NULL#" );
87 TRACE( win, "Window %04x (%p):\n", hwnd, ptr );
88 DUMP( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
89 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
90 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
91 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
92 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
93 ptr->next, ptr->child, ptr->parent, ptr->owner,
94 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
95 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
96 ptr->dwStyle, ptr->dwExStyle, (UINT32)ptr->winproc,
97 ptr->text ? ptr->text : "",
98 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
99 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
100 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
101 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
103 if (ptr->class->cbWndExtra)
105 DUMP( "extra bytes:" );
106 for (i = 0; i < ptr->class->cbWndExtra; i++)
107 DUMP( " %02x", *((BYTE*)ptr->wExtra+i) );
108 DUMP( "\n" );
110 DUMP( "\n" );
114 /***********************************************************************
115 * WIN_WalkWindows
117 * Walk the windows tree and print each window on stderr.
119 void WIN_WalkWindows( HWND32 hwnd, int indent )
121 WND *ptr;
122 char className[80];
124 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop;
125 if (!ptr)
127 WARN( win, "Invalid window handle %04x\n", hwnd );
128 return;
131 if (!indent) /* first time around */
132 DUMP( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
133 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
134 " Text");
136 while (ptr)
138 DUMP( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
140 GlobalGetAtomName16(ptr->class->atomName,className,sizeof(className));
142 DUMP( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
143 (DWORD)ptr, ptr->hmemTaskQ, className,
144 (UINT32)ptr->dwStyle, (UINT32)ptr->winproc,
145 ptr->text?ptr->text:"<null>");
147 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
148 ptr = ptr->next;
152 /***********************************************************************
153 * WIN_UnlinkWindow
155 * Remove a window from the siblings linked list.
157 BOOL32 WIN_UnlinkWindow( HWND32 hwnd )
159 WND *wndPtr, **ppWnd;
161 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
162 ppWnd = &wndPtr->parent->child;
163 while (*ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
164 *ppWnd = wndPtr->next;
165 return TRUE;
169 /***********************************************************************
170 * WIN_LinkWindow
172 * Insert a window into the siblings linked list.
173 * The window is inserted after the specified window, which can also
174 * be specified as HWND_TOP or HWND_BOTTOM.
176 BOOL32 WIN_LinkWindow( HWND32 hwnd, HWND32 hwndInsertAfter )
178 WND *wndPtr, **ppWnd;
180 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
182 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
184 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
185 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
186 while (*ppWnd) ppWnd = &(*ppWnd)->next;
188 else /* Normal case */
190 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
191 if (!afterPtr) return FALSE;
192 ppWnd = &afterPtr->next;
194 wndPtr->next = *ppWnd;
195 *ppWnd = wndPtr;
196 return TRUE;
200 /***********************************************************************
201 * WIN_FindWinToRepaint
203 * Find a window that needs repaint.
205 HWND32 WIN_FindWinToRepaint( HWND32 hwnd, HQUEUE16 hQueue )
207 HWND32 hwndRet;
208 WND *pWnd = pWndDesktop;
210 /* Note: the desktop window never gets WM_PAINT messages
211 * The real reason why is because Windows DesktopWndProc
212 * does ValidateRgn inside WM_ERASEBKGND handler.
215 pWnd = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop->child;
217 for ( ; pWnd ; pWnd = pWnd->next )
219 if (!(pWnd->dwStyle & WS_VISIBLE))
221 TRACE(win, "skipping window %04x\n",
222 pWnd->hwndSelf );
223 continue;
225 if ((pWnd->hmemTaskQ == hQueue) &&
226 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))) break;
228 if (pWnd->child )
229 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
230 return hwndRet;
233 if (!pWnd) return 0;
235 hwndRet = pWnd->hwndSelf;
237 /* look among siblings if we got a transparent window */
238 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
239 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
241 pWnd = pWnd->next;
243 if (pWnd) hwndRet = pWnd->hwndSelf;
244 TRACE(win,"found %04x\n",hwndRet);
245 return hwndRet;
249 /***********************************************************************
250 * WIN_DestroyWindow
252 * Destroy storage associated to a window. "Internals" p.358
254 static WND* WIN_DestroyWindow( WND* wndPtr )
256 HWND32 hwnd = wndPtr->hwndSelf;
257 WND *pWnd;
259 TRACE(win, "%04x\n", wndPtr->hwndSelf );
261 #ifdef CONFIG_IPC
262 if (main_block)
263 DDE_DestroyWindow(wndPtr->hwndSelf);
264 #endif /* CONFIG_IPC */
266 /* free child windows */
268 while ((pWnd = wndPtr->child))
269 wndPtr->child = WIN_DestroyWindow( pWnd );
271 SendMessage32A( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
273 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
275 WINPOS_CheckInternalPos( hwnd );
276 if( hwnd == GetCapture32()) ReleaseCapture();
278 /* free resources associated with the window */
280 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
281 PROPERTY_RemoveWindowProps( wndPtr );
283 wndPtr->dwMagic = 0; /* Mark it as invalid */
285 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
287 if (wndPtr->hrgnUpdate > 1) DeleteObject32( wndPtr->hrgnUpdate );
288 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
291 /* toss stale messages from the queue */
293 if( wndPtr->hmemTaskQ )
295 int pos;
296 BOOL32 bPostQuit = FALSE;
297 WPARAM32 wQuitParam = 0;
298 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) GlobalLock16(wndPtr->hmemTaskQ);
300 while( (pos = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != -1 )
302 if( msgQ->messages[pos].msg.message == WM_QUIT )
304 bPostQuit = TRUE;
305 wQuitParam = msgQ->messages[pos].msg.wParam;
307 QUEUE_RemoveMsg(msgQ, pos);
309 /* repost WM_QUIT to make sure this app exits its message loop */
310 if( bPostQuit ) PostQuitMessage32(wQuitParam);
311 wndPtr->hmemTaskQ = 0;
314 if (!(wndPtr->dwStyle & WS_CHILD))
315 if (wndPtr->wIDmenu) DestroyMenu32( (HMENU32)wndPtr->wIDmenu );
316 if (wndPtr->hSysMenu) DestroyMenu32( wndPtr->hSysMenu );
317 wndPtr->pDriver->pDestroyWindow( wndPtr );
318 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
319 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
320 wndPtr->hwndSelf = 0;
321 wndPtr->class->cWindows--;
322 wndPtr->class = NULL;
323 pWnd = wndPtr->next;
325 wndPtr->pDriver->pFinalize(wndPtr);
326 USER_HEAP_FREE( hwnd );
327 return pWnd;
330 /***********************************************************************
331 * WIN_ResetQueueWindows
333 * Reset the queue of all the children of a given window.
334 * Return TRUE if something was done.
336 BOOL32 WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
338 BOOL32 ret = FALSE;
340 if (hNew) /* Set a new queue */
342 for (wnd = wnd->child; (wnd); wnd = wnd->next)
344 if (wnd->hmemTaskQ == hQueue)
346 wnd->hmemTaskQ = hNew;
347 ret = TRUE;
349 if (wnd->child)
350 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
353 else /* Queue is being destroyed */
355 while (wnd->child)
357 WND *tmp = wnd->child;
358 ret = FALSE;
359 while (tmp)
361 if (tmp->hmemTaskQ == hQueue)
363 DestroyWindow32( tmp->hwndSelf );
364 ret = TRUE;
365 break;
367 if (tmp->child && WIN_ResetQueueWindows(tmp->child,hQueue,0))
368 ret = TRUE;
369 else
370 tmp = tmp->next;
372 if (!ret) break;
375 return ret;
378 /***********************************************************************
379 * WIN_CreateDesktopWindow
381 * Create the desktop window.
383 BOOL32 WIN_CreateDesktopWindow(void)
385 CLASS *class;
386 HWND32 hwndDesktop;
388 TRACE(win,"Creating desktop window\n");
390 if (!ICONTITLE_Init() ||
391 !WINPOS_CreateInternalPosAtom() ||
392 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
393 return FALSE;
395 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
396 if (!hwndDesktop) return FALSE;
397 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
399 pWndDesktop->pDriver = &X11DRV_WND_Driver;
400 pWndDesktop->pDriver->pInitialize(pWndDesktop);
402 pWndDesktop->next = NULL;
403 pWndDesktop->child = NULL;
404 pWndDesktop->parent = NULL;
405 pWndDesktop->owner = NULL;
406 pWndDesktop->class = class;
407 pWndDesktop->dwMagic = WND_MAGIC;
408 pWndDesktop->hwndSelf = hwndDesktop;
409 pWndDesktop->hInstance = 0;
410 pWndDesktop->rectWindow.left = 0;
411 pWndDesktop->rectWindow.top = 0;
412 pWndDesktop->rectWindow.right = SYSMETRICS_CXSCREEN;
413 pWndDesktop->rectWindow.bottom = SYSMETRICS_CYSCREEN;
414 pWndDesktop->rectClient = pWndDesktop->rectWindow;
415 pWndDesktop->text = NULL;
416 pWndDesktop->hmemTaskQ = GetFastQueue();
417 pWndDesktop->hrgnUpdate = 0;
418 pWndDesktop->hwndLastActive = hwndDesktop;
419 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
420 WS_CLIPSIBLINGS;
421 pWndDesktop->dwExStyle = 0;
422 pWndDesktop->dce = NULL;
423 pWndDesktop->pVScroll = NULL;
424 pWndDesktop->pHScroll = NULL;
425 pWndDesktop->pProp = NULL;
426 pWndDesktop->wIDmenu = 0;
427 pWndDesktop->helpContext = 0;
428 pWndDesktop->flags = 0;
429 pWndDesktop->hSysMenu = 0;
430 pWndDesktop->userdata = 0;
431 pWndDesktop->winproc = (WNDPROC16)class->winproc;
433 /* FIXME: How do we know if it should be Unicode or not */
434 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop, class, FALSE))
435 return FALSE;
437 SendMessage32A( hwndDesktop, WM_NCCREATE, 0, 0 );
438 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
439 return TRUE;
443 /***********************************************************************
444 * WIN_CreateWindowEx
446 * Implementation of CreateWindowEx().
448 static HWND32 WIN_CreateWindowEx( CREATESTRUCT32A *cs, ATOM classAtom,
449 BOOL32 win32, BOOL32 unicode )
451 CLASS *classPtr;
452 WND *wndPtr;
453 HWND16 hwnd, hwndLinkAfter;
454 POINT32 maxSize, maxPos, minTrack, maxTrack;
455 LRESULT (CALLBACK *localSend32)(HWND32, UINT32, WPARAM32, LPARAM);
457 TRACE(win, "%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
458 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
459 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
460 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
461 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
463 /* Find the parent window */
465 if (cs->hwndParent)
467 /* Make sure parent is valid */
468 if (!IsWindow32( cs->hwndParent ))
470 WARN( win, "Bad parent %04x\n", cs->hwndParent );
471 return 0;
473 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
474 WARN( win, "No parent for child window\n" );
475 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
478 /* Find the window class */
479 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
481 char buffer[256];
482 GlobalGetAtomName32A( classAtom, buffer, sizeof(buffer) );
483 WARN( win, "Bad class '%s'\n", buffer );
484 return 0;
487 /* Fix the coordinates */
489 if (cs->x == CW_USEDEFAULT32)
491 PDB32 *pdb = PROCESS_Current();
492 if ( !(cs->style & (WS_CHILD | WS_POPUP))
493 && (pdb->env_db->startup_info->dwFlags & STARTF_USEPOSITION) )
495 cs->x = pdb->env_db->startup_info->dwX;
496 cs->y = pdb->env_db->startup_info->dwY;
498 else
500 cs->x = 0;
501 cs->y = 0;
504 if (cs->cx == CW_USEDEFAULT32)
506 PDB32 *pdb = PROCESS_Current();
507 if ( !(cs->style & (WS_CHILD | WS_POPUP))
508 && (pdb->env_db->startup_info->dwFlags & STARTF_USESIZE) )
510 cs->cx = pdb->env_db->startup_info->dwXSize;
511 cs->cy = pdb->env_db->startup_info->dwYSize;
513 else
515 cs->cx = 600; /* FIXME */
516 cs->cy = 400;
520 /* Create the window structure */
522 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
523 - sizeof(wndPtr->wExtra) )))
525 TRACE(win, "out of memory\n" );
526 return 0;
529 /* Fill the window structure */
531 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
532 wndPtr->next = NULL;
533 wndPtr->child = NULL;
535 if ((cs->style & WS_CHILD) && cs->hwndParent)
537 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
538 wndPtr->owner = NULL;
540 else
542 wndPtr->parent = pWndDesktop;
543 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
544 wndPtr->owner = NULL;
545 else
546 wndPtr->owner = WIN_GetTopParentPtr(WIN_FindWndPtr(cs->hwndParent));
549 wndPtr->pDriver = wndPtr->parent->pDriver;
550 wndPtr->pDriver->pInitialize(wndPtr);
552 wndPtr->class = classPtr;
553 wndPtr->winproc = classPtr->winproc;
554 wndPtr->dwMagic = WND_MAGIC;
555 wndPtr->hwndSelf = hwnd;
556 wndPtr->hInstance = cs->hInstance;
557 wndPtr->text = NULL;
558 wndPtr->hmemTaskQ = GetFastQueue();
559 wndPtr->hrgnUpdate = 0;
560 wndPtr->hwndLastActive = hwnd;
561 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
562 wndPtr->dwExStyle = cs->dwExStyle;
563 wndPtr->wIDmenu = 0;
564 wndPtr->helpContext = 0;
565 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
566 wndPtr->pVScroll = NULL;
567 wndPtr->pHScroll = NULL;
568 wndPtr->pProp = NULL;
569 wndPtr->userdata = 0;
570 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
571 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
573 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
575 /* Call the WH_CBT hook */
577 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
578 ? HWND_BOTTOM : HWND_TOP;
580 if (HOOK_IsHooked( WH_CBT ))
582 CBT_CREATEWND32A cbtc;
583 LRESULT ret;
585 cbtc.lpcs = cs;
586 cbtc.hwndInsertAfter = hwndLinkAfter;
587 ret = unicode ? HOOK_CallHooks32W(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
588 : HOOK_CallHooks32A(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
589 if (ret)
591 TRACE(win, "CBT-hook returned 0\n");
592 wndPtr->pDriver->pFinalize(wndPtr);
593 USER_HEAP_FREE( hwnd );
594 return 0;
598 /* Increment class window counter */
600 classPtr->cWindows++;
602 /* Correct the window style */
604 if (!(cs->style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
606 wndPtr->dwStyle |= WS_CAPTION | WS_CLIPSIBLINGS;
607 wndPtr->flags |= WIN_NEED_SIZE;
609 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
611 /* Get class or window DC if needed */
613 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
614 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
615 else wndPtr->dce = NULL;
617 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
619 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
621 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
622 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
623 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
624 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
625 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
628 if(cs->style & WS_CHILD)
630 if(cs->cx < 0) cs->cx = 0;
631 if(cs->cy < 0) cs->cy = 0;
633 else
635 if (cs->cx <= 0) cs->cx = 1;
636 if (cs->cy <= 0) cs->cy = 1;
639 wndPtr->rectWindow.left = cs->x;
640 wndPtr->rectWindow.top = cs->y;
641 wndPtr->rectWindow.right = cs->x + cs->cx;
642 wndPtr->rectWindow.bottom = cs->y + cs->cy;
643 wndPtr->rectClient = wndPtr->rectWindow;
645 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
646 return FALSE;
648 /* Set the window menu */
650 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
652 if (cs->hMenu) SetMenu32(hwnd, cs->hMenu);
653 else
655 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
656 if (classPtr->menuNameA)
657 cs->hMenu = HIWORD(classPtr->menuNameA) ?
658 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
659 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
660 #else
661 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
662 if (menuName)
664 if (HIWORD(cs->hInstance))
665 cs->hMenu = LoadMenu32A(cs->hInstance,PTR_SEG_TO_LIN(menuName));
666 else
667 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
669 if (cs->hMenu) SetMenu32( hwnd, cs->hMenu );
671 #endif
674 else wndPtr->wIDmenu = (UINT32)cs->hMenu;
676 /* Send the WM_CREATE message
677 * Perhaps we shouldn't allow width/height changes as well.
678 * See p327 in "Internals".
681 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
683 localSend32 = unicode ? SendMessage32W : SendMessage32A;
684 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
686 /* Insert the window in the linked list */
688 WIN_LinkWindow( hwnd, hwndLinkAfter );
690 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
691 NULL, NULL, 0, &wndPtr->rectClient );
692 OffsetRect32(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
693 maxPos.y - wndPtr->rectWindow.top);
694 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
696 /* Send the size messages */
698 if (!(wndPtr->flags & WIN_NEED_SIZE))
700 /* send it anyway */
701 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
702 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
703 WARN(win,"sending bogus WM_SIZE message 0x%08lx\n",
704 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
705 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
706 SendMessage32A( hwnd, WM_SIZE, SIZE_RESTORED,
707 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
708 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
709 SendMessage32A( hwnd, WM_MOVE, 0,
710 MAKELONG( wndPtr->rectClient.left,
711 wndPtr->rectClient.top ) );
714 /* Show the window, maximizing or minimizing if needed */
716 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
718 RECT16 newPos;
719 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
720 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
721 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
722 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow32())
723 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
724 : SWP_NOZORDER | SWP_FRAMECHANGED;
725 SetWindowPos32( hwnd, 0, newPos.left, newPos.top,
726 newPos.right, newPos.bottom, swFlag );
729 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
731 /* Notify the parent window only */
733 SendMessage32A( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
734 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
735 if( !IsWindow32(hwnd) ) return 0;
738 if (cs->style & WS_VISIBLE) ShowWindow32( hwnd, SW_SHOW );
740 /* Call WH_SHELL hook */
742 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
743 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
745 TRACE(win, "created window %04x\n", hwnd);
746 return hwnd;
748 WIN_UnlinkWindow( hwnd );
751 /* Abort window creation */
753 WARN(win, "aborted by WM_xxCREATE!\n");
754 WIN_DestroyWindow( wndPtr );
755 return 0;
759 /***********************************************************************
760 * CreateWindow16 (USER.41)
762 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
763 DWORD style, INT16 x, INT16 y, INT16 width,
764 INT16 height, HWND16 parent, HMENU16 menu,
765 HINSTANCE16 instance, LPVOID data )
767 return CreateWindowEx16( 0, className, windowName, style,
768 x, y, width, height, parent, menu, instance, data );
772 /***********************************************************************
773 * CreateWindowEx16 (USER.452)
775 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
776 LPCSTR windowName, DWORD style, INT16 x,
777 INT16 y, INT16 width, INT16 height,
778 HWND16 parent, HMENU16 menu,
779 HINSTANCE16 instance, LPVOID data )
781 ATOM classAtom;
782 CREATESTRUCT32A cs;
784 /* Find the class atom */
786 if (!(classAtom = GlobalFindAtom32A( className )))
788 fprintf( stderr, "CreateWindowEx16: bad class name " );
789 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
790 else fprintf( stderr, "'%s'\n", className );
791 return 0;
794 /* Fix the coordinates */
796 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)x;
797 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)y;
798 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)width;
799 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)height;
801 /* Create the window */
803 cs.lpCreateParams = data;
804 cs.hInstance = (HINSTANCE32)instance;
805 cs.hMenu = (HMENU32)menu;
806 cs.hwndParent = (HWND32)parent;
807 cs.style = style;
808 cs.lpszName = windowName;
809 cs.lpszClass = className;
810 cs.dwExStyle = exStyle;
811 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
815 /***********************************************************************
816 * CreateWindowEx32A (USER32.83)
818 HWND32 WINAPI CreateWindowEx32A( DWORD exStyle, LPCSTR className,
819 LPCSTR windowName, DWORD style, INT32 x,
820 INT32 y, INT32 width, INT32 height,
821 HWND32 parent, HMENU32 menu,
822 HINSTANCE32 instance, LPVOID data )
824 ATOM classAtom;
825 CREATESTRUCT32A cs;
827 if(exStyle & WS_EX_MDICHILD)
828 return MDI_CreateMDIWindow32A(className, windowName, style, x, y, width, height, parent, instance, data);
829 /* Find the class atom */
831 if (!(classAtom = GlobalFindAtom32A( className )))
833 fprintf( stderr, "CreateWindowEx32A: bad class name " );
834 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
835 else fprintf( stderr, "'%s'\n", className );
836 return 0;
839 /* Create the window */
841 cs.lpCreateParams = data;
842 cs.hInstance = instance;
843 cs.hMenu = menu;
844 cs.hwndParent = parent;
845 cs.x = x;
846 cs.y = y;
847 cs.cx = width;
848 cs.cy = height;
849 cs.style = style;
850 cs.lpszName = windowName;
851 cs.lpszClass = className;
852 cs.dwExStyle = exStyle;
853 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
857 /***********************************************************************
858 * CreateWindowEx32W (USER32.84)
860 HWND32 WINAPI CreateWindowEx32W( DWORD exStyle, LPCWSTR className,
861 LPCWSTR windowName, DWORD style, INT32 x,
862 INT32 y, INT32 width, INT32 height,
863 HWND32 parent, HMENU32 menu,
864 HINSTANCE32 instance, LPVOID data )
866 ATOM classAtom;
867 CREATESTRUCT32W cs;
869 if(exStyle & WS_EX_MDICHILD)
870 return MDI_CreateMDIWindow32W(className, windowName, style, x, y, width, height, parent, instance, data);
872 /* Find the class atom */
874 if (!(classAtom = GlobalFindAtom32W( className )))
876 if (HIWORD(className))
878 LPSTR cn = HEAP_strdupWtoA( GetProcessHeap(), 0, className );
879 WARN( win, "Bad class name '%s'\n",cn);
880 HeapFree( GetProcessHeap(), 0, cn );
882 else
883 WARN( win, "Bad class name %p\n", className );
884 return 0;
887 /* Create the window */
889 cs.lpCreateParams = data;
890 cs.hInstance = instance;
891 cs.hMenu = menu;
892 cs.hwndParent = parent;
893 cs.x = x;
894 cs.y = y;
895 cs.cx = width;
896 cs.cy = height;
897 cs.style = style;
898 cs.lpszName = windowName;
899 cs.lpszClass = className;
900 cs.dwExStyle = exStyle;
901 /* Note: we rely on the fact that CREATESTRUCT32A and */
902 /* CREATESTRUCT32W have the same layout. */
903 return WIN_CreateWindowEx( (CREATESTRUCT32A *)&cs, classAtom, TRUE, TRUE );
907 /***********************************************************************
908 * WIN_CheckFocus
910 static void WIN_CheckFocus( WND* pWnd )
912 if( GetFocus16() == pWnd->hwndSelf )
913 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
916 /***********************************************************************
917 * WIN_SendDestroyMsg
919 static void WIN_SendDestroyMsg( WND* pWnd )
921 WIN_CheckFocus(pWnd);
923 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret32();
924 CLIPBOARD_GetDriver()->pResetOwner( pWnd, TRUE );
926 SendMessage32A( pWnd->hwndSelf, WM_DESTROY, 0, 0);
928 if( IsWindow32(pWnd->hwndSelf) )
930 WND* pChild = pWnd->child;
931 while( pChild )
933 WIN_SendDestroyMsg( pChild );
934 pChild = pChild->next;
936 WIN_CheckFocus(pWnd);
938 else
939 WARN(win, "\tdestroyed itself while in WM_DESTROY!\n");
943 /***********************************************************************
944 * DestroyWindow16 (USER.53)
946 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
948 return DestroyWindow32(hwnd);
952 /***********************************************************************
953 * DestroyWindow32 (USER32.135)
955 BOOL32 WINAPI DestroyWindow32( HWND32 hwnd )
957 WND * wndPtr;
959 TRACE(win, "(%04x)\n", hwnd);
961 /* Initialization */
963 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
964 if (wndPtr == pWndDesktop) return FALSE; /* Can't destroy desktop */
966 /* Call hooks */
968 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
969 return FALSE;
971 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
973 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
974 /* FIXME: clean up palette - see "Internals" p.352 */
977 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
978 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
980 /* Notify the parent window only */
981 SendMessage32A( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
982 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
983 if( !IsWindow32(hwnd) ) return TRUE;
986 CLIPBOARD_GetDriver()->pResetOwner( wndPtr, FALSE ); /* before the window is unmapped */
988 /* Hide the window */
990 if (wndPtr->dwStyle & WS_VISIBLE)
992 SetWindowPos32( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
993 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
994 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
995 if (!IsWindow32(hwnd)) return TRUE;
998 /* Recursively destroy owned windows */
1000 if( !(wndPtr->dwStyle & WS_CHILD) )
1002 /* make sure top menu popup doesn't get destroyed */
1003 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1005 for (;;)
1007 WND *siblingPtr = wndPtr->parent->child; /* First sibling */
1008 while (siblingPtr)
1010 if (siblingPtr->owner == wndPtr)
1012 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1013 break;
1014 else
1015 siblingPtr->owner = NULL;
1017 siblingPtr = siblingPtr->next;
1019 if (siblingPtr) DestroyWindow32( siblingPtr->hwndSelf );
1020 else break;
1023 if( !Options.managed || EVENT_CheckFocus() )
1024 WINPOS_ActivateOtherWindow(wndPtr);
1026 if( wndPtr->owner &&
1027 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1028 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1031 /* Send destroy messages */
1033 WIN_SendDestroyMsg( wndPtr );
1034 if (!IsWindow32(hwnd)) return TRUE;
1036 /* Unlink now so we won't bother with the children later on */
1038 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1040 /* Destroy the window storage */
1042 WIN_DestroyWindow( wndPtr );
1043 return TRUE;
1047 /***********************************************************************
1048 * CloseWindow16 (USER.43)
1050 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1052 return CloseWindow32( hwnd );
1056 /***********************************************************************
1057 * CloseWindow32 (USER32.56)
1059 BOOL32 WINAPI CloseWindow32( HWND32 hwnd )
1061 WND * wndPtr = WIN_FindWndPtr( hwnd );
1062 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD)) return FALSE;
1063 ShowWindow32( hwnd, SW_MINIMIZE );
1064 return TRUE;
1068 /***********************************************************************
1069 * OpenIcon16 (USER.44)
1071 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1073 return OpenIcon32( hwnd );
1077 /***********************************************************************
1078 * OpenIcon32 (USER32.410)
1080 BOOL32 WINAPI OpenIcon32( HWND32 hwnd )
1082 if (!IsIconic32( hwnd )) return FALSE;
1083 ShowWindow32( hwnd, SW_SHOWNORMAL );
1084 return TRUE;
1088 /***********************************************************************
1089 * WIN_FindWindow
1091 * Implementation of FindWindow() and FindWindowEx().
1093 static HWND32 WIN_FindWindow( HWND32 parent, HWND32 child, ATOM className,
1094 LPCSTR title )
1096 WND *pWnd;
1097 CLASS *pClass = NULL;
1099 if (child)
1101 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1102 if (parent)
1104 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent)) return 0;
1106 else if (pWnd->parent != pWndDesktop) return 0;
1107 pWnd = pWnd->next;
1109 else
1111 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : pWndDesktop)) return 0;
1112 pWnd = pWnd->child;
1114 if (!pWnd) return 0;
1116 /* For a child window, all siblings will have the same hInstance, */
1117 /* so we can look for the class once and for all. */
1119 if (className && (pWnd->dwStyle & WS_CHILD))
1121 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1122 return 0;
1126 for ( ; pWnd; pWnd = pWnd->next)
1128 if (className && !(pWnd->dwStyle & WS_CHILD))
1130 if (!(pClass = CLASS_FindClassByAtom( className, GetExePtr(pWnd->hInstance))))
1131 continue; /* Skip this window */
1134 if (pClass && (pWnd->class != pClass))
1135 continue; /* Not the right class */
1137 /* Now check the title */
1139 if (!title) return pWnd->hwndSelf;
1140 if (pWnd->text && !strcmp( pWnd->text, title )) return pWnd->hwndSelf;
1142 return 0;
1147 /***********************************************************************
1148 * FindWindow16 (USER.50)
1150 HWND16 WINAPI FindWindow16( SEGPTR className, LPCSTR title )
1152 return FindWindowEx16( 0, 0, className, title );
1156 /***********************************************************************
1157 * FindWindowEx16 (USER.427)
1159 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child,
1160 SEGPTR className, LPCSTR title )
1162 ATOM atom = 0;
1164 TRACE(win, "%04x %04x '%s' '%s'\n", parent,
1165 child, HIWORD(className)?(char *)PTR_SEG_TO_LIN(className):"",
1166 title ? title : "");
1168 if (className)
1170 /* If the atom doesn't exist, then no class */
1171 /* with this name exists either. */
1172 if (!(atom = GlobalFindAtom16( className ))) return 0;
1174 return WIN_FindWindow( parent, child, atom, title );
1178 /***********************************************************************
1179 * FindWindow32A (USER32.198)
1181 HWND32 WINAPI FindWindow32A( LPCSTR className, LPCSTR title )
1183 HWND32 ret = FindWindowEx32A( 0, 0, className, title );
1184 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1185 return ret;
1189 /***********************************************************************
1190 * FindWindowEx32A (USER32.199)
1192 HWND32 WINAPI FindWindowEx32A( HWND32 parent, HWND32 child,
1193 LPCSTR className, LPCSTR title )
1195 ATOM atom = 0;
1197 if (className)
1199 /* If the atom doesn't exist, then no class */
1200 /* with this name exists either. */
1201 if (!(atom = GlobalFindAtom32A( className )))
1203 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1204 return 0;
1207 return WIN_FindWindow( parent, child, atom, title );
1211 /***********************************************************************
1212 * FindWindowEx32W (USER32.200)
1214 HWND32 WINAPI FindWindowEx32W( HWND32 parent, HWND32 child,
1215 LPCWSTR className, LPCWSTR title )
1217 ATOM atom = 0;
1218 char *buffer;
1219 HWND32 hwnd;
1221 if (className)
1223 /* If the atom doesn't exist, then no class */
1224 /* with this name exists either. */
1225 if (!(atom = GlobalFindAtom32W( className )))
1227 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1228 return 0;
1231 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1232 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1233 HeapFree( GetProcessHeap(), 0, buffer );
1234 return hwnd;
1238 /***********************************************************************
1239 * FindWindow32W (USER32.201)
1241 HWND32 WINAPI FindWindow32W( LPCWSTR className, LPCWSTR title )
1243 return FindWindowEx32W( 0, 0, className, title );
1247 /**********************************************************************
1248 * WIN_GetDesktop
1250 WND *WIN_GetDesktop(void)
1252 return pWndDesktop;
1256 /**********************************************************************
1257 * GetDesktopWindow16 (USER.286)
1259 HWND16 WINAPI GetDesktopWindow16(void)
1261 return (HWND16)pWndDesktop->hwndSelf;
1265 /**********************************************************************
1266 * GetDesktopWindow32 (USER32.232)
1268 HWND32 WINAPI GetDesktopWindow32(void)
1270 return pWndDesktop->hwndSelf;
1274 /**********************************************************************
1275 * GetDesktopHwnd (USER.278)
1277 * Exactly the same thing as GetDesktopWindow(), but not documented.
1278 * Don't ask me why...
1280 HWND16 WINAPI GetDesktopHwnd(void)
1282 return (HWND16)pWndDesktop->hwndSelf;
1286 /*******************************************************************
1287 * EnableWindow16 (USER.34)
1289 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1291 return EnableWindow32( hwnd, enable );
1295 /*******************************************************************
1296 * EnableWindow32 (USER32.172)
1298 BOOL32 WINAPI EnableWindow32( HWND32 hwnd, BOOL32 enable )
1300 WND *wndPtr;
1302 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1303 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1305 /* Enable window */
1306 wndPtr->dwStyle &= ~WS_DISABLED;
1307 SendMessage32A( hwnd, WM_ENABLE, TRUE, 0 );
1308 return TRUE;
1310 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1312 /* Disable window */
1313 wndPtr->dwStyle |= WS_DISABLED;
1314 if ((hwnd == GetFocus32()) || IsChild32( hwnd, GetFocus32() ))
1315 SetFocus32( 0 ); /* A disabled window can't have the focus */
1316 if ((hwnd == GetCapture32()) || IsChild32( hwnd, GetCapture32() ))
1317 ReleaseCapture(); /* A disabled window can't capture the mouse */
1318 SendMessage32A( hwnd, WM_ENABLE, FALSE, 0 );
1319 return FALSE;
1321 return ((wndPtr->dwStyle & WS_DISABLED) != 0);
1325 /***********************************************************************
1326 * IsWindowEnabled16 (USER.35)
1328 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1330 return IsWindowEnabled32(hWnd);
1334 /***********************************************************************
1335 * IsWindowEnabled32 (USER32.349)
1337 BOOL32 WINAPI IsWindowEnabled32(HWND32 hWnd)
1339 WND * wndPtr;
1341 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1342 return !(wndPtr->dwStyle & WS_DISABLED);
1346 /***********************************************************************
1347 * IsWindowUnicode (USER32.350)
1349 BOOL32 WINAPI IsWindowUnicode( HWND32 hwnd )
1351 WND * wndPtr;
1353 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1354 return (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1358 /**********************************************************************
1359 * GetWindowWord16 (USER.133)
1361 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1363 return GetWindowWord32( hwnd, offset );
1367 /**********************************************************************
1368 * GetWindowWord32 (USER32.314)
1370 WORD WINAPI GetWindowWord32( HWND32 hwnd, INT32 offset )
1372 WND * wndPtr = WIN_FindWndPtr( hwnd );
1373 if (!wndPtr) return 0;
1374 if (offset >= 0)
1376 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1378 WARN( win, "Invalid offset %d\n", offset );
1379 return 0;
1381 return *(WORD *)(((char *)wndPtr->wExtra) + offset);
1383 switch(offset)
1385 case GWW_ID:
1386 if (HIWORD(wndPtr->wIDmenu))
1387 WARN( win,"GWW_ID: discards high bits of 0x%08x!\n",
1388 wndPtr->wIDmenu);
1389 return (WORD)wndPtr->wIDmenu;
1390 case GWW_HWNDPARENT:
1391 return wndPtr->parent ?
1392 wndPtr->parent->hwndSelf : (
1393 wndPtr->owner ?
1394 wndPtr->owner->hwndSelf :
1396 case GWW_HINSTANCE:
1397 if (HIWORD(wndPtr->hInstance))
1398 WARN(win,"GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1399 wndPtr->hInstance);
1400 return (WORD)wndPtr->hInstance;
1401 default:
1402 WARN( win, "Invalid offset %d\n", offset );
1403 return 0;
1408 /**********************************************************************
1409 * WIN_GetWindowInstance
1411 HINSTANCE32 WIN_GetWindowInstance( HWND32 hwnd )
1413 WND * wndPtr = WIN_FindWndPtr( hwnd );
1414 if (!wndPtr) return (HINSTANCE32)0;
1415 return wndPtr->hInstance;
1419 /**********************************************************************
1420 * SetWindowWord16 (USER.134)
1422 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1424 return SetWindowWord32( hwnd, offset, newval );
1428 /**********************************************************************
1429 * SetWindowWord32 (USER32.524)
1431 WORD WINAPI SetWindowWord32( HWND32 hwnd, INT32 offset, WORD newval )
1433 WORD *ptr, retval;
1434 WND * wndPtr = WIN_FindWndPtr( hwnd );
1435 if (!wndPtr) return 0;
1436 if (offset >= 0)
1438 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1440 WARN( win, "Invalid offset %d\n", offset );
1441 return 0;
1443 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1445 else switch(offset)
1447 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1448 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1449 case GWW_HWNDPARENT: return SetParent32( hwnd, newval );
1450 default:
1451 WARN( win, "Invalid offset %d\n", offset );
1452 return 0;
1454 retval = *ptr;
1455 *ptr = newval;
1456 return retval;
1460 /**********************************************************************
1461 * WIN_GetWindowLong
1463 * Helper function for GetWindowLong().
1465 static LONG WIN_GetWindowLong( HWND32 hwnd, INT32 offset, WINDOWPROCTYPE type )
1467 LONG retval;
1468 WND * wndPtr = WIN_FindWndPtr( hwnd );
1469 if (!wndPtr) return 0;
1470 if (offset >= 0)
1472 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1474 WARN( win, "Invalid offset %d\n", offset );
1475 return 0;
1477 retval = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1478 /* Special case for dialog window procedure */
1479 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1480 return (LONG)WINPROC_GetProc( (HWINDOWPROC)retval, type );
1481 return retval;
1483 switch(offset)
1485 case GWL_USERDATA: return wndPtr->userdata;
1486 case GWL_STYLE: return wndPtr->dwStyle;
1487 case GWL_EXSTYLE: return wndPtr->dwExStyle;
1488 case GWL_ID: return (LONG)wndPtr->wIDmenu;
1489 case GWL_WNDPROC: return (LONG)WINPROC_GetProc( wndPtr->winproc,
1490 type );
1491 case GWL_HWNDPARENT: return wndPtr->parent ?
1492 (HWND32)wndPtr->parent->hwndSelf : 0;
1493 case GWL_HINSTANCE: return wndPtr->hInstance;
1494 default:
1495 WARN( win, "Unknown offset %d\n", offset );
1497 return 0;
1501 /**********************************************************************
1502 * WIN_SetWindowLong
1504 * Helper function for SetWindowLong().
1506 * 0 is the failure code. However, in the case of failure SetLastError
1507 * must be set to distinguish between a 0 return value and a failure.
1509 * FIXME: The error values for SetLastError may not be right. Can
1510 * someone check with the real thing?
1512 static LONG WIN_SetWindowLong( HWND32 hwnd, INT32 offset, LONG newval,
1513 WINDOWPROCTYPE type )
1515 LONG *ptr, retval;
1516 WND * wndPtr = WIN_FindWndPtr( hwnd );
1517 STYLESTRUCT style;
1519 TRACE(win,"%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1521 if (!wndPtr)
1523 /* Is this the right error? */
1524 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1525 return 0;
1528 if (offset >= 0)
1530 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1532 WARN( win, "Invalid offset %d\n", offset );
1534 /* Is this the right error? */
1535 SetLastError( ERROR_OUTOFMEMORY );
1537 return 0;
1539 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1540 /* Special case for dialog window procedure */
1541 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1543 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1544 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1545 type, WIN_PROC_WINDOW );
1546 return retval;
1549 else switch(offset)
1551 case GWL_ID:
1552 ptr = (DWORD*)&wndPtr->wIDmenu;
1553 break;
1554 case GWL_HINSTANCE:
1555 return SetWindowWord32( hwnd, offset, newval );
1556 case GWL_WNDPROC:
1557 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1558 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1559 type, WIN_PROC_WINDOW );
1560 return retval;
1561 case GWL_STYLE:
1562 style.styleOld = wndPtr->dwStyle;
1563 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
1564 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
1566 if (wndPtr->flags & WIN_ISWIN32)
1567 SendMessage32A(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1568 wndPtr->dwStyle = style.styleNew;
1569 if (wndPtr->flags & WIN_ISWIN32)
1570 SendMessage32A(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1571 return style.styleOld;
1573 case GWL_USERDATA:
1574 ptr = &wndPtr->userdata;
1575 break;
1576 case GWL_EXSTYLE:
1577 style.styleOld = wndPtr->dwExStyle;
1578 style.styleNew = newval;
1579 if (wndPtr->flags & WIN_ISWIN32)
1580 SendMessage32A(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1581 wndPtr->dwExStyle = newval;
1582 if (wndPtr->flags & WIN_ISWIN32)
1583 SendMessage32A(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1584 return style.styleOld;
1586 default:
1587 WARN( win, "Invalid offset %d\n", offset );
1589 /* Don't think this is right error but it should do */
1590 SetLastError( ERROR_OUTOFMEMORY );
1592 return 0;
1594 retval = *ptr;
1595 *ptr = newval;
1596 return retval;
1600 /**********************************************************************
1601 * GetWindowLong16 (USER.135)
1603 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1605 return WIN_GetWindowLong( (HWND32)hwnd, offset, WIN_PROC_16 );
1609 /**********************************************************************
1610 * GetWindowLong32A (USER32.305)
1612 LONG WINAPI GetWindowLong32A( HWND32 hwnd, INT32 offset )
1614 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1618 /**********************************************************************
1619 * GetWindowLong32W (USER32.306)
1621 LONG WINAPI GetWindowLong32W( HWND32 hwnd, INT32 offset )
1623 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1627 /**********************************************************************
1628 * SetWindowLong16 (USER.136)
1630 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1632 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1636 /**********************************************************************
1637 * SetWindowLong32A (USER32.517)
1639 LONG WINAPI SetWindowLong32A( HWND32 hwnd, INT32 offset, LONG newval )
1641 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1645 /**********************************************************************
1646 * SetWindowLong32W (USER32.518) Set window attribute
1648 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
1649 * value in a window's extra memory.
1651 * The _hwnd_ parameter specifies the window. is the handle to a
1652 * window that has extra memory. The _newval_ parameter contains the
1653 * new attribute or extra memory value. If positive, the _offset_
1654 * parameter is the byte-addressed location in the window's extra
1655 * memory to set. If negative, _offset_ specifies the window
1656 * attribute to set, and should be one of the following values:
1658 * GWL_EXSTYLE The window's extended window style
1660 * GWL_STYLE The window's window style.
1662 * GWL_WNDPROC Pointer to the window's window procedure.
1664 * GWL_HINSTANCE The window's pplication instance handle.
1666 * GWL_ID The window's identifier.
1668 * GWL_USERDATA The window's user-specified data.
1670 * If the window is a dialog box, the _offset_ parameter can be one of
1671 * the following values:
1673 * DWL_DLGPROC The address of the window's dialog box procedure.
1675 * DWL_MSGRESULT The return value of a message
1676 * that the dialog box procedure processed.
1678 * DWL_USER Application specific information.
1680 * RETURNS
1682 * If successful, returns the previous value located at _offset_. Otherwise,
1683 * returns 0.
1685 * NOTES
1687 * Extra memory for a window class is specified by a nonzero cbWndExtra
1688 * parameter of the WNDCLASS structure passed to RegisterClass() at the
1689 * time of class creation.
1691 * Using GWL_WNDPROC to set a new window procedure effectively creates
1692 * a window subclass. Use CallWindowProc() in the new windows procedure
1693 * to pass messages to the superclass's window procedure.
1695 * The user data is reserved for use by the application which created
1696 * the window.
1698 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
1699 * instead, call the EnableWindow() function to change the window's
1700 * disabled state.
1702 * Do not use GWL_HWNDPARENT to reset the window's parent, use
1703 * SetParent() instead.
1705 * Win95:
1706 * When offset is GWL_STYLE and the calling app's ver is 4.0,
1707 * it sends WM_STYLECHANGING before changing the settings
1708 * and WM_STYLECHANGED afterwards.
1709 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
1711 * BUGS
1713 * GWL_STYLE does not dispatch WM_STYLE... messages.
1715 * CONFORMANCE
1717 * ECMA-234, Win32
1720 LONG WINAPI SetWindowLong32W(
1721 HWND32 hwnd, /* window to alter */
1722 INT32 offset, /* offset, in bytes, of location to alter */
1723 LONG newval /* new value of location */
1725 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1729 /*******************************************************************
1730 * GetWindowText16 (USER.36)
1732 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
1734 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1738 /*******************************************************************
1739 * GetWindowText32A (USER32.309)
1741 INT32 WINAPI GetWindowText32A( HWND32 hwnd, LPSTR lpString, INT32 nMaxCount )
1743 return (INT32)SendMessage32A( hwnd, WM_GETTEXT, nMaxCount,
1744 (LPARAM)lpString );
1747 /*******************************************************************
1748 * InternalGetWindowText (USER32.326)
1750 INT32 WINAPI InternalGetWindowText(HWND32 hwnd,LPWSTR lpString,INT32 nMaxCount )
1752 FIXME(win,"(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
1753 return GetWindowText32W(hwnd,lpString,nMaxCount);
1757 /*******************************************************************
1758 * GetWindowText32W (USER32.312)
1760 INT32 WINAPI GetWindowText32W( HWND32 hwnd, LPWSTR lpString, INT32 nMaxCount )
1762 return (INT32)SendMessage32W( hwnd, WM_GETTEXT, nMaxCount,
1763 (LPARAM)lpString );
1767 /*******************************************************************
1768 * SetWindowText16 (USER.37)
1770 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
1772 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1776 /*******************************************************************
1777 * SetWindowText32A (USER32.521)
1779 BOOL32 WINAPI SetWindowText32A( HWND32 hwnd, LPCSTR lpString )
1781 return (BOOL32)SendMessage32A( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1785 /*******************************************************************
1786 * SetWindowText32W (USER32.523)
1788 BOOL32 WINAPI SetWindowText32W( HWND32 hwnd, LPCWSTR lpString )
1790 return (BOOL32)SendMessage32W( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1794 /*******************************************************************
1795 * GetWindowTextLength16 (USER.38)
1797 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
1799 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1803 /*******************************************************************
1804 * GetWindowTextLength32A (USER32.310)
1806 INT32 WINAPI GetWindowTextLength32A( HWND32 hwnd )
1808 return SendMessage32A( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1811 /*******************************************************************
1812 * GetWindowTextLength32W (USER32.311)
1814 INT32 WINAPI GetWindowTextLength32W( HWND32 hwnd )
1816 return SendMessage32W( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1820 /*******************************************************************
1821 * IsWindow16 (USER.47)
1823 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
1825 return IsWindow32( hwnd );
1828 void WINAPI WIN16_IsWindow16( CONTEXT *context )
1830 WORD *stack = PTR_SEG_OFF_TO_LIN(SS_reg(context), SP_reg(context));
1831 HWND16 hwnd = (HWND16)stack[2];
1833 AX_reg(context) = IsWindow32( hwnd );
1834 ES_reg(context) = USER_HeapSel;
1838 /*******************************************************************
1839 * IsWindow32 (USER32.348)
1841 BOOL32 WINAPI IsWindow32( HWND32 hwnd )
1843 WND * wndPtr = WIN_FindWndPtr( hwnd );
1844 return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
1848 /*****************************************************************
1849 * GetParent16 (USER.46)
1851 HWND16 WINAPI GetParent16( HWND16 hwnd )
1853 return (HWND16)GetParent32( hwnd );
1857 /*****************************************************************
1858 * GetParent32 (USER32.278)
1860 HWND32 WINAPI GetParent32( HWND32 hwnd )
1862 WND *wndPtr = WIN_FindWndPtr(hwnd);
1863 if ((!wndPtr) || (!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD)))) return 0;
1864 wndPtr = (wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner;
1865 return wndPtr ? wndPtr->hwndSelf : 0;
1868 /*****************************************************************
1869 * WIN_GetTopParent
1871 * Get the top-level parent for a child window.
1873 WND* WIN_GetTopParentPtr( WND* pWnd )
1875 while( pWnd && (pWnd->dwStyle & WS_CHILD)) pWnd = pWnd->parent;
1876 return pWnd;
1879 /*****************************************************************
1880 * WIN_GetTopParent
1882 * Get the top-level parent for a child window.
1884 HWND32 WIN_GetTopParent( HWND32 hwnd )
1886 WND *wndPtr = WIN_GetTopParentPtr ( WIN_FindWndPtr( hwnd ) );
1887 return wndPtr ? wndPtr->hwndSelf : 0;
1891 /*****************************************************************
1892 * SetParent16 (USER.233)
1894 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
1896 return SetParent32( hwndChild, hwndNewParent );
1900 /*****************************************************************
1901 * SetParent32 (USER32.495)
1903 HWND32 WINAPI SetParent32( HWND32 hwndChild, HWND32 hwndNewParent )
1905 WND *wndPtr = WIN_FindWndPtr( hwndChild );
1906 WND *pWndNewParent =
1907 (hwndNewParent) ? WIN_FindWndPtr( hwndNewParent ) : pWndDesktop;
1908 WND *pWndOldParent =
1909 (wndPtr)?(*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent):NULL;
1911 /* SetParent32 additionally needs to make hwndChild the topmost window
1912 in the x-order and send the expected WM_WINDOWPOSCHANGING and
1913 WM_WINDOWPOSCHANGED notification messages.
1915 SetWindowPos32( hwndChild, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
1917 return pWndOldParent?pWndOldParent->hwndSelf:0;
1920 /*******************************************************************
1921 * IsChild16 (USER.48)
1923 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
1925 return IsChild32(parent,child);
1929 /*******************************************************************
1930 * IsChild32 (USER32.339)
1932 BOOL32 WINAPI IsChild32( HWND32 parent, HWND32 child )
1934 WND * wndPtr = WIN_FindWndPtr( child );
1935 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1937 wndPtr = wndPtr->parent;
1938 if (wndPtr->hwndSelf == parent) return TRUE;
1940 return FALSE;
1944 /***********************************************************************
1945 * IsWindowVisible16 (USER.49)
1947 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
1949 return IsWindowVisible32(hwnd);
1953 /***********************************************************************
1954 * IsWindowVisible32 (USER32.351)
1956 BOOL32 WINAPI IsWindowVisible32( HWND32 hwnd )
1958 WND *wndPtr = WIN_FindWndPtr( hwnd );
1959 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1961 if (!(wndPtr->dwStyle & WS_VISIBLE)) return FALSE;
1962 wndPtr = wndPtr->parent;
1964 return (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
1968 /***********************************************************************
1969 * WIN_IsWindowDrawable
1971 * hwnd is drawable when it is visible, all parents are not
1972 * minimized, and it is itself not minimized unless we are
1973 * trying to draw its default class icon.
1975 BOOL32 WIN_IsWindowDrawable( WND* wnd, BOOL32 icon )
1977 if( (wnd->dwStyle & WS_MINIMIZE &&
1978 icon && wnd->class->hIcon) ||
1979 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
1980 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
1981 if( wnd->dwStyle & WS_MINIMIZE ||
1982 !(wnd->dwStyle & WS_VISIBLE) ) break;
1983 return (wnd == NULL);
1987 /*******************************************************************
1988 * GetTopWindow16 (USER.229)
1990 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
1992 return GetTopWindow32(hwnd);
1996 /*******************************************************************
1997 * GetTopWindow32 (USER.229)
1999 HWND32 WINAPI GetTopWindow32( HWND32 hwnd )
2001 WND * wndPtr = WIN_FindWndPtr( hwnd );
2002 if (wndPtr && wndPtr->child) return wndPtr->child->hwndSelf;
2003 else return 0;
2007 /*******************************************************************
2008 * GetWindow16 (USER.262)
2010 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2012 return GetWindow32( hwnd,rel );
2016 /*******************************************************************
2017 * GetWindow32 (USER32.302)
2019 HWND32 WINAPI GetWindow32( HWND32 hwnd, WORD rel )
2021 WND * wndPtr = WIN_FindWndPtr( hwnd );
2022 if (!wndPtr) return 0;
2023 switch(rel)
2025 case GW_HWNDFIRST:
2026 if (wndPtr->parent) return wndPtr->parent->child->hwndSelf;
2027 else return 0;
2029 case GW_HWNDLAST:
2030 if (!wndPtr->parent) return 0; /* Desktop window */
2031 while (wndPtr->next) wndPtr = wndPtr->next;
2032 return wndPtr->hwndSelf;
2034 case GW_HWNDNEXT:
2035 if (!wndPtr->next) return 0;
2036 return wndPtr->next->hwndSelf;
2038 case GW_HWNDPREV:
2039 if (!wndPtr->parent) return 0; /* Desktop window */
2040 wndPtr = wndPtr->parent->child; /* First sibling */
2041 if (wndPtr->hwndSelf == hwnd) return 0; /* First in list */
2042 while (wndPtr->next)
2044 if (wndPtr->next->hwndSelf == hwnd) return wndPtr->hwndSelf;
2045 wndPtr = wndPtr->next;
2047 return 0;
2049 case GW_OWNER:
2050 return wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2052 case GW_CHILD:
2053 return wndPtr->child ? wndPtr->child->hwndSelf : 0;
2055 return 0;
2059 /*******************************************************************
2060 * GetNextWindow16 (USER.230)
2062 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2064 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2065 return GetWindow16( hwnd, flag );
2068 /*******************************************************************
2069 * ShowOwnedPopups16 (USER.265)
2071 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2073 ShowOwnedPopups32( owner, fShow );
2077 /*******************************************************************
2078 * ShowOwnedPopups32 (USER32.531)
2080 BOOL32 WINAPI ShowOwnedPopups32( HWND32 owner, BOOL32 fShow )
2082 WND *pWnd = pWndDesktop->child;
2083 while (pWnd)
2085 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
2086 (pWnd->dwStyle & WS_POPUP))
2087 ShowWindow32( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
2088 pWnd = pWnd->next;
2090 return TRUE;
2094 /*******************************************************************
2095 * GetLastActivePopup16 (USER.287)
2097 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2099 return GetLastActivePopup32( hwnd );
2102 /*******************************************************************
2103 * GetLastActivePopup32 (USER32.256)
2105 HWND32 WINAPI GetLastActivePopup32( HWND32 hwnd )
2107 WND *wndPtr;
2108 wndPtr = WIN_FindWndPtr(hwnd);
2109 if (wndPtr == NULL) return hwnd;
2110 return wndPtr->hwndLastActive;
2114 /*******************************************************************
2115 * WIN_BuildWinArray
2117 * Build an array of pointers to the children of a given window.
2118 * The array must be freed with HeapFree(SystemHeap). Return NULL
2119 * when no windows are found.
2121 WND **WIN_BuildWinArray( WND *wndPtr, UINT32 bwaFlags, UINT32* pTotal )
2123 WND **list, **ppWnd;
2124 WND *pWnd;
2125 UINT32 count, skipOwned, skipHidden;
2126 DWORD skipFlags;
2128 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2129 skipOwned = bwaFlags & BWA_SKIPOWNED;
2130 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2131 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2133 /* First count the windows */
2135 if (!wndPtr) wndPtr = pWndDesktop;
2136 for (pWnd = wndPtr->child, count = 0; pWnd; pWnd = pWnd->next)
2138 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
2139 if( !skipHidden || pWnd->dwStyle & WS_VISIBLE ) count++;
2142 if( count )
2144 /* Now build the list of all windows */
2146 if ((list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * (count + 1))))
2148 for (pWnd = wndPtr->child, ppWnd = list, count = 0; pWnd; pWnd = pWnd->next)
2150 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
2151 if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2153 *ppWnd++ = pWnd;
2154 count++;
2157 *ppWnd = NULL;
2159 else count = 0;
2160 } else list = NULL;
2162 if( pTotal ) *pTotal = count;
2163 return list;
2167 /*******************************************************************
2168 * EnumWindows16 (USER.54)
2170 BOOL16 WINAPI EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
2172 WND **list, **ppWnd;
2174 /* We have to build a list of all windows first, to avoid */
2175 /* unpleasant side-effects, for instance if the callback */
2176 /* function changes the Z-order of the windows. */
2178 if (!(list = WIN_BuildWinArray( pWndDesktop, 0, NULL ))) return FALSE;
2180 /* Now call the callback function for every window */
2182 for (ppWnd = list; *ppWnd; ppWnd++)
2184 /* Make sure that the window still exists */
2185 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2186 if (!lpEnumFunc( (*ppWnd)->hwndSelf, lParam )) break;
2188 HeapFree( SystemHeap, 0, list );
2189 return TRUE;
2193 /*******************************************************************
2194 * EnumWindows32 (USER32.193)
2196 BOOL32 WINAPI EnumWindows32( WNDENUMPROC32 lpEnumFunc, LPARAM lParam )
2198 return (BOOL32)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2202 /**********************************************************************
2203 * EnumTaskWindows16 (USER.225)
2205 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2206 LPARAM lParam )
2208 WND **list, **ppWnd;
2210 /* This function is the same as EnumWindows(), */
2211 /* except for an added check on the window's task. */
2213 if (!(list = WIN_BuildWinArray( pWndDesktop, 0, NULL ))) return FALSE;
2215 /* Now call the callback function for every window */
2217 for (ppWnd = list; *ppWnd; ppWnd++)
2219 /* Make sure that the window still exists */
2220 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2221 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2222 if (!func( (*ppWnd)->hwndSelf, lParam )) break;
2224 HeapFree( SystemHeap, 0, list );
2225 return TRUE;
2229 /**********************************************************************
2230 * EnumThreadWindows (USER32.190)
2232 BOOL32 WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC32 func, LPARAM lParam )
2234 THDB *tdb = THREAD_ID_TO_THDB(id);
2236 return (BOOL16)EnumTaskWindows16(tdb->teb.htask16, (WNDENUMPROC16)func, lParam);
2240 /**********************************************************************
2241 * WIN_EnumChildWindows
2243 * Helper function for EnumChildWindows().
2245 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2246 LPARAM lParam )
2248 WND **childList;
2249 BOOL16 ret = FALSE;
2251 for ( ; *ppWnd; ppWnd++)
2253 /* Make sure that the window still exists */
2254 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2255 /* Build children list first */
2256 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2257 ret = func( (*ppWnd)->hwndSelf, lParam );
2258 if (childList)
2260 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2261 HeapFree( SystemHeap, 0, childList );
2263 if (!ret) return FALSE;
2265 return TRUE;
2269 /**********************************************************************
2270 * EnumChildWindows16 (USER.55)
2272 BOOL16 WINAPI EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
2273 LPARAM lParam )
2275 WND **list, *pParent;
2277 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2278 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL ))) return FALSE;
2279 WIN_EnumChildWindows( list, func, lParam );
2280 HeapFree( SystemHeap, 0, list );
2281 return TRUE;
2285 /**********************************************************************
2286 * EnumChildWindows32 (USER32.178)
2288 BOOL32 WINAPI EnumChildWindows32( HWND32 parent, WNDENUMPROC32 func,
2289 LPARAM lParam )
2291 return (BOOL32)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2292 lParam );
2296 /*******************************************************************
2297 * AnyPopup16 (USER.52)
2299 BOOL16 WINAPI AnyPopup16(void)
2301 return AnyPopup32();
2305 /*******************************************************************
2306 * AnyPopup32 (USER32.4)
2308 BOOL32 WINAPI AnyPopup32(void)
2310 WND *wndPtr;
2311 for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next)
2312 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE)) return TRUE;
2313 return FALSE;
2317 /*******************************************************************
2318 * FlashWindow16 (USER.105)
2320 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2322 return FlashWindow32( hWnd, bInvert );
2326 /*******************************************************************
2327 * FlashWindow32 (USER32.202)
2329 BOOL32 WINAPI FlashWindow32( HWND32 hWnd, BOOL32 bInvert )
2331 WND *wndPtr = WIN_FindWndPtr(hWnd);
2333 TRACE(win,"%04x\n", hWnd);
2335 if (!wndPtr) return FALSE;
2337 if (wndPtr->dwStyle & WS_MINIMIZE)
2339 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2341 HDC32 hDC = GetDC32(hWnd);
2343 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2344 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2346 ReleaseDC32( hWnd, hDC );
2347 wndPtr->flags |= WIN_NCACTIVATED;
2349 else
2351 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2352 RDW_UPDATENOW | RDW_FRAME, 0 );
2353 wndPtr->flags &= ~WIN_NCACTIVATED;
2355 return TRUE;
2357 else
2359 WPARAM16 wparam;
2360 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2361 else wparam = (hWnd == GetActiveWindow32());
2363 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2364 return wparam;
2369 /*******************************************************************
2370 * SetSysModalWindow16 (USER.188)
2372 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
2374 HWND32 hWndOldModal = hwndSysModal;
2375 hwndSysModal = hWnd;
2376 FIXME(win, "EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2377 return hWndOldModal;
2381 /*******************************************************************
2382 * GetSysModalWindow16 (USER.52)
2384 HWND16 WINAPI GetSysModalWindow16(void)
2386 return hwndSysModal;
2390 /*******************************************************************
2391 * GetWindowContextHelpId (USER32.303)
2393 DWORD WINAPI GetWindowContextHelpId( HWND32 hwnd )
2395 WND *wnd = WIN_FindWndPtr( hwnd );
2396 if (!wnd) return 0;
2397 return wnd->helpContext;
2401 /*******************************************************************
2402 * SetWindowContextHelpId (USER32.515)
2404 BOOL32 WINAPI SetWindowContextHelpId( HWND32 hwnd, DWORD id )
2406 WND *wnd = WIN_FindWndPtr( hwnd );
2407 if (!wnd) return FALSE;
2408 wnd->helpContext = id;
2409 return TRUE;
2413 /*******************************************************************
2414 * DRAG_QueryUpdate
2416 * recursively find a child that contains spDragInfo->pt point
2417 * and send WM_QUERYDROPOBJECT
2419 BOOL16 DRAG_QueryUpdate( HWND32 hQueryWnd, SEGPTR spDragInfo, BOOL32 bNoSend )
2421 BOOL16 wParam,bResult = 0;
2422 POINT32 pt;
2423 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
2424 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
2425 RECT32 tempRect;
2427 if( !ptrQueryWnd || !ptrDragInfo ) return 0;
2429 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
2431 GetWindowRect32(hQueryWnd,&tempRect);
2433 if( !PtInRect32(&tempRect,pt) ||
2434 (ptrQueryWnd->dwStyle & WS_DISABLED) )
2435 return 0;
2437 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
2439 tempRect = ptrQueryWnd->rectClient;
2440 if(ptrQueryWnd->dwStyle & WS_CHILD)
2441 MapWindowPoints32( ptrQueryWnd->parent->hwndSelf, 0,
2442 (LPPOINT32)&tempRect, 2 );
2444 if (PtInRect32( &tempRect, pt))
2446 wParam = 0;
2448 for (ptrWnd = ptrQueryWnd->child; ptrWnd ;ptrWnd = ptrWnd->next)
2449 if( ptrWnd->dwStyle & WS_VISIBLE )
2451 GetWindowRect32( ptrWnd->hwndSelf, &tempRect );
2452 if (PtInRect32( &tempRect, pt )) break;
2455 if(ptrWnd)
2457 TRACE(msg,"hwnd = %04x, %d %d - %d %d\n",
2458 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
2459 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
2460 if( !(ptrWnd->dwStyle & WS_DISABLED) )
2461 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
2464 if(bResult) return bResult;
2466 else wParam = 1;
2468 else wParam = 1;
2470 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
2472 ptrDragInfo->hScope = hQueryWnd;
2474 bResult = ( bNoSend )
2475 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
2476 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
2477 (WPARAM16)wParam ,(LPARAM) spDragInfo );
2478 if( !bResult )
2479 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
2481 return bResult;
2485 /*******************************************************************
2486 * DragDetect (USER.465)
2488 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
2490 POINT32 pt32;
2491 CONV_POINT16TO32( &pt, &pt32 );
2492 return DragDetect32( hWnd, pt32 );
2495 /*******************************************************************
2496 * DragDetect32 (USER32.151)
2498 BOOL32 WINAPI DragDetect32( HWND32 hWnd, POINT32 pt )
2500 MSG16 msg;
2501 RECT16 rect;
2503 rect.left = pt.x - wDragWidth;
2504 rect.right = pt.x + wDragWidth;
2506 rect.top = pt.y - wDragHeight;
2507 rect.bottom = pt.y + wDragHeight;
2509 SetCapture32(hWnd);
2511 while(1)
2513 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
2515 if( msg.message == WM_LBUTTONUP )
2517 ReleaseCapture();
2518 return 0;
2520 if( msg.message == WM_MOUSEMOVE )
2522 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
2524 ReleaseCapture();
2525 return 1;
2529 WaitMessage();
2531 return 0;
2534 /******************************************************************************
2535 * DragObject16 (USER.464)
2537 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
2538 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
2540 MSG16 msg;
2541 LPDRAGINFO lpDragInfo;
2542 SEGPTR spDragInfo;
2543 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
2544 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
2545 WND *wndPtr = WIN_FindWndPtr(hWnd);
2546 HCURSOR16 hCurrentCursor = 0;
2547 HWND16 hCurrentWnd = 0;
2549 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
2550 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
2552 if( !lpDragInfo || !spDragInfo ) return 0L;
2554 hBummer = LoadCursor16(0, IDC_BUMMER16);
2556 if( !hBummer || !wndPtr )
2558 GlobalFree16(hDragInfo);
2559 return 0L;
2562 if(hCursor)
2564 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
2566 GlobalFree16(hDragInfo);
2567 return 0L;
2570 if( hDragCursor == hCursor ) hDragCursor = 0;
2571 else hCursor = hDragCursor;
2573 hOldCursor = SetCursor32(hDragCursor);
2576 lpDragInfo->hWnd = hWnd;
2577 lpDragInfo->hScope = 0;
2578 lpDragInfo->wFlags = wObj;
2579 lpDragInfo->hList = szList; /* near pointer! */
2580 lpDragInfo->hOfStruct = hOfStruct;
2581 lpDragInfo->l = 0L;
2583 SetCapture32(hWnd);
2584 ShowCursor32( TRUE );
2588 do{ WaitMessage(); }
2589 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
2591 *(lpDragInfo+1) = *lpDragInfo;
2593 lpDragInfo->pt = msg.pt;
2595 /* update DRAGINFO struct */
2596 TRACE(msg,"lpDI->hScope = %04x\n",lpDragInfo->hScope);
2598 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
2599 hCurrentCursor = hCursor;
2600 else
2602 hCurrentCursor = hBummer;
2603 lpDragInfo->hScope = 0;
2605 if( hCurrentCursor )
2606 SetCursor32(hCurrentCursor);
2608 /* send WM_DRAGLOOP */
2609 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
2610 (LPARAM) spDragInfo );
2611 /* send WM_DRAGSELECT or WM_DRAGMOVE */
2612 if( hCurrentWnd != lpDragInfo->hScope )
2614 if( hCurrentWnd )
2615 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
2616 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
2617 HIWORD(spDragInfo)) );
2618 hCurrentWnd = lpDragInfo->hScope;
2619 if( hCurrentWnd )
2620 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
2622 else
2623 if( hCurrentWnd )
2624 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
2626 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
2628 ReleaseCapture();
2629 ShowCursor32( FALSE );
2631 if( hCursor )
2633 SetCursor32( hOldCursor );
2634 if (hDragCursor) DestroyCursor32( hDragCursor );
2637 if( hCurrentCursor != hBummer )
2638 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
2639 (WPARAM16)hWnd, (LPARAM)spDragInfo );
2640 else
2641 msg.lParam = 0;
2642 GlobalFree16(hDragInfo);
2644 return (DWORD)(msg.lParam);