home *** CD-ROM | disk | FTP | other *** search
/ Supercompiler 1997 / SUPERCOMPILER97.iso / MS_VC.50 / VC / MFC / SRC / CTLEVENT.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-30  |  16.2 KB  |  652 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. #include <stdarg.h>
  13.  
  14. #ifdef AFXCTL_CORE2_SEG
  15. #pragma code_seg(AFXCTL_CORE2_SEG)
  16. #endif
  17.  
  18. #ifdef _DEBUG
  19. #undef THIS_FILE
  20. static char THIS_FILE[] = __FILE__;
  21. #endif
  22.  
  23. #define new DEBUG_NEW
  24.  
  25. #pragma warning(disable: 4706) // assignment within conditional
  26.  
  27. /////////////////////////////////////////////////////////////////////////////
  28. // Stock event mask
  29.  
  30. #define STOCKEVENT_CLICK            0x00000001
  31. #define STOCKEVENT_DBLCLICK         0x00000002
  32. #define STOCKEVENT_KEYDOWN          0x00000004
  33. #define STOCKEVENT_KEYPRESS         0x00000008
  34. #define STOCKEVENT_KEYUP            0x00000010
  35. #define STOCKEVENT_MOUSEDOWN        0x00000020
  36. #define STOCKEVENT_MOUSEMOVE        0x00000040
  37. #define STOCKEVENT_MOUSEUP          0x00000080
  38. #define STOCKEVENT_ERROR            0x00000100
  39. #define STOCKEVENT_READYSTATECHANGE 0x00000200
  40.  
  41. #define STOCKEVENTS_MOUSE       0x000000A3  // Click, DblClick, MouseDown, MouseUp
  42.  
  43. void COleControl::InitStockEventMask()
  44. {
  45.     static const DWORD _dwStockFlags[] =
  46.     {
  47.         STOCKEVENT_CLICK,               // -600
  48.         STOCKEVENT_DBLCLICK,            // -601
  49.         STOCKEVENT_KEYDOWN,             // -602
  50.         STOCKEVENT_KEYPRESS,            // -603
  51.         STOCKEVENT_KEYUP,               // -604
  52.         STOCKEVENT_MOUSEDOWN,           // -605
  53.         STOCKEVENT_MOUSEMOVE,           // -606
  54.         STOCKEVENT_MOUSEUP,             // -607
  55.         STOCKEVENT_ERROR,               // -608
  56.         STOCKEVENT_READYSTATECHANGE,    // -609
  57.     };
  58.  
  59.     const AFX_EVENTMAP* pEventMap = GetEventMap();
  60.     const AFX_EVENTMAP_ENTRY* pEntry;
  61.     ASSERT(pEventMap != NULL);
  62.  
  63.     // If stock event mask is already initialized, we're outta here.
  64.     if (*pEventMap->lpStockEventMask != (DWORD)-1)
  65.         return;
  66.  
  67.     AfxLockGlobals(CRIT_STOCKMASK);
  68.  
  69.     if (*pEventMap->lpStockEventMask == (DWORD)-1)
  70.     {
  71.         const AFX_EVENTMAP* pEventMapTop = pEventMap;
  72.         DWORD dwStockEventMask = 0;
  73.  
  74.         while (pEventMap != NULL)
  75.         {
  76.             pEntry = pEventMap->lpEntries;
  77.             while (pEntry != NULL && pEntry->pszName != NULL)
  78.             {
  79.                 int nIndex = DISPID_CLICK - pEntry->dispid;
  80.                 DWORD dwFlag;
  81.                 if ((pEntry->flags & afxEventStock) && (nIndex >= 0) &&
  82.                     (nIndex < _countof(_dwStockFlags)) &&
  83.                     (dwFlag = _dwStockFlags[nIndex]) != 0)
  84.                 {
  85.                     dwStockEventMask |= dwFlag;
  86.                 }
  87.  
  88.                 ++pEntry;
  89.             }
  90.             // check base class
  91.             pEventMap = pEventMap->lpBaseEventMap;
  92.         }
  93.  
  94.         *pEventMapTop->lpStockEventMask = dwStockEventMask;
  95.     }
  96.  
  97.     AfxUnlockGlobals(CRIT_STOCKMASK);
  98. }
  99.  
  100. /////////////////////////////////////////////////////////////////////////////
  101. // Event map operations
  102.  
  103. const AFX_EVENTMAP* COleControl::GetEventMap() const
  104. {
  105.     return &eventMap;
  106. }
  107.  
  108. const AFX_EVENTMAP_ENTRY* COleControl::GetEventMapEntry(
  109.         LPCTSTR pszName,
  110.         DISPID* pDispid) const
  111. {
  112.     ASSERT(pszName != NULL);
  113.     ASSERT(pDispid != NULL);
  114.  
  115.     const AFX_EVENTMAP* pEventMap = GetEventMap();
  116.     const AFX_EVENTMAP_ENTRY* pEntry;
  117.     DISPID dispid = MAKELONG(1, 0);
  118.  
  119.     while (pEventMap != NULL)
  120.     {
  121.         pEntry = pEventMap->lpEntries;
  122.  
  123.         // Scan entries in this event map
  124.  
  125.         if (pEntry != NULL)
  126.         {
  127.             while (pEntry->pszName != NULL)
  128.             {
  129.                 if (_tcscmp(pEntry->pszName, pszName) == 0)
  130.                 {
  131.                     if (pEntry->dispid != DISPID_UNKNOWN)
  132.                         dispid = pEntry->dispid;
  133.  
  134.                     *pDispid = dispid;
  135.                     return pEntry;
  136.                 }
  137.  
  138.                 ++pEntry;
  139.                 ++dispid;
  140.             }
  141.         }
  142.  
  143.         // If we didn't find it, go to the base class's event map
  144.  
  145.         pEventMap = pEventMap->lpBaseEventMap;
  146.         dispid = MAKELONG(1, HIWORD(dispid)+1);
  147.     }
  148.  
  149.     // If we reach here, the event isn't supported
  150.  
  151.     return NULL;
  152. }
  153.  
  154. void COleControl::FireEventV(DISPID dispid, BYTE* pbParams,
  155.     va_list argList)
  156. {
  157.     COleDispatchDriver driver;
  158.  
  159.     POSITION pos = m_xEventConnPt.GetStartPosition();
  160.     LPDISPATCH pDispatch;
  161.     while (pos != NULL)
  162.     {
  163.         pDispatch = (LPDISPATCH)m_xEventConnPt.GetNextConnection(pos);
  164.         ASSERT(pDispatch != NULL);
  165.         driver.AttachDispatch(pDispatch, FALSE);
  166.         TRY
  167.             driver.InvokeHelperV(dispid, DISPATCH_METHOD, VT_EMPTY, NULL,
  168.                 pbParams, argList);
  169.         END_TRY
  170.         driver.DetachDispatch();
  171.     }
  172. }
  173.  
  174. void AFX_CDECL COleControl::FireEvent(DISPID dispid, BYTE* pbParams, ...)
  175. {
  176.     va_list argList;
  177.     va_start(argList, pbParams);
  178.     FireEventV(dispid, pbParams, argList);
  179.     va_end(argList);
  180. }
  181.  
  182. /////////////////////////////////////////////////////////////////////////////
  183. // Helper function for stock events
  184.  
  185. short AFXAPI _AfxShiftState()
  186. {
  187.     BOOL bShift = (GetKeyState(VK_SHIFT) < 0);
  188.     BOOL bCtrl  = (GetKeyState(VK_CONTROL) < 0);
  189.     BOOL bAlt   = (GetKeyState(VK_MENU) < 0);
  190.  
  191.     return (short)(bShift + (bCtrl << 1) + (bAlt << 2));
  192. }
  193.  
  194. /////////////////////////////////////////////////////////////////////////////
  195. // Window message handlers for stock events
  196.  
  197. void COleControl::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
  198. {
  199.     HWND hWndSave = m_hWnd;
  200.     USHORT nCharShort = (USHORT)nChar;
  201.     KeyDown(&nCharShort);
  202.     if ((m_hWnd == hWndSave) && (nCharShort != 0))
  203.         DefWindowProc(WM_SYSKEYDOWN, nCharShort, MAKELONG(nRepCnt, nFlags));
  204. }
  205.  
  206. void COleControl::OnSysKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
  207. {
  208.     HWND hWndSave = m_hWnd;
  209.     USHORT nCharShort = (USHORT)nChar;
  210.     KeyUp(&nCharShort);
  211.     if ((m_hWnd == hWndSave) && (nCharShort != 0))
  212.         DefWindowProc(WM_SYSKEYUP, nCharShort, MAKELONG(nRepCnt, nFlags));
  213. }
  214.  
  215. void COleControl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
  216. {
  217.     HWND hWndSave = m_hWnd;
  218.     USHORT nCharShort = (USHORT)nChar;
  219.     KeyDown(&nCharShort);
  220.     if ((m_hWnd == hWndSave) && (nCharShort != 0))
  221.         DefWindowProc(WM_KEYDOWN, nCharShort, MAKELONG(nRepCnt, nFlags));
  222. }
  223.  
  224. void COleControl::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
  225. {
  226.     HWND hWndSave = m_hWnd;
  227.     USHORT nCharShort = (USHORT)nChar;
  228.     KeyUp(&nCharShort);
  229.     if ((m_hWnd == hWndSave) && (nCharShort != 0))
  230.         DefWindowProc(WM_KEYUP, nCharShort, MAKELONG(nRepCnt, nFlags));
  231. }
  232.  
  233. void COleControl::KeyUp(USHORT* pnChar)
  234. {
  235.     if (GetStockEventMask() & STOCKEVENT_KEYUP)
  236.     {
  237.         USHORT nShiftState = _AfxShiftState();
  238.         FireKeyUp(pnChar, nShiftState);
  239.  
  240.         // If handler set *pnChar to zero, cancel further processing.
  241.         if (*pnChar != 0)
  242.             OnKeyUpEvent(*pnChar, nShiftState);
  243.     }
  244. }
  245.  
  246. void COleControl::KeyDown(USHORT* pnChar)
  247. {
  248.     if (GetStockEventMask() & STOCKEVENT_KEYDOWN)
  249.     {
  250.         USHORT nShiftState = _AfxShiftState();
  251.         FireKeyDown(pnChar, nShiftState);
  252.  
  253.         // If handler set *pnChar to zero, cancel further processing.
  254.         if (*pnChar != 0)
  255.             OnKeyDownEvent(*pnChar, nShiftState);
  256.     }
  257. }
  258.  
  259. static void PostTrailByte(CWnd* pWnd, BYTE bTrailByte)
  260. {
  261.     // Force new trail byte to the front of the queue.
  262.     pWnd->PostMessage(WM_QUEUE_SENTINEL);
  263.     pWnd->PostMessage(WM_CHAR, bTrailByte);
  264.     MSG msg;
  265.     while (::PeekMessage(&msg, NULL, 0, 0, PM_NOYIELD | PM_REMOVE) &&
  266.         (msg.message != WM_QUEUE_SENTINEL))
  267.     {
  268.         ::PostMessage(msg.hwnd, msg.message, msg.wParam, msg.lParam);
  269.     }
  270.  
  271.     ASSERT(msg.message == WM_QUEUE_SENTINEL);
  272.     ASSERT(msg.hwnd == pWnd->m_hWnd);
  273. }
  274.  
  275. UINT COleControl::OnGetDlgCode()
  276. {
  277.     // If we're firing KeyPress, prevent the container from stealing WM_CHAR.
  278.     return (IsSubclassedControl() ? CWnd::OnGetDlgCode() : 0) |
  279.         ((GetStockEventMask() & STOCKEVENT_KEYPRESS) ? DLGC_WANTCHARS : 0);
  280. }
  281.  
  282. void COleControl::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
  283. {
  284.     USHORT nCharShort = (USHORT)nChar;
  285.     USHORT nCharSave = nCharShort;
  286.     BOOL bLeadByte = IsDBCSLeadByte((BYTE)nCharShort);
  287.     MSG msg;
  288.  
  289.     if (GetStockEventMask() & STOCKEVENT_KEYPRESS)
  290.     {
  291.         if (bLeadByte)
  292.         {
  293.             // We have the lead-byte of a DBCS character.  Peek for the
  294.             // next WM_CHAR message, which will contain the other byte.
  295.  
  296.             BOOL bMessage;
  297.             VERIFY(bMessage = ::PeekMessage(&msg, m_hWnd, WM_CHAR, WM_CHAR,
  298.                 PM_NOYIELD | PM_NOREMOVE));
  299.  
  300.             // Combine the bytes to form the DBCS character.
  301.  
  302.             if (bMessage)
  303.                 nCharShort = (USHORT)((nCharShort << 8) | msg.wParam);
  304.         }
  305.  
  306.         HWND hWndSave = m_hWnd;
  307.         nCharSave = nCharShort;
  308.         FireKeyPress(&nCharShort);
  309.  
  310.         // If handler set nCharShort to zero, cancel further processing.
  311.         if (nCharShort != 0)
  312.             OnKeyPressEvent(nCharShort);
  313.  
  314.         if (m_hWnd != hWndSave)
  315.             return;
  316.     }
  317.  
  318.     if (nCharShort != 0)
  319.     {
  320.         if (nCharSave != nCharShort)
  321.         {
  322.             nChar = nCharShort;
  323.  
  324.             // Event handler has changed the character.
  325.  
  326.             BOOL bNewLeadByte = IsDBCSLeadByte(HIBYTE(nCharShort));
  327.  
  328.             if (bLeadByte)
  329.             {
  330.                 if (bNewLeadByte)
  331.                 {
  332.                     // Event handler changed character from DBCS to DBCS:
  333.                     // Remove the old trail byte and post the new one.
  334.  
  335.                     VERIFY(::PeekMessage(&msg, m_hWnd, WM_CHAR, WM_CHAR,
  336.                         PM_NOYIELD | PM_REMOVE));
  337.                     PostTrailByte(this, LOBYTE(nCharShort));
  338.                     nChar = HIBYTE(nCharShort);
  339.                 }
  340.                 else
  341.                 {
  342.                     // Event handler changed character from DBCS to SBCS:
  343.                     // Remove the second byte from the queue, and forward
  344.                     // along the new single-byte character.
  345.  
  346.                     VERIFY(::PeekMessage(&msg, m_hWnd, WM_CHAR, WM_CHAR,
  347.                         PM_NOYIELD | PM_REMOVE));
  348.                 }
  349.             }
  350.             else
  351.             {
  352.                 if (bNewLeadByte)
  353.                 {
  354.                     // Event handler changed character from SBCS to DBCS:
  355.                     // Post the new trail byte.
  356.  
  357.                     PostTrailByte(this, LOBYTE(nCharShort));
  358.                     nChar = HIBYTE(nCharShort);
  359.                 }
  360.             }
  361.         }
  362.  
  363.         DefWindowProc(WM_CHAR, nChar, MAKELONG(nRepCnt, nFlags));
  364.     }
  365.  
  366.     if (bLeadByte)
  367.     {
  368.         // Cleanup after processing a DBCS character:
  369.         // Remove the next WM_CHAR message (containing the second byte) from
  370.         // the message queue, UNLESS we're subclassing an Edit, ListBox, or
  371.         // ComboBox control.
  372.  
  373.         TCHAR szClassName[10];
  374.         if ((!::GetClassName(m_hWnd, szClassName, 10)) ||  // didn't get class
  375.             (_tcsicmp(szClassName, _T("Edit")) &&           // not Edit
  376.              _tcsicmp(szClassName, _T("ListBox")) &&        // not ListBox
  377.              _tcsicmp(szClassName, _T("ComboBox"))))        // not ComboBox
  378.         {
  379.             VERIFY(::PeekMessage(&msg, m_hWnd, WM_CHAR, WM_CHAR,
  380.                 PM_NOYIELD | PM_REMOVE));
  381.         }
  382.     }
  383. }
  384.  
  385. void COleControl::OnKeyPressEvent(USHORT)
  386. {
  387.     // Can be overridden by subclass
  388. }
  389.  
  390. void COleControl::OnKeyDownEvent(USHORT, USHORT)
  391. {
  392.     // Can be overridden by subclass
  393. }
  394.  
  395. void COleControl::OnKeyUpEvent(USHORT, USHORT)
  396. {
  397.     // Can be overridden by subclass
  398. }
  399.  
  400. void COleControl::ButtonDown(USHORT iButton, UINT, CPoint point)
  401. {
  402.     DWORD dwStockEventMask = GetStockEventMask();
  403.     if ((dwStockEventMask & STOCKEVENTS_MOUSE) || m_bPendingUIActivation)
  404.     {
  405.         if (m_iButtonState == 0)
  406.             SetCapture();
  407.  
  408.         m_iButtonState |= iButton;
  409.  
  410.         if (dwStockEventMask & STOCKEVENT_MOUSEDOWN)
  411.             FireMouseDown(iButton, _AfxShiftState(), point.x, point.y);
  412.  
  413.         m_iDblClkState &= ~iButton;
  414.     }
  415. }
  416.  
  417. void COleControl::ButtonUp(USHORT iButton, UINT, CPoint point)
  418. {
  419.     if (m_iButtonState != 0)
  420.     {
  421.         m_iButtonState &= ~iButton;
  422.  
  423.         if (m_iButtonState == 0)
  424.             ReleaseCapture();
  425.  
  426.         DWORD dwStockEventMask = GetStockEventMask();
  427.  
  428.         if (dwStockEventMask & STOCKEVENT_MOUSEUP)
  429.             FireMouseUp(iButton, _AfxShiftState(), point.x, point.y);
  430.  
  431.         if ((dwStockEventMask & STOCKEVENT_CLICK) &&
  432.             !(m_iDblClkState & iButton))
  433.         {
  434.             CRect rect;
  435.             GetClientRect(&rect);
  436.             if (rect.PtInRect(point))
  437.                 OnClick(iButton);
  438.         }
  439.  
  440.         m_iDblClkState &= ~iButton;
  441.     }
  442. }
  443.  
  444. void COleControl::ButtonDblClk(USHORT iButton, UINT, CPoint)
  445. {
  446.     DWORD dwStockEventMask = GetStockEventMask();
  447.     if (dwStockEventMask & STOCKEVENTS_MOUSE)
  448.     {
  449.         SetCapture();
  450.         m_iButtonState |= iButton;
  451.  
  452.         if (dwStockEventMask & STOCKEVENT_DBLCLICK)
  453.         {
  454.             FireDblClick();
  455.             m_iDblClkState |= iButton;
  456.         }
  457.     }
  458. }
  459.  
  460. void COleControl::OnMouseMove(UINT nFlags, CPoint point)
  461. {
  462.     if (GetStockEventMask() & STOCKEVENT_MOUSEMOVE)
  463.     {
  464.         HWND hWndSave = m_hWnd;
  465.         FireMouseMove((short)m_iButtonState, _AfxShiftState(), point.x, point.y);
  466.         if (m_hWnd != hWndSave)
  467.             return;
  468.     }
  469.  
  470.     CWnd::OnMouseMove(nFlags, point);
  471. }
  472.  
  473. void COleControl::OnLButtonDown(UINT nFlags, CPoint point)
  474. {
  475.     HWND hWndSave = m_hWnd;
  476.     SetFocus();
  477.     ButtonDown(LEFT_BUTTON, nFlags, point);
  478.     if (m_hWnd != hWndSave)
  479.         return;
  480.  
  481.     CWnd::OnLButtonDown(nFlags, point);
  482. }
  483.  
  484. void COleControl::OnLButtonUp(UINT nFlags, CPoint point)
  485. {
  486.     HWND hWndSave = m_hWnd;
  487.     CWnd::OnLButtonUp(nFlags, point);
  488.     ButtonUp(LEFT_BUTTON, nFlags, point);
  489.     if (m_hWnd != hWndSave)
  490.         return;
  491.  
  492.     if (m_bInPlaceActive && !m_bUIActive && m_bPendingUIActivation &&
  493.         (GetFocus() == this || IsChild(GetFocus())))
  494.     {
  495.         m_bPendingUIActivation = FALSE;
  496.         OnActivateInPlace(TRUE, NULL);
  497.     }
  498. }
  499.  
  500. void COleControl::OnLButtonDblClk(UINT nFlags, CPoint point)
  501. {
  502.     HWND hWndSave = m_hWnd;
  503.     ButtonDblClk(LEFT_BUTTON, nFlags, point);
  504.     if (m_hWnd != hWndSave)
  505.         return;
  506.  
  507.     CWnd::OnLButtonDblClk(nFlags, point);
  508. }
  509.  
  510. void COleControl::OnMButtonDown(UINT nFlags, CPoint point)
  511. {
  512.     HWND hWndSave = m_hWnd;
  513.     ButtonDown(MIDDLE_BUTTON, nFlags, point);
  514.     if (m_hWnd != hWndSave)
  515.         return;
  516.  
  517.     CWnd::OnMButtonDown(nFlags, point);
  518. }
  519.  
  520. void COleControl::OnMButtonUp(UINT nFlags, CPoint point)
  521. {
  522.     HWND hWndSave = m_hWnd;
  523.     CWnd::OnMButtonUp(nFlags, point);
  524.     ButtonUp(MIDDLE_BUTTON, nFlags, point);
  525.     if (m_hWnd != hWndSave)
  526.         return;
  527.  
  528.     if (m_bInPlaceActive && !m_bUIActive && m_bPendingUIActivation &&
  529.         (GetFocus() == this || IsChild(GetFocus())))
  530.     {
  531.         m_bPendingUIActivation = FALSE;
  532.         OnActivateInPlace(TRUE, NULL);
  533.     }
  534. }
  535.  
  536. void COleControl::OnMButtonDblClk(UINT nFlags, CPoint point)
  537. {
  538.     HWND hWndSave = m_hWnd;
  539.     ButtonDblClk(MIDDLE_BUTTON, nFlags, point);
  540.     if (m_hWnd != hWndSave)
  541.         return;
  542.  
  543.     CWnd::OnMButtonDblClk(nFlags, point);
  544. }
  545.  
  546. void COleControl::OnRButtonDown(UINT nFlags, CPoint point)
  547. {
  548.     HWND hWndSave = m_hWnd;
  549.     ButtonDown(RIGHT_BUTTON, nFlags, point);
  550.     if (m_hWnd != hWndSave)
  551.         return;
  552.  
  553.     CWnd::OnRButtonDown(nFlags, point);
  554. }
  555.  
  556. void COleControl::OnRButtonUp(UINT nFlags, CPoint point)
  557. {
  558.     HWND hWndSave = m_hWnd;
  559.     CWnd::OnRButtonUp(nFlags, point);
  560.     ButtonUp(RIGHT_BUTTON, nFlags, point);
  561.     if (m_hWnd != hWndSave)
  562.         return;
  563.  
  564.     if (m_bInPlaceActive && !m_bUIActive && m_bPendingUIActivation &&
  565.         (GetFocus() == this || IsChild(GetFocus())))
  566.     {
  567.         m_bPendingUIActivation = FALSE;
  568.         OnActivateInPlace(TRUE, NULL);
  569.     }
  570. }
  571.  
  572. void COleControl::OnRButtonDblClk(UINT nFlags, CPoint point)
  573. {
  574.     HWND hWndSave = m_hWnd;
  575.     ButtonDblClk(RIGHT_BUTTON, nFlags, point);
  576.     if (m_hWnd != hWndSave)
  577.         return;
  578.  
  579.     CWnd::OnRButtonDblClk(nFlags, point);
  580. }
  581.  
  582. void COleControl::OnCancelMode()
  583. {
  584.     CWnd::OnCancelMode();
  585.  
  586.     if ((m_iButtonState != 0) || (m_iDblClkState != 0))
  587.     {
  588.         ReleaseCapture();
  589.         m_iButtonState = 0;
  590.         m_iDblClkState = 0;
  591.     }
  592. }
  593.  
  594. void COleControl::OnClick(USHORT /*iButton*/)
  595. {
  596.     // May be overridden by subclass
  597.  
  598.     if (GetStockEventMask() & STOCKEVENT_CLICK)
  599.         FireClick();
  600. }
  601.  
  602. /////////////////////////////////////////////////////////////////////////////
  603. // Error event
  604.  
  605. #define ERROR_PARAMS \
  606.      EVENT_PARAM(VTS_I2 VTS_PBSTR VTS_SCODE VTS_BSTR VTS_BSTR VTS_I4 VTS_PBOOL)
  607.  
  608. void COleControl::FireError(SCODE scode, LPCTSTR lpszDescription, UINT nHelpID)
  609. {
  610.     USES_CONVERSION;
  611.  
  612.     ExternalAddRef();   // "Insurance" addref -- keeps control alive.
  613.  
  614.     BSTR bstrDescription = ::SysAllocString(T2COLE(lpszDescription));
  615.     LPCTSTR lpszSource = AfxGetAppName();
  616.     LPCTSTR lpszHelpFile = _T("");
  617.  
  618.     if (nHelpID != 0)
  619.         lpszHelpFile = AfxGetApp()->m_pszHelpFilePath;
  620.  
  621.     if (lpszHelpFile == NULL)
  622.         lpszHelpFile = _T("");
  623.  
  624.     BOOL bCancelDisplay = FALSE;
  625.  
  626.     FireEvent(DISPID_ERROREVENT, ERROR_PARAMS, (WORD)SCODE_CODE(scode),
  627.         &bstrDescription, scode, lpszSource, lpszHelpFile, (DWORD)nHelpID,
  628.         &bCancelDisplay);
  629.  
  630.     if (!bCancelDisplay)
  631.         DisplayError(scode, OLE2CT(bstrDescription), lpszSource, lpszHelpFile, nHelpID);
  632.  
  633.     ::SysFreeString(bstrDescription);
  634.  
  635.     ExternalRelease();
  636. }
  637.  
  638. void COleControl::DisplayError(SCODE /*scode*/, LPCTSTR lpszDescription,
  639.     LPCTSTR lpszSource, LPCTSTR /*lpszHelpFile*/, UINT /*nHelpID*/)
  640. {
  641.     // May be overridden by subclass.
  642.  
  643.     MessageBox(lpszDescription, lpszSource);
  644. }
  645.  
  646. /////////////////////////////////////////////////////////////////////////////
  647. // Force any extra compiler-generated code into AFX_INIT_SEG
  648.  
  649. #ifdef AFX_INIT_SEG
  650. #pragma code_seg(AFX_INIT_SEG)
  651. #endif
  652.