4 * Copyright 2014 Giannis Adamopoulos
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 /* NOTE: The following constants may *NOT* be changed because
24 they're hardcoded and need to be the exact values
25 in order to get the start menu to work! */
26 #define IDM_PROGRAMS 504
27 #define IDM_FAVORITES 507
28 #define IDM_DOCUMENTS 501
29 #define IDM_SETTINGS 508
30 #define IDM_CONTROLPANEL 505
31 #define IDM_SECURITY 5001
32 #define IDM_NETWORKCONNECTIONS 557
33 #define IDM_PRINTERSANDFAXES 510
34 #define IDM_TASKBARANDSTARTMENU 413
35 #define IDM_SEARCH 520
36 #define IDM_HELPANDSUPPORT 503
38 #define IDM_SYNCHRONIZE 553
39 #define IDM_LOGOFF 402
40 #define IDM_DISCONNECT 5000
41 #define IDM_UNDOCKCOMPUTER 410
42 #define IDM_SHUTDOWN 506
43 #define IDM_LASTSTARTMENU_SEPARATOR 450
47 * 1. append the start menu contents from all users
48 * 2. implement the context menu for start menu entries (programs, control panel, network connetions, printers)
49 * 3. filter out programs folder from the shell folder part of the start menu
52 class CShellMenuCallback
:
53 public CComObjectRootEx
<CComMultiThreadModelNoCS
>,
54 public IShellMenuCallback
59 CComPtr
<IShellMenu
> m_pShellMenu
;
60 CComPtr
<IBandSite
> m_pBandSite
;
61 CComPtr
<IDeskBar
> m_pDeskBar
;
62 CComPtr
<ITrayPriv
> m_pTrayPriv
;
72 hr
= IUnknown_GetSite(m_pDeskBar
, IID_PPV_ARG(ITrayPriv
, &m_pTrayPriv
));
73 hr
= IUnknown_GetWindow(m_pTrayPriv
, &m_hwndTray
);
74 hr
= m_pTrayPriv
->AppendMenuW(&hmenu
);
75 hr
= m_pShellMenu
->SetMenu(hmenu
, NULL
, SMSET_BOTTOM
);
80 HRESULT
OnGetInfo(LPSMDATA psmd
, SMINFO
*psminfo
)
86 case IDM_PROGRAMS
: iconIndex
= -20; break;
87 case IDM_FAVORITES
: iconIndex
= -173; break;
88 case IDM_DOCUMENTS
: iconIndex
= -21; break;
89 case IDM_SETTINGS
: iconIndex
= -22; break;
90 case IDM_CONTROLPANEL
: iconIndex
= -22; break;
91 //case IDM_SECURITY: iconIndex = -21; break;
92 case IDM_NETWORKCONNECTIONS
: iconIndex
= -257; break;
93 case IDM_PRINTERSANDFAXES
: iconIndex
= -138; break;
94 case IDM_TASKBARANDSTARTMENU
: iconIndex
= -40; break;
95 case IDM_SEARCH
: iconIndex
= -23; break;
96 case IDM_HELPANDSUPPORT
: iconIndex
= -24; break;
97 case IDM_RUN
: iconIndex
= -25; break;
98 //case IDM_SYNCHRONIZE: iconIndex = -21; break;
99 case IDM_LOGOFF
: iconIndex
= -45; break;
100 //case IDM_DISCONNECT: iconIndex = -21; break;
101 //case IDM_UNDOCKCOMPUTER: iconIndex = -21; break;
102 case IDM_SHUTDOWN
: iconIndex
= -28; break;
109 psminfo
->dwMask
= SMIM_ICON
;
110 psminfo
->iIcon
= Shell_GetCachedImageIndex(L
"shell32.dll", iconIndex
, FALSE
);
115 HRESULT
OnGetSubMenu(LPSMDATA psmd
, REFIID iid
, void ** pv
)
119 IShellMenu
*pShellMenu
;
123 case IDM_PROGRAMS
: csidl
= CSIDL_PROGRAMS
; break;
124 case IDM_FAVORITES
: csidl
= CSIDL_FAVORITES
; break;
125 case IDM_DOCUMENTS
: csidl
= CSIDL_RECENT
; break;
128 hr
= CoCreateInstance(CLSID_MenuBand
,
130 CLSCTX_INPROC_SERVER
,
131 IID_PPV_ARG(IShellMenu
,&pShellMenu
));
133 hr
= pShellMenu
->Initialize(this, 0, ANCESTORDEFAULT
, SMINIT_VERTICAL
);
137 LPITEMIDLIST pidlStartMenu
;
138 IShellFolder
*psfDestop
, *psfStartMenu
;
140 hr
= SHGetFolderLocation(NULL
, csidl
, 0, 0, &pidlStartMenu
);
141 hr
= SHGetDesktopFolder(&psfDestop
);
142 hr
= psfDestop
->BindToObject(pidlStartMenu
, NULL
, IID_PPV_ARG(IShellFolder
, &psfStartMenu
));
144 hr
= pShellMenu
->SetShellFolder(psfStartMenu
, NULL
, NULL
, 0);
149 mii
.cbSize
= sizeof(mii
);
150 mii
.fMask
= MIIM_SUBMENU
;
151 if (GetMenuItemInfoW( psmd
->hmenu
, psmd
->uId
, FALSE
, &mii
))
153 hr
= pShellMenu
->SetMenu(mii
.hSubMenu
, NULL
, SMSET_BOTTOM
);
156 return pShellMenu
->QueryInterface(iid
, pv
);
159 HRESULT
OnGetContextMenu(LPSMDATA psmd
, REFIID iid
, void ** pv
)
161 if (psmd
->uId
== IDM_PROGRAMS
||
162 psmd
->uId
== IDM_CONTROLPANEL
||
163 psmd
->uId
== IDM_NETWORKCONNECTIONS
||
164 psmd
->uId
== IDM_PRINTERSANDFAXES
)
172 HRESULT
OnGetObject(LPSMDATA psmd
, REFIID iid
, void ** pv
)
174 if (IsEqualIID(iid
, IID_IShellMenu
))
175 return OnGetSubMenu(psmd
, iid
, pv
);
176 else if (IsEqualIID( iid
, IID_IContextMenu
))
177 return OnGetContextMenu(psmd
, iid
, pv
);
182 HRESULT
OnExec(LPSMDATA psmd
)
184 if(psmd
->uId
== IDM_CONTROLPANEL
)
185 ShellExecuteW(NULL
, L
"open", L
"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}", NULL
,NULL
, 1);
186 else if(psmd
->uId
== IDM_NETWORKCONNECTIONS
)
187 ShellExecuteW(NULL
, L
"open", L
"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{7007ACC7-3202-11D1-AAD2-00805FC1270E}", NULL
,NULL
, 1);
188 else if(psmd
->uId
== IDM_PRINTERSANDFAXES
)
189 ShellExecuteW(NULL
, L
"open", L
"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{2227A280-3AEA-1069-A2DE-08002B30309D}", NULL
,NULL
, 1);
191 PostMessageW( m_hwndTray
, WM_COMMAND
, psmd
->uId
, 0);
198 DECLARE_NOT_AGGREGATABLE(CShellMenuCallback
)
199 DECLARE_PROTECT_FINAL_CONSTRUCT()
200 BEGIN_COM_MAP(CShellMenuCallback
)
201 COM_INTERFACE_ENTRY_IID(IID_IShellMenuCallback
, IShellMenuCallback
)
205 IShellMenu
* pShellMenu
,
206 IBandSite
* pBandSite
,
209 m_pShellMenu
.Attach(pShellMenu
);
210 m_pBandSite
.Attach(pBandSite
);
211 m_pDeskBar
.Attach(pDeskBar
);
214 ~CShellMenuCallback()
216 m_pShellMenu
.Release();
217 m_pBandSite
.Release();
218 m_pDeskBar
.Release();
221 HRESULT STDMETHODCALLTYPE
CallbackSM(
232 return OnGetInfo(psmd
, reinterpret_cast<SMINFO
*>(lParam
));
234 return OnGetObject(psmd
, *reinterpret_cast<IID
*>(wParam
), reinterpret_cast<void **>(lParam
));
238 m_pTrayPriv
->Execute(psmd
->psf
, psmd
->pidlItem
);
248 CStartMenu_Constructor(
252 IShellMenu
* pShellMenu
;
253 IBandSite
* pBandSite
;
255 IShellMenuCallback
* callback
;
256 LPITEMIDLIST pidlStartMenu
;
259 IShellFolder
*shellFolder
;
260 IShellFolder
*psfStartMenu
;
262 hr
= CoCreateInstance(CLSID_MenuBand
,
264 CLSCTX_INPROC_SERVER
,
265 IID_PPV_ARG(IShellMenu
, &pShellMenu
));
270 hr
= CoCreateInstance(CLSID_MenuBandSite
,
272 CLSCTX_INPROC_SERVER
,
273 IID_PPV_ARG(IBandSite
, &pBandSite
));
275 hr
= CMenuSite_Constructor(IID_PPV_ARG(IBandSite
, &pBandSite
));
280 hr
= CoCreateInstance(CLSID_MenuDeskBar
,
282 CLSCTX_INPROC_SERVER
,
283 IID_PPV_ARG(IDeskBar
, &pDeskBar
));
287 CComObject
<CShellMenuCallback
> *pCallback
;
288 hr
= CComObject
<CShellMenuCallback
>::CreateInstance(&pCallback
);
291 pCallback
->AddRef(); // CreateInstance returns object with 0 ref count */
292 pCallback
->Initialize(pShellMenu
, pBandSite
, pDeskBar
);
293 callback
= pCallback
;
295 hr
= CShellMenuCallback::_CreatorClass::CreateInstance(NULL
, IID_PPV_ARG(IShellMenuCallback
, &callback
));
299 pShellMenu
->Initialize(pCallback
, -1, 0, SMINIT_TOPLEVEL
| SMINIT_VERTICAL
);
303 hr
= SHGetFolderLocation(NULL
, CSIDL_STARTMENU
, 0, 0, &pidlStartMenu
);
304 hr
= SHGetDesktopFolder(&shellFolder
);
305 hr
= shellFolder
->BindToObject(pidlStartMenu
, NULL
, IID_IShellFolder
, (void**)&psfStartMenu
);
307 hr
= pShellMenu
->SetShellFolder(psfStartMenu
, NULL
, NULL
, 0);
309 hr
= pDeskBar
->SetClient(pBandSite
);
313 hr
= pBandSite
->AddBand(pShellMenu
);
317 return pDeskBar
->QueryInterface(riid
, ppv
);