【发布时间】:2012-02-17 22:36:14
【问题描述】:
我正在尝试使用无法调整大小的WindowStyle="None"(用于自定义按钮且无标题)创建一个 WPF 窗口。将ResizeMode 设置为NoResize 会删除我想保留的航空边框。
我可以设置最小/最大尺寸属性并完成它,除了:
- 调整大小的光标仍然可见,并且
- 显示窗口以响应用户操作并适合其内容。它会显示一张图片,因此大小会发生变化。
所以,我有一个简单的方案,可以让我完成 99% 的任务:
public class BorderedWindowNoResize : Window
{
[DllImport( "DwmApi.dll" )]
public static extern int DwmExtendFrameIntoClientArea(
IntPtr hwnd,
ref MARGINS pMarInset );
[DllImport( "user32.dll", CharSet = CharSet.Auto )]
public static extern IntPtr DefWindowProc(
IntPtr hWnd,
int msg,
IntPtr wParam,
IntPtr lParam );
public BorderedWindowNoResize()
{
Loaded += BorderedWindowNoResize_Loaded;
}
private void BorderedWindowNoResize_Loaded( object sender, RoutedEventArgs e )
{
IntPtr mainWindowPtr = new WindowInteropHelper( this ).Handle;
HwndSource mainWindowSrc = HwndSource.FromHwnd( mainWindowPtr );
mainWindowSrc.AddHook( WndProc );
}
private IntPtr WndProc( IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled )
{
var htLocation = DefWindowProc( hwnd, msg, wParam, lParam ).ToInt32();
if( msg == (uint)WM.NCHITTEST )
{
handled = true;
switch( htLocation )
{
case (int)HitTestResult.HTBOTTOM:
case (int)HitTestResult.HTBOTTOMLEFT:
case (int)HitTestResult.HTBOTTOMRIGHT:
case (int)HitTestResult.HTLEFT:
case (int)HitTestResult.HTRIGHT:
case (int)HitTestResult.HTTOP:
case (int)HitTestResult.HTTOPLEFT:
case (int)HitTestResult.HTTOPRIGHT:
htLocation = (int)HitTestResult.HTBORDER;
break;
}
}
return new IntPtr( htLocation );
}
}
基本上;
- 覆盖窗口过程。
- 调用默认窗口过程。
- 如果邮件是
WM_NCHITTEST,检查边框结果。 - 如果是边框,返回正则
HTBORDER。
这可以让我保留 aero 窗口边框并隐藏调整大小的光标,但它会在我的窗口内部添加约 5 像素的白色边框。
事实上,即使我在WndPrc 的顶部返回默认的windows 过程结果并且什么都不做,边框仍然在那里。我需要在我的窗口上使用不同的背景颜色,所以这对我不起作用。
有什么想法吗?一如既往地提前感谢。
【问题讨论】: