cmdtarg.cpp 21 KB

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