web-dev-qa-db-ja.com

マウスイベントの通過を許可する半透明のウィンドウをWPFで作成する方法

WPFを除いて、Adobe Lightroom( http://www.youtube.com/watch?v=87hNd3vaENE )のLights out/lightsdim機能と同様の効果を作成しようとしています。

私が試したのは、既存のウィンドウの上に別のウィンドウを作成し、それを透明にして、その上に半透明のパスジオメトリを配置することでした。しかし、私はマウスイベントがこの半透明のウィンドウを通過できるようにしたい(下のウィンドウに)。

これは私が持っているものの簡略版です:

<Window x:Class="LightsOut.MaskWindow"
    xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
    AllowsTransparency="True" 
    WindowStyle="None"
    ShowInTaskbar="False"
    Topmost="True" 
    Background="Transparent">

<Grid>

    <Button HorizontalAlignment="Left" Height="20" Width="60">click</Button>

    <Path IsHitTestVisible="False" Stroke="Black" Fill="Black" Opacity="0.3">

        <Path.Data>
            <RectangleGeometry Rect="0,0,1000,1000 "/>
        </Path.Data>
    </Path>             

</Grid>

ウィンドウは完全に透明であるため、パスがカバーされていない場所では、マウスイベントが直接通過します。ここまでは順調ですね。パスオブジェクトでは、IsHitTestvisibleがfalseに設定されています。したがって、マウスイベントは、同じフォーム上の他のコントロールに渡されます(つまり、同じフォーム上にあるため、ボタンをクリックできます)。

ただし、マウスイベントは、Pathオブジェクトを通過してその下のウィンドウに移動することはありません。

何か案は?または、この問題を解決するためのより良い方法はありますか?

ありがとう。

34
RMK

私は同様の問題を抱えており、解決策を見つけました:

public static class WindowsServices
{
  const int WS_EX_TRANSPARENT = 0x00000020;
  const int GWL_EXSTYLE = (-20);

  [DllImport("user32.dll")]
  static extern int GetWindowLong(IntPtr hwnd, int index);

  [DllImport("user32.dll")]
  static extern int SetWindowLong(IntPtr hwnd, int index, int newStyle);

  public static void SetWindowExTransparent(IntPtr hwnd)
  {
    var extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
    SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_TRANSPARENT);
  }
}

ウィンドウセットの場合:

WindowStyle = None
Topmost = true
AllowsTransparency = true

ウィンドウの背後にあるコードで次を追加します。

protected override void OnSourceInitialized(EventArgs e)
{
  base.OnSourceInitialized(e);
  var hwnd = new WindowInteropHelper(this).Handle;
  WindowsServices.SetWindowExTransparent(hwnd);
}

そして出来上がり-クリックスルーウィンドウ!元の回答を参照してください: http://social.msdn.Microsoft.com/Forums/en-US/wpf/thread/a3cb7db6-5014-430f-a5c2-c9746b077d4f

58
Oleg Kolosov

あなたが説明したことは、期待される動作のように聞こえます。 1つの解決策は、パスで塗りつぶしを{x:Null}に設定することです。これが、オブジェクトをテストにヒットさせない唯一の確実な方法です。

2
Steven

別の考えがあります。

マウスカーソルの真下にある1つのピクセルを完全に透明にした場合はどうなりますか? :]

1
AgentFire