Release 960528
[wine/gsoc-2012-control.git] / windows / win.c
blobc89ef234db54c5e018cc290d70ee5860e57c7cc7
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 "heap.h"
14 #include "user.h"
15 #include "dce.h"
16 #include "sysmetrics.h"
17 #include "cursoricon.h"
18 #include "heap.h"
19 #include "hook.h"
20 #include "menu.h"
21 #include "message.h"
22 #include "nonclient.h"
23 #include "string32.h"
24 #include "queue.h"
25 #include "winpos.h"
26 #include "color.h"
27 #include "shm_main_blk.h"
28 #include "dde_proc.h"
29 #include "callback.h"
30 #include "winproc.h"
31 #include "stddebug.h"
32 /* #define DEBUG_WIN */
33 /* #define DEBUG_MENU */
34 #include "debug.h"
36 /* Desktop window */
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 /***********************************************************************
48 * WIN_FindWndPtr
50 * Return a pointer to the WND structure corresponding to a HWND.
52 WND * WIN_FindWndPtr( HWND hwnd )
54 WND * ptr;
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 );
63 return NULL;
65 return ptr;
69 /***********************************************************************
70 * WIN_DumpWindow
72 * Dump the content of a window structure to stderr.
74 void WIN_DumpWindow( HWND hwnd )
76 WND *ptr;
77 char className[80];
78 int i;
80 if (!(ptr = WIN_FindWndPtr( hwnd )))
82 fprintf( stderr, "%04x is not a window handle\n", hwnd );
83 return;
86 if (!GetClassName32A( hwnd, className, sizeof(className ) ))
87 strcpy( className, "#NULL#" );
89 fprintf( stderr, "Window %04x (%p):\n", hwnd, ptr );
90 fprintf( stderr,
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 /***********************************************************************
119 * WIN_WalkWindows
121 * Walk the windows tree and print each window on stderr.
123 void WIN_WalkWindows( HWND hwnd, int indent )
125 WND *ptr;
126 char className[80];
128 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop;
129 if (!ptr)
131 fprintf( stderr, "*** Invalid window handle\n" );
132 return;
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");
139 while (ptr)
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 );
152 ptr = ptr->next;
157 /***********************************************************************
158 * WIN_GetXWindow
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 /***********************************************************************
171 * WIN_UnlinkWindow
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;
183 return TRUE;
187 /***********************************************************************
188 * WIN_LinkWindow
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;
213 *ppWnd = wndPtr;
214 return TRUE;
218 /***********************************************************************
219 * WIN_FindWinToRepaint
221 * Find a window that needs repaint.
223 HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE hQueue )
225 HWND hwndRet;
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",
236 pWnd->hwndSelf );
237 continue;
239 if ((pWnd->hmemTaskQ == hQueue) &&
240 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))) break;
242 if (pWnd->child )
243 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
244 return hwndRet;
247 if (!pWnd) return 0;
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))))
255 pWnd = pWnd->next;
257 if (pWnd) hwndRet = pWnd->hwndSelf;
258 dprintf_win(stddeb,"FindWinToRepaint: found %04x\n",hwndRet);
259 return 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);
279 #ifndef WINELIB32
280 else lValue = MAKELONG( LOWORD(lValue), idChild );
281 #endif
283 while (wndPtr)
285 if ((wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) ||
286 !(wndPtr->dwStyle & WS_CHILD)) break;
288 if (bMouse)
290 lppt->x += wndPtr->rectClient.left;
291 lppt->y += wndPtr->rectClient.top;
294 wndPtr = wndPtr->parent;
295 #ifdef WINELIB32
296 SendMessage32A( wndPtr->hwndSelf, WM_PARENTNOTIFY,
297 MAKEWPARAM( event, idChild ), lValue );
298 #else
299 SendMessage16( wndPtr->hwndSelf, WM_PARENTNOTIFY, event, (LPARAM)lValue);
300 #endif
305 /***********************************************************************
306 * WIN_SetWndProc
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 );
316 return oldProc;
320 /***********************************************************************
321 * WIN_DestroyWindow
323 * Destroy storage associated to a window
325 static void WIN_DestroyWindow( HWND hwnd )
327 WND *wndPtr = WIN_FindWndPtr( hwnd );
329 #ifdef CONFIG_IPC
330 if (main_block)
331 DDE_DestroyWindow(hwnd);
332 #endif /* CONFIG_IPC */
334 if (!wndPtr) return;
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 )
362 WND* next;
364 while (wnd)
366 next = wnd->next;
367 if (wnd->hmemTaskQ == hQueue) DestroyWindow( wnd->hwndSelf );
368 else WIN_DestroyQueueWindows( wnd->child, hQueue );
369 wnd = next;
374 /***********************************************************************
375 * WIN_CreateDesktopWindow
377 * Create the desktop window.
379 BOOL WIN_CreateDesktopWindow(void)
381 CLASS *class;
382 HDC hdc;
383 HWND hwndDesktop;
385 if (!(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
386 return FALSE;
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 |
416 WS_CLIPSIBLINGS;
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 );
435 return TRUE;
439 /***********************************************************************
440 * WIN_CreateWindowEx
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 )
448 CLASS *classPtr;
449 WND *wndPtr;
450 HWND16 hwnd;
451 POINT16 maxSize, maxPos, minTrack, maxTrack;
453 /* Find the parent window */
455 if (parent)
457 /* Make sure parent is valid */
458 if (!IsWindow( parent ))
460 fprintf( stderr, "CreateWindowEx: bad parent %04x\n", parent );
461 return 0;
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) )))
474 char buffer[256];
475 GlobalGetAtomName32A( classAtom, buffer, sizeof(buffer) );
476 fprintf( stderr, "CreateWindowEx: bad class '%s'\n", buffer );
477 return 0;
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;
486 else */
488 width = 600;
489 height = 400;
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" );
499 return 0;
502 /* Fill the window structure */
504 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
505 wndPtr->next = NULL;
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));
509 wndPtr->window = 0;
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;
518 wndPtr->text = NULL;
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;
525 wndPtr->wIDmenu = 0;
526 wndPtr->flags = 0;
527 wndPtr->hVScroll = 0;
528 wndPtr->hHScroll = 0;
529 wndPtr->hSysMenu = MENU_GetDefSysMenu();
530 wndPtr->hProp = 0;
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;
595 else
597 win_attr.event_mask = ExposureMask | KeyPressMask |
598 KeyReleaseMask | PointerMotionMask |
599 ButtonPressMask | ButtonReleaseMask |
600 FocusChangeMask;
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",
614 False );
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);
629 else
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 );
636 #else
637 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
638 if (menuName) menu = LoadMenu( instance, menuName );
639 #endif
641 if (menu) SetMenu( hwnd, menu );
643 else wndPtr->wIDmenu = (UINT)menu;
645 return hwnd;
649 /***********************************************************************
650 * WIN_FinalWindowInit
652 static HWND WIN_FinalWindowInit( WND *wndPtr, DWORD style )
654 if (!(wndPtr->flags & WIN_NEED_SIZE))
656 /* send it anyway */
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,
676 SWP_FRAMECHANGED |
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 )
720 ATOM classAtom;
721 HWND16 hwnd;
722 WND *wndPtr;
723 LRESULT wmcreate;
725 dprintf_win( stddeb, "CreateWindowEx: " );
726 if (HIWORD(windowName))
727 dprintf_win( stddeb, "'%s' ", (char *)PTR_SEG_TO_LIN(windowName) );
728 else
729 dprintf_win( stddeb, "%04x ", LOWORD(windowName) );
730 if (HIWORD(className))
731 dprintf_win( stddeb, "'%s' ", (char *)PTR_SEG_TO_LIN(className) );
732 else
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) );
746 return 0;
749 hwnd = WIN_CreateWindowEx( exStyle, classAtom, style, x, y, width, height,
750 parent, menu, instance );
751 if (!hwnd) return 0;
752 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
754 /* Send the WM_CREATE message */
756 #ifndef WINELIB
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 ) ))
770 wmcreate = -1;
771 else
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 */
787 #endif /* WINELIB */
789 CREATESTRUCT32A cs;
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;
804 else
806 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
807 NULL, NULL, 0, &wndPtr->rectClient );
808 wmcreate = SendMessage32A( hwnd, WM_CREATE, 0, (LPARAM)&cs );
812 if (wmcreate == -1)
814 /* Abort window creation */
815 dprintf_win(stddeb,"CreateWindowEx: wmcreate==-1, aborting\n");
816 WIN_DestroyWindow( hwnd );
817 return 0;
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 )
833 ATOM classAtom;
834 HWND16 hwnd;
835 WND *wndPtr;
836 LRESULT wmcreate;
837 CREATESTRUCT32A cs;
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 );
846 return 0;
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 );
858 if (!hwnd) return 0;
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;
877 else
879 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
880 NULL, NULL, 0, &wndPtr->rectClient );
881 wmcreate = SendMessage32A( hwnd, WM_CREATE, 0, (LPARAM)&cs );
884 if (wmcreate == -1)
886 /* Abort window creation */
887 dprintf_win(stddeb,"CreateWindowEx32A: wmcreate==-1, aborting\n");
888 WIN_DestroyWindow( hwnd );
889 return 0;
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 )
905 ATOM classAtom;
906 HWND16 hwnd;
907 WND *wndPtr;
908 LRESULT wmcreate;
909 CREATESTRUCT32W cs;
911 /* Find the class atom */
913 if (!(classAtom = GlobalFindAtom32W( className )))
915 fprintf( stderr, "CreateWindowEx32W: bad class name %p\n", className );
916 return 0;
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 );
928 if (!hwnd) return 0;
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;
947 else
949 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
950 NULL, NULL, 0, &wndPtr->rectClient );
951 wmcreate = SendMessage32W( hwnd, WM_CREATE, 0, (LPARAM)&cs );
954 if (wmcreate == -1)
956 /* Abort window creation */
957 dprintf_win(stddeb,"CreateWindowEx32W: wmcreate==-1, aborting\n");
958 WIN_DestroyWindow( hwnd );
959 return 0;
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 )
972 WND * wndPtr;
974 dprintf_win(stddeb, "DestroyWindow(%04x)\n", hwnd);
976 /* Initialization */
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() ))
995 ReleaseCapture();
996 if (!QUEUE_GetDoomedQueue())
997 WIN_SendParentNotify( hwnd, WM_DESTROY, wndPtr->wIDmenu, (LONG)hwnd );
999 /* Recursively destroy owned windows */
1001 for (;;)
1003 WND *siblingPtr = wndPtr->parent->child; /* First sibling */
1004 while (siblingPtr)
1006 if (siblingPtr->owner == wndPtr) break;
1007 siblingPtr = siblingPtr->next;
1009 if (siblingPtr) DestroyWindow( siblingPtr->hwndSelf );
1010 else break;
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 );
1023 return TRUE;
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);
1035 return TRUE;
1039 /***********************************************************************
1040 * OpenIcon (USER.44)
1042 BOOL OpenIcon(HWND hWnd)
1044 if (!IsIconic(hWnd)) return FALSE;
1045 ShowWindow(hWnd, SW_SHOWNORMAL);
1046 return(TRUE);
1050 /***********************************************************************
1051 * WIN_FindWindow
1053 * Implementation of FindWindow() and FindWindowEx().
1055 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1056 LPCSTR title )
1058 WND *pWnd;
1059 CLASS *pClass = NULL;
1061 if (child)
1063 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1064 if (parent)
1066 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent)) return 0;
1068 else if (pWnd->parent != pWndDesktop) return 0;
1069 pWnd = pWnd->next;
1071 else
1073 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : pWndDesktop)) return 0;
1074 pWnd = pWnd->child;
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 )))
1084 return 0;
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;
1102 return 0;
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 )
1121 ATOM atom;
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 )
1142 ATOM atom;
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)
1154 ATOM atom;
1155 char *buffer;
1156 HWND hwnd;
1158 atom = className ? GlobalFindAtom32W( className ) : 0;
1159 buffer = STRING32_DupUniToAnsi( title );
1160 hwnd = WIN_FindWindow( 0, 0, atom, buffer );
1161 free( buffer );
1162 return hwnd;
1166 /***********************************************************************
1167 * FindWindow32W (USER32.200)
1169 HWND FindWindow32W( LPCWSTR className, LPCWSTR title )
1171 return FindWindowEx32W( 0, 0, className, title );
1175 /**********************************************************************
1176 * WIN_GetDesktop
1178 WND *WIN_GetDesktop(void)
1180 return pWndDesktop;
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 )
1210 WND *wndPtr;
1212 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1213 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1215 /* Enable window */
1216 wndPtr->dwStyle &= ~WS_DISABLED;
1217 SendMessage16( hwnd, WM_ENABLE, TRUE, 0 );
1218 return TRUE;
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 );
1229 return FALSE;
1231 return ((wndPtr->dwStyle & WS_DISABLED) != 0);
1235 /***********************************************************************
1236 * IsWindowEnabled (USER.35) (USER32.348)
1238 BOOL IsWindowEnabled(HWND hWnd)
1240 WND * wndPtr;
1242 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1243 return !(wndPtr->dwStyle & WS_DISABLED);
1247 /***********************************************************************
1248 * IsWindowUnicode (USER32.349)
1250 BOOL IsWindowUnicode( HWND hwnd )
1252 WND * wndPtr;
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);
1267 switch(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;
1272 default:
1273 fprintf( stderr, "GetWindowWord: invalid offset %d\n", offset );
1274 return 0;
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 )
1295 WORD *ptr, retval;
1296 WND * wndPtr = WIN_FindWndPtr( hwnd );
1297 if (!wndPtr) return 0;
1298 if (offset >= 0) ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1299 else switch(offset)
1301 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1302 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1303 default:
1304 fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
1305 return 0;
1307 retval = *ptr;
1308 *ptr = newval;
1309 return retval;
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);
1321 switch(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;
1331 default:
1332 fprintf( stderr, "GetWindowLong: unknown offset %d\n", offset );
1334 return 0;
1338 /**********************************************************************
1339 * SetWindowLong16 (USER.136)
1341 LONG SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1343 WND *wndPtr;
1344 switch(offset)
1346 case GWL_WNDPROC:
1347 wndPtr = WIN_FindWndPtr( hwnd );
1348 return (LONG)WIN_SetWndProc( wndPtr, (WNDPROC16)newval, WIN_PROC_16 );
1349 default:
1350 return SetWindowLong32A( hwnd, offset, newval );
1355 /**********************************************************************
1356 * SetWindowLong32A (USER32.516)
1358 LONG SetWindowLong32A( HWND32 hwnd, INT32 offset, LONG newval )
1360 LONG *ptr, retval;
1361 WND * wndPtr = WIN_FindWndPtr( hwnd );
1362 if (!wndPtr) return 0;
1363 if (offset >= 0) ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1364 else switch(offset)
1366 case GWL_ID:
1367 case GWL_HINSTANCE:
1368 return SetWindowWord( hwnd, offset, (WORD)newval );
1369 case GWL_WNDPROC:
1370 return (LONG)WIN_SetWndProc( wndPtr, (WNDPROC16)newval,
1371 WIN_PROC_32A );
1372 case GWL_USERDATA: return 0;
1373 case GWL_STYLE: ptr = &wndPtr->dwStyle; break;
1374 case GWL_EXSTYLE: ptr = &wndPtr->dwExStyle; break;
1375 default:
1376 fprintf( stderr, "SetWindowLong: invalid offset %d\n", offset );
1377 return 0;
1379 retval = *ptr;
1380 *ptr = newval;
1381 return retval;
1385 /**********************************************************************
1386 * SetWindowLong32W (USER32.517)
1388 LONG SetWindowLong32W( HWND32 hwnd, INT32 offset, LONG newval )
1390 WND *wndPtr;
1391 switch(offset)
1393 case GWL_WNDPROC:
1394 wndPtr = WIN_FindWndPtr( hwnd );
1395 return (LONG)WIN_SetWndProc( wndPtr, (WNDPROC16)newval, WIN_PROC_32W );
1396 default:
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,
1417 (LPARAM)lpString );
1421 /*******************************************************************
1422 * GetWindowText32W (USER32.311)
1424 INT32 GetWindowText32W( HWND32 hwnd, LPWSTR lpString, INT32 nMaxCount )
1426 return (INT32)SendMessage32W( hwnd, WM_GETTEXT, nMaxCount,
1427 (LPARAM)lpString );
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 /*****************************************************************
1490 * WIN_GetTopParent
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)
1507 HWND oldParent;
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);
1521 return oldParent;
1526 /*******************************************************************
1527 * IsChild (USER.48)
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;
1537 return FALSE;
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;
1564 else return 0;
1568 /*******************************************************************
1569 * GetWindow (USER.262)
1571 HWND GetWindow( HWND hwnd, WORD rel )
1573 WND * wndPtr = WIN_FindWndPtr( hwnd );
1574 if (!wndPtr) return 0;
1575 switch(rel)
1577 case GW_HWNDFIRST:
1578 if (wndPtr->parent) return wndPtr->parent->child->hwndSelf;
1579 else return 0;
1581 case GW_HWNDLAST:
1582 if (!wndPtr->parent) return 0; /* Desktop window */
1583 while (wndPtr->next) wndPtr = wndPtr->next;
1584 return wndPtr->hwndSelf;
1586 case GW_HWNDNEXT:
1587 if (!wndPtr->next) return 0;
1588 return wndPtr->next->hwndSelf;
1590 case GW_HWNDPREV:
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;
1599 return 0;
1601 case GW_OWNER:
1602 return wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
1604 case GW_CHILD:
1605 return wndPtr->child ? wndPtr->child->hwndSelf : 0;
1607 return 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;
1626 while (pWnd)
1628 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
1629 (pWnd->dwStyle & WS_POPUP))
1630 ShowWindow( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
1631 pWnd = pWnd->next;
1636 /*******************************************************************
1637 * GetLastActivePopup (USER.287)
1639 HWND GetLastActivePopup(HWND hwnd)
1641 WND *wndPtr;
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 )
1653 WND *wndPtr;
1654 HWND *list, *pWnd;
1655 int count;
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 */
1663 count = 0;
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;
1681 free( list );
1682 return TRUE;
1686 /**********************************************************************
1687 * EnumTaskWindows (USER.225)
1689 BOOL EnumTaskWindows( HTASK hTask, WNDENUMPROC lpEnumFunc, LPARAM lParam )
1691 WND *wndPtr;
1692 HWND *list, *pWnd;
1693 HANDLE hQueue = GetTaskQueue( hTask );
1694 int count;
1696 /* This function is the same as EnumWindows(), */
1697 /* except for an added check on the window queue. */
1699 /* First count the windows */
1701 count = 0;
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;
1720 free( list );
1721 return TRUE;
1725 /*******************************************************************
1726 * WIN_EnumChildWin
1728 * o hwnd is the first child to use, loop until all next windows
1729 * are processed
1731 * o call wdnenumprc
1733 * o call ourselves with the next child window
1736 static BOOL WIN_EnumChildWin( WND *wndPtr, FARPROC wndenumprc, LPARAM lParam )
1738 WND *pWndNext, *pWndChild;
1739 while (wndPtr)
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 ))
1744 return 0;
1745 if (pWndChild && IsWindow(pWndChild->hwndSelf))
1746 if (!WIN_EnumChildWin(pWndChild, wndenumprc, lParam)) return 0;
1747 wndPtr = pWndNext;
1749 return 1;
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)
1762 WND *wndPtr;
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)
1775 BOOL AnyPopup(void)
1777 WND *wndPtr;
1778 for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next)
1779 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE)) return TRUE;
1780 return FALSE;
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;
1806 else
1808 RedrawWindow32( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
1809 RDW_UPDATENOW | RDW_FRAME );
1810 wndPtr->flags &= ~WIN_NCACTIVATED;
1812 return TRUE;
1814 else
1816 WPARAM wparam;
1817 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
1818 else wparam = (hWnd == GetActiveWindow());
1820 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
1821 return wparam;
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 /*******************************************************************
1847 * DRAG_QueryUpdate
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;
1855 POINT16 pt;
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) )
1868 return 0;
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) )
1878 wParam = 0;
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) )
1886 break;
1889 if(ptrWnd)
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;
1900 else wParam = 1;
1902 else wParam = 1;
1904 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
1906 ptrDragInfo->hScope = hQueryWnd;
1908 bResult = SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
1909 (WPARAM)wParam ,(LPARAM) spDragInfo );
1910 if( !bResult )
1911 ptrDragInfo->pt = pt;
1913 return bResult;
1916 /*******************************************************************
1917 * DragDetect ( USER.465 )
1920 BOOL16 DragDetect(HWND16 hWnd, POINT16 pt)
1922 MSG msg;
1923 RECT16 rect;
1925 rect.left = pt.x - wDragWidth;
1926 rect.right = pt.x + wDragWidth;
1928 rect.top = pt.y - wDragHeight;
1929 rect.bottom = pt.y + wDragHeight;
1931 SetCapture(hWnd);
1933 while(1)
1935 while(PeekMessage(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
1937 if( msg.message == WM_LBUTTONUP )
1939 ReleaseCapture();
1940 return 0;
1942 if( msg.message == WM_MOUSEMOVE )
1944 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
1946 ReleaseCapture();
1947 return 1;
1951 WaitMessage();
1954 return 0;
1957 /******************************************************************************
1958 * DragObject ( USER.464 )
1961 DWORD DragObject(HWND hwndScope, HWND hWnd, WORD wObj, HANDLE hOfStruct,
1962 WORD szList , HCURSOR hCursor)
1964 MSG msg;
1965 LPDRAGINFO lpDragInfo;
1966 SEGPTR spDragInfo;
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);
1970 DWORD dwRet = 0;
1971 short dragDone = 0;
1972 HCURSOR hCurrentCursor = 0;
1973 HWND hCurrentWnd = 0;
1974 WORD btemp;
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);
1986 return 0L;
1989 if(hCursor)
1991 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor)) )
1993 GlobalFree16(hDragInfo);
1994 return 0L;
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;
2008 lpDragInfo->l = 0L;
2010 SetCapture(hWnd);
2011 ShowCursor(1);
2013 while( !dragDone )
2015 WaitMessage();
2017 if( !PeekMessage(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) )
2018 continue;
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;
2029 else
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 )
2045 if( hCurrentWnd )
2046 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
2047 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
2048 HIWORD(spDragInfo)) );
2049 hCurrentWnd = lpDragInfo->hScope;
2050 if( hCurrentWnd )
2051 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
2053 else
2054 if( hCurrentWnd )
2055 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
2058 /* check if we're done */
2059 if( msg.message == WM_LBUTTONUP || msg.message == WM_NCLBUTTONUP )
2060 dragDone = TRUE;
2063 ReleaseCapture();
2064 ShowCursor(0);
2066 if( hCursor )
2068 SetCursor(hOldCursor);
2069 if( hDragCursor )
2070 DestroyCursor(hDragCursor);
2073 if( hCurrentCursor != hBummer )
2074 dwRet = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
2075 (WPARAM)hWnd, (LPARAM)spDragInfo );
2076 GlobalFree16(hDragInfo);
2078 return dwRet;