Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Minimize Button Click Not Detected #526

Open
TheBobman03 opened this issue Nov 16, 2017 · 7 comments
Open

Minimize Button Click Not Detected #526

TheBobman03 opened this issue Nov 16, 2017 · 7 comments

Comments

@TheBobman03
Copy link

TheBobman03 commented Nov 16, 2017

uint result = Win32Helper.IsRunningOnMono ? 0 : NativeMethods.SendMessage(this.Handle, (int)Win32.Msgs.WM_NCHITTEST, 0, (uint)m.LParam);

On some setups, clicking the in lower left corner of the minimize button on the title bar will not be detected correctly. The result from the hit test will come back with a 2 indicating the title bar rather than an 8 for the minimize button. For the WM_NCLBUTTONDOWN message, the WParam included in the Message passed to WndProc should be used to determine where the click occurred.
https://msdn.microsoft.com/en-us/library/windows/desktop/ms645620(v=vs.85).aspx

This line should be removed and the relevant part of the if statement on the next line should be changed to
(uint)m.WParam == 2

@lextm
Copy link
Member

lextm commented Nov 17, 2017

We cannot make the changes you described so far. Though there are tons of related articles from Microsoft, this library itself proves that many tricks are still necessary.

We are also cautious on patches. You can review our recent releases and see how patch controller was invented to enable experimental patches.

