实际上,没必要笑——在我看来,你已经以正确的方式做这件事了。由于您不拥有桌面,因此不应直接在其上绘图。相反,您需要通过覆盖您拥有的透明表单来模拟它,然后在其上进行绘制。因为你拥有透明的覆盖表格,所以在上面画画是没有问题的。
但除此之外,听起来您只是在随机尝试值,而没有清楚地了解它们的实际作用。这就像闭着眼睛扔飞镖一样。你不会有很高的命中数。
让我们从了解您的代码的作用开始。魔术值0x84对应于WM_NCHITTEST消息,该消息由 Windows 发送到窗口以确定应如何处理该窗口上的鼠标单击。作为对该消息的响应,您使用HT*链接文档中给出的值之一进行回复。这些值中的每一个都有特定的含义,文档中也对此进行了说明。例如:
HTCAPTION(其值为 2)意味着窗口的单击部分应被视为窗口的标题/标题栏。您从使用 Windows 中知道,您可以使用标题栏在屏幕上拖动窗口,因此HTCAPTION响应鼠标单击返回将允许您的窗口可拖动是有道理的。您将看到这用于无边界表单(即没有标题栏的表单)以允许它们可移动。
HTTRANSPARENT(其值为 -1)是另一个可用值。这个很简单。它只是让你的窗口看起来透明。这就像在说“别介意我,这里没有窗户!” 鼠标点击会被简单地传递到按 Z 顺序位于您下方的窗口,就好像您不在那里一样。
HTCLIENT(值为 1)是单击发生在窗口客户区的任何位置时的默认结果。当您希望一切正常工作时,您将返回它(或简单地调用默认窗口过程)。返回此值的单击事件将继续由框架正常处理,引发表单的Click事件,或传递给位于表单上的子控件。
所以,当你不画画的时候,你可能想要 return HTTRANSPARENT。在绘图时,您可能希望返回HTCLIENT,以便您的绘图代码可以看到鼠标事件并绘制结果。
修复您的代码,然后:
// Code for allowing clicking through of the form
protected override void WndProc(ref Message m)
{
const uint WM_NCHITTEST = 0x84;
const int HTTRANSPARENT = -1;
const int HTCLIENT = 1;
const int HTCAPTION = 2;
// ... or define an enum with all the values
if (m.Msg == WM_NCHITTEST)
{
// If it's the message we want, handle it.
if (penMode)
{
// If we're drawing, we want to see mouse events like normal.
m.Result = new IntPtr(HTCLIENT);
}
else
{
// Otherwise, we want to pass mouse events on to the desktop,
// as if we were not even here.
m.Result = new IntPtr(HTTRANSPARENT);
}
return; // bail out because we've handled the message
}
// Otherwise, call the base class implementation for default processing.
base.WndProc(ref m);
}