home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / ppgpict.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-06-16  |  11.1 KB  |  493 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12.  
  13. #ifdef AFXCTL_PAGE_SEG
  14. #pragma code_seg(AFXCTL_PAGE_SEG)
  15. #endif
  16.  
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21.  
  22. #define new DEBUG_NEW
  23.  
  24. /////////////////////////////////////////////////////////////////////////////
  25. // CPicturePropPage implementation
  26.  
  27. BEGIN_MESSAGE_MAP(CPicturePropPage, CStockPropPage)
  28.     //{{AFX_MSG_MAP(CPicturePropPage)
  29.     ON_CBN_SELCHANGE(AFX_IDC_PROPNAME, OnSelchangePictProp)
  30.     ON_WM_PAINT()
  31.     ON_BN_CLICKED(AFX_IDC_BROWSE, OnBrowse)
  32.     ON_BN_CLICKED(AFX_IDC_CLEAR, OnClear)
  33.     //}}AFX_MSG_MAP
  34. END_MESSAGE_MAP()
  35.  
  36. CPicturePropPage::CPicturePropPage() :
  37.     CStockPropPage(IDD, AFX_IDS_PICTURE_PPG_CAPTION),
  38.     m_pPictDisp(NULL)
  39. {
  40.     //{{AFX_DATA_INIT(CPicturePropPage)
  41.         // NOTE: the ClassWizard will add member initialization here
  42.     //}}AFX_DATA_INIT
  43. }
  44.  
  45. CPicturePropPage::~CPicturePropPage()
  46. {
  47.     // Release picture, if any
  48.  
  49.     if (m_pPictDisp != NULL)
  50.     {
  51.         m_pPictDisp->Release();
  52.         m_pPictDisp = NULL;
  53.     }
  54. }
  55.  
  56. BOOL CPicturePropPage::OnInitDialog()
  57. {
  58.     m_pPictDisp = NULL;
  59.     SetModifiedFlag(FALSE);
  60.     CStockPropPage::OnInitDialog();
  61.     OnObjectsChanged();
  62.     IgnoreApply(AFX_IDC_BROWSE);
  63.     IgnoreApply(AFX_IDC_PROPNAME);
  64.     OnSelchangePictProp();
  65.     return TRUE;
  66. }
  67.  
  68. void CPicturePropPage::DoDataExchange(CDataExchange* pDX)
  69. {
  70.     //{{AFX_DATA_MAP(CPicturePropPage)
  71.     DDX_Control(pDX, AFX_IDC_PROPNAME, m_PropName);
  72.     DDX_Control(pDX, AFX_IDC_PICTURE, m_Static);
  73.     //}}AFX_DATA_MAP
  74.  
  75.     if (pDX->m_bSaveAndValidate)
  76.     {
  77.         if (IsModified())
  78.             if (!SetPictureProp(pDX, m_pPictDisp, m_strPropName))
  79.                 GetPictureProp(pDX, &m_pPictDisp, m_strPropName);
  80.     }
  81.     else
  82.     {
  83.         GetPictureProp(pDX, &m_pPictDisp, m_strPropName);
  84.         SetModifiedFlag(FALSE);
  85.     }
  86. }
  87.  
  88. BOOL CPicturePropPage::SetPictureProp(CDataExchange*, LPPICTUREDISP pPictDisp, LPCTSTR pszPropName)
  89. {
  90.     USES_CONVERSION;
  91.  
  92.     COleDispatchDriver PropDispDriver;
  93.  
  94.     // Set the properties for all the objects
  95.  
  96.     ULONG nObjects;
  97.     LPDISPATCH* ppDisp = GetObjectArray(&nObjects);
  98.     BOOL bSuccess = TRUE;
  99.  
  100.     for (ULONG i = 0; bSuccess && (i < nObjects); i++)
  101.     {
  102.         DISPID dwDispID;
  103.  
  104.         // Get the Dispatch ID for the property and if successful set the value
  105.         LPCOLESTR lpOleStr = T2COLE(pszPropName);
  106.         if (SUCCEEDED(ppDisp[i]->GetIDsOfNames(IID_NULL, (LPOLESTR*)&lpOleStr,
  107.             1, m_lcid, &dwDispID)))
  108.         {
  109.             // Set property
  110.             PropDispDriver.AttachDispatch(ppDisp[i], FALSE);
  111.             TRY
  112.             {
  113.                 PropDispDriver.SetProperty(dwDispID, VT_DISPATCH, pPictDisp);
  114.             }
  115.             CATCH(COleDispatchException, e)
  116.             {
  117.                 // Display message box for dispatch exceptions.
  118.                 e->ReportError(MB_ICONEXCLAMATION | MB_OK);
  119.                 DELETE_EXCEPTION(e);
  120.  
  121.                 bSuccess = FALSE;
  122.             }
  123.             AND_CATCH_ALL(e)
  124.             {
  125.                 // Ignore other exceptions.
  126.                 DELETE_EXCEPTION(e);
  127.             }
  128.             END_CATCH_ALL
  129.             PropDispDriver.DetachDispatch();
  130.         }
  131.     }
  132.     return bSuccess;
  133. }
  134.  
  135. BOOL CPicturePropPage::GetPictureProp(CDataExchange*, LPPICTUREDISP* ppPictDisp, LPCTSTR pszPropName)
  136. {
  137.     USES_CONVERSION;
  138.  
  139.     // Release previous picture, if any.
  140.     if (*ppPictDisp != NULL)
  141.     {
  142.         (*ppPictDisp)->Release();
  143.         *ppPictDisp = NULL;
  144.     }
  145.  
  146.     COleDispatchDriver PropDispDriver;
  147.  
  148.     ULONG nObjects;
  149.     LPDISPATCH* ppDisp = GetObjectArray(&nObjects);
  150.  
  151.     for (ULONG i = 0; i < nObjects; i++)
  152.     {
  153.         DISPID dwDispID;
  154.  
  155.         // Get the Dispatch ID for the property and if successful get the value
  156.         LPCOLESTR lpOleStr = T2COLE(pszPropName);
  157.         if (SUCCEEDED(ppDisp[i]->GetIDsOfNames(IID_NULL, (LPOLESTR*)&lpOleStr,
  158.             1, m_lcid, &dwDispID)))
  159.         {
  160.             // Get property
  161.             LPPICTUREDISP pPictDisp = NULL;
  162.  
  163.             PropDispDriver.AttachDispatch(ppDisp[i], FALSE);
  164.             TRY
  165.                 PropDispDriver.GetProperty(dwDispID, VT_DISPATCH, &pPictDisp);
  166.             END_TRY
  167.             PropDispDriver.DetachDispatch();
  168.  
  169.             // If more than one object, all pictures must be the same.
  170.  
  171.             if ((i != 0) && (pPictDisp != *ppPictDisp))
  172.             {
  173.                 if (*ppPictDisp != NULL)
  174.                     (*ppPictDisp)->Release();
  175.  
  176.                 *ppPictDisp = NULL;
  177.             }
  178.             else
  179.             {
  180.                 *ppPictDisp = pPictDisp;
  181.             }
  182.  
  183.             // Don't keep multiple references to the picture.
  184.  
  185.             if ((i != 0) && (pPictDisp != NULL))
  186.                 pPictDisp->Release();
  187.         }
  188.     }
  189.  
  190.     InvalidateRect(NULL);
  191.     return TRUE;
  192. }
  193.  
  194. /////////////////////////////////////////////////////////////////////////////
  195. // CPicturePropPage message handlers
  196.  
  197. void CPicturePropPage::OnPaint()
  198. {
  199.     CPaintDC dc(this); // device context for painting
  200.  
  201.     // Determine rectangle for drawing picture
  202.  
  203.     CRect rc;
  204.     m_Static.GetWindowRect(&rc);
  205.     rc.InflateRect(-::GetSystemMetrics(SM_CXBORDER) * 2,
  206.         -::GetSystemMetrics(SM_CYBORDER) * 2);
  207.     ScreenToClient(&rc);
  208.  
  209.     LPPICTURE pPict = NULL;
  210.  
  211.     if ((m_pPictDisp != NULL) &&
  212.         SUCCEEDED(m_pPictDisp->QueryInterface(IID_IPicture, (LPVOID*)&pPict)))
  213.     {
  214.         ASSERT(pPict != NULL);
  215.  
  216.         // Draw it
  217.  
  218.         OLE_XSIZE_HIMETRIC hmWidth;
  219.         OLE_YSIZE_HIMETRIC hmHeight;
  220.  
  221.         pPict->get_Width(&hmWidth);
  222.         pPict->get_Height(&hmHeight);
  223.  
  224.         int cxRect = rc.Width();
  225.         int cyRect = rc.Height();
  226.         if ((hmWidth != 0) && (hmHeight != 0) && (cxRect != 0) && (cyRect != 0))
  227.         {
  228.             // Adjust aspect ratio of rectangle to match picture.
  229.  
  230.             int nPictureRatio = hmWidth * 1000 / hmHeight;
  231.             int nRectRatio = cxRect * 1000 / cyRect;
  232.  
  233.             if (nPictureRatio > nRectRatio)
  234.             {
  235.                 int dy = (cyRect - (cxRect * 1000 / nPictureRatio) + 1) / 2;
  236.                 rc.InflateRect(0, -dy);
  237.             }
  238.             else
  239.             {
  240.                 int dx = (cxRect - (cyRect * nPictureRatio / 1000) + 1) / 2;
  241.                 rc.InflateRect(-dx, 0);
  242.             }
  243.         }
  244.  
  245.         pPict->Render(dc.m_hDC, rc.left, rc.top, rc.Width(), rc.Height(),
  246.             0, hmHeight-1, hmWidth, -hmHeight, &rc);
  247.  
  248.         pPict->Release();
  249.     }
  250. }
  251.  
  252. HRESULT _AfxCreateStreamOnFile(LPCTSTR pszPath, LPSTREAM* ppstm,
  253.     LONG* plSize)
  254. {
  255.     ASSERT(pszPath != NULL);
  256.     ASSERT(ppstm != NULL);
  257.  
  258.     *ppstm = NULL;
  259.  
  260.     if (plSize != NULL)
  261.         *plSize = 0;
  262.  
  263.     CFileStatus fstatus;
  264.     CFile file;
  265.     HRESULT hr = E_FAIL;
  266.     LONG cb;
  267.  
  268.     if (file.Open(pszPath, CFile::modeRead) &&
  269.         file.GetStatus(pszPath, fstatus) &&
  270.         ((cb = fstatus.m_size) != -1))
  271.     {
  272.         HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, cb);
  273.         LPVOID pvData = NULL;
  274.  
  275.         if (hGlobal != NULL)
  276.         {
  277.             if ((pvData = GlobalLock(hGlobal)) != NULL)
  278.             {
  279.                 BOOL bRead = (file.ReadHuge(pvData, cb) == (ULONG)cb);
  280.                 GlobalUnlock(hGlobal);
  281.  
  282.                 if (bRead &&
  283.                     SUCCEEDED(hr = CreateStreamOnHGlobal(hGlobal, TRUE, ppstm)))
  284.                 {
  285.                     ASSERT(*ppstm != NULL);
  286.                     if (plSize != NULL)
  287.                         *plSize = fstatus.m_size;
  288.                     hr = S_OK;
  289.                 }
  290.             }
  291.  
  292.             if (FAILED(hr))
  293.                 GlobalFree(hGlobal);
  294.         }
  295.         else
  296.         {
  297.             hr = E_OUTOFMEMORY;
  298.         }
  299.     }
  300.     else
  301.     {
  302.         hr = E_ACCESSDENIED;
  303.     }
  304.  
  305.     return hr;
  306. }
  307.  
  308. void CPicturePropPage::OnBrowse()
  309. {
  310.     CString strFilter;
  311.     strFilter.LoadString(AFX_IDS_PICTUREFILTER);
  312.  
  313.     CString strTitle;
  314.     strTitle.LoadString(AFX_IDS_PICTUREBROWSETITLE);
  315.  
  316.     CFileDialog fdlg(TRUE, NULL, NULL,
  317.             OFN_FILEMUSTEXIST |
  318.             OFN_HIDEREADONLY |
  319.             OFN_PATHMUSTEXIST,
  320.             strFilter);
  321.  
  322.     fdlg.m_ofn.lpstrTitle = strTitle;
  323.  
  324.     int nResult = fdlg.DoModal();
  325.     SetFocus();
  326.  
  327.     if (nResult != IDOK)
  328.         return;
  329.  
  330.     CString strPath = fdlg.GetPathName();
  331.  
  332.     LPSTREAM pstm = NULL;
  333.     LONG lSize;
  334.     HRESULT hr;
  335.  
  336.     if (FAILED(hr = _AfxCreateStreamOnFile(strPath, &pstm, &lSize)))
  337.     {
  338.         UINT idsText;
  339.         CString strText;
  340.         CString strCaption;
  341.  
  342.         switch (GetScode(hr))
  343.         {
  344.         case E_OUTOFMEMORY:
  345.             idsText = AFX_IDP_PICTURETOOLARGE;
  346.             break;
  347.  
  348.         case E_ACCESSDENIED:
  349.             idsText = AFX_IDP_PICTURECANTOPEN;
  350.             break;
  351.  
  352.         default:
  353.             idsText = AFX_IDP_PICTUREREADFAILED;
  354.             break;
  355.         }
  356.  
  357.         AfxFormatString1(strText, idsText, strPath);
  358.         strCaption.LoadString(AFX_IDS_PICTURE_PPG_CAPTION);
  359.         MessageBox(strText, strCaption, MB_OK | MB_ICONEXCLAMATION);
  360.         SetFocus();
  361.         return;
  362.     }
  363.  
  364.     ASSERT(pstm != NULL);
  365.  
  366.     LPPICTURE pPict;
  367.     if (SUCCEEDED(::OleLoadPicture(pstm, lSize, FALSE, IID_IPicture, (LPVOID *)&pPict)))
  368.     {
  369.         ChangePicture(pPict);
  370.     }
  371.     else
  372.     {
  373.         CString strText;
  374.         CString strCaption;
  375.         AfxFormatString1(strText, AFX_IDP_PICTURECANTLOAD, strPath);
  376.         strCaption.LoadString(AFX_IDS_PICTURE_PPG_CAPTION);
  377.         MessageBox(strText, strCaption, MB_OK | MB_ICONEXCLAMATION);
  378.         SetFocus();
  379.     }
  380.  
  381.     pstm->Release();
  382. }
  383.  
  384. AFX_STATIC_DATA PICTDESC _afxPictDescEmpty = { sizeof(PICTDESC), PICTYPE_NONE, };
  385.  
  386. void CPicturePropPage::OnClear()
  387. {
  388.     LPPICTURE pPict;
  389.     if (SUCCEEDED(::OleCreatePictureIndirect(&_afxPictDescEmpty, IID_IPicture, TRUE,
  390.         (LPVOID *)&pPict)))
  391.     {
  392.         ChangePicture(pPict);
  393.     }
  394.     else
  395.     {
  396.         ASSERT(FALSE);  // This should never happen!
  397.     }
  398. }
  399.  
  400. void CPicturePropPage::ChangePicture(LPPICTURE pPict)
  401. {
  402.     ASSERT(pPict != NULL);
  403.  
  404.     LPPICTUREDISP pPictDisp = NULL;
  405.     if (SUCCEEDED(pPict->QueryInterface(IID_IPictureDisp,
  406.             (LPVOID*)&pPictDisp)))
  407.     {
  408.         ASSERT(pPictDisp != NULL);
  409.  
  410.         if (m_pPictDisp != NULL)
  411.             m_pPictDisp->Release();
  412.  
  413.         m_pPictDisp = pPictDisp;
  414.         SetModifiedFlag();
  415.  
  416.         LPPROPERTYPAGESITE pPageSite = GetPageSite();
  417.         if (pPageSite != NULL)
  418.             pPageSite->OnStatusChange(
  419.                 PROPPAGESTATUS_VALIDATE | PROPPAGESTATUS_DIRTY);
  420.  
  421.         InvalidateRect(NULL);
  422.     }
  423.  
  424.     pPict->Release();
  425. }
  426.  
  427. void CPicturePropPage::OnSelchangePictProp()
  428. {
  429.     OnSelchangePropname(m_PropName);
  430.  
  431.     // disable Browse button if no property selected
  432.     CComboBox* pPropName = (CComboBox*)GetDlgItem(AFX_IDC_PROPNAME);
  433.     CWnd* pBrowse = GetDlgItem(AFX_IDC_BROWSE);
  434.     pBrowse->EnableWindow(pPropName->GetCurSel() != CB_ERR);
  435.  
  436.     // redraw bitmap for new picture property
  437.     CRect rect;
  438.  
  439.     m_Static.GetWindowRect(rect);
  440.     rect.InflateRect(-::GetSystemMetrics(SM_CXBORDER),
  441.         -::GetSystemMetrics(SM_CYBORDER));
  442.     ScreenToClient(rect);
  443.  
  444.     InvalidateRect(rect);
  445. }
  446.  
  447. BOOL CPicturePropPage::OnEditProperty(DISPID dispid)
  448. {
  449.     return CStockPropPage::OnEditProperty(dispid, m_PropName);
  450. }
  451.  
  452. void CPicturePropPage::OnObjectsChanged()
  453. {
  454.     ULONG nObjects;
  455.     if (GetObjectArray(&nObjects) != NULL && m_hWnd != NULL)
  456.         FillPropnameList(IID_IPictureDisp, 1, m_PropName);
  457.  
  458.     if (m_hWnd != NULL)
  459.         OnSelchangePictProp();
  460. }
  461.  
  462. /////////////////////////////////////////////////////////////////////////////
  463. // Class factory for Picture property page
  464.  
  465. #ifdef _AFXDLL
  466.  
  467. #ifdef AFXCTL_FACT_SEG
  468. #pragma code_seg(AFXCTL_FACT_SEG)
  469. #endif
  470.  
  471. IMPLEMENT_OLECREATE_EX(CPicturePropPage, "OCxx.CPicturePropPage",
  472.     0x0be35202,0x8f91,0x11ce,0x9d,0xe3,0x00,0xaa,0x00,0x4b,0xb8,0x51)
  473.  
  474. BOOL CPicturePropPage::CPicturePropPageFactory::UpdateRegistry(BOOL bRegister)
  475. {
  476.     if (bRegister)
  477.         return AfxOleRegisterPropertyPageClass(AfxGetInstanceHandle(),
  478.             m_clsid, AFX_IDS_PICTURE_PPG);
  479.     else
  480.         return AfxOleUnregisterClass(m_clsid, NULL);
  481. }
  482.  
  483. #endif //_AFXDLL
  484.  
  485. /////////////////////////////////////////////////////////////////////////////
  486. // Force any extra compiler-generated code into AFX_INIT_SEG
  487.  
  488. #ifdef AFX_INIT_SEG
  489. #pragma code_seg(AFX_INIT_SEG)
  490. #endif
  491.  
  492. IMPLEMENT_DYNCREATE(CPicturePropPage, CStockPropPage)
  493.