My guess on the cause is also different. Maybe the minimize button area calculation code has some issues under that setup so indeed the hit test returns 2. This happened once in the past (like #510). Thus, before drawing a conclusion, we need to identify exactly the setup and steps to reproduce it reliably. That can give us a solid foundation to troubleshoot and locate the culprit.

@TheBobman03
Copy link
Author

My specific setup is using Dock Panel Suite on Windows 10 with 3 monitors. From left to right, monitor one has a screen resolution of 1920x1080 scaled to 125%, monitor three is 1680x1050 scaled to 100% and monitor two is 1920x1080 scaled to 100%.

When using a float window, the red section in the image below does not work while the green section does. When I make the suggested change, everything works as expected. But like you mentioned that was only under the limited testing of my system. My coworkers have similar setups except on Windows 7. They can reproduce the issue to a lesser extent in that the red region is not as pronounced.

float window

If you are willing to impart some of your knowledge and experience on me, out of my own intellectual curiosity, what issues are there with using the WParam that is provided with the Message?

lextm added a commit that referenced this issue Nov 18, 2017
@lextm
Copy link
Member

lextm commented Nov 18, 2017

Just noticed that you are using a customized FloatWindow. Then you can override WndProc to resolve the issue.

I will be reluctant to include the changes in master, as

  • For the default FloatWindow with no such buttons, the existing code seems to work.
  • Current maintainers including me try to avoid changes to existing code base whenever possible, as honestly speaking we are not the original developers, and we don't know what harm any change can lead to.

I put your changes on a new branch, and might put the patch under patch controller for future releases, but that's just an idea, not a promise.

@mapper55
Copy link

mapper55 commented Nov 8, 2018

In case anyone is still interested in this issue, I added a custom MinimizingFloatWindow using instructions found here:
[http://docs.dockpanelsuite.com/tutorials/customizing-floatwindow.html]

It had the same issue which I have seen in other free software (Click Minimize only works on one side). I set up a MinButton variable and captured the mouse move message to set it to true when you mouse over the minimize button. Then the click message check the variable and minimizes or restores the form depending on its window state. Its kludgy but it works.

    bool MinButton = false;
    int SC_MINIMIZE = 0xF020;
    int SC_RESTORE = 0xF120;

    [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
    [System.Diagnostics.DebuggerStepThrough]
    protected override void WndProc(ref Message m)
    {
        if (m.Msg == (int)Win32.Msgs.WM_NCMOUSEMOVE)
        {
            if ((int)m.WParam == 0x8)
                MinButton = true;
            else
                MinButton = false;
        }
        else if (m.Msg == (int)Win32.Msgs.WM_MOUSEMOVE)
        {
            MinButton = false;
        }

        switch (m.Msg)
        {
            case (int)Win32.Msgs.WM_NCLBUTTONDOWN:
                {
                    if (IsDisposed)
                        return;
                    
                    if (MinButton)
                    {
                        if (this.WindowState == FormWindowState.Minimized)
                            NativeMethods.SendMessage(this.Handle, (int)Win32.Msgs.WM_SYSCOMMAND, (uint)SC_RESTORE, 0);
                        else
                            NativeMethods.SendMessage(this.Handle, (int)Win32.Msgs.WM_SYSCOMMAND, (uint)SC_MINIMIZE, 0);
                        return;
                    }

The rest of the WndProc procedure is the same as the standard FloatWindow.

@DanCarterGMSL
Copy link

The suggested solution by @mapper55 will minimize the window as soon as the left mouse button is pressed down. This is not how Windows usually works; normally it's only on mouseup that the action is taken.

That said, if you change it to look at WM_NCLBUTTONUP instead, then clicking in the red region initiates a drag operation, whereas minimizing on mousedown doesn't give time for that. The proper fix would be to use the correct hit test value for the drag operation too.

@DanCarterGMSL
Copy link

I think the better fix would be the one suggested by @TheBobman03. This would mean the dragging code works as it should too.

@capodast78
Copy link

In case anyone is "still still" interested in this issue I'll post a complete implementation of a customized FloatWindow. It will address the minimize issue with the solution suggested by @mapper55 and also address another annoying issue where you dock two FloatWindows together and a new instance is created automatically that does not preserve any Icon set (will force null / default icon).

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Windows.Forms;
using WeifenLuo.WinFormsUI.Docking;

namespace MyNamespace
{
    public class CustomFloatWindow : FloatWindow
    {
        Icon mIcon;

        public CustomFloatWindow(DockPanel dockPanel, DockPane pane)
            : base(dockPanel, pane)
        {
            setDefaultProperties();
        }

        public CustomFloatWindow(DockPanel dockPanel, DockPane pane, Rectangle bounds)
            : base(dockPanel, pane, bounds)
        {
            setDefaultProperties();
        }

        private void setDefaultProperties()
        {
            FormBorderStyle = FormBorderStyle.Sizable;

            // To enable Alt+Tab between your undocked forms and your main form
            ShowInTaskbar = true;
            Owner = null;

            // Allow the Windows default behavior of maximizing/restoring the window
            DoubleClickTitleBarToDock = false;

            var resources = new System.ComponentModel.ComponentResourceManager(typeof(MyChosenForm));
            mIcon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));

            Icon = mIcon;
        }

        [DllImport("User32.dll", CharSet = CharSet.Auto)]
        public static extern uint SendMessage(IntPtr hWnd, int Msg, uint wParam, uint lParam);

        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
        protected override void WndProc(ref Message m)
        {
            int WM_NCLBUTTONDOWN = 0x00A1;
            int WM_SYSCOMMAND = 0x0112;
            int WM_GETICON = 0x007F;

            int SC_MINIMIZE = 0xF020;
            int SC_RESTORE = 0xF120;

            if (m.Msg == WM_NCLBUTTONDOWN)
            {
                if (IsDisposed)
                    return;

                if ((uint)m.WParam == 8) // Check if button down occured in minimize box
                {
                    if (WindowState == FormWindowState.Minimized)
                        CustomFloatWindow.SendMessage(Handle, (int)WM_SYSCOMMAND, (uint)SC_RESTORE, 0);
                    else
                        CustomFloatWindow.SendMessage(Handle, (int)WM_SYSCOMMAND, (uint)SC_MINIMIZE, 0);

                    return;
                }
            }
            else if (m.Msg == WM_GETICON)
            {
                // A combined new FloatWindow will use default SetText() method which sets Text to space and Icon to null,
                // hammering an override here until both are properly set, C-
                if (Text == " ")
                {
                    Text = "MyText"; // Anything but spacy really
                    Icon = mIcon;
                }
            }

            base.WndProc(ref m);
        }
    }

    public class CustomFloatWindowFactory : DockPanelExtender.IFloatWindowFactory
    {
        public FloatWindow CreateFloatWindow(DockPanel dockPanel, DockPane pane, Rectangle bounds)
        {
            return new CustomFloatWindow(dockPanel, pane, bounds);
        }

        public FloatWindow CreateFloatWindow(DockPanel dockPanel, DockPane pane)
        {
            return new CustomFloatWindow(dockPanel, pane);
        }
    }
}

magriggs added a commit to magriggs/mRemoteNG that referenced this issue Jan 3, 2024
magriggs added a commit to magriggs/mRemoteNG that referenced this issue Jan 3, 2024
…anelsuite#526 (comment). Main change is to enable minimize and close buttons

Remove unnecessary using
magriggs added a commit to magriggs/mRemoteNG that referenced this issue Jan 3, 2024
…anelsuite#526 (comment). Main change is to enable minimize and close buttons
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants