2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
11 #include "wine/winbase16.h"
12 #include "wine/winuser16.h"
13 #include "wine/server.h"
14 #include "wine/unicode.h"
20 #include "cursoricon.h"
27 #include "stackframe.h"
28 #include "debugtools.h"
30 DEFAULT_DEBUG_CHANNEL(win);
31 DECLARE_DEBUG_CHANNEL(msg);
33 #define NB_USER_HANDLES (LAST_USER_HANDLE - FIRST_USER_HANDLE + 1)
35 /**********************************************************************/
38 static WND *pWndDesktop = NULL;
40 static WORD wDragWidth = 4;
41 static WORD wDragHeight= 3;
43 static void *user_handles[NB_USER_HANDLES];
46 extern SYSLEVEL USER_SysLevel; /* FIXME */
48 /***********************************************************************
51 * Suspend the lock on WND structures.
52 * Returns the number of locks suspended
54 int WIN_SuspendWndsLock( void )
56 int isuspendedLocks = _ConfirmSysLevel( &USER_SysLevel );
57 int count = isuspendedLocks;
60 _LeaveSysLevel( &USER_SysLevel );
62 return isuspendedLocks;
65 /***********************************************************************
68 * Restore the suspended locks on WND structures
70 void WIN_RestoreWndsLock( int ipreviousLocks )
72 while ( ipreviousLocks-- > 0 )
73 _EnterSysLevel( &USER_SysLevel );
76 /***********************************************************************
77 * create_window_handle
79 * Create a window handle with the server.
81 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom, INT size )
84 user_handle_t handle = 0;
86 WND *win = HeapAlloc( GetProcessHeap(), 0, size );
88 if (!win) return NULL;
92 SERVER_START_REQ( create_window )
97 if ((res = !SERVER_CALL_ERR())) handle = req->handle;
104 HeapFree( GetProcessHeap(), 0, win );
107 index = LOWORD(handle) - FIRST_USER_HANDLE;
108 assert( index < NB_USER_HANDLES );
109 user_handles[index] = win;
110 win->hwndSelf = handle;
111 win->dwMagic = WND_MAGIC;
117 /***********************************************************************
120 * Free a window handle.
122 static WND *free_window_handle( HWND hwnd )
125 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
127 if (index >= NB_USER_HANDLES) return NULL;
129 if ((ptr = user_handles[index]))
131 SERVER_START_REQ( destroy_window )
134 if (!SERVER_CALL_ERR())
135 user_handles[index] = NULL;
142 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
147 /*******************************************************************
148 * list_window_children
150 * Build an array of the children of a given window. The array must be
151 * freed with HeapFree. Returns NULL when no windows are found.
153 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
157 SERVER_START_VAR_REQ( get_window_children, REQUEST_MAX_VAR_SIZE )
161 req->tid = (void *)tid;
164 user_handle_t *data = server_data_ptr(req);
165 int i, count = server_data_size(req) / sizeof(*data);
166 if (count && ((list = HeapAlloc( GetProcessHeap(), 0, (count + 1) * sizeof(HWND) ))))
168 for (i = 0; i < count; i++) list[i] = data[i];
178 /*******************************************************************
181 static void send_parent_notify( HWND hwnd, UINT msg )
183 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) return;
184 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) return;
185 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
186 MAKEWPARAM( msg, GetWindowLongW( hwnd, GWL_ID )), (LPARAM)hwnd );
190 /*******************************************************************
191 * get_server_window_text
193 * Retrieve the window text from the server.
195 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
197 size_t len = (count - 1) * sizeof(WCHAR);
198 len = min( len, REQUEST_MAX_VAR_SIZE );
199 SERVER_START_VAR_REQ( get_window_text, len )
202 if (!SERVER_CALL_ERR())
204 len = server_data_size(req);
205 memcpy( text, server_data_ptr(req), len );
210 text[len / sizeof(WCHAR)] = 0;
214 /***********************************************************************
217 * Return a pointer to the WND structure if local to the process,
218 * or WND_OTHER_PROCESS is handle may be valid in other process.
219 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
221 WND *WIN_GetPtr( HWND hwnd )
224 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
226 if (index >= NB_USER_HANDLES) return NULL;
229 if ((ptr = user_handles[index]))
231 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
235 else ptr = WND_OTHER_PROCESS;
241 /***********************************************************************
242 * WIN_IsCurrentProcess
244 * Check whether a given window belongs to the current process (and return the full handle).
246 HWND WIN_IsCurrentProcess( HWND hwnd )
251 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
253 WIN_ReleasePtr( ptr );
258 /***********************************************************************
259 * WIN_IsCurrentThread
261 * Check whether a given window belongs to the current thread (and return the full handle).
263 HWND WIN_IsCurrentThread( HWND hwnd )
268 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
270 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
271 WIN_ReleasePtr( ptr );
277 /***********************************************************************
280 * Convert a 16-bit window handle to a full 32-bit handle.
282 HWND WIN_Handle32( HWND16 hwnd16 )
285 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
287 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
288 /* do sign extension for -2 and -3 */
289 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
291 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
293 if (ptr != WND_OTHER_PROCESS)
295 hwnd = ptr->hwndSelf;
296 WIN_ReleasePtr( ptr );
298 else /* may belong to another process */
300 SERVER_START_REQ( get_window_info )
303 if (!SERVER_CALL_ERR()) hwnd = req->full_handle;
311 /***********************************************************************
314 * Return a pointer to the WND structure corresponding to a HWND.
316 WND * WIN_FindWndPtr( HWND hwnd )
320 if (!hwnd) return NULL;
322 if ((ptr = WIN_GetPtr( hwnd )))
324 if (ptr != WND_OTHER_PROCESS)
326 /* increment destruction monitoring */
330 if (IsWindow( hwnd )) /* check other processes */
332 ERR( "window %04x belongs to other process\n", hwnd );
333 /* DbgBreakPoint(); */
336 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
341 /***********************************************************************
344 * Release the pointer to the WND structure.
346 void WIN_ReleaseWndPtr(WND *wndPtr)
350 /* Decrement destruction monitoring value */
352 /* Check if it's time to release the memory */
353 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
356 free_window_handle( wndPtr->hwndSelf );
358 else if(wndPtr->irefCount < 0)
360 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
361 ERR("forgot a Lock on %p somewhere\n",wndPtr);
363 /* unlock all WND structures for thread safeness */
368 /***********************************************************************
371 * Remove a window from the siblings linked list.
373 void WIN_UnlinkWindow( HWND hwnd )
375 WIN_LinkWindow( hwnd, 0, 0 );
379 /***********************************************************************
382 * Insert a window into the siblings linked list.
383 * The window is inserted after the specified window, which can also
384 * be specified as HWND_TOP or HWND_BOTTOM.
385 * If parent is 0, window is unlinked from the tree.
387 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
389 WND *wndPtr = WIN_GetPtr( hwnd );
392 if (wndPtr == WND_OTHER_PROCESS)
394 if (IsWindow(hwnd)) ERR(" cannot link other process window %x\n", hwnd );
398 SERVER_START_REQ( link_window )
401 req->parent = parent;
402 req->previous = hwndInsertAfter;
405 if (req->full_parent && req->full_parent != wndPtr->parent)
407 wndPtr->owner = 0; /* reset owner when changing parent */
408 wndPtr->parent = req->full_parent;
414 WIN_ReleasePtr( wndPtr );
418 /***********************************************************************
421 * Change the owner of a window.
423 void WIN_SetOwner( HWND hwnd, HWND owner )
425 WND *win = WIN_GetPtr( hwnd );
428 if (win == WND_OTHER_PROCESS)
430 if (IsWindow(hwnd)) ERR( "cannot set owner %x on other process window %x\n", owner, hwnd );
433 SERVER_START_REQ( set_window_owner )
437 if (!SERVER_CALL()) win->owner = req->full_owner;
440 WIN_ReleasePtr( win );
444 /***********************************************************************
447 * Change the style of a window.
449 LONG WIN_SetStyle( HWND hwnd, LONG style )
453 WND *win = WIN_GetPtr( hwnd );
456 if (win == WND_OTHER_PROCESS)
459 ERR( "cannot set style %lx on other process window %x\n", style, hwnd );
462 if (style == win->dwStyle)
464 WIN_ReleasePtr( win );
467 SERVER_START_REQ( set_window_info )
470 req->flags = SET_WIN_STYLE;
472 if ((ok = !SERVER_CALL()))
474 ret = req->old_style;
475 win->dwStyle = style;
479 WIN_ReleasePtr( win );
480 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret );
485 /***********************************************************************
488 * Change the extended style of a window.
490 LONG WIN_SetExStyle( HWND hwnd, LONG style )
493 WND *win = WIN_GetPtr( hwnd );
496 if (win == WND_OTHER_PROCESS)
499 ERR( "cannot set exstyle %lx on other process window %x\n", style, hwnd );
502 if (style == win->dwExStyle)
504 WIN_ReleasePtr( win );
507 SERVER_START_REQ( set_window_info )
510 req->flags = SET_WIN_EXSTYLE;
511 req->ex_style = style;
514 ret = req->old_ex_style;
515 win->dwExStyle = style;
519 WIN_ReleasePtr( win );
524 /***********************************************************************
527 * Set the window and client rectangles.
529 void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient )
531 WND *win = WIN_GetPtr( hwnd );
535 if (win == WND_OTHER_PROCESS)
537 if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %x\n", hwnd );
540 SERVER_START_REQ( set_window_rectangles )
543 req->window.left = rectWindow->left;
544 req->window.top = rectWindow->top;
545 req->window.right = rectWindow->right;
546 req->window.bottom = rectWindow->bottom;
547 req->client.left = rectClient->left;
548 req->client.top = rectClient->top;
549 req->client.right = rectClient->right;
550 req->client.bottom = rectClient->bottom;
551 ret = !SERVER_CALL();
556 win->rectWindow = *rectWindow;
557 win->rectClient = *rectClient;
559 TRACE( "win %x window (%d,%d)-(%d,%d) client (%d,%d)-(%d,%d)\n", hwnd,
560 rectWindow->left, rectWindow->top, rectWindow->right, rectWindow->bottom,
561 rectClient->left, rectClient->top, rectClient->right, rectClient->bottom );
563 WIN_ReleasePtr( win );
567 /***********************************************************************
568 * find_child_to_repaint
570 * Find a window that needs repaint among the children of the specified window.
572 static HWND find_child_to_repaint( HWND parent )
578 if (!parent) parent = GetDesktopWindow();
579 if (!(list = list_window_children( parent, 0, 0 ))) return 0;
581 for (i = 0; list[i] && !ret; i++)
583 WND *win = WIN_GetPtr( list[i] );
584 if (!win) continue; /* ignore it */
585 if (win == WND_OTHER_PROCESS)
587 /* doesn't belong to this process, but check children */
588 ret = find_child_to_repaint( list[i] );
591 if (!(win->dwStyle & WS_VISIBLE))
593 WIN_ReleasePtr( win );
596 if ((win->tid != GetCurrentThreadId()) ||
597 (!win->hrgnUpdate && !(win->flags & WIN_INTERNAL_PAINT)))
599 /* does not need repaint, check children */
600 WIN_ReleasePtr( win );
601 ret = find_child_to_repaint( list[i] );
605 /* now we have something */
607 if (!(win->dwExStyle & WS_EX_TRANSPARENT))
609 /* not transparent, we can repaint it */
610 WIN_ReleasePtr( win );
613 WIN_ReleasePtr( win );
615 /* transparent window, look for non-transparent sibling to paint first */
616 for (i++; list[i]; i++)
618 if (!(win = WIN_GetPtr( list[i] ))) continue;
619 if (win == WND_OTHER_PROCESS) continue;
620 if (!(win->dwStyle & WS_VISIBLE))
622 WIN_ReleasePtr( win );
625 if (!(win->dwExStyle & WS_EX_TRANSPARENT) &&
626 (win->hrgnUpdate || (win->flags & WIN_INTERNAL_PAINT)))
629 WIN_ReleasePtr( win );
632 WIN_ReleasePtr( win );
635 HeapFree( GetProcessHeap(), 0, list );
640 /***********************************************************************
641 * WIN_FindWinToRepaint
643 * Find a window that needs repaint.
645 HWND WIN_FindWinToRepaint( HWND hwnd )
647 /* Note: the desktop window never gets WM_PAINT messages
648 * The real reason why is because Windows DesktopWndProc
649 * does ValidateRgn inside WM_ERASEBKGND handler.
651 if (hwnd == GetDesktopWindow()) hwnd = 0;
655 /* check the window itself first */
656 WND *win = WIN_FindWndPtr( hwnd );
658 if ((win->dwStyle & WS_VISIBLE) &&
659 (win->hrgnUpdate || (win->flags & WIN_INTERNAL_PAINT)))
661 WIN_ReleaseWndPtr( win );
664 WIN_ReleaseWndPtr( win );
666 /* now check its children */
667 return find_child_to_repaint( hwnd );
671 /***********************************************************************
674 * Destroy storage associated to a window. "Internals" p.358
676 LRESULT WIN_DestroyWindow( HWND hwnd )
681 TRACE("%04x\n", hwnd );
683 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
685 ERR( "window doesn't belong to current thread\n" );
689 /* free child windows */
690 if ((list = WIN_ListChildren( hwnd )))
693 for (i = 0; list[i]; i++)
695 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
696 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
698 HeapFree( GetProcessHeap(), 0, list );
702 * Clear the update region to make sure no WM_PAINT messages will be
703 * generated for this window while processing the WM_NCDESTROY.
705 RedrawWindow( hwnd, NULL, 0,
706 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
709 * Send the WM_NCDESTROY to the window being destroyed.
711 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
713 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
715 WINPOS_CheckInternalPos( hwnd );
716 if( hwnd == GetCapture()) ReleaseCapture();
718 /* free resources associated with the window */
720 TIMER_RemoveWindowTimers( hwnd );
722 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
723 wndPtr->hmemTaskQ = 0;
725 if (!(wndPtr->dwStyle & WS_CHILD))
727 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
728 if (menu) DestroyMenu( menu );
730 if (wndPtr->hSysMenu)
732 DestroyMenu( wndPtr->hSysMenu );
733 wndPtr->hSysMenu = 0;
735 USER_Driver.pDestroyWindow( hwnd );
736 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
737 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
738 CLASS_RemoveWindow( wndPtr->class );
739 wndPtr->class = NULL;
740 wndPtr->dwMagic = 0; /* Mark it as invalid */
741 WIN_ReleaseWndPtr( wndPtr );
745 /***********************************************************************
746 * WIN_DestroyThreadWindows
748 * Destroy all children of 'wnd' owned by the current thread.
749 * Return TRUE if something was done.
751 void WIN_DestroyThreadWindows( HWND hwnd )
756 if (!(list = WIN_ListChildren( hwnd ))) return;
757 for (i = 0; list[i]; i++)
759 if (WIN_IsCurrentThread( list[i] ))
760 DestroyWindow( list[i] );
762 WIN_DestroyThreadWindows( list[i] );
764 HeapFree( GetProcessHeap(), 0, list );
767 /***********************************************************************
768 * WIN_CreateDesktopWindow
770 * Create the desktop window.
772 BOOL WIN_CreateDesktopWindow(void)
774 struct tagCLASS *class;
783 TRACE("Creating desktop window\n");
785 if (!WINPOS_CreateInternalPosAtom() ||
786 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
787 &wndExtra, &winproc, &clsStyle, &dce )))
790 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM),
791 sizeof(WND) + wndExtra - sizeof(pWndDesktop->wExtra) );
792 if (!pWndDesktop) return FALSE;
793 hwndDesktop = pWndDesktop->hwndSelf;
795 pWndDesktop->tid = 0; /* nobody owns the desktop */
796 pWndDesktop->parent = 0;
797 pWndDesktop->owner = 0;
798 pWndDesktop->class = class;
799 pWndDesktop->hInstance = 0;
800 pWndDesktop->text = NULL;
801 pWndDesktop->hmemTaskQ = 0;
802 pWndDesktop->hrgnUpdate = 0;
803 pWndDesktop->hwndLastActive = hwndDesktop;
804 pWndDesktop->dwStyle = 0;
805 pWndDesktop->dwExStyle = 0;
806 pWndDesktop->clsStyle = clsStyle;
807 pWndDesktop->dce = NULL;
808 pWndDesktop->pVScroll = NULL;
809 pWndDesktop->pHScroll = NULL;
810 pWndDesktop->wIDmenu = 0;
811 pWndDesktop->helpContext = 0;
812 pWndDesktop->flags = 0;
813 pWndDesktop->hSysMenu = 0;
814 pWndDesktop->userdata = 0;
815 pWndDesktop->winproc = winproc;
816 pWndDesktop->cbWndExtra = wndExtra;
818 cs.lpCreateParams = NULL;
824 cs.cx = GetSystemMetrics( SM_CXSCREEN );
825 cs.cy = GetSystemMetrics( SM_CYSCREEN );
826 cs.style = pWndDesktop->dwStyle;
827 cs.dwExStyle = pWndDesktop->dwExStyle;
829 cs.lpszClass = DESKTOP_CLASS_ATOM;
831 SetRect( &rect, 0, 0, cs.cx, cs.cy );
832 WIN_SetRectangles( hwndDesktop, &rect, &rect );
833 WIN_SetStyle( hwndDesktop, WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS );
835 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE )) return FALSE;
837 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
838 WIN_ReleaseWndPtr( pWndDesktop );
843 /***********************************************************************
846 * Fix the coordinates - Helper for WIN_CreateWindowEx.
847 * returns default show mode in sw.
848 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
850 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
852 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
853 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
855 if (cs->style & (WS_CHILD | WS_POPUP))
857 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
858 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
860 else /* overlapped window */
864 GetStartupInfoA( &info );
866 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
868 /* Never believe Microsoft's documentation... CreateWindowEx doc says
869 * that if an overlapped window is created with WS_VISIBLE style bit
870 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
871 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
874 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
875 * 2) it does not ignore the y parameter as the docs claim; instead, it
876 * uses it as second parameter to ShowWindow() unless y is either
877 * CW_USEDEFAULT or CW_USEDEFAULT16.
879 * The fact that we didn't do 2) caused bogus windows pop up when wine
880 * was running apps that were using this obscure feature. Example -
881 * calc.exe that comes with Win98 (only Win98, it's different from
882 * the one that comes with Win95 and NT)
884 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
885 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
886 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
889 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
891 if (info.dwFlags & STARTF_USESIZE)
893 cs->cx = info.dwXSize;
894 cs->cy = info.dwYSize;
896 else /* if no other hint from the app, pick 3/4 of the screen real estate */
899 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
900 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
901 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
908 /***********************************************************************
911 static void dump_window_styles( DWORD style, DWORD exstyle )
914 if(style & WS_POPUP) DPRINTF(" WS_POPUP");
915 if(style & WS_CHILD) DPRINTF(" WS_CHILD");
916 if(style & WS_MINIMIZE) DPRINTF(" WS_MINIMIZE");
917 if(style & WS_VISIBLE) DPRINTF(" WS_VISIBLE");
918 if(style & WS_DISABLED) DPRINTF(" WS_DISABLED");
919 if(style & WS_CLIPSIBLINGS) DPRINTF(" WS_CLIPSIBLINGS");
920 if(style & WS_CLIPCHILDREN) DPRINTF(" WS_CLIPCHILDREN");
921 if(style & WS_MAXIMIZE) DPRINTF(" WS_MAXIMIZE");
922 if((style & WS_CAPTION) == WS_CAPTION) DPRINTF(" WS_CAPTION");
925 if(style & WS_BORDER) DPRINTF(" WS_BORDER");
926 if(style & WS_DLGFRAME) DPRINTF(" WS_DLGFRAME");
928 if(style & WS_VSCROLL) DPRINTF(" WS_VSCROLL");
929 if(style & WS_HSCROLL) DPRINTF(" WS_HSCROLL");
930 if(style & WS_SYSMENU) DPRINTF(" WS_SYSMENU");
931 if(style & WS_THICKFRAME) DPRINTF(" WS_THICKFRAME");
932 if(style & WS_GROUP) DPRINTF(" WS_GROUP");
933 if(style & WS_TABSTOP) DPRINTF(" WS_TABSTOP");
934 if(style & WS_MINIMIZEBOX) DPRINTF(" WS_MINIMIZEBOX");
935 if(style & WS_MAXIMIZEBOX) DPRINTF(" WS_MAXIMIZEBOX");
937 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
938 #define DUMPED_STYLES \
958 if(style & ~DUMPED_STYLES) DPRINTF(" %08lx", style & ~DUMPED_STYLES);
963 if(exstyle & WS_EX_DLGMODALFRAME) DPRINTF(" WS_EX_DLGMODALFRAME");
964 if(exstyle & WS_EX_DRAGDETECT) DPRINTF(" WS_EX_DRAGDETECT");
965 if(exstyle & WS_EX_NOPARENTNOTIFY) DPRINTF(" WS_EX_NOPARENTNOTIFY");
966 if(exstyle & WS_EX_TOPMOST) DPRINTF(" WS_EX_TOPMOST");
967 if(exstyle & WS_EX_ACCEPTFILES) DPRINTF(" WS_EX_ACCEPTFILES");
968 if(exstyle & WS_EX_TRANSPARENT) DPRINTF(" WS_EX_TRANSPARENT");
969 if(exstyle & WS_EX_MDICHILD) DPRINTF(" WS_EX_MDICHILD");
970 if(exstyle & WS_EX_TOOLWINDOW) DPRINTF(" WS_EX_TOOLWINDOW");
971 if(exstyle & WS_EX_WINDOWEDGE) DPRINTF(" WS_EX_WINDOWEDGE");
972 if(exstyle & WS_EX_CLIENTEDGE) DPRINTF(" WS_EX_CLIENTEDGE");
973 if(exstyle & WS_EX_CONTEXTHELP) DPRINTF(" WS_EX_CONTEXTHELP");
974 if(exstyle & WS_EX_RIGHT) DPRINTF(" WS_EX_RIGHT");
975 if(exstyle & WS_EX_RTLREADING) DPRINTF(" WS_EX_RTLREADING");
976 if(exstyle & WS_EX_LEFTSCROLLBAR) DPRINTF(" WS_EX_LEFTSCROLLBAR");
977 if(exstyle & WS_EX_CONTROLPARENT) DPRINTF(" WS_EX_CONTROLPARENT");
978 if(exstyle & WS_EX_STATICEDGE) DPRINTF(" WS_EX_STATICEDGE");
979 if(exstyle & WS_EX_APPWINDOW) DPRINTF(" WS_EX_APPWINDOW");
980 if(exstyle & WS_EX_LAYERED) DPRINTF(" WS_EX_LAYERED");
982 #define DUMPED_EX_STYLES \
983 (WS_EX_DLGMODALFRAME | \
985 WS_EX_NOPARENTNOTIFY | \
987 WS_EX_ACCEPTFILES | \
988 WS_EX_TRANSPARENT | \
993 WS_EX_CONTEXTHELP | \
996 WS_EX_LEFTSCROLLBAR | \
997 WS_EX_CONTROLPARENT | \
1002 if(exstyle & ~DUMPED_EX_STYLES) DPRINTF(" %08lx", exstyle & ~DUMPED_EX_STYLES);
1004 #undef DUMPED_EX_STYLES
1008 /***********************************************************************
1009 * WIN_CreateWindowEx
1011 * Implementation of CreateWindowEx().
1013 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
1014 WINDOWPROCTYPE type )
1017 struct tagCLASS *classPtr;
1019 HWND hwnd, hwndLinkAfter, parent, owner;
1024 BOOL unicode = (type == WIN_PROC_32W);
1026 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%04x menu=%04x inst=%08x params=%p\n",
1027 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
1028 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
1029 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
1030 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
1032 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
1034 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
1035 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
1037 /* Find the parent window */
1039 parent = GetDesktopWindow();
1043 /* Make sure parent is valid */
1044 if (!IsWindow( cs->hwndParent ))
1046 WARN("Bad parent %04x\n", cs->hwndParent );
1049 if (cs->style & WS_CHILD) parent = WIN_GetFullHandle(cs->hwndParent);
1050 else owner = GetAncestor( cs->hwndParent, GA_ROOT );
1052 else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP))
1054 WARN("No parent for child window\n" );
1055 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1058 /* Find the window class */
1059 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
1060 &wndExtra, &winproc, &clsStyle, &dce )))
1062 WARN("Bad class '%s'\n", cs->lpszClass );
1066 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1068 /* Correct the window style - stage 1
1070 * These are patches that appear to affect both the style loaded into the
1071 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
1073 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1074 * why does the user get to set it?
1077 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1078 * tested for WS_POPUP
1080 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1081 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1082 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1083 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1085 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1087 /* Create the window structure */
1089 if (!(wndPtr = create_window_handle( parent, owner, classAtom,
1090 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
1092 TRACE("out of memory\n" );
1095 hwnd = wndPtr->hwndSelf;
1097 /* Fill the window structure */
1099 wndPtr->tid = GetCurrentThreadId();
1100 wndPtr->owner = owner;
1101 wndPtr->parent = parent;
1102 wndPtr->class = classPtr;
1103 wndPtr->winproc = winproc;
1104 wndPtr->hInstance = cs->hInstance;
1105 wndPtr->text = NULL;
1106 wndPtr->hmemTaskQ = InitThreadInput16( 0, 0 );
1107 wndPtr->hrgnUpdate = 0;
1108 wndPtr->hrgnWnd = 0;
1109 wndPtr->hwndLastActive = hwnd;
1110 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1111 wndPtr->dwExStyle = cs->dwExStyle;
1112 wndPtr->clsStyle = clsStyle;
1113 wndPtr->wIDmenu = 0;
1114 wndPtr->helpContext = 0;
1115 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1116 wndPtr->pVScroll = NULL;
1117 wndPtr->pHScroll = NULL;
1118 wndPtr->userdata = 0;
1119 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
1120 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1121 wndPtr->cbWndExtra = wndExtra;
1123 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
1125 /* Call the WH_CBT hook */
1127 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
1128 ? HWND_BOTTOM : HWND_TOP;
1130 if (HOOK_IsHooked( WH_CBT ))
1132 CBT_CREATEWNDA cbtc;
1136 cbtc.hwndInsertAfter = hwndLinkAfter;
1137 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND,
1138 (WPARAM)hwnd, (LPARAM)&cbtc)
1139 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND,
1140 (WPARAM)hwnd, (LPARAM)&cbtc);
1143 TRACE("CBT-hook returned 0\n");
1144 free_window_handle( hwnd );
1145 CLASS_RemoveWindow( classPtr );
1146 WIN_ReleaseWndPtr(wndPtr);
1151 /* Correct the window style - stage 2 */
1153 if (!(cs->style & WS_CHILD))
1155 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1156 if (!(cs->style & WS_POPUP))
1158 wndPtr->dwStyle |= WS_CAPTION;
1159 wndPtr->flags |= WIN_NEED_SIZE;
1162 SERVER_START_REQ( set_window_info )
1165 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1166 req->style = wndPtr->dwStyle;
1167 req->ex_style = wndPtr->dwExStyle;
1168 req->instance = (void *)wndPtr->hInstance;
1173 /* Get class or window DC if needed */
1175 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1176 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
1177 else wndPtr->dce = NULL;
1179 /* Set the window menu */
1181 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
1183 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
1186 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1189 if (HIWORD(cs->hInstance))
1190 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1192 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
1194 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
1198 else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
1199 WIN_ReleaseWndPtr( wndPtr );
1201 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
1203 WIN_DestroyWindow( hwnd );
1207 /* Notify the parent window only */
1209 send_parent_notify( hwnd, WM_CREATE );
1210 if (!IsWindow( hwnd )) return 0;
1212 if (cs->style & WS_VISIBLE)
1214 /* in case WS_VISIBLE got set in the meantime */
1215 if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0;
1216 WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
1217 WIN_ReleasePtr( wndPtr );
1218 ShowWindow( hwnd, sw );
1221 /* Call WH_SHELL hook */
1223 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1224 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0 );
1226 TRACE("created window %04x\n", hwnd);
1231 /***********************************************************************
1232 * CreateWindow (USER.41)
1234 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1235 DWORD style, INT16 x, INT16 y, INT16 width,
1236 INT16 height, HWND16 parent, HMENU16 menu,
1237 HINSTANCE16 instance, LPVOID data )
1239 return CreateWindowEx16( 0, className, windowName, style,
1240 x, y, width, height, parent, menu, instance, data );
1244 /***********************************************************************
1245 * CreateWindowEx (USER.452)
1247 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1248 LPCSTR windowName, DWORD style, INT16 x,
1249 INT16 y, INT16 width, INT16 height,
1250 HWND16 parent, HMENU16 menu,
1251 HINSTANCE16 instance, LPVOID data )
1257 /* Find the class atom */
1259 if (HIWORD(className))
1261 if (!(classAtom = GlobalFindAtomA( className )))
1263 ERR( "bad class name %s\n", debugres_a(className) );
1269 classAtom = LOWORD(className);
1270 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1272 ERR( "bad atom %x\n", classAtom);
1278 /* Fix the coordinates */
1280 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1281 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1282 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1283 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1285 /* Create the window */
1287 cs.lpCreateParams = data;
1288 cs.hInstance = (HINSTANCE)instance;
1289 cs.hMenu = (HMENU)menu;
1290 cs.hwndParent = WIN_Handle32( parent );
1292 cs.lpszName = windowName;
1293 cs.lpszClass = className;
1294 cs.dwExStyle = exStyle;
1296 return WIN_Handle16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1300 /***********************************************************************
1301 * CreateWindowExA (USER32.@)
1303 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1304 LPCSTR windowName, DWORD style, INT x,
1305 INT y, INT width, INT height,
1306 HWND parent, HMENU menu,
1307 HINSTANCE instance, LPVOID data )
1314 instance=GetModuleHandleA(NULL);
1316 if(exStyle & WS_EX_MDICHILD)
1317 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1319 /* Find the class atom */
1321 if (HIWORD(className))
1323 if (!(classAtom = GlobalFindAtomA( className )))
1325 ERR( "bad class name %s\n", debugres_a(className) );
1331 classAtom = LOWORD(className);
1332 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1334 ERR( "bad atom %x\n", classAtom);
1340 /* Create the window */
1342 cs.lpCreateParams = data;
1343 cs.hInstance = instance;
1345 cs.hwndParent = parent;
1351 cs.lpszName = windowName;
1352 cs.lpszClass = className;
1353 cs.dwExStyle = exStyle;
1355 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1359 /***********************************************************************
1360 * CreateWindowExW (USER32.@)
1362 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1363 LPCWSTR windowName, DWORD style, INT x,
1364 INT y, INT width, INT height,
1365 HWND parent, HMENU menu,
1366 HINSTANCE instance, LPVOID data )
1373 instance=GetModuleHandleA(NULL);
1375 if(exStyle & WS_EX_MDICHILD)
1376 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1378 /* Find the class atom */
1380 if (HIWORD(className))
1382 if (!(classAtom = GlobalFindAtomW( className )))
1384 ERR( "bad class name %s\n", debugres_w(className) );
1390 classAtom = LOWORD(className);
1391 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1393 ERR( "bad atom %x\n", classAtom);
1399 /* Create the window */
1401 cs.lpCreateParams = data;
1402 cs.hInstance = instance;
1404 cs.hwndParent = parent;
1410 cs.lpszName = windowName;
1411 cs.lpszClass = className;
1412 cs.dwExStyle = exStyle;
1414 /* Note: we rely on the fact that CREATESTRUCTA and */
1415 /* CREATESTRUCTW have the same layout. */
1416 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1420 /***********************************************************************
1421 * WIN_SendDestroyMsg
1423 static void WIN_SendDestroyMsg( HWND hwnd )
1425 if( CARET_GetHwnd() == hwnd) DestroyCaret();
1426 if (USER_Driver.pResetSelectionOwner)
1427 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1430 * Send the WM_DESTROY to the window.
1432 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1435 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1436 * make sure that the window still exists when we come back.
1443 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1445 /* start from the end (FIXME: is this needed?) */
1446 for (i = 0; pWndArray[i]; i++) ;
1450 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1452 HeapFree( GetProcessHeap(), 0, pWndArray );
1455 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1459 /***********************************************************************
1460 * DestroyWindow (USER32.@)
1462 BOOL WINAPI DestroyWindow( HWND hwnd )
1467 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1469 SetLastError( ERROR_ACCESS_DENIED );
1473 TRACE("(%04x)\n", hwnd);
1475 /* Look whether the focus is within the tree of windows we will
1479 if (h == hwnd || IsChild( hwnd, h ))
1481 HWND parent = GetAncestor( hwnd, GA_PARENT );
1482 if (parent == GetDesktopWindow()) parent = 0;
1488 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0L) ) return FALSE;
1490 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1494 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1495 send_parent_notify( hwnd, WM_DESTROY );
1497 else if (!GetWindow( hwnd, GW_OWNER ))
1499 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L );
1500 /* FIXME: clean up palette - see "Internals" p.352 */
1503 if (!IsWindow(hwnd)) return TRUE;
1505 if (USER_Driver.pResetSelectionOwner)
1506 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1508 /* Hide the window */
1510 ShowWindow( hwnd, SW_HIDE );
1511 if (!IsWindow(hwnd)) return TRUE;
1513 /* Recursively destroy owned windows */
1522 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1525 for (i = 0; list[i]; i++)
1527 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1528 if (WIN_IsCurrentThread( list[i] ))
1530 DestroyWindow( list[i] );
1534 WIN_SetOwner( list[i], 0 );
1536 HeapFree( GetProcessHeap(), 0, list );
1538 if (!got_one) break;
1541 WINPOS_ActivateOtherWindow( hwnd );
1543 if ((owner = GetWindow( hwnd, GW_OWNER )))
1545 WND *ptr = WIN_FindWndPtr( owner );
1548 if (ptr->hwndLastActive == hwnd) ptr->hwndLastActive = owner;
1549 WIN_ReleaseWndPtr( ptr );
1554 /* Send destroy messages */
1556 WIN_SendDestroyMsg( hwnd );
1557 if (!IsWindow( hwnd )) return TRUE;
1559 /* Unlink now so we won't bother with the children later on */
1561 WIN_UnlinkWindow( hwnd );
1563 /* Destroy the window storage */
1565 WIN_DestroyWindow( hwnd );
1570 /***********************************************************************
1571 * CloseWindow (USER32.@)
1573 BOOL WINAPI CloseWindow( HWND hwnd )
1575 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1576 ShowWindow( hwnd, SW_MINIMIZE );
1581 /***********************************************************************
1582 * OpenIcon (USER32.@)
1584 BOOL WINAPI OpenIcon( HWND hwnd )
1586 if (!IsIconic( hwnd )) return FALSE;
1587 ShowWindow( hwnd, SW_SHOWNORMAL );
1592 /***********************************************************************
1595 * Implementation of FindWindow() and FindWindowEx().
1597 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1602 WCHAR *buffer = NULL;
1604 if (!parent) parent = GetDesktopWindow();
1607 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1608 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1611 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1615 child = WIN_GetFullHandle( child );
1616 while (list[i] && list[i] != child) i++;
1617 if (!list[i]) goto done;
1618 i++; /* start from next window */
1625 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1632 if (list) HeapFree( GetProcessHeap(), 0, list );
1633 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1639 /***********************************************************************
1640 * FindWindowA (USER32.@)
1642 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1644 HWND ret = FindWindowExA( 0, 0, className, title );
1645 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1650 /***********************************************************************
1651 * FindWindowExA (USER32.@)
1653 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1654 LPCSTR className, LPCSTR title )
1662 /* If the atom doesn't exist, then no class */
1663 /* with this name exists either. */
1664 if (!(atom = GlobalFindAtomA( className )))
1666 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1671 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1672 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1673 HeapFree( GetProcessHeap(), 0, buffer );
1678 /***********************************************************************
1679 * FindWindowExW (USER32.@)
1681 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1682 LPCWSTR className, LPCWSTR title )
1688 /* If the atom doesn't exist, then no class */
1689 /* with this name exists either. */
1690 if (!(atom = GlobalFindAtomW( className )))
1692 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1696 return WIN_FindWindow( parent, child, atom, title );
1700 /***********************************************************************
1701 * FindWindowW (USER32.@)
1703 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1705 return FindWindowExW( 0, 0, className, title );
1709 /**********************************************************************
1710 * GetDesktopWindow (USER32.@)
1712 HWND WINAPI GetDesktopWindow(void)
1714 if (pWndDesktop) return pWndDesktop->hwndSelf;
1715 ERR( "You need the -desktop option when running with native USER\n" );
1721 /*******************************************************************
1722 * EnableWindow (USER32.@)
1724 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1731 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1732 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1736 TRACE("( %x, %d )\n", hwnd, enable);
1738 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1739 style = wndPtr->dwStyle;
1740 retvalue = ((style & WS_DISABLED) != 0);
1741 WIN_ReleasePtr( wndPtr );
1743 if (enable && retvalue)
1745 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1746 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1748 else if (!enable && !retvalue)
1750 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1752 WIN_SetStyle( hwnd, style | WS_DISABLED );
1754 if (hwnd == GetFocus())
1755 SetFocus( 0 ); /* A disabled window can't have the focus */
1757 if (hwnd == GetCapture())
1758 ReleaseCapture(); /* A disabled window can't capture the mouse */
1760 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1766 /***********************************************************************
1767 * IsWindowEnabled (USER32.@)
1769 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1771 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1775 /***********************************************************************
1776 * IsWindowUnicode (USER32.@)
1778 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1783 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1784 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1785 WIN_ReleaseWndPtr(wndPtr);
1790 /**********************************************************************
1791 * GetWindowWord (USER32.@)
1793 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1798 WND *wndPtr = WIN_GetPtr( hwnd );
1801 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1804 if (wndPtr == WND_OTHER_PROCESS)
1806 if (IsWindow( hwnd ))
1807 FIXME( "(%d) not supported yet on other process window %x\n", offset, hwnd );
1808 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1811 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1813 WARN("Invalid offset %d\n", offset );
1814 SetLastError( ERROR_INVALID_INDEX );
1816 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1817 WIN_ReleasePtr( wndPtr );
1823 case GWL_HWNDPARENT:
1824 return GetWindowLongW( hwnd, offset );
1828 LONG ret = GetWindowLongW( hwnd, offset );
1830 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1834 WARN("Invalid offset %d\n", offset );
1840 /**********************************************************************
1841 * SetWindowWord (USER32.@)
1843 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1852 case GWL_HWNDPARENT:
1853 return SetWindowLongW( hwnd, offset, (UINT)newval );
1857 WARN("Invalid offset %d\n", offset );
1858 SetLastError( ERROR_INVALID_INDEX );
1863 wndPtr = WIN_GetPtr( hwnd );
1864 if (wndPtr == WND_OTHER_PROCESS)
1867 FIXME( "set %d <- %x not supported yet on other process window %x\n",
1868 offset, newval, hwnd );
1873 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1877 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1879 WARN("Invalid offset %d\n", offset );
1880 WIN_ReleasePtr(wndPtr);
1881 SetLastError( ERROR_INVALID_INDEX );
1884 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1887 WIN_ReleasePtr(wndPtr);
1892 /**********************************************************************
1895 * Helper function for GetWindowLong().
1897 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1902 if (offset == GWL_HWNDPARENT) return (LONG)GetParent( hwnd );
1904 if (!(wndPtr = WIN_GetPtr( hwnd )))
1906 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1910 if (wndPtr == WND_OTHER_PROCESS)
1915 FIXME( "(%d) not supported on other process window %x\n", offset, hwnd );
1916 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1919 if (offset == GWL_WNDPROC)
1921 SetLastError( ERROR_ACCESS_DENIED );
1924 SERVER_START_REQ( set_window_info )
1927 req->flags = 0; /* don't set anything, just retrieve */
1928 if (!SERVER_CALL_ERR())
1932 case GWL_STYLE: retvalue = req->style; break;
1933 case GWL_EXSTYLE: retvalue = req->ex_style; break;
1934 case GWL_ID: retvalue = req->id; break;
1935 case GWL_HINSTANCE: retvalue = (ULONG_PTR)req->instance; break;
1936 case GWL_USERDATA: retvalue = (ULONG_PTR)req->user_data; break;
1938 SetLastError( ERROR_INVALID_INDEX );
1947 /* now we have a valid wndPtr */
1951 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
1953 WARN("Invalid offset %d\n", offset );
1954 WIN_ReleasePtr( wndPtr );
1955 SetLastError( ERROR_INVALID_INDEX );
1958 /* Special case for dialog window procedure */
1959 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1960 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1962 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1963 WIN_ReleasePtr( wndPtr );
1969 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
1970 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1971 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1972 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
1973 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
1974 case GWL_HINSTANCE: retvalue = wndPtr->hInstance; break;
1976 WARN("Unknown offset %d\n", offset );
1977 SetLastError( ERROR_INVALID_INDEX );
1980 WIN_ReleasePtr(wndPtr);
1985 /**********************************************************************
1988 * Helper function for SetWindowLong().
1990 * 0 is the failure code. However, in the case of failure SetLastError
1991 * must be set to distinguish between a 0 return value and a failure.
1993 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1994 WINDOWPROCTYPE type )
1999 TRACE( "%x %d %lx %x\n", hwnd, offset, newval, type );
2001 if (!WIN_IsCurrentProcess( hwnd ))
2003 if (offset == GWL_WNDPROC)
2005 SetLastError( ERROR_ACCESS_DENIED );
2008 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
2011 wndPtr = WIN_GetPtr( hwnd );
2015 LONG *ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2016 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
2018 WARN("Invalid offset %d\n", offset );
2019 WIN_ReleasePtr( wndPtr );
2020 SetLastError( ERROR_INVALID_INDEX );
2023 /* Special case for dialog window procedure */
2024 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2026 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2027 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2028 type, WIN_PROC_WINDOW );
2029 WIN_ReleasePtr( wndPtr );
2034 WIN_ReleasePtr( wndPtr );
2041 /* first some special cases */
2046 style.styleOld = wndPtr->dwStyle;
2047 style.styleNew = newval;
2048 WIN_ReleasePtr( wndPtr );
2049 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
2050 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
2051 newval = style.styleNew;
2053 case GWL_HWNDPARENT:
2054 WIN_ReleasePtr( wndPtr );
2055 return (LONG)SetParent( hwnd, (HWND)newval );
2057 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2058 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2059 type, WIN_PROC_WINDOW );
2060 WIN_ReleasePtr( wndPtr );
2067 WIN_ReleasePtr( wndPtr );
2068 WARN("Invalid offset %d\n", offset );
2069 SetLastError( ERROR_INVALID_INDEX );
2073 SERVER_START_REQ( set_window_info )
2079 req->flags = SET_WIN_STYLE;
2080 req->style = newval;
2083 req->flags = SET_WIN_EXSTYLE;
2084 req->ex_style = newval;
2087 req->flags = SET_WIN_ID;
2091 req->flags = SET_WIN_INSTANCE;
2092 req->instance = (void *)newval;
2095 req->flags = SET_WIN_USERDATA;
2096 req->user_data = (void *)newval;
2099 if ((ok = !SERVER_CALL_ERR()))
2104 wndPtr->dwStyle = newval;
2105 retval = req->old_style;
2108 wndPtr->dwExStyle = newval;
2109 retval = req->old_ex_style;
2112 wndPtr->wIDmenu = newval;
2113 retval = req->old_id;
2116 wndPtr->hInstance = newval;
2117 retval = (HINSTANCE)req->old_instance;
2120 wndPtr->userdata = newval;
2121 retval = (ULONG_PTR)req->old_user_data;
2127 WIN_ReleasePtr( wndPtr );
2131 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2132 USER_Driver.pSetWindowStyle( hwnd, retval );
2134 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2135 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2142 /**********************************************************************
2143 * GetWindowLong (USER.135)
2145 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2147 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2151 /**********************************************************************
2152 * GetWindowLongA (USER32.@)
2154 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2156 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2160 /**********************************************************************
2161 * GetWindowLongW (USER32.@)
2163 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2165 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2169 /**********************************************************************
2170 * SetWindowLong (USER.136)
2172 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2174 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2178 /**********************************************************************
2179 * SetWindowLongA (USER32.@)
2181 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2183 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2187 /**********************************************************************
2188 * SetWindowLongW (USER32.@) Set window attribute
2190 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2191 * value in a window's extra memory.
2193 * The _hwnd_ parameter specifies the window. is the handle to a
2194 * window that has extra memory. The _newval_ parameter contains the
2195 * new attribute or extra memory value. If positive, the _offset_
2196 * parameter is the byte-addressed location in the window's extra
2197 * memory to set. If negative, _offset_ specifies the window
2198 * attribute to set, and should be one of the following values:
2200 * GWL_EXSTYLE The window's extended window style
2202 * GWL_STYLE The window's window style.
2204 * GWL_WNDPROC Pointer to the window's window procedure.
2206 * GWL_HINSTANCE The window's pplication instance handle.
2208 * GWL_ID The window's identifier.
2210 * GWL_USERDATA The window's user-specified data.
2212 * If the window is a dialog box, the _offset_ parameter can be one of
2213 * the following values:
2215 * DWL_DLGPROC The address of the window's dialog box procedure.
2217 * DWL_MSGRESULT The return value of a message
2218 * that the dialog box procedure processed.
2220 * DWL_USER Application specific information.
2224 * If successful, returns the previous value located at _offset_. Otherwise,
2229 * Extra memory for a window class is specified by a nonzero cbWndExtra
2230 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2231 * time of class creation.
2233 * Using GWL_WNDPROC to set a new window procedure effectively creates
2234 * a window subclass. Use CallWindowProc() in the new windows procedure
2235 * to pass messages to the superclass's window procedure.
2237 * The user data is reserved for use by the application which created
2240 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2241 * instead, call the EnableWindow() function to change the window's
2244 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2245 * SetParent() instead.
2248 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2249 * it sends WM_STYLECHANGING before changing the settings
2250 * and WM_STYLECHANGED afterwards.
2251 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2253 LONG WINAPI SetWindowLongW(
2254 HWND hwnd, /* [in] window to alter */
2255 INT offset, /* [in] offset, in bytes, of location to alter */
2256 LONG newval /* [in] new value of location */
2258 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2262 /*******************************************************************
2263 * GetWindowTextA (USER32.@)
2265 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2269 if (WIN_IsCurrentProcess( hwnd ))
2270 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2272 /* when window belongs to other process, don't send a message */
2273 if (nMaxCount <= 0) return 0;
2274 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2275 get_server_window_text( hwnd, buffer, nMaxCount );
2276 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2277 lpString[nMaxCount-1] = 0;
2278 HeapFree( GetProcessHeap(), 0, buffer );
2279 return strlen(lpString);
2283 /*******************************************************************
2284 * InternalGetWindowText (USER32.@)
2286 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2290 if (nMaxCount <= 0) return 0;
2291 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2292 if (win != WND_OTHER_PROCESS)
2294 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2295 else lpString[0] = 0;
2296 WIN_ReleasePtr( win );
2300 get_server_window_text( hwnd, lpString, nMaxCount );
2302 return strlenW(lpString);
2306 /*******************************************************************
2307 * GetWindowTextW (USER32.@)
2309 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2311 if (WIN_IsCurrentProcess( hwnd ))
2312 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2314 /* when window belongs to other process, don't send a message */
2315 if (nMaxCount <= 0) return 0;
2316 get_server_window_text( hwnd, lpString, nMaxCount );
2317 return strlenW(lpString);
2321 /*******************************************************************
2322 * SetWindowText (USER32.@)
2323 * SetWindowTextA (USER32.@)
2325 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2327 if (!WIN_IsCurrentProcess( hwnd ))
2329 FIXME( "cannot set text %s of other process window %x\n", debugstr_a(lpString), hwnd );
2330 SetLastError( ERROR_ACCESS_DENIED );
2333 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2337 /*******************************************************************
2338 * SetWindowTextW (USER32.@)
2340 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2342 if (!WIN_IsCurrentProcess( hwnd ))
2344 FIXME( "cannot set text %s of other process window %x\n", debugstr_w(lpString), hwnd );
2345 SetLastError( ERROR_ACCESS_DENIED );
2348 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2352 /*******************************************************************
2353 * GetWindowTextLengthA (USER32.@)
2355 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2357 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2360 /*******************************************************************
2361 * GetWindowTextLengthW (USER32.@)
2363 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2365 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2369 /*******************************************************************
2370 * IsWindow (USER32.@)
2372 BOOL WINAPI IsWindow( HWND hwnd )
2377 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2379 if (ptr != WND_OTHER_PROCESS)
2381 WIN_ReleasePtr( ptr );
2385 /* check other processes */
2386 SERVER_START_REQ( get_window_info )
2389 ret = !SERVER_CALL_ERR();
2396 /***********************************************************************
2397 * GetWindowThreadProcessId (USER32.@)
2399 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2404 if (!(ptr = WIN_GetPtr( hwnd )))
2406 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2410 if (ptr != WND_OTHER_PROCESS)
2412 /* got a valid window */
2414 if (process) *process = GetCurrentProcessId();
2415 WIN_ReleasePtr( ptr );
2419 /* check other processes */
2420 SERVER_START_REQ( get_window_info )
2423 if (!SERVER_CALL_ERR())
2425 tid = (DWORD)req->tid;
2426 if (process) *process = (DWORD)req->pid;
2434 /*****************************************************************
2435 * GetParent (USER32.@)
2437 HWND WINAPI GetParent( HWND hwnd )
2442 if (!(wndPtr = WIN_GetPtr( hwnd )))
2444 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2447 if (wndPtr == WND_OTHER_PROCESS)
2449 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2450 if (style & (WS_POPUP | WS_CHILD))
2452 SERVER_START_REQ( get_window_tree )
2455 if (!SERVER_CALL_ERR())
2457 if (style & WS_CHILD) retvalue = req->parent;
2458 else retvalue = req->owner;
2466 if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2467 else if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2468 WIN_ReleasePtr( wndPtr );
2474 /*****************************************************************
2475 * GetAncestor (USER32.@)
2477 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2485 if (!(win = WIN_GetPtr( hwnd )))
2487 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2490 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2492 WIN_ReleasePtr( win );
2493 if (type == GA_PARENT) return ret;
2494 if (!ret || ret == GetDesktopWindow())
2496 ret = hwnd; /* if ret is the desktop, hwnd is the root ancestor */
2499 hwnd = ret; /* restart with parent as hwnd */
2502 size = (type == GA_PARENT) ? sizeof(user_handle_t) : REQUEST_MAX_VAR_SIZE;
2504 SERVER_START_VAR_REQ( get_window_parents, size )
2509 user_handle_t *data = server_data_ptr(req);
2510 int count = server_data_size(req) / sizeof(*data);
2520 if (count > 1) ret = data[count - 2]; /* get the one before the desktop */
2521 else ret = WIN_GetFullHandle( hwnd );
2530 if (ret && type == GA_ROOTOWNER)
2534 HWND owner = GetWindow( ret, GW_OWNER );
2543 /*****************************************************************
2544 * SetParent (USER32.@)
2546 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2549 HWND retvalue, full_handle;
2552 if (!parent) parent = GetDesktopWindow();
2553 else parent = WIN_GetFullHandle( parent );
2555 if (!IsWindow( parent ))
2557 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2561 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2562 return SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2566 if (USER_Driver.pSetParent)
2567 return USER_Driver.pSetParent( hwnd, parent );
2569 /* Windows hides the window first, then shows it again
2570 * including the WM_SHOWWINDOW messages and all */
2571 was_visible = ShowWindow( hwnd, SW_HIDE );
2573 if (!IsWindow( parent )) return 0;
2574 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2576 retvalue = wndPtr->parent; /* old parent */
2577 if (parent != retvalue)
2579 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2581 if (parent != GetDesktopWindow()) /* a child window */
2583 if (!(wndPtr->dwStyle & WS_CHILD))
2585 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2586 if (menu) DestroyMenu( menu );
2590 WIN_ReleasePtr( wndPtr );
2592 /* SetParent additionally needs to make hwnd the topmost window
2593 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2594 WM_WINDOWPOSCHANGED notification messages.
2596 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2597 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2598 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2599 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2604 /*******************************************************************
2605 * IsChild (USER32.@)
2607 BOOL WINAPI IsChild( HWND parent, HWND child )
2609 HWND *list = WIN_ListParents( child );
2613 if (!list) return FALSE;
2614 parent = WIN_GetFullHandle( parent );
2615 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2616 ret = (list[i] != 0);
2617 HeapFree( GetProcessHeap(), 0, list );
2622 /***********************************************************************
2623 * IsWindowVisible (USER32.@)
2625 BOOL WINAPI IsWindowVisible( HWND hwnd )
2631 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2632 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2633 for (i = 0; list[i]; i++)
2634 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2636 HeapFree( GetProcessHeap(), 0, list );
2641 /***********************************************************************
2642 * WIN_IsWindowDrawable
2644 * hwnd is drawable when it is visible, all parents are not
2645 * minimized, and it is itself not minimized unless we are
2646 * trying to draw its default class icon.
2648 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2653 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2655 if (!(style & WS_VISIBLE)) return FALSE;
2656 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2658 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2659 for (i = 0; list[i]; i++)
2660 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2663 HeapFree( GetProcessHeap(), 0, list );
2668 /*******************************************************************
2669 * GetTopWindow (USER32.@)
2671 HWND WINAPI GetTopWindow( HWND hwnd )
2673 if (!hwnd) hwnd = GetDesktopWindow();
2674 return GetWindow( hwnd, GW_CHILD );
2678 /*******************************************************************
2679 * GetWindow (USER32.@)
2681 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2685 if (rel == GW_OWNER) /* this one may be available locally */
2687 WND *wndPtr = WIN_GetPtr( hwnd );
2690 SetLastError( ERROR_INVALID_HANDLE );
2693 if (wndPtr != WND_OTHER_PROCESS)
2695 retval = wndPtr->owner;
2696 WIN_ReleasePtr( wndPtr );
2699 /* else fall through to server call */
2702 SERVER_START_REQ( get_window_tree )
2705 if (!SERVER_CALL_ERR())
2710 retval = req->first_sibling;
2713 retval = req->last_sibling;
2716 retval = req->next_sibling;
2719 retval = req->prev_sibling;
2722 retval = req->owner;
2725 retval = req->first_child;
2735 /***********************************************************************
2736 * WIN_InternalShowOwnedPopups
2738 * Internal version of ShowOwnedPopups; Wine functions should use this
2739 * to avoid interfering with application calls to ShowOwnedPopups
2740 * and to make sure the application can't prevent showing/hiding.
2742 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2746 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2750 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2752 if (!win_array) return TRUE;
2755 * Show windows Lowest first, Highest last to preserve Z-Order
2757 while (win_array[count]) count++;
2758 while (--count >= 0)
2760 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2761 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2763 if (pWnd->dwStyle & WS_POPUP)
2767 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2768 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2771 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2773 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2774 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2779 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2780 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2781 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2784 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2786 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2787 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2788 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2792 WIN_ReleaseWndPtr( pWnd );
2794 HeapFree( GetProcessHeap(), 0, win_array );
2799 /*******************************************************************
2800 * ShowOwnedPopups (USER32.@)
2802 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2806 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2808 if (!win_array) return TRUE;
2810 while (win_array[count]) count++;
2811 while (--count >= 0)
2813 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2814 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2816 if (pWnd->dwStyle & WS_POPUP)
2820 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2822 /* In Windows, ShowOwnedPopups(TRUE) generates
2823 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2824 * regardless of the state of the owner
2826 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2827 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2832 if (IsWindowVisible(pWnd->hwndSelf))
2834 /* In Windows, ShowOwnedPopups(FALSE) generates
2835 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2836 * regardless of the state of the owner
2838 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2839 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2843 WIN_ReleaseWndPtr( pWnd );
2845 HeapFree( GetProcessHeap(), 0, win_array );
2850 /*******************************************************************
2851 * GetLastActivePopup (USER32.@)
2853 HWND WINAPI GetLastActivePopup( HWND hwnd )
2856 WND *wndPtr =WIN_FindWndPtr(hwnd);
2857 if (!wndPtr) return hwnd;
2858 retval = wndPtr->hwndLastActive;
2859 if (!IsWindow( retval )) retval = wndPtr->hwndSelf;
2860 WIN_ReleaseWndPtr(wndPtr);
2865 /*******************************************************************
2868 * Build an array of all parents of a given window, starting with
2869 * the immediate parent. The array must be freed with HeapFree.
2870 * Returns NULL if window is a top-level window.
2872 HWND *WIN_ListParents( HWND hwnd )
2875 HWND current, *list;
2876 int pos = 0, size = 16, count = 0;
2878 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2883 if (!(win = WIN_GetPtr( current ))) goto empty;
2884 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2885 list[pos] = win->parent;
2886 WIN_ReleasePtr( win );
2887 if (!(current = list[pos]))
2889 if (!pos) goto empty;
2892 if (++pos == size - 1)
2894 /* need to grow the list */
2895 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2896 if (!new_list) goto empty;
2902 /* at least one parent belongs to another process, have to query the server */
2903 SERVER_START_VAR_REQ( get_window_parents, REQUEST_MAX_VAR_SIZE )
2908 user_handle_t *data = server_data_ptr(req);
2909 count = server_data_size(req) / sizeof(*data);
2912 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0,
2913 list, (count + 1) * sizeof(HWND) );
2917 for (pos = 0; pos < count; pos++) list[pos] = data[pos];
2925 if (count) return list;
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 FALSE;
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 * EnumTaskWindows16 (USER.225)
2978 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2981 TDB *tdb = TASK_GetPtr( hTask );
2982 if (!tdb) return FALSE;
2983 return EnumThreadWindows( (DWORD)tdb->teb->tid, (WNDENUMPROC)func, lParam );
2987 /**********************************************************************
2988 * EnumThreadWindows (USER32.@)
2990 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2995 if (!(list = list_window_children( GetDesktopWindow(), 0, GetCurrentThreadId() )))
2998 /* Now call the callback function for every window */
3000 iWndsLocks = WIN_SuspendWndsLock();
3001 for (i = 0; list[i]; i++)
3002 if (!func( list[i], lParam )) break;
3003 WIN_RestoreWndsLock(iWndsLocks);
3004 HeapFree( GetProcessHeap(), 0, list );
3009 /**********************************************************************
3010 * WIN_EnumChildWindows
3012 * Helper function for EnumChildWindows().
3014 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
3019 for ( ; *list; list++)
3021 /* Make sure that the window still exists */
3022 if (!IsWindow( *list )) continue;
3023 /* skip owned windows */
3024 if (GetWindow( *list, GW_OWNER )) continue;
3025 /* Build children list first */
3026 childList = WIN_ListChildren( *list );
3028 ret = func( *list, lParam );
3032 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
3033 HeapFree( GetProcessHeap(), 0, childList );
3035 if (!ret) return FALSE;
3041 /**********************************************************************
3042 * EnumChildWindows (USER32.@)
3044 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
3049 if (!(list = WIN_ListChildren( parent ))) return FALSE;
3050 iWndsLocks = WIN_SuspendWndsLock();
3051 WIN_EnumChildWindows( list, func, lParam );
3052 WIN_RestoreWndsLock(iWndsLocks);
3053 HeapFree( GetProcessHeap(), 0, list );
3058 /*******************************************************************
3059 * AnyPopup (USER.52)
3061 BOOL16 WINAPI AnyPopup16(void)
3067 /*******************************************************************
3068 * AnyPopup (USER32.@)
3070 BOOL WINAPI AnyPopup(void)
3074 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3076 if (!list) return FALSE;
3077 for (i = 0; list[i]; i++)
3079 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3081 retvalue = (list[i] != 0);
3082 HeapFree( GetProcessHeap(), 0, list );
3087 /*******************************************************************
3088 * FlashWindow (USER32.@)
3090 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3092 WND *wndPtr = WIN_FindWndPtr(hWnd);
3094 TRACE("%04x\n", hWnd);
3096 if (!wndPtr) return FALSE;
3097 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3099 if (wndPtr->dwStyle & WS_MINIMIZE)
3101 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3103 HDC hDC = GetDC(hWnd);
3105 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
3106 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3108 ReleaseDC( hWnd, hDC );
3109 wndPtr->flags |= WIN_NCACTIVATED;
3113 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3114 wndPtr->flags &= ~WIN_NCACTIVATED;
3116 WIN_ReleaseWndPtr(wndPtr);
3122 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3123 else wparam = (hWnd == GetActiveWindow());
3125 WIN_ReleaseWndPtr(wndPtr);
3126 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3132 /*******************************************************************
3133 * GetWindowContextHelpId (USER32.@)
3135 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3138 WND *wnd = WIN_FindWndPtr( hwnd );
3140 retval = wnd->helpContext;
3141 WIN_ReleaseWndPtr(wnd);
3146 /*******************************************************************
3147 * SetWindowContextHelpId (USER32.@)
3149 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3151 WND *wnd = WIN_FindWndPtr( hwnd );
3152 if (!wnd) return FALSE;
3153 wnd->helpContext = id;
3154 WIN_ReleaseWndPtr(wnd);
3159 /*******************************************************************
3162 * recursively find a child that contains spDragInfo->pt point
3163 * and send WM_QUERYDROPOBJECT
3165 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3167 BOOL16 wParam, bResult = 0;
3169 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3172 if (!ptrDragInfo) return FALSE;
3174 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3176 GetWindowRect(hQueryWnd,&tempRect);
3178 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
3180 if (!IsIconic( hQueryWnd ))
3182 GetClientRect( hQueryWnd, &tempRect );
3183 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
3185 if (PtInRect( &tempRect, pt))
3188 HWND *list = WIN_ListChildren( hQueryWnd );
3194 for (i = 0; list[i]; i++)
3196 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
3198 GetWindowRect( list[i], &tempRect );
3199 if (PtInRect( &tempRect, pt )) break;
3204 if (IsWindowEnabled( list[i] ))
3205 bResult = DRAG_QueryUpdate( list[i], spDragInfo, bNoSend );
3207 HeapFree( GetProcessHeap(), 0, list );
3209 if(bResult) return bResult;
3215 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3217 ptrDragInfo->hScope = hQueryWnd;
3219 if (bNoSend) bResult = (GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) != 0;
3220 else bResult = SendMessage16( hQueryWnd, WM_QUERYDROPOBJECT, (WPARAM16)wParam, spDragInfo );
3222 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3228 /*******************************************************************
3229 * DragDetect (USER32.@)
3231 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3236 rect.left = pt.x - wDragWidth;
3237 rect.right = pt.x + wDragWidth;
3239 rect.top = pt.y - wDragHeight;
3240 rect.bottom = pt.y + wDragHeight;
3246 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3248 if( msg.message == WM_LBUTTONUP )
3253 if( msg.message == WM_MOUSEMOVE )
3256 tmp.x = LOWORD(msg.lParam);
3257 tmp.y = HIWORD(msg.lParam);
3258 if( !PtInRect( &rect, tmp ))
3270 /******************************************************************************
3271 * DragObject (USER.464)
3273 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3274 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3277 LPDRAGINFO16 lpDragInfo;
3279 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3280 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3281 HCURSOR16 hCurrentCursor = 0;
3282 HWND16 hCurrentWnd = 0;
3284 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3285 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3287 if( !lpDragInfo || !spDragInfo ) return 0L;
3289 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
3291 GlobalFree16(hDragInfo);
3297 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3299 GlobalFree16(hDragInfo);
3303 if( hDragCursor == hCursor ) hDragCursor = 0;
3304 else hCursor = hDragCursor;
3306 hOldCursor = SetCursor(hDragCursor);
3309 lpDragInfo->hWnd = hWnd;
3310 lpDragInfo->hScope = 0;
3311 lpDragInfo->wFlags = wObj;
3312 lpDragInfo->hList = szList; /* near pointer! */
3313 lpDragInfo->hOfStruct = hOfStruct;
3321 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
3323 *(lpDragInfo+1) = *lpDragInfo;
3325 lpDragInfo->pt.x = msg.pt.x;
3326 lpDragInfo->pt.y = msg.pt.y;
3328 /* update DRAGINFO struct */
3329 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3331 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3332 hCurrentCursor = hCursor;
3335 hCurrentCursor = hBummer;
3336 lpDragInfo->hScope = 0;
3338 if( hCurrentCursor )
3339 SetCursor(hCurrentCursor);
3341 /* send WM_DRAGLOOP */
3342 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3343 (LPARAM) spDragInfo );
3344 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3345 if( hCurrentWnd != lpDragInfo->hScope )
3348 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3349 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3350 HIWORD(spDragInfo)) );
3351 hCurrentWnd = lpDragInfo->hScope;
3353 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3357 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3359 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3362 ShowCursor( FALSE );
3366 SetCursor( hOldCursor );
3367 if (hDragCursor) DestroyCursor( hDragCursor );
3370 if( hCurrentCursor != hBummer )
3371 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3372 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3375 GlobalFree16(hDragInfo);
3377 return (DWORD)(msg.lParam);
3381 /******************************************************************************
3382 * GetWindowModuleFileNameA (USER32.@)
3384 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3386 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3387 hwnd, lpszFileName, cchFileNameMax);
3391 /******************************************************************************
3392 * GetWindowModuleFileNameW (USER32.@)
3394 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3396 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3397 hwnd, lpszFileName, cchFileNameMax);