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