推奨される解決策
このシグネチャを持つ単純な「AirRepair」クラスをお勧めします。
public class AirRepair : Decorator
{
public HwndHost Win32Host ... // DP bound to HwndHost
public Geometry RepairArea ... // Default is entire decorated control,
// or use OpacityMask
}
このように使用:
<Grid>
<WebBrowser x:Name="browser" ... />
<AirRepair Win32Host="{Binding ElementName=browser}"
Margin="10" HorizontalAlignment="Left" ...>
<TextBox ... />
</AirRepair>
</Grid>
AirRepairは、、、またはその他の任意ので使用WebBrowser
できWindowsFormsHost
ますHwndHost
。装飾されたコントロールでカバーされる領域は、Win32コンテンツ内に表示され、フォーカスイベントとマウスイベントを受け入れます。長方形以外の装飾が施されたコントロールの場合、表示する領域は、RepairArea
および/またはOpacityMask
プロパティで指定できます。
使い方
AirRepairは、次の方法で空域の問題を解決します。
HwndHost
与えられた使用の下で子hWndを作成するHwndSource
- そのhRgnを適切な領域に設定する
- 装飾されたコントロールのaに
RootVisual
設定するBorder
Background
VisualBrush
WM_MOUSEMOVE
子hWndが受信したWPFメインウィンドウへの転送など
この結果、WPFは引き続きWin32コンテンツの背後にコンテンツを描画しますが、AirRepairの子ウィンドウは別のWin32コントロールのWin32コンテンツの前に同じコンテンツを再描画します。
いくつかの重要な実装の詳細
親hWndを取得する
が最初に設定された場合Win32Host
、hWndがある場合とない場合があります。は/をPropertyChangedCallback
使用して可能なhWnd変更を検出し、コールバックで独自のhWndポインターを更新して、イベントの処理を終了できるようにする必要があります。PresentationSource.AddSourceChangedHandler
PresentationSource.RemoveSourceChangedHandler
Dispatcher.BeginInvoke
HwndHost
SourceChanged
子の作成hWnd
子hWndは、HwndSource
クラスを使用して作成、ペアレント化、およびマネージコードにフックできます。Win32Hostの親hWndが使用できなくなったら、必ず廃棄してください。
子の配置hWnd
子hWndのウィンドウ位置(その親に対する)は、次のように計算できます。
var compositionTarget = PresentationSource.FromVisual(this).CompositionTarget;
var position = compositionTarget.TransformToDevice(
this.TransformToVisual(Win32Host));
イベントは、UIELement.LayoutUpdated
これを最新の状態に保つために使用する必要があります。
hRgnと不透明度の計算
オプション:長方形の修復領域のみがサポートされている場合は省略します
RepairArea
orOpacityMask
が設定されていて、子hWndが存在する場合は、aを使用してを使用してペイントRenderTargetBitmap
し、そこからhRgnを作成します。nullの場合、長方形を使用します。nullの場合、黒を使用します。サイズは、AirRepairデコレータの座標をデバイスの座標に変換することによって設定されます。これは、アニメートされたブラシや変化しているaなどの変数を適切に処理しないことに注意してください。RepairArea
OpacityMask
RepairArea
OpacityMask
RenderTargetBitmap
OpacityMask
VisualBrush
Visual
子hWndにコンテンツを描画する
装飾されたコントロールではなく、AirRepairデコレータであるaVisualBrush
を使用します。Visual
これにより、コンテンツを変更せずに装飾されたコントロールを置き換えることができます。
childHwndSource.RootVisual =
new Border
{
Background = new VisualBrush
{
Visual = this,
ViewBoxUnits = BrushMappingMode.Absolute,
ViewPortUnits = BrushMappingMode.Absolute,
}
};
マウスメッセージの転送
を使用してフックを追加してから、 HwndSource.AddHook
Win32PostMessage
をコンテナに使用します。
childHwndSource.AddHook((hwnd, msg, wParam, lParam, handled) =>
{
// Check if message needs forwarding and update parameters if necessary
switch(msg)
{
default:
return; // Not recognized - do not forward
case WM_MOUSEMOVE:
...
}
var target = PresentationSource.FromVisual(this).CompositionTarget as HwndTarget;
if(target!=null)
Win32Methods.PostMessage(target.Handle, msg, wParam, lParam);
};