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)
50 /**********************************************************************/
53 static WND *pWndDesktop = NULL;
55 static WORD wDragWidth = 4;
56 static WORD wDragHeight= 3;
58 static void *user_handles[NB_USER_HANDLES];
60 /***********************************************************************
61 * create_window_handle
63 * Create a window handle with the server.
65 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom, unsigned int extra_bytes )
68 user_handle_t handle = 0;
70 WND *win = HeapAlloc( GetProcessHeap(), 0, sizeof(WND) + extra_bytes - sizeof(win->wExtra) );
72 if (!win) return NULL;
76 SERVER_START_REQ( create_window )
81 req->extra = extra_bytes;
82 if ((res = !wine_server_call_err( req ))) handle = reply->handle;
89 HeapFree( GetProcessHeap(), 0, win );
92 index = LOWORD(handle) - FIRST_USER_HANDLE;
93 assert( index < NB_USER_HANDLES );
94 user_handles[index] = win;
95 win->hwndSelf = handle;
96 win->dwMagic = WND_MAGIC;
102 /***********************************************************************
105 * Free a window handle.
107 static WND *free_window_handle( HWND hwnd )
110 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
112 if (index >= NB_USER_HANDLES) return NULL;
114 if ((ptr = user_handles[index]))
116 SERVER_START_REQ( destroy_window )
119 if (!wine_server_call_err( req ))
120 user_handles[index] = NULL;
127 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
132 /*******************************************************************
133 * list_window_children
135 * Build an array of the children of a given window. The array must be
136 * freed with HeapFree. Returns NULL when no windows are found.
138 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
147 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
149 SERVER_START_REQ( get_window_children )
154 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
155 if (!wine_server_call( req )) count = reply->count;
158 if (count && count < size)
163 HeapFree( GetProcessHeap(), 0, list );
165 size = count + 1; /* restart with a large enough buffer */
171 /*******************************************************************
174 static void send_parent_notify( HWND hwnd, UINT msg )
176 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) return;
177 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) return;
178 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
179 MAKEWPARAM( msg, GetWindowLongW( hwnd, GWL_ID )), (LPARAM)hwnd );
183 /*******************************************************************
184 * get_server_window_text
186 * Retrieve the window text from the server.
188 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
192 SERVER_START_REQ( get_window_text )
195 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
196 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
199 text[len / sizeof(WCHAR)] = 0;
203 /***********************************************************************
206 * Return a pointer to the WND structure if local to the process,
207 * or WND_OTHER_PROCESS if handle may be valid in other process.
208 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
210 WND *WIN_GetPtr( HWND hwnd )
213 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
215 if (index >= NB_USER_HANDLES) return NULL;
218 if ((ptr = user_handles[index]))
220 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
224 else ptr = WND_OTHER_PROCESS;
230 /***********************************************************************
231 * WIN_IsCurrentProcess
233 * Check whether a given window belongs to the current process (and return the full handle).
235 HWND WIN_IsCurrentProcess( HWND hwnd )
240 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
242 WIN_ReleasePtr( ptr );
247 /***********************************************************************
248 * WIN_IsCurrentThread
250 * Check whether a given window belongs to the current thread (and return the full handle).
252 HWND WIN_IsCurrentThread( HWND hwnd )
257 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
259 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
260 WIN_ReleasePtr( ptr );
266 /***********************************************************************
269 * Convert a 16-bit window handle to a full 32-bit handle.
271 HWND WIN_Handle32( HWND16 hwnd16 )
274 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
276 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
277 /* do sign extension for -2 and -3 */
278 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
280 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
282 if (ptr != WND_OTHER_PROCESS)
284 hwnd = ptr->hwndSelf;
285 WIN_ReleasePtr( ptr );
287 else /* may belong to another process */
289 SERVER_START_REQ( get_window_info )
292 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
300 /***********************************************************************
303 * Return a pointer to the WND structure corresponding to a HWND.
305 WND * WIN_FindWndPtr( HWND hwnd )
309 if (!hwnd) return NULL;
311 if ((ptr = WIN_GetPtr( hwnd )))
313 if (ptr != WND_OTHER_PROCESS)
315 /* increment destruction monitoring */
319 if (IsWindow( hwnd )) /* check other processes */
321 ERR( "window %p belongs to other process\n", hwnd );
322 /* DbgBreakPoint(); */
325 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
330 /***********************************************************************
333 * Release the pointer to the WND structure.
335 void WIN_ReleaseWndPtr(WND *wndPtr)
339 /* Decrement destruction monitoring value */
341 /* Check if it's time to release the memory */
342 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
345 free_window_handle( wndPtr->hwndSelf );
347 else if(wndPtr->irefCount < 0)
349 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
350 ERR("forgot a Lock on %p somewhere\n",wndPtr);
352 /* unlock all WND structures for thread safeness */
357 /***********************************************************************
360 * Remove a window from the siblings linked list.
362 void WIN_UnlinkWindow( HWND hwnd )
364 WIN_LinkWindow( hwnd, 0, 0 );
368 /***********************************************************************
371 * Insert a window into the siblings linked list.
372 * The window is inserted after the specified window, which can also
373 * be specified as HWND_TOP or HWND_BOTTOM.
374 * If parent is 0, window is unlinked from the tree.
376 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
378 WND *wndPtr = WIN_GetPtr( hwnd );
381 if (wndPtr == WND_OTHER_PROCESS)
383 if (IsWindow(hwnd)) ERR(" cannot link other process window %p\n", hwnd );
387 SERVER_START_REQ( link_window )
390 req->parent = parent;
391 req->previous = hwndInsertAfter;
392 if (!wine_server_call( req ))
394 if (reply->full_parent) wndPtr->parent = reply->full_parent;
399 WIN_ReleasePtr( wndPtr );
403 /***********************************************************************
406 * Change the owner of a window.
408 HWND WIN_SetOwner( HWND hwnd, HWND owner )
410 WND *win = WIN_GetPtr( hwnd );
414 if (win == WND_OTHER_PROCESS)
416 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
419 SERVER_START_REQ( set_window_owner )
423 if (!wine_server_call( req ))
425 win->owner = reply->full_owner;
426 ret = reply->prev_owner;
430 WIN_ReleasePtr( win );
435 /***********************************************************************
438 * Change the style of a window.
440 LONG WIN_SetStyle( HWND hwnd, LONG style )
444 WND *win = WIN_GetPtr( hwnd );
447 if (win == WND_OTHER_PROCESS)
450 ERR( "cannot set style %lx on other process window %p\n", style, hwnd );
453 if (style == win->dwStyle)
455 WIN_ReleasePtr( win );
458 SERVER_START_REQ( set_window_info )
461 req->flags = SET_WIN_STYLE;
463 req->extra_offset = -1;
464 if ((ok = !wine_server_call( req )))
466 ret = reply->old_style;
467 win->dwStyle = style;
471 WIN_ReleasePtr( win );
472 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret );
477 /***********************************************************************
480 * Change the extended style of a window.
482 LONG WIN_SetExStyle( HWND hwnd, LONG style )
485 WND *win = WIN_GetPtr( hwnd );
488 if (win == WND_OTHER_PROCESS)
491 ERR( "cannot set exstyle %lx on other process window %p\n", style, hwnd );
494 if (style == win->dwExStyle)
496 WIN_ReleasePtr( win );
499 SERVER_START_REQ( set_window_info )
502 req->flags = SET_WIN_EXSTYLE;
503 req->ex_style = style;
504 req->extra_offset = -1;
505 if (!wine_server_call( req ))
507 ret = reply->old_ex_style;
508 win->dwExStyle = style;
512 WIN_ReleasePtr( win );
517 /***********************************************************************
520 * Set the window and client rectangles.
522 void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient )
524 WND *win = WIN_GetPtr( hwnd );
528 if (win == WND_OTHER_PROCESS)
530 if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %p\n", hwnd );
533 SERVER_START_REQ( set_window_rectangles )
536 req->window.left = rectWindow->left;
537 req->window.top = rectWindow->top;
538 req->window.right = rectWindow->right;
539 req->window.bottom = rectWindow->bottom;
540 req->client.left = rectClient->left;
541 req->client.top = rectClient->top;
542 req->client.right = rectClient->right;
543 req->client.bottom = rectClient->bottom;
544 ret = !wine_server_call( req );
549 win->rectWindow = *rectWindow;
550 win->rectClient = *rectClient;
552 TRACE( "win %p window (%ld,%ld)-(%ld,%ld) client (%ld,%ld)-(%ld,%ld)\n", hwnd,
553 rectWindow->left, rectWindow->top, rectWindow->right, rectWindow->bottom,
554 rectClient->left, rectClient->top, rectClient->right, rectClient->bottom );
556 WIN_ReleasePtr( win );
560 /***********************************************************************
563 * Get the window and client rectangles.
565 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
567 WND *win = WIN_GetPtr( hwnd );
570 if (!win) return FALSE;
571 if (win == WND_OTHER_PROCESS)
573 SERVER_START_REQ( get_window_rectangles )
576 if ((ret = !wine_server_call( req )))
580 rectWindow->left = reply->window.left;
581 rectWindow->top = reply->window.top;
582 rectWindow->right = reply->window.right;
583 rectWindow->bottom = reply->window.bottom;
587 rectClient->left = reply->client.left;
588 rectClient->top = reply->client.top;
589 rectClient->right = reply->client.right;
590 rectClient->bottom = reply->client.bottom;
598 if (rectWindow) *rectWindow = win->rectWindow;
599 if (rectClient) *rectClient = win->rectClient;
600 WIN_ReleasePtr( win );
606 /***********************************************************************
609 * Destroy storage associated to a window. "Internals" p.358
611 LRESULT WIN_DestroyWindow( HWND hwnd )
616 TRACE("%p\n", hwnd );
618 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
620 ERR( "window doesn't belong to current thread\n" );
624 /* free child windows */
625 if ((list = WIN_ListChildren( hwnd )))
628 for (i = 0; list[i]; i++)
630 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
631 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
633 HeapFree( GetProcessHeap(), 0, list );
637 * Clear the update region to make sure no WM_PAINT messages will be
638 * generated for this window while processing the WM_NCDESTROY.
640 RedrawWindow( hwnd, NULL, 0,
641 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
644 * Send the WM_NCDESTROY to the window being destroyed.
646 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
648 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
650 WINPOS_CheckInternalPos( hwnd );
651 if( hwnd == GetCapture()) ReleaseCapture();
653 /* free resources associated with the window */
655 TIMER_RemoveWindowTimers( hwnd );
657 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
659 if (!(wndPtr->dwStyle & WS_CHILD))
661 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
662 if (menu) DestroyMenu( menu );
664 if (wndPtr->hSysMenu)
666 DestroyMenu( wndPtr->hSysMenu );
667 wndPtr->hSysMenu = 0;
669 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
670 USER_Driver.pDestroyWindow( hwnd );
671 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
672 CLASS_RemoveWindow( wndPtr->class );
673 wndPtr->class = NULL;
674 wndPtr->dwMagic = 0; /* Mark it as invalid */
675 WIN_ReleaseWndPtr( wndPtr );
679 /***********************************************************************
680 * WIN_DestroyThreadWindows
682 * Destroy all children of 'wnd' owned by the current thread.
683 * Return TRUE if something was done.
685 void WIN_DestroyThreadWindows( HWND hwnd )
690 if (!(list = WIN_ListChildren( hwnd ))) return;
691 for (i = 0; list[i]; i++)
693 if (WIN_IsCurrentThread( list[i] ))
694 DestroyWindow( list[i] );
696 WIN_DestroyThreadWindows( list[i] );
698 HeapFree( GetProcessHeap(), 0, list );
701 /***********************************************************************
702 * WIN_CreateDesktopWindow
704 * Create the desktop window.
706 BOOL WIN_CreateDesktopWindow(void)
708 struct tagCLASS *class;
717 TRACE("Creating desktop window\n");
719 if (!WINPOS_CreateInternalPosAtom() ||
720 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
721 &wndExtra, &winproc, &clsStyle, &dce )))
724 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM), wndExtra );
725 if (!pWndDesktop) return FALSE;
726 hwndDesktop = pWndDesktop->hwndSelf;
728 pWndDesktop->tid = 0; /* nobody owns the desktop */
729 pWndDesktop->parent = 0;
730 pWndDesktop->owner = 0;
731 pWndDesktop->class = class;
732 pWndDesktop->text = NULL;
733 pWndDesktop->hrgnUpdate = 0;
734 pWndDesktop->clsStyle = clsStyle;
735 pWndDesktop->dce = NULL;
736 pWndDesktop->pVScroll = NULL;
737 pWndDesktop->pHScroll = NULL;
738 pWndDesktop->helpContext = 0;
739 pWndDesktop->flags = 0;
740 pWndDesktop->hSysMenu = 0;
741 pWndDesktop->winproc = winproc;
742 pWndDesktop->cbWndExtra = wndExtra;
744 cs.lpCreateParams = NULL;
750 cs.cx = GetSystemMetrics( SM_CXSCREEN );
751 cs.cy = GetSystemMetrics( SM_CYSCREEN );
752 cs.style = pWndDesktop->dwStyle;
753 cs.dwExStyle = pWndDesktop->dwExStyle;
755 cs.lpszClass = DESKTOP_CLASS_ATOM;
757 SetRect( &rect, 0, 0, cs.cx, cs.cy );
758 WIN_SetRectangles( hwndDesktop, &rect, &rect );
760 SERVER_START_REQ( set_window_info )
762 req->handle = hwndDesktop;
763 req->flags = 0; /* don't set anything, just retrieve */
764 req->extra_offset = -1;
765 wine_server_call( req );
766 pWndDesktop->dwStyle = reply->old_style;
767 pWndDesktop->dwExStyle = reply->old_ex_style;
768 pWndDesktop->hInstance = (HINSTANCE)reply->old_instance;
769 pWndDesktop->userdata = (ULONG_PTR)reply->old_user_data;
770 pWndDesktop->wIDmenu = reply->old_id;
774 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE ))
776 WIN_ReleaseWndPtr( pWndDesktop );
780 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
781 WIN_ReleaseWndPtr( pWndDesktop );
786 /***********************************************************************
789 * Fix the coordinates - Helper for WIN_CreateWindowEx.
790 * returns default show mode in sw.
791 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
793 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
795 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
796 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
798 if (cs->style & (WS_CHILD | WS_POPUP))
800 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
801 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
803 else /* overlapped window */
807 GetStartupInfoA( &info );
809 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
811 /* Never believe Microsoft's documentation... CreateWindowEx doc says
812 * that if an overlapped window is created with WS_VISIBLE style bit
813 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
814 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
817 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
818 * 2) it does not ignore the y parameter as the docs claim; instead, it
819 * uses it as second parameter to ShowWindow() unless y is either
820 * CW_USEDEFAULT or CW_USEDEFAULT16.
822 * The fact that we didn't do 2) caused bogus windows pop up when wine
823 * was running apps that were using this obscure feature. Example -
824 * calc.exe that comes with Win98 (only Win98, it's different from
825 * the one that comes with Win95 and NT)
827 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
828 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
829 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
832 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
834 if (info.dwFlags & STARTF_USESIZE)
836 cs->cx = info.dwXSize;
837 cs->cy = info.dwYSize;
839 else /* if no other hint from the app, pick 3/4 of the screen real estate */
842 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
843 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
844 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
851 /* neither x nor cx are default. Check the y values .
852 * In the trace we see Outlook and Outlook Express using
853 * cy set to CW_USEDEFAULT when opening the address book.
855 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
857 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
858 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
859 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
864 /***********************************************************************
867 static void dump_window_styles( DWORD style, DWORD exstyle )
870 if(style & WS_POPUP) TRACE(" WS_POPUP");
871 if(style & WS_CHILD) TRACE(" WS_CHILD");
872 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
873 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
874 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
875 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
876 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
877 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
878 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
881 if(style & WS_BORDER) TRACE(" WS_BORDER");
882 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
884 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
885 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
886 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
887 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
888 if(style & WS_GROUP) TRACE(" WS_GROUP");
889 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
890 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
891 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
893 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
894 #define DUMPED_STYLES \
914 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
919 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
920 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
921 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
922 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
923 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
924 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
925 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
926 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
927 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
928 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
929 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
930 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
931 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
932 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
933 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
934 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
935 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
936 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
938 #define DUMPED_EX_STYLES \
939 (WS_EX_DLGMODALFRAME | \
941 WS_EX_NOPARENTNOTIFY | \
943 WS_EX_ACCEPTFILES | \
944 WS_EX_TRANSPARENT | \
949 WS_EX_CONTEXTHELP | \
952 WS_EX_LEFTSCROLLBAR | \
953 WS_EX_CONTROLPARENT | \
958 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
960 #undef DUMPED_EX_STYLES
964 /***********************************************************************
967 * Implementation of CreateWindowEx().
969 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
970 WINDOWPROCTYPE type )
973 struct tagCLASS *classPtr;
975 HWND hwnd, parent, owner;
980 BOOL unicode = (type == WIN_PROC_32W);
982 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
983 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
984 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
985 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
986 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
988 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
990 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
991 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
993 /* Find the parent window */
995 parent = GetDesktopWindow();
998 if (cs->hwndParent == HWND_MESSAGE)
1000 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
1001 * message window (style: WS_POPUP|WS_DISABLED)
1003 FIXME("Parent is HWND_MESSAGE\n");
1005 else if (cs->hwndParent)
1007 /* Make sure parent is valid */
1008 if (!IsWindow( cs->hwndParent ))
1010 WARN("Bad parent %p\n", cs->hwndParent );
1013 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1014 parent = WIN_GetFullHandle(cs->hwndParent);
1016 owner = GetAncestor( cs->hwndParent, GA_ROOT );
1018 else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1020 WARN("No parent for child window\n" );
1021 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1024 /* Find the window class */
1025 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
1026 &wndExtra, &winproc, &clsStyle, &dce )))
1028 WARN("Bad class '%s'\n", cs->lpszClass );
1032 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1034 /* Correct the window style - stage 1
1036 * These are patches that appear to affect both the style loaded into the
1037 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
1039 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1040 * why does the user get to set it?
1043 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1044 * tested for WS_POPUP
1046 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1047 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1048 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1049 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1051 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1053 /* Create the window structure */
1055 if (!(wndPtr = create_window_handle( parent, owner, classAtom, wndExtra )))
1057 TRACE("out of memory\n" );
1060 hwnd = wndPtr->hwndSelf;
1062 /* Fill the window structure */
1064 wndPtr->tid = GetCurrentThreadId();
1065 wndPtr->owner = owner;
1066 wndPtr->parent = parent;
1067 wndPtr->class = classPtr;
1068 wndPtr->winproc = winproc;
1069 wndPtr->hInstance = cs->hInstance;
1070 wndPtr->text = NULL;
1071 wndPtr->hrgnUpdate = 0;
1072 wndPtr->hrgnWnd = 0;
1073 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1074 wndPtr->dwExStyle = cs->dwExStyle;
1075 wndPtr->clsStyle = clsStyle;
1076 wndPtr->wIDmenu = 0;
1077 wndPtr->helpContext = 0;
1078 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1079 wndPtr->pVScroll = NULL;
1080 wndPtr->pHScroll = NULL;
1081 wndPtr->userdata = 0;
1082 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU) ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1083 wndPtr->cbWndExtra = wndExtra;
1085 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
1087 /* Correct the window style - stage 2 */
1089 if (!(cs->style & WS_CHILD))
1091 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1092 if (!(cs->style & WS_POPUP))
1094 wndPtr->dwStyle |= WS_CAPTION;
1095 wndPtr->flags |= WIN_NEED_SIZE;
1098 SERVER_START_REQ( set_window_info )
1101 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1102 req->style = wndPtr->dwStyle;
1103 req->ex_style = wndPtr->dwExStyle;
1104 req->instance = (void *)wndPtr->hInstance;
1105 req->extra_offset = -1;
1106 wine_server_call( req );
1110 /* Get class or window DC if needed */
1112 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1113 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
1114 else wndPtr->dce = NULL;
1116 /* Set the window menu */
1118 if (((wndPtr->dwStyle & (WS_CAPTION|WS_CHILD)) == WS_CAPTION) ||
1119 (wndPtr->dwExStyle & WS_EX_APPWINDOW))
1121 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
1124 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1127 if (HIWORD(cs->hInstance))
1128 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1130 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1132 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
1136 else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
1137 WIN_ReleaseWndPtr( wndPtr );
1139 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
1141 WIN_DestroyWindow( hwnd );
1145 /* Notify the parent window only */
1147 send_parent_notify( hwnd, WM_CREATE );
1148 if (!IsWindow( hwnd )) return 0;
1150 if (cs->style & WS_VISIBLE)
1152 /* in case WS_VISIBLE got set in the meantime */
1153 if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0;
1154 WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
1155 WIN_ReleasePtr( wndPtr );
1156 ShowWindow( hwnd, sw );
1159 /* Call WH_SHELL hook */
1161 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1162 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1164 TRACE("created window %p\n", hwnd);
1169 /***********************************************************************
1170 * CreateWindow (USER.41)
1172 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1173 DWORD style, INT16 x, INT16 y, INT16 width,
1174 INT16 height, HWND16 parent, HMENU16 menu,
1175 HINSTANCE16 instance, LPVOID data )
1177 return CreateWindowEx16( 0, className, windowName, style,
1178 x, y, width, height, parent, menu, instance, data );
1182 /***********************************************************************
1183 * CreateWindowEx (USER.452)
1185 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1186 LPCSTR windowName, DWORD style, INT16 x,
1187 INT16 y, INT16 width, INT16 height,
1188 HWND16 parent, HMENU16 menu,
1189 HINSTANCE16 instance, LPVOID data )
1195 /* Find the class atom */
1197 if (HIWORD(className))
1199 if (!(classAtom = GlobalFindAtomA( className )))
1201 ERR( "bad class name %s\n", debugstr_a(className) );
1207 classAtom = LOWORD(className);
1208 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1210 ERR( "bad atom %x\n", classAtom);
1216 /* Fix the coordinates */
1218 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1219 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1220 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1221 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1223 /* Create the window */
1225 cs.lpCreateParams = data;
1226 cs.hInstance = HINSTANCE_32(instance);
1227 cs.hMenu = HMENU_32(menu);
1228 cs.hwndParent = WIN_Handle32( parent );
1230 cs.lpszName = windowName;
1231 cs.lpszClass = className;
1232 cs.dwExStyle = exStyle;
1234 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1238 /***********************************************************************
1239 * CreateWindowExA (USER32.@)
1241 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1242 LPCSTR windowName, DWORD style, INT x,
1243 INT y, INT width, INT height,
1244 HWND parent, HMENU menu,
1245 HINSTANCE instance, LPVOID data )
1252 instance=GetModuleHandleA(NULL);
1254 if(exStyle & WS_EX_MDICHILD)
1255 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1257 /* Find the class atom */
1259 if (HIWORD(className))
1261 if (!(classAtom = GlobalFindAtomA( className )))
1263 ERR( "bad class name %s\n", debugstr_a(className) );
1269 classAtom = LOWORD(className);
1270 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1272 ERR( "bad atom %x\n", classAtom);
1278 /* Create the window */
1280 cs.lpCreateParams = data;
1281 cs.hInstance = instance;
1283 cs.hwndParent = parent;
1289 cs.lpszName = windowName;
1290 cs.lpszClass = className;
1291 cs.dwExStyle = exStyle;
1293 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1297 /***********************************************************************
1298 * CreateWindowExW (USER32.@)
1300 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1301 LPCWSTR windowName, DWORD style, INT x,
1302 INT y, INT width, INT height,
1303 HWND parent, HMENU menu,
1304 HINSTANCE instance, LPVOID data )
1311 instance=GetModuleHandleW(NULL);
1313 if(exStyle & WS_EX_MDICHILD)
1314 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1316 /* Find the class atom */
1318 if (HIWORD(className))
1320 if (!(classAtom = GlobalFindAtomW( className )))
1322 ERR( "bad class name %s\n", debugstr_w(className) );
1328 classAtom = LOWORD(className);
1329 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1331 ERR( "bad atom %x\n", classAtom);
1337 /* Create the window */
1339 cs.lpCreateParams = data;
1340 cs.hInstance = instance;
1342 cs.hwndParent = parent;
1348 cs.lpszName = windowName;
1349 cs.lpszClass = className;
1350 cs.dwExStyle = exStyle;
1352 /* Note: we rely on the fact that CREATESTRUCTA and */
1353 /* CREATESTRUCTW have the same layout. */
1354 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1358 /***********************************************************************
1359 * WIN_SendDestroyMsg
1361 static void WIN_SendDestroyMsg( HWND hwnd )
1365 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1367 if (hwnd == info.hwndCaret) DestroyCaret();
1369 if (USER_Driver.pResetSelectionOwner)
1370 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1373 * Send the WM_DESTROY to the window.
1375 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1378 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1379 * make sure that the window still exists when we come back.
1386 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1388 /* start from the end (FIXME: is this needed?) */
1389 for (i = 0; pWndArray[i]; i++) ;
1393 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1395 HeapFree( GetProcessHeap(), 0, pWndArray );
1398 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1402 /***********************************************************************
1403 * DestroyWindow (USER32.@)
1405 BOOL WINAPI DestroyWindow( HWND hwnd )
1410 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1412 SetLastError( ERROR_ACCESS_DENIED );
1416 TRACE("(%p)\n", hwnd);
1418 /* Look whether the focus is within the tree of windows we will
1422 if (h == hwnd || IsChild( hwnd, h ))
1424 HWND parent = GetAncestor( hwnd, GA_PARENT );
1425 if (parent == GetDesktopWindow()) parent = 0;
1431 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1433 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1437 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1438 send_parent_notify( hwnd, WM_DESTROY );
1440 else if (!GetWindow( hwnd, GW_OWNER ))
1442 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1443 /* FIXME: clean up palette - see "Internals" p.352 */
1446 if (!IsWindow(hwnd)) return TRUE;
1448 if (USER_Driver.pResetSelectionOwner)
1449 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1451 /* Hide the window */
1453 if (!ShowWindow( hwnd, SW_HIDE ))
1455 if (hwnd == GetActiveWindow()) WINPOS_ActivateOtherWindow( hwnd );
1457 if (!IsWindow(hwnd)) return TRUE;
1459 /* Recursively destroy owned windows */
1466 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1469 for (i = 0; list[i]; i++)
1471 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1472 if (WIN_IsCurrentThread( list[i] ))
1474 DestroyWindow( list[i] );
1478 WIN_SetOwner( list[i], 0 );
1480 HeapFree( GetProcessHeap(), 0, list );
1482 if (!got_one) break;
1486 /* Send destroy messages */
1488 WIN_SendDestroyMsg( hwnd );
1489 if (!IsWindow( hwnd )) return TRUE;
1491 if (GetClipboardOwner() == hwnd)
1492 CLIPBOARD_ReleaseOwner();
1494 /* Unlink now so we won't bother with the children later on */
1496 WIN_UnlinkWindow( hwnd );
1498 /* Destroy the window storage */
1500 WIN_DestroyWindow( hwnd );
1505 /***********************************************************************
1506 * CloseWindow (USER32.@)
1508 BOOL WINAPI CloseWindow( HWND hwnd )
1510 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1511 ShowWindow( hwnd, SW_MINIMIZE );
1516 /***********************************************************************
1517 * OpenIcon (USER32.@)
1519 BOOL WINAPI OpenIcon( HWND hwnd )
1521 if (!IsIconic( hwnd )) return FALSE;
1522 ShowWindow( hwnd, SW_SHOWNORMAL );
1527 /***********************************************************************
1530 * Implementation of FindWindow() and FindWindowEx().
1532 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1537 WCHAR *buffer = NULL;
1539 if (!parent) parent = GetDesktopWindow();
1542 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1543 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1546 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1550 child = WIN_GetFullHandle( child );
1551 while (list[i] && list[i] != child) i++;
1552 if (!list[i]) goto done;
1553 i++; /* start from next window */
1560 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1567 if (list) HeapFree( GetProcessHeap(), 0, list );
1568 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1574 /***********************************************************************
1575 * FindWindowA (USER32.@)
1577 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1579 HWND ret = FindWindowExA( 0, 0, className, title );
1580 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1585 /***********************************************************************
1586 * FindWindowExA (USER32.@)
1588 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1589 LPCSTR className, LPCSTR title )
1598 /* If the atom doesn't exist, then no class */
1599 /* with this name exists either. */
1600 if (!(atom = GlobalFindAtomA( className )))
1602 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1606 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1608 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1609 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1610 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1611 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1612 HeapFree( GetProcessHeap(), 0, buffer );
1617 /***********************************************************************
1618 * FindWindowExW (USER32.@)
1620 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1621 LPCWSTR className, LPCWSTR title )
1627 /* If the atom doesn't exist, then no class */
1628 /* with this name exists either. */
1629 if (!(atom = GlobalFindAtomW( className )))
1631 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1635 return WIN_FindWindow( parent, child, atom, title );
1639 /***********************************************************************
1640 * FindWindowW (USER32.@)
1642 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1644 return FindWindowExW( 0, 0, className, title );
1648 /**********************************************************************
1649 * GetDesktopWindow (USER32.@)
1651 HWND WINAPI GetDesktopWindow(void)
1653 if (pWndDesktop) return pWndDesktop->hwndSelf;
1654 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" );
1660 /*******************************************************************
1661 * EnableWindow (USER32.@)
1663 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1670 if (is_broadcast(hwnd))
1672 SetLastError( ERROR_INVALID_PARAMETER );
1676 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1677 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1681 TRACE("( %p, %d )\n", hwnd, enable);
1683 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1684 style = wndPtr->dwStyle;
1685 retvalue = ((style & WS_DISABLED) != 0);
1686 WIN_ReleasePtr( wndPtr );
1688 if (enable && retvalue)
1690 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1691 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1693 else if (!enable && !retvalue)
1695 HWND focus_wnd, capture_wnd;
1697 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1699 WIN_SetStyle( hwnd, style | WS_DISABLED );
1701 focus_wnd = GetFocus();
1702 if (hwnd == focus_wnd || IsChild(hwnd, focus_wnd))
1703 SetFocus( 0 ); /* A disabled window can't have the focus */
1705 capture_wnd = GetCapture();
1706 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1707 ReleaseCapture(); /* A disabled window can't capture the mouse */
1709 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1715 /***********************************************************************
1716 * IsWindowEnabled (USER32.@)
1718 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1720 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1724 /***********************************************************************
1725 * IsWindowUnicode (USER32.@)
1727 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1732 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1733 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1734 WIN_ReleaseWndPtr(wndPtr);
1739 /**********************************************************************
1740 * GetWindowWord (USER32.@)
1742 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1747 WND *wndPtr = WIN_GetPtr( hwnd );
1750 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1753 if (wndPtr == WND_OTHER_PROCESS)
1755 if (IsWindow( hwnd ))
1756 FIXME( "(%d) not supported yet on other process window %p\n", offset, hwnd );
1757 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1760 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1762 WARN("Invalid offset %d\n", offset );
1763 SetLastError( ERROR_INVALID_INDEX );
1765 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1766 WIN_ReleasePtr( wndPtr );
1772 case GWL_HWNDPARENT:
1773 return GetWindowLongW( hwnd, offset );
1777 LONG ret = GetWindowLongW( hwnd, offset );
1779 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1783 WARN("Invalid offset %d\n", offset );
1789 /**********************************************************************
1790 * SetWindowWord (USER32.@)
1792 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1801 case GWL_HWNDPARENT:
1802 return SetWindowLongW( hwnd, offset, (UINT)newval );
1806 WARN("Invalid offset %d\n", offset );
1807 SetLastError( ERROR_INVALID_INDEX );
1812 wndPtr = WIN_GetPtr( hwnd );
1813 if (wndPtr == WND_OTHER_PROCESS)
1816 FIXME( "set %d <- %x not supported yet on other process window %p\n",
1817 offset, newval, hwnd );
1822 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1826 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1828 WARN("Invalid offset %d\n", offset );
1829 WIN_ReleasePtr(wndPtr);
1830 SetLastError( ERROR_INVALID_INDEX );
1834 SERVER_START_REQ( set_window_info )
1837 req->flags = SET_WIN_EXTRAWORD;
1838 req->extra_offset = offset;
1839 req->extra_value = newval;
1840 if (!wine_server_call_err( req ))
1842 WORD *ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1848 WIN_ReleasePtr( wndPtr );
1853 /**********************************************************************
1856 * Helper function for GetWindowLong().
1858 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1863 if (offset == GWL_HWNDPARENT)
1865 HWND parent = GetAncestor( hwnd, GA_PARENT );
1866 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1867 return (LONG)parent;
1870 if (!(wndPtr = WIN_GetPtr( hwnd )))
1872 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1876 if (wndPtr == WND_OTHER_PROCESS)
1878 if (offset == GWL_WNDPROC)
1880 SetLastError( ERROR_ACCESS_DENIED );
1883 SERVER_START_REQ( set_window_info )
1886 req->flags = 0; /* don't set anything, just retrieve */
1887 req->extra_offset = (offset >= 0) ? offset : -1;
1888 if (!wine_server_call_err( req ))
1892 case GWL_STYLE: retvalue = reply->old_style; break;
1893 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1894 case GWL_ID: retvalue = reply->old_id; break;
1895 case GWL_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1896 case GWL_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1898 if (offset >= 0) retvalue = reply->old_extra_value;
1899 else SetLastError( ERROR_INVALID_INDEX );
1903 else if (offset >= 0 && GetLastError() == ERROR_INVALID_PARAMETER)
1904 SetLastError( ERROR_INVALID_INDEX );
1910 /* now we have a valid wndPtr */
1914 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1917 * Some programs try to access last element from 16 bit
1918 * code using illegal offset value. Hopefully this is
1919 * what those programs really expect.
1921 if (type == WIN_PROC_16 &&
1922 wndPtr->cbWndExtra >= 4 &&
1923 offset == wndPtr->cbWndExtra - sizeof(WORD))
1925 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1927 ERR( "- replaced invalid offset %d with %d\n",
1930 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset2);
1931 WIN_ReleasePtr( wndPtr );
1934 WARN("Invalid offset %d\n", offset );
1935 WIN_ReleasePtr( wndPtr );
1936 SetLastError( ERROR_INVALID_INDEX );
1939 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1940 /* Special case for dialog window procedure */
1941 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1942 retvalue = (LONG)WINPROC_GetProc( (WNDPROC)retvalue, type );
1943 WIN_ReleasePtr( wndPtr );
1949 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
1950 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1951 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1952 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
1953 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
1954 case GWL_HINSTANCE: retvalue = (LONG)wndPtr->hInstance; break;
1956 WARN("Unknown offset %d\n", offset );
1957 SetLastError( ERROR_INVALID_INDEX );
1960 WIN_ReleasePtr(wndPtr);
1965 /**********************************************************************
1968 * Helper function for SetWindowLong().
1970 * 0 is the failure code. However, in the case of failure SetLastError
1971 * must be set to distinguish between a 0 return value and a failure.
1973 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1974 WINDOWPROCTYPE type )
1981 TRACE( "%p %d %lx %x\n", hwnd, offset, newval, type );
1983 if (is_broadcast(hwnd))
1985 SetLastError( ERROR_INVALID_PARAMETER );
1988 if (!WIN_IsCurrentProcess( hwnd ))
1990 if (offset == GWL_WNDPROC)
1992 SetLastError( ERROR_ACCESS_DENIED );
1995 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1998 wndPtr = WIN_GetPtr( hwnd );
1999 if (wndPtr->hwndSelf == GetDesktopWindow())
2001 /* can't change anything on the desktop window */
2002 WIN_ReleasePtr( wndPtr );
2003 SetLastError( ERROR_ACCESS_DENIED );
2007 /* first some special cases */
2013 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
2014 style.styleNew = newval;
2015 WIN_ReleasePtr( wndPtr );
2016 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2017 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2018 newval = style.styleNew;
2020 case GWL_HWNDPARENT:
2021 if (wndPtr->parent == GetDesktopWindow())
2023 WIN_ReleasePtr( wndPtr );
2024 return (LONG)WIN_SetOwner( hwnd, (HWND)newval );
2028 WIN_ReleasePtr( wndPtr );
2029 return (LONG)SetParent( hwnd, (HWND)newval );
2032 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2033 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC)newval, type, WIN_PROC_WINDOW );
2034 WIN_ReleasePtr( wndPtr );
2041 if ((wndPtr->cbWndExtra + sizeof(LONG) >= DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2043 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWL_DLGPROC);
2044 retval = (LONG)WINPROC_GetProc( *ptr, type );
2045 WINPROC_SetProc( ptr, (WNDPROC)newval, type, WIN_PROC_WINDOW );
2046 WIN_ReleasePtr( wndPtr );
2051 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2053 WARN("Invalid offset %d\n", offset );
2054 WIN_ReleasePtr( wndPtr );
2055 SetLastError( ERROR_INVALID_INDEX );
2060 LONG *ptr = (LONG *)((char *)wndPtr->wExtra + offset);
2061 if (*ptr == newval) /* already set to the same value */
2063 WIN_ReleasePtr( wndPtr );
2070 SERVER_START_REQ( set_window_info )
2073 req->extra_offset = -1;
2077 req->flags = SET_WIN_STYLE;
2078 req->style = newval;
2081 req->flags = SET_WIN_EXSTYLE;
2082 req->ex_style = newval;
2085 req->flags = SET_WIN_ID;
2089 req->flags = SET_WIN_INSTANCE;
2090 req->instance = (void *)newval;
2093 req->flags = SET_WIN_USERDATA;
2094 req->user_data = (void *)newval;
2097 req->flags = SET_WIN_EXTRALONG;
2098 req->extra_offset = offset;
2099 req->extra_value = newval;
2101 if ((ok = !wine_server_call_err( req )))
2106 wndPtr->dwStyle = newval;
2107 retval = reply->old_style;
2110 wndPtr->dwExStyle = newval;
2111 retval = reply->old_ex_style;
2114 wndPtr->wIDmenu = newval;
2115 retval = reply->old_id;
2118 wndPtr->hInstance = (HINSTANCE)newval;
2119 retval = (ULONG_PTR)reply->old_instance;
2122 wndPtr->userdata = newval;
2123 retval = (ULONG_PTR)reply->old_user_data;
2127 LONG *ptr = (LONG *)((char *)wndPtr->wExtra + offset);
2136 WIN_ReleasePtr( wndPtr );
2140 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2141 USER_Driver.pSetWindowStyle( hwnd, retval );
2143 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2144 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2150 /**********************************************************************
2151 * GetWindowLong (USER.135)
2153 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2155 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2159 /**********************************************************************
2160 * GetWindowLongA (USER32.@)
2162 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2164 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2168 /**********************************************************************
2169 * GetWindowLongW (USER32.@)
2171 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2173 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2177 /**********************************************************************
2178 * SetWindowLong (USER.136)
2180 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2182 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2186 /**********************************************************************
2187 * SetWindowLongA (USER32.@)
2189 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2191 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2195 /**********************************************************************
2196 * SetWindowLongW (USER32.@) Set window attribute
2198 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2199 * value in a window's extra memory.
2201 * The _hwnd_ parameter specifies the window. is the handle to a
2202 * window that has extra memory. The _newval_ parameter contains the
2203 * new attribute or extra memory value. If positive, the _offset_
2204 * parameter is the byte-addressed location in the window's extra
2205 * memory to set. If negative, _offset_ specifies the window
2206 * attribute to set, and should be one of the following values:
2208 * GWL_EXSTYLE The window's extended window style
2210 * GWL_STYLE The window's window style.
2212 * GWL_WNDPROC Pointer to the window's window procedure.
2214 * GWL_HINSTANCE The window's pplication instance handle.
2216 * GWL_ID The window's identifier.
2218 * GWL_USERDATA The window's user-specified data.
2220 * If the window is a dialog box, the _offset_ parameter can be one of
2221 * the following values:
2223 * DWL_DLGPROC The address of the window's dialog box procedure.
2225 * DWL_MSGRESULT The return value of a message
2226 * that the dialog box procedure processed.
2228 * DWL_USER Application specific information.
2232 * If successful, returns the previous value located at _offset_. Otherwise,
2237 * Extra memory for a window class is specified by a nonzero cbWndExtra
2238 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2239 * time of class creation.
2241 * Using GWL_WNDPROC to set a new window procedure effectively creates
2242 * a window subclass. Use CallWindowProc() in the new windows procedure
2243 * to pass messages to the superclass's window procedure.
2245 * The user data is reserved for use by the application which created
2248 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2249 * instead, call the EnableWindow() function to change the window's
2252 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2253 * SetParent() instead.
2256 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2257 * it sends WM_STYLECHANGING before changing the settings
2258 * and WM_STYLECHANGED afterwards.
2259 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2261 LONG WINAPI SetWindowLongW(
2262 HWND hwnd, /* [in] window to alter */
2263 INT offset, /* [in] offset, in bytes, of location to alter */
2264 LONG newval /* [in] new value of location */
2266 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2270 /*******************************************************************
2271 * GetWindowTextA (USER32.@)
2273 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2277 if (WIN_IsCurrentProcess( hwnd ))
2278 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2280 /* when window belongs to other process, don't send a message */
2281 if (nMaxCount <= 0) return 0;
2282 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2283 get_server_window_text( hwnd, buffer, nMaxCount );
2284 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2285 lpString[nMaxCount-1] = 0;
2286 HeapFree( GetProcessHeap(), 0, buffer );
2287 return strlen(lpString);
2291 /*******************************************************************
2292 * InternalGetWindowText (USER32.@)
2294 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2298 if (nMaxCount <= 0) return 0;
2299 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2300 if (win != WND_OTHER_PROCESS)
2302 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2303 else lpString[0] = 0;
2304 WIN_ReleasePtr( win );
2308 get_server_window_text( hwnd, lpString, nMaxCount );
2310 return strlenW(lpString);
2314 /*******************************************************************
2315 * GetWindowTextW (USER32.@)
2317 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2319 if (WIN_IsCurrentProcess( hwnd ))
2320 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2322 /* when window belongs to other process, don't send a message */
2323 if (nMaxCount <= 0) return 0;
2324 get_server_window_text( hwnd, lpString, nMaxCount );
2325 return strlenW(lpString);
2329 /*******************************************************************
2330 * SetWindowText (USER32.@)
2331 * SetWindowTextA (USER32.@)
2333 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2335 if (is_broadcast(hwnd))
2337 SetLastError( ERROR_INVALID_PARAMETER );
2340 if (!WIN_IsCurrentProcess( hwnd ))
2342 FIXME( "cannot set text %s of other process window %p\n", debugstr_a(lpString), hwnd );
2343 SetLastError( ERROR_ACCESS_DENIED );
2346 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2350 /*******************************************************************
2351 * SetWindowTextW (USER32.@)
2353 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2355 if (is_broadcast(hwnd))
2357 SetLastError( ERROR_INVALID_PARAMETER );
2360 if (!WIN_IsCurrentProcess( hwnd ))
2362 FIXME( "cannot set text %s of other process window %p\n", debugstr_w(lpString), hwnd );
2363 SetLastError( ERROR_ACCESS_DENIED );
2366 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2370 /*******************************************************************
2371 * GetWindowTextLengthA (USER32.@)
2373 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2375 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2378 /*******************************************************************
2379 * GetWindowTextLengthW (USER32.@)
2381 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2383 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2387 /*******************************************************************
2388 * IsWindow (USER32.@)
2390 BOOL WINAPI IsWindow( HWND hwnd )
2395 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2397 if (ptr != WND_OTHER_PROCESS)
2399 WIN_ReleasePtr( ptr );
2403 /* check other processes */
2404 SERVER_START_REQ( get_window_info )
2407 ret = !wine_server_call_err( req );
2414 /***********************************************************************
2415 * GetWindowThreadProcessId (USER32.@)
2417 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2422 if (!(ptr = WIN_GetPtr( hwnd )))
2424 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2428 if (ptr != WND_OTHER_PROCESS)
2430 /* got a valid window */
2432 if (process) *process = GetCurrentProcessId();
2433 WIN_ReleasePtr( ptr );
2437 /* check other processes */
2438 SERVER_START_REQ( get_window_info )
2441 if (!wine_server_call_err( req ))
2443 tid = (DWORD)reply->tid;
2444 if (process) *process = (DWORD)reply->pid;
2452 /*****************************************************************
2453 * GetParent (USER32.@)
2455 HWND WINAPI GetParent( HWND hwnd )
2460 if (!(wndPtr = WIN_GetPtr( hwnd )))
2462 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2465 if (wndPtr == WND_OTHER_PROCESS)
2467 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2468 if (style & (WS_POPUP | WS_CHILD))
2470 SERVER_START_REQ( get_window_tree )
2473 if (!wine_server_call_err( req ))
2475 if (style & WS_POPUP) retvalue = reply->owner;
2476 else if (style & WS_CHILD) retvalue = reply->parent;
2484 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2485 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2486 WIN_ReleasePtr( wndPtr );
2492 /*****************************************************************
2493 * GetAncestor (USER32.@)
2495 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2498 HWND *list, ret = 0;
2503 if (!(win = WIN_GetPtr( hwnd )))
2505 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2508 if (win != WND_OTHER_PROCESS)
2511 WIN_ReleasePtr( win );
2513 else /* need to query the server */
2515 SERVER_START_REQ( get_window_tree )
2518 if (!wine_server_call_err( req )) ret = reply->parent;
2525 if (!(list = WIN_ListParents( hwnd ))) return 0;
2527 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2531 while (list[count]) count++;
2532 ret = list[count - 2]; /* get the one before the desktop */
2534 HeapFree( GetProcessHeap(), 0, list );
2538 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2541 HWND parent = GetParent( ret );
2551 /*****************************************************************
2552 * SetParent (USER32.@)
2554 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2557 HWND retvalue, full_handle;
2560 if (is_broadcast(hwnd) || is_broadcast(parent))
2562 SetLastError(ERROR_INVALID_PARAMETER);
2566 if (!parent) parent = GetDesktopWindow();
2567 else parent = WIN_GetFullHandle( parent );
2569 if (!IsWindow( parent ))
2571 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2575 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2576 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2580 if (USER_Driver.pSetParent)
2581 return USER_Driver.pSetParent( hwnd, parent );
2583 /* Windows hides the window first, then shows it again
2584 * including the WM_SHOWWINDOW messages and all */
2585 was_visible = ShowWindow( hwnd, SW_HIDE );
2587 if (!IsWindow( parent )) return 0;
2588 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2590 retvalue = wndPtr->parent; /* old parent */
2591 if (parent != retvalue)
2593 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2595 if (parent != GetDesktopWindow()) /* a child window */
2597 if (!(wndPtr->dwStyle & WS_CHILD))
2599 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2600 if (menu) DestroyMenu( menu );
2604 WIN_ReleasePtr( wndPtr );
2606 /* SetParent additionally needs to make hwnd the topmost window
2607 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2608 WM_WINDOWPOSCHANGED notification messages.
2610 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2611 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2612 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2613 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2618 /*******************************************************************
2619 * IsChild (USER32.@)
2621 BOOL WINAPI IsChild( HWND parent, HWND child )
2623 HWND *list = WIN_ListParents( child );
2627 if (!list) return FALSE;
2628 parent = WIN_GetFullHandle( parent );
2629 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2630 ret = (list[i] != 0);
2631 HeapFree( GetProcessHeap(), 0, list );
2636 /***********************************************************************
2637 * IsWindowVisible (USER32.@)
2639 BOOL WINAPI IsWindowVisible( HWND hwnd )
2645 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2646 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2647 for (i = 0; list[i]; i++)
2648 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2650 HeapFree( GetProcessHeap(), 0, list );
2655 /***********************************************************************
2656 * WIN_IsWindowDrawable
2658 * hwnd is drawable when it is visible, all parents are not
2659 * minimized, and it is itself not minimized unless we are
2660 * trying to draw its default class icon.
2662 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2667 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2669 if (!(style & WS_VISIBLE)) return FALSE;
2670 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2672 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2673 for (i = 0; list[i]; i++)
2674 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2677 HeapFree( GetProcessHeap(), 0, list );
2682 /*******************************************************************
2683 * GetTopWindow (USER32.@)
2685 HWND WINAPI GetTopWindow( HWND hwnd )
2687 if (!hwnd) hwnd = GetDesktopWindow();
2688 return GetWindow( hwnd, GW_CHILD );
2692 /*******************************************************************
2693 * GetWindow (USER32.@)
2695 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2699 if (rel == GW_OWNER) /* this one may be available locally */
2701 WND *wndPtr = WIN_GetPtr( hwnd );
2704 SetLastError( ERROR_INVALID_HANDLE );
2707 if (wndPtr != WND_OTHER_PROCESS)
2709 retval = wndPtr->owner;
2710 WIN_ReleasePtr( wndPtr );
2713 /* else fall through to server call */
2716 SERVER_START_REQ( get_window_tree )
2719 if (!wine_server_call_err( req ))
2724 retval = reply->first_sibling;
2727 retval = reply->last_sibling;
2730 retval = reply->next_sibling;
2733 retval = reply->prev_sibling;
2736 retval = reply->owner;
2739 retval = reply->first_child;
2749 /***********************************************************************
2750 * WIN_InternalShowOwnedPopups
2752 * Internal version of ShowOwnedPopups; Wine functions should use this
2753 * to avoid interfering with application calls to ShowOwnedPopups
2754 * and to make sure the application can't prevent showing/hiding.
2756 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2760 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2764 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2766 if (!win_array) return TRUE;
2769 * Show windows Lowest first, Highest last to preserve Z-Order
2771 while (win_array[count]) count++;
2772 while (--count >= 0)
2774 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2775 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2777 if (pWnd->dwStyle & WS_POPUP)
2781 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2782 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2785 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2787 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2788 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2793 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2794 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2795 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2798 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2800 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2801 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2802 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2806 WIN_ReleaseWndPtr( pWnd );
2808 HeapFree( GetProcessHeap(), 0, win_array );
2813 /*******************************************************************
2814 * ShowOwnedPopups (USER32.@)
2816 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2820 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2822 if (!win_array) return TRUE;
2824 while (win_array[count]) count++;
2825 while (--count >= 0)
2827 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2828 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2830 if (pWnd->dwStyle & WS_POPUP)
2834 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2836 /* In Windows, ShowOwnedPopups(TRUE) generates
2837 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2838 * regardless of the state of the owner
2840 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2841 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2846 if (IsWindowVisible(pWnd->hwndSelf))
2848 /* In Windows, ShowOwnedPopups(FALSE) generates
2849 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2850 * regardless of the state of the owner
2852 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2853 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2857 WIN_ReleaseWndPtr( pWnd );
2859 HeapFree( GetProcessHeap(), 0, win_array );
2864 /*******************************************************************
2865 * GetLastActivePopup (USER32.@)
2867 HWND WINAPI GetLastActivePopup( HWND hwnd )
2871 SERVER_START_REQ( get_window_info )
2874 if (!wine_server_call_err( req )) retval = reply->last_active;
2881 /*******************************************************************
2884 * Build an array of all parents of a given window, starting with
2885 * the immediate parent. The array must be freed with HeapFree.
2886 * Returns NULL if window is a top-level window.
2888 HWND *WIN_ListParents( HWND hwnd )
2891 HWND current, *list;
2892 int pos = 0, size = 16, count = 0;
2894 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2899 if (!(win = WIN_GetPtr( current ))) goto empty;
2900 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2901 list[pos] = win->parent;
2902 WIN_ReleasePtr( win );
2903 if (!(current = list[pos]))
2905 if (!pos) goto empty;
2908 if (++pos == size - 1)
2910 /* need to grow the list */
2911 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2912 if (!new_list) goto empty;
2918 /* at least one parent belongs to another process, have to query the server */
2923 SERVER_START_REQ( get_window_parents )
2926 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2927 if (!wine_server_call( req )) count = reply->count;
2930 if (!count) goto empty;
2936 HeapFree( GetProcessHeap(), 0, list );
2938 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2942 HeapFree( GetProcessHeap(), 0, list );
2947 /*******************************************************************
2950 * Build an array of the children of a given window. The array must be
2951 * freed with HeapFree. Returns NULL when no windows are found.
2953 HWND *WIN_ListChildren( HWND hwnd )
2955 return list_window_children( hwnd, 0, 0 );
2959 /*******************************************************************
2960 * EnumWindows (USER32.@)
2962 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2968 /* We have to build a list of all windows first, to avoid */
2969 /* unpleasant side-effects, for instance if the callback */
2970 /* function changes the Z-order of the windows. */
2972 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2974 /* Now call the callback function for every window */
2976 iWndsLocks = WIN_SuspendWndsLock();
2977 for (i = 0; list[i]; i++)
2979 /* Make sure that the window still exists */
2980 if (!IsWindow( list[i] )) continue;
2981 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2983 WIN_RestoreWndsLock(iWndsLocks);
2984 HeapFree( GetProcessHeap(), 0, list );
2989 /**********************************************************************
2990 * EnumThreadWindows (USER32.@)
2992 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2997 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2999 /* Now call the callback function for every window */
3001 iWndsLocks = WIN_SuspendWndsLock();
3002 for (i = 0; list[i]; i++)
3003 if (!func( list[i], lParam )) break;
3004 WIN_RestoreWndsLock(iWndsLocks);
3005 HeapFree( GetProcessHeap(), 0, list );
3010 /**********************************************************************
3011 * WIN_EnumChildWindows
3013 * Helper function for EnumChildWindows().
3015 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
3020 for ( ; *list; list++)
3022 /* Make sure that the window still exists */
3023 if (!IsWindow( *list )) continue;
3024 /* skip owned windows */
3025 if (GetWindow( *list, GW_OWNER )) continue;
3026 /* Build children list first */
3027 childList = WIN_ListChildren( *list );
3029 ret = func( *list, lParam );
3033 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
3034 HeapFree( GetProcessHeap(), 0, childList );
3036 if (!ret) return FALSE;
3042 /**********************************************************************
3043 * EnumChildWindows (USER32.@)
3045 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3050 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3051 iWndsLocks = WIN_SuspendWndsLock();
3052 WIN_EnumChildWindows( list, func, lParam );
3053 WIN_RestoreWndsLock(iWndsLocks);
3054 HeapFree( GetProcessHeap(), 0, list );
3059 /*******************************************************************
3060 * AnyPopup (USER.52)
3062 BOOL16 WINAPI AnyPopup16(void)
3068 /*******************************************************************
3069 * AnyPopup (USER32.@)
3071 BOOL WINAPI AnyPopup(void)
3075 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3077 if (!list) return FALSE;
3078 for (i = 0; list[i]; i++)
3080 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3082 retvalue = (list[i] != 0);
3083 HeapFree( GetProcessHeap(), 0, list );
3088 /*******************************************************************
3089 * FlashWindow (USER32.@)
3091 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3093 WND *wndPtr = WIN_FindWndPtr(hWnd);
3095 TRACE("%p\n", hWnd);
3097 if (!wndPtr) return FALSE;
3098 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3100 if (wndPtr->dwStyle & WS_MINIMIZE)
3102 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3104 HDC hDC = GetDC(hWnd);
3106 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM)hDC, 0 ))
3107 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3109 ReleaseDC( hWnd, hDC );
3110 wndPtr->flags |= WIN_NCACTIVATED;
3114 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3115 wndPtr->flags &= ~WIN_NCACTIVATED;
3117 WIN_ReleaseWndPtr(wndPtr);
3123 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3124 else wparam = (hWnd == GetForegroundWindow());
3126 WIN_ReleaseWndPtr(wndPtr);
3127 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3132 /*******************************************************************
3133 * FlashWindowEx (USER32.@)
3135 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3137 FIXME("%p\n", pfwi);
3141 /*******************************************************************
3142 * GetWindowContextHelpId (USER32.@)
3144 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3147 WND *wnd = WIN_FindWndPtr( hwnd );
3149 retval = wnd->helpContext;
3150 WIN_ReleaseWndPtr(wnd);
3155 /*******************************************************************
3156 * SetWindowContextHelpId (USER32.@)
3158 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3160 WND *wnd = WIN_FindWndPtr( hwnd );
3161 if (!wnd) return FALSE;
3162 wnd->helpContext = id;
3163 WIN_ReleaseWndPtr(wnd);
3168 /*******************************************************************
3169 * DragDetect (USER32.@)
3171 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3176 rect.left = pt.x - wDragWidth;
3177 rect.right = pt.x + wDragWidth;
3179 rect.top = pt.y - wDragHeight;
3180 rect.bottom = pt.y + wDragHeight;
3186 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3188 if( msg.message == WM_LBUTTONUP )
3193 if( msg.message == WM_MOUSEMOVE )
3196 tmp.x = LOWORD(msg.lParam);
3197 tmp.y = HIWORD(msg.lParam);
3198 if( !PtInRect( &rect, tmp ))
3210 /******************************************************************************
3211 * GetWindowModuleFileNameA (USER32.@)
3213 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3215 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3216 hwnd, lpszFileName, cchFileNameMax);
3220 /******************************************************************************
3221 * GetWindowModuleFileNameW (USER32.@)
3223 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3225 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3226 hwnd, lpszFileName, cchFileNameMax);
3230 /******************************************************************************
3231 * GetWindowInfo (USER32.@)
3234 * MS Documentation mentions that pwi->cbSize must be set to SIZEOF(WINDOWINFO)
3235 * this may be because this structure changed over time. If this is the
3236 * the case, then please: FIXME.
3237 * Using the structure described in MSDN for 98/ME/NT(4.0 SP3)/2000/XP.
3239 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3241 if (!pwi) return FALSE;
3242 if (pwi->cbSize != sizeof(WINDOWINFO))
3244 FIXME("windowinfo->cbSize != sizeof(WINDOWINFO). Please report\n");
3247 if (!IsWindow(hwnd)) return FALSE;
3249 GetWindowRect(hwnd, &pwi->rcWindow);
3250 GetClientRect(hwnd, &pwi->rcClient);
3251 /* translate to screen coordinates */
3252 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3254 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3255 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3256 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3258 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3259 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3261 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3262 pwi->wCreatorVersion = 0x0400;