Leo1906

Can't display png as GUI on Windows 7

6 posts in this topic

#1 ·  Posted (edited)

Hello there, it's me aggain .. :D

I just noticed that displaying a png GUI doesn't seem to work on Windows 7 ..?
I recently used some code written by UEZ with some minor changes:

#include <ButtonConstants.au3>
#include <MsgBoxConstants.au3>
#include <StructureConstants.au3>
#include <WinAPIConstants.au3>
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>


$hMain = GUICreate("Parent", 400, 400, -1, -1, $WS_POPUP, BitOR($WS_EX_LAYERED,$WS_EX_TOOLWINDOW,$WS_EX_TOPMOST,$WS_EX_LAYERED))
_WinAPI_SetLayeredWindowAttributes($hMain, 0xABCDEF, 255)
GUISetBkColor(0xABCDEF)
GUISetState()

_GDIPlus_Startup()
Global Const $SC_DRAGMOVE = 0xF012
Global $iW, $iH, $hImage, $hBitmap, $hGUI
$hImage = _GDIPlus_BitmapCreateFromFile("C:\Program Files (x86)\AutoIt3\Examples\GUI\Torus.png")
$hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
$iW = _GDIPlus_ImageGetWidth($hImage)
$iH = _GDIPlus_ImageGetHeight($hImage)
$hGUI = GUICreate("", $iW, $iH, 0, 0, $WS_POPUP, $WS_EX_LAYERED)
_WinAPI_SetParent($hGUI, $hMain)
GUISetState()
_WinAPI_BitmapDisplayTransparentInGUI($hBitmap, $hGUI)

;~ GUIRegisterMsg($WM_NCHITTEST, "WM_NCHITTEST")
GUIRegisterMsg($WM_LBUTTONDOWN, "_WM_LBUTTONDOWN")

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

_WinAPI_DeleteObject($hBitmap)
_GDIPlus_BitmapDispose($hImage)
_GDIPlus_Shutdown()
GUIDelete()

Func _WinAPI_BitmapDisplayTransparentInGUI(ByRef $hHBitmap, ByRef $hGUI, $iOpacity = 0xFF, $bReleaseGDI = True)
    If Not BitAND(GUIGetStyle($hGUI)[1], $WS_EX_LAYERED) = $WS_EX_LAYERED Then Return SetError(1, 0, 0)
    Local $tDim = DllStructCreate($tagBITMAP)
    If Not _WinAPI_GetObject($hHBitmap, DllStructGetSize($tDim), DllStructGetPtr($tDim)) Then Return SetError(2, 0, 0)
    Local $tSize = DllStructCreate($tagSIZE), $tSource = DllStructCreate($tagPOINT), $tBlend = DllStructCreate($tagBLENDFUNCTION)
    Local Const $hScrDC = _WinAPI_GetDC(0), $hMemDC = _WinAPI_CreateCompatibleDC($hScrDC), $hOld = _WinAPI_SelectObject($hMemDC, $hHBitmap)
    $tSize.X = $tDim.bmWidth
    $tSize.Y = $tDim.bmHeight
    $tBlend.Alpha = $iOpacity
    $tBlend.Format = 1
    _WinAPI_UpdateLayeredWindow($hGUI, $hScrDC, 0, DllStructGetPtr($tSize), $hMemDC, DllStructGetPtr($tSource), 0, DllStructGetPtr($tBlend), $ULW_ALPHA)
    _WinAPI_ReleaseDC(0, $hScrDC)
    _WinAPI_SelectObject($hMemDC, $hOld)
    _WinAPI_DeleteDC($hMemDC)
    If $bReleaseGDI Then _WinAPI_DeleteObject($hHBitmap)
    Return True
EndFunc

Func _WM_LBUTTONDOWN($hWnd, $iMsg, $wParam, $lParam)
    _SendMessage($hGUI, $WM_SYSCOMMAND, $SC_DRAGMOVE, 0)
EndFunc   ;==>_WM_LBUTTONDOWN

