1 /*
2  * Copyright 2003, 2004 Martin Fuchs
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18 
19 
20  //
21  // Explorer and Desktop clone
22  //
23  // startmenu.h
24  //
25  // Martin Fuchs, 16.08.2003
26  //
27 
28 
29 #define	CLASSNAME_STARTMENU		TEXT("ReactOSStartmenuClass")
30 #define	TITLE_STARTMENU			TEXT("Start Menu")
31 
32 
33 #define	STARTMENU_WIDTH_MIN					120
34 #define	STARTMENU_LINE_HEIGHT(icon_size)	(icon_size+4)
35 #define	STARTMENU_SEP_HEIGHT(icon_size)		(STARTMENU_LINE_HEIGHT(icon_size)/2)
36 #define	STARTMENU_TOP_BTN_SPACE				8
37 
38 
39  // private message constants
40 #define	PM_STARTMENU_CLOSED		(WM_APP+0x11)
41 #define	PM_STARTENTRY_LAUNCHED	(WM_APP+0x12)
42 
43 #ifndef _LIGHT_STARTMENU
44 #define	PM_STARTENTRY_FOCUSED	(WM_APP+0x13)
45 #endif
46 
47 #define	PM_UPDATE_ICONS			(WM_APP+0x14)
48 #define	PM_SELECT_ENTRY			(WM_APP+0x15)
49 
50 
51  /// StartMenuDirectory is used to store the base directory of start menus.
52 struct StartMenuDirectory
53 {
54 	StartMenuDirectory(const ShellDirectory& dir, const String& ignore="")
55 	 :	_dir(dir), _ignore(ignore)
56 	{
57 	}
58 
59 	~StartMenuDirectory()
60 	{
61 		_dir.free_subentries();
62 	}
63 
64 	ShellDirectory _dir;
65 	String	_ignore;
66 };
67 
68 typedef list<StartMenuDirectory> StartMenuShellDirs;
69 typedef set<Entry*> ShellEntrySet;
70 
71  /// structure holding information about one start menu entry
72 struct StartMenuEntry
73 {
74 	StartMenuEntry() : _icon_id(ICID_UNKNOWN) {}
75 
76 	String	_title;
77 	ICON_ID	_icon_id;
78 	ShellEntrySet _entries;
79 };
80 
81 
82 extern int GetStartMenuBtnTextWidth(HDC hdc, LPCTSTR title, HWND hwnd);
83 
84 
85 #ifndef _LIGHT_STARTMENU
86 
87  /**
88 	StartMenuButton draws the face of a StartMenuCtrl button control.
89  */
90 struct StartMenuButton : public OwnerdrawnButton
91 {
92 	typedef OwnerdrawnButton super;
93 
94 	StartMenuButton(HWND hwnd, ICON_ID icon_id, bool hasSubmenu)
95 	 :	super(hwnd), _hIcon(hIcon), _hasSubmenu(hasSubmenu) {}
96 
97 protected:
98 	LRESULT	WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam);
99 	virtual void DrawItem(LPDRAWITEMSTRUCT dis);
100 
101 	ICON_ID	_icon_id;
102 	bool	_hasSubmenu;
103 };
104 
105 
106  /**
107 	To create a Startmenu button control, construct a StartMenuCtrl object.
108  */
109 struct StartMenuCtrl : public Button
110 {
111 	StartMenuCtrl(HWND parent, int x, int y, int w, LPCTSTR title,
112 					UINT id, HICON hIcon=0, bool hasSubmenu=false, DWORD style=WS_VISIBLE|WS_CHILD|BS_OWNERDRAW, DWORD exStyle=0)
113 	 :	Button(parent, title, x, y, w, STARTMENU_LINE_HEIGHT(icon_size), id, style, exStyle)
114 	{
115 		*new StartMenuButton(_hwnd, hIcon, hasSubmenu);
116 
117 		SetWindowFont(_hwnd, GetStockFont(DEFAULT_GUI_FONT), FALSE);
118 	}
119 };
120 
121 
122  /// separator between start menu entries
123 struct StartMenuSeparator : public Static
124 {
125 	StartMenuSeparator(HWND parent, int x, int y, int w, DWORD style=WS_VISIBLE|WS_CHILD|WS_DISABLED|SS_ETCHEDHORZ, DWORD exStyle=0)
126 	 :	Static(parent, NULL, x, y+STARTMENU_SEP_HEIGHT(icon_size)/2-1, w, 2, -1, style, exStyle)
127 	{
128 	}
129 };
130 
131 #endif
132 
133 
134 typedef list<ShellPath> StartMenuFolders;
135 
136  /// structor containing information for creating of start menus
137 struct StartMenuCreateInfo
138 {
139 	StartMenuCreateInfo() : _border_top(0) {}
140 
141 	StartMenuFolders _folders;
142 	int		_border_top;
143 	String	_title;
144 	Window::CREATORFUNC_INFO _creator;
145 	void*	_info;
146 	String	_filter;
147 };
148 
149 #define STARTMENU_CREATOR(WND_CLASS) WINDOW_CREATOR_INFO(WND_CLASS, StartMenuCreateInfo)
150 
151 typedef map<int, StartMenuEntry> ShellEntryMap;
152 
153 
154 #ifdef _LIGHT_STARTMENU
155 
156 struct SMBtnInfo
157 {
158 	SMBtnInfo(const StartMenuEntry& entry, int id, bool hasSubmenu=false, bool enabled=true)
159 	 :	_title(entry._title),
160 		_icon_id(entry._icon_id),
161 		_id(id),
162 		_hasSubmenu(hasSubmenu),
163 		_enabled(enabled)
164 	{
165 	}
166 
167 	SMBtnInfo(LPCTSTR title, ICON_ID icon_id, int id, bool hasSubmenu=false, bool enabled=true)
168 	 :	_title(title),
169 		_icon_id(icon_id),
170 		_id(id),
171 		_hasSubmenu(hasSubmenu),
172 		_enabled(enabled)
173 	{
174 	}
175 
176 	String	_title;
177 	ICON_ID	_icon_id;
178 	int		_id;
179 	bool	_hasSubmenu;
180 	bool	_enabled;
181 };
182 
183 typedef vector<SMBtnInfo> SMBtnVector;
184 
185 extern void DrawStartMenuButton(HDC hdc, const RECT& rect, LPCTSTR title, const SMBtnInfo& btn, bool has_focus, bool pushed, int icon_size);
186 
187 #else
188 
189 extern void DrawStartMenuButton(HDC hdc, const RECT& rect, LPCTSTR title, HICON hIcon,
190 								bool hasSubmenu, bool enabled, bool has_focus, bool pushed, int icon_size);
191 
192 #endif
193 
194 
195  /**
196 	Startmenu window.
197 	To create a start menu call its Create() function.
198  */
199 struct StartMenu :
200 #ifdef _LIGHT_STARTMENU
201 	public ExtContextMenuHandlerT<OwnerDrawParent<Window> >
202 #else
203 	public ExtContextMenuHandlerT<OwnerDrawParent<DialogWindow> >
204 #endif
205 {
206 #ifdef _LIGHT_STARTMENU
207 	typedef ExtContextMenuHandlerT<OwnerDrawParent<Window> > super;
208 #else
209 	typedef ExtContextMenuHandlerT<OwnerDrawParent<DialogWindow> > super;
210 #endif
211 
212 	StartMenu(HWND hwnd, int icon_size=ICON_SIZE_SMALL);
213 	StartMenu(HWND hwnd, const StartMenuCreateInfo& create_info, int icon_size=ICON_SIZE_SMALL);
214 	~StartMenu();
215 
216 	static HWND Create(int x, int y, const StartMenuFolders&, HWND hwndParent, LPCTSTR title,
217 						CREATORFUNC_INFO creator=s_def_creator, void* info=NULL, const String& filter="");
218 	static CREATORFUNC_INFO s_def_creator;
219 
220 protected:
221 	 // overridden member functions
222 	LRESULT	Init(LPCREATESTRUCT pcs);
223 	LRESULT	WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam);
224 	int		Command(int id, int code);
225 
226 	 // window class
227 	static BtnWindowClass& GetWndClasss();
228 
229 	 // data members
230 	int		_next_id;
231 	ShellEntryMap _entries;
232 	StartMenuShellDirs _dirs;
233 
234 	int		_submenu_id;
235 	WindowHandle _submenu;
236 
237 	int		_border_left;	// left border in pixels
238 	int		_border_top;	// top border in pixels
239 	int		_bottom_max;	// limit display area for long start menus
240 
241 	bool	_floating_btn;
242 	bool	_arrow_btns;
243 
244 	POINT	_last_pos;
245 	enum SCROLL_MODE {SCROLL_NOT, SCROLL_UP, SCROLL_DOWN} _scroll_mode;
246 	int		_scroll_pos;
247 	int		_invisible_lines;
248 
249 	StartMenuCreateInfo _create_info;	// copy of the original create info
250 
251 	int		_icon_size;
252 
253 #ifdef _LIGHT_STARTMENU
254 	SMBtnVector _buttons;
255 	int		_selected_id;
256 	LPARAM	_last_mouse_pos;
257 
258 	void	ResizeToButtons();
259 	int		ButtonHitTest(POINT pt);
260 	void	InvalidateSelection();
261 	const SMBtnInfo* GetButtonInfo(int id) const;
262 	bool	SelectButton(int id, bool open_sub=true);
263 	bool	SelectButtonIndex(int idx, bool open_sub=true);
264 	int		GetSelectionIndex();
265 	virtual void ProcessKey(int vk);
266 	bool	Navigate(int step);
267 	bool	OpenSubmenu(bool select_first=false);
268 	bool	JumpToNextShortcut(char c);
269 #endif
270 
271 	 // member functions
272 	void	ResizeButtons(int cx);
273 
274 	virtual void AddEntries();
275 
276 	ShellEntryMap::iterator AddEntry(const String& title, ICON_ID icon_id, Entry* entry);
277 	ShellEntryMap::iterator AddEntry(const String& title, ICON_ID icon_id=ICID_NONE, int id=-1);
278 	ShellEntryMap::iterator AddEntry(const ShellFolder folder, ShellEntry* entry);
279 	ShellEntryMap::iterator AddEntry(const ShellFolder folder, Entry* entry);
280 
281 	void	AddShellEntries(const ShellDirectory& dir, int max=-1, const String& ignore="");
282 
283 	void	AddButton(LPCTSTR title, ICON_ID icon_id=ICID_NONE, bool hasSubmenu=false, int id=-1, bool enabled=true);
284 	void	AddSeparator();
285 
286 	bool	CloseSubmenus() {return CloseOtherSubmenus();}
287 	bool	CloseOtherSubmenus(int id=0);
288 	void	CreateSubmenu(int id, LPCTSTR title, CREATORFUNC_INFO creator=s_def_creator, void*info=NULL);
289 	bool	CreateSubmenu(int id, int folder, LPCTSTR title, CREATORFUNC_INFO creator=s_def_creator, void*info=NULL);
290 	bool	CreateSubmenu(int id, int folder1, int folder2, LPCTSTR title, CREATORFUNC_INFO creator=s_def_creator, void*info=NULL);
291 	void	CreateSubmenu(int id, const StartMenuFolders& new_folders, LPCTSTR title, CREATORFUNC_INFO creator=s_def_creator, void*info=NULL);
292 	void	ActivateEntry(int id, const ShellEntrySet& entries);
293 	virtual void CloseStartMenu(int id=0);
294 
295 	bool	GetButtonRect(int id, PRECT prect) const;
296 
297 	void	DrawFloatingButton(HDC hdc);
298 	void	GetFloatingButtonRect(LPRECT prect);
299 	void	GetArrowButtonRects(LPRECT prect_up, LPRECT prect_down, int icon_size);
300 
301 	void	DrawArrows(HDC hdc, int icon_size);
302 
303 	void	Paint(PaintCanvas& canvas);
304 	void	UpdateIcons(/*int idx*/);
305 };
306 
307 
308  // declare shell32's "Run..." dialog export function
309 typedef	void (WINAPI* RUNFILEDLG)(HWND hwndOwner, HICON hIcon, LPCSTR lpstrDirectory, LPCSTR lpstrTitle, LPCSTR lpstrDescription, UINT uFlags);
310 
311  //
312  // Flags for RunFileDlg
313  //
314 
315 #define	RFF_NOBROWSE		0x01	// Removes the browse button.
316 #define	RFF_NODEFAULT		0x02	// No default item selected.
317 #define	RFF_CALCDIRECTORY	0x04	// Calculates the working directory from the file name.
318 #define	RFF_NOLABEL			0x08	// Removes the edit box label.
319 #define	RFF_NOSEPARATEMEM	0x20	// Removes the Separate Memory Space check box (Windows NT only).
320 
321 
322  // declare more previously undocumented shell32 functions
323 typedef	void (WINAPI* EXITWINDOWSDLG)(HWND hwndOwner);
324 typedef	int (WINAPI* LOGOFFWINDOWSDIALOG)(UINT flags);
325 typedef	int (WINAPI* RESTARTWINDOWSDLG)(HWND hwndOwner, LPCWSTR reason, UINT flags);
326 typedef	int (WINAPI* RESTARTWINDOWSDLGEX)(HWND hWndOwner, LPCWSTR lpwstrReason, DWORD uFlags, DWORD uReason);
327 typedef	BOOL (WINAPI* SHFINDFILES)(LPCITEMIDLIST pidlRoot, LPCITEMIDLIST pidlSavedSearch);
328 typedef	BOOL (WINAPI* SHFINDCOMPUTER)(LPCITEMIDLIST pidlRoot, LPCITEMIDLIST pidlSavedSearch);
329 
330 
331  /// Handling of standard start menu commands
332 struct StartMenuHandler : public StartMenu
333 {
334 	typedef StartMenu super;
335 
336 	StartMenuHandler(HWND hwnd, int icon_size=ICON_SIZE_SMALL)
337 	 :	super(hwnd, icon_size)
338 	{
339 	}
340 
341 	StartMenuHandler(HWND hwnd, const StartMenuCreateInfo& create_info, int icon_size=ICON_SIZE_SMALL)
342 	 :	super(hwnd, create_info, icon_size)
343 	{
344 	}
345 
346 protected:
347 	int		Command(int id, int code);
348 
349 	static void	ShowLaunchDialog(HWND hwndOwner);
350 	static void	ShowLogoffDialog(HWND hwndOwner);
351     static void	ShowRestartDialog(HWND hwndOwner, UINT flags);
352 	static void	ShowSearchDialog();
353 	static void	ShowSearchComputer();
354 };
355 
356 
357 struct StartMenuRootCreateInfo
358 {
359 	int	_icon_size;
360 };
361 
362 
363  /// Startmenu root window
364 struct StartMenuRoot : public StartMenuHandler
365 {
366 	typedef StartMenuHandler super;
367 
368 	StartMenuRoot(HWND hwnd, const StartMenuRootCreateInfo& info);
369 
370 	static HWND Create(HWND hwndDesktopBar, int icon_size);
371 	void	TrackStartmenu();
372 	void	CloseStartMenu(int id=0);
373 	bool    IsStartMenuVisible() const;
374 	int	Command(int id, int code);
375 
376 	HWND	_hwndStartButton;
377 
378 protected:
379 	LRESULT	Init(LPCREATESTRUCT pcs);
380 	LRESULT	WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam);
381 
382 	SIZE	_logo_size;
383 
384 	virtual void AddEntries();
385 	virtual void ProcessKey(int vk);
386 
387 	void	Paint(PaintCanvas& canvas);
388 
389 
390 	void	ReadLogoSize();
391 	UINT	GetLogoResId();
392 };
393 
394 
395  /// Settings sub-startmenu
396 struct SettingsMenu : public StartMenuHandler
397 {
398 	typedef StartMenuHandler super;
399 
400 	SettingsMenu(HWND hwnd, const StartMenuCreateInfo& create_info)
401 	 :	super(hwnd, create_info)
402 	{
403 	}
404 
405 protected:
406 	virtual void AddEntries();
407 };
408 
409 
410  /// "Browse Files..." sub-start menu
411 struct BrowseMenu : public StartMenuHandler
412 {
413 	typedef StartMenuHandler super;
414 
415 	BrowseMenu(HWND hwnd, const StartMenuCreateInfo& create_info)
416 	 :	super(hwnd, create_info)
417 	{
418 	}
419 
420 protected:
421 	virtual void AddEntries();
422 };
423 
424 
425  /// Search sub-startmenu
426 struct SearchMenu : public StartMenuHandler
427 {
428 	typedef StartMenuHandler super;
429 
430 	SearchMenu(HWND hwnd, const StartMenuCreateInfo& create_info)
431 	 :	super(hwnd, create_info)
432 	{
433 	}
434 
435 protected:
436 	virtual void AddEntries();
437 };
438 
439 
440 #define	RECENT_DOCS_COUNT	20	///@todo read max. count of entries from registry
441 
442  /// "Recent Files" sub-start menu
443 struct RecentStartMenu : public StartMenu
444 {
445 	typedef StartMenu super;
446 
447 	RecentStartMenu(HWND hwnd, const StartMenuCreateInfo& create_info)
448 	 :	super(hwnd, create_info)
449 	{
450 	}
451 
452 protected:
453 	virtual void AddEntries();
454 };
455 
456 
457 #ifndef _SHELL32_FAVORITES
458 
459 typedef map<int, BookmarkNode> BookmarkMap;
460 
461  /// Bookmarks sub-startmenu
462 struct FavoritesMenu : public StartMenu
463 {
464 	typedef StartMenu super;
465 
466 	FavoritesMenu(HWND hwnd, const StartMenuCreateInfo& create_info)
467 	 :	super(hwnd, create_info),
468 		_bookmarks(*(BookmarkList*)create_info._info)
469 	{
470 	}
471 
472 protected:
473 	virtual int Command(int id, int code);
474 	virtual void AddEntries();
475 
476 	BookmarkList _bookmarks;
477 	BookmarkMap	_entries;
478 };
479 
480 #endif
481