From 37e6b935a9b182ccc361b7f96a951e9a1c600671 Mon Sep 17 00:00:00 2001 From: Martin Karpisek Date: Fri, 8 Sep 2017 16:47:20 +0530 Subject: Bug 443250 - [win32] Support modern native directory dialog - directory dialog on windows vista and newer will be from now using more modern 'Common Item Dialog' -if this vista-style dialog is not available (old windows version) then basic win32 directory dialog will be used Change-Id: Ib0f4f02e5909908442c23e0b618b82faf3b7cac8 Signed-off-by: Martin Karpisek --- .../org/eclipse/swt/widgets/DirectoryDialog.java | 85 +++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) (limited to 'bundles/org.eclipse.swt/Eclipse SWT') diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/DirectoryDialog.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/DirectoryDialog.java index 6c7b65fc82..aa29191360 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/DirectoryDialog.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/DirectoryDialog.java @@ -7,12 +7,14 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Martin Karpisek - Bug 443250 *******************************************************************************/ package org.eclipse.swt.widgets; import org.eclipse.swt.*; import org.eclipse.swt.internal.*; +import org.eclipse.swt.internal.com.win32.*; import org.eclipse.swt.internal.win32.*; /** @@ -34,6 +36,19 @@ import org.eclipse.swt.internal.win32.*; * @noextend This class is not intended to be subclassed by clients. */ public class DirectoryDialog extends Dialog { + static final byte[] CLSID_FileOpenDialog = new byte[16]; + static final byte[] IID_IFileOpenDialog = new byte[16]; + static final byte[] IID_IShellItem = new byte[16]; + static { + if (OS.IsWinVista) { + //Common Item/File Dialog + OS.IIDFromString("{DC1C5A9C-E88A-4dde-A5A1-60F82A20AEF7}\0".toCharArray(), CLSID_FileOpenDialog); //$NON-NLS-1$ + OS.IIDFromString("{d57c7288-d4ad-4768-be02-9d969532d960}\0".toCharArray(), IID_IFileOpenDialog); //$NON-NLS-1$ + OS.IIDFromString("{43826d1e-e718-42ee-bc55-a1e261c37bfe}\0".toCharArray(), IID_IShellItem); //$NON-NLS-1$ + } + } + + String message = "", filterPath = ""; //$NON-NLS-1$//$NON-NLS-2$ String directoryPath; @@ -145,7 +160,14 @@ public String getMessage () { *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the dialog
  • * */ -public String open () { +public String open() { + if (OS.IsWinVista) { + return openCommonItemDialog(); + } + return openCommonFileDialog(); +} + +private String openCommonFileDialog () { if (OS.IsWinCE) error (SWT.ERROR_NOT_IMPLEMENTED); long /*int*/ hHeap = OS.GetProcessHeap (); @@ -274,6 +296,67 @@ public String open () { return directoryPath; } +private String openCommonItemDialog() { + this.directoryPath = null; + + long /*int*/ [] ppv = new long /*int*/ [1]; + if (OS.CoCreateInstance(CLSID_FileOpenDialog, 0, OS.CLSCTX_INPROC_SERVER, IID_IFileOpenDialog, ppv) == OS.S_OK) { + long /*int*/ fileDialog = ppv[0]; + + int[] options = new int[1]; + if ((OS.VtblCall(FileDialogVtbl.GET_OPTIONS, fileDialog, options)) == OS.S_OK) { + options[0] |= OS.FOS_PICKFOLDERS | OS.FOS_FORCEFILESYSTEM | OS.FOS_NOCHANGEDIR; + + OS.VtblCall(FileDialogVtbl.SET_OPTIONS, fileDialog, options[0]); + } + + if (title == null) title = ""; + if (title.length() > 0) { + char[] buffer = new char[title.length() + 1]; + title.getChars(0, title.length(), buffer, 0); + OS.VtblCall(FileDialogVtbl.SET_TITLE, fileDialog, buffer); + } + + if (filterPath != null && filterPath.length() > 0) { + String path = filterPath.replace('/', '\\'); + char[] buffer = new char[path.length() + 1]; + path.getChars(0, path.length(), buffer, 0); + if (OS.SHCreateItemFromParsingName(buffer, 0, IID_IShellItem, ppv) == OS.S_OK) { + long /*int*/ psi = ppv[0]; + /* + * SetDefaultDirectory does not work if the dialog has + * persisted recently used folder. The fix is to clear the + * persisted data. + */ + OS.VtblCall(FileDialogVtbl.CLEAR_CLIENT_DATA, fileDialog); + OS.VtblCall(FileDialogVtbl.SET_DEFAULT_FOLDER, fileDialog, psi); + OS.VtblCall(FileDialogVtbl.RELEASE, psi); + } + } + + long /*int*/ hwndOwner = parent.handle; + if (OS.VtblCall(FileDialogVtbl.SHOW, fileDialog, hwndOwner) == OS.S_OK) { + if (OS.VtblCall(FileDialogVtbl.GET_RESULT, fileDialog, ppv) == OS.S_OK) { + long /*int*/ psi = ppv[0]; + if (OS.VtblCall(ShellItemVtbl.GET_DISPLAY_NAME, psi, OS.SIGDN_FILESYSPATH, ppv) == OS.S_OK) { + long /*int*/ wstr = ppv[0]; + int length = OS.wcslen(wstr); + char[] buffer = new char[length]; + OS.MoveMemory(buffer, wstr, length * 2); + OS.CoTaskMemFree(wstr); + + directoryPath = new String(buffer); + } + OS.VtblCall(FileDialogVtbl.RELEASE, psi); + } + } + + OS.VtblCall(FileDialogVtbl.RELEASE, fileDialog); + } + + return directoryPath; +} + /** * Sets the path that the dialog will use to filter * the directories it shows to the argument, which may -- cgit v1.2.1