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"
28 #include "wine/winbase16.h"
29 #include "wine/winuser16.h"
31 #include "wine/server.h"
32 #include "wine/unicode.h"
37 #include "cursoricon.h"
42 #include "stackframe.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];
61 extern SYSLEVEL USER_SysLevel; /* FIXME */
63 /***********************************************************************
66 * Suspend the lock on WND structures.
67 * Returns the number of locks suspended
69 int WIN_SuspendWndsLock( void )
71 int isuspendedLocks = _ConfirmSysLevel( &USER_SysLevel );
72 int count = isuspendedLocks;
75 _LeaveSysLevel( &USER_SysLevel );
77 return isuspendedLocks;
80 /***********************************************************************
83 * Restore the suspended locks on WND structures
85 void WIN_RestoreWndsLock( int ipreviousLocks )
87 while ( ipreviousLocks-- > 0 )
88 _EnterSysLevel( &USER_SysLevel );
91 /***********************************************************************
92 * create_window_handle
94 * Create a window handle with the server.
96 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom, INT size )
99 user_handle_t handle = 0;
101 WND *win = HeapAlloc( GetProcessHeap(), 0, size );
103 if (!win) return NULL;
107 SERVER_START_REQ( create_window )
109 req->parent = parent;
112 if ((res = !wine_server_call_err( req ))) handle = reply->handle;
119 HeapFree( GetProcessHeap(), 0, win );
122 index = LOWORD(handle) - FIRST_USER_HANDLE;
123 assert( index < NB_USER_HANDLES );
124 user_handles[index] = win;
125 win->hwndSelf = handle;
126 win->dwMagic = WND_MAGIC;
132 /***********************************************************************
135 * Free a window handle.
137 static WND *free_window_handle( HWND hwnd )
140 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
142 if (index >= NB_USER_HANDLES) return NULL;
144 if ((ptr = user_handles[index]))
146 SERVER_START_REQ( destroy_window )
149 if (!wine_server_call_err( req ))
150 user_handles[index] = NULL;
157 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
162 /*******************************************************************
163 * list_window_children
165 * Build an array of the children of a given window. The array must be
166 * freed with HeapFree. Returns NULL when no windows are found.
168 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
177 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
179 SERVER_START_REQ( get_window_children )
184 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
185 if (!wine_server_call( req )) count = reply->count;
188 if (count && count < size)
193 HeapFree( GetProcessHeap(), 0, list );
195 size = count + 1; /* restart with a large enough buffer */
201 /*******************************************************************
204 static void send_parent_notify( HWND hwnd, UINT msg )
206 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) return;
207 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) return;
208 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
209 MAKEWPARAM( msg, GetWindowLongW( hwnd, GWL_ID )), (LPARAM)hwnd );
213 /*******************************************************************
214 * get_server_window_text
216 * Retrieve the window text from the server.
218 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
222 SERVER_START_REQ( get_window_text )
225 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
226 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
229 text[len / sizeof(WCHAR)] = 0;
233 /***********************************************************************
236 * Return a pointer to the WND structure if local to the process,
237 * or WND_OTHER_PROCESS if handle may be valid in other process.
238 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
240 WND *WIN_GetPtr( HWND hwnd )
243 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
245 if (index >= NB_USER_HANDLES) return NULL;
248 if ((ptr = user_handles[index]))
250 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
254 else ptr = WND_OTHER_PROCESS;
260 /***********************************************************************
261 * WIN_IsCurrentProcess
263 * Check whether a given window belongs to the current process (and return the full handle).
265 HWND WIN_IsCurrentProcess( HWND hwnd )
270 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
272 WIN_ReleasePtr( ptr );
277 /***********************************************************************
278 * WIN_IsCurrentThread
280 * Check whether a given window belongs to the current thread (and return the full handle).
282 HWND WIN_IsCurrentThread( HWND hwnd )
287 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
289 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
290 WIN_ReleasePtr( ptr );
296 /***********************************************************************
299 * Convert a 16-bit window handle to a full 32-bit handle.
301 HWND WIN_Handle32( HWND16 hwnd16 )
304 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
306 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
307 /* do sign extension for -2 and -3 */
308 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
310 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
312 if (ptr != WND_OTHER_PROCESS)
314 hwnd = ptr->hwndSelf;
315 WIN_ReleasePtr( ptr );
317 else /* may belong to another process */
319 SERVER_START_REQ( get_window_info )
322 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
330 /***********************************************************************
333 * Return a pointer to the WND structure corresponding to a HWND.
335 WND * WIN_FindWndPtr( HWND hwnd )
339 if (!hwnd) return NULL;
341 if ((ptr = WIN_GetPtr( hwnd )))
343 if (ptr != WND_OTHER_PROCESS)
345 /* increment destruction monitoring */
349 if (IsWindow( hwnd )) /* check other processes */
351 ERR( "window %04x belongs to other process\n", hwnd );
352 /* DbgBreakPoint(); */
355 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
360 /***********************************************************************
363 * Release the pointer to the WND structure.
365 void WIN_ReleaseWndPtr(WND *wndPtr)
369 /* Decrement destruction monitoring value */
371 /* Check if it's time to release the memory */
372 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
375 free_window_handle( wndPtr->hwndSelf );
377 else if(wndPtr->irefCount < 0)
379 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
380 ERR("forgot a Lock on %p somewhere\n",wndPtr);
382 /* unlock all WND structures for thread safeness */
387 /***********************************************************************
390 * Remove a window from the siblings linked list.
392 void WIN_UnlinkWindow( HWND hwnd )
394 WIN_LinkWindow( hwnd, 0, 0 );
398 /***********************************************************************
401 * Insert a window into the siblings linked list.
402 * The window is inserted after the specified window, which can also
403 * be specified as HWND_TOP or HWND_BOTTOM.
404 * If parent is 0, window is unlinked from the tree.
406 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
408 WND *wndPtr = WIN_GetPtr( hwnd );
411 if (wndPtr == WND_OTHER_PROCESS)
413 if (IsWindow(hwnd)) ERR(" cannot link other process window %x\n", hwnd );
417 SERVER_START_REQ( link_window )
420 req->parent = parent;
421 req->previous = hwndInsertAfter;
422 if (!wine_server_call( req ))
424 if (reply->full_parent) wndPtr->parent = reply->full_parent;
429 WIN_ReleasePtr( wndPtr );
433 /***********************************************************************
436 * Change the owner of a window.
438 HWND WIN_SetOwner( HWND hwnd, HWND owner )
440 WND *win = WIN_GetPtr( hwnd );
444 if (win == WND_OTHER_PROCESS)
446 if (IsWindow(hwnd)) ERR( "cannot set owner %x on other process window %x\n", owner, hwnd );
449 SERVER_START_REQ( set_window_owner )
453 if (!wine_server_call( req ))
455 win->owner = reply->full_owner;
456 ret = reply->prev_owner;
460 WIN_ReleasePtr( win );
465 /***********************************************************************
468 * Change the style of a window.
470 LONG WIN_SetStyle( HWND hwnd, LONG style )
474 WND *win = WIN_GetPtr( hwnd );
477 if (win == WND_OTHER_PROCESS)
480 ERR( "cannot set style %lx on other process window %x\n", style, hwnd );
483 if (style == win->dwStyle)
485 WIN_ReleasePtr( win );
488 SERVER_START_REQ( set_window_info )
491 req->flags = SET_WIN_STYLE;
493 if ((ok = !wine_server_call( req )))
495 ret = reply->old_style;
496 win->dwStyle = style;
500 WIN_ReleasePtr( win );
501 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret );
506 /***********************************************************************
509 * Change the extended style of a window.
511 LONG WIN_SetExStyle( HWND hwnd, LONG style )
514 WND *win = WIN_GetPtr( hwnd );
517 if (win == WND_OTHER_PROCESS)
520 ERR( "cannot set exstyle %lx on other process window %x\n", style, hwnd );
523 if (style == win->dwExStyle)
525 WIN_ReleasePtr( win );
528 SERVER_START_REQ( set_window_info )
531 req->flags = SET_WIN_EXSTYLE;
532 req->ex_style = style;
533 if (!wine_server_call( req ))
535 ret = reply->old_ex_style;
536 win->dwExStyle = style;
540 WIN_ReleasePtr( win );
545 /***********************************************************************
548 * Set the window and client rectangles.
550 void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient )
552 WND *win = WIN_GetPtr( hwnd );
556 if (win == WND_OTHER_PROCESS)
558 if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %x\n", hwnd );
561 SERVER_START_REQ( set_window_rectangles )
564 req->window.left = rectWindow->left;
565 req->window.top = rectWindow->top;
566 req->window.right = rectWindow->right;
567 req->window.bottom = rectWindow->bottom;
568 req->client.left = rectClient->left;
569 req->client.top = rectClient->top;
570 req->client.right = rectClient->right;
571 req->client.bottom = rectClient->bottom;
572 ret = !wine_server_call( req );
577 win->rectWindow = *rectWindow;
578 win->rectClient = *rectClient;
580 TRACE( "win %x window (%d,%d)-(%d,%d) client (%d,%d)-(%d,%d)\n", hwnd,
581 rectWindow->left, rectWindow->top, rectWindow->right, rectWindow->bottom,
582 rectClient->left, rectClient->top, rectClient->right, rectClient->bottom );
584 WIN_ReleasePtr( win );
588 /***********************************************************************
591 * Get the window and client rectangles.
593 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
595 WND *win = WIN_GetPtr( hwnd );
598 if (!win) return FALSE;
599 if (win == WND_OTHER_PROCESS)
601 SERVER_START_REQ( get_window_rectangles )
604 if ((ret = !wine_server_call( req )))
608 rectWindow->left = reply->window.left;
609 rectWindow->top = reply->window.top;
610 rectWindow->right = reply->window.right;
611 rectWindow->bottom = reply->window.bottom;
615 rectClient->left = reply->client.left;
616 rectClient->top = reply->client.top;
617 rectClient->right = reply->client.right;
618 rectClient->bottom = reply->client.bottom;
626 if (rectWindow) *rectWindow = win->rectWindow;
627 if (rectClient) *rectClient = win->rectClient;
628 WIN_ReleasePtr( win );
634 /***********************************************************************
637 * Destroy storage associated to a window. "Internals" p.358
639 LRESULT WIN_DestroyWindow( HWND hwnd )
644 TRACE("%04x\n", hwnd );
646 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
648 ERR( "window doesn't belong to current thread\n" );
652 /* free child windows */
653 if ((list = WIN_ListChildren( hwnd )))
656 for (i = 0; list[i]; i++)
658 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
659 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
661 HeapFree( GetProcessHeap(), 0, list );
665 * Clear the update region to make sure no WM_PAINT messages will be
666 * generated for this window while processing the WM_NCDESTROY.
668 RedrawWindow( hwnd, NULL, 0,
669 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
672 * Send the WM_NCDESTROY to the window being destroyed.
674 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
676 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
678 WINPOS_CheckInternalPos( hwnd );
679 if( hwnd == GetCapture()) ReleaseCapture();
681 /* free resources associated with the window */
683 TIMER_RemoveWindowTimers( hwnd );
685 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
687 if (!(wndPtr->dwStyle & WS_CHILD))
689 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
690 if (menu) DestroyMenu( menu );
692 if (wndPtr->hSysMenu)
694 DestroyMenu( wndPtr->hSysMenu );
695 wndPtr->hSysMenu = 0;
697 USER_Driver.pDestroyWindow( hwnd );
698 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
699 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
700 CLASS_RemoveWindow( wndPtr->class );
701 wndPtr->class = NULL;
702 wndPtr->dwMagic = 0; /* Mark it as invalid */
703 WIN_ReleaseWndPtr( wndPtr );
707 /***********************************************************************
708 * WIN_DestroyThreadWindows
710 * Destroy all children of 'wnd' owned by the current thread.
711 * Return TRUE if something was done.
713 void WIN_DestroyThreadWindows( HWND hwnd )
718 if (!(list = WIN_ListChildren( hwnd ))) return;
719 for (i = 0; list[i]; i++)
721 if (WIN_IsCurrentThread( list[i] ))
722 DestroyWindow( list[i] );
724 WIN_DestroyThreadWindows( list[i] );
726 HeapFree( GetProcessHeap(), 0, list );
729 /***********************************************************************
730 * WIN_CreateDesktopWindow
732 * Create the desktop window.
734 BOOL WIN_CreateDesktopWindow(void)
736 struct tagCLASS *class;
745 TRACE("Creating desktop window\n");
747 if (!WINPOS_CreateInternalPosAtom() ||
748 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
749 &wndExtra, &winproc, &clsStyle, &dce )))
752 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM),
753 sizeof(WND) + wndExtra - sizeof(pWndDesktop->wExtra) );
754 if (!pWndDesktop) return FALSE;
755 hwndDesktop = pWndDesktop->hwndSelf;
757 pWndDesktop->tid = 0; /* nobody owns the desktop */
758 pWndDesktop->parent = 0;
759 pWndDesktop->owner = 0;
760 pWndDesktop->class = class;
761 pWndDesktop->text = NULL;
762 pWndDesktop->hrgnUpdate = 0;
763 pWndDesktop->clsStyle = clsStyle;
764 pWndDesktop->dce = NULL;
765 pWndDesktop->pVScroll = NULL;
766 pWndDesktop->pHScroll = NULL;
767 pWndDesktop->helpContext = 0;
768 pWndDesktop->flags = 0;
769 pWndDesktop->hSysMenu = 0;
770 pWndDesktop->winproc = winproc;
771 pWndDesktop->cbWndExtra = wndExtra;
773 cs.lpCreateParams = NULL;
779 cs.cx = GetSystemMetrics( SM_CXSCREEN );
780 cs.cy = GetSystemMetrics( SM_CYSCREEN );
781 cs.style = pWndDesktop->dwStyle;
782 cs.dwExStyle = pWndDesktop->dwExStyle;
784 cs.lpszClass = DESKTOP_CLASS_ATOM;
786 SetRect( &rect, 0, 0, cs.cx, cs.cy );
787 WIN_SetRectangles( hwndDesktop, &rect, &rect );
789 SERVER_START_REQ( set_window_info )
791 req->handle = hwndDesktop;
792 req->flags = 0; /* don't set anything, just retrieve */
793 wine_server_call( req );
794 pWndDesktop->dwStyle = reply->old_style;
795 pWndDesktop->dwExStyle = reply->old_ex_style;
796 pWndDesktop->hInstance = (ULONG_PTR)reply->old_instance;
797 pWndDesktop->userdata = (ULONG_PTR)reply->old_user_data;
798 pWndDesktop->wIDmenu = reply->old_id;
802 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE ))
804 WIN_ReleaseWndPtr( pWndDesktop );
808 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
809 WIN_ReleaseWndPtr( pWndDesktop );
814 /***********************************************************************
817 * Fix the coordinates - Helper for WIN_CreateWindowEx.
818 * returns default show mode in sw.
819 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
821 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
823 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
824 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
826 if (cs->style & (WS_CHILD | WS_POPUP))
828 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
829 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
831 else /* overlapped window */
835 GetStartupInfoA( &info );
837 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
839 /* Never believe Microsoft's documentation... CreateWindowEx doc says
840 * that if an overlapped window is created with WS_VISIBLE style bit
841 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
842 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
845 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
846 * 2) it does not ignore the y parameter as the docs claim; instead, it
847 * uses it as second parameter to ShowWindow() unless y is either
848 * CW_USEDEFAULT or CW_USEDEFAULT16.
850 * The fact that we didn't do 2) caused bogus windows pop up when wine
851 * was running apps that were using this obscure feature. Example -
852 * calc.exe that comes with Win98 (only Win98, it's different from
853 * the one that comes with Win95 and NT)
855 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
856 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
857 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
860 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
862 if (info.dwFlags & STARTF_USESIZE)
864 cs->cx = info.dwXSize;
865 cs->cy = info.dwYSize;
867 else /* if no other hint from the app, pick 3/4 of the screen real estate */
870 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
871 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
872 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
879 /* neither x nor cx are default. Check the y values .
880 * In the trace we see Outlook and Outlook Express using
881 * cy set to CW_USEDEFAULT when opening the address book.
883 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
885 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
886 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
887 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
892 /***********************************************************************
895 static void dump_window_styles( DWORD style, DWORD exstyle )
898 if(style & WS_POPUP) DPRINTF(" WS_POPUP");
899 if(style & WS_CHILD) DPRINTF(" WS_CHILD");
900 if(style & WS_MINIMIZE) DPRINTF(" WS_MINIMIZE");
901 if(style & WS_VISIBLE) DPRINTF(" WS_VISIBLE");
902 if(style & WS_DISABLED) DPRINTF(" WS_DISABLED");
903 if(style & WS_CLIPSIBLINGS) DPRINTF(" WS_CLIPSIBLINGS");
904 if(style & WS_CLIPCHILDREN) DPRINTF(" WS_CLIPCHILDREN");
905 if(style & WS_MAXIMIZE) DPRINTF(" WS_MAXIMIZE");
906 if((style & WS_CAPTION) == WS_CAPTION) DPRINTF(" WS_CAPTION");
909 if(style & WS_BORDER) DPRINTF(" WS_BORDER");
910 if(style & WS_DLGFRAME) DPRINTF(" WS_DLGFRAME");
912 if(style & WS_VSCROLL) DPRINTF(" WS_VSCROLL");
913 if(style & WS_HSCROLL) DPRINTF(" WS_HSCROLL");
914 if(style & WS_SYSMENU) DPRINTF(" WS_SYSMENU");
915 if(style & WS_THICKFRAME) DPRINTF(" WS_THICKFRAME");
916 if(style & WS_GROUP) DPRINTF(" WS_GROUP");
917 if(style & WS_TABSTOP) DPRINTF(" WS_TABSTOP");
918 if(style & WS_MINIMIZEBOX) DPRINTF(" WS_MINIMIZEBOX");
919 if(style & WS_MAXIMIZEBOX) DPRINTF(" WS_MAXIMIZEBOX");
921 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
922 #define DUMPED_STYLES \
942 if(style & ~DUMPED_STYLES) DPRINTF(" %08lx", style & ~DUMPED_STYLES);
947 if(exstyle & WS_EX_DLGMODALFRAME) DPRINTF(" WS_EX_DLGMODALFRAME");
948 if(exstyle & WS_EX_DRAGDETECT) DPRINTF(" WS_EX_DRAGDETECT");
949 if(exstyle & WS_EX_NOPARENTNOTIFY) DPRINTF(" WS_EX_NOPARENTNOTIFY");
950 if(exstyle & WS_EX_TOPMOST) DPRINTF(" WS_EX_TOPMOST");
951 if(exstyle & WS_EX_ACCEPTFILES) DPRINTF(" WS_EX_ACCEPTFILES");
952 if(exstyle & WS_EX_TRANSPARENT) DPRINTF(" WS_EX_TRANSPARENT");
953 if(exstyle & WS_EX_MDICHILD) DPRINTF(" WS_EX_MDICHILD");
954 if(exstyle & WS_EX_TOOLWINDOW) DPRINTF(" WS_EX_TOOLWINDOW");
955 if(exstyle & WS_EX_WINDOWEDGE) DPRINTF(" WS_EX_WINDOWEDGE");
956 if(exstyle & WS_EX_CLIENTEDGE) DPRINTF(" WS_EX_CLIENTEDGE");
957 if(exstyle & WS_EX_CONTEXTHELP) DPRINTF(" WS_EX_CONTEXTHELP");
958 if(exstyle & WS_EX_RIGHT) DPRINTF(" WS_EX_RIGHT");
959 if(exstyle & WS_EX_RTLREADING) DPRINTF(" WS_EX_RTLREADING");
960 if(exstyle & WS_EX_LEFTSCROLLBAR) DPRINTF(" WS_EX_LEFTSCROLLBAR");
961 if(exstyle & WS_EX_CONTROLPARENT) DPRINTF(" WS_EX_CONTROLPARENT");
962 if(exstyle & WS_EX_STATICEDGE) DPRINTF(" WS_EX_STATICEDGE");
963 if(exstyle & WS_EX_APPWINDOW) DPRINTF(" WS_EX_APPWINDOW");
964 if(exstyle & WS_EX_LAYERED) DPRINTF(" WS_EX_LAYERED");
966 #define DUMPED_EX_STYLES \
967 (WS_EX_DLGMODALFRAME | \
969 WS_EX_NOPARENTNOTIFY | \
971 WS_EX_ACCEPTFILES | \
972 WS_EX_TRANSPARENT | \
977 WS_EX_CONTEXTHELP | \
980 WS_EX_LEFTSCROLLBAR | \
981 WS_EX_CONTROLPARENT | \
986 if(exstyle & ~DUMPED_EX_STYLES) DPRINTF(" %08lx", exstyle & ~DUMPED_EX_STYLES);
988 #undef DUMPED_EX_STYLES
992 /***********************************************************************
995 * Implementation of CreateWindowEx().
997 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
998 WINDOWPROCTYPE type )
1001 struct tagCLASS *classPtr;
1003 HWND hwnd, parent, owner;
1008 BOOL unicode = (type == WIN_PROC_32W);
1010 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%04x menu=%04x inst=%08x params=%p\n",
1011 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
1012 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
1013 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
1014 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
1016 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
1018 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
1019 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
1021 /* Find the parent window */
1023 parent = GetDesktopWindow();
1026 if (cs->hwndParent == HWND_MESSAGE)
1028 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
1029 * message window (style: WS_POPUP|WS_DISABLED)
1031 FIXME("Parent is HWND_MESSAGE\n");
1033 else if (cs->hwndParent)
1035 /* Make sure parent is valid */
1036 if (!IsWindow( cs->hwndParent ))
1038 WARN("Bad parent %04x\n", cs->hwndParent );
1041 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1042 parent = WIN_GetFullHandle(cs->hwndParent);
1044 owner = GetAncestor( cs->hwndParent, GA_ROOT );
1046 else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1048 WARN("No parent for child window\n" );
1049 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1052 /* Find the window class */
1053 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
1054 &wndExtra, &winproc, &clsStyle, &dce )))
1056 WARN("Bad class '%s'\n", cs->lpszClass );
1060 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1062 /* Correct the window style - stage 1
1064 * These are patches that appear to affect both the style loaded into the
1065 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
1067 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1068 * why does the user get to set it?
1071 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1072 * tested for WS_POPUP
1074 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1075 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1076 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1077 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1079 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1081 /* Create the window structure */
1083 if (!(wndPtr = create_window_handle( parent, owner, classAtom,
1084 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
1086 TRACE("out of memory\n" );
1089 hwnd = wndPtr->hwndSelf;
1091 /* Fill the window structure */
1093 wndPtr->tid = GetCurrentThreadId();
1094 wndPtr->owner = owner;
1095 wndPtr->parent = parent;
1096 wndPtr->class = classPtr;
1097 wndPtr->winproc = winproc;
1098 wndPtr->hInstance = cs->hInstance;
1099 wndPtr->text = NULL;
1100 wndPtr->hrgnUpdate = 0;
1101 wndPtr->hrgnWnd = 0;
1102 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1103 wndPtr->dwExStyle = cs->dwExStyle;
1104 wndPtr->clsStyle = clsStyle;
1105 wndPtr->wIDmenu = 0;
1106 wndPtr->helpContext = 0;
1107 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1108 wndPtr->pVScroll = NULL;
1109 wndPtr->pHScroll = NULL;
1110 wndPtr->userdata = 0;
1111 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU) ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1112 wndPtr->cbWndExtra = wndExtra;
1114 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
1116 /* Correct the window style - stage 2 */
1118 if (!(cs->style & WS_CHILD))
1120 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1121 if (!(cs->style & WS_POPUP))
1123 wndPtr->dwStyle |= WS_CAPTION;
1124 wndPtr->flags |= WIN_NEED_SIZE;
1127 SERVER_START_REQ( set_window_info )
1130 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1131 req->style = wndPtr->dwStyle;
1132 req->ex_style = wndPtr->dwExStyle;
1133 req->instance = (void *)wndPtr->hInstance;
1134 wine_server_call( req );
1138 /* Get class or window DC if needed */
1140 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1141 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
1142 else wndPtr->dce = NULL;
1144 /* Set the window menu */
1146 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
1148 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
1151 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1154 if (HIWORD(cs->hInstance))
1155 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1157 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
1159 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
1163 else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
1164 WIN_ReleaseWndPtr( wndPtr );
1166 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
1168 WIN_DestroyWindow( hwnd );
1172 /* Notify the parent window only */
1174 send_parent_notify( hwnd, WM_CREATE );
1175 if (!IsWindow( hwnd )) return 0;
1177 if (cs->style & WS_VISIBLE)
1179 /* in case WS_VISIBLE got set in the meantime */
1180 if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0;
1181 WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
1182 WIN_ReleasePtr( wndPtr );
1183 ShowWindow( hwnd, sw );
1186 /* Call WH_SHELL hook */
1188 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1189 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1191 TRACE("created window %04x\n", hwnd);
1196 /***********************************************************************
1197 * CreateWindow (USER.41)
1199 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1200 DWORD style, INT16 x, INT16 y, INT16 width,
1201 INT16 height, HWND16 parent, HMENU16 menu,
1202 HINSTANCE16 instance, LPVOID data )
1204 return CreateWindowEx16( 0, className, windowName, style,
1205 x, y, width, height, parent, menu, instance, data );
1209 /***********************************************************************
1210 * CreateWindowEx (USER.452)
1212 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1213 LPCSTR windowName, DWORD style, INT16 x,
1214 INT16 y, INT16 width, INT16 height,
1215 HWND16 parent, HMENU16 menu,
1216 HINSTANCE16 instance, LPVOID data )
1222 /* Find the class atom */
1224 if (HIWORD(className))
1226 if (!(classAtom = GlobalFindAtomA( className )))
1228 ERR( "bad class name %s\n", debugstr_a(className) );
1234 classAtom = LOWORD(className);
1235 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1237 ERR( "bad atom %x\n", classAtom);
1243 /* Fix the coordinates */
1245 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1246 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1247 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1248 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1250 /* Create the window */
1252 cs.lpCreateParams = data;
1253 cs.hInstance = (HINSTANCE)instance;
1254 cs.hMenu = HMENU_32(menu);
1255 cs.hwndParent = WIN_Handle32( parent );
1257 cs.lpszName = windowName;
1258 cs.lpszClass = className;
1259 cs.dwExStyle = exStyle;
1261 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1265 /***********************************************************************
1266 * CreateWindowExA (USER32.@)
1268 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1269 LPCSTR windowName, DWORD style, INT x,
1270 INT y, INT width, INT height,
1271 HWND parent, HMENU menu,
1272 HINSTANCE instance, LPVOID data )
1279 instance=GetModuleHandleA(NULL);
1281 if(exStyle & WS_EX_MDICHILD)
1282 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1284 /* Find the class atom */
1286 if (HIWORD(className))
1288 if (!(classAtom = GlobalFindAtomA( className )))
1290 ERR( "bad class name %s\n", debugstr_a(className) );
1296 classAtom = LOWORD(className);
1297 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1299 ERR( "bad atom %x\n", classAtom);
1305 /* Create the window */
1307 cs.lpCreateParams = data;
1308 cs.hInstance = instance;
1310 cs.hwndParent = parent;
1316 cs.lpszName = windowName;
1317 cs.lpszClass = className;
1318 cs.dwExStyle = exStyle;
1320 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1324 /***********************************************************************
1325 * CreateWindowExW (USER32.@)
1327 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1328 LPCWSTR windowName, DWORD style, INT x,
1329 INT y, INT width, INT height,
1330 HWND parent, HMENU menu,
1331 HINSTANCE instance, LPVOID data )
1338 instance=GetModuleHandleA(NULL);
1340 if(exStyle & WS_EX_MDICHILD)
1341 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)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();
1396 if (USER_Driver.pResetSelectionOwner)
1397 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1400 * Send the WM_DESTROY to the window.
1402 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1405 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1406 * make sure that the window still exists when we come back.
1413 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1415 /* start from the end (FIXME: is this needed?) */
1416 for (i = 0; pWndArray[i]; i++) ;
1420 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1422 HeapFree( GetProcessHeap(), 0, pWndArray );
1425 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1429 /***********************************************************************
1430 * DestroyWindow (USER32.@)
1432 BOOL WINAPI DestroyWindow( HWND hwnd )
1437 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1439 SetLastError( ERROR_ACCESS_DENIED );
1443 TRACE("(%04x)\n", hwnd);
1445 /* Look whether the focus is within the tree of windows we will
1449 if (h == hwnd || IsChild( hwnd, h ))
1451 HWND parent = GetAncestor( hwnd, GA_PARENT );
1452 if (parent == GetDesktopWindow()) parent = 0;
1458 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1460 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1464 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1465 send_parent_notify( hwnd, WM_DESTROY );
1467 else if (!GetWindow( hwnd, GW_OWNER ))
1469 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1470 /* FIXME: clean up palette - see "Internals" p.352 */
1473 if (!IsWindow(hwnd)) return TRUE;
1475 if (USER_Driver.pResetSelectionOwner)
1476 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1478 /* Hide the window */
1480 if (!ShowWindow( hwnd, SW_HIDE ))
1482 if (hwnd == GetActiveWindow()) WINPOS_ActivateOtherWindow( hwnd );
1484 if (!IsWindow(hwnd)) return TRUE;
1486 /* Recursively destroy owned windows */
1493 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1496 for (i = 0; list[i]; i++)
1498 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1499 if (WIN_IsCurrentThread( list[i] ))
1501 DestroyWindow( list[i] );
1505 WIN_SetOwner( list[i], 0 );
1507 HeapFree( GetProcessHeap(), 0, list );
1509 if (!got_one) break;
1513 /* Send destroy messages */
1515 WIN_SendDestroyMsg( hwnd );
1516 if (!IsWindow( hwnd )) return TRUE;
1518 /* Unlink now so we won't bother with the children later on */
1520 WIN_UnlinkWindow( hwnd );
1522 /* Destroy the window storage */
1524 WIN_DestroyWindow( hwnd );
1529 /***********************************************************************
1530 * CloseWindow (USER32.@)
1532 BOOL WINAPI CloseWindow( HWND hwnd )
1534 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1535 ShowWindow( hwnd, SW_MINIMIZE );
1540 /***********************************************************************
1541 * OpenIcon (USER32.@)
1543 BOOL WINAPI OpenIcon( HWND hwnd )
1545 if (!IsIconic( hwnd )) return FALSE;
1546 ShowWindow( hwnd, SW_SHOWNORMAL );
1551 /***********************************************************************
1554 * Implementation of FindWindow() and FindWindowEx().
1556 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1561 WCHAR *buffer = NULL;
1563 if (!parent) parent = GetDesktopWindow();
1566 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1567 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1570 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1574 child = WIN_GetFullHandle( child );
1575 while (list[i] && list[i] != child) i++;
1576 if (!list[i]) goto done;
1577 i++; /* start from next window */
1584 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1591 if (list) HeapFree( GetProcessHeap(), 0, list );
1592 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1598 /***********************************************************************
1599 * FindWindowA (USER32.@)
1601 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1603 HWND ret = FindWindowExA( 0, 0, className, title );
1604 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1609 /***********************************************************************
1610 * FindWindowExA (USER32.@)
1612 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1613 LPCSTR className, LPCSTR title )
1622 /* If the atom doesn't exist, then no class */
1623 /* with this name exists either. */
1624 if (!(atom = GlobalFindAtomA( className )))
1626 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1630 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1632 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1633 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1634 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1635 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1636 HeapFree( GetProcessHeap(), 0, buffer );
1641 /***********************************************************************
1642 * FindWindowExW (USER32.@)
1644 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1645 LPCWSTR className, LPCWSTR title )
1651 /* If the atom doesn't exist, then no class */
1652 /* with this name exists either. */
1653 if (!(atom = GlobalFindAtomW( className )))
1655 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1659 return WIN_FindWindow( parent, child, atom, title );
1663 /***********************************************************************
1664 * FindWindowW (USER32.@)
1666 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1668 return FindWindowExW( 0, 0, className, title );
1672 /**********************************************************************
1673 * GetDesktopWindow (USER32.@)
1675 HWND WINAPI GetDesktopWindow(void)
1677 if (pWndDesktop) return pWndDesktop->hwndSelf;
1678 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" );
1684 /*******************************************************************
1685 * EnableWindow (USER32.@)
1687 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1694 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1695 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1699 TRACE("( %x, %d )\n", hwnd, enable);
1701 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1702 style = wndPtr->dwStyle;
1703 retvalue = ((style & WS_DISABLED) != 0);
1704 WIN_ReleasePtr( wndPtr );
1706 if (enable && retvalue)
1708 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1709 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1711 else if (!enable && !retvalue)
1713 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1715 WIN_SetStyle( hwnd, style | WS_DISABLED );
1717 if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1718 SetFocus( 0 ); /* A disabled window can't have the focus */
1720 if (hwnd == GetCapture() || IsChild(hwnd, GetCapture()))
1721 ReleaseCapture(); /* A disabled window can't capture the mouse */
1723 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1729 /***********************************************************************
1730 * IsWindowEnabled (USER32.@)
1732 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1734 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1738 /***********************************************************************
1739 * IsWindowUnicode (USER32.@)
1741 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1746 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1747 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1748 WIN_ReleaseWndPtr(wndPtr);
1753 /**********************************************************************
1754 * GetWindowWord (USER32.@)
1756 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1761 WND *wndPtr = WIN_GetPtr( hwnd );
1764 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1767 if (wndPtr == WND_OTHER_PROCESS)
1769 if (IsWindow( hwnd ))
1770 FIXME( "(%d) not supported yet on other process window %x\n", offset, hwnd );
1771 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1774 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1776 WARN("Invalid offset %d\n", offset );
1777 SetLastError( ERROR_INVALID_INDEX );
1779 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1780 WIN_ReleasePtr( wndPtr );
1786 case GWL_HWNDPARENT:
1787 return GetWindowLongW( hwnd, offset );
1791 LONG ret = GetWindowLongW( hwnd, offset );
1793 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1797 WARN("Invalid offset %d\n", offset );
1803 /**********************************************************************
1804 * SetWindowWord (USER32.@)
1806 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1815 case GWL_HWNDPARENT:
1816 return SetWindowLongW( hwnd, offset, (UINT)newval );
1820 WARN("Invalid offset %d\n", offset );
1821 SetLastError( ERROR_INVALID_INDEX );
1826 wndPtr = WIN_GetPtr( hwnd );
1827 if (wndPtr == WND_OTHER_PROCESS)
1830 FIXME( "set %d <- %x not supported yet on other process window %x\n",
1831 offset, newval, hwnd );
1836 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1840 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1842 WARN("Invalid offset %d\n", offset );
1843 WIN_ReleasePtr(wndPtr);
1844 SetLastError( ERROR_INVALID_INDEX );
1847 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1850 WIN_ReleasePtr(wndPtr);
1855 /**********************************************************************
1858 * Helper function for GetWindowLong().
1860 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1865 if (offset == GWL_HWNDPARENT)
1867 HWND parent = GetAncestor( hwnd, GA_PARENT );
1868 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1869 return (LONG)parent;
1872 if (!(wndPtr = WIN_GetPtr( hwnd )))
1874 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1878 if (wndPtr == WND_OTHER_PROCESS)
1883 FIXME( "(%d) not supported on other process window %x\n", offset, hwnd );
1884 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1887 if (offset == GWL_WNDPROC)
1889 SetLastError( ERROR_ACCESS_DENIED );
1892 SERVER_START_REQ( set_window_info )
1895 req->flags = 0; /* don't set anything, just retrieve */
1896 if (!wine_server_call_err( req ))
1900 case GWL_STYLE: retvalue = reply->old_style; break;
1901 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1902 case GWL_ID: retvalue = reply->old_id; break;
1903 case GWL_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1904 case GWL_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1906 SetLastError( ERROR_INVALID_INDEX );
1915 /* now we have a valid wndPtr */
1919 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
1922 * Some programs try to access last element from 16 bit
1923 * code using illegal offset value. Hopefully this is
1924 * what those programs really expect.
1926 if (type == WIN_PROC_16 &&
1927 wndPtr->cbWndExtra >= 4 &&
1928 offset == wndPtr->cbWndExtra - sizeof(WORD))
1930 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1932 ERR( "- replaced invalid offset %d with %d\n",
1935 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset2);
1936 WIN_ReleasePtr( wndPtr );
1939 WARN("Invalid offset %d\n", offset );
1940 WIN_ReleasePtr( wndPtr );
1941 SetLastError( ERROR_INVALID_INDEX );
1944 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1945 /* Special case for dialog window procedure */
1946 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1947 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1948 WIN_ReleasePtr( wndPtr );
1954 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
1955 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1956 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1957 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
1958 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
1959 case GWL_HINSTANCE: retvalue = wndPtr->hInstance; break;
1961 WARN("Unknown offset %d\n", offset );
1962 SetLastError( ERROR_INVALID_INDEX );
1965 WIN_ReleasePtr(wndPtr);
1970 /**********************************************************************
1973 * Helper function for SetWindowLong().
1975 * 0 is the failure code. However, in the case of failure SetLastError
1976 * must be set to distinguish between a 0 return value and a failure.
1978 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1979 WINDOWPROCTYPE type )
1984 TRACE( "%x %d %lx %x\n", hwnd, offset, newval, type );
1986 if (!WIN_IsCurrentProcess( hwnd ))
1988 if (offset == GWL_WNDPROC)
1990 SetLastError( ERROR_ACCESS_DENIED );
1993 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1996 wndPtr = WIN_GetPtr( hwnd );
1997 if (wndPtr->hwndSelf == GetDesktopWindow())
1999 /* can't change anything on the desktop window */
2000 WIN_ReleasePtr( wndPtr );
2001 SetLastError( ERROR_ACCESS_DENIED );
2007 LONG *ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2008 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
2010 WARN("Invalid offset %d\n", offset );
2011 WIN_ReleasePtr( wndPtr );
2012 SetLastError( ERROR_INVALID_INDEX );
2015 /* Special case for dialog window procedure */
2016 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2018 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2019 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2020 type, WIN_PROC_WINDOW );
2021 WIN_ReleasePtr( wndPtr );
2026 WIN_ReleasePtr( wndPtr );
2033 /* first some special cases */
2038 style.styleOld = wndPtr->dwStyle;
2039 style.styleNew = newval;
2040 WIN_ReleasePtr( wndPtr );
2041 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2042 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2043 newval = style.styleNew;
2045 case GWL_HWNDPARENT:
2046 if (wndPtr->parent == GetDesktopWindow())
2048 WIN_ReleasePtr( wndPtr );
2049 return (LONG)WIN_SetOwner( hwnd, (HWND)newval );
2053 WIN_ReleasePtr( wndPtr );
2054 return (LONG)SetParent( hwnd, (HWND)newval );
2057 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2058 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2059 type, WIN_PROC_WINDOW );
2060 WIN_ReleasePtr( wndPtr );
2067 WIN_ReleasePtr( wndPtr );
2068 WARN("Invalid offset %d\n", offset );
2069 SetLastError( ERROR_INVALID_INDEX );
2073 SERVER_START_REQ( set_window_info )
2079 req->flags = SET_WIN_STYLE;
2080 req->style = newval;
2083 req->flags = SET_WIN_EXSTYLE;
2084 req->ex_style = newval;
2087 req->flags = SET_WIN_ID;
2091 req->flags = SET_WIN_INSTANCE;
2092 req->instance = (void *)newval;
2095 req->flags = SET_WIN_USERDATA;
2096 req->user_data = (void *)newval;
2099 if ((ok = !wine_server_call_err( req )))
2104 wndPtr->dwStyle = newval;
2105 retval = reply->old_style;
2108 wndPtr->dwExStyle = newval;
2109 retval = reply->old_ex_style;
2112 wndPtr->wIDmenu = newval;
2113 retval = reply->old_id;
2116 wndPtr->hInstance = newval;
2117 retval = (HINSTANCE)reply->old_instance;
2120 wndPtr->userdata = newval;
2121 retval = (ULONG_PTR)reply->old_user_data;
2127 WIN_ReleasePtr( wndPtr );
2131 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2132 USER_Driver.pSetWindowStyle( hwnd, retval );
2134 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2135 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2142 /**********************************************************************
2143 * GetWindowLong (USER.135)
2145 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2147 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2151 /**********************************************************************
2152 * GetWindowLongA (USER32.@)
2154 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2156 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2160 /**********************************************************************
2161 * GetWindowLongW (USER32.@)
2163 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2165 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2169 /**********************************************************************
2170 * SetWindowLong (USER.136)
2172 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2174 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2178 /**********************************************************************
2179 * SetWindowLongA (USER32.@)
2181 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2183 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2187 /**********************************************************************
2188 * SetWindowLongW (USER32.@) Set window attribute
2190 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2191 * value in a window's extra memory.
2193 * The _hwnd_ parameter specifies the window. is the handle to a
2194 * window that has extra memory. The _newval_ parameter contains the
2195 * new attribute or extra memory value. If positive, the _offset_
2196 * parameter is the byte-addressed location in the window's extra
2197 * memory to set. If negative, _offset_ specifies the window
2198 * attribute to set, and should be one of the following values:
2200 * GWL_EXSTYLE The window's extended window style
2202 * GWL_STYLE The window's window style.
2204 * GWL_WNDPROC Pointer to the window's window procedure.
2206 * GWL_HINSTANCE The window's pplication instance handle.
2208 * GWL_ID The window's identifier.
2210 * GWL_USERDATA The window's user-specified data.
2212 * If the window is a dialog box, the _offset_ parameter can be one of
2213 * the following values:
2215 * DWL_DLGPROC The address of the window's dialog box procedure.
2217 * DWL_MSGRESULT The return value of a message
2218 * that the dialog box procedure processed.
2220 * DWL_USER Application specific information.
2224 * If successful, returns the previous value located at _offset_. Otherwise,
2229 * Extra memory for a window class is specified by a nonzero cbWndExtra
2230 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2231 * time of class creation.
2233 * Using GWL_WNDPROC to set a new window procedure effectively creates
2234 * a window subclass. Use CallWindowProc() in the new windows procedure
2235 * to pass messages to the superclass's window procedure.
2237 * The user data is reserved for use by the application which created
2240 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2241 * instead, call the EnableWindow() function to change the window's
2244 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2245 * SetParent() instead.
2248 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2249 * it sends WM_STYLECHANGING before changing the settings
2250 * and WM_STYLECHANGED afterwards.
2251 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2253 LONG WINAPI SetWindowLongW(
2254 HWND hwnd, /* [in] window to alter */
2255 INT offset, /* [in] offset, in bytes, of location to alter */
2256 LONG newval /* [in] new value of location */
2258 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2262 /*******************************************************************
2263 * GetWindowTextA (USER32.@)
2265 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2269 if (WIN_IsCurrentProcess( hwnd ))
2270 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2272 /* when window belongs to other process, don't send a message */
2273 if (nMaxCount <= 0) return 0;
2274 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2275 get_server_window_text( hwnd, buffer, nMaxCount );
2276 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2277 lpString[nMaxCount-1] = 0;
2278 HeapFree( GetProcessHeap(), 0, buffer );
2279 return strlen(lpString);
2283 /*******************************************************************
2284 * InternalGetWindowText (USER32.@)
2286 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2290 if (nMaxCount <= 0) return 0;
2291 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2292 if (win != WND_OTHER_PROCESS)
2294 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2295 else lpString[0] = 0;
2296 WIN_ReleasePtr( win );
2300 get_server_window_text( hwnd, lpString, nMaxCount );
2302 return strlenW(lpString);
2306 /*******************************************************************
2307 * GetWindowTextW (USER32.@)
2309 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2311 if (WIN_IsCurrentProcess( hwnd ))
2312 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2314 /* when window belongs to other process, don't send a message */
2315 if (nMaxCount <= 0) return 0;
2316 get_server_window_text( hwnd, lpString, nMaxCount );
2317 return strlenW(lpString);
2321 /*******************************************************************
2322 * SetWindowText (USER32.@)
2323 * SetWindowTextA (USER32.@)
2325 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2327 if (!WIN_IsCurrentProcess( hwnd ))
2329 FIXME( "cannot set text %s of other process window %x\n", debugstr_a(lpString), hwnd );
2330 SetLastError( ERROR_ACCESS_DENIED );
2333 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2337 /*******************************************************************
2338 * SetWindowTextW (USER32.@)
2340 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2342 if (!WIN_IsCurrentProcess( hwnd ))
2344 FIXME( "cannot set text %s of other process window %x\n", debugstr_w(lpString), hwnd );
2345 SetLastError( ERROR_ACCESS_DENIED );
2348 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2352 /*******************************************************************
2353 * GetWindowTextLengthA (USER32.@)
2355 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2357 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2360 /*******************************************************************
2361 * GetWindowTextLengthW (USER32.@)
2363 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2365 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2369 /*******************************************************************
2370 * IsWindow (USER32.@)
2372 BOOL WINAPI IsWindow( HWND hwnd )
2377 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2379 if (ptr != WND_OTHER_PROCESS)
2381 WIN_ReleasePtr( ptr );
2385 /* check other processes */
2386 SERVER_START_REQ( get_window_info )
2389 ret = !wine_server_call_err( req );
2396 /***********************************************************************
2397 * GetWindowThreadProcessId (USER32.@)
2399 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2404 if (!(ptr = WIN_GetPtr( hwnd )))
2406 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2410 if (ptr != WND_OTHER_PROCESS)
2412 /* got a valid window */
2414 if (process) *process = GetCurrentProcessId();
2415 WIN_ReleasePtr( ptr );
2419 /* check other processes */
2420 SERVER_START_REQ( get_window_info )
2423 if (!wine_server_call_err( req ))
2425 tid = (DWORD)reply->tid;
2426 if (process) *process = (DWORD)reply->pid;
2434 /*****************************************************************
2435 * GetParent (USER32.@)
2437 HWND WINAPI GetParent( HWND hwnd )
2442 if (!(wndPtr = WIN_GetPtr( hwnd )))
2444 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2447 if (wndPtr == WND_OTHER_PROCESS)
2449 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2450 if (style & (WS_POPUP | WS_CHILD))
2452 SERVER_START_REQ( get_window_tree )
2455 if (!wine_server_call_err( req ))
2457 if (style & WS_POPUP) retvalue = reply->owner;
2458 else if (style & WS_CHILD) retvalue = reply->parent;
2466 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2467 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2468 WIN_ReleasePtr( wndPtr );
2474 /*****************************************************************
2475 * GetAncestor (USER32.@)
2477 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2480 HWND *list, ret = 0;
2485 if (!(win = WIN_GetPtr( hwnd )))
2487 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2490 if (win != WND_OTHER_PROCESS)
2493 WIN_ReleasePtr( win );
2495 else /* need to query the server */
2497 SERVER_START_REQ( get_window_tree )
2500 if (!wine_server_call_err( req )) ret = reply->parent;
2507 if (!(list = WIN_ListParents( hwnd ))) return 0;
2509 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2513 while (list[count]) count++;
2514 ret = list[count - 2]; /* get the one before the desktop */
2516 HeapFree( GetProcessHeap(), 0, list );
2520 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2523 HWND parent = GetParent( ret );
2533 /*****************************************************************
2534 * SetParent (USER32.@)
2536 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2539 HWND retvalue, full_handle;
2542 if (!parent) parent = GetDesktopWindow();
2543 else parent = WIN_GetFullHandle( parent );
2545 if (!IsWindow( parent ))
2547 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2551 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2552 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2556 if (USER_Driver.pSetParent)
2557 return USER_Driver.pSetParent( hwnd, parent );
2559 /* Windows hides the window first, then shows it again
2560 * including the WM_SHOWWINDOW messages and all */
2561 was_visible = ShowWindow( hwnd, SW_HIDE );
2563 if (!IsWindow( parent )) return 0;
2564 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2566 retvalue = wndPtr->parent; /* old parent */
2567 if (parent != retvalue)
2569 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2571 if (parent != GetDesktopWindow()) /* a child window */
2573 if (!(wndPtr->dwStyle & WS_CHILD))
2575 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2576 if (menu) DestroyMenu( menu );
2580 WIN_ReleasePtr( wndPtr );
2582 /* SetParent additionally needs to make hwnd the topmost window
2583 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2584 WM_WINDOWPOSCHANGED notification messages.
2586 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2587 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2588 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2589 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2594 /*******************************************************************
2595 * IsChild (USER32.@)
2597 BOOL WINAPI IsChild( HWND parent, HWND child )
2599 HWND *list = WIN_ListParents( child );
2603 if (!list) return FALSE;
2604 parent = WIN_GetFullHandle( parent );
2605 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2606 ret = (list[i] != 0);
2607 HeapFree( GetProcessHeap(), 0, list );
2612 /***********************************************************************
2613 * IsWindowVisible (USER32.@)
2615 BOOL WINAPI IsWindowVisible( HWND hwnd )
2621 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2622 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2623 for (i = 0; list[i]; i++)
2624 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2626 HeapFree( GetProcessHeap(), 0, list );
2631 /***********************************************************************
2632 * WIN_IsWindowDrawable
2634 * hwnd is drawable when it is visible, all parents are not
2635 * minimized, and it is itself not minimized unless we are
2636 * trying to draw its default class icon.
2638 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2643 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2645 if (!(style & WS_VISIBLE)) return FALSE;
2646 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2648 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2649 for (i = 0; list[i]; i++)
2650 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2653 HeapFree( GetProcessHeap(), 0, list );
2658 /*******************************************************************
2659 * GetTopWindow (USER32.@)
2661 HWND WINAPI GetTopWindow( HWND hwnd )
2663 if (!hwnd) hwnd = GetDesktopWindow();
2664 return GetWindow( hwnd, GW_CHILD );
2668 /*******************************************************************
2669 * GetWindow (USER32.@)
2671 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2675 if (rel == GW_OWNER) /* this one may be available locally */
2677 WND *wndPtr = WIN_GetPtr( hwnd );
2680 SetLastError( ERROR_INVALID_HANDLE );
2683 if (wndPtr != WND_OTHER_PROCESS)
2685 retval = wndPtr->owner;
2686 WIN_ReleasePtr( wndPtr );
2689 /* else fall through to server call */
2692 SERVER_START_REQ( get_window_tree )
2695 if (!wine_server_call_err( req ))
2700 retval = reply->first_sibling;
2703 retval = reply->last_sibling;
2706 retval = reply->next_sibling;
2709 retval = reply->prev_sibling;
2712 retval = reply->owner;
2715 retval = reply->first_child;
2725 /***********************************************************************
2726 * WIN_InternalShowOwnedPopups
2728 * Internal version of ShowOwnedPopups; Wine functions should use this
2729 * to avoid interfering with application calls to ShowOwnedPopups
2730 * and to make sure the application can't prevent showing/hiding.
2732 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2736 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2740 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2742 if (!win_array) return TRUE;
2745 * Show windows Lowest first, Highest last to preserve Z-Order
2747 while (win_array[count]) count++;
2748 while (--count >= 0)
2750 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2751 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2753 if (pWnd->dwStyle & WS_POPUP)
2757 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2758 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2761 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2763 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2764 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2769 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2770 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2771 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2774 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2776 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2777 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2778 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2782 WIN_ReleaseWndPtr( pWnd );
2784 HeapFree( GetProcessHeap(), 0, win_array );
2789 /*******************************************************************
2790 * ShowOwnedPopups (USER32.@)
2792 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2796 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2798 if (!win_array) return TRUE;
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 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2812 /* In Windows, ShowOwnedPopups(TRUE) generates
2813 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2814 * regardless of the state of the owner
2816 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2817 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2822 if (IsWindowVisible(pWnd->hwndSelf))
2824 /* In Windows, ShowOwnedPopups(FALSE) generates
2825 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2826 * regardless of the state of the owner
2828 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2829 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2833 WIN_ReleaseWndPtr( pWnd );
2835 HeapFree( GetProcessHeap(), 0, win_array );
2840 /*******************************************************************
2841 * GetLastActivePopup (USER32.@)
2843 HWND WINAPI GetLastActivePopup( HWND hwnd )
2847 SERVER_START_REQ( get_window_info )
2850 if (!wine_server_call_err( req )) retval = reply->last_active;
2857 /*******************************************************************
2860 * Build an array of all parents of a given window, starting with
2861 * the immediate parent. The array must be freed with HeapFree.
2862 * Returns NULL if window is a top-level window.
2864 HWND *WIN_ListParents( HWND hwnd )
2867 HWND current, *list;
2868 int pos = 0, size = 16, count = 0;
2870 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2875 if (!(win = WIN_GetPtr( current ))) goto empty;
2876 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2877 list[pos] = win->parent;
2878 WIN_ReleasePtr( win );
2879 if (!(current = list[pos]))
2881 if (!pos) goto empty;
2884 if (++pos == size - 1)
2886 /* need to grow the list */
2887 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2888 if (!new_list) goto empty;
2894 /* at least one parent belongs to another process, have to query the server */
2899 SERVER_START_REQ( get_window_parents )
2902 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2903 if (!wine_server_call( req )) count = reply->count;
2906 if (!count) goto empty;
2912 HeapFree( GetProcessHeap(), 0, list );
2914 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2918 HeapFree( GetProcessHeap(), 0, list );
2923 /*******************************************************************
2926 * Build an array of the children of a given window. The array must be
2927 * freed with HeapFree. Returns NULL when no windows are found.
2929 HWND *WIN_ListChildren( HWND hwnd )
2931 return list_window_children( hwnd, 0, 0 );
2935 /*******************************************************************
2936 * EnumWindows (USER32.@)
2938 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2944 /* We have to build a list of all windows first, to avoid */
2945 /* unpleasant side-effects, for instance if the callback */
2946 /* function changes the Z-order of the windows. */
2948 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2950 /* Now call the callback function for every window */
2952 iWndsLocks = WIN_SuspendWndsLock();
2953 for (i = 0; list[i]; i++)
2955 /* Make sure that the window still exists */
2956 if (!IsWindow( list[i] )) continue;
2957 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2959 WIN_RestoreWndsLock(iWndsLocks);
2960 HeapFree( GetProcessHeap(), 0, list );
2965 /**********************************************************************
2966 * EnumThreadWindows (USER32.@)
2968 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2973 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2975 /* Now call the callback function for every window */
2977 iWndsLocks = WIN_SuspendWndsLock();
2978 for (i = 0; list[i]; i++)
2979 if (!func( list[i], lParam )) break;
2980 WIN_RestoreWndsLock(iWndsLocks);
2981 HeapFree( GetProcessHeap(), 0, list );
2986 /**********************************************************************
2987 * WIN_EnumChildWindows
2989 * Helper function for EnumChildWindows().
2991 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2996 for ( ; *list; list++)
2998 /* Make sure that the window still exists */
2999 if (!IsWindow( *list )) continue;
3000 /* skip owned windows */
3001 if (GetWindow( *list, GW_OWNER )) continue;
3002 /* Build children list first */
3003 childList = WIN_ListChildren( *list );
3005 ret = func( *list, lParam );
3009 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
3010 HeapFree( GetProcessHeap(), 0, childList );
3012 if (!ret) return FALSE;
3018 /**********************************************************************
3019 * EnumChildWindows (USER32.@)
3021 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3026 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3027 iWndsLocks = WIN_SuspendWndsLock();
3028 WIN_EnumChildWindows( list, func, lParam );
3029 WIN_RestoreWndsLock(iWndsLocks);
3030 HeapFree( GetProcessHeap(), 0, list );
3035 /*******************************************************************
3036 * AnyPopup (USER.52)
3038 BOOL16 WINAPI AnyPopup16(void)
3044 /*******************************************************************
3045 * AnyPopup (USER32.@)
3047 BOOL WINAPI AnyPopup(void)
3051 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3053 if (!list) return FALSE;
3054 for (i = 0; list[i]; i++)
3056 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3058 retvalue = (list[i] != 0);
3059 HeapFree( GetProcessHeap(), 0, list );
3064 /*******************************************************************
3065 * FlashWindow (USER32.@)
3067 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3069 WND *wndPtr = WIN_FindWndPtr(hWnd);
3071 TRACE("%04x\n", hWnd);
3073 if (!wndPtr) return FALSE;
3074 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3076 if (wndPtr->dwStyle & WS_MINIMIZE)
3078 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3080 HDC hDC = GetDC(hWnd);
3082 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM)hDC, 0 ))
3083 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3085 ReleaseDC( hWnd, hDC );
3086 wndPtr->flags |= WIN_NCACTIVATED;
3090 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3091 wndPtr->flags &= ~WIN_NCACTIVATED;
3093 WIN_ReleaseWndPtr(wndPtr);
3099 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3100 else wparam = (hWnd == GetForegroundWindow());
3102 WIN_ReleaseWndPtr(wndPtr);
3103 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3109 /*******************************************************************
3110 * GetWindowContextHelpId (USER32.@)
3112 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3115 WND *wnd = WIN_FindWndPtr( hwnd );
3117 retval = wnd->helpContext;
3118 WIN_ReleaseWndPtr(wnd);
3123 /*******************************************************************
3124 * SetWindowContextHelpId (USER32.@)
3126 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3128 WND *wnd = WIN_FindWndPtr( hwnd );
3129 if (!wnd) return FALSE;
3130 wnd->helpContext = id;
3131 WIN_ReleaseWndPtr(wnd);
3136 /*******************************************************************
3137 * DragDetect (USER32.@)
3139 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3144 rect.left = pt.x - wDragWidth;
3145 rect.right = pt.x + wDragWidth;
3147 rect.top = pt.y - wDragHeight;
3148 rect.bottom = pt.y + wDragHeight;
3154 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3156 if( msg.message == WM_LBUTTONUP )
3161 if( msg.message == WM_MOUSEMOVE )
3164 tmp.x = LOWORD(msg.lParam);
3165 tmp.y = HIWORD(msg.lParam);
3166 if( !PtInRect( &rect, tmp ))
3178 /******************************************************************************
3179 * GetWindowModuleFileNameA (USER32.@)
3181 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3183 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3184 hwnd, lpszFileName, cchFileNameMax);
3188 /******************************************************************************
3189 * GetWindowModuleFileNameW (USER32.@)
3191 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3193 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3194 hwnd, lpszFileName, cchFileNameMax);
3198 /******************************************************************************
3199 * GetWindowInfo (USER32.@)
3202 * MS Documentation mentions that pwi->cbSize must be set to SIZEOF(WINDOWINFO)
3203 * this may be because this structure changed over time. If this is the
3204 * the case, then please: FIXME.
3205 * Using the structure described in MSDN for 98/ME/NT(4.0 SP3)/2000/XP.
3207 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3209 WND *wndInfo = NULL;
3210 if (!pwi) return FALSE;
3211 if (pwi->cbSize != sizeof(WINDOWINFO))
3213 FIXME("windowinfo->cbSize != sizeof(WINDOWINFO). Please report\n");
3216 wndInfo = WIN_GetPtr(hwnd);
3217 if (!wndInfo) return FALSE;
3218 if (wndInfo == WND_OTHER_PROCESS)
3220 FIXME("window belong to other process\n");
3224 pwi->rcWindow = wndInfo->rectWindow;
3225 pwi->rcClient = wndInfo->rectClient;
3226 pwi->dwStyle = wndInfo->dwStyle;
3227 pwi->dwExStyle = wndInfo->dwExStyle;
3228 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3229 /* if active WS_ACTIVECAPTION, else 0 */
3231 pwi->cxWindowBorders = ((wndInfo->dwStyle & WS_BORDER) ?
3232 GetSystemMetrics(SM_CXBORDER) : 0);
3233 pwi->cyWindowBorders = ((wndInfo->dwStyle & WS_BORDER) ?
3234 GetSystemMetrics(SM_CYBORDER) : 0);
3235 /* above two: I'm presuming that borders widths are the same
3236 * for each window - so long as its actually using a border.. */
3238 pwi->atomWindowType = GetClassLongA( hwnd, GCW_ATOM );
3239 pwi->wCreatorVersion = GetVersion();
3240 /* Docs say this should be the version that
3241 * CREATED the window. But eh?.. Isn't that just the
3242 * version we are running.. Unless ofcourse its some wacky
3243 * RPC stuff or something */
3245 WIN_ReleasePtr(wndInfo);