ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

win32-dialogs.cpp

Go to the documentation of this file.
00001 /* ScummVM - Graphic Adventure Engine
00002  *
00003  * ScummVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023  // We cannot use common/scummsys.h directly as it will include
00024  // windows.h and we need to do it by hand to allow excluded functions
00025 #if defined(HAVE_CONFIG_H)
00026 #include "config.h"
00027 #endif
00028 
00029 #if defined(WIN32) && defined(USE_SYSDIALOGS)
00030 
00031 // HACK: To get __MINGW64_VERSION_foo defines we need to manually include
00032 // _mingw.h in this file because we do not include any system headers at this
00033 // point on purpose. The defines are required to detect whether this is a
00034 // classic MinGW toolchain or a MinGW-w64 based one.
00035 #if defined(__MINGW32__)
00036 #include <_mingw.h>
00037 #endif
00038 
00039 // Needed for dialog functions
00040 // HACK: MinGW-w64 based toolchains include the symbols we require in their
00041 // headers. The 32 bit incarnation only defines __MINGW32__. This leads to
00042 // build breakage due to clashes with our compat header. Luckily MinGW-w64
00043 // based toolchains define __MINGW64_VERSION_foo macros inside _mingw.h,
00044 // which is included from all system headers. Thus we abuse that to detect
00045 // them.
00046 #if defined(__GNUC__) && defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
00047 #include "backends/dialogs/win32/mingw-compat.h"
00048 #else
00049     // We use functionality introduced with Vista in this file.
00050     // To assure that including the respective system headers gives us all
00051     // required definitions we set Vista as minimum version we target.
00052     // See: https://msdn.microsoft.com/en-us/library/windows/desktop/aa383745%28v=vs.85%29.aspx#macros_for_conditional_declarations
00053 #include <sdkddkver.h>
00054 #undef _WIN32_WINNT
00055 #define _WIN32_WINNT _WIN32_WINNT_VISTA
00056 
00057 #define WIN32_LEAN_AND_MEAN
00058 #include <windows.h>
00059 #endif
00060 
00061 #include <shlobj.h>
00062 
00063 #include "common/scummsys.h"
00064 
00065 #include "backends/dialogs/win32/win32-dialogs.h"
00066 #include "backends/platform/sdl/win32/win32_wrapper.h"
00067 #include "backends/platform/sdl/win32/win32-window.h"
00068 
00069 #include "common/config-manager.h"
00070 #include "common/translation.h"
00071 
00072 Win32DialogManager::Win32DialogManager(SdlWindow_Win32 *window) : _window(window) {
00073     CoInitialize(NULL);
00074 }
00075 
00076 Win32DialogManager::~Win32DialogManager() {
00077     CoUninitialize();
00078 }
00079 
00080 // Wrapper for old Windows versions
00081 HRESULT winCreateItemFromParsingName(PCWSTR pszPath, IBindCtx *pbc, REFIID riid, void **ppv) {
00082     typedef HRESULT(WINAPI *SHFunc)(PCWSTR, IBindCtx *, REFIID, void **);
00083 
00084     SHFunc func = (SHFunc)GetProcAddress(GetModuleHandle(TEXT("shell32.dll")), "SHCreateItemFromParsingName");
00085     if (func == NULL)
00086         return E_NOTIMPL;
00087 
00088     return func(pszPath, pbc, riid, ppv);
00089 }
00090 
00091 HRESULT getShellPath(IShellItem *item, Common::String &path) {
00092     LPWSTR name = NULL;
00093     HRESULT hr = item->GetDisplayName(SIGDN_FILESYSPATH, &name);
00094     if (SUCCEEDED(hr)) {
00095         char *str = Win32::unicodeToAnsi(name);
00096         path = Common::String(str);
00097         CoTaskMemFree(name);
00098         delete[] str;
00099     }
00100     return hr;
00101 }
00102 
00103 Common::DialogManager::DialogResult Win32DialogManager::showFileBrowser(const char *title, Common::FSNode &choice, bool isDirBrowser) {
00104     DialogResult result = kDialogError;
00105 
00106     // Do nothing if not running on Windows Vista or later
00107     if (!Win32::confirmWindowsVersion(6, 0))
00108         return result;
00109 
00110     IFileOpenDialog *dialog = NULL;
00111     HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog,
00112         NULL,
00113         CLSCTX_INPROC_SERVER,
00114         IID_IFileOpenDialog,
00115         reinterpret_cast<void **> (&(dialog)));
00116 
00117     if (SUCCEEDED(hr)) {
00118         beginDialog();
00119 
00120         // Customize dialog
00121         bool showHidden = ConfMan.getBool("gui_browser_show_hidden", Common::ConfigManager::kApplicationDomain);
00122 
00123         DWORD dwOptions;
00124         hr = dialog->GetOptions(&dwOptions);
00125         if (SUCCEEDED(hr)) {
00126             if (isDirBrowser)
00127                 dwOptions |= FOS_PICKFOLDERS;
00128             if (showHidden)
00129                 dwOptions |= FOS_FORCESHOWHIDDEN;
00130             hr = dialog->SetOptions(dwOptions);
00131         }
00132 
00133         LPWSTR str = Win32::ansiToUnicode(title, Win32::getCurrentCharset());
00134         hr = dialog->SetTitle(str);
00135         delete[] str;
00136 
00137         str = Win32::ansiToUnicode(_("Choose"), Win32::getCurrentCharset());
00138         hr = dialog->SetOkButtonLabel(str);
00139         delete[] str;
00140 
00141         if (ConfMan.hasKey("browser_lastpath")) {
00142             str = Win32::ansiToUnicode(ConfMan.get("browser_lastpath").c_str());
00143             IShellItem *item = NULL;
00144             hr = winCreateItemFromParsingName(str, NULL, IID_IShellItem, reinterpret_cast<void **> (&(item)));
00145             if (SUCCEEDED(hr)) {
00146                 hr = dialog->SetDefaultFolder(item);
00147             }
00148             delete[] str;
00149         }
00150 
00151         // Show dialog
00152         hr = dialog->Show(_window->getHwnd());
00153 
00154         if (SUCCEEDED(hr)) {
00155             // Get the selection from the user
00156             IShellItem *selectedItem = NULL;
00157             hr = dialog->GetResult(&selectedItem);
00158             if (SUCCEEDED(hr)) {
00159                 Common::String path;
00160                 hr = getShellPath(selectedItem, path);
00161                 if (SUCCEEDED(hr)) {
00162                     choice = Common::FSNode(path);
00163                     result = kDialogOk;
00164                 }
00165                 selectedItem->Release();
00166             }
00167 
00168             // Save last path
00169             IShellItem *lastFolder = NULL;
00170             hr = dialog->GetFolder(&lastFolder);
00171             if (SUCCEEDED(hr)) {
00172                 Common::String path;
00173                 hr = getShellPath(lastFolder, path);
00174                 if (SUCCEEDED(hr)) {
00175                     ConfMan.set("browser_lastpath", path);
00176                 }
00177                 lastFolder->Release();
00178             }
00179         }
00180         else if (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED)) {
00181             result = kDialogCancel;
00182         }
00183 
00184         dialog->Release();
00185 
00186         endDialog();
00187     }
00188 
00189     return result;
00190 }
00191 
00192 #endif


Generated on Sat Jun 27 2020 05:00:30 for ResidualVM by doxygen 1.7.1
curved edge   curved edge