home *** CD-ROM | disk | FTP | other *** search
/ Supercompiler 1997 / SUPERCOMPILER97.iso / MS_VC.50 / VC / MFC / SRC / CTLPROP.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-30  |  36.5 KB  |  1,572 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1997 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_PROP_SEG
  14. #pragma code_seg(AFXCTL_PROP_SEG)
  15. #endif
  16.  
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21.  
  22. #ifndef _DEBUG
  23. #pragma intrinsic(memset)
  24. #endif
  25.  
  26. #define new DEBUG_NEW
  27.  
  28. /////////////////////////////////////////////////////////////////////////////
  29. // Stock property mask
  30.  
  31. #define STOCKPROP_BACKCOLOR     0x00000001
  32. #define STOCKPROP_CAPTION       0x00000002
  33. #define STOCKPROP_FONT          0x00000004
  34. #define STOCKPROP_FORECOLOR     0x00000008
  35. #define STOCKPROP_TEXT          0x00000010
  36. #define STOCKPROP_BORDERSTYLE   0x00000020
  37. #define STOCKPROP_ENABLED       0x00000040
  38. #define STOCKPROP_APPEARANCE    0x00000080
  39.  
  40. void COleControl::InitStockPropMask()
  41. {
  42.     static const DWORD _dwStockFlags[] =
  43.     {
  44.         STOCKPROP_BACKCOLOR,    // -501
  45.         0,                      // -502
  46.         0,                      // -503
  47.         STOCKPROP_BORDERSTYLE,  // -504
  48.         0,                      // -505
  49.         0,                      // -506
  50.         0,                      // -507
  51.         0,                      // -508
  52.         0,                      // -509
  53.         0,                      // -510
  54.         0,                      // -511
  55.         STOCKPROP_FONT,         // -512
  56.         STOCKPROP_FORECOLOR,    // -513
  57.         STOCKPROP_ENABLED,      // -514
  58.         0,                      // -515
  59.         0,                      // -516
  60.         STOCKPROP_TEXT,         // -517
  61.         STOCKPROP_CAPTION,      // -518
  62.         0,                      // -519
  63.         STOCKPROP_APPEARANCE,   // -520
  64.     };
  65.  
  66.     const AFX_DISPMAP* pDispMap = GetDispatchMap();
  67.     const AFX_DISPMAP_ENTRY* pEntry;
  68.     ASSERT(pDispMap != NULL);
  69.  
  70.     // If stock property mask is already initialized, we're outta here.
  71.     if (*pDispMap->lpStockPropMask != (DWORD)-1)
  72.         return;
  73.  
  74.     AfxLockGlobals(CRIT_STOCKMASK);
  75.  
  76.     if (*pDispMap->lpStockPropMask == (DWORD)-1)
  77.     {
  78.         const AFX_DISPMAP* pDispMapTop = pDispMap;
  79.         DWORD dwStockPropMask = 0;
  80.  
  81.         while (pDispMap != NULL)
  82.         {
  83.             pEntry = pDispMap->lpEntries;
  84.             while (pEntry->nPropOffset != -1)
  85.             {
  86.                 int nIndex = DISPID_BACKCOLOR - pEntry->lDispID;
  87.                 DWORD dwFlag;
  88.                 if (nIndex >= 0 && nIndex < _countof(_dwStockFlags) &&
  89.                     (dwFlag = _dwStockFlags[nIndex]) != 0)
  90.                 {
  91.                     dwStockPropMask |= dwFlag;
  92.                 }
  93.  
  94.                 ++pEntry;
  95.             }
  96.             // check base class
  97. #ifdef _AFXDLL
  98.             pDispMap = (*pDispMap->pfnGetBaseMap)();
  99. #else
  100.             pDispMap = pDispMap->pBaseMap;
  101. #endif
  102.         }
  103.  
  104.         *pDispMapTop->lpStockPropMask = dwStockPropMask;
  105.     }
  106.  
  107.     AfxUnlockGlobals(CRIT_STOCKMASK);
  108. }
  109.  
  110. static void ToggleBorderStyle(CWnd* pWnd)
  111. {
  112.     if (pWnd->m_hWnd != NULL)
  113.     {
  114.         // toggle border style and force redraw of border
  115.         ::SetWindowLong(pWnd->m_hWnd, GWL_STYLE, pWnd->GetStyle() ^ WS_BORDER);
  116.         ::SetWindowPos(pWnd->m_hWnd, NULL, 0, 0, 0, 0,
  117.             SWP_DRAWFRAME | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
  118.     }
  119. }
  120.  
  121. static void ToggleAppearance(CWnd* pWnd)
  122. {
  123.     if (pWnd->m_hWnd != NULL)
  124.     {
  125.         // toggle border style and force redraw of border
  126.         ::SetWindowLong(pWnd->m_hWnd, GWL_EXSTYLE, pWnd->GetExStyle() ^
  127.             WS_EX_CLIENTEDGE);
  128.         ::SetWindowPos(pWnd->m_hWnd, NULL, 0, 0, 0, 0,
  129.             SWP_DRAWFRAME | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
  130.     }
  131. }
  132.  
  133. /////////////////////////////////////////////////////////////////////////////
  134. // Property exchange for stock properties
  135.  
  136. void COleControl::ExchangeStockProps(CPropExchange* pPX)
  137. {
  138.     BOOL bLoading = pPX->IsLoading();
  139.     DWORD dwStockPropMask = GetStockPropMask();
  140.     DWORD dwPersistMask = dwStockPropMask;
  141.  
  142.     PX_ULong(pPX, _T("_StockProps"), dwPersistMask);
  143.  
  144.     if (dwStockPropMask & (STOCKPROP_CAPTION | STOCKPROP_TEXT))
  145.     {
  146.         CString strText;
  147.  
  148.         if (dwPersistMask & (STOCKPROP_CAPTION | STOCKPROP_TEXT))
  149.         {
  150.             if (!bLoading)
  151.                 strText = InternalGetText();
  152.             if (dwStockPropMask & STOCKPROP_CAPTION)
  153.                 PX_String(pPX, _T("Caption"), strText, _T(""));
  154.             if (dwStockPropMask & STOCKPROP_TEXT)
  155.                 PX_String(pPX, _T("Text"), strText, _T(""));
  156.         }
  157.         if (bLoading)
  158.         {
  159.             TRY
  160.                 SetText(strText);
  161.             END_TRY
  162.         }
  163.     }
  164.  
  165.     if (dwStockPropMask & STOCKPROP_FORECOLOR)
  166.     {
  167.         if (dwPersistMask & STOCKPROP_FORECOLOR)
  168.             PX_Color(pPX, _T("ForeColor"), m_clrForeColor, AmbientForeColor());
  169.         else if (bLoading)
  170.             m_clrForeColor = AmbientForeColor();
  171.     }
  172.  
  173.     if (dwStockPropMask & STOCKPROP_BACKCOLOR)
  174.     {
  175.         if (dwPersistMask & STOCKPROP_BACKCOLOR)
  176.             PX_Color(pPX, _T("BackColor"), m_clrBackColor, AmbientBackColor());
  177.         else if (bLoading)
  178.             m_clrBackColor = AmbientBackColor();
  179.     }
  180.  
  181.     if (dwStockPropMask & STOCKPROP_FONT)
  182.     {
  183.         LPFONTDISP pFontDispAmbient = AmbientFont();
  184.         BOOL bChanged = TRUE;
  185.  
  186.         if (dwPersistMask & STOCKPROP_FONT)
  187.             bChanged = PX_Font(pPX, _T("Font"), m_font, NULL, pFontDispAmbient);
  188.         else if (bLoading)
  189.             m_font.InitializeFont(NULL, pFontDispAmbient);
  190.  
  191.         if (bLoading && bChanged)
  192.             OnFontChanged();
  193.  
  194.         RELEASE(pFontDispAmbient);
  195.     }
  196.  
  197.     if (dwStockPropMask & STOCKPROP_BORDERSTYLE)
  198.     {
  199.         short sBorderStyle = m_sBorderStyle;
  200.  
  201.         if (dwPersistMask & STOCKPROP_BORDERSTYLE)
  202.             PX_Short(pPX, _T("BorderStyle"), m_sBorderStyle, 0);
  203.         else if (bLoading)
  204.             m_sBorderStyle = 0;
  205.  
  206.         if (sBorderStyle != m_sBorderStyle)
  207.             ToggleBorderStyle(this);
  208.     }
  209.  
  210.     if (dwStockPropMask & STOCKPROP_ENABLED)
  211.     {
  212.         BOOL bEnabled = m_bEnabled;
  213.  
  214.         if (dwPersistMask & STOCKPROP_ENABLED)
  215.             PX_Bool(pPX, _T("Enabled"), m_bEnabled, TRUE);
  216.         else if (bLoading)
  217.             m_bEnabled = TRUE;
  218.  
  219.         if ((bEnabled != m_bEnabled) && (m_hWnd != NULL))
  220.             ::EnableWindow(m_hWnd, m_bEnabled);
  221.     }
  222.  
  223.     if (dwStockPropMask & STOCKPROP_APPEARANCE)
  224.     {
  225.         short sAppearance = m_sAppearance;
  226.  
  227.         if (dwPersistMask & STOCKPROP_APPEARANCE)
  228.             PX_Short(pPX, _T("Appearance"), m_sAppearance, 0);
  229.         else if (bLoading)
  230.             m_sAppearance = AmbientAppearance();
  231.  
  232.         if (sAppearance != m_sAppearance)
  233.             ToggleAppearance(this);
  234.     }
  235. }
  236.  
  237. /////////////////////////////////////////////////////////////////////////////
  238. // Serialization for stock properties
  239.  
  240. void COleControl::SerializeStockProps(CArchive& ar)
  241. {
  242.     BOOL bLoading = ar.IsLoading();
  243.     DWORD dwStockPropMask = GetStockPropMask();
  244.     DWORD dwPersistMask = dwStockPropMask;
  245.  
  246.     if (bLoading)
  247.     {
  248.         ar >> dwPersistMask;
  249.  
  250.         if (dwStockPropMask & (STOCKPROP_CAPTION | STOCKPROP_TEXT))
  251.         {
  252.             if (dwPersistMask & (STOCKPROP_CAPTION | STOCKPROP_TEXT))
  253.             {
  254.                 CString strText;
  255.                 ar >> strText;
  256.                 TRY
  257.                     SetText(strText);
  258.                 END_TRY
  259.             }
  260.             else
  261.             {
  262.                 TRY
  263.                     SetText(_T(""));
  264.                 END_TRY
  265.             }
  266.         }
  267.  
  268.         if (dwStockPropMask & STOCKPROP_FORECOLOR)
  269.         {
  270.             if (dwPersistMask & STOCKPROP_FORECOLOR)
  271.                 ar >> m_clrForeColor;
  272.             else
  273.                 m_clrForeColor = AmbientForeColor();
  274.         }
  275.  
  276.         if (dwStockPropMask & STOCKPROP_BACKCOLOR)
  277.         {
  278.             if (dwPersistMask & STOCKPROP_BACKCOLOR)
  279.                 ar >> m_clrBackColor;
  280.             else
  281.                 m_clrBackColor = AmbientBackColor();
  282.         }
  283.  
  284.         if (dwStockPropMask & STOCKPROP_FONT)
  285.         {
  286.             BOOL bRead = FALSE;
  287.  
  288.             if (dwPersistMask & STOCKPROP_FONT)
  289.             {
  290.                 BYTE bFlag;
  291.                 ar >> bFlag;
  292.                 if (bFlag != 0xFF)
  293.                 {
  294.                     CArchiveStream stm(&ar);
  295.                     LPSTREAM pstm = _AfxGetArchiveStream(ar, stm);
  296.                     LPFONT pFont = _AfxCreateFontFromStream(pstm);
  297.                     if (pFont != NULL)
  298.                     {
  299.                         m_font.SetFont(pFont);
  300.                         bRead = TRUE;
  301.                     }
  302.                 }
  303.             }
  304.  
  305.             if (! bRead)
  306.             {
  307.                 LPFONTDISP pFontDispAmbient = AmbientFont();
  308.                 m_font.InitializeFont(NULL, pFontDispAmbient);
  309.                 RELEASE(pFontDispAmbient);
  310.             }
  311.  
  312.             OnFontChanged();
  313.         }
  314.  
  315.         if (dwStockPropMask & STOCKPROP_BORDERSTYLE)
  316.         {
  317.             if (dwPersistMask & STOCKPROP_BORDERSTYLE)
  318.             {
  319.                 short sBorderStyle = m_sBorderStyle;
  320.                 ar >> m_sBorderStyle;
  321.                 if (sBorderStyle != m_sBorderStyle)
  322.                     ToggleBorderStyle(this);
  323.             }
  324.             else
  325.             {
  326.                 m_sBorderStyle = 0;
  327.             }
  328.         }
  329.  
  330.         if (dwStockPropMask & STOCKPROP_ENABLED)
  331.         {
  332.             if (dwPersistMask & STOCKPROP_ENABLED)
  333.             {
  334.                 BOOL bEnabled = m_bEnabled;
  335.                 ar >> m_bEnabled;
  336.                 if ((bEnabled != m_bEnabled) && (m_hWnd != NULL))
  337.                     ::EnableWindow(m_hWnd, m_bEnabled);
  338.             }
  339.             else
  340.             {
  341.                 m_bEnabled = TRUE;
  342.             }
  343.         }
  344.  
  345.         if (dwStockPropMask & STOCKPROP_APPEARANCE)
  346.         {
  347.             if (dwPersistMask & STOCKPROP_APPEARANCE)
  348.             {
  349.                 short sAppearance = m_sAppearance;
  350.                 ar >> m_sAppearance;
  351.  
  352.                 if (sAppearance != m_sAppearance)
  353.                     ToggleAppearance(this);
  354.             }
  355.             else
  356.             {
  357.                 m_sAppearance = AmbientAppearance();
  358.             }
  359.         }
  360.     }
  361.     else
  362.     {
  363.         ar << dwPersistMask;
  364.  
  365.         if (dwStockPropMask & (STOCKPROP_CAPTION | STOCKPROP_TEXT))
  366.             ar << m_strText;
  367.  
  368.         if (dwStockPropMask & STOCKPROP_FORECOLOR)
  369.             ar << m_clrForeColor;
  370.  
  371.         if (dwStockPropMask & STOCKPROP_BACKCOLOR)
  372.             ar << m_clrBackColor;
  373.  
  374.         if (dwStockPropMask & STOCKPROP_FONT)
  375.         {
  376.             BOOL bWrite = FALSE;
  377.             LPFONT pFont = m_font.m_pFont;
  378.             if (pFont != NULL)
  379.             {
  380.                 // If same as ambient font (or error), write 0xFF for the flag
  381.                 LPFONTDISP pFontDispAmbient = AmbientFont();
  382.                 if (!_AfxIsSameFont(m_font, NULL, pFontDispAmbient))
  383.                 {
  384.                     LPPERSISTSTREAM pps = NULL;
  385.                     if (SUCCEEDED(pFont->QueryInterface(IID_IPersistStream,
  386.                         (LPVOID*)&pps)))
  387.                     {
  388.                         ASSERT_POINTER(pps, IPersistStream);
  389.                         ar << (BYTE)0x00;
  390.                         CArchiveStream stm(&ar);
  391.                         LPSTREAM pstm = _AfxGetArchiveStream(ar, stm);
  392.                         bWrite = SUCCEEDED(::OleSaveToStream(pps, pstm));
  393.                         pps->Release();
  394.                         if (!bWrite)
  395.                             AfxThrowArchiveException(CArchiveException::generic);
  396.                     }
  397.                 }
  398.                 RELEASE(pFontDispAmbient);
  399.             }
  400.             if (! bWrite)
  401.             {
  402.                 ar << (BYTE)0xFF;
  403.             }
  404.         }
  405.  
  406.         if (dwStockPropMask & STOCKPROP_BORDERSTYLE)
  407.             ar << m_sBorderStyle;
  408.  
  409.         if (dwStockPropMask & STOCKPROP_ENABLED)
  410.             ar << m_bEnabled;
  411.  
  412.         if (dwStockPropMask & STOCKPROP_APPEARANCE)
  413.             ar << m_sAppearance;
  414.     }
  415. }
  416.  
  417. /////////////////////////////////////////////////////////////////////////////
  418. // Initialization for stock properties
  419.  
  420. void COleControl::ResetStockProps()
  421. {
  422.     DWORD dwStockPropMask = GetStockPropMask();
  423.  
  424.     if (dwStockPropMask & (STOCKPROP_CAPTION | STOCKPROP_TEXT))
  425.     {
  426.         TRY
  427.             SetText(_T(""));
  428.         END_TRY
  429.     }
  430.  
  431.     if (dwStockPropMask & STOCKPROP_FORECOLOR)
  432.         m_clrForeColor = AmbientForeColor();
  433.  
  434.     if (dwStockPropMask & STOCKPROP_BACKCOLOR)
  435.         m_clrBackColor = AmbientBackColor();
  436.  
  437.     if (dwStockPropMask & STOCKPROP_FONT)
  438.     {
  439.         LPFONTDISP pFontDispAmbient = AmbientFont();
  440.         m_font.InitializeFont(NULL, pFontDispAmbient);
  441.         RELEASE(pFontDispAmbient);
  442.         OnFontChanged();
  443.     }
  444.  
  445.     if (dwStockPropMask & STOCKPROP_BORDERSTYLE)
  446.         m_sBorderStyle = 0;
  447.  
  448.     if (dwStockPropMask & STOCKPROP_ENABLED)
  449.         m_bEnabled = TRUE;
  450.  
  451.     if (dwStockPropMask & STOCKPROP_APPEARANCE)
  452.         m_sAppearance = AmbientAppearance();
  453. }
  454.  
  455. /////////////////////////////////////////////////////////////////////////////
  456. // Appearance property
  457.  
  458. short COleControl::GetAppearance()
  459. {
  460.     return m_sAppearance;
  461. }
  462.  
  463. void COleControl::SetAppearance(short sAppearance)
  464. {
  465.     if (sAppearance != 0 && sAppearance != 1)
  466.         ThrowError(CTL_E_INVALIDPROPERTYVALUE, AFX_IDP_E_INVALIDPROPERTYVALUE);
  467.  
  468.     // Is the property changing?
  469.     if (m_sAppearance == sAppearance)
  470.         return;
  471.  
  472.     if (!BoundPropertyRequestEdit(DISPID_APPEARANCE))
  473.         SetNotPermitted();
  474.  
  475.     ASSERT((m_hWnd == NULL) ||
  476.         ((GetExStyle() & WS_EX_CLIENTEDGE) == (DWORD)(m_sAppearance ?
  477.             WS_EX_CLIENTEDGE : 0)));
  478.  
  479.     m_sAppearance = sAppearance;
  480.     m_bModified = TRUE;
  481.  
  482.     ToggleAppearance(this);
  483.     OnAppearanceChanged();
  484.  
  485.     BoundPropertyChanged(DISPID_APPEARANCE);
  486. }
  487.  
  488. void COleControl::OnAppearanceChanged()
  489. {
  490.     // Can be overridden by subclass
  491.  
  492.     InvalidateControl();
  493. }
  494.  
  495. /////////////////////////////////////////////////////////////////////////////
  496. // BackColor property
  497.  
  498. OLE_COLOR COleControl::GetBackColor()
  499. {
  500.     return m_clrBackColor;
  501. }
  502.  
  503. void COleControl::SetBackColor(OLE_COLOR clrBackColor)
  504. {
  505.     // Is the property changing?
  506.     if (m_clrBackColor == clrBackColor)
  507.         return;
  508.  
  509.     if (FAILED(_AfxOleTranslateColor(clrBackColor, NULL, NULL)))
  510.         ThrowError(CTL_E_INVALIDPROPERTYVALUE, AFX_IDP_E_INVALIDPROPERTYVALUE);
  511.  
  512.     if (!BoundPropertyRequestEdit(DISPID_BACKCOLOR))
  513.         SetNotPermitted();
  514.  
  515.     m_clrBackColor = clrBackColor;
  516.     m_bModified = TRUE;
  517.     OnBackColorChanged();
  518.  
  519.     BoundPropertyChanged(DISPID_BACKCOLOR);
  520. }
  521.  
  522. void COleControl::OnBackColorChanged()
  523. {
  524.     // Can be overridden by subclass
  525.     InvalidateControl();
  526. }
  527.  
  528. /////////////////////////////////////////////////////////////////////////////
  529. // BorderStyle property
  530.  
  531. short COleControl::GetBorderStyle()
  532. {
  533.     return m_sBorderStyle;
  534. }
  535.  
  536. void COleControl::SetBorderStyle(short sBorderStyle)
  537. {
  538.     if (sBorderStyle != 0 && sBorderStyle != 1)
  539.         ThrowError(CTL_E_INVALIDPROPERTYVALUE, AFX_IDP_E_INVALIDPROPERTYVALUE);
  540.  
  541.     // Is the property changing?
  542.     if (m_sBorderStyle == sBorderStyle)
  543.         return;
  544.  
  545.     if (!BoundPropertyRequestEdit(DISPID_BORDERSTYLE))
  546.         SetNotPermitted();
  547.  
  548.     ASSERT((m_hWnd == NULL) ||
  549.         ((GetStyle() & WS_BORDER) == (DWORD)(m_sBorderStyle ? WS_BORDER : 0)));
  550.  
  551.     m_sBorderStyle = sBorderStyle;
  552.     m_bModified = TRUE;
  553.  
  554.     ToggleBorderStyle(this);
  555.     OnBorderStyleChanged();
  556.  
  557.     BoundPropertyChanged(DISPID_BORDERSTYLE);
  558. }
  559.  
  560. void COleControl::OnBorderStyleChanged()
  561. {
  562.     // Can be overridden by subclass
  563.  
  564.     InvalidateControl();
  565. }
  566.  
  567. /////////////////////////////////////////////////////////////////////////////
  568. // Text and Caption properties
  569.  
  570. const CString& COleControl::InternalGetText()
  571. {
  572.     // Some subclassed controls (such as edit controls and comboboxes) change
  573.     // the window text without sending WM_SETTEXT. Therefore, we need to
  574.     // ensure that m_strText is up-to-date.
  575.  
  576.     if (m_hWnd != NULL && IsSubclassedControl())
  577.     {
  578.         // Usually, the window text will be shorter than 32 characters.
  579.         // When it is, we can be more efficient.
  580.  
  581.         static const int _cchUsual = 32;
  582.  
  583.         if (DefWindowProc(WM_GETTEXT, (WPARAM)_cchUsual,
  584.             (LPARAM)m_strText.GetBufferSetLength(_cchUsual)) >= _cchUsual - 1)
  585.         {
  586.             // Text was too long: allocate a bigger buffer.
  587.  
  588.             int nLen = DefWindowProc(WM_GETTEXTLENGTH, (WPARAM)0, (LPARAM)0) + 1;
  589.             DefWindowProc(WM_GETTEXT, (WPARAM)nLen,
  590.                 (LPARAM)m_strText.GetBufferSetLength(nLen));
  591.         }
  592.         m_strText.ReleaseBuffer();
  593.     }
  594.  
  595.     return m_strText;
  596. }
  597.  
  598. BSTR COleControl::GetText()
  599. {
  600.     return ((CString&)InternalGetText()).AllocSysString();
  601. }
  602.  
  603. void COleControl::SetText(LPCTSTR pszText)
  604. {
  605.     LRESULT lResult;
  606.     if (m_hWnd != NULL)
  607.         lResult = SendMessage(WM_SETTEXT, 0, (LPARAM)pszText);
  608.     else
  609.         lResult = OnSetText(0, (LPARAM)pszText);
  610.  
  611.     if (lResult == -1)
  612.         SetNotPermitted();
  613. }
  614.  
  615. LRESULT COleControl::OnSetText(WPARAM wParam, LPARAM lParam)
  616. {
  617.     ASSERT(lParam == 0 || AfxIsValidString((LPCTSTR)lParam));
  618.  
  619.     // Is the property changing?
  620.     if ((lParam == 0 && InternalGetText().IsEmpty()) ||
  621.         (lParam != 0 && m_strText == (LPCTSTR)lParam))
  622.         return 0;
  623.  
  624.     DWORD dwStockPropMask = GetStockPropMask();
  625.  
  626.     if (dwStockPropMask & STOCKPROP_CAPTION)
  627.         if (!BoundPropertyRequestEdit(DISPID_CAPTION))
  628.             return -1;
  629.  
  630.     if (dwStockPropMask & STOCKPROP_TEXT)
  631.         if (!BoundPropertyRequestEdit(DISPID_TEXT))
  632.             return -1;
  633.  
  634.     LRESULT lResult = 0;
  635.     m_strText = (LPCTSTR)lParam;
  636.     m_bModified = TRUE;
  637.  
  638.     if (m_hWnd != NULL)
  639.         lResult = DefWindowProc(WM_SETTEXT, wParam, lParam);
  640.  
  641.     OnTextChanged();
  642.  
  643.     if (dwStockPropMask & STOCKPROP_CAPTION)
  644.         BoundPropertyChanged(DISPID_CAPTION);
  645.  
  646.     if (dwStockPropMask & STOCKPROP_TEXT)
  647.         BoundPropertyChanged(DISPID_TEXT);
  648.  
  649.     return lResult;
  650. }
  651.  
  652. void COleControl::OnTextChanged()
  653. {
  654.     // Can be overridden by subclass
  655.     InvalidateControl();
  656. }
  657.  
  658. /////////////////////////////////////////////////////////////////////////////
  659. // Enabled property
  660.  
  661. BOOL COleControl::GetEnabled()
  662. {
  663.     return m_bEnabled;
  664. }
  665.  
  666. void COleControl::SetEnabled(BOOL bEnabled)
  667. {
  668.     // Is the property changing?
  669.     if (m_bEnabled == bEnabled)
  670.         return;
  671.  
  672.     if (!BoundPropertyRequestEdit(DISPID_ENABLED))
  673.         SetNotPermitted();
  674.  
  675.     m_bEnabled = bEnabled;
  676.     m_bModified = TRUE;
  677.     if (m_hWnd != NULL)
  678.         ::EnableWindow(m_hWnd, m_bEnabled);
  679.  
  680.     // If the control is UI Active and the Enabled property changed to FALSE,
  681.     // then UI Deactivate the control.
  682.  
  683.     if (m_bUIActive && !bEnabled)
  684.         m_xOleInPlaceObject.UIDeactivate();
  685.  
  686.     OnEnabledChanged();
  687.  
  688.     BoundPropertyChanged(DISPID_ENABLED);
  689. }
  690.  
  691. void COleControl::OnEnabledChanged()
  692. {
  693.     // Can be overridden by subclass
  694.     InvalidateControl();
  695. }
  696.  
  697. /////////////////////////////////////////////////////////////////////////////
  698. // Font property
  699.  
  700. CFontHolder& COleControl::InternalGetFont()
  701. {
  702.     return m_font;
  703. }
  704.  
  705. LPFONTDISP COleControl::GetFont()
  706. {
  707.     return m_font.GetFontDispatch();
  708. }
  709.  
  710. void COleControl::SetFont(LPFONTDISP pFontDisp)
  711. {
  712.     ASSERT((pFontDisp == NULL) ||
  713.            AfxIsValidAddress(pFontDisp, sizeof(IDispatch), FALSE));
  714.  
  715.     m_font.InitializeFont(NULL, pFontDisp);
  716.     m_bModified = TRUE;
  717.     OnFontChanged();
  718.  
  719.     BoundPropertyChanged(DISPID_FONT);
  720. }
  721.  
  722. void COleControl::OnFontChanged()
  723. {
  724.     // Can be overridden by subclass
  725.  
  726.     // Send WM_SETFONT to control's window
  727.     if ((m_hWnd != NULL) &&
  728.         (GetStockPropMask() & STOCKPROP_FONT) &&
  729.         IsSubclassedControl())
  730.     {
  731.         HFONT hFontPrev = (HFONT)SendMessage(WM_GETFONT, 0, 0);
  732.  
  733.         CFontHolder& font = InternalGetFont();
  734.  
  735.         if (font.m_pFont != NULL)
  736.         {
  737.             HFONT hFont = font.GetFontHandle();
  738.             font.m_pFont->AddRefHfont(hFont);
  739.             SendMessage(WM_SETFONT, (WPARAM)hFont, 0);
  740.  
  741.             if (m_hFontPrev != NULL)
  742.             {
  743.                 ASSERT(hFontPrev == m_hFontPrev);
  744.                 font.m_pFont->ReleaseHfont(hFontPrev);
  745.             }
  746.             m_hFontPrev = hFont;
  747.         }
  748.         else
  749.         {
  750.             SendMessage(WM_SETFONT, NULL, 0);
  751.             m_hFontPrev = NULL;
  752.         }
  753.     }
  754.  
  755.     // Invalidate the control
  756.     InvalidateControl();
  757. }
  758.  
  759. /////////////////////////////////////////////////////////////////////////////
  760. // ForeColor property
  761.  
  762. OLE_COLOR COleControl::GetForeColor()
  763. {
  764.     return m_clrForeColor;
  765. }
  766.  
  767. void COleControl::SetForeColor(OLE_COLOR clrForeColor)
  768. {
  769.     // Is the property changing?
  770.     if (m_clrForeColor == clrForeColor)
  771.         return;
  772.  
  773.     if (FAILED(_AfxOleTranslateColor(clrForeColor, NULL, NULL)))
  774.         ThrowError(CTL_E_INVALIDPROPERTYVALUE, AFX_IDP_E_INVALIDPROPERTYVALUE);
  775.  
  776.     if (!BoundPropertyRequestEdit(DISPID_FORECOLOR))
  777.         SetNotPermitted();
  778.  
  779.     m_clrForeColor = clrForeColor;
  780.     m_bModified = TRUE;
  781.     OnForeColorChanged();
  782.  
  783.     BoundPropertyChanged(DISPID_FORECOLOR);
  784. }
  785.  
  786. void COleControl::OnForeColorChanged()
  787. {
  788.     // Can be overridden by subclass
  789.     InvalidateControl();
  790. }
  791.  
  792. /////////////////////////////////////////////////////////////////////////////
  793. // hWnd property
  794.  
  795. OLE_HANDLE COleControl::GetHwnd()
  796. {
  797.     return (OLE_HANDLE)((m_bInPlaceActive || m_bOpen) ? m_hWnd : NULL);
  798. }
  799.  
  800. /////////////////////////////////////////////////////////////////////////////
  801. // ReadyState property
  802.  
  803. long COleControl::GetReadyState()
  804. {
  805.     return m_lReadyState;
  806. }
  807.  
  808. ////////////////////////////////////////////////////////////////////////////
  809. // COleControl::XFontNotification
  810.  
  811. STDMETHODIMP_(ULONG) COleControl::XFontNotification::AddRef()
  812. {
  813.     return 1;
  814. }
  815.  
  816. STDMETHODIMP_(ULONG) COleControl::XFontNotification::Release()
  817. {
  818.     return 0;
  819. }
  820.  
  821. STDMETHODIMP COleControl::XFontNotification::QueryInterface(
  822.     REFIID iid, LPVOID* ppvObj)
  823. {
  824.     ASSERT(ppvObj != NULL);
  825.  
  826.     if (IsEqualIID(iid, IID_IUnknown) ||
  827.         IsEqualIID(iid, IID_IPropertyNotifySink))
  828.     {
  829.         *ppvObj = this;
  830.         return S_OK;
  831.     }
  832.  
  833.     return E_NOINTERFACE;
  834. }
  835.  
  836. STDMETHODIMP COleControl::XFontNotification::OnChanged(DISPID)
  837. {
  838.     METHOD_PROLOGUE_EX(COleControl, FontNotification)
  839.     pThis->OnFontChanged();
  840.     pThis->m_bModified = TRUE;
  841.     pThis->BoundPropertyChanged(DISPID_FONT);
  842.     return S_OK;
  843. }
  844.  
  845. STDMETHODIMP COleControl::XFontNotification::OnRequestEdit(DISPID)
  846. {
  847.     return S_OK;
  848. }
  849.  
  850. CFont* COleControl::SelectStockFont(CDC* pDC)
  851. {
  852.     return SelectFontObject(pDC, m_font);
  853. }
  854.  
  855. CFont* COleControl::SelectFontObject(CDC* pDC, CFontHolder& fontHolder)
  856. {
  857.     return fontHolder.Select(pDC, m_rcBounds.Height(), m_cyExtent);
  858. }
  859.  
  860. void COleControl::GetStockTextMetrics(LPTEXTMETRIC lptm)
  861. {
  862.     m_font.QueryTextMetrics(lptm);
  863. }
  864.  
  865. void COleControl::GetFontTextMetrics(LPTEXTMETRIC lptm, CFontHolder& fontHolder)
  866. {
  867.     fontHolder.QueryTextMetrics(lptm);
  868. }
  869.  
  870. /////////////////////////////////////////////////////////////////////////////
  871. // Ambient property access
  872.  
  873. BOOL AFXAPI _GetI4Property(LPDISPATCH pDispatch, DISPID dwDispID, DWORD* pdwResult)
  874. {
  875.     if (pDispatch == NULL)
  876.         return FALSE;
  877.  
  878.     DISPPARAMS dispparams;
  879.     memset(&dispparams, 0, sizeof dispparams);
  880.  
  881.     VARIANT vaResult;
  882.     AfxVariantInit(&vaResult);
  883.  
  884.     EXCEPINFO excepInfo;
  885.     memset(&excepInfo, 0, sizeof excepInfo);
  886.  
  887.     UINT nArgErr = (UINT)-1;  // initialize to invalid arg
  888.  
  889.     HRESULT hr = pDispatch->Invoke(dwDispID, IID_NULL, 0, DISPATCH_PROPERTYGET,
  890.         &dispparams, &vaResult, &excepInfo, &nArgErr);
  891.  
  892.     if (SUCCEEDED(hr))
  893.     {
  894.         if ((V_VT(&vaResult) == VT_I4) ||
  895.             SUCCEEDED(VariantChangeType(&vaResult, &vaResult, 0, VT_I4)))
  896.         {
  897.             *pdwResult = V_I4(&vaResult);
  898.             return TRUE;
  899.         }
  900.     }
  901.  
  902.     VariantClear(&vaResult);
  903.  
  904.     if (excepInfo.bstrSource != NULL)
  905.         SysFreeString(excepInfo.bstrSource);
  906.     if (excepInfo.bstrDescription != NULL)
  907.         SysFreeString(excepInfo.bstrDescription);
  908.     if (excepInfo.bstrHelpFile != NULL)
  909.         SysFreeString(excepInfo.bstrHelpFile);
  910.  
  911.     return FALSE;
  912. }
  913.  
  914. COleDispatchDriver* COleControl::GetAmbientDispatchDriver()
  915. {
  916.     if (m_ambientDispDriver.m_lpDispatch == NULL)
  917.     {
  918.         // Initialize pointer to ambient property dispinterface.
  919.         IDispatch* pDispatch = NULL;
  920.  
  921.         if (m_pClientSite != NULL &&
  922.             SUCCEEDED(m_pClientSite->QueryInterface(IID_IDispatch,
  923.                 reinterpret_cast<void**>(&pDispatch))))
  924.         {
  925.             ASSERT(pDispatch != NULL);
  926.             m_ambientDispDriver.AttachDispatch(pDispatch);
  927.         }
  928.     }
  929.  
  930.     return &m_ambientDispDriver;
  931. }
  932.  
  933. BOOL COleControl::GetAmbientProperty(DISPID dwDispID, VARTYPE vtProp, void* pvProp)
  934. {
  935.     // First, check whether ambient property can be obtained from cache.
  936.  
  937.     _AFXCTL_AMBIENT_CACHE* pAmbientCache = _afxAmbientCache;
  938.     if (pAmbientCache->m_bValid)
  939.     {
  940.         switch (vtProp)
  941.         {
  942.         // Fetch boolean by selecting appropriate flag in cache.
  943.         case VT_BOOL:
  944.             {
  945.                 static const DWORD _dwAmbientFlags[] =
  946.                 {
  947.                     QACONTAINER_MESSAGEREFLECT,     // -706
  948.                     0,                              // -707
  949.                     0,                              // -708
  950.                     QACONTAINER_USERMODE,           // -709
  951.                     QACONTAINER_UIDEAD,             // -710
  952.                     QACONTAINER_SHOWGRABHANDLES,    // -711
  953.                     QACONTAINER_SHOWHATCHING,       // -712
  954.                     QACONTAINER_DISPLAYASDEFAULT,   // -713
  955.                     QACONTAINER_SUPPORTSMNEMONICS,  // -714
  956.                     QACONTAINER_AUTOCLIP,           // -715
  957.                 };
  958.  
  959.                 int nIndex = DISPID_AMBIENT_MESSAGEREFLECT - dwDispID;
  960.                 DWORD dwFlag;
  961.                 if (nIndex >= 0 && nIndex < _countof(_dwAmbientFlags) &&
  962.                     (dwFlag = _dwAmbientFlags[nIndex]) != 0)
  963.                 {
  964.                     *(BOOL*)pvProp =
  965.                         ((pAmbientCache->m_dwAmbientFlags & dwFlag) != 0);
  966.                     return TRUE;
  967.                 }
  968.             }
  969.             break;
  970.  
  971.         // Fetch color, appearance, or font from corresponding cache entry.
  972.         case VT_I4:
  973.             switch (dwDispID)
  974.             {
  975.             case DISPID_AMBIENT_FORECOLOR:
  976.                 *(DWORD*)pvProp = pAmbientCache->m_colorFore;
  977.                 return TRUE;
  978.  
  979.             case DISPID_AMBIENT_BACKCOLOR:
  980.                 *(DWORD*)pvProp = pAmbientCache->m_colorBack;
  981.                 return TRUE;
  982.  
  983.             case DISPID_AMBIENT_APPEARANCE:
  984.                 *(DWORD*)pvProp = pAmbientCache->m_dwAppearance;
  985.                 return TRUE;
  986.             }
  987.             break;
  988.  
  989.         case VT_I2:
  990.             if (dwDispID == DISPID_AMBIENT_APPEARANCE)
  991.             {
  992.                 *(short*)pvProp = (short)pAmbientCache->m_dwAppearance;
  993.                 return TRUE;
  994.             }
  995.             break;
  996.  
  997.         case VT_DISPATCH:
  998.             if ((dwDispID == DISPID_AMBIENT_FONT) &&
  999.                 (pAmbientCache->m_pFont != NULL) &&
  1000.                 SUCCEEDED(pAmbientCache->m_pFont->QueryInterface(IID_IFontDisp,
  1001.                     reinterpret_cast<void**>(pvProp))))
  1002.             {
  1003.                 return TRUE;
  1004.             }
  1005.             break;
  1006.         }
  1007.     }
  1008.  
  1009.     // If there's no ambient dispatch interface available, then fail.
  1010.  
  1011.     COleDispatchDriver* pDispDriver = GetAmbientDispatchDriver();
  1012.     if (pDispDriver->m_lpDispatch == NULL)
  1013.         return FALSE;
  1014.  
  1015.     // If requested property is of type VT_I4, use optimized function.
  1016.  
  1017.     if (vtProp == VT_I4)
  1018.         return _GetI4Property(pDispDriver->m_lpDispatch, dwDispID,
  1019.             (DWORD*)pvProp);
  1020.  
  1021.     // If none of the above apply, just use the dispatch driver.
  1022.  
  1023.     BOOL bSuccess = FALSE;
  1024.     TRY
  1025.     {
  1026.         pDispDriver->GetProperty(dwDispID, vtProp, pvProp);
  1027.         bSuccess = TRUE;
  1028.     }
  1029.     END_TRY
  1030.  
  1031.     return bSuccess;
  1032. }
  1033.  
  1034. short COleControl::AmbientAppearance()
  1035. {
  1036.     DWORD dwAppearance;
  1037.     if (!GetAmbientProperty(DISPID_AMBIENT_APPEARANCE, VT_I4, &dwAppearance))
  1038.         dwAppearance = 0;
  1039.     return (short)dwAppearance;
  1040. }
  1041.  
  1042. OLE_COLOR COleControl::AmbientBackColor()
  1043. {
  1044.     OLE_COLOR clrBackColor;
  1045.     if (!GetAmbientProperty(DISPID_AMBIENT_BACKCOLOR, VT_I4, &clrBackColor))
  1046.         clrBackColor = GetSysColor(COLOR_WINDOW);
  1047.     return clrBackColor;
  1048. }
  1049.  
  1050. CString COleControl::AmbientDisplayName()
  1051. {
  1052.     CString strDisplayName;
  1053.     GetAmbientProperty(DISPID_AMBIENT_DISPLAYNAME, VT_BSTR, &strDisplayName);
  1054.     return strDisplayName;
  1055. }
  1056.  
  1057. LPFONTDISP COleControl::AmbientFont()
  1058. {
  1059.     // Note: Caller MUST Release the font!
  1060.     LPFONTDISP pDisp;
  1061.     if (!GetAmbientProperty(DISPID_AMBIENT_FONT, VT_DISPATCH, &pDisp))
  1062.         pDisp = NULL;
  1063.     return pDisp;
  1064. }
  1065.  
  1066. OLE_COLOR COleControl::AmbientForeColor()
  1067. {
  1068.     OLE_COLOR clrForeColor;
  1069.     if (!GetAmbientProperty(DISPID_AMBIENT_FORECOLOR, VT_I4, &clrForeColor))
  1070.         clrForeColor = GetSysColor(COLOR_WINDOWTEXT);
  1071.     return clrForeColor;
  1072. }
  1073.  
  1074. LCID COleControl::AmbientLocaleID()
  1075. {
  1076.     LCID lcid;
  1077.     if (!GetAmbientProperty(DISPID_AMBIENT_LOCALEID, VT_I4, &lcid))
  1078.         lcid = 0;
  1079.     return lcid;
  1080. }
  1081.  
  1082. CString COleControl::AmbientScaleUnits()
  1083. {
  1084.     CString strScaleUnits;
  1085.     GetAmbientProperty(DISPID_AMBIENT_SCALEUNITS, VT_BSTR, &strScaleUnits);
  1086.     return strScaleUnits;
  1087. }
  1088.  
  1089. short COleControl::AmbientTextAlign()
  1090. {
  1091.     short iTextAlign;
  1092.     if (!GetAmbientProperty(DISPID_AMBIENT_TEXTALIGN, VT_I2, &iTextAlign))
  1093.         iTextAlign = 0;
  1094.     return iTextAlign;
  1095. }
  1096.  
  1097. BOOL COleControl::AmbientUserMode()
  1098. {
  1099.     BOOL bUserMode;
  1100.     if (!GetAmbientProperty(DISPID_AMBIENT_USERMODE, VT_BOOL, &bUserMode))
  1101.         bUserMode = TRUE;
  1102.     return bUserMode;
  1103. }
  1104.  
  1105. BOOL COleControl::AmbientUIDead()
  1106. {
  1107.     BOOL bUIDead;
  1108.     if (!GetAmbientProperty(DISPID_AMBIENT_UIDEAD, VT_BOOL, &bUIDead))
  1109.         bUIDead = FALSE;
  1110.     return bUIDead;
  1111. }
  1112.  
  1113. BOOL COleControl::AmbientShowGrabHandles()
  1114. {
  1115.     BOOL bShowGrab;
  1116.     if (!GetAmbientProperty(DISPID_AMBIENT_SHOWGRABHANDLES, VT_BOOL, &bShowGrab))
  1117.         bShowGrab = TRUE;
  1118.     return bShowGrab;
  1119. }
  1120.  
  1121. BOOL COleControl::AmbientShowHatching()
  1122. {
  1123.     BOOL bShowHatch;
  1124.     if (!GetAmbientProperty(DISPID_AMBIENT_SHOWHATCHING, VT_BOOL, &bShowHatch))
  1125.         bShowHatch = TRUE;
  1126.     return bShowHatch;
  1127. }
  1128.  
  1129. /////////////////////////////////////////////////////////////////////////////
  1130. // Calls to IPropertyNotifySink
  1131.  
  1132. void COleControl::BoundPropertyChanged(DISPID dispid)
  1133. {
  1134.     POSITION pos = m_xPropConnPt.GetStartPosition();
  1135.     LPPROPERTYNOTIFYSINK pPropNotifySink;
  1136.  
  1137.     while (pos != NULL)
  1138.     {
  1139.         pPropNotifySink =
  1140.             (LPPROPERTYNOTIFYSINK)m_xPropConnPt.GetNextConnection(pos);
  1141.         ASSERT(pPropNotifySink != NULL);
  1142.         pPropNotifySink->OnChanged(dispid);
  1143.     }
  1144. }
  1145.  
  1146. BOOL COleControl::BoundPropertyRequestEdit(DISPID dispid)
  1147. {
  1148.     POSITION pos = m_xPropConnPt.GetStartPosition();
  1149.     LPPROPERTYNOTIFYSINK pPropNotifySink;
  1150.  
  1151.     while (pos != NULL)
  1152.     {
  1153.         pPropNotifySink =
  1154.             (LPPROPERTYNOTIFYSINK)m_xPropConnPt.GetNextConnection(pos);
  1155.         ASSERT(pPropNotifySink != NULL);
  1156.         if (pPropNotifySink->OnRequestEdit(dispid) != S_OK)
  1157.             return FALSE;
  1158.     }
  1159.  
  1160.     // All of the sinks said yes, so it's ok.
  1161.     return TRUE;
  1162. }
  1163.  
  1164. /////////////////////////////////////////////////////////////////////////////
  1165. // Function to call when BoundPropertyRequestEdit fails
  1166.  
  1167. void COleControl::SetNotPermitted()
  1168. {
  1169.     ThrowError(CTL_E_SETNOTPERMITTED, AFX_IDP_E_SETNOTPERMITTED);
  1170. }
  1171.  
  1172. /////////////////////////////////////////////////////////////////////////////
  1173. // Placeholder functions for read-only or write-only properties
  1174.  
  1175. void COleControl::SetNotSupported()
  1176. {
  1177.     ThrowError(CTL_E_SETNOTSUPPORTED, AFX_IDP_E_SETNOTSUPPORTED);
  1178. }
  1179.  
  1180. void COleControl::GetNotSupported()
  1181. {
  1182.     ThrowError(CTL_E_GETNOTSUPPORTED, AFX_IDP_E_GETNOTSUPPORTED);
  1183. }
  1184.  
  1185. /////////////////////////////////////////////////////////////////////////////
  1186. // COleControl::XPerPropertyBrowsing
  1187.  
  1188. STDMETHODIMP_(ULONG) COleControl::XPerPropertyBrowsing::AddRef()
  1189. {
  1190.     METHOD_PROLOGUE_EX_(COleControl, PerPropertyBrowsing)
  1191.     return (ULONG)pThis->ExternalAddRef();
  1192. }
  1193.  
  1194. STDMETHODIMP_(ULONG) COleControl::XPerPropertyBrowsing::Release()
  1195. {
  1196.     METHOD_PROLOGUE_EX_(COleControl, PerPropertyBrowsing)
  1197.     return (ULONG)pThis->ExternalRelease();
  1198. }
  1199.  
  1200. STDMETHODIMP COleControl::XPerPropertyBrowsing::QueryInterface(
  1201.     REFIID iid, LPVOID* ppvObj)
  1202. {
  1203.     METHOD_PROLOGUE_EX_(COleControl, PerPropertyBrowsing)
  1204.     return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);
  1205. }
  1206.  
  1207. STDMETHODIMP COleControl::XPerPropertyBrowsing::GetDisplayString(
  1208.     DISPID dispid, BSTR* lpbstr)
  1209. {
  1210.     METHOD_PROLOGUE_EX(COleControl, PerPropertyBrowsing)
  1211.  
  1212.     ASSERT_NULL_OR_POINTER(lpbstr, BSTR);
  1213.  
  1214.     CString strValue;
  1215.     BOOL bSuccess = pThis->OnGetDisplayString(dispid, strValue);
  1216.  
  1217.     if (lpbstr != NULL)
  1218.         *lpbstr = (bSuccess ? strValue.AllocSysString() : NULL);
  1219.  
  1220.     return bSuccess ? S_OK : S_FALSE;
  1221. }
  1222.  
  1223. BOOL COleControl::OnGetDisplayString(DISPID dispid, CString& strValue)
  1224. {
  1225.     TRY
  1226.     {
  1227.         switch (dispid)
  1228.         {
  1229.         case DISPID_FONT:
  1230.             return m_font.GetDisplayString(strValue);
  1231.  
  1232.         case DISPID_BORDERSTYLE:
  1233.             return strValue.LoadString(m_sBorderStyle == 0 ?
  1234.                 AFX_IDS_BORDERSTYLE_0 : AFX_IDS_BORDERSTYLE_1);
  1235.         }
  1236.     }
  1237.     END_TRY
  1238.  
  1239.     return FALSE;
  1240. }
  1241.  
  1242. STDMETHODIMP COleControl::XPerPropertyBrowsing::MapPropertyToPage(
  1243.     DISPID dispid, LPCLSID lpclsid)
  1244. {
  1245.     METHOD_PROLOGUE_EX(COleControl, PerPropertyBrowsing)
  1246.  
  1247.     ASSERT_NULL_OR_POINTER(lpclsid, CLSID);
  1248.  
  1249.     CLSID clsid = GUID_NULL;
  1250.     BOOL bPageOptional = FALSE;
  1251.     BOOL bSuccess = pThis->OnMapPropertyToPage(dispid, &clsid, &bPageOptional);
  1252.  
  1253.     if (lpclsid != NULL)
  1254.         *lpclsid = (bSuccess ? clsid : GUID_NULL);
  1255.  
  1256.     return bSuccess ? (bPageOptional ? S_OK : S_FALSE) :
  1257.         PERPROP_E_NOPAGEAVAILABLE;
  1258. }
  1259.  
  1260. BOOL COleControl::OnMapPropertyToPage(DISPID dispid, LPCLSID lpclsid,
  1261.     BOOL* pbPageOptional)
  1262. {
  1263.     switch (dispid)
  1264.     {
  1265.     case DISPID_FONT:
  1266.         *lpclsid = CLSID_CFontPropPage;
  1267.         *pbPageOptional = TRUE;
  1268.         return TRUE;
  1269.  
  1270.     case DISPID_BACKCOLOR:
  1271.     case DISPID_FORECOLOR:
  1272.         *lpclsid = CLSID_CColorPropPage;
  1273.         *pbPageOptional = TRUE;
  1274.         return TRUE;
  1275.     }
  1276.  
  1277.     return FALSE;
  1278. }
  1279.  
  1280. inline LPOLESTR AFXAPI _AfxCopyString(LPCTSTR psz)
  1281. {
  1282.     if (psz == NULL)
  1283.         return NULL;
  1284.  
  1285.     int cch = lstrlen(psz) + 1;
  1286.     LPOLESTR pszCopy = NULL;
  1287.  
  1288.     if ((pszCopy = (LPOLESTR)CoTaskMemAlloc(cch * sizeof(OLECHAR))) != NULL)
  1289.     {
  1290. #ifdef _UNICODE
  1291.         wcscpy(pszCopy, psz);
  1292. #elif !defined(OLE2ANSI)
  1293.         MultiByteToWideChar(CP_ACP, 0, psz, -1, pszCopy, cch);
  1294. #else
  1295.         lstrcpy(pszCopy, psz);
  1296. #endif
  1297.     }
  1298.  
  1299.     return pszCopy;
  1300. }
  1301.  
  1302. STDMETHODIMP COleControl::XPerPropertyBrowsing::GetPredefinedStrings(
  1303.     DISPID dispid, CALPOLESTR* lpcaStringsOut, CADWORD* lpcaCookiesOut)
  1304. {
  1305.     METHOD_PROLOGUE_EX(COleControl, PerPropertyBrowsing)
  1306.  
  1307.     if ((lpcaStringsOut == NULL) || (lpcaCookiesOut == NULL))
  1308.         return E_POINTER;
  1309.  
  1310.     ASSERT_POINTER(lpcaStringsOut, CALPOLESTR);
  1311.     ASSERT_POINTER(lpcaCookiesOut, CADWORD);
  1312.  
  1313.     CStringArray stringArray;
  1314.     CDWordArray cookieArray;
  1315.  
  1316.     BOOL bSuccess = pThis->OnGetPredefinedStrings(dispid, &stringArray,
  1317.         &cookieArray);
  1318.  
  1319.     if (bSuccess)
  1320.     {
  1321.         // Allocate and fill arrays to return.
  1322.  
  1323.         ASSERT(stringArray.GetSize() == cookieArray.GetSize());
  1324.  
  1325.         int iElem = 0;
  1326.         LPOLESTR lpszCopy;
  1327.         ULONG cElems = stringArray.GetSize();
  1328.  
  1329.         lpcaStringsOut->pElems = (LPOLESTR*)CoTaskMemAlloc(
  1330.             sizeof(LPOLESTR) * cElems);
  1331.  
  1332.         if (lpcaStringsOut->pElems == NULL)
  1333.             return E_OUTOFMEMORY;
  1334.  
  1335.         lpcaCookiesOut->pElems = (DWORD*)CoTaskMemAlloc(
  1336.             sizeof(DWORD*) * cElems);
  1337.  
  1338.         if (lpcaCookiesOut->pElems == NULL)
  1339.         {
  1340.             CoTaskMemFree(lpcaStringsOut->pElems);
  1341.             return E_OUTOFMEMORY;
  1342.         }
  1343.  
  1344.         lpcaStringsOut->cElems = cElems;
  1345.         lpcaCookiesOut->cElems = cElems;
  1346.  
  1347.         for (iElem = 0; iElem < (int)cElems; iElem++)
  1348.         {
  1349.             lpszCopy = _AfxCopyString(stringArray.GetAt(iElem));
  1350.  
  1351.             if (lpszCopy == NULL)
  1352.             {
  1353.                 // cleanup everything allocated so far...
  1354.                 while (--iElem >= 0)
  1355.                     CoTaskMemFree(lpcaStringsOut->pElems[iElem]);
  1356.  
  1357.                 CoTaskMemFree(lpcaCookiesOut->pElems);
  1358.                 CoTaskMemFree(lpcaStringsOut->pElems);
  1359.  
  1360.                 return E_OUTOFMEMORY;
  1361.             }
  1362.  
  1363.             lpcaStringsOut->pElems[iElem] = lpszCopy;
  1364.             lpcaCookiesOut->pElems[iElem] = cookieArray.GetAt(iElem);
  1365.         }
  1366.     }
  1367.  
  1368.     return bSuccess ? S_OK : S_FALSE;
  1369. }
  1370.  
  1371. BOOL COleControl::OnGetPredefinedStrings(DISPID dispid,
  1372.     CStringArray* pStringArray, CDWordArray* pCookieArray)
  1373. {
  1374.     BOOL bResult = FALSE;
  1375.  
  1376.     switch (dispid)
  1377.     {
  1378.     case DISPID_BORDERSTYLE:
  1379.         TRY
  1380.         {
  1381.             CString str;
  1382.             str.LoadString(AFX_IDS_BORDERSTYLE_0);
  1383.             pStringArray->Add(str);
  1384.             pCookieArray->Add(0);
  1385.             str.LoadString(AFX_IDS_BORDERSTYLE_1);
  1386.             pStringArray->Add(str);
  1387.             pCookieArray->Add(1);
  1388.             bResult = TRUE;
  1389.         }
  1390.         CATCH (CException, e)
  1391.         {
  1392.             pStringArray->RemoveAll();
  1393.             pCookieArray->RemoveAll();
  1394.             bResult = FALSE;
  1395.         }
  1396.         END_CATCH
  1397.         break;
  1398.     }
  1399.  
  1400.     return bResult;
  1401. }
  1402.  
  1403. STDMETHODIMP COleControl::XPerPropertyBrowsing::GetPredefinedValue(
  1404.     DISPID dispid, DWORD dwCookie, VARIANT* lpvarOut)
  1405. {
  1406.     METHOD_PROLOGUE_EX(COleControl, PerPropertyBrowsing)
  1407.  
  1408.     ASSERT_POINTER(lpvarOut, VARIANT);
  1409.  
  1410.     return pThis->OnGetPredefinedValue(dispid, dwCookie, lpvarOut) ?
  1411.         S_OK : E_FAIL;
  1412. }
  1413.  
  1414. BOOL COleControl::OnGetPredefinedValue(DISPID dispid, DWORD dwCookie,
  1415.     VARIANT* lpvarOut)
  1416. {
  1417.     switch (dispid)
  1418.     {
  1419.     case DISPID_BORDERSTYLE:
  1420.         if ((dwCookie == 0) || (dwCookie == 1))
  1421.         {
  1422.             VariantClear(lpvarOut);
  1423.             V_VT(lpvarOut) = VT_I4;
  1424.             V_I4(lpvarOut) = dwCookie;
  1425.             return TRUE;
  1426.         }
  1427.         break;
  1428.     }
  1429.  
  1430.     return FALSE;
  1431. }
  1432.  
  1433. #ifndef _MAC
  1434. void COleControl::Load(LPCTSTR strNewPath, CDataPathProperty& prop)
  1435. {
  1436.     prop.SetControl(this);
  1437.     prop.Open(strNewPath);
  1438. }
  1439. #endif
  1440.  
  1441. /////////////////////////////////////////////////////////////////////////////
  1442. // CDataPathProperty implementation
  1443.  
  1444. #ifndef _MAC
  1445.  
  1446. BOOL CDataPathProperty::Open(CFileException* pError)
  1447. {
  1448.     return CAsyncMonikerFile::Open(m_strPath, m_pControl ? m_pControl->GetClientSite() : NULL, pError);
  1449. }
  1450.  
  1451. BOOL CDataPathProperty::Open(LPCTSTR lpszPath, CFileException* pError)
  1452. {
  1453.     SetPath(lpszPath);
  1454.     return Open(pError);
  1455. }
  1456.  
  1457. BOOL CDataPathProperty::Open(COleControl* pControl, CFileException* pError)
  1458. {
  1459.     SetControl(pControl);
  1460.     return Open(pError);
  1461. }
  1462.  
  1463. BOOL CDataPathProperty::Open(LPCTSTR lpszPath, COleControl* pControl, CFileException* pError)
  1464. {
  1465.     SetControl(pControl);
  1466.     SetPath(lpszPath);
  1467.     return Open(pError);
  1468. }
  1469.  
  1470. void CDataPathProperty::ResetData()
  1471. {
  1472. }
  1473.  
  1474. #ifdef _DEBUG
  1475. void CDataPathProperty::AssertValid() const
  1476. {
  1477.     CAsyncMonikerFile::AssertValid();
  1478. }
  1479.  
  1480. void CDataPathProperty::Dump(CDumpContext& dc) const
  1481. {
  1482.     CAsyncMonikerFile::Dump(dc);
  1483.  
  1484.     dc << "\nm_pControl = " << m_pControl;
  1485.     dc << "\nm_strPath = \"" << m_strPath;
  1486.     dc << "\"\n";
  1487. }
  1488. #endif //_DEBUG
  1489.  
  1490. #endif // !_MAC
  1491.  
  1492. /////////////////////////////////////////////////////////////////////////////
  1493. // CCachedDataPathProperty implementation
  1494.  
  1495. #ifndef _MAC
  1496.  
  1497. static inline
  1498. DWORD AfxTransferFileContent(CFile* pFrom, CFile* pTo)
  1499. {
  1500.     BYTE buff[1024];
  1501.     DWORD dwRead = 0;
  1502.     DWORD dwActual;
  1503.     do
  1504.     {
  1505.         dwActual = pFrom->Read(buff, 1024);
  1506.         pTo->Write(buff, dwActual);
  1507.  
  1508.         dwRead += dwActual;
  1509.     }
  1510.     while (dwActual > 0);
  1511.     return dwRead;
  1512. }
  1513.  
  1514. void CCachedDataPathProperty::OnDataAvailable(DWORD dwSize, DWORD bscfFlag)
  1515. {
  1516.     UNUSED_ALWAYS(bscfFlag);
  1517.     UNUSED_ALWAYS(dwSize);
  1518.     DWORD dwPos = m_Cache.GetPosition();
  1519.     TRY
  1520.     {
  1521.         // Cache the data in our mem file.
  1522.         m_Cache.SeekToEnd();
  1523.         AfxTransferFileContent(this, &m_Cache);
  1524.     }
  1525.     CATCH_ALL(e)
  1526.     {
  1527.         m_Cache.Seek(dwPos, CFile::begin);
  1528.         THROW_LAST();
  1529.     }
  1530.     END_CATCH_ALL
  1531.     m_Cache.Seek(dwPos, CFile::begin);
  1532. }
  1533.  
  1534. void CCachedDataPathProperty::Close()
  1535. {
  1536.     m_Cache.SetLength(0);
  1537.     CDataPathProperty::Close();
  1538. }
  1539.  
  1540. void CCachedDataPathProperty::ResetData()
  1541. {
  1542.     m_Cache.SetLength(0);
  1543. }
  1544. #ifdef _DEBUG
  1545. void CCachedDataPathProperty::AssertValid() const
  1546. {
  1547.     CDataPathProperty::AssertValid();
  1548.     m_Cache.AssertValid();
  1549. }
  1550.  
  1551. void CCachedDataPathProperty::Dump(CDumpContext& dc) const
  1552. {
  1553.     CDataPathProperty::Dump(dc);
  1554.  
  1555.     m_Cache.Dump(dc);
  1556. }
  1557. #endif //_DEBUG
  1558.  
  1559. #endif // !_MAC
  1560.  
  1561. /////////////////////////////////////////////////////////////////////////////
  1562. // Force any extra compiler-generated code into AFX_INIT_SEG
  1563.  
  1564. #ifdef AFX_INIT_SEG
  1565. #pragma code_seg(AFX_INIT_SEG)
  1566. #endif
  1567.  
  1568. #ifndef _MAC
  1569. IMPLEMENT_DYNAMIC(CDataPathProperty, CAsyncMonikerFile)
  1570. IMPLEMENT_DYNAMIC(CCachedDataPathProperty, CDataPathProperty)
  1571. #endif //!_MAC
  1572.