3

Vista で通知アイコン (ネットワーク アイコンやサウンド アイコンなど) をシングルクリックすると、縁取りされたキャプションのないダイアログが表示されます ( http://i.msdn.microsoft.com/Aa511448.NotificationArea22(en-us,MSDN. 10).png ):

http://i.msdn.microsoft.com/Aa511448.NotificationArea22(ja-jp,MSDN.10).png

これらをWPFでエミュレートするにはどうすればよいですか? 新しいウィンドウを作成し、WindowStyle を "None" に設定し、ResizeMode を "CanResize" に設定すると、フレームが少し細くなり、ダイアログがサイズ変更可能になることを除いて、ほぼ同じ結果になりますが、これは望ましくありません。ResizeMode を "NoResize" に設定すると、Aero 境界線のないウィンドウになります (細い 2 ピクセルの実線境界線のみ)。

4

5 に答える 5

2

私は最終的にそれを理解しました: WindowStyle を "None" に設定し、ResizeMode を "CanResize" に設定すると、キャプションなしで正しい太い境界線が表示されます。唯一の問題は、ウィンドウのサイズを変更できることです。

Window幸い、この問題はインスタンスの WM_NCHITTEST を処理することで簡単に修正できます。

private IntPtr _hwnd;

protected override void OnSourceInitialized(EventArgs e) {
    _hwnd = new System.Windows.Interop.WindowInteropHelper(this).Handle;
    System.Windows.Interop.HwndSource.FromHwnd(_hwnd).AddHook(_WndProc);
    base.OnSourceInitialized(e);
}

private const int WM_NCHITTEST = 132;
private const int HTCLIENT = 1;

private IntPtr _WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) {
    // We should only receive messages for our own window handle.
    System.Diagnostics.Debug.Assert(hwnd == _hwnd);

    if (msg == WM_NCHITTEST) {
        handled = true;
        return (IntPtr)HTCLIENT;
    }
    return IntPtr.Zero;
}

カーソルが境界線上にあることを Windows に知らせないことで、サイズ変更カーソルが表示されることはありません。

于 2009-03-26T10:34:00.607 に答える
1

必要なのは、ウィンドウ スタイルの適切な組み合わせを指定することです。WPF は、Windows で使用可能なすべてのオプションを公開しているわけではありませんが、pinvoke を使用して自分で設定できます。

私は現在、Vista マシンを使用していないため、スタイルの組み合わせをテストして正しい外観を確認することはできませんが、スタイルのリスト (C#) はhttp://pinvoke.net/default.aspx/user32/にあります。 GetWindowLong.html

あなたはウィンドウクラスです:

[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong);

[DllImport("user32.dll")]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);

private const int GWL_STYLE = -16;
private const int GWL_EXSTYLE = -20;
private const UInt32 SWP_NOSIZE = 0x0001;
private const UInt32 SWP_NOMOVE = 0x0002;
private const UInt32 SWP_NOZORDER = 0x0004;
private const UInt32 SWP_NOREDRAW = 0x0008;
private const UInt32 SWP_NOACTIVATE = 0x0010;
private const UInt32 SWP_FRAMECHANGED = 0x0020;

public override void OnSourceInitialized(EventArgs e)
{
    IntPtr hwnd = new System.Windows.Interop.WindowInteropHelper(this).Handle;

    // set styles to a combination of WS_ flags and exstyles to a combination of WS_EX_ flags

    SetWindowLong(hwnd, GWL_STYLE, styles);
    SetWindowLong(hwnd, GWL_EXSTYLE, exstyles);

    // and to activate changes:
    SetWindowPos(hwnd,IntPtr.Zero,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_FRAMECHANGED);
}
于 2009-03-23T09:02:42.223 に答える
0

ここに投稿されたコードに解決策があります。ストレートXAMLでそれを行うことを検討しますが、ウィンドウの境界線を近くに表示するようにスタイルを設定する方法があるはずです。フォーラムの投稿が何をしているのかをよりよく説明するために、これも見てください。

于 2009-03-23T02:16:48.797 に答える
0

今まで考えてきたことを発信していきたいと思います。これはかなり近くなります:

<Window.Style>
    <Style TargetType="{x:Type Window}">
        <Setter Property="AllowsTransparency"       Value="True"            />
        <Setter Property="Background"           Value="{x:Null}"        />
        <Setter Property="BorderBrush"          Value="{x:Null}"        />
        <Setter Property="BorderThickness"      Value="0"           />
        <Setter Property="OverridesDefaultStyle"    Value="True"            />
        <Setter Property="ResizeMode"           Value="NoResize"        />
        <Setter Property="SizeToContent"        Value="WidthAndHeight"      />
        <Setter Property="WindowStyle"          Value="None"            />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Window}">
                    <Border BorderThickness="1" CornerRadius="4" Background="{x:Null}">
                        <Border.BorderBrush>
                            <SolidColorBrush Color="{x:Static SystemColors.WindowFrameColor}" Opacity="0.75" />
                        </Border.BorderBrush>
                        <Border BorderThickness="5" Background="{x:Null}">
                            <Border.BorderBrush>
                                <SolidColorBrush Color="{x:Static SystemColors.ActiveBorderColor}" Opacity="0.5" />
                            </Border.BorderBrush>
                            <Border BorderThickness="1" Background="White">
                                <Border.BorderBrush>
                                    <SolidColorBrush Color="{x:Static SystemColors.WindowFrameColor}" Opacity="0.75" />
                                </Border.BorderBrush>

                                <ContentPresenter />
                            </Border>
                        </Border>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Style>

明らかに、ActiveWindowBorderColor の透明度以上のものを使用して境界線の中央を描画しています。上部の 1/4 には白いオーバーレイがあり、下部の 3/4 には黒いオーバーレイがあるようです。外枠も右端と下端にアクセントカラーを入れています。実際にこれを行う場合は、Border から派生する UserControl を作成して、そのような小さな詳細をすべて処理し (必要に応じてサイズを変更できるようにする)、ウィンドウのスタイルをリソース ディクショナリにスローします。

于 2009-03-23T03:23:32.227 に答える