2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
16 #include "sysmetrics.h"
17 #include "cursoricon.h"
22 #include "nonclient.h"
27 #include "shm_main_blk.h"
32 /* #define DEBUG_WIN */
33 /* #define DEBUG_MENU */
37 static WND
*pWndDesktop
= NULL
;
39 static HWND hwndSysModal
= 0;
41 static WORD wDragWidth
= 4;
42 static WORD wDragHeight
= 3;
44 extern HCURSOR
CURSORICON_IconToCursor(HICON
);
45 extern HQUEUE
QUEUE_GetDoomedQueue();
47 /***********************************************************************
50 * Return a pointer to the WND structure corresponding to a HWND.
52 WND
* WIN_FindWndPtr( HWND hwnd
)
56 if (!hwnd
) return NULL
;
57 ptr
= (WND
*) USER_HEAP_LIN_ADDR( hwnd
);
58 if (ptr
->dwMagic
!= WND_MAGIC
) return NULL
;
59 if (ptr
->hwndSelf
!= hwnd
)
61 fprintf( stderr
, "Can't happen: hwnd %04x self pointer is %04x\n",
62 hwnd
, ptr
->hwndSelf
);
69 /***********************************************************************
72 * Dump the content of a window structure to stderr.
74 void WIN_DumpWindow( HWND hwnd
)
80 if (!(ptr
= WIN_FindWndPtr( hwnd
)))
82 fprintf( stderr
, "%04x is not a window handle\n", hwnd
);
86 if (!GetClassName32A( hwnd
, className
, sizeof(className
) ))
87 strcpy( className
, "#NULL#" );
89 fprintf( stderr
, "Window %04x (%p):\n", hwnd
, ptr
);
91 "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
92 "inst=%04x taskQ=%04x updRgn=%04x active=%04x hdce=%04x idmenu=%04x\n"
93 "style=%08lx exstyle=%08lx wndproc=%08lx text='%s'\n"
94 "client=%d,%d-%d,%d window=%d,%d-%d,%d iconpos=%d,%d maxpos=%d,%d\n"
95 "sysmenu=%04x flags=%04x props=%04x vscroll=%04x hscroll=%04x\n",
96 ptr
->next
, ptr
->child
, ptr
->parent
, ptr
->owner
,
97 ptr
->class, className
, ptr
->hInstance
, ptr
->hmemTaskQ
,
98 ptr
->hrgnUpdate
, ptr
->hwndLastActive
, ptr
->hdce
, ptr
->wIDmenu
,
99 ptr
->dwStyle
, ptr
->dwExStyle
, (DWORD
)ptr
->lpfnWndProc
,
100 ptr
->text
? ptr
->text
: "",
101 ptr
->rectClient
.left
, ptr
->rectClient
.top
, ptr
->rectClient
.right
,
102 ptr
->rectClient
.bottom
, ptr
->rectWindow
.left
, ptr
->rectWindow
.top
,
103 ptr
->rectWindow
.right
, ptr
->rectWindow
.bottom
, ptr
->ptIconPos
.x
,
104 ptr
->ptIconPos
.y
, ptr
->ptMaxPos
.x
, ptr
->ptMaxPos
.y
, ptr
->hSysMenu
,
105 ptr
->flags
, ptr
->hProp
, ptr
->hVScroll
, ptr
->hHScroll
);
107 if (ptr
->class->cbWndExtra
)
109 fprintf( stderr
, "extra bytes:" );
110 for (i
= 0; i
< ptr
->class->cbWndExtra
; i
++)
111 fprintf( stderr
, " %02x", *((BYTE
*)ptr
->wExtra
+i
) );
112 fprintf( stderr
, "\n" );
114 fprintf( stderr
, "\n" );
118 /***********************************************************************
121 * Walk the windows tree and print each window on stderr.
123 void WIN_WalkWindows( HWND hwnd
, int indent
)
128 ptr
= hwnd
? WIN_FindWndPtr( hwnd
) : pWndDesktop
;
131 fprintf( stderr
, "*** Invalid window handle\n" );
135 if (!indent
) /* first time around */
136 fprintf( stderr
, "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
137 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc");
141 fprintf(stderr
, "%*s%04x%*s", indent
, "", ptr
->hwndSelf
, 13-indent
,"");
143 GlobalGetAtomName16(ptr
->class->atomName
,className
,sizeof(className
));
145 fprintf( stderr
, "%08lx %-6.4x %-17.17s %08x %04x:%04x\n",
146 (DWORD
)ptr
, ptr
->hmemTaskQ
, className
,
147 (unsigned) ptr
->dwStyle
,
148 HIWORD(ptr
->lpfnWndProc
),
149 LOWORD(ptr
->lpfnWndProc
));
151 if (ptr
->child
) WIN_WalkWindows( ptr
->child
->hwndSelf
, indent
+1 );
157 /***********************************************************************
160 * Return the X window associated to a window.
162 Window
WIN_GetXWindow( HWND hwnd
)
164 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
165 while (wndPtr
&& !wndPtr
->window
) wndPtr
= wndPtr
->parent
;
166 return wndPtr
? wndPtr
->window
: 0;
170 /***********************************************************************
173 * Remove a window from the siblings linked list.
175 BOOL
WIN_UnlinkWindow( HWND hwnd
)
177 WND
*wndPtr
, **ppWnd
;
179 if (!(wndPtr
= WIN_FindWndPtr( hwnd
)) || !wndPtr
->parent
) return FALSE
;
180 ppWnd
= &wndPtr
->parent
->child
;
181 while (*ppWnd
!= wndPtr
) ppWnd
= &(*ppWnd
)->next
;
182 *ppWnd
= wndPtr
->next
;
187 /***********************************************************************
190 * Insert a window into the siblings linked list.
191 * The window is inserted after the specified window, which can also
192 * be specified as HWND_TOP or HWND_BOTTOM.
194 BOOL
WIN_LinkWindow( HWND hwnd
, HWND hwndInsertAfter
)
196 WND
*wndPtr
, **ppWnd
;
198 if (!(wndPtr
= WIN_FindWndPtr( hwnd
)) || !wndPtr
->parent
) return FALSE
;
200 if ((hwndInsertAfter
== HWND_TOP
) || (hwndInsertAfter
== HWND_BOTTOM
))
202 ppWnd
= &wndPtr
->parent
->child
; /* Point to first sibling hwnd */
203 if (hwndInsertAfter
== HWND_BOTTOM
) /* Find last sibling hwnd */
204 while (*ppWnd
) ppWnd
= &(*ppWnd
)->next
;
206 else /* Normal case */
208 WND
* afterPtr
= WIN_FindWndPtr( hwndInsertAfter
);
209 if (!afterPtr
) return FALSE
;
210 ppWnd
= &afterPtr
->next
;
212 wndPtr
->next
= *ppWnd
;
218 /***********************************************************************
219 * WIN_FindWinToRepaint
221 * Find a window that needs repaint.
223 HWND
WIN_FindWinToRepaint( HWND hwnd
, HQUEUE hQueue
)
226 WND
*pWnd
= pWndDesktop
;
228 /* Note: the desktop window never gets WM_PAINT messages */
229 pWnd
= hwnd
? WIN_FindWndPtr( hwnd
) : pWndDesktop
->child
;
231 for ( ; pWnd
; pWnd
= pWnd
->next
)
233 if (!(pWnd
->dwStyle
& WS_VISIBLE
) || (pWnd
->flags
& WIN_NO_REDRAW
))
235 dprintf_win( stddeb
, "FindWinToRepaint: skipping window %04x\n",
239 if ((pWnd
->hmemTaskQ
== hQueue
) &&
240 (pWnd
->hrgnUpdate
|| (pWnd
->flags
& WIN_INTERNAL_PAINT
))) break;
243 if ((hwndRet
= WIN_FindWinToRepaint( pWnd
->child
->hwndSelf
, hQueue
)) )
249 hwndRet
= pWnd
->hwndSelf
;
251 /* look among siblings if we got a transparent window */
252 while (pWnd
&& ((pWnd
->dwExStyle
& WS_EX_TRANSPARENT
) ||
253 !(pWnd
->hrgnUpdate
|| (pWnd
->flags
& WIN_INTERNAL_PAINT
))))
257 if (pWnd
) hwndRet
= pWnd
->hwndSelf
;
258 dprintf_win(stddeb
,"FindWinToRepaint: found %04x\n",hwndRet
);
263 /***********************************************************************
264 * WIN_SendParentNotify
266 * Send a WM_PARENTNOTIFY to all ancestors of the given window, unless
267 * the window has the WS_EX_NOPARENTNOTIFY style.
269 void WIN_SendParentNotify( HWND hwnd
, WORD event
, WORD idChild
, LONG lValue
)
271 LPPOINT16 lppt
= (LPPOINT16
)&lValue
;
272 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
273 BOOL bMouse
= ((event
<= WM_MOUSELAST
) && (event
>= WM_MOUSEFIRST
));
275 /* if lValue contains cursor coordinates they have to be
276 * mapped to the client area of parent window */
278 if (bMouse
) MapWindowPoints16(0, hwnd
, lppt
, 1);
280 else lValue
= MAKELONG( LOWORD(lValue
), idChild
);
285 if ((wndPtr
->dwExStyle
& WS_EX_NOPARENTNOTIFY
) ||
286 !(wndPtr
->dwStyle
& WS_CHILD
)) break;
290 lppt
->x
+= wndPtr
->rectClient
.left
;
291 lppt
->y
+= wndPtr
->rectClient
.top
;
294 wndPtr
= wndPtr
->parent
;
296 SendMessage32A( wndPtr
->hwndSelf
, WM_PARENTNOTIFY
,
297 MAKEWPARAM( event
, idChild
), lValue
);
299 SendMessage16( wndPtr
->hwndSelf
, WM_PARENTNOTIFY
, event
, (LPARAM
)lValue
);
305 /***********************************************************************
308 * Set the window procedure and return the old one.
310 static WNDPROC16
WIN_SetWndProc(WND
*pWnd
, WNDPROC16 proc
, WINDOWPROCTYPE type
)
312 WNDPROC16 oldProc
= pWnd
->lpfnWndProc
;
313 if (type
== WIN_PROC_16
) pWnd
->lpfnWndProc
= proc
;
314 else pWnd
->lpfnWndProc
= WINPROC_AllocWinProc( (WNDPROC32
)proc
, type
);
315 WINPROC_FreeWinProc( oldProc
);
320 /***********************************************************************
323 * Destroy storage associated to a window
325 static void WIN_DestroyWindow( HWND hwnd
)
327 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
331 DDE_DestroyWindow(hwnd
);
332 #endif /* CONFIG_IPC */
335 WIN_UnlinkWindow( hwnd
); /* Remove the window from the linked list */
336 TIMER_RemoveWindowTimers( hwnd
);
337 wndPtr
->dwMagic
= 0; /* Mark it as invalid */
338 wndPtr
->hwndSelf
= 0;
339 if ((wndPtr
->hrgnUpdate
) || (wndPtr
->flags
& WIN_INTERNAL_PAINT
))
341 if (wndPtr
->hrgnUpdate
) DeleteObject( wndPtr
->hrgnUpdate
);
342 QUEUE_DecPaintCount( wndPtr
->hmemTaskQ
);
344 if (!(wndPtr
->dwStyle
& WS_CHILD
))
346 if (wndPtr
->wIDmenu
) DestroyMenu( (HMENU
)wndPtr
->wIDmenu
);
348 if (wndPtr
->hSysMenu
) DestroyMenu( wndPtr
->hSysMenu
);
349 if (wndPtr
->window
) XDestroyWindow( display
, wndPtr
->window
);
350 if (wndPtr
->class->style
& CS_OWNDC
) DCE_FreeDCE( wndPtr
->hdce
);
351 WIN_SetWndProc( wndPtr
, (WNDPROC16
)0, WIN_PROC_16
);
352 wndPtr
->class->cWindows
--;
353 USER_HEAP_FREE( hwnd
);
357 /***********************************************************************
358 * WIN_DestroyQueueWindows
360 void WIN_DestroyQueueWindows( WND
* wnd
, HQUEUE hQueue
)
367 if (wnd
->hmemTaskQ
== hQueue
) DestroyWindow( wnd
->hwndSelf
);
368 else WIN_DestroyQueueWindows( wnd
->child
, hQueue
);
374 /***********************************************************************
375 * WIN_CreateDesktopWindow
377 * Create the desktop window.
379 BOOL
WIN_CreateDesktopWindow(void)
385 if (!(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM
, 0 )))
388 hwndDesktop
= USER_HEAP_ALLOC( sizeof(WND
)+class->cbWndExtra
);
389 if (!hwndDesktop
) return FALSE
;
390 pWndDesktop
= (WND
*) USER_HEAP_LIN_ADDR( hwndDesktop
);
392 pWndDesktop
->next
= NULL
;
393 pWndDesktop
->child
= NULL
;
394 pWndDesktop
->parent
= NULL
;
395 pWndDesktop
->owner
= NULL
;
396 pWndDesktop
->class = class;
397 pWndDesktop
->dwMagic
= WND_MAGIC
;
398 pWndDesktop
->hwndSelf
= hwndDesktop
;
399 pWndDesktop
->hInstance
= 0;
400 pWndDesktop
->rectWindow
.left
= 0;
401 pWndDesktop
->rectWindow
.top
= 0;
402 pWndDesktop
->rectWindow
.right
= SYSMETRICS_CXSCREEN
;
403 pWndDesktop
->rectWindow
.bottom
= SYSMETRICS_CYSCREEN
;
404 pWndDesktop
->rectClient
= pWndDesktop
->rectWindow
;
405 pWndDesktop
->rectNormal
= pWndDesktop
->rectWindow
;
406 pWndDesktop
->ptIconPos
.x
= -1;
407 pWndDesktop
->ptIconPos
.y
= -1;
408 pWndDesktop
->ptMaxPos
.x
= -1;
409 pWndDesktop
->ptMaxPos
.y
= -1;
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
->lpfnWndProc
= (WNDPROC16
)0;
415 pWndDesktop
->dwStyle
= WS_VISIBLE
| WS_CLIPCHILDREN
|
417 pWndDesktop
->dwExStyle
= 0;
418 pWndDesktop
->hdce
= 0;
419 pWndDesktop
->hVScroll
= 0;
420 pWndDesktop
->hHScroll
= 0;
421 pWndDesktop
->wIDmenu
= 0;
422 pWndDesktop
->flags
= 0;
423 pWndDesktop
->window
= rootWindow
;
424 pWndDesktop
->hSysMenu
= 0;
425 pWndDesktop
->hProp
= 0;
426 WIN_SetWndProc( pWndDesktop
, class->lpfnWndProc
,
427 WINPROC_GetWinProcType(class->lpfnWndProc
) );
428 EVENT_RegisterWindow( pWndDesktop
->window
, hwndDesktop
);
429 SendMessage32A( hwndDesktop
, WM_NCCREATE
, 0, 0 );
430 if ((hdc
= GetDC( hwndDesktop
)) != 0)
432 SendMessage32A( hwndDesktop
, WM_ERASEBKGND
, hdc
, 0 );
433 ReleaseDC( hwndDesktop
, hdc
);
439 /***********************************************************************
442 * Implementation of CreateWindowEx().
444 static HWND
WIN_CreateWindowEx( DWORD exStyle
, ATOM classAtom
, DWORD style
,
445 INT16 x
, INT16 y
, INT16 width
, INT16 height
,
446 HWND parent
, HMENU menu
, HINSTANCE16 instance
)
451 POINT16 maxSize
, maxPos
, minTrack
, maxTrack
;
453 /* Find the parent window */
457 /* Make sure parent is valid */
458 if (!IsWindow( parent
))
460 fprintf( stderr
, "CreateWindowEx: bad parent %04x\n", parent
);
464 else if (style
& WS_CHILD
)
466 fprintf( stderr
, "CreateWindowEx: no parent for child window\n" );
467 return 0; /* WS_CHILD needs a parent */
470 /* Find the window class */
472 if (!(classPtr
= CLASS_FindClassByAtom( classAtom
, GetExePtr(instance
) )))
475 GlobalGetAtomName32A( classAtom
, buffer
, sizeof(buffer
) );
476 fprintf( stderr
, "CreateWindowEx: bad class '%s'\n", buffer
);
480 /* Fix the coordinates */
482 if (x
== CW_USEDEFAULT16
) x
= y
= 0;
483 if (width
== CW_USEDEFAULT16
)
485 /* if (!(style & (WS_CHILD | WS_POPUP))) width = height = 0;
493 /* Create the window structure */
495 if (!(hwnd
= USER_HEAP_ALLOC( sizeof(*wndPtr
) + classPtr
->cbWndExtra
496 - sizeof(wndPtr
->wExtra
) )))
498 dprintf_win( stddeb
, "CreateWindowEx: out of memory\n" );
502 /* Fill the window structure */
504 wndPtr
= (WND
*) USER_HEAP_LIN_ADDR( hwnd
);
506 wndPtr
->child
= NULL
;
507 wndPtr
->parent
= (style
& WS_CHILD
) ? WIN_FindWndPtr( parent
) : pWndDesktop
;
508 wndPtr
->owner
= (style
& WS_CHILD
) ? NULL
: WIN_FindWndPtr(WIN_GetTopParent(parent
));
510 wndPtr
->class = classPtr
;
511 wndPtr
->dwMagic
= WND_MAGIC
;
512 wndPtr
->hwndSelf
= hwnd
;
513 wndPtr
->hInstance
= instance
;
514 wndPtr
->ptIconPos
.x
= -1;
515 wndPtr
->ptIconPos
.y
= -1;
516 wndPtr
->ptMaxPos
.x
= -1;
517 wndPtr
->ptMaxPos
.y
= -1;
519 wndPtr
->hmemTaskQ
= GetTaskQueue(0);
520 wndPtr
->hrgnUpdate
= 0;
521 wndPtr
->hwndLastActive
= hwnd
;
522 wndPtr
->lpfnWndProc
= (WNDPROC16
)0;
523 wndPtr
->dwStyle
= style
& ~WS_VISIBLE
;
524 wndPtr
->dwExStyle
= exStyle
;
527 wndPtr
->hVScroll
= 0;
528 wndPtr
->hHScroll
= 0;
529 wndPtr
->hSysMenu
= MENU_GetDefSysMenu();
532 if (classPtr
->cbWndExtra
) memset( wndPtr
->wExtra
, 0, classPtr
->cbWndExtra
);
533 classPtr
->cWindows
++;
535 /* Correct the window style */
537 if (!(style
& (WS_POPUP
| WS_CHILD
))) /* Overlapped window */
539 wndPtr
->dwStyle
|= WS_CAPTION
| WS_CLIPSIBLINGS
;
540 wndPtr
->flags
|= WIN_NEED_SIZE
;
542 if (exStyle
& WS_EX_DLGMODALFRAME
) wndPtr
->dwStyle
&= ~WS_THICKFRAME
;
544 /* Get class or window DC if needed */
546 if (classPtr
->style
& CS_OWNDC
) wndPtr
->hdce
= DCE_AllocDCE(DCE_WINDOW_DC
);
547 else if (classPtr
->style
& CS_CLASSDC
) wndPtr
->hdce
= classPtr
->hdce
;
548 else wndPtr
->hdce
= 0;
550 /* Set the window procedure */
552 WIN_SetWndProc( wndPtr
, classPtr
->lpfnWndProc
,
553 WINPROC_GetWinProcType(classPtr
->lpfnWndProc
) );
555 /* Insert the window in the linked list */
557 WIN_LinkWindow( hwnd
, HWND_TOP
);
559 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
561 if ((style
& WS_THICKFRAME
) || !(style
& (WS_POPUP
| WS_CHILD
)))
563 NC_GetMinMaxInfo( hwnd
, &maxSize
, &maxPos
, &minTrack
, &maxTrack
);
564 if (maxSize
.x
< width
) width
= maxSize
.x
;
565 if (maxSize
.y
< height
) height
= maxSize
.y
;
567 if (width
<= 0) width
= 1;
568 if (height
<= 0) height
= 1;
570 wndPtr
->rectWindow
.left
= x
;
571 wndPtr
->rectWindow
.top
= y
;
572 wndPtr
->rectWindow
.right
= x
+ width
;
573 wndPtr
->rectWindow
.bottom
= y
+ height
;
574 wndPtr
->rectClient
= wndPtr
->rectWindow
;
575 wndPtr
->rectNormal
= wndPtr
->rectWindow
;
577 /* Create the X window (only for top-level windows, and then only */
578 /* when there's no desktop window) */
580 if (!(style
& WS_CHILD
) && (rootWindow
== DefaultRootWindow(display
)))
582 XSetWindowAttributes win_attr
;
583 Atom XA_WM_DELETE_WINDOW
;
585 if (Options
.managed
&& ((style
& (WS_DLGFRAME
| WS_THICKFRAME
)) ||
586 (exStyle
& WS_EX_DLGMODALFRAME
)))
588 win_attr
.event_mask
= ExposureMask
| KeyPressMask
|
589 KeyReleaseMask
| PointerMotionMask
|
590 ButtonPressMask
| ButtonReleaseMask
|
591 FocusChangeMask
| StructureNotifyMask
;
592 win_attr
.override_redirect
= FALSE
;
593 wndPtr
->flags
|= WIN_MANAGED
;
597 win_attr
.event_mask
= ExposureMask
| KeyPressMask
|
598 KeyReleaseMask
| PointerMotionMask
|
599 ButtonPressMask
| ButtonReleaseMask
|
601 win_attr
.override_redirect
= TRUE
;
603 win_attr
.colormap
= COLOR_WinColormap
;
604 win_attr
.backing_store
= Options
.backingstore
? WhenMapped
: NotUseful
;
605 win_attr
.save_under
= ((classPtr
->style
& CS_SAVEBITS
) != 0);
606 win_attr
.cursor
= CURSORICON_XCursor
;
607 wndPtr
->window
= XCreateWindow( display
, rootWindow
, x
, y
,
608 width
, height
, 0, CopyFromParent
,
609 InputOutput
, CopyFromParent
,
610 CWEventMask
| CWOverrideRedirect
|
611 CWColormap
| CWCursor
| CWSaveUnder
|
612 CWBackingStore
, &win_attr
);
613 XA_WM_DELETE_WINDOW
= XInternAtom( display
, "WM_DELETE_WINDOW",
615 XSetWMProtocols( display
, wndPtr
->window
, &XA_WM_DELETE_WINDOW
, 1 );
616 if (parent
) /* Get window owner */
618 Window win
= WIN_GetXWindow( parent
);
619 if (win
) XSetTransientForHint( display
, wndPtr
->window
, win
);
621 EVENT_RegisterWindow( wndPtr
->window
, hwnd
);
624 /* Set the window menu */
626 if ((style
& WS_CAPTION
) && !(style
& WS_CHILD
))
628 if (menu
) SetMenu(hwnd
, menu
);
631 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
632 if (classPtr
->menuNameA
)
633 menu
= HIWORD(classPtr
->menuNameA
) ?
634 LoadMenu( instance
, SEGPTR_GET(classPtr
->menuNameA
) ) :
635 LoadMenu( instance
, (SEGPTR
)classPtr
->menuNameA
);
637 SEGPTR menuName
= (SEGPTR
)GetClassLong16( hwnd
, GCL_MENUNAME
);
638 if (menuName
) menu
= LoadMenu( instance
, menuName
);
641 if (menu
) SetMenu( hwnd
, menu
);
643 else wndPtr
->wIDmenu
= (UINT
)menu
;
649 /***********************************************************************
650 * WIN_FinalWindowInit
652 static HWND
WIN_FinalWindowInit( WND
*wndPtr
, DWORD style
)
654 if (!(wndPtr
->flags
& WIN_NEED_SIZE
))
657 SendMessage16( wndPtr
->hwndSelf
, WM_SIZE
, SIZE_RESTORED
,
658 MAKELONG(wndPtr
->rectClient
.right
-wndPtr
->rectClient
.left
,
659 wndPtr
->rectClient
.bottom
-wndPtr
->rectClient
.top
));
660 SendMessage16( wndPtr
->hwndSelf
, WM_MOVE
, 0,
661 MAKELONG(wndPtr
->rectClient
.left
, wndPtr
->rectClient
.top
) );
664 WIN_SendParentNotify( wndPtr
->hwndSelf
, WM_CREATE
, wndPtr
->wIDmenu
,
665 (LONG
)wndPtr
->hwndSelf
);
666 if (!IsWindow(wndPtr
->hwndSelf
)) return 0;
668 /* Show the window, maximizing or minimizing if needed */
670 if (wndPtr
->dwStyle
& WS_MINIMIZE
)
672 wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
673 WINPOS_FindIconPos( wndPtr
->hwndSelf
);
674 SetWindowPos(wndPtr
->hwndSelf
, 0, wndPtr
->ptIconPos
.x
,
675 wndPtr
->ptIconPos
.y
, SYSMETRICS_CXICON
, SYSMETRICS_CYICON
,
677 (style
& WS_VISIBLE
) ? SWP_SHOWWINDOW
: 0 );
679 else if (wndPtr
->dwStyle
& WS_MAXIMIZE
)
681 POINT16 maxSize
, maxPos
, minTrack
, maxTrack
;
682 NC_GetMinMaxInfo( wndPtr
->hwndSelf
, &maxSize
, &maxPos
,
683 &minTrack
, &maxTrack
);
684 SetWindowPos( wndPtr
->hwndSelf
, 0, maxPos
.x
, maxPos
.y
, maxSize
.x
,
685 maxSize
.y
, SWP_FRAMECHANGED
|
686 (style
& WS_VISIBLE
) ? SWP_SHOWWINDOW
: 0 );
688 else if (style
& WS_VISIBLE
) ShowWindow( wndPtr
->hwndSelf
, SW_SHOW
);
690 /* Call WH_SHELL hook */
692 if (!(wndPtr
->dwStyle
& WS_CHILD
) && !wndPtr
->owner
)
693 HOOK_CallHooks( WH_SHELL
, HSHELL_WINDOWCREATED
, wndPtr
->hwndSelf
, 0 );
695 return wndPtr
->hwndSelf
;
699 /***********************************************************************
700 * CreateWindow16 (USER.41)
702 HWND16
CreateWindow16( SEGPTR className
, SEGPTR windowName
,
703 DWORD style
, INT16 x
, INT16 y
, INT16 width
,
704 INT16 height
, HWND16 parent
, HMENU16 menu
,
705 HINSTANCE16 instance
, SEGPTR data
)
707 return CreateWindowEx16( 0, className
, windowName
, style
,
708 x
, y
, width
, height
, parent
, menu
, instance
, data
);
712 /***********************************************************************
713 * CreateWindowEx16 (USER.452)
715 HWND16
CreateWindowEx16( DWORD exStyle
, SEGPTR className
, SEGPTR windowName
,
716 DWORD style
, INT16 x
, INT16 y
, INT16 width
,
717 INT16 height
, HWND16 parent
, HMENU16 menu
,
718 HINSTANCE16 instance
, SEGPTR data
)
725 dprintf_win( stddeb
, "CreateWindowEx: " );
726 if (HIWORD(windowName
))
727 dprintf_win( stddeb
, "'%s' ", (char *)PTR_SEG_TO_LIN(windowName
) );
729 dprintf_win( stddeb
, "%04x ", LOWORD(windowName
) );
730 if (HIWORD(className
))
731 dprintf_win( stddeb
, "'%s' ", (char *)PTR_SEG_TO_LIN(className
) );
733 dprintf_win( stddeb
, "%04x ", LOWORD(className
) );
735 dprintf_win(stddeb
, "%08lx %08lx %d,%d %dx%d %04x %04x %04x %08lx\n",
736 exStyle
, style
, x
, y
, width
, height
,
737 parent
, menu
, instance
, (DWORD
)data
);
739 /* Find the class atom */
741 if (!(classAtom
= GlobalFindAtom16( className
)))
743 fprintf( stderr
, "CreateWindowEx16: bad class name " );
744 if (!HIWORD(className
)) fprintf( stderr
, "%04x\n", LOWORD(className
) );
745 else fprintf( stderr
, "'%s'\n", (char *)PTR_SEG_TO_LIN(className
) );
749 hwnd
= WIN_CreateWindowEx( exStyle
, classAtom
, style
, x
, y
, width
, height
,
750 parent
, menu
, instance
);
752 wndPtr
= (WND
*) USER_HEAP_LIN_ADDR( hwnd
);
754 /* Send the WM_CREATE message */
757 if (WINPROC_GetWinProcType( wndPtr
->lpfnWndProc
) == WIN_PROC_16
)
759 /* Build the CREATESTRUCT on the 16-bit stack. */
760 /* This is really ugly, but some programs (notably the */
761 /* "Undocumented Windows" examples) want it that way. */
762 if (!CallWndProcNCCREATE16( wndPtr
->lpfnWndProc
, wndPtr
->hInstance
,
763 wndPtr
->dwExStyle
, className
, windowName
, wndPtr
->dwStyle
,
764 wndPtr
->rectWindow
.left
, wndPtr
->rectWindow
.top
,
765 wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
,
766 wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
,
767 parent
, menu
, wndPtr
->hInstance
, data
, hwnd
, WM_NCCREATE
, 0,
768 MAKELONG( IF1632_Saved16_sp
-sizeof(CREATESTRUCT16
),
769 IF1632_Saved16_ss
) ))
773 WINPOS_SendNCCalcSize( hwnd
, FALSE
, &wndPtr
->rectWindow
,
774 NULL
, NULL
, 0, &wndPtr
->rectClient
);
775 wmcreate
= CallWndProcNCCREATE16( wndPtr
->lpfnWndProc
,
776 wndPtr
->hInstance
, wndPtr
->dwExStyle
, className
,
777 windowName
, wndPtr
->dwStyle
,
778 wndPtr
->rectWindow
.left
, wndPtr
->rectWindow
.top
,
779 wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
,
780 wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
,
781 parent
, menu
, wndPtr
->hInstance
, data
, hwnd
, WM_CREATE
, 0,
782 MAKELONG( IF1632_Saved16_sp
-sizeof(CREATESTRUCT16
),
783 IF1632_Saved16_ss
) );
786 else /* We have a 32-bit window procedure */
790 cs
.lpCreateParams
= (LPVOID
)data
;
791 cs
.hInstance
= wndPtr
->hInstance
;
792 cs
.hMenu
= wndPtr
->wIDmenu
;
793 cs
.hwndParent
= parent
;
794 cs
.cx
= wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
;
795 cs
.cy
= wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
;
796 cs
.x
= wndPtr
->rectWindow
.left
;
797 cs
.y
= wndPtr
->rectWindow
.top
;
798 cs
.style
= wndPtr
->dwStyle
| (style
& WS_VISIBLE
);
799 cs
.lpszName
= PTR_SEG_TO_LIN(windowName
);
800 cs
.lpszClass
= PTR_SEG_TO_LIN(className
);
801 cs
.dwExStyle
= wndPtr
->dwExStyle
;
803 if (!SendMessage32A( hwnd
, WM_NCCREATE
, 0, (LPARAM
)&cs
)) wmcreate
= -1;
806 WINPOS_SendNCCalcSize( hwnd
, FALSE
, &wndPtr
->rectWindow
,
807 NULL
, NULL
, 0, &wndPtr
->rectClient
);
808 wmcreate
= SendMessage32A( hwnd
, WM_CREATE
, 0, (LPARAM
)&cs
);
814 /* Abort window creation */
815 dprintf_win(stddeb
,"CreateWindowEx: wmcreate==-1, aborting\n");
816 WIN_DestroyWindow( hwnd
);
820 dprintf_win(stddeb
, "CreateWindowEx16: return %04x\n", hwnd
);
821 return WIN_FinalWindowInit( wndPtr
, style
);
825 /***********************************************************************
826 * CreateWindowEx32A (USER32.82)
828 HWND32
CreateWindowEx32A( DWORD exStyle
, LPCSTR className
, LPCSTR windowName
,
829 DWORD style
, INT32 x
, INT32 y
, INT32 width
,
830 INT32 height
, HWND32 parent
, HMENU32 menu
,
831 HINSTANCE32 instance
, LPVOID data
)
839 /* Find the class atom */
841 if (!(classAtom
= GlobalFindAtom32A( className
)))
843 fprintf( stderr
, "CreateWindowEx32A: bad class name " );
844 if (!HIWORD(className
)) fprintf( stderr
, "%04x\n", LOWORD(className
) );
845 else fprintf( stderr
, "'%s'\n", className
);
849 /* Fix the coordinates */
851 if (x
== CW_USEDEFAULT32
) x
= y
= (UINT32
)CW_USEDEFAULT16
;
852 if (width
== CW_USEDEFAULT32
) width
= height
= (UINT32
)CW_USEDEFAULT16
;
854 /* Create the window structure */
856 hwnd
= WIN_CreateWindowEx( exStyle
, classAtom
, style
, x
, y
, width
, height
,
857 parent
, menu
, instance
);
859 wndPtr
= (WND
*) USER_HEAP_LIN_ADDR( hwnd
);
861 /* Send the WM_CREATE message */
863 cs
.lpCreateParams
= data
;
864 cs
.hInstance
= wndPtr
->hInstance
;
865 cs
.hMenu
= wndPtr
->wIDmenu
;
866 cs
.hwndParent
= parent
;
867 cs
.cx
= wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
;
868 cs
.cy
= wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
;
869 cs
.x
= wndPtr
->rectWindow
.left
;
870 cs
.y
= wndPtr
->rectWindow
.top
;
871 cs
.style
= wndPtr
->dwStyle
| (style
& WS_VISIBLE
);
872 cs
.lpszName
= windowName
;
873 cs
.lpszClass
= className
;
874 cs
.dwExStyle
= wndPtr
->dwExStyle
;
876 if (!SendMessage32A( hwnd
, WM_NCCREATE
, 0, (LPARAM
)&cs
)) wmcreate
= -1;
879 WINPOS_SendNCCalcSize( hwnd
, FALSE
, &wndPtr
->rectWindow
,
880 NULL
, NULL
, 0, &wndPtr
->rectClient
);
881 wmcreate
= SendMessage32A( hwnd
, WM_CREATE
, 0, (LPARAM
)&cs
);
886 /* Abort window creation */
887 dprintf_win(stddeb
,"CreateWindowEx32A: wmcreate==-1, aborting\n");
888 WIN_DestroyWindow( hwnd
);
892 dprintf_win(stddeb
, "CreateWindowEx32A: return %04x\n", hwnd
);
893 return WIN_FinalWindowInit( wndPtr
, style
);
897 /***********************************************************************
898 * CreateWindowEx32W (USER32.83)
900 HWND32
CreateWindowEx32W( DWORD exStyle
, LPCWSTR className
, LPCWSTR windowName
,
901 DWORD style
, INT32 x
, INT32 y
, INT32 width
,
902 INT32 height
, HWND32 parent
, HMENU32 menu
,
903 HINSTANCE32 instance
, LPVOID data
)
911 /* Find the class atom */
913 if (!(classAtom
= GlobalFindAtom32W( className
)))
915 fprintf( stderr
, "CreateWindowEx32W: bad class name %p\n", className
);
919 /* Fix the coordinates */
921 if (x
== CW_USEDEFAULT32
) x
= y
= (UINT32
)CW_USEDEFAULT16
;
922 if (width
== CW_USEDEFAULT32
) width
= height
= (UINT32
)CW_USEDEFAULT16
;
924 /* Create the window structure */
926 hwnd
= WIN_CreateWindowEx( exStyle
, classAtom
, style
, x
, y
, width
, height
,
927 parent
, menu
, instance
);
929 wndPtr
= (WND
*) USER_HEAP_LIN_ADDR( hwnd
);
931 /* Send the WM_CREATE message */
933 cs
.lpCreateParams
= data
;
934 cs
.hInstance
= wndPtr
->hInstance
;
935 cs
.hMenu
= wndPtr
->wIDmenu
;
936 cs
.hwndParent
= parent
;
937 cs
.cx
= wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
;
938 cs
.cy
= wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
;
939 cs
.x
= wndPtr
->rectWindow
.left
;
940 cs
.y
= wndPtr
->rectWindow
.top
;
941 cs
.style
= wndPtr
->dwStyle
| (style
& WS_VISIBLE
);
942 cs
.lpszName
= windowName
;
943 cs
.lpszClass
= className
;
944 cs
.dwExStyle
= wndPtr
->dwExStyle
;
946 if (!SendMessage32W( hwnd
, WM_NCCREATE
, 0, (LPARAM
)&cs
)) wmcreate
= -1;
949 WINPOS_SendNCCalcSize( hwnd
, FALSE
, &wndPtr
->rectWindow
,
950 NULL
, NULL
, 0, &wndPtr
->rectClient
);
951 wmcreate
= SendMessage32W( hwnd
, WM_CREATE
, 0, (LPARAM
)&cs
);
956 /* Abort window creation */
957 dprintf_win(stddeb
,"CreateWindowEx32W: wmcreate==-1, aborting\n");
958 WIN_DestroyWindow( hwnd
);
962 dprintf_win(stddeb
, "CreateWindowEx32W: return %04x\n", hwnd
);
963 return WIN_FinalWindowInit( wndPtr
, style
);
967 /***********************************************************************
968 * DestroyWindow (USER.53)
970 BOOL
DestroyWindow( HWND hwnd
)
974 dprintf_win(stddeb
, "DestroyWindow(%04x)\n", hwnd
);
978 if (hwnd
== pWndDesktop
->hwndSelf
) return FALSE
; /* Can't destroy desktop*/
979 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
981 /* Top-level window */
983 if (!(wndPtr
->dwStyle
& WS_CHILD
) && !wndPtr
->owner
)
985 HOOK_CallHooks( WH_SHELL
, HSHELL_WINDOWDESTROYED
, hwnd
, 0L );
986 /* FIXME: clean up palette - see "Internals" p.352 */
989 /* Hide the window */
991 if (wndPtr
->dwStyle
& WS_VISIBLE
)
992 SetWindowPos( hwnd
, 0, 0, 0, 0, 0, SWP_HIDEWINDOW
| SWP_NOACTIVATE
|
993 SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOSIZE
);
994 if ((hwnd
== GetCapture()) || IsChild( hwnd
, GetCapture() ))
996 if (!QUEUE_GetDoomedQueue())
997 WIN_SendParentNotify( hwnd
, WM_DESTROY
, wndPtr
->wIDmenu
, (LONG
)hwnd
);
999 /* Recursively destroy owned windows */
1003 WND
*siblingPtr
= wndPtr
->parent
->child
; /* First sibling */
1006 if (siblingPtr
->owner
== wndPtr
) break;
1007 siblingPtr
= siblingPtr
->next
;
1009 if (siblingPtr
) DestroyWindow( siblingPtr
->hwndSelf
);
1013 /* Send destroy messages and destroy children */
1015 SendMessage16( hwnd
, WM_DESTROY
, 0, 0 );
1016 while (wndPtr
->child
) /* The child removes itself from the list */
1017 DestroyWindow( wndPtr
->child
->hwndSelf
);
1018 SendMessage16( hwnd
, WM_NCDESTROY
, 0, 0 );
1020 /* Destroy the window */
1022 WIN_DestroyWindow( hwnd
);
1027 /***********************************************************************
1028 * CloseWindow (USER.43)
1030 BOOL
CloseWindow(HWND hWnd
)
1032 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
1033 if (wndPtr
->dwStyle
& WS_CHILD
) return TRUE
;
1034 ShowWindow(hWnd
, SW_MINIMIZE
);
1039 /***********************************************************************
1040 * OpenIcon (USER.44)
1042 BOOL
OpenIcon(HWND hWnd
)
1044 if (!IsIconic(hWnd
)) return FALSE
;
1045 ShowWindow(hWnd
, SW_SHOWNORMAL
);
1050 /***********************************************************************
1053 * Implementation of FindWindow() and FindWindowEx().
1055 static HWND
WIN_FindWindow( HWND parent
, HWND child
, ATOM className
,
1059 CLASS
*pClass
= NULL
;
1063 if (!(pWnd
= WIN_FindWndPtr( child
))) return 0;
1066 if (!pWnd
->parent
|| (pWnd
->parent
->hwndSelf
!= parent
)) return 0;
1068 else if (pWnd
->parent
!= pWndDesktop
) return 0;
1073 if (!(pWnd
= parent
? WIN_FindWndPtr(parent
) : pWndDesktop
)) return 0;
1076 if (!pWnd
) return 0;
1078 /* For a child window, all siblings will have the same hInstance, */
1079 /* so we can look for the class once and for all. */
1081 if (className
&& (pWnd
->dwStyle
& WS_CHILD
))
1083 if (!(pClass
= CLASS_FindClassByAtom( className
, pWnd
->hInstance
)))
1087 for ( ; pWnd
; pWnd
= pWnd
->next
)
1089 if (className
&& !(pWnd
->dwStyle
& WS_CHILD
))
1091 if (!(pClass
= CLASS_FindClassByAtom( className
, pWnd
->hInstance
)))
1092 continue; /* Skip this window */
1094 if (pClass
&& (pWnd
->class != pClass
))
1095 continue; /* Not the right class */
1097 /* Now check the title */
1099 if (!title
) return pWnd
->hwndSelf
;
1100 if (pWnd
->text
&& !strcmp( pWnd
->text
, title
)) return pWnd
->hwndSelf
;
1107 /***********************************************************************
1108 * FindWindow16 (USER.50)
1110 HWND
FindWindow16( SEGPTR className
, LPCSTR title
)
1112 return FindWindowEx16( 0, 0, className
, title
);
1116 /***********************************************************************
1117 * FindWindowEx16 (USER.427)
1119 HWND
FindWindowEx16( HWND parent
, HWND child
, SEGPTR className
, LPCSTR title
)
1123 atom
= className
? GlobalFindAtom16( className
) : 0;
1124 return WIN_FindWindow( parent
, child
, atom
, title
);
1128 /***********************************************************************
1129 * FindWindow32A (USER32.197)
1131 HWND
FindWindow32A( LPCSTR className
, LPCSTR title
)
1133 return FindWindowEx32A( 0, 0, className
, title
);
1137 /***********************************************************************
1138 * FindWindowEx32A (USER32.198)
1140 HWND
FindWindowEx32A( HWND parent
, HWND child
, LPCSTR className
, LPCSTR title
)
1144 atom
= className
? GlobalFindAtom32A( className
) : 0;
1145 return WIN_FindWindow( 0, 0, atom
, title
);
1149 /***********************************************************************
1150 * FindWindowEx32W (USER32.199)
1152 HWND
FindWindowEx32W(HWND parent
, HWND child
, LPCWSTR className
, LPCWSTR title
)
1158 atom
= className
? GlobalFindAtom32W( className
) : 0;
1159 buffer
= STRING32_DupUniToAnsi( title
);
1160 hwnd
= WIN_FindWindow( 0, 0, atom
, buffer
);
1166 /***********************************************************************
1167 * FindWindow32W (USER32.200)
1169 HWND
FindWindow32W( LPCWSTR className
, LPCWSTR title
)
1171 return FindWindowEx32W( 0, 0, className
, title
);
1175 /**********************************************************************
1178 WND
*WIN_GetDesktop(void)
1184 /**********************************************************************
1185 * GetDesktopWindow (USER.286)
1187 HWND
GetDesktopWindow(void)
1189 return pWndDesktop
->hwndSelf
;
1193 /**********************************************************************
1194 * GetDesktopHwnd (USER.278)
1196 * Exactly the same thing as GetDesktopWindow(), but not documented.
1197 * Don't ask me why...
1199 HWND
GetDesktopHwnd(void)
1201 return pWndDesktop
->hwndSelf
;
1205 /*******************************************************************
1206 * EnableWindow (USER.34)
1208 BOOL
EnableWindow( HWND hwnd
, BOOL enable
)
1212 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
1213 if (enable
&& (wndPtr
->dwStyle
& WS_DISABLED
))
1216 wndPtr
->dwStyle
&= ~WS_DISABLED
;
1217 SendMessage16( hwnd
, WM_ENABLE
, TRUE
, 0 );
1220 else if (!enable
&& !(wndPtr
->dwStyle
& WS_DISABLED
))
1222 /* Disable window */
1223 wndPtr
->dwStyle
|= WS_DISABLED
;
1224 if ((hwnd
== GetFocus()) || IsChild( hwnd
, GetFocus() ))
1225 SetFocus( 0 ); /* A disabled window can't have the focus */
1226 if ((hwnd
== GetCapture()) || IsChild( hwnd
, GetCapture() ))
1227 ReleaseCapture(); /* A disabled window can't capture the mouse */
1228 SendMessage16( hwnd
, WM_ENABLE
, FALSE
, 0 );
1231 return ((wndPtr
->dwStyle
& WS_DISABLED
) != 0);
1235 /***********************************************************************
1236 * IsWindowEnabled (USER.35) (USER32.348)
1238 BOOL
IsWindowEnabled(HWND hWnd
)
1242 if (!(wndPtr
= WIN_FindWndPtr(hWnd
))) return FALSE
;
1243 return !(wndPtr
->dwStyle
& WS_DISABLED
);
1247 /***********************************************************************
1248 * IsWindowUnicode (USER32.349)
1250 BOOL
IsWindowUnicode( HWND hwnd
)
1254 if (!(wndPtr
= WIN_FindWndPtr(hwnd
))) return FALSE
;
1255 return (WINPROC_GetWinProcType( wndPtr
->lpfnWndProc
) == WIN_PROC_32W
);
1259 /**********************************************************************
1260 * GetWindowWord (USER.133) (USER32.313)
1262 WORD
GetWindowWord( HWND32 hwnd
, INT32 offset
)
1264 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
1265 if (!wndPtr
) return 0;
1266 if (offset
>= 0) return *(WORD
*)(((char *)wndPtr
->wExtra
) + offset
);
1269 case GWW_ID
: return wndPtr
->wIDmenu
;
1270 case GWW_HWNDPARENT
: return wndPtr
->parent
? wndPtr
->parent
->hwndSelf
: 0;
1271 case GWW_HINSTANCE
: return (WORD
)wndPtr
->hInstance
;
1273 fprintf( stderr
, "GetWindowWord: invalid offset %d\n", offset
);
1279 /**********************************************************************
1280 * WIN_GetWindowInstance
1282 HINSTANCE
WIN_GetWindowInstance(HWND hwnd
)
1284 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
1285 if (!wndPtr
) return (HINSTANCE
)0;
1286 return wndPtr
->hInstance
;
1290 /**********************************************************************
1291 * SetWindowWord (USER.134) (USER32.523)
1293 WORD
SetWindowWord( HWND32 hwnd
, INT32 offset
, WORD newval
)
1296 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
1297 if (!wndPtr
) return 0;
1298 if (offset
>= 0) ptr
= (WORD
*)(((char *)wndPtr
->wExtra
) + offset
);
1301 case GWW_ID
: ptr
= (WORD
*)&wndPtr
->wIDmenu
; break;
1302 case GWW_HINSTANCE
: ptr
= (WORD
*)&wndPtr
->hInstance
; break;
1304 fprintf( stderr
, "SetWindowWord: invalid offset %d\n", offset
);
1313 /**********************************************************************
1314 * GetWindowLong (USER.135)
1316 LONG
GetWindowLong( HWND32 hwnd
, INT32 offset
)
1318 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
1319 if (!wndPtr
) return 0;
1320 if (offset
>= 0) return *(LONG
*)(((char *)wndPtr
->wExtra
) + offset
);
1323 case GWL_USERDATA
: return 0;
1324 case GWL_STYLE
: return wndPtr
->dwStyle
;
1325 case GWL_EXSTYLE
: return wndPtr
->dwExStyle
;
1326 case GWL_ID
: return wndPtr
->wIDmenu
;
1327 case GWL_WNDPROC
: return (LONG
)wndPtr
->lpfnWndProc
;
1328 case GWL_HWNDPARENT
: return wndPtr
->parent
?
1329 (HWND32
)wndPtr
->parent
->hwndSelf
: 0;
1330 case GWL_HINSTANCE
: return (HINSTANCE32
)wndPtr
->hInstance
;
1332 fprintf( stderr
, "GetWindowLong: unknown offset %d\n", offset
);
1338 /**********************************************************************
1339 * SetWindowLong16 (USER.136)
1341 LONG
SetWindowLong16( HWND16 hwnd
, INT16 offset
, LONG newval
)
1347 wndPtr
= WIN_FindWndPtr( hwnd
);
1348 return (LONG
)WIN_SetWndProc( wndPtr
, (WNDPROC16
)newval
, WIN_PROC_16
);
1350 return SetWindowLong32A( hwnd
, offset
, newval
);
1355 /**********************************************************************
1356 * SetWindowLong32A (USER32.516)
1358 LONG
SetWindowLong32A( HWND32 hwnd
, INT32 offset
, LONG newval
)
1361 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
1362 if (!wndPtr
) return 0;
1363 if (offset
>= 0) ptr
= (LONG
*)(((char *)wndPtr
->wExtra
) + offset
);
1368 return SetWindowWord( hwnd
, offset
, (WORD
)newval
);
1370 return (LONG
)WIN_SetWndProc( wndPtr
, (WNDPROC16
)newval
,
1372 case GWL_USERDATA
: return 0;
1373 case GWL_STYLE
: ptr
= &wndPtr
->dwStyle
; break;
1374 case GWL_EXSTYLE
: ptr
= &wndPtr
->dwExStyle
; break;
1376 fprintf( stderr
, "SetWindowLong: invalid offset %d\n", offset
);
1385 /**********************************************************************
1386 * SetWindowLong32W (USER32.517)
1388 LONG
SetWindowLong32W( HWND32 hwnd
, INT32 offset
, LONG newval
)
1394 wndPtr
= WIN_FindWndPtr( hwnd
);
1395 return (LONG
)WIN_SetWndProc( wndPtr
, (WNDPROC16
)newval
, WIN_PROC_32W
);
1397 return SetWindowLong32A( hwnd
, offset
, newval
);
1402 /*******************************************************************
1403 * GetWindowText16 (USER.36)
1405 INT16
GetWindowText16( HWND16 hwnd
, SEGPTR lpString
, INT16 nMaxCount
)
1407 return (INT16
)SendMessage16(hwnd
, WM_GETTEXT
, nMaxCount
, (LPARAM
)lpString
);
1411 /*******************************************************************
1412 * GetWindowText32A (USER32.308)
1414 INT32
GetWindowText32A( HWND32 hwnd
, LPSTR lpString
, INT32 nMaxCount
)
1416 return (INT32
)SendMessage32A( hwnd
, WM_GETTEXT
, nMaxCount
,
1421 /*******************************************************************
1422 * GetWindowText32W (USER32.311)
1424 INT32
GetWindowText32W( HWND32 hwnd
, LPWSTR lpString
, INT32 nMaxCount
)
1426 return (INT32
)SendMessage32W( hwnd
, WM_GETTEXT
, nMaxCount
,
1431 /*******************************************************************
1432 * SetWindowText16 (USER.37)
1434 void SetWindowText16( HWND16 hwnd
, SEGPTR lpString
)
1436 SendMessage16( hwnd
, WM_SETTEXT
, 0, (LPARAM
)lpString
);
1440 /*******************************************************************
1441 * SetWindowText32A (USER32.)
1443 void SetWindowText32A( HWND32 hwnd
, LPCSTR lpString
)
1445 SendMessage32A( hwnd
, WM_SETTEXT
, 0, (LPARAM
)lpString
);
1449 /*******************************************************************
1450 * SetWindowText32W (USER32.)
1452 void SetWindowText32W( HWND32 hwnd
, LPCWSTR lpString
)
1454 SendMessage32W( hwnd
, WM_SETTEXT
, 0, (LPARAM
)lpString
);
1458 /*******************************************************************
1459 * GetWindowTextLength (USER.38)
1461 int GetWindowTextLength(HWND hwnd
)
1463 return (int)SendMessage16(hwnd
, WM_GETTEXTLENGTH
, 0, 0 );
1467 /*******************************************************************
1468 * IsWindow (USER.47)
1470 BOOL
IsWindow( HWND hwnd
)
1472 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
1473 return ((wndPtr
!= NULL
) && (wndPtr
->dwMagic
== WND_MAGIC
));
1477 /*****************************************************************
1478 * GetParent (USER.46)
1480 HWND
GetParent(HWND hwnd
)
1482 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1483 if (!wndPtr
) return 0;
1484 wndPtr
= (wndPtr
->dwStyle
& WS_CHILD
) ? wndPtr
->parent
: wndPtr
->owner
;
1485 return wndPtr
? wndPtr
->hwndSelf
: 0;
1489 /*****************************************************************
1492 * Get the top-level parent for a child window.
1494 HWND
WIN_GetTopParent( HWND hwnd
)
1496 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
1497 while (wndPtr
&& (wndPtr
->dwStyle
& WS_CHILD
)) wndPtr
= wndPtr
->parent
;
1498 return wndPtr
? wndPtr
->hwndSelf
: 0;
1502 /*****************************************************************
1503 * SetParent (USER.233)
1505 HWND
SetParent(HWND hwndChild
, HWND hwndNewParent
)
1509 WND
*wndPtr
= WIN_FindWndPtr(hwndChild
);
1510 WND
*pWndParent
= WIN_FindWndPtr( hwndNewParent
);
1511 if (!wndPtr
|| !pWndParent
|| !(wndPtr
->dwStyle
& WS_CHILD
)) return 0;
1513 oldParent
= wndPtr
->parent
->hwndSelf
;
1515 WIN_UnlinkWindow(hwndChild
);
1516 if (hwndNewParent
) wndPtr
->parent
= pWndParent
;
1517 WIN_LinkWindow(hwndChild
, HWND_BOTTOM
);
1519 if (IsWindowVisible(hwndChild
)) UpdateWindow(hwndChild
);
1526 /*******************************************************************
1529 BOOL
IsChild( HWND parent
, HWND child
)
1531 WND
* wndPtr
= WIN_FindWndPtr( child
);
1532 while (wndPtr
&& (wndPtr
->dwStyle
& WS_CHILD
))
1534 wndPtr
= wndPtr
->parent
;
1535 if (wndPtr
->hwndSelf
== parent
) return TRUE
;
1541 /***********************************************************************
1542 * IsWindowVisible (USER.49) (USER32.350)
1544 BOOL
IsWindowVisible( HWND hwnd
)
1546 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
1547 while (wndPtr
&& (wndPtr
->dwStyle
& WS_CHILD
))
1549 if (!(wndPtr
->dwStyle
& WS_VISIBLE
)) return FALSE
;
1550 wndPtr
= wndPtr
->parent
;
1552 return (wndPtr
&& (wndPtr
->dwStyle
& WS_VISIBLE
));
1557 /*******************************************************************
1558 * GetTopWindow (USER.229)
1560 HWND
GetTopWindow( HWND hwnd
)
1562 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
1563 if (wndPtr
&& wndPtr
->child
) return wndPtr
->child
->hwndSelf
;
1568 /*******************************************************************
1569 * GetWindow (USER.262)
1571 HWND
GetWindow( HWND hwnd
, WORD rel
)
1573 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
1574 if (!wndPtr
) return 0;
1578 if (wndPtr
->parent
) return wndPtr
->parent
->child
->hwndSelf
;
1582 if (!wndPtr
->parent
) return 0; /* Desktop window */
1583 while (wndPtr
->next
) wndPtr
= wndPtr
->next
;
1584 return wndPtr
->hwndSelf
;
1587 if (!wndPtr
->next
) return 0;
1588 return wndPtr
->next
->hwndSelf
;
1591 if (!wndPtr
->parent
) return 0; /* Desktop window */
1592 wndPtr
= wndPtr
->parent
->child
; /* First sibling */
1593 if (wndPtr
->hwndSelf
== hwnd
) return 0; /* First in list */
1594 while (wndPtr
->next
)
1596 if (wndPtr
->next
->hwndSelf
== hwnd
) return wndPtr
->hwndSelf
;
1597 wndPtr
= wndPtr
->next
;
1602 return wndPtr
->owner
? wndPtr
->owner
->hwndSelf
: 0;
1605 return wndPtr
->child
? wndPtr
->child
->hwndSelf
: 0;
1611 /*******************************************************************
1612 * GetNextWindow (USER.230)
1614 HWND
GetNextWindow( HWND hwnd
, WORD flag
)
1616 if ((flag
!= GW_HWNDNEXT
) && (flag
!= GW_HWNDPREV
)) return 0;
1617 return GetWindow( hwnd
, flag
);
1620 /*******************************************************************
1621 * ShowOwnedPopups (USER.265)
1623 void ShowOwnedPopups( HWND owner
, BOOL fShow
)
1625 WND
*pWnd
= pWndDesktop
->child
;
1628 if (pWnd
->owner
&& (pWnd
->owner
->hwndSelf
== owner
) &&
1629 (pWnd
->dwStyle
& WS_POPUP
))
1630 ShowWindow( pWnd
->hwndSelf
, fShow
? SW_SHOW
: SW_HIDE
);
1636 /*******************************************************************
1637 * GetLastActivePopup (USER.287)
1639 HWND
GetLastActivePopup(HWND hwnd
)
1642 wndPtr
= WIN_FindWndPtr(hwnd
);
1643 if (wndPtr
== NULL
) return hwnd
;
1644 return wndPtr
->hwndLastActive
;
1648 /*******************************************************************
1649 * EnumWindows (USER.54)
1651 BOOL
EnumWindows( WNDENUMPROC lpEnumFunc
, LPARAM lParam
)
1657 /* We have to build a list of all windows first, to avoid */
1658 /* unpleasant side-effects, for instance if the callback */
1659 /* function changes the Z-order of the windows. */
1661 /* First count the windows */
1664 for (wndPtr
= pWndDesktop
->child
; wndPtr
; wndPtr
= wndPtr
->next
) count
++;
1665 if (!count
) return TRUE
;
1667 /* Now build the list of all windows */
1669 if (!(pWnd
= list
= (HWND
*)malloc( sizeof(HWND
) * count
))) return FALSE
;
1670 for (wndPtr
= pWndDesktop
->child
; wndPtr
; wndPtr
= wndPtr
->next
)
1671 *pWnd
++ = wndPtr
->hwndSelf
;
1673 /* Now call the callback function for every window */
1675 for (pWnd
= list
; count
> 0; count
--, pWnd
++)
1677 /* Make sure that window still exists */
1678 if (!IsWindow(*pWnd
)) continue;
1679 if (!CallEnumWindowsProc( lpEnumFunc
, *pWnd
, lParam
)) break;
1686 /**********************************************************************
1687 * EnumTaskWindows (USER.225)
1689 BOOL
EnumTaskWindows( HTASK hTask
, WNDENUMPROC lpEnumFunc
, LPARAM lParam
)
1693 HANDLE hQueue
= GetTaskQueue( hTask
);
1696 /* This function is the same as EnumWindows(), */
1697 /* except for an added check on the window queue. */
1699 /* First count the windows */
1702 for (wndPtr
= pWndDesktop
->child
; wndPtr
; wndPtr
= wndPtr
->next
)
1703 if (wndPtr
->hmemTaskQ
== hQueue
) count
++;
1704 if (!count
) return TRUE
;
1706 /* Now build the list of all windows */
1708 if (!(pWnd
= list
= (HWND
*)malloc( sizeof(HWND
) * count
))) return FALSE
;
1709 for (wndPtr
= pWndDesktop
->child
; wndPtr
; wndPtr
= wndPtr
->next
)
1710 if (wndPtr
->hmemTaskQ
== hQueue
) *pWnd
++ = wndPtr
->hwndSelf
;
1712 /* Now call the callback function for every window */
1714 for (pWnd
= list
; count
> 0; count
--, pWnd
++)
1716 /* Make sure that window still exists */
1717 if (!IsWindow(*pWnd
)) continue;
1718 if (!CallEnumTaskWndProc( lpEnumFunc
, *pWnd
, lParam
)) break;
1725 /*******************************************************************
1728 * o hwnd is the first child to use, loop until all next windows
1733 * o call ourselves with the next child window
1736 static BOOL
WIN_EnumChildWin( WND
*wndPtr
, FARPROC wndenumprc
, LPARAM lParam
)
1738 WND
*pWndNext
, *pWndChild
;
1741 pWndNext
= wndPtr
->next
; /* storing hwnd is a way to avoid.. */
1742 pWndChild
= wndPtr
->child
; /* ..side effects after wndenumprc */
1743 if (!CallEnumWindowsProc( wndenumprc
, wndPtr
->hwndSelf
, lParam
))
1745 if (pWndChild
&& IsWindow(pWndChild
->hwndSelf
))
1746 if (!WIN_EnumChildWin(pWndChild
, wndenumprc
, lParam
)) return 0;
1753 /*******************************************************************
1754 * EnumChildWindows (USER.55)
1756 * o gets the first child of hwnd
1758 * o calls WIN_EnumChildWin to do a recursive decent of child windows
1760 BOOL
EnumChildWindows(HWND hwnd
, WNDENUMPROC wndenumprc
, LPARAM lParam
)
1764 dprintf_enum(stddeb
,"EnumChildWindows\n");
1766 if (hwnd
== 0) return 0;
1767 if (!(wndPtr
= WIN_FindWndPtr(hwnd
))) return 0;
1768 return WIN_EnumChildWin(wndPtr
->child
, wndenumprc
, lParam
);
1772 /*******************************************************************
1773 * AnyPopup (USER.52)
1778 for (wndPtr
= pWndDesktop
->child
; wndPtr
; wndPtr
= wndPtr
->next
)
1779 if (wndPtr
->owner
&& (wndPtr
->dwStyle
& WS_VISIBLE
)) return TRUE
;
1783 /*******************************************************************
1784 * FlashWindow [USER.105]
1786 BOOL
FlashWindow(HWND hWnd
, BOOL bInvert
)
1788 WND
*wndPtr
= WIN_FindWndPtr(hWnd
);
1790 dprintf_win(stddeb
,"FlashWindow: %04x\n", hWnd
);
1792 if (!wndPtr
) return FALSE
;
1794 if (wndPtr
->dwStyle
& WS_MINIMIZE
)
1796 if (bInvert
&& !(wndPtr
->flags
& WIN_NCACTIVATED
))
1798 HDC hDC
= GetDC(hWnd
);
1800 if (!SendMessage16( hWnd
, WM_ERASEBKGND
, (WPARAM
)hDC
, (LPARAM
)0 ))
1801 wndPtr
->flags
|= WIN_NEEDS_ERASEBKGND
;
1803 ReleaseDC( hWnd
, hDC
);
1804 wndPtr
->flags
|= WIN_NCACTIVATED
;
1808 RedrawWindow32( hWnd
, 0, 0, RDW_INVALIDATE
| RDW_ERASE
|
1809 RDW_UPDATENOW
| RDW_FRAME
);
1810 wndPtr
->flags
&= ~WIN_NCACTIVATED
;
1817 if (bInvert
) wparam
= !(wndPtr
->flags
& WIN_NCACTIVATED
);
1818 else wparam
= (hWnd
== GetActiveWindow());
1820 SendMessage16( hWnd
, WM_NCACTIVATE
, wparam
, (LPARAM
)0 );
1826 /*******************************************************************
1827 * SetSysModalWindow [USER.188]
1829 HWND
SetSysModalWindow(HWND hWnd
)
1831 HWND hWndOldModal
= hwndSysModal
;
1832 hwndSysModal
= hWnd
;
1833 dprintf_win(stdnimp
,"EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd
);
1834 return hWndOldModal
;
1838 /*******************************************************************
1839 * GetSysModalWindow [USER.189]
1841 HWND
GetSysModalWindow(void)
1843 return hwndSysModal
;
1846 /*******************************************************************
1849 * recursively find a child that contains spDragInfo->pt point
1850 * and send WM_QUERYDROPOBJECT
1852 BOOL
DRAG_QueryUpdate( HWND hQueryWnd
, SEGPTR spDragInfo
)
1854 BOOL wParam
,bResult
= 0;
1856 LPDRAGINFO ptrDragInfo
= (LPDRAGINFO
) PTR_SEG_TO_LIN(spDragInfo
);
1857 WND
*ptrQueryWnd
= WIN_FindWndPtr(hQueryWnd
),*ptrWnd
;
1858 RECT16 tempRect
; /* this sucks */
1860 if( !ptrQueryWnd
|| !ptrDragInfo
) return 0;
1862 pt
= ptrDragInfo
->pt
;
1864 GetWindowRect16(hQueryWnd
,&tempRect
);
1866 if( !PtInRect16(&tempRect
,pt
) ||
1867 (ptrQueryWnd
->dwStyle
& WS_DISABLED
) )
1870 if( !(ptrQueryWnd
->dwStyle
& WS_MINIMIZE
) )
1872 tempRect
= ptrQueryWnd
->rectClient
;
1873 if(ptrQueryWnd
->dwStyle
& WS_CHILD
)
1874 MapWindowPoints16(ptrQueryWnd
->parent
->hwndSelf
,0,(LPPOINT16
)&tempRect
,2);
1876 if( PtInRect16(&tempRect
,pt
) )
1880 for (ptrWnd
= ptrQueryWnd
->child
; ptrWnd
;ptrWnd
= ptrWnd
->next
)
1881 if( ptrWnd
->dwStyle
& WS_VISIBLE
)
1883 GetWindowRect16(ptrWnd
->hwndSelf
,&tempRect
);
1885 if( PtInRect16(&tempRect
,pt
) )
1891 dprintf_msg(stddeb
,"DragQueryUpdate: hwnd = %04x, %d %d - %d %d\n",
1892 ptrWnd
->hwndSelf
, ptrWnd
->rectWindow
.left
, ptrWnd
->rectWindow
.top
,
1893 ptrWnd
->rectWindow
.right
, ptrWnd
->rectWindow
.bottom
);
1894 if( !(ptrWnd
->dwStyle
& WS_DISABLED
) )
1895 bResult
= DRAG_QueryUpdate(ptrWnd
->hwndSelf
, spDragInfo
);
1898 if(bResult
) return bResult
;
1904 ScreenToClient16(hQueryWnd
,&ptrDragInfo
->pt
);
1906 ptrDragInfo
->hScope
= hQueryWnd
;
1908 bResult
= SendMessage16( hQueryWnd
,WM_QUERYDROPOBJECT
,
1909 (WPARAM
)wParam
,(LPARAM
) spDragInfo
);
1911 ptrDragInfo
->pt
= pt
;
1916 /*******************************************************************
1917 * DragDetect ( USER.465 )
1920 BOOL16
DragDetect(HWND16 hWnd
, POINT16 pt
)
1925 rect
.left
= pt
.x
- wDragWidth
;
1926 rect
.right
= pt
.x
+ wDragWidth
;
1928 rect
.top
= pt
.y
- wDragHeight
;
1929 rect
.bottom
= pt
.y
+ wDragHeight
;
1935 while(PeekMessage(&msg
,0 ,WM_MOUSEFIRST
,WM_MOUSELAST
,PM_REMOVE
))
1937 if( msg
.message
== WM_LBUTTONUP
)
1942 if( msg
.message
== WM_MOUSEMOVE
)
1944 if( !PtInRect16( &rect
, MAKEPOINT16(msg
.lParam
) ) )
1957 /******************************************************************************
1958 * DragObject ( USER.464 )
1961 DWORD
DragObject(HWND hwndScope
, HWND hWnd
, WORD wObj
, HANDLE hOfStruct
,
1962 WORD szList
, HCURSOR hCursor
)
1965 LPDRAGINFO lpDragInfo
;
1967 HCURSOR hDragCursor
=0, hOldCursor
=0, hBummer
=0;
1968 HANDLE hDragInfo
= GlobalAlloc16( GMEM_SHARE
| GMEM_ZEROINIT
, 2*sizeof(DRAGINFO
));
1969 WND
*wndPtr
= WIN_FindWndPtr(hWnd
);
1972 HCURSOR hCurrentCursor
= 0;
1973 HWND hCurrentWnd
= 0;
1976 lpDragInfo
= (LPDRAGINFO
) GlobalLock16(hDragInfo
);
1977 spDragInfo
= (SEGPTR
) WIN16_GlobalLock16(hDragInfo
);
1979 if( !lpDragInfo
|| !spDragInfo
) return 0L;
1981 hBummer
= LoadCursor(0,IDC_BUMMER
);
1983 if( !hBummer
|| !wndPtr
)
1985 GlobalFree16(hDragInfo
);
1991 if( !(hDragCursor
= CURSORICON_IconToCursor(hCursor
)) )
1993 GlobalFree16(hDragInfo
);
1997 if( hDragCursor
== hCursor
) hDragCursor
= 0;
1998 else hCursor
= hDragCursor
;
2000 hOldCursor
= SetCursor(hDragCursor
);
2003 lpDragInfo
->hWnd
= hWnd
;
2004 lpDragInfo
->hScope
= 0;
2005 lpDragInfo
->wFlags
= wObj
;
2006 lpDragInfo
->hList
= szList
; /* near pointer! */
2007 lpDragInfo
->hOfStruct
= hOfStruct
;
2017 if( !PeekMessage(&msg
,0,WM_MOUSEFIRST
,WM_MOUSELAST
,PM_REMOVE
) )
2020 *(lpDragInfo
+1) = *lpDragInfo
;
2022 lpDragInfo
->pt
= msg
.pt
;
2024 /* update DRAGINFO struct */
2025 dprintf_msg(stddeb
,"drag: lpDI->hScope = %04x\n",lpDragInfo
->hScope
);
2027 if( (btemp
= (WORD
)DRAG_QueryUpdate(hwndScope
, spDragInfo
)) > 0 )
2028 hCurrentCursor
= hCursor
;
2031 hCurrentCursor
= hBummer
;
2032 lpDragInfo
->hScope
= 0;
2034 if( hCurrentCursor
)
2035 SetCursor(hCurrentCursor
);
2037 dprintf_msg(stddeb
,"drag: got %04x\n",btemp
);
2039 /* send WM_DRAGLOOP */
2040 SendMessage16( hWnd
, WM_DRAGLOOP
, (WPARAM
)(hCurrentCursor
!= hBummer
) ,
2041 (LPARAM
) spDragInfo
);
2042 /* send WM_DRAGSELECT or WM_DRAGMOVE */
2043 if( hCurrentWnd
!= lpDragInfo
->hScope
)
2046 SendMessage16( hCurrentWnd
, WM_DRAGSELECT
, 0,
2047 (LPARAM
)MAKELONG(LOWORD(spDragInfo
)+sizeof(DRAGINFO
),
2048 HIWORD(spDragInfo
)) );
2049 hCurrentWnd
= lpDragInfo
->hScope
;
2051 SendMessage16( hCurrentWnd
, WM_DRAGSELECT
, 1, (LPARAM
)spDragInfo
);
2055 SendMessage16( hCurrentWnd
, WM_DRAGMOVE
, 0, (LPARAM
)spDragInfo
);
2058 /* check if we're done */
2059 if( msg
.message
== WM_LBUTTONUP
|| msg
.message
== WM_NCLBUTTONUP
)
2068 SetCursor(hOldCursor
);
2070 DestroyCursor(hDragCursor
);
2073 if( hCurrentCursor
!= hBummer
)
2074 dwRet
= SendMessage16( lpDragInfo
->hScope
, WM_DROPOBJECT
,
2075 (WPARAM
)hWnd
, (LPARAM
)spDragInfo
);
2076 GlobalFree16(hDragInfo
);