如果同时设置了InitialDirectory,OpenFileDialog是否可以自动选择FileName中设置的值的文件?

Dou*_*nse 26 c# windows winforms

这是NIT挑剔,但为什么不将文件都会自动如果它存在选择都FileNameInitialDirectory设置是否正确?

我有OpenFileDialog两个FileNameInitialDirectory正确设置,文件存在于此文件夹中.为什么在运行ShowDialog()方法时没有选择文件?

没有选择文件,但如果选择它会很好,所以我不必向下滚动以选择与其相邻的下一个文件.

有什么建议?

Ber*_*kay 11

也许它并不完美但它以某种方式满足了期望.

我有一个Button显示OpenFileDialog上单击事件.和SendKeys到OpenFileDialog的异步方法.

    private async void button1_Click(object sender, EventArgs e){
                string initialDir = "directory\\";
                string FileName = "filename.smthng";
                string combinedDir = initialDir + FileName;
                if (File.Exists(combinedDir)) // if there is a file with that name at that directory
                {
                    openFileDialog1.InitialDirectory = initialDir; // setting directory name
                    openFileDialog1.FileName = FileName; // filename
                    BeginInvoke((Action)(() => openFileDialog1.ShowDialog())); // we need to use BeginInvoke to continue to the following code.
                    await SendKey(FileName); // Sends Key to Dialog 
                }
                else // if there is not file with that name works here because no keys need to send.
                {
                    openFileDialog1.InitialDirectory = initialDir;
                    openFileDialog1.FileName = FileName;
                    openFileDialog1.ShowDialog();
                }

    }

    private async Task SendKey(string FileName){
            await Task.Delay(250); // Wait for the Dialog shown at the screen
            SendKeys.SendWait("+{TAB}"); // First Shift + Tab moves to Header of DataGridView of OpenFileDialog
            SendKeys.SendWait("+{TAB}"); // Second Shift + Tab moves to first item of list
            SendKeys.SendWait(FileName); // after sending filename will directly moves it to the file that we are looking for
    }
Run Code Online (Sandbox Code Playgroud)

结果;

打开文件对话框

编辑1;

好的,因为.Net 3.5还有TaskParalelLibrary使用Thread会更容易.

 Thread t;
 private const string initialDir = "C:\\";
 private const string FileName = "test.txt";
 private void button1_Click(object sender, EventArgs e){
       string combinedDir = initialDir + FileName;
       if (File.Exists(combinedDir)) // if there is a file with that name at that directory
            {
                openFileDialog1.InitialDirectory = initialDir; // setting directory name
                openFileDialog1.FileName = FileName; // filename
                BeginInvoke((Action)(() => openFileDialog1.ShowDialog())); // we need to use BeginInvoke to continue to the following code.
                t = new Thread(new ThreadStart(SendKey)); // Sends Key to Dialog with an seperate Thread.
                t.Start(); // Thread starts.
            }
            else // if there is not file with that name works here because no keys need to send.
            {
                openFileDialog1.InitialDirectory = initialDir;
                openFileDialog1.FileName = FileName;
                openFileDialog1.ShowDialog();
            }
        }

        private void SendKey()
        {
            Thread.Sleep(100); // Wait for the Dialog shown at the screen
            SendKeys.SendWait("+{TAB}"); // First Shift + Tab moves to Header of DataGridView of OpenFileDialog
            SendKeys.SendWait("+{TAB}"); // Second Shift + Tab moves to first item of list
            SendKeys.SendWait(FileName); // after sending filename will directly moves it to the file that we are looking for
        }
Run Code Online (Sandbox Code Playgroud)

希望有帮助,


Jer*_*son 9

的SendKeys

SendKeys似乎是一个黑客,但它是最简单的,并且由于下面解释的原因可能比使用Win32 API更长期可持续.

依赖a await Task.Delay(250); 是有风险的.在慢速系统上显示对话框之前,超时可能太快,另一方面,如果超时增加,快速用户可能会在与SendKeys自动化竞争时进行交互.

我建议您使用消息循环来通知何时SendKeys.

bool IsOpenFileDialog = false;
private void openDialog_Click(object sender, EventArgs e)
{
    IsOpenFileDialog = true;
    openFileDialog1.ShowDialog();
    IsOpenFileDialog = false;
}

uint _lastDialogHandle = 0;
protected override void WndProc(ref Message m)
{
    base.WndProc(ref m);
    if (!IsOpenFileDialog) return;
    if (m.Msg == 289) //Notify of message loop
    {
        try
        {
            uint dialogHandle = (uint)m.LParam; //handle of the file dialog
            if (dialogHandle != _lastDialogHandle) //only when not already changed
            {
                _lastDialogHandle = dialogHandle;
                SendKeys.SendWait("+{TAB}");
                SendKeys.SendWait("+{TAB}");   
                SendKeys.SendWait(EscapeSendKeySpecialCharacters("temp.xls"));

                //Or try via Win32
                //List<string> childWindows = GetDialogChildWindows(dialogHandle);
                //TODO set ListView Item
            }
        }
        catch (Exception ex) {}
    }
}

private string EscapeSendKeySpecialCharacters(string sentence)
{
    sentence = sentence.Replace("+", "{+}");
    sentence = sentence.Replace("^", "{^}");
    sentence = sentence.Replace("%", "{%}");
    sentence = sentence.Replace("~", "{~}");
    sentence = sentence.Replace("(", "{(}");
    sentence = sentence.Replace(")", "{)}");
    return sentence;
}
Run Code Online (Sandbox Code Playgroud)

