2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
11 #include "wine/winbase16.h"
18 #include "sysmetrics.h"
19 #include "cursoricon.h"
23 #include "nonclient.h"
26 #include "shm_main_blk.h"
28 #include "clipboard.h"
39 #ifndef X_DISPLAY_MISSING
40 extern DESKTOP_DRIVER X11DRV_DESKTOP_Driver;
41 extern WND_DRIVER X11DRV_WND_Driver;
42 #else /* X_DISPLAY_MISSING */
43 extern DESKTOP_DRIVER TTYDRV_DESKTOP_Driver;
44 extern WND_DRIVER TTYDRV_WND_Driver;
45 #endif /* X_DISPLAY_MISSING */
48 static WND *pWndDesktop = NULL;
50 static HWND hwndSysModal = 0;
52 static WORD wDragWidth = 4;
53 static WORD wDragHeight= 3;
56 static CRITICAL_SECTION WIN_CritSection;
57 static int ilockCounter = 0;
59 /***********************************************************************
62 * Locks access to all WND structures for thread safeness
66 EnterCriticalSection(&WIN_CritSection);
68 TRACE(win,"All windows hinstances have been locked (lock #%i)\n",ilockCounter);
71 /***********************************************************************
74 * Unlocks access to all WND structures
79 TRACE(win,"Lock #%i been unlocked\n",ilockCounter+1);
83 LeaveCriticalSection(&WIN_CritSection);
84 TRACE(win,"All windows hinstances have been unlocked\n");
86 else if(ilockCounter < 0)
88 ERR(win,"Negative lock reference ==> missing call to WIN_Lock!\n");
91 /***********************************************************************
94 * Suspend the lock on WND structures.
95 * Returns the number of locks suspended
97 int WIN_SuspendWndsLock()
99 int isuspendedLocks = ilockCounter;
101 LeaveCriticalSection(&WIN_CritSection);
102 TRACE(win,"All windows hinstances locks have been suspended\n");
103 return isuspendedLocks;
107 /***********************************************************************
108 * WIN_RestoreWndsLock
110 * Restore the suspended locks on WND structures
112 void WIN_Unlock(int ipreviousLocks)
114 EnterCriticalSection(&WIN_CritSection);
115 ilockCounter = ipreviousLocks;
117 /***********************************************************************
120 * Return a pointer to the WND structure corresponding to a HWND.
122 WND * WIN_FindWndPtr( HWND hwnd )
126 if (!hwnd || HIWORD(hwnd)) goto error2;
127 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
128 /* Lock all WND structures for thread safeness
130 and increment destruction monitoring value
133 if (ptr->dwMagic != WND_MAGIC) goto error;
134 if (ptr->hwndSelf != hwnd)
136 ERR( win, "Can't happen: hwnd %04x self pointer is %04x\n",
137 hwnd, ptr->hwndSelf );
142 /* Unlock all WND structures for thread safeness
144 and decrement destruction monitoring value
148 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
152 /***********************************************************************
155 * Release the pointer to the WND structure.
157 void WIN_ReleaseWndPtr(WND *wndPtr)
160 /*Decrement destruction monitoring value
162 Check if it's time to release the memory
163 if(wndPtr->irefCount == 0)
165 Add memory releasing code here
167 unlock all WND structures for thread safeness
174 /***********************************************************************
177 * Dump the content of a window structure to stderr.
179 void WIN_DumpWindow( HWND hwnd )
185 if (!(ptr = WIN_FindWndPtr( hwnd )))
187 WARN( win, "%04x is not a window handle\n", hwnd );
191 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
192 strcpy( className, "#NULL#" );
194 TRACE( win, "Window %04x (%p):\n", hwnd, ptr );
195 DUMP( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
196 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
197 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
198 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
199 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
200 ptr->next, ptr->child, ptr->parent, ptr->owner,
201 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
202 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
203 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
204 ptr->text ? ptr->text : "",
205 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
206 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
207 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
208 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
210 if (ptr->class->cbWndExtra)
212 DUMP( "extra bytes:" );
213 for (i = 0; i < ptr->class->cbWndExtra; i++)
214 DUMP( " %02x", *((BYTE*)ptr->wExtra+i) );
221 /***********************************************************************
224 * Walk the windows tree and print each window on stderr.
226 void WIN_WalkWindows( HWND hwnd, int indent )
231 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop;
234 WARN( win, "Invalid window handle %04x\n", hwnd );
238 if (!indent) /* first time around */
239 DUMP( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
240 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
245 DUMP( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
247 GlobalGetAtomName16(ptr->class->atomName,className,sizeof(className));
249 DUMP( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
250 (DWORD)ptr, ptr->hmemTaskQ, className,
251 (UINT)ptr->dwStyle, (UINT)ptr->winproc,
252 ptr->text?ptr->text:"<null>");
254 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
259 /***********************************************************************
262 * Remove a window from the siblings linked list.
264 BOOL WIN_UnlinkWindow( HWND hwnd )
266 WND *wndPtr, **ppWnd;
268 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
269 ppWnd = &wndPtr->parent->child;
270 while (*ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
271 *ppWnd = wndPtr->next;
276 /***********************************************************************
279 * Insert a window into the siblings linked list.
280 * The window is inserted after the specified window, which can also
281 * be specified as HWND_TOP or HWND_BOTTOM.
283 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
285 WND *wndPtr, **ppWnd;
287 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
289 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
291 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
292 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
293 while (*ppWnd) ppWnd = &(*ppWnd)->next;
295 else /* Normal case */
297 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
298 if (!afterPtr) return FALSE;
299 ppWnd = &afterPtr->next;
301 wndPtr->next = *ppWnd;
307 /***********************************************************************
308 * WIN_FindWinToRepaint
310 * Find a window that needs repaint.
312 HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE16 hQueue )
315 WND *pWnd = pWndDesktop;
317 /* Note: the desktop window never gets WM_PAINT messages
318 * The real reason why is because Windows DesktopWndProc
319 * does ValidateRgn inside WM_ERASEBKGND handler.
322 pWnd = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop->child;
324 for ( ; pWnd ; pWnd = pWnd->next )
326 if (!(pWnd->dwStyle & WS_VISIBLE))
328 TRACE(win, "skipping window %04x\n",
332 if ((pWnd->hmemTaskQ == hQueue) &&
333 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))) break;
336 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
342 hwndRet = pWnd->hwndSelf;
344 /* look among siblings if we got a transparent window */
345 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
346 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
350 if (pWnd) hwndRet = pWnd->hwndSelf;
351 TRACE(win,"found %04x\n",hwndRet);
356 /***********************************************************************
359 * Destroy storage associated to a window. "Internals" p.358
361 static WND* WIN_DestroyWindow( WND* wndPtr )
363 HWND hwnd = wndPtr->hwndSelf;
366 TRACE(win, "%04x\n", wndPtr->hwndSelf );
370 DDE_DestroyWindow(wndPtr->hwndSelf);
371 #endif /* CONFIG_IPC */
373 /* free child windows */
375 while ((pWnd = wndPtr->child))
376 wndPtr->child = WIN_DestroyWindow( pWnd );
378 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
380 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
382 WINPOS_CheckInternalPos( wndPtr );
383 if( hwnd == GetCapture()) ReleaseCapture();
385 /* free resources associated with the window */
387 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
388 PROPERTY_RemoveWindowProps( wndPtr );
390 wndPtr->dwMagic = 0; /* Mark it as invalid */
392 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
394 if (wndPtr->hrgnUpdate > 1) DeleteObject( wndPtr->hrgnUpdate );
395 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
398 /* toss stale messages from the queue */
400 if( wndPtr->hmemTaskQ )
402 BOOL bPostQuit = FALSE;
403 WPARAM wQuitParam = 0;
404 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) QUEUE_Lock(wndPtr->hmemTaskQ);
407 while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
409 if( qmsg->msg.message == WM_QUIT )
412 wQuitParam = qmsg->msg.wParam;
414 QUEUE_RemoveMsg(msgQ, qmsg);
419 /* repost WM_QUIT to make sure this app exits its message loop */
420 if( bPostQuit ) PostQuitMessage(wQuitParam);
421 wndPtr->hmemTaskQ = 0;
424 if (!(wndPtr->dwStyle & WS_CHILD))
425 if (wndPtr->wIDmenu) DestroyMenu( (HMENU)wndPtr->wIDmenu );
426 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
427 wndPtr->pDriver->pDestroyWindow( wndPtr );
428 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
429 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
430 wndPtr->hwndSelf = 0;
431 wndPtr->class->cWindows--;
432 wndPtr->class = NULL;
435 wndPtr->pDriver->pFinalize(wndPtr);
436 USER_HEAP_FREE( hwnd );
440 /***********************************************************************
441 * WIN_ResetQueueWindows
443 * Reset the queue of all the children of a given window.
444 * Return TRUE if something was done.
446 BOOL WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
450 if (hNew) /* Set a new queue */
452 for (wnd = wnd->child; (wnd); wnd = wnd->next)
454 if (wnd->hmemTaskQ == hQueue)
456 wnd->hmemTaskQ = hNew;
460 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
463 else /* Queue is being destroyed */
467 WND *tmp = wnd->child;
471 if (tmp->hmemTaskQ == hQueue)
473 DestroyWindow( tmp->hwndSelf );
477 if (tmp->child && WIN_ResetQueueWindows(tmp->child,hQueue,0))
488 /***********************************************************************
489 * WIN_CreateDesktopWindow
491 * Create the desktop window.
493 BOOL WIN_CreateDesktopWindow(void)
499 TRACE(win,"Creating desktop window\n");
501 if (!ICONTITLE_Init() ||
502 !WINPOS_CreateInternalPosAtom() ||
503 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
506 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
507 if (!hwndDesktop) return FALSE;
508 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
510 pDesktop = (DESKTOP *) pWndDesktop->wExtra;
511 #ifndef X_DISPLAY_MISSING
512 pDesktop->pDriver = &X11DRV_DESKTOP_Driver;
513 pWndDesktop->pDriver = &X11DRV_WND_Driver;
514 #else /* X_DISPLAY_MISSING */
515 pDesktop->pDriver = &TTYDRV_DESKTOP_Driver;
516 pWndDesktop->pDriver = &TTYDRV_WND_Driver;
517 #endif /* X_DISPLAY_MISSING */
519 pDesktop->pDriver->pInitialize(pDesktop);
520 pWndDesktop->pDriver->pInitialize(pWndDesktop);
522 pWndDesktop->next = NULL;
523 pWndDesktop->child = NULL;
524 pWndDesktop->parent = NULL;
525 pWndDesktop->owner = NULL;
526 pWndDesktop->class = class;
527 pWndDesktop->dwMagic = WND_MAGIC;
528 pWndDesktop->hwndSelf = hwndDesktop;
529 pWndDesktop->hInstance = 0;
530 pWndDesktop->rectWindow.left = 0;
531 pWndDesktop->rectWindow.top = 0;
532 pWndDesktop->rectWindow.right = SYSMETRICS_CXSCREEN;
533 pWndDesktop->rectWindow.bottom = SYSMETRICS_CYSCREEN;
534 pWndDesktop->rectClient = pWndDesktop->rectWindow;
535 pWndDesktop->text = NULL;
536 pWndDesktop->hmemTaskQ = GetFastQueue16();
537 pWndDesktop->hrgnUpdate = 0;
538 pWndDesktop->hwndLastActive = hwndDesktop;
539 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
541 pWndDesktop->dwExStyle = 0;
542 pWndDesktop->dce = NULL;
543 pWndDesktop->pVScroll = NULL;
544 pWndDesktop->pHScroll = NULL;
545 pWndDesktop->pProp = NULL;
546 pWndDesktop->wIDmenu = 0;
547 pWndDesktop->helpContext = 0;
548 pWndDesktop->flags = 0;
549 pWndDesktop->hSysMenu = 0;
550 pWndDesktop->userdata = 0;
551 pWndDesktop->winproc = (WNDPROC16)class->winproc;
553 /* FIXME: How do we know if it should be Unicode or not */
554 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop, class, FALSE))
557 SendMessageA( hwndDesktop, WM_NCCREATE, 0, 0 );
558 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
563 /***********************************************************************
566 * Implementation of CreateWindowEx().
568 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
569 BOOL win32, BOOL unicode )
573 HWND16 hwnd, hwndLinkAfter;
574 POINT maxSize, maxPos, minTrack, maxTrack;
575 LRESULT (CALLBACK *localSend32)(HWND, UINT, WPARAM, LPARAM);
577 TRACE(win, "%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
578 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
579 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
580 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
581 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
583 /* Find the parent window */
587 /* Make sure parent is valid */
588 if (!IsWindow( cs->hwndParent ))
590 WARN( win, "Bad parent %04x\n", cs->hwndParent );
593 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
594 WARN( win, "No parent for child window\n" );
595 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
598 /* Find the window class */
599 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
602 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
603 WARN( win, "Bad class '%s'\n", buffer );
607 /* Fix the coordinates */
609 if (cs->x == CW_USEDEFAULT)
611 PDB *pdb = PROCESS_Current();
612 if ( !(cs->style & (WS_CHILD | WS_POPUP))
613 && (pdb->env_db->startup_info->dwFlags & STARTF_USEPOSITION) )
615 cs->x = pdb->env_db->startup_info->dwX;
616 cs->y = pdb->env_db->startup_info->dwY;
624 if (cs->cx == CW_USEDEFAULT)
626 PDB *pdb = PROCESS_Current();
627 if ( !(cs->style & (WS_CHILD | WS_POPUP))
628 && (pdb->env_db->startup_info->dwFlags & STARTF_USESIZE) )
630 cs->cx = pdb->env_db->startup_info->dwXSize;
631 cs->cy = pdb->env_db->startup_info->dwYSize;
635 cs->cx = 600; /* FIXME */
640 /* Create the window structure */
642 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
643 - sizeof(wndPtr->wExtra) )))
645 TRACE(win, "out of memory\n" );
649 /* Fill the window structure */
651 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
653 wndPtr->child = NULL;
655 if ((cs->style & WS_CHILD) && cs->hwndParent)
657 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
658 wndPtr->owner = NULL;
662 wndPtr->parent = pWndDesktop;
663 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
664 wndPtr->owner = NULL;
666 wndPtr->owner = WIN_GetTopParentPtr(WIN_FindWndPtr(cs->hwndParent));
669 wndPtr->pDriver = wndPtr->parent->pDriver;
670 wndPtr->pDriver->pInitialize(wndPtr);
672 wndPtr->class = classPtr;
673 wndPtr->winproc = classPtr->winproc;
674 wndPtr->dwMagic = WND_MAGIC;
675 wndPtr->hwndSelf = hwnd;
676 wndPtr->hInstance = cs->hInstance;
678 wndPtr->hmemTaskQ = GetFastQueue16();
679 wndPtr->hrgnUpdate = 0;
680 wndPtr->hwndLastActive = hwnd;
681 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
682 wndPtr->dwExStyle = cs->dwExStyle;
684 wndPtr->helpContext = 0;
685 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
686 wndPtr->pVScroll = NULL;
687 wndPtr->pHScroll = NULL;
688 wndPtr->pProp = NULL;
689 wndPtr->userdata = 0;
690 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
691 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
693 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
695 /* Call the WH_CBT hook */
697 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
698 ? HWND_BOTTOM : HWND_TOP;
700 if (HOOK_IsHooked( WH_CBT ))
706 cbtc.hwndInsertAfter = hwndLinkAfter;
707 ret = unicode ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
708 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
711 TRACE(win, "CBT-hook returned 0\n");
712 wndPtr->pDriver->pFinalize(wndPtr);
713 USER_HEAP_FREE( hwnd );
718 /* Increment class window counter */
720 classPtr->cWindows++;
722 /* Correct the window style */
724 if (!(cs->style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
726 wndPtr->dwStyle |= WS_CAPTION | WS_CLIPSIBLINGS;
727 wndPtr->flags |= WIN_NEED_SIZE;
729 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
731 /* Get class or window DC if needed */
733 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
734 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
735 else wndPtr->dce = NULL;
737 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
739 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
741 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
742 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
743 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
744 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
745 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
748 if(cs->style & WS_CHILD)
750 if(cs->cx < 0) cs->cx = 0;
751 if(cs->cy < 0) cs->cy = 0;
755 if (cs->cx <= 0) cs->cx = 1;
756 if (cs->cy <= 0) cs->cy = 1;
759 wndPtr->rectWindow.left = cs->x;
760 wndPtr->rectWindow.top = cs->y;
761 wndPtr->rectWindow.right = cs->x + cs->cx;
762 wndPtr->rectWindow.bottom = cs->y + cs->cy;
763 wndPtr->rectClient = wndPtr->rectWindow;
765 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
768 /* Set the window menu */
770 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
772 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
775 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
776 if (classPtr->menuNameA)
777 cs->hMenu = HIWORD(classPtr->menuNameA) ?
778 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
779 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
781 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
784 if (HIWORD(cs->hInstance))
785 cs->hMenu = LoadMenuA(cs->hInstance,PTR_SEG_TO_LIN(menuName));
787 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
789 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
794 else wndPtr->wIDmenu = (UINT)cs->hMenu;
796 /* Send the WM_CREATE message
797 * Perhaps we shouldn't allow width/height changes as well.
798 * See p327 in "Internals".
801 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
803 localSend32 = unicode ? SendMessageW : SendMessageA;
804 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
806 /* Insert the window in the linked list */
808 WIN_LinkWindow( hwnd, hwndLinkAfter );
810 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
811 NULL, NULL, 0, &wndPtr->rectClient );
812 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
813 maxPos.y - wndPtr->rectWindow.top);
814 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
816 /* Send the size messages */
818 if (!(wndPtr->flags & WIN_NEED_SIZE))
821 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
822 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
823 WARN(win,"sending bogus WM_SIZE message 0x%08lx\n",
824 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
825 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
826 SendMessageA( hwnd, WM_SIZE, SIZE_RESTORED,
827 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
828 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
829 SendMessageA( hwnd, WM_MOVE, 0,
830 MAKELONG( wndPtr->rectClient.left,
831 wndPtr->rectClient.top ) );
834 /* Show the window, maximizing or minimizing if needed */
836 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
839 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
840 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
841 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
842 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
843 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
844 : SWP_NOZORDER | SWP_FRAMECHANGED;
845 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
846 newPos.right, newPos.bottom, swFlag );
849 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
851 /* Notify the parent window only */
853 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
854 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
855 if( !IsWindow(hwnd) ) return 0;
858 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
860 /* Call WH_SHELL hook */
862 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
863 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
865 TRACE(win, "created window %04x\n", hwnd);
868 WIN_UnlinkWindow( hwnd );
871 /* Abort window creation */
873 WARN(win, "aborted by WM_xxCREATE!\n");
874 WIN_DestroyWindow( wndPtr );
879 /***********************************************************************
880 * CreateWindow16 (USER.41)
882 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
883 DWORD style, INT16 x, INT16 y, INT16 width,
884 INT16 height, HWND16 parent, HMENU16 menu,
885 HINSTANCE16 instance, LPVOID data )
887 return CreateWindowEx16( 0, className, windowName, style,
888 x, y, width, height, parent, menu, instance, data );
892 /***********************************************************************
893 * CreateWindowEx16 (USER.452)
895 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
896 LPCSTR windowName, DWORD style, INT16 x,
897 INT16 y, INT16 width, INT16 height,
898 HWND16 parent, HMENU16 menu,
899 HINSTANCE16 instance, LPVOID data )
904 /* Find the class atom */
906 if (!(classAtom = GlobalFindAtomA( className )))
908 fprintf( stderr, "CreateWindowEx16: bad class name " );
909 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
910 else fprintf( stderr, "'%s'\n", className );
914 /* Fix the coordinates */
916 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
917 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
918 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
919 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
921 /* Create the window */
923 cs.lpCreateParams = data;
924 cs.hInstance = (HINSTANCE)instance;
925 cs.hMenu = (HMENU)menu;
926 cs.hwndParent = (HWND)parent;
928 cs.lpszName = windowName;
929 cs.lpszClass = className;
930 cs.dwExStyle = exStyle;
931 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
935 /***********************************************************************
936 * CreateWindowEx32A (USER32.83)
938 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
939 LPCSTR windowName, DWORD style, INT x,
940 INT y, INT width, INT height,
941 HWND parent, HMENU menu,
942 HINSTANCE instance, LPVOID data )
947 if(exStyle & WS_EX_MDICHILD)
948 return MDI_CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
949 /* Find the class atom */
951 if (!(classAtom = GlobalFindAtomA( className )))
953 fprintf( stderr, "CreateWindowEx32A: bad class name " );
954 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
955 else fprintf( stderr, "'%s'\n", className );
959 /* Create the window */
961 cs.lpCreateParams = data;
962 cs.hInstance = instance;
964 cs.hwndParent = parent;
970 cs.lpszName = windowName;
971 cs.lpszClass = className;
972 cs.dwExStyle = exStyle;
973 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
977 /***********************************************************************
978 * CreateWindowEx32W (USER32.84)
980 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
981 LPCWSTR windowName, DWORD style, INT x,
982 INT y, INT width, INT height,
983 HWND parent, HMENU menu,
984 HINSTANCE instance, LPVOID data )
989 if(exStyle & WS_EX_MDICHILD)
990 return MDI_CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
992 /* Find the class atom */
994 if (!(classAtom = GlobalFindAtomW( className )))
996 if (HIWORD(className))
998 LPSTR cn = HEAP_strdupWtoA( GetProcessHeap(), 0, className );
999 WARN( win, "Bad class name '%s'\n",cn);
1000 HeapFree( GetProcessHeap(), 0, cn );
1003 WARN( win, "Bad class name %p\n", className );
1007 /* Create the window */
1009 cs.lpCreateParams = data;
1010 cs.hInstance = instance;
1012 cs.hwndParent = parent;
1018 cs.lpszName = windowName;
1019 cs.lpszClass = className;
1020 cs.dwExStyle = exStyle;
1021 /* Note: we rely on the fact that CREATESTRUCT32A and */
1022 /* CREATESTRUCT32W have the same layout. */
1023 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, TRUE, TRUE );
1027 /***********************************************************************
1030 static void WIN_CheckFocus( WND* pWnd )
1032 if( GetFocus16() == pWnd->hwndSelf )
1033 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
1036 /***********************************************************************
1037 * WIN_SendDestroyMsg
1039 static void WIN_SendDestroyMsg( WND* pWnd )
1041 WIN_CheckFocus(pWnd);
1043 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1044 CLIPBOARD_GetDriver()->pResetOwner( pWnd, TRUE );
1046 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1048 if( IsWindow(pWnd->hwndSelf) )
1050 WND* pChild = pWnd->child;
1053 WIN_SendDestroyMsg( pChild );
1054 pChild = pChild->next;
1056 WIN_CheckFocus(pWnd);
1059 WARN(win, "\tdestroyed itself while in WM_DESTROY!\n");
1063 /***********************************************************************
1064 * DestroyWindow16 (USER.53)
1066 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1068 return DestroyWindow(hwnd);
1072 /***********************************************************************
1073 * DestroyWindow32 (USER32.135)
1075 BOOL WINAPI DestroyWindow( HWND hwnd )
1079 TRACE(win, "(%04x)\n", hwnd);
1081 /* Initialization */
1083 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1084 if (wndPtr == pWndDesktop) return FALSE; /* Can't destroy desktop */
1088 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1091 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1093 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1094 /* FIXME: clean up palette - see "Internals" p.352 */
1097 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1098 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1100 /* Notify the parent window only */
1101 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1102 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1103 if( !IsWindow(hwnd) ) return TRUE;
1106 CLIPBOARD_GetDriver()->pResetOwner( wndPtr, FALSE ); /* before the window is unmapped */
1108 /* Hide the window */
1110 if (wndPtr->dwStyle & WS_VISIBLE)
1112 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1113 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1114 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1115 if (!IsWindow(hwnd)) return TRUE;
1118 /* Recursively destroy owned windows */
1120 if( !(wndPtr->dwStyle & WS_CHILD) )
1122 /* make sure top menu popup doesn't get destroyed */
1123 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1127 WND *siblingPtr = wndPtr->parent->child; /* First sibling */
1130 if (siblingPtr->owner == wndPtr)
1132 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1135 siblingPtr->owner = NULL;
1137 siblingPtr = siblingPtr->next;
1139 if (siblingPtr) DestroyWindow( siblingPtr->hwndSelf );
1143 if( !Options.managed || EVENT_CheckFocus() )
1144 WINPOS_ActivateOtherWindow(wndPtr);
1146 if( wndPtr->owner &&
1147 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1148 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1151 /* Send destroy messages */
1153 WIN_SendDestroyMsg( wndPtr );
1154 if (!IsWindow(hwnd)) return TRUE;
1156 /* Unlink now so we won't bother with the children later on */
1158 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1160 /* Destroy the window storage */
1162 WIN_DestroyWindow( wndPtr );
1167 /***********************************************************************
1168 * CloseWindow16 (USER.43)
1170 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1172 return CloseWindow( hwnd );
1176 /***********************************************************************
1177 * CloseWindow32 (USER32.56)
1179 BOOL WINAPI CloseWindow( HWND hwnd )
1181 WND * wndPtr = WIN_FindWndPtr( hwnd );
1182 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD)) return FALSE;
1183 ShowWindow( hwnd, SW_MINIMIZE );
1188 /***********************************************************************
1189 * OpenIcon16 (USER.44)
1191 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1193 return OpenIcon( hwnd );
1197 /***********************************************************************
1198 * OpenIcon32 (USER32.410)
1200 BOOL WINAPI OpenIcon( HWND hwnd )
1202 if (!IsIconic( hwnd )) return FALSE;
1203 ShowWindow( hwnd, SW_SHOWNORMAL );
1208 /***********************************************************************
1211 * Implementation of FindWindow() and FindWindowEx().
1213 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1217 CLASS *pClass = NULL;
1221 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1224 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent)) return 0;
1226 else if (pWnd->parent != pWndDesktop) return 0;
1231 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : pWndDesktop)) return 0;
1234 if (!pWnd) return 0;
1236 /* For a child window, all siblings will have the same hInstance, */
1237 /* so we can look for the class once and for all. */
1239 if (className && (pWnd->dwStyle & WS_CHILD))
1241 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1246 for ( ; pWnd; pWnd = pWnd->next)
1248 if (className && !(pWnd->dwStyle & WS_CHILD))
1250 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance)))
1251 continue; /* Skip this window */
1254 if (pClass && (pWnd->class != pClass))
1255 continue; /* Not the right class */
1257 /* Now check the title */
1259 if (!title) return pWnd->hwndSelf;
1260 if (pWnd->text && !strcmp( pWnd->text, title )) return pWnd->hwndSelf;
1267 /***********************************************************************
1268 * FindWindow16 (USER.50)
1270 HWND16 WINAPI FindWindow16( SEGPTR className, LPCSTR title )
1272 return FindWindowEx16( 0, 0, className, title );
1276 /***********************************************************************
1277 * FindWindowEx16 (USER.427)
1279 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child,
1280 SEGPTR className, LPCSTR title )
1284 TRACE(win, "%04x %04x '%s' '%s'\n", parent,
1285 child, HIWORD(className)?(char *)PTR_SEG_TO_LIN(className):"",
1286 title ? title : "");
1290 /* If the atom doesn't exist, then no class */
1291 /* with this name exists either. */
1292 if (!(atom = GlobalFindAtom16( className ))) return 0;
1294 return WIN_FindWindow( parent, child, atom, title );
1298 /***********************************************************************
1299 * FindWindow32A (USER32.198)
1301 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1303 HWND ret = FindWindowExA( 0, 0, className, title );
1304 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1309 /***********************************************************************
1310 * FindWindowEx32A (USER32.199)
1312 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1313 LPCSTR className, LPCSTR title )
1319 /* If the atom doesn't exist, then no class */
1320 /* with this name exists either. */
1321 if (!(atom = GlobalFindAtomA( className )))
1323 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1327 return WIN_FindWindow( parent, child, atom, title );
1331 /***********************************************************************
1332 * FindWindowEx32W (USER32.200)
1334 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1335 LPCWSTR className, LPCWSTR title )
1343 /* If the atom doesn't exist, then no class */
1344 /* with this name exists either. */
1345 if (!(atom = GlobalFindAtomW( className )))
1347 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1351 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1352 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1353 HeapFree( GetProcessHeap(), 0, buffer );
1358 /***********************************************************************
1359 * FindWindow32W (USER32.201)
1361 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1363 return FindWindowExW( 0, 0, className, title );
1367 /**********************************************************************
1370 WND *WIN_GetDesktop(void)
1376 /**********************************************************************
1377 * GetDesktopWindow16 (USER.286)
1379 HWND16 WINAPI GetDesktopWindow16(void)
1381 return (HWND16)pWndDesktop->hwndSelf;
1385 /**********************************************************************
1386 * GetDesktopWindow32 (USER32.232)
1388 HWND WINAPI GetDesktopWindow(void)
1390 return pWndDesktop->hwndSelf;
1394 /**********************************************************************
1395 * GetDesktopHwnd (USER.278)
1397 * Exactly the same thing as GetDesktopWindow(), but not documented.
1398 * Don't ask me why...
1400 HWND16 WINAPI GetDesktopHwnd16(void)
1402 return (HWND16)pWndDesktop->hwndSelf;
1406 /*******************************************************************
1407 * EnableWindow16 (USER.34)
1409 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1411 return EnableWindow( hwnd, enable );
1415 /*******************************************************************
1416 * EnableWindow32 (USER32.172)
1418 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1422 TRACE(win,"EnableWindow32: ( %x, %d )\n", hwnd, enable);
1424 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1425 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1428 wndPtr->dwStyle &= ~WS_DISABLED;
1429 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1432 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1434 /* Disable window */
1435 wndPtr->dwStyle |= WS_DISABLED;
1436 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus() ))
1438 SetFocus( 0 ); /* A disabled window can't have the focus */
1440 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
1442 ReleaseCapture(); /* A disabled window can't capture the mouse */
1444 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1447 return ((wndPtr->dwStyle & WS_DISABLED) != 0);
1451 /***********************************************************************
1452 * IsWindowEnabled16 (USER.35)
1454 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1456 return IsWindowEnabled(hWnd);
1460 /***********************************************************************
1461 * IsWindowEnabled32 (USER32.349)
1463 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1467 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1468 return !(wndPtr->dwStyle & WS_DISABLED);
1472 /***********************************************************************
1473 * IsWindowUnicode (USER32.350)
1475 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1479 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1480 return (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1484 /**********************************************************************
1485 * GetWindowWord16 (USER.133)
1487 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1489 return GetWindowWord( hwnd, offset );
1493 /**********************************************************************
1494 * GetWindowWord32 (USER32.314)
1496 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1498 WND * wndPtr = WIN_FindWndPtr( hwnd );
1499 if (!wndPtr) return 0;
1502 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1504 WARN( win, "Invalid offset %d\n", offset );
1507 return *(WORD *)(((char *)wndPtr->wExtra) + offset);
1512 if (HIWORD(wndPtr->wIDmenu))
1513 WARN( win,"GWW_ID: discards high bits of 0x%08x!\n",
1515 return (WORD)wndPtr->wIDmenu;
1516 case GWW_HWNDPARENT:
1517 return GetParent( hwnd );
1519 if (HIWORD(wndPtr->hInstance))
1520 WARN(win,"GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1522 return (WORD)wndPtr->hInstance;
1524 WARN( win, "Invalid offset %d\n", offset );
1530 /**********************************************************************
1531 * WIN_GetWindowInstance
1533 HINSTANCE WIN_GetWindowInstance( HWND hwnd )
1535 WND * wndPtr = WIN_FindWndPtr( hwnd );
1536 if (!wndPtr) return (HINSTANCE)0;
1537 return wndPtr->hInstance;
1541 /**********************************************************************
1542 * SetWindowWord16 (USER.134)
1544 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1546 return SetWindowWord( hwnd, offset, newval );
1550 /**********************************************************************
1551 * SetWindowWord32 (USER32.524)
1553 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1556 WND * wndPtr = WIN_FindWndPtr( hwnd );
1557 if (!wndPtr) return 0;
1560 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1562 WARN( win, "Invalid offset %d\n", offset );
1565 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1569 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1570 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1571 case GWW_HWNDPARENT: return SetParent( hwnd, newval );
1573 WARN( win, "Invalid offset %d\n", offset );
1582 /**********************************************************************
1585 * Helper function for GetWindowLong().
1587 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1590 WND * wndPtr = WIN_FindWndPtr( hwnd );
1591 if (!wndPtr) return 0;
1594 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1596 WARN( win, "Invalid offset %d\n", offset );
1599 retval = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1600 /* Special case for dialog window procedure */
1601 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1602 return (LONG)WINPROC_GetProc( (HWINDOWPROC)retval, type );
1607 case GWL_USERDATA: return wndPtr->userdata;
1608 case GWL_STYLE: return wndPtr->dwStyle;
1609 case GWL_EXSTYLE: return wndPtr->dwExStyle;
1610 case GWL_ID: return (LONG)wndPtr->wIDmenu;
1611 case GWL_WNDPROC: return (LONG)WINPROC_GetProc( wndPtr->winproc,
1613 case GWL_HWNDPARENT: return GetParent(hwnd);
1614 case GWL_HINSTANCE: return wndPtr->hInstance;
1616 WARN( win, "Unknown offset %d\n", offset );
1622 /**********************************************************************
1625 * Helper function for SetWindowLong().
1627 * 0 is the failure code. However, in the case of failure SetLastError
1628 * must be set to distinguish between a 0 return value and a failure.
1630 * FIXME: The error values for SetLastError may not be right. Can
1631 * someone check with the real thing?
1633 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1634 WINDOWPROCTYPE type )
1637 WND * wndPtr = WIN_FindWndPtr( hwnd );
1640 TRACE(win,"%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1644 /* Is this the right error? */
1645 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1651 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1653 WARN( win, "Invalid offset %d\n", offset );
1655 /* Is this the right error? */
1656 SetLastError( ERROR_OUTOFMEMORY );
1660 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1661 /* Special case for dialog window procedure */
1662 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1664 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1665 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1666 type, WIN_PROC_WINDOW );
1673 ptr = (DWORD*)&wndPtr->wIDmenu;
1676 return SetWindowWord( hwnd, offset, newval );
1678 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1679 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1680 type, WIN_PROC_WINDOW );
1683 style.styleOld = wndPtr->dwStyle;
1684 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
1685 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
1687 if (wndPtr->flags & WIN_ISWIN32)
1688 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1689 wndPtr->dwStyle = style.styleNew;
1690 if (wndPtr->flags & WIN_ISWIN32)
1691 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1692 return style.styleOld;
1695 ptr = &wndPtr->userdata;
1698 style.styleOld = wndPtr->dwExStyle;
1699 style.styleNew = newval;
1700 if (wndPtr->flags & WIN_ISWIN32)
1701 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1702 wndPtr->dwExStyle = newval;
1703 if (wndPtr->flags & WIN_ISWIN32)
1704 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1705 return style.styleOld;
1708 WARN( win, "Invalid offset %d\n", offset );
1710 /* Don't think this is right error but it should do */
1711 SetLastError( ERROR_OUTOFMEMORY );
1721 /**********************************************************************
1722 * GetWindowLong16 (USER.135)
1724 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1726 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
1730 /**********************************************************************
1731 * GetWindowLong32A (USER32.305)
1733 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
1735 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1739 /**********************************************************************
1740 * GetWindowLong32W (USER32.306)
1742 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
1744 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1748 /**********************************************************************
1749 * SetWindowLong16 (USER.136)
1751 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1753 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1757 /**********************************************************************
1758 * SetWindowLong32A (USER32.517)
1760 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
1762 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1766 /**********************************************************************
1767 * SetWindowLong32W (USER32.518) Set window attribute
1769 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
1770 * value in a window's extra memory.
1772 * The _hwnd_ parameter specifies the window. is the handle to a
1773 * window that has extra memory. The _newval_ parameter contains the
1774 * new attribute or extra memory value. If positive, the _offset_
1775 * parameter is the byte-addressed location in the window's extra
1776 * memory to set. If negative, _offset_ specifies the window
1777 * attribute to set, and should be one of the following values:
1779 * GWL_EXSTYLE The window's extended window style
1781 * GWL_STYLE The window's window style.
1783 * GWL_WNDPROC Pointer to the window's window procedure.
1785 * GWL_HINSTANCE The window's pplication instance handle.
1787 * GWL_ID The window's identifier.
1789 * GWL_USERDATA The window's user-specified data.
1791 * If the window is a dialog box, the _offset_ parameter can be one of
1792 * the following values:
1794 * DWL_DLGPROC The address of the window's dialog box procedure.
1796 * DWL_MSGRESULT The return value of a message
1797 * that the dialog box procedure processed.
1799 * DWL_USER Application specific information.
1803 * If successful, returns the previous value located at _offset_. Otherwise,
1808 * Extra memory for a window class is specified by a nonzero cbWndExtra
1809 * parameter of the WNDCLASS structure passed to RegisterClass() at the
1810 * time of class creation.
1812 * Using GWL_WNDPROC to set a new window procedure effectively creates
1813 * a window subclass. Use CallWindowProc() in the new windows procedure
1814 * to pass messages to the superclass's window procedure.
1816 * The user data is reserved for use by the application which created
1819 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
1820 * instead, call the EnableWindow() function to change the window's
1823 * Do not use GWL_HWNDPARENT to reset the window's parent, use
1824 * SetParent() instead.
1827 * When offset is GWL_STYLE and the calling app's ver is 4.0,
1828 * it sends WM_STYLECHANGING before changing the settings
1829 * and WM_STYLECHANGED afterwards.
1830 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
1834 * GWL_STYLE does not dispatch WM_STYLE... messages.
1841 LONG WINAPI SetWindowLongW(
1842 HWND hwnd, /* window to alter */
1843 INT offset, /* offset, in bytes, of location to alter */
1844 LONG newval /* new value of location */
1846 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1850 /*******************************************************************
1851 * GetWindowText16 (USER.36)
1853 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
1855 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1859 /*******************************************************************
1860 * GetWindowText32A (USER32.309)
1862 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
1864 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
1868 /*******************************************************************
1869 * InternalGetWindowText (USER32.326)
1871 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
1873 FIXME(win,"(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
1874 return GetWindowTextW(hwnd,lpString,nMaxCount);
1878 /*******************************************************************
1879 * GetWindowText32W (USER32.312)
1881 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
1883 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
1888 /*******************************************************************
1889 * SetWindowText16 (USER.37)
1891 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
1893 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1897 /*******************************************************************
1898 * SetWindowText32A (USER32.521)
1900 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
1902 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1906 /*******************************************************************
1907 * SetWindowText32W (USER32.523)
1909 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
1911 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1915 /*******************************************************************
1916 * GetWindowTextLength16 (USER.38)
1918 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
1920 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1924 /*******************************************************************
1925 * GetWindowTextLength32A (USER32.310)
1927 INT WINAPI GetWindowTextLengthA( HWND hwnd )
1929 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1932 /*******************************************************************
1933 * GetWindowTextLength32W (USER32.311)
1935 INT WINAPI GetWindowTextLengthW( HWND hwnd )
1937 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1941 /*******************************************************************
1942 * IsWindow16 (USER.47)
1944 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
1946 return IsWindow( hwnd );
1949 void WINAPI WIN16_IsWindow16( CONTEXT *context )
1951 WORD *stack = PTR_SEG_OFF_TO_LIN(SS_reg(context), SP_reg(context));
1952 HWND16 hwnd = (HWND16)stack[2];
1954 AX_reg(context) = IsWindow( hwnd );
1955 ES_reg(context) = USER_HeapSel;
1959 /*******************************************************************
1960 * IsWindow32 (USER32.348)
1962 BOOL WINAPI IsWindow( HWND hwnd )
1964 WND * wndPtr = WIN_FindWndPtr( hwnd );
1965 return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
1969 /*****************************************************************
1970 * GetParent16 (USER.46)
1972 HWND16 WINAPI GetParent16( HWND16 hwnd )
1974 return (HWND16)GetParent( hwnd );
1978 /*****************************************************************
1979 * GetParent32 (USER32.278)
1981 HWND WINAPI GetParent( HWND hwnd )
1983 WND *wndPtr = WIN_FindWndPtr(hwnd);
1984 if ((!wndPtr) || (!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD)))) return 0;
1985 wndPtr = (wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner;
1986 return wndPtr ? wndPtr->hwndSelf : 0;
1989 /*****************************************************************
1992 * Get the top-level parent for a child window.
1994 WND* WIN_GetTopParentPtr( WND* pWnd )
1996 while( pWnd && (pWnd->dwStyle & WS_CHILD)) pWnd = pWnd->parent;
2000 /*****************************************************************
2003 * Get the top-level parent for a child window.
2005 HWND WIN_GetTopParent( HWND hwnd )
2007 WND *wndPtr = WIN_GetTopParentPtr ( WIN_FindWndPtr( hwnd ) );
2008 return wndPtr ? wndPtr->hwndSelf : 0;
2012 /*****************************************************************
2013 * SetParent16 (USER.233)
2015 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2017 return SetParent( hwndChild, hwndNewParent );
2021 /*****************************************************************
2022 * SetParent32 (USER32.495)
2024 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2026 WND *wndPtr = WIN_FindWndPtr( hwndChild );
2027 DWORD dwStyle = (wndPtr)?(wndPtr->dwStyle):0;
2028 WND *pWndNewParent =
2029 (hwndNewParent) ? WIN_FindWndPtr( hwndNewParent ) : pWndDesktop;
2032 /* Windows hides the window first, then shows it again
2033 * including the WM_SHOWWINDOW messages and all */
2034 if (dwStyle & WS_VISIBLE)
2035 ShowWindow( hwndChild, SW_HIDE );
2037 pWndOldParent = (wndPtr)?(*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent):NULL;
2039 /* SetParent32 additionally needs to make hwndChild the topmost window
2040 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2041 WM_WINDOWPOSCHANGED notification messages.
2043 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2044 SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2045 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2046 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2048 return pWndOldParent?pWndOldParent->hwndSelf:0;
2051 /*******************************************************************
2052 * IsChild16 (USER.48)
2054 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2056 return IsChild(parent,child);
2060 /*******************************************************************
2061 * IsChild32 (USER32.339)
2063 BOOL WINAPI IsChild( HWND parent, HWND child )
2065 WND * wndPtr = WIN_FindWndPtr( child );
2066 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2068 wndPtr = wndPtr->parent;
2069 if (wndPtr->hwndSelf == parent) return TRUE;
2075 /***********************************************************************
2076 * IsWindowVisible16 (USER.49)
2078 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2080 return IsWindowVisible(hwnd);
2084 /***********************************************************************
2085 * IsWindowVisible32 (USER32.351)
2087 BOOL WINAPI IsWindowVisible( HWND hwnd )
2089 WND *wndPtr = WIN_FindWndPtr( hwnd );
2090 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2092 if (!(wndPtr->dwStyle & WS_VISIBLE)) return FALSE;
2093 wndPtr = wndPtr->parent;
2095 return (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2099 /***********************************************************************
2100 * WIN_IsWindowDrawable
2102 * hwnd is drawable when it is visible, all parents are not
2103 * minimized, and it is itself not minimized unless we are
2104 * trying to draw its default class icon.
2106 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2108 if( (wnd->dwStyle & WS_MINIMIZE &&
2109 icon && wnd->class->hIcon) ||
2110 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2111 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2112 if( wnd->dwStyle & WS_MINIMIZE ||
2113 !(wnd->dwStyle & WS_VISIBLE) ) break;
2114 return (wnd == NULL);
2118 /*******************************************************************
2119 * GetTopWindow16 (USER.229)
2121 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2123 return GetTopWindow(hwnd);
2127 /*******************************************************************
2128 * GetTopWindow32 (USER.229)
2130 HWND WINAPI GetTopWindow( HWND hwnd )
2132 WND * wndPtr = WIN_FindWndPtr( hwnd );
2133 if (wndPtr && wndPtr->child) return wndPtr->child->hwndSelf;
2138 /*******************************************************************
2139 * GetWindow16 (USER.262)
2141 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2143 return GetWindow( hwnd,rel );
2147 /*******************************************************************
2148 * GetWindow32 (USER32.302)
2150 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2152 WND * wndPtr = WIN_FindWndPtr( hwnd );
2153 if (!wndPtr) return 0;
2157 if (wndPtr->parent) return wndPtr->parent->child->hwndSelf;
2161 if (!wndPtr->parent) return 0; /* Desktop window */
2162 while (wndPtr->next) wndPtr = wndPtr->next;
2163 return wndPtr->hwndSelf;
2166 if (!wndPtr->next) return 0;
2167 return wndPtr->next->hwndSelf;
2170 if (!wndPtr->parent) return 0; /* Desktop window */
2171 wndPtr = wndPtr->parent->child; /* First sibling */
2172 if (wndPtr->hwndSelf == hwnd) return 0; /* First in list */
2173 while (wndPtr->next)
2175 if (wndPtr->next->hwndSelf == hwnd) return wndPtr->hwndSelf;
2176 wndPtr = wndPtr->next;
2181 return wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2184 return wndPtr->child ? wndPtr->child->hwndSelf : 0;
2190 /*******************************************************************
2191 * GetNextWindow16 (USER.230)
2193 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2195 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2196 return GetWindow16( hwnd, flag );
2199 /*******************************************************************
2200 * ShowOwnedPopups16 (USER.265)
2202 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2204 ShowOwnedPopups( owner, fShow );
2208 /*******************************************************************
2209 * ShowOwnedPopups32 (USER32.531)
2211 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2213 WND *pWnd = pWndDesktop->child;
2216 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
2217 (pWnd->dwStyle & WS_POPUP))
2218 ShowWindow( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
2225 /*******************************************************************
2226 * GetLastActivePopup16 (USER.287)
2228 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2230 return GetLastActivePopup( hwnd );
2233 /*******************************************************************
2234 * GetLastActivePopup32 (USER32.256)
2236 HWND WINAPI GetLastActivePopup( HWND hwnd )
2239 wndPtr = WIN_FindWndPtr(hwnd);
2240 if (wndPtr == NULL) return hwnd;
2241 return wndPtr->hwndLastActive;
2245 /*******************************************************************
2248 * Build an array of pointers to the children of a given window.
2249 * The array must be freed with HeapFree(SystemHeap). Return NULL
2250 * when no windows are found.
2252 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2254 WND **list, **ppWnd;
2256 UINT count, skipOwned, skipHidden;
2259 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2260 skipOwned = bwaFlags & BWA_SKIPOWNED;
2261 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2262 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2264 /* First count the windows */
2266 if (!wndPtr) wndPtr = pWndDesktop;
2267 for (pWnd = wndPtr->child, count = 0; pWnd; pWnd = pWnd->next)
2269 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
2270 if( !skipHidden || pWnd->dwStyle & WS_VISIBLE ) count++;
2275 /* Now build the list of all windows */
2277 if ((list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * (count + 1))))
2279 for (pWnd = wndPtr->child, ppWnd = list, count = 0; pWnd; pWnd = pWnd->next)
2281 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
2282 if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2293 if( pTotal ) *pTotal = count;
2298 /*******************************************************************
2299 * EnumWindows16 (USER.54)
2301 BOOL16 WINAPI EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
2303 WND **list, **ppWnd;
2305 /* We have to build a list of all windows first, to avoid */
2306 /* unpleasant side-effects, for instance if the callback */
2307 /* function changes the Z-order of the windows. */
2309 if (!(list = WIN_BuildWinArray( pWndDesktop, 0, NULL ))) return FALSE;
2311 /* Now call the callback function for every window */
2313 for (ppWnd = list; *ppWnd; ppWnd++)
2315 /* Make sure that the window still exists */
2316 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2317 if (!lpEnumFunc( (*ppWnd)->hwndSelf, lParam )) break;
2319 HeapFree( SystemHeap, 0, list );
2324 /*******************************************************************
2325 * EnumWindows32 (USER32.193)
2327 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2329 return (BOOL)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2333 /**********************************************************************
2334 * EnumTaskWindows16 (USER.225)
2336 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2339 WND **list, **ppWnd;
2341 /* This function is the same as EnumWindows(), */
2342 /* except for an added check on the window's task. */
2344 if (!(list = WIN_BuildWinArray( pWndDesktop, 0, NULL ))) return FALSE;
2346 /* Now call the callback function for every window */
2348 for (ppWnd = list; *ppWnd; ppWnd++)
2350 /* Make sure that the window still exists */
2351 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2352 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2353 if (!func( (*ppWnd)->hwndSelf, lParam )) break;
2355 HeapFree( SystemHeap, 0, list );
2360 /**********************************************************************
2361 * EnumThreadWindows (USER32.190)
2363 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2365 THDB *tdb = THREAD_ID_TO_THDB(id);
2367 return (BOOL16)EnumTaskWindows16(tdb->teb.htask16, (WNDENUMPROC16)func, lParam);
2371 /**********************************************************************
2372 * WIN_EnumChildWindows
2374 * Helper function for EnumChildWindows().
2376 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2382 for ( ; *ppWnd; ppWnd++)
2384 /* Make sure that the window still exists */
2385 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2386 /* Build children list first */
2387 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2388 ret = func( (*ppWnd)->hwndSelf, lParam );
2391 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2392 HeapFree( SystemHeap, 0, childList );
2394 if (!ret) return FALSE;
2400 /**********************************************************************
2401 * EnumChildWindows16 (USER.55)
2403 BOOL16 WINAPI EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
2406 WND **list, *pParent;
2408 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2409 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL ))) return FALSE;
2410 WIN_EnumChildWindows( list, func, lParam );
2411 HeapFree( SystemHeap, 0, list );
2416 /**********************************************************************
2417 * EnumChildWindows32 (USER32.178)
2419 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2422 return (BOOL)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2427 /*******************************************************************
2428 * AnyPopup16 (USER.52)
2430 BOOL16 WINAPI AnyPopup16(void)
2436 /*******************************************************************
2437 * AnyPopup32 (USER32.4)
2439 BOOL WINAPI AnyPopup(void)
2442 for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next)
2443 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE)) return TRUE;
2448 /*******************************************************************
2449 * FlashWindow16 (USER.105)
2451 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2453 return FlashWindow( hWnd, bInvert );
2457 /*******************************************************************
2458 * FlashWindow32 (USER32.202)
2460 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2462 WND *wndPtr = WIN_FindWndPtr(hWnd);
2464 TRACE(win,"%04x\n", hWnd);
2466 if (!wndPtr) return FALSE;
2468 if (wndPtr->dwStyle & WS_MINIMIZE)
2470 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2472 HDC hDC = GetDC(hWnd);
2474 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2475 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2477 ReleaseDC( hWnd, hDC );
2478 wndPtr->flags |= WIN_NCACTIVATED;
2482 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2483 RDW_UPDATENOW | RDW_FRAME, 0 );
2484 wndPtr->flags &= ~WIN_NCACTIVATED;
2491 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2492 else wparam = (hWnd == GetActiveWindow());
2494 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2500 /*******************************************************************
2501 * SetSysModalWindow16 (USER.188)
2503 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
2505 HWND hWndOldModal = hwndSysModal;
2506 hwndSysModal = hWnd;
2507 FIXME(win, "EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2508 return hWndOldModal;
2512 /*******************************************************************
2513 * GetSysModalWindow16 (USER.52)
2515 HWND16 WINAPI GetSysModalWindow16(void)
2517 return hwndSysModal;
2521 /*******************************************************************
2522 * GetWindowContextHelpId (USER32.303)
2524 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2526 WND *wnd = WIN_FindWndPtr( hwnd );
2528 return wnd->helpContext;
2532 /*******************************************************************
2533 * SetWindowContextHelpId (USER32.515)
2535 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
2537 WND *wnd = WIN_FindWndPtr( hwnd );
2538 if (!wnd) return FALSE;
2539 wnd->helpContext = id;
2544 /*******************************************************************
2547 * recursively find a child that contains spDragInfo->pt point
2548 * and send WM_QUERYDROPOBJECT
2550 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
2552 BOOL16 wParam,bResult = 0;
2554 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
2555 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
2558 if( !ptrQueryWnd || !ptrDragInfo ) return 0;
2560 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
2562 GetWindowRect(hQueryWnd,&tempRect);
2564 if( !PtInRect(&tempRect,pt) ||
2565 (ptrQueryWnd->dwStyle & WS_DISABLED) )
2568 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
2570 tempRect = ptrQueryWnd->rectClient;
2571 if(ptrQueryWnd->dwStyle & WS_CHILD)
2572 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
2573 (LPPOINT)&tempRect, 2 );
2575 if (PtInRect( &tempRect, pt))
2579 for (ptrWnd = ptrQueryWnd->child; ptrWnd ;ptrWnd = ptrWnd->next)
2580 if( ptrWnd->dwStyle & WS_VISIBLE )
2582 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
2583 if (PtInRect( &tempRect, pt )) break;
2588 TRACE(msg,"hwnd = %04x, %d %d - %d %d\n",
2589 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
2590 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
2591 if( !(ptrWnd->dwStyle & WS_DISABLED) )
2592 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
2595 if(bResult) return bResult;
2601 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
2603 ptrDragInfo->hScope = hQueryWnd;
2605 bResult = ( bNoSend )
2606 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
2607 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
2608 (WPARAM16)wParam ,(LPARAM) spDragInfo );
2610 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
2616 /*******************************************************************
2617 * DragDetect (USER.465)
2619 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
2622 CONV_POINT16TO32( &pt, &pt32 );
2623 return DragDetect( hWnd, pt32 );
2626 /*******************************************************************
2627 * DragDetect32 (USER32.151)
2629 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
2634 rect.left = pt.x - wDragWidth;
2635 rect.right = pt.x + wDragWidth;
2637 rect.top = pt.y - wDragHeight;
2638 rect.bottom = pt.y + wDragHeight;
2644 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
2646 if( msg.message == WM_LBUTTONUP )
2651 if( msg.message == WM_MOUSEMOVE )
2653 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
2665 /******************************************************************************
2666 * DragObject16 (USER.464)
2668 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
2669 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
2672 LPDRAGINFO lpDragInfo;
2674 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
2675 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
2676 WND *wndPtr = WIN_FindWndPtr(hWnd);
2677 HCURSOR16 hCurrentCursor = 0;
2678 HWND16 hCurrentWnd = 0;
2680 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
2681 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
2683 if( !lpDragInfo || !spDragInfo ) return 0L;
2685 hBummer = LoadCursor16(0, IDC_BUMMER16);
2687 if( !hBummer || !wndPtr )
2689 GlobalFree16(hDragInfo);
2695 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
2697 GlobalFree16(hDragInfo);
2701 if( hDragCursor == hCursor ) hDragCursor = 0;
2702 else hCursor = hDragCursor;
2704 hOldCursor = SetCursor(hDragCursor);
2707 lpDragInfo->hWnd = hWnd;
2708 lpDragInfo->hScope = 0;
2709 lpDragInfo->wFlags = wObj;
2710 lpDragInfo->hList = szList; /* near pointer! */
2711 lpDragInfo->hOfStruct = hOfStruct;
2719 do{ WaitMessage(); }
2720 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
2722 *(lpDragInfo+1) = *lpDragInfo;
2724 lpDragInfo->pt = msg.pt;
2726 /* update DRAGINFO struct */
2727 TRACE(msg,"lpDI->hScope = %04x\n",lpDragInfo->hScope);
2729 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
2730 hCurrentCursor = hCursor;
2733 hCurrentCursor = hBummer;
2734 lpDragInfo->hScope = 0;
2736 if( hCurrentCursor )
2737 SetCursor(hCurrentCursor);
2739 /* send WM_DRAGLOOP */
2740 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
2741 (LPARAM) spDragInfo );
2742 /* send WM_DRAGSELECT or WM_DRAGMOVE */
2743 if( hCurrentWnd != lpDragInfo->hScope )
2746 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
2747 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
2748 HIWORD(spDragInfo)) );
2749 hCurrentWnd = lpDragInfo->hScope;
2751 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
2755 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
2757 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
2760 ShowCursor( FALSE );
2764 SetCursor( hOldCursor );
2765 if (hDragCursor) DestroyCursor( hDragCursor );
2768 if( hCurrentCursor != hBummer )
2769 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
2770 (WPARAM16)hWnd, (LPARAM)spDragInfo );
2773 GlobalFree16(hDragInfo);
2775 return (DWORD)(msg.lParam);