1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
/*
 * Copyright 2003, 2004 Martin Fuchs
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */


 //
 // Explorer and Desktop clone
 //
 // startmenu.h
 //
 // Martin Fuchs, 16.08.2003
 //


#define	CLASSNAME_STARTMENU		TEXT("ReactOSStartmenuClass")
#define	TITLE_STARTMENU			TEXT("Start Menu")


#define	STARTMENU_WIDTH_MIN					120
#define	STARTMENU_LINE_HEIGHT(icon_size)	(icon_size+4)
#define	STARTMENU_SEP_HEIGHT(icon_size)		(STARTMENU_LINE_HEIGHT(icon_size)/2)
#define	STARTMENU_TOP_BTN_SPACE				8


 // private message constants
#define	PM_STARTMENU_CLOSED		(WM_APP+0x11)
#define	PM_STARTENTRY_LAUNCHED	(WM_APP+0x12)

#ifndef _LIGHT_STARTMENU
#define	PM_STARTENTRY_FOCUSED	(WM_APP+0x13)
#endif

#define	PM_UPDATE_ICONS			(WM_APP+0x14)
#define	PM_SELECT_ENTRY			(WM_APP+0x15)


 /// StartMenuDirectory is used to store the base directory of start menus.
struct StartMenuDirectory
{
	StartMenuDirectory(const ShellDirectory& dir, const String& ignore="")
	 :	_dir(dir), _ignore(ignore)
	{
	}

	~StartMenuDirectory()
	{
		_dir.free_subentries();
	}

	ShellDirectory _dir;
	String	_ignore;
};

typedef list<StartMenuDirectory> StartMenuShellDirs;
typedef set<Entry*> ShellEntrySet;

 /// structure holding information about one start menu entry
struct StartMenuEntry
{
	StartMenuEntry() : _icon_id(ICID_UNKNOWN) {}

	String	_title;
	ICON_ID	_icon_id;
	ShellEntrySet _entries;
};


extern int GetStartMenuBtnTextWidth(HDC hdc, LPCTSTR title, HWND hwnd);


#ifndef _LIGHT_STARTMENU

 /**
	StartMenuButton draws the face of a StartMenuCtrl button control.
 */
struct StartMenuButton : public OwnerdrawnButton
{
	typedef OwnerdrawnButton super;

	StartMenuButton(HWND hwnd, ICON_ID icon_id, bool hasSubmenu)
	 :	super(hwnd), _hIcon(hIcon), _hasSubmenu(hasSubmenu) {}

protected:
	LRESULT	WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam);
	virtual void DrawItem(LPDRAWITEMSTRUCT dis);

	ICON_ID	_icon_id;
	bool	_hasSubmenu;
};


 /**
	To create a Startmenu button control, construct a StartMenuCtrl object.
 */
struct StartMenuCtrl : public Button
{
	StartMenuCtrl(HWND parent, int x, int y, int w, LPCTSTR title,
					UINT id, HICON hIcon=0, bool hasSubmenu=false, DWORD style=WS_VISIBLE|WS_CHILD|BS_OWNERDRAW, DWORD exStyle=0)
	 :	Button(parent, title, x, y, w, STARTMENU_LINE_HEIGHT(icon_size), id, style, exStyle)
	{
		*new StartMenuButton(_hwnd, hIcon, hasSubmenu);

		SetWindowFont(_hwnd, GetStockFont(DEFAULT_GUI_FONT), FALSE);
	}
};


 /// separator between start menu entries
struct StartMenuSeparator : public Static
{
	StartMenuSeparator(HWND parent, int x, int y, int w, DWORD style=WS_VISIBLE|WS_CHILD|WS_DISABLED|SS_ETCHEDHORZ, DWORD exStyle=0)
	 :	Static(parent, NULL, x, y+STARTMENU_SEP_HEIGHT(icon_size)/2-1, w, 2, -1, style, exStyle)
	{
	}
};

#endif


typedef list<ShellPath> StartMenuFolders;

 /// structor containing information for creating of start menus
