Much nicer way to select wine's location.
[wine/testsucceed.git] / windows / mdi.c
blob291007e0b17a0678742b2464b0295495ce004c12
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 DEFAULT_DEBUG_CHANNEL(mdi)
33 #define MDIF_NEEDUPDATE 0x0001
35 static HBITMAP16 hBmpClose = 0;
36 static HBITMAP16 hBmpRestore = 0;
38 INT SCROLL_SetNCSbState(WND*,int,int,int,int,int,int);
40 /* ----------------- declarations ----------------- */
41 static void MDI_UpdateFrameText(WND *, HWND, BOOL, LPCSTR);
42 static BOOL MDI_AugmentFrameMenu(MDICLIENTINFO*, WND *, HWND);
43 static BOOL MDI_RestoreFrameMenu(WND *, HWND);
45 static LONG MDI_ChildActivate( WND*, HWND );
47 /* -------- Miscellaneous service functions ----------
49 * MDI_GetChildByID
52 static HWND MDI_GetChildByID(WND* wndPtr, INT id)
54 for (wndPtr = wndPtr->child; wndPtr; wndPtr = wndPtr->next)
55 if (wndPtr->wIDmenu == id) return wndPtr->hwndSelf;
56 return 0;
59 static void MDI_PostUpdate(HWND hwnd, MDICLIENTINFO* ci, WORD recalc)
61 if( !(ci->mdiFlags & MDIF_NEEDUPDATE) )
63 ci->mdiFlags |= MDIF_NEEDUPDATE;
64 PostMessageA( hwnd, WM_MDICALCCHILDSCROLL, 0, 0);
66 ci->sbRecalc = recalc;
69 /**********************************************************************
70 * MDI_MenuModifyItem
72 static BOOL MDI_MenuModifyItem(WND* clientWnd, HWND hWndChild )
74 char buffer[128];
75 MDICLIENTINFO *clientInfo = (MDICLIENTINFO*)clientWnd->wExtra;
76 WND *wndPtr = WIN_FindWndPtr(hWndChild);
77 UINT n = sprintf(buffer, "%d ",
78 wndPtr->wIDmenu - clientInfo->idFirstChild + 1);
79 BOOL bRet = 0;
81 if( !clientInfo->hWindowMenu )
83 bRet = FALSE;
84 goto END;
87 if (wndPtr->text) lstrcpynA(buffer + n, wndPtr->text, sizeof(buffer) - n );
89 n = GetMenuState(clientInfo->hWindowMenu,wndPtr->wIDmenu ,MF_BYCOMMAND);
90 bRet = ModifyMenuA(clientInfo->hWindowMenu , wndPtr->wIDmenu,
91 MF_BYCOMMAND | MF_STRING, wndPtr->wIDmenu, buffer );
92 CheckMenuItem(clientInfo->hWindowMenu ,wndPtr->wIDmenu , n & MF_CHECKED);
93 END:
94 WIN_ReleaseWndPtr(wndPtr);
95 return bRet;
98 /**********************************************************************
99 * MDI_MenuDeleteItem
101 static BOOL MDI_MenuDeleteItem(WND* clientWnd, HWND hWndChild )
103 char buffer[128];
104 MDICLIENTINFO *clientInfo = (MDICLIENTINFO*)clientWnd->wExtra;
105 WND *wndPtr = WIN_FindWndPtr(hWndChild);
106 UINT index = 0,id,n;
107 BOOL retvalue;
109 if( !clientInfo->nActiveChildren ||
110 !clientInfo->hWindowMenu )
112 retvalue = FALSE;
113 goto END;
116 id = wndPtr->wIDmenu;
117 DeleteMenu(clientInfo->hWindowMenu,id,MF_BYCOMMAND);
119 /* walk the rest of MDI children to prevent gaps in the id
120 * sequence and in the menu child list */
122 for( index = id+1; index <= clientInfo->nActiveChildren +
123 clientInfo->idFirstChild; index++ )
125 WND *tmpWnd = WIN_FindWndPtr(MDI_GetChildByID(clientWnd,index));
126 if( !tmpWnd )
128 TRACE(mdi,"no window for id=%i\n",index);
129 WIN_ReleaseWndPtr(tmpWnd);
130 continue;
133 /* set correct id */
134 tmpWnd->wIDmenu--;
136 n = sprintf(buffer, "%d ",index - clientInfo->idFirstChild);
137 if (tmpWnd->text)
138 lstrcpynA(buffer + n, tmpWnd->text, sizeof(buffer) - n );
140 /* change menu */
141 ModifyMenuA(clientInfo->hWindowMenu ,index ,MF_BYCOMMAND | MF_STRING,
142 index - 1 , buffer );
143 WIN_ReleaseWndPtr(tmpWnd);
145 retvalue = TRUE;
146 END:
147 WIN_ReleaseWndPtr(wndPtr);
148 return retvalue;
151 /**********************************************************************
152 * MDI_GetWindow
154 * returns "activateable" child different from the current or zero
156 static HWND MDI_GetWindow(WND *clientWnd, HWND hWnd, BOOL bNext,
157 DWORD dwStyleMask )
159 MDICLIENTINFO *clientInfo = (MDICLIENTINFO*)clientWnd->wExtra;
160 WND *wndPtr, *pWnd, *pWndLast = NULL;
162 dwStyleMask |= WS_DISABLED | WS_VISIBLE;
163 if( !hWnd ) hWnd = clientInfo->hwndActiveChild;
165 if( !(wndPtr = WIN_FindWndPtr(hWnd)) ) return 0;
167 for ( pWnd = WIN_LockWndPtr(wndPtr->next); ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
169 if (!pWnd ) WIN_UpdateWndPtr(&pWnd,wndPtr->parent->child);
171 if ( pWnd == wndPtr ) break; /* went full circle */
173 if (!pWnd->owner && (pWnd->dwStyle & dwStyleMask) == WS_VISIBLE )
175 pWndLast = pWnd;
176 if ( bNext ) break;
179 WIN_ReleaseWndPtr(wndPtr);
180 WIN_ReleaseWndPtr(pWnd);
181 return pWndLast ? pWndLast->hwndSelf : 0;
184 /**********************************************************************
185 * MDI_CalcDefaultChildPos
187 * It seems that the default height is about 2/3 of the client rect
189 static void MDI_CalcDefaultChildPos( WND* w, WORD n, LPPOINT lpPos,
190 INT delta)
192 INT nstagger;
193 RECT rect = w->rectClient;
194 INT spacing = GetSystemMetrics(SM_CYCAPTION) +
195 GetSystemMetrics(SM_CYFRAME) - 1;
197 if( rect.bottom - rect.top - delta >= spacing )
198 rect.bottom -= delta;
200 nstagger = (rect.bottom - rect.top)/(3 * spacing);
201 lpPos[1].x = (rect.right - rect.left - nstagger * spacing);
202 lpPos[1].y = (rect.bottom - rect.top - nstagger * spacing);
203 lpPos[0].x = lpPos[0].y = spacing * (n%(nstagger+1));
206 /**********************************************************************
207 * MDISetMenu
209 static LRESULT MDISetMenu( HWND hwnd, HMENU hmenuFrame,
210 HMENU hmenuWindow)
212 WND *w = WIN_FindWndPtr(hwnd);
213 MDICLIENTINFO *ci;
214 HWND hwndFrame = GetParent(hwnd);
215 HMENU oldFrameMenu = GetMenu(hwndFrame);
217 TRACE(mdi, "%04x %04x %04x\n",
218 hwnd, hmenuFrame, hmenuWindow);
220 ci = (MDICLIENTINFO *) w->wExtra;
222 if( ci->hwndChildMaximized && hmenuFrame && hmenuFrame!=oldFrameMenu )
223 MDI_RestoreFrameMenu(w->parent, ci->hwndChildMaximized );
225 if( hmenuWindow && hmenuWindow!=ci->hWindowMenu )
227 /* delete menu items from ci->hWindowMenu
228 * and add them to hmenuWindow */
230 INT i = GetMenuItemCount(ci->hWindowMenu) - 1;
231 INT pos = GetMenuItemCount(hmenuWindow) + 1;
233 AppendMenuA( hmenuWindow, MF_SEPARATOR, 0, NULL);
235 if( ci->nActiveChildren )
237 INT j = i - ci->nActiveChildren + 1;
238 char buffer[100];
239 UINT id,state;
241 for( ; i >= j ; i-- )
243 id = GetMenuItemID(ci->hWindowMenu,i );
244 state = GetMenuState(ci->hWindowMenu,i,MF_BYPOSITION);
246 GetMenuStringA(ci->hWindowMenu, i, buffer, 100, MF_BYPOSITION);
248 DeleteMenu(ci->hWindowMenu, i , MF_BYPOSITION);
249 InsertMenuA(hmenuWindow, pos, MF_BYPOSITION | MF_STRING,
250 id, buffer);
251 CheckMenuItem(hmenuWindow ,pos , MF_BYPOSITION | (state & MF_CHECKED));
255 /* remove separator */
256 DeleteMenu(ci->hWindowMenu, i, MF_BYPOSITION);
258 ci->hWindowMenu = hmenuWindow;
261 if( hmenuFrame && hmenuFrame!=oldFrameMenu)
263 SetMenu(hwndFrame, hmenuFrame);
264 if( ci->hwndChildMaximized )
265 MDI_AugmentFrameMenu(ci, w->parent, ci->hwndChildMaximized );
266 WIN_ReleaseWndPtr(w);
267 return oldFrameMenu;
269 WIN_ReleaseWndPtr(w);
270 return 0;
273 /**********************************************************************
274 * MDIRefreshMenu
276 static LRESULT MDIRefreshMenu( HWND hwnd, HMENU hmenuFrame,
277 HMENU hmenuWindow)
279 HWND hwndFrame = GetParent(hwnd);
280 HMENU oldFrameMenu = GetMenu(hwndFrame);
282 TRACE(mdi, "%04x %04x %04x\n",
283 hwnd, hmenuFrame, hmenuWindow);
285 FIXME(mdi,"partially function stub\n");
287 return oldFrameMenu;
291 /* ------------------ MDI child window functions ---------------------- */
294 /**********************************************************************
295 * MDICreateChild
297 static HWND MDICreateChild( WND *w, MDICLIENTINFO *ci, HWND parent,
298 LPMDICREATESTRUCTA cs )
300 POINT pos[2];
301 DWORD style = cs->style | (WS_CHILD | WS_CLIPSIBLINGS);
302 HWND hwnd, hwndMax = 0;
303 WORD wIDmenu = ci->idFirstChild + ci->nActiveChildren;
304 char lpstrDef[]="junk!";
306 TRACE(mdi, "origin %i,%i - dim %i,%i, style %08x\n",
307 cs->x, cs->y, cs->cx, cs->cy, (unsigned)cs->style);
308 /* calculate placement */
309 MDI_CalcDefaultChildPos(w, ci->nTotalCreated++, pos, 0);
311 if (cs->cx == CW_USEDEFAULT || !cs->cx) cs->cx = pos[1].x;
312 if (cs->cy == CW_USEDEFAULT || !cs->cy) cs->cy = pos[1].y;
314 if( cs->x == CW_USEDEFAULT )
316 cs->x = pos[0].x;
317 cs->y = pos[0].y;
320 /* restore current maximized child */
321 if( style & WS_VISIBLE && ci->hwndChildMaximized )
323 if( style & WS_MAXIMIZE )
324 SendMessageA(w->hwndSelf, WM_SETREDRAW, FALSE, 0L );
325 hwndMax = ci->hwndChildMaximized;
326 ShowWindow( hwndMax, SW_SHOWNOACTIVATE );
327 if( style & WS_MAXIMIZE )
328 SendMessageA(w->hwndSelf, WM_SETREDRAW, TRUE, 0L );
331 /* this menu is needed to set a check mark in MDI_ChildActivate */
332 AppendMenuA(ci->hWindowMenu ,MF_STRING ,wIDmenu, lpstrDef );
334 ci->nActiveChildren++;
336 /* fix window style */
337 if( !(w->dwStyle & MDIS_ALLCHILDSTYLES) )
339 style &= (WS_CHILD | WS_CLIPSIBLINGS | WS_MINIMIZE | WS_MAXIMIZE |
340 WS_CLIPCHILDREN | WS_DISABLED | WS_VSCROLL | WS_HSCROLL );
341 style |= (WS_VISIBLE | WS_OVERLAPPEDWINDOW);
344 if( w->flags & WIN_ISWIN32 )
346 hwnd = CreateWindowA( cs->szClass, cs->szTitle, style,
347 cs->x, cs->y, cs->cx, cs->cy, parent,
348 (HMENU16)wIDmenu, cs->hOwner, cs );
350 else
352 MDICREATESTRUCT16 *cs16;
353 LPSTR title, cls;
355 cs16 = SEGPTR_NEW(MDICREATESTRUCT16);
356 STRUCT32_MDICREATESTRUCT32Ato16( cs, cs16 );
357 title = SEGPTR_STRDUP( cs->szTitle );
358 cls = SEGPTR_STRDUP( cs->szClass );
359 cs16->szTitle = SEGPTR_GET(title);
360 cs16->szClass = SEGPTR_GET(cls);
362 hwnd = CreateWindow16( cs->szClass, cs->szTitle, style,
363 cs16->x, cs16->y, cs16->cx, cs16->cy, parent,
364 (HMENU)wIDmenu, cs16->hOwner,
365 (LPVOID)SEGPTR_GET(cs16) );
366 SEGPTR_FREE( title );
367 SEGPTR_FREE( cls );
368 SEGPTR_FREE( cs16 );
371 /* MDI windows are WS_CHILD so they won't be activated by CreateWindow */
373 if (hwnd)
375 WND* wnd = WIN_FindWndPtr( hwnd );
377 MDI_MenuModifyItem(w ,hwnd);
378 if( wnd->dwStyle & WS_MINIMIZE && ci->hwndActiveChild )
379 ShowWindow( hwnd, SW_SHOWMINNOACTIVE );
380 else
382 /* WS_VISIBLE is clear if a) the MDI client has
383 * MDIS_ALLCHILDSTYLES style and 2) the flag is cleared in the
384 * MDICreateStruct. If so the created window is not shown nor
385 * activated.
387 int showflag=wnd->dwStyle & WS_VISIBLE;
388 /* clear visible flag, otherwise SetWindoPos32 ignores
389 * the SWP_SHOWWINDOW command.
391 wnd->dwStyle &= ~WS_VISIBLE;
392 if(showflag){
393 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE );
395 /* Set maximized state here in case hwnd didn't receive WM_SIZE
396 * during CreateWindow - bad!
399 if((wnd->dwStyle & WS_MAXIMIZE) && !ci->hwndChildMaximized )
401 ci->hwndChildMaximized = wnd->hwndSelf;
402 MDI_AugmentFrameMenu( ci, w->parent, hwnd );
403 MDI_UpdateFrameText( w->parent, ci->self, MDI_REPAINTFRAME, NULL );
405 }else
406 /* needed, harmless ? */
407 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE );
410 WIN_ReleaseWndPtr(wnd);
411 TRACE(mdi, "created child - %04x\n",hwnd);
413 else
415 ci->nActiveChildren--;
416 DeleteMenu(ci->hWindowMenu,wIDmenu,MF_BYCOMMAND);
417 if( IsWindow(hwndMax) )
418 ShowWindow(hwndMax, SW_SHOWMAXIMIZED);
421 return hwnd;
424 /**********************************************************************
425 * MDI_ChildGetMinMaxInfo
427 * Note: The rule here is that client rect of the maximized MDI child
428 * is equal to the client rect of the MDI client window.
430 static void MDI_ChildGetMinMaxInfo( WND* clientWnd, HWND hwnd,
431 MINMAXINFO16* lpMinMax )
433 WND* childWnd = WIN_FindWndPtr(hwnd);
434 RECT rect = clientWnd->rectClient;
436 MapWindowPoints( clientWnd->parent->hwndSelf,
437 ((MDICLIENTINFO*)clientWnd->wExtra)->self, (LPPOINT)&rect, 2);
438 AdjustWindowRectEx( &rect, childWnd->dwStyle, 0, childWnd->dwExStyle );
440 lpMinMax->ptMaxSize.x = rect.right -= rect.left;
441 lpMinMax->ptMaxSize.y = rect.bottom -= rect.top;
443 lpMinMax->ptMaxPosition.x = rect.left;
444 lpMinMax->ptMaxPosition.y = rect.top;
446 WIN_ReleaseWndPtr(childWnd);
448 TRACE(mdi,"max rect (%i,%i - %i, %i)\n",
449 rect.left,rect.top,rect.right,rect.bottom);
453 /**********************************************************************
454 * MDI_SwitchActiveChild
456 * Note: SetWindowPos sends WM_CHILDACTIVATE to the child window that is
457 * being activated
459 static void MDI_SwitchActiveChild( HWND clientHwnd, HWND childHwnd,
460 BOOL bNextWindow )
462 WND *w = WIN_FindWndPtr(clientHwnd);
463 HWND hwndTo = 0;
464 HWND hwndPrev = 0;
465 MDICLIENTINFO *ci;
467 hwndTo = MDI_GetWindow(w, childHwnd, bNextWindow, 0);
469 ci = (MDICLIENTINFO *) w->wExtra;
471 TRACE(mdi, "from %04x, to %04x\n",childHwnd,hwndTo);
473 if ( !hwndTo ) goto END; /* no window to switch to */
475 hwndPrev = ci->hwndActiveChild;
477 if ( hwndTo != hwndPrev )
479 BOOL bOptimize = 0;
481 if( ci->hwndChildMaximized )
483 bOptimize = 1;
484 w->dwStyle &= ~WS_VISIBLE;
487 SetWindowPos( hwndTo, HWND_TOP, 0, 0, 0, 0,
488 SWP_NOMOVE | SWP_NOSIZE );
490 if( bNextWindow && hwndPrev )
491 SetWindowPos( hwndPrev, HWND_BOTTOM, 0, 0, 0, 0,
492 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE );
493 if( bOptimize )
494 ShowWindow( clientHwnd, SW_SHOW );
496 END:
497 WIN_ReleaseWndPtr(w);
501 /**********************************************************************
502 * MDIDestroyChild
504 static LRESULT MDIDestroyChild( WND *w_parent, MDICLIENTINFO *ci,
505 HWND parent, HWND child,
506 BOOL flagDestroy )
508 WND *childPtr = WIN_FindWndPtr(child);
510 if( childPtr )
512 if( child == ci->hwndActiveChild )
514 MDI_SwitchActiveChild(parent, child, TRUE);
516 if( child == ci->hwndActiveChild )
518 ShowWindow( child, SW_HIDE);
519 if( child == ci->hwndChildMaximized )
521 MDI_RestoreFrameMenu(w_parent->parent, child);
522 ci->hwndChildMaximized = 0;
523 MDI_UpdateFrameText(w_parent->parent,parent,TRUE,NULL);
526 MDI_ChildActivate(w_parent, 0);
528 MDI_MenuDeleteItem(w_parent, child);
530 WIN_ReleaseWndPtr(childPtr);
532 ci->nActiveChildren--;
534 TRACE(mdi,"child destroyed - %04x\n",child);
536 if (flagDestroy)
538 MDI_PostUpdate(GetParent(child), ci, SB_BOTH+1);
539 DestroyWindow(child);
543 return 0;
547 /**********************************************************************
548 * MDI_ChildActivate
550 * Note: hWndChild is NULL when last child is being destroyed
552 static LONG MDI_ChildActivate( WND *clientPtr, HWND hWndChild )
554 MDICLIENTINFO *clientInfo = (MDICLIENTINFO*)clientPtr->wExtra;
555 HWND prevActiveWnd = clientInfo->hwndActiveChild;
556 WND *wndPtr = WIN_FindWndPtr( hWndChild );
557 WND *wndPrev = WIN_FindWndPtr( prevActiveWnd );
558 BOOL isActiveFrameWnd = 0;
559 LONG retvalue;
561 if( hWndChild == prevActiveWnd )
563 retvalue = 0L;
564 goto END;
567 if( wndPtr )
569 if( wndPtr->dwStyle & WS_DISABLED )
571 retvalue = 0L;
572 goto END;
576 TRACE(mdi,"%04x\n", hWndChild);
578 if( GetActiveWindow() == clientPtr->parent->hwndSelf )
579 isActiveFrameWnd = TRUE;
581 /* deactivate prev. active child */
582 if( wndPrev )
584 wndPrev->dwStyle |= WS_SYSMENU;
585 SendMessageA( prevActiveWnd, WM_NCACTIVATE, FALSE, 0L );
586 SendMessageA( prevActiveWnd, WM_MDIACTIVATE, (WPARAM)prevActiveWnd,
587 (LPARAM)hWndChild);
588 /* uncheck menu item */
589 if( clientInfo->hWindowMenu )
590 CheckMenuItem( clientInfo->hWindowMenu,
591 wndPrev->wIDmenu, 0);
594 /* set appearance */
595 if( clientInfo->hwndChildMaximized )
597 if( clientInfo->hwndChildMaximized != hWndChild ) {
598 if( hWndChild ) {
599 clientInfo->hwndActiveChild = hWndChild;
600 ShowWindow( hWndChild, SW_SHOWMAXIMIZED);
601 } else
602 ShowWindow( clientInfo->hwndActiveChild, SW_SHOWNORMAL );
606 clientInfo->hwndActiveChild = hWndChild;
608 /* check if we have any children left */
609 if( !hWndChild )
611 if( isActiveFrameWnd )
612 SetFocus( clientInfo->self );
613 retvalue = 0;
614 goto END;
617 /* check menu item */
618 if( clientInfo->hWindowMenu )
619 CheckMenuItem( clientInfo->hWindowMenu,
620 wndPtr->wIDmenu, MF_CHECKED);
622 /* bring active child to the top */
623 SetWindowPos( hWndChild, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
625 if( isActiveFrameWnd )
627 SendMessageA( hWndChild, WM_NCACTIVATE, TRUE, 0L);
628 if( GetFocus() == clientInfo->self )
629 SendMessageA( clientInfo->self, WM_SETFOCUS,
630 (WPARAM)clientInfo->self, 0L );
631 else
632 SetFocus( clientInfo->self );
634 SendMessageA( hWndChild, WM_MDIACTIVATE, (WPARAM)prevActiveWnd,
635 (LPARAM)hWndChild );
636 retvalue = 1;
637 END:
638 WIN_ReleaseWndPtr(wndPtr);
639 WIN_ReleaseWndPtr(wndPrev);
640 return retvalue;
643 /* -------------------- MDI client window functions ------------------- */
645 /**********************************************************************
646 * CreateMDIMenuBitmap
648 static HBITMAP16 CreateMDIMenuBitmap(void)
650 HDC hDCSrc = CreateCompatibleDC(0);
651 HDC hDCDest = CreateCompatibleDC(hDCSrc);
652 HBITMAP16 hbClose = LoadBitmap16(0, MAKEINTRESOURCE16(OBM_CLOSE) );
653 HBITMAP16 hbCopy;
654 HANDLE16 hobjSrc, hobjDest;
656 hobjSrc = SelectObject(hDCSrc, hbClose);
657 hbCopy = CreateCompatibleBitmap(hDCSrc,SYSMETRICS_CXSIZE,SYSMETRICS_CYSIZE);
658 hobjDest = SelectObject(hDCDest, hbCopy);
660 BitBlt(hDCDest, 0, 0, SYSMETRICS_CXSIZE, SYSMETRICS_CYSIZE,
661 hDCSrc, SYSMETRICS_CXSIZE, 0, SRCCOPY);
663 SelectObject(hDCSrc, hobjSrc);
664 DeleteObject(hbClose);
665 DeleteDC(hDCSrc);
667 hobjSrc = SelectObject( hDCDest, GetStockObject(BLACK_PEN) );
669 MoveToEx( hDCDest, SYSMETRICS_CXSIZE - 1, 0, NULL );
670 LineTo( hDCDest, SYSMETRICS_CXSIZE - 1, SYSMETRICS_CYSIZE - 1);
672 SelectObject(hDCDest, hobjSrc );
673 SelectObject(hDCDest, hobjDest);
674 DeleteDC(hDCDest);
676 return hbCopy;
679 /**********************************************************************
680 * MDICascade
682 static LONG MDICascade(WND* clientWnd, MDICLIENTINFO *ci)
684 WND** ppWnd;
685 UINT total;
687 if (ci->hwndChildMaximized)
688 SendMessageA( clientWnd->hwndSelf, WM_MDIRESTORE,
689 (WPARAM)ci->hwndChildMaximized, 0);
691 if (ci->nActiveChildren == 0) return 0;
693 if ((ppWnd = WIN_BuildWinArray(clientWnd, BWA_SKIPHIDDEN | BWA_SKIPOWNED |
694 BWA_SKIPICONIC, &total)))
696 WND** heapPtr = ppWnd;
697 if( total )
699 INT delta = 0, n = 0;
700 POINT pos[2];
701 if( total < ci->nActiveChildren )
702 delta = SYSMETRICS_CYICONSPACING + SYSMETRICS_CYICON;
704 /* walk the list (backwards) and move windows */
705 while (*ppWnd) ppWnd++;
706 while (ppWnd != heapPtr)
708 ppWnd--;
709 TRACE(mdi, "move %04x to (%ld,%ld) size [%ld,%ld]\n",
710 (*ppWnd)->hwndSelf, pos[0].x, pos[0].y, pos[1].x, pos[1].y);
712 MDI_CalcDefaultChildPos(clientWnd, n++, pos, delta);
713 SetWindowPos( (*ppWnd)->hwndSelf, 0, pos[0].x, pos[0].y,
714 pos[1].x, pos[1].y,
715 SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER);
718 WIN_ReleaseWinArray(heapPtr);
721 if( total < ci->nActiveChildren )
722 ArrangeIconicWindows( clientWnd->hwndSelf );
723 return 0;
726 /**********************************************************************
727 * MDITile
729 static void MDITile( WND* wndClient, MDICLIENTINFO *ci, WPARAM wParam )
731 WND** ppWnd;
732 UINT total = 0;
734 if (ci->hwndChildMaximized)
735 SendMessageA( wndClient->hwndSelf, WM_MDIRESTORE,
736 (WPARAM)ci->hwndChildMaximized, 0);
738 if (ci->nActiveChildren == 0) return;
740 ppWnd = WIN_BuildWinArray(wndClient, BWA_SKIPHIDDEN | BWA_SKIPOWNED | BWA_SKIPICONIC |
741 ((wParam & MDITILE_SKIPDISABLED)? BWA_SKIPDISABLED : 0), &total );
743 TRACE(mdi,"%u windows to tile\n", total);
745 if( ppWnd )
747 WND** heapPtr = ppWnd;
749 if( total )
751 RECT rect;
752 int x, y, xsize, ysize;
753 int rows, columns, r, c, i;
755 rect = wndClient->rectClient;
756 rows = (int) sqrt((double)total);
757 columns = total / rows;
759 if( wParam & MDITILE_HORIZONTAL ) /* version >= 3.1 */
761 i = rows;
762 rows = columns; /* exchange r and c */
763 columns = i;
766 if( total != ci->nActiveChildren)
768 y = rect.bottom - 2 * SYSMETRICS_CYICONSPACING - SYSMETRICS_CYICON;
769 rect.bottom = ( y - SYSMETRICS_CYICON < rect.top )? rect.bottom: y;
772 ysize = rect.bottom / rows;
773 xsize = rect.right / columns;
775 for (x = i = 0, c = 1; c <= columns && *ppWnd; c++)
777 if (c == columns)
779 rows = total - i;
780 ysize = rect.bottom / rows;
783 y = 0;
784 for (r = 1; r <= rows && *ppWnd; r++, i++)
786 SetWindowPos((*ppWnd)->hwndSelf, 0, x, y, xsize, ysize,
787 SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER);
788 y += ysize;
789 ppWnd++;
791 x += xsize;
794 WIN_ReleaseWinArray(heapPtr);
797 if( total < ci->nActiveChildren ) ArrangeIconicWindows( wndClient->hwndSelf );
800 /* ----------------------- Frame window ---------------------------- */
803 /**********************************************************************
804 * MDI_AugmentFrameMenu
806 static BOOL MDI_AugmentFrameMenu( MDICLIENTINFO* ci, WND *frame,
807 HWND hChild )
809 WND* child = WIN_FindWndPtr(hChild);
810 HMENU hSysPopup = 0;
812 TRACE(mdi,"frame %p,child %04x\n",frame,hChild);
814 if( !frame->wIDmenu || !child->hSysMenu )
816 WIN_ReleaseWndPtr(child);
817 return 0;
819 WIN_ReleaseWndPtr(child);
821 /* create a copy of sysmenu popup and insert it into frame menu bar */
823 if (!(hSysPopup = LoadMenuIndirectA(SYSRES_GetResPtr(SYSRES_MENU_SYSMENU))))
824 return 0;
826 TRACE(mdi,"\tgot popup %04x in sysmenu %04x\n",
827 hSysPopup, child->hSysMenu);
829 AppendMenuA(frame->wIDmenu,MF_HELP | MF_BITMAP,
830 SC_MINIMIZE, (LPSTR)(DWORD)HBMMENU_MBAR_MINIMIZE ) ;
831 AppendMenuA(frame->wIDmenu,MF_HELP | MF_BITMAP,
832 SC_RESTORE, (LPSTR)(DWORD)HBMMENU_MBAR_RESTORE );
834 if( !InsertMenuA(frame->wIDmenu,0,MF_BYPOSITION | MF_BITMAP | MF_POPUP,
835 hSysPopup, (LPSTR)(DWORD)hBmpClose ))
837 TRACE(mdi,"not inserted\n");
838 DestroyMenu(hSysPopup);
839 return 0;
842 /* The close button is only present in Win 95 look */
843 if(TWEAK_WineLook > WIN31_LOOK)
845 AppendMenuA(frame->wIDmenu,MF_HELP | MF_BITMAP,
846 SC_CLOSE, (LPSTR)(DWORD)HBMMENU_MBAR_CLOSE );
849 EnableMenuItem(hSysPopup, SC_SIZE, MF_BYCOMMAND | MF_GRAYED);
850 EnableMenuItem(hSysPopup, SC_MOVE, MF_BYCOMMAND | MF_GRAYED);
851 EnableMenuItem(hSysPopup, SC_MAXIMIZE, MF_BYCOMMAND | MF_GRAYED);
853 /* redraw menu */
854 DrawMenuBar(frame->hwndSelf);
856 return 1;
859 /**********************************************************************
860 * MDI_RestoreFrameMenu
862 static BOOL MDI_RestoreFrameMenu( WND *frameWnd, HWND hChild )
864 INT nItems = GetMenuItemCount(frameWnd->wIDmenu) - 1;
865 UINT iId = GetMenuItemID(frameWnd->wIDmenu,nItems) ;
867 TRACE(mdi,"frameWnd %p,child %04x\n",frameWnd,hChild);
869 if(!(iId == SC_RESTORE || iId == SC_CLOSE) )
870 return 0;
872 /* app button */
873 RemoveMenu(frameWnd->wIDmenu,0,MF_BYPOSITION);
875 if(TWEAK_WineLook > WIN31_LOOK)
877 /* close */
878 DeleteMenu(frameWnd->wIDmenu,GetMenuItemCount(frameWnd->wIDmenu) - 1,MF_BYPOSITION);
880 /* restore */
881 DeleteMenu(frameWnd->wIDmenu,GetMenuItemCount(frameWnd->wIDmenu) - 1,MF_BYPOSITION);
882 /* minimize */
883 DeleteMenu(frameWnd->wIDmenu,GetMenuItemCount(frameWnd->wIDmenu) - 1,MF_BYPOSITION);
885 DrawMenuBar(frameWnd->hwndSelf);
887 return 1;
891 /**********************************************************************
892 * MDI_UpdateFrameText
894 * used when child window is maximized/restored
896 * Note: lpTitle can be NULL
898 static void MDI_UpdateFrameText( WND *frameWnd, HWND hClient,
899 BOOL repaint, LPCSTR lpTitle )
901 char lpBuffer[MDI_MAXTITLELENGTH+1];
902 WND* clientWnd = WIN_FindWndPtr(hClient);
903 MDICLIENTINFO *ci = (MDICLIENTINFO *) clientWnd->wExtra;
905 TRACE(mdi, "repaint %i, frameText %s\n", repaint, (lpTitle)?lpTitle:"NULL");
907 if (!clientWnd)
908 return;
910 if (!ci)
912 WIN_ReleaseWndPtr(clientWnd);
913 return;
916 /* store new "default" title if lpTitle is not NULL */
917 if (lpTitle)
919 if (ci->frameTitle) HeapFree( SystemHeap, 0, ci->frameTitle );
920 ci->frameTitle = HEAP_strdupA( SystemHeap, 0, lpTitle );
923 if (ci->frameTitle)
925 WND* childWnd = WIN_FindWndPtr( ci->hwndChildMaximized );
927 if( childWnd && childWnd->text )
929 /* combine frame title and child title if possible */
931 LPCSTR lpBracket = " - [";
932 int i_frame_text_length = strlen(ci->frameTitle);
933 int i_child_text_length = strlen(childWnd->text);
935 lstrcpynA( lpBuffer, ci->frameTitle, MDI_MAXTITLELENGTH);
937 if( i_frame_text_length + 6 < MDI_MAXTITLELENGTH )
939 strcat( lpBuffer, lpBracket );
941 if( i_frame_text_length + i_child_text_length + 6 < MDI_MAXTITLELENGTH )
943 strcat( lpBuffer, childWnd->text );
944 strcat( lpBuffer, "]" );
946 else
948 lstrcpynA( lpBuffer + i_frame_text_length + 4,
949 childWnd->text, MDI_MAXTITLELENGTH - i_frame_text_length - 5 );
950 strcat( lpBuffer, "]" );
954 else
956 strncpy(lpBuffer, ci->frameTitle, MDI_MAXTITLELENGTH );
957 lpBuffer[MDI_MAXTITLELENGTH]='\0';
959 WIN_ReleaseWndPtr(childWnd);
962 else
963 lpBuffer[0] = '\0';
965 DEFWND_SetText( frameWnd, lpBuffer );
966 if( repaint == MDI_REPAINTFRAME)
967 SetWindowPos( frameWnd->hwndSelf, 0,0,0,0,0, SWP_FRAMECHANGED |
968 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER );
970 WIN_ReleaseWndPtr(clientWnd);
975 /* ----------------------------- Interface ---------------------------- */
978 /**********************************************************************
979 * MDIClientWndProc
981 * This function handles all MDI requests.
983 LRESULT WINAPI MDIClientWndProc( HWND hwnd, UINT message, WPARAM wParam,
984 LPARAM lParam )
986 LPCREATESTRUCTA cs;
987 MDICLIENTINFO *ci;
988 RECT rect;
989 WND *w = WIN_FindWndPtr(hwnd);
990 WND *frameWnd = WIN_LockWndPtr(w->parent);
991 INT nItems;
992 LRESULT retvalue;
994 ci = (MDICLIENTINFO *) w->wExtra;
996 switch (message)
998 case WM_CREATE:
1000 cs = (LPCREATESTRUCTA)lParam;
1002 /* Translation layer doesn't know what's in the cs->lpCreateParams
1003 * so we have to keep track of what environment we're in. */
1005 if( w->flags & WIN_ISWIN32 )
1007 #define ccs ((LPCLIENTCREATESTRUCT)cs->lpCreateParams)
1008 ci->hWindowMenu = ccs->hWindowMenu;
1009 ci->idFirstChild = ccs->idFirstChild;
1010 #undef ccs
1012 else
1014 LPCLIENTCREATESTRUCT16 ccs = (LPCLIENTCREATESTRUCT16)
1015 PTR_SEG_TO_LIN(cs->lpCreateParams);
1016 ci->hWindowMenu = ccs->hWindowMenu;
1017 ci->idFirstChild = ccs->idFirstChild;
1020 ci->hwndChildMaximized = 0;
1021 ci->nActiveChildren = 0;
1022 ci->nTotalCreated = 0;
1023 ci->frameTitle = NULL;
1024 ci->mdiFlags = 0;
1025 ci->self = hwnd;
1026 w->dwStyle |= WS_CLIPCHILDREN;
1028 if (!hBmpClose)
1030 hBmpClose = CreateMDIMenuBitmap();
1031 hBmpRestore = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_RESTORE) );
1033 MDI_UpdateFrameText(frameWnd, hwnd, MDI_NOFRAMEREPAINT,frameWnd->text);
1035 AppendMenuA( ci->hWindowMenu, MF_SEPARATOR, 0, NULL );
1037 GetClientRect(frameWnd->hwndSelf, &rect);
1038 NC_HandleNCCalcSize( w, &rect );
1039 w->rectClient = rect;
1041 TRACE(mdi,"Client created - hwnd = %04x, idFirst = %u\n",
1042 hwnd, ci->idFirstChild );
1044 retvalue = 0;
1045 goto END;
1047 case WM_DESTROY:
1048 if( ci->hwndChildMaximized ) MDI_RestoreFrameMenu(w, frameWnd->hwndSelf);
1049 if((nItems = GetMenuItemCount(ci->hWindowMenu)) > 0)
1051 ci->idFirstChild = nItems - 1;
1052 ci->nActiveChildren++; /* to delete a separator */
1053 while( ci->nActiveChildren-- )
1054 DeleteMenu(ci->hWindowMenu,MF_BYPOSITION,ci->idFirstChild--);
1056 retvalue = 0;
1057 goto END;
1059 case WM_MDIACTIVATE:
1060 if( ci->hwndActiveChild != (HWND)wParam )
1061 SetWindowPos((HWND)wParam, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE);
1062 retvalue = 0;
1063 goto END;
1065 case WM_MDICASCADE:
1066 retvalue = MDICascade(w, ci);
1067 goto END;
1069 case WM_MDICREATE:
1070 if (lParam) retvalue = MDICreateChild( w, ci, hwnd,
1071 (MDICREATESTRUCTA*)lParam );
1072 else retvalue = 0;
1073 goto END;
1075 case WM_MDIDESTROY:
1076 retvalue = MDIDestroyChild( w, ci, hwnd, (HWND)wParam, TRUE );
1077 goto END;
1079 case WM_MDIGETACTIVE:
1080 if (lParam) *(BOOL *)lParam = (ci->hwndChildMaximized > 0);
1081 retvalue = ci->hwndActiveChild;
1082 goto END;
1084 case WM_MDIICONARRANGE:
1085 ci->mdiFlags |= MDIF_NEEDUPDATE;
1086 ArrangeIconicWindows(hwnd);
1087 ci->sbRecalc = SB_BOTH+1;
1088 SendMessageA(hwnd, WM_MDICALCCHILDSCROLL, 0, 0L);
1089 retvalue = 0;
1090 goto END;
1092 case WM_MDIMAXIMIZE:
1093 ShowWindow( (HWND)wParam, SW_MAXIMIZE );
1094 retvalue = 0;
1095 goto END;
1097 case WM_MDINEXT: /* lParam != 0 means previous window */
1098 MDI_SwitchActiveChild(hwnd, (HWND)wParam, (lParam)? FALSE : TRUE );
1099 break;
1101 case WM_MDIRESTORE:
1102 SendMessageA( (HWND)wParam, WM_SYSCOMMAND, SC_RESTORE, 0);
1103 retvalue = 0;
1104 goto END;
1106 case WM_MDISETMENU:
1107 retvalue = MDISetMenu( hwnd, (HMENU)wParam, (HMENU)lParam );
1108 goto END;
1109 case WM_MDIREFRESHMENU:
1110 retvalue = MDIRefreshMenu( hwnd, (HMENU)wParam, (HMENU)lParam );
1111 goto END;
1113 case WM_MDITILE:
1114 ci->mdiFlags |= MDIF_NEEDUPDATE;
1115 ShowScrollBar(hwnd,SB_BOTH,FALSE);
1116 MDITile(w, ci, wParam);
1117 ci->mdiFlags &= ~MDIF_NEEDUPDATE;
1118 retvalue = 0;
1119 goto END;
1121 case WM_VSCROLL:
1122 case WM_HSCROLL:
1123 ci->mdiFlags |= MDIF_NEEDUPDATE;
1124 ScrollChildren(hwnd, message, wParam, lParam);
1125 ci->mdiFlags &= ~MDIF_NEEDUPDATE;
1126 retvalue = 0;
1127 goto END;
1129 case WM_SETFOCUS:
1130 if( ci->hwndActiveChild )
1132 w = WIN_FindWndPtr( ci->hwndActiveChild );
1133 if( !(w->dwStyle & WS_MINIMIZE) )
1134 SetFocus( ci->hwndActiveChild );
1136 retvalue = 0;
1137 goto END;
1139 case WM_NCACTIVATE:
1140 if( ci->hwndActiveChild )
1141 SendMessageA(ci->hwndActiveChild, message, wParam, lParam);
1142 break;
1144 case WM_PARENTNOTIFY:
1145 if (LOWORD(wParam) == WM_LBUTTONDOWN)
1147 POINT16 pt = MAKEPOINT16(lParam);
1148 HWND16 child = ChildWindowFromPoint16(hwnd, pt);
1150 TRACE(mdi,"notification from %04x (%i,%i)\n",child,pt.x,pt.y);
1152 if( child && child != hwnd && child != ci->hwndActiveChild )
1153 SetWindowPos(child, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE );
1155 retvalue = 0;
1156 goto END;
1158 case WM_SIZE:
1159 if( IsWindow(ci->hwndChildMaximized) )
1161 WND* child = WIN_FindWndPtr(ci->hwndChildMaximized);
1162 RECT rect;
1164 rect.left = 0;
1165 rect.top = 0;
1166 rect.right = LOWORD(lParam);
1167 rect.bottom = HIWORD(lParam);
1169 AdjustWindowRectEx(&rect, child->dwStyle, 0, child->dwExStyle);
1170 MoveWindow(ci->hwndChildMaximized, rect.left, rect.top,
1171 rect.right - rect.left, rect.bottom - rect.top, 1);
1172 WIN_ReleaseWndPtr(child);
1174 else
1175 MDI_PostUpdate(hwnd, ci, SB_BOTH+1);
1177 break;
1179 case WM_MDICALCCHILDSCROLL:
1180 if( (ci->mdiFlags & MDIF_NEEDUPDATE) && ci->sbRecalc )
1182 CalcChildScroll16(hwnd, ci->sbRecalc-1);
1183 ci->sbRecalc = 0;
1184 ci->mdiFlags &= ~MDIF_NEEDUPDATE;
1186 retvalue = 0;
1187 goto END;
1190 retvalue = DefWindowProcA( hwnd, message, wParam, lParam );
1191 END:
1192 WIN_ReleaseWndPtr(w);
1193 WIN_ReleaseWndPtr(frameWnd);
1194 return retvalue;
1198 /***********************************************************************
1199 * DefFrameProc16 (USER.445)
1201 LRESULT WINAPI DefFrameProc16( HWND16 hwnd, HWND16 hwndMDIClient,
1202 UINT16 message, WPARAM16 wParam, LPARAM lParam )
1204 HWND16 childHwnd;
1205 MDICLIENTINFO* ci;
1206 WND* wndPtr;
1208 if (hwndMDIClient)
1210 switch (message)
1212 case WM_COMMAND:
1213 wndPtr = WIN_FindWndPtr(hwndMDIClient);
1215 if (!wndPtr) {
1216 ERR(mdi,"null wndPtr for mdi window hwndMDIClient=%04x\n",
1217 hwndMDIClient);
1218 return 0;
1221 ci = (MDICLIENTINFO*)wndPtr->wExtra;
1223 /* check for possible syscommands for maximized MDI child */
1224 WIN_ReleaseWndPtr(wndPtr);
1226 if( ci && (
1227 wParam < ci->idFirstChild ||
1228 wParam >= ci->idFirstChild + ci->nActiveChildren
1230 if( (wParam - 0xF000) & 0xF00F ) break;
1231 switch( wParam )
1233 case SC_SIZE:
1234 case SC_MOVE:
1235 case SC_MINIMIZE:
1236 case SC_MAXIMIZE:
1237 case SC_NEXTWINDOW:
1238 case SC_PREVWINDOW:
1239 case SC_CLOSE:
1240 case SC_RESTORE:
1241 if( ci->hwndChildMaximized )
1242 return SendMessage16( ci->hwndChildMaximized, WM_SYSCOMMAND,
1243 wParam, lParam);
1246 else
1248 wndPtr = WIN_FindWndPtr(hwndMDIClient);
1249 childHwnd = MDI_GetChildByID(wndPtr,wParam );
1250 WIN_ReleaseWndPtr(wndPtr);
1252 if( childHwnd )
1253 SendMessage16(hwndMDIClient, WM_MDIACTIVATE,
1254 (WPARAM16)childHwnd , 0L);
1256 break;
1258 case WM_NCACTIVATE:
1259 SendMessage16(hwndMDIClient, message, wParam, lParam);
1260 break;
1262 case WM_SETTEXT:
1263 wndPtr = WIN_FindWndPtr(hwnd);
1264 MDI_UpdateFrameText(wndPtr, hwndMDIClient,
1265 MDI_REPAINTFRAME,
1266 (LPCSTR)PTR_SEG_TO_LIN(lParam));
1267 WIN_ReleaseWndPtr(wndPtr);
1268 return 0;
1270 case WM_SETFOCUS:
1271 SetFocus(hwndMDIClient);
1272 break;
1274 case WM_SIZE:
1275 MoveWindow16(hwndMDIClient, 0, 0,
1276 LOWORD(lParam), HIWORD(lParam), TRUE);
1277 break;
1279 case WM_NEXTMENU:
1281 wndPtr = WIN_FindWndPtr(hwndMDIClient);
1282 ci = (MDICLIENTINFO*)wndPtr->wExtra;
1284 if( !(wndPtr->parent->dwStyle & WS_MINIMIZE)
1285 && ci->hwndActiveChild && !ci->hwndChildMaximized )
1287 /* control menu is between the frame system menu and
1288 * the first entry of menu bar */
1290 if( (wParam == VK_LEFT &&
1291 wndPtr->parent->wIDmenu == LOWORD(lParam)) ||
1292 (wParam == VK_RIGHT &&
1293 GetSubMenu16(wndPtr->parent->hSysMenu, 0) == LOWORD(lParam)) )
1295 LRESULT retvalue;
1296 WIN_ReleaseWndPtr(wndPtr);
1297 wndPtr = WIN_FindWndPtr(ci->hwndActiveChild);
1298 retvalue = MAKELONG( GetSubMenu16(wndPtr->hSysMenu, 0),
1299 ci->hwndActiveChild);
1300 WIN_ReleaseWndPtr(wndPtr);
1301 return retvalue;
1304 WIN_ReleaseWndPtr(wndPtr);
1305 break;
1309 return DefWindowProc16(hwnd, message, wParam, lParam);
1313 /***********************************************************************
1314 * DefFrameProc32A (USER32.122)
1316 LRESULT WINAPI DefFrameProcA( HWND hwnd, HWND hwndMDIClient,
1317 UINT message, WPARAM wParam, LPARAM lParam)
1319 if (hwndMDIClient)
1321 switch (message)
1323 case WM_COMMAND:
1324 return DefFrameProc16( hwnd, hwndMDIClient, message,
1325 (WPARAM16)wParam,
1326 MAKELPARAM( (HWND16)lParam, HIWORD(wParam) ) );
1328 case WM_NCACTIVATE:
1329 SendMessageA(hwndMDIClient, message, wParam, lParam);
1330 break;
1332 case WM_SETTEXT: {
1333 LRESULT ret;
1334 LPSTR segstr = SEGPTR_STRDUP((LPSTR)lParam);
1336 ret = DefFrameProc16(hwnd, hwndMDIClient, message,
1337 wParam, (LPARAM)SEGPTR_GET(segstr) );
1338 SEGPTR_FREE(segstr);
1339 return ret;
1342 case WM_NEXTMENU:
1343 case WM_SETFOCUS:
1344 case WM_SIZE:
1345 return DefFrameProc16( hwnd, hwndMDIClient, message,
1346 wParam, lParam );
1350 return DefWindowProcA(hwnd, message, wParam, lParam);
1354 /***********************************************************************
1355 * DefFrameProc32W (USER32.123)
1357 LRESULT WINAPI DefFrameProcW( HWND hwnd, HWND hwndMDIClient,
1358 UINT message, WPARAM wParam, LPARAM lParam)
1360 if (hwndMDIClient)
1362 switch (message)
1364 case WM_COMMAND:
1365 return DefFrameProc16( hwnd, hwndMDIClient, message,
1366 (WPARAM16)wParam,
1367 MAKELPARAM( (HWND16)lParam, HIWORD(wParam) ) );
1369 case WM_NCACTIVATE:
1370 SendMessageW(hwndMDIClient, message, wParam, lParam);
1371 break;
1373 case WM_SETTEXT:
1375 LPSTR txt = HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)lParam);
1376 LRESULT ret = DefFrameProcA( hwnd, hwndMDIClient, message,
1377 wParam, (DWORD)txt );
1378 HeapFree(GetProcessHeap(),0,txt);
1379 return ret;
1381 case WM_NEXTMENU:
1382 case WM_SETFOCUS:
1383 case WM_SIZE:
1384 return DefFrameProcA( hwnd, hwndMDIClient, message,
1385 wParam, lParam );
1389 return DefWindowProcW( hwnd, message, wParam, lParam );
1393 /***********************************************************************
1394 * DefMDIChildProc16 (USER.447)
1396 LRESULT WINAPI DefMDIChildProc16( HWND16 hwnd, UINT16 message,
1397 WPARAM16 wParam, LPARAM lParam )
1399 MDICLIENTINFO *ci;
1400 WND *clientWnd,*tmpWnd = 0;
1401 LRESULT retvalue;
1403 clientWnd = WIN_FindWndPtr(GetParent16(hwnd));
1404 ci = (MDICLIENTINFO *) clientWnd->wExtra;
1406 switch (message)
1408 case WM_SETTEXT:
1409 DefWindowProc16(hwnd, message, wParam, lParam);
1410 MDI_MenuModifyItem(clientWnd,hwnd);
1411 if( ci->hwndChildMaximized == hwnd )
1412 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1413 MDI_REPAINTFRAME, NULL );
1414 retvalue = 0;
1415 goto END;
1417 case WM_CLOSE:
1418 SendMessage16(ci->self,WM_MDIDESTROY,(WPARAM16)hwnd,0L);
1419 retvalue = 0;
1420 goto END;
1422 case WM_SETFOCUS:
1423 if( ci->hwndActiveChild != hwnd )
1424 MDI_ChildActivate(clientWnd, hwnd);
1425 break;
1427 case WM_CHILDACTIVATE:
1428 MDI_ChildActivate(clientWnd, hwnd);
1429 retvalue = 0;
1430 goto END;
1432 case WM_NCPAINT:
1433 TRACE(mdi,"WM_NCPAINT for %04x, active %04x\n",
1434 hwnd, ci->hwndActiveChild );
1435 break;
1437 case WM_SYSCOMMAND:
1438 switch( wParam )
1440 case SC_MOVE:
1441 if( ci->hwndChildMaximized == hwnd)
1443 retvalue = 0;
1444 goto END;
1446 break;
1447 case SC_RESTORE:
1448 case SC_MINIMIZE:
1449 tmpWnd = WIN_FindWndPtr(hwnd);
1450 tmpWnd->dwStyle |= WS_SYSMENU;
1451 WIN_ReleaseWndPtr(tmpWnd);
1452 break;
1453 case SC_MAXIMIZE:
1454 if( ci->hwndChildMaximized == hwnd)
1456 retvalue = SendMessage16( clientWnd->parent->hwndSelf,
1457 message, wParam, lParam);
1458 goto END;
1460 tmpWnd = WIN_FindWndPtr(hwnd);
1461 tmpWnd->dwStyle &= ~WS_SYSMENU;
1462 WIN_ReleaseWndPtr(tmpWnd);
1463 break;
1464 case SC_NEXTWINDOW:
1465 SendMessage16( ci->self, WM_MDINEXT, 0, 0);
1466 retvalue = 0;
1467 goto END;
1468 case SC_PREVWINDOW:
1469 SendMessage16( ci->self, WM_MDINEXT, 0, 1);
1470 retvalue = 0;
1471 goto END;
1473 break;
1475 case WM_GETMINMAXINFO:
1476 MDI_ChildGetMinMaxInfo(clientWnd, hwnd, (MINMAXINFO16*) PTR_SEG_TO_LIN(lParam));
1477 retvalue = 0;
1478 goto END;
1480 case WM_SETVISIBLE:
1481 if( ci->hwndChildMaximized) ci->mdiFlags &= ~MDIF_NEEDUPDATE;
1482 else
1483 MDI_PostUpdate(clientWnd->hwndSelf, ci, SB_BOTH+1);
1484 break;
1486 case WM_SIZE:
1487 /* do not change */
1489 if( ci->hwndActiveChild == hwnd && wParam != SIZE_MAXIMIZED )
1491 ci->hwndChildMaximized = 0;
1493 MDI_RestoreFrameMenu( clientWnd->parent, hwnd);
1494 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1495 MDI_REPAINTFRAME, NULL );
1498 if( wParam == SIZE_MAXIMIZED )
1500 HWND16 hMaxChild = ci->hwndChildMaximized;
1502 if( hMaxChild == hwnd ) break;
1504 if( hMaxChild)
1506 SendMessage16( hMaxChild, WM_SETREDRAW, FALSE, 0L );
1508 MDI_RestoreFrameMenu( clientWnd->parent, hMaxChild);
1509 ShowWindow16( hMaxChild, SW_SHOWNOACTIVATE);
1511 SendMessage16( hMaxChild, WM_SETREDRAW, TRUE, 0L );
1514 TRACE(mdi,"maximizing child %04x\n", hwnd );
1516 ci->hwndChildMaximized = hwnd; /* !!! */
1517 ci->hwndActiveChild = hwnd;
1519 MDI_AugmentFrameMenu( ci, clientWnd->parent, hwnd);
1520 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1521 MDI_REPAINTFRAME, NULL );
1524 if( wParam == SIZE_MINIMIZED )
1526 HWND16 switchTo = MDI_GetWindow(clientWnd, hwnd, TRUE, WS_MINIMIZE);
1528 if( switchTo )
1529 SendMessage16( switchTo, WM_CHILDACTIVATE, 0, 0L);
1532 MDI_PostUpdate(clientWnd->hwndSelf, ci, SB_BOTH+1);
1533 break;
1535 case WM_MENUCHAR:
1537 /* MDI children don't have menu bars */
1538 PostMessage16( clientWnd->parent->hwndSelf, WM_SYSCOMMAND,
1539 (WPARAM16)SC_KEYMENU, (LPARAM)wParam);
1540 retvalue = 0x00010000L;
1541 goto END;
1543 case WM_NEXTMENU:
1545 if( wParam == VK_LEFT ) /* switch to frame system menu */
1547 retvalue = MAKELONG( GetSubMenu16(clientWnd->parent->hSysMenu, 0),
1548 clientWnd->parent->hwndSelf );
1549 goto END;
1551 if( wParam == VK_RIGHT ) /* to frame menu bar */
1553 retvalue = MAKELONG( clientWnd->parent->wIDmenu,
1554 clientWnd->parent->hwndSelf );
1555 goto END;
1558 break;
1560 case WM_SYSCHAR:
1561 if (wParam == '-')
1563 SendMessage16(hwnd,WM_SYSCOMMAND,
1564 (WPARAM16)SC_KEYMENU, (LPARAM)(DWORD)VK_SPACE);
1565 retvalue = 0;
1566 goto END;
1570 retvalue = DefWindowProc16(hwnd, message, wParam, lParam);
1571 END:
1572 WIN_ReleaseWndPtr(clientWnd);
1573 return retvalue;
1577 /***********************************************************************
1578 * DefMDIChildProc32A (USER32.124)
1580 LRESULT WINAPI DefMDIChildProcA( HWND hwnd, UINT message,
1581 WPARAM wParam, LPARAM lParam )
1583 MDICLIENTINFO *ci;
1584 WND *clientWnd,*tmpWnd;
1585 LRESULT retvalue;
1587 tmpWnd = WIN_FindWndPtr(hwnd);
1588 clientWnd = WIN_FindWndPtr(tmpWnd->parent->hwndSelf);
1589 ci = (MDICLIENTINFO *) clientWnd->wExtra;
1590 WIN_ReleaseWndPtr(tmpWnd);
1592 switch (message)
1594 case WM_SETTEXT:
1595 DefWindowProcA(hwnd, message, wParam, lParam);
1596 MDI_MenuModifyItem(clientWnd,hwnd);
1597 if( ci->hwndChildMaximized == hwnd )
1598 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1599 MDI_REPAINTFRAME, NULL );
1600 retvalue = 0;
1601 goto END;
1603 case WM_GETMINMAXINFO:
1605 MINMAXINFO16 mmi;
1606 STRUCT32_MINMAXINFO32to16( (MINMAXINFO *)lParam, &mmi );
1607 MDI_ChildGetMinMaxInfo( clientWnd, hwnd, &mmi );
1608 STRUCT32_MINMAXINFO16to32( &mmi, (MINMAXINFO *)lParam );
1610 retvalue = 0;
1611 goto END;
1613 case WM_MENUCHAR:
1615 /* MDI children don't have menu bars */
1616 PostMessage16( clientWnd->parent->hwndSelf, WM_SYSCOMMAND,
1617 (WPARAM16)SC_KEYMENU, (LPARAM)LOWORD(wParam) );
1618 retvalue = 0x00010000L;
1619 goto END;
1621 case WM_CLOSE:
1622 case WM_SETFOCUS:
1623 case WM_CHILDACTIVATE:
1624 case WM_NCPAINT:
1625 case WM_SYSCOMMAND:
1626 case WM_SETVISIBLE:
1627 case WM_SIZE:
1628 case WM_NEXTMENU:
1629 retvalue = DefMDIChildProc16( hwnd, message, (WPARAM16)wParam, lParam );
1630 goto END;
1632 case WM_SYSCHAR:
1633 if (wParam == '-')
1635 SendMessageA(hwnd,WM_SYSCOMMAND,
1636 (WPARAM)SC_KEYMENU, (LPARAM)(DWORD)VK_SPACE);
1637 retvalue = 0;
1638 goto END;
1641 retvalue = DefWindowProcA(hwnd, message, wParam, lParam);
1642 END:
1643 WIN_ReleaseWndPtr(clientWnd);
1644 return retvalue;
1648 /***********************************************************************
1649 * DefMDIChildProc32W (USER32.125)
1651 LRESULT WINAPI DefMDIChildProcW( HWND hwnd, UINT message,
1652 WPARAM wParam, LPARAM lParam )
1654 MDICLIENTINFO *ci;
1655 WND *clientWnd;
1656 LRESULT retvalue;
1658 clientWnd = WIN_FindWndPtr(GetParent16(hwnd));
1659 ci = (MDICLIENTINFO *) clientWnd->wExtra;
1661 switch (message)
1663 case WM_SETTEXT:
1664 DefWindowProcW(hwnd, message, wParam, lParam);
1665 MDI_MenuModifyItem(clientWnd,hwnd);
1666 if( ci->hwndChildMaximized == hwnd )
1667 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1668 MDI_REPAINTFRAME, NULL );
1669 retvalue = 0;
1670 goto END;
1672 case WM_GETMINMAXINFO:
1673 case WM_MENUCHAR:
1674 case WM_CLOSE:
1675 case WM_SETFOCUS:
1676 case WM_CHILDACTIVATE:
1677 case WM_NCPAINT:
1678 case WM_SYSCOMMAND:
1679 case WM_SETVISIBLE:
1680 case WM_SIZE:
1681 case WM_NEXTMENU:
1682 retvalue = DefMDIChildProcA( hwnd, message, (WPARAM16)wParam, lParam );
1683 goto END;
1685 case WM_SYSCHAR:
1686 if (wParam == '-')
1688 SendMessageW(hwnd,WM_SYSCOMMAND,
1689 (WPARAM)SC_KEYMENU, (LPARAM)(DWORD)VK_SPACE);
1690 retvalue = 0;
1691 goto END;
1694 retvalue = DefWindowProcW(hwnd, message, wParam, lParam);
1695 END:
1696 WIN_ReleaseWndPtr(clientWnd);
1697 return retvalue;
1702 /**********************************************************************
1703 * CreateMDIWindowA [USER32.79] Creates a MDI child in new thread
1704 * FIXME: its in the same thread now
1706 * RETURNS
1707 * Success: Handle to created window
1708 * Failure: NULL
1710 HWND WINAPI CreateMDIWindowA(
1711 LPCSTR lpClassName, /* [in] Pointer to registered child class name */
1712 LPCSTR lpWindowName, /* [in] Pointer to window name */
1713 DWORD dwStyle, /* [in] Window style */
1714 INT X, /* [in] Horizontal position of window */
1715 INT Y, /* [in] Vertical position of window */
1716 INT nWidth, /* [in] Width of window */
1717 INT nHeight, /* [in] Height of window */
1718 HWND hWndParent, /* [in] Handle to parent window */
1719 HINSTANCE hInstance, /* [in] Handle to application instance */
1720 LPARAM lParam) /* [in] Application-defined value */
1722 WARN(mdi,"is only single threaded!\n");
1723 return MDI_CreateMDIWindowA(lpClassName, lpWindowName, dwStyle, X, Y,
1724 nWidth, nHeight, hWndParent, hInstance, lParam);
1727 /**********************************************************************
1728 * MDI_CreateMDIWindowA
1729 * single threaded version of CreateMDIWindowA
1730 * called by CreateWindowEx32A
1732 HWND MDI_CreateMDIWindowA(
1733 LPCSTR lpClassName,
1734 LPCSTR lpWindowName,
1735 DWORD dwStyle,
1736 INT X,
1737 INT Y,
1738 INT nWidth,
1739 INT nHeight,
1740 HWND hWndParent,
1741 HINSTANCE hInstance,
1742 LPARAM lParam)
1744 MDICLIENTINFO* pCi;
1745 MDICREATESTRUCTA cs;
1746 WND *pWnd=WIN_FindWndPtr(hWndParent);
1747 HWND retvalue;
1749 TRACE(mdi, "(%s,%s,%ld,%d,%d,%d,%d,%x,%d,%ld)\n",
1750 debugstr_a(lpClassName),debugstr_a(lpWindowName),dwStyle,X,Y,
1751 nWidth,nHeight,hWndParent,hInstance,lParam);
1753 if(!pWnd){
1754 ERR(mdi," bad hwnd for MDI-client: %d\n",hWndParent);
1755 return 0;
1757 cs.szClass=lpClassName;
1758 cs.szTitle=lpWindowName;
1759 cs.hOwner=hInstance;
1760 cs.x=X;
1761 cs.y=Y;
1762 cs.cx=nWidth;
1763 cs.cy=nHeight;
1764 cs.style=dwStyle;
1765 cs.lParam=lParam;
1767 pCi=(MDICLIENTINFO *)pWnd->wExtra;
1769 retvalue = MDICreateChild(pWnd,pCi,hWndParent,&cs);
1770 WIN_ReleaseWndPtr(pWnd);
1771 return retvalue;
1774 /***************************************
1775 * CreateMDIWindow32W [USER32.80] Creates a MDI child in new thread
1777 * RETURNS
1778 * Success: Handle to created window
1779 * Failure: NULL
1781 HWND WINAPI CreateMDIWindowW(
1782 LPCWSTR lpClassName, /* [in] Pointer to registered child class name */
1783 LPCWSTR lpWindowName, /* [in] Pointer to window name */
1784 DWORD dwStyle, /* [in] Window style */
1785 INT X, /* [in] Horizontal position of window */
1786 INT Y, /* [in] Vertical position of window */
1787 INT nWidth, /* [in] Width of window */
1788 INT nHeight, /* [in] Height of window */
1789 HWND hWndParent, /* [in] Handle to parent window */
1790 HINSTANCE hInstance, /* [in] Handle to application instance */
1791 LPARAM lParam) /* [in] Application-defined value */
1793 FIXME(mdi, "(%s,%s,%ld,%d,%d,%d,%d,%x,%d,%ld): stub\n",
1794 debugstr_w(lpClassName),debugstr_w(lpWindowName),dwStyle,X,Y,
1795 nWidth,nHeight,hWndParent,hInstance,lParam);
1796 return (HWND)NULL;
1800 /******************************************************************************
1801 * CreateMDIWindow32W [USER32.80] Creates a MDI child window
1802 * single threaded version of CreateMDIWindow
1803 * called by CreateWindowEx32W().
1805 HWND MDI_CreateMDIWindowW(
1806 LPCWSTR lpClassName, /* [in] Pointer to registered child class name */
1807 LPCWSTR lpWindowName, /* [in] Pointer to window name */
1808 DWORD dwStyle, /* [in] Window style */
1809 INT X, /* [in] Horizontal position of window */
1810 INT Y, /* [in] Vertical position of window */
1811 INT nWidth, /* [in] Width of window */
1812 INT nHeight, /* [in] Height of window */
1813 HWND hWndParent, /* [in] Handle to parent window */
1814 HINSTANCE hInstance, /* [in] Handle to application instance */
1815 LPARAM lParam) /* [in] Application-defined value */
1817 FIXME(mdi, "(%s,%s,%ld,%d,%d,%d,%d,%x,%d,%ld): stub\n",
1818 debugstr_w(lpClassName),debugstr_w(lpWindowName),dwStyle,X,Y,
1819 nWidth,nHeight,hWndParent,hInstance,lParam);
1820 return (HWND)NULL;
1824 /**********************************************************************
1825 * TranslateMDISysAccel32 (USER32.555)
1827 BOOL WINAPI TranslateMDISysAccel( HWND hwndClient, LPMSG msg )
1829 MSG16 msg16;
1831 STRUCT32_MSG32to16(msg,&msg16);
1832 /* MDICLIENTINFO is still the same for win32 and win16 ... */
1833 return TranslateMDISysAccel16(hwndClient,&msg16);
1837 /**********************************************************************
1838 * TranslateMDISysAccel16 (USER.451)
1840 BOOL16 WINAPI TranslateMDISysAccel16( HWND16 hwndClient, LPMSG16 msg )
1842 WND* clientWnd = WIN_FindWndPtr( hwndClient);
1844 if( clientWnd && (msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN))
1846 MDICLIENTINFO *ci = NULL;
1847 WND* wnd;
1849 ci = (MDICLIENTINFO*) clientWnd->wExtra;
1850 WIN_ReleaseWndPtr(clientWnd);
1851 wnd = WIN_FindWndPtr(ci->hwndActiveChild);
1852 if( wnd && !(wnd->dwStyle & WS_DISABLED) )
1854 WPARAM16 wParam = 0;
1856 WIN_ReleaseWndPtr(wnd);
1857 /* translate if the Ctrl key is down and Alt not. */
1859 if( (GetKeyState(VK_CONTROL) & 0x8000) &&
1860 !(GetKeyState(VK_MENU) & 0x8000))
1862 switch( msg->wParam )
1864 case VK_F6:
1865 case VK_TAB:
1866 wParam = ( GetKeyState(VK_SHIFT) & 0x8000 )
1867 ? SC_NEXTWINDOW : SC_PREVWINDOW;
1868 break;
1869 case VK_F4:
1870 case VK_RBUTTON:
1871 wParam = SC_CLOSE;
1872 break;
1873 default:
1874 return 0;
1876 TRACE(mdi,"wParam = %04x\n", wParam);
1877 SendMessage16( ci->hwndActiveChild, WM_SYSCOMMAND,
1878 wParam, (LPARAM)msg->wParam);
1879 return 1;
1882 WIN_ReleaseWndPtr(wnd);
1884 WIN_ReleaseWndPtr(clientWnd);
1885 return 0; /* failure */
1889 /***********************************************************************
1890 * CalcChildScroll (USER.462)
1892 void WINAPI CalcChildScroll16( HWND16 hwnd, WORD scroll )
1894 SCROLLINFO info;
1895 RECT childRect, clientRect;
1896 INT vmin, vmax, hmin, hmax, vpos, hpos;
1897 WND *pWnd, *Wnd;
1899 if (!(pWnd = WIN_FindWndPtr( hwnd ))) return;
1900 Wnd = WIN_FindWndPtr(hwnd);
1901 GetClientRect( hwnd, &clientRect );
1902 SetRectEmpty( &childRect );
1904 for ( WIN_UpdateWndPtr(&pWnd,pWnd->child); pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1906 if( pWnd->dwStyle & WS_MAXIMIZE )
1908 ShowScrollBar(hwnd, SB_BOTH, FALSE);
1909 WIN_ReleaseWndPtr(pWnd);
1910 WIN_ReleaseWndPtr(Wnd);
1911 return;
1913 UnionRect( &childRect, &pWnd->rectWindow, &childRect );
1915 WIN_ReleaseWndPtr(pWnd);
1916 UnionRect( &childRect, &clientRect, &childRect );
1918 hmin = childRect.left; hmax = childRect.right - clientRect.right;
1919 hpos = clientRect.left - childRect.left;
1920 vmin = childRect.top; vmax = childRect.bottom - clientRect.bottom;
1921 vpos = clientRect.top - childRect.top;
1923 switch( scroll )
1925 case SB_HORZ:
1926 vpos = hpos; vmin = hmin; vmax = hmax;
1927 case SB_VERT:
1928 info.cbSize = sizeof(info);
1929 info.nMax = vmax; info.nMin = vmin; info.nPos = vpos;
1930 info.fMask = SIF_POS | SIF_RANGE;
1931 SetScrollInfo(hwnd, scroll, &info, TRUE);
1932 break;
1933 case SB_BOTH:
1934 SCROLL_SetNCSbState( Wnd, vmin, vmax, vpos,
1935 hmin, hmax, hpos);
1937 WIN_ReleaseWndPtr(Wnd);
1941 /***********************************************************************
1942 * ScrollChildren16 (USER.463)
1944 void WINAPI ScrollChildren16(HWND16 hWnd, UINT16 uMsg, WPARAM16 wParam, LPARAM lParam)
1946 ScrollChildren( hWnd, uMsg, wParam, lParam );
1950 /***********************************************************************
1951 * ScrollChildren32 (USER32.448)
1953 void WINAPI ScrollChildren(HWND hWnd, UINT uMsg, WPARAM wParam,
1954 LPARAM lParam)
1956 WND *wndPtr = WIN_FindWndPtr(hWnd);
1957 INT newPos = -1;
1958 INT curPos, length, minPos, maxPos, shift;
1960 if( !wndPtr ) return;
1962 if( uMsg == WM_HSCROLL )
1964 GetScrollRange(hWnd,SB_HORZ,&minPos,&maxPos);
1965 curPos = GetScrollPos(hWnd,SB_HORZ);
1966 length = (wndPtr->rectClient.right - wndPtr->rectClient.left)/2;
1967 shift = SYSMETRICS_CYHSCROLL;
1969 else if( uMsg == WM_VSCROLL )
1971 GetScrollRange(hWnd,SB_VERT,&minPos,&maxPos);
1972 curPos = GetScrollPos(hWnd,SB_VERT);
1973 length = (wndPtr->rectClient.bottom - wndPtr->rectClient.top)/2;
1974 shift = SYSMETRICS_CXVSCROLL;
1976 else
1978 WIN_ReleaseWndPtr(wndPtr);
1979 return;
1982 WIN_ReleaseWndPtr(wndPtr);
1983 switch( wParam )
1985 case SB_LINEUP:
1986 newPos = curPos - shift;
1987 break;
1988 case SB_LINEDOWN:
1989 newPos = curPos + shift;
1990 break;
1991 case SB_PAGEUP:
1992 newPos = curPos - length;
1993 break;
1994 case SB_PAGEDOWN:
1995 newPos = curPos + length;
1996 break;
1998 case SB_THUMBPOSITION:
1999 newPos = LOWORD(lParam);
2000 break;
2002 case SB_THUMBTRACK:
2003 return;
2005 case SB_TOP:
2006 newPos = minPos;
2007 break;
2008 case SB_BOTTOM:
2009 newPos = maxPos;
2010 break;
2011 case SB_ENDSCROLL:
2012 CalcChildScroll16(hWnd,(uMsg == WM_VSCROLL)?SB_VERT:SB_HORZ);
2013 return;
2016 if( newPos > maxPos )
2017 newPos = maxPos;
2018 else
2019 if( newPos < minPos )
2020 newPos = minPos;
2022 SetScrollPos(hWnd, (uMsg == WM_VSCROLL)?SB_VERT:SB_HORZ , newPos, TRUE);
2024 if( uMsg == WM_VSCROLL )
2025 ScrollWindowEx(hWnd ,0 ,curPos - newPos, NULL, NULL, 0, NULL,
2026 SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
2027 else
2028 ScrollWindowEx(hWnd ,curPos - newPos, 0, NULL, NULL, 0, NULL,
2029 SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
2033 /******************************************************************************
2034 * CascadeWindows [USER32.21] Cascades MDI child windows
2036 * RETURNS
2037 * Success: Number of cascaded windows.
2038 * Failure: 0
2040 WORD WINAPI
2041 CascadeWindows (HWND hwndParent, UINT wFlags, const LPRECT lpRect,
2042 UINT cKids, const HWND *lpKids)
2044 FIXME (mdi, "(0x%08x,0x%08x,...,%u,...): stub\n",
2045 hwndParent, wFlags, cKids);
2047 return 0;
2051 /******************************************************************************
2052 * TileWindows [USER32.545] Tiles MDI child windows
2054 * RETURNS
2055 * Success: Number of tiled windows.
2056 * Failure: 0
2058 WORD WINAPI
2059 TileWindows (HWND hwndParent, UINT wFlags, const LPRECT lpRect,
2060 UINT cKids, const HWND *lpKids)
2062 FIXME (mdi, "(0x%08x,0x%08x,...,%u,...): stub\n",
2063 hwndParent, wFlags, cKids);
2065 return 0;