1c2c66affSColin Finck /*
2c2c66affSColin Finck  * Copyright 2003, 2004, 2005 Martin Fuchs
3c2c66affSColin Finck  *
4c2c66affSColin Finck  * This library is free software; you can redistribute it and/or
5c2c66affSColin Finck  * modify it under the terms of the GNU Lesser General Public
6c2c66affSColin Finck  * License as published by the Free Software Foundation; either
7c2c66affSColin Finck  * version 2.1 of the License, or (at your option) any later version.
8c2c66affSColin Finck  *
9c2c66affSColin Finck  * This library is distributed in the hope that it will be useful,
10c2c66affSColin Finck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12c2c66affSColin Finck  * Lesser General Public License for more details.
13c2c66affSColin Finck  *
14c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public
15c2c66affSColin Finck  * License along with this library; if not, write to the Free Software
16c2c66affSColin Finck  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17c2c66affSColin Finck  */
18c2c66affSColin Finck 
19c2c66affSColin Finck 
20c2c66affSColin Finck  //
21c2c66affSColin Finck  // Explorer clone
22c2c66affSColin Finck  //
23c2c66affSColin Finck  // window.h
24c2c66affSColin Finck  //
25c2c66affSColin Finck  // Martin Fuchs, 23.07.2003
26c2c66affSColin Finck  //
27c2c66affSColin Finck 
28c2c66affSColin Finck 
29c2c66affSColin Finck typedef set<HWND> WindowSet;
30c2c66affSColin Finck 
31c2c66affSColin Finck 
32c2c66affSColin Finck  /*
33c2c66affSColin Finck 	Classes are declared using "struct", not "class" because the default
34c2c66affSColin Finck 	access mode is "public". This way we can list the member functions in a
35c2c66affSColin Finck 	natural order without explicitly specifying any access mode at the begin
36c2c66affSColin Finck 	of the definition.
37c2c66affSColin Finck 	First are public constructors and destructor, then public member functions.
38c2c66affSColin Finck 	After that we list protected member varibables and functions. If needed,
39c2c66affSColin Finck 	private implemenation varibales and functions are positioned at the end.
40c2c66affSColin Finck  */
41c2c66affSColin Finck 
42c2c66affSColin Finck 
43c2c66affSColin Finck  /// information structure for creation of a MDI child window
44c2c66affSColin Finck struct ChildWndInfo
45c2c66affSColin Finck {
ChildWndInfoChildWndInfo46c2c66affSColin Finck 	ChildWndInfo(HWND hmdiclient)
47c2c66affSColin Finck 	 :	_hmdiclient(hmdiclient) {}
48c2c66affSColin Finck 
49c2c66affSColin Finck 	HWND	_hmdiclient;
50c2c66affSColin Finck };
51c2c66affSColin Finck 
52c2c66affSColin Finck 
53c2c66affSColin Finck  /**
54c2c66affSColin Finck 	Class Window is the base class for several C++ window wrapper classes.
55c2c66affSColin Finck 	Window objects are allocated from the heap. They are automatically freed
56c2c66affSColin Finck 	when the window gets destroyed.
57c2c66affSColin Finck  */
58c2c66affSColin Finck struct Window : public WindowHandle
59c2c66affSColin Finck {
60c2c66affSColin Finck 	Window(HWND hwnd);
61c2c66affSColin Finck 	virtual ~Window();
62c2c66affSColin Finck 
63c2c66affSColin Finck 
64c2c66affSColin Finck 	typedef map<HWND,Window*> WindowMap;
65c2c66affSColin Finck 
66c2c66affSColin Finck 	typedef Window* (*CREATORFUNC)(HWND);
67c2c66affSColin Finck 	typedef Window* (*CREATORFUNC_INFO)(HWND, const void*);
68c2c66affSColin Finck 
69c2c66affSColin Finck 	static HWND Create(CREATORFUNC creator,
70c2c66affSColin Finck 				DWORD dwExStyle, LPCTSTR lpClassName, LPCTSTR lpWindowName,
71c2c66affSColin Finck 				DWORD dwStyle, int x, int y, int w, int h,
72c2c66affSColin Finck 				HWND hwndParent=0, HMENU hMenu=0/*, LPVOID lpParam=0*/);
73c2c66affSColin Finck 
74c2c66affSColin Finck 	static HWND Create(CREATORFUNC_INFO creator, const void* info,
75c2c66affSColin Finck 				DWORD dwExStyle, LPCTSTR lpClassName, LPCTSTR lpWindowName,
76c2c66affSColin Finck 				DWORD dwStyle, int x, int y, int w, int h,
77c2c66affSColin Finck 				HWND hwndParent=0, HMENU hMenu=0/*, LPVOID lpParam=0*/);
78c2c66affSColin Finck 
79c2c66affSColin Finck 	static Window* create_mdi_child(const ChildWndInfo& info, const MDICREATESTRUCT& mcs, CREATORFUNC_INFO creator);
80c2c66affSColin Finck //	static Window* create_property_sheet(struct PropertySheetDialog* ppsd, CREATORFUNC creator, const void* info);
81c2c66affSColin Finck 
82c2c66affSColin Finck 	static LRESULT CALLBACK WindowWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam);
83c2c66affSColin Finck 	static INT_PTR CALLBACK DialogProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam);
84c2c66affSColin Finck 
85c2c66affSColin Finck 	static Window* get_window(HWND hwnd);
86c2c66affSColin Finck #ifndef _MSC_VER
get_windowWindow87c2c66affSColin Finck 	template<typename CLASS> static CLASS* get_window(HWND hwnd) {return static_cast<CLASS*>(get_window(hwnd));}
88c2c66affSColin Finck #define	GET_WINDOW(CLASS, hwnd) Window::get_window<CLASS>(hwnd)
89c2c66affSColin Finck #endif
90c2c66affSColin Finck 
91c2c66affSColin Finck 	static void register_pretranslate(HWND hwnd);
92c2c66affSColin Finck 	static void unregister_pretranslate(HWND hwnd);
93c2c66affSColin Finck 	static BOOL	pretranslate_msg(LPMSG pmsg);
94c2c66affSColin Finck 
95c2c66affSColin Finck 	static void	register_dialog(HWND hwnd);
96c2c66affSColin Finck 	static void	unregister_dialog(HWND hwnd);
97c2c66affSColin Finck 	static BOOL	dispatch_dialog_msg(LPMSG pmsg);
98c2c66affSColin Finck 
99c2c66affSColin Finck 	static int	MessageLoop();
100c2c66affSColin Finck 
101c2c66affSColin Finck 
102c2c66affSColin Finck 	LRESULT	SendParent(UINT nmsg, WPARAM wparam=0, LPARAM lparam=0);
103c2c66affSColin Finck 	LRESULT	PostParent(UINT nmsg, WPARAM wparam=0, LPARAM lparam=0);
104c2c66affSColin Finck 
105c2c66affSColin Finck 	static void CancelModes();
106c2c66affSColin Finck 
107c2c66affSColin Finck 
108c2c66affSColin Finck protected:
109c2c66affSColin Finck 	virtual LRESULT	Init(LPCREATESTRUCT pcs);							// WM_CREATE processing
110c2c66affSColin Finck 	virtual LRESULT	WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam);
111c2c66affSColin Finck 	virtual int		Command(int id, int code);							// WM_COMMAND processing
112c2c66affSColin Finck 	virtual int		Notify(int id, NMHDR* pnmh);						// WM_NOTIFY processing
113c2c66affSColin Finck 
114c2c66affSColin Finck 	static Window* create_controller(HWND hwnd);
115c2c66affSColin Finck 
116c2c66affSColin Finck 
117c2c66affSColin Finck 	static WindowMap	s_wnd_map;
118c2c66affSColin Finck 
119c2c66affSColin Finck 	static const void*	s_new_info;
120c2c66affSColin Finck 	static CREATORFUNC	s_window_creator;
121c2c66affSColin Finck 
122c2c66affSColin Finck 
123c2c66affSColin Finck 	 /// structure for managing critical sections as static class information in struct Window
124c2c66affSColin Finck 	struct StaticWindowData {
125c2c66affSColin Finck 		CritSect	_map_crit_sect;
126c2c66affSColin Finck 		CritSect	_create_crit_sect;
127c2c66affSColin Finck 	};
128c2c66affSColin Finck 
129c2c66affSColin Finck 	static StaticWindowData& GetStaticWindowData();
130c2c66affSColin Finck 
131c2c66affSColin Finck 
132c2c66affSColin Finck 	 // MDI child creation
133c2c66affSColin Finck 	static HHOOK s_hcbtHook;
134c2c66affSColin Finck 	static LRESULT CALLBACK MDICBTHookProc(int code, WPARAM wparam, LPARAM lparam);
135c2c66affSColin Finck 	static LRESULT CALLBACK PropSheetCBTHookProc(int code, WPARAM wparam, LPARAM lparam);
136c2c66affSColin Finck 
137c2c66affSColin Finck 	static WindowSet s_pretranslate_windows;
138c2c66affSColin Finck 	static WindowSet s_dialogs;
139c2c66affSColin Finck };
140c2c66affSColin Finck 
141c2c66affSColin Finck #ifdef UNICODE
142c2c66affSColin Finck #define	NFR_CURRENT	NFR_UNICODE
143c2c66affSColin Finck #else
144c2c66affSColin Finck #define	NFR_CURRENT	NFR_ANSI
145c2c66affSColin Finck #endif
146c2c66affSColin Finck 
147c2c66affSColin Finck 
148c2c66affSColin Finck #ifdef _MSC_VER
149c2c66affSColin Finck template<typename CLASS> struct GetWindowHelper
150c2c66affSColin Finck {
get_windowGetWindowHelper151c2c66affSColin Finck 	static CLASS* get_window(HWND hwnd) {
152c2c66affSColin Finck 		return static_cast<CLASS*>(Window::get_window(hwnd));
153c2c66affSColin Finck 	}
154c2c66affSColin Finck };
155c2c66affSColin Finck #define	GET_WINDOW(CLASS, hwnd) GetWindowHelper<CLASS>::get_window(hwnd)
156c2c66affSColin Finck #endif
157c2c66affSColin Finck 
158c2c66affSColin Finck 
159c2c66affSColin Finck  /// dynamic casting of Window pointers
160c2c66affSColin Finck template<typename CLASS> struct TypeCheck
161c2c66affSColin Finck {
dyn_castTypeCheck162c2c66affSColin Finck 	static CLASS* dyn_cast(Window* wnd)
163c2c66affSColin Finck 		{return dynamic_cast<CLASS*>(wnd);}
164c2c66affSColin Finck };
165c2c66affSColin Finck 
166c2c66affSColin Finck #define	WINDOW_DYNAMIC_CAST(CLASS, hwnd) \
167c2c66affSColin Finck 	TypeCheck<CLASS>::dyn_cast(Window::get_window(hwnd))
168c2c66affSColin Finck 
169c2c66affSColin Finck 
170c2c66affSColin Finck  /**
171c2c66affSColin Finck 	SubclassedWindow is used to wrap already existing window handles
172c2c66affSColin Finck 	into C++ Window objects. To construct a object, use the "new" operator
173c2c66affSColin Finck 	to put it in the heap. It is automatically freed, when the window
174c2c66affSColin Finck 	gets destroyed.
175c2c66affSColin Finck  */
176c2c66affSColin Finck struct SubclassedWindow : public Window
177c2c66affSColin Finck {
178c2c66affSColin Finck 	typedef Window super;
179c2c66affSColin Finck 
180c2c66affSColin Finck 	SubclassedWindow(HWND);
181c2c66affSColin Finck 
182c2c66affSColin Finck protected:
183c2c66affSColin Finck 	WNDPROC	_orgWndProc;
184c2c66affSColin Finck 
185c2c66affSColin Finck 	static LRESULT CALLBACK SubclassedWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam);
186c2c66affSColin Finck 
187c2c66affSColin Finck 	virtual LRESULT	WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam);
188c2c66affSColin Finck 	virtual int		Command(int id, int code);
189c2c66affSColin Finck 	virtual int		Notify(int id, NMHDR* pnmh);
190c2c66affSColin Finck };
191c2c66affSColin Finck 
192c2c66affSColin Finck 
193c2c66affSColin Finck  /// template class used in macro WINDOW_CREATOR to define the creater functions for Window objects
194c2c66affSColin Finck template<typename WND_CLASS> struct WindowCreator
195c2c66affSColin Finck {
window_creatorWindowCreator196c2c66affSColin Finck 	static WND_CLASS* window_creator(HWND hwnd)
197c2c66affSColin Finck 	{
198c2c66affSColin Finck 		return new WND_CLASS(hwnd);
199c2c66affSColin Finck 	}
200c2c66affSColin Finck };
201c2c66affSColin Finck 
202c2c66affSColin Finck #define WINDOW_CREATOR(WND_CLASS) \
203c2c66affSColin Finck 	((Window::CREATORFUNC) WindowCreator<WND_CLASS>::window_creator)
204c2c66affSColin Finck 
205c2c66affSColin Finck 
206c2c66affSColin Finck  /// template class used in macro WINDOW_CREATOR_INFO to the define creater functions for Window objects with additional creation information
207c2c66affSColin Finck template<typename WND_CLASS, typename INFO_CLASS> struct WindowCreatorInfo
208c2c66affSColin Finck {
window_creatorWindowCreatorInfo209c2c66affSColin Finck 	static WND_CLASS* window_creator(HWND hwnd, const void* info)
210c2c66affSColin Finck 	{
211c2c66affSColin Finck 		return new WND_CLASS(hwnd, *static_cast<const INFO_CLASS*>(info));
212c2c66affSColin Finck 	}
213c2c66affSColin Finck };
214c2c66affSColin Finck 
215c2c66affSColin Finck #define WINDOW_CREATOR_INFO(WND_CLASS, INFO_CLASS) \
216c2c66affSColin Finck 	((Window::CREATORFUNC_INFO) WindowCreatorInfo<WND_CLASS, INFO_CLASS>::window_creator)
217c2c66affSColin Finck 
218c2c66affSColin Finck 
219c2c66affSColin Finck  /**
220c2c66affSColin Finck 	WindowClass is a neat wrapper for RegisterClassEx().
221c2c66affSColin Finck 	Just construct a WindowClass object, override the attributes you want
222c2c66affSColin Finck 	to change, then call Register() or simply request the ATOM value to
223c2c66affSColin Finck 	register the window class. You don't have to worry calling Register()
224c2c66affSColin Finck 	more than once. It checks if, the class has already been registered.
225c2c66affSColin Finck  */
226c2c66affSColin Finck struct WindowClass : public WNDCLASSEX
227c2c66affSColin Finck {
228c2c66affSColin Finck 	WindowClass(LPCTSTR classname, UINT style=0, WNDPROC wndproc=Window::WindowWndProc);
229c2c66affSColin Finck 
RegisterWindowClass230c2c66affSColin Finck 	ATOM Register()
231c2c66affSColin Finck 	{
232c2c66affSColin Finck 		if (!_atomClass)
233c2c66affSColin Finck 			_atomClass = RegisterClassEx(this);
234c2c66affSColin Finck 
235c2c66affSColin Finck 		return _atomClass;
236c2c66affSColin Finck 	}
237c2c66affSColin Finck 
ATOMWindowClass238c2c66affSColin Finck 	operator ATOM() {return Register();}
239c2c66affSColin Finck 
240c2c66affSColin Finck 	 // return LPCTSTR for the CreateWindowEx() parameter
LPCTSTRWindowClass241c2c66affSColin Finck 	operator LPCTSTR() {return (LPCTSTR)(int)Register();}
242c2c66affSColin Finck 
243c2c66affSColin Finck protected:
244c2c66affSColin Finck 	ATOM	_atomClass;
245c2c66affSColin Finck };
246c2c66affSColin Finck 
247c2c66affSColin Finck  /// window class with gray background color
248c2c66affSColin Finck struct BtnWindowClass : public WindowClass
249c2c66affSColin Finck {
250c2c66affSColin Finck 	BtnWindowClass(LPCTSTR classname, UINT style=0, WNDPROC wndproc=Window::WindowWndProc)
WindowClassBtnWindowClass251c2c66affSColin Finck 	 :	WindowClass(classname, style, wndproc)
252c2c66affSColin Finck 	{
253c2c66affSColin Finck 		hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
254c2c66affSColin Finck 	}
255c2c66affSColin Finck };
256c2c66affSColin Finck 
257c2c66affSColin Finck  /// window class with specified icon from resources
258c2c66affSColin Finck struct IconWindowClass : public WindowClass
259c2c66affSColin Finck {
260c2c66affSColin Finck 	IconWindowClass(LPCTSTR classname, UINT nid, UINT style=0, WNDPROC wndproc=Window::WindowWndProc);
261c2c66affSColin Finck };
262c2c66affSColin Finck 
263c2c66affSColin Finck 
264c2c66affSColin Finck  // private message constants
265c2c66affSColin Finck #define	PM_DISPATCH_COMMAND		(WM_APP+0x00)
266c2c66affSColin Finck #define	PM_TRANSLATE_MSG		(WM_APP+0x01)
267c2c66affSColin Finck 
268c2c66affSColin Finck 
269c2c66affSColin Finck #define SPLIT_WIDTH 		5
270c2c66affSColin Finck #define DEFAULT_SPLIT_POS	300
271c2c66affSColin Finck #define	COLOR_SPLITBAR		LTGRAY_BRUSH
272c2c66affSColin Finck 
273c2c66affSColin Finck 
274c2c66affSColin Finck  /// menu info structure
275c2c66affSColin Finck struct MenuInfo
276c2c66affSColin Finck {
277c2c66affSColin Finck 	HMENU	_hMenuView;
278c2c66affSColin Finck };
279c2c66affSColin Finck 
280c2c66affSColin Finck #define	PM_FRM_GET_MENUINFO		(WM_APP+0x02)
281c2c66affSColin Finck 
282c2c66affSColin Finck #define	Frame_GetMenuInfo(hwnd) ((MenuInfo*)SNDMSG(hwnd, PM_FRM_GET_MENUINFO, 0, 0))
283c2c66affSColin Finck 
284c2c66affSColin Finck 
285c2c66affSColin Finck  /**
286c2c66affSColin Finck 	PreTranslateWindow is used to register windows to be called by Window::pretranslate_msg().
287c2c66affSColin Finck 	This way you get PM_TRANSLATE_MSG messages before the message loop dispatches messages.
288c2c66affSColin Finck 	You can then for example use TranslateAccelerator() to implement key shortcuts.
289c2c66affSColin Finck  */
290c2c66affSColin Finck struct PreTranslateWindow : public Window
291c2c66affSColin Finck {
292c2c66affSColin Finck 	typedef Window super;
293c2c66affSColin Finck 
294c2c66affSColin Finck 	PreTranslateWindow(HWND);
295c2c66affSColin Finck 	~PreTranslateWindow();
296c2c66affSColin Finck };
297c2c66affSColin Finck 
298c2c66affSColin Finck 
299c2c66affSColin Finck 
300c2c66affSColin Finck  /**
301c2c66affSColin Finck 	Class ChildWindow represents MDI child windows.
302c2c66affSColin Finck 	It is used with class MainFrame.
303c2c66affSColin Finck  */
304c2c66affSColin Finck struct ChildWindow : public PreTranslateWindow
305c2c66affSColin Finck {
306c2c66affSColin Finck 	typedef PreTranslateWindow super;
307c2c66affSColin Finck 
308c2c66affSColin Finck 	ChildWindow(HWND hwnd, const ChildWndInfo& info);
309c2c66affSColin Finck 
310c2c66affSColin Finck 	static ChildWindow* create(const ChildWndInfo& info, const RECT& rect, CREATORFUNC_INFO creator,
311c2c66affSColin Finck 								LPCTSTR classname, LPCTSTR title=NULL, DWORD style=0);
312c2c66affSColin Finck 
313c2c66affSColin Finck 	bool	go_to(LPCTSTR url);
314c2c66affSColin Finck 
315c2c66affSColin Finck protected:
316c2c66affSColin Finck 	LRESULT	WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam);
317c2c66affSColin Finck 
318c2c66affSColin Finck 	virtual void resize_children(int cx, int cy);
319c2c66affSColin Finck 	virtual String jump_to_int(LPCTSTR url) = 0;
320c2c66affSColin Finck 
321c2c66affSColin Finck protected:
322c2c66affSColin Finck 	MenuInfo*_menu_info;
323c2c66affSColin Finck 
324c2c66affSColin Finck 	WindowHandle _left_hwnd;
325c2c66affSColin Finck 	WindowHandle _right_hwnd;
326c2c66affSColin Finck 	int 	_focus_pane;		// 0: left	1: right
327c2c66affSColin Finck 
328c2c66affSColin Finck 	int 	_split_pos;
329c2c66affSColin Finck 	int		_last_split;
330c2c66affSColin Finck 
331c2c66affSColin Finck 	HWND	_hwndFrame;
332c2c66affSColin Finck 	String	_statusText;
333c2c66affSColin Finck 	String	_url;
334c2c66affSColin Finck 
335c2c66affSColin Finck 	stack<String> _url_history;
336c2c66affSColin Finck 
337c2c66affSColin Finck 	void	set_url(LPCTSTR url);
338c2c66affSColin Finck };
339c2c66affSColin Finck 
340c2c66affSColin Finck #define	PM_SETSTATUSTEXT		(WM_APP+0x1E)
341c2c66affSColin Finck 
342c2c66affSColin Finck 
343c2c66affSColin Finck  /**
344c2c66affSColin Finck 	The class DialogWindow implements modeless dialogs, which are managed by
345c2c66affSColin Finck 	Window::dispatch_dialog_msg() in Window::MessageLoop().
346c2c66affSColin Finck 	A DialogWindow object should be constructed by calling Window::Create()
347c2c66affSColin Finck 	and specifying the class using the WINDOW_CREATOR() macro.
348c2c66affSColin Finck  */
349c2c66affSColin Finck struct DialogWindow : public Window
350c2c66affSColin Finck {
351c2c66affSColin Finck 	typedef Window super;
352c2c66affSColin Finck 
DialogWindowDialogWindow353c2c66affSColin Finck 	DialogWindow(HWND hwnd)
354c2c66affSColin Finck 	 :	super(hwnd)
355c2c66affSColin Finck 	{
356c2c66affSColin Finck 		register_dialog(hwnd);
357c2c66affSColin Finck 	}
358c2c66affSColin Finck 
~DialogWindowDialogWindow359c2c66affSColin Finck 	~DialogWindow()
360c2c66affSColin Finck 	{
361c2c66affSColin Finck 		unregister_dialog(_hwnd);
362c2c66affSColin Finck 	}
363c2c66affSColin Finck };
364c2c66affSColin Finck 
365c2c66affSColin Finck 
366c2c66affSColin Finck  /**
367c2c66affSColin Finck 	The class Dialog implements modal dialogs.
368c2c66affSColin Finck 	A Dialog object should be constructed by calling Dialog::DoModal()
369c2c66affSColin Finck 	and specifying the class using the WINDOW_CREATOR() macro.
370c2c66affSColin Finck  */
371c2c66affSColin Finck struct Dialog : public Window
372c2c66affSColin Finck {
373c2c66affSColin Finck 	typedef Window super;
374c2c66affSColin Finck 
375c2c66affSColin Finck 	Dialog(HWND);
376c2c66affSColin Finck 	~Dialog();
377c2c66affSColin Finck 
378c2c66affSColin Finck 	static int DoModal(UINT nid, CREATORFUNC creator, HWND hwndParent=0);
379c2c66affSColin Finck 	static int DoModal(UINT nid, CREATORFUNC_INFO creator, const void* info, HWND hwndParent=0);
380c2c66affSColin Finck 
381c2c66affSColin Finck protected:
382c2c66affSColin Finck 	LRESULT	WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam);
383c2c66affSColin Finck 	int		Command(int id, int code);
384c2c66affSColin Finck };
385c2c66affSColin Finck 
386c2c66affSColin Finck 
387c2c66affSColin Finck #define	PM_FRM_CALC_CLIENT		(WM_APP+0x03)
388c2c66affSColin Finck #define	Frame_CalcFrameClient(hwnd, prt) ((BOOL)SNDMSG(hwnd, PM_FRM_CALC_CLIENT, 0, (LPARAM)(PRECT)prt))
389c2c66affSColin Finck 
390c2c66affSColin Finck #define	PM_JUMP_TO_URL			(WM_APP+0x25)
391c2c66affSColin Finck #define	PM_URL_CHANGED			(WM_APP+0x26)
392c2c66affSColin Finck 
393c2c66affSColin Finck 
394c2c66affSColin Finck struct PropSheetPage : public PROPSHEETPAGE
395c2c66affSColin Finck {
396c2c66affSColin Finck 	PropSheetPage(UINT nid, Window::CREATORFUNC dlg_creator);
397c2c66affSColin Finck 
398c2c66affSColin Finck 	void	init(struct PropertySheetDialog*);
399c2c66affSColin Finck 
400c2c66affSColin Finck protected:
401c2c66affSColin Finck 	friend struct PropSheetPageDlg;
402c2c66affSColin Finck 
403c2c66affSColin Finck 	Window::CREATORFUNC	_dlg_creator;
404c2c66affSColin Finck };
405c2c66affSColin Finck 
406c2c66affSColin Finck 
407c2c66affSColin Finck  /// Property Sheet dialog
408c2c66affSColin Finck struct PropertySheetDialog : public PROPSHEETHEADER
409c2c66affSColin Finck {
410c2c66affSColin Finck 	PropertySheetDialog(HWND owner);
411c2c66affSColin Finck 
412c2c66affSColin Finck 	void	add(PropSheetPage& psp);
413c2c66affSColin Finck 	int		DoModal(int start_page=0);
414c2c66affSColin Finck 
415c2c66affSColin Finck 	HWND	GetCurrentPage();
416c2c66affSColin Finck 
417c2c66affSColin Finck protected:
418c2c66affSColin Finck 	typedef vector<PROPSHEETPAGE> Vector;
419c2c66affSColin Finck 	Vector	_pages;
420c2c66affSColin Finck 	HWND	_hwnd;
421c2c66affSColin Finck };
422c2c66affSColin Finck 
423c2c66affSColin Finck 
424c2c66affSColin Finck  /// Property Sheet Page (inner dialog)
425c2c66affSColin Finck struct PropSheetPageDlg : public Dialog
426c2c66affSColin Finck {
427c2c66affSColin Finck 	typedef Dialog super;
428c2c66affSColin Finck 
429c2c66affSColin Finck 	PropSheetPageDlg(HWND);
430c2c66affSColin Finck 
431c2c66affSColin Finck protected:
432c2c66affSColin Finck 	friend struct PropertySheetDialog;
433c2c66affSColin Finck 	friend struct PropSheetPage;
434c2c66affSColin Finck 
435c2c66affSColin Finck 	static INT_PTR CALLBACK DialogProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam);
436c2c66affSColin Finck 
437c2c66affSColin Finck 	int	Command(int id, int code);
438c2c66affSColin Finck };
439c2c66affSColin Finck 
440c2c66affSColin Finck 
441c2c66affSColin Finck /*
442c2c66affSColin Finck  /// Property Sheet Dialog (outer dialog)
443c2c66affSColin Finck struct PropertySheetDlg : public SubclassedWindow
444c2c66affSColin Finck {
445c2c66affSColin Finck 	typedef SubclassedWindow super;
446c2c66affSColin Finck 
447c2c66affSColin Finck 	PropertySheetDlg(HWND hwnd) : super(hwnd) {}
448c2c66affSColin Finck };
449c2c66affSColin Finck */
450c2c66affSColin Finck 
451c2c66affSColin Finck 
452c2c66affSColin Finck  // Layouting of resizable windows
453c2c66affSColin Finck 
454c2c66affSColin Finck  /// Flags to specify how to move and resize controls when resizing their parent window
455c2c66affSColin Finck enum RESIZE_FLAGS {
456c2c66affSColin Finck 	MOVE_LEFT	= 0x1,
457c2c66affSColin Finck 	MOVE_RIGHT	= 0x2,
458c2c66affSColin Finck 	MOVE_TOP	= 0x4,
459c2c66affSColin Finck 	MOVE_BOTTOM	= 0x8,
460c2c66affSColin Finck 
461c2c66affSColin Finck 	MOVE_X	=  MOVE_LEFT | MOVE_RIGHT,
462c2c66affSColin Finck 	MOVE_Y	=  MOVE_TOP | MOVE_BOTTOM,
463c2c66affSColin Finck 	RESIZE_X=  MOVE_RIGHT,
464c2c66affSColin Finck 	RESIZE_Y=  MOVE_BOTTOM,
465c2c66affSColin Finck 
466c2c66affSColin Finck 	MOVE	= MOVE_X   | MOVE_Y,
467c2c66affSColin Finck 	RESIZE	= RESIZE_X | RESIZE_Y
468c2c66affSColin Finck };
469c2c66affSColin Finck 
470c2c66affSColin Finck  /// structure to assign RESIZE_FLAGS to dialogs control
471c2c66affSColin Finck struct ResizeEntry
472c2c66affSColin Finck {
ResizeEntryResizeEntry473c2c66affSColin Finck 	ResizeEntry(UINT id, int flags)
474c2c66affSColin Finck 	 : _id(id), _flags(flags) {}
475c2c66affSColin Finck 
ResizeEntryResizeEntry476c2c66affSColin Finck 	ResizeEntry(HWND hwnd, int flags)
477c2c66affSColin Finck 	 : _id(GetDlgCtrlID(hwnd)), _flags(flags) {}
478c2c66affSColin Finck 
479c2c66affSColin Finck 	UINT	_id;
480c2c66affSColin Finck 	int		_flags;
481c2c66affSColin Finck };
482c2c66affSColin Finck 
483c2c66affSColin Finck 
484c2c66affSColin Finck  /// Management of controls in resizable dialogs
485c2c66affSColin Finck struct ResizeManager : public std::list<ResizeEntry>
486c2c66affSColin Finck {
487c2c66affSColin Finck 	typedef std::list<ResizeEntry> super;
488c2c66affSColin Finck 
489c2c66affSColin Finck 	ResizeManager(HWND hwnd);
490c2c66affSColin Finck 
AddResizeManager491c2c66affSColin Finck 	void Add(UINT id, int flags)
492c2c66affSColin Finck 		{push_back(ResizeEntry(id, flags));}
493c2c66affSColin Finck 
AddResizeManager494c2c66affSColin Finck 	void Add(HWND hwnd, int flags)
495c2c66affSColin Finck 		{push_back(ResizeEntry(hwnd, flags));}
496c2c66affSColin Finck 
497c2c66affSColin Finck 	void HandleSize(int cx, int cy);
498c2c66affSColin Finck 	void Resize(int dx, int dy);
499c2c66affSColin Finck 
SetMinMaxInfoResizeManager500c2c66affSColin Finck 	void SetMinMaxInfo(LPMINMAXINFO lpmmi)
501c2c66affSColin Finck 	{
502c2c66affSColin Finck 		lpmmi->ptMinTrackSize.x = _min_wnd_size.cx;
503c2c66affSColin Finck 		lpmmi->ptMinTrackSize.y = _min_wnd_size.cy;
504c2c66affSColin Finck 	}
505c2c66affSColin Finck 
506c2c66affSColin Finck 	SIZE	_min_wnd_size;
507c2c66affSColin Finck 
508c2c66affSColin Finck protected:
509c2c66affSColin Finck 	HWND	_hwnd;
510c2c66affSColin Finck 	SIZE	_last_size;
511c2c66affSColin Finck };
512c2c66affSColin Finck 
513c2c66affSColin Finck 
514c2c66affSColin Finck  /// Controller base template class for resizable dialogs
515c2c66affSColin Finck template<typename BASE> struct ResizeController : public BASE
516c2c66affSColin Finck {
517c2c66affSColin Finck 	typedef BASE super;
518c2c66affSColin Finck 
ResizeControllerResizeController519c2c66affSColin Finck 	ResizeController(HWND hwnd)
520c2c66affSColin Finck 	 :	super(hwnd),
521c2c66affSColin Finck 		_resize_mgr(hwnd)
522c2c66affSColin Finck 	{
523c2c66affSColin Finck 	}
524c2c66affSColin Finck 
WndProcResizeController525c2c66affSColin Finck 	LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
526c2c66affSColin Finck 	{
527c2c66affSColin Finck 		switch(nmsg) {
528c2c66affSColin Finck 		  case PM_FRM_CALC_CLIENT:
529c2c66affSColin Finck 			GetClientSpace((PRECT)lparam);
530c2c66affSColin Finck 			return TRUE;
531c2c66affSColin Finck 
532c2c66affSColin Finck 		  case WM_SIZE:
533c2c66affSColin Finck 			if (wparam != SIZE_MINIMIZED)
534c2c66affSColin Finck 				_resize_mgr.HandleSize(LOWORD(lparam), HIWORD(lparam));
535c2c66affSColin Finck 			goto def;
536c2c66affSColin Finck 
537c2c66affSColin Finck 		  case WM_GETMINMAXINFO:
538c2c66affSColin Finck 			_resize_mgr.SetMinMaxInfo((LPMINMAXINFO)lparam);
539c2c66affSColin Finck 			goto def;
540c2c66affSColin Finck 
541c2c66affSColin Finck 		  default: def:
542c2c66affSColin Finck 			return super::WndProc(nmsg, wparam, lparam);
543c2c66affSColin Finck 		}
544c2c66affSColin Finck 	}
545c2c66affSColin Finck 
GetClientSpaceResizeController546c2c66affSColin Finck 	virtual void GetClientSpace(PRECT prect)
547c2c66affSColin Finck 	{
548c2c66affSColin Finck 		 if (!IsIconic(this->_hwnd)) {
549c2c66affSColin Finck 			GetClientRect(this->_hwnd, prect);
550c2c66affSColin Finck 		 } else {
551c2c66affSColin Finck 			WINDOWPLACEMENT wp;
552c2c66affSColin Finck 			GetWindowPlacement(this->_hwnd, &wp);
553c2c66affSColin Finck 			prect->left = prect->top = 0;
554c2c66affSColin Finck 			prect->right = wp.rcNormalPosition.right-wp.rcNormalPosition.left-
555c2c66affSColin Finck 				2*(GetSystemMetrics(SM_CXSIZEFRAME)+GetSystemMetrics(SM_CXEDGE));
556c2c66affSColin Finck 			prect->bottom = wp.rcNormalPosition.bottom-wp.rcNormalPosition.top-
557c2c66affSColin Finck 				2*(GetSystemMetrics(SM_CYSIZEFRAME)+GetSystemMetrics(SM_CYEDGE))-
558c2c66affSColin Finck 				GetSystemMetrics(SM_CYCAPTION)-GetSystemMetrics(SM_CYMENUSIZE);
559c2c66affSColin Finck 		}
560c2c66affSColin Finck 	}
561c2c66affSColin Finck 
562c2c66affSColin Finck protected:
563c2c66affSColin Finck 	ResizeManager _resize_mgr;
564c2c66affSColin Finck };
565c2c66affSColin Finck 
566c2c66affSColin Finck 
567c2c66affSColin Finck  /**
568c2c66affSColin Finck 	This class constructs button controls.
569c2c66affSColin Finck 	The button will remain existent when the C++ Button object is destroyed.
570c2c66affSColin Finck 	There is no conjunction between C++ object and windows control life time.
571c2c66affSColin Finck  */
572c2c66affSColin Finck struct Button : public WindowHandle
573c2c66affSColin Finck {
574c2c66affSColin Finck 	Button(HWND parent, LPCTSTR text, int left, int top, int width, int height,
575c2c66affSColin Finck 			int id, DWORD flags=WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON, DWORD exStyle=0);
576c2c66affSColin Finck };
577c2c66affSColin Finck 
578c2c66affSColin Finck 
579c2c66affSColin Finck  /**
580c2c66affSColin Finck 	This class constructs static controls.
581c2c66affSColin Finck 	The control will remain existent when the C++ object is destroyed.
582c2c66affSColin Finck 	There is no conjunction between C++ object and windows control life time.
583c2c66affSColin Finck  */
584c2c66affSColin Finck struct Static : public WindowHandle
585c2c66affSColin Finck {
586c2c66affSColin Finck 	Static(HWND parent, LPCTSTR text, int left, int top, int width, int height,
587c2c66affSColin Finck 			int id, DWORD flags=WS_VISIBLE|WS_CHILD|SS_SIMPLE, DWORD ex_flags=0);
588c2c66affSColin Finck };
589c2c66affSColin Finck 
590c2c66affSColin Finck 
591c2c66affSColin Finck  // control color message routing for ColorStatic and HyperlinkCtrl
592c2c66affSColin Finck 
593c2c66affSColin Finck #define	PM_DISPATCH_CTLCOLOR	(WM_APP+0x08)
594c2c66affSColin Finck 
595c2c66affSColin Finck template<typename BASE> struct CtlColorParent : public BASE
596c2c66affSColin Finck {
597c2c66affSColin Finck 	typedef BASE super;
598c2c66affSColin Finck 
CtlColorParentCtlColorParent599c2c66affSColin Finck 	CtlColorParent(HWND hwnd)
600c2c66affSColin Finck 	 : super(hwnd) {}
601c2c66affSColin Finck 
WndProcCtlColorParent602c2c66affSColin Finck 	LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
603c2c66affSColin Finck 	{
604c2c66affSColin Finck 		switch(nmsg) {
605c2c66affSColin Finck 		  case WM_CTLCOLOR:
606c2c66affSColin Finck 		  case WM_CTLCOLORBTN:
607c2c66affSColin Finck 		  case WM_CTLCOLORDLG:
608c2c66affSColin Finck 		  case WM_CTLCOLORSCROLLBAR:
609c2c66affSColin Finck 		  case WM_CTLCOLORSTATIC: {
610c2c66affSColin Finck 			HWND hctl = (HWND) lparam;
611c2c66affSColin Finck 			return SendMessage(hctl, PM_DISPATCH_CTLCOLOR, wparam, nmsg);
612c2c66affSColin Finck 		  }
613c2c66affSColin Finck 
614c2c66affSColin Finck 		  default:
615c2c66affSColin Finck 			return super::WndProc(nmsg, wparam, lparam);
616c2c66affSColin Finck 		}
617c2c66affSColin Finck 	}
618c2c66affSColin Finck };
619c2c66affSColin Finck 
620c2c66affSColin Finck 
621c2c66affSColin Finck #define	PM_DISPATCH_DRAWITEM	(WM_APP+0x09)
622c2c66affSColin Finck 
623c2c66affSColin Finck  /// draw message routing for ColorButton and PictureButton
624c2c66affSColin Finck template<typename BASE> struct OwnerDrawParent : public BASE
625c2c66affSColin Finck {
626c2c66affSColin Finck 	typedef BASE super;
627c2c66affSColin Finck 
OwnerDrawParentOwnerDrawParent628c2c66affSColin Finck 	OwnerDrawParent(HWND hwnd)
629c2c66affSColin Finck 	 : super(hwnd) {}
630c2c66affSColin Finck 
WndProcOwnerDrawParent631c2c66affSColin Finck 	LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
632c2c66affSColin Finck 	{
633c2c66affSColin Finck 		switch(nmsg) {
634c2c66affSColin Finck 		  case WM_DRAWITEM:
635c2c66affSColin Finck 			if (wparam) {	// should there be drawn a control?
636c2c66affSColin Finck 				HWND hctl = GetDlgItem(this->_hwnd, wparam);
637c2c66affSColin Finck 
638c2c66affSColin Finck 				if (hctl)
639c2c66affSColin Finck 					return SendMessage(hctl, PM_DISPATCH_DRAWITEM, wparam, lparam);
640c2c66affSColin Finck 			} /*else		// or is it a menu entry?
641c2c66affSColin Finck 				; */
642c2c66affSColin Finck 
643c2c66affSColin Finck 			return 0;
644c2c66affSColin Finck 
645c2c66affSColin Finck 		  default:
646c2c66affSColin Finck 			return super::WndProc(nmsg, wparam, lparam);
647c2c66affSColin Finck 		}
648c2c66affSColin Finck 	}
649c2c66affSColin Finck };
650c2c66affSColin Finck 
651c2c66affSColin Finck 
652c2c66affSColin Finck  /**
653c2c66affSColin Finck 	Subclass button controls to draw them by using PM_DISPATCH_DRAWITEM
654c2c66affSColin Finck 	The owning window should use the OwnerDrawParent template to route owner draw messages to the buttons.
655c2c66affSColin Finck  */
656c2c66affSColin Finck struct OwnerdrawnButton : public SubclassedWindow
657c2c66affSColin Finck {
658c2c66affSColin Finck 	typedef SubclassedWindow super;
659c2c66affSColin Finck 
OwnerdrawnButtonOwnerdrawnButton660c2c66affSColin Finck 	OwnerdrawnButton(HWND hwnd)
661c2c66affSColin Finck 	 :	super(hwnd) {}
662c2c66affSColin Finck 
663c2c66affSColin Finck protected:
664c2c66affSColin Finck 	LRESULT	WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam);
665c2c66affSColin Finck 
666c2c66affSColin Finck 	virtual void DrawItem(LPDRAWITEMSTRUCT dis) = 0;
667c2c66affSColin Finck };
668c2c66affSColin Finck 
669c2c66affSColin Finck extern void DrawGrayText(HDC hdc, LPRECT pRect, LPCTSTR text, int dt_flags);
670c2c66affSColin Finck 
671c2c66affSColin Finck 
672c2c66affSColin Finck  /**
673c2c66affSColin Finck 	Subclass button controls to paint colored text labels.
674c2c66affSColin Finck 	The owning window should use the OwnerDrawParent template to route owner draw messages to the buttons.
675c2c66affSColin Finck  */
676c2c66affSColin Finck /* not yet used
677c2c66affSColin Finck struct ColorButton : public OwnerdrawnButton
678c2c66affSColin Finck {
679c2c66affSColin Finck 	typedef OwnerdrawnButton super;
680c2c66affSColin Finck 
681c2c66affSColin Finck 	ColorButton(HWND hwnd, COLORREF textColor)
682c2c66affSColin Finck 	 :	super(hwnd), _textColor(textColor) {}
683c2c66affSColin Finck 
684c2c66affSColin Finck protected:
685c2c66affSColin Finck 	virtual void DrawItem(LPDRAWITEMSTRUCT dis);
686c2c66affSColin Finck 
687c2c66affSColin Finck 	COLORREF _textColor;
688c2c66affSColin Finck };
689c2c66affSColin Finck */
690c2c66affSColin Finck 
691c2c66affSColin Finck 
692c2c66affSColin Finck struct FlatButton : public OwnerdrawnButton
693c2c66affSColin Finck {
694c2c66affSColin Finck 	typedef OwnerdrawnButton super;
695c2c66affSColin Finck 
FlatButtonFlatButton696c2c66affSColin Finck 	FlatButton(HWND hwnd)
697c2c66affSColin Finck 	 : super(hwnd), _active(false) {}
698c2c66affSColin Finck 
FlatButtonFlatButton699c2c66affSColin Finck 	FlatButton(HWND owner, int id)
700c2c66affSColin Finck 	 : super(GetDlgItem(owner, IDOK)), _active(false) {}
701c2c66affSColin Finck 
702c2c66affSColin Finck protected:
703c2c66affSColin Finck 	LRESULT	WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam);
704c2c66affSColin Finck 	virtual void DrawItem(LPDRAWITEMSTRUCT dis);
705c2c66affSColin Finck 
706c2c66affSColin Finck 	COLORREF _textColor;
707c2c66affSColin Finck 	COLORREF _activeColor;
708c2c66affSColin Finck 	bool	_active;
709c2c66affSColin Finck };
710c2c66affSColin Finck 
711c2c66affSColin Finck 
712c2c66affSColin Finck  /**
713c2c66affSColin Finck 	Subclass button controls to paint pictures left to the labels.
714c2c66affSColin Finck 	The buttons should have set the style bit BS_OWNERDRAW.
715c2c66affSColin Finck 	The owning window should use the OwnerDrawParent template to route owner draw messages to the buttons.
716c2c66affSColin Finck  */
717c2c66affSColin Finck struct PictureButton : public OwnerdrawnButton
718c2c66affSColin Finck {
719c2c66affSColin Finck 	typedef OwnerdrawnButton super;
720c2c66affSColin Finck 
721c2c66affSColin Finck 	PictureButton(HWND hwnd, HICON hIcon, HBRUSH hbrush=GetSysColorBrush(COLOR_BTNFACE), bool flat=false)
superPictureButton722c2c66affSColin Finck 	 :	super(hwnd), _hIcon(hIcon), _hBmp(0), _hBrush(hbrush), _flat(flat)
723c2c66affSColin Finck 	{
724c2c66affSColin Finck 		_cx = 16;
725c2c66affSColin Finck 		_cy = 16;
726c2c66affSColin Finck 	}
727c2c66affSColin Finck 
728c2c66affSColin Finck 	PictureButton(HWND hparent, int id, HICON hIcon, HBRUSH hbrush=GetSysColorBrush(COLOR_BTNFACE), bool flat=false)
superPictureButton729c2c66affSColin Finck 	 :	super(GetDlgItem(hparent, id)), _hIcon(hIcon), _hBmp(0), _hBrush(hbrush), _flat(flat)
730c2c66affSColin Finck 	{
731c2c66affSColin Finck 		_cx = 16;
732c2c66affSColin Finck 		_cy = 16;
733c2c66affSColin Finck 	}
734c2c66affSColin Finck 
735c2c66affSColin Finck 	PictureButton(HWND hwnd, HBITMAP hBmp, HBRUSH hbrush=GetSysColorBrush(COLOR_BTNFACE), bool flat=false)
superPictureButton736c2c66affSColin Finck 	 :	super(hwnd), _hIcon(0), _hBmp(hBmp), _hBrush(hbrush), _flat(flat)
737c2c66affSColin Finck 	{
738c2c66affSColin Finck 		BITMAP bmp;
739c2c66affSColin Finck 		GetObject(hBmp, sizeof(bmp), &bmp);
740c2c66affSColin Finck 		_cx = bmp.bmWidth;
741c2c66affSColin Finck 		_cy = bmp.bmHeight;
742c2c66affSColin Finck 	}
743c2c66affSColin Finck 
744c2c66affSColin Finck 	PictureButton(HWND hparent, int id, HBITMAP hBmp, HBRUSH hbrush=GetSysColorBrush(COLOR_BTNFACE), bool flat=false)
superPictureButton745c2c66affSColin Finck 	 :	super(GetDlgItem(hparent, id)), _hIcon(0), _hBmp(hBmp), _hBrush(hbrush), _flat(flat)
746c2c66affSColin Finck 	{
747c2c66affSColin Finck 		BITMAP bmp;
748c2c66affSColin Finck 		GetObject(hBmp, sizeof(bmp), &bmp);
749c2c66affSColin Finck 		_cx = bmp.bmWidth;
750c2c66affSColin Finck 		_cy = bmp.bmHeight;
751c2c66affSColin Finck 	}
752c2c66affSColin Finck 
753c2c66affSColin Finck protected:
754c2c66affSColin Finck 	virtual void DrawItem(LPDRAWITEMSTRUCT dis);
755c2c66affSColin Finck 
756c2c66affSColin Finck 	HICON	_hIcon;
757c2c66affSColin Finck 	HBITMAP	_hBmp;
758c2c66affSColin Finck 	HBRUSH	_hBrush;
759c2c66affSColin Finck 
760c2c66affSColin Finck 	int		_cx;
761c2c66affSColin Finck 	int		_cy;
762c2c66affSColin Finck 
763c2c66affSColin Finck 	bool	_flat;
764c2c66affSColin Finck };
765c2c66affSColin Finck 
766c2c66affSColin Finck 
767c2c66affSColin Finck struct ColorStatic : public SubclassedWindow
768c2c66affSColin Finck {
769c2c66affSColin Finck 	typedef SubclassedWindow super;
770c2c66affSColin Finck 
771c2c66affSColin Finck 	ColorStatic(HWND hwnd, COLORREF textColor=RGB(255,0,0), HBRUSH hbrush_bkgnd=0, HFONT hfont=0)
superColorStatic772c2c66affSColin Finck 	 :	super(hwnd),
773c2c66affSColin Finck 		_textColor(textColor),
774c2c66affSColin Finck 		_hbrush_bkgnd(hbrush_bkgnd),
775c2c66affSColin Finck 		_hfont(hfont)
776c2c66affSColin Finck 	{
777c2c66affSColin Finck 	}
778c2c66affSColin Finck 
779c2c66affSColin Finck 	ColorStatic(HWND owner, int id, COLORREF textColor=RGB(255,0,0), HBRUSH hbrush_bkgnd=0, HFONT hfont=0)
superColorStatic780c2c66affSColin Finck 	 :	super(GetDlgItem(owner, id)),
781c2c66affSColin Finck 		_textColor(textColor),
782c2c66affSColin Finck 		_hbrush_bkgnd(hbrush_bkgnd),
783c2c66affSColin Finck 		_hfont(hfont)
784c2c66affSColin Finck 	{
785c2c66affSColin Finck 	}
786c2c66affSColin Finck 
787c2c66affSColin Finck protected:
WndProcColorStatic788c2c66affSColin Finck 	LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
789c2c66affSColin Finck 	{
790c2c66affSColin Finck 		if (nmsg == PM_DISPATCH_CTLCOLOR) {
791c2c66affSColin Finck 			HDC hdc = (HDC) wparam;
792c2c66affSColin Finck 
793c2c66affSColin Finck 			SetTextColor(hdc, _textColor);
794c2c66affSColin Finck 
795c2c66affSColin Finck 			if (_hfont)
796c2c66affSColin Finck 				SelectFont(hdc, _hfont);
797c2c66affSColin Finck 
798c2c66affSColin Finck 			if (_hbrush_bkgnd)
799c2c66affSColin Finck 				return (LRESULT)_hbrush_bkgnd;
800c2c66affSColin Finck 			else {
801c2c66affSColin Finck 				SetBkMode(hdc, TRANSPARENT);
802c2c66affSColin Finck 				return (LRESULT)GetStockBrush(HOLLOW_BRUSH);
803c2c66affSColin Finck 			}
804c2c66affSColin Finck 		} else
805c2c66affSColin Finck 			return super::WndProc(nmsg, wparam, lparam);
806c2c66affSColin Finck 	}
807c2c66affSColin Finck 
808c2c66affSColin Finck 	COLORREF	_textColor;
809c2c66affSColin Finck 	HBRUSH		_hbrush_bkgnd;
810c2c66affSColin Finck 	HFONT		_hfont;
811c2c66affSColin Finck };
812c2c66affSColin Finck 
813c2c66affSColin Finck 
814c2c66affSColin Finck   /// Hyperlink Controls
815c2c66affSColin Finck 
816c2c66affSColin Finck struct HyperlinkCtrl : public SubclassedWindow
817c2c66affSColin Finck {
818c2c66affSColin Finck 	typedef SubclassedWindow super;
819c2c66affSColin Finck 
820c2c66affSColin Finck 	HyperlinkCtrl(HWND hwnd, COLORREF colorLink=RGB(0,0,255), COLORREF colorVisited=RGB(128,0,128));
821c2c66affSColin Finck 	HyperlinkCtrl(HWND owner, int id, COLORREF colorLink=RGB(0,0,255), COLORREF colorVisited=RGB(128,0,128));
822c2c66affSColin Finck 
823c2c66affSColin Finck 	~HyperlinkCtrl();
824c2c66affSColin Finck 
825c2c66affSColin Finck 	String	_cmd;
826c2c66affSColin Finck 
827c2c66affSColin Finck protected:
828c2c66affSColin Finck 	COLORREF _textColor;
829c2c66affSColin Finck 	COLORREF _colorVisited;
830c2c66affSColin Finck 	HFONT	 _hfont;
831c2c66affSColin Finck 	HCURSOR	_crsr_link;
832c2c66affSColin Finck 
833c2c66affSColin Finck 	LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam);
834c2c66affSColin Finck 
835c2c66affSColin Finck 	void init();
836c2c66affSColin Finck 
LaunchLinkHyperlinkCtrl837c2c66affSColin Finck 	bool LaunchLink()
838c2c66affSColin Finck 	{
839c2c66affSColin Finck 		if (!_cmd.empty()) {
840c2c66affSColin Finck 			HINSTANCE hinst = ShellExecute(GetParent(_hwnd), _T("open"), _cmd, 0, 0, SW_SHOWNORMAL);
841*a2f7de7eSTimo Kreuzer 			return (INT_PTR)hinst > HINSTANCE_ERROR;
842c2c66affSColin Finck 		}
843c2c66affSColin Finck 
844c2c66affSColin Finck 		return true;
845c2c66affSColin Finck 	}
846c2c66affSColin Finck };
847c2c66affSColin Finck 
848c2c66affSColin Finck 
849c2c66affSColin Finck  /// encapsulation of tool tip controls
850c2c66affSColin Finck struct ToolTip : public WindowHandle
851c2c66affSColin Finck {
852c2c66affSColin Finck 	typedef WindowHandle super;
853c2c66affSColin Finck 
854c2c66affSColin Finck 	ToolTip(HWND owner);
855c2c66affSColin Finck 
856c2c66affSColin Finck 	void activate(BOOL active=TRUE)
857c2c66affSColin Finck 	{
858c2c66affSColin Finck 		SendMessage(_hwnd, TTM_ACTIVATE, active, 0);
859c2c66affSColin Finck 	}
860c2c66affSColin Finck 
861c2c66affSColin Finck 	void add(HWND hparent, HWND htool, LPCTSTR txt=LPSTR_TEXTCALLBACK, LPARAM lparam=0)
862c2c66affSColin Finck 	{
863c2c66affSColin Finck 		TOOLINFO ti = {
864*a2f7de7eSTimo Kreuzer 			sizeof(TOOLINFO), TTF_SUBCLASS|TTF_IDISHWND|TTF_TRANSPARENT, hparent, (UINT_PTR)htool,
865c2c66affSColin Finck 			{0,0,0,0}, 0, (LPTSTR)txt, lparam
866c2c66affSColin Finck 		};
867c2c66affSColin Finck 
868c2c66affSColin Finck #ifdef UNICODE	///@todo Why is it neccesary to try both TTM_ADDTOOLW and TTM_ADDTOOLW ?!
869c2c66affSColin Finck 		if (!SendMessage(_hwnd, TTM_ADDTOOLW, 0, (LPARAM)&ti))
870c2c66affSColin Finck 			SendMessage(_hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti);
871c2c66affSColin Finck #else
872c2c66affSColin Finck 		if (!SendMessage(_hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti))
873c2c66affSColin Finck 			SendMessage(_hwnd, TTM_ADDTOOLW, 0, (LPARAM)&ti);
874c2c66affSColin Finck #endif
875c2c66affSColin Finck 	}
876c2c66affSColin Finck 
877c2c66affSColin Finck 	void add(HWND hparent, UINT id, const RECT& rect, LPCTSTR txt=LPSTR_TEXTCALLBACK, LPARAM lparam=0)
878c2c66affSColin Finck 	{
879c2c66affSColin Finck 		TOOLINFO ti = {
880c2c66affSColin Finck 			sizeof(TOOLINFO), TTF_SUBCLASS|TTF_TRANSPARENT, hparent, id,
881c2c66affSColin Finck 			{rect.left,rect.top,rect.right,rect.bottom}, 0, (LPTSTR)txt, lparam
882c2c66affSColin Finck 		};
883c2c66affSColin Finck 
884c2c66affSColin Finck #ifdef UNICODE
885c2c66affSColin Finck 		if (!SendMessage(_hwnd, TTM_ADDTOOLW, 0, (LPARAM)&ti))
886c2c66affSColin Finck 			SendMessage(_hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti);
887c2c66affSColin Finck #else
888c2c66affSColin Finck 		if (!SendMessage(_hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti))
889c2c66affSColin Finck 			SendMessage(_hwnd, TTM_ADDTOOLW, 0, (LPARAM)&ti);
890c2c66affSColin Finck #endif
891c2c66affSColin Finck 	}
892c2c66affSColin Finck 
removeToolTip893c2c66affSColin Finck 	void remove(HWND hparent, HWND htool)
894c2c66affSColin Finck 	{
895c2c66affSColin Finck 		TOOLINFO ti = {
896*a2f7de7eSTimo Kreuzer 			sizeof(TOOLINFO), TTF_IDISHWND, hparent, (UINT_PTR)htool,
897c2c66affSColin Finck 			{0,0,0,0}, 0, 0, 0
898c2c66affSColin Finck 		};
899c2c66affSColin Finck 
900c2c66affSColin Finck 		SendMessage(_hwnd, TTM_DELTOOL, 0, (LPARAM)&ti);
901c2c66affSColin Finck 	}
902c2c66affSColin Finck 
removeToolTip903c2c66affSColin Finck 	void remove(HWND hparent, UINT id)
904c2c66affSColin Finck 	{
905c2c66affSColin Finck 		TOOLINFO ti = {
906c2c66affSColin Finck 			sizeof(TOOLINFO), 0, hparent, id,
907c2c66affSColin Finck 			{0,0,0,0}, 0, 0, 0
908c2c66affSColin Finck 		};
909c2c66affSColin Finck 
910c2c66affSColin Finck 		SendMessage(_hwnd, TTM_DELTOOL, 0, (LPARAM)&ti);
911c2c66affSColin Finck 	}
912c2c66affSColin Finck };
913c2c66affSColin Finck 
914c2c66affSColin Finck 
ListView_GetItemData(HWND list_ctrl,int idx)915c2c66affSColin Finck inline int ListView_GetItemData(HWND list_ctrl, int idx)
916c2c66affSColin Finck {
917c2c66affSColin Finck 	LV_ITEM item;
918c2c66affSColin Finck 
919c2c66affSColin Finck 	item.mask = LVIF_PARAM;
920c2c66affSColin Finck 	item.iItem = idx;
921c2c66affSColin Finck 
922c2c66affSColin Finck 	if (!ListView_GetItem(list_ctrl, &item))
923c2c66affSColin Finck 		return 0;
924c2c66affSColin Finck 
925c2c66affSColin Finck 	return item.lParam;
926c2c66affSColin Finck }
927c2c66affSColin Finck 
ListView_FindItemPara(HWND list_ctrl,LPARAM param)928c2c66affSColin Finck inline int ListView_FindItemPara(HWND list_ctrl, LPARAM param)
929c2c66affSColin Finck {
930c2c66affSColin Finck 	LVFINDINFO fi;
931c2c66affSColin Finck 
932c2c66affSColin Finck 	fi.flags = LVFI_PARAM;
933c2c66affSColin Finck 	fi.lParam = param;
934c2c66affSColin Finck 
935c2c66affSColin Finck 	return ListView_FindItem(list_ctrl, (unsigned)-1, &fi);
936c2c66affSColin Finck }
937c2c66affSColin Finck 
ListView_GetFocusedItem(HWND list_ctrl)938c2c66affSColin Finck inline int ListView_GetFocusedItem(HWND list_ctrl)
939c2c66affSColin Finck {
940c2c66affSColin Finck 	int idx = ListView_GetItemCount(list_ctrl);
941c2c66affSColin Finck 
942c2c66affSColin Finck 	while(--idx >= 0)
943c2c66affSColin Finck 		if (ListView_GetItemState(list_ctrl, idx, LVIS_FOCUSED))
944c2c66affSColin Finck 			break;
945c2c66affSColin Finck 
946c2c66affSColin Finck 	return idx;
947c2c66affSColin Finck }
948c2c66affSColin Finck 
949c2c66affSColin Finck 
950c2c66affSColin Finck  /// sorting of list controls
951c2c66affSColin Finck struct ListSort : public WindowHandle
952c2c66affSColin Finck {
953c2c66affSColin Finck 	ListSort(HWND hwndListview, PFNLVCOMPARE compare_fct);
954c2c66affSColin Finck 
955c2c66affSColin Finck 	void	toggle_sort(int idx);
956c2c66affSColin Finck 	void	sort();
957c2c66affSColin Finck 
958c2c66affSColin Finck 	int		_sort_crit;
959c2c66affSColin Finck 	bool	_direction;
960c2c66affSColin Finck 
961c2c66affSColin Finck protected:
962c2c66affSColin Finck 	PFNLVCOMPARE _compare_fct;
963c2c66affSColin Finck 
964c2c66affSColin Finck 	static int CALLBACK CompareFunc(LPARAM lparam1, LPARAM lparam2, LPARAM lparamSort);
965c2c66affSColin Finck };
966c2c66affSColin Finck 
967c2c66affSColin Finck 
TreeView_GetItemData(HWND hwndTreeView,HTREEITEM hItem)968c2c66affSColin Finck inline LPARAM TreeView_GetItemData(HWND hwndTreeView, HTREEITEM hItem)
969c2c66affSColin Finck {
970c2c66affSColin Finck 	TVITEM tvItem;
971c2c66affSColin Finck 
972c2c66affSColin Finck 	tvItem.mask = TVIF_PARAM;
973c2c66affSColin Finck 	tvItem.hItem = hItem;
974c2c66affSColin Finck 
975c2c66affSColin Finck 	if (!TreeView_GetItem(hwndTreeView, &tvItem))
976c2c66affSColin Finck 		return 0;
977c2c66affSColin Finck 
978c2c66affSColin Finck 	return tvItem.lParam;
979c2c66affSColin Finck }
980c2c66affSColin Finck 
981c2c66affSColin Finck 
982c2c66affSColin Finck enum {TRAYBUTTON_LEFT=0, TRAYBUTTON_RIGHT, TRAYBUTTON_MIDDLE};
983c2c66affSColin Finck 
984c2c66affSColin Finck #define	PM_TRAYICON		(WM_APP+0x20)
985c2c66affSColin Finck 
986c2c66affSColin Finck #define	WINMSG_TASKBARCREATED	TEXT("TaskbarCreated")
987c2c66affSColin Finck 
988c2c66affSColin Finck #define	WINMSG_SHELLHOOK		TEXT("SHELLHOOK")
989c2c66affSColin Finck 
990c2c66affSColin Finck 
991c2c66affSColin Finck struct TrayIcon
992c2c66affSColin Finck {
TrayIconTrayIcon993c2c66affSColin Finck 	TrayIcon(HWND hparent, UINT id)
994c2c66affSColin Finck 	 :	_hparent(hparent), _id(id) {}
995c2c66affSColin Finck 
~TrayIconTrayIcon996c2c66affSColin Finck 	~TrayIcon()
997c2c66affSColin Finck 		{Remove();}
998c2c66affSColin Finck 
999c2c66affSColin Finck 	void	Add(HICON hIcon, LPCTSTR tooltip=NULL)
1000c2c66affSColin Finck 		{Set(NIM_ADD, _id, hIcon, tooltip);}
1001c2c66affSColin Finck 
1002c2c66affSColin Finck 	void	Modify(HICON hIcon, LPCTSTR tooltip=NULL)
1003c2c66affSColin Finck 		{Set(NIM_MODIFY, _id, hIcon, tooltip);}
1004c2c66affSColin Finck 
RemoveTrayIcon1005c2c66affSColin Finck 	void	Remove()
1006c2c66affSColin Finck 	{
1007c2c66affSColin Finck 		NOTIFYICONDATA nid = {
1008c2c66affSColin Finck 			sizeof(NOTIFYICONDATA),	// cbSize
1009c2c66affSColin Finck 			_hparent,				// hWnd
1010c2c66affSColin Finck 			_id,					// uID
1011c2c66affSColin Finck 		};
1012c2c66affSColin Finck 
1013c2c66affSColin Finck 		Shell_NotifyIcon(NIM_DELETE, &nid);
1014c2c66affSColin Finck 	}
1015c2c66affSColin Finck 
1016c2c66affSColin Finck protected:
1017c2c66affSColin Finck 	HWND	_hparent;
1018c2c66affSColin Finck 	UINT	_id;
1019c2c66affSColin Finck 
1020c2c66affSColin Finck 	void	Set(DWORD dwMessage, UINT id, HICON hIcon, LPCTSTR tooltip=NULL)
1021c2c66affSColin Finck 	{
1022c2c66affSColin Finck 		NOTIFYICONDATA nid = {
1023c2c66affSColin Finck 			sizeof(NOTIFYICONDATA),	// cbSize
1024c2c66affSColin Finck 			_hparent,				// hWnd
1025c2c66affSColin Finck 			id,						// uID
1026c2c66affSColin Finck 			NIF_MESSAGE|NIF_ICON,	// uFlags
1027c2c66affSColin Finck 			PM_TRAYICON,			// uCallbackMessage
1028c2c66affSColin Finck 			hIcon					// hIcon
1029c2c66affSColin Finck 		};
1030c2c66affSColin Finck 
1031c2c66affSColin Finck 		if (tooltip)
1032c2c66affSColin Finck 			lstrcpyn(nid.szTip, tooltip, COUNTOF(nid.szTip));
1033c2c66affSColin Finck 
1034c2c66affSColin Finck 		if (nid.szTip[0])
1035c2c66affSColin Finck 			nid.uFlags |= NIF_TIP;
1036c2c66affSColin Finck 
1037c2c66affSColin Finck 		Shell_NotifyIcon(dwMessage, &nid);
1038c2c66affSColin Finck 	}
1039c2c66affSColin Finck };
1040c2c66affSColin Finck 
1041c2c66affSColin Finck 
1042c2c66affSColin Finck template<typename BASE> struct TrayIconControllerTemplate : public BASE
1043c2c66affSColin Finck {
1044c2c66affSColin Finck 	typedef BASE super;
1045c2c66affSColin Finck 
TrayIconControllerTemplateTrayIconControllerTemplate1046c2c66affSColin Finck 	TrayIconControllerTemplate(HWND hwnd) : BASE(hwnd),
1047c2c66affSColin Finck 		WM_TASKBARCREATED(RegisterWindowMessage(WINMSG_TASKBARCREATED))
1048c2c66affSColin Finck 	{
1049c2c66affSColin Finck 	}
1050c2c66affSColin Finck 
WndProcTrayIconControllerTemplate1051c2c66affSColin Finck 	LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
1052c2c66affSColin Finck 	{
1053c2c66affSColin Finck 		if (nmsg == PM_TRAYICON) {
1054c2c66affSColin Finck 			switch(lparam) {
1055c2c66affSColin Finck 			  case WM_MOUSEMOVE:
1056c2c66affSColin Finck 				TrayMouseOver(wparam);
1057c2c66affSColin Finck 				break;
1058c2c66affSColin Finck 
1059c2c66affSColin Finck 			  case WM_LBUTTONDOWN:
1060c2c66affSColin Finck 				TrayClick(wparam, TRAYBUTTON_LEFT);
1061c2c66affSColin Finck 				break;
1062c2c66affSColin Finck 
1063c2c66affSColin Finck 			  case WM_LBUTTONDBLCLK:
1064c2c66affSColin Finck 				TrayDblClick(wparam, TRAYBUTTON_LEFT);
1065c2c66affSColin Finck 				break;
1066c2c66affSColin Finck 
1067c2c66affSColin Finck 			  case WM_RBUTTONDOWN:
1068c2c66affSColin Finck 				TrayClick(wparam, TRAYBUTTON_RIGHT);
1069c2c66affSColin Finck 				break;
1070c2c66affSColin Finck 
1071c2c66affSColin Finck 			  case WM_RBUTTONDBLCLK:
1072c2c66affSColin Finck 				TrayDblClick(wparam, TRAYBUTTON_RIGHT);
1073c2c66affSColin Finck 				break;
1074c2c66affSColin Finck 
1075c2c66affSColin Finck 			  case WM_MBUTTONDOWN:
1076c2c66affSColin Finck 				TrayClick(wparam, TRAYBUTTON_MIDDLE);
1077c2c66affSColin Finck 				break;
1078c2c66affSColin Finck 
1079c2c66affSColin Finck 			  case WM_MBUTTONDBLCLK:
1080c2c66affSColin Finck 				TrayDblClick(wparam, TRAYBUTTON_MIDDLE);
1081c2c66affSColin Finck 				break;
1082c2c66affSColin Finck 			}
1083c2c66affSColin Finck 
1084c2c66affSColin Finck 			return 0;
1085c2c66affSColin Finck 		} else if (nmsg == WM_TASKBARCREATED) {
1086c2c66affSColin Finck 			AddTrayIcons();
1087c2c66affSColin Finck 			return 0;
1088c2c66affSColin Finck 		} else
1089c2c66affSColin Finck 			return super::WndProc(nmsg, wparam, lparam);
1090c2c66affSColin Finck 	}
1091c2c66affSColin Finck 
1092c2c66affSColin Finck 	virtual void AddTrayIcons() = 0;
TrayMouseOverTrayIconControllerTemplate1093c2c66affSColin Finck 	virtual void TrayMouseOver(UINT id) {}
TrayClickTrayIconControllerTemplate1094c2c66affSColin Finck 	virtual void TrayClick(UINT id, int btn) {}
TrayDblClickTrayIconControllerTemplate1095c2c66affSColin Finck 	virtual void TrayDblClick(UINT id, int btn) {}
1096c2c66affSColin Finck 
1097c2c66affSColin Finck protected:
1098c2c66affSColin Finck 	const UINT WM_TASKBARCREATED;
1099c2c66affSColin Finck };
1100c2c66affSColin Finck 
1101c2c66affSColin Finck 
1102c2c66affSColin Finck struct EditController : public SubclassedWindow
1103c2c66affSColin Finck {
1104c2c66affSColin Finck 	typedef SubclassedWindow super;
1105c2c66affSColin Finck 
EditControllerEditController1106c2c66affSColin Finck 	EditController(HWND hwnd)
1107c2c66affSColin Finck 	 :	super(hwnd)
1108c2c66affSColin Finck 	{
1109c2c66affSColin Finck 	}
1110c2c66affSColin Finck 
1111c2c66affSColin Finck protected:
WndProcEditController1112c2c66affSColin Finck 	LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
1113c2c66affSColin Finck 	{
1114c2c66affSColin Finck 		if (nmsg==WM_KEYDOWN && wparam==VK_RETURN) {
1115c2c66affSColin Finck 			SendParent(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(_hwnd),1), (LPARAM)_hwnd);
1116c2c66affSColin Finck 			return 0;
1117c2c66affSColin Finck 		} else
1118c2c66affSColin Finck 			return super::WndProc(nmsg, wparam, lparam);
1119c2c66affSColin Finck 	}
1120c2c66affSColin Finck };
1121