Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

win32wmdichild.cpp

Go to the documentation of this file.
00001 /* $Id: win32wmdichild.cpp,v 1.27 2001/06/11 20:08:25 sandervl Exp $ */
00002 /*
00003  * Win32 MDI Child Window Class for OS/2
00004  *
00005  * Copyright 1998-1999 Sander van Leeuwen (sandervl@xs4all.nl)
00006  *
00007  * Based on Wine (windows\mdi.c) (990815)
00008  *
00009  * Copyright 1994, Bob Amstadt
00010  *           1995,1996 Alex Korobka
00011  * Copyright 1993, 1994 Alexandre Julliard
00012  *
00013  *
00014  *
00015  * TODO: See #if 0's
00016  *
00017  * Project Odin Software License can be found in LICENSE.TXT
00018  *
00019  */
00020 #include <os2win.h>
00021 #include <win.h>
00022 #include <stdlib.h>
00023 #include <stdio.h>
00024 #include <string.h>
00025 #include <stdarg.h>
00026 #include <assert.h>
00027 #include <misc.h>
00028 #include <heapstring.h>
00029 #include <win32wnd.h>
00030 #include <win32wmdiclient.h>
00031 #include <win32wmdichild.h>
00032 #include <spy.h>
00033 #include "wndmsg.h"
00034 #include <oslibwin.h>
00035 #include <oslibutil.h>
00036 #include <oslibgdi.h>
00037 #include <oslibres.h>
00038 #include "oslibdos.h"
00039 #include "syscolor.h"
00040 #include "win32wndhandle.h"
00041 
00042 #define DBG_LOCALLOG    DBG_win32wmdichild
00043 #include "dbglocal.h"
00044 
00045 //******************************************************************************
00046 //******************************************************************************
00047 Win32MDIChildWindow::Win32MDIChildWindow(CREATESTRUCTA *lpCreateStructA, ATOM classAtom, BOOL fUnicode)
00048                     : Win32BaseWindow()
00049 {
00050     isUnicode = fUnicode;
00051     CreateWindowExA(lpCreateStructA, classAtom);
00052 }
00053 //******************************************************************************
00054 //******************************************************************************
00055 Win32MDIChildWindow::~Win32MDIChildWindow()
00056 {
00057 }
00058 //******************************************************************************
00059 //******************************************************************************
00060 BOOL Win32MDIChildWindow::isMDIChild()
00061 {
00062     return TRUE;
00063 }
00064 //******************************************************************************
00065 //******************************************************************************
00066 LRESULT Win32MDIChildWindow::DefMDIChildProcA(UINT Msg, WPARAM wParam, LPARAM lParam)
00067 {
00068  Win32MDIClientWindow *client = (Win32MDIClientWindow *)getParent();
00069 
00070     switch (Msg)
00071     {
00072     case WM_SETTEXT:
00073         DefWindowProcA(Msg, wParam, lParam);
00074         menuModifyItem();
00075         if( client->getMaximizedChild() == getWindowHandle() )
00076                 client->updateFrameText(MDI_REPAINTFRAME, NULL);
00077         return 0;
00078 
00079     case WM_GETMINMAXINFO:
00080     {
00081         childGetMinMaxInfo((MINMAXINFO *)lParam);
00082         return 0;
00083     }
00084 
00085     case WM_MENUCHAR:
00086         /* MDI children don't have menu bars */
00087         PostMessageA(client->getWindowHandle(), WM_SYSCOMMAND, (WPARAM)SC_KEYMENU, (LPARAM)LOWORD(wParam) );
00088         return 0x00010000L;
00089 
00090     case WM_CLOSE:
00091         client->SendMessageA(WM_MDIDESTROY,(WPARAM)getWindowHandle(), 0L);
00092         return 0;
00093 
00094     case WM_SETFOCUS:
00095         if(client->getActiveChild() != getWindowHandle() )
00096             client->childActivate(this);
00097         break;
00098 
00099     case WM_CHILDACTIVATE:
00100         client->childActivate(this);
00101         return 0;
00102 
00103     case WM_NCPAINT:
00104         break;
00105 
00106     case WM_SYSCOMMAND:
00107         switch( wParam )
00108         {
00109         case SC_MOVE:
00110             if( client->getMaximizedChild() == getWindowHandle())
00111             {
00112                 return 0;
00113             }
00114             break;
00115         case SC_RESTORE:
00116         case SC_MINIMIZE:
00117             setStyle(getStyle() | WS_SYSMENU);
00118             break;
00119 
00120         case SC_MAXIMIZE:
00121             if( client->getMaximizedChild() == getWindowHandle())
00122             {
00123                   return client->SendMessageA(Msg, wParam, lParam);
00124             }
00125             setStyle(getStyle() & ~WS_SYSMENU);
00126             break;
00127 
00128         case SC_NEXTWINDOW:
00129              client->SendMessageA(WM_MDINEXT, 0, 0);
00130              return 0;
00131 
00132         case SC_PREVWINDOW: //WM_MDINEXT??
00133              client->SendMessageA(WM_MDINEXT, 0, 0);
00134              return 0;
00135         }
00136         break;
00137 
00138     case WM_SETVISIBLE:
00139         if( client->getMaximizedChild()) {
00140                 client->setMdiFlags(client->getMdiFlags() & ~MDIF_NEEDUPDATE);
00141         }
00142         else    client->postUpdate(SB_BOTH+1);
00143         break;
00144 
00145     case WM_SIZE:
00146         /* do not change */
00147         if( client->getActiveChild() == getWindowHandle() && wParam != SIZE_MAXIMIZED )
00148         {
00149             client->setMaximizedChild(NULL);
00150             client->restoreFrameMenu(getWindowHandle());
00151             client->updateFrameText(MDI_REPAINTFRAME, NULL );
00152         }
00153 
00154         if( wParam == SIZE_MAXIMIZED )
00155         {
00156             HWND maxChild = client->getMaximizedChild();
00157 
00158             if( maxChild == getWindowHandle() ) break;
00159 
00160             if( maxChild)
00161             {
00162                 ::SendMessageA(maxChild, WM_SETREDRAW, FALSE, 0L );
00163                 client->restoreFrameMenu(maxChild);
00164                 ::ShowWindow(maxChild, SW_SHOWNOACTIVATE);
00165 
00166                 ::SendMessageA(maxChild, WM_SETREDRAW, TRUE, 0L );
00167             }
00168 
00169             client->setMaximizedChild(getWindowHandle());
00170             client->setActiveChild(getWindowHandle());
00171 
00172             client->augmentFrameMenu(getWindowHandle());
00173 
00174             client->updateFrameText(MDI_REPAINTFRAME, NULL );
00175         }
00176 
00177         if( wParam == SIZE_MINIMIZED )
00178         {
00179             Win32MDIChildWindow *switchTo = client->getWindow(this, TRUE, WS_MINIMIZE);
00180 
00181             if( switchTo )
00182                 switchTo->SendMessageA(WM_CHILDACTIVATE, 0, 0L);
00183         }
00184 
00185         client->postUpdate(SB_BOTH+1);
00186         break;
00187 
00188 #if 0
00189     case WM_NEXTMENU:
00190         if( wParam == VK_LEFT )     /* switch to frame system menu */
00191         {
00192             return MAKELONG( GetSubMenu(clientWnd->parent->hSysMenu, 0),
00193                clientWnd->parent->hwndSelf );
00194             goto END;
00195         }
00196         if( wParam == VK_RIGHT )    /* to frame menu bar */
00197         {
00198             retvalue = MAKELONG( clientWnd->parent->wIDmenu,
00199                clientWnd->parent->hwndSelf );
00200             goto END;
00201         }
00202 #endif
00203     case WM_SYSCHAR:
00204         if (wParam == '-')
00205         {
00206             SendInternalMessageA(WM_SYSCOMMAND, (WPARAM)SC_KEYMENU, (LPARAM)(DWORD)VK_SPACE);
00207             return 0;
00208         }
00209     }
00210     return DefWindowProcA(Msg, wParam, lParam);
00211 }
00212 //******************************************************************************
00213 //******************************************************************************
00214 LRESULT Win32MDIChildWindow::DefMDIChildProcW(UINT Msg, WPARAM wParam, LPARAM lParam)
00215 {
00216  Win32MDIClientWindow *client = (Win32MDIClientWindow *)getParent();
00217 
00218     switch (Msg)
00219     {
00220     case WM_SETTEXT:
00221         DefWindowProcW(Msg, wParam, lParam);
00222         menuModifyItem();
00223         if( client->getMaximizedChild() == getWindowHandle() )
00224                 client->updateFrameText(MDI_REPAINTFRAME, NULL );
00225 
00226         return 0;
00227 
00228     case WM_GETMINMAXINFO:
00229     case WM_MENUCHAR:
00230     case WM_CLOSE:
00231     case WM_SETFOCUS:
00232     case WM_CHILDACTIVATE:
00233     case WM_NCPAINT:
00234     case WM_SYSCOMMAND:
00235     case WM_SETVISIBLE:
00236     case WM_SIZE:
00237     case WM_NEXTMENU:
00238         return DefMDIChildProcA(Msg, wParam, lParam );
00239 
00240     case WM_SYSCHAR:
00241         if (wParam == '-')
00242         {
00243             SendInternalMessageW(WM_SYSCOMMAND, SC_KEYMENU, (LPARAM)(DWORD)VK_SPACE);
00244             return 0;
00245         }
00246         break;
00247     }
00248     return DefWindowProcW(Msg, wParam, lParam);
00249 }
00250 /**********************************************************************
00251  *                  MDICreateChild
00252  */
00253 HWND Win32MDIChildWindow::createChild(Win32MDIClientWindow *client, LPMDICREATESTRUCTA cs )
00254 {
00255   POINT        pos[2];
00256   DWORD        style = cs->style | (WS_CHILD | WS_CLIPSIBLINGS);
00257   WORD         wIDmenu = client->getFirstChildId() + client->getNrOfChildren();
00258   char         lpstrDef[]="junk!";
00259   Win32MDIChildWindow *newchild;
00260   HWND         maximizedChild;
00261   CREATESTRUCTA createstruct;
00262   ATOM         classAtom;
00263   char         tmpClassA[20] = "";
00264   WCHAR        tmpClassW[20];
00265   LPSTR        className;
00266 
00267     dprintf(("Win32MDIChildWindow::createChild %i,%i - dim %i,%i, style %08x\n",
00268              cs->x, cs->y, cs->cx, cs->cy, (unsigned)cs->style));
00269 
00270     /* calculate placement */
00271     calcDefaultChildPos(client, client->incTotalCreated()-1, pos, 0);
00272 
00273     if (cs->cx == CW_USEDEFAULT || !cs->cx) cs->cx = pos[1].x;
00274     if (cs->cy == CW_USEDEFAULT || !cs->cy) cs->cy = pos[1].y;
00275 
00276     if( cs->x == CW_USEDEFAULT )
00277     {
00278         cs->x = pos[0].x;
00279         cs->y = pos[0].y;
00280     }
00281 
00282     /* restore current maximized child */
00283     if( style & WS_VISIBLE && client->getMaximizedChild() )
00284     {
00285         if( style & WS_MAXIMIZE )
00286             client->SendMessageA(WM_SETREDRAW, FALSE, 0L );
00287 
00288         maximizedChild = client->getMaximizedChild();
00289 
00290         ::ShowWindow(maximizedChild, SW_SHOWNOACTIVATE );
00291 
00292         if( style & WS_MAXIMIZE )
00293             client->SendMessageA(WM_SETREDRAW, TRUE, 0L );
00294     }
00295 
00296     /* this menu is needed to set a check mark in MDI_ChildActivate */
00297     if(client->getMDIMenu())
00298         AppendMenuA(client->getMDIMenu(), MF_STRING ,wIDmenu, lpstrDef );
00299 
00300     client->incNrActiveChildren();
00301 
00302     /* fix window style */
00303     if( !(client->getStyle() & MDIS_ALLCHILDSTYLES) )
00304     {
00305         dprintf(("Fixing MDI window style! %x -> %x", style, style | WS_VISIBLE | WS_OVERLAPPEDWINDOW));
00306         style &= (WS_CHILD | WS_CLIPSIBLINGS | WS_MINIMIZE | WS_MAXIMIZE |
00307                   WS_CLIPCHILDREN | WS_DISABLED | WS_VSCROLL | WS_HSCROLL );
00308         style |= (WS_VISIBLE | WS_OVERLAPPEDWINDOW);
00309     }
00310 
00311     createstruct.lpszName  = cs->szTitle;
00312     createstruct.style     = style;
00313     createstruct.dwExStyle = 0;
00314     createstruct.x         = cs->x;
00315     createstruct.y         = cs->y;
00316     createstruct.cx        = cs->cx;
00317     createstruct.cy        = cs->cy;
00318     createstruct.hInstance = cs->hOwner;
00319     createstruct.hMenu     = wIDmenu;
00320     createstruct.hwndParent= client->getWindowHandle();
00321     createstruct.lpCreateParams = (LPVOID)cs;
00322 
00323     className = (LPSTR)cs->szClass;
00324     /* Find the class atom */
00325     classAtom = GlobalFindAtomA(cs->szClass);
00326     if(classAtom == 0)
00327     {
00328         if (!HIWORD(cs->szClass))
00329         {
00330             sprintf(tmpClassA,"#%d", (int) className);
00331             classAtom = GlobalFindAtomA(tmpClassA);
00332             className = tmpClassA;
00333         }
00334         if (!classAtom)
00335         {
00336           if (!HIWORD(cs->szClass)) {
00337                   dprintf(("createChild: bad class name %04x\n", LOWORD(className)));
00338           }
00339           else    dprintf(("createChild: bad class name '%s'\n", tmpClassA ));
00340 
00341           SetLastError(ERROR_INVALID_PARAMETER);
00342           return 0;
00343         }
00344     }
00345     createstruct.lpszClass = className;
00346 
00347     newchild = new Win32MDIChildWindow(&createstruct, classAtom, FALSE);
00348 
00349     if(newchild && GetLastError() == 0)
00350     {
00351         /* All MDI child windows have the WS_EX_MDICHILD style */
00352         newchild->setExStyle(newchild->getExStyle() | WS_EX_MDICHILD);
00353 
00354         newchild->menuModifyItem();
00355 
00356         if( newchild->getStyle() & WS_MINIMIZE && client->getActiveChild()) {
00357             newchild->ShowWindow(SW_SHOWMINNOACTIVE);
00358         }
00359         else
00360         {
00361             /* WS_VISIBLE is clear if a) the MDI client has
00362              * MDIS_ALLCHILDSTYLES style and 2) the flag is cleared in the
00363              * MDICreateStruct. If so the created window is not shown nor
00364              * activated.
00365              */
00366             int showflag = newchild->getStyle() & WS_VISIBLE;
00367             /* clear visible flag, otherwise SetWindoPos32 ignores
00368              * the SWP_SHOWWINDOW command.
00369              */
00370             newchild->setStyle(newchild->getStyle() & ~WS_VISIBLE);
00371 
00372             if(showflag){
00373                 dprintf(("newchild->SetWindowPos active window %x", GetActiveWindow()));
00374                 newchild->SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE );
00375                 dprintf(("newchild->SetWindowPos active window %x", GetActiveWindow()));
00376 
00377                 /* Set maximized state here in case hwnd didn't receive WM_SIZE
00378                  * during CreateWindow - bad!
00379                  */
00380 
00381                 if((newchild->getStyle() & WS_MAXIMIZE) && !client->getMaximizedChild() )
00382                 {
00383                     client->setMaximizedChild(newchild->getWindowHandle());
00384 
00385                     client->augmentFrameMenu(newchild->getWindowHandle());
00386 
00387                     client->updateFrameText(MDI_REPAINTFRAME, NULL );
00388                 }
00389             }
00390             else
00391                 /* needed, harmless ? */
00392                 newchild->SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE );
00393 
00394         }
00395     }
00396     else
00397     {
00398         client->decNrActiveChildren();
00399         if(client->getMDIMenu()) {
00400                 DeleteMenu(client->getMDIMenu(), wIDmenu,MF_BYCOMMAND);
00401         }
00402 
00403         maximizedChild = client->getMaximizedChild();
00404         if( ::IsWindow(maximizedChild) )
00405             ::ShowWindow(maximizedChild, SW_SHOWMAXIMIZED);
00406 
00407         dprintf(("MDI child creation failed!!"));
00408         return 0;
00409     }
00410     return newchild->getWindowHandle();
00411 }
00412 /**********************************************************************
00413  *          MDI_MenuModifyItem
00414  */
00415 BOOL Win32MDIChildWindow::menuModifyItem()
00416 {
00417     Win32MDIClientWindow *client = (Win32MDIClientWindow *)getParent();
00418     char   buffer[128];
00419     UINT   id   = getWindowId()-client->getFirstChildId()+1;
00420     UINT   n    = sprintf(buffer,(id > 9) ? "%d":"&%d ",id);
00421     BOOL   bRet = 0;
00422 
00423     if( !client->getMDIMenu() )
00424     {
00425         return FALSE;
00426     }
00427 
00428     if (getWindowNameA()) lstrcpynA(buffer + n, getWindowNameA(), sizeof(buffer) - n );
00429 
00430     n    = GetMenuState(client->getMDIMenu(), getWindowId() ,MF_BYCOMMAND);
00431     bRet = ModifyMenuA(client->getMDIMenu() , getWindowId(),
00432                        MF_BYCOMMAND | MF_STRING, getWindowId(), buffer );
00433     CheckMenuItem(client->getMDIMenu(), getWindowId() , n & MF_CHECKED);
00434 
00435     return bRet;
00436 }
00437 
00438 /**********************************************************************
00439  *          MDI_MenuDeleteItem
00440  */
00441 BOOL Win32MDIChildWindow::menuDeleteItem()
00442 {
00443     Win32MDIClientWindow *client = (Win32MDIClientWindow *)getParent();
00444     char    buffer[128];
00445     UINT    index      = 0,id,n;
00446     BOOL    retvalue;
00447 
00448     if( !client->getNrOfChildren() ||
00449         !client->getMDIMenu())
00450     {
00451         return FALSE;
00452     }
00453 
00454     id = getWindowId();
00455     DeleteMenu(client->getMDIMenu(),id,MF_BYCOMMAND);
00456 
00457     /* walk the rest of MDI children to prevent gaps in the id
00458      * sequence and in the menu child list */
00459 
00460     lock();
00461     for( index = id+1; index <= client->getNrOfChildren() +
00462          client->getFirstChildId(); index++ )
00463     {
00464         Win32MDIChildWindow *tmpWnd = (Win32MDIChildWindow *)GetWindowFromHandle(client->getChildByID(index));
00465         if( !tmpWnd )
00466         {
00467             dprintf(("no window for id=%i\n",index));
00468             continue;
00469         }
00470 
00471         /* set correct id */
00472         tmpWnd->setWindowId(tmpWnd->getWindowId()-1);
00473 
00474         n = sprintf(buffer, "%d ",index - client->getFirstChildId());
00475         if (tmpWnd->getWindowNameA())
00476             lstrcpynA(buffer + n, tmpWnd->getWindowNameA(), sizeof(buffer) - n );
00477 
00478         RELEASE_WNDOBJ(tmpWnd);
00479 
00480         unlock();
00481         /* change menu */
00482         ModifyMenuA(client->getMDIMenu(), index ,MF_BYCOMMAND | MF_STRING,
00483                     index - 1 , buffer );
00484         lock();
00485     }
00486     unlock();
00487     return TRUE;
00488 }
00489 /**********************************************************************
00490  *          MDI_CalcDefaultChildPos
00491  *
00492  *  It seems that the default height is about 2/3 of the client rect
00493  */
00494 void Win32MDIChildWindow::calcDefaultChildPos(Win32MDIClientWindow *client, WORD n, LPPOINT lpPos, INT delta)
00495 {
00496     INT  nstagger;
00497     RECT rect;
00498     INT  spacing = GetSystemMetrics(SM_CYCAPTION) +
00499                    GetSystemMetrics(SM_CYFRAME) - 1;
00500 
00501     client->getClientRect(&rect);
00502     if( rect.bottom - rect.top - delta >= spacing )
00503         rect.bottom -= delta;
00504 
00505     nstagger = (rect.bottom - rect.top)/(3 * spacing);
00506     lpPos[1].x = (rect.right - rect.left - nstagger * spacing);
00507     lpPos[1].y = (rect.bottom - rect.top - nstagger * spacing);
00508     lpPos[0].x = lpPos[0].y = spacing * (n%(nstagger+1));
00509 }
00510 
00511 /**********************************************************************
00512  *          MDI_ChildGetMinMaxInfo
00513  *
00514  * Note: The rule here is that client rect of the maximized MDI child
00515  *   is equal to the client rect of the MDI client window.
00516  */
00517 void Win32MDIChildWindow::childGetMinMaxInfo(MINMAXINFO* lpMinMax )
00518 {
00519     Win32MDIClientWindow *client = (Win32MDIClientWindow *)getParent();
00520     RECT rect;
00521 
00522     if(client == NULL) {
00523         dprintf(("Win32MDIChildWindow::childGetMinMaxInfo:: client == NULL!!"));
00524         return;
00525     }
00526 
00527     client->getClientRect(&rect);
00528     if(client->getParent() == NULL) {
00529         dprintf(("Win32MDIChildWindow::childGetMinMaxInfo:: client parent == NULL!!"));
00530         return;
00531     }
00532     //SvL: No mapping required as our client rectangle is in frame coordinates (not relative to parent!)
00533 /////    MapWindowPoints(client->getParent()->getWindowHandle(), client->getWindowHandle(), (LPPOINT)&rect, 2);
00534 
00535     AdjustWindowRectEx( &rect, getStyle(), 0, getExStyle());
00536 
00537     lpMinMax->ptMaxSize.x = rect.right -= rect.left;
00538     lpMinMax->ptMaxSize.y = rect.bottom -= rect.top;
00539 
00540     lpMinMax->ptMaxPosition.x = rect.left;
00541     lpMinMax->ptMaxPosition.y = rect.top;
00542 }
00543 
00544 //******************************************************************************
00545 //******************************************************************************
00546 

Generated on Wed Jan 23 23:17:49 2002 for ODIN-user32 by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001