克服操作系统强加的Windows窗体的最小大小限制窗体、最小、操作系统、大小

2023-09-02 01:33:25 作者:年轻,不能失败。

在我开发一个应用程序,我需要能够使Windows窗体不是由操作系统(36 PX在Vista中)规定的最低高度限制较小。我试图拦截WM_GETMINMAXINFO,并提供自己的信息,覆盖的操作系统的限制,但只适用于用户。从code我可以设置的高度为比限制小,但我的变化只能到WM_WINDOWPOSCHANGED发布到消息队列(这恰好就在我改变高度)。

In an application I am developing, I need to be able to make a windows form smaller than the minimum height limit imposed by the operating system (36 px in Vista). I have tried intercepting WM_GETMINMAXINFO and providing my own information to override the OS limits, but this only works for the user. From code I can set the height to a value smaller than the limit, but my change only works until WM_WINDOWPOSCHANGED is posted to the message queue (which happens just after I change the height).

推荐答案

经过大量的实验和试错,我发现了一个解决方案。我重写onResize,并符合形式的大小在其列表框(见我在约翰·桑德斯回答评论)。正如我在我的问题提到的,我注意到,窗体的大小倒退WM_WINDOWPOSCHANGED发送后。进一步调查显示,大小回归实际开始时WM_WINDOWPOSCHANGING发送。 WM_WINDOWPOSCHANGING是WM_WINDOWPOSCHANGED的发生前的窗口大小实际上改变了妹妹的消息。我不知道为什么,但由于某些原因WM_WINDOWPOSCHANGING盲目遵循的形式向指定的操作系统限制(显然它不会查询与WM_GETMINMAXINFO窗口)的大小。因此,我需要拦截WM_WINDOWPOSCHANGING和我真的很想规模覆盖它。这意味着我不再符合使用onResize受到窗体的大小,而是我符合窗体大小,当我收到WM_WINDOWPOSCHANGING。这甚至比onResize受到更好,因为当尺寸被变更,然后再次改变时的大小onResize受到期间一致。其中没有发生相关联的闪烁

After much experimentation and trial-and-error, I have discovered a solution. I was overriding OnResize and conforming the size of the form to the ListBox in it (see my comment on John Saunders answer). As I mentioned in my question, I noticed that the size of the form regresses after WM_WINDOWPOSCHANGED is sent. Further investigation revealed that the size regression actually begins when WM_WINDOWPOSCHANGING is sent. WM_WINDOWPOSCHANGING is the sister message of WM_WINDOWPOSCHANGED which occurs before the window size actually changes. I don't know why, but for some reason WM_WINDOWPOSCHANGING blindly conforms the size of the form to the OS specified limits (apparently it does not query the window with WM_GETMINMAXINFO). Thus, I needed to intercept WM_WINDOWPOSCHANGING and override it with the size I really wanted. This means that I am no longer conforming the size of the form using OnResize, but instead I am conforming the form size when I receive WM_WINDOWPOSCHANGING. This is even better than OnResize, because there is no associated flicker which occurs when the size is changed and then changed again when the size is conformed during OnResize.

此外,有必要进行拦截和重写WM_GETMINMAXINFO,否则,甚至拦截WM_WINDOWPOSCHANGING对你没好处。

Also, it is necessary to intercept and override WM_GETMINMAXINFO, otherwise, even intercepting WM_WINDOWPOSCHANGING will do you no good.

using System.Runtime.InteropServices;

private const int WM_WINDOWPOSCHANGING = 0x0046;
private const int WM_GETMINMAXINFO = 0x0024;

protected override void WndProc(ref Message m)
{
    if (m.Msg == WM_WINDOWPOSCHANGING)
    {
        WindowPos windowPos = (WindowPos)m.GetLParam(typeof(WindowPos));

        // Make changes to windowPos

        // Then marshal the changes back to the message
        Marshal.StructureToPtr(windowPos, m.LParam, true);
    }

    base.WndProc(ref m);

    // Make changes to WM_GETMINMAXINFO after it has been handled by the underlying
    // WndProc, so we only need to repopulate the minimum size constraints
    if (m.Msg == WM_GETMINMAXINFO)
    {
        MinMaxInfo minMaxInfo = (MinMaxInfo)m.GetLParam(typeof(MinMaxInfo));
        minMaxInfo.ptMinTrackSize.x = this.MinimumSize.Width;
        minMaxInfo.ptMinTrackSize.y = this.MinimumSize.Height;
        Marshal.StructureToPtr(minMaxInfo, m.LParam, true);
   }
}

struct WindowPos
{
     public IntPtr hwnd;
     public IntPtr hwndInsertAfter;
     public int x;
     public int y;
     public int width;
     public int height;
     public uint flags;
}

struct POINT
{
    public int x;
    public int y;
}

struct MinMaxInfo
{
    public POINT ptReserved;
    public POINT ptMaxSize;
    public POINT ptMaxPosition;
    public POINT ptMinTrackSize;
    public POINT ptMaxTrackSize;
}