struct StartMenuCreateInfo
{
	StartMenuCreateInfo() : _border_top(0) {}<--- Member variable 'StartMenuCreateInfo::_info' is not initialized in the constructor.

	StartMenuFolders _folders;
	int		_border_top;
	String	_title;
	Window::CREATORFUNC_INFO _creator;
	void*	_info;
	String	_filter;
};

#define STARTMENU_CREATOR(WND_CLASS) WINDOW_CREATOR_INFO(WND_CLASS, StartMenuCreateInfo)

typedef map<int, StartMenuEntry> ShellEntryMap;


#ifdef _LIGHT_STARTMENU

struct SMBtnInfo
{
	SMBtnInfo(const StartMenuEntry& entry, int id, bool hasSubmenu=false, bool enabled=true)
	 :	_title(entry._title),
		_icon_id(entry._icon_id),
		_id(id),
		_hasSubmenu(hasSubmenu),
		_enabled(enabled)
	{
	}

	SMBtnInfo(LPCTSTR title, ICON_ID icon_id, int id, bool hasSubmenu=false, bool enabled=true)
	 :	_title(title),
		_icon_id(icon_id),
		_id(id),
		_hasSubmenu(hasSubmenu),
		_enabled(enabled)
	{
	}

	String	_title;
	ICON_ID	_icon_id;
	int		_id;
	bool	_hasSubmenu;
	bool	_enabled;
};

typedef vector<SMBtnInfo> SMBtnVector;

extern void DrawStartMenuButton(HDC hdc, const RECT& rect, LPCTSTR title, const SMBtnInfo& btn, bool has_focus, bool pushed, int icon_size);

#else

extern void DrawStartMenuButton(HDC hdc, const RECT& rect, LPCTSTR title, HICON hIcon,
								bool hasSubmenu, bool enabled, bool has_focus, bool pushed, int icon_size);

#endif


 /**
	Startmenu window.
	To create a start menu call its Create() function.
 */
struct StartMenu :
#ifdef _LIGHT_STARTMENU
	public ExtContextMenuHandlerT<OwnerDrawParent<Window> >
#else
	public ExtContextMenuHandlerT<OwnerDrawParent<DialogWindow> >
#endif
{
#ifdef _LIGHT_STARTMENU
	typedef ExtContextMenuHandlerT<OwnerDrawParent<Window> > super;
#else
	typedef ExtContextMenuHandlerT<OwnerDrawParent<DialogWindow> > super;
#endif

	StartMenu(HWND hwnd, int icon_size=ICON_SIZE_SMALL);
	StartMenu(HWND hwnd, const StartMenuCreateInfo& create_info, int icon_size=ICON_SIZE_SMALL);
	~StartMenu();

	static HWND Create(int x, int y, const StartMenuFolders&, HWND hwndParent, LPCTSTR title,
						CREATORFUNC_INFO creator=s_def_creator, void* info=NULL, const String& filter="");
	static CREATORFUNC_INFO s_def_creator;

protected:
	 // overridden member functions
	LRESULT	Init(LPCREATESTRUCT pcs);
	LRESULT	WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam);
	int		Command(int id, int code);

	 // window class
	static BtnWindowClass& GetWndClasss();

	 // data members
	int		_next_id;
	ShellEntryMap _entries;<--- Parent variable 'StartMenu::_entries'
	StartMenuShellDirs _dirs;

	int		_submenu_id;
	WindowHandle _submenu;

	int		_border_left;	// left border in pixels
	int		_border_top;	// top border in pixels
	int		_bottom_max;	// limit display area for long start menus

	bool	_floating_btn;
	bool	_arrow_btns;

	POINT	_last_pos;
	enum SCROLL_MODE {SCROLL_NOT, SCROLL_UP, SCROLL_DOWN} _scroll_mode;
	int		_scroll_pos;
	int		_invisible_lines;

	StartMenuCreateInfo _create_info;	// copy of the original create info

	int		_icon_size;

#ifdef _LIGHT_STARTMENU
	SMBtnVector _buttons;
	int		_selected_id;
	LPARAM	_last_mouse_pos;

	void	ResizeToButtons();
	int		ButtonHitTest(POINT pt);
	void	InvalidateSelection();
	const SMBtnInfo* GetButtonInfo(int id) const;
	bool	SelectButton(int id, bool open_sub=true);
	bool	SelectButtonIndex(int idx, bool open_sub=true);
	int		GetSelectionIndex();
	virtual void ProcessKey(int vk);
	bool	Navigate(int step);
	bool	OpenSubmenu(bool select_first=false);
	bool	JumpToNextShortcut(char c);
#endif

	 // member functions
	void	ResizeButtons(int cx);

	virtual void AddEntries();

	ShellEntryMap::iterator AddEntry(const String& title, ICON_ID icon_id, Entry* entry);
	ShellEntryMap::iterator AddEntry(const String& title, ICON_ID icon_id=ICID_NONE, int id=-1);
	ShellEntryMap::iterator AddEntry(const ShellFolder folder, ShellEntry* entry);
	ShellEntryMap::iterator AddEntry(const ShellFolder folder, Entry* entry);

	void	AddShellEntries(const ShellDirectory& dir, int max=-1, const String& ignore="");

	void	AddButton(LPCTSTR title, ICON_ID icon_id=ICID_NONE, bool hasSubmenu=false, int id=-1, bool enabled=true);
	void	AddSeparator();

	bool	CloseSubmenus() {return CloseOtherSubmenus();}
	bool	CloseOtherSubmenus(int id=0);
	void	CreateSubmenu(int id, LPCTSTR title, CREATORFUNC_INFO creator=s_def_creator, void*info=NULL);
	bool	CreateSubmenu(int id, int folder, LPCTSTR title, CREATORFUNC_INFO creator=s_def_creator, void*info=NULL);
	bool	CreateSubmenu(int id, int folder1, int folder2, LPCTSTR title, CREATORFUNC_INFO creator=s_def_creator, void*info=NULL);
	void	CreateSubmenu(int id, const StartMenuFolders& new_folders, LPCTSTR title, CREATORFUNC_INFO creator=s_def_creator, void*info=NULL);
	void	ActivateEntry(int id, const ShellEntrySet& entries);
	virtual void CloseStartMenu(int id=0);

	bool	GetButtonRect(int id, PRECT prect) const;

	void	DrawFloatingButton(HDC hdc);
	void	GetFloatingButtonRect(LPRECT prect);
	void	GetArrowButtonRects(LPRECT prect_up, LPRECT prect_down, int icon_size);

	void	DrawArrows(HDC hdc, int icon_size);

	void	Paint(PaintCanvas& canvas);
	void	UpdateIcons(/*int idx*/);
};


 // declare shell32's "Run..." dialog export function
typedef	void (WINAPI* RUNFILEDLG)(HWND hwndOwner, HICON hIcon, LPCSTR lpstrDirectory, LPCSTR lpstrTitle, LPCSTR lpstrDescription, UINT uFlags);

 //
 // Flags for RunFileDlg
 //

#define	RFF_NOBROWSE		0x01	// Removes the browse button.
#define	RFF_NODEFAULT		0x02	// No default item selected.
#define	RFF_CALCDIRECTORY	0x04	// Calculates the working directory from the file name.
#define	RFF_NOLABEL			0x08	// Removes the edit box label.
#define	RFF_NOSEPARATEMEM	0x20	// Removes the Separate Memory Space check box (Windows NT only).


 // declare more previously undocumented shell32 functions
typedef	void (WINAPI* EXITWINDOWSDLG)(HWND hwndOwner);
typedef	int (WINAPI* LOGOFFWINDOWSDIALOG)(UINT flags);
typedef	int (WINAPI* RESTARTWINDOWSDLG)(HWND hwndOwner, LPCWSTR reason, UINT flags);
typedef	int (WINAPI* RESTARTWINDOWSDLGEX)(HWND hWndOwner, LPCWSTR lpwstrReason, DWORD uFlags, DWORD uReason);
typedef	BOOL (WINAPI* SHFINDFILES)(LPCITEMIDLIST pidlRoot, LPCITEMIDLIST pidlSavedSearch);
typedef	BOOL (WINAPI* SHFINDCOMPUTER)(LPCITEMIDLIST pidlRoot, LPCITEMIDLIST pidlSavedSearch);


 /// Handling of standard start menu commands
