代码之家  ›  专栏  ›  技术社区  ›  Sasha Chedygov

WPF:使窗口不可调整,但保持框架?

  •  7
  • Sasha Chedygov  · 技术社区  · 14 年前

    我有一个没有标题栏的窗口( WindowStyle == WindowStyle.None )整个窗口使用航空玻璃效果。当我使窗户无法调节时( ResizeMode == ResizeMode.NoResize )玻璃效果消失了,我的控制装置就挂在半空中。(本质上,窗口本身会消失,但会留下内容。)

    我有没有办法在不去掉窗框的情况下使窗户无法调节?


    我读过这个问题 Enable Vista glass effect on a borderless WPF window ,但这不是我想要的——我想保持窗口边界。有关我希望窗口的外观的示例,请在启用Aero的情况下单击alt+tab。


    澄清, 我不希望调整大小的光标出现 当鼠标悬停在窗口边框上时。这就是我希望我的窗口看起来的本质:

    Projector http://i37.tinypic.com/2mg4jty.png

    解决方案不必是严格的WPF——我可以通过使用win32 API进行黑客攻击来实现这一点。

    4 回复  |  直到 14 年前
        1
  •  9
  •   Eric Brown    14 年前

    你可以钩住wndproc并截获 WM_WINDOWPOSCHANGING 消息。不是严格的WPF,但可能是你的最佳选择。

    如果您想隐藏调整大小的光标,那么最好的选择是截取 WM_NCHITTEST . 调用defwindowproc(以获取默认行为),并测试返回值;如果它是htbottom、htbottomlft、htbottomlight、httop、httopleft或httopright,请将返回值更改为htborder。

        2
  •  9
  •   Cameron MacFarland    14 年前

    基于Erics答案。

    public-partial-class-mainwindow:window
    {
    [dllimport(“dwmapi.dll”)]
    公共静态外部int dwmextendframeintoclientarea(
    IntPtr hwnd
    参考利润率pmarinset);
    
    [dllimport(“user32.dll”,charset=charset.auto)]
    公共静态外部intptr defwindowproc(
    IntPtr hWnd
    int
    IntPtr wParam
    IntPtr lParam);
    
    private const int wm_nchittest=0x0084;
    private const int htborder=18;
    private const int htbottom=15;
    private const int htbottomlet=16;
    private const int htbottomright=17;
    private const int htleft=10;
    private const int htright=11;
    private const int httop=12;
    private const int httopleft=13;
    private const int httopright=14;
    
    公共主窗口()
    {
    初始化组件();
    
    this.loaded+=新的routedeventhandler(主窗口已加载);
    }
    
    已加载void主窗口(对象发送方、RoutedEventargs e)
    {
    尝试
    {
    //获取wpf应用程序的窗口句柄
    intptr mainWindowptr=新的WindowInteropHelper(this).handle;
    hwndsource mainwindowsrc=hwndsource.fromhwnd(主窗口指针);
    mainWindowsrc.compositionTarget.backgroundColor=color.fromargb(0,0,0,0);
    主窗口rc.addhook(wndproc);
    
    /设置边距
    页边距=新页边距();
    页边距.cxlefwidth=10;
    页边距.cxRightWidth=10;
    页边距.cyBottomHeight=10;
    边缘。细胞重量=10;
    
    int hr=dwmextendframeintoclientarea(主窗口rc.handle,参考页边距);
    / /
    如果(HR & lt;0)
    {
    //dwmextendframeintoclientarea失败
    }
    }
    //如果不是Vista,请将背景漆成白色。
    catch(dllnotfoundException)
    {
    application.current.mainwindow.background=画笔.white;
    }
    }
    
    private intptr wndproc(intptr hwnd,int msg,intptr wparam,intptr lparam,ref bool handled)
    {
    //重写窗口命中测试
    //如果光标位于调整大小的边框上,
    //返回标准边框结果。
    如果(msg==wm-nchittest)
    {
    处理=真;
    var htlocation=defwindowproc(hwnd,msg,wparam,lparam).toint32();
    开关(H位置)
    {
    HTBOTTOM案:
    案例HTBottomLeft:
    案例H右下角:
    HTLEFT案:
    HTRIGHT案:
    HTTOP案:
    HTTOPLEFT案:
    右上角大小写:
    htlocation=htborder;
    断裂;
    }
    
    返回新的intptr(htlocation);
    }
    
    返回intptr.zero;
    }
    
    “私人作废”按钮“单击”(对象发送者、路由器和目标)
    {
    这个。
    }
    }
    
    [结构布局(layoutkind.sequential)]
    公共结构页边距
    {
    public int cxlefwidth;//保留其大小的左边框宽度
    public int cxrightwidth;//保留其大小的右边框宽度
    public int cytopheight;//保留其大小的上边框高度
    public int cybottomheight;//保留其大小的下边框高度
    };
    
    <window x:class=“wpfApplication1.mainWindow”窗口
    xmlns=“http://schemas.microsoft.com/winfx/2006/xaml/presentation”(http://schemas.microsoft.com/winfx/2006/xaml/presentation)
    xmlns:x=“http://schemas.microsoft.com/winfx/2006/xaml”
    title=“主窗口”height=“150”width=“200”
    background=“透明”
    windowstyle=“无”
    resizeMode=“可以调整大小”
    gt;
    <grid background=“white”margin=“10,10,10,10”>
    <button content=“go away”click=“button\u click”height=“20”width=“100”/>
    和/格栅& GT;
    &窗/窗;
    < /代码> 
    

    public partial class MainWindow : 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);
    
        private const int WM_NCHITTEST = 0x0084;
        private const int HTBORDER = 18;
        private const int HTBOTTOM = 15;
        private const int HTBOTTOMLEFT = 16;
        private const int HTBOTTOMRIGHT = 17;
        private const int HTLEFT = 10;
        private const int HTRIGHT = 11;
        private const int HTTOP = 12;
        private const int HTTOPLEFT = 13;
        private const int HTTOPRIGHT = 14;
    
        public MainWindow()
        {
            InitializeComponent();
    
            this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
        }
    
        void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            try
            {
                // Obtain the window handle for WPF application
                IntPtr mainWindowPtr = new WindowInteropHelper(this).Handle;
                HwndSource mainWindowSrc = HwndSource.FromHwnd(mainWindowPtr);
                mainWindowSrc.CompositionTarget.BackgroundColor = Color.FromArgb(0, 0, 0, 0);
                mainWindowSrc.AddHook(WndProc);
    
                // Set Margins
                MARGINS margins = new MARGINS();
                margins.cxLeftWidth = 10;
                margins.cxRightWidth = 10;
                margins.cyBottomHeight = 10;
                margins.cyTopHeight = 10;
    
                int hr = DwmExtendFrameIntoClientArea(mainWindowSrc.Handle, ref margins);
                //
                if (hr < 0)
                {
                    //DwmExtendFrameIntoClientArea Failed
                }
            }
            // If not Vista, paint background white.
            catch (DllNotFoundException)
            {
                Application.Current.MainWindow.Background = Brushes.White;
            }
        }
    
        private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            // Override the window hit test
            // and if the cursor is over a resize border,
            // return a standard border result instead.
            if (msg == WM_NCHITTEST)
            {
                handled = true;
                var htLocation = DefWindowProc(hwnd, msg, wParam, lParam).ToInt32();
                switch (htLocation)
                {
                    case HTBOTTOM:
                    case HTBOTTOMLEFT:
                    case HTBOTTOMRIGHT:
                    case HTLEFT:
                    case HTRIGHT:
                    case HTTOP:
                    case HTTOPLEFT:
                    case HTTOPRIGHT:
                        htLocation = HTBORDER;
                        break;
                }
    
                return new IntPtr(htLocation);
            }
    
            return IntPtr.Zero;
        }
    
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }
    }
    
    [StructLayout(LayoutKind.Sequential)]
    public struct MARGINS
    {
        public int cxLeftWidth;      // width of left border that retains its size
        public int cxRightWidth;     // width of right border that retains its size
        public int cyTopHeight;      // height of top border that retains its size
        public int cyBottomHeight;   // height of bottom border that retains its size
    };
    
    <Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="150" Width="200" 
        Background="Transparent"
        WindowStyle="None"
        ResizeMode="CanResize"
    >
        <Grid Background="White" Margin="10,10,10,10">
            <Button Content="Go Away" Click="Button_Click" Height="20" Width="100" />
        </Grid>
    </Window>
    
        3
  •  1
  •   RQDQ    14 年前

    一种简单的方法是设置minwidth/maxwidth和minheight/maxheight属性,以有效地使其不可调整。当然,存在的问题是,您仍然可以在边界上获得调整大小的光标。

        4
  •  1
  •   Kevin    14 年前

    为什么不为窗口创建此窗口边框? 它使用偏移量来设置窗口的颜色。 所以,一个简单的方法就是把整个边框环绕在窗户上,然后在上面画上你自己的颜色!