使用 GetOpenFileName 代替 OpenFileDialog

发布于 2025-01-01 13:33:39 字数 2374 浏览 0 评论 0原文

我无法在我的应用程序中使用 OpenFileDialog。

作为替代方案,我使用 GetOpenFileName() 方法:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace Reader
{
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public class OpenFileName
    {
        public int lstructSize;
        public IntPtr hwndOwner;
        public IntPtr hInstance;
        public string lpstrFilter = null;
        public string lpstrCustomFilter = null;
        public int lMaxCustomFilter;
        public int lFilterIndex;
        public string lpstrFile = null;
        public int lMaxFile = 0;
        public string lpstrFileTitle = null;
        public int lMaxFileTitle = 0;
        public string lpstrInitialDir = null;
        public string lpstrTitle = null;
        public int lFlags;
        public ushort nFileOffset;
        public ushort nFileExtension;
        public string lpstrDefExt = null;
        public int lCustData;
        public int lpfHook;
        public int lpTemplateName;
    }

    public class OpenDialog
    {
        [DllImport("Comdlg32.dll",CharSet = CharSet.Auto)]
        public static extern bool GetOpenFileName([In, Out] OpenFileName ofn);
    }
}

然后在按钮的 OnClick 事件中使用它,如下所示:

OpenFileName qofn = new OpenFileName();

qofn.lstructSize = Marshal.SizeOf(qofn);
qofn.lpstrFile = "";
qofn.lMaxFile = 256;
qofn.lpstrFileTitle = "";
qofn.lMaxFileTitle = 64;
qofn.hInstance = this.Handle;
source.Text = "Wait...";
if (OpenDialog.GetOpenFileName(qofn))
{
    MessageBox.Show("ofn.file: " + qofn. lpstrFile );
}

当应用程序运行并单击按钮并且我尝试打开文件时,会发生以下情况:

第一次尝试:

它返回我的文件的路径,但不是 c:\dira\dirb\dirc\filename.ext 我有 c:\dira\dirb\dircfilename.ext 文件名前没有“\”

第二次尝试

一切正常

下一步: 存在随机崩溃,例如随机访问冲突,或 GUI 冻结,并且即使在任务管理器中也无法终止应用程序进程,或其他错误。

通常,对话框会工作 2-3 次,然后应用程序就会永久崩溃。

我的代码有什么问题吗?

编辑:

我无法使用OpenFileDialog。我正在使用 WinPE 4.0(Windows 评估和部署工具包 ADK)。当我尝试 OpenFileDIalog 时,它会抛出运行时错误 80040111。可能是因为核心不支持(就像Server Core不支持OpenFileDialog,错误是一样的)。可能在 WinPE 4.0 上,他们在记事本等应用程序中使用 GetOpenFileName。这对他们有用。

I can't use OpenFileDialog in my application.

As an alternative I use GetOpenFileName() method:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace Reader
{
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public class OpenFileName
    {
        public int lstructSize;
        public IntPtr hwndOwner;
        public IntPtr hInstance;
        public string lpstrFilter = null;
        public string lpstrCustomFilter = null;
        public int lMaxCustomFilter;
        public int lFilterIndex;
        public string lpstrFile = null;
        public int lMaxFile = 0;
        public string lpstrFileTitle = null;
        public int lMaxFileTitle = 0;
        public string lpstrInitialDir = null;
        public string lpstrTitle = null;
        public int lFlags;
        public ushort nFileOffset;
        public ushort nFileExtension;
        public string lpstrDefExt = null;
        public int lCustData;
        public int lpfHook;
        public int lpTemplateName;
    }

    public class OpenDialog
    {
        [DllImport("Comdlg32.dll",CharSet = CharSet.Auto)]
        public static extern bool GetOpenFileName([In, Out] OpenFileName ofn);
    }
}

And then use it in OnClick event of a button like this:

OpenFileName qofn = new OpenFileName();

qofn.lstructSize = Marshal.SizeOf(qofn);
qofn.lpstrFile = "";
qofn.lMaxFile = 256;
qofn.lpstrFileTitle = "";
qofn.lMaxFileTitle = 64;
qofn.hInstance = this.Handle;
source.Text = "Wait...";
if (OpenDialog.GetOpenFileName(qofn))
{
    MessageBox.Show("ofn.file: " + qofn. lpstrFile );
}

When application runs and button is clicked and I try to open file this is what happens:

1st try:

it returns the path to my file, but instead of
c:\dira\dirb\dirc\filename.ext
I have
c:\dira\dirb\dircfilename.ext
without '\' before the name of the file

2nd try

Everything is OK

