はWPF

2009-03-22 5 views
3

とVistaの通知アイコンのダイアログボックスをエミュレートする場合、シングルクリック、あなたが接さまだcaptionlessダイアログ(http://i.msdn.microsoft.com/Aa511448.NotificationArea22(en-us,MSDN.10).png)を提示している(そのようなネットワークやサウンドアイコンなど)Vistaの通知アイコンを:はWPF

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

これらをWPFでどのようにエミュレートできますか?新しいウィンドウを作成し、WindowStyleを "None"に設定し、ResizeModeを "CanResize"に設定すると、フレームがわずかに薄く、ダイアログがサイズ変更可能であることを除いて、近い結果が生成されます。 ResizeModeを「NoResize」に設定すると、エアロボーダーのないウィンドウが表示されます(薄い2pxの実線ボーダーのみ)。

+0

リンクが悪い..... –

答えて

2

私はついにそれを考え出した:あなたは「CanResize」は、あなたがキャプションなしで正しい太枠を買ってあげるために、「なし」にWindowStyleがを設定し、ResizeModeです場合は、唯一のヒッチはまだあなたができることですウィンドウのサイズを変更します。

幸い、この問題は簡単に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は、カーソルが境界上にある、我々はサイズ変更カーソルを提示することはありませんことを知らせることはありませんでは。

2

トリックは自分自身にボーダーを追加することです。私はメインのコンテンツ要素をDockPanelにしてBorderを追加することでそうしました。境界線を使用して、Vistaスタイルのウィンドウと一致するように外観をカスタマイズできます。私は色が良くないので、その特定の名前を付けることはできませんが、例としてGrayを使用しました。

<Window x:Class="WpfApplication10.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Window1" 
    Height="300" 
    Width="300" 
    WindowStyle="None" 
    ResizeMode="NoResize"> 
    <DockPanel> 
     <Border 
      BorderBrush="Gray" 
      BorderThickness="5"> 

      <TextBlock>Here we go</TextBlock> 

     </Border> 
    </DockPanel> 
</Window> 
+0

私はこのアプローチを考えましたが、問題はシステムのビジュアルスタイルに合わせて境界線を取得しています。 – Jonathan

+0

実際には、DockPanelは必要ありません。 –

+0

@ブライアン、私はDockPanelなしで試してみました。ボーダーはクライアントエリアを満たしていませんでした。 DockPanelを追加すると修正されました。 – JaredPar

0

here投稿をコードで解決策があります試してみてください。私はまっすぐXAMLでそれをやってみるつもりですが、あなたのウィンドウの境界をスタイルして近くに見えるようにする方法があるはずです。フォーラム投稿が何をしているのかについてのより良い説明については、thisをご覧ください。

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を作成して、そのような小さな詳細をすべて処理し(必要に応じてサイズを変更できるようにして)、Windowのスタイルをリソース辞書にスローします。

1

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

私はので、私は(C#で)正しい見た目が、スタイルのリストを与えるかを確認するために、スタイルの組み合わせをテストすることはできません今はVistaマシンではないんだけど、ここであなたしているウィンドウで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); 
} 
+0

私はこれを動作させることはできません。私はWS_CAPTIONを残すと、Aeroフレームは残っていますが、キャプション(ウィンドウを移動するのに使うことができる)の上に大きなボーダーがあります。WS_CAPTIONを省略すると、Aeroフレームを失い、代わりに薄いウィンドウフレームを取得します。 – Jonathan