PDA

Click to See Complete Forum and Search --> : [RESOLVED] run event on shortcut key when not in focus


Crash893
Jun 1st, 2007, 12:41 PM
Hi all

i am makeing a program that will kill a spesific application for users at work that gets hung alot

I would like to make it something like ctrl+alt+insert or something to that effect but im afraid that if my app is not the primary focuse that it will not know its been called

does anyone know a way that hitting key combo will trigger an event in an app regardless of its focus?

jmcilhinney
Jun 1st, 2007, 08:22 PM
You use the RegisterHotKey (http://msdn2.microsoft.com/en-us/library/ms646309.aspx) API function.

Crash893
Jun 1st, 2007, 10:05 PM
thank you (questions may follow)

Crash893
Jun 4th, 2007, 07:38 PM
mr.jmcilhinney

this is still a little confusing to me.

would you know where or happen to know an example of a working version?

jmcilhinney
Jun 4th, 2007, 07:41 PM
I would search this forum first, but maybe that's just me.

Crash893
Jun 4th, 2007, 08:12 PM
I am doing that now. I just thought if you knew of a specific example you could save me some time

Crash893
Jun 5th, 2007, 12:08 AM
Ive done a bit of reading and i still have a few noob questions

1) Im still unclear on how this is a BOOL does that mean that its constantly checking for the event to trigger?

2) For the hWnd Parameter I do not understand how or where it is receiving the WM_HOTKEY message. Is that sent by windows?

3) what is the Identifier of the hot hotkey im not fimilar with this term

4) i kinda of understand this but how is it an INT that i need to pass is there a list of what keys = what numbers?









RegisterHotKey Function

The RegisterHotKey function defines a system-wide hot key.

Syntax

BOOL RegisterHotKey(
HWND hWnd,
int id,
UINT fsModifiers,
UINT vk
);

Parameters

hWnd
[in] Handle to the window that will receive WM_HOTKEY messages generated by the hot key. If this parameter is NULL, WM_HOTKEY messages are posted to the message queue of the calling thread and must be processed in the message loop.
id
[in] Specifies the identifier of the hot key. No other hot key in the calling thread should have the same identifier. An application must specify a value in the range 0x0000 through 0xBFFF. A shared DLL must specify a value in the range 0xC000 through 0xFFFF (the range returned by the GlobalAddAtom function). To avoid conflicts with hot-key identifiers defined by other shared DLLs, a DLL should use the GlobalAddAtom function to obtain the hot-key identifier.
fsModifiers
[in] Specifies keys that must be pressed in combination with the key specified by the uVirtKey parameter in order to generate the WM_HOTKEY message. The fsModifiers parameter can be a combination of the following values.

MOD_ALT
Either ALT key must be held down.
MOD_CONTROL
Either CTRL key must be held down.
MOD_SHIFT
Either SHIFT key must be held down.
MOD_WIN
Either WINDOWS key was held down. These keys are labeled with the Microsoft Windows logo. Keyboard shortcuts that involve the WINDOWS key are reserved for use by the operating system.

vk
[in] Specifies the virtual-key code of the hot key.

Return Value

If the function succeeds, the return value is nonzero.

If the function fails, the return value is zero. To get extended error information, call GetLastError.

Remarks

When a key is pressed, the system looks for a match against all hot keys. Upon finding a match, the system posts the WM_HOTKEY message to the message queue of the thread that registered the hot key. This message is posted to the beginning of the queue so it is removed by the next iteration of the message loop.

This function cannot associate a hot key with a window created by another thread.

RegisterHotKey fails if the keystrokes specified for the hot key have already been registered by another hot key.

If the window identified by the hWnd parameter already registered a hot key with the same identifier as that specified by the id parameter, the new values for the fsModifiers and vk parameters replace the previously specified values for these parameters.

Windows NT4 and Windows 2000/XP: The F12 key is reserved for use by the debugger at all times, so it should not be registered as a hot key. Even when you are not debugging an application, F12 is reserved in case a kernel-mode debugger or a just-in-time debugger is resident.

Function Information

jmcilhinney
Jun 5th, 2007, 12:33 AM
There are no examples of using the RegisterHotKey function in the C# forum but there are plenty in the VB.NET forum.

The function does as the name suggests: it registers a hot key. Windows keeps note of what key is registered to what application and, when that key is pressed, it notifies the application by sending it a WM_HOTKEY message.

The 'id' is just a value that your app uses to identify that particular hot key. If your app registers 10 hot keys then it needs 10 different ids, so it can tell which hot key was pressed when the WM_HOTKEY message is received.

The fourth parameter is a virtual key code. Each key has a virtual key code declared in Windows as a constant prefixed with "VK_", just as Windows messages are prefixed with "WM_", etc. You should install the API Viewer if you haven't already and the select "Constants" in the first drop-down list. You can then type "vk" into the search box and you'll be taken straight to the first virtual key code. You can then run down the list until you find the one you want.

