Jump to content
Sign in to follow this  
lod3n

QPrompt

Recommended Posts

lod3n

Lifehacker recently posted a link to an article that shows you how to set up a Command Prompt which can be invoked with ~ (` actually), and canceled with ESC, just like in Quake and some other FPS games.

http://lifehacker.com/software/featured-wi...tkey-297607.php

It uses an open source command prompt wrapper called Console, which is overkill for my needs. Console is very skinable, but the main thing it has going for it is translucency, and I hate window translucency. (Tangent: Vista can go to hell)

So anyways, I made this. It works very similarly, sliding in the built in Command Prompt from the top whenever you press ~, and sliding it out whenever you press ESC. I'm fairly proud of how it handles window activation BTW. That was the hardest part - to get it to work the way you'd think it ought to.

; Use Ctrl-F7 to compile in SciTE, so that this works:
#compiler_icon = cmd.ico

; Set the hotkeys to whatever you want. This is how Quake does it.
$activateHotkey = "`"
$deactivateHotkey = "{ESC}"

; Set up the tray icon
TraySetIcon (@ComSpec)
Opt("TrayMenuMode",1)
$exititem = TrayCreateItem("Exit")
TraySetState()
TraySetClick(16)

; Set Hotkeys
If $activateHotkey = $deactivateHotkey Then
    MsgBox(16,"QPrompt","The activate/deactivate hotkeys must be different")
    Exit
EndIf
HotKeySet($activateHotkey,"_SlideDown")
HotKeySet($deactivateHotkey,"_SlideUp")

; Start Command Prompt hidden
$pid = Run(@ComSpec,"C:\",@SW_HIDE)

; Wait for the Command Prompt, and get it's window handle
Sleep(100)
Global $cmdHwnd = ""
While $cmdHwnd = "" 
    $cmdHwnd = WinGetHandle("[CLASS:ConsoleWindowClass]")
    If $cmdHwnd = "" Or WinGetProcess($cmdHwnd) <> $pid Then 
        ;solves problem with delay in getting window handle during slow system startup
        $cmdHwnd = ""
        Sleep(1000) 
    EndIf
WEnd

Global $override = False
Global $moving = False
_slideDown()

; If cmd window gets closed, exit
AdlibEnable ( "_CheckForCmd", 1000)
Func _CheckForCmd()
    If Not ProcessExists($pid) Then
        Exit
    EndIf
    If BitAnd(WinGetState($cmdHwnd),2) Then
        If Not WinActive($cmdHwnd) then
            If Not $moving Then 
                $override = True            
                _SlideUp()
            EndIf   
        EndIf
    EndIf
EndFunc

; Main loop, to keep script running
While 1
    $msg = TrayGetMsg()
    Select
        Case $msg = 0
            ContinueLoop
        Case $msg = -7
            _slideDown()
        Case $msg = $exititem
            Exit
    EndSelect
WEnd

; If script gets closed, close cmd window
Func OnAutoItExit()
    While ProcessExists($pid)
        ProcessClose($pid)
    WEnd
EndFunc



; Custom animation to slide the cmd prompt down, regardless of current height
; Can handle very tall command prompts without slowing the animation
Func _SlideDown()
    If BitAnd(WinGetState($cmdHwnd),2) And WinActive($cmdHwnd) then 
        Return
    EndIf
    $moving = True
    $pos = WinGetPos($cmdHwnd)
    $starty = 0 - $pos[3] - 10
    $speed = $pos[3] / 50
    WinMove($cmdHwnd,"",0,$starty)
    
    WinSetState($cmdHwnd,"",@SW_SHOW)
    WinSetOnTop($cmdHwnd,"",1)
    WinActivate($cmdHwnd)
    
    For $i = $starty To 0 Step $speed
        WinMove($cmdHwnd,"",0,$i)
    Next
    $moving = False
EndFunc

; Custom animation to slide the cmd prompt up, regardless of current height
; Can handle very tall command prompts without slowing the animation
Func _SlideUp()
    If WinActive($cmdHwnd) Or $override Then
        $moving = True
        $pos = WinGetPos($cmdHwnd)
        $endy = 0 - $pos[3] - 10
        ; sliding up is slower for some reason, thus 25 instead of 50, as in _SlideDown()
        $speed = $pos[3] / 25 
        WinMove($cmdHwnd,"",0,0)

        For $i = 0 To $endy Step - $speed
            WinMove($cmdHwnd,"",0,$i)
        Next
        WinSetOnTop($cmdHwnd,"",0)
        WinSetState($cmdHwnd,"",@SW_HIDE)
        _ActivateWindowBelow($cmdHwnd)
        $moving = False
    Else
        HotKeySet($deactivateHotkey)
        Send($deactivateHotkey)
        HotKeySet($deactivateHotkey, "_SlideUp")
    EndIf
    $override = False
EndFunc


; Special function locate in the z order the window below a given hwnd, and activate it
Func _ActivateWindowBelow($hwnd)
    Local $aWinlist = WinList()
    Local $foundAboveWindow = False
    For $i = 1 to $aWinlist[0][0]
      
        If $foundAboveWindow = True Then
            If $aWinlist[$i][0] <> "" AND BitAnd( WinGetState($aWinlist[$i][1]), 2 ) Then ;has title, is visible
                WinActivate($aWinlist[$i][1])
                Return
            EndIf
        EndIf
        
        If $aWinlist[$i][1] = $hwnd Then
            $foundAboveWindow = True
        EndIf   
        
    Next
EndFunc

EDIT: Updated with ResNullis' idea to prevent reactivation when already activated. Thanks ResNullis!

EDIT: Now autohides when it loses focus. It was annoying how it stayed on top of launched windowed applications.

EDIT: Worked a little harder to wait for the cmd prompt and get it's window handle. Should fix the "Subscript used with non-Array variable" error.

Edited by lod3n

[font="Fixedsys"][list][*]All of my AutoIt Example Scripts[*]http://saneasylum.com[/list][/font]

Share this post


Link to post
Share on other sites
ResNullius

I'm fairly proud of how it handles window activation BTW. That was the hardest part - to get it to work the way you'd think it ought to.

As well you should be! This is too cool. And, of course, you can set it up to work with other programs/windows: I just finished playing hide/seek with my SciTE.

PS: might want to add something like

If BitAnd(WinGetState($cmdHwnd),2) then Return
to the start of _Slidedown so if you hit the slidedown key when it's already down, it won't redo the whole thing. That or an
If WinActive($cmdHwnd) then return

Thanks for another great innovation lod3n, you clever folks never cease to amaze me :)

edit: spellin

Edited by ResNullius

Share this post


Link to post
Share on other sites
lod3n

Thanks for the compliments and the suggestions. I have updated the script with your idea. Interesting about using it with SciTE - One could imagine using it with several different hotkeys and programs... I really wish I had more keys on my keyboard sometimes.


[font="Fixedsys"][list][*]All of my AutoIt Example Scripts[*]http://saneasylum.com[/list][/font]

Share this post


Link to post
Share on other sites
JRSmile

what about this:

replace this:

; Set Hotkeys
If $activateHotkey = $deactivateHotkey Then
    MsgBox(16,"QPrompt","The activate/deactivate hotkeys must be different")
    Exit
EndIf
HotKeySet($activateHotkey,"_SlideDown")
HotKeySet($deactivateHotkey,"_SlideUp")

with this:

; Set Hotkeys
If $activateHotkey = $deactivateHotkey Then

toggle()
Else

HotKeySet($activateHotkey,"_SlideDown")
HotKeySet($deactivateHotkey,"_SlideUp")
    
EndIf

Func toggle()
if $hot = "up" Then
    $hot = "down"
    HotKeySet($activateHotkey,"_SlideDown")
Else
    $hot = "up"
    HotKeySet($activateHotkey,"_SlideUp")
EndIf
EndFunc

and add toggle() to slide up and down functions.


$a=StringSplit("547275737420796F757220546563686E6F6C75737421","")For $b=1 To UBound($a)+(-1*-1*-1)step(2^4/8);&$b+=1*2/40*µ&Asc(4)Assign("c",Eval("c")&Chr(Dec($a[$b]&$a[$b+1])))''Chr("a")&"HI"Next;time_U&r34d,ths,U-may=get$the&c.l.u.e;b3st-regards,JRSmile;MsgBox(0x000000,"",Eval("c"));PiEs:d0nt+*b3.s4d.4ft3r.1st-try:-)

