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