2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
10 #include "wine/winbase16.h"
11 #include "wine/winuser16.h"
12 #include "wine/server.h"
13 #include "wine/unicode.h"
19 #include "cursoricon.h"
26 #include "stackframe.h"
27 #include "debugtools.h"
29 DEFAULT_DEBUG_CHANNEL(win);
30 DECLARE_DEBUG_CHANNEL(msg);
32 /**********************************************************************/
35 static WND *pWndDesktop = NULL;
37 static WORD wDragWidth = 4;
38 static WORD wDragHeight= 3;
40 static void *user_handles[65536];
43 extern SYSLEVEL USER_SysLevel; /* FIXME */
45 /***********************************************************************
48 * Suspend the lock on WND structures.
49 * Returns the number of locks suspended
51 int WIN_SuspendWndsLock( void )
53 int isuspendedLocks = _ConfirmSysLevel( &USER_SysLevel );
54 int count = isuspendedLocks;
57 _LeaveSysLevel( &USER_SysLevel );
59 return isuspendedLocks;
62 /***********************************************************************
65 * Restore the suspended locks on WND structures
67 void WIN_RestoreWndsLock( int ipreviousLocks )
69 while ( ipreviousLocks-- > 0 )
70 _EnterSysLevel( &USER_SysLevel );
73 /***********************************************************************
74 * create_window_handle
76 * Create a window handle with the server.
78 static WND *create_window_handle( BOOL desktop, INT size )
81 user_handle_t handle = 0;
82 WND *win = HeapAlloc( GetProcessHeap(), 0, size );
84 if (!win) return NULL;
90 SERVER_START_REQ( create_desktop_window )
92 if ((res = !SERVER_CALL_ERR())) handle = req->handle;
98 SERVER_START_REQ( create_window )
100 if ((res = !SERVER_CALL_ERR())) handle = req->handle;
108 HeapFree( GetProcessHeap(), 0, win );
111 user_handles[LOWORD(handle)] = win;
112 win->hwndSelf = handle;
113 win->dwMagic = WND_MAGIC;
119 /***********************************************************************
122 * Free a window handle.
124 static WND *free_window_handle( HWND hwnd )
129 if ((ptr = user_handles[LOWORD(hwnd)]))
131 SERVER_START_REQ( destroy_window )
134 if (!SERVER_CALL_ERR())
135 user_handles[LOWORD(hwnd)] = NULL;
142 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
147 /***********************************************************************
150 * Return a pointer to the WND structure if local to the process.
151 * If ret value is non-NULL, the user lock is held.
153 static WND *get_wnd_ptr( HWND hwnd )
157 if (!hwnd) return NULL;
160 if ((ptr = user_handles[LOWORD(hwnd)]))
162 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
170 /***********************************************************************
173 * Convert a 16-bit window handle to a full 32-bit handle.
175 HWND WIN_Handle32( HWND16 hwnd16 )
178 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
180 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
181 /* do sign extension for -2 and -3 */
182 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
184 if ((ptr = get_wnd_ptr( hwnd )))
186 hwnd = ptr->hwndSelf;
189 else /* may belong to another process */
191 SERVER_START_REQ( get_window_info )
194 if (!SERVER_CALL_ERR()) hwnd = req->full_handle;
202 /***********************************************************************
205 * Return a pointer to the WND structure corresponding to a HWND.
207 WND * WIN_FindWndPtr( HWND hwnd )
211 if (!hwnd) return NULL;
213 if ((ptr = get_wnd_ptr( hwnd )))
215 /* increment destruction monitoring */
220 /* check other processes */
221 if (IsWindow( hwnd ))
223 ERR( "window %04x belongs to other process\n", hwnd );
224 /* DbgBreakPoint(); */
226 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
231 /***********************************************************************
234 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
236 * Returns the locked initialisation pointer
238 WND *WIN_LockWndPtr(WND *initWndPtr)
240 if(!initWndPtr) return 0;
242 /* Lock all WND structures for thread safeness*/
244 /*and increment destruction monitoring*/
245 initWndPtr->irefCount++;
251 /***********************************************************************
254 * Release the pointer to the WND structure.
256 void WIN_ReleaseWndPtr(WND *wndPtr)
260 /*Decrement destruction monitoring value*/
262 /* Check if it's time to release the memory*/
263 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
266 free_window_handle( wndPtr->hwndSelf );
268 else if(wndPtr->irefCount < 0)
270 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
271 ERR("forgot a Lock on %p somewhere\n",wndPtr);
273 /*unlock all WND structures for thread safeness*/
277 /***********************************************************************
280 * Updates the value of oldPtr to newPtr.
282 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
286 tmpWnd = WIN_LockWndPtr(newPtr);
287 WIN_ReleaseWndPtr(*oldPtr);
293 /***********************************************************************
296 * Remove a window from the siblings linked list.
298 void WIN_UnlinkWindow( HWND hwnd )
300 WIN_LinkWindow( hwnd, 0, 0 );
304 /***********************************************************************
307 * Insert a window into the siblings linked list.
308 * The window is inserted after the specified window, which can also
309 * be specified as HWND_TOP or HWND_BOTTOM.
310 * If parent is 0, window is unlinked from the tree.
312 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
314 WND *wndPtr, **ppWnd, *parentPtr = NULL;
317 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return;
318 if (parent && !(parentPtr = WIN_FindWndPtr( parent )))
320 WIN_ReleaseWndPtr(wndPtr);
324 SERVER_START_REQ( link_window )
327 req->parent = parent;
328 req->previous = hwndInsertAfter;
329 ret = !SERVER_CALL_ERR();
334 /* first unlink it if it is linked */
337 ppWnd = &wndPtr->parent->child;
338 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
339 if (*ppWnd) *ppWnd = wndPtr->next;
344 wndPtr->parent = parentPtr;
345 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
347 ppWnd = &parentPtr->child; /* Point to first sibling hwnd */
348 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
349 while (*ppWnd) ppWnd = &(*ppWnd)->next;
351 else /* Normal case */
353 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
354 if (!afterPtr) goto done;
355 ppWnd = &afterPtr->next;
356 WIN_ReleaseWndPtr(afterPtr);
358 wndPtr->next = *ppWnd;
361 else wndPtr->next = NULL; /* unlinked */
364 WIN_ReleaseWndPtr( parentPtr );
365 WIN_ReleaseWndPtr( wndPtr );
369 /***********************************************************************
370 * WIN_FindWinToRepaint
372 * Find a window that needs repaint.
374 HWND WIN_FindWinToRepaint( HWND hwnd )
379 /* Note: the desktop window never gets WM_PAINT messages
380 * The real reason why is because Windows DesktopWndProc
381 * does ValidateRgn inside WM_ERASEBKGND handler.
383 if (hwnd == GetDesktopWindow()) hwnd = 0;
385 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
387 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
389 if (!(pWnd->dwStyle & WS_VISIBLE)) continue;
390 if ((pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)) &&
391 GetWindowThreadProcessId( pWnd->hwndSelf, NULL ) == GetCurrentThreadId())
395 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf )) )
397 WIN_ReleaseWndPtr(pWnd);
405 TRACE("nothing found\n");
408 hwndRet = pWnd->hwndSelf;
410 /* look among siblings if we got a transparent window */
413 if (!(pWnd->dwExStyle & WS_EX_TRANSPARENT) &&
414 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)) &&
415 GetWindowThreadProcessId( pWnd->hwndSelf, NULL ) == GetCurrentThreadId())
417 hwndRet = pWnd->hwndSelf;
418 WIN_ReleaseWndPtr(pWnd);
421 WIN_UpdateWndPtr(&pWnd,pWnd->next);
423 TRACE("found %04x\n",hwndRet);
428 /***********************************************************************
431 * Destroy storage associated to a window. "Internals" p.358
432 * returns a locked wndPtr->next
434 static WND* WIN_DestroyWindow( WND* wndPtr )
436 HWND hwnd = wndPtr->hwndSelf;
439 TRACE("%04x\n", wndPtr->hwndSelf );
441 /* free child windows */
442 WIN_LockWndPtr(wndPtr->child);
443 while ((pWnd = wndPtr->child))
445 wndPtr->child = WIN_DestroyWindow( pWnd );
446 WIN_ReleaseWndPtr(pWnd);
450 * Clear the update region to make sure no WM_PAINT messages will be
451 * generated for this window while processing the WM_NCDESTROY.
453 RedrawWindow( wndPtr->hwndSelf, NULL, 0,
454 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
457 * Send the WM_NCDESTROY to the window being destroyed.
459 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
461 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
463 WINPOS_CheckInternalPos( hwnd );
464 if( hwnd == GetCapture()) ReleaseCapture();
466 /* free resources associated with the window */
468 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
469 PROPERTY_RemoveWindowProps( wndPtr );
471 /* toss stale messages from the queue */
473 QUEUE_CleanupWindow( hwnd );
474 wndPtr->hmemTaskQ = 0;
476 if (!(wndPtr->dwStyle & WS_CHILD))
479 DestroyMenu( wndPtr->wIDmenu );
482 if (wndPtr->hSysMenu)
484 DestroyMenu( wndPtr->hSysMenu );
485 wndPtr->hSysMenu = 0;
487 USER_Driver.pDestroyWindow( wndPtr->hwndSelf );
488 DCE_FreeWindowDCE( wndPtr->hwndSelf ); /* Always do this to catch orphaned DCs */
489 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
490 CLASS_RemoveWindow( wndPtr->class );
491 wndPtr->class = NULL;
492 wndPtr->dwMagic = 0; /* Mark it as invalid */
494 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
499 /***********************************************************************
500 * WIN_DestroyThreadWindows
502 * Destroy all children of 'wnd' owned by the current thread.
503 * Return TRUE if something was done.
505 void WIN_DestroyThreadWindows( HWND hwnd )
510 if (!(list = WIN_ListChildren( hwnd ))) return;
511 for (i = 0; list[i]; i++)
513 if (!IsWindow( list[i] )) continue;
514 if (GetWindowThreadProcessId( list[i], NULL ) == GetCurrentThreadId())
515 DestroyWindow( list[i] );
517 WIN_DestroyThreadWindows( list[i] );
519 HeapFree( GetProcessHeap(), 0, list );
522 /***********************************************************************
523 * WIN_CreateDesktopWindow
525 * Create the desktop window.
527 BOOL WIN_CreateDesktopWindow(void)
529 struct tagCLASS *class;
537 TRACE("Creating desktop window\n");
540 if (!WINPOS_CreateInternalPosAtom() ||
541 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
542 &wndExtra, &winproc, &clsStyle, &dce )))
545 pWndDesktop = create_window_handle( TRUE, sizeof(WND) + wndExtra );
546 if (!pWndDesktop) return FALSE;
547 hwndDesktop = pWndDesktop->hwndSelf;
549 pWndDesktop->tid = 0; /* nobody owns the desktop */
550 pWndDesktop->next = NULL;
551 pWndDesktop->child = NULL;
552 pWndDesktop->parent = NULL;
553 pWndDesktop->owner = 0;
554 pWndDesktop->class = class;
555 pWndDesktop->hInstance = 0;
556 pWndDesktop->rectWindow.left = 0;
557 pWndDesktop->rectWindow.top = 0;
558 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
559 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
560 pWndDesktop->rectClient = pWndDesktop->rectWindow;
561 pWndDesktop->text = NULL;
562 pWndDesktop->hmemTaskQ = 0;
563 pWndDesktop->hrgnUpdate = 0;
564 pWndDesktop->hwndLastActive = hwndDesktop;
565 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
567 pWndDesktop->dwExStyle = 0;
568 pWndDesktop->clsStyle = clsStyle;
569 pWndDesktop->dce = NULL;
570 pWndDesktop->pVScroll = NULL;
571 pWndDesktop->pHScroll = NULL;
572 pWndDesktop->pProp = NULL;
573 pWndDesktop->wIDmenu = 0;
574 pWndDesktop->helpContext = 0;
575 pWndDesktop->flags = 0;
576 pWndDesktop->hSysMenu = 0;
577 pWndDesktop->userdata = 0;
578 pWndDesktop->winproc = winproc;
579 pWndDesktop->cbWndExtra = wndExtra;
581 cs.lpCreateParams = NULL;
587 cs.cx = pWndDesktop->rectWindow.right;
588 cs.cy = pWndDesktop->rectWindow.bottom;
589 cs.style = pWndDesktop->dwStyle;
590 cs.dwExStyle = pWndDesktop->dwExStyle;
592 cs.lpszClass = DESKTOP_CLASS_ATOM;
594 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE )) return FALSE;
596 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
597 WIN_ReleaseWndPtr( pWndDesktop );
602 /***********************************************************************
605 * Fix the coordinates - Helper for WIN_CreateWindowEx.
606 * returns default show mode in sw.
607 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
609 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
611 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
612 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
614 if (cs->style & (WS_CHILD | WS_POPUP))
616 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
617 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
619 else /* overlapped window */
623 GetStartupInfoA( &info );
625 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
627 /* Never believe Microsoft's documentation... CreateWindowEx doc says
628 * that if an overlapped window is created with WS_VISIBLE style bit
629 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
630 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
633 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
634 * 2) it does not ignore the y parameter as the docs claim; instead, it
635 * uses it as second parameter to ShowWindow() unless y is either
636 * CW_USEDEFAULT or CW_USEDEFAULT16.
638 * The fact that we didn't do 2) caused bogus windows pop up when wine
639 * was running apps that were using this obscure feature. Example -
640 * calc.exe that comes with Win98 (only Win98, it's different from
641 * the one that comes with Win95 and NT)
643 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
644 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
645 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
648 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
650 if (info.dwFlags & STARTF_USESIZE)
652 cs->cx = info.dwXSize;
653 cs->cy = info.dwYSize;
655 else /* if no other hint from the app, pick 3/4 of the screen real estate */
658 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
659 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
660 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
667 /***********************************************************************
670 * Implementation of CreateWindowEx().
672 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
673 WINDOWPROCTYPE type )
676 struct tagCLASS *classPtr;
678 HWND hwnd, hwndLinkAfter;
679 POINT maxSize, maxPos, minTrack, maxTrack;
684 BOOL unicode = (type == WIN_PROC_32W);
686 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%04x menu=%04x inst=%08x params=%p\n",
687 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
688 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
689 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
690 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
692 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
693 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
695 /* Find the parent window */
699 /* Make sure parent is valid */
700 if (!IsWindow( cs->hwndParent ))
702 WARN("Bad parent %04x\n", cs->hwndParent );
705 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
706 WARN("No parent for child window\n" );
707 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
710 /* Find the window class */
711 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
712 &wndExtra, &winproc, &clsStyle, &dce )))
714 WARN("Bad class '%s'\n", cs->lpszClass );
718 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
720 /* Correct the window style - stage 1
722 * These are patches that appear to affect both the style loaded into the
723 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
725 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
726 * why does the user get to set it?
729 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
730 * tested for WS_POPUP
732 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
733 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
734 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
735 cs->dwExStyle |= WS_EX_WINDOWEDGE;
737 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
739 /* Create the window structure */
741 if (!(wndPtr = create_window_handle( FALSE,
742 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
744 TRACE("out of memory\n" );
747 hwnd = wndPtr->hwndSelf;
749 /* Fill the window structure */
751 wndPtr->tid = GetCurrentThreadId();
753 wndPtr->child = NULL;
755 if ((cs->style & WS_CHILD) && cs->hwndParent)
757 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
759 WIN_ReleaseWndPtr(wndPtr->parent);
763 wndPtr->parent = pWndDesktop;
764 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
767 wndPtr->owner = GetAncestor( cs->hwndParent, GA_ROOT );
771 wndPtr->class = classPtr;
772 wndPtr->winproc = winproc;
773 wndPtr->hInstance = cs->hInstance;
775 wndPtr->hmemTaskQ = InitThreadInput16( 0, 0 );
776 wndPtr->hrgnUpdate = 0;
778 wndPtr->hwndLastActive = hwnd;
779 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
780 wndPtr->dwExStyle = cs->dwExStyle;
781 wndPtr->clsStyle = clsStyle;
783 wndPtr->helpContext = 0;
784 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
785 wndPtr->pVScroll = NULL;
786 wndPtr->pHScroll = NULL;
787 wndPtr->pProp = NULL;
788 wndPtr->userdata = 0;
789 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
790 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
791 wndPtr->cbWndExtra = wndExtra;
793 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
795 /* Call the WH_CBT hook */
797 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
798 ? HWND_BOTTOM : HWND_TOP;
800 if (HOOK_IsHooked( WH_CBT ))
806 cbtc.hwndInsertAfter = hwndLinkAfter;
807 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND,
808 (WPARAM)hwnd, (LPARAM)&cbtc)
809 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND,
810 (WPARAM)hwnd, (LPARAM)&cbtc);
813 TRACE("CBT-hook returned 0\n");
814 free_window_handle( hwnd );
815 CLASS_RemoveWindow( classPtr );
821 /* Correct the window style - stage 2 */
823 if (!(cs->style & WS_CHILD))
825 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
826 if (!(cs->style & WS_POPUP))
828 wndPtr->dwStyle |= WS_CAPTION;
829 wndPtr->flags |= WIN_NEED_SIZE;
833 /* Get class or window DC if needed */
835 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
836 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
837 else wndPtr->dce = NULL;
839 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
841 wndPtr->rectWindow.left = cs->x;
842 wndPtr->rectWindow.top = cs->y;
843 wndPtr->rectWindow.right = cs->x + cs->cx;
844 wndPtr->rectWindow.bottom = cs->y + cs->cy;
845 wndPtr->rectClient = wndPtr->rectWindow;
847 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
849 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
851 WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
852 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
853 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
854 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
855 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
858 if (cs->cx < 0) cs->cx = 0;
859 if (cs->cy < 0) cs->cy = 0;
861 wndPtr->rectWindow.left = cs->x;
862 wndPtr->rectWindow.top = cs->y;
863 wndPtr->rectWindow.right = cs->x + cs->cx;
864 wndPtr->rectWindow.bottom = cs->y + cs->cy;
865 wndPtr->rectClient = wndPtr->rectWindow;
867 /* Set the window menu */
869 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
871 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
874 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
877 if (HIWORD(cs->hInstance))
878 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
880 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
882 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
886 else wndPtr->wIDmenu = (UINT)cs->hMenu;
888 if (!USER_Driver.pCreateWindow( wndPtr->hwndSelf, cs, unicode))
890 WARN("aborted by WM_xxCREATE!\n");
891 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
892 CLASS_RemoveWindow( classPtr );
893 WIN_ReleaseWndPtr(wndPtr);
897 if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
899 /* Notify the parent window only */
901 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
902 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
903 if( !IsWindow(hwnd) )
910 if (cs->style & WS_VISIBLE)
912 /* in case WS_VISIBLE got set in the meantime */
913 wndPtr->dwStyle &= ~WS_VISIBLE;
914 ShowWindow( hwnd, sw );
917 /* Call WH_SHELL hook */
919 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
920 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0 );
922 TRACE("created window %04x\n", hwnd);
924 WIN_ReleaseWndPtr(wndPtr);
929 /***********************************************************************
930 * CreateWindow (USER.41)
932 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
933 DWORD style, INT16 x, INT16 y, INT16 width,
934 INT16 height, HWND16 parent, HMENU16 menu,
935 HINSTANCE16 instance, LPVOID data )
937 return CreateWindowEx16( 0, className, windowName, style,
938 x, y, width, height, parent, menu, instance, data );
942 /***********************************************************************
943 * CreateWindowEx (USER.452)
945 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
946 LPCSTR windowName, DWORD style, INT16 x,
947 INT16 y, INT16 width, INT16 height,
948 HWND16 parent, HMENU16 menu,
949 HINSTANCE16 instance, LPVOID data )
955 /* Find the class atom */
957 if (HIWORD(className))
959 if (!(classAtom = GlobalFindAtomA( className )))
961 ERR( "bad class name %s\n", debugres_a(className) );
967 classAtom = LOWORD(className);
968 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
970 ERR( "bad atom %x\n", classAtom);
976 /* Fix the coordinates */
978 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
979 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
980 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
981 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
983 /* Create the window */
985 cs.lpCreateParams = data;
986 cs.hInstance = (HINSTANCE)instance;
987 cs.hMenu = (HMENU)menu;
988 cs.hwndParent = WIN_Handle32( parent );
990 cs.lpszName = windowName;
991 cs.lpszClass = className;
992 cs.dwExStyle = exStyle;
994 return WIN_Handle16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
998 /***********************************************************************
999 * CreateWindowExA (USER32.@)
1001 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1002 LPCSTR windowName, DWORD style, INT x,
1003 INT y, INT width, INT height,
1004 HWND parent, HMENU menu,
1005 HINSTANCE instance, LPVOID data )
1012 instance=GetModuleHandleA(NULL);
1014 if(exStyle & WS_EX_MDICHILD)
1015 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1017 /* Find the class atom */
1019 if (HIWORD(className))
1021 if (!(classAtom = GlobalFindAtomA( className )))
1023 ERR( "bad class name %s\n", debugres_a(className) );
1029 classAtom = LOWORD(className);
1030 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1032 ERR( "bad atom %x\n", classAtom);
1038 /* Create the window */
1040 cs.lpCreateParams = data;
1041 cs.hInstance = instance;
1043 cs.hwndParent = parent;
1049 cs.lpszName = windowName;
1050 cs.lpszClass = className;
1051 cs.dwExStyle = exStyle;
1053 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1057 /***********************************************************************
1058 * CreateWindowExW (USER32.@)
1060 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1061 LPCWSTR windowName, DWORD style, INT x,
1062 INT y, INT width, INT height,
1063 HWND parent, HMENU menu,
1064 HINSTANCE instance, LPVOID data )
1071 instance=GetModuleHandleA(NULL);
1073 if(exStyle & WS_EX_MDICHILD)
1074 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1076 /* Find the class atom */
1078 if (HIWORD(className))
1080 if (!(classAtom = GlobalFindAtomW( className )))
1082 ERR( "bad class name %s\n", debugres_w(className) );
1088 classAtom = LOWORD(className);
1089 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1091 ERR( "bad atom %x\n", classAtom);
1097 /* Create the window */
1099 cs.lpCreateParams = data;
1100 cs.hInstance = instance;
1102 cs.hwndParent = parent;
1108 cs.lpszName = windowName;
1109 cs.lpszClass = className;
1110 cs.dwExStyle = exStyle;
1112 /* Note: we rely on the fact that CREATESTRUCTA and */
1113 /* CREATESTRUCTW have the same layout. */
1114 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1118 /***********************************************************************
1119 * WIN_SendDestroyMsg
1121 static void WIN_SendDestroyMsg( HWND hwnd )
1123 if( CARET_GetHwnd() == hwnd) DestroyCaret();
1124 if (USER_Driver.pResetSelectionOwner)
1125 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1128 * Send the WM_DESTROY to the window.
1130 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1133 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1134 * make sure that the window still exists when we come back.
1141 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1143 /* start from the end (FIXME: is this needed?) */
1144 for (i = 0; pWndArray[i]; i++) ;
1148 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1150 HeapFree( GetProcessHeap(), 0, pWndArray );
1153 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1157 /***********************************************************************
1158 * DestroyWindow (USER32.@)
1160 BOOL WINAPI DestroyWindow( HWND hwnd )
1166 hwnd = WIN_GetFullHandle( hwnd );
1167 TRACE("(%04x)\n", hwnd);
1169 /* Initialization */
1171 if (hwnd == GetDesktopWindow()) return FALSE; /* Can't destroy desktop */
1173 /* Look whether the focus is within the tree of windows we will
1177 if (h == hwnd || IsChild( hwnd, h ))
1179 HWND parent = GetAncestor( hwnd, GA_PARENT );
1180 if (parent == GetDesktopWindow()) parent = 0;
1186 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0L) ) return FALSE;
1188 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1189 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1191 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L );
1192 /* FIXME: clean up palette - see "Internals" p.352 */
1195 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1196 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1198 /* Notify the parent window only */
1199 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1200 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1201 if( !IsWindow(hwnd) )
1208 if (USER_Driver.pResetSelectionOwner)
1209 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1211 /* Hide the window */
1213 if (wndPtr->dwStyle & WS_VISIBLE)
1215 ShowWindow( hwnd, SW_HIDE );
1216 if (!IsWindow(hwnd))
1223 /* Recursively destroy owned windows */
1225 if( !(wndPtr->dwStyle & WS_CHILD) )
1230 HWND *list = WIN_ListChildren( wndPtr->parent->hwndSelf );
1233 for (i = 0; list[i]; i++)
1235 WND *siblingPtr = WIN_FindWndPtr( list[i] );
1236 if (!siblingPtr) continue;
1237 if (siblingPtr->owner == hwnd)
1239 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1241 WIN_ReleaseWndPtr( siblingPtr );
1242 DestroyWindow( list[i] );
1246 else siblingPtr->owner = 0;
1248 WIN_ReleaseWndPtr( siblingPtr );
1250 HeapFree( GetProcessHeap(), 0, list );
1252 if (!got_one) break;
1255 WINPOS_ActivateOtherWindow(wndPtr->hwndSelf);
1259 WND *owner = WIN_FindWndPtr( wndPtr->owner );
1260 if (owner->hwndLastActive == hwnd) owner->hwndLastActive = wndPtr->owner;
1261 WIN_ReleaseWndPtr( owner );
1265 /* Send destroy messages */
1267 WIN_SendDestroyMsg( hwnd );
1268 if (!IsWindow(hwnd))
1274 /* Unlink now so we won't bother with the children later on */
1276 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1278 /* Destroy the window storage */
1280 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1283 WIN_ReleaseWndPtr(wndPtr);
1288 /***********************************************************************
1289 * CloseWindow (USER32.@)
1291 BOOL WINAPI CloseWindow( HWND hwnd )
1293 WND * wndPtr = WIN_FindWndPtr( hwnd );
1296 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1301 ShowWindow( hwnd, SW_MINIMIZE );
1304 WIN_ReleaseWndPtr(wndPtr);
1310 /***********************************************************************
1311 * OpenIcon (USER32.@)
1313 BOOL WINAPI OpenIcon( HWND hwnd )
1315 if (!IsIconic( hwnd )) return FALSE;
1316 ShowWindow( hwnd, SW_SHOWNORMAL );
1321 /***********************************************************************
1324 * Implementation of FindWindow() and FindWindowEx().
1326 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1331 WCHAR *buffer = NULL;
1333 if (!parent) parent = GetDesktopWindow();
1336 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1337 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1340 if (!(list = WIN_ListChildren( parent )))
1342 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1348 child = WIN_GetFullHandle( child );
1349 while (list[i] && list[i] != child) i++;
1350 if (!list[i]) return 0;
1351 i++; /* start from next window */
1354 for ( ; list[i]; i++)
1356 if (className && (GetClassWord(list[i], GCW_ATOM) != className))
1357 continue; /* Not the right class */
1359 /* Now check the title */
1361 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1364 HeapFree( GetProcessHeap(), 0, list );
1365 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1367 /* In this case we need to check whether other processes
1368 own a window with the given paramters on the Desktop,
1369 but we don't, so let's at least warn about it */
1370 if (!retvalue) FIXME("Returning 0 without checking other processes\n");
1376 /***********************************************************************
1377 * FindWindowA (USER32.@)
1379 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1381 HWND ret = FindWindowExA( 0, 0, className, title );
1382 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1387 /***********************************************************************
1388 * FindWindowExA (USER32.@)
1390 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1391 LPCSTR className, LPCSTR title )
1399 /* If the atom doesn't exist, then no class */
1400 /* with this name exists either. */
1401 if (!(atom = GlobalFindAtomA( className )))
1403 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1408 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1409 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1410 HeapFree( GetProcessHeap(), 0, buffer );
1415 /***********************************************************************
1416 * FindWindowExW (USER32.@)
1418 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1419 LPCWSTR className, LPCWSTR title )
1425 /* If the atom doesn't exist, then no class */
1426 /* with this name exists either. */
1427 if (!(atom = GlobalFindAtomW( className )))
1429 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1433 return WIN_FindWindow( parent, child, atom, title );
1437 /***********************************************************************
1438 * FindWindowW (USER32.@)
1440 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1442 return FindWindowExW( 0, 0, className, title );
1446 /**********************************************************************
1447 * GetDesktopWindow (USER32.@)
1449 HWND WINAPI GetDesktopWindow(void)
1451 if (pWndDesktop) return pWndDesktop->hwndSelf;
1452 ERR( "You need the -desktop option when running with native USER\n" );
1458 /*******************************************************************
1459 * EnableWindow (USER32.@)
1461 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1466 TRACE("( %x, %d )\n", hwnd, enable);
1468 if (USER_Driver.pEnableWindow)
1469 return USER_Driver.pEnableWindow( hwnd, enable );
1471 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1472 hwnd = wndPtr->hwndSelf; /* make it a full handle */
1474 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1476 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1478 wndPtr->dwStyle &= ~WS_DISABLED; /* Enable window */
1479 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1481 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1483 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1485 wndPtr->dwStyle |= WS_DISABLED; /* Disable window */
1487 if (hwnd == GetFocus())
1488 SetFocus( 0 ); /* A disabled window can't have the focus */
1490 if (hwnd == GetCapture())
1491 ReleaseCapture(); /* A disabled window can't capture the mouse */
1493 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1495 WIN_ReleaseWndPtr(wndPtr);
1500 /***********************************************************************
1501 * IsWindowEnabled (USER32.@)
1503 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1508 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1509 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1510 WIN_ReleaseWndPtr(wndPtr);
1516 /***********************************************************************
1517 * IsWindowUnicode (USER32.@)
1519 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1524 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1525 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1526 WIN_ReleaseWndPtr(wndPtr);
1531 /**********************************************************************
1532 * GetWindowWord (USER32.@)
1534 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1537 WND * wndPtr = WIN_FindWndPtr( hwnd );
1538 if (!wndPtr) return 0;
1541 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1543 WARN("Invalid offset %d\n", offset );
1546 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1547 WIN_ReleaseWndPtr(wndPtr);
1551 WIN_ReleaseWndPtr(wndPtr);
1554 case GWL_HWNDPARENT:
1555 return GetWindowLongW( hwnd, offset );
1559 LONG ret = GetWindowLongW( hwnd, offset );
1561 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1565 WARN("Invalid offset %d\n", offset );
1571 /**********************************************************************
1572 * SetWindowWord (USER32.@)
1574 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1577 WND * wndPtr = WIN_FindWndPtr( hwnd );
1578 if (!wndPtr) return 0;
1581 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1583 WARN("Invalid offset %d\n", offset );
1584 WIN_ReleaseWndPtr(wndPtr);
1587 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1590 WIN_ReleaseWndPtr(wndPtr);
1594 WIN_ReleaseWndPtr(wndPtr);
1599 case GWL_HWNDPARENT:
1600 return SetWindowLongW( hwnd, offset, (UINT)newval );
1602 WARN("Invalid offset %d\n", offset );
1608 /**********************************************************************
1611 * Helper function for GetWindowLong().
1613 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1616 WND * wndPtr = WIN_FindWndPtr( hwnd );
1617 if (!wndPtr) return 0;
1620 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1622 WARN("Invalid offset %d\n", offset );
1626 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1627 /* Special case for dialog window procedure */
1628 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1630 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1637 case GWL_USERDATA: retvalue = wndPtr->userdata;
1639 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1641 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1643 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1645 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1648 case GWL_HWNDPARENT: retvalue = (LONG)GetParent(hwnd);
1650 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1653 WARN("Unknown offset %d\n", offset );
1657 WIN_ReleaseWndPtr(wndPtr);
1662 /**********************************************************************
1665 * Helper function for SetWindowLong().
1667 * 0 is the failure code. However, in the case of failure SetLastError
1668 * must be set to distinguish between a 0 return value and a failure.
1670 * FIXME: The error values for SetLastError may not be right. Can
1671 * someone check with the real thing?
1673 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1674 WINDOWPROCTYPE type )
1677 WND * wndPtr = WIN_FindWndPtr( hwnd );
1680 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1684 /* Is this the right error? */
1685 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1691 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1693 WARN("Invalid offset %d\n", offset );
1695 /* Is this the right error? */
1696 SetLastError( ERROR_OUTOFMEMORY );
1701 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1702 /* Special case for dialog window procedure */
1703 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1705 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1706 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1707 type, WIN_PROC_WINDOW );
1714 ptr = (DWORD*)&wndPtr->wIDmenu;
1717 retval = SetWindowWord( hwnd, offset, newval );
1720 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1721 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1722 type, WIN_PROC_WINDOW );
1725 style.styleOld = wndPtr->dwStyle;
1726 style.styleNew = newval;
1727 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1728 wndPtr->dwStyle = style.styleNew;
1729 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1730 retval = style.styleOld;
1734 ptr = &wndPtr->userdata;
1737 style.styleOld = wndPtr->dwExStyle;
1738 style.styleNew = newval;
1739 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1740 wndPtr->dwExStyle = style.styleNew;
1741 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1742 retval = style.styleOld;
1746 WARN("Invalid offset %d\n", offset );
1748 /* Don't think this is right error but it should do */
1749 SetLastError( ERROR_OUTOFMEMORY );
1757 WIN_ReleaseWndPtr(wndPtr);
1762 /**********************************************************************
1763 * GetWindowLong (USER.135)
1765 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1767 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
1771 /**********************************************************************
1772 * GetWindowLongA (USER32.@)
1774 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
1776 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1780 /**********************************************************************
1781 * GetWindowLongW (USER32.@)
1783 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
1785 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1789 /**********************************************************************
1790 * SetWindowLong (USER.136)
1792 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1794 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
1798 /**********************************************************************
1799 * SetWindowLongA (USER32.@)
1801 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
1803 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1807 /**********************************************************************
1808 * SetWindowLongW (USER32.@) Set window attribute
1810 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
1811 * value in a window's extra memory.
1813 * The _hwnd_ parameter specifies the window. is the handle to a
1814 * window that has extra memory. The _newval_ parameter contains the
1815 * new attribute or extra memory value. If positive, the _offset_
1816 * parameter is the byte-addressed location in the window's extra
1817 * memory to set. If negative, _offset_ specifies the window
1818 * attribute to set, and should be one of the following values:
1820 * GWL_EXSTYLE The window's extended window style
1822 * GWL_STYLE The window's window style.
1824 * GWL_WNDPROC Pointer to the window's window procedure.
1826 * GWL_HINSTANCE The window's pplication instance handle.
1828 * GWL_ID The window's identifier.
1830 * GWL_USERDATA The window's user-specified data.
1832 * If the window is a dialog box, the _offset_ parameter can be one of
1833 * the following values:
1835 * DWL_DLGPROC The address of the window's dialog box procedure.
1837 * DWL_MSGRESULT The return value of a message
1838 * that the dialog box procedure processed.
1840 * DWL_USER Application specific information.
1844 * If successful, returns the previous value located at _offset_. Otherwise,
1849 * Extra memory for a window class is specified by a nonzero cbWndExtra
1850 * parameter of the WNDCLASS structure passed to RegisterClass() at the
1851 * time of class creation.
1853 * Using GWL_WNDPROC to set a new window procedure effectively creates
1854 * a window subclass. Use CallWindowProc() in the new windows procedure
1855 * to pass messages to the superclass's window procedure.
1857 * The user data is reserved for use by the application which created
1860 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
1861 * instead, call the EnableWindow() function to change the window's
1864 * Do not use GWL_HWNDPARENT to reset the window's parent, use
1865 * SetParent() instead.
1868 * When offset is GWL_STYLE and the calling app's ver is 4.0,
1869 * it sends WM_STYLECHANGING before changing the settings
1870 * and WM_STYLECHANGED afterwards.
1871 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
1875 * GWL_STYLE does not dispatch WM_STYLE... messages.
1882 LONG WINAPI SetWindowLongW(
1883 HWND hwnd, /* [in] window to alter */
1884 INT offset, /* [in] offset, in bytes, of location to alter */
1885 LONG newval /* [in] new value of location */
1887 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1891 /*******************************************************************
1892 * GetWindowTextA (USER32.@)
1894 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
1896 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
1900 /*******************************************************************
1901 * InternalGetWindowText (USER32.@)
1903 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
1905 WND *win = WIN_FindWndPtr( hwnd );
1907 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
1908 else lpString[0] = 0;
1909 WIN_ReleaseWndPtr( win );
1910 return strlenW(lpString);
1914 /*******************************************************************
1915 * GetWindowTextW (USER32.@)
1917 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
1919 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
1924 /*******************************************************************
1925 * SetWindowText (USER32.@)
1926 * SetWindowTextA (USER32.@)
1928 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
1930 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1934 /*******************************************************************
1935 * SetWindowTextW (USER32.@)
1937 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
1939 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1943 /*******************************************************************
1944 * GetWindowTextLengthA (USER32.@)
1946 INT WINAPI GetWindowTextLengthA( HWND hwnd )
1948 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1951 /*******************************************************************
1952 * GetWindowTextLengthW (USER32.@)
1954 INT WINAPI GetWindowTextLengthW( HWND hwnd )
1956 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1960 /*******************************************************************
1961 * IsWindow (USER32.@)
1963 BOOL WINAPI IsWindow( HWND hwnd )
1969 if ((ptr = user_handles[LOWORD(hwnd)]))
1971 ret = ((ptr->dwMagic == WND_MAGIC) && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf));
1977 /* check other processes */
1978 SERVER_START_REQ( get_window_info )
1981 ret = !SERVER_CALL_ERR();
1988 /***********************************************************************
1989 * GetWindowThreadProcessId (USER32.@)
1991 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
1997 if ((ptr = user_handles[LOWORD(hwnd)]))
1999 if ((ptr->dwMagic == WND_MAGIC) && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
2001 /* got a valid window */
2003 if (process) *process = GetCurrentProcessId();
2005 else SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2011 /* check other processes */
2012 SERVER_START_REQ( get_window_info )
2015 if (!SERVER_CALL_ERR())
2017 tid = (DWORD)req->tid;
2018 if (process) *process = (DWORD)req->pid;
2026 /*****************************************************************
2027 * GetParent (USER32.@)
2029 HWND WINAPI GetParent( HWND hwnd )
2034 if ((wndPtr = WIN_FindWndPtr(hwnd)))
2036 if (wndPtr->dwStyle & WS_CHILD)
2037 retvalue = wndPtr->parent->hwndSelf;
2038 else if (wndPtr->dwStyle & WS_POPUP)
2039 retvalue = wndPtr->owner;
2040 WIN_ReleaseWndPtr(wndPtr);
2046 /*****************************************************************
2047 * GetAncestor (USER32.@)
2049 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2054 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2055 if (wndPtr->hwndSelf == GetDesktopWindow()) goto done;
2060 WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
2063 while (wndPtr->parent->hwndSelf != GetDesktopWindow())
2064 WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
2067 while (wndPtr->parent->hwndSelf != GetDesktopWindow())
2068 WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
2069 while (wndPtr && wndPtr->owner)
2071 WND *ptr = WIN_FindWndPtr( wndPtr->owner );
2072 WIN_ReleaseWndPtr( wndPtr );
2077 ret = wndPtr ? wndPtr->hwndSelf : 0;
2079 WIN_ReleaseWndPtr( wndPtr );
2084 /*****************************************************************
2085 * SetParent (USER32.@)
2087 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2093 if (!parent) parent = GetDesktopWindow();
2094 else parent = WIN_GetFullHandle( parent );
2097 if (WIN_GetFullHandle(hwnd) == GetDesktopWindow() || !IsWindow( parent ))
2099 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2103 if (USER_Driver.pSetParent)
2104 return USER_Driver.pSetParent( hwnd, parent );
2106 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2108 dwStyle = wndPtr->dwStyle;
2110 /* Windows hides the window first, then shows it again
2111 * including the WM_SHOWWINDOW messages and all */
2112 if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
2114 retvalue = wndPtr->parent->hwndSelf; /* old parent */
2115 if (parent != retvalue)
2117 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2119 if (parent != GetDesktopWindow()) /* a child window */
2121 if (!(dwStyle & WS_CHILD))
2123 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2124 if (menu) DestroyMenu( menu );
2128 WIN_ReleaseWndPtr( wndPtr );
2130 /* SetParent additionally needs to make hwnd the topmost window
2131 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2132 WM_WINDOWPOSCHANGED notification messages.
2134 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2135 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|
2136 ((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2137 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2138 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2143 /*******************************************************************
2144 * IsChild (USER32.@)
2146 BOOL WINAPI IsChild( HWND parent, HWND child )
2148 HWND *list = WIN_ListParents( child );
2152 if (!list) return FALSE;
2153 parent = WIN_GetFullHandle( parent );
2154 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2155 ret = (list[i] != 0);
2156 HeapFree( GetProcessHeap(), 0, list );
2161 /***********************************************************************
2162 * IsWindowVisible (USER32.@)
2164 BOOL WINAPI IsWindowVisible( HWND hwnd )
2170 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2171 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2172 for (i = 0; list[i]; i++)
2173 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2175 HeapFree( GetProcessHeap(), 0, list );
2180 /***********************************************************************
2181 * WIN_IsWindowDrawable
2183 * hwnd is drawable when it is visible, all parents are not
2184 * minimized, and it is itself not minimized unless we are
2185 * trying to draw its default class icon.
2187 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2193 if (!(wnd->dwStyle & WS_VISIBLE)) return FALSE;
2194 if ((wnd->dwStyle & WS_MINIMIZE) &&
2195 icon && GetClassLongA( wnd->hwndSelf, GCL_HICON )) return FALSE;
2197 if (!(list = WIN_ListParents( wnd->hwndSelf ))) return TRUE;
2198 for (i = 0; list[i]; i++)
2199 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2202 HeapFree( GetProcessHeap(), 0, list );
2207 /*******************************************************************
2208 * GetTopWindow (USER32.@)
2210 HWND WINAPI GetTopWindow( HWND hwnd )
2212 if (!hwnd) hwnd = GetDesktopWindow();
2213 return GetWindow( hwnd, GW_CHILD );
2217 /*******************************************************************
2218 * GetWindow (USER32.@)
2220 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2224 WND * wndPtr = WIN_FindWndPtr( hwnd );
2225 if (!wndPtr) return 0;
2226 hwnd = wndPtr->hwndSelf; /* make it a full handle */
2231 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2235 if (!wndPtr->parent)
2237 retval = 0; /* Desktop window */
2240 while (wndPtr->next)
2242 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2244 retval = wndPtr->hwndSelf;
2248 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2252 if (!wndPtr->parent)
2254 retval = 0; /* Desktop window */
2257 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2258 if (wndPtr->hwndSelf == hwnd)
2260 retval = 0; /* First in list */
2263 while (wndPtr->next)
2265 if (wndPtr->next->hwndSelf == hwnd)
2267 retval = wndPtr->hwndSelf;
2270 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2276 retval = wndPtr->owner;
2280 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2285 WIN_ReleaseWndPtr(wndPtr);
2290 /***********************************************************************
2291 * WIN_InternalShowOwnedPopups
2293 * Internal version of ShowOwnedPopups; Wine functions should use this
2294 * to avoid interfering with application calls to ShowOwnedPopups
2295 * and to make sure the application can't prevent showing/hiding.
2297 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2301 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2305 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2307 if (!win_array) return TRUE;
2310 * Show windows Lowest first, Highest last to preserve Z-Order
2312 while (win_array[count]) count++;
2313 while (--count >= 0)
2315 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2316 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2318 if (pWnd->dwStyle & WS_POPUP)
2322 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2323 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2326 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2328 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2329 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2334 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2335 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2336 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2339 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2341 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2342 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2343 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2347 WIN_ReleaseWndPtr( pWnd );
2349 HeapFree( GetProcessHeap(), 0, win_array );
2354 /*******************************************************************
2355 * ShowOwnedPopups (USER32.@)
2357 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2361 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2363 if (!win_array) return TRUE;
2365 while (win_array[count]) count++;
2366 while (--count >= 0)
2368 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2369 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2371 if (pWnd->dwStyle & WS_POPUP)
2375 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2377 /* In Windows, ShowOwnedPopups(TRUE) generates
2378 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2379 * regardless of the state of the owner
2381 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2382 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2387 if (IsWindowVisible(pWnd->hwndSelf))
2389 /* In Windows, ShowOwnedPopups(FALSE) generates
2390 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2391 * regardless of the state of the owner
2393 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2394 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2398 WIN_ReleaseWndPtr( pWnd );
2400 HeapFree( GetProcessHeap(), 0, win_array );
2405 /*******************************************************************
2406 * GetLastActivePopup (USER32.@)
2408 HWND WINAPI GetLastActivePopup( HWND hwnd )
2411 WND *wndPtr =WIN_FindWndPtr(hwnd);
2412 if (!wndPtr) return hwnd;
2413 retval = wndPtr->hwndLastActive;
2414 if (!IsWindow( retval )) retval = wndPtr->hwndSelf;
2415 WIN_ReleaseWndPtr(wndPtr);
2420 /*******************************************************************
2423 * Build an array of all parents of a given window, starting with
2424 * the immediate parent. The array must be freed with HeapFree.
2425 * Returns NULL if window is a top-level window.
2427 HWND *WIN_ListParents( HWND hwnd )
2429 WND *parent, *wndPtr = WIN_FindWndPtr( hwnd );
2433 /* First count the windows */
2435 if (!wndPtr) return NULL;
2437 parent = wndPtr->parent;
2438 while (parent && parent->hwndSelf != GetDesktopWindow())
2441 parent = parent->parent;
2446 if ((list = HeapAlloc( GetProcessHeap(), 0, sizeof(HWND) * (count + 1) )))
2448 parent = wndPtr->parent;
2449 for (i = 0; i < count; i++)
2451 list[i] = parent->hwndSelf;
2452 parent = parent->parent;
2458 WIN_ReleaseWndPtr( wndPtr );
2463 /*******************************************************************
2466 * Build an array of the children of a given window. The array must be
2467 * freed with HeapFree. Returns NULL when no windows are found.
2469 HWND *WIN_ListChildren( HWND hwnd )
2471 WND *pWnd, *wndPtr = WIN_FindWndPtr( hwnd );
2475 /* First count the windows */
2477 if (!wndPtr) return NULL;
2479 pWnd = WIN_LockWndPtr(wndPtr->child);
2483 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2488 /* Now build the list of all windows */
2490 if ((list = HeapAlloc( GetProcessHeap(), 0, sizeof(HWND) * (count + 1))))
2492 for (pWnd = WIN_LockWndPtr(wndPtr->child), phwnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2494 *phwnd++ = pWnd->hwndSelf;
2497 WIN_ReleaseWndPtr(pWnd);
2503 WIN_ReleaseWndPtr( wndPtr );
2508 /*******************************************************************
2509 * EnumWindows (USER32.@)
2511 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2517 /* We have to build a list of all windows first, to avoid */
2518 /* unpleasant side-effects, for instance if the callback */
2519 /* function changes the Z-order of the windows. */
2521 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return FALSE;
2523 /* Now call the callback function for every window */
2525 iWndsLocks = WIN_SuspendWndsLock();
2526 for (i = 0; list[i]; i++)
2528 /* Make sure that the window still exists */
2529 if (!IsWindow( list[i] )) continue;
2530 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2532 WIN_RestoreWndsLock(iWndsLocks);
2533 HeapFree( GetProcessHeap(), 0, list );
2538 /**********************************************************************
2539 * EnumTaskWindows16 (USER.225)
2541 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2544 TDB *tdb = TASK_GetPtr( hTask );
2545 if (!tdb) return FALSE;
2546 return EnumThreadWindows( (DWORD)tdb->teb->tid, (WNDENUMPROC)func, lParam );
2550 /**********************************************************************
2551 * EnumThreadWindows (USER32.@)
2553 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2558 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return FALSE;
2560 /* Now call the callback function for every window */
2562 iWndsLocks = WIN_SuspendWndsLock();
2563 for (i = 0; list[i]; i++)
2565 if (GetWindowThreadProcessId( list[i], NULL ) != id) continue;
2566 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);