next:
there are random crashes, e.g. random access violation, or GUI freezes and application's process can't be kiled even in task manager, or other errors.

Usually dialog works 2-3 times before application crashes for good.

What is wrong with my code?

EDIT:

I can't use OpenFileDialog. I'm using WinPE 4.0 (Windows Assessment and Deployment Kit ADK). When I try OpenFileDIalog, it throws run time error 80040111. It's probably because the core is not supported (just like Server Core doesn't support OpenFileDialog, the error's the same). Probably on WinPE 4.0 they use GetOpenFileName in applications such as notepad. And it works for them.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

能怎样 2025-01-08 13:33:39

好的,我找到了这个微软示例并且它有效:

// Copyright
// Microsoft Corporation
// All rights reserved

// OpenFileDlg.cs

using System;
using System.Text;
using System.Runtime.InteropServices;

/*
typedef struct tagOFN { 
  DWORD         lStructSize; 
  HWND          hwndOwner; 
  HINSTANCE     hInstance; 
  LPCTSTR       lpstrFilter; 
  LPTSTR        lpstrCustomFilter; 
  DWORD         nMaxCustFilter; 
  DWORD         nFilterIndex; 
  LPTSTR        lpstrFile; 
  DWORD         nMaxFile; 
  LPTSTR        lpstrFileTitle; 
  DWORD         nMaxFileTitle; 
  LPCTSTR       lpstrInitialDir; 
  LPCTSTR       lpstrTitle; 
  DWORD         Flags; 
  WORD          nFileOffset; 
  WORD          nFileExtension; 
  LPCTSTR       lpstrDefExt; 
  LPARAM        lCustData; 
  LPOFNHOOKPROC lpfnHook; 
  LPCTSTR       lpTemplateName; 
#if (_WIN32_WINNT >= 0x0500)
  void *        pvReserved;
  DWORD         dwReserved;
  DWORD         FlagsEx;
#endif // (_WIN32_WINNT >= 0x0500)
} OPENFILENAME, *LPOPENFILENAME; 
*/

[ StructLayout( LayoutKind.Sequential, CharSet=CharSet.Auto )]  
public class OpenFileName 
{
    public int      structSize = 0;
    public IntPtr   dlgOwner = IntPtr.Zero; 
    public IntPtr   instance = IntPtr.Zero;

    public String   filter = null;
    public String   customFilter = null;
    public int      maxCustFilter = 0;
    public int      filterIndex = 0;

    public String   file = null;
    public int      maxFile = 0;

    public String   fileTitle = null;
    public int      maxFileTitle = 0;

    public String   initialDir = null;

    public String   title = null;   

    public int      flags = 0; 
    public short    fileOffset = 0;
    public short    fileExtension = 0;

    public String   defExt = null; 

    public IntPtr   custData = IntPtr.Zero;  
    public IntPtr   hook = IntPtr.Zero;  

    public String   templateName = null; 

    public IntPtr   reservedPtr = IntPtr.Zero; 
    public int      reservedInt = 0;
    public int      flagsEx = 0;
}

public class LibWrap
{
    //BOOL GetOpenFileName(LPOPENFILENAME lpofn);

    [ DllImport( "Comdlg32.dll", CharSet=CharSet.Auto )]                
    public static extern bool GetOpenFileName([ In, Out ] OpenFileName ofn );   
}

public class App
{
    public static void Main()
    {
        OpenFileName ofn = new OpenFileName();

        ofn.structSize = Marshal.SizeOf( ofn );

        ofn.filter = "Log files\0*.log\0Batch files\0*.bat\0";

        ofn.file = new String( new char[ 256 ]);
        ofn.maxFile = ofn.file.Length;

        ofn.fileTitle = new String( new char[ 64 ]);
        ofn.maxFileTitle = ofn.fileTitle.Length;    

        ofn.initialDir = "C:\\";
        ofn.title = "Open file called using platform invoke...";
        ofn.defExt = "txt";

        if( LibWrap.GetOpenFileName( ofn ))
        {
            Console.WriteLine( "Selected file with full path: {0}", ofn.file );
            Console.WriteLine( "Selected file name: {0}", ofn.fileTitle );
            Console.WriteLine( "Offset from file name: {0}", ofn.fileOffset );
            Console.WriteLine( "Offset from file extension: {0}", ofn.fileExtension );
        }
    }
}

OK, I found this microsoft sample and it works:

// Copyright
// Microsoft Corporation
// All rights reserved

// OpenFileDlg.cs

using System;
using System.Text;
using System.Runtime.InteropServices;