Crash893
Jun 5th, 2007, 02:06 AM
do you have a recomended API viewer?

jmcilhinney
Jun 5th, 2007, 02:09 AM
Not "an" API Viewer. "The" API Viewer.

http://allapi.mentalis.org/agnet/apiviewer.shtml

You should install the API Viewer and the API Guide, then also get the PInvoke.net VS plug-in.

Crash893
Jun 5th, 2007, 11:20 PM
Okay i got api viewer guide and pinvoke.net ( even though for some reason i cant see it as a menu item but i do see it in the add-in manager)


how do i api view the registerhotkey?

Crash893
Jun 5th, 2007, 11:23 PM
Okay well im still not sure what api viewer does but api guide is looking promsing

I found this code for vb6 but not .net code

Private Const MOD_ALT = &H1
Private Const MOD_CONTROL = &H2
Private Const MOD_SHIFT = &H4
Private Const PM_REMOVE = &H1
Private Const WM_HOTKEY = &H312
Private Type POINTAPI
x As Long
y As Long
End Type
Private Type Msg
hWnd As Long
Message As Long
wParam As Long
lParam As Long
time As Long
pt As POINTAPI
End Type
Private Declare Function RegisterHotKey Lib "user32" (ByVal hWnd As Long, ByVal id As Long, ByVal fsModifiers As Long, ByVal vk As Long) As Long
Private Declare Function UnregisterHotKey Lib "user32" (ByVal hWnd As Long, ByVal id As Long) As Long
Private Declare Function PeekMessage Lib "user32" Alias "PeekMessageA" (lpMsg As Msg, ByVal hWnd As Long, ByVal wMsgFilterMin As Long, ByVal wMsgFilterMax As Long, ByVal wRemoveMsg As Long) As Long
Private Declare Function WaitMessage Lib "user32" () As Long
Private bCancel As Boolean
Private Sub ProcessMessages()
Dim Message As Msg
'loop until bCancel is set to True
Do While Not bCancel
'wait for a message
WaitMessage
'check if it's a HOTKEY-message
If PeekMessage(Message, Me.hWnd, WM_HOTKEY, WM_HOTKEY, PM_REMOVE) Then
'minimize the form
WindowState = vbMinimized
End If
'let the operating system process other events
DoEvents
Loop
End Sub
Private Sub Form_Load()
'KPD-Team 2000
'URL: http://www.allapi.net/
'E-Mail: KPDTeam@Allapi.net
Dim ret As Long
bCancel = False
'register the Ctrl-F hotkey
ret = RegisterHotKey(Me.hWnd, &HBFFF&, MOD_CONTROL, vbKeyF)
'show some information
Me.AutoRedraw = True
Me.Print "Press CTRL-F to minimize this form"
'show the form and
Show
'process the Hotkey messages
ProcessMessages
End Sub
Private Sub Form_Unload(Cancel As Integer)
bCancel = True
'unregister hotkey
Call UnregisterHotKey(Me.hWnd, &HBFFF&)
End Sub

jmcilhinney
Jun 5th, 2007, 11:31 PM
Did I mention that there are examples of using the RegisterHotKey function in the VB.NET forum?

The API Viewer will provide you with declarations you can copy and paste into your code. If you set the language to VB.NET then it will provide VB.NET-compliant declarations. They all use the Declare statement so they'd need a bit of massaging to convert to C# but at least you'll get the appropriate types for each argument and return value.

Crash893
Jun 5th, 2007, 11:42 PM
Okay i think i understand a few priciples from this


i understand the address ( in this case &hbfff&)
i understand that you register it and unregister it when you leave ( to be polite)

what im still having trouble with is

1) i do not understand the Me.hWnd yet

2) ret = RegisterHotKey(Me.hWnd, &HBFFF&, MOD_CONTROL, vbKeyF)
I dont understand why it the coder would assigne this to ret and then not use ret again

3) In the sub routine ProcessMessages is that just a loop that constantly checks to see if the hotkey has been pressed.? is that the triggering event?

jmcilhinney
Jun 6th, 2007, 12:04 AM
Why are you still trying to decipher VB6 code when I've told you more than once that there are VB.NET examples on the VB.NET forum?

Crash893
Jun 6th, 2007, 12:44 AM
linky?

otherwise im still looking for them

jmcilhinney
Jun 6th, 2007, 01:26 AM
I found them by searching the VB.NET forum for registerhotkey. If I found them that way then you can do the same.

Crash893
Jun 8th, 2007, 12:37 AM
http://www.vbforums.com/showthread.php?t=451415

Okay i have it down and working and i can modifiy it at will

now all i have to do is convert it over to c#


