3

ガラス フレームをクライアント領域に拡張するためにウィンドウに設定できる添付プロパティを作成しました ( DwmExtendFrameIntoClientAreaAPI を使用)。ほとんどの場合、問題なく動作します。ウィンドウをボーダレスにしたいので、ウィンドウに次の属性を設定します。

    WindowStyle="None"
    ResizeMode="NoResize"
    Background="Transparent"
    u:WinUtil.EnableGlass="True"
    ShowInTaskbar="False"

しかし、これらの属性では、ガラスはまったく表示されません。ウィンドウの背景が透明になっているだけです。に設定ResizeModeするCanResizeと、ガラスが表示されますが、ウィンドウのサイズを変更したくありません。

これは、非クライアント フレームをクライアント領域に拡張することでガラス効果が得られることが原因であると思われWindowStyle = NoneますResizeMode = NoResize。サイズ変更を有効にすると、ウィンドウの周りにフレームが作成されるため、フレームを拡張できます。

適切な WS_* ビットを設定することで、枠線が細く、タイトル バーがなく、サイズ変更できないウィンドウを作成できるはずですが、どのビットが正確かはわかりません。

だから私の質問は:

  1. 目的の外観と動作を実現するには、どのスタイル ビットを設定または設定解除する必要がありますか?
  2. ウィンドウのスタイル ビットを初期化するにはどうすればよいですか? Window クラスには、Windows Forms プロパティのようなものはないようですCreateParams...ハンドルが作成された後にこれらのビットを設定してもよろしいですか?
  3. 質問 2 への回答となるクラスを見つけましたHwndSourceが、Win32 の専門家でない場合、使用するのは少し複雑に思えます... 私の問題に対する賢明な解決策でしょうか?

どんなアドバイスでも大歓迎です

4

2 に答える 2

5

DwmEnableBlurBehindWindowを使用してみましたか? これにより、ウィンドウのクライアント領域の特定の部分を透明にすることができます。

于 2009-08-24T20:01:01.463 に答える
4

ガラスボーダー(タイトルバーなし、サイズ変更不可)だけを表示したいウィンドウがあり、あなたと同じ問題が発生しました。ウィンドウのスタイルを設定するだけでは、これを実現することはできません。私の解決策は、ResizeMode="CanResize"とWindowStyle="None"を設定してから、WM_NCHITTESTイベントを処理して、サイズ変更可能な境界線ヒットをサイズ変更不可能な境界線ヒットに変換することでした。また、ウィンドウのスタイルを変更して、最大化と最小化(Windowsショートカットを使用)とシステムメニューを無効にする必要がありました。

private void Window_SourceInitialized(object sender, EventArgs e)
{
    System.Windows.Interop.HwndSource source = (System.Windows.Interop.HwndSource)PresentationSource.FromVisual(this);
    source.AddHook(new System.Windows.Interop.HwndSourceHook(HwndSourceHook));

    IntPtr hWnd = new System.Windows.Interop.WindowInteropHelper(this).Handle;
    IntPtr flags = GetWindowLongPtr(hWnd, -16 /*GWL_STYLE*/);
    SetWindowLongPtr(hWnd, -16 /*GWL_STYLE*/, new IntPtr(flags.ToInt64() & ~(0x00010000L /*WS_MAXIMIZEBOX*/ | 0x00020000L /*WS_MINIMIZEBOX*/ | 0x00080000L /*WS_SYSMENU*/)));
}

private static IntPtr HwndSourceHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    switch (msg)
    {
        case 0x0084 /*WM_NCHITTEST*/:
            IntPtr result = DefWindowProc(hwnd, msg, wParam, lParam);
            if (result.ToInt32() >= 10 /*HTLEFT*/ && result.ToInt32() <= 17 /*HTBOTTOMRIGHT*/ )
            {
                handled = true;
                return new IntPtr(18 /*HTBORDER*/);
            }
            break;
    }
    return IntPtr.Zero;
}

[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern IntPtr DefWindowProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);

[System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
[System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex);

これにより、通知領域のフライアウト(時計や音量のフライアウトなど)に適したWindows7のウィンドウが表示されます。ところで、高さ44のコントロールを作成し、その背景を設定することで、フライアウトの下部の陰影を再現できます。

<Control.Background>
    <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
        <GradientStop Color="{x:Static SystemColors.GradientActiveCaptionColor}" Offset="0"/>
        <GradientStop Color="{x:Static SystemColors.InactiveBorderColor}" Offset="0.1"/>
    </LinearGradientBrush>
</Control.Background>
于 2010-08-04T05:29:31.180 に答える