WM_HELP 在启动 vtk 或 spy++ 时停止发送 运行
WM_HELP stops being send when vtk is started or spy++ is running
在我们的软件中,我们偶尔使用通过 SendMessage api 向控件发送 WM_HELP。通常 "HelpRequested" 事件随后会被触发(或在父层次结构中向上,直到事件处理程序被注册)。
我们包含了一个名为 "VTK" 的外部复杂 3d 可视化库,此后,此消息传递不再有效。在试图追查问题时,我使用 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" 的按钮。
当您在调试器中启动时,您每秒都会在输出 window 中看到 "HelpRequested called"。当您启动 Spy++ 时,仅此而已,只要启动,它就会停止!当关闭 spy++ 时,它会继续工作。每个人都对这种行为有解释吗? Spy++ 对我的应用程序做了什么?我希望相同的机制对 vtk 的相同问题负责(尽管只有进程内)。
当然,使用 win32 api SendMessage 似乎不适合 WinForms 应用程序,但我们现在没有时间重构所有这些东西,但我还是想了解这里发生了什么!
顺便说一句:用户 window 消息不受影响(WM_USER 到 0x7FFF),通过覆盖 WndProc 检查。 WM_HELP 也不会显示在 WndProc 中,而 spy++ 是 运行,顺便说一句。
问题是 HelpInfo.cbSize 的尺码错误。在 64 位模式下它是 40,在 32 位模式下它是 28。是的我应该使用 sizeof(),但这只允许在 "unsafe" 模式下。
但是 spy++ 或 VTK 到底是怎么干扰这个的?
在我们的软件中,我们偶尔使用通过 SendMessage api 向控件发送 WM_HELP。通常 "HelpRequested" 事件随后会被触发(或在父层次结构中向上,直到事件处理程序被注册)。
我们包含了一个名为 "VTK" 的外部复杂 3d 可视化库,此后,此消息传递不再有效。在试图追查问题时,我使用 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" 的按钮。
当您在调试器中启动时,您每秒都会在输出 window 中看到 "HelpRequested called"。当您启动 Spy++ 时,仅此而已,只要启动,它就会停止!当关闭 spy++ 时,它会继续工作。每个人都对这种行为有解释吗? Spy++ 对我的应用程序做了什么?我希望相同的机制对 vtk 的相同问题负责(尽管只有进程内)。 当然,使用 win32 api SendMessage 似乎不适合 WinForms 应用程序,但我们现在没有时间重构所有这些东西,但我还是想了解这里发生了什么! 顺便说一句:用户 window 消息不受影响(WM_USER 到 0x7FFF),通过覆盖 WndProc 检查。 WM_HELP 也不会显示在 WndProc 中,而 spy++ 是 运行,顺便说一句。
问题是 HelpInfo.cbSize 的尺码错误。在 64 位模式下它是 40,在 32 位模式下它是 28。是的我应该使用 sizeof(),但这只允许在 "unsafe" 模式下。 但是 spy++ 或 VTK 到底是怎么干扰这个的?