Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Keyboard hook
#1
Hi Gintaras,

I've made a utility with QM that kills and then restarts two specific programs (I have compiled the utility to an executable). What I would like is another compiled executable (made with QM as well) that functions as a hotkey listener (keyboard hook). So that my utility can be launched by a hotkey.

I know that QM listens for triggers while it's running but is it possible to compile this process into an executable (that then has to be in the Windows startup folder of course)?
#2
does your executable have a dialog?
there are a few options depending on yes or no

have a look in the archive file
http://www.quickmacros.com/forum/showthr...p?tid=2852
lots of examples 

here are a couple
Function __RegisterHotKey_example
Code:
Select All      Help
;Shows how to use __RegisterHotKey to use hotkeys in a windowless thread.
;This should be function, not macro, because runs all the time.

__RegisterHotKey hk1.Register(0 1 MOD_CONTROL|MOD_SHIFT VK_F5)
;also can register more hotkeys, for example
__RegisterHotKey hk2.Register(0 2 MOD_CONTROL 'B')
;...

MSG m
rep
,if(GetMessage(&m 0 0 0)<1) break
,sel m.message
,,case WM_HOTKEY
,,sel m.wParam
,,,case 1 ;;Ctrl+Shift+F5 pressed
,,,mac "Function_that_does_something_on_Ctrl_Shift_F5"
,,,out "Ctrl+Shift+F5
,,,case 2
,,,out "Ctrl+B"
,,,
,,,;...
,,,
,DispatchMessage &m

Function dialog_hotkeys
Code:
Select All      Help
\Dialog_Editor

str dd=
;BEGIN DIALOG
;0 "" 0x90C80AC8 0x0 0 0 223 135 "Dialog"
;1 Button 0x54030001 0x4 120 116 48 14 "OK"
;2 Button 0x54030000 0x4 170 116 48 14 "Cancel"
;END DIALOG
;DIALOG EDITOR: "" 0x2030506 "*" "" "" ""

if(!ShowDialog(dd &sub.DlgProc 0)) ret


#sub DlgProc
function# hDlg message wParam lParam
__RegisterHotKey- t_hk1 t_hk2
sel message
,case WM_INITDIALOG
,t_hk1.Register(hDlg 1 MOD_CONTROL|MOD_SHIFT VK_F5) ;;Ctrl+Shift+F5
,t_hk2.Register(hDlg 2 MOD_ALT|MOD_WIN 'Q') ;;Alt+Win+Q
,
,case WM_HOTKEY
,sel wParam
,,case 1 out "Ctrl+Shift+F5"
,,case 2 out "Alt+Win+Q"
,
,case WM_DESTROY
,case WM_COMMAND goto messages2
ret
;messages2
sel wParam
,case IDOK
,case IDCANCEL
ret 1

and many more in archive file
easiest would be to add a function like one of these or others and rebuild your exe
#3
Thank you Kevin,

No it's not a dialog it's a simple utility that displays some text on the screen, stops a program (kills the process) and then starts that program again.
If I understand correctly the first sample function you mentioned can do this. Let's say I would indeed use Ctrl+Shift+F5 as a hotkey. How do I insert the path to my target executable in this function?

"C:\Program Files (x86)\Restart Utility\Restartapp.exe"

Assuming this can be done, I would then be able to compile this function to exe. Start that executable, press Ctrl+Shift+F5 and then it would run my Restartapp utility ?
#4
something like this should work

Function __RegisterHotKey_example
Code:
Select All      Help
;Shows how to use __RegisterHotKey to use hotkeys in a windowless thread.
;This should be function, not macro, because runs all the time.

__RegisterHotKey hk1.Register(0 1 MOD_CONTROL|MOD_SHIFT VK_F5)
;also can register more hotkeys, for example
;__RegisterHotKey hk2.Register(0 2 MOD_CONTROL 'B')
;...

MSG m
rep
,if(GetMessage(&m 0 0 0)<1) break
,sel m.message
,,case WM_HOTKEY
,,sel m.wParam
,,,case 1 ;;Ctrl+Shift+F5 pressed
,,,run "C:\Program Files (x86)\Restart Utility\Restartapp.exe"
,,,;case 2
,,,;out "Ctrl+B"
,DispatchMessage &m
may need to adjust file location..
two ways to do it
drag and drop the exe into the qm editor
or use the run program dialog in the floating toolbar
   
   
   
#5
Thank you Kevin!

Works like a charm  Smile
This opens up a whole new range of possibilities for me. What a great program this is!
#6
My utility that kills and then restarts programs (controlled with a keyboard hook) works properly.
However, the programs that were 'killed" leave orphan tray icons in the taskbar.

