Modify

Opened 6 years ago

Closed 6 years ago

#2368 closed Bug (No Bug)

Inconsistent GUICreate results

Reported by: vlad@… Owned by:
Milestone: Component: AutoIt
Version: 3.3.8.1 Severity: None
Keywords: Cc:

Description

GUICreate produces a window with sizes dependent on the style used.

I am attaching two files: a demo script and the script's output. While I'm sure there are reasons behind this (maybe even Win API "philosophy"), I think a user not well versed in GUI tweaking might expect a consistent behavior (as WinMove offers - see the example).

Attachments (2)

BugDemo1.au3 (1.6 KB) - added by vlad@… 6 years ago.
Demo Script
BugDemo1.txt (391 bytes) - added by vlad@… 6 years ago.
Demo Script output

Download all attachments as: .zip

Change History (10)

Changed 6 years ago by vlad@…

Demo Script

Changed 6 years ago by vlad@…

Demo Script output

comment:1 follow-up: Changed 6 years ago by FireFox

No, it's not a bug. Depending on the window' style, you will have to add the borders.

See below:

I changed the window' style of the Test2 because it's simpler (otherwise other metrics are needed that I don't bother to search).

#include <WindowsConstants.au3>
#include <WinAPI.au3>
#include <Constants.au3>

Local $iBorderSize = _WinAPI_GetSystemMetrics($SM_CXDLGFRAME)
Local $iCaptionSize = _WinAPI_GetSystemMetrics($SM_CYCAPTION)

Local $hGUI = 0, $aClientSize = 0, $aPos = 0, $sDebugNotes = ""
$sDebugNotes = "Window with DEFAULT (-1) Style:" & @CRLF

#region Test1
$hGUI = GUICreate("Demo Window", 640, 480)

$aClientSize = WinGetClientSize($hGUI)
$sDebugNotes &= "  GUICreate [640x480]: WinGetClientSize returns " & $aClientSize[0] & "x" & $aClientSize[1] & ","
$sDebugNotes &= " width borders: " & $aClientSize[0] + ($iBorderSize * 2) & "x" & $aClientSize[1] + ($iCaptionSize + $iBorderSize * 2) & ","


$aPos = WinGetPos($hGUI)
$sDebugNotes &= " WinGetPos returns " & $aPos[2] & "x" & $aPos[3] & @CRLF

;the winmove function will resize the window's client area, you need to add the borders
WinMove($hGUI, "", Default, Default, 640 + ($iBorderSize * 2), 480 + ($iCaptionSize + $iBorderSize * 2))

$aClientSize = WinGetClientSize($hGUI)
$sDebugNotes &= "  WinMove   [640x480]: WinGetClientSize returns " & $aClientSize[0] & "x" & $aClientSize[1] & ","
$sDebugNotes &= " width borders: " & $aClientSize[0] + ($iBorderSize * 2) & "x" & $aClientSize[1] + ($iCaptionSize + $iBorderSize * 2) & ","

$aPos = WinGetPos($hGUI)
$sDebugNotes &= " WinGetPos returns " & $aPos[2] & "x" & $aPos[3] & @CRLF

GUIDelete($hGUI)
#endregion

#region Test2
$sDebugNotes &= @CRLF & "Window with DEFAULT+$WS_SIZEBOX Style:" & @CRLF

Global Const $SM_CXSIZEFRAME = 32
$iBorderSize = _WinAPI_GetSystemMetrics($SM_CXSIZEFRAME)

;~ $hGUI = GUICreate("Demo Window", 640, 480, -1, -1, BitOR($WS_SIZEBOX, $WS_SYSMENU))
$hGUI = GUICreate("Demo Window", 640, 480, -1, -1, BitOR($GUI_SS_DEFAULT_GUI, $WS_SIZEBOX))

$aClientSize = WinGetClientSize($hGUI)
$sDebugNotes &= "  GUICreate [640x480]: WinGetClientSize returns " & $aClientSize[0] & "x" & $aClientSize[1] & ","
$sDebugNotes &= " width borders: " & $aClientSize[0] + ($iBorderSize * 2) & "x" & $aClientSize[1] + ($iCaptionSize + $iBorderSize * 2) & ","

$aPos = WinGetPos($hGUI)
$sDebugNotes &= " WinGetPos returns " & $aPos[2] & "x" & $aPos[3] & @CRLF

WinMove($hGUI, "", Default, Default, 640, 480)

$aClientSize = WinGetClientSize($hGUI)
$sDebugNotes &= "  WinMove   [640x480]: WinGetClientSize returns " & $aClientSize[0] & "x" & $aClientSize[1] & ","
$sDebugNotes &= " width borders: " & $aClientSize[0] + ($iBorderSize * 2) & "x" & $aClientSize[1] + ($iCaptionSize + $iBorderSize * 2) & ","

$aPos = WinGetPos($hGUI)
$sDebugNotes &= " WinGetPos returns " & $aPos[2] & "x" & $aPos[3] & @CRLF

ConsoleWrite($sDebugNotes)
#endregion

comment:2 in reply to: ↑ 1 Changed 6 years ago by vlad@…

I have done something quite similar in my project, but this wasn't quite my point...

WinMove behaves consistently: you tell it to do a 640x480, 640x480 it is, no matter what style the window is (of course, the size of the "client area" will be affected by the thickness of the borders).

GUICreate, on the other hand, creates a window with a mostly random size: you tell it 640x480 and in most cases you get a window that has neither the "outer box" nor the "client area" of 640x480 ... it just happens that for the "default style" the outer box is 640x480.

I believe the implementation of GUICreate should offer some "certitude", in the sense that either the outer or the inner dimensions of the created window should be the ones specified by the calling arguments. It's just a matter of consistency ... Of course, this wouldn't change the fact that most programs will have to figure out the other dimensions so the GUI arrangement matches the intended design.

Anyhow, in my view this issue would fall somewhere between annoyance and minor bug. But as most of the AutoIT features are quite neat and clean, I thought it made sense letting you guys know about it.

comment:3 follow-up: Changed 6 years ago by FireFox

huh, it's the same with Visual Express Form builder.

If you change the FormBorderStyle, it resizes the Form in order to keep the same client area which is IMO quite logic.

And so does autoit.

comment:4 in reply to: ↑ 3 Changed 6 years ago by vlad@…

Keeping the client area constant would be OK as well, but it just doesn't happen in AutoIT (see the BugDemo1.txt file that I've attached originally) - everything changes ...