Func WM_NCHITTEST($hWnd, $iMsg, $iwParam, $ilParam)
    If ($iMsg = $WM_NCHITTEST) Then Return $HTCAPTION
EndFunc

The png GUI is a child GUI, captured in the invisible borders of the parent GUI.

I was using this code under Windows 10 Pro without any problems. Now I tried it with Windows 7 Ultimate (32 Bit - on VMWare) and Windows 7 Professional (32 Bit) (real laptop).
Using any of those operating systems the code will be executed without errors but won't display anything ..
(the path to the png was ofcourse adjusted :D)

I didn't test Windows 8 right now, because if have no running installation of it, but I will set it up on a VM soon ..

Any ideas why this feature isn't available on all recent OS?
Searching the forum didn't help ..

Thanks for your help! :) 

 

Edit: just testet under Windows 8.1 x64 and the png is shown .. So it seems to be a Windows 7 only problem?

Edit2: maybe something with _WinAPI_SetParent() ..? Because if this get's disabled the GUI is displayed (but not inside the other GUI ..)

Edited by Leo1906

Share this post


Link to post
Share on other sites



I can't test things right now, but I did notice that this Program Files path is not valid on my Win7 Pro 32-bit:

$hImage = _GDIPlus_BitmapCreateFromFile("C:\Program Files (x86)\AutoIt3\Examples\GUI\Torus.png")

There is no "(x86)" portion.

 

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

4 hours ago, qwert said:

I can't test things right now, but I did notice that this Program Files path is not valid on my Win7 Pro 32-bit

To avoid such problem i use:

Local $sAutoItPath = StringReplace(StringReplace(@AutoItExe,"_64",""), "autoit3.exe", "")
ConsoleWrite($sAutoItPath & "Examples\GUI\msoobe.jpg" & @CRLF)

 

Edited by AutoBert

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

Well .. I'm not stupid and as I said: I adjustet the path to point to the png. So that's definitly not the problem ..

 

Edit: The same with non PNG-GUIs. Normal $WS_POPUP GUI won't be shown either. Example code:

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WinApi.au3>

HotKeySet("^w", "_test") ; ctrl + w
Global $numberCores = 7
Global $WorkAera = _GetWorkArea()
Global $GUIFADE_MAXTRANS = 240

$dummy = GUICreate("", 255, $numberCores*50+140, @DesktopWidth-255, $WorkAera[3]-$numberCores*50-165, $WS_POPUP, BitOR($WS_EX_LAYERED,$WS_EX_TOPMOST))
;~ _WinAPI_SetLayeredWindowAttributes($dummy, 0xABCDEF, 255)
;~ GUISetBkColor(0xABCDEF)
GUISetState(@SW_SHOWNA)

$MainGUIMainGUI = GUICreate("ThreadMain", 230, 130,10, 10, BitOR($WS_POPUP, $WS_SYSMENU, $WS_MINIMIZEBOX), $WS_EX_TOPMOST)
GUISetBkColor(0x919191)
;~ WinSetTrans($MainGUIMainGUI, "", 240)
$progressALL = GUICtrlCreateProgress(20, 70, 190, 20)

_GuiRoundCorners($MainGUIMainGUI, 0, 0, 20, 20)

_WinAPI_SetParent($MainGUIMainGUI, $dummy)
GUISetState(@SW_SHOWNA, $MainGUIMainGUI)


GUIRegisterMsg($WM_NCHITTEST, "WM_NCHITTEST")
GUIRegisterMsg($WM_WINDOWPOSCHANGING, 'WM_WINDOWPOSCHANGING')
_FadeInGUI($MainGUIMainGUI)

While 1
    Sleep(100)
WEnd

Func WM_WINDOWPOSCHANGING($hWnd, $iMsg, $wParam, $lParam)
    #forceref $iMsg, $wParam, $lParam
        Local $aWinGetPos = WinGetPos($hWnd)
        If @error Then Return $GUI_RUNDEFMSG
        Local $tWindowPos = DllStructCreate($tagWINDOWPOS, $lParam)
