首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >CDN_SELCHANGE通知消息由FileOpenDialog为32位构建生成而不是为64位生成生成

CDN_SELCHANGE通知消息由FileOpenDialog为32位构建生成而不是为64位生成生成
EN

Stack Overflow用户
提问于 2015-08-15 10:19:51
回答 2查看 257关注 0票数 0

我从微软编写的网站下载"Extensible“(使用P/Invoke的C#),演示如何将Windows控件放置在一个常见的文件对话框中。(例如:添加预览功能)。此项目具有测试客户端代码,即打开对话框,一旦单击图片,就可以在对话框的右侧预览图片。测试客户端代码在32位构建中运行良好,但在64位构建中不工作。

经过一些调试后,我发现这是因为在64位构建中,CDN_SELCHANGE通知消息来自

代码语言:javascript
复制
    [DllImport("ComDlg32.dll", CharSet = CharSet.Unicode)]
    internal static extern bool GetOpenFileName( ref OpenFileName ofn );

在c#代码中无法识别或无法正确处理。

代码语言:javascript
复制
// 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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-10-09 01:41:46

感谢所有的回复,我想出了解决办法。当结构定义应用于64位应用程序时,它的定义是错误的。在NativeMethods.cs (由微软编写,可能不针对64位应用程序)中,它定义了

代码语言:javascript
复制
/// <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重新定义结构

代码语言:javascript
复制
[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库,这样可以使生活更轻松。

票数 1
EN

Stack Overflow用户

发布于 2015-11-30 13:24:26

NMHDR idFrom不是IntPtr,而是MSDN2005中的UINT。后来被记录为UINT_PTR..。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32023755

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档