Sign in to follow this  
Followers 0
Cotino

Overlay graphic/label

11 posts in this topic

Hi,
I'd like to make an overlay for showing basic things like ping/fps, circle something on the screen, but as an overlay on top of another window.
Bonus point if clicking on the overlay doesn't lose focus of the current window.

I searched here and there, and the closest thing would probably be melba's script here :


However this only allows lines, and lose focus on click.

I'm not sure if that would be possible using Autoit, but does anyone have an idea on how to do this ?

Cheers

Share this post


Link to post
Share on other sites



I believe it's possible, but how to do it, would depend on the window i would say. If the window does not refresh by itself, you could use GDI+. If it does indeed repaint itself, i would suggest a transparent window, generated by Autoit with whatever way to paint it you wish. Thirdly it might be possible to paint the original window, topmost with the same API like DirectDraw

Share this post


Link to post
Share on other sites

I have tried making a transparent window showing graphic to no avail. GDI seems to use the same concept, so the transparent window is still a problem.
The example shown here :

doesn't work.
 

GUISetStyle($WS_POPUP + $WS_VISIBLE, 0x08000000)

It just makes a regular window.

 

I couldn't find any DirectDraw UDF, though that would seem to be the best solution (wouldn't work on the dekstop i presume ?)
Found some for C++, but making GUI in C++ is truly a pain which is why i tend to use mostly autoit.

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

@Cotino

I have a example for the transparent GUI, and found an example from c# with click through window code.

I'll try to combine them and post the small example for you.

 

Edit:

FYI: my example for the transparent GUI is with WINAPI and GDI+

Edited by genius257

Share this post


Link to post
Share on other sites

the code is old and some parts of it may not be needed for the final result. Also i suspect some parts may be taking the "long route" but i haven't looked into this for 2years or more.

here it is:

#include <GUIConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GDIPlus.au3>

Opt("GUIOnEventMode", 1)
Opt("TrayIconHide", 1)

Global $iWidth = 500, $iHeight = $iWidth, $iW = $iWidth, $iH = $iHeight

_GDIPlus_Startup()
$hGUI = GUICreate("", $iWidth, $iHeight, -1, -1, 0, 0x00000020 + 0x00080000 + 0x00000080 + 0x00000008)
$hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI)
$hBitmap = _GDIPlus_BitmapCreateFromGraphics($iWidth, $iHeight, $hGraphics)
$hBackbuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)

; _WinAPI_UpdateLayeredWindow parameters
$tSize = DllStructCreate($tagSIZE)
$pSize = DllStructGetPtr($tSize)
DllStructSetData($tSize, "X", $iWidth)
DllStructSetData($tSize, "Y", $iHeight)

$tSource = DllStructCreate($tagPOINT)
$pSource = DllStructGetPtr($tSource)

Global $alpha =255
Global $alpha_steps = 5
$tBlend = DllStructCreate($tagBLENDFUNCTION)
$pBlend = DllStructGetPtr($tBlend)
DllStructSetData($tBlend, "Alpha", $alpha)
DllStructSetData($tBlend, "Format", 1)

$tPoint = DllStructCreate($tagPOINT) ; For Custom Line Caps
$pPoint = DllStructGetPtr($tPoint)
DllStructSetData($tPoint, "X", 0)
DllStructSetData($tPoint, "Y", 0)

GuiSetState()

$ScreenDc = _WinAPI_GetDC($hGUI)
$gdibitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hbitmap)
$dc = _WinAPI_CreateCompatibleDC($ScreenDc)
ConsoleWrite($dc&@CRLF)
_WinAPI_SelectObject($dc, $gdibitmap)
_WinAPI_DeleteObject($gdibitmap)
; Using antialiasing
_GDIPlus_GraphicsSetSmoothingMode($hBackbuffer, 2)
_GDIPlus_GraphicsSetSmoothingMode($hGraphics, 2)

GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit")

;--------------------[ custom editing]------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
_GDIPlus_GraphicsClear($hBackbuffer, 0x00000000)

$hBrush = _GDIPlus_BrushCreateSolid(0xA0FFFFFF)
$hPen = _GDIPlus_PenCreate(0x50FFFFFF)

_GDIPlus_GraphicsDrawRect($hBackbuffer, 0, 0, $iWidth-1, $iHeight-1, $hPen)
_GDIPlus_GraphicsFillRect($hBackbuffer, 1, 1, $iWidth-2, $iHeight-202, $hBrush)
_GDIPlus_GraphicsFillRect($hBackbuffer, 1, $iHeight-152, $iWidth-2, $iHeight-202-50, $hBrush)

_GDIPlus_BrushSetSolidColor($hBrush, 0x20000000)

