1

カスタム コントロールで理解したいことがあります。WM_NCCALCSIZE を処理して、クライアント領域をウィンドウ全体に設定します。つまり、非クライアント領域はありません。WM_NCPAINT を受信しないことを期待していましたが、ウィンドウ サイズが変更されるたびに受信します。ここに私のWndProcコードがあります:

if (m.Msg == Win32Calls.WM_NCPAINT)
{
    // I don't know why WM_NCPAINT is sent when WM_NCCALCSIZE has stated that there is no client area, so here is my workaround to stop processing here
    if (Bounds.Size == ClientSize)
        return;

    // Draw borders if any

    if (handled)
        return;
}
else if (m.Msg == Win32Calls.WM_NCCALCSIZE)
{
    if (m.WParam != IntPtr.Zero)
    {
        Win32Calls.NCCALCSIZE_PARAMS csp;

        csp = (Win32Calls.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(Win32Calls.NCCALCSIZE_PARAMS));
        Rectangle rect = new Rectangle(csp.rgrc0.Left, csp.rgrc0.Top,
            csp.rgrc0.Right - csp.rgrc0.Left, csp.rgrc0.Bottom - csp.rgrc0.Top);

        _drawManager.NcCalcSize(ref rect);

        csp.rgrc0.Left = rect.X;
        csp.rgrc0.Right = rect.X + rect.Width;
        csp.rgrc0.Top = rect.Y;
        csp.rgrc0.Bottom = rect.Y + rect.Height;
        Marshal.StructureToPtr(csp, m.LParam, false);
    }
}

そのため、サイズ変更が発生したときに確認したところ、WM_NCCALCSIZE が正しく受信され、_drawManager.NcCalcSize は「rect」を変更しません。次に、WM_NCPAINT が受信され、境界とクライアント rect を比較して、非クライアント ペインティングが発生するかどうかを確認する必要があります。 . これは正常ですか?

4

1 に答える 1

0

私の推測では、それは

1) Windows がこの方法でそれを行うのはより簡単で (境界線が欠落しているという特別なケースはありません)、それを送信しないことの利点はわずかなパフォーマンスの向上にすぎません。
2) 一部のプログラムでは、ハンドラーでの処理が多すぎるためにメッセージを送信する必要があるため、現在は変更できません。Raymond Chen のブログを読めば、それが Windows API チームにとっていかに重要であるかがわかるでしょう。

于 2010-11-11T20:14:22.007 に答える