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 WND_OTHER_PROCESS is handle may be valid in other process.
183 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
185 WND *WIN_GetPtr( HWND hwnd )
188 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
190 if (index >= NB_USER_HANDLES) return NULL;
193 if ((ptr = user_handles[index]))
195 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
199 else ptr = WND_OTHER_PROCESS;
205 /***********************************************************************
206 * WIN_IsCurrentProcess
208 * Check whether a given window belongs to the current process (and return the full handle).
210 HWND WIN_IsCurrentProcess( HWND hwnd )
215 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
217 WIN_ReleasePtr( ptr );
222 /***********************************************************************
223 * WIN_IsCurrentThread
225 * Check whether a given window belongs to the current thread (and return the full handle).
227 HWND WIN_IsCurrentThread( HWND hwnd )
232 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
234 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
235 WIN_ReleasePtr( ptr );
241 /***********************************************************************
244 * Convert a 16-bit window handle to a full 32-bit handle.
246 HWND WIN_Handle32( HWND16 hwnd16 )
249 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
251 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
252 /* do sign extension for -2 and -3 */
253 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
255 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
257 if (ptr != WND_OTHER_PROCESS)
259 hwnd = ptr->hwndSelf;
260 WIN_ReleasePtr( ptr );
262 else /* may belong to another process */
264 SERVER_START_REQ( get_window_info )
267 if (!SERVER_CALL_ERR()) hwnd = req->full_handle;
275 /***********************************************************************
278 * Return a pointer to the WND structure corresponding to a HWND.
280 WND * WIN_FindWndPtr( HWND hwnd )
284 if (!hwnd) return NULL;
286 if ((ptr = WIN_GetPtr( hwnd )))
288 if (ptr != WND_OTHER_PROCESS)
290 /* increment destruction monitoring */
294 if (IsWindow( hwnd )) /* check other processes */
296 ERR( "window %04x belongs to other process\n", hwnd );
297 /* DbgBreakPoint(); */
300 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
305 /***********************************************************************
308 * Release the pointer to the WND structure.
310 void WIN_ReleaseWndPtr(WND *wndPtr)
314 /*Decrement destruction monitoring value*/
316 /* Check if it's time to release the memory*/
317 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
320 free_window_handle( wndPtr->hwndSelf );
322 else if(wndPtr->irefCount < 0)
324 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
325 ERR("forgot a Lock on %p somewhere\n",wndPtr);
327 /*unlock all WND structures for thread safeness*/
332 /***********************************************************************
335 * Remove a window from the siblings linked list.
337 void WIN_UnlinkWindow( HWND hwnd )
339 WIN_LinkWindow( hwnd, 0, 0 );
343 /***********************************************************************
346 * Insert a window into the siblings linked list.
347 * The window is inserted after the specified window, which can also
348 * be specified as HWND_TOP or HWND_BOTTOM.
349 * If parent is 0, window is unlinked from the tree.
351 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
355 SERVER_START_REQ( link_window )
358 req->parent = parent;
359 req->previous = hwndInsertAfter;
360 ret = !SERVER_CALL_ERR();
365 WND *wndPtr = WIN_FindWndPtr( hwnd );
368 wndPtr->parent = WIN_GetFullHandle(parent);
369 WIN_ReleaseWndPtr( wndPtr );
375 /***********************************************************************
376 * find_child_to_repaint
378 * Find a window that needs repaint among the children of the specified window.
380 static HWND find_child_to_repaint( HWND parent )
386 if (!parent) parent = GetDesktopWindow();
387 if (!(list = list_window_children( parent, 0, 0 ))) return 0;
389 for (i = 0; list[i] && !ret; i++)
391 WND *win = WIN_GetPtr( list[i] );
392 if (!win) continue; /* ignore it */
393 if (win == WND_OTHER_PROCESS)
395 /* doesn't belong to this process, but check children */
396 ret = find_child_to_repaint( list[i] );
399 if (!(win->dwStyle & WS_VISIBLE))
401 WIN_ReleasePtr( win );
404 if ((win->tid != GetCurrentThreadId()) ||
405 (!win->hrgnUpdate && !(win->flags & WIN_INTERNAL_PAINT)))
407 /* does not need repaint, check children */
408 WIN_ReleasePtr( win );
409 ret = find_child_to_repaint( list[i] );
413 /* now we have something */
415 if (!(win->dwExStyle & WS_EX_TRANSPARENT))
417 /* not transparent, we can repaint it */
418 WIN_ReleasePtr( win );
421 WIN_ReleasePtr( win );
423 /* transparent window, look for non-transparent sibling to paint first */
424 for (i++; list[i]; i++)
426 if (!(win = WIN_GetPtr( list[i] ))) continue;
427 if (win == WND_OTHER_PROCESS) continue;
428 if (!(win->dwStyle & WS_VISIBLE))
430 WIN_ReleasePtr( win );
433 if (!(win->dwExStyle & WS_EX_TRANSPARENT) &&
434 (win->hrgnUpdate || (win->flags & WIN_INTERNAL_PAINT)))
437 WIN_ReleasePtr( win );
440 WIN_ReleasePtr( win );
443 HeapFree( GetProcessHeap(), 0, list );
448 /***********************************************************************
449 * WIN_FindWinToRepaint
451 * Find a window that needs repaint.
453 HWND WIN_FindWinToRepaint( HWND hwnd )
455 /* Note: the desktop window never gets WM_PAINT messages
456 * The real reason why is because Windows DesktopWndProc
457 * does ValidateRgn inside WM_ERASEBKGND handler.
459 if (hwnd == GetDesktopWindow()) hwnd = 0;
463 /* check the window itself first */
464 WND *win = WIN_FindWndPtr( hwnd );
466 if ((win->dwStyle & WS_VISIBLE) &&
467 (win->hrgnUpdate || (win->flags & WIN_INTERNAL_PAINT)))
469 WIN_ReleaseWndPtr( win );
472 WIN_ReleaseWndPtr( win );
474 /* now check its children */
475 return find_child_to_repaint( hwnd );
479 /***********************************************************************
482 * Destroy storage associated to a window. "Internals" p.358
484 static void WIN_DestroyWindow( HWND hwnd )
489 TRACE("%04x\n", hwnd );
491 /* free child windows */
492 if ((list = WIN_ListChildren( hwnd )))
495 for (i = 0; list[i]; i++) WIN_DestroyWindow( list[i] );
496 HeapFree( GetProcessHeap(), 0, list );
500 * Clear the update region to make sure no WM_PAINT messages will be
501 * generated for this window while processing the WM_NCDESTROY.
503 RedrawWindow( hwnd, NULL, 0,
504 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
507 * Send the WM_NCDESTROY to the window being destroyed.
509 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
511 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
513 WINPOS_CheckInternalPos( hwnd );
514 if( hwnd == GetCapture()) ReleaseCapture();
516 /* free resources associated with the window */
518 TIMER_RemoveWindowTimers( hwnd );
520 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return;
521 wndPtr->hmemTaskQ = 0;
523 if (!(wndPtr->dwStyle & WS_CHILD))
526 DestroyMenu( wndPtr->wIDmenu );
529 if (wndPtr->hSysMenu)
531 DestroyMenu( wndPtr->hSysMenu );
532 wndPtr->hSysMenu = 0;
534 USER_Driver.pDestroyWindow( hwnd );
535 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
536 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
537 CLASS_RemoveWindow( wndPtr->class );
538 wndPtr->class = NULL;
539 wndPtr->dwMagic = 0; /* Mark it as invalid */
540 WIN_ReleaseWndPtr( wndPtr );
543 /***********************************************************************
544 * WIN_DestroyThreadWindows
546 * Destroy all children of 'wnd' owned by the current thread.
547 * Return TRUE if something was done.
549 void WIN_DestroyThreadWindows( HWND hwnd )
554 if (!(list = WIN_ListChildren( hwnd ))) return;
555 for (i = 0; list[i]; i++)
557 if (WIN_IsCurrentThread( list[i] ))
558 DestroyWindow( list[i] );
560 WIN_DestroyThreadWindows( list[i] );
562 HeapFree( GetProcessHeap(), 0, list );
565 /***********************************************************************
566 * WIN_CreateDesktopWindow
568 * Create the desktop window.
570 BOOL WIN_CreateDesktopWindow(void)
572 struct tagCLASS *class;
580 TRACE("Creating desktop window\n");
583 if (!WINPOS_CreateInternalPosAtom() ||
584 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
585 &wndExtra, &winproc, &clsStyle, &dce )))
588 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM),
589 sizeof(WND) + wndExtra - sizeof(pWndDesktop->wExtra) );
590 if (!pWndDesktop) return FALSE;
591 hwndDesktop = pWndDesktop->hwndSelf;
593 pWndDesktop->tid = 0; /* nobody owns the desktop */
594 pWndDesktop->parent = 0;
595 pWndDesktop->owner = 0;
596 pWndDesktop->class = class;
597 pWndDesktop->hInstance = 0;
598 pWndDesktop->rectWindow.left = 0;
599 pWndDesktop->rectWindow.top = 0;
600 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
601 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
602 pWndDesktop->rectClient = pWndDesktop->rectWindow;
603 pWndDesktop->text = NULL;
604 pWndDesktop->hmemTaskQ = 0;
605 pWndDesktop->hrgnUpdate = 0;
606 pWndDesktop->hwndLastActive = hwndDesktop;
607 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
609 pWndDesktop->dwExStyle = 0;
610 pWndDesktop->clsStyle = clsStyle;
611 pWndDesktop->dce = NULL;
612 pWndDesktop->pVScroll = NULL;
613 pWndDesktop->pHScroll = NULL;
614 pWndDesktop->wIDmenu = 0;
615 pWndDesktop->helpContext = 0;
616 pWndDesktop->flags = 0;
617 pWndDesktop->hSysMenu = 0;
618 pWndDesktop->userdata = 0;
619 pWndDesktop->winproc = winproc;
620 pWndDesktop->cbWndExtra = wndExtra;
622 cs.lpCreateParams = NULL;
628 cs.cx = pWndDesktop->rectWindow.right;
629 cs.cy = pWndDesktop->rectWindow.bottom;
630 cs.style = pWndDesktop->dwStyle;
631 cs.dwExStyle = pWndDesktop->dwExStyle;
633 cs.lpszClass = DESKTOP_CLASS_ATOM;
635 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE )) return FALSE;
637 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
638 WIN_ReleaseWndPtr( pWndDesktop );
643 /***********************************************************************
646 * Fix the coordinates - Helper for WIN_CreateWindowEx.
647 * returns default show mode in sw.
648 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
650 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
652 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
653 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
655 if (cs->style & (WS_CHILD | WS_POPUP))
657 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
658 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
660 else /* overlapped window */
664 GetStartupInfoA( &info );
666 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
668 /* Never believe Microsoft's documentation... CreateWindowEx doc says
669 * that if an overlapped window is created with WS_VISIBLE style bit
670 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
671 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
674 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
675 * 2) it does not ignore the y parameter as the docs claim; instead, it
676 * uses it as second parameter to ShowWindow() unless y is either
677 * CW_USEDEFAULT or CW_USEDEFAULT16.
679 * The fact that we didn't do 2) caused bogus windows pop up when wine
680 * was running apps that were using this obscure feature. Example -
681 * calc.exe that comes with Win98 (only Win98, it's different from
682 * the one that comes with Win95 and NT)
684 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
685 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
686 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
689 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
691 if (info.dwFlags & STARTF_USESIZE)
693 cs->cx = info.dwXSize;
694 cs->cy = info.dwYSize;
696 else /* if no other hint from the app, pick 3/4 of the screen real estate */
699 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
700 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
701 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
708 /***********************************************************************
711 * Implementation of CreateWindowEx().
713 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
714 WINDOWPROCTYPE type )
717 struct tagCLASS *classPtr;
719 HWND hwnd, hwndLinkAfter, parent, owner;
720 POINT maxSize, maxPos, minTrack, maxTrack;
725 BOOL unicode = (type == WIN_PROC_32W);
727 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%04x menu=%04x inst=%08x params=%p\n",
728 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
729 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
730 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
731 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
733 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
734 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
736 /* Find the parent window */
738 parent = GetDesktopWindow();
742 /* Make sure parent is valid */
743 if (!IsWindow( cs->hwndParent ))
745 WARN("Bad parent %04x\n", cs->hwndParent );
748 if (cs->style & WS_CHILD) parent = WIN_GetFullHandle(cs->hwndParent);
749 else owner = GetAncestor( cs->hwndParent, GA_ROOT );
751 else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP))
753 WARN("No parent for child window\n" );
754 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
757 /* Find the window class */
758 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
759 &wndExtra, &winproc, &clsStyle, &dce )))
761 WARN("Bad class '%s'\n", cs->lpszClass );
765 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
767 /* Correct the window style - stage 1
769 * These are patches that appear to affect both the style loaded into the
770 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
772 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
773 * why does the user get to set it?
776 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
777 * tested for WS_POPUP
779 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
780 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
781 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
782 cs->dwExStyle |= WS_EX_WINDOWEDGE;
784 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
786 /* Create the window structure */
788 if (!(wndPtr = create_window_handle( parent, owner, classAtom,
789 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
791 TRACE("out of memory\n" );
794 hwnd = wndPtr->hwndSelf;
796 /* Fill the window structure */
798 wndPtr->tid = GetCurrentThreadId();
799 wndPtr->owner = owner;
800 wndPtr->parent = parent;
801 wndPtr->class = classPtr;
802 wndPtr->winproc = winproc;
803 wndPtr->hInstance = cs->hInstance;
805 wndPtr->hmemTaskQ = InitThreadInput16( 0, 0 );
806 wndPtr->hrgnUpdate = 0;
808 wndPtr->hwndLastActive = hwnd;
809 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
810 wndPtr->dwExStyle = cs->dwExStyle;
811 wndPtr->clsStyle = clsStyle;
813 wndPtr->helpContext = 0;
814 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
815 wndPtr->pVScroll = NULL;
816 wndPtr->pHScroll = NULL;
817 wndPtr->userdata = 0;
818 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
819 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
820 wndPtr->cbWndExtra = wndExtra;
822 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
824 /* Call the WH_CBT hook */
826 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
827 ? HWND_BOTTOM : HWND_TOP;
829 if (HOOK_IsHooked( WH_CBT ))
835 cbtc.hwndInsertAfter = hwndLinkAfter;
836 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND,
837 (WPARAM)hwnd, (LPARAM)&cbtc)
838 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND,
839 (WPARAM)hwnd, (LPARAM)&cbtc);
842 TRACE("CBT-hook returned 0\n");
843 free_window_handle( hwnd );
844 CLASS_RemoveWindow( classPtr );
850 /* Correct the window style - stage 2 */
852 if (!(cs->style & WS_CHILD))
854 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
855 if (!(cs->style & WS_POPUP))
857 wndPtr->dwStyle |= WS_CAPTION;
858 wndPtr->flags |= WIN_NEED_SIZE;
862 /* Get class or window DC if needed */
864 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
865 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
866 else wndPtr->dce = NULL;
868 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
870 wndPtr->rectWindow.left = cs->x;
871 wndPtr->rectWindow.top = cs->y;
872 wndPtr->rectWindow.right = cs->x + cs->cx;
873 wndPtr->rectWindow.bottom = cs->y + cs->cy;
874 wndPtr->rectClient = wndPtr->rectWindow;
876 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
878 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
880 WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
881 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
882 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
883 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
884 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
887 if (cs->cx < 0) cs->cx = 0;
888 if (cs->cy < 0) cs->cy = 0;
890 wndPtr->rectWindow.left = cs->x;
891 wndPtr->rectWindow.top = cs->y;
892 wndPtr->rectWindow.right = cs->x + cs->cx;
893 wndPtr->rectWindow.bottom = cs->y + cs->cy;
894 wndPtr->rectClient = wndPtr->rectWindow;
896 /* Set the window menu */
898 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
900 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
903 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
906 if (HIWORD(cs->hInstance))
907 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
909 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
911 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
915 else wndPtr->wIDmenu = (UINT)cs->hMenu;
917 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
919 WARN("aborted by WM_xxCREATE!\n");
920 WIN_ReleaseWndPtr( wndPtr );
921 WIN_DestroyWindow( hwnd );
922 CLASS_RemoveWindow( classPtr );
926 if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
928 /* Notify the parent window only */
930 SendMessageA( wndPtr->parent, WM_PARENTNOTIFY,
931 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
932 if( !IsWindow(hwnd) )
939 if (cs->style & WS_VISIBLE)
941 /* in case WS_VISIBLE got set in the meantime */
942 wndPtr->dwStyle &= ~WS_VISIBLE;
943 ShowWindow( hwnd, sw );
946 /* Call WH_SHELL hook */
948 if (!(wndPtr->dwStyle & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
949 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0 );
951 TRACE("created window %04x\n", hwnd);
953 WIN_ReleaseWndPtr(wndPtr);
958 /***********************************************************************
959 * CreateWindow (USER.41)
961 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
962 DWORD style, INT16 x, INT16 y, INT16 width,
963 INT16 height, HWND16 parent, HMENU16 menu,
964 HINSTANCE16 instance, LPVOID data )
966 return CreateWindowEx16( 0, className, windowName, style,
967 x, y, width, height, parent, menu, instance, data );
971 /***********************************************************************
972 * CreateWindowEx (USER.452)
974 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
975 LPCSTR windowName, DWORD style, INT16 x,
976 INT16 y, INT16 width, INT16 height,
977 HWND16 parent, HMENU16 menu,
978 HINSTANCE16 instance, LPVOID data )
984 /* Find the class atom */
986 if (HIWORD(className))
988 if (!(classAtom = GlobalFindAtomA( className )))
990 ERR( "bad class name %s\n", debugres_a(className) );
996 classAtom = LOWORD(className);
997 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
999 ERR( "bad atom %x\n", classAtom);
1005 /* Fix the coordinates */
1007 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1008 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1009 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1010 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1012 /* Create the window */
1014 cs.lpCreateParams = data;
1015 cs.hInstance = (HINSTANCE)instance;
1016 cs.hMenu = (HMENU)menu;
1017 cs.hwndParent = WIN_Handle32( parent );
1019 cs.lpszName = windowName;
1020 cs.lpszClass = className;
1021 cs.dwExStyle = exStyle;
1023 return WIN_Handle16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1027 /***********************************************************************
1028 * CreateWindowExA (USER32.@)
1030 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1031 LPCSTR windowName, DWORD style, INT x,
1032 INT y, INT width, INT height,
1033 HWND parent, HMENU menu,
1034 HINSTANCE instance, LPVOID data )
1041 instance=GetModuleHandleA(NULL);
1043 if(exStyle & WS_EX_MDICHILD)
1044 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1046 /* Find the class atom */
1048 if (HIWORD(className))
1050 if (!(classAtom = GlobalFindAtomA( className )))
1052 ERR( "bad class name %s\n", debugres_a(className) );
1058 classAtom = LOWORD(className);
1059 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1061 ERR( "bad atom %x\n", classAtom);
1067 /* Create the window */
1069 cs.lpCreateParams = data;
1070 cs.hInstance = instance;
1072 cs.hwndParent = parent;
1078 cs.lpszName = windowName;
1079 cs.lpszClass = className;
1080 cs.dwExStyle = exStyle;
1082 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1086 /***********************************************************************
1087 * CreateWindowExW (USER32.@)
1089 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1090 LPCWSTR windowName, DWORD style, INT x,
1091 INT y, INT width, INT height,
1092 HWND parent, HMENU menu,
1093 HINSTANCE instance, LPVOID data )
1100 instance=GetModuleHandleA(NULL);
1102 if(exStyle & WS_EX_MDICHILD)
1103 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1105 /* Find the class atom */
1107 if (HIWORD(className))
1109 if (!(classAtom = GlobalFindAtomW( className )))
1111 ERR( "bad class name %s\n", debugres_w(className) );
1117 classAtom = LOWORD(className);
1118 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1120 ERR( "bad atom %x\n", classAtom);
1126 /* Create the window */
1128 cs.lpCreateParams = data;
1129 cs.hInstance = instance;
1131 cs.hwndParent = parent;
1137 cs.lpszName = windowName;
1138 cs.lpszClass = className;
1139 cs.dwExStyle = exStyle;
1141 /* Note: we rely on the fact that CREATESTRUCTA and */
1142 /* CREATESTRUCTW have the same layout. */
1143 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1147 /***********************************************************************
1148 * WIN_SendDestroyMsg
1150 static void WIN_SendDestroyMsg( HWND hwnd )
1152 if( CARET_GetHwnd() == hwnd) DestroyCaret();
1153 if (USER_Driver.pResetSelectionOwner)
1154 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1157 * Send the WM_DESTROY to the window.
1159 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1162 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1163 * make sure that the window still exists when we come back.
1170 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1172 /* start from the end (FIXME: is this needed?) */
1173 for (i = 0; pWndArray[i]; i++) ;
1177 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1179 HeapFree( GetProcessHeap(), 0, pWndArray );
1182 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1186 /***********************************************************************
1187 * DestroyWindow (USER32.@)
1189 BOOL WINAPI DestroyWindow( HWND hwnd )
1195 hwnd = WIN_GetFullHandle( hwnd );
1196 TRACE("(%04x)\n", hwnd);
1198 /* Initialization */
1200 if (hwnd == GetDesktopWindow()) return FALSE; /* Can't destroy desktop */
1202 /* Look whether the focus is within the tree of windows we will
1206 if (h == hwnd || IsChild( hwnd, h ))
1208 HWND parent = GetAncestor( hwnd, GA_PARENT );
1209 if (parent == GetDesktopWindow()) parent = 0;
1215 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0L) ) return FALSE;
1217 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1218 if (!(wndPtr->dwStyle & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1220 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L );
1221 /* FIXME: clean up palette - see "Internals" p.352 */
1224 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1225 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1227 /* Notify the parent window only */
1228 SendMessageA( wndPtr->parent, WM_PARENTNOTIFY,
1229 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1230 if( !IsWindow(hwnd) )
1237 if (USER_Driver.pResetSelectionOwner)
1238 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1240 /* Hide the window */
1242 ShowWindow( hwnd, SW_HIDE );
1243 if (!IsWindow(hwnd))
1249 /* Recursively destroy owned windows */
1251 if( !(wndPtr->dwStyle & WS_CHILD) )
1258 HWND *list = WIN_ListChildren( wndPtr->parent );
1261 for (i = 0; list[i]; i++)
1264 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1265 if (!(siblingPtr = WIN_FindWndPtr( list[i] ))) continue;
1266 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1268 WIN_ReleaseWndPtr( siblingPtr );
1269 DestroyWindow( list[i] );
1273 else siblingPtr->owner = 0;
1274 WIN_ReleaseWndPtr( siblingPtr );
1276 HeapFree( GetProcessHeap(), 0, list );
1278 if (!got_one) break;
1281 WINPOS_ActivateOtherWindow( hwnd );
1283 if ((owner = GetWindow( hwnd, GW_OWNER )))
1285 WND *ptr = WIN_FindWndPtr( owner );
1288 if (ptr->hwndLastActive == hwnd) ptr->hwndLastActive = owner;
1289 WIN_ReleaseWndPtr( ptr );
1294 /* Send destroy messages */
1296 WIN_SendDestroyMsg( hwnd );
1297 if (!IsWindow(hwnd))
1303 /* Unlink now so we won't bother with the children later on */
1305 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1307 /* Destroy the window storage */
1309 WIN_DestroyWindow( hwnd );
1312 WIN_ReleaseWndPtr(wndPtr);
1317 /***********************************************************************
1318 * CloseWindow (USER32.@)
1320 BOOL WINAPI CloseWindow( HWND hwnd )
1322 WND * wndPtr = WIN_FindWndPtr( hwnd );
1325 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1330 ShowWindow( hwnd, SW_MINIMIZE );
1333 WIN_ReleaseWndPtr(wndPtr);
1339 /***********************************************************************
1340 * OpenIcon (USER32.@)
1342 BOOL WINAPI OpenIcon( HWND hwnd )
1344 if (!IsIconic( hwnd )) return FALSE;
1345 ShowWindow( hwnd, SW_SHOWNORMAL );
1350 /***********************************************************************
1353 * Implementation of FindWindow() and FindWindowEx().
1355 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1360 WCHAR *buffer = NULL;
1362 if (!parent) parent = GetDesktopWindow();
1365 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1366 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1369 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1373 child = WIN_GetFullHandle( child );
1374 while (list[i] && list[i] != child) i++;
1375 if (!list[i]) goto done;
1376 i++; /* start from next window */
1383 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1390 if (list) HeapFree( GetProcessHeap(), 0, list );
1391 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1397 /***********************************************************************
1398 * FindWindowA (USER32.@)
1400 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1402 HWND ret = FindWindowExA( 0, 0, className, title );
1403 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1408 /***********************************************************************
1409 * FindWindowExA (USER32.@)
1411 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1412 LPCSTR className, LPCSTR title )
1420 /* If the atom doesn't exist, then no class */
1421 /* with this name exists either. */
1422 if (!(atom = GlobalFindAtomA( className )))
1424 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1429 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1430 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1431 HeapFree( GetProcessHeap(), 0, buffer );
1436 /***********************************************************************
1437 * FindWindowExW (USER32.@)
1439 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1440 LPCWSTR className, LPCWSTR title )
1446 /* If the atom doesn't exist, then no class */
1447 /* with this name exists either. */
1448 if (!(atom = GlobalFindAtomW( className )))
1450 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1454 return WIN_FindWindow( parent, child, atom, title );
1458 /***********************************************************************
1459 * FindWindowW (USER32.@)
1461 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1463 return FindWindowExW( 0, 0, className, title );
1467 /**********************************************************************
1468 * GetDesktopWindow (USER32.@)
1470 HWND WINAPI GetDesktopWindow(void)
1472 if (pWndDesktop) return pWndDesktop->hwndSelf;
1473 ERR( "You need the -desktop option when running with native USER\n" );
1479 /*******************************************************************
1480 * EnableWindow (USER32.@)
1482 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1487 TRACE("( %x, %d )\n", hwnd, enable);
1489 if (USER_Driver.pEnableWindow)
1490 return USER_Driver.pEnableWindow( hwnd, enable );
1492 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1493 hwnd = wndPtr->hwndSelf; /* make it a full handle */
1495 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1497 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1499 wndPtr->dwStyle &= ~WS_DISABLED; /* Enable window */
1500 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1502 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1504 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1506 wndPtr->dwStyle |= WS_DISABLED; /* Disable window */
1508 if (hwnd == GetFocus())
1509 SetFocus( 0 ); /* A disabled window can't have the focus */
1511 if (hwnd == GetCapture())
1512 ReleaseCapture(); /* A disabled window can't capture the mouse */
1514 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1516 WIN_ReleaseWndPtr(wndPtr);
1521 /***********************************************************************
1522 * IsWindowEnabled (USER32.@)
1524 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1529 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1530 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1531 WIN_ReleaseWndPtr(wndPtr);
1537 /***********************************************************************
1538 * IsWindowUnicode (USER32.@)
1540 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1545 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1546 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1547 WIN_ReleaseWndPtr(wndPtr);
1552 /**********************************************************************
1553 * GetWindowWord (USER32.@)
1555 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1558 WND * wndPtr = WIN_FindWndPtr( hwnd );
1559 if (!wndPtr) return 0;
1562 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1564 WARN("Invalid offset %d\n", offset );
1567 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1568 WIN_ReleaseWndPtr(wndPtr);
1572 WIN_ReleaseWndPtr(wndPtr);
1575 case GWL_HWNDPARENT:
1576 return GetWindowLongW( hwnd, offset );
1580 LONG ret = GetWindowLongW( hwnd, offset );
1582 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1586 WARN("Invalid offset %d\n", offset );
1592 /**********************************************************************
1593 * SetWindowWord (USER32.@)
1595 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1598 WND * wndPtr = WIN_FindWndPtr( hwnd );
1599 if (!wndPtr) return 0;
1602 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1604 WARN("Invalid offset %d\n", offset );
1605 WIN_ReleaseWndPtr(wndPtr);
1608 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1611 WIN_ReleaseWndPtr(wndPtr);
1615 WIN_ReleaseWndPtr(wndPtr);
1620 case GWL_HWNDPARENT:
1621 return SetWindowLongW( hwnd, offset, (UINT)newval );
1623 WARN("Invalid offset %d\n", offset );
1629 /**********************************************************************
1632 * Helper function for GetWindowLong().
1634 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1637 WND * wndPtr = WIN_FindWndPtr( hwnd );
1638 if (!wndPtr) return 0;
1641 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1643 WARN("Invalid offset %d\n", offset );
1647 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1648 /* Special case for dialog window procedure */
1649 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1651 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1658 case GWL_USERDATA: retvalue = wndPtr->userdata;
1660 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1662 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1664 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1666 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1669 case GWL_HWNDPARENT: retvalue = (LONG)GetParent(hwnd);
1671 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1674 WARN("Unknown offset %d\n", offset );
1678 WIN_ReleaseWndPtr(wndPtr);
1683 /**********************************************************************
1686 * Helper function for SetWindowLong().
1688 * 0 is the failure code. However, in the case of failure SetLastError
1689 * must be set to distinguish between a 0 return value and a failure.
1691 * FIXME: The error values for SetLastError may not be right. Can
1692 * someone check with the real thing?
1694 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1695 WINDOWPROCTYPE type )
1698 WND * wndPtr = WIN_FindWndPtr( hwnd );
1701 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1705 /* Is this the right error? */
1706 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1712 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1714 WARN("Invalid offset %d\n", offset );
1716 /* Is this the right error? */
1717 SetLastError( ERROR_OUTOFMEMORY );
1722 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1723 /* Special case for dialog window procedure */
1724 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1726 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1727 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1728 type, WIN_PROC_WINDOW );
1735 ptr = (DWORD*)&wndPtr->wIDmenu;
1738 ptr = (DWORD*)&wndPtr->hInstance;
1741 ptr = &wndPtr->userdata;
1743 case GWL_HWNDPARENT:
1744 retval = SetParent( hwnd, (HWND)newval );
1747 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1748 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1749 type, WIN_PROC_WINDOW );
1752 retval = wndPtr->dwStyle;
1753 style.styleOld = wndPtr->dwStyle;
1754 style.styleNew = newval;
1755 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1756 wndPtr->dwStyle = style.styleNew;
1757 if (USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, retval );
1758 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1759 retval = style.styleOld;
1762 style.styleOld = wndPtr->dwExStyle;
1763 style.styleNew = newval;
1764 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1765 wndPtr->dwExStyle = style.styleNew;
1766 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1767 retval = style.styleOld;
1771 WARN("Invalid offset %d\n", offset );
1773 /* Don't think this is right error but it should do */
1774 SetLastError( ERROR_OUTOFMEMORY );
1782 WIN_ReleaseWndPtr(wndPtr);
1787 /**********************************************************************
1788 * GetWindowLong (USER.135)
1790 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1792 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
1796 /**********************************************************************
1797 * GetWindowLongA (USER32.@)
1799 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
1801 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1805 /**********************************************************************
1806 * GetWindowLongW (USER32.@)
1808 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
1810 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1814 /**********************************************************************
1815 * SetWindowLong (USER.136)
1817 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1819 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
1823 /**********************************************************************
1824 * SetWindowLongA (USER32.@)
1826 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
1828 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1832 /**********************************************************************
1833 * SetWindowLongW (USER32.@) Set window attribute
1835 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
1836 * value in a window's extra memory.
1838 * The _hwnd_ parameter specifies the window. is the handle to a
1839 * window that has extra memory. The _newval_ parameter contains the
1840 * new attribute or extra memory value. If positive, the _offset_
1841 * parameter is the byte-addressed location in the window's extra
1842 * memory to set. If negative, _offset_ specifies the window
1843 * attribute to set, and should be one of the following values:
1845 * GWL_EXSTYLE The window's extended window style
1847 * GWL_STYLE The window's window style.
1849 * GWL_WNDPROC Pointer to the window's window procedure.
1851 * GWL_HINSTANCE The window's pplication instance handle.
1853 * GWL_ID The window's identifier.
1855 * GWL_USERDATA The window's user-specified data.
1857 * If the window is a dialog box, the _offset_ parameter can be one of
1858 * the following values:
1860 * DWL_DLGPROC The address of the window's dialog box procedure.
1862 * DWL_MSGRESULT The return value of a message
1863 * that the dialog box procedure processed.
1865 * DWL_USER Application specific information.
1869 * If successful, returns the previous value located at _offset_. Otherwise,
1874 * Extra memory for a window class is specified by a nonzero cbWndExtra
1875 * parameter of the WNDCLASS structure passed to RegisterClass() at the
1876 * time of class creation.
1878 * Using GWL_WNDPROC to set a new window procedure effectively creates
1879 * a window subclass. Use CallWindowProc() in the new windows procedure
1880 * to pass messages to the superclass's window procedure.
1882 * The user data is reserved for use by the application which created
1885 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
1886 * instead, call the EnableWindow() function to change the window's
1889 * Do not use GWL_HWNDPARENT to reset the window's parent, use
1890 * SetParent() instead.
1893 * When offset is GWL_STYLE and the calling app's ver is 4.0,
1894 * it sends WM_STYLECHANGING before changing the settings
1895 * and WM_STYLECHANGED afterwards.
1896 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
1900 * GWL_STYLE does not dispatch WM_STYLE... messages.
1907 LONG WINAPI SetWindowLongW(
1908 HWND hwnd, /* [in] window to alter */
1909 INT offset, /* [in] offset, in bytes, of location to alter */
1910 LONG newval /* [in] new value of location */
1912 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1916 /*******************************************************************
1917 * GetWindowTextA (USER32.@)
1919 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
1921 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
1925 /*******************************************************************
1926 * InternalGetWindowText (USER32.@)
1928 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
1930 WND *win = WIN_FindWndPtr( hwnd );
1932 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
1933 else lpString[0] = 0;
1934 WIN_ReleaseWndPtr( win );
1935 return strlenW(lpString);
1939 /*******************************************************************
1940 * GetWindowTextW (USER32.@)
1942 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
1944 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
1949 /*******************************************************************
1950 * SetWindowText (USER32.@)
1951 * SetWindowTextA (USER32.@)
1953 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
1955 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1959 /*******************************************************************
1960 * SetWindowTextW (USER32.@)
1962 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
1964 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1968 /*******************************************************************
1969 * GetWindowTextLengthA (USER32.@)
1971 INT WINAPI GetWindowTextLengthA( HWND hwnd )
1973 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1976 /*******************************************************************
1977 * GetWindowTextLengthW (USER32.@)
1979 INT WINAPI GetWindowTextLengthW( HWND hwnd )
1981 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1985 /*******************************************************************
1986 * IsWindow (USER32.@)
1988 BOOL WINAPI IsWindow( HWND hwnd )
1993 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
1995 if (ptr != WND_OTHER_PROCESS)
1997 WIN_ReleasePtr( ptr );
2001 /* check other processes */
2002 SERVER_START_REQ( get_window_info )
2005 ret = !SERVER_CALL_ERR();
2012 /***********************************************************************
2013 * GetWindowThreadProcessId (USER32.@)
2015 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2020 if (!(ptr = WIN_GetPtr( hwnd )))
2022 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2026 if (ptr != WND_OTHER_PROCESS)
2028 /* got a valid window */
2030 if (process) *process = GetCurrentProcessId();
2031 WIN_ReleasePtr( ptr );
2035 /* check other processes */
2036 SERVER_START_REQ( get_window_info )
2039 if (!SERVER_CALL_ERR())
2041 tid = (DWORD)req->tid;
2042 if (process) *process = (DWORD)req->pid;
2050 /*****************************************************************
2051 * GetParent (USER32.@)
2053 HWND WINAPI GetParent( HWND hwnd )
2058 if ((wndPtr = WIN_FindWndPtr(hwnd)))
2060 if (wndPtr->dwStyle & WS_CHILD)
2061 retvalue = wndPtr->parent;
2062 else if (wndPtr->dwStyle & WS_POPUP)
2063 retvalue = wndPtr->owner;
2064 WIN_ReleaseWndPtr(wndPtr);
2070 /*****************************************************************
2071 * GetAncestor (USER32.@)
2073 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2076 size_t size = (type == GA_PARENT) ? sizeof(user_handle_t) : REQUEST_MAX_VAR_SIZE;
2078 SERVER_START_VAR_REQ( get_window_parents, size )
2083 user_handle_t *data = server_data_ptr(req);
2084 int count = server_data_size(req) / sizeof(*data);
2094 if (count > 1) ret = data[count - 2]; /* get the one before the desktop */
2095 else ret = WIN_GetFullHandle( hwnd );
2103 if (ret && type == GA_ROOTOWNER)
2107 HWND owner = GetWindow( ret, GW_OWNER );
2116 /*****************************************************************
2117 * SetParent (USER32.@)
2119 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2125 if (!parent) parent = GetDesktopWindow();
2126 else parent = WIN_GetFullHandle( parent );
2129 if (WIN_GetFullHandle(hwnd) == GetDesktopWindow() || !IsWindow( parent ))
2131 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2135 if (USER_Driver.pSetParent)
2136 return USER_Driver.pSetParent( hwnd, parent );
2138 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2140 dwStyle = wndPtr->dwStyle;
2142 /* Windows hides the window first, then shows it again
2143 * including the WM_SHOWWINDOW messages and all */
2144 if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
2146 retvalue = wndPtr->parent; /* old parent */
2147 if (parent != retvalue)
2149 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2151 if (parent != GetDesktopWindow()) /* a child window */
2153 if (!(dwStyle & WS_CHILD))
2155 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2156 if (menu) DestroyMenu( menu );
2160 WIN_ReleaseWndPtr( wndPtr );
2162 /* SetParent additionally needs to make hwnd the topmost window
2163 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2164 WM_WINDOWPOSCHANGED notification messages.
2166 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2167 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|
2168 ((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2169 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2170 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2175 /*******************************************************************
2176 * IsChild (USER32.@)
2178 BOOL WINAPI IsChild( HWND parent, HWND child )
2180 HWND *list = WIN_ListParents( child );
2184 if (!list) return FALSE;
2185 parent = WIN_GetFullHandle( parent );
2186 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2187 ret = (list[i] != 0);
2188 HeapFree( GetProcessHeap(), 0, list );
2193 /***********************************************************************
2194 * IsWindowVisible (USER32.@)
2196 BOOL WINAPI IsWindowVisible( HWND hwnd )
2202 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2203 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2204 for (i = 0; list[i]; i++)
2205 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2207 HeapFree( GetProcessHeap(), 0, list );
2212 /***********************************************************************
2213 * WIN_IsWindowDrawable
2215 * hwnd is drawable when it is visible, all parents are not
2216 * minimized, and it is itself not minimized unless we are
2217 * trying to draw its default class icon.
2219 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2224 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2226 if (!(style & WS_VISIBLE)) return FALSE;
2227 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2229 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2230 for (i = 0; list[i]; i++)
2231 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2234 HeapFree( GetProcessHeap(), 0, list );
2239 /*******************************************************************
2240 * GetTopWindow (USER32.@)
2242 HWND WINAPI GetTopWindow( HWND hwnd )
2244 if (!hwnd) hwnd = GetDesktopWindow();
2245 return GetWindow( hwnd, GW_CHILD );
2249 /*******************************************************************
2250 * GetWindow (USER32.@)
2252 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2256 if (rel == GW_OWNER) /* special case: not fully supported in the server yet */
2258 WND *wndPtr = WIN_FindWndPtr( hwnd );
2259 if (!wndPtr) return 0;
2260 retval = wndPtr->owner;
2261 WIN_ReleaseWndPtr( wndPtr );
2265 SERVER_START_REQ( get_window_tree )
2268 if (!SERVER_CALL_ERR())
2273 retval = req->first_sibling;
2276 retval = req->last_sibling;
2279 retval = req->next_sibling;
2282 retval = req->prev_sibling;
2285 retval = req->first_child;
2295 /***********************************************************************
2296 * WIN_InternalShowOwnedPopups
2298 * Internal version of ShowOwnedPopups; Wine functions should use this
2299 * to avoid interfering with application calls to ShowOwnedPopups
2300 * and to make sure the application can't prevent showing/hiding.
2302 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2306 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2310 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2312 if (!win_array) return TRUE;
2315 * Show windows Lowest first, Highest last to preserve Z-Order
2317 while (win_array[count]) count++;
2318 while (--count >= 0)
2320 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2321 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2323 if (pWnd->dwStyle & WS_POPUP)
2327 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2328 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2331 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2333 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2334 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2339 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2340 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2341 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2344 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2346 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2347 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2348 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2352 WIN_ReleaseWndPtr( pWnd );
2354 HeapFree( GetProcessHeap(), 0, win_array );
2359 /*******************************************************************
2360 * ShowOwnedPopups (USER32.@)
2362 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2366 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2368 if (!win_array) return TRUE;
2370 while (win_array[count]) count++;
2371 while (--count >= 0)
2373 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2374 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2376 if (pWnd->dwStyle & WS_POPUP)
2380 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2382 /* In Windows, ShowOwnedPopups(TRUE) generates
2383 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2384 * regardless of the state of the owner
2386 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2387 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2392 if (IsWindowVisible(pWnd->hwndSelf))
2394 /* In Windows, ShowOwnedPopups(FALSE) generates
2395 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2396 * regardless of the state of the owner
2398 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2399 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2403 WIN_ReleaseWndPtr( pWnd );
2405 HeapFree( GetProcessHeap(), 0, win_array );
2410 /*******************************************************************
2411 * GetLastActivePopup (USER32.@)
2413 HWND WINAPI GetLastActivePopup( HWND hwnd )
2416 WND *wndPtr =WIN_FindWndPtr(hwnd);
2417 if (!wndPtr) return hwnd;
2418 retval = wndPtr->hwndLastActive;
2419 if (!IsWindow( retval )) retval = wndPtr->hwndSelf;
2420 WIN_ReleaseWndPtr(wndPtr);
2425 /*******************************************************************
2428 * Build an array of all parents of a given window, starting with
2429 * the immediate parent. The array must be freed with HeapFree.
2430 * Returns NULL if window is a top-level window.
2432 HWND *WIN_ListParents( HWND hwnd )
2436 SERVER_START_VAR_REQ( get_window_parents, REQUEST_MAX_VAR_SIZE )
2441 user_handle_t *data = server_data_ptr(req);
2442 int i, count = server_data_size(req) / sizeof(*data);
2443 if (count && ((list = HeapAlloc( GetProcessHeap(), 0, (count + 1) * sizeof(HWND) ))))
2445 for (i = 0; i < count; i++) list[i] = data[i];
2455 /*******************************************************************
2458 * Build an array of the children of a given window. The array must be
2459 * freed with HeapFree. Returns NULL when no windows are found.
2461 HWND *WIN_ListChildren( HWND hwnd )
2463 return list_window_children( hwnd, 0, 0 );
2467 /*******************************************************************
2468 * EnumWindows (USER32.@)
2470 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2476 /* We have to build a list of all windows first, to avoid */
2477 /* unpleasant side-effects, for instance if the callback */
2478 /* function changes the Z-order of the windows. */
2480 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return FALSE;
2482 /* Now call the callback function for every window */
2484 iWndsLocks = WIN_SuspendWndsLock();
2485 for (i = 0; list[i]; i++)
2487 /* Make sure that the window still exists */
2488 if (!IsWindow( list[i] )) continue;
2489 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2491 WIN_RestoreWndsLock(iWndsLocks);
2492 HeapFree( GetProcessHeap(), 0, list );
2497 /**********************************************************************
2498 * EnumTaskWindows16 (USER.225)
2500 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2503 TDB *tdb = TASK_GetPtr( hTask );
2504 if (!tdb) return FALSE;
2505 return EnumThreadWindows( (DWORD)tdb->teb->tid, (WNDENUMPROC)func, lParam );
2509 /**********************************************************************
2510 * EnumThreadWindows (USER32.@)
2512 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2517 if (!(list = list_window_children( GetDesktopWindow(), 0, GetCurrentThreadId() )))
2520 /* Now call the callback function for every window */
2522 iWndsLocks = WIN_SuspendWndsLock();
2523 for (i = 0; list[i]; i++)
2524 if (!func( list[i], lParam )) break;
2525 WIN_RestoreWndsLock(iWndsLocks);
2526 HeapFree( GetProcessHeap(), 0, list );
2531 /**********************************************************************
2532 * WIN_EnumChildWindows
2534 * Helper function for EnumChildWindows().
2536 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2541 for ( ; *list; list++)
2543 /* Make sure that the window still exists */
2544 if (!IsWindow( *list )) continue;
2545 /* skip owned windows */
2546 if (GetWindow( *list, GW_OWNER )) continue;
2547 /* Build children list first */
2548 childList = WIN_ListChildren( *list );
2550 ret = func( *list, lParam );
2554 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2555 HeapFree( GetProcessHeap(), 0, childList );
2557 if (!ret) return FALSE;
2563 /**********************************************************************
2564 * EnumChildWindows (USER32.@)
2566 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2571 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2572 iWndsLocks = WIN_SuspendWndsLock();
2573 WIN_EnumChildWindows( list, func, lParam );
2574 WIN_RestoreWndsLock(iWndsLocks);
2575 HeapFree( GetProcessHeap(), 0, list );
2580 /*******************************************************************
2581 * AnyPopup (USER.52)
2583 BOOL16 WINAPI AnyPopup16(void)
2589 /*******************************************************************
2590 * AnyPopup (USER32.@)
2592 BOOL WINAPI AnyPopup(void)
2596 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2598 if (!list) return FALSE;
2599 for (i = 0; list[i]; i++)
2601 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2603 retvalue = (list[i] != 0);
2604 HeapFree( GetProcessHeap(), 0, list );
2609 /*******************************************************************
2610 * FlashWindow (USER32.@)
2612 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2614 WND *wndPtr = WIN_FindWndPtr(hWnd);
2616 TRACE("%04x\n", hWnd);
2618 if (!wndPtr) return FALSE;
2619 hWnd = wndPtr->hwndSelf; /* make it a full handle */
2621 if (wndPtr->dwStyle & WS_MINIMIZE)
2623 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2625 HDC hDC = GetDC(hWnd);
2627 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2628 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2630 ReleaseDC( hWnd, hDC );
2631 wndPtr->flags |= WIN_NCACTIVATED;
2635 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2636 wndPtr->flags &= ~WIN_NCACTIVATED;
2638 WIN_ReleaseWndPtr(wndPtr);
2644 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2645 else wparam = (hWnd == GetActiveWindow());
2647 WIN_ReleaseWndPtr(wndPtr);
2648 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2654 /*******************************************************************
2655 * GetWindowContextHelpId (USER32.@)
2657 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2660 WND *wnd = WIN_FindWndPtr( hwnd );
2662 retval = wnd->helpContext;
2663 WIN_ReleaseWndPtr(wnd);
2668 /*******************************************************************
2669 * SetWindowContextHelpId (USER32.@)
2671 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
2673 WND *wnd = WIN_FindWndPtr( hwnd );
2674 if (!wnd) return FALSE;
2675 wnd->helpContext = id;
2676 WIN_ReleaseWndPtr(wnd);
2681 /*******************************************************************
2684 * recursively find a child that contains spDragInfo->pt point
2685 * and send WM_QUERYDROPOBJECT
2687 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
2689 BOOL16 wParam, bResult = 0;
2691 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
2694 if (!ptrDragInfo) return FALSE;
2696 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
2698 GetWindowRect(hQueryWnd,&tempRect);
2700 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
2702 if (!IsIconic( hQueryWnd ))
2704 GetClientRect( hQueryWnd, &tempRect );
2705 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
2707 if (PtInRect( &tempRect, pt))
2710 HWND *list = WIN_ListChildren( hQueryWnd );
2716 for (i = 0; list[i]; i++)
2718 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
2720 GetWindowRect( list[i], &tempRect );
2721 if (PtInRect( &tempRect, pt )) break;
2726 if (IsWindowEnabled( list[i] ))
2727 bResult = DRAG_QueryUpdate( list[i], spDragInfo, bNoSend );
2729 HeapFree( GetProcessHeap(), 0, list );
2731 if(bResult) return bResult;
2737 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
2739 ptrDragInfo->hScope = hQueryWnd;
2741 if (bNoSend) bResult = (GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) != 0;
2742 else bResult = SendMessage16( hQueryWnd, WM_QUERYDROPOBJECT, (WPARAM16)wParam, spDragInfo );
2744 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
2750 /*******************************************************************
2751 * DragDetect (USER32.@)
2753 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
2758 rect.left = pt.x - wDragWidth;
2759 rect.right = pt.x + wDragWidth;
2761 rect.top = pt.y - wDragHeight;
2762 rect.bottom = pt.y + wDragHeight;
2768 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
2770 if( msg.message == WM_LBUTTONUP )
2775 if( msg.message == WM_MOUSEMOVE )
2778 tmp.x = LOWORD(msg.lParam);
2779 tmp.y = HIWORD(msg.lParam);
2780 if( !PtInRect( &rect, tmp ))
2792 /******************************************************************************
2793 * DragObject (USER.464)
2795 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
2796 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
2799 LPDRAGINFO16 lpDragInfo;
2801 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
2802 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
2803 HCURSOR16 hCurrentCursor = 0;
2804 HWND16 hCurrentWnd = 0;
2806 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
2807 spDragInfo = K32WOWGlobalLock16(hDragInfo);
2809 if( !lpDragInfo || !spDragInfo ) return 0L;
2811 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
2813 GlobalFree16(hDragInfo);
2819 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
2821 GlobalFree16(hDragInfo);
2825 if( hDragCursor == hCursor ) hDragCursor = 0;
2826 else hCursor = hDragCursor;
2828 hOldCursor = SetCursor(hDragCursor);
2831 lpDragInfo->hWnd = hWnd;
2832 lpDragInfo->hScope = 0;
2833 lpDragInfo->wFlags = wObj;
2834 lpDragInfo->hList = szList; /* near pointer! */
2835 lpDragInfo->hOfStruct = hOfStruct;
2843 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
2845 *(lpDragInfo+1) = *lpDragInfo;
2847 lpDragInfo->pt.x = msg.pt.x;
2848 lpDragInfo->pt.y = msg.pt.y;
2850 /* update DRAGINFO struct */
2851 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
2853 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
2854 hCurrentCursor = hCursor;
2857 hCurrentCursor = hBummer;
2858 lpDragInfo->hScope = 0;
2860 if( hCurrentCursor )
2861 SetCursor(hCurrentCursor);
2863 /* send WM_DRAGLOOP */
2864 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
2865 (LPARAM) spDragInfo );
2866 /* send WM_DRAGSELECT or WM_DRAGMOVE */
2867 if( hCurrentWnd != lpDragInfo->hScope )
2870 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
2871 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
2872 HIWORD(spDragInfo)) );
2873 hCurrentWnd = lpDragInfo->hScope;
2875 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
2879 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
2881 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
2884 ShowCursor( FALSE );
2888 SetCursor( hOldCursor );
2889 if (hDragCursor) DestroyCursor( hDragCursor );
2892 if( hCurrentCursor != hBummer )
2893 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
2894 (WPARAM16)hWnd, (LPARAM)spDragInfo );
2897 GlobalFree16(hDragInfo);
2899 return (DWORD)(msg.lParam);
2903 /******************************************************************************
2904 * GetWindowModuleFileNameA (USER32.@)
2906 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
2908 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
2909 hwnd, lpszFileName, cchFileNameMax);
2913 /******************************************************************************
2914 * GetWindowModuleFileNameW (USER32.@)
2916 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
2918 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
2919 hwnd, lpszFileName, cchFileNameMax);