Getting Proper Window Sizes in Windows

Hey guys,

I’m trying to get a proper starting point for the .left and .top properties of a window in Windows. The 0,0 point of the window in Xojo is the first pixel of usable space once you get inside the window (i.e.: past the menu bar and the frame of the window). I’m trying to calculate the thickness of the titlebar/menu bar and am not having as much success as I want.

I am use WindowsSystemMetricsMBS which basically implements the functions defined here:

Problem is, I can’t figure out which value to use. I thought it would be 15 (also that was based on Christian’s recommendation), but that’s not quite good enough. That is the “CYMenus” parameters. It only reports the menus as being 20 pixels. The actual position where I need to be is somewhere around 45 pixels or so (based on “standard” frame thicknesses). So I’m trying to add in other items like CYBorder or CXBorder, etc. Nothings quite where I want it to be.

And the result as well is that my window height is too large and drops below the task bar a bit. So any help is appreciated on how people calculate the thickness of the upper frame of the window, etc.




Does this help?:



That’s pretty close. Thank you. I experimented last night and found that you also need to include SM_CYCAPTION which takes into account the caption of the window. I don’t know if that parameter existed back in 2005 when Aaron posted his code, but this is what I just whipped up as an extension method for a window. Add the parameter for which dimension you want to calculate or use “All” to set the full size of the window:

Sub SetWindowsWindowMaxSizes(Extends w as Window, WinDimension as String)
  #If TargetWin32 Then  //This is a Win32 method only
    Declare Sub GetClientRect Lib "User32" ( handle as Integer, r as Ptr )
    Declare Function GetSystemMetrics Lib "User32" ( index as Integer ) as Integer
    Const SM_CXFRAME = 32
    Const SM_CYFRAME = 33
    Const SM_CYMENU = 15
    Const SM_CYCAPTION = 4
    Dim mb as new MemoryBlock( 16 )
    GetClientRect( App.MDIWindow.Handle, mb )
    Dim mLeft as Boolean
    Dim mWidth as Boolean
    Dim mTop as Boolean
    Dim mHeight as Boolean
    Select Case WinDimension
    Case "All"
      mLeft = True
      mWidth = True
      mTop = True
      mHeight = True
    Case "Left"
      mLeft = True
    Case "Width"
      mWidth = True
    Case "Top"
      mTop = True
    Case "Height"
      mHeight = True
    End Select
    If mLeft Then
      w.Left = GetSystemMetrics( SM_CXFRAME )
    End If
    If mTop THen
      w.Top = GetSystemMetrics( SM_CYMENU ) + GetSystemMetrics( SM_CYFRAME ) + GetSystemMetrics( SM_CYCAPTION)
    End If
    If mWidth Then
      w.Width = mb.Long( 8 ) - w.Left - GetSystemMetrics( SM_CXFRAME )
    End If
    If mHeight Then
      w.Height = mb.Long( 12 ) - w.Top - GetSystemMetrics( SM_CYFRAME )
    End If
End Sub

Actually, the code for setting the height of the window seems to not work. I based it on Aaron Ballman’s code but the GetClientRect function is returning 0. So I’m changing the list if-then clause to:

If mHeight Then
w.Height = w.GetScreen.AvailableHeight - w.Top - GetySystemMetrics(SM_CYFRAME)
End If

GetScreen is a method by Kem Tekinay for being able to determine what screen the window is in.