Local $aPoints[5][2] = [[4,0],[50, 1],[$iWidth-50, 1], [$iWidth-60, 11], [60, 11]]
_GDIPlus_GraphicsFillPolygon($hBackbuffer, $aPoints, $hBrush)

_GDIPlus_BrushSetSolidColor($hBrush, 0x00000000)
_GDIPlus_GraphicsSetCompositingMode($hBackbuffer, 1)
_GDIPlus_GraphicsFillEllipse($hBackbuffer, 100, 100, 100, 100, $hBrush)

_GDIPlus_BrushDispose($hBrush)
_GDIPlus_PenDispose($hPen)
;-----

$hBmp = _GDIPlus_BitmapCreateFromScan0($iW, $iH, 0x0026200A)
Local $hContext = _GDIPlus_ImageGetGraphicsContext($hBmp)
_GDIPlus_GraphicsDrawImageRect($hContext, $hBitmap, 0, 0, $iW, $iH)

$gdibitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBmp)
_WinAPI_SelectObject($dc, $gdibitmap)
DllStructSetData($tSize, "X", $iW)
DllStructSetData($tSize, "Y", $iH)
_WinAPI_UpdateLayeredWindow($hGUI, $ScreenDc, 0, $pSize, $dc, $pSource, 0, $pBlend, 2)
_WinAPI_DeleteObject($gdibitmap)

_WinAPI_RedrawWindow($hGUI)
_GDIPlus_GraphicsDispose($hContext)
_GDIPlus_BitmapDispose($hBmp)

While Sleep(10)

WEnd

Func _Exit()
    ;---------------------[CleanUp]---------------------------------------------------------------------------------------------------------------------------------
    _WinAPI_DeleteDC($dc)
    _WinAPI_ReleaseDC($hGUI, $ScreenDc)
    ; Clean up GDI+ resources
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_GraphicsDispose($hBackbuffer)
    _GDIPlus_GraphicsDispose($hGraphics)
    ; Uninitialize GDI+
    _GDIPlus_Shutdown()
    GUIDelete($hGUI)
    Exit
EndFunc

 

Share this post


Link to post
Share on other sites

Thank you kind sir for sharing your code.

I will try this at once and give feedback/simplified version.

Share this post


Link to post
Share on other sites

Here is a simplified version :

#include <WindowsConstants.au3>
#include <GDIPlus.au3>

HotKeySet("{ESC}", "_Exit") ; Only way to exit

Opt("GUIOnEventMode", 1) ; Set event mode
;~ Opt("TrayIconHide", 1) ; Hide tray icon

; ######################
; Global parameters

$iX = 0 ; -1 for centered
$iY = 0
$iWidth = @DesktopWidth
$iHeight = @DesktopHeight

; ######################
; Create Graphic

_GDIPlus_Startup()
$hGUI = GUICreate("", $iWidth, $iHeight, $iX, $iY, 0, $WS_EX_TRANSPARENT + $WS_EX_LAYERED + $WS_EX_TOOLWINDOW + $WS_EX_TOPMOST)

$hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI)
$hBitmap = _GDIPlus_BitmapCreateFromGraphics($iWidth, $iHeight, $hGraphics)
$hBackbuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)

$ScreenDc = _WinAPI_GetDC($hGUI)
$gdibitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hbitmap)
$dc = _WinAPI_CreateCompatibleDC($ScreenDc)

; ######################
; _WinAPI_UpdateLayeredWindow parameters

$tSize = DllStructCreate($tagSIZE)
$pSize = DllStructGetPtr($tSize)
DllStructSetData($tSize, "X", $iWidth)
DllStructSetData($tSize, "Y", $iHeight)

$tSource = DllStructCreate($tagPOINT)
$pSource = DllStructGetPtr($tSource)

$tBlend = DllStructCreate($tagBLENDFUNCTION)
$pBlend = DllStructGetPtr($tBlend)
DllStructSetData($tBlend, "Alpha", 255)
DllStructSetData($tBlend, "Format", 1)

; struct tSize { X = $iWidth, Y = $iHeight } (pointer pSize)
; struct tSource { } (pointer pSource)
; struct tBlend { Alpha = 255, Format = 1 } (pointer pBlend)

; ###########################################
; Create shapes

_GDIPlus_GraphicsClear($hBackbuffer, 0)
$hBrush = _GDIPlus_BrushCreateSolid(0)
$hPen = _GDIPlus_PenCreate(0)

#cs
GDIPlus memo :
Use pen to draw (outline of shape)
Use brush to fill
You can fill without drawing
Alpha : 00 is transparent. FF is opaque
ARGB : 0xAARRGGBB

