顶层窗口大小 [英] Top-level window size

查看:154
本文介绍了顶层窗口大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  
      
  1. 为什么是一个顶层窗口约束的最小尺寸的 2×2 像素?
  2.   
  3. 是否有可能重写此约束,这样我可以设置宽度/高度为< 2
  4.   

如果您运行示例应用程序,并改变窗口的大小,比方说 1.1 你会看到大小被限制在 2,2

样例应用程序

 公共类Form1中

    公共子新()
        Me.InitializeComponent()
        Me.wnd =新窗口{.BackColor = Color.Red,.Bounds =新的Rectangle(100,100,200,200)}
        Me.grid =新的PropertyGrid随着{.Dock = DockStyle.Fill,.SelectedObject = Me.wnd,.TabIndex = 1}
        Me.btn =新按钮使用{。文=设置{使用SetWindowPos宽度= 1,高度= 1},.Dock = DockStyle.Top,.Height = 30,.TabIndex = 0}
        Me.Controls.AddRange({Me.grid,Me.btn})
    结束小组

    私人小组HandleDisposed(发送者为对象,E作为EventArgs的)把手Me.Disposed
        如果(不Me.grid是没有什么)然后Me.grid.Dispose()
        如果(不Me.wnd是没有什么)然后Me.wnd.Dispose()
        如果(不Me.btn是没有什么)然后Me.btn.Dispose()
    结束小组

    私人小组HandleButtonClick(发送者为对象,E作为EventArgs的)把手btn.Click
        Window.SetWindowPos(新HandleRef(Me.wnd,Me.wnd.Handle),没什么,0,0,1,1,(Window.SWP_DRAWFRAME或者Window.SWP_NOMOVE或者Window.SWP_NOZORDER或者Window.SWP_NOOWNERZORDER))
        Me.grid.Refresh()
    结束小组

    私人WithEvents就WND作为窗口
    私人WithEvents就电网作为PropertyGrid中
    BTN为按钮私人WithEvents就

    公共类窗口
        继承控制

        公共子新()
            Me.SetTopLevel(真)
        结束小组

        受保护的覆盖子OnHandleCreated(五作为System.EventArgs)
            尝试
                如果(IntPtr.Size = 4)然后
                    昏暗的风格的Int32 =(GetWindowLong32(新HandleRef(我,Me.Handle),GWL_STYLE),而不是(WS_CAPTION或者WS_THICKFRAME或者WS_MINIMIZE或者WS_MAXIMIZE或者WS_SYSMENU))
                    昏暗的扩展风格作为的Int32 =(GetWindowLong32(新HandleRef(我,Me.Handle),GWL_EXSTYLE),而不是(WS_EX_DLGMODALFRAME或者WS_EX_CLIENTEDGE或者WS_EX_STATICEDGE))
                    SetWindowLong32(新HandleRef(我,Me.Handle),GWL_STYLE,新HandleRef(没有新的IntPtr(样式)))
                    SetWindowLong32(新HandleRef(我,Me.Handle),GWL_EXSTYLE,新HandleRef(没有新的IntPtr(扩展风格)))
                其他
                    昏暗的风格的Int64 =(GetWindowLong64(新HandleRef(我,Me.Handle),GWL_STYLE),而不是CLng函数(WS_CAPTION或者WS_THICKFRAME或者WS_MINIMIZE或者WS_MAXIMIZE或者WS_SYSMENU))
                    昏暗扩展风格作为的Int64 =(GetWindowLong64(新HandleRef(我,Me.Handle),GWL_EXSTYLE),而不是CLng函数(WS_EX_DLGMODALFRAME或者WS_EX_CLIENTEDGE或者WS_EX_STATICEDGE))
                    SetWindowLong64(新HandleRef(我,Me.Handle),GWL_STYLE,新HandleRef(没有新的IntPtr(样式)))
                    SetWindowLong64(新HandleRef(我,Me.Handle),GWL_EXSTYLE,新HandleRef(没有新的IntPtr(扩展风格)))
                结束如果
                SetWindowPos(新HandleRef(我,Me.Handle),新HandleRef(没有新的IntPtr(HWND_TOPMOST)),0,0,0,0,(SWP_DRAWFRAME或者SWP_NOMOVE或者SWP_NOSIZE))
            抓住EX为例外
                投掷前
            最后
                MyBase.OnHandleCreated(五)
            结束尝试
        结束小组

        <的DllImport(user32.dll中,入口点:=GetWindowLong,字符集:= CharSet.Auto)> _
        朋友共享功能GetWindowLong32(BYVAL的HWND作为HandleRef,BYVAL参数nIndex为整数)作为的Int32
        端功能

        <的DllImport(user32.dll中,入口点:=GetWindowLongPtr,字符集:= CharSet.Auto)> _
        朋友共享功能GetWindowLong64(BYVAL的HWND作为HandleRef,BYVAL参数nIndex为整数)作为的Int64
        端功能

        <的DllImport(user32.dll中,入口点:=的SetWindowLong,字符集:= CharSet.Auto)> _
        朋友共享功能SetWindowLong32(BYVAL的HWND作为HandleRef,BYVAL参数nIndex整数,BYVAL dwNewLong作为HandleRef)作为的Int32
        端功能

        <的DllImport(user32.dll中,入口点:=SetWindowLongPtr,字符集:= CharSet.Auto)> _
        朋友共享功能SetWindowLong64(BYVAL的HWND作为HandleRef,BYVAL参数nIndex整数,BYVAL dwNewLong作为HandleRef)作为的Int64
        端功能

        <的DllImport(user32.dll中,字符集:= CharSet.Auto,ExactSpelling:= TRUE)> _
        朋友共享功能SetWindowPos(BYVAL的HWND作为HandleRef,BYVAL hWndInsertAfter作为HandleRef,BYVAL x As中整数,BYVAL y为整数,BYVAL CX作为整数,BYVAL CY作为整数,BYVAL标志为整数)作为布尔
        端功能

        朋友常量GWL_EXSTYLE作为整数= -20
        朋友常量GWL_STYLE作为整数= -16
        朋友常量HWND_TOPMOST作为整数= -1
        朋友常量SWP_DRAWFRAME作为整数=安培; H20
        朋友常量SWP_NOMOVE作为整数= 2
        朋友常量SWP_NOSIZE作为整数= 1
        朋友常量SWP_NOZORDER作为整数= 4
        朋友常量SWP_NOOWNERZORDER作为整数=安培; H200
        朋友常量WS_CAPTION作为整数=安培; HC00000
        朋友常量WS_THICKFRAME作为整数=安培; H40000
        朋友常量WS_MAXIMIZE作为整数=安培; H1000000
        朋友常量WS_MINIMIZE作为整数=安培; H20000000
        朋友常量WS_SYSMENU作为整数=安培; H80000
        朋友常量WS_EX_DLGMODALFRAME作为整数= 1
        朋友常量WS_EX_CLIENTEDGE作为整数=安培; H200
        朋友常量WS_EX_STATICEDGE作为整数=安培; H20000

    末级