;~      If DLLStructGetData($tWindowPos, "X") < @DesktopWidth-235 Then
;~          DllStructSetData($tWindowPos, 'X', $aWinGetPos[0])
;~      EndIf
        DllStructSetData($tWindowPos, 'Y', 10)
        Return $GUI_RUNDEFMSG
EndFunc

Func WM_NCHITTEST($hWnd, $iMsg, $iwParam, $ilParam)
    If ($iMsg = $WM_NCHITTEST) Then Return $HTCAPTION
EndFunc

Func _GetWorkArea()
    Local $Area[6]
    Local $StartRect = DllStructCreate("int[4]")
    Local $PStartRect = DllStructGetPtr($StartRect)
    DllCall("user32.dll", "int", "SystemParametersInfo", "int", 48, "int", 0, "ptr", $PStartRect, "int", 0)
    $Area[0] = DllStructGetData($StartRect,1,1)
    $Area[1] = DllStructGetData($StartRect,1,2)
    $Area[2] = DllStructGetData($StartRect,1,3)
    $Area[3] = DllStructGetData($StartRect,1,4)
    $Area[4] = $Area[2] - $Area[0]
    $Area[5] = $Area[3] - $Area[1]
    Return $Area
EndFunc

Func _GuiRoundCorners($h_win, $i_x1, $i_y1, $i_x3, $i_y3)
    Dim $pos, $ret, $ret2
    $pos = WinGetPos($h_win)
    $ret = DllCall("gdi32.dll", "long", "CreateRoundRectRgn", "long", $i_x1, "long", $i_y1, "long", $pos[2], "long", $pos[3], "long", $i_x3, "long", $i_y3)
    If $ret[0] Then
        $ret2 = DllCall("user32.dll", "long", "SetWindowRgn", "hwnd", $h_win, "long", $ret[0], "int", 1)
        If $ret2[0] Then
            Return 1
        Else
            Return 0
        EndIf
    Else
        Return 0
    EndIf
EndFunc

Func _FadeInGUI($hWnd)
    WinSetTrans($hWnd, "", 0)
    GUISetState(@SW_SHOW, $hWnd)
    For $i = 1 To $GUIFADE_MAXTRANS Step 0.05
        WinSetTrans($hWnd, "", $i)
    Next
EndFunc

Func _FadeOutGUI($hWnd)
    For $i = $GUIFADE_MAXTRANS To 0 Step -0.05
        WinSetTrans($hWnd, "", $i)
    Next
    GUISetState(@SW_HIDE, $hWnd)
EndFunc

Func _test()
;~  WinActivate($hChild)
    WinMove($dummy, "", 100, 100, 500, 500, 10)
EndFunc

This code works fine under Windows 8.1, Windows 10 and Windows Server 2012 (all three testet).
The code does not work on Windows XP, Windows Vista and Windows 7 (tested)

But where's the problem? MSDN says that minimum requirement for the SetParent function is Windows 2000, so that should work .. but it obvioulsy doesn't ..? Is the DllCall in the WinAPI.au3 not ok?

Edited by Leo1906

Share this post


Link to post
Share on other sites

What I found is that it depends on if Aero is enabled. Further coordinates for the image are not relative to the main GUI.

Example:

#include <ButtonConstants.au3>
#include <MsgBoxConstants.au3>
#include <StructureConstants.au3>
#include <WinAPIConstants.au3>
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

Global $tChkAero = DllStructCreate("int Enabled;")
DllCall("DwmApi.Dll", "int", "DwmIsCompositionEnabled", "ptr", DllStructGetPtr($tChkAero))
If $tChkAero.Enabled Then DllCall("DwmApi.Dll", "int", "DwmEnableComposition", "uint", 0)