Pen :
_GDIPlus_PenSetWidth($hPen, widthInPixel)
_GDIPlus_PenSetColor($hPen, ARGB)

Brush :
_GDIPlus_BrushSetSolidColor($hBrush, ARGB)

Rectangle :
_GDIPlus_GraphicsDrawRect($hBackbuffer, X, Y, width, height, $hPen)
_GDIPlus_GraphicsFillRect($hBackbuffer, X, Y, width, height, $hBrush)

Ellipse :
_GDIPlus_GraphicsDrawEllipse($hBackbuffer, X, Y, width, height, $hPen)
_GDIPlus_GraphicsFillEllipse($hBackbuffer, X, Y, width, height, $hBrush)

String :
All of the following are needed
$hFormat = _GDIPlus_StringFormatCreate()
$hFamily = _GDIPlus_FontFamilyCreate("Arial")
$hFont = _GDIPlus_FontCreate($hFamily, fontSize)
$tLayout = _GDIPlus_RectFCreate(X, Y)
$sString = "String"
$aInfo = _GDIPlus_GraphicsMeasureString($hBackBuffer, $sString, $hFont, $tLayout, $hFormat)
_GDIPlus_GraphicsDrawStringEx($hBackBuffer, $sString, $hFont, $aInfo[0], $hFormat, $hBrush)
_GDIPlus_FontDispose($hFont)
_GDIPlus_FontFamilyDispose($hFamily)
_GDIPlus_StringFormatDispose($hFormat)


More complex shapes are available
Search for _GDIPlus_Graphics in the help

#ce

; ###########################################
; Write your shapes below

;~ ; Red transparent rectangle
;~ _GDIPlus_BrushSetSolidColor($hBrush, 0x60FF0000)
;~ _GDIPlus_GraphicsFillRect($hBackbuffer, $iWidth/2-$iX-100, $iHeight/2-$iY-100, 200, 200, $hBrush)

;~ ; Blue circle outline
;~ _GDIPlus_PenSetWidth($hPen, 5)
;~ _GDIPlus_PenSetColor($hPen, 0xFF0000FF)
;~ _GDIPlus_GraphicsDrawEllipse($hBackbuffer, $iX, $iY, $iWidth, $iHeight, $hPen)

;~ ; Green string
;~ _GDIPlus_BrushSetSolidColor($hBrush, 0xFF00FF00)
;~ $hFormat = _GDIPlus_StringFormatCreate()
;~ $hFamily = _GDIPlus_FontFamilyCreate("Consolas")
;~ $hFont = _GDIPlus_FontCreate($hFamily, 20, 1)
;~ $tLayout = _GDIPlus_RectFCreate($iWidth/2-$iX, $iHeight/2-$iY-200)
;~ $sString = "I am a green opaque string"
;~ $aInfo = _GDIPlus_GraphicsMeasureString($hBackBuffer, $sString, $hFont, $tLayout, $hFormat)
;~ _GDIPlus_GraphicsDrawStringEx($hBackBuffer, $sString, $hFont, $aInfo[0], $hFormat, $hBrush)
;~ _GDIPlus_FontDispose($hFont)
;~ _GDIPlus_FontFamilyDispose($hFamily)
;~ _GDIPlus_StringFormatDispose($hFormat)

; ###########################################
_GDIPlus_BrushDispose($hBrush)
_GDIPlus_PenDispose($hPen)
; ###########################################
; Show image

$hBmp = _GDIPlus_BitmapCreateFromScan0($iWidth, $iHeight, $GDIP_PXF32ARGB)
$hContext = _GDIPlus_ImageGetGraphicsContext($hBmp)
_GDIPlus_GraphicsDrawImageRect($hContext, $hBitmap, 0, 0, $iWidth, $iHeight)

$gdibitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBmp)
_WinAPI_SelectObject($dc, $gdibitmap)
_WinAPI_UpdateLayeredWindow($hGUI, $ScreenDc, 0, $pSize, $dc, $pSource, 0, $pBlend, 2)
_WinAPI_DeleteObject($gdibitmap)

_WinAPI_RedrawWindow($hGUI)
_GDIPlus_GraphicsDispose($hContext)
_GDIPlus_BitmapDispose($hBmp)

; ###########################################


GUISetState(@SW_SHOW, $hGUI)

While 1
    Sleep(10)
WEnd

Func _Exit()
    _WinAPI_DeleteDC($dc)
    _WinAPI_ReleaseDC($hGUI, $ScreenDc)
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_GraphicsDispose($hBackbuffer)
    _GDIPlus_GraphicsDispose($hGraphics)
    _GDIPlus_Shutdown()
    GUIDelete($hGUI)
    Exit
