In my attempt to Windows11ify my app taking into account the current theme, I cam accross a need for most VB6 programmers out there trying to change the appearance of their forms. That is: Get the size of the current windows frame OUTSIDE the working client area. Yes, there's a bunch of API calls and a bunch of other methods. Here's my method which I think works best and does an EXCELLENT job at giving everything you need so you can work with the re-arangment of your form.

1 - The calls:
Code:
Private Const WS_EX_WINDOWEDGE As Long = &H100
Private Const WS_EX_CLIENTEDGE As Long = &H200
Private Const WS_EX_STATICEDGE As Long = &H20000
Private Const WS_THICKFRAME As Long = &H40000
Private Const WS_EX_LAYERED As Long = &H80000
Private Const WS_DLGFRAME As Long = &H400000
Private Const WS_BORDER As Long = &H800000

Private Const GWL_STYLE As Long = (-16)
Private Const GWL_EXSTYLE As Long = (-20)

Private Const SWP_NOSIZE As Long = &H1
Private Const SWP_NOMOVE As Long = &H2
Private Const SWP_NOZORDER = &H4
Private Const SWP_FRAMECHANGED As Long = &H20
Private Const SWP_NOOWNERZORDER = &H200

Private Type POINTAPI
  X As Long
  Y As Long
End Type

Private Type RECT
  Left As Long
  Top As Long
  Right As Long
  Bottom As Long
End Type

Private Type RECTW
  Left As Long
  Top As Long
  Right As Long
  Bottom As Long
  Width As Long
  Height As Long
End Type

Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
Private Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
Private Declare Function GetClientRect Lib "user32.dll" (ByVal hwnd As Long, ByRef lpRect As RECT) As Long
Private Declare Function SetWindowLongA Lib "user32" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal X As Long, ByVal Y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
2 - The custom functions
Code:
' Gets the size of each border of the frame and the size of the client area that is the actual size of the form without a frame
' Returns size in pixels as RECTW
Public Function GetFormBorderSize(ByVal oForm As Form) As RECTW

  Dim oRect As RECT
  Dim oPoint As POINTAPI
  Dim ocRect As RECT
  Dim oRetVal As RECTW
  
  ClientToScreen oForm.hwnd, oPoint
  GetWindowRect oForm.hwnd, oRect
  GetClientRect oForm.hwnd, ocRect
  
  ' Get the size of each sides of the frame
  oRetVal.Top = oPoint.Y - oRect.Top
  oRetVal.Left = oPoint.X - oRect.Left
  oRetVal.Bottom = ((oRect.Bottom - oRect.Top) - ocRect.Bottom) - oRetVal.Top
  oRetVal.Right = ((oRect.Right - oRect.Left) - ocRect.Right) - oRetVal.Left
  oRetVal.Height = ocRect.Bottom
  oRetVal.Width = ocRect.Right
  
  GetFormBorderSize = oRetVal

End Function

' Removes the borders from controls and forms (usually for ListBoxes since they keep their borders even when flat but works for forms too)
Public Sub RemoveBorder(ByRef oObject As Object)
  
  Dim lWin As Long

  lWin = GetWindowLongA(oObject.hwnd, GWL_STYLE)
  lWin = lWin And (Not WS_BORDER) And (Not WS_DLGFRAME) And (Not WS_THICKFRAME)
  
  SetWindowLongA oObject.hwnd, GWL_STYLE, lWin
  
  lWin = GetWindowLongA(oObject.hwnd, GWL_EXSTYLE)
  lWin = lWin And (Not WS_EX_WINDOWEDGE) And (Not WS_EX_CLIENTEDGE) And (Not WS_EX_STATICEDGE)
  
  SetWindowLongA oObject.hwnd, GWL_EXSTYLE, lWin
  
  SetWindowPos oObject.hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE Or SWP_NOOWNERZORDER Or SWP_NOZORDER Or SWP_FRAMECHANGED

End Sub
I needed to remove the borders of my listboxes since I put them in pictureboxes to add some style, the only big annoyance was the fact that the border stayed there which pushed me into figuring out how to remove those borders. It also turns out that I needed to remove the frame around my form since I am extending the client aread using DWM calls (which are FAR from working for now) but the forms actually work too.

Now to put this into practice, the code to remove the border of the form is as folllows:
Code:
Dim oRect As RECT
Dim ofRect As RECTW

' First, get the position and sizes of the form and frame
ofRect = GetFormBorderSize(Me)
GetWindowRect Me.hWnd, oRect

' Remove the windows borders
RemoveBorder Me
' Resize the form to accomodate the shifting that occures when removing the border
SetWindowPos Me.hWnd, vbNull, oRect.Left, oRect.Top, ofRect.Width, ofRect.Height, SWP_FRAMECHANGED
And to remove the frame of a list box:
Code:
RemoveBorder List1
And there you have it. I also wanted to make sure you people have all the const variables because getting the values of some of them is quite challengin, maybe not THESE ones but in my run for Windows11ifying, there's lots of undoccumented API and lots of const variables that I need to dig deep in Google to find their values since Microsoft does not make it easy to get those on their website.

As always, well, this is my second post, but as usual for me, please feel free to comment or offer alternatives.