1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-16 00:34:19 +00:00
JUCE/src/native/windows/juce_win32_FileChooser.cpp

338 lines
11 KiB
C++

/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-9 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
// (This file gets included by juce_win32_NativeCode.cpp, rather than being
// compiled on its own).
#if JUCE_INCLUDED_FILE
//==============================================================================
static const void* defaultDirPath = 0;
static String returnedString; // need this to get non-existent pathnames from the directory chooser
static Component* currentExtraFileWin = 0;
static bool areThereAnyAlwaysOnTopWindows()
{
for (int i = Desktop::getInstance().getNumComponents(); --i >= 0;)
{
Component* c = Desktop::getInstance().getComponent (i);
if (c != 0 && c->isAlwaysOnTop() && c->isShowing())
return true;
}
return false;
}
static int CALLBACK browseCallbackProc (HWND hWnd, UINT msg, LPARAM lParam, LPARAM /*lpData*/)
{
if (msg == BFFM_INITIALIZED)
{
SendMessage (hWnd, BFFM_SETSELECTIONW, TRUE, (LPARAM) defaultDirPath);
}
else if (msg == BFFM_VALIDATEFAILEDW)
{
returnedString = (LPCWSTR) lParam;
}
else if (msg == BFFM_VALIDATEFAILEDA)
{
returnedString = (const char*) lParam;
}
return 0;
}
void juce_setWindowStyleBit (HWND h, const int styleType, const int feature, const bool bitIsSet) throw();
static UINT_PTR CALLBACK openCallback (HWND hdlg, UINT uiMsg, WPARAM /*wParam*/, LPARAM lParam)
{
if (currentExtraFileWin != 0)
{
if (uiMsg == WM_INITDIALOG)
{
HWND dialogH = GetParent (hdlg);
jassert (dialogH != 0);
if (dialogH == 0)
dialogH = hdlg;
RECT r, cr;
GetWindowRect (dialogH, &r);
GetClientRect (dialogH, &cr);
SetWindowPos (dialogH, 0,
r.left, r.top,
currentExtraFileWin->getWidth() + jmax (150, r.right - r.left),
jmax (150, r.bottom - r.top),
SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER);
currentExtraFileWin->setBounds (cr.right, cr.top, currentExtraFileWin->getWidth(), cr.bottom - cr.top);
currentExtraFileWin->getChildComponent(0)->setBounds (0, 0, currentExtraFileWin->getWidth(), currentExtraFileWin->getHeight());
SetParent ((HWND) currentExtraFileWin->getWindowHandle(), (HWND) dialogH);
juce_setWindowStyleBit ((HWND)currentExtraFileWin->getWindowHandle(), GWL_STYLE, WS_CHILD, (dialogH != 0));
juce_setWindowStyleBit ((HWND)currentExtraFileWin->getWindowHandle(), GWL_STYLE, WS_POPUP, (dialogH == 0));
}
else if (uiMsg == WM_NOTIFY)
{
LPOFNOTIFY ofn = (LPOFNOTIFY) lParam;
if (ofn->hdr.code == CDN_SELCHANGE)
{
FilePreviewComponent* comp = (FilePreviewComponent*) currentExtraFileWin->getChildComponent(0);
if (comp != 0)
{
TCHAR path [MAX_PATH * 2];
path[0] = 0;
CommDlg_OpenSave_GetFilePath (GetParent (hdlg), (LPARAM) &path, MAX_PATH);
const String fn ((const WCHAR*) path);
comp->selectedFileChanged (File (fn));
}
}
}
}
return 0;
}
class FPComponentHolder : public Component
{
public:
FPComponentHolder()
{
setVisible (true);
setOpaque (true);
}
~FPComponentHolder()
{
}
void paint (Graphics& g)
{
g.fillAll (Colours::lightgrey);
}
private:
FPComponentHolder (const FPComponentHolder&);
const FPComponentHolder& operator= (const FPComponentHolder&);
};
//==============================================================================
void FileChooser::showPlatformDialog (OwnedArray<File>& results,
const String& title,
const File& currentFileOrDirectory,
const String& filter,
bool selectsDirectory,
bool selectsFiles,
bool isSaveDialogue,
bool warnAboutOverwritingExistingFiles,
bool selectMultipleFiles,
FilePreviewComponent* extraInfoComponent)
{
const int numCharsAvailable = 32768;
MemoryBlock filenameSpace ((numCharsAvailable + 1) * sizeof (WCHAR), true);
WCHAR* const fname = (WCHAR*) filenameSpace.getData();
int fnameIdx = 0;
JUCE_TRY
{
// use a modal window as the parent for this dialog box
// to block input from other app windows
const Rectangle mainMon (Desktop::getInstance().getMainMonitorArea());
Component w (String::empty);
w.setBounds (mainMon.getX() + mainMon.getWidth() / 4,
mainMon.getY() + mainMon.getHeight() / 4,
0, 0);
w.setOpaque (true);
w.setAlwaysOnTop (areThereAnyAlwaysOnTopWindows());
w.addToDesktop (0);
if (extraInfoComponent == 0)
w.enterModalState();
String initialDir;
if (currentFileOrDirectory.isDirectory())
{
initialDir = currentFileOrDirectory.getFullPathName();
}
else
{
currentFileOrDirectory.getFileName().copyToBuffer (fname, numCharsAvailable);
initialDir = currentFileOrDirectory.getParentDirectory().getFullPathName();
}
if (currentExtraFileWin->isValidComponent())
{
jassertfalse
return;
}
if (selectsDirectory)
{
LPITEMIDLIST list = 0;
filenameSpace.fillWith (0);
{
BROWSEINFO bi;
zerostruct (bi);
bi.hwndOwner = (HWND) w.getWindowHandle();
bi.pszDisplayName = fname;
bi.lpszTitle = title;
bi.lpfn = browseCallbackProc;
#ifdef BIF_USENEWUI
bi.ulFlags = BIF_USENEWUI | BIF_VALIDATE;
#else
bi.ulFlags = 0x50;
#endif
defaultDirPath = (const WCHAR*) initialDir;
list = SHBrowseForFolder (&bi);
if (! SHGetPathFromIDListW (list, fname))
{
fname[0] = 0;
returnedString = String::empty;
}
}
LPMALLOC al;
if (list != 0 && SUCCEEDED (SHGetMalloc (&al)))
al->Free (list);
defaultDirPath = 0;
if (returnedString.isNotEmpty())
{
const String stringFName (fname);
results.add (new File (File (stringFName).getSiblingFile (returnedString)));
returnedString = String::empty;
return;
}
}
else
{
DWORD flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_NOCHANGEDIR | OFN_HIDEREADONLY;
if (warnAboutOverwritingExistingFiles)
flags |= OFN_OVERWRITEPROMPT;
if (selectMultipleFiles)
flags |= OFN_ALLOWMULTISELECT;
if (extraInfoComponent != 0)
{
flags |= OFN_ENABLEHOOK;
currentExtraFileWin = new FPComponentHolder();
currentExtraFileWin->addAndMakeVisible (extraInfoComponent);
currentExtraFileWin->setSize (jlimit (20, 800, extraInfoComponent->getWidth()),
extraInfoComponent->getHeight());
currentExtraFileWin->addToDesktop (0);
currentExtraFileWin->enterModalState();
}
{
WCHAR filters [1024];
zeromem (filters, sizeof (filters));
filter.copyToBuffer (filters, 1024);
filter.copyToBuffer (filters + filter.length() + 1,
1022 - filter.length());
OPENFILENAMEW of;
zerostruct (of);
#ifdef OPENFILENAME_SIZE_VERSION_400W
of.lStructSize = OPENFILENAME_SIZE_VERSION_400W;
#else
of.lStructSize = sizeof (of);
#endif
of.hwndOwner = (HWND) w.getWindowHandle();
of.lpstrFilter = filters;
of.nFilterIndex = 1;
of.lpstrFile = fname;
of.nMaxFile = numCharsAvailable;
of.lpstrInitialDir = initialDir;
of.lpstrTitle = title;
of.Flags = flags;
if (extraInfoComponent != 0)
of.lpfnHook = &openCallback;
if (isSaveDialogue)
{
if (! GetSaveFileName (&of))
fname[0] = 0;
else
fnameIdx = of.nFileOffset;
}
else
{
if (! GetOpenFileName (&of))
fname[0] = 0;
else
fnameIdx = of.nFileOffset;
}
}
}
}
#if JUCE_CATCH_UNHANDLED_EXCEPTIONS
catch (...)
{
fname[0] = 0;
}
#endif
deleteAndZero (currentExtraFileWin);
const WCHAR* const files = fname;
if (selectMultipleFiles && fnameIdx > 0 && files [fnameIdx - 1] == 0)
{
const WCHAR* filename = files + fnameIdx;
while (*filename != 0)
{
const String filepath (String (files) + T("\\") + String (filename));
results.add (new File (filepath));
filename += CharacterFunctions::length (filename) + 1;
}
}
else if (files[0] != 0)
{
results.add (new File (files));
}
}
#endif