2

I'm trying to make a small application that executes specific functions when F keys are pressed (F1, F2 & F3 in the current context). I just recently started playing with hotkeys in C# but I can't seem to figure it out. I tried chaning System.Windows.Input.KeyEventArgs to System.Windows.Forms.KeyEventArgs but it does not work. I am not sure if this is the best/correct way to do it but yeah logically it makes sense to me. activeTracker acts like a trigger for my loop while other F keys send out text commands.

namespace WpfApplication1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        [DllImport("user32.dll", CharSet = CharSet.Unicode)]
        public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("user32.dll")]
        public static extern bool SetForegroundWindow(IntPtr hWnd);

        bool activeTracker = false;

        private void btnActive_Click(object sender, RoutedEventArgs e)
        {
            while (activeTracker)
            {
                IntPtr WindowHandle = FindWindow(txtClassName.Text, txtWindowTitle.Text);
                if (WindowHandle == IntPtr.Zero)
                {
                    System.Windows.MessageBox.Show(txtWindowTitle.Text + " does not exist");
                    return;
                }

                SetForegroundWindow(WindowHandle);

                SendKeys.SendWait(txtMessage1.Text + "{ENTER}");
                System.Threading.Thread.Sleep(TimeSpan.FromSeconds(1));
                SendKeys.SendWait(txtMessage2.Text + "{ENTER}");
            }
        }

        private void Window_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {
            if (e.KeyCode == "F1")
            {
                activateTracker = True;
                return;
            }else if(e.KeyCode == "F2")
            {
                activateTracker = False;
                return;
            }else if(e.KeyCode == "F3")
            {
                SendKeys.SendWait(txtMessage5.Text + "{ENTER}");
            }
        }
    }
}


<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" KeyDown="Window_KeyDown">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="108*"/>
            <ColumnDefinition Width="409*"/>
        </Grid.ColumnDefinitions>
        <TextBox x:Name="txtWindowTitle" HorizontalAlignment="Left" Height="23" Margin="176,10,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="233" Visibility="Hidden" Text="Value1" Grid.Column="1"/>
        <TextBlock HorizontalAlignment="Left" Margin="33,130,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Grid.Column="1"/>
        <TextBox x:Name="txtClassName" HorizontalAlignment="Left" Height="23" Margin="176,41,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="233" Visibility="Hidden" Text="Value2" Grid.Column="1"/>
        <Label Content="Message 1:" HorizontalAlignment="Left" Margin="10,37,0,0" VerticalAlignment="Top"/>
        <Label Content="Message 2:" HorizontalAlignment="Left" Margin="10,68,0,0" VerticalAlignment="Top"/>
        <TextBox x:Name="txtMessage1" HorizontalAlignment="Left" Height="23" Margin="96,40,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="370" Grid.ColumnSpan="2"/>
        <Label Content="Message 3:" HorizontalAlignment="Left" Margin="10,99,0,0" VerticalAlignment="Top"/>
        <TextBox x:Name="txtMessage2" HorizontalAlignment="Left" Height="23" Margin="96,72,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="370" Grid.ColumnSpan="2"/>
        <TextBox x:Name="txtMessage3" HorizontalAlignment="Left" Height="23" Margin="96,102,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="370" Grid.ColumnSpan="2"/>
        <Button x:Name="btnActive" Content="Activate" HorizontalAlignment="Left" Margin="56,237,0,0" VerticalAlignment="Top" Width="75" Click="btnActive_Click" Grid.ColumnSpan="2"/>
       <TextBox x:Name="txtMessage5" HorizontalAlignment="Left" Height="23" Margin="96,146,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="370" Grid.ColumnSpan="2"/>


    </Grid>
</Window>
ChrisF
  • 134,786
  • 31
  • 255
  • 325
HereToLearn
  • 292
  • 5
  • 16
  • Have you set a breakpoint in the `Window_KeyDown` event handler to make sure it's getting called? You don't show the XAML so I can only assume you are adding the `KeyDown` event there. – ChrisF Jan 23 '16 at 17:52
  • Added my XAML code to my post, not quite sure what you mean by set a breakpoint. – HereToLearn Jan 23 '16 at 17:59
  • Use the Visual Studio debugger - "F5". Press "F9" on the line where you want the code to stop so you can examine variables and check that they're the values you expect them to be. – ChrisF Jan 23 '16 at 18:01
  • maybe helpful for you http://stackoverflow.com/questions/11572411/sendkeys-send-method-in-wpf-application – kenny Jan 23 '16 at 19:30

2 Answers2

2

Use the Key property:

    private void Window_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
    {
        switch (e.Key)
        {
            case Key.F1:
                activeTracker= True;
                break;
            case Key.F2:
                activeTracker= False;
                break;
            case Key.F3:
                SendKeys.SendWait(txtMessage5.Text + "{ENTER}");
                break;
    }

I'm not sure how you're managing to compare the KeyCode property with a string as a) that's WinForms and b) it returns Keys value anyway.

Your KeyDown handler wouldn't compile because you had the wrong variable name activateTracker instead of activeTracker.

Change that and make sure you explicitly reference the System.Windows.Input version of KeyEventArgs and you should be good to go.

ChrisF
  • 134,786
  • 31
  • 255
  • 325
  • When I use the following switch statement activateTracker does not exist in the current context for some reason. Even though it is a global variable. – HereToLearn Jan 23 '16 at 18:21
  • 1
    @HereToLearn as long as you've just replaced your existing KeyDown event handler with this code then I can't see why it shouldn't compile. – ChrisF Jan 23 '16 at 18:23
  • Yes, however when I used the following code KeyEventArgs asked me to change it to either System.Windows.Input.KeyEventArgs or System.Windows.Forms.KeyEventArgs. When using Input the actionTracker variable cannot be found and when using Forms the 'Key' does not contain a definition. What am I missing here? – HereToLearn Jan 23 '16 at 18:34
  • @HereToLearn That doesn't sound right. If your handler is in your `MainWindow` class it should compile. – ChrisF Jan 23 '16 at 18:50
  • 'KeyEventArgs' is an ambiguous reference between 'System.Windows.Input.KeyEventArgs' and 'System.Windows.Forms.KeyEventArgs' Is the error I am receiving. Looks like a library reference issue. – HereToLearn Jan 23 '16 at 19:00
  • By doing so it create a problem with SendKeys and activeTracker variable. – HereToLearn Jan 23 '16 at 19:05
  • @HereToLearn - OK - I can understand that for `SendKeys` but not for a boolean variable. Sorry, I'm all out of ideas. – ChrisF Jan 23 '16 at 19:09
  • To try resolve the ambiguous reference issue you can try `using Input = System.Windows.Input;` and the in your code put `Input.KeyEventArgs` where necessary? – Balah Jan 23 '16 at 20:40
0

You don't need to set up them. You can use FrameworkElement.KeyDown event handler.

In case your application has only one window, you can directly add them to code.

private void Window_KeyDown(object sender, KeyEventArgs e)
   {
   switch(e.Key)
   {
   // Add cases for F buttons.
   }
}

But if your app uses windows more than one, you can use that:

public static class KeyF
{
    public static void RunF(KeyEventArgs e)
    {
        switch(e.Key)
        {
           // Add cases for F keys.
          // And do stuff.
        }
    }
}

Then just run it with KeyF.RunF(e);

Burak Yeniçeri
  • 91
  • 2
  • 15