In the Archive there are several scripts about tray icons, tooltips etc. But I can find one that will remove these orphans.
I could create a mouse drag command to hover over them in order to get rid of them but that won't work with different screen resolutions......
Any ideas?
#7
whats the code your using to end the processes? Sometimes windows will leave ghost windows and processes as well. what happens when you move your mouse over that icon? does it disappear?
#8
Kevin,

My utility currently stops both Dragon NaturallySpeaking and VoiceComputer (an add-on program) and then starts them again (there's no processes left from both executables once they have been stopped). They also restart correctly (VoiceComputer restarts Dragon). This is the code:

Macro Restart Dragon and VC
Code:
Select All      Help
OnScreenDisplay "If any instance of VoiceComputer or Dragon is running, it will now exit" 3
3
ShutDownProcess("VP")
ShutDownProcess("natspeak")
3
OnScreenDisplay "DONE! VoiceComputer will now start and relaunch Dragon" 2.5
3
OnScreenDisplay "This operation will probably leave some 'orphan' tray icons in your taskbar" 2.5
3
OnScreenDisplay "Simply hover your mouse cursor over them and they will be removed" 2.5
3
run "$program files$\VoiceTeach\VoiceComputer\scripts\VoiceComputer.exe"

When I hover the mouse over the (ghost) tray icons they disappear.
Also, I would like to change the on-screen display color from green into something else (red for instance). I followed some of the examples in the documentation but didn't get any changing of color.
#9
Function Function23
Code:
Select All      Help
OnScreenDisplay "If any instance of VoiceComputer or Dragon is running, it will now exit." 3  0 0 "" 0 0x0000FF 
3
ShutDownProcess("VP")
ShutDownProcess("natspeak")
3
OnScreenDisplay "DONE! VoiceComputer will now start and relaunch Dragon" 2.5  0 0 "" 0 0x0000FF 
3
OnScreenDisplay "This operation will probably leave some 'orphan' tray icons in your taskbar" 2.5  0 0 "" 0 0x0000FF
3
OnScreenDisplay "Simply hover your mouse cursor over them and they will be removed" 2.5  0 0 "" 0 0x0000FF
3
run "$program files$\VoiceTeach\VoiceComputer\scripts\VoiceComputer.exe"

;other options

;int w=win("- Notepad" "Notepad" "" 2)

;ShutDownProcess(w 2) ;;;with flag 2 soft close if poosible

;clo w ;;;using qm close window function

;using PostMessage

;PostMessage w WM_SYSCOMMAND SC_CLOSE 0;;
;or
;PostMessage w WM_CLOSE 0 0

more about osd
   
more about ShutDownProcess
   
more about close window
http://www.quickmacros.com/help/Commands/IDP_CLO.html
for even more information about these topics search the forum
#10
Thanks Kevin, but the only thing that appears to work in this situation is ShutDownProcess (the executables to be killed are windowless programs). Also, adding a flag doesn't make a difference.

I can reach the Taskbar tray Icon with sending keys: Win+T  TAB  RIGHT  ENTER (and repeat those last two a couple of times).
This procedure will remove the orphans but it will also activate any working tray Icon which of course is undesired.....

I found a shorter way and that is restarting explorer.exe. The orphan icons will immediately be removed after that:

Macro Restart Dragon and VC
Code:
Select All      Help
ShutDownProcess("explorer")
3
run "$windows$\explorer.exe"
3
key AF4         ;; Alt+F4

It doesn't appear to affect any running programs (but I will have to test that more thoroughly). I added  ALT + F4  to immediately close Windows Explorer when it pops up.
#11
To remove a ghost tray icon, maybe a better way exists, but I know only the "mouse move" way. Find it as accessible object and mouse-move.

Macro Macro3030
Code:
Select All      Help
run "$program files$\VideoLAN\VLC\vlc.exe"
3
ShutDownProcess "VLC"
int w=win("" "Shell_TrayWnd")
Acc a.Find(w "PUSHBUTTON" "VLC*" "class=ToolbarWindow32[]id=1504" 0x1005) ;;Win10. On other OS may be different id.
a.Mouse()
mou

or
Macro Macro3031
Code:
Select All      Help
run "$program files$\VideoLAN\VLC\vlc.exe"
3
ShutDownProcess "VLC"
int w=win("" "Shell_TrayWnd")
Acc a.Find(w "PUSHBUTTON" "VLC*" "class=ToolbarWindow32[]id=1504" 0x1005) ;;Win10. On other OS may be different id.
POINT p; a.Location(p.x p.y)
w=child(a)
ScreenToClient w &p
PostMessage w WM_MOUSEMOVE 0 MakeInt(p.x+5 p.y+5)
#12
Smile 
Thank you Gintaras! This works very well. 

And it is definitely much more elegant (and safer) then killing and restarting Explorer.


Forum Jump:


Users browsing this thread: 1 Guest(s)