none
Tastendruck abfragen RRS feed

  • Frage

  • Hi Leute ...

    WIe kann ich es machen das Tasten die man drückt in zb. einem string gespeichert werden ? 

    Also ich will nicht sowas machen wie :

    If (Keyis down(UP))

    bild.X += 5;

     

    Also das soll nicht für so ein SPiel werden ... sondern einfach abfragen welche tasten gedrückt werden und die dann speichern ... also in nem string oder so ... den rest kann ich dann selber machen 

    Samstag, 2. April 2011 10:43

Antworten

  • Hallo B.,

    • > Wie zitiert man [...]

    super. Es kann zum Beispiel auch reichen, ohne direktes Zitat nur einen kleinen Teil herauszunehmen und den Aspekt dazu zu beantworten. Hauptsache letztlich, dass derjenige weiss, auf was Du Dich beziehst.

    Eigentlich müssten wir die anderen Dinge, wie Forenbeiträge bewerten/abschliessen, aber wir können ja nicht alles zu einem Zeitpunkt, deswegen werden ich mich noch mal der Beantwortung Deiner Frage widmen - ich hoffe jedenfalls, dass Du da auch noch etwas nachschaust.

     

    • > Du fragtest bzgl. Hooks: "Aber wo wird denn gespeichert wass man drückt ? Also ich hab dafür eine neue Klasse angelegt"

    na in Deinem Beispiel in KeyCodes.
    Eventuell hast Du vergessen:  new KeyHook(); in Deiner Start-Form auszuführen.

        KeyHook hook = new KeyHook();
    
        public Form1()
        {
          InitializeComponent();
          Button btnAnzeige = new Button();
          btnAnzeige.Text = "Tasten";
          btnAnzeige.Click += BtnAnzeige_Click;
          Controls.Add(btnAnzeige);
        }
    
        void BtnAnzeige_Click(object sender, EventArgs e)
        {
          string info = "Gedrückte Tasten:\r\n";
          string zusatz = string.Join("\r\n", KeyHook.KeyCodes.Select(k => k.ToString()));
          MessageBox.Show(info + zusatz);
        }
    



     

    • ... 256) || ((int)wParam == 260))

    nimm hier Konstanten(Namen), wie in meinem Beispiel. Das sind CleanCode (hier Lesbarkeits) Prinzipien. Ein Außenstehender kann Dir nicht auf den ersten Blick sagen, was wohl 260 ist. Außerdem, hast Du 260 noch woanders stehen, so wäre ein Refactoring fehleranfällig. Mit Konstanten nicht.

     

    • warum ich das nicht empfehlenswert finde ...

    Nur ein paar Dinge: globale Hooks können zum Teil bei unsachgemäßer Beendigung des Prozesses im System verbleiben, weil sie nicht mehr freigegeben werden - und auch andere Apps negativ beeinflussen. Applikations-weites Mithören ist aus Sichherheits-Gründen oft problematisch. Man muss weiterhin immer die Applikation zuordnen. Siehe ggf. auch:
    Zitat: http://www.codeproject.com/KB/system/globalsystemhook.aspx

    • Let me paraphrase Dr. Seuss in the famous children's book Fox in Sox in providing this final warning:
    • Take it slowly. These classes are dangerous.    Deutsch: "Diese Klassen sind gefährlich"
      System hooks are powerful. And, with that power comes responsibility. When something goes wrong with system hooks, they don't just break your application. They can break every application running on your system. It is unlikely that it would actually come to that extreme. Nonetheless, you need to double and triple check your code when using system hooks.

    Wenn also mein Vorschlag mit dem MessageFilter eben funktioniert, würde man normal nicht solche Brecher wie globale Hooks benutzen.


    ciao Frank
    • Als Antwort markiert Basti1 Sonntag, 3. April 2011 07:20
    Samstag, 2. April 2011 19:27

