Handle suspend/resume_thread requests in phase STARTING correctly.
[wine/hacks.git] / windows / mdi.c
blob5be8bc38c2e9fe033a4d9e739a928199fca3d712
1 /* MDI.C
3 * Copyright 1994, Bob Amstadt
4 * 1995,1996 Alex Korobka
6 * This file contains routines to support MDI features.
8 * Notes: Fairly complete implementation. Any volunteers for
9 * "More windows..." stuff?
11 * Also, Excel and WinWord do _not_ use MDI so if you're trying
12 * to fix them look elsewhere.
15 #include <stdlib.h>
16 #include <string.h>
17 #include <math.h>
18 #include "winuser.h"
19 #include "win.h"
20 #include "heap.h"
21 #include "nonclient.h"
22 #include "mdi.h"
23 #include "user.h"
24 #include "menu.h"
25 #include "resource.h"
26 #include "struct32.h"
27 #include "sysmetrics.h"
28 #include "tweak.h"
29 #include "debug.h"
31 #define MDIF_NEEDUPDATE 0x0001
33 static HBITMAP16 hBmpClose = 0;
34 static HBITMAP16 hBmpRestore = 0;
36 INT SCROLL_SetNCSbState(WND*,int,int,int,int,int,int);
38 /* ----------------- declarations ----------------- */
39 static void MDI_UpdateFrameText(WND *, HWND, BOOL, LPCSTR);
40 static BOOL MDI_AugmentFrameMenu(MDICLIENTINFO*, WND *, HWND);
41 static BOOL MDI_RestoreFrameMenu(WND *, HWND);
43 static LONG MDI_ChildActivate( WND*, HWND );
45 /* -------- Miscellaneous service functions ----------
47 * MDI_GetChildByID
50 static HWND MDI_GetChildByID(WND* wndPtr, INT id)
52 for (wndPtr = wndPtr->child; wndPtr; wndPtr = wndPtr->next)
53 if (wndPtr->wIDmenu == id) return wndPtr->hwndSelf;
54 return 0;
57 static void MDI_PostUpdate(HWND hwnd, MDICLIENTINFO* ci, WORD recalc)
59 if( !(ci->mdiFlags & MDIF_NEEDUPDATE) )
61 ci->mdiFlags |= MDIF_NEEDUPDATE;
62 PostMessageA( hwnd, WM_MDICALCCHILDSCROLL, 0, 0);
64 ci->sbRecalc = recalc;
67 /**********************************************************************
68 * MDI_MenuModifyItem
70 static BOOL MDI_MenuModifyItem(WND* clientWnd, HWND hWndChild )
72 char buffer[128];
73 MDICLIENTINFO *clientInfo = (MDICLIENTINFO*)clientWnd->wExtra;
74 WND *wndPtr = WIN_FindWndPtr(hWndChild);
75 UINT n = sprintf(buffer, "%d ",
76 wndPtr->wIDmenu - clientInfo->idFirstChild + 1);
77 BOOL bRet = 0;
79 if( !clientInfo->hWindowMenu )
81 bRet = FALSE;
82 goto END;
85 if (wndPtr->text) lstrcpynA(buffer + n, wndPtr->text, sizeof(buffer) - n );
87 n = GetMenuState(clientInfo->hWindowMenu,wndPtr->wIDmenu ,MF_BYCOMMAND);
88 bRet = ModifyMenuA(clientInfo->hWindowMenu , wndPtr->wIDmenu,
89 MF_BYCOMMAND | MF_STRING, wndPtr->wIDmenu, buffer );
90 CheckMenuItem(clientInfo->hWindowMenu ,wndPtr->wIDmenu , n & MF_CHECKED);
91 END:
92 WIN_ReleaseWndPtr(wndPtr);
93 return bRet;
96 /**********************************************************************
97 * MDI_MenuDeleteItem
99 static BOOL MDI_MenuDeleteItem(WND* clientWnd, HWND hWndChild )
101 char buffer[128];
102 MDICLIENTINFO *clientInfo = (MDICLIENTINFO*)clientWnd->wExtra;
103 WND *wndPtr = WIN_FindWndPtr(hWndChild);
104 UINT index = 0,id,n;
105 BOOL retvalue;
107 if( !clientInfo->nActiveChildren ||
108 !clientInfo->hWindowMenu )
110 retvalue = FALSE;
111 goto END;
114 id = wndPtr->wIDmenu;
115 DeleteMenu(clientInfo->hWindowMenu,id,MF_BYCOMMAND);
117 /* walk the rest of MDI children to prevent gaps in the id
118 * sequence and in the menu child list */
120 for( index = id+1; index <= clientInfo->nActiveChildren +
121 clientInfo->idFirstChild; index++ )
123 wndPtr = WIN_FindWndPtr(MDI_GetChildByID(clientWnd,index));
124 if( !wndPtr )
126 TRACE(mdi,"no window for id=%i\n",index);
127 continue;
130 /* set correct id */
131 wndPtr->wIDmenu--;
133 n = sprintf(buffer, "%d ",index - clientInfo->idFirstChild);
134 if (wndPtr->text)
135 lstrcpynA(buffer + n, wndPtr->text, sizeof(buffer) - n );
137 /* change menu */
138 ModifyMenuA(clientInfo->hWindowMenu ,index ,MF_BYCOMMAND | MF_STRING,
139 index - 1 , buffer );
141 retvalue = TRUE;
142 END:
143 WIN_ReleaseWndPtr(wndPtr);
144 return retvalue;
147 /**********************************************************************
148 * MDI_GetWindow
150 * returns "activateable" child different from the current or zero
152 static HWND MDI_GetWindow(WND *clientWnd, HWND hWnd, BOOL bNext,
153 DWORD dwStyleMask )
155 MDICLIENTINFO *clientInfo = (MDICLIENTINFO*)clientWnd->wExtra;
156 WND *wndPtr, *pWnd, *pWndLast = NULL;
158 dwStyleMask |= WS_DISABLED | WS_VISIBLE;
159 if( !hWnd ) hWnd = clientInfo->hwndActiveChild;
161 if( !(wndPtr = WIN_FindWndPtr(hWnd)) ) return 0;
163 for ( pWnd = WIN_LockWndPtr(wndPtr->next); ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
165 if (!pWnd ) WIN_UpdateWndPtr(&pWnd,wndPtr->parent->child);
167 if ( pWnd == wndPtr ) break; /* went full circle */
169 if (!pWnd->owner && (pWnd->dwStyle & dwStyleMask) == WS_VISIBLE )
171 pWndLast = pWnd;
172 if ( bNext ) break;
175 WIN_ReleaseWndPtr(wndPtr);
176 WIN_ReleaseWndPtr(pWnd);
177 return pWndLast ? pWndLast->hwndSelf : 0;
180 /**********************************************************************
181 * MDI_CalcDefaultChildPos
183 * It seems that the default height is about 2/3 of the client rect
185 static void MDI_CalcDefaultChildPos( WND* w, WORD n, LPPOINT lpPos,
186 INT delta)
188 INT nstagger;
189 RECT rect = w->rectClient;
190 INT spacing = GetSystemMetrics(SM_CYCAPTION) +
191 GetSystemMetrics(SM_CYFRAME) - 1;
193 if( rect.bottom - rect.top - delta >= spacing )
194 rect.bottom -= delta;
196 nstagger = (rect.bottom - rect.top)/(3 * spacing);
197 lpPos[1].x = (rect.right - rect.left - nstagger * spacing);
198 lpPos[1].y = (rect.bottom - rect.top - nstagger * spacing);
199 lpPos[0].x = lpPos[0].y = spacing * (n%(nstagger+1));
202 /**********************************************************************
203 * MDISetMenu
205 static LRESULT MDISetMenu( HWND hwnd, HMENU hmenuFrame,
206 HMENU hmenuWindow)
208 WND *w = WIN_FindWndPtr(hwnd);
209 MDICLIENTINFO *ci;
210 HWND hwndFrame = GetParent(hwnd);
211 HMENU oldFrameMenu = GetMenu(hwndFrame);
213 TRACE(mdi, "%04x %04x %04x\n",
214 hwnd, hmenuFrame, hmenuWindow);
216 ci = (MDICLIENTINFO *) w->wExtra;
218 if( ci->hwndChildMaximized && hmenuFrame && hmenuFrame!=oldFrameMenu )
219 MDI_RestoreFrameMenu(w->parent, ci->hwndChildMaximized );
221 if( hmenuWindow && hmenuWindow!=ci->hWindowMenu )
223 /* delete menu items from ci->hWindowMenu
224 * and add them to hmenuWindow */
226 INT i = GetMenuItemCount(ci->hWindowMenu) - 1;
227 INT pos = GetMenuItemCount(hmenuWindow) + 1;
229 AppendMenuA( hmenuWindow, MF_SEPARATOR, 0, NULL);
231 if( ci->nActiveChildren )
233 INT j = i - ci->nActiveChildren + 1;
234 char buffer[100];
235 UINT id,state;
237 for( ; i >= j ; i-- )
239 id = GetMenuItemID(ci->hWindowMenu,i );
240 state = GetMenuState(ci->hWindowMenu,i,MF_BYPOSITION);
242 GetMenuStringA(ci->hWindowMenu, i, buffer, 100, MF_BYPOSITION);
244 DeleteMenu(ci->hWindowMenu, i , MF_BYPOSITION);
245 InsertMenuA(hmenuWindow, pos, MF_BYPOSITION | MF_STRING,
246 id, buffer);
247 CheckMenuItem(hmenuWindow ,pos , MF_BYPOSITION | (state & MF_CHECKED));
251 /* remove separator */
252 DeleteMenu(ci->hWindowMenu, i, MF_BYPOSITION);
254 ci->hWindowMenu = hmenuWindow;
257 if( hmenuFrame && hmenuFrame!=oldFrameMenu)
259 SetMenu(hwndFrame, hmenuFrame);
260 if( ci->hwndChildMaximized )
261 MDI_AugmentFrameMenu(ci, w->parent, ci->hwndChildMaximized );
262 WIN_ReleaseWndPtr(w);
263 return oldFrameMenu;
265 WIN_ReleaseWndPtr(w);
266 return 0;
269 /**********************************************************************
270 * MDIRefreshMenu
272 static LRESULT MDIRefreshMenu( HWND hwnd, HMENU hmenuFrame,
273 HMENU hmenuWindow)
275 HWND hwndFrame = GetParent(hwnd);
276 HMENU oldFrameMenu = GetMenu(hwndFrame);
278 TRACE(mdi, "%04x %04x %04x\n",
279 hwnd, hmenuFrame, hmenuWindow);
281 FIXME(mdi,"partially function stub\n");
283 return oldFrameMenu;
287 /* ------------------ MDI child window functions ---------------------- */
290 /**********************************************************************
291 * MDICreateChild
293 static HWND MDICreateChild( WND *w, MDICLIENTINFO *ci, HWND parent,
294 LPMDICREATESTRUCTA cs )
296 POINT pos[2];
297 DWORD style = cs->style | (WS_CHILD | WS_CLIPSIBLINGS);
298 HWND hwnd, hwndMax = 0;
299 WORD wIDmenu = ci->idFirstChild + ci->nActiveChildren;
300 char lpstrDef[]="junk!";
302 TRACE(mdi, "origin %i,%i - dim %i,%i, style %08x\n",
303 cs->x, cs->y, cs->cx, cs->cy, (unsigned)cs->style);
304 /* calculate placement */
305 MDI_CalcDefaultChildPos(w, ci->nTotalCreated++, pos, 0);
307 if (cs->cx == CW_USEDEFAULT || !cs->cx) cs->cx = pos[1].x;
308 if (cs->cy == CW_USEDEFAULT || !cs->cy) cs->cy = pos[1].y;
310 if( cs->x == CW_USEDEFAULT )
312 cs->x = pos[0].x;
313 cs->y = pos[0].y;
316 /* restore current maximized child */
317 if( style & WS_VISIBLE && ci->hwndChildMaximized )
319 if( style & WS_MAXIMIZE )
320 SendMessageA(w->hwndSelf, WM_SETREDRAW, FALSE, 0L );
321 hwndMax = ci->hwndChildMaximized;
322 ShowWindow( hwndMax, SW_SHOWNOACTIVATE );
323 if( style & WS_MAXIMIZE )
324 SendMessageA(w->hwndSelf, WM_SETREDRAW, TRUE, 0L );
327 /* this menu is needed to set a check mark in MDI_ChildActivate */
328 AppendMenuA(ci->hWindowMenu ,MF_STRING ,wIDmenu, lpstrDef );
330 ci->nActiveChildren++;
332 /* fix window style */
333 if( !(w->dwStyle & MDIS_ALLCHILDSTYLES) )
335 style &= (WS_CHILD | WS_CLIPSIBLINGS | WS_MINIMIZE | WS_MAXIMIZE |
336 WS_CLIPCHILDREN | WS_DISABLED | WS_VSCROLL | WS_HSCROLL );
337 style |= (WS_VISIBLE | WS_OVERLAPPEDWINDOW);
340 if( w->flags & WIN_ISWIN32 )
342 hwnd = CreateWindowA( cs->szClass, cs->szTitle, style,
343 cs->x, cs->y, cs->cx, cs->cy, parent,
344 (HMENU16)wIDmenu, cs->hOwner, cs );
346 else
348 MDICREATESTRUCT16 *cs16;
349 LPSTR title, cls;
351 cs16 = SEGPTR_NEW(MDICREATESTRUCT16);
352 STRUCT32_MDICREATESTRUCT32Ato16( cs, cs16 );
353 title = SEGPTR_STRDUP( cs->szTitle );
354 cls = SEGPTR_STRDUP( cs->szClass );
355 cs16->szTitle = SEGPTR_GET(title);
356 cs16->szClass = SEGPTR_GET(cls);
358 hwnd = CreateWindow16( cs->szClass, cs->szTitle, style,
359 cs16->x, cs16->y, cs16->cx, cs16->cy, parent,
360 (HMENU)wIDmenu, cs16->hOwner,
361 (LPVOID)SEGPTR_GET(cs16) );
362 SEGPTR_FREE( title );
363 SEGPTR_FREE( cls );
364 SEGPTR_FREE( cs16 );
367 /* MDI windows are WS_CHILD so they won't be activated by CreateWindow */
369 if (hwnd)
371 WND* wnd = WIN_FindWndPtr( hwnd );
373 MDI_MenuModifyItem(w ,hwnd);
374 if( wnd->dwStyle & WS_MINIMIZE && ci->hwndActiveChild )
375 ShowWindow( hwnd, SW_SHOWMINNOACTIVE );
376 else
378 /* WS_VISIBLE is clear if a) the MDI client has
379 * MDIS_ALLCHILDSTYLES style and 2) the flag is cleared in the
380 * MDICreateStruct. If so the created window is not shown nor
381 * activated.
383 int showflag=wnd->dwStyle & WS_VISIBLE;
384 /* clear visible flag, otherwise SetWindoPos32 ignores
385 * the SWP_SHOWWINDOW command.
387 wnd->dwStyle &= ~WS_VISIBLE;
388 if(showflag){
389 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE );
391 /* Set maximized state here in case hwnd didn't receive WM_SIZE
392 * during CreateWindow - bad!
395 if((wnd->dwStyle & WS_MAXIMIZE) && !ci->hwndChildMaximized )
397 ci->hwndChildMaximized = wnd->hwndSelf;
398 MDI_AugmentFrameMenu( ci, w->parent, hwnd );
399 MDI_UpdateFrameText( w->parent, ci->self, MDI_REPAINTFRAME, NULL );
401 }else
402 /* needed, harmless ? */
403 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE );
406 WIN_ReleaseWndPtr(wnd);
407 TRACE(mdi, "created child - %04x\n",hwnd);
409 else
411 ci->nActiveChildren--;
412 DeleteMenu(ci->hWindowMenu,wIDmenu,MF_BYCOMMAND);
413 if( IsWindow(hwndMax) )
414 ShowWindow(hwndMax, SW_SHOWMAXIMIZED);
417 return hwnd;
420 /**********************************************************************
421 * MDI_ChildGetMinMaxInfo
423 * Note: The rule here is that client rect of the maximized MDI child
424 * is equal to the client rect of the MDI client window.
426 static void MDI_ChildGetMinMaxInfo( WND* clientWnd, HWND hwnd,
427 MINMAXINFO16* lpMinMax )
429 WND* childWnd = WIN_FindWndPtr(hwnd);
430 RECT rect = clientWnd->rectClient;
432 MapWindowPoints( clientWnd->parent->hwndSelf,
433 ((MDICLIENTINFO*)clientWnd->wExtra)->self, (LPPOINT)&rect, 2);
434 AdjustWindowRectEx( &rect, childWnd->dwStyle, 0, childWnd->dwExStyle );
436 lpMinMax->ptMaxSize.x = rect.right -= rect.left;
437 lpMinMax->ptMaxSize.y = rect.bottom -= rect.top;
439 lpMinMax->ptMaxPosition.x = rect.left;
440 lpMinMax->ptMaxPosition.y = rect.top;
442 WIN_ReleaseWndPtr(childWnd);
444 TRACE(mdi,"max rect (%i,%i - %i, %i)\n",
445 rect.left,rect.top,rect.right,rect.bottom);
449 /**********************************************************************
450 * MDI_SwitchActiveChild
452 * Note: SetWindowPos sends WM_CHILDACTIVATE to the child window that is
453 * being activated
455 static void MDI_SwitchActiveChild( HWND clientHwnd, HWND childHwnd,
456 BOOL bNextWindow )
458 WND *w = WIN_FindWndPtr(clientHwnd);
459 HWND hwndTo = 0;
460 HWND hwndPrev = 0;
461 MDICLIENTINFO *ci;
463 hwndTo = MDI_GetWindow(w, childHwnd, bNextWindow, 0);
465 ci = (MDICLIENTINFO *) w->wExtra;
467 TRACE(mdi, "from %04x, to %04x\n",childHwnd,hwndTo);
469 if ( !hwndTo ) goto END; /* no window to switch to */
471 hwndPrev = ci->hwndActiveChild;
473 if ( hwndTo != hwndPrev )
475 BOOL bOptimize = 0;
477 if( ci->hwndChildMaximized )
479 bOptimize = 1;
480 w->dwStyle &= ~WS_VISIBLE;
483 SetWindowPos( hwndTo, HWND_TOP, 0, 0, 0, 0,
484 SWP_NOMOVE | SWP_NOSIZE );
486 if( bNextWindow && hwndPrev )
487 SetWindowPos( hwndPrev, HWND_BOTTOM, 0, 0, 0, 0,
488 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE );
489 if( bOptimize )
490 ShowWindow( clientHwnd, SW_SHOW );
492 END:
493 WIN_ReleaseWndPtr(w);
497 /**********************************************************************
498 * MDIDestroyChild
500 static LRESULT MDIDestroyChild( WND *w_parent, MDICLIENTINFO *ci,
501 HWND parent, HWND child,
502 BOOL flagDestroy )
504 WND *childPtr = WIN_FindWndPtr(child);
506 if( childPtr )
508 if( child == ci->hwndActiveChild )
510 MDI_SwitchActiveChild(parent, child, TRUE);
512 if( child == ci->hwndActiveChild )
514 ShowWindow( child, SW_HIDE);
515 if( child == ci->hwndChildMaximized )
517 MDI_RestoreFrameMenu(w_parent->parent, child);
518 ci->hwndChildMaximized = 0;
519 MDI_UpdateFrameText(w_parent->parent,parent,TRUE,NULL);
522 MDI_ChildActivate(w_parent, 0);
524 MDI_MenuDeleteItem(w_parent, child);
526 WIN_ReleaseWndPtr(childPtr);
528 ci->nActiveChildren--;
530 TRACE(mdi,"child destroyed - %04x\n",child);
532 if (flagDestroy)
534 MDI_PostUpdate(GetParent(child), ci, SB_BOTH+1);
535 DestroyWindow(child);
539 return 0;
543 /**********************************************************************
544 * MDI_ChildActivate
546 * Note: hWndChild is NULL when last child is being destroyed
548 static LONG MDI_ChildActivate( WND *clientPtr, HWND hWndChild )
550 MDICLIENTINFO *clientInfo = (MDICLIENTINFO*)clientPtr->wExtra;
551 HWND prevActiveWnd = clientInfo->hwndActiveChild;
552 WND *wndPtr = WIN_FindWndPtr( hWndChild );
553 WND *wndPrev = WIN_FindWndPtr( prevActiveWnd );
554 BOOL isActiveFrameWnd = 0;
555 LONG retvalue;
557 if( hWndChild == prevActiveWnd )
559 retvalue = 0L;
560 goto END;
563 if( wndPtr )
565 if( wndPtr->dwStyle & WS_DISABLED )
567 retvalue = 0L;
568 goto END;
572 TRACE(mdi,"%04x\n", hWndChild);
574 if( GetActiveWindow() == clientPtr->parent->hwndSelf )
575 isActiveFrameWnd = TRUE;
577 /* deactivate prev. active child */
578 if( wndPrev )
580 wndPrev->dwStyle |= WS_SYSMENU;
581 SendMessageA( prevActiveWnd, WM_NCACTIVATE, FALSE, 0L );
582 SendMessageA( prevActiveWnd, WM_MDIACTIVATE, (WPARAM)prevActiveWnd,
583 (LPARAM)hWndChild);
584 /* uncheck menu item */
585 if( clientInfo->hWindowMenu )
586 CheckMenuItem( clientInfo->hWindowMenu,
587 wndPrev->wIDmenu, 0);
590 /* set appearance */
591 if( clientInfo->hwndChildMaximized )
593 if( clientInfo->hwndChildMaximized != hWndChild ) {
594 if( hWndChild ) {
595 clientInfo->hwndActiveChild = hWndChild;
596 ShowWindow( hWndChild, SW_SHOWMAXIMIZED);
597 } else
598 ShowWindow( clientInfo->hwndActiveChild, SW_SHOWNORMAL );
602 clientInfo->hwndActiveChild = hWndChild;
604 /* check if we have any children left */
605 if( !hWndChild )
607 if( isActiveFrameWnd )
608 SetFocus( clientInfo->self );
609 retvalue = 0;
610 goto END;
613 /* check menu item */
614 if( clientInfo->hWindowMenu )
615 CheckMenuItem( clientInfo->hWindowMenu,
616 wndPtr->wIDmenu, MF_CHECKED);
618 /* bring active child to the top */
619 SetWindowPos( hWndChild, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
621 if( isActiveFrameWnd )
623 SendMessageA( hWndChild, WM_NCACTIVATE, TRUE, 0L);
624 if( GetFocus() == clientInfo->self )
625 SendMessageA( clientInfo->self, WM_SETFOCUS,
626 (WPARAM)clientInfo->self, 0L );
627 else
628 SetFocus( clientInfo->self );
630 SendMessageA( hWndChild, WM_MDIACTIVATE, (WPARAM)prevActiveWnd,
631 (LPARAM)hWndChild );
632 retvalue = 1;
633 END:
634 WIN_ReleaseWndPtr(wndPtr);
635 WIN_ReleaseWndPtr(wndPrev);
638 /* -------------------- MDI client window functions ------------------- */
640 /**********************************************************************
641 * CreateMDIMenuBitmap
643 static HBITMAP16 CreateMDIMenuBitmap(void)
645 HDC hDCSrc = CreateCompatibleDC(0);
646 HDC hDCDest = CreateCompatibleDC(hDCSrc);
647 HBITMAP16 hbClose = LoadBitmap16(0, MAKEINTRESOURCE16(OBM_CLOSE) );
648 HBITMAP16 hbCopy;
649 HANDLE16 hobjSrc, hobjDest;
651 hobjSrc = SelectObject(hDCSrc, hbClose);
652 hbCopy = CreateCompatibleBitmap(hDCSrc,SYSMETRICS_CXSIZE,SYSMETRICS_CYSIZE);
653 hobjDest = SelectObject(hDCDest, hbCopy);
655 BitBlt(hDCDest, 0, 0, SYSMETRICS_CXSIZE, SYSMETRICS_CYSIZE,
656 hDCSrc, SYSMETRICS_CXSIZE, 0, SRCCOPY);
658 SelectObject(hDCSrc, hobjSrc);
659 DeleteObject(hbClose);
660 DeleteDC(hDCSrc);
662 hobjSrc = SelectObject( hDCDest, GetStockObject(BLACK_PEN) );
664 MoveToEx( hDCDest, SYSMETRICS_CXSIZE - 1, 0, NULL );
665 LineTo( hDCDest, SYSMETRICS_CXSIZE - 1, SYSMETRICS_CYSIZE - 1);
667 SelectObject(hDCDest, hobjSrc );
668 SelectObject(hDCDest, hobjDest);
669 DeleteDC(hDCDest);
671 return hbCopy;
674 /**********************************************************************
675 * MDICascade
677 static LONG MDICascade(WND* clientWnd, MDICLIENTINFO *ci)
679 WND** ppWnd;
680 UINT total;
682 if (ci->hwndChildMaximized)
683 SendMessageA( clientWnd->hwndSelf, WM_MDIRESTORE,
684 (WPARAM)ci->hwndChildMaximized, 0);
686 if (ci->nActiveChildren == 0) return 0;
688 if ((ppWnd = WIN_BuildWinArray(clientWnd, BWA_SKIPHIDDEN | BWA_SKIPOWNED |
689 BWA_SKIPICONIC, &total)))
691 WND** heapPtr = ppWnd;
692 if( total )
694 INT delta = 0, n = 0;
695 POINT pos[2];
696 if( total < ci->nActiveChildren )
697 delta = SYSMETRICS_CYICONSPACING + SYSMETRICS_CYICON;
699 /* walk the list (backwards) and move windows */
700 while (*ppWnd) ppWnd++;
701 while (ppWnd != heapPtr)
703 ppWnd--;
704 TRACE(mdi, "move %04x to (%ld,%ld) size [%ld,%ld]\n",
705 (*ppWnd)->hwndSelf, pos[0].x, pos[0].y, pos[1].x, pos[1].y);
707 MDI_CalcDefaultChildPos(clientWnd, n++, pos, delta);
708 SetWindowPos( (*ppWnd)->hwndSelf, 0, pos[0].x, pos[0].y,
709 pos[1].x, pos[1].y,
710 SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER);
713 HeapFree( SystemHeap, 0, heapPtr );
716 if( total < ci->nActiveChildren )
717 ArrangeIconicWindows( clientWnd->hwndSelf );
718 return 0;
721 /**********************************************************************
722 * MDITile
724 static void MDITile( WND* wndClient, MDICLIENTINFO *ci, WPARAM wParam )
726 WND** ppWnd;
727 UINT total = 0;
729 if (ci->hwndChildMaximized)
730 SendMessageA( wndClient->hwndSelf, WM_MDIRESTORE,
731 (WPARAM)ci->hwndChildMaximized, 0);
733 if (ci->nActiveChildren == 0) return;
735 ppWnd = WIN_BuildWinArray(wndClient, BWA_SKIPHIDDEN | BWA_SKIPOWNED | BWA_SKIPICONIC |
736 ((wParam & MDITILE_SKIPDISABLED)? BWA_SKIPDISABLED : 0), &total );
738 TRACE(mdi,"%u windows to tile\n", total);
740 if( ppWnd )
742 WND** heapPtr = ppWnd;
744 if( total )
746 RECT rect;
747 int x, y, xsize, ysize;
748 int rows, columns, r, c, i;
750 rect = wndClient->rectClient;
751 rows = (int) sqrt((double)total);
752 columns = total / rows;
754 if( wParam & MDITILE_HORIZONTAL ) /* version >= 3.1 */
756 i = rows;
757 rows = columns; /* exchange r and c */
758 columns = i;
761 if( total != ci->nActiveChildren)
763 y = rect.bottom - 2 * SYSMETRICS_CYICONSPACING - SYSMETRICS_CYICON;
764 rect.bottom = ( y - SYSMETRICS_CYICON < rect.top )? rect.bottom: y;
767 ysize = rect.bottom / rows;
768 xsize = rect.right / columns;
770 for (x = i = 0, c = 1; c <= columns && *ppWnd; c++)
772 if (c == columns)
774 rows = total - i;
775 ysize = rect.bottom / rows;
778 y = 0;
779 for (r = 1; r <= rows && *ppWnd; r++, i++)
781 SetWindowPos((*ppWnd)->hwndSelf, 0, x, y, xsize, ysize,
782 SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER);
783 y += ysize;
784 ppWnd++;
786 x += xsize;
789 HeapFree( SystemHeap, 0, heapPtr );
792 if( total < ci->nActiveChildren ) ArrangeIconicWindows( wndClient->hwndSelf );
795 /* ----------------------- Frame window ---------------------------- */
798 /**********************************************************************
799 * MDI_AugmentFrameMenu
801 static BOOL MDI_AugmentFrameMenu( MDICLIENTINFO* ci, WND *frame,
802 HWND hChild )
804 WND* child = WIN_FindWndPtr(hChild);
805 HMENU hSysPopup = 0;
807 TRACE(mdi,"frame %p,child %04x\n",frame,hChild);
809 if( !frame->wIDmenu || !child->hSysMenu )
811 WIN_ReleaseWndPtr(child);
812 return 0;
814 WIN_ReleaseWndPtr(child);
816 /* create a copy of sysmenu popup and insert it into frame menu bar */
818 if (!(hSysPopup = LoadMenuIndirectA(SYSRES_GetResPtr(SYSRES_MENU_SYSMENU))))
819 return 0;
821 TRACE(mdi,"\tgot popup %04x in sysmenu %04x\n",
822 hSysPopup, child->hSysMenu);
824 AppendMenuA(frame->wIDmenu,MF_HELP | MF_BITMAP,
825 SC_MINIMIZE, (LPSTR)(DWORD)MAGIC_REDUCE ) ;
826 AppendMenuA(frame->wIDmenu,MF_HELP | MF_BITMAP,
827 SC_RESTORE, (LPSTR)(DWORD)MAGIC_RESTORE );
829 if( !InsertMenuA(frame->wIDmenu,0,MF_BYPOSITION | MF_BITMAP | MF_POPUP,
830 hSysPopup, (LPSTR)(DWORD)hBmpClose ))
832 TRACE(mdi,"not inserted\n");
833 DestroyMenu(hSysPopup);
834 return 0;
837 // The close button is only present in Win 95 look
838 if(TWEAK_WineLook > WIN31_LOOK)
840 AppendMenuA(frame->wIDmenu,MF_HELP | MF_BITMAP,
841 SC_CLOSE, (LPSTR)(DWORD)MAGIC_CLOSE );
844 EnableMenuItem(hSysPopup, SC_SIZE, MF_BYCOMMAND | MF_GRAYED);
845 EnableMenuItem(hSysPopup, SC_MOVE, MF_BYCOMMAND | MF_GRAYED);
846 EnableMenuItem(hSysPopup, SC_MAXIMIZE, MF_BYCOMMAND | MF_GRAYED);
848 /* redraw menu */
849 DrawMenuBar(frame->hwndSelf);
851 return 1;
854 /**********************************************************************
855 * MDI_RestoreFrameMenu
857 static BOOL MDI_RestoreFrameMenu( WND *frameWnd, HWND hChild )
859 INT nItems = GetMenuItemCount(frameWnd->wIDmenu) - 1;
860 UINT iId = GetMenuItemID(frameWnd->wIDmenu,nItems) ;
862 TRACE(mdi,"frameWnd %p,child %04x\n",frameWnd,hChild);
864 if(!(iId == SC_RESTORE || iId == SC_CLOSE) )
865 return 0;
867 // app button
868 RemoveMenu(frameWnd->wIDmenu,0,MF_BYPOSITION);
870 if(TWEAK_WineLook > WIN31_LOOK)
872 // close
873 DeleteMenu(frameWnd->wIDmenu,GetMenuItemCount(frameWnd->wIDmenu) - 1,MF_BYPOSITION);
875 // restore
876 DeleteMenu(frameWnd->wIDmenu,GetMenuItemCount(frameWnd->wIDmenu) - 1,MF_BYPOSITION);
877 // minimize
878 DeleteMenu(frameWnd->wIDmenu,GetMenuItemCount(frameWnd->wIDmenu) - 1,MF_BYPOSITION);
880 DrawMenuBar(frameWnd->hwndSelf);
882 return 1;
886 /**********************************************************************
887 * MDI_UpdateFrameText
889 * used when child window is maximized/restored
891 * Note: lpTitle can be NULL
893 static void MDI_UpdateFrameText( WND *frameWnd, HWND hClient,
894 BOOL repaint, LPCSTR lpTitle )
896 char lpBuffer[MDI_MAXTITLELENGTH+1];
897 WND* clientWnd = WIN_FindWndPtr(hClient);
898 MDICLIENTINFO *ci = (MDICLIENTINFO *) clientWnd->wExtra;
900 TRACE(mdi, "repaint %i, frameText %s\n", repaint, (lpTitle)?lpTitle:"NULL");
902 if (!clientWnd)
903 return;
904 WIN_ReleaseWndPtr(clientWnd);
906 if (!ci)
907 return;
909 /* store new "default" title if lpTitle is not NULL */
910 if (lpTitle)
912 if (ci->frameTitle) HeapFree( SystemHeap, 0, ci->frameTitle );
913 ci->frameTitle = HEAP_strdupA( SystemHeap, 0, lpTitle );
916 if (ci->frameTitle)
918 WND* childWnd = WIN_FindWndPtr( ci->hwndChildMaximized );
920 if( childWnd && childWnd->text )
922 /* combine frame title and child title if possible */
924 LPCSTR lpBracket = " - [";
925 int i_frame_text_length = strlen(ci->frameTitle);
926 int i_child_text_length = strlen(childWnd->text);
928 lstrcpynA( lpBuffer, ci->frameTitle, MDI_MAXTITLELENGTH);
930 if( i_frame_text_length + 6 < MDI_MAXTITLELENGTH )
932 strcat( lpBuffer, lpBracket );
934 if( i_frame_text_length + i_child_text_length + 6 < MDI_MAXTITLELENGTH )
936 strcat( lpBuffer, childWnd->text );
937 strcat( lpBuffer, "]" );
939 else
941 lstrcpynA( lpBuffer + i_frame_text_length + 4,
942 childWnd->text, MDI_MAXTITLELENGTH - i_frame_text_length - 5 );
943 strcat( lpBuffer, "]" );
946 WIN_ReleaseWndPtr(childWnd);
948 else
950 strncpy(lpBuffer, ci->frameTitle, MDI_MAXTITLELENGTH );
951 lpBuffer[MDI_MAXTITLELENGTH]='\0';
954 else
955 lpBuffer[0] = '\0';
957 DEFWND_SetText( frameWnd, lpBuffer );
958 if( repaint == MDI_REPAINTFRAME)
959 SetWindowPos( frameWnd->hwndSelf, 0,0,0,0,0, SWP_FRAMECHANGED |
960 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER );
964 /* ----------------------------- Interface ---------------------------- */
967 /**********************************************************************
968 * MDIClientWndProc
970 * This function handles all MDI requests.
972 LRESULT WINAPI MDIClientWndProc( HWND hwnd, UINT message, WPARAM wParam,
973 LPARAM lParam )
975 LPCREATESTRUCTA cs;
976 MDICLIENTINFO *ci;
977 RECT rect;
978 WND *w = WIN_FindWndPtr(hwnd);
979 WND *frameWnd = WIN_LockWndPtr(w->parent);
980 INT nItems;
981 LRESULT retvalue;
983 ci = (MDICLIENTINFO *) w->wExtra;
985 switch (message)
987 case WM_CREATE:
989 cs = (LPCREATESTRUCTA)lParam;
991 /* Translation layer doesn't know what's in the cs->lpCreateParams
992 * so we have to keep track of what environment we're in. */
994 if( w->flags & WIN_ISWIN32 )
996 #define ccs ((LPCLIENTCREATESTRUCT)cs->lpCreateParams)
997 ci->hWindowMenu = ccs->hWindowMenu;
998 ci->idFirstChild = ccs->idFirstChild;
999 #undef ccs
1001 else
1003 LPCLIENTCREATESTRUCT16 ccs = (LPCLIENTCREATESTRUCT16)
1004 PTR_SEG_TO_LIN(cs->lpCreateParams);
1005 ci->hWindowMenu = ccs->hWindowMenu;
1006 ci->idFirstChild = ccs->idFirstChild;
1009 ci->hwndChildMaximized = 0;
1010 ci->nActiveChildren = 0;
1011 ci->nTotalCreated = 0;
1012 ci->frameTitle = NULL;
1013 ci->mdiFlags = 0;
1014 ci->self = hwnd;
1015 w->dwStyle |= WS_CLIPCHILDREN;
1017 if (!hBmpClose)
1019 hBmpClose = CreateMDIMenuBitmap();
1020 hBmpRestore = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_RESTORE) );
1022 MDI_UpdateFrameText(frameWnd, hwnd, MDI_NOFRAMEREPAINT,frameWnd->text);
1024 AppendMenuA( ci->hWindowMenu, MF_SEPARATOR, 0, NULL );
1026 GetClientRect(frameWnd->hwndSelf, &rect);
1027 NC_HandleNCCalcSize( w, &rect );
1028 w->rectClient = rect;
1030 TRACE(mdi,"Client created - hwnd = %04x, idFirst = %u\n",
1031 hwnd, ci->idFirstChild );
1033 retvalue = 0;
1034 goto END;
1036 case WM_DESTROY:
1037 if( ci->hwndChildMaximized ) MDI_RestoreFrameMenu(w, frameWnd->hwndSelf);
1038 if((nItems = GetMenuItemCount(ci->hWindowMenu)) > 0)
1040 ci->idFirstChild = nItems - 1;
1041 ci->nActiveChildren++; /* to delete a separator */
1042 while( ci->nActiveChildren-- )
1043 DeleteMenu(ci->hWindowMenu,MF_BYPOSITION,ci->idFirstChild--);
1045 retvalue = 0;
1046 goto END;
1048 case WM_MDIACTIVATE:
1049 if( ci->hwndActiveChild != (HWND)wParam )
1050 SetWindowPos((HWND)wParam, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE);
1051 retvalue = 0;
1052 goto END;
1054 case WM_MDICASCADE:
1055 retvalue = MDICascade(w, ci);
1056 goto END;
1058 case WM_MDICREATE:
1059 if (lParam) retvalue = MDICreateChild( w, ci, hwnd,
1060 (MDICREATESTRUCTA*)lParam );
1061 else retvalue = 0;
1062 goto END;
1064 case WM_MDIDESTROY:
1065 retvalue = MDIDestroyChild( w, ci, hwnd, (HWND)wParam, TRUE );
1066 goto END;
1068 case WM_MDIGETACTIVE:
1069 if (lParam) *(BOOL *)lParam = (ci->hwndChildMaximized > 0);
1070 retvalue = ci->hwndActiveChild;
1071 goto END;
1073 case WM_MDIICONARRANGE:
1074 ci->mdiFlags |= MDIF_NEEDUPDATE;
1075 ArrangeIconicWindows(hwnd);
1076 ci->sbRecalc = SB_BOTH+1;
1077 SendMessageA(hwnd, WM_MDICALCCHILDSCROLL, 0, 0L);
1078 retvalue = 0;
1079 goto END;
1081 case WM_MDIMAXIMIZE:
1082 ShowWindow( (HWND)wParam, SW_MAXIMIZE );
1083 retvalue = 0;
1084 goto END;
1086 case WM_MDINEXT: /* lParam != 0 means previous window */
1087 MDI_SwitchActiveChild(hwnd, (HWND)wParam, (lParam)? FALSE : TRUE );
1088 break;
1090 case WM_MDIRESTORE:
1091 SendMessageA( (HWND)wParam, WM_SYSCOMMAND, SC_RESTORE, 0);
1092 retvalue = 0;
1093 goto END;
1095 case WM_MDISETMENU:
1096 retvalue = MDISetMenu( hwnd, (HMENU)wParam, (HMENU)lParam );
1097 goto END;
1098 case WM_MDIREFRESHMENU:
1099 retvalue = MDIRefreshMenu( hwnd, (HMENU)wParam, (HMENU)lParam );
1100 goto END;
1102 case WM_MDITILE:
1103 ci->mdiFlags |= MDIF_NEEDUPDATE;
1104 ShowScrollBar(hwnd,SB_BOTH,FALSE);
1105 MDITile(w, ci, wParam);
1106 ci->mdiFlags &= ~MDIF_NEEDUPDATE;
1107 retvalue = 0;
1108 goto END;
1110 case WM_VSCROLL:
1111 case WM_HSCROLL:
1112 ci->mdiFlags |= MDIF_NEEDUPDATE;
1113 ScrollChildren(hwnd, message, wParam, lParam);
1114 ci->mdiFlags &= ~MDIF_NEEDUPDATE;
1115 retvalue = 0;
1116 goto END;
1118 case WM_SETFOCUS:
1119 if( ci->hwndActiveChild )
1121 w = WIN_FindWndPtr( ci->hwndActiveChild );
1122 if( !(w->dwStyle & WS_MINIMIZE) )
1123 SetFocus( ci->hwndActiveChild );
1125 retvalue = 0;
1126 goto END;
1128 case WM_NCACTIVATE:
1129 if( ci->hwndActiveChild )
1130 SendMessageA(ci->hwndActiveChild, message, wParam, lParam);
1131 break;
1133 case WM_PARENTNOTIFY:
1134 if (LOWORD(wParam) == WM_LBUTTONDOWN)
1136 POINT16 pt = MAKEPOINT16(lParam);
1137 HWND16 child = ChildWindowFromPoint16(hwnd, pt);
1139 TRACE(mdi,"notification from %04x (%i,%i)\n",child,pt.x,pt.y);
1141 if( child && child != hwnd && child != ci->hwndActiveChild )
1142 SetWindowPos(child, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE );
1144 retvalue = 0;
1145 goto END;
1147 case WM_SIZE:
1148 if( IsWindow(ci->hwndChildMaximized) )
1150 WND* child = WIN_FindWndPtr(ci->hwndChildMaximized);
1151 RECT rect = { 0, 0, LOWORD(lParam), HIWORD(lParam) };
1153 AdjustWindowRectEx(&rect, child->dwStyle, 0, child->dwExStyle);
1154 MoveWindow(ci->hwndChildMaximized, rect.left, rect.top,
1155 rect.right - rect.left, rect.bottom - rect.top, 1);
1156 WIN_ReleaseWndPtr(child);
1158 else
1159 MDI_PostUpdate(hwnd, ci, SB_BOTH+1);
1161 break;
1163 case WM_MDICALCCHILDSCROLL:
1164 if( (ci->mdiFlags & MDIF_NEEDUPDATE) && ci->sbRecalc )
1166 CalcChildScroll16(hwnd, ci->sbRecalc-1);
1167 ci->sbRecalc = 0;
1168 ci->mdiFlags &= ~MDIF_NEEDUPDATE;
1170 retvalue = 0;
1171 goto END;
1174 retvalue = DefWindowProcA( hwnd, message, wParam, lParam );
1175 END:
1176 WIN_ReleaseWndPtr(w);
1177 WIN_ReleaseWndPtr(frameWnd);
1178 return retvalue;
1182 /***********************************************************************
1183 * DefFrameProc16 (USER.445)
1185 LRESULT WINAPI DefFrameProc16( HWND16 hwnd, HWND16 hwndMDIClient,
1186 UINT16 message, WPARAM16 wParam, LPARAM lParam )
1188 HWND16 childHwnd;
1189 MDICLIENTINFO* ci;
1190 WND* wndPtr;
1192 if (hwndMDIClient)
1194 switch (message)
1196 case WM_COMMAND:
1197 wndPtr = WIN_FindWndPtr(hwndMDIClient);
1199 if (!wndPtr) {
1200 ERR(mdi,"null wndPtr for mdi window hwndMDIClient=%04x\n",
1201 hwndMDIClient);
1202 return 0;
1205 ci = (MDICLIENTINFO*)wndPtr->wExtra;
1207 /* check for possible syscommands for maximized MDI child */
1208 WIN_ReleaseWndPtr(wndPtr);
1210 if( ci && (
1211 wParam < ci->idFirstChild ||
1212 wParam >= ci->idFirstChild + ci->nActiveChildren
1214 if( (wParam - 0xF000) & 0xF00F ) break;
1215 switch( wParam )
1217 case SC_SIZE:
1218 case SC_MOVE:
1219 case SC_MINIMIZE:
1220 case SC_MAXIMIZE:
1221 case SC_NEXTWINDOW:
1222 case SC_PREVWINDOW:
1223 case SC_CLOSE:
1224 case SC_RESTORE:
1225 if( ci->hwndChildMaximized )
1226 return SendMessage16( ci->hwndChildMaximized, WM_SYSCOMMAND,
1227 wParam, lParam);
1230 else
1232 wndPtr = WIN_FindWndPtr(hwndMDIClient);
1233 childHwnd = MDI_GetChildByID(wndPtr,wParam );
1234 WIN_ReleaseWndPtr(wndPtr);
1236 if( childHwnd )
1237 SendMessage16(hwndMDIClient, WM_MDIACTIVATE,
1238 (WPARAM16)childHwnd , 0L);
1240 break;
1242 case WM_NCACTIVATE:
1243 SendMessage16(hwndMDIClient, message, wParam, lParam);
1244 break;
1246 case WM_SETTEXT:
1247 wndPtr = WIN_FindWndPtr(hwnd);
1248 MDI_UpdateFrameText(wndPtr, hwndMDIClient,
1249 MDI_REPAINTFRAME,
1250 (LPCSTR)PTR_SEG_TO_LIN(lParam));
1251 WIN_ReleaseWndPtr(wndPtr);
1252 return 0;
1254 case WM_SETFOCUS:
1255 SetFocus(hwndMDIClient);
1256 break;
1258 case WM_SIZE:
1259 MoveWindow16(hwndMDIClient, 0, 0,
1260 LOWORD(lParam), HIWORD(lParam), TRUE);
1261 break;
1263 case WM_NEXTMENU:
1265 wndPtr = WIN_FindWndPtr(hwndMDIClient);
1266 ci = (MDICLIENTINFO*)wndPtr->wExtra;
1268 if( !(wndPtr->parent->dwStyle & WS_MINIMIZE)
1269 && ci->hwndActiveChild && !ci->hwndChildMaximized )
1271 /* control menu is between the frame system menu and
1272 * the first entry of menu bar */
1274 if( (wParam == VK_LEFT &&
1275 wndPtr->parent->wIDmenu == LOWORD(lParam)) ||
1276 (wParam == VK_RIGHT &&
1277 GetSubMenu16(wndPtr->parent->hSysMenu, 0) == LOWORD(lParam)) )
1279 LRESULT retvalue;
1280 WIN_ReleaseWndPtr(wndPtr);
1281 wndPtr = WIN_FindWndPtr(ci->hwndActiveChild);
1282 retvalue = MAKELONG( GetSubMenu16(wndPtr->hSysMenu, 0),
1283 ci->hwndActiveChild);
1284 WIN_ReleaseWndPtr(wndPtr);
1285 return retvalue;
1288 WIN_ReleaseWndPtr(wndPtr);
1289 break;
1293 return DefWindowProc16(hwnd, message, wParam, lParam);
1297 /***********************************************************************
1298 * DefFrameProc32A (USER32.122)
1300 LRESULT WINAPI DefFrameProcA( HWND hwnd, HWND hwndMDIClient,
1301 UINT message, WPARAM wParam, LPARAM lParam)
1303 if (hwndMDIClient)
1305 switch (message)
1307 case WM_COMMAND:
1308 return DefFrameProc16( hwnd, hwndMDIClient, message,
1309 (WPARAM16)wParam,
1310 MAKELPARAM( (HWND16)lParam, HIWORD(wParam) ) );
1312 case WM_NCACTIVATE:
1313 SendMessageA(hwndMDIClient, message, wParam, lParam);
1314 break;
1316 case WM_SETTEXT: {
1317 LRESULT ret;
1318 LPSTR segstr = SEGPTR_STRDUP((LPSTR)lParam);
1320 ret = DefFrameProc16(hwnd, hwndMDIClient, message,
1321 wParam, (LPARAM)SEGPTR_GET(segstr) );
1322 SEGPTR_FREE(segstr);
1323 return ret;
1326 case WM_NEXTMENU:
1327 case WM_SETFOCUS:
1328 case WM_SIZE:
1329 return DefFrameProc16( hwnd, hwndMDIClient, message,
1330 wParam, lParam );
1334 return DefWindowProcA(hwnd, message, wParam, lParam);
1338 /***********************************************************************
1339 * DefFrameProc32W (USER32.123)
1341 LRESULT WINAPI DefFrameProcW( HWND hwnd, HWND hwndMDIClient,
1342 UINT message, WPARAM wParam, LPARAM lParam)
1344 if (hwndMDIClient)
1346 switch (message)
1348 case WM_COMMAND:
1349 return DefFrameProc16( hwnd, hwndMDIClient, message,
1350 (WPARAM16)wParam,
1351 MAKELPARAM( (HWND16)lParam, HIWORD(wParam) ) );
1353 case WM_NCACTIVATE:
1354 SendMessageW(hwndMDIClient, message, wParam, lParam);
1355 break;
1357 case WM_SETTEXT:
1359 LPSTR txt = HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)lParam);
1360 LRESULT ret = DefFrameProcA( hwnd, hwndMDIClient, message,
1361 wParam, (DWORD)txt );
1362 HeapFree(GetProcessHeap(),0,txt);
1363 return ret;
1365 case WM_NEXTMENU:
1366 case WM_SETFOCUS:
1367 case WM_SIZE:
1368 return DefFrameProcA( hwnd, hwndMDIClient, message,
1369 wParam, lParam );
1373 return DefWindowProcW( hwnd, message, wParam, lParam );
1377 /***********************************************************************
1378 * DefMDIChildProc16 (USER.447)
1380 LRESULT WINAPI DefMDIChildProc16( HWND16 hwnd, UINT16 message,
1381 WPARAM16 wParam, LPARAM lParam )
1383 MDICLIENTINFO *ci;
1384 WND *clientWnd,*tmpWnd = 0;
1385 LRESULT retvalue;
1387 clientWnd = WIN_FindWndPtr(GetParent16(hwnd));
1388 ci = (MDICLIENTINFO *) clientWnd->wExtra;
1390 switch (message)
1392 case WM_SETTEXT:
1393 DefWindowProc16(hwnd, message, wParam, lParam);
1394 MDI_MenuModifyItem(clientWnd,hwnd);
1395 if( ci->hwndChildMaximized == hwnd )
1396 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1397 MDI_REPAINTFRAME, NULL );
1398 retvalue = 0;
1399 goto END;
1401 case WM_CLOSE:
1402 SendMessage16(ci->self,WM_MDIDESTROY,(WPARAM16)hwnd,0L);
1403 retvalue = 0;
1404 goto END;
1406 case WM_SETFOCUS:
1407 if( ci->hwndActiveChild != hwnd )
1408 MDI_ChildActivate(clientWnd, hwnd);
1409 break;
1411 case WM_CHILDACTIVATE:
1412 MDI_ChildActivate(clientWnd, hwnd);
1413 retvalue = 0;
1414 goto END;
1416 case WM_NCPAINT:
1417 TRACE(mdi,"WM_NCPAINT for %04x, active %04x\n",
1418 hwnd, ci->hwndActiveChild );
1419 break;
1421 case WM_SYSCOMMAND:
1422 switch( wParam )
1424 case SC_MOVE:
1425 if( ci->hwndChildMaximized == hwnd)
1427 retvalue = 0;
1428 goto END;
1430 break;
1431 case SC_RESTORE:
1432 case SC_MINIMIZE:
1433 tmpWnd = WIN_FindWndPtr(hwnd);
1434 tmpWnd->dwStyle |= WS_SYSMENU;
1435 WIN_ReleaseWndPtr(tmpWnd);
1436 break;
1437 case SC_MAXIMIZE:
1438 if( ci->hwndChildMaximized == hwnd)
1440 retvalue = SendMessage16( clientWnd->parent->hwndSelf,
1441 message, wParam, lParam);
1442 goto END;
1444 tmpWnd = WIN_FindWndPtr(hwnd);
1445 tmpWnd->dwStyle &= ~WS_SYSMENU;
1446 WIN_ReleaseWndPtr(tmpWnd);
1447 break;
1448 case SC_NEXTWINDOW:
1449 SendMessage16( ci->self, WM_MDINEXT, 0, 0);
1450 retvalue = 0;
1451 goto END;
1452 case SC_PREVWINDOW:
1453 SendMessage16( ci->self, WM_MDINEXT, 0, 1);
1454 retvalue = 0;
1455 goto END;
1457 break;
1459 case WM_GETMINMAXINFO:
1460 MDI_ChildGetMinMaxInfo(clientWnd, hwnd, (MINMAXINFO16*) PTR_SEG_TO_LIN(lParam));
1461 retvalue = 0;
1462 goto END;
1464 case WM_SETVISIBLE:
1465 if( ci->hwndChildMaximized) ci->mdiFlags &= ~MDIF_NEEDUPDATE;
1466 else
1467 MDI_PostUpdate(clientWnd->hwndSelf, ci, SB_BOTH+1);
1468 break;
1470 case WM_SIZE:
1471 /* do not change */
1473 if( ci->hwndActiveChild == hwnd && wParam != SIZE_MAXIMIZED )
1475 ci->hwndChildMaximized = 0;
1477 MDI_RestoreFrameMenu( clientWnd->parent, hwnd);
1478 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1479 MDI_REPAINTFRAME, NULL );
1482 if( wParam == SIZE_MAXIMIZED )
1484 HWND16 hMaxChild = ci->hwndChildMaximized;
1486 if( hMaxChild == hwnd ) break;
1488 if( hMaxChild)
1490 SendMessage16( hMaxChild, WM_SETREDRAW, FALSE, 0L );
1492 MDI_RestoreFrameMenu( clientWnd->parent, hMaxChild);
1493 ShowWindow16( hMaxChild, SW_SHOWNOACTIVATE);
1495 SendMessage16( hMaxChild, WM_SETREDRAW, TRUE, 0L );
1498 TRACE(mdi,"maximizing child %04x\n", hwnd );
1500 ci->hwndChildMaximized = hwnd; /* !!! */
1501 ci->hwndActiveChild = hwnd;
1503 MDI_AugmentFrameMenu( ci, clientWnd->parent, hwnd);
1504 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1505 MDI_REPAINTFRAME, NULL );
1508 if( wParam == SIZE_MINIMIZED )
1510 HWND16 switchTo = MDI_GetWindow(clientWnd, hwnd, TRUE, WS_MINIMIZE);
1512 if( switchTo )
1513 SendMessage16( switchTo, WM_CHILDACTIVATE, 0, 0L);
1516 MDI_PostUpdate(clientWnd->hwndSelf, ci, SB_BOTH+1);
1517 break;
1519 case WM_MENUCHAR:
1521 /* MDI children don't have menu bars */
1522 PostMessage16( clientWnd->parent->hwndSelf, WM_SYSCOMMAND,
1523 (WPARAM16)SC_KEYMENU, (LPARAM)wParam);
1524 retvalue = 0x00010000L;
1525 goto END;
1527 case WM_NEXTMENU:
1529 if( wParam == VK_LEFT ) /* switch to frame system menu */
1531 retvalue = MAKELONG( GetSubMenu16(clientWnd->parent->hSysMenu, 0),
1532 clientWnd->parent->hwndSelf );
1533 goto END;
1535 if( wParam == VK_RIGHT ) /* to frame menu bar */
1537 retvalue = MAKELONG( clientWnd->parent->wIDmenu,
1538 clientWnd->parent->hwndSelf );
1539 goto END;
1542 break;
1544 case WM_SYSCHAR:
1545 if (wParam == '-')
1547 SendMessage16(hwnd,WM_SYSCOMMAND,
1548 (WPARAM16)SC_KEYMENU, (LPARAM)(DWORD)VK_SPACE);
1549 retvalue = 0;
1550 goto END;
1554 retvalue = DefWindowProc16(hwnd, message, wParam, lParam);
1555 END:
1556 WIN_ReleaseWndPtr(clientWnd);
1560 /***********************************************************************
1561 * DefMDIChildProc32A (USER32.124)
1563 LRESULT WINAPI DefMDIChildProcA( HWND hwnd, UINT message,
1564 WPARAM wParam, LPARAM lParam )
1566 MDICLIENTINFO *ci;
1567 WND *clientWnd,*tmpWnd;
1568 LRESULT retvalue;
1570 tmpWnd = WIN_FindWndPtr(hwnd);
1571 clientWnd = WIN_FindWndPtr(tmpWnd->parent->hwndSelf);
1572 ci = (MDICLIENTINFO *) clientWnd->wExtra;
1573 WIN_ReleaseWndPtr(tmpWnd);
1575 switch (message)
1577 case WM_SETTEXT:
1578 DefWindowProcA(hwnd, message, wParam, lParam);
1579 MDI_MenuModifyItem(clientWnd,hwnd);
1580 if( ci->hwndChildMaximized == hwnd )
1581 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1582 MDI_REPAINTFRAME, NULL );
1583 retvalue = 0;
1584 goto END;
1586 case WM_GETMINMAXINFO:
1588 MINMAXINFO16 mmi;
1589 STRUCT32_MINMAXINFO32to16( (MINMAXINFO *)lParam, &mmi );
1590 MDI_ChildGetMinMaxInfo( clientWnd, hwnd, &mmi );
1591 STRUCT32_MINMAXINFO16to32( &mmi, (MINMAXINFO *)lParam );
1593 retvalue = 0;
1594 goto END;
1596 case WM_MENUCHAR:
1598 /* MDI children don't have menu bars */
1599 PostMessage16( clientWnd->parent->hwndSelf, WM_SYSCOMMAND,
1600 (WPARAM16)SC_KEYMENU, (LPARAM)LOWORD(wParam) );
1601 retvalue = 0x00010000L;
1602 goto END;
1604 case WM_CLOSE:
1605 case WM_SETFOCUS:
1606 case WM_CHILDACTIVATE:
1607 case WM_NCPAINT:
1608 case WM_SYSCOMMAND:
1609 case WM_SETVISIBLE:
1610 case WM_SIZE:
1611 case WM_NEXTMENU:
1612 retvalue = DefMDIChildProc16( hwnd, message, (WPARAM16)wParam, lParam );
1613 goto END;
1615 case WM_SYSCHAR:
1616 if (wParam == '-')
1618 SendMessageA(hwnd,WM_SYSCOMMAND,
1619 (WPARAM)SC_KEYMENU, (LPARAM)(DWORD)VK_SPACE);
1620 retvalue = 0;
1621 goto END;
1624 retvalue = DefWindowProcA(hwnd, message, wParam, lParam);
1625 END:
1626 WIN_ReleaseWndPtr(clientWnd);
1627 return retvalue;
1631 /***********************************************************************
1632 * DefMDIChildProc32W (USER32.125)
1634 LRESULT WINAPI DefMDIChildProcW( HWND hwnd, UINT message,
1635 WPARAM wParam, LPARAM lParam )
1637 MDICLIENTINFO *ci;
1638 WND *clientWnd;
1639 LRESULT retvalue;
1641 clientWnd = WIN_FindWndPtr(GetParent16(hwnd));
1642 ci = (MDICLIENTINFO *) clientWnd->wExtra;
1644 switch (message)
1646 case WM_SETTEXT:
1647 DefWindowProcW(hwnd, message, wParam, lParam);
1648 MDI_MenuModifyItem(clientWnd,hwnd);
1649 if( ci->hwndChildMaximized == hwnd )
1650 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1651 MDI_REPAINTFRAME, NULL );
1652 retvalue = 0;
1653 goto END;
1655 case WM_GETMINMAXINFO:
1656 case WM_MENUCHAR:
1657 case WM_CLOSE:
1658 case WM_SETFOCUS:
1659 case WM_CHILDACTIVATE:
1660 case WM_NCPAINT:
1661 case WM_SYSCOMMAND:
1662 case WM_SETVISIBLE:
1663 case WM_SIZE:
1664 case WM_NEXTMENU:
1665 retvalue = DefMDIChildProcA( hwnd, message, (WPARAM16)wParam, lParam );
1666 goto END;
1668 case WM_SYSCHAR:
1669 if (wParam == '-')
1671 SendMessageW(hwnd,WM_SYSCOMMAND,
1672 (WPARAM)SC_KEYMENU, (LPARAM)(DWORD)VK_SPACE);
1673 retvalue = 0;
1674 goto END;
1677 retvalue = DefWindowProcW(hwnd, message, wParam, lParam);
1678 END:
1679 WIN_ReleaseWndPtr(clientWnd);
1680 return retvalue;
1685 /**********************************************************************
1686 * CreateMDIWindowA [USER32.79] Creates a MDI child in new thread
1687 * FIXME: its in the same thread now
1689 * RETURNS
1690 * Success: Handle to created window
1691 * Failure: NULL
1693 HWND WINAPI CreateMDIWindowA(
1694 LPCSTR lpClassName, /* [in] Pointer to registered child class name */
1695 LPCSTR lpWindowName, /* [in] Pointer to window name */
1696 DWORD dwStyle, /* [in] Window style */
1697 INT X, /* [in] Horizontal position of window */
1698 INT Y, /* [in] Vertical position of window */
1699 INT nWidth, /* [in] Width of window */
1700 INT nHeight, /* [in] Height of window */
1701 HWND hWndParent, /* [in] Handle to parent window */
1702 HINSTANCE hInstance, /* [in] Handle to application instance */
1703 LPARAM lParam) /* [in] Application-defined value */
1705 WARN(mdi,"is only single threaded!\n");
1706 return MDI_CreateMDIWindowA(lpClassName, lpWindowName, dwStyle, X, Y,
1707 nWidth, nHeight, hWndParent, hInstance, lParam);
1710 /**********************************************************************
1711 * MDI_CreateMDIWindowA
1712 * single threaded version of CreateMDIWindowA
1713 * called by CreateWindowEx32A
1715 HWND MDI_CreateMDIWindowA(
1716 LPCSTR lpClassName,
1717 LPCSTR lpWindowName,
1718 DWORD dwStyle,
1719 INT X,
1720 INT Y,
1721 INT nWidth,
1722 INT nHeight,
1723 HWND hWndParent,
1724 HINSTANCE hInstance,
1725 LPARAM lParam)
1727 MDICLIENTINFO* pCi;
1728 MDICREATESTRUCTA cs;
1729 WND *pWnd=WIN_FindWndPtr(hWndParent);
1730 HWND retvalue;
1732 TRACE(mdi, "(%s,%s,%ld,%d,%d,%d,%d,%x,%d,%ld)\n",
1733 debugstr_a(lpClassName),debugstr_a(lpWindowName),dwStyle,X,Y,
1734 nWidth,nHeight,hWndParent,hInstance,lParam);
1736 if(!pWnd){
1737 ERR(mdi," bad hwnd for MDI-client: %d\n",hWndParent);
1738 return 0;
1740 cs.szClass=lpClassName;
1741 cs.szTitle=lpWindowName;
1742 cs.hOwner=hInstance;
1743 cs.x=X;
1744 cs.y=Y;
1745 cs.cx=nWidth;
1746 cs.cy=nHeight;
1747 cs.style=dwStyle;
1748 cs.lParam=lParam;
1750 pCi=(MDICLIENTINFO *)pWnd->wExtra;
1752 retvalue = MDICreateChild(pWnd,pCi,hWndParent,&cs);
1753 WIN_ReleaseWndPtr(pWnd);
1754 return retvalue;
1757 /***************************************
1758 * CreateMDIWindow32W [USER32.80] Creates a MDI child in new thread
1760 * RETURNS
1761 * Success: Handle to created window
1762 * Failure: NULL
1764 HWND WINAPI CreateMDIWindowW(
1765 LPCWSTR lpClassName, /* [in] Pointer to registered child class name */
1766 LPCWSTR lpWindowName, /* [in] Pointer to window name */
1767 DWORD dwStyle, /* [in] Window style */
1768 INT X, /* [in] Horizontal position of window */
1769 INT Y, /* [in] Vertical position of window */
1770 INT nWidth, /* [in] Width of window */
1771 INT nHeight, /* [in] Height of window */
1772 HWND hWndParent, /* [in] Handle to parent window */
1773 HINSTANCE hInstance, /* [in] Handle to application instance */
1774 LPARAM lParam) /* [in] Application-defined value */
1776 FIXME(mdi, "(%s,%s,%ld,%d,%d,%d,%d,%x,%d,%ld): stub\n",
1777 debugstr_w(lpClassName),debugstr_w(lpWindowName),dwStyle,X,Y,
1778 nWidth,nHeight,hWndParent,hInstance,lParam);
1779 return (HWND)NULL;
1783 /******************************************************************************
1784 * CreateMDIWindow32W [USER32.80] Creates a MDI child window
1785 * single threaded version of CreateMDIWindow
1786 * called by CreateWindowEx32W().
1788 HWND MDI_CreateMDIWindowW(
1789 LPCWSTR lpClassName, /* [in] Pointer to registered child class name */
1790 LPCWSTR lpWindowName, /* [in] Pointer to window name */
1791 DWORD dwStyle, /* [in] Window style */
1792 INT X, /* [in] Horizontal position of window */
1793 INT Y, /* [in] Vertical position of window */
1794 INT nWidth, /* [in] Width of window */
1795 INT nHeight, /* [in] Height of window */
1796 HWND hWndParent, /* [in] Handle to parent window */
1797 HINSTANCE hInstance, /* [in] Handle to application instance */
1798 LPARAM lParam) /* [in] Application-defined value */
1800 FIXME(mdi, "(%s,%s,%ld,%d,%d,%d,%d,%x,%d,%ld): stub\n",
1801 debugstr_w(lpClassName),debugstr_w(lpWindowName),dwStyle,X,Y,
1802 nWidth,nHeight,hWndParent,hInstance,lParam);
1803 return (HWND)NULL;
1807 /**********************************************************************
1808 * TranslateMDISysAccel32 (USER32.555)
1810 BOOL WINAPI TranslateMDISysAccel( HWND hwndClient, LPMSG msg )
1812 MSG16 msg16;
1814 STRUCT32_MSG32to16(msg,&msg16);
1815 /* MDICLIENTINFO is still the same for win32 and win16 ... */
1816 return TranslateMDISysAccel16(hwndClient,&msg16);
1820 /**********************************************************************
1821 * TranslateMDISysAccel16 (USER.451)
1823 BOOL16 WINAPI TranslateMDISysAccel16( HWND16 hwndClient, LPMSG16 msg )
1825 WND* clientWnd = WIN_FindWndPtr( hwndClient);
1827 if( clientWnd && (msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN))
1829 MDICLIENTINFO *ci = NULL;
1830 WND* wnd;
1832 ci = (MDICLIENTINFO*) clientWnd->wExtra;
1833 WIN_ReleaseWndPtr(clientWnd);
1834 wnd = WIN_FindWndPtr(ci->hwndActiveChild);
1835 if( wnd && !(wnd->dwStyle & WS_DISABLED) )
1837 WPARAM16 wParam = 0;
1839 WIN_ReleaseWndPtr(wnd);
1840 /* translate if the Ctrl key is down and Alt not. */
1842 if( (GetKeyState(VK_CONTROL) & 0x8000) &&
1843 !(GetKeyState(VK_MENU) & 0x8000))
1845 switch( msg->wParam )
1847 case VK_F6:
1848 case VK_TAB:
1849 wParam = ( GetKeyState(VK_SHIFT) & 0x8000 )
1850 ? SC_NEXTWINDOW : SC_PREVWINDOW;
1851 break;
1852 case VK_F4:
1853 case VK_RBUTTON:
1854 wParam = SC_CLOSE;
1855 break;
1856 default:
1857 return 0;
1859 TRACE(mdi,"wParam = %04x\n", wParam);
1860 SendMessage16( ci->hwndActiveChild, WM_SYSCOMMAND,
1861 wParam, (LPARAM)msg->wParam);
1862 return 1;
1865 WIN_ReleaseWndPtr(wnd);
1867 WIN_ReleaseWndPtr(clientWnd);
1868 return 0; /* failure */
1872 /***********************************************************************
1873 * CalcChildScroll (USER.462)
1875 void WINAPI CalcChildScroll16( HWND16 hwnd, WORD scroll )
1877 SCROLLINFO info;
1878 RECT childRect, clientRect;
1879 INT vmin, vmax, hmin, hmax, vpos, hpos;
1880 WND *pWnd, *Wnd;
1882 if (!(Wnd = pWnd = WIN_FindWndPtr( hwnd ))) return;
1883 GetClientRect( hwnd, &clientRect );
1884 SetRectEmpty( &childRect );
1886 for ( WIN_UpdateWndPtr(&pWnd,pWnd->child); pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1888 if( pWnd->dwStyle & WS_MAXIMIZE )
1890 ShowScrollBar(hwnd, SB_BOTH, FALSE);
1891 WIN_ReleaseWndPtr(pWnd);
1892 return;
1894 UnionRect( &childRect, &pWnd->rectWindow, &childRect );
1896 WIN_ReleaseWndPtr(pWnd);
1897 UnionRect( &childRect, &clientRect, &childRect );
1899 hmin = childRect.left; hmax = childRect.right - clientRect.right;
1900 hpos = clientRect.left - childRect.left;
1901 vmin = childRect.top; vmax = childRect.bottom - clientRect.bottom;
1902 vpos = clientRect.top - childRect.top;
1904 switch( scroll )
1906 case SB_HORZ:
1907 vpos = hpos; vmin = hmin; vmax = hmax;
1908 case SB_VERT:
1909 info.cbSize = sizeof(info);
1910 info.nMax = vmax; info.nMin = vmin; info.nPos = vpos;
1911 info.fMask = SIF_POS | SIF_RANGE;
1912 SetScrollInfo(hwnd, scroll, &info, TRUE);
1913 break;
1914 case SB_BOTH:
1915 SCROLL_SetNCSbState( Wnd, vmin, vmax, vpos,
1916 hmin, hmax, hpos);
1918 WIN_ReleaseWndPtr(Wnd);
1922 /***********************************************************************
1923 * ScrollChildren16 (USER.463)
1925 void WINAPI ScrollChildren16(HWND16 hWnd, UINT16 uMsg, WPARAM16 wParam, LPARAM lParam)
1927 return ScrollChildren( hWnd, uMsg, wParam, lParam );
1931 /***********************************************************************
1932 * ScrollChildren32 (USER32.448)
1934 void WINAPI ScrollChildren(HWND hWnd, UINT uMsg, WPARAM wParam,
1935 LPARAM lParam)
1937 WND *wndPtr = WIN_FindWndPtr(hWnd);
1938 INT newPos = -1;
1939 INT curPos, length, minPos, maxPos, shift;
1941 if( !wndPtr ) return;
1943 if( uMsg == WM_HSCROLL )
1945 GetScrollRange(hWnd,SB_HORZ,&minPos,&maxPos);
1946 curPos = GetScrollPos(hWnd,SB_HORZ);
1947 length = (wndPtr->rectClient.right - wndPtr->rectClient.left)/2;
1948 shift = SYSMETRICS_CYHSCROLL;
1950 else if( uMsg == WM_VSCROLL )
1952 GetScrollRange(hWnd,SB_VERT,&minPos,&maxPos);
1953 curPos = GetScrollPos(hWnd,SB_VERT);
1954 length = (wndPtr->rectClient.bottom - wndPtr->rectClient.top)/2;
1955 shift = SYSMETRICS_CXVSCROLL;
1957 else
1959 WIN_ReleaseWndPtr(wndPtr);
1960 return;
1963 WIN_ReleaseWndPtr(wndPtr);
1964 switch( wParam )
1966 case SB_LINEUP:
1967 newPos = curPos - shift;
1968 break;
1969 case SB_LINEDOWN:
1970 newPos = curPos + shift;
1971 break;
1972 case SB_PAGEUP:
1973 newPos = curPos - length;
1974 break;
1975 case SB_PAGEDOWN:
1976 newPos = curPos + length;
1977 break;
1979 case SB_THUMBPOSITION:
1980 newPos = LOWORD(lParam);
1981 break;
1983 case SB_THUMBTRACK:
1984 return;
1986 case SB_TOP:
1987 newPos = minPos;
1988 break;
1989 case SB_BOTTOM:
1990 newPos = maxPos;
1991 break;
1992 case SB_ENDSCROLL:
1993 CalcChildScroll16(hWnd,(uMsg == WM_VSCROLL)?SB_VERT:SB_HORZ);
1994 return;
1997 if( newPos > maxPos )
1998 newPos = maxPos;
1999 else
2000 if( newPos < minPos )
2001 newPos = minPos;
2003 SetScrollPos(hWnd, (uMsg == WM_VSCROLL)?SB_VERT:SB_HORZ , newPos, TRUE);
2005 if( uMsg == WM_VSCROLL )
2006 ScrollWindowEx(hWnd ,0 ,curPos - newPos, NULL, NULL, 0, NULL,
2007 SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
2008 else
2009 ScrollWindowEx(hWnd ,curPos - newPos, 0, NULL, NULL, 0, NULL,
2010 SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
2014 /******************************************************************************
2015 * CascadeWindows [USER32.21] Cascades MDI child windows
2017 * RETURNS
2018 * Success: Number of cascaded windows.
2019 * Failure: 0
2021 WORD WINAPI
2022 CascadeWindows (HWND hwndParent, UINT wFlags, const LPRECT lpRect,
2023 UINT cKids, const HWND *lpKids)
2025 FIXME (mdi, "(0x%08x,0x%08x,...,%u,...): stub\n",
2026 hwndParent, wFlags, cKids);
2028 return 0;
2032 /******************************************************************************
2033 * TileWindows [USER32.545] Tiles MDI child windows
2035 * RETURNS
2036 * Success: Number of tiled windows.
2037 * Failure: 0
2039 WORD WINAPI
2040 TileWindows (HWND hwndParent, UINT wFlags, const LPRECT lpRect,
2041 UINT cKids, const HWND *lpKids)
2043 FIXME (mdi, "(0x%08x,0x%08x,...,%u,...): stub\n",
2044 hwndParent, wFlags, cKids);
2046 return 0;