我从微软编写的网站下载"Extensible“(使用P/Invoke的C#),演示如何将Windows控件放置在一个常见的文件对话框中。(例如:添加预览功能)。此项目具有测试客户端代码,即打开对话框,一旦单击图片,就可以在对话框的右侧预览图片。测试客户端代码在32位构建中运行良好,但在64位构建中不工作。
经过一些调试后,我发现这是因为在64位构建中,CDN_SELCHANGE通知消息来自
[DllImport("ComDlg32.dll", CharSet = CharSet.Unicode)]
internal static extern bool GetOpenFileName( ref OpenFileName ofn );在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;
}即使我在OpenFileDialog中选择了不同的文件,ofNot.hdr.code始终是0,因此,应用程序在if( code == CommonDlgNotification.SelChange )之后永远不会遇到代码块。有人能让这个测试样本在64位构建中工作吗?提前感谢!
示例代码下载链接:ExtensibleDialogsSource.msi
发布于 2015-10-09 01:41:46
感谢所有的回复,我想出了解决办法。当结构定义应用于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字节,所以我们需要IntPtr重新定义结构。
[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库,这样可以使生活更轻松。
发布于 2015-11-30 13:24:26
NMHDR idFrom不是IntPtr,而是MSDN2005中的UINT。后来被记录为UINT_PTR..。
https://stackoverflow.com/questions/32023755
复制相似问题