Added a few authors.
[wine/multimedia.git] / windows / win.c
blob649f85224457ec217a76357efd793f9c5fac71b0
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->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
566 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
568 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
570 /* Call the WH_CBT hook */
572 hwndLinkAfter = (cs->style & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
574 if (HOOK_IsHooked( WH_CBT ))
576 CBT_CREATEWND32A cbtc;
577 LRESULT ret;
579 cbtc.lpcs = cs;
580 cbtc.hwndInsertAfter = hwndLinkAfter;
581 ret = unicode ? HOOK_CallHooks32W(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
582 : HOOK_CallHooks32A(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
583 if (ret)
585 TRACE(win, "CBT-hook returned 0\n");
586 USER_HEAP_FREE( hwnd );
587 return 0;
591 /* Increment class window counter */
593 classPtr->cWindows++;
595 /* Correct the window style */
597 if (!(cs->style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
599 wndPtr->dwStyle |= WS_CAPTION | WS_CLIPSIBLINGS;
600 wndPtr->flags |= WIN_NEED_SIZE;
602 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
604 /* Get class or window DC if needed */
606 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
607 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
608 else wndPtr->dce = NULL;
610 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
612 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
614 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
615 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
616 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
617 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
618 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
621 if(cs->style & WS_CHILD)
623 if(cs->cx < 0) cs->cx = 0;
624 if(cs->cy < 0) cs->cy = 0;
626 else
628 if (cs->cx <= 0) cs->cx = 1;
629 if (cs->cy <= 0) cs->cy = 1;
632 wndPtr->rectWindow.left = cs->x;
633 wndPtr->rectWindow.top = cs->y;
634 wndPtr->rectWindow.right = cs->x + cs->cx;
635 wndPtr->rectWindow.bottom = cs->y + cs->cy;
636 wndPtr->rectClient = wndPtr->rectWindow;
638 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
639 return FALSE;
641 /* Set the window menu */
643 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
645 if (cs->hMenu) SetMenu32(hwnd, cs->hMenu);
646 else
648 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
649 if (classPtr->menuNameA)
650 cs->hMenu = HIWORD(classPtr->menuNameA) ?
651 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
652 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
653 #else
654 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
655 if (menuName)
657 if (HIWORD(cs->hInstance))
658 cs->hMenu = LoadMenu32A(cs->hInstance,PTR_SEG_TO_LIN(menuName));
659 else
660 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
662 if (cs->hMenu) SetMenu32( hwnd, cs->hMenu );
664 #endif
667 else wndPtr->wIDmenu = (UINT32)cs->hMenu;
669 /* Send the WM_CREATE message
670 * Perhaps we shouldn't allow width/height changes as well.
671 * See p327 in "Internals".
674 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
676 localSend32 = unicode ? SendMessage32W : SendMessage32A;
677 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
679 /* Insert the window in the linked list */
681 WIN_LinkWindow( hwnd, hwndLinkAfter );
683 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
684 NULL, NULL, 0, &wndPtr->rectClient );
685 OffsetRect32(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
686 maxPos.y - wndPtr->rectWindow.top);
687 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
689 /* Send the size messages */
691 if (!(wndPtr->flags & WIN_NEED_SIZE))
693 /* send it anyway */
694 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
695 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
696 WARN(win,"sending bogus WM_SIZE message 0x%08lx\n",
697 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
698 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
699 SendMessage32A( hwnd, WM_SIZE, SIZE_RESTORED,
700 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
701 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
702 SendMessage32A( hwnd, WM_MOVE, 0,
703 MAKELONG( wndPtr->rectClient.left,
704 wndPtr->rectClient.top ) );
707 /* Show the window, maximizing or minimizing if needed */
709 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
711 RECT16 newPos;
712 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
713 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
714 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
715 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow32()) ? SWP_NOACTIVATE : 0;
716 SetWindowPos32( hwnd, 0, newPos.left, newPos.top,
717 newPos.right, newPos.bottom, SWP_FRAMECHANGED | swFlag );
720 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
722 /* Notify the parent window only */
724 SendMessage32A( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
725 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
726 if( !IsWindow32(hwnd) ) return 0;
729 if (cs->style & WS_VISIBLE) ShowWindow32( hwnd, SW_SHOW );
731 /* Call WH_SHELL hook */
733 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
734 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
736 TRACE(win, "created window %04x\n", hwnd);
737 return hwnd;
739 WIN_UnlinkWindow( hwnd );
742 /* Abort window creation */
744 WARN(win, "aborted by WM_xxCREATE!\n");
745 WIN_DestroyWindow( wndPtr );
746 return 0;
750 /***********************************************************************
751 * CreateWindow16 (USER.41)
753 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
754 DWORD style, INT16 x, INT16 y, INT16 width,
755 INT16 height, HWND16 parent, HMENU16 menu,
756 HINSTANCE16 instance, LPVOID data )
758 return CreateWindowEx16( 0, className, windowName, style,
759 x, y, width, height, parent, menu, instance, data );
763 /***********************************************************************
764 * CreateWindowEx16 (USER.452)
766 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
767 LPCSTR windowName, DWORD style, INT16 x,
768 INT16 y, INT16 width, INT16 height,
769 HWND16 parent, HMENU16 menu,
770 HINSTANCE16 instance, LPVOID data )
772 ATOM classAtom;
773 CREATESTRUCT32A cs;
775 /* Find the class atom */
777 if (!(classAtom = GlobalFindAtom32A( className )))
779 fprintf( stderr, "CreateWindowEx16: bad class name " );
780 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
781 else fprintf( stderr, "'%s'\n", className );
782 return 0;
785 /* Fix the coordinates */
787 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)x;
788 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)y;
789 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)width;
790 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)height;
792 /* Create the window */
794 cs.lpCreateParams = data;
795 cs.hInstance = (HINSTANCE32)instance;
796 cs.hMenu = (HMENU32)menu;
797 cs.hwndParent = (HWND32)parent;
798 cs.style = style;
799 cs.lpszName = windowName;
800 cs.lpszClass = className;
801 cs.dwExStyle = exStyle;
802 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
806 /***********************************************************************
807 * CreateWindowEx32A (USER32.83)
809 HWND32 WINAPI CreateWindowEx32A( DWORD exStyle, LPCSTR className,
810 LPCSTR windowName, DWORD style, INT32 x,
811 INT32 y, INT32 width, INT32 height,
812 HWND32 parent, HMENU32 menu,
813 HINSTANCE32 instance, LPVOID data )
815 ATOM classAtom;
816 CREATESTRUCT32A cs;
818 if(exStyle & WS_EX_MDICHILD)
819 return MDI_CreateMDIWindow32A(className, windowName, style, x, y, width, height, parent, instance, data);
820 /* Find the class atom */
822 if (!(classAtom = GlobalFindAtom32A( className )))
824 fprintf( stderr, "CreateWindowEx32A: bad class name " );
825 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
826 else fprintf( stderr, "'%s'\n", className );
827 return 0;
830 /* Create the window */
832 cs.lpCreateParams = data;
833 cs.hInstance = instance;
834 cs.hMenu = menu;
835 cs.hwndParent = parent;
836 cs.x = x;
837 cs.y = y;
838 cs.cx = width;
839 cs.cy = height;
840 cs.style = style;
841 cs.lpszName = windowName;
842 cs.lpszClass = className;
843 cs.dwExStyle = exStyle;
844 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
848 /***********************************************************************
849 * CreateWindowEx32W (USER32.84)
851 HWND32 WINAPI CreateWindowEx32W( DWORD exStyle, LPCWSTR className,
852 LPCWSTR windowName, DWORD style, INT32 x,
853 INT32 y, INT32 width, INT32 height,
854 HWND32 parent, HMENU32 menu,
855 HINSTANCE32 instance, LPVOID data )
857 ATOM classAtom;
858 CREATESTRUCT32W cs;
860 if(exStyle & WS_EX_MDICHILD)
861 return MDI_CreateMDIWindow32W(className, windowName, style, x, y, width, height, parent, instance, data);
863 /* Find the class atom */
865 if (!(classAtom = GlobalFindAtom32W( className )))
867 if (HIWORD(className))
869 LPSTR cn = HEAP_strdupWtoA( GetProcessHeap(), 0, className );
870 WARN( win, "Bad class name '%s'\n",cn);
871 HeapFree( GetProcessHeap(), 0, cn );
873 else
874 WARN( win, "Bad class name %p\n", className );
875 return 0;
878 /* Create the window */
880 cs.lpCreateParams = data;
881 cs.hInstance = instance;
882 cs.hMenu = menu;
883 cs.hwndParent = parent;
884 cs.x = x;
885 cs.y = y;
886 cs.cx = width;
887 cs.cy = height;
888 cs.style = style;
889 cs.lpszName = windowName;
890 cs.lpszClass = className;
891 cs.dwExStyle = exStyle;
892 /* Note: we rely on the fact that CREATESTRUCT32A and */
893 /* CREATESTRUCT32W have the same layout. */
894 return WIN_CreateWindowEx( (CREATESTRUCT32A *)&cs, classAtom, TRUE, TRUE );
898 /***********************************************************************
899 * WIN_CheckFocus
901 static void WIN_CheckFocus( WND* pWnd )
903 if( GetFocus16() == pWnd->hwndSelf )
904 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
907 /***********************************************************************
908 * WIN_SendDestroyMsg
910 static void WIN_SendDestroyMsg( WND* pWnd )
912 WIN_CheckFocus(pWnd);
914 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret32();
915 if( !pWnd->window ) CLIPBOARD_GetDriver()->pResetOwner( pWnd );
917 SendMessage32A( pWnd->hwndSelf, WM_DESTROY, 0, 0);
919 if( IsWindow32(pWnd->hwndSelf) )
921 WND* pChild = pWnd->child;
922 while( pChild )
924 WIN_SendDestroyMsg( pChild );
925 pChild = pChild->next;
927 WIN_CheckFocus(pWnd);
929 else
930 WARN(win, "\tdestroyed itself while in WM_DESTROY!\n");
934 /***********************************************************************
935 * DestroyWindow16 (USER.53)
937 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
939 return DestroyWindow32(hwnd);
943 /***********************************************************************
944 * DestroyWindow32 (USER32.135)
946 BOOL32 WINAPI DestroyWindow32( HWND32 hwnd )
948 WND * wndPtr;
950 TRACE(win, "(%04x)\n", hwnd);
952 /* Initialization */
954 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
955 if (wndPtr == pWndDesktop) return FALSE; /* Can't destroy desktop */
957 /* Call hooks */
959 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
960 return FALSE;
962 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
964 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
965 /* FIXME: clean up palette - see "Internals" p.352 */
968 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
969 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
971 /* Notify the parent window only */
972 SendMessage32A( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
973 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
974 if( !IsWindow32(hwnd) ) return TRUE;
977 if( wndPtr->window ) CLIPBOARD_GetDriver()->pResetOwner( wndPtr ); /* before the window is unmapped */
979 /* Hide the window */
981 if (wndPtr->dwStyle & WS_VISIBLE)
983 SetWindowPos32( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
984 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
985 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
986 if (!IsWindow32(hwnd)) return TRUE;
989 /* Recursively destroy owned windows */
991 if( !(wndPtr->dwStyle & WS_CHILD) )
993 /* make sure top menu popup doesn't get destroyed */
994 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
996 for (;;)
998 WND *siblingPtr = wndPtr->parent->child; /* First sibling */
999 while (siblingPtr)
1001 if (siblingPtr->owner == wndPtr)
1003 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1004 break;
1005 else
1006 siblingPtr->owner = NULL;
1008 siblingPtr = siblingPtr->next;
1010 if (siblingPtr) DestroyWindow32( siblingPtr->hwndSelf );
1011 else break;
1014 if( !Options.managed || EVENT_CheckFocus() )
1015 WINPOS_ActivateOtherWindow(wndPtr);
1017 if( wndPtr->owner &&
1018 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1019 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1022 /* Send destroy messages */
1024 WIN_SendDestroyMsg( wndPtr );
1025 if (!IsWindow32(hwnd)) return TRUE;
1027 /* Unlink now so we won't bother with the children later on */
1029 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1031 /* Destroy the window storage */
1033 WIN_DestroyWindow( wndPtr );
1034 return TRUE;
1038 /***********************************************************************
1039 * CloseWindow16 (USER.43)
1041 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1043 return CloseWindow32( hwnd );
1047 /***********************************************************************
1048 * CloseWindow32 (USER32.56)
1050 BOOL32 WINAPI CloseWindow32( HWND32 hwnd )
1052 WND * wndPtr = WIN_FindWndPtr( hwnd );
1053 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD)) return FALSE;
1054 ShowWindow32( hwnd, SW_MINIMIZE );
1055 return TRUE;
1059 /***********************************************************************
1060 * OpenIcon16 (USER.44)
1062 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1064 return OpenIcon32( hwnd );
1068 /***********************************************************************
1069 * OpenIcon32 (USER32.410)
1071 BOOL32 WINAPI OpenIcon32( HWND32 hwnd )
1073 if (!IsIconic32( hwnd )) return FALSE;
1074 ShowWindow32( hwnd, SW_SHOWNORMAL );
1075 return TRUE;
1079 /***********************************************************************
1080 * WIN_FindWindow
1082 * Implementation of FindWindow() and FindWindowEx().
1084 static HWND32 WIN_FindWindow( HWND32 parent, HWND32 child, ATOM className,
1085 LPCSTR title )
1087 WND *pWnd;
1088 CLASS *pClass = NULL;
1090 if (child)
1092 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1093 if (parent)
1095 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent)) return 0;
1097 else if (pWnd->parent != pWndDesktop) return 0;
1098 pWnd = pWnd->next;
1100 else
1102 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : pWndDesktop)) return 0;
1103 pWnd = pWnd->child;
1105 if (!pWnd) return 0;
1107 /* For a child window, all siblings will have the same hInstance, */
1108 /* so we can look for the class once and for all. */
1110 if (className && (pWnd->dwStyle & WS_CHILD))
1112 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1113 return 0;
1117 for ( ; pWnd; pWnd = pWnd->next)
1119 if (className && !(pWnd->dwStyle & WS_CHILD))
1121 if (!(pClass = CLASS_FindClassByAtom( className, GetExePtr(pWnd->hInstance))))
1122 continue; /* Skip this window */
1125 if (pClass && (pWnd->class != pClass))
1126 continue; /* Not the right class */
1128 /* Now check the title */
1130 if (!title) return pWnd->hwndSelf;
1131 if (pWnd->text && !strcmp( pWnd->text, title )) return pWnd->hwndSelf;
1133 return 0;
1138 /***********************************************************************
1139 * FindWindow16 (USER.50)
1141 HWND16 WINAPI FindWindow16( SEGPTR className, LPCSTR title )
1143 return FindWindowEx16( 0, 0, className, title );
1147 /***********************************************************************
1148 * FindWindowEx16 (USER.427)
1150 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child,
1151 SEGPTR className, LPCSTR title )
1153 ATOM atom = 0;
1155 TRACE(win, "%04x %04x '%s' '%s'\n", parent,
1156 child, HIWORD(className)?(char *)PTR_SEG_TO_LIN(className):"",
1157 title ? title : "");
1159 if (className)
1161 /* If the atom doesn't exist, then no class */
1162 /* with this name exists either. */
1163 if (!(atom = GlobalFindAtom16( className ))) return 0;
1165 return WIN_FindWindow( parent, child, atom, title );
1169 /***********************************************************************
1170 * FindWindow32A (USER32.198)
1172 HWND32 WINAPI FindWindow32A( LPCSTR className, LPCSTR title )
1174 HWND32 ret = FindWindowEx32A( 0, 0, className, title );
1175 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1176 return ret;
1180 /***********************************************************************
1181 * FindWindowEx32A (USER32.199)
1183 HWND32 WINAPI FindWindowEx32A( HWND32 parent, HWND32 child,
1184 LPCSTR className, LPCSTR title )
1186 ATOM atom = 0;
1188 if (className)
1190 /* If the atom doesn't exist, then no class */
1191 /* with this name exists either. */
1192 if (!(atom = GlobalFindAtom32A( className )))
1194 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1195 return 0;
1198 return WIN_FindWindow( parent, child, atom, title );
1202 /***********************************************************************
1203 * FindWindowEx32W (USER32.200)
1205 HWND32 WINAPI FindWindowEx32W( HWND32 parent, HWND32 child,
1206 LPCWSTR className, LPCWSTR title )
1208 ATOM atom = 0;
1209 char *buffer;
1210 HWND32 hwnd;
1212 if (className)
1214 /* If the atom doesn't exist, then no class */
1215 /* with this name exists either. */
1216 if (!(atom = GlobalFindAtom32W( className )))
1218 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1219 return 0;
1222 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1223 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1224 HeapFree( GetProcessHeap(), 0, buffer );
1225 return hwnd;
1229 /***********************************************************************
1230 * FindWindow32W (USER32.201)
1232 HWND32 WINAPI FindWindow32W( LPCWSTR className, LPCWSTR title )
1234 return FindWindowEx32W( 0, 0, className, title );
1238 /**********************************************************************
1239 * WIN_GetDesktop
1241 WND *WIN_GetDesktop(void)
1243 return pWndDesktop;
1247 /**********************************************************************
1248 * GetDesktopWindow16 (USER.286)
1250 HWND16 WINAPI GetDesktopWindow16(void)
1252 return (HWND16)pWndDesktop->hwndSelf;
1256 /**********************************************************************
1257 * GetDesktopWindow32 (USER32.232)
1259 HWND32 WINAPI GetDesktopWindow32(void)
1261 return pWndDesktop->hwndSelf;
1265 /**********************************************************************
1266 * GetDesktopHwnd (USER.278)
1268 * Exactly the same thing as GetDesktopWindow(), but not documented.
1269 * Don't ask me why...
1271 HWND16 WINAPI GetDesktopHwnd(void)
1273 return (HWND16)pWndDesktop->hwndSelf;
1277 /*******************************************************************
1278 * EnableWindow16 (USER.34)
1280 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1282 return EnableWindow32( hwnd, enable );
1286 /*******************************************************************
1287 * EnableWindow32 (USER32.172)
1289 BOOL32 WINAPI EnableWindow32( HWND32 hwnd, BOOL32 enable )
1291 WND *wndPtr;
1293 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1294 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1296 /* Enable window */
1297 wndPtr->dwStyle &= ~WS_DISABLED;
1298 SendMessage32A( hwnd, WM_ENABLE, TRUE, 0 );
1299 return TRUE;
1301 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1303 /* Disable window */
1304 wndPtr->dwStyle |= WS_DISABLED;
1305 if ((hwnd == GetFocus32()) || IsChild32( hwnd, GetFocus32() ))
1306 SetFocus32( 0 ); /* A disabled window can't have the focus */
1307 if ((hwnd == GetCapture32()) || IsChild32( hwnd, GetCapture32() ))
1308 ReleaseCapture(); /* A disabled window can't capture the mouse */
1309 SendMessage32A( hwnd, WM_ENABLE, FALSE, 0 );
1310 return FALSE;
1312 return ((wndPtr->dwStyle & WS_DISABLED) != 0);
1316 /***********************************************************************
1317 * IsWindowEnabled16 (USER.35)
1319 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1321 return IsWindowEnabled32(hWnd);
1325 /***********************************************************************
1326 * IsWindowEnabled32 (USER32.349)
1328 BOOL32 WINAPI IsWindowEnabled32(HWND32 hWnd)
1330 WND * wndPtr;
1332 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1333 return !(wndPtr->dwStyle & WS_DISABLED);
1337 /***********************************************************************
1338 * IsWindowUnicode (USER32.350)
1340 BOOL32 WINAPI IsWindowUnicode( HWND32 hwnd )
1342 WND * wndPtr;
1344 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1345 return (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1349 /**********************************************************************
1350 * GetWindowWord16 (USER.133)
1352 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1354 return GetWindowWord32( hwnd, offset );
1358 /**********************************************************************
1359 * GetWindowWord32 (USER32.314)
1361 WORD WINAPI GetWindowWord32( HWND32 hwnd, INT32 offset )
1363 WND * wndPtr = WIN_FindWndPtr( hwnd );
1364 if (!wndPtr) return 0;
1365 if (offset >= 0)
1367 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1369 WARN( win, "Invalid offset %d\n", offset );
1370 return 0;
1372 return *(WORD *)(((char *)wndPtr->wExtra) + offset);
1374 switch(offset)
1376 case GWW_ID:
1377 if (HIWORD(wndPtr->wIDmenu))
1378 WARN( win,"GWW_ID: discards high bits of 0x%08x!\n",
1379 wndPtr->wIDmenu);
1380 return (WORD)wndPtr->wIDmenu;
1381 case GWW_HWNDPARENT:
1382 return wndPtr->parent ?
1383 wndPtr->parent->hwndSelf : (
1384 wndPtr->owner ?
1385 wndPtr->owner->hwndSelf :
1387 case GWW_HINSTANCE:
1388 if (HIWORD(wndPtr->hInstance))
1389 WARN(win,"GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1390 wndPtr->hInstance);
1391 return (WORD)wndPtr->hInstance;
1392 default:
1393 WARN( win, "Invalid offset %d\n", offset );
1394 return 0;
1399 /**********************************************************************
1400 * WIN_GetWindowInstance
1402 HINSTANCE32 WIN_GetWindowInstance( HWND32 hwnd )
1404 WND * wndPtr = WIN_FindWndPtr( hwnd );
1405 if (!wndPtr) return (HINSTANCE32)0;
1406 return wndPtr->hInstance;
1410 /**********************************************************************
1411 * SetWindowWord16 (USER.134)
1413 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1415 return SetWindowWord32( hwnd, offset, newval );
1419 /**********************************************************************
1420 * SetWindowWord32 (USER32.524)
1422 WORD WINAPI SetWindowWord32( HWND32 hwnd, INT32 offset, WORD newval )
1424 WORD *ptr, retval;
1425 WND * wndPtr = WIN_FindWndPtr( hwnd );
1426 if (!wndPtr) return 0;
1427 if (offset >= 0)
1429 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1431 WARN( win, "Invalid offset %d\n", offset );
1432 return 0;
1434 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1436 else switch(offset)
1438 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1439 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1440 case GWW_HWNDPARENT: return SetParent32( hwnd, newval );
1441 default:
1442 WARN( win, "Invalid offset %d\n", offset );
1443 return 0;
1445 retval = *ptr;
1446 *ptr = newval;
1447 return retval;
1451 /**********************************************************************
1452 * WIN_GetWindowLong
1454 * Helper function for GetWindowLong().
1456 static LONG WIN_GetWindowLong( HWND32 hwnd, INT32 offset, WINDOWPROCTYPE type )
1458 LONG retval;
1459 WND * wndPtr = WIN_FindWndPtr( hwnd );
1460 if (!wndPtr) return 0;
1461 if (offset >= 0)
1463 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1465 WARN( win, "Invalid offset %d\n", offset );
1466 return 0;
1468 retval = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1469 /* Special case for dialog window procedure */
1470 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1471 return (LONG)WINPROC_GetProc( (HWINDOWPROC)retval, type );
1472 return retval;
1474 switch(offset)
1476 case GWL_USERDATA: return wndPtr->userdata;
1477 case GWL_STYLE: return wndPtr->dwStyle;
1478 case GWL_EXSTYLE: return wndPtr->dwExStyle;
1479 case GWL_ID: return (LONG)wndPtr->wIDmenu;
1480 case GWL_WNDPROC: return (LONG)WINPROC_GetProc( wndPtr->winproc,
1481 type );
1482 case GWL_HWNDPARENT: return wndPtr->parent ?
1483 (HWND32)wndPtr->parent->hwndSelf : 0;
1484 case GWL_HINSTANCE: return wndPtr->hInstance;
1485 default:
1486 WARN( win, "Unknown offset %d\n", offset );
1488 return 0;
1492 /**********************************************************************
1493 * WIN_SetWindowLong
1495 * Helper function for SetWindowLong().
1497 * 0 is the failure code. However, in the case of failure SetLastError
1498 * must be set to distinguish between a 0 return value and a failure.
1500 * FIXME: The error values for SetLastError may not be right. Can
1501 * someone check with the real thing?
1503 static LONG WIN_SetWindowLong( HWND32 hwnd, INT32 offset, LONG newval,
1504 WINDOWPROCTYPE type )
1506 LONG *ptr, retval;
1507 WND * wndPtr = WIN_FindWndPtr( hwnd );
1508 STYLESTRUCT style;
1510 TRACE(win,"%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1512 if (!wndPtr)
1514 /* Is this the right error? */
1515 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1516 return 0;
1519 if (offset >= 0)
1521 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1523 WARN( win, "Invalid offset %d\n", offset );
1525 /* Is this the right error? */
1526 SetLastError( ERROR_OUTOFMEMORY );
1528 return 0;
1530 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1531 /* Special case for dialog window procedure */
1532 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1534 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1535 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1536 type, WIN_PROC_WINDOW );
1537 return retval;
1540 else switch(offset)
1542 case GWL_ID:
1543 ptr = (DWORD*)&wndPtr->wIDmenu;
1544 break;
1545 case GWL_HINSTANCE:
1546 return SetWindowWord32( hwnd, offset, newval );
1547 case GWL_WNDPROC:
1548 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1549 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1550 type, WIN_PROC_WINDOW );
1551 return retval;
1552 case GWL_STYLE:
1553 style.styleOld = wndPtr->dwStyle;
1554 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
1555 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
1557 if (wndPtr->flags & WIN_ISWIN32)
1558 SendMessage32A(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1559 wndPtr->dwStyle = style.styleNew;
1560 if (wndPtr->flags & WIN_ISWIN32)
1561 SendMessage32A(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1562 return style.styleOld;
1564 case GWL_USERDATA:
1565 ptr = &wndPtr->userdata;
1566 break;
1567 case GWL_EXSTYLE:
1568 style.styleOld = wndPtr->dwExStyle;
1569 style.styleNew = newval;
1570 if (wndPtr->flags & WIN_ISWIN32)
1571 SendMessage32A(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1572 wndPtr->dwExStyle = newval;
1573 if (wndPtr->flags & WIN_ISWIN32)
1574 SendMessage32A(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1575 return style.styleOld;
1577 default:
1578 WARN( win, "Invalid offset %d\n", offset );
1580 /* Don't think this is right error but it should do */
1581 SetLastError( ERROR_OUTOFMEMORY );
1583 return 0;
1585 retval = *ptr;
1586 *ptr = newval;
1587 return retval;
1591 /**********************************************************************
1592 * GetWindowLong16 (USER.135)
1594 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1596 return WIN_GetWindowLong( (HWND32)hwnd, offset, WIN_PROC_16 );
1600 /**********************************************************************
1601 * GetWindowLong32A (USER32.305)
1603 LONG WINAPI GetWindowLong32A( HWND32 hwnd, INT32 offset )
1605 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1609 /**********************************************************************
1610 * GetWindowLong32W (USER32.306)
1612 LONG WINAPI GetWindowLong32W( HWND32 hwnd, INT32 offset )
1614 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1618 /**********************************************************************
1619 * SetWindowLong16 (USER.136)
1621 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1623 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1627 /**********************************************************************
1628 * SetWindowLong32A (USER32.517)
1630 LONG WINAPI SetWindowLong32A( HWND32 hwnd, INT32 offset, LONG newval )
1632 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1636 /**********************************************************************
1637 * SetWindowLong32W (USER32.518) Set window attribute
1639 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
1640 * value in a window's extra memory.
1642 * The _hwnd_ parameter specifies the window. is the handle to a
1643 * window that has extra memory. The _newval_ parameter contains the
1644 * new attribute or extra memory value. If positive, the _offset_
1645 * parameter is the byte-addressed location in the window's extra
1646 * memory to set. If negative, _offset_ specifies the window
1647 * attribute to set, and should be one of the following values:
1649 * GWL_EXSTYLE The window's extended window style
1651 * GWL_STYLE The window's window style.
1653 * GWL_WNDPROC Pointer to the window's window procedure.
1655 * GWL_HINSTANCE The window's pplication instance handle.
1657 * GWL_ID The window's identifier.
1659 * GWL_USERDATA The window's user-specified data.
1661 * If the window is a dialog box, the _offset_ parameter can be one of
1662 * the following values:
1664 * DWL_DLGPROC The address of the window's dialog box procedure.
1666 * DWL_MSGRESULT The return value of a message
1667 * that the dialog box procedure processed.
1669 * DWL_USER Application specific information.
1671 * RETURNS
1673 * If successful, returns the previous value located at _offset_. Otherwise,
1674 * returns 0.
1676 * NOTES
1678 * Extra memory for a window class is specified by a nonzero cbWndExtra
1679 * parameter of the WNDCLASS structure passed to RegisterClass() at the
1680 * time of class creation.
1682 * Using GWL_WNDPROC to set a new window procedure effectively creates
1683 * a window subclass. Use CallWindowProc() in the new windows procedure
1684 * to pass messages to the superclass's window procedure.
1686 * The user data is reserved for use by the application which created
1687 * the window.
1689 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
1690 * instead, call the EnableWindow() function to change the window's
1691 * disabled state.
1693 * Do not use GWL_HWNDPARENT to reset the window's parent, use
1694 * SetParent() instead.
1696 * BUGS
1698 * GWL_STYLE does not dispatch WM_STYLE_... messages.
1700 * CONFORMANCE
1702 * ECMA-234, Win32
1705 LONG WINAPI SetWindowLong32W(
1706 HWND32 hwnd, /* window to alter */
1707 INT32 offset, /* offset, in bytes, of location to alter */
1708 LONG newval /* new value of location */
1710 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1714 /*******************************************************************
1715 * GetWindowText16 (USER.36)
1717 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
1719 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1723 /*******************************************************************
1724 * GetWindowText32A (USER32.309)
1726 INT32 WINAPI GetWindowText32A( HWND32 hwnd, LPSTR lpString, INT32 nMaxCount )
1728 return (INT32)SendMessage32A( hwnd, WM_GETTEXT, nMaxCount,
1729 (LPARAM)lpString );
1732 /*******************************************************************
1733 * InternalGetWindowText (USER32.326)
1735 INT32 WINAPI InternalGetWindowText(HWND32 hwnd,LPWSTR lpString,INT32 nMaxCount )
1737 FIXME(win,"(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
1738 return GetWindowText32W(hwnd,lpString,nMaxCount);
1742 /*******************************************************************
1743 * GetWindowText32W (USER32.312)
1745 INT32 WINAPI GetWindowText32W( HWND32 hwnd, LPWSTR lpString, INT32 nMaxCount )
1747 return (INT32)SendMessage32W( hwnd, WM_GETTEXT, nMaxCount,
1748 (LPARAM)lpString );
1752 /*******************************************************************
1753 * SetWindowText16 (USER.37)
1755 void WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
1757 SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1761 /*******************************************************************
1762 * SetWindowText32A (USER32.521)
1764 void WINAPI SetWindowText32A( HWND32 hwnd, LPCSTR lpString )
1766 SendMessage32A( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1770 /*******************************************************************
1771 * SetWindowText32W (USER32.523)
1773 void WINAPI SetWindowText32W( HWND32 hwnd, LPCWSTR lpString )
1775 SendMessage32W( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1779 /*******************************************************************
1780 * GetWindowTextLength16 (USER.38)
1782 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
1784 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1788 /*******************************************************************
1789 * GetWindowTextLength32A (USER32.310)
1791 INT32 WINAPI GetWindowTextLength32A( HWND32 hwnd )
1793 return SendMessage32A( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1796 /*******************************************************************
1797 * GetWindowTextLength32W (USER32.311)
1799 INT32 WINAPI GetWindowTextLength32W( HWND32 hwnd )
1801 return SendMessage32W( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1805 /*******************************************************************
1806 * IsWindow16 (USER.47)
1808 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
1810 return IsWindow32( hwnd );
1813 void WINAPI WIN16_IsWindow16( CONTEXT *context )
1815 WORD *stack = PTR_SEG_OFF_TO_LIN(SS_reg(context), SP_reg(context));
1816 HWND16 hwnd = (HWND16)stack[2];
1818 AX_reg(context) = IsWindow32( hwnd );
1819 ES_reg(context) = USER_HeapSel;
1823 /*******************************************************************
1824 * IsWindow32 (USER32.348)
1826 BOOL32 WINAPI IsWindow32( HWND32 hwnd )
1828 WND * wndPtr = WIN_FindWndPtr( hwnd );
1829 return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
1833 /*****************************************************************
1834 * GetParent16 (USER.46)
1836 HWND16 WINAPI GetParent16( HWND16 hwnd )
1838 return (HWND16)GetParent32( hwnd );
1842 /*****************************************************************
1843 * GetParent32 (USER32.278)
1845 HWND32 WINAPI GetParent32( HWND32 hwnd )
1847 WND *wndPtr = WIN_FindWndPtr(hwnd);
1848 if ((!wndPtr) || (!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD)))) return 0;
1849 wndPtr = (wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner;
1850 return wndPtr ? wndPtr->hwndSelf : 0;
1853 /*****************************************************************
1854 * WIN_GetTopParent
1856 * Get the top-level parent for a child window.
1858 WND* WIN_GetTopParentPtr( WND* pWnd )
1860 while( pWnd && (pWnd->dwStyle & WS_CHILD)) pWnd = pWnd->parent;
1861 return pWnd;
1864 /*****************************************************************
1865 * WIN_GetTopParent
1867 * Get the top-level parent for a child window.
1869 HWND32 WIN_GetTopParent( HWND32 hwnd )
1871 WND *wndPtr = WIN_GetTopParentPtr ( WIN_FindWndPtr( hwnd ) );
1872 return wndPtr ? wndPtr->hwndSelf : 0;
1876 /*****************************************************************
1877 * SetParent16 (USER.233)
1879 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
1881 return SetParent32( hwndChild, hwndNewParent );
1885 /*****************************************************************
1886 * SetParent32 (USER32.495)
1888 HWND32 WINAPI SetParent32( HWND32 hwndChild, HWND32 hwndNewParent )
1890 WND *wndPtr = WIN_FindWndPtr( hwndChild );
1891 WND *pWndNewParent =
1892 (hwndNewParent) ? WIN_FindWndPtr( hwndNewParent ) : pWndDesktop;
1893 WND *pWndOldParent =
1894 (wndPtr)?(*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent):NULL;
1896 return pWndOldParent?pWndOldParent->hwndSelf:0;
1899 /*******************************************************************
1900 * IsChild16 (USER.48)
1902 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
1904 return IsChild32(parent,child);
1908 /*******************************************************************
1909 * IsChild32 (USER32.339)
1911 BOOL32 WINAPI IsChild32( HWND32 parent, HWND32 child )
1913 WND * wndPtr = WIN_FindWndPtr( child );
1914 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1916 wndPtr = wndPtr->parent;
1917 if (wndPtr->hwndSelf == parent) return TRUE;
1919 return FALSE;
1923 /***********************************************************************
1924 * IsWindowVisible16 (USER.49)
1926 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
1928 return IsWindowVisible32(hwnd);
1932 /***********************************************************************
1933 * IsWindowVisible32 (USER32.351)
1935 BOOL32 WINAPI IsWindowVisible32( HWND32 hwnd )
1937 WND *wndPtr = WIN_FindWndPtr( hwnd );
1938 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1940 if (!(wndPtr->dwStyle & WS_VISIBLE)) return FALSE;
1941 wndPtr = wndPtr->parent;
1943 return (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
1947 /***********************************************************************
1948 * WIN_IsWindowDrawable
1950 * hwnd is drawable when it is visible, all parents are not
1951 * minimized, and it is itself not minimized unless we are
1952 * trying to draw its default class icon.
1954 BOOL32 WIN_IsWindowDrawable( WND* wnd, BOOL32 icon )
1956 if( (wnd->dwStyle & WS_MINIMIZE &&
1957 icon && wnd->class->hIcon) ||
1958 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
1959 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
1960 if( wnd->dwStyle & WS_MINIMIZE ||
1961 !(wnd->dwStyle & WS_VISIBLE) ) break;
1962 return (wnd == NULL);
1966 /*******************************************************************
1967 * GetTopWindow16 (USER.229)
1969 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
1971 return GetTopWindow32(hwnd);
1975 /*******************************************************************
1976 * GetTopWindow32 (USER.229)
1978 HWND32 WINAPI GetTopWindow32( HWND32 hwnd )
1980 WND * wndPtr = WIN_FindWndPtr( hwnd );
1981 if (wndPtr && wndPtr->child) return wndPtr->child->hwndSelf;
1982 else return 0;
1986 /*******************************************************************
1987 * GetWindow16 (USER.262)
1989 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
1991 return GetWindow32( hwnd,rel );
1995 /*******************************************************************
1996 * GetWindow32 (USER32.302)
1998 HWND32 WINAPI GetWindow32( HWND32 hwnd, WORD rel )
2000 WND * wndPtr = WIN_FindWndPtr( hwnd );
2001 if (!wndPtr) return 0;
2002 switch(rel)
2004 case GW_HWNDFIRST:
2005 if (wndPtr->parent) return wndPtr->parent->child->hwndSelf;
2006 else return 0;
2008 case GW_HWNDLAST:
2009 if (!wndPtr->parent) return 0; /* Desktop window */
2010 while (wndPtr->next) wndPtr = wndPtr->next;
2011 return wndPtr->hwndSelf;
2013 case GW_HWNDNEXT:
2014 if (!wndPtr->next) return 0;
2015 return wndPtr->next->hwndSelf;
2017 case GW_HWNDPREV:
2018 if (!wndPtr->parent) return 0; /* Desktop window */
2019 wndPtr = wndPtr->parent->child; /* First sibling */
2020 if (wndPtr->hwndSelf == hwnd) return 0; /* First in list */
2021 while (wndPtr->next)
2023 if (wndPtr->next->hwndSelf == hwnd) return wndPtr->hwndSelf;
2024 wndPtr = wndPtr->next;
2026 return 0;
2028 case GW_OWNER:
2029 return wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2031 case GW_CHILD:
2032 return wndPtr->child ? wndPtr->child->hwndSelf : 0;
2034 return 0;
2038 /*******************************************************************
2039 * GetNextWindow16 (USER.230)
2041 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2043 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2044 return GetWindow16( hwnd, flag );
2047 /*******************************************************************
2048 * ShowOwnedPopups16 (USER.265)
2050 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2052 ShowOwnedPopups32( owner, fShow );
2056 /*******************************************************************
2057 * ShowOwnedPopups32 (USER32.531)
2059 BOOL32 WINAPI ShowOwnedPopups32( HWND32 owner, BOOL32 fShow )
2061 WND *pWnd = pWndDesktop->child;
2062 while (pWnd)
2064 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
2065 (pWnd->dwStyle & WS_POPUP))
2066 ShowWindow32( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
2067 pWnd = pWnd->next;
2069 return TRUE;
2073 /*******************************************************************
2074 * GetLastActivePopup16 (USER.287)
2076 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2078 return GetLastActivePopup32( hwnd );
2081 /*******************************************************************
2082 * GetLastActivePopup32 (USER32.256)
2084 HWND32 WINAPI GetLastActivePopup32( HWND32 hwnd )
2086 WND *wndPtr;
2087 wndPtr = WIN_FindWndPtr(hwnd);
2088 if (wndPtr == NULL) return hwnd;
2089 return wndPtr->hwndLastActive;
2093 /*******************************************************************
2094 * WIN_BuildWinArray
2096 * Build an array of pointers to the children of a given window.
2097 * The array must be freed with HeapFree(SystemHeap). Return NULL
2098 * when no windows are found.
2100 WND **WIN_BuildWinArray( WND *wndPtr, UINT32 bwaFlags, UINT32* pTotal )
2102 WND **list, **ppWnd;
2103 WND *pWnd;
2104 UINT32 count, skipOwned, skipHidden;
2105 DWORD skipFlags;
2107 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2108 skipOwned = bwaFlags & BWA_SKIPOWNED;
2109 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2110 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2112 /* First count the windows */
2114 if (!wndPtr) wndPtr = pWndDesktop;
2115 for (pWnd = wndPtr->child, count = 0; pWnd; pWnd = pWnd->next)
2117 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
2118 if( !skipHidden || pWnd->dwStyle & WS_VISIBLE ) count++;
2121 if( count )
2123 /* Now build the list of all windows */
2125 if ((list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * (count + 1))))
2127 for (pWnd = wndPtr->child, ppWnd = list, count = 0; pWnd; pWnd = pWnd->next)
2129 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
2130 if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2132 *ppWnd++ = pWnd;
2133 count++;
2136 *ppWnd = NULL;
2138 else count = 0;
2139 } else list = NULL;
2141 if( pTotal ) *pTotal = count;
2142 return list;
2146 /*******************************************************************
2147 * EnumWindows16 (USER.54)
2149 BOOL16 WINAPI EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
2151 WND **list, **ppWnd;
2153 /* We have to build a list of all windows first, to avoid */
2154 /* unpleasant side-effects, for instance if the callback */
2155 /* function changes the Z-order of the windows. */
2157 if (!(list = WIN_BuildWinArray( pWndDesktop, 0, NULL ))) return FALSE;
2159 /* Now call the callback function for every window */
2161 for (ppWnd = list; *ppWnd; ppWnd++)
2163 /* Make sure that the window still exists */
2164 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2165 if (!lpEnumFunc( (*ppWnd)->hwndSelf, lParam )) break;
2167 HeapFree( SystemHeap, 0, list );
2168 return TRUE;
2172 /*******************************************************************
2173 * EnumWindows32 (USER32.193)
2175 BOOL32 WINAPI EnumWindows32( WNDENUMPROC32 lpEnumFunc, LPARAM lParam )
2177 return (BOOL32)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2181 /**********************************************************************
2182 * EnumTaskWindows16 (USER.225)
2184 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2185 LPARAM lParam )
2187 WND **list, **ppWnd;
2189 /* This function is the same as EnumWindows(), */
2190 /* except for an added check on the window's task. */
2192 if (!(list = WIN_BuildWinArray( pWndDesktop, 0, NULL ))) return FALSE;
2194 /* Now call the callback function for every window */
2196 for (ppWnd = list; *ppWnd; ppWnd++)
2198 /* Make sure that the window still exists */
2199 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2200 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2201 if (!func( (*ppWnd)->hwndSelf, lParam )) break;
2203 HeapFree( SystemHeap, 0, list );
2204 return TRUE;
2208 /**********************************************************************
2209 * EnumThreadWindows (USER32.190)
2211 BOOL32 WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC32 func, LPARAM lParam )
2213 THDB *tdb = THREAD_ID_TO_THDB(id);
2215 return (BOOL16)EnumTaskWindows16(tdb->teb.htask16, (WNDENUMPROC16)func, lParam);
2219 /**********************************************************************
2220 * WIN_EnumChildWindows
2222 * Helper function for EnumChildWindows().
2224 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2225 LPARAM lParam )
2227 WND **childList;
2228 BOOL16 ret = FALSE;
2230 for ( ; *ppWnd; ppWnd++)
2232 /* Make sure that the window still exists */
2233 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2234 /* Build children list first */
2235 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2236 ret = func( (*ppWnd)->hwndSelf, lParam );
2237 if (childList)
2239 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2240 HeapFree( SystemHeap, 0, childList );
2242 if (!ret) return FALSE;
2244 return TRUE;
2248 /**********************************************************************
2249 * EnumChildWindows16 (USER.55)
2251 BOOL16 WINAPI EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
2252 LPARAM lParam )
2254 WND **list, *pParent;
2256 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2257 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL ))) return FALSE;
2258 WIN_EnumChildWindows( list, func, lParam );
2259 HeapFree( SystemHeap, 0, list );
2260 return TRUE;
2264 /**********************************************************************
2265 * EnumChildWindows32 (USER32.178)
2267 BOOL32 WINAPI EnumChildWindows32( HWND32 parent, WNDENUMPROC32 func,
2268 LPARAM lParam )
2270 return (BOOL32)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2271 lParam );
2275 /*******************************************************************
2276 * AnyPopup16 (USER.52)
2278 BOOL16 WINAPI AnyPopup16(void)
2280 return AnyPopup32();
2284 /*******************************************************************
2285 * AnyPopup32 (USER32.4)
2287 BOOL32 WINAPI AnyPopup32(void)
2289 WND *wndPtr;
2290 for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next)
2291 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE)) return TRUE;
2292 return FALSE;
2296 /*******************************************************************
2297 * FlashWindow16 (USER.105)
2299 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2301 return FlashWindow32( hWnd, bInvert );
2305 /*******************************************************************
2306 * FlashWindow32 (USER32.202)
2308 BOOL32 WINAPI FlashWindow32( HWND32 hWnd, BOOL32 bInvert )
2310 WND *wndPtr = WIN_FindWndPtr(hWnd);
2312 TRACE(win,"%04x\n", hWnd);
2314 if (!wndPtr) return FALSE;
2316 if (wndPtr->dwStyle & WS_MINIMIZE)
2318 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2320 HDC32 hDC = GetDC32(hWnd);
2322 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2323 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2325 ReleaseDC32( hWnd, hDC );
2326 wndPtr->flags |= WIN_NCACTIVATED;
2328 else
2330 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2331 RDW_UPDATENOW | RDW_FRAME, 0 );
2332 wndPtr->flags &= ~WIN_NCACTIVATED;
2334 return TRUE;
2336 else
2338 WPARAM16 wparam;
2339 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2340 else wparam = (hWnd == GetActiveWindow32());
2342 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2343 return wparam;
2348 /*******************************************************************
2349 * SetSysModalWindow16 (USER.188)
2351 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
2353 HWND32 hWndOldModal = hwndSysModal;
2354 hwndSysModal = hWnd;
2355 FIXME(win, "EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2356 return hWndOldModal;
2360 /*******************************************************************
2361 * GetSysModalWindow16 (USER.52)
2363 HWND16 WINAPI GetSysModalWindow16(void)
2365 return hwndSysModal;
2369 /*******************************************************************
2370 * GetWindowContextHelpId (USER32.303)
2372 DWORD WINAPI GetWindowContextHelpId( HWND32 hwnd )
2374 WND *wnd = WIN_FindWndPtr( hwnd );
2375 if (!wnd) return 0;
2376 return wnd->helpContext;
2380 /*******************************************************************
2381 * SetWindowContextHelpId (USER32.515)
2383 BOOL32 WINAPI SetWindowContextHelpId( HWND32 hwnd, DWORD id )
2385 WND *wnd = WIN_FindWndPtr( hwnd );
2386 if (!wnd) return FALSE;
2387 wnd->helpContext = id;
2388 return TRUE;
2392 /*******************************************************************
2393 * DRAG_QueryUpdate
2395 * recursively find a child that contains spDragInfo->pt point
2396 * and send WM_QUERYDROPOBJECT
2398 BOOL16 DRAG_QueryUpdate( HWND32 hQueryWnd, SEGPTR spDragInfo, BOOL32 bNoSend )
2400 BOOL16 wParam,bResult = 0;
2401 POINT32 pt;
2402 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
2403 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
2404 RECT32 tempRect;
2406 if( !ptrQueryWnd || !ptrDragInfo ) return 0;
2408 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
2410 GetWindowRect32(hQueryWnd,&tempRect);
2412 if( !PtInRect32(&tempRect,pt) ||
2413 (ptrQueryWnd->dwStyle & WS_DISABLED) )
2414 return 0;
2416 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
2418 tempRect = ptrQueryWnd->rectClient;
2419 if(ptrQueryWnd->dwStyle & WS_CHILD)
2420 MapWindowPoints32( ptrQueryWnd->parent->hwndSelf, 0,
2421 (LPPOINT32)&tempRect, 2 );
2423 if (PtInRect32( &tempRect, pt))
2425 wParam = 0;
2427 for (ptrWnd = ptrQueryWnd->child; ptrWnd ;ptrWnd = ptrWnd->next)
2428 if( ptrWnd->dwStyle & WS_VISIBLE )
2430 GetWindowRect32( ptrWnd->hwndSelf, &tempRect );
2431 if (PtInRect32( &tempRect, pt )) break;
2434 if(ptrWnd)
2436 TRACE(msg,"hwnd = %04x, %d %d - %d %d\n",
2437 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
2438 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
2439 if( !(ptrWnd->dwStyle & WS_DISABLED) )
2440 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
2443 if(bResult) return bResult;
2445 else wParam = 1;
2447 else wParam = 1;
2449 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
2451 ptrDragInfo->hScope = hQueryWnd;
2453 bResult = ( bNoSend )
2454 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
2455 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
2456 (WPARAM16)wParam ,(LPARAM) spDragInfo );
2457 if( !bResult )
2458 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
2460 return bResult;
2464 /*******************************************************************
2465 * DragDetect (USER.465)
2467 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
2469 POINT32 pt32;
2470 CONV_POINT16TO32( &pt, &pt32 );
2471 return DragDetect32( hWnd, pt32 );
2474 /*******************************************************************
2475 * DragDetect32 (USER32.151)
2477 BOOL32 WINAPI DragDetect32( HWND32 hWnd, POINT32 pt )
2479 MSG16 msg;
2480 RECT16 rect;
2482 rect.left = pt.x - wDragWidth;
2483 rect.right = pt.x + wDragWidth;
2485 rect.top = pt.y - wDragHeight;
2486 rect.bottom = pt.y + wDragHeight;
2488 SetCapture32(hWnd);
2490 while(1)
2492 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
2494 if( msg.message == WM_LBUTTONUP )
2496 ReleaseCapture();
2497 return 0;
2499 if( msg.message == WM_MOUSEMOVE )
2501 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
2503 ReleaseCapture();
2504 return 1;
2508 WaitMessage();
2510 return 0;
2513 /******************************************************************************
2514 * DragObject16 (USER.464)
2516 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
2517 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
2519 MSG16 msg;
2520 LPDRAGINFO lpDragInfo;
2521 SEGPTR spDragInfo;
2522 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
2523 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
2524 WND *wndPtr = WIN_FindWndPtr(hWnd);
2525 HCURSOR16 hCurrentCursor = 0;
2526 HWND16 hCurrentWnd = 0;
2528 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
2529 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
2531 if( !lpDragInfo || !spDragInfo ) return 0L;
2533 hBummer = LoadCursor16(0, IDC_BUMMER16);
2535 if( !hBummer || !wndPtr )
2537 GlobalFree16(hDragInfo);
2538 return 0L;
2541 if(hCursor)
2543 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
2545 GlobalFree16(hDragInfo);
2546 return 0L;
2549 if( hDragCursor == hCursor ) hDragCursor = 0;
2550 else hCursor = hDragCursor;
2552 hOldCursor = SetCursor32(hDragCursor);
2555 lpDragInfo->hWnd = hWnd;
2556 lpDragInfo->hScope = 0;
2557 lpDragInfo->wFlags = wObj;
2558 lpDragInfo->hList = szList; /* near pointer! */
2559 lpDragInfo->hOfStruct = hOfStruct;
2560 lpDragInfo->l = 0L;
2562 SetCapture32(hWnd);
2563 ShowCursor32( TRUE );
2567 do{ WaitMessage(); }
2568 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
2570 *(lpDragInfo+1) = *lpDragInfo;
2572 lpDragInfo->pt = msg.pt;
2574 /* update DRAGINFO struct */
2575 TRACE(msg,"lpDI->hScope = %04x\n",lpDragInfo->hScope);
2577 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
2578 hCurrentCursor = hCursor;
2579 else
2581 hCurrentCursor = hBummer;
2582 lpDragInfo->hScope = 0;
2584 if( hCurrentCursor )
2585 SetCursor32(hCurrentCursor);
2587 /* send WM_DRAGLOOP */
2588 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
2589 (LPARAM) spDragInfo );
2590 /* send WM_DRAGSELECT or WM_DRAGMOVE */
2591 if( hCurrentWnd != lpDragInfo->hScope )
2593 if( hCurrentWnd )
2594 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
2595 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
2596 HIWORD(spDragInfo)) );
2597 hCurrentWnd = lpDragInfo->hScope;
2598 if( hCurrentWnd )
2599 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
2601 else
2602 if( hCurrentWnd )
2603 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
2605 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
2607 ReleaseCapture();
2608 ShowCursor32( FALSE );
2610 if( hCursor )
2612 SetCursor32( hOldCursor );
2613 if (hDragCursor) DestroyCursor32( hDragCursor );
2616 if( hCurrentCursor != hBummer )
2617 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
2618 (WPARAM16)hWnd, (LPARAM)spDragInfo );
2619 else
2620 msg.lParam = 0;
2621 GlobalFree16(hDragInfo);
2623 return (DWORD)(msg.lParam);