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/system.h"
00071 #include "common/events.h"
00072 #include "common/translation.h"
00073 
00074 Win32DialogManager::Win32DialogManager(SdlWindow_Win32 *window) : _window(window) {
00075     CoInitialize(NULL);
00076 }
00077 
00078 Win32DialogManager::~Win32DialogManager() {
00079     CoUninitialize();
00080 }
00081 
00082 // Wrapper for old Windows versions
00083 HRESULT winCreateItemFromParsingName(PCWSTR pszPath, IBindCtx *pbc, REFIID riid, void **ppv) {
00084     typedef HRESULT(WINAPI *SHFunc)(PCWSTR, IBindCtx *, REFIID, void **);
00085 
00086     SHFunc func = (SHFunc)GetProcAddress(GetModuleHandle(TEXT("shell32.dll")), "SHCreateItemFromParsingName");
00087     if (func == NULL)
00088         return E_NOTIMPL;
00089 
00090     return func(pszPath, pbc, riid, ppv);
00091 }
00092 
00093 HRESULT getShellPath(IShellItem *item, Common::String &path) {
00094     LPWSTR name = NULL;
00095     HRESULT hr = item->GetDisplayName(SIGDN_FILESYSPATH, &name);
00096     if (SUCCEEDED(hr)) {
00097         char *str = Win32::unicodeToAnsi(name);
00098         path = Common::String(str);
00099         CoTaskMemFree(name);
00100         delete[] str;
00101     }
00102     return hr;
00103 }
00104 
00105 Common::DialogManager::DialogResult Win32DialogManager::showFileBrowser(const char *title, Common::FSNode &choice, bool isDirBrowser) {
00106     DialogResult result = kDialogError;
00107 
00108     // Do nothing if not running on Windows Vista or later
00109     if (!Win32::confirmWindowsVersion(6, 0))
00110         return result;
00111 
00112     IFileOpenDialog *dialog = NULL;
00113     HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog,
00114         NULL,
00115         CLSCTX_INPROC_SERVER,
00116         IID_IFileOpenDialog,
00117         reinterpret_cast<void **> (&(dialog)));
00118 
00119     if (SUCCEEDED(hr)) {
00120         // If in fullscreen mode, switch to windowed mode
00121         bool wasFullscreen = g_system->getFeatureState(OSystem::kFeatureFullscreenMode);
00122         if (wasFullscreen) {
00123             g_system->beginGFXTransaction();
00124             g_system->setFeatureState(OSystem::kFeatureFullscreenMode, false);
00125             g_system->endGFXTransaction();
00126         }
00127 
00128         // Customize dialog
00129         bool showHidden = ConfMan.getBool("gui_browser_show_hidden", Common::ConfigManager::kApplicationDomain);
00130 
00131         DWORD dwOptions;
00132         hr = dialog->GetOptions(&dwOptions);
00133         if (SUCCEEDED(hr)) {
00134             if (isDirBrowser)
00135                 dwOptions |= FOS_PICKFOLDERS;
00136             if (showHidden)
00137                 dwOptions |= FOS_FORCESHOWHIDDEN;
00138             hr = dialog->SetOptions(dwOptions);
00139         }
00140 
00141         LPWSTR str = Win32::ansiToUnicode(title);
00142         hr = dialog->SetTitle(str);
00143         delete[] str;
00144 
00145         str = Win32::ansiToUnicode(_("Choose"));
00146         hr = dialog->SetOkButtonLabel(str);
00147         delete[] str;
00148 
00149         if (ConfMan.hasKey("browser_lastpath")) {
00150             str = Win32::ansiToUnicode(ConfMan.get("browser_lastpath").c_str());
00151             IShellItem *item = NULL;
00152             hr = winCreateItemFromParsingName(str, NULL, IID_IShellItem, reinterpret_cast<void **> (&(item)));
00153             if (SUCCEEDED(hr)) {
00154                 hr = dialog->SetDefaultFolder(item);
00155             }
00156             delete[] str;
00157         }
00158 
00159         // Show dialog
00160         hr = dialog->Show(_window->getHwnd());
00161 
00162         if (SUCCEEDED(hr)) {
00163             // Get the selection from the user
00164             IShellItem *selectedItem = NULL;
00165             hr = dialog->GetResult(&selectedItem);
00166             if (SUCCEEDED(hr)) {
00167                 Common::String path;
00168                 hr = getShellPath(selectedItem, path);
00169                 if (SUCCEEDED(hr)) {
00170                     choice = Common::FSNode(path);
00171                     result = kDialogOk;
00172                 }
00173                 selectedItem->Release();
00174             }
00175 
00176             // Save last path
00177             IShellItem *lastFolder = NULL;
00178             hr = dialog->GetFolder(&lastFolder);
00179             if (SUCCEEDED(hr)) {
00180                 Common::String path;
00181                 hr = getShellPath(lastFolder, path);
00182                 if (SUCCEEDED(hr)) {
00183                     ConfMan.set("browser_lastpath", path);
00184                 }
00185                 lastFolder->Release();
00186             }
00187         }
00188         else if (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED)) {
00189             result = kDialogCancel;
00190         }
00191 
00192         dialog->Release();
00193 
00194         // If we were in fullscreen mode, switch back
00195         if (wasFullscreen) {
00196             g_system->beginGFXTransaction();
00197             g_system->setFeatureState(OSystem::kFeatureFullscreenMode, true);
00198             g_system->endGFXTransaction();
00199         }
00200     }
00201 
00202     return result;
00203 }
00204 
00205 #endif


Generated on Sat May 18 2019 05:01:29 for ResidualVM by doxygen 1.7.1
curved edge   curved edge