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"
43 #include "stackframe.h"
44 #include "wine/debug.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(win);
47 WINE_DECLARE_DEBUG_CHANNEL(msg);
49 #define NB_USER_HANDLES (LAST_USER_HANDLE - FIRST_USER_HANDLE + 1)
51 /**********************************************************************/
54 static WND *pWndDesktop = NULL;
56 static WORD wDragWidth = 4;
57 static WORD wDragHeight= 3;
59 static void *user_handles[NB_USER_HANDLES];
62 extern SYSLEVEL USER_SysLevel; /* FIXME */
64 /***********************************************************************
67 * Suspend the lock on WND structures.
68 * Returns the number of locks suspended
70 int WIN_SuspendWndsLock( void )
72 int isuspendedLocks = _ConfirmSysLevel( &USER_SysLevel );
73 int count = isuspendedLocks;
76 _LeaveSysLevel( &USER_SysLevel );
78 return isuspendedLocks;
81 /***********************************************************************
84 * Restore the suspended locks on WND structures
86 void WIN_RestoreWndsLock( int ipreviousLocks )
88 while ( ipreviousLocks-- > 0 )
89 _EnterSysLevel( &USER_SysLevel );
92 /***********************************************************************
93 * create_window_handle
95 * Create a window handle with the server.
97 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom, INT size )
100 user_handle_t handle = 0;
102 WND *win = HeapAlloc( GetProcessHeap(), 0, size );
104 if (!win) return NULL;
108 SERVER_START_REQ( create_window )
110 req->parent = parent;
113 if ((res = !wine_server_call_err( req ))) handle = reply->handle;
120 HeapFree( GetProcessHeap(), 0, win );
123 index = LOWORD(handle) - FIRST_USER_HANDLE;
124 assert( index < NB_USER_HANDLES );
125 user_handles[index] = win;
126 win->hwndSelf = handle;
127 win->dwMagic = WND_MAGIC;
133 /***********************************************************************
136 * Free a window handle.
138 static WND *free_window_handle( HWND hwnd )
141 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
143 if (index >= NB_USER_HANDLES) return NULL;
145 if ((ptr = user_handles[index]))
147 SERVER_START_REQ( destroy_window )
150 if (!wine_server_call_err( req ))
151 user_handles[index] = NULL;
158 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
163 /*******************************************************************
164 * list_window_children
166 * Build an array of the children of a given window. The array must be
167 * freed with HeapFree. Returns NULL when no windows are found.
169 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
178 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
180 SERVER_START_REQ( get_window_children )
185 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
186 if (!wine_server_call( req )) count = reply->count;
189 if (count && count < size)
194 HeapFree( GetProcessHeap(), 0, list );
196 size = count + 1; /* restart with a large enough buffer */
202 /*******************************************************************
205 static void send_parent_notify( HWND hwnd, UINT msg )
207 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) return;
208 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) return;
209 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
210 MAKEWPARAM( msg, GetWindowLongW( hwnd, GWL_ID )), (LPARAM)hwnd );
214 /*******************************************************************
215 * get_server_window_text
217 * Retrieve the window text from the server.
219 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
223 SERVER_START_REQ( get_window_text )
226 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
227 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
230 text[len / sizeof(WCHAR)] = 0;
234 /***********************************************************************
237 * Return a pointer to the WND structure if local to the process,
238 * or WND_OTHER_PROCESS if handle may be valid in other process.
239 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
241 WND *WIN_GetPtr( HWND hwnd )
244 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
246 if (index >= NB_USER_HANDLES) return NULL;
249 if ((ptr = user_handles[index]))
251 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
255 else ptr = WND_OTHER_PROCESS;
261 /***********************************************************************
262 * WIN_IsCurrentProcess
264 * Check whether a given window belongs to the current process (and return the full handle).
266 HWND WIN_IsCurrentProcess( HWND hwnd )
271 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
273 WIN_ReleasePtr( ptr );
278 /***********************************************************************
279 * WIN_IsCurrentThread
281 * Check whether a given window belongs to the current thread (and return the full handle).
283 HWND WIN_IsCurrentThread( HWND hwnd )
288 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
290 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
291 WIN_ReleasePtr( ptr );
297 /***********************************************************************
300 * Convert a 16-bit window handle to a full 32-bit handle.
302 HWND WIN_Handle32( HWND16 hwnd16 )
305 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
307 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
308 /* do sign extension for -2 and -3 */
309 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
311 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
313 if (ptr != WND_OTHER_PROCESS)
315 hwnd = ptr->hwndSelf;
316 WIN_ReleasePtr( ptr );
318 else /* may belong to another process */
320 SERVER_START_REQ( get_window_info )
323 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
331 /***********************************************************************
334 * Return a pointer to the WND structure corresponding to a HWND.
336 WND * WIN_FindWndPtr( HWND hwnd )
340 if (!hwnd) return NULL;
342 if ((ptr = WIN_GetPtr( hwnd )))
344 if (ptr != WND_OTHER_PROCESS)
346 /* increment destruction monitoring */
350 if (IsWindow( hwnd )) /* check other processes */
352 ERR( "window %04x belongs to other process\n", hwnd );
353 /* DbgBreakPoint(); */
356 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
361 /***********************************************************************
364 * Release the pointer to the WND structure.
366 void WIN_ReleaseWndPtr(WND *wndPtr)
370 /* Decrement destruction monitoring value */
372 /* Check if it's time to release the memory */
373 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
376 free_window_handle( wndPtr->hwndSelf );
378 else if(wndPtr->irefCount < 0)
380 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
381 ERR("forgot a Lock on %p somewhere\n",wndPtr);
383 /* unlock all WND structures for thread safeness */
388 /***********************************************************************
391 * Remove a window from the siblings linked list.
393 void WIN_UnlinkWindow( HWND hwnd )
395 WIN_LinkWindow( hwnd, 0, 0 );
399 /***********************************************************************
402 * Insert a window into the siblings linked list.
403 * The window is inserted after the specified window, which can also
404 * be specified as HWND_TOP or HWND_BOTTOM.
405 * If parent is 0, window is unlinked from the tree.
407 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
409 WND *wndPtr = WIN_GetPtr( hwnd );
412 if (wndPtr == WND_OTHER_PROCESS)
414 if (IsWindow(hwnd)) ERR(" cannot link other process window %x\n", hwnd );
418 SERVER_START_REQ( link_window )
421 req->parent = parent;
422 req->previous = hwndInsertAfter;
423 if (!wine_server_call( req ))
425 if (reply->full_parent) wndPtr->parent = reply->full_parent;
430 WIN_ReleasePtr( wndPtr );
434 /***********************************************************************
437 * Change the owner of a window.
439 HWND WIN_SetOwner( HWND hwnd, HWND owner )
441 WND *win = WIN_GetPtr( hwnd );
445 if (win == WND_OTHER_PROCESS)
447 if (IsWindow(hwnd)) ERR( "cannot set owner %x on other process window %x\n", owner, hwnd );
450 SERVER_START_REQ( set_window_owner )
454 if (!wine_server_call( req ))
456 win->owner = reply->full_owner;
457 ret = reply->prev_owner;
461 WIN_ReleasePtr( win );
466 /***********************************************************************
469 * Change the style of a window.
471 LONG WIN_SetStyle( HWND hwnd, LONG style )
475 WND *win = WIN_GetPtr( hwnd );
478 if (win == WND_OTHER_PROCESS)
481 ERR( "cannot set style %lx on other process window %x\n", style, hwnd );
484 if (style == win->dwStyle)
486 WIN_ReleasePtr( win );
489 SERVER_START_REQ( set_window_info )
492 req->flags = SET_WIN_STYLE;
494 if ((ok = !wine_server_call( req )))
496 ret = reply->old_style;
497 win->dwStyle = style;
501 WIN_ReleasePtr( win );
502 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret );
507 /***********************************************************************
510 * Change the extended style of a window.
512 LONG WIN_SetExStyle( HWND hwnd, LONG style )
515 WND *win = WIN_GetPtr( hwnd );
518 if (win == WND_OTHER_PROCESS)
521 ERR( "cannot set exstyle %lx on other process window %x\n", style, hwnd );
524 if (style == win->dwExStyle)
526 WIN_ReleasePtr( win );
529 SERVER_START_REQ( set_window_info )
532 req->flags = SET_WIN_EXSTYLE;
533 req->ex_style = style;
534 if (!wine_server_call( req ))
536 ret = reply->old_ex_style;
537 win->dwExStyle = style;
541 WIN_ReleasePtr( win );
546 /***********************************************************************
549 * Set the window and client rectangles.
551 void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient )
553 WND *win = WIN_GetPtr( hwnd );
557 if (win == WND_OTHER_PROCESS)
559 if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %x\n", hwnd );
562 SERVER_START_REQ( set_window_rectangles )
565 req->window.left = rectWindow->left;
566 req->window.top = rectWindow->top;
567 req->window.right = rectWindow->right;
568 req->window.bottom = rectWindow->bottom;
569 req->client.left = rectClient->left;
570 req->client.top = rectClient->top;
571 req->client.right = rectClient->right;
572 req->client.bottom = rectClient->bottom;
573 ret = !wine_server_call( req );
578 win->rectWindow = *rectWindow;
579 win->rectClient = *rectClient;
581 TRACE( "win %x window (%d,%d)-(%d,%d) client (%d,%d)-(%d,%d)\n", hwnd,
582 rectWindow->left, rectWindow->top, rectWindow->right, rectWindow->bottom,
583 rectClient->left, rectClient->top, rectClient->right, rectClient->bottom );
585 WIN_ReleasePtr( win );
589 /***********************************************************************
592 * Get the window and client rectangles.
594 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
596 WND *win = WIN_GetPtr( hwnd );
599 if (!win) return FALSE;
600 if (win == WND_OTHER_PROCESS)
602 SERVER_START_REQ( get_window_rectangles )
605 if ((ret = !wine_server_call( req )))
609 rectWindow->left = reply->window.left;
610 rectWindow->top = reply->window.top;
611 rectWindow->right = reply->window.right;
612 rectWindow->bottom = reply->window.bottom;
616 rectClient->left = reply->client.left;
617 rectClient->top = reply->client.top;
618 rectClient->right = reply->client.right;
619 rectClient->bottom = reply->client.bottom;
627 if (rectWindow) *rectWindow = win->rectWindow;
628 if (rectClient) *rectClient = win->rectClient;
629 WIN_ReleasePtr( win );
635 /***********************************************************************
638 * Destroy storage associated to a window. "Internals" p.358
640 LRESULT WIN_DestroyWindow( HWND hwnd )
645 TRACE("%04x\n", hwnd );
647 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
649 ERR( "window doesn't belong to current thread\n" );
653 /* free child windows */
654 if ((list = WIN_ListChildren( hwnd )))
657 for (i = 0; list[i]; i++)
659 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
660 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
662 HeapFree( GetProcessHeap(), 0, list );
666 * Clear the update region to make sure no WM_PAINT messages will be
667 * generated for this window while processing the WM_NCDESTROY.
669 RedrawWindow( hwnd, NULL, 0,
670 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
673 * Send the WM_NCDESTROY to the window being destroyed.
675 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
677 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
679 WINPOS_CheckInternalPos( hwnd );
680 if( hwnd == GetCapture()) ReleaseCapture();
682 /* free resources associated with the window */
684 TIMER_RemoveWindowTimers( hwnd );
686 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
688 if (!(wndPtr->dwStyle & WS_CHILD))
690 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
691 if (menu) DestroyMenu( menu );
693 if (wndPtr->hSysMenu)
695 DestroyMenu( wndPtr->hSysMenu );
696 wndPtr->hSysMenu = 0;
698 USER_Driver.pDestroyWindow( hwnd );
699 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
700 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
701 CLASS_RemoveWindow( wndPtr->class );
702 wndPtr->class = NULL;
703 wndPtr->dwMagic = 0; /* Mark it as invalid */
704 WIN_ReleaseWndPtr( wndPtr );
708 /***********************************************************************
709 * WIN_DestroyThreadWindows
711 * Destroy all children of 'wnd' owned by the current thread.
712 * Return TRUE if something was done.
714 void WIN_DestroyThreadWindows( HWND hwnd )
719 if (!(list = WIN_ListChildren( hwnd ))) return;
720 for (i = 0; list[i]; i++)
722 if (WIN_IsCurrentThread( list[i] ))
723 DestroyWindow( list[i] );
725 WIN_DestroyThreadWindows( list[i] );
727 HeapFree( GetProcessHeap(), 0, list );
730 /***********************************************************************
731 * WIN_CreateDesktopWindow
733 * Create the desktop window.
735 BOOL WIN_CreateDesktopWindow(void)
737 struct tagCLASS *class;
746 TRACE("Creating desktop window\n");
748 if (!WINPOS_CreateInternalPosAtom() ||
749 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
750 &wndExtra, &winproc, &clsStyle, &dce )))
753 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM),
754 sizeof(WND) + wndExtra - sizeof(pWndDesktop->wExtra) );
755 if (!pWndDesktop) return FALSE;
756 hwndDesktop = pWndDesktop->hwndSelf;
758 pWndDesktop->tid = 0; /* nobody owns the desktop */
759 pWndDesktop->parent = 0;
760 pWndDesktop->owner = 0;
761 pWndDesktop->class = class;
762 pWndDesktop->text = NULL;
763 pWndDesktop->hrgnUpdate = 0;
764 pWndDesktop->clsStyle = clsStyle;
765 pWndDesktop->dce = NULL;
766 pWndDesktop->pVScroll = NULL;
767 pWndDesktop->pHScroll = NULL;
768 pWndDesktop->helpContext = 0;
769 pWndDesktop->flags = 0;
770 pWndDesktop->hSysMenu = 0;
771 pWndDesktop->winproc = winproc;
772 pWndDesktop->cbWndExtra = wndExtra;
774 cs.lpCreateParams = NULL;
780 cs.cx = GetSystemMetrics( SM_CXSCREEN );
781 cs.cy = GetSystemMetrics( SM_CYSCREEN );
782 cs.style = pWndDesktop->dwStyle;
783 cs.dwExStyle = pWndDesktop->dwExStyle;
785 cs.lpszClass = DESKTOP_CLASS_ATOM;
787 SetRect( &rect, 0, 0, cs.cx, cs.cy );
788 WIN_SetRectangles( hwndDesktop, &rect, &rect );
790 SERVER_START_REQ( set_window_info )
792 req->handle = hwndDesktop;
793 req->flags = 0; /* don't set anything, just retrieve */
794 wine_server_call( req );
795 pWndDesktop->dwStyle = reply->old_style;
796 pWndDesktop->dwExStyle = reply->old_ex_style;
797 pWndDesktop->hInstance = (ULONG_PTR)reply->old_instance;
798 pWndDesktop->userdata = (ULONG_PTR)reply->old_user_data;
799 pWndDesktop->wIDmenu = reply->old_id;
803 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE ))
805 WIN_ReleaseWndPtr( pWndDesktop );
809 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
810 WIN_ReleaseWndPtr( pWndDesktop );
815 /***********************************************************************
818 * Fix the coordinates - Helper for WIN_CreateWindowEx.
819 * returns default show mode in sw.
820 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
822 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
824 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
825 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
827 if (cs->style & (WS_CHILD | WS_POPUP))
829 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
830 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
832 else /* overlapped window */
836 GetStartupInfoA( &info );
838 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
840 /* Never believe Microsoft's documentation... CreateWindowEx doc says
841 * that if an overlapped window is created with WS_VISIBLE style bit
842 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
843 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
846 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
847 * 2) it does not ignore the y parameter as the docs claim; instead, it
848 * uses it as second parameter to ShowWindow() unless y is either
849 * CW_USEDEFAULT or CW_USEDEFAULT16.
851 * The fact that we didn't do 2) caused bogus windows pop up when wine
852 * was running apps that were using this obscure feature. Example -
853 * calc.exe that comes with Win98 (only Win98, it's different from
854 * the one that comes with Win95 and NT)
856 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
857 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
858 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
861 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
863 if (info.dwFlags & STARTF_USESIZE)
865 cs->cx = info.dwXSize;
866 cs->cy = info.dwYSize;
868 else /* if no other hint from the app, pick 3/4 of the screen real estate */
871 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
872 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
873 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
880 /* neither x nor cx are default. Check the y values .
881 * In the trace we see Outlook and Outlook Express using
882 * cy set to CW_USEDEFAULT when opening the address book.
884 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
886 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
887 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
888 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
893 /***********************************************************************
896 static void dump_window_styles( DWORD style, DWORD exstyle )
899 if(style & WS_POPUP) DPRINTF(" WS_POPUP");
900 if(style & WS_CHILD) DPRINTF(" WS_CHILD");
901 if(style & WS_MINIMIZE) DPRINTF(" WS_MINIMIZE");
902 if(style & WS_VISIBLE) DPRINTF(" WS_VISIBLE");
903 if(style & WS_DISABLED) DPRINTF(" WS_DISABLED");
904 if(style & WS_CLIPSIBLINGS) DPRINTF(" WS_CLIPSIBLINGS");
905 if(style & WS_CLIPCHILDREN) DPRINTF(" WS_CLIPCHILDREN");
906 if(style & WS_MAXIMIZE) DPRINTF(" WS_MAXIMIZE");
907 if((style & WS_CAPTION) == WS_CAPTION) DPRINTF(" WS_CAPTION");
910 if(style & WS_BORDER) DPRINTF(" WS_BORDER");
911 if(style & WS_DLGFRAME) DPRINTF(" WS_DLGFRAME");
913 if(style & WS_VSCROLL) DPRINTF(" WS_VSCROLL");
914 if(style & WS_HSCROLL) DPRINTF(" WS_HSCROLL");
915 if(style & WS_SYSMENU) DPRINTF(" WS_SYSMENU");
916 if(style & WS_THICKFRAME) DPRINTF(" WS_THICKFRAME");
917 if(style & WS_GROUP) DPRINTF(" WS_GROUP");
918 if(style & WS_TABSTOP) DPRINTF(" WS_TABSTOP");
919 if(style & WS_MINIMIZEBOX) DPRINTF(" WS_MINIMIZEBOX");
920 if(style & WS_MAXIMIZEBOX) DPRINTF(" WS_MAXIMIZEBOX");
922 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
923 #define DUMPED_STYLES \
943 if(style & ~DUMPED_STYLES) DPRINTF(" %08lx", style & ~DUMPED_STYLES);
948 if(exstyle & WS_EX_DLGMODALFRAME) DPRINTF(" WS_EX_DLGMODALFRAME");
949 if(exstyle & WS_EX_DRAGDETECT) DPRINTF(" WS_EX_DRAGDETECT");
950 if(exstyle & WS_EX_NOPARENTNOTIFY) DPRINTF(" WS_EX_NOPARENTNOTIFY");
951 if(exstyle & WS_EX_TOPMOST) DPRINTF(" WS_EX_TOPMOST");
952 if(exstyle & WS_EX_ACCEPTFILES) DPRINTF(" WS_EX_ACCEPTFILES");
953 if(exstyle & WS_EX_TRANSPARENT) DPRINTF(" WS_EX_TRANSPARENT");
954 if(exstyle & WS_EX_MDICHILD) DPRINTF(" WS_EX_MDICHILD");
955 if(exstyle & WS_EX_TOOLWINDOW) DPRINTF(" WS_EX_TOOLWINDOW");
956 if(exstyle & WS_EX_WINDOWEDGE) DPRINTF(" WS_EX_WINDOWEDGE");
957 if(exstyle & WS_EX_CLIENTEDGE) DPRINTF(" WS_EX_CLIENTEDGE");
958 if(exstyle & WS_EX_CONTEXTHELP) DPRINTF(" WS_EX_CONTEXTHELP");
959 if(exstyle & WS_EX_RIGHT) DPRINTF(" WS_EX_RIGHT");
960 if(exstyle & WS_EX_RTLREADING) DPRINTF(" WS_EX_RTLREADING");
961 if(exstyle & WS_EX_LEFTSCROLLBAR) DPRINTF(" WS_EX_LEFTSCROLLBAR");
962 if(exstyle & WS_EX_CONTROLPARENT) DPRINTF(" WS_EX_CONTROLPARENT");
963 if(exstyle & WS_EX_STATICEDGE) DPRINTF(" WS_EX_STATICEDGE");
964 if(exstyle & WS_EX_APPWINDOW) DPRINTF(" WS_EX_APPWINDOW");
965 if(exstyle & WS_EX_LAYERED) DPRINTF(" WS_EX_LAYERED");
967 #define DUMPED_EX_STYLES \
968 (WS_EX_DLGMODALFRAME | \
970 WS_EX_NOPARENTNOTIFY | \
972 WS_EX_ACCEPTFILES | \
973 WS_EX_TRANSPARENT | \
978 WS_EX_CONTEXTHELP | \
981 WS_EX_LEFTSCROLLBAR | \
982 WS_EX_CONTROLPARENT | \
987 if(exstyle & ~DUMPED_EX_STYLES) DPRINTF(" %08lx", exstyle & ~DUMPED_EX_STYLES);
989 #undef DUMPED_EX_STYLES
993 /***********************************************************************
996 * Implementation of CreateWindowEx().
998 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
999 WINDOWPROCTYPE type )
1002 struct tagCLASS *classPtr;
1004 HWND hwnd, parent, owner;
1009 BOOL unicode = (type == WIN_PROC_32W);
1011 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%04x menu=%04x inst=%08x params=%p\n",
1012 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
1013 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
1014 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
1015 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
1017 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
1019 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
1020 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
1022 /* Find the parent window */
1024 parent = GetDesktopWindow();
1027 if (cs->hwndParent == HWND_MESSAGE)
1029 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
1030 * message window (style: WS_POPUP|WS_DISABLED)
1032 FIXME("Parent is HWND_MESSAGE\n");
1034 else if (cs->hwndParent)
1036 /* Make sure parent is valid */
1037 if (!IsWindow( cs->hwndParent ))
1039 WARN("Bad parent %04x\n", cs->hwndParent );
1042 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1043 parent = WIN_GetFullHandle(cs->hwndParent);
1045 owner = GetAncestor( cs->hwndParent, GA_ROOT );
1047 else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1049 WARN("No parent for child window\n" );
1050 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1053 /* Find the window class */
1054 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
1055 &wndExtra, &winproc, &clsStyle, &dce )))
1057 WARN("Bad class '%s'\n", cs->lpszClass );
1061 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1063 /* Correct the window style - stage 1
1065 * These are patches that appear to affect both the style loaded into the
1066 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
1068 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1069 * why does the user get to set it?
1072 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1073 * tested for WS_POPUP
1075 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1076 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1077 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1078 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1080 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1082 /* Create the window structure */
1084 if (!(wndPtr = create_window_handle( parent, owner, classAtom,
1085 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
1087 TRACE("out of memory\n" );
1090 hwnd = wndPtr->hwndSelf;
1092 /* Fill the window structure */
1094 wndPtr->tid = GetCurrentThreadId();
1095 wndPtr->owner = owner;
1096 wndPtr->parent = parent;
1097 wndPtr->class = classPtr;
1098 wndPtr->winproc = winproc;
1099 wndPtr->hInstance = cs->hInstance;
1100 wndPtr->text = NULL;
1101 wndPtr->hrgnUpdate = 0;
1102 wndPtr->hrgnWnd = 0;
1103 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1104 wndPtr->dwExStyle = cs->dwExStyle;
1105 wndPtr->clsStyle = clsStyle;
1106 wndPtr->wIDmenu = 0;
1107 wndPtr->helpContext = 0;
1108 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1109 wndPtr->pVScroll = NULL;
1110 wndPtr->pHScroll = NULL;
1111 wndPtr->userdata = 0;
1112 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
1113 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1114 wndPtr->cbWndExtra = wndExtra;
1116 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
1118 /* Correct the window style - stage 2 */
1120 if (!(cs->style & WS_CHILD))
1122 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1123 if (!(cs->style & WS_POPUP))
1125 wndPtr->dwStyle |= WS_CAPTION;
1126 wndPtr->flags |= WIN_NEED_SIZE;
1129 SERVER_START_REQ( set_window_info )
1132 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1133 req->style = wndPtr->dwStyle;
1134 req->ex_style = wndPtr->dwExStyle;
1135 req->instance = (void *)wndPtr->hInstance;
1136 wine_server_call( req );
1140 /* Get class or window DC if needed */
1142 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1143 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
1144 else wndPtr->dce = NULL;
1146 /* Set the window menu */
1148 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
1150 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
1153 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1156 if (HIWORD(cs->hInstance))
1157 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1159 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
1161 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
1165 else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
1166 WIN_ReleaseWndPtr( wndPtr );
1168 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
1170 WIN_DestroyWindow( hwnd );
1174 /* Notify the parent window only */
1176 send_parent_notify( hwnd, WM_CREATE );
1177 if (!IsWindow( hwnd )) return 0;
1179 if (cs->style & WS_VISIBLE)
1181 /* in case WS_VISIBLE got set in the meantime */
1182 if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0;
1183 WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
1184 WIN_ReleasePtr( wndPtr );
1185 ShowWindow( hwnd, sw );
1188 /* Call WH_SHELL hook */
1190 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1191 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0 );
1193 TRACE("created window %04x\n", hwnd);
1198 /***********************************************************************
1199 * CreateWindow (USER.41)
1201 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1202 DWORD style, INT16 x, INT16 y, INT16 width,
1203 INT16 height, HWND16 parent, HMENU16 menu,
1204 HINSTANCE16 instance, LPVOID data )
1206 return CreateWindowEx16( 0, className, windowName, style,
1207 x, y, width, height, parent, menu, instance, data );
1211 /***********************************************************************
1212 * CreateWindowEx (USER.452)
1214 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1215 LPCSTR windowName, DWORD style, INT16 x,
1216 INT16 y, INT16 width, INT16 height,
1217 HWND16 parent, HMENU16 menu,
1218 HINSTANCE16 instance, LPVOID data )
1224 /* Find the class atom */
1226 if (HIWORD(className))
1228 if (!(classAtom = GlobalFindAtomA( className )))
1230 ERR( "bad class name %s\n", debugstr_a(className) );
1236 classAtom = LOWORD(className);
1237 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1239 ERR( "bad atom %x\n", classAtom);
1245 /* Fix the coordinates */
1247 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1248 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1249 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1250 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1252 /* Create the window */
1254 cs.lpCreateParams = data;
1255 cs.hInstance = (HINSTANCE)instance;
1256 cs.hMenu = (HMENU)menu;
1257 cs.hwndParent = WIN_Handle32( parent );
1259 cs.lpszName = windowName;
1260 cs.lpszClass = className;
1261 cs.dwExStyle = exStyle;
1263 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1267 /***********************************************************************
1268 * CreateWindowExA (USER32.@)
1270 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1271 LPCSTR windowName, DWORD style, INT x,
1272 INT y, INT width, INT height,
1273 HWND parent, HMENU menu,
1274 HINSTANCE instance, LPVOID data )
1281 instance=GetModuleHandleA(NULL);
1283 if(exStyle & WS_EX_MDICHILD)
1284 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1286 /* Find the class atom */
1288 if (HIWORD(className))
1290 if (!(classAtom = GlobalFindAtomA( className )))
1292 ERR( "bad class name %s\n", debugstr_a(className) );
1298 classAtom = LOWORD(className);
1299 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1301 ERR( "bad atom %x\n", classAtom);
1307 /* Create the window */
1309 cs.lpCreateParams = data;
1310 cs.hInstance = instance;
1312 cs.hwndParent = parent;
1318 cs.lpszName = windowName;
1319 cs.lpszClass = className;
1320 cs.dwExStyle = exStyle;
1322 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1326 /***********************************************************************
1327 * CreateWindowExW (USER32.@)
1329 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1330 LPCWSTR windowName, DWORD style, INT x,
1331 INT y, INT width, INT height,
1332 HWND parent, HMENU menu,
1333 HINSTANCE instance, LPVOID data )
1340 instance=GetModuleHandleA(NULL);
1342 if(exStyle & WS_EX_MDICHILD)
1343 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1345 /* Find the class atom */
1347 if (HIWORD(className))
1349 if (!(classAtom = GlobalFindAtomW( className )))
1351 ERR( "bad class name %s\n", debugstr_w(className) );
1357 classAtom = LOWORD(className);
1358 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1360 ERR( "bad atom %x\n", classAtom);
1366 /* Create the window */
1368 cs.lpCreateParams = data;
1369 cs.hInstance = instance;
1371 cs.hwndParent = parent;
1377 cs.lpszName = windowName;
1378 cs.lpszClass = className;
1379 cs.dwExStyle = exStyle;
1381 /* Note: we rely on the fact that CREATESTRUCTA and */
1382 /* CREATESTRUCTW have the same layout. */
1383 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1387 /***********************************************************************
1388 * WIN_SendDestroyMsg
1390 static void WIN_SendDestroyMsg( HWND hwnd )
1394 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1396 if (hwnd == info.hwndCaret) DestroyCaret();
1398 if (USER_Driver.pResetSelectionOwner)
1399 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1402 * Send the WM_DESTROY to the window.
1404 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1407 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1408 * make sure that the window still exists when we come back.
1415 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1417 /* start from the end (FIXME: is this needed?) */
1418 for (i = 0; pWndArray[i]; i++) ;
1422 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1424 HeapFree( GetProcessHeap(), 0, pWndArray );
1427 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1431 /***********************************************************************
1432 * DestroyWindow (USER32.@)
1434 BOOL WINAPI DestroyWindow( HWND hwnd )
1439 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1441 SetLastError( ERROR_ACCESS_DENIED );
1445 TRACE("(%04x)\n", hwnd);
1447 /* Look whether the focus is within the tree of windows we will
1451 if (h == hwnd || IsChild( hwnd, h ))
1453 HWND parent = GetAncestor( hwnd, GA_PARENT );
1454 if (parent == GetDesktopWindow()) parent = 0;
1460 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0L) ) return FALSE;
1462 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1466 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1467 send_parent_notify( hwnd, WM_DESTROY );
1469 else if (!GetWindow( hwnd, GW_OWNER ))
1471 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L );
1472 /* FIXME: clean up palette - see "Internals" p.352 */
1475 if (!IsWindow(hwnd)) return TRUE;
1477 if (USER_Driver.pResetSelectionOwner)
1478 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1480 /* Hide the window */
1482 if (!ShowWindow( hwnd, SW_HIDE ))
1484 if (hwnd == GetActiveWindow()) WINPOS_ActivateOtherWindow( hwnd );
1486 if (!IsWindow(hwnd)) return TRUE;
1488 /* Recursively destroy owned windows */
1495 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1498 for (i = 0; list[i]; i++)
1500 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1501 if (WIN_IsCurrentThread( list[i] ))
1503 DestroyWindow( list[i] );
1507 WIN_SetOwner( list[i], 0 );
1509 HeapFree( GetProcessHeap(), 0, list );
1511 if (!got_one) break;
1515 /* Send destroy messages */
1517 WIN_SendDestroyMsg( hwnd );
1518 if (!IsWindow( hwnd )) return TRUE;
1520 /* Unlink now so we won't bother with the children later on */
1522 WIN_UnlinkWindow( hwnd );
1524 /* Destroy the window storage */
1526 WIN_DestroyWindow( hwnd );
1531 /***********************************************************************
1532 * CloseWindow (USER32.@)
1534 BOOL WINAPI CloseWindow( HWND hwnd )
1536 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1537 ShowWindow( hwnd, SW_MINIMIZE );
1542 /***********************************************************************
1543 * OpenIcon (USER32.@)
1545 BOOL WINAPI OpenIcon( HWND hwnd )
1547 if (!IsIconic( hwnd )) return FALSE;
1548 ShowWindow( hwnd, SW_SHOWNORMAL );
1553 /***********************************************************************
1556 * Implementation of FindWindow() and FindWindowEx().
1558 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1563 WCHAR *buffer = NULL;
1565 if (!parent) parent = GetDesktopWindow();
1568 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1569 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1572 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1576 child = WIN_GetFullHandle( child );
1577 while (list[i] && list[i] != child) i++;
1578 if (!list[i]) goto done;
1579 i++; /* start from next window */
1586 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1593 if (list) HeapFree( GetProcessHeap(), 0, list );
1594 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1600 /***********************************************************************
1601 * FindWindowA (USER32.@)
1603 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1605 HWND ret = FindWindowExA( 0, 0, className, title );
1606 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1611 /***********************************************************************
1612 * FindWindowExA (USER32.@)
1614 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1615 LPCSTR className, LPCSTR title )
1624 /* If the atom doesn't exist, then no class */
1625 /* with this name exists either. */
1626 if (!(atom = GlobalFindAtomA( className )))
1628 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1632 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1634 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1635 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1636 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1637 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1638 HeapFree( GetProcessHeap(), 0, buffer );
1643 /***********************************************************************
1644 * FindWindowExW (USER32.@)
1646 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1647 LPCWSTR className, LPCWSTR title )
1653 /* If the atom doesn't exist, then no class */
1654 /* with this name exists either. */
1655 if (!(atom = GlobalFindAtomW( className )))
1657 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1661 return WIN_FindWindow( parent, child, atom, title );
1665 /***********************************************************************
1666 * FindWindowW (USER32.@)
1668 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1670 return FindWindowExW( 0, 0, className, title );
1674 /**********************************************************************
1675 * GetDesktopWindow (USER32.@)
1677 HWND WINAPI GetDesktopWindow(void)
1679 if (pWndDesktop) return pWndDesktop->hwndSelf;
1680 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" );
1686 /*******************************************************************
1687 * EnableWindow (USER32.@)
1689 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1696 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1697 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1701 TRACE("( %x, %d )\n", hwnd, enable);
1703 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1704 style = wndPtr->dwStyle;
1705 retvalue = ((style & WS_DISABLED) != 0);
1706 WIN_ReleasePtr( wndPtr );
1708 if (enable && retvalue)
1710 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1711 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1713 else if (!enable && !retvalue)
1715 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1717 WIN_SetStyle( hwnd, style | WS_DISABLED );
1719 if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1720 SetFocus( 0 ); /* A disabled window can't have the focus */
1722 if (hwnd == GetCapture() || IsChild(hwnd, GetCapture()))
1723 ReleaseCapture(); /* A disabled window can't capture the mouse */
1725 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1731 /***********************************************************************
1732 * IsWindowEnabled (USER32.@)
1734 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1736 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1740 /***********************************************************************
1741 * IsWindowUnicode (USER32.@)
1743 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1748 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1749 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1750 WIN_ReleaseWndPtr(wndPtr);
1755 /**********************************************************************
1756 * GetWindowWord (USER32.@)
1758 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1763 WND *wndPtr = WIN_GetPtr( hwnd );
1766 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1769 if (wndPtr == WND_OTHER_PROCESS)
1771 if (IsWindow( hwnd ))
1772 FIXME( "(%d) not supported yet on other process window %x\n", offset, hwnd );
1773 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1776 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1778 WARN("Invalid offset %d\n", offset );
1779 SetLastError( ERROR_INVALID_INDEX );
1781 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1782 WIN_ReleasePtr( wndPtr );
1788 case GWL_HWNDPARENT:
1789 return GetWindowLongW( hwnd, offset );
1793 LONG ret = GetWindowLongW( hwnd, offset );
1795 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1799 WARN("Invalid offset %d\n", offset );
1805 /**********************************************************************
1806 * SetWindowWord (USER32.@)
1808 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1817 case GWL_HWNDPARENT:
1818 return SetWindowLongW( hwnd, offset, (UINT)newval );
1822 WARN("Invalid offset %d\n", offset );
1823 SetLastError( ERROR_INVALID_INDEX );
1828 wndPtr = WIN_GetPtr( hwnd );
1829 if (wndPtr == WND_OTHER_PROCESS)
1832 FIXME( "set %d <- %x not supported yet on other process window %x\n",
1833 offset, newval, hwnd );
1838 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1842 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1844 WARN("Invalid offset %d\n", offset );
1845 WIN_ReleasePtr(wndPtr);
1846 SetLastError( ERROR_INVALID_INDEX );
1849 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1852 WIN_ReleasePtr(wndPtr);
1857 /**********************************************************************
1860 * Helper function for GetWindowLong().
1862 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1867 if (offset == GWL_HWNDPARENT)
1869 HWND parent = GetAncestor( hwnd, GA_PARENT );
1870 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1871 return (LONG)parent;
1874 if (!(wndPtr = WIN_GetPtr( hwnd )))
1876 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1880 if (wndPtr == WND_OTHER_PROCESS)
1885 FIXME( "(%d) not supported on other process window %x\n", offset, hwnd );
1886 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1889 if (offset == GWL_WNDPROC)
1891 SetLastError( ERROR_ACCESS_DENIED );
1894 SERVER_START_REQ( set_window_info )
1897 req->flags = 0; /* don't set anything, just retrieve */
1898 if (!wine_server_call_err( req ))
1902 case GWL_STYLE: retvalue = reply->old_style; break;
1903 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1904 case GWL_ID: retvalue = reply->old_id; break;
1905 case GWL_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1906 case GWL_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1908 SetLastError( ERROR_INVALID_INDEX );
1917 /* now we have a valid wndPtr */
1921 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
1924 * Some programs try to access last element from 16 bit
1925 * code using illegal offset value. Hopefully this is
1926 * what those programs really expect.
1928 if (type == WIN_PROC_16 &&
1929 wndPtr->cbWndExtra >= 4 &&
1930 offset == wndPtr->cbWndExtra - sizeof(WORD))
1932 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1934 ERR( "- replaced invalid offset %d with %d\n",
1937 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset2);
1938 WIN_ReleasePtr( wndPtr );
1941 WARN("Invalid offset %d\n", offset );
1942 WIN_ReleasePtr( wndPtr );
1943 SetLastError( ERROR_INVALID_INDEX );
1946 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1947 /* Special case for dialog window procedure */
1948 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1949 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1950 WIN_ReleasePtr( wndPtr );
1956 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
1957 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1958 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1959 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
1960 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
1961 case GWL_HINSTANCE: retvalue = wndPtr->hInstance; break;
1963 WARN("Unknown offset %d\n", offset );
1964 SetLastError( ERROR_INVALID_INDEX );
1967 WIN_ReleasePtr(wndPtr);
1972 /**********************************************************************
1975 * Helper function for SetWindowLong().
1977 * 0 is the failure code. However, in the case of failure SetLastError
1978 * must be set to distinguish between a 0 return value and a failure.
1980 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1981 WINDOWPROCTYPE type )
1986 TRACE( "%x %d %lx %x\n", hwnd, offset, newval, type );
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 );
2009 LONG *ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2010 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
2012 WARN("Invalid offset %d\n", offset );
2013 WIN_ReleasePtr( wndPtr );
2014 SetLastError( ERROR_INVALID_INDEX );
2017 /* Special case for dialog window procedure */
2018 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2020 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2021 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2022 type, WIN_PROC_WINDOW );
2023 WIN_ReleasePtr( wndPtr );
2028 WIN_ReleasePtr( wndPtr );
2035 /* first some special cases */
2040 style.styleOld = wndPtr->dwStyle;
2041 style.styleNew = newval;
2042 WIN_ReleasePtr( wndPtr );
2043 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2044 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2045 newval = style.styleNew;
2047 case GWL_HWNDPARENT:
2048 if (wndPtr->parent == GetDesktopWindow())
2050 WIN_ReleasePtr( wndPtr );
2051 return (LONG)WIN_SetOwner( hwnd, (HWND)newval );
2055 WIN_ReleasePtr( wndPtr );
2056 return (LONG)SetParent( hwnd, (HWND)newval );
2059 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2060 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2061 type, WIN_PROC_WINDOW );
2062 WIN_ReleasePtr( wndPtr );
2069 WIN_ReleasePtr( wndPtr );
2070 WARN("Invalid offset %d\n", offset );
2071 SetLastError( ERROR_INVALID_INDEX );
2075 SERVER_START_REQ( set_window_info )
2081 req->flags = SET_WIN_STYLE;
2082 req->style = newval;
2085 req->flags = SET_WIN_EXSTYLE;
2086 req->ex_style = newval;
2089 req->flags = SET_WIN_ID;
2093 req->flags = SET_WIN_INSTANCE;
2094 req->instance = (void *)newval;
2097 req->flags = SET_WIN_USERDATA;
2098 req->user_data = (void *)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 = newval;
2119 retval = (HINSTANCE)reply->old_instance;
2122 wndPtr->userdata = newval;
2123 retval = (ULONG_PTR)reply->old_user_data;
2129 WIN_ReleasePtr( wndPtr );
2133 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2134 USER_Driver.pSetWindowStyle( hwnd, retval );
2136 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2137 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2144 /**********************************************************************
2145 * GetWindowLong (USER.135)
2147 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2149 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2153 /**********************************************************************
2154 * GetWindowLongA (USER32.@)
2156 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2158 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2162 /**********************************************************************
2163 * GetWindowLongW (USER32.@)
2165 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2167 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2171 /**********************************************************************
2172 * SetWindowLong (USER.136)
2174 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2176 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2180 /**********************************************************************
2181 * SetWindowLongA (USER32.@)
2183 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2185 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2189 /**********************************************************************
2190 * SetWindowLongW (USER32.@) Set window attribute
2192 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2193 * value in a window's extra memory.
2195 * The _hwnd_ parameter specifies the window. is the handle to a
2196 * window that has extra memory. The _newval_ parameter contains the
2197 * new attribute or extra memory value. If positive, the _offset_
2198 * parameter is the byte-addressed location in the window's extra
2199 * memory to set. If negative, _offset_ specifies the window
2200 * attribute to set, and should be one of the following values:
2202 * GWL_EXSTYLE The window's extended window style
2204 * GWL_STYLE The window's window style.
2206 * GWL_WNDPROC Pointer to the window's window procedure.
2208 * GWL_HINSTANCE The window's pplication instance handle.
2210 * GWL_ID The window's identifier.
2212 * GWL_USERDATA The window's user-specified data.
2214 * If the window is a dialog box, the _offset_ parameter can be one of
2215 * the following values:
2217 * DWL_DLGPROC The address of the window's dialog box procedure.
2219 * DWL_MSGRESULT The return value of a message
2220 * that the dialog box procedure processed.
2222 * DWL_USER Application specific information.
2226 * If successful, returns the previous value located at _offset_. Otherwise,
2231 * Extra memory for a window class is specified by a nonzero cbWndExtra
2232 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2233 * time of class creation.
2235 * Using GWL_WNDPROC to set a new window procedure effectively creates
2236 * a window subclass. Use CallWindowProc() in the new windows procedure
2237 * to pass messages to the superclass's window procedure.
2239 * The user data is reserved for use by the application which created
2242 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2243 * instead, call the EnableWindow() function to change the window's
2246 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2247 * SetParent() instead.
2250 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2251 * it sends WM_STYLECHANGING before changing the settings
2252 * and WM_STYLECHANGED afterwards.
2253 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2255 LONG WINAPI SetWindowLongW(
2256 HWND hwnd, /* [in] window to alter */
2257 INT offset, /* [in] offset, in bytes, of location to alter */
2258 LONG newval /* [in] new value of location */
2260 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2264 /*******************************************************************
2265 * GetWindowTextA (USER32.@)
2267 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2271 if (WIN_IsCurrentProcess( hwnd ))
2272 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2274 /* when window belongs to other process, don't send a message */
2275 if (nMaxCount <= 0) return 0;
2276 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2277 get_server_window_text( hwnd, buffer, nMaxCount );
2278 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2279 lpString[nMaxCount-1] = 0;
2280 HeapFree( GetProcessHeap(), 0, buffer );
2281 return strlen(lpString);
2285 /*******************************************************************
2286 * InternalGetWindowText (USER32.@)
2288 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2292 if (nMaxCount <= 0) return 0;
2293 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2294 if (win != WND_OTHER_PROCESS)
2296 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2297 else lpString[0] = 0;
2298 WIN_ReleasePtr( win );
2302 get_server_window_text( hwnd, lpString, nMaxCount );
2304 return strlenW(lpString);
2308 /*******************************************************************
2309 * GetWindowTextW (USER32.@)
2311 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2313 if (WIN_IsCurrentProcess( hwnd ))
2314 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2316 /* when window belongs to other process, don't send a message */
2317 if (nMaxCount <= 0) return 0;
2318 get_server_window_text( hwnd, lpString, nMaxCount );
2319 return strlenW(lpString);
2323 /*******************************************************************
2324 * SetWindowText (USER32.@)
2325 * SetWindowTextA (USER32.@)
2327 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2329 if (!WIN_IsCurrentProcess( hwnd ))
2331 FIXME( "cannot set text %s of other process window %x\n", debugstr_a(lpString), hwnd );
2332 SetLastError( ERROR_ACCESS_DENIED );
2335 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2339 /*******************************************************************
2340 * SetWindowTextW (USER32.@)
2342 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2344 if (!WIN_IsCurrentProcess( hwnd ))
2346 FIXME( "cannot set text %s of other process window %x\n", debugstr_w(lpString), hwnd );
2347 SetLastError( ERROR_ACCESS_DENIED );
2350 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2354 /*******************************************************************
2355 * GetWindowTextLengthA (USER32.@)
2357 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2359 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2362 /*******************************************************************
2363 * GetWindowTextLengthW (USER32.@)
2365 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2367 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2371 /*******************************************************************
2372 * IsWindow (USER32.@)
2374 BOOL WINAPI IsWindow( HWND hwnd )
2379 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2381 if (ptr != WND_OTHER_PROCESS)
2383 WIN_ReleasePtr( ptr );
2387 /* check other processes */
2388 SERVER_START_REQ( get_window_info )
2391 ret = !wine_server_call_err( req );
2398 /***********************************************************************
2399 * GetWindowThreadProcessId (USER32.@)
2401 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2406 if (!(ptr = WIN_GetPtr( hwnd )))
2408 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2412 if (ptr != WND_OTHER_PROCESS)
2414 /* got a valid window */
2416 if (process) *process = GetCurrentProcessId();
2417 WIN_ReleasePtr( ptr );
2421 /* check other processes */
2422 SERVER_START_REQ( get_window_info )
2425 if (!wine_server_call_err( req ))
2427 tid = (DWORD)reply->tid;
2428 if (process) *process = (DWORD)reply->pid;
2436 /*****************************************************************
2437 * GetParent (USER32.@)
2439 HWND WINAPI GetParent( HWND hwnd )
2444 if (!(wndPtr = WIN_GetPtr( hwnd )))
2446 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2449 if (wndPtr == WND_OTHER_PROCESS)
2451 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2452 if (style & (WS_POPUP | WS_CHILD))
2454 SERVER_START_REQ( get_window_tree )
2457 if (!wine_server_call_err( req ))
2459 if (style & WS_POPUP) retvalue = reply->owner;
2460 else if (style & WS_CHILD) retvalue = reply->parent;
2468 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2469 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2470 WIN_ReleasePtr( wndPtr );
2476 /*****************************************************************
2477 * GetAncestor (USER32.@)
2479 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2482 HWND *list, ret = 0;
2487 if (!(win = WIN_GetPtr( hwnd )))
2489 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2492 if (win != WND_OTHER_PROCESS)
2495 WIN_ReleasePtr( win );
2497 else /* need to query the server */
2499 SERVER_START_REQ( get_window_tree )
2502 if (!wine_server_call_err( req )) ret = reply->parent;
2509 if (!(list = WIN_ListParents( hwnd ))) return 0;
2511 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2515 while (list[count]) count++;
2516 ret = list[count - 2]; /* get the one before the desktop */
2518 HeapFree( GetProcessHeap(), 0, list );
2522 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2525 HWND parent = GetParent( ret );
2535 /*****************************************************************
2536 * SetParent (USER32.@)
2538 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2541 HWND retvalue, full_handle;
2544 if (!parent) parent = GetDesktopWindow();
2545 else parent = WIN_GetFullHandle( parent );
2547 if (!IsWindow( parent ))
2549 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2553 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2554 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2558 if (USER_Driver.pSetParent)
2559 return USER_Driver.pSetParent( hwnd, parent );
2561 /* Windows hides the window first, then shows it again
2562 * including the WM_SHOWWINDOW messages and all */
2563 was_visible = ShowWindow( hwnd, SW_HIDE );
2565 if (!IsWindow( parent )) return 0;
2566 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2568 retvalue = wndPtr->parent; /* old parent */
2569 if (parent != retvalue)
2571 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2573 if (parent != GetDesktopWindow()) /* a child window */
2575 if (!(wndPtr->dwStyle & WS_CHILD))
2577 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2578 if (menu) DestroyMenu( menu );
2582 WIN_ReleasePtr( wndPtr );
2584 /* SetParent additionally needs to make hwnd the topmost window
2585 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2586 WM_WINDOWPOSCHANGED notification messages.
2588 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2589 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2590 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2591 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2596 /*******************************************************************
2597 * IsChild (USER32.@)
2599 BOOL WINAPI IsChild( HWND parent, HWND child )
2601 HWND *list = WIN_ListParents( child );
2605 if (!list) return FALSE;
2606 parent = WIN_GetFullHandle( parent );
2607 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2608 ret = (list[i] != 0);
2609 HeapFree( GetProcessHeap(), 0, list );
2614 /***********************************************************************
2615 * IsWindowVisible (USER32.@)
2617 BOOL WINAPI IsWindowVisible( HWND hwnd )
2623 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2624 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2625 for (i = 0; list[i]; i++)
2626 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2628 HeapFree( GetProcessHeap(), 0, list );
2633 /***********************************************************************
2634 * WIN_IsWindowDrawable
2636 * hwnd is drawable when it is visible, all parents are not
2637 * minimized, and it is itself not minimized unless we are
2638 * trying to draw its default class icon.
2640 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2645 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2647 if (!(style & WS_VISIBLE)) return FALSE;
2648 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2650 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2651 for (i = 0; list[i]; i++)
2652 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2655 HeapFree( GetProcessHeap(), 0, list );
2660 /*******************************************************************
2661 * GetTopWindow (USER32.@)
2663 HWND WINAPI GetTopWindow( HWND hwnd )
2665 if (!hwnd) hwnd = GetDesktopWindow();
2666 return GetWindow( hwnd, GW_CHILD );
2670 /*******************************************************************
2671 * GetWindow (USER32.@)
2673 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2677 if (rel == GW_OWNER) /* this one may be available locally */
2679 WND *wndPtr = WIN_GetPtr( hwnd );
2682 SetLastError( ERROR_INVALID_HANDLE );
2685 if (wndPtr != WND_OTHER_PROCESS)
2687 retval = wndPtr->owner;
2688 WIN_ReleasePtr( wndPtr );
2691 /* else fall through to server call */
2694 SERVER_START_REQ( get_window_tree )
2697 if (!wine_server_call_err( req ))
2702 retval = reply->first_sibling;
2705 retval = reply->last_sibling;
2708 retval = reply->next_sibling;
2711 retval = reply->prev_sibling;
2714 retval = reply->owner;
2717 retval = reply->first_child;
2727 /***********************************************************************
2728 * WIN_InternalShowOwnedPopups
2730 * Internal version of ShowOwnedPopups; Wine functions should use this
2731 * to avoid interfering with application calls to ShowOwnedPopups
2732 * and to make sure the application can't prevent showing/hiding.
2734 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2738 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2742 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2744 if (!win_array) return TRUE;
2747 * Show windows Lowest first, Highest last to preserve Z-Order
2749 while (win_array[count]) count++;
2750 while (--count >= 0)
2752 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2753 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2755 if (pWnd->dwStyle & WS_POPUP)
2759 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2760 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2763 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2765 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2766 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2771 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2772 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2773 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2776 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2778 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2779 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2780 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2784 WIN_ReleaseWndPtr( pWnd );
2786 HeapFree( GetProcessHeap(), 0, win_array );
2791 /*******************************************************************
2792 * ShowOwnedPopups (USER32.@)
2794 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2798 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2800 if (!win_array) return TRUE;
2802 while (win_array[count]) count++;
2803 while (--count >= 0)
2805 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2806 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2808 if (pWnd->dwStyle & WS_POPUP)
2812 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2814 /* In Windows, ShowOwnedPopups(TRUE) generates
2815 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2816 * regardless of the state of the owner
2818 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2819 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2824 if (IsWindowVisible(pWnd->hwndSelf))
2826 /* In Windows, ShowOwnedPopups(FALSE) generates
2827 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2828 * regardless of the state of the owner
2830 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2831 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2835 WIN_ReleaseWndPtr( pWnd );
2837 HeapFree( GetProcessHeap(), 0, win_array );
2842 /*******************************************************************
2843 * GetLastActivePopup (USER32.@)
2845 HWND WINAPI GetLastActivePopup( HWND hwnd )
2849 SERVER_START_REQ( get_window_info )
2852 if (!wine_server_call_err( req )) retval = reply->last_active;
2859 /*******************************************************************
2862 * Build an array of all parents of a given window, starting with
2863 * the immediate parent. The array must be freed with HeapFree.
2864 * Returns NULL if window is a top-level window.
2866 HWND *WIN_ListParents( HWND hwnd )
2869 HWND current, *list;
2870 int pos = 0, size = 16, count = 0;
2872 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2877 if (!(win = WIN_GetPtr( current ))) goto empty;
2878 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2879 list[pos] = win->parent;
2880 WIN_ReleasePtr( win );
2881 if (!(current = list[pos]))
2883 if (!pos) goto empty;
2886 if (++pos == size - 1)
2888 /* need to grow the list */
2889 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2890 if (!new_list) goto empty;
2896 /* at least one parent belongs to another process, have to query the server */
2901 SERVER_START_REQ( get_window_parents )
2904 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2905 if (!wine_server_call( req )) count = reply->count;
2908 if (!count) goto empty;
2914 HeapFree( GetProcessHeap(), 0, list );
2916 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2920 HeapFree( GetProcessHeap(), 0, list );
2925 /*******************************************************************
2928 * Build an array of the children of a given window. The array must be
2929 * freed with HeapFree. Returns NULL when no windows are found.
2931 HWND *WIN_ListChildren( HWND hwnd )
2933 return list_window_children( hwnd, 0, 0 );
2937 /*******************************************************************
2938 * EnumWindows (USER32.@)
2940 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2946 /* We have to build a list of all windows first, to avoid */
2947 /* unpleasant side-effects, for instance if the callback */
2948 /* function changes the Z-order of the windows. */
2950 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2952 /* Now call the callback function for every window */
2954 iWndsLocks = WIN_SuspendWndsLock();
2955 for (i = 0; list[i]; i++)
2957 /* Make sure that the window still exists */
2958 if (!IsWindow( list[i] )) continue;
2959 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2961 WIN_RestoreWndsLock(iWndsLocks);
2962 HeapFree( GetProcessHeap(), 0, list );
2967 /**********************************************************************
2968 * EnumThreadWindows (USER32.@)
2970 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2975 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2977 /* Now call the callback function for every window */
2979 iWndsLocks = WIN_SuspendWndsLock();
2980 for (i = 0; list[i]; i++)
2981 if (!func( list[i], lParam )) break;
2982 WIN_RestoreWndsLock(iWndsLocks);
2983 HeapFree( GetProcessHeap(), 0, list );
2988 /**********************************************************************
2989 * WIN_EnumChildWindows
2991 * Helper function for EnumChildWindows().
2993 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2998 for ( ; *list; list++)
3000 /* Make sure that the window still exists */
3001 if (!IsWindow( *list )) continue;
3002 /* skip owned windows */
3003 if (GetWindow( *list, GW_OWNER )) continue;
3004 /* Build children list first */
3005 childList = WIN_ListChildren( *list );
3007 ret = func( *list, lParam );
3011 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
3012 HeapFree( GetProcessHeap(), 0, childList );
3014 if (!ret) return FALSE;
3020 /**********************************************************************
3021 * EnumChildWindows (USER32.@)
3023 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3028 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3029 iWndsLocks = WIN_SuspendWndsLock();
3030 WIN_EnumChildWindows( list, func, lParam );
3031 WIN_RestoreWndsLock(iWndsLocks);
3032 HeapFree( GetProcessHeap(), 0, list );
3037 /*******************************************************************
3038 * AnyPopup (USER.52)
3040 BOOL16 WINAPI AnyPopup16(void)
3046 /*******************************************************************
3047 * AnyPopup (USER32.@)
3049 BOOL WINAPI AnyPopup(void)
3053 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3055 if (!list) return FALSE;
3056 for (i = 0; list[i]; i++)
3058 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3060 retvalue = (list[i] != 0);
3061 HeapFree( GetProcessHeap(), 0, list );
3066 /*******************************************************************
3067 * FlashWindow (USER32.@)
3069 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3071 WND *wndPtr = WIN_FindWndPtr(hWnd);
3073 TRACE("%04x\n", hWnd);
3075 if (!wndPtr) return FALSE;
3076 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3078 if (wndPtr->dwStyle & WS_MINIMIZE)
3080 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3082 HDC hDC = GetDC(hWnd);
3084 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM)hDC, 0 ))
3085 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3087 ReleaseDC( hWnd, hDC );
3088 wndPtr->flags |= WIN_NCACTIVATED;
3092 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3093 wndPtr->flags &= ~WIN_NCACTIVATED;
3095 WIN_ReleaseWndPtr(wndPtr);
3101 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3102 else wparam = (hWnd == GetForegroundWindow());
3104 WIN_ReleaseWndPtr(wndPtr);
3105 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3111 /*******************************************************************
3112 * GetWindowContextHelpId (USER32.@)
3114 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3117 WND *wnd = WIN_FindWndPtr( hwnd );
3119 retval = wnd->helpContext;
3120 WIN_ReleaseWndPtr(wnd);
3125 /*******************************************************************
3126 * SetWindowContextHelpId (USER32.@)
3128 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3130 WND *wnd = WIN_FindWndPtr( hwnd );
3131 if (!wnd) return FALSE;
3132 wnd->helpContext = id;
3133 WIN_ReleaseWndPtr(wnd);
3138 /*******************************************************************
3139 * DRAG_QueryUpdate16
3141 * recursively find a child that contains spDragInfo->pt point
3142 * and send WM_QUERYDROPOBJECT
3144 static BOOL16 DRAG_QueryUpdate16( HWND hQueryWnd, SEGPTR spDragInfo )
3146 BOOL16 wParam, bResult = 0;
3147 POINT pt, client_pt;
3148 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3151 if (!ptrDragInfo) return FALSE;
3153 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3155 GetWindowRect(hQueryWnd,&tempRect);
3157 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
3159 if (!IsIconic( hQueryWnd ))
3161 GetClientRect( hQueryWnd, &tempRect );
3162 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
3164 if (PtInRect( &tempRect, pt))
3167 HWND *list = WIN_ListChildren( hQueryWnd );
3173 for (i = 0; list[i]; i++)
3175 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
3177 GetWindowRect( list[i], &tempRect );
3178 if (PtInRect( &tempRect, pt )) break;
3183 if (IsWindowEnabled( list[i] ))
3184 bResult = DRAG_QueryUpdate16( list[i], spDragInfo );
3186 HeapFree( GetProcessHeap(), 0, list );
3188 if(bResult) return bResult;
3195 ScreenToClient( hQueryWnd, &client_pt );
3196 ptrDragInfo->pt.x = client_pt.x;
3197 ptrDragInfo->pt.y = client_pt.y;
3198 ptrDragInfo->hScope = HWND_16(hQueryWnd);
3200 bResult = SendMessage16( HWND_16(hQueryWnd), WM_QUERYDROPOBJECT, (WPARAM16)wParam, spDragInfo );
3202 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3208 /*******************************************************************
3209 * DragDetect (USER32.@)
3211 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3216 rect.left = pt.x - wDragWidth;
3217 rect.right = pt.x + wDragWidth;
3219 rect.top = pt.y - wDragHeight;
3220 rect.bottom = pt.y + wDragHeight;
3226 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3228 if( msg.message == WM_LBUTTONUP )
3233 if( msg.message == WM_MOUSEMOVE )
3236 tmp.x = LOWORD(msg.lParam);
3237 tmp.y = HIWORD(msg.lParam);
3238 if( !PtInRect( &rect, tmp ))
3250 /******************************************************************************
3251 * DragObject (USER.464)
3253 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3254 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3257 LPDRAGINFO16 lpDragInfo;
3259 HCURSOR hOldCursor=0, hBummer=0;
3260 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3261 HCURSOR hCurrentCursor = 0;
3262 HWND16 hCurrentWnd = 0;
3264 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3265 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3267 if( !lpDragInfo || !spDragInfo ) return 0L;
3269 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
3271 GlobalFree16(hDragInfo);
3275 if(hCursor) hOldCursor = SetCursor(HCURSOR_32(hCursor));
3277 lpDragInfo->hWnd = hWnd;
3278 lpDragInfo->hScope = 0;
3279 lpDragInfo->wFlags = wObj;
3280 lpDragInfo->hList = szList; /* near pointer! */
3281 lpDragInfo->hOfStruct = hOfStruct;
3284 SetCapture(WIN_Handle32(hWnd));
3289 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
3291 *(lpDragInfo+1) = *lpDragInfo;
3293 lpDragInfo->pt.x = msg.pt.x;
3294 lpDragInfo->pt.y = msg.pt.y;
3296 /* update DRAGINFO struct */
3297 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3299 if( DRAG_QueryUpdate16(WIN_Handle32(hwndScope), spDragInfo) > 0 )
3300 hCurrentCursor = HCURSOR_32(hCursor);
3303 hCurrentCursor = hBummer;
3304 lpDragInfo->hScope = 0;
3306 if( hCurrentCursor )
3307 SetCursor(hCurrentCursor);
3309 /* send WM_DRAGLOOP */
3310 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3311 (LPARAM) spDragInfo );
3312 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3313 if( hCurrentWnd != lpDragInfo->hScope )
3316 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3317 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3318 HIWORD(spDragInfo)) );
3319 hCurrentWnd = lpDragInfo->hScope;
3321 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3325 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3327 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3330 ShowCursor( FALSE );
3332 if( hCursor ) SetCursor(hOldCursor);
3334 if( hCurrentCursor != hBummer )
3335 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3336 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3339 GlobalFree16(hDragInfo);
3341 return (DWORD)(msg.lParam);
3345 /******************************************************************************
3346 * GetWindowModuleFileNameA (USER32.@)
3348 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3350 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3351 hwnd, lpszFileName, cchFileNameMax);
3355 /******************************************************************************
3356 * GetWindowModuleFileNameW (USER32.@)
3358 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3360 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3361 hwnd, lpszFileName, cchFileNameMax);
3365 /******************************************************************************
3366 * GetWindowInfo (USER32.@)
3369 * MS Documentation mentions that pwi->cbSize must be set to SIZEOF(WINDOWINFO)
3370 * this may be because this structure changed over time. If this is the
3371 * the case, then please: FIXME.
3372 * Using the structure described in MSDN for 98/ME/NT(4.0 SP3)/2000/XP.
3374 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3376 WND *wndInfo = NULL;
3377 if (!pwi) return FALSE;
3378 if (pwi->cbSize != sizeof(WINDOWINFO))
3380 FIXME("windowinfo->cbSize != sizeof(WINDOWINFO). Please report\n");
3383 wndInfo = WIN_GetPtr(hwnd);
3384 if (!wndInfo) return FALSE;
3385 if (wndInfo == WND_OTHER_PROCESS)
3387 FIXME("window belong to other process\n");
3391 pwi->rcWindow = wndInfo->rectWindow;
3392 pwi->rcClient = wndInfo->rectClient;
3393 pwi->dwStyle = wndInfo->dwStyle;
3394 pwi->dwExStyle = wndInfo->dwExStyle;
3395 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3396 /* if active WS_ACTIVECAPTION, else 0 */
3398 pwi->cxWindowBorders = ((wndInfo->dwStyle & WS_BORDER) ?
3399 GetSystemMetrics(SM_CXBORDER) : 0);
3400 pwi->cyWindowBorders = ((wndInfo->dwStyle & WS_BORDER) ?
3401 GetSystemMetrics(SM_CYBORDER) : 0);
3402 /* above two: I'm presuming that borders widths are the same
3403 * for each window - so long as its actually using a border.. */
3405 pwi->atomWindowType = GetClassLongA( hwnd, GCW_ATOM );
3406 pwi->wCreatorVersion = GetVersion();
3407 /* Docs say this should be the version that
3408 * CREATED the window. But eh?.. Isn't that just the
3409 * version we are running.. Unless ofcourse its some wacky
3410 * RPC stuff or something */
3412 WIN_ReleasePtr(wndInfo);