home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1996 December / PCWKCD1296.iso / vjplusb / activex / inetsdk / samples / framer / framer.cpp next >
Encoding:
C/C++ Source or Header  |  1996-03-01  |  32.1 KB  |  1,368 lines

  1. /*
  2.  * FRAMER.CPP
  3.  * Document Objects Framer
  4.  *
  5.  * Sample to demonstrate in-place activation of a DocObject--also
  6.  * activates normal embeddings in separate windows.
  7.  *
  8.  * Copyright (c)1995-1996 Microsoft Corporation, All Rights Reserved
  9.  */
  10.  
  11.  
  12. #define INITGUID
  13. #include "framer.h"
  14.  
  15.  
  16. /*
  17.  * WinMain
  18.  *
  19.  * Purpose:
  20.  *  Main entry point of application.  Should register the app class
  21.  *  if a previous instance has not done so and do any other one-time
  22.  *  initializations.
  23.  */
  24.  
  25. int PASCAL WinMain (HINSTANCE hInst, HINSTANCE hPrev
  26.     , LPSTR pszCmdLine, int nCmdShow)
  27.     {
  28.     PCFrame         pFR;    
  29.     WPARAM          wRet;
  30.  
  31.     //Attempt to allocate and initialize the application
  32.     pFR=new CFrame(hInst, hPrev, pszCmdLine, nCmdShow);
  33.  
  34.     if (NULL==pFR)
  35.         return 0;
  36.     
  37.     //If we can initialize pFR, start chugging messages
  38.     if (pFR->Init(CMENUS, CW_USEDEFAULT, CW_USEDEFAULT
  39.         , CW_USEDEFAULT, CW_USEDEFAULT))
  40.         wRet=pFR->MessageLoop();
  41.  
  42.     delete pFR;
  43.     return wRet;
  44.     }
  45.  
  46.  
  47.  
  48. /*
  49.  * CFrame::CFrame
  50.  * CFrame::~CFrame
  51.  *
  52.  * Constructor Parameters:
  53.  *  hInst           HINSTANCE from WinMain
  54.  *  hInstPrev       HINSTANCE from WinMain
  55.  *  pszCmdLine      LPSTR from WinMain
  56.  *  nCmdShow        int from WinMain
  57.  */
  58.  
  59. CFrame::CFrame(HINSTANCE hInst, HINSTANCE hInstPrev
  60.     , LPSTR pszCmdLine, int nCmdShow)    
  61.     {
  62.     m_hInst=hInst;
  63.     m_hWnd=NULL;
  64.     m_hInstPrev=hInstPrev;
  65.     m_nCmdShow=nCmdShow;
  66.  
  67.     m_phMenu=NULL;
  68.     m_hAccel=NULL;
  69.     m_hWndClient=NULL;
  70.  
  71.     m_fInitialized=FALSE;
  72.     m_pIStorage=NULL;
  73.     m_dwIDCounter=0;
  74.  
  75.     m_hMenuOrg=NULL;
  76.     m_hMenuTop=NULL;
  77.     m_hMenuHelp=NULL;
  78.     m_fInObjectHelp=FALSE;
  79.     m_fUsingOurHelp=FALSE;
  80.             
  81.     m_fHaveObject=FALSE;
  82.     m_hWndObj=NULL;
  83.  
  84.     m_pSite=NULL;
  85.     m_fOurMenuShowing=TRUE;
  86.     SetRect(&m_bwIP, 0, 0, 0, 0);
  87.     m_fInContextHelp=FALSE;
  88.     m_pIOleIPActiveObject=NULL;
  89.  
  90.     return;
  91.     }
  92.  
  93.  
  94.  
  95. CFrame::~CFrame(void)
  96.     {
  97.     if (NULL!=m_hWndClient)
  98.         DestroyWindow(m_hWndClient);
  99.     
  100.     //Frees the temp file.
  101.     ReleaseInterface(m_pIStorage);
  102.     
  103.     //m_pSite cleaned up in Close
  104.  
  105.     //Accelerators freed automatically.
  106.  
  107.     //Destroy the special help menu
  108.     if (NULL!=m_hMenuHelp)
  109.         DestroyMenu(m_hMenuHelp);
  110.  
  111.     //Free the menu handle array
  112.     if (NULL!=m_phMenu)
  113.         delete []((UINT *)m_phMenu);
  114.  
  115.     if (m_fInitialized)
  116.         OleUninitialize();
  117.  
  118.     return;
  119.     }
  120.  
  121.  
  122. /*
  123.  * CFrame::Init
  124.  *
  125.  * Purpose:
  126.  *  Initializer for a CFrame object containing anything prone to
  127.  *  failure.
  128.  *
  129.  * Parameters:
  130.  *  cMenus          UINT number of menus on the frame
  131.  *  x, y, cx, cy    int location and size of frame window 
  132.  *
  133.  * Return Value:
  134.  *  BOOL            TRUE if initialization succeeded, FALSE
  135.  *                  otherwise. If FALSE is returned, the caller must
  136.  *                  guarantee that the destructor is called promptly
  137.  *                  to insure cleanup.
  138.  */
  139.  
  140. BOOL CFrame::Init(UINT cMenus, int x, int y, int cx, int cy)
  141.     {
  142.     HMENU               hMenu;
  143.     UINT                uTemp;
  144.     RECT                rc;
  145.  
  146.     //1.  Initialize OLE
  147.     if (SUCCEEDED(OleInitialize(NULL)))
  148.         m_fInitialized=TRUE;
  149.     else
  150.         return FALSE;
  151.  
  152.  
  153.     //2.  Register window classes
  154.     if (NULL==m_hInstPrev)
  155.         {
  156.         if (!RegisterAllClasses())
  157.             return FALSE;
  158.         }
  159.  
  160.  
  161.     //3.  Create the main window and client-area window
  162.     m_hWnd=CreateWindow(SZCLASSFRAME, TEXT("DocObject Framer")
  163.         , WS_MINIMIZEBOX | WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN
  164.         , x, y, cx, cy, NULL, NULL, m_hInst, this);
  165.         
  166.     if (NULL==m_hWnd)
  167.         return FALSE;
  168.  
  169.     GetClientRect(m_hWnd, &rc);
  170.  
  171.     m_hWndClient=CreateWindow(SZCLASSCLIENT, SZCLASSCLIENT
  172.         , WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | WS_CLIPSIBLINGS
  173.         , rc.left, rc.top, rc.right-rc.left
  174.         , rc.bottom-rc.top, m_hWnd, NULL, m_hInst, this);
  175.  
  176.     if (NULL==m_hWndClient)
  177.         return FALSE;
  178.  
  179.     //4. Allocate menu array for use with in-place menu merging.
  180.     m_phMenu=new HMENU[cMenus];
  181.     hMenu=GetMenu(m_hWnd);
  182.     m_hMenuOrg=hMenu;
  183.  
  184.     for (uTemp=0; uTemp < cMenus; uTemp++)
  185.         m_phMenu[uTemp]=GetSubMenu(hMenu, uTemp);
  186.  
  187.     //Also load the special help menu
  188.     m_hMenuHelp=LoadMenu(m_hInst
  189.         , MAKEINTRESOURCE(IDR_MENUHELP));
  190.  
  191.     //5.  Load accelerators
  192.     m_hAccel=LoadAccelerators(m_hInst
  193.         , MAKEINTRESOURCE(IDR_ACCELERATORS));
  194.  
  195.     if (NULL==m_hAccel)
  196.         return FALSE;
  197.  
  198.  
  199.     //6.  Make us all visible.
  200.     ShowWindow(m_hWnd, m_nCmdShow);
  201.     UpdateWindow(m_hWnd);
  202.  
  203.  
  204.     /*
  205.      * 7.  Create a temp file for all embedded files.  Note that in this
  206.      *     sample we don't save any changes to DocObjects because we 
  207.      *     don't manage any storage directly.
  208.      */      
  209.     if (FAILED(StgCreateDocfile(NULL, STGM_TRANSACTED | STGM_READWRITE
  210.         | STGM_SHARE_EXCLUSIVE | STGM_CREATE| STGM_DELETEONRELEASE
  211.         , 0, &m_pIStorage)))
  212.         return FALSE;
  213.  
  214.     return TRUE;
  215.     }
  216.  
  217.  
  218.  
  219.  
  220.  
  221. /*
  222.  * CFrame::RegisterAllClasses
  223.  *
  224.  * Purpose:
  225.  *  Registers all classes used in this application.
  226.  *
  227.  * Return Value:
  228.  *  BOOL            TRUE if registration succeeded, FALSE otherwise.
  229.  */
  230.  
  231. BOOL CFrame::RegisterAllClasses(void)
  232.     {
  233.     WNDCLASS        wc;
  234.  
  235.     //Field that are the same for all windows.
  236.     wc.style         = CS_HREDRAW | CS_VREDRAW;
  237.     wc.hInstance     = m_hInst;
  238.     wc.cbClsExtra    = 0;
  239.  
  240.     //Register the Frame window
  241.     wc.lpfnWndProc   = FrameWndProc;
  242.     wc.cbWndExtra    = CBFRAMEWNDEXTRA;
  243.     wc.hIcon         = LoadIcon(m_hInst, TEXT("Icon"));
  244.     wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
  245.     wc.hbrBackground = NULL;
  246.     wc.lpszMenuName  = MAKEINTRESOURCE(IDR_MENU);
  247.     wc.lpszClassName = SZCLASSFRAME;
  248.  
  249.     if (!RegisterClass(&wc))
  250.         return FALSE;
  251.  
  252.  
  253.     //Register the do-nothing Client window
  254.     wc.lpfnWndProc   = ClientWndProc;
  255.     wc.cbWndExtra    = CBCLIENTWNDEXTRA;
  256.     wc.hIcon         = NULL;
  257.     wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
  258.     wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  259.     wc.lpszMenuName  = NULL;
  260.     wc.lpszClassName = SZCLASSCLIENT;
  261.  
  262.     if (!RegisterClass(&wc))
  263.         return FALSE;
  264.  
  265.     return TRUE;
  266.     }
  267.  
  268.  
  269.  
  270.  
  271. /*
  272.  * CFrame::OnCommand
  273.  *
  274.  * Purpose:
  275.  *  WM_COMMAND handler for the frame window so derivations can
  276.  *  process their messages and then pass the standard commands (like
  277.  *  file open and save) on to the base class.
  278.  *
  279.  * Parameters:
  280.  *  hWnd            HWND of the frame window.
  281.  *  wParam          WPARAM of the message.
  282.  *  lParam          LPARAM of the message.
  283.  *
  284.  * Return Value:
  285.  *  LRESULT         Return value for the message.
  286.  */
  287.  
  288. LRESULT CFrame::OnCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
  289.     {
  290.     TCHAR           szFile[MAX_PATH];
  291.     BOOL            fOK;
  292.     PCHourglass     pHour;
  293.     WORD            wID=LOWORD(wParam);
  294.  
  295.     switch (wID)
  296.         {
  297.         case IDM_FILEOPEN:
  298.             /*
  299.              * This will be disabled if we already have an object.
  300.              * User must File/Close first to get back here. 
  301.              *
  302.              * Otherwise open the File/Open dialog
  303.              */
  304.             szFile[0]=0;
  305.             if (!OpenDialog(szFile, MAX_PATH))
  306.                 return 0L;
  307.                 
  308.             pHour=new CHourglass;            
  309.             fOK=CreateObject(szFile);
  310.             delete pHour;
  311.             return 0;
  312.  
  313.  
  314.         case IDM_FILECLOSE:
  315.             Close();
  316.             break;
  317.  
  318.  
  319.         case IDM_FILEEXIT:
  320.             PostMessage(hWnd, WM_CLOSE, 0, 0L);            
  321.             break;
  322.  
  323.  
  324.         case IDM_HELPABOUT:
  325.             DialogBox(m_hInst, MAKEINTRESOURCE(IDD_ABOUT)
  326.                 , m_hWnd, (DLGPROC)AboutProc);
  327.             break;
  328.  
  329.  
  330.         case IDM_ENTERCONTEXTHELP:
  331.         case IDM_ESCAPECONTEXTHELP:
  332.             //Notify the object on entry and exit.
  333.             ContextSensitiveHelp(IDM_ENTERCONTEXTHELP==wID);
  334.             break;
  335.  
  336.  
  337.         default:
  338.            return DefWindowProc(hWnd, WM_COMMAND, wParam, lParam);
  339.                
  340.         }
  341.  
  342.     return 0L;
  343.     }
  344.  
  345.  
  346.  
  347.  
  348.  
  349. /*
  350.  * CFrame::OpenDialog
  351.  *
  352.  * Purpose:
  353.  *  Invokes the COMMDLG.DLL GetOpenFileName dialog and retrieves
  354.  *  a filename for saving or opening.
  355.  *
  356.  * Parameters:
  357.  *  pszFile         LPTSTR buffer to receive the entered filename.
  358.  *  cchFile         UINT length of pszFile 
  359.  *
  360.  * Return Value:
  361.  *  BOOL            TRUE if the function retrieved a filename,
  362.  *                  FALSE if the user pressed CANCEL.
  363.  */
  364.  
  365. BOOL CFrame::OpenDialog(LPTSTR pszFile, UINT cchFile)
  366.     {
  367.     OPENFILENAME        ofn;
  368.     static TCHAR        szFilter[80]=TEXT("All Files (*.*)\0*.*\0\0");
  369.     BOOL                fRet;
  370.    #ifdef DEBUG
  371.     DWORD               dwErr;
  372.    #endif
  373.  
  374.     if (NULL==pszFile)
  375.         return FALSE;
  376.  
  377.     memset(&ofn, 0, sizeof(OPENFILENAME));
  378.     ofn.lStructSize      =sizeof(OPENFILENAME);
  379.     ofn.hwndOwner        =m_hWnd;
  380.  
  381.     ofn.lpstrFilter      =szFilter;
  382.     ofn.nFilterIndex     =1L;
  383.  
  384.     ofn.lpstrTitle       =NULL;
  385.     ofn.lpstrFile        =pszFile;
  386.     ofn.nMaxFile         =cchFile;
  387.  
  388.     ofn.lpstrDefExt      =TEXT("*");
  389.     ofn.Flags            =OFN_HIDEREADONLY | OFN_FILEMUSTEXIST;
  390.  
  391.     fRet=GetOpenFileName(&ofn);
  392.     
  393.    #ifdef DEBUG
  394.     dwErr=CommDlgExtendedError();
  395.    #endif
  396.     return fRet;
  397.     }
  398.  
  399.  
  400.  
  401. /*
  402.  * CFrame::CreateObject
  403.  *
  404.  * Purpose:
  405.  *  Creates a site and has it create an object based on a filename.
  406.  *
  407.  * Parameters:
  408.  *  pszFile         LPTSTR pointing to the filename from which to
  409.  *                  create the object.
  410.  *
  411.  * Return Value:
  412.  *  BOOL            TRUE if successful, FALSE otherwise.
  413.  */
  414.  
  415. BOOL CFrame::CreateObject(LPTSTR pszFile)
  416.     {    
  417.     m_pSite=new CSite(++m_dwIDCounter, m_hWndClient, this);
  418.  
  419.     if (NULL==m_pSite)
  420.         return FALSE;
  421.  
  422.     m_pSite->AddRef();  //So we can free with Release
  423.  
  424.     /*
  425.      * Now tell the site to create an object in it using the filename
  426.      * and the storage we opened.  The site will create a sub-storage
  427.      * for the doc object's use.
  428.      */
  429.     if (!m_pSite->Create(pszFile, m_pIStorage))
  430.         return FALSE;
  431.  
  432.     m_fHaveObject=TRUE;
  433.  
  434.     //We created the thing, now activate it with "Show"
  435.     m_pSite->Activate(OLEIVERB_SHOW);
  436.  
  437.     //Force repaint to show "have object" message
  438.     InvalidateRect(m_hWndClient, NULL, TRUE);
  439.     UpdateWindow(m_hWndClient);
  440.     return TRUE;        
  441.     }
  442.  
  443.  
  444.  
  445. /*
  446.  * CFrame::Close
  447.  *
  448.  * Purpose:
  449.  *  Handles File/Close by freeing the object and resetting the
  450.  *  application state.
  451.  *
  452.  * Parameters:
  453.  *  None
  454.  *
  455.  * Return Value:
  456.  *  None
  457.  */
  458.  
  459. void CFrame::Close(void)
  460.     {    
  461.     RECT    rc;
  462.  
  463.     if (NULL!=m_pSite)
  464.         {
  465.         CSite *pSite=m_pSite;        //Prevents reentry
  466.         m_pSite=NULL;
  467.  
  468.         pSite->Close(FALSE);         //Frees the object
  469.         pSite->Destroy(m_pIStorage); //Cleans up the storage
  470.         pSite->Release();            //Frees the site        
  471.         }
  472.     
  473.     m_fHaveObject=FALSE;    
  474.     SetRect(&m_bwIP, 0, 0, 0, 0);    
  475.  
  476.     GetClientRect(m_hWnd, &rc);    
  477.     ResizeClientWindow(rc.left, rc.top, rc.right-rc.left
  478.         , rc.bottom-rc.top);    
  479.  
  480.     //Force repaint to remove "have object" message
  481.     InvalidateRect(m_hWndClient, NULL, TRUE);
  482.     UpdateWindow(m_hWndClient);
  483.     
  484.     return;        
  485.     }
  486.  
  487.  
  488. /*
  489.  * CFrame::ResizeClientWindow
  490.  *
  491.  * Purpose:
  492.  *    Resizes the client-area window according to current toolbar sizes
  493.  *  and the frame window size.
  494.  *
  495.  * Parameters:
  496.  *    x,y,cx,cy        UINT origin and dimensions of the window
  497.  *
  498.  * Return Value:
  499.  *    None
  500.  */
  501.  
  502. void CFrame::ResizeClientWindow(UINT x, UINT y, UINT cx, UINT cy)
  503.     {
  504.     SetWindowPos(m_hWndClient, NULL, x, y, cx, cy        
  505.         , SWP_NOZORDER | SWP_NOACTIVATE);
  506.  
  507.     //Tell the site to tell the object.
  508.     if (NULL!=m_pSite)
  509.         m_pSite->UpdateObjectRects();
  510.  
  511.     return;
  512.     }
  513.  
  514.  
  515. /*
  516.  * CFrame::MessageLoop
  517.  *
  518.  * Purpose:
  519.  *  Spins in a standard message loop (with accelerators) until
  520.  *  WM_QUIT is found after which it returns.
  521.  *
  522.  * Return Value:
  523.  *  WPARAM          Contents of msg.wParam from WM_QUIT.
  524.  */
  525.  
  526. WPARAM CFrame::MessageLoop(void)
  527.     {
  528.     MSG     msg;
  529.  
  530.     while (GetMessage(&msg, NULL, 0,0 ))
  531.         {
  532.         //Always give the object first crack at translation.
  533.         if (NULL!=m_pIOleIPActiveObject)
  534.             {
  535.             HRESULT     hr;
  536.  
  537.             hr=m_pIOleIPActiveObject->TranslateAccelerator(&msg);
  538.  
  539.             //If the object translated the accelerator, we're done
  540.             if (NOERROR==hr)
  541.                 continue;
  542.             }
  543.  
  544.         if (!::TranslateAccelerator(m_hWnd, m_hAccel, &msg))
  545.             {
  546.             TranslateMessage(&msg);
  547.             DispatchMessage(&msg);
  548.             }
  549.         }
  550.  
  551.     return msg.wParam;
  552.     }
  553.  
  554.  
  555.  
  556. /*
  557.  * FrameWndProc
  558.  *
  559.  * Purpose:
  560.  *  Frame window class procedure that allows a derivation of these
  561.  *  classes to hook and process any messages desired.  Otherwise this
  562.  *  handles standard commands as well as the status line and menus.
  563.  */
  564.  
  565. LRESULT APIENTRY FrameWndProc(HWND hWnd, UINT iMsg
  566.     , WPARAM wParam, LPARAM lParam)
  567.     {
  568.     PCFrame         pFR;
  569.     RECT            rc;
  570.     HMENU           hMenu;
  571.  
  572.     pFR=(PCFrame)GetWindowLong(hWnd, FRAMEWL_STRUCTURE);
  573.  
  574.     switch (iMsg)
  575.         {
  576.         case WM_NCCREATE:
  577.             pFR=(PCFrame)((LPCREATESTRUCT)lParam)->lpCreateParams;
  578.  
  579.             SetWindowLong(hWnd, FRAMEWL_STRUCTURE, (LONG)pFR);
  580.             return DefWindowProc(hWnd, iMsg, wParam, lParam);
  581.  
  582.         case WM_DESTROY:
  583.             PostQuitMessage(0);
  584.             break;
  585.  
  586.         case WM_CLOSE:                        
  587.             pFR->Close();
  588.             DestroyWindow(hWnd);
  589.             break;
  590.  
  591.         case WM_ERASEBKGND:
  592.             //Client area window always manages painting
  593.             return FALSE;
  594.  
  595.         case WM_SIZE:
  596.             //Tell the in-place object about the new frame size
  597.             GetClientRect(hWnd, &rc);
  598.  
  599.             if (NULL!=pFR->m_pIOleIPActiveObject)
  600.                 pFR->m_pIOleIPActiveObject->ResizeBorder(&rc, pFR, TRUE);
  601.                     
  602.             /*
  603.              * Resize the client, which is done in all cases since this window
  604.              * is the parent of the DocObject, plus we need to tell the 
  605.              * DocObject of the new size through IOleDocumentView::SetRect.
  606.              */
  607.             rc.left  +=pFR->m_bwIP.left;
  608.             rc.right -=pFR->m_bwIP.right;
  609.             rc.top   +=pFR->m_bwIP.top;
  610.             rc.bottom-=pFR->m_bwIP.bottom;            
  611.  
  612.             pFR->ResizeClientWindow(rc.left, rc.top, rc.right-rc.left
  613.                 , rc.bottom-rc.top);
  614.             
  615.             break;
  616.  
  617.  
  618.         case WM_SETFOCUS:
  619.             if (NULL!=pFR->m_pIOleIPActiveObject)
  620.                 {
  621.                 HWND    hWndObj;
  622.  
  623.                 pFR->m_pIOleIPActiveObject->GetWindow(&hWndObj);
  624.                 SetFocus(hWndObj);
  625.                 }
  626.  
  627.             return TRUE;
  628.  
  629.  
  630.         case WM_INITMENU:
  631.             pFR->m_fInObjectHelp=FALSE;
  632.             break;
  633.  
  634.  
  635.         case WM_MENUSELECT:
  636.                 {
  637.                  UINT fuFlags=(UINT)HIWORD(wParam);
  638.                  UINT uItem=(UINT)LOWORD(wParam);
  639.  
  640.                 if (MF_POPUP & fuFlags)
  641.                     {
  642.                     /*
  643.                      * If we're inside our m_hMenuHelp, and uItem is
  644.                      * not zero (first item on the menu, which is ours),
  645.                      * then we must be in an object-supplied menu.
  646.                      *
  647.                      * Therefore we set our flag and forward the message
  648.                      * as well as others that occur later.  Otherwise we
  649.                      * clear the flag so we get messages again.
  650.                      */                
  651.                     if (NULL!=pFR->m_hMenuHelp
  652.                         && (HMENU)lParam==pFR->m_hMenuHelp)                    
  653.                         {
  654.                         pFR->m_fInObjectHelp=(0!=uItem);
  655.                 
  656.                         if (pFR->m_fInObjectHelp)
  657.                             SendMessage(pFR->m_hWndObj, iMsg, wParam, lParam);
  658.                         }                
  659.                     }
  660.                 else
  661.                     {
  662.                     //Forward the message on
  663.                     if (pFR->m_fInObjectHelp)
  664.                         {
  665.                         SendMessage(pFR->m_hWndObj, iMsg, wParam, lParam);
  666.                         break;
  667.                         }
  668.                     }        
  669.                 }
  670.             break;
  671.  
  672.         case WM_INITMENUPOPUP:
  673.             /*
  674.              * If we're in the object's Help menu, forward to
  675.              * the object received in IOleInPlaceFrame::SetActiveObject
  676.              */
  677.             if (pFR->m_fInObjectHelp && NULL!=pFR->m_hWndObj) 
  678.                 SendMessage(pFR->m_hWndObj, iMsg, wParam, lParam);
  679.  
  680.  
  681.             //Skip the system menu
  682.             if (TRUE==(BOOL)HIWORD(lParam))
  683.                 break;
  684.  
  685.             /*
  686.              * If we have an object, enable Close, otherwise
  687.              * enable Open.
  688.              */
  689.             hMenu=(HMENU)wParam;
  690.  
  691.             if (hMenu==pFR->m_phMenu[0])
  692.                 {
  693.                 UINT uTempE=MF_BYCOMMAND | MF_ENABLED;
  694.                 UINT uTempD=MF_BYCOMMAND | MF_DISABLED | MF_GRAYED;
  695.  
  696.                 EnableMenuItem(hMenu, IDM_FILEOPEN
  697.                     , pFR->m_fHaveObject ? uTempD : uTempE);
  698.                 EnableMenuItem(hMenu, IDM_FILECLOSE
  699.                     , pFR->m_fHaveObject ? uTempE : uTempD);
  700.                 }
  701.             
  702.             break;
  703.  
  704.         case WM_COMMAND:
  705.             if (pFR->m_fInObjectHelp)
  706.                 {
  707.                 SendMessage(pFR->m_hWndObj, iMsg, wParam, lParam);
  708.                 break;
  709.                 }
  710.             else
  711.                 return pFR->OnCommand(hWnd, wParam, lParam);
  712.  
  713.         default:
  714.             return DefWindowProc(hWnd, iMsg, wParam, lParam);
  715.         }
  716.  
  717.     return 0L;
  718.     }
  719.  
  720.  
  721.  
  722. /*
  723.  * ClientWndProc
  724.  *
  725.  * Purpose:
  726.  *  Client window class procedure that's only used to paint a
  727.  *  message when we have a non-DocObject open.  Otherwise this
  728.  *  is completely hidden.
  729.  */
  730.  
  731. LRESULT APIENTRY ClientWndProc(HWND hWnd, UINT iMsg
  732.     , WPARAM wParam, LPARAM lParam)
  733.     {
  734.     PCFrame         pFR;
  735.     PAINTSTRUCT        ps;
  736.  
  737.     pFR=(PCFrame)GetWindowLong(hWnd, CLIENTWL_STRUCTURE);
  738.  
  739.     switch (iMsg)
  740.         {
  741.         case WM_NCCREATE:
  742.             pFR=(PCFrame)((LPCREATESTRUCT)lParam)->lpCreateParams;
  743.  
  744.             SetWindowLong(hWnd, CLIENTWL_STRUCTURE, (LONG)pFR);
  745.             return DefWindowProc(hWnd, iMsg, wParam, lParam);
  746.  
  747.         case WM_PAINT:
  748.             BeginPaint(hWnd, &ps);
  749.  
  750.             if (pFR->m_fHaveObject)
  751.                 {
  752.                 static TCHAR szMsg[]={TEXT("A non-DocObject is open or loaded. Use File/Close to destroy it.")};
  753.  
  754.                 SetBkColor(ps.hdc, GetSysColor(COLOR_WINDOW));
  755.                 TextOut(ps.hdc, 0, 0, szMsg, lstrlen(szMsg));
  756.                 }
  757.  
  758.             EndPaint(hWnd, &ps);
  759.             break;
  760.  
  761.  
  762.         default:
  763.             return DefWindowProc(hWnd, iMsg, wParam, lParam);
  764.         }
  765.  
  766.     return 0L;
  767.     }
  768.  
  769.  
  770.  
  771.  
  772.  
  773. /*
  774.  * AboutProc
  775.  *
  776.  * Purpose:
  777.  *  Dialog procedure for the omnipresent About box.
  778.  *
  779.  * Parameters:
  780.  *  The standard.
  781.  *
  782.  * Return Value:
  783.  *  The value to be returned through the DialogBox call that
  784.  *  created the dialog.
  785.  *
  786.  */
  787.  
  788. BOOL APIENTRY AboutProc(HWND hDlg, UINT iMsg
  789.     , WPARAM wParam, LPARAM lParam)
  790.     {
  791.     switch (iMsg)
  792.         {
  793.         case WM_INITDIALOG:
  794.             return TRUE;
  795.  
  796.         case WM_COMMAND:
  797.             switch (LOWORD(wParam))
  798.                 {
  799.                 case IDOK:
  800.                     EndDialog(hDlg, TRUE);
  801.                 }
  802.             break;
  803.         }
  804.     return FALSE;
  805.     }
  806.  
  807.  
  808.  
  809.  
  810.  
  811.  
  812.  
  813.  
  814.  
  815. /*
  816.  * IUnknown implementation
  817.  */
  818.  
  819.  
  820. /*
  821.  * CFrame::QueryInterface
  822.  * CFrame::AddRef
  823.  * CFrame::Release
  824.  */
  825.  
  826. STDMETHODIMP CFrame::QueryInterface(REFIID riid, void **ppv)
  827.     {
  828.     /*
  829.      * We only know IOleInPlaceFrame and its base interfaces as well
  830.      * as a bogus IOleCommandTarget to make PowerPoint happy.
  831.      */
  832.     *ppv=NULL;
  833.  
  834.     if (IID_IUnknown==riid || IID_IOleInPlaceUIWindow==riid
  835.         || IID_IOleWindow==riid || IID_IOleInPlaceFrame==riid)
  836.         *ppv=(IOleInPlaceFrame *)this;
  837.  
  838.     if (IID_IOleCommandTarget==riid)
  839.         *ppv=(IOleCommandTarget *)this;
  840.  
  841.     if (NULL!=*ppv)
  842.         {
  843.         ((LPUNKNOWN)*ppv)->AddRef();
  844.         return NOERROR;
  845.         }
  846.  
  847.     return E_NOINTERFACE;
  848.     }
  849.  
  850.  
  851. STDMETHODIMP_(ULONG) CFrame::AddRef(void)
  852.     {
  853.     return ++m_cRef;
  854.     }
  855.  
  856. STDMETHODIMP_(ULONG) CFrame::Release(void)
  857.     {
  858.     //Nothing special happening here--frame's life if user-controlled.
  859.     return --m_cRef;
  860.     }
  861.  
  862.  
  863. /*
  864.  * IOleInPlaceFrame implementation
  865.  */
  866.  
  867.  
  868. /*
  869.  * CFrame::GetWindow
  870.  *
  871.  * Purpose:
  872.  *  Retrieves the handle of the window associated with the object
  873.  *  on which this interface is implemented.
  874.  *
  875.  * Parameters:
  876.  *  phWnd           HWND * in which to store the window handle.
  877.  *
  878.  * Return Value:
  879.  *  HRESULT         NOERROR if successful, E_FAIL if there is no
  880.  *                  window.
  881.  */
  882.  
  883. STDMETHODIMP CFrame::GetWindow(HWND *phWnd)
  884.     {
  885.     *phWnd=m_hWnd;
  886.     return NOERROR;
  887.     }
  888.  
  889.  
  890.  
  891.  
  892. /*
  893.  * CFrame::ContextSensitiveHelp
  894.  *
  895.  * Purpose:
  896.  *  Instructs the object on which this interface is implemented to
  897.  *  enter or leave a context-sensitive help mode.
  898.  *
  899.  * Parameters:
  900.  *  fEnterMode      BOOL TRUE to enter the mode, FALSE otherwise.
  901.  *
  902.  * Return Value:
  903.  *  HRESULT         NOERROR
  904.  */
  905.  
  906. STDMETHODIMP CFrame::ContextSensitiveHelp(BOOL fEnterMode)
  907.     {
  908.     /*
  909.      * Don't bother if there is no active object since we don't do
  910.      * context help on our own.
  911.      */
  912.     if (NULL==m_pIOleIPActiveObject)
  913.         return NOERROR;
  914.  
  915.     //If the state changes, notify the active object.
  916.     if (m_fInContextHelp!=fEnterMode)
  917.         {
  918.         m_fInContextHelp=fEnterMode;
  919.         m_pIOleIPActiveObject->ContextSensitiveHelp(fEnterMode);
  920.         }
  921.  
  922.     return NOERROR;
  923.     }
  924.  
  925.  
  926.  
  927.  
  928. /*
  929.  * CFrame::GetBorder
  930.  *
  931.  * Purpose:
  932.  *  Returns the rectangle in which the container is willing to
  933.  *  negotiate about an object's adornments.
  934.  *
  935.  * Parameters:
  936.  *  prcBorder       LPRECT in which to store the rectangle.
  937.  *
  938.  * Return Value:
  939.  *  HRESULT         NOERROR if all is well, INPLACE_E_NOTOOLSPACE
  940.  *                  if there is no negotiable space.
  941.  */
  942.  
  943. STDMETHODIMP CFrame::GetBorder(LPRECT prcBorder)
  944.     {
  945.     if (NULL==prcBorder)
  946.         return E_INVALIDARG;
  947.  
  948.     //We return all the client area space
  949.     GetClientRect(m_hWnd, prcBorder);
  950.     return NOERROR;
  951.     }
  952.  
  953.  
  954.  
  955.  
  956. /*
  957.  * CFrame::RequestBorderSpace
  958.  *
  959.  * Purpose:
  960.  *  Asks the container if it can surrender the amount of space
  961.  *  in pBW that the object would like for it's adornments.  The
  962.  *  container does nothing but validate the spaces on this call.
  963.  *
  964.  * Parameters:
  965.  *  pBW             LPCBORDERWIDTHS containing the requested space.
  966.  *                  The values are the amount of space requested
  967.  *                  from each side of the relevant window.
  968.  *
  969.  * Return Value:
  970.  *  HRESULT         NOERROR if we can give up space,
  971.  *                  INPLACE_E_NOTOOLSPACE otherwise.
  972.  */
  973.  
  974. STDMETHODIMP CFrame::RequestBorderSpace(LPCBORDERWIDTHS pBW)
  975.     {
  976.     //Framer has no border space restrictions
  977.     return NOERROR;
  978.     }
  979.  
  980.  
  981.  
  982.  
  983. /*
  984.  * CFrame::SetBorderSpace
  985.  *
  986.  * Purpose:
  987.  *  Called when the object now officially requests that the
  988.  *  container surrender border space it previously allowed
  989.  *  in RequestBorderSpace.  The container should resize windows
  990.  *  appropriately to surrender this space.
  991.  *
  992.  * Parameters:
  993.  *  pBW             LPCBORDERWIDTHS containing the amount of space
  994.  *                  from each side of the relevant window that the
  995.  *                  object is now reserving.
  996.  *
  997.  * Return Value:
  998.  *  HRESULT         NOERROR
  999.  */
  1000.  
  1001. STDMETHODIMP CFrame::SetBorderSpace(LPCBORDERWIDTHS pBW)
  1002.     {
  1003.     RECT            rc;
  1004.  
  1005.     /*
  1006.      * Since we have no tools, we can accept anything the object sends
  1007.      * and must therefore adjust the client-area window accordingly.
  1008.      */
  1009.  
  1010.     /*
  1011.      * If pBW is NULL, the object is not interested in tools, so we
  1012.      * don't have to do anything.  In either case we need to save
  1013.      * the toolspace allocations in order to resize the client window
  1014.      * correctly.
  1015.      */
  1016.     if (NULL==pBW)
  1017.         {
  1018.         if (!m_fOurMenuShowing)
  1019.             SetMenu(NULL, NULL, NULL);
  1020.  
  1021.         SetRect(&m_bwIP, 0, 0, 0, 0);
  1022.         return NOERROR;
  1023.         }
  1024.     else
  1025.         {
  1026.         GetClientRect(m_hWnd, &rc);
  1027.         rc.left  +=pBW->left;
  1028.         rc.right -=pBW->right;
  1029.         rc.top   +=pBW->top;
  1030.         rc.bottom-=pBW->bottom;
  1031.  
  1032.         m_bwIP=*pBW;
  1033.         }
  1034.  
  1035.     ResizeClientWindow(rc.left, rc.top, rc.right-rc.left
  1036.         , rc.bottom-rc.top);
  1037.     
  1038.     return NOERROR;
  1039.     }
  1040.  
  1041.  
  1042.  
  1043.  
  1044. /*
  1045.  * CFrame::SetActiveObject
  1046.  *
  1047.  * Purpose:
  1048.  *  Provides the container with the object's IOleInPlaceActiveObject
  1049.  *  pointer
  1050.  *
  1051.  * Parameters:
  1052.  *  pIIPActiveObj   LPOLEINPLACEACTIVEOBJECT of interest.
  1053.  *  pszObj          LPCOLESTR naming the object.  Not used.
  1054.  *
  1055.  * Return Value:
  1056.  *  HRESULT         NOERROR
  1057.  */
  1058.  
  1059. STDMETHODIMP CFrame::SetActiveObject
  1060.     (LPOLEINPLACEACTIVEOBJECT pIIPActiveObj, LPCOLESTR pszObj)
  1061.     {
  1062.     if (NULL!=m_pIOleIPActiveObject)
  1063.         m_pIOleIPActiveObject->Release();
  1064.  
  1065.     //NULLs m_pIOleIPActiveObject if pIIPActiveObj is NULL
  1066.     m_pIOleIPActiveObject=pIIPActiveObj;
  1067.  
  1068.     if (NULL!=m_pIOleIPActiveObject)
  1069.         m_pIOleIPActiveObject->AddRef();
  1070.  
  1071.     m_pIOleIPActiveObject->GetWindow(&m_hWndObj);
  1072.     return NOERROR;
  1073.     }
  1074.  
  1075.  
  1076.  
  1077.  
  1078. /*
  1079.  * CFrame::InsertMenus
  1080.  *
  1081.  * Purpose:
  1082.  *  Instructs the container to place its in-place menu items where
  1083.  *  necessary in the given menu and to fill in elements 0, 2, and 4
  1084.  *  of the OLEMENUGROUPWIDTHS array to indicate how many top-level
  1085.  *  items are in each group.
  1086.  *
  1087.  * Parameters:
  1088.  *  hMenu           HMENU in which to add popups.
  1089.  *  pMGW            LPOLEMENUGROUPWIDTHS in which to store the
  1090.  *                  width of each container menu group.
  1091.  *
  1092.  * Return Value:
  1093.  *  HRESULT         NOERROR
  1094.  */
  1095.  
  1096. STDMETHODIMP CFrame::InsertMenus(HMENU hMenu
  1097.     , LPOLEMENUGROUPWIDTHS pMGW)
  1098.     {    
  1099.     //Copy our File menu into the shared menu.    
  1100.     InsertMenu(hMenu, 0, MF_BYPOSITION | MF_POPUP, (UINT)m_phMenu[0]
  1101.         , TEXT("&File"));
  1102.  
  1103.     pMGW->width[0]=1;
  1104.     pMGW->width[2]=0;
  1105.     pMGW->width[4]=0;
  1106.  
  1107.     /*
  1108.      * Add the special help menu which is the first item in
  1109.      * the m_hMenuHelp popup that's sitting around.
  1110.      */
  1111.     InsertMenu(hMenu, 1, MF_BYPOSITION | MF_POPUP
  1112.         , (UINT)m_hMenuHelp, TEXT("&Help"));
  1113.  
  1114.     //Tell the object we added our Help menu
  1115.     pMGW->width[5]=1;    
  1116.     return NOERROR;
  1117.     }
  1118.  
  1119.  
  1120.  
  1121.  
  1122. /*
  1123.  * CFrame::SetMenu
  1124.  *
  1125.  * Purpose:
  1126.  *  Instructs the container to replace whatever menu it's currently
  1127.  *  using with the given menu and to call OleSetMenuDescritor so OLE
  1128.  *  knows to whom to dispatch messages.
  1129.  *
  1130.  * Parameters:
  1131.  *  hMenu           HMENU to show.
  1132.  *  hOLEMenu        HOLEMENU to the menu descriptor.
  1133.  *  hWndObj         HWND of the active object to which messages are
  1134.  *                  dispatched.
  1135.  *
  1136.  * Return Value:
  1137.  *  HRESULT         NOERROR
  1138.  */
  1139.  
  1140. STDMETHODIMP CFrame::SetMenu(HMENU hMenu, HOLEMENU hOLEMenu
  1141.     , HWND hWndObj)
  1142.     {
  1143.     HRESULT         hr;
  1144.  
  1145.     /*
  1146.      * Our responsibilities here are to put the menu on the frame
  1147.      * window and call OleSetMenuDescriptor.
  1148.      */
  1149.  
  1150.     if (NULL==hMenu)
  1151.         {
  1152.         //Prevent redundant calls, or debug warnings on startup.
  1153.         if (NULL==m_hMenuTop)
  1154.             return NOERROR;
  1155.  
  1156.         hMenu=m_hMenuTop;
  1157.         m_hMenuTop=NULL;
  1158.         m_fOurMenuShowing=TRUE;
  1159.         }
  1160.     else
  1161.         {
  1162.         m_hMenuTop=m_hMenuOrg;
  1163.         m_fOurMenuShowing=FALSE;
  1164.  
  1165.         /*
  1166.          * Check if our Help menu has anything added to it.  If so, then
  1167.          * remember to forward menu messages.  If not, remove the Help
  1168.          * menu altogether (destroying it after removing our normal Help
  1169.          * popup, as we also do in RemoveMenus.
  1170.          */
  1171.         if (CHELPITEMS!=GetMenuItemCount(m_hMenuHelp))
  1172.             m_fUsingOurHelp=TRUE;
  1173.         else
  1174.             {            
  1175.             UINT    i, cItems;
  1176.                 
  1177.             cItems=GetMenuItemCount(hMenu);            
  1178.  
  1179.             //Find m_hMenuHelp in the menu and remove it.
  1180.             for (i=0; i < cItems; i++)
  1181.                 {
  1182.                 if (GetSubMenu(hMenu, i)==m_hMenuHelp)
  1183.                     {
  1184.                     RemoveMenu(hMenu, i, MF_BYPOSITION);
  1185.                     break;
  1186.                     }
  1187.                 }                            
  1188.             }            
  1189.         }
  1190.  
  1191.     if (NULL!=hMenu)
  1192.         ::SetMenu(m_hWnd, hMenu);
  1193.  
  1194.     DrawMenuBar(m_hWnd);
  1195.  
  1196.     hr=OleSetMenuDescriptor(hOLEMenu, m_hWnd, hWndObj, NULL, NULL);
  1197.     return hr;
  1198.     }
  1199.  
  1200.  
  1201.  
  1202.  
  1203. /*
  1204.  * CFrame::RemoveMenus
  1205.  *
  1206.  * Purpose:
  1207.  *  Asks the container to remove any menus it put into hMenu in
  1208.  *  InsertMenus.
  1209.  *
  1210.  * Parameters:
  1211.  *  hMenu           HMENU from which to remove the container's
  1212.  *                  items.
  1213.  *
  1214.  * Return Value:
  1215.  *  HRESULT         NOERROR
  1216.  */
  1217.  
  1218. STDMETHODIMP CFrame::RemoveMenus(HMENU hMenu)
  1219.     {
  1220.     int         cItems, i, j;
  1221.     HMENU       hMenuT;
  1222.  
  1223.     /*
  1224.      * To be defensive, loop through this menu removing anything
  1225.      * we recognize (that is, anything in m_phMenu) just in case
  1226.      * the server didn't clean it up right.  At least we can
  1227.      * give ourselves the prophylactic benefit.
  1228.      */
  1229.  
  1230.     if (NULL==hMenu)
  1231.         return NOERROR;
  1232.  
  1233.     cItems=GetMenuItemCount(hMenu);
  1234.  
  1235.     /*
  1236.      * Walk backwards down the menu.  For each popup, see if it
  1237.      * matches any other popup we know about, and if so, remove
  1238.      * it from the shared menu.
  1239.      */
  1240.     for (i=cItems; i >=0; i--)
  1241.         {
  1242.         hMenuT=GetSubMenu(hMenu, i);
  1243.  
  1244.         for (j=0; j <= CMENUS; j++)
  1245.             {
  1246.             //Remove any owned popup, or our special help menu
  1247.             if (hMenuT==m_phMenu[j]
  1248.                 || (hMenuT==m_hMenuHelp && m_hMenuHelp!=NULL))
  1249.                 RemoveMenu(hMenu, i, MF_BYPOSITION);
  1250.             }
  1251.         }
  1252.     
  1253.     m_fUsingOurHelp=FALSE;
  1254.  
  1255.     //The menu should now be empty.
  1256.     return NOERROR;
  1257.     }
  1258.  
  1259.  
  1260.  
  1261.  
  1262. /*
  1263.  * CFrame::SetStatusText
  1264.  *
  1265.  * Purpose:
  1266.  *  Asks the container to place some text in a status line, if one
  1267.  *  exists.  If the container does not have a status line it
  1268.  *  should return E_FAIL here in which case the object could
  1269.  *  display its own.
  1270.  *
  1271.  * Parameters:
  1272.  *  pszText         LPCOLESTR to display.
  1273.  *
  1274.  * Return Value:
  1275.  *  HRESULT         NOERROR if successful, S_TRUNCATED if not all
  1276.  *                  of the text could be displayed, or E_FAIL if
  1277.  *                  the container has no status line.
  1278.  */
  1279.  
  1280. STDMETHODIMP CFrame::SetStatusText(LPCOLESTR pszText)
  1281.     {
  1282.     //We have no status line...
  1283.     return E_NOTIMPL;
  1284.     }
  1285.  
  1286.  
  1287.  
  1288. /*
  1289.  * CFrame::EnableModeless
  1290.  *
  1291.  * Purpose:
  1292.  *  Instructs the container to show or hide any modeless popup
  1293.  *  windows that it may be using.
  1294.  *
  1295.  * Parameters:
  1296.  *  fEnable         BOOL indicating to enable/show the windows
  1297.  *                  (TRUE) or to hide them (FALSE).
  1298.  *
  1299.  * Return Value:
  1300.  *  HRESULT         NOERROR
  1301.  */
  1302.  
  1303. STDMETHODIMP CFrame::EnableModeless(BOOL fEnable)
  1304.     {
  1305.     return NOERROR;
  1306.     }
  1307.  
  1308.  
  1309.  
  1310.  
  1311. /*
  1312.  * CFrame::TranslateAccelerator
  1313.  *
  1314.  * Purpose:
  1315.  *  When dealing with an in-place object from an EXE server, this
  1316.  *  is called to give the container a chance to process accelerators
  1317.  *  after the server has looked at the message.
  1318.  *
  1319.  * Parameters:
  1320.  *  pMSG            LPMSG for the container to examine.
  1321.  *  wID             WORD the identifier in the container's
  1322.  *                  accelerator table (from IOleInPlaceSite
  1323.  *                  ::GetWindowContext) for this message (OLE does
  1324.  *                  some translation before calling).
  1325.  *
  1326.  * Return Value:
  1327.  *  HRESULT         NOERROR if the keystroke was used,
  1328.  *                  S_FALSE otherwise.
  1329.  */
  1330.  
  1331. STDMETHODIMP CFrame::TranslateAccelerator(LPMSG pMSG, WORD wID)
  1332.     {
  1333.     /*
  1334.      * wID already has anything translated from m_hAccel for us,
  1335.      * so we can just check for the commands we want and process
  1336.      * them instead of calling TranslateAccelerator which would be
  1337.      * redundant and which also has a possibility of dispatching to
  1338.      * the wrong window.
  1339.      */
  1340.     if (IDM_ENTERCONTEXTHELP==wID || IDM_ESCAPECONTEXTHELP==wID)
  1341.         {
  1342.         //wID properly expands to 32-bits
  1343.         OnCommand(m_hWnd, (WPARAM)wID, 0L);
  1344.         return NOERROR;
  1345.         }
  1346.  
  1347.     return S_FALSE;
  1348.     }
  1349.  
  1350.  
  1351. /*
  1352.  * IOleCommandTarget methods, provided to make PowerPoint happy
  1353.  * with this frame.
  1354.  */
  1355.  
  1356. STDMETHODIMP CFrame::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds
  1357.     , OLECMD *prgCmds, OLECMDTEXT *pCmdText)
  1358.     {
  1359.     return OLECMDERR_E_UNKNOWNGROUP;
  1360.     }
  1361.         
  1362. STDMETHODIMP CFrame::Exec(const GUID *pguidCmdGroup, DWORD nCmdID
  1363.     , DWORD nCmdexecopt, VARIANTARG *pvaIn, VARIANTARG *pvaOut)
  1364.     {
  1365.     return OLECMDERR_E_UNKNOWNGROUP;
  1366.     }
  1367.     
  1368.