(C#) Wie Button einen numpad(0-9) Hotkey zuweisen?

2 Antworten

Vom Fragesteller als hilfreich ausgezeichnet

Nutze on key press und dann button.click(). Da natürlich eine if Abfrage einbauen, die den Key checked

regex9  18.08.2022, 08:05

Das wäre keine gute Methodik. Die Logik sollte stattdessen in einer Hilfsmethode definiert werden, die in den jeweiligen Event Handlern aufgerufen werden kann.

0
FaTech  18.08.2022, 08:07
@regex9

Richtig. Ich habe es nur so verstanden, dass er die Buttons direkt ansprechen will. Gut, man kann da argumentieren, dass er es nicht besser weiß ... Ich gebe dir da vollkommen Recht

0
Nutzer4596 
Fragesteller
 18.08.2022, 08:11

Ich habe noch nie vorher etwas gecoded bis auf in cmd batch falls das zählt und bin ein absoluter Anfänger haha
Wärst du so nett und könntest mir das als code schreiben den in dann einfügen kann?

0
FaTech  18.08.2022, 08:12
@Nutzer4596

Nein, weil ich am Handy bin. Dort geht das nicht so gut. Womit arbeitest du überhaupt? WinForms?

0
Nutzer4596 
Fragesteller
 18.08.2022, 08:13
@FaTech

Windows Forms App mit .NET 6.0 in Visual Studio

0
FaTech  18.08.2022, 08:15
@Nutzer4596

Im Windows forms designer, bei den Eigenschaften, dort ist ein Blitz. Klick den an. Da findest du alle Events zum ausgewählten element. Wähle die Form für die Form Events. Dann suche da das von mir genannte event

0
Nutzer4596 
Fragesteller
 18.08.2022, 08:21
@FaTech

Habe KeyPress gefunden, Drauf geklickt und dann hat es eine Referenz in meiner from erstellt. Aber wie geht es jetzt weiter? Außerdem benötige ich ja noch den namen des Keys, also in meinem fall eines von denen auf dem numpad

        private void materialSwitch1_KeyPress(object sender, KeyPressEventArgs e)
        {


        }
    }
0
FaTech  18.08.2022, 08:23
@Nutzer4596

KeyPressEventArgs nehme e und Frage den Key ab. if (e. Und dann zeigt visual Studio Vorschläge

0
Nutzer4596 
Fragesteller
 18.08.2022, 08:33
@FaTech

Aber was soll ich dann nehmen? Wie geht es dann weiter?

e.GetHashCode
e.Equals
e.GetType
e.Handled
e.KeyChar
e.ToString

0
Nutzer4596 
Fragesteller
 18.08.2022, 08:39
@FaTech

also
if (e.KeyChar == );
aber was soll ich dann angeben? Es werden einfach nur ein Haufen an Sachen vorgeschlagen.

0
FaTech  18.08.2022, 08:40
@Nutzer4596

KeyPress bietet nicht den passenden sehe ich gerade. Du kannst einen char angeben, der fragt aber nicht ab, ob es vom Nummernfeld kommt. Alternativ, habe ich gerade geschaut, kannst du das KeyUp Event benutzen: (KeyDown geht auch, würde aber Up empfehlen)

private void Form1_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e)
        {
            if (e.KeyCode.Equals(Keys.NumPad0))
            {
                // Action
            }
        }
0
Nutzer4596 
Fragesteller
 18.08.2022, 08:57
@FaTech

Ich habe testweise als Aktion eine messagebox hinzugefügt, allerdings passiert nichts wenn ich numpad0 drücke/los lasse

        private void Form1_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode.Equals(Keys.NumPad0))
            {
                MessageBox.Show("Klappt");
            } 
        }
0
FaTech  18.08.2022, 09:04
@Nutzer4596

Hast das KeyPress Event noch drin? Das muss raus, am besten

0
Nutzer4596 
Fragesteller
 18.08.2022, 09:14
@FaTech