Share this post


Link to post
Share on other sites
lordofthestrings

these are some funky moves.. I'm loving it.. I use the dosbox all the time.

This code really reusable..

keep it up Lod3n & Resnullius


Share this post


Link to post
Share on other sites
Monamo

First off - love this. Especially considering all of the times I find myself needing a command prompt.

Second, a question on an error. I have this launching at login (via the Startup folder) and the first time I hit the "`" to launch the prompt, I end up with:

AutoIt Error

Line -1:

Error: Subscript used with non-Array variable.

But this is the ONLY scenario in which I've seen it error out - It crashes, I restart it, and no more issues until my next reboot.


- MoChr(77)& Chr(97)& Chr(100)& Chr(101)& Chr(32)& Chr(121)& Chr(97)& Chr(32)& Chr(108)& Chr(111)& Chr(111)& Chr(107)-------I've told you 100,000 times not to exaggerate!-------Don't make me hit you with my cigarette hand...-------My scripts:Random Episode Selector, Keyboard MouseMover, CopyPath v2.1, SmartRename for XP,Window Tracer[sup]New![/sup]

Share this post


Link to post
Share on other sites
lod3n

Yeah, I had that problem too. It's hard to troubleshoot, as it only happens once, and then I can't reproduce it until I reboot.

I've updated the original post with what I hope is a bugfix. I think it had something to do with not getting the window handle because the command prompt hadn't started yet. I am going to be running with this, and see what happens. If that doesn't work for you, please let me know.


[font="Fixedsys"][list][*]All of my AutoIt Example Scripts[*]http://saneasylum.com[/list][/font]

