OSD Console / Log

Post your working scripts, libraries and tools for AHK v1.1 and older
User avatar
svArtist
Posts: 62
Joined: 08 Mar 2015, 18:16

OSD Console / Log

02 Feb 2017, 19:49


  • Always on Top
  • Clickable, but never takes focus.* (Use right click menu to copy from console)
  • Adds date + time to messages
  • Standard log saved in Script Dir, clears on restart
  • Buttons:
    • _: Minimize console (restores on new message)
    • <: Slide out of view (buttons remain on screen)
    • C: Clear console
    • S: Save console
    • O: Open console log
    • X: Close console
* Very useful, I think. Of course, when saving or opening log files, the resulting dialogs/windows will take focus. But logging, minimizing, sliding, clearing and closing, even selecting in the console won't take your focus.
That's why you can't use CTRL+C to copy here, use right click instead.

Latest version:
v1.1 here

Below is the original post.
Please refer to the latest version as linked above, unless you really want to use the older, messier version with fewer features.
Spoiler
Last edited by svArtist on 10 Dec 2018, 11:42, edited 5 times in total.
:morebeard:
guest3456
Posts: 3454
Joined: 09 Oct 2013, 10:31

Re: OSD Console / Log

02 Feb 2017, 23:26

nice

brutus_skywalker
Posts: 175
Joined: 24 Dec 2016, 13:16
Location: Antarctica

Re: OSD Console / Log

03 Feb 2017, 11:22

Awesome.......
Outsourcing Clicks & Presses Since 2004.
User avatar
svArtist
Posts: 62
Joined: 08 Mar 2015, 18:16

Re: OSD Console / Log

03 Feb 2017, 12:35

:) I'm glad some people seem to like it ^^
I thought this offshoot of my other project was probably too boring to share, and on top of that it's not useful as a standalone.
But it could probably more or less easily be made to work as a standalone using command line parameters. I might do that later :)
:morebeard:
brutus_skywalker
Posts: 175
Joined: 24 Dec 2016, 13:16
Location: Antarctica

Re: OSD Console / Log

04 Feb 2017, 13:30

Interesting,Presumably a more interactive standalone OSD,that could double as a console interface might be a cooler/simpler alternative to the awesome LibCon library which is a bit visually, NOT your OSD console... look forward to that. CHEERS.
Outsourcing Clicks & Presses Since 2004.
User avatar
svArtist
Posts: 62
Joined: 08 Mar 2015, 18:16

Re: OSD Console / Log

05 Feb 2017, 08:55