Nein. Wie schon gesagt.
Ich habe es aber gerade noch mal probiert und zwar habe ich statt Form1_KeyUp direkt den switch genommen. Also in meinem fall, materialSwitch1_KeyUp. Das funktioniert. Allerdings klappt das nur wenn ich denn Switch einmal an gemacht habe. Vorher geht es nicht wieso auch immer. Danach kann ich den switch aber auch aus machen, der hotkey geht dann immer noch was ja so sein soll. Nur das er am anfang nicht geht ist nicht gut

0
FaTech  18.08.2022, 09:16
@Nutzer4596

Ja, du musst die Form nehmen. Ich kann nachher Mal schauen ...

0
FaTech  18.08.2022, 20:20
@Nutzer4596

Habe gerade mal was probiert. Ich selber bin auch kein Fan der fertigen WinForm Events, weil die Key Events dort einfach Müll sind und nicht perfekt funktionieren ...

Ich habe mal dieses Script zusammen gebastelt. Es ist nicht die schönste Lösung, funktioniert aber perfekt.

using System.Windows.Forms;

namespace NamespaceVonDeinemProgramm // Hier deinen Namespace rein
{
    public class KeyFilterForm : Form, IMessageFilter
    {
        public bool EnableKeyFilter
        {
            set
            {
                if (value)
                    Application.AddMessageFilter(this);
                else
                    Application.RemoveMessageFilter(this);
            }
        }


        public bool PreFilterMessage(ref Message m)
        {
            if (m.Msg == 0x0100)
            {
                OnKeyDownFilter((Keys)m.WParam);
            }


            if (m.Msg == 0x0101)
            {
                OnKeyUpFilter((Keys)m.WParam);
            }


            return false;
        }


        protected virtual void OnKeyDownFilter(Keys key)
        {
            // Nothing
        }


        protected virtual void OnKeyUpFilter(Keys key)
        {
            // Nothing
        }
    }
}

Das fügst du in eine neue CS Datei. Dann kannst deine Form ändern.

Statt:

public partial class Form1 : Form

machst du das:

public partial class Form1 : KeyFilterForm

Jetzt kannst du nach Belieben einfach diese Methoden überschreiben und für dich benutzen:

protected override void OnKeyDownFilter(Keys key)
        {
            
        }


        protected override void OnKeyUpFilter(Keys key)
        {
            if (key == Keys.NumPad0)
            {
                MessageBox.Show("Test");
            }
        }

Die Methoden werden automatisch getriggert, sobald man einen Key drückt.

Mit einer einfachen if Abfrage, kannst du den Wunsch Key angeben.

Mit:

EnableKeyFilter = true;

Kannst du den KeyFilter an und aus schalten. True = an und False = aus.

public Form1()
        {
            InitializeComponent();
            EnableKeyFilter = true;
        }
0
FaTech  18.08.2022, 20:26
@Nutzer4596

Alternativ zu meinem Code gibt es noch die:

protected override bool ProcessCmdKey(ref Message message, Keys keyData)
{

}

Siehe Antwort von regex9

Ich persönlich finde aber ProcessCmdKey nicht so aussagekräftig und finde es mit ordentlicher Benamung, wie bei mir schöner. Aber wie du willst. Nimm das, was dir gefällt :)

0
Nutzer4596 
Fragesteller
 19.08.2022, 03:25
@FaTech

Vielen vielen dank! Ich habe allerdings noch eine frage. Und zwar wie füge ich das meinem bestehendem projekt bei? Ich habe ja schon eins und möchte kein neues erstellen. Ich meine ich habe ja schon ein namespace, public partial class etc.

0
FaTech  19.08.2022, 07:40
@Nutzer4596

Ich sagte ja ...

Du hast aktuell die Vererbung Form. Also du hast da Public partial class DEINNAMEDAFÜR : Form. Hier wirfst du Form raus und setzt dafür KeyFilterForm. Dann hast du direkt die Filter in die Form integriert.

0
Nutzer4596 
Fragesteller
 19.08.2022, 15:01
@FaTech

