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