New debug scheme with explicit debug channels declaration.
[wine/hacks.git] / windows / mdi.c
blob17e8e233095c29cc3f9799cce549f6c94fdc080e
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 = { 0, 0, LOWORD(lParam), HIWORD(lParam) };
1164 AdjustWindowRectEx(&rect, child->dwStyle, 0, child->dwExStyle);
1165 MoveWindow(ci->hwndChildMaximized, rect.left, rect.top,
1166 rect.right - rect.left, rect.bottom - rect.top, 1);
1167 WIN_ReleaseWndPtr(child);
1169 else
1170 MDI_PostUpdate(hwnd, ci, SB_BOTH+1);
1172 break;
1174 case WM_MDICALCCHILDSCROLL:
1175 if( (ci->mdiFlags & MDIF_NEEDUPDATE) && ci->sbRecalc )
1177 CalcChildScroll16(hwnd, ci->sbRecalc-1);
1178 ci->sbRecalc = 0;
1179 ci->mdiFlags &= ~MDIF_NEEDUPDATE;
1181 retvalue = 0;
1182 goto END;
1185 retvalue = DefWindowProcA( hwnd, message, wParam, lParam );
1186 END:
1187 WIN_ReleaseWndPtr(w);
1188 WIN_ReleaseWndPtr(frameWnd);
1189 return retvalue;
1193 /***********************************************************************
1194 * DefFrameProc16 (USER.445)
1196 LRESULT WINAPI DefFrameProc16( HWND16 hwnd, HWND16 hwndMDIClient,
1197 UINT16 message, WPARAM16 wParam, LPARAM lParam )
1199 HWND16 childHwnd;
1200 MDICLIENTINFO* ci;
1201 WND* wndPtr;
1203 if (hwndMDIClient)
1205 switch (message)
1207 case WM_COMMAND:
1208 wndPtr = WIN_FindWndPtr(hwndMDIClient);
1210 if (!wndPtr) {
1211 ERR(mdi,"null wndPtr for mdi window hwndMDIClient=%04x\n",
1212 hwndMDIClient);
1213 return 0;
1216 ci = (MDICLIENTINFO*)wndPtr->wExtra;
1218 /* check for possible syscommands for maximized MDI child */
1219 WIN_ReleaseWndPtr(wndPtr);
1221 if( ci && (
1222 wParam < ci->idFirstChild ||
1223 wParam >= ci->idFirstChild + ci->nActiveChildren
1225 if( (wParam - 0xF000) & 0xF00F ) break;
1226 switch( wParam )
1228 case SC_SIZE:
1229 case SC_MOVE:
1230 case SC_MINIMIZE:
1231 case SC_MAXIMIZE:
1232 case SC_NEXTWINDOW:
1233 case SC_PREVWINDOW:
1234 case SC_CLOSE:
1235 case SC_RESTORE:
1236 if( ci->hwndChildMaximized )
1237 return SendMessage16( ci->hwndChildMaximized, WM_SYSCOMMAND,
1238 wParam, lParam);
1241 else
1243 wndPtr = WIN_FindWndPtr(hwndMDIClient);
1244 childHwnd = MDI_GetChildByID(wndPtr,wParam );
1245 WIN_ReleaseWndPtr(wndPtr);
1247 if( childHwnd )
1248 SendMessage16(hwndMDIClient, WM_MDIACTIVATE,
1249 (WPARAM16)childHwnd , 0L);
1251 break;
1253 case WM_NCACTIVATE:
1254 SendMessage16(hwndMDIClient, message, wParam, lParam);
1255 break;
1257 case WM_SETTEXT:
1258 wndPtr = WIN_FindWndPtr(hwnd);
1259 MDI_UpdateFrameText(wndPtr, hwndMDIClient,
1260 MDI_REPAINTFRAME,
1261 (LPCSTR)PTR_SEG_TO_LIN(lParam));
1262 WIN_ReleaseWndPtr(wndPtr);
1263 return 0;
1265 case WM_SETFOCUS:
1266 SetFocus(hwndMDIClient);
1267 break;
1269 case WM_SIZE:
1270 MoveWindow16(hwndMDIClient, 0, 0,
1271 LOWORD(lParam), HIWORD(lParam), TRUE);
1272 break;
1274 case WM_NEXTMENU:
1276 wndPtr = WIN_FindWndPtr(hwndMDIClient);
1277 ci = (MDICLIENTINFO*)wndPtr->wExtra;
1279 if( !(wndPtr->parent->dwStyle & WS_MINIMIZE)
1280 && ci->hwndActiveChild && !ci->hwndChildMaximized )
1282 /* control menu is between the frame system menu and
1283 * the first entry of menu bar */
1285 if( (wParam == VK_LEFT &&
1286 wndPtr->parent->wIDmenu == LOWORD(lParam)) ||
1287 (wParam == VK_RIGHT &&
1288 GetSubMenu16(wndPtr->parent->hSysMenu, 0) == LOWORD(lParam)) )
1290 LRESULT retvalue;
1291 WIN_ReleaseWndPtr(wndPtr);
1292 wndPtr = WIN_FindWndPtr(ci->hwndActiveChild);
1293 retvalue = MAKELONG( GetSubMenu16(wndPtr->hSysMenu, 0),
1294 ci->hwndActiveChild);
1295 WIN_ReleaseWndPtr(wndPtr);
1296 return retvalue;
1299 WIN_ReleaseWndPtr(wndPtr);
1300 break;
1304 return DefWindowProc16(hwnd, message, wParam, lParam);
1308 /***********************************************************************
1309 * DefFrameProc32A (USER32.122)
1311 LRESULT WINAPI DefFrameProcA( HWND hwnd, HWND hwndMDIClient,
1312 UINT message, WPARAM wParam, LPARAM lParam)
1314 if (hwndMDIClient)
1316 switch (message)
1318 case WM_COMMAND:
1319 return DefFrameProc16( hwnd, hwndMDIClient, message,
1320 (WPARAM16)wParam,
1321 MAKELPARAM( (HWND16)lParam, HIWORD(wParam) ) );
1323 case WM_NCACTIVATE:
1324 SendMessageA(hwndMDIClient, message, wParam, lParam);
1325 break;
1327 case WM_SETTEXT: {
1328 LRESULT ret;
1329 LPSTR segstr = SEGPTR_STRDUP((LPSTR)lParam);
1331 ret = DefFrameProc16(hwnd, hwndMDIClient, message,
1332 wParam, (LPARAM)SEGPTR_GET(segstr) );
1333 SEGPTR_FREE(segstr);
1334 return ret;
1337 case WM_NEXTMENU:
1338 case WM_SETFOCUS:
1339 case WM_SIZE:
1340 return DefFrameProc16( hwnd, hwndMDIClient, message,
1341 wParam, lParam );
1345 return DefWindowProcA(hwnd, message, wParam, lParam);
1349 /***********************************************************************
1350 * DefFrameProc32W (USER32.123)
1352 LRESULT WINAPI DefFrameProcW( HWND hwnd, HWND hwndMDIClient,
1353 UINT message, WPARAM wParam, LPARAM lParam)
1355 if (hwndMDIClient)
1357 switch (message)
1359 case WM_COMMAND:
1360 return DefFrameProc16( hwnd, hwndMDIClient, message,
1361 (WPARAM16)wParam,
1362 MAKELPARAM( (HWND16)lParam, HIWORD(wParam) ) );
1364 case WM_NCACTIVATE:
1365 SendMessageW(hwndMDIClient, message, wParam, lParam);
1366 break;
1368 case WM_SETTEXT:
1370 LPSTR txt = HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)lParam);
1371 LRESULT ret = DefFrameProcA( hwnd, hwndMDIClient, message,
1372 wParam, (DWORD)txt );
1373 HeapFree(GetProcessHeap(),0,txt);
1374 return ret;
1376 case WM_NEXTMENU:
1377 case WM_SETFOCUS:
1378 case WM_SIZE:
1379 return DefFrameProcA( hwnd, hwndMDIClient, message,
1380 wParam, lParam );
1384 return DefWindowProcW( hwnd, message, wParam, lParam );
1388 /***********************************************************************
1389 * DefMDIChildProc16 (USER.447)
1391 LRESULT WINAPI DefMDIChildProc16( HWND16 hwnd, UINT16 message,
1392 WPARAM16 wParam, LPARAM lParam )
1394 MDICLIENTINFO *ci;
1395 WND *clientWnd,*tmpWnd = 0;
1396 LRESULT retvalue;
1398 clientWnd = WIN_FindWndPtr(GetParent16(hwnd));
1399 ci = (MDICLIENTINFO *) clientWnd->wExtra;
1401 switch (message)
1403 case WM_SETTEXT:
1404 DefWindowProc16(hwnd, message, wParam, lParam);
1405 MDI_MenuModifyItem(clientWnd,hwnd);
1406 if( ci->hwndChildMaximized == hwnd )
1407 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1408 MDI_REPAINTFRAME, NULL );
1409 retvalue = 0;
1410 goto END;
1412 case WM_CLOSE:
1413 SendMessage16(ci->self,WM_MDIDESTROY,(WPARAM16)hwnd,0L);
1414 retvalue = 0;
1415 goto END;
1417 case WM_SETFOCUS:
1418 if( ci->hwndActiveChild != hwnd )
1419 MDI_ChildActivate(clientWnd, hwnd);
1420 break;
1422 case WM_CHILDACTIVATE:
1423 MDI_ChildActivate(clientWnd, hwnd);
1424 retvalue = 0;
1425 goto END;
1427 case WM_NCPAINT:
1428 TRACE(mdi,"WM_NCPAINT for %04x, active %04x\n",
1429 hwnd, ci->hwndActiveChild );
1430 break;
1432 case WM_SYSCOMMAND:
1433 switch( wParam )
1435 case SC_MOVE:
1436 if( ci->hwndChildMaximized == hwnd)
1438 retvalue = 0;
1439 goto END;
1441 break;
1442 case SC_RESTORE:
1443 case SC_MINIMIZE:
1444 tmpWnd = WIN_FindWndPtr(hwnd);
1445 tmpWnd->dwStyle |= WS_SYSMENU;
1446 WIN_ReleaseWndPtr(tmpWnd);
1447 break;
1448 case SC_MAXIMIZE:
1449 if( ci->hwndChildMaximized == hwnd)
1451 retvalue = SendMessage16( clientWnd->parent->hwndSelf,
1452 message, wParam, lParam);
1453 goto END;
1455 tmpWnd = WIN_FindWndPtr(hwnd);
1456 tmpWnd->dwStyle &= ~WS_SYSMENU;
1457 WIN_ReleaseWndPtr(tmpWnd);
1458 break;
1459 case SC_NEXTWINDOW:
1460 SendMessage16( ci->self, WM_MDINEXT, 0, 0);
1461 retvalue = 0;
1462 goto END;
1463 case SC_PREVWINDOW:
1464 SendMessage16( ci->self, WM_MDINEXT, 0, 1);
1465 retvalue = 0;
1466 goto END;
1468 break;
1470 case WM_GETMINMAXINFO:
1471 MDI_ChildGetMinMaxInfo(clientWnd, hwnd, (MINMAXINFO16*) PTR_SEG_TO_LIN(lParam));
1472 retvalue = 0;
1473 goto END;
1475 case WM_SETVISIBLE:
1476 if( ci->hwndChildMaximized) ci->mdiFlags &= ~MDIF_NEEDUPDATE;
1477 else
1478 MDI_PostUpdate(clientWnd->hwndSelf, ci, SB_BOTH+1);
1479 break;
1481 case WM_SIZE:
1482 /* do not change */
1484 if( ci->hwndActiveChild == hwnd && wParam != SIZE_MAXIMIZED )
1486 ci->hwndChildMaximized = 0;
1488 MDI_RestoreFrameMenu( clientWnd->parent, hwnd);
1489 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1490 MDI_REPAINTFRAME, NULL );
1493 if( wParam == SIZE_MAXIMIZED )
1495 HWND16 hMaxChild = ci->hwndChildMaximized;
1497 if( hMaxChild == hwnd ) break;
1499 if( hMaxChild)
1501 SendMessage16( hMaxChild, WM_SETREDRAW, FALSE, 0L );
1503 MDI_RestoreFrameMenu( clientWnd->parent, hMaxChild);
1504 ShowWindow16( hMaxChild, SW_SHOWNOACTIVATE);
1506 SendMessage16( hMaxChild, WM_SETREDRAW, TRUE, 0L );
1509 TRACE(mdi,"maximizing child %04x\n", hwnd );
1511 ci->hwndChildMaximized = hwnd; /* !!! */
1512 ci->hwndActiveChild = hwnd;
1514 MDI_AugmentFrameMenu( ci, clientWnd->parent, hwnd);
1515 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1516 MDI_REPAINTFRAME, NULL );
1519 if( wParam == SIZE_MINIMIZED )
1521 HWND16 switchTo = MDI_GetWindow(clientWnd, hwnd, TRUE, WS_MINIMIZE);
1523 if( switchTo )
1524 SendMessage16( switchTo, WM_CHILDACTIVATE, 0, 0L);
1527 MDI_PostUpdate(clientWnd->hwndSelf, ci, SB_BOTH+1);
1528 break;
1530 case WM_MENUCHAR:
1532 /* MDI children don't have menu bars */
1533 PostMessage16( clientWnd->parent->hwndSelf, WM_SYSCOMMAND,
1534 (WPARAM16)SC_KEYMENU, (LPARAM)wParam);
1535 retvalue = 0x00010000L;
1536 goto END;
1538 case WM_NEXTMENU:
1540 if( wParam == VK_LEFT ) /* switch to frame system menu */
1542 retvalue = MAKELONG( GetSubMenu16(clientWnd->parent->hSysMenu, 0),
1543 clientWnd->parent->hwndSelf );
1544 goto END;
1546 if( wParam == VK_RIGHT ) /* to frame menu bar */
1548 retvalue = MAKELONG( clientWnd->parent->wIDmenu,
1549 clientWnd->parent->hwndSelf );
1550 goto END;
1553 break;
1555 case WM_SYSCHAR:
1556 if (wParam == '-')
1558 SendMessage16(hwnd,WM_SYSCOMMAND,
1559 (WPARAM16)SC_KEYMENU, (LPARAM)(DWORD)VK_SPACE);
1560 retvalue = 0;
1561 goto END;
1565 retvalue = DefWindowProc16(hwnd, message, wParam, lParam);
1566 END:
1567 WIN_ReleaseWndPtr(clientWnd);
1568 return retvalue;
1572 /***********************************************************************
1573 * DefMDIChildProc32A (USER32.124)
1575 LRESULT WINAPI DefMDIChildProcA( HWND hwnd, UINT message,
1576 WPARAM wParam, LPARAM lParam )
1578 MDICLIENTINFO *ci;
1579 WND *clientWnd,*tmpWnd;
1580 LRESULT retvalue;
1582 tmpWnd = WIN_FindWndPtr(hwnd);
1583 clientWnd = WIN_FindWndPtr(tmpWnd->parent->hwndSelf);
1584 ci = (MDICLIENTINFO *) clientWnd->wExtra;
1585 WIN_ReleaseWndPtr(tmpWnd);
1587 switch (message)
1589 case WM_SETTEXT:
1590 DefWindowProcA(hwnd, message, wParam, lParam);
1591 MDI_MenuModifyItem(clientWnd,hwnd);
1592 if( ci->hwndChildMaximized == hwnd )
1593 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1594 MDI_REPAINTFRAME, NULL );
1595 retvalue = 0;
1596 goto END;
1598 case WM_GETMINMAXINFO:
1600 MINMAXINFO16 mmi;
1601 STRUCT32_MINMAXINFO32to16( (MINMAXINFO *)lParam, &mmi );
1602 MDI_ChildGetMinMaxInfo( clientWnd, hwnd, &mmi );
1603 STRUCT32_MINMAXINFO16to32( &mmi, (MINMAXINFO *)lParam );
1605 retvalue = 0;
1606 goto END;
1608 case WM_MENUCHAR:
1610 /* MDI children don't have menu bars */
1611 PostMessage16( clientWnd->parent->hwndSelf, WM_SYSCOMMAND,
1612 (WPARAM16)SC_KEYMENU, (LPARAM)LOWORD(wParam) );
1613 retvalue = 0x00010000L;
1614 goto END;
1616 case WM_CLOSE:
1617 case WM_SETFOCUS:
1618 case WM_CHILDACTIVATE:
1619 case WM_NCPAINT:
1620 case WM_SYSCOMMAND:
1621 case WM_SETVISIBLE:
1622 case WM_SIZE:
1623 case WM_NEXTMENU:
1624 retvalue = DefMDIChildProc16( hwnd, message, (WPARAM16)wParam, lParam );
1625 goto END;
1627 case WM_SYSCHAR:
1628 if (wParam == '-')
1630 SendMessageA(hwnd,WM_SYSCOMMAND,
1631 (WPARAM)SC_KEYMENU, (LPARAM)(DWORD)VK_SPACE);
1632 retvalue = 0;
1633 goto END;
1636 retvalue = DefWindowProcA(hwnd, message, wParam, lParam);
1637 END:
1638 WIN_ReleaseWndPtr(clientWnd);
1639 return retvalue;
1643 /***********************************************************************
1644 * DefMDIChildProc32W (USER32.125)
1646 LRESULT WINAPI DefMDIChildProcW( HWND hwnd, UINT message,
1647 WPARAM wParam, LPARAM lParam )
1649 MDICLIENTINFO *ci;
1650 WND *clientWnd;
1651 LRESULT retvalue;
1653 clientWnd = WIN_FindWndPtr(GetParent16(hwnd));
1654 ci = (MDICLIENTINFO *) clientWnd->wExtra;
1656 switch (message)
1658 case WM_SETTEXT:
1659 DefWindowProcW(hwnd, message, wParam, lParam);
1660 MDI_MenuModifyItem(clientWnd,hwnd);
1661 if( ci->hwndChildMaximized == hwnd )
1662 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1663 MDI_REPAINTFRAME, NULL );
1664 retvalue = 0;
1665 goto END;
1667 case WM_GETMINMAXINFO:
1668 case WM_MENUCHAR:
1669 case WM_CLOSE:
1670 case WM_SETFOCUS:
1671 case WM_CHILDACTIVATE:
1672 case WM_NCPAINT:
1673 case WM_SYSCOMMAND:
1674 case WM_SETVISIBLE:
1675 case WM_SIZE:
1676 case WM_NEXTMENU:
1677 retvalue = DefMDIChildProcA( hwnd, message, (WPARAM16)wParam, lParam );
1678 goto END;
1680 case WM_SYSCHAR:
1681 if (wParam == '-')
1683 SendMessageW(hwnd,WM_SYSCOMMAND,
1684 (WPARAM)SC_KEYMENU, (LPARAM)(DWORD)VK_SPACE);
1685 retvalue = 0;
1686 goto END;
1689 retvalue = DefWindowProcW(hwnd, message, wParam, lParam);
1690 END:
1691 WIN_ReleaseWndPtr(clientWnd);
1692 return retvalue;
1697 /**********************************************************************
1698 * CreateMDIWindowA [USER32.79] Creates a MDI child in new thread
1699 * FIXME: its in the same thread now
1701 * RETURNS
1702 * Success: Handle to created window
1703 * Failure: NULL
1705 HWND WINAPI CreateMDIWindowA(
1706 LPCSTR lpClassName, /* [in] Pointer to registered child class name */
1707 LPCSTR lpWindowName, /* [in] Pointer to window name */
1708 DWORD dwStyle, /* [in] Window style */
1709 INT X, /* [in] Horizontal position of window */
1710 INT Y, /* [in] Vertical position of window */
1711 INT nWidth, /* [in] Width of window */
1712 INT nHeight, /* [in] Height of window */
1713 HWND hWndParent, /* [in] Handle to parent window */
1714 HINSTANCE hInstance, /* [in] Handle to application instance */
1715 LPARAM lParam) /* [in] Application-defined value */
1717 WARN(mdi,"is only single threaded!\n");
1718 return MDI_CreateMDIWindowA(lpClassName, lpWindowName, dwStyle, X, Y,
1719 nWidth, nHeight, hWndParent, hInstance, lParam);
1722 /**********************************************************************
1723 * MDI_CreateMDIWindowA
1724 * single threaded version of CreateMDIWindowA
1725 * called by CreateWindowEx32A
1727 HWND MDI_CreateMDIWindowA(
1728 LPCSTR lpClassName,
1729 LPCSTR lpWindowName,
1730 DWORD dwStyle,
1731 INT X,
1732 INT Y,
1733 INT nWidth,
1734 INT nHeight,
1735 HWND hWndParent,
1736 HINSTANCE hInstance,
1737 LPARAM lParam)
1739 MDICLIENTINFO* pCi;
1740 MDICREATESTRUCTA cs;
1741 WND *pWnd=WIN_FindWndPtr(hWndParent);
1742 HWND retvalue;
1744 TRACE(mdi, "(%s,%s,%ld,%d,%d,%d,%d,%x,%d,%ld)\n",
1745 debugstr_a(lpClassName),debugstr_a(lpWindowName),dwStyle,X,Y,
1746 nWidth,nHeight,hWndParent,hInstance,lParam);
1748 if(!pWnd){
1749 ERR(mdi," bad hwnd for MDI-client: %d\n",hWndParent);
1750 return 0;
1752 cs.szClass=lpClassName;
1753 cs.szTitle=lpWindowName;
1754 cs.hOwner=hInstance;
1755 cs.x=X;
1756 cs.y=Y;
1757 cs.cx=nWidth;
1758 cs.cy=nHeight;
1759 cs.style=dwStyle;
1760 cs.lParam=lParam;
1762 pCi=(MDICLIENTINFO *)pWnd->wExtra;
1764 retvalue = MDICreateChild(pWnd,pCi,hWndParent,&cs);
1765 WIN_ReleaseWndPtr(pWnd);
1766 return retvalue;
1769 /***************************************
1770 * CreateMDIWindow32W [USER32.80] Creates a MDI child in new thread
1772 * RETURNS
1773 * Success: Handle to created window
1774 * Failure: NULL
1776 HWND WINAPI CreateMDIWindowW(
1777 LPCWSTR lpClassName, /* [in] Pointer to registered child class name */
1778 LPCWSTR lpWindowName, /* [in] Pointer to window name */
1779 DWORD dwStyle, /* [in] Window style */
1780 INT X, /* [in] Horizontal position of window */
1781 INT Y, /* [in] Vertical position of window */
1782 INT nWidth, /* [in] Width of window */
1783 INT nHeight, /* [in] Height of window */
1784 HWND hWndParent, /* [in] Handle to parent window */
1785 HINSTANCE hInstance, /* [in] Handle to application instance */
1786 LPARAM lParam) /* [in] Application-defined value */
1788 FIXME(mdi, "(%s,%s,%ld,%d,%d,%d,%d,%x,%d,%ld): stub\n",
1789 debugstr_w(lpClassName),debugstr_w(lpWindowName),dwStyle,X,Y,
1790 nWidth,nHeight,hWndParent,hInstance,lParam);
1791 return (HWND)NULL;
1795 /******************************************************************************
1796 * CreateMDIWindow32W [USER32.80] Creates a MDI child window
1797 * single threaded version of CreateMDIWindow
1798 * called by CreateWindowEx32W().
1800 HWND MDI_CreateMDIWindowW(
1801 LPCWSTR lpClassName, /* [in] Pointer to registered child class name */
1802 LPCWSTR lpWindowName, /* [in] Pointer to window name */
1803 DWORD dwStyle, /* [in] Window style */
1804 INT X, /* [in] Horizontal position of window */
1805 INT Y, /* [in] Vertical position of window */
1806 INT nWidth, /* [in] Width of window */
1807 INT nHeight, /* [in] Height of window */
1808 HWND hWndParent, /* [in] Handle to parent window */
1809 HINSTANCE hInstance, /* [in] Handle to application instance */
1810 LPARAM lParam) /* [in] Application-defined value */
1812 FIXME(mdi, "(%s,%s,%ld,%d,%d,%d,%d,%x,%d,%ld): stub\n",
1813 debugstr_w(lpClassName),debugstr_w(lpWindowName),dwStyle,X,Y,
1814 nWidth,nHeight,hWndParent,hInstance,lParam);
1815 return (HWND)NULL;
1819 /**********************************************************************
1820 * TranslateMDISysAccel32 (USER32.555)
1822 BOOL WINAPI TranslateMDISysAccel( HWND hwndClient, LPMSG msg )
1824 MSG16 msg16;
1826 STRUCT32_MSG32to16(msg,&msg16);
1827 /* MDICLIENTINFO is still the same for win32 and win16 ... */
1828 return TranslateMDISysAccel16(hwndClient,&msg16);
1832 /**********************************************************************
1833 * TranslateMDISysAccel16 (USER.451)
1835 BOOL16 WINAPI TranslateMDISysAccel16( HWND16 hwndClient, LPMSG16 msg )
1837 WND* clientWnd = WIN_FindWndPtr( hwndClient);
1839 if( clientWnd && (msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN))
1841 MDICLIENTINFO *ci = NULL;
1842 WND* wnd;
1844 ci = (MDICLIENTINFO*) clientWnd->wExtra;
1845 WIN_ReleaseWndPtr(clientWnd);
1846 wnd = WIN_FindWndPtr(ci->hwndActiveChild);
1847 if( wnd && !(wnd->dwStyle & WS_DISABLED) )
1849 WPARAM16 wParam = 0;
1851 WIN_ReleaseWndPtr(wnd);
1852 /* translate if the Ctrl key is down and Alt not. */
1854 if( (GetKeyState(VK_CONTROL) & 0x8000) &&
1855 !(GetKeyState(VK_MENU) & 0x8000))
1857 switch( msg->wParam )
1859 case VK_F6:
1860 case VK_TAB:
1861 wParam = ( GetKeyState(VK_SHIFT) & 0x8000 )
1862 ? SC_NEXTWINDOW : SC_PREVWINDOW;
1863 break;
1864 case VK_F4:
1865 case VK_RBUTTON:
1866 wParam = SC_CLOSE;
1867 break;
1868 default:
1869 return 0;
1871 TRACE(mdi,"wParam = %04x\n", wParam);
1872 SendMessage16( ci->hwndActiveChild, WM_SYSCOMMAND,
1873 wParam, (LPARAM)msg->wParam);
1874 return 1;
1877 WIN_ReleaseWndPtr(wnd);
1879 WIN_ReleaseWndPtr(clientWnd);
1880 return 0; /* failure */
1884 /***********************************************************************
1885 * CalcChildScroll (USER.462)
1887 void WINAPI CalcChildScroll16( HWND16 hwnd, WORD scroll )
1889 SCROLLINFO info;
1890 RECT childRect, clientRect;
1891 INT vmin, vmax, hmin, hmax, vpos, hpos;
1892 WND *pWnd, *Wnd;
1894 if (!(pWnd = WIN_FindWndPtr( hwnd ))) return;
1895 Wnd = WIN_FindWndPtr(hwnd);
1896 GetClientRect( hwnd, &clientRect );
1897 SetRectEmpty( &childRect );
1899 for ( WIN_UpdateWndPtr(&pWnd,pWnd->child); pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1901 if( pWnd->dwStyle & WS_MAXIMIZE )
1903 ShowScrollBar(hwnd, SB_BOTH, FALSE);
1904 WIN_ReleaseWndPtr(pWnd);
1905 WIN_ReleaseWndPtr(Wnd);
1906 return;
1908 UnionRect( &childRect, &pWnd->rectWindow, &childRect );
1910 WIN_ReleaseWndPtr(pWnd);
1911 UnionRect( &childRect, &clientRect, &childRect );
1913 hmin = childRect.left; hmax = childRect.right - clientRect.right;
1914 hpos = clientRect.left - childRect.left;
1915 vmin = childRect.top; vmax = childRect.bottom - clientRect.bottom;
1916 vpos = clientRect.top - childRect.top;
1918 switch( scroll )
1920 case SB_HORZ:
1921 vpos = hpos; vmin = hmin; vmax = hmax;
1922 case SB_VERT:
1923 info.cbSize = sizeof(info);
1924 info.nMax = vmax; info.nMin = vmin; info.nPos = vpos;
1925 info.fMask = SIF_POS | SIF_RANGE;
1926 SetScrollInfo(hwnd, scroll, &info, TRUE);
1927 break;
1928 case SB_BOTH:
1929 SCROLL_SetNCSbState( Wnd, vmin, vmax, vpos,
1930 hmin, hmax, hpos);
1932 WIN_ReleaseWndPtr(Wnd);
1936 /***********************************************************************
1937 * ScrollChildren16 (USER.463)
1939 void WINAPI ScrollChildren16(HWND16 hWnd, UINT16 uMsg, WPARAM16 wParam, LPARAM lParam)
1941 return ScrollChildren( hWnd, uMsg, wParam, lParam );
1945 /***********************************************************************
1946 * ScrollChildren32 (USER32.448)
1948 void WINAPI ScrollChildren(HWND hWnd, UINT uMsg, WPARAM wParam,
1949 LPARAM lParam)
1951 WND *wndPtr = WIN_FindWndPtr(hWnd);
1952 INT newPos = -1;
1953 INT curPos, length, minPos, maxPos, shift;
1955 if( !wndPtr ) return;
1957 if( uMsg == WM_HSCROLL )
1959 GetScrollRange(hWnd,SB_HORZ,&minPos,&maxPos);
1960 curPos = GetScrollPos(hWnd,SB_HORZ);
1961 length = (wndPtr->rectClient.right - wndPtr->rectClient.left)/2;
1962 shift = SYSMETRICS_CYHSCROLL;
1964 else if( uMsg == WM_VSCROLL )
1966 GetScrollRange(hWnd,SB_VERT,&minPos,&maxPos);
1967 curPos = GetScrollPos(hWnd,SB_VERT);
1968 length = (wndPtr->rectClient.bottom - wndPtr->rectClient.top)/2;
1969 shift = SYSMETRICS_CXVSCROLL;
1971 else
1973 WIN_ReleaseWndPtr(wndPtr);
1974 return;
1977 WIN_ReleaseWndPtr(wndPtr);
1978 switch( wParam )
1980 case SB_LINEUP:
1981 newPos = curPos - shift;
1982 break;
1983 case SB_LINEDOWN:
1984 newPos = curPos + shift;
1985 break;
1986 case SB_PAGEUP:
1987 newPos = curPos - length;
1988 break;
1989 case SB_PAGEDOWN:
1990 newPos = curPos + length;
1991 break;
1993 case SB_THUMBPOSITION:
1994 newPos = LOWORD(lParam);
1995 break;
1997 case SB_THUMBTRACK:
1998 return;
2000 case SB_TOP:
2001 newPos = minPos;
2002 break;
2003 case SB_BOTTOM:
2004 newPos = maxPos;
2005 break;
2006 case SB_ENDSCROLL:
2007 CalcChildScroll16(hWnd,(uMsg == WM_VSCROLL)?SB_VERT:SB_HORZ);
2008 return;
2011 if( newPos > maxPos )
2012 newPos = maxPos;
2013 else
2014 if( newPos < minPos )
2015 newPos = minPos;
2017 SetScrollPos(hWnd, (uMsg == WM_VSCROLL)?SB_VERT:SB_HORZ , newPos, TRUE);
2019 if( uMsg == WM_VSCROLL )
2020 ScrollWindowEx(hWnd ,0 ,curPos - newPos, NULL, NULL, 0, NULL,
2021 SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
2022 else
2023 ScrollWindowEx(hWnd ,curPos - newPos, 0, NULL, NULL, 0, NULL,
2024 SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
2028 /******************************************************************************
2029 * CascadeWindows [USER32.21] Cascades MDI child windows
2031 * RETURNS
2032 * Success: Number of cascaded windows.
2033 * Failure: 0
2035 WORD WINAPI
2036 CascadeWindows (HWND hwndParent, UINT wFlags, const LPRECT lpRect,
2037 UINT cKids, const HWND *lpKids)
2039 FIXME (mdi, "(0x%08x,0x%08x,...,%u,...): stub\n",
2040 hwndParent, wFlags, cKids);
2042 return 0;
2046 /******************************************************************************
2047 * TileWindows [USER32.545] Tiles MDI child windows
2049 * RETURNS
2050 * Success: Number of tiled windows.
2051 * Failure: 0
2053 WORD WINAPI
2054 TileWindows (HWND hwndParent, UINT wFlags, const LPRECT lpRect,
2055 UINT cKids, const HWND *lpKids)
2057 FIXME (mdi, "(0x%08x,0x%08x,...,%u,...): stub\n",
2058 hwndParent, wFlags, cKids);
2060 return 0;