2011-04-20 97 views
6

我在我的.NET 4 WPF應用程序中使用WPF OpenFileDialog和SaveFileDialog。我使用Filter屬性來允許用戶設置不同的文件過濾器。在.NET 4中,它使用Windows Vista引入的本機文件對話框(如果可能)。在Vista/Windows 7隱藏擴展WPF FileDialog.Filter

但是,這些對話框顯示組成文件過濾器的擴展名。由於其中一些使用了相當多的擴展,這是非常難看的。

例如,我有一個篩選器Image files|*.bmp;*.dib;*.jpg;*.jpeg;*.jpe;*.jfif;*.gif;*.tif;*.tiff;*.png;*.ico|All files|*.*,在對話框中顯示爲Image files (*.bmp;*.dib;*.jpg;*.jpeg;*.jpe;*.jfif;*.gif;*.tif;*.tiff;*.png;*.ico)。括號中的所有內容都會自動添加,即根據過濾器字符串,它應顯示Image files。但是在某個地方添加了括號中的內容。我試着用Reflector來查看代碼是否在某處完成,但很快就放棄了,因爲它相當複雜。

啓動Paint,例如,我可以看到可以使用這些文件對話框而沒有括號中的內容,即它顯示Image files

有沒有人知道這個「功能」的解決方法?

+1

我從來沒有見過在過濾元件會自動添加行爲。什麼是您使用的OpenFileDialog的完整名稱空間? – 2011-04-20 15:39:47

+0

lol只是在Windows 7的VS 2010中試過這個,現在我得到了相同的結果... – 2011-04-20 15:46:13

+0

我正在使用Microsoft.Win32.OpenFileFilter。沒有自動添加過濾元素。相反,括號中的內容會自動添加。 – 2011-04-20 15:46:18

回答

5

你在正確的軌道上。有兩種方法可以顯示打開的文件對話框。較新的方法使用IFileOpenDialog(其延伸IFileDialog)。使用這種方法,過濾器描述和文件規範是使用COMDLG_FILTERSPEC結構定義的。這使得分開的領域更加自然。

如果您想使用此方法從組合框中刪除文件規格,那麼您必須添加自己的自定義控件或在對話框上操作組合框控件。雖然這會變得混亂,但應該是可行的。

舊派方法使用GetOpenFileNameOPENFILENAME結構。這一招的訣竅是,它可以顯示一箇舊的外觀或新的外觀對話框。外觀由OPENFILENAME結構中的設置決定,如here所述。

WinForms OpenFileDialog的問題在於,它們在AutoUpgradeEnabled爲true時使用IFileOpenDialog,在AutoUpgradeEnabled爲false時使用舊外觀時使用GetOpenFileName。

WPF版本不給你一個選擇,但仍然使用與WinForms相同的邏輯,但根據需要自動執行。這對於.NET 4中的WPF來說是正確的,在以前的版本中,它只會以舊的外觀使用GetOpenFileName。

繪畫最有可能使用GetOpenFileName以新外觀。這裏是一個C#示例:

private delegate IntPtr WndProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam); 

private const int OFN_ALLOWMULTISELECT = 0x00000200; 
private const int OFN_CREATEPROMPT = 0x00002000; 
private const int OFN_DONTADDTORECENT = 0x02000000; 
private const int OFN_ENABLEHOOK = 0x00000020; 
private const int OFN_ENABLEINCLUDENOTIFY = 0x00400000; 
private const int OFN_ENABLESIZING = 0x00800000; 
private const int OFN_ENABLETEMPLATE = 0x00000040; 
private const int OFN_ENABLETEMPLATEHANDLE = 0x00000080; 
private const int OFN_EXPLORER = 0x00080000; 
private const int OFN_EXTENSIONDIFFERENT = 0x00000400; 
private const int OFN_FILEMUSTEXIST = 0x00001000; 
private const int OFN_FORCESHOWHIDDEN = 0x10000000; 
private const int OFN_HIDEREADONLY = 0x00000004; 
private const int OFN_LONGNAMES = 0x00200000; 
private const int OFN_NOCHANGEDIR = 0x00000008; 
private const int OFN_NODEREFERENCELINKS = 0x00100000; 
private const int OFN_NOLONGNAMES = 0x00040000; 
private const int OFN_NONETWORKBUTTON = 0x00020000; 
private const int OFN_NOREADONLYRETURN = 0x00008000; 
private const int OFN_NOTESTFILECREATE = 0x00010000; 
private const int OFN_NOVALIDATE = 0x00000100; 
private const int OFN_OVERWRITEPROMPT = 0x00000002; 
private const int OFN_PATHMUSTEXIST = 0x00000800; 
private const int OFN_READONLY = 0x00000001; 
private const int OFN_SHAREAWARE = 0x00004000; 
private const int OFN_SHOWHELP = 0x00000010; 

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 
public class OPENFILENAME_I { 
    public int lStructSize; 
    public IntPtr hwndOwner; 
    public IntPtr hInstance; 
    public string lpstrFilter; 
    public IntPtr lpstrCustomFilter; 
    public int nMaxCustFilter; 
    public int nFilterIndex; 
    public IntPtr lpstrFile; 
    public int nMaxFile = 260; 
    public IntPtr lpstrFileTitle; 
    public int nMaxFileTitle = 260; 
    public string lpstrInitialDir; 
    public string lpstrTitle; 
    public int Flags; 
    public short nFileOffset; 
    public short nFileExtension; 
    public string lpstrDefExt; 
    public IntPtr lCustData; 
    public WndProc lpfnHook; 
    public string lpTemplateName; 
    public IntPtr pvReserved; 
    public int dwReserved; 
    public int FlagsEx; 
} 

[DllImport("comdlg32.dll", CharSet = CharSet.Unicode, SetLastError = true)] 
private static extern bool GetOpenFileName([In, Out] OPENFILENAME_I ofn); 

private void ShowOpenFileDialog() { 
    OPENFILENAME_I ofn = new OPENFILENAME_I(); 
    ofn.lStructSize = Marshal.SizeOf(typeof(OPENFILENAME_I)); 
    ofn.lpstrFilter = "Text Files (*.txt)\0*.txt\0All Files\0*.*\0\0"; 
    ofn.nFilterIndex = 0; 
    //ofn.Flags = OFN_EXPLORER | OFN_ENABLEHOOK | OFN_ENABLESIZING | OFN_NODEREFERENCELINKS | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; 
    ofn.Flags = OFN_ENABLESIZING | OFN_NODEREFERENCELINKS | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; 
    GetOpenFileName(ofn); 
} 

您可以嘗試重新加入OFN_EXPLORER和/或OFN_ENABLEHOOK標誌,也將恢復到老樣子。但按原樣,上面的代碼將顯示一個打開的文件對話框,所有文件都不顯示它的文件規範。

+0

非常感謝。我想我會跳過這樣做,因爲它會導致大量的工作,對於大多數用戶不會注意到的小改進... – 2011-04-21 13:58:20

1

經過一堆測試後,我得到以下結果:WPF中的FileDialog調用本地IFileDialog::SetFileTypes方法,並使用過濾器定義的字符串。根據Windows選項隱藏已知文件類型的擴展名(在Windows資源管理器文件夾設置中),擴展名會自動添加或不添加。

現在唯一的問題是,Paint如何在其打開的文件對話框中不能顯示「圖像文件」的擴展名。