menusite.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 13k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. #include "priv.h"
  2. #include "sccls.h"
  3. #include "menusite.h"
  4. #include "inpobj.h"
  5. CMenuSite::CMenuSite() : _cRef(1)
  6. {
  7. }
  8. CMenuSite::~CMenuSite()
  9. {
  10.     // Make sure that SetDeskBarSite(NULL) was called
  11.     ASSERT(_punkSite == NULL);
  12.     ASSERT(_punkSubActive == NULL);
  13.     ASSERT(_pweh == NULL);
  14.     ASSERT(_pdb == NULL);
  15.     ASSERT(_hwnd == NULL);
  16. }
  17. STDAPI CMenuBandSite_CreateInstance(IUnknown* pUnkOuter, IUnknown** ppunk, LPCOBJECTINFO poi)
  18. {
  19.     CMenuSite *pbs = new CMenuSite();
  20.     if (pbs)
  21.     {
  22.         *ppunk = SAFECAST(pbs, IOleWindow*);
  23.         return S_OK;
  24.     }
  25.     *ppunk = NULL;
  26.     return E_OUTOFMEMORY;
  27. }
  28. /*----------------------------------------------------------
  29. Purpose: IUnknown::QueryInterface method
  30. */
  31. STDMETHODIMP CMenuSite::QueryInterface(REFIID riid, LPVOID * ppvObj)
  32. {
  33.     static const QITAB qit[] = {
  34.         QITABENT(CMenuSite, IBandSite),
  35.         QITABENT(CMenuSite, IDeskBarClient),
  36.         QITABENT(CMenuSite, IOleCommandTarget),
  37.         QITABENT(CMenuSite, IInputObject),
  38.         QITABENT(CMenuSite, IInputObjectSite),
  39.         QITABENT(CMenuSite, IWinEventHandler),
  40.         QITABENT(CMenuSite, IServiceProvider),
  41.         QITABENT(CMenuSite, IOleWindow),
  42.         { 0 },
  43.     };
  44.     return QISearch(this, qit, riid, ppvObj);
  45. }
  46. /*----------------------------------------------------------
  47. Purpose: IUnknown::AddRef method
  48. */
  49. STDMETHODIMP_(ULONG) CMenuSite::AddRef(void)
  50. {
  51.     _cRef++;
  52.     return _cRef;
  53. }
  54. /*----------------------------------------------------------
  55. Purpose: IUnknown::Release method
  56. */
  57. STDMETHODIMP_(ULONG) CMenuSite::Release()
  58. {
  59.     ASSERT(_cRef > 0);
  60.     _cRef--;
  61.     if (_cRef > 0)
  62.         return _cRef;
  63.     delete this;
  64.     return 0;
  65. }
  66. /*----------------------------------------------------------
  67. Purpose: IServiceProvider::QueryService method
  68. */
  69. STDMETHODIMP CMenuSite::QueryService(REFGUID guidService, REFIID riid, void **ppvObj)
  70. {
  71.     HRESULT hres = E_FAIL;
  72.     *ppvObj = NULL;     // assume error
  73.     if (IsEqualIID(guidService, SID_SMenuBandBottom) ||
  74.         IsEqualIID(guidService, SID_SMenuBandBottomSelected)||
  75.         IsEqualIID(guidService, SID_SMenuBandChild))
  76.     {
  77.         if (_punkSubActive)
  78.             hres = IUnknown_QueryService(_punkSubActive, guidService, riid, ppvObj);
  79.     }
  80.     else
  81.     {
  82.         ASSERT(_punkSite);
  83.         hres = IUnknown_QueryService(_punkSite, guidService, riid, ppvObj);
  84.     }
  85.     return hres;
  86. }    
  87. /*----------------------------------------------------------
  88. Purpose: IOleCommandTarget::QueryStatus
  89. */
  90. STDMETHODIMP CMenuSite::QueryStatus(const GUID *pguidCmdGroup,
  91.         ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT *pcmdtext)
  92. {
  93.     ASSERT(_punkSite);
  94.     return IUnknown_QueryStatus(_punkSite, pguidCmdGroup, cCmds, rgCmds, pcmdtext);
  95. }
  96. /*----------------------------------------------------------
  97. Purpose: IOleCommandTarget::Exec
  98. */
  99. STDMETHODIMP CMenuSite::Exec(const GUID *pguidCmdGroup,
  100.         DWORD nCmdID, DWORD nCmdexecopt,
  101.         VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  102. {
  103.     ASSERT(_punkSite);
  104.     return IUnknown_Exec(_punkSite, pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  105. }
  106. /*----------------------------------------------------------
  107. Purpose: IInputObjectSite::OnFocusChangeIS
  108.          This function is called by the client band to negotiate
  109.          which band in this bandsite gets the focus.  Typically
  110.          this function will then change its focus to the given
  111.          client band.
  112.          CMenuSite only maintains one and only one band, which
  113.          is set at AddBand time, so this function is a nop.
  114. */
  115. STDMETHODIMP CMenuSite::OnFocusChangeIS(IUnknown *punk, BOOL fSetFocus)
  116. {
  117.     // Return S_OK since the menu site only ever has one band.
  118.     // No need to negotiate which other band in this bandsite 
  119.     // might have the "activation".
  120.     return S_OK;
  121. }
  122. /*----------------------------------------------------------
  123. Purpose: IInputObject::UIActivateIO method
  124. */
  125. STDMETHODIMP CMenuSite::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
  126. {
  127.     ASSERT(NULL == lpMsg || IS_VALID_WRITE_PTR(lpMsg, MSG));
  128.     // Forward onto the client band
  129.     return UnkUIActivateIO(_punkSubActive, fActivate, lpMsg);
  130. }
  131. /*----------------------------------------------------------
  132. Purpose: IInputObject::HasFocusIO
  133.          Since the menuband can never have true activation (from
  134.          the browser's perspective) this always returns S_FALSE.
  135.          See comments in CMenuBand::UIActivateIO for more details
  136.          about this.
  137. */
  138. STDMETHODIMP CMenuSite::HasFocusIO()
  139. {
  140.     return S_FALSE;
  141. }
  142. /*----------------------------------------------------------
  143. Purpose: IInputObject::TranslateAcceleratorIO
  144.          Menubands cannot ever have the activation, so this method 
  145.          should never be called.
  146. */
  147. STDMETHODIMP CMenuSite::TranslateAcceleratorIO(LPMSG lpMsg)
  148. {
  149.     AssertMsg(0, TEXT("Menuband has the activation but it shouldn't!"));
  150.     return S_FALSE;
  151. }
  152. // Utility Functions
  153. void CMenuSite::_CacheSubActiveBand(IUnknown * punk)
  154. {
  155.     if (SHIsSameObject(punk, _punkSubActive))
  156.         return;
  157.     
  158.     IUnknown_SetSite(_punkSubActive, NULL);
  159.     ATOMICRELEASE(_punkSubActive);
  160.     ATOMICRELEASE(_pdb);
  161.     ATOMICRELEASE(_pweh);
  162.     _hwndChild = NULL;
  163.     if (punk != NULL) 
  164.     {
  165.         EVAL(SUCCEEDED(punk->QueryInterface(IID_IDeskBand, (void **)&_pdb)));
  166.         EVAL(SUCCEEDED(punk->QueryInterface(IID_IWinEventHandler, (void**)&_pweh)));
  167.         IUnknown_SetSite(punk, SAFECAST(this, IOleWindow*));
  168.         IUnknown_GetWindow(punk, &_hwndChild);
  169.         _punkSubActive = punk;
  170.         _punkSubActive->AddRef();
  171.     }
  172. }
  173. /*----------------------------------------------------------
  174. Purpose: IBandSite::AddBand
  175. */
  176. STDMETHODIMP CMenuSite::AddBand(IUnknown* punk)
  177. {
  178.     _CacheSubActiveBand(punk);
  179.     return NOERROR;
  180. }
  181. /*----------------------------------------------------------
  182. Purpose: IBandSite::EnumBands
  183. */
  184. STDMETHODIMP CMenuSite::EnumBands(UINT uBand, DWORD* pdwBandID)
  185. {
  186.     HRESULT hres = NOERROR;
  187.     // The menusite only holds one band ever
  188.     if (0 == uBand)
  189.         *pdwBandID = 0;
  190.     else
  191.         hres = E_FAIL;
  192.     return hres;
  193. }
  194. /*----------------------------------------------------------
  195. Purpose: IBandSite::QueryBand
  196. */
  197. HRESULT CMenuSite::QueryBand(DWORD dwBandID, IDeskBand** ppstb, DWORD* pdwState, LPWSTR pszName, int cchName)
  198. {
  199.     HRESULT hres = E_NOINTERFACE;
  200.     ASSERT(dwBandID == 0);
  201.     ASSERT(IS_VALID_WRITE_PTR(ppstb, IDeskBand *));
  202.     if (_punkSubActive && 0 == dwBandID)
  203.     {
  204.         hres = _punkSubActive->QueryInterface(IID_IDeskBand, (void**)ppstb);
  205.         *pdwState = BSSF_VISIBLE; // Only band....
  206.         if (cchName > 0)
  207.             *pszName = L'';
  208.     }
  209.     else
  210.         *ppstb = NULL;
  211.     return hres;
  212. }
  213. /*----------------------------------------------------------
  214. Purpose: IBandSite::SetBandState
  215. */
  216. HRESULT CMenuSite::SetBandState(DWORD dwBandID, DWORD dwMask, DWORD dwState)
  217. {
  218.     return E_NOTIMPL;
  219. }
  220. /*----------------------------------------------------------
  221. Purpose: IBandSite::RemoveBand
  222. */
  223. HRESULT CMenuSite::RemoveBand(DWORD dwBandID)
  224. {
  225.     return E_NOTIMPL;
  226. }
  227. /*----------------------------------------------------------
  228. Purpose: IBandSite::GetBandObject
  229. */
  230. HRESULT CMenuSite::GetBandObject(DWORD dwBandID, REFIID riid, LPVOID *ppvObj)
  231. {
  232.     HRESULT hres;
  233.     ASSERT(dwBandID == 0);
  234.     if (_punkSubActive && 0 == dwBandID)
  235.         hres = _punkSubActive->QueryInterface(riid, ppvObj);
  236.     else
  237.     {
  238.         *ppvObj = NULL;
  239.         hres = E_NOINTERFACE;
  240.     }
  241.     return hres;
  242. }
  243. /*----------------------------------------------------------
  244. Purpose: IBandSite::SetBandSiteInfo
  245. */
  246. HRESULT CMenuSite::SetBandSiteInfo(const BANDSITEINFO * pbsinfo)
  247. {
  248.     return E_NOTIMPL;
  249. }
  250. /*----------------------------------------------------------
  251. Purpose: IBandSite::GetBandSiteInfo
  252. */
  253. HRESULT CMenuSite::GetBandSiteInfo(BANDSITEINFO * pbsinfo)
  254. {
  255.     return E_NOTIMPL;
  256. }
  257. /*----------------------------------------------------------
  258. Purpose: IOleWindow::GetWindow
  259. */
  260. HRESULT CMenuSite::GetWindow(HWND * lphwnd)
  261. {
  262.     ASSERT(IS_VALID_HANDLE(_hwnd, WND));
  263.     *lphwnd = _hwnd;
  264.     return NOERROR;
  265. }
  266. /*----------------------------------------------------------
  267. Purpose: IOleWindow::ContextSensitiveHelp
  268. */
  269. HRESULT CMenuSite::ContextSensitiveHelp(BOOL fEnterMode)
  270. {
  271.     return E_NOTIMPL;
  272. }
  273. /*----------------------------------------------------------
  274. Purpose: IDeskBarClient::SetDeskBarSite
  275. */
  276. HRESULT CMenuSite::SetDeskBarSite(IUnknown* punkSite)
  277. {
  278.     ATOMICRELEASE(_punkSite);
  279.     if (punkSite)
  280.     {
  281.         HWND hwnd;
  282.         IUnknown_GetWindow(punkSite, &hwnd);
  283.         if (hwnd)
  284.         {
  285.             _CreateSite(hwnd);
  286.             _punkSite = punkSite;
  287.             _punkSite->AddRef();
  288.         }
  289.     }
  290.     else
  291.     {
  292.         _pdb->CloseDW(0);
  293.         _CacheSubActiveBand(NULL);      // This is asymetric by design
  294.         if (_hwnd)
  295.         {
  296.             DestroyWindow(_hwnd);
  297.             _hwnd = NULL;
  298.         }
  299.     }
  300.     return _hwnd ? NOERROR : E_FAIL;
  301. }
  302. /*----------------------------------------------------------
  303. Purpose: IDeskBarClient::SetModeDBC
  304. */
  305. HRESULT CMenuSite::SetModeDBC(DWORD dwMode)
  306. {
  307.     return E_NOTIMPL;
  308. }
  309. /*----------------------------------------------------------
  310. Purpose: IDeskBarClient::UIActivateDBC
  311. */
  312. HRESULT CMenuSite::UIActivateDBC(DWORD dwState)
  313. {
  314.     ASSERT(_pdb);
  315.     if (_pdb)
  316.         _pdb->ShowDW(0 != dwState);
  317.     return NOERROR;
  318. }
  319. /*----------------------------------------------------------
  320. Purpose: IDeskBarClient::GetSize
  321. */
  322. HRESULT CMenuSite::GetSize(DWORD dwWhich, LPRECT prc)
  323. {
  324.     if (dwWhich == DBC_GS_IDEAL)
  325.     {
  326.         if (_pdb)
  327.         {
  328.             DESKBANDINFO dbi = {0};
  329.             _pdb->GetBandInfo(0, 0, &dbi);
  330.             prc->right = dbi.ptMaxSize.x;
  331.             prc->bottom = dbi.ptMaxSize.y;
  332.         }
  333.     }
  334.     return NOERROR;
  335. }
  336. /*----------------------------------------------------------
  337. Purpose: IWinEventHandler::OnWinEvent
  338. */
  339. HRESULT CMenuSite::OnWinEvent(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* plres)
  340. {
  341.     if (_pweh)
  342.         return _pweh->OnWinEvent(hwnd, uMsg, wParam, lParam, plres);
  343.     return NOERROR;
  344. }
  345. /*----------------------------------------------------------
  346. Purpose: IWinEventHandler::IsWindowOwner
  347. */
  348. HRESULT CMenuSite::IsWindowOwner(HWND hwnd)
  349. {
  350.     if (_hwnd == hwnd || (_pweh && _pweh->IsWindowOwner(hwnd) != S_FALSE))
  351.         return S_OK;
  352.     else
  353.         return S_FALSE;
  354. }
  355. LRESULT CMenuSite::v_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  356. {
  357.     LRESULT lres = 0;
  358.     EnterModeless();
  359.     switch(uMsg)
  360.     {
  361.     case WM_SIZE:
  362.         {
  363.             IMenuPopup* pmp;
  364.             if (_punkSubActive && SUCCEEDED(_punkSubActive->QueryInterface(IID_IMenuPopup, (void**)&pmp)))
  365.             {
  366.                 RECT rc = {0};
  367.                 GetClientRect(_hwnd, &rc);
  368.                 pmp->OnPosRectChangeDB(&rc);
  369.                 pmp->Release();
  370.             }
  371.             lres = 1;
  372.         }
  373.         break;
  374.     case WM_NOTIFY:
  375.         hwnd = ((LPNMHDR)lParam)->hwndFrom;
  376.         break;
  377.         
  378.     case WM_COMMAND:
  379.         hwnd = GET_WM_COMMAND_HWND(wParam, lParam);
  380.         break;
  381.         
  382.     default:
  383.         ExitModeless();
  384.         return DefWindowProcWrap(hwnd, uMsg, wParam, lParam);
  385.         break;
  386.     }
  387.     if (hwnd && _pweh && _pweh->IsWindowOwner(hwnd) == S_OK) 
  388.     {
  389.         _pweh->OnWinEvent(hwnd, uMsg, wParam, lParam, &lres);
  390.     }
  391.     ExitModeless();
  392.     return lres;
  393. }
  394. void CMenuSite::_CreateSite(HWND hwndParent)
  395. {
  396.     if (_hwnd)
  397.     {
  398.         ASSERT(IS_VALID_HANDLE(_hwnd, WND));    // just to be safe...
  399.         return;
  400.     }
  401.     WNDCLASS  wc = {0};
  402.     wc.style            = 0;
  403.     wc.lpfnWndProc      = s_WndProc;
  404.     //wc.cbClsExtra       = 0;
  405.     wc.cbWndExtra       = SIZEOF(CMenuSite*);
  406.     wc.hInstance        = HINST_THISDLL;
  407.     wc.hCursor          = LoadCursor(NULL, IDC_ARROW);
  408.     wc.hbrBackground    = (HBRUSH) (COLOR_MENU+1);
  409.     //wc.lpszMenuName     =  NULL;
  410.     wc.lpszClassName    = TEXT("MenuSite");
  411.     //wc.hIcon            = NULL;
  412.     SHRegisterClass(&wc);
  413.     _hwnd = CreateWindow(TEXT("MenuSite"), NULL, WS_VISIBLE | WS_CHILD, 0, 0, 0, 0, 
  414.         hwndParent, NULL, HINST_THISDLL, (LPVOID)SAFECAST(this, CImpWndProc*));
  415.     ASSERT(_hwnd);
  416. }