FlightGear next
WindowsFileDialog.cxx
Go to the documentation of this file.
1
2
4
5#include <windows.h>
6#include <Shlobj.h>
7
8#include <osgViewer/Viewer>
9#include <osgViewer/api/Win32/GraphicsWindowWin32>
10
11#include <simgear/debug/logstream.hxx>
12#include <simgear/misc/strutils.hxx>
13
14#include <Main/globals.hxx>
15#include <Main/fg_props.hxx>
16#include <Viewer/renderer.hxx>
17
18namespace {
19
21{
22 osgViewer::Viewer::Windows windows;
23 if (!globals->get_renderer() || !globals->get_renderer()->getViewerBase()) {
24 return 0;
25 }
26
27 globals->get_renderer()->getViewerBase()->getWindows(windows);
28 osgViewer::Viewer::Windows::const_iterator it = windows.begin();
29 for(; it != windows.end(); ++it) {
30 if (strcmp((*it)->className(), "GraphicsWindowWin32")) {
31 continue;
32 }
33
34 osgViewer::GraphicsWindowWin32* platformWin =
35 static_cast<osgViewer::GraphicsWindowWin32*>(*it);
36 return platformWin->getHWND();
37 }
38
39 return 0;
40}
41
42static int CALLBACK BrowseFolderCallback(
43 HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
44{
45 if (uMsg == BFFM_INITIALIZED) {
46 // set the initial directory now
47 WindowsFileDialog* dlg = reinterpret_cast<WindowsFileDialog*>(lpData);
48 const auto w = dlg->getDirectory().wstr();
49 ::SendMessageW(hwnd, BFFM_SETSELECTIONW, true, (LPARAM) w.c_str());
50 }
51 return 0;
52}
53
54} // of anonymous namespace
55
61
66
68{
69 char Filestring[MAX_PATH] = "\0";
70 OPENFILENAMEA opf = {0};
71 opf.lStructSize = sizeof(OPENFILENAME);
72 opf.lpstrFile = Filestring;
73 opf.lpstrTitle = const_cast<char *>(_title.c_str());
74 opf.nMaxFile = MAX_PATH;
75
76 std::string extensions;
77 size_t extensionsLen=0;
78 if (!_filterPatterns.empty()) {
79 for (const auto& ext : _filterPatterns) {
80 if (!simgear::strutils::starts_with(ext, "*.")) {
81 SG_LOG(SG_GENERAL, SG_ALERT, "WindowsFileDialog: can't use pattern on Windows:" << ext);
82 continue;
83 }
84 extensions += "("+ext+")\0"+ext+"\0";
85 extensionsLen += ext.size()*2+4;
86 }
87 opf.lpstrFilter = (LPCSTR) malloc(extensionsLen);
88 memcpy((void*)opf.lpstrFilter, (void*)extensions.data(), extensionsLen);
89 }
90
91 std::string s = _initialPath.local8BitStr();
92 opf.lpstrInitialDir = const_cast<char *>(s.c_str());
93
94 if (_showHidden) {
95 opf.Flags = OFN_PATHMUSTEXIST;
96 }
97
98 if (_usage == USE_SAVE_FILE) {
99 if (GetSaveFileNameA(&opf)) {
100 std::string stringPath(opf.lpstrFile);
101 _callback->onFileDialogDone(this, stringPath);
102 }
103 } else if (_usage == USE_CHOOSE_DIR) {
104 chooseDir();
105 } else {
106 if (GetOpenFileNameA(&opf)) {
107 std::string stringPath(opf.lpstrFile);
108 _callback->onFileDialogDone(this, stringPath);
109 }
110 }
111}
112
114{
115
116}
117
118void WindowsFileDialog::chooseDir()
119{
120 // MSDN says this needs to be called first
121 OleInitialize(NULL);
122
123 char pathBuf[MAX_PATH] = "\0";
124
125 BROWSEINFOA binfo;
126 memset(&binfo, 0, sizeof(BROWSEINFOA));
127 binfo.hwndOwner = getMainViewerHWND();
128 binfo.ulFlags = BIF_USENEWUI | BIF_RETURNONLYFSDIRS | BIF_EDITBOX;
129
130 binfo.pidlRoot = NULL; // can browse anywhere
131 binfo.lpszTitle = const_cast<char *>(_title.c_str());
132 binfo.lpfn = BrowseFolderCallback;
133 binfo.lParam = reinterpret_cast<LPARAM>(this);
134
135 PIDLIST_ABSOLUTE results = SHBrowseForFolderA(&binfo);
136 if (results == NULL) {
137 // user cancelled
138 return;
139 }
140
141 SHGetPathFromIDListA(results, pathBuf);
142 CoTaskMemFree(results);
143
144 _callback->onFileDialogDone(this, SGPath(pathBuf));
145}
static HWND getMainViewerHWND()
SGPath _initialPath
string_list _filterPatterns
FGFileDialog(Usage use)
const Usage _usage
SGPath getDirectory() const
std::unique_ptr< Callback > _callback
std::string _title
WindowsFileDialog(FGFileDialog::Usage use)
FGGlobals * globals
Definition globals.cxx:142