4

Possible Duplicate:
How to detect the currently pressed key?

(EDIT: For what it's worth, this is not a duplicate... not sure why it was voted as such)

I have a small timer application that we use in the office to track the hours spent on a project. There is a start and stop button, and a project and task fields. When we go on break and to lunch and other things, we stop the timer for that project, then restart it. This is a repetitive task that generally involves digging the window out from behind several other Windows, then the same after the break.

What I want to do is assign WindowKey+W to the work timer application and have it not only bring the timer application to the front and focus it, but also have it toggle the Start/Stop.

I have tried a number of searches, but I can't seem to narrow down the examples to what I want. I do know that you can open the properties of a Windows shortcut and assign a shortcut key to launch a program, and (I guess?) if you have that app already open and it is set to allow only one instance of the program that it will bring that program to the front??? maybe..

Anyway.. but that method will not accept the WindowsKey as a valid key combo. And I don't know if it can somehow pass that key combo in to the program.

I appreciate any help or direction here!!

EDIT - Answer Update

Thank you @huadianz for your answer! I converted your code to VB:

Public Const MOD_WIN As Integer = &H8
Public Const KEY_W As Integer = &H57

<DllImport("user32.dll")> _
Public Shared Function RegisterHotKey(hWnd As IntPtr, id As Integer, fsModifiers As Integer, vlc As Integer) As Boolean
End Function

<DllImport("user32.dll")> _
Public Shared Function UnregisterHotKey(hWnd As IntPtr, id As Integer) As Boolean
End Function

Public Sub RegisterKeys()
    RegisterHotKey(Me.Handle, 1, MOD_WIN, KEY_W)
End Sub

Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
    MyBase.WndProc(m)

    If (m.Msg = &H312) Then
        Me.TopMost = True
        Me.PlayPauseTimer()
        Me.TopMost = False
    End If
End Sub

On an interesting note, Me.BringToFront() would not actually bring the application to the front in this scenario in Win7, nor did Me.Focus(). However, Me.TopMost = True worked, but it has the secondary effect of making the window always on top. Setting it to True, toggling the timer, then setting it back to False works great!

Community
  • 1
  • 1
jwatts1980
  • 7,254
  • 2
  • 28
  • 44
  • possible dup: http://stackoverflow.com/questions/1100285/how-to-detect-the-currently-pressed-key – Liam McInroy Aug 27 '12 at 23:14
  • Check the WINAPI. You can register hotkeys. – hakre Aug 28 '12 at 09:18
  • I did read that question before asking mine. The focus of the question was for when the application is currently active. The focus of the question was not quite what I am looking for, so I felt that another question was needed. – jwatts1980 Aug 28 '12 at 13:51

3 Answers3

4

If you want full operating system intergration, you can hook into the kernel input functions by using PInvoke.

What you are looking for is the explorer.exe Windows API function, described in detail here:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms646309%28v=vs.85%29.aspx

Using PInvoke, you can invoke this C++ function

[DllImport("user32.dll")]
private static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vlc);
[DllImport("user32.dll")]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);

public const int MOD_WIN = 0x00000008;
public const int KEY_W = 0x00000057

public static void RegisterKeys()
{
    RegisterHotKey((IntPtr)this.Handle, 1, MOD_WIN, KEY_W);
}

protected override void WndProc(ref Message m)
{
    base.WndProc(ref m);

    if (m.Msg == 0x0312)
        this.Visible = !this.Visible;
}
Cole Tobin
  • 9,206
  • 15
  • 49
  • 74
HenryZhang
  • 1,318
  • 8
  • 11
  • Out of curiosity so people don't get annoyed later on: What namespace is `Message` in? – Cole Tobin Aug 27 '12 at 23:55
  • @ColeJohnson `System.Windows.Forms.Message`. It is the standard callback present in `System.Windows.Forms` for interprocess communications. http://msdn.microsoft.com/en-us/library/system.windows.forms.control.wndproc.aspx – HenryZhang Aug 28 '12 at 00:43
  • Well then, what if I don't use WinForms, I use WPF? (Note: I am not asking for myself, but there are some n00bs here) – Cole Tobin Aug 28 '12 at 00:50
  • @ColeJohnson I stay away from WPF like it is the plague, since it takes control away from me. As such I would not know that answer. – HenryZhang Aug 28 '12 at 00:52
  • How does it take control away? All it doesn IMO is give you more features. Sure there is a bit more to learn if your on VB, but I don't use VB. – Cole Tobin Aug 28 '12 at 00:54
  • @ColeJohnson I'm a guy that creates my own controls on occasion because I don't like the way stock ones work and feel, and often PInvoke OS functions instead of using the BCL due to having underlying integration with the operating system/prevent the user from doing some stupid stuff. – HenryZhang Aug 28 '12 at 00:56
  • Oh that makes sense. Just a tip: invoking any kernel routines is slow. Try to stay away from them as much as possible. Except in this case, there is no other way. The reason being that WinForms and WPF abstract it so the underlying work is sometimes optimized because the people at M$ know how to make it faster. – Cole Tobin Aug 28 '12 at 00:59
  • Awesome! This did the trick :) I'm going to update the question with my VB code. Thank you so much! – jwatts1980 Aug 28 '12 at 14:31
2

I would also suggest looking at Auto Hotkey: http://www.autohotkey.com/. If all you're after is sending a window to front on key-press then you may find it faster to learn AHK and write a script to do so (be only 1 or 2 lines) than writing something in C# or VB.

*edit*As regards pressing a button automatically, if it's set as the default button then you can just send the enter keystroke to it. Otherwise you may need to send a mouse click even to the window. Neither is particularly difficult once you have the first part done.

#W::MsgBox "This is a message box. You just need to use something like send to send keystrokes and other commands to the window you want to control, instead of the this message box."

Sysyphus
  • 1,061
  • 5
  • 10
  • This is not what he asked for. – Cole Tobin Aug 27 '12 at 23:55
  • This may be a valid option if I cannot get it to work with the native application programming. I suspect with this route, it would require 2 keystrokes: 1 to bring up the application with AHK, and one to toggle the timer. – jwatts1980 Aug 28 '12 at 13:40
0

You can use Windows SendKeys. If you look at that link it shows the codes and syntax for applying a ctrl, alt or shift key. I imagine you can send these keys to your application to simulate a shortcut press.

Nashibukasan
  • 2,028
  • 23
  • 37