2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "wine/port.h"
30 #include "wine/winbase16.h"
31 #include "wine/winuser16.h"
33 #include "wine/server.h"
34 #include "wine/unicode.h"
39 #include "cursoricon.h"
43 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(win);
46 WINE_DECLARE_DEBUG_CHANNEL(msg);
48 #define NB_USER_HANDLES ((LAST_USER_HANDLE - FIRST_USER_HANDLE + 1) >> 1)
49 #define USER_HANDLE_TO_INDEX(hwnd) ((LOWORD(hwnd) - FIRST_USER_HANDLE) >> 1)
51 /**********************************************************************/
54 static WND *pWndDesktop = NULL;
56 static WORD wDragWidth = 4;
57 static WORD wDragHeight= 3;
59 static void *user_handles[NB_USER_HANDLES];
61 /***********************************************************************
62 * create_window_handle
64 * Create a window handle with the server.
66 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom,
67 HINSTANCE instance, WINDOWPROCTYPE type )
71 struct tagCLASS *class = NULL;
72 user_handle_t handle = 0;
75 /* if 16-bit instance, map to module handle */
76 if (instance && !HIWORD(instance))
77 instance = HINSTANCE_32(GetExePtr(HINSTANCE_16(instance)));
79 SERVER_START_REQ( create_window )
84 req->instance = instance;
85 if (!wine_server_call_err( req ))
87 handle = reply->handle;
88 extra_bytes = reply->extra;
89 class = reply->class_ptr;
96 WARN( "error %ld creating window\n", GetLastError() );
100 if (!(win = HeapAlloc( GetProcessHeap(), 0, sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
102 SERVER_START_REQ( destroy_window )
104 req->handle = handle;
105 wine_server_call( req );
108 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
114 index = USER_HANDLE_TO_INDEX(handle);
115 assert( index < NB_USER_HANDLES );
116 user_handles[index] = win;
117 win->hwndSelf = handle;
118 win->dwMagic = WND_MAGIC;
120 win->cbWndExtra = extra_bytes;
121 memset( win->wExtra, 0, extra_bytes );
122 CLASS_AddWindow( class, win, type );
127 /***********************************************************************
130 * Free a window handle.
132 static WND *free_window_handle( HWND hwnd )
135 WORD index = USER_HANDLE_TO_INDEX(hwnd);
137 if (index >= NB_USER_HANDLES) return NULL;
139 if ((ptr = user_handles[index]))
141 SERVER_START_REQ( destroy_window )
144 if (!wine_server_call_err( req ))
145 user_handles[index] = NULL;
152 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
157 /*******************************************************************
158 * list_window_children
160 * Build an array of the children of a given window. The array must be
161 * freed with HeapFree. Returns NULL when no windows are found.
163 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
172 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
174 SERVER_START_REQ( get_window_children )
179 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
180 if (!wine_server_call( req )) count = reply->count;
183 if (count && count < size)
188 HeapFree( GetProcessHeap(), 0, list );
190 size = count + 1; /* restart with a large enough buffer */
196 /*******************************************************************
199 static void send_parent_notify( HWND hwnd, UINT msg )
201 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
202 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
203 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
204 MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
208 /*******************************************************************
209 * get_server_window_text
211 * Retrieve the window text from the server.
213 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
217 SERVER_START_REQ( get_window_text )
220 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
221 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
224 text[len / sizeof(WCHAR)] = 0;
228 /***********************************************************************
231 * Return a pointer to the WND structure if local to the process,
232 * or WND_OTHER_PROCESS if handle may be valid in other process.
233 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
235 WND *WIN_GetPtr( HWND hwnd )
238 WORD index = USER_HANDLE_TO_INDEX(hwnd);
240 if (index >= NB_USER_HANDLES) return NULL;
243 if ((ptr = user_handles[index]))
245 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
249 else ptr = WND_OTHER_PROCESS;
255 /***********************************************************************
256 * WIN_IsCurrentProcess
258 * Check whether a given window belongs to the current process (and return the full handle).
260 HWND WIN_IsCurrentProcess( HWND hwnd )
265 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
267 WIN_ReleasePtr( ptr );
272 /***********************************************************************
273 * WIN_IsCurrentThread
275 * Check whether a given window belongs to the current thread (and return the full handle).
277 HWND WIN_IsCurrentThread( HWND hwnd )
282 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
284 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
285 WIN_ReleasePtr( ptr );
291 /***********************************************************************
294 * Convert a 16-bit window handle to a full 32-bit handle.
296 HWND WIN_Handle32( HWND16 hwnd16 )
299 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
301 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
302 /* do sign extension for -2 and -3 */
303 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
305 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
307 if (ptr != WND_OTHER_PROCESS)
309 hwnd = ptr->hwndSelf;
310 WIN_ReleasePtr( ptr );
312 else /* may belong to another process */
314 SERVER_START_REQ( get_window_info )
317 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
325 /***********************************************************************
328 * Return a pointer to the WND structure corresponding to a HWND.
330 WND * WIN_FindWndPtr( HWND hwnd )
334 if (!hwnd) return NULL;
336 if ((ptr = WIN_GetPtr( hwnd )))
338 if (ptr != WND_OTHER_PROCESS)
340 /* increment destruction monitoring */
344 if (IsWindow( hwnd )) /* check other processes */
346 ERR( "window %p belongs to other process\n", hwnd );
347 /* DbgBreakPoint(); */
350 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
355 /***********************************************************************
358 * Release the pointer to the WND structure.
360 void WIN_ReleaseWndPtr(WND *wndPtr)
364 /* Decrement destruction monitoring value */
366 /* Check if it's time to release the memory */
367 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
370 free_window_handle( wndPtr->hwndSelf );
372 else if(wndPtr->irefCount < 0)
374 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
375 ERR("forgot a Lock on %p somewhere\n",wndPtr);
377 /* unlock all WND structures for thread safeness */
382 /***********************************************************************
385 * Remove a window from the siblings linked list.
387 void WIN_UnlinkWindow( HWND hwnd )
389 WIN_LinkWindow( hwnd, 0, 0 );
393 /***********************************************************************
396 * Insert a window into the siblings linked list.
397 * The window is inserted after the specified window, which can also
398 * be specified as HWND_TOP or HWND_BOTTOM.
399 * If parent is 0, window is unlinked from the tree.
401 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
403 WND *wndPtr = WIN_GetPtr( hwnd );
406 if (wndPtr == WND_OTHER_PROCESS)
408 if (IsWindow(hwnd)) ERR(" cannot link other process window %p\n", hwnd );
412 SERVER_START_REQ( link_window )
415 req->parent = parent;
416 req->previous = hwndInsertAfter;
417 if (!wine_server_call( req ))
419 if (reply->full_parent) wndPtr->parent = reply->full_parent;
424 WIN_ReleasePtr( wndPtr );
428 /***********************************************************************
431 * Change the owner of a window.
433 HWND WIN_SetOwner( HWND hwnd, HWND owner )
435 WND *win = WIN_GetPtr( hwnd );
439 if (win == WND_OTHER_PROCESS)
441 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
444 SERVER_START_REQ( set_window_owner )
448 if (!wine_server_call( req ))
450 win->owner = reply->full_owner;
451 ret = reply->prev_owner;
455 WIN_ReleasePtr( win );
460 /***********************************************************************
463 * Change the style of a window.
465 LONG WIN_SetStyle( HWND hwnd, LONG style )
469 WND *win = WIN_GetPtr( hwnd );
472 if (win == WND_OTHER_PROCESS)
475 ERR( "cannot set style %lx on other process window %p\n", style, hwnd );
478 if (style == win->dwStyle)
480 WIN_ReleasePtr( win );
483 SERVER_START_REQ( set_window_info )
486 req->flags = SET_WIN_STYLE;
488 req->extra_offset = -1;
489 if ((ok = !wine_server_call( req )))
491 ret = reply->old_style;
492 win->dwStyle = style;
496 WIN_ReleasePtr( win );
497 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret );
502 /***********************************************************************
505 * Change the extended style of a window.
507 LONG WIN_SetExStyle( HWND hwnd, LONG style )
510 WND *win = WIN_GetPtr( hwnd );
513 if (win == WND_OTHER_PROCESS)
516 ERR( "cannot set exstyle %lx on other process window %p\n", style, hwnd );
519 if (style == win->dwExStyle)
521 WIN_ReleasePtr( win );
524 SERVER_START_REQ( set_window_info )
527 req->flags = SET_WIN_EXSTYLE;
528 req->ex_style = style;
529 req->extra_offset = -1;
530 if (!wine_server_call( req ))
532 ret = reply->old_ex_style;
533 win->dwExStyle = style;
537 WIN_ReleasePtr( win );
542 /***********************************************************************
545 * Get the window and client rectangles.
547 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
549 WND *win = WIN_GetPtr( hwnd );
552 if (!win) return FALSE;
553 if (win == WND_OTHER_PROCESS)
555 SERVER_START_REQ( get_window_rectangles )
558 if ((ret = !wine_server_call( req )))
562 rectWindow->left = reply->window.left;
563 rectWindow->top = reply->window.top;
564 rectWindow->right = reply->window.right;
565 rectWindow->bottom = reply->window.bottom;
569 rectClient->left = reply->client.left;
570 rectClient->top = reply->client.top;
571 rectClient->right = reply->client.right;
572 rectClient->bottom = reply->client.bottom;
580 if (rectWindow) *rectWindow = win->rectWindow;
581 if (rectClient) *rectClient = win->rectClient;
582 WIN_ReleasePtr( win );
588 /***********************************************************************
591 * Destroy storage associated to a window. "Internals" p.358
593 LRESULT WIN_DestroyWindow( HWND hwnd )
598 TRACE("%p\n", hwnd );
600 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
602 ERR( "window doesn't belong to current thread\n" );
606 /* free child windows */
607 if ((list = WIN_ListChildren( hwnd )))
610 for (i = 0; list[i]; i++)
612 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
613 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
615 HeapFree( GetProcessHeap(), 0, list );
619 * Clear the update region to make sure no WM_PAINT messages will be
620 * generated for this window while processing the WM_NCDESTROY.
622 RedrawWindow( hwnd, NULL, 0,
623 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
626 * Send the WM_NCDESTROY to the window being destroyed.
628 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
630 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
632 WINPOS_CheckInternalPos( hwnd );
633 if( hwnd == GetCapture()) ReleaseCapture();
635 /* free resources associated with the window */
637 TIMER_RemoveWindowTimers( hwnd );
639 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
641 if (!(wndPtr->dwStyle & WS_CHILD))
643 HMENU menu = (HMENU)SetWindowLongPtrW( hwnd, GWLP_ID, 0 );
644 if (menu) DestroyMenu( menu );
646 if (wndPtr->hSysMenu)
648 DestroyMenu( wndPtr->hSysMenu );
649 wndPtr->hSysMenu = 0;
651 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
652 USER_Driver.pDestroyWindow( hwnd );
653 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
654 wndPtr->class = NULL;
655 wndPtr->dwMagic = 0; /* Mark it as invalid */
656 WIN_ReleaseWndPtr( wndPtr );
660 /***********************************************************************
661 * WIN_DestroyThreadWindows
663 * Destroy all children of 'wnd' owned by the current thread.
664 * Return TRUE if something was done.
666 void WIN_DestroyThreadWindows( HWND hwnd )
671 if (!(list = WIN_ListChildren( hwnd ))) return;
672 for (i = 0; list[i]; i++)
674 if (WIN_IsCurrentThread( list[i] ))
675 DestroyWindow( list[i] );
677 WIN_DestroyThreadWindows( list[i] );
679 HeapFree( GetProcessHeap(), 0, list );
682 /***********************************************************************
683 * WIN_CreateDesktopWindow
685 * Create the desktop window.
687 BOOL WIN_CreateDesktopWindow(void)
692 TRACE("Creating desktop window\n");
694 if (!WINPOS_CreateInternalPosAtom()) return FALSE;
696 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W );
697 if (!pWndDesktop) return FALSE;
698 hwndDesktop = pWndDesktop->hwndSelf;
700 pWndDesktop->tid = 0; /* nobody owns the desktop */
701 pWndDesktop->parent = 0;
702 pWndDesktop->owner = 0;
703 pWndDesktop->text = NULL;
704 pWndDesktop->hrgnUpdate = 0;
705 pWndDesktop->pVScroll = NULL;
706 pWndDesktop->pHScroll = NULL;
707 pWndDesktop->helpContext = 0;
708 pWndDesktop->flags = 0;
709 pWndDesktop->hSysMenu = 0;
711 cs.lpCreateParams = NULL;
717 cs.cx = GetSystemMetrics( SM_CXSCREEN );
718 cs.cy = GetSystemMetrics( SM_CYSCREEN );
719 cs.style = pWndDesktop->dwStyle;
720 cs.dwExStyle = pWndDesktop->dwExStyle;
722 cs.lpszClass = DESKTOP_CLASS_ATOM;
724 SERVER_START_REQ( set_window_info )
726 req->handle = hwndDesktop;
727 req->flags = 0; /* don't set anything, just retrieve */
728 req->extra_offset = -1;
729 wine_server_call( req );
730 pWndDesktop->dwStyle = reply->old_style;
731 pWndDesktop->dwExStyle = reply->old_ex_style;
732 pWndDesktop->hInstance = (HINSTANCE)reply->old_instance;
733 pWndDesktop->userdata = (ULONG_PTR)reply->old_user_data;
734 pWndDesktop->wIDmenu = reply->old_id;
738 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE ))
740 WIN_ReleaseWndPtr( pWndDesktop );
744 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
745 WIN_ReleaseWndPtr( pWndDesktop );
750 /***********************************************************************
753 * Fix the coordinates - Helper for WIN_CreateWindowEx.
754 * returns default show mode in sw.
755 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
757 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
759 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
760 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
762 if (cs->style & (WS_CHILD | WS_POPUP))
764 if (cs->dwExStyle & WS_EX_MDICHILD)
768 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0);
770 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
775 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16 || !cs->cx)
777 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16 || !cs->cy)
782 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
784 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
788 else /* overlapped window */
792 GetStartupInfoA( &info );
794 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
796 /* Never believe Microsoft's documentation... CreateWindowEx doc says
797 * that if an overlapped window is created with WS_VISIBLE style bit
798 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
799 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
802 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
803 * 2) it does not ignore the y parameter as the docs claim; instead, it
804 * uses it as second parameter to ShowWindow() unless y is either
805 * CW_USEDEFAULT or CW_USEDEFAULT16.
807 * The fact that we didn't do 2) caused bogus windows pop up when wine
808 * was running apps that were using this obscure feature. Example -
809 * calc.exe that comes with Win98 (only Win98, it's different from
810 * the one that comes with Win95 and NT)
812 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
813 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
814 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
817 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
819 if (info.dwFlags & STARTF_USESIZE)
821 cs->cx = info.dwXSize;
822 cs->cy = info.dwYSize;
824 else /* if no other hint from the app, pick 3/4 of the screen real estate */
827 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
828 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
829 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
836 /* neither x nor cx are default. Check the y values .
837 * In the trace we see Outlook and Outlook Express using
838 * cy set to CW_USEDEFAULT when opening the address book.
840 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
842 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
843 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
844 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
849 /***********************************************************************
852 static void dump_window_styles( DWORD style, DWORD exstyle )
855 if(style & WS_POPUP) TRACE(" WS_POPUP");
856 if(style & WS_CHILD) TRACE(" WS_CHILD");
857 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
858 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
859 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
860 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
861 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
862 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
863 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
866 if(style & WS_BORDER) TRACE(" WS_BORDER");
867 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
869 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
870 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
871 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
872 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
873 if(style & WS_GROUP) TRACE(" WS_GROUP");
874 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
875 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
876 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
878 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
879 #define DUMPED_STYLES \
899 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
904 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
905 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
906 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
907 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
908 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
909 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
910 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
911 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
912 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
913 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
914 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
915 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
916 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
917 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
918 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
919 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
920 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
921 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
923 #define DUMPED_EX_STYLES \
924 (WS_EX_DLGMODALFRAME | \
926 WS_EX_NOPARENTNOTIFY | \
928 WS_EX_ACCEPTFILES | \
929 WS_EX_TRANSPARENT | \
934 WS_EX_CONTEXTHELP | \
937 WS_EX_LEFTSCROLLBAR | \
938 WS_EX_CONTROLPARENT | \
943 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
945 #undef DUMPED_EX_STYLES
949 /***********************************************************************
952 * Implementation of CreateWindowEx().
954 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
955 WINDOWPROCTYPE type )
959 HWND hwnd, parent, owner, top_child = 0;
960 BOOL unicode = (type == WIN_PROC_32W);
962 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
963 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
964 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
965 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
966 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
968 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
970 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
971 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
973 /* Fix the styles for MDI children */
974 if (cs->dwExStyle & WS_EX_MDICHILD)
976 MDICREATESTRUCTA mdi_cs;
979 wndPtr = WIN_GetPtr(cs->hwndParent);
980 if (wndPtr && wndPtr != WND_OTHER_PROCESS)
982 flags = wndPtr->flags;
983 WIN_ReleasePtr(wndPtr);
986 if (!(flags & WIN_ISMDICLIENT))
988 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
992 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
993 * MDICREATESTRUCT members have the originally passed values.
995 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
996 * have the same layout.
998 mdi_cs.szClass = cs->lpszClass;
999 mdi_cs.szTitle = cs->lpszName;
1000 mdi_cs.hOwner = cs->hInstance;
1005 mdi_cs.style = cs->style;
1006 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
1008 cs->lpCreateParams = (LPVOID)&mdi_cs;
1010 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1012 if (cs->style & WS_POPUP)
1014 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
1017 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
1021 cs->style &= ~WS_POPUP;
1022 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
1023 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
1026 top_child = GetWindow(cs->hwndParent, GW_CHILD);
1030 /* Restore current maximized child */
1031 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
1033 TRACE("Restoring current maximized child %p\n", top_child);
1034 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
1035 ShowWindow(top_child, SW_RESTORE);
1036 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
1041 /* Find the parent window */
1043 parent = GetDesktopWindow();
1046 if (cs->hwndParent == HWND_MESSAGE)
1048 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
1049 * message window (style: WS_POPUP|WS_DISABLED)
1051 FIXME("Parent is HWND_MESSAGE\n");
1053 else if (cs->hwndParent)
1055 /* Make sure parent is valid */
1056 if (!IsWindow( cs->hwndParent ))
1058 WARN("Bad parent %p\n", cs->hwndParent );
1061 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1062 parent = WIN_GetFullHandle(cs->hwndParent);
1064 owner = GetAncestor( cs->hwndParent, GA_ROOT );
1066 else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1068 WARN("No parent for child window\n" );
1069 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1072 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1074 /* Correct the window styles.
1076 * It affects both the style loaded into the WIN structure and
1077 * passed in the CREATESTRUCT to the WM_[NC]CREATE.
1079 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1080 * why does the user get to set it?
1083 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1084 * tested for WS_POPUP
1086 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1087 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1088 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1089 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1091 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1093 if (!(cs->style & WS_CHILD))
1095 cs->style |= WS_CLIPSIBLINGS;
1096 if (!(cs->style & WS_POPUP))
1097 cs->style |= WS_CAPTION;
1100 /* Create the window structure */
1102 if (!(wndPtr = create_window_handle( parent, owner, classAtom, cs->hInstance, type )))
1104 TRACE("out of memory\n" );
1107 hwnd = wndPtr->hwndSelf;
1109 /* Fill the window structure */
1111 wndPtr->tid = GetCurrentThreadId();
1112 wndPtr->owner = owner;
1113 wndPtr->parent = parent;
1114 wndPtr->hInstance = cs->hInstance;
1115 wndPtr->text = NULL;
1116 wndPtr->hrgnUpdate = 0;
1117 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1118 wndPtr->dwExStyle = cs->dwExStyle;
1119 wndPtr->wIDmenu = 0;
1120 wndPtr->helpContext = 0;
1121 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1122 wndPtr->pVScroll = NULL;
1123 wndPtr->pHScroll = NULL;
1124 wndPtr->userdata = 0;
1126 wndPtr->hIconSmall = 0;
1127 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU) ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1129 if (!(cs->style & (WS_CHILD | WS_POPUP)))
1130 wndPtr->flags |= WIN_NEED_SIZE;
1132 SERVER_START_REQ( set_window_info )
1135 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1136 req->style = wndPtr->dwStyle;
1137 req->ex_style = wndPtr->dwExStyle;
1138 req->instance = (void *)wndPtr->hInstance;
1139 req->extra_offset = -1;
1140 wine_server_call( req );
1144 /* Get class or window DC if needed */
1146 if (wndPtr->clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1148 /* Set the window menu */
1150 if (((wndPtr->dwStyle & (WS_CAPTION|WS_CHILD)) == WS_CAPTION) ||
1151 (wndPtr->dwExStyle & WS_EX_APPWINDOW))
1153 if (cs->hMenu) MENU_SetMenu(hwnd, cs->hMenu);
1156 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1159 if (HIWORD(cs->hInstance))
1160 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1162 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1164 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1168 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1169 WIN_ReleaseWndPtr( wndPtr );
1171 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
1173 WIN_DestroyWindow( hwnd );
1177 /* Notify the parent window only */
1179 send_parent_notify( hwnd, WM_CREATE );
1180 if (!IsWindow( hwnd )) return 0;
1182 if (cs->style & WS_VISIBLE)
1184 if (cs->style & WS_MAXIMIZE)
1185 sw = SW_SHOWMAXIMIZED;
1186 else if (cs->style & WS_MINIMIZE)
1187 sw = SW_SHOWMINIMIZED;
1189 ShowWindow( hwnd, sw );
1190 if (cs->dwExStyle & WS_EX_MDICHILD)
1192 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1193 /* ShowWindow won't activate child windows */
1194 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1198 /* Call WH_SHELL hook */
1200 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1201 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1203 TRACE("created window %p\n", hwnd);
1208 /***********************************************************************
1209 * CreateWindow (USER.41)
1211 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1212 DWORD style, INT16 x, INT16 y, INT16 width,
1213 INT16 height, HWND16 parent, HMENU16 menu,
1214 HINSTANCE16 instance, LPVOID data )
1216 return CreateWindowEx16( 0, className, windowName, style,
1217 x, y, width, height, parent, menu, instance, data );
1221 /***********************************************************************
1222 * CreateWindowEx (USER.452)
1224 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1225 LPCSTR windowName, DWORD style, INT16 x,
1226 INT16 y, INT16 width, INT16 height,
1227 HWND16 parent, HMENU16 menu,
1228 HINSTANCE16 instance, LPVOID data )
1234 /* Find the class atom */
1236 if (HIWORD(className))
1238 if (!(classAtom = GlobalFindAtomA( className )))
1240 ERR( "bad class name %s\n", debugstr_a(className) );
1246 classAtom = LOWORD(className);
1247 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1249 ERR( "bad atom %x\n", classAtom);
1255 /* Fix the coordinates */
1257 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1258 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1259 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1260 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1262 /* Create the window */
1264 cs.lpCreateParams = data;
1265 cs.hInstance = HINSTANCE_32(instance);
1266 cs.hMenu = HMENU_32(menu);
1267 cs.hwndParent = WIN_Handle32( parent );
1269 cs.lpszName = windowName;
1270 cs.lpszClass = className;
1271 cs.dwExStyle = exStyle;
1273 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1277 /***********************************************************************
1278 * CreateWindowExA (USER32.@)
1280 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1281 LPCSTR windowName, DWORD style, INT x,
1282 INT y, INT width, INT height,
1283 HWND parent, HMENU menu,
1284 HINSTANCE instance, LPVOID data )
1290 /* Find the class atom */
1292 if (HIWORD(className))
1294 if (!(classAtom = GlobalFindAtomA( className )))
1296 ERR( "bad class name %s\n", debugstr_a(className) );
1302 classAtom = LOWORD(className);
1303 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1305 ERR( "bad atom %x\n", classAtom);
1311 /* Create the window */
1313 cs.lpCreateParams = data;
1314 cs.hInstance = instance;
1316 cs.hwndParent = parent;
1322 cs.lpszName = windowName;
1323 cs.lpszClass = className;
1324 cs.dwExStyle = exStyle;
1326 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1330 /***********************************************************************
1331 * CreateWindowExW (USER32.@)
1333 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1334 LPCWSTR windowName, DWORD style, INT x,
1335 INT y, INT width, INT height,
1336 HWND parent, HMENU menu,
1337 HINSTANCE instance, LPVOID data )
1343 /* Find the class atom */
1345 if (HIWORD(className))
1347 if (!(classAtom = GlobalFindAtomW( className )))
1349 ERR( "bad class name %s\n", debugstr_w(className) );
1355 classAtom = LOWORD(className);
1356 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1358 ERR( "bad atom %x\n", classAtom);
1364 /* Create the window */
1366 cs.lpCreateParams = data;
1367 cs.hInstance = instance;
1369 cs.hwndParent = parent;
1375 cs.lpszName = windowName;
1376 cs.lpszClass = className;
1377 cs.dwExStyle = exStyle;
1379 /* Note: we rely on the fact that CREATESTRUCTA and */
1380 /* CREATESTRUCTW have the same layout. */
1381 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1385 /***********************************************************************
1386 * WIN_SendDestroyMsg
1388 static void WIN_SendDestroyMsg( HWND hwnd )
1392 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1394 if (hwnd == info.hwndCaret) DestroyCaret();
1395 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1397 if (USER_Driver.pResetSelectionOwner)
1398 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1401 * Send the WM_DESTROY to the window.
1403 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1406 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1407 * make sure that the window still exists when we come back.
1414 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1416 /* start from the end (FIXME: is this needed?) */
1417 for (i = 0; pWndArray[i]; i++) ;
1421 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1423 HeapFree( GetProcessHeap(), 0, pWndArray );
1426 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1430 /***********************************************************************
1431 * DestroyWindow (USER32.@)
1433 BOOL WINAPI DestroyWindow( HWND hwnd )
1437 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1439 SetLastError( ERROR_ACCESS_DENIED );
1443 TRACE("(%p)\n", hwnd);
1447 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1449 if (MENU_IsMenuActive() == hwnd)
1452 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1456 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1457 send_parent_notify( hwnd, WM_DESTROY );
1459 else if (!GetWindow( hwnd, GW_OWNER ))
1461 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1462 /* FIXME: clean up palette - see "Internals" p.352 */
1465 if (!IsWindow(hwnd)) return TRUE;
1467 if (USER_Driver.pResetSelectionOwner)
1468 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1470 /* Hide the window */
1472 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1474 ShowWindow( hwnd, SW_HIDE );
1476 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1477 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1479 if (!IsWindow(hwnd)) return TRUE;
1481 /* Recursively destroy owned windows */
1488 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1491 for (i = 0; list[i]; i++)
1493 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1494 if (WIN_IsCurrentThread( list[i] ))
1496 DestroyWindow( list[i] );
1500 WIN_SetOwner( list[i], 0 );
1502 HeapFree( GetProcessHeap(), 0, list );
1504 if (!got_one) break;
1508 /* Send destroy messages */
1510 WIN_SendDestroyMsg( hwnd );
1511 if (!IsWindow( hwnd )) return TRUE;
1513 if (GetClipboardOwner() == hwnd)
1514 CLIPBOARD_ReleaseOwner();
1516 /* Unlink now so we won't bother with the children later on */
1518 WIN_UnlinkWindow( hwnd );
1520 /* Destroy the window storage */
1522 WIN_DestroyWindow( hwnd );
1527 /***********************************************************************
1528 * CloseWindow (USER32.@)
1530 BOOL WINAPI CloseWindow( HWND hwnd )
1532 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1533 ShowWindow( hwnd, SW_MINIMIZE );
1538 /***********************************************************************
1539 * OpenIcon (USER32.@)
1541 BOOL WINAPI OpenIcon( HWND hwnd )
1543 if (!IsIconic( hwnd )) return FALSE;
1544 ShowWindow( hwnd, SW_SHOWNORMAL );
1549 /***********************************************************************
1552 * Implementation of FindWindow() and FindWindowEx().
1554 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1559 WCHAR *buffer = NULL;
1561 if (!parent) parent = GetDesktopWindow();
1564 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1565 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1568 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1572 child = WIN_GetFullHandle( child );
1573 while (list[i] && list[i] != child) i++;
1574 if (!list[i]) goto done;
1575 i++; /* start from next window */
1582 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1589 if (list) HeapFree( GetProcessHeap(), 0, list );
1590 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1596 /***********************************************************************
1597 * FindWindowA (USER32.@)
1599 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1601 HWND ret = FindWindowExA( 0, 0, className, title );
1602 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1607 /***********************************************************************
1608 * FindWindowExA (USER32.@)
1610 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1611 LPCSTR className, LPCSTR title )
1620 /* If the atom doesn't exist, then no class */
1621 /* with this name exists either. */
1622 if (!(atom = GlobalFindAtomA( className )))
1624 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1628 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1630 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1631 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1632 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1633 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1634 HeapFree( GetProcessHeap(), 0, buffer );
1639 /***********************************************************************
1640 * FindWindowExW (USER32.@)
1642 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1643 LPCWSTR className, LPCWSTR title )
1649 /* If the atom doesn't exist, then no class */
1650 /* with this name exists either. */
1651 if (!(atom = GlobalFindAtomW( className )))
1653 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1657 return WIN_FindWindow( parent, child, atom, title );
1661 /***********************************************************************
1662 * FindWindowW (USER32.@)
1664 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1666 return FindWindowExW( 0, 0, className, title );
1670 /**********************************************************************
1671 * GetDesktopWindow (USER32.@)
1673 HWND WINAPI GetDesktopWindow(void)
1675 if (pWndDesktop) return pWndDesktop->hwndSelf;
1676 ERR( "Wine init error: either you're trying to use an invalid native USER.EXE config, or some graphics/GUI libraries or DLLs didn't initialize properly. Aborting.\n" );
1682 /*******************************************************************
1683 * EnableWindow (USER32.@)
1685 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1692 if (is_broadcast(hwnd))
1694 SetLastError( ERROR_INVALID_PARAMETER );
1698 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1699 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1703 TRACE("( %p, %d )\n", hwnd, enable);
1705 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1706 style = wndPtr->dwStyle;
1707 retvalue = ((style & WS_DISABLED) != 0);
1708 WIN_ReleasePtr( wndPtr );
1710 if (enable && retvalue)
1712 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1713 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1715 else if (!enable && !retvalue)
1719 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1721 WIN_SetStyle( hwnd, style | WS_DISABLED );
1723 if (hwnd == GetFocus())
1724 SetFocus( 0 ); /* A disabled window can't have the focus */
1726 capture_wnd = GetCapture();
1727 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1728 ReleaseCapture(); /* A disabled window can't capture the mouse */
1730 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1736 /***********************************************************************
1737 * IsWindowEnabled (USER32.@)
1739 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1741 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1745 /***********************************************************************
1746 * IsWindowUnicode (USER32.@)
1748 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1753 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1754 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1755 WIN_ReleaseWndPtr(wndPtr);
1760 /**********************************************************************
1761 * GetWindowWord (USER32.@)
1763 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1768 WND *wndPtr = WIN_GetPtr( hwnd );
1771 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1774 if (wndPtr == WND_OTHER_PROCESS)
1776 SERVER_START_REQ( set_window_info )
1779 req->flags = 0; /* don't set anything, just retrieve */
1780 req->extra_offset = offset;
1781 req->extra_size = sizeof(retvalue);
1782 if (!wine_server_call_err( req ))
1783 memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) );
1788 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1790 WARN("Invalid offset %d\n", offset );
1791 SetLastError( ERROR_INVALID_INDEX );
1793 else memcpy( &retvalue, (char *)wndPtr->wExtra + offset, sizeof(retvalue) );
1794 WIN_ReleasePtr( wndPtr );
1800 case GWLP_HWNDPARENT:
1801 return GetWindowLongPtrW( hwnd, offset );
1803 case GWLP_HINSTANCE:
1805 LONG_PTR ret = GetWindowLongPtrW( hwnd, offset );
1807 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1811 WARN("Invalid offset %d\n", offset );
1817 /**********************************************************************
1818 * SetWindowWord (USER32.@)
1820 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1828 case GWLP_HINSTANCE:
1829 case GWLP_HWNDPARENT:
1830 return SetWindowLongPtrW( hwnd, offset, (ULONG_PTR)newval );
1834 WARN("Invalid offset %d\n", offset );
1835 SetLastError( ERROR_INVALID_INDEX );
1840 wndPtr = WIN_GetPtr( hwnd );
1841 if (wndPtr == WND_OTHER_PROCESS)
1844 FIXME( "set %d <- %x not supported yet on other process window %p\n",
1845 offset, newval, hwnd );
1850 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1854 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1856 WARN("Invalid offset %d\n", offset );
1857 WIN_ReleasePtr(wndPtr);
1858 SetLastError( ERROR_INVALID_INDEX );
1862 SERVER_START_REQ( set_window_info )
1865 req->flags = SET_WIN_EXTRA;
1866 req->extra_offset = offset;
1867 req->extra_size = sizeof(newval);
1868 memcpy( &req->extra_value, &newval, sizeof(newval) );
1869 if (!wine_server_call_err( req ))
1871 void *ptr = (char *)wndPtr->wExtra + offset;
1872 memcpy( &retval, ptr, sizeof(retval) );
1873 memcpy( ptr, &newval, sizeof(newval) );
1877 WIN_ReleasePtr( wndPtr );
1882 /**********************************************************************
1885 * Helper function for GetWindowLong().
1887 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1889 LONG_PTR retvalue = 0;
1892 if (offset == GWLP_HWNDPARENT)
1894 HWND parent = GetAncestor( hwnd, GA_PARENT );
1895 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1896 return (ULONG_PTR)parent;
1899 if (!(wndPtr = WIN_GetPtr( hwnd )))
1901 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1905 if (wndPtr == WND_OTHER_PROCESS)
1907 if (offset == GWLP_WNDPROC)
1909 SetLastError( ERROR_ACCESS_DENIED );
1912 SERVER_START_REQ( set_window_info )
1915 req->flags = 0; /* don't set anything, just retrieve */
1916 req->extra_offset = (offset >= 0) ? offset : -1;
1917 req->extra_size = (offset >= 0) ? sizeof(retvalue) : 0;
1918 if (!wine_server_call_err( req ))
1922 case GWL_STYLE: retvalue = reply->old_style; break;
1923 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1924 case GWLP_ID: retvalue = reply->old_id; break;
1925 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1926 case GWLP_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1928 if (offset >= 0) retvalue = reply->old_extra_value;
1929 else SetLastError( ERROR_INVALID_INDEX );
1938 /* now we have a valid wndPtr */
1942 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1945 * Some programs try to access last element from 16 bit
1946 * code using illegal offset value. Hopefully this is
1947 * what those programs really expect.
1949 if (type == WIN_PROC_16 &&
1950 wndPtr->cbWndExtra >= 4 &&
1951 offset == wndPtr->cbWndExtra - sizeof(WORD))
1953 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1955 ERR( "- replaced invalid offset %d with %d\n",
1958 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset2);
1959 WIN_ReleasePtr( wndPtr );
1962 WARN("Invalid offset %d\n", offset );
1963 WIN_ReleasePtr( wndPtr );
1964 SetLastError( ERROR_INVALID_INDEX );
1967 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1968 /* Special case for dialog window procedure */
1969 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1970 retvalue = (LONG)WINPROC_GetProc( (WNDPROC)retvalue, type );
1971 WIN_ReleasePtr( wndPtr );
1977 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1978 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1979 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1980 case GWLP_ID: retvalue = (ULONG_PTR)wndPtr->wIDmenu; break;
1981 case GWLP_WNDPROC: retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, type ); break;
1982 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1984 WARN("Unknown offset %d\n", offset );
1985 SetLastError( ERROR_INVALID_INDEX );
1988 WIN_ReleasePtr(wndPtr);
1993 /**********************************************************************
1996 * Helper function for SetWindowLong().
1998 * 0 is the failure code. However, in the case of failure SetLastError
1999 * must be set to distinguish between a 0 return value and a failure.
2001 static LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, LONG_PTR newval,
2002 WINDOWPROCTYPE type )
2009 TRACE( "%p %d %lx %x\n", hwnd, offset, newval, type );
2011 if (is_broadcast(hwnd))
2013 SetLastError( ERROR_INVALID_PARAMETER );
2016 if (!WIN_IsCurrentProcess( hwnd ))
2018 if (offset == GWLP_WNDPROC)
2020 SetLastError( ERROR_ACCESS_DENIED );
2023 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
2026 wndPtr = WIN_GetPtr( hwnd );
2027 if (wndPtr->hwndSelf == GetDesktopWindow())
2029 /* can't change anything on the desktop window */
2030 WIN_ReleasePtr( wndPtr );
2031 SetLastError( ERROR_ACCESS_DENIED );
2035 /* first some special cases */
2041 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
2042 style.styleNew = newval;
2043 WIN_ReleasePtr( wndPtr );
2044 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2045 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2046 newval = style.styleNew;
2048 case GWLP_HWNDPARENT:
2049 if (wndPtr->parent == GetDesktopWindow())
2051 WIN_ReleasePtr( wndPtr );
2052 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
2056 WIN_ReleasePtr( wndPtr );
2057 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
2060 retval = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, type );
2061 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC)newval, type, WIN_PROC_WINDOW );
2062 WIN_ReleasePtr( wndPtr );
2065 case GWLP_HINSTANCE:
2069 if ((wndPtr->cbWndExtra + sizeof(LONG) >= DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2071 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
2072 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, type );
2073 WINPROC_SetProc( ptr, (WNDPROC)newval, type, WIN_PROC_WINDOW );
2074 WIN_ReleasePtr( wndPtr );
2079 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2081 WARN("Invalid offset %d\n", offset );
2082 WIN_ReleasePtr( wndPtr );
2083 SetLastError( ERROR_INVALID_INDEX );
2088 LONG_PTR *ptr = (LONG_PTR *)((char *)wndPtr->wExtra + offset);
2089 if (*ptr == newval) /* already set to the same value */
2091 WIN_ReleasePtr( wndPtr );
2098 SERVER_START_REQ( set_window_info )
2101 req->extra_offset = -1;
2105 req->flags = SET_WIN_STYLE;
2106 req->style = newval;
2109 req->flags = SET_WIN_EXSTYLE;
2110 req->ex_style = newval;
2113 req->flags = SET_WIN_ID;
2116 case GWLP_HINSTANCE:
2117 req->flags = SET_WIN_INSTANCE;
2118 req->instance = (void *)newval;
2121 req->flags = SET_WIN_USERDATA;
2122 req->user_data = (void *)newval;
2125 req->flags = SET_WIN_EXTRA;
2126 req->extra_offset = offset;
2127 req->extra_size = sizeof(newval);
2128 memcpy( &req->extra_value, &newval, sizeof(newval) );
2130 if ((ok = !wine_server_call_err( req )))
2135 wndPtr->dwStyle = newval;
2136 retval = reply->old_style;
2139 wndPtr->dwExStyle = newval;
2140 retval = reply->old_ex_style;
2143 wndPtr->wIDmenu = newval;
2144 retval = reply->old_id;
2146 case GWLP_HINSTANCE:
2147 wndPtr->hInstance = (HINSTANCE)newval;
2148 retval = (ULONG_PTR)reply->old_instance;
2151 wndPtr->userdata = newval;
2152 retval = (ULONG_PTR)reply->old_user_data;
2156 void *ptr = (char *)wndPtr->wExtra + offset;
2157 memcpy( &retval, ptr, sizeof(retval) );
2158 memcpy( ptr, &newval, sizeof(newval) );
2165 WIN_ReleasePtr( wndPtr );
2169 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2170 USER_Driver.pSetWindowStyle( hwnd, retval );
2172 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2173 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2179 /**********************************************************************
2180 * GetWindowLong (USER.135)
2182 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2184 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2188 /**********************************************************************
2189 * GetWindowLongA (USER32.@)
2191 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2193 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2197 /**********************************************************************
2198 * GetWindowLongW (USER32.@)
2200 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2202 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2206 /**********************************************************************
2207 * SetWindowLong (USER.136)
2209 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2211 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2215 /**********************************************************************
2216 * SetWindowLongA (USER32.@)
2218 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2220 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2224 /**********************************************************************
2225 * SetWindowLongW (USER32.@) Set window attribute
2227 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2228 * value in a window's extra memory.
2230 * The _hwnd_ parameter specifies the window. is the handle to a
2231 * window that has extra memory. The _newval_ parameter contains the
2232 * new attribute or extra memory value. If positive, the _offset_
2233 * parameter is the byte-addressed location in the window's extra
2234 * memory to set. If negative, _offset_ specifies the window
2235 * attribute to set, and should be one of the following values:
2237 * GWL_EXSTYLE The window's extended window style
2239 * GWL_STYLE The window's window style.
2241 * GWLP_WNDPROC Pointer to the window's window procedure.
2243 * GWLP_HINSTANCE The window's pplication instance handle.
2245 * GWLP_ID The window's identifier.
2247 * GWLP_USERDATA The window's user-specified data.
2249 * If the window is a dialog box, the _offset_ parameter can be one of
2250 * the following values:
2252 * DWLP_DLGPROC The address of the window's dialog box procedure.
2254 * DWLP_MSGRESULT The return value of a message
2255 * that the dialog box procedure processed.
2257 * DWLP_USER Application specific information.
2261 * If successful, returns the previous value located at _offset_. Otherwise,
2266 * Extra memory for a window class is specified by a nonzero cbWndExtra
2267 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2268 * time of class creation.
2270 * Using GWL_WNDPROC to set a new window procedure effectively creates
2271 * a window subclass. Use CallWindowProc() in the new windows procedure
2272 * to pass messages to the superclass's window procedure.
2274 * The user data is reserved for use by the application which created
2277 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2278 * instead, call the EnableWindow() function to change the window's
2281 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2282 * SetParent() instead.
2285 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2286 * it sends WM_STYLECHANGING before changing the settings
2287 * and WM_STYLECHANGED afterwards.
2288 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2290 LONG WINAPI SetWindowLongW(
2291 HWND hwnd, /* [in] window to alter */
2292 INT offset, /* [in] offset, in bytes, of location to alter */
2293 LONG newval /* [in] new value of location */
2295 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2299 /*******************************************************************
2300 * GetWindowTextA (USER32.@)
2302 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2306 if (WIN_IsCurrentProcess( hwnd ))
2307 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2309 /* when window belongs to other process, don't send a message */
2310 if (nMaxCount <= 0) return 0;
2311 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2312 get_server_window_text( hwnd, buffer, nMaxCount );
2313 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2314 lpString[nMaxCount-1] = 0;
2315 HeapFree( GetProcessHeap(), 0, buffer );
2316 return strlen(lpString);
2320 /*******************************************************************
2321 * InternalGetWindowText (USER32.@)
2323 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2327 if (nMaxCount <= 0) return 0;
2328 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2329 if (win != WND_OTHER_PROCESS)
2331 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2332 else lpString[0] = 0;
2333 WIN_ReleasePtr( win );
2337 get_server_window_text( hwnd, lpString, nMaxCount );
2339 return strlenW(lpString);
2343 /*******************************************************************
2344 * GetWindowTextW (USER32.@)
2346 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2348 if (WIN_IsCurrentProcess( hwnd ))
2349 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2351 /* when window belongs to other process, don't send a message */
2352 if (nMaxCount <= 0) return 0;
2353 get_server_window_text( hwnd, lpString, nMaxCount );
2354 return strlenW(lpString);
2358 /*******************************************************************
2359 * SetWindowText (USER32.@)
2360 * SetWindowTextA (USER32.@)
2362 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2364 if (is_broadcast(hwnd))
2366 SetLastError( ERROR_INVALID_PARAMETER );
2369 if (!WIN_IsCurrentProcess( hwnd ))
2371 FIXME( "cannot set text %s of other process window %p\n", debugstr_a(lpString), hwnd );
2372 SetLastError( ERROR_ACCESS_DENIED );
2375 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2379 /*******************************************************************
2380 * SetWindowTextW (USER32.@)
2382 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2384 if (is_broadcast(hwnd))
2386 SetLastError( ERROR_INVALID_PARAMETER );
2389 if (!WIN_IsCurrentProcess( hwnd ))
2391 FIXME( "cannot set text %s of other process window %p\n", debugstr_w(lpString), hwnd );
2392 SetLastError( ERROR_ACCESS_DENIED );
2395 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2399 /*******************************************************************
2400 * GetWindowTextLengthA (USER32.@)
2402 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2404 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2407 /*******************************************************************
2408 * GetWindowTextLengthW (USER32.@)
2410 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2412 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2416 /*******************************************************************
2417 * IsWindow (USER32.@)
2419 BOOL WINAPI IsWindow( HWND hwnd )
2424 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2426 if (ptr != WND_OTHER_PROCESS)
2428 WIN_ReleasePtr( ptr );
2432 /* check other processes */
2433 SERVER_START_REQ( get_window_info )
2436 ret = !wine_server_call_err( req );
2443 /***********************************************************************
2444 * GetWindowThreadProcessId (USER32.@)
2446 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2451 if (!(ptr = WIN_GetPtr( hwnd )))
2453 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2457 if (ptr != WND_OTHER_PROCESS)
2459 /* got a valid window */
2461 if (process) *process = GetCurrentProcessId();
2462 WIN_ReleasePtr( ptr );
2466 /* check other processes */
2467 SERVER_START_REQ( get_window_info )
2470 if (!wine_server_call_err( req ))
2472 tid = (DWORD)reply->tid;
2473 if (process) *process = (DWORD)reply->pid;
2481 /*****************************************************************
2482 * GetParent (USER32.@)
2484 HWND WINAPI GetParent( HWND hwnd )
2489 if (!(wndPtr = WIN_GetPtr( hwnd )))
2491 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2494 if (wndPtr == WND_OTHER_PROCESS)
2496 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2497 if (style & (WS_POPUP | WS_CHILD))
2499 SERVER_START_REQ( get_window_tree )
2502 if (!wine_server_call_err( req ))
2504 if (style & WS_POPUP) retvalue = reply->owner;
2505 else if (style & WS_CHILD) retvalue = reply->parent;
2513 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2514 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2515 WIN_ReleasePtr( wndPtr );
2521 /*****************************************************************
2522 * GetAncestor (USER32.@)
2524 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2527 HWND *list, ret = 0;
2532 if (!(win = WIN_GetPtr( hwnd )))
2534 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2537 if (win != WND_OTHER_PROCESS)
2540 WIN_ReleasePtr( win );
2542 else /* need to query the server */
2544 SERVER_START_REQ( get_window_tree )
2547 if (!wine_server_call_err( req )) ret = reply->parent;
2554 if (!(list = WIN_ListParents( hwnd ))) return 0;
2556 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2560 while (list[count]) count++;
2561 ret = list[count - 2]; /* get the one before the desktop */
2563 HeapFree( GetProcessHeap(), 0, list );
2567 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2570 HWND parent = GetParent( ret );
2580 /*****************************************************************
2581 * SetParent (USER32.@)
2583 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2586 HWND retvalue, full_handle;
2589 if (is_broadcast(hwnd) || is_broadcast(parent))
2591 SetLastError(ERROR_INVALID_PARAMETER);
2595 if (!parent) parent = GetDesktopWindow();
2596 else parent = WIN_GetFullHandle( parent );
2598 if (!IsWindow( parent ))
2600 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2604 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2605 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2609 if (USER_Driver.pSetParent)
2610 return USER_Driver.pSetParent( hwnd, parent );
2612 /* Windows hides the window first, then shows it again
2613 * including the WM_SHOWWINDOW messages and all */
2614 was_visible = ShowWindow( hwnd, SW_HIDE );
2616 if (!IsWindow( parent )) return 0;
2617 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2619 retvalue = wndPtr->parent; /* old parent */
2620 if (parent != retvalue)
2622 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2624 if (parent != GetDesktopWindow()) /* a child window */
2626 if (!(wndPtr->dwStyle & WS_CHILD))
2628 HMENU menu = (HMENU)SetWindowLongPtrW( hwnd, GWLP_ID, 0 );
2629 if (menu) DestroyMenu( menu );
2633 WIN_ReleasePtr( wndPtr );
2635 /* SetParent additionally needs to make hwnd the topmost window
2636 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2637 WM_WINDOWPOSCHANGED notification messages.
2639 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2640 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2641 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2642 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2647 /*******************************************************************
2648 * IsChild (USER32.@)
2650 BOOL WINAPI IsChild( HWND parent, HWND child )
2652 HWND *list = WIN_ListParents( child );
2656 if (!list) return FALSE;
2657 parent = WIN_GetFullHandle( parent );
2658 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2659 ret = (list[i] != 0);
2660 HeapFree( GetProcessHeap(), 0, list );
2665 /***********************************************************************
2666 * IsWindowVisible (USER32.@)
2668 BOOL WINAPI IsWindowVisible( HWND hwnd )
2674 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2675 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2676 for (i = 0; list[i]; i++)
2677 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2679 HeapFree( GetProcessHeap(), 0, list );
2684 /***********************************************************************
2685 * WIN_IsWindowDrawable
2687 * hwnd is drawable when it is visible, all parents are not
2688 * minimized, and it is itself not minimized unless we are
2689 * trying to draw its default class icon.
2691 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2696 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2698 if (!(style & WS_VISIBLE)) return FALSE;
2699 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2701 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2702 for (i = 0; list[i]; i++)
2703 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2706 HeapFree( GetProcessHeap(), 0, list );
2711 /*******************************************************************
2712 * GetTopWindow (USER32.@)
2714 HWND WINAPI GetTopWindow( HWND hwnd )
2716 if (!hwnd) hwnd = GetDesktopWindow();
2717 return GetWindow( hwnd, GW_CHILD );
2721 /*******************************************************************
2722 * GetWindow (USER32.@)
2724 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2728 if (rel == GW_OWNER) /* this one may be available locally */
2730 WND *wndPtr = WIN_GetPtr( hwnd );
2733 SetLastError( ERROR_INVALID_HANDLE );
2736 if (wndPtr != WND_OTHER_PROCESS)
2738 retval = wndPtr->owner;
2739 WIN_ReleasePtr( wndPtr );
2742 /* else fall through to server call */
2745 SERVER_START_REQ( get_window_tree )
2748 if (!wine_server_call_err( req ))
2753 retval = reply->first_sibling;
2756 retval = reply->last_sibling;
2759 retval = reply->next_sibling;
2762 retval = reply->prev_sibling;
2765 retval = reply->owner;
2768 retval = reply->first_child;
2778 /***********************************************************************
2779 * WIN_InternalShowOwnedPopups
2781 * Internal version of ShowOwnedPopups; Wine functions should use this
2782 * to avoid interfering with application calls to ShowOwnedPopups
2783 * and to make sure the application can't prevent showing/hiding.
2785 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2789 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2793 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2795 if (!win_array) return TRUE;
2798 * Show windows Lowest first, Highest last to preserve Z-Order
2800 while (win_array[count]) count++;
2801 while (--count >= 0)
2803 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2804 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2806 if (pWnd->dwStyle & WS_POPUP)
2810 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2811 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2814 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2816 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2817 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2822 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2823 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2824 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2827 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2829 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2830 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2831 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2835 WIN_ReleaseWndPtr( pWnd );
2837 HeapFree( GetProcessHeap(), 0, win_array );
2842 /*******************************************************************
2843 * ShowOwnedPopups (USER32.@)
2845 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2849 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2851 if (!win_array) return TRUE;
2853 while (win_array[count]) count++;
2854 while (--count >= 0)
2856 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2857 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2859 if (pWnd->dwStyle & WS_POPUP)
2863 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2865 /* In Windows, ShowOwnedPopups(TRUE) generates
2866 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2867 * regardless of the state of the owner
2869 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2870 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2875 if (IsWindowVisible(pWnd->hwndSelf))
2877 /* In Windows, ShowOwnedPopups(FALSE) generates
2878 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2879 * regardless of the state of the owner
2881 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2882 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2886 WIN_ReleaseWndPtr( pWnd );
2888 HeapFree( GetProcessHeap(), 0, win_array );
2893 /*******************************************************************
2894 * GetLastActivePopup (USER32.@)
2896 HWND WINAPI GetLastActivePopup( HWND hwnd )
2900 SERVER_START_REQ( get_window_info )
2903 if (!wine_server_call_err( req )) retval = reply->last_active;
2910 /*******************************************************************
2913 * Build an array of all parents of a given window, starting with
2914 * the immediate parent. The array must be freed with HeapFree.
2915 * Returns NULL if window is a top-level window.
2917 HWND *WIN_ListParents( HWND hwnd )
2920 HWND current, *list;
2921 int pos = 0, size = 16, count = 0;
2923 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2928 if (!(win = WIN_GetPtr( current ))) goto empty;
2929 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2930 list[pos] = win->parent;
2931 WIN_ReleasePtr( win );
2932 if (!(current = list[pos]))
2934 if (!pos) goto empty;
2937 if (++pos == size - 1)
2939 /* need to grow the list */
2940 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2941 if (!new_list) goto empty;
2947 /* at least one parent belongs to another process, have to query the server */
2952 SERVER_START_REQ( get_window_parents )
2955 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2956 if (!wine_server_call( req )) count = reply->count;
2959 if (!count) goto empty;
2965 HeapFree( GetProcessHeap(), 0, list );
2967 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2971 HeapFree( GetProcessHeap(), 0, list );
2976 /*******************************************************************
2979 * Build an array of the children of a given window. The array must be
2980 * freed with HeapFree. Returns NULL when no windows are found.
2982 HWND *WIN_ListChildren( HWND hwnd )
2984 return list_window_children( hwnd, 0, 0 );
2988 /*******************************************************************
2989 * EnumWindows (USER32.@)
2991 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2997 /* We have to build a list of all windows first, to avoid */
2998 /* unpleasant side-effects, for instance if the callback */
2999 /* function changes the Z-order of the windows. */
3001 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
3003 /* Now call the callback function for every window */
3005 iWndsLocks = WIN_SuspendWndsLock();
3006 for (i = 0; list[i]; i++)
3008 /* Make sure that the window still exists */
3009 if (!IsWindow( list[i] )) continue;
3010 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
3012 WIN_RestoreWndsLock(iWndsLocks);
3013 HeapFree( GetProcessHeap(), 0, list );
3018 /**********************************************************************
3019 * EnumThreadWindows (USER32.@)
3021 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
3026 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
3028 /* Now call the callback function for every window */
3030 iWndsLocks = WIN_SuspendWndsLock();
3031 for (i = 0; list[i]; i++)
3032 if (!func( list[i], lParam )) break;
3033 WIN_RestoreWndsLock(iWndsLocks);
3034 HeapFree( GetProcessHeap(), 0, list );
3039 /**********************************************************************
3040 * WIN_EnumChildWindows
3042 * Helper function for EnumChildWindows().
3044 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
3049 for ( ; *list; list++)
3051 /* Make sure that the window still exists */
3052 if (!IsWindow( *list )) continue;
3053 /* skip owned windows */
3054 if (GetWindow( *list, GW_OWNER )) continue;
3055 /* Build children list first */
3056 childList = WIN_ListChildren( *list );
3058 ret = func( *list, lParam );
3062 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
3063 HeapFree( GetProcessHeap(), 0, childList );
3065 if (!ret) return FALSE;
3071 /**********************************************************************
3072 * EnumChildWindows (USER32.@)
3074 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3079 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3080 iWndsLocks = WIN_SuspendWndsLock();
3081 WIN_EnumChildWindows( list, func, lParam );
3082 WIN_RestoreWndsLock(iWndsLocks);
3083 HeapFree( GetProcessHeap(), 0, list );
3088 /*******************************************************************
3089 * AnyPopup (USER.52)
3091 BOOL16 WINAPI AnyPopup16(void)
3097 /*******************************************************************
3098 * AnyPopup (USER32.@)
3100 BOOL WINAPI AnyPopup(void)
3104 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3106 if (!list) return FALSE;
3107 for (i = 0; list[i]; i++)
3109 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3111 retvalue = (list[i] != 0);
3112 HeapFree( GetProcessHeap(), 0, list );
3117 /*******************************************************************
3118 * FlashWindow (USER32.@)
3120 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3122 WND *wndPtr = WIN_FindWndPtr(hWnd);
3124 TRACE("%p\n", hWnd);
3126 if (!wndPtr) return FALSE;
3127 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3129 if (wndPtr->dwStyle & WS_MINIMIZE)
3131 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3133 HDC hDC = GetDC(hWnd);
3135 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM)hDC, 0 ))
3136 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3138 ReleaseDC( hWnd, hDC );
3139 wndPtr->flags |= WIN_NCACTIVATED;
3143 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3144 wndPtr->flags &= ~WIN_NCACTIVATED;
3146 WIN_ReleaseWndPtr(wndPtr);
3152 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3153 else wparam = (hWnd == GetForegroundWindow());
3155 WIN_ReleaseWndPtr(wndPtr);
3156 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3161 /*******************************************************************
3162 * FlashWindowEx (USER32.@)
3164 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3166 FIXME("%p\n", pfwi);
3170 /*******************************************************************
3171 * GetWindowContextHelpId (USER32.@)
3173 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3176 WND *wnd = WIN_FindWndPtr( hwnd );
3178 retval = wnd->helpContext;
3179 WIN_ReleaseWndPtr(wnd);
3184 /*******************************************************************
3185 * SetWindowContextHelpId (USER32.@)
3187 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3189 WND *wnd = WIN_FindWndPtr( hwnd );
3190 if (!wnd) return FALSE;
3191 wnd->helpContext = id;
3192 WIN_ReleaseWndPtr(wnd);
3197 /*******************************************************************
3198 * DragDetect (USER32.@)
3200 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3205 rect.left = pt.x - wDragWidth;
3206 rect.right = pt.x + wDragWidth;
3208 rect.top = pt.y - wDragHeight;
3209 rect.bottom = pt.y + wDragHeight;
3215 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3217 if( msg.message == WM_LBUTTONUP )
3222 if( msg.message == WM_MOUSEMOVE )
3225 tmp.x = LOWORD(msg.lParam);
3226 tmp.y = HIWORD(msg.lParam);
3227 if( !PtInRect( &rect, tmp ))
3239 /******************************************************************************
3240 * GetWindowModuleFileNameA (USER32.@)
3242 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3244 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3245 hwnd, lpszFileName, cchFileNameMax);
3249 /******************************************************************************
3250 * GetWindowModuleFileNameW (USER32.@)
3252 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3254 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3255 hwnd, lpszFileName, cchFileNameMax);
3259 /******************************************************************************
3260 * GetWindowInfo (USER32.@)
3262 * Note: tests show that Windows doesn't check cbSize of the structure.
3264 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3266 if (!pwi) return FALSE;
3267 if (!IsWindow(hwnd)) return FALSE;
3269 GetWindowRect(hwnd, &pwi->rcWindow);
3270 GetClientRect(hwnd, &pwi->rcClient);
3271 /* translate to screen coordinates */
3272 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3274 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3275 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3276 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3278 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3279 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3281 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3282 pwi->wCreatorVersion = 0x0400;
3287 /******************************************************************************
3288 * SwitchDesktop (USER32.@)
3290 * NOTES: Sets the current input or interactive desktop.
3292 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3294 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);