注意:加号(+),插入符号(^),百分号(%),波浪号(〜)和括号()对SendKeys具有特殊含义.要指定其中一个字符,请将其括在大括号({})中.

因此,例如,如果您的文件名有括号,则需要使用大括号来转义它们:

SendKeys.SendWait("New Text Document - Copy {(}8{)}.txt");
Run Code Online (Sandbox Code Playgroud)

Win32(尝试 - 不完整,不工作)

您可以尝试迭代OpenFileDialogs的子窗口以查找listview控件:

private List<string> GetDialogChildWindows(dialogHandle) {
//IEnumerable<IntPtr> allWindows = EnumWindowsAndChild.EnumAllWindows((IntPtr)dialogHandle, "Dialog");
List<IntPtr>  children = EnumWindowsAndChild.GetChildWindows((IntPtr)dialogHandle);
List<string> childWindows = new List<string>();
foreach (IntPtr ptr in children)
{
    string s = ptr.ToString() + ",  " + EnumWindowsAndChild.GetWindowsTextTitle(ptr) + ", " + EnumWindowsAndChild.GetWindowClassName(ptr);
System.Diagnostics.Debug.WriteLine(s);
        childWindows.Add(s);
   }
  return childWindows;
 }
Run Code Online (Sandbox Code Playgroud)

Enum Windows和Child类助手:

public static class EnumWindowsAndChild
{
    public delegate bool Win32Callback(IntPtr hwnd, IntPtr lParam);

    [DllImport("user32.Dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool EnumChildWindows(IntPtr parentHandle, Win32Callback callback, IntPtr lParam);

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    static public extern IntPtr GetClassName(IntPtr hWnd, System.Text.StringBuilder lpClassName, int nMaxCount);

    private static bool EnumWindow(IntPtr handle, IntPtr pointer)
    {
        GCHandle gch = GCHandle.FromIntPtr(pointer);
        List<IntPtr> list = gch.Target as List<IntPtr>;
        if (list == null)
            throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
        list.Add(handle);
        return true;
    }

    public static List<IntPtr> GetChildWindows(IntPtr parent)
    {
        List<IntPtr> result = new List<IntPtr>();
        GCHandle listHandle = GCHandle.Alloc(result);
        try
        {
            Win32Callback childProc = new Win32Callback(EnumWindow);
            EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle));
        }
        finally
        {
            if (listHandle.IsAllocated)
                listHandle.Free();
        }
        return result;
    }

    public static string GetWinClass(IntPtr hwnd)
    {
        if (hwnd == IntPtr.Zero)
            return null;
        StringBuilder classname = new StringBuilder(100);
        IntPtr result = GetClassName(hwnd, classname, classname.Capacity);
        if (result != IntPtr.Zero)
            return classname.ToString();
        return null;
    }

    public static IEnumerable<IntPtr> EnumAllWindows(IntPtr hwnd, string childClassName)
    {
        List<IntPtr> children = GetChildWindows(hwnd);
        if (children == null)
            yield break;
        foreach (IntPtr child in children)
        {
            if (GetWinClass(child) == childClassName)
                yield return child;
            foreach (var childchild in EnumAllWindows(child, childClassName))
                yield return childchild;
        }
    }

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern int GetWindowTextLength(HandleRef hWnd);
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern int GetWindowText(HandleRef hWnd, StringBuilder lpString, int nMaxCount);

    public static string GetWindowsTextTitle(IntPtr hwnd)
    {
        int capacity = GetWindowTextLength(new HandleRef(null, hwnd)) * 2;
        StringBuilder stringBuilder = new StringBuilder(capacity);
        GetWindowText(new HandleRef(null, hwnd), stringBuilder, stringBuilder.Capacity);
        return stringBuilder.ToString();

    }

    public static string GetWindowClassName(IntPtr hWnd)
    {
        StringBuilder buffer = new StringBuilder(128);
        GetClassName(hWnd, buffer, buffer.Capacity);
        return buffer.ToString();
    }
}
Run Code Online (Sandbox Code Playgroud)

一旦你的HWND你可以尝试设置其项目的ListView,但你需要使用NativeWindow并将其不会是漂亮,看到这篇文章,知道我的意思:HTTP://www.codeproject. COM /用品/ 2890 /使用-的ListView-控制下的Win-API

尽管我不愿意承认,但这是我通过Win32 API建议SendKeys的罕见情况之一.Win32 Api可能最终甚至无法工作,如果API发生变化,SendKeys更有可能继续工作.例如,我们看到XP到Vista,FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle)由于Aero隐藏了windowTitle参数所需的Windows Captions ,因此API 现在几乎无用.一种解决方案是使用经典主题,没有多少人会接受,所以这是我不会指望Win32 apis做这个特殊事情而只是简单地使用SendKeys的原因之一.看这里:

在此输入图像描述

我不能得到任何这方面的东西再工作:https://bytes.com/topic/c-sharp/answers/262498-openfiledialog-how-select-files-coding,这是从微软的电子邮件DIST.

// Getting the handle of the ListBox in the OpenFileDialog dialog.
uint listviewHandle = FindWindowEx(dialogHandle, 0,
"SHELLDLL_DefView", "");

// Sending message to the ListBox to set the view to Thumbnails
//Icons=0x7029, List=0x702b, Details=0x702c, Thumbnails=0x702d,
Tiles=0x702e
SendMessage(listviewHandle, 0x0111/*WM_COMMAND*/, (uint)0x702d, 0);

// Sending message to the ListBox to select all items.
SendMessage(listviewHandle, 0x0111/*WM_COMMAND*/, (uint)0x00017021,
(uint)0);
Run Code Online (Sandbox Code Playgroud)