Public Class Form1
Public Declare Function RegisterHotKey Lib "user32" (ByVal hwnd As IntPtr, ByVal id As Integer, ByVal fsModifiers As Integer, ByVal vk As Integer) As Integer
Public Declare Function UnregisterHotKey Lib "user32" (ByVal hwnd As IntPtr, ByVal id As Integer) As Integer
Public Const WM_HOTKEY As Integer = &H312
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If m.Msg = WM_HOTKEY Then
' Pressed the hotkey!
MessageBox.Show("hot key works")
Debug.WriteLine(m.Msg.ToString & ":" & m.WParam.ToString & ":" & m.LParam.ToString)
End If
MyBase.WndProc(m) '<-- Never Ever Forget This!
End Sub
Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
Call UnregisterHotKey(Me.Handle, 9) '<-- Don't forget this
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Call RegisterHotKey(Me.Handle, 9, &H3, 65) '<-- Play with these settings
' Use these in the 3rd param ( add the numbers to combine modifyer keys ( ex alt shift = &h5)
'MOD_ALT = &H1
'MOD_CONTROL = &H2
'MOD_SHIFT = &H4
'MOD_WIN = &H8
End Sub
End Class

Crash893
Jun 8th, 2007, 01:01 AM
I am having a small problem with line 12
( i am not sure what the conversion is in VB i don't know what &h stands for) so i don't know what to look for in terms of conversion to c#
EDIT

I kinda of got this working ALT = 0x01 but it would seem that ALT CTRL does not = 0x03 I will keep expermenting

and on line 29. _done

It says that it cant accept M as a pramater but im not sure what exactly it wants and why M is diffrent than the M in VB

i know its probably M.something but im not sure what something ( i tired tostring but that did not work

EDIT for fix
REF m seems to work





[System.Runtime.InteropServices.DllImport("user32")]
public static extern int RegisterHotKey(IntPtr hwnd, int id, int fsModifiers, int vk);
[System.Runtime.InteropServices.DllImport("user32")]
public static extern int UnregisterHotKey(IntPtr hwnd, int id);

public const int WM_HOTKEY = 0x312; // c# for hex is 0x rather than &H



private void Form1_Load(object sender, EventArgs e)
{
RegisterHotKey(this.Handle, 9, &H1, 65);
//MOD_ALT = &H1
//MOD_CONTROL = &H2
//MOD_SHIFT = &H4
//MOD_WIN = &H8
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
UnregisterHotKey(this.Handle, 9); //<-- Don't forget this
}
protected override void WndProc(ref System.Windows.Forms.Message m)
{
if (m.Msg == WM_HOTKEY)
{
MessageBox.Show("hot key works");
System.Diagnostics.Debug.WriteLine(m.Msg.ToString() + ":" + m.WParam.ToString() + ":" + m.LParam.ToString());
}
base.WndProc(m);
}

jmcilhinney
Jun 8th, 2007, 01:31 AM
"&H" is the prefix for hexadecimal numbers in VB. The C# equivalent is "0x".

The WndProc method's 'm' argument is passed by reference. When you pass a parameter by reference in C# you must do so explicitly:base.WndProc(ref m);

Crash893
Jun 8th, 2007, 01:43 AM
i got the ref part ( see my edits)

Thanks for the hex thing i just got that and was comeing back to post my findings

my only small problem is that i think 0x03 should = Ctrl + alt but it doesnt seem to everything else works but im wondering if thats my system or if im messing it up


0x01 = alt
0x02 = Ctrl
0x03 = alt ctrl <--- not working Ideas?
0x04 = shift
0x05 = alt shift
0x06 = ctrl shift
0x07 = ctrl alt shift
0x08 = windows key

i think everyone will get the idea

Crash893
Jun 8th, 2007, 01:55 AM
Now if i wanted to do Multi hot keys

i understand i register another with a new id and new keys

but do i have to do something with

public const int WM_HOTKEY = 0x312; <------ this


Namely how do i know what my new hotkeys m value will be

jmcilhinney
Jun 8th, 2007, 02:11 AM
The message will always be WM_HOTKEY when a hot key is pressed. Read the documentation for the WM_HOTKEY message and it explains how to identify which hot key was pressed. Always read the documentation first, then ask questions later if you don't get what you need.

Crash893
Jun 8th, 2007, 02:22 AM
Why not do both and who ever answers first wins

If i am having these questions then some one else might search on them later.

so this post maybe helpfull to others.


Edit

So far it seems that all registered hotkeys trigger the event
I will search more on the ID portion to see how i can tell which was pushed

Crash893
Jun 8th, 2007, 02:40 AM
I didnt notice that line 10 was alot more usefull than i thought

if (m.Msg == WM_HOTKEY)
{

if((m.WParam.ToInt32() == 9))
{MessageBox.Show("ctrl+alt+h");}
if (m.WParam.ToInt32() == 8)
{ MessageBox.Show("ctrl+alt+v"); }
//RunAll();
//MessageBox.Show("hot key works");
System.Diagnostics.Debug.WriteLine(m.Msg.ToString() + ":" + m.WParam.ToString() + ":" + m.LParam.ToString());
}
base.WndProc(ref m);