1*c2c66affSColin Finck /*
2*c2c66affSColin Finck * Shell Menu Band
3*c2c66affSColin Finck *
4*c2c66affSColin Finck * Copyright 2014 David Quintana
5*c2c66affSColin Finck *
6*c2c66affSColin Finck * This library is free software; you can redistribute it and/or
7*c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public
8*c2c66affSColin Finck * License as published by the Free Software Foundation; either
9*c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version.
10*c2c66affSColin Finck *
11*c2c66affSColin Finck * This library is distributed in the hope that it will be useful,
12*c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of
13*c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14*c2c66affSColin Finck * Lesser General Public License for more details.
15*c2c66affSColin Finck *
16*c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public
17*c2c66affSColin Finck * License along with this library; if not, write to the Free Software
18*c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19*c2c66affSColin Finck */
20*c2c66affSColin Finck #pragma once
21*c2c66affSColin Finck 
22*c2c66affSColin Finck class CMenuBand;
23*c2c66affSColin Finck 
24*c2c66affSColin Finck class CMenuFocusManager :
25*c2c66affSColin Finck     public CComCoClass<CMenuFocusManager>,
26*c2c66affSColin Finck     public CComObjectRootEx<CComMultiThreadModelNoCS>
27*c2c66affSColin Finck {
28*c2c66affSColin Finck private:
29*c2c66affSColin Finck     static DWORD TlsIndex;
30*c2c66affSColin Finck 
31*c2c66affSColin Finck     static CMenuFocusManager * GetManager();
32*c2c66affSColin Finck 
33*c2c66affSColin Finck     enum StackEntryType
34*c2c66affSColin Finck     {
35*c2c66affSColin Finck         NoEntry,
36*c2c66affSColin Finck         MenuBarEntry,
37*c2c66affSColin Finck         MenuPopupEntry,
38*c2c66affSColin Finck         TrackedMenuEntry
39*c2c66affSColin Finck     };
40*c2c66affSColin Finck 
41*c2c66affSColin Finck     struct StackEntry
42*c2c66affSColin Finck     {
43*c2c66affSColin Finck         StackEntryType type;
44*c2c66affSColin Finck         CMenuBand *    mb;
45*c2c66affSColin Finck         HMENU          hmenu;
46*c2c66affSColin Finck         HWND           hwnd;
47*c2c66affSColin Finck     };
48*c2c66affSColin Finck 
49*c2c66affSColin Finck public:
50*c2c66affSColin Finck     static CMenuFocusManager * AcquireManager();
51*c2c66affSColin Finck 
52*c2c66affSColin Finck     static void ReleaseManager(CMenuFocusManager * obj);
53*c2c66affSColin Finck 
54*c2c66affSColin Finck private:
55*c2c66affSColin Finck     static LRESULT CALLBACK s_MsgFilterHook(INT nCode, WPARAM wParam, LPARAM lParam);
56*c2c66affSColin Finck     static LRESULT CALLBACK s_GetMsgHook(INT nCode, WPARAM wParam, LPARAM lParam);
57*c2c66affSColin Finck 
58*c2c66affSColin Finck private:
59*c2c66affSColin Finck     StackEntry * m_current;
60*c2c66affSColin Finck     StackEntry * m_parent;
61*c2c66affSColin Finck     StackEntry * m_menuBar;
62*c2c66affSColin Finck 
63*c2c66affSColin Finck     HHOOK m_hMsgFilterHook;
64*c2c66affSColin Finck     HHOOK m_hGetMsgHook;
65*c2c66affSColin Finck     DWORD m_threadId;
66*c2c66affSColin Finck 
67*c2c66affSColin Finck     BOOL m_mouseTrackDisabled;
68*c2c66affSColin Finck 
69*c2c66affSColin Finck     POINT m_ptPrev;
70*c2c66affSColin Finck 
71*c2c66affSColin Finck     HWND m_captureHwnd;
72*c2c66affSColin Finck 
73*c2c66affSColin Finck     HWND m_hwndUnderMouse;
74*c2c66affSColin Finck     StackEntry * m_entryUnderMouse;
75*c2c66affSColin Finck 
76*c2c66affSColin Finck     HMENU m_selectedMenu;
77*c2c66affSColin Finck     INT   m_selectedItem;
78*c2c66affSColin Finck     DWORD m_selectedItemFlags;
79*c2c66affSColin Finck 
80*c2c66affSColin Finck     BOOL m_movedSinceDown;
81*c2c66affSColin Finck     HWND m_windowAtDown;
82*c2c66affSColin Finck 
83*c2c66affSColin Finck     HWND m_PreviousForeground;
84*c2c66affSColin Finck 
85*c2c66affSColin Finck     // TODO: make dynamic
86*c2c66affSColin Finck #define MAX_RECURSE 20
87*c2c66affSColin Finck     StackEntry m_bandStack[MAX_RECURSE];
88*c2c66affSColin Finck     int m_bandCount;
89*c2c66affSColin Finck     int m_menuDepth;
90*c2c66affSColin Finck 
91*c2c66affSColin Finck     HRESULT PushToArray(StackEntryType type, CMenuBand * mb, HMENU hmenu);
92*c2c66affSColin Finck     HRESULT PopFromArray(StackEntryType * pType, CMenuBand ** pMb, HMENU * pHmenu);
93*c2c66affSColin Finck 
94*c2c66affSColin Finck protected:
95*c2c66affSColin Finck     CMenuFocusManager();
96*c2c66affSColin Finck     ~CMenuFocusManager();
97*c2c66affSColin Finck 
98*c2c66affSColin Finck public:
99*c2c66affSColin Finck 
100*c2c66affSColin Finck     DECLARE_NOT_AGGREGATABLE(CMenuFocusManager)
101*c2c66affSColin Finck     DECLARE_PROTECT_FINAL_CONSTRUCT()
102*c2c66affSColin Finck     BEGIN_COM_MAP(CMenuFocusManager)
103*c2c66affSColin Finck     END_COM_MAP()
104*c2c66affSColin Finck 
105*c2c66affSColin Finck private:
106*c2c66affSColin Finck     LRESULT GetMsgHook(INT nCode, WPARAM wParam, LPARAM lParam);
107*c2c66affSColin Finck     LRESULT MsgFilterHook(INT nCode, WPARAM wParam, LPARAM lParam);
108*c2c66affSColin Finck     HRESULT PlaceHooks();
109*c2c66affSColin Finck     HRESULT RemoveHooks();
110*c2c66affSColin Finck     HRESULT UpdateFocus();
111*c2c66affSColin Finck     HRESULT IsTrackedWindow(HWND hWnd, StackEntry ** pentry = NULL);
112*c2c66affSColin Finck     HRESULT IsTrackedWindowOrParent(HWND hWnd);
113*c2c66affSColin Finck 
114*c2c66affSColin Finck     void DisableMouseTrack(HWND parent, BOOL disableThis);
115*c2c66affSColin Finck     void SetMenuCapture(HWND child);
116*c2c66affSColin Finck 
117*c2c66affSColin Finck     LRESULT ProcessMouseMove(MSG* msg);
118*c2c66affSColin Finck     LRESULT ProcessMouseDown(MSG* msg, BOOL isLButton);
119*c2c66affSColin Finck     LRESULT ProcessMouseUp(MSG* msg, BOOL isLButton);
120*c2c66affSColin Finck public:
121*c2c66affSColin Finck     HRESULT PushMenuBar(CMenuBand * mb);
122*c2c66affSColin Finck     HRESULT PushMenuPopup(CMenuBand * mb);
123*c2c66affSColin Finck     HRESULT PushTrackedPopup(HMENU popup);
124*c2c66affSColin Finck     HRESULT PopMenuBar(CMenuBand * mb);
125*c2c66affSColin Finck     HRESULT PopMenuPopup(CMenuBand * mb);
126*c2c66affSColin Finck     HRESULT PopTrackedPopup(HMENU popup);
127*c2c66affSColin Finck };
128