[GDI+ Object] Subtitle.Render() - Beautiful Text on Screen
Re: Subtitle.Render() - Show text with style (Easy, painless Gdip interpreter)
thanx a lot for these great examples... opened my eyes instantly!
Re: Subtitle.Render() - Show text with style (Easy, painless Gdip interpreter)
Any chance to get x and y position after dragging with left mouse? I tried it with postmessage, a1, 2... no success!
Re: Subtitle.Render() - Show text with style (Easy, painless Gdip interpreter)
I do not think so. When you send PostMessage, 0xA1, 2, you are moving the window, not the object drawn on the window.
You should be moving the object drawn on the window by changing the x and y values.
To give you an idea, you can use MouseGetPos to find your (x, y) value. When you click on the screen, save the values as x_click, y_click. Then when you are dragging, save the new values as x_drag, y_drag.
Subtract. dx := x_drag - x_click. Now add dx to the the x value you set in background. Add dy to the y value you set in background. I apologize if this isn't a clear explanation.
Keep in mind I am not trying to port Rainmeter over to AHK, even though it is possible. It's just too much work.
Even though this reminds me of string.meter
You should be moving the object drawn on the window by changing the x and y values.
To give you an idea, you can use MouseGetPos to find your (x, y) value. When you click on the screen, save the values as x_click, y_click. Then when you are dragging, save the new values as x_drag, y_drag.
Subtract. dx := x_drag - x_click. Now add dx to the the x value you set in background. Add dy to the y value you set in background. I apologize if this isn't a clear explanation.
Keep in mind I am not trying to port Rainmeter over to AHK, even though it is possible. It's just too much work.
Even though this reminds me of string.meter
Re: Subtitle.Render() - Show text with style (Easy, painless Gdip interpreter)
thanks for the clear explanation, iseahound... while checking out my tips'n'tricks-repository grabbed the following solution:
after coding a little with sendmessage, 0xA1, 2 I found out that using a dummy-key for GetKeyState, status would position the objects (background and text) by dragging as expected.
So here's a tiny code for a desktop-clock using your fantastic subtitle-class for any purpose and testing... hints are welcome!
P.S.: we don't want just to copy any released application or its design, but never give up to be curious and inspired...
after coding a little with sendmessage, 0xA1, 2 I found out that using a dummy-key for GetKeyState, status would position the objects (background and text) by dragging as expected.
So here's a tiny code for a desktop-clock using your fantastic subtitle-class for any purpose and testing... hints are welcome!
Code: Select all
; subtitleDESKTOPCLOCK - using class_Subtitle and Gdip_All (many thanks to iseahound and tic)
; draggable with CTRL + leftbutton (center-positioned)
; Exit with ESC
; ===========================================================================================
#include class_Subtitle.ahk
#include Gdip_All.ahk
CoordMode, Mouse, Screen
OnMessage(0x201, "OnLeftClick")
IfNotExist, %A_ScriptDir%\config.ini
ExitApp
IniRead, xpos, %A_ScriptDir%\config.ini, desktopclock, xpos
IniRead, ypos, %A_ScriptDir%\config.ini, desktopclock, ypos
pToken := Gdip_Startup()
desktopclock := new Subtitle()
font := "Arial Black"
size := 100
w := size * 6
ydif := size - 28
background := {"x":xpos, "y":ypos, "w":"550", "h":"150", "r":"20" , "anchor":2, "color":"0x10FFFFFF"}
text := {"x":xpos, "y":ypos, "w":w, "anchor":2, "font":font, "size":size, "color":"FFFFFFFF"}
text.outline := {"width":"20", "color":"FF8000", "glow":"0", "glowcolor":"FFFFFFFF"}
text.dropShadow := {"blur":"8", "color":"25000000", "horizontal":"8", "vertical":"8", "strength":"100"}
SetTimer, ticktack, 992
ticktack:
text.x := background.x := xpos
text.y := background.y := ypos
FormatTime, time,, HH·mm·ss
desktopclock.Draw(time, background, text)
desktopclock.Render(time, "cNone", text)
Return
GuiEscape:
ExitApp
OnLeftClick() {
GetKeyState, status, Ctrl ; draggable only with CTRL
If status = D ; while key is down...
{
SendMessage, 0xA1, 2 ; make draggable
GetKeyState, status, SHIFT ; get dummybutton-status
If status = U ; positioning after release dummybutton
{
global xpos, ypos, ydif
MouseGetPos, dragx, dragy
xpos := dragx
ypos := dragy - ydif ; repositioning mouse, centered for dragging after
IniWrite, %xpos%, %A_ScriptDir%\config.ini, desktopclock, xpos
IniWrite, %ypos%, %A_ScriptDir%\config.ini, desktopclock, ypos
}
}
}
Return
Re: Subtitle.Render() - Show text with style (Easy, painless Gdip interpreter)
...content of my config.ini (has to be created and saved in script-dir )
Code: Select all
[desktopclock]
xpos =200
ypos =200
Re: Subtitle.Render() - Show text with style (Easy, painless Gdip interpreter)
Why did you need a dummy button? I got it to work without. It still flashes someones when you release the left mouse button, but I imagine that is due to the timer and gosub clashing or something.
Code: Select all
; subtitleDESKTOPCLOCK - using class_Subtitle and Gdip_All (many thanks to iseahound and tic)
; draggable with CTRL + leftbutton (center-positioned)
; Exit with ESC
; ===========================================================================================
#include class_Subtitle.ahk
#include Gdip_All.ahk
CoordMode, Mouse, Screen
Global xpos, ypos
OnMessage(0x201, "OnLeftClick")
IfNotExist, %A_ScriptDir%\config.ini
xpos := 400, ypos := 200
Else {
IniRead, xpos, %A_ScriptDir%\config.ini, desktopclock, xpos
IniRead, ypos, %A_ScriptDir%\config.ini, desktopclock, ypos
}
pToken := Gdip_Startup()
desktopclock := new Subtitle()
font := "Arial Black"
size := 100
w := size * 6
ydif := size - 28
background := {"x":xpos, "y":ypos, "w":"550", "h":"150", "r":"20" , "anchor":2, "color":"0x10FFFFFF"}
text := {"x":xpos, "y":ypos, "w":w, "anchor":2, "font":font, "size":size, "color":"FFFFFFFF"}
text.outline := {"width":"20", "color":"FF8000", "glow":"0", "glowcolor":"FFFFFFFF"}
text.dropShadow := {"blur":"8", "color":"25000000", "horizontal":"8", "vertical":"8", "strength":"100"}
SetTimer, ticktack, 992
ticktack:
text.x := background.x := xpos
text.y := background.y := ypos
FormatTime, time,, HH:mm:ss
desktopclock.Draw(time, background, text)
desktopclock.Render(time, "cNone", text)
Return
GuiEscape:
ExitApp
OnLeftClick() {
MouseGetPos, xClick, yClick ; Where did we click on the screen
GetKeyState, status, Ctrl ; draggable only with CTRL
If (status = "D") { ; while key is down...
SendMessage, 0xA1, 2 ; make draggable
MouseGetPos, dragx, dragy
xpos := dragx - (xclick - xpos) ; Get our x-offset on the rendering
ypos := dragy - (yClick - ypos) ; Get our y-offset on the rendering
; Save the values
IniWrite, %xpos%, %A_ScriptDir%\config.ini, desktopclock, xpos
IniWrite, %ypos%, %A_ScriptDir%\config.ini, desktopclock, ypos
; Update the position
GoSub, ticktack
}
}
Return
Re: Subtitle.Render() - Show text with style (Easy, painless Gdip interpreter)
well improved... thanks for clean-up, kczx3
regarding the dummybutton, I stumbled over an old code and unfortunately decided to take that (crappy) one...
Only positive vertical-movements (dragy > ypos) show no flashes... no idea, maybe someone else
regarding the dummybutton, I stumbled over an old code and unfortunately decided to take that (crappy) one...
Only positive vertical-movements (dragy > ypos) show no flashes... no idea, maybe someone else
Re: Subtitle.Render() - Show text with style (Easy, painless Gdip interpreter)
I ended up removing a lot of "extra" code
Try to avoid sendmessage, 0xA1, 2 and PostMessage, 0xA1, 2 because we want to move the Subtitle Object, not the window it is drawn on.
You don't need to specify the width or height ever, because my Subtitle class will compute that for you. Also, there's no need to ever change text x, y positions, as that is also computed for you!
I changed the render time to 10 milliseconds. Depending on your CPU, this is 10 milliseconds, 15.6 milliseconds, or 1 tick of the processor. This may eat up some CPU power, but I'm sure you can modify the code so that it only draws at 10 milliseconds a frame when it is being dragged.
Also strength doesn't do anything at the moment.
Code: Select all
; subtitleDESKTOPCLOCK - using class_Subtitle and Gdip_All (many thanks to iseahound and tic)
; draggable with CTRL + leftbutton (center-positioned)
; Exit with ESC
; ===========================================================================================
#include class_Subtitle.ahk
#include Gdip_All.ahk
CoordMode, Mouse, Screen
OnMessage(0x201, "OnLeftClick")
isClicked := 0
pToken := Gdip_Startup()
desktopclock := new Subtitle()
font := "Arial Black"
size := 100
background := {"x":400, "y":200, "anchor":2, "color":"0x10FFFFFF"}
text := {"font":font, "size":size, "color":"FFFFFFFF"}
text.outline := {"width":"20", "color":"FF8000", "glow":"0", "glowcolor":"FFFFFFFF"}
text.dropShadow := {"blur":"8", "color":"25000000", "horizontal":"8", "vertical":"8", "strength":"100"}
SetTimer, ticktack, 10 ; Changed to 10 milliseconds for smooth animation.
return
ticktack(){
global desktopClock, background, text
global xpos, ypos, isClicked, xClick, yClick
FormatTime, time,, HH:mm:ss
if (isClicked = 1 && GetKeyState("Ctrl")) {
MouseGetPos, dragx, dragy
background.x := xpos + dragx - xClick
background.y := ypos + dragy - yClick
}
if (!GetKeyState("LButton"))
isClicked := 0
desktopclock.Render(time, background, text)
Return
}
GuiEscape:
ExitApp
OnLeftClick() {
global ; Make all these values global.
isClicked := 1
MouseGetPos, xClick, yClick
xpos := background.x
ypos := background.y
}
Return
You don't need to specify the width or height ever, because my Subtitle class will compute that for you. Also, there's no need to ever change text x, y positions, as that is also computed for you!
I changed the render time to 10 milliseconds. Depending on your CPU, this is 10 milliseconds, 15.6 milliseconds, or 1 tick of the processor. This may eat up some CPU power, but I'm sure you can modify the code so that it only draws at 10 milliseconds a frame when it is being dragged.
Also strength doesn't do anything at the moment.
Re: Subtitle.Render() - Show text with style (Easy, painless Gdip interpreter)
I've finally added some documentation.
Click on List of Methods on the main post.
Click on List of Methods on the main post.
Re: Subtitle.Render() - Show text with style (Easy, painless Gdip interpreter)
Iseahound, your version is quite laggy imo.
Re: Subtitle.Render() - Show text with style (Easy, painless Gdip interpreter)
I did mention that it would eat up CPU power, as it is rendering every 10ms ≈ 100 frames per second. That's quite excessive, so it is possible to render a frame only when 1) time changes, 2) x position changes, or 3) y position changes.kczx3 wrote:Iseahound, your version is quite laggy imo.
Code: Select all
; subtitleDESKTOPCLOCK - using class_Subtitle and Gdip_All (many thanks to iseahound and tic)
; draggable with CTRL + leftbutton (center-positioned)
; Exit with ESC
; ===========================================================================================
#include class_Subtitle.ahk
#include <Gdip_All>
CoordMode, Mouse, Screen
OnMessage(0x201, "OnLeftClick")
isClicked := 0
pToken := Gdip_Startup()
desktopclock := new Subtitle()
font := "Arial Black"
size := 100
background := {"x":400, "y":200, "anchor":2, "color":"0x10FFFFFF"}
text := {"font":font, "size":size, "color":"FFFFFFFF"}
text.outline := {"width":"20", "color":"FF8000", "glow":"0", "glowcolor":"FFFFFFFF"}
text.dropShadow := {"blur":"8", "color":"25000000", "horizontal":"8", "vertical":"8", "strength":"100"}
SetTimer, ticktack, 10
return
ticktack(){
global desktopClock, background, text
global xpos, ypos, isClicked, xClick, yClick
static time_past, x_past, y_past
FormatTime, time,, HH:mm:ss
if (isClicked = 1 && GetKeyState("Ctrl")) {
MouseGetPos, dragx, dragy
background.x := xpos + dragx - xClick
background.y := ypos + dragy - yClick
}
if (!GetKeyState("LButton"))
isClicked := 0
if (time != time_past || background.x != x_past || background.y != y_past) {
time_past := time, x_past := background.x, y_past := background.y
desktopclock.Render(time, background, text)
}
Return
}
GuiEscape:
ExitApp
OnLeftClick() {
global ; Make all these values global.
isClicked := 1
MouseGetPos, xClick, yClick
xpos := background.x
ypos := background.y
}
Return
Re: Subtitle.Render() - Show text with style (Easy, painless Gdip interpreter)
Meh, it seems better but still laggy.
Re: Subtitle.Render() - Show text with style (Easy, painless Gdip interpreter)
Found out that the blur-function eats most of memory (>38MB at 4% load) on my barebone (i5) while displaying with fontsize 48... increases extremly with sizes above!. So I decided to code with gdip+ and simulate the shadow with another Gdip_TextToGraphics underneath the coloured text (see pic). In addition I use sendmessage, 0xA1,2 in combination with a transparent GUI... works very smooth!
There are many combinations possible with tic's great gdip+, like alphablending gradients, reliefs, etc. My current project (smartClock) is taking shape. Thanks to tic, iseahound, kczx3 for inspiration and motivation. moefr01
There are many combinations possible with tic's great gdip+, like alphablending gradients, reliefs, etc. My current project (smartClock) is taking shape. Thanks to tic, iseahound, kczx3 for inspiration and motivation. moefr01
Re: Subtitle.Render() - Show text with style (Easy, painless Gdip interpreter)
Nice! I'm looking forward to seeing how your project turns out.
If you think the blur function is slow, the glow function is much slower... Alpha Blending is one of the costliest operations to perform. If you set the blur to 0 and only set horizontal and vertical offsets the shadow renders fast with low memory usage.
Still looking for a better blur function (tic's Gdip_BlurBitmap is terribly slow) preferably in machine code.
If you think the blur function is slow, the glow function is much slower... Alpha Blending is one of the costliest operations to perform. If you set the blur to 0 and only set horizontal and vertical offsets the shadow renders fast with low memory usage.
Still looking for a better blur function (tic's Gdip_BlurBitmap is terribly slow) preferably in machine code.
Re: Subtitle.Render() - Show text with style (Easy, painless Gdip interpreter)
Awesome
Windows 10 x64 Professional, Intel i5-8500, NVIDIA GTX 1060 6GB, 2x16GB Kingston FURY Beast - DDR4 3200 MHz | [About Me] | [About the AHK Foundation] | [Courses on AutoHotkey]
[ASPDM - StdLib Distribution] | [Qonsole - Quake-like console emulator] | [LibCon - Autohotkey Console Library]
Re: Subtitle.Render() - Show text with style (Easy, painless Gdip interpreter)
I have added a few static variables and augmented your __New() and __Delete() to automatically start and shutdown Gdip so that the user need not be bothered.
Snippet below:
Snippet below:
Code: Select all
static instances := []
static pToken := ""
past := {}, ScreenWidth := A_ScreenWidth, ScreenHeight := A_ScreenHeight
__New(name := "")
{
if (Subtitle.instances.Length() = 0)
Subtitle.pToken := Gdip_Startup()
Subtitle.instances.Push(&this)
parent := ((___ := RegExReplace(A_ThisFunc, "^(.*)\..*\..*$", "$1")) != A_ThisFunc) ? ___ : ""
Loop, Parse, parent, .
this.parent := (A_Index=1) ? %A_LoopField% : this.parent[A_LoopField]
this.parent.Startup()
Gui, New, +LastFound +AlwaysOnTop -Caption -DPIScale +E0x80000 +ToolWindow +hwndSecretName
this.hwnd := SecretName
this.name := (name != "") ? name "_Subtitle" : "Subtitle_" this.hwnd
DllCall("ShowWindow", "ptr",this.hWnd, "int",8)
DllCall("SetWindowText", "ptr",this.hWnd, "str",this.name)
this.hbm := CreateDIBSection(this.ScreenWidth, this.ScreenHeight)
this.hdc := CreateCompatibleDC()
this.obm := SelectObject(this.hdc, this.hbm)
this.G := Gdip_GraphicsFromHDC(this.hdc)
this.colorMap := this.colorMap()
}
__Delete(){
this.parent.Shutdown()
for k, v in Subtitle.instances
if (v = &this)
Subtitle.instances.RemoveAt(k)
if (Subtitle.instances.Length() = 0)
Gdip_Shutdown(Subtitle.pToken)
}
Re: Subtitle.Render() - Show text with style (Easy, painless Gdip interpreter)
@Relayer
Here's an alternative Gdip_Startup() and Gdip_Shutdown() wrapper.
That's actually what this code is referring to:
The reason that I do not save the instances within class Subtitle is because I have multiple Graphics objects, and not all of them are Subtitle objects.
Still, many people will find your addition to be useful!
Warning: Calling Gdip_Startup() twice in the same AHK script may cause random crashing. That's another reason I was hesitant to include it.
Here's an alternative Gdip_Startup() and Gdip_Shutdown() wrapper.
Code: Select all
class Graphics {
static pToken, Gdip := 0
Startup(){
return Graphics.pToken := (Graphics.Gdip++ > 0) ? Graphics.pToken : Gdip_Startup()
}
Shutdown(){
return Graphics.pToken := (--Graphics.Gdip == 0) ? Gdip_Shutdown(Graphics.pToken) : Graphics.pToken
}
// insert Subtitle class here
}
Code: Select all
; Check if this class is nested within a parent class
parent := ((___ := RegExReplace(A_ThisFunc, "^(.*)\..*\..*$", "$1")) != A_ThisFunc) ? ___ : ""
; Find the name of the parent class
Loop, Parse, parent, .
this.parent := (A_Index=1) ? %A_LoopField% : this.parent[A_LoopField]
; Call the startup method of the parent class
this.parent.Startup()
Still, many people will find your addition to be useful!
Warning: Calling Gdip_Startup() twice in the same AHK script may cause random crashing. That's another reason I was hesitant to include it.
Re: Subtitle.Render() - Show text with style (Easy, painless Gdip interpreter)
Thank you very much, iseahound. I have used it in a UiPath workflow to add subtitles as part of a text-to-speech activity that also uses AHK.
https://forum.uipath.com/t/text-to-spee ... le-s/15391
Regards,
burque505
https://forum.uipath.com/t/text-to-spee ... le-s/15391
Regards,
burque505
Re: Subtitle.Render() - Beautiful Text on Screen
UPDATE
Some changes have been made. It's not perfect, but I was running into some limitations with the previous version that have been resolved in this version.
Some syntax for drop shadow:
horizontal:50px - denotes the horizontal offset.
vertical:50px - denotes the vertical offset.
blur:5px - blurs by 5 pixels (radius)
color:Black - changes color to black.
opacity:0.5 - opacity is at 50%. you might want to do 50% if you like integers.
size:10px - extends the edges by 10 pixels.
So dropshadow:(h:50px v:50px b:5px c:Black o:50% s:10px) would be used.
Syntax for outline:
stroke:1px - a one pixel outline does wonders to increase the readability of text without changing the font size.
color:Blue - outline color.
glow:7px - extends the edge (counting from the end of the outline) and creates a glow of 7pixels. Try to use a value less than 4 pixels if you want fast rendering.
tint:Purple - specifies the glow tint. This will give the glow a unique color.
So outline:(stroke:1px color:Blue glow:7px tint:purple) would be used.
You can drop the colons but it's harder to read. Also I increased rendering speeds by 10x. Also you don't need to call Gdip_Startup anymore. Also there's a real gaussian blur made in C.
Some changes have been made. It's not perfect, but I was running into some limitations with the previous version that have been resolved in this version.
Some syntax for drop shadow:
horizontal:50px - denotes the horizontal offset.
vertical:50px - denotes the vertical offset.
blur:5px - blurs by 5 pixels (radius)
color:Black - changes color to black.
opacity:0.5 - opacity is at 50%. you might want to do 50% if you like integers.
size:10px - extends the edges by 10 pixels.
So dropshadow:(h:50px v:50px b:5px c:Black o:50% s:10px) would be used.
Syntax for outline:
stroke:1px - a one pixel outline does wonders to increase the readability of text without changing the font size.
color:Blue - outline color.
glow:7px - extends the edge (counting from the end of the outline) and creates a glow of 7pixels. Try to use a value less than 4 pixels if you want fast rendering.
tint:Purple - specifies the glow tint. This will give the glow a unique color.
So outline:(stroke:1px color:Blue glow:7px tint:purple) would be used.
You can drop the colons but it's harder to read. Also I increased rendering speeds by 10x. Also you don't need to call Gdip_Startup anymore. Also there's a real gaussian blur made in C.
Re: Subtitle.Render() - Beautiful Text on Screen
That's really a great script, iseahound. Awesome.
Regards,
burque505
Regards,
burque505
Return to “Scripts and Functions (v1)”
Who is online
Users browsing this forum: No registered users and 108 guests