/*
typedef struct tagOFN { 
  DWORD         lStructSize; 
  HWND          hwndOwner; 
  HINSTANCE     hInstance; 
  LPCTSTR       lpstrFilter; 
  LPTSTR        lpstrCustomFilter; 
  DWORD         nMaxCustFilter; 
  DWORD         nFilterIndex; 
  LPTSTR        lpstrFile; 
  DWORD         nMaxFile; 
  LPTSTR        lpstrFileTitle; 
  DWORD         nMaxFileTitle; 
  LPCTSTR       lpstrInitialDir; 
  LPCTSTR       lpstrTitle; 
  DWORD         Flags; 
  WORD          nFileOffset; 
  WORD          nFileExtension; 
  LPCTSTR       lpstrDefExt; 
  LPARAM        lCustData; 
  LPOFNHOOKPROC lpfnHook; 
  LPCTSTR       lpTemplateName; 
#if (_WIN32_WINNT >= 0x0500)
  void *        pvReserved;
  DWORD         dwReserved;
  DWORD         FlagsEx;
#endif // (_WIN32_WINNT >= 0x0500)
} OPENFILENAME, *LPOPENFILENAME; 
*/

[ StructLayout( LayoutKind.Sequential, CharSet=CharSet.Auto )]  
public class OpenFileName 
{
    public int      structSize = 0;
    public IntPtr   dlgOwner = IntPtr.Zero; 
    public IntPtr   instance = IntPtr.Zero;

    public String   filter = null;
    public String   customFilter = null;
    public int      maxCustFilter = 0;
    public int      filterIndex = 0;

    public String   file = null;
    public int      maxFile = 0;

    public String   fileTitle = null;
    public int      maxFileTitle = 0;

    public String   initialDir = null;

    public String   title = null;   

    public int      flags = 0; 
    public short    fileOffset = 0;
    public short    fileExtension = 0;

    public String   defExt = null; 

    public IntPtr   custData = IntPtr.Zero;  
    public IntPtr   hook = IntPtr.Zero;  

    public String   templateName = null; 

    public IntPtr   reservedPtr = IntPtr.Zero; 
    public int      reservedInt = 0;
    public int      flagsEx = 0;
}

public class LibWrap
{
    //BOOL GetOpenFileName(LPOPENFILENAME lpofn);

    [ DllImport( "Comdlg32.dll", CharSet=CharSet.Auto )]                
    public static extern bool GetOpenFileName([ In, Out ] OpenFileName ofn );   
}

public class App
{
    public static void Main()
    {
        OpenFileName ofn = new OpenFileName();

        ofn.structSize = Marshal.SizeOf( ofn );

        ofn.filter = "Log files\0*.log\0Batch files\0*.bat\0";

        ofn.file = new String( new char[ 256 ]);
        ofn.maxFile = ofn.file.Length;

        ofn.fileTitle = new String( new char[ 64 ]);
        ofn.maxFileTitle = ofn.fileTitle.Length;    

        ofn.initialDir = "C:\\";
        ofn.title = "Open file called using platform invoke...";
        ofn.defExt = "txt";

        if( LibWrap.GetOpenFileName( ofn ))
        {
            Console.WriteLine( "Selected file with full path: {0}", ofn.file );
            Console.WriteLine( "Selected file name: {0}", ofn.fileTitle );
            Console.WriteLine( "Offset from file name: {0}", ofn.fileOffset );
            Console.WriteLine( "Offset from file extension: {0}", ofn.fileExtension );
        }
    }
}
森林迷了鹿 2025-01-08 13:33:39

OpenFileDlg 示例(如 Arie 的答案中使用的示例)可在 这里

该页面有 C#、C++ 和 VB 示例。我已经在 WinPE 5.1 中测试了 VB 示例,除了文件类型过滤器之外,它运行良好;它始终显示所有文件类型。

我惊讶地发现,即使在我的 WinPE 映像中安装了 WinPE-NetFX 包,OpenFileDialog 在 WinPE 中也不可用,并且尝试使用它会引发问题中引用的错误。这些使用非托管 GetOpenFileName 函数的 OpenFileDlg 示例是我能够找到的在 WinPE 中使用的唯一替代方案。

The OpenFileDlg examples (like the one used in Arie's answer) are available Here.

The page has C#, C++, and VB examples. I have tested the VB example in WinPE 5.1 and it works great with the exception of the file type filter; It shows all file types all the time.

I was surprised to find that even with the WinPE-NetFX package installed in my WinPE image OpenFileDialog is not available in WinPE and trying to use it throws the error referenced in the question. These OpenFileDlg examples, which use the unmanaged GetOpenFileName function, are the only alternative that I have been able to find for use in WinPE.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文