none
Mauszeiger in TextBox positionieren RRS feed

  • Frage

  • Hallo,

    mit z.B.  TextBox.SelectionStart=0  bekomme ich den Cursor in die TextBox.
    Wie kann ich aber den Mauszeiger auch auf diese Position bekommen?

    Gruß
    Sven

    Donnerstag, 26. Januar 2012 18:22

Antworten

  • Hallo Sven und Stefan,

    das Entführen des Mauszeigers kann für den Benutzer tatsächlich sehr verwirrend sein. Aber wenn man den "entführten" Mauszeiger schnell wieder dahin zurückbringt, wo er hingehört, behält der Benutzer die Kontrolle über seine Maus.

    Als Beispiel-Szenario habe ich mir eine Anwendung ausgedacht, die einen Text auf Rechtschreibefehler überprüft. Sobald ein Fehler entdeckt wird, wird:

    1. das fehlerhafte Wort in der TextBox selektiert,
    2. der Mauszeiger wandert unter das selektierte Wort,
    3. der Mauscursor wird zu einem Hand-Cursor geändert
    4. nach weniger als eine Sekunde wird die alte Maus-Position wiederhergestellt

     

    Und hier kommt der Code (leider C#, da ich gerade keine Zeit für die VB-Konvertierung habe):

    using System;
    using System.Drawing;
    using System.Windows.Forms;
    
    namespace MoveMouseCursorDemo
    {
        public partial class Form1 : Form
        {
            private Timer timer = new Timer();
            private int index;
            private Cursor savedCursor;
            private Point savedPoint;
    
            public Form1()
            {
                InitializeComponent();
    
                // Timer einrichten
                this.timer.Enabled = false;
                this.timer.Interval = 400;
                this.timer.Tick += OnTimerTick;
    
                // TextBox einrichten
                this.textBox1.Text = "Katz und Maus sollte man nur dann spielen, wenn man keine maus ist.";
                this.textBox1.SelectionStart = 0;
                this.textBox1.HideSelection = false;
            }
    
            private void OnTimerTick(object sender, EventArgs e)
            {
                this.timer.Stop();
                RestoreMousePositionAndTextBoxCursor();
            }
    
            private void RestoreMousePositionAndTextBoxCursor()
            {
                this.textBox1.Cursor = savedCursor;
                Cursor.Position = savedPoint;
            }
    
            private void buttonSpellCheck_Click(object sender, EventArgs e)
            {
                ShowSpellCheckError("maus");
            }
    
            private void ShowSpellCheckError(string wordToFind)
            {
                // Wir haben einen Rechtschreibfehler gefunden 
                // ("maus" statt "Maus") und selektieren das Wort
                index = this.textBox1.Text.IndexOf(wordToFind);
                this.textBox1.SelectionStart = index;
                this.textBox1.SelectionLength = wordToFind.Length;
    
                // Nun lassen wir die Maus auf diese Position
                // hinweisen
                MoveCursorToCharIndex(index);
            }
    
            private void MoveCursorToCharIndex(int charIndex) 
            {
                // Wir verschieben den Cursor vertikal unter
                // das ausgewählte Wort
    
                Graphics graphics = textBox1.CreateGraphics();
                SizeF size = graphics.MeasureString(textBox1.Text, textBox1.Font);
                int VERTICAL_OFFSET = (int)size.Height;
    
                // Aktuelle Maus-Position und aktuellen Cursor speichern
                this.savedPoint = Cursor.Position;
                this.savedCursor = this.textBox1.Cursor;
    
                // Position des Carets ermitteln
                Point caretPosition = this.textBox1.GetPositionFromCharIndex(this.textBox1.SelectionStart);
                Cursor.Position = this.textBox1.PointToScreen(new Point(caretPosition.X, caretPosition.Y + VERTICAL_OFFSET));
    
                // Für die Dauer von Timer.Interval den Cursor ändern
                this.textBox1.Cursor = Cursors.Hand;
    
                // Timer starten, damit der gespeicherte Cursor wiederhergestellt werden kann
                this.timer.Start();
            } 
        }
    }
    


    (Noch eine Anmerkung für jene, die den Code auf einer virtuellen Maschine ausführen: Oft, z.B. bei VMWare-Boxen, funktioniert Cursor.Position nicht. Führt den Code also bitte auf einer echten Maschine aus. Und nicht übertreiben! Der Code soll nur zeigen, was geht :-)

    Gruß
    Marcel

    • Bearbeitet Marcel Roma Freitag, 27. Januar 2012 09:41 Anmerkung
    • Als Antwort vorgeschlagen Stefan FalzModerator Freitag, 27. Januar 2012 11:38
    • Als Antwort markiert SvenGrab Freitag, 3. Februar 2012 07:47
    Freitag, 27. Januar 2012 09:33
  • Hallo Stefan, hallo Marcel,

    vielen Dank für Eure Antworten. Natürlich ist es nicht besonders "schick", wenn man die Maus entführt.

    Nur: Hier wird durch einen Klick auf eine Schaltfläche eine TextBox für Text-Änderungen geöffnet - und da ist es m.E. für den User besser, wenn sich der Mauszeiger auch gleich auf dem zu ändernden Text befindet.
    Die Anregung mit Cursor-Hand finde ich gut. Hatte Sie bisher nicht bedacht und werde sie übernehmen.

    Das Umsetzen von C# ist keine Problem: Ich sehe hier, dass Du hier mit absoluten Positionen (bezogen auf den Screen) arbeitest. Meine Textbox ist ein Control in einem Panel, hat also innerhalb des Panel nur relative Positionen. Den Cursor positioniere ich mit MeineTextBox.focus() - und ich suchte eine ähnlich einfache Möglichkeit für den Mauszeiger.

    Nun gut - dann muss ich halt die Position für den Mauszeiger ausrechnen.

    Trotzdem vielen Dank für Eure Hilfe.

    Gruß
    Sven

     

    • Als Antwort markiert SvenGrab Samstag, 4. Februar 2012 18:40
    Mittwoch, 1. Februar 2012 17:27

Alle Antworten

  • Hallo Sven,

    warum sollte man das tun? Wenn ein User am Rechner sitzt, wird der sich herzlichst bedanken, wenn man ihm den Mauszeiger "entführt". Das wäre dann das letzte mal, dass diese Anwendung bei mir das Licht der Welt erblickt.

    Wenn kein User am Rechner sitzt, brauchst Du den Mauszeiger in der Regel nicht. Daher dann die Frage: Für was brauchst Du das? Dann kann man ggfs. auch Alternativlösungen vorschlagen.


     


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community
    Donnerstag, 26. Januar 2012 19:15
    Moderator
  • Hallo Sven und Stefan,

    das Entführen des Mauszeigers kann für den Benutzer tatsächlich sehr verwirrend sein. Aber wenn man den "entführten" Mauszeiger schnell wieder dahin zurückbringt, wo er hingehört, behält der Benutzer die Kontrolle über seine Maus.

    Als Beispiel-Szenario habe ich mir eine Anwendung ausgedacht, die einen Text auf Rechtschreibefehler überprüft. Sobald ein Fehler entdeckt wird, wird:

    1. das fehlerhafte Wort in der TextBox selektiert,
    2. der Mauszeiger wandert unter das selektierte Wort,
    3. der Mauscursor wird zu einem Hand-Cursor geändert
    4. nach weniger als eine Sekunde wird die alte Maus-Position wiederhergestellt

     

    Und hier kommt der Code (leider C#, da ich gerade keine Zeit für die VB-Konvertierung habe):

    using System;
    using System.Drawing;
    using System.Windows.Forms;
    
    namespace MoveMouseCursorDemo
    {
        public partial class Form1 : Form
        {
            private Timer timer = new Timer();
            private int index;
            private Cursor savedCursor;
            private Point savedPoint;
    
            public Form1()
            {
                InitializeComponent();
    
                // Timer einrichten
                this.timer.Enabled = false;
                this.timer.Interval = 400;
                this.timer.Tick += OnTimerTick;
    
                // TextBox einrichten
                this.textBox1.Text = "Katz und Maus sollte man nur dann spielen, wenn man keine maus ist.";
                this.textBox1.SelectionStart = 0;
                this.textBox1.HideSelection = false;
            }
    
            private void OnTimerTick(object sender, EventArgs e)
            {
                this.timer.Stop();
                RestoreMousePositionAndTextBoxCursor();
            }
    
            private void RestoreMousePositionAndTextBoxCursor()
            {
                this.textBox1.Cursor = savedCursor;
                Cursor.Position = savedPoint;
            }
    
            private void buttonSpellCheck_Click(object sender, EventArgs e)
            {
                ShowSpellCheckError("maus");
            }
    
            private void ShowSpellCheckError(string wordToFind)
            {
                // Wir haben einen Rechtschreibfehler gefunden 
                // ("maus" statt "Maus") und selektieren das Wort
                index = this.textBox1.Text.IndexOf(wordToFind);
                this.textBox1.SelectionStart = index;
                this.textBox1.SelectionLength = wordToFind.Length;
    
                // Nun lassen wir die Maus auf diese Position
                // hinweisen
                MoveCursorToCharIndex(index);
            }
    
            private void MoveCursorToCharIndex(int charIndex) 
            {
                // Wir verschieben den Cursor vertikal unter
                // das ausgewählte Wort
    
                Graphics graphics = textBox1.CreateGraphics();
                SizeF size = graphics.MeasureString(textBox1.Text, textBox1.Font);
                int VERTICAL_OFFSET = (int)size.Height;
    
                // Aktuelle Maus-Position und aktuellen Cursor speichern
                this.savedPoint = Cursor.Position;
                this.savedCursor = this.textBox1.Cursor;
    
                // Position des Carets ermitteln
                Point caretPosition = this.textBox1.GetPositionFromCharIndex(this.textBox1.SelectionStart);
                Cursor.Position = this.textBox1.PointToScreen(new Point(caretPosition.X, caretPosition.Y + VERTICAL_OFFSET));
    
                // Für die Dauer von Timer.Interval den Cursor ändern
                this.textBox1.Cursor = Cursors.Hand;
    
                // Timer starten, damit der gespeicherte Cursor wiederhergestellt werden kann
                this.timer.Start();
            } 
        }
    }
    


    (Noch eine Anmerkung für jene, die den Code auf einer virtuellen Maschine ausführen: Oft, z.B. bei VMWare-Boxen, funktioniert Cursor.Position nicht. Führt den Code also bitte auf einer echten Maschine aus. Und nicht übertreiben! Der Code soll nur zeigen, was geht :-)

    Gruß
    Marcel

    • Bearbeitet Marcel Roma Freitag, 27. Januar 2012 09:41 Anmerkung
    • Als Antwort vorgeschlagen Stefan FalzModerator Freitag, 27. Januar 2012 11:38
    • Als Antwort markiert SvenGrab Freitag, 3. Februar 2012 07:47
    Freitag, 27. Januar 2012 09:33
  • Hallo Marcel,

    Aber wenn man den "entführten" Mauszeiger schnell wieder dahin zurückbringt, wo er hingehört, behält der Benutzer die Kontrolle über seine Maus.

    nicht wirklich. Auch eine Sekunde, halbe Sekunde, ... ist alles andere als hilfreich, egal, um welche Funktionalität es geht. Um bspw. etwas zu markieren, gibt es andere/bessere Wege.

    Aber dennoch dürfte dein Beispiel die Antwort auf Svens Frage sein :)

     


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community
    Freitag, 27. Januar 2012 11:38
    Moderator
  • Hallo Stefan,

    nicht wirklich. Auch eine Sekunde, halbe Sekunde, ... ist alles andere als hilfreich [...]

    Damit hast Du grundsätzlich Recht. Auch wenn die wenigsten von uns im Millisekundenbereich reagieren können, würde die "Entführung der Maus" während der Mausbewegung unangenehm auffallen und evtl. als unverständliches Ruckeln oder gar Desorientierung empfunden werden. In statischen Situationen hingegen wurde das auch schon in der Windows API genutzt, um z.B. den Mauszeiger auf die Standardschaltfläche eines Dialogs zu führen. Es ist m.E. auch immer ein bischen Geschmackssache, ob man das verwenden möchte (und nicht unbedingt mein Geschmack).

    Gruß
    Marcel

    Freitag, 27. Januar 2012 12:08
  • Hallo Stefan, hallo Marcel,

    vielen Dank für Eure Antworten. Natürlich ist es nicht besonders "schick", wenn man die Maus entführt.

    Nur: Hier wird durch einen Klick auf eine Schaltfläche eine TextBox für Text-Änderungen geöffnet - und da ist es m.E. für den User besser, wenn sich der Mauszeiger auch gleich auf dem zu ändernden Text befindet.
    Die Anregung mit Cursor-Hand finde ich gut. Hatte Sie bisher nicht bedacht und werde sie übernehmen.

    Das Umsetzen von C# ist keine Problem: Ich sehe hier, dass Du hier mit absoluten Positionen (bezogen auf den Screen) arbeitest. Meine Textbox ist ein Control in einem Panel, hat also innerhalb des Panel nur relative Positionen. Den Cursor positioniere ich mit MeineTextBox.focus() - und ich suchte eine ähnlich einfache Möglichkeit für den Mauszeiger.

    Nun gut - dann muss ich halt die Position für den Mauszeiger ausrechnen.

    Trotzdem vielen Dank für Eure Hilfe.

    Gruß
    Sven

     

    • Als Antwort markiert SvenGrab Samstag, 4. Februar 2012 18:40
    Mittwoch, 1. Februar 2012 17:27
  • Hallo Sven,

    > Die Anregung mit Cursor-Hand finde ich gut. Hatte Sie bisher nicht bedacht und werde sie übernehmen.

    Freut mich.

    > (...) und ich suchte eine ähnlich einfache Möglichkeit für den Mauszeiger.

    Die "eingebaute" Möglichkeit gibt's leider nicht. Aber die Berechnung der Mauszeigerposition ist - wie Du siehst - auch kein Kunststück.

    Gruß
    Marcel

    Mittwoch, 1. Februar 2012 17:42
  • Hallo SvenGrab,

    Ich möchte Dich bitten folgendes lesen und die Beiträge die Dir geholfen haben zu bewerten.

    Vielen Dank.

    Nutzen Sie die Bewertungsfunktionen ("Antwort" und "Hilfreich") in den MSDN Foren! Unter anderem können andere später eine Lösung schneller finden. Es ist also wünschenswert, dass die fragenden (Benutzer) die Postings/Beiträge anderer Beantworter bewerten.
    Hier dazu die wichtigsten Anhaltspunkte aus den Forenregeln und FAQs.


    Lösungsbeiträge als „Die Antwort“ markieren
    Bitte markieren Sie den Beitrag, der zur Lösung geführt hat, als "Die Antwort". Durch Bewerten eines Beitrags als "Die Antwort" können andere Teilnehmer die Lösung schneller finden. Außerdem können Sie dem Benutzer, der die Antwort eingereicht hat, für seinen Beitrag danken und zur Steigerung der Antwortqualität in der Diskussionsgruppe beitragen.
    [Quelle: Forenregeln]

    Wie bewerte ich einen Beitrag? Um einen Beitrag als hilfreich zu bewerten, klicken Sie in einem beliebigen Beitrag auf Als hilfreich bewerten. Sie können Ihre Stimme nur einmal für einen Beitrag abgeben.
    [Quelle: Häufig gestellte Fragen]

    Grüße,

    Robert


    Robert Breitenhofer, MICROSOFT  Twitter Facebook
    Bitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-Prinzip „Entwickler helfen Entwickler“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können.

    Donnerstag, 2. Februar 2012 15:21