1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #ifndef _FILEOPENDLG_HXX_
25 #define _FILEOPENDLG_HXX_
26 
27 //------------------------------------------------------------------------
28 // includes
29 //------------------------------------------------------------------------
30 
31 #include <sal/types.h>
32 
33 #ifndef _RTL_USTRING_HXX_
34 #include <rtl/ustring>
35 #endif
36 #include <rtl/ustrbuf.hxx>
37 
38 #include "platform_xp.h"
39 #include "getfilenamewrapper.hxx"
40 
41 // because we don't want to import the new W2k platform skd
42 // into our build environment if have stolen the definition
43 // for the new OPENFILENAME structure from the new headers
44 
45 #ifndef _CDSIZEOF_STRUCT
46 #define _CDSIZEOF_STRUCT(structname, member)  (((int)((LPBYTE)(&((structname*)0)->member) - ((LPBYTE)((structname*)0)))) + sizeof(((structname*)0)->member))
47 #endif
48 
49 typedef struct _tagOFNA {
50    DWORD        lStructSize;
51    HWND         hwndOwner;
52    HINSTANCE    hInstance;
53    LPCSTR       lpstrFilter;
54    LPSTR        lpstrCustomFilter;
55    DWORD        nMaxCustFilter;
56    DWORD        nFilterIndex;
57    LPSTR        lpstrFile;
58    DWORD        nMaxFile;
59    LPSTR        lpstrFileTitle;
60    DWORD        nMaxFileTitle;
61    LPCSTR       lpstrInitialDir;
62    LPCSTR       lpstrTitle;
63    DWORD        Flags;
64    WORD         nFileOffset;
65    WORD         nFileExtension;
66    LPCSTR       lpstrDefExt;
67    LPARAM       lCustData;
68    LPOFNHOOKPROC lpfnHook;
69    LPCSTR       lpTemplateName;
70 #ifdef _MAC
71    LPEDITMENU   lpEditInfo;
72    LPCSTR       lpstrPrompt;
73 #endif
74 #if (_WIN32_WINNT >= 0x0500)
75    void *		pvReserved;
76    DWORD        dwReserved;
77    DWORD        FlagsEx;
78 #endif // (_WIN32_WINNT >= 0x0500)
79 } _OPENFILENAMEA, *_LPOPENFILENAMEA;
80 
81 typedef struct _tagOFNW {
82    DWORD        lStructSize;
83    HWND         hwndOwner;
84    HINSTANCE    hInstance;
85    LPCWSTR      lpstrFilter;
86    LPWSTR       lpstrCustomFilter;
87    DWORD        nMaxCustFilter;
88    DWORD        nFilterIndex;
89    LPWSTR       lpstrFile;
90    DWORD        nMaxFile;
91    LPWSTR       lpstrFileTitle;
92    DWORD        nMaxFileTitle;
93    LPCWSTR      lpstrInitialDir;
94    LPCWSTR      lpstrTitle;
95    DWORD        Flags;
96    WORD         nFileOffset;
97    WORD         nFileExtension;
98    LPCWSTR      lpstrDefExt;
99    LPARAM       lCustData;
100    LPOFNHOOKPROC lpfnHook;
101    LPCWSTR      lpTemplateName;
102 #if (_WIN32_WINNT >= 0x0500)
103    void *       pvReserved;
104    DWORD        dwReserved;
105    DWORD        FlagsEx;
106 #endif // (_WIN32_WINNT >= 0x0500)
107 } _OPENFILENAMEW, *_LPOPENFILENAMEW;
108 
109 #ifdef UNICODE
110 typedef _OPENFILENAMEW _OPENFILENAME;
111 typedef _LPOPENFILENAMEW _LPOPENFILENAME;
112 #else
113 typedef _OPENFILENAMEA _OPENFILENAME;
114 typedef _LPOPENFILENAMEA _LPOPENFILENAME;
115 #endif // UNICODE
116 
117 #if (_WIN32_WINNT >= 0x0500)
118     #define _OPENFILENAME_SIZE_VERSION_400A  _CDSIZEOF_STRUCT(_OPENFILENAMEA,lpTemplateName)
119     #define _OPENFILENAME_SIZE_VERSION_400W  _CDSIZEOF_STRUCT(_OPENFILENAMEW,lpTemplateName)
120     #ifdef UNICODE
121         #define _OPENFILENAME_SIZE_VERSION_400  _OPENFILENAME_SIZE_VERSION_400W
122     #else
123         #define _OPENFILENAME_SIZE_VERSION_400  _OPENFILENAME_SIZE_VERSION_400A
124     #endif // !UNICODE
125 #else
126     #error _WIN32_WINNT seems not to be valid.
127 #endif // (_WIN32_WINNT >= 0x0500)
128 
129 
130 //-------------------------------------------------------------
131 // A simple wrapper class around the Win32 GetOpenFileName API.
132 // This class is not thread-safe and only one instance at a
133 // time is allowed
134 //-------------------------------------------------------------
135 
136 class CFileOpenDialog
137 {
138 public:
139 	// ctor
140 	// bFileOpenDialog idicates if we want a FileOpen or FileSave
141 	// dialog
142 	// dwFlags see OPENFILENAME
143 	// dwTemplateId - an ID for custom templates
144 	// hInstance    - an instance handle for the module
145 	// which provides the custom template, unused if dwTemplateId
146 	// is 0
147 	CFileOpenDialog(
148 		bool bFileOpenDialog = sal_True,
149 		sal_uInt32 dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
150 		sal_uInt32 dwTemplateId = 0,
151 		HINSTANCE hInstance = 0);
152 
153 	virtual ~CFileOpenDialog();
154 
155 	virtual void SAL_CALL setTitle(const rtl::OUString& aTitle);
156 
157 	// to set a filter string using the M$ format
158 	// e.g. FltName\0*.txt;*.rtf\0...\0\0
159 	void SAL_CALL setFilter(const rtl::OUString& aFilter);
160 
161 	// set the index of the current filter when the
162 	// dialog is about to shown, the index starts with 1
163 	// the function succeeded if the given filter index
164 	// is greater than zero and is a valid position
165 	// within filter string that was previously set
166 	bool SAL_CALL setFilterIndex(sal_uInt32 aIndex);
167 
168 	// get the index of the currently selected filter
169 	// the index of the returned filter starts with 1
170 	sal_uInt32 SAL_CALL getSelectedFilterIndex() const;
171 
172 	// set the name and optional the path of the
173 	// file that will be initially be shown when
174 	// the dialog will be displayed
175 	virtual void SAL_CALL setDefaultName(const rtl::OUString& aName);
176 
177 	// set the initial directory
178 	virtual void SAL_CALL setDisplayDirectory(const rtl::OUString& aDirectory);
179 
180 	// returns only the path of the selected file
181 	virtual rtl::OUString SAL_CALL getLastDisplayDirectory() const;
182 
183 	// returns the full file name including drive letter, path
184 	// file name and file extension
185 	virtual rtl::OUString SAL_CALL getFullFileName() const;
186 
187 	// returns the file name and the file extension without
188 	// drive letter and path
189 	rtl::OUString SAL_CALL getFileName() const;
190 
191 	// returns the file extension of the selected file
192 	rtl::OUString SAL_CALL getFileExtension();
193 
194 	// set a default extension, only the first three letters of
195 	// the given extension will be used; the given extension
196 	// should not contain a '.'
197 	void SAL_CALL setDefaultFileExtension(const rtl::OUString& aExtension);
198 
199 	// enables or disables the multiselection mode for
200 	// the FileOpen/FileSave dialog
201 	void SAL_CALL setMultiSelectionMode(bool bMode);
202 
203 	// returns whether multi-selection mode is enabled or not
204 	bool SAL_CALL getMultiSelectionMode() const;
205 
206 	// shows the dialog, calls preModal before
207 	// showing the dialog and postModal after
208 	// showing the dialog
209 	// the method returns:
210 	//  0 - when the dialog was canceled by the user
211 	//  1 - when the dialog was closed with ok
212 	// -1 - when an error occurred
213 	sal_Int16 SAL_CALL doModal();
214 
215 	// returns the last dialog error that occurred
216 	sal_uInt32 SAL_CALL getLastDialogError() const;
217 
218 	// retrieves the currently selected file
219 	// including path and drive information
220 	// can be called only if the dialog is
221 	// already displayed
222 	rtl::OUString SAL_CALL getCurrentFilePath() const;
223 
224 	// retrieves the currently selected folder
225 	rtl::OUString SAL_CALL getCurrentFolderPath() const;
226 
227 	// retrieves the currently selected file name
228 	// without drive and path
229 	rtl::OUString SAL_CALL getCurrentFileName() const;
230 
231 protected:
232 	// have to be overwritten when subclasses
233 	// want to do special pre- and post-modal
234 	// processing
235 
236 	// if preModal return true processing will
237 	// continue else doModal exit without showing
238 	// a dialog and returns -1
239 	virtual bool SAL_CALL preModal();
240 
241 	// post modal processing
242 	// the function should accept only values returned from
243 	// doModal and act appropriately
244 	virtual void SAL_CALL postModal(sal_Int16 nDialogResult);
245 
246 	// message handler, to be overwritten by subclasses
247 	virtual sal_uInt32 SAL_CALL onShareViolation(const rtl::OUString& aPathName);
248 	virtual sal_uInt32 SAL_CALL onFileOk();
249 	virtual void SAL_CALL onSelChanged(HWND hwndListBox);
250 	virtual void SAL_CALL onHelp();
251 
252 	// only called back if OFN_EXPLORER is set
253 	virtual void SAL_CALL onInitDone();
254 	virtual void SAL_CALL onFolderChanged();
255 	virtual void SAL_CALL onTypeChanged(sal_uInt32 nFilterIndex);
256 
257 	virtual void SAL_CALL onInitDialog(HWND hwndDlg) = 0;
258 
259 	virtual sal_uInt32 SAL_CALL onCtrlCommand(HWND hwndDlg, sal_uInt16 ctrlId, sal_uInt16 notifyCode);
260 
261 	sal_uInt32 SAL_CALL onWMNotify(HWND hwndChild, LPOFNOTIFYW lpOfNotify);
262 
263 	// we use non-virtual functions to do necessary work before
264 	// calling the virtual functions (see Gamma: Template method)
265 	void SAL_CALL handleInitDialog(HWND hwndDlg, HWND hwndChild);
266 
267 protected:
268 
269 	// handle to the window of the
270 	// FileOpen/FileSave dialog
271 	// will be set on message
272 	// WM_INITDIALOG, before this
273 	// value is undefined
274 	HWND	m_hwndFileOpenDlg;
275 	HWND	m_hwndFileOpenDlgChild;
276 
277 	_OPENFILENAME	m_ofn;
278 
279     // we connect the instance with the dialog window using
280     // SetProp, with this function we can reconnect from
281     // callback functions to this instance
282     static CFileOpenDialog* SAL_CALL getCurrentInstance(HWND hwnd);
283 
284     void SAL_CALL centerPositionToParent() const;
285 
286 private:
287 	// FileOpen or FileSaveDialog
288 	bool			m_bFileOpenDialog;
289 	rtl::OUString	m_dialogTitle;
290 	rtl::OUString	m_displayDirectory;
291 	rtl::OUString	m_defaultExtension;
292 
293 	mutable	rtl::OUStringBuffer m_filterBuffer;
294 	mutable	rtl::OUStringBuffer m_fileTitleBuffer;
295 	mutable rtl::OUStringBuffer	m_helperBuffer;
296 	mutable rtl::OUStringBuffer m_fileNameBuffer;
297 
298     CGetFileNameWrapper m_GetFileNameWrapper;
299 
300     WNDPROC	    		m_pfnBaseDlgProc;
301 
302 	// callback function
303 	static unsigned int CALLBACK ofnHookProc(
304 		HWND hChildDlg, // handle to child dialog box
305 		unsigned int uiMsg,     // message identifier
306 		WPARAM wParam,  // message parameter
307 		LPARAM lParam   // message parameter
308 	);
309 
310     // we have to subclass the dialog in order
311     // to clean up the window property we are
312     // using to connect the window with a class
313     // instance in WM_NCDESTROY
314     static LRESULT CALLBACK BaseDlgProc(
315         HWND hWnd, UINT wMessage, WPARAM wParam, LPARAM lParam );
316 
317 private:
318 	// avoid copy and assignment
319 	CFileOpenDialog(const CFileOpenDialog&);
320 	CFileOpenDialog& operator=(const CFileOpenDialog&);
321 };
322 
323 #endif
324