struct StartMenuHandler : public StartMenu
{
	typedef StartMenu super;

	StartMenuHandler(HWND hwnd, int icon_size=ICON_SIZE_SMALL)
	 :	super(hwnd, icon_size)
	{
	}

	StartMenuHandler(HWND hwnd, const StartMenuCreateInfo& create_info, int icon_size=ICON_SIZE_SMALL)
	 :	super(hwnd, create_info, icon_size)
	{
	}

protected:
	int		Command(int id, int code);

	static void	ShowLaunchDialog(HWND hwndOwner);
	static void	ShowLogoffDialog(HWND hwndOwner);
    static void	ShowRestartDialog(HWND hwndOwner, UINT flags);
	static void	ShowSearchDialog();
	static void	ShowSearchComputer();
};


struct StartMenuRootCreateInfo
{
	int	_icon_size;
};


 /// Startmenu root window
struct StartMenuRoot : public StartMenuHandler
{
	typedef StartMenuHandler super;

	StartMenuRoot(HWND hwnd, const StartMenuRootCreateInfo& info);

	static HWND Create(HWND hwndDesktopBar, int icon_size);
	void	TrackStartmenu();
	void	CloseStartMenu(int id=0);
	bool    IsStartMenuVisible() const;
	int	Command(int id, int code);

	HWND	_hwndStartButton;

protected:
	LRESULT	Init(LPCREATESTRUCT pcs);
	LRESULT	WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam);

	SIZE	_logo_size;

	virtual void AddEntries();
	virtual void ProcessKey(int vk);

	void	Paint(PaintCanvas& canvas);
	

	void	ReadLogoSize();
	UINT	GetLogoResId();
};


 /// Settings sub-startmenu
struct SettingsMenu : public StartMenuHandler
{
	typedef StartMenuHandler super;

	SettingsMenu(HWND hwnd, const StartMenuCreateInfo& create_info)
	 :	super(hwnd, create_info)
	{
	}

protected:
	virtual void AddEntries();
};


 /// "Browse Files..." sub-start menu
struct BrowseMenu : public StartMenuHandler
{
	typedef StartMenuHandler super;

	BrowseMenu(HWND hwnd, const StartMenuCreateInfo& create_info)
	 :	super(hwnd, create_info)
	{
	}

protected:
	virtual void AddEntries();
};


 /// Search sub-startmenu
struct SearchMenu : public StartMenuHandler
{
	typedef StartMenuHandler super;

	SearchMenu(HWND hwnd, const StartMenuCreateInfo& create_info)
	 :	super(hwnd, create_info)
	{
	}

protected:
	virtual void AddEntries();
};


#define	RECENT_DOCS_COUNT	20	///@todo read max. count of entries from registry

 /// "Recent Files" sub-start menu
struct RecentStartMenu : public StartMenu
{
	typedef StartMenu super;

	RecentStartMenu(HWND hwnd, const StartMenuCreateInfo& create_info)
	 :	super(hwnd, create_info)
	{
	}

protected:
	virtual void AddEntries();
};


#ifndef _SHELL32_FAVORITES

typedef map<int, BookmarkNode> BookmarkMap;

 /// Bookmarks sub-startmenu
struct FavoritesMenu : public StartMenu
{
	typedef StartMenu super;

	FavoritesMenu(HWND hwnd, const StartMenuCreateInfo& create_info)
	 :	super(hwnd, create_info),
		_bookmarks(*(BookmarkList*)create_info._info)
	{
	}

protected:
	virtual int Command(int id, int code);
	virtual void AddEntries();

	BookmarkList _bookmarks;
	BookmarkMap	_entries;<--- Derived variable 'FavoritesMenu::_entries'
};

#endif