末级
 

解决方案

窗口的最小尺寸通常限制在最小尺寸仍允许系统菜单和标题按钮被用户访问。即使是无国界的窗口,不完全恰当的。你可以把它通过明确设置Size属性的的窗口创建,通常Load事件处理程序是你的第一个机会更小。或者OnHandleCreated()。

但是,是的,Windows仍然是限制为2×2,为什么是难以实现的。当然,你的真正的想知道的是如何解决它。您可以通过截获WM_GETMINMAXINFO消息,并降低最低的轨道的大小这样做​​。一个演示的方法示例表单类:

 导入了System.Runtime.InteropServices

公共类Form1中
    受保护的覆盖子的WndProc(为ByRef米作为消息)
        MyBase.WndProc(米)
        如果m.Msg = WM_GETMINMAXINFO然后
            昏暗MMI = DirectCast(Marshal.PtrToStructure(m.LParam,的GetType(MINMAXINFO)),MINMAXINFO)
            mmi.ptMinTrackSize =新的点(0,0)
            Marshal.StructureToPtr(MMI,m.LParam,FALSE)
        结束如果
    结束小组

    私人小组Form1_Load的(发送者为对象,E作为EventArgs的)把手MyBase.Load
        Me.Size =新尺寸(0,0)
        MSGBOX(Me.Size.ToString())
    结束小组

    私人常量WM_GETMINMAXINFO作为整数=安培; H24
    PRIVATE STRUCTURE MINMAXINFO
        公共ptReserved作为点
        公共ptMaxSize作为点
        公共ptMaxPosition作为点
        公共ptMinTrackSize作为点
        公共ptMaxTrackSize作为点
    末端结构
