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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/port.h"
30 #include "wine/winbase16.h"
31 #include "wine/winuser16.h"
33 #include "wine/server.h"
34 #include "wine/unicode.h"
36 #include "user_private.h"
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(win);
43 #define NB_USER_HANDLES ((LAST_USER_HANDLE - FIRST_USER_HANDLE + 1) >> 1)
44 #define USER_HANDLE_TO_INDEX(hwnd) ((LOWORD(hwnd) - FIRST_USER_HANDLE) >> 1)
46 /**********************************************************************/
48 /* helper for Get/SetWindowLong */
49 static inline LONG_PTR get_win_data( const void *ptr, UINT size )
51 if (size == sizeof(WORD))
54 memcpy( &ret, ptr, sizeof(ret) );
57 else if (size == sizeof(DWORD))
60 memcpy( &ret, ptr, sizeof(ret) );
66 memcpy( &ret, ptr, sizeof(ret) );
71 /* helper for Get/SetWindowLong */
72 static inline void set_win_data( void *ptr, LONG_PTR val, UINT size )
74 if (size == sizeof(WORD))
77 memcpy( ptr, &newval, sizeof(newval) );
79 else if (size == sizeof(DWORD))
82 memcpy( ptr, &newval, sizeof(newval) );
86 memcpy( ptr, &val, sizeof(val) );
91 static void *user_handles[NB_USER_HANDLES];
93 /***********************************************************************
96 HANDLE alloc_user_handle( struct user_object *ptr, enum user_obj_type type )
100 SERVER_START_REQ( alloc_user_handle )
102 if (!wine_server_call_err( req )) handle = wine_server_ptr_handle( reply->handle );
108 UINT index = USER_HANDLE_TO_INDEX( handle );
110 assert( index < NB_USER_HANDLES );
111 ptr->handle = handle;
113 user_handles[index] = ptr;
119 /***********************************************************************
120 * get_user_handle_ptr
122 void *get_user_handle_ptr( HANDLE handle, enum user_obj_type type )
124 struct user_object *ptr;
125 WORD index = USER_HANDLE_TO_INDEX( handle );
127 if (index >= NB_USER_HANDLES) return NULL;
130 if ((ptr = user_handles[index]))
132 if (ptr->type == type &&
133 ((UINT)(UINT_PTR)ptr->handle == (UINT)(UINT_PTR)handle ||
134 !HIWORD(handle) || HIWORD(handle) == 0xffff))
138 else ptr = OBJ_OTHER_PROCESS;
144 /***********************************************************************
145 * release_user_handle_ptr
147 void release_user_handle_ptr( void *ptr )
153 /***********************************************************************
156 void *free_user_handle( HANDLE handle, enum user_obj_type type )
158 struct user_object *ptr;
159 WORD index = USER_HANDLE_TO_INDEX( handle );
161 if ((ptr = get_user_handle_ptr( handle, type )) && ptr != OBJ_OTHER_PROCESS)
163 SERVER_START_REQ( free_user_handle )
165 req->handle = wine_server_user_handle( handle );
166 if (!wine_server_call( req )) user_handles[index] = NULL;
170 release_user_handle_ptr( ptr );
176 /***********************************************************************
177 * create_window_handle
179 * Create a window handle with the server.
181 static WND *create_window_handle( HWND parent, HWND owner, LPCWSTR name,
182 HINSTANCE instance, BOOL unicode )
186 HWND handle = 0, full_parent = 0, full_owner = 0;
187 struct tagCLASS *class = NULL;
190 /* if 16-bit instance, map to module handle */
191 if (instance && !HIWORD(instance))
192 instance = HINSTANCE_32(GetExePtr(HINSTANCE_16(instance)));
194 SERVER_START_REQ( create_window )
196 req->parent = wine_server_user_handle( parent );
197 req->owner = wine_server_user_handle( owner );
198 req->instance = wine_server_client_ptr( instance );
199 if (!(req->atom = get_int_atom_value( name )) && name)
200 wine_server_add_data( req, name, strlenW(name)*sizeof(WCHAR) );
201 if (!wine_server_call_err( req ))
203 handle = wine_server_ptr_handle( reply->handle );
204 full_parent = wine_server_ptr_handle( reply->parent );
205 full_owner = wine_server_ptr_handle( reply->owner );
206 extra_bytes = reply->extra;
207 class = wine_server_get_ptr( reply->class_ptr );
214 WARN( "error %d creating window\n", GetLastError() );
218 if (!(win = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
219 sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
221 SERVER_START_REQ( destroy_window )
223 req->handle = wine_server_user_handle( handle );
224 wine_server_call( req );
227 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
231 if (!parent) /* if parent is 0 we don't have a desktop window yet */
233 struct user_thread_info *thread_info = get_user_thread_info();
235 if (name == (LPCWSTR)DESKTOP_CLASS_ATOM)
237 if (!thread_info->top_window) thread_info->top_window = full_parent ? full_parent : handle;
238 else assert( full_parent == thread_info->top_window );
239 if (full_parent && !USER_Driver->pCreateDesktopWindow( thread_info->top_window ))
240 ERR( "failed to create desktop window\n" );
242 else /* HWND_MESSAGE parent */
244 if (!thread_info->msg_window && !full_parent) thread_info->msg_window = handle;
250 index = USER_HANDLE_TO_INDEX(handle);
251 assert( index < NB_USER_HANDLES );
252 user_handles[index] = win;
253 win->obj.handle = handle;
254 win->obj.type = USER_WINDOW;
255 win->parent = full_parent;
256 win->owner = full_owner;
258 win->winproc = get_class_winproc( class );
259 win->cbWndExtra = extra_bytes;
260 if (WINPROC_IsUnicode( win->winproc, unicode )) win->flags |= WIN_ISUNICODE;
265 /***********************************************************************
268 * Free a window handle.
270 static void free_window_handle( HWND hwnd )
272 struct user_object *ptr;
273 WORD index = USER_HANDLE_TO_INDEX(hwnd);
275 if ((ptr = get_user_handle_ptr( hwnd, USER_WINDOW )) && ptr != OBJ_OTHER_PROCESS)
277 SERVER_START_REQ( destroy_window )
279 req->handle = wine_server_user_handle( hwnd );
280 if (!wine_server_call_err( req )) user_handles[index] = NULL;
284 release_user_handle_ptr( ptr );
285 HeapFree( GetProcessHeap(), 0, ptr );
290 /*******************************************************************
291 * list_window_children
293 * Build an array of the children of a given window. The array must be
294 * freed with HeapFree. Returns NULL when no windows are found.
296 static HWND *list_window_children( HDESK desktop, HWND hwnd, LPCWSTR class, DWORD tid )
300 ATOM atom = get_int_atom_value( class );
302 /* empty class is not the same as NULL class */
303 if (!atom && class && !class[0]) return NULL;
309 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
311 SERVER_START_REQ( get_window_children )
313 req->desktop = wine_server_obj_handle( desktop );
314 req->parent = wine_server_user_handle( hwnd );
317 if (!atom && class) wine_server_add_data( req, class, strlenW(class)*sizeof(WCHAR) );
318 wine_server_set_reply( req, list, (size-1) * sizeof(user_handle_t) );
319 if (!wine_server_call( req )) count = reply->count;
322 if (count && count < size)
324 /* start from the end since HWND is potentially larger than user_handle_t */
325 for (i = count - 1; i >= 0; i--)
326 list[i] = wine_server_ptr_handle( ((user_handle_t *)list)[i] );
330 HeapFree( GetProcessHeap(), 0, list );
332 size = count + 1; /* restart with a large enough buffer */
338 /*******************************************************************
339 * list_window_parents
341 * Build an array of all parents of a given window, starting with
342 * the immediate parent. The array must be freed with HeapFree.
344 static HWND *list_window_parents( HWND hwnd )
348 int i, pos = 0, size = 16, count = 0;
350 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
355 if (!(win = WIN_GetPtr( current ))) goto empty;
356 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
357 if (win == WND_DESKTOP)
359 if (!pos) goto empty;
363 list[pos] = current = win->parent;
364 WIN_ReleasePtr( win );
365 if (!current) return list;
366 if (++pos == size - 1)
368 /* need to grow the list */
369 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
370 if (!new_list) goto empty;
376 /* at least one parent belongs to another process, have to query the server */
381 SERVER_START_REQ( get_window_parents )
383 req->handle = wine_server_user_handle( hwnd );
384 wine_server_set_reply( req, list, (size-1) * sizeof(user_handle_t) );
385 if (!wine_server_call( req )) count = reply->count;
388 if (!count) goto empty;
391 /* start from the end since HWND is potentially larger than user_handle_t */
392 for (i = count - 1; i >= 0; i--)
393 list[i] = wine_server_ptr_handle( ((user_handle_t *)list)[i] );
397 HeapFree( GetProcessHeap(), 0, list );
399 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
403 HeapFree( GetProcessHeap(), 0, list );
408 /*******************************************************************
411 static void send_parent_notify( HWND hwnd, UINT msg )
413 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
414 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
416 HWND parent = GetParent(hwnd);
417 if (parent && parent != GetDesktopWindow())
418 SendMessageW( parent, WM_PARENTNOTIFY,
419 MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
424 /*******************************************************************
425 * get_server_window_text
427 * Retrieve the window text from the server.
429 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
433 SERVER_START_REQ( get_window_text )
435 req->handle = wine_server_user_handle( hwnd );
436 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
437 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
440 text[len / sizeof(WCHAR)] = 0;
444 /*******************************************************************
445 * get_hwnd_message_parent
447 * Return the parent for HWND_MESSAGE windows.
449 HWND get_hwnd_message_parent(void)
451 struct user_thread_info *thread_info = get_user_thread_info();
453 if (!thread_info->msg_window) GetDesktopWindow(); /* trigger creation */
454 return thread_info->msg_window;
458 /*******************************************************************
461 * Check if window is the desktop or the HWND_MESSAGE top parent.
463 BOOL is_desktop_window( HWND hwnd )
465 struct user_thread_info *thread_info = get_user_thread_info();
467 if (!hwnd) return FALSE;
468 if (hwnd == thread_info->top_window) return TRUE;
469 if (hwnd == thread_info->msg_window) return TRUE;
471 if (!HIWORD(hwnd) || HIWORD(hwnd) == 0xffff)
473 if (LOWORD(thread_info->top_window) == LOWORD(hwnd)) return TRUE;
474 if (LOWORD(thread_info->msg_window) == LOWORD(hwnd)) return TRUE;
480 /***********************************************************************
483 * Return a pointer to the WND structure if local to the process,
484 * or WND_OTHER_PROCESS if handle may be valid in other process.
485 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
487 WND *WIN_GetPtr( HWND hwnd )
491 if ((ptr = get_user_handle_ptr( hwnd, USER_WINDOW )) == WND_OTHER_PROCESS)
493 if (is_desktop_window( hwnd )) ptr = WND_DESKTOP;
499 /***********************************************************************
500 * WIN_IsCurrentProcess
502 * Check whether a given window belongs to the current process (and return the full handle).
504 HWND WIN_IsCurrentProcess( HWND hwnd )
509 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
510 ret = ptr->obj.handle;
511 WIN_ReleasePtr( ptr );
516 /***********************************************************************
517 * WIN_IsCurrentThread
519 * Check whether a given window belongs to the current thread (and return the full handle).
521 HWND WIN_IsCurrentThread( HWND hwnd )
526 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
527 if (ptr->tid == GetCurrentThreadId()) ret = ptr->obj.handle;
528 WIN_ReleasePtr( ptr );
533 /***********************************************************************
536 * Convert a 16-bit window handle to a full 32-bit handle.
538 HWND WIN_Handle32( HWND16 hwnd16 )
541 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
543 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
544 /* do sign extension for -2 and -3 */
545 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
547 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
549 if (ptr == WND_DESKTOP)
551 if (LOWORD(hwnd) == LOWORD(GetDesktopWindow())) return GetDesktopWindow();
552 else return get_hwnd_message_parent();
555 if (ptr != WND_OTHER_PROCESS)
557 hwnd = ptr->obj.handle;
558 WIN_ReleasePtr( ptr );
560 else /* may belong to another process */
562 SERVER_START_REQ( get_window_info )
564 req->handle = wine_server_user_handle( hwnd );
565 if (!wine_server_call_err( req )) hwnd = wine_server_ptr_handle( reply->full_handle );
573 /***********************************************************************
576 * Change the owner of a window.
578 HWND WIN_SetOwner( HWND hwnd, HWND owner )
580 WND *win = WIN_GetPtr( hwnd );
583 if (!win || win == WND_DESKTOP) return 0;
584 if (win == WND_OTHER_PROCESS)
586 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
589 SERVER_START_REQ( set_window_owner )
591 req->handle = wine_server_user_handle( hwnd );
592 req->owner = wine_server_user_handle( owner );
593 if (!wine_server_call( req ))
595 win->owner = wine_server_ptr_handle( reply->full_owner );
596 ret = wine_server_ptr_handle( reply->prev_owner );
600 WIN_ReleasePtr( win );
605 /***********************************************************************
608 * Change the style of a window.
610 ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
614 WND *win = WIN_GetPtr( hwnd );
616 if (!win || win == WND_DESKTOP) return 0;
617 if (win == WND_OTHER_PROCESS)
620 ERR( "cannot set style %x/%x on other process window %p\n",
621 set_bits, clear_bits, hwnd );
624 style.styleOld = win->dwStyle;
625 style.styleNew = (win->dwStyle | set_bits) & ~clear_bits;
626 if (style.styleNew == style.styleOld)
628 WIN_ReleasePtr( win );
629 return style.styleNew;
631 SERVER_START_REQ( set_window_info )
633 req->handle = wine_server_user_handle( hwnd );
634 req->flags = SET_WIN_STYLE;
635 req->style = style.styleNew;
636 req->extra_offset = -1;
637 if ((ok = !wine_server_call( req )))
639 style.styleOld = reply->old_style;
640 win->dwStyle = style.styleNew;
644 WIN_ReleasePtr( win );
647 USER_Driver->pSetWindowStyle( hwnd, GWL_STYLE, &style );
648 if ((style.styleOld ^ style.styleNew) & WS_VISIBLE) invalidate_dce( hwnd, NULL );
650 return style.styleOld;
654 /***********************************************************************
657 * Get the window and client rectangles.
659 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
661 WND *win = WIN_GetPtr( hwnd );
666 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
669 if (win == WND_DESKTOP)
672 rect.left = rect.top = 0;
673 if (hwnd == get_hwnd_message_parent())
680 rect.right = GetSystemMetrics(SM_CXSCREEN);
681 rect.bottom = GetSystemMetrics(SM_CYSCREEN);
683 if (rectWindow) *rectWindow = rect;
684 if (rectClient) *rectClient = rect;
686 else if (win == WND_OTHER_PROCESS)
688 SERVER_START_REQ( get_window_rectangles )
690 req->handle = wine_server_user_handle( hwnd );
691 if ((ret = !wine_server_call_err( req )))
695 rectWindow->left = reply->window.left;
696 rectWindow->top = reply->window.top;
697 rectWindow->right = reply->window.right;
698 rectWindow->bottom = reply->window.bottom;
702 rectClient->left = reply->client.left;
703 rectClient->top = reply->client.top;
704 rectClient->right = reply->client.right;
705 rectClient->bottom = reply->client.bottom;
713 if (rectWindow) *rectWindow = win->rectWindow;
714 if (rectClient) *rectClient = win->rectClient;
715 WIN_ReleasePtr( win );
721 /***********************************************************************
724 * Destroy storage associated to a window. "Internals" p.358
726 LRESULT WIN_DestroyWindow( HWND hwnd )
730 HMENU menu = 0, sys_menu;
733 TRACE("%p\n", hwnd );
735 /* free child windows */
736 if ((list = WIN_ListChildren( hwnd )))
739 for (i = 0; list[i]; i++)
741 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
742 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
744 HeapFree( GetProcessHeap(), 0, list );
747 /* Unlink now so we won't bother with the children later on */
748 SERVER_START_REQ( set_parent )
750 req->handle = wine_server_user_handle( hwnd );
752 wine_server_call( req );
757 * Send the WM_NCDESTROY to the window being destroyed.
759 SendMessageW( hwnd, WM_NCDESTROY, 0, 0 );
761 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
763 /* free resources associated with the window */
765 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
766 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
767 menu = (HMENU)wndPtr->wIDmenu;
768 sys_menu = wndPtr->hSysMenu;
769 free_dce( wndPtr->dce, hwnd );
771 icon_title = wndPtr->icon_title;
772 HeapFree( GetProcessHeap(), 0, wndPtr->text );
774 HeapFree( GetProcessHeap(), 0, wndPtr->pScroll );
775 wndPtr->pScroll = NULL;
776 WIN_ReleasePtr( wndPtr );
778 if (icon_title) DestroyWindow( icon_title );
779 if (menu) DestroyMenu( menu );
780 if (sys_menu) DestroyMenu( sys_menu );
782 USER_Driver->pDestroyWindow( hwnd );
784 free_window_handle( hwnd );
789 /***********************************************************************
790 * destroy_thread_window
792 * Destroy a window upon exit of its thread.
794 static void destroy_thread_window( HWND hwnd )
798 HMENU menu = 0, sys_menu = 0;
801 /* free child windows */
803 if ((list = WIN_ListChildren( hwnd )))
806 for (i = 0; list[i]; i++)
808 if (WIN_IsCurrentThread( list[i] )) destroy_thread_window( list[i] );
809 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
811 HeapFree( GetProcessHeap(), 0, list );
814 /* destroy the client-side storage */
816 index = USER_HANDLE_TO_INDEX(hwnd);
817 if (index >= NB_USER_HANDLES) return;
819 if ((wndPtr = user_handles[index]))
821 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) menu = (HMENU)wndPtr->wIDmenu;
822 sys_menu = wndPtr->hSysMenu;
823 free_dce( wndPtr->dce, hwnd );
824 user_handles[index] = NULL;
828 HeapFree( GetProcessHeap(), 0, wndPtr );
829 if (menu) DestroyMenu( menu );
830 if (sys_menu) DestroyMenu( sys_menu );
834 /***********************************************************************
835 * destroy_thread_child_windows
837 * Destroy child windows upon exit of its thread.
839 static void destroy_thread_child_windows( HWND hwnd )
844 if (WIN_IsCurrentThread( hwnd ))
846 destroy_thread_window( hwnd );
848 else if ((list = WIN_ListChildren( hwnd )))
850 for (i = 0; list[i]; i++) destroy_thread_child_windows( list[i] );
851 HeapFree( GetProcessHeap(), 0, list );
856 /***********************************************************************
857 * WIN_DestroyThreadWindows
859 * Destroy all children of 'wnd' owned by the current thread.
861 void WIN_DestroyThreadWindows( HWND hwnd )
866 if (!(list = WIN_ListChildren( hwnd ))) return;
868 /* reset owners of top-level windows */
869 for (i = 0; list[i]; i++)
871 if (!WIN_IsCurrentThread( list[i] ))
873 HWND owner = GetWindow( list[i], GW_OWNER );
874 if (owner && WIN_IsCurrentThread( owner )) WIN_SetOwner( list[i], 0 );
878 for (i = 0; list[i]; i++) destroy_thread_child_windows( list[i] );
879 HeapFree( GetProcessHeap(), 0, list );
883 /***********************************************************************
886 * Fix the coordinates - Helper for WIN_CreateWindowEx.
887 * returns default show mode in sw.
889 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
891 #define IS_DEFAULT(x) ((x) == CW_USEDEFAULT || (x) == CW_USEDEFAULT16)
894 if (cs->dwExStyle & WS_EX_MDICHILD)
898 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0, &id);
899 if (!(cs->style & WS_POPUP)) cs->hMenu = ULongToHandle(id);
901 TRACE("MDI child id %04x\n", id);
904 if (cs->style & (WS_CHILD | WS_POPUP))
906 if (cs->dwExStyle & WS_EX_MDICHILD)
908 if (IS_DEFAULT(cs->x))
913 if (IS_DEFAULT(cs->cx) || !cs->cx) cs->cx = pos[1].x;
914 if (IS_DEFAULT(cs->cy) || !cs->cy) cs->cy = pos[1].y;
918 if (IS_DEFAULT(cs->x)) cs->x = cs->y = 0;
919 if (IS_DEFAULT(cs->cx)) cs->cx = cs->cy = 0;
922 else /* overlapped window */
925 MONITORINFO mon_info;
928 if (!IS_DEFAULT(cs->x) && !IS_DEFAULT(cs->cx) && !IS_DEFAULT(cs->cy)) return;
930 monitor = MonitorFromWindow( cs->hwndParent, MONITOR_DEFAULTTOPRIMARY );
931 mon_info.cbSize = sizeof(mon_info);
932 GetMonitorInfoW( monitor, &mon_info );
933 GetStartupInfoW( &info );
935 if (IS_DEFAULT(cs->x))
937 if (!IS_DEFAULT(cs->y)) *sw = cs->y;
938 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : mon_info.rcWork.left;
939 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : mon_info.rcWork.top;
942 if (IS_DEFAULT(cs->cx))
944 if (info.dwFlags & STARTF_USESIZE)
946 cs->cx = info.dwXSize;
947 cs->cy = info.dwYSize;
951 cs->cx = (mon_info.rcWork.right - mon_info.rcWork.left) * 3 / 4 - cs->x;
952 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
955 /* neither x nor cx are default. Check the y values .
956 * In the trace we see Outlook and Outlook Express using
957 * cy set to CW_USEDEFAULT when opening the address book.
959 else if (IS_DEFAULT(cs->cy))
961 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
962 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
968 /***********************************************************************
971 static void dump_window_styles( DWORD style, DWORD exstyle )
974 if(style & WS_POPUP) TRACE(" WS_POPUP");
975 if(style & WS_CHILD) TRACE(" WS_CHILD");
976 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
977 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
978 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
979 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
980 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
981 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
982 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
985 if(style & WS_BORDER) TRACE(" WS_BORDER");
986 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
988 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
989 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
990 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
991 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
992 if (style & WS_CHILD)
994 if(style & WS_GROUP) TRACE(" WS_GROUP");
995 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
999 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
1000 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
1003 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
1004 #define DUMPED_STYLES \
1024 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
1026 #undef DUMPED_STYLES
1028 TRACE( "exstyle:" );
1029 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
1030 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
1031 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
1032 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
1033 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
1034 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
1035 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
1036 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
1037 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
1038 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
1039 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
1040 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
1041 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
1042 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
1043 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
1044 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
1045 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
1046 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
1048 #define DUMPED_EX_STYLES \
1049 (WS_EX_DLGMODALFRAME | \
1050 WS_EX_DRAGDETECT | \
1051 WS_EX_NOPARENTNOTIFY | \
1053 WS_EX_ACCEPTFILES | \
1054 WS_EX_TRANSPARENT | \
1056 WS_EX_TOOLWINDOW | \
1057 WS_EX_WINDOWEDGE | \
1058 WS_EX_CLIENTEDGE | \
1059 WS_EX_CONTEXTHELP | \
1061 WS_EX_RTLREADING | \
1062 WS_EX_LEFTSCROLLBAR | \
1063 WS_EX_CONTROLPARENT | \
1064 WS_EX_STATICEDGE | \
1068 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
1070 #undef DUMPED_EX_STYLES
1074 /***********************************************************************
1075 * WIN_CreateWindowEx
1077 * Implementation of CreateWindowEx().
1079 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, LPCWSTR className, UINT flags )
1081 INT cx, cy, style, sw = SW_SHOW;
1085 HWND hwnd, parent, owner, top_child = 0;
1086 BOOL unicode = (flags & WIN_ISUNICODE) != 0;
1087 MDICREATESTRUCTA mdi_cs;
1088 CBT_CREATEWNDA cbtc;
1091 TRACE("%s %s ex=%08x style=%08x %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
1092 unicode ? debugstr_w((LPCWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
1093 debugstr_w(className),
1094 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
1095 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
1096 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
1098 /* Fix the styles for MDI children */
1099 if (cs->dwExStyle & WS_EX_MDICHILD)
1103 wndPtr = WIN_GetPtr(cs->hwndParent);
1104 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
1106 flags = wndPtr->flags;
1107 WIN_ReleasePtr(wndPtr);
1110 if (!(flags & WIN_ISMDICLIENT))
1112 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
1116 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
1117 * MDICREATESTRUCT members have the originally passed values.
1119 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
1120 * have the same layout.
1122 mdi_cs.szClass = cs->lpszClass;
1123 mdi_cs.szTitle = cs->lpszName;
1124 mdi_cs.hOwner = cs->hInstance;
1129 mdi_cs.style = cs->style;
1130 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
1132 cs->lpCreateParams = &mdi_cs;
1134 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1136 if (cs->style & WS_POPUP)
1138 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
1141 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
1145 cs->style &= ~WS_POPUP;
1146 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
1147 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
1150 top_child = GetWindow(cs->hwndParent, GW_CHILD);
1154 /* Restore current maximized child */
1155 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
1157 TRACE("Restoring current maximized child %p\n", top_child);
1158 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
1159 ShowWindow( top_child, SW_SHOWNORMAL );
1160 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
1165 /* Find the parent window */
1167 parent = cs->hwndParent;
1170 if (cs->hwndParent == HWND_MESSAGE)
1172 cs->hwndParent = parent = get_hwnd_message_parent();
1174 else if (cs->hwndParent)
1176 if ((cs->style & (WS_CHILD|WS_POPUP)) != WS_CHILD)
1178 parent = GetDesktopWindow();
1179 owner = cs->hwndParent;
1184 static const WCHAR messageW[] = {'M','e','s','s','a','g','e',0};
1186 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1188 WARN("No parent for child window\n" );
1189 SetLastError(ERROR_TLW_WITH_WSCHILD);
1190 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1192 /* are we creating the desktop or HWND_MESSAGE parent itself? */
1193 if (className != (LPCWSTR)DESKTOP_CLASS_ATOM &&
1194 (IS_INTRESOURCE(className) || strcmpiW( className, messageW )))
1195 parent = GetDesktopWindow();
1198 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1200 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1201 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1202 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1203 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1205 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1207 /* Create the window structure */
1209 if (!(wndPtr = create_window_handle( parent, owner, className, cs->hInstance, unicode )))
1211 hwnd = wndPtr->obj.handle;
1213 /* Fill the window structure */
1215 wndPtr->tid = GetCurrentThreadId();
1216 wndPtr->hInstance = cs->hInstance;
1217 wndPtr->text = NULL;
1218 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1219 wndPtr->dwExStyle = cs->dwExStyle;
1220 wndPtr->wIDmenu = 0;
1221 wndPtr->helpContext = 0;
1222 wndPtr->pScroll = NULL;
1223 wndPtr->userdata = 0;
1225 wndPtr->hIconSmall = 0;
1226 wndPtr->hSysMenu = 0;
1227 wndPtr->flags |= (flags & WIN_ISWIN32);
1229 wndPtr->min_pos.x = wndPtr->min_pos.y = -1;
1230 wndPtr->max_pos.x = wndPtr->max_pos.y = -1;
1232 if (wndPtr->dwStyle & WS_SYSMENU) SetSystemMenu( hwnd, 0 );
1235 * Correct the window styles.
1237 * It affects only the style loaded into the WIN structure.
1240 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1242 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1243 if (!(wndPtr->dwStyle & WS_POPUP))
1244 wndPtr->dwStyle |= WS_CAPTION;
1248 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1249 * why does the user get to set it?
1252 if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) ||
1253 (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))
1254 wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
1256 wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE;
1258 if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
1259 wndPtr->flags |= WIN_NEED_SIZE;
1261 SERVER_START_REQ( set_window_info )
1263 req->handle = wine_server_user_handle( hwnd );
1264 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE;
1265 req->style = wndPtr->dwStyle;
1266 req->ex_style = wndPtr->dwExStyle;
1267 req->instance = wine_server_client_ptr( wndPtr->hInstance );
1268 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
1269 req->extra_offset = -1;
1270 wine_server_call( req );
1274 /* Set the window menu */
1276 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1280 if (!MENU_SetMenu(hwnd, cs->hMenu))
1282 WIN_ReleasePtr( wndPtr );
1283 free_window_handle( hwnd );
1289 LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
1292 if (!cs->hInstance || HIWORD(cs->hInstance))
1293 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1295 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1297 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1301 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1303 /* call the WH_CBT hook */
1305 /* the window style passed to the hook must be the real window style,
1306 * rather than just the window style that the caller to CreateWindowEx
1307 * passed in, so we have to copy the original CREATESTRUCT and get the
1308 * the real style. */
1310 cbcs.style = wndPtr->dwStyle;
1312 cbtc.hwndInsertAfter = HWND_TOP;
1313 WIN_ReleasePtr( wndPtr );
1314 if (HOOK_CallHooks( WH_CBT, HCBT_CREATEWND, (WPARAM)hwnd, (LPARAM)&cbtc, unicode )) goto failed;
1316 /* send the WM_GETMINMAXINFO message and fix the size if needed */
1320 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
1322 POINT maxSize, maxPos, minTrack, maxTrack;
1323 WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
1324 if (maxTrack.x < cx) cx = maxTrack.x;
1325 if (maxTrack.y < cy) cy = maxTrack.y;
1326 if (minTrack.x > cx) cx = minTrack.x;
1327 if (minTrack.y > cy) cy = minTrack.y;
1332 SetRect( &rect, cs->x, cs->y, cs->x + cx, cs->y + cy );
1333 /* check for wraparound */
1334 if (cs->x + cx < cs->x) rect.right = 0x7fffffff;
1335 if (cs->y + cy < cs->y) rect.bottom = 0x7fffffff;
1336 if (!set_window_pos( hwnd, 0, SWP_NOZORDER | SWP_NOACTIVATE, &rect, &rect, NULL )) goto failed;
1338 /* send WM_NCCREATE */
1340 TRACE( "hwnd %p cs %d,%d %dx%d\n", hwnd, cs->x, cs->y, cx, cy );
1342 result = SendMessageW( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
1344 result = SendMessageA( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
1347 WARN( "%p: aborted by WM_NCCREATE\n", hwnd );
1351 /* send WM_NCCALCSIZE */
1353 if ((wndPtr = WIN_GetPtr(hwnd)))
1355 /* yes, even if the CBT hook was called with HWND_TOP */
1357 HWND insert_after = (wndPtr->dwStyle & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
1358 RECT window_rect = wndPtr->rectWindow;
1359 RECT client_rect = window_rect;
1360 WIN_ReleasePtr( wndPtr );
1362 /* the rectangle is in screen coords for WM_NCCALCSIZE when wparam is FALSE */
1364 MapWindowPoints( parent, 0, &pt, 1 );
1365 OffsetRect( &client_rect, pt.x, pt.y );
1366 SendMessageW( hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&client_rect );
1367 OffsetRect( &client_rect, -pt.x, -pt.y );
1368 set_window_pos( hwnd, insert_after, SWP_NOACTIVATE, &window_rect, &client_rect, NULL );
1372 /* send WM_CREATE */
1375 result = SendMessageW( hwnd, WM_CREATE, 0, (LPARAM)cs );
1377 result = SendMessageA( hwnd, WM_CREATE, 0, (LPARAM)cs );
1378 if (result == -1) goto failed;
1380 /* call the driver */
1382 if (!USER_Driver->pCreateWindow( hwnd )) goto failed;
1384 NotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_WINDOW, 0);
1386 /* send the size messages */
1388 if (!(wndPtr = WIN_GetPtr( hwnd )) ||
1389 wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return 0;
1390 if (!(wndPtr->flags & WIN_NEED_SIZE))
1392 rect = wndPtr->rectClient;
1393 WIN_ReleasePtr( wndPtr );
1394 SendMessageW( hwnd, WM_SIZE, SIZE_RESTORED,
1395 MAKELONG(rect.right-rect.left, rect.bottom-rect.top));
1396 SendMessageW( hwnd, WM_MOVE, 0, MAKELONG( rect.left, rect.top ) );
1398 else WIN_ReleasePtr( wndPtr );
1400 /* Show the window, maximizing or minimizing if needed */
1402 style = WIN_SetStyle( hwnd, 0, WS_MAXIMIZE | WS_MINIMIZE );
1403 if (style & (WS_MINIMIZE | WS_MAXIMIZE))
1406 UINT swFlag = (style & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
1408 swFlag = WINPOS_MinMaximize( hwnd, swFlag, &newPos );
1409 swFlag |= SWP_FRAMECHANGED; /* Frame always gets changed */
1410 if (!(style & WS_VISIBLE) || (style & WS_CHILD) || GetActiveWindow()) swFlag |= SWP_NOACTIVATE;
1411 SetWindowPos( hwnd, 0, newPos.left, newPos.top, newPos.right - newPos.left,
1412 newPos.bottom - newPos.top, swFlag );
1415 /* Notify the parent window only */
1417 send_parent_notify( hwnd, WM_CREATE );
1418 if (!IsWindow( hwnd )) return 0;
1420 if (cs->style & WS_VISIBLE)
1422 if (cs->style & WS_MAXIMIZE)
1424 else if (cs->style & WS_MINIMIZE)
1425 sw = SW_SHOWMINIMIZED;
1427 ShowWindow( hwnd, sw );
1428 if (cs->dwExStyle & WS_EX_MDICHILD)
1430 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1431 /* ShowWindow won't activate child windows */
1432 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1436 /* Call WH_SHELL hook */
1438 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1439 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1441 TRACE("created window %p\n", hwnd);
1445 WIN_DestroyWindow( hwnd );
1450 /***********************************************************************
1451 * CreateWindow (USER.41)
1453 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1454 DWORD style, INT16 x, INT16 y, INT16 width,
1455 INT16 height, HWND16 parent, HMENU16 menu,
1456 HINSTANCE16 instance, LPVOID data )
1458 return CreateWindowEx16( 0, className, windowName, style,
1459 x, y, width, height, parent, menu, instance, data );
1463 /***********************************************************************
1464 * CreateWindowEx (USER.452)
1466 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1467 LPCSTR windowName, DWORD style, INT16 x,
1468 INT16 y, INT16 width, INT16 height,
1469 HWND16 parent, HMENU16 menu,
1470 HINSTANCE16 instance, LPVOID data )
1475 /* Fix the coordinates */
1477 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1478 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1479 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1480 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1482 /* Create the window */
1484 cs.lpCreateParams = data;
1485 cs.hInstance = HINSTANCE_32(instance);
1486 cs.hMenu = HMENU_32(menu);
1487 cs.hwndParent = WIN_Handle32( parent );
1489 cs.lpszName = windowName;
1490 cs.lpszClass = className;
1491 cs.dwExStyle = exStyle;
1493 if (!IS_INTRESOURCE(className))
1497 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1499 return HWND_16( WIN_CreateWindowEx( &cs, bufferW, 0 ));
1503 if (!GlobalGetAtomNameA( LOWORD(className), buffer, sizeof(buffer) ))
1505 ERR( "bad atom %x\n", LOWORD(className));
1508 cs.lpszClass = buffer;
1509 return HWND_16( WIN_CreateWindowEx( &cs, (LPCWSTR)className, 0 ));
1514 /***********************************************************************
1515 * CreateWindowExA (USER32.@)
1517 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1518 LPCSTR windowName, DWORD style, INT x,
1519 INT y, INT width, INT height,
1520 HWND parent, HMENU menu,
1521 HINSTANCE instance, LPVOID data )
1525 cs.lpCreateParams = data;
1526 cs.hInstance = instance;
1528 cs.hwndParent = parent;
1534 cs.lpszName = windowName;
1535 cs.lpszClass = className;
1536 cs.dwExStyle = exStyle;
1538 if (!IS_INTRESOURCE(className))
1541 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1543 return WIN_CreateWindowEx( &cs, bufferW, WIN_ISWIN32 );
1545 return WIN_CreateWindowEx( &cs, (LPCWSTR)className, WIN_ISWIN32 );
1549 /***********************************************************************
1550 * CreateWindowExW (USER32.@)
1552 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1553 LPCWSTR windowName, DWORD style, INT x,
1554 INT y, INT width, INT height,
1555 HWND parent, HMENU menu,
1556 HINSTANCE instance, LPVOID data )
1560 cs.lpCreateParams = data;
1561 cs.hInstance = instance;
1563 cs.hwndParent = parent;
1569 cs.lpszName = windowName;
1570 cs.lpszClass = className;
1571 cs.dwExStyle = exStyle;
1573 /* Note: we rely on the fact that CREATESTRUCTA and */
1574 /* CREATESTRUCTW have the same layout. */
1575 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, className, WIN_ISWIN32 | WIN_ISUNICODE );
1579 /***********************************************************************
1580 * WIN_SendDestroyMsg
1582 static void WIN_SendDestroyMsg( HWND hwnd )
1586 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1588 if (hwnd == info.hwndCaret) DestroyCaret();
1589 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1593 * Send the WM_DESTROY to the window.
1595 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1598 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1599 * make sure that the window still exists when we come back.
1606 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1608 for (i = 0; pWndArray[i]; i++)
1610 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1612 HeapFree( GetProcessHeap(), 0, pWndArray );
1615 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1619 /***********************************************************************
1620 * DestroyWindow (USER32.@)
1622 BOOL WINAPI DestroyWindow( HWND hwnd )
1626 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || is_desktop_window( hwnd ))
1628 SetLastError( ERROR_ACCESS_DENIED );
1632 TRACE("(%p)\n", hwnd);
1636 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1638 if (MENU_IsMenuActive() == hwnd)
1641 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1645 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1646 send_parent_notify( hwnd, WM_DESTROY );
1648 else if (!GetWindow( hwnd, GW_OWNER ))
1650 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1651 /* FIXME: clean up palette - see "Internals" p.352 */
1654 if (!IsWindow(hwnd)) return TRUE;
1656 /* Hide the window */
1657 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1659 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1661 ShowWindow( hwnd, SW_HIDE );
1663 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1664 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1667 if (!IsWindow(hwnd)) return TRUE;
1669 /* Recursively destroy owned windows */
1676 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1679 for (i = 0; list[i]; i++)
1681 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1682 if (WIN_IsCurrentThread( list[i] ))
1684 DestroyWindow( list[i] );
1688 WIN_SetOwner( list[i], 0 );
1690 HeapFree( GetProcessHeap(), 0, list );
1692 if (!got_one) break;
1696 /* Send destroy messages */
1698 WIN_SendDestroyMsg( hwnd );
1699 if (!IsWindow( hwnd )) return TRUE;
1701 if (GetClipboardOwner() == hwnd)
1702 CLIPBOARD_ReleaseOwner();
1704 /* Destroy the window storage */
1706 WIN_DestroyWindow( hwnd );
1711 /***********************************************************************
1712 * CloseWindow (USER32.@)
1714 BOOL WINAPI CloseWindow( HWND hwnd )
1716 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1717 ShowWindow( hwnd, SW_MINIMIZE );
1722 /***********************************************************************
1723 * OpenIcon (USER32.@)
1725 BOOL WINAPI OpenIcon( HWND hwnd )
1727 if (!IsIconic( hwnd )) return FALSE;
1728 ShowWindow( hwnd, SW_SHOWNORMAL );
1733 /***********************************************************************
1734 * FindWindowExW (USER32.@)
1736 HWND WINAPI FindWindowExW( HWND parent, HWND child, LPCWSTR className, LPCWSTR title )
1741 WCHAR *buffer = NULL;
1743 if (!parent && child) parent = GetDesktopWindow();
1744 else if (parent == HWND_MESSAGE) parent = get_hwnd_message_parent();
1748 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1749 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1752 if (!(list = list_window_children( 0, parent, className, 0 ))) goto done;
1756 child = WIN_GetFullHandle( child );
1757 while (list[i] && list[i] != child) i++;
1758 if (!list[i]) goto done;
1759 i++; /* start from next window */
1766 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1773 HeapFree( GetProcessHeap(), 0, list );
1774 HeapFree( GetProcessHeap(), 0, buffer );
1780 /***********************************************************************
1781 * FindWindowA (USER32.@)
1783 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1785 HWND ret = FindWindowExA( 0, 0, className, title );
1786 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1791 /***********************************************************************
1792 * FindWindowExA (USER32.@)
1794 HWND WINAPI FindWindowExA( HWND parent, HWND child, LPCSTR className, LPCSTR title )
1796 LPWSTR titleW = NULL;
1801 DWORD len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1802 if (!(titleW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1803 MultiByteToWideChar( CP_ACP, 0, title, -1, titleW, len );
1806 if (!IS_INTRESOURCE(className))
1809 if (MultiByteToWideChar( CP_ACP, 0, className, -1, classW, sizeof(classW)/sizeof(WCHAR) ))
1810 hwnd = FindWindowExW( parent, child, classW, titleW );
1814 hwnd = FindWindowExW( parent, child, (LPCWSTR)className, titleW );
1817 HeapFree( GetProcessHeap(), 0, titleW );
1822 /***********************************************************************
1823 * FindWindowW (USER32.@)
1825 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1827 return FindWindowExW( 0, 0, className, title );
1831 /**********************************************************************
1832 * GetDesktopWindow (USER32.@)
1834 HWND WINAPI GetDesktopWindow(void)
1836 struct user_thread_info *thread_info = get_user_thread_info();
1838 if (thread_info->top_window) return thread_info->top_window;
1840 SERVER_START_REQ( get_desktop_window )
1843 if (!wine_server_call( req ))
1845 thread_info->top_window = wine_server_ptr_handle( reply->top_window );
1846 thread_info->msg_window = wine_server_ptr_handle( reply->msg_window );
1851 if (!thread_info->top_window)
1853 USEROBJECTFLAGS flags;
1854 if (!GetUserObjectInformationW( GetProcessWindowStation(), UOI_FLAGS, &flags,
1855 sizeof(flags), NULL ) || (flags.dwFlags & WSF_VISIBLE))
1857 static const WCHAR explorer[] = {'\\','e','x','p','l','o','r','e','r','.','e','x','e',0};
1858 static const WCHAR args[] = {' ','/','d','e','s','k','t','o','p',0};
1860 PROCESS_INFORMATION pi;
1861 WCHAR windir[MAX_PATH];
1862 WCHAR app[MAX_PATH + sizeof(explorer)/sizeof(WCHAR)];
1863 WCHAR cmdline[MAX_PATH + (sizeof(explorer) + sizeof(args))/sizeof(WCHAR)];
1865 memset( &si, 0, sizeof(si) );
1867 si.dwFlags = STARTF_USESTDHANDLES;
1870 si.hStdError = GetStdHandle( STD_ERROR_HANDLE );
1872 GetWindowsDirectoryW( windir, MAX_PATH );
1873 strcpyW( app, windir );
1874 strcatW( app, explorer );
1875 strcpyW( cmdline, app );
1876 strcatW( cmdline, args );
1877 if (CreateProcessW( app, cmdline, NULL, NULL, FALSE, DETACHED_PROCESS,
1878 NULL, windir, &si, &pi ))
1880 TRACE( "started explorer pid %04x tid %04x\n", pi.dwProcessId, pi.dwThreadId );
1881 WaitForInputIdle( pi.hProcess, 10000 );
1882 CloseHandle( pi.hThread );
1883 CloseHandle( pi.hProcess );
1885 else WARN( "failed to start explorer, err %d\n", GetLastError() );
1887 else TRACE( "not starting explorer since winstation is not visible\n" );
1889 SERVER_START_REQ( get_desktop_window )
1892 if (!wine_server_call( req ))
1894 thread_info->top_window = wine_server_ptr_handle( reply->top_window );
1895 thread_info->msg_window = wine_server_ptr_handle( reply->msg_window );
1901 if (!thread_info->top_window || !USER_Driver->pCreateDesktopWindow( thread_info->top_window ))
1902 ERR( "failed to create desktop window\n" );
1904 return thread_info->top_window;
1908 /*******************************************************************
1909 * EnableWindow (USER32.@)
1911 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1916 if (is_broadcast(hwnd))
1918 SetLastError( ERROR_INVALID_PARAMETER );
1922 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1923 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1927 TRACE("( %p, %d )\n", hwnd, enable);
1929 retvalue = !IsWindowEnabled( hwnd );
1931 if (enable && retvalue)
1933 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1934 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1936 else if (!enable && !retvalue)
1940 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1942 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1944 if (hwnd == GetFocus())
1945 SetFocus( 0 ); /* A disabled window can't have the focus */
1947 capture_wnd = GetCapture();
1948 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1949 ReleaseCapture(); /* A disabled window can't capture the mouse */
1951 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1957 /***********************************************************************
1958 * IsWindowEnabled (USER32.@)
1960 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1962 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1966 /***********************************************************************
1967 * IsWindowUnicode (USER32.@)
1969 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1972 BOOL retvalue = FALSE;
1974 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1976 if (wndPtr == WND_DESKTOP) return TRUE;
1978 if (wndPtr != WND_OTHER_PROCESS)
1980 retvalue = (wndPtr->flags & WIN_ISUNICODE) != 0;
1981 WIN_ReleasePtr( wndPtr );
1985 SERVER_START_REQ( get_window_info )
1987 req->handle = wine_server_user_handle( hwnd );
1988 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1996 /**********************************************************************
1999 * Helper function for GetWindowLong().
2001 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicode )
2003 LONG_PTR retvalue = 0;
2006 if (offset == GWLP_HWNDPARENT)
2008 HWND parent = GetAncestor( hwnd, GA_PARENT );
2009 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
2010 return (ULONG_PTR)parent;
2013 if (!(wndPtr = WIN_GetPtr( hwnd )))
2015 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2019 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
2021 if (offset == GWLP_WNDPROC)
2023 SetLastError( ERROR_ACCESS_DENIED );
2026 SERVER_START_REQ( set_window_info )
2028 req->handle = wine_server_user_handle( hwnd );
2029 req->flags = 0; /* don't set anything, just retrieve */
2030 req->extra_offset = (offset >= 0) ? offset : -1;
2031 req->extra_size = (offset >= 0) ? size : 0;
2032 if (!wine_server_call_err( req ))
2036 case GWL_STYLE: retvalue = reply->old_style; break;
2037 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
2038 case GWLP_ID: retvalue = reply->old_id; break;
2039 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wine_server_get_ptr( reply->old_instance ); break;
2040 case GWLP_USERDATA: retvalue = reply->old_user_data; break;
2042 if (offset >= 0) retvalue = get_win_data( &reply->old_extra_value, size );
2043 else SetLastError( ERROR_INVALID_INDEX );
2052 /* now we have a valid wndPtr */
2056 if (offset > (int)(wndPtr->cbWndExtra - size))
2058 WARN("Invalid offset %d\n", offset );
2059 WIN_ReleasePtr( wndPtr );
2060 SetLastError( ERROR_INVALID_INDEX );
2063 retvalue = get_win_data( (char *)wndPtr->wExtra + offset, size );
2065 /* Special case for dialog window procedure */
2066 if ((offset == DWLP_DLGPROC) && (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
2067 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, unicode );
2068 WIN_ReleasePtr( wndPtr );
2074 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
2075 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
2076 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
2077 case GWLP_ID: retvalue = wndPtr->wIDmenu; break;
2078 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
2080 /* This looks like a hack only for the edit control (see tests). This makes these controls
2081 * more tolerant to A/W mismatches. The lack of W->A->W conversion for such a mismatch suggests
2082 * that the hack is in GetWindowLongPtr[AW], not in winprocs.
2084 if (wndPtr->winproc == EDIT_winproc_handle && (!unicode != !(wndPtr->flags & WIN_ISUNICODE)))
2085 retvalue = (ULONG_PTR)wndPtr->winproc;
2087 retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode );
2090 WARN("Unknown offset %d\n", offset );
2091 SetLastError( ERROR_INVALID_INDEX );
2094 WIN_ReleasePtr(wndPtr);
2099 /**********************************************************************
2102 * Helper function for SetWindowLong().
2104 * 0 is the failure code. However, in the case of failure SetLastError
2105 * must be set to distinguish between a 0 return value and a failure.
2107 LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL unicode )
2111 LONG_PTR retval = 0;
2114 TRACE( "%p %d %lx %c\n", hwnd, offset, newval, unicode ? 'W' : 'A' );
2116 if (is_broadcast(hwnd))
2118 SetLastError( ERROR_INVALID_PARAMETER );
2122 if (!(wndPtr = WIN_GetPtr( hwnd )))
2124 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2127 if (wndPtr == WND_DESKTOP)
2129 /* can't change anything on the desktop window */
2130 SetLastError( ERROR_ACCESS_DENIED );
2133 if (wndPtr == WND_OTHER_PROCESS)
2135 if (offset == GWLP_WNDPROC)
2137 SetLastError( ERROR_ACCESS_DENIED );
2140 if (offset > 32767 || offset < -32767)
2142 SetLastError( ERROR_INVALID_INDEX );
2145 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, MAKEWPARAM( offset, size ), newval );
2148 /* first some special cases */
2154 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
2155 style.styleNew = newval;
2156 WIN_ReleasePtr( wndPtr );
2157 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2158 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2159 newval = style.styleNew;
2161 case GWLP_HWNDPARENT:
2162 if (wndPtr->parent == GetDesktopWindow())
2164 WIN_ReleasePtr( wndPtr );
2165 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
2169 WIN_ReleasePtr( wndPtr );
2170 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
2175 UINT old_flags = wndPtr->flags;
2176 retval = WIN_GetWindowLong( hwnd, offset, size, unicode );
2177 if (unicode) proc = WINPROC_AllocProc( NULL, (WNDPROC)newval );
2178 else proc = WINPROC_AllocProc( (WNDPROC)newval, NULL );
2179 if (proc) wndPtr->winproc = proc;
2180 if (WINPROC_IsUnicode( proc, unicode )) wndPtr->flags |= WIN_ISUNICODE;
2181 else wndPtr->flags &= ~WIN_ISUNICODE;
2182 if (!((old_flags ^ wndPtr->flags) & WIN_ISUNICODE))
2184 WIN_ReleasePtr( wndPtr );
2187 /* update is_unicode flag on the server side */
2191 case GWLP_HINSTANCE:
2195 if ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2196 (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
2198 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
2199 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, unicode );
2200 if (unicode) *ptr = WINPROC_AllocProc( NULL, (WNDPROC)newval );
2201 else *ptr = WINPROC_AllocProc( (WNDPROC)newval, NULL );
2202 WIN_ReleasePtr( wndPtr );
2207 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - size))
2209 WARN("Invalid offset %d\n", offset );
2210 WIN_ReleasePtr( wndPtr );
2211 SetLastError( ERROR_INVALID_INDEX );
2214 else if (get_win_data( (char *)wndPtr->wExtra + offset, size ) == newval)
2216 /* already set to the same value */
2217 WIN_ReleasePtr( wndPtr );
2223 SERVER_START_REQ( set_window_info )
2225 req->handle = wine_server_user_handle( hwnd );
2226 req->extra_offset = -1;
2230 req->flags = SET_WIN_STYLE;
2231 req->style = newval;
2234 req->flags = SET_WIN_EXSTYLE;
2235 /* WS_EX_TOPMOST can only be changed through SetWindowPos */
2236 newval = (newval & ~WS_EX_TOPMOST) | (wndPtr->dwExStyle & WS_EX_TOPMOST);
2237 req->ex_style = newval;
2240 req->flags = SET_WIN_ID;
2243 case GWLP_HINSTANCE:
2244 req->flags = SET_WIN_INSTANCE;
2245 req->instance = wine_server_client_ptr( (void *)newval );
2248 req->flags = SET_WIN_UNICODE;
2249 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
2252 req->flags = SET_WIN_USERDATA;
2253 req->user_data = newval;
2256 req->flags = SET_WIN_EXTRA;
2257 req->extra_offset = offset;
2258 req->extra_size = size;
2259 set_win_data( &req->extra_value, newval, size );
2261 if ((ok = !wine_server_call_err( req )))
2266 wndPtr->dwStyle = newval;
2267 retval = reply->old_style;
2270 wndPtr->dwExStyle = newval;
2271 retval = reply->old_ex_style;
2274 wndPtr->wIDmenu = newval;
2275 retval = reply->old_id;
2277 case GWLP_HINSTANCE:
2278 wndPtr->hInstance = (HINSTANCE)newval;
2279 retval = (ULONG_PTR)wine_server_get_ptr( reply->old_instance );
2284 wndPtr->userdata = newval;
2285 retval = reply->old_user_data;
2288 retval = get_win_data( (char *)wndPtr->wExtra + offset, size );
2289 set_win_data( (char *)wndPtr->wExtra + offset, newval, size );
2295 WIN_ReleasePtr( wndPtr );
2299 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2301 USER_Driver->pSetWindowStyle( hwnd, offset, &style );
2302 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2309 /**********************************************************************
2310 * GetWindowWord (USER32.@)
2312 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
2317 case GWLP_HINSTANCE:
2318 case GWLP_HWNDPARENT:
2323 WARN("Invalid offset %d\n", offset );
2324 SetLastError( ERROR_INVALID_INDEX );
2329 return WIN_GetWindowLong( hwnd, offset, sizeof(WORD), FALSE );
2333 /**********************************************************************
2334 * GetWindowLongA (USER32.@)
2336 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2338 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), FALSE );
2342 /**********************************************************************
2343 * GetWindowLongW (USER32.@)
2345 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2347 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), TRUE );
2351 /**********************************************************************
2352 * SetWindowWord (USER32.@)
2354 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
2359 case GWLP_HINSTANCE:
2360 case GWLP_HWNDPARENT:
2365 WARN("Invalid offset %d\n", offset );
2366 SetLastError( ERROR_INVALID_INDEX );
2371 return WIN_SetWindowLong( hwnd, offset, sizeof(WORD), newval, FALSE );
2375 /**********************************************************************
2376 * SetWindowLongA (USER32.@)
2378 * See SetWindowLongW.
2380 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2382 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, FALSE );
2386 /**********************************************************************
2387 * SetWindowLongW (USER32.@) Set window attribute
2389 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2390 * value in a window's extra memory.
2392 * The _hwnd_ parameter specifies the window. is the handle to a
2393 * window that has extra memory. The _newval_ parameter contains the
2394 * new attribute or extra memory value. If positive, the _offset_
2395 * parameter is the byte-addressed location in the window's extra
2396 * memory to set. If negative, _offset_ specifies the window
2397 * attribute to set, and should be one of the following values:
2399 * GWL_EXSTYLE The window's extended window style
2401 * GWL_STYLE The window's window style.
2403 * GWLP_WNDPROC Pointer to the window's window procedure.
2405 * GWLP_HINSTANCE The window's pplication instance handle.
2407 * GWLP_ID The window's identifier.
2409 * GWLP_USERDATA The window's user-specified data.
2411 * If the window is a dialog box, the _offset_ parameter can be one of
2412 * the following values:
2414 * DWLP_DLGPROC The address of the window's dialog box procedure.
2416 * DWLP_MSGRESULT The return value of a message
2417 * that the dialog box procedure processed.
2419 * DWLP_USER Application specific information.
2423 * If successful, returns the previous value located at _offset_. Otherwise,
2428 * Extra memory for a window class is specified by a nonzero cbWndExtra
2429 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2430 * time of class creation.
2432 * Using GWL_WNDPROC to set a new window procedure effectively creates
2433 * a window subclass. Use CallWindowProc() in the new windows procedure
2434 * to pass messages to the superclass's window procedure.
2436 * The user data is reserved for use by the application which created
2439 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2440 * instead, call the EnableWindow() function to change the window's
2443 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2444 * SetParent() instead.
2447 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2448 * it sends WM_STYLECHANGING before changing the settings
2449 * and WM_STYLECHANGED afterwards.
2450 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2452 LONG WINAPI SetWindowLongW(
2453 HWND hwnd, /* [in] window to alter */
2454 INT offset, /* [in] offset, in bytes, of location to alter */
2455 LONG newval /* [in] new value of location */
2457 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, TRUE );
2461 /*******************************************************************
2462 * GetWindowTextA (USER32.@)
2464 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2468 if (!lpString) return 0;
2470 if (WIN_IsCurrentProcess( hwnd ))
2471 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2473 /* when window belongs to other process, don't send a message */
2474 if (nMaxCount <= 0) return 0;
2475 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2476 get_server_window_text( hwnd, buffer, nMaxCount );
2477 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2478 lpString[nMaxCount-1] = 0;
2479 HeapFree( GetProcessHeap(), 0, buffer );
2480 return strlen(lpString);
2484 /*******************************************************************
2485 * InternalGetWindowText (USER32.@)
2487 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2491 if (nMaxCount <= 0) return 0;
2492 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2493 if (win == WND_DESKTOP) lpString[0] = 0;
2494 else if (win != WND_OTHER_PROCESS)
2496 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2497 else lpString[0] = 0;
2498 WIN_ReleasePtr( win );
2502 get_server_window_text( hwnd, lpString, nMaxCount );
2504 return strlenW(lpString);
2508 /*******************************************************************
2509 * GetWindowTextW (USER32.@)
2511 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2513 if (!lpString) return 0;
2515 if (WIN_IsCurrentProcess( hwnd ))
2516 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2518 /* when window belongs to other process, don't send a message */
2519 if (nMaxCount <= 0) return 0;
2520 get_server_window_text( hwnd, lpString, nMaxCount );
2521 return strlenW(lpString);
2525 /*******************************************************************
2526 * SetWindowTextA (USER32.@)
2527 * SetWindowText (USER32.@)
2529 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2531 if (is_broadcast(hwnd))
2533 SetLastError( ERROR_INVALID_PARAMETER );
2536 if (!WIN_IsCurrentProcess( hwnd ))
2537 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2538 debugstr_a(lpString), hwnd );
2539 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2543 /*******************************************************************
2544 * SetWindowTextW (USER32.@)
2546 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2548 if (is_broadcast(hwnd))
2550 SetLastError( ERROR_INVALID_PARAMETER );
2553 if (!WIN_IsCurrentProcess( hwnd ))
2554 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2555 debugstr_w(lpString), hwnd );
2556 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2560 /*******************************************************************
2561 * GetWindowTextLengthA (USER32.@)
2563 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2565 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2568 /*******************************************************************
2569 * GetWindowTextLengthW (USER32.@)
2571 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2573 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2577 /*******************************************************************
2578 * IsWindow (USER32.@)
2580 BOOL WINAPI IsWindow( HWND hwnd )
2585 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2586 if (ptr == WND_DESKTOP) return TRUE;
2588 if (ptr != WND_OTHER_PROCESS)
2590 WIN_ReleasePtr( ptr );
2594 /* check other processes */
2595 SERVER_START_REQ( get_window_info )
2597 req->handle = wine_server_user_handle( hwnd );
2598 ret = !wine_server_call_err( req );
2605 /***********************************************************************
2606 * GetWindowThreadProcessId (USER32.@)
2608 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2613 if (!(ptr = WIN_GetPtr( hwnd )))
2615 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2619 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2621 /* got a valid window */
2623 if (process) *process = GetCurrentProcessId();
2624 WIN_ReleasePtr( ptr );
2628 /* check other processes */
2629 SERVER_START_REQ( get_window_info )
2631 req->handle = wine_server_user_handle( hwnd );
2632 if (!wine_server_call_err( req ))
2634 tid = (DWORD)reply->tid;
2635 if (process) *process = (DWORD)reply->pid;
2643 /*****************************************************************
2644 * GetParent (USER32.@)
2646 HWND WINAPI GetParent( HWND hwnd )
2651 if (!(wndPtr = WIN_GetPtr( hwnd )))
2653 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2656 if (wndPtr == WND_DESKTOP) return 0;
2657 if (wndPtr == WND_OTHER_PROCESS)
2659 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2660 if (style & (WS_POPUP | WS_CHILD))
2662 SERVER_START_REQ( get_window_tree )
2664 req->handle = wine_server_user_handle( hwnd );
2665 if (!wine_server_call_err( req ))
2667 if (style & WS_POPUP) retvalue = wine_server_ptr_handle( reply->owner );
2668 else if (style & WS_CHILD) retvalue = wine_server_ptr_handle( reply->parent );
2676 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2677 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2678 WIN_ReleasePtr( wndPtr );
2684 /*****************************************************************
2685 * GetAncestor (USER32.@)
2687 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2690 HWND *list, ret = 0;
2695 if (!(win = WIN_GetPtr( hwnd )))
2697 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2700 if (win == WND_DESKTOP) return 0;
2701 if (win != WND_OTHER_PROCESS)
2704 WIN_ReleasePtr( win );
2706 else /* need to query the server */
2708 SERVER_START_REQ( get_window_tree )
2710 req->handle = wine_server_user_handle( hwnd );
2711 if (!wine_server_call_err( req )) ret = wine_server_ptr_handle( reply->parent );
2718 if (!(list = list_window_parents( hwnd ))) return 0;
2720 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2724 while (list[count]) count++;
2725 ret = list[count - 2]; /* get the one before the desktop */
2727 HeapFree( GetProcessHeap(), 0, list );
2731 if (is_desktop_window( hwnd )) return 0;
2732 ret = WIN_GetFullHandle( hwnd );
2735 HWND parent = GetParent( ret );
2745 /*****************************************************************
2746 * SetParent (USER32.@)
2748 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2751 HWND old_parent = 0;
2756 if (is_broadcast(hwnd) || is_broadcast(parent))
2758 SetLastError(ERROR_INVALID_PARAMETER);
2762 if (!parent) parent = GetDesktopWindow();
2763 else if (parent == HWND_MESSAGE) parent = get_hwnd_message_parent();
2764 else parent = WIN_GetFullHandle( parent );
2766 if (!IsWindow( parent ))
2768 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2772 /* Some applications try to set a child as a parent */
2773 if (IsChild(hwnd, parent))
2775 SetLastError( ERROR_INVALID_PARAMETER );
2779 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2780 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2782 /* Windows hides the window first, then shows it again
2783 * including the WM_SHOWWINDOW messages and all */
2784 was_visible = ShowWindow( hwnd, SW_HIDE );
2786 wndPtr = WIN_GetPtr( hwnd );
2787 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return 0;
2789 SERVER_START_REQ( set_parent )
2791 req->handle = wine_server_user_handle( hwnd );
2792 req->parent = wine_server_user_handle( parent );
2793 if ((ret = !wine_server_call( req )))
2795 old_parent = wine_server_ptr_handle( reply->old_parent );
2796 wndPtr->parent = parent = wine_server_ptr_handle( reply->full_parent );
2801 WIN_ReleasePtr( wndPtr );
2804 USER_Driver->pSetParent( full_handle, parent, old_parent );
2806 /* SetParent additionally needs to make hwnd the topmost window
2807 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2808 WM_WINDOWPOSCHANGED notification messages.
2810 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0,
2811 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2812 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2813 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2819 /*******************************************************************
2820 * IsChild (USER32.@)
2822 BOOL WINAPI IsChild( HWND parent, HWND child )
2824 HWND *list = list_window_parents( child );
2828 if (!list) return FALSE;
2829 parent = WIN_GetFullHandle( parent );
2830 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2831 ret = list[i] && list[i+1];
2832 HeapFree( GetProcessHeap(), 0, list );
2837 /***********************************************************************
2838 * IsWindowVisible (USER32.@)
2840 BOOL WINAPI IsWindowVisible( HWND hwnd )
2846 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2847 if (!(list = list_window_parents( hwnd ))) return TRUE;
2850 for (i = 0; list[i+1]; i++)
2851 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2852 retval = !list[i+1] && (list[i] == GetDesktopWindow()); /* top message window isn't visible */
2854 HeapFree( GetProcessHeap(), 0, list );
2859 /***********************************************************************
2860 * WIN_IsWindowDrawable
2862 * hwnd is drawable when it is visible, all parents are not
2863 * minimized, and it is itself not minimized unless we are
2864 * trying to draw its default class icon.
2866 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2871 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2873 if (!(style & WS_VISIBLE)) return FALSE;
2874 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2876 if (!(list = list_window_parents( hwnd ))) return TRUE;
2879 for (i = 0; list[i+1]; i++)
2880 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2882 retval = !list[i+1] && (list[i] == GetDesktopWindow()); /* top message window isn't visible */
2884 HeapFree( GetProcessHeap(), 0, list );
2889 /*******************************************************************
2890 * GetTopWindow (USER32.@)
2892 HWND WINAPI GetTopWindow( HWND hwnd )
2894 if (!hwnd) hwnd = GetDesktopWindow();
2895 return GetWindow( hwnd, GW_CHILD );
2899 /*******************************************************************
2900 * GetWindow (USER32.@)
2902 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2906 if (rel == GW_OWNER) /* this one may be available locally */
2908 WND *wndPtr = WIN_GetPtr( hwnd );
2911 SetLastError( ERROR_INVALID_HANDLE );
2914 if (wndPtr == WND_DESKTOP) return 0;
2915 if (wndPtr != WND_OTHER_PROCESS)
2917 retval = wndPtr->owner;
2918 WIN_ReleasePtr( wndPtr );
2921 /* else fall through to server call */
2924 SERVER_START_REQ( get_window_tree )
2926 req->handle = wine_server_user_handle( hwnd );
2927 if (!wine_server_call_err( req ))
2932 retval = wine_server_ptr_handle( reply->first_sibling );
2935 retval = wine_server_ptr_handle( reply->last_sibling );
2938 retval = wine_server_ptr_handle( reply->next_sibling );
2941 retval = wine_server_ptr_handle( reply->prev_sibling );
2944 retval = wine_server_ptr_handle( reply->owner );
2947 retval = wine_server_ptr_handle( reply->first_child );
2957 /*******************************************************************
2958 * ShowOwnedPopups (USER32.@)
2960 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2964 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2966 if (!win_array) return TRUE;
2968 while (win_array[count]) count++;
2969 while (--count >= 0)
2971 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2972 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2973 if (pWnd == WND_OTHER_PROCESS) continue;
2976 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2978 WIN_ReleasePtr( pWnd );
2979 /* In Windows, ShowOwnedPopups(TRUE) generates
2980 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2981 * regardless of the state of the owner
2983 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2989 if (pWnd->dwStyle & WS_VISIBLE)
2991 WIN_ReleasePtr( pWnd );
2992 /* In Windows, ShowOwnedPopups(FALSE) generates
2993 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2994 * regardless of the state of the owner
2996 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
3000 WIN_ReleasePtr( pWnd );
3002 HeapFree( GetProcessHeap(), 0, win_array );
3007 /*******************************************************************
3008 * GetLastActivePopup (USER32.@)
3010 HWND WINAPI GetLastActivePopup( HWND hwnd )
3014 SERVER_START_REQ( get_window_info )
3016 req->handle = wine_server_user_handle( hwnd );
3017 if (!wine_server_call_err( req )) retval = wine_server_ptr_handle( reply->last_active );
3024 /*******************************************************************
3027 * Build an array of the children of a given window. The array must be
3028 * freed with HeapFree. Returns NULL when no windows are found.
3030 HWND *WIN_ListChildren( HWND hwnd )
3034 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
3037 return list_window_children( 0, hwnd, NULL, 0 );
3041 /*******************************************************************
3042 * EnumWindows (USER32.@)
3044 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
3050 USER_CheckNotLock();
3052 /* We have to build a list of all windows first, to avoid */
3053 /* unpleasant side-effects, for instance if the callback */
3054 /* function changes the Z-order of the windows. */
3056 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
3058 /* Now call the callback function for every window */
3060 for (i = 0; list[i]; i++)
3062 /* Make sure that the window still exists */
3063 if (!IsWindow( list[i] )) continue;
3064 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
3066 HeapFree( GetProcessHeap(), 0, list );
3071 /**********************************************************************
3072 * EnumThreadWindows (USER32.@)
3074 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
3080 USER_CheckNotLock();
3082 if (!(list = list_window_children( 0, GetDesktopWindow(), NULL, id ))) return TRUE;
3084 /* Now call the callback function for every window */
3086 for (i = 0; list[i]; i++)
3087 if (!(ret = func( list[i], lParam ))) break;
3088 HeapFree( GetProcessHeap(), 0, list );
3093 /***********************************************************************
3094 * EnumDesktopWindows (USER32.@)
3096 BOOL WINAPI EnumDesktopWindows( HDESK desktop, WNDENUMPROC func, LPARAM lparam )
3101 USER_CheckNotLock();
3103 if (!(list = list_window_children( desktop, 0, NULL, 0 ))) return TRUE;
3105 for (i = 0; list[i]; i++)
3106 if (!func( list[i], lparam )) break;
3107 HeapFree( GetProcessHeap(), 0, list );
3112 /**********************************************************************
3113 * WIN_EnumChildWindows
3115 * Helper function for EnumChildWindows().
3117 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
3122 for ( ; *list; list++)
3124 /* Make sure that the window still exists */
3125 if (!IsWindow( *list )) continue;
3126 /* Build children list first */
3127 childList = WIN_ListChildren( *list );
3129 ret = func( *list, lParam );
3133 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
3134 HeapFree( GetProcessHeap(), 0, childList );
3136 if (!ret) return FALSE;
3142 /**********************************************************************
3143 * EnumChildWindows (USER32.@)
3145 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3150 USER_CheckNotLock();
3152 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3153 ret = WIN_EnumChildWindows( list, func, lParam );
3154 HeapFree( GetProcessHeap(), 0, list );
3159 /*******************************************************************
3160 * AnyPopup (USER.52)
3162 BOOL16 WINAPI AnyPopup16(void)
3168 /*******************************************************************
3169 * AnyPopup (USER32.@)
3171 BOOL WINAPI AnyPopup(void)
3175 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3177 if (!list) return FALSE;
3178 for (i = 0; list[i]; i++)
3180 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3182 retvalue = (list[i] != 0);
3183 HeapFree( GetProcessHeap(), 0, list );
3188 /*******************************************************************
3189 * FlashWindow (USER32.@)
3191 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3195 TRACE("%p\n", hWnd);
3197 if (IsIconic( hWnd ))
3199 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3201 wndPtr = WIN_GetPtr(hWnd);
3202 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3203 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3205 wndPtr->flags |= WIN_NCACTIVATED;
3209 wndPtr->flags &= ~WIN_NCACTIVATED;
3211 WIN_ReleasePtr( wndPtr );
3218 wndPtr = WIN_GetPtr(hWnd);
3219 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3220 hWnd = wndPtr->obj.handle; /* make it a full handle */
3222 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3223 else wparam = (hWnd == GetForegroundWindow());
3225 WIN_ReleasePtr( wndPtr );
3226 SendMessageW( hWnd, WM_NCACTIVATE, wparam, 0 );
3231 /*******************************************************************
3232 * FlashWindowEx (USER32.@)
3234 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3236 FIXME("%p\n", pfwi);
3240 /*******************************************************************
3241 * GetWindowContextHelpId (USER32.@)
3243 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3246 WND *wnd = WIN_GetPtr( hwnd );
3247 if (!wnd || wnd == WND_DESKTOP) return 0;
3248 if (wnd == WND_OTHER_PROCESS)
3250 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3253 retval = wnd->helpContext;
3254 WIN_ReleasePtr( wnd );
3259 /*******************************************************************
3260 * SetWindowContextHelpId (USER32.@)
3262 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3264 WND *wnd = WIN_GetPtr( hwnd );
3265 if (!wnd || wnd == WND_DESKTOP) return FALSE;
3266 if (wnd == WND_OTHER_PROCESS)
3268 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3271 wnd->helpContext = id;
3272 WIN_ReleasePtr( wnd );
3277 /*******************************************************************
3278 * DragDetect (USER32.@)
3280 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3284 WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
3285 WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
3287 rect.left = pt.x - wDragWidth;
3288 rect.right = pt.x + wDragWidth;
3290 rect.top = pt.y - wDragHeight;
3291 rect.bottom = pt.y + wDragHeight;
3297 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3299 if( msg.message == WM_LBUTTONUP )
3304 if( msg.message == WM_MOUSEMOVE )
3307 tmp.x = (short)LOWORD(msg.lParam);
3308 tmp.y = (short)HIWORD(msg.lParam);
3309 if( !PtInRect( &rect, tmp ))
3321 /******************************************************************************
3322 * GetWindowModuleFileNameA (USER32.@)
3324 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR module, UINT size )
3329 TRACE( "%p, %p, %u\n", hwnd, module, size );
3331 win = WIN_GetPtr( hwnd );
3332 if (!win || win == WND_OTHER_PROCESS || win == WND_DESKTOP)
3334 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
3337 hinst = win->hInstance;
3338 WIN_ReleasePtr( win );
3340 return GetModuleFileNameA( hinst, module, size );
3343 /******************************************************************************
3344 * GetWindowModuleFileNameW (USER32.@)
3346 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR module, UINT size )
3351 TRACE( "%p, %p, %u\n", hwnd, module, size );
3353 win = WIN_GetPtr( hwnd );
3354 if (!win || win == WND_OTHER_PROCESS || win == WND_DESKTOP)
3356 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
3359 hinst = win->hInstance;
3360 WIN_ReleasePtr( win );
3362 return GetModuleFileNameW( hinst, module, size );
3365 /******************************************************************************
3366 * GetWindowInfo (USER32.@)
3368 * Note: tests show that Windows doesn't check cbSize of the structure.
3370 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3372 if (!pwi) return FALSE;
3373 if (!IsWindow(hwnd)) return FALSE;
3375 GetWindowRect(hwnd, &pwi->rcWindow);
3376 GetClientRect(hwnd, &pwi->rcClient);
3377 /* translate to screen coordinates */
3378 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3380 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3381 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3382 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3384 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3385 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3387 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3388 pwi->wCreatorVersion = 0x0400;
3393 /******************************************************************************
3394 * SwitchDesktop (USER32.@)
3396 * NOTES: Sets the current input or interactive desktop.
3398 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3400 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3404 /*****************************************************************************
3405 * SetLayeredWindowAttributes (USER32.@)
3407 BOOL WINAPI SetLayeredWindowAttributes( HWND hwnd, COLORREF key, BYTE alpha, DWORD flags )
3411 TRACE("(%p,%08x,%d,%x): stub!\n", hwnd, key, alpha, flags);
3413 SERVER_START_REQ( set_window_layered_info )
3415 req->handle = wine_server_user_handle( hwnd );
3416 req->color_key = key;
3419 ret = !wine_server_call_err( req );
3423 if (ret) USER_Driver->pSetLayeredWindowAttributes( hwnd, key, alpha, flags );
3429 /*****************************************************************************
3430 * GetLayeredWindowAttributes (USER32.@)
3432 BOOL WINAPI GetLayeredWindowAttributes( HWND hwnd, COLORREF *key, BYTE *alpha, DWORD *flags )
3436 SERVER_START_REQ( get_window_layered_info )
3438 req->handle = wine_server_user_handle( hwnd );
3439 if ((ret = !wine_server_call_err( req )))
3441 if (key) *key = reply->color_key;
3442 if (alpha) *alpha = reply->alpha;
3443 if (flags) *flags = reply->flags;
3452 /*****************************************************************************
3453 * UpdateLayeredWindowIndirect (USER32.@)
3455 BOOL WINAPI UpdateLayeredWindowIndirect( HWND hwnd, const UPDATELAYEREDWINDOWINFO *info )
3459 if (!(info->dwFlags & ULW_EX_NORESIZE) && (info->pptDst || info->psize))
3461 int x = 0, y = 0, cx = 0, cy = 0;
3462 DWORD flags = SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOSENDCHANGING;
3466 x = info->pptDst->x;
3467 y = info->pptDst->y;
3468 flags &= ~SWP_NOMOVE;
3472 cx = info->psize->cx;
3473 cy = info->psize->cy;
3474 flags &= ~SWP_NOSIZE;
3476 TRACE( "moving window %p pos %d,%d %dx%x\n", hwnd, x, y, cx, cy );
3477 SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
3483 HDC hdc = GetDCEx( hwnd, 0, DCX_CACHE );
3489 GetClientRect( hwnd, &rect );
3492 x = info->pptSrc->x;
3493 y = info->pptSrc->y;
3495 /* FIXME: intersect rect with info->prcDirty */
3496 TRACE( "copying window %p pos %d,%d\n", hwnd, x, y );
3497 BitBlt( hdc, rect.left, rect.top, rect.right, rect.bottom,
3498 info->hdcSrc, rect.left + x, rect.top + y, SRCCOPY );
3499 ReleaseDC( hwnd, hdc );
3503 if (info->pblend && !(info->dwFlags & ULW_OPAQUE)) alpha = info->pblend->SourceConstantAlpha;
3504 TRACE( "setting window %p alpha %u\n", hwnd, alpha );
3505 USER_Driver->pSetLayeredWindowAttributes( hwnd, info->crKey, alpha,
3506 info->dwFlags & (LWA_ALPHA | LWA_COLORKEY) );
3511 /*****************************************************************************
3512 * UpdateLayeredWindow (USER32.@)
3514 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3515 HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3518 UPDATELAYEREDWINDOWINFO info;
3520 info.cbSize = sizeof(info);
3521 info.hdcDst = hdcDst;
3522 info.pptDst = pptDst;
3524 info.hdcSrc = hdcSrc;
3525 info.pptSrc = pptSrc;
3527 info.pblend = pblend;
3528 info.dwFlags = dwFlags;
3529 info.prcDirty = NULL;
3530 return UpdateLayeredWindowIndirect( hwnd, &info );
3533 /* 64bit versions */
3535 #ifdef GetWindowLongPtrW
3536 #undef GetWindowLongPtrW
3539 #ifdef GetWindowLongPtrA
3540 #undef GetWindowLongPtrA
3543 #ifdef SetWindowLongPtrW
3544 #undef SetWindowLongPtrW
3547 #ifdef SetWindowLongPtrA
3548 #undef SetWindowLongPtrA
3551 /*****************************************************************************
3552 * GetWindowLongPtrW (USER32.@)
3554 LONG_PTR WINAPI GetWindowLongPtrW( HWND hwnd, INT offset )
3556 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), TRUE );
3559 /*****************************************************************************
3560 * GetWindowLongPtrA (USER32.@)
3562 LONG_PTR WINAPI GetWindowLongPtrA( HWND hwnd, INT offset )
3564 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), FALSE );
3567 /*****************************************************************************
3568 * SetWindowLongPtrW (USER32.@)
3570 LONG_PTR WINAPI SetWindowLongPtrW( HWND hwnd, INT offset, LONG_PTR newval )
3572 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, TRUE );
3575 /*****************************************************************************
3576 * SetWindowLongPtrA (USER32.@)
3578 LONG_PTR WINAPI SetWindowLongPtrA( HWND hwnd, INT offset, LONG_PTR newval )
3580 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, FALSE );