10

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?

General Grievance
  • 4,555
  • 31
  • 31
  • 45
Cris McLaughlin
  • 1,201
  • 2
  • 14
  • 23
  • 1
    Why not use `ResizeMode = "CanResizeWithGrip"`? You are trying to achieve this effect (just to resize it around the window without `Grip`)? – Anatoliy Nikolaev Jul 15 '13 at 04:28
  • 1
    Because I still want to be able to resize the window from any corner or side like the normal functionality. I figured out the issue and I am posting the answer now. – Cris McLaughlin Jul 15 '13 at 11:55

3 Answers3

17

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

kiran
  • 1,062
  • 24
  • 31
  • 1
    Thank you for the response. I didn't know about the System.Windows.Shell namespace which would have saved me quite a bit of time. – Cris McLaughlin Jan 29 '14 at 14:38
9

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 Challenge The Solution

Community
  • 1
  • 1
Fernando Aguirre
  • 1,346
  • 1
  • 9
  • 7
2

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.

Cris McLaughlin
  • 1,201
  • 2
  • 14
  • 23