home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / winui / shell / fileview / fvtext.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-06-12  |  27.1 KB  |  939 lines

  1. //THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 
  2. //ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 
  3. //THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 
  4. // PARTICULAR PURPOSE.
  5. //
  6. // Copyright  1994-1996  Microsoft Corporation.  All Rights Reserved.
  7. //
  8. //    PROGRAM: FVTEXT.CPP        
  9. //
  10. //    PURPOSE:  Sample FileViewer for text files to integrate with the Explorer.  This sample serves as a 
  11. //    framework for custom viewers.  Initialization and other low-use functions are in FVMISC.CPP.
  12. //
  13. //    PLATFORMS:    Windows 95
  14. //
  15. //    FUNCTIONS:    
  16. //   
  17. //
  18. //    SPECIAL INSTRUCTIONS: N/A
  19. //
  20.  
  21. #include "fileview.h"
  22.  
  23. //
  24. //   FUNCTION: CFileViewer::CFileViewer    
  25. //
  26. //   PURPOSE: Constructor for the CFileViewer class.  Initializes all variables.
  27. //
  28. //   PARAMETERS: 
  29. //    pUnkOuter - LPUNKNOWN of a controlling unknown.
  30. //    hInst - HINSTANCE of the module we're in
  31. //    pfnDestroy - LPFNDESTROYED to call when an object is destroyed.
  32. //
  33. CFileViewer::CFileViewer(LPUNKNOWN pUnkOuter, HINSTANCE hInst, PFNDESTROYED pfnDestroy)
  34. {
  35.     m_cRef=0;
  36.     m_pUnkOuter=pUnkOuter;
  37.     m_hInst=hInst;
  38.     m_pfnDestroy=pfnDestroy;
  39.     m_lpfsi = NULL;
  40.  
  41.     //MODIFY:  Change this CLSID to your own
  42.     m_clsID=CLSID_FileViewerText;
  43.  
  44.     m_pszPath=NULL;
  45.     m_grfMode=0L;
  46.     m_fLoadCalled=FALSE;
  47.     m_fShowInit=FALSE;
  48.     m_fPostQuitMsg=TRUE;
  49.  
  50.     //NULL any contained interfaces initially.
  51.     m_pIPersistFile=NULL;
  52.     m_pIFileViewer=NULL;
  53.     m_pvsi = NULL;
  54.  
  55.     m_pST=NULL;
  56.     m_pSH=NULL;
  57.     m_fClassReg=FALSE;
  58.  
  59.     m_hWnd=NULL;
  60.     m_hWndOld = NULL;
  61.     m_hWndToolbar=NULL;
  62.     m_hWndStatus=NULL;
  63.     m_hWndViewport=NULL;
  64.  
  65.     //MODIFY:  Initalize viewer-specific values
  66.     m_hMemText=NULL;
  67.     m_hFont=NULL;
  68.     m_xPos=0;
  69.     m_yPos=0;
  70.     return;
  71. }
  72.  
  73. //
  74. //   FUNCTION:  CFileViewer::~CFileViewer
  75. //
  76. //   PURPOSE:   Destructor:deletes all the windows, all allocations, cleans up objects, and
  77. //   frees the filename copied in IPersistFile::Load.
  78. //
  79. CFileViewer::~CFileViewer(void)
  80. {
  81.     //MODIFY:  m_hMemText and m_hFont are viewer-specific.
  82.     if (NULL!=m_hMemText)
  83.         GlobalFree(m_hMemText);
  84.  
  85.     if (NULL!=m_hFont)
  86.         DeleteObject(m_hFont);
  87.  
  88.     //MODIFY:  Do any other viewer-specific cleanup
  89.     //Destroying the parent destroys the children as well
  90.     if (NULL!=m_hWnd)
  91.     {
  92.         m_fPostQuitMsg = FALSE;    // Destroy from here implies not from our loop
  93.         DestroyWindow(m_hWnd);
  94.     }
  95.  
  96.      // Unregistering the classes is important for DLL's because we
  97.      // should not assume that whoever loaded us (the task) is going
  98.      // to quit anytime soon and unregister the class.  Normally
  99.      // QVStub is going to quit, but a test app like TestFV does not
  100.      // which can cause some development headaches.
  101.     if (m_fClassReg)
  102.         {
  103.         UnregisterClass(String(IDS_CLASSFRAME),    m_hInst);
  104.         UnregisterClass(String(IDS_CLASSVIEWPORT), m_hInst);
  105.         }
  106.  
  107.     if (NULL!=m_pSH)
  108.         delete m_pSH;
  109.  
  110.     if (NULL!=m_pST)
  111.         delete m_pST;
  112.  
  113.     //Free the pathname string from IPersistFile::Load if we got one
  114.     MemFree(m_pszPath);
  115.  
  116.     //Free contained interfaces.
  117.     if (NULL!=m_pIPersistFile)
  118.         delete m_pIPersistFile;
  119.  
  120.     if (NULL!=m_pIFileViewer)
  121.         delete m_pIFileViewer;
  122.     if (NULL!=m_lpfsi)
  123.         m_lpfsi->Release();
  124.  
  125.     return;
  126. }
  127.  
  128. //
  129. //   FUNCTION: CFileViewer::FileShowInit    
  130. //
  131. //   PURPOSE:Provides the implementation of IFileViewer::ShowInitialize that performs 
  132. //   anything subject to failure. This function creates the main window, initializes the toolbar,
  133. //   initializes the status bar controls, sets the initial menu state, creates the viewport window, and
  134. //   loads the accelerators.
  135. //
  136. //   RETURN VALUE:
  137. //
  138. //   HRESULT         NOERROR or an appropriate error code.
  139. //
  140. STDMETHODIMP CFileViewer::FileShowInit(LPFILEVIEWERSITE lpfsi)
  141. {
  142.     HRESULT         hr;
  143.     HMENU           hMenu;
  144.  
  145.     //MODIFY:  Do pre-show initialization here.
  146.     if (m_lpfsi != lpfsi)
  147.     {
  148.         if (NULL!=m_lpfsi)
  149.             m_lpfsi->Release();
  150.  
  151.         m_lpfsi = lpfsi;
  152.         lpfsi->AddRef();
  153.     }
  154.  
  155.     //Default error code
  156.     hr=ResultFromScode(E_OUTOFMEMORY);
  157.  
  158.     //Create the main window passing "this" to it
  159.     m_hWndOld = m_hWnd;
  160.     m_hWnd=CreateWindow(String(IDS_CLASSFRAME)
  161.         , String(IDS_CAPTION), WS_MINIMIZEBOX | WS_OVERLAPPEDWINDOW
  162.         | WS_CLIPCHILDREN, CW_USEDEFAULT , CW_USEDEFAULT, 350, 450
  163.         , NULL, NULL, m_hInst, (LPVOID)this);
  164.  
  165.     if (NULL==m_hWnd)
  166.         {
  167.         ODS("CFileViewer::FileShow failed to create main window.");
  168.         return hr;
  169.         }
  170.  
  171.     // Let us accept files.
  172.     DragAcceptFiles(m_hWnd, TRUE);
  173.  
  174.     if (!FInitFrameControls())
  175.         {
  176.         ODS("CFileViewer::FileShow failed to create frame tools.");
  177.         return hr;
  178.         }
  179.  
  180.     //Set initial view menu item checks
  181.     hMenu=GetMenu(m_hWnd);
  182.     CheckMenuItem(hMenu, IDM_VIEWTOOLBAR, MF_BYCOMMAND | MF_CHECKED);
  183.     CheckMenuItem(hMenu, IDM_VIEWSTATUSBAR, MF_BYCOMMAND | MF_CHECKED);
  184.  
  185.     m_fToolsVisible=TRUE;
  186.     m_fStatusVisible=TRUE;
  187.  
  188.     m_pSH->MessageDisplay(ID_MSGREADY);
  189.  
  190.      // ViewportResize puts the viewport window created here
  191.      // in the right location, so we don't have to worry
  192.      // about initial position.
  193.     //BUGBUG:  Not getting proportional thumbs here.
  194.  
  195.     m_hWndViewport=CreateWindowEx(WS_EX_CLIENTEDGE
  196.         , String(IDS_CLASSVIEWPORT), "Viewport"
  197.         , WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL
  198.         , 0, 0, 100, 100, m_hWnd, (HMENU)ID_VIEWPORT
  199.         , m_hInst, (LPVOID)this);
  200.  
  201.     if (NULL==m_hWndViewport)
  202.         {
  203.         ODS("CFileViewer::FileShow failed to create viewport.");
  204.         return hr;
  205.         }
  206.  
  207.     ViewportResize();
  208.  
  209.      // Go load the file.  This means pulling into memory whatever
  210.      // is necessary for the initial display.
  211.     hr=FileLoad();
  212.  
  213.     if (FAILED(hr))
  214.         {
  215.         ODS("CFileViewer::FileShow failed to load file.");
  216.         return hr;
  217.         }
  218.  
  219.     m_hAccel=LoadAccelerators(m_hInst
  220.         , MAKEINTRESOURCE(IDR_ACCELERATORS));
  221.  
  222.     //Tell IFileViewer::Show it's OK to call it
  223.     m_fShowInit=TRUE;
  224.     return NOERROR;
  225. }
  226.  
  227. //
  228. //   FUNCTION:      CFileViewer::FileShow
  229. //
  230. //   PURPOSE: Displays the viewing window and enters a message loop.  This function must not fail.  
  231. //
  232. //   PARAMETERS: 
  233. //   pvsi - LPFVSHOWINFO indicates how to initially show the FileViewer window.
  234. //
  235. //   RETURN VALUE:
  236. //    HRESULT  - NOERROR always
  237. //
  238. STDMETHODIMP CFileViewer::FileShow(LPFVSHOWINFO pvsi)
  239. {
  240.     MSG             msg;
  241.  
  242.     // We need to handle the case where the ShowInitialize may have
  243.     // failed and we set the hwnd to NULL and the hwndOld is not NULL.
  244.     // and the FVSIF_NEWFAILED is set.  In this case set the hwnd Back
  245.     // to the old hwnd...
  246.     if ((pvsi->dwFlags & FVSIF_NEWFAILED) && (m_hWnd == NULL))
  247.     {
  248.         m_hWnd = m_hWndOld;
  249.     }
  250.  
  251.     if (!IsWindow (m_hWnd))
  252.             return ResultFromScode(E_UNEXPECTED);
  253.  
  254.     m_pvsi = pvsi;
  255.  
  256.     // If the new failed flag was passed to us we know that we got here
  257.     // because we tried to view a file and it failed, so simply go back
  258.     // to message loop...
  259.     if ((pvsi->dwFlags & FVSIF_NEWFAILED) == 0)
  260.     {
  261.         if (pvsi->dwFlags & FVSIF_RECT)
  262.             SetWindowPos(m_hWnd, NULL, pvsi->rect.left, pvsi->rect.top,
  263.                     pvsi->rect.right - pvsi->rect.left, pvsi->rect.bottom - pvsi->rect.top,
  264.                     SWP_NOZORDER | SWP_NOACTIVATE);
  265.         ShowWindow(m_hWnd, pvsi->iShow);
  266.  
  267.         if (SW_HIDE!=pvsi->iShow)
  268.         {
  269.             SetForegroundWindow(m_hWnd);
  270.             UpdateWindow(m_hWnd);
  271.         }
  272.  
  273.         // If there is an Old window destroy it now
  274.         // It would be nicer to reuse the window!
  275.         if (pvsi->dwFlags & FVSIF_PINNED)
  276.         {
  277.             m_lpfsi->SetPinnedWindow(NULL);
  278.             m_lpfsi->SetPinnedWindow(m_hWnd);
  279.  
  280.             HMENU hMenu=GetMenu(m_hWnd);
  281.             CheckMenuItem(hMenu, IDM_VIEWREPLACE, MF_BYCOMMAND|MF_CHECKED);
  282.         }
  283.  
  284.         if (SW_HIDE!=pvsi->iShow)
  285.             UpdateWindow(m_hWnd);
  286.  
  287.         if ((NULL!=m_hWndOld) && IsWindow(m_hWndOld))
  288.         {
  289.             ODS("CFileViewer::FileShow Destroy Previous hwnd");
  290.             m_fPostQuitMsg = FALSE; // Don't destroy the queue for this one.
  291.             DestroyWindow(m_hWndOld);
  292.             m_hWndOld = NULL;
  293.         }
  294.  
  295.         if (NULL!=pvsi->punkRel)
  296.         {
  297.             ODSlu("CFileViewer::FileShow Release of previous viewers punkRel(%x)", pvsi->punkRel);
  298.             pvsi->punkRel->Release();
  299.             pvsi->punkRel = NULL;
  300.         }
  301.     }
  302.  
  303.     while (GetMessage(&msg, NULL, 0,0 ))
  304.         {
  305.         if (!TranslateAccelerator(m_hWnd, m_hAccel, &msg))
  306.             {
  307.             TranslateMessage(&msg);
  308.             DispatchMessage(&msg);
  309.             }
  310.         // If there is a new file bail out now.
  311.         if (m_pvsi->dwFlags & FVSIF_NEWFILE)
  312.             break;
  313.         }
  314.  
  315.     //MODIFY:  Perform cleanup here.
  316.     return NOERROR;
  317. }
  318.  
  319. //
  320. //   FUNCTION:     CFileViewer::PrintTo
  321. //
  322. //   PURPOSE:  Provides the implementation of IFileViewer::PrintTo that
  323. //  prints the file to a given printer driver, suppressing UI
  324. //  if necessary.  This function currently does nothing.
  325. //
  326. //   PARAMETERS: 
  327. //    pszDriver - LPSTR with the path of the driver to use.  If NULL, use the default driver.
  328. //    fSuppressUI - BOOL indicating if this function is to show any  UI or not.
  329. //
  330. //   RETURN VALUE:
  331. //   HRESULT - NOERROR on success, error code otherwise.
  332. //
  333. STDMETHODIMP CFileViewer::PrintTo(LPSTR pszDriver, BOOL fSuppressUI)
  334.     {
  335.     //Printing not implemented in this sample
  336.     //MODIFY:  Add your printing code here.
  337.     return ResultFromScode(E_NOTIMPL);
  338. }
  339.  
  340. //
  341. //   FUNCTION:      CFileViewer::FileLoad
  342. //
  343. //   PURPOSE: Loads the file with the path in m_pszPath and places the
  344. //   contents into the m_hWndViewport window.  This function can load
  345. //   a compound file with a "Text" stream or text from a .TXT file.
  346. //
  347. HRESULT CFileViewer::FileLoad(void)
  348. {
  349.     HRESULT     hr;
  350.     HGLOBAL     hMem=NULL;
  351.     LPSTR       psz;
  352.     OLECHAR     szwFile[512];
  353.  
  354.     //MODIFY: Load your own file type here.
  355.     if (NULL==m_pszPath)
  356.         return ResultFromScode(E_UNEXPECTED);
  357.  
  358.      // This FileViewer is registered for a .TXT extension that
  359.      // is either in a compound file (single stream called "Text"
  360.      // or in a flat text file.  This sample is meant to show
  361.      // how to open and work with both types of files.
  362.     //Make Unicode copy of filename
  363.     mbstowcs(szwFile, m_pszPath, sizeof(szwFile));
  364.  
  365.      // CAREFUL:  StgIsStorageFile returns S_FALSE if not--
  366.      //           don't use SUCCEEDED to test the return value!
  367.     if (NOERROR==StgIsStorageFile(szwFile))
  368.         {
  369.         LPSTORAGE   pIStorage=NULL;
  370.         LPSTREAM    pIStream=NULL;
  371.         STATSTG     stat;
  372.  
  373.         //Case for a compound file, open it and the text stream
  374.         hr=StgOpenStorage(szwFile, NULL, m_grfMode, NULL, 0
  375.             , &pIStorage);
  376.  
  377.         if (FAILED(hr))
  378.             {
  379.             ODS("CFileViewer::FileLoad failed StgOpenStorage");
  380.             return hr;
  381.             }
  382.  
  383.         mbstowcs(szwFile, "Text", sizeof(szwFile));
  384.  
  385.         hr=pIStorage->OpenStream(szwFile, 0, STGM_DIRECT | STGM_READ
  386.             | STGM_SHARE_EXCLUSIVE, 0, &pIStream);
  387.  
  388.         if (SUCCEEDED(hr))
  389.             {
  390.             //Determine the amount of text and allocate memory
  391.             hr=pIStream->Stat(&stat, STATFLAG_NONAME);
  392.  
  393.             if (SUCCEEDED(hr))
  394.                 {
  395.                 hMem=GlobalAlloc(GHND, stat.cbSize.LowPart+1);
  396.  
  397.                 if (NULL!=hMem)
  398.                     {
  399.                      // Now load the text into the controls.
  400.                      // GlobalLock will always work because we
  401.                      // allocated at least 1 byte.
  402.                     psz=(LPSTR)GlobalLock(hMem);
  403.                     hr=pIStream->Read((LPVOID)psz
  404.                         , stat.cbSize.LowPart, NULL);
  405.                     GlobalUnlock(hMem);
  406.                     }
  407.                 else
  408.                     {
  409.                     ODS("CFileViewer::FileLoad failed to allocate memory");
  410.                     hr=ResultFromScode(E_OUTOFMEMORY);
  411.                     }
  412.                 }
  413.  
  414.             pIStream->Release();
  415.             }
  416.         else
  417.             {
  418.             ODS("CFileViewer::FileLoad failed StgOpenStorage");
  419.             }
  420.  
  421.         pIStorage->Release();
  422.         }
  423.     else
  424.         {
  425.         int         hFile=NULL;
  426.         OFSTRUCT    of;
  427.         DWORD       cb, cbRead;
  428.  
  429.          // Case for straight text file, open and read.  In opening
  430.          // the file, mask off the upper word or m_grfMode which
  431.          // contains the compound file specific flags.  The lower
  432.          // word has OpenFile flags (consistent between
  433.          // StgOpenStorage and OpenFile).
  434.         hFile=OpenFile(m_pszPath, &of
  435.             , (UINT)(m_grfMode & 0x0000FFFF));
  436.  
  437.         if (HFILE_ERROR==hFile)
  438.             {
  439.             ODS("CFileViewer::FileLoad failed OpenFile");
  440.             return ResultFromScode(STG_E_FILENOTFOUND);
  441.             }
  442.  
  443.         //Scan to end and then back to determine file size.
  444.         cb=_llseek(hFile, 0L, 2);
  445.         _llseek(hFile, 0L, 0);
  446.  
  447.         hMem=GlobalAlloc(GHND, cb+1);
  448.  
  449.         if (NULL!=hMem)
  450.             {
  451.              // Now load the text into the controls.  GlobalLock will
  452.              // always work because we allocated at least 1 byte
  453.             psz=(LPSTR)GlobalLock(hMem);
  454.             cbRead=_lread(hFile, psz, (UINT)cb);
  455.             GlobalUnlock(hMem);
  456.  
  457.             hr=ResultFromScode((cb==cbRead) ? S_OK : STG_E_READFAULT);
  458.             }
  459.         else
  460.             {
  461.             ODS("CFileViewer::FileLoad failed to allocate memory");
  462.             hr=ResultFromScode(E_OUTOFMEMORY);
  463.             }
  464.  
  465.         _lclose(hFile);
  466.         }
  467.  
  468.     //Set edit control to read-only:  no modifications allowed!
  469.     if (SUCCEEDED(hr) && NULL!=hMem)
  470.         {
  471.         if (NULL!=m_hMemText)
  472.             GlobalFree(m_hMemText);
  473.  
  474.         //Make the text current and repaint.
  475.         m_hMemText=hMem;
  476.         InvalidateRect(m_hWndViewport, NULL, TRUE);
  477.         UpdateWindow(m_hWndViewport);
  478.         }
  479.  
  480.     return hr;
  481. }
  482.  
  483. //
  484. //   FUNCTION:     CFileViewer::OnCommand
  485. //
  486. //   PURPOSE: WM_COMMAND message handler for a FileViewer window.  
  487. //
  488. //   PARAMETERS: 
  489. //       wID             WORD ID of the command.
  490. //  wCode           WORD notification code with the command
  491. //  hWndCtl         HWND sending the message (if a control)
  492. //
  493. void CFileViewer::OnCommand(WORD wID, WORD wCode, HWND hWndCtl)
  494. {
  495.     //MODIFY:  Do your command processing here.
  496.     switch (wID)
  497.         {
  498.         case IDM_FILEOPENAS:
  499.             if (FOpenAs())
  500.                 PostMessage(m_hWnd, WM_CLOSE, 0, 0L);
  501.             break;
  502.  
  503.         case IDM_FILEPAGESETUP:
  504.             //Not implemented in this sample
  505.             break;
  506.  
  507.         case IDM_FILEPRINT:
  508.             //Not implemented in this sample
  509.             break;
  510.  
  511.         case IDM_FILEEXIT:
  512.             PostMessage(m_hWnd, WM_CLOSE, 0, 0L);
  513.             break;
  514.  
  515.         case IDM_VIEWTOOLBAR:
  516.             m_fToolsVisible=!m_fToolsVisible;
  517.  
  518.             CheckMenuItem(GetMenu(m_hWnd), IDM_VIEWTOOLBAR
  519.                 , MF_BYCOMMAND | (m_fToolsVisible
  520.                 ? MF_CHECKED : MF_UNCHECKED));
  521.  
  522.             ShowWindow(m_hWndToolbar, m_fToolsVisible
  523.                 ? SW_SHOW : SW_HIDE);
  524.  
  525.             //Resize the viewport window
  526.             ViewportResize();
  527.             break;
  528.  
  529.         case IDM_VIEWSTATUSBAR:
  530.             m_fStatusVisible=!m_fStatusVisible;
  531.  
  532.             CheckMenuItem(GetMenu(m_hWnd), IDM_VIEWSTATUSBAR
  533.                 , MF_BYCOMMAND | (m_fStatusVisible
  534.                 ? MF_CHECKED : MF_UNCHECKED));
  535.  
  536.             ShowWindow(m_hWndStatus, m_fStatusVisible
  537.                 ? SW_SHOW : SW_HIDE);
  538.  
  539.             //Resize the viewport window
  540.             ViewportResize();
  541.             break;
  542.         case IDM_VIEWREPLACE:
  543.             // Switch the Replace mode
  544.             ReplaceWindowModeChange();
  545.             break;
  546.         case IDM_VIEWFONT:
  547.             FontChange(VIEWFONT_SELECT);
  548.             break;
  549.  
  550.         case IDM_VIEWFONTINCREASE:
  551.             FontChange(VIEWFONT_INCREASESIZE);
  552.             break;
  553.  
  554.         case IDM_VIEWFONTDECREASE:
  555.             FontChange(VIEWFONT_DECREASESIZE);
  556.             break;
  557.  
  558.         case IDM_HELPCONTENTS:
  559.             MessageBox(m_hWnd, String(IDS_NOHELP)
  560.                 , String(IDS_CAPTION), MB_OK);
  561.             break;
  562.  
  563.         case IDM_HELPABOUT:
  564.             DialogBox(m_hInst, MAKEINTRESOURCE(IDD_ABOUT), m_hWnd
  565.                 , (DLGPROC)AboutProc);
  566.             break;
  567.         }
  568.  
  569.     return;
  570. }
  571.  
  572. //
  573. //   FUNCTION:  CFileViewer::ChildrenResize    
  574. //
  575. //   PURPOSE:    Handles the situation when the FileViewer frame window was
  576. //   resized. The toolbar, status bar and viewport are resized via a call to the 
  577. //   the ViewportResize function.
  578. //
  579. //   COMMENTS:
  580. //   Note that the toolbar and status bar are resized even when
  581. //   they are not visible so we can just reshow them again when
  582. //   necessary.
  583. //
  584. void CFileViewer::ChildrenResize(void)
  585. {
  586.     RECT        rc;
  587.  
  588.     GetClientRect(m_hWnd, &rc);
  589.  
  590.     //We resize toolbar and status bar regardless of visibility
  591.     SetWindowPos(m_hWndToolbar, NULL, 0, 0
  592.         , rc.right-rc.left, m_cyTools
  593.         , SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
  594.  
  595.     SetWindowPos(m_hWndStatus, NULL, 0, rc.bottom-m_cyStatus
  596.         , rc.right-rc.left, m_cyStatus
  597.         , SWP_NOZORDER | SWP_NOACTIVATE);
  598.  
  599.     ViewportResize();
  600.     return;
  601. }
  602.  
  603. //
  604. //   FUNCTION: CFileViewer::ViewportResize    
  605. //
  606. //   PURPOSE: Updates the size and position of the viewport window
  607. //   depending on visibility of the toolbar and status bar.  
  608. //
  609. void CFileViewer::ViewportResize(void)
  610. {
  611.     RECT        rc;
  612.     UINT        dy1, dy2;
  613.  
  614.     GetClientRect(m_hWnd, &rc);
  615.  
  616.     dy1=m_fToolsVisible  ? m_cyTools  : 0;
  617.     dy2=m_fStatusVisible ? m_cyStatus : 0;
  618.  
  619.     //We resize toolbar and status bar regardless of visibility
  620.     SetWindowPos(m_hWndViewport, NULL, 0, dy1
  621.         , rc.right-rc.left, rc.bottom-rc.top-dy1-dy2
  622.         , SWP_NOZORDER | SWP_NOACTIVATE);
  623.  
  624.     ViewportScrollSet();
  625.     return;
  626. }
  627.  
  628. //
  629. //   FUNCTION:     CFileViewer::ViewportScrollSet
  630. //
  631. //   PURPOSE:  Updates the scrollbar ranges in the viewport depending on
  632. //   the current font in use and the size of the window.  
  633. //
  634. void CFileViewer::ViewportScrollSet(void)
  635. {
  636.     RECT        rc, rcFmt;
  637.     LPSTR       psz;
  638.     HDC         hDC;
  639.     HFONT       hFont;
  640.     SCROLLINFO  si;
  641.  
  642.     if (NULL==m_hMemText)
  643.         return;
  644.  
  645.     psz=(LPSTR)GlobalLock(m_hMemText);
  646.     hDC=GetDC(m_hWndViewport);
  647.     hFont=(HFONT)SelectObject(hDC, m_hFont);
  648.  
  649.      // Set initially large formatting rectangle, and let
  650.      // DrawText walk all over it.
  651.     SetRect(&rcFmt, 0, 0, 32767, 32767);
  652.     DrawText(hDC, psz, -1, &rcFmt, DT_LEFT | DT_CALCRECT
  653.         | DT_EXPANDTABS);
  654.  
  655.     SelectObject(hDC, hFont);
  656.     ReleaseDC(m_hWndViewport, hDC);
  657.  
  658.     GetClientRect(m_hWndViewport, &rc);
  659.  
  660.     //Scroll ranges are draw rect minus visible rect, +1 for buffer
  661.     // First set the horizontal scrollbars information...
  662.     si.cbSize = sizeof(si);
  663.     si.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
  664.     si.nMin = 0;
  665.     si.nMax = (rcFmt.right-rcFmt.left)+1;
  666.     si.nPage = rc.right;
  667.     si.nPos = 0;
  668.     SetScrollInfo(m_hWndViewport, SB_HORZ, &si, TRUE);
  669.     m_xPos=0;
  670.  
  671.     // Now Set the vertical scrollbar
  672.     si.nMax = (rcFmt.bottom-rcFmt.top)+1;
  673.     si.nPage = rc.bottom;
  674.     SetScrollInfo(m_hWndViewport, SB_VERT, &si, TRUE);
  675.     m_yPos=0;
  676.  
  677.     GlobalUnlock(m_hMemText);
  678.     return;
  679. }
  680.  
  681. //
  682. //   FUNCTION: CFileViewer::FOpenAs    
  683. //
  684. //   PURPOSE:  Attempts to launch an application to open the file for editing.  
  685. //
  686. //   RETURN VALUE:
  687. //   BOOL -  TRUE if the application is opened in which case
  688. //                  the FileViewer can shut down.  Otherwise FALSE
  689. //                  meaning launching failed.
  690. //
  691. BOOL CFileViewer::FOpenAs(void)
  692. {
  693.     SHELLEXECUTEINFO sei = {sizeof(sei), 0, m_hWnd, "open",
  694.             m_pszPath, NULL, NULL, SW_SHOWNORMAL, m_hInst};
  695.  
  696.     return ShellExecuteEx(&sei);
  697. }
  698.  
  699. //
  700. //   FUNCTION:     CFileViewer::FontChange
  701. //
  702. //   PURPOSE:  Either allows the user to choose a font or increments or
  703. //  decrements the font size depending on uOpt.  This is all
  704. //  handled in one function here because each operation
  705. //  involves obtaining the current viewport font, messing with
  706. //  it in some way, and setting a new font again.
  707. //
  708. //   PARAMETERS: 
  709. //     uOpt          VIEWFONTOPTION of the way to change the font:
  710. //                      VIEWFONT_SELECT     Display dialog
  711. //                      VIEWFONT_INCREASE   Increase size by 2pt
  712. //                      VIEWFONT_DECREASE   Decreate size by 2pt
  713. //
  714. void CFileViewer::FontChange(VIEWFONTOPTION uOpt)
  715. {
  716.     HFONT       hFont;
  717.     LOGFONT     lf;
  718.     CHOOSEFONT  cf;
  719.     BOOL        fChange=TRUE;
  720.     int         z;
  721.  
  722.      // We have a system font from the constructor, so m_hFont
  723.      // will never be NULL, but assert it anyway.
  724.     D(if (NULL==m_hFont) ODS("Assertion Failed:  m_hFont is NULL"););
  725.  
  726.     GetObject(m_hFont, sizeof(lf), &lf);
  727.      // Each option is responsible for manipulating
  728.      // the LOGFONT structure in some way.  If there
  729.      // is nothing to do, they set fChange to FALSE
  730.     switch (uOpt)
  731.         {
  732.         case VIEWFONT_SELECT:
  733.             memset(&cf, 0, sizeof(CHOOSECOLOR));
  734.             cf.lStructSize=sizeof(CHOOSECOLOR);
  735.             cf.hwndOwner  =m_hWnd;
  736.             cf.lpLogFont  =&lf;
  737.             cf.nSizeMin   =FONTSIZETHRESHOLDMIN;
  738.             cf.nSizeMax   =FONTSIZETHRESHOLDMAX;
  739.  
  740.             cf.Flags=CF_SCREENFONTS | CF_INITTOLOGFONTSTRUCT
  741.                 | CF_FORCEFONTEXIST;
  742.  
  743.             if (!ChooseFont(&cf))
  744.                 {
  745.                 D(DWORD dwErr=CommDlgExtendedError();
  746.                 ODSlu("FVTEXT.DLL:  ChooseFont failed with %lu", dwErr););
  747.  
  748.                 fChange=FALSE;
  749.                 }
  750.  
  751.             break;
  752.  
  753.  
  754.         case VIEWFONT_INCREASESIZE:
  755.             //Convert logical size to point size.
  756.             z=MulDiv(-lf.lfHeight, 72, m_cyPPI);
  757.  
  758.             //Vary the size increase depending on point size.
  759.             if (z < FONTSIZETHRESHOLDMAX)
  760.                 {
  761.                 if (z < FONTSIZETHRESHOLDLOW)
  762.                     z+=FONTSIZEDELTASMALL;
  763.                 else
  764.                     {
  765.                     if (z < FONTSIZETHRESHOLDMID)
  766.                         z+=FONTSIZEDELTAMEDIUM;
  767.                     else
  768.                         z+=FONTSIZEDELTALARGE;
  769.                     }
  770.  
  771.                 //Convert point size to logical size.
  772.                 lf.lfHeight=MulDiv(-z, m_cyPPI, 72);
  773.                 }
  774.             else
  775.                 fChange=FALSE;
  776.  
  777.             break;
  778.  
  779.         case VIEWFONT_DECREASESIZE:
  780.             //Convert logical size to point size.
  781.             z=MulDiv(-lf.lfHeight, 72, m_cyPPI);
  782.  
  783.             //Vary the size decrease depending on point size.
  784.             if (z > FONTSIZETHRESHOLDMIN)
  785.                 {
  786.                 if (z > FONTSIZETHRESHOLDMID)
  787.                     z-=FONTSIZEDELTALARGE;
  788.                 else
  789.                     {
  790.                     if (z > FONTSIZETHRESHOLDLOW)
  791.                         z-=FONTSIZEDELTAMEDIUM;
  792.                     else
  793.                         z-=FONTSIZEDELTASMALL;
  794.                     }
  795.  
  796.                 //Convert point size to logical size.
  797.                 lf.lfHeight=MulDiv(-z, m_cyPPI, 72);
  798.                 }
  799.             else
  800.                 fChange=FALSE;
  801.  
  802.             break;
  803.  
  804.         default:
  805.             fChange=FALSE;
  806.         }
  807.  
  808.     //Return now if we didn't change anything.
  809.     if (!fChange)
  810.         return;
  811.  
  812.     //Now switch fonts and update the viewport.
  813.     hFont=CreateFontIndirect(&lf);
  814.  
  815.     if (NULL!=hFont)
  816.         {
  817.         if (NULL!=m_hFont)
  818.             DeleteObject(m_hFont);
  819.  
  820.         m_hFont=hFont;
  821.  
  822.         ViewportScrollSet();
  823.  
  824.         //Repaint the viewport
  825.         InvalidateRect(m_hWndViewport, NULL, TRUE);
  826.         UpdateWindow(m_hWndViewport);
  827.         }
  828.  
  829.     return;
  830. }
  831.  
  832. //
  833. //   FUNCTION:     CFileViewer::ReplaceWindowModeChange
  834. //
  835. //   PURPOSE: Sets the window to be pinned or not to be pinned.  When the
  836. //   window is pinned, the caller of the viewers will attempt
  837. //   to replace the contents of the window instead of creating
  838. //   new windows.  
  839. //
  840. void CFileViewer::ReplaceWindowModeChange(void)
  841. {
  842.     HWND hwnd;
  843.     UINT  uCheck = MF_BYCOMMAND;
  844.  
  845.     if (m_lpfsi)
  846.     {
  847.         m_lpfsi->GetPinnedWindow(&hwnd);
  848.         if ((HWND)NULL==hwnd)
  849.         {
  850.             m_lpfsi->SetPinnedWindow(m_hWnd);
  851.             uCheck = MF_BYCOMMAND | MF_CHECKED;
  852.         }
  853.         else
  854.         {
  855.             if (hwnd==m_hWnd)
  856.                 m_lpfsi->SetPinnedWindow(NULL);
  857.         }
  858.  
  859.     }
  860.  
  861.     HMENU hMenu=GetMenu(m_hWnd);
  862.     CheckMenuItem(hMenu, IDM_VIEWREPLACE, uCheck);
  863. }
  864.  
  865. //
  866. //   FUNCTION: CFileViewer::DropFiles    
  867. //
  868. //   PURPOSE:   Processes a drop 
  869. //
  870. BOOL    CFileViewer::DropFiles (HDROP hdrop)
  871. {
  872.     // We should now proces the files that were dropped on us
  873.     char    szPath[MAX_PATH];
  874.     int     cb;
  875.  
  876.     // For now only process the first file.
  877.     if (DragQueryFile(hdrop, 0, szPath, sizeof(szPath)) > 0)
  878.     {
  879.         ODSsz("CFileViewer::DropFiles filename=%s", szPath);
  880.  
  881.         // Need to convert the string to ole string...
  882.         cb = (lstrlen(szPath)+1) * sizeof(OLECHAR);
  883.         mbstowcs(m_pvsi->strNewFile, szPath, cb);
  884.  
  885.         // Now get the window rectangle to use to display this in...
  886.         GetWindowRect(m_hWnd, &m_pvsi->rect);
  887.         m_pvsi->dwFlags |= (FVSIF_RECT | FVSIF_NEWFILE);
  888.  
  889.         // Should check for failure but now sure what to do with it anyway
  890.         QueryInterface(IID_IUnknown, (LPVOID *)&m_pvsi->punkRel);
  891.         ODSlu("CFileViewer::DropFiles Query Interface(%x)", m_pvsi->punkRel);
  892.     }
  893.  
  894.     DragFinish(hdrop);
  895.     return TRUE;
  896. }
  897.  
  898. //
  899. //   FUNCTION: CFileViewer::PszToolTip    
  900. //
  901. //   PURPOSE: Returns a string pointer to a tool tip for the given command
  902. //   ID value.  When asked for a string we also display a similar
  903. //   one in the status bar.  
  904. //
  905. //   PARAMETERS: 
  906. //   uID - UINT of the toolbar button command.
  907. //
  908. //   RETURN VALUE:
  909. //   LPSTR - Pointer to the string to display.
  910. //
  911. LPSTR CFileViewer::PszToolTip(UINT uID)
  912. {
  913.     UINT        iString, iStatusMsg;
  914.  
  915.     switch (uID)
  916.         {
  917.         case IDM_FILEOPENAS:
  918.             iString=IDS_TOOLTIPOPENAS;
  919.             iStatusMsg=IDM_FILEOPENAS;
  920.             break;
  921.  
  922.         case IDM_VIEWFONTINCREASE:
  923.             iString=IDS_TOOLTIPFONTINC;
  924.             iStatusMsg=ID_TIPFONTINC;
  925.             break;
  926.  
  927.         case IDM_VIEWFONTDECREASE:
  928.             iString=IDS_TOOLTIPFONTDEC;
  929.             iStatusMsg=ID_TIPFONTDEC;
  930.             break;
  931.  
  932.         default:
  933.             return NULL;
  934.         }
  935.  
  936.     m_pSH->MessageDisplay(iStatusMsg);
  937.     return String(iString);
  938. }
  939.