mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-17 07:44:09 +02:00
Add support for Vista File Dialogs
This commit is contained in:
parent
f0cca6dc40
commit
694e663630
6 changed files with 935 additions and 597 deletions
159
BeefLibs/corlib/src/IO/FileDialog.Vista.bf
Normal file
159
BeefLibs/corlib/src/IO/FileDialog.Vista.bf
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
// This file contains portions of code released by Microsoft under the MIT license as part
|
||||||
|
// of an open-sourcing initiative in 2014 of the C# core libraries.
|
||||||
|
// The original source was submitted to https://github.com/Microsoft/referencesource
|
||||||
|
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Collections;
|
||||||
|
|
||||||
|
#if BF_PLATFORM_WINDOWS
|
||||||
|
namespace System.IO
|
||||||
|
{
|
||||||
|
extension FileDialog
|
||||||
|
{
|
||||||
|
protected abstract Result<Windows.COM_IFileDialog*> CreateVistaDialog();
|
||||||
|
|
||||||
|
private Result<DialogResult> TryRunDialogVista(Windows.HWnd hWndOwner)
|
||||||
|
{
|
||||||
|
Windows.COM_IFileDialog* dialog;
|
||||||
|
if (!(CreateVistaDialog() case .Ok(out dialog)))
|
||||||
|
return .Err;
|
||||||
|
|
||||||
|
OnBeforeVistaDialog(dialog);
|
||||||
|
dialog.VT.Show(dialog, hWndOwner);
|
||||||
|
|
||||||
|
List<String> files = scope .();
|
||||||
|
ProcessVistaFiles(dialog, files);
|
||||||
|
|
||||||
|
DeleteContainerAndItems!(mFileNames);
|
||||||
|
mFileNames = new String[files.Count];
|
||||||
|
files.CopyTo(mFileNames);
|
||||||
|
|
||||||
|
dialog.VT.Release(dialog);
|
||||||
|
|
||||||
|
return .Ok(files.IsEmpty ? .Cancel : .OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnBeforeVistaDialog(Windows.COM_IFileDialog* dialog)
|
||||||
|
{
|
||||||
|
dialog.VT.SetDefaultExtension(dialog, DefaultExt.ToScopedNativeWChar!());
|
||||||
|
|
||||||
|
if (mFileNames != null && !mFileNames.IsEmpty)
|
||||||
|
dialog.VT.SetFileName(dialog, mFileNames[0].ToScopedNativeWChar!());
|
||||||
|
|
||||||
|
if (!String.IsNullOrEmpty(mInitialDir))
|
||||||
|
{
|
||||||
|
Windows.COM_IShellItem* folderShellItem = null;
|
||||||
|
Windows.SHCreateItemFromParsingName(mInitialDir.ToScopedNativeWChar!(), null, Windows.COM_IShellItem.sIID, (void**)&folderShellItem);
|
||||||
|
if (folderShellItem != null)
|
||||||
|
{
|
||||||
|
dialog.VT.SetDefaultFolder(dialog, folderShellItem);
|
||||||
|
dialog.VT.SetFolder(dialog, folderShellItem);
|
||||||
|
folderShellItem.VT.Release(folderShellItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog.VT.SetTitle(dialog, mTitle.ToScopedNativeWChar!());
|
||||||
|
dialog.VT.SetOptions(dialog, GetOptions());
|
||||||
|
SetFileTypes(dialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Windows.COM_IFileDialog.FOS GetOptions()
|
||||||
|
{
|
||||||
|
const Windows.COM_IFileDialog.FOS BlittableOptions =
|
||||||
|
Windows.COM_IFileDialog.FOS.OVERWRITEPROMPT
|
||||||
|
| Windows.COM_IFileDialog.FOS.NOCHANGEDIR
|
||||||
|
| Windows.COM_IFileDialog.FOS.NOVALIDATE
|
||||||
|
| Windows.COM_IFileDialog.FOS.ALLOWMULTISELECT
|
||||||
|
| Windows.COM_IFileDialog.FOS.PATHMUSTEXIST
|
||||||
|
| Windows.COM_IFileDialog.FOS.FILEMUSTEXIST
|
||||||
|
| Windows.COM_IFileDialog.FOS.CREATEPROMPT
|
||||||
|
| Windows.COM_IFileDialog.FOS.NODEREFERENCELINKS;
|
||||||
|
|
||||||
|
const int32 UnexpectedOptions =
|
||||||
|
(int32)(Windows.OFN_SHOWHELP // If ShowHelp is true, we don't use the Vista Dialog
|
||||||
|
| Windows.OFN_ENABLEHOOK // These shouldn't be set in options (only set in the flags for the legacy dialog)
|
||||||
|
| Windows.OFN_ENABLESIZING // These shouldn't be set in options (only set in the flags for the legacy dialog)
|
||||||
|
| Windows.OFN_EXPLORER); // These shouldn't be set in options (only set in the flags for the legacy dialog)
|
||||||
|
|
||||||
|
Debug.Assert((UnexpectedOptions & mOptions) == 0, "Unexpected FileDialog options");
|
||||||
|
|
||||||
|
Windows.COM_IFileDialog.FOS ret = (Windows.COM_IFileDialog.FOS)mOptions & BlittableOptions;
|
||||||
|
|
||||||
|
// Force no mini mode for the SaveFileDialog
|
||||||
|
ret |= Windows.COM_IFileDialog.FOS.DEFAULTNOMINIMODE;
|
||||||
|
|
||||||
|
// Make sure that the Open dialog allows the user to specify
|
||||||
|
// non-file system locations. This flag will cause the dialog to copy the resource
|
||||||
|
// to a local cache (Temporary Internet Files), and return that path instead. This
|
||||||
|
// also affects the Save dialog by disallowing navigation to these areas.
|
||||||
|
// An example of a non-file system location is a URL (http://), or a file stored on
|
||||||
|
// a digital camera that is not mapped to a drive letter.
|
||||||
|
// This reproduces the behavior of the "classic" Open and Save dialogs.
|
||||||
|
ret |= Windows.COM_IFileDialog.FOS.FORCEFILESYSTEM;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void ProcessVistaFiles(Windows.COM_IFileDialog* dialog, List<String> files);
|
||||||
|
|
||||||
|
private Result<void> SetFileTypes(Windows.COM_IFileDialog* dialog)
|
||||||
|
{
|
||||||
|
List<Windows.COMDLG_FILTERSPEC> filterItems = scope .();
|
||||||
|
GetFilterItems(filterItems, mFilter);
|
||||||
|
|
||||||
|
if (filterItems.Count == 0)
|
||||||
|
return .Ok;
|
||||||
|
|
||||||
|
defer
|
||||||
|
{
|
||||||
|
for (var filter in filterItems)
|
||||||
|
{
|
||||||
|
delete filter.pszName;
|
||||||
|
delete filter.pszSpec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Windows.COM_IUnknown.HResult hr = dialog.VT.SetFileTypes(dialog, (uint32)filterItems.Count, filterItems.Ptr);
|
||||||
|
if (hr.Failed)
|
||||||
|
return .Err;
|
||||||
|
|
||||||
|
hr = dialog.VT.SetFileTypeIndex(dialog, (uint32)mFilterIndex);
|
||||||
|
if (hr.Failed)
|
||||||
|
return .Err;
|
||||||
|
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GetFilterItems(List<Windows.COMDLG_FILTERSPEC> list, String filter)
|
||||||
|
{
|
||||||
|
mixin ToHeapWChar(var str)
|
||||||
|
{
|
||||||
|
int encodedLen = System.Text.UTF16.GetEncodedLen(str);
|
||||||
|
char16* buf = new char16[encodedLen]* ( ? );
|
||||||
|
System.Text.UTF16.Encode(str, buf, encodedLen);
|
||||||
|
buf
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expected input types
|
||||||
|
// "Text files (*.txt)|*.txt|All files (*.*)|*.*"
|
||||||
|
// "Image Files(*.BMP;*.JPG;*.GIF)|*.BMP;*.JPG;*.GIF|All files (*.*)|*.*"
|
||||||
|
if (!String.IsNullOrEmpty(filter))
|
||||||
|
{
|
||||||
|
StringView[] tokens = filter.Split!('|');
|
||||||
|
if (0 == tokens.Count % 2)
|
||||||
|
{
|
||||||
|
// All even numbered tokens should be labels
|
||||||
|
// Odd numbered tokens are the associated extensions
|
||||||
|
for (int i = 1; i < tokens.Count; i += 2)
|
||||||
|
{
|
||||||
|
Windows.COMDLG_FILTERSPEC ext;
|
||||||
|
ext.pszSpec = ToHeapWChar!(tokens[i]); // This may be a semicolon delimited list of extensions (that's ok)
|
||||||
|
ext.pszName = ToHeapWChar!(tokens[i - 1]);
|
||||||
|
list.Add(ext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
456
BeefLibs/corlib/src/IO/FileDialog.bf
Normal file
456
BeefLibs/corlib/src/IO/FileDialog.bf
Normal file
|
@ -0,0 +1,456 @@
|
||||||
|
// This file contains portions of code released by Microsoft under the MIT license as part
|
||||||
|
// of an open-sourcing initiative in 2014 of the C# core libraries.
|
||||||
|
// The original source was submitted to https://github.com/Microsoft/referencesource
|
||||||
|
|
||||||
|
using System.Text;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
#if BF_PLATFORM_WINDOWS
|
||||||
|
namespace System.IO
|
||||||
|
{
|
||||||
|
enum DialogResult
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
OK = 1,
|
||||||
|
Cancel = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class CommonDialog
|
||||||
|
{
|
||||||
|
public Windows.HWnd mHWnd;
|
||||||
|
public Windows.HWnd mDefaultControlHwnd;
|
||||||
|
public int mDefWndProc;
|
||||||
|
|
||||||
|
private const int32 CDM_SETDEFAULTFOCUS = Windows.WM_USER + 0x51;
|
||||||
|
|
||||||
|
public static Dictionary<int, CommonDialog> sHookMap = new Dictionary<int, CommonDialog>() ~
|
||||||
|
{
|
||||||
|
Debug.Assert(sHookMap.Count == 0);
|
||||||
|
delete _;
|
||||||
|
};
|
||||||
|
public static Monitor sMonitor = new Monitor() ~ delete _;
|
||||||
|
|
||||||
|
public Result<DialogResult> ShowDialog(INativeWindow owner = null)
|
||||||
|
{
|
||||||
|
Windows.HWnd hwndOwner = 0;
|
||||||
|
if (owner != null)
|
||||||
|
hwndOwner = (.)owner.Handle;
|
||||||
|
//Native.WndProc wndProc = scope => OwnerWndProc;
|
||||||
|
|
||||||
|
//mDefWndProc = Native.SetWindowLong(mHWnd, Native.GWL_WNDPROC, (intptr)wndProc.GetFuncPtr().Value);
|
||||||
|
|
||||||
|
var result = RunDialog(hwndOwner);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual int OwnerWndProc(Windows.HWnd hWnd, int32 msg, int wParam, int lParam)
|
||||||
|
{
|
||||||
|
return Windows.CallWindowProcW(mDefWndProc, hWnd, msg, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual int HookProc(Windows.HWnd hWnd, int32 msg, int wParam, int lparam)
|
||||||
|
{
|
||||||
|
if (msg == Windows.WM_INITDIALOG)
|
||||||
|
{
|
||||||
|
//TODO: MoveToScreenCenter(hWnd);
|
||||||
|
// Under some circumstances, the dialog
|
||||||
|
// does not initially focus on any control. We fix that by explicitly
|
||||||
|
// setting focus ourselves. See ASURT 39435.
|
||||||
|
//
|
||||||
|
mDefaultControlHwnd = (Windows.HWnd)wParam;
|
||||||
|
if (mDefaultControlHwnd != 0)
|
||||||
|
Windows.SetFocus(mDefaultControlHwnd);
|
||||||
|
}
|
||||||
|
else if (msg == Windows.WM_SETFOCUS)
|
||||||
|
{
|
||||||
|
Windows.PostMessageW(hWnd, CDM_SETDEFAULTFOCUS, 0, 0);
|
||||||
|
}
|
||||||
|
else if (msg == CDM_SETDEFAULTFOCUS)
|
||||||
|
{
|
||||||
|
// If the dialog box gets focus, bounce it to the default control.
|
||||||
|
// so we post a message back to ourselves to wait for the focus change then push it to the default
|
||||||
|
// control. See ASURT 84016.
|
||||||
|
//
|
||||||
|
if (mDefaultControlHwnd != 0)
|
||||||
|
Windows.SetFocus(mDefaultControlHwnd);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract Result<DialogResult> RunDialog(Windows.HWnd hWndOwner);
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class FileDialog : CommonDialog
|
||||||
|
{
|
||||||
|
protected abstract Result<DialogResult> RunFileDialog(ref Windows.OpenFileName ofn);
|
||||||
|
|
||||||
|
protected override Result<DialogResult> RunDialog(Windows.HWnd hWndOwner)
|
||||||
|
{
|
||||||
|
if (TryRunDialogVista(hWndOwner) case .Ok(let result))
|
||||||
|
return .Ok(result);
|
||||||
|
|
||||||
|
return RunDialogOld(hWndOwner);
|
||||||
|
}
|
||||||
|
|
||||||
|
private const int32 FILEBUFSIZE = 8192;
|
||||||
|
protected const int32 OPTION_ADDEXTENSION = (int32)0x80000000;
|
||||||
|
|
||||||
|
protected int32 mOptions;
|
||||||
|
private String mTitle ~ delete _;
|
||||||
|
private String mInitialDir ~ delete _;
|
||||||
|
private String mDefaultExt ~ delete _;
|
||||||
|
protected String[] mFileNames ~ DeleteContainerAndItems!(_);
|
||||||
|
private bool mSecurityCheckFileNames;
|
||||||
|
private String mFilter ~ delete _;
|
||||||
|
private String mFilterBuffer = new String() ~ delete _;
|
||||||
|
private int32 mFilterIndex;
|
||||||
|
private bool mSupportMultiDottedExtensions;
|
||||||
|
private bool mIgnoreSecondFileOkNotification; // Used for VS Whidbey 95342
|
||||||
|
private int32 mOKNotificationCount; // Same
|
||||||
|
//private String char8Buffer = new String(FILEBUFSIZE) ~ delete _;
|
||||||
|
|
||||||
|
public this()
|
||||||
|
{
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Reset()
|
||||||
|
{
|
||||||
|
DeleteAndNullify!(mTitle);
|
||||||
|
DeleteAndNullify!(mInitialDir);
|
||||||
|
DeleteAndNullify!(mDefaultExt);
|
||||||
|
DeleteContainerAndItems!(mFileNames);
|
||||||
|
mFileNames = null;
|
||||||
|
DeleteAndNullify!(mFilter);
|
||||||
|
mFilterIndex = 1;
|
||||||
|
mSupportMultiDottedExtensions = false;
|
||||||
|
mOptions = Windows.OFN_HIDEREADONLY | Windows.OFN_PATHMUSTEXIST |
|
||||||
|
OPTION_ADDEXTENSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected int32 Options
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return mOptions & (
|
||||||
|
Windows.OFN_READONLY |
|
||||||
|
Windows.OFN_HIDEREADONLY |
|
||||||
|
Windows.OFN_NOCHANGEDIR |
|
||||||
|
Windows.OFN_SHOWHELP |
|
||||||
|
Windows.OFN_NOVALIDATE |
|
||||||
|
Windows.OFN_ALLOWMULTISELECT |
|
||||||
|
Windows.OFN_PATHMUSTEXIST |
|
||||||
|
Windows.OFN_FILEMUSTEXIST |
|
||||||
|
Windows.OFN_NODEREFERENCELINKS |
|
||||||
|
Windows.OFN_OVERWRITEPROMPT);
|
||||||
|
//return mOptions;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringView Title
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
String.NewOrSet!(mTitle, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return mTitle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringView InitialDirectory
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
String.NewOrSet!(mInitialDir, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return mInitialDir;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] FileNames
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return mFileNames;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringView FileName
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (mFileNames == null)
|
||||||
|
{
|
||||||
|
mFileNames = new String[](new String(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddExtension
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return GetOption(OPTION_ADDEXTENSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetOption(OPTION_ADDEXTENSION, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual bool CheckFileExists
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return GetOption(Windows.OFN_FILEMUSTEXIST);
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetOption(Windows.OFN_FILEMUSTEXIST, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DereferenceLinks
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return !GetOption(Windows.OFN_NODEREFERENCELINKS);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetOption(Windows.OFN_NODEREFERENCELINKS, !value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CheckPathExists
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return GetOption(Windows.OFN_PATHMUSTEXIST);
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetOption(Windows.OFN_PATHMUSTEXIST, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Multiselect
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return GetOption(Windows.OFN_ALLOWMULTISELECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetOption(Windows.OFN_ALLOWMULTISELECT, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ValidateNames
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return !GetOption(Windows.OFN_NOVALIDATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetOption(Windows.OFN_NOVALIDATE, !value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringView DefaultExt
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return mDefaultExt == null ? "" : mDefaultExt;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
delete mDefaultExt;
|
||||||
|
mDefaultExt = null;
|
||||||
|
|
||||||
|
//if (!String.IsNullOrEmpty(value))
|
||||||
|
if (value.Length > 0)
|
||||||
|
{
|
||||||
|
mDefaultExt = new String(value);
|
||||||
|
if (mDefaultExt.StartsWith("."))
|
||||||
|
mDefaultExt.Remove(0, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetFilter(String outFilter)
|
||||||
|
{
|
||||||
|
if (mFilter != null)
|
||||||
|
outFilter.Append(mFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result<void> SetFilter(StringView value)
|
||||||
|
{
|
||||||
|
String useValue = scope String(value);
|
||||||
|
if (useValue != null && useValue.Length > 0)
|
||||||
|
{
|
||||||
|
var formats = String.StackSplit!(useValue, '|');
|
||||||
|
if (formats == null || formats.Count % 2 != 0)
|
||||||
|
{
|
||||||
|
return .Err;
|
||||||
|
}
|
||||||
|
///
|
||||||
|
/*String[] formats = value.Split('|');
|
||||||
|
if (formats == null || formats.Length % 2 != 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentException(SR.GetString(SR.FileDialogInvalidFilter));
|
||||||
|
}*/
|
||||||
|
String.NewOrSet!(mFilter, useValue);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
useValue = null;
|
||||||
|
DeleteAndNullify!(mFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected bool GetOption(int32 option)
|
||||||
|
{
|
||||||
|
return (mOptions & option) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void SetOption(int32 option, bool value)
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
mOptions |= option;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mOptions &= ~option;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Result<void> MakeFilterString(String s, bool dereferenceLinks, String filterBuffer)
|
||||||
|
{
|
||||||
|
String useStr = s;
|
||||||
|
if (useStr == null || useStr.Length == 0)
|
||||||
|
{
|
||||||
|
// Workaround for Whidbey bug #5165
|
||||||
|
// Apply the workaround only when DereferenceLinks is true and OS is at least WinXP.
|
||||||
|
if (dereferenceLinks && System.Environment.OSVersion.Version.Major >= 5)
|
||||||
|
{
|
||||||
|
useStr = " |*.*";
|
||||||
|
}
|
||||||
|
else if (useStr == null)
|
||||||
|
{
|
||||||
|
return .Err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
filterBuffer.Set(s);
|
||||||
|
for (int32 i = 0; i < filterBuffer.Length; i++)
|
||||||
|
if (filterBuffer[i] == '|')
|
||||||
|
filterBuffer[i] = (char8)0;
|
||||||
|
filterBuffer.Append((char8)0);
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Result<DialogResult> RunDialogOld(Windows.HWnd hWndOwner)
|
||||||
|
{
|
||||||
|
//RunDialogTest(hWndOwner);
|
||||||
|
|
||||||
|
Windows.WndProc hookProcPtr = => StaticHookProc;
|
||||||
|
Windows.OpenFileName ofn = Windows.OpenFileName();
|
||||||
|
|
||||||
|
char16[FILEBUFSIZE] char16Buffer = .(0, ?);
|
||||||
|
|
||||||
|
if (mFileNames != null && !mFileNames.IsEmpty)
|
||||||
|
{
|
||||||
|
//int len = UTF16.GetEncodedLen(fileNames[0]);
|
||||||
|
//char16Buffer = scope:: char16[len + 1]*;
|
||||||
|
UTF16.Encode(mFileNames[0], (char16*)&char16Buffer, FILEBUFSIZE);
|
||||||
|
}
|
||||||
|
// Degrade to the older style dialog if we're not on Win2K.
|
||||||
|
// We do this by setting the struct size to a different value
|
||||||
|
//
|
||||||
|
|
||||||
|
if (Environment.OSVersion.Platform != System.PlatformID.Win32NT ||
|
||||||
|
Environment.OSVersion.Version.Major < 5) {
|
||||||
|
ofn.mStructSize = 0x4C;
|
||||||
|
}
|
||||||
|
ofn.mHwndOwner = hWndOwner;
|
||||||
|
ofn.mHInstance = (Windows.HInstance)Windows.GetModuleHandleW(null);
|
||||||
|
|
||||||
|
if (mFilter != null)
|
||||||
|
{
|
||||||
|
Try!(MakeFilterString(mFilter, this.DereferenceLinks, mFilterBuffer));
|
||||||
|
ofn.mFilter = mFilterBuffer.ToScopedNativeWChar!::();
|
||||||
|
}
|
||||||
|
ofn.nFilterIndex = mFilterIndex;
|
||||||
|
ofn.mFile = (char16*)&char16Buffer;
|
||||||
|
ofn.nMaxFile = FILEBUFSIZE;
|
||||||
|
if (mInitialDir != null)
|
||||||
|
ofn.mInitialDir = mInitialDir.ToScopedNativeWChar!::();
|
||||||
|
if (mTitle != null)
|
||||||
|
ofn.mTitle = mTitle.ToScopedNativeWChar!::();
|
||||||
|
ofn.mFlags = Options | (Windows.OFN_EXPLORER | Windows.OFN_ENABLEHOOK | Windows.OFN_ENABLESIZING);
|
||||||
|
ofn.mHook = hookProcPtr;
|
||||||
|
ofn.mCustData = (int)Internal.UnsafeCastToPtr(this);
|
||||||
|
ofn.mFlagsEx = Windows.OFN_USESHELLITEM;
|
||||||
|
if (mDefaultExt != null && AddExtension)
|
||||||
|
ofn.mDefExt = mDefaultExt.ToScopedNativeWChar!::();
|
||||||
|
|
||||||
|
DeleteContainerAndItems!(mFileNames);
|
||||||
|
mFileNames = null;
|
||||||
|
//Security checks happen here
|
||||||
|
return RunFileDialog(ref ofn);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int StaticHookProc(Windows.HWnd hWnd, int32 msg, int wParam, int lparam)
|
||||||
|
{
|
||||||
|
if (msg == Windows.WM_INITDIALOG)
|
||||||
|
{
|
||||||
|
using (sMonitor.Enter())
|
||||||
|
{
|
||||||
|
var ofn = (Windows.OpenFileName*)(void*)lparam;
|
||||||
|
sHookMap[(int)hWnd] = (CommonDialog)Internal.UnsafeCastToObject((void*)ofn.mCustData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CommonDialog dlg;
|
||||||
|
using (sMonitor.Enter())
|
||||||
|
{
|
||||||
|
sHookMap.TryGetValue((int)hWnd, out dlg);
|
||||||
|
}
|
||||||
|
if (dlg == null)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
dlg.[Friend]HookProc(hWnd, msg, wParam, lparam);
|
||||||
|
if (msg == Windows.WM_DESTROY)
|
||||||
|
{
|
||||||
|
using (sMonitor.Enter())
|
||||||
|
{
|
||||||
|
sHookMap.Remove((int)hWnd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
//TODO: Add ProcessFileNames for validation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -57,7 +57,7 @@ namespace System.IO
|
||||||
ShowNewFolderButton = true;
|
ShowNewFolderButton = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Result<DialogResult> RunDialog_New(Windows.HWnd hWndOwner, FolderBrowserDialog.COM_IFileDialog* fileDialog)
|
protected Result<DialogResult> RunDialog_New(Windows.HWnd hWndOwner, Windows.COM_IFileDialog* fileDialog)
|
||||||
{
|
{
|
||||||
//COM_IFileDialogEvents evts;
|
//COM_IFileDialogEvents evts;
|
||||||
/*COM_IFileDialogEvents.VTable funcs;
|
/*COM_IFileDialogEvents.VTable funcs;
|
||||||
|
@ -106,8 +106,8 @@ namespace System.IO
|
||||||
|
|
||||||
if (!mSelectedPath.IsEmpty)
|
if (!mSelectedPath.IsEmpty)
|
||||||
{
|
{
|
||||||
COM_IShellItem* folderShellItem = null;
|
Windows.COM_IShellItem* folderShellItem = null;
|
||||||
Windows.SHCreateItemFromParsingName(mSelectedPath.ToScopedNativeWChar!(), null, COM_IShellItem.sIID, (void**)&folderShellItem);
|
Windows.SHCreateItemFromParsingName(mSelectedPath.ToScopedNativeWChar!(), null, Windows.COM_IShellItem.sIID, (void**)&folderShellItem);
|
||||||
if (folderShellItem != null)
|
if (folderShellItem != null)
|
||||||
{
|
{
|
||||||
fileDialog.VT.SetDefaultFolder(fileDialog, folderShellItem);
|
fileDialog.VT.SetDefaultFolder(fileDialog, folderShellItem);
|
||||||
|
@ -121,7 +121,7 @@ namespace System.IO
|
||||||
DialogResult result = .Cancel;
|
DialogResult result = .Cancel;
|
||||||
|
|
||||||
mSelectedPath.Clear();
|
mSelectedPath.Clear();
|
||||||
COM_IShellItem* shellItem = null;
|
Windows.COM_IShellItem* shellItem = null;
|
||||||
fileDialog.VT.GetResult(fileDialog, out shellItem);
|
fileDialog.VT.GetResult(fileDialog, out shellItem);
|
||||||
if (shellItem != null)
|
if (shellItem != null)
|
||||||
{
|
{
|
||||||
|
@ -142,10 +142,10 @@ namespace System.IO
|
||||||
|
|
||||||
protected override Result<DialogResult> RunDialog(Windows.HWnd hWndOwner)
|
protected override Result<DialogResult> RunDialog(Windows.HWnd hWndOwner)
|
||||||
{
|
{
|
||||||
FolderBrowserDialog.COM_IFileDialog* fileDialog = null;
|
Windows.COM_IFileDialog* fileDialog = null;
|
||||||
Windows.COM_IUnknown.HResult hr;
|
Windows.COM_IUnknown.HResult hr;
|
||||||
//if (mFolderKind == .Open)
|
//if (mFolderKind == .Open)
|
||||||
hr = Windows.COM_IUnknown.CoCreateInstance(ref FolderBrowserDialog.COM_IFileDialog.sCLSID, null, .INPROC_SERVER, ref FolderBrowserDialog.COM_IFileDialog.sIID, (void**)&fileDialog);
|
hr = Windows.COM_IUnknown.CoCreateInstance(ref Windows.COM_IFileDialog.sCLSID, null, .INPROC_SERVER, ref Windows.COM_IFileDialog.sIID, (void**)&fileDialog);
|
||||||
//else
|
//else
|
||||||
//hr = Windows.COM_IUnknown.CoCreateInstance(ref FolderBrowserDialog.COM_FileSaveDialog.sCLSID, null, .INPROC_SERVER, ref FolderBrowserDialog.COM_FileSaveDialog.sIID, (void**)&fileDialog);
|
//hr = Windows.COM_IUnknown.CoCreateInstance(ref FolderBrowserDialog.COM_FileSaveDialog.sCLSID, null, .INPROC_SERVER, ref FolderBrowserDialog.COM_FileSaveDialog.sIID, (void**)&fileDialog);
|
||||||
if (hr == 0)
|
if (hr == 0)
|
||||||
|
@ -219,143 +219,6 @@ namespace System.IO
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FDE_SHAREVIOLATION_RESPONSE;
|
|
||||||
struct FDE_OVERWRITE_RESPONSE;
|
|
||||||
|
|
||||||
struct COM_IFileDialogEvents : Windows.COM_IUnknown
|
|
||||||
{
|
|
||||||
public struct VTable : Windows.COM_IUnknown.VTable
|
|
||||||
{
|
|
||||||
public function HResult(COM_IFileDialogEvents* self, COM_IFileDialog* fileDialog) OnFileOk;
|
|
||||||
public function HResult(COM_IFileDialogEvents* self, COM_IFileDialog* fileDialog, COM_IShellItem* psiFolder) OnFolderChanging;
|
|
||||||
public function HResult(COM_IFileDialogEvents* self, COM_IFileDialog* fileDialog) OnFolderChange;
|
|
||||||
public function HResult(COM_IFileDialogEvents* self, COM_IFileDialog* fileDialog) OnSelectionChange;
|
|
||||||
public function HResult(COM_IFileDialogEvents* self, COM_IFileDialog* fileDialog, FDE_SHAREVIOLATION_RESPONSE* pResponse) OnShareViolation;
|
|
||||||
public function HResult(COM_IFileDialogEvents* self, COM_IFileDialog* fileDialog) OnTypeChange;
|
|
||||||
public function HResult(COM_IFileDialogEvents* self, COM_IFileDialog* fileDialog, COM_IShellItem* shellItem, FDE_OVERWRITE_RESPONSE* response) OnOverwrite;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct COM_IShellItem : Windows.COM_IUnknown
|
|
||||||
{
|
|
||||||
public static Guid sIID = .(0x43826d1e, 0xe718, 0x42ee, 0xbc, 0x55, 0xa1, 0xe2, 0x61, 0xc3, 0x7b, 0xfe);
|
|
||||||
|
|
||||||
public enum SIGDN : uint32
|
|
||||||
{
|
|
||||||
NORMALDISPLAY = 0x00000000, // SHGDN_NORMAL
|
|
||||||
PARENTRELATIVEPARSING = 0x80018001, // SHGDN_INFOLDER | SHGDN_FORPARSING
|
|
||||||
DESKTOPABSOLUTEPARSING = 0x80028000, // SHGDN_FORPARSING
|
|
||||||
PARENTRELATIVEEDITING = 0x80031001, // SHGDN_INFOLDER | SHGDN_FOREDITING
|
|
||||||
DESKTOPABSOLUTEEDITING = 0x8004c000, // SHGDN_FORPARSING | SHGDN_FORADDRESSBAR
|
|
||||||
FILESYSPATH = 0x80058000, // SHGDN_FORPARSING
|
|
||||||
URL = 0x80068000, // SHGDN_FORPARSING
|
|
||||||
PARENTRELATIVEFORADDRESSBAR = 0x8007c001, // SHGDN_INFOLDER | SHGDN_FORPARSING | SHGDN_FORADDRESSBAR
|
|
||||||
PARENTRELATIVE = 0x80080001 // SHGDN_INFOLDER
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct VTable : Windows.COM_IUnknown.VTable
|
|
||||||
{
|
|
||||||
public function HResult(COM_IShellItem* self, void* pbc, ref Guid bhid, ref Guid riid, void** ppv) BindToHandler;
|
|
||||||
public function HResult(COM_IShellItem* self, out COM_IShellItem* ppsi) GetParent;
|
|
||||||
public function HResult(COM_IShellItem* self, SIGDN sigdnName, out char16* ppszName) GetDisplayName;
|
|
||||||
public function HResult(COM_IShellItem* self, uint sfgaoMask, out uint psfgaoAttribs) GetAttributes;
|
|
||||||
public function HResult(COM_IShellItem* self, COM_IShellItem* psi, uint32 hint, out int32 piOrder) Compare;
|
|
||||||
|
|
||||||
}
|
|
||||||
public new VTable* VT
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return (.)mVT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct COMDLG_FILTERSPEC
|
|
||||||
{
|
|
||||||
public char16* pszName;
|
|
||||||
public char16* pszSpec;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum FDAP : uint32
|
|
||||||
{
|
|
||||||
FDAP_BOTTOM = 0x00000000,
|
|
||||||
FDAP_TOP = 0x00000001,
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct COM_IFileDialog : Windows.COM_IUnknown
|
|
||||||
{
|
|
||||||
public static Guid sIID = .(0x42f85136, 0xdb7e, 0x439c, 0x85, 0xf1, 0xe4, 0x07, 0x5d, 0x13, 0x5f, 0xc8);
|
|
||||||
public static Guid sCLSID = .(0xdc1c5a9c, 0xe88a, 0x4dde, 0xa5, 0xa1, 0x60, 0xf8, 0x2a, 0x20, 0xae, 0xf7);
|
|
||||||
|
|
||||||
///s
|
|
||||||
public enum FOS : uint32
|
|
||||||
{
|
|
||||||
OVERWRITEPROMPT = 0x00000002,
|
|
||||||
STRICTFILETYPES = 0x00000004,
|
|
||||||
NOCHANGEDIR = 0x00000008,
|
|
||||||
PICKFOLDERS = 0x00000020,
|
|
||||||
FORCEFILESYSTEM = 0x00000040,
|
|
||||||
ALLNONSTORAGEITEMS = 0x00000080,
|
|
||||||
NOVALIDATE = 0x00000100,
|
|
||||||
ALLOWMULTISELECT = 0x00000200,
|
|
||||||
PATHMUSTEXIST = 0x00000800,
|
|
||||||
FILEMUSTEXIST = 0x00001000,
|
|
||||||
CREATEPROMPT = 0x00002000,
|
|
||||||
SHAREAWARE = 0x00004000,
|
|
||||||
NOREADONLYRETURN = 0x00008000,
|
|
||||||
NOTESTFILECREATE = 0x00010000,
|
|
||||||
HIDEMRUPLACES = 0x00020000,
|
|
||||||
HIDEPINNEDPLACES = 0x00040000,
|
|
||||||
NODEREFERENCELINKS = 0x00100000,
|
|
||||||
DONTADDTORECENT = 0x02000000,
|
|
||||||
FORCESHOWHIDDEN = 0x10000000,
|
|
||||||
DEFAULTNOMINIMODE = 0x20000000
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct VTable : Windows.COM_IUnknown.VTable
|
|
||||||
{
|
|
||||||
public function HResult(COM_IFileDialog* self, Windows.HWnd parent) Show;
|
|
||||||
public function HResult(COM_IFileDialog* self, uint cFileTypes, COMDLG_FILTERSPEC* rgFilterSpec) SetFileTypes;
|
|
||||||
public function HResult(COM_IFileDialog* self, uint iFileType) SetFileTypeIndex;
|
|
||||||
public function HResult(COM_IFileDialog* self, out uint piFileType) GetFileTypeIndex;
|
|
||||||
public function HResult(COM_IFileDialog* self, COM_IFileDialogEvents* pfde, out uint pdwCookie) Advise;
|
|
||||||
public function HResult(COM_IFileDialog* self, uint dwCookie) Unadvise;
|
|
||||||
public function HResult(COM_IFileDialog* self, FOS fos) SetOptions;
|
|
||||||
public function HResult(COM_IFileDialog* self, out FOS pfos) GetOptions;
|
|
||||||
public function HResult(COM_IFileDialog* self, COM_IShellItem* psi) SetDefaultFolder;
|
|
||||||
public function HResult(COM_IFileDialog* self, COM_IShellItem* psi) SetFolder;
|
|
||||||
public function HResult(COM_IFileDialog* self, out COM_IShellItem* ppsi) GetFolder;
|
|
||||||
public function HResult(COM_IFileDialog* self, out COM_IShellItem* ppsi) GetCurrentSelection;
|
|
||||||
public function HResult(COM_IFileDialog* self, char16* pszName) SetFileName;
|
|
||||||
public function HResult(COM_IFileDialog* self, out char16* pszName) GetFileName;
|
|
||||||
public function HResult(COM_IFileDialog* self, char16* pszTitle) SetTitle;
|
|
||||||
public function HResult(COM_IFileDialog* self, char16* pszText) SetOkButtonLabel;
|
|
||||||
public function HResult(COM_IFileDialog* self, char16* pszLabel) SetFileNameLabel;
|
|
||||||
public function HResult(COM_IFileDialog* self, out COM_IShellItem* ppsi) GetResult;
|
|
||||||
public function HResult(COM_IFileDialog* self, COM_IShellItem* psi, FDAP fdap) AddPlace;
|
|
||||||
public function HResult(COM_IFileDialog* self, char16* pszDefaultExtension) SetDefaultExtension;
|
|
||||||
public function HResult(COM_IFileDialog* self, int hr) Close;
|
|
||||||
public function HResult(COM_IFileDialog* self, ref Guid guid) SetClientGuid;
|
|
||||||
public function HResult(COM_IFileDialog* self) ClearClientData;
|
|
||||||
public function HResult(COM_IFileDialog* self, void* pFilter) SetFilter;
|
|
||||||
}
|
|
||||||
public new VTable* VT
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return (.)mVT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct COM_FileSaveDialog : COM_IFileDialog
|
|
||||||
{
|
|
||||||
public static new Guid sIID = .(0x84bccd23, 0x5fde, 0x4cdb, 0xae, 0xa4, 0xaf, 0x64, 0xb8, 0x3d, 0x78, 0xab);
|
|
||||||
public static new Guid sCLSID = .(0xC0B4E2F3, 0xBA21, 0x4773, 0x8D, 0xBA, 0x33, 0x5E, 0xC9, 0x46, 0xEB, 0x8B);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
|
@ -11,460 +11,6 @@ using System.Text;
|
||||||
|
|
||||||
namespace System.IO
|
namespace System.IO
|
||||||
{
|
{
|
||||||
enum DialogResult
|
|
||||||
{
|
|
||||||
None = 0,
|
|
||||||
OK = 1,
|
|
||||||
Cancel = 2
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class CommonDialog
|
|
||||||
{
|
|
||||||
public Windows.HWnd mHWnd;
|
|
||||||
public Windows.HWnd mDefaultControlHwnd;
|
|
||||||
public int mDefWndProc;
|
|
||||||
|
|
||||||
private const int32 CDM_SETDEFAULTFOCUS = Windows.WM_USER + 0x51;
|
|
||||||
|
|
||||||
public static Dictionary<int, CommonDialog> sHookMap = new Dictionary<int, CommonDialog>() ~
|
|
||||||
{
|
|
||||||
Debug.Assert(sHookMap.Count == 0);
|
|
||||||
delete _;
|
|
||||||
};
|
|
||||||
public static Monitor sMonitor = new Monitor() ~ delete _;
|
|
||||||
|
|
||||||
public Result<DialogResult> ShowDialog(INativeWindow owner = null)
|
|
||||||
{
|
|
||||||
Windows.HWnd hwndOwner = 0;
|
|
||||||
if (owner != null)
|
|
||||||
hwndOwner = (.)owner.Handle;
|
|
||||||
//Native.WndProc wndProc = scope => OwnerWndProc;
|
|
||||||
|
|
||||||
//mDefWndProc = Native.SetWindowLong(mHWnd, Native.GWL_WNDPROC, (intptr)wndProc.GetFuncPtr().Value);
|
|
||||||
|
|
||||||
var result = RunDialog(hwndOwner);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual int OwnerWndProc(Windows.HWnd hWnd, int32 msg, int wParam, int lParam)
|
|
||||||
{
|
|
||||||
return Windows.CallWindowProcW(mDefWndProc, hWnd, msg, wParam, lParam);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual int HookProc(Windows.HWnd hWnd, int32 msg, int wParam, int lparam)
|
|
||||||
{
|
|
||||||
if (msg == Windows.WM_INITDIALOG)
|
|
||||||
{
|
|
||||||
//TODO: MoveToScreenCenter(hWnd);
|
|
||||||
// Under some circumstances, the dialog
|
|
||||||
// does not initially focus on any control. We fix that by explicitly
|
|
||||||
// setting focus ourselves. See ASURT 39435.
|
|
||||||
//
|
|
||||||
mDefaultControlHwnd = (Windows.HWnd)wParam;
|
|
||||||
if (mDefaultControlHwnd != 0)
|
|
||||||
Windows.SetFocus(mDefaultControlHwnd);
|
|
||||||
}
|
|
||||||
else if (msg == Windows.WM_SETFOCUS)
|
|
||||||
{
|
|
||||||
Windows.PostMessageW(hWnd, CDM_SETDEFAULTFOCUS, 0, 0);
|
|
||||||
}
|
|
||||||
else if (msg == CDM_SETDEFAULTFOCUS)
|
|
||||||
{
|
|
||||||
// If the dialog box gets focus, bounce it to the default control.
|
|
||||||
// so we post a message back to ourselves to wait for the focus change then push it to the default
|
|
||||||
// control. See ASURT 84016.
|
|
||||||
//
|
|
||||||
if (mDefaultControlHwnd != 0)
|
|
||||||
Windows.SetFocus(mDefaultControlHwnd);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract Result<DialogResult> RunDialog(Windows.HWnd hWndOwner);
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class FileDialog : CommonDialog
|
|
||||||
{
|
|
||||||
protected abstract Result<DialogResult> RunFileDialog(ref Windows.OpenFileName ofn);
|
|
||||||
|
|
||||||
protected override Result<DialogResult> RunDialog(Windows.HWnd hWndOwner)
|
|
||||||
{
|
|
||||||
return RunDialogOld(hWndOwner);
|
|
||||||
}
|
|
||||||
|
|
||||||
private const int32 FILEBUFSIZE = 8192;
|
|
||||||
protected const int32 OPTION_ADDEXTENSION = (int32)0x80000000;
|
|
||||||
|
|
||||||
protected int32 mOptions;
|
|
||||||
private String mTitle ~ delete _;
|
|
||||||
private String mInitialDir ~ delete _;
|
|
||||||
private String mDefaultExt ~ delete _;
|
|
||||||
protected String[] mFileNames ~ DeleteContainerAndItems!(_);
|
|
||||||
private bool mSecurityCheckFileNames;
|
|
||||||
private String mFilter ~ delete _;
|
|
||||||
private String mFilterBuffer = new String() ~ delete _;
|
|
||||||
private int32 mFilterIndex;
|
|
||||||
private bool mSupportMultiDottedExtensions;
|
|
||||||
private bool mIgnoreSecondFileOkNotification; // Used for VS Whidbey 95342
|
|
||||||
private int32 mOKNotificationCount; // Same
|
|
||||||
//private String char8Buffer = new String(FILEBUFSIZE) ~ delete _;
|
|
||||||
|
|
||||||
public this()
|
|
||||||
{
|
|
||||||
Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual void Reset()
|
|
||||||
{
|
|
||||||
DeleteAndNullify!(mTitle);
|
|
||||||
DeleteAndNullify!(mInitialDir);
|
|
||||||
DeleteAndNullify!(mDefaultExt);
|
|
||||||
DeleteContainerAndItems!(mFileNames);
|
|
||||||
mFileNames = null;
|
|
||||||
DeleteAndNullify!(mFilter);
|
|
||||||
mFilterIndex = 1;
|
|
||||||
mSupportMultiDottedExtensions = false;
|
|
||||||
mOptions = Windows.OFN_HIDEREADONLY | Windows.OFN_PATHMUSTEXIST |
|
|
||||||
OPTION_ADDEXTENSION;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected int32 Options
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return mOptions & (
|
|
||||||
Windows.OFN_READONLY |
|
|
||||||
Windows.OFN_HIDEREADONLY |
|
|
||||||
Windows.OFN_NOCHANGEDIR |
|
|
||||||
Windows.OFN_SHOWHELP |
|
|
||||||
Windows.OFN_NOVALIDATE |
|
|
||||||
Windows.OFN_ALLOWMULTISELECT |
|
|
||||||
Windows.OFN_PATHMUSTEXIST |
|
|
||||||
Windows.OFN_FILEMUSTEXIST |
|
|
||||||
Windows.OFN_NODEREFERENCELINKS |
|
|
||||||
Windows.OFN_OVERWRITEPROMPT);
|
|
||||||
//return mOptions;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public StringView Title
|
|
||||||
{
|
|
||||||
set
|
|
||||||
{
|
|
||||||
String.NewOrSet!(mTitle, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return mTitle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public StringView InitialDirectory
|
|
||||||
{
|
|
||||||
set
|
|
||||||
{
|
|
||||||
String.NewOrSet!(mInitialDir, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return mInitialDir;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String[] FileNames
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return mFileNames;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public StringView FileName
|
|
||||||
{
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (mFileNames == null)
|
|
||||||
{
|
|
||||||
mFileNames = new String[](new String(value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool AddExtension
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return GetOption(OPTION_ADDEXTENSION);
|
|
||||||
}
|
|
||||||
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetOption(OPTION_ADDEXTENSION, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual bool CheckFileExists
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return GetOption(Windows.OFN_FILEMUSTEXIST);
|
|
||||||
}
|
|
||||||
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetOption(Windows.OFN_FILEMUSTEXIST, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool DereferenceLinks
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return !GetOption(Windows.OFN_NODEREFERENCELINKS);
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetOption(Windows.OFN_NODEREFERENCELINKS, !value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool CheckPathExists
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return GetOption(Windows.OFN_PATHMUSTEXIST);
|
|
||||||
}
|
|
||||||
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetOption(Windows.OFN_PATHMUSTEXIST, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Multiselect
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return GetOption(Windows.OFN_ALLOWMULTISELECT);
|
|
||||||
}
|
|
||||||
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetOption(Windows.OFN_ALLOWMULTISELECT, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool ValidateNames
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return !GetOption(Windows.OFN_NOVALIDATE);
|
|
||||||
}
|
|
||||||
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetOption(Windows.OFN_NOVALIDATE, !value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public StringView DefaultExt
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return mDefaultExt == null ? "" : mDefaultExt;
|
|
||||||
}
|
|
||||||
|
|
||||||
set
|
|
||||||
{
|
|
||||||
delete mDefaultExt;
|
|
||||||
mDefaultExt = null;
|
|
||||||
|
|
||||||
//if (!String.IsNullOrEmpty(value))
|
|
||||||
if (value.Length > 0)
|
|
||||||
{
|
|
||||||
mDefaultExt = new String(value);
|
|
||||||
if (mDefaultExt.StartsWith("."))
|
|
||||||
mDefaultExt.Remove(0, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void GetFilter(String outFilter)
|
|
||||||
{
|
|
||||||
if (mFilter != null)
|
|
||||||
outFilter.Append(mFilter);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Result<void> SetFilter(StringView value)
|
|
||||||
{
|
|
||||||
String useValue = scope String(value);
|
|
||||||
if (useValue != null && useValue.Length > 0)
|
|
||||||
{
|
|
||||||
var formats = String.StackSplit!(useValue, '|');
|
|
||||||
if (formats == null || formats.Count % 2 != 0)
|
|
||||||
{
|
|
||||||
return .Err;
|
|
||||||
}
|
|
||||||
///
|
|
||||||
/*String[] formats = value.Split('|');
|
|
||||||
if (formats == null || formats.Length % 2 != 0)
|
|
||||||
{
|
|
||||||
throw new ArgumentException(SR.GetString(SR.FileDialogInvalidFilter));
|
|
||||||
}*/
|
|
||||||
String.NewOrSet!(mFilter, useValue);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
useValue = null;
|
|
||||||
DeleteAndNullify!(mFilter);
|
|
||||||
}
|
|
||||||
|
|
||||||
return .Ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected bool GetOption(int32 option)
|
|
||||||
{
|
|
||||||
return (mOptions & option) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void SetOption(int32 option, bool value)
|
|
||||||
{
|
|
||||||
if (value)
|
|
||||||
{
|
|
||||||
mOptions |= option;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mOptions &= ~option;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Result<void> MakeFilterString(String s, bool dereferenceLinks, String filterBuffer)
|
|
||||||
{
|
|
||||||
String useStr = s;
|
|
||||||
if (useStr == null || useStr.Length == 0)
|
|
||||||
{
|
|
||||||
// Workaround for Whidbey bug #5165
|
|
||||||
// Apply the workaround only when DereferenceLinks is true and OS is at least WinXP.
|
|
||||||
if (dereferenceLinks && System.Environment.OSVersion.Version.Major >= 5)
|
|
||||||
{
|
|
||||||
useStr = " |*.*";
|
|
||||||
}
|
|
||||||
else if (useStr == null)
|
|
||||||
{
|
|
||||||
return .Err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
filterBuffer.Set(s);
|
|
||||||
for (int32 i = 0; i < filterBuffer.Length; i++)
|
|
||||||
if (filterBuffer[i] == '|')
|
|
||||||
filterBuffer[i] = (char8)0;
|
|
||||||
filterBuffer.Append((char8)0);
|
|
||||||
return .Ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static mixin Testie()
|
|
||||||
{
|
|
||||||
int a = 123;
|
|
||||||
char16* buf;
|
|
||||||
if (a == 0)
|
|
||||||
{
|
|
||||||
buf = null;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
buf = new char16[123]* ( ? );
|
|
||||||
defer:mixin delete buf;
|
|
||||||
}
|
|
||||||
buf
|
|
||||||
}
|
|
||||||
|
|
||||||
private Result<DialogResult> RunDialogOld(Windows.HWnd hWndOwner)
|
|
||||||
{
|
|
||||||
//RunDialogTest(hWndOwner);
|
|
||||||
|
|
||||||
Windows.WndProc hookProcPtr = => StaticHookProc;
|
|
||||||
Windows.OpenFileName ofn = Windows.OpenFileName();
|
|
||||||
|
|
||||||
char16[FILEBUFSIZE] char16Buffer = .(0, ?);
|
|
||||||
|
|
||||||
if (mFileNames != null)
|
|
||||||
{
|
|
||||||
//int len = UTF16.GetEncodedLen(fileNames[0]);
|
|
||||||
//char16Buffer = scope:: char16[len + 1]*;
|
|
||||||
UTF16.Encode(mFileNames[0], (char16*)&char16Buffer, FILEBUFSIZE);
|
|
||||||
}
|
|
||||||
// Degrade to the older style dialog if we're not on Win2K.
|
|
||||||
// We do this by setting the struct size to a different value
|
|
||||||
//
|
|
||||||
|
|
||||||
if (Environment.OSVersion.Platform != System.PlatformID.Win32NT ||
|
|
||||||
Environment.OSVersion.Version.Major < 5) {
|
|
||||||
ofn.mStructSize = 0x4C;
|
|
||||||
}
|
|
||||||
ofn.mHwndOwner = hWndOwner;
|
|
||||||
ofn.mHInstance = (Windows.HInstance)Windows.GetModuleHandleW(null);
|
|
||||||
|
|
||||||
if (mFilter != null)
|
|
||||||
{
|
|
||||||
Try!(MakeFilterString(mFilter, this.DereferenceLinks, mFilterBuffer));
|
|
||||||
ofn.mFilter = mFilterBuffer.ToScopedNativeWChar!::();
|
|
||||||
}
|
|
||||||
ofn.nFilterIndex = mFilterIndex;
|
|
||||||
ofn.mFile = (char16*)&char16Buffer;
|
|
||||||
ofn.nMaxFile = FILEBUFSIZE;
|
|
||||||
if (mInitialDir != null)
|
|
||||||
ofn.mInitialDir = mInitialDir.ToScopedNativeWChar!::();
|
|
||||||
if (mTitle != null)
|
|
||||||
ofn.mTitle = mTitle.ToScopedNativeWChar!::();
|
|
||||||
ofn.mFlags = Options | (Windows.OFN_EXPLORER | Windows.OFN_ENABLEHOOK | Windows.OFN_ENABLESIZING);
|
|
||||||
ofn.mHook = hookProcPtr;
|
|
||||||
ofn.mCustData = (int)Internal.UnsafeCastToPtr(this);
|
|
||||||
ofn.mFlagsEx = Windows.OFN_USESHELLITEM;
|
|
||||||
if (mDefaultExt != null && AddExtension)
|
|
||||||
ofn.mDefExt = mDefaultExt.ToScopedNativeWChar!::();
|
|
||||||
|
|
||||||
DeleteContainerAndItems!(mFileNames);
|
|
||||||
mFileNames = null;
|
|
||||||
//Security checks happen here
|
|
||||||
return RunFileDialog(ref ofn);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int StaticHookProc(Windows.HWnd hWnd, int32 msg, int wParam, int lparam)
|
|
||||||
{
|
|
||||||
if (msg == Windows.WM_INITDIALOG)
|
|
||||||
{
|
|
||||||
using (sMonitor.Enter())
|
|
||||||
{
|
|
||||||
var ofn = (Windows.OpenFileName*)(void*)lparam;
|
|
||||||
sHookMap[(int)hWnd] = (CommonDialog)Internal.UnsafeCastToObject((void*)ofn.mCustData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CommonDialog dlg;
|
|
||||||
using (sMonitor.Enter())
|
|
||||||
{
|
|
||||||
sHookMap.TryGetValue((int)hWnd, out dlg);
|
|
||||||
}
|
|
||||||
if (dlg == null)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
dlg.[Friend]HookProc(hWnd, msg, wParam, lparam);
|
|
||||||
if (msg == Windows.WM_DESTROY)
|
|
||||||
{
|
|
||||||
using (sMonitor.Enter())
|
|
||||||
{
|
|
||||||
sHookMap.Remove((int)hWnd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
//TODO: Add ProcessFileNames for validation
|
|
||||||
}
|
|
||||||
|
|
||||||
class OpenFileDialog : FileDialog
|
class OpenFileDialog : FileDialog
|
||||||
{
|
{
|
||||||
public override void Reset()
|
public override void Reset()
|
||||||
|
@ -557,6 +103,70 @@ namespace System.IO
|
||||||
|
|
||||||
return DialogResult.OK;
|
return DialogResult.OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void ProcessVistaFiles(Windows.COM_IFileDialog* dialog, List<String> files)
|
||||||
|
{
|
||||||
|
mixin GetFilePathFromShellItem(Windows.COM_IShellItem* shellItem)
|
||||||
|
{
|
||||||
|
String str = null;
|
||||||
|
if (shellItem.VT.GetDisplayName(shellItem, .FILESYSPATH, let cStr) == .OK)
|
||||||
|
{
|
||||||
|
str = new String()..Append(cStr);
|
||||||
|
Windows.COM_IUnknown.CoTaskMemFree(cStr);
|
||||||
|
}
|
||||||
|
str
|
||||||
|
}
|
||||||
|
|
||||||
|
Windows.COM_IFileOpenDialog* openDialog = (.)dialog;
|
||||||
|
if (Multiselect)
|
||||||
|
{
|
||||||
|
openDialog.VT.GetResults(openDialog, let results);
|
||||||
|
|
||||||
|
if (results != null)
|
||||||
|
{
|
||||||
|
results.VT.GetCount(results, let count);
|
||||||
|
for (uint32 i < count)
|
||||||
|
{
|
||||||
|
results.VT.GetItemAt(results, i, let item);
|
||||||
|
if (item != null)
|
||||||
|
{
|
||||||
|
let filePath = GetFilePathFromShellItem!(item);
|
||||||
|
if (filePath != null)
|
||||||
|
files.Add(filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
results.VT.Release(results);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
openDialog.VT.GetResult(openDialog, let shellItem);
|
||||||
|
|
||||||
|
if (shellItem != null)
|
||||||
|
{
|
||||||
|
let filePath = GetFilePathFromShellItem!(shellItem);
|
||||||
|
if (filePath != null)
|
||||||
|
files.Add(filePath);
|
||||||
|
shellItem.VT.Release(shellItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Result<Windows.COM_IFileDialog*> CreateVistaDialog()
|
||||||
|
{
|
||||||
|
Windows.COM_IFileDialog* fileDialog = null;
|
||||||
|
|
||||||
|
Windows.COM_IUnknown.HResult hr = (Windows.COM_IUnknown.CoCreateInstance(
|
||||||
|
ref Windows.COM_IFileDialog.sCLSID,
|
||||||
|
null,
|
||||||
|
.INPROC_SERVER | .LOCAL_SERVER | .REMOTE_SERVER,
|
||||||
|
ref Windows.COM_IFileOpenDialog.sIID,
|
||||||
|
(void**)&fileDialog));
|
||||||
|
if (hr.Failed)
|
||||||
|
return .Err;
|
||||||
|
|
||||||
|
return fileDialog;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -94,6 +94,47 @@ namespace System.IO
|
||||||
|
|
||||||
return DialogResult.OK;
|
return DialogResult.OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void ProcessVistaFiles(Windows.COM_IFileDialog* dialog, System.Collections.List<String> files)
|
||||||
|
{
|
||||||
|
mixin GetFilePathFromShellItem(Windows.COM_IShellItem* shellItem)
|
||||||
|
{
|
||||||
|
String str = null;
|
||||||
|
if (shellItem.VT.GetDisplayName(shellItem, .FILESYSPATH, let cStr) == .OK)
|
||||||
|
{
|
||||||
|
str = new String()..Append(cStr);
|
||||||
|
Windows.COM_IUnknown.CoTaskMemFree(cStr);
|
||||||
|
}
|
||||||
|
str
|
||||||
|
}
|
||||||
|
|
||||||
|
Windows.COM_IFileSaveDialog* saveDialog = (.)dialog;
|
||||||
|
saveDialog.VT.GetResult(saveDialog, let shellItem);
|
||||||
|
|
||||||
|
if (shellItem != null)
|
||||||
|
{
|
||||||
|
let filePath = GetFilePathFromShellItem!(shellItem);
|
||||||
|
if (filePath != null)
|
||||||
|
files.Add(filePath);
|
||||||
|
shellItem.VT.Release(shellItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Result<Windows.COM_IFileDialog*> CreateVistaDialog()
|
||||||
|
{
|
||||||
|
Windows.COM_IFileDialog* fileDialog = null;
|
||||||
|
|
||||||
|
Windows.COM_IUnknown.HResult hr = (Windows.COM_IUnknown.CoCreateInstance(
|
||||||
|
ref Windows.COM_IFileSaveDialog.sCLSID,
|
||||||
|
null,
|
||||||
|
.INPROC_SERVER | .LOCAL_SERVER | .REMOTE_SERVER,
|
||||||
|
ref Windows.COM_IFileSaveDialog.sIID,
|
||||||
|
(void**)&fileDialog));
|
||||||
|
if (hr.Failed)
|
||||||
|
return .Err;
|
||||||
|
|
||||||
|
return fileDialog;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1117,6 +1117,215 @@ namespace System
|
||||||
TRUSTEE_W Trustee;
|
TRUSTEE_W Trustee;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct COM_IFileDialogEvents : Windows.COM_IUnknown
|
||||||
|
{
|
||||||
|
struct FDE_SHAREVIOLATION_RESPONSE;
|
||||||
|
struct FDE_OVERWRITE_RESPONSE;
|
||||||
|
|
||||||
|
public struct VTable : Windows.COM_IUnknown.VTable
|
||||||
|
{
|
||||||
|
public function HResult(COM_IFileDialogEvents* self, COM_IFileDialog* fileDialog) OnFileOk;
|
||||||
|
public function HResult(COM_IFileDialogEvents* self, COM_IFileDialog* fileDialog, COM_IShellItem* psiFolder) OnFolderChanging;
|
||||||
|
public function HResult(COM_IFileDialogEvents* self, COM_IFileDialog* fileDialog) OnFolderChange;
|
||||||
|
public function HResult(COM_IFileDialogEvents* self, COM_IFileDialog* fileDialog) OnSelectionChange;
|
||||||
|
public function HResult(COM_IFileDialogEvents* self, COM_IFileDialog* fileDialog, FDE_SHAREVIOLATION_RESPONSE* pResponse) OnShareViolation;
|
||||||
|
public function HResult(COM_IFileDialogEvents* self, COM_IFileDialog* fileDialog) OnTypeChange;
|
||||||
|
public function HResult(COM_IFileDialogEvents* self, COM_IFileDialog* fileDialog, COM_IShellItem* shellItem, FDE_OVERWRITE_RESPONSE* response) OnOverwrite;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct COM_IShellItem : Windows.COM_IUnknown
|
||||||
|
{
|
||||||
|
public static Guid sIID = .(0x43826d1e, 0xe718, 0x42ee, 0xbc, 0x55, 0xa1, 0xe2, 0x61, 0xc3, 0x7b, 0xfe);
|
||||||
|
|
||||||
|
public enum SIGDN : uint32
|
||||||
|
{
|
||||||
|
NORMALDISPLAY = 0x00000000, // SHGDN_NORMAL
|
||||||
|
PARENTRELATIVEPARSING = 0x80018001, // SHGDN_INFOLDER | SHGDN_FORPARSING
|
||||||
|
DESKTOPABSOLUTEPARSING = 0x80028000, // SHGDN_FORPARSING
|
||||||
|
PARENTRELATIVEEDITING = 0x80031001, // SHGDN_INFOLDER | SHGDN_FOREDITING
|
||||||
|
DESKTOPABSOLUTEEDITING = 0x8004c000, // SHGDN_FORPARSING | SHGDN_FORADDRESSBAR
|
||||||
|
FILESYSPATH = 0x80058000, // SHGDN_FORPARSING
|
||||||
|
URL = 0x80068000, // SHGDN_FORPARSING
|
||||||
|
PARENTRELATIVEFORADDRESSBAR = 0x8007c001, // SHGDN_INFOLDER | SHGDN_FORPARSING | SHGDN_FORADDRESSBAR
|
||||||
|
PARENTRELATIVE = 0x80080001 // SHGDN_INFOLDER
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct VTable : Windows.COM_IUnknown.VTable
|
||||||
|
{
|
||||||
|
public function HResult(COM_IShellItem* self, void* pbc, ref Guid bhid, ref Guid riid, void** ppv) BindToHandler;
|
||||||
|
public function HResult(COM_IShellItem* self, out COM_IShellItem* ppsi) GetParent;
|
||||||
|
public function HResult(COM_IShellItem* self, SIGDN sigdnName, out char16* ppszName) GetDisplayName;
|
||||||
|
public function HResult(COM_IShellItem* self, uint sfgaoMask, out uint psfgaoAttribs) GetAttributes;
|
||||||
|
public function HResult(COM_IShellItem* self, COM_IShellItem* psi, uint32 hint, out int32 piOrder) Compare;
|
||||||
|
|
||||||
|
}
|
||||||
|
public new VTable* VT
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (.)mVT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct COM_IShellItemArray : Windows.COM_IUnknown
|
||||||
|
{
|
||||||
|
public enum GETPROPERTYSTOREFLAGS : uint
|
||||||
|
{
|
||||||
|
DEFAULT = 0x00000000,
|
||||||
|
HANDLERPROPERTIESONLY = 0x00000001,
|
||||||
|
READWRITE = 0x00000002,
|
||||||
|
TEMPORARY = 0x00000004,
|
||||||
|
FASTPROPERTIESONLY = 0x00000008,
|
||||||
|
OPENSLOWITEM = 0x00000010,
|
||||||
|
DELAYCREATION = 0x00000020,
|
||||||
|
BESTEFFORT = 0x00000040,
|
||||||
|
NO_OPLOCK = 0x00000080,
|
||||||
|
PREFERQUERYPROPERTIES = 0x00000100,
|
||||||
|
EXTRINSICPROPERTIES = 0x00000200,
|
||||||
|
EXTRINSICPROPERTIESONLY = 0x00000400,
|
||||||
|
VOLATILEPROPERTIES = 0x00000800,
|
||||||
|
VOLATILEPROPERTIESONLY = 0x00001000,
|
||||||
|
MASK_VALID = 0x00001FFF
|
||||||
|
}
|
||||||
|
|
||||||
|
[AllowDuplicates]
|
||||||
|
public enum SIATTRIBFLAGS : uint
|
||||||
|
{
|
||||||
|
AND = 0x1,
|
||||||
|
OR = 0x2,
|
||||||
|
APPCOMPAT = 0x3,
|
||||||
|
MASK = 0x3,
|
||||||
|
ALLITEMS = 0x4000
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct PROPERTYKEY;
|
||||||
|
|
||||||
|
public static Guid sIID = .(0xB63EA76D, 0x1F85, 0x456F, 0xA1, 0x9C, 0x48, 0x15, 0x9E, 0xFA, 0x85, 0x8B);
|
||||||
|
|
||||||
|
public struct VTable : Windows.COM_IUnknown.VTable
|
||||||
|
{
|
||||||
|
public function HResult(COM_IShellItemArray* self, void* pbc, ref Guid rbhid, ref Guid riid, out void* ppvOut) BindToHandler;
|
||||||
|
public function HResult(COM_IShellItemArray* self, GETPROPERTYSTOREFLAGS flags, ref Guid riid, out void* ppv) GetPropertyStore;
|
||||||
|
public function HResult(COM_IShellItemArray* self, ref PROPERTYKEY keyType, ref Guid riid, out void* ppv) GetPropertyDescriptionList;
|
||||||
|
public function HResult(COM_IShellItemArray* self, SIATTRIBFLAGS dwAttribFlags, uint32 sfgaoMask, out uint32 psfgaoAttribs) GetAttributes;
|
||||||
|
public function HResult(COM_IShellItemArray* self, out uint32 pdwNumItems) GetCount;
|
||||||
|
public function HResult(COM_IShellItemArray* self, uint32 dwIndex, out COM_IShellItem* ppsi) GetItemAt;
|
||||||
|
public function HResult(COM_IShellItemArray* self, out void* ppenumShellItems) EnumItems;
|
||||||
|
}
|
||||||
|
public new VTable* VT
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (.)mVT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct COMDLG_FILTERSPEC
|
||||||
|
{
|
||||||
|
public char16* pszName;
|
||||||
|
public char16* pszSpec;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum FDAP : uint32
|
||||||
|
{
|
||||||
|
FDAP_BOTTOM = 0x00000000,
|
||||||
|
FDAP_TOP = 0x00000001,
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct COM_IFileDialog : Windows.COM_IUnknown
|
||||||
|
{
|
||||||
|
public static Guid sIID = .(0x42f85136, 0xdb7e, 0x439c, 0x85, 0xf1, 0xe4, 0x07, 0x5d, 0x13, 0x5f, 0xc8);
|
||||||
|
public static Guid sCLSID = .(0xdc1c5a9c, 0xe88a, 0x4dde, 0xa5, 0xa1, 0x60, 0xf8, 0x2a, 0x20, 0xae, 0xf7);
|
||||||
|
|
||||||
|
///s
|
||||||
|
public enum FOS : uint32
|
||||||
|
{
|
||||||
|
OVERWRITEPROMPT = 0x00000002,
|
||||||
|
STRICTFILETYPES = 0x00000004,
|
||||||
|
NOCHANGEDIR = 0x00000008,
|
||||||
|
PICKFOLDERS = 0x00000020,
|
||||||
|
FORCEFILESYSTEM = 0x00000040,
|
||||||
|
ALLNONSTORAGEITEMS = 0x00000080,
|
||||||
|
NOVALIDATE = 0x00000100,
|
||||||
|
ALLOWMULTISELECT = 0x00000200,
|
||||||
|
PATHMUSTEXIST = 0x00000800,
|
||||||
|
FILEMUSTEXIST = 0x00001000,
|
||||||
|
CREATEPROMPT = 0x00002000,
|
||||||
|
SHAREAWARE = 0x00004000,
|
||||||
|
NOREADONLYRETURN = 0x00008000,
|
||||||
|
NOTESTFILECREATE = 0x00010000,
|
||||||
|
HIDEMRUPLACES = 0x00020000,
|
||||||
|
HIDEPINNEDPLACES = 0x00040000,
|
||||||
|
NODEREFERENCELINKS = 0x00100000,
|
||||||
|
DONTADDTORECENT = 0x02000000,
|
||||||
|
FORCESHOWHIDDEN = 0x10000000,
|
||||||
|
DEFAULTNOMINIMODE = 0x20000000
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct VTable : Windows.COM_IUnknown.VTable
|
||||||
|
{
|
||||||
|
public function HResult(COM_IFileDialog* self, Windows.HWnd parent) Show;
|
||||||
|
public function HResult(COM_IFileDialog* self, uint cFileTypes, COMDLG_FILTERSPEC* rgFilterSpec) SetFileTypes;
|
||||||
|
public function HResult(COM_IFileDialog* self, uint iFileType) SetFileTypeIndex;
|
||||||
|
public function HResult(COM_IFileDialog* self, out uint piFileType) GetFileTypeIndex;
|
||||||
|
public function HResult(COM_IFileDialog* self, COM_IFileDialogEvents* pfde, out uint pdwCookie) Advise;
|
||||||
|
public function HResult(COM_IFileDialog* self, uint dwCookie) Unadvise;
|
||||||
|
public function HResult(COM_IFileDialog* self, FOS fos) SetOptions;
|
||||||
|
public function HResult(COM_IFileDialog* self, out FOS pfos) GetOptions;
|
||||||
|
public function HResult(COM_IFileDialog* self, COM_IShellItem* psi) SetDefaultFolder;
|
||||||
|
public function HResult(COM_IFileDialog* self, COM_IShellItem* psi) SetFolder;
|
||||||
|
public function HResult(COM_IFileDialog* self, out COM_IShellItem* ppsi) GetFolder;
|
||||||
|
public function HResult(COM_IFileDialog* self, out COM_IShellItem* ppsi) GetCurrentSelection;
|
||||||
|
public function HResult(COM_IFileDialog* self, char16* pszName) SetFileName;
|
||||||
|
public function HResult(COM_IFileDialog* self, out char16* pszName) GetFileName;
|
||||||
|
public function HResult(COM_IFileDialog* self, char16* pszTitle) SetTitle;
|
||||||
|
public function HResult(COM_IFileDialog* self, char16* pszText) SetOkButtonLabel;
|
||||||
|
public function HResult(COM_IFileDialog* self, char16* pszLabel) SetFileNameLabel;
|
||||||
|
public function HResult(COM_IFileDialog* self, out COM_IShellItem* ppsi) GetResult;
|
||||||
|
public function HResult(COM_IFileDialog* self, COM_IShellItem* psi, FDAP fdap) AddPlace;
|
||||||
|
public function HResult(COM_IFileDialog* self, char16* pszDefaultExtension) SetDefaultExtension;
|
||||||
|
public function HResult(COM_IFileDialog* self, int hr) Close;
|
||||||
|
public function HResult(COM_IFileDialog* self, ref Guid guid) SetClientGuid;
|
||||||
|
public function HResult(COM_IFileDialog* self) ClearClientData;
|
||||||
|
public function HResult(COM_IFileDialog* self, void* pFilter) SetFilter;
|
||||||
|
}
|
||||||
|
public new VTable* VT
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (.)mVT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct COM_IFileSaveDialog : COM_IFileDialog
|
||||||
|
{
|
||||||
|
public static new Guid sIID = .(0x84BCCD23, 0x5FDE, 0x4CDB, 0xAE, 0xA4, 0xAF, 0x64, 0xB8, 0x3D, 0x78, 0xAB);
|
||||||
|
public static new Guid sCLSID = .(0xC0B4E2F3, 0xBA21, 0x4773, 0x8D, 0xBA, 0x33, 0x5E, 0xC9, 0x46, 0xEB, 0x8B);
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct COM_IFileOpenDialog : COM_IFileDialog
|
||||||
|
{
|
||||||
|
public static new Guid sIID = .(0xD57C7288, 0xD4AD, 0x4768, 0xBE, 0x02, 0x9D, 0x96, 0x95, 0x32, 0xD9, 0x60);
|
||||||
|
|
||||||
|
public struct VTable : COM_IFileDialog.VTable
|
||||||
|
{
|
||||||
|
public function HResult(COM_IFileOpenDialog* self, out COM_IShellItemArray* ppenum) GetResults;
|
||||||
|
public function HResult(COM_IFileOpenDialog* self, out COM_IShellItemArray* ppsai) GetSelectedItems;
|
||||||
|
}
|
||||||
|
public new VTable* VT
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (.)mVT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Import("version.lib"), CLink, CallingConvention(.Stdcall)]
|
[Import("version.lib"), CLink, CallingConvention(.Stdcall)]
|
||||||
public static extern IntBool GetFileVersionInfoW(char16* lptstrFilename, uint32 dwHandle, uint32 dwLen, void* lpData);
|
public static extern IntBool GetFileVersionInfoW(char16* lptstrFilename, uint32 dwHandle, uint32 dwLen, void* lpData);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue