Make sure that all MDI children have the WS_EX_MDICHILD style set.
[wine/dcerpc.git] / windows / mdi.c
blob3547b44f6e6adf932d99ba7a1225f9eb36808b49
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 "scroll.h"
27 #include "struct32.h"
28 #include "tweak.h"
29 #include "debugtools.h"
31 DEFAULT_DEBUG_CHANNEL(mdi)
33 #define MDIF_NEEDUPDATE 0x0001
35 static HBITMAP16 hBmpClose = 0;
36 static HBITMAP16 hBmpRestore = 0;
38 /* ----------------- declarations ----------------- */
39 static void MDI_UpdateFrameText(WND *, HWND, BOOL, LPCSTR);
40 static BOOL MDI_AugmentFrameMenu(MDICLIENTINFO*, WND *, HWND);
41 static BOOL MDI_RestoreFrameMenu(WND *, HWND);
43 static LONG MDI_ChildActivate( WND*, HWND );
45 /* -------- Miscellaneous service functions ----------
47 * MDI_GetChildByID
50 static HWND MDI_GetChildByID(WND* wndPtr, INT id)
52 for (wndPtr = wndPtr->child; wndPtr; wndPtr = wndPtr->next)
53 if (wndPtr->wIDmenu == id) return wndPtr->hwndSelf;
54 return 0;
57 static void MDI_PostUpdate(HWND hwnd, MDICLIENTINFO* ci, WORD recalc)
59 if( !(ci->mdiFlags & MDIF_NEEDUPDATE) )
61 ci->mdiFlags |= MDIF_NEEDUPDATE;
62 PostMessageA( hwnd, WM_MDICALCCHILDSCROLL, 0, 0);
64 ci->sbRecalc = recalc;
67 /**********************************************************************
68 * MDI_MenuModifyItem
70 static BOOL MDI_MenuModifyItem(WND* clientWnd, HWND hWndChild )
72 char buffer[128];
73 MDICLIENTINFO *clientInfo = (MDICLIENTINFO*)clientWnd->wExtra;
74 WND *wndPtr = WIN_FindWndPtr(hWndChild);
75 UINT n = sprintf(buffer, "%d ",
76 wndPtr->wIDmenu - clientInfo->idFirstChild + 1);
77 BOOL bRet = 0;
79 if( !clientInfo->hWindowMenu )
81 bRet = FALSE;
82 goto END;
85 if (wndPtr->text) lstrcpynA(buffer + n, wndPtr->text, sizeof(buffer) - n );
87 n = GetMenuState(clientInfo->hWindowMenu,wndPtr->wIDmenu ,MF_BYCOMMAND);
88 bRet = ModifyMenuA(clientInfo->hWindowMenu , wndPtr->wIDmenu,
89 MF_BYCOMMAND | MF_STRING, wndPtr->wIDmenu, buffer );
90 CheckMenuItem(clientInfo->hWindowMenu ,wndPtr->wIDmenu , n & MF_CHECKED);
91 END:
92 WIN_ReleaseWndPtr(wndPtr);
93 return bRet;
96 /**********************************************************************
97 * MDI_MenuDeleteItem
99 static BOOL MDI_MenuDeleteItem(WND* clientWnd, HWND hWndChild )
101 char buffer[128];
102 MDICLIENTINFO *clientInfo = (MDICLIENTINFO*)clientWnd->wExtra;
103 WND *wndPtr = WIN_FindWndPtr(hWndChild);
104 UINT index = 0,id,n;
105 BOOL retvalue;
107 if( !clientInfo->nActiveChildren ||
108 !clientInfo->hWindowMenu )
110 retvalue = FALSE;
111 goto END;
114 id = wndPtr->wIDmenu;
115 DeleteMenu(clientInfo->hWindowMenu,id,MF_BYCOMMAND);
117 /* walk the rest of MDI children to prevent gaps in the id
118 * sequence and in the menu child list */
120 for( index = id+1; index <= clientInfo->nActiveChildren +
121 clientInfo->idFirstChild; index++ )
123 WND *tmpWnd = WIN_FindWndPtr(MDI_GetChildByID(clientWnd,index));
124 if( !tmpWnd )
126 TRACE("no window for id=%i\n",index);
127 WIN_ReleaseWndPtr(tmpWnd);
128 continue;
131 /* set correct id */
132 tmpWnd->wIDmenu--;
134 n = sprintf(buffer, "%d ",index - clientInfo->idFirstChild);
135 if (tmpWnd->text)
136 lstrcpynA(buffer + n, tmpWnd->text, sizeof(buffer) - n );
138 /* change menu */
139 ModifyMenuA(clientInfo->hWindowMenu ,index ,MF_BYCOMMAND | MF_STRING,
140 index - 1 , buffer );
141 WIN_ReleaseWndPtr(tmpWnd);
143 retvalue = TRUE;
144 END:
145 WIN_ReleaseWndPtr(wndPtr);
146 return retvalue;
149 /**********************************************************************
150 * MDI_GetWindow
152 * returns "activateable" child different from the current or zero
154 static HWND MDI_GetWindow(WND *clientWnd, HWND hWnd, BOOL bNext,
155 DWORD dwStyleMask )
157 MDICLIENTINFO *clientInfo = (MDICLIENTINFO*)clientWnd->wExtra;
158 WND *wndPtr, *pWnd, *pWndLast = NULL;
160 dwStyleMask |= WS_DISABLED | WS_VISIBLE;
161 if( !hWnd ) hWnd = clientInfo->hwndActiveChild;
163 if( !(wndPtr = WIN_FindWndPtr(hWnd)) ) return 0;
165 for ( pWnd = WIN_LockWndPtr(wndPtr->next); ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
167 if (!pWnd ) WIN_UpdateWndPtr(&pWnd,wndPtr->parent->child);
169 if ( pWnd == wndPtr ) break; /* went full circle */
171 if (!pWnd->owner && (pWnd->dwStyle & dwStyleMask) == WS_VISIBLE )
173 pWndLast = pWnd;
174 if ( bNext ) break;
177 WIN_ReleaseWndPtr(wndPtr);
178 WIN_ReleaseWndPtr(pWnd);
179 return pWndLast ? pWndLast->hwndSelf : 0;
182 /**********************************************************************
183 * MDI_CalcDefaultChildPos
185 * It seems that the default height is about 2/3 of the client rect
187 static void MDI_CalcDefaultChildPos( WND* w, WORD n, LPPOINT lpPos,
188 INT delta)
190 INT nstagger;
191 RECT rect = w->rectClient;
192 INT spacing = GetSystemMetrics(SM_CYCAPTION) +
193 GetSystemMetrics(SM_CYFRAME) - 1;
195 if( rect.bottom - rect.top - delta >= spacing )
196 rect.bottom -= delta;
198 nstagger = (rect.bottom - rect.top)/(3 * spacing);
199 lpPos[1].x = (rect.right - rect.left - nstagger * spacing);
200 lpPos[1].y = (rect.bottom - rect.top - nstagger * spacing);
201 lpPos[0].x = lpPos[0].y = spacing * (n%(nstagger+1));
204 /**********************************************************************
205 * MDISetMenu
207 static LRESULT MDISetMenu( HWND hwnd, HMENU hmenuFrame,
208 HMENU hmenuWindow)
210 WND *w = WIN_FindWndPtr(hwnd);
211 MDICLIENTINFO *ci;
212 HWND hwndFrame = GetParent(hwnd);
213 HMENU oldFrameMenu = GetMenu(hwndFrame);
215 TRACE("%04x %04x %04x\n",
216 hwnd, hmenuFrame, hmenuWindow);
218 ci = (MDICLIENTINFO *) w->wExtra;
220 if( ci->hwndChildMaximized && hmenuFrame && hmenuFrame!=oldFrameMenu )
221 MDI_RestoreFrameMenu(w->parent, ci->hwndChildMaximized );
223 if( hmenuWindow && hmenuWindow!=ci->hWindowMenu )
225 /* delete menu items from ci->hWindowMenu
226 * and add them to hmenuWindow */
228 INT i = GetMenuItemCount(ci->hWindowMenu) - 1;
229 INT pos = GetMenuItemCount(hmenuWindow) + 1;
231 AppendMenuA( hmenuWindow, MF_SEPARATOR, 0, NULL);
233 if( ci->nActiveChildren )
235 INT j = i - ci->nActiveChildren + 1;
236 char buffer[100];
237 UINT id,state;
239 for( ; i >= j ; i-- )
241 id = GetMenuItemID(ci->hWindowMenu,i );
242 state = GetMenuState(ci->hWindowMenu,i,MF_BYPOSITION);
244 GetMenuStringA(ci->hWindowMenu, i, buffer, 100, MF_BYPOSITION);
246 DeleteMenu(ci->hWindowMenu, i , MF_BYPOSITION);
247 InsertMenuA(hmenuWindow, pos, MF_BYPOSITION | MF_STRING,
248 id, buffer);
249 CheckMenuItem(hmenuWindow ,pos , MF_BYPOSITION | (state & MF_CHECKED));
253 /* remove separator */
254 DeleteMenu(ci->hWindowMenu, i, MF_BYPOSITION);
256 ci->hWindowMenu = hmenuWindow;
259 if( hmenuFrame && hmenuFrame!=oldFrameMenu)
261 SetMenu(hwndFrame, hmenuFrame);
262 if( ci->hwndChildMaximized )
263 MDI_AugmentFrameMenu(ci, w->parent, ci->hwndChildMaximized );
264 WIN_ReleaseWndPtr(w);
265 return oldFrameMenu;
267 WIN_ReleaseWndPtr(w);
268 return 0;
271 /**********************************************************************
272 * MDIRefreshMenu
274 static LRESULT MDIRefreshMenu( HWND hwnd, HMENU hmenuFrame,
275 HMENU hmenuWindow)
277 HWND hwndFrame = GetParent(hwnd);
278 HMENU oldFrameMenu = GetMenu(hwndFrame);
280 TRACE("%04x %04x %04x\n",
281 hwnd, hmenuFrame, hmenuWindow);
283 FIXME("partially function stub\n");
285 return oldFrameMenu;
289 /* ------------------ MDI child window functions ---------------------- */
292 /**********************************************************************
293 * MDICreateChild
295 static HWND MDICreateChild( WND *w, MDICLIENTINFO *ci, HWND parent,
296 LPMDICREATESTRUCTA cs )
298 POINT pos[2];
299 DWORD style = cs->style | (WS_CHILD | WS_CLIPSIBLINGS);
300 HWND hwnd, hwndMax = 0;
301 WORD wIDmenu = ci->idFirstChild + ci->nActiveChildren;
302 char lpstrDef[]="junk!";
304 TRACE("origin %i,%i - dim %i,%i, style %08x\n",
305 cs->x, cs->y, cs->cx, cs->cy, (unsigned)cs->style);
306 /* calculate placement */
307 MDI_CalcDefaultChildPos(w, ci->nTotalCreated++, pos, 0);
309 if (cs->cx == CW_USEDEFAULT || !cs->cx) cs->cx = pos[1].x;
310 if (cs->cy == CW_USEDEFAULT || !cs->cy) cs->cy = pos[1].y;
312 if( cs->x == CW_USEDEFAULT )
314 cs->x = pos[0].x;
315 cs->y = pos[0].y;
318 /* restore current maximized child */
319 if( style & WS_VISIBLE && ci->hwndChildMaximized )
321 if( style & WS_MAXIMIZE )
322 SendMessageA(w->hwndSelf, WM_SETREDRAW, FALSE, 0L );
323 hwndMax = ci->hwndChildMaximized;
324 ShowWindow( hwndMax, SW_SHOWNOACTIVATE );
325 if( style & WS_MAXIMIZE )
326 SendMessageA(w->hwndSelf, WM_SETREDRAW, TRUE, 0L );
329 /* this menu is needed to set a check mark in MDI_ChildActivate */
330 AppendMenuA(ci->hWindowMenu ,MF_STRING ,wIDmenu, lpstrDef );
332 ci->nActiveChildren++;
334 /* fix window style */
335 if( !(w->dwStyle & MDIS_ALLCHILDSTYLES) )
337 style &= (WS_CHILD | WS_CLIPSIBLINGS | WS_MINIMIZE | WS_MAXIMIZE |
338 WS_CLIPCHILDREN | WS_DISABLED | WS_VSCROLL | WS_HSCROLL );
339 style |= (WS_VISIBLE | WS_OVERLAPPEDWINDOW);
342 if( w->flags & WIN_ISWIN32 )
344 hwnd = CreateWindowA( cs->szClass, cs->szTitle, style,
345 cs->x, cs->y, cs->cx, cs->cy, parent,
346 (HMENU16)wIDmenu, cs->hOwner, cs );
348 else
350 MDICREATESTRUCT16 *cs16;
351 LPSTR title, cls;
353 cs16 = SEGPTR_NEW(MDICREATESTRUCT16);
354 STRUCT32_MDICREATESTRUCT32Ato16( cs, cs16 );
355 title = SEGPTR_STRDUP( cs->szTitle );
356 cls = SEGPTR_STRDUP( cs->szClass );
357 cs16->szTitle = SEGPTR_GET(title);
358 cs16->szClass = SEGPTR_GET(cls);
360 hwnd = CreateWindow16( cs->szClass, cs->szTitle, style,
361 cs16->x, cs16->y, cs16->cx, cs16->cy, parent,
362 (HMENU)wIDmenu, cs16->hOwner,
363 (LPVOID)SEGPTR_GET(cs16) );
364 SEGPTR_FREE( title );
365 SEGPTR_FREE( cls );
366 SEGPTR_FREE( cs16 );
369 /* MDI windows are WS_CHILD so they won't be activated by CreateWindow */
371 if (hwnd)
373 WND* wnd = WIN_FindWndPtr( hwnd );
375 /* All MDI child windows have the WS_EX_MDICHILD style */
376 wnd->dwExStyle |= WS_EX_MDICHILD;
378 MDI_MenuModifyItem(w ,hwnd);
379 if( wnd->dwStyle & WS_MINIMIZE && ci->hwndActiveChild )
380 ShowWindow( hwnd, SW_SHOWMINNOACTIVE );
381 else
383 /* WS_VISIBLE is clear if a) the MDI client has
384 * MDIS_ALLCHILDSTYLES style and 2) the flag is cleared in the
385 * MDICreateStruct. If so the created window is not shown nor
386 * activated.
388 int showflag=wnd->dwStyle & WS_VISIBLE;
389 /* clear visible flag, otherwise SetWindoPos32 ignores
390 * the SWP_SHOWWINDOW command.
392 wnd->dwStyle &= ~WS_VISIBLE;
393 if(showflag){
394 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE );
396 /* Set maximized state here in case hwnd didn't receive WM_SIZE
397 * during CreateWindow - bad!
400 if((wnd->dwStyle & WS_MAXIMIZE) && !ci->hwndChildMaximized )
402 ci->hwndChildMaximized = wnd->hwndSelf;
403 MDI_AugmentFrameMenu( ci, w->parent, hwnd );
404 MDI_UpdateFrameText( w->parent, ci->self, MDI_REPAINTFRAME, NULL );
406 }else
407 /* needed, harmless ? */
408 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE );
411 WIN_ReleaseWndPtr(wnd);
412 TRACE("created child - %04x\n",hwnd);
414 else
416 ci->nActiveChildren--;
417 DeleteMenu(ci->hWindowMenu,wIDmenu,MF_BYCOMMAND);
418 if( IsWindow(hwndMax) )
419 ShowWindow(hwndMax, SW_SHOWMAXIMIZED);
422 return hwnd;
425 /**********************************************************************
426 * MDI_ChildGetMinMaxInfo
428 * Note: The rule here is that client rect of the maximized MDI child
429 * is equal to the client rect of the MDI client window.
431 static void MDI_ChildGetMinMaxInfo( WND* clientWnd, HWND hwnd,
432 MINMAXINFO16* lpMinMax )
434 WND* childWnd = WIN_FindWndPtr(hwnd);
435 RECT rect = clientWnd->rectClient;
437 MapWindowPoints( clientWnd->parent->hwndSelf,
438 ((MDICLIENTINFO*)clientWnd->wExtra)->self, (LPPOINT)&rect, 2);
439 AdjustWindowRectEx( &rect, childWnd->dwStyle, 0, childWnd->dwExStyle );
441 lpMinMax->ptMaxSize.x = rect.right -= rect.left;
442 lpMinMax->ptMaxSize.y = rect.bottom -= rect.top;
444 lpMinMax->ptMaxPosition.x = rect.left;
445 lpMinMax->ptMaxPosition.y = rect.top;
447 WIN_ReleaseWndPtr(childWnd);
449 TRACE("max rect (%i,%i - %i, %i)\n",
450 rect.left,rect.top,rect.right,rect.bottom);
454 /**********************************************************************
455 * MDI_SwitchActiveChild
457 * Note: SetWindowPos sends WM_CHILDACTIVATE to the child window that is
458 * being activated
460 static void MDI_SwitchActiveChild( HWND clientHwnd, HWND childHwnd,
461 BOOL bNextWindow )
463 WND *w = WIN_FindWndPtr(clientHwnd);
464 HWND hwndTo = 0;
465 HWND hwndPrev = 0;
466 MDICLIENTINFO *ci;
468 hwndTo = MDI_GetWindow(w, childHwnd, bNextWindow, 0);
470 ci = (MDICLIENTINFO *) w->wExtra;
472 TRACE("from %04x, to %04x\n",childHwnd,hwndTo);
474 if ( !hwndTo ) goto END; /* no window to switch to */
476 hwndPrev = ci->hwndActiveChild;
478 if ( hwndTo != hwndPrev )
480 BOOL bOptimize = 0;
482 if( ci->hwndChildMaximized )
484 bOptimize = 1;
485 w->dwStyle &= ~WS_VISIBLE;
488 SetWindowPos( hwndTo, HWND_TOP, 0, 0, 0, 0,
489 SWP_NOMOVE | SWP_NOSIZE );
491 if( bNextWindow && hwndPrev )
492 SetWindowPos( hwndPrev, HWND_BOTTOM, 0, 0, 0, 0,
493 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE );
494 if( bOptimize )
495 ShowWindow( clientHwnd, SW_SHOW );
497 END:
498 WIN_ReleaseWndPtr(w);
502 /**********************************************************************
503 * MDIDestroyChild
505 static LRESULT MDIDestroyChild( WND *w_parent, MDICLIENTINFO *ci,
506 HWND parent, HWND child,
507 BOOL flagDestroy )
509 WND *childPtr = WIN_FindWndPtr(child);
511 if( childPtr )
513 if( child == ci->hwndActiveChild )
515 MDI_SwitchActiveChild(parent, child, TRUE);
517 if( child == ci->hwndActiveChild )
519 ShowWindow( child, SW_HIDE);
520 if( child == ci->hwndChildMaximized )
522 MDI_RestoreFrameMenu(w_parent->parent, child);
523 ci->hwndChildMaximized = 0;
524 MDI_UpdateFrameText(w_parent->parent,parent,TRUE,NULL);
527 MDI_ChildActivate(w_parent, 0);
530 MDI_MenuDeleteItem(w_parent, child);
532 WIN_ReleaseWndPtr(childPtr);
534 ci->nActiveChildren--;
536 TRACE("child destroyed - %04x\n",child);
538 if (flagDestroy)
540 MDI_PostUpdate(GetParent(child), ci, SB_BOTH+1);
541 DestroyWindow(child);
545 return 0;
549 /**********************************************************************
550 * MDI_ChildActivate
552 * Note: hWndChild is NULL when last child is being destroyed
554 static LONG MDI_ChildActivate( WND *clientPtr, HWND hWndChild )
556 MDICLIENTINFO *clientInfo = (MDICLIENTINFO*)clientPtr->wExtra;
557 HWND prevActiveWnd = clientInfo->hwndActiveChild;
558 WND *wndPtr = WIN_FindWndPtr( hWndChild );
559 WND *wndPrev = WIN_FindWndPtr( prevActiveWnd );
560 BOOL isActiveFrameWnd = 0;
561 LONG retvalue;
563 if( wndPtr )
565 if( wndPtr->dwStyle & WS_DISABLED )
567 retvalue = 0L;
568 goto END;
572 TRACE("%04x\n", hWndChild);
574 if( GetActiveWindow() == clientPtr->parent->hwndSelf )
575 isActiveFrameWnd = TRUE;
577 /* deactivate prev. active child */
578 if( wndPrev )
580 wndPrev->dwStyle |= WS_SYSMENU;
581 SendMessageA( prevActiveWnd, WM_NCACTIVATE, FALSE, 0L );
582 SendMessageA( prevActiveWnd, WM_MDIACTIVATE, (WPARAM)prevActiveWnd,
583 (LPARAM)hWndChild);
584 /* uncheck menu item */
585 if( clientInfo->hWindowMenu )
586 CheckMenuItem( clientInfo->hWindowMenu,
587 wndPrev->wIDmenu, 0);
590 /* set appearance */
591 if( clientInfo->hwndChildMaximized )
593 if( clientInfo->hwndChildMaximized != hWndChild ) {
594 if( hWndChild ) {
595 clientInfo->hwndActiveChild = hWndChild;
596 ShowWindow( hWndChild, SW_SHOWMAXIMIZED);
597 } else
598 ShowWindow( clientInfo->hwndActiveChild, SW_SHOWNORMAL );
602 clientInfo->hwndActiveChild = hWndChild;
604 /* check if we have any children left */
605 if( !hWndChild )
607 if( isActiveFrameWnd )
608 SetFocus( clientInfo->self );
609 retvalue = 0;
610 goto END;
613 /* check menu item */
614 if( clientInfo->hWindowMenu )
615 CheckMenuItem( clientInfo->hWindowMenu,
616 wndPtr->wIDmenu, MF_CHECKED);
618 /* bring active child to the top */
619 SetWindowPos( hWndChild, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
621 if( isActiveFrameWnd )
623 SendMessageA( hWndChild, WM_NCACTIVATE, TRUE, 0L);
624 if( GetFocus() == clientInfo->self )
625 SendMessageA( clientInfo->self, WM_SETFOCUS,
626 (WPARAM)clientInfo->self, 0L );
627 else
628 SetFocus( clientInfo->self );
630 SendMessageA( hWndChild, WM_MDIACTIVATE, (WPARAM)prevActiveWnd,
631 (LPARAM)hWndChild );
632 retvalue = 1;
633 END:
634 WIN_ReleaseWndPtr(wndPtr);
635 WIN_ReleaseWndPtr(wndPrev);
636 return retvalue;
639 /* -------------------- MDI client window functions ------------------- */
641 /**********************************************************************
642 * CreateMDIMenuBitmap
644 static HBITMAP16 CreateMDIMenuBitmap(void)
646 HDC hDCSrc = CreateCompatibleDC(0);
647 HDC hDCDest = CreateCompatibleDC(hDCSrc);
648 HBITMAP16 hbClose = LoadBitmap16(0, MAKEINTRESOURCE16(OBM_CLOSE) );
649 HBITMAP16 hbCopy;
650 HANDLE16 hobjSrc, hobjDest;
652 hobjSrc = SelectObject(hDCSrc, hbClose);
653 hbCopy = CreateCompatibleBitmap(hDCSrc,GetSystemMetrics(SM_CXSIZE),GetSystemMetrics(SM_CYSIZE));
654 hobjDest = SelectObject(hDCDest, hbCopy);
656 BitBlt(hDCDest, 0, 0, GetSystemMetrics(SM_CXSIZE), GetSystemMetrics(SM_CYSIZE),
657 hDCSrc, GetSystemMetrics(SM_CXSIZE), 0, SRCCOPY);
659 SelectObject(hDCSrc, hobjSrc);
660 DeleteObject(hbClose);
661 DeleteDC(hDCSrc);
663 hobjSrc = SelectObject( hDCDest, GetStockObject(BLACK_PEN) );
665 MoveToEx( hDCDest, GetSystemMetrics(SM_CXSIZE) - 1, 0, NULL );
666 LineTo( hDCDest, GetSystemMetrics(SM_CXSIZE) - 1, GetSystemMetrics(SM_CYSIZE) - 1);
668 SelectObject(hDCDest, hobjSrc );
669 SelectObject(hDCDest, hobjDest);
670 DeleteDC(hDCDest);
672 return hbCopy;
675 /**********************************************************************
676 * MDICascade
678 static LONG MDICascade(WND* clientWnd, MDICLIENTINFO *ci)
680 WND** ppWnd;
681 UINT total;
683 if (ci->hwndChildMaximized)
684 SendMessageA( clientWnd->hwndSelf, WM_MDIRESTORE,
685 (WPARAM)ci->hwndChildMaximized, 0);
687 if (ci->nActiveChildren == 0) return 0;
689 if ((ppWnd = WIN_BuildWinArray(clientWnd, BWA_SKIPHIDDEN | BWA_SKIPOWNED |
690 BWA_SKIPICONIC, &total)))
692 WND** heapPtr = ppWnd;
693 if( total )
695 INT delta = 0, n = 0;
696 POINT pos[2];
697 if( total < ci->nActiveChildren )
698 delta = GetSystemMetrics(SM_CYICONSPACING) +
699 GetSystemMetrics(SM_CYICON);
701 /* walk the list (backwards) and move windows */
702 while (*ppWnd) ppWnd++;
703 while (ppWnd != heapPtr)
705 ppWnd--;
706 TRACE("move %04x to (%ld,%ld) size [%ld,%ld]\n",
707 (*ppWnd)->hwndSelf, pos[0].x, pos[0].y, pos[1].x, pos[1].y);
709 MDI_CalcDefaultChildPos(clientWnd, n++, pos, delta);
710 SetWindowPos( (*ppWnd)->hwndSelf, 0, pos[0].x, pos[0].y,
711 pos[1].x, pos[1].y,
712 SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER);
715 WIN_ReleaseWinArray(heapPtr);
718 if( total < ci->nActiveChildren )
719 ArrangeIconicWindows( clientWnd->hwndSelf );
720 return 0;
723 /**********************************************************************
724 * MDITile
726 static void MDITile( WND* wndClient, MDICLIENTINFO *ci, WPARAM wParam )
728 WND** ppWnd;
729 UINT total = 0;
731 if (ci->hwndChildMaximized)
732 SendMessageA( wndClient->hwndSelf, WM_MDIRESTORE,
733 (WPARAM)ci->hwndChildMaximized, 0);
735 if (ci->nActiveChildren == 0) return;
737 ppWnd = WIN_BuildWinArray(wndClient, BWA_SKIPHIDDEN | BWA_SKIPOWNED | BWA_SKIPICONIC |
738 ((wParam & MDITILE_SKIPDISABLED)? BWA_SKIPDISABLED : 0), &total );
740 TRACE("%u windows to tile\n", total);
742 if( ppWnd )
744 WND** heapPtr = ppWnd;
746 if( total )
748 RECT rect;
749 int x, y, xsize, ysize;
750 int rows, columns, r, c, i;
752 GetClientRect(wndClient->hwndSelf,&rect);
753 rows = (int) sqrt((double)total);
754 columns = total / rows;
756 if( wParam & MDITILE_HORIZONTAL ) /* version >= 3.1 */
758 i = rows;
759 rows = columns; /* exchange r and c */
760 columns = i;
763 if( total != ci->nActiveChildren)
765 y = rect.bottom - 2 * GetSystemMetrics(SM_CYICONSPACING) - GetSystemMetrics(SM_CYICON);
766 rect.bottom = ( y - GetSystemMetrics(SM_CYICON) < rect.top )? rect.bottom: y;
769 ysize = rect.bottom / rows;
770 xsize = rect.right / columns;
772 for (x = i = 0, c = 1; c <= columns && *ppWnd; c++)
774 if (c == columns)
776 rows = total - i;
777 ysize = rect.bottom / rows;
780 y = 0;
781 for (r = 1; r <= rows && *ppWnd; r++, i++)
783 SetWindowPos((*ppWnd)->hwndSelf, 0, x, y, xsize, ysize,
784 SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER);
785 y += ysize;
786 ppWnd++;
788 x += xsize;
791 WIN_ReleaseWinArray(heapPtr);
794 if( total < ci->nActiveChildren ) ArrangeIconicWindows( wndClient->hwndSelf );
797 /* ----------------------- Frame window ---------------------------- */
800 /**********************************************************************
801 * MDI_AugmentFrameMenu
803 static BOOL MDI_AugmentFrameMenu( MDICLIENTINFO* ci, WND *frame,
804 HWND hChild )
806 WND* child = WIN_FindWndPtr(hChild);
807 HMENU hSysPopup = 0;
808 HBITMAP hSysMenuBitmap = 0;
810 TRACE("frame %p,child %04x\n",frame,hChild);
812 if( !frame->wIDmenu || !child->hSysMenu )
814 WIN_ReleaseWndPtr(child);
815 return 0;
817 WIN_ReleaseWndPtr(child);
819 /* create a copy of sysmenu popup and insert it into frame menu bar */
821 if (!(hSysPopup = LoadMenuA(GetModuleHandleA("USER32"), "SYSMENU")))
822 return 0;
824 TRACE("\tgot popup %04x in sysmenu %04x\n",
825 hSysPopup, child->hSysMenu);
827 AppendMenuA(frame->wIDmenu,MF_HELP | MF_BITMAP,
828 SC_MINIMIZE, (LPSTR)(DWORD)HBMMENU_MBAR_MINIMIZE ) ;
829 AppendMenuA(frame->wIDmenu,MF_HELP | MF_BITMAP,
830 SC_RESTORE, (LPSTR)(DWORD)HBMMENU_MBAR_RESTORE );
832 /* In Win 95 look, the system menu is replaced by the child icon */
834 if(TWEAK_WineLook > WIN31_LOOK)
836 HICON hIcon = GetClassLongA(hChild, GCL_HICONSM);
837 if (!hIcon)
838 hIcon = GetClassLongA(hChild, GCL_HICON);
839 if (hIcon)
841 HDC hMemDC;
842 HBITMAP hBitmap, hOldBitmap;
843 HBRUSH hBrush;
844 HDC hdc = GetDC(hChild);
846 if (hdc)
848 int cx, cy;
849 cx = GetSystemMetrics(SM_CXSMICON);
850 cy = GetSystemMetrics(SM_CYSMICON);
851 hMemDC = CreateCompatibleDC(hdc);
852 hBitmap = CreateCompatibleBitmap(hdc, cx, cy);
853 hOldBitmap = SelectObject(hMemDC, hBitmap);
854 SetMapMode(hMemDC, MM_TEXT);
855 hBrush = CreateSolidBrush(GetSysColor(COLOR_MENU));
856 DrawIconEx(hMemDC, 0, 0, hIcon, cx, cy, 0, hBrush, DI_NORMAL);
857 SelectObject (hMemDC, hOldBitmap);
858 DeleteObject(hBrush);
859 DeleteDC(hMemDC);
860 ReleaseDC(hChild, hdc);
861 hSysMenuBitmap = hBitmap;
865 else
866 hSysMenuBitmap = hBmpClose;
868 if( !InsertMenuA(frame->wIDmenu,0,MF_BYPOSITION | MF_BITMAP | MF_POPUP,
869 hSysPopup, (LPSTR)(DWORD)hSysMenuBitmap))
871 TRACE("not inserted\n");
872 DestroyMenu(hSysPopup);
873 return 0;
876 /* The close button is only present in Win 95 look */
877 if(TWEAK_WineLook > WIN31_LOOK)
879 AppendMenuA(frame->wIDmenu,MF_HELP | MF_BITMAP,
880 SC_CLOSE, (LPSTR)(DWORD)HBMMENU_MBAR_CLOSE );
883 EnableMenuItem(hSysPopup, SC_SIZE, MF_BYCOMMAND | MF_GRAYED);
884 EnableMenuItem(hSysPopup, SC_MOVE, MF_BYCOMMAND | MF_GRAYED);
885 EnableMenuItem(hSysPopup, SC_MAXIMIZE, MF_BYCOMMAND | MF_GRAYED);
886 SetMenuDefaultItem(hSysPopup, SC_CLOSE, FALSE);
888 /* redraw menu */
889 DrawMenuBar(frame->hwndSelf);
891 return 1;
894 /**********************************************************************
895 * MDI_RestoreFrameMenu
897 static BOOL MDI_RestoreFrameMenu( WND *frameWnd, HWND hChild )
899 MENUITEMINFOA menuInfo;
900 INT nItems = GetMenuItemCount(frameWnd->wIDmenu) - 1;
901 UINT iId = GetMenuItemID(frameWnd->wIDmenu,nItems) ;
903 TRACE("frameWnd %p,child %04x\n",frameWnd,hChild);
905 if(!(iId == SC_RESTORE || iId == SC_CLOSE) )
906 return 0;
909 * Remove the system menu, If that menu is the icon of the window
910 * as it is in win95, we have to delete the bitmap.
912 menuInfo.cbSize = sizeof(MENUITEMINFOA);
913 menuInfo.fMask = MIIM_DATA | MIIM_TYPE;
915 GetMenuItemInfoA(frameWnd->wIDmenu,
917 TRUE,
918 &menuInfo);
920 RemoveMenu(frameWnd->wIDmenu,0,MF_BYPOSITION);
922 if ( (menuInfo.fType & MFT_BITMAP) &&
923 (LOWORD(menuInfo.dwTypeData)!=0) &&
924 (LOWORD(menuInfo.dwTypeData)!=hBmpClose) )
926 DeleteObject((HBITMAP)LOWORD(menuInfo.dwTypeData));
929 if(TWEAK_WineLook > WIN31_LOOK)
931 /* close */
932 DeleteMenu(frameWnd->wIDmenu,GetMenuItemCount(frameWnd->wIDmenu) - 1,MF_BYPOSITION);
934 /* restore */
935 DeleteMenu(frameWnd->wIDmenu,GetMenuItemCount(frameWnd->wIDmenu) - 1,MF_BYPOSITION);
936 /* minimize */
937 DeleteMenu(frameWnd->wIDmenu,GetMenuItemCount(frameWnd->wIDmenu) - 1,MF_BYPOSITION);
939 DrawMenuBar(frameWnd->hwndSelf);
941 return 1;
945 /**********************************************************************
946 * MDI_UpdateFrameText
948 * used when child window is maximized/restored
950 * Note: lpTitle can be NULL
952 static void MDI_UpdateFrameText( WND *frameWnd, HWND hClient,
953 BOOL repaint, LPCSTR lpTitle )
955 char lpBuffer[MDI_MAXTITLELENGTH+1];
956 WND* clientWnd = WIN_FindWndPtr(hClient);
957 MDICLIENTINFO *ci = (MDICLIENTINFO *) clientWnd->wExtra;
959 TRACE("repaint %i, frameText %s\n", repaint, (lpTitle)?lpTitle:"NULL");
961 if (!clientWnd)
962 return;
964 if (!ci)
966 WIN_ReleaseWndPtr(clientWnd);
967 return;
970 /* store new "default" title if lpTitle is not NULL */
971 if (lpTitle)
973 if (ci->frameTitle) HeapFree( SystemHeap, 0, ci->frameTitle );
974 ci->frameTitle = HEAP_strdupA( SystemHeap, 0, lpTitle );
977 if (ci->frameTitle)
979 WND* childWnd = WIN_FindWndPtr( ci->hwndChildMaximized );
981 if( childWnd && childWnd->text )
983 /* combine frame title and child title if possible */
985 LPCSTR lpBracket = " - [";
986 int i_frame_text_length = strlen(ci->frameTitle);
987 int i_child_text_length = strlen(childWnd->text);
989 lstrcpynA( lpBuffer, ci->frameTitle, MDI_MAXTITLELENGTH);
991 if( i_frame_text_length + 6 < MDI_MAXTITLELENGTH )
993 strcat( lpBuffer, lpBracket );
995 if( i_frame_text_length + i_child_text_length + 6 < MDI_MAXTITLELENGTH )
997 strcat( lpBuffer, childWnd->text );
998 strcat( lpBuffer, "]" );
1000 else
1002 lstrcpynA( lpBuffer + i_frame_text_length + 4,
1003 childWnd->text, MDI_MAXTITLELENGTH - i_frame_text_length - 5 );
1004 strcat( lpBuffer, "]" );
1008 else
1010 strncpy(lpBuffer, ci->frameTitle, MDI_MAXTITLELENGTH );
1011 lpBuffer[MDI_MAXTITLELENGTH]='\0';
1013 WIN_ReleaseWndPtr(childWnd);
1016 else
1017 lpBuffer[0] = '\0';
1019 DEFWND_SetText( frameWnd, lpBuffer );
1020 if( repaint == MDI_REPAINTFRAME)
1021 SetWindowPos( frameWnd->hwndSelf, 0,0,0,0,0, SWP_FRAMECHANGED |
1022 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER );
1024 WIN_ReleaseWndPtr(clientWnd);
1029 /* ----------------------------- Interface ---------------------------- */
1032 /**********************************************************************
1033 * MDIClientWndProc
1035 * This function handles all MDI requests.
1037 LRESULT WINAPI MDIClientWndProc( HWND hwnd, UINT message, WPARAM wParam,
1038 LPARAM lParam )
1040 LPCREATESTRUCTA cs;
1041 MDICLIENTINFO *ci;
1042 RECT rect;
1043 WND *w, *frameWnd;
1044 INT nItems;
1045 LRESULT retvalue;
1047 if ( ( w = WIN_FindWndPtr(hwnd) ) == NULL )
1048 return 0;
1050 if ( ( frameWnd = WIN_LockWndPtr(w->parent) ) == NULL ) {
1051 WIN_ReleaseWndPtr(w);
1052 return 0;
1055 ci = (MDICLIENTINFO *) w->wExtra;
1057 switch (message)
1059 case WM_CREATE:
1061 cs = (LPCREATESTRUCTA)lParam;
1063 /* Translation layer doesn't know what's in the cs->lpCreateParams
1064 * so we have to keep track of what environment we're in. */
1066 if( w->flags & WIN_ISWIN32 )
1068 #define ccs ((LPCLIENTCREATESTRUCT)cs->lpCreateParams)
1069 ci->hWindowMenu = ccs->hWindowMenu;
1070 ci->idFirstChild = ccs->idFirstChild;
1071 #undef ccs
1073 else
1075 LPCLIENTCREATESTRUCT16 ccs = (LPCLIENTCREATESTRUCT16)
1076 PTR_SEG_TO_LIN(cs->lpCreateParams);
1077 ci->hWindowMenu = ccs->hWindowMenu;
1078 ci->idFirstChild = ccs->idFirstChild;
1081 ci->hwndChildMaximized = 0;
1082 ci->nActiveChildren = 0;
1083 ci->nTotalCreated = 0;
1084 ci->frameTitle = NULL;
1085 ci->mdiFlags = 0;
1086 ci->self = hwnd;
1087 w->dwStyle |= WS_CLIPCHILDREN;
1089 if (!hBmpClose)
1091 hBmpClose = CreateMDIMenuBitmap();
1092 hBmpRestore = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_RESTORE) );
1094 MDI_UpdateFrameText(frameWnd, hwnd, MDI_NOFRAMEREPAINT,frameWnd->text);
1096 AppendMenuA( ci->hWindowMenu, MF_SEPARATOR, 0, NULL );
1098 GetClientRect(frameWnd->hwndSelf, &rect);
1099 NC_HandleNCCalcSize( w, &rect );
1100 w->rectClient = rect;
1102 TRACE("Client created - hwnd = %04x, idFirst = %u\n",
1103 hwnd, ci->idFirstChild );
1105 retvalue = 0;
1106 goto END;
1108 case WM_DESTROY:
1109 if( ci->hwndChildMaximized ) MDI_RestoreFrameMenu(w, frameWnd->hwndSelf);
1110 if((nItems = GetMenuItemCount(ci->hWindowMenu)) > 0)
1112 ci->idFirstChild = nItems - 1;
1113 ci->nActiveChildren++; /* to delete a separator */
1114 while( ci->nActiveChildren-- )
1115 DeleteMenu(ci->hWindowMenu,MF_BYPOSITION,ci->idFirstChild--);
1117 retvalue = 0;
1118 goto END;
1120 case WM_MDIACTIVATE:
1121 if( ci->hwndActiveChild != (HWND)wParam )
1122 SetWindowPos((HWND)wParam, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE);
1123 retvalue = 0;
1124 goto END;
1126 case WM_MDICASCADE:
1127 retvalue = MDICascade(w, ci);
1128 goto END;
1130 case WM_MDICREATE:
1131 if (lParam) retvalue = MDICreateChild( w, ci, hwnd,
1132 (MDICREATESTRUCTA*)lParam );
1133 else retvalue = 0;
1134 goto END;
1136 case WM_MDIDESTROY:
1137 retvalue = MDIDestroyChild( w, ci, hwnd, (HWND)wParam, TRUE );
1138 goto END;
1140 case WM_MDIGETACTIVE:
1141 if (lParam) *(BOOL *)lParam = (ci->hwndChildMaximized > 0);
1142 retvalue = ci->hwndActiveChild;
1143 goto END;
1145 case WM_MDIICONARRANGE:
1146 ci->mdiFlags |= MDIF_NEEDUPDATE;
1147 ArrangeIconicWindows(hwnd);
1148 ci->sbRecalc = SB_BOTH+1;
1149 SendMessageA(hwnd, WM_MDICALCCHILDSCROLL, 0, 0L);
1150 retvalue = 0;
1151 goto END;
1153 case WM_MDIMAXIMIZE:
1154 ShowWindow( (HWND)wParam, SW_MAXIMIZE );
1155 retvalue = 0;
1156 goto END;
1158 case WM_MDINEXT: /* lParam != 0 means previous window */
1159 MDI_SwitchActiveChild(hwnd, (HWND)wParam, (lParam)? FALSE : TRUE );
1160 break;
1162 case WM_MDIRESTORE:
1163 SendMessageA( (HWND)wParam, WM_SYSCOMMAND, SC_RESTORE, 0);
1164 retvalue = 0;
1165 goto END;
1167 case WM_MDISETMENU:
1168 retvalue = MDISetMenu( hwnd, (HMENU)wParam, (HMENU)lParam );
1169 goto END;
1170 case WM_MDIREFRESHMENU:
1171 retvalue = MDIRefreshMenu( hwnd, (HMENU)wParam, (HMENU)lParam );
1172 goto END;
1174 case WM_MDITILE:
1175 ci->mdiFlags |= MDIF_NEEDUPDATE;
1176 ShowScrollBar(hwnd,SB_BOTH,FALSE);
1177 MDITile(w, ci, wParam);
1178 ci->mdiFlags &= ~MDIF_NEEDUPDATE;
1179 retvalue = 0;
1180 goto END;
1182 case WM_VSCROLL:
1183 case WM_HSCROLL:
1184 ci->mdiFlags |= MDIF_NEEDUPDATE;
1185 ScrollChildren(hwnd, message, wParam, lParam);
1186 ci->mdiFlags &= ~MDIF_NEEDUPDATE;
1187 retvalue = 0;
1188 goto END;
1190 case WM_SETFOCUS:
1191 if( ci->hwndActiveChild )
1193 WND* pw = WIN_FindWndPtr( ci->hwndActiveChild );
1194 if( !(pw->dwStyle & WS_MINIMIZE) )
1195 SetFocus( ci->hwndActiveChild );
1196 WIN_ReleaseWndPtr(pw);
1198 retvalue = 0;
1199 goto END;
1201 case WM_NCACTIVATE:
1202 if( ci->hwndActiveChild )
1203 SendMessageA(ci->hwndActiveChild, message, wParam, lParam);
1204 break;
1206 case WM_PARENTNOTIFY:
1207 if (LOWORD(wParam) == WM_LBUTTONDOWN)
1209 POINT16 pt = MAKEPOINT16(lParam);
1210 HWND16 child = ChildWindowFromPoint16(hwnd, pt);
1212 TRACE("notification from %04x (%i,%i)\n",child,pt.x,pt.y);
1214 if( child && child != hwnd && child != ci->hwndActiveChild )
1215 SetWindowPos(child, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE );
1217 retvalue = 0;
1218 goto END;
1220 case WM_SIZE:
1221 if( IsWindow(ci->hwndChildMaximized) )
1223 WND* child = WIN_FindWndPtr(ci->hwndChildMaximized);
1224 RECT rect;
1226 rect.left = 0;
1227 rect.top = 0;
1228 rect.right = LOWORD(lParam);
1229 rect.bottom = HIWORD(lParam);
1231 AdjustWindowRectEx(&rect, child->dwStyle, 0, child->dwExStyle);
1232 MoveWindow(ci->hwndChildMaximized, rect.left, rect.top,
1233 rect.right - rect.left, rect.bottom - rect.top, 1);
1234 WIN_ReleaseWndPtr(child);
1236 else
1237 MDI_PostUpdate(hwnd, ci, SB_BOTH+1);
1239 break;
1241 case WM_MDICALCCHILDSCROLL:
1242 if( (ci->mdiFlags & MDIF_NEEDUPDATE) && ci->sbRecalc )
1244 CalcChildScroll16(hwnd, ci->sbRecalc-1);
1245 ci->sbRecalc = 0;
1246 ci->mdiFlags &= ~MDIF_NEEDUPDATE;
1248 retvalue = 0;
1249 goto END;
1252 retvalue = DefWindowProcA( hwnd, message, wParam, lParam );
1253 END:
1254 WIN_ReleaseWndPtr(w);
1255 WIN_ReleaseWndPtr(frameWnd);
1256 return retvalue;
1260 /***********************************************************************
1261 * DefFrameProc16 (USER.445)
1263 LRESULT WINAPI DefFrameProc16( HWND16 hwnd, HWND16 hwndMDIClient,
1264 UINT16 message, WPARAM16 wParam, LPARAM lParam )
1266 HWND16 childHwnd;
1267 MDICLIENTINFO* ci;
1268 WND* wndPtr;
1270 if (hwndMDIClient)
1272 switch (message)
1274 case WM_COMMAND:
1275 wndPtr = WIN_FindWndPtr(hwndMDIClient);
1277 if (!wndPtr) {
1278 ERR("null wndPtr for mdi window hwndMDIClient=%04x\n",
1279 hwndMDIClient);
1280 return 0;
1283 ci = (MDICLIENTINFO*)wndPtr->wExtra;
1285 /* check for possible syscommands for maximized MDI child */
1286 WIN_ReleaseWndPtr(wndPtr);
1288 if( ci && (
1289 wParam < ci->idFirstChild ||
1290 wParam >= ci->idFirstChild + ci->nActiveChildren
1292 if( (wParam - 0xF000) & 0xF00F ) break;
1293 switch( wParam )
1295 case SC_SIZE:
1296 case SC_MOVE:
1297 case SC_MINIMIZE:
1298 case SC_MAXIMIZE:
1299 case SC_NEXTWINDOW:
1300 case SC_PREVWINDOW:
1301 case SC_CLOSE:
1302 case SC_RESTORE:
1303 if( ci->hwndChildMaximized )
1304 return SendMessage16( ci->hwndChildMaximized, WM_SYSCOMMAND,
1305 wParam, lParam);
1308 else
1310 wndPtr = WIN_FindWndPtr(hwndMDIClient);
1311 childHwnd = MDI_GetChildByID(wndPtr,wParam );
1312 WIN_ReleaseWndPtr(wndPtr);
1314 if( childHwnd )
1315 SendMessage16(hwndMDIClient, WM_MDIACTIVATE,
1316 (WPARAM16)childHwnd , 0L);
1318 break;
1320 case WM_NCACTIVATE:
1321 SendMessage16(hwndMDIClient, message, wParam, lParam);
1322 break;
1324 case WM_SETTEXT:
1325 wndPtr = WIN_FindWndPtr(hwnd);
1326 MDI_UpdateFrameText(wndPtr, hwndMDIClient,
1327 MDI_REPAINTFRAME,
1328 (LPCSTR)PTR_SEG_TO_LIN(lParam));
1329 WIN_ReleaseWndPtr(wndPtr);
1330 return 0;
1332 case WM_SETFOCUS:
1333 SetFocus(hwndMDIClient);
1334 break;
1336 case WM_SIZE:
1337 MoveWindow16(hwndMDIClient, 0, 0,
1338 LOWORD(lParam), HIWORD(lParam), TRUE);
1339 break;
1341 case WM_NEXTMENU:
1343 wndPtr = WIN_FindWndPtr(hwndMDIClient);
1344 ci = (MDICLIENTINFO*)wndPtr->wExtra;
1346 if( !(wndPtr->parent->dwStyle & WS_MINIMIZE)
1347 && ci->hwndActiveChild && !ci->hwndChildMaximized )
1349 /* control menu is between the frame system menu and
1350 * the first entry of menu bar */
1352 if( (wParam == VK_LEFT &&
1353 wndPtr->parent->wIDmenu == LOWORD(lParam)) ||
1354 (wParam == VK_RIGHT &&
1355 GetSubMenu16(wndPtr->parent->hSysMenu, 0) == LOWORD(lParam)) )
1357 LRESULT retvalue;
1358 WIN_ReleaseWndPtr(wndPtr);
1359 wndPtr = WIN_FindWndPtr(ci->hwndActiveChild);
1360 retvalue = MAKELONG( GetSubMenu16(wndPtr->hSysMenu, 0),
1361 ci->hwndActiveChild);
1362 WIN_ReleaseWndPtr(wndPtr);
1363 return retvalue;
1366 WIN_ReleaseWndPtr(wndPtr);
1367 break;
1371 return DefWindowProc16(hwnd, message, wParam, lParam);
1375 /***********************************************************************
1376 * DefFrameProc32A (USER32.122)
1378 LRESULT WINAPI DefFrameProcA( HWND hwnd, HWND hwndMDIClient,
1379 UINT message, WPARAM wParam, LPARAM lParam)
1381 if (hwndMDIClient)
1383 switch (message)
1385 case WM_COMMAND:
1386 return DefFrameProc16( hwnd, hwndMDIClient, message,
1387 (WPARAM16)wParam,
1388 MAKELPARAM( (HWND16)lParam, HIWORD(wParam) ) );
1390 case WM_NCACTIVATE:
1391 SendMessageA(hwndMDIClient, message, wParam, lParam);
1392 break;
1394 case WM_SETTEXT: {
1395 LRESULT ret;
1396 LPSTR segstr = SEGPTR_STRDUP((LPSTR)lParam);
1398 ret = DefFrameProc16(hwnd, hwndMDIClient, message,
1399 wParam, (LPARAM)SEGPTR_GET(segstr) );
1400 SEGPTR_FREE(segstr);
1401 return ret;
1404 case WM_NEXTMENU:
1405 case WM_SETFOCUS:
1406 case WM_SIZE:
1407 return DefFrameProc16( hwnd, hwndMDIClient, message,
1408 wParam, lParam );
1412 return DefWindowProcA(hwnd, message, wParam, lParam);
1416 /***********************************************************************
1417 * DefFrameProc32W (USER32.123)
1419 LRESULT WINAPI DefFrameProcW( HWND hwnd, HWND hwndMDIClient,
1420 UINT message, WPARAM wParam, LPARAM lParam)
1422 if (hwndMDIClient)
1424 switch (message)
1426 case WM_COMMAND:
1427 return DefFrameProc16( hwnd, hwndMDIClient, message,
1428 (WPARAM16)wParam,
1429 MAKELPARAM( (HWND16)lParam, HIWORD(wParam) ) );
1431 case WM_NCACTIVATE:
1432 SendMessageW(hwndMDIClient, message, wParam, lParam);
1433 break;
1435 case WM_SETTEXT:
1437 LPSTR txt = HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)lParam);
1438 LRESULT ret = DefFrameProcA( hwnd, hwndMDIClient, message,
1439 wParam, (DWORD)txt );
1440 HeapFree(GetProcessHeap(),0,txt);
1441 return ret;
1443 case WM_NEXTMENU:
1444 case WM_SETFOCUS:
1445 case WM_SIZE:
1446 return DefFrameProcA( hwnd, hwndMDIClient, message,
1447 wParam, lParam );
1451 return DefWindowProcW( hwnd, message, wParam, lParam );
1455 /***********************************************************************
1456 * DefMDIChildProc16 (USER.447)
1458 LRESULT WINAPI DefMDIChildProc16( HWND16 hwnd, UINT16 message,
1459 WPARAM16 wParam, LPARAM lParam )
1461 MDICLIENTINFO *ci;
1462 WND *clientWnd,*tmpWnd = 0;
1463 LRESULT retvalue;
1465 clientWnd = WIN_FindWndPtr(GetParent16(hwnd));
1466 ci = (MDICLIENTINFO *) clientWnd->wExtra;
1468 switch (message)
1470 case WM_SETTEXT:
1471 DefWindowProc16(hwnd, message, wParam, lParam);
1472 MDI_MenuModifyItem(clientWnd,hwnd);
1473 if( ci->hwndChildMaximized == hwnd )
1474 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1475 MDI_REPAINTFRAME, NULL );
1476 retvalue = 0;
1477 goto END;
1479 case WM_CLOSE:
1480 SendMessage16(ci->self,WM_MDIDESTROY,(WPARAM16)hwnd,0L);
1481 retvalue = 0;
1482 goto END;
1484 case WM_SETFOCUS:
1485 if( ci->hwndActiveChild != hwnd )
1486 MDI_ChildActivate(clientWnd, hwnd);
1487 break;
1489 case WM_CHILDACTIVATE:
1490 MDI_ChildActivate(clientWnd, hwnd);
1491 retvalue = 0;
1492 goto END;
1494 case WM_NCPAINT:
1495 TRACE("WM_NCPAINT for %04x, active %04x\n",
1496 hwnd, ci->hwndActiveChild );
1497 break;
1499 case WM_SYSCOMMAND:
1500 switch( wParam )
1502 case SC_MOVE:
1503 if( ci->hwndChildMaximized == hwnd)
1505 retvalue = 0;
1506 goto END;
1508 break;
1509 case SC_RESTORE:
1510 case SC_MINIMIZE:
1511 tmpWnd = WIN_FindWndPtr(hwnd);
1512 tmpWnd->dwStyle |= WS_SYSMENU;
1513 WIN_ReleaseWndPtr(tmpWnd);
1514 break;
1515 case SC_MAXIMIZE:
1516 if( ci->hwndChildMaximized == hwnd)
1518 retvalue = SendMessage16( clientWnd->parent->hwndSelf,
1519 message, wParam, lParam);
1520 goto END;
1522 tmpWnd = WIN_FindWndPtr(hwnd);
1523 tmpWnd->dwStyle &= ~WS_SYSMENU;
1524 WIN_ReleaseWndPtr(tmpWnd);
1525 break;
1526 case SC_NEXTWINDOW:
1527 SendMessage16( ci->self, WM_MDINEXT, 0, 0);
1528 retvalue = 0;
1529 goto END;
1530 case SC_PREVWINDOW:
1531 SendMessage16( ci->self, WM_MDINEXT, 0, 1);
1532 retvalue = 0;
1533 goto END;
1535 break;
1537 case WM_GETMINMAXINFO:
1538 MDI_ChildGetMinMaxInfo(clientWnd, hwnd, (MINMAXINFO16*) PTR_SEG_TO_LIN(lParam));
1539 retvalue = 0;
1540 goto END;
1542 case WM_SETVISIBLE:
1543 if( ci->hwndChildMaximized) ci->mdiFlags &= ~MDIF_NEEDUPDATE;
1544 else
1545 MDI_PostUpdate(clientWnd->hwndSelf, ci, SB_BOTH+1);
1546 break;
1548 case WM_SIZE:
1549 /* do not change */
1551 if( ci->hwndActiveChild == hwnd && wParam != SIZE_MAXIMIZED )
1553 ci->hwndChildMaximized = 0;
1555 MDI_RestoreFrameMenu( clientWnd->parent, hwnd);
1556 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1557 MDI_REPAINTFRAME, NULL );
1560 if( wParam == SIZE_MAXIMIZED )
1562 HWND16 hMaxChild = ci->hwndChildMaximized;
1564 if( hMaxChild == hwnd ) break;
1566 if( hMaxChild)
1568 SendMessage16( hMaxChild, WM_SETREDRAW, FALSE, 0L );
1570 MDI_RestoreFrameMenu( clientWnd->parent, hMaxChild);
1571 ShowWindow16( hMaxChild, SW_SHOWNOACTIVATE);
1573 SendMessage16( hMaxChild, WM_SETREDRAW, TRUE, 0L );
1576 TRACE("maximizing child %04x\n", hwnd );
1578 ci->hwndChildMaximized = hwnd; /* !!! */
1579 ci->hwndActiveChild = hwnd;
1581 MDI_AugmentFrameMenu( ci, clientWnd->parent, hwnd);
1582 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1583 MDI_REPAINTFRAME, NULL );
1586 if( wParam == SIZE_MINIMIZED )
1588 HWND16 switchTo = MDI_GetWindow(clientWnd, hwnd, TRUE, WS_MINIMIZE);
1590 if( switchTo )
1591 SendMessage16( switchTo, WM_CHILDACTIVATE, 0, 0L);
1594 MDI_PostUpdate(clientWnd->hwndSelf, ci, SB_BOTH+1);
1595 break;
1597 case WM_MENUCHAR:
1599 /* MDI children don't have menu bars */
1600 PostMessage16( clientWnd->parent->hwndSelf, WM_SYSCOMMAND,
1601 (WPARAM16)SC_KEYMENU, (LPARAM)wParam);
1602 retvalue = 0x00010000L;
1603 goto END;
1605 case WM_NEXTMENU:
1607 if( wParam == VK_LEFT ) /* switch to frame system menu */
1609 retvalue = MAKELONG( GetSubMenu16(clientWnd->parent->hSysMenu, 0),
1610 clientWnd->parent->hwndSelf );
1611 goto END;
1613 if( wParam == VK_RIGHT ) /* to frame menu bar */
1615 retvalue = MAKELONG( clientWnd->parent->wIDmenu,
1616 clientWnd->parent->hwndSelf );
1617 goto END;
1620 break;
1622 case WM_SYSCHAR:
1623 if (wParam == '-')
1625 SendMessage16(hwnd,WM_SYSCOMMAND,
1626 (WPARAM16)SC_KEYMENU, (LPARAM)(DWORD)VK_SPACE);
1627 retvalue = 0;
1628 goto END;
1632 retvalue = DefWindowProc16(hwnd, message, wParam, lParam);
1633 END:
1634 WIN_ReleaseWndPtr(clientWnd);
1635 return retvalue;
1639 /***********************************************************************
1640 * DefMDIChildProc32A (USER32.124)
1642 LRESULT WINAPI DefMDIChildProcA( HWND hwnd, UINT message,
1643 WPARAM wParam, LPARAM lParam )
1645 MDICLIENTINFO *ci;
1646 WND *clientWnd,*tmpWnd;
1647 LRESULT retvalue;
1649 tmpWnd = WIN_FindWndPtr(hwnd);
1650 clientWnd = WIN_FindWndPtr(tmpWnd->parent->hwndSelf);
1651 ci = (MDICLIENTINFO *) clientWnd->wExtra;
1652 WIN_ReleaseWndPtr(tmpWnd);
1654 switch (message)
1656 case WM_SETTEXT:
1657 DefWindowProcA(hwnd, message, wParam, lParam);
1658 MDI_MenuModifyItem(clientWnd,hwnd);
1659 if( ci->hwndChildMaximized == hwnd )
1660 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1661 MDI_REPAINTFRAME, NULL );
1662 retvalue = 0;
1663 goto END;
1665 case WM_GETMINMAXINFO:
1667 MINMAXINFO16 mmi;
1668 STRUCT32_MINMAXINFO32to16( (MINMAXINFO *)lParam, &mmi );
1669 MDI_ChildGetMinMaxInfo( clientWnd, hwnd, &mmi );
1670 STRUCT32_MINMAXINFO16to32( &mmi, (MINMAXINFO *)lParam );
1672 retvalue = 0;
1673 goto END;
1675 case WM_MENUCHAR:
1677 /* MDI children don't have menu bars */
1678 PostMessage16( clientWnd->parent->hwndSelf, WM_SYSCOMMAND,
1679 (WPARAM16)SC_KEYMENU, (LPARAM)LOWORD(wParam) );
1680 retvalue = 0x00010000L;
1681 goto END;
1683 case WM_CLOSE:
1684 case WM_SETFOCUS:
1685 case WM_CHILDACTIVATE:
1686 case WM_NCPAINT:
1687 case WM_SYSCOMMAND:
1688 case WM_SETVISIBLE:
1689 case WM_SIZE:
1690 case WM_NEXTMENU:
1691 retvalue = DefMDIChildProc16( hwnd, message, (WPARAM16)wParam, lParam );
1692 goto END;
1694 case WM_SYSCHAR:
1695 if (wParam == '-')
1697 SendMessageA(hwnd,WM_SYSCOMMAND,
1698 (WPARAM)SC_KEYMENU, (LPARAM)(DWORD)VK_SPACE);
1699 retvalue = 0;
1700 goto END;
1703 retvalue = DefWindowProcA(hwnd, message, wParam, lParam);
1704 END:
1705 WIN_ReleaseWndPtr(clientWnd);
1706 return retvalue;
1710 /***********************************************************************
1711 * DefMDIChildProc32W (USER32.125)
1713 LRESULT WINAPI DefMDIChildProcW( HWND hwnd, UINT message,
1714 WPARAM wParam, LPARAM lParam )
1716 MDICLIENTINFO *ci;
1717 WND *clientWnd;
1718 LRESULT retvalue;
1720 clientWnd = WIN_FindWndPtr(GetParent16(hwnd));
1721 ci = (MDICLIENTINFO *) clientWnd->wExtra;
1723 switch (message)
1725 case WM_SETTEXT:
1726 DefWindowProcW(hwnd, message, wParam, lParam);
1727 MDI_MenuModifyItem(clientWnd,hwnd);
1728 if( ci->hwndChildMaximized == hwnd )
1729 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1730 MDI_REPAINTFRAME, NULL );
1731 retvalue = 0;
1732 goto END;
1734 case WM_GETMINMAXINFO:
1735 case WM_MENUCHAR:
1736 case WM_CLOSE:
1737 case WM_SETFOCUS:
1738 case WM_CHILDACTIVATE:
1739 case WM_NCPAINT:
1740 case WM_SYSCOMMAND:
1741 case WM_SETVISIBLE:
1742 case WM_SIZE:
1743 case WM_NEXTMENU:
1744 retvalue = DefMDIChildProcA( hwnd, message, (WPARAM16)wParam, lParam );
1745 goto END;
1747 case WM_SYSCHAR:
1748 if (wParam == '-')
1750 SendMessageW(hwnd,WM_SYSCOMMAND,
1751 (WPARAM)SC_KEYMENU, (LPARAM)(DWORD)VK_SPACE);
1752 retvalue = 0;
1753 goto END;
1756 retvalue = DefWindowProcW(hwnd, message, wParam, lParam);
1757 END:
1758 WIN_ReleaseWndPtr(clientWnd);
1759 return retvalue;
1764 /**********************************************************************
1765 * CreateMDIWindowA [USER32.79] Creates a MDI child in new thread
1766 * FIXME: its in the same thread now
1768 * RETURNS
1769 * Success: Handle to created window
1770 * Failure: NULL
1772 HWND WINAPI CreateMDIWindowA(
1773 LPCSTR lpClassName, /* [in] Pointer to registered child class name */
1774 LPCSTR lpWindowName, /* [in] Pointer to window name */
1775 DWORD dwStyle, /* [in] Window style */
1776 INT X, /* [in] Horizontal position of window */
1777 INT Y, /* [in] Vertical position of window */
1778 INT nWidth, /* [in] Width of window */
1779 INT nHeight, /* [in] Height of window */
1780 HWND hWndParent, /* [in] Handle to parent window */
1781 HINSTANCE hInstance, /* [in] Handle to application instance */
1782 LPARAM lParam) /* [in] Application-defined value */
1784 WARN("is only single threaded!\n");
1785 return MDI_CreateMDIWindowA(lpClassName, lpWindowName, dwStyle, X, Y,
1786 nWidth, nHeight, hWndParent, hInstance, lParam);
1789 /**********************************************************************
1790 * MDI_CreateMDIWindowA
1791 * single threaded version of CreateMDIWindowA
1792 * called by CreateWindowEx32A
1794 HWND MDI_CreateMDIWindowA(
1795 LPCSTR lpClassName,
1796 LPCSTR lpWindowName,
1797 DWORD dwStyle,
1798 INT X,
1799 INT Y,
1800 INT nWidth,
1801 INT nHeight,
1802 HWND hWndParent,
1803 HINSTANCE hInstance,
1804 LPARAM lParam)
1806 MDICLIENTINFO* pCi;
1807 MDICREATESTRUCTA cs;
1808 WND *pWnd=WIN_FindWndPtr(hWndParent);
1809 HWND retvalue;
1811 TRACE("(%s,%s,%ld,%d,%d,%d,%d,%x,%d,%ld)\n",
1812 debugstr_a(lpClassName),debugstr_a(lpWindowName),dwStyle,X,Y,
1813 nWidth,nHeight,hWndParent,hInstance,lParam);
1815 if(!pWnd){
1816 ERR(" bad hwnd for MDI-client: %d\n",hWndParent);
1817 return 0;
1819 cs.szClass=lpClassName;
1820 cs.szTitle=lpWindowName;
1821 cs.hOwner=hInstance;
1822 cs.x=X;
1823 cs.y=Y;
1824 cs.cx=nWidth;
1825 cs.cy=nHeight;
1826 cs.style=dwStyle;
1827 cs.lParam=lParam;
1829 pCi=(MDICLIENTINFO *)pWnd->wExtra;
1831 retvalue = MDICreateChild(pWnd,pCi,hWndParent,&cs);
1832 WIN_ReleaseWndPtr(pWnd);
1833 return retvalue;
1836 /***************************************
1837 * CreateMDIWindow32W [USER32.80] Creates a MDI child in new thread
1839 * RETURNS
1840 * Success: Handle to created window
1841 * Failure: NULL
1843 HWND WINAPI CreateMDIWindowW(
1844 LPCWSTR lpClassName, /* [in] Pointer to registered child class name */
1845 LPCWSTR lpWindowName, /* [in] Pointer to window name */
1846 DWORD dwStyle, /* [in] Window style */
1847 INT X, /* [in] Horizontal position of window */
1848 INT Y, /* [in] Vertical position of window */
1849 INT nWidth, /* [in] Width of window */
1850 INT nHeight, /* [in] Height of window */
1851 HWND hWndParent, /* [in] Handle to parent window */
1852 HINSTANCE hInstance, /* [in] Handle to application instance */
1853 LPARAM lParam) /* [in] Application-defined value */
1855 FIXME("(%s,%s,%ld,%d,%d,%d,%d,%x,%d,%ld): stub\n",
1856 debugstr_w(lpClassName),debugstr_w(lpWindowName),dwStyle,X,Y,
1857 nWidth,nHeight,hWndParent,hInstance,lParam);
1858 return (HWND)NULL;
1862 /******************************************************************************
1863 * CreateMDIWindow32W [USER32.80] Creates a MDI child window
1864 * single threaded version of CreateMDIWindow
1865 * called by CreateWindowEx32W().
1867 HWND MDI_CreateMDIWindowW(
1868 LPCWSTR lpClassName, /* [in] Pointer to registered child class name */
1869 LPCWSTR lpWindowName, /* [in] Pointer to window name */
1870 DWORD dwStyle, /* [in] Window style */
1871 INT X, /* [in] Horizontal position of window */
1872 INT Y, /* [in] Vertical position of window */
1873 INT nWidth, /* [in] Width of window */
1874 INT nHeight, /* [in] Height of window */
1875 HWND hWndParent, /* [in] Handle to parent window */
1876 HINSTANCE hInstance, /* [in] Handle to application instance */
1877 LPARAM lParam) /* [in] Application-defined value */
1879 FIXME("(%s,%s,%ld,%d,%d,%d,%d,%x,%d,%ld): stub\n",
1880 debugstr_w(lpClassName),debugstr_w(lpWindowName),dwStyle,X,Y,
1881 nWidth,nHeight,hWndParent,hInstance,lParam);
1882 return (HWND)NULL;
1886 /**********************************************************************
1887 * TranslateMDISysAccel32 (USER32.555)
1889 BOOL WINAPI TranslateMDISysAccel( HWND hwndClient, LPMSG msg )
1891 MSG16 msg16;
1893 STRUCT32_MSG32to16(msg,&msg16);
1894 /* MDICLIENTINFO is still the same for win32 and win16 ... */
1895 return TranslateMDISysAccel16(hwndClient,&msg16);
1899 /**********************************************************************
1900 * TranslateMDISysAccel16 (USER.451)
1902 BOOL16 WINAPI TranslateMDISysAccel16( HWND16 hwndClient, LPMSG16 msg )
1905 if( IsWindow(hwndClient) && (msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN))
1907 MDICLIENTINFO *ci = NULL;
1908 HWND wnd;
1909 WND *clientWnd = WIN_FindWndPtr(hwndClient);
1911 ci = (MDICLIENTINFO*) clientWnd->wExtra;
1912 wnd = ci->hwndActiveChild;
1914 WIN_ReleaseWndPtr(clientWnd);
1916 if( IsWindow(wnd) && !(GetWindowLongA(wnd,GWL_STYLE) & WS_DISABLED) )
1918 WPARAM16 wParam = 0;
1920 /* translate if the Ctrl key is down and Alt not. */
1922 if( (GetKeyState(VK_CONTROL) & 0x8000) &&
1923 !(GetKeyState(VK_MENU) & 0x8000))
1925 switch( msg->wParam )
1927 case VK_F6:
1928 case VK_TAB:
1929 wParam = ( GetKeyState(VK_SHIFT) & 0x8000 )
1930 ? SC_NEXTWINDOW : SC_PREVWINDOW;
1931 break;
1932 case VK_F4:
1933 case VK_RBUTTON:
1934 wParam = SC_CLOSE;
1935 break;
1936 default:
1937 return 0;
1939 TRACE("wParam = %04x\n", wParam);
1940 SendMessage16( ci->hwndActiveChild, WM_SYSCOMMAND,
1941 wParam, (LPARAM)msg->wParam);
1942 return 1;
1946 return 0; /* failure */
1950 /***********************************************************************
1951 * CalcChildScroll (USER.462)
1953 void WINAPI CalcChildScroll16( HWND16 hwnd, WORD scroll )
1955 SCROLLINFO info;
1956 RECT childRect, clientRect;
1957 INT vmin, vmax, hmin, hmax, vpos, hpos;
1958 WND *pWnd, *Wnd;
1960 if (!(pWnd = WIN_FindWndPtr( hwnd ))) return;
1961 Wnd = WIN_FindWndPtr(hwnd);
1962 GetClientRect( hwnd, &clientRect );
1963 SetRectEmpty( &childRect );
1965 for ( WIN_UpdateWndPtr(&pWnd,pWnd->child); pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1967 if( pWnd->dwStyle & WS_MAXIMIZE )
1969 ShowScrollBar(hwnd, SB_BOTH, FALSE);
1970 WIN_ReleaseWndPtr(pWnd);
1971 WIN_ReleaseWndPtr(Wnd);
1972 return;
1974 UnionRect( &childRect, &pWnd->rectWindow, &childRect );
1976 WIN_ReleaseWndPtr(pWnd);
1977 UnionRect( &childRect, &clientRect, &childRect );
1979 hmin = childRect.left; hmax = childRect.right - clientRect.right;
1980 hpos = clientRect.left - childRect.left;
1981 vmin = childRect.top; vmax = childRect.bottom - clientRect.bottom;
1982 vpos = clientRect.top - childRect.top;
1984 switch( scroll )
1986 case SB_HORZ:
1987 vpos = hpos; vmin = hmin; vmax = hmax;
1988 case SB_VERT:
1989 info.cbSize = sizeof(info);
1990 info.nMax = vmax; info.nMin = vmin; info.nPos = vpos;
1991 info.fMask = SIF_POS | SIF_RANGE;
1992 SetScrollInfo(hwnd, scroll, &info, TRUE);
1993 break;
1994 case SB_BOTH:
1995 SCROLL_SetNCSbState( Wnd, vmin, vmax, vpos,
1996 hmin, hmax, hpos);
1998 WIN_ReleaseWndPtr(Wnd);
2002 /***********************************************************************
2003 * ScrollChildren16 (USER.463)
2005 void WINAPI ScrollChildren16(HWND16 hWnd, UINT16 uMsg, WPARAM16 wParam, LPARAM lParam)
2007 ScrollChildren( hWnd, uMsg, wParam, lParam );
2011 /***********************************************************************
2012 * ScrollChildren32 (USER32.448)
2014 void WINAPI ScrollChildren(HWND hWnd, UINT uMsg, WPARAM wParam,
2015 LPARAM lParam)
2017 WND *wndPtr = WIN_FindWndPtr(hWnd);
2018 INT newPos = -1;
2019 INT curPos, length, minPos, maxPos, shift;
2021 if( !wndPtr ) return;
2023 if( uMsg == WM_HSCROLL )
2025 GetScrollRange(hWnd,SB_HORZ,&minPos,&maxPos);
2026 curPos = GetScrollPos(hWnd,SB_HORZ);
2027 length = (wndPtr->rectClient.right - wndPtr->rectClient.left)/2;
2028 shift = GetSystemMetrics(SM_CYHSCROLL);
2030 else if( uMsg == WM_VSCROLL )
2032 GetScrollRange(hWnd,SB_VERT,&minPos,&maxPos);
2033 curPos = GetScrollPos(hWnd,SB_VERT);
2034 length = (wndPtr->rectClient.bottom - wndPtr->rectClient.top)/2;
2035 shift = GetSystemMetrics(SM_CXVSCROLL);
2037 else
2039 WIN_ReleaseWndPtr(wndPtr);
2040 return;
2043 WIN_ReleaseWndPtr(wndPtr);
2044 switch( wParam )
2046 case SB_LINEUP:
2047 newPos = curPos - shift;
2048 break;
2049 case SB_LINEDOWN:
2050 newPos = curPos + shift;
2051 break;
2052 case SB_PAGEUP:
2053 newPos = curPos - length;
2054 break;
2055 case SB_PAGEDOWN:
2056 newPos = curPos + length;
2057 break;
2059 case SB_THUMBPOSITION:
2060 newPos = LOWORD(lParam);
2061 break;
2063 case SB_THUMBTRACK:
2064 return;
2066 case SB_TOP:
2067 newPos = minPos;
2068 break;
2069 case SB_BOTTOM:
2070 newPos = maxPos;
2071 break;
2072 case SB_ENDSCROLL:
2073 CalcChildScroll16(hWnd,(uMsg == WM_VSCROLL)?SB_VERT:SB_HORZ);
2074 return;
2077 if( newPos > maxPos )
2078 newPos = maxPos;
2079 else
2080 if( newPos < minPos )
2081 newPos = minPos;
2083 SetScrollPos(hWnd, (uMsg == WM_VSCROLL)?SB_VERT:SB_HORZ , newPos, TRUE);
2085 if( uMsg == WM_VSCROLL )
2086 ScrollWindowEx(hWnd ,0 ,curPos - newPos, NULL, NULL, 0, NULL,
2087 SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
2088 else
2089 ScrollWindowEx(hWnd ,curPos - newPos, 0, NULL, NULL, 0, NULL,
2090 SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
2094 /******************************************************************************
2095 * CascadeWindows [USER32.21] Cascades MDI child windows
2097 * RETURNS
2098 * Success: Number of cascaded windows.
2099 * Failure: 0
2101 WORD WINAPI
2102 CascadeWindows (HWND hwndParent, UINT wFlags, const LPRECT lpRect,
2103 UINT cKids, const HWND *lpKids)
2105 FIXME("(0x%08x,0x%08x,...,%u,...): stub\n",
2106 hwndParent, wFlags, cKids);
2108 return 0;
2112 /******************************************************************************
2113 * TileWindows [USER32.545] Tiles MDI child windows
2115 * RETURNS
2116 * Success: Number of tiled windows.
2117 * Failure: 0
2119 WORD WINAPI
2120 TileWindows (HWND hwndParent, UINT wFlags, const LPRECT lpRect,
2121 UINT cKids, const HWND *lpKids)
2123 FIXME("(0x%08x,0x%08x,...,%u,...): stub\n",
2124 hwndParent, wFlags, cKids);
2126 return 0;