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"
30 #include "wine/server.h"
31 #include "wine/unicode.h"
36 #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 )
184 req->tid = (void *)tid;
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;
687 wndPtr->hmemTaskQ = 0;
689 if (!(wndPtr->dwStyle & WS_CHILD))
691 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
692 if (menu) DestroyMenu( menu );
694 if (wndPtr->hSysMenu)
696 DestroyMenu( wndPtr->hSysMenu );
697 wndPtr->hSysMenu = 0;
699 USER_Driver.pDestroyWindow( hwnd );
700 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
701 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
702 CLASS_RemoveWindow( wndPtr->class );
703 wndPtr->class = NULL;
704 wndPtr->dwMagic = 0; /* Mark it as invalid */
705 WIN_ReleaseWndPtr( wndPtr );
709 /***********************************************************************
710 * WIN_DestroyThreadWindows
712 * Destroy all children of 'wnd' owned by the current thread.
713 * Return TRUE if something was done.
715 void WIN_DestroyThreadWindows( HWND hwnd )
720 if (!(list = WIN_ListChildren( hwnd ))) return;
721 for (i = 0; list[i]; i++)
723 if (WIN_IsCurrentThread( list[i] ))
724 DestroyWindow( list[i] );
726 WIN_DestroyThreadWindows( list[i] );
728 HeapFree( GetProcessHeap(), 0, list );
731 /***********************************************************************
732 * WIN_CreateDesktopWindow
734 * Create the desktop window.
736 BOOL WIN_CreateDesktopWindow(void)
738 struct tagCLASS *class;
747 TRACE("Creating desktop window\n");
749 if (!WINPOS_CreateInternalPosAtom() ||
750 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
751 &wndExtra, &winproc, &clsStyle, &dce )))
754 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM),
755 sizeof(WND) + wndExtra - sizeof(pWndDesktop->wExtra) );
756 if (!pWndDesktop) return FALSE;
757 hwndDesktop = pWndDesktop->hwndSelf;
759 pWndDesktop->tid = 0; /* nobody owns the desktop */
760 pWndDesktop->parent = 0;
761 pWndDesktop->owner = 0;
762 pWndDesktop->class = class;
763 pWndDesktop->text = NULL;
764 pWndDesktop->hmemTaskQ = 0;
765 pWndDesktop->hrgnUpdate = 0;
766 pWndDesktop->hwndLastActive = hwndDesktop;
767 pWndDesktop->clsStyle = clsStyle;
768 pWndDesktop->dce = NULL;
769 pWndDesktop->pVScroll = NULL;
770 pWndDesktop->pHScroll = NULL;
771 pWndDesktop->helpContext = 0;
772 pWndDesktop->flags = 0;
773 pWndDesktop->hSysMenu = 0;
774 pWndDesktop->winproc = winproc;
775 pWndDesktop->cbWndExtra = wndExtra;
777 cs.lpCreateParams = NULL;
783 cs.cx = GetSystemMetrics( SM_CXSCREEN );
784 cs.cy = GetSystemMetrics( SM_CYSCREEN );
785 cs.style = pWndDesktop->dwStyle;
786 cs.dwExStyle = pWndDesktop->dwExStyle;
788 cs.lpszClass = DESKTOP_CLASS_ATOM;
790 SetRect( &rect, 0, 0, cs.cx, cs.cy );
791 WIN_SetRectangles( hwndDesktop, &rect, &rect );
793 SERVER_START_REQ( set_window_info )
795 req->handle = hwndDesktop;
796 req->flags = 0; /* don't set anything, just retrieve */
797 wine_server_call( req );
798 pWndDesktop->dwStyle = reply->old_style;
799 pWndDesktop->dwExStyle = reply->old_ex_style;
800 pWndDesktop->hInstance = (ULONG_PTR)reply->old_instance;
801 pWndDesktop->userdata = (ULONG_PTR)reply->old_user_data;
802 pWndDesktop->wIDmenu = reply->old_id;
806 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE ))
808 WIN_ReleaseWndPtr( pWndDesktop );
812 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
813 WIN_ReleaseWndPtr( pWndDesktop );
818 /***********************************************************************
821 * Fix the coordinates - Helper for WIN_CreateWindowEx.
822 * returns default show mode in sw.
823 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
825 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
827 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
828 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
830 if (cs->style & (WS_CHILD | WS_POPUP))
832 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
833 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
835 else /* overlapped window */
839 GetStartupInfoA( &info );
841 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
843 /* Never believe Microsoft's documentation... CreateWindowEx doc says
844 * that if an overlapped window is created with WS_VISIBLE style bit
845 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
846 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
849 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
850 * 2) it does not ignore the y parameter as the docs claim; instead, it
851 * uses it as second parameter to ShowWindow() unless y is either
852 * CW_USEDEFAULT or CW_USEDEFAULT16.
854 * The fact that we didn't do 2) caused bogus windows pop up when wine
855 * was running apps that were using this obscure feature. Example -
856 * calc.exe that comes with Win98 (only Win98, it's different from
857 * the one that comes with Win95 and NT)
859 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
860 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
861 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
864 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
866 if (info.dwFlags & STARTF_USESIZE)
868 cs->cx = info.dwXSize;
869 cs->cy = info.dwYSize;
871 else /* if no other hint from the app, pick 3/4 of the screen real estate */
874 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
875 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
876 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
883 /* neither x nor cx are default. Check the y values .
884 * In the trace we see Outlook and Outlook Express using
885 * cy set to CW_USEDEFAULT when opening the address book.
887 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
889 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
890 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
891 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
896 /***********************************************************************
899 static void dump_window_styles( DWORD style, DWORD exstyle )
902 if(style & WS_POPUP) DPRINTF(" WS_POPUP");
903 if(style & WS_CHILD) DPRINTF(" WS_CHILD");
904 if(style & WS_MINIMIZE) DPRINTF(" WS_MINIMIZE");
905 if(style & WS_VISIBLE) DPRINTF(" WS_VISIBLE");
906 if(style & WS_DISABLED) DPRINTF(" WS_DISABLED");
907 if(style & WS_CLIPSIBLINGS) DPRINTF(" WS_CLIPSIBLINGS");
908 if(style & WS_CLIPCHILDREN) DPRINTF(" WS_CLIPCHILDREN");
909 if(style & WS_MAXIMIZE) DPRINTF(" WS_MAXIMIZE");
910 if((style & WS_CAPTION) == WS_CAPTION) DPRINTF(" WS_CAPTION");
913 if(style & WS_BORDER) DPRINTF(" WS_BORDER");
914 if(style & WS_DLGFRAME) DPRINTF(" WS_DLGFRAME");
916 if(style & WS_VSCROLL) DPRINTF(" WS_VSCROLL");
917 if(style & WS_HSCROLL) DPRINTF(" WS_HSCROLL");
918 if(style & WS_SYSMENU) DPRINTF(" WS_SYSMENU");
919 if(style & WS_THICKFRAME) DPRINTF(" WS_THICKFRAME");
920 if(style & WS_GROUP) DPRINTF(" WS_GROUP");
921 if(style & WS_TABSTOP) DPRINTF(" WS_TABSTOP");
922 if(style & WS_MINIMIZEBOX) DPRINTF(" WS_MINIMIZEBOX");
923 if(style & WS_MAXIMIZEBOX) DPRINTF(" WS_MAXIMIZEBOX");
925 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
926 #define DUMPED_STYLES \
946 if(style & ~DUMPED_STYLES) DPRINTF(" %08lx", style & ~DUMPED_STYLES);
951 if(exstyle & WS_EX_DLGMODALFRAME) DPRINTF(" WS_EX_DLGMODALFRAME");
952 if(exstyle & WS_EX_DRAGDETECT) DPRINTF(" WS_EX_DRAGDETECT");
953 if(exstyle & WS_EX_NOPARENTNOTIFY) DPRINTF(" WS_EX_NOPARENTNOTIFY");
954 if(exstyle & WS_EX_TOPMOST) DPRINTF(" WS_EX_TOPMOST");
955 if(exstyle & WS_EX_ACCEPTFILES) DPRINTF(" WS_EX_ACCEPTFILES");
956 if(exstyle & WS_EX_TRANSPARENT) DPRINTF(" WS_EX_TRANSPARENT");
957 if(exstyle & WS_EX_MDICHILD) DPRINTF(" WS_EX_MDICHILD");
958 if(exstyle & WS_EX_TOOLWINDOW) DPRINTF(" WS_EX_TOOLWINDOW");
959 if(exstyle & WS_EX_WINDOWEDGE) DPRINTF(" WS_EX_WINDOWEDGE");
960 if(exstyle & WS_EX_CLIENTEDGE) DPRINTF(" WS_EX_CLIENTEDGE");
961 if(exstyle & WS_EX_CONTEXTHELP) DPRINTF(" WS_EX_CONTEXTHELP");
962 if(exstyle & WS_EX_RIGHT) DPRINTF(" WS_EX_RIGHT");
963 if(exstyle & WS_EX_RTLREADING) DPRINTF(" WS_EX_RTLREADING");
964 if(exstyle & WS_EX_LEFTSCROLLBAR) DPRINTF(" WS_EX_LEFTSCROLLBAR");
965 if(exstyle & WS_EX_CONTROLPARENT) DPRINTF(" WS_EX_CONTROLPARENT");
966 if(exstyle & WS_EX_STATICEDGE) DPRINTF(" WS_EX_STATICEDGE");
967 if(exstyle & WS_EX_APPWINDOW) DPRINTF(" WS_EX_APPWINDOW");
968 if(exstyle & WS_EX_LAYERED) DPRINTF(" WS_EX_LAYERED");
970 #define DUMPED_EX_STYLES \
971 (WS_EX_DLGMODALFRAME | \
973 WS_EX_NOPARENTNOTIFY | \
975 WS_EX_ACCEPTFILES | \
976 WS_EX_TRANSPARENT | \
981 WS_EX_CONTEXTHELP | \
984 WS_EX_LEFTSCROLLBAR | \
985 WS_EX_CONTROLPARENT | \
990 if(exstyle & ~DUMPED_EX_STYLES) DPRINTF(" %08lx", exstyle & ~DUMPED_EX_STYLES);
992 #undef DUMPED_EX_STYLES
996 /***********************************************************************
999 * Implementation of CreateWindowEx().
1001 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
1002 WINDOWPROCTYPE type )
1005 struct tagCLASS *classPtr;
1007 HWND hwnd, parent, owner;
1012 BOOL unicode = (type == WIN_PROC_32W);
1014 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%04x menu=%04x inst=%08x params=%p\n",
1015 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
1016 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
1017 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
1018 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
1020 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
1022 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
1023 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
1025 /* Find the parent window */
1027 parent = GetDesktopWindow();
1030 if (cs->hwndParent == HWND_MESSAGE)
1032 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
1033 * message window (style: WS_POPUP|WS_DISABLED)
1035 FIXME("Parent is HWND_MESSAGE\n");
1037 else if (cs->hwndParent)
1039 /* Make sure parent is valid */
1040 if (!IsWindow( cs->hwndParent ))
1042 WARN("Bad parent %04x\n", cs->hwndParent );
1045 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1046 parent = WIN_GetFullHandle(cs->hwndParent);
1048 owner = GetAncestor( cs->hwndParent, GA_ROOT );
1050 else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1052 WARN("No parent for child window\n" );
1053 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1056 /* Find the window class */
1057 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
1058 &wndExtra, &winproc, &clsStyle, &dce )))
1060 WARN("Bad class '%s'\n", cs->lpszClass );
1064 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1066 /* Correct the window style - stage 1
1068 * These are patches that appear to affect both the style loaded into the
1069 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
1071 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1072 * why does the user get to set it?
1075 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1076 * tested for WS_POPUP
1078 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1079 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1080 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1081 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1083 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1085 /* Create the window structure */
1087 if (!(wndPtr = create_window_handle( parent, owner, classAtom,
1088 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
1090 TRACE("out of memory\n" );
1093 hwnd = wndPtr->hwndSelf;
1095 /* Fill the window structure */
1097 wndPtr->tid = GetCurrentThreadId();
1098 wndPtr->owner = owner;
1099 wndPtr->parent = parent;
1100 wndPtr->class = classPtr;
1101 wndPtr->winproc = winproc;
1102 wndPtr->hInstance = cs->hInstance;
1103 wndPtr->text = NULL;
1104 wndPtr->hmemTaskQ = InitThreadInput16( 0, 0 );
1105 wndPtr->hrgnUpdate = 0;
1106 wndPtr->hrgnWnd = 0;
1107 wndPtr->hwndLastActive = hwnd;
1108 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1109 wndPtr->dwExStyle = cs->dwExStyle;
1110 wndPtr->clsStyle = clsStyle;
1111 wndPtr->wIDmenu = 0;
1112 wndPtr->helpContext = 0;
1113 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1114 wndPtr->pVScroll = NULL;
1115 wndPtr->pHScroll = NULL;
1116 wndPtr->userdata = 0;
1117 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
1118 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1119 wndPtr->cbWndExtra = wndExtra;
1121 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
1123 /* Correct the window style - stage 2 */
1125 if (!(cs->style & WS_CHILD))
1127 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1128 if (!(cs->style & WS_POPUP))
1130 wndPtr->dwStyle |= WS_CAPTION;
1131 wndPtr->flags |= WIN_NEED_SIZE;
1134 SERVER_START_REQ( set_window_info )
1137 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1138 req->style = wndPtr->dwStyle;
1139 req->ex_style = wndPtr->dwExStyle;
1140 req->instance = (void *)wndPtr->hInstance;
1141 wine_server_call( req );
1145 /* Get class or window DC if needed */
1147 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1148 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
1149 else wndPtr->dce = NULL;
1151 /* Set the window menu */
1153 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
1155 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
1158 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1161 if (HIWORD(cs->hInstance))
1162 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1164 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
1166 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
1170 else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
1171 WIN_ReleaseWndPtr( wndPtr );
1173 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
1175 WIN_DestroyWindow( hwnd );
1179 /* Notify the parent window only */
1181 send_parent_notify( hwnd, WM_CREATE );
1182 if (!IsWindow( hwnd )) return 0;
1184 if (cs->style & WS_VISIBLE)
1186 /* in case WS_VISIBLE got set in the meantime */
1187 if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0;
1188 WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
1189 WIN_ReleasePtr( wndPtr );
1190 ShowWindow( hwnd, sw );
1193 /* Call WH_SHELL hook */
1195 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1196 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0 );
1198 TRACE("created window %04x\n", hwnd);
1203 /***********************************************************************
1204 * CreateWindow (USER.41)
1206 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1207 DWORD style, INT16 x, INT16 y, INT16 width,
1208 INT16 height, HWND16 parent, HMENU16 menu,
1209 HINSTANCE16 instance, LPVOID data )
1211 return CreateWindowEx16( 0, className, windowName, style,
1212 x, y, width, height, parent, menu, instance, data );
1216 /***********************************************************************
1217 * CreateWindowEx (USER.452)
1219 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1220 LPCSTR windowName, DWORD style, INT16 x,
1221 INT16 y, INT16 width, INT16 height,
1222 HWND16 parent, HMENU16 menu,
1223 HINSTANCE16 instance, LPVOID data )
1229 /* Find the class atom */
1231 if (HIWORD(className))
1233 if (!(classAtom = GlobalFindAtomA( className )))
1235 ERR( "bad class name %s\n", debugstr_a(className) );
1241 classAtom = LOWORD(className);
1242 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1244 ERR( "bad atom %x\n", classAtom);
1250 /* Fix the coordinates */
1252 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1253 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1254 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1255 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1257 /* Create the window */
1259 cs.lpCreateParams = data;
1260 cs.hInstance = (HINSTANCE)instance;
1261 cs.hMenu = (HMENU)menu;
1262 cs.hwndParent = WIN_Handle32( parent );
1264 cs.lpszName = windowName;
1265 cs.lpszClass = className;
1266 cs.dwExStyle = exStyle;
1268 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1272 /***********************************************************************
1273 * CreateWindowExA (USER32.@)
1275 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1276 LPCSTR windowName, DWORD style, INT x,
1277 INT y, INT width, INT height,
1278 HWND parent, HMENU menu,
1279 HINSTANCE instance, LPVOID data )
1286 instance=GetModuleHandleA(NULL);
1288 if(exStyle & WS_EX_MDICHILD)
1289 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1291 /* Find the class atom */
1293 if (HIWORD(className))
1295 if (!(classAtom = GlobalFindAtomA( className )))
1297 ERR( "bad class name %s\n", debugstr_a(className) );
1303 classAtom = LOWORD(className);
1304 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1306 ERR( "bad atom %x\n", classAtom);
1312 /* Create the window */
1314 cs.lpCreateParams = data;
1315 cs.hInstance = instance;
1317 cs.hwndParent = parent;
1323 cs.lpszName = windowName;
1324 cs.lpszClass = className;
1325 cs.dwExStyle = exStyle;
1327 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1331 /***********************************************************************
1332 * CreateWindowExW (USER32.@)
1334 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1335 LPCWSTR windowName, DWORD style, INT x,
1336 INT y, INT width, INT height,
1337 HWND parent, HMENU menu,
1338 HINSTANCE instance, LPVOID data )
1345 instance=GetModuleHandleA(NULL);
1347 if(exStyle & WS_EX_MDICHILD)
1348 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1350 /* Find the class atom */
1352 if (HIWORD(className))
1354 if (!(classAtom = GlobalFindAtomW( className )))
1356 ERR( "bad class name %s\n", debugstr_w(className) );
1362 classAtom = LOWORD(className);
1363 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1365 ERR( "bad atom %x\n", classAtom);
1371 /* Create the window */
1373 cs.lpCreateParams = data;
1374 cs.hInstance = instance;
1376 cs.hwndParent = parent;
1382 cs.lpszName = windowName;
1383 cs.lpszClass = className;
1384 cs.dwExStyle = exStyle;
1386 /* Note: we rely on the fact that CREATESTRUCTA and */
1387 /* CREATESTRUCTW have the same layout. */
1388 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1392 /***********************************************************************
1393 * WIN_SendDestroyMsg
1395 static void WIN_SendDestroyMsg( HWND hwnd )
1397 if( CARET_GetHwnd() == hwnd) 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 ShowWindow( hwnd, SW_HIDE );
1483 if (!IsWindow(hwnd)) return TRUE;
1485 /* Recursively destroy owned windows */
1494 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1497 for (i = 0; list[i]; i++)
1499 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1500 if (WIN_IsCurrentThread( list[i] ))
1502 DestroyWindow( list[i] );
1506 WIN_SetOwner( list[i], 0 );
1508 HeapFree( GetProcessHeap(), 0, list );
1510 if (!got_one) break;
1513 WINPOS_ActivateOtherWindow( hwnd );
1515 if ((owner = GetWindow( hwnd, GW_OWNER )))
1517 WND *ptr = WIN_FindWndPtr( owner );
1520 if (ptr->hwndLastActive == hwnd) ptr->hwndLastActive = owner;
1521 WIN_ReleaseWndPtr( ptr );
1526 /* Send destroy messages */
1528 WIN_SendDestroyMsg( hwnd );
1529 if (!IsWindow( hwnd )) return TRUE;
1531 /* Unlink now so we won't bother with the children later on */
1533 WIN_UnlinkWindow( hwnd );
1535 /* Destroy the window storage */
1537 WIN_DestroyWindow( hwnd );
1542 /***********************************************************************
1543 * CloseWindow (USER32.@)
1545 BOOL WINAPI CloseWindow( HWND hwnd )
1547 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1548 ShowWindow( hwnd, SW_MINIMIZE );
1553 /***********************************************************************
1554 * OpenIcon (USER32.@)
1556 BOOL WINAPI OpenIcon( HWND hwnd )
1558 if (!IsIconic( hwnd )) return FALSE;
1559 ShowWindow( hwnd, SW_SHOWNORMAL );
1564 /***********************************************************************
1567 * Implementation of FindWindow() and FindWindowEx().
1569 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1574 WCHAR *buffer = NULL;
1576 if (!parent) parent = GetDesktopWindow();
1579 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1580 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1583 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1587 child = WIN_GetFullHandle( child );
1588 while (list[i] && list[i] != child) i++;
1589 if (!list[i]) goto done;
1590 i++; /* start from next window */
1597 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1604 if (list) HeapFree( GetProcessHeap(), 0, list );
1605 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1611 /***********************************************************************
1612 * FindWindowA (USER32.@)
1614 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1616 HWND ret = FindWindowExA( 0, 0, className, title );
1617 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1622 /***********************************************************************
1623 * FindWindowExA (USER32.@)
1625 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1626 LPCSTR className, LPCSTR title )
1635 /* If the atom doesn't exist, then no class */
1636 /* with this name exists either. */
1637 if (!(atom = GlobalFindAtomA( className )))
1639 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1643 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1645 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1646 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1647 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1648 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1649 HeapFree( GetProcessHeap(), 0, buffer );
1654 /***********************************************************************
1655 * FindWindowExW (USER32.@)
1657 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1658 LPCWSTR className, LPCWSTR title )
1664 /* If the atom doesn't exist, then no class */
1665 /* with this name exists either. */
1666 if (!(atom = GlobalFindAtomW( className )))
1668 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1672 return WIN_FindWindow( parent, child, atom, title );
1676 /***********************************************************************
1677 * FindWindowW (USER32.@)
1679 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1681 return FindWindowExW( 0, 0, className, title );
1685 /**********************************************************************
1686 * GetDesktopWindow (USER32.@)
1688 HWND WINAPI GetDesktopWindow(void)
1690 if (pWndDesktop) return pWndDesktop->hwndSelf;
1691 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" );
1697 /*******************************************************************
1698 * EnableWindow (USER32.@)
1700 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1707 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1708 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1712 TRACE("( %x, %d )\n", hwnd, enable);
1714 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1715 style = wndPtr->dwStyle;
1716 retvalue = ((style & WS_DISABLED) != 0);
1717 WIN_ReleasePtr( wndPtr );
1719 if (enable && retvalue)
1721 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1722 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1724 else if (!enable && !retvalue)
1726 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1728 WIN_SetStyle( hwnd, style | WS_DISABLED );
1730 if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1731 SetFocus( 0 ); /* A disabled window can't have the focus */
1733 if (hwnd == GetCapture() || IsChild(hwnd, GetCapture()))
1734 ReleaseCapture(); /* A disabled window can't capture the mouse */
1736 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1742 /***********************************************************************
1743 * IsWindowEnabled (USER32.@)
1745 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1747 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1751 /***********************************************************************
1752 * IsWindowUnicode (USER32.@)
1754 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1759 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1760 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1761 WIN_ReleaseWndPtr(wndPtr);
1766 /**********************************************************************
1767 * GetWindowWord (USER32.@)
1769 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1774 WND *wndPtr = WIN_GetPtr( hwnd );
1777 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1780 if (wndPtr == WND_OTHER_PROCESS)
1782 if (IsWindow( hwnd ))
1783 FIXME( "(%d) not supported yet on other process window %x\n", offset, hwnd );
1784 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1787 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1789 WARN("Invalid offset %d\n", offset );
1790 SetLastError( ERROR_INVALID_INDEX );
1792 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1793 WIN_ReleasePtr( wndPtr );
1799 case GWL_HWNDPARENT:
1800 return GetWindowLongW( hwnd, offset );
1804 LONG ret = GetWindowLongW( hwnd, offset );
1806 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1810 WARN("Invalid offset %d\n", offset );
1816 /**********************************************************************
1817 * SetWindowWord (USER32.@)
1819 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1828 case GWL_HWNDPARENT:
1829 return SetWindowLongW( hwnd, offset, (UINT)newval );
1833 WARN("Invalid offset %d\n", offset );
1834 SetLastError( ERROR_INVALID_INDEX );
1839 wndPtr = WIN_GetPtr( hwnd );
1840 if (wndPtr == WND_OTHER_PROCESS)
1843 FIXME( "set %d <- %x not supported yet on other process window %x\n",
1844 offset, newval, hwnd );
1849 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1853 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1855 WARN("Invalid offset %d\n", offset );
1856 WIN_ReleasePtr(wndPtr);
1857 SetLastError( ERROR_INVALID_INDEX );
1860 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1863 WIN_ReleasePtr(wndPtr);
1868 /**********************************************************************
1871 * Helper function for GetWindowLong().
1873 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1878 if (offset == GWL_HWNDPARENT)
1880 HWND parent = GetAncestor( hwnd, GA_PARENT );
1881 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1882 return (LONG)parent;
1885 if (!(wndPtr = WIN_GetPtr( hwnd )))
1887 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1891 if (wndPtr == WND_OTHER_PROCESS)
1896 FIXME( "(%d) not supported on other process window %x\n", offset, hwnd );
1897 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1900 if (offset == GWL_WNDPROC)
1902 SetLastError( ERROR_ACCESS_DENIED );
1905 SERVER_START_REQ( set_window_info )
1908 req->flags = 0; /* don't set anything, just retrieve */
1909 if (!wine_server_call_err( req ))
1913 case GWL_STYLE: retvalue = reply->old_style; break;
1914 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1915 case GWL_ID: retvalue = reply->old_id; break;
1916 case GWL_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1917 case GWL_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1919 SetLastError( ERROR_INVALID_INDEX );
1928 /* now we have a valid wndPtr */
1932 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
1935 * Some programs try to access last element from 16 bit
1936 * code using illegal offset value. Hopefully this is
1937 * what those programs really expect.
1939 if (type == WIN_PROC_16 &&
1940 wndPtr->cbWndExtra >= 4 &&
1941 offset == wndPtr->cbWndExtra - sizeof(WORD))
1943 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1945 ERR( "- replaced invalid offset %d with %d\n",
1948 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset2);
1949 WIN_ReleasePtr( wndPtr );
1952 WARN("Invalid offset %d\n", offset );
1953 WIN_ReleasePtr( wndPtr );
1954 SetLastError( ERROR_INVALID_INDEX );
1957 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1958 /* Special case for dialog window procedure */
1959 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1960 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1961 WIN_ReleasePtr( wndPtr );
1967 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
1968 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1969 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1970 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
1971 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
1972 case GWL_HINSTANCE: retvalue = wndPtr->hInstance; break;
1974 WARN("Unknown offset %d\n", offset );
1975 SetLastError( ERROR_INVALID_INDEX );
1978 WIN_ReleasePtr(wndPtr);
1983 /**********************************************************************
1986 * Helper function for SetWindowLong().
1988 * 0 is the failure code. However, in the case of failure SetLastError
1989 * must be set to distinguish between a 0 return value and a failure.
1991 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1992 WINDOWPROCTYPE type )
1997 TRACE( "%x %d %lx %x\n", hwnd, offset, newval, type );
1999 if (!WIN_IsCurrentProcess( hwnd ))
2001 if (offset == GWL_WNDPROC)
2003 SetLastError( ERROR_ACCESS_DENIED );
2006 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
2009 wndPtr = WIN_GetPtr( hwnd );
2010 if (wndPtr->hwndSelf == GetDesktopWindow())
2012 /* can't change anything on the desktop window */
2013 SetLastError( ERROR_ACCESS_DENIED );
2019 LONG *ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2020 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
2022 WARN("Invalid offset %d\n", offset );
2023 WIN_ReleasePtr( wndPtr );
2024 SetLastError( ERROR_INVALID_INDEX );
2027 /* Special case for dialog window procedure */
2028 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2030 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2031 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2032 type, WIN_PROC_WINDOW );
2033 WIN_ReleasePtr( wndPtr );
2038 WIN_ReleasePtr( wndPtr );
2045 /* first some special cases */
2050 style.styleOld = wndPtr->dwStyle;
2051 style.styleNew = newval;
2052 WIN_ReleasePtr( wndPtr );
2053 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2054 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2055 newval = style.styleNew;
2057 case GWL_HWNDPARENT:
2058 if (wndPtr->parent == GetDesktopWindow())
2060 WIN_ReleasePtr( wndPtr );
2061 return (LONG)WIN_SetOwner( hwnd, (HWND)newval );
2065 WIN_ReleasePtr( wndPtr );
2066 return (LONG)SetParent( hwnd, (HWND)newval );
2069 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2070 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2071 type, WIN_PROC_WINDOW );
2072 WIN_ReleasePtr( wndPtr );
2079 WIN_ReleasePtr( wndPtr );
2080 WARN("Invalid offset %d\n", offset );
2081 SetLastError( ERROR_INVALID_INDEX );
2085 SERVER_START_REQ( set_window_info )
2091 req->flags = SET_WIN_STYLE;
2092 req->style = newval;
2095 req->flags = SET_WIN_EXSTYLE;
2096 req->ex_style = newval;
2099 req->flags = SET_WIN_ID;
2103 req->flags = SET_WIN_INSTANCE;
2104 req->instance = (void *)newval;
2107 req->flags = SET_WIN_USERDATA;
2108 req->user_data = (void *)newval;
2111 if ((ok = !wine_server_call_err( req )))
2116 wndPtr->dwStyle = newval;
2117 retval = reply->old_style;
2120 wndPtr->dwExStyle = newval;
2121 retval = reply->old_ex_style;
2124 wndPtr->wIDmenu = newval;
2125 retval = reply->old_id;
2128 wndPtr->hInstance = newval;
2129 retval = (HINSTANCE)reply->old_instance;
2132 wndPtr->userdata = newval;
2133 retval = (ULONG_PTR)reply->old_user_data;
2139 WIN_ReleasePtr( wndPtr );
2143 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2144 USER_Driver.pSetWindowStyle( hwnd, retval );
2146 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2147 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2154 /**********************************************************************
2155 * GetWindowLong (USER.135)
2157 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2159 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2163 /**********************************************************************
2164 * GetWindowLongA (USER32.@)
2166 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2168 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2172 /**********************************************************************
2173 * GetWindowLongW (USER32.@)
2175 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2177 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2181 /**********************************************************************
2182 * SetWindowLong (USER.136)
2184 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2186 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2190 /**********************************************************************
2191 * SetWindowLongA (USER32.@)
2193 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2195 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2199 /**********************************************************************
2200 * SetWindowLongW (USER32.@) Set window attribute
2202 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2203 * value in a window's extra memory.
2205 * The _hwnd_ parameter specifies the window. is the handle to a
2206 * window that has extra memory. The _newval_ parameter contains the
2207 * new attribute or extra memory value. If positive, the _offset_
2208 * parameter is the byte-addressed location in the window's extra
2209 * memory to set. If negative, _offset_ specifies the window
2210 * attribute to set, and should be one of the following values:
2212 * GWL_EXSTYLE The window's extended window style
2214 * GWL_STYLE The window's window style.
2216 * GWL_WNDPROC Pointer to the window's window procedure.
2218 * GWL_HINSTANCE The window's pplication instance handle.
2220 * GWL_ID The window's identifier.
2222 * GWL_USERDATA The window's user-specified data.
2224 * If the window is a dialog box, the _offset_ parameter can be one of
2225 * the following values:
2227 * DWL_DLGPROC The address of the window's dialog box procedure.
2229 * DWL_MSGRESULT The return value of a message
2230 * that the dialog box procedure processed.
2232 * DWL_USER Application specific information.
2236 * If successful, returns the previous value located at _offset_. Otherwise,
2241 * Extra memory for a window class is specified by a nonzero cbWndExtra
2242 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2243 * time of class creation.
2245 * Using GWL_WNDPROC to set a new window procedure effectively creates
2246 * a window subclass. Use CallWindowProc() in the new windows procedure
2247 * to pass messages to the superclass's window procedure.
2249 * The user data is reserved for use by the application which created
2252 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2253 * instead, call the EnableWindow() function to change the window's
2256 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2257 * SetParent() instead.
2260 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2261 * it sends WM_STYLECHANGING before changing the settings
2262 * and WM_STYLECHANGED afterwards.
2263 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2265 LONG WINAPI SetWindowLongW(
2266 HWND hwnd, /* [in] window to alter */
2267 INT offset, /* [in] offset, in bytes, of location to alter */
2268 LONG newval /* [in] new value of location */
2270 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2274 /*******************************************************************
2275 * GetWindowTextA (USER32.@)
2277 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2281 if (WIN_IsCurrentProcess( hwnd ))
2282 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2284 /* when window belongs to other process, don't send a message */
2285 if (nMaxCount <= 0) return 0;
2286 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2287 get_server_window_text( hwnd, buffer, nMaxCount );
2288 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2289 lpString[nMaxCount-1] = 0;
2290 HeapFree( GetProcessHeap(), 0, buffer );
2291 return strlen(lpString);
2295 /*******************************************************************
2296 * InternalGetWindowText (USER32.@)
2298 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2302 if (nMaxCount <= 0) return 0;
2303 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2304 if (win != WND_OTHER_PROCESS)
2306 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2307 else lpString[0] = 0;
2308 WIN_ReleasePtr( win );
2312 get_server_window_text( hwnd, lpString, nMaxCount );
2314 return strlenW(lpString);
2318 /*******************************************************************
2319 * GetWindowTextW (USER32.@)
2321 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2323 if (WIN_IsCurrentProcess( hwnd ))
2324 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2326 /* when window belongs to other process, don't send a message */
2327 if (nMaxCount <= 0) return 0;
2328 get_server_window_text( hwnd, lpString, nMaxCount );
2329 return strlenW(lpString);
2333 /*******************************************************************
2334 * SetWindowText (USER32.@)
2335 * SetWindowTextA (USER32.@)
2337 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2339 if (!WIN_IsCurrentProcess( hwnd ))
2341 FIXME( "cannot set text %s of other process window %x\n", debugstr_a(lpString), hwnd );
2342 SetLastError( ERROR_ACCESS_DENIED );
2345 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2349 /*******************************************************************
2350 * SetWindowTextW (USER32.@)
2352 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2354 if (!WIN_IsCurrentProcess( hwnd ))
2356 FIXME( "cannot set text %s of other process window %x\n", debugstr_w(lpString), hwnd );
2357 SetLastError( ERROR_ACCESS_DENIED );
2360 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2364 /*******************************************************************
2365 * GetWindowTextLengthA (USER32.@)
2367 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2369 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2372 /*******************************************************************
2373 * GetWindowTextLengthW (USER32.@)
2375 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2377 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2381 /*******************************************************************
2382 * IsWindow (USER32.@)
2384 BOOL WINAPI IsWindow( HWND hwnd )
2389 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2391 if (ptr != WND_OTHER_PROCESS)
2393 WIN_ReleasePtr( ptr );
2397 /* check other processes */
2398 SERVER_START_REQ( get_window_info )
2401 ret = !wine_server_call_err( req );
2408 /***********************************************************************
2409 * GetWindowThreadProcessId (USER32.@)
2411 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2416 if (!(ptr = WIN_GetPtr( hwnd )))
2418 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2422 if (ptr != WND_OTHER_PROCESS)
2424 /* got a valid window */
2426 if (process) *process = GetCurrentProcessId();
2427 WIN_ReleasePtr( ptr );
2431 /* check other processes */
2432 SERVER_START_REQ( get_window_info )
2435 if (!wine_server_call_err( req ))
2437 tid = (DWORD)reply->tid;
2438 if (process) *process = (DWORD)reply->pid;
2446 /*****************************************************************
2447 * GetParent (USER32.@)
2449 HWND WINAPI GetParent( HWND hwnd )
2454 if (!(wndPtr = WIN_GetPtr( hwnd )))
2456 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2459 if (wndPtr == WND_OTHER_PROCESS)
2461 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2462 if (style & (WS_POPUP | WS_CHILD))
2464 SERVER_START_REQ( get_window_tree )
2467 if (!wine_server_call_err( req ))
2469 if (style & WS_POPUP) retvalue = reply->owner;
2470 else if (style & WS_CHILD) retvalue = reply->parent;
2478 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2479 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2480 WIN_ReleasePtr( wndPtr );
2486 /*****************************************************************
2487 * GetAncestor (USER32.@)
2489 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2492 HWND *list, ret = 0;
2497 if (!(win = WIN_GetPtr( hwnd )))
2499 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2502 if (win != WND_OTHER_PROCESS)
2505 WIN_ReleasePtr( win );
2507 else /* need to query the server */
2509 SERVER_START_REQ( get_window_tree )
2512 if (!wine_server_call_err( req )) ret = reply->parent;
2519 if (!(list = WIN_ListParents( hwnd ))) return 0;
2521 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2525 while (list[count]) count++;
2526 ret = list[count - 2]; /* get the one before the desktop */
2528 HeapFree( GetProcessHeap(), 0, list );
2532 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2535 HWND parent = GetParent( ret );
2545 /*****************************************************************
2546 * SetParent (USER32.@)
2548 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2551 HWND retvalue, full_handle;
2554 if (!parent) parent = GetDesktopWindow();
2555 else parent = WIN_GetFullHandle( parent );
2557 if (!IsWindow( parent ))
2559 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2563 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2564 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2568 if (USER_Driver.pSetParent)
2569 return USER_Driver.pSetParent( hwnd, parent );
2571 /* Windows hides the window first, then shows it again
2572 * including the WM_SHOWWINDOW messages and all */
2573 was_visible = ShowWindow( hwnd, SW_HIDE );
2575 if (!IsWindow( parent )) return 0;
2576 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2578 retvalue = wndPtr->parent; /* old parent */
2579 if (parent != retvalue)
2581 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2583 if (parent != GetDesktopWindow()) /* a child window */
2585 if (!(wndPtr->dwStyle & WS_CHILD))
2587 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2588 if (menu) DestroyMenu( menu );
2592 WIN_ReleasePtr( wndPtr );
2594 /* SetParent additionally needs to make hwnd the topmost window
2595 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2596 WM_WINDOWPOSCHANGED notification messages.
2598 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2599 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2600 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2601 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2606 /*******************************************************************
2607 * IsChild (USER32.@)
2609 BOOL WINAPI IsChild( HWND parent, HWND child )
2611 HWND *list = WIN_ListParents( child );
2615 if (!list) return FALSE;
2616 parent = WIN_GetFullHandle( parent );
2617 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2618 ret = (list[i] != 0);
2619 HeapFree( GetProcessHeap(), 0, list );
2624 /***********************************************************************
2625 * IsWindowVisible (USER32.@)
2627 BOOL WINAPI IsWindowVisible( HWND hwnd )
2633 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2634 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2635 for (i = 0; list[i]; i++)
2636 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2638 HeapFree( GetProcessHeap(), 0, list );
2643 /***********************************************************************
2644 * WIN_IsWindowDrawable
2646 * hwnd is drawable when it is visible, all parents are not
2647 * minimized, and it is itself not minimized unless we are
2648 * trying to draw its default class icon.
2650 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2655 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2657 if (!(style & WS_VISIBLE)) return FALSE;
2658 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2660 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2661 for (i = 0; list[i]; i++)
2662 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2665 HeapFree( GetProcessHeap(), 0, list );
2670 /*******************************************************************
2671 * GetTopWindow (USER32.@)
2673 HWND WINAPI GetTopWindow( HWND hwnd )
2675 if (!hwnd) hwnd = GetDesktopWindow();
2676 return GetWindow( hwnd, GW_CHILD );
2680 /*******************************************************************
2681 * GetWindow (USER32.@)
2683 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2687 if (rel == GW_OWNER) /* this one may be available locally */
2689 WND *wndPtr = WIN_GetPtr( hwnd );
2692 SetLastError( ERROR_INVALID_HANDLE );
2695 if (wndPtr != WND_OTHER_PROCESS)
2697 retval = wndPtr->owner;
2698 WIN_ReleasePtr( wndPtr );
2701 /* else fall through to server call */
2704 SERVER_START_REQ( get_window_tree )
2707 if (!wine_server_call_err( req ))
2712 retval = reply->first_sibling;
2715 retval = reply->last_sibling;
2718 retval = reply->next_sibling;
2721 retval = reply->prev_sibling;
2724 retval = reply->owner;
2727 retval = reply->first_child;
2737 /***********************************************************************
2738 * WIN_InternalShowOwnedPopups
2740 * Internal version of ShowOwnedPopups; Wine functions should use this
2741 * to avoid interfering with application calls to ShowOwnedPopups
2742 * and to make sure the application can't prevent showing/hiding.
2744 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2748 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2752 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2754 if (!win_array) return TRUE;
2757 * Show windows Lowest first, Highest last to preserve Z-Order
2759 while (win_array[count]) count++;
2760 while (--count >= 0)
2762 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2763 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2765 if (pWnd->dwStyle & WS_POPUP)
2769 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2770 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2773 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2775 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2776 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2781 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2782 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2783 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2786 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2788 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2789 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2790 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2794 WIN_ReleaseWndPtr( pWnd );
2796 HeapFree( GetProcessHeap(), 0, win_array );
2801 /*******************************************************************
2802 * ShowOwnedPopups (USER32.@)
2804 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2808 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2810 if (!win_array) return TRUE;
2812 while (win_array[count]) count++;
2813 while (--count >= 0)
2815 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2816 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2818 if (pWnd->dwStyle & WS_POPUP)
2822 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2824 /* In Windows, ShowOwnedPopups(TRUE) generates
2825 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2826 * regardless of the state of the owner
2828 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2829 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2834 if (IsWindowVisible(pWnd->hwndSelf))
2836 /* In Windows, ShowOwnedPopups(FALSE) generates
2837 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2838 * regardless of the state of the owner
2840 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2841 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2845 WIN_ReleaseWndPtr( pWnd );
2847 HeapFree( GetProcessHeap(), 0, win_array );
2852 /*******************************************************************
2853 * GetLastActivePopup (USER32.@)
2855 HWND WINAPI GetLastActivePopup( HWND hwnd )
2858 WND *wndPtr =WIN_FindWndPtr(hwnd);
2859 if (!wndPtr) return hwnd;
2860 retval = wndPtr->hwndLastActive;
2861 if (!IsWindow( retval )) retval = wndPtr->hwndSelf;
2862 WIN_ReleaseWndPtr(wndPtr);
2867 /*******************************************************************
2870 * Build an array of all parents of a given window, starting with
2871 * the immediate parent. The array must be freed with HeapFree.
2872 * Returns NULL if window is a top-level window.
2874 HWND *WIN_ListParents( HWND hwnd )
2877 HWND current, *list;
2878 int pos = 0, size = 16, count = 0;
2880 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2885 if (!(win = WIN_GetPtr( current ))) goto empty;
2886 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2887 list[pos] = win->parent;
2888 WIN_ReleasePtr( win );
2889 if (!(current = list[pos]))
2891 if (!pos) goto empty;
2894 if (++pos == size - 1)
2896 /* need to grow the list */
2897 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2898 if (!new_list) goto empty;
2904 /* at least one parent belongs to another process, have to query the server */
2909 SERVER_START_REQ( get_window_parents )
2912 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2913 if (!wine_server_call( req )) count = reply->count;
2916 if (!count) goto empty;
2922 HeapFree( GetProcessHeap(), 0, list );
2924 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2928 HeapFree( GetProcessHeap(), 0, list );
2933 /*******************************************************************
2936 * Build an array of the children of a given window. The array must be
2937 * freed with HeapFree. Returns NULL when no windows are found.
2939 HWND *WIN_ListChildren( HWND hwnd )
2941 return list_window_children( hwnd, 0, 0 );
2945 /*******************************************************************
2946 * EnumWindows (USER32.@)
2948 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2954 /* We have to build a list of all windows first, to avoid */
2955 /* unpleasant side-effects, for instance if the callback */
2956 /* function changes the Z-order of the windows. */
2958 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2960 /* Now call the callback function for every window */
2962 iWndsLocks = WIN_SuspendWndsLock();
2963 for (i = 0; list[i]; i++)
2965 /* Make sure that the window still exists */
2966 if (!IsWindow( list[i] )) continue;
2967 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2969 WIN_RestoreWndsLock(iWndsLocks);
2970 HeapFree( GetProcessHeap(), 0, list );
2975 /**********************************************************************
2976 * EnumThreadWindows (USER32.@)
2978 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2983 if (!(list = list_window_children( GetDesktopWindow(), 0, GetCurrentThreadId() )))
2986 /* Now call the callback function for every window */
2988 iWndsLocks = WIN_SuspendWndsLock();
2989 for (i = 0; list[i]; i++)
2990 if (!func( list[i], lParam )) break;
2991 WIN_RestoreWndsLock(iWndsLocks);
2992 HeapFree( GetProcessHeap(), 0, list );
2997 /**********************************************************************
2998 * WIN_EnumChildWindows
3000 * Helper function for EnumChildWindows().
3002 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
3007 for ( ; *list; list++)
3009 /* Make sure that the window still exists */
3010 if (!IsWindow( *list )) continue;
3011 /* skip owned windows */
3012 if (GetWindow( *list, GW_OWNER )) continue;
3013 /* Build children list first */
3014 childList = WIN_ListChildren( *list );
3016 ret = func( *list, lParam );
3020 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
3021 HeapFree( GetProcessHeap(), 0, childList );
3023 if (!ret) return FALSE;
3029 /**********************************************************************
3030 * EnumChildWindows (USER32.@)
3032 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3037 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3038 iWndsLocks = WIN_SuspendWndsLock();
3039 WIN_EnumChildWindows( list, func, lParam );
3040 WIN_RestoreWndsLock(iWndsLocks);
3041 HeapFree( GetProcessHeap(), 0, list );
3046 /*******************************************************************
3047 * AnyPopup (USER.52)
3049 BOOL16 WINAPI AnyPopup16(void)
3055 /*******************************************************************
3056 * AnyPopup (USER32.@)
3058 BOOL WINAPI AnyPopup(void)
3062 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3064 if (!list) return FALSE;
3065 for (i = 0; list[i]; i++)
3067 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3069 retvalue = (list[i] != 0);
3070 HeapFree( GetProcessHeap(), 0, list );
3075 /*******************************************************************
3076 * FlashWindow (USER32.@)
3078 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3080 WND *wndPtr = WIN_FindWndPtr(hWnd);
3082 TRACE("%04x\n", hWnd);
3084 if (!wndPtr) return FALSE;
3085 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3087 if (wndPtr->dwStyle & WS_MINIMIZE)
3089 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3091 HDC hDC = GetDC(hWnd);
3093 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
3094 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3096 ReleaseDC( hWnd, hDC );
3097 wndPtr->flags |= WIN_NCACTIVATED;
3101 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3102 wndPtr->flags &= ~WIN_NCACTIVATED;
3104 WIN_ReleaseWndPtr(wndPtr);
3110 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3111 else wparam = (hWnd == GetActiveWindow());
3113 WIN_ReleaseWndPtr(wndPtr);
3114 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3120 /*******************************************************************
3121 * GetWindowContextHelpId (USER32.@)
3123 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3126 WND *wnd = WIN_FindWndPtr( hwnd );
3128 retval = wnd->helpContext;
3129 WIN_ReleaseWndPtr(wnd);
3134 /*******************************************************************
3135 * SetWindowContextHelpId (USER32.@)
3137 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3139 WND *wnd = WIN_FindWndPtr( hwnd );
3140 if (!wnd) return FALSE;
3141 wnd->helpContext = id;
3142 WIN_ReleaseWndPtr(wnd);
3147 /*******************************************************************
3148 * DRAG_QueryUpdate16
3150 * recursively find a child that contains spDragInfo->pt point
3151 * and send WM_QUERYDROPOBJECT
3153 static BOOL16 DRAG_QueryUpdate16( HWND hQueryWnd, SEGPTR spDragInfo )
3155 BOOL16 wParam, bResult = 0;
3157 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3160 if (!ptrDragInfo) return FALSE;
3162 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3164 GetWindowRect(hQueryWnd,&tempRect);
3166 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
3168 if (!IsIconic( hQueryWnd ))
3170 GetClientRect( hQueryWnd, &tempRect );
3171 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
3173 if (PtInRect( &tempRect, pt))
3176 HWND *list = WIN_ListChildren( hQueryWnd );
3182 for (i = 0; list[i]; i++)
3184 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
3186 GetWindowRect( list[i], &tempRect );
3187 if (PtInRect( &tempRect, pt )) break;
3192 if (IsWindowEnabled( list[i] ))
3193 bResult = DRAG_QueryUpdate16( list[i], spDragInfo );
3195 HeapFree( GetProcessHeap(), 0, list );
3197 if(bResult) return bResult;
3203 ScreenToClient16(HWND_16(hQueryWnd),&ptrDragInfo->pt);
3205 ptrDragInfo->hScope = HWND_16(hQueryWnd);
3207 bResult = SendMessage16( HWND_16(hQueryWnd), WM_QUERYDROPOBJECT, (WPARAM16)wParam, spDragInfo );
3209 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3215 /*******************************************************************
3216 * DragDetect (USER32.@)
3218 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3223 rect.left = pt.x - wDragWidth;
3224 rect.right = pt.x + wDragWidth;
3226 rect.top = pt.y - wDragHeight;
3227 rect.bottom = pt.y + wDragHeight;
3233 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3235 if( msg.message == WM_LBUTTONUP )
3240 if( msg.message == WM_MOUSEMOVE )
3243 tmp.x = LOWORD(msg.lParam);
3244 tmp.y = HIWORD(msg.lParam);
3245 if( !PtInRect( &rect, tmp ))
3257 /******************************************************************************
3258 * DragObject (USER.464)
3260 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3261 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3264 LPDRAGINFO16 lpDragInfo;
3266 HCURSOR16 hOldCursor=0, hBummer=0;
3267 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3268 HCURSOR16 hCurrentCursor = 0;
3269 HWND16 hCurrentWnd = 0;
3271 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3272 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3274 if( !lpDragInfo || !spDragInfo ) return 0L;
3276 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
3278 GlobalFree16(hDragInfo);
3282 if(hCursor) hOldCursor = SetCursor(hCursor);
3284 lpDragInfo->hWnd = hWnd;
3285 lpDragInfo->hScope = 0;
3286 lpDragInfo->wFlags = wObj;
3287 lpDragInfo->hList = szList; /* near pointer! */
3288 lpDragInfo->hOfStruct = hOfStruct;
3291 SetCapture(WIN_Handle32(hWnd));
3296 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
3298 *(lpDragInfo+1) = *lpDragInfo;
3300 lpDragInfo->pt.x = msg.pt.x;
3301 lpDragInfo->pt.y = msg.pt.y;
3303 /* update DRAGINFO struct */
3304 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3306 if( DRAG_QueryUpdate16(WIN_Handle32(hwndScope), spDragInfo) > 0 )
3307 hCurrentCursor = hCursor;
3310 hCurrentCursor = hBummer;
3311 lpDragInfo->hScope = 0;
3313 if( hCurrentCursor )
3314 SetCursor(hCurrentCursor);
3316 /* send WM_DRAGLOOP */
3317 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3318 (LPARAM) spDragInfo );
3319 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3320 if( hCurrentWnd != lpDragInfo->hScope )
3323 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3324 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3325 HIWORD(spDragInfo)) );
3326 hCurrentWnd = lpDragInfo->hScope;
3328 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3332 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3334 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3337 ShowCursor( FALSE );
3339 if( hCursor ) SetCursor( hOldCursor );
3341 if( hCurrentCursor != hBummer )
3342 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3343 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3346 GlobalFree16(hDragInfo);
3348 return (DWORD)(msg.lParam);
3352 /******************************************************************************
3353 * GetWindowModuleFileNameA (USER32.@)
3355 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3357 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3358 hwnd, lpszFileName, cchFileNameMax);
3362 /******************************************************************************
3363 * GetWindowModuleFileNameW (USER32.@)
3365 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3367 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3368 hwnd, lpszFileName, cchFileNameMax);
3372 /******************************************************************************
3373 * GetWindowInfo (USER32.@)
3376 * MS Documentation mentions that pwi->cbSize must be set to SIZEOF(WINDOWINFO)
3377 * this may be because this structure changed over time. If this is the
3378 * the case, then please: FIXME.
3379 * Using the structure described in MSDN for 98/ME/NT(4.0 SP3)/2000/XP.
3381 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3383 WND *wndInfo = NULL;
3384 if (!pwi) return FALSE;
3385 if (pwi->cbSize != sizeof(WINDOWINFO))
3387 FIXME("windowinfo->cbSize != sizeof(WINDOWINFO). Please report\n");
3390 wndInfo = WIN_GetPtr(hwnd);
3391 if (!wndInfo) return FALSE;
3392 if (wndInfo == WND_OTHER_PROCESS)
3394 FIXME("window belong to other process\n");
3398 pwi->rcWindow = wndInfo->rectWindow;
3399 pwi->rcClient = wndInfo->rectClient;
3400 pwi->dwStyle = wndInfo->dwStyle;
3401 pwi->dwExStyle = wndInfo->dwExStyle;
3402 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3403 /* if active WS_ACTIVECAPTION, else 0 */
3405 pwi->cxWindowBorders = ((wndInfo->dwStyle & WS_BORDER) ?
3406 GetSystemMetrics(SM_CXBORDER) : 0);
3407 pwi->cyWindowBorders = ((wndInfo->dwStyle & WS_BORDER) ?
3408 GetSystemMetrics(SM_CYBORDER) : 0);
3409 /* above two: I'm presuming that borders widths are the same
3410 * for each window - so long as its actually using a border.. */
3412 pwi->atomWindowType = GetClassLongA( hwnd, GCW_ATOM );
3413 pwi->wCreatorVersion = GetVersion();
3414 /* Docs say this should be the version that
3415 * CREATED the window. But eh?.. Isn't that just the
3416 * version we are running.. Unless ofcourse its some wacky
3417 * RPC stuff or something */
3419 WIN_ReleasePtr(wndInfo);