実際、笑う必要はありません。私には、あなたがこれをすでに正しい方法で行っているように思えます。デスクトップを所有していないので、デスクトップに直接描画しないでください。代わりに、所有している透明なフォームをオーバーレイし、その上に描画することでシミュレートする必要があります。透明なオーバーレイ フォームを所有しているため、その上に描画することは問題ありません。
しかし、それを超えて、値が実際に何をするのかを明確に理解せずに、値をランダムに試しているように思えます。それは、目を閉じてダーツを投げるようなものです。ヒット数はそれほど高くありません。
コードの機能を理解することから始めましょう。マジック値はメッセージに0x84
対応し、WM_NCHITTEST
Windows からウィンドウに送信され、そのウィンドウでのマウス クリックの処理方法を決定します。そのメッセージに応答してHT*
、リンクされたドキュメントに示されている値の 1 つを返信します。これらの値にはそれぞれ特定の意味があり、ドキュメントでも説明されています。例えば:
HTCAPTION
(値は 2) は、ウィンドウのクリックされた部分をウィンドウのキャプション/タイトル バーとして扱う必要があることを意味します。HTCAPTION
Windows を使用して、タイトル バーを使用して画面上でウィンドウをドラッグできることを知っているので、マウス クリックに応答して戻ることで、ウィンドウをドラッグ可能にすることは理にかなっています。これは、ボーダレス フォーム (つまり、タイトル バーのないフォーム) で使用され、移動できるようになっていることがわかります。
HTTRANSPARENT
(-1 の値を持つ) は、別の使用可能な値です。これはかなり単純です。ウィンドウが透明に見えるだけです。「気にしないで、ここに窓はないよ!」と言っているようなものです。マウス クリックは、あたかもそこにいないかのように、Z オーダーの下にあるウィンドウに単純に渡されます。
HTCLIENT
(値 1) は、ウィンドウのクライアント領域のどこかでクリックが発生した場合のデフォルトの結果です。すべてを正常に動作させたい場合は、これを返します (または単に既定のウィンドウ プロシージャを呼び出します)。この値を返すクリック イベントは、フレームワークによって通常どおり処理され、フォームのClick
イベントが発生するか、フォームにある子コントロールに渡されます。
したがって、描画していないときは、おそらく戻りたいと思うでしょう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);
}