home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / cmdtarg.cpp < prev    next >
C/C++ Source or Header  |  1998-06-16  |  22KB  |  862 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. #include "occimpl.h"
  13.  
  14. #ifdef AFX_CORE1_SEG
  15. #pragma code_seg(AFX_CORE1_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. /////////////////////////////////////////////////////////////////////////////
  26. // CCmdTarget construction/destruction
  27.  
  28. CCmdTarget::CCmdTarget()
  29. {
  30.     // capture module state where object was constructed
  31. #ifdef _AFXDLL
  32.     m_pModuleState = AfxGetModuleState();
  33.     ASSERT(m_pModuleState != NULL);
  34. #endif
  35.  
  36.     // initialize state
  37. #ifndef _AFX_NO_OLE_SUPPORT
  38.     m_dwRef = 1;
  39.     m_pOuterUnknown = NULL;
  40.     m_xInnerUnknown = 0;
  41.     m_xDispatch.m_vtbl = 0;
  42.     m_bResultExpected = TRUE;
  43.     m_xConnPtContainer.m_vtbl = 0;
  44. #endif
  45. }
  46.  
  47. CCmdTarget::~CCmdTarget()
  48. {
  49. #ifndef _AFX_NO_OLE_SUPPORT
  50.     if (m_xDispatch.m_vtbl != 0)
  51.         ((COleDispatchImpl*)&m_xDispatch)->Disconnect();
  52.     ASSERT(m_dwRef <= 1);
  53. #endif
  54. #ifdef _AFXDLL
  55.     m_pModuleState = NULL;
  56. #endif
  57. }
  58.  
  59. /////////////////////////////////////////////////////////////////////////////
  60. // CCmdTarget windows message dispatching
  61.  
  62. AFX_STATIC BOOL AFXAPI _AfxDispatchCmdMsg(CCmdTarget* pTarget, UINT nID, int nCode,
  63.     AFX_PMSG pfn, void* pExtra, UINT nSig, AFX_CMDHANDLERINFO* pHandlerInfo)
  64.         // return TRUE to stop routing
  65. {
  66.     ASSERT_VALID(pTarget);
  67.     UNUSED(nCode);   // unused in release builds
  68.  
  69.     union MessageMapFunctions mmf;
  70.     mmf.pfn = pfn;
  71.     BOOL bResult = TRUE; // default is ok
  72.  
  73.     if (pHandlerInfo != NULL)
  74.     {
  75.         // just fill in the information, don't do it
  76.         pHandlerInfo->pTarget = pTarget;
  77.         pHandlerInfo->pmf = mmf.pfn;
  78.         return TRUE;
  79.     }
  80.  
  81.     switch (nSig)
  82.     {
  83.     case AfxSig_vv:
  84.         // normal command or control notification
  85.         ASSERT(CN_COMMAND == 0);        // CN_COMMAND same as BN_CLICKED
  86.         ASSERT(pExtra == NULL);
  87.         (pTarget->*mmf.pfn_COMMAND)();
  88.         break;
  89.  
  90.     case AfxSig_bv:
  91.         // normal command or control notification
  92.         ASSERT(CN_COMMAND == 0);        // CN_COMMAND same as BN_CLICKED
  93.         ASSERT(pExtra == NULL);
  94.         bResult = (pTarget->*mmf.pfn_bCOMMAND)();
  95.         break;
  96.  
  97.     case AfxSig_vw:
  98.         // normal command or control notification in a range
  99.         ASSERT(CN_COMMAND == 0);        // CN_COMMAND same as BN_CLICKED
  100.         ASSERT(pExtra == NULL);
  101.         (pTarget->*mmf.pfn_COMMAND_RANGE)(nID);
  102.         break;
  103.  
  104.     case AfxSig_bw:
  105.         // extended command (passed ID, returns bContinue)
  106.         ASSERT(pExtra == NULL);
  107.         bResult = (pTarget->*mmf.pfn_COMMAND_EX)(nID);
  108.         break;
  109.  
  110.     case AfxSig_vNMHDRpl:
  111.         {
  112.             AFX_NOTIFY* pNotify = (AFX_NOTIFY*)pExtra;
  113.             ASSERT(pNotify != NULL);
  114.             ASSERT(pNotify->pResult != NULL);
  115.             ASSERT(pNotify->pNMHDR != NULL);
  116.             (pTarget->*mmf.pfn_NOTIFY)(pNotify->pNMHDR, pNotify->pResult);
  117.         }
  118.         break;
  119.     case AfxSig_bNMHDRpl:
  120.         {
  121.             AFX_NOTIFY* pNotify = (AFX_NOTIFY*)pExtra;
  122.             ASSERT(pNotify != NULL);
  123.             ASSERT(pNotify->pResult != NULL);
  124.             ASSERT(pNotify->pNMHDR != NULL);
  125.             bResult = (pTarget->*mmf.pfn_bNOTIFY)(pNotify->pNMHDR, pNotify->pResult);
  126.         }
  127.         break;
  128.     case AfxSig_vwNMHDRpl:
  129.         {
  130.             AFX_NOTIFY* pNotify = (AFX_NOTIFY*)pExtra;
  131.             ASSERT(pNotify != NULL);
  132.             ASSERT(pNotify->pResult != NULL);
  133.             ASSERT(pNotify->pNMHDR != NULL);
  134.             (pTarget->*mmf.pfn_NOTIFY_RANGE)(nID, pNotify->pNMHDR,
  135.                 pNotify->pResult);
  136.         }
  137.         break;
  138.     case AfxSig_bwNMHDRpl:
  139.         {
  140.             AFX_NOTIFY* pNotify = (AFX_NOTIFY*)pExtra;
  141.             ASSERT(pNotify != NULL);
  142.             ASSERT(pNotify->pResult != NULL);
  143.             ASSERT(pNotify->pNMHDR != NULL);
  144.             bResult = (pTarget->*mmf.pfn_NOTIFY_EX)(nID, pNotify->pNMHDR,
  145.                 pNotify->pResult);
  146.         }
  147.         break;
  148.     case AfxSig_cmdui:
  149.         {
  150.             // ON_UPDATE_COMMAND_UI or ON_UPDATE_COMMAND_UI_REFLECT case
  151.             ASSERT(CN_UPDATE_COMMAND_UI == (UINT)-1);
  152.             ASSERT(nCode == CN_UPDATE_COMMAND_UI || nCode == 0xFFFF);
  153.             ASSERT(pExtra != NULL);
  154.             CCmdUI* pCmdUI = (CCmdUI*)pExtra;
  155.             ASSERT(!pCmdUI->m_bContinueRouting);    // idle - not set
  156.             (pTarget->*mmf.pfn_UPDATE_COMMAND_UI)(pCmdUI);
  157.             bResult = !pCmdUI->m_bContinueRouting;
  158.             pCmdUI->m_bContinueRouting = FALSE;     // go back to idle
  159.         }
  160.         break;
  161.  
  162.     case AfxSig_cmduiw:
  163.         {
  164.             // ON_UPDATE_COMMAND_UI case
  165.             ASSERT(nCode == CN_UPDATE_COMMAND_UI);
  166.             ASSERT(pExtra != NULL);
  167.             CCmdUI* pCmdUI = (CCmdUI*)pExtra;
  168.             ASSERT(pCmdUI->m_nID == nID);           // sanity assert
  169.             ASSERT(!pCmdUI->m_bContinueRouting);    // idle - not set
  170.             (pTarget->*mmf.pfn_UPDATE_COMMAND_UI_RANGE)(pCmdUI, nID);
  171.             bResult = !pCmdUI->m_bContinueRouting;
  172.             pCmdUI->m_bContinueRouting = FALSE;     // go back to idle
  173.         }
  174.         break;
  175.  
  176.     // general extensibility hooks
  177.     case AfxSig_vpv:
  178.         (pTarget->*mmf.pfn_OTHER)(pExtra);
  179.         break;
  180.     case AfxSig_bpv:
  181.         bResult = (pTarget->*mmf.pfn_OTHER_EX)(pExtra);
  182.         break;
  183.  
  184.     default:    // illegal
  185.         ASSERT(FALSE);
  186.         return 0;
  187.     }
  188.     return bResult;
  189. }
  190.  
  191. // compare two pointers to GUIDs -- TRUE if both pointers are NULL
  192. // or both pointers point to same GUID; FALSE otherwise
  193.  
  194. #define IsEqualNULLGuid(pGuid1, pGuid2) \
  195.     (((pGuid1) == NULL && (pGuid2) == NULL) || \
  196.      ((pGuid1) != NULL && (pGuid2) != NULL && \
  197.         IsEqualGUID(*(pGuid1), *(pGuid2))))
  198.  
  199.  
  200. BOOL CCmdTarget::OnCmdMsg(UINT nID, int nCode, void* pExtra,
  201.     AFX_CMDHANDLERINFO* pHandlerInfo)
  202. {
  203. #ifndef _AFX_NO_OCC_SUPPORT
  204.     // OLE control events are a special case
  205.     if (nCode == CN_EVENT)
  206.     {
  207.         ASSERT(afxOccManager != NULL);
  208.         return afxOccManager->OnEvent(this, nID, (AFX_EVENT*)pExtra, pHandlerInfo);
  209.     }
  210. #endif // !_AFX_NO_OCC_SUPPORT
  211.  
  212.     // determine the message number and code (packed into nCode)
  213.     const AFX_MSGMAP* pMessageMap;
  214.     const AFX_MSGMAP_ENTRY* lpEntry;
  215.     UINT nMsg = 0;
  216.  
  217. #ifndef _AFX_NO_DOCOBJECT_SUPPORT
  218.     if (nCode == CN_OLECOMMAND)
  219.     {
  220.         BOOL bResult = FALSE;
  221.  
  222.         const AFX_OLECMDMAP* pOleCommandMap;
  223.         const AFX_OLECMDMAP_ENTRY* pEntry;
  224.  
  225.         COleCmdUI* pUI = (COleCmdUI*) pExtra;
  226.         const GUID* pguidCmdGroup = pUI->m_pguidCmdGroup;
  227.  
  228. #ifdef _AFXDLL
  229.         for (pOleCommandMap = GetCommandMap(); pOleCommandMap != NULL && !bResult;
  230.             pOleCommandMap = pOleCommandMap->pfnGetBaseMap())
  231. #else
  232.         for (pOleCommandMap = GetCommandMap(); pOleCommandMap != NULL && !bResult;
  233.             pOleCommandMap = pOleCommandMap->pBaseMap)
  234. #endif
  235.         {
  236.             for (pEntry = pOleCommandMap->lpEntries;
  237.                 pEntry->cmdID != 0 && pEntry->nID != 0 && !bResult;
  238.                 pEntry++)
  239.             {
  240.                 if (nID == pEntry->cmdID &&
  241.                     IsEqualNULLGuid(pguidCmdGroup, pEntry->pguid))
  242.                 {
  243.                     pUI->m_nID = pEntry->nID;
  244.                     bResult = TRUE;
  245.                 }
  246.             }
  247.         }
  248.  
  249.         return bResult;
  250.     }
  251. #endif
  252.  
  253.     if (nCode != CN_UPDATE_COMMAND_UI)
  254.     {
  255.         nMsg = HIWORD(nCode);
  256.         nCode = LOWORD(nCode);
  257.     }
  258.  
  259.     // for backward compatibility HIWORD(nCode)==0 is WM_COMMAND
  260.     if (nMsg == 0)
  261.         nMsg = WM_COMMAND;
  262.  
  263.     // look through message map to see if it applies to us
  264. #ifdef _AFXDLL
  265.     for (pMessageMap = GetMessageMap(); pMessageMap != NULL;
  266.       pMessageMap = (*pMessageMap->pfnGetBaseMap)())
  267. #else
  268.     for (pMessageMap = GetMessageMap(); pMessageMap != NULL;
  269.       pMessageMap = pMessageMap->pBaseMap)
  270. #endif
  271.     {
  272.         // Note: catches BEGIN_MESSAGE_MAP(CMyClass, CMyClass)!
  273. #ifdef _AFXDLL
  274.         ASSERT(pMessageMap != (*pMessageMap->pfnGetBaseMap)());
  275. #else
  276.         ASSERT(pMessageMap != pMessageMap->pBaseMap);
  277. #endif
  278.  
  279.         lpEntry = AfxFindMessageEntry(pMessageMap->lpEntries, nMsg, nCode, nID);
  280.         if (lpEntry != NULL)
  281.         {
  282.             // found it
  283. #ifdef _DEBUG
  284.             if (afxTraceFlags & traceCmdRouting)
  285.             {
  286.                 if (nCode == CN_COMMAND)
  287.                 {
  288.                     TRACE2("SENDING command id 0x%04X to %hs target.\n", nID,
  289.                         GetRuntimeClass()->m_lpszClassName);
  290.                 }
  291.                 else if (nCode > CN_COMMAND)
  292.                 {
  293.                     if (afxTraceFlags & traceWinMsg)
  294.                     {
  295.                         TRACE3("SENDING control notification %d from control id 0x%04X to %hs window.\n",
  296.                             nCode, nID, GetRuntimeClass()->m_lpszClassName);
  297.                     }
  298.                 }
  299.             }
  300. #endif //_DEBUG
  301.             return _AfxDispatchCmdMsg(this, nID, nCode,
  302.                 lpEntry->pfn, pExtra, lpEntry->nSig, pHandlerInfo);
  303.         }
  304.     }
  305.     return FALSE;   // not handled
  306. }
  307.  
  308. /////////////////////////////////////////////////////////////////////////////
  309. // Hook to disable automation handlers
  310.  
  311. #ifndef _AFX_NO_OLE_SUPPORT
  312.  
  313. BOOL CCmdTarget::IsInvokeAllowed(DISPID)
  314. {
  315.     return TRUE;    // normally, invoke is always allowed
  316. }
  317.  
  318. #endif // !_AFX_NO_OLE_SUPPORT
  319.  
  320. /////////////////////////////////////////////////////////////////////////////
  321. // Stubs for OLE type library functions
  322.  
  323. #ifndef _AFX_NO_OLE_SUPPORT
  324.  
  325. BOOL CCmdTarget::GetDispatchIID(IID*)
  326. {
  327.     // Subclass must implement (typically via COleControl implementation)
  328.     return FALSE;
  329. }
  330.  
  331. UINT CCmdTarget::GetTypeInfoCount()
  332. {
  333.     // Subclass must implement (typically via IMPLEMENT_OLETYPELIB macro)
  334.     return 0;
  335. }
  336.  
  337. CTypeLibCache* CCmdTarget::GetTypeLibCache()
  338. {
  339.     // Subclass must implement (typically via IMPLEMENT_OLETYPELIB macro)
  340.     return NULL;
  341. }
  342.  
  343. HRESULT CCmdTarget::GetTypeLib(LCID, LPTYPELIB*)
  344. {
  345.     // Subclass must implement (typically via IMPLEMENT_OLETYPELIB macro)
  346.     return TYPE_E_CANTLOADLIBRARY;
  347. }
  348.  
  349. #endif // !_AFX_NO_OLE_SUPPORT
  350.  
  351. /////////////////////////////////////////////////////////////////////////////
  352. // CCmdTarget routines that delegate to the WinApp
  353.  
  354. void CCmdTarget::BeginWaitCursor()
  355.     { AfxGetApp()->DoWaitCursor(1); }
  356. void CCmdTarget::EndWaitCursor()
  357.     { AfxGetApp()->DoWaitCursor(-1); }
  358. void CCmdTarget::RestoreWaitCursor()
  359.     { AfxGetApp()->DoWaitCursor(0); }
  360.  
  361. /////////////////////////////////////////////////////////////////////////////
  362. // Root of message maps
  363.  
  364. const AFX_DATADEF AFX_MSGMAP CCmdTarget::messageMap =
  365. {
  366. #ifdef _AFXDLL
  367.     &CCmdTarget::_GetBaseMessageMap,
  368. #else
  369.     NULL,
  370. #endif
  371.     &CCmdTarget::_messageEntries[0]
  372. };
  373.  
  374. #ifdef _AFXDLL
  375. const AFX_MSGMAP* CCmdTarget::_GetBaseMessageMap()
  376. {
  377.     return NULL;
  378. }
  379. #endif
  380.  
  381. const AFX_MSGMAP* CCmdTarget::GetMessageMap() const
  382. {
  383.     return &CCmdTarget::messageMap;
  384. }
  385.  
  386. const AFX_MSGMAP_ENTRY CCmdTarget::_messageEntries[] =
  387. {
  388.     { 0, 0, AfxSig_end, 0 }     // nothing here
  389. };
  390.  
  391. /////////////////////////////////////////////////////////////////////////////
  392. // Root of dispatch maps
  393.  
  394. #ifndef _AFX_NO_OLE_SUPPORT
  395.  
  396. UINT CCmdTarget::_dispatchEntryCount = (UINT)-1;
  397. DWORD CCmdTarget::_dwStockPropMask = (DWORD)-1;
  398.  
  399. const AFX_DISPMAP CCmdTarget::dispatchMap =
  400. {
  401. #ifdef _AFXDLL
  402.     &CCmdTarget::_GetBaseDispatchMap,
  403. #else
  404.     NULL,
  405. #endif
  406.     &CCmdTarget::_dispatchEntries[0],
  407.     &CCmdTarget::_dispatchEntryCount,
  408.     &CCmdTarget::_dwStockPropMask
  409. };
  410.  
  411. #ifdef _AFXDLL
  412. const AFX_DISPMAP* CCmdTarget::_GetBaseDispatchMap()
  413. {
  414.     return NULL;
  415. }
  416. #endif
  417.  
  418. const AFX_DISPMAP* CCmdTarget::GetDispatchMap() const
  419. {
  420.     return &CCmdTarget::dispatchMap;
  421. }
  422.  
  423. const AFX_DISPMAP_ENTRY CCmdTarget::_dispatchEntries[] =
  424. {
  425.     { NULL, -1, NULL, 0, (AFX_PMSG)NULL, (AFX_PMSG)NULL, (size_t)-1,
  426.       afxDispCustom }
  427.     // nothing here
  428. };
  429.  
  430. #endif //!_AFX_NO_OLE_SUPPORT
  431.  
  432. /////////////////////////////////////////////////////////////////////////////
  433. // Root of event sink maps
  434.  
  435. #ifndef _AFX_NO_OCC_SUPPORT
  436.  
  437. UINT CCmdTarget::_eventsinkEntryCount = (UINT)-1;
  438.  
  439. const AFX_EVENTSINKMAP CCmdTarget::eventsinkMap =
  440. {
  441. #ifdef _AFXDLL
  442.     &CCmdTarget::_GetBaseEventSinkMap,
  443. #else
  444.     NULL,
  445. #endif
  446.     &CCmdTarget::_eventsinkEntries[0],
  447.     &CCmdTarget::_eventsinkEntryCount
  448. };
  449.  
  450. #ifdef _AFXDLL
  451. const AFX_EVENTSINKMAP* CCmdTarget::_GetBaseEventSinkMap()
  452. {
  453.     return NULL;
  454. }
  455. #endif
  456.  
  457. const AFX_EVENTSINKMAP* CCmdTarget::GetEventSinkMap() const
  458. {
  459.     return &CCmdTarget::eventsinkMap;
  460. }
  461.  
  462. const AFX_EVENTSINKMAP_ENTRY CCmdTarget::_eventsinkEntries[] =
  463. {
  464.     { NULL, -1, NULL, 0, (AFX_PMSG)NULL, (AFX_PMSG)NULL, (size_t)-1,
  465.       afxDispCustom, (UINT)-1, (UINT)-1 }
  466.     // nothing here
  467. };
  468.  
  469. #endif //!_AFX_NO_OCC_SUPPORT
  470.  
  471. /////////////////////////////////////////////////////////////////////////////
  472. // Root of interface maps
  473.  
  474. #ifndef _AFX_NO_OLE_SUPPORT
  475.  
  476. #ifdef _AFXDLL
  477. const AFX_INTERFACEMAP* CCmdTarget::_GetBaseInterfaceMap()
  478. {
  479.     return NULL;
  480. }
  481. #endif
  482.  
  483. const AFX_INTERFACEMAP* CCmdTarget::GetInterfaceMap() const
  484. {
  485.     return &CCmdTarget::interfaceMap;
  486. }
  487.  
  488. const AFX_INTERFACEMAP CCmdTarget::interfaceMap =
  489. {
  490. #ifdef _AFXDLL
  491.     &CCmdTarget::_GetBaseInterfaceMap,
  492. #else
  493.     NULL,
  494. #endif
  495.     &CCmdTarget::_interfaceEntries[0]
  496. };
  497.  
  498. const AFX_INTERFACEMAP_ENTRY CCmdTarget::_interfaceEntries[] =
  499. {
  500. #ifndef _AFX_NO_OLE_SUPPORT
  501.     INTERFACE_PART(CCmdTarget, IID_IDispatch, Dispatch)
  502. #endif
  503.     { NULL, (size_t)-1 }    // end of entries
  504. };
  505.  
  506. void CCmdTarget::OnFinalRelease()
  507. {
  508. #ifndef _AFX_NO_OLE_SUPPORT
  509.     AfxLockGlobals(CRIT_TYPELIBCACHE);
  510.  
  511.     // release the typelib cache, if any
  512.     CTypeLibCache* pTypeLibCache = GetTypeLibCache();
  513.     if (pTypeLibCache != NULL)
  514.         pTypeLibCache->Unlock();
  515.  
  516.     AfxUnlockGlobals(CRIT_TYPELIBCACHE);
  517. #endif
  518.  
  519.     delete this;
  520. }
  521.  
  522. BOOL CCmdTarget::OnCreateAggregates()
  523. {
  524.     return TRUE;
  525. }
  526.  
  527. LPUNKNOWN CCmdTarget::GetInterfaceHook(const void*)
  528. {
  529.     return NULL;
  530. }
  531.  
  532. #endif //!_AFX_NO_OLE_SUPPORT
  533.  
  534. /////////////////////////////////////////////////////////////////////////////
  535. // Root of connection maps
  536.  
  537. #ifndef _AFX_NO_OLE_SUPPORT
  538.  
  539. #ifdef _AFXDLL
  540. const AFX_CONNECTIONMAP* CCmdTarget::_GetBaseConnectionMap()
  541. {
  542.     return NULL;
  543. }
  544. #endif
  545.  
  546. const AFX_CONNECTIONMAP* CCmdTarget::GetConnectionMap() const
  547. {
  548.     return &CCmdTarget::connectionMap;
  549. }
  550.  
  551. const AFX_CONNECTIONMAP CCmdTarget::connectionMap =
  552. {
  553. #ifdef _AFXDLL
  554.     &CCmdTarget::_GetBaseConnectionMap,
  555. #else
  556.     NULL,
  557. #endif
  558.     &CCmdTarget::_connectionEntries[0]
  559. };
  560.  
  561. const AFX_CONNECTIONMAP_ENTRY CCmdTarget::_connectionEntries[] =
  562. {
  563.     { NULL, (size_t)-1 }    // end of entries
  564. };
  565.  
  566. LPCONNECTIONPOINT CCmdTarget::GetConnectionHook(const IID&)
  567. {
  568.     return NULL;
  569. }
  570.  
  571. BOOL CCmdTarget::GetExtraConnectionPoints(CPtrArray*)
  572. {
  573.     return FALSE;
  574. }
  575.  
  576. #endif //!_AFX_NO_OLE_SUPPORT
  577.  
  578. /////////////////////////////////////////////////////////////////////////////
  579. // Root of command target maps
  580.  
  581. #ifndef _AFX_NO_DOCOBJECT_SUPPORT
  582.  
  583. #ifdef _AFXDLL
  584. const AFX_OLECMDMAP* CCmdTarget::_GetBaseCommandMap()
  585. {
  586.     return NULL;
  587. }
  588. #endif
  589.  
  590. const AFX_OLECMDMAP CCmdTarget::commandMap =
  591. {
  592. #ifdef _AFXDLL
  593.     &CCmdTarget::_GetBaseCommandMap,
  594. #else
  595.     NULL,
  596. #endif
  597.     &CCmdTarget::_commandEntries[0]
  598. };
  599.  
  600. const AFX_OLECMDMAP_ENTRY CCmdTarget::_commandEntries[] =
  601. {
  602.     { NULL, 0, 0 }    // end of entries
  603. };
  604.  
  605. const AFX_OLECMDMAP* CCmdTarget::GetCommandMap() const
  606. {
  607.     return &CCmdTarget::commandMap;
  608. }
  609.  
  610. #endif //!_AFX_NO_DOCOBJECT_SUPPORT
  611.  
  612. /////////////////////////////////////////////////////////////////////////////
  613. // Special access to view routing info
  614.  
  615. CView* CCmdTarget::GetRoutingView()
  616. {
  617.     return GetRoutingView_();
  618. }
  619.  
  620. CFrameWnd* CCmdTarget::GetRoutingFrame()
  621. {
  622.     return GetRoutingFrame_();
  623. }
  624.  
  625. /////////////////////////////////////////////////////////////////////////////
  626. // CCmdUI - User Interface for a command
  627.  
  628. // CCmdUI is a protocol class for all command handler variants
  629. //      CCmdUI is an implementation class for menus and general dialog
  630. //        controls (usually buttons)
  631.  
  632. CCmdUI::CCmdUI()
  633. {
  634.     // zero out everything
  635.     m_nID = m_nIndex = m_nIndexMax = 0;
  636.     m_pMenu = m_pSubMenu = m_pParentMenu = NULL;
  637.     m_pOther = NULL;
  638.     m_bEnableChanged = m_bContinueRouting = FALSE;
  639. }
  640.  
  641. // default CCmdUI implementation only works for Menu Items
  642. void CCmdUI::Enable(BOOL bOn)
  643. {
  644.     if (m_pMenu != NULL)
  645.     {
  646.         if (m_pSubMenu != NULL)
  647.             return; // don't change popup menus indirectly
  648.  
  649.         ASSERT(m_nIndex < m_nIndexMax);
  650.         m_pMenu->EnableMenuItem(m_nIndex, MF_BYPOSITION |
  651.             (bOn ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
  652.     }
  653.     else
  654.     {
  655.         // enable/disable a control (i.e. child window)
  656.         ASSERT(m_pOther != NULL);
  657.  
  658.         // if control has the focus, move the focus before disabling
  659.         if (!bOn && (::GetFocus() == m_pOther->m_hWnd))
  660.             m_pOther->GetParent()->GetNextDlgTabItem(m_pOther)->SetFocus();
  661.         m_pOther->EnableWindow(bOn);
  662.     }
  663.     m_bEnableChanged = TRUE;
  664. }
  665.  
  666. void CCmdUI::SetCheck(int nCheck)
  667. {
  668.     if (m_pMenu != NULL)
  669.     {
  670.         if (m_pSubMenu != NULL)
  671.             return; // don't change popup menus indirectly
  672.  
  673.         // place checkmark next to menu item
  674.         ASSERT(m_nIndex < m_nIndexMax);
  675.         m_pMenu->CheckMenuItem(m_nIndex, MF_BYPOSITION |
  676.             (nCheck ? MF_CHECKED : MF_UNCHECKED));
  677.     }
  678.     else
  679.     {
  680.         // we can only check buttons or controls acting like buttons
  681.         ASSERT(m_pOther != NULL);
  682.         if (m_pOther->SendMessage(WM_GETDLGCODE) & DLGC_BUTTON)
  683.             m_pOther->SendMessage(BM_SETCHECK, nCheck);
  684.         // otherwise ignore it
  685.     }
  686. }
  687.  
  688. AFX_STATIC void AFXAPI _AfxLoadDotBitmap(); // for swap tuning
  689.  
  690. void CCmdUI::SetRadio(BOOL bOn)
  691. {
  692.     SetCheck(bOn ? 1 : 0); // this default works for most things as well
  693.     if (m_pMenu != NULL)
  694.     {
  695.         if (m_pSubMenu != NULL)
  696.             return; // don't change popup menus indirectly
  697.  
  698.         // for menu item - use dot instead of checkmark
  699.         ASSERT(m_nIndex < m_nIndexMax);
  700.  
  701.         if (afxData.hbmMenuDot == NULL)
  702.             _AfxLoadDotBitmap();    // in INIT segment
  703.  
  704.         if (afxData.hbmMenuDot != NULL)
  705.             SetMenuItemBitmaps(m_pMenu->m_hMenu, m_nIndex, MF_BYPOSITION,
  706.                 NULL, afxData.hbmMenuDot);
  707.     }
  708. }
  709.  
  710. void CCmdUI::SetText(LPCTSTR lpszText)
  711. {
  712.     ASSERT(lpszText != NULL);
  713.     ASSERT(AfxIsValidString(lpszText));
  714.  
  715.     if (m_pMenu != NULL)
  716.     {
  717.         if (m_pSubMenu != NULL)
  718.             return; // don't change popup menus indirectly
  719.  
  720.         // get current menu state so it doesn't change
  721.         UINT nState = m_pMenu->GetMenuState(m_nIndex, MF_BYPOSITION);
  722.         nState &= ~(MF_BITMAP|MF_OWNERDRAW|MF_SEPARATOR);
  723.  
  724.         // set menu text
  725.         ASSERT(m_nIndex < m_nIndexMax);
  726.         VERIFY(m_pMenu->ModifyMenu(m_nIndex, MF_BYPOSITION |
  727.             MF_STRING | nState, m_nID, lpszText));
  728.     }
  729.     else
  730.     {
  731.         ASSERT(m_pOther != NULL);
  732.         AfxSetWindowText(m_pOther->m_hWnd, lpszText);
  733.     }
  734. }
  735.  
  736. BOOL CCmdUI::DoUpdate(CCmdTarget* pTarget, BOOL bDisableIfNoHndler)
  737. {
  738.     ASSERT_VALID(pTarget);
  739.  
  740.     if (m_nID == 0 || LOWORD(m_nID) == 0xFFFF)
  741.         return TRUE;     // ignore invalid IDs
  742.  
  743.     m_bEnableChanged = FALSE;
  744.     BOOL bResult = pTarget->OnCmdMsg(m_nID, CN_UPDATE_COMMAND_UI, this, NULL);
  745.     if (!bResult)
  746.         ASSERT(!m_bEnableChanged); // not routed
  747.  
  748.     if (bDisableIfNoHndler && !m_bEnableChanged)
  749.     {
  750.         AFX_CMDHANDLERINFO info;
  751.         info.pTarget = NULL;
  752.         BOOL bHandler = pTarget->OnCmdMsg(m_nID, CN_COMMAND, this, &info);
  753.  
  754. #ifdef _DEBUG
  755.         if ((afxTraceFlags & traceCmdRouting) && !bHandler)
  756.             TRACE1("No handler for command ID 0x%04X, disabling it.\n", m_nID);
  757. #endif
  758.         // Enable or Disable based on whether there is a handler there
  759.         Enable(bHandler);
  760.     }
  761.     return bResult;
  762. }
  763.  
  764. /////////////////////////////////////////////////////////////////////////////
  765. // Special init
  766.  
  767. #ifdef AFX_INIT_SEG
  768. #pragma code_seg(AFX_INIT_SEG)
  769. #endif
  770.  
  771. AFX_STATIC_DATA const BYTE _afxDot[] =
  772.     { 0x6, 0xF, 0xF, 0xF, 0x6 }; // simple byte bitmap, 1=> bit on
  773. #define DOT_WIDTH   4
  774. #define DOT_HEIGHT  5
  775.  
  776. AFX_STATIC void AFXAPI _AfxLoadDotBitmap()
  777. {
  778.     ASSERT(afxData.hbmMenuDot == NULL);
  779.     // attempt to load special bitmap, else default to arrow
  780.     CSize size = ::GetMenuCheckMarkDimensions();
  781.     ASSERT(size.cx > 4 && size.cy > 5); // not too small please
  782.     if (size.cx > 32)
  783.         size.cx = 32;
  784.     int iwRow = (size.cx + 15) >> 4;    // # of WORDs per raster line
  785.     int nShift = (size.cx - DOT_WIDTH) / 2;     // # of bits to shift over
  786.     nShift += ((iwRow * 16) - size.cx); // padding for word alignment
  787.     if (nShift > 16 - DOT_WIDTH)
  788.         nShift = 16 - DOT_WIDTH;    // maximum shift for 1 word
  789.  
  790.     if (size.cy > 32)
  791.         size.cy = 32;
  792.  
  793.     // bitmap 2/4/4/4/2 pixels wide - centered (0 => black)
  794.     BYTE rgbBitmap[32 * 2 * sizeof(WORD)];
  795.     memset(rgbBitmap, 0xff, sizeof(rgbBitmap));
  796.  
  797.     BYTE* pbOut = &rgbBitmap[iwRow * sizeof(WORD) *
  798.                             ((size.cy - (DOT_HEIGHT+1)) >> 1)];
  799.     const BYTE* pbIn = _afxDot;
  800.     for (int y = 0; y < DOT_HEIGHT; y++)
  801.     {
  802.         WORD w = (WORD)~(((DWORD)*pbIn++) << nShift);
  803.         // bitmaps are always hi-lo
  804.         pbOut[0] = HIBYTE(w);
  805.         pbOut[1] = LOBYTE(w);
  806.         pbOut += iwRow * sizeof(WORD);
  807.     }
  808.  
  809.     afxData.hbmMenuDot = ::CreateBitmap(size.cx, size.cy, 1, 1,
  810.             (LPVOID)&rgbBitmap);
  811.     if (afxData.hbmMenuDot == NULL)
  812.     {
  813.         TRACE0("Warning: using system arrow bitmap instead of dot.\n");
  814.         #define OBM_MNARROW         32739
  815.         afxData.hbmMenuDot = ::LoadBitmap(NULL, MAKEINTRESOURCE(OBM_MNARROW));
  816.     }
  817. }
  818.  
  819. /////////////////////////////////////////////////////////////////////////////
  820. // CCmdTarget diagnostics
  821.  
  822. #ifdef _DEBUG
  823. void CCmdTarget::Dump(CDumpContext& dc) const
  824. {
  825.     CObject::Dump(dc);
  826.  
  827. #ifndef _AFX_NO_OLE_SUPPORT
  828.     if (m_xDispatch.m_vtbl != 0)
  829.     {
  830.         dc << "with IDispatch (OLE Automation) capability\n";
  831.         dc << "m_bResultExpected = " << m_bResultExpected << "\n";
  832.     }
  833.     if (m_xConnPtContainer.m_vtbl != 0)
  834.     {
  835.         dc << "with OLE Connection Point capability\n";
  836.     }
  837.     if (GetInterfaceMap() != &CCmdTarget::interfaceMap)
  838.     {
  839.         dc << "with OLE capability";
  840.         dc << "\nm_dwRef = " << m_dwRef;
  841.         dc << "\nm_pOuterUnknown = " << m_pOuterUnknown;
  842.         if (m_xInnerUnknown != 0)
  843.             dc << "\nwith aggregation capability";
  844.         dc << "\n";
  845.     }
  846. #endif //!_AFX_NO_OLE_SUPPORT
  847. }
  848.  
  849. void CCmdTarget::AssertValid() const
  850. {
  851.     CObject::AssertValid();
  852. }
  853. #endif
  854.  
  855. #ifdef AFX_INIT_SEG
  856. #pragma code_seg(AFX_INIT_SEG)
  857. #endif
  858.  
  859. IMPLEMENT_DYNAMIC(CCmdTarget, CObject)
  860.  
  861. /////////////////////////////////////////////////////////////////////////////
  862.