Update:
I'm currently extending the functionality:
  • Including bool to choose log order (newest on top or newest at bottom) [done]
  • Including bool to always flush to disk (what it is now) (slower), or to update only the display (faster, less robust/failsafe) [done]
  • Implementing commands to change some settings at runtime [in progress]
  • Console Mode to run AHK commands and hopefully receive feedback [we'll see]
  • Maybe turn it all into a class/object? [we'll see]
  • Ways of implementing a standalone [in progress]
  • Managing project based solutions so you can log different scripts at different times [in progress]
  • Different modes if interactivity (drag on screen, turn off "never focus"-feature) [in progress]
Changes are not in the above version yet.

Hmmmm... I've run into major issues trying to expand my OSD log today.
By "sand-alone", I mean an executable that you can just fire strings at as a command line parameter, btw.

It works as a standalone (my local WIP, not the old version above), but to pass arbitrary strings the call has to be wrapped in an encoding function.
I'm currently using something like

Code: Select all

logg(msg){
	if(consid == 0)
	{
		run, % "AutoHotkey.exe " consoleScriptPath " " customEncode(msg)
	}
}

customEncode(str){
	StringReplace, str, str, $, $36, All
	Loop
		If (RegExMatch(str, "i)[^\w\.~$]", char))
				StringReplace, str, str, %char%, % "$" . Asc(char), All
			else break
	Return, str
}
The console will then reverse the encoding (everything that isn't a word-character is converted into their ASCII value preceded by "$" here) and there you go. One solid string with no spaces or other characters that might interfere with the command call.
This necessity makes it a bit uglier :/
I mean, use would still be the same. logg(msg), done.

But the thing is, I either have to do an ugly check for other instances and have work-arounds in the script itself (working on it), or I have to move even more code back to the calling script, making it even less "stand alone".
And worst of all, if I do it that way (having new instances check for the original manually), it'll be quite slow, because you have to run the console.exe for each call, which then checks and finds the original process window, reads out the IDs, then manipulates the original window (including the already cumbersome methods necessary to ensure auto-fitting / flowing the text) from outside :/
It might be too slow for very small time intervals to work. I'm not done testing yet, but I'm afraid it'll be all very messy.

If anybody has an idea how to circumvent that, I'm all ears.
:morebeard:
brutus_skywalker
Posts: 175
Joined: 24 Dec 2016, 13:16
Location: Antarctica

Re: OSD Console / Log

05 Feb 2017, 13:47

I think you might want to look into autohotkey.dll by hotkeyit, it allows dynamically running ahk code which might simplify string parsing of a parameter, even as a dynamically run command which might come in handy,tons of examples out there so I wont get in to it...

But in the mean time here's a really simple instance checking system you place at the very top of you're script,if any other instance exists-script exits,works only when compiled sadly:

Code: Select all

;instance checking section placed at very top of script autoexecute section
SplitPath, A_ScriptFullPath, OutFileName, OutDir, OutExtension, OutNameNoExt, OutDrive
count = 0
For process in ComObjGet("winmgmts:").ExecQuery("Select *from Win32_Process")
	If (process.name = A_ScriptName)
		count++
IfGreaterOrEqual, count, 2		;if another instance is detected in addition to one currently running,it exists.
	{
	ExitApp
	}

And here's one for basic command line parsing,It should work for this purpose,I don't really know why you're bothering with encodings and all,so long as param is passed in quotes is will be placed in a single variable and with the dll above you can even execute commands passed as params:

Code: Select all

;basic command line parsing of strings, note:strings in quotes are parsed as one parameter,obviously
NumberOfParameters = %0%
Loop, %NumberOfParameters%
{
Parameter := %A_Index%
MsgBox, % Parameter		;just to check param got passed to alright...
}
return

Outsourcing Clicks & Presses Since 2004.
User avatar
svArtist
Posts: 62
Joined: 08 Mar 2015, 18:16

Re: OSD Console / Log

05 Feb 2017, 14:15

brutus_skywalker wrote:I think you might want to look into autohotkey.dll by hotkeyit, it allows dynamically running ahk code which might simplify string parsing of a parameter, even as a dynamically run command which might come in handy,tons of examples out there so I wont get in to it...

But in the mean time here's a really simple instance checking system you place at the very top of you're script,if any other instance exists-script exits,works only when compiled sadly:

Code: Select all

;instance checking section placed at very top of script autoexecute section
SplitPath, A_ScriptFullPath, OutFileName, OutDir, OutExtension, OutNameNoExt, OutDrive
count = 0
For process in ComObjGet("winmgmts:").ExecQuery("Select *from Win32_Process")
	If (process.name = A_ScriptName)
		count++
IfGreaterOrEqual, count, 2		;if another instance is detected in addition to one currently running,it exists.
	{
	ExitApp
	}

And here's one for basic command line parsing,It should work for this purpose,I don't really know why you're bothering with encodings and all,so long as param is passed in quotes is will be placed in a single variable and with the dll above you can even execute commands passed as params:

Code: Select all

;basic command line parsing of strings, note:strings in quotes are parsed as one parameter,obviously
NumberOfParameters = %0%
Loop, %NumberOfParameters%
{
Parameter := %A_Index%
MsgBox, % Parameter		;just to check param got passed to alright...
}
return

:D thanks, Brutus! :)
I'm currently focusing on the #include version (far more likely to be useful anyways), so the standalone branch is taking a back seat.
I already have the checking for instances down, and CLI parameters as well, of course. But your instance check is of course a bit neater than what I wrote for AHK scripts, and I'm thankful for the input!
(Just out of curiosity, I'm guessing this is just an example showcasing the process detection - but is the literal above example ever needed? If you simply want to quit (ExitApp), wouldn't a#SingleInstance, force do the trick?)
:morebeard:
brutus_skywalker
Posts: 175
Joined: 24 Dec 2016, 13:16
Location: Antarctica

Re: OSD Console / Log

07 Feb 2017, 12:41

In most cases #SingleInstance force does work, but what I found is that it fails spectacularly at times when running a script as a task for example where the windows task scheduler occasionally starts multiple instances regardless. So I use my instance checking approach as a redundancy,as I run some scripts that should they ever run in multiple instances will f$!@k up my system.
Outsourcing Clicks & Presses Since 2004.
User avatar
svArtist
Posts: 62
Joined: 08 Mar 2015, 18:16

Re: OSD Console / Log

07 Feb 2017, 12:56

brutus_skywalker wrote:In most cases #SingleInstance force does work, but what I found is that it fails spectacularly at times when running a script as a task for example where the windows task scheduler occasionally starts multiple instances regardless. So I use my instance checking approach as a redundancy,as I run some scripts that should they ever run in multiple instances will f$!@k up my system.
Thanks, good to know!
:morebeard:
User avatar
svArtist
Posts: 62
Joined: 08 Mar 2015, 18:16

UPDATE: OSD Console / Log

10 Dec 2018, 10:30

I just realized I never updated this thread.
I've since switched to a class-based implementation to keep everything tidy.
Along the way I also added some things.

Version 1.1.1:

Code: Select all

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Ben's Console, V 1.1.1             ;
; Contact: [email protected]  ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

class BensConsole
{
	; exposed in __NEW constructor
	consolecol := "000000"
	fontcol := "15bb10"
	textBackgroundCol := "000000"
	opacity := 180
	fontsize := 10
	titlebar := true
	topToBottom := true
	prependDate := true
	animate := false
	clearOnClose := true
	alwaysFlushToDisk := false
	enableCommands := true
	consoleMode := false
	logCommands := true
	nameInLog := false
	
	; User changable
	maxHeight := 1050
	minHeight := 150
	width := 500
	padding := 5
	posX := 0
	posY := 0
	
	; best don't touch
	consid := 0
	LogContsID := ""
	LogContents := ""
	consslid := true
	logloc := A_WorkingDir . "\AHK_LOG.log"
	conshide := false
	startpos := 0
	ctH := 0
	oH := 0
	maxTextHeight := 0
	minTextHeight := 0
	winHeightAdd := 0
	winAbsMinHeight := 0
	allset := false
	myName := ""
	myTitle := "AHK Console"
	myGUIName := "AHK_Console"
	ctit := ""
	; End of variable declarations
	
	setTitle(name)
	{
		this.myName := name
		this.ctit := this.myName != "" ? this.myName . ": " : ""
		this.myTitle := this.ctit . "AHK Console"
		varsafename := RegExReplace(this.myTitle, "i)([^\w]+)", "_")
		if inStr("0123456789", substr(varsafename, 1,1))
			varsafename := "v" . varsafename
		this.myGUIName := varsafename
	}
	
	setLocation(path)
	{
		this.logloc := path
	}

	__New(name = "", color = "000000", fontColor = "15bb10", textBackgroundCol = "000000", opacity = 180, fontsize = 10, titlebar = true, topToBottom = false, prependDate = true, animate = false, clearOnClose = true, alwaysFlushToDisk = false, enableCommands = true, consoleMode = false, logCommands = true, nameInLog = false)
	{
		if(isObject(name))
		{
			this.setTitle(name.name)
			this.consolecol := name.color
			this.fontcol := name.fontColor
			this.textBackgroundCol := name.textBackgroundCol
			this.opacity := name.opacity
			this.fontsize := name.fontsize
			this.topToBottom := name.topToBottom
			this.prependDate := name.prependDate
			this.animate := name.animate
			this.clearOnClose := name.clearOnClose
			this.titlebar := name.titlebar
			this.alwaysFlushToDisk := name.alwaysFlushToDisk
			this.enableCommands := name.enableCommands
			this.consoleMode := name.consoleMode
			this.logCommands := name.logCommands
			this.nameInLog := name.nameInLog
		}
		else
		{
			this.setTitle(name)
			this.consolecol := color
			this.fontcol := fontColor
			this.textBackgroundCol := textBackgroundCol
			this.opacity := opacity
			this.fontsize := fontsize
			this.topToBottom := topToBottom
			this.prependDate := prependDate
			this.animate := animate
			this.clearOnClose := clearOnClose
			this.titlebar := titlebar
			this.alwaysFlushToDisk := alwaysFlushToDisk
			this.enableCommands := enableCommands
			this.consoleMode := consoleMode
			this.logCommands := logCommands
			this.nameInLog := nameInLog
		}
	}
	

	log(msg)
	{
		tv := false
		if(this.enableCommands && ! this.logCommands)
		{
			tv := this.doEvals(msg)
		}
		if(tv != false)
			return
		
		omsg := msg
		
		if(this.nameInLog)
			msg := this.ctit . msg
		
		if(this.prependDate)
			msg := this.DateString() . ": " . msg
		if(this.alwaysFlushToDisk)
		{
			FileRead, lc, % this.logloc
			this.LogContents := lc
			FileDelete, % this.logloc
		}
		
		if(this.LogContents != "")
		{
			if(this.topToBottom)
			{
				this.LogContents := msg . "`r`n" . this.LogContents
				; msgbox, ttb
			}
			else
			{
				this.LogContents := this.LogContents . "`r`n" . msg
				; msgbox, btt
			}
		}
		else
		{
			; msgbox, no content yet...
			this.LogContents := msg
		}
		; msgbox, % "result: `n" this.LogContents
		
		if(this.alwaysFlushToDisk)
		{
			FileAppend, % this.LogContents, % this.logloc
		}
		
		if(this.consid == 0)
		{
			this.buildGui()
			; this.setTextHeight(20)
			; this.doSizePos()
		}
		else
		{
			if(this.conshide)
			{
				; WinShow, % "ahk_id " this.consid
				gui, % this.myGUIName ": show", % "x" this.posX " y" this.posY " NoActivate"
				this.conshide := false
			}
			this.applyContents()
		}
		
		
		if(this.enableCommands && this.logCommands)
			this.doEvals(omsg)
		
	} ; END log
	
	buildGui()
	{
		; +E0x20 ; <-- click through!
		GUI, % this.myGUIName ": New", +Lastfound +AlwaysOnTop +ToolWindow +E0x08000000, % this.myTitle ; 
		gui, % this.myGUIName ": color", % this.consolecol
		WinSet, Transparent, % this.opacity
		Gui, % this.myGUIName ": -Caption"
		Gui, % this.myGUIName ": Color",, % this.textBackgroundCol
		this.startpos := this.padding
		if(this.titlebar)
		{	
			Gui, % this.myGUIName ": Font", S8 bold
			tmw := this.width - 2* this.padding
			global titbar
			Gui, % this.myGUIName ": Add", Text, % "x" this.padding " y" this.padding " w" tmw " h15 c" this.fontcol " vtitbar", % this.myTitle
			this.startpos := 15 + 2* this.padding 
		}
		
		cbuy := this.startpos
		cbuwi := 17
		cbuhe := 14
		cbux := this.width - cbuwi - this.padding
		
		gui, % this.myGUIName ": Font", S7 norm center
		gui, % this.myGUIName ": Add", button, w%cbuwi% h%cbuhe% x%cbux% y%cbuy% hwndtbutt, _
		fn := this.minimize.Bind(this)
		GuiControl +g, %tbutt%, % fn
		cbuy += 18
		gui, % this.myGUIName ": Add", button, w%cbuwi% h%cbuhe% x%cbux% y%cbuy% hwndtbutt, <
		fn := this.slide.Bind(this)
		GuiControl +g, %tbutt%, % fn
		cbuy += 18
		gui, % this.myGUIName ": Add", button, w%cbuwi% h%cbuhe% x%cbux% y%cbuy% hwndtbutt, C
		fn := this.clear.Bind(this)
		GuiControl +g, %tbutt%, % fn
		cbuy += 18
		gui, % this.myGUIName ": Add", button, w%cbuwi% h%cbuhe% x%cbux% y%cbuy% hwndtbutt, S
		fn := this.save.Bind(this)
		GuiControl +g, %tbutt%, % fn
		cbuy += 18
		gui, % this.myGUIName ": Add", button, w%cbuwi% h%cbuhe% x%cbux% y%cbuy% hwndtbutt, O
		fn := this.open.Bind(this)
		GuiControl +g, %tbutt%, % fn
		cbuy += 18
		gui, % this.myGUIName ": Add", button, w%cbuwi% h%cbuhe% x%cbux% y%cbuy% hwndtbutt, X
		fn := this.close.Bind(this)
		GuiControl +g, %tbutt%, % fn
		
		absminh := cbuy + cbuhe - this.padding
		if this.minHeight < absminh
			this.minHeight := absminh
			
		this.tWmax := this.width - (2*this.padding) - 25
		Gui, % this.myGUIName ": Font", % "S" this.fontsize, Consolas
		Gui, % this.myGUIName ": Add", Edit, % "x" this.padding " y" this.startpos " w" this.tWmax " +Multi c" this.fontcol " -VScroll -E0x200 HwndtLogContsID", % this.LogContents
		this.LogContsID := tLogContsID
		gui, % this.myGUIName ": show", % "x" this.posX " y" this.posY " autosize NoActivate"
		gui, % this.myGUIName ": +LastFound"
		this.consid := WinExist()
		
		WinGetPos,,,,mbH, % "ahk_id " this.consid
		this.winAbsMinHeight := mbH
		this.setMaxTextHeight()
		
		clickdrag := ObjBindMethod(this, "drag")
		OnMessage(0x201, clickdrag) ; WM_LBUTTONDOWN
		
		moving := ObjBindMethod(this, "moving")
		OnMessage(0x03, moving) ; WM_MOVE
		; OnMessage(0x0047, moving) ; WINDOWPOSCHANGED
		
		; applyContents()
	}
	
	applyContents()
	{
		; controlRemove(this.Ghost)
		Gui, % this.myGUIName ": Font", % "S" this.fontsize, Consolas
		Gui, % this.myGUIName ": Add", Edit, % "x" this.padding " y" this.startpos " w" this.tWmax " +Hidden -VScroll -E0x200 HwndtGhost", % this.LogContents
		this.Ghost := tGhost
		ControlGetPos,,,, ctH,, % "ahk_id " this.Ghost
		SendMessage, 0x10,,,, % "ahk_id " this.Ghost
		
		GuiControl, Text, % this.LogContsID, % this.LogContents
		
		this.setTextHeight(ctH)
		
		if(this.topToBottom)
			postMessage,0x115,0x6,,,% "ahk_id " this.LogContsID ; WM_VSCROLL = 0x0115 ; controlsend,, ^{home}, % "ahk_id " this.LogContsID
		else
			postMessage,0x115,0x7,,,% "ahk_id " this.LogContsID ; WM_VSCROLL = 0x0115 ; controlsend,, ^{end}, % "ahk_id " this.LogContsID
		
		
	}
	
	setTextHeight(num)
	{
		; msgbox, % "in: " num
		this.ctH := num > this.maxTextHeight ? this.maxTextHeight : num
		; this.ctH := this.ctH < this.minTextHeight ? this.minTextHeight : this.ctH
		; msgbox, % "out: " this.ctH
		if(this.ctH != this.oH)
		{
			ControlMove,,,,,this.ctH, % "ahk_id " this.LogContsID
			this.oH := this.ctH
			if (this.ctH + this.winHeightAdd > this.winAbsMinHeight)
				winmove, % "ahk_id " this.consid,,,,,% this.ctH + this.winHeightAdd
			; this.allset := false
		}
	}
		
	setMaxTextHeight()
	{
		this.winHeightAdd := this.startpos + this.padding
		this.maxTextHeight := this.maxHeight-this.winHeightAdd
		; this.minTextHeight := this.minHeight-this.winHeightAdd
	}
	
	doSizePos(isUpdate = false)
	{
		; capTextHeight()
		
		; if(this.ctH != this.oH)
		; {
			; if this.ctH < this.minHeight
			; {
				; this.ctH := this.minHeight
			; }
			; this.oH := this.ctH
			; winmove, % "ahk_id " this.consid,,,,,% this.ctH + this.startpos + this.padding
		; }
		
	}
	
	position(x="",y="")
	{
		if(x!="")
			this.posX := x
		if(y!="")
			this.posY := y
		WinMove, % "ahk_id " this.consid,,% this.posX,% this.posY
	}
	
	setX(x)
	{
		this.position(x)
	}
	
	setY(y)
	{
		this.position(,y)
	}
	
	doEvals(msg)
	{
		cmd := this.explode(msg, ",")
		if(cmd.MaxIndex()<1 || subStr(msg, 1, 1) != "\")
			return false
			
		; why does AHK not support SWITCH statements yet? :(
		if(this.toLower(cmd[1]) == "\close")
			this.close()
		else if(this.toLower(cmd[1]) == "\hide")
			this.minimize()
		else if(this.toLower(cmd[1]) == "\show")
			this.restore()
		else if(this.toLower(cmd[1]) == "\save")
			this.save()
		else if(this.toLower(cmd[1]) == "\view")
			this.open()
		else if(this.toLower(cmd[1]) == "\setx")
			this.setX(cmd[2])
		else if(this.toLower(cmd[1]) == "\sety")
			this.setY(cmd[2])
		else if(this.toLower(cmd[1]) == "\setpos")
			this.position(cmd[2], cmd[3])
		else if(this.toLower(cmd[1]) == "\rep")
			msgbox, % this.posX ", " this.posY
		else
			return false
	}

	minimize(){
		WinHide, % "ahk_id " this.consid
		this.conshide := true
	}
	
	restore(){
		; WinShow, % "ahk_id " this.consid
		gui, % this.myGUIName ": show", % "x" this.posX " y" this.posY " NoActivate"
		this.conshide := false
	}

	close()
	{
		if(this.animate)
		{
			this.fadeWin(this.consid, 1, true)
		}
		else
		{
			gui, % this.myGUIName ": Destroy"
		}
		if(this.clearOnClose)
		{
			this.LogContents := ""
			FileDelete, % this.logloc
		}
		this.consid := 0
	}
	
	drag(w,l,m,h)
	{
		if(h == this.consid)
		{
			PostMessage, 0xA1, 2,,, % "Ahk_id " h
			return
		}
	}
	
	moving(w, l, m, h)
	{
		if(h == this.consid && ! this.sliding)
		{
			this.posX := this.GET_X_LPARAM(l)
			this.posY := this.GET_Y_LPARAM(l)
			this.consslid := true
		}
	}

	save(){
		GUI, % this.myGUIName ": +OwnDialogs"
		FileSelectFile, logsaveloc,S,% "Log " . this.DateString(true) . ".log",Save Log, Logs (*.log)
		if(logsaveloc)
		{
			filecopy, % this.logloc, %logsaveloc%
		}
	}

	open(){
		run, % this.logloc
	}
	sliding := false
	slide()
	{
		this.sliding := true
		if(this.consslid := ! this.consslid)
		{
			if(this.animate)
			{
				this.slideWin(this.consid, this.posX,this.posY,200)
			}
			else
			{
				WinMove, % "ahk_id " this.consid,,% this.posX,% this.posY
			}
		}
		else
		{
			if(this.animate)
			{
				this.slideWin(this.consid, 30 - this.width,this.posY, 200)
			}
			else
			{
				WinMove, % "ahk_id " this.consid,,% 30 - this.width,% this.posY
			}
		
		}
		this.sliding := false
	}

	clear(){
		this.LogContents := ""
		FileDelete, % this.logloc
		this.applyContents()
	}
	
	; ######### general functions ##########
	
	DateString(filesafe = false)
	{
		if(filesafe)
			FormatTime, mcurrentTime, %A_Now%, yyyy-MM-dd HH-mm-ss
		else
			FormatTime, mcurrentTime, %A_Now%, yyyy-MM-dd HH:mm:ss
		return mcurrentTime
	}

	explode(string, delim=",", trimvals = true)
	{
		parr := StrSplit(string, delim)
		if(trimvals)
		{
			for k, v in parr{
				parr[k] := trim(v)
			}
		}
		return, parr
	}
	
	toLower(string)
	{
		StringLower, string, string
		return % string
	}
	
	fadeWin(msid, ms = 10, closeOnFinish = false, trans = 256)
	{
		if(trans>=256)
		{
			WinGet, trans, Transparent, ahk_id %msid%
		}
		ntrans := trans-2
		WinSet, Transparent, %ntrans%, ahk_id %msid%
		if(ntrans>0)
		{
			sleep, ms
			this.fadeWin(msid, ms, closeOnFinish, ntrans)
		}
		else
			if(closeOnFinish)
				WinClose, ahk_id %msid%
	}

	slideWin(msid, tX = 0, tY = 0, T = 500, rightAlign = false, closeOnFinish = false, frst = true, dX = 0, dY = 0, step=0, maxStep=0)
	{
		anint := 100
		winGetPos, wX,wY,wW,wH,ahk_id %msid%
		woX := wX
		if(rightAlign)
		{
		wX += wW
		}
		
		if(frst)
		{
		maxStep := Round(T/(anint + 0))
		dX := Round((tX - wX) / maxStep)
		dY := Round((tY - wY) / maxStep)
		}
		
		if(step<maxStep)
		{
			newX := woX + dX
			newY := wY + dY
			winMove, ahk_id %msid%,,newX,newY
			; sleep, anint-19
			this.slideWin(msid, tX, tY, T, rightAlign, closeOnFinish, false, dX, dY, step+1, maxStep)
		}
		else
		{
			if(rightAlign)
			{
				winMove, ahk_id %msid%,, tX-wW,tY
			}
			else
			{
				winMove, ahk_id %msid%,, tX,tY
			}
			if(closeOnFinish)
			{
				WinClose, ahk_id %msid%
			}
		}
	}

	GET_X_LPARAM(lParam) {
	   NumPut(lParam, Buffer:="    ", "UInt")
	   Return NumGet(Buffer, 0, "Short")
	}
	GET_Y_LPARAM(lParam) {
	   NumPut(lParam, Buffer:="    ", "UInt")
	   Return NumGet(Buffer, 2, "Short")
	}
}

logg(str){
	global console
	if(console ==""){
		global console = new BensConsole()
	}
	console.log(str)
}
Quickstart
Save the script as "console_include.ahk" in your script directory and include the following in your script:

Code: Select all

#include %A_ScriptDir%\console_include.ahk
global console = new BensConsole()

console.log("Look, mom, I'm logging something to a console!")
console.log("That's nice, dear.")

Use
The old logg() approach still works, for backwards compatibility.
However, the standard procedure would be to create an instance of the console class, which you can configure to your liking, and then to use its log() method.

1. Include the script: As always

Code: Select all

#include %A_ScriptDir%\console_include.ahk
If the console script is not in the same path as the calling script, replace "%A_ScriptDir%" with the correct path, of course.

2. Instantiate
Create an instance of the BensConsole class with the new keyword:

Code: Select all

global console = new BensConsole()
You can assign the console to any regular variable. In this instance, we're simply calling it "console".

2.2 configure
Optionally, you can configure the console settings when you're creating an instance.
This can be done "in-line" using the variables in the constructor signature, or with an object.
When you construct an instance, the constructor expects the following:
  • no parameters: A console will be set-up using the standard parameters (title, font-size, color, position, size, behavior, etc)

    Code: Select all

    global console = new BensConsole()
  • an object containing definitions of the available options as outlined below

    Code: Select all

    global console = new BensConsole({name: "Console in " . A_ScriptName
    	, color: "000000"
    	, fontcolor: "ffffff"
    	, textBackgroundCol: "000000"
    	, opacity: 180
    	, fontsize: 10
    	, titlebar: true
    	, topToBottom: false
    	, prependDate: true
    	, animate: false
    	, clearOnClose: false
    	, alwaysFlushToDisk: true
    	, enableCommands: true
    	, consoleMode: false
    	, logCommands: true
    	, nameInLog: true})
  • or parameters according to the construction signature (name = "", color = "000000", fontColor = "15bb10", textBackgroundCol = "000000", opacity = 180, fontsize = 10, titlebar = true, topToBottom = false, prependDate = true, animate = false, clearOnClose = true, alwaysFlushToDisk = false, enableCommands = true, consoleMode = false, logCommands = true, nameInLog = false), where all the parameters are optional.

    Code: Select all

    global console = new BensConsole("Function Log", , "ffffff", "660000", , 12)
3. Log
call the log method of the console instance.
assuming you called your instance "console":

Code: Select all

console.log("Log this!")
Of course, you can make that shorter by writing a function in your script's global space:

Code: Select all

log(str){
console.log(str)
}
now, you can simply call log in order to log something in the console.

Options
The console has the following options:
1. Options exposed in the constructor:
  • name: Name of the console as shown in the title bar. Default = ""
  • consolecol: Background color of the console window. Default = "000000"
  • fontcol: Font color. Default = "15bb10"
  • textBackgroundCol: Background of text lines. Default = "000000"
  • opacity: Opacity of the console window (0-255). Default = 190
  • fontsize: Log font size. Default = 10
  • titlebar: Whether the log window should have a title bar (recommended: you can move the window by dragging on the title bar). Default = true
  • topToBottom: Whether the log window should display new log lines at the top (false) or at the bottom (true). Default = true
  • prependDate: Whether the date and time should be prepended to every line logged. Default = true
  • animate: Whether sliding and hiding/viewing should be animated. Default = false
  • clearOnClose: Whether the contents of the log should be cleared when you close the window. If false, contents will be there again if you log something after closing the window (If not flushed to disk, this lasts only until you reload the script). Default = true
  • alwaysFlushToDisk: Whether lines logged should be immediately saved to a physical log on disk. Default = true
  • enableCommands: Whether rudimentary commands should be interpreted. See commands for further information. Default = true
  • logCommands: Whether console commands should show up in the log. Default = true
  • nameInLog: Whether the console name should be prepended to every log line. Might be useful if no title bar is enabled and several different consoles are running. Default = false
2. Other options
  • maxHeight: Maximum height of the log window. Default = 1050
  • minHeight: Minimum height of the log window. Default = 150
  • width: Width of the console window. Default = 500
  • padding: Padding inside the window. Default = 5
  • posX: Horizontal position of the window. Default = 0
  • posY: Vertical position of the window. Default = 0
You can set any of the above as members of your console instance.
Example:

Code: Select all

console.fontcol := "ff0000"
console.posX := 500
console.posY := 800
Will set the console font color to red, and its position to (500,800)

Commands
You can log specific messages that will act as commands:
  • \close
    Closes the console window
  • \hide
    Hides the console window
  • \show
    Shows the console window
  • \save
    Save the current log
  • \view
    Opens the current log file, if it exists
  • \setx, X
    Sets the horizontal position of the console window, where X is the position in pixels
  • \sety, Y
    Sets the vertical position of the console window, where Y is the position in pixels
  • \setpos, X, Y
    Sets the position of the console window, where X and Y are the horizontal and vertical positions in pixels, respectively.
Not sure if this is really all that useful, but there it goes.
Last edited by svArtist on 12 Apr 2019, 15:51, edited 2 times in total.
:morebeard:
pk23
Posts: 110
Joined: 24 Apr 2015, 00:49

Re: OSD Console / Log

12 Apr 2019, 15:29

How to save the log to the disk? "\save" command and "alwaysFlushToDisk" seems both not working normally on my machine, or I misunderstand or misuse somewhere? If so, please correct me.
As the gif below shows, I executed the command "\save" and there's no log file shown on the disk.
https://i.imgur.com/lyxE1ZH.gifv
User avatar
svArtist
Posts: 62
Joined: 08 Mar 2015, 18:16

Re: OSD Console / Log

12 Apr 2019, 15:54

pk23 wrote:
12 Apr 2019, 15:29
How to save the log to the disk? "\save" command and "alwaysFlushToDisk" seems both not working normally on my machine, or I misunderstand or misuse somewhere? If so, please correct me.
As the gif below shows, I executed the command "\save" and there's no log file shown on the disk.
https://i.imgur.com/lyxE1ZH.gifv
Oh, I'm so sorry!
There were some lines I used to test something (god knows what) still in the code, returning the call early.

I've updated the embedded script, and here it is again:

Code: Select all

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Ben's Console, V 1.1.1             ;
; Contact: [email protected]  ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

class BensConsole
{
	; exposed in __NEW constructor
	consolecol := "000000"
	fontcol := "15bb10"
	textBackgroundCol := "000000"
	opacity := 180
	fontsize := 10
	titlebar := true
	topToBottom := true
	prependDate := true
	animate := false
	clearOnClose := true
	alwaysFlushToDisk := false
	enableCommands := true
	consoleMode := false
	logCommands := true
	nameInLog := false
	
	; User changable
	maxHeight := 1050
	minHeight := 150
	width := 500
	padding := 5
	posX := 0
	posY := 0
	
	; best don't touch
	consid := 0
	LogContsID := ""
	LogContents := ""
	consslid := true
	logloc := A_WorkingDir . "\AHK_LOG.log"
	conshide := false
	startpos := 0
	ctH := 0
	oH := 0
	maxTextHeight := 0
	minTextHeight := 0
	winHeightAdd := 0
	winAbsMinHeight := 0
	allset := false
	myName := ""
	myTitle := "AHK Console"
	myGUIName := "AHK_Console"
	ctit := ""
	; End of variable declarations
	
	setTitle(name)
	{
		this.myName := name
		this.ctit := this.myName != "" ? this.myName . ": " : ""
		this.myTitle := this.ctit . "AHK Console"
		varsafename := RegExReplace(this.myTitle, "i)([^\w]+)", "_")
		if inStr("0123456789", substr(varsafename, 1,1))
			varsafename := "v" . varsafename
		this.myGUIName := varsafename
	}
	
	setLocation(path)
	{
		this.logloc := path
	}

	__New(name = "", color = "000000", fontColor = "15bb10", textBackgroundCol = "000000", opacity = 180, fontsize = 10, titlebar = true, topToBottom = false, prependDate = true, animate = false, clearOnClose = true, alwaysFlushToDisk = false, enableCommands = true, consoleMode = false, logCommands = true, nameInLog = false)
	{
		if(isObject(name))
		{
			this.setTitle(name.name)
			this.consolecol := name.color
			this.fontcol := name.fontColor
			this.textBackgroundCol := name.textBackgroundCol
			this.opacity := name.opacity
			this.fontsize := name.fontsize
			this.topToBottom := name.topToBottom
			this.prependDate := name.prependDate
			this.animate := name.animate
			this.clearOnClose := name.clearOnClose
			this.titlebar := name.titlebar
			this.alwaysFlushToDisk := name.alwaysFlushToDisk
			this.enableCommands := name.enableCommands
			this.consoleMode := name.consoleMode
			this.logCommands := name.logCommands
			this.nameInLog := name.nameInLog
		}
		else
		{
			this.setTitle(name)
			this.consolecol := color
			this.fontcol := fontColor
			this.textBackgroundCol := textBackgroundCol
			this.opacity := opacity
			this.fontsize := fontsize
			this.topToBottom := topToBottom
			this.prependDate := prependDate
			this.animate := animate
			this.clearOnClose := clearOnClose
			this.titlebar := titlebar
			this.alwaysFlushToDisk := alwaysFlushToDisk
			this.enableCommands := enableCommands
			this.consoleMode := consoleMode
			this.logCommands := logCommands
			this.nameInLog := nameInLog
		}
	}
	

	log(msg)
	{
		tv := false
		if(this.enableCommands && ! this.logCommands)
		{
			tv := this.doEvals(msg)
		}
		if(tv != false)
			return
		
		omsg := msg
		
		if(this.nameInLog)
			msg := this.ctit . msg
		
		if(this.prependDate)
			msg := this.DateString() . ": " . msg
		if(this.alwaysFlushToDisk)
		{
			FileRead, lc, % this.logloc
			this.LogContents := lc
			FileDelete, % this.logloc
		}
		
		if(this.LogContents != "")
		{
			if(this.topToBottom)
			{
				this.LogContents := msg . "`r`n" . this.LogContents
				; msgbox, ttb
			}
			else
			{
				this.LogContents := this.LogContents . "`r`n" . msg
				; msgbox, btt
			}
		}
		else
		{
			; msgbox, no content yet...
			this.LogContents := msg
		}
		; msgbox, % "result: `n" this.LogContents
		
		if(this.alwaysFlushToDisk)
		{
			FileAppend, % this.LogContents, % this.logloc
		}
		
		if(this.consid == 0)
		{
			this.buildGui()
			; this.setTextHeight(20)
			; this.doSizePos()
		}
		else
		{
			if(this.conshide)
			{
				; WinShow, % "ahk_id " this.consid
				gui, % this.myGUIName ": show", % "x" this.posX " y" this.posY " NoActivate"
				this.conshide := false
			}
			this.applyContents()
		}
		
		
		if(this.enableCommands && this.logCommands)
			this.doEvals(omsg)
		
	} ; END log
	
	buildGui()
	{
		; +E0x20 ; <-- click through!
		GUI, % this.myGUIName ": New", +Lastfound +AlwaysOnTop +ToolWindow +E0x08000000, % this.myTitle ; 
		gui, % this.myGUIName ": color", % this.consolecol
		WinSet, Transparent, % this.opacity
		Gui, % this.myGUIName ": -Caption"
		Gui, % this.myGUIName ": Color",, % this.textBackgroundCol
		this.startpos := this.padding
		if(this.titlebar)
		{	
			Gui, % this.myGUIName ": Font", S8 bold
			tmw := this.width - 2* this.padding
			global titbar
			Gui, % this.myGUIName ": Add", Text, % "x" this.padding " y" this.padding " w" tmw " h15 c" this.fontcol " vtitbar", % this.myTitle
			this.startpos := 15 + 2* this.padding 
		}
		
		cbuy := this.startpos
		cbuwi := 17
		cbuhe := 14
		cbux := this.width - cbuwi - this.padding
		
		gui, % this.myGUIName ": Font", S7 norm center
		gui, % this.myGUIName ": Add", button, w%cbuwi% h%cbuhe% x%cbux% y%cbuy% hwndtbutt, _
		fn := this.minimize.Bind(this)
		GuiControl +g, %tbutt%, % fn
		cbuy += 18
		gui, % this.myGUIName ": Add", button, w%cbuwi% h%cbuhe% x%cbux% y%cbuy% hwndtbutt, <
		fn := this.slide.Bind(this)
		GuiControl +g, %tbutt%, % fn
		cbuy += 18
		gui, % this.myGUIName ": Add", button, w%cbuwi% h%cbuhe% x%cbux% y%cbuy% hwndtbutt, C
		fn := this.clear.Bind(this)
		GuiControl +g, %tbutt%, % fn
		cbuy += 18
		gui, % this.myGUIName ": Add", button, w%cbuwi% h%cbuhe% x%cbux% y%cbuy% hwndtbutt, S
		fn := this.save.Bind(this)
		GuiControl +g, %tbutt%, % fn
		cbuy += 18
		gui, % this.myGUIName ": Add", button, w%cbuwi% h%cbuhe% x%cbux% y%cbuy% hwndtbutt, O
		fn := this.open.Bind(this)
		GuiControl +g, %tbutt%, % fn
		cbuy += 18
		gui, % this.myGUIName ": Add", button, w%cbuwi% h%cbuhe% x%cbux% y%cbuy% hwndtbutt, X
		fn := this.close.Bind(this)
		GuiControl +g, %tbutt%, % fn
		
		absminh := cbuy + cbuhe - this.padding
		if this.minHeight < absminh
			this.minHeight := absminh
			
		this.tWmax := this.width - (2*this.padding) - 25
		Gui, % this.myGUIName ": Font", % "S" this.fontsize, Consolas
		Gui, % this.myGUIName ": Add", Edit, % "x" this.padding " y" this.startpos " w" this.tWmax " +Multi c" this.fontcol " -VScroll -E0x200 HwndtLogContsID", % this.LogContents
		this.LogContsID := tLogContsID
		gui, % this.myGUIName ": show", % "x" this.posX " y" this.posY " autosize NoActivate"
		gui, % this.myGUIName ": +LastFound"
		this.consid := WinExist()
		
		WinGetPos,,,,mbH, % "ahk_id " this.consid
		this.winAbsMinHeight := mbH
		this.setMaxTextHeight()
		
		clickdrag := ObjBindMethod(this, "drag")
		OnMessage(0x201, clickdrag) ; WM_LBUTTONDOWN
		
		moving := ObjBindMethod(this, "moving")
		OnMessage(0x03, moving) ; WM_MOVE
		; OnMessage(0x0047, moving) ; WINDOWPOSCHANGED
		
		; applyContents()
	}
	
	applyContents()
	{
		; controlRemove(this.Ghost)
		Gui, % this.myGUIName ": Font", % "S" this.fontsize, Consolas
		Gui, % this.myGUIName ": Add", Edit, % "x" this.padding " y" this.startpos " w" this.tWmax " +Hidden -VScroll -E0x200 HwndtGhost", % this.LogContents
		this.Ghost := tGhost
		ControlGetPos,,,, ctH,, % "ahk_id " this.Ghost
		SendMessage, 0x10,,,, % "ahk_id " this.Ghost
		
		GuiControl, Text, % this.LogContsID, % this.LogContents
		
		this.setTextHeight(ctH)
		
		if(this.topToBottom)
			postMessage,0x115,0x6,,,% "ahk_id " this.LogContsID ; WM_VSCROLL = 0x0115 ; controlsend,, ^{home}, % "ahk_id " this.LogContsID
		else
			postMessage,0x115,0x7,,,% "ahk_id " this.LogContsID ; WM_VSCROLL = 0x0115 ; controlsend,, ^{end}, % "ahk_id " this.LogContsID
		
		
	}
	
	setTextHeight(num)
	{
		; msgbox, % "in: " num
		this.ctH := num > this.maxTextHeight ? this.maxTextHeight : num
		; this.ctH := this.ctH < this.minTextHeight ? this.minTextHeight : this.ctH
		; msgbox, % "out: " this.ctH
		if(this.ctH != this.oH)
		{
			ControlMove,,,,,this.ctH, % "ahk_id " this.LogContsID
			this.oH := this.ctH
			if (this.ctH + this.winHeightAdd > this.winAbsMinHeight)
				winmove, % "ahk_id " this.consid,,,,,% this.ctH + this.winHeightAdd
			; this.allset := false
		}
	}
		
	setMaxTextHeight()
	{
		this.winHeightAdd := this.startpos + this.padding
		this.maxTextHeight := this.maxHeight-this.winHeightAdd
		; this.minTextHeight := this.minHeight-this.winHeightAdd
	}
	
	doSizePos(isUpdate = false)
	{
		; capTextHeight()
		
		; if(this.ctH != this.oH)
		; {
			; if this.ctH < this.minHeight
			; {
				; this.ctH := this.minHeight
			; }
			; this.oH := this.ctH
			; winmove, % "ahk_id " this.consid,,,,,% this.ctH + this.startpos + this.padding
		; }
		
	}
	
	position(x="",y="")
	{
		if(x!="")
			this.posX := x
		if(y!="")
			this.posY := y
		WinMove, % "ahk_id " this.consid,,% this.posX,% this.posY
	}
	
	setX(x)
	{
		this.position(x)
	}
	
	setY(y)
	{
		this.position(,y)
	}
	
	doEvals(msg)
	{
		cmd := this.explode(msg, ",")
		if(cmd.MaxIndex()<1 || subStr(msg, 1, 1) != "\")
			return false
			
		; why does AHK not support SWITCH statements yet? :(
		if(this.toLower(cmd[1]) == "\close")
			this.close()
		else if(this.toLower(cmd[1]) == "\hide")
			this.minimize()
		else if(this.toLower(cmd[1]) == "\show")
			this.restore()
		else if(this.toLower(cmd[1]) == "\save")
			this.save()
		else if(this.toLower(cmd[1]) == "\view")
			this.open()
		else if(this.toLower(cmd[1]) == "\setx")
			this.setX(cmd[2])
		else if(this.toLower(cmd[1]) == "\sety")
			this.setY(cmd[2])
		else if(this.toLower(cmd[1]) == "\setpos")
			this.position(cmd[2], cmd[3])
		else if(this.toLower(cmd[1]) == "\rep")
			msgbox, % this.posX ", " this.posY
		else
			return false
	}

	minimize(){
		WinHide, % "ahk_id " this.consid
		this.conshide := true
	}
	
	restore(){
		; WinShow, % "ahk_id " this.consid
		gui, % this.myGUIName ": show", % "x" this.posX " y" this.posY " NoActivate"
		this.conshide := false
	}

	close()
	{
		if(this.animate)
		{
			this.fadeWin(this.consid, 1, true)
		}
		else
		{
			gui, % this.myGUIName ": Destroy"
		}
		if(this.clearOnClose)
		{
			this.LogContents := ""
			FileDelete, % this.logloc
		}
		this.consid := 0
	}
	
	drag(w,l,m,h)
	{
		if(h == this.consid)
		{
			PostMessage, 0xA1, 2,,, % "Ahk_id " h
			return
		}
	}
	
	moving(w, l, m, h)
	{
		if(h == this.consid && ! this.sliding)
		{
			this.posX := this.GET_X_LPARAM(l)
			this.posY := this.GET_Y_LPARAM(l)
			this.consslid := true
		}
	}

	save(){
		GUI, % this.myGUIName ": +OwnDialogs"
		FileSelectFile, logsaveloc,S,% "Log " . this.DateString(true) . ".log",Save Log, Logs (*.log)
		if(logsaveloc)
		{
			filecopy, % this.logloc, %logsaveloc%
		}
	}

	open(){
		run, % this.logloc
	}
	sliding := false
	slide()
	{
		this.sliding := true
		if(this.consslid := ! this.consslid)
		{
			if(this.animate)
			{
				this.slideWin(this.consid, this.posX,this.posY,200)
			}
			else
			{
				WinMove, % "ahk_id " this.consid,,% this.posX,% this.posY
			}
		}
		else
		{
			if(this.animate)
			{
				this.slideWin(this.consid, 30 - this.width,this.posY, 200)
			}
			else
			{
				WinMove, % "ahk_id " this.consid,,% 30 - this.width,% this.posY
			}
		
		}
		this.sliding := false
	}

	clear(){
		this.LogContents := ""
		FileDelete, % this.logloc
		this.applyContents()
	}
	
	; ######### general functions ##########
	
	DateString(filesafe = false)
	{
		if(filesafe)
			FormatTime, mcurrentTime, %A_Now%, yyyy-MM-dd HH-mm-ss
		else
			FormatTime, mcurrentTime, %A_Now%, yyyy-MM-dd HH:mm:ss
		return mcurrentTime
	}

	explode(string, delim=",", trimvals = true)
	{
		parr := StrSplit(string, delim)
		if(trimvals)
		{
			for k, v in parr{
				parr[k] := trim(v)
			}
		}
		return, parr
	}
	
	toLower(string)
	{
		StringLower, string, string
		return % string
	}
	
	fadeWin(msid, ms = 10, closeOnFinish = false, trans = 256)
	{
		if(trans>=256)
		{
			WinGet, trans, Transparent, ahk_id %msid%
		}
		ntrans := trans-2
		WinSet, Transparent, %ntrans%, ahk_id %msid%
		if(ntrans>0)
		{
			sleep, ms
			this.fadeWin(msid, ms, closeOnFinish, ntrans)
		}
		else
			if(closeOnFinish)
				WinClose, ahk_id %msid%
	}

	slideWin(msid, tX = 0, tY = 0, T = 500, rightAlign = false, closeOnFinish = false, frst = true, dX = 0, dY = 0, step=0, maxStep=0)
	{
		anint := 100
		winGetPos, wX,wY,wW,wH,ahk_id %msid%
		woX := wX
		if(rightAlign)
		{
		wX += wW
		}
		
		if(frst)
		{
		maxStep := Round(T/(anint + 0))
		dX := Round((tX - wX) / maxStep)
		dY := Round((tY - wY) / maxStep)
		}
		
		if(step<maxStep)
		{
			newX := woX + dX
			newY := wY + dY
			winMove, ahk_id %msid%,,newX,newY
			; sleep, anint-19
			this.slideWin(msid, tX, tY, T, rightAlign, closeOnFinish, false, dX, dY, step+1, maxStep)
		}
		else
		{
			if(rightAlign)
			{
				winMove, ahk_id %msid%,, tX-wW,tY
			}
			else
			{
				winMove, ahk_id %msid%,, tX,tY
			}
			if(closeOnFinish)
			{
				WinClose, ahk_id %msid%
			}
		}
	}

	GET_X_LPARAM(lParam) {
	   NumPut(lParam, Buffer:="    ", "UInt")
	   Return NumGet(Buffer, 0, "Short")
	}
	GET_Y_LPARAM(lParam) {
	   NumPut(lParam, Buffer:="    ", "UInt")
	   Return NumGet(Buffer, 2, "Short")
	}
}

logg(str){
	global console
	if(console ==""){
		global console = new BensConsole()
	}
	console.log(str)
}
Thanks for bringing that to my attention!
Let me know if it works now :)
:morebeard:
pk23
Posts: 110
Joined: 24 Apr 2015, 00:49

Re: OSD Console / Log

12 Apr 2019, 20:32

no need to sorry, you're the creator who deserve to be thanked. :P
After using the \save command, the save dialog box did pop up and I choose D:\, but the log file didn't appear on the D:\ disk, maybe I did wrong somewhere.
However, alwaysFlushToDisk is now working normally and is already totally enough for me to use. so thank you.

https://i.imgur.com/T72Js6F.gifv
User avatar
svArtist
Posts: 62
Joined: 08 Mar 2015, 18:16

Re: OSD Console / Log

12 Apr 2019, 20:46

pk23 wrote:
12 Apr 2019, 20:32
After using the \save command, the save dialog box did pop up and I choose D:\, but the log file didn't appear on the D:\ disk
Hmmm... that is strange.
I can't reproduce the behavior.

Maybe there is an issue with acces rights going on.
Have you tried running AHK as Administrator?
(Go to the location of your AutoHotkey.exe, probably C:\Program Files\AutoHotkey, right click on the .exe -> Properties -> Compatibility, check "Run this program as an administrator".

I have mine always set to run as Administrator, to avoid running into issues like that. Maybe that helps.
Image
:morebeard:
pk23
Posts: 110
Joined: 24 Apr 2015, 00:49

Re: OSD Console / Log

12 Apr 2019, 21:33

After giving AutoHotkey.exe admin rights (in fact the login account is already admin, but just gave it again via context menu - properties anyway), the log file still cannot be written to the disk (other paths have also been tried), which is really strange, considering the built-in command eg. FileAppend works well.
but I think we can't rule out the problem with my computer, and it's also not important at present (alwaysFlushToDisk is enough to use for me), so let's just put this issue on hold for the time being. :D
This library function is very useful for debugging and troubleshooting scripts. thank you for your creation.
User avatar
svArtist
Posts: 62
Joined: 08 Mar 2015, 18:16

Re: OSD Console / Log

14 Apr 2019, 06:22

I'm happy to hear that :)
If it becomes important and you feel like looking at it, keep me in the loop. In case I can improve something. (Error handling in higher level functions is a bitch, not sure if we can even detect something is going wrong from here)
:morebeard:
Andrew1802
Posts: 23
Joined: 02 Jul 2020, 07:28

Re: UPDATE: OSD Console / Log

24 Sep 2022, 04:19

Fix for the slide method, on displays with scaling enabled:
Old:

Code: Select all

slide()
	{
		this.sliding := true
		if(this.consslid := ! this.consslid)
		{
			if(this.animate)
			{
				this.slideWin(this.consid, this.posX,this.posY,200)
			}
			else
			{
				WinMove, % "ahk_id " this.consid,,% this.posX,% this.posY
			}
		}
		else
		{
			if(this.animate)
			{
				this.slideWin(this.consid, 30 - this.width,this.posY, 200)
			}
			else
			{
				WinMove, % "ahk_id " this.consid,,% 30 - this.width,% this.posY
			}
		}
		this.sliding := false
	}
New:

Code: Select all

slide()
	{
		this.sliding := true
		if(this.consslid := ! this.consslid)
		{
			if(this.animate)
			{
				this.slideWin(this.consid, this.posX,this.posY,200)
			}
			else
			{
				WinMove, % "ahk_id " this.consid,,% this.posX,% this.posY
			}
		}
		else
		{
			if(this.animate)
			{
				this.slideWin(this.consid, 30 - this.width*(A_ScreenDPI/96),this.posY, 200)
			}
			else
			{
				WinMove, % "ahk_id " this.consid,,% 30 - this.width*(A_ScreenDPI/96),% this.posY
			}
		}
		this.sliding := false
	}

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: metallizer and 95 guests