none
C#, user32.dll, globale Hotkeys RRS feed

  • Frage

  • Als C# Anfänger habe ich mit der Hilfe von Lektüre und dem Internet ein Programm geschrieben, dass die Tastenanschläge des Benutzer in einem Fenster anzeigt. Nun habe ich allerdings 3 Dinge bei denen ich einfach nicht dahinter komme.

    • Das Schwerwiegendste Problem, ist das er zwar die ausgewählten Tasten erkennt, allerdings diese auch dem System stiehlt. Wenn man schnell genug hintereinander (zb W) drückt, dann bekommt auch das Windows 7 ein paar Tasteninfos ab.
    • Gibt es einen Weg, ohne alles X-mal hineinschreiben zu müssen, dass man auch Anschläge von 2, 3,.. Tasten gleichzeitig erkennt und anzeigt?
    • Ich schaffe es einfach nicht, dass das Fenster nicht in den Fokus gerät. Es soll so sein, dass im Hintergrund ein Spiel läuft und das Programm im Vordergrund läuft. Leider "verläuft" sich die Maus ständig und das Fenster bekommt den Focus. Wie schaffe ich es, dass das Fenster nicht mehr wählbar ist? Bzw. dass es nur durch eine Funktionstaste wieder wählbar ist?

    Das Programm ist eine Windows Form Application.

    (Als Inspiration zu den Globalen Hotkeys, hat mir dieses Tutorial geholfen: http://social.technet.microsoft.com/wiki/contents/articles/30568.wpf-implementing-global-hot-keys.aspx)

    Genug der Worte, hier der Code:

    using System;
    using System.Drawing;
    using System.Windows.Forms;
    using System.Windows;
    using System.Runtime.InteropServices;
    
    namespace WASD
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
    
                //Set time for showing messages in label
                timer1.Interval = 400;
            }
    
            //// The window should not be in focus but didn't work
            //protected override void DefWndProc(ref Message m)
            //{
            //    const int WM_MOUSEACTIVATE = 0x21;
            //    const int MA_NOACTIVATE = 0x0003;
    
            //    switch (m.Msg)
            //    {
            //        case WM_MOUSEACTIVATE:
            //            m.Result = (IntPtr)MA_NOACTIVATE;
            //            return;
            //    }
            //    base.DefWndProc(ref m);
            //}
    
            //Invoke global hotkey (unmanaged code)
            [DllImport("user32.dll")]
            public static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vlc);
            [DllImport("user32.dll")]
            public static extern bool UnregisterHotKey(IntPtr hWnd, int id);
    
            //Modifiers
            private const int MOD_NONE = 0x0000;
            private const int MOD_SHIFT = 0x0004;
            private const int MOD_CONTROL = 0x0002;
    
            //Intercept input hotkey
            private const int WM_HOTKEY = 0x0312;
    
            //Creating the Rectangle
            private PictureBox pictureBox1 = new PictureBox();
            private bool wPressed = false;
            private bool aPressed = false;
            private bool sPressed = false;
            private bool dPressed = false;
            private bool qPressed = false;
            private bool ePressed = false;
    
            private void Form1_Load(object sender, EventArgs e)
            {
                //Register global hotkeys. DON'T forget to unregister OnClosing
                // w
                RegisterHotKey(this.Handle, 1, MOD_NONE, (int)Keys.W);
                // a
                RegisterHotKey(this.Handle, 2, MOD_NONE, (int)Keys.A);
                // s
                RegisterHotKey(this.Handle, 3, MOD_NONE, (int)Keys.S);
                // d
                RegisterHotKey(this.Handle, 4, MOD_NONE, (int)Keys.D);
                // q
                RegisterHotKey(this.Handle, 5, MOD_NONE, (int)Keys.Q);
                // e
                RegisterHotKey(this.Handle, 6, MOD_NONE, (int)Keys.E);
    
                // W
                RegisterHotKey(this.Handle, 7, MOD_SHIFT, (int)Keys.W);
                // A
                RegisterHotKey(this.Handle, 8, MOD_SHIFT, (int)Keys.A);
                // S
                RegisterHotKey(this.Handle, 9, MOD_SHIFT, (int)Keys.S);
                // D
                RegisterHotKey(this.Handle, 10, MOD_SHIFT, (int)Keys.D);
                // Q
                RegisterHotKey(this.Handle, 11, MOD_SHIFT, (int)Keys.Q);
                // E
                RegisterHotKey(this.Handle, 12, MOD_SHIFT, (int)Keys.E);
    
                // F7
                RegisterHotKey(this.Handle, 13, MOD_NONE, (int)Keys.F7);
                // F8
                RegisterHotKey(this.Handle, 14, MOD_NONE, (int)Keys.F8);
                // F9
                RegisterHotKey(this.Handle, 15, MOD_NONE, (int)Keys.F9);
                // F10
                RegisterHotKey(this.Handle, 16, MOD_NONE, (int)Keys.F10);
    
    
                //Dock the PictureBox to the form
                pictureBox1.Dock = DockStyle.Fill;
                //Set background color
                pictureBox1.BackColor = Color.White;
                pictureBox1.Paint += DrawRectangle;
                //Add the PictureBox control to the form
                this.Controls.Add(pictureBox1);
            }
    
            protected override void WndProc(ref Message m)
            {
                wPressed = false;
                aPressed = false;
                sPressed = false;
                dPressed = false;
                qPressed = false;
                ePressed = false;
    
                if (m.Msg == WM_HOTKEY)
                {
                    switch ((int)m.WParam)
                    {
                        // If pressed w or W
                        case 1:
                        case 7:
                            wPressed = true;
                            break;
                        // If pressed a or A
                        case 2:
                        case 8:
                            aPressed = true;
                            break;
                        // If pressed s or S
                        case 3:
                        case 9:
                            sPressed = true;
                            break;
                        // If pressed d or D
                        case 4:
                        case 10:
                            dPressed = true;
                            break;
                        // If pressed q or Q
                        case 5:
                        case 11:
                            qPressed = true;
                            break;
                        // If pressed e or E
                        case 6:
                        case 12:
                            ePressed = true;
                            break;
    
                        // If pressed F7
                        case 13:
                            MessageBox.Show(@"Info:
            F7     -   Show this help
            F8     -   Hide or show title
            F9     -   Dock window to top
            F10   -   Prevent window beeing in focus
    
            Version: 0.2.0");
                            break;
                        // If pressed F8
                        case 14:
                            HideOrShowTitle();
                            break;
                        // IF pressed F9
                        case 15:
                            DockOrUndockWindowOnTop();
                            break;
                        // IF pressed F10 then never let the window get focus
                        case 16:
                            break;
    
                        // When pressed other keys - TODO not working
                        default:
                            lblMessage.Text = "asdasd";
                            timer1.Enabled = true;
                            timer1.Start();
                            break;
                    }
                }
    
                pictureBox1.Refresh();
    
                base.WndProc(ref m);
            }
    
            private void HideOrShowTitle()
            {
                if (this.FormBorderStyle == FormBorderStyle.None)
                    this.FormBorderStyle = FormBorderStyle.Sizable;
                else
                    this.FormBorderStyle = FormBorderStyle.None;
            }
    
            private void DockOrUndockWindowOnTop()
            {
                switch (this.TopMost)
                {
                    case false:
                        this.TopMost = true;
                        lblMessage.Text = "Docked!";
                        timer1.Enabled = true;
                        timer1.Start();
                        break;
                    case true:
                        this.TopMost = false;
                        lblMessage.Text = "Undocked!";
                        timer1.Enabled = true;
                        timer1.Start();
                        break;
                }
            }
    
            private void PreventWindowBeeingInFocus()
            {
    
            }
            
    
            public void DrawRectangle(object sender, PaintEventArgs e)
            {
                DefineRectangle(e, new Point(40, 10), new Size(20, 20), 'W', wPressed ? Color.Crimson : Color.White);
                DefineRectangle(e, new Point(10, 40), new Size(20, 20), 'A', aPressed ? Color.Crimson : Color.White);
                DefineRectangle(e, new Point(40, 40), new Size(20, 20), 'S', sPressed ? Color.Crimson : Color.White);
                DefineRectangle(e, new Point(70, 40), new Size(20, 20), 'D', dPressed ? Color.Crimson : Color.White);
                DefineRectangle(e, new Point(10, 10), new Size(20, 20), 'Q', qPressed ? Color.Crimson : Color.White);
                DefineRectangle(e, new Point(70, 10), new Size(20, 20), 'E', ePressed ? Color.Crimson : Color.White);
            }
    
            private void DefineRectangle(PaintEventArgs e, Point p, Size s, char letter, Color c)
            {
                //Create Pen
                var blackPen = new Pen(Color.Black, 3);
                var brush = new SolidBrush(c);
                //Create Rectangle
                var rect = new Rectangle(p, s);
    
                //Drawing
                e.Graphics.DrawRectangle(blackPen, rect);
                e.Graphics.FillRectangle(brush, rect);
                e.Graphics.DrawString(letter.ToString(), new Font(FontFamily.GenericSerif, 12), Brushes.Black, rect);
            }
    
            private void timer1_Tick(object sender, EventArgs e)
            {
                lblMessage.Text = "";
                timer1.Enabled = false;
                timer1.Stop();
            }
    
            private void Form1_FormClosed(object sender, FormClosedEventArgs e)
            {
                UnregisterHotKey(this.Handle, 1);
                UnregisterHotKey(this.Handle, 2);
                UnregisterHotKey(this.Handle, 3);
                UnregisterHotKey(this.Handle, 4);
                UnregisterHotKey(this.Handle, 5);
                UnregisterHotKey(this.Handle, 6);
                UnregisterHotKey(this.Handle, 7);
                UnregisterHotKey(this.Handle, 8);
                UnregisterHotKey(this.Handle, 9);
                UnregisterHotKey(this.Handle, 10);
                UnregisterHotKey(this.Handle, 11);
                UnregisterHotKey(this.Handle, 12);
                UnregisterHotKey(this.Handle, 13);
                UnregisterHotKey(this.Handle, 14);
                UnregisterHotKey(this.Handle, 15);
                UnregisterHotKey(this.Handle, 16);
            }
        }
    }

    Und hier ein Bild, wie das Programm letztlich dann aussieht:

    Wie gesagt nichts großartiges, allerdings hätte ich irgendwie noch die letzten nicht funktionierenden Punkte "verstanden" bzw. behoben.



    • Bearbeitet dr34mup Mittwoch, 10. Februar 2016 17:58
    Mittwoch, 10. Februar 2016 17:55

Antworten

Alle Antworten