Release 960302
[wine/hacks.git] / windows / win.c
blob697bef1a3a3a5e9f7ef50648b4abe9990709cdee
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <string.h>
10 #include "options.h"
11 #include "class.h"
12 #include "win.h"
13 #include "user.h"
14 #include "dce.h"
15 #include "sysmetrics.h"
16 #include "cursoricon.h"
17 #include "event.h"
18 #include "message.h"
19 #include "nonclient.h"
20 #include "winpos.h"
21 #include "color.h"
22 #include "shm_main_blk.h"
23 #include "dde_proc.h"
24 #include "callback.h"
25 #include "stddebug.h"
26 /* #define DEBUG_WIN */
27 /* #define DEBUG_MENU */
28 #include "debug.h"
30 static HWND hwndDesktop = 0;
31 static HWND hwndSysModal = 0;
33 static WORD wDragWidth = 4;
34 static WORD wDragHeight= 3;
36 extern HCURSOR CURSORICON_IconToCursor(HICON);
38 /***********************************************************************
39 * WIN_FindWndPtr
41 * Return a pointer to the WND structure corresponding to a HWND.
43 WND * WIN_FindWndPtr( HWND hwnd )
45 WND * ptr;
47 if (!hwnd) return NULL;
48 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
49 if (ptr->dwMagic != WND_MAGIC) return NULL;
50 return ptr;
54 /***********************************************************************
55 * WIN_GetXWindow
57 * Return the X window associated to a window.
59 Window WIN_GetXWindow( HWND hwnd )
61 WND *wndPtr = WIN_FindWndPtr( hwnd );
62 while (wndPtr && !wndPtr->window)
64 wndPtr = WIN_FindWndPtr( wndPtr->hwndParent );
66 return wndPtr ? wndPtr->window : 0;
70 /***********************************************************************
71 * WIN_UnlinkWindow
73 * Remove a window from the siblings linked list.
75 BOOL WIN_UnlinkWindow( HWND hwnd )
77 HWND * curWndPtr;
78 WND *parentPtr, *wndPtr;
80 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
81 if (!(parentPtr = WIN_FindWndPtr( wndPtr->hwndParent ))) return FALSE;
83 curWndPtr = &parentPtr->hwndChild;
85 while (*curWndPtr != hwnd)
87 WND * curPtr = WIN_FindWndPtr( *curWndPtr );
88 curWndPtr = &curPtr->hwndNext;
90 *curWndPtr = wndPtr->hwndNext;
91 return TRUE;
95 /***********************************************************************
96 * WIN_LinkWindow
98 * Insert a window into the siblings linked list.
99 * The window is inserted after the specified window, which can also
100 * be specified as HWND_TOP or HWND_BOTTOM.
102 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
104 HWND * hwndPtr = NULL; /* pointer to hwnd to change */
105 WND *wndPtr, *parentPtr;
107 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
108 if (!(parentPtr = WIN_FindWndPtr( wndPtr->hwndParent ))) return FALSE;
110 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
112 hwndPtr = &parentPtr->hwndChild; /* Point to first sibling hwnd */
113 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
114 while (*hwndPtr)
116 WND * nextPtr = WIN_FindWndPtr( *hwndPtr );
117 hwndPtr = &nextPtr->hwndNext;
120 else /* Normal case */
122 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
123 if (afterPtr) hwndPtr = &afterPtr->hwndNext;
125 if (!hwndPtr) return FALSE;
126 wndPtr->hwndNext = *hwndPtr;
127 *hwndPtr = hwnd;
128 return TRUE;
132 /***********************************************************************
133 * WIN_FindWinToRepaint
135 * Find a window that needs repaint.
137 HWND WIN_FindWinToRepaint( HWND hwnd )
139 WND * wndPtr;
141 /* Note: the desktop window never gets WM_PAINT messages */
142 if (!hwnd) hwnd = GetTopWindow( hwndDesktop );
143 for ( ; hwnd != 0; hwnd = wndPtr->hwndNext )
145 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
146 dprintf_win( stddeb, "WIN_FindWinToRepaint: "NPFMT", style %08lx\n",
147 hwnd, wndPtr->dwStyle );
148 if (!(wndPtr->dwStyle & WS_VISIBLE) || (wndPtr->flags & WIN_NO_REDRAW))
149 continue;
150 if ((wndPtr->dwStyle & WS_MINIMIZE) && (WIN_CLASS_INFO(wndPtr).hIcon))
151 continue;
152 if (wndPtr->hrgnUpdate || (wndPtr->flags & WIN_INTERNAL_PAINT))
153 return hwnd;
154 if (wndPtr->hwndChild)
156 HWND child;
157 if ((child = WIN_FindWinToRepaint( wndPtr->hwndChild )))
158 return child;
161 return 0;
165 /***********************************************************************
166 * WIN_SendParentNotify
168 * Send a WM_PARENTNOTIFY to all ancestors of the given window, unless
169 * the window has the WS_EX_NOPARENTNOTIFY style.
171 void WIN_SendParentNotify( HWND hwnd, WORD event, WORD idChild, LONG lValue )
173 WND *wndPtr = WIN_FindWndPtr( hwnd );
175 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
177 if (wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) break;
178 #ifdef WINELIB32
179 SendMessage( wndPtr->hwndParent, WM_PARENTNOTIFY,
180 MAKEWPARAM(event,idChild),
181 (LPARAM)lValue );
182 #else
183 SendMessage( wndPtr->hwndParent, WM_PARENTNOTIFY, event,
184 MAKELPARAM(LOWORD(lValue), idChild) );
185 #endif
186 wndPtr = WIN_FindWndPtr( wndPtr->hwndParent );
191 /***********************************************************************
192 * WIN_DestroyWindow
194 * Destroy storage associated to a window
196 static void WIN_DestroyWindow( HWND hwnd )
198 WND *wndPtr = WIN_FindWndPtr( hwnd );
199 CLASS *classPtr = CLASS_FindClassPtr( wndPtr->hClass );
201 #ifdef CONFIG_IPC
202 if (main_block)
203 DDE_DestroyWindow(hwnd);
204 #endif /* CONFIG_IPC */
206 if (!wndPtr || !classPtr) return;
207 WIN_UnlinkWindow( hwnd ); /* Remove the window from the linked list */
208 wndPtr->dwMagic = 0; /* Mark it as invalid */
209 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
211 if (wndPtr->hrgnUpdate) DeleteObject( wndPtr->hrgnUpdate );
212 MSG_DecPaintCount( wndPtr->hmemTaskQ );
214 if (!(wndPtr->dwStyle & WS_CHILD))
216 if (wndPtr->wIDmenu) DestroyMenu( (HMENU)wndPtr->wIDmenu );
218 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
219 if (wndPtr->window) XDestroyWindow( display, wndPtr->window );
220 if (classPtr->wc.style & CS_OWNDC) DCE_FreeDCE( wndPtr->hdce );
221 classPtr->cWindows--;
222 USER_HEAP_FREE( hwnd );
226 /***********************************************************************
227 * WIN_CreateDesktopWindow
229 * Create the desktop window.
231 BOOL WIN_CreateDesktopWindow(void)
233 WND *wndPtr;
234 HCLASS hclass;
235 CLASS *classPtr;
236 HDC hdc;
238 if (!(hclass = CLASS_FindClassByName( DESKTOP_CLASS_ATOM, 0, &classPtr )))
239 return FALSE;
241 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+classPtr->wc.cbWndExtra );
242 if (!hwndDesktop) return FALSE;
243 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
245 wndPtr->hwndNext = 0;
246 wndPtr->hwndChild = 0;
247 wndPtr->dwMagic = WND_MAGIC;
248 wndPtr->hwndParent = 0;
249 wndPtr->hwndOwner = 0;
250 wndPtr->hClass = hclass;
251 wndPtr->hInstance = 0;
252 wndPtr->rectWindow.left = 0;
253 wndPtr->rectWindow.top = 0;
254 wndPtr->rectWindow.right = SYSMETRICS_CXSCREEN;
255 wndPtr->rectWindow.bottom = SYSMETRICS_CYSCREEN;
256 wndPtr->rectClient = wndPtr->rectWindow;
257 wndPtr->rectNormal = wndPtr->rectWindow;
258 wndPtr->ptIconPos.x = -1;
259 wndPtr->ptIconPos.y = -1;
260 wndPtr->ptMaxPos.x = -1;
261 wndPtr->ptMaxPos.y = -1;
262 wndPtr->hmemTaskQ = 0; /* Desktop does not belong to a task */
263 wndPtr->hrgnUpdate = 0;
264 wndPtr->hwndLastActive = hwndDesktop;
265 wndPtr->lpfnWndProc = classPtr->wc.lpfnWndProc;
266 wndPtr->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
267 wndPtr->dwExStyle = 0;
268 wndPtr->hdce = 0;
269 wndPtr->hVScroll = 0;
270 wndPtr->hHScroll = 0;
271 wndPtr->wIDmenu = 0;
272 wndPtr->hText = 0;
273 wndPtr->flags = 0;
274 wndPtr->window = rootWindow;
275 wndPtr->hSysMenu = 0;
276 wndPtr->hProp = 0;
277 EVENT_RegisterWindow( wndPtr->window, hwndDesktop );
278 SendMessage( hwndDesktop, WM_NCCREATE, 0, 0 );
279 if ((hdc = GetDC( hwndDesktop )) != 0)
281 SendMessage( hwndDesktop, WM_ERASEBKGND, (WPARAM)hdc, 0 );
282 ReleaseDC( hwndDesktop, hdc );
284 return TRUE;
288 /***********************************************************************
289 * CreateWindow (USER.41)
291 HWND CreateWindow( SEGPTR className, SEGPTR windowName,
292 DWORD style, INT x, INT y, INT width, INT height,
293 HWND parent, HMENU menu, HANDLE instance, SEGPTR data )
295 return CreateWindowEx( 0, className, windowName, style,
296 x, y, width, height, parent, menu, instance, data );
300 /***********************************************************************
301 * CreateWindowEx (USER.452)
303 HWND CreateWindowEx( DWORD exStyle, SEGPTR className, SEGPTR windowName,
304 DWORD style, INT x, INT y, INT width, INT height,
305 HWND parent, HMENU menu, HANDLE instance, SEGPTR data )
307 HANDLE class, hwnd;
308 CLASS *classPtr;
309 WND *wndPtr, *parentWndPtr;
310 POINT maxSize, maxPos, minTrack, maxTrack;
311 CREATESTRUCT createStruct;
312 int wmcreate;
313 XSetWindowAttributes win_attr;
314 Atom XA_WM_DELETE_WINDOW;
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) );
321 else
322 dprintf_win( stddeb, "%04x ", LOWORD(windowName) );
323 if (HIWORD(className))
324 dprintf_win( stddeb, "'%s' ", (char *)PTR_SEG_TO_LIN(className) );
325 else
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)
335 width = 600;
336 height = 400;
339 /* Find the parent and class */
341 if (parent)
343 /* Make sure parent is valid */
344 if (!IsWindow( parent )) {
345 dprintf_win(stddeb,"CreateWindowEx: Parent "NPFMT" is not a window\n", parent);
346 return 0;
349 else
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),
358 &classPtr )))
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) );
364 return 0;
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 );
376 if (!hwnd) {
377 dprintf_win(stddeb,"CreateWindowEx: Out of memory\n");
378 return 0;
381 /* Fill the structure */
383 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
384 wndPtr->hwndNext = 0;
385 wndPtr->hwndChild = 0;
386 wndPtr->window = 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;
402 wndPtr->wIDmenu = 0;
403 wndPtr->hText = 0;
404 wndPtr->flags = 0;
405 wndPtr->hVScroll = 0;
406 wndPtr->hHScroll = 0;
407 wndPtr->hSysMenu = 0;
408 wndPtr->hProp = 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;
420 else
421 wndPtr->hdce = 0;
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 && ((style & (WS_DLGFRAME | WS_THICKFRAME)) ||
449 (exStyle & WS_EX_DLGMODALFRAME)))
451 win_attr.event_mask = ExposureMask | KeyPressMask |
452 KeyReleaseMask | PointerMotionMask |
453 ButtonPressMask | ButtonReleaseMask |
454 FocusChangeMask | StructureNotifyMask;
455 win_attr.override_redirect = FALSE;
456 wndPtr->flags |= WIN_MANAGED;
458 else
460 win_attr.event_mask = ExposureMask | KeyPressMask |
461 KeyReleaseMask | PointerMotionMask |
462 ButtonPressMask | ButtonReleaseMask |
463 FocusChangeMask;
464 win_attr.override_redirect = TRUE;
466 win_attr.colormap = COLOR_WinColormap;
467 win_attr.backing_store = Options.backingstore ? WhenMapped : NotUseful;
468 win_attr.save_under = ((classPtr->wc.style & CS_SAVEBITS) != 0);
469 win_attr.cursor = CURSORICON_XCursor;
470 wndPtr->window = XCreateWindow( display, rootWindow, x, y,
471 width, height, 0, CopyFromParent,
472 InputOutput, CopyFromParent,
473 CWEventMask | CWOverrideRedirect |
474 CWColormap | CWCursor | CWSaveUnder |
475 CWBackingStore, &win_attr );
476 XStoreName( display, wndPtr->window, PTR_SEG_TO_LIN(windowName) );
477 XA_WM_DELETE_WINDOW = XInternAtom( display, "WM_DELETE_WINDOW",
478 False );
479 XSetWMProtocols( display, wndPtr->window, &XA_WM_DELETE_WINDOW, 1 );
480 if (parent) /* Get window owner */
482 Window win = WIN_GetXWindow( parent );
483 if (win) XSetTransientForHint( display, wndPtr->window, win );
486 EVENT_RegisterWindow( wndPtr->window, hwnd );
489 if ((style & WS_CAPTION) && !(style & WS_CHILD))
491 if (menu) SetMenu(hwnd, menu);
492 else if (classPtr->wc.lpszMenuName)
493 SetMenu( hwnd, LoadMenu( instance, classPtr->wc.lpszMenuName ) );
495 else wndPtr->wIDmenu = (UINT)menu;
497 GetSystemMenu( hwnd, TRUE ); /* Create a copy of the system menu */
499 /* Send the WM_CREATE message */
501 createStruct.lpCreateParams = (LPSTR)data;
502 createStruct.hInstance = instance;
503 createStruct.hMenu = menu;
504 createStruct.hwndParent = parent;
505 createStruct.cx = width;
506 createStruct.cy = height;
507 createStruct.x = x;
508 createStruct.y = y;
509 createStruct.style = style;
510 createStruct.lpszName = windowName;
511 createStruct.lpszClass = className;
512 createStruct.dwExStyle = 0;
514 wmcreate = SendMessage( hwnd, WM_NCCREATE, 0, (LPARAM)MAKE_SEGPTR(&createStruct) );
515 if (!wmcreate)
517 dprintf_win(stddeb,"CreateWindowEx: WM_NCCREATE return 0\n");
518 wmcreate = -1;
520 else
522 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
523 NULL, NULL, NULL, &wndPtr->rectClient );
524 wmcreate = SendMessage(hwnd, WM_CREATE, 0, (LPARAM)MAKE_SEGPTR(&createStruct));
527 if (wmcreate == -1)
529 /* Abort window creation */
530 dprintf_win(stddeb,"CreateWindowEx: wmcreate==-1, aborting\n");
531 WIN_DestroyWindow( hwnd );
532 return 0;
535 WIN_SendParentNotify( hwnd, WM_CREATE, wndPtr->wIDmenu, (LONG)hwnd );
537 /* Show the window, maximizing or minimizing if needed */
539 if (wndPtr->dwStyle & WS_MINIMIZE)
541 wndPtr->dwStyle &= ~WS_MAXIMIZE;
542 WINPOS_FindIconPos( hwnd );
543 SetWindowPos( hwnd, 0, wndPtr->ptIconPos.x, wndPtr->ptIconPos.y,
544 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
545 SWP_FRAMECHANGED |
546 (style & WS_VISIBLE) ? SWP_SHOWWINDOW : 0 );
548 else if (wndPtr->dwStyle & WS_MAXIMIZE)
550 SetWindowPos( hwnd, 0, maxPos.x, maxPos.y, maxSize.x, maxSize.y,
551 SWP_FRAMECHANGED |
552 (style & WS_VISIBLE) ? SWP_SHOWWINDOW : 0 );
554 else if (style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
556 dprintf_win(stddeb, "CreateWindowEx: return "NPFMT" \n", hwnd);
557 return hwnd;
561 /***********************************************************************
562 * DestroyWindow (USER.53)
564 BOOL DestroyWindow( HWND hwnd )
566 WND * wndPtr;
567 CLASS * classPtr;
569 dprintf_win(stddeb, "DestroyWindow ("NPFMT")\n", hwnd);
571 /* Initialisation */
573 if (hwnd == hwndDesktop) return FALSE; /* Can't destroy desktop */
574 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
575 if (!(classPtr = CLASS_FindClassPtr( wndPtr->hClass ))) return FALSE;
577 /* Hide the window */
579 if (wndPtr->dwStyle & WS_VISIBLE)
580 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE |
581 SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE );
582 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
583 ReleaseCapture();
584 WIN_SendParentNotify( hwnd, WM_DESTROY, wndPtr->wIDmenu, (LONG)hwnd );
586 /* Recursively destroy owned windows */
588 for (;;)
590 HWND hwndSibling = GetWindow( hwnd, GW_HWNDFIRST );
591 while (hwndSibling)
593 WND *siblingPtr = WIN_FindWndPtr( hwndSibling );
594 if (siblingPtr->hwndOwner == hwnd) break;
595 hwndSibling = siblingPtr->hwndNext;
597 if (hwndSibling) DestroyWindow( hwndSibling );
598 else break;
601 /* Send destroy messages and destroy children */
603 SendMessage( hwnd, WM_DESTROY, 0, 0 );
604 while (wndPtr->hwndChild) /* The child removes itself from the list */
605 DestroyWindow( wndPtr->hwndChild );
606 SendMessage( hwnd, WM_NCDESTROY, 0, 0 );
608 /* Destroy the window */
610 WIN_DestroyWindow( hwnd );
611 return TRUE;
615 /***********************************************************************
616 * CloseWindow (USER.43)
618 BOOL CloseWindow(HWND hWnd)
620 WND * wndPtr = WIN_FindWndPtr(hWnd);
621 if (wndPtr->dwStyle & WS_CHILD) return TRUE;
622 ShowWindow(hWnd, SW_MINIMIZE);
623 return TRUE;
627 /***********************************************************************
628 * OpenIcon (USER.44)
630 BOOL OpenIcon(HWND hWnd)
632 if (!IsIconic(hWnd)) return FALSE;
633 ShowWindow(hWnd, SW_SHOWNORMAL);
634 return(TRUE);
638 /***********************************************************************
639 * FindWindow (USER.50)
641 HWND FindWindow( SEGPTR ClassMatch, LPSTR TitleMatch )
643 HCLASS hclass;
644 CLASS *classPtr;
645 HWND hwnd;
647 if (ClassMatch)
649 hclass = CLASS_FindClassByName( ClassMatch, (HINSTANCE)0xffff,
650 &classPtr );
651 if (!hclass) return 0;
653 else hclass = 0;
655 hwnd = GetTopWindow( hwndDesktop );
656 while(hwnd)
658 WND *wndPtr = WIN_FindWndPtr( hwnd );
659 if (!hclass || (wndPtr->hClass == hclass))
661 /* Found matching class */
662 if (!TitleMatch) return hwnd;
663 if (wndPtr->hText)
665 char *textPtr = (char *) USER_HEAP_LIN_ADDR( wndPtr->hText );
666 if (!strcmp( textPtr, TitleMatch )) return hwnd;
669 hwnd = wndPtr->hwndNext;
671 return 0;
675 /**********************************************************************
676 * GetDesktopWindow (USER.286)
678 HWND GetDesktopWindow(void)
680 return hwndDesktop;
684 /**********************************************************************
685 * GetDesktopHwnd (USER.278)
687 * Exactly the same thing as GetDesktopWindow(), but not documented.
688 * Don't ask me why...
690 HWND GetDesktopHwnd(void)
692 return hwndDesktop;
696 /*******************************************************************
697 * EnableWindow (USER.34)
699 BOOL EnableWindow( HWND hwnd, BOOL enable )
701 WND *wndPtr;
703 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
704 if (enable && (wndPtr->dwStyle & WS_DISABLED))
706 /* Enable window */
707 wndPtr->dwStyle &= ~WS_DISABLED;
708 SendMessage( hwnd, WM_ENABLE, TRUE, 0 );
709 return TRUE;
711 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
713 /* Disable window */
714 wndPtr->dwStyle |= WS_DISABLED;
715 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus() ))
716 SetFocus( 0 ); /* A disabled window can't have the focus */
717 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
718 ReleaseCapture(); /* A disabled window can't capture the mouse */
719 SendMessage( hwnd, WM_ENABLE, FALSE, 0 );
720 return FALSE;
722 return ((wndPtr->dwStyle & WS_DISABLED) != 0);
726 /***********************************************************************
727 * IsWindowEnabled (USER.35)
729 BOOL IsWindowEnabled(HWND hWnd)
731 WND * wndPtr;
733 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
734 return !(wndPtr->dwStyle & WS_DISABLED);
738 /**********************************************************************
739 * GetWindowWord (USER.133)
741 WORD GetWindowWord( HWND hwnd, short offset )
743 WND * wndPtr = WIN_FindWndPtr( hwnd );
744 if (!wndPtr) return 0;
745 if (offset >= 0) return *(WORD *)(((char *)wndPtr->wExtra) + offset);
746 switch(offset)
748 case GWW_ID: return wndPtr->wIDmenu;
749 #ifdef WINELIB32
750 case GWW_HWNDPARENT:
751 case GWW_HINSTANCE:
752 fprintf(stderr,"GetWindowWord called with offset %d.\n",offset);
753 return 0;
754 #else
755 case GWW_HWNDPARENT: return (WORD)wndPtr->hwndParent;
756 case GWW_HINSTANCE: return (WORD)wndPtr->hInstance;
757 #endif
759 return 0;
763 /**********************************************************************
764 * WIN_GetWindowInstance
766 HINSTANCE WIN_GetWindowInstance(HWND hwnd)
768 WND * wndPtr = WIN_FindWndPtr( hwnd );
769 if (!wndPtr) return (HINSTANCE)0;
770 return wndPtr->hInstance;
774 /**********************************************************************
775 * SetWindowWord (USER.134)
777 WORD SetWindowWord( HWND hwnd, short offset, WORD newval )
779 WORD *ptr, retval;
780 WND * wndPtr = WIN_FindWndPtr( hwnd );
781 if (!wndPtr) return 0;
782 if (offset >= 0) ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
783 else switch(offset)
785 #ifdef WINELIB32
786 case GWW_ID:
787 case GWW_HINSTANCE:
788 fprintf(stderr,"SetWindowWord called with offset %d.\n",offset);
789 return 0;
790 #else
791 case GWW_ID: ptr = &wndPtr->wIDmenu; break;
792 case GWW_HINSTANCE: ptr = (WORD*)&wndPtr->hInstance; break;
793 #endif
794 default: return 0;
796 retval = *ptr;
797 *ptr = newval;
798 return retval;
802 /**********************************************************************
803 * GetWindowLong (USER.135)
805 LONG GetWindowLong( HWND hwnd, short offset )
807 WND * wndPtr = WIN_FindWndPtr( hwnd );
808 if (!wndPtr) return 0;
809 if (offset >= 0) return *(LONG *)(((char *)wndPtr->wExtra) + offset);
810 switch(offset)
812 case GWL_STYLE: return wndPtr->dwStyle;
813 case GWL_EXSTYLE: return wndPtr->dwExStyle;
814 case GWL_WNDPROC: return (LONG)wndPtr->lpfnWndProc;
815 #ifdef WINELIB32
816 case GWW_HWNDPARENT: return (LONG)wndPtr->hwndParent;
817 case GWW_HINSTANCE: return (LONG)wndPtr->hInstance;
818 #endif
820 return 0;
824 /**********************************************************************
825 * SetWindowLong (USER.136)
827 LONG SetWindowLong( HWND hwnd, short offset, LONG newval )
829 LONG *ptr, retval;
830 WND * wndPtr = WIN_FindWndPtr( hwnd );
831 if (!wndPtr) return 0;
832 if (offset >= 0) ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
833 else switch(offset)
835 case GWL_STYLE: ptr = &wndPtr->dwStyle; break;
836 case GWL_EXSTYLE: ptr = &wndPtr->dwExStyle; break;
837 case GWL_WNDPROC: ptr = (LONG *)&wndPtr->lpfnWndProc; break;
838 default: return 0;
840 retval = *ptr;
841 *ptr = newval;
842 return retval;
846 /*******************************************************************
847 * GetWindowText (USER.36)
849 int WIN16_GetWindowText( HWND hwnd, SEGPTR lpString, int nMaxCount )
851 return (int)SendMessage(hwnd, WM_GETTEXT, (WORD)nMaxCount,
852 (DWORD)lpString);
855 int GetWindowText( HWND hwnd, LPSTR lpString, int nMaxCount )
857 int len;
858 HANDLE handle;
860 /* We have to allocate a buffer on the USER heap */
861 /* to be able to pass its address to 16-bit code */
862 if (!(handle = USER_HEAP_ALLOC( nMaxCount ))) return 0;
863 len = (int)SendMessage( hwnd, WM_GETTEXT, (WPARAM)nMaxCount,
864 (LPARAM)USER_HEAP_SEG_ADDR(handle) );
865 strncpy( lpString, USER_HEAP_LIN_ADDR(handle), nMaxCount );
866 USER_HEAP_FREE( handle );
867 return len;
871 /*******************************************************************
872 * SetWindowText (USER.37)
874 void WIN16_SetWindowText( HWND hwnd, SEGPTR lpString )
876 SendMessage( hwnd, WM_SETTEXT, 0, (DWORD)lpString );
879 void SetWindowText( HWND hwnd, LPCSTR lpString )
881 HANDLE handle;
883 /* We have to allocate a buffer on the USER heap */
884 /* to be able to pass its address to 16-bit code */
885 if (!(handle = USER_HEAP_ALLOC( strlen(lpString)+1 ))) return;
886 strcpy( USER_HEAP_LIN_ADDR(handle), lpString );
887 SendMessage( hwnd, WM_SETTEXT, 0, (LPARAM)USER_HEAP_SEG_ADDR(handle) );
888 USER_HEAP_FREE( handle );
892 /*******************************************************************
893 * GetWindowTextLength (USER.38)
895 int GetWindowTextLength(HWND hwnd)
897 return (int)SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0 );
901 /*******************************************************************
902 * IsWindow (USER.47)
904 BOOL IsWindow( HWND hwnd )
906 WND * wndPtr = WIN_FindWndPtr( hwnd );
907 return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
911 /*****************************************************************
912 * GetParent (USER.46)
914 HWND GetParent(HWND hwnd)
916 WND *wndPtr = WIN_FindWndPtr(hwnd);
917 if (!wndPtr) return 0;
918 return (wndPtr->dwStyle & WS_CHILD) ?
919 wndPtr->hwndParent : wndPtr->hwndOwner;
923 /*****************************************************************
924 * WIN_GetTopParent
926 * Get the top-level parent for a child window.
928 HWND WIN_GetTopParent( HWND hwnd )
930 while (hwnd)
932 WND *wndPtr = WIN_FindWndPtr( hwnd );
933 if (wndPtr->dwStyle & WS_CHILD) hwnd = wndPtr->hwndParent;
934 else break;
936 return hwnd;
940 /*****************************************************************
941 * SetParent (USER.233)
943 HWND SetParent(HWND hwndChild, HWND hwndNewParent)
945 HWND temp;
947 WND *wndPtr = WIN_FindWndPtr(hwndChild);
948 if (!wndPtr || !(wndPtr->dwStyle & WS_CHILD)) return 0;
950 temp = wndPtr->hwndParent;
952 WIN_UnlinkWindow(hwndChild);
953 if (hwndNewParent)
954 wndPtr->hwndParent = hwndNewParent;
955 else
956 wndPtr->hwndParent = GetDesktopWindow();
957 WIN_LinkWindow(hwndChild, HWND_BOTTOM);
959 if (IsWindowVisible(hwndChild)) UpdateWindow(hwndChild);
961 return temp;
966 /*******************************************************************
967 * IsChild (USER.48)
969 BOOL IsChild( HWND parent, HWND child )
971 WND * wndPtr = WIN_FindWndPtr( child );
972 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
974 if (wndPtr->hwndParent == parent) return TRUE;
975 wndPtr = WIN_FindWndPtr( wndPtr->hwndParent );
977 return FALSE;
981 /***********************************************************************
982 * IsWindowVisible (USER.49)
984 BOOL IsWindowVisible( HWND hwnd )
986 WND *wndPtr = WIN_FindWndPtr( hwnd );
987 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
989 if (!(wndPtr->dwStyle & WS_VISIBLE)) return FALSE;
990 wndPtr = WIN_FindWndPtr( wndPtr->hwndParent );
992 return (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
997 /*******************************************************************
998 * GetTopWindow (USER.229)
1000 HWND GetTopWindow( HWND hwnd )
1002 WND * wndPtr = WIN_FindWndPtr( hwnd );
1003 if (wndPtr) return wndPtr->hwndChild;
1004 else return 0;
1008 /*******************************************************************
1009 * GetWindow (USER.262)
1011 HWND GetWindow( HWND hwnd, WORD rel )
1013 WND * wndPtr = WIN_FindWndPtr( hwnd );
1014 if (!wndPtr) return 0;
1015 switch(rel)
1017 case GW_HWNDFIRST:
1018 if (wndPtr->hwndParent)
1020 WND * parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
1021 return parentPtr->hwndChild;
1023 else return 0;
1025 case GW_HWNDLAST:
1026 if (!wndPtr->hwndParent) return 0; /* Desktop window */
1027 while (wndPtr->hwndNext)
1029 hwnd = wndPtr->hwndNext;
1030 wndPtr = WIN_FindWndPtr( hwnd );
1032 return hwnd;
1034 case GW_HWNDNEXT:
1035 return wndPtr->hwndNext;
1037 case GW_HWNDPREV:
1039 HWND hwndPrev;
1041 if (wndPtr->hwndParent)
1043 WND * parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
1044 hwndPrev = parentPtr->hwndChild;
1046 else return 0; /* Desktop window */
1047 if (hwndPrev == hwnd) return 0;
1048 while (hwndPrev)
1050 wndPtr = WIN_FindWndPtr( hwndPrev );
1051 if (wndPtr->hwndNext == hwnd) break;
1052 hwndPrev = wndPtr->hwndNext;
1054 return hwndPrev;
1057 case GW_OWNER:
1058 return wndPtr->hwndOwner;
1060 case GW_CHILD:
1061 return wndPtr->hwndChild;
1063 return 0;
1067 /*******************************************************************
1068 * GetNextWindow (USER.230)
1070 HWND GetNextWindow( HWND hwnd, WORD flag )
1072 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
1073 return GetWindow( hwnd, flag );
1076 /*******************************************************************
1077 * ShowOwnedPopups (USER.265)
1079 void ShowOwnedPopups( HWND owner, BOOL fShow )
1081 HWND hwnd = GetWindow( hwndDesktop, GW_CHILD );
1082 while (hwnd)
1084 WND *wnd = WIN_FindWndPtr(hwnd);
1085 if (wnd->hwndOwner == owner && (wnd->dwStyle & WS_POPUP))
1086 ShowWindow( hwnd, fShow ? SW_SHOW : SW_HIDE );
1087 hwnd = wnd->hwndNext;
1092 /*******************************************************************
1093 * GetLastActivePopup (USER.287)
1095 HWND GetLastActivePopup(HWND hwnd)
1097 WND *wndPtr;
1098 wndPtr = WIN_FindWndPtr(hwnd);
1099 if (wndPtr == NULL) return hwnd;
1100 return wndPtr->hwndLastActive;
1104 /*******************************************************************
1105 * EnumWindows (USER.54)
1107 BOOL EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
1109 HWND hwnd;
1110 WND *wndPtr;
1111 HWND *list, *pWnd;
1112 int count;
1114 /* We have to build a list of all windows first, to avoid */
1115 /* unpleasant side-effects, for instance if the callback */
1116 /* function changes the Z-order of the windows. */
1118 /* First count the windows */
1120 count = 0;
1121 for (hwnd = GetTopWindow(hwndDesktop); hwnd != 0; hwnd = wndPtr->hwndNext)
1123 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1124 count++;
1126 if (!count) return TRUE;
1128 /* Now build the list of all windows */
1130 if (!(list = (HWND *)malloc( sizeof(HWND) * count ))) return FALSE;
1131 for (hwnd = GetTopWindow(hwndDesktop), pWnd = list; hwnd != 0; hwnd = wndPtr->hwndNext)
1133 wndPtr = WIN_FindWndPtr( hwnd );
1134 *pWnd++ = hwnd;
1137 /* Now call the callback function for every window */
1139 for (pWnd = list; count > 0; count--, pWnd++)
1141 /* Make sure that window still exists */
1142 if (!IsWindow(*pWnd)) continue;
1143 if (!CallEnumWindowsProc( lpEnumFunc, *pWnd, lParam )) break;
1145 free( list );
1146 return TRUE;
1150 /**********************************************************************
1151 * EnumTaskWindows (USER.225)
1153 BOOL EnumTaskWindows( HTASK hTask, WNDENUMPROC lpEnumFunc, LPARAM lParam )
1155 HWND hwnd;
1156 WND *wndPtr;
1157 HWND *list, *pWnd;
1158 HANDLE hQueue = GetTaskQueue( hTask );
1159 int count;
1161 /* This function is the same as EnumWindows(), */
1162 /* except for an added check on the window queue. */
1164 /* First count the windows */
1166 count = 0;
1167 for (hwnd = GetTopWindow(hwndDesktop); hwnd != 0; hwnd = wndPtr->hwndNext)
1169 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1170 if (wndPtr->hmemTaskQ == hQueue) count++;
1172 if (!count) return TRUE;
1174 /* Now build the list of all windows */
1176 if (!(list = (HWND *)malloc( sizeof(HWND) * count ))) return FALSE;
1177 for (hwnd = GetTopWindow(hwndDesktop), pWnd = list; hwnd != 0; hwnd = wndPtr->hwndNext)
1179 wndPtr = WIN_FindWndPtr( hwnd );
1180 if (wndPtr->hmemTaskQ == hQueue) *pWnd++ = hwnd;
1183 /* Now call the callback function for every window */
1185 for (pWnd = list; count > 0; count--, pWnd++)
1187 /* Make sure that window still exists */
1188 if (!IsWindow(*pWnd)) continue;
1189 if (!CallEnumTaskWndProc( lpEnumFunc, *pWnd, lParam )) break;
1191 free( list );
1192 return TRUE;
1196 /*******************************************************************
1197 * WIN_EnumChildWin
1199 * o hwnd is the first child to use, loop until all next windows
1200 * are processed
1202 * o call wdnenumprc
1204 * o call ourselves with the next child window
1207 static BOOL WIN_EnumChildWin(HWND hwnd, FARPROC wndenumprc, LPARAM lParam)
1209 WND *wndPtr;
1211 while (hwnd)
1213 if (!(wndPtr=WIN_FindWndPtr(hwnd))) return 0;
1214 if (!CallEnumWindowsProc( wndenumprc, hwnd, lParam )) return 0;
1215 if (!WIN_EnumChildWin(wndPtr->hwndChild, wndenumprc, lParam)) return 0;
1216 hwnd=wndPtr->hwndNext;
1218 return 1;
1221 /*******************************************************************
1222 * EnumChildWindows (USER.55)
1224 * o gets the first child of hwnd
1226 * o calls WIN_EnumChildWin to do a recursive decent of child windows
1228 BOOL EnumChildWindows(HWND hwnd, WNDENUMPROC wndenumprc, LPARAM lParam)
1230 WND *wndPtr;
1232 dprintf_enum(stddeb,"EnumChildWindows\n");
1234 if (hwnd == 0) return 0;
1235 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
1236 hwnd = wndPtr->hwndChild;
1237 return WIN_EnumChildWin(hwnd, wndenumprc, lParam);
1241 /*******************************************************************
1242 * AnyPopup [USER.52]
1244 BOOL AnyPopup()
1246 WND *wndPtr = WIN_FindWndPtr(hwndDesktop);
1247 HWND hwnd = wndPtr->hwndChild;
1249 for( ; hwnd ; hwnd = wndPtr->hwndNext )
1251 wndPtr = WIN_FindWndPtr(hwnd);
1252 if(wndPtr->hwndOwner)
1253 if(wndPtr->dwStyle & WS_VISIBLE)
1254 return TRUE;
1256 return FALSE;
1259 /*******************************************************************
1260 * FlashWindow [USER.105]
1262 BOOL FlashWindow(HWND hWnd, BOOL bInvert)
1264 WND *wndPtr = WIN_FindWndPtr(hWnd);
1266 dprintf_win(stddeb,"FlashWindow: "NPFMT"\n", hWnd);
1268 if (!wndPtr) return FALSE;
1270 if (wndPtr->dwStyle & WS_MINIMIZE)
1272 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
1274 HDC hDC = GetDC(hWnd);
1276 if (!SendMessage( hWnd, WM_ERASEBKGND, (WPARAM)hDC, (LPARAM)0 ))
1277 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
1279 ReleaseDC( hWnd, hDC );
1280 wndPtr->flags |= WIN_NCACTIVATED;
1282 else
1284 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
1285 RDW_UPDATENOW | RDW_FRAME );
1286 wndPtr->flags &= ~WIN_NCACTIVATED;
1288 return TRUE;
1290 else
1292 WPARAM wparam;
1293 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
1294 else wparam = (hWnd == GetActiveWindow());
1296 SendMessage( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
1297 return wparam;
1302 /*******************************************************************
1303 * SetSysModalWindow [USER.188]
1305 HWND SetSysModalWindow(HWND hWnd)
1307 HWND hWndOldModal = hwndSysModal;
1308 hwndSysModal = hWnd;
1309 dprintf_win(stdnimp,"EMPTY STUB !! SetSysModalWindow("NPFMT") !\n", hWnd);
1310 return hWndOldModal;
1314 /*******************************************************************
1315 * GetSysModalWindow [USER.189]
1317 HWND GetSysModalWindow(void)
1319 return hwndSysModal;
1322 /*******************************************************************
1323 * DRAG_QueryUpdate
1325 * recursively find a child that contains spDragInfo->pt point
1326 * and send WM_QUERYDROPOBJECT
1328 BOOL DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo )
1330 HWND hWnd;
1331 BOOL wParam,bResult = 0;
1332 POINT pt;
1333 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
1334 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
1335 RECT tempRect; /* this sucks */
1337 if( !ptrQueryWnd || !ptrDragInfo ) return 0;
1339 pt = ptrDragInfo->pt;
1341 GetWindowRect(hQueryWnd,&tempRect);
1343 if( !PtInRect(&tempRect,pt) ||
1344 (ptrQueryWnd->dwStyle & WS_DISABLED) )
1345 return 0;
1347 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
1349 tempRect = ptrQueryWnd->rectClient;
1350 if(ptrQueryWnd->dwStyle & WS_CHILD)
1351 MapWindowPoints(ptrQueryWnd->hwndParent,0,(LPPOINT)&tempRect,2);
1353 if( PtInRect(&tempRect,pt) )
1355 wParam = 0;
1356 ptrWnd = WIN_FindWndPtr(hWnd = ptrQueryWnd->hwndChild);
1358 for( ;ptrWnd ;ptrWnd = WIN_FindWndPtr(hWnd = ptrWnd->hwndNext) )
1359 if( ptrWnd->dwStyle & WS_VISIBLE )
1361 GetWindowRect(hWnd,&tempRect);
1363 if( PtInRect(&tempRect,pt) )
1364 break;
1367 if(ptrWnd)
1368 dprintf_msg(stddeb,"DragQueryUpdate: hwnd = "NPFMT", %i %i - %i %i\n",hWnd,
1369 (int)ptrWnd->rectWindow.left,(int)ptrWnd->rectWindow.top,
1370 (int)ptrWnd->rectWindow.right,(int)ptrWnd->rectWindow.bottom);
1371 else
1372 dprintf_msg(stddeb,"DragQueryUpdate: hwnd = "NPFMT"\n",hWnd);
1374 if(ptrWnd)
1375 if( !(ptrWnd->dwStyle & WS_DISABLED) )
1376 bResult = DRAG_QueryUpdate(hWnd, spDragInfo);
1378 if(bResult) return bResult;
1380 else wParam = 1;
1382 else wParam = 1;
1384 ScreenToClient(hQueryWnd,&ptrDragInfo->pt);
1386 ptrDragInfo->hScope = hQueryWnd;
1388 bResult = SendMessage( hQueryWnd ,WM_QUERYDROPOBJECT ,
1389 (WPARAM)wParam ,(LPARAM) spDragInfo );
1390 if( !bResult )
1391 ptrDragInfo->pt = pt;
1393 return bResult;
1396 /*******************************************************************
1397 * DragDetect ( USER.465 )
1400 BOOL DragDetect(HWND hWnd, POINT pt)
1402 MSG msg;
1403 RECT rect;
1405 rect.left = pt.x - wDragWidth;
1406 rect.right = pt.x + wDragWidth;
1408 rect.top = pt.y - wDragHeight;
1409 rect.bottom = pt.y + wDragHeight;
1411 SetCapture(hWnd);
1413 while(1)
1415 while(PeekMessage(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
1417 if( msg.message == WM_LBUTTONUP )
1419 ReleaseCapture();
1420 return 0;
1422 if( msg.message == WM_MOUSEMOVE )
1424 POINT pt = { LOWORD(msg.lParam), HIWORD(msg.lParam) };
1425 if( !PtInRect( &rect, pt ) )
1427 ReleaseCapture();
1428 return 1;
1432 WaitMessage();
1435 return 0;
1438 /******************************************************************************
1439 * DragObject ( USER.464 )
1442 DWORD DragObject(HWND hwndScope, HWND hWnd, WORD wObj, HANDLE hOfStruct,
1443 WORD szList , HCURSOR hCursor)
1445 MSG msg;
1446 LPDRAGINFO lpDragInfo;
1447 SEGPTR spDragInfo;
1448 HCURSOR hDragCursor=0, hOldCursor=0, hBummer=0;
1449 HANDLE hDragInfo = GlobalAlloc( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
1450 WND *wndPtr = WIN_FindWndPtr(hWnd);
1451 DWORD dwRet = 0;
1452 short dragDone = 0;
1453 HCURSOR hCurrentCursor = 0;
1454 HWND hCurrentWnd = 0;
1455 WORD btemp;
1457 lpDragInfo = (LPDRAGINFO) GlobalLock(hDragInfo);
1458 spDragInfo = (SEGPTR) WIN16_GlobalLock(hDragInfo);
1460 if( !lpDragInfo || !spDragInfo ) return 0L;
1462 hBummer = LoadCursor(0,IDC_BUMMER);
1464 if( !hBummer || !wndPtr )
1466 GlobalFree(hDragInfo);
1467 return 0L;
1470 if(hCursor)
1472 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor)) )
1474 GlobalFree(hDragInfo);
1475 return 0L;
1478 if( hDragCursor == hCursor ) hDragCursor = 0;
1479 else hCursor = hDragCursor;
1481 hOldCursor = SetCursor(hDragCursor);
1484 lpDragInfo->hWnd = hWnd;
1485 lpDragInfo->hScope = 0;
1486 lpDragInfo->wFlags = wObj;
1487 lpDragInfo->hList = szList; /* near pointer! */
1488 lpDragInfo->hOfStruct = hOfStruct;
1489 lpDragInfo->l = 0L;
1491 SetCapture(hWnd);
1492 ShowCursor(1);
1494 while( !dragDone )
1496 WaitMessage();
1498 if( !PeekMessage(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) )
1499 continue;
1501 *(lpDragInfo+1) = *lpDragInfo;
1503 lpDragInfo->pt = msg.pt;
1505 /* update DRAGINFO struct */
1506 dprintf_msg(stddeb,"drag: lpDI->hScope = "NPFMT"\n",lpDragInfo->hScope);
1508 if( (btemp = (WORD)DRAG_QueryUpdate(hwndScope, spDragInfo)) > 0 )
1509 hCurrentCursor = hCursor;
1510 else
1512 hCurrentCursor = hBummer;
1513 lpDragInfo->hScope = 0;
1515 if( hCurrentCursor )
1516 SetCursor(hCurrentCursor);
1518 dprintf_msg(stddeb,"drag: got %04x\n",btemp);
1520 /* send WM_DRAGLOOP */
1521 SendMessage( hWnd, WM_DRAGLOOP, (WPARAM)(hCurrentCursor != hBummer) ,
1522 (LPARAM) spDragInfo );
1523 /* send WM_DRAGSELECT or WM_DRAGMOVE */
1524 if( hCurrentWnd != lpDragInfo->hScope )
1526 if( hCurrentWnd )
1527 SendMessage( hCurrentWnd, WM_DRAGSELECT, 0,
1528 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
1529 HIWORD(spDragInfo)) );
1530 hCurrentWnd = lpDragInfo->hScope;
1531 if( hCurrentWnd )
1532 SendMessage( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
1534 else
1535 if( hCurrentWnd )
1536 SendMessage( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
1539 /* check if we're done */
1540 if( msg.message == WM_LBUTTONUP || msg.message == WM_NCLBUTTONUP )
1541 dragDone = TRUE;
1544 ReleaseCapture();
1545 ShowCursor(0);
1547 if( hCursor )
1549 SetCursor(hOldCursor);
1550 if( hDragCursor )
1551 DestroyCursor(hDragCursor);
1554 if( hCurrentCursor != hBummer )
1555 dwRet = SendMessage( lpDragInfo->hScope, WM_DROPOBJECT,
1556 (WPARAM)hWnd, (LPARAM)spDragInfo );
1557 GlobalFree(hDragInfo);
1559 return dwRet;