末级
 

测试在Windows 8.1。我不能保证它会在所有的Windows版本。应该是的。

  1. Why is the minimum size of a top-level window constrained to 2x2 pixels?
  2. Is it possible to override this constraint so that I can set the width/height to < 2.

If you run the sample application and change the size of the window to let's say 1,1 you'll see that the size is constrained to 2,2.

Sample application

Public Class Form1

    Public Sub New()
        Me.InitializeComponent()
        Me.wnd = New Window With {.BackColor = Color.Red, .Bounds = New Rectangle(100, 100, 200, 200)}
        Me.grid = New PropertyGrid With {.Dock = DockStyle.Fill, .SelectedObject = Me.wnd, .TabIndex = 1}
        Me.btn = New Button With {.Text = "Set {width=1, height=1} using SetWindowPos.", .Dock = DockStyle.Top, .Height = 30, .TabIndex = 0}
        Me.Controls.AddRange({Me.grid, Me.btn})
    End Sub

    Private Sub HandleDisposed(sender As Object, e As EventArgs) Handles Me.Disposed
        If (Not Me.grid Is Nothing) Then Me.grid.Dispose()
        If (Not Me.wnd Is Nothing) Then Me.wnd.Dispose()
        If (Not Me.btn Is Nothing) Then Me.btn.Dispose()
    End Sub

    Private Sub HandleButtonClick(sender As Object, e As EventArgs) Handles btn.Click
        Window.SetWindowPos(New HandleRef(Me.wnd, Me.wnd.Handle), Nothing, 0, 0, 1, 1, (Window.SWP_DRAWFRAME Or Window.SWP_NOMOVE Or Window.SWP_NOZORDER Or Window.SWP_NOOWNERZORDER))
        Me.grid.Refresh()
    End Sub

    Private WithEvents wnd As Window
    Private WithEvents grid As PropertyGrid
    Private WithEvents btn As Button

    Public Class Window
        Inherits Control

        Public Sub New()
            Me.SetTopLevel(True)
        End Sub

        Protected Overrides Sub OnHandleCreated(e As System.EventArgs)
            Try
                If (IntPtr.Size = 4) Then
                    Dim style As Int32 = (GetWindowLong32(New HandleRef(Me, Me.Handle), GWL_STYLE) And Not (WS_CAPTION Or WS_THICKFRAME Or WS_MINIMIZE Or WS_MAXIMIZE Or WS_SYSMENU))
                    Dim exstyle As Int32 = (GetWindowLong32(New HandleRef(Me, Me.Handle), GWL_EXSTYLE) And Not (WS_EX_DLGMODALFRAME Or WS_EX_CLIENTEDGE Or WS_EX_STATICEDGE))
                    SetWindowLong32(New HandleRef(Me, Me.Handle), GWL_STYLE, New HandleRef(Nothing, New IntPtr(style)))
                    SetWindowLong32(New HandleRef(Me, Me.Handle), GWL_EXSTYLE, New HandleRef(Nothing, New IntPtr(exstyle)))
                Else
                    Dim style As Int64 = (GetWindowLong64(New HandleRef(Me, Me.Handle), GWL_STYLE) And Not CLng(WS_CAPTION Or WS_THICKFRAME Or WS_MINIMIZE Or WS_MAXIMIZE Or WS_SYSMENU))
                    Dim exstyle As Int64 = (GetWindowLong64(New HandleRef(Me, Me.Handle), GWL_EXSTYLE) And Not CLng(WS_EX_DLGMODALFRAME Or WS_EX_CLIENTEDGE Or WS_EX_STATICEDGE))
                    SetWindowLong64(New HandleRef(Me, Me.Handle), GWL_STYLE, New HandleRef(Nothing, New IntPtr(style)))
                    SetWindowLong64(New HandleRef(Me, Me.Handle), GWL_EXSTYLE, New HandleRef(Nothing, New IntPtr(exstyle)))
                End If
                SetWindowPos(New HandleRef(Me, Me.Handle), New HandleRef(Nothing, New IntPtr(HWND_TOPMOST)), 0, 0, 0, 0, (SWP_DRAWFRAME Or SWP_NOMOVE Or SWP_NOSIZE))
            Catch ex As Exception
                Throw ex
            Finally
                MyBase.OnHandleCreated(e)
            End Try
        End Sub

        <DllImport("user32.dll", EntryPoint:="GetWindowLong", CharSet:=CharSet.Auto)> _
        Friend Shared Function GetWindowLong32(ByVal hWnd As HandleRef, ByVal nIndex As Integer) As Int32
        End Function

        <DllImport("user32.dll", EntryPoint:="GetWindowLongPtr", CharSet:=CharSet.Auto)> _
        Friend Shared Function GetWindowLong64(ByVal hWnd As HandleRef, ByVal nIndex As Integer) As Int64
        End Function

        <DllImport("user32.dll", EntryPoint:="SetWindowLong", CharSet:=CharSet.Auto)> _
        Friend Shared Function SetWindowLong32(ByVal hWnd As HandleRef, ByVal nIndex As Integer, ByVal dwNewLong As HandleRef) As Int32
        End Function

        <DllImport("user32.dll", EntryPoint:="SetWindowLongPtr", CharSet:=CharSet.Auto)> _
        Friend Shared Function SetWindowLong64(ByVal hWnd As HandleRef, ByVal nIndex As Integer, ByVal dwNewLong As HandleRef) As Int64
        End Function

        <DllImport("user32.dll", CharSet:=CharSet.Auto, ExactSpelling:=True)> _
        Friend Shared Function SetWindowPos(ByVal hWnd As HandleRef, ByVal hWndInsertAfter As HandleRef, ByVal x As Integer, ByVal y As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal flags As Integer) As Boolean
        End Function

        Friend Const GWL_EXSTYLE As Integer = -20
        Friend Const GWL_STYLE As Integer = -16
        Friend Const HWND_TOPMOST As Integer = -1
        Friend Const SWP_DRAWFRAME As Integer = &H20
        Friend Const SWP_NOMOVE As Integer = 2
        Friend Const SWP_NOSIZE As Integer = 1
        Friend Const SWP_NOZORDER As Integer = 4
        Friend Const SWP_NOOWNERZORDER As Integer = &H200
        Friend Const WS_CAPTION As Integer = &HC00000
        Friend Const WS_THICKFRAME As Integer = &H40000
        Friend Const WS_MAXIMIZE As Integer = &H1000000
        Friend Const WS_MINIMIZE As Integer = &H20000000
        Friend Const WS_SYSMENU As Integer = &H80000
        Friend Const WS_EX_DLGMODALFRAME As Integer = 1
        Friend Const WS_EX_CLIENTEDGE As Integer = &H200
        Friend Const WS_EX_STATICEDGE As Integer = &H20000

    End Class