Alle Antworten

  • Hallo Bastian,

    mach es zum Beispiel so:

      public Form1()
      {
       KeyPreview = true;
       KeyDown += Form1_KeyDown;
       InitializeComponent();
      }
    
      List<KeyEventArgs> tasten = new List<KeyEventArgs>();
    
      void Form1_KeyDown(object sender, KeyEventArgs e)
      {
       tasten.Add(e);   
      }
    


    Klassen-Daten über Strings zu halten wäre normal unvorteilhaft und fehleranfällig.

    Dennoch, wenn man es wirklich über Strings machen wollte, zum Beispiel so:

      StringBuilder tasten = new StringBuilder();
    
      void Form1_KeyDown(object sender, KeyEventArgs e)
      {
       tasten.AppendLine(e.KeyCode.ToString());
       // string gesamtTasten = tasten.ToString();
      }
    

     


    ciao Frank
    Samstag, 2. April 2011 11:30
  • dein erstes beipsiel da ... wie kann ich die gedrückten tasten dann abrufen wenn ich sie zb.  in einer textbox anzeigen will ?
    Samstag, 2. April 2011 11:42
  • Hallo Bastian,

    • erstes Beispiel .... Tasten anzeigen ...

    hier ein Beispiel:

    using System.Collections.Generic;
    using System.Linq;
    using System.Windows.Forms;
    
    namespace WinTastenSpeichern
    {
     public partial class Form1 : Form
     {
      TextBox txtInfo = new TextBox();
    
      public Form1()
      {
       KeyPreview = true;
       KeyDown += Form1_KeyDown;
       InitializeComponent();
       txtInfo.Multiline = true;
       txtInfo.Height = 100; txtInfo.Width = 200;
       txtInfo.TabStop = false; txtInfo.ReadOnly = true;
       txtInfo.ScrollBars = ScrollBars.Both;
       Controls.Add(txtInfo);
    
       TextBox txt2 = new TextBox();
       txt2.Top = txtInfo.Height + 20;
       Controls.Add(txt2);
      }
    
      List<KeyEventArgs> tasten = new List<KeyEventArgs>();
    
      void Form1_KeyDown(object sender, KeyEventArgs e)
      {
       tasten.Add(e);
       AnzeigeDerTasten();
      }
    
      private void AnzeigeDerTasten()
      {
       string info = "Gedrückte Tasten:\r\n";
       string zusatz = string.Join("\r\n", tasten.Select(t => t.KeyCode.ToString()));
       txtInfo.Text = info + zusatz;
       txtInfo.SelectionStart = txtInfo.Text.Length;
       txtInfo.ScrollToCaret();
      }
     }
    }
    
    Samstag, 2. April 2011 12:05
  • Der Name "InitializeComponent" ist im aktuellen Kontext nicht vorhanden.
    huaaa ? wie kommt das denn ?
    EDIT:oha jetzt sind da auf einmal um die 80 fehler ...
    EDIT2: jetzt funtzts'
    Jetzt probier ich noch ein bisschen herum :D 
    THX
    Samstag, 2. April 2011 12:36
  • Hallo Bastian,

    Du musst den Namespace entsprechend ändern. Bei mir heisst er 'WinTastenSpeichern'. Das muss an Deinen unter Projekt/Eigenschaften/Standardnamespace geändert/angepasst werden.

     


    ciao Frank
    Samstag, 2. April 2011 12:43
  • hmm naja ... Also funzt supi aber kann man es auch machen das das die Buchstaben in die Liste geschrieben werden wenn das fenster garnicht aktiv gerade ist ? oder ist sowas unmöglich ? Also die TextBox ist dnn auch nicht nötig ...
    Samstag, 2. April 2011 12:44
  • B.,

    • funzt supi ...

    wenn es funktioniert, warum ist es dann nicht hilfreich?
    Warum schliesst Du Deine Fragen manchmal nicht ab?

    Form-Fokus-Unabhängigkeit zum Beispiel über:

    using System;
    using System.Collections.Generic;
    using System.Security.Permissions;
    using System.Windows.Forms;
    
    namespace WinTastenSpeichern
    {
     static class Program
     {
      [STAThread]
      static void Main()
      {
       Application.EnableVisualStyles();
       Application.SetCompatibleTextRenderingDefault(false);
       TastenFilter = new TastenMessageFilter();
       Application.AddMessageFilter(TastenFilter);
       Application.Run(new Form1());
      }
    
      static public event KeyEventHandler TasteGedrückt;
      
      static public TastenMessageFilter TastenFilter {get;set;}
     
      [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
      public class TastenMessageFilter : IMessageFilter
      {
       public TastenMessageFilter()
       {
        Tasten = new List<Keys>();
       }
    
       public List<Keys> Tasten { get; set; }
       
       public bool PreFilterMessage(ref Message m)
       {
        const int WM_KEYDOWN = 0x100;
        const int WM_SYSKEYDOWN = 0x104;
    
        if ((m.Msg == WM_KEYDOWN) || (m.Msg == WM_SYSKEYDOWN))
        {
         Keys k = (Keys)m.WParam.ToInt32();
         Tasten.Add(k);
         TasteGedrückt(null, new KeyEventArgs(k));
        }
        return false;
       }
      }
    
     }
    }
    
    

    ---------------------------------------

    using System.Collections.Generic;
    using System.Linq;
    using System.Windows.Forms;
    
    namespace WinTastenSpeichern
    {
     public partial class Form1 : Form
     {
      TextBox txtInfo = new TextBox();
    
      public Form1()
      {
       Form2 f2 = new Form2(); f2.Show();
       InitializeComponent();
       txtInfo.Multiline = true;
       txtInfo.Height = 100; txtInfo.Width = 200;
       txtInfo.TabStop = false; txtInfo.ReadOnly = true;
       txtInfo.ScrollBars = ScrollBars.Both;
       Controls.Add(txtInfo);
       Program.TasteGedrückt += new KeyEventHandler(Program_TasteGedrückt);
      }
    
      void Program_TasteGedrückt(object sender, KeyEventArgs e)
      {
       AnzeigeDerTasten();
      }
    
      private void AnzeigeDerTasten()
      {
       string info = "Gedrückte Tasten:\r\n";
       string zusatz = string.Join("\r\n",
        Program.TastenFilter.Tasten.Select(k => k.ToString()));
       txtInfo.Text = info + zusatz;
       txtInfo.SelectionStart = txtInfo.Text.Length;
       txtInfo.ScrollToCaret();
      }
     }
    }
    
    

    Komplette Applikations-Fokus-Unabhängigkeit (also auch bei Fokus anderer Applikationen) über globale Tastatur-Hooks (würde ich mal erstmal lieber nicht machen).

     


    ciao Frank
    Samstag, 2. April 2011 13:26
  • wiso ?  Und also ich hab das jetzt getestet mit diesem code :

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    
    namespace WindowsFormsApplication1
    {
      public class KeyHook
      {
        private delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);
    
        //Declare hook handle as int.
        static int hHook = 0;
    
        public static List<Keys> KeyCodes = new List<Keys>();
    
        //Declare keyboard hook constant.
        //For other hook types, you can obtain these values from Winuser.h in Microsoft SDK.
        const int WH_KEYBOARD_LL = 13;
    
        HookProc KeyboardHookProcedure;
    
        [StructLayout(LayoutKind.Sequential)]
        private class keyboardHookStruct
        {
          public int vkCode;
          public int scanCode;
          public int flags;
          public int time;
          public int dwExtraInfo;
        }
    
        //Import for SetWindowsHookEx function.
        //Use this function to install thread-specific hook.
        [DllImport("user32.dll", CharSet = CharSet.Auto,
         CallingConvention = CallingConvention.StdCall)]
        private static extern int SetWindowsHookEx(int idHook, HookProc lpfn,
        IntPtr hInstance, int threadId);
    
        //Import for UnhookWindowsHookEx.
        //Call this function to uninstall the hook.
        [DllImport("user32.dll", CharSet = CharSet.Auto,
         CallingConvention = CallingConvention.StdCall)]
        private static extern bool UnhookWindowsHookEx(int idHook);
    
        //Import for CallNextHookEx.
        //Use this function to pass the hook information to next hook procedure in chain.
        [DllImport("user32.dll", CharSet = CharSet.Auto,
         CallingConvention = CallingConvention.StdCall)]
        private static extern int CallNextHookEx(int idHook, int nCode,
        IntPtr wParam, IntPtr lParam);
    
        [DllImport("kernel32.dll")]
        static extern IntPtr LoadLibrary(string lpFileName);
    
        public KeyHook()
        {
          Hook();
        }
    
        ~KeyHook()
        {
          UnHook();
        }
    
        public int Hook()
        {
          KeyboardHookProcedure = new HookProc(KeyHook.KeyboardHookProc);
    
          hHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProcedure, (IntPtr)LoadLibrary("User32"), 0);
          return hHook;
        }
    
        public bool UnHook()
        {
          bool ret = UnhookWindowsHookEx(hHook);
          if (ret)
            hHook = 0;
          return ret;
        }
    
        private static int KeyboardHookProc(int nCode, IntPtr wParam, IntPtr lParam)
        {
          if (nCode < 0)
          {
            return CallNextHookEx(hHook, nCode, wParam, lParam);
          }
          else
          {
    
            if (((int)wParam == 256) || ((int)wParam == 260))
            {
              keyboardHookStruct MyKeyboardHookStruct = (keyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(keyboardHookStruct));
              KeyCodes.Add((Keys)MyKeyboardHookStruct.vkCode);
            }
            return 1;
          }
        }
    
      }
    }
    
    Aber wo wird denn gespeichert wass man drückt ? Also ich hab dafür eine neue Klasse angelegt ^^

    Samstag, 2. April 2011 14:41
  • B.,

    - Du gehst nicht auf Fragen ein, stellst immer wieder neue.
      Hier beantworten wir normal jeweils eine Frage.
    - Du bewertest Postings nicht immer.
    - Du zitierst die Phrasen nicht, zu denen Du etwas sagen möchtest, so dass dies unverständlich ist.

    Die Frage ist lange beantwortet und ich werde da auch nicht mehr viel dazu schreiben und mir ggf. auch zukünftig überlegen, inwieweit ich bei Dir antworte.
    Globale Hooks kannst Du machen, ich empfehle das nicht.


    ciao Frank
    Samstag, 2. April 2011 15:28
  • joa is jetzt auch beantwortet ... Aber soll ich jetzt einen neune Thread aufmachen um zu fargen warum Globale hooks nicht zu empfehlen sind ?

    EDIT: okeist eigentlich nicht beantwortet so richtig ganz abr naja 

    Samstag, 2. April 2011 16:26
  • Hallo B.,

    pass mal auf, wir lernen das jetzt mal:

    Zitieren und auf Aspekte des Antwortenden eingehen:
    http://social.msdn.microsoft.com/Forums/de-DE/help#271

    Du bist nicht besonders auf mein vorangegangenes Posting eingegangen.
    Kürze am besten Teile aus dem vorangegangenen Postings auf jeweils eine Teil-Essenz quote (zitiere die) und antworte darauf. Es könnte also zum Beispiel so aussehen:

    • Globale Hooks kannst Du machen, ich empfehle das nicht.

    kannst Du mir sagen, warum Du das nicht empfehlst?

    ____________________________

    Bei Dir stehen die Wörter manchmal im Raum und man versteht deswegen nicht, wie/wozu sie gemeint sind.

    Auch ich habe jetzt neuerliche Fragen von Dir nicht beantwortet, vielleicht merkst Du, wie das auf andere wirkt, wenn Du ihre Fragen oder Aspekte nicht in Deinen Postings berücksichtigst.

    Nimm Dir Zeit um Deine Fragen/Aussagen gut zu durchdenken und Aspekte von Antwortenden sinnvoll zu berücksichtigen. Zeit heisst zum Teil auch, dass man etwas sehr deutlich und unverkennbar z.T. mit mehreren Worten und möglichst reproduzierbar beschreibt.

    Und jetzt versuche bitte einmal zu zitieren !!!  (dann hätten wir Step1 geschafft und viele andere Beantworter werden Dir später sicher dankbar sein)

     


    ciao Frank
    Samstag, 2. April 2011 17:57
  • Und jetzt versuche bitte einmal zu zitieren !!!  (dann hätten wir Step1 geschafft und viele andere Beantworter werden Dir später sicher dankbar sein)
    Wie zitiert man ? :D 
    Samstag, 2. April 2011 18:15
  • Hallo B.,

    • > Wie zitiert man [...]

    super. Es kann zum Beispiel auch reichen, ohne direktes Zitat nur einen kleinen Teil herauszunehmen und den Aspekt dazu zu beantworten. Hauptsache letztlich, dass derjenige weiss, auf was Du Dich beziehst.

    Eigentlich müssten wir die anderen Dinge, wie Forenbeiträge bewerten/abschliessen, aber wir können ja nicht alles zu einem Zeitpunkt, deswegen werden ich mich noch mal der Beantwortung Deiner Frage widmen - ich hoffe jedenfalls, dass Du da auch noch etwas nachschaust.

     

    • > Du fragtest bzgl. Hooks: "Aber wo wird denn gespeichert wass man drückt ? Also ich hab dafür eine neue Klasse angelegt"

    na in Deinem Beispiel in KeyCodes.
    Eventuell hast Du vergessen:  new KeyHook(); in Deiner Start-Form auszuführen.

        KeyHook hook = new KeyHook();
    
        public Form1()
        {
          InitializeComponent();
          Button btnAnzeige = new Button();
          btnAnzeige.Text = "Tasten";
          btnAnzeige.Click += BtnAnzeige_Click;
          Controls.Add(btnAnzeige);
        }
    
        void BtnAnzeige_Click(object sender, EventArgs e)
        {
          string info = "Gedrückte Tasten:\r\n";
          string zusatz = string.Join("\r\n", KeyHook.KeyCodes.Select(k => k.ToString()));
          MessageBox.Show(info + zusatz);
        }
    



     

    • ... 256) || ((int)wParam == 260))

    nimm hier Konstanten(Namen), wie in meinem Beispiel. Das sind CleanCode (hier Lesbarkeits) Prinzipien. Ein Außenstehender kann Dir nicht auf den ersten Blick sagen, was wohl 260 ist. Außerdem, hast Du 260 noch woanders stehen, so wäre ein Refactoring fehleranfällig. Mit Konstanten nicht.

     

    • warum ich das nicht empfehlenswert finde ...

    Nur ein paar Dinge: globale Hooks können zum Teil bei unsachgemäßer Beendigung des Prozesses im System verbleiben, weil sie nicht mehr freigegeben werden - und auch andere Apps negativ beeinflussen. Applikations-weites Mithören ist aus Sichherheits-Gründen oft problematisch. Man muss weiterhin immer die Applikation zuordnen. Siehe ggf. auch:
    Zitat: http://www.codeproject.com/KB/system/globalsystemhook.aspx

    • Let me paraphrase Dr. Seuss in the famous children's book Fox in Sox in providing this final warning:
    • Take it slowly. These classes are dangerous.    Deutsch: "Diese Klassen sind gefährlich"
      System hooks are powerful. And, with that power comes responsibility. When something goes wrong with system hooks, they don't just break your application. They can break every application running on your system. It is unlikely that it would actually come to that extreme. Nonetheless, you need to double and triple check your code when using system hooks.

    Wenn also mein Vorschlag mit dem MessageFilter eben funktioniert, würde man normal nicht solche Brecher wie globale Hooks benutzen.


    ciao Frank
    • Als Antwort markiert Basti1 Sonntag, 3. April 2011 07:20
    Samstag, 2. April 2011 19:27