Release 961208
[wine.git] / windows / win.c
blob56cfa04a461f3a6b02665758f77cd601fe380d84
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <X11/Xatom.h>
12 #include "options.h"
13 #include "class.h"
14 #include "win.h"
15 #include "heap.h"
16 #include "user.h"
17 #include "dce.h"
18 #include "sysmetrics.h"
19 #include "cursoricon.h"
20 #include "heap.h"
21 #include "hook.h"
22 #include "menu.h"
23 #include "message.h"
24 #include "nonclient.h"
25 #include "string32.h"
26 #include "queue.h"
27 #include "winpos.h"
28 #include "color.h"
29 #include "shm_main_blk.h"
30 #include "dde_proc.h"
31 #include "clipboard.h"
32 #include "winproc.h"
33 #include "stddebug.h"
34 /* #define DEBUG_WIN */
35 /* #define DEBUG_MENU */
36 #include "debug.h"
38 /* Desktop window */
39 static WND *pWndDesktop = NULL;
41 static HWND hwndSysModal = 0;
43 static WORD wDragWidth = 4;
44 static WORD wDragHeight= 3;
46 extern HCURSOR16 CURSORICON_IconToCursor(HICON16, BOOL32);
47 extern HWND32 CARET_GetHwnd(void);
48 extern BOOL32 WINPOS_ActivateOtherWindow(WND* pWnd);
49 extern void WINPOS_CheckActive(HWND32);
51 /***********************************************************************
52 * WIN_FindWndPtr
54 * Return a pointer to the WND structure corresponding to a HWND.
56 WND * WIN_FindWndPtr( HWND32 hwnd )
58 WND * ptr;
60 if (!hwnd || HIWORD(hwnd)) return NULL;
61 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
62 if (ptr->dwMagic != WND_MAGIC) return NULL;
63 if (ptr->hwndSelf != hwnd)
65 fprintf( stderr, "Can't happen: hwnd %04x self pointer is %04x\n",
66 hwnd, ptr->hwndSelf );
67 return NULL;
69 return ptr;
73 /***********************************************************************
74 * WIN_DumpWindow
76 * Dump the content of a window structure to stderr.
78 void WIN_DumpWindow( HWND32 hwnd )
80 WND *ptr;
81 char className[80];
82 int i;
84 if (!(ptr = WIN_FindWndPtr( hwnd )))
86 fprintf( stderr, "%04x is not a window handle\n", hwnd );
87 return;
90 if (!GetClassName32A( hwnd, className, sizeof(className ) ))
91 strcpy( className, "#NULL#" );
93 fprintf( stderr, "Window %04x (%p):\n", hwnd, ptr );
94 fprintf( stderr,
95 "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
96 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%04x\n"
97 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
98 "client=%d,%d-%d,%d window=%d,%d-%d,%d iconpos=%d,%d maxpos=%d,%d\n"
99 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
100 ptr->next, ptr->child, ptr->parent, ptr->owner,
101 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
102 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
103 ptr->dwStyle, ptr->dwExStyle, (UINT32)ptr->winproc,
104 ptr->text ? ptr->text : "",
105 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
106 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
107 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->ptIconPos.x,
108 ptr->ptIconPos.y, ptr->ptMaxPos.x, ptr->ptMaxPos.y, ptr->hSysMenu,
109 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
111 if (ptr->class->cbWndExtra)
113 fprintf( stderr, "extra bytes:" );
114 for (i = 0; i < ptr->class->cbWndExtra; i++)
115 fprintf( stderr, " %02x", *((BYTE*)ptr->wExtra+i) );
116 fprintf( stderr, "\n" );
118 fprintf( stderr, "\n" );
122 /***********************************************************************
123 * WIN_WalkWindows
125 * Walk the windows tree and print each window on stderr.
127 void WIN_WalkWindows( HWND32 hwnd, int indent )
129 WND *ptr;
130 char className[80];
132 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop;
133 if (!ptr)
135 fprintf( stderr, "*** Invalid window handle %04x\n", hwnd );
136 return;
139 if (!indent) /* first time around */
140 fprintf( stderr, "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
141 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc");
143 while (ptr)
145 fprintf(stderr, "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
147 GlobalGetAtomName16(ptr->class->atomName,className,sizeof(className));
149 fprintf( stderr, "%08lx %-6.4x %-17.17s %08x %08x\n",
150 (DWORD)ptr, ptr->hmemTaskQ, className,
151 (UINT32)ptr->dwStyle, (UINT32)ptr->winproc );
153 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
154 ptr = ptr->next;
159 /***********************************************************************
160 * WIN_GetXWindow
162 * Return the X window associated to a window.
164 Window WIN_GetXWindow( HWND32 hwnd )
166 WND *wndPtr = WIN_FindWndPtr( hwnd );
167 while (wndPtr && !wndPtr->window) wndPtr = wndPtr->parent;
168 return wndPtr ? wndPtr->window : 0;
172 /***********************************************************************
173 * WIN_UnlinkWindow
175 * Remove a window from the siblings linked list.
177 BOOL32 WIN_UnlinkWindow( HWND32 hwnd )
179 WND *wndPtr, **ppWnd;
181 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
182 ppWnd = &wndPtr->parent->child;
183 while (*ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
184 *ppWnd = wndPtr->next;
185 return TRUE;
189 /***********************************************************************
190 * WIN_LinkWindow
192 * Insert a window into the siblings linked list.
193 * The window is inserted after the specified window, which can also
194 * be specified as HWND_TOP or HWND_BOTTOM.
196 BOOL32 WIN_LinkWindow( HWND32 hwnd, HWND32 hwndInsertAfter )
198 WND *wndPtr, **ppWnd;
200 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
202 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
204 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
205 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
206 while (*ppWnd) ppWnd = &(*ppWnd)->next;
208 else /* Normal case */
210 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
211 if (!afterPtr) return FALSE;
212 ppWnd = &afterPtr->next;
214 wndPtr->next = *ppWnd;
215 *ppWnd = wndPtr;
216 return TRUE;
220 /***********************************************************************
221 * WIN_FindWinToRepaint
223 * Find a window that needs repaint.
225 HWND32 WIN_FindWinToRepaint( HWND32 hwnd, HQUEUE16 hQueue )
227 HWND hwndRet;
228 WND *pWnd = pWndDesktop;
230 /* Note: the desktop window never gets WM_PAINT messages
231 * The real reason why is because Windows DesktopWndProc
232 * does ValidateRgn inside WM_ERASEBKGND handler.
235 pWnd = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop->child;
237 for ( ; pWnd ; pWnd = pWnd->next )
239 if (!(pWnd->dwStyle & WS_VISIBLE) || (pWnd->flags & WIN_NO_REDRAW))
241 dprintf_win( stddeb, "FindWinToRepaint: skipping window %04x\n",
242 pWnd->hwndSelf );
243 continue;
245 if ((pWnd->hmemTaskQ == hQueue) &&
246 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))) break;
248 if (pWnd->child )
249 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
250 return hwndRet;
253 if (!pWnd) return 0;
255 hwndRet = pWnd->hwndSelf;
257 /* look among siblings if we got a transparent window */
258 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
259 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
261 pWnd = pWnd->next;
263 if (pWnd) hwndRet = pWnd->hwndSelf;
264 dprintf_win(stddeb,"FindWinToRepaint: found %04x\n",hwndRet);
265 return hwndRet;
269 /***********************************************************************
270 * WIN_SendParentNotify
272 * Send a WM_PARENTNOTIFY to all ancestors of the given window, unless
273 * the window has the WS_EX_NOPARENTNOTIFY style.
275 void WIN_SendParentNotify(HWND32 hwnd, WORD event, WORD idChild, LPARAM lValue)
277 LPPOINT16 lppt = (LPPOINT16)&lValue;
278 WND *wndPtr = WIN_FindWndPtr( hwnd );
279 BOOL bMouse = ((event <= WM_MOUSELAST) && (event >= WM_MOUSEFIRST));
281 /* if lValue contains cursor coordinates they have to be
282 * mapped to the client area of parent window */
284 if (bMouse) MapWindowPoints16( 0, hwnd, lppt, 1 );
286 while (wndPtr)
288 if ((wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) ||
289 !(wndPtr->dwStyle & WS_CHILD)) break;
291 if (bMouse)
293 lppt->x += wndPtr->rectClient.left;
294 lppt->y += wndPtr->rectClient.top;
297 wndPtr = wndPtr->parent;
298 SendMessage32A( wndPtr->hwndSelf, WM_PARENTNOTIFY,
299 MAKEWPARAM( event, idChild ), lValue );
304 /***********************************************************************
305 * WIN_DestroyWindow
307 * Destroy storage associated to a window. "Internals" p.358
309 static void WIN_DestroyWindow( WND* wndPtr )
311 HWND hwnd = wndPtr->hwndSelf;
312 WND* pWnd,*pNext;
314 dprintf_win( stddeb, "WIN_DestroyWindow: %04x\n", wndPtr->hwndSelf );
316 #ifdef CONFIG_IPC
317 if (main_block)
318 DDE_DestroyWindow(wndPtr->hwndSelf);
319 #endif /* CONFIG_IPC */
321 /* free child windows */
323 pNext = wndPtr->child;
324 while( (pWnd = pNext) )
326 pNext = pWnd->next;
327 WIN_DestroyWindow( pWnd );
330 SendMessage32A( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
332 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
334 WINPOS_CheckActive( hwnd );
335 if( hwnd == GetCapture32()) ReleaseCapture();
337 /* free resources associated with the window */
339 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
340 PROPERTY_RemoveWindowProps( wndPtr );
342 wndPtr->dwMagic = 0; /* Mark it as invalid */
343 wndPtr->hwndSelf = 0;
345 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
347 if (wndPtr->hrgnUpdate) DeleteObject32( wndPtr->hrgnUpdate );
348 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
351 /* toss stale messages from the queue */
353 if( wndPtr->hmemTaskQ )
355 int pos;
356 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) GlobalLock16(wndPtr->hmemTaskQ);
358 while( (pos = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != -1 )
359 QUEUE_RemoveMsg(msgQ, pos);
360 wndPtr->hmemTaskQ = 0;
363 if (!(wndPtr->dwStyle & WS_CHILD))
364 if (wndPtr->wIDmenu) DestroyMenu( (HMENU16)wndPtr->wIDmenu );
365 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
366 if (wndPtr->window) XDestroyWindow( display, wndPtr->window );
367 if (wndPtr->class->style & CS_OWNDC) DCE_FreeDCE( wndPtr->dce );
369 WINPROC_FreeProc( wndPtr->winproc );
371 wndPtr->class->cWindows--;
372 wndPtr->class = NULL;
374 USER_HEAP_FREE( hwnd );
377 /***********************************************************************
378 * WIN_ResetQueueWindows
380 void WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
382 WND* next;
384 while (wnd)
386 next = wnd->next;
387 if (wnd->hmemTaskQ == hQueue)
388 if( hNew ) wnd->hmemTaskQ = hNew;
389 else DestroyWindow( wnd->hwndSelf );
390 else WIN_ResetQueueWindows( wnd->child, hQueue, hNew );
391 wnd = next;
395 /***********************************************************************
396 * WIN_CreateDesktopWindow
398 * Create the desktop window.
400 BOOL32 WIN_CreateDesktopWindow(void)
402 CLASS *class;
403 HWND hwndDesktop;
405 dprintf_win(stddeb,"Creating desktop window\n");
407 if (!(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
408 return FALSE;
410 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
411 if (!hwndDesktop) return FALSE;
412 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
414 pWndDesktop->next = NULL;
415 pWndDesktop->child = NULL;
416 pWndDesktop->parent = NULL;
417 pWndDesktop->owner = NULL;
418 pWndDesktop->class = class;
419 pWndDesktop->winproc = NULL;
420 pWndDesktop->dwMagic = WND_MAGIC;
421 pWndDesktop->hwndSelf = hwndDesktop;
422 pWndDesktop->hInstance = 0;
423 pWndDesktop->rectWindow.left = 0;
424 pWndDesktop->rectWindow.top = 0;
425 pWndDesktop->rectWindow.right = SYSMETRICS_CXSCREEN;
426 pWndDesktop->rectWindow.bottom = SYSMETRICS_CYSCREEN;
427 pWndDesktop->rectClient = pWndDesktop->rectWindow;
428 pWndDesktop->rectNormal = pWndDesktop->rectWindow;
429 pWndDesktop->ptIconPos.x = -1;
430 pWndDesktop->ptIconPos.y = -1;
431 pWndDesktop->ptMaxPos.x = -1;
432 pWndDesktop->ptMaxPos.y = -1;
433 pWndDesktop->text = NULL;
434 pWndDesktop->hmemTaskQ = 0; /* Desktop does not belong to a task */
435 pWndDesktop->hrgnUpdate = 0;
436 pWndDesktop->hwndLastActive = hwndDesktop;
437 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
438 WS_CLIPSIBLINGS;
439 pWndDesktop->dwExStyle = 0;
440 pWndDesktop->dce = NULL;
441 pWndDesktop->pVScroll = NULL;
442 pWndDesktop->pHScroll = NULL;
443 pWndDesktop->pProp = NULL;
444 pWndDesktop->wIDmenu = 0;
445 pWndDesktop->flags = 0;
446 pWndDesktop->window = rootWindow;
447 pWndDesktop->hSysMenu = 0;
448 pWndDesktop->userdata = 0;
450 WINPROC_SetProc( &pWndDesktop->winproc, (WNDPROC16)class->winproc, 0 );
451 EVENT_RegisterWindow( pWndDesktop );
452 SendMessage32A( hwndDesktop, WM_NCCREATE, 0, 0 );
453 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
454 return TRUE;
458 /***********************************************************************
459 * WIN_CreateWindowEx
461 * Implementation of CreateWindowEx().
463 static HWND WIN_CreateWindowEx( CREATESTRUCT32A *cs, ATOM classAtom,
464 BOOL unicode )
466 CLASS *classPtr;
467 WND *wndPtr;
468 HWND16 hwnd, hwndLinkAfter;
469 POINT16 maxSize, maxPos, minTrack, maxTrack;
470 LRESULT wmcreate;
472 dprintf_win( stddeb, "CreateWindowEx: " );
473 if (HIWORD(cs->lpszName)) dprintf_win( stddeb, "'%s' ", cs->lpszName );
474 else dprintf_win( stddeb, "#%04x ", LOWORD(cs->lpszName) );
475 if (HIWORD(cs->lpszClass)) dprintf_win( stddeb, "'%s' ", cs->lpszClass );
476 else dprintf_win( stddeb, "#%04x ", LOWORD(cs->lpszClass) );
478 dprintf_win( stddeb, "%08lx %08lx %d,%d %dx%d %04x %04x %04x %p\n",
479 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
480 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams);
482 /* Find the parent window */
484 if (cs->hwndParent)
486 /* Make sure parent is valid */
487 if (!IsWindow( cs->hwndParent ))
489 fprintf( stderr, "CreateWindowEx: bad parent %04x\n", cs->hwndParent );
490 return 0;
493 else if (cs->style & WS_CHILD)
495 fprintf( stderr, "CreateWindowEx: no parent for child window\n" );
496 return 0; /* WS_CHILD needs a parent */
499 /* Find the window class */
501 if (!(classPtr = CLASS_FindClassByAtom( classAtom,
502 GetExePtr(cs->hInstance) )))
504 char buffer[256];
505 GlobalGetAtomName32A( classAtom, buffer, sizeof(buffer) );
506 fprintf( stderr, "CreateWindowEx: bad class '%s'\n", buffer );
507 return 0;
510 /* Fix the coordinates */
512 if (cs->x == CW_USEDEFAULT32) cs->x = cs->y = 0;
513 if (cs->cx == CW_USEDEFAULT32)
515 /* if (!(cs->style & (WS_CHILD | WS_POPUP))) cs->cx = cs->cy = 0;
516 else */
518 cs->cx = 600;
519 cs->cy = 400;
523 /* Create the window structure */
525 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
526 - sizeof(wndPtr->wExtra) )))
528 dprintf_win( stddeb, "CreateWindowEx: out of memory\n" );
529 return 0;
532 /* Fill the window structure */
534 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
535 wndPtr->next = NULL;
536 wndPtr->child = NULL;
538 if (cs->style & WS_CHILD)
540 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
541 wndPtr->owner = NULL;
543 else
545 wndPtr->parent = pWndDesktop;
546 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
547 wndPtr->owner = NULL;
548 else
549 wndPtr->owner = WIN_FindWndPtr(WIN_GetTopParent(cs->hwndParent));
552 wndPtr->window = 0;
553 wndPtr->class = classPtr;
554 wndPtr->winproc = NULL;
555 wndPtr->dwMagic = WND_MAGIC;
556 wndPtr->hwndSelf = hwnd;
557 wndPtr->hInstance = cs->hInstance;
558 wndPtr->ptIconPos.x = -1;
559 wndPtr->ptIconPos.y = -1;
560 wndPtr->ptMaxPos.x = -1;
561 wndPtr->ptMaxPos.y = -1;
562 wndPtr->text = NULL;
563 wndPtr->hmemTaskQ = GetTaskQueue(0);
564 wndPtr->hrgnUpdate = 0;
565 wndPtr->hwndLastActive = hwnd;
566 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
567 wndPtr->dwExStyle = cs->dwExStyle;
568 wndPtr->wIDmenu = 0;
569 wndPtr->flags = 0;
570 wndPtr->pVScroll = NULL;
571 wndPtr->pHScroll = NULL;
572 wndPtr->pProp = NULL;
573 wndPtr->hSysMenu = MENU_GetDefSysMenu();
574 wndPtr->userdata = 0;
576 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
578 /* Call the WH_CBT hook */
580 hwndLinkAfter = (cs->style & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
582 if (HOOK_IsHooked( WH_CBT ))
584 CBT_CREATEWND32A cbtc;
586 cbtc.lpcs = cs;
587 cbtc.hwndInsertAfter = hwndLinkAfter;
588 wmcreate = !HOOK_CallHooks32A( WH_CBT, HCBT_CREATEWND, hwnd,
589 (LPARAM)&cbtc );
590 if (!wmcreate)
592 dprintf_win(stddeb, "CreateWindowEx: CBT-hook returned 0\n");
593 USER_HEAP_FREE( hwnd );
594 return 0;
598 /* Set the window procedure */
600 classPtr->cWindows++;
601 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)classPtr->winproc, 0 );
603 /* Correct the window style */
605 if (!(cs->style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
607 wndPtr->dwStyle |= WS_CAPTION | WS_CLIPSIBLINGS;
608 wndPtr->flags |= WIN_NEED_SIZE;
610 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
612 /* Get class or window DC if needed */
614 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
615 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
616 else wndPtr->dce = NULL;
618 /* Insert the window in the linked list */
620 WIN_LinkWindow( hwnd, hwndLinkAfter );
622 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
624 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
626 NC_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack );
627 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
628 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
629 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
630 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
632 if (cs->cx <= 0) cs->cx = 1;
633 if (cs->cy <= 0) cs->cy = 1;
635 wndPtr->rectWindow.left = cs->x;
636 wndPtr->rectWindow.top = cs->y;
637 wndPtr->rectWindow.right = cs->x + cs->cx;
638 wndPtr->rectWindow.bottom = cs->y + cs->cy;
639 wndPtr->rectClient = wndPtr->rectWindow;
640 wndPtr->rectNormal = wndPtr->rectWindow;
642 /* Create the X window (only for top-level windows, and then only */
643 /* when there's no desktop window) */
645 if (!(cs->style & WS_CHILD) && (rootWindow == DefaultRootWindow(display)))
647 XSetWindowAttributes win_attr;
649 if (Options.managed && ((cs->style & (WS_DLGFRAME | WS_THICKFRAME)) ||
650 (cs->dwExStyle & WS_EX_DLGMODALFRAME)))
652 win_attr.event_mask = ExposureMask | KeyPressMask |
653 KeyReleaseMask | PointerMotionMask |
654 ButtonPressMask | ButtonReleaseMask |
655 FocusChangeMask | StructureNotifyMask;
656 win_attr.override_redirect = FALSE;
657 wndPtr->flags |= WIN_MANAGED;
659 else
661 win_attr.event_mask = ExposureMask | KeyPressMask |
662 KeyReleaseMask | PointerMotionMask |
663 ButtonPressMask | ButtonReleaseMask |
664 FocusChangeMask | StructureNotifyMask;
665 win_attr.override_redirect = TRUE;
667 win_attr.colormap = COLOR_GetColormap();
668 win_attr.backing_store = Options.backingstore ? WhenMapped : NotUseful;
669 win_attr.save_under = ((classPtr->style & CS_SAVEBITS) != 0);
670 win_attr.cursor = CURSORICON_XCursor;
671 wndPtr->window = XCreateWindow( display, rootWindow, cs->x, cs->y,
672 cs->cx, cs->cy, 0, CopyFromParent,
673 InputOutput, CopyFromParent,
674 CWEventMask | CWOverrideRedirect |
675 CWColormap | CWCursor | CWSaveUnder |
676 CWBackingStore, &win_attr );
678 if ((wndPtr->flags & WIN_MANAGED) &&
679 (cs->dwExStyle & WS_EX_DLGMODALFRAME))
681 XSizeHints* size_hints = XAllocSizeHints();
683 if (size_hints)
685 size_hints->min_width = size_hints->max_width = cs->cx;
686 size_hints->min_height = size_hints->max_height = cs->cy;
687 size_hints->flags = (PSize | PMinSize | PMaxSize);
688 XSetWMSizeHints( display, wndPtr->window, size_hints,
689 XA_WM_NORMAL_HINTS );
690 XFree(size_hints);
694 if (cs->hwndParent) /* Get window owner */
696 Window win = WIN_GetXWindow( cs->hwndParent );
697 if (win) XSetTransientForHint( display, wndPtr->window, win );
699 EVENT_RegisterWindow( wndPtr );
702 /* Set the window menu */
704 if ((cs->style & WS_CAPTION) && !(cs->style & WS_CHILD))
706 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
707 else
709 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
710 if (classPtr->menuNameA)
711 cs->hMenu = HIWORD(classPtr->menuNameA) ?
712 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
713 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
714 #else
715 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
716 if (menuName) cs->hMenu = LoadMenu16( cs->hInstance, menuName );
717 #endif
719 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
721 else wndPtr->wIDmenu = (UINT)cs->hMenu;
723 /* Send the WM_CREATE message
724 * Perhaps we shouldn't allow width/height changes as well.
725 * See p327 in "Internals".
728 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
729 if (unicode)
731 if (!SendMessage32W( hwnd, WM_NCCREATE, 0, (LPARAM)cs)) wmcreate = -1;
732 else
734 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
735 NULL, NULL, 0, &wndPtr->rectClient );
736 OffsetRect16(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
737 maxPos.y - wndPtr->rectWindow.top);
738 wmcreate = SendMessage32W( hwnd, WM_CREATE, 0, (LPARAM)cs );
741 else
743 if (!SendMessage32A( hwnd, WM_NCCREATE, 0, (LPARAM)cs)) wmcreate = -1;
744 else
746 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
747 NULL, NULL, 0, &wndPtr->rectClient );
748 OffsetRect16(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
749 maxPos.y - wndPtr->rectWindow.top);
750 wmcreate = SendMessage32A( hwnd, WM_CREATE, 0, (LPARAM)cs );
754 if (wmcreate == -1)
756 /* Abort window creation */
757 dprintf_win(stddeb,"CreateWindowEx: wmcreate==-1, aborting\n");
758 WIN_UnlinkWindow( hwnd );
759 WIN_DestroyWindow( wndPtr );
760 return 0;
763 /* Send the size messages */
765 if (!(wndPtr->flags & WIN_NEED_SIZE))
767 /* send it anyway */
768 SendMessage16( hwnd, WM_SIZE, SIZE_RESTORED,
769 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
770 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
771 SendMessage16( hwnd, WM_MOVE, 0, MAKELONG( wndPtr->rectClient.left,
772 wndPtr->rectClient.top ));
775 WIN_SendParentNotify( hwnd, WM_CREATE, wndPtr->wIDmenu, (LPARAM)hwnd );
776 if (!IsWindow(hwnd)) return 0;
778 /* Show the window, maximizing or minimizing if needed */
780 if (wndPtr->dwStyle & WS_MINIMIZE)
782 /* MinMaximize(hwnd, SW_SHOWMINNOACTIVE, 1) in "Internals" */
784 wndPtr->dwStyle &= ~WS_MAXIMIZE;
785 WINPOS_FindIconPos( hwnd );
786 SetWindowPos( hwnd, 0, wndPtr->ptIconPos.x, wndPtr->ptIconPos.y,
787 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
788 SWP_FRAMECHANGED | ((GetActiveWindow())? SWP_NOACTIVATE : 0) );
790 else if (wndPtr->dwStyle & WS_MAXIMIZE)
792 /* MinMaximize(hwnd, SW_SHOWMAXIMIZED, 1) */
794 NC_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack );
795 SetWindowPos( hwnd, 0, maxPos.x, maxPos.y, maxSize.x, maxSize.y,
796 ((GetActiveWindow())? SWP_NOACTIVATE : 0) | SWP_FRAMECHANGED );
799 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
801 /* Call WH_SHELL hook */
803 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
804 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
806 dprintf_win(stddeb, "CreateWindowEx: returning %04x\n", hwnd);
807 return hwnd;
811 /***********************************************************************
812 * CreateWindow16 (USER.41)
814 HWND16 CreateWindow16( LPCSTR className, LPCSTR windowName,
815 DWORD style, INT16 x, INT16 y, INT16 width,
816 INT16 height, HWND16 parent, HMENU16 menu,
817 HINSTANCE16 instance, LPVOID data )
819 return CreateWindowEx16( 0, className, windowName, style,
820 x, y, width, height, parent, menu, instance, data );
824 /***********************************************************************
825 * CreateWindowEx16 (USER.452)
827 HWND16 CreateWindowEx16( DWORD exStyle, LPCSTR className, LPCSTR windowName,
828 DWORD style, INT16 x, INT16 y, INT16 width,
829 INT16 height, HWND16 parent, HMENU16 menu,
830 HINSTANCE16 instance, LPVOID data )
832 ATOM classAtom;
833 CREATESTRUCT32A cs;
835 /* Find the class atom */
837 if (!(classAtom = GlobalFindAtom32A( className )))
839 fprintf( stderr, "CreateWindowEx16: bad class name " );
840 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
841 else fprintf( stderr, "'%s'\n", className );
842 return 0;
845 /* Fix the coordinates */
847 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)x;
848 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)y;
849 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)width;
850 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)height;
852 /* Create the window */
854 cs.lpCreateParams = data;
855 cs.hInstance = (HINSTANCE32)instance;
856 cs.hMenu = (HMENU32)menu;
857 cs.hwndParent = (HWND32)parent;
858 cs.style = style;
859 cs.lpszName = windowName;
860 cs.lpszClass = className;
861 cs.dwExStyle = exStyle;
862 return WIN_CreateWindowEx( &cs, classAtom, FALSE );
866 /***********************************************************************
867 * CreateWindowEx32A (USER32.82)
869 HWND32 CreateWindowEx32A( DWORD exStyle, LPCSTR className, LPCSTR windowName,
870 DWORD style, INT32 x, INT32 y, INT32 width,
871 INT32 height, HWND32 parent, HMENU32 menu,
872 HINSTANCE32 instance, LPVOID data )
874 ATOM classAtom;
875 CREATESTRUCT32A cs;
877 /* Find the class atom */
879 if (!(classAtom = GlobalFindAtom32A( className )))
881 fprintf( stderr, "CreateWindowEx32A: bad class name " );
882 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
883 else fprintf( stderr, "'%s'\n", className );
884 return 0;
887 /* Create the window */
889 cs.lpCreateParams = data;
890 cs.hInstance = instance;
891 cs.hMenu = menu;
892 cs.hwndParent = parent;
893 cs.x = x;
894 cs.y = y;
895 cs.cx = width;
896 cs.cy = height;
897 cs.style = style;
898 cs.lpszName = windowName;
899 cs.lpszClass = className;
900 cs.dwExStyle = exStyle;
901 return WIN_CreateWindowEx( &cs, classAtom, FALSE );
905 /***********************************************************************
906 * CreateWindowEx32W (USER32.83)
908 HWND32 CreateWindowEx32W( DWORD exStyle, LPCWSTR className, LPCWSTR windowName,
909 DWORD style, INT32 x, INT32 y, INT32 width,
910 INT32 height, HWND32 parent, HMENU32 menu,
911 HINSTANCE32 instance, LPVOID data )
913 ATOM classAtom;
914 CREATESTRUCT32W cs;
916 /* Find the class atom */
918 if (!(classAtom = GlobalFindAtom32W( className )))
920 if (HIWORD(className))
922 LPSTR cn = STRING32_DupUniToAnsi(className);
923 fprintf( stderr, "CreateWindowEx32W: bad class name '%s'\n",cn);
924 free(cn);
926 else
927 fprintf( stderr, "CreateWindowEx32W: bad class name %p\n", className );
928 return 0;
931 /* Create the window */
933 cs.lpCreateParams = data;
934 cs.hInstance = instance;
935 cs.hMenu = menu;
936 cs.hwndParent = parent;
937 cs.x = x;
938 cs.y = y;
939 cs.cx = width;
940 cs.cy = height;
941 cs.style = style;
942 cs.lpszName = windowName;
943 cs.lpszClass = className;
944 cs.dwExStyle = exStyle;
945 /* Note: we rely on the fact that CREATESTRUCT32A and */
946 /* CREATESTRUCT32W have the same layout. */
947 return WIN_CreateWindowEx( (CREATESTRUCT32A *)&cs, classAtom, TRUE );
951 /***********************************************************************
952 * WIN_CheckFocus
954 static void WIN_CheckFocus( WND* pWnd )
956 if( GetFocus16() == pWnd->hwndSelf )
957 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
960 /***********************************************************************
961 * WIN_SendDestroyMsg
963 static void WIN_SendDestroyMsg( WND* pWnd )
965 WND* pChild;
967 WIN_CheckFocus(pWnd);
969 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
970 if( !pWnd->window ) CLIPBOARD_DisOwn( pWnd );
972 SendMessage32A( pWnd->hwndSelf, WM_DESTROY, 0, 0);
974 if( !IsWindow(pWnd->hwndSelf) )
976 dprintf_win(stddeb,"\tdestroyed itself while in WM_DESTROY!\n");
977 return;
980 pChild = pWnd->child;
981 while( pChild )
983 WIN_SendDestroyMsg( pChild );
984 pChild = pChild->next;
986 WIN_CheckFocus(pWnd);
990 /***********************************************************************
991 * DestroyWindow (USER.53)
993 BOOL DestroyWindow( HWND hwnd )
995 WND * wndPtr;
997 dprintf_win(stddeb, "DestroyWindow(%04x)\n", hwnd);
999 /* Initialization */
1001 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1002 if (wndPtr == pWndDesktop) return FALSE; /* Can't destroy desktop */
1004 /* Call hooks */
1006 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1007 return FALSE;
1009 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1011 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1012 /* FIXME: clean up palette - see "Internals" p.352 */
1015 if( !QUEUE_IsDoomedQueue(wndPtr->hmemTaskQ) )
1016 WIN_SendParentNotify( hwnd, WM_DESTROY, wndPtr->wIDmenu, (LPARAM)hwnd );
1017 if( !IsWindow(hwnd) ) return TRUE;
1019 if( wndPtr->window ) CLIPBOARD_DisOwn( wndPtr ); /* before window is unmapped */
1021 /* Hide the window */
1023 if (wndPtr->dwStyle & WS_VISIBLE)
1025 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1026 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE |
1027 ((QUEUE_IsDoomedQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1028 if( !IsWindow(hwnd) ) return TRUE;
1031 /* Recursively destroy owned windows */
1033 if( !(wndPtr->dwStyle & WS_CHILD) )
1035 for (;;)
1037 WND *siblingPtr = wndPtr->parent->child; /* First sibling */
1038 while (siblingPtr)
1040 if (siblingPtr->owner == wndPtr)
1041 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1042 break;
1043 else
1044 siblingPtr->owner = NULL;
1045 siblingPtr = siblingPtr->next;
1047 if (siblingPtr) DestroyWindow( siblingPtr->hwndSelf );
1048 else break;
1051 WINPOS_ActivateOtherWindow(wndPtr);
1053 if( wndPtr->owner &&
1054 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1055 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1058 /* Send destroy messages */
1060 WIN_SendDestroyMsg( wndPtr );
1061 if( !IsWindow(hwnd) ) return TRUE;
1063 /* Unlink now so we won't bother with the children later on */
1065 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1067 /* Destroy the window storage */
1069 WIN_DestroyWindow( wndPtr );
1070 return TRUE;
1074 /***********************************************************************
1075 * CloseWindow (USER.43)
1077 BOOL CloseWindow(HWND hWnd)
1079 WND * wndPtr = WIN_FindWndPtr(hWnd);
1080 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD)) return TRUE;
1081 ShowWindow(hWnd, SW_MINIMIZE);
1082 return TRUE;
1086 /***********************************************************************
1087 * OpenIcon (USER.44)
1089 BOOL OpenIcon(HWND hWnd)
1091 if (!IsIconic(hWnd)) return FALSE;
1092 ShowWindow(hWnd, SW_SHOWNORMAL);
1093 return(TRUE);
1097 /***********************************************************************
1098 * WIN_FindWindow
1100 * Implementation of FindWindow() and FindWindowEx().
1102 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1103 LPCSTR title )
1105 WND *pWnd;
1106 CLASS *pClass = NULL;
1108 if (child)
1110 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1111 if (parent)
1113 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent)) return 0;
1115 else if (pWnd->parent != pWndDesktop) return 0;
1116 pWnd = pWnd->next;
1118 else
1120 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : pWndDesktop)) return 0;
1121 pWnd = pWnd->child;
1123 if (!pWnd) return 0;
1125 /* For a child window, all siblings will have the same hInstance, */
1126 /* so we can look for the class once and for all. */
1128 if (className && (pWnd->dwStyle & WS_CHILD))
1130 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1131 return 0;
1134 for ( ; pWnd; pWnd = pWnd->next)
1136 if (className && !(pWnd->dwStyle & WS_CHILD))
1138 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance)))
1139 continue; /* Skip this window */
1141 if (pClass && (pWnd->class != pClass))
1142 continue; /* Not the right class */
1144 /* Now check the title */
1146 if (!title) return pWnd->hwndSelf;
1147 if (pWnd->text && !strcmp( pWnd->text, title )) return pWnd->hwndSelf;
1149 return 0;
1154 /***********************************************************************
1155 * FindWindow16 (USER.50)
1157 HWND16 FindWindow16( SEGPTR className, LPCSTR title )
1159 return FindWindowEx16( 0, 0, className, title );
1163 /***********************************************************************
1164 * FindWindowEx16 (USER.427)
1166 HWND16 FindWindowEx16( HWND16 parent, HWND16 child,
1167 SEGPTR className, LPCSTR title )
1169 ATOM atom = 0;
1171 if (className)
1173 /* If the atom doesn't exist, then no class */
1174 /* with this name exists either. */
1175 if (!(atom = GlobalFindAtom16( className ))) return 0;
1177 return WIN_FindWindow( parent, child, atom, title );
1181 /***********************************************************************
1182 * FindWindow32A (USER32.197)
1184 HWND32 FindWindow32A( LPCSTR className, LPCSTR title )
1186 return FindWindowEx32A( 0, 0, className, title );
1190 /***********************************************************************
1191 * FindWindowEx32A (USER32.198)
1193 HWND32 FindWindowEx32A( HWND32 parent, HWND32 child,
1194 LPCSTR className, LPCSTR title )
1196 ATOM atom = 0;
1198 if (className)
1200 /* If the atom doesn't exist, then no class */
1201 /* with this name exists either. */
1202 if (!(atom = GlobalFindAtom32A( className ))) return 0;
1204 return WIN_FindWindow( 0, 0, atom, title );
1208 /***********************************************************************
1209 * FindWindowEx32W (USER32.199)
1211 HWND32 FindWindowEx32W( HWND32 parent, HWND32 child,
1212 LPCWSTR className, LPCWSTR title )
1214 ATOM atom = 0;
1215 char *buffer;
1216 HWND hwnd;
1218 if (className)
1220 /* If the atom doesn't exist, then no class */
1221 /* with this name exists either. */
1222 if (!(atom = GlobalFindAtom32W( className ))) return 0;
1224 buffer = title ? STRING32_DupUniToAnsi( title ) : NULL;
1225 hwnd = WIN_FindWindow( 0, 0, atom, buffer );
1226 if (buffer) free( buffer );
1227 return hwnd;
1231 /***********************************************************************
1232 * FindWindow32W (USER32.200)
1234 HWND32 FindWindow32W( LPCWSTR className, LPCWSTR title )
1236 return FindWindowEx32W( 0, 0, className, title );
1240 /**********************************************************************
1241 * WIN_GetDesktop
1243 WND *WIN_GetDesktop(void)
1245 return pWndDesktop;
1249 /**********************************************************************
1250 * GetDesktopWindow16 (USER.286)
1252 HWND16 GetDesktopWindow16(void)
1254 return (HWND16)pWndDesktop->hwndSelf;
1258 /**********************************************************************
1259 * GetDesktopWindow32 (USER32.231)
1261 HWND32 GetDesktopWindow32(void)
1263 return pWndDesktop->hwndSelf;
1267 /**********************************************************************
1268 * GetDesktopHwnd (USER.278)
1270 * Exactly the same thing as GetDesktopWindow(), but not documented.
1271 * Don't ask me why...
1273 HWND16 GetDesktopHwnd(void)
1275 return (HWND16)pWndDesktop->hwndSelf;
1279 /*******************************************************************
1280 * EnableWindow (USER.34)
1282 BOOL EnableWindow( HWND hwnd, BOOL enable )
1284 WND *wndPtr;
1286 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1287 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1289 /* Enable window */
1290 wndPtr->dwStyle &= ~WS_DISABLED;
1291 SendMessage16( hwnd, WM_ENABLE, TRUE, 0 );
1292 return TRUE;
1294 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1296 /* Disable window */
1297 wndPtr->dwStyle |= WS_DISABLED;
1298 if ((hwnd == GetFocus32()) || IsChild( hwnd, GetFocus32() ))
1299 SetFocus32( 0 ); /* A disabled window can't have the focus */
1300 if ((hwnd == GetCapture32()) || IsChild( hwnd, GetCapture32() ))
1301 ReleaseCapture(); /* A disabled window can't capture the mouse */
1302 SendMessage16( hwnd, WM_ENABLE, FALSE, 0 );
1303 return FALSE;
1305 return ((wndPtr->dwStyle & WS_DISABLED) != 0);
1309 /***********************************************************************
1310 * IsWindowEnabled (USER.35) (USER32.348)
1312 BOOL IsWindowEnabled(HWND hWnd)
1314 WND * wndPtr;
1316 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1317 return !(wndPtr->dwStyle & WS_DISABLED);
1321 /***********************************************************************
1322 * IsWindowUnicode (USER32.349)
1324 BOOL32 IsWindowUnicode( HWND32 hwnd )
1326 WND * wndPtr;
1328 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1329 return (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1333 /**********************************************************************
1334 * GetWindowWord (USER.133) (USER32.313)
1336 WORD GetWindowWord( HWND32 hwnd, INT32 offset )
1338 WND * wndPtr = WIN_FindWndPtr( hwnd );
1339 if (!wndPtr) return 0;
1340 if (offset >= 0)
1342 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1344 fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
1345 return 0;
1347 return *(WORD *)(((char *)wndPtr->wExtra) + offset);
1349 switch(offset)
1351 case GWW_ID: return wndPtr->wIDmenu;
1352 case GWW_HWNDPARENT: return wndPtr->parent ? wndPtr->parent->hwndSelf : 0;
1353 case GWW_HINSTANCE: return (WORD)wndPtr->hInstance;
1354 default:
1355 fprintf( stderr, "GetWindowWord: invalid offset %d\n", offset );
1356 return 0;
1361 /**********************************************************************
1362 * WIN_GetWindowInstance
1364 HINSTANCE16 WIN_GetWindowInstance( HWND32 hwnd )
1366 WND * wndPtr = WIN_FindWndPtr( hwnd );
1367 if (!wndPtr) return (HINSTANCE16)0;
1368 return wndPtr->hInstance;
1372 /**********************************************************************
1373 * SetWindowWord (USER.134) (USER32.523)
1375 WORD SetWindowWord( HWND32 hwnd, INT32 offset, WORD newval )
1377 WORD *ptr, retval;
1378 WND * wndPtr = WIN_FindWndPtr( hwnd );
1379 if (!wndPtr) return 0;
1380 if (offset >= 0)
1382 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1384 fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
1385 return 0;
1387 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1389 else switch(offset)
1391 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1392 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1393 case GWW_HWNDPARENT: return SetParent( hwnd, newval );
1394 default:
1395 fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
1396 return 0;
1398 retval = *ptr;
1399 *ptr = newval;
1400 return retval;
1404 /**********************************************************************
1405 * WIN_GetWindowLong
1407 * Helper function for GetWindowLong().
1409 static LONG WIN_GetWindowLong( HWND32 hwnd, INT32 offset, WINDOWPROCTYPE type )
1411 LONG retval;
1412 WND * wndPtr = WIN_FindWndPtr( hwnd );
1413 if (!wndPtr) return 0;
1414 if (offset >= 0)
1416 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1418 fprintf( stderr, "GetWindowLong: invalid offset %d\n", offset );
1419 return 0;
1421 retval = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1422 /* Special case for dialog window procedure */
1423 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1424 return (LONG)WINPROC_GetProc( (HWINDOWPROC)retval, type );
1425 return retval;
1427 switch(offset)
1429 case GWL_USERDATA: return wndPtr->userdata;
1430 case GWL_STYLE: return wndPtr->dwStyle;
1431 case GWL_EXSTYLE: return wndPtr->dwExStyle;
1432 case GWL_ID: return wndPtr->wIDmenu;
1433 case GWL_WNDPROC: return (LONG)WINPROC_GetProc( wndPtr->winproc,
1434 type );
1435 case GWL_HWNDPARENT: return wndPtr->parent ?
1436 (HWND32)wndPtr->parent->hwndSelf : 0;
1437 case GWL_HINSTANCE: return (HINSTANCE32)wndPtr->hInstance;
1438 default:
1439 fprintf( stderr, "GetWindowLong: unknown offset %d\n", offset );
1441 return 0;
1445 /**********************************************************************
1446 * WIN_SetWindowLong
1448 * Helper function for SetWindowLong().
1450 static LONG WIN_SetWindowLong( HWND32 hwnd, INT32 offset, LONG newval,
1451 WINDOWPROCTYPE type )
1453 LONG *ptr, retval;
1454 WND * wndPtr = WIN_FindWndPtr( hwnd );
1455 if (!wndPtr) return 0;
1456 if (offset >= 0)
1458 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1460 fprintf( stderr, "SetWindowLong: invalid offset %d\n", offset );
1461 return 0;
1463 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1464 /* Special case for dialog window procedure */
1465 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1467 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1468 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval, type );
1469 return retval;
1472 else switch(offset)
1474 case GWL_ID:
1475 case GWL_HINSTANCE:
1476 return SetWindowWord( hwnd, offset, (WORD)newval );
1477 case GWL_WNDPROC:
1478 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1479 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval, type );
1480 return retval;
1481 case GWL_STYLE:
1482 ptr = &wndPtr->dwStyle;
1483 /* Some bits can't be changed this way */
1484 newval &= ~(WS_VISIBLE | WS_CHILD);
1485 newval |= (*ptr & (WS_VISIBLE | WS_CHILD));
1486 break;
1487 case GWL_USERDATA: ptr = &wndPtr->userdata; break;
1488 case GWL_EXSTYLE: ptr = &wndPtr->dwExStyle; break;
1489 default:
1490 fprintf( stderr, "SetWindowLong: invalid offset %d\n", offset );
1491 return 0;
1493 retval = *ptr;
1494 *ptr = newval;
1495 return retval;
1499 /**********************************************************************
1500 * GetWindowLong16 (USER.135)
1502 LONG GetWindowLong16( HWND16 hwnd, INT16 offset )
1504 return WIN_GetWindowLong( (HWND32)hwnd, offset, WIN_PROC_16 );
1508 /**********************************************************************
1509 * GetWindowLong32A (USER32.304)
1511 LONG GetWindowLong32A( HWND32 hwnd, INT32 offset )
1513 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1517 /**********************************************************************
1518 * GetWindowLong32W (USER32.305)
1520 LONG GetWindowLong32W( HWND32 hwnd, INT32 offset )
1522 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1526 /**********************************************************************
1527 * SetWindowLong16 (USER.136)
1529 LONG SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1531 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1535 /**********************************************************************
1536 * SetWindowLong32A (USER32.516)
1538 LONG SetWindowLong32A( HWND32 hwnd, INT32 offset, LONG newval )
1540 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1544 /**********************************************************************
1545 * SetWindowLong32W (USER32.517)
1547 LONG SetWindowLong32W( HWND32 hwnd, INT32 offset, LONG newval )
1549 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1553 /*******************************************************************
1554 * GetWindowText16 (USER.36)
1556 INT16 GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
1558 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1562 /*******************************************************************
1563 * GetWindowText32A (USER32.308)
1565 INT32 GetWindowText32A( HWND32 hwnd, LPSTR lpString, INT32 nMaxCount )
1567 return (INT32)SendMessage32A( hwnd, WM_GETTEXT, nMaxCount,
1568 (LPARAM)lpString );
1572 /*******************************************************************
1573 * GetWindowText32W (USER32.311)
1575 INT32 GetWindowText32W( HWND32 hwnd, LPWSTR lpString, INT32 nMaxCount )
1577 return (INT32)SendMessage32W( hwnd, WM_GETTEXT, nMaxCount,
1578 (LPARAM)lpString );
1582 /*******************************************************************
1583 * SetWindowText16 (USER.37)
1585 void SetWindowText16( HWND16 hwnd, SEGPTR lpString )
1587 SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1591 /*******************************************************************
1592 * SetWindowText32A (USER32.)
1594 void SetWindowText32A( HWND32 hwnd, LPCSTR lpString )
1596 SendMessage32A( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1600 /*******************************************************************
1601 * SetWindowText32W (USER32.)
1603 void SetWindowText32W( HWND32 hwnd, LPCWSTR lpString )
1605 SendMessage32W( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1609 /*******************************************************************
1610 * GetWindowTextLength (USER.38)
1612 int GetWindowTextLength(HWND hwnd)
1614 return (int)SendMessage16(hwnd, WM_GETTEXTLENGTH, 0, 0 );
1618 /*******************************************************************
1619 * IsWindow (USER.47) (USER32.347)
1621 BOOL16 IsWindow( HWND32 hwnd )
1623 WND * wndPtr = WIN_FindWndPtr( hwnd );
1624 return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
1628 /*****************************************************************
1629 * GetParent16 (USER.46)
1631 HWND16 GetParent16( HWND16 hwnd )
1633 return (HWND16)GetParent32( hwnd );
1637 /*****************************************************************
1638 * GetParent32 (USER32.277)
1640 HWND32 GetParent32( HWND32 hwnd )
1642 WND *wndPtr = WIN_FindWndPtr(hwnd);
1643 if (!wndPtr) return 0;
1644 wndPtr = (wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner;
1645 return wndPtr ? wndPtr->hwndSelf : 0;
1649 /*****************************************************************
1650 * WIN_GetTopParent
1652 * Get the top-level parent for a child window.
1654 HWND32 WIN_GetTopParent( HWND32 hwnd )
1656 WND *wndPtr = WIN_FindWndPtr( hwnd );
1657 while (wndPtr && (wndPtr->dwStyle & WS_CHILD)) wndPtr = wndPtr->parent;
1658 return wndPtr ? wndPtr->hwndSelf : 0;
1662 /*****************************************************************
1663 * SetParent (USER.233)
1665 HWND SetParent(HWND hwndChild, HWND hwndNewParent)
1667 HWND oldParent;
1669 WND *wndPtr = WIN_FindWndPtr(hwndChild);
1670 WND *pWndParent = WIN_FindWndPtr( hwndNewParent );
1671 if (!wndPtr || !pWndParent || !(wndPtr->dwStyle & WS_CHILD)) return 0;
1673 oldParent = wndPtr->parent->hwndSelf;
1675 WIN_UnlinkWindow(hwndChild);
1676 if (hwndNewParent) wndPtr->parent = pWndParent;
1677 WIN_LinkWindow(hwndChild, HWND_BOTTOM);
1679 if (IsWindowVisible(hwndChild)) UpdateWindow(hwndChild);
1681 return oldParent;
1686 /*******************************************************************
1687 * IsChild (USER.48)
1689 BOOL IsChild( HWND parent, HWND child )
1691 WND * wndPtr = WIN_FindWndPtr( child );
1692 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1694 wndPtr = wndPtr->parent;
1695 if (wndPtr->hwndSelf == parent) return TRUE;
1697 return FALSE;
1701 /***********************************************************************
1702 * IsWindowVisible (USER.49) (USER32.350)
1704 BOOL IsWindowVisible( HWND hwnd )
1706 WND *wndPtr = WIN_FindWndPtr( hwnd );
1707 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1709 if (!(wndPtr->dwStyle & WS_VISIBLE)) return FALSE;
1710 wndPtr = wndPtr->parent;
1712 return (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
1715 /***********************************************************************
1716 * WIN_IsWindowDrawable
1718 * hwnd is drawable when it is visible, all parents are not
1719 * minimized, and it is itself not minimized unless we are
1720 * trying to draw icon and the default class icon is set.
1722 BOOL32 WIN_IsWindowDrawable( WND* wnd , BOOL32 icon )
1724 HWND hwnd= wnd->hwndSelf;
1725 BOOL32 yes = TRUE;
1727 while(wnd && yes)
1729 if( wnd->dwStyle & WS_MINIMIZE )
1730 if( wnd->hwndSelf != hwnd ) break;
1731 else if( icon && wnd->class->hIcon ) break;
1733 yes = yes && (wnd->dwStyle & WS_VISIBLE);
1734 wnd = wnd->parent; }
1735 return (!wnd && yes);
1738 /*******************************************************************
1739 * GetTopWindow (USER.229)
1741 HWND GetTopWindow( HWND hwnd )
1743 WND * wndPtr = WIN_FindWndPtr( hwnd );
1744 if (wndPtr && wndPtr->child) return wndPtr->child->hwndSelf;
1745 else return 0;
1749 /*******************************************************************
1750 * GetWindow (USER.262)
1752 HWND GetWindow( HWND hwnd, WORD rel )
1754 WND * wndPtr = WIN_FindWndPtr( hwnd );
1755 if (!wndPtr) return 0;
1756 switch(rel)
1758 case GW_HWNDFIRST:
1759 if (wndPtr->parent) return wndPtr->parent->child->hwndSelf;
1760 else return 0;
1762 case GW_HWNDLAST:
1763 if (!wndPtr->parent) return 0; /* Desktop window */
1764 while (wndPtr->next) wndPtr = wndPtr->next;
1765 return wndPtr->hwndSelf;
1767 case GW_HWNDNEXT:
1768 if (!wndPtr->next) return 0;
1769 return wndPtr->next->hwndSelf;
1771 case GW_HWNDPREV:
1772 if (!wndPtr->parent) return 0; /* Desktop window */
1773 wndPtr = wndPtr->parent->child; /* First sibling */
1774 if (wndPtr->hwndSelf == hwnd) return 0; /* First in list */
1775 while (wndPtr->next)
1777 if (wndPtr->next->hwndSelf == hwnd) return wndPtr->hwndSelf;
1778 wndPtr = wndPtr->next;
1780 return 0;
1782 case GW_OWNER:
1783 return wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
1785 case GW_CHILD:
1786 return wndPtr->child ? wndPtr->child->hwndSelf : 0;
1788 return 0;
1792 /*******************************************************************
1793 * GetNextWindow (USER.230)
1795 HWND GetNextWindow( HWND hwnd, WORD flag )
1797 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
1798 return GetWindow( hwnd, flag );
1801 /*******************************************************************
1802 * ShowOwnedPopups (USER.265)
1804 void ShowOwnedPopups( HWND owner, BOOL fShow )
1806 WND *pWnd = pWndDesktop->child;
1807 while (pWnd)
1809 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
1810 (pWnd->dwStyle & WS_POPUP))
1811 ShowWindow( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
1812 pWnd = pWnd->next;
1817 /*******************************************************************
1818 * GetLastActivePopup (USER.287)
1820 HWND GetLastActivePopup(HWND hwnd)
1822 WND *wndPtr;
1823 wndPtr = WIN_FindWndPtr(hwnd);
1824 if (wndPtr == NULL) return hwnd;
1825 return wndPtr->hwndLastActive;
1829 /*******************************************************************
1830 * WIN_BuildWinArray
1832 * Build an array of pointers to all children of a given window.
1833 * The array must be freed with HeapFree(SystemHeap).
1835 WND **WIN_BuildWinArray( WND *wndPtr )
1837 WND **list, **ppWnd;
1838 WND *pWnd;
1839 INT32 count;
1841 /* First count the windows */
1843 if (!wndPtr) wndPtr = pWndDesktop;
1844 for (pWnd = wndPtr->child, count = 0; pWnd; pWnd = pWnd->next) count++;
1845 count++; /* For the terminating NULL */
1847 /* Now build the list of all windows */
1849 if (!(list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * count )))
1850 return NULL;
1851 for (pWnd = wndPtr->child, ppWnd = list; pWnd; pWnd = pWnd->next)
1852 *ppWnd++ = pWnd;
1853 *ppWnd = NULL;
1854 return list;
1858 /*******************************************************************
1859 * EnumWindows16 (USER.54)
1861 BOOL16 EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
1863 WND **list, **ppWnd;
1865 /* We have to build a list of all windows first, to avoid */
1866 /* unpleasant side-effects, for instance if the callback */
1867 /* function changes the Z-order of the windows. */
1869 if (!(list = WIN_BuildWinArray( pWndDesktop ))) return FALSE;
1871 /* Now call the callback function for every window */
1873 for (ppWnd = list; *ppWnd; ppWnd++)
1875 /* Make sure that the window still exists */
1876 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
1877 if (!lpEnumFunc( (*ppWnd)->hwndSelf, lParam )) break;
1879 HeapFree( SystemHeap, 0, list );
1880 return TRUE;
1884 /*******************************************************************
1885 * EnumWindows32 (USER32.192)
1887 BOOL32 EnumWindows32( WNDENUMPROC32 lpEnumFunc, LPARAM lParam )
1889 return (BOOL32)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
1893 /**********************************************************************
1894 * EnumTaskWindows16 (USER.225)
1896 BOOL16 EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func, LPARAM lParam )
1898 WND **list, **ppWnd;
1899 HQUEUE16 hQueue = GetTaskQueue( hTask );
1901 /* This function is the same as EnumWindows(), */
1902 /* except for an added check on the window queue. */
1904 if (!(list = WIN_BuildWinArray( pWndDesktop ))) return FALSE;
1906 /* Now call the callback function for every window */
1908 for (ppWnd = list; *ppWnd; ppWnd++)
1910 /* Make sure that the window still exists */
1911 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
1912 if ((*ppWnd)->hmemTaskQ != hQueue) continue; /* Check the queue */
1913 if (!func( (*ppWnd)->hwndSelf, lParam )) break;
1915 HeapFree( SystemHeap, 0, list );
1916 return TRUE;
1920 /**********************************************************************
1921 * EnumThreadWindows (USER32.189)
1923 BOOL32 EnumThreadWindows( DWORD id, WNDENUMPROC32 func, LPARAM lParam )
1925 return (BOOL16)EnumTaskWindows16((HTASK16)id, (WNDENUMPROC16)func, lParam);
1929 /**********************************************************************
1930 * WIN_EnumChildWindows
1932 * Helper function for EnumChildWindows().
1934 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
1935 LPARAM lParam )
1937 WND **childList;
1938 BOOL16 ret = FALSE;
1940 while (*ppWnd)
1942 /* Make sure that the window still exists */
1943 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
1944 /* Build children list first */
1945 if (!(childList = WIN_BuildWinArray( *ppWnd ))) return FALSE;
1946 if (!func( (*ppWnd)->hwndSelf, lParam )) return FALSE;
1947 ret = WIN_EnumChildWindows( childList, func, lParam );
1948 HeapFree( SystemHeap, 0, childList );
1949 if (!ret) return FALSE;
1950 ppWnd++;
1952 return TRUE;
1956 /**********************************************************************
1957 * EnumChildWindows16 (USER.55)
1959 BOOL16 EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func, LPARAM lParam )
1961 WND **list, *pParent;
1963 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
1964 if (!(list = WIN_BuildWinArray( pParent ))) return FALSE;
1965 WIN_EnumChildWindows( list, func, lParam );
1966 HeapFree( SystemHeap, 0, list );
1967 return TRUE;
1971 /**********************************************************************
1972 * EnumChildWindows32 (USER32.177)
1974 BOOL32 EnumChildWindows32( HWND32 parent, WNDENUMPROC32 func, LPARAM lParam )
1976 return (BOOL32)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
1977 lParam );
1981 /*******************************************************************
1982 * AnyPopup (USER.52)
1984 BOOL AnyPopup(void)
1986 WND *wndPtr;
1987 for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next)
1988 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE)) return TRUE;
1989 return FALSE;
1992 /*******************************************************************
1993 * FlashWindow [USER.105]
1995 BOOL FlashWindow(HWND hWnd, BOOL bInvert)
1997 WND *wndPtr = WIN_FindWndPtr(hWnd);
1999 dprintf_win(stddeb,"FlashWindow: %04x\n", hWnd);
2001 if (!wndPtr) return FALSE;
2003 if (wndPtr->dwStyle & WS_MINIMIZE)
2005 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2007 HDC32 hDC = GetDC32(hWnd);
2009 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2010 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2012 ReleaseDC32( hWnd, hDC );
2013 wndPtr->flags |= WIN_NCACTIVATED;
2015 else
2017 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2018 RDW_UPDATENOW | RDW_FRAME, 0 );
2019 wndPtr->flags &= ~WIN_NCACTIVATED;
2021 return TRUE;
2023 else
2025 WPARAM16 wparam;
2026 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2027 else wparam = (hWnd == GetActiveWindow());
2029 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2030 return wparam;
2035 /*******************************************************************
2036 * SetSysModalWindow16 (USER.188)
2038 HWND16 SetSysModalWindow16( HWND16 hWnd )
2040 HWND hWndOldModal = hwndSysModal;
2041 hwndSysModal = hWnd;
2042 dprintf_win(stdnimp,"EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2043 return hWndOldModal;
2047 /*******************************************************************
2048 * GetSysModalWindow16 (USER.52)
2050 HWND16 GetSysModalWindow16(void)
2052 return hwndSysModal;
2056 /*******************************************************************
2057 * DRAG_QueryUpdate
2059 * recursively find a child that contains spDragInfo->pt point
2060 * and send WM_QUERYDROPOBJECT
2062 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL32 bNoSend )
2064 BOOL16 wParam,bResult = 0;
2065 POINT16 pt;
2066 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
2067 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
2068 RECT16 tempRect;
2070 if( !ptrQueryWnd || !ptrDragInfo ) return 0;
2072 pt = ptrDragInfo->pt;
2074 GetWindowRect16(hQueryWnd,&tempRect);
2076 if( !PtInRect16(&tempRect,pt) ||
2077 (ptrQueryWnd->dwStyle & WS_DISABLED) )
2078 return 0;
2080 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
2082 tempRect = ptrQueryWnd->rectClient;
2083 if(ptrQueryWnd->dwStyle & WS_CHILD)
2084 MapWindowPoints16(ptrQueryWnd->parent->hwndSelf,0,(LPPOINT16)&tempRect,2);
2086 if( PtInRect16(&tempRect,pt) )
2088 wParam = 0;
2090 for (ptrWnd = ptrQueryWnd->child; ptrWnd ;ptrWnd = ptrWnd->next)
2091 if( ptrWnd->dwStyle & WS_VISIBLE )
2093 GetWindowRect16(ptrWnd->hwndSelf,&tempRect);
2095 if( PtInRect16(&tempRect,pt) )
2096 break;
2099 if(ptrWnd)
2101 dprintf_msg(stddeb,"DragQueryUpdate: hwnd = %04x, %d %d - %d %d\n",
2102 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
2103 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
2104 if( !(ptrWnd->dwStyle & WS_DISABLED) )
2105 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
2108 if(bResult) return bResult;
2110 else wParam = 1;
2112 else wParam = 1;
2114 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
2116 ptrDragInfo->hScope = hQueryWnd;
2118 bResult = ( bNoSend )
2119 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
2120 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
2121 (WPARAM16)wParam ,(LPARAM) spDragInfo );
2122 if( !bResult )
2123 ptrDragInfo->pt = pt;
2125 return bResult;
2128 /*******************************************************************
2129 * DragDetect ( USER.465 )
2132 BOOL16 DragDetect(HWND16 hWnd, POINT16 pt)
2134 MSG16 msg;
2135 RECT16 rect;
2137 rect.left = pt.x - wDragWidth;
2138 rect.right = pt.x + wDragWidth;
2140 rect.top = pt.y - wDragHeight;
2141 rect.bottom = pt.y + wDragHeight;
2143 SetCapture32(hWnd);
2145 while(1)
2147 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
2149 if( msg.message == WM_LBUTTONUP )
2151 ReleaseCapture();
2152 return 0;
2154 if( msg.message == WM_MOUSEMOVE )
2156 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
2158 ReleaseCapture();
2159 return 1;
2163 WaitMessage();
2166 return 0;
2169 /******************************************************************************
2170 * DragObject ( USER.464 )
2173 DWORD DragObject(HWND hwndScope, HWND hWnd, WORD wObj, HANDLE16 hOfStruct,
2174 WORD szList , HCURSOR16 hCursor)
2176 MSG16 msg;
2177 LPDRAGINFO lpDragInfo;
2178 SEGPTR spDragInfo;
2179 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
2180 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
2181 WND *wndPtr = WIN_FindWndPtr(hWnd);
2182 DWORD dwRet = 0;
2183 short dragDone = 0;
2184 HCURSOR16 hCurrentCursor = 0;
2185 HWND hCurrentWnd = 0;
2186 BOOL16 b;
2188 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
2189 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
2191 if( !lpDragInfo || !spDragInfo ) return 0L;
2193 hBummer = LoadCursor16(0,IDC_BUMMER);
2195 if( !hBummer || !wndPtr )
2197 GlobalFree16(hDragInfo);
2198 return 0L;
2201 if(hCursor)
2203 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
2205 GlobalFree16(hDragInfo);
2206 return 0L;
2209 if( hDragCursor == hCursor ) hDragCursor = 0;
2210 else hCursor = hDragCursor;
2212 hOldCursor = SetCursor(hDragCursor);
2215 lpDragInfo->hWnd = hWnd;
2216 lpDragInfo->hScope = 0;
2217 lpDragInfo->wFlags = wObj;
2218 lpDragInfo->hList = szList; /* near pointer! */
2219 lpDragInfo->hOfStruct = hOfStruct;
2220 lpDragInfo->l = 0L;
2222 SetCapture32(hWnd);
2223 ShowCursor(1);
2225 while( !dragDone )
2227 WaitMessage();
2229 if( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) )
2230 continue;
2232 *(lpDragInfo+1) = *lpDragInfo;
2234 lpDragInfo->pt = msg.pt;
2236 /* update DRAGINFO struct */
2237 dprintf_msg(stddeb,"drag: lpDI->hScope = %04x\n",lpDragInfo->hScope);
2239 if( (b = DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE)) > 0 )
2240 hCurrentCursor = hCursor;
2241 else
2243 hCurrentCursor = hBummer;
2244 lpDragInfo->hScope = 0;
2246 if( hCurrentCursor )
2247 SetCursor(hCurrentCursor);
2249 dprintf_msg(stddeb,"drag: got %04x\n", b);
2251 /* send WM_DRAGLOOP */
2252 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer) ,
2253 (LPARAM) spDragInfo );
2254 /* send WM_DRAGSELECT or WM_DRAGMOVE */
2255 if( hCurrentWnd != lpDragInfo->hScope )
2257 if( hCurrentWnd )
2258 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
2259 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
2260 HIWORD(spDragInfo)) );
2261 hCurrentWnd = lpDragInfo->hScope;
2262 if( hCurrentWnd )
2263 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
2265 else
2266 if( hCurrentWnd )
2267 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
2270 /* check if we're done */
2271 if( msg.message == WM_LBUTTONUP || msg.message == WM_NCLBUTTONUP )
2272 dragDone = TRUE;
2275 ReleaseCapture();
2276 ShowCursor(0);
2278 if( hCursor )
2280 SetCursor(hOldCursor);
2281 if( hDragCursor )
2282 DestroyCursor(hDragCursor);
2285 if( hCurrentCursor != hBummer )
2286 dwRet = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
2287 (WPARAM16)hWnd, (LPARAM)spDragInfo );
2288 GlobalFree16(hDragInfo);
2290 return dwRet;