2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
15 #include "sysmetrics.h"
17 #include "cursoricon.h"
20 #include "nonclient.h"
23 #include "shm_main_blk.h"
27 /* #define DEBUG_WIN */
28 /* #define DEBUG_MENU */
31 static HWND hwndDesktop
= 0;
32 static HWND hwndSysModal
= 0;
34 static WORD wDragWidth
= 4;
35 static WORD wDragHeight
= 3;
37 extern HCURSOR
CURSORICON_IconToCursor(HICON
);
39 /***********************************************************************
42 * Return a pointer to the WND structure corresponding to a HWND.
44 WND
* WIN_FindWndPtr( HWND hwnd
)
48 if (!hwnd
) return NULL
;
49 ptr
= (WND
*) USER_HEAP_LIN_ADDR( hwnd
);
50 if (ptr
->dwMagic
!= WND_MAGIC
) return NULL
;
55 /***********************************************************************
58 * Return the X window associated to a window.
60 Window
WIN_GetXWindow( HWND hwnd
)
62 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
63 while (wndPtr
&& !wndPtr
->window
)
65 wndPtr
= WIN_FindWndPtr( wndPtr
->hwndParent
);
67 return wndPtr
? wndPtr
->window
: 0;
71 /***********************************************************************
74 * Remove a window from the siblings linked list.
76 BOOL
WIN_UnlinkWindow( HWND hwnd
)
79 WND
*parentPtr
, *wndPtr
;
81 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
82 if (!(parentPtr
= WIN_FindWndPtr( wndPtr
->hwndParent
))) return FALSE
;
84 curWndPtr
= &parentPtr
->hwndChild
;
86 while (*curWndPtr
!= hwnd
)
88 WND
* curPtr
= WIN_FindWndPtr( *curWndPtr
);
89 curWndPtr
= &curPtr
->hwndNext
;
91 *curWndPtr
= wndPtr
->hwndNext
;
96 /***********************************************************************
99 * Insert a window into the siblings linked list.
100 * The window is inserted after the specified window, which can also
101 * be specified as HWND_TOP or HWND_BOTTOM.
103 BOOL
WIN_LinkWindow( HWND hwnd
, HWND hwndInsertAfter
)
105 HWND
* hwndPtr
= NULL
; /* pointer to hwnd to change */
106 WND
*wndPtr
, *parentPtr
;
108 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
109 if (!(parentPtr
= WIN_FindWndPtr( wndPtr
->hwndParent
))) return FALSE
;
111 if ((hwndInsertAfter
== HWND_TOP
) || (hwndInsertAfter
== HWND_BOTTOM
))
113 hwndPtr
= &parentPtr
->hwndChild
; /* Point to first sibling hwnd */
114 if (hwndInsertAfter
== HWND_BOTTOM
) /* Find last sibling hwnd */
117 WND
* nextPtr
= WIN_FindWndPtr( *hwndPtr
);
118 hwndPtr
= &nextPtr
->hwndNext
;
121 else /* Normal case */
123 WND
* afterPtr
= WIN_FindWndPtr( hwndInsertAfter
);
124 if (afterPtr
) hwndPtr
= &afterPtr
->hwndNext
;
126 if (!hwndPtr
) return FALSE
;
127 wndPtr
->hwndNext
= *hwndPtr
;
133 /***********************************************************************
134 * WIN_FindWinToRepaint
136 * Find a window that needs repaint.
138 HWND
WIN_FindWinToRepaint( HWND hwnd
)
142 /* Note: the desktop window never gets WM_PAINT messages */
143 if (!hwnd
) hwnd
= GetTopWindow( hwndDesktop
);
144 for ( ; hwnd
!= 0; hwnd
= wndPtr
->hwndNext
)
146 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return 0;
147 dprintf_win( stddeb
, "WIN_FindWinToRepaint: "NPFMT
", style %08lx\n",
148 hwnd
, wndPtr
->dwStyle
);
149 if (!(wndPtr
->dwStyle
& WS_VISIBLE
) || (wndPtr
->flags
& WIN_NO_REDRAW
))
151 if ((wndPtr
->dwStyle
& WS_MINIMIZE
) && (WIN_CLASS_INFO(wndPtr
).hIcon
))
153 if (wndPtr
->hrgnUpdate
|| (wndPtr
->flags
& WIN_INTERNAL_PAINT
))
155 if (wndPtr
->hwndChild
)
158 if ((child
= WIN_FindWinToRepaint( wndPtr
->hwndChild
)))
166 /***********************************************************************
167 * WIN_SendParentNotify
169 * Send a WM_PARENTNOTIFY to all ancestors of the given window, unless
170 * the window has the WS_EX_NOPARENTNOTIFY style.
172 void WIN_SendParentNotify( HWND hwnd
, WORD event
, WORD idChild
, LONG lValue
)
174 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
176 while (wndPtr
&& (wndPtr
->dwStyle
& WS_CHILD
))
178 if (wndPtr
->dwExStyle
& WS_EX_NOPARENTNOTIFY
) break;
180 SendMessage( wndPtr
->hwndParent
, WM_PARENTNOTIFY
,
181 MAKEWPARAM(event
,idChild
),
184 SendMessage( wndPtr
->hwndParent
, WM_PARENTNOTIFY
, event
,
185 MAKELPARAM(LOWORD(lValue
), idChild
) );
187 wndPtr
= WIN_FindWndPtr( wndPtr
->hwndParent
);
192 /***********************************************************************
195 * Destroy storage associated to a window
197 static void WIN_DestroyWindow( HWND hwnd
)
199 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
200 CLASS
*classPtr
= CLASS_FindClassPtr( wndPtr
->hClass
);
204 DDE_DestroyWindow(hwnd
);
205 #endif /* CONFIG_IPC */
207 if (!wndPtr
|| !classPtr
) return;
208 WIN_UnlinkWindow( hwnd
); /* Remove the window from the linked list */
209 wndPtr
->dwMagic
= 0; /* Mark it as invalid */
210 if ((wndPtr
->hrgnUpdate
) || (wndPtr
->flags
& WIN_INTERNAL_PAINT
))
212 if (wndPtr
->hrgnUpdate
) DeleteObject( wndPtr
->hrgnUpdate
);
213 MSG_DecPaintCount( wndPtr
->hmemTaskQ
);
215 if (!(wndPtr
->dwStyle
& WS_CHILD
))
217 if (wndPtr
->wIDmenu
) DestroyMenu( (HMENU
)wndPtr
->wIDmenu
);
219 if (wndPtr
->hSysMenu
) DestroyMenu( wndPtr
->hSysMenu
);
220 if (wndPtr
->window
) XDestroyWindow( display
, wndPtr
->window
);
221 if (classPtr
->wc
.style
& CS_OWNDC
) DCE_FreeDCE( wndPtr
->hdce
);
222 classPtr
->cWindows
--;
223 USER_HEAP_FREE( hwnd
);
227 /***********************************************************************
228 * WIN_CreateDesktopWindow
230 * Create the desktop window.
232 BOOL
WIN_CreateDesktopWindow(void)
239 if (!(hclass
= CLASS_FindClassByName( DESKTOP_CLASS_ATOM
, 0, &classPtr
)))
242 hwndDesktop
= USER_HEAP_ALLOC( sizeof(WND
)+classPtr
->wc
.cbWndExtra
);
243 if (!hwndDesktop
) return FALSE
;
244 wndPtr
= (WND
*) USER_HEAP_LIN_ADDR( hwndDesktop
);
246 wndPtr
->hwndNext
= 0;
247 wndPtr
->hwndChild
= 0;
248 wndPtr
->dwMagic
= WND_MAGIC
;
249 wndPtr
->hwndParent
= 0;
250 wndPtr
->hwndOwner
= 0;
251 wndPtr
->hClass
= hclass
;
252 wndPtr
->hInstance
= 0;
253 wndPtr
->rectWindow
.left
= 0;
254 wndPtr
->rectWindow
.top
= 0;
255 wndPtr
->rectWindow
.right
= SYSMETRICS_CXSCREEN
;
256 wndPtr
->rectWindow
.bottom
= SYSMETRICS_CYSCREEN
;
257 wndPtr
->rectClient
= wndPtr
->rectWindow
;
258 wndPtr
->rectNormal
= wndPtr
->rectWindow
;
259 wndPtr
->ptIconPos
.x
= -1;
260 wndPtr
->ptIconPos
.y
= -1;
261 wndPtr
->ptMaxPos
.x
= -1;
262 wndPtr
->ptMaxPos
.y
= -1;
263 wndPtr
->hmemTaskQ
= 0; /* Desktop does not belong to a task */
264 wndPtr
->hrgnUpdate
= 0;
265 wndPtr
->hwndLastActive
= hwndDesktop
;
266 wndPtr
->lpfnWndProc
= classPtr
->wc
.lpfnWndProc
;
267 wndPtr
->dwStyle
= WS_VISIBLE
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
;
268 wndPtr
->dwExStyle
= 0;
270 wndPtr
->hVScroll
= 0;
271 wndPtr
->hHScroll
= 0;
275 wndPtr
->window
= rootWindow
;
276 wndPtr
->hSysMenu
= 0;
278 EVENT_RegisterWindow( wndPtr
->window
, hwndDesktop
);
279 SendMessage( hwndDesktop
, WM_NCCREATE
, 0, 0 );
280 if ((hdc
= GetDC( hwndDesktop
)) != 0)
282 SendMessage( hwndDesktop
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0 );
283 ReleaseDC( hwndDesktop
, hdc
);
289 /***********************************************************************
290 * CreateWindow (USER.41)
292 HWND
CreateWindow( SEGPTR className
, SEGPTR windowName
,
293 DWORD style
, INT x
, INT y
, INT width
, INT height
,
294 HWND parent
, HMENU menu
, HANDLE instance
, SEGPTR data
)
296 return CreateWindowEx( 0, className
, windowName
, style
,
297 x
, y
, width
, height
, parent
, menu
, instance
, data
);
301 /***********************************************************************
302 * CreateWindowEx (USER.452)
304 HWND
CreateWindowEx( DWORD exStyle
, SEGPTR className
, SEGPTR windowName
,
305 DWORD style
, INT x
, INT y
, INT width
, INT height
,
306 HWND parent
, HMENU menu
, HANDLE instance
, SEGPTR data
)
311 POINT maxSize
, maxPos
, minTrack
, maxTrack
;
312 CREATESTRUCT createStruct
;
314 XSetWindowAttributes win_attr
;
316 /* FIXME: windowName and className should be SEGPTRs */
318 dprintf_win( stddeb
, "CreateWindowEx: " );
319 if (HIWORD(windowName
))
320 dprintf_win( stddeb
, "'%s' ", (char *)PTR_SEG_TO_LIN(windowName
) );
322 dprintf_win( stddeb
, "%04x ", LOWORD(windowName
) );
323 if (HIWORD(className
))
324 dprintf_win( stddeb
, "'%s' ", (char *)PTR_SEG_TO_LIN(className
) );
326 dprintf_win( stddeb
, "%04x ", LOWORD(className
) );
328 dprintf_win(stddeb
, "%08lx %08lx %d,%d %dx%d "NPFMT
" "NPFMT
" "NPFMT
" %08lx\n",
329 exStyle
, style
, x
, y
, width
, height
,
330 parent
, menu
, instance
, (DWORD
)data
);
332 if (x
== CW_USEDEFAULT
) x
= y
= 0;
333 if (width
== CW_USEDEFAULT
)
339 /* Find the parent and class */
343 /* Make sure parent is valid */
344 if (!IsWindow( parent
)) {
345 dprintf_win(stddeb
,"CreateWindowEx: Parent "NPFMT
" is not a window\n", parent
);
351 if (style
& WS_CHILD
) {
352 dprintf_win(stddeb
,"CreateWindowEx: no parent\n");
353 return 0; /* WS_CHILD needs a parent */
357 if (!(class = CLASS_FindClassByName( className
, GetExePtr(instance
),
360 fprintf(stderr
,"CreateWindow BAD CLASSNAME " );
361 if (HIWORD(className
)) fprintf( stderr
, "'%s'\n",
362 (char *)PTR_SEG_TO_LIN(className
) );
363 else fprintf( stderr
, "%04x\n", LOWORD(className
) );
367 /* Correct the window style */
369 if (!(style
& (WS_POPUP
| WS_CHILD
))) /* Overlapped window */
370 style
|= WS_CAPTION
| WS_CLIPSIBLINGS
;
371 if (exStyle
& WS_EX_DLGMODALFRAME
) style
&= ~WS_THICKFRAME
;
373 /* Create the window structure */
375 hwnd
= USER_HEAP_ALLOC( sizeof(WND
)+classPtr
->wc
.cbWndExtra
);
377 dprintf_win(stddeb
,"CreateWindowEx: Out of memory\n");
381 /* Fill the structure */
383 wndPtr
= (WND
*) USER_HEAP_LIN_ADDR( hwnd
);
384 wndPtr
->hwndNext
= 0;
385 wndPtr
->hwndChild
= 0;
387 wndPtr
->dwMagic
= WND_MAGIC
;
388 wndPtr
->hwndParent
= (style
& WS_CHILD
) ? parent
: hwndDesktop
;
389 wndPtr
->hwndOwner
= (style
& WS_CHILD
) ? 0 : WIN_GetTopParent(parent
);
390 wndPtr
->hClass
= class;
391 wndPtr
->hInstance
= instance
;
392 wndPtr
->ptIconPos
.x
= -1;
393 wndPtr
->ptIconPos
.y
= -1;
394 wndPtr
->ptMaxPos
.x
= -1;
395 wndPtr
->ptMaxPos
.y
= -1;
396 wndPtr
->hmemTaskQ
= GetTaskQueue(0);
397 wndPtr
->hrgnUpdate
= 0;
398 wndPtr
->hwndLastActive
= hwnd
;
399 wndPtr
->lpfnWndProc
= classPtr
->wc
.lpfnWndProc
;
400 wndPtr
->dwStyle
= style
& ~WS_VISIBLE
;
401 wndPtr
->dwExStyle
= exStyle
;
405 wndPtr
->hVScroll
= 0;
406 wndPtr
->hHScroll
= 0;
407 wndPtr
->hSysMenu
= 0;
410 if (classPtr
->wc
.cbWndExtra
)
411 memset( wndPtr
->wExtra
, 0, classPtr
->wc
.cbWndExtra
);
412 classPtr
->cWindows
++;
414 /* Get class or window DC if needed */
416 if (classPtr
->wc
.style
& CS_OWNDC
)
417 wndPtr
->hdce
= DCE_AllocDCE( DCE_WINDOW_DC
);
418 else if (classPtr
->wc
.style
& CS_CLASSDC
)
419 wndPtr
->hdce
= classPtr
->hdce
;
423 /* Insert the window in the linked list */
425 WIN_LinkWindow( hwnd
, HWND_TOP
);
427 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
429 NC_GetMinMaxInfo( hwnd
, &maxSize
, &maxPos
, &minTrack
, &maxTrack
);
431 if (maxSize
.x
< width
) width
= maxSize
.x
;
432 if (maxSize
.y
< height
) height
= maxSize
.y
;
433 if (width
<= 0) width
= 1;
434 if (height
<= 0) height
= 1;
436 wndPtr
->rectWindow
.left
= x
;
437 wndPtr
->rectWindow
.top
= y
;
438 wndPtr
->rectWindow
.right
= x
+ width
;
439 wndPtr
->rectWindow
.bottom
= y
+ height
;
440 wndPtr
->rectClient
= wndPtr
->rectWindow
;
441 wndPtr
->rectNormal
= wndPtr
->rectWindow
;
443 /* Create the X window (only for top-level windows, and then only */
444 /* when there's no desktop window) */
446 if (!(style
& WS_CHILD
) && (rootWindow
== DefaultRootWindow(display
)))
448 if(Options
.managed
&& className
!= POPUPMENU_CLASS_ATOM
) {
449 win_attr
.event_mask
= ExposureMask
| KeyPressMask
|
450 KeyReleaseMask
| PointerMotionMask
|
451 ButtonPressMask
| ButtonReleaseMask
|
452 FocusChangeMask
| StructureNotifyMask
;
453 win_attr
.override_redirect
= FALSE
;
456 win_attr
.event_mask
= ExposureMask
| KeyPressMask
|
457 KeyReleaseMask
| PointerMotionMask
|
458 ButtonPressMask
| ButtonReleaseMask
|
460 win_attr
.override_redirect
= TRUE
;
462 win_attr
.colormap
= COLOR_WinColormap
;
463 win_attr
.backing_store
= Options
.backingstore
? WhenMapped
: NotUseful
;
464 win_attr
.save_under
= ((classPtr
->wc
.style
& CS_SAVEBITS
) != 0);
465 win_attr
.cursor
= CURSORICON_XCursor
;
466 wndPtr
->window
= XCreateWindow( display
, rootWindow
, x
, y
,
467 width
, height
, 0, CopyFromParent
,
468 InputOutput
, CopyFromParent
,
469 CWEventMask
| CWOverrideRedirect
|
470 CWColormap
| CWCursor
| CWSaveUnder
|
471 CWBackingStore
, &win_attr
);
472 XStoreName( display
, wndPtr
->window
, PTR_SEG_TO_LIN(windowName
) );
473 EVENT_RegisterWindow( wndPtr
->window
, hwnd
);
476 if ((style
& WS_CAPTION
) && !(style
& WS_CHILD
))
478 if (menu
) SetMenu(hwnd
, menu
);
479 else if (classPtr
->wc
.lpszMenuName
)
480 SetMenu( hwnd
, LoadMenu( instance
, classPtr
->wc
.lpszMenuName
) );
482 else wndPtr
->wIDmenu
= (UINT
)menu
;
484 /* Send the WM_CREATE message */
486 createStruct
.lpCreateParams
= (LPSTR
)data
;
487 createStruct
.hInstance
= instance
;
488 createStruct
.hMenu
= menu
;
489 createStruct
.hwndParent
= parent
;
490 createStruct
.cx
= width
;
491 createStruct
.cy
= height
;
494 createStruct
.style
= style
;
495 createStruct
.lpszName
= windowName
;
496 createStruct
.lpszClass
= className
;
497 createStruct
.dwExStyle
= 0;
499 wmcreate
= SendMessage( hwnd
, WM_NCCREATE
, 0, MAKE_SEGPTR(&createStruct
) );
502 dprintf_win(stddeb
,"CreateWindowEx: WM_NCCREATE return 0\n");
507 WINPOS_SendNCCalcSize( hwnd
, FALSE
, &wndPtr
->rectWindow
,
508 NULL
, NULL
, NULL
, &wndPtr
->rectClient
);
509 wmcreate
= SendMessage(hwnd
, WM_CREATE
, 0, MAKE_SEGPTR(&createStruct
));
514 /* Abort window creation */
515 dprintf_win(stddeb
,"CreateWindowEx: wmcreate==-1, aborting\n");
516 WIN_DestroyWindow( hwnd
);
520 /* Create a copy of SysMenu */
521 if (style
& WS_SYSMENU
) wndPtr
->hSysMenu
= CopySysMenu();
523 WIN_SendParentNotify( hwnd
, WM_CREATE
, wndPtr
->wIDmenu
, (LONG
)hwnd
);
525 /* Show the window, maximizing or minimizing if needed */
527 if (wndPtr
->dwStyle
& WS_MINIMIZE
)
529 wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
530 WINPOS_FindIconPos( hwnd
);
531 SetWindowPos( hwnd
, 0, wndPtr
->ptIconPos
.x
, wndPtr
->ptIconPos
.y
,
532 SYSMETRICS_CXICON
, SYSMETRICS_CYICON
,
534 (style
& WS_VISIBLE
) ? SWP_SHOWWINDOW
: 0 );
536 else if (wndPtr
->dwStyle
& WS_MAXIMIZE
)
538 SetWindowPos( hwnd
, 0, maxPos
.x
, maxPos
.y
, maxSize
.x
, maxSize
.y
,
540 (style
& WS_VISIBLE
) ? SWP_SHOWWINDOW
: 0 );
542 else if (style
& WS_VISIBLE
) ShowWindow( hwnd
, SW_SHOW
);
544 dprintf_win(stddeb
, "CreateWindowEx: return "NPFMT
" \n", hwnd
);
549 /***********************************************************************
550 * DestroyWindow (USER.53)
552 BOOL
DestroyWindow( HWND hwnd
)
557 dprintf_win(stddeb
, "DestroyWindow ("NPFMT
")\n", hwnd
);
561 if (hwnd
== hwndDesktop
) return FALSE
; /* Can't destroy desktop */
562 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
563 if (!(classPtr
= CLASS_FindClassPtr( wndPtr
->hClass
))) return FALSE
;
565 /* Hide the window */
567 if (wndPtr
->dwStyle
& WS_VISIBLE
)
568 SetWindowPos( hwnd
, 0, 0, 0, 0, 0, SWP_HIDEWINDOW
| SWP_NOACTIVATE
|
569 SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOSIZE
);
570 if ((hwnd
== GetCapture()) || IsChild( hwnd
, GetCapture() ))
572 WIN_SendParentNotify( hwnd
, WM_DESTROY
, wndPtr
->wIDmenu
, (LONG
)hwnd
);
574 /* Recursively destroy owned windows */
578 HWND hwndSibling
= GetWindow( hwnd
, GW_HWNDFIRST
);
581 WND
*siblingPtr
= WIN_FindWndPtr( hwndSibling
);
582 if (siblingPtr
->hwndOwner
== hwnd
) break;
583 hwndSibling
= siblingPtr
->hwndNext
;
585 if (hwndSibling
) DestroyWindow( hwndSibling
);
589 /* Send destroy messages and destroy children */
591 SendMessage( hwnd
, WM_DESTROY
, 0, 0 );
592 while (wndPtr
->hwndChild
) /* The child removes itself from the list */
593 DestroyWindow( wndPtr
->hwndChild
);
594 SendMessage( hwnd
, WM_NCDESTROY
, 0, 0 );
596 /* Destroy the window */
598 WIN_DestroyWindow( hwnd
);
603 /***********************************************************************
604 * CloseWindow (USER.43)
606 void CloseWindow(HWND hWnd
)
608 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
609 if (wndPtr
->dwStyle
& WS_CHILD
) return;
610 ShowWindow(hWnd
, SW_MINIMIZE
);
614 /***********************************************************************
617 BOOL
OpenIcon(HWND hWnd
)
619 if (!IsIconic(hWnd
)) return FALSE
;
620 ShowWindow(hWnd
, SW_SHOWNORMAL
);
625 /***********************************************************************
626 * FindWindow (USER.50)
628 HWND
FindWindow( SEGPTR ClassMatch
, LPSTR TitleMatch
)
636 hclass
= CLASS_FindClassByName( ClassMatch
, (HINSTANCE
)0xffff,
638 if (!hclass
) return 0;
642 hwnd
= GetTopWindow( hwndDesktop
);
645 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
646 if (!hclass
|| (wndPtr
->hClass
== hclass
))
648 /* Found matching class */
649 if (!TitleMatch
) return hwnd
;
652 char *textPtr
= (char *) USER_HEAP_LIN_ADDR( wndPtr
->hText
);
653 if (!strcmp( textPtr
, TitleMatch
)) return hwnd
;
656 hwnd
= wndPtr
->hwndNext
;
662 /**********************************************************************
663 * GetDesktopWindow (USER.286)
664 * GetDeskTopHwnd (USER.278)
666 HWND
GetDesktopWindow(void)
672 /*******************************************************************
673 * EnableWindow (USER.34)
675 BOOL
EnableWindow( HWND hwnd
, BOOL enable
)
679 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
680 if (enable
&& (wndPtr
->dwStyle
& WS_DISABLED
))
683 wndPtr
->dwStyle
&= ~WS_DISABLED
;
684 SendMessage( hwnd
, WM_ENABLE
, TRUE
, 0 );
687 else if (!enable
&& !(wndPtr
->dwStyle
& WS_DISABLED
))
690 wndPtr
->dwStyle
|= WS_DISABLED
;
691 if ((hwnd
== GetFocus()) || IsChild( hwnd
, GetFocus() ))
692 SetFocus( 0 ); /* A disabled window can't have the focus */
693 if ((hwnd
== GetCapture()) || IsChild( hwnd
, GetCapture() ))
694 ReleaseCapture(); /* A disabled window can't capture the mouse */
695 SendMessage( hwnd
, WM_ENABLE
, FALSE
, 0 );
698 return ((wndPtr
->dwStyle
& WS_DISABLED
) != 0);
702 /***********************************************************************
703 * IsWindowEnabled (USER.35)
705 BOOL
IsWindowEnabled(HWND hWnd
)
709 if (!(wndPtr
= WIN_FindWndPtr(hWnd
))) return FALSE
;
710 return !(wndPtr
->dwStyle
& WS_DISABLED
);
714 /**********************************************************************
715 * GetWindowWord (USER.133)
717 WORD
GetWindowWord( HWND hwnd
, short offset
)
719 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
720 if (!wndPtr
) return 0;
721 if (offset
>= 0) return *(WORD
*)(((char *)wndPtr
->wExtra
) + offset
);
724 case GWW_ID
: return wndPtr
->wIDmenu
;
728 fprintf(stderr
,"GetWindowWord called with offset %d.\n",offset
);
731 case GWW_HWNDPARENT
: return (WORD
)wndPtr
->hwndParent
;
732 case GWW_HINSTANCE
: return (WORD
)wndPtr
->hInstance
;
739 /**********************************************************************
740 * WIN_GetWindowInstance
742 HINSTANCE
WIN_GetWindowInstance(HWND hwnd
)
744 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
745 if (!wndPtr
) return (HINSTANCE
)0;
746 return wndPtr
->hInstance
;
750 /**********************************************************************
751 * SetWindowWord (USER.134)
753 WORD
SetWindowWord( HWND hwnd
, short offset
, WORD newval
)
756 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
757 if (!wndPtr
) return 0;
758 if (offset
>= 0) ptr
= (WORD
*)(((char *)wndPtr
->wExtra
) + offset
);
764 fprintf(stderr
,"SetWindowWord called with offset %d.\n",offset
);
767 case GWW_ID
: ptr
= &wndPtr
->wIDmenu
; break;
768 case GWW_HINSTANCE
: ptr
= (WORD
*)&wndPtr
->hInstance
; break;
778 /**********************************************************************
779 * GetWindowLong (USER.135)
781 LONG
GetWindowLong( HWND hwnd
, short offset
)
783 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
784 if (!wndPtr
) return 0;
785 if (offset
>= 0) return *(LONG
*)(((char *)wndPtr
->wExtra
) + offset
);
788 case GWL_STYLE
: return wndPtr
->dwStyle
;
789 case GWL_EXSTYLE
: return wndPtr
->dwExStyle
;
790 case GWL_WNDPROC
: return (LONG
)wndPtr
->lpfnWndProc
;
792 case GWW_HWNDPARENT
: return (LONG
)wndPtr
->hwndParent
;
793 case GWW_HINSTANCE
: return (LONG
)wndPtr
->hInstance
;
800 /**********************************************************************
801 * SetWindowLong (USER.136)
803 LONG
SetWindowLong( HWND hwnd
, short offset
, LONG newval
)
806 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
807 if (!wndPtr
) return 0;
808 if (offset
>= 0) ptr
= (LONG
*)(((char *)wndPtr
->wExtra
) + offset
);
811 case GWL_STYLE
: ptr
= &wndPtr
->dwStyle
; break;
812 case GWL_EXSTYLE
: ptr
= &wndPtr
->dwExStyle
; break;
813 case GWL_WNDPROC
: ptr
= (LONG
*)&wndPtr
->lpfnWndProc
; break;
822 /*******************************************************************
823 * GetWindowText (USER.36)
825 int WIN16_GetWindowText( HWND hwnd
, SEGPTR lpString
, int nMaxCount
)
827 return (int)SendMessage(hwnd
, WM_GETTEXT
, (WORD
)nMaxCount
,
831 int GetWindowText( HWND hwnd
, LPSTR lpString
, int nMaxCount
)
836 /* We have to allocate a buffer on the USER heap */
837 /* to be able to pass its address to 16-bit code */
838 if (!(handle
= USER_HEAP_ALLOC( nMaxCount
))) return 0;
839 len
= (int)SendMessage( hwnd
, WM_GETTEXT
, (WPARAM
)nMaxCount
,
840 (LPARAM
)USER_HEAP_SEG_ADDR(handle
) );
841 strncpy( lpString
, USER_HEAP_LIN_ADDR(handle
), nMaxCount
);
842 USER_HEAP_FREE( handle
);
847 /*******************************************************************
848 * SetWindowText (USER.37)
850 void WIN16_SetWindowText( HWND hwnd
, SEGPTR lpString
)
852 SendMessage( hwnd
, WM_SETTEXT
, 0, (DWORD
)lpString
);
855 void SetWindowText( HWND hwnd
, LPSTR lpString
)
859 /* We have to allocate a buffer on the USER heap */
860 /* to be able to pass its address to 16-bit code */
861 if (!(handle
= USER_HEAP_ALLOC( strlen(lpString
)+1 ))) return;
862 strcpy( USER_HEAP_LIN_ADDR(handle
), lpString
);
863 SendMessage( hwnd
, WM_SETTEXT
, 0, (LPARAM
)USER_HEAP_SEG_ADDR(handle
) );
864 USER_HEAP_FREE( handle
);
868 /*******************************************************************
869 * GetWindowTextLength (USER.38)
871 int GetWindowTextLength(HWND hwnd
)
873 return (int)SendMessage(hwnd
, WM_GETTEXTLENGTH
, 0, 0 );
877 /*******************************************************************
880 BOOL
IsWindow( HWND hwnd
)
882 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
883 return ((wndPtr
!= NULL
) && (wndPtr
->dwMagic
== WND_MAGIC
));
887 /*****************************************************************
888 * GetParent (USER.46)
890 HWND
GetParent(HWND hwnd
)
892 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
893 if (!wndPtr
) return 0;
894 return (wndPtr
->dwStyle
& WS_CHILD
) ?
895 wndPtr
->hwndParent
: wndPtr
->hwndOwner
;
899 /*****************************************************************
902 * Get the top-level parent for a child window.
904 HWND
WIN_GetTopParent( HWND hwnd
)
908 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
909 if (wndPtr
->dwStyle
& WS_CHILD
) hwnd
= wndPtr
->hwndParent
;
916 /*****************************************************************
917 * SetParent (USER.233)
919 HWND
SetParent(HWND hwndChild
, HWND hwndNewParent
)
923 WND
*wndPtr
= WIN_FindWndPtr(hwndChild
);
924 if (!wndPtr
|| !(wndPtr
->dwStyle
& WS_CHILD
)) return 0;
926 temp
= wndPtr
->hwndParent
;
928 WIN_UnlinkWindow(hwndChild
);
930 wndPtr
->hwndParent
= hwndNewParent
;
932 wndPtr
->hwndParent
= GetDesktopWindow();
933 WIN_LinkWindow(hwndChild
, HWND_BOTTOM
);
935 if (IsWindowVisible(hwndChild
)) UpdateWindow(hwndChild
);
942 /*******************************************************************
945 BOOL
IsChild( HWND parent
, HWND child
)
947 WND
* wndPtr
= WIN_FindWndPtr( child
);
948 while (wndPtr
&& (wndPtr
->dwStyle
& WS_CHILD
))
950 if (wndPtr
->hwndParent
== parent
) return TRUE
;
951 wndPtr
= WIN_FindWndPtr( wndPtr
->hwndParent
);
957 /***********************************************************************
958 * IsWindowVisible (USER.49)
960 BOOL
IsWindowVisible( HWND hwnd
)
962 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
963 while (wndPtr
&& (wndPtr
->dwStyle
& WS_CHILD
))
965 if (!(wndPtr
->dwStyle
& WS_VISIBLE
)) return FALSE
;
966 wndPtr
= WIN_FindWndPtr( wndPtr
->hwndParent
);
968 return (wndPtr
&& (wndPtr
->dwStyle
& WS_VISIBLE
));
973 /*******************************************************************
974 * GetTopWindow (USER.229)
976 HWND
GetTopWindow( HWND hwnd
)
978 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
979 if (wndPtr
) return wndPtr
->hwndChild
;
984 /*******************************************************************
985 * GetWindow (USER.262)
987 HWND
GetWindow( HWND hwnd
, WORD rel
)
989 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
990 if (!wndPtr
) return 0;
994 if (wndPtr
->hwndParent
)
996 WND
* parentPtr
= WIN_FindWndPtr( wndPtr
->hwndParent
);
997 return parentPtr
->hwndChild
;
1002 if (!wndPtr
->hwndParent
) return 0; /* Desktop window */
1003 while (wndPtr
->hwndNext
)
1005 hwnd
= wndPtr
->hwndNext
;
1006 wndPtr
= WIN_FindWndPtr( hwnd
);
1011 return wndPtr
->hwndNext
;
1017 if (wndPtr
->hwndParent
)
1019 WND
* parentPtr
= WIN_FindWndPtr( wndPtr
->hwndParent
);
1020 hwndPrev
= parentPtr
->hwndChild
;
1022 else return 0; /* Desktop window */
1023 if (hwndPrev
== hwnd
) return 0;
1026 wndPtr
= WIN_FindWndPtr( hwndPrev
);
1027 if (wndPtr
->hwndNext
== hwnd
) break;
1028 hwndPrev
= wndPtr
->hwndNext
;
1034 return wndPtr
->hwndOwner
;
1037 return wndPtr
->hwndChild
;
1043 /*******************************************************************
1044 * GetNextWindow (USER.230)
1046 HWND
GetNextWindow( HWND hwnd
, WORD flag
)
1048 if ((flag
!= GW_HWNDNEXT
) && (flag
!= GW_HWNDPREV
)) return 0;
1049 return GetWindow( hwnd
, flag
);
1052 /*******************************************************************
1053 * ShowOwnedPopups (USER.265)
1055 void ShowOwnedPopups( HWND owner
, BOOL fShow
)
1057 HWND hwnd
= GetWindow( hwndDesktop
, GW_CHILD
);
1060 WND
*wnd
= WIN_FindWndPtr(hwnd
);
1061 if (wnd
->hwndOwner
== owner
&& (wnd
->dwStyle
& WS_POPUP
))
1062 ShowWindow( hwnd
, fShow
? SW_SHOW
: SW_HIDE
);
1063 hwnd
= wnd
->hwndNext
;
1068 /*******************************************************************
1069 * GetLastActivePopup (USER.287)
1071 HWND
GetLastActivePopup(HWND hwnd
)
1074 wndPtr
= WIN_FindWndPtr(hwnd
);
1075 if (wndPtr
== NULL
) return hwnd
;
1076 return wndPtr
->hwndLastActive
;
1080 /*******************************************************************
1081 * EnumWindows (USER.54)
1083 BOOL
EnumWindows( FARPROC lpEnumFunc
, LPARAM lParam
)
1090 /* We have to build a list of all windows first, to avoid */
1091 /* unpleasant side-effects, for instance if the callback */
1092 /* function changes the Z-order of the windows. */
1094 /* First count the windows */
1097 for (hwnd
= GetTopWindow(hwndDesktop
); hwnd
!= 0; hwnd
= wndPtr
->hwndNext
)
1099 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
1102 if (!count
) return TRUE
;
1104 /* Now build the list of all windows */
1106 if (!(list
= (HWND
*)malloc( sizeof(HWND
) * count
))) return FALSE
;
1107 for (hwnd
= GetTopWindow(hwndDesktop
), pWnd
= list
; hwnd
!= 0; hwnd
= wndPtr
->hwndNext
)
1109 wndPtr
= WIN_FindWndPtr( hwnd
);
1113 /* Now call the callback function for every window */
1115 for (pWnd
= list
; count
> 0; count
--, pWnd
++)
1117 /* Make sure that window still exists */
1118 if (!IsWindow(*pWnd
)) continue;
1119 if (!CallEnumWindowsProc( lpEnumFunc
, *pWnd
, lParam
)) break;
1126 /**********************************************************************
1127 * EnumTaskWindows (USER.225)
1129 BOOL
EnumTaskWindows( HTASK hTask
, FARPROC lpEnumFunc
, LONG lParam
)
1134 HANDLE hQueue
= GetTaskQueue( hTask
);
1137 /* This function is the same as EnumWindows(), */
1138 /* except for an added check on the window queue. */
1140 /* First count the windows */
1143 for (hwnd
= GetTopWindow(hwndDesktop
); hwnd
!= 0; hwnd
= wndPtr
->hwndNext
)
1145 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
1146 if (wndPtr
->hmemTaskQ
== hQueue
) count
++;
1148 if (!count
) return TRUE
;
1150 /* Now build the list of all windows */
1152 if (!(list
= (HWND
*)malloc( sizeof(HWND
) * count
))) return FALSE
;
1153 for (hwnd
= GetTopWindow(hwndDesktop
), pWnd
= list
; hwnd
!= 0; hwnd
= wndPtr
->hwndNext
)
1155 wndPtr
= WIN_FindWndPtr( hwnd
);
1156 if (wndPtr
->hmemTaskQ
== hQueue
) *pWnd
++ = hwnd
;
1159 /* Now call the callback function for every window */
1161 for (pWnd
= list
; count
> 0; count
--, pWnd
++)
1163 /* Make sure that window still exists */
1164 if (!IsWindow(*pWnd
)) continue;
1165 if (!CallEnumTaskWndProc( lpEnumFunc
, *pWnd
, lParam
)) break;
1172 /*******************************************************************
1175 * o hwnd is the first child to use, loop until all next windows
1180 * o call ourselves with the next child window
1183 static BOOL
WIN_EnumChildWin(HWND hwnd
, FARPROC wndenumprc
, LPARAM lParam
)
1189 if (!(wndPtr
=WIN_FindWndPtr(hwnd
))) return 0;
1190 if (!CallEnumWindowsProc( wndenumprc
, hwnd
, lParam
)) return 0;
1191 if (!WIN_EnumChildWin(wndPtr
->hwndChild
, wndenumprc
, lParam
)) return 0;
1192 hwnd
=wndPtr
->hwndNext
;
1197 /*******************************************************************
1198 * EnumChildWindows (USER.55)
1200 * o gets the first child of hwnd
1202 * o calls WIN_EnumChildWin to do a recursive decent of child windows
1204 BOOL
EnumChildWindows(HWND hwnd
, FARPROC wndenumprc
, LPARAM lParam
)
1208 dprintf_enum(stddeb
,"EnumChildWindows\n");
1210 if (hwnd
== 0) return 0;
1211 if (!(wndPtr
= WIN_FindWndPtr(hwnd
))) return 0;
1212 hwnd
= wndPtr
->hwndChild
;
1213 return WIN_EnumChildWin(hwnd
, wndenumprc
, lParam
);
1217 /*******************************************************************
1218 * AnyPopup [USER.52]
1222 WND
*wndPtr
= WIN_FindWndPtr(hwndDesktop
);
1223 HWND hwnd
= wndPtr
->hwndChild
;
1225 for( ; hwnd
; hwnd
= wndPtr
->hwndNext
)
1227 wndPtr
= WIN_FindWndPtr(hwnd
);
1228 if(wndPtr
->hwndOwner
)
1229 if(wndPtr
->dwStyle
& WS_VISIBLE
)
1235 /*******************************************************************
1236 * FlashWindow [USER.105]
1238 BOOL
FlashWindow(HWND hWnd
, BOOL bInvert
)
1240 dprintf_win(stdnimp
,"EMPTY STUB !! FlashWindow !\n");
1245 /*******************************************************************
1246 * SetSysModalWindow [USER.188]
1248 HWND
SetSysModalWindow(HWND hWnd
)
1250 HWND hWndOldModal
= hwndSysModal
;
1251 hwndSysModal
= hWnd
;
1252 dprintf_win(stdnimp
,"EMPTY STUB !! SetSysModalWindow("NPFMT
") !\n", hWnd
);
1253 return hWndOldModal
;
1257 /*******************************************************************
1258 * GetSysModalWindow [USER.189]
1260 HWND
GetSysModalWindow(void)
1262 return hwndSysModal
;
1265 /*******************************************************************
1268 * recursively find a child that contains spDragInfo->pt point
1269 * and send WM_QUERYDROPOBJECT
1271 BOOL
DRAG_QueryUpdate( HWND hQueryWnd
, SEGPTR spDragInfo
)
1274 BOOL wParam
,bResult
= 0;
1276 LPDRAGINFO ptrDragInfo
= (LPDRAGINFO
) PTR_SEG_TO_LIN(spDragInfo
);
1277 WND
*ptrQueryWnd
= WIN_FindWndPtr(hQueryWnd
),*ptrWnd
;
1278 RECT tempRect
; /* this sucks */
1280 if( !ptrQueryWnd
|| !ptrDragInfo
) return 0;
1282 pt
= ptrDragInfo
->pt
;
1284 GetWindowRect(hQueryWnd
,&tempRect
);
1286 if( !PtInRect(&tempRect
,pt
) ||
1287 (ptrQueryWnd
->dwStyle
& WS_DISABLED
) )
1290 if( !(ptrQueryWnd
->dwStyle
& WS_MINIMIZE
) )
1292 tempRect
= ptrQueryWnd
->rectClient
;
1293 if(ptrQueryWnd
->dwStyle
& WS_CHILD
)
1294 MapWindowPoints(ptrQueryWnd
->hwndParent
,0,(LPPOINT
)&tempRect
,2);
1296 if( PtInRect(&tempRect
,pt
) )
1299 ptrWnd
= WIN_FindWndPtr(hWnd
= ptrQueryWnd
->hwndChild
);
1301 for( ;ptrWnd
;ptrWnd
= WIN_FindWndPtr(hWnd
= ptrWnd
->hwndNext
) )
1302 if( ptrWnd
->dwStyle
& WS_VISIBLE
)
1304 GetWindowRect(hWnd
,&tempRect
);
1306 if( PtInRect(&tempRect
,pt
) )
1311 dprintf_msg(stddeb
,"DragQueryUpdate: hwnd = "NPFMT
", %i %i - %i %i\n",hWnd
,
1312 ptrWnd
->rectWindow
.left
,ptrWnd
->rectWindow
.top
,
1313 ptrWnd
->rectWindow
.right
,ptrWnd
->rectWindow
.bottom
);
1315 dprintf_msg(stddeb
,"DragQueryUpdate: hwnd = "NPFMT
"\n",hWnd
);
1318 if( !(ptrWnd
->dwStyle
& WS_DISABLED
) )
1319 bResult
= DRAG_QueryUpdate(hWnd
, spDragInfo
);
1321 if(bResult
) return bResult
;
1327 ScreenToClient(hQueryWnd
,&ptrDragInfo
->pt
);
1329 ptrDragInfo
->hScope
= hQueryWnd
;
1331 bResult
= SendMessage( hQueryWnd
,WM_QUERYDROPOBJECT
,
1332 (WPARAM
)wParam
,(LPARAM
) spDragInfo
);
1334 ptrDragInfo
->pt
= pt
;
1339 /*******************************************************************
1340 * DragDetect ( USER.465 )
1343 BOOL
DragDetect(HWND hWnd
, POINT pt
)
1348 rect
.left
= pt
.x
- wDragWidth
;
1349 rect
.right
= pt
.x
+ wDragWidth
;
1351 rect
.top
= pt
.y
- wDragHeight
;
1352 rect
.bottom
= pt
.y
+ wDragHeight
;
1358 while(PeekMessage(&msg
,0 ,WM_MOUSEFIRST
,WM_MOUSELAST
,PM_REMOVE
))
1360 if( msg
.message
== WM_LBUTTONUP
)
1365 if( msg
.message
== WM_MOUSEMOVE
)
1367 POINT pt
= { LOWORD(msg
.lParam
), HIWORD(msg
.lParam
) };
1368 if( !PtInRect( &rect
, pt
) )
1381 /******************************************************************************
1382 * DragObject ( USER.464 )
1385 DWORD
DragObject(HWND hwndScope
, HWND hWnd
, WORD wObj
, HANDLE hOfStruct
,
1386 WORD szList
, HCURSOR hCursor
)
1389 LPDRAGINFO lpDragInfo
;
1391 HCURSOR hDragCursor
=0, hOldCursor
=0, hBummer
=0;
1392 HANDLE hDragInfo
= GlobalAlloc( GMEM_SHARE
| GMEM_ZEROINIT
, 2*sizeof(DRAGINFO
));
1393 WND
*wndPtr
= WIN_FindWndPtr(hWnd
);
1396 HCURSOR hCurrentCursor
= 0;
1397 HWND hCurrentWnd
= 0;
1400 fprintf(stdnimp
,"DragObject: experimental\n");
1402 lpDragInfo
= (LPDRAGINFO
) GlobalLock(hDragInfo
);
1403 spDragInfo
= (SEGPTR
) WIN16_GlobalLock(hDragInfo
);
1405 if( !lpDragInfo
|| !spDragInfo
) return 0L;
1407 hBummer
= LoadCursor(0,IDC_BUMMER
);
1409 if( !hBummer
|| !wndPtr
)
1411 GlobalFree(hDragInfo
);
1417 if( !(hDragCursor
= CURSORICON_IconToCursor(hCursor
)) )
1419 GlobalFree(hDragInfo
);
1423 if( hDragCursor
== hCursor
) hDragCursor
= 0;
1424 else hCursor
= hDragCursor
;
1426 hOldCursor
= SetCursor(hDragCursor
);
1429 lpDragInfo
->hWnd
= hWnd
;
1430 lpDragInfo
->hScope
= 0;
1431 lpDragInfo
->wFlags
= wObj
;
1432 lpDragInfo
->hList
= szList
; /* near pointer! */
1433 lpDragInfo
->hOfStruct
= hOfStruct
;
1443 if( !PeekMessage(&msg
,0,WM_MOUSEFIRST
,WM_MOUSELAST
,PM_REMOVE
) )
1446 *(lpDragInfo
+1) = *lpDragInfo
;
1448 lpDragInfo
->pt
= msg
.pt
;
1450 /* update DRAGINFO struct */
1451 dprintf_msg(stddeb
,"drag: lpDI->hScope = "NPFMT
"\n",lpDragInfo
->hScope
);
1453 if( (btemp
= (WORD
)DRAG_QueryUpdate(hwndScope
, spDragInfo
)) > 0 )
1454 hCurrentCursor
= hCursor
;
1457 hCurrentCursor
= hBummer
;
1458 lpDragInfo
->hScope
= 0;
1460 if( hCurrentCursor
)
1461 SetCursor(hCurrentCursor
);
1463 dprintf_msg(stddeb
,"drag: got "NPFMT
"\n",btemp
);
1465 /* send WM_DRAGLOOP */
1466 SendMessage( hWnd
, WM_DRAGLOOP
, (WPARAM
)(hCurrentCursor
!= hBummer
) ,
1467 (LPARAM
) spDragInfo
);
1468 /* send WM_DRAGSELECT or WM_DRAGMOVE */
1469 if( hCurrentWnd
!= lpDragInfo
->hScope
)
1472 SendMessage( hCurrentWnd
, WM_DRAGSELECT
, 0,
1473 (LPARAM
)MAKELONG(LOWORD(spDragInfo
)+sizeof(DRAGINFO
),
1474 HIWORD(spDragInfo
)) );
1475 hCurrentWnd
= lpDragInfo
->hScope
;
1477 SendMessage( hCurrentWnd
, WM_DRAGSELECT
, 1, (LPARAM
)spDragInfo
);
1481 SendMessage( hCurrentWnd
, WM_DRAGMOVE
, 0, (LPARAM
)spDragInfo
);
1484 /* check if we're done */
1485 if( msg
.message
== WM_LBUTTONUP
|| msg
.message
== WM_NCLBUTTONUP
)
1494 SetCursor(hOldCursor
);
1496 DestroyCursor(hDragCursor
);
1499 if( hCurrentCursor
!= hBummer
)
1500 dwRet
= SendMessage( lpDragInfo
->hScope
, WM_DROPOBJECT
,
1501 hWnd
, (LPARAM
)spDragInfo
);
1502 GlobalFree(hDragInfo
);