Replying to FireFox:

huh, it's the same with Visual Express Form builder.

If you change the FormBorderStyle, it resizes the Form in order to keep the same client area which is IMO quite logic.

And so does autoit.

comment:5 Changed 6 years ago by FireFox

I don't see why the internal function of GUICreate would contain superfluous code to create a wrong window size.

I tried with the CreateWindowEx function, it gives different results with some styles but the client area does not correspond either to the size initially set.

comment:6 Changed 6 years ago by Mat

The correct solution is using the AdjustWindowRectEx function. This wrapper around GUICreate should always create a window with the correct client size.

Func _GUICreate($sTitle, $w, $h, $x = -1, $y = -1, $iStyle = -1, $iExStyle = -1, $hParent = 0)
	Local Const $iDefStyle = BitOR($WS_MINIMIZEBOX, $WS_CAPTION, $WS_POPUP, $WS_SYSMENU)
	Local Const $iDefExStyle = $WS_EX_WINDOWEDGE

	If $iStyle = -1 Then $iStyle = $iDefStyle
	If $iExStyle = -1 Then $iExStyle = $iDefExStyle

	Local $rect = DllStructCreate($tagRECT)
	DllStructSetData($rect, "left", $x)
	DllStructSetData($rect, "right", $x + $w)
	DllStructSetData($rect, "top", $y)
	DllStructSetData($rect, "bottom", $y + $h)

	_WinAPI_AdjustWindowRectEx($rect, $iStyle, $iExStyle, False)

	$w = DllStructGetData($rect, "right") - DllStructGetData($rect, "left")
	$h = DllStructGetData($rect, "bottom") - DllStructGetData($rect, "top")

	If $x = -1 Then
		$x = (@DesktopWidth - $w) / 2
	Else
		$x = DllStructGetData($rect, "left")
	EndIf

	If $y = -1 Then
		$y = (@DesktopHeight - $h) / 2
	Else
		$y = DllStructGetData($rect, "top")
	EndIf

	Local $hRet = GUICreate($sTitle, $w, $h, $x, $y, $iStyle, $iExStyle, $hParent)
	WinMove($hRet, "", $x, $y, $w, $h)

	Return $hRet
EndFunc   ;==>_GUICreate

AdjustWindowRectEx has a note about not being able to specify the WS_OVERLAPPED style. I'll have to test what that actually means.

comment:7 Changed 6 years ago by Mat

Full code that works for all the styles I've tested can be found here: http://www.autoitscript.com/forum/topic/154224-winsetclientpos/

Don't think this will be changed in the AutoIt core as a lot of existing scripts probably rely on their windows being the same size.

comment:8 Changed 6 years ago by Jpm

  • Resolution set to No Bug
  • Status changed from new to closed

In fact there is no bug as GUICreate defined the Windows Size not the Client Size
@Mat suggestion is a good suggestion if you want to manage with Client size

Guidelines for posting comments:

  • You cannot re-open a ticket but you may still leave a comment if you have additional information to add.
  • In-depth discussions should take place on the forum.

For more information see the full version of the ticket guidelines here.

Add Comment

Modify Ticket

Action
as closed The ticket will remain with no owner.
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.