EndFunc


_GDIPlus_GraphicsDrawStringEx makes the string have a black outline, which makes small font size unreadable.

Aside from that it works pretty neatly, i don't quite understand everything that's going on but it works.

Just modify the part under "Write your shapes below" and eventually the global parameters if you want to modify the window size.

Share this post


Link to post
Share on other sites
16 hours ago, Cotino said:

_GDIPlus_GraphicsDrawStringEx makes the string have a black outline, which makes small font size unreadable.

I don't know how much experience you have with GDI+, but you can set many options, changing the final result of your "picture".

So with that in mind i knew it was something with the render/string-render settings, i googled: "gdiplus string black outline". 3rd result, accepted answer:

Quote

tempGr.TextRenderingHint = TextRenderingHint.AntiAlias;

Then, knowing the AuotIt "GDIPlus.au3" function name syntax i try: "_gdiplus_graphics", because it's an option, within graphics, then i add: "set", because i want to set it, naturally. And finially the option, as named in the answer i quoted above: "TextRenderingHint". I would suggesting searching the AutoIt help for "TextRenderingHint", but the search is far from perfect, and i personal don't get any results.

Then i read about the paraimiters, trying to find the "AntiAlias". I find second parimiter should be 4:

_GDIPlus_GraphicsSetTextRenderingHint($hBackBuffer, 4)

This will remove the black outline in my case at least.

 

 

16 hours ago, Cotino said:

HotKeySet("{ESC}", "_Exit") ; Only way to exit

Also, i would haft to say this is a wrong assumption. The tray icon is not hidden, so the script can be closed like that. In my example you can close it with Esc, but only if you don't change the window focus (ie. clicking) after script launch.

 

 

But yeah you sure slimmed it down :) A suggestion: don't use "HotKeySet", it's hell if another script uses the same keys and if there's no other way to exit the application.

Share this post


Link to post
Share on other sites

What would you use instead of hotkeyset ?
In your example you removed the tray icon and i couldn't find any way to close the window, that's why i added that.

As you can guess my experience with gdi+ is about one hour when i looked at your script. I can see it has a lot of potential (there are lots of wonderful examples from UEZ on this forum)

Nice finding for the black outline, i didn't look much further as i didn't really need it right now but it sure makes it look smoother. Kinda weird it's not naturally like that, but heh i didn't code gdi+.

TBH i would never have made it all by myself simply because of the struct, it would never occur to me that autoit would need a struct, so thanks a lot for your help.

Share this post


Link to post
Share on other sites
4 minutes ago, Cotino said:

What would you use instead of hotkeyset ?

I would suggest a custom trayicon menu. Currently you only really need a entry named "Exit". I personally recommend something like this:

Opt("TrayMenuMode", 3)
Opt("TrayOnEventMode", 1)
TrayCreateItem("Exit")
TrayItemSetOnEvent(-1, "_Exit")

 

17 minutes ago, Cotino said:

In your example you removed the tray icon and i couldn't find any way to close the window, that's why i added that.

As i mentioned in my previous post, my example can be closed with the "Esc" key, as long as you don't remove window focus. I realize it's not a practical way of doing it for the actual application.

19 minutes ago, Cotino said:

As you can guess my experience with gdi+ is about one hour when i looked at your script. I can see it has a lot of potential (there are lots of wonderful examples from UEZ on this forum)

Well i hope you'll get at least as mutch fun with GDI+, as i have :). And yeah, UEZ is the "big daddy" with GDI+ examples :lol:. But in my experience, his areas of expertise is broad and deep :)

25 minutes ago, Cotino said:

Nice finding for the black outline, i didn't look much further as i didn't really need it right now but it sure makes it look smoother. Kinda weird it's not naturally like that, but heh i didn't code gdi+.

Thank you :). Well i think it has something to do with speed and maybe the default options is just for portability, so a newer version of the GDI+ won't render anything differently. That's just my guess though.

28 minutes ago, Cotino said:

TBH i would never have made it all by myself simply because of the struct, it would never occur to me that autoit would need a struct, so thanks a lot for your help.

Well i did not make it from scratch :) I would love to add credit to the origin sources of inspiration, within this forum, however it's been so long so i can't remember where i got the different bits and pieces. I just got it to work, out of desperation, to make a TRULY transparent gdi+ with tranparency for ALL colors. You see, some solutions will use a color as the tranparency key, without regard for transparency, so if i got an image with an rainbow, and a gradient background from black to white, transparency 255 to 0 left to right. Some parts of that image will be See-through, even though the alpha channel of the image on those parts may be 255.

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
Sign in to follow this  
Followers 0