Fixed/commented out duplicate entry point names.
[wine/hacks.git] / windows / mdi.c
blobb67ada10d4ded48e0b5aee8e0197771112066edf
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;
211 MDICLIENTINFO *ci;
212 HWND hwndFrame = GetParent(hwnd);
213 HMENU oldFrameMenu = GetMenu(hwndFrame);
215 TRACE("%04x %04x %04x\n",
216 hwnd, hmenuFrame, hmenuWindow);
218 if (hmenuFrame && !IsMenu(hmenuFrame))
220 WARN("hmenuFrame is not a menu handle\n");
221 return 0L;
224 if (hmenuWindow && !IsMenu(hmenuWindow))
226 WARN("hmenuWindow is not a menu handle\n");
227 return 0L;
230 w = WIN_FindWndPtr(hwnd);
231 ci = (MDICLIENTINFO *) w->wExtra;
233 if( ci->hwndChildMaximized && hmenuFrame && hmenuFrame!=oldFrameMenu )
234 MDI_RestoreFrameMenu(w->parent, ci->hwndChildMaximized );
236 if( hmenuWindow && hmenuWindow!=ci->hWindowMenu )
238 /* delete menu items from ci->hWindowMenu
239 * and add them to hmenuWindow */
241 INT i = GetMenuItemCount(ci->hWindowMenu) - 1;
242 INT pos = GetMenuItemCount(hmenuWindow) + 1;
244 AppendMenuA( hmenuWindow, MF_SEPARATOR, 0, NULL);
246 if( ci->nActiveChildren )
248 INT j = i - ci->nActiveChildren + 1;
249 char buffer[100];
250 UINT id,state;
252 for( ; i >= j ; i-- )
254 id = GetMenuItemID(ci->hWindowMenu,i );
255 state = GetMenuState(ci->hWindowMenu,i,MF_BYPOSITION);
257 GetMenuStringA(ci->hWindowMenu, i, buffer, 100, MF_BYPOSITION);
259 DeleteMenu(ci->hWindowMenu, i , MF_BYPOSITION);
260 InsertMenuA(hmenuWindow, pos, MF_BYPOSITION | MF_STRING,
261 id, buffer);
262 CheckMenuItem(hmenuWindow ,pos , MF_BYPOSITION | (state & MF_CHECKED));
266 /* remove separator */
267 DeleteMenu(ci->hWindowMenu, i, MF_BYPOSITION);
269 ci->hWindowMenu = hmenuWindow;
272 if( hmenuFrame && hmenuFrame!=oldFrameMenu)
274 SetMenu(hwndFrame, hmenuFrame);
275 if( ci->hwndChildMaximized )
276 MDI_AugmentFrameMenu(ci, w->parent, ci->hwndChildMaximized );
277 WIN_ReleaseWndPtr(w);
278 return oldFrameMenu;
280 WIN_ReleaseWndPtr(w);
281 return 0;
284 /**********************************************************************
285 * MDIRefreshMenu
287 static LRESULT MDIRefreshMenu( HWND hwnd, HMENU hmenuFrame,
288 HMENU hmenuWindow)
290 HWND hwndFrame = GetParent(hwnd);
291 HMENU oldFrameMenu = GetMenu(hwndFrame);
293 TRACE("%04x %04x %04x\n",
294 hwnd, hmenuFrame, hmenuWindow);
296 FIXME("partially function stub\n");
298 return oldFrameMenu;
302 /* ------------------ MDI child window functions ---------------------- */
305 /**********************************************************************
306 * MDICreateChild
308 static HWND MDICreateChild( WND *w, MDICLIENTINFO *ci, HWND parent,
309 LPMDICREATESTRUCTA cs )
311 POINT pos[2];
312 DWORD style = cs->style | (WS_CHILD | WS_CLIPSIBLINGS);
313 HWND hwnd, hwndMax = 0;
314 WORD wIDmenu = ci->idFirstChild + ci->nActiveChildren;
315 char lpstrDef[]="junk!";
317 TRACE("origin %i,%i - dim %i,%i, style %08x\n",
318 cs->x, cs->y, cs->cx, cs->cy, (unsigned)cs->style);
319 /* calculate placement */
320 MDI_CalcDefaultChildPos(w, ci->nTotalCreated++, pos, 0);
322 if (cs->cx == CW_USEDEFAULT || !cs->cx) cs->cx = pos[1].x;
323 if (cs->cy == CW_USEDEFAULT || !cs->cy) cs->cy = pos[1].y;
325 if( cs->x == CW_USEDEFAULT )
327 cs->x = pos[0].x;
328 cs->y = pos[0].y;
331 /* restore current maximized child */
332 if( style & WS_VISIBLE && ci->hwndChildMaximized )
334 if( style & WS_MAXIMIZE )
335 SendMessageA(w->hwndSelf, WM_SETREDRAW, FALSE, 0L );
336 hwndMax = ci->hwndChildMaximized;
337 ShowWindow( hwndMax, SW_SHOWNOACTIVATE );
338 if( style & WS_MAXIMIZE )
339 SendMessageA(w->hwndSelf, WM_SETREDRAW, TRUE, 0L );
342 /* this menu is needed to set a check mark in MDI_ChildActivate */
343 AppendMenuA(ci->hWindowMenu ,MF_STRING ,wIDmenu, lpstrDef );
345 ci->nActiveChildren++;
347 /* fix window style */
348 if( !(w->dwStyle & MDIS_ALLCHILDSTYLES) )
350 style &= (WS_CHILD | WS_CLIPSIBLINGS | WS_MINIMIZE | WS_MAXIMIZE |
351 WS_CLIPCHILDREN | WS_DISABLED | WS_VSCROLL | WS_HSCROLL );
352 style |= (WS_VISIBLE | WS_OVERLAPPEDWINDOW);
355 if( w->flags & WIN_ISWIN32 )
357 hwnd = CreateWindowA( cs->szClass, cs->szTitle, style,
358 cs->x, cs->y, cs->cx, cs->cy, parent,
359 (HMENU16)wIDmenu, cs->hOwner, cs );
361 else
363 MDICREATESTRUCT16 *cs16;
364 LPSTR title, cls;
366 cs16 = SEGPTR_NEW(MDICREATESTRUCT16);
367 STRUCT32_MDICREATESTRUCT32Ato16( cs, cs16 );
368 title = SEGPTR_STRDUP( cs->szTitle );
369 cls = SEGPTR_STRDUP( cs->szClass );
370 cs16->szTitle = SEGPTR_GET(title);
371 cs16->szClass = SEGPTR_GET(cls);
373 hwnd = CreateWindow16( cs->szClass, cs->szTitle, style,
374 cs16->x, cs16->y, cs16->cx, cs16->cy, parent,
375 (HMENU)wIDmenu, cs16->hOwner,
376 (LPVOID)SEGPTR_GET(cs16) );
377 SEGPTR_FREE( title );
378 SEGPTR_FREE( cls );
379 SEGPTR_FREE( cs16 );
382 /* MDI windows are WS_CHILD so they won't be activated by CreateWindow */
384 if (hwnd)
386 WND* wnd = WIN_FindWndPtr( hwnd );
388 /* All MDI child windows have the WS_EX_MDICHILD style */
389 wnd->dwExStyle |= WS_EX_MDICHILD;
391 MDI_MenuModifyItem(w ,hwnd);
392 if( wnd->dwStyle & WS_MINIMIZE && ci->hwndActiveChild )
393 ShowWindow( hwnd, SW_SHOWMINNOACTIVE );
394 else
396 /* WS_VISIBLE is clear if a) the MDI client has
397 * MDIS_ALLCHILDSTYLES style and 2) the flag is cleared in the
398 * MDICreateStruct. If so the created window is not shown nor
399 * activated.
401 int showflag=wnd->dwStyle & WS_VISIBLE;
402 /* clear visible flag, otherwise SetWindoPos32 ignores
403 * the SWP_SHOWWINDOW command.
405 wnd->dwStyle &= ~WS_VISIBLE;
406 if(showflag){
407 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE );
409 /* Set maximized state here in case hwnd didn't receive WM_SIZE
410 * during CreateWindow - bad!
413 if((wnd->dwStyle & WS_MAXIMIZE) && !ci->hwndChildMaximized )
415 ci->hwndChildMaximized = wnd->hwndSelf;
416 MDI_AugmentFrameMenu( ci, w->parent, hwnd );
417 MDI_UpdateFrameText( w->parent, ci->self, MDI_REPAINTFRAME, NULL );
419 }else
420 /* needed, harmless ? */
421 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE );
424 WIN_ReleaseWndPtr(wnd);
425 TRACE("created child - %04x\n",hwnd);
427 else
429 ci->nActiveChildren--;
430 DeleteMenu(ci->hWindowMenu,wIDmenu,MF_BYCOMMAND);
431 if( IsWindow(hwndMax) )
432 ShowWindow(hwndMax, SW_SHOWMAXIMIZED);
435 return hwnd;
438 /**********************************************************************
439 * MDI_ChildGetMinMaxInfo
441 * Note: The rule here is that client rect of the maximized MDI child
442 * is equal to the client rect of the MDI client window.
444 static void MDI_ChildGetMinMaxInfo( WND* clientWnd, HWND hwnd,
445 MINMAXINFO16* lpMinMax )
447 WND* childWnd = WIN_FindWndPtr(hwnd);
448 RECT rect = clientWnd->rectClient;
450 MapWindowPoints( clientWnd->parent->hwndSelf,
451 ((MDICLIENTINFO*)clientWnd->wExtra)->self, (LPPOINT)&rect, 2);
452 AdjustWindowRectEx( &rect, childWnd->dwStyle, 0, childWnd->dwExStyle );
454 lpMinMax->ptMaxSize.x = rect.right -= rect.left;
455 lpMinMax->ptMaxSize.y = rect.bottom -= rect.top;
457 lpMinMax->ptMaxPosition.x = rect.left;
458 lpMinMax->ptMaxPosition.y = rect.top;
460 WIN_ReleaseWndPtr(childWnd);
462 TRACE("max rect (%i,%i - %i, %i)\n",
463 rect.left,rect.top,rect.right,rect.bottom);
467 /**********************************************************************
468 * MDI_SwitchActiveChild
470 * Note: SetWindowPos sends WM_CHILDACTIVATE to the child window that is
471 * being activated
473 static void MDI_SwitchActiveChild( HWND clientHwnd, HWND childHwnd,
474 BOOL bNextWindow )
476 WND *w = WIN_FindWndPtr(clientHwnd);
477 HWND hwndTo = 0;
478 HWND hwndPrev = 0;
479 MDICLIENTINFO *ci;
481 hwndTo = MDI_GetWindow(w, childHwnd, bNextWindow, 0);
483 ci = (MDICLIENTINFO *) w->wExtra;
485 TRACE("from %04x, to %04x\n",childHwnd,hwndTo);
487 if ( !hwndTo ) goto END; /* no window to switch to */
489 hwndPrev = ci->hwndActiveChild;
491 if ( hwndTo != hwndPrev )
493 BOOL bOptimize = 0;
495 if( ci->hwndChildMaximized )
497 bOptimize = 1;
498 w->dwStyle &= ~WS_VISIBLE;
501 SetWindowPos( hwndTo, HWND_TOP, 0, 0, 0, 0,
502 SWP_NOMOVE | SWP_NOSIZE );
504 if( bNextWindow && hwndPrev )
505 SetWindowPos( hwndPrev, HWND_BOTTOM, 0, 0, 0, 0,
506 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE );
507 if( bOptimize )
508 ShowWindow( clientHwnd, SW_SHOW );
510 END:
511 WIN_ReleaseWndPtr(w);
515 /**********************************************************************
516 * MDIDestroyChild
518 static LRESULT MDIDestroyChild( WND *w_parent, MDICLIENTINFO *ci,
519 HWND parent, HWND child,
520 BOOL flagDestroy )
522 WND *childPtr = WIN_FindWndPtr(child);
524 if( childPtr )
526 if( child == ci->hwndActiveChild )
528 MDI_SwitchActiveChild(parent, child, TRUE);
530 if( child == ci->hwndActiveChild )
532 ShowWindow( child, SW_HIDE);
533 if( child == ci->hwndChildMaximized )
535 MDI_RestoreFrameMenu(w_parent->parent, child);
536 ci->hwndChildMaximized = 0;
537 MDI_UpdateFrameText(w_parent->parent,parent,TRUE,NULL);
540 MDI_ChildActivate(w_parent, 0);
543 MDI_MenuDeleteItem(w_parent, child);
545 WIN_ReleaseWndPtr(childPtr);
547 ci->nActiveChildren--;
549 TRACE("child destroyed - %04x\n",child);
551 if (flagDestroy)
553 MDI_PostUpdate(GetParent(child), ci, SB_BOTH+1);
554 DestroyWindow(child);
558 return 0;
562 /**********************************************************************
563 * MDI_ChildActivate
565 * Note: hWndChild is NULL when last child is being destroyed
567 static LONG MDI_ChildActivate( WND *clientPtr, HWND hWndChild )
569 MDICLIENTINFO *clientInfo = (MDICLIENTINFO*)clientPtr->wExtra;
570 HWND prevActiveWnd = clientInfo->hwndActiveChild;
571 WND *wndPtr = WIN_FindWndPtr( hWndChild );
572 WND *wndPrev = WIN_FindWndPtr( prevActiveWnd );
573 BOOL isActiveFrameWnd = 0;
574 LONG retvalue;
576 if( wndPtr )
578 if( wndPtr->dwStyle & WS_DISABLED )
580 retvalue = 0L;
581 goto END;
585 /* Don't activate if it is already active. Might happen
586 since ShowWindow DOES activate MDI children */
587 if (clientInfo->hwndActiveChild == hWndChild)
589 retvalue = 0L;
590 goto END;
593 TRACE("%04x\n", hWndChild);
595 if( GetActiveWindow() == clientPtr->parent->hwndSelf )
596 isActiveFrameWnd = TRUE;
598 /* deactivate prev. active child */
599 if( wndPrev )
601 wndPrev->dwStyle |= WS_SYSMENU;
602 SendMessageA( prevActiveWnd, WM_NCACTIVATE, FALSE, 0L );
603 SendMessageA( prevActiveWnd, WM_MDIACTIVATE, (WPARAM)prevActiveWnd,
604 (LPARAM)hWndChild);
605 /* uncheck menu item */
606 if( clientInfo->hWindowMenu )
607 CheckMenuItem( clientInfo->hWindowMenu,
608 wndPrev->wIDmenu, 0);
611 /* set appearance */
612 if( clientInfo->hwndChildMaximized )
614 if( clientInfo->hwndChildMaximized != hWndChild ) {
615 if( hWndChild ) {
616 clientInfo->hwndActiveChild = hWndChild;
617 ShowWindow( hWndChild, SW_SHOWMAXIMIZED);
618 } else
619 ShowWindow( clientInfo->hwndActiveChild, SW_SHOWNORMAL );
623 clientInfo->hwndActiveChild = hWndChild;
625 /* check if we have any children left */
626 if( !hWndChild )
628 if( isActiveFrameWnd )
629 SetFocus( clientInfo->self );
630 retvalue = 0;
631 goto END;
634 /* check menu item */
635 if( clientInfo->hWindowMenu )
636 CheckMenuItem( clientInfo->hWindowMenu,
637 wndPtr->wIDmenu, MF_CHECKED);
639 /* bring active child to the top */
640 SetWindowPos( hWndChild, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
642 if( isActiveFrameWnd )
644 SendMessageA( hWndChild, WM_NCACTIVATE, TRUE, 0L);
645 if( GetFocus() == clientInfo->self )
646 SendMessageA( clientInfo->self, WM_SETFOCUS,
647 (WPARAM)clientInfo->self, 0L );
648 else
649 SetFocus( clientInfo->self );
651 SendMessageA( hWndChild, WM_MDIACTIVATE, (WPARAM)prevActiveWnd,
652 (LPARAM)hWndChild );
653 retvalue = 1;
654 END:
655 WIN_ReleaseWndPtr(wndPtr);
656 WIN_ReleaseWndPtr(wndPrev);
657 return retvalue;
660 /* -------------------- MDI client window functions ------------------- */
662 /**********************************************************************
663 * CreateMDIMenuBitmap
665 static HBITMAP16 CreateMDIMenuBitmap(void)
667 HDC hDCSrc = CreateCompatibleDC(0);
668 HDC hDCDest = CreateCompatibleDC(hDCSrc);
669 HBITMAP16 hbClose = LoadBitmap16(0, MAKEINTRESOURCE16(OBM_CLOSE) );
670 HBITMAP16 hbCopy;
671 HANDLE16 hobjSrc, hobjDest;
673 hobjSrc = SelectObject(hDCSrc, hbClose);
674 hbCopy = CreateCompatibleBitmap(hDCSrc,GetSystemMetrics(SM_CXSIZE),GetSystemMetrics(SM_CYSIZE));
675 hobjDest = SelectObject(hDCDest, hbCopy);
677 BitBlt(hDCDest, 0, 0, GetSystemMetrics(SM_CXSIZE), GetSystemMetrics(SM_CYSIZE),
678 hDCSrc, GetSystemMetrics(SM_CXSIZE), 0, SRCCOPY);
680 SelectObject(hDCSrc, hobjSrc);
681 DeleteObject(hbClose);
682 DeleteDC(hDCSrc);
684 hobjSrc = SelectObject( hDCDest, GetStockObject(BLACK_PEN) );
686 MoveToEx( hDCDest, GetSystemMetrics(SM_CXSIZE) - 1, 0, NULL );
687 LineTo( hDCDest, GetSystemMetrics(SM_CXSIZE) - 1, GetSystemMetrics(SM_CYSIZE) - 1);
689 SelectObject(hDCDest, hobjSrc );
690 SelectObject(hDCDest, hobjDest);
691 DeleteDC(hDCDest);
693 return hbCopy;
696 /**********************************************************************
697 * MDICascade
699 static LONG MDICascade(WND* clientWnd, MDICLIENTINFO *ci)
701 WND** ppWnd;
702 UINT total;
704 if (ci->hwndChildMaximized)
705 SendMessageA( clientWnd->hwndSelf, WM_MDIRESTORE,
706 (WPARAM)ci->hwndChildMaximized, 0);
708 if (ci->nActiveChildren == 0) return 0;
710 if ((ppWnd = WIN_BuildWinArray(clientWnd, BWA_SKIPHIDDEN | BWA_SKIPOWNED |
711 BWA_SKIPICONIC, &total)))
713 WND** heapPtr = ppWnd;
714 if( total )
716 INT delta = 0, n = 0;
717 POINT pos[2];
718 if( total < ci->nActiveChildren )
719 delta = GetSystemMetrics(SM_CYICONSPACING) +
720 GetSystemMetrics(SM_CYICON);
722 /* walk the list (backwards) and move windows */
723 while (*ppWnd) ppWnd++;
724 while (ppWnd != heapPtr)
726 ppWnd--;
727 TRACE("move %04x to (%ld,%ld) size [%ld,%ld]\n",
728 (*ppWnd)->hwndSelf, pos[0].x, pos[0].y, pos[1].x, pos[1].y);
730 MDI_CalcDefaultChildPos(clientWnd, n++, pos, delta);
731 SetWindowPos( (*ppWnd)->hwndSelf, 0, pos[0].x, pos[0].y,
732 pos[1].x, pos[1].y,
733 SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER);
736 WIN_ReleaseWinArray(heapPtr);
739 if( total < ci->nActiveChildren )
740 ArrangeIconicWindows( clientWnd->hwndSelf );
741 return 0;
744 /**********************************************************************
745 * MDITile
747 static void MDITile( WND* wndClient, MDICLIENTINFO *ci, WPARAM wParam )
749 WND** ppWnd;
750 UINT total = 0;
752 if (ci->hwndChildMaximized)
753 SendMessageA( wndClient->hwndSelf, WM_MDIRESTORE,
754 (WPARAM)ci->hwndChildMaximized, 0);
756 if (ci->nActiveChildren == 0) return;
758 ppWnd = WIN_BuildWinArray(wndClient, BWA_SKIPHIDDEN | BWA_SKIPOWNED | BWA_SKIPICONIC |
759 ((wParam & MDITILE_SKIPDISABLED)? BWA_SKIPDISABLED : 0), &total );
761 TRACE("%u windows to tile\n", total);
763 if( ppWnd )
765 WND** heapPtr = ppWnd;
767 if( total )
769 RECT rect;
770 int x, y, xsize, ysize;
771 int rows, columns, r, c, i;
773 GetClientRect(wndClient->hwndSelf,&rect);
774 rows = (int) sqrt((double)total);
775 columns = total / rows;
777 if( wParam & MDITILE_HORIZONTAL ) /* version >= 3.1 */
779 i = rows;
780 rows = columns; /* exchange r and c */
781 columns = i;
784 if( total != ci->nActiveChildren)
786 y = rect.bottom - 2 * GetSystemMetrics(SM_CYICONSPACING) - GetSystemMetrics(SM_CYICON);
787 rect.bottom = ( y - GetSystemMetrics(SM_CYICON) < rect.top )? rect.bottom: y;
790 ysize = rect.bottom / rows;
791 xsize = rect.right / columns;
793 for (x = i = 0, c = 1; c <= columns && *ppWnd; c++)
795 if (c == columns)
797 rows = total - i;
798 ysize = rect.bottom / rows;
801 y = 0;
802 for (r = 1; r <= rows && *ppWnd; r++, i++)
804 SetWindowPos((*ppWnd)->hwndSelf, 0, x, y, xsize, ysize,
805 SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER);
806 y += ysize;
807 ppWnd++;
809 x += xsize;
812 WIN_ReleaseWinArray(heapPtr);
815 if( total < ci->nActiveChildren ) ArrangeIconicWindows( wndClient->hwndSelf );
818 /* ----------------------- Frame window ---------------------------- */
821 /**********************************************************************
822 * MDI_AugmentFrameMenu
824 static BOOL MDI_AugmentFrameMenu( MDICLIENTINFO* ci, WND *frame,
825 HWND hChild )
827 WND* child = WIN_FindWndPtr(hChild);
828 HMENU hSysPopup = 0;
829 HBITMAP hSysMenuBitmap = 0;
831 TRACE("frame %p,child %04x\n",frame,hChild);
833 if( !frame->wIDmenu || !child->hSysMenu )
835 WIN_ReleaseWndPtr(child);
836 return 0;
838 WIN_ReleaseWndPtr(child);
840 /* create a copy of sysmenu popup and insert it into frame menu bar */
842 if (!(hSysPopup = LoadMenuA(GetModuleHandleA("USER32"), "SYSMENU")))
843 return 0;
845 TRACE("\tgot popup %04x in sysmenu %04x\n",
846 hSysPopup, child->hSysMenu);
848 AppendMenuA(frame->wIDmenu,MF_HELP | MF_BITMAP,
849 SC_MINIMIZE, (LPSTR)(DWORD)HBMMENU_MBAR_MINIMIZE ) ;
850 AppendMenuA(frame->wIDmenu,MF_HELP | MF_BITMAP,
851 SC_RESTORE, (LPSTR)(DWORD)HBMMENU_MBAR_RESTORE );
853 /* In Win 95 look, the system menu is replaced by the child icon */
855 if(TWEAK_WineLook > WIN31_LOOK)
857 HICON hIcon = GetClassLongA(hChild, GCL_HICONSM);
858 if (!hIcon)
859 hIcon = GetClassLongA(hChild, GCL_HICON);
860 if (hIcon)
862 HDC hMemDC;
863 HBITMAP hBitmap, hOldBitmap;
864 HBRUSH hBrush;
865 HDC hdc = GetDC(hChild);
867 if (hdc)
869 int cx, cy;
870 cx = GetSystemMetrics(SM_CXSMICON);
871 cy = GetSystemMetrics(SM_CYSMICON);
872 hMemDC = CreateCompatibleDC(hdc);
873 hBitmap = CreateCompatibleBitmap(hdc, cx, cy);
874 hOldBitmap = SelectObject(hMemDC, hBitmap);
875 SetMapMode(hMemDC, MM_TEXT);
876 hBrush = CreateSolidBrush(GetSysColor(COLOR_MENU));
877 DrawIconEx(hMemDC, 0, 0, hIcon, cx, cy, 0, hBrush, DI_NORMAL);
878 SelectObject (hMemDC, hOldBitmap);
879 DeleteObject(hBrush);
880 DeleteDC(hMemDC);
881 ReleaseDC(hChild, hdc);
882 hSysMenuBitmap = hBitmap;
886 else
887 hSysMenuBitmap = hBmpClose;
889 if( !InsertMenuA(frame->wIDmenu,0,MF_BYPOSITION | MF_BITMAP | MF_POPUP,
890 hSysPopup, (LPSTR)(DWORD)hSysMenuBitmap))
892 TRACE("not inserted\n");
893 DestroyMenu(hSysPopup);
894 return 0;
897 /* The close button is only present in Win 95 look */
898 if(TWEAK_WineLook > WIN31_LOOK)
900 AppendMenuA(frame->wIDmenu,MF_HELP | MF_BITMAP,
901 SC_CLOSE, (LPSTR)(DWORD)HBMMENU_MBAR_CLOSE );
904 EnableMenuItem(hSysPopup, SC_SIZE, MF_BYCOMMAND | MF_GRAYED);
905 EnableMenuItem(hSysPopup, SC_MOVE, MF_BYCOMMAND | MF_GRAYED);
906 EnableMenuItem(hSysPopup, SC_MAXIMIZE, MF_BYCOMMAND | MF_GRAYED);
907 SetMenuDefaultItem(hSysPopup, SC_CLOSE, FALSE);
909 /* redraw menu */
910 DrawMenuBar(frame->hwndSelf);
912 return 1;
915 /**********************************************************************
916 * MDI_RestoreFrameMenu
918 static BOOL MDI_RestoreFrameMenu( WND *frameWnd, HWND hChild )
920 MENUITEMINFOA menuInfo;
921 INT nItems = GetMenuItemCount(frameWnd->wIDmenu) - 1;
922 UINT iId = GetMenuItemID(frameWnd->wIDmenu,nItems) ;
924 TRACE("frameWnd %p,child %04x\n",frameWnd,hChild);
926 if(!(iId == SC_RESTORE || iId == SC_CLOSE) )
927 return 0;
930 * Remove the system menu, If that menu is the icon of the window
931 * as it is in win95, we have to delete the bitmap.
933 menuInfo.cbSize = sizeof(MENUITEMINFOA);
934 menuInfo.fMask = MIIM_DATA | MIIM_TYPE;
936 GetMenuItemInfoA(frameWnd->wIDmenu,
938 TRUE,
939 &menuInfo);
941 RemoveMenu(frameWnd->wIDmenu,0,MF_BYPOSITION);
943 if ( (menuInfo.fType & MFT_BITMAP) &&
944 (LOWORD(menuInfo.dwTypeData)!=0) &&
945 (LOWORD(menuInfo.dwTypeData)!=hBmpClose) )
947 DeleteObject((HBITMAP)LOWORD(menuInfo.dwTypeData));
950 if(TWEAK_WineLook > WIN31_LOOK)
952 /* close */
953 DeleteMenu(frameWnd->wIDmenu,GetMenuItemCount(frameWnd->wIDmenu) - 1,MF_BYPOSITION);
955 /* restore */
956 DeleteMenu(frameWnd->wIDmenu,GetMenuItemCount(frameWnd->wIDmenu) - 1,MF_BYPOSITION);
957 /* minimize */
958 DeleteMenu(frameWnd->wIDmenu,GetMenuItemCount(frameWnd->wIDmenu) - 1,MF_BYPOSITION);
960 DrawMenuBar(frameWnd->hwndSelf);
962 return 1;
966 /**********************************************************************
967 * MDI_UpdateFrameText
969 * used when child window is maximized/restored
971 * Note: lpTitle can be NULL
973 static void MDI_UpdateFrameText( WND *frameWnd, HWND hClient,
974 BOOL repaint, LPCSTR lpTitle )
976 char lpBuffer[MDI_MAXTITLELENGTH+1];
977 WND* clientWnd = WIN_FindWndPtr(hClient);
978 MDICLIENTINFO *ci = (MDICLIENTINFO *) clientWnd->wExtra;
980 TRACE("repaint %i, frameText %s\n", repaint, (lpTitle)?lpTitle:"NULL");
982 if (!clientWnd)
983 return;
985 if (!ci)
987 WIN_ReleaseWndPtr(clientWnd);
988 return;
991 /* store new "default" title if lpTitle is not NULL */
992 if (lpTitle)
994 if (ci->frameTitle) HeapFree( SystemHeap, 0, ci->frameTitle );
995 ci->frameTitle = HEAP_strdupA( SystemHeap, 0, lpTitle );
998 if (ci->frameTitle)
1000 WND* childWnd = WIN_FindWndPtr( ci->hwndChildMaximized );
1002 if( childWnd && childWnd->text )
1004 /* combine frame title and child title if possible */
1006 LPCSTR lpBracket = " - [";
1007 int i_frame_text_length = strlen(ci->frameTitle);
1008 int i_child_text_length = strlen(childWnd->text);
1010 lstrcpynA( lpBuffer, ci->frameTitle, MDI_MAXTITLELENGTH);
1012 if( i_frame_text_length + 6 < MDI_MAXTITLELENGTH )
1014 strcat( lpBuffer, lpBracket );
1016 if( i_frame_text_length + i_child_text_length + 6 < MDI_MAXTITLELENGTH )
1018 strcat( lpBuffer, childWnd->text );
1019 strcat( lpBuffer, "]" );
1021 else
1023 lstrcpynA( lpBuffer + i_frame_text_length + 4,
1024 childWnd->text, MDI_MAXTITLELENGTH - i_frame_text_length - 5 );
1025 strcat( lpBuffer, "]" );
1029 else
1031 strncpy(lpBuffer, ci->frameTitle, MDI_MAXTITLELENGTH );
1032 lpBuffer[MDI_MAXTITLELENGTH]='\0';
1034 WIN_ReleaseWndPtr(childWnd);
1037 else
1038 lpBuffer[0] = '\0';
1040 DEFWND_SetText( frameWnd, lpBuffer );
1041 if( repaint == MDI_REPAINTFRAME)
1042 SetWindowPos( frameWnd->hwndSelf, 0,0,0,0,0, SWP_FRAMECHANGED |
1043 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER );
1045 WIN_ReleaseWndPtr(clientWnd);
1050 /* ----------------------------- Interface ---------------------------- */
1053 /**********************************************************************
1054 * MDIClientWndProc
1056 * This function handles all MDI requests.
1058 LRESULT WINAPI MDIClientWndProc( HWND hwnd, UINT message, WPARAM wParam,
1059 LPARAM lParam )
1061 LPCREATESTRUCTA cs;
1062 MDICLIENTINFO *ci;
1063 RECT rect;
1064 WND *w, *frameWnd;
1065 INT nItems;
1066 LRESULT retvalue;
1068 if ( ( w = WIN_FindWndPtr(hwnd) ) == NULL )
1069 return 0;
1071 if ( ( frameWnd = WIN_LockWndPtr(w->parent) ) == NULL ) {
1072 WIN_ReleaseWndPtr(w);
1073 return 0;
1076 ci = (MDICLIENTINFO *) w->wExtra;
1078 switch (message)
1080 case WM_CREATE:
1082 cs = (LPCREATESTRUCTA)lParam;
1084 /* Translation layer doesn't know what's in the cs->lpCreateParams
1085 * so we have to keep track of what environment we're in. */
1087 if( w->flags & WIN_ISWIN32 )
1089 #define ccs ((LPCLIENTCREATESTRUCT)cs->lpCreateParams)
1090 ci->hWindowMenu = ccs->hWindowMenu;
1091 ci->idFirstChild = ccs->idFirstChild;
1092 #undef ccs
1094 else
1096 LPCLIENTCREATESTRUCT16 ccs = (LPCLIENTCREATESTRUCT16)
1097 PTR_SEG_TO_LIN(cs->lpCreateParams);
1098 ci->hWindowMenu = ccs->hWindowMenu;
1099 ci->idFirstChild = ccs->idFirstChild;
1102 ci->hwndChildMaximized = 0;
1103 ci->nActiveChildren = 0;
1104 ci->nTotalCreated = 0;
1105 ci->frameTitle = NULL;
1106 ci->mdiFlags = 0;
1107 ci->self = hwnd;
1108 w->dwStyle |= WS_CLIPCHILDREN;
1110 if (!hBmpClose)
1112 hBmpClose = CreateMDIMenuBitmap();
1113 hBmpRestore = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_RESTORE) );
1115 MDI_UpdateFrameText(frameWnd, hwnd, MDI_NOFRAMEREPAINT,frameWnd->text);
1117 AppendMenuA( ci->hWindowMenu, MF_SEPARATOR, 0, NULL );
1119 GetClientRect(frameWnd->hwndSelf, &rect);
1120 NC_HandleNCCalcSize( w, &rect );
1121 w->rectClient = rect;
1123 TRACE("Client created - hwnd = %04x, idFirst = %u\n",
1124 hwnd, ci->idFirstChild );
1126 retvalue = 0;
1127 goto END;
1129 case WM_DESTROY:
1130 if( ci->hwndChildMaximized ) MDI_RestoreFrameMenu(w, frameWnd->hwndSelf);
1131 if((nItems = GetMenuItemCount(ci->hWindowMenu)) > 0)
1133 ci->idFirstChild = nItems - 1;
1134 ci->nActiveChildren++; /* to delete a separator */
1135 while( ci->nActiveChildren-- )
1136 DeleteMenu(ci->hWindowMenu,MF_BYPOSITION,ci->idFirstChild--);
1138 retvalue = 0;
1139 goto END;
1141 case WM_MDIACTIVATE:
1142 if( ci->hwndActiveChild != (HWND)wParam )
1143 SetWindowPos((HWND)wParam, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE);
1144 retvalue = 0;
1145 goto END;
1147 case WM_MDICASCADE:
1148 retvalue = MDICascade(w, ci);
1149 goto END;
1151 case WM_MDICREATE:
1152 if (lParam) retvalue = MDICreateChild( w, ci, hwnd,
1153 (MDICREATESTRUCTA*)lParam );
1154 else retvalue = 0;
1155 goto END;
1157 case WM_MDIDESTROY:
1158 retvalue = MDIDestroyChild( w, ci, hwnd, (HWND)wParam, TRUE );
1159 goto END;
1161 case WM_MDIGETACTIVE:
1162 if (lParam) *(BOOL *)lParam = (ci->hwndChildMaximized > 0);
1163 retvalue = ci->hwndActiveChild;
1164 goto END;
1166 case WM_MDIICONARRANGE:
1167 ci->mdiFlags |= MDIF_NEEDUPDATE;
1168 ArrangeIconicWindows(hwnd);
1169 ci->sbRecalc = SB_BOTH+1;
1170 SendMessageA(hwnd, WM_MDICALCCHILDSCROLL, 0, 0L);
1171 retvalue = 0;
1172 goto END;
1174 case WM_MDIMAXIMIZE:
1175 ShowWindow( (HWND)wParam, SW_MAXIMIZE );
1176 retvalue = 0;
1177 goto END;
1179 case WM_MDINEXT: /* lParam != 0 means previous window */
1180 MDI_SwitchActiveChild(hwnd, (HWND)wParam, (lParam)? FALSE : TRUE );
1181 break;
1183 case WM_MDIRESTORE:
1184 SendMessageA( (HWND)wParam, WM_SYSCOMMAND, SC_RESTORE, 0);
1185 retvalue = 0;
1186 goto END;
1188 case WM_MDISETMENU:
1189 retvalue = MDISetMenu( hwnd, (HMENU)wParam, (HMENU)lParam );
1190 goto END;
1191 case WM_MDIREFRESHMENU:
1192 retvalue = MDIRefreshMenu( hwnd, (HMENU)wParam, (HMENU)lParam );
1193 goto END;
1195 case WM_MDITILE:
1196 ci->mdiFlags |= MDIF_NEEDUPDATE;
1197 ShowScrollBar(hwnd,SB_BOTH,FALSE);
1198 MDITile(w, ci, wParam);
1199 ci->mdiFlags &= ~MDIF_NEEDUPDATE;
1200 retvalue = 0;
1201 goto END;
1203 case WM_VSCROLL:
1204 case WM_HSCROLL:
1205 ci->mdiFlags |= MDIF_NEEDUPDATE;
1206 ScrollChildren(hwnd, message, wParam, lParam);
1207 ci->mdiFlags &= ~MDIF_NEEDUPDATE;
1208 retvalue = 0;
1209 goto END;
1211 case WM_SETFOCUS:
1212 if( ci->hwndActiveChild )
1214 WND* pw = WIN_FindWndPtr( ci->hwndActiveChild );
1215 if( !(pw->dwStyle & WS_MINIMIZE) )
1216 SetFocus( ci->hwndActiveChild );
1217 WIN_ReleaseWndPtr(pw);
1219 retvalue = 0;
1220 goto END;
1222 case WM_NCACTIVATE:
1223 if( ci->hwndActiveChild )
1224 SendMessageA(ci->hwndActiveChild, message, wParam, lParam);
1225 break;
1227 case WM_PARENTNOTIFY:
1228 if (LOWORD(wParam) == WM_LBUTTONDOWN)
1230 POINT16 pt = MAKEPOINT16(lParam);
1231 HWND16 child = ChildWindowFromPoint16(hwnd, pt);
1233 TRACE("notification from %04x (%i,%i)\n",child,pt.x,pt.y);
1235 if( child && child != hwnd && child != ci->hwndActiveChild )
1236 SetWindowPos(child, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE );
1238 retvalue = 0;
1239 goto END;
1241 case WM_SIZE:
1242 if( IsWindow(ci->hwndChildMaximized) )
1244 WND* child = WIN_FindWndPtr(ci->hwndChildMaximized);
1245 RECT rect;
1247 rect.left = 0;
1248 rect.top = 0;
1249 rect.right = LOWORD(lParam);
1250 rect.bottom = HIWORD(lParam);
1252 AdjustWindowRectEx(&rect, child->dwStyle, 0, child->dwExStyle);
1253 MoveWindow(ci->hwndChildMaximized, rect.left, rect.top,
1254 rect.right - rect.left, rect.bottom - rect.top, 1);
1255 WIN_ReleaseWndPtr(child);
1257 else
1258 MDI_PostUpdate(hwnd, ci, SB_BOTH+1);
1260 break;
1262 case WM_MDICALCCHILDSCROLL:
1263 if( (ci->mdiFlags & MDIF_NEEDUPDATE) && ci->sbRecalc )
1265 CalcChildScroll16(hwnd, ci->sbRecalc-1);
1266 ci->sbRecalc = 0;
1267 ci->mdiFlags &= ~MDIF_NEEDUPDATE;
1269 retvalue = 0;
1270 goto END;
1273 retvalue = DefWindowProcA( hwnd, message, wParam, lParam );
1274 END:
1275 WIN_ReleaseWndPtr(w);
1276 WIN_ReleaseWndPtr(frameWnd);
1277 return retvalue;
1281 /***********************************************************************
1282 * DefFrameProc16 (USER.445)
1284 LRESULT WINAPI DefFrameProc16( HWND16 hwnd, HWND16 hwndMDIClient,
1285 UINT16 message, WPARAM16 wParam, LPARAM lParam )
1287 HWND16 childHwnd;
1288 MDICLIENTINFO* ci;
1289 WND* wndPtr;
1291 if (hwndMDIClient)
1293 switch (message)
1295 case WM_COMMAND:
1296 wndPtr = WIN_FindWndPtr(hwndMDIClient);
1298 if (!wndPtr) {
1299 ERR("null wndPtr for mdi window hwndMDIClient=%04x\n",
1300 hwndMDIClient);
1301 return 0;
1304 ci = (MDICLIENTINFO*)wndPtr->wExtra;
1306 /* check for possible syscommands for maximized MDI child */
1307 WIN_ReleaseWndPtr(wndPtr);
1309 if( ci && (
1310 wParam < ci->idFirstChild ||
1311 wParam >= ci->idFirstChild + ci->nActiveChildren
1313 if( (wParam - 0xF000) & 0xF00F ) break;
1314 switch( wParam )
1316 case SC_SIZE:
1317 case SC_MOVE:
1318 case SC_MINIMIZE:
1319 case SC_MAXIMIZE:
1320 case SC_NEXTWINDOW:
1321 case SC_PREVWINDOW:
1322 case SC_CLOSE:
1323 case SC_RESTORE:
1324 if( ci->hwndChildMaximized )
1325 return SendMessage16( ci->hwndChildMaximized, WM_SYSCOMMAND,
1326 wParam, lParam);
1329 else
1331 wndPtr = WIN_FindWndPtr(hwndMDIClient);
1332 childHwnd = MDI_GetChildByID(wndPtr,wParam );
1333 WIN_ReleaseWndPtr(wndPtr);
1335 if( childHwnd )
1336 SendMessage16(hwndMDIClient, WM_MDIACTIVATE,
1337 (WPARAM16)childHwnd , 0L);
1339 break;
1341 case WM_NCACTIVATE:
1342 SendMessage16(hwndMDIClient, message, wParam, lParam);
1343 break;
1345 case WM_SETTEXT:
1346 wndPtr = WIN_FindWndPtr(hwnd);
1347 MDI_UpdateFrameText(wndPtr, hwndMDIClient,
1348 MDI_REPAINTFRAME,
1349 (LPCSTR)PTR_SEG_TO_LIN(lParam));
1350 WIN_ReleaseWndPtr(wndPtr);
1351 return 0;
1353 case WM_SETFOCUS:
1354 SetFocus(hwndMDIClient);
1355 break;
1357 case WM_SIZE:
1358 MoveWindow16(hwndMDIClient, 0, 0,
1359 LOWORD(lParam), HIWORD(lParam), TRUE);
1360 break;
1362 case WM_NEXTMENU:
1364 wndPtr = WIN_FindWndPtr(hwndMDIClient);
1365 ci = (MDICLIENTINFO*)wndPtr->wExtra;
1367 if( !(wndPtr->parent->dwStyle & WS_MINIMIZE)
1368 && ci->hwndActiveChild && !ci->hwndChildMaximized )
1370 /* control menu is between the frame system menu and
1371 * the first entry of menu bar */
1373 if( (wParam == VK_LEFT &&
1374 wndPtr->parent->wIDmenu == LOWORD(lParam)) ||
1375 (wParam == VK_RIGHT &&
1376 GetSubMenu16(wndPtr->parent->hSysMenu, 0) == LOWORD(lParam)) )
1378 LRESULT retvalue;
1379 WIN_ReleaseWndPtr(wndPtr);
1380 wndPtr = WIN_FindWndPtr(ci->hwndActiveChild);
1381 retvalue = MAKELONG( GetSubMenu16(wndPtr->hSysMenu, 0),
1382 ci->hwndActiveChild);
1383 WIN_ReleaseWndPtr(wndPtr);
1384 return retvalue;
1387 WIN_ReleaseWndPtr(wndPtr);
1388 break;
1392 return DefWindowProc16(hwnd, message, wParam, lParam);
1396 /***********************************************************************
1397 * DefFrameProc32A (USER32.122)
1399 LRESULT WINAPI DefFrameProcA( HWND hwnd, HWND hwndMDIClient,
1400 UINT message, WPARAM wParam, LPARAM lParam)
1402 if (hwndMDIClient)
1404 switch (message)
1406 case WM_COMMAND:
1407 return DefFrameProc16( hwnd, hwndMDIClient, message,
1408 (WPARAM16)wParam,
1409 MAKELPARAM( (HWND16)lParam, HIWORD(wParam) ) );
1411 case WM_NCACTIVATE:
1412 SendMessageA(hwndMDIClient, message, wParam, lParam);
1413 break;
1415 case WM_SETTEXT: {
1416 LRESULT ret;
1417 LPSTR segstr = SEGPTR_STRDUP((LPSTR)lParam);
1419 ret = DefFrameProc16(hwnd, hwndMDIClient, message,
1420 wParam, (LPARAM)SEGPTR_GET(segstr) );
1421 SEGPTR_FREE(segstr);
1422 return ret;
1425 case WM_NEXTMENU:
1426 case WM_SETFOCUS:
1427 case WM_SIZE:
1428 return DefFrameProc16( hwnd, hwndMDIClient, message,
1429 wParam, lParam );
1433 return DefWindowProcA(hwnd, message, wParam, lParam);
1437 /***********************************************************************
1438 * DefFrameProc32W (USER32.123)
1440 LRESULT WINAPI DefFrameProcW( HWND hwnd, HWND hwndMDIClient,
1441 UINT message, WPARAM wParam, LPARAM lParam)
1443 if (hwndMDIClient)
1445 switch (message)
1447 case WM_COMMAND:
1448 return DefFrameProc16( hwnd, hwndMDIClient, message,
1449 (WPARAM16)wParam,
1450 MAKELPARAM( (HWND16)lParam, HIWORD(wParam) ) );
1452 case WM_NCACTIVATE:
1453 SendMessageW(hwndMDIClient, message, wParam, lParam);
1454 break;
1456 case WM_SETTEXT:
1458 LPSTR txt = HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)lParam);
1459 LRESULT ret = DefFrameProcA( hwnd, hwndMDIClient, message,
1460 wParam, (DWORD)txt );
1461 HeapFree(GetProcessHeap(),0,txt);
1462 return ret;
1464 case WM_NEXTMENU:
1465 case WM_SETFOCUS:
1466 case WM_SIZE:
1467 return DefFrameProcA( hwnd, hwndMDIClient, message,
1468 wParam, lParam );
1472 return DefWindowProcW( hwnd, message, wParam, lParam );
1476 /***********************************************************************
1477 * DefMDIChildProc16 (USER.447)
1479 LRESULT WINAPI DefMDIChildProc16( HWND16 hwnd, UINT16 message,
1480 WPARAM16 wParam, LPARAM lParam )
1482 MDICLIENTINFO *ci;
1483 WND *clientWnd,*tmpWnd = 0;
1484 LRESULT retvalue;
1486 tmpWnd = WIN_FindWndPtr(hwnd);
1487 if (!tmpWnd) return 0;
1488 clientWnd = WIN_FindWndPtr(tmpWnd->parent->hwndSelf);
1489 ci = (MDICLIENTINFO *) clientWnd->wExtra;
1490 WIN_ReleaseWndPtr(tmpWnd);
1492 switch (message)
1494 case WM_SETTEXT:
1495 DefWindowProc16(hwnd, message, wParam, lParam);
1496 MDI_MenuModifyItem(clientWnd,hwnd);
1497 if( ci->hwndChildMaximized == hwnd )
1498 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1499 MDI_REPAINTFRAME, NULL );
1500 retvalue = 0;
1501 goto END;
1503 case WM_CLOSE:
1504 SendMessage16(ci->self,WM_MDIDESTROY,(WPARAM16)hwnd,0L);
1505 retvalue = 0;
1506 goto END;
1508 case WM_SETFOCUS:
1509 if( ci->hwndActiveChild != hwnd )
1510 MDI_ChildActivate(clientWnd, hwnd);
1511 break;
1513 case WM_CHILDACTIVATE:
1514 MDI_ChildActivate(clientWnd, hwnd);
1515 retvalue = 0;
1516 goto END;
1518 case WM_NCPAINT:
1519 TRACE("WM_NCPAINT for %04x, active %04x\n",
1520 hwnd, ci->hwndActiveChild );
1521 break;
1523 case WM_SYSCOMMAND:
1524 switch( wParam )
1526 case SC_MOVE:
1527 if( ci->hwndChildMaximized == hwnd)
1529 retvalue = 0;
1530 goto END;
1532 break;
1533 case SC_RESTORE:
1534 case SC_MINIMIZE:
1535 tmpWnd = WIN_FindWndPtr(hwnd);
1536 tmpWnd->dwStyle |= WS_SYSMENU;
1537 WIN_ReleaseWndPtr(tmpWnd);
1538 break;
1539 case SC_MAXIMIZE:
1540 if( ci->hwndChildMaximized == hwnd)
1542 retvalue = SendMessage16( clientWnd->parent->hwndSelf,
1543 message, wParam, lParam);
1544 goto END;
1546 tmpWnd = WIN_FindWndPtr(hwnd);
1547 tmpWnd->dwStyle &= ~WS_SYSMENU;
1548 WIN_ReleaseWndPtr(tmpWnd);
1549 break;
1550 case SC_NEXTWINDOW:
1551 SendMessage16( ci->self, WM_MDINEXT, 0, 0);
1552 retvalue = 0;
1553 goto END;
1554 case SC_PREVWINDOW:
1555 SendMessage16( ci->self, WM_MDINEXT, 0, 1);
1556 retvalue = 0;
1557 goto END;
1559 break;
1561 case WM_GETMINMAXINFO:
1562 MDI_ChildGetMinMaxInfo(clientWnd, hwnd, (MINMAXINFO16*) PTR_SEG_TO_LIN(lParam));
1563 retvalue = 0;
1564 goto END;
1566 case WM_SETVISIBLE:
1567 if( ci->hwndChildMaximized) ci->mdiFlags &= ~MDIF_NEEDUPDATE;
1568 else
1569 MDI_PostUpdate(clientWnd->hwndSelf, ci, SB_BOTH+1);
1570 break;
1572 case WM_SIZE:
1573 /* do not change */
1575 if( ci->hwndActiveChild == hwnd && wParam != SIZE_MAXIMIZED )
1577 ci->hwndChildMaximized = 0;
1579 MDI_RestoreFrameMenu( clientWnd->parent, hwnd);
1580 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1581 MDI_REPAINTFRAME, NULL );
1584 if( wParam == SIZE_MAXIMIZED )
1586 HWND16 hMaxChild = ci->hwndChildMaximized;
1588 if( hMaxChild == hwnd ) break;
1590 if( hMaxChild)
1592 SendMessage16( hMaxChild, WM_SETREDRAW, FALSE, 0L );
1594 MDI_RestoreFrameMenu( clientWnd->parent, hMaxChild);
1595 ShowWindow16( hMaxChild, SW_SHOWNOACTIVATE);
1597 SendMessage16( hMaxChild, WM_SETREDRAW, TRUE, 0L );
1600 TRACE("maximizing child %04x\n", hwnd );
1602 ci->hwndChildMaximized = hwnd; /* !!! */
1603 ci->hwndActiveChild = hwnd;
1605 MDI_AugmentFrameMenu( ci, clientWnd->parent, hwnd);
1606 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1607 MDI_REPAINTFRAME, NULL );
1610 if( wParam == SIZE_MINIMIZED )
1612 HWND16 switchTo = MDI_GetWindow(clientWnd, hwnd, TRUE, WS_MINIMIZE);
1614 if( switchTo )
1615 SendMessage16( switchTo, WM_CHILDACTIVATE, 0, 0L);
1618 MDI_PostUpdate(clientWnd->hwndSelf, ci, SB_BOTH+1);
1619 break;
1621 case WM_MENUCHAR:
1623 /* MDI children don't have menu bars */
1624 retvalue = 0x00010000L;
1625 goto END;
1627 case WM_NEXTMENU:
1629 if( wParam == VK_LEFT ) /* switch to frame system menu */
1631 retvalue = MAKELONG( GetSubMenu16(clientWnd->parent->hSysMenu, 0),
1632 clientWnd->parent->hwndSelf );
1633 goto END;
1635 if( wParam == VK_RIGHT ) /* to frame menu bar */
1637 retvalue = MAKELONG( clientWnd->parent->wIDmenu,
1638 clientWnd->parent->hwndSelf );
1639 goto END;
1642 break;
1644 case WM_SYSCHAR:
1645 if (wParam == '-')
1647 SendMessage16(hwnd,WM_SYSCOMMAND,
1648 (WPARAM16)SC_KEYMENU, (LPARAM)(DWORD)VK_SPACE);
1649 retvalue = 0;
1650 goto END;
1654 retvalue = DefWindowProc16(hwnd, message, wParam, lParam);
1655 END:
1656 WIN_ReleaseWndPtr(clientWnd);
1657 return retvalue;
1661 /***********************************************************************
1662 * DefMDIChildProc32A (USER32.124)
1664 LRESULT WINAPI DefMDIChildProcA( HWND hwnd, UINT message,
1665 WPARAM wParam, LPARAM lParam )
1667 MDICLIENTINFO *ci;
1668 WND *clientWnd,*tmpWnd;
1669 LRESULT retvalue;
1671 tmpWnd = WIN_FindWndPtr(hwnd);
1672 if (!tmpWnd) return 0;
1673 clientWnd = WIN_FindWndPtr(tmpWnd->parent->hwndSelf);
1674 ci = (MDICLIENTINFO *) clientWnd->wExtra;
1675 WIN_ReleaseWndPtr(tmpWnd);
1677 switch (message)
1679 case WM_SETTEXT:
1680 DefWindowProcA(hwnd, message, wParam, lParam);
1681 MDI_MenuModifyItem(clientWnd,hwnd);
1682 if( ci->hwndChildMaximized == hwnd )
1683 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1684 MDI_REPAINTFRAME, NULL );
1685 retvalue = 0;
1686 goto END;
1688 case WM_GETMINMAXINFO:
1690 MINMAXINFO16 mmi;
1691 STRUCT32_MINMAXINFO32to16( (MINMAXINFO *)lParam, &mmi );
1692 MDI_ChildGetMinMaxInfo( clientWnd, hwnd, &mmi );
1693 STRUCT32_MINMAXINFO16to32( &mmi, (MINMAXINFO *)lParam );
1695 retvalue = 0;
1696 goto END;
1698 case WM_MENUCHAR:
1700 /* MDI children don't have menu bars */
1701 retvalue = 0x00010000L;
1702 goto END;
1704 case WM_CLOSE:
1705 case WM_SETFOCUS:
1706 case WM_CHILDACTIVATE:
1707 case WM_NCPAINT:
1708 case WM_SYSCOMMAND:
1709 case WM_SETVISIBLE:
1710 case WM_SIZE:
1711 case WM_NEXTMENU:
1712 retvalue = DefMDIChildProc16( hwnd, message, (WPARAM16)wParam, lParam );
1713 goto END;
1715 case WM_SYSCHAR:
1716 if (wParam == '-')
1718 SendMessageA(hwnd,WM_SYSCOMMAND,
1719 (WPARAM)SC_KEYMENU, (LPARAM)(DWORD)VK_SPACE);
1720 retvalue = 0;
1721 goto END;
1724 retvalue = DefWindowProcA(hwnd, message, wParam, lParam);
1725 END:
1726 WIN_ReleaseWndPtr(clientWnd);
1727 return retvalue;
1731 /***********************************************************************
1732 * DefMDIChildProc32W (USER32.125)
1734 LRESULT WINAPI DefMDIChildProcW( HWND hwnd, UINT message,
1735 WPARAM wParam, LPARAM lParam )
1737 MDICLIENTINFO *ci;
1738 WND *clientWnd,*tmpWnd;
1739 LRESULT retvalue;
1741 tmpWnd = WIN_FindWndPtr(hwnd);
1742 if (!tmpWnd) return 0;
1743 clientWnd = WIN_FindWndPtr(tmpWnd->parent->hwndSelf);
1744 ci = (MDICLIENTINFO *) clientWnd->wExtra;
1745 WIN_ReleaseWndPtr(tmpWnd);
1747 switch (message)
1749 case WM_SETTEXT:
1750 DefWindowProcW(hwnd, message, wParam, lParam);
1751 MDI_MenuModifyItem(clientWnd,hwnd);
1752 if( ci->hwndChildMaximized == hwnd )
1753 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1754 MDI_REPAINTFRAME, NULL );
1755 retvalue = 0;
1756 goto END;
1758 case WM_GETMINMAXINFO:
1759 case WM_MENUCHAR:
1760 case WM_CLOSE:
1761 case WM_SETFOCUS:
1762 case WM_CHILDACTIVATE:
1763 case WM_NCPAINT:
1764 case WM_SYSCOMMAND:
1765 case WM_SETVISIBLE:
1766 case WM_SIZE:
1767 case WM_NEXTMENU:
1768 retvalue = DefMDIChildProcA( hwnd, message, (WPARAM16)wParam, lParam );
1769 goto END;
1771 case WM_SYSCHAR:
1772 if (wParam == '-')
1774 SendMessageW(hwnd,WM_SYSCOMMAND,
1775 (WPARAM)SC_KEYMENU, (LPARAM)(DWORD)VK_SPACE);
1776 retvalue = 0;
1777 goto END;
1780 retvalue = DefWindowProcW(hwnd, message, wParam, lParam);
1781 END:
1782 WIN_ReleaseWndPtr(clientWnd);
1783 return retvalue;
1788 /**********************************************************************
1789 * CreateMDIWindowA [USER32.79] Creates a MDI child in new thread
1790 * FIXME: its in the same thread now
1792 * RETURNS
1793 * Success: Handle to created window
1794 * Failure: NULL
1796 HWND WINAPI CreateMDIWindowA(
1797 LPCSTR lpClassName, /* [in] Pointer to registered child class name */
1798 LPCSTR lpWindowName, /* [in] Pointer to window name */
1799 DWORD dwStyle, /* [in] Window style */
1800 INT X, /* [in] Horizontal position of window */
1801 INT Y, /* [in] Vertical position of window */
1802 INT nWidth, /* [in] Width of window */
1803 INT nHeight, /* [in] Height of window */
1804 HWND hWndParent, /* [in] Handle to parent window */
1805 HINSTANCE hInstance, /* [in] Handle to application instance */
1806 LPARAM lParam) /* [in] Application-defined value */
1808 WARN("is only single threaded!\n");
1809 return MDI_CreateMDIWindowA(lpClassName, lpWindowName, dwStyle, X, Y,
1810 nWidth, nHeight, hWndParent, hInstance, lParam);
1813 /**********************************************************************
1814 * MDI_CreateMDIWindowA
1815 * single threaded version of CreateMDIWindowA
1816 * called by CreateWindowEx32A
1818 HWND MDI_CreateMDIWindowA(
1819 LPCSTR lpClassName,
1820 LPCSTR lpWindowName,
1821 DWORD dwStyle,
1822 INT X,
1823 INT Y,
1824 INT nWidth,
1825 INT nHeight,
1826 HWND hWndParent,
1827 HINSTANCE hInstance,
1828 LPARAM lParam)
1830 MDICLIENTINFO* pCi;
1831 MDICREATESTRUCTA cs;
1832 WND *pWnd=WIN_FindWndPtr(hWndParent);
1833 HWND retvalue;
1835 TRACE("(%s,%s,%ld,%d,%d,%d,%d,%x,%d,%ld)\n",
1836 debugstr_a(lpClassName),debugstr_a(lpWindowName),dwStyle,X,Y,
1837 nWidth,nHeight,hWndParent,hInstance,lParam);
1839 if(!pWnd){
1840 ERR(" bad hwnd for MDI-client: %d\n",hWndParent);
1841 return 0;
1843 cs.szClass=lpClassName;
1844 cs.szTitle=lpWindowName;
1845 cs.hOwner=hInstance;
1846 cs.x=X;
1847 cs.y=Y;
1848 cs.cx=nWidth;
1849 cs.cy=nHeight;
1850 cs.style=dwStyle;
1851 cs.lParam=lParam;
1853 pCi=(MDICLIENTINFO *)pWnd->wExtra;
1855 retvalue = MDICreateChild(pWnd,pCi,hWndParent,&cs);
1856 WIN_ReleaseWndPtr(pWnd);
1857 return retvalue;
1860 /***************************************
1861 * CreateMDIWindow32W [USER32.80] Creates a MDI child in new thread
1863 * RETURNS
1864 * Success: Handle to created window
1865 * Failure: NULL
1867 HWND WINAPI 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 * CreateMDIWindow32W [USER32.80] Creates a MDI child window
1888 * single threaded version of CreateMDIWindow
1889 * called by CreateWindowEx32W().
1891 HWND MDI_CreateMDIWindowW(
1892 LPCWSTR lpClassName, /* [in] Pointer to registered child class name */
1893 LPCWSTR lpWindowName, /* [in] Pointer to window name */
1894 DWORD dwStyle, /* [in] Window style */
1895 INT X, /* [in] Horizontal position of window */
1896 INT Y, /* [in] Vertical position of window */
1897 INT nWidth, /* [in] Width of window */
1898 INT nHeight, /* [in] Height of window */
1899 HWND hWndParent, /* [in] Handle to parent window */
1900 HINSTANCE hInstance, /* [in] Handle to application instance */
1901 LPARAM lParam) /* [in] Application-defined value */
1903 FIXME("(%s,%s,%ld,%d,%d,%d,%d,%x,%d,%ld): stub\n",
1904 debugstr_w(lpClassName),debugstr_w(lpWindowName),dwStyle,X,Y,
1905 nWidth,nHeight,hWndParent,hInstance,lParam);
1906 return (HWND)NULL;
1910 /**********************************************************************
1911 * TranslateMDISysAccel32 (USER32.555)
1913 BOOL WINAPI TranslateMDISysAccel( HWND hwndClient, LPMSG msg )
1915 MSG16 msg16;
1917 STRUCT32_MSG32to16(msg,&msg16);
1918 /* MDICLIENTINFO is still the same for win32 and win16 ... */
1919 return TranslateMDISysAccel16(hwndClient,&msg16);
1923 /**********************************************************************
1924 * TranslateMDISysAccel16 (USER.451)
1926 BOOL16 WINAPI TranslateMDISysAccel16( HWND16 hwndClient, LPMSG16 msg )
1929 if( IsWindow(hwndClient) && (msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN))
1931 MDICLIENTINFO *ci = NULL;
1932 HWND wnd;
1933 WND *clientWnd = WIN_FindWndPtr(hwndClient);
1935 ci = (MDICLIENTINFO*) clientWnd->wExtra;
1936 wnd = ci->hwndActiveChild;
1938 WIN_ReleaseWndPtr(clientWnd);
1940 if( IsWindow(wnd) && !(GetWindowLongA(wnd,GWL_STYLE) & WS_DISABLED) )
1942 WPARAM16 wParam = 0;
1944 /* translate if the Ctrl key is down and Alt not. */
1946 if( (GetKeyState(VK_CONTROL) & 0x8000) &&
1947 !(GetKeyState(VK_MENU) & 0x8000))
1949 switch( msg->wParam )
1951 case VK_F6:
1952 case VK_TAB:
1953 wParam = ( GetKeyState(VK_SHIFT) & 0x8000 )
1954 ? SC_NEXTWINDOW : SC_PREVWINDOW;
1955 break;
1956 case VK_F4:
1957 case VK_RBUTTON:
1958 wParam = SC_CLOSE;
1959 break;
1960 default:
1961 return 0;
1963 TRACE("wParam = %04x\n", wParam);
1964 SendMessage16( ci->hwndActiveChild, WM_SYSCOMMAND,
1965 wParam, (LPARAM)msg->wParam);
1966 return 1;
1970 return 0; /* failure */
1974 /***********************************************************************
1975 * CalcChildScroll (USER.462)
1977 void WINAPI CalcChildScroll16( HWND16 hwnd, WORD scroll )
1979 SCROLLINFO info;
1980 RECT childRect, clientRect;
1981 INT vmin, vmax, hmin, hmax, vpos, hpos;
1982 WND *pWnd, *Wnd;
1984 if (!(pWnd = WIN_FindWndPtr( hwnd ))) return;
1985 Wnd = WIN_FindWndPtr(hwnd);
1986 GetClientRect( hwnd, &clientRect );
1987 SetRectEmpty( &childRect );
1989 for ( WIN_UpdateWndPtr(&pWnd,pWnd->child); pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1991 if( pWnd->dwStyle & WS_MAXIMIZE )
1993 ShowScrollBar(hwnd, SB_BOTH, FALSE);
1994 WIN_ReleaseWndPtr(pWnd);
1995 WIN_ReleaseWndPtr(Wnd);
1996 return;
1998 UnionRect( &childRect, &pWnd->rectWindow, &childRect );
2000 WIN_ReleaseWndPtr(pWnd);
2001 UnionRect( &childRect, &clientRect, &childRect );
2003 hmin = childRect.left; hmax = childRect.right - clientRect.right;
2004 hpos = clientRect.left - childRect.left;
2005 vmin = childRect.top; vmax = childRect.bottom - clientRect.bottom;
2006 vpos = clientRect.top - childRect.top;
2008 switch( scroll )
2010 case SB_HORZ:
2011 vpos = hpos; vmin = hmin; vmax = hmax;
2012 case SB_VERT:
2013 info.cbSize = sizeof(info);
2014 info.nMax = vmax; info.nMin = vmin; info.nPos = vpos;
2015 info.fMask = SIF_POS | SIF_RANGE;
2016 SetScrollInfo(hwnd, scroll, &info, TRUE);
2017 break;
2018 case SB_BOTH:
2019 SCROLL_SetNCSbState( Wnd, vmin, vmax, vpos,
2020 hmin, hmax, hpos);
2022 WIN_ReleaseWndPtr(Wnd);
2026 /***********************************************************************
2027 * ScrollChildren16 (USER.463)
2029 void WINAPI ScrollChildren16(HWND16 hWnd, UINT16 uMsg, WPARAM16 wParam, LPARAM lParam)
2031 ScrollChildren( hWnd, uMsg, wParam, lParam );
2035 /***********************************************************************
2036 * ScrollChildren32 (USER32.448)
2038 void WINAPI ScrollChildren(HWND hWnd, UINT uMsg, WPARAM wParam,
2039 LPARAM lParam)
2041 WND *wndPtr = WIN_FindWndPtr(hWnd);
2042 INT newPos = -1;
2043 INT curPos, length, minPos, maxPos, shift;
2045 if( !wndPtr ) return;
2047 if( uMsg == WM_HSCROLL )
2049 GetScrollRange(hWnd,SB_HORZ,&minPos,&maxPos);
2050 curPos = GetScrollPos(hWnd,SB_HORZ);
2051 length = (wndPtr->rectClient.right - wndPtr->rectClient.left)/2;
2052 shift = GetSystemMetrics(SM_CYHSCROLL);
2054 else if( uMsg == WM_VSCROLL )
2056 GetScrollRange(hWnd,SB_VERT,&minPos,&maxPos);
2057 curPos = GetScrollPos(hWnd,SB_VERT);
2058 length = (wndPtr->rectClient.bottom - wndPtr->rectClient.top)/2;
2059 shift = GetSystemMetrics(SM_CXVSCROLL);
2061 else
2063 WIN_ReleaseWndPtr(wndPtr);
2064 return;
2067 WIN_ReleaseWndPtr(wndPtr);
2068 switch( wParam )
2070 case SB_LINEUP:
2071 newPos = curPos - shift;
2072 break;
2073 case SB_LINEDOWN:
2074 newPos = curPos + shift;
2075 break;
2076 case SB_PAGEUP:
2077 newPos = curPos - length;
2078 break;
2079 case SB_PAGEDOWN:
2080 newPos = curPos + length;
2081 break;
2083 case SB_THUMBPOSITION:
2084 newPos = LOWORD(lParam);
2085 break;
2087 case SB_THUMBTRACK:
2088 return;
2090 case SB_TOP:
2091 newPos = minPos;
2092 break;
2093 case SB_BOTTOM:
2094 newPos = maxPos;
2095 break;
2096 case SB_ENDSCROLL:
2097 CalcChildScroll16(hWnd,(uMsg == WM_VSCROLL)?SB_VERT:SB_HORZ);
2098 return;
2101 if( newPos > maxPos )
2102 newPos = maxPos;
2103 else
2104 if( newPos < minPos )
2105 newPos = minPos;
2107 SetScrollPos(hWnd, (uMsg == WM_VSCROLL)?SB_VERT:SB_HORZ , newPos, TRUE);
2109 if( uMsg == WM_VSCROLL )
2110 ScrollWindowEx(hWnd ,0 ,curPos - newPos, NULL, NULL, 0, NULL,
2111 SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
2112 else
2113 ScrollWindowEx(hWnd ,curPos - newPos, 0, NULL, NULL, 0, NULL,
2114 SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
2118 /******************************************************************************
2119 * CascadeWindows [USER32.21] Cascades MDI child windows
2121 * RETURNS
2122 * Success: Number of cascaded windows.
2123 * Failure: 0
2125 WORD WINAPI
2126 CascadeWindows (HWND hwndParent, UINT wFlags, const LPRECT lpRect,
2127 UINT cKids, const HWND *lpKids)
2129 FIXME("(0x%08x,0x%08x,...,%u,...): stub\n",
2130 hwndParent, wFlags, cKids);
2132 return 0;
2136 /******************************************************************************
2137 * TileWindows [USER32.545] Tiles MDI child windows
2139 * RETURNS
2140 * Success: Number of tiled windows.
2141 * Failure: 0
2143 WORD WINAPI
2144 TileWindows (HWND hwndParent, UINT wFlags, const LPRECT lpRect,
2145 UINT cKids, const HWND *lpKids)
2147 FIXME("(0x%08x,0x%08x,...,%u,...): stub\n",
2148 hwndParent, wFlags, cKids);
2150 return 0;