Author: dquintana
Date: Wed Apr 2 17:37:37 2014
New Revision: 62601
URL:
http://svn.reactos.org/svn/reactos?rev=62601&view=rev
Log:
[RSHELL]
* Improvements on the focus manager. The menus work better, but still not fully. Commiting
for backup/history purposes.
CORE-7586
Modified:
branches/shell-experiments/base/shell/rshell/CMenuBand.cpp
branches/shell-experiments/base/shell/rshell/CMenuBand.h
branches/shell-experiments/base/shell/rshell/CMenuFocusManager.cpp
branches/shell-experiments/base/shell/rshell/CMenuFocusManager.h
branches/shell-experiments/base/shell/rshell/CMenuToolbars.cpp
branches/shell-experiments/base/shell/rshell/CMenuToolbars.h
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 Apr 2
17:37:37 2014
@@ -65,7 +65,8 @@
m_topLevelWindow(NULL),
m_hotBar(NULL),
m_hotItem(-1),
- m_trackingPopup(FALSE)
+ m_popupBar(NULL),
+ m_popupItem(-1)
{
m_focusManager = CMenuFocusManager::AcquireManager();
}
@@ -504,6 +505,10 @@
HRESULT CMenuBand::_SetChildBand(CMenuBand * child)
{
m_childBand = child;
+ if (!child)
+ {
+ _ChangePopupItem(NULL, -1);
+ }
return S_OK;
}
@@ -524,13 +529,11 @@
if (!punkClient)
{
- if (m_staticToolbar) m_staticToolbar->OnPopupItemChanged(NULL, -1);
- if (m_SFToolbar) m_SFToolbar->OnPopupItemChanged(NULL, -1);
return S_OK;
}
+
HRESULT hr = punkClient->QueryInterface(IID_PPV_ARG(IMenuPopup,
&m_subMenuChild));
- m_trackingPopup = m_subMenuChild != NULL;
- DbgPrint("Tracking: %d\n", m_trackingPopup);
+
return hr;
}
@@ -666,8 +669,7 @@
UINT flags = TPM_VERPOSANIMATION | TPM_VERTICAL | TPM_LEFTALIGN;
- m_trackingPopup = TRUE;
- DbgPrint("Tracking: %d\n", m_trackingPopup);
+ //_DisableMouseTrack(TRUE);
m_focusManager->PushTrackedPopup(popup);
if (m_menuOwner)
@@ -680,8 +682,7 @@
}
m_focusManager->PopTrackedPopup(popup);
- m_trackingPopup = FALSE;
- DbgPrint("Tracking: %d\n", m_trackingPopup);
+ _DisableMouseTrack(FALSE);
return S_OK;
}
@@ -692,16 +693,36 @@
return S_OK;
}
-HRESULT CMenuBand::_OnHotItemChanged(CMenuToolbarBase * tb, INT id)
-{
- if (m_trackingPopup && id == -1)
- {
+HRESULT CMenuBand::_ChangeHotItem(CMenuToolbarBase * tb, INT id, DWORD dwFlags)
+{
+ if (m_hotBar == tb && m_hotItem == id)
return S_FALSE;
- }
+
+ DbgPrint("Hot item changed from %p %p, to %p %p\n", m_hotBar, m_hotItem,
tb, id);
+
+ if (m_hotBar != tb)
+ _KillPopupTimers();
+
m_hotBar = tb;
m_hotItem = id;
- if (m_staticToolbar) m_staticToolbar->OnHotItemChanged(tb, id);
- if (m_SFToolbar) m_SFToolbar->OnHotItemChanged(tb, id);
+ if (m_staticToolbar) m_staticToolbar->ChangeHotItem(tb, id, dwFlags);
+ if (m_SFToolbar) m_SFToolbar->ChangeHotItem(tb, id, dwFlags);
+
+ _MenuItemHotTrack(MPOS_CHILDTRACKING);
+
+
+ return S_OK;
+}
+
+HRESULT CMenuBand::_ChangePopupItem(CMenuToolbarBase * tb, INT id)
+{
+ DbgPrint("Popup item changed from %p %p, to %p %p\n", m_popupBar,
m_popupItem, tb, id);
+
+ m_popupBar = tb;
+ m_popupItem = id;
+ if (m_staticToolbar) m_staticToolbar->ChangePopupItem(tb, id);
+ if (m_SFToolbar) m_SFToolbar->ChangePopupItem(tb, id);
+
return S_OK;
}
@@ -721,13 +742,13 @@
}
else if (m_staticToolbar && m_hotBar == m_staticToolbar)
{
- hr = m_staticToolbar->ChangeHotItem(VK_DOWN);
+ hr = m_staticToolbar->KeyboardItemChange(VK_DOWN);
if (hr == S_FALSE)
{
if (m_SFToolbar)
- return m_SFToolbar->ChangeHotItem(VK_HOME);
+ return m_SFToolbar->KeyboardItemChange(VK_HOME);
else
- return m_staticToolbar->ChangeHotItem(VK_HOME);
+ return m_staticToolbar->KeyboardItemChange(VK_HOME);
}
return hr;
}
@@ -737,13 +758,13 @@
SendMessageW(m_menuOwner, WM_CANCELMODE, 0, 0);
if (m_staticToolbar && (m_hotBar == m_staticToolbar || m_hotBar ==
NULL))
{
- hr = m_staticToolbar->ChangeHotItem(VK_UP);
+ hr = m_staticToolbar->KeyboardItemChange(VK_UP);
if (hr == S_FALSE)
{
if (m_SFToolbar)
- return m_SFToolbar->ChangeHotItem(VK_END);
+ return m_SFToolbar->KeyboardItemChange(VK_END);
else
- return m_staticToolbar->ChangeHotItem(VK_END);
+ return m_staticToolbar->KeyboardItemChange(VK_END);
}
return hr;
}
@@ -758,25 +779,25 @@
{
if (m_SFToolbar && (m_hotBar == m_SFToolbar || m_hotBar == NULL))
{
- hr = m_SFToolbar->ChangeHotItem(VK_DOWN);
+ hr = m_SFToolbar->KeyboardItemChange(VK_DOWN);
if (hr == S_FALSE)
{
if (m_staticToolbar)
- return m_staticToolbar->ChangeHotItem(VK_HOME);
+ return m_staticToolbar->KeyboardItemChange(VK_HOME);
else
- return m_SFToolbar->ChangeHotItem(VK_HOME);
+ return m_SFToolbar->KeyboardItemChange(VK_HOME);
}
return hr;
}
else if (m_staticToolbar && m_hotBar == m_staticToolbar)
{
- hr = m_staticToolbar->ChangeHotItem(VK_DOWN);
+ hr = m_staticToolbar->KeyboardItemChange(VK_DOWN);
if (hr == S_FALSE)
{
if (m_SFToolbar)
- return m_SFToolbar->ChangeHotItem(VK_HOME);
+ return m_SFToolbar->KeyboardItemChange(VK_HOME);
else
- return m_staticToolbar->ChangeHotItem(VK_HOME);
+ return m_staticToolbar->KeyboardItemChange(VK_HOME);
}
return hr;
}
@@ -785,25 +806,25 @@
{
if (m_staticToolbar && (m_hotBar == m_staticToolbar || m_hotBar ==
NULL))
{
- hr = m_staticToolbar->ChangeHotItem(VK_UP);
+ hr = m_staticToolbar->KeyboardItemChange(VK_UP);
if (hr == S_FALSE)
{
if (m_SFToolbar)
- return m_SFToolbar->ChangeHotItem(VK_END);
+ return m_SFToolbar->KeyboardItemChange(VK_END);
else
- return m_staticToolbar->ChangeHotItem(VK_END);
+ return m_staticToolbar->KeyboardItemChange(VK_END);
}
return hr;
}
else if (m_SFToolbar && m_hotBar == m_SFToolbar)
{
- hr = m_SFToolbar->ChangeHotItem(VK_UP);
+ hr = m_SFToolbar->KeyboardItemChange(VK_UP);
if (hr == S_FALSE)
{
if (m_staticToolbar)
- return m_staticToolbar->ChangeHotItem(VK_END);
+ return m_staticToolbar->KeyboardItemChange(VK_END);
else
- return m_SFToolbar->ChangeHotItem(VK_END);
+ return m_SFToolbar->KeyboardItemChange(VK_END);
}
return hr;
}
@@ -836,31 +857,25 @@
return S_OK;
}
-HRESULT CMenuBand::_OnPopupSubMenu(IMenuPopup * popup, POINTL * pAt, RECTL * pExclude,
CMenuToolbarBase * toolbar, INT item)
-{
- if (m_subMenuChild)
- {
- HRESULT hr = m_subMenuChild->OnSelect(MPOS_CANCELLEVEL);
- if (FAILED_UNEXPECTEDLY(hr))
- return hr;
- }
-
- if (m_staticToolbar) m_staticToolbar->OnPopupItemChanged(toolbar, item);
- if (m_SFToolbar) m_SFToolbar->OnPopupItemChanged(toolbar, item);
-
+HRESULT CMenuBand::_CancelCurrentPopup()
+{
+ if (!m_subMenuChild)
+ return S_FALSE;
+
+ HRESULT hr = m_subMenuChild->OnSelect(MPOS_CANCELLEVEL);
+ return hr;
+}
+
+HRESULT CMenuBand::_OnPopupSubMenu(IMenuPopup * popup, POINTL * pAt, RECTL * pExclude)
+{
m_subMenuChild = popup;
- m_trackingPopup = popup != NULL;
- DbgPrint("Tracking: %d\n", m_trackingPopup);
-
- if (popup)
- {
- if (m_subMenuParent)
- IUnknown_SetSite(popup, m_subMenuParent);
- else
- IUnknown_SetSite(popup, m_site);
-
- popup->Popup(pAt, pExclude, MPPF_RIGHT);
- }
+
+ if (m_subMenuParent)
+ IUnknown_SetSite(popup, m_subMenuParent);
+ else
+ IUnknown_SetSite(popup, m_site);
+
+ popup->Popup(pAt, pExclude, MPPF_RIGHT);
return S_OK;
}
@@ -874,6 +889,20 @@
return S_OK;
}
+HRESULT CMenuBand::_KillPopupTimers()
+{
+ HRESULT hr = S_OK;
+ if (m_staticToolbar)
+ hr = m_staticToolbar->KillPopupTimer();
+ if (FAILED(hr))
+ return hr;
+
+ if (m_SFToolbar)
+ hr = m_SFToolbar->KillPopupTimer();
+
+ return hr;
+}
+
HRESULT STDMETHODCALLTYPE CMenuBand::InvalidateItem(LPSMDATA psmd, DWORD dwFlags)
{
UNIMPLEMENTED;
Modified: branches/shell-experiments/base/shell/rshell/CMenuBand.h
URL:
http://svn.reactos.org/svn/reactos/branches/shell-experiments/base/shell/rs…
==============================================================================
--- branches/shell-experiments/base/shell/rshell/CMenuBand.h [iso-8859-1] (original)
+++ branches/shell-experiments/base/shell/rshell/CMenuBand.h [iso-8859-1] Wed Apr 2
17:37:37 2014
@@ -62,7 +62,8 @@
CMenuToolbarBase * m_hotBar;
INT m_hotItem;
- BOOL m_trackingPopup;
+ CMenuToolbarBase * m_popupBar;
+ INT m_popupItem;
public:
CMenuBand();
@@ -176,13 +177,16 @@
HRESULT _CallCBWithItemPidl(LPITEMIDLIST pidl, UINT uMsg, WPARAM wParam, LPARAM
lParam);
HRESULT _TrackSubMenuUsingTrackPopupMenu(HMENU popup, INT x, INT y, RECT&
rcExclude);
HRESULT _GetTopLevelWindow(HWND*topLevel);
- HRESULT _OnHotItemChanged(CMenuToolbarBase * tb, INT id);
+ HRESULT _ChangeHotItem(CMenuToolbarBase * tb, INT id, DWORD dwFlags);
+ HRESULT _ChangePopupItem(CMenuToolbarBase * tb, INT id);
HRESULT _MenuItemHotTrack(DWORD changeType);
- HRESULT _OnPopupSubMenu(IMenuPopup * popup, POINTL * pAt, RECTL * pExclude,
CMenuToolbarBase * toolbar, INT item);
+ HRESULT _CancelCurrentPopup();
+ HRESULT _OnPopupSubMenu(IMenuPopup * popup, POINTL * pAt, RECTL * pExclude);
HRESULT _DisableMouseTrack(BOOL bDisable);
HRESULT _SetChildBand(CMenuBand * child);
HRESULT _SetParentBand(CMenuBand * parent);
HRESULT _IsPopup();
+ HRESULT _KillPopupTimers();
BOOL UseBigIcons()
{
Modified: branches/shell-experiments/base/shell/rshell/CMenuFocusManager.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/shell-experiments/base/shell/rs…
==============================================================================
--- branches/shell-experiments/base/shell/rshell/CMenuFocusManager.cpp [iso-8859-1]
(original)
+++ branches/shell-experiments/base/shell/rshell/CMenuFocusManager.cpp [iso-8859-1] Wed
Apr 2 17:37:37 2014
@@ -149,8 +149,6 @@
m_hMsgFilterHook(NULL),
m_hGetMsgHook(NULL),
m_mouseTrackDisabled(FALSE),
- m_lastMoveFlags(0),
- m_lastMovePos(0),
m_captureHwnd(0),
m_bandCount(0)
{
@@ -173,7 +171,7 @@
{
StackEntry& entry = m_bandStack[i];
- if (entry.type == MenuPopupEntry)
+ if (entry.type != TrackedMenuEntry)
{
HWND hwnd;
HRESULT hr = entry.mb->_GetTopLevelWindow(&hwnd);
@@ -192,10 +190,10 @@
entry.mb->_DisableMouseTrack(bDisable);
}
}
- else
- {
- continue;
- }
+ //else
+ //{
+ // continue;
+ //}
}
m_mouseTrackDisabled = lastDisable;
}
@@ -220,20 +218,26 @@
}
}
-HRESULT CMenuFocusManager::IsTrackedWindow(HWND hWnd)
-{
- int i = m_bandCount;
- while (--i >= 0)
+HRESULT CMenuFocusManager::IsTrackedWindow(HWND hWnd, StackEntry ** pentry)
+{
+ if (pentry)
+ *pentry = NULL;
+
+ for (int i = m_bandCount; --i >= 0;)
{
StackEntry& entry = m_bandStack[i];
- if (entry.type == MenuPopupEntry)
+ if (entry.type != TrackedMenuEntry)
{
HRESULT hr = entry.mb->IsWindowOwner(hWnd);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
if (hr == S_OK)
+ {
+ if (pentry)
+ *pentry = &entry;
return S_OK;
+ }
}
}
@@ -243,43 +247,58 @@
LRESULT CMenuFocusManager::ProcessMouseMove(MSG* msg)
{
HWND child;
- POINT pt;
int iHitTestResult;
- pt = msg->pt;
+ POINT pt2 = { GET_X_LPARAM(msg->lParam), GET_Y_LPARAM(msg->lParam) };
+ ClientToScreen(msg->hwnd, &pt2);
+
+ /* Don't do anything if the mouse has not been moved */
+ POINT pt = msg->pt;
+ if (pt.x == m_ptPrev.x && pt.y == m_ptPrev.y)
+ return TRUE;
+
+ m_ptPrev = pt;
child = WindowFromPoint(pt);
- if (!m_parent)
- return TRUE;
-
- if (m_parent->mb->IsWindowOwner(child) != S_OK)
- return TRUE;
-
- ScreenToClient(child, &msg->pt);
-
- /* Don't do anything if the mouse has not been moved */
- if (msg->pt.x == m_ptPrev.x && msg->pt.y == m_ptPrev.y)
- return TRUE;
-
- m_ptPrev = msg->pt;
-
- iHitTestResult = SendMessageW(child, TB_HITTEST, 0, (LPARAM) &msg->pt);
-
- /* Make sure that iHitTestResult is one of the menu items and that it is not the
current menu item */
- if (iHitTestResult >= 0)
- {
- HWND hwndToolbar = child;
- if (SendMessage(hwndToolbar, WM_USER_ISTRACKEDITEM, iHitTestResult, 0))
- {
- DbgPrint("Hot item tracking detected a change...\n");
+ if (m_hwndUnderMouse != child)
+ {
+ WCHAR cn[1024];
+ GetClassName(child, cn, 1023);
+ DbgPrint("Mouse moved to %p (%S)\n", child, cn);
+ m_hwndUnderMouse = child;
+ }
+
+ StackEntry * entry = NULL;
+
+ if (IsTrackedWindow(child, &entry) == S_OK)
+ {
+ ScreenToClient(child, &pt);
+ iHitTestResult = SendMessageW(child, TB_HITTEST, 0, (LPARAM) &pt);
+
+ if (iHitTestResult >= 0 &&
+ SendMessage(child, WM_USER_ISTRACKEDITEM, iHitTestResult, 0) == S_FALSE)
+ {
+ DbgPrint("Hot item tracking detected a change (capture=%p)...\n",
m_captureHwnd);
+ DisableMouseTrack(NULL, FALSE);
if (m_current->type == TrackedMenuEntry)
- SendMessage(m_parent->hwnd, WM_CANCELMODE, 0, 0);
- else
- m_current->mb->_MenuItemHotTrack(MPOS_CANCELLEVEL);
- PostMessage(hwndToolbar, WM_USER_CHANGETRACKEDITEM, iHitTestResult,
iHitTestResult);
+ SendMessage(entry->hwnd, WM_CANCELMODE, 0, 0);
+ PostMessage(child, WM_USER_CHANGETRACKEDITEM, iHitTestResult,
iHitTestResult);
return FALSE;
}
+
+ if (m_current->type == MenuPopupEntry)
+ {
+ SetCapture(child);
+ ScreenToClient(child, &pt2);
+ SendMessage(child, WM_MOUSEMOVE, msg->wParam, MAKELPARAM(pt2.x, pt2.y));
+ }
+ }
+
+ if (m_current->type == MenuPopupEntry)
+ {
+ HWND parent = GetAncestor(child, GA_ROOT);
+ DisableMouseTrack(parent, FALSE);
}
return TRUE;
@@ -294,16 +313,30 @@
{
BOOL callNext = TRUE;
MSG* msg = reinterpret_cast<MSG*>(lParam);
-
+
switch (msg->message)
{
+ case WM_NCLBUTTONDOWN:
+ case WM_LBUTTONDOWN:
+ if (m_menuBar)
+ {
+ POINT pt = msg->pt;
+ HWND child = WindowFromPoint(pt);
+ BOOL hoveringMenuBar = m_menuBar->mb->IsWindowOwner(child) ==
S_OK;
+ if (hoveringMenuBar)
+ {
+ HWND parent = GetAncestor(child, GA_ROOT);
+ m_menuBar->mb->_DisableMouseTrack(TRUE);
+ }
+ }
+ break;
case WM_MOUSEMOVE:
callNext = ProcessMouseMove(msg);
break;
}
if (!callNext)
- return 0;
+ return 1;
}
return CallNextHookEx(m_hMsgFilterHook, nCode, wParam, lParam);
@@ -313,13 +346,12 @@
{
if (nCode < 0)
return CallNextHookEx(m_hGetMsgHook, nCode, wParam, lParam);
-
- LPARAM pos = (LPARAM) GetMessagePos();
-
+
if (nCode == HC_ACTION)
{
BOOL callNext = TRUE;
MSG* msg = reinterpret_cast<MSG*>(lParam);
+ POINT pt = msg->pt;
switch (msg->message)
{
@@ -330,53 +362,17 @@
case WM_LBUTTONDOWN:
if (m_current->type == MenuPopupEntry)
{
- POINT pt = { GET_X_LPARAM(pos), GET_Y_LPARAM(pos) };
-
HWND child = WindowFromPoint(pt);
- HWND window = GetAncestor(child, GA_ROOT);
- if (IsTrackedWindow(window) != S_OK)
+ if (IsTrackedWindow(child) != S_OK)
{
+ SetCapture(NULL);
m_current->mb->_MenuItemHotTrack(MPOS_FULLCANCEL);
}
}
break;
case WM_MOUSEMOVE:
- if ((m_parent && m_parent->type==MenuPopupEntry) ||
ProcessMouseMove(msg))
- {
- if (m_current->type == MenuPopupEntry)
- {
- if (m_lastMoveFlags != wParam || m_lastMovePos != pos)
- {
- m_lastMoveFlags = wParam;
- m_lastMovePos = pos;
-
- POINT pt = { GET_X_LPARAM(pos), GET_Y_LPARAM(pos) };
-
- HWND child = WindowFromPoint(pt);
- HWND window = GetAncestor(child, GA_ROOT);
-
- if (m_parent && m_parent->mb->IsWindowOwner(child)
== S_OK)
- {
- DisableMouseTrack(window, FALSE);
- }
- else if (IsTrackedWindow(child) == S_OK)
- {
- DisableMouseTrack(window, FALSE);
- SetCapture(child);
- }
- else
- {
- DisableMouseTrack(NULL, FALSE);
- SetCapture(NULL);
- }
- }
- }
- }
- else
- {
- callNext = FALSE;
- }
+ callNext = ProcessMouseMove(msg);
break;
case WM_SYSKEYDOWN:
case WM_KEYDOWN:
@@ -405,7 +401,7 @@
}
if (!callNext)
- return 0;
+ return 1;
}
return CallNextHookEx(m_hGetMsgHook, nCode, wParam, lParam);
@@ -413,12 +409,12 @@
HRESULT CMenuFocusManager::PlaceHooks()
{
- if (m_current->hmenu)
+ if (m_current->type == TrackedMenuEntry)
{
DbgPrint("Entering MSGFILTER hook...\n");
m_hMsgFilterHook = SetWindowsHookEx(WH_MSGFILTER, s_MsgFilterHook, NULL,
m_threadId);
}
- else
+ else if (m_current->type == MenuPopupEntry)
{
DbgPrint("Entering GETMESSAGE hook...\n");
m_hGetMsgHook = SetWindowsHookEx(WH_GETMESSAGE, s_GetMsgHook, NULL, m_threadId);
@@ -468,9 +464,21 @@
m_parent = NULL;
}
+ if (m_bandCount >= 1 && m_bandStack[0].type == MenuBarEntry)
+ {
+ m_menuBar = &(m_bandStack[0]);
+ }
+ else
+ {
+ m_menuBar = NULL;
+ }
+
if (old && (!m_current || old->type != m_current->type))
{
- DisableMouseTrack(NULL, FALSE);
+ if (m_current->type != TrackedMenuEntry)
+ {
+ DisableMouseTrack(m_current->hwnd, FALSE);
+ }
hr = RemoveHooks();
if (FAILED_UNEXPECTEDLY(hr))
@@ -484,13 +492,22 @@
return hr;
}
+ if (m_parent)
+ {
+ DisableMouseTrack(m_parent->hwnd, TRUE);
+ }
+
if ((m_current && m_current->type == MenuPopupEntry) &&
(!m_parent || m_parent->type == MenuBarEntry))
{
- DisableMouseTrack(m_current->hwnd, FALSE);
-
// When the mouse moves, it should set itself to the proper band
SetCapture(m_current->hwnd);
+
+ //// FIXME: Debugging code, probably not right
+ //POINT pt2;
+ //GetCursorPos(&pt2);
+ //ScreenToClient(m_current->hwnd, &pt2);
+ //SendMessage(m_current->hwnd, WM_MOUSEMOVE, 0, MAKELPARAM(pt2.x, pt2.y));
}
_ASSERT(!m_parent || m_parent->type != TrackedMenuEntry);
Modified: branches/shell-experiments/base/shell/rshell/CMenuFocusManager.h
URL:
http://svn.reactos.org/svn/reactos/branches/shell-experiments/base/shell/rs…
==============================================================================
--- branches/shell-experiments/base/shell/rshell/CMenuFocusManager.h [iso-8859-1]
(original)
+++ branches/shell-experiments/base/shell/rshell/CMenuFocusManager.h [iso-8859-1] Wed Apr
2 17:37:37 2014
@@ -58,6 +58,7 @@
private:
StackEntry * m_current;
StackEntry * m_parent;
+ StackEntry * m_menuBar;
HHOOK m_hMsgFilterHook;
HHOOK m_hGetMsgHook;
@@ -65,12 +66,11 @@
BOOL m_mouseTrackDisabled;
- WPARAM m_lastMoveFlags;
- LPARAM m_lastMovePos;
-
POINT m_ptPrev;
HWND m_captureHwnd;
+
+ HWND m_hwndUnderMouse;
// TODO: make dynamic
#define MAX_RECURSE 20
@@ -97,7 +97,7 @@
HRESULT PlaceHooks();
HRESULT RemoveHooks();
HRESULT UpdateFocus();
- HRESULT IsTrackedWindow(HWND hWnd);
+ HRESULT IsTrackedWindow(HWND hWnd, StackEntry ** pentry = NULL);
void DisableMouseTrack(HWND parent, BOOL disableThis);
void SetCapture(HWND child);
Modified: branches/shell-experiments/base/shell/rshell/CMenuToolbars.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/shell-experiments/base/shell/rs…
==============================================================================
--- branches/shell-experiments/base/shell/rshell/CMenuToolbars.cpp [iso-8859-1]
(original)
+++ branches/shell-experiments/base/shell/rshell/CMenuToolbars.cpp [iso-8859-1] Wed Apr 2
17:37:37 2014
@@ -37,20 +37,12 @@
// FIXME: Enable if/when wine comctl supports this flag properly
#define USE_TBSTYLE_EX_VERTICAL 0
+// User-defined timer ID used while hot-tracking around the menu
#define TIMERID_HOTTRACK 1
-#define SUBCLASS_ID_MENUBAND 1
-
-HRESULT CMenuToolbarBase::DisableMouseTrack(BOOL bDisable)
-{
- m_disableMouseTrack = bDisable;
- return S_OK;
-}
HRESULT CMenuToolbarBase::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
LRESULT *theResult)
{
NMHDR * hdr;
- NMPGCALCSIZE* csize;
- SIZE tbs;
*theResult = 0;
switch (uMsg)
@@ -62,26 +54,11 @@
hdr = reinterpret_cast<LPNMHDR>(lParam);
switch (hdr->code)
{
- case TTN_GETDISPINFOA:
- case TTN_GETDISPINFOW:
- return S_OK;
-
case TBN_DELETINGBUTTON:
return OnDeletingButton(reinterpret_cast<LPNMTOOLBAR>(hdr));
case PGN_CALCSIZE:
- csize = reinterpret_cast<LPNMPGCALCSIZE>(hdr);
-
- GetIdealSize(tbs);
- if (csize->dwFlag == PGF_CALCHEIGHT)
- {
- csize->iHeight = tbs.cy;
- }
- else if (csize->dwFlag == PGF_CALCWIDTH)
- {
- csize->iHeight = tbs.cx;
- }
- return S_OK;
+ return OnPagerCalcSize(reinterpret_cast<LPNMPGCALCSIZE>(hdr));
case TBN_DROPDOWN:
return OnCommand(reinterpret_cast<LPNMTOOLBAR>(hdr)->iItem, 0,
theResult);
@@ -95,12 +72,20 @@
case NM_CUSTOMDRAW:
return OnCustomDraw(reinterpret_cast<LPNMTBCUSTOMDRAW>(hdr),
theResult);
+ case TBN_GETINFOTIP:
+ return OnGetInfoTip(reinterpret_cast<LPNMTBGETINFOTIP>(hdr));
+
+ // Silence unhandled items so that they don't print as unknown
case RBN_CHILDSIZE:
return S_OK;
+ case TTN_GETDISPINFO:
+ return S_OK;
+
case NM_RELEASEDCAPTURE:
break;
+ case NM_CLICK:
case NM_RDOWN:
case NM_LDOWN:
break;
@@ -115,10 +100,6 @@
case NM_TOOLTIPSCREATED:
break;
- case TBN_GETINFOTIP:
- // TODO: Get tooltip for item
- break;
-
default:
DbgPrint("WM_NOTIFY unknown code %d, %d\n", hdr->code,
hdr->idFrom);
return S_OK;
@@ -129,76 +110,159 @@
return S_FALSE;
}
+LRESULT CALLBACK CMenuToolbarBase::s_SubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam,
LPARAM lParam)
+{
+ CMenuToolbarBase * pthis = reinterpret_cast<CMenuToolbarBase
*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
+ return pthis->SubclassProc(hWnd, uMsg, wParam, lParam);
+}
+
+LRESULT CMenuToolbarBase::SubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM
lParam)
+{
+ LRESULT lr;
+
+ switch (uMsg)
+ {
+ case WM_USER_ISTRACKEDITEM:
+ m_SubclassOld(hWnd, uMsg, wParam, lParam);
+ return IsTrackedItem(wParam);
+ case WM_USER_CHANGETRACKEDITEM:
+ m_SubclassOld(hWnd, uMsg, wParam, lParam);
+ return ChangeTrackedItem(wParam);
+
+ case WM_COMMAND:
+ OnWinEvent(hWnd, uMsg, wParam, lParam, &lr);
+ break;
+ case WM_NOTIFY:
+ OnWinEvent(hWnd, uMsg, wParam, lParam, &lr);
+ break;
+ case WM_TIMER:
+ OnPopupTimer(wParam);
+ }
+
+ return m_SubclassOld(hWnd, uMsg, wParam, lParam);
+}
+
+HRESULT CMenuToolbarBase::DisableMouseTrack(BOOL bDisable)
+{
+ if (m_disableMouseTrack != bDisable)
+ {
+ m_disableMouseTrack = bDisable;
+ DbgPrint("DisableMouseTrack %d\n", bDisable);
+ }
+ return S_OK;
+}
+
+HRESULT CMenuToolbarBase::OnPagerCalcSize(LPNMPGCALCSIZE csize)
+{
+ SIZE tbs;
+ GetIdealSize(tbs);
+ if (csize->dwFlag == PGF_CALCHEIGHT)
+ {
+ csize->iHeight = tbs.cy;
+ }
+ else if (csize->dwFlag == PGF_CALCWIDTH)
+ {
+ csize->iWidth = tbs.cx;
+ }
+ return S_OK;
+}
+
HRESULT CMenuToolbarBase::OnCustomDraw(LPNMTBCUSTOMDRAW cdraw, LRESULT * theResult)
{
- RECT rc;
- HDC hdc;
- HBRUSH bgBrush;
- HBRUSH hotBrush;
+ RECT rc;
+ HDC hdc;
COLORREF clrText;
- COLORREF clrTextHighlight;
- bool isHot, isPopup;
+ HBRUSH bgBrush;
+ bool isHot, isPopup;
TBBUTTONINFO btni;
switch (cdraw->nmcd.dwDrawStage)
{
case CDDS_PREPAINT:
- if (m_toolbarFlags & SMINIT_VERTICAL)
- *theResult = CDRF_NOTIFYITEMDRAW;
+ *theResult = CDRF_NOTIFYITEMDRAW;
return S_OK;
case CDDS_ITEMPREPAINT:
-
- clrText = GetSysColor(COLOR_MENUTEXT);
- clrTextHighlight = GetSysColor(COLOR_HIGHLIGHTTEXT);
-
- bgBrush = GetSysColorBrush(COLOR_MENU);
- hotBrush = GetSysColorBrush(m_useFlatMenus ? COLOR_MENUHILIGHT :
COLOR_HIGHLIGHT);
rc = cdraw->nmcd.rc;
hdc = cdraw->nmcd.hdc;
- isHot = m_hotBar == this && m_hotItem ==
static_cast<INT>(cdraw->nmcd.dwItemSpec);
- isPopup = m_popupBar == this && m_popupItem ==
static_cast<INT>(cdraw->nmcd.dwItemSpec);
-
- if (isHot || (m_hotItem < 0 && isPopup))
- {
- cdraw->nmcd.uItemState |= CDIS_HOT;
+ // The item with an active submenu gets the CHECKED flag.
+ isHot = m_hotBar == this && cdraw->nmcd.dwItemSpec == m_hotItem;
+ isPopup = m_popupBar == this && cdraw->nmcd.dwItemSpec ==
m_popupItem;
+
+ if (m_initFlags & SMINIT_VERTICAL)
+ {
+ // Remove HOT and CHECKED flags (will restore HOT if necessary)
+ cdraw->nmcd.uItemState &= ~(CDIS_HOT|CDIS_CHECKED);
+
+ // Decide on the colors
+ if (isHot || (m_hotItem < 0 && isPopup))
+ {
+ cdraw->nmcd.uItemState |= CDIS_HOT;
+
+ clrText = GetSysColor(COLOR_HIGHLIGHTTEXT);
+ bgBrush = GetSysColorBrush(m_useFlatMenus ? COLOR_MENUHILIGHT :
COLOR_HIGHLIGHT);
+ }
+ else
+ {
+ clrText = GetSysColor(COLOR_MENUTEXT);
+ bgBrush = GetSysColorBrush(COLOR_MENU);
+ }
+
+ // Paint the background color with the selected color
+ FillRect(hdc, &rc, bgBrush);
+
+ // Set the text color in advance, this color will be assigned when the
ITEMPOSTPAINT triggers
+ SetTextColor(hdc, clrText);
+
+ // Set the text color, will be used by the internal drawing code
+ cdraw->clrText = clrText;
+ cdraw->iListGap += 4;
+
+ // Tell the default drawing code we don't want any fanciness, not even a
background.
+ *theResult = CDRF_NOTIFYPOSTPAINT | TBCDRF_NOBACKGROUND | TBCDRF_NOEDGES |
TBCDRF_NOOFFSET | TBCDRF_NOMARK | 0x00800000; // FIXME: the last bit is Vista+, useful for
debugging only
}
else
{
+ // Remove HOT and CHECKED flags (will restore HOT if necessary)
cdraw->nmcd.uItemState &= ~CDIS_HOT;
- }
-
- if (cdraw->nmcd.uItemState&CDIS_HOT)
- {
- FillRect(hdc, &rc, hotBrush);
- SetTextColor(hdc, clrTextHighlight);
- cdraw->clrText = clrTextHighlight;
- }
- else
- {
- FillRect(hdc, &rc, bgBrush);
- SetTextColor(hdc, clrText);
- cdraw->clrText = clrText;
- }
-
- cdraw->iListGap += 4;
-
- *theResult = CDRF_NOTIFYPOSTPAINT | TBCDRF_NOBACKGROUND | TBCDRF_NOEDGES |
TBCDRF_NOOFFSET | TBCDRF_NOMARK | 0x00800000; // FIXME: the last bit is Vista+, for
debugging only
+
+ // Decide on the colors
+ if (isHot || (m_hotItem < 0 && isPopup))
+ {
+ cdraw->nmcd.uItemState |= CDIS_HOT;
+ }
+
+ *theResult = 0;
+ }
+
return S_OK;
case CDDS_ITEMPOSTPAINT:
+
+ // Fetch the button style
btni.cbSize = sizeof(btni);
btni.dwMask = TBIF_STYLE;
SendMessage(m_hwndToolbar, TB_GETBUTTONINFO, cdraw->nmcd.dwItemSpec,
reinterpret_cast<LPARAM>(&btni));
+
+ // Check if we need to draw a submenu arrow
if (btni.fsStyle & BTNS_DROPDOWN)
{
+ // TODO: Support RTL text modes by drawing a leftwards arrow aligned to the
left of the control
+
+ // "8" is the rightwards dropdown arrow in the Marlett font
+ WCHAR text[] = L"8";
+
+ // Configure the font to draw with Marlett, keeping the current background
color as-is
SelectObject(cdraw->nmcd.hdc, m_marlett);
- WCHAR text [] = L"8";
SetBkMode(cdraw->nmcd.hdc, TRANSPARENT);
+
+ // Tweak the alignment by 1 pixel so the menu draws like the Windows start
menu.
RECT rc = cdraw->nmcd.rc;
rc.right += 1;
+
+ // The arrow is drawn at the right of the item's rect, aligned
vertically.
DrawTextEx(cdraw->nmcd.hdc, text, 1, &rc, DT_NOCLIP | DT_VCENTER |
DT_RIGHT | DT_SINGLELINE, NULL);
}
*theResult = TRUE;
@@ -212,6 +276,7 @@
m_useFlatMenus(FALSE),
m_SubclassOld(NULL),
m_disableMouseTrack(FALSE),
+ m_timerEnabled(FALSE),
m_menuBand(menuBand),
m_hwndToolbar(NULL),
m_dwMenuFlags(0),
@@ -229,15 +294,15 @@
CMenuToolbarBase::~CMenuToolbarBase()
{
+ if (m_hwndToolbar && m_hwndToolbar != m_hwnd)
+ DestroyWindow(m_hwndToolbar);
+
+ if (m_hwnd)
+ DestroyWindow(m_hwnd);
+
DeleteObject(m_marlett);
}
-HRESULT CMenuToolbarBase::IsWindowOwner(HWND hwnd)
-{
- return (m_hwnd && m_hwnd == hwnd) ||
- (m_hwndToolbar && m_hwndToolbar == hwnd) ? S_OK : S_FALSE;
-}
-
void CMenuToolbarBase::InvalidateDraw()
{
InvalidateRect(m_hwnd, NULL, FALSE);
@@ -247,8 +312,10 @@
{
::ShowWindow(m_hwnd, fShow ? SW_SHOW : SW_HIDE);
+ // Ensure that the right image list is assigned to the toolbar
UpdateImageLists();
+ // For custom-drawing
SystemParametersInfo(SPI_GETFLATMENU, 0, &m_useFlatMenus, 0);
return S_OK;
@@ -256,13 +323,15 @@
HRESULT CMenuToolbarBase::UpdateImageLists()
{
- if ((m_toolbarFlags & (SMINIT_TOPLEVEL | SMINIT_VERTICAL)) == SMINIT_TOPLEVEL) //
not vertical.
- {
- /* Hide the placeholders for the button images */
+ if ((m_initFlags & (SMINIT_TOPLEVEL | SMINIT_VERTICAL)) == SMINIT_TOPLEVEL) //
not vertical.
+ {
+ // No image list, prevents the buttons from having a margin at the left side
SendMessageW(m_hwnd, TB_SETIMAGELIST, 0, 0);
return S_OK;
}
+ // Assign the correct imagelist and padding based on the current icon size
+
int shiml;
if (m_menuBand->UseBigIcons())
{
@@ -277,24 +346,27 @@
IImageList * piml;
HRESULT hr = SHGetImageList(shiml, IID_PPV_ARG(IImageList, &piml));
- if (SUCCEEDED(hr))
+ if (FAILED_UNEXPECTEDLY(hr))
+ {
+ SendMessageW(m_hwndToolbar, TB_SETIMAGELIST, 0, 0);
+ }
+ else
{
SendMessageW(m_hwndToolbar, TB_SETIMAGELIST, 0,
reinterpret_cast<LPARAM>(piml));
}
- else
- {
- SendMessageW(m_hwndToolbar, TB_SETIMAGELIST, 0, 0);
- }
return S_OK;
}
HRESULT CMenuToolbarBase::Close()
{
- DestroyWindow(m_hwndToolbar);
if (m_hwndToolbar != m_hwnd)
- DestroyWindow(m_hwnd);
+ DestroyWindow(m_hwndToolbar);
+
+ DestroyWindow(m_hwnd);
+
m_hwndToolbar = NULL;
m_hwnd = NULL;
+
return S_OK;
}
@@ -303,23 +375,26 @@
LONG tbStyles = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
TBSTYLE_TOOLTIPS | TBSTYLE_TRANSPARENT | TBSTYLE_REGISTERDROP | TBSTYLE_LIST |
TBSTYLE_FLAT | TBSTYLE_CUSTOMERASE |
CCS_NODIVIDER | CCS_NOPARENTALIGN | CCS_NORESIZE | CCS_TOP;
- LONG tbExStyles = TBSTYLE_EX_DOUBLEBUFFER;
+ LONG tbExStyles = TBSTYLE_EX_DOUBLEBUFFER | WS_EX_TOOLWINDOW;
if (dwFlags & SMINIT_VERTICAL)
{
+ // Activate vertical semantics
tbStyles |= CCS_VERT;
#if USE_TBSTYLE_EX_VERTICAL
- // FIXME: Use when it works in ros (?)
- tbExStyles |= TBSTYLE_EX_VERTICAL | WS_EX_TOOLWINDOW;
+ tbExStyles |= TBSTYLE_EX_VERTICAL;
#endif
}
- m_toolbarFlags = dwFlags;
-
+ m_initFlags = dwFlags;
+
+ // Get a temporary rect to use while creating the toolbar window.
+ // Ensure that it is not a null rect.
RECT rc;
-
- if (!::GetClientRect(hwndParent, &rc) || (rc.left == rc.right) || (rc.top ==
rc.bottom))
+ if (!::GetClientRect(hwndParent, &rc) ||
+ (rc.left == rc.right) ||
+ (rc.top == rc.bottom))
{
rc.left = 0;
rc.top = 0;
@@ -335,6 +410,7 @@
if (hwndToolbar == NULL)
return E_FAIL;
+ // If needed, create the pager.
if (m_usePager)
{
LONG pgStyles = PGS_VERT | WS_CHILD | WS_VISIBLE;
@@ -359,12 +435,14 @@
m_hwnd = hwndToolbar;
}
- /* Identify the version of the used Common Controls DLL by sending the size of the
TBBUTTON structure */
+ // Identify the version of the used Common Controls DLL by sending the size of the
TBBUTTON structure.
SendMessageW(hwndToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
+ // Apply subclassing
SetWindowLongPtr(hwndToolbar, GWLP_USERDATA,
reinterpret_cast<LONG_PTR>(this));
m_SubclassOld = (WNDPROC) SetWindowLongPtr(hwndToolbar, GWLP_WNDPROC,
reinterpret_cast<LONG_PTR>(CMenuToolbarBase::s_SubclassProc));
+ // Configure the image lists
UpdateImageLists();
return S_OK;
@@ -388,17 +466,30 @@
HRESULT CMenuToolbarBase::SetPosSize(int x, int y, int cx, int cy)
{
+ // If we have a pager, set the toolbar height to the ideal height of the toolbar
if (m_hwnd != m_hwndToolbar)
{
SetWindowPos(m_hwndToolbar, NULL, x, y, cx, m_idealSize.cy, 0);
}
+
+ // Update the toolbar or pager to fit the requested rect
SetWindowPos(m_hwnd, NULL, x, y, cx, cy, 0);
- if (m_toolbarFlags & SMINIT_VERTICAL)
+
+ // In a vertical menu, resize the buttons to fit the width
+ if (m_initFlags & SMINIT_VERTICAL)
{
DWORD btnSize = SendMessage(m_hwndToolbar, TB_GETBUTTONSIZE, 0, 0);
SendMessage(m_hwndToolbar, TB_SETBUTTONSIZE, 0, MAKELPARAM(cx,
HIWORD(btnSize)));
}
- return S_OK;
+
+ return S_OK;
+}
+
+HRESULT CMenuToolbarBase::IsWindowOwner(HWND hwnd)
+{
+ if (m_hwnd && m_hwnd == hwnd) return S_OK;
+ if (m_hwndToolbar && m_hwndToolbar == hwnd) return S_OK;
+ return S_FALSE;
}
HRESULT CMenuToolbarBase::GetWindow(HWND *phwnd)
@@ -411,132 +502,165 @@
return S_OK;
}
-LRESULT CALLBACK CMenuToolbarBase::s_SubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam,
LPARAM lParam)
-{
- CMenuToolbarBase * pthis = reinterpret_cast<CMenuToolbarBase
*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
- return pthis->SubclassProc(hWnd, uMsg, wParam, lParam);
-}
-
-LRESULT CMenuToolbarBase::SubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM
lParam)
-{
- LRESULT lr;
-
- switch (uMsg)
- {
- case WM_USER_ISTRACKEDITEM:
- m_SubclassOld(hWnd, uMsg, wParam, lParam);
- return IsTrackedItem(wParam);
- case WM_USER_CHANGETRACKEDITEM:
- m_SubclassOld(hWnd, uMsg, wParam, lParam);
- return ChangeTrackedItem(wParam);
-
- case WM_COMMAND:
- OnWinEvent(hWnd, uMsg, wParam, lParam, &lr);
- break;
- case WM_NOTIFY:
- OnWinEvent(hWnd, uMsg, wParam, lParam, &lr);
- break;
- case WM_TIMER:
- if (wParam == TIMERID_HOTTRACK)
- {
- KillTimer(hWnd, TIMERID_HOTTRACK);
-
- DbgPrint("Closing previous submenu...\n");
-
- m_menuBand->_OnPopupSubMenu(NULL, NULL, NULL, NULL, -1);
-
- DbgPrint("Opening new submenu...\n");
-
- PopupItem(m_hotItem);
- }
- }
-
- return m_SubclassOld(hWnd, uMsg, wParam, lParam);
+HRESULT CMenuToolbarBase::OnGetInfoTip(NMTBGETINFOTIP * tip)
+{
+ INT index;
+ DWORD_PTR dwData;
+
+ INT iItem = tip->iItem;
+
+ GetDataFromId(iItem, &index, &dwData);
+
+ return GetInfoTip(tip->pszText, tip->cchTextMax, iItem, index, dwData);
+}
+
+HRESULT CMenuToolbarBase::OnPopupTimer(DWORD timerId)
+{
+ if (timerId != TIMERID_HOTTRACK)
+ return S_FALSE;
+
+ KillTimer(m_hwndToolbar, TIMERID_HOTTRACK);
+
+ if (!m_timerEnabled)
+ return S_FALSE;
+
+ m_timerEnabled = FALSE;
+
+ if (m_hotItem < 0)
+ return S_FALSE;
+
+ // Returns S_FALSE if the current item did not show a submenu
+ HRESULT hr = PopupItem(m_hotItem);
+ if (hr != S_FALSE)
+ return hr;
+
+ // If we didn't switch submenus, cancel the current popup regardless
+ if (m_popupBar)
+ {
+ HRESULT hr = CancelCurrentPopup();
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+ }
+
+ return S_OK;
+}
+
+HRESULT CMenuToolbarBase::KillPopupTimer()
+{
+ if (m_timerEnabled)
+ {
+ m_timerEnabled = FALSE;
+ KillTimer(m_hwndToolbar, TIMERID_HOTTRACK);
+ return S_OK;
+ }
+ return S_FALSE;
}
HRESULT CMenuToolbarBase::OnHotItemChange(const NMTBHOTITEM * hot, LRESULT * theResult)
{
+ // Prevent a change of hot item if the change was triggered by the mouse,
+ // and mouse tracking is disabled.
if (m_disableMouseTrack && hot->dwFlags & HICF_MOUSE)
{
*theResult = 1;
+ DbgPrint("Hot item change prevented by DisableMouseTrack\n");
return S_OK;
}
+ HRESULT hr = S_OK;
if (hot->dwFlags & HICF_LEAVING)
{
- KillTimer(m_hwndToolbar, TIMERID_HOTTRACK);
-
- if (m_menuBand->_OnHotItemChanged(NULL, -1) == S_FALSE)
- {
- *theResult = 1;
- }
- else
- {
- m_menuBand->_OnHotItemChanged(NULL, -1);
- m_menuBand->_MenuItemHotTrack(MPOS_CHILDTRACKING);
- }
-
- return S_OK;
- }
-
- if (m_hotItem != hot->idNew)
- {
- if (hot->dwFlags & HICF_MOUSE &&
- m_toolbarFlags & SMINIT_VERTICAL)
- {
- DWORD elapsed = 0;
- SystemParametersInfo(SPI_GETMENUSHOWDELAY, 0, &elapsed, 0);
- SetTimer(m_hwndToolbar, TIMERID_HOTTRACK, elapsed, NULL);
- }
-
- m_menuBand->_OnHotItemChanged(this, hot->idNew);
- m_menuBand->_MenuItemHotTrack(MPOS_CHILDTRACKING);
-
- if (m_isTracking && !(m_toolbarFlags & SMINIT_VERTICAL))
- {
- KillTimer(m_hwndToolbar, TIMERID_HOTTRACK);
-
- m_menuBand->_OnPopupSubMenu(NULL, NULL, NULL, NULL, -1);
-
- PopupItem(m_hotItem);
- }
- return S_OK;
- }
-
- return S_OK;
-}
-
-HRESULT CMenuToolbarBase::OnHotItemChanged(CMenuToolbarBase * toolbar, INT item)
-{
- BOOL wasChecked = FALSE;
- if (m_hotBar == this && !(m_toolbarFlags & SMINIT_VERTICAL))
- {
- wasChecked = SendMessage(m_hwndToolbar, TB_ISBUTTONCHECKED, m_hotItem, 0);
- if (wasChecked)
- {
- SendMessage(m_hwndToolbar, TB_CHECKBUTTON, m_hotItem, FALSE);
- }
- }
+ // Only notify of LEAVING if this was the hot toolbar.
+ if (m_hotBar == this)
+ {
+ DbgPrint("The hot bar is now cold.\n");
+ hr = m_menuBand->_ChangeHotItem(NULL, -1, hot->dwFlags);
+ }
+ }
+ else
+ {
+ hr = m_menuBand->_ChangeHotItem(this, hot->idNew, hot->dwFlags);
+ }
+
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+
+ // Reuse S_OK/S_FALSE as Continue/Cancel
+ *theResult = hr;
+
+ return S_OK;
+}
+
+HRESULT CMenuToolbarBase::ChangeHotItem(CMenuToolbarBase * toolbar, INT item, DWORD
dwFlags)
+{
+ if (m_hotBar == toolbar && m_hotItem == item)
+ return S_FALSE;
+
+ if (m_hotBar == this && toolbar != this)
+ {
+ SendMessage(m_hwndToolbar, TB_SETHOTITEM, -1, 0);
+ }
+
m_hotBar = toolbar;
m_hotItem = item;
- if (wasChecked && m_hotBar == this && !(m_toolbarFlags &
SMINIT_VERTICAL))
- {
- SendMessage(m_hwndToolbar, TB_CHECKBUTTON, m_hotItem, TRUE);
- }
+
+ if (m_hotBar == this)
+ {
+ if (dwFlags & HICF_MOUSE)
+ {
+ // Vertical menus show/hide the submenu after a delay,
+ // but horizontal menubars switch between items instantly,
+ // if they were open.
+ if (m_initFlags & SMINIT_VERTICAL)
+ {
+ DWORD elapsed = 0;
+ SystemParametersInfo(SPI_GETMENUSHOWDELAY, 0, &elapsed, 0);
+ SetTimer(m_hwndToolbar, TIMERID_HOTTRACK, elapsed, NULL);
+ m_timerEnabled = TRUE;
+ DbgPrint("SetTimer called with m_hotItem=%d\n", m_hotItem);
+ }
+ else if (m_isTracking)
+ {
+ m_menuBand->_KillPopupTimers();
+
+ PopupItem(m_hotItem);
+ }
+ }
+ else
+ {
+ TBBUTTONINFO info;
+ info.cbSize = sizeof(info);
+ info.dwMask = 0;
+
+ int index = SendMessage(m_hwndToolbar, TB_GETBUTTONINFO, item,
reinterpret_cast<LPARAM>(&info));
+
+ SendMessage(m_hwndToolbar, TB_SETHOTITEM, index, 0);
+ }
+ }
+
InvalidateDraw();
return S_OK;
}
-HRESULT CMenuToolbarBase::OnPopupItemChanged(CMenuToolbarBase * toolbar, INT item)
-{
- if (toolbar == NULL && m_popupBar == this)
+HRESULT CMenuToolbarBase::ChangePopupItem(CMenuToolbarBase * toolbar, INT item)
+{
+ if (m_popupBar == toolbar && m_popupItem == item)
+ return S_FALSE;
+
+ if (m_popupBar == this && toolbar != this)
{
SendMessage(m_hwndToolbar, TB_CHECKBUTTON, m_popupItem, FALSE);
m_isTracking = FALSE;
- DbgPrint("%s -- Is Tracking: %d\n", __FUNCTION__, m_isTracking);
- }
+ }
+
m_popupBar = toolbar;
m_popupItem = item;
+
+ if (m_popupBar == this)
+ {
+ SendMessage(m_hwndToolbar, TB_CHECKBUTTON, m_popupItem, TRUE);
+ }
+
InvalidateDraw();
return S_OK;
}
@@ -548,32 +672,32 @@
if (m_hotBar != this)
return S_FALSE;
- SendMessage(m_hwndToolbar, TB_GETBUTTON, index,
reinterpret_cast<LPARAM>(&btn));
+ if (!SendMessage(m_hwndToolbar, TB_GETBUTTON, index,
reinterpret_cast<LPARAM>(&btn)))
+ return E_FAIL;
if (m_hotItem == btn.idCommand)
return S_OK;
+
+ if (m_popupItem == btn.idCommand)
+ return S_OK;
+
return S_FALSE;
}
HRESULT CMenuToolbarBase::ChangeTrackedItem(INT index)
{
TBBUTTON btn;
- SendMessage(m_hwndToolbar, TB_GETBUTTON, index,
reinterpret_cast<LPARAM>(&btn));
+ if (!SendMessage(m_hwndToolbar, TB_GETBUTTON, index,
reinterpret_cast<LPARAM>(&btn)))
+ return E_FAIL;
DbgPrint("Changing tracked item to %d...\n", index);
-
- if (m_hotItem != btn.idCommand)
- {
- m_isTracking = TRUE;
- DbgPrint("%s -- Is Tracking: %d\n", __FUNCTION__, m_isTracking);
-
- SendMessage(m_hwndToolbar, TB_SETHOTITEM, index, 0);
- }
-
- return S_OK;
-}
-
-HRESULT CMenuToolbarBase::PopupSubMenu(UINT uItem, UINT index, IShellMenu*
childShellMenu)
+ m_isTracking = TRUE;
+ m_menuBand->_ChangeHotItem(this, btn.idCommand, HICF_MOUSE);
+
+ return S_OK;
+}
+
+HRESULT CMenuToolbarBase::PopupSubMenu(UINT iItem, UINT index, IShellMenu*
childShellMenu)
{
IBandSite* pBandSite;
IDeskBar* pDeskBar;
@@ -600,7 +724,7 @@
POINTL pt = { a.x, b.y };
RECTL rcl = { c.x, c.y, d.x, d.y };
- if (m_toolbarFlags & SMINIT_VERTICAL)
+ if (m_initFlags & SMINIT_VERTICAL)
{
pt.x = b.x - 3;
pt.y = a.y - 3;
@@ -652,14 +776,14 @@
return hr;
m_isTracking = TRUE;
- DbgPrint("%s -- Is Tracking: %d\n", __FUNCTION__, m_isTracking);
-
- m_menuBand->_OnPopupSubMenu(popup, &pt, &rcl, this, uItem);
-
- return S_OK;
-}
-
-HRESULT CMenuToolbarBase::PopupSubMenu(UINT uItem, UINT index, HMENU menu)
+
+ m_menuBand->_ChangePopupItem(this, iItem);
+ m_menuBand->_OnPopupSubMenu(popup, &pt, &rcl);
+
+ return S_OK;
+}
+
+HRESULT CMenuToolbarBase::PopupSubMenu(UINT iItem, UINT index, HMENU menu)
{
RECT rc = { 0 };
RECT rcx = { 0 };
@@ -682,7 +806,7 @@
POINT pt = { a.x, b.y };
RECT rcl = { c.x, c.y, d.x, d.y };
- if (m_toolbarFlags & SMINIT_VERTICAL)
+ if (m_initFlags & SMINIT_VERTICAL)
{
pt.x = b.x;
pt.y = a.y;
@@ -691,14 +815,12 @@
HMENU popup = GetSubMenu(menu, index);
m_isTracking = TRUE;
- DbgPrint("%s -- Is Tracking: %d\n", __FUNCTION__, m_isTracking);
-
+
+ m_menuBand->_ChangePopupItem(this, iItem);
m_menuBand->_TrackSubMenuUsingTrackPopupMenu(popup, pt.x, pt.y, rcl);
-
- SendMessage(m_hwndToolbar, TB_CHECKBUTTON, uItem, FALSE);
+ m_menuBand->_ChangePopupItem(NULL, -1);
m_isTracking = FALSE;
- DbgPrint("%s -- Is Tracking: %d\n", __FUNCTION__, m_isTracking);
return S_OK;
}
@@ -735,12 +857,24 @@
HRESULT CMenuToolbarBase::OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult)
{
- theResult = 0;
-
- KillTimer(m_hwndToolbar, TIMERID_HOTTRACK);
+ if (m_disableMouseTrack)
+ {
+ *theResult = 1;
+ DbgPrint("Item click prevented by DisableMouseTrack\n");
+ return S_OK;
+ }
+
+ *theResult = 0;
+
+ m_menuBand->_KillPopupTimers();
if (PopupItem(wParam) == S_OK)
+ {
+ DbgPrint("PopupItem returned S_OK\n");
return S_FALSE;
+ }
+
+ DbgPrint("Executing...\n");
HRESULT hr = m_menuBand->_MenuItemHotTrack(MPOS_EXECUTE);
@@ -750,7 +884,7 @@
return S_OK; // filter out a possible S_FALSE from here.
}
-HRESULT CMenuToolbarBase::ChangeHotItem(DWORD dwSelectType)
+HRESULT CMenuToolbarBase::KeyboardItemChange(DWORD dwSelectType)
{
int prev = m_hotItem;
int index = -1;
@@ -811,6 +945,7 @@
{
if (prev != btn.idCommand)
{
+ DbgPrint("Setting Hot item to %d\n", index);
SendMessage(m_hwndToolbar, TB_SETHOTITEM, index, 0);
}
return S_OK;
@@ -829,6 +964,7 @@
if (prev != -1)
{
+ DbgPrint("Setting Hot item to null\n");
SendMessage(m_hwndToolbar, TB_SETHOTITEM, -1, 0);
}
return S_FALSE;
@@ -840,16 +976,16 @@
tbb.fsState = TBSTATE_ENABLED;
#if !USE_TBSTYLE_EX_VERTICAL
- if (!last && (m_toolbarFlags & SMINIT_VERTICAL))
+ if (!last && (m_initFlags & SMINIT_VERTICAL))
tbb.fsState |= TBSTATE_WRAP;
#endif
- tbb.fsStyle = 0;
-
- if (hasSubMenu && (m_toolbarFlags & SMINIT_VERTICAL))
+ tbb.fsStyle = BTNS_CHECKGROUP;
+
+ if (hasSubMenu && (m_initFlags & SMINIT_VERTICAL))
tbb.fsStyle |= BTNS_DROPDOWN;
- if (!(m_toolbarFlags & SMINIT_VERTICAL))
- tbb.fsStyle |= BTNS_AUTOSIZE | BTNS_CHECKGROUP;
+ if (!(m_initFlags & SMINIT_VERTICAL))
+ tbb.fsStyle |= BTNS_AUTOSIZE;
tbb.iString = (INT_PTR) caption;
tbb.idCommand = commandId;
@@ -869,7 +1005,7 @@
tbb.fsState = TBSTATE_ENABLED;
#if !USE_TBSTYLE_EX_VERTICAL
- if (!last && (m_toolbarFlags & SMINIT_VERTICAL))
+ if (!last && (m_initFlags & SMINIT_VERTICAL))
tbb.fsState |= TBSTATE_WRAP;
#endif
tbb.fsStyle = BTNS_SEP;
@@ -897,15 +1033,23 @@
return S_OK;
}
-HRESULT CMenuToolbarBase::GetDataFromId(INT uItem, INT* pIndex, DWORD_PTR* pData)
-{
+HRESULT CMenuToolbarBase::GetDataFromId(INT iItem, INT* pIndex, DWORD_PTR* pData)
+{
+ if (pData)
+ *pData = NULL;
+
+ if (pIndex)
+ *pIndex = -1;
+
+ if (iItem < 0)
+ return S_OK;
+
TBBUTTONINFO info = { 0 };
- DbgPrint("GetDataFromId %d\n", uItem);
info.cbSize = sizeof(TBBUTTONINFO);
info.dwMask = TBIF_COMMAND | TBIF_LPARAM;
- int index = SendMessage(m_hwndToolbar, TB_GETBUTTONINFO, uItem,
reinterpret_cast<LPARAM>(&info));
+ int index = SendMessage(m_hwndToolbar, TB_GETBUTTONINFO, iItem,
reinterpret_cast<LPARAM>(&info));
if (index < 0)
return E_FAIL;
@@ -915,29 +1059,45 @@
if (pData)
*pData = info.lParam;
- DbgPrint("GetDataFromId ret: %d, %d, %x, %x\n", info.idCommand, index,
info.lParam);
-
- return S_OK;
-}
-
-HRESULT CMenuToolbarBase::PopupItem(INT uItem)
+ return S_OK;
+}
+
+HRESULT CMenuToolbarBase::CancelCurrentPopup()
+{
+ return m_menuBand->_CancelCurrentPopup();
+}
+
+HRESULT CMenuToolbarBase::PopupItem(INT iItem)
{
INT index;
DWORD_PTR dwData;
- GetDataFromId(uItem, &index, &dwData);
-
- if (!(m_toolbarFlags & SMINIT_VERTICAL))
- {
- SendMessage(m_hwndToolbar, TB_SETHOTITEM, index, 0);
- SendMessage(m_hwndToolbar, TB_CHECKBUTTON, uItem, TRUE);
- }
-
- HRESULT hr = InternalHasSubMenu(uItem, index, dwData);
+ if (iItem < 0)
+ return S_OK;
+
+ if (m_popupBar == this && m_popupItem == iItem)
+ return S_OK;
+
+ GetDataFromId(iItem, &index, &dwData);
+
+ HRESULT hr = InternalHasSubMenu(iItem, index, dwData);
if (hr != S_OK)
return hr;
- return InternalPopupItem(uItem, index, dwData);
+ if (m_popupBar)
+ {
+ HRESULT hr = CancelCurrentPopup();
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+ }
+
+ if (!(m_initFlags & SMINIT_VERTICAL))
+ {
+ DbgPrint("PopupItem non-vertical %d %d\n", index, iItem);
+ m_menuBand->_ChangeHotItem(this, iItem, 0);
+ }
+
+ return InternalPopupItem(iItem, index, dwData);
}
CMenuStaticToolbar::CMenuStaticToolbar(CMenuBand *menuBand) :
@@ -1031,9 +1191,14 @@
}
}
- DbgPrint("Created toolbar with %d buttons.\n", count);
-
- return S_OK;
+ return S_OK;
+}
+
+HRESULT CMenuStaticToolbar::GetInfoTip(LPWSTR pszText, INT cchTextMax, INT iItem, INT
index, DWORD_PTR dwData)
+{
+ //SMINFO * info = reinterpret_cast<SMINFO*>(dwData);
+ UNIMPLEMENTED;
+ return E_NOTIMPL;
}
HRESULT CMenuStaticToolbar::OnDeletingButton(const NMTOOLBAR * tb)
@@ -1074,7 +1239,7 @@
return m_menuBand->_CallCBWithItemId(wParam, SMC_EXEC, 0, 0);
}
-HRESULT CMenuStaticToolbar::InternalPopupItem(INT uItem, INT index, DWORD_PTR dwData)
+HRESULT CMenuStaticToolbar::InternalPopupItem(INT iItem, INT index, DWORD_PTR dwData)
{
SMINFO * nfo = reinterpret_cast<SMINFO*>(dwData);
if (!nfo)
@@ -1082,20 +1247,20 @@
if (nfo->dwFlags&SMIF_TRACKPOPUP)
{
- return PopupSubMenu(uItem, index, m_hmenu);
+ return PopupSubMenu(iItem, index, m_hmenu);
}
else
{
CComPtr<IShellMenu> shellMenu;
- HRESULT hr = m_menuBand->_CallCBWithItemId(uItem, SMC_GETOBJECT,
reinterpret_cast<WPARAM>(&IID_IShellMenu),
reinterpret_cast<LPARAM>(&shellMenu));
+ HRESULT hr = m_menuBand->_CallCBWithItemId(iItem, SMC_GETOBJECT,
reinterpret_cast<WPARAM>(&IID_IShellMenu),
reinterpret_cast<LPARAM>(&shellMenu));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
- return PopupSubMenu(uItem, index, shellMenu);
- }
-}
-
-HRESULT CMenuStaticToolbar::InternalHasSubMenu(INT uItem, INT index, DWORD_PTR dwData)
+ return PopupSubMenu(iItem, index, shellMenu);
+ }
+}
+
+HRESULT CMenuStaticToolbar::InternalHasSubMenu(INT iItem, INT index, DWORD_PTR dwData)
{
return ::GetSubMenu(m_hmenu, index) ? S_OK : S_FALSE;
}
@@ -1163,9 +1328,14 @@
return AddPlaceholder();
}
- DbgPrint("Created toolbar with %d buttons.\n", i);
-
return hr;
+}
+
+HRESULT CMenuSFToolbar::GetInfoTip(LPWSTR pszText, INT cchTextMax, INT iItem, INT index,
DWORD_PTR dwData)
+{
+ //ITEMIDLIST * pidl = reinterpret_cast<LPITEMIDLIST>(dwData);
+ UNIMPLEMENTED;
+ return E_NOTIMPL;
}
HRESULT CMenuSFToolbar::OnDeletingButton(const NMTOOLBAR * tb)
@@ -1247,7 +1417,7 @@
return m_menuBand->_CallCBWithItemPidl(reinterpret_cast<LPITEMIDLIST>(data),
SMC_SFEXEC, 0, 0);
}
-HRESULT CMenuSFToolbar::InternalPopupItem(INT uItem, INT index, DWORD_PTR dwData)
+HRESULT CMenuSFToolbar::InternalPopupItem(INT iItem, INT index, DWORD_PTR dwData)
{
HRESULT hr;
UINT uId;
@@ -1293,10 +1463,10 @@
if (FAILED_UNEXPECTEDLY(hr))
return hr;
- return PopupSubMenu(uItem, index, shellMenu);
-}
-
-HRESULT CMenuSFToolbar::InternalHasSubMenu(INT uItem, INT index, DWORD_PTR dwData)
+ return PopupSubMenu(iItem, index, shellMenu);
+}
+
+HRESULT CMenuSFToolbar::InternalHasSubMenu(INT iItem, INT index, DWORD_PTR dwData)
{
HRESULT hr;
LPCITEMIDLIST pidl = reinterpret_cast<LPITEMIDLIST>(dwData);
Modified: branches/shell-experiments/base/shell/rshell/CMenuToolbars.h
URL:
http://svn.reactos.org/svn/reactos/branches/shell-experiments/base/shell/rs…
==============================================================================
--- branches/shell-experiments/base/shell/rshell/CMenuToolbars.h [iso-8859-1] (original)
+++ branches/shell-experiments/base/shell/rshell/CMenuToolbars.h [iso-8859-1] Wed Apr 2
17:37:37 2014
@@ -34,6 +34,7 @@
BOOL m_useFlatMenus;
WNDPROC m_SubclassOld;
BOOL m_disableMouseTrack;
+ BOOL m_timerEnabled;
protected:
CMenuBand * m_menuBand;
@@ -47,7 +48,7 @@
CMenuToolbarBase * m_popupBar;
INT m_popupItem;
- DWORD m_toolbarFlags;
+ DWORD m_initFlags;
BOOL m_isTracking;
private:
@@ -65,14 +66,14 @@
HRESULT OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT
*theResult);
- HRESULT OnHotItemChanged(CMenuToolbarBase * toolbar, INT item);
- HRESULT OnPopupItemChanged(CMenuToolbarBase * toolbar, INT item);
+ HRESULT ChangeHotItem(CMenuToolbarBase * toolbar, INT item, DWORD dwFlags);
+ HRESULT ChangePopupItem(CMenuToolbarBase * toolbar, INT item);
HRESULT PopupSubMenu(UINT itemId, UINT index, IShellMenu* childShellMenu);
HRESULT PopupSubMenu(UINT itemId, UINT index, HMENU menu);
HRESULT DoContextMenu(IContextMenu* contextMenu);
- HRESULT ChangeHotItem(DWORD changeType);
+ HRESULT KeyboardItemChange(DWORD changeType);
HRESULT OnHotItemChange(const NMTBHOTITEM * hot, LRESULT * theResult);
HRESULT IsTrackedItem(INT index);
@@ -88,15 +89,20 @@
virtual HRESULT FillToolbar(BOOL clearFirst=FALSE) = 0;
virtual HRESULT OnContextMenu(NMMOUSE * rclick) = 0;
- HRESULT PopupItem(INT uItem);
- HRESULT GetDataFromId(INT uItem, INT* pIndex, DWORD_PTR* pData);
+ HRESULT CancelCurrentPopup();
+ HRESULT PopupItem(INT iItem);
+ HRESULT GetDataFromId(INT iItem, INT* pIndex, DWORD_PTR* pData);
+
+ HRESULT KillPopupTimer();
protected:
virtual HRESULT OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult);
virtual HRESULT OnDeletingButton(const NMTOOLBAR * tb) = 0;
- virtual HRESULT InternalPopupItem(INT uItem, INT index, DWORD_PTR dwData) = 0;
- virtual HRESULT InternalHasSubMenu(INT uItem, INT index, DWORD_PTR dwData) = 0;
+ virtual HRESULT InternalPopupItem(INT iItem, INT index, DWORD_PTR dwData) = 0;
+ virtual HRESULT InternalHasSubMenu(INT iItem, INT index, DWORD_PTR dwData) = 0;
+
+ virtual HRESULT GetInfoTip(LPWSTR pszText, INT cchTextMax, INT iItem, INT index,
DWORD_PTR dwData)=0;
LRESULT CALLBACK SubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
@@ -107,7 +113,10 @@
HRESULT UpdateImageLists();
private:
+ HRESULT OnPagerCalcSize(LPNMPGCALCSIZE csize);
+ HRESULT OnPopupTimer(DWORD timerId);
HRESULT OnCustomDraw(LPNMTBCUSTOMDRAW cdraw, LRESULT * theResult);
+ HRESULT OnGetInfoTip(NMTBGETINFOTIP * tip);
};
class CMenuStaticToolbar :
@@ -130,8 +139,10 @@
protected:
virtual HRESULT OnDeletingButton(const NMTOOLBAR * tb);
- virtual HRESULT InternalPopupItem(INT uItem, INT index, DWORD_PTR dwData);
- virtual HRESULT InternalHasSubMenu(INT uItem, INT index, DWORD_PTR dwData);
+ virtual HRESULT GetInfoTip(LPWSTR pszText, INT cchTextMax, INT iItem, INT index,
DWORD_PTR dwData);
+
+ virtual HRESULT InternalPopupItem(INT iItem, INT index, DWORD_PTR dwData);
+ virtual HRESULT InternalHasSubMenu(INT iItem, INT index, DWORD_PTR dwData);
};
class CMenuSFToolbar :
@@ -156,6 +167,8 @@
protected:
virtual HRESULT OnDeletingButton(const NMTOOLBAR * tb);
- virtual HRESULT InternalPopupItem(INT uItem, INT index, DWORD_PTR dwData);
- virtual HRESULT InternalHasSubMenu(INT uItem, INT index, DWORD_PTR dwData);
+ virtual HRESULT GetInfoTip(LPWSTR pszText, INT cchTextMax, INT iItem, INT index,
DWORD_PTR dwData);
+
+ virtual HRESULT InternalPopupItem(INT iItem, INT index, DWORD_PTR dwData);
+ virtual HRESULT InternalHasSubMenu(INT iItem, INT index, DWORD_PTR dwData);
};
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 Apr 2
17:37:37 2014
@@ -72,7 +72,7 @@
else
fname++;
- szMsgStart = szMsg + sprintf(szMsg, "%s:%d: ", fname, line);
+ szMsgStart = szMsg + sprintf(szMsg, "[%10d] %s:%d: ", GetTickCount(),
fname, line);
va_start(vl, lpFormat);
uRet = (ULONG) vsprintf(szMsgStart, lpFormat, vl);