2#include <control/SMenuBar.h>
12const wchar_t XmlBtnStyle[] = L
"btnStyle";
13const wchar_t XmlMenus[] = L
"menus";
18 DEF_SOBJECT(
SButton, L
"menuItem")
19 friend class SMenuBar;
22 SMenuBarItem(SMenuBar *pHostMenu);
25 void SetData(ULONG_PTR data)
34 bool IsMenuLoaded()
const;
39 HRESULT OnAttrSrc(
const SStringW &strValue, BOOL bLoading);
41 virtual void WINAPI OnFinalRelease()
45 STDMETHOD_(
void, GetDesiredSize)(THIS_ SIZE *psz,
int nParentWid,
int nParentHei);
46 BOOL OnCmd(IEvtArgs *e);
48 void OnTimer(
char timerID);
51 MSG_WM_TIMER_EX(OnTimer)
55 ATTR_CUSTOM(L
"src", OnAttrSrc)
59 SMenuBar *m_pHostMenu;
65SMenuBarItem::SMenuBarItem(
SMenuBar *pHostMenu)
67 , m_pHostMenu(pHostMenu)
68 , m_bIsRegHotKey(FALSE)
76SMenuBarItem::~SMenuBarItem()
80bool SMenuBarItem::IsMenuLoaded()
const
85UINT SMenuBarItem::PopMenu()
87 if (m_pHostMenu->m_pNowMenu != NULL)
89 m_pHostMenu->m_bIsShow = TRUE;
90 m_pHostMenu->m_pNowMenu =
this;
91 m_pHostMenu->m_iNowMenu = m_iIndex;
94 EventPopMenu evt_pop(m_pHostMenu);
95 evt_pop.nMenuIndex = m_iIndex;
107 GetCurrentThreadId());
110 iRet =
TrackPopupMenu(TPM_RETURNCMD, rcHost.left + rcMenu.left, rcHost.top + rcMenu.bottom + 2, m_pHostMenu->m_hWnd);
113 m_pHostMenu->m_bIsShow = FALSE;
114 if (m_pHostMenu->m_pNowMenu !=
this || iRet == 0)
116 m_pHostMenu->m_pNowMenu = NULL;
117 m_pHostMenu->m_iNowMenu = -1;
120 SSLOGI() <<
"###quit menu and kill timer for " << m_pHostMenu->m_iNowMenu;
121 m_pHostMenu->m_pNowMenu->KillTimer(TIMER_POP);
122 m_pHostMenu->m_iNowMenu = -1;
123 m_pHostMenu->m_pNowMenu = NULL;
130 EventSelectMenu evt_sel(m_pHostMenu);
131 evt_sel.nMenuId = iRet;
132 evt_sel.pMenu =
this;
138HRESULT SMenuBarItem::OnAttrSrc(
const SStringW &strValue, BOOL bLoading)
140 return LoadMenu(S_CW2T(strValue)) ? S_OK : E_INVALIDARG;
143void SMenuBarItem::GetDesiredSize(SIZE *psz,
int nParentWid,
int nParentHei)
150BOOL SMenuBarItem::OnCmd(IEvtArgs *e)
152 if (!::IsWindow(m_pHostMenu->m_hWnd))
155 e->SetBubbleUp(
false);
160void SMenuBarItem::OnTimer(
char timerID)
162 if (timerID == TIMER_POP)
164 if (!m_pHostMenu->m_bIsShow)
182 m_evtSet.addEvent(EVENTID(EventSelectMenu));
199 SMenuBarItem *pNewMenu =
new SMenuBarItem(
this);
210 pNewMenu->SetAttribute(L
"src", S_CT2W(pszResName));
213 if (!pNewMenu->IsMenuLoaded())
219 SStringT strText = pszTitle;
220 int nPos = strText.ReverseFind(
'&');
222 pNewMenu->SetAttribute(L
"accel",
SStringW().Format(L
"alt+%c", strText[nPos + 1]));
228 pNewMenu->m_iIndex = iPos;
238 SMenuBarItem *pNewMenu =
new SMenuBarItem(
this);
247 if (!pNewMenu->IsMenuLoaded())
257 pNewMenu->SetAttribute(L
"accel",
SStringW().Format(L
"alt+%c", strText[nPos + 1]));
263 pNewMenu->m_iIndex = iPos;
283 if (rcItem.PtInRect(pt))
318 if (code == MSGF_MENU)
320 MSG msg = *(MSG *)lParam;
321 int nMsg = msg.message;
326 CPoint pt(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam));
339 ::PostMessage(msg.hwnd, WM_CANCELMODE, 0, 0);
346 SSLOGI() <<
"###set timer for " << nIndex;
355 TCHAR vKey = (TCHAR)msg.wParam;
358 if (vKey != VK_LEFT && vKey != VK_RIGHT)
364 for (
int i = 0; i < GetMenuItemCount(pNowMenu->m_hMenu); i++)
366 MENUITEMINFO mii = { 0 };
367 mii.cbSize =
sizeof(MENUITEMINFO);
368 mii.fMask = MIIM_STATE | MIIM_SUBMENU;
369 GetMenuItemInfo(pNowMenu->m_hMenu, i, TRUE, &mii);
370 if (mii.fState & MF_HILITE)
373 hSubMenu = mii.hSubMenu;
377 if (selItem != -1 && hSubMenu)
379 BOOL isMenuExpended = IsWindowVisible((HWND)hSubMenu);
380 if (isMenuExpended && vKey == VK_LEFT)
384 if (!isMenuExpended && vKey == VK_RIGHT)
400 ::PostMessage(msg.hwnd, WM_CANCELMODE, 0, 0);
405 else if (vKey == VK_RIGHT)
416 ::PostMessage(msg.hwnd, WM_CANCELMODE, 0, 0);
424 return CallNextHookEx(
m_hMsgHook, code, wParam, lParam);
BOOL subscribeEvent(DWORD dwEventID, const IEvtSlot &subscriber)
订阅事件
static LPCWSTR GetClassName()
A class representing an ASCII string.
int ReverseFind(wchar_t ch) SCONST
Finds the last occurrence of a character in the string.
BOOL SetTimer(char id, UINT uElapse) OVERRIDE
Sets a timer for the window.
BOOL FireEvent(IEvtArgs *evt) OVERRIDE
Fires an event.
BOOL DestroyChild(SWindow *pChild)
Destroys a child window.
void GetDesiredSize(SIZE *psz, int nParentWid, int nParentHei) OVERRIDE
Retrieves the desired size of the window.
void GetClientRect(LPRECT prect) SCONST OVERRIDE
Retrieves the client rectangle of the window.
CRect GetWindowRect() const
Retrieves the bounding rectangle of the window.
ISwndContainer * GetContainer() OVERRIDE
Retrieves the container associated with this window.
virtual CRect GetClientRect() const
Retrieves the client rectangle of the window.
void InsertChild(SWindow *pNewChild, SWindow *pInsertAfter=NULL)
Inserts a child window into the window tree.
void SetCheck(BOOL bCheck) OVERRIDE
Sets the check state of the window.
SEventSet * GetEventSet()
Retrieves the event set associated with the window.
BOOL KillTimer(char id) OVERRIDE
Kills a timer for the window.
void SetWindowText(LPCTSTR lpszText) OVERRIDE
Sets the window text.
void SetMsgHandled(BOOL bHandled)
Sets the message handled flag.
Class representing an XML node.
SXmlNode next_sibling() const
Gets the next sibling node in the children list of the parent node.
SXmlNode first_child() const
Gets the first child node of the node.
SXmlNode child(const wchar_t *name, bool bCaseSensitive=false) const
Gets the child node, attribute, or next/previous sibling with the specified name.
const wchar_t * value() const
Gets the value of the node.
HWND GetHostHwnd() PURE
Retrieves the handle to the host window.