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 );
552 PROPERTY_RemoveWindowProps( hwnd );
554 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return;
555 wndPtr->hmemTaskQ = 0;
557 if (!(wndPtr->dwStyle & WS_CHILD))
560 DestroyMenu( wndPtr->wIDmenu );
563 if (wndPtr->hSysMenu)
565 DestroyMenu( wndPtr->hSysMenu );
566 wndPtr->hSysMenu = 0;
568 USER_Driver.pDestroyWindow( hwnd );
569 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
570 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
571 CLASS_RemoveWindow( wndPtr->class );
572 wndPtr->class = NULL;
573 wndPtr->dwMagic = 0; /* Mark it as invalid */
574 WIN_ReleaseWndPtr( wndPtr );
577 /***********************************************************************
578 * WIN_DestroyThreadWindows
580 * Destroy all children of 'wnd' owned by the current thread.
581 * Return TRUE if something was done.
583 void WIN_DestroyThreadWindows( HWND hwnd )
588 if (!(list = WIN_ListChildren( hwnd ))) return;
589 for (i = 0; list[i]; i++)
591 if (!IsWindow( list[i] )) continue;
592 if (WIN_IsCurrentThread( list[i] ))
593 DestroyWindow( list[i] );
595 WIN_DestroyThreadWindows( list[i] );
597 HeapFree( GetProcessHeap(), 0, list );
600 /***********************************************************************
601 * WIN_CreateDesktopWindow
603 * Create the desktop window.
605 BOOL WIN_CreateDesktopWindow(void)
607 struct tagCLASS *class;
615 TRACE("Creating desktop window\n");
618 if (!WINPOS_CreateInternalPosAtom() ||
619 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
620 &wndExtra, &winproc, &clsStyle, &dce )))
623 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM),
624 sizeof(WND) + wndExtra - sizeof(pWndDesktop->wExtra) );
625 if (!pWndDesktop) return FALSE;
626 hwndDesktop = pWndDesktop->hwndSelf;
628 pWndDesktop->tid = 0; /* nobody owns the desktop */
629 pWndDesktop->parent = 0;
630 pWndDesktop->owner = 0;
631 pWndDesktop->class = class;
632 pWndDesktop->hInstance = 0;
633 pWndDesktop->rectWindow.left = 0;
634 pWndDesktop->rectWindow.top = 0;
635 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
636 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
637 pWndDesktop->rectClient = pWndDesktop->rectWindow;
638 pWndDesktop->text = NULL;
639 pWndDesktop->hmemTaskQ = 0;
640 pWndDesktop->hrgnUpdate = 0;
641 pWndDesktop->hwndLastActive = hwndDesktop;
642 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
644 pWndDesktop->dwExStyle = 0;
645 pWndDesktop->clsStyle = clsStyle;
646 pWndDesktop->dce = NULL;
647 pWndDesktop->pVScroll = NULL;
648 pWndDesktop->pHScroll = NULL;
649 pWndDesktop->pProp = NULL;
650 pWndDesktop->wIDmenu = 0;
651 pWndDesktop->helpContext = 0;
652 pWndDesktop->flags = 0;
653 pWndDesktop->hSysMenu = 0;
654 pWndDesktop->userdata = 0;
655 pWndDesktop->winproc = winproc;
656 pWndDesktop->cbWndExtra = wndExtra;
658 cs.lpCreateParams = NULL;
664 cs.cx = pWndDesktop->rectWindow.right;
665 cs.cy = pWndDesktop->rectWindow.bottom;
666 cs.style = pWndDesktop->dwStyle;
667 cs.dwExStyle = pWndDesktop->dwExStyle;
669 cs.lpszClass = DESKTOP_CLASS_ATOM;
671 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE )) return FALSE;
673 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
674 WIN_ReleaseWndPtr( pWndDesktop );
679 /***********************************************************************
682 * Fix the coordinates - Helper for WIN_CreateWindowEx.
683 * returns default show mode in sw.
684 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
686 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
688 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
689 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
691 if (cs->style & (WS_CHILD | WS_POPUP))
693 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
694 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
696 else /* overlapped window */
700 GetStartupInfoA( &info );
702 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
704 /* Never believe Microsoft's documentation... CreateWindowEx doc says
705 * that if an overlapped window is created with WS_VISIBLE style bit
706 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
707 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
710 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
711 * 2) it does not ignore the y parameter as the docs claim; instead, it
712 * uses it as second parameter to ShowWindow() unless y is either
713 * CW_USEDEFAULT or CW_USEDEFAULT16.
715 * The fact that we didn't do 2) caused bogus windows pop up when wine
716 * was running apps that were using this obscure feature. Example -
717 * calc.exe that comes with Win98 (only Win98, it's different from
718 * the one that comes with Win95 and NT)
720 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
721 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
722 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
725 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
727 if (info.dwFlags & STARTF_USESIZE)
729 cs->cx = info.dwXSize;
730 cs->cy = info.dwYSize;
732 else /* if no other hint from the app, pick 3/4 of the screen real estate */
735 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
736 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
737 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
744 /***********************************************************************
747 * Implementation of CreateWindowEx().
749 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
750 WINDOWPROCTYPE type )
753 struct tagCLASS *classPtr;
755 HWND hwnd, hwndLinkAfter, parent, owner;
756 POINT maxSize, maxPos, minTrack, maxTrack;
761 BOOL unicode = (type == WIN_PROC_32W);
763 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%04x menu=%04x inst=%08x params=%p\n",
764 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
765 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
766 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
767 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
769 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
770 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
772 /* Find the parent window */
774 parent = GetDesktopWindow();
778 /* Make sure parent is valid */
779 if (!IsWindow( cs->hwndParent ))
781 WARN("Bad parent %04x\n", cs->hwndParent );
784 if (cs->style & WS_CHILD)
786 parent = WIN_GetFullHandle(cs->hwndParent);
787 if (!WIN_IsCurrentProcess(parent))
789 FIXME( "creating child window of %x in other process not supported yet\n",
794 else owner = GetAncestor( cs->hwndParent, GA_ROOT );
796 else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP))
798 WARN("No parent for child window\n" );
799 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
802 /* Find the window class */
803 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
804 &wndExtra, &winproc, &clsStyle, &dce )))
806 WARN("Bad class '%s'\n", cs->lpszClass );
810 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
812 /* Correct the window style - stage 1
814 * These are patches that appear to affect both the style loaded into the
815 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
817 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
818 * why does the user get to set it?
821 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
822 * tested for WS_POPUP
824 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
825 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
826 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
827 cs->dwExStyle |= WS_EX_WINDOWEDGE;
829 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
831 /* Create the window structure */
833 if (!(wndPtr = create_window_handle( parent, owner, classAtom,
834 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
836 TRACE("out of memory\n" );
839 hwnd = wndPtr->hwndSelf;
841 /* Fill the window structure */
843 wndPtr->tid = GetCurrentThreadId();
844 wndPtr->owner = owner;
845 wndPtr->parent = parent;
846 wndPtr->class = classPtr;
847 wndPtr->winproc = winproc;
848 wndPtr->hInstance = cs->hInstance;
850 wndPtr->hmemTaskQ = InitThreadInput16( 0, 0 );
851 wndPtr->hrgnUpdate = 0;
853 wndPtr->hwndLastActive = hwnd;
854 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
855 wndPtr->dwExStyle = cs->dwExStyle;
856 wndPtr->clsStyle = clsStyle;
858 wndPtr->helpContext = 0;
859 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
860 wndPtr->pVScroll = NULL;
861 wndPtr->pHScroll = NULL;
862 wndPtr->pProp = NULL;
863 wndPtr->userdata = 0;
864 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
865 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
866 wndPtr->cbWndExtra = wndExtra;
868 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
870 /* Call the WH_CBT hook */
872 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
873 ? HWND_BOTTOM : HWND_TOP;
875 if (HOOK_IsHooked( WH_CBT ))
881 cbtc.hwndInsertAfter = hwndLinkAfter;
882 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND,
883 (WPARAM)hwnd, (LPARAM)&cbtc)
884 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND,
885 (WPARAM)hwnd, (LPARAM)&cbtc);
888 TRACE("CBT-hook returned 0\n");
889 free_window_handle( hwnd );
890 CLASS_RemoveWindow( classPtr );
896 /* Correct the window style - stage 2 */
898 if (!(cs->style & WS_CHILD))
900 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
901 if (!(cs->style & WS_POPUP))
903 wndPtr->dwStyle |= WS_CAPTION;
904 wndPtr->flags |= WIN_NEED_SIZE;
908 /* Get class or window DC if needed */
910 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
911 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
912 else wndPtr->dce = NULL;
914 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
916 wndPtr->rectWindow.left = cs->x;
917 wndPtr->rectWindow.top = cs->y;
918 wndPtr->rectWindow.right = cs->x + cs->cx;
919 wndPtr->rectWindow.bottom = cs->y + cs->cy;
920 wndPtr->rectClient = wndPtr->rectWindow;
922 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
924 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
926 WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
927 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
928 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
929 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
930 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
933 if (cs->cx < 0) cs->cx = 0;
934 if (cs->cy < 0) cs->cy = 0;
936 wndPtr->rectWindow.left = cs->x;
937 wndPtr->rectWindow.top = cs->y;
938 wndPtr->rectWindow.right = cs->x + cs->cx;
939 wndPtr->rectWindow.bottom = cs->y + cs->cy;
940 wndPtr->rectClient = wndPtr->rectWindow;
942 /* Set the window menu */
944 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
946 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
949 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
952 if (HIWORD(cs->hInstance))
953 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
955 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
957 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
961 else wndPtr->wIDmenu = (UINT)cs->hMenu;
963 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
965 WARN("aborted by WM_xxCREATE!\n");
966 WIN_ReleaseWndPtr( wndPtr );
967 WIN_DestroyWindow( hwnd );
968 CLASS_RemoveWindow( classPtr );
972 if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
974 /* Notify the parent window only */
976 SendMessageA( wndPtr->parent, WM_PARENTNOTIFY,
977 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
978 if( !IsWindow(hwnd) )
985 if (cs->style & WS_VISIBLE)
987 /* in case WS_VISIBLE got set in the meantime */
988 wndPtr->dwStyle &= ~WS_VISIBLE;
989 ShowWindow( hwnd, sw );
992 /* Call WH_SHELL hook */
994 if (!(wndPtr->dwStyle & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
995 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0 );
997 TRACE("created window %04x\n", hwnd);
999 WIN_ReleaseWndPtr(wndPtr);
1004 /***********************************************************************
1005 * CreateWindow (USER.41)
1007 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1008 DWORD style, INT16 x, INT16 y, INT16 width,
1009 INT16 height, HWND16 parent, HMENU16 menu,
1010 HINSTANCE16 instance, LPVOID data )
1012 return CreateWindowEx16( 0, className, windowName, style,
1013 x, y, width, height, parent, menu, instance, data );
1017 /***********************************************************************
1018 * CreateWindowEx (USER.452)
1020 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1021 LPCSTR windowName, DWORD style, INT16 x,
1022 INT16 y, INT16 width, INT16 height,
1023 HWND16 parent, HMENU16 menu,
1024 HINSTANCE16 instance, LPVOID data )
1030 /* Find the class atom */
1032 if (HIWORD(className))
1034 if (!(classAtom = GlobalFindAtomA( className )))
1036 ERR( "bad class name %s\n", debugres_a(className) );
1042 classAtom = LOWORD(className);
1043 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1045 ERR( "bad atom %x\n", classAtom);
1051 /* Fix the coordinates */
1053 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1054 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1055 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1056 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1058 /* Create the window */
1060 cs.lpCreateParams = data;
1061 cs.hInstance = (HINSTANCE)instance;
1062 cs.hMenu = (HMENU)menu;
1063 cs.hwndParent = WIN_Handle32( parent );
1065 cs.lpszName = windowName;
1066 cs.lpszClass = className;
1067 cs.dwExStyle = exStyle;
1069 return WIN_Handle16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1073 /***********************************************************************
1074 * CreateWindowExA (USER32.@)
1076 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1077 LPCSTR windowName, DWORD style, INT x,
1078 INT y, INT width, INT height,
1079 HWND parent, HMENU menu,
1080 HINSTANCE instance, LPVOID data )
1087 instance=GetModuleHandleA(NULL);
1089 if(exStyle & WS_EX_MDICHILD)
1090 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1092 /* Find the class atom */
1094 if (HIWORD(className))
1096 if (!(classAtom = GlobalFindAtomA( className )))
1098 ERR( "bad class name %s\n", debugres_a(className) );
1104 classAtom = LOWORD(className);
1105 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1107 ERR( "bad atom %x\n", classAtom);
1113 /* Create the window */
1115 cs.lpCreateParams = data;
1116 cs.hInstance = instance;
1118 cs.hwndParent = parent;
1124 cs.lpszName = windowName;
1125 cs.lpszClass = className;
1126 cs.dwExStyle = exStyle;
1128 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1132 /***********************************************************************
1133 * CreateWindowExW (USER32.@)
1135 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1136 LPCWSTR windowName, DWORD style, INT x,
1137 INT y, INT width, INT height,
1138 HWND parent, HMENU menu,
1139 HINSTANCE instance, LPVOID data )
1146 instance=GetModuleHandleA(NULL);
1148 if(exStyle & WS_EX_MDICHILD)
1149 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1151 /* Find the class atom */
1153 if (HIWORD(className))
1155 if (!(classAtom = GlobalFindAtomW( className )))
1157 ERR( "bad class name %s\n", debugres_w(className) );
1163 classAtom = LOWORD(className);
1164 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1166 ERR( "bad atom %x\n", classAtom);
1172 /* Create the window */
1174 cs.lpCreateParams = data;
1175 cs.hInstance = instance;
1177 cs.hwndParent = parent;
1183 cs.lpszName = windowName;
1184 cs.lpszClass = className;
1185 cs.dwExStyle = exStyle;
1187 /* Note: we rely on the fact that CREATESTRUCTA and */
1188 /* CREATESTRUCTW have the same layout. */
1189 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1193 /***********************************************************************
1194 * WIN_SendDestroyMsg
1196 static void WIN_SendDestroyMsg( HWND hwnd )
1198 if( CARET_GetHwnd() == hwnd) DestroyCaret();
1199 if (USER_Driver.pResetSelectionOwner)
1200 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1203 * Send the WM_DESTROY to the window.
1205 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1208 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1209 * make sure that the window still exists when we come back.
1216 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1218 /* start from the end (FIXME: is this needed?) */
1219 for (i = 0; pWndArray[i]; i++) ;
1223 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1225 HeapFree( GetProcessHeap(), 0, pWndArray );
1228 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1232 /***********************************************************************
1233 * DestroyWindow (USER32.@)
1235 BOOL WINAPI DestroyWindow( HWND hwnd )
1241 hwnd = WIN_GetFullHandle( hwnd );
1242 TRACE("(%04x)\n", hwnd);
1244 /* Initialization */
1246 if (hwnd == GetDesktopWindow()) return FALSE; /* Can't destroy desktop */
1248 /* Look whether the focus is within the tree of windows we will
1252 if (h == hwnd || IsChild( hwnd, h ))
1254 HWND parent = GetAncestor( hwnd, GA_PARENT );
1255 if (parent == GetDesktopWindow()) parent = 0;
1261 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0L) ) return FALSE;
1263 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1264 if (!(wndPtr->dwStyle & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1266 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L );
1267 /* FIXME: clean up palette - see "Internals" p.352 */
1270 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1271 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1273 /* Notify the parent window only */
1274 SendMessageA( wndPtr->parent, WM_PARENTNOTIFY,
1275 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1276 if( !IsWindow(hwnd) )
1283 if (USER_Driver.pResetSelectionOwner)
1284 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1286 /* Hide the window */
1288 ShowWindow( hwnd, SW_HIDE );
1289 if (!IsWindow(hwnd))
1295 /* Recursively destroy owned windows */
1297 if( !(wndPtr->dwStyle & WS_CHILD) )
1304 HWND *list = WIN_ListChildren( wndPtr->parent );
1307 for (i = 0; list[i]; i++)
1310 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1311 if (!(siblingPtr = WIN_FindWndPtr( list[i] ))) continue;
1312 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1314 WIN_ReleaseWndPtr( siblingPtr );
1315 DestroyWindow( list[i] );
1319 else siblingPtr->owner = 0;
1320 WIN_ReleaseWndPtr( siblingPtr );
1322 HeapFree( GetProcessHeap(), 0, list );
1324 if (!got_one) break;
1327 WINPOS_ActivateOtherWindow( hwnd );
1329 if ((owner = GetWindow( hwnd, GW_OWNER )))
1331 WND *ptr = WIN_FindWndPtr( owner );
1334 if (ptr->hwndLastActive == hwnd) ptr->hwndLastActive = owner;
1335 WIN_ReleaseWndPtr( ptr );
1340 /* Send destroy messages */
1342 WIN_SendDestroyMsg( hwnd );
1343 if (!IsWindow(hwnd))
1349 /* Unlink now so we won't bother with the children later on */
1351 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1353 /* Destroy the window storage */
1355 WIN_DestroyWindow( hwnd );
1358 WIN_ReleaseWndPtr(wndPtr);
1363 /***********************************************************************
1364 * CloseWindow (USER32.@)
1366 BOOL WINAPI CloseWindow( HWND hwnd )
1368 WND * wndPtr = WIN_FindWndPtr( hwnd );
1371 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1376 ShowWindow( hwnd, SW_MINIMIZE );
1379 WIN_ReleaseWndPtr(wndPtr);
1385 /***********************************************************************
1386 * OpenIcon (USER32.@)
1388 BOOL WINAPI OpenIcon( HWND hwnd )
1390 if (!IsIconic( hwnd )) return FALSE;
1391 ShowWindow( hwnd, SW_SHOWNORMAL );
1396 /***********************************************************************
1399 * Implementation of FindWindow() and FindWindowEx().
1401 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1406 WCHAR *buffer = NULL;
1408 if (!parent) parent = GetDesktopWindow();
1411 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1412 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1415 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1419 child = WIN_GetFullHandle( child );
1420 while (list[i] && list[i] != child) i++;
1421 if (!list[i]) goto done;
1422 i++; /* start from next window */
1429 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1436 if (list) HeapFree( GetProcessHeap(), 0, list );
1437 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1443 /***********************************************************************
1444 * FindWindowA (USER32.@)
1446 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1448 HWND ret = FindWindowExA( 0, 0, className, title );
1449 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1454 /***********************************************************************
1455 * FindWindowExA (USER32.@)
1457 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1458 LPCSTR className, LPCSTR title )
1466 /* If the atom doesn't exist, then no class */
1467 /* with this name exists either. */
1468 if (!(atom = GlobalFindAtomA( className )))
1470 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1475 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1476 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1477 HeapFree( GetProcessHeap(), 0, buffer );
1482 /***********************************************************************
1483 * FindWindowExW (USER32.@)
1485 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1486 LPCWSTR className, LPCWSTR title )
1492 /* If the atom doesn't exist, then no class */
1493 /* with this name exists either. */
1494 if (!(atom = GlobalFindAtomW( className )))
1496 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1500 return WIN_FindWindow( parent, child, atom, title );
1504 /***********************************************************************
1505 * FindWindowW (USER32.@)
1507 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1509 return FindWindowExW( 0, 0, className, title );
1513 /**********************************************************************
1514 * GetDesktopWindow (USER32.@)
1516 HWND WINAPI GetDesktopWindow(void)
1518 if (pWndDesktop) return pWndDesktop->hwndSelf;
1519 ERR( "You need the -desktop option when running with native USER\n" );
1525 /*******************************************************************
1526 * EnableWindow (USER32.@)
1528 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1533 TRACE("( %x, %d )\n", hwnd, enable);
1535 if (USER_Driver.pEnableWindow)
1536 return USER_Driver.pEnableWindow( hwnd, enable );
1538 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1539 hwnd = wndPtr->hwndSelf; /* make it a full handle */
1541 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1543 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1545 wndPtr->dwStyle &= ~WS_DISABLED; /* Enable window */
1546 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1548 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1550 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1552 wndPtr->dwStyle |= WS_DISABLED; /* Disable window */
1554 if (hwnd == GetFocus())
1555 SetFocus( 0 ); /* A disabled window can't have the focus */
1557 if (hwnd == GetCapture())
1558 ReleaseCapture(); /* A disabled window can't capture the mouse */
1560 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1562 WIN_ReleaseWndPtr(wndPtr);
1567 /***********************************************************************
1568 * IsWindowEnabled (USER32.@)
1570 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1575 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1576 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1577 WIN_ReleaseWndPtr(wndPtr);
1583 /***********************************************************************
1584 * IsWindowUnicode (USER32.@)
1586 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1591 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1592 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1593 WIN_ReleaseWndPtr(wndPtr);
1598 /**********************************************************************
1599 * GetWindowWord (USER32.@)
1601 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1604 WND * wndPtr = WIN_FindWndPtr( hwnd );
1605 if (!wndPtr) return 0;
1608 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1610 WARN("Invalid offset %d\n", offset );
1613 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1614 WIN_ReleaseWndPtr(wndPtr);
1618 WIN_ReleaseWndPtr(wndPtr);
1621 case GWL_HWNDPARENT:
1622 return GetWindowLongW( hwnd, offset );
1626 LONG ret = GetWindowLongW( hwnd, offset );
1628 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1632 WARN("Invalid offset %d\n", offset );
1638 /**********************************************************************
1639 * SetWindowWord (USER32.@)
1641 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1644 WND * wndPtr = WIN_FindWndPtr( hwnd );
1645 if (!wndPtr) return 0;
1648 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1650 WARN("Invalid offset %d\n", offset );
1651 WIN_ReleaseWndPtr(wndPtr);
1654 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1657 WIN_ReleaseWndPtr(wndPtr);
1661 WIN_ReleaseWndPtr(wndPtr);
1666 case GWL_HWNDPARENT:
1667 return SetWindowLongW( hwnd, offset, (UINT)newval );
1669 WARN("Invalid offset %d\n", offset );
1675 /**********************************************************************
1678 * Helper function for GetWindowLong().
1680 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1683 WND * wndPtr = WIN_FindWndPtr( hwnd );
1684 if (!wndPtr) return 0;
1687 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1689 WARN("Invalid offset %d\n", offset );
1693 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1694 /* Special case for dialog window procedure */
1695 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1697 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1704 case GWL_USERDATA: retvalue = wndPtr->userdata;
1706 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1708 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1710 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1712 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1715 case GWL_HWNDPARENT: retvalue = (LONG)GetParent(hwnd);
1717 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1720 WARN("Unknown offset %d\n", offset );
1724 WIN_ReleaseWndPtr(wndPtr);
1729 /**********************************************************************
1732 * Helper function for SetWindowLong().
1734 * 0 is the failure code. However, in the case of failure SetLastError
1735 * must be set to distinguish between a 0 return value and a failure.
1737 * FIXME: The error values for SetLastError may not be right. Can
1738 * someone check with the real thing?
1740 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1741 WINDOWPROCTYPE type )
1744 WND * wndPtr = WIN_FindWndPtr( hwnd );
1747 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1751 /* Is this the right error? */
1752 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1758 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1760 WARN("Invalid offset %d\n", offset );
1762 /* Is this the right error? */
1763 SetLastError( ERROR_OUTOFMEMORY );
1768 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1769 /* Special case for dialog window procedure */
1770 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1772 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1773 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1774 type, WIN_PROC_WINDOW );
1781 ptr = (DWORD*)&wndPtr->wIDmenu;
1784 ptr = (DWORD*)&wndPtr->hInstance;
1787 ptr = &wndPtr->userdata;
1789 case GWL_HWNDPARENT:
1790 retval = SetParent( hwnd, (HWND)newval );
1793 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1794 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1795 type, WIN_PROC_WINDOW );
1798 retval = wndPtr->dwStyle;
1799 style.styleOld = wndPtr->dwStyle;
1800 style.styleNew = newval;
1801 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1802 wndPtr->dwStyle = style.styleNew;
1803 if (USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, retval );
1804 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1805 retval = style.styleOld;
1808 style.styleOld = wndPtr->dwExStyle;
1809 style.styleNew = newval;
1810 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1811 wndPtr->dwExStyle = style.styleNew;
1812 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1813 retval = style.styleOld;
1817 WARN("Invalid offset %d\n", offset );
1819 /* Don't think this is right error but it should do */
1820 SetLastError( ERROR_OUTOFMEMORY );
1828 WIN_ReleaseWndPtr(wndPtr);
1833 /**********************************************************************
1834 * GetWindowLong (USER.135)
1836 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1838 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
1842 /**********************************************************************
1843 * GetWindowLongA (USER32.@)
1845 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
1847 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1851 /**********************************************************************
1852 * GetWindowLongW (USER32.@)
1854 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
1856 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1860 /**********************************************************************
1861 * SetWindowLong (USER.136)
1863 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1865 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
1869 /**********************************************************************
1870 * SetWindowLongA (USER32.@)
1872 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
1874 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1878 /**********************************************************************
1879 * SetWindowLongW (USER32.@) Set window attribute
1881 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
1882 * value in a window's extra memory.
1884 * The _hwnd_ parameter specifies the window. is the handle to a
1885 * window that has extra memory. The _newval_ parameter contains the
1886 * new attribute or extra memory value. If positive, the _offset_
1887 * parameter is the byte-addressed location in the window's extra
1888 * memory to set. If negative, _offset_ specifies the window
1889 * attribute to set, and should be one of the following values:
1891 * GWL_EXSTYLE The window's extended window style
1893 * GWL_STYLE The window's window style.
1895 * GWL_WNDPROC Pointer to the window's window procedure.
1897 * GWL_HINSTANCE The window's pplication instance handle.
1899 * GWL_ID The window's identifier.
1901 * GWL_USERDATA The window's user-specified data.
1903 * If the window is a dialog box, the _offset_ parameter can be one of
1904 * the following values:
1906 * DWL_DLGPROC The address of the window's dialog box procedure.
1908 * DWL_MSGRESULT The return value of a message
1909 * that the dialog box procedure processed.
1911 * DWL_USER Application specific information.
1915 * If successful, returns the previous value located at _offset_. Otherwise,
1920 * Extra memory for a window class is specified by a nonzero cbWndExtra
1921 * parameter of the WNDCLASS structure passed to RegisterClass() at the
1922 * time of class creation.
1924 * Using GWL_WNDPROC to set a new window procedure effectively creates
1925 * a window subclass. Use CallWindowProc() in the new windows procedure
1926 * to pass messages to the superclass's window procedure.
1928 * The user data is reserved for use by the application which created
1931 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
1932 * instead, call the EnableWindow() function to change the window's
1935 * Do not use GWL_HWNDPARENT to reset the window's parent, use
1936 * SetParent() instead.
1939 * When offset is GWL_STYLE and the calling app's ver is 4.0,
1940 * it sends WM_STYLECHANGING before changing the settings
1941 * and WM_STYLECHANGED afterwards.
1942 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
1946 * GWL_STYLE does not dispatch WM_STYLE... messages.
1953 LONG WINAPI SetWindowLongW(
1954 HWND hwnd, /* [in] window to alter */
1955 INT offset, /* [in] offset, in bytes, of location to alter */
1956 LONG newval /* [in] new value of location */
1958 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1962 /*******************************************************************
1963 * GetWindowTextA (USER32.@)
1965 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
1967 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
1971 /*******************************************************************
1972 * InternalGetWindowText (USER32.@)
1974 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
1976 WND *win = WIN_FindWndPtr( hwnd );
1978 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
1979 else lpString[0] = 0;
1980 WIN_ReleaseWndPtr( win );
1981 return strlenW(lpString);
1985 /*******************************************************************
1986 * GetWindowTextW (USER32.@)
1988 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
1990 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
1995 /*******************************************************************
1996 * SetWindowText (USER32.@)
1997 * SetWindowTextA (USER32.@)
1999 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2001 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2005 /*******************************************************************
2006 * SetWindowTextW (USER32.@)
2008 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2010 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2014 /*******************************************************************
2015 * GetWindowTextLengthA (USER32.@)
2017 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2019 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2022 /*******************************************************************
2023 * GetWindowTextLengthW (USER32.@)
2025 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2027 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2031 /*******************************************************************
2032 * IsWindow (USER32.@)
2034 BOOL WINAPI IsWindow( HWND hwnd )
2039 if ((ptr = WIN_GetWndPtr( hwnd )))
2041 if (ptr == BAD_WND_PTR) return FALSE;
2046 /* check other processes */
2047 SERVER_START_REQ( get_window_info )
2050 ret = !SERVER_CALL_ERR();
2057 /***********************************************************************
2058 * GetWindowThreadProcessId (USER32.@)
2060 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2065 if ((ptr = WIN_GetWndPtr( hwnd )))
2067 if (ptr != BAD_WND_PTR)
2069 /* got a valid window */
2071 if (process) *process = GetCurrentProcessId();
2074 else SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2078 /* check other processes */
2079 SERVER_START_REQ( get_window_info )
2082 if (!SERVER_CALL_ERR())
2084 tid = (DWORD)req->tid;
2085 if (process) *process = (DWORD)req->pid;
2093 /*****************************************************************
2094 * GetParent (USER32.@)
2096 HWND WINAPI GetParent( HWND hwnd )
2101 if ((wndPtr = WIN_FindWndPtr(hwnd)))
2103 if (wndPtr->dwStyle & WS_CHILD)
2104 retvalue = wndPtr->parent;
2105 else if (wndPtr->dwStyle & WS_POPUP)
2106 retvalue = wndPtr->owner;
2107 WIN_ReleaseWndPtr(wndPtr);
2113 /*****************************************************************
2114 * GetAncestor (USER32.@)
2116 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2119 size_t size = (type == GA_PARENT) ? sizeof(user_handle_t) : REQUEST_MAX_VAR_SIZE;
2121 SERVER_START_VAR_REQ( get_window_parents, size )
2126 user_handle_t *data = server_data_ptr(req);
2127 int count = server_data_size(req) / sizeof(*data);
2137 if (count > 1) ret = data[count - 2]; /* get the one before the desktop */
2138 else ret = WIN_GetFullHandle( hwnd );
2146 if (ret && type == GA_ROOTOWNER)
2150 HWND owner = GetWindow( ret, GW_OWNER );
2159 /*****************************************************************
2160 * SetParent (USER32.@)
2162 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2168 if (!parent) parent = GetDesktopWindow();
2169 else parent = WIN_GetFullHandle( parent );
2172 if (WIN_GetFullHandle(hwnd) == GetDesktopWindow() || !IsWindow( parent ))
2174 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2178 if (USER_Driver.pSetParent)
2179 return USER_Driver.pSetParent( hwnd, parent );
2181 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2183 dwStyle = wndPtr->dwStyle;
2185 /* Windows hides the window first, then shows it again
2186 * including the WM_SHOWWINDOW messages and all */
2187 if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
2189 retvalue = wndPtr->parent; /* old parent */
2190 if (parent != retvalue)
2192 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2194 if (parent != GetDesktopWindow()) /* a child window */
2196 if (!(dwStyle & WS_CHILD))
2198 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2199 if (menu) DestroyMenu( menu );
2203 WIN_ReleaseWndPtr( wndPtr );
2205 /* SetParent additionally needs to make hwnd the topmost window
2206 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2207 WM_WINDOWPOSCHANGED notification messages.
2209 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2210 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|
2211 ((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2212 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2213 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2218 /*******************************************************************
2219 * IsChild (USER32.@)
2221 BOOL WINAPI IsChild( HWND parent, HWND child )
2223 HWND *list = WIN_ListParents( child );
2227 if (!list) return FALSE;
2228 parent = WIN_GetFullHandle( parent );
2229 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2230 ret = (list[i] != 0);
2231 HeapFree( GetProcessHeap(), 0, list );
2236 /***********************************************************************
2237 * IsWindowVisible (USER32.@)
2239 BOOL WINAPI IsWindowVisible( HWND hwnd )
2245 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2246 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2247 for (i = 0; list[i]; i++)
2248 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2250 HeapFree( GetProcessHeap(), 0, list );
2255 /***********************************************************************
2256 * WIN_IsWindowDrawable
2258 * hwnd is drawable when it is visible, all parents are not
2259 * minimized, and it is itself not minimized unless we are
2260 * trying to draw its default class icon.
2262 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2268 if (!(wnd->dwStyle & WS_VISIBLE)) return FALSE;
2269 if ((wnd->dwStyle & WS_MINIMIZE) &&
2270 icon && GetClassLongA( wnd->hwndSelf, GCL_HICON )) return FALSE;
2272 if (!(list = WIN_ListParents( wnd->hwndSelf ))) return TRUE;
2273 for (i = 0; list[i]; i++)
2274 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2277 HeapFree( GetProcessHeap(), 0, list );
2282 /*******************************************************************
2283 * GetTopWindow (USER32.@)
2285 HWND WINAPI GetTopWindow( HWND hwnd )
2287 if (!hwnd) hwnd = GetDesktopWindow();
2288 return GetWindow( hwnd, GW_CHILD );
2292 /*******************************************************************
2293 * GetWindow (USER32.@)
2295 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2299 if (rel == GW_OWNER) /* special case: not fully supported in the server yet */
2301 WND *wndPtr = WIN_FindWndPtr( hwnd );
2302 if (!wndPtr) return 0;
2303 retval = wndPtr->owner;
2304 WIN_ReleaseWndPtr( wndPtr );
2308 SERVER_START_REQ( get_window_tree )
2311 if (!SERVER_CALL_ERR())
2316 retval = req->first_sibling;
2319 retval = req->last_sibling;
2322 retval = req->next_sibling;
2325 retval = req->prev_sibling;
2328 retval = req->first_child;
2338 /***********************************************************************
2339 * WIN_InternalShowOwnedPopups
2341 * Internal version of ShowOwnedPopups; Wine functions should use this
2342 * to avoid interfering with application calls to ShowOwnedPopups
2343 * and to make sure the application can't prevent showing/hiding.
2345 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2349 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2353 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2355 if (!win_array) return TRUE;
2358 * Show windows Lowest first, Highest last to preserve Z-Order
2360 while (win_array[count]) count++;
2361 while (--count >= 0)
2363 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2364 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2366 if (pWnd->dwStyle & WS_POPUP)
2370 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2371 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2374 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2376 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2377 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2382 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2383 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2384 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2387 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2389 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2390 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2391 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2395 WIN_ReleaseWndPtr( pWnd );
2397 HeapFree( GetProcessHeap(), 0, win_array );
2402 /*******************************************************************
2403 * ShowOwnedPopups (USER32.@)
2405 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2409 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2411 if (!win_array) return TRUE;
2413 while (win_array[count]) count++;
2414 while (--count >= 0)
2416 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2417 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2419 if (pWnd->dwStyle & WS_POPUP)
2423 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2425 /* In Windows, ShowOwnedPopups(TRUE) generates
2426 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2427 * regardless of the state of the owner
2429 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2430 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2435 if (IsWindowVisible(pWnd->hwndSelf))
2437 /* In Windows, ShowOwnedPopups(FALSE) generates
2438 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2439 * regardless of the state of the owner
2441 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2442 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2446 WIN_ReleaseWndPtr( pWnd );
2448 HeapFree( GetProcessHeap(), 0, win_array );
2453 /*******************************************************************
2454 * GetLastActivePopup (USER32.@)
2456 HWND WINAPI GetLastActivePopup( HWND hwnd )
2459 WND *wndPtr =WIN_FindWndPtr(hwnd);
2460 if (!wndPtr) return hwnd;
2461 retval = wndPtr->hwndLastActive;
2462 if (!IsWindow( retval )) retval = wndPtr->hwndSelf;
2463 WIN_ReleaseWndPtr(wndPtr);
2468 /*******************************************************************
2471 * Build an array of all parents of a given window, starting with
2472 * the immediate parent. The array must be freed with HeapFree.
2473 * Returns NULL if window is a top-level window.
2475 HWND *WIN_ListParents( HWND hwnd )
2479 SERVER_START_VAR_REQ( get_window_parents, REQUEST_MAX_VAR_SIZE )
2484 user_handle_t *data = server_data_ptr(req);
2485 int i, count = server_data_size(req) / sizeof(*data);
2486 if (count && ((list = HeapAlloc( GetProcessHeap(), 0, (count + 1) * sizeof(HWND) ))))
2488 for (i = 0; i < count; i++) list[i] = data[i];
2498 /*******************************************************************
2501 * Build an array of the children of a given window. The array must be
2502 * freed with HeapFree. Returns NULL when no windows are found.
2504 HWND *WIN_ListChildren( HWND hwnd )
2506 return list_window_children( hwnd, 0, 0 );
2510 /*******************************************************************
2511 * EnumWindows (USER32.@)
2513 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2519 /* We have to build a list of all windows first, to avoid */
2520 /* unpleasant side-effects, for instance if the callback */
2521 /* function changes the Z-order of the windows. */
2523 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return FALSE;
2525 /* Now call the callback function for every window */
2527 iWndsLocks = WIN_SuspendWndsLock();
2528 for (i = 0; list[i]; i++)
2530 /* Make sure that the window still exists */
2531 if (!IsWindow( list[i] )) continue;
2532 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2534 WIN_RestoreWndsLock(iWndsLocks);
2535 HeapFree( GetProcessHeap(), 0, list );
2540 /**********************************************************************
2541 * EnumTaskWindows16 (USER.225)
2543 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2546 TDB *tdb = TASK_GetPtr( hTask );
2547 if (!tdb) return FALSE;
2548 return EnumThreadWindows( (DWORD)tdb->teb->tid, (WNDENUMPROC)func, lParam );
2552 /**********************************************************************
2553 * EnumThreadWindows (USER32.@)
2555 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2560 if (!(list = list_window_children( GetDesktopWindow(), 0, GetCurrentThreadId() )))
2563 /* Now call the callback function for every window */
2565 iWndsLocks = WIN_SuspendWndsLock();
2566 for (i = 0; list[i]; i++)
2567 if (!func( list[i], lParam )) break;
2568 WIN_RestoreWndsLock(iWndsLocks);
2569 HeapFree( GetProcessHeap(), 0, list );
2574 /**********************************************************************
2575 * WIN_EnumChildWindows
2577 * Helper function for EnumChildWindows().
2579 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2584 for ( ; *list; list++)
2586 /* Make sure that the window still exists */
2587 if (!IsWindow( *list )) continue;
2588 /* skip owned windows */
2589 if (GetWindow( *list, GW_OWNER )) continue;
2590 /* Build children list first */
2591 childList = WIN_ListChildren( *list );
2593 ret = func( *list, lParam );
2597 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2598 HeapFree( GetProcessHeap(), 0, childList );
2600 if (!ret) return FALSE;
2606 /**********************************************************************
2607 * EnumChildWindows (USER32.@)
2609 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2614 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2615 iWndsLocks = WIN_SuspendWndsLock();
2616 WIN_EnumChildWindows( list, func, lParam );
2617 WIN_RestoreWndsLock(iWndsLocks);
2618 HeapFree( GetProcessHeap(), 0, list );
2623 /*******************************************************************
2624 * AnyPopup (USER.52)
2626 BOOL16 WINAPI AnyPopup16(void)
2632 /*******************************************************************
2633 * AnyPopup (USER32.@)
2635 BOOL WINAPI AnyPopup(void)
2639 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2641 if (!list) return FALSE;
2642 for (i = 0; list[i]; i++)
2644 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2646 retvalue = (list[i] != 0);
2647 HeapFree( GetProcessHeap(), 0, list );
2652 /*******************************************************************
2653 * FlashWindow (USER32.@)
2655 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2657 WND *wndPtr = WIN_FindWndPtr(hWnd);
2659 TRACE("%04x\n", hWnd);
2661 if (!wndPtr) return FALSE;
2662 hWnd = wndPtr->hwndSelf; /* make it a full handle */
2664 if (wndPtr->dwStyle & WS_MINIMIZE)
2666 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2668 HDC hDC = GetDC(hWnd);
2670 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2671 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2673 ReleaseDC( hWnd, hDC );
2674 wndPtr->flags |= WIN_NCACTIVATED;
2678 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2679 wndPtr->flags &= ~WIN_NCACTIVATED;
2681 WIN_ReleaseWndPtr(wndPtr);
2687 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2688 else wparam = (hWnd == GetActiveWindow());
2690 WIN_ReleaseWndPtr(wndPtr);
2691 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2697 /*******************************************************************
2698 * GetWindowContextHelpId (USER32.@)
2700 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2703 WND *wnd = WIN_FindWndPtr( hwnd );
2705 retval = wnd->helpContext;
2706 WIN_ReleaseWndPtr(wnd);
2711 /*******************************************************************
2712 * SetWindowContextHelpId (USER32.@)
2714 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
2716 WND *wnd = WIN_FindWndPtr( hwnd );
2717 if (!wnd) return FALSE;
2718 wnd->helpContext = id;
2719 WIN_ReleaseWndPtr(wnd);
2724 /*******************************************************************
2727 * recursively find a child that contains spDragInfo->pt point
2728 * and send WM_QUERYDROPOBJECT
2730 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
2732 BOOL16 wParam, bResult = 0;
2734 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
2737 if (!ptrDragInfo) return FALSE;
2739 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
2741 GetWindowRect(hQueryWnd,&tempRect);
2743 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
2745 if (!IsIconic( hQueryWnd ))
2747 GetClientRect( hQueryWnd, &tempRect );
2748 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
2750 if (PtInRect( &tempRect, pt))
2753 HWND *list = WIN_ListChildren( hQueryWnd );
2759 for (i = 0; list[i]; i++)
2761 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
2763 GetWindowRect( list[i], &tempRect );
2764 if (PtInRect( &tempRect, pt )) break;
2769 if (IsWindowEnabled( list[i] ))
2770 bResult = DRAG_QueryUpdate( list[i], spDragInfo, bNoSend );
2772 HeapFree( GetProcessHeap(), 0, list );
2774 if(bResult) return bResult;
2780 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
2782 ptrDragInfo->hScope = hQueryWnd;
2784 if (bNoSend) bResult = (GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) != 0;
2785 else bResult = SendMessage16( hQueryWnd, WM_QUERYDROPOBJECT, (WPARAM16)wParam, spDragInfo );
2787 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
2793 /*******************************************************************
2794 * DragDetect (USER32.@)
2796 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
2801 rect.left = pt.x - wDragWidth;
2802 rect.right = pt.x + wDragWidth;
2804 rect.top = pt.y - wDragHeight;
2805 rect.bottom = pt.y + wDragHeight;
2811 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
2813 if( msg.message == WM_LBUTTONUP )
2818 if( msg.message == WM_MOUSEMOVE )
2821 tmp.x = LOWORD(msg.lParam);
2822 tmp.y = HIWORD(msg.lParam);
2823 if( !PtInRect( &rect, tmp ))
2835 /******************************************************************************
2836 * DragObject (USER.464)
2838 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
2839 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
2842 LPDRAGINFO16 lpDragInfo;
2844 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
2845 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
2846 HCURSOR16 hCurrentCursor = 0;
2847 HWND16 hCurrentWnd = 0;
2849 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
2850 spDragInfo = K32WOWGlobalLock16(hDragInfo);
2852 if( !lpDragInfo || !spDragInfo ) return 0L;
2854 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
2856 GlobalFree16(hDragInfo);
2862 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
2864 GlobalFree16(hDragInfo);
2868 if( hDragCursor == hCursor ) hDragCursor = 0;
2869 else hCursor = hDragCursor;
2871 hOldCursor = SetCursor(hDragCursor);
2874 lpDragInfo->hWnd = hWnd;
2875 lpDragInfo->hScope = 0;
2876 lpDragInfo->wFlags = wObj;
2877 lpDragInfo->hList = szList; /* near pointer! */
2878 lpDragInfo->hOfStruct = hOfStruct;
2886 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
2888 *(lpDragInfo+1) = *lpDragInfo;
2890 lpDragInfo->pt.x = msg.pt.x;
2891 lpDragInfo->pt.y = msg.pt.y;
2893 /* update DRAGINFO struct */
2894 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
2896 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
2897 hCurrentCursor = hCursor;
2900 hCurrentCursor = hBummer;
2901 lpDragInfo->hScope = 0;
2903 if( hCurrentCursor )
2904 SetCursor(hCurrentCursor);
2906 /* send WM_DRAGLOOP */
2907 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
2908 (LPARAM) spDragInfo );
2909 /* send WM_DRAGSELECT or WM_DRAGMOVE */
2910 if( hCurrentWnd != lpDragInfo->hScope )
2913 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
2914 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
2915 HIWORD(spDragInfo)) );
2916 hCurrentWnd = lpDragInfo->hScope;
2918 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
2922 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
2924 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
2927 ShowCursor( FALSE );
2931 SetCursor( hOldCursor );
2932 if (hDragCursor) DestroyCursor( hDragCursor );
2935 if( hCurrentCursor != hBummer )
2936 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
2937 (WPARAM16)hWnd, (LPARAM)spDragInfo );
2940 GlobalFree16(hDragInfo);
2942 return (DWORD)(msg.lParam);
2946 /******************************************************************************
2947 * GetWindowModuleFileNameA (USER32.@)
2949 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
2951 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
2952 hwnd, lpszFileName, cchFileNameMax);
2956 /******************************************************************************
2957 * GetWindowModuleFileNameW (USER32.@)
2959 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
2961 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
2962 hwnd, lpszFileName, cchFileNameMax);