1 /*
2  * Copyright 2003, 2004, 2005 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 clone
22  //
23  // shellbrowser.h
24  //
25  // Martin Fuchs, 23.07.2003
26  //
27 
28 #include "../utility/treedroptarget.h"
29 #include "../utility/shellbrowserimpl.h"
30 
31 #include <memory>
32 
33  /// information structure to hold current shell folder information
34 struct ShellPathInfo
35 {
36 	ShellPathInfo(int mode=0) : _open_mode(mode) {}
37 
38 	ShellPathInfo(const ShellChildWndInfo& info)
39 	 :	_shell_path(info._shell_path),
40 		_root_shell_path(info._root_shell_path),
41 		_open_mode(info._open_mode)
42 	{
43 	}
44 
45 	ShellPath	_shell_path;
46 	ShellPath	_root_shell_path;
47 
48 	int			_open_mode;	//OPEN_WINDOW_MODE
49 };
50 
51 
52 struct BrowserCallback
53 {
54 	virtual ~BrowserCallback() {}
55 	virtual void entry_selected(Entry* entry) = 0;
56 };
57 
58 
59  /// Implementation of IShellBrowserImpl interface in explorer child windows
60 struct ShellBrowser : public IShellBrowserImpl,
61 		public IComSrvBase<IShellFolderViewCB, ShellBrowser>, public SimpleComObject
62 {
63 	ShellBrowser(HWND hwnd, HWND hwndFrame, HWND left_hwnd, WindowHandle& right_hwnd, ShellPathInfo& create_info,
64 					BrowserCallback* cb, CtxMenuInterfaces& cm_ifs);
65 	virtual ~ShellBrowser();
66 
67 	//IOleWindow
68 	virtual HRESULT STDMETHODCALLTYPE GetWindow(HWND* lphwnd)
69 	{
70 		*lphwnd = _hwnd;
71 		return S_OK;
72 	}
73 
74 	//IShellBrowser
75 	virtual HRESULT STDMETHODCALLTYPE QueryActiveShellView(IShellView** ppshv)
76 	{
77 		_pShellView->AddRef();
78 		*ppshv = _pShellView;
79 		return S_OK;
80 	}
81 
82 	virtual HRESULT STDMETHODCALLTYPE GetControlWindow(UINT id, HWND* lphwnd)
83 	{
84 		if (!lphwnd)
85 			return E_POINTER;
86 
87 		if (id == FCW_TREE) {
88 			*lphwnd = _left_hwnd;
89 			return S_OK;
90 		}
91 
92 		HWND hwnd = (HWND)SendMessage(_hwndFrame, PM_GET_CONTROLWINDOW, id, 0);
93 
94 		if (hwnd) {
95 			*lphwnd = hwnd;
96 			return S_OK;
97 		}
98 
99 		return E_NOTIMPL;
100 	}
101 
102 	virtual HRESULT STDMETHODCALLTYPE SendControlMsg(UINT id, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* pret)
103 	{
104 		if (!pret)
105 			return E_POINTER;
106 
107 		HWND hstatusbar = (HWND)SendMessage(_hwndFrame, PM_GET_CONTROLWINDOW, id, 0);
108 
109 		if (hstatusbar) {
110 			*pret = ::SendMessage(hstatusbar, uMsg, wParam, lParam);
111 			return S_OK;
112 		}
113 
114 		return E_NOTIMPL;
115 	}
116 
117 	const Root& get_root() const {return _root;}
118 
119 	void	OnTreeGetDispInfo(int idCtrl, LPNMHDR pnmh);
120 	void	OnTreeItemExpanding(int idCtrl, LPNMTREEVIEW pnmtv);
121 	void	OnTreeItemRClick(int idCtrl, LPNMHDR pnmh);
122 	void	OnTreeItemSelected(int idCtrl, LPNMTREEVIEW pnmtv);
123 
124 	void	Init();
125 
126 	int		InsertSubitems(HTREEITEM hParentItem, Entry* entry, IShellFolder* pParentFolder);
127 
128 	bool	jump_to_pidl(LPCITEMIDLIST pidl);
129 
130 	HRESULT OnDefaultCommand(LPIDA pida);
131 
132 	void	UpdateFolderView(IShellFolder* folder);
133 	HTREEITEM select_entry(HTREEITEM hitem, Entry* entry, bool expand=true);
134 
135 	bool	select_folder(Entry* entry, bool expand);
136 
137 	 // for SDIMainFrame
138 	void	jump_to(LPCITEMIDLIST pidl);
139 
140 	void	invalidate_cache();
141 
142 	bool TranslateAccelerator(LPMSG lpmsg);
143 
144 protected:
145 	HWND			_hwnd;
146 	HWND			_hwndFrame;
147 	HWND			_left_hwnd;
148 	WindowHandle&	_right_hwnd;
149 	ShellPathInfo&	_create_info;
150 	HIMAGELIST		_himl;
151 	HIMAGELIST		_himl_old;
152 	BrowserCallback* _callback;
153 
154 	ShellFolder		_folder;
155 
156 	IShellView*		_pShellView;	// current hosted shellview
157 	TreeDropTarget*	_pDropTarget;
158 
159 	HTREEITEM		_last_sel;
160 
161 	Root			_root;
162 	ShellDirectory*	_cur_dir;
163 
164 	CtxMenuInterfaces& _cm_ifs;
165 
166 	void	InitializeTree();
167 	bool	InitDragDrop();
168 
169 	typedef IComSrvBase<IShellFolderViewCB, ShellBrowser> super;
170 
171 	 // IShellFolderViewCB
172 	virtual HRESULT STDMETHODCALLTYPE MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam);
173 
174 	map<int, int> _image_map;
175 
176 	int		get_image_idx(int icon_id);
177 
178 	void	refresh();
179 };
180 
181 
182 #define	C_DRIVE_STR TEXT("C:\\")
183 
184  // work around GCC's wide string constant bug
185 #ifdef __GNUC__
186 extern const LPCTSTR C_DRIVE;
187 #else
188 #define	C_DRIVE C_DRIVE_STR
189 #endif
190 
191 template<typename BASE> struct ShellBrowserChildT
192  : public BASE, public BrowserCallback
193 {
194 	typedef BASE super;
195 
196 	 // constructor for SDIMainFrame
197 	ShellBrowserChildT(HWND hwnd)
198 	 :	super(hwnd)
199 	{
200 	}
201 
202 	 // constructor for MDIShellBrowserChild
203 	ShellBrowserChildT(HWND hwnd, const ShellChildWndInfo& info)
204 	 :	super(hwnd, info)
205 	{
206 	}
207 
208 protected:
209 	auto_ptr<ShellBrowser> _shellBrowser;
210 
211 	LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
212 	{
213 		switch(nmsg) {
214 		  case PM_GET_SHELLBROWSER_PTR:
215 			return (LRESULT)&*_shellBrowser;
216 
217 		  case WM_GETISHELLBROWSER:	// for Registry Explorer Plugin
218 			return (LRESULT)static_cast<IShellBrowser*>(&*_shellBrowser);
219 
220 		  default:
221 			return super::WndProc(nmsg, wparam, lparam);
222 		}
223 
224 		return 0;
225 	}
226 
227 	int Notify(int id, NMHDR* pnmh)
228 	{
229 		if (_shellBrowser.get())
230 			switch(pnmh->code) {
231 			  case TVN_GETDISPINFO:		_shellBrowser->OnTreeGetDispInfo(id, pnmh);					break;
232 			  case TVN_SELCHANGED:		_shellBrowser->OnTreeItemSelected(id, (LPNMTREEVIEW)pnmh);	break;
233 			  case TVN_ITEMEXPANDING:	_shellBrowser->OnTreeItemExpanding(id, (LPNMTREEVIEW)pnmh);	break;
234 			  case NM_RCLICK:			_shellBrowser->OnTreeItemRClick(id, pnmh);					break;
235 			  default:					return super::Notify(id, pnmh);
236 			}
237 		else
238 			return super::Notify(id, pnmh);
239 
240 		return 0;
241 	}
242 };
243 
244 
245 #ifndef _NO_MDI
246 
247 struct MDIShellBrowserChild : public ExtContextMenuHandlerT<
248 				ShellBrowserChildT<ChildWindow>
249 			>
250 {
251 	typedef ExtContextMenuHandlerT<
252 				ShellBrowserChildT<ChildWindow>
253 			> super;
254 
255 	MDIShellBrowserChild(HWND hwnd, const ShellChildWndInfo& info);
256 
257 	static MDIShellBrowserChild* create(const ShellChildWndInfo& info);
258 
259 	LRESULT	Init(LPCREATESTRUCT);
260 
261 	virtual String jump_to_int(LPCTSTR url);
262 
263 protected:
264 	ShellChildWndInfo _create_info;
265 	ShellPathInfo	_shellpath_info;
266 
267 	LRESULT	WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam);
268 
269 	void	update_shell_browser();
270 
271 	 // interface BrowserCallback
272 	virtual void entry_selected(Entry* entry);
273 };
274 
275 #endif
276