Added registry support to the server.
[wine.git] / windows / mdi.c
blobed2d49d9ada6c7f5ce0a6193910cbf54b168fb96
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 clientWnd = WIN_FindWndPtr(GetParent16(hwnd));
1487 ci = (MDICLIENTINFO *) clientWnd->wExtra;
1489 switch (message)
1491 case WM_SETTEXT:
1492 DefWindowProc16(hwnd, message, wParam, lParam);
1493 MDI_MenuModifyItem(clientWnd,hwnd);
1494 if( ci->hwndChildMaximized == hwnd )
1495 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1496 MDI_REPAINTFRAME, NULL );
1497 retvalue = 0;
1498 goto END;
1500 case WM_CLOSE:
1501 SendMessage16(ci->self,WM_MDIDESTROY,(WPARAM16)hwnd,0L);
1502 retvalue = 0;
1503 goto END;
1505 case WM_SETFOCUS:
1506 if( ci->hwndActiveChild != hwnd )
1507 MDI_ChildActivate(clientWnd, hwnd);
1508 break;
1510 case WM_CHILDACTIVATE:
1511 MDI_ChildActivate(clientWnd, hwnd);
1512 retvalue = 0;
1513 goto END;
1515 case WM_NCPAINT:
1516 TRACE("WM_NCPAINT for %04x, active %04x\n",
1517 hwnd, ci->hwndActiveChild );
1518 break;
1520 case WM_SYSCOMMAND:
1521 switch( wParam )
1523 case SC_MOVE:
1524 if( ci->hwndChildMaximized == hwnd)
1526 retvalue = 0;
1527 goto END;
1529 break;
1530 case SC_RESTORE:
1531 case SC_MINIMIZE:
1532 tmpWnd = WIN_FindWndPtr(hwnd);
1533 tmpWnd->dwStyle |= WS_SYSMENU;
1534 WIN_ReleaseWndPtr(tmpWnd);
1535 break;
1536 case SC_MAXIMIZE:
1537 if( ci->hwndChildMaximized == hwnd)
1539 retvalue = SendMessage16( clientWnd->parent->hwndSelf,
1540 message, wParam, lParam);
1541 goto END;
1543 tmpWnd = WIN_FindWndPtr(hwnd);
1544 tmpWnd->dwStyle &= ~WS_SYSMENU;
1545 WIN_ReleaseWndPtr(tmpWnd);
1546 break;
1547 case SC_NEXTWINDOW:
1548 SendMessage16( ci->self, WM_MDINEXT, 0, 0);
1549 retvalue = 0;
1550 goto END;
1551 case SC_PREVWINDOW:
1552 SendMessage16( ci->self, WM_MDINEXT, 0, 1);
1553 retvalue = 0;
1554 goto END;
1556 break;
1558 case WM_GETMINMAXINFO:
1559 MDI_ChildGetMinMaxInfo(clientWnd, hwnd, (MINMAXINFO16*) PTR_SEG_TO_LIN(lParam));
1560 retvalue = 0;
1561 goto END;
1563 case WM_SETVISIBLE:
1564 if( ci->hwndChildMaximized) ci->mdiFlags &= ~MDIF_NEEDUPDATE;
1565 else
1566 MDI_PostUpdate(clientWnd->hwndSelf, ci, SB_BOTH+1);
1567 break;
1569 case WM_SIZE:
1570 /* do not change */
1572 if( ci->hwndActiveChild == hwnd && wParam != SIZE_MAXIMIZED )
1574 ci->hwndChildMaximized = 0;
1576 MDI_RestoreFrameMenu( clientWnd->parent, hwnd);
1577 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1578 MDI_REPAINTFRAME, NULL );
1581 if( wParam == SIZE_MAXIMIZED )
1583 HWND16 hMaxChild = ci->hwndChildMaximized;
1585 if( hMaxChild == hwnd ) break;
1587 if( hMaxChild)
1589 SendMessage16( hMaxChild, WM_SETREDRAW, FALSE, 0L );
1591 MDI_RestoreFrameMenu( clientWnd->parent, hMaxChild);
1592 ShowWindow16( hMaxChild, SW_SHOWNOACTIVATE);
1594 SendMessage16( hMaxChild, WM_SETREDRAW, TRUE, 0L );
1597 TRACE("maximizing child %04x\n", hwnd );
1599 ci->hwndChildMaximized = hwnd; /* !!! */
1600 ci->hwndActiveChild = hwnd;
1602 MDI_AugmentFrameMenu( ci, clientWnd->parent, hwnd);
1603 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1604 MDI_REPAINTFRAME, NULL );
1607 if( wParam == SIZE_MINIMIZED )
1609 HWND16 switchTo = MDI_GetWindow(clientWnd, hwnd, TRUE, WS_MINIMIZE);
1611 if( switchTo )
1612 SendMessage16( switchTo, WM_CHILDACTIVATE, 0, 0L);
1615 MDI_PostUpdate(clientWnd->hwndSelf, ci, SB_BOTH+1);
1616 break;
1618 case WM_MENUCHAR:
1620 /* MDI children don't have menu bars */
1621 retvalue = 0x00010000L;
1622 goto END;
1624 case WM_NEXTMENU:
1626 if( wParam == VK_LEFT ) /* switch to frame system menu */
1628 retvalue = MAKELONG( GetSubMenu16(clientWnd->parent->hSysMenu, 0),
1629 clientWnd->parent->hwndSelf );
1630 goto END;
1632 if( wParam == VK_RIGHT ) /* to frame menu bar */
1634 retvalue = MAKELONG( clientWnd->parent->wIDmenu,
1635 clientWnd->parent->hwndSelf );
1636 goto END;
1639 break;
1641 case WM_SYSCHAR:
1642 if (wParam == '-')
1644 SendMessage16(hwnd,WM_SYSCOMMAND,
1645 (WPARAM16)SC_KEYMENU, (LPARAM)(DWORD)VK_SPACE);
1646 retvalue = 0;
1647 goto END;
1651 retvalue = DefWindowProc16(hwnd, message, wParam, lParam);
1652 END:
1653 WIN_ReleaseWndPtr(clientWnd);
1654 return retvalue;
1658 /***********************************************************************
1659 * DefMDIChildProc32A (USER32.124)
1661 LRESULT WINAPI DefMDIChildProcA( HWND hwnd, UINT message,
1662 WPARAM wParam, LPARAM lParam )
1664 MDICLIENTINFO *ci;
1665 WND *clientWnd,*tmpWnd;
1666 LRESULT retvalue;
1668 tmpWnd = WIN_FindWndPtr(hwnd);
1669 clientWnd = WIN_FindWndPtr(tmpWnd->parent->hwndSelf);
1670 ci = (MDICLIENTINFO *) clientWnd->wExtra;
1671 WIN_ReleaseWndPtr(tmpWnd);
1673 switch (message)
1675 case WM_SETTEXT:
1676 DefWindowProcA(hwnd, message, wParam, lParam);
1677 MDI_MenuModifyItem(clientWnd,hwnd);
1678 if( ci->hwndChildMaximized == hwnd )
1679 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1680 MDI_REPAINTFRAME, NULL );
1681 retvalue = 0;
1682 goto END;
1684 case WM_GETMINMAXINFO:
1686 MINMAXINFO16 mmi;
1687 STRUCT32_MINMAXINFO32to16( (MINMAXINFO *)lParam, &mmi );
1688 MDI_ChildGetMinMaxInfo( clientWnd, hwnd, &mmi );
1689 STRUCT32_MINMAXINFO16to32( &mmi, (MINMAXINFO *)lParam );
1691 retvalue = 0;
1692 goto END;
1694 case WM_MENUCHAR:
1696 /* MDI children don't have menu bars */
1697 retvalue = 0x00010000L;
1698 goto END;
1700 case WM_CLOSE:
1701 case WM_SETFOCUS:
1702 case WM_CHILDACTIVATE:
1703 case WM_NCPAINT:
1704 case WM_SYSCOMMAND:
1705 case WM_SETVISIBLE:
1706 case WM_SIZE:
1707 case WM_NEXTMENU:
1708 retvalue = DefMDIChildProc16( hwnd, message, (WPARAM16)wParam, lParam );
1709 goto END;
1711 case WM_SYSCHAR:
1712 if (wParam == '-')
1714 SendMessageA(hwnd,WM_SYSCOMMAND,
1715 (WPARAM)SC_KEYMENU, (LPARAM)(DWORD)VK_SPACE);
1716 retvalue = 0;
1717 goto END;
1720 retvalue = DefWindowProcA(hwnd, message, wParam, lParam);
1721 END:
1722 WIN_ReleaseWndPtr(clientWnd);
1723 return retvalue;
1727 /***********************************************************************
1728 * DefMDIChildProc32W (USER32.125)
1730 LRESULT WINAPI DefMDIChildProcW( HWND hwnd, UINT message,
1731 WPARAM wParam, LPARAM lParam )
1733 MDICLIENTINFO *ci;
1734 WND *clientWnd;
1735 LRESULT retvalue;
1737 clientWnd = WIN_FindWndPtr(GetParent16(hwnd));
1738 ci = (MDICLIENTINFO *) clientWnd->wExtra;
1740 switch (message)
1742 case WM_SETTEXT:
1743 DefWindowProcW(hwnd, message, wParam, lParam);
1744 MDI_MenuModifyItem(clientWnd,hwnd);
1745 if( ci->hwndChildMaximized == hwnd )
1746 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1747 MDI_REPAINTFRAME, NULL );
1748 retvalue = 0;
1749 goto END;
1751 case WM_GETMINMAXINFO:
1752 case WM_MENUCHAR:
1753 case WM_CLOSE:
1754 case WM_SETFOCUS:
1755 case WM_CHILDACTIVATE:
1756 case WM_NCPAINT:
1757 case WM_SYSCOMMAND:
1758 case WM_SETVISIBLE:
1759 case WM_SIZE:
1760 case WM_NEXTMENU:
1761 retvalue = DefMDIChildProcA( hwnd, message, (WPARAM16)wParam, lParam );
1762 goto END;
1764 case WM_SYSCHAR:
1765 if (wParam == '-')
1767 SendMessageW(hwnd,WM_SYSCOMMAND,
1768 (WPARAM)SC_KEYMENU, (LPARAM)(DWORD)VK_SPACE);
1769 retvalue = 0;
1770 goto END;
1773 retvalue = DefWindowProcW(hwnd, message, wParam, lParam);
1774 END:
1775 WIN_ReleaseWndPtr(clientWnd);
1776 return retvalue;
1781 /**********************************************************************
1782 * CreateMDIWindowA [USER32.79] Creates a MDI child in new thread
1783 * FIXME: its in the same thread now
1785 * RETURNS
1786 * Success: Handle to created window
1787 * Failure: NULL
1789 HWND WINAPI CreateMDIWindowA(
1790 LPCSTR lpClassName, /* [in] Pointer to registered child class name */
1791 LPCSTR lpWindowName, /* [in] Pointer to window name */
1792 DWORD dwStyle, /* [in] Window style */
1793 INT X, /* [in] Horizontal position of window */
1794 INT Y, /* [in] Vertical position of window */
1795 INT nWidth, /* [in] Width of window */
1796 INT nHeight, /* [in] Height of window */
1797 HWND hWndParent, /* [in] Handle to parent window */
1798 HINSTANCE hInstance, /* [in] Handle to application instance */
1799 LPARAM lParam) /* [in] Application-defined value */
1801 WARN("is only single threaded!\n");
1802 return MDI_CreateMDIWindowA(lpClassName, lpWindowName, dwStyle, X, Y,
1803 nWidth, nHeight, hWndParent, hInstance, lParam);
1806 /**********************************************************************
1807 * MDI_CreateMDIWindowA
1808 * single threaded version of CreateMDIWindowA
1809 * called by CreateWindowEx32A
1811 HWND MDI_CreateMDIWindowA(
1812 LPCSTR lpClassName,
1813 LPCSTR lpWindowName,
1814 DWORD dwStyle,
1815 INT X,
1816 INT Y,
1817 INT nWidth,
1818 INT nHeight,
1819 HWND hWndParent,
1820 HINSTANCE hInstance,
1821 LPARAM lParam)
1823 MDICLIENTINFO* pCi;
1824 MDICREATESTRUCTA cs;
1825 WND *pWnd=WIN_FindWndPtr(hWndParent);
1826 HWND retvalue;
1828 TRACE("(%s,%s,%ld,%d,%d,%d,%d,%x,%d,%ld)\n",
1829 debugstr_a(lpClassName),debugstr_a(lpWindowName),dwStyle,X,Y,
1830 nWidth,nHeight,hWndParent,hInstance,lParam);
1832 if(!pWnd){
1833 ERR(" bad hwnd for MDI-client: %d\n",hWndParent);
1834 return 0;
1836 cs.szClass=lpClassName;
1837 cs.szTitle=lpWindowName;
1838 cs.hOwner=hInstance;
1839 cs.x=X;
1840 cs.y=Y;
1841 cs.cx=nWidth;
1842 cs.cy=nHeight;
1843 cs.style=dwStyle;
1844 cs.lParam=lParam;
1846 pCi=(MDICLIENTINFO *)pWnd->wExtra;
1848 retvalue = MDICreateChild(pWnd,pCi,hWndParent,&cs);
1849 WIN_ReleaseWndPtr(pWnd);
1850 return retvalue;
1853 /***************************************
1854 * CreateMDIWindow32W [USER32.80] Creates a MDI child in new thread
1856 * RETURNS
1857 * Success: Handle to created window
1858 * Failure: NULL
1860 HWND WINAPI CreateMDIWindowW(
1861 LPCWSTR lpClassName, /* [in] Pointer to registered child class name */
1862 LPCWSTR lpWindowName, /* [in] Pointer to window name */
1863 DWORD dwStyle, /* [in] Window style */
1864 INT X, /* [in] Horizontal position of window */
1865 INT Y, /* [in] Vertical position of window */
1866 INT nWidth, /* [in] Width of window */
1867 INT nHeight, /* [in] Height of window */
1868 HWND hWndParent, /* [in] Handle to parent window */
1869 HINSTANCE hInstance, /* [in] Handle to application instance */
1870 LPARAM lParam) /* [in] Application-defined value */
1872 FIXME("(%s,%s,%ld,%d,%d,%d,%d,%x,%d,%ld): stub\n",
1873 debugstr_w(lpClassName),debugstr_w(lpWindowName),dwStyle,X,Y,
1874 nWidth,nHeight,hWndParent,hInstance,lParam);
1875 return (HWND)NULL;
1879 /******************************************************************************
1880 * CreateMDIWindow32W [USER32.80] Creates a MDI child window
1881 * single threaded version of CreateMDIWindow
1882 * called by CreateWindowEx32W().
1884 HWND MDI_CreateMDIWindowW(
1885 LPCWSTR lpClassName, /* [in] Pointer to registered child class name */
1886 LPCWSTR lpWindowName, /* [in] Pointer to window name */
1887 DWORD dwStyle, /* [in] Window style */
1888 INT X, /* [in] Horizontal position of window */
1889 INT Y, /* [in] Vertical position of window */
1890 INT nWidth, /* [in] Width of window */
1891 INT nHeight, /* [in] Height of window */
1892 HWND hWndParent, /* [in] Handle to parent window */
1893 HINSTANCE hInstance, /* [in] Handle to application instance */
1894 LPARAM lParam) /* [in] Application-defined value */
1896 FIXME("(%s,%s,%ld,%d,%d,%d,%d,%x,%d,%ld): stub\n",
1897 debugstr_w(lpClassName),debugstr_w(lpWindowName),dwStyle,X,Y,
1898 nWidth,nHeight,hWndParent,hInstance,lParam);
1899 return (HWND)NULL;
1903 /**********************************************************************
1904 * TranslateMDISysAccel32 (USER32.555)
1906 BOOL WINAPI TranslateMDISysAccel( HWND hwndClient, LPMSG msg )
1908 MSG16 msg16;
1910 STRUCT32_MSG32to16(msg,&msg16);
1911 /* MDICLIENTINFO is still the same for win32 and win16 ... */
1912 return TranslateMDISysAccel16(hwndClient,&msg16);
1916 /**********************************************************************
1917 * TranslateMDISysAccel16 (USER.451)
1919 BOOL16 WINAPI TranslateMDISysAccel16( HWND16 hwndClient, LPMSG16 msg )
1922 if( IsWindow(hwndClient) && (msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN))
1924 MDICLIENTINFO *ci = NULL;
1925 HWND wnd;
1926 WND *clientWnd = WIN_FindWndPtr(hwndClient);
1928 ci = (MDICLIENTINFO*) clientWnd->wExtra;
1929 wnd = ci->hwndActiveChild;
1931 WIN_ReleaseWndPtr(clientWnd);
1933 if( IsWindow(wnd) && !(GetWindowLongA(wnd,GWL_STYLE) & WS_DISABLED) )
1935 WPARAM16 wParam = 0;
1937 /* translate if the Ctrl key is down and Alt not. */
1939 if( (GetKeyState(VK_CONTROL) & 0x8000) &&
1940 !(GetKeyState(VK_MENU) & 0x8000))
1942 switch( msg->wParam )
1944 case VK_F6:
1945 case VK_TAB:
1946 wParam = ( GetKeyState(VK_SHIFT) & 0x8000 )
1947 ? SC_NEXTWINDOW : SC_PREVWINDOW;
1948 break;
1949 case VK_F4:
1950 case VK_RBUTTON:
1951 wParam = SC_CLOSE;
1952 break;
1953 default:
1954 return 0;
1956 TRACE("wParam = %04x\n", wParam);
1957 SendMessage16( ci->hwndActiveChild, WM_SYSCOMMAND,
1958 wParam, (LPARAM)msg->wParam);
1959 return 1;
1963 return 0; /* failure */
1967 /***********************************************************************
1968 * CalcChildScroll (USER.462)
1970 void WINAPI CalcChildScroll16( HWND16 hwnd, WORD scroll )
1972 SCROLLINFO info;
1973 RECT childRect, clientRect;
1974 INT vmin, vmax, hmin, hmax, vpos, hpos;
1975 WND *pWnd, *Wnd;
1977 if (!(pWnd = WIN_FindWndPtr( hwnd ))) return;
1978 Wnd = WIN_FindWndPtr(hwnd);
1979 GetClientRect( hwnd, &clientRect );
1980 SetRectEmpty( &childRect );
1982 for ( WIN_UpdateWndPtr(&pWnd,pWnd->child); pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1984 if( pWnd->dwStyle & WS_MAXIMIZE )
1986 ShowScrollBar(hwnd, SB_BOTH, FALSE);
1987 WIN_ReleaseWndPtr(pWnd);
1988 WIN_ReleaseWndPtr(Wnd);
1989 return;
1991 UnionRect( &childRect, &pWnd->rectWindow, &childRect );
1993 WIN_ReleaseWndPtr(pWnd);
1994 UnionRect( &childRect, &clientRect, &childRect );
1996 hmin = childRect.left; hmax = childRect.right - clientRect.right;
1997 hpos = clientRect.left - childRect.left;
1998 vmin = childRect.top; vmax = childRect.bottom - clientRect.bottom;
1999 vpos = clientRect.top - childRect.top;
2001 switch( scroll )
2003 case SB_HORZ:
2004 vpos = hpos; vmin = hmin; vmax = hmax;
2005 case SB_VERT:
2006 info.cbSize = sizeof(info);
2007 info.nMax = vmax; info.nMin = vmin; info.nPos = vpos;
2008 info.fMask = SIF_POS | SIF_RANGE;
2009 SetScrollInfo(hwnd, scroll, &info, TRUE);
2010 break;
2011 case SB_BOTH:
2012 SCROLL_SetNCSbState( Wnd, vmin, vmax, vpos,
2013 hmin, hmax, hpos);
2015 WIN_ReleaseWndPtr(Wnd);
2019 /***********************************************************************
2020 * ScrollChildren16 (USER.463)
2022 void WINAPI ScrollChildren16(HWND16 hWnd, UINT16 uMsg, WPARAM16 wParam, LPARAM lParam)
2024 ScrollChildren( hWnd, uMsg, wParam, lParam );
2028 /***********************************************************************
2029 * ScrollChildren32 (USER32.448)
2031 void WINAPI ScrollChildren(HWND hWnd, UINT uMsg, WPARAM wParam,
2032 LPARAM lParam)
2034 WND *wndPtr = WIN_FindWndPtr(hWnd);
2035 INT newPos = -1;
2036 INT curPos, length, minPos, maxPos, shift;
2038 if( !wndPtr ) return;
2040 if( uMsg == WM_HSCROLL )
2042 GetScrollRange(hWnd,SB_HORZ,&minPos,&maxPos);
2043 curPos = GetScrollPos(hWnd,SB_HORZ);
2044 length = (wndPtr->rectClient.right - wndPtr->rectClient.left)/2;
2045 shift = GetSystemMetrics(SM_CYHSCROLL);
2047 else if( uMsg == WM_VSCROLL )
2049 GetScrollRange(hWnd,SB_VERT,&minPos,&maxPos);
2050 curPos = GetScrollPos(hWnd,SB_VERT);
2051 length = (wndPtr->rectClient.bottom - wndPtr->rectClient.top)/2;
2052 shift = GetSystemMetrics(SM_CXVSCROLL);
2054 else
2056 WIN_ReleaseWndPtr(wndPtr);
2057 return;
2060 WIN_ReleaseWndPtr(wndPtr);
2061 switch( wParam )
2063 case SB_LINEUP:
2064 newPos = curPos - shift;
2065 break;
2066 case SB_LINEDOWN:
2067 newPos = curPos + shift;
2068 break;
2069 case SB_PAGEUP:
2070 newPos = curPos - length;
2071 break;
2072 case SB_PAGEDOWN:
2073 newPos = curPos + length;
2074 break;
2076 case SB_THUMBPOSITION:
2077 newPos = LOWORD(lParam);
2078 break;
2080 case SB_THUMBTRACK:
2081 return;
2083 case SB_TOP:
2084 newPos = minPos;
2085 break;
2086 case SB_BOTTOM:
2087 newPos = maxPos;
2088 break;
2089 case SB_ENDSCROLL:
2090 CalcChildScroll16(hWnd,(uMsg == WM_VSCROLL)?SB_VERT:SB_HORZ);
2091 return;
2094 if( newPos > maxPos )
2095 newPos = maxPos;
2096 else
2097 if( newPos < minPos )
2098 newPos = minPos;
2100 SetScrollPos(hWnd, (uMsg == WM_VSCROLL)?SB_VERT:SB_HORZ , newPos, TRUE);
2102 if( uMsg == WM_VSCROLL )
2103 ScrollWindowEx(hWnd ,0 ,curPos - newPos, NULL, NULL, 0, NULL,
2104 SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
2105 else
2106 ScrollWindowEx(hWnd ,curPos - newPos, 0, NULL, NULL, 0, NULL,
2107 SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
2111 /******************************************************************************
2112 * CascadeWindows [USER32.21] Cascades MDI child windows
2114 * RETURNS
2115 * Success: Number of cascaded windows.
2116 * Failure: 0
2118 WORD WINAPI
2119 CascadeWindows (HWND hwndParent, UINT wFlags, const LPRECT lpRect,
2120 UINT cKids, const HWND *lpKids)
2122 FIXME("(0x%08x,0x%08x,...,%u,...): stub\n",
2123 hwndParent, wFlags, cKids);
2125 return 0;
2129 /******************************************************************************
2130 * TileWindows [USER32.545] Tiles MDI child windows
2132 * RETURNS
2133 * Success: Number of tiled windows.
2134 * Failure: 0
2136 WORD WINAPI
2137 TileWindows (HWND hwndParent, UINT wFlags, const LPRECT lpRect,
2138 UINT cKids, const HWND *lpKids)
2140 FIXME("(0x%08x,0x%08x,...,%u,...): stub\n",
2141 hwndParent, wFlags, cKids);
2143 return 0;