Author: dquintana
Date: Wed Feb 19 20:35:50 2014
New Revision: 62259
URL:
http://svn.reactos.org/svn/reactos?rev=62259&view=rev
Log:
[RSHELL]
* CMenuDeskBar: Use the submenu pointer to pass on the cancel events. Windows appears to
call this with code=2 (cancellevel).
* CMenuBand: Begin implementing a focus manager for the menu windows. This class will take
care of handling mouse and keyboard interactions, including closing the start menu and
submenus when the user clicks outside the menu window.
CORE-7881
Modified:
branches/shell-experiments/base/shell/rshell/CMenuBand.cpp
branches/shell-experiments/base/shell/rshell/CMenuDeskBar.cpp
branches/shell-experiments/base/shell/rshell/precomp.h
Modified: branches/shell-experiments/base/shell/rshell/CMenuBand.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/shell-experiments/base/shell/rs…
==============================================================================
--- branches/shell-experiments/base/shell/rshell/CMenuBand.cpp [iso-8859-1] (original)
+++ branches/shell-experiments/base/shell/rshell/CMenuBand.cpp [iso-8859-1] Wed Feb 19
20:35:50 2014
@@ -31,6 +31,7 @@
extern "C" BOOL WINAPI Shell_GetImageLists(HIMAGELIST * lpBigList, HIMAGELIST *
lpSmallList);
class CMenuBand;
+class CMenuFocusManager;
class CMenuToolbarBase
{
@@ -149,6 +150,8 @@
BOOL m_useBigIcons;
HWND m_topLevelWindow;
+
+ CMenuFocusManager * m_focusManager;
public:
@@ -237,6 +240,7 @@
HRESULT CallCBWithId(UINT Id, UINT uMsg, WPARAM wParam, LPARAM lParam);
HRESULT CallCBWithPidl(LPITEMIDLIST pidl, UINT uMsg, WPARAM wParam, LPARAM lParam);
HRESULT TrackPopup(HMENU popup, INT x, INT y);
+ HRESULT GetTopLevelWindow(HWND*topLevel);
BOOL UseBigIcons() {
return m_useBigIcons;
@@ -268,6 +272,261 @@
HRESULT _CallCB(UINT uMsg, WPARAM wParam, LPARAM lParam, UINT id = 0, LPITEMIDLIST
pidl = NULL);
};
+class CMenuFocusManager :
+ public CComCoClass<CMenuFocusManager>,
+ public CComObjectRootEx<CComMultiThreadModelNoCS>
+{
+private:
+ static DWORD TlsIndex;
+
+ static CMenuFocusManager * GetManager()
+ {
+ return reinterpret_cast<CMenuFocusManager *>(TlsGetValue(TlsIndex));
+ }
+
+public:
+ static CMenuFocusManager * AcquireManager()
+ {
+ CMenuFocusManager * obj = NULL;
+
+ if (!TlsIndex)
+ {
+ if ((TlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
+ return NULL;
+ }
+
+ obj = GetManager();
+
+ if (!obj)
+ {
+ obj = new CComObject<CMenuFocusManager>();
+ TlsSetValue(TlsIndex, obj);
+ }
+
+ obj->AddRef();
+
+ return obj;
+ }
+
+ static void ReleaseManager(CMenuFocusManager * obj)
+ {
+ if (!obj->Release())
+ {
+ TlsSetValue(TlsIndex, NULL);
+ }
+ }
+
+private:
+ static LRESULT CALLBACK s_GetMsgHook(INT nCode, WPARAM wParam, LPARAM lParam)
+ {
+ return GetManager()->GetMsgHook(nCode, wParam, lParam);
+ }
+
+private:
+ // TODO: make dynamic
+#define MAX_RECURSE 100
+ CMenuBand* m_bandStack[MAX_RECURSE];
+ int m_bandCount;
+
+ HRESULT PushToArray(CMenuBand * item)
+ {
+ if (m_bandCount >= MAX_RECURSE)
+ return E_OUTOFMEMORY;
+
+ m_bandStack[m_bandCount++] = item;
+ return S_OK;
+ }
+
+ HRESULT PopFromArray(CMenuBand ** pItem)
+ {
+ if (pItem)
+ *pItem = NULL;
+
+ if (m_bandCount <= 0)
+ return E_FAIL;
+
+ m_bandCount--;
+
+ if (pItem)
+ *pItem = m_bandStack[m_bandCount];
+
+ return S_OK;
+ }
+
+ HRESULT PeekArray(CMenuBand ** pItem)
+ {
+ if (!pItem)
+ return E_FAIL;
+
+ *pItem = NULL;
+
+ if (m_bandCount <= 0)
+ return E_FAIL;
+
+ *pItem = m_bandStack[m_bandCount - 1];
+
+ return S_OK;
+ }
+
+protected:
+ CMenuFocusManager() :
+ m_currentBand(NULL),
+ m_currentFocus(NULL),
+ m_bandCount(0)
+ {
+ m_threadId = GetCurrentThreadId();
+ }
+
+ ~CMenuFocusManager()
+ {
+ }
+
+public:
+
+ DECLARE_NOT_AGGREGATABLE(CMenuFocusManager)
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+ BEGIN_COM_MAP(CMenuFocusManager)
+ END_COM_MAP()
+
+private:
+ CMenuBand * m_currentBand;
+ HWND m_currentFocus;
+ HHOOK m_hHook;
+ DWORD m_threadId;
+
+ LRESULT GetMsgHook(INT nCode, WPARAM wParam, LPARAM lParam)
+ {
+ if (nCode < 0)
+ return CallNextHookEx(m_hHook, nCode, wParam, lParam);
+
+ BOOL callNext = TRUE;
+ BOOL fRemoved = wParam;
+ MSG* msg = reinterpret_cast<MSG*>(lParam);
+
+ if (nCode == HC_ACTION)
+ {
+ // Do whatever is necessary here
+
+ switch (msg->message)
+ {
+ case WM_CLOSE:
+ break;
+ case WM_SYSKEYDOWN:
+ case WM_KEYDOWN:
+ switch (msg->wParam)
+ {
+ case VK_MENU:
+ case VK_LMENU:
+ case VK_RMENU:
+ m_currentBand->OnSelect(MPOS_FULLCANCEL);
+ break;
+ case VK_LEFT:
+ m_currentBand->OnSelect(MPOS_SELECTLEFT);
+ break;
+ case VK_RIGHT:
+ m_currentBand->OnSelect(MPOS_SELECTRIGHT);
+ break;
+ case VK_UP:
+ //m_currentBand->ChildTrack(VK_UP);
+ break;
+ case VK_DOWN:
+ //m_currentBand->ChildTrack(VK_DOWN);
+ break;
+ }
+ break;
+ case WM_CHAR:
+ //if (msg->wParam >= 'a' && msg->wParam <=
'z')
+ //{
+ // callNext = FALSE;
+ // PostMessage(m_currentFocus, WM_SYSCHAR, wParam, lParam);
+ //}
+ break;
+ case WM_ACTIVATE:
+ break;
+
+ }
+
+ if (!callNext)
+ return 0;
+ }
+
+ return CallNextHookEx(m_hHook, nCode, wParam, lParam);
+ }
+
+ HRESULT PlaceHooks(HWND window)
+ {
+ //SetCapture(window);
+ m_hHook = SetWindowsHookEx(WH_GETMESSAGE, s_GetMsgHook, NULL, m_threadId);
+ return S_OK;
+ }
+
+ HRESULT RemoveHooks(HWND window)
+ {
+ UnhookWindowsHookEx(m_hHook);
+ //ReleaseCapture();
+ return S_OK;
+ }
+
+ HRESULT UpdateFocus(CMenuBand * newBand)
+ {
+ HRESULT hr;
+
+ hr = RemoveHooks(m_currentFocus);
+
+ if (FAILED(hr) || !newBand)
+ {
+ m_currentFocus = NULL;
+ m_currentBand = NULL;
+ return S_OK;
+ }
+
+ HWND newFocus;
+ hr = newBand->GetTopLevelWindow(&newFocus);
+ if (FAILED(hr))
+ return hr;
+
+ hr = PlaceHooks(m_currentFocus);
+ if (FAILED(hr))
+ return hr;
+
+ m_currentFocus = newFocus;
+ m_currentBand = newBand;
+
+ return S_OK;
+ }
+
+public:
+ HRESULT PushMenu(CMenuBand * mb)
+ {
+ HRESULT hr;
+
+ hr = PushToArray(mb);
+ if (FAILED(hr))
+ return hr;
+
+ return UpdateFocus(mb);
+ }
+
+ HRESULT PopMenu(CMenuBand * mb)
+ {
+ CMenuBand * mbc;
+ HRESULT hr;
+
+ hr = PopFromArray(&mbc);
+ if (FAILED(hr))
+ return hr;
+
+ if (mb != mbc)
+ return E_FAIL;
+
+ hr = PeekArray(&mbc);
+
+ return UpdateFocus(mbc);
+ }
+};
+
+DWORD CMenuFocusManager::TlsIndex = 0;
+
extern "C"
HRESULT CMenuBand_Constructor(REFIID riid, LPVOID *ppv)
{
@@ -930,10 +1189,13 @@
m_SFToolbar(NULL),
m_useBigIcons(FALSE)
{
+ m_focusManager = CMenuFocusManager::AcquireManager();
}
CMenuBand::~CMenuBand()
{
+ CMenuFocusManager::ReleaseManager(m_focusManager);
+
if (m_site)
m_site->Release();
@@ -1258,9 +1520,18 @@
return hr;
if (fShow)
- return _CallCB(SMC_INITMENU, 0, 0);
-
- return S_OK;
+ {
+ hr = _CallCB(SMC_INITMENU, 0, 0);
+ if (FAILED(hr))
+ return hr;
+ }
+
+ if (fShow)
+ hr = m_focusManager->PushMenu(this);
+ else
+ hr = m_focusManager->PopMenu(this);
+
+ return hr;
}
HRESULT STDMETHODCALLTYPE CMenuBand::CloseDW(DWORD dwReserved)
@@ -1722,3 +1993,9 @@
::TrackPopupMenu(popup, 0, x, y, 0, m_menuOwner, NULL);
return S_OK;
}
+
+HRESULT CMenuBand::GetTopLevelWindow(HWND*topLevel)
+{
+ *topLevel = m_topLevelWindow;
+ return S_OK;
+}
Modified: branches/shell-experiments/base/shell/rshell/CMenuDeskBar.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/shell-experiments/base/shell/rs…
==============================================================================
--- branches/shell-experiments/base/shell/rshell/CMenuDeskBar.cpp [iso-8859-1] (original)
+++ branches/shell-experiments/base/shell/rshell/CMenuDeskBar.cpp [iso-8859-1] Wed Feb 19
20:35:50 2014
@@ -576,14 +576,11 @@
UIActivateIO(FALSE, NULL);
}
- //if (bubbleUp && m_Site)
- //{
- // CComPtr<IMenuPopup> pmp;
- // HRESULT hr = IUnknown_QueryService(m_Site, SID_SMenuPopup,
IID_PPV_ARG(IMenuPopup, &pmp));
- // if (FAILED(hr))
- // return hr;
- // pmp->OnSelect(dwSelectType);
- //}
+ if (bubbleUp && m_SubMenuParent)
+ {
+ hr = m_SubMenuParent->OnSelect(MPOS_CANCELLEVEL); // why??
+ return hr;
+ }
return S_OK;
}
Modified: branches/shell-experiments/base/shell/rshell/precomp.h
URL:
http://svn.reactos.org/svn/reactos/branches/shell-experiments/base/shell/rs…
==============================================================================
--- branches/shell-experiments/base/shell/rshell/precomp.h [iso-8859-1] (original)
+++ branches/shell-experiments/base/shell/rshell/precomp.h [iso-8859-1] Wed Feb 19
20:35:50 2014
@@ -3,9 +3,9 @@
#define USE_SYSTEM_MENUSITE 0
#define USE_SYSTEM_MENUBAND 0
-#define WRAP_MENUDESKBAR 1
-#define WRAP_MENUSITE 1
-#define WRAP_MENUBAND 1
+#define WRAP_MENUDESKBAR 0
+#define WRAP_MENUSITE 0
+#define WRAP_MENUBAND 0
#include <stdio.h>
#include <tchar.h>