Missing parentheses added.
[wine/multimedia.git] / windows / win.c
blobc3197914b5e8ebe59d3bd682f0247029c23111d8
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 "thread.h"
29 #include "process.h"
30 #include "debug.h"
31 #include "winerror.h"
32 #include "mdi.h"
34 extern WND_DRIVER X11DRV_WND_Driver;
36 /* Desktop window */
37 static WND *pWndDesktop = NULL;
39 static HWND32 hwndSysModal = 0;
41 static WORD wDragWidth = 4;
42 static WORD wDragHeight= 3;
44 /***********************************************************************
45 * WIN_FindWndPtr
47 * Return a pointer to the WND structure corresponding to a HWND.
49 WND * WIN_FindWndPtr( HWND32 hwnd )
51 WND * ptr;
53 if (!hwnd || HIWORD(hwnd)) return NULL;
54 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
55 if (ptr->dwMagic != WND_MAGIC) return NULL;
56 if (ptr->hwndSelf != hwnd)
58 ERR( win, "Can't happen: hwnd %04x self pointer is %04x\n",
59 hwnd, ptr->hwndSelf );
60 return NULL;
62 return ptr;
66 /***********************************************************************
67 * WIN_DumpWindow
69 * Dump the content of a window structure to stderr.
71 void WIN_DumpWindow( HWND32 hwnd )
73 WND *ptr;
74 char className[80];
75 int i;
77 if (!(ptr = WIN_FindWndPtr( hwnd )))
79 WARN( win, "%04x is not a window handle\n", hwnd );
80 return;
83 if (!GetClassName32A( hwnd, className, sizeof(className ) ))
84 strcpy( className, "#NULL#" );
86 TRACE( win, "Window %04x (%p):\n", hwnd, ptr );
87 DUMP( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
88 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
89 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
90 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
91 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
92 ptr->next, ptr->child, ptr->parent, ptr->owner,
93 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
94 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
95 ptr->dwStyle, ptr->dwExStyle, (UINT32)ptr->winproc,
96 ptr->text ? ptr->text : "",
97 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
98 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
99 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
100 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
102 if (ptr->class->cbWndExtra)
104 DUMP( "extra bytes:" );
105 for (i = 0; i < ptr->class->cbWndExtra; i++)
106 DUMP( " %02x", *((BYTE*)ptr->wExtra+i) );
107 DUMP( "\n" );
109 DUMP( "\n" );
113 /***********************************************************************
114 * WIN_WalkWindows
116 * Walk the windows tree and print each window on stderr.
118 void WIN_WalkWindows( HWND32 hwnd, int indent )
120 WND *ptr;
121 char className[80];
123 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop;
124 if (!ptr)
126 WARN( win, "Invalid window handle %04x\n", hwnd );
127 return;
130 if (!indent) /* first time around */
131 DUMP( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
132 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
133 " Text");
135 while (ptr)
137 DUMP( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
139 GlobalGetAtomName16(ptr->class->atomName,className,sizeof(className));
141 DUMP( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
142 (DWORD)ptr, ptr->hmemTaskQ, className,
143 (UINT32)ptr->dwStyle, (UINT32)ptr->winproc,
144 ptr->text?ptr->text:"<null>");
146 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
147 ptr = ptr->next;
151 /***********************************************************************
152 * WIN_UnlinkWindow
154 * Remove a window from the siblings linked list.
156 BOOL32 WIN_UnlinkWindow( HWND32 hwnd )
158 WND *wndPtr, **ppWnd;
160 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
161 ppWnd = &wndPtr->parent->child;
162 while (*ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
163 *ppWnd = wndPtr->next;
164 return TRUE;
168 /***********************************************************************
169 * WIN_LinkWindow
171 * Insert a window into the siblings linked list.
172 * The window is inserted after the specified window, which can also
173 * be specified as HWND_TOP or HWND_BOTTOM.
175 BOOL32 WIN_LinkWindow( HWND32 hwnd, HWND32 hwndInsertAfter )
177 WND *wndPtr, **ppWnd;
179 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
181 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
183 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
184 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
185 while (*ppWnd) ppWnd = &(*ppWnd)->next;
187 else /* Normal case */
189 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
190 if (!afterPtr) return FALSE;
191 ppWnd = &afterPtr->next;
193 wndPtr->next = *ppWnd;
194 *ppWnd = wndPtr;
195 return TRUE;
199 /***********************************************************************
200 * WIN_FindWinToRepaint
202 * Find a window that needs repaint.
204 HWND32 WIN_FindWinToRepaint( HWND32 hwnd, HQUEUE16 hQueue )
206 HWND32 hwndRet;
207 WND *pWnd = pWndDesktop;
209 /* Note: the desktop window never gets WM_PAINT messages
210 * The real reason why is because Windows DesktopWndProc
211 * does ValidateRgn inside WM_ERASEBKGND handler.
214 pWnd = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop->child;
216 for ( ; pWnd ; pWnd = pWnd->next )
218 if (!(pWnd->dwStyle & WS_VISIBLE))
220 TRACE(win, "skipping window %04x\n",
221 pWnd->hwndSelf );
222 continue;
224 if ((pWnd->hmemTaskQ == hQueue) &&
225 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))) break;
227 if (pWnd->child )
228 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
229 return hwndRet;
232 if (!pWnd) return 0;
234 hwndRet = pWnd->hwndSelf;
236 /* look among siblings if we got a transparent window */
237 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
238 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
240 pWnd = pWnd->next;
242 if (pWnd) hwndRet = pWnd->hwndSelf;
243 TRACE(win,"found %04x\n",hwndRet);
244 return hwndRet;
248 /***********************************************************************
249 * WIN_DestroyWindow
251 * Destroy storage associated to a window. "Internals" p.358
253 static WND* WIN_DestroyWindow( WND* wndPtr )
255 HWND32 hwnd = wndPtr->hwndSelf;
256 WND *pWnd;
258 TRACE(win, "%04x\n", wndPtr->hwndSelf );
260 #ifdef CONFIG_IPC
261 if (main_block)
262 DDE_DestroyWindow(wndPtr->hwndSelf);
263 #endif /* CONFIG_IPC */
265 /* free child windows */
267 while ((pWnd = wndPtr->child))
268 wndPtr->child = WIN_DestroyWindow( pWnd );
270 SendMessage32A( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
272 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
274 WINPOS_CheckInternalPos( hwnd );
275 if( hwnd == GetCapture32()) ReleaseCapture();
277 /* free resources associated with the window */
279 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
280 PROPERTY_RemoveWindowProps( wndPtr );
282 wndPtr->dwMagic = 0; /* Mark it as invalid */
284 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
286 if (wndPtr->hrgnUpdate > 1) DeleteObject32( wndPtr->hrgnUpdate );
287 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
290 /* toss stale messages from the queue */
292 if( wndPtr->hmemTaskQ )
294 int pos;
295 BOOL32 bPostQuit = FALSE;
296 WPARAM32 wQuitParam = 0;
297 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) GlobalLock16(wndPtr->hmemTaskQ);
299 while( (pos = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != -1 )
301 if( msgQ->messages[pos].msg.message == WM_QUIT )
303 bPostQuit = TRUE;
304 wQuitParam = msgQ->messages[pos].msg.wParam;
306 QUEUE_RemoveMsg(msgQ, pos);
308 /* repost WM_QUIT to make sure this app exits its message loop */
309 if( bPostQuit ) PostQuitMessage32(wQuitParam);
310 wndPtr->hmemTaskQ = 0;
313 if (!(wndPtr->dwStyle & WS_CHILD))
314 if (wndPtr->wIDmenu) DestroyMenu32( (HMENU32)wndPtr->wIDmenu );
315 if (wndPtr->hSysMenu) DestroyMenu32( wndPtr->hSysMenu );
316 wndPtr->pDriver->pDestroyWindow( wndPtr );
317 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
318 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
319 wndPtr->hwndSelf = 0;
320 wndPtr->class->cWindows--;
321 wndPtr->class = NULL;
322 pWnd = wndPtr->next;
324 USER_HEAP_FREE( hwnd );
325 return pWnd;
328 /***********************************************************************
329 * WIN_ResetQueueWindows
331 * Reset the queue of all the children of a given window.
332 * Return TRUE if something was done.
334 BOOL32 WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
336 BOOL32 ret = FALSE;
338 if (hNew) /* Set a new queue */
340 for (wnd = wnd->child; (wnd); wnd = wnd->next)
342 if (wnd->hmemTaskQ == hQueue)
344 wnd->hmemTaskQ = hNew;
345 ret = TRUE;
347 if (wnd->child)
348 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
351 else /* Queue is being destroyed */
353 while (wnd->child)
355 WND *tmp = wnd->child;
356 ret = FALSE;
357 while (tmp)
359 if (tmp->hmemTaskQ == hQueue)
361 DestroyWindow32( tmp->hwndSelf );
362 ret = TRUE;
363 break;
365 if (tmp->child && WIN_ResetQueueWindows(tmp->child,hQueue,0))
366 ret = TRUE;
367 else
368 tmp = tmp->next;
370 if (!ret) break;
373 return ret;
376 /***********************************************************************
377 * WIN_CreateDesktopWindow
379 * Create the desktop window.
381 BOOL32 WIN_CreateDesktopWindow(void)
383 CLASS *class;
384 HWND32 hwndDesktop;
386 TRACE(win,"Creating desktop window\n");
388 if (!ICONTITLE_Init() ||
389 !WINPOS_CreateInternalPosAtom() ||
390 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
391 return FALSE;
393 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
394 if (!hwndDesktop) return FALSE;
395 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
397 pWndDesktop->next = NULL;
398 pWndDesktop->child = NULL;
399 pWndDesktop->parent = NULL;
400 pWndDesktop->owner = NULL;
401 pWndDesktop->class = class;
402 pWndDesktop->dwMagic = WND_MAGIC;
403 pWndDesktop->hwndSelf = hwndDesktop;
404 pWndDesktop->hInstance = 0;
405 pWndDesktop->rectWindow.left = 0;
406 pWndDesktop->rectWindow.top = 0;
407 pWndDesktop->rectWindow.right = SYSMETRICS_CXSCREEN;
408 pWndDesktop->rectWindow.bottom = SYSMETRICS_CYSCREEN;
409 pWndDesktop->rectClient = pWndDesktop->rectWindow;
410 pWndDesktop->text = NULL;
411 pWndDesktop->hmemTaskQ = 0; /* Desktop does not belong to a task */
412 pWndDesktop->hrgnUpdate = 0;
413 pWndDesktop->hwndLastActive = hwndDesktop;
414 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
415 WS_CLIPSIBLINGS;
416 pWndDesktop->dwExStyle = 0;
417 pWndDesktop->dce = NULL;
418 pWndDesktop->pVScroll = NULL;
419 pWndDesktop->pHScroll = NULL;
420 pWndDesktop->pProp = NULL;
421 pWndDesktop->wIDmenu = 0;
422 pWndDesktop->helpContext = 0;
423 pWndDesktop->flags = 0;
424 pWndDesktop->hSysMenu = 0;
425 pWndDesktop->userdata = 0;
426 pWndDesktop->pDriver = &X11DRV_WND_Driver;
427 pWndDesktop->winproc = (WNDPROC16)class->winproc;
429 /* FIXME: How do we know if it should be Unicode or not */
430 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop, class, FALSE))
431 return FALSE;
433 SendMessage32A( hwndDesktop, WM_NCCREATE, 0, 0 );
434 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
435 return TRUE;
439 /***********************************************************************
440 * WIN_CreateWindowEx
442 * Implementation of CreateWindowEx().
444 static HWND32 WIN_CreateWindowEx( CREATESTRUCT32A *cs, ATOM classAtom,
445 BOOL32 win32, BOOL32 unicode )
447 CLASS *classPtr;
448 WND *wndPtr;
449 HWND16 hwnd, hwndLinkAfter;
450 POINT32 maxSize, maxPos, minTrack, maxTrack;
451 LRESULT (CALLBACK *localSend32)(HWND32, UINT32, WPARAM32, LPARAM);
453 TRACE(win, "%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
454 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
455 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
456 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
457 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
459 /* Find the parent window */
461 if (cs->hwndParent)
463 /* Make sure parent is valid */
464 if (!IsWindow32( cs->hwndParent ))
466 WARN( win, "Bad parent %04x\n", cs->hwndParent );
467 return 0;
469 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
470 WARN( win, "No parent for child window\n" );
471 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
474 /* Find the window class */
475 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
477 char buffer[256];
478 GlobalGetAtomName32A( classAtom, buffer, sizeof(buffer) );
479 WARN( win, "Bad class '%s'\n", buffer );
480 return 0;
483 /* Fix the coordinates */
485 if (cs->x == CW_USEDEFAULT32)
487 PDB32 *pdb = PROCESS_Current();
488 if ( !(cs->style & (WS_CHILD | WS_POPUP))
489 && (pdb->env_db->startup_info->dwFlags & STARTF_USEPOSITION) )
491 cs->x = pdb->env_db->startup_info->dwX;
492 cs->y = pdb->env_db->startup_info->dwY;
494 else
496 cs->x = 0;
497 cs->y = 0;
500 if (cs->cx == CW_USEDEFAULT32)
502 PDB32 *pdb = PROCESS_Current();
503 if ( !(cs->style & (WS_CHILD | WS_POPUP))
504 && (pdb->env_db->startup_info->dwFlags & STARTF_USESIZE) )
506 cs->cx = pdb->env_db->startup_info->dwXSize;
507 cs->cy = pdb->env_db->startup_info->dwYSize;
509 else
511 cs->cx = 600; /* FIXME */
512 cs->cy = 400;
516 /* Create the window structure */
518 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
519 - sizeof(wndPtr->wExtra) )))
521 TRACE(win, "out of memory\n" );
522 return 0;
525 /* Fill the window structure */
527 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
528 wndPtr->next = NULL;
529 wndPtr->child = NULL;
531 if ((cs->style & WS_CHILD) && cs->hwndParent)
533 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
534 wndPtr->owner = NULL;
536 else
538 wndPtr->parent = pWndDesktop;
539 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
540 wndPtr->owner = NULL;
541 else
542 wndPtr->owner = WIN_GetTopParentPtr(WIN_FindWndPtr(cs->hwndParent));
545 wndPtr->pDriver = &X11DRV_WND_Driver;
546 wndPtr->window = 0;
547 wndPtr->class = classPtr;
548 wndPtr->winproc = classPtr->winproc;
549 wndPtr->dwMagic = WND_MAGIC;
550 wndPtr->hwndSelf = hwnd;
551 wndPtr->hInstance = cs->hInstance;
552 wndPtr->text = NULL;
553 wndPtr->hmemTaskQ = GetTaskQueue(0);
554 wndPtr->hrgnUpdate = 0;
555 wndPtr->hwndLastActive = hwnd;
556 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
557 wndPtr->dwExStyle = cs->dwExStyle;
558 wndPtr->wIDmenu = 0;
559 wndPtr->helpContext = 0;
560 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
561 wndPtr->pVScroll = NULL;
562 wndPtr->pHScroll = NULL;
563 wndPtr->pProp = NULL;
564 wndPtr->userdata = 0;
565 wndPtr->expose_event = NULL;
566 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
567 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
569 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
571 /* Call the WH_CBT hook */
573 hwndLinkAfter = (cs->style & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
575 if (HOOK_IsHooked( WH_CBT ))
577 CBT_CREATEWND32A cbtc;
578 LRESULT ret;
580 cbtc.lpcs = cs;
581 cbtc.hwndInsertAfter = hwndLinkAfter;
582 ret = unicode ? HOOK_CallHooks32W(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
583 : HOOK_CallHooks32A(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
584 if (ret)
586 TRACE(win, "CBT-hook returned 0\n");
587 USER_HEAP_FREE( hwnd );
588 return 0;
592 /* Increment class window counter */
594 classPtr->cWindows++;
596 /* Correct the window style */
598 if (!(cs->style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
600 wndPtr->dwStyle |= WS_CAPTION | WS_CLIPSIBLINGS;
601 wndPtr->flags |= WIN_NEED_SIZE;
603 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
605 /* Get class or window DC if needed */
607 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
608 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
609 else wndPtr->dce = NULL;
611 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
613 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
615 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
616 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
617 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
618 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
619 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
622 if(cs->style & WS_CHILD)
624 if(cs->cx < 0) cs->cx = 0;
625 if(cs->cy < 0) cs->cy = 0;
627 else
629 if (cs->cx <= 0) cs->cx = 1;
630 if (cs->cy <= 0) cs->cy = 1;
633 wndPtr->rectWindow.left = cs->x;
634 wndPtr->rectWindow.top = cs->y;
635 wndPtr->rectWindow.right = cs->x + cs->cx;
636 wndPtr->rectWindow.bottom = cs->y + cs->cy;
637 wndPtr->rectClient = wndPtr->rectWindow;
639 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
640 return FALSE;
642 /* Set the window menu */
644 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
646 if (cs->hMenu) SetMenu32(hwnd, cs->hMenu);
647 else
649 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
650 if (classPtr->menuNameA)
651 cs->hMenu = HIWORD(classPtr->menuNameA) ?
652 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
653 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
654 #else
655 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
656 if (menuName)
658 if (HIWORD(cs->hInstance))
659 cs->hMenu = LoadMenu32A(cs->hInstance,PTR_SEG_TO_LIN(menuName));
660 else
661 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
663 if (cs->hMenu) SetMenu32( hwnd, cs->hMenu );
665 #endif
668 else wndPtr->wIDmenu = (UINT32)cs->hMenu;
670 /* Send the WM_CREATE message
671 * Perhaps we shouldn't allow width/height changes as well.
672 * See p327 in "Internals".
675 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
677 localSend32 = unicode ? SendMessage32W : SendMessage32A;
678 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
680 /* Insert the window in the linked list */
682 WIN_LinkWindow( hwnd, hwndLinkAfter );
684 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
685 NULL, NULL, 0, &wndPtr->rectClient );
686 OffsetRect32(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
687 maxPos.y - wndPtr->rectWindow.top);
688 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
690 /* Send the size messages */
692 if (!(wndPtr->flags & WIN_NEED_SIZE))
694 /* send it anyway */
695 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
696 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
697 WARN(win,"sending bogus WM_SIZE message 0x%08lx\n",
698 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
699 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
700 SendMessage32A( hwnd, WM_SIZE, SIZE_RESTORED,
701 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
702 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
703 SendMessage32A( hwnd, WM_MOVE, 0,
704 MAKELONG( wndPtr->rectClient.left,
705 wndPtr->rectClient.top ) );
708 /* Show the window, maximizing or minimizing if needed */
710 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
712 RECT16 newPos;
713 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
714 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
715 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
716 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow32()) ? SWP_NOACTIVATE : 0;
717 SetWindowPos32( hwnd, 0, newPos.left, newPos.top,
718 newPos.right, newPos.bottom, SWP_FRAMECHANGED | swFlag );
721 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
723 /* Notify the parent window only */
725 SendMessage32A( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
726 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
727 if( !IsWindow32(hwnd) ) return 0;
730 if (cs->style & WS_VISIBLE) ShowWindow32( hwnd, SW_SHOW );
732 /* Call WH_SHELL hook */
734 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
735 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
737 TRACE(win, "created window %04x\n", hwnd);
738 return hwnd;
740 WIN_UnlinkWindow( hwnd );
743 /* Abort window creation */
745 WARN(win, "aborted by WM_xxCREATE!\n");
746 WIN_DestroyWindow( wndPtr );
747 return 0;
751 /***********************************************************************
752 * CreateWindow16 (USER.41)
754 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
755 DWORD style, INT16 x, INT16 y, INT16 width,
756 INT16 height, HWND16 parent, HMENU16 menu,
757 HINSTANCE16 instance, LPVOID data )
759 return CreateWindowEx16( 0, className, windowName, style,
760 x, y, width, height, parent, menu, instance, data );
764 /***********************************************************************
765 * CreateWindowEx16 (USER.452)
767 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
768 LPCSTR windowName, DWORD style, INT16 x,
769 INT16 y, INT16 width, INT16 height,
770 HWND16 parent, HMENU16 menu,
771 HINSTANCE16 instance, LPVOID data )
773 ATOM classAtom;
774 CREATESTRUCT32A cs;
776 /* Find the class atom */
778 if (!(classAtom = GlobalFindAtom32A( className )))
780 fprintf( stderr, "CreateWindowEx16: bad class name " );
781 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
782 else fprintf( stderr, "'%s'\n", className );
783 return 0;
786 /* Fix the coordinates */
788 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)x;
789 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)y;
790 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)width;
791 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)height;
793 /* Create the window */
795 cs.lpCreateParams = data;
796 cs.hInstance = (HINSTANCE32)instance;
797 cs.hMenu = (HMENU32)menu;
798 cs.hwndParent = (HWND32)parent;
799 cs.style = style;
800 cs.lpszName = windowName;
801 cs.lpszClass = className;
802 cs.dwExStyle = exStyle;
803 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
807 /***********************************************************************
808 * CreateWindowEx32A (USER32.83)
810 HWND32 WINAPI CreateWindowEx32A( DWORD exStyle, LPCSTR className,
811 LPCSTR windowName, DWORD style, INT32 x,
812 INT32 y, INT32 width, INT32 height,
813 HWND32 parent, HMENU32 menu,
814 HINSTANCE32 instance, LPVOID data )
816 ATOM classAtom;
817 CREATESTRUCT32A cs;
819 if(exStyle & WS_EX_MDICHILD)
820 return MDI_CreateMDIWindow32A(className, windowName, style, x, y, width, height, parent, instance, data);
821 /* Find the class atom */
823 if (!(classAtom = GlobalFindAtom32A( className )))
825 fprintf( stderr, "CreateWindowEx32A: bad class name " );
826 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
827 else fprintf( stderr, "'%s'\n", className );
828 return 0;
831 /* Create the window */
833 cs.lpCreateParams = data;
834 cs.hInstance = instance;
835 cs.hMenu = menu;
836 cs.hwndParent = parent;
837 cs.x = x;
838 cs.y = y;
839 cs.cx = width;
840 cs.cy = height;
841 cs.style = style;
842 cs.lpszName = windowName;
843 cs.lpszClass = className;
844 cs.dwExStyle = exStyle;
845 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
849 /***********************************************************************
850 * CreateWindowEx32W (USER32.84)
852 HWND32 WINAPI CreateWindowEx32W( DWORD exStyle, LPCWSTR className,
853 LPCWSTR windowName, DWORD style, INT32 x,
854 INT32 y, INT32 width, INT32 height,
855 HWND32 parent, HMENU32 menu,
856 HINSTANCE32 instance, LPVOID data )
858 ATOM classAtom;
859 CREATESTRUCT32W cs;
861 if(exStyle & WS_EX_MDICHILD)
862 return MDI_CreateMDIWindow32W(className, windowName, style, x, y, width, height, parent, instance, data);
864 /* Find the class atom */
866 if (!(classAtom = GlobalFindAtom32W( className )))
868 if (HIWORD(className))
870 LPSTR cn = HEAP_strdupWtoA( GetProcessHeap(), 0, className );
871 WARN( win, "Bad class name '%s'\n",cn);
872 HeapFree( GetProcessHeap(), 0, cn );
874 else
875 WARN( win, "Bad class name %p\n", className );
876 return 0;
879 /* Create the window */
881 cs.lpCreateParams = data;
882 cs.hInstance = instance;
883 cs.hMenu = menu;
884 cs.hwndParent = parent;
885 cs.x = x;
886 cs.y = y;
887 cs.cx = width;
888 cs.cy = height;
889 cs.style = style;
890 cs.lpszName = windowName;
891 cs.lpszClass = className;
892 cs.dwExStyle = exStyle;
893 /* Note: we rely on the fact that CREATESTRUCT32A and */
894 /* CREATESTRUCT32W have the same layout. */
895 return WIN_CreateWindowEx( (CREATESTRUCT32A *)&cs, classAtom, TRUE, TRUE );
899 /***********************************************************************
900 * WIN_CheckFocus
902 static void WIN_CheckFocus( WND* pWnd )
904 if( GetFocus16() == pWnd->hwndSelf )
905 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
908 /***********************************************************************
909 * WIN_SendDestroyMsg
911 static void WIN_SendDestroyMsg( WND* pWnd )
913 WIN_CheckFocus(pWnd);
915 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret32();
916 if( !pWnd->window ) CLIPBOARD_GetDriver()->pResetOwner( pWnd );
918 SendMessage32A( pWnd->hwndSelf, WM_DESTROY, 0, 0);
920 if( IsWindow32(pWnd->hwndSelf) )
922 WND* pChild = pWnd->child;
923 while( pChild )
925 WIN_SendDestroyMsg( pChild );
926 pChild = pChild->next;
928 WIN_CheckFocus(pWnd);
930 else
931 WARN(win, "\tdestroyed itself while in WM_DESTROY!\n");
935 /***********************************************************************
936 * DestroyWindow16 (USER.53)
938 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
940 return DestroyWindow32(hwnd);
944 /***********************************************************************
945 * DestroyWindow32 (USER32.135)
947 BOOL32 WINAPI DestroyWindow32( HWND32 hwnd )
949 WND * wndPtr;
951 TRACE(win, "(%04x)\n", hwnd);
953 /* Initialization */
955 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
956 if (wndPtr == pWndDesktop) return FALSE; /* Can't destroy desktop */
958 /* Call hooks */
960 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
961 return FALSE;
963 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
965 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
966 /* FIXME: clean up palette - see "Internals" p.352 */
969 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
970 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
972 /* Notify the parent window only */
973 SendMessage32A( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
974 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
975 if( !IsWindow32(hwnd) ) return TRUE;
978 if( wndPtr->window ) CLIPBOARD_GetDriver()->pResetOwner( wndPtr ); /* before the window is unmapped */
980 /* Hide the window */
982 if (wndPtr->dwStyle & WS_VISIBLE)
984 SetWindowPos32( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
985 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
986 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
987 if (!IsWindow32(hwnd)) return TRUE;
990 /* Recursively destroy owned windows */
992 if( !(wndPtr->dwStyle & WS_CHILD) )
994 /* make sure top menu popup doesn't get destroyed */
995 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
997 for (;;)
999 WND *siblingPtr = wndPtr->parent->child; /* First sibling */
1000 while (siblingPtr)
1002 if (siblingPtr->owner == wndPtr)
1004 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1005 break;
1006 else
1007 siblingPtr->owner = NULL;
1009 siblingPtr = siblingPtr->next;
1011 if (siblingPtr) DestroyWindow32( siblingPtr->hwndSelf );
1012 else break;
1015 if( !Options.managed || EVENT_CheckFocus() )
1016 WINPOS_ActivateOtherWindow(wndPtr);
1018 if( wndPtr->owner &&
1019 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1020 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1023 /* Send destroy messages */
1025 WIN_SendDestroyMsg( wndPtr );
1026 if (!IsWindow32(hwnd)) return TRUE;
1028 /* Unlink now so we won't bother with the children later on */
1030 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1032 /* Destroy the window storage */
1034 WIN_DestroyWindow( wndPtr );
1035 return TRUE;
1039 /***********************************************************************
1040 * CloseWindow16 (USER.43)
1042 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1044 return CloseWindow32( hwnd );
1048 /***********************************************************************
1049 * CloseWindow32 (USER32.56)
1051 BOOL32 WINAPI CloseWindow32( HWND32 hwnd )
1053 WND * wndPtr = WIN_FindWndPtr( hwnd );
1054 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD)) return FALSE;
1055 ShowWindow32( hwnd, SW_MINIMIZE );
1056 return TRUE;
1060 /***********************************************************************
1061 * OpenIcon16 (USER.44)
1063 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1065 return OpenIcon32( hwnd );
1069 /***********************************************************************
1070 * OpenIcon32 (USER32.410)
1072 BOOL32 WINAPI OpenIcon32( HWND32 hwnd )
1074 if (!IsIconic32( hwnd )) return FALSE;
1075 ShowWindow32( hwnd, SW_SHOWNORMAL );
1076 return TRUE;
1080 /***********************************************************************
1081 * WIN_FindWindow
1083 * Implementation of FindWindow() and FindWindowEx().
1085 static HWND32 WIN_FindWindow( HWND32 parent, HWND32 child, ATOM className,
1086 LPCSTR title )
1088 WND *pWnd;
1089 CLASS *pClass = NULL;
1091 if (child)
1093 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1094 if (parent)
1096 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent)) return 0;
1098 else if (pWnd->parent != pWndDesktop) return 0;
1099 pWnd = pWnd->next;
1101 else
1103 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : pWndDesktop)) return 0;
1104 pWnd = pWnd->child;
1106 if (!pWnd) return 0;
1108 /* For a child window, all siblings will have the same hInstance, */
1109 /* so we can look for the class once and for all. */
1111 if (className && (pWnd->dwStyle & WS_CHILD))
1113 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1114 return 0;
1118 for ( ; pWnd; pWnd = pWnd->next)
1120 if (className && !(pWnd->dwStyle & WS_CHILD))
1122 if (!(pClass = CLASS_FindClassByAtom( className, GetExePtr(pWnd->hInstance))))
1123 continue; /* Skip this window */
1126 if (pClass && (pWnd->class != pClass))
1127 continue; /* Not the right class */
1129 /* Now check the title */
1131 if (!title) return pWnd->hwndSelf;
1132 if (pWnd->text && !strcmp( pWnd->text, title )) return pWnd->hwndSelf;
1134 return 0;
1139 /***********************************************************************
1140 * FindWindow16 (USER.50)
1142 HWND16 WINAPI FindWindow16( SEGPTR className, LPCSTR title )
1144 return FindWindowEx16( 0, 0, className, title );
1148 /***********************************************************************
1149 * FindWindowEx16 (USER.427)
1151 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child,
1152 SEGPTR className, LPCSTR title )
1154 ATOM atom = 0;
1156 TRACE(win, "%04x %04x '%s' '%s'\n", parent,
1157 child, HIWORD(className)?(char *)PTR_SEG_TO_LIN(className):"",
1158 title ? title : "");
1160 if (className)
1162 /* If the atom doesn't exist, then no class */
1163 /* with this name exists either. */
1164 if (!(atom = GlobalFindAtom16( className ))) return 0;
1166 return WIN_FindWindow( parent, child, atom, title );
1170 /***********************************************************************
1171 * FindWindow32A (USER32.198)
1173 HWND32 WINAPI FindWindow32A( LPCSTR className, LPCSTR title )
1175 HWND32 ret = FindWindowEx32A( 0, 0, className, title );
1176 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1177 return ret;
1181 /***********************************************************************
1182 * FindWindowEx32A (USER32.199)
1184 HWND32 WINAPI FindWindowEx32A( HWND32 parent, HWND32 child,
1185 LPCSTR className, LPCSTR title )
1187 ATOM atom = 0;
1189 if (className)
1191 /* If the atom doesn't exist, then no class */
1192 /* with this name exists either. */
1193 if (!(atom = GlobalFindAtom32A( className )))
1195 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1196 return 0;
1199 return WIN_FindWindow( parent, child, atom, title );
1203 /***********************************************************************
1204 * FindWindowEx32W (USER32.200)
1206 HWND32 WINAPI FindWindowEx32W( HWND32 parent, HWND32 child,
1207 LPCWSTR className, LPCWSTR title )
1209 ATOM atom = 0;
1210 char *buffer;
1211 HWND32 hwnd;
1213 if (className)
1215 /* If the atom doesn't exist, then no class */
1216 /* with this name exists either. */
1217 if (!(atom = GlobalFindAtom32W( className )))
1219 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1220 return 0;
1223 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1224 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1225 HeapFree( GetProcessHeap(), 0, buffer );
1226 return hwnd;
1230 /***********************************************************************
1231 * FindWindow32W (USER32.201)
1233 HWND32 WINAPI FindWindow32W( LPCWSTR className, LPCWSTR title )
1235 return FindWindowEx32W( 0, 0, className, title );
1239 /**********************************************************************
1240 * WIN_GetDesktop
1242 WND *WIN_GetDesktop(void)
1244 return pWndDesktop;
1248 /**********************************************************************
1249 * GetDesktopWindow16 (USER.286)
1251 HWND16 WINAPI GetDesktopWindow16(void)
1253 return (HWND16)pWndDesktop->hwndSelf;
1257 /**********************************************************************
1258 * GetDesktopWindow32 (USER32.232)
1260 HWND32 WINAPI GetDesktopWindow32(void)
1262 return pWndDesktop->hwndSelf;
1266 /**********************************************************************
1267 * GetDesktopHwnd (USER.278)
1269 * Exactly the same thing as GetDesktopWindow(), but not documented.
1270 * Don't ask me why...
1272 HWND16 WINAPI GetDesktopHwnd(void)
1274 return (HWND16)pWndDesktop->hwndSelf;
1278 /*******************************************************************
1279 * EnableWindow16 (USER.34)
1281 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1283 return EnableWindow32( hwnd, enable );
1287 /*******************************************************************
1288 * EnableWindow32 (USER32.172)
1290 BOOL32 WINAPI EnableWindow32( HWND32 hwnd, BOOL32 enable )
1292 WND *wndPtr;
1294 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1295 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1297 /* Enable window */
1298 wndPtr->dwStyle &= ~WS_DISABLED;
1299 SendMessage32A( hwnd, WM_ENABLE, TRUE, 0 );
1300 return TRUE;
1302 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1304 /* Disable window */
1305 wndPtr->dwStyle |= WS_DISABLED;
1306 if ((hwnd == GetFocus32()) || IsChild32( hwnd, GetFocus32() ))
1307 SetFocus32( 0 ); /* A disabled window can't have the focus */
1308 if ((hwnd == GetCapture32()) || IsChild32( hwnd, GetCapture32() ))
1309 ReleaseCapture(); /* A disabled window can't capture the mouse */
1310 SendMessage32A( hwnd, WM_ENABLE, FALSE, 0 );
1311 return FALSE;
1313 return ((wndPtr->dwStyle & WS_DISABLED) != 0);
1317 /***********************************************************************
1318 * IsWindowEnabled16 (USER.35)
1320 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1322 return IsWindowEnabled32(hWnd);
1326 /***********************************************************************
1327 * IsWindowEnabled32 (USER32.349)
1329 BOOL32 WINAPI IsWindowEnabled32(HWND32 hWnd)
1331 WND * wndPtr;
1333 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1334 return !(wndPtr->dwStyle & WS_DISABLED);
1338 /***********************************************************************
1339 * IsWindowUnicode (USER32.350)
1341 BOOL32 WINAPI IsWindowUnicode( HWND32 hwnd )
1343 WND * wndPtr;
1345 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1346 return (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1350 /**********************************************************************
1351 * GetWindowWord16 (USER.133)
1353 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1355 return GetWindowWord32( hwnd, offset );
1359 /**********************************************************************
1360 * GetWindowWord32 (USER32.314)
1362 WORD WINAPI GetWindowWord32( HWND32 hwnd, INT32 offset )
1364 WND * wndPtr = WIN_FindWndPtr( hwnd );
1365 if (!wndPtr) return 0;
1366 if (offset >= 0)
1368 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1370 WARN( win, "Invalid offset %d\n", offset );
1371 return 0;
1373 return *(WORD *)(((char *)wndPtr->wExtra) + offset);
1375 switch(offset)
1377 case GWW_ID:
1378 if (HIWORD(wndPtr->wIDmenu))
1379 WARN( win,"GWW_ID: discards high bits of 0x%08x!\n",
1380 wndPtr->wIDmenu);
1381 return (WORD)wndPtr->wIDmenu;
1382 case GWW_HWNDPARENT:
1383 return wndPtr->parent ?
1384 wndPtr->parent->hwndSelf : (
1385 wndPtr->owner ?
1386 wndPtr->owner->hwndSelf :
1388 case GWW_HINSTANCE:
1389 if (HIWORD(wndPtr->hInstance))
1390 WARN(win,"GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1391 wndPtr->hInstance);
1392 return (WORD)wndPtr->hInstance;
1393 default:
1394 WARN( win, "Invalid offset %d\n", offset );
1395 return 0;
1400 /**********************************************************************
1401 * WIN_GetWindowInstance
1403 HINSTANCE32 WIN_GetWindowInstance( HWND32 hwnd )
1405 WND * wndPtr = WIN_FindWndPtr( hwnd );
1406 if (!wndPtr) return (HINSTANCE32)0;
1407 return wndPtr->hInstance;
1411 /**********************************************************************
1412 * SetWindowWord16 (USER.134)
1414 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1416 return SetWindowWord32( hwnd, offset, newval );
1420 /**********************************************************************
1421 * SetWindowWord32 (USER32.524)
1423 WORD WINAPI SetWindowWord32( HWND32 hwnd, INT32 offset, WORD newval )
1425 WORD *ptr, retval;
1426 WND * wndPtr = WIN_FindWndPtr( hwnd );
1427 if (!wndPtr) return 0;
1428 if (offset >= 0)
1430 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1432 WARN( win, "Invalid offset %d\n", offset );
1433 return 0;
1435 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1437 else switch(offset)
1439 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1440 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1441 case GWW_HWNDPARENT: return SetParent32( hwnd, newval );
1442 default:
1443 WARN( win, "Invalid offset %d\n", offset );
1444 return 0;
1446 retval = *ptr;
1447 *ptr = newval;
1448 return retval;
1452 /**********************************************************************
1453 * WIN_GetWindowLong
1455 * Helper function for GetWindowLong().
1457 static LONG WIN_GetWindowLong( HWND32 hwnd, INT32 offset, WINDOWPROCTYPE type )
1459 LONG retval;
1460 WND * wndPtr = WIN_FindWndPtr( hwnd );
1461 if (!wndPtr) return 0;
1462 if (offset >= 0)
1464 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1466 WARN( win, "Invalid offset %d\n", offset );
1467 return 0;
1469 retval = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1470 /* Special case for dialog window procedure */
1471 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1472 return (LONG)WINPROC_GetProc( (HWINDOWPROC)retval, type );
1473 return retval;
1475 switch(offset)
1477 case GWL_USERDATA: return wndPtr->userdata;
1478 case GWL_STYLE: return wndPtr->dwStyle;
1479 case GWL_EXSTYLE: return wndPtr->dwExStyle;
1480 case GWL_ID: return (LONG)wndPtr->wIDmenu;
1481 case GWL_WNDPROC: return (LONG)WINPROC_GetProc( wndPtr->winproc,
1482 type );
1483 case GWL_HWNDPARENT: return wndPtr->parent ?
1484 (HWND32)wndPtr->parent->hwndSelf : 0;
1485 case GWL_HINSTANCE: return wndPtr->hInstance;
1486 default:
1487 WARN( win, "Unknown offset %d\n", offset );
1489 return 0;
1493 /**********************************************************************
1494 * WIN_SetWindowLong
1496 * Helper function for SetWindowLong().
1498 * 0 is the failure code. However, in the case of failure SetLastError
1499 * must be set to distinguish between a 0 return value and a failure.
1501 * FIXME: The error values for SetLastError may not be right. Can
1502 * someone check with the real thing?
1504 static LONG WIN_SetWindowLong( HWND32 hwnd, INT32 offset, LONG newval,
1505 WINDOWPROCTYPE type )
1507 LONG *ptr, retval;
1508 WND * wndPtr = WIN_FindWndPtr( hwnd );
1509 STYLESTRUCT style;
1511 TRACE(win,"%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1513 if (!wndPtr)
1515 /* Is this the right error? */
1516 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1517 return 0;
1520 if (offset >= 0)
1522 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1524 WARN( win, "Invalid offset %d\n", offset );
1526 /* Is this the right error? */
1527 SetLastError( ERROR_OUTOFMEMORY );
1529 return 0;
1531 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1532 /* Special case for dialog window procedure */
1533 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1535 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1536 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1537 type, WIN_PROC_WINDOW );
1538 return retval;
1541 else switch(offset)
1543 case GWL_ID:
1544 ptr = (DWORD*)&wndPtr->wIDmenu;
1545 break;
1546 case GWL_HINSTANCE:
1547 return SetWindowWord32( hwnd, offset, newval );
1548 case GWL_WNDPROC:
1549 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1550 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1551 type, WIN_PROC_WINDOW );
1552 return retval;
1553 case GWL_STYLE:
1554 style.styleOld = wndPtr->dwStyle;
1555 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
1556 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
1558 if (wndPtr->flags & WIN_ISWIN32)
1559 SendMessage32A(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1560 wndPtr->dwStyle = style.styleNew;
1561 if (wndPtr->flags & WIN_ISWIN32)
1562 SendMessage32A(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1563 return style.styleOld;
1565 case GWL_USERDATA:
1566 ptr = &wndPtr->userdata;
1567 break;
1568 case GWL_EXSTYLE:
1569 style.styleOld = wndPtr->dwExStyle;
1570 style.styleNew = newval;
1571 if (wndPtr->flags & WIN_ISWIN32)
1572 SendMessage32A(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1573 wndPtr->dwExStyle = newval;
1574 if (wndPtr->flags & WIN_ISWIN32)
1575 SendMessage32A(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1576 return style.styleOld;
1578 default:
1579 WARN( win, "Invalid offset %d\n", offset );
1581 /* Don't think this is right error but it should do */
1582 SetLastError( ERROR_OUTOFMEMORY );
1584 return 0;
1586 retval = *ptr;
1587 *ptr = newval;
1588 return retval;
1592 /**********************************************************************
1593 * GetWindowLong16 (USER.135)
1595 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1597 return WIN_GetWindowLong( (HWND32)hwnd, offset, WIN_PROC_16 );
1601 /**********************************************************************
1602 * GetWindowLong32A (USER32.305)
1604 LONG WINAPI GetWindowLong32A( HWND32 hwnd, INT32 offset )
1606 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1610 /**********************************************************************
1611 * GetWindowLong32W (USER32.306)
1613 LONG WINAPI GetWindowLong32W( HWND32 hwnd, INT32 offset )
1615 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1619 /**********************************************************************
1620 * SetWindowLong16 (USER.136)
1622 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1624 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1628 /**********************************************************************
1629 * SetWindowLong32A (USER32.517)
1631 LONG WINAPI SetWindowLong32A( HWND32 hwnd, INT32 offset, LONG newval )
1633 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1637 /**********************************************************************
1638 * SetWindowLong32W (USER32.518) Set window attribute
1640 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
1641 * value in a window's extra memory.
1643 * The _hwnd_ parameter specifies the window. is the handle to a
1644 * window that has extra memory. The _newval_ parameter contains the
1645 * new attribute or extra memory value. If positive, the _offset_
1646 * parameter is the byte-addressed location in the window's extra
1647 * memory to set. If negative, _offset_ specifies the window
1648 * attribute to set, and should be one of the following values:
1650 * GWL_EXSTYLE The window's extended window style
1652 * GWL_STYLE The window's window style.
1654 * GWL_WNDPROC Pointer to the window's window procedure.
1656 * GWL_HINSTANCE The window's pplication instance handle.
1658 * GWL_ID The window's identifier.
1660 * GWL_USERDATA The window's user-specified data.
1662 * If the window is a dialog box, the _offset_ parameter can be one of
1663 * the following values:
1665 * DWL_DLGPROC The address of the window's dialog box procedure.
1667 * DWL_MSGRESULT The return value of a message
1668 * that the dialog box procedure processed.
1670 * DWL_USER Application specific information.
1672 * RETURNS
1674 * If successful, returns the previous value located at _offset_. Otherwise,
1675 * returns 0.
1677 * NOTES
1679 * Extra memory for a window class is specified by a nonzero cbWndExtra
1680 * parameter of the WNDCLASS structure passed to RegisterClass() at the
1681 * time of class creation.
1683 * Using GWL_WNDPROC to set a new window procedure effectively creates
1684 * a window subclass. Use CallWindowProc() in the new windows procedure
1685 * to pass messages to the superclass's window procedure.
1687 * The user data is reserved for use by the application which created
1688 * the window.
1690 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
1691 * instead, call the EnableWindow() function to change the window's
1692 * disabled state.
1694 * Do not use GWL_HWNDPARENT to reset the window's parent, use
1695 * SetParent() instead.
1697 * BUGS
1699 * GWL_STYLE does not dispatch WM_STYLE_... messages.
1701 * CONFORMANCE
1703 * ECMA-234, Win32
1706 LONG WINAPI SetWindowLong32W(
1707 HWND32 hwnd, /* window to alter */
1708 INT32 offset, /* offset, in bytes, of location to alter */
1709 LONG newval /* new value of location */
1711 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1715 /*******************************************************************
1716 * GetWindowText16 (USER.36)
1718 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
1720 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1724 /*******************************************************************
1725 * GetWindowText32A (USER32.309)
1727 INT32 WINAPI GetWindowText32A( HWND32 hwnd, LPSTR lpString, INT32 nMaxCount )
1729 return (INT32)SendMessage32A( hwnd, WM_GETTEXT, nMaxCount,
1730 (LPARAM)lpString );
1733 /*******************************************************************
1734 * InternalGetWindowText (USER32.326)
1736 INT32 WINAPI InternalGetWindowText(HWND32 hwnd,LPWSTR lpString,INT32 nMaxCount )
1738 FIXME(win,"(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
1739 return GetWindowText32W(hwnd,lpString,nMaxCount);
1743 /*******************************************************************
1744 * GetWindowText32W (USER32.312)
1746 INT32 WINAPI GetWindowText32W( HWND32 hwnd, LPWSTR lpString, INT32 nMaxCount )
1748 return (INT32)SendMessage32W( hwnd, WM_GETTEXT, nMaxCount,
1749 (LPARAM)lpString );
1753 /*******************************************************************
1754 * SetWindowText16 (USER.37)
1756 void WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
1758 SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1762 /*******************************************************************
1763 * SetWindowText32A (USER32.521)
1765 void WINAPI SetWindowText32A( HWND32 hwnd, LPCSTR lpString )
1767 SendMessage32A( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1771 /*******************************************************************
1772 * SetWindowText32W (USER32.523)
1774 void WINAPI SetWindowText32W( HWND32 hwnd, LPCWSTR lpString )
1776 SendMessage32W( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1780 /*******************************************************************
1781 * GetWindowTextLength16 (USER.38)
1783 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
1785 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1789 /*******************************************************************
1790 * GetWindowTextLength32A (USER32.310)
1792 INT32 WINAPI GetWindowTextLength32A( HWND32 hwnd )
1794 return SendMessage32A( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1797 /*******************************************************************
1798 * GetWindowTextLength32W (USER32.311)
1800 INT32 WINAPI GetWindowTextLength32W( HWND32 hwnd )
1802 return SendMessage32W( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1806 /*******************************************************************
1807 * IsWindow16 (USER.47)
1809 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
1811 return IsWindow32( hwnd );
1814 void WINAPI WIN16_IsWindow16( CONTEXT *context )
1816 WORD *stack = PTR_SEG_OFF_TO_LIN(SS_reg(context), SP_reg(context));
1817 HWND16 hwnd = (HWND16)stack[2];
1819 AX_reg(context) = IsWindow32( hwnd );
1820 ES_reg(context) = USER_HeapSel;
1824 /*******************************************************************
1825 * IsWindow32 (USER32.348)
1827 BOOL32 WINAPI IsWindow32( HWND32 hwnd )
1829 WND * wndPtr = WIN_FindWndPtr( hwnd );
1830 return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
1834 /*****************************************************************
1835 * GetParent16 (USER.46)
1837 HWND16 WINAPI GetParent16( HWND16 hwnd )
1839 return (HWND16)GetParent32( hwnd );
1843 /*****************************************************************
1844 * GetParent32 (USER32.278)
1846 HWND32 WINAPI GetParent32( HWND32 hwnd )
1848 WND *wndPtr = WIN_FindWndPtr(hwnd);
1849 if ((!wndPtr) || (!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD)))) return 0;
1850 wndPtr = (wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner;
1851 return wndPtr ? wndPtr->hwndSelf : 0;
1854 /*****************************************************************
1855 * WIN_GetTopParent
1857 * Get the top-level parent for a child window.
1859 WND* WIN_GetTopParentPtr( WND* pWnd )
1861 while( pWnd && (pWnd->dwStyle & WS_CHILD)) pWnd = pWnd->parent;
1862 return pWnd;
1865 /*****************************************************************
1866 * WIN_GetTopParent
1868 * Get the top-level parent for a child window.
1870 HWND32 WIN_GetTopParent( HWND32 hwnd )
1872 WND *wndPtr = WIN_GetTopParentPtr ( WIN_FindWndPtr( hwnd ) );
1873 return wndPtr ? wndPtr->hwndSelf : 0;
1877 /*****************************************************************
1878 * SetParent16 (USER.233)
1880 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
1882 return SetParent32( hwndChild, hwndNewParent );
1886 /*****************************************************************
1887 * SetParent32 (USER32.495)
1889 HWND32 WINAPI SetParent32( HWND32 hwndChild, HWND32 hwndNewParent )
1891 WND *wndPtr = WIN_FindWndPtr( hwndChild );
1892 WND *pWndNewParent =
1893 (hwndNewParent) ? WIN_FindWndPtr( hwndNewParent ) : pWndDesktop;
1894 WND *pWndOldParent =
1895 (wndPtr)?(*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent):NULL;
1897 return pWndOldParent?pWndOldParent->hwndSelf:0;
1900 /*******************************************************************
1901 * IsChild16 (USER.48)
1903 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
1905 return IsChild32(parent,child);
1909 /*******************************************************************
1910 * IsChild32 (USER32.339)
1912 BOOL32 WINAPI IsChild32( HWND32 parent, HWND32 child )
1914 WND * wndPtr = WIN_FindWndPtr( child );
1915 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1917 wndPtr = wndPtr->parent;
1918 if (wndPtr->hwndSelf == parent) return TRUE;
1920 return FALSE;
1924 /***********************************************************************
1925 * IsWindowVisible16 (USER.49)
1927 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
1929 return IsWindowVisible32(hwnd);
1933 /***********************************************************************
1934 * IsWindowVisible32 (USER32.351)
1936 BOOL32 WINAPI IsWindowVisible32( HWND32 hwnd )
1938 WND *wndPtr = WIN_FindWndPtr( hwnd );
1939 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1941 if (!(wndPtr->dwStyle & WS_VISIBLE)) return FALSE;
1942 wndPtr = wndPtr->parent;
1944 return (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
1948 /***********************************************************************
1949 * WIN_IsWindowDrawable
1951 * hwnd is drawable when it is visible, all parents are not
1952 * minimized, and it is itself not minimized unless we are
1953 * trying to draw its default class icon.
1955 BOOL32 WIN_IsWindowDrawable( WND* wnd, BOOL32 icon )
1957 if( (wnd->dwStyle & WS_MINIMIZE &&
1958 icon && wnd->class->hIcon) ||
1959 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
1960 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
1961 if( wnd->dwStyle & WS_MINIMIZE ||
1962 !(wnd->dwStyle & WS_VISIBLE) ) break;
1963 return (wnd == NULL);
1967 /*******************************************************************
1968 * GetTopWindow16 (USER.229)
1970 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
1972 return GetTopWindow32(hwnd);
1976 /*******************************************************************
1977 * GetTopWindow32 (USER.229)
1979 HWND32 WINAPI GetTopWindow32( HWND32 hwnd )
1981 WND * wndPtr = WIN_FindWndPtr( hwnd );
1982 if (wndPtr && wndPtr->child) return wndPtr->child->hwndSelf;
1983 else return 0;
1987 /*******************************************************************
1988 * GetWindow16 (USER.262)
1990 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
1992 return GetWindow32( hwnd,rel );
1996 /*******************************************************************
1997 * GetWindow32 (USER32.302)
1999 HWND32 WINAPI GetWindow32( HWND32 hwnd, WORD rel )
2001 WND * wndPtr = WIN_FindWndPtr( hwnd );
2002 if (!wndPtr) return 0;
2003 switch(rel)
2005 case GW_HWNDFIRST:
2006 if (wndPtr->parent) return wndPtr->parent->child->hwndSelf;
2007 else return 0;
2009 case GW_HWNDLAST:
2010 if (!wndPtr->parent) return 0; /* Desktop window */
2011 while (wndPtr->next) wndPtr = wndPtr->next;
2012 return wndPtr->hwndSelf;
2014 case GW_HWNDNEXT:
2015 if (!wndPtr->next) return 0;
2016 return wndPtr->next->hwndSelf;
2018 case GW_HWNDPREV:
2019 if (!wndPtr->parent) return 0; /* Desktop window */
2020 wndPtr = wndPtr->parent->child; /* First sibling */
2021 if (wndPtr->hwndSelf == hwnd) return 0; /* First in list */
2022 while (wndPtr->next)
2024 if (wndPtr->next->hwndSelf == hwnd) return wndPtr->hwndSelf;
2025 wndPtr = wndPtr->next;
2027 return 0;
2029 case GW_OWNER:
2030 return wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2032 case GW_CHILD:
2033 return wndPtr->child ? wndPtr->child->hwndSelf : 0;
2035 return 0;
2039 /*******************************************************************
2040 * GetNextWindow16 (USER.230)
2042 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2044 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2045 return GetWindow16( hwnd, flag );
2048 /*******************************************************************
2049 * ShowOwnedPopups16 (USER.265)
2051 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2053 ShowOwnedPopups32( owner, fShow );
2057 /*******************************************************************
2058 * ShowOwnedPopups32 (USER32.531)
2060 BOOL32 WINAPI ShowOwnedPopups32( HWND32 owner, BOOL32 fShow )
2062 WND *pWnd = pWndDesktop->child;
2063 while (pWnd)
2065 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
2066 (pWnd->dwStyle & WS_POPUP))
2067 ShowWindow32( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
2068 pWnd = pWnd->next;
2070 return TRUE;
2074 /*******************************************************************
2075 * GetLastActivePopup16 (USER.287)
2077 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2079 return GetLastActivePopup32( hwnd );
2082 /*******************************************************************
2083 * GetLastActivePopup32 (USER32.256)
2085 HWND32 WINAPI GetLastActivePopup32( HWND32 hwnd )
2087 WND *wndPtr;
2088 wndPtr = WIN_FindWndPtr(hwnd);
2089 if (wndPtr == NULL) return hwnd;
2090 return wndPtr->hwndLastActive;
2094 /*******************************************************************
2095 * WIN_BuildWinArray
2097 * Build an array of pointers to the children of a given window.
2098 * The array must be freed with HeapFree(SystemHeap). Return NULL
2099 * when no windows are found.
2101 WND **WIN_BuildWinArray( WND *wndPtr, UINT32 bwaFlags, UINT32* pTotal )
2103 WND **list, **ppWnd;
2104 WND *pWnd;
2105 UINT32 count, skipOwned, skipHidden;
2106 DWORD skipFlags;
2108 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2109 skipOwned = bwaFlags & BWA_SKIPOWNED;
2110 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2111 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2113 /* First count the windows */
2115 if (!wndPtr) wndPtr = pWndDesktop;
2116 for (pWnd = wndPtr->child, count = 0; pWnd; pWnd = pWnd->next)
2118 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
2119 if( !skipHidden || pWnd->dwStyle & WS_VISIBLE ) count++;
2122 if( count )
2124 /* Now build the list of all windows */
2126 if ((list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * (count + 1))))
2128 for (pWnd = wndPtr->child, ppWnd = list, count = 0; pWnd; pWnd = pWnd->next)
2130 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
2131 if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2133 *ppWnd++ = pWnd;
2134 count++;
2137 *ppWnd = NULL;
2139 else count = 0;
2140 } else list = NULL;
2142 if( pTotal ) *pTotal = count;
2143 return list;
2147 /*******************************************************************
2148 * EnumWindows16 (USER.54)
2150 BOOL16 WINAPI EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
2152 WND **list, **ppWnd;
2154 /* We have to build a list of all windows first, to avoid */
2155 /* unpleasant side-effects, for instance if the callback */
2156 /* function changes the Z-order of the windows. */
2158 if (!(list = WIN_BuildWinArray( pWndDesktop, 0, NULL ))) return FALSE;
2160 /* Now call the callback function for every window */
2162 for (ppWnd = list; *ppWnd; ppWnd++)
2164 /* Make sure that the window still exists */
2165 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2166 if (!lpEnumFunc( (*ppWnd)->hwndSelf, lParam )) break;
2168 HeapFree( SystemHeap, 0, list );
2169 return TRUE;
2173 /*******************************************************************
2174 * EnumWindows32 (USER32.193)
2176 BOOL32 WINAPI EnumWindows32( WNDENUMPROC32 lpEnumFunc, LPARAM lParam )
2178 return (BOOL32)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2182 /**********************************************************************
2183 * EnumTaskWindows16 (USER.225)
2185 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2186 LPARAM lParam )
2188 WND **list, **ppWnd;
2190 /* This function is the same as EnumWindows(), */
2191 /* except for an added check on the window's task. */
2193 if (!(list = WIN_BuildWinArray( pWndDesktop, 0, NULL ))) return FALSE;
2195 /* Now call the callback function for every window */
2197 for (ppWnd = list; *ppWnd; ppWnd++)
2199 /* Make sure that the window still exists */
2200 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2201 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2202 if (!func( (*ppWnd)->hwndSelf, lParam )) break;
2204 HeapFree( SystemHeap, 0, list );
2205 return TRUE;
2209 /**********************************************************************
2210 * EnumThreadWindows (USER32.190)
2212 BOOL32 WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC32 func, LPARAM lParam )
2214 THDB *tdb = THREAD_ID_TO_THDB(id);
2216 return (BOOL16)EnumTaskWindows16(tdb->teb.htask16, (WNDENUMPROC16)func, lParam);
2220 /**********************************************************************
2221 * WIN_EnumChildWindows
2223 * Helper function for EnumChildWindows().
2225 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2226 LPARAM lParam )
2228 WND **childList;
2229 BOOL16 ret = FALSE;
2231 for ( ; *ppWnd; ppWnd++)
2233 /* Make sure that the window still exists */
2234 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2235 /* Build children list first */
2236 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2237 ret = func( (*ppWnd)->hwndSelf, lParam );
2238 if (childList)
2240 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2241 HeapFree( SystemHeap, 0, childList );
2243 if (!ret) return FALSE;
2245 return TRUE;
2249 /**********************************************************************
2250 * EnumChildWindows16 (USER.55)
2252 BOOL16 WINAPI EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
2253 LPARAM lParam )
2255 WND **list, *pParent;
2257 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2258 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL ))) return FALSE;
2259 WIN_EnumChildWindows( list, func, lParam );
2260 HeapFree( SystemHeap, 0, list );
2261 return TRUE;
2265 /**********************************************************************
2266 * EnumChildWindows32 (USER32.178)
2268 BOOL32 WINAPI EnumChildWindows32( HWND32 parent, WNDENUMPROC32 func,
2269 LPARAM lParam )
2271 return (BOOL32)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2272 lParam );
2276 /*******************************************************************
2277 * AnyPopup16 (USER.52)
2279 BOOL16 WINAPI AnyPopup16(void)
2281 return AnyPopup32();
2285 /*******************************************************************
2286 * AnyPopup32 (USER32.4)
2288 BOOL32 WINAPI AnyPopup32(void)
2290 WND *wndPtr;
2291 for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next)
2292 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE)) return TRUE;
2293 return FALSE;
2297 /*******************************************************************
2298 * FlashWindow16 (USER.105)
2300 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2302 return FlashWindow32( hWnd, bInvert );
2306 /*******************************************************************
2307 * FlashWindow32 (USER32.202)
2309 BOOL32 WINAPI FlashWindow32( HWND32 hWnd, BOOL32 bInvert )
2311 WND *wndPtr = WIN_FindWndPtr(hWnd);
2313 TRACE(win,"%04x\n", hWnd);
2315 if (!wndPtr) return FALSE;
2317 if (wndPtr->dwStyle & WS_MINIMIZE)
2319 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2321 HDC32 hDC = GetDC32(hWnd);
2323 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2324 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2326 ReleaseDC32( hWnd, hDC );
2327 wndPtr->flags |= WIN_NCACTIVATED;
2329 else
2331 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2332 RDW_UPDATENOW | RDW_FRAME, 0 );
2333 wndPtr->flags &= ~WIN_NCACTIVATED;
2335 return TRUE;
2337 else
2339 WPARAM16 wparam;
2340 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2341 else wparam = (hWnd == GetActiveWindow32());
2343 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2344 return wparam;
2349 /*******************************************************************
2350 * SetSysModalWindow16 (USER.188)
2352 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
2354 HWND32 hWndOldModal = hwndSysModal;
2355 hwndSysModal = hWnd;
2356 FIXME(win, "EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2357 return hWndOldModal;
2361 /*******************************************************************
2362 * GetSysModalWindow16 (USER.52)
2364 HWND16 WINAPI GetSysModalWindow16(void)
2366 return hwndSysModal;
2370 /*******************************************************************
2371 * GetWindowContextHelpId (USER32.303)
2373 DWORD WINAPI GetWindowContextHelpId( HWND32 hwnd )
2375 WND *wnd = WIN_FindWndPtr( hwnd );
2376 if (!wnd) return 0;
2377 return wnd->helpContext;
2381 /*******************************************************************
2382 * SetWindowContextHelpId (USER32.515)
2384 BOOL32 WINAPI SetWindowContextHelpId( HWND32 hwnd, DWORD id )
2386 WND *wnd = WIN_FindWndPtr( hwnd );
2387 if (!wnd) return FALSE;
2388 wnd->helpContext = id;
2389 return TRUE;
2393 /*******************************************************************
2394 * DRAG_QueryUpdate
2396 * recursively find a child that contains spDragInfo->pt point
2397 * and send WM_QUERYDROPOBJECT
2399 BOOL16 DRAG_QueryUpdate( HWND32 hQueryWnd, SEGPTR spDragInfo, BOOL32 bNoSend )
2401 BOOL16 wParam,bResult = 0;
2402 POINT32 pt;
2403 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
2404 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
2405 RECT32 tempRect;
2407 if( !ptrQueryWnd || !ptrDragInfo ) return 0;
2409 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
2411 GetWindowRect32(hQueryWnd,&tempRect);
2413 if( !PtInRect32(&tempRect,pt) ||
2414 (ptrQueryWnd->dwStyle & WS_DISABLED) )
2415 return 0;
2417 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
2419 tempRect = ptrQueryWnd->rectClient;
2420 if(ptrQueryWnd->dwStyle & WS_CHILD)
2421 MapWindowPoints32( ptrQueryWnd->parent->hwndSelf, 0,
2422 (LPPOINT32)&tempRect, 2 );
2424 if (PtInRect32( &tempRect, pt))
2426 wParam = 0;
2428 for (ptrWnd = ptrQueryWnd->child; ptrWnd ;ptrWnd = ptrWnd->next)
2429 if( ptrWnd->dwStyle & WS_VISIBLE )
2431 GetWindowRect32( ptrWnd->hwndSelf, &tempRect );
2432 if (PtInRect32( &tempRect, pt )) break;
2435 if(ptrWnd)
2437 TRACE(msg,"hwnd = %04x, %d %d - %d %d\n",
2438 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
2439 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
2440 if( !(ptrWnd->dwStyle & WS_DISABLED) )
2441 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
2444 if(bResult) return bResult;
2446 else wParam = 1;
2448 else wParam = 1;
2450 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
2452 ptrDragInfo->hScope = hQueryWnd;
2454 bResult = ( bNoSend )
2455 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
2456 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
2457 (WPARAM16)wParam ,(LPARAM) spDragInfo );
2458 if( !bResult )
2459 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
2461 return bResult;
2465 /*******************************************************************
2466 * DragDetect (USER.465)
2468 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
2470 POINT32 pt32;
2471 CONV_POINT16TO32( &pt, &pt32 );
2472 return DragDetect32( hWnd, pt32 );
2475 /*******************************************************************
2476 * DragDetect32 (USER32.151)
2478 BOOL32 WINAPI DragDetect32( HWND32 hWnd, POINT32 pt )
2480 MSG16 msg;
2481 RECT16 rect;
2483 rect.left = pt.x - wDragWidth;
2484 rect.right = pt.x + wDragWidth;
2486 rect.top = pt.y - wDragHeight;
2487 rect.bottom = pt.y + wDragHeight;
2489 SetCapture32(hWnd);
2491 while(1)
2493 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
2495 if( msg.message == WM_LBUTTONUP )
2497 ReleaseCapture();
2498 return 0;
2500 if( msg.message == WM_MOUSEMOVE )
2502 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
2504 ReleaseCapture();
2505 return 1;
2509 WaitMessage();
2511 return 0;
2514 /******************************************************************************
2515 * DragObject16 (USER.464)
2517 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
2518 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
2520 MSG16 msg;
2521 LPDRAGINFO lpDragInfo;
2522 SEGPTR spDragInfo;
2523 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
2524 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
2525 WND *wndPtr = WIN_FindWndPtr(hWnd);
2526 HCURSOR16 hCurrentCursor = 0;
2527 HWND16 hCurrentWnd = 0;
2529 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
2530 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
2532 if( !lpDragInfo || !spDragInfo ) return 0L;
2534 hBummer = LoadCursor16(0, IDC_BUMMER16);
2536 if( !hBummer || !wndPtr )
2538 GlobalFree16(hDragInfo);
2539 return 0L;
2542 if(hCursor)
2544 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
2546 GlobalFree16(hDragInfo);
2547 return 0L;
2550 if( hDragCursor == hCursor ) hDragCursor = 0;
2551 else hCursor = hDragCursor;
2553 hOldCursor = SetCursor32(hDragCursor);
2556 lpDragInfo->hWnd = hWnd;
2557 lpDragInfo->hScope = 0;
2558 lpDragInfo->wFlags = wObj;
2559 lpDragInfo->hList = szList; /* near pointer! */
2560 lpDragInfo->hOfStruct = hOfStruct;
2561 lpDragInfo->l = 0L;
2563 SetCapture32(hWnd);
2564 ShowCursor32( TRUE );
2568 do{ WaitMessage(); }
2569 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
2571 *(lpDragInfo+1) = *lpDragInfo;
2573 lpDragInfo->pt = msg.pt;
2575 /* update DRAGINFO struct */
2576 TRACE(msg,"lpDI->hScope = %04x\n",lpDragInfo->hScope);
2578 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
2579 hCurrentCursor = hCursor;
2580 else
2582 hCurrentCursor = hBummer;
2583 lpDragInfo->hScope = 0;
2585 if( hCurrentCursor )
2586 SetCursor32(hCurrentCursor);
2588 /* send WM_DRAGLOOP */
2589 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
2590 (LPARAM) spDragInfo );
2591 /* send WM_DRAGSELECT or WM_DRAGMOVE */
2592 if( hCurrentWnd != lpDragInfo->hScope )
2594 if( hCurrentWnd )
2595 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
2596 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
2597 HIWORD(spDragInfo)) );
2598 hCurrentWnd = lpDragInfo->hScope;
2599 if( hCurrentWnd )
2600 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
2602 else
2603 if( hCurrentWnd )
2604 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
2606 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
2608 ReleaseCapture();
2609 ShowCursor32( FALSE );
2611 if( hCursor )
2613 SetCursor32( hOldCursor );
2614 if (hDragCursor) DestroyCursor32( hDragCursor );
2617 if( hCurrentCursor != hBummer )
2618 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
2619 (WPARAM16)hWnd, (LPARAM)spDragInfo );
2620 else
2621 msg.lParam = 0;
2622 GlobalFree16(hDragInfo);
2624 return (DWORD)(msg.lParam);