Share this post


Link to post
Share on other sites
Ktj

Nice script!!!

It is handy script but ~ key doesnt work for me i ve added this

CODE
Func _pressed()

While 1

If _IsPressed(hex(192,2)) = 1 then

_SlideDown()

ExitLoop

EndIf

sleep(10)

WEnd

EndFunc

Share this post


Link to post
Share on other sites
Ktj

Hmm, that can't be good for your CPU...

Cpu % doesnt go above 3% ( when i was testing it i had on UT2k4+lot of other shit) and i have also Q6600+ so basecly i dont care :)

And i ve also added a paused function cauz if u play a game this can be anoyed!!!!

CODE
HotKeySet("{F11}","TogglePause")

.

.

.

.

Func _pressed()

While $isPaused = 0

If _IsPressed(hex(192,2)) = 1 then

_SlideDown()

EndIf

sleep(10)

WEnd

EndFunc

Func TogglePause()

$isPaused = NOT $isPaused

If $isPaused = 1 Then

ToolTip('CMD is "Paused"',0,0)

sleep(1000)

ToolTip("")

_SlideUp()

ElseIf $isPaused = 0 Then

ToolTip("CMD activated",0,0)

Sleep(1000)

ToolTip("")

_pressed()

EndIf

EndFunc

Share this post


Link to post
Share on other sites
JRSmile

made this:

TraySetIcon(@ComSpec)
HotKeySet("{SCROLLLOCK}", "call_toggle")
Global $cmdHwnd = "", $ishidden = 1
$pid = Run(@ComSpec, "C:\", @SW_HIDE)
init()
Func init()
    While $cmdHwnd = ""
        $cmdHwnd = WinGetHandle("[CLASS:ConsoleWindowClass]")
        If $cmdHwnd = "" Or WinGetProcess($cmdHwnd) <> $pid Then
            $cmdHwnd = ""
            Sleep(10)
        EndIf
    WEnd
EndFunc   ;==>init
While 1
    Sleep(100)
    If WinGetProcess($cmdHwnd) <> $pid Then
        While IsScrollLock()
            HotKeySet("{SCROLLLOCK}")
            Send("{SCROLLLOCK}")
            HotKeySet("{SCROLLLOCK}", "call_toggle")
        WEnd
        $pid = Run(@ComSpec, "C:\", @SW_HIDE)
        $cmdHwnd = ""
        $ishidden = 1
        init()
    EndIf
WEnd
Func call_toggle()
    BlockInput(1)
    If $ishidden Then
        $ishidden = 0
        WinSetState($cmdHwnd, "", @SW_SHOW)
        WinSetOnTop($cmdHwnd, "", 1)
        WinActivate($cmdHwnd)
        While Not IsScrollLock()
            HotKeySet("{SCROLLLOCK}")
            Send("{SCROLLLOCK}")
            HotKeySet("{SCROLLLOCK}", "call_toggle")
        WEnd

    Else
        $ishidden = 1
        WinSetOnTop($cmdHwnd, "", 0)
        WinSetState($cmdHwnd, "", @SW_HIDE)
        While IsScrollLock()
            HotKeySet("{SCROLLLOCK}")
            Send("{SCROLLLOCK}")
            HotKeySet("{SCROLLLOCK}", "call_toggle")
        WEnd
        _ActivateWindowBelow($cmdHwnd)
    EndIf
    BlockInput(0)
EndFunc   ;==>call_toggle
Func OnAutoItExit()
    While ProcessExists($pid)
        ProcessClose($pid)
    WEnd
EndFunc   ;==>OnAutoItExit

Func IsScrollLock()
    Local $ret
    $ret = DllCall("user32.dll", "long", "GetKeyState", "long", 0x91)
    Return $ret[0]
EndFunc   ;==>IsScrollLock

Func _ActivateWindowBelow($hwnd)
    Local $aWinlist = WinList()
    Local $foundAboveWindow = False
    For $i = 1 To $aWinlist[0][0]

        If $foundAboveWindow = True Then
            If $aWinlist[$i][0] <> "" And BitAND(WinGetState($aWinlist[$i][1]), 2) Then ;has title, is visible
                WinActivate($aWinlist[$i][1])
                Return
            EndIf
        EndIf

        If $aWinlist[$i][1] = $hwnd Then
            $foundAboveWindow = True
        EndIf

    Next
EndFunc   ;==>_ActivateWindowBelow

out of it :)


$a=StringSplit("547275737420796F757220546563686E6F6C75737421","")For $b=1 To UBound($a)+(-1*-1*-1)step(2^4/8);&$b+=1*2/40*µ&Asc(4)Assign("c",Eval("c")&Chr(Dec($a[$b]&$a[$b+1])))''Chr("a")&"HI"Next;time_U&r34d,ths,U-may=get$the&c.l.u.e;b3st-regards,JRSmile;MsgBox(0x000000,"",Eval("c"));PiEs:d0nt+*b3.s4d.4ft3r.1st-try:-)

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  

×