2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
11 #include "wine/winbase16.h"
12 #include "wine/winuser16.h"
13 #include "wine/server.h"
14 #include "wine/unicode.h"
20 #include "cursoricon.h"
27 #include "stackframe.h"
28 #include "debugtools.h"
30 DEFAULT_DEBUG_CHANNEL(win);
31 DECLARE_DEBUG_CHANNEL(msg);
33 #define NB_USER_HANDLES (LAST_USER_HANDLE - FIRST_USER_HANDLE + 1)
35 /**********************************************************************/
38 static WND *pWndDesktop = NULL;
40 static WORD wDragWidth = 4;
41 static WORD wDragHeight= 3;
43 static void *user_handles[NB_USER_HANDLES];
46 extern SYSLEVEL USER_SysLevel; /* FIXME */
48 /***********************************************************************
51 * Suspend the lock on WND structures.
52 * Returns the number of locks suspended
54 int WIN_SuspendWndsLock( void )
56 int isuspendedLocks = _ConfirmSysLevel( &USER_SysLevel );
57 int count = isuspendedLocks;
60 _LeaveSysLevel( &USER_SysLevel );
62 return isuspendedLocks;
65 /***********************************************************************
68 * Restore the suspended locks on WND structures
70 void WIN_RestoreWndsLock( int ipreviousLocks )
72 while ( ipreviousLocks-- > 0 )
73 _EnterSysLevel( &USER_SysLevel );
76 /***********************************************************************
77 * create_window_handle
79 * Create a window handle with the server.
81 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom, INT size )
84 user_handle_t handle = 0;
86 WND *win = HeapAlloc( GetProcessHeap(), 0, size );
88 if (!win) return NULL;
92 SERVER_START_REQ( create_window )
97 if ((res = !SERVER_CALL_ERR())) handle = req->handle;
104 HeapFree( GetProcessHeap(), 0, win );
107 index = LOWORD(handle) - FIRST_USER_HANDLE;
108 assert( index < NB_USER_HANDLES );
109 user_handles[index] = win;
110 win->hwndSelf = handle;
111 win->dwMagic = WND_MAGIC;
117 /***********************************************************************
120 * Free a window handle.
122 static WND *free_window_handle( HWND hwnd )
125 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
127 if (index >= NB_USER_HANDLES) return NULL;
129 if ((ptr = user_handles[index]))
131 SERVER_START_REQ( destroy_window )
134 if (!SERVER_CALL_ERR())
135 user_handles[index] = NULL;
142 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
147 /*******************************************************************
148 * list_window_children
150 * Build an array of the children of a given window. The array must be
151 * freed with HeapFree. Returns NULL when no windows are found.
153 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
157 SERVER_START_VAR_REQ( get_window_children, REQUEST_MAX_VAR_SIZE )
161 req->tid = (void *)tid;
164 user_handle_t *data = server_data_ptr(req);
165 int i, count = server_data_size(req) / sizeof(*data);
166 if (count && ((list = HeapAlloc( GetProcessHeap(), 0, (count + 1) * sizeof(HWND) ))))
168 for (i = 0; i < count; i++) list[i] = data[i];
178 /*******************************************************************
181 static void send_parent_notify( HWND hwnd, UINT msg )
183 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) return;
184 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) return;
185 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
186 MAKEWPARAM( msg, GetWindowLongW( hwnd, GWL_ID )), (LPARAM)hwnd );
190 /***********************************************************************
193 * Return a pointer to the WND structure if local to the process,
194 * or WND_OTHER_PROCESS is handle may be valid in other process.
195 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
197 WND *WIN_GetPtr( HWND hwnd )
200 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
202 if (index >= NB_USER_HANDLES) return NULL;
205 if ((ptr = user_handles[index]))
207 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
211 else ptr = WND_OTHER_PROCESS;
217 /***********************************************************************
218 * WIN_IsCurrentProcess
220 * Check whether a given window belongs to the current process (and return the full handle).
222 HWND WIN_IsCurrentProcess( HWND hwnd )
227 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
229 WIN_ReleasePtr( ptr );
234 /***********************************************************************
235 * WIN_IsCurrentThread
237 * Check whether a given window belongs to the current thread (and return the full handle).
239 HWND WIN_IsCurrentThread( HWND hwnd )
244 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
246 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
247 WIN_ReleasePtr( ptr );
253 /***********************************************************************
256 * Convert a 16-bit window handle to a full 32-bit handle.
258 HWND WIN_Handle32( HWND16 hwnd16 )
261 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
263 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
264 /* do sign extension for -2 and -3 */
265 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
267 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
269 if (ptr != WND_OTHER_PROCESS)
271 hwnd = ptr->hwndSelf;
272 WIN_ReleasePtr( ptr );
274 else /* may belong to another process */
276 SERVER_START_REQ( get_window_info )
279 if (!SERVER_CALL_ERR()) hwnd = req->full_handle;
287 /***********************************************************************
290 * Return a pointer to the WND structure corresponding to a HWND.
292 WND * WIN_FindWndPtr( HWND hwnd )
296 if (!hwnd) return NULL;
298 if ((ptr = WIN_GetPtr( hwnd )))
300 if (ptr != WND_OTHER_PROCESS)
302 /* increment destruction monitoring */
306 if (IsWindow( hwnd )) /* check other processes */
308 ERR( "window %04x belongs to other process\n", hwnd );
309 /* DbgBreakPoint(); */
312 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
317 /***********************************************************************
320 * Release the pointer to the WND structure.
322 void WIN_ReleaseWndPtr(WND *wndPtr)
326 /*Decrement destruction monitoring value*/
328 /* Check if it's time to release the memory*/
329 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
332 free_window_handle( wndPtr->hwndSelf );
334 else if(wndPtr->irefCount < 0)
336 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
337 ERR("forgot a Lock on %p somewhere\n",wndPtr);
339 /*unlock all WND structures for thread safeness*/
344 /***********************************************************************
347 * Remove a window from the siblings linked list.
349 void WIN_UnlinkWindow( HWND hwnd )
351 WIN_LinkWindow( hwnd, 0, 0 );
355 /***********************************************************************
358 * Insert a window into the siblings linked list.
359 * The window is inserted after the specified window, which can also
360 * be specified as HWND_TOP or HWND_BOTTOM.
361 * If parent is 0, window is unlinked from the tree.
363 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
366 WND *wndPtr = WIN_GetPtr( hwnd );
369 if (wndPtr == WND_OTHER_PROCESS)
371 if (IsWindow(hwnd)) ERR(" cannot link other process window %x\n", hwnd );
375 SERVER_START_REQ( link_window )
378 req->parent = parent;
379 req->previous = hwndInsertAfter;
380 ret = !SERVER_CALL_ERR();
383 if (ret && parent) wndPtr->parent = WIN_GetFullHandle(parent);
384 WIN_ReleasePtr( wndPtr );
388 /***********************************************************************
391 * Change the owner of a window.
393 void WIN_SetOwner( HWND hwnd, HWND owner )
395 WND *win = WIN_FindWndPtr( hwnd );
399 WIN_ReleaseWndPtr( win );
404 /***********************************************************************
407 * Set the window and client rectangles.
409 void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient )
411 WND *win = WIN_GetPtr( hwnd );
415 if (win == WND_OTHER_PROCESS)
417 if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %x\n", hwnd );
420 SERVER_START_REQ( set_window_rectangles )
423 req->window.left = rectWindow->left;
424 req->window.top = rectWindow->top;
425 req->window.right = rectWindow->right;
426 req->window.bottom = rectWindow->bottom;
427 req->client.left = rectClient->left;
428 req->client.top = rectClient->top;
429 req->client.right = rectClient->right;
430 req->client.bottom = rectClient->bottom;
431 ret = !SERVER_CALL();
436 win->rectWindow = *rectWindow;
437 win->rectClient = *rectClient;
439 TRACE( "win %x window (%d,%d)-(%d,%d) client (%d,%d)-(%d,%d)\n", hwnd,
440 rectWindow->left, rectWindow->top, rectWindow->right, rectWindow->bottom,
441 rectClient->left, rectClient->top, rectClient->right, rectClient->bottom );
443 WIN_ReleasePtr( win );
447 /***********************************************************************
448 * find_child_to_repaint
450 * Find a window that needs repaint among the children of the specified window.
452 static HWND find_child_to_repaint( HWND parent )
458 if (!parent) parent = GetDesktopWindow();
459 if (!(list = list_window_children( parent, 0, 0 ))) return 0;
461 for (i = 0; list[i] && !ret; i++)
463 WND *win = WIN_GetPtr( list[i] );
464 if (!win) continue; /* ignore it */
465 if (win == WND_OTHER_PROCESS)
467 /* doesn't belong to this process, but check children */
468 ret = find_child_to_repaint( list[i] );
471 if (!(win->dwStyle & WS_VISIBLE))
473 WIN_ReleasePtr( win );
476 if ((win->tid != GetCurrentThreadId()) ||
477 (!win->hrgnUpdate && !(win->flags & WIN_INTERNAL_PAINT)))
479 /* does not need repaint, check children */
480 WIN_ReleasePtr( win );
481 ret = find_child_to_repaint( list[i] );
485 /* now we have something */
487 if (!(win->dwExStyle & WS_EX_TRANSPARENT))
489 /* not transparent, we can repaint it */
490 WIN_ReleasePtr( win );
493 WIN_ReleasePtr( win );
495 /* transparent window, look for non-transparent sibling to paint first */
496 for (i++; list[i]; i++)
498 if (!(win = WIN_GetPtr( list[i] ))) continue;
499 if (win == WND_OTHER_PROCESS) continue;
500 if (!(win->dwStyle & WS_VISIBLE))
502 WIN_ReleasePtr( win );
505 if (!(win->dwExStyle & WS_EX_TRANSPARENT) &&
506 (win->hrgnUpdate || (win->flags & WIN_INTERNAL_PAINT)))
509 WIN_ReleasePtr( win );
512 WIN_ReleasePtr( win );
515 HeapFree( GetProcessHeap(), 0, list );
520 /***********************************************************************
521 * WIN_FindWinToRepaint
523 * Find a window that needs repaint.
525 HWND WIN_FindWinToRepaint( HWND hwnd )
527 /* Note: the desktop window never gets WM_PAINT messages
528 * The real reason why is because Windows DesktopWndProc
529 * does ValidateRgn inside WM_ERASEBKGND handler.
531 if (hwnd == GetDesktopWindow()) hwnd = 0;
535 /* check the window itself first */
536 WND *win = WIN_FindWndPtr( hwnd );
538 if ((win->dwStyle & WS_VISIBLE) &&
539 (win->hrgnUpdate || (win->flags & WIN_INTERNAL_PAINT)))
541 WIN_ReleaseWndPtr( win );
544 WIN_ReleaseWndPtr( win );
546 /* now check its children */
547 return find_child_to_repaint( hwnd );
551 /***********************************************************************
554 * Destroy storage associated to a window. "Internals" p.358
556 LRESULT WIN_DestroyWindow( HWND hwnd )
561 TRACE("%04x\n", hwnd );
563 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
565 ERR( "window doesn't belong to current thread\n" );
569 /* free child windows */
570 if ((list = WIN_ListChildren( hwnd )))
573 for (i = 0; list[i]; i++)
575 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
576 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
578 HeapFree( GetProcessHeap(), 0, list );
582 * Clear the update region to make sure no WM_PAINT messages will be
583 * generated for this window while processing the WM_NCDESTROY.
585 RedrawWindow( hwnd, NULL, 0,
586 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
589 * Send the WM_NCDESTROY to the window being destroyed.
591 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
593 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
595 WINPOS_CheckInternalPos( hwnd );
596 if( hwnd == GetCapture()) ReleaseCapture();
598 /* free resources associated with the window */
600 TIMER_RemoveWindowTimers( hwnd );
602 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
603 wndPtr->hmemTaskQ = 0;
605 if (!(wndPtr->dwStyle & WS_CHILD))
608 DestroyMenu( wndPtr->wIDmenu );
611 if (wndPtr->hSysMenu)
613 DestroyMenu( wndPtr->hSysMenu );
614 wndPtr->hSysMenu = 0;
616 USER_Driver.pDestroyWindow( hwnd );
617 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
618 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
619 CLASS_RemoveWindow( wndPtr->class );
620 wndPtr->class = NULL;
621 wndPtr->dwMagic = 0; /* Mark it as invalid */
622 WIN_ReleaseWndPtr( wndPtr );
626 /***********************************************************************
627 * WIN_DestroyThreadWindows
629 * Destroy all children of 'wnd' owned by the current thread.
630 * Return TRUE if something was done.
632 void WIN_DestroyThreadWindows( HWND hwnd )
637 if (!(list = WIN_ListChildren( hwnd ))) return;
638 for (i = 0; list[i]; i++)
640 if (WIN_IsCurrentThread( list[i] ))
641 DestroyWindow( list[i] );
643 WIN_DestroyThreadWindows( list[i] );
645 HeapFree( GetProcessHeap(), 0, list );
648 /***********************************************************************
649 * WIN_CreateDesktopWindow
651 * Create the desktop window.
653 BOOL WIN_CreateDesktopWindow(void)
655 struct tagCLASS *class;
664 TRACE("Creating desktop window\n");
666 if (!WINPOS_CreateInternalPosAtom() ||
667 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
668 &wndExtra, &winproc, &clsStyle, &dce )))
671 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM),
672 sizeof(WND) + wndExtra - sizeof(pWndDesktop->wExtra) );
673 if (!pWndDesktop) return FALSE;
674 hwndDesktop = pWndDesktop->hwndSelf;
676 pWndDesktop->tid = 0; /* nobody owns the desktop */
677 pWndDesktop->parent = 0;
678 pWndDesktop->owner = 0;
679 pWndDesktop->class = class;
680 pWndDesktop->hInstance = 0;
681 pWndDesktop->text = NULL;
682 pWndDesktop->hmemTaskQ = 0;
683 pWndDesktop->hrgnUpdate = 0;
684 pWndDesktop->hwndLastActive = hwndDesktop;
685 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
687 pWndDesktop->dwExStyle = 0;
688 pWndDesktop->clsStyle = clsStyle;
689 pWndDesktop->dce = NULL;
690 pWndDesktop->pVScroll = NULL;
691 pWndDesktop->pHScroll = NULL;
692 pWndDesktop->wIDmenu = 0;
693 pWndDesktop->helpContext = 0;
694 pWndDesktop->flags = 0;
695 pWndDesktop->hSysMenu = 0;
696 pWndDesktop->userdata = 0;
697 pWndDesktop->winproc = winproc;
698 pWndDesktop->cbWndExtra = wndExtra;
700 cs.lpCreateParams = NULL;
706 cs.cx = GetSystemMetrics( SM_CXSCREEN );
707 cs.cy = GetSystemMetrics( SM_CYSCREEN );
708 cs.style = pWndDesktop->dwStyle;
709 cs.dwExStyle = pWndDesktop->dwExStyle;
711 cs.lpszClass = DESKTOP_CLASS_ATOM;
713 SetRect( &rect, 0, 0, cs.cx, cs.cy );
714 WIN_SetRectangles( hwndDesktop, &rect, &rect );
716 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE )) return FALSE;
718 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
719 WIN_ReleaseWndPtr( pWndDesktop );
724 /***********************************************************************
727 * Fix the coordinates - Helper for WIN_CreateWindowEx.
728 * returns default show mode in sw.
729 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
731 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
733 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
734 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
736 if (cs->style & (WS_CHILD | WS_POPUP))
738 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
739 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
741 else /* overlapped window */
745 GetStartupInfoA( &info );
747 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
749 /* Never believe Microsoft's documentation... CreateWindowEx doc says
750 * that if an overlapped window is created with WS_VISIBLE style bit
751 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
752 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
755 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
756 * 2) it does not ignore the y parameter as the docs claim; instead, it
757 * uses it as second parameter to ShowWindow() unless y is either
758 * CW_USEDEFAULT or CW_USEDEFAULT16.
760 * The fact that we didn't do 2) caused bogus windows pop up when wine
761 * was running apps that were using this obscure feature. Example -
762 * calc.exe that comes with Win98 (only Win98, it's different from
763 * the one that comes with Win95 and NT)
765 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
766 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
767 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
770 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
772 if (info.dwFlags & STARTF_USESIZE)
774 cs->cx = info.dwXSize;
775 cs->cy = info.dwYSize;
777 else /* if no other hint from the app, pick 3/4 of the screen real estate */
780 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
781 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
782 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
789 /***********************************************************************
792 * Implementation of CreateWindowEx().
794 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
795 WINDOWPROCTYPE type )
798 struct tagCLASS *classPtr;
800 HWND hwnd, hwndLinkAfter, parent, owner;
801 POINT maxSize, maxPos, minTrack, maxTrack;
807 BOOL unicode = (type == WIN_PROC_32W);
809 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%04x menu=%04x inst=%08x params=%p\n",
810 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
811 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
812 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
813 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
815 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
816 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
818 /* Find the parent window */
820 parent = GetDesktopWindow();
824 /* Make sure parent is valid */
825 if (!IsWindow( cs->hwndParent ))
827 WARN("Bad parent %04x\n", cs->hwndParent );
830 if (cs->style & WS_CHILD) parent = WIN_GetFullHandle(cs->hwndParent);
831 else owner = GetAncestor( cs->hwndParent, GA_ROOT );
833 else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP))
835 WARN("No parent for child window\n" );
836 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
839 /* Find the window class */
840 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
841 &wndExtra, &winproc, &clsStyle, &dce )))
843 WARN("Bad class '%s'\n", cs->lpszClass );
847 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
849 /* Correct the window style - stage 1
851 * These are patches that appear to affect both the style loaded into the
852 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
854 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
855 * why does the user get to set it?
858 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
859 * tested for WS_POPUP
861 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
862 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
863 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
864 cs->dwExStyle |= WS_EX_WINDOWEDGE;
866 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
868 /* Create the window structure */
870 if (!(wndPtr = create_window_handle( parent, owner, classAtom,
871 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
873 TRACE("out of memory\n" );
876 hwnd = wndPtr->hwndSelf;
878 /* Fill the window structure */
880 wndPtr->tid = GetCurrentThreadId();
881 wndPtr->owner = owner;
882 wndPtr->parent = parent;
883 wndPtr->class = classPtr;
884 wndPtr->winproc = winproc;
885 wndPtr->hInstance = cs->hInstance;
887 wndPtr->hmemTaskQ = InitThreadInput16( 0, 0 );
888 wndPtr->hrgnUpdate = 0;
890 wndPtr->hwndLastActive = hwnd;
891 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
892 wndPtr->dwExStyle = cs->dwExStyle;
893 wndPtr->clsStyle = clsStyle;
895 wndPtr->helpContext = 0;
896 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
897 wndPtr->pVScroll = NULL;
898 wndPtr->pHScroll = NULL;
899 wndPtr->userdata = 0;
900 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
901 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
902 wndPtr->cbWndExtra = wndExtra;
904 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
906 /* Call the WH_CBT hook */
908 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
909 ? HWND_BOTTOM : HWND_TOP;
911 if (HOOK_IsHooked( WH_CBT ))
917 cbtc.hwndInsertAfter = hwndLinkAfter;
918 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND,
919 (WPARAM)hwnd, (LPARAM)&cbtc)
920 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND,
921 (WPARAM)hwnd, (LPARAM)&cbtc);
924 TRACE("CBT-hook returned 0\n");
925 free_window_handle( hwnd );
926 CLASS_RemoveWindow( classPtr );
932 /* Correct the window style - stage 2 */
934 if (!(cs->style & WS_CHILD))
936 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
937 if (!(cs->style & WS_POPUP))
939 wndPtr->dwStyle |= WS_CAPTION;
940 wndPtr->flags |= WIN_NEED_SIZE;
944 /* Get class or window DC if needed */
946 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
947 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
948 else wndPtr->dce = NULL;
950 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
952 SetRect( &rect, cs->x, cs->y, cs->x + cs->cx, cs->y + cs->cy );
953 WIN_SetRectangles( hwnd, &rect, &rect );
955 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
957 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
959 WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
960 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
961 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
962 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
963 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
966 if (cs->cx < 0) cs->cx = 0;
967 if (cs->cy < 0) cs->cy = 0;
969 SetRect( &rect, cs->x, cs->y, cs->x + cs->cx, cs->y + cs->cy );
970 WIN_SetRectangles( hwnd, &rect, &rect );
972 /* Set the window menu */
974 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
976 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
979 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
982 if (HIWORD(cs->hInstance))
983 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
985 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
987 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
991 else wndPtr->wIDmenu = (UINT)cs->hMenu;
993 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
995 WARN("aborted by WM_xxCREATE!\n");
996 WIN_ReleaseWndPtr( wndPtr );
997 WIN_DestroyWindow( hwnd );
998 CLASS_RemoveWindow( classPtr );
1002 /* Notify the parent window only */
1004 send_parent_notify( hwnd, WM_CREATE );
1005 if( !IsWindow(hwnd) )
1011 if (cs->style & WS_VISIBLE)
1013 /* in case WS_VISIBLE got set in the meantime */
1014 wndPtr->dwStyle &= ~WS_VISIBLE;
1015 ShowWindow( hwnd, sw );
1018 /* Call WH_SHELL hook */
1020 if (!(wndPtr->dwStyle & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1021 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0 );
1023 TRACE("created window %04x\n", hwnd);
1025 WIN_ReleaseWndPtr(wndPtr);
1030 /***********************************************************************
1031 * CreateWindow (USER.41)
1033 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1034 DWORD style, INT16 x, INT16 y, INT16 width,
1035 INT16 height, HWND16 parent, HMENU16 menu,
1036 HINSTANCE16 instance, LPVOID data )
1038 return CreateWindowEx16( 0, className, windowName, style,
1039 x, y, width, height, parent, menu, instance, data );
1043 /***********************************************************************
1044 * CreateWindowEx (USER.452)
1046 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1047 LPCSTR windowName, DWORD style, INT16 x,
1048 INT16 y, INT16 width, INT16 height,
1049 HWND16 parent, HMENU16 menu,
1050 HINSTANCE16 instance, LPVOID data )
1056 /* Find the class atom */
1058 if (HIWORD(className))
1060 if (!(classAtom = GlobalFindAtomA( className )))
1062 ERR( "bad class name %s\n", debugres_a(className) );
1068 classAtom = LOWORD(className);
1069 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1071 ERR( "bad atom %x\n", classAtom);
1077 /* Fix the coordinates */
1079 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1080 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1081 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1082 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1084 /* Create the window */
1086 cs.lpCreateParams = data;
1087 cs.hInstance = (HINSTANCE)instance;
1088 cs.hMenu = (HMENU)menu;
1089 cs.hwndParent = WIN_Handle32( parent );
1091 cs.lpszName = windowName;
1092 cs.lpszClass = className;
1093 cs.dwExStyle = exStyle;
1095 return WIN_Handle16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1099 /***********************************************************************
1100 * CreateWindowExA (USER32.@)
1102 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1103 LPCSTR windowName, DWORD style, INT x,
1104 INT y, INT width, INT height,
1105 HWND parent, HMENU menu,
1106 HINSTANCE instance, LPVOID data )
1113 instance=GetModuleHandleA(NULL);
1115 if(exStyle & WS_EX_MDICHILD)
1116 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1118 /* Find the class atom */
1120 if (HIWORD(className))
1122 if (!(classAtom = GlobalFindAtomA( className )))
1124 ERR( "bad class name %s\n", debugres_a(className) );
1130 classAtom = LOWORD(className);
1131 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1133 ERR( "bad atom %x\n", classAtom);
1139 /* Create the window */
1141 cs.lpCreateParams = data;
1142 cs.hInstance = instance;
1144 cs.hwndParent = parent;
1150 cs.lpszName = windowName;
1151 cs.lpszClass = className;
1152 cs.dwExStyle = exStyle;
1154 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1158 /***********************************************************************
1159 * CreateWindowExW (USER32.@)
1161 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1162 LPCWSTR windowName, DWORD style, INT x,
1163 INT y, INT width, INT height,
1164 HWND parent, HMENU menu,
1165 HINSTANCE instance, LPVOID data )
1172 instance=GetModuleHandleA(NULL);
1174 if(exStyle & WS_EX_MDICHILD)
1175 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1177 /* Find the class atom */
1179 if (HIWORD(className))
1181 if (!(classAtom = GlobalFindAtomW( className )))
1183 ERR( "bad class name %s\n", debugres_w(className) );
1189 classAtom = LOWORD(className);
1190 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1192 ERR( "bad atom %x\n", classAtom);
1198 /* Create the window */
1200 cs.lpCreateParams = data;
1201 cs.hInstance = instance;
1203 cs.hwndParent = parent;
1209 cs.lpszName = windowName;
1210 cs.lpszClass = className;
1211 cs.dwExStyle = exStyle;
1213 /* Note: we rely on the fact that CREATESTRUCTA and */
1214 /* CREATESTRUCTW have the same layout. */
1215 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1219 /***********************************************************************
1220 * WIN_SendDestroyMsg
1222 static void WIN_SendDestroyMsg( HWND hwnd )
1224 if( CARET_GetHwnd() == hwnd) DestroyCaret();
1225 if (USER_Driver.pResetSelectionOwner)
1226 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1229 * Send the WM_DESTROY to the window.
1231 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1234 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1235 * make sure that the window still exists when we come back.
1242 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1244 /* start from the end (FIXME: is this needed?) */
1245 for (i = 0; pWndArray[i]; i++) ;
1249 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1251 HeapFree( GetProcessHeap(), 0, pWndArray );
1254 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1258 /***********************************************************************
1259 * DestroyWindow (USER32.@)
1261 BOOL WINAPI DestroyWindow( HWND hwnd )
1266 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1268 SetLastError( ERROR_ACCESS_DENIED );
1272 TRACE("(%04x)\n", hwnd);
1274 /* Look whether the focus is within the tree of windows we will
1278 if (h == hwnd || IsChild( hwnd, h ))
1280 HWND parent = GetAncestor( hwnd, GA_PARENT );
1281 if (parent == GetDesktopWindow()) parent = 0;
1287 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0L) ) return FALSE;
1289 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1293 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1294 send_parent_notify( hwnd, WM_DESTROY );
1296 else if (!GetWindow( hwnd, GW_OWNER ))
1298 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L );
1299 /* FIXME: clean up palette - see "Internals" p.352 */
1302 if (!IsWindow(hwnd)) return TRUE;
1304 if (USER_Driver.pResetSelectionOwner)
1305 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1307 /* Hide the window */
1309 ShowWindow( hwnd, SW_HIDE );
1310 if (!IsWindow(hwnd)) return TRUE;
1312 /* Recursively destroy owned windows */
1321 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1324 for (i = 0; list[i]; i++)
1326 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1327 if (WIN_IsCurrentThread( list[i] ))
1329 DestroyWindow( list[i] );
1333 WIN_SetOwner( list[i], 0 );
1335 HeapFree( GetProcessHeap(), 0, list );
1337 if (!got_one) break;
1340 WINPOS_ActivateOtherWindow( hwnd );
1342 if ((owner = GetWindow( hwnd, GW_OWNER )))
1344 WND *ptr = WIN_FindWndPtr( owner );
1347 if (ptr->hwndLastActive == hwnd) ptr->hwndLastActive = owner;
1348 WIN_ReleaseWndPtr( ptr );
1353 /* Send destroy messages */
1355 WIN_SendDestroyMsg( hwnd );
1356 if (!IsWindow( hwnd )) return TRUE;
1358 /* Unlink now so we won't bother with the children later on */
1360 WIN_UnlinkWindow( hwnd );
1362 /* Destroy the window storage */
1364 WIN_DestroyWindow( hwnd );
1369 /***********************************************************************
1370 * CloseWindow (USER32.@)
1372 BOOL WINAPI CloseWindow( HWND hwnd )
1374 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1375 ShowWindow( hwnd, SW_MINIMIZE );
1380 /***********************************************************************
1381 * OpenIcon (USER32.@)
1383 BOOL WINAPI OpenIcon( HWND hwnd )
1385 if (!IsIconic( hwnd )) return FALSE;
1386 ShowWindow( hwnd, SW_SHOWNORMAL );
1391 /***********************************************************************
1394 * Implementation of FindWindow() and FindWindowEx().
1396 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1401 WCHAR *buffer = NULL;
1403 if (!parent) parent = GetDesktopWindow();
1406 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1407 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1410 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1414 child = WIN_GetFullHandle( child );
1415 while (list[i] && list[i] != child) i++;
1416 if (!list[i]) goto done;
1417 i++; /* start from next window */
1424 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1431 if (list) HeapFree( GetProcessHeap(), 0, list );
1432 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1438 /***********************************************************************
1439 * FindWindowA (USER32.@)
1441 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1443 HWND ret = FindWindowExA( 0, 0, className, title );
1444 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1449 /***********************************************************************
1450 * FindWindowExA (USER32.@)
1452 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1453 LPCSTR className, LPCSTR title )
1461 /* If the atom doesn't exist, then no class */
1462 /* with this name exists either. */
1463 if (!(atom = GlobalFindAtomA( className )))
1465 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1470 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1471 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1472 HeapFree( GetProcessHeap(), 0, buffer );
1477 /***********************************************************************
1478 * FindWindowExW (USER32.@)
1480 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1481 LPCWSTR className, LPCWSTR title )
1487 /* If the atom doesn't exist, then no class */
1488 /* with this name exists either. */
1489 if (!(atom = GlobalFindAtomW( className )))
1491 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1495 return WIN_FindWindow( parent, child, atom, title );
1499 /***********************************************************************
1500 * FindWindowW (USER32.@)
1502 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1504 return FindWindowExW( 0, 0, className, title );
1508 /**********************************************************************
1509 * GetDesktopWindow (USER32.@)
1511 HWND WINAPI GetDesktopWindow(void)
1513 if (pWndDesktop) return pWndDesktop->hwndSelf;
1514 ERR( "You need the -desktop option when running with native USER\n" );
1520 /*******************************************************************
1521 * EnableWindow (USER32.@)
1523 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1528 TRACE("( %x, %d )\n", hwnd, enable);
1530 if (USER_Driver.pEnableWindow)
1531 return USER_Driver.pEnableWindow( hwnd, enable );
1533 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1534 hwnd = wndPtr->hwndSelf; /* make it a full handle */
1536 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1538 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1540 wndPtr->dwStyle &= ~WS_DISABLED; /* Enable window */
1541 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1543 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1545 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1547 wndPtr->dwStyle |= WS_DISABLED; /* Disable window */
1549 if (hwnd == GetFocus())
1550 SetFocus( 0 ); /* A disabled window can't have the focus */
1552 if (hwnd == GetCapture())
1553 ReleaseCapture(); /* A disabled window can't capture the mouse */
1555 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1557 WIN_ReleaseWndPtr(wndPtr);
1562 /***********************************************************************
1563 * IsWindowEnabled (USER32.@)
1565 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1567 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1571 /***********************************************************************
1572 * IsWindowUnicode (USER32.@)
1574 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1579 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1580 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1581 WIN_ReleaseWndPtr(wndPtr);
1586 /**********************************************************************
1587 * GetWindowWord (USER32.@)
1589 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1592 WND * wndPtr = WIN_FindWndPtr( hwnd );
1593 if (!wndPtr) return 0;
1596 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1598 WARN("Invalid offset %d\n", offset );
1601 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1602 WIN_ReleaseWndPtr(wndPtr);
1606 WIN_ReleaseWndPtr(wndPtr);
1609 case GWL_HWNDPARENT:
1610 return GetWindowLongW( hwnd, offset );
1614 LONG ret = GetWindowLongW( hwnd, offset );
1616 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1620 WARN("Invalid offset %d\n", offset );
1626 /**********************************************************************
1627 * SetWindowWord (USER32.@)
1629 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1632 WND * wndPtr = WIN_FindWndPtr( hwnd );
1633 if (!wndPtr) return 0;
1636 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1638 WARN("Invalid offset %d\n", offset );
1639 WIN_ReleaseWndPtr(wndPtr);
1642 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1645 WIN_ReleaseWndPtr(wndPtr);
1649 WIN_ReleaseWndPtr(wndPtr);
1654 case GWL_HWNDPARENT:
1655 return SetWindowLongW( hwnd, offset, (UINT)newval );
1657 WARN("Invalid offset %d\n", offset );
1663 /**********************************************************************
1666 * Helper function for GetWindowLong().
1668 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1671 WND * wndPtr = WIN_FindWndPtr( hwnd );
1672 if (!wndPtr) return 0;
1675 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1677 WARN("Invalid offset %d\n", offset );
1681 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1682 /* Special case for dialog window procedure */
1683 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1685 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1692 case GWL_USERDATA: retvalue = wndPtr->userdata;
1694 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1696 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1698 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1700 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1703 case GWL_HWNDPARENT: retvalue = (LONG)GetParent(hwnd);
1705 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1708 WARN("Unknown offset %d\n", offset );
1712 WIN_ReleaseWndPtr(wndPtr);
1717 /**********************************************************************
1720 * Helper function for SetWindowLong().
1722 * 0 is the failure code. However, in the case of failure SetLastError
1723 * must be set to distinguish between a 0 return value and a failure.
1725 * FIXME: The error values for SetLastError may not be right. Can
1726 * someone check with the real thing?
1728 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1729 WINDOWPROCTYPE type )
1732 WND * wndPtr = WIN_FindWndPtr( hwnd );
1735 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1739 /* Is this the right error? */
1740 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1746 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1748 WARN("Invalid offset %d\n", offset );
1750 /* Is this the right error? */
1751 SetLastError( ERROR_OUTOFMEMORY );
1756 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1757 /* Special case for dialog window procedure */
1758 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1760 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1761 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1762 type, WIN_PROC_WINDOW );
1769 ptr = (DWORD*)&wndPtr->wIDmenu;
1772 ptr = (DWORD*)&wndPtr->hInstance;
1775 ptr = &wndPtr->userdata;
1777 case GWL_HWNDPARENT:
1778 retval = SetParent( hwnd, (HWND)newval );
1781 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1782 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1783 type, WIN_PROC_WINDOW );
1786 retval = wndPtr->dwStyle;
1787 style.styleOld = wndPtr->dwStyle;
1788 style.styleNew = newval;
1789 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1790 wndPtr->dwStyle = style.styleNew;
1791 if (USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, retval );
1792 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1793 retval = style.styleOld;
1796 style.styleOld = wndPtr->dwExStyle;
1797 style.styleNew = newval;
1798 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1799 wndPtr->dwExStyle = style.styleNew;
1800 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1801 retval = style.styleOld;
1805 WARN("Invalid offset %d\n", offset );
1807 /* Don't think this is right error but it should do */
1808 SetLastError( ERROR_OUTOFMEMORY );
1816 WIN_ReleaseWndPtr(wndPtr);
1821 /**********************************************************************
1822 * GetWindowLong (USER.135)
1824 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1826 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
1830 /**********************************************************************
1831 * GetWindowLongA (USER32.@)
1833 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
1835 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1839 /**********************************************************************
1840 * GetWindowLongW (USER32.@)
1842 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
1844 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1848 /**********************************************************************
1849 * SetWindowLong (USER.136)
1851 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1853 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
1857 /**********************************************************************
1858 * SetWindowLongA (USER32.@)
1860 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
1862 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1866 /**********************************************************************
1867 * SetWindowLongW (USER32.@) Set window attribute
1869 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
1870 * value in a window's extra memory.
1872 * The _hwnd_ parameter specifies the window. is the handle to a
1873 * window that has extra memory. The _newval_ parameter contains the
1874 * new attribute or extra memory value. If positive, the _offset_
1875 * parameter is the byte-addressed location in the window's extra
1876 * memory to set. If negative, _offset_ specifies the window
1877 * attribute to set, and should be one of the following values:
1879 * GWL_EXSTYLE The window's extended window style
1881 * GWL_STYLE The window's window style.
1883 * GWL_WNDPROC Pointer to the window's window procedure.
1885 * GWL_HINSTANCE The window's pplication instance handle.
1887 * GWL_ID The window's identifier.
1889 * GWL_USERDATA The window's user-specified data.
1891 * If the window is a dialog box, the _offset_ parameter can be one of
1892 * the following values:
1894 * DWL_DLGPROC The address of the window's dialog box procedure.
1896 * DWL_MSGRESULT The return value of a message
1897 * that the dialog box procedure processed.
1899 * DWL_USER Application specific information.
1903 * If successful, returns the previous value located at _offset_. Otherwise,
1908 * Extra memory for a window class is specified by a nonzero cbWndExtra
1909 * parameter of the WNDCLASS structure passed to RegisterClass() at the
1910 * time of class creation.
1912 * Using GWL_WNDPROC to set a new window procedure effectively creates
1913 * a window subclass. Use CallWindowProc() in the new windows procedure
1914 * to pass messages to the superclass's window procedure.
1916 * The user data is reserved for use by the application which created
1919 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
1920 * instead, call the EnableWindow() function to change the window's
1923 * Do not use GWL_HWNDPARENT to reset the window's parent, use
1924 * SetParent() instead.
1927 * When offset is GWL_STYLE and the calling app's ver is 4.0,
1928 * it sends WM_STYLECHANGING before changing the settings
1929 * and WM_STYLECHANGED afterwards.
1930 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
1934 * GWL_STYLE does not dispatch WM_STYLE... messages.
1941 LONG WINAPI SetWindowLongW(
1942 HWND hwnd, /* [in] window to alter */
1943 INT offset, /* [in] offset, in bytes, of location to alter */
1944 LONG newval /* [in] new value of location */
1946 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1950 /*******************************************************************
1951 * GetWindowTextA (USER32.@)
1953 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
1955 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
1959 /*******************************************************************
1960 * InternalGetWindowText (USER32.@)
1962 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
1964 WND *win = WIN_FindWndPtr( hwnd );
1966 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
1967 else lpString[0] = 0;
1968 WIN_ReleaseWndPtr( win );
1969 return strlenW(lpString);
1973 /*******************************************************************
1974 * GetWindowTextW (USER32.@)
1976 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
1978 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
1983 /*******************************************************************
1984 * SetWindowText (USER32.@)
1985 * SetWindowTextA (USER32.@)
1987 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
1989 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1993 /*******************************************************************
1994 * SetWindowTextW (USER32.@)
1996 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
1998 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2002 /*******************************************************************
2003 * GetWindowTextLengthA (USER32.@)
2005 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2007 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2010 /*******************************************************************
2011 * GetWindowTextLengthW (USER32.@)
2013 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2015 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2019 /*******************************************************************
2020 * IsWindow (USER32.@)
2022 BOOL WINAPI IsWindow( HWND hwnd )
2027 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2029 if (ptr != WND_OTHER_PROCESS)
2031 WIN_ReleasePtr( ptr );
2035 /* check other processes */
2036 SERVER_START_REQ( get_window_info )
2039 ret = !SERVER_CALL_ERR();
2046 /***********************************************************************
2047 * GetWindowThreadProcessId (USER32.@)
2049 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2054 if (!(ptr = WIN_GetPtr( hwnd )))
2056 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2060 if (ptr != WND_OTHER_PROCESS)
2062 /* got a valid window */
2064 if (process) *process = GetCurrentProcessId();
2065 WIN_ReleasePtr( ptr );
2069 /* check other processes */
2070 SERVER_START_REQ( get_window_info )
2073 if (!SERVER_CALL_ERR())
2075 tid = (DWORD)req->tid;
2076 if (process) *process = (DWORD)req->pid;
2084 /*****************************************************************
2085 * GetParent (USER32.@)
2087 HWND WINAPI GetParent( HWND hwnd )
2092 if ((wndPtr = WIN_FindWndPtr(hwnd)))
2094 if (wndPtr->dwStyle & WS_CHILD)
2095 retvalue = wndPtr->parent;
2096 else if (wndPtr->dwStyle & WS_POPUP)
2097 retvalue = wndPtr->owner;
2098 WIN_ReleaseWndPtr(wndPtr);
2104 /*****************************************************************
2105 * GetAncestor (USER32.@)
2107 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2110 size_t size = (type == GA_PARENT) ? sizeof(user_handle_t) : REQUEST_MAX_VAR_SIZE;
2112 SERVER_START_VAR_REQ( get_window_parents, size )
2117 user_handle_t *data = server_data_ptr(req);
2118 int count = server_data_size(req) / sizeof(*data);
2128 if (count > 1) ret = data[count - 2]; /* get the one before the desktop */
2129 else ret = WIN_GetFullHandle( hwnd );
2137 if (ret && type == GA_ROOTOWNER)
2141 HWND owner = GetWindow( ret, GW_OWNER );
2150 /*****************************************************************
2153 * Implementation of SetParent, runs in the thread owning the window.
2155 HWND WIN_SetParent( HWND hwnd, HWND parent )
2161 if (USER_Driver.pSetParent)
2162 return USER_Driver.pSetParent( hwnd, parent );
2164 /* Windows hides the window first, then shows it again
2165 * including the WM_SHOWWINDOW messages and all */
2166 was_visible = ShowWindow( hwnd, SW_HIDE );
2168 if (!IsWindow( parent )) return 0;
2169 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2171 retvalue = wndPtr->parent; /* old parent */
2172 if (parent != retvalue)
2174 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2176 if (parent != GetDesktopWindow()) /* a child window */
2178 if (!(wndPtr->dwStyle & WS_CHILD))
2180 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2181 if (menu) DestroyMenu( menu );
2185 WIN_ReleasePtr( wndPtr );
2187 /* SetParent additionally needs to make hwnd the topmost window
2188 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2189 WM_WINDOWPOSCHANGED notification messages.
2191 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2192 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2193 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2194 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2199 /*****************************************************************
2200 * SetParent (USER32.@)
2202 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2206 if (!parent) parent = GetDesktopWindow();
2207 else parent = WIN_GetFullHandle( parent );
2209 if (!IsWindow( parent ))
2211 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2215 if ((full_handle = WIN_IsCurrentThread( hwnd )))
2216 return WIN_SetParent( full_handle, parent );
2218 if ((full_handle = WIN_GetFullHandle(hwnd)) == GetDesktopWindow())
2220 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2223 return SendMessageW( full_handle, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2227 /*******************************************************************
2228 * IsChild (USER32.@)
2230 BOOL WINAPI IsChild( HWND parent, HWND child )
2232 HWND *list = WIN_ListParents( child );
2236 if (!list) return FALSE;
2237 parent = WIN_GetFullHandle( parent );
2238 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2239 ret = (list[i] != 0);
2240 HeapFree( GetProcessHeap(), 0, list );
2245 /***********************************************************************
2246 * IsWindowVisible (USER32.@)
2248 BOOL WINAPI IsWindowVisible( HWND hwnd )
2254 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2255 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2256 for (i = 0; list[i]; i++)
2257 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2259 HeapFree( GetProcessHeap(), 0, list );
2264 /***********************************************************************
2265 * WIN_IsWindowDrawable
2267 * hwnd is drawable when it is visible, all parents are not
2268 * minimized, and it is itself not minimized unless we are
2269 * trying to draw its default class icon.
2271 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2276 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2278 if (!(style & WS_VISIBLE)) return FALSE;
2279 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2281 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2282 for (i = 0; list[i]; i++)
2283 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2286 HeapFree( GetProcessHeap(), 0, list );
2291 /*******************************************************************
2292 * GetTopWindow (USER32.@)
2294 HWND WINAPI GetTopWindow( HWND hwnd )
2296 if (!hwnd) hwnd = GetDesktopWindow();
2297 return GetWindow( hwnd, GW_CHILD );
2301 /*******************************************************************
2302 * GetWindow (USER32.@)
2304 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2308 if (rel == GW_OWNER) /* special case: not fully supported in the server yet */
2310 WND *wndPtr = WIN_FindWndPtr( hwnd );
2311 if (!wndPtr) return 0;
2312 retval = wndPtr->owner;
2313 WIN_ReleaseWndPtr( wndPtr );
2317 SERVER_START_REQ( get_window_tree )
2320 if (!SERVER_CALL_ERR())
2325 retval = req->first_sibling;
2328 retval = req->last_sibling;
2331 retval = req->next_sibling;
2334 retval = req->prev_sibling;
2337 retval = req->first_child;
2347 /***********************************************************************
2348 * WIN_InternalShowOwnedPopups
2350 * Internal version of ShowOwnedPopups; Wine functions should use this
2351 * to avoid interfering with application calls to ShowOwnedPopups
2352 * and to make sure the application can't prevent showing/hiding.
2354 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2358 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2362 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2364 if (!win_array) return TRUE;
2367 * Show windows Lowest first, Highest last to preserve Z-Order
2369 while (win_array[count]) count++;
2370 while (--count >= 0)
2372 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2373 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2375 if (pWnd->dwStyle & WS_POPUP)
2379 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2380 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2383 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2385 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2386 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2391 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2392 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2393 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2396 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2398 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2399 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2400 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2404 WIN_ReleaseWndPtr( pWnd );
2406 HeapFree( GetProcessHeap(), 0, win_array );
2411 /*******************************************************************
2412 * ShowOwnedPopups (USER32.@)
2414 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2418 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2420 if (!win_array) return TRUE;
2422 while (win_array[count]) count++;
2423 while (--count >= 0)
2425 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2426 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2428 if (pWnd->dwStyle & WS_POPUP)
2432 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2434 /* In Windows, ShowOwnedPopups(TRUE) generates
2435 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2436 * regardless of the state of the owner
2438 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2439 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2444 if (IsWindowVisible(pWnd->hwndSelf))
2446 /* In Windows, ShowOwnedPopups(FALSE) generates
2447 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2448 * regardless of the state of the owner
2450 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2451 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2455 WIN_ReleaseWndPtr( pWnd );
2457 HeapFree( GetProcessHeap(), 0, win_array );
2462 /*******************************************************************
2463 * GetLastActivePopup (USER32.@)
2465 HWND WINAPI GetLastActivePopup( HWND hwnd )
2468 WND *wndPtr =WIN_FindWndPtr(hwnd);
2469 if (!wndPtr) return hwnd;
2470 retval = wndPtr->hwndLastActive;
2471 if (!IsWindow( retval )) retval = wndPtr->hwndSelf;
2472 WIN_ReleaseWndPtr(wndPtr);
2477 /*******************************************************************
2480 * Build an array of all parents of a given window, starting with
2481 * the immediate parent. The array must be freed with HeapFree.
2482 * Returns NULL if window is a top-level window.
2484 HWND *WIN_ListParents( HWND hwnd )
2488 SERVER_START_VAR_REQ( get_window_parents, REQUEST_MAX_VAR_SIZE )
2493 user_handle_t *data = server_data_ptr(req);
2494 int i, count = server_data_size(req) / sizeof(*data);
2495 if (count && ((list = HeapAlloc( GetProcessHeap(), 0, (count + 1) * sizeof(HWND) ))))
2497 for (i = 0; i < count; i++) list[i] = data[i];
2507 /*******************************************************************
2510 * Build an array of the children of a given window. The array must be
2511 * freed with HeapFree. Returns NULL when no windows are found.
2513 HWND *WIN_ListChildren( HWND hwnd )
2515 return list_window_children( hwnd, 0, 0 );
2519 /*******************************************************************
2520 * EnumWindows (USER32.@)
2522 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2528 /* We have to build a list of all windows first, to avoid */
2529 /* unpleasant side-effects, for instance if the callback */
2530 /* function changes the Z-order of the windows. */
2532 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return FALSE;
2534 /* Now call the callback function for every window */
2536 iWndsLocks = WIN_SuspendWndsLock();
2537 for (i = 0; list[i]; i++)
2539 /* Make sure that the window still exists */
2540 if (!IsWindow( list[i] )) continue;
2541 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2543 WIN_RestoreWndsLock(iWndsLocks);
2544 HeapFree( GetProcessHeap(), 0, list );
2549 /**********************************************************************
2550 * EnumTaskWindows16 (USER.225)
2552 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2555 TDB *tdb = TASK_GetPtr( hTask );
2556 if (!tdb) return FALSE;
2557 return EnumThreadWindows( (DWORD)tdb->teb->tid, (WNDENUMPROC)func, lParam );
2561 /**********************************************************************
2562 * EnumThreadWindows (USER32.@)
2564 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2569 if (!(list = list_window_children( GetDesktopWindow(), 0, GetCurrentThreadId() )))
2572 /* Now call the callback function for every window */
2574 iWndsLocks = WIN_SuspendWndsLock();
2575 for (i = 0; list[i]; i++)
2576 if (!func( list[i], lParam )) break;
2577 WIN_RestoreWndsLock(iWndsLocks);
2578 HeapFree( GetProcessHeap(), 0, list );
2583 /**********************************************************************
2584 * WIN_EnumChildWindows
2586 * Helper function for EnumChildWindows().
2588 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2593 for ( ; *list; list++)
2595 /* Make sure that the window still exists */
2596 if (!IsWindow( *list )) continue;
2597 /* skip owned windows */
2598 if (GetWindow( *list, GW_OWNER )) continue;
2599 /* Build children list first */
2600 childList = WIN_ListChildren( *list );
2602 ret = func( *list, lParam );
2606 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2607 HeapFree( GetProcessHeap(), 0, childList );
2609 if (!ret) return FALSE;
2615 /**********************************************************************
2616 * EnumChildWindows (USER32.@)
2618 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2623 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2624 iWndsLocks = WIN_SuspendWndsLock();
2625 WIN_EnumChildWindows( list, func, lParam );
2626 WIN_RestoreWndsLock(iWndsLocks);
2627 HeapFree( GetProcessHeap(), 0, list );
2632 /*******************************************************************
2633 * AnyPopup (USER.52)
2635 BOOL16 WINAPI AnyPopup16(void)
2641 /*******************************************************************
2642 * AnyPopup (USER32.@)
2644 BOOL WINAPI AnyPopup(void)
2648 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2650 if (!list) return FALSE;
2651 for (i = 0; list[i]; i++)
2653 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2655 retvalue = (list[i] != 0);
2656 HeapFree( GetProcessHeap(), 0, list );
2661 /*******************************************************************
2662 * FlashWindow (USER32.@)
2664 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2666 WND *wndPtr = WIN_FindWndPtr(hWnd);
2668 TRACE("%04x\n", hWnd);
2670 if (!wndPtr) return FALSE;
2671 hWnd = wndPtr->hwndSelf; /* make it a full handle */
2673 if (wndPtr->dwStyle & WS_MINIMIZE)
2675 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2677 HDC hDC = GetDC(hWnd);
2679 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2680 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2682 ReleaseDC( hWnd, hDC );
2683 wndPtr->flags |= WIN_NCACTIVATED;
2687 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2688 wndPtr->flags &= ~WIN_NCACTIVATED;
2690 WIN_ReleaseWndPtr(wndPtr);
2696 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2697 else wparam = (hWnd == GetActiveWindow());
2699 WIN_ReleaseWndPtr(wndPtr);
2700 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2706 /*******************************************************************
2707 * GetWindowContextHelpId (USER32.@)
2709 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2712 WND *wnd = WIN_FindWndPtr( hwnd );
2714 retval = wnd->helpContext;
2715 WIN_ReleaseWndPtr(wnd);
2720 /*******************************************************************
2721 * SetWindowContextHelpId (USER32.@)
2723 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
2725 WND *wnd = WIN_FindWndPtr( hwnd );
2726 if (!wnd) return FALSE;
2727 wnd->helpContext = id;
2728 WIN_ReleaseWndPtr(wnd);
2733 /*******************************************************************
2736 * recursively find a child that contains spDragInfo->pt point
2737 * and send WM_QUERYDROPOBJECT
2739 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
2741 BOOL16 wParam, bResult = 0;
2743 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
2746 if (!ptrDragInfo) return FALSE;
2748 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
2750 GetWindowRect(hQueryWnd,&tempRect);
2752 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
2754 if (!IsIconic( hQueryWnd ))
2756 GetClientRect( hQueryWnd, &tempRect );
2757 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
2759 if (PtInRect( &tempRect, pt))
2762 HWND *list = WIN_ListChildren( hQueryWnd );
2768 for (i = 0; list[i]; i++)
2770 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
2772 GetWindowRect( list[i], &tempRect );
2773 if (PtInRect( &tempRect, pt )) break;
2778 if (IsWindowEnabled( list[i] ))
2779 bResult = DRAG_QueryUpdate( list[i], spDragInfo, bNoSend );
2781 HeapFree( GetProcessHeap(), 0, list );
2783 if(bResult) return bResult;
2789 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
2791 ptrDragInfo->hScope = hQueryWnd;
2793 if (bNoSend) bResult = (GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) != 0;
2794 else bResult = SendMessage16( hQueryWnd, WM_QUERYDROPOBJECT, (WPARAM16)wParam, spDragInfo );
2796 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
2802 /*******************************************************************
2803 * DragDetect (USER32.@)
2805 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
2810 rect.left = pt.x - wDragWidth;
2811 rect.right = pt.x + wDragWidth;
2813 rect.top = pt.y - wDragHeight;
2814 rect.bottom = pt.y + wDragHeight;
2820 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
2822 if( msg.message == WM_LBUTTONUP )
2827 if( msg.message == WM_MOUSEMOVE )
2830 tmp.x = LOWORD(msg.lParam);
2831 tmp.y = HIWORD(msg.lParam);
2832 if( !PtInRect( &rect, tmp ))
2844 /******************************************************************************
2845 * DragObject (USER.464)
2847 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
2848 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
2851 LPDRAGINFO16 lpDragInfo;
2853 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
2854 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
2855 HCURSOR16 hCurrentCursor = 0;
2856 HWND16 hCurrentWnd = 0;
2858 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
2859 spDragInfo = K32WOWGlobalLock16(hDragInfo);
2861 if( !lpDragInfo || !spDragInfo ) return 0L;
2863 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
2865 GlobalFree16(hDragInfo);
2871 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
2873 GlobalFree16(hDragInfo);
2877 if( hDragCursor == hCursor ) hDragCursor = 0;
2878 else hCursor = hDragCursor;
2880 hOldCursor = SetCursor(hDragCursor);
2883 lpDragInfo->hWnd = hWnd;
2884 lpDragInfo->hScope = 0;
2885 lpDragInfo->wFlags = wObj;
2886 lpDragInfo->hList = szList; /* near pointer! */
2887 lpDragInfo->hOfStruct = hOfStruct;
2895 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
2897 *(lpDragInfo+1) = *lpDragInfo;
2899 lpDragInfo->pt.x = msg.pt.x;
2900 lpDragInfo->pt.y = msg.pt.y;
2902 /* update DRAGINFO struct */
2903 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
2905 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
2906 hCurrentCursor = hCursor;
2909 hCurrentCursor = hBummer;
2910 lpDragInfo->hScope = 0;
2912 if( hCurrentCursor )
2913 SetCursor(hCurrentCursor);
2915 /* send WM_DRAGLOOP */
2916 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
2917 (LPARAM) spDragInfo );
2918 /* send WM_DRAGSELECT or WM_DRAGMOVE */
2919 if( hCurrentWnd != lpDragInfo->hScope )
2922 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
2923 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
2924 HIWORD(spDragInfo)) );
2925 hCurrentWnd = lpDragInfo->hScope;
2927 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
2931 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
2933 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
2936 ShowCursor( FALSE );
2940 SetCursor( hOldCursor );
2941 if (hDragCursor) DestroyCursor( hDragCursor );
2944 if( hCurrentCursor != hBummer )
2945 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
2946 (WPARAM16)hWnd, (LPARAM)spDragInfo );
2949 GlobalFree16(hDragInfo);
2951 return (DWORD)(msg.lParam);
2955 /******************************************************************************
2956 * GetWindowModuleFileNameA (USER32.@)
2958 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
2960 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
2961 hwnd, lpszFileName, cchFileNameMax);
2965 /******************************************************************************
2966 * GetWindowModuleFileNameW (USER32.@)
2968 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
2970 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
2971 hwnd, lpszFileName, cchFileNameMax);