$hMain = GUICreate("Parent", @DesktopWidth, @DesktopHeight, -1, -1, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOPMOST))
;~ GUISetBkColor(0xABCDEF)
;~ _WinAPI_SetLayeredWindowAttributes($hMain, 0xABCDEF, 255)

_GDIPlus_Startup()
Global Const $SC_DRAGMOVE = 0xF012
Global $iW, $iH, $hImage, $hBitmap, $hGUI
$hImage = _GDIPlus_BitmapCreateFromFile("C:\Program Files (x86)\AutoIt3\Examples\GUI\Torus.png")
$hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
$iW = _GDIPlus_ImageGetWidth($hImage)
$iH = _GDIPlus_ImageGetHeight($hImage)
$aPos = WinGetPos($hMain)

$hGUI = GUICreate("", $iW, $iH, 500, 300, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOPMOST))

_WinAPI_SetParent($hGUI, $hMain)
_WinAPI_BitmapDisplayTransparentInGUI($hBitmap, $hGUI)

GUISetState(@SW_SHOWNA, $hMain)
GUISetState(@SW_SHOW, $hGUI)


;~ GUIRegisterMsg($WM_NCHITTEST, "WM_NCHITTEST")
GUIRegisterMsg($WM_LBUTTONDOWN, "_WM_LBUTTONDOWN")

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

_WinAPI_DeleteObject($hBitmap)
_GDIPlus_BitmapDispose($hImage)
_GDIPlus_Shutdown()
GUIDelete()
If $tChkAero.Enabled Then DllCall("DwmApi.Dll", "int", "DwmEnableComposition", "uint", 1)

Func _WinAPI_BitmapDisplayTransparentInGUI(ByRef $hHBitmap, ByRef $hGUI, $iOpacity = 0xFF, $bReleaseGDI = True)
    If Not BitAND(GUIGetStyle($hGUI)[1], $WS_EX_LAYERED) = $WS_EX_LAYERED Then Return SetError(1, 0, 0)
    Local $tDim = DllStructCreate($tagBITMAP)
    If Not _WinAPI_GetObject($hHBitmap, DllStructGetSize($tDim), DllStructGetPtr($tDim)) Then Return SetError(2, 0, 0)
    Local $tSize = DllStructCreate($tagSIZE), $tSource = DllStructCreate($tagPOINT), $tBlend = DllStructCreate($tagBLENDFUNCTION)
    Local Const $hScrDC = _WinAPI_GetDC(0), $hMemDC = _WinAPI_CreateCompatibleDC($hScrDC), $hOld = _WinAPI_SelectObject($hMemDC, $hHBitmap)
    $tSize.X = $tDim.bmWidth
    $tSize.Y = $tDim.bmHeight
    $tBlend.Alpha = $iOpacity
    $tBlend.Format = 1
    _WinAPI_UpdateLayeredWindow($hGUI, $hScrDC, 0, DllStructGetPtr($tSize), $hMemDC, DllStructGetPtr($tSource), 0, DllStructGetPtr($tBlend), $ULW_ALPHA)
    _WinAPI_ReleaseDC(0, $hScrDC)
    _WinAPI_SelectObject($hMemDC, $hOld)
    _WinAPI_DeleteDC($hMemDC)
    If $bReleaseGDI Then _WinAPI_DeleteObject($hHBitmap)
    Return True
EndFunc

Func _WM_LBUTTONDOWN($hWnd, $iMsg, $wParam, $lParam)
    _SendMessage($hGUI, $WM_SYSCOMMAND, $SC_DRAGMOVE, 0)
EndFunc   ;==>_WM_LBUTTONDOWN

Func WM_NCHITTEST($hWnd, $iMsg, $iwParam, $ilParam)
    If ($iMsg = $WM_NCHITTEST) Then Return $HTCAPTION
EndFunc

The image cannot be moved.


Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯

Share this post


Link to post
Share on other sites

Ok good to know. So this feature is basically not available for Windows below 8 ..
Windows XP has no aero either, but it still doesn't work. And disabling the aero like you do know isn't a great of a deal I think .. :D 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now