Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF Borderless window resize

I am designing my own custom window in WPF and I have been trying to implement the resizing functionality I have used previously in WinForms. For some reason the return value of my WndProc isn't giving me the proper result.

I have a NativeMethods class for all my WndProc messages and results:

public class NativeMethods
{
    public const int WM_NCHITTEST  = 0x84;
    public const int HTCAPTION     = 2;
    public const int HTLEFT        = 10;
    public const int HTRIGHT       = 11;
    public const int HTTOP         = 12;
    public const int HTTOPLEFT     = 13;
    public const int HTTOPRIGHT    = 14;
    public const int HTBOTTOM      = 15;
    public const int HTBOTTOMLEFT  = 16;
    public const int HTBOTTOMRIGHT = 17;
}

And here is the code behind for my window:

public partial class MainWindow : Window
{
    const int GripSize   = 16;
    const int BorderSize = 7;

    public MainWindow()
    {
        InitializeComponent();
    }

    protected override void OnSourceInitialized(EventArgs e)
    {
        base.OnSourceInitialized(e);
        IntPtr windowHandle = new WindowInteropHelper(this).Handle;
        HwndSource windowSource = HwndSource.FromHwnd(windowHandle);
        windowSource.AddHook(WndProc);
    }

    private IntPtr WndProc(IntPtr hwnd, int msg,
        IntPtr wParam, IntPtr lParam, ref bool handled)
    {
        if (msg == NativeMethods.WM_NCHITTEST)
        {
            int x = lParam.ToInt32() << 16 >> 16, y = lParam.ToInt32() >> 16;
            Point pos = PointFromScreen(new Point(x, y));

            if (pos.X > GripSize && 
                pos.X < ActualWidth - GripSize &&
                pos.Y >= ActualHeight - BorderSize)
            {
                return (IntPtr)NativeMethods.HTBOTTOM; // This doesn't work?
            }

            // Top, Left, Right, Corners, Etc.
        }

        return IntPtr.Zero;
    }
}

I expected the cursor to change to the "resize down arrow" and the resizing functionality to work as it did in my WinForms project. I have set breakpoints and the HTBOTTOM return is firing when the cursor is in the expected location. In XAML I have ResizeMode set to CanResize and the WindowStyle set to None. What am I doing wrong?

like image 723
Cris McLaughlin Avatar asked Jul 15 '13 00:07

Cris McLaughlin


3 Answers

Maybe it is simpler to assign WindowChrome.As per your comment you must be able to resize from all the sides as well as using grip.You can do all this by setting the WindowStyle to None and ResizeMode to CanResizeWithGrip or CanResize (whatever you wish to acheive)

<Window x:Class="MVVMProtoType.View.Test.Test"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="Test" Height="300" Width="300" WindowStyle="None" AllowsTransparency="False" ResizeMode="CanResizeWithGrip">

In the code behid you must set the Window Chrome for the window . You can do it like this :

WindowChrome.SetWindowChrome(this, new WindowChrome());

OR You can use setter for window style like :

<Setter Property="WindowChrome.WindowChrome">
        <Setter.Value>
            <WindowChrome CornerRadius="0" GlassFrameThickness="1" UseAeroCaptionButtons="False"/>
        </Setter.Value>
</Setter>

MSDN link for more information

Please note WindowChrome class is a part of .NET 4.5 Framework. For.NET 4.0 users check out archive.msdn.microsoft.com/WPFShell

like image 196
kiran Avatar answered Oct 08 '22 20:10

kiran


I wrote a solution in an other post, you can resize the window, you need to use .NET 4.5 or WPFShell

You can also put the WindowChrome code directly on your MainWindow.xaml like this, and it works perfectly without putting a setter.

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:Concursos"
    mc:Ignorable="d"
    Title="Concuros" Height="350" Width="525"
    WindowStyle="None"
    WindowState="Normal" 
    ResizeMode="CanResize"
    >
<WindowChrome.WindowChrome>
    <WindowChrome 
        CaptionHeight="0"
        ResizeBorderThickness="5" />
</WindowChrome.WindowChrome>

    <Grid>

    <YOUR CODE HERE

</Grid>

You can go here to view the complete post.

Solution

Here is the before and after

The ChallengeThe Solution

like image 40
Fernando Aguirre Avatar answered Oct 08 '22 22:10

Fernando Aguirre


Well this was a stupid mistake. I forgot to add handled = true; before I returned the result. Now the window is functioning as normal. As a note if you set the ResizeMode to NoResize this code won't work at all.

like image 31
Cris McLaughlin Avatar answered Oct 08 '22 21:10

Cris McLaughlin