ich benutze nicht die normale form. Ich benutze MaterialForm von dem Material Form 2 NuGet Package. Wie kann ich denn beide gleichzeitig benutzen?

0
FaTech  19.08.2022, 15:18
@Nutzer4596

Genau so. Wenn du dir meinen Code anschaust, siehst du da ein : Form, was dort geerbt wird. Das musst du dann durch die Materialform Klasse ersetzen, sodass der davon erbt

public class KeyFilterForm : Form, IMessageFilter

Hier musst du das Form zu MaterialForm (oder wie auch immer die Klasse heißt) ändern und schon übernimmt der diese. Thema Vererbung, gerne Googlen, wenn du dazu mehr wissen willst

0
Nutzer4596 
Fragesteller
 19.08.2022, 15:23
@FaTech

Ich verstehe es leider immer noch nicht ganz.

    public partial class Form1 : MaterialForm
    {
        readonly swed swed = new swed();
        IntPtr module; 


        public Form1()
        {
            InitializeComponent();




            var materialSkinManager = MaterialSkinManager.Instance;
            materialSkinManager.AddFormToManage(this);
            materialSkinManager.Theme = MaterialSkinManager.Themes.DARK;
            materialSkinManager.ColorScheme = new ColorScheme(Primary.Purple800, Primary.Purple900, Primary.Purple800, Accent.Purple700, TextShade.BLACK);


        }

Das ist der oberste teil so wie er jetzt momentan ist. Was muss ich dort jetzt konkret ändern damit ich zb. EnableKeyFilter = true; bei InitializeComponent(); benutzen kann und den rest

0
FaTech  19.08.2022, 15:34
@Nutzer4596

Du ersetzt das MaterialForm durch KeyFilterForm und im KeyFilterForm Script, was du von mir kopiert hast, da ersetzt du das Form durch MaterialForm. Dann erbt KeyFilterForm alles von MaterialForm und Form1 erbt das von KeyFilterForm und bleibt damit weiterhin MaterialForm, nur eben erweitert mit diesen Key Features

0
Nutzer4596 
Fragesteller
 19.08.2022, 15:38
@FaTech

Ah ok. Wie kann ich so eine neue cs datei öffnen? Muss ich einfach ein neues projekt machen? Also windows forms app und .NET 6.0

0
FaTech  19.08.2022, 15:39
@Nutzer4596

Beim Projektexplorer auf dein Projekt rechtsklick > Hinzufügen > Klasse

0
Nutzer4596 
Fragesteller
 19.08.2022, 15:45
@FaTech

Wenn ich auf Klasse (Ich habe es auf englisch, also auf Class) gedrückt habe kommt eine liste. Soll ich dort dann auch Class auswählen? oder etwas anderes

0
FaTech  19.08.2022, 15:47
@Nutzer4596

Class sollte schon gewählt sein. Du musst nur noch den Namen anpassen unten. Da steht jetzt sowas wie Class.cs oder so. Das passt du an. Pro Datei immer nur eine Klasse und Die Datei und Klasse immer gleich nennen. Wenn du mein Script importieren willst, musst du also die Datei KeyFilterForm.cs nennen

0
Nutzer4596 
Fragesteller
 19.08.2022, 15:49
@FaTech

Ah, das habe ich nicht gesehen. Ok danke!

1
Nutzer4596 
Fragesteller
 19.08.2022, 15:59
@FaTech

dadurch das ich jetzt aber keyfilterform bei Form1 benutze statt Materialskin bekomme ich bei dem design von form1 nur fehler
"The designer could not be shown for this file because none of the classes within it can be designed. The designer inspected the following classes in the file: The designer could not be shown for this file because none of the classes within it can be designed. The designer inspected the following classes in the file: \r\n Form1 --- The base class 'Kotor_Trainer.KeyFilterForm' could not be loaded. Ensure the assembly has been referenced and that all projects have been built."

0
FaTech  19.08.2022, 16:09
@Nutzer4596

Hast du in KeyFormFilter die Form Vererbung geändert gehabt zu MaterialForm?

0
Nutzer4596 
Fragesteller
 19.08.2022, 16:10
@FaTech

ja.

public class KeyFilterForm : MaterialForm, IMessageFilter 

Ich habe oben extra

using MaterialSkin;
using MaterialSkin.Controls;

Wie bei meiner normalen form benutzt ganz oben

0
FaTech  19.08.2022, 16:13
@Nutzer4596

Oh Mann .... Ok, aber macht nichts. Dann ändere es erstmal zurück. Wir müssen da eine Anpassung nochmal vornehmen am script. Kann das am Handy aber nicht, musst also warten, bis ich daheim bin. Scheint, als wenn der Entwickler eine Prüfung eingebaut hat, die das verhindert. Das kann man aber umgehen

0
Nutzer4596 
Fragesteller
 19.08.2022, 16:15
@FaTech

Ich vermute mal ich muss irgendwie bei dem KeyFilterForm.cs auch ein

InitializeComponent();

Einfügen. (Material Form braucht das nämlich) Nur weiß ich nicht wo und wie ich das schreiben soll. Habe es schon mit

    public KeyFilterForm()
    {
      InitializeComponent();

versucht aber das hat nicht geklappt

0
FaTech  19.08.2022, 16:16
@Nutzer4596

Ne ne. Das ist nicht der Grund. Das ist nur die ausgelagerte Methode zum Form bauen. In die Datei , wo es ausgelagert ist, schreibt der Designer rein

0
Nutzer4596 
Fragesteller
 19.08.2022, 16:18
@FaTech

Also das ist wie gesagt das was die normale form für material Skin 2 benutz hat

        public Form1()
        {
            InitializeComponent();


            EnableKeyFilter = true;
            var materialSkinManager = MaterialSkinManager.Instance;
            materialSkinManager.AddFormToManage(this);
            materialSkinManager.Theme = MaterialSkinManager.Themes.DARK;
            materialSkinManager.ColorScheme = new ColorScheme(Primary.Purple800, Primary.Purple900, Primary.Purple800, Accent.Purple700, TextShade.BLACK);
        }
0
FaTech  19.08.2022, 16:20
@Nutzer4596

Ja, aber das macht nichts. Durch die Vererbung ist es weiterhin erreichbar. Ich baue das Script nachher einmal um und sende es dir dann nochmal

0
FaTech  20.08.2022, 17:07
@Nutzer4596

Oh, sorry, vergessen 😅 Gut das du nochmal schreibst. Ich mache mich gleich dran 😅

0

Du kannst dem Form selbst einen Event Handler für das KeyPress oder KeyDown-Event zuordnen. Das Event-Objekt, welches dem Handler als Parameter überreicht wird, besitzt ein KeyCode-Property. Dessen Wert entspricht der gedrückten Taste. Du kannst es also für eine Prüfung auf eine bestimmte Taste nutzen.

Damit das Form das Event auch dann abfängt, wenn eine andere Kindkomponente in ihm fokussiert ist, sollte das KeyPreview-Property zuvor auf true gesetzt werden.

Konträr zum Setzen eines solchen Event Handlers gibt es noch die Lösung, die ProcessCmdKey-Methode zu überschreiben. Die gedrückte Taste steht in keyData.

protected override bool ProcessCmdKey(ref Message message, Keys keyData)
{
  // check keyData and return true, if event is handled ...

  // otherwise:
  return base.ProcessCmdKey(ref message, keyData);
}

Im Vergleich zur erstbeschriebenen Lösung werden auch Ereignisse mit speziellen Tasten (z.B. Enter/Esc) abgefangen, wenn ein anderes Element im Fokus ist (z.B. wenn eine MessageBox / ein Dialog geöffnet ist und mit Enter bestätigt wird).

Die grundsätzliche Logik, die bei Klick oder Tastendruck durchgeführt werden soll, gehört in eine eigene Helfermethode, die dann im jeweiligen Event Handler / ProcessCmdKey aufgerufen wird.