Fixed some deadlock(s) in message sending.
[wine.git] / windows / mdi.c
blob000b368ddd5d9cff4f1e464ca10869255c0384bc
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 = LoadMenuA(GetModuleHandleA("USER32"), "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 WND* pw = WIN_FindWndPtr( ci->hwndActiveChild );
1133 if( !(pw->dwStyle & WS_MINIMIZE) )
1134 SetFocus( ci->hwndActiveChild );
1135 WIN_ReleaseWndPtr(pw);
1137 retvalue = 0;
1138 goto END;
1140 case WM_NCACTIVATE:
1141 if( ci->hwndActiveChild )
1142 SendMessageA(ci->hwndActiveChild, message, wParam, lParam);
1143 break;
1145 case WM_PARENTNOTIFY:
1146 if (LOWORD(wParam) == WM_LBUTTONDOWN)
1148 POINT16 pt = MAKEPOINT16(lParam);
1149 HWND16 child = ChildWindowFromPoint16(hwnd, pt);
1151 TRACE(mdi,"notification from %04x (%i,%i)\n",child,pt.x,pt.y);
1153 if( child && child != hwnd && child != ci->hwndActiveChild )
1154 SetWindowPos(child, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE );
1156 retvalue = 0;
1157 goto END;
1159 case WM_SIZE:
1160 if( IsWindow(ci->hwndChildMaximized) )
1162 WND* child = WIN_FindWndPtr(ci->hwndChildMaximized);
1163 RECT rect;
1165 rect.left = 0;
1166 rect.top = 0;
1167 rect.right = LOWORD(lParam);
1168 rect.bottom = HIWORD(lParam);
1170 AdjustWindowRectEx(&rect, child->dwStyle, 0, child->dwExStyle);
1171 MoveWindow(ci->hwndChildMaximized, rect.left, rect.top,
1172 rect.right - rect.left, rect.bottom - rect.top, 1);
1173 WIN_ReleaseWndPtr(child);
1175 else
1176 MDI_PostUpdate(hwnd, ci, SB_BOTH+1);
1178 break;
1180 case WM_MDICALCCHILDSCROLL:
1181 if( (ci->mdiFlags & MDIF_NEEDUPDATE) && ci->sbRecalc )
1183 CalcChildScroll16(hwnd, ci->sbRecalc-1);
1184 ci->sbRecalc = 0;
1185 ci->mdiFlags &= ~MDIF_NEEDUPDATE;
1187 retvalue = 0;
1188 goto END;
1191 retvalue = DefWindowProcA( hwnd, message, wParam, lParam );
1192 END:
1193 WIN_ReleaseWndPtr(w);
1194 WIN_ReleaseWndPtr(frameWnd);
1195 return retvalue;
1199 /***********************************************************************
1200 * DefFrameProc16 (USER.445)
1202 LRESULT WINAPI DefFrameProc16( HWND16 hwnd, HWND16 hwndMDIClient,
1203 UINT16 message, WPARAM16 wParam, LPARAM lParam )
1205 HWND16 childHwnd;
1206 MDICLIENTINFO* ci;
1207 WND* wndPtr;
1209 if (hwndMDIClient)
1211 switch (message)
1213 case WM_COMMAND:
1214 wndPtr = WIN_FindWndPtr(hwndMDIClient);
1216 if (!wndPtr) {
1217 ERR(mdi,"null wndPtr for mdi window hwndMDIClient=%04x\n",
1218 hwndMDIClient);
1219 return 0;
1222 ci = (MDICLIENTINFO*)wndPtr->wExtra;
1224 /* check for possible syscommands for maximized MDI child */
1225 WIN_ReleaseWndPtr(wndPtr);
1227 if( ci && (
1228 wParam < ci->idFirstChild ||
1229 wParam >= ci->idFirstChild + ci->nActiveChildren
1231 if( (wParam - 0xF000) & 0xF00F ) break;
1232 switch( wParam )
1234 case SC_SIZE:
1235 case SC_MOVE:
1236 case SC_MINIMIZE:
1237 case SC_MAXIMIZE:
1238 case SC_NEXTWINDOW:
1239 case SC_PREVWINDOW:
1240 case SC_CLOSE:
1241 case SC_RESTORE:
1242 if( ci->hwndChildMaximized )
1243 return SendMessage16( ci->hwndChildMaximized, WM_SYSCOMMAND,
1244 wParam, lParam);
1247 else
1249 wndPtr = WIN_FindWndPtr(hwndMDIClient);
1250 childHwnd = MDI_GetChildByID(wndPtr,wParam );
1251 WIN_ReleaseWndPtr(wndPtr);
1253 if( childHwnd )
1254 SendMessage16(hwndMDIClient, WM_MDIACTIVATE,
1255 (WPARAM16)childHwnd , 0L);
1257 break;
1259 case WM_NCACTIVATE:
1260 SendMessage16(hwndMDIClient, message, wParam, lParam);
1261 break;
1263 case WM_SETTEXT:
1264 wndPtr = WIN_FindWndPtr(hwnd);
1265 MDI_UpdateFrameText(wndPtr, hwndMDIClient,
1266 MDI_REPAINTFRAME,
1267 (LPCSTR)PTR_SEG_TO_LIN(lParam));
1268 WIN_ReleaseWndPtr(wndPtr);
1269 return 0;
1271 case WM_SETFOCUS:
1272 SetFocus(hwndMDIClient);
1273 break;
1275 case WM_SIZE:
1276 MoveWindow16(hwndMDIClient, 0, 0,
1277 LOWORD(lParam), HIWORD(lParam), TRUE);
1278 break;
1280 case WM_NEXTMENU:
1282 wndPtr = WIN_FindWndPtr(hwndMDIClient);
1283 ci = (MDICLIENTINFO*)wndPtr->wExtra;
1285 if( !(wndPtr->parent->dwStyle & WS_MINIMIZE)
1286 && ci->hwndActiveChild && !ci->hwndChildMaximized )
1288 /* control menu is between the frame system menu and
1289 * the first entry of menu bar */
1291 if( (wParam == VK_LEFT &&
1292 wndPtr->parent->wIDmenu == LOWORD(lParam)) ||
1293 (wParam == VK_RIGHT &&
1294 GetSubMenu16(wndPtr->parent->hSysMenu, 0) == LOWORD(lParam)) )
1296 LRESULT retvalue;
1297 WIN_ReleaseWndPtr(wndPtr);
1298 wndPtr = WIN_FindWndPtr(ci->hwndActiveChild);
1299 retvalue = MAKELONG( GetSubMenu16(wndPtr->hSysMenu, 0),
1300 ci->hwndActiveChild);
1301 WIN_ReleaseWndPtr(wndPtr);
1302 return retvalue;
1305 WIN_ReleaseWndPtr(wndPtr);
1306 break;
1310 return DefWindowProc16(hwnd, message, wParam, lParam);
1314 /***********************************************************************
1315 * DefFrameProc32A (USER32.122)
1317 LRESULT WINAPI DefFrameProcA( HWND hwnd, HWND hwndMDIClient,
1318 UINT message, WPARAM wParam, LPARAM lParam)
1320 if (hwndMDIClient)
1322 switch (message)
1324 case WM_COMMAND:
1325 return DefFrameProc16( hwnd, hwndMDIClient, message,
1326 (WPARAM16)wParam,
1327 MAKELPARAM( (HWND16)lParam, HIWORD(wParam) ) );
1329 case WM_NCACTIVATE:
1330 SendMessageA(hwndMDIClient, message, wParam, lParam);
1331 break;
1333 case WM_SETTEXT: {
1334 LRESULT ret;
1335 LPSTR segstr = SEGPTR_STRDUP((LPSTR)lParam);
1337 ret = DefFrameProc16(hwnd, hwndMDIClient, message,
1338 wParam, (LPARAM)SEGPTR_GET(segstr) );
1339 SEGPTR_FREE(segstr);
1340 return ret;
1343 case WM_NEXTMENU:
1344 case WM_SETFOCUS:
1345 case WM_SIZE:
1346 return DefFrameProc16( hwnd, hwndMDIClient, message,
1347 wParam, lParam );
1351 return DefWindowProcA(hwnd, message, wParam, lParam);
1355 /***********************************************************************
1356 * DefFrameProc32W (USER32.123)
1358 LRESULT WINAPI DefFrameProcW( HWND hwnd, HWND hwndMDIClient,
1359 UINT message, WPARAM wParam, LPARAM lParam)
1361 if (hwndMDIClient)
1363 switch (message)
1365 case WM_COMMAND:
1366 return DefFrameProc16( hwnd, hwndMDIClient, message,
1367 (WPARAM16)wParam,
1368 MAKELPARAM( (HWND16)lParam, HIWORD(wParam) ) );
1370 case WM_NCACTIVATE:
1371 SendMessageW(hwndMDIClient, message, wParam, lParam);
1372 break;
1374 case WM_SETTEXT:
1376 LPSTR txt = HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)lParam);
1377 LRESULT ret = DefFrameProcA( hwnd, hwndMDIClient, message,
1378 wParam, (DWORD)txt );
1379 HeapFree(GetProcessHeap(),0,txt);
1380 return ret;
1382 case WM_NEXTMENU:
1383 case WM_SETFOCUS:
1384 case WM_SIZE:
1385 return DefFrameProcA( hwnd, hwndMDIClient, message,
1386 wParam, lParam );
1390 return DefWindowProcW( hwnd, message, wParam, lParam );
1394 /***********************************************************************
1395 * DefMDIChildProc16 (USER.447)
1397 LRESULT WINAPI DefMDIChildProc16( HWND16 hwnd, UINT16 message,
1398 WPARAM16 wParam, LPARAM lParam )
1400 MDICLIENTINFO *ci;
1401 WND *clientWnd,*tmpWnd = 0;
1402 LRESULT retvalue;
1404 clientWnd = WIN_FindWndPtr(GetParent16(hwnd));
1405 ci = (MDICLIENTINFO *) clientWnd->wExtra;
1407 switch (message)
1409 case WM_SETTEXT:
1410 DefWindowProc16(hwnd, message, wParam, lParam);
1411 MDI_MenuModifyItem(clientWnd,hwnd);
1412 if( ci->hwndChildMaximized == hwnd )
1413 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1414 MDI_REPAINTFRAME, NULL );
1415 retvalue = 0;
1416 goto END;
1418 case WM_CLOSE:
1419 SendMessage16(ci->self,WM_MDIDESTROY,(WPARAM16)hwnd,0L);
1420 retvalue = 0;
1421 goto END;
1423 case WM_SETFOCUS:
1424 if( ci->hwndActiveChild != hwnd )
1425 MDI_ChildActivate(clientWnd, hwnd);
1426 break;
1428 case WM_CHILDACTIVATE:
1429 MDI_ChildActivate(clientWnd, hwnd);
1430 retvalue = 0;
1431 goto END;
1433 case WM_NCPAINT:
1434 TRACE(mdi,"WM_NCPAINT for %04x, active %04x\n",
1435 hwnd, ci->hwndActiveChild );
1436 break;
1438 case WM_SYSCOMMAND:
1439 switch( wParam )
1441 case SC_MOVE:
1442 if( ci->hwndChildMaximized == hwnd)
1444 retvalue = 0;
1445 goto END;
1447 break;
1448 case SC_RESTORE:
1449 case SC_MINIMIZE:
1450 tmpWnd = WIN_FindWndPtr(hwnd);
1451 tmpWnd->dwStyle |= WS_SYSMENU;
1452 WIN_ReleaseWndPtr(tmpWnd);
1453 break;
1454 case SC_MAXIMIZE:
1455 if( ci->hwndChildMaximized == hwnd)
1457 retvalue = SendMessage16( clientWnd->parent->hwndSelf,
1458 message, wParam, lParam);
1459 goto END;
1461 tmpWnd = WIN_FindWndPtr(hwnd);
1462 tmpWnd->dwStyle &= ~WS_SYSMENU;
1463 WIN_ReleaseWndPtr(tmpWnd);
1464 break;
1465 case SC_NEXTWINDOW:
1466 SendMessage16( ci->self, WM_MDINEXT, 0, 0);
1467 retvalue = 0;
1468 goto END;
1469 case SC_PREVWINDOW:
1470 SendMessage16( ci->self, WM_MDINEXT, 0, 1);
1471 retvalue = 0;
1472 goto END;
1474 break;
1476 case WM_GETMINMAXINFO:
1477 MDI_ChildGetMinMaxInfo(clientWnd, hwnd, (MINMAXINFO16*) PTR_SEG_TO_LIN(lParam));
1478 retvalue = 0;
1479 goto END;
1481 case WM_SETVISIBLE:
1482 if( ci->hwndChildMaximized) ci->mdiFlags &= ~MDIF_NEEDUPDATE;
1483 else
1484 MDI_PostUpdate(clientWnd->hwndSelf, ci, SB_BOTH+1);
1485 break;
1487 case WM_SIZE:
1488 /* do not change */
1490 if( ci->hwndActiveChild == hwnd && wParam != SIZE_MAXIMIZED )
1492 ci->hwndChildMaximized = 0;
1494 MDI_RestoreFrameMenu( clientWnd->parent, hwnd);
1495 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1496 MDI_REPAINTFRAME, NULL );
1499 if( wParam == SIZE_MAXIMIZED )
1501 HWND16 hMaxChild = ci->hwndChildMaximized;
1503 if( hMaxChild == hwnd ) break;
1505 if( hMaxChild)
1507 SendMessage16( hMaxChild, WM_SETREDRAW, FALSE, 0L );
1509 MDI_RestoreFrameMenu( clientWnd->parent, hMaxChild);
1510 ShowWindow16( hMaxChild, SW_SHOWNOACTIVATE);
1512 SendMessage16( hMaxChild, WM_SETREDRAW, TRUE, 0L );
1515 TRACE(mdi,"maximizing child %04x\n", hwnd );
1517 ci->hwndChildMaximized = hwnd; /* !!! */
1518 ci->hwndActiveChild = hwnd;
1520 MDI_AugmentFrameMenu( ci, clientWnd->parent, hwnd);
1521 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1522 MDI_REPAINTFRAME, NULL );
1525 if( wParam == SIZE_MINIMIZED )
1527 HWND16 switchTo = MDI_GetWindow(clientWnd, hwnd, TRUE, WS_MINIMIZE);
1529 if( switchTo )
1530 SendMessage16( switchTo, WM_CHILDACTIVATE, 0, 0L);
1533 MDI_PostUpdate(clientWnd->hwndSelf, ci, SB_BOTH+1);
1534 break;
1536 case WM_MENUCHAR:
1538 /* MDI children don't have menu bars */
1539 PostMessage16( clientWnd->parent->hwndSelf, WM_SYSCOMMAND,
1540 (WPARAM16)SC_KEYMENU, (LPARAM)wParam);
1541 retvalue = 0x00010000L;
1542 goto END;
1544 case WM_NEXTMENU:
1546 if( wParam == VK_LEFT ) /* switch to frame system menu */
1548 retvalue = MAKELONG( GetSubMenu16(clientWnd->parent->hSysMenu, 0),
1549 clientWnd->parent->hwndSelf );
1550 goto END;
1552 if( wParam == VK_RIGHT ) /* to frame menu bar */
1554 retvalue = MAKELONG( clientWnd->parent->wIDmenu,
1555 clientWnd->parent->hwndSelf );
1556 goto END;
1559 break;
1561 case WM_SYSCHAR:
1562 if (wParam == '-')
1564 SendMessage16(hwnd,WM_SYSCOMMAND,
1565 (WPARAM16)SC_KEYMENU, (LPARAM)(DWORD)VK_SPACE);
1566 retvalue = 0;
1567 goto END;
1571 retvalue = DefWindowProc16(hwnd, message, wParam, lParam);
1572 END:
1573 WIN_ReleaseWndPtr(clientWnd);
1574 return retvalue;
1578 /***********************************************************************
1579 * DefMDIChildProc32A (USER32.124)
1581 LRESULT WINAPI DefMDIChildProcA( HWND hwnd, UINT message,
1582 WPARAM wParam, LPARAM lParam )
1584 MDICLIENTINFO *ci;
1585 WND *clientWnd,*tmpWnd;
1586 LRESULT retvalue;
1588 tmpWnd = WIN_FindWndPtr(hwnd);
1589 clientWnd = WIN_FindWndPtr(tmpWnd->parent->hwndSelf);
1590 ci = (MDICLIENTINFO *) clientWnd->wExtra;
1591 WIN_ReleaseWndPtr(tmpWnd);
1593 switch (message)
1595 case WM_SETTEXT:
1596 DefWindowProcA(hwnd, message, wParam, lParam);
1597 MDI_MenuModifyItem(clientWnd,hwnd);
1598 if( ci->hwndChildMaximized == hwnd )
1599 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1600 MDI_REPAINTFRAME, NULL );
1601 retvalue = 0;
1602 goto END;
1604 case WM_GETMINMAXINFO:
1606 MINMAXINFO16 mmi;
1607 STRUCT32_MINMAXINFO32to16( (MINMAXINFO *)lParam, &mmi );
1608 MDI_ChildGetMinMaxInfo( clientWnd, hwnd, &mmi );
1609 STRUCT32_MINMAXINFO16to32( &mmi, (MINMAXINFO *)lParam );
1611 retvalue = 0;
1612 goto END;
1614 case WM_MENUCHAR:
1616 /* MDI children don't have menu bars */
1617 PostMessage16( clientWnd->parent->hwndSelf, WM_SYSCOMMAND,
1618 (WPARAM16)SC_KEYMENU, (LPARAM)LOWORD(wParam) );
1619 retvalue = 0x00010000L;
1620 goto END;
1622 case WM_CLOSE:
1623 case WM_SETFOCUS:
1624 case WM_CHILDACTIVATE:
1625 case WM_NCPAINT:
1626 case WM_SYSCOMMAND:
1627 case WM_SETVISIBLE:
1628 case WM_SIZE:
1629 case WM_NEXTMENU:
1630 retvalue = DefMDIChildProc16( hwnd, message, (WPARAM16)wParam, lParam );
1631 goto END;
1633 case WM_SYSCHAR:
1634 if (wParam == '-')
1636 SendMessageA(hwnd,WM_SYSCOMMAND,
1637 (WPARAM)SC_KEYMENU, (LPARAM)(DWORD)VK_SPACE);
1638 retvalue = 0;
1639 goto END;
1642 retvalue = DefWindowProcA(hwnd, message, wParam, lParam);
1643 END:
1644 WIN_ReleaseWndPtr(clientWnd);
1645 return retvalue;
1649 /***********************************************************************
1650 * DefMDIChildProc32W (USER32.125)
1652 LRESULT WINAPI DefMDIChildProcW( HWND hwnd, UINT message,
1653 WPARAM wParam, LPARAM lParam )
1655 MDICLIENTINFO *ci;
1656 WND *clientWnd;
1657 LRESULT retvalue;
1659 clientWnd = WIN_FindWndPtr(GetParent16(hwnd));
1660 ci = (MDICLIENTINFO *) clientWnd->wExtra;
1662 switch (message)
1664 case WM_SETTEXT:
1665 DefWindowProcW(hwnd, message, wParam, lParam);
1666 MDI_MenuModifyItem(clientWnd,hwnd);
1667 if( ci->hwndChildMaximized == hwnd )
1668 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1669 MDI_REPAINTFRAME, NULL );
1670 retvalue = 0;
1671 goto END;
1673 case WM_GETMINMAXINFO:
1674 case WM_MENUCHAR:
1675 case WM_CLOSE:
1676 case WM_SETFOCUS:
1677 case WM_CHILDACTIVATE:
1678 case WM_NCPAINT:
1679 case WM_SYSCOMMAND:
1680 case WM_SETVISIBLE:
1681 case WM_SIZE:
1682 case WM_NEXTMENU:
1683 retvalue = DefMDIChildProcA( hwnd, message, (WPARAM16)wParam, lParam );
1684 goto END;
1686 case WM_SYSCHAR:
1687 if (wParam == '-')
1689 SendMessageW(hwnd,WM_SYSCOMMAND,
1690 (WPARAM)SC_KEYMENU, (LPARAM)(DWORD)VK_SPACE);
1691 retvalue = 0;
1692 goto END;
1695 retvalue = DefWindowProcW(hwnd, message, wParam, lParam);
1696 END:
1697 WIN_ReleaseWndPtr(clientWnd);
1698 return retvalue;
1703 /**********************************************************************
1704 * CreateMDIWindowA [USER32.79] Creates a MDI child in new thread
1705 * FIXME: its in the same thread now
1707 * RETURNS
1708 * Success: Handle to created window
1709 * Failure: NULL
1711 HWND WINAPI CreateMDIWindowA(
1712 LPCSTR lpClassName, /* [in] Pointer to registered child class name */
1713 LPCSTR lpWindowName, /* [in] Pointer to window name */
1714 DWORD dwStyle, /* [in] Window style */
1715 INT X, /* [in] Horizontal position of window */
1716 INT Y, /* [in] Vertical position of window */
1717 INT nWidth, /* [in] Width of window */
1718 INT nHeight, /* [in] Height of window */
1719 HWND hWndParent, /* [in] Handle to parent window */
1720 HINSTANCE hInstance, /* [in] Handle to application instance */
1721 LPARAM lParam) /* [in] Application-defined value */
1723 WARN(mdi,"is only single threaded!\n");
1724 return MDI_CreateMDIWindowA(lpClassName, lpWindowName, dwStyle, X, Y,
1725 nWidth, nHeight, hWndParent, hInstance, lParam);
1728 /**********************************************************************
1729 * MDI_CreateMDIWindowA
1730 * single threaded version of CreateMDIWindowA
1731 * called by CreateWindowEx32A
1733 HWND MDI_CreateMDIWindowA(
1734 LPCSTR lpClassName,
1735 LPCSTR lpWindowName,
1736 DWORD dwStyle,
1737 INT X,
1738 INT Y,
1739 INT nWidth,
1740 INT nHeight,
1741 HWND hWndParent,
1742 HINSTANCE hInstance,
1743 LPARAM lParam)
1745 MDICLIENTINFO* pCi;
1746 MDICREATESTRUCTA cs;
1747 WND *pWnd=WIN_FindWndPtr(hWndParent);
1748 HWND retvalue;
1750 TRACE(mdi, "(%s,%s,%ld,%d,%d,%d,%d,%x,%d,%ld)\n",
1751 debugstr_a(lpClassName),debugstr_a(lpWindowName),dwStyle,X,Y,
1752 nWidth,nHeight,hWndParent,hInstance,lParam);
1754 if(!pWnd){
1755 ERR(mdi," bad hwnd for MDI-client: %d\n",hWndParent);
1756 return 0;
1758 cs.szClass=lpClassName;
1759 cs.szTitle=lpWindowName;
1760 cs.hOwner=hInstance;
1761 cs.x=X;
1762 cs.y=Y;
1763 cs.cx=nWidth;
1764 cs.cy=nHeight;
1765 cs.style=dwStyle;
1766 cs.lParam=lParam;
1768 pCi=(MDICLIENTINFO *)pWnd->wExtra;
1770 retvalue = MDICreateChild(pWnd,pCi,hWndParent,&cs);
1771 WIN_ReleaseWndPtr(pWnd);
1772 return retvalue;
1775 /***************************************
1776 * CreateMDIWindow32W [USER32.80] Creates a MDI child in new thread
1778 * RETURNS
1779 * Success: Handle to created window
1780 * Failure: NULL
1782 HWND WINAPI CreateMDIWindowW(
1783 LPCWSTR lpClassName, /* [in] Pointer to registered child class name */
1784 LPCWSTR lpWindowName, /* [in] Pointer to window name */
1785 DWORD dwStyle, /* [in] Window style */
1786 INT X, /* [in] Horizontal position of window */
1787 INT Y, /* [in] Vertical position of window */
1788 INT nWidth, /* [in] Width of window */
1789 INT nHeight, /* [in] Height of window */
1790 HWND hWndParent, /* [in] Handle to parent window */
1791 HINSTANCE hInstance, /* [in] Handle to application instance */
1792 LPARAM lParam) /* [in] Application-defined value */
1794 FIXME(mdi, "(%s,%s,%ld,%d,%d,%d,%d,%x,%d,%ld): stub\n",
1795 debugstr_w(lpClassName),debugstr_w(lpWindowName),dwStyle,X,Y,
1796 nWidth,nHeight,hWndParent,hInstance,lParam);
1797 return (HWND)NULL;
1801 /******************************************************************************
1802 * CreateMDIWindow32W [USER32.80] Creates a MDI child window
1803 * single threaded version of CreateMDIWindow
1804 * called by CreateWindowEx32W().
1806 HWND MDI_CreateMDIWindowW(
1807 LPCWSTR lpClassName, /* [in] Pointer to registered child class name */
1808 LPCWSTR lpWindowName, /* [in] Pointer to window name */
1809 DWORD dwStyle, /* [in] Window style */
1810 INT X, /* [in] Horizontal position of window */
1811 INT Y, /* [in] Vertical position of window */
1812 INT nWidth, /* [in] Width of window */
1813 INT nHeight, /* [in] Height of window */
1814 HWND hWndParent, /* [in] Handle to parent window */
1815 HINSTANCE hInstance, /* [in] Handle to application instance */
1816 LPARAM lParam) /* [in] Application-defined value */
1818 FIXME(mdi, "(%s,%s,%ld,%d,%d,%d,%d,%x,%d,%ld): stub\n",
1819 debugstr_w(lpClassName),debugstr_w(lpWindowName),dwStyle,X,Y,
1820 nWidth,nHeight,hWndParent,hInstance,lParam);
1821 return (HWND)NULL;
1825 /**********************************************************************
1826 * TranslateMDISysAccel32 (USER32.555)
1828 BOOL WINAPI TranslateMDISysAccel( HWND hwndClient, LPMSG msg )
1830 MSG16 msg16;
1832 STRUCT32_MSG32to16(msg,&msg16);
1833 /* MDICLIENTINFO is still the same for win32 and win16 ... */
1834 return TranslateMDISysAccel16(hwndClient,&msg16);
1838 /**********************************************************************
1839 * TranslateMDISysAccel16 (USER.451)
1841 BOOL16 WINAPI TranslateMDISysAccel16( HWND16 hwndClient, LPMSG16 msg )
1844 if( IsWindow(hwndClient) && (msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN))
1846 MDICLIENTINFO *ci = NULL;
1847 HWND wnd;
1848 WND *clientWnd = WIN_FindWndPtr(hwndClient);
1850 ci = (MDICLIENTINFO*) clientWnd->wExtra;
1851 wnd = ci->hwndActiveChild;
1853 WIN_ReleaseWndPtr(clientWnd);
1855 if( IsWindow(wnd) && !(GetWindowLongA(wnd,GWL_STYLE) & WS_DISABLED) )
1857 WPARAM16 wParam = 0;
1859 /* translate if the Ctrl key is down and Alt not. */
1861 if( (GetKeyState(VK_CONTROL) & 0x8000) &&
1862 !(GetKeyState(VK_MENU) & 0x8000))
1864 switch( msg->wParam )
1866 case VK_F6:
1867 case VK_TAB:
1868 wParam = ( GetKeyState(VK_SHIFT) & 0x8000 )
1869 ? SC_NEXTWINDOW : SC_PREVWINDOW;
1870 break;
1871 case VK_F4:
1872 case VK_RBUTTON:
1873 wParam = SC_CLOSE;
1874 break;
1875 default:
1876 return 0;
1878 TRACE(mdi,"wParam = %04x\n", wParam);
1879 SendMessage16( ci->hwndActiveChild, WM_SYSCOMMAND,
1880 wParam, (LPARAM)msg->wParam);
1881 return 1;
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;