2015-08-15 65 views
0

我從微軟編寫的網站下載「Extensible Dialogs Source」(C#使用P/Invoke),以顯示如何將Windows Forms控件放入內部常用文件對話框之一。 (如:添加預覽功能)。 這個項目有測試客戶端代碼,它是打開一個對話框,一旦你點擊一張圖片,你就可以在對話框的右側預覽圖片。 測試客戶端代碼在中工作良好32位構建,但不在64位構建由FileOpenDialog生成的通知消息生成32位構建不生成64位

一些調試後,我發現這是因爲在64位的版本,從

[DllImport("ComDlg32.dll", CharSet = CharSet.Unicode)] 
    internal static extern bool GetOpenFileName(ref OpenFileName ofn); 

CDN_SELCHANGE通知消息不能被識別或不正確的在C#代碼處理。

// WM_NOTIFY - we're only interested in the CDN_SELCHANGE notification message 
// we grab the currently-selected filename and fire our event 
case WindowMessage.Notify: 
{ 
    IntPtr ipNotify = new IntPtr(lParam); 
    OfNotify ofNot = (OfNotify)Marshal.PtrToStructure(ipNotify, typeof(OfNotify)); 
    UInt16 code = ofNot.hdr.code; 
    if(code == CommonDlgNotification.SelChange) 
    { 
     // This is the first time we can rely on the presence of the content panel 
     // Resize the content and user-supplied panels to fit nicely 
     FindAndResizePanels(hWnd); 

     // get the newly-selected path 
     IntPtr hWndParent = NativeMethods.GetParent(hWnd); 
     StringBuilder pathBuffer = new StringBuilder(_MAX_PATH); 
     UInt32 ret = NativeMethods.SendMessage(hWndParent, CommonDlgMessage.GetFilePath, _MAX_PATH, pathBuffer); 
     string path = pathBuffer.ToString(); 

     // copy the string into the path buffer 
     UnicodeEncoding ue = new UnicodeEncoding(); 
     byte[] pathBytes = ue.GetBytes(path); 
     Marshal.Copy(pathBytes, 0, _fileNameBuffer, pathBytes.Length); 

     // fire selection-changed event 
     if(SelectionChanged != null) SelectionChanged(path); 
    } 
    return IntPtr.Zero; 
} 

即使我在打開文件對話框選擇不同的文件,ofNot.hdr.code始終爲0,其結果是,應用程序從未if(code == CommonDlgNotification.SelChange)後跑入代碼塊。 任何人都可以使這個測試樣本工作在64位構建?提前致謝!

示例代碼下載鏈接:ExtensibleDialogsSource.msi

+0

這是擴展文件對話框的錯誤方法。使用IFileDialogCustomize。 –

+0

我的水晶球說OfNotify宣言是錯誤的。例如,NMHDR.idFrom很容易犯錯,應該是IntPtr。它對於NMHDR.code是可見的,它不是UInt16。 –

+0

是的,你是對的!非常感謝! –

回答

1

感謝所有美好的答覆,我想出瞭解決方案。某些結構定義錯誤當它適用於64位應用程序。 在NativeMethods.cs(寫由微軟可能不定位到64位應用程序),它定義

/// <summary> 
/// Part of the notification messages sent by the common dialogs 
/// </summary> 
[StructLayout(LayoutKind.Explicit)] 
internal struct NMHDR 
{ 
    [FieldOffset(0)] public IntPtr hWndFrom; 
    [FieldOffset(4)] public UInt16 idFrom; 
    [FieldOffset(8)] public UInt16 code; 
}; 

/// <summary> 
/// Part of the notification messages sent by the common dialogs 
/// </summary> 
[StructLayout(LayoutKind.Explicit)] 
internal struct OfNotify 
{ 
    [FieldOffset(0)] public NMHDR hdr; 
    [FieldOffset(12)] public IntPtr ipOfn; 
    [FieldOffset(16)] public IntPtr ipFile; 
}; 

由於IntPtr的的大小被改變從4字節到8個字節。 所以我們需要重新定義結構

[StructLayout(LayoutKind.Explicit)] 
internal struct NMHDR 
{ 
    [FieldOffset(0)] 
    public IntPtr hWndFrom; 
    [FieldOffset(8)] 
    public IntPtr idFrom; 
    [FieldOffset(16)] 
    public UInt16 code; 
}; 

/// <summary> 
/// Part of the notification messages sent by the common dialogs 
/// </summary> 
[StructLayout(LayoutKind.Explicit)] 
internal struct OfNotify 
{ 
    [FieldOffset(0)] 
    public NMHDR hdr; 
    [FieldOffset(20)] 
    public IntPtr ipOfn; 
    [FieldOffset(28)] 
    public IntPtr ipFile; 
}; 

現在它適用於64位應用程序。

從我的角度來看,如果可能的話,我們最好使用.Net庫,這可以使生活更輕鬆。

0

NMHDR idFrom不是IntPtr,而是MSDN2005中的UINT。稍後將其記錄爲UINT_PTR ...