在我们的软件中,我们偶尔会使用SendMessage api将WM_HELP发送到控件。通常,然后触发“HelpRequested”事件(或在父层次结构中向上,直到注册事件处理程序)。
我们包含了一个名为“VTK”的外部复杂三维可视化库,之后,此消息传递不再起作用。在尝试追踪问题时,我使用Spy ++来查看消息是否显示在那里,并意识到运行spy ++会产生同样的问题! (也没有任何vtk的东西)。它可以用这个小程序显示:
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace TestHelp
{
public partial class Form1 : Form
{
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
struct HelpInfo
{
public uint cbSize;
public int iContextType;
public int iCtrlID;
public int hItemHandle;
public int dwContextID;
public int MouseX;
public int MouseY;
}
[DllImport("user32.DLL", EntryPoint = "SendMessage", SetLastError = true)]
private static extern int SendHelpMessage(int hWnd, uint Msg, uint wparam, ref HelpInfo helpinfo);
public static void RaiseHelp(Control ctrl)
{
HelpInfo helpInfo = new HelpInfo
{
cbSize = 48,
iContextType = 1,
iCtrlID = 0,
hItemHandle = ctrl.Handle.ToInt32(),
dwContextID = 0,
MouseX = 10,
MouseY = 10,
};
var res = SendHelpMessage(ctrl.Handle.ToInt32(), 0x053, 0, ref helpInfo);
Debug.WriteLine($"SendMessage returns:{res}");
}
public Form1()
{
InitializeComponent();
button1.HelpRequested += (sender, hlpevent) => { Trace.WriteLine("HelpRequested called"); };
timer = new Timer() {Interval = 1000, Enabled = true};
timer.Tick += (sender, args) => RaiseHelp(button1);
}
private Timer timer;
}
}
表单只包含一个名为“button1”的按钮。
当您在调试器中启动时,您会在“输出”窗口中看到“每次调用HelpRequested”。当你启动Spy ++时,仅此而已,它就会停止!当关闭spy ++时,它会继续工作。每个人都对这种行为有解释吗?什么是Spy ++对我的应用程序做什么?我希望同样的机制能够解决与vtk相同的问题(尽管只在进程中)。 当然,使用win32 api SendMessage似乎不适合WinForms应用程序,但我们现在没有时间重构所有这些东西,但我仍然想了解这里发生了什么! 顺便说一句:用户窗口消息不受影响(WM_USER到0x7FFF),通过覆盖WndProc进行检查。当spy ++正在运行时,WM_HELP也没有在WndProc中显示,顺便说一句。
答案 0 :(得分:0)
HelpInfo.cbSize的大小问题错误。在64位模式下,它是40,在32位,它是28.是的我应该使用sizeof(),但这只允许在"不安全"模式。 但是地狱间谍++或VTK如何干扰这个呢?