WPF シェル統合ライブラリ ( http://archive.msdn.microsoft.com/WPFShell ) を使用してカスタム ウィンドウ クロムを実装しました。
ReSizeMode を NoResize に設定するまで、Chrome は機能します。次に、閉じるボタンにカーソルを合わせると、基になるシステムの閉じるボタンがカスタム クロームの閉じるボタンの下に表示されていることがわかります。
予想される動作は、基になる閉じるボタンが表示されないことです。ウィンドウを移動するか、デスクトップ上の別のウィンドウを選択してこのウィンドウに戻ると、システムの [閉じる] ボタンが再び非表示になっていることに気付きます。したがって、おそらく (1) アプリケーションが最初に起動したとき、および (2) ResizeMode = NoResize のときです。
私の最初の疑いは、カスタム Chrome での WM.NCHITTEST の処理方法です。HTCLient を返すようにこの関数を変更すると、この問題は解決されます。ただし、キャプション バーをドラッグ アンド ドロップしたり、右クリックしたりすることはできません。
以下は、WindowsChromeWorker クラスからの WM.NCHITTEST メッセージのハンドラーのコードです。
private IntPtr _HandleNCHitTest( WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled ) {
IntPtr lRet = IntPtr.Zero;
handled = false;
// Give DWM a chance at this first.
if ( Utility.IsOSVistaOrNewer && _chromeInfo.GlassFrameThickness != default( Thickness ) && _isGlassEnabled ) {
// If we're on Vista, give the DWM a chance to handle the message first.
handled = NativeMethods.DwmDefWindowProc( _hwnd, uMsg, wParam, lParam, out lRet );
}
// Handle letting the system know if we consider the mouse to be in our effective non-client area.
// If DWM already handled this by way of DwmDefWindowProc, then respect their call.
if ( IntPtr.Zero == lRet ) {
var mousePosScreen = new Point( Utility.GET_X_LPARAM( lParam ), Utility.GET_Y_LPARAM( lParam ) );
Rect windowPosition = _GetWindowRect();
HT ht = _HitTestNca(
DpiHelper.DeviceRectToLogical( windowPosition ),
DpiHelper.DevicePixelsToLogical( mousePosScreen ) );
// Don't blindly respect HTCAPTION.
// We want UIElements in the caption area to be actionable so run through a hittest first.
if ( ht != HT.CLIENT) {
Point mousePosWindow = mousePosScreen;
mousePosWindow.Offset( -windowPosition.X, -windowPosition.Y );
mousePosWindow = DpiHelper.DevicePixelsToLogical( mousePosWindow );
IInputElement inputElement = _window.InputHitTest( mousePosWindow );
if ( inputElement != null && WindowChrome.GetIsHitTestVisibleInChrome( inputElement ) ) {
ht = HT.CLIENT;
}
}
//handled = false;
handled = true;
lRet = new IntPtr((int)ht);
}
return lRet;
}
private static readonly HT[,] _HitTestBorders = new[,]
{
{ HT.TOPLEFT, HT.TOP, HT.TOPRIGHT },
{ HT.LEFT, HT.CLIENT, HT.RIGHT },
{ HT.BOTTOMLEFT, HT.BOTTOM, HT.BOTTOMRIGHT },
};
private HT _HitTestNca( Rect windowPosition, Point mousePosition ) {
// Determine if hit test is for resizing, default middle (1,1).
int uRow = 1;
int uCol = 1;
bool onResizeBorder = false;
//if (_window.ResizeMode == ResizeMode.NoResize)
// _chromeInfo.ResizeBorderThickness = new Thickness(0);
// Determine if the point is at the top or bottom of the window.
if ( mousePosition.Y >= windowPosition.Top && mousePosition.Y < windowPosition.Top + _chromeInfo.ResizeBorderThickness.Top + _chromeInfo.CaptionHeight ) {
onResizeBorder = ( mousePosition.Y < ( windowPosition.Top + _chromeInfo.ResizeBorderThickness.Top ) );
uRow = 0; // top (caption or resize border)
} else if ( mousePosition.Y < windowPosition.Bottom && mousePosition.Y >= windowPosition.Bottom - (int)_chromeInfo.ResizeBorderThickness.Bottom ) {
uRow = 2; // bottom
}
// Determine if the point is at the left or right of the window.
if ( mousePosition.X >= windowPosition.Left && mousePosition.X < windowPosition.Left + (int)_chromeInfo.ResizeBorderThickness.Left ) {
uCol = 0; // left side
} else if ( mousePosition.X < windowPosition.Right && mousePosition.X >= windowPosition.Right - _chromeInfo.ResizeBorderThickness.Right ) {
uCol = 2; // right side
}
// If the cursor is in one of the top edges by the caption bar, but below the top resize border,
// then resize left-right rather than diagonally.
if ( uRow == 0 && uCol != 1 && !onResizeBorder ) {
uRow = 1;
}
HT ht = _HitTestBorders[uRow, uCol];
if ( ht == HT.TOP && !onResizeBorder) {
ht = HT.CAPTION;
}
return ht;
}
これを修正する方法はありますか?
どうもありがとう、アルジュン