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 * Return a pointer to the WND structure if local to the process,
182 * or BAD_WND_PTR is handle is local but not valid.
183 * If ret value is a valid pointer, the user lock is held.
185 WND *WIN_GetWndPtr( HWND hwnd )
188 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
190 if (index >= NB_USER_HANDLES) return BAD_WND_PTR;
193 if ((ptr = user_handles[index]))
195 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
204 /***********************************************************************
205 * WIN_IsCurrentProcess
207 * Check whether a given window belongs to the current process.
209 BOOL WIN_IsCurrentProcess( HWND hwnd )
213 if (!(ptr = WIN_GetWndPtr( hwnd )) || ptr == BAD_WND_PTR) return FALSE;
219 /***********************************************************************
220 * WIN_IsCurrentThread
222 * Check whether a given window belongs to the current thread.
224 BOOL WIN_IsCurrentThread( HWND hwnd )
229 if ((ptr = WIN_GetWndPtr( hwnd )) && ptr != BAD_WND_PTR)
231 ret = (ptr->tid == GetCurrentThreadId());
238 /***********************************************************************
241 * Convert a 16-bit window handle to a full 32-bit handle.
243 HWND WIN_Handle32( HWND16 hwnd16 )
246 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
248 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
249 /* do sign extension for -2 and -3 */
250 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
252 if ((ptr = WIN_GetWndPtr( hwnd )))
254 if (ptr != BAD_WND_PTR)
256 hwnd = ptr->hwndSelf;
260 else /* may belong to another process */
262 SERVER_START_REQ( get_window_info )
265 if (!SERVER_CALL_ERR()) hwnd = req->full_handle;
273 /***********************************************************************
276 * Return a pointer to the WND structure corresponding to a HWND.
278 WND * WIN_FindWndPtr( HWND hwnd )
282 if (!hwnd) return NULL;
284 if ((ptr = WIN_GetWndPtr( hwnd )))
286 if (ptr != BAD_WND_PTR)
288 /* increment destruction monitoring */
293 else if (IsWindow( hwnd )) /* check other processes */
295 ERR( "window %04x belongs to other process\n", hwnd );
296 /* DbgBreakPoint(); */
298 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
303 /***********************************************************************
306 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
308 * Returns the locked initialisation pointer
310 WND *WIN_LockWndPtr(WND *initWndPtr)
312 if(!initWndPtr) return 0;
314 /* Lock all WND structures for thread safeness*/
316 /*and increment destruction monitoring*/
317 initWndPtr->irefCount++;
323 /***********************************************************************
326 * Release the pointer to the WND structure.
328 void WIN_ReleaseWndPtr(WND *wndPtr)
332 /*Decrement destruction monitoring value*/
334 /* Check if it's time to release the memory*/
335 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
338 free_window_handle( wndPtr->hwndSelf );
340 else if(wndPtr->irefCount < 0)
342 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
343 ERR("forgot a Lock on %p somewhere\n",wndPtr);
345 /*unlock all WND structures for thread safeness*/
349 /***********************************************************************
352 * Updates the value of oldPtr to newPtr.
354 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
358 tmpWnd = WIN_LockWndPtr(newPtr);
359 WIN_ReleaseWndPtr(*oldPtr);
365 /***********************************************************************
368 * Remove a window from the siblings linked list.
370 void WIN_UnlinkWindow( HWND hwnd )
372 WIN_LinkWindow( hwnd, 0, 0 );
376 /***********************************************************************
379 * Insert a window into the siblings linked list.
380 * The window is inserted after the specified window, which can also
381 * be specified as HWND_TOP or HWND_BOTTOM.
382 * If parent is 0, window is unlinked from the tree.
384 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
388 SERVER_START_REQ( link_window )
391 req->parent = parent;
392 req->previous = hwndInsertAfter;
393 ret = !SERVER_CALL_ERR();
398 WND *wndPtr = WIN_FindWndPtr( hwnd );
401 wndPtr->parent = WIN_GetFullHandle(parent);
402 WIN_ReleaseWndPtr( wndPtr );
408 /***********************************************************************
409 * find_child_to_repaint
411 * Find a window that needs repaint among the children of the specified window.
413 static HWND find_child_to_repaint( HWND parent )
419 if (!parent) parent = GetDesktopWindow();
420 if (!(list = list_window_children( parent, 0, 0 ))) return 0;
422 for (i = 0; list[i] && !ret; i++)
424 WND *win = WIN_GetWndPtr( list[i] );
425 if (win == BAD_WND_PTR) continue; /* ignore it */
428 /* doesn't belong to this process, but check children */
429 ret = find_child_to_repaint( list[i] );
432 if (!(win->dwStyle & WS_VISIBLE))
437 if ((win->tid != GetCurrentThreadId()) ||
438 (!win->hrgnUpdate && !(win->flags & WIN_INTERNAL_PAINT)))
440 /* does not need repaint, check children */
442 ret = find_child_to_repaint( list[i] );
446 /* now we have something */
448 if (!(win->dwExStyle & WS_EX_TRANSPARENT))
450 /* not transparent, we can repaint it */
456 /* transparent window, look for non-transparent sibling to paint first */
457 for (i++; list[i]; i++)
459 if (!(win = WIN_GetWndPtr( list[i] ))) continue;
460 if (win == BAD_WND_PTR) continue;
461 if (!(win->dwStyle & WS_VISIBLE))
466 if (!(win->dwExStyle & WS_EX_TRANSPARENT) &&
467 (win->hrgnUpdate || (win->flags & WIN_INTERNAL_PAINT)))
476 HeapFree( GetProcessHeap(), 0, list );
481 /***********************************************************************
482 * WIN_FindWinToRepaint
484 * Find a window that needs repaint.
486 HWND WIN_FindWinToRepaint( HWND hwnd )
488 /* Note: the desktop window never gets WM_PAINT messages
489 * The real reason why is because Windows DesktopWndProc
490 * does ValidateRgn inside WM_ERASEBKGND handler.
492 if (hwnd == GetDesktopWindow()) hwnd = 0;
496 /* check the window itself first */
497 WND *win = WIN_FindWndPtr( hwnd );
499 if ((win->dwStyle & WS_VISIBLE) &&
500 (win->hrgnUpdate || (win->flags & WIN_INTERNAL_PAINT)))
502 WIN_ReleaseWndPtr( win );
505 WIN_ReleaseWndPtr( win );
507 /* now check its children */
508 return find_child_to_repaint( hwnd );
512 /***********************************************************************
515 * Destroy storage associated to a window. "Internals" p.358
517 static void WIN_DestroyWindow( HWND hwnd )
522 TRACE("%04x\n", hwnd );
524 /* free child windows */
525 if ((list = WIN_ListChildren( hwnd )))
528 for (i = 0; list[i]; i++) WIN_DestroyWindow( list[i] );
529 HeapFree( GetProcessHeap(), 0, list );
533 * Clear the update region to make sure no WM_PAINT messages will be
534 * generated for this window while processing the WM_NCDESTROY.
536 RedrawWindow( hwnd, NULL, 0,
537 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
540 * Send the WM_NCDESTROY to the window being destroyed.
542 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
544 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
546 WINPOS_CheckInternalPos( hwnd );
547 if( hwnd == GetCapture()) ReleaseCapture();
549 /* free resources associated with the window */
551 TIMER_RemoveWindowTimers( hwnd );
553 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return;
554 wndPtr->hmemTaskQ = 0;
556 if (!(wndPtr->dwStyle & WS_CHILD))
559 DestroyMenu( wndPtr->wIDmenu );
562 if (wndPtr->hSysMenu)
564 DestroyMenu( wndPtr->hSysMenu );
565 wndPtr->hSysMenu = 0;
567 USER_Driver.pDestroyWindow( hwnd );
568 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
569 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
570 CLASS_RemoveWindow( wndPtr->class );
571 wndPtr->class = NULL;
572 wndPtr->dwMagic = 0; /* Mark it as invalid */
573 WIN_ReleaseWndPtr( wndPtr );
576 /***********************************************************************
577 * WIN_DestroyThreadWindows
579 * Destroy all children of 'wnd' owned by the current thread.
580 * Return TRUE if something was done.
582 void WIN_DestroyThreadWindows( HWND hwnd )
587 if (!(list = WIN_ListChildren( hwnd ))) return;
588 for (i = 0; list[i]; i++)
590 if (!IsWindow( list[i] )) continue;
591 if (WIN_IsCurrentThread( list[i] ))
592 DestroyWindow( list[i] );
594 WIN_DestroyThreadWindows( list[i] );
596 HeapFree( GetProcessHeap(), 0, list );
599 /***********************************************************************
600 * WIN_CreateDesktopWindow
602 * Create the desktop window.
604 BOOL WIN_CreateDesktopWindow(void)
606 struct tagCLASS *class;
614 TRACE("Creating desktop window\n");
617 if (!WINPOS_CreateInternalPosAtom() ||
618 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
619 &wndExtra, &winproc, &clsStyle, &dce )))
622 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM),
623 sizeof(WND) + wndExtra - sizeof(pWndDesktop->wExtra) );
624 if (!pWndDesktop) return FALSE;
625 hwndDesktop = pWndDesktop->hwndSelf;
627 pWndDesktop->tid = 0; /* nobody owns the desktop */
628 pWndDesktop->parent = 0;
629 pWndDesktop->owner = 0;
630 pWndDesktop->class = class;
631 pWndDesktop->hInstance = 0;
632 pWndDesktop->rectWindow.left = 0;
633 pWndDesktop->rectWindow.top = 0;
634 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
635 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
636 pWndDesktop->rectClient = pWndDesktop->rectWindow;
637 pWndDesktop->text = NULL;
638 pWndDesktop->hmemTaskQ = 0;
639 pWndDesktop->hrgnUpdate = 0;
640 pWndDesktop->hwndLastActive = hwndDesktop;
641 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
643 pWndDesktop->dwExStyle = 0;
644 pWndDesktop->clsStyle = clsStyle;
645 pWndDesktop->dce = NULL;
646 pWndDesktop->pVScroll = NULL;
647 pWndDesktop->pHScroll = NULL;
648 pWndDesktop->wIDmenu = 0;
649 pWndDesktop->helpContext = 0;
650 pWndDesktop->flags = 0;
651 pWndDesktop->hSysMenu = 0;
652 pWndDesktop->userdata = 0;
653 pWndDesktop->winproc = winproc;
654 pWndDesktop->cbWndExtra = wndExtra;
656 cs.lpCreateParams = NULL;
662 cs.cx = pWndDesktop->rectWindow.right;
663 cs.cy = pWndDesktop->rectWindow.bottom;
664 cs.style = pWndDesktop->dwStyle;
665 cs.dwExStyle = pWndDesktop->dwExStyle;
667 cs.lpszClass = DESKTOP_CLASS_ATOM;
669 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE )) return FALSE;
671 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
672 WIN_ReleaseWndPtr( pWndDesktop );
677 /***********************************************************************
680 * Fix the coordinates - Helper for WIN_CreateWindowEx.
681 * returns default show mode in sw.
682 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
684 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
686 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
687 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
689 if (cs->style & (WS_CHILD | WS_POPUP))
691 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
692 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
694 else /* overlapped window */
698 GetStartupInfoA( &info );
700 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
702 /* Never believe Microsoft's documentation... CreateWindowEx doc says
703 * that if an overlapped window is created with WS_VISIBLE style bit
704 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
705 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
708 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
709 * 2) it does not ignore the y parameter as the docs claim; instead, it
710 * uses it as second parameter to ShowWindow() unless y is either
711 * CW_USEDEFAULT or CW_USEDEFAULT16.
713 * The fact that we didn't do 2) caused bogus windows pop up when wine
714 * was running apps that were using this obscure feature. Example -
715 * calc.exe that comes with Win98 (only Win98, it's different from
716 * the one that comes with Win95 and NT)
718 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
719 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
720 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
723 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
725 if (info.dwFlags & STARTF_USESIZE)
727 cs->cx = info.dwXSize;
728 cs->cy = info.dwYSize;
730 else /* if no other hint from the app, pick 3/4 of the screen real estate */
733 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
734 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
735 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
742 /***********************************************************************
745 * Implementation of CreateWindowEx().
747 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
748 WINDOWPROCTYPE type )
751 struct tagCLASS *classPtr;
753 HWND hwnd, hwndLinkAfter, parent, owner;
754 POINT maxSize, maxPos, minTrack, maxTrack;
759 BOOL unicode = (type == WIN_PROC_32W);
761 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%04x menu=%04x inst=%08x params=%p\n",
762 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
763 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
764 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
765 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
767 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
768 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
770 /* Find the parent window */
772 parent = GetDesktopWindow();
776 /* Make sure parent is valid */
777 if (!IsWindow( cs->hwndParent ))
779 WARN("Bad parent %04x\n", cs->hwndParent );
782 if (cs->style & WS_CHILD)
784 parent = WIN_GetFullHandle(cs->hwndParent);
785 if (!WIN_IsCurrentProcess(parent))
787 FIXME( "creating child window of %x in other process not supported yet\n",
792 else owner = GetAncestor( cs->hwndParent, GA_ROOT );
794 else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP))
796 WARN("No parent for child window\n" );
797 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
800 /* Find the window class */
801 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
802 &wndExtra, &winproc, &clsStyle, &dce )))
804 WARN("Bad class '%s'\n", cs->lpszClass );
808 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
810 /* Correct the window style - stage 1
812 * These are patches that appear to affect both the style loaded into the
813 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
815 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
816 * why does the user get to set it?
819 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
820 * tested for WS_POPUP
822 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
823 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
824 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
825 cs->dwExStyle |= WS_EX_WINDOWEDGE;
827 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
829 /* Create the window structure */
831 if (!(wndPtr = create_window_handle( parent, owner, classAtom,
832 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
834 TRACE("out of memory\n" );
837 hwnd = wndPtr->hwndSelf;
839 /* Fill the window structure */
841 wndPtr->tid = GetCurrentThreadId();
842 wndPtr->owner = owner;
843 wndPtr->parent = parent;
844 wndPtr->class = classPtr;
845 wndPtr->winproc = winproc;
846 wndPtr->hInstance = cs->hInstance;
848 wndPtr->hmemTaskQ = InitThreadInput16( 0, 0 );
849 wndPtr->hrgnUpdate = 0;
851 wndPtr->hwndLastActive = hwnd;
852 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
853 wndPtr->dwExStyle = cs->dwExStyle;
854 wndPtr->clsStyle = clsStyle;
856 wndPtr->helpContext = 0;
857 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
858 wndPtr->pVScroll = NULL;
859 wndPtr->pHScroll = NULL;
860 wndPtr->userdata = 0;
861 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
862 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
863 wndPtr->cbWndExtra = wndExtra;
865 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
867 /* Call the WH_CBT hook */
869 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
870 ? HWND_BOTTOM : HWND_TOP;
872 if (HOOK_IsHooked( WH_CBT ))
878 cbtc.hwndInsertAfter = hwndLinkAfter;
879 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND,
880 (WPARAM)hwnd, (LPARAM)&cbtc)
881 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND,
882 (WPARAM)hwnd, (LPARAM)&cbtc);
885 TRACE("CBT-hook returned 0\n");
886 free_window_handle( hwnd );
887 CLASS_RemoveWindow( classPtr );
893 /* Correct the window style - stage 2 */
895 if (!(cs->style & WS_CHILD))
897 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
898 if (!(cs->style & WS_POPUP))
900 wndPtr->dwStyle |= WS_CAPTION;
901 wndPtr->flags |= WIN_NEED_SIZE;
905 /* Get class or window DC if needed */
907 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
908 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
909 else wndPtr->dce = NULL;
911 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
913 wndPtr->rectWindow.left = cs->x;
914 wndPtr->rectWindow.top = cs->y;
915 wndPtr->rectWindow.right = cs->x + cs->cx;
916 wndPtr->rectWindow.bottom = cs->y + cs->cy;
917 wndPtr->rectClient = wndPtr->rectWindow;
919 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
921 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
923 WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
924 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
925 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
926 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
927 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
930 if (cs->cx < 0) cs->cx = 0;
931 if (cs->cy < 0) cs->cy = 0;
933 wndPtr->rectWindow.left = cs->x;
934 wndPtr->rectWindow.top = cs->y;
935 wndPtr->rectWindow.right = cs->x + cs->cx;
936 wndPtr->rectWindow.bottom = cs->y + cs->cy;
937 wndPtr->rectClient = wndPtr->rectWindow;
939 /* Set the window menu */
941 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
943 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
946 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
949 if (HIWORD(cs->hInstance))
950 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
952 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
954 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
958 else wndPtr->wIDmenu = (UINT)cs->hMenu;
960 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
962 WARN("aborted by WM_xxCREATE!\n");
963 WIN_ReleaseWndPtr( wndPtr );
964 WIN_DestroyWindow( hwnd );
965 CLASS_RemoveWindow( classPtr );
969 if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
971 /* Notify the parent window only */
973 SendMessageA( wndPtr->parent, WM_PARENTNOTIFY,
974 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
975 if( !IsWindow(hwnd) )
982 if (cs->style & WS_VISIBLE)
984 /* in case WS_VISIBLE got set in the meantime */
985 wndPtr->dwStyle &= ~WS_VISIBLE;
986 ShowWindow( hwnd, sw );
989 /* Call WH_SHELL hook */
991 if (!(wndPtr->dwStyle & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
992 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0 );
994 TRACE("created window %04x\n", hwnd);
996 WIN_ReleaseWndPtr(wndPtr);
1001 /***********************************************************************
1002 * CreateWindow (USER.41)
1004 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1005 DWORD style, INT16 x, INT16 y, INT16 width,
1006 INT16 height, HWND16 parent, HMENU16 menu,
1007 HINSTANCE16 instance, LPVOID data )
1009 return CreateWindowEx16( 0, className, windowName, style,
1010 x, y, width, height, parent, menu, instance, data );
1014 /***********************************************************************
1015 * CreateWindowEx (USER.452)
1017 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1018 LPCSTR windowName, DWORD style, INT16 x,
1019 INT16 y, INT16 width, INT16 height,
1020 HWND16 parent, HMENU16 menu,
1021 HINSTANCE16 instance, LPVOID data )
1027 /* Find the class atom */
1029 if (HIWORD(className))
1031 if (!(classAtom = GlobalFindAtomA( className )))
1033 ERR( "bad class name %s\n", debugres_a(className) );
1039 classAtom = LOWORD(className);
1040 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1042 ERR( "bad atom %x\n", classAtom);
1048 /* Fix the coordinates */
1050 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1051 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1052 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1053 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1055 /* Create the window */
1057 cs.lpCreateParams = data;
1058 cs.hInstance = (HINSTANCE)instance;
1059 cs.hMenu = (HMENU)menu;
1060 cs.hwndParent = WIN_Handle32( parent );
1062 cs.lpszName = windowName;
1063 cs.lpszClass = className;
1064 cs.dwExStyle = exStyle;
1066 return WIN_Handle16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1070 /***********************************************************************
1071 * CreateWindowExA (USER32.@)
1073 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1074 LPCSTR windowName, DWORD style, INT x,
1075 INT y, INT width, INT height,
1076 HWND parent, HMENU menu,
1077 HINSTANCE instance, LPVOID data )
1084 instance=GetModuleHandleA(NULL);
1086 if(exStyle & WS_EX_MDICHILD)
1087 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1089 /* Find the class atom */
1091 if (HIWORD(className))
1093 if (!(classAtom = GlobalFindAtomA( className )))
1095 ERR( "bad class name %s\n", debugres_a(className) );
1101 classAtom = LOWORD(className);
1102 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1104 ERR( "bad atom %x\n", classAtom);
1110 /* Create the window */
1112 cs.lpCreateParams = data;
1113 cs.hInstance = instance;
1115 cs.hwndParent = parent;
1121 cs.lpszName = windowName;
1122 cs.lpszClass = className;
1123 cs.dwExStyle = exStyle;
1125 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1129 /***********************************************************************
1130 * CreateWindowExW (USER32.@)
1132 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1133 LPCWSTR windowName, DWORD style, INT x,
1134 INT y, INT width, INT height,
1135 HWND parent, HMENU menu,
1136 HINSTANCE instance, LPVOID data )
1143 instance=GetModuleHandleA(NULL);
1145 if(exStyle & WS_EX_MDICHILD)
1146 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1148 /* Find the class atom */
1150 if (HIWORD(className))
1152 if (!(classAtom = GlobalFindAtomW( className )))
1154 ERR( "bad class name %s\n", debugres_w(className) );
1160 classAtom = LOWORD(className);
1161 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1163 ERR( "bad atom %x\n", classAtom);
1169 /* Create the window */
1171 cs.lpCreateParams = data;
1172 cs.hInstance = instance;
1174 cs.hwndParent = parent;
1180 cs.lpszName = windowName;
1181 cs.lpszClass = className;
1182 cs.dwExStyle = exStyle;
1184 /* Note: we rely on the fact that CREATESTRUCTA and */
1185 /* CREATESTRUCTW have the same layout. */
1186 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1190 /***********************************************************************
1191 * WIN_SendDestroyMsg
1193 static void WIN_SendDestroyMsg( HWND hwnd )
1195 if( CARET_GetHwnd() == hwnd) DestroyCaret();
1196 if (USER_Driver.pResetSelectionOwner)
1197 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1200 * Send the WM_DESTROY to the window.
1202 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1205 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1206 * make sure that the window still exists when we come back.
1213 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1215 /* start from the end (FIXME: is this needed?) */
1216 for (i = 0; pWndArray[i]; i++) ;
1220 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1222 HeapFree( GetProcessHeap(), 0, pWndArray );
1225 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1229 /***********************************************************************
1230 * DestroyWindow (USER32.@)
1232 BOOL WINAPI DestroyWindow( HWND hwnd )
1238 hwnd = WIN_GetFullHandle( hwnd );
1239 TRACE("(%04x)\n", hwnd);
1241 /* Initialization */
1243 if (hwnd == GetDesktopWindow()) return FALSE; /* Can't destroy desktop */
1245 /* Look whether the focus is within the tree of windows we will
1249 if (h == hwnd || IsChild( hwnd, h ))
1251 HWND parent = GetAncestor( hwnd, GA_PARENT );
1252 if (parent == GetDesktopWindow()) parent = 0;
1258 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0L) ) return FALSE;
1260 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1261 if (!(wndPtr->dwStyle & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1263 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L );
1264 /* FIXME: clean up palette - see "Internals" p.352 */
1267 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1268 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1270 /* Notify the parent window only */
1271 SendMessageA( wndPtr->parent, WM_PARENTNOTIFY,
1272 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1273 if( !IsWindow(hwnd) )
1280 if (USER_Driver.pResetSelectionOwner)
1281 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1283 /* Hide the window */
1285 ShowWindow( hwnd, SW_HIDE );
1286 if (!IsWindow(hwnd))
1292 /* Recursively destroy owned windows */
1294 if( !(wndPtr->dwStyle & WS_CHILD) )
1301 HWND *list = WIN_ListChildren( wndPtr->parent );
1304 for (i = 0; list[i]; i++)
1307 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1308 if (!(siblingPtr = WIN_FindWndPtr( list[i] ))) continue;
1309 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1311 WIN_ReleaseWndPtr( siblingPtr );
1312 DestroyWindow( list[i] );
1316 else siblingPtr->owner = 0;
1317 WIN_ReleaseWndPtr( siblingPtr );
1319 HeapFree( GetProcessHeap(), 0, list );
1321 if (!got_one) break;
1324 WINPOS_ActivateOtherWindow( hwnd );
1326 if ((owner = GetWindow( hwnd, GW_OWNER )))
1328 WND *ptr = WIN_FindWndPtr( owner );
1331 if (ptr->hwndLastActive == hwnd) ptr->hwndLastActive = owner;
1332 WIN_ReleaseWndPtr( ptr );
1337 /* Send destroy messages */
1339 WIN_SendDestroyMsg( hwnd );
1340 if (!IsWindow(hwnd))
1346 /* Unlink now so we won't bother with the children later on */
1348 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1350 /* Destroy the window storage */
1352 WIN_DestroyWindow( hwnd );
1355 WIN_ReleaseWndPtr(wndPtr);
1360 /***********************************************************************
1361 * CloseWindow (USER32.@)
1363 BOOL WINAPI CloseWindow( HWND hwnd )
1365 WND * wndPtr = WIN_FindWndPtr( hwnd );
1368 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1373 ShowWindow( hwnd, SW_MINIMIZE );
1376 WIN_ReleaseWndPtr(wndPtr);
1382 /***********************************************************************
1383 * OpenIcon (USER32.@)
1385 BOOL WINAPI OpenIcon( HWND hwnd )
1387 if (!IsIconic( hwnd )) return FALSE;
1388 ShowWindow( hwnd, SW_SHOWNORMAL );
1393 /***********************************************************************
1396 * Implementation of FindWindow() and FindWindowEx().
1398 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1403 WCHAR *buffer = NULL;
1405 if (!parent) parent = GetDesktopWindow();
1408 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1409 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1412 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1416 child = WIN_GetFullHandle( child );
1417 while (list[i] && list[i] != child) i++;
1418 if (!list[i]) goto done;
1419 i++; /* start from next window */
1426 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1433 if (list) HeapFree( GetProcessHeap(), 0, list );
1434 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1440 /***********************************************************************
1441 * FindWindowA (USER32.@)
1443 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1445 HWND ret = FindWindowExA( 0, 0, className, title );
1446 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1451 /***********************************************************************
1452 * FindWindowExA (USER32.@)
1454 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1455 LPCSTR className, LPCSTR title )
1463 /* If the atom doesn't exist, then no class */
1464 /* with this name exists either. */
1465 if (!(atom = GlobalFindAtomA( className )))
1467 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1472 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1473 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1474 HeapFree( GetProcessHeap(), 0, buffer );
1479 /***********************************************************************
1480 * FindWindowExW (USER32.@)
1482 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1483 LPCWSTR className, LPCWSTR title )
1489 /* If the atom doesn't exist, then no class */
1490 /* with this name exists either. */
1491 if (!(atom = GlobalFindAtomW( className )))
1493 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1497 return WIN_FindWindow( parent, child, atom, title );
1501 /***********************************************************************
1502 * FindWindowW (USER32.@)
1504 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1506 return FindWindowExW( 0, 0, className, title );
1510 /**********************************************************************
1511 * GetDesktopWindow (USER32.@)
1513 HWND WINAPI GetDesktopWindow(void)
1515 if (pWndDesktop) return pWndDesktop->hwndSelf;
1516 ERR( "You need the -desktop option when running with native USER\n" );
1522 /*******************************************************************
1523 * EnableWindow (USER32.@)
1525 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1530 TRACE("( %x, %d )\n", hwnd, enable);
1532 if (USER_Driver.pEnableWindow)
1533 return USER_Driver.pEnableWindow( hwnd, enable );
1535 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1536 hwnd = wndPtr->hwndSelf; /* make it a full handle */
1538 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1540 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1542 wndPtr->dwStyle &= ~WS_DISABLED; /* Enable window */
1543 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1545 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1547 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1549 wndPtr->dwStyle |= WS_DISABLED; /* Disable window */
1551 if (hwnd == GetFocus())
1552 SetFocus( 0 ); /* A disabled window can't have the focus */
1554 if (hwnd == GetCapture())
1555 ReleaseCapture(); /* A disabled window can't capture the mouse */
1557 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1559 WIN_ReleaseWndPtr(wndPtr);
1564 /***********************************************************************
1565 * IsWindowEnabled (USER32.@)
1567 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1572 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1573 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1574 WIN_ReleaseWndPtr(wndPtr);
1580 /***********************************************************************
1581 * IsWindowUnicode (USER32.@)
1583 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1588 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1589 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1590 WIN_ReleaseWndPtr(wndPtr);
1595 /**********************************************************************
1596 * GetWindowWord (USER32.@)
1598 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1601 WND * wndPtr = WIN_FindWndPtr( hwnd );
1602 if (!wndPtr) return 0;
1605 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1607 WARN("Invalid offset %d\n", offset );
1610 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1611 WIN_ReleaseWndPtr(wndPtr);
1615 WIN_ReleaseWndPtr(wndPtr);
1618 case GWL_HWNDPARENT:
1619 return GetWindowLongW( hwnd, offset );
1623 LONG ret = GetWindowLongW( hwnd, offset );
1625 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1629 WARN("Invalid offset %d\n", offset );
1635 /**********************************************************************
1636 * SetWindowWord (USER32.@)
1638 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1641 WND * wndPtr = WIN_FindWndPtr( hwnd );
1642 if (!wndPtr) return 0;
1645 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1647 WARN("Invalid offset %d\n", offset );
1648 WIN_ReleaseWndPtr(wndPtr);
1651 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1654 WIN_ReleaseWndPtr(wndPtr);
1658 WIN_ReleaseWndPtr(wndPtr);
1663 case GWL_HWNDPARENT:
1664 return SetWindowLongW( hwnd, offset, (UINT)newval );
1666 WARN("Invalid offset %d\n", offset );
1672 /**********************************************************************
1675 * Helper function for GetWindowLong().
1677 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1680 WND * wndPtr = WIN_FindWndPtr( hwnd );
1681 if (!wndPtr) return 0;
1684 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1686 WARN("Invalid offset %d\n", offset );
1690 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1691 /* Special case for dialog window procedure */
1692 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1694 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1701 case GWL_USERDATA: retvalue = wndPtr->userdata;
1703 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1705 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1707 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1709 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1712 case GWL_HWNDPARENT: retvalue = (LONG)GetParent(hwnd);
1714 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1717 WARN("Unknown offset %d\n", offset );
1721 WIN_ReleaseWndPtr(wndPtr);
1726 /**********************************************************************
1729 * Helper function for SetWindowLong().
1731 * 0 is the failure code. However, in the case of failure SetLastError
1732 * must be set to distinguish between a 0 return value and a failure.
1734 * FIXME: The error values for SetLastError may not be right. Can
1735 * someone check with the real thing?
1737 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1738 WINDOWPROCTYPE type )
1741 WND * wndPtr = WIN_FindWndPtr( hwnd );
1744 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1748 /* Is this the right error? */
1749 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1755 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1757 WARN("Invalid offset %d\n", offset );
1759 /* Is this the right error? */
1760 SetLastError( ERROR_OUTOFMEMORY );
1765 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1766 /* Special case for dialog window procedure */
1767 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1769 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1770 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1771 type, WIN_PROC_WINDOW );
1778 ptr = (DWORD*)&wndPtr->wIDmenu;
1781 ptr = (DWORD*)&wndPtr->hInstance;
1784 ptr = &wndPtr->userdata;
1786 case GWL_HWNDPARENT:
1787 retval = SetParent( hwnd, (HWND)newval );
1790 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1791 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1792 type, WIN_PROC_WINDOW );
1795 retval = wndPtr->dwStyle;
1796 style.styleOld = wndPtr->dwStyle;
1797 style.styleNew = newval;
1798 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1799 wndPtr->dwStyle = style.styleNew;
1800 if (USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, retval );
1801 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1802 retval = style.styleOld;
1805 style.styleOld = wndPtr->dwExStyle;
1806 style.styleNew = newval;
1807 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1808 wndPtr->dwExStyle = style.styleNew;
1809 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1810 retval = style.styleOld;
1814 WARN("Invalid offset %d\n", offset );
1816 /* Don't think this is right error but it should do */
1817 SetLastError( ERROR_OUTOFMEMORY );
1825 WIN_ReleaseWndPtr(wndPtr);
1830 /**********************************************************************
1831 * GetWindowLong (USER.135)
1833 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1835 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
1839 /**********************************************************************
1840 * GetWindowLongA (USER32.@)
1842 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
1844 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1848 /**********************************************************************
1849 * GetWindowLongW (USER32.@)
1851 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
1853 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1857 /**********************************************************************
1858 * SetWindowLong (USER.136)
1860 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1862 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
1866 /**********************************************************************
1867 * SetWindowLongA (USER32.@)
1869 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
1871 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1875 /**********************************************************************
1876 * SetWindowLongW (USER32.@) Set window attribute
1878 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
1879 * value in a window's extra memory.
1881 * The _hwnd_ parameter specifies the window. is the handle to a
1882 * window that has extra memory. The _newval_ parameter contains the
1883 * new attribute or extra memory value. If positive, the _offset_
1884 * parameter is the byte-addressed location in the window's extra
1885 * memory to set. If negative, _offset_ specifies the window
1886 * attribute to set, and should be one of the following values:
1888 * GWL_EXSTYLE The window's extended window style
1890 * GWL_STYLE The window's window style.
1892 * GWL_WNDPROC Pointer to the window's window procedure.
1894 * GWL_HINSTANCE The window's pplication instance handle.
1896 * GWL_ID The window's identifier.
1898 * GWL_USERDATA The window's user-specified data.
1900 * If the window is a dialog box, the _offset_ parameter can be one of
1901 * the following values:
1903 * DWL_DLGPROC The address of the window's dialog box procedure.
1905 * DWL_MSGRESULT The return value of a message
1906 * that the dialog box procedure processed.
1908 * DWL_USER Application specific information.
1912 * If successful, returns the previous value located at _offset_. Otherwise,
1917 * Extra memory for a window class is specified by a nonzero cbWndExtra
1918 * parameter of the WNDCLASS structure passed to RegisterClass() at the
1919 * time of class creation.
1921 * Using GWL_WNDPROC to set a new window procedure effectively creates
1922 * a window subclass. Use CallWindowProc() in the new windows procedure
1923 * to pass messages to the superclass's window procedure.
1925 * The user data is reserved for use by the application which created
1928 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
1929 * instead, call the EnableWindow() function to change the window's
1932 * Do not use GWL_HWNDPARENT to reset the window's parent, use
1933 * SetParent() instead.
1936 * When offset is GWL_STYLE and the calling app's ver is 4.0,
1937 * it sends WM_STYLECHANGING before changing the settings
1938 * and WM_STYLECHANGED afterwards.
1939 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
1943 * GWL_STYLE does not dispatch WM_STYLE... messages.
1950 LONG WINAPI SetWindowLongW(
1951 HWND hwnd, /* [in] window to alter */
1952 INT offset, /* [in] offset, in bytes, of location to alter */
1953 LONG newval /* [in] new value of location */
1955 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1959 /*******************************************************************
1960 * GetWindowTextA (USER32.@)
1962 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
1964 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
1968 /*******************************************************************
1969 * InternalGetWindowText (USER32.@)
1971 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
1973 WND *win = WIN_FindWndPtr( hwnd );
1975 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
1976 else lpString[0] = 0;
1977 WIN_ReleaseWndPtr( win );
1978 return strlenW(lpString);
1982 /*******************************************************************
1983 * GetWindowTextW (USER32.@)
1985 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
1987 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
1992 /*******************************************************************
1993 * SetWindowText (USER32.@)
1994 * SetWindowTextA (USER32.@)
1996 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
1998 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2002 /*******************************************************************
2003 * SetWindowTextW (USER32.@)
2005 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2007 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2011 /*******************************************************************
2012 * GetWindowTextLengthA (USER32.@)
2014 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2016 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2019 /*******************************************************************
2020 * GetWindowTextLengthW (USER32.@)
2022 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2024 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2028 /*******************************************************************
2029 * IsWindow (USER32.@)
2031 BOOL WINAPI IsWindow( HWND hwnd )
2036 if ((ptr = WIN_GetWndPtr( hwnd )))
2038 if (ptr == BAD_WND_PTR) return FALSE;
2043 /* check other processes */
2044 SERVER_START_REQ( get_window_info )
2047 ret = !SERVER_CALL_ERR();
2054 /***********************************************************************
2055 * GetWindowThreadProcessId (USER32.@)
2057 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2062 if ((ptr = WIN_GetWndPtr( hwnd )))
2064 if (ptr != BAD_WND_PTR)
2066 /* got a valid window */
2068 if (process) *process = GetCurrentProcessId();
2071 else SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2075 /* check other processes */
2076 SERVER_START_REQ( get_window_info )
2079 if (!SERVER_CALL_ERR())
2081 tid = (DWORD)req->tid;
2082 if (process) *process = (DWORD)req->pid;
2090 /*****************************************************************
2091 * GetParent (USER32.@)
2093 HWND WINAPI GetParent( HWND hwnd )
2098 if ((wndPtr = WIN_FindWndPtr(hwnd)))
2100 if (wndPtr->dwStyle & WS_CHILD)
2101 retvalue = wndPtr->parent;
2102 else if (wndPtr->dwStyle & WS_POPUP)
2103 retvalue = wndPtr->owner;
2104 WIN_ReleaseWndPtr(wndPtr);
2110 /*****************************************************************
2111 * GetAncestor (USER32.@)
2113 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2116 size_t size = (type == GA_PARENT) ? sizeof(user_handle_t) : REQUEST_MAX_VAR_SIZE;
2118 SERVER_START_VAR_REQ( get_window_parents, size )
2123 user_handle_t *data = server_data_ptr(req);
2124 int count = server_data_size(req) / sizeof(*data);
2134 if (count > 1) ret = data[count - 2]; /* get the one before the desktop */
2135 else ret = WIN_GetFullHandle( hwnd );
2143 if (ret && type == GA_ROOTOWNER)
2147 HWND owner = GetWindow( ret, GW_OWNER );
2156 /*****************************************************************
2157 * SetParent (USER32.@)
2159 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2165 if (!parent) parent = GetDesktopWindow();
2166 else parent = WIN_GetFullHandle( parent );
2169 if (WIN_GetFullHandle(hwnd) == GetDesktopWindow() || !IsWindow( parent ))
2171 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2175 if (USER_Driver.pSetParent)
2176 return USER_Driver.pSetParent( hwnd, parent );
2178 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2180 dwStyle = wndPtr->dwStyle;
2182 /* Windows hides the window first, then shows it again
2183 * including the WM_SHOWWINDOW messages and all */
2184 if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
2186 retvalue = wndPtr->parent; /* old parent */
2187 if (parent != retvalue)
2189 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2191 if (parent != GetDesktopWindow()) /* a child window */
2193 if (!(dwStyle & WS_CHILD))
2195 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2196 if (menu) DestroyMenu( menu );
2200 WIN_ReleaseWndPtr( wndPtr );
2202 /* SetParent additionally needs to make hwnd the topmost window
2203 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2204 WM_WINDOWPOSCHANGED notification messages.
2206 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2207 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|
2208 ((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2209 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2210 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2215 /*******************************************************************
2216 * IsChild (USER32.@)
2218 BOOL WINAPI IsChild( HWND parent, HWND child )
2220 HWND *list = WIN_ListParents( child );
2224 if (!list) return FALSE;
2225 parent = WIN_GetFullHandle( parent );
2226 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2227 ret = (list[i] != 0);
2228 HeapFree( GetProcessHeap(), 0, list );
2233 /***********************************************************************
2234 * IsWindowVisible (USER32.@)
2236 BOOL WINAPI IsWindowVisible( HWND hwnd )
2242 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2243 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2244 for (i = 0; list[i]; i++)
2245 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2247 HeapFree( GetProcessHeap(), 0, list );
2252 /***********************************************************************
2253 * WIN_IsWindowDrawable
2255 * hwnd is drawable when it is visible, all parents are not
2256 * minimized, and it is itself not minimized unless we are
2257 * trying to draw its default class icon.
2259 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2265 if (!(wnd->dwStyle & WS_VISIBLE)) return FALSE;
2266 if ((wnd->dwStyle & WS_MINIMIZE) &&
2267 icon && GetClassLongA( wnd->hwndSelf, GCL_HICON )) return FALSE;
2269 if (!(list = WIN_ListParents( wnd->hwndSelf ))) return TRUE;
2270 for (i = 0; list[i]; i++)
2271 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2274 HeapFree( GetProcessHeap(), 0, list );
2279 /*******************************************************************
2280 * GetTopWindow (USER32.@)
2282 HWND WINAPI GetTopWindow( HWND hwnd )
2284 if (!hwnd) hwnd = GetDesktopWindow();
2285 return GetWindow( hwnd, GW_CHILD );
2289 /*******************************************************************
2290 * GetWindow (USER32.@)
2292 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2296 if (rel == GW_OWNER) /* special case: not fully supported in the server yet */
2298 WND *wndPtr = WIN_FindWndPtr( hwnd );
2299 if (!wndPtr) return 0;
2300 retval = wndPtr->owner;
2301 WIN_ReleaseWndPtr( wndPtr );
2305 SERVER_START_REQ( get_window_tree )
2308 if (!SERVER_CALL_ERR())
2313 retval = req->first_sibling;
2316 retval = req->last_sibling;
2319 retval = req->next_sibling;
2322 retval = req->prev_sibling;
2325 retval = req->first_child;
2335 /***********************************************************************
2336 * WIN_InternalShowOwnedPopups
2338 * Internal version of ShowOwnedPopups; Wine functions should use this
2339 * to avoid interfering with application calls to ShowOwnedPopups
2340 * and to make sure the application can't prevent showing/hiding.
2342 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2346 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2350 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2352 if (!win_array) return TRUE;
2355 * Show windows Lowest first, Highest last to preserve Z-Order
2357 while (win_array[count]) count++;
2358 while (--count >= 0)
2360 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2361 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2363 if (pWnd->dwStyle & WS_POPUP)
2367 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2368 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2371 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2373 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2374 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2379 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2380 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2381 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2384 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2386 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2387 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2388 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2392 WIN_ReleaseWndPtr( pWnd );
2394 HeapFree( GetProcessHeap(), 0, win_array );
2399 /*******************************************************************
2400 * ShowOwnedPopups (USER32.@)
2402 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2406 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2408 if (!win_array) return TRUE;
2410 while (win_array[count]) count++;
2411 while (--count >= 0)
2413 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2414 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2416 if (pWnd->dwStyle & WS_POPUP)
2420 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2422 /* In Windows, ShowOwnedPopups(TRUE) generates
2423 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2424 * regardless of the state of the owner
2426 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2427 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2432 if (IsWindowVisible(pWnd->hwndSelf))
2434 /* In Windows, ShowOwnedPopups(FALSE) generates
2435 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2436 * regardless of the state of the owner
2438 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2439 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2443 WIN_ReleaseWndPtr( pWnd );
2445 HeapFree( GetProcessHeap(), 0, win_array );
2450 /*******************************************************************
2451 * GetLastActivePopup (USER32.@)
2453 HWND WINAPI GetLastActivePopup( HWND hwnd )
2456 WND *wndPtr =WIN_FindWndPtr(hwnd);
2457 if (!wndPtr) return hwnd;
2458 retval = wndPtr->hwndLastActive;
2459 if (!IsWindow( retval )) retval = wndPtr->hwndSelf;
2460 WIN_ReleaseWndPtr(wndPtr);
2465 /*******************************************************************
2468 * Build an array of all parents of a given window, starting with
2469 * the immediate parent. The array must be freed with HeapFree.
2470 * Returns NULL if window is a top-level window.
2472 HWND *WIN_ListParents( HWND hwnd )
2476 SERVER_START_VAR_REQ( get_window_parents, REQUEST_MAX_VAR_SIZE )
2481 user_handle_t *data = server_data_ptr(req);
2482 int i, count = server_data_size(req) / sizeof(*data);
2483 if (count && ((list = HeapAlloc( GetProcessHeap(), 0, (count + 1) * sizeof(HWND) ))))
2485 for (i = 0; i < count; i++) list[i] = data[i];
2495 /*******************************************************************
2498 * Build an array of the children of a given window. The array must be
2499 * freed with HeapFree. Returns NULL when no windows are found.
2501 HWND *WIN_ListChildren( HWND hwnd )
2503 return list_window_children( hwnd, 0, 0 );
2507 /*******************************************************************
2508 * EnumWindows (USER32.@)
2510 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2516 /* We have to build a list of all windows first, to avoid */
2517 /* unpleasant side-effects, for instance if the callback */
2518 /* function changes the Z-order of the windows. */
2520 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return FALSE;
2522 /* Now call the callback function for every window */
2524 iWndsLocks = WIN_SuspendWndsLock();
2525 for (i = 0; list[i]; i++)
2527 /* Make sure that the window still exists */
2528 if (!IsWindow( list[i] )) continue;
2529 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2531 WIN_RestoreWndsLock(iWndsLocks);
2532 HeapFree( GetProcessHeap(), 0, list );
2537 /**********************************************************************
2538 * EnumTaskWindows16 (USER.225)
2540 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2543 TDB *tdb = TASK_GetPtr( hTask );
2544 if (!tdb) return FALSE;
2545 return EnumThreadWindows( (DWORD)tdb->teb->tid, (WNDENUMPROC)func, lParam );
2549 /**********************************************************************
2550 * EnumThreadWindows (USER32.@)
2552 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2557 if (!(list = list_window_children( GetDesktopWindow(), 0, GetCurrentThreadId() )))
2560 /* Now call the callback function for every window */
2562 iWndsLocks = WIN_SuspendWndsLock();
2563 for (i = 0; list[i]; i++)
2564 if (!func( list[i], lParam )) break;
2565 WIN_RestoreWndsLock(iWndsLocks);
2566 HeapFree( GetProcessHeap(), 0, list );
2571 /**********************************************************************
2572 * WIN_EnumChildWindows
2574 * Helper function for EnumChildWindows().
2576 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2581 for ( ; *list; list++)
2583 /* Make sure that the window still exists */
2584 if (!IsWindow( *list )) continue;
2585 /* skip owned windows */
2586 if (GetWindow( *list, GW_OWNER )) continue;
2587 /* Build children list first */
2588 childList = WIN_ListChildren( *list );
2590 ret = func( *list, lParam );
2594 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2595 HeapFree( GetProcessHeap(), 0, childList );
2597 if (!ret) return FALSE;
2603 /**********************************************************************
2604 * EnumChildWindows (USER32.@)
2606 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2611 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2612 iWndsLocks = WIN_SuspendWndsLock();
2613 WIN_EnumChildWindows( list, func, lParam );
2614 WIN_RestoreWndsLock(iWndsLocks);
2615 HeapFree( GetProcessHeap(), 0, list );
2620 /*******************************************************************
2621 * AnyPopup (USER.52)
2623 BOOL16 WINAPI AnyPopup16(void)
2629 /*******************************************************************
2630 * AnyPopup (USER32.@)
2632 BOOL WINAPI AnyPopup(void)
2636 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2638 if (!list) return FALSE;
2639 for (i = 0; list[i]; i++)
2641 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2643 retvalue = (list[i] != 0);
2644 HeapFree( GetProcessHeap(), 0, list );
2649 /*******************************************************************
2650 * FlashWindow (USER32.@)
2652 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2654 WND *wndPtr = WIN_FindWndPtr(hWnd);
2656 TRACE("%04x\n", hWnd);
2658 if (!wndPtr) return FALSE;
2659 hWnd = wndPtr->hwndSelf; /* make it a full handle */
2661 if (wndPtr->dwStyle & WS_MINIMIZE)
2663 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2665 HDC hDC = GetDC(hWnd);
2667 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2668 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2670 ReleaseDC( hWnd, hDC );
2671 wndPtr->flags |= WIN_NCACTIVATED;
2675 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2676 wndPtr->flags &= ~WIN_NCACTIVATED;
2678 WIN_ReleaseWndPtr(wndPtr);
2684 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2685 else wparam = (hWnd == GetActiveWindow());
2687 WIN_ReleaseWndPtr(wndPtr);
2688 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2694 /*******************************************************************
2695 * GetWindowContextHelpId (USER32.@)
2697 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2700 WND *wnd = WIN_FindWndPtr( hwnd );
2702 retval = wnd->helpContext;
2703 WIN_ReleaseWndPtr(wnd);
2708 /*******************************************************************
2709 * SetWindowContextHelpId (USER32.@)
2711 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
2713 WND *wnd = WIN_FindWndPtr( hwnd );
2714 if (!wnd) return FALSE;
2715 wnd->helpContext = id;
2716 WIN_ReleaseWndPtr(wnd);
2721 /*******************************************************************
2724 * recursively find a child that contains spDragInfo->pt point
2725 * and send WM_QUERYDROPOBJECT
2727 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
2729 BOOL16 wParam, bResult = 0;
2731 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
2734 if (!ptrDragInfo) return FALSE;
2736 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
2738 GetWindowRect(hQueryWnd,&tempRect);
2740 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
2742 if (!IsIconic( hQueryWnd ))
2744 GetClientRect( hQueryWnd, &tempRect );
2745 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
2747 if (PtInRect( &tempRect, pt))
2750 HWND *list = WIN_ListChildren( hQueryWnd );
2756 for (i = 0; list[i]; i++)
2758 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
2760 GetWindowRect( list[i], &tempRect );
2761 if (PtInRect( &tempRect, pt )) break;
2766 if (IsWindowEnabled( list[i] ))
2767 bResult = DRAG_QueryUpdate( list[i], spDragInfo, bNoSend );
2769 HeapFree( GetProcessHeap(), 0, list );
2771 if(bResult) return bResult;
2777 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
2779 ptrDragInfo->hScope = hQueryWnd;
2781 if (bNoSend) bResult = (GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) != 0;
2782 else bResult = SendMessage16( hQueryWnd, WM_QUERYDROPOBJECT, (WPARAM16)wParam, spDragInfo );
2784 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
2790 /*******************************************************************
2791 * DragDetect (USER32.@)
2793 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
2798 rect.left = pt.x - wDragWidth;
2799 rect.right = pt.x + wDragWidth;
2801 rect.top = pt.y - wDragHeight;
2802 rect.bottom = pt.y + wDragHeight;
2808 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
2810 if( msg.message == WM_LBUTTONUP )
2815 if( msg.message == WM_MOUSEMOVE )
2818 tmp.x = LOWORD(msg.lParam);
2819 tmp.y = HIWORD(msg.lParam);
2820 if( !PtInRect( &rect, tmp ))
2832 /******************************************************************************
2833 * DragObject (USER.464)
2835 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
2836 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
2839 LPDRAGINFO16 lpDragInfo;
2841 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
2842 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
2843 HCURSOR16 hCurrentCursor = 0;
2844 HWND16 hCurrentWnd = 0;
2846 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
2847 spDragInfo = K32WOWGlobalLock16(hDragInfo);
2849 if( !lpDragInfo || !spDragInfo ) return 0L;
2851 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
2853 GlobalFree16(hDragInfo);
2859 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
2861 GlobalFree16(hDragInfo);
2865 if( hDragCursor == hCursor ) hDragCursor = 0;
2866 else hCursor = hDragCursor;
2868 hOldCursor = SetCursor(hDragCursor);
2871 lpDragInfo->hWnd = hWnd;
2872 lpDragInfo->hScope = 0;
2873 lpDragInfo->wFlags = wObj;
2874 lpDragInfo->hList = szList; /* near pointer! */
2875 lpDragInfo->hOfStruct = hOfStruct;
2883 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
2885 *(lpDragInfo+1) = *lpDragInfo;
2887 lpDragInfo->pt.x = msg.pt.x;
2888 lpDragInfo->pt.y = msg.pt.y;
2890 /* update DRAGINFO struct */
2891 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
2893 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
2894 hCurrentCursor = hCursor;
2897 hCurrentCursor = hBummer;
2898 lpDragInfo->hScope = 0;
2900 if( hCurrentCursor )
2901 SetCursor(hCurrentCursor);
2903 /* send WM_DRAGLOOP */
2904 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
2905 (LPARAM) spDragInfo );
2906 /* send WM_DRAGSELECT or WM_DRAGMOVE */
2907 if( hCurrentWnd != lpDragInfo->hScope )
2910 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
2911 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
2912 HIWORD(spDragInfo)) );
2913 hCurrentWnd = lpDragInfo->hScope;
2915 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
2919 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
2921 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
2924 ShowCursor( FALSE );
2928 SetCursor( hOldCursor );
2929 if (hDragCursor) DestroyCursor( hDragCursor );
2932 if( hCurrentCursor != hBummer )
2933 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
2934 (WPARAM16)hWnd, (LPARAM)spDragInfo );
2937 GlobalFree16(hDragInfo);
2939 return (DWORD)(msg.lParam);
2943 /******************************************************************************
2944 * GetWindowModuleFileNameA (USER32.@)
2946 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
2948 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
2949 hwnd, lpszFileName, cchFileNameMax);
2953 /******************************************************************************
2954 * GetWindowModuleFileNameW (USER32.@)
2956 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
2958 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
2959 hwnd, lpszFileName, cchFileNameMax);