End Class 

解决方案

The minimum size of a window is normally restricted to the smallest size that still allows the system menu and the caption buttons to be accessible by the user. Even for borderless windows, not exactly appropriate. You can make it smaller by explicitly setting the Size property after the window is created, normally the Load event handler is your first opportunity. Or OnHandleCreated().

But yeah, Windows still restricts it to 2x2, the "why" is elusive. Surely what you really want to know is how to work around it. You do so by intercepting the WM_GETMINMAXINFO message and lowering the minimum track size. A sample form class that demonstrates the approach:

Imports System.Runtime.InteropServices

Public Class Form1
    Protected Overrides Sub WndProc(ByRef m As Message)
        MyBase.WndProc(m)
        If m.Msg = WM_GETMINMAXINFO Then
            Dim mmi = DirectCast(Marshal.PtrToStructure(m.LParam, GetType(MINMAXINFO)), MINMAXINFO)
            mmi.ptMinTrackSize = New Point(0, 0)
            Marshal.StructureToPtr(mmi, m.LParam, False)
        End If
    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Me.Size = New Size(0, 0)
        MsgBox(Me.Size.ToString())
    End Sub

    Private Const WM_GETMINMAXINFO As Integer = &h24
    Private Structure MINMAXINFO
        Public ptReserved As Point
        Public ptMaxSize As Point
        Public ptMaxPosition As Point
        Public ptMinTrackSize As Point
        Public ptMaxTrackSize As Point
    End Structure
End Class

Tested on Windows 8.1. I can't promise that it will work on all Windows versions. It should.

这篇关于顶层窗口大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