1
votes

I have been searching for hours and haven't found anything useful because all other issues are too localized, so here is my version of this (common) problem:

I have a WPF window with WindowStyle=None and ResizeMode=NoResize (otherwise I would get resize borders which I do not want) and most important AllowsTransparency= False and I must stick to this setup.

Changing the ResizeMode to CanResize and having a custom resize grip with the following MouseDown handler

[DllImport("User32.dll")]
public static extern bool ReleaseCapture();

[DllImport("User32.dll")]
public static extern IntPtr SendMessage(
     IntPtr hWnd, UInt32 Msg, Int32 wParam, Int32 lParam);

private void OnResizeGripMouseDown(object sender, MouseButtonEventArgs e) {
    ReleaseCapture();
    SendMessage(Window.Handle, WM_NCLBUTTONDOWN, HTBOTTOMRIGHT, 0);
}

allows me to resize the window perfectly, however there is the resize border left. Is there any way to force the resizability of the window although it has ResizeMode=NoResize?

(Maybe via SetWindowLong and GWL_EXSTYLE? If there is the the need for messages, I already have a WindowProc setup to handle this.)

2

2 Answers

4
votes

I was able to force the desired behaviour by using another message

SendMessage(Handle, WM_SYSCOMMAND, SC_SIZE + direction, 0);

where WM_SYSCOMMAND is the default Windows message, SC_SIZE is the wParam defined by 0xF000 and the direction is the numerical value of the hit test handle defined by this enum

public enum SysCommandSize : int {
     SC_SIZE_HTLEFT = 1,
     SC_SIZE_HTRIGHT = 2,
     SC_SIZE_HTTOP = 3,
     SC_SIZE_HTTOPLEFT = 4,
     SC_SIZE_HTTOPRIGHT = 5,
     SC_SIZE_HTBOTTOM = 6,
     SC_SIZE_HTBOTTOMLEFT = 7,
     SC_SIZE_HTBOTTOMRIGHT = 8
}
1
votes

Christian, your solution brought me on the right way but it's lacking copy paste code for the dumb and lazy like me! Here we go, if you uncomment the commented parts you can move the window around except for the borders.

    private void Action_LMouseDownAndMove(object sender, MouseEventArgs e)
    {
        Point mousePosition = this.PointToClient(System.Windows.Forms.Cursor.Position);
        const int WM_NCLBUTTONDOWN = 0xA1;
        //const int HT_CAPTION = 0x2;
        if (e.Button == MouseButtons.Left)
        {
            ReleaseCapture();
            if (mousePosition.X < 20)
            {
                if (mousePosition.Y < 20)
                    SendMessage(Handle, WM_NCLBUTTONDOWN, 13, 0);
                else if (mousePosition.Y > this.Size.Height - 20)
                    SendMessage(Handle, WM_NCLBUTTONDOWN, 16, 0);
                else
                    SendMessage(Handle, WM_NCLBUTTONDOWN, 10, 0);
            }
            else if (mousePosition.X > this.Size.Width - 20)
            {
                if (mousePosition.Y < 20)
                    SendMessage(Handle, WM_NCLBUTTONDOWN, 14, 0);
                else if (mousePosition.Y > this.Size.Height - 20)
                    SendMessage(Handle, WM_NCLBUTTONDOWN, 17, 0);
                else
                    SendMessage(Handle, WM_NCLBUTTONDOWN, 11, 0);
            }
            else if (mousePosition.Y < 20)
                SendMessage(Handle, WM_NCLBUTTONDOWN, 12, 0);
            else if (mousePosition.Y > this.Size.Height - 20)
                SendMessage(Handle, WM_NCLBUTTONDOWN, 15, 0);
            //else
            //  SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
        }

Change the 20 pixel value depending on your taste. I am not 100% sure left/right and top/bottom have exactly the same resize areas or whether one value needs to be 19/21 if you know what I mean... There are some reduction possibilities for the if/else tree here, I know. And instead of 20 I should use a constant.

To change the cursor for showing the user he can resize I use the following code, it's simply a MouseMove Event handler:

        this.pictureBox.MouseMove += new MouseEventHandler((a, e) =>
        {
            Point h = this.PointToClient(System.Windows.Forms.Cursor.Position);

            if (h.X < 20)
            {
                if (h.Y < 20)
                {
                    pictureBox.Cursor = System.Windows.Forms.Cursors.SizeNWSE;
                }
                else if (h.Y > this.Size.Height - 20)
                {
                    pictureBox.Cursor = System.Windows.Forms.Cursors.SizeNESW;
                }
                else
                {
                    pictureBox.Cursor = System.Windows.Forms.Cursors.SizeWE;
                }
            }
            else if (h.X > this.Size.Width - 20)
            {
                if (h.Y < 20)
                {
                    pictureBox.Cursor = System.Windows.Forms.Cursors.SizeNESW;
                }
                else if (h.Y > this.Size.Height - 20)
                {
                    pictureBox.Cursor = System.Windows.Forms.Cursors.SizeNWSE;
                }
                else
                {
                    pictureBox.Cursor = System.Windows.Forms.Cursors.SizeWE;
                }
            }
            else if (h.Y < 20)
            {
                pictureBox.Cursor = System.Windows.Forms.Cursors.SizeNS;
            }
            else if (h.Y > this.Size.Height - 20)
            {
                pictureBox.Cursor = System.Windows.Forms.Cursors.SizeNS;
            }
            else
            {
                pictureBox.Cursor = System.Windows.Forms.Cursors.Default;
            }
        });