none
TextBox zum Cursor scrollen RRS feed

  • Frage

  • Hi,
    ich habe eine Anwendung mit einem TextBox entwickelt. Da die Text und Cursor per Funktionen gesteuert ist muß ich um Scrollen auch selbst kümmern. Leider habe ich außer "zum Ende scrollen" und "ScrollToCaret" nichts gefunden.

    Mein Problem ist, ScrollToCaret erfüllt nicht das was ich möchte. Das Funktion scrollt immer so, daß der Cursor unten ist.

    D.h. wenn ich mit dem Cursor am oberen Rand eins nach oben bewege (und somit auserhalb von Textfeld komme) und dann ScrollToCaret ausführe, geht die Scrollbar leider nicht nur um eine Zeile nach oben. Sondern es springt gleich eine Seite nach oben (so daß Cursor unten ist).

    Wenn ich aber an unteren Rand eins nach unten bewege, dann passt es ja (weil der Cursor eh unten ist). Wie kann ich es sauber lösen? Evtl. ist da ne Funktion wovon ich nichts weiß?

    Gibt es auch eine Möglichkeit zu prüfen, ob der Cursor noch innerhalb von der Sichtbereich der TextBox ist, oder ob es schon "außerhalb" ist?

    Thanx!

    Floh

    Freitag, 17. Juni 2011 12:40

Antworten

  • Hallo Floh,

    > Ich muß wohl eine Funktion überschreiben der für Vorverarbeitung zuständig ist wo ich dann die gewünschte Tasten abfangen muß.

    Oh, da hast Du aber bei RichTextBox und TextBox die Qual der Wahl (wenn Du davon ableitest). Nachfolgend einige der Handler, die Du verwenden könntest um Enter und Backspace abzufangen:

    class RichTextBoxEx : RichTextBox {
     const int WM_KEYDOWN = 0x100;
     const int WM_KEYUP = 0x101;
    
     private static bool ShouldIgnoreMessage(Message msg) {
      if ((msg.Msg == WM_KEYDOWN || msg.Msg == WM_KEYUP) &&
       (msg.WParam.ToInt32() == (int)Keys.Back || msg.WParam.ToInt32() == (int)Keys.Enter))
       return true;
      return false;
     }
    
     public override bool PreProcessMessage(ref Message msg) {
      if (ShouldIgnoreMessage(msg))
       return true;
      return base.PreProcessMessage(ref msg);
     }
    
     protected override bool ProcessCmdKey(ref Message m, Keys keyData) {
      if (ShouldIgnoreMessage(m))
       return true;
      return base.ProcessCmdKey(ref m, keyData);
     }
    
     protected override bool ProcessDialogKey(Keys keyData) {
      if (keyData == Keys.Back || keyData == Keys.Enter)
       return true;
      return base.ProcessDialogKey(keyData);
     }
    
     protected override bool ProcessKeyMessage(ref Message m) {
      if (ShouldIgnoreMessage(m))
       return true;
      return base.ProcessKeyMessage(ref m);
     }
    
     protected override bool ProcessKeyEventArgs(ref Message m) {
      if (ShouldIgnoreMessage(m))
       return true;
      return base.ProcessKeyEventArgs(ref m);
     }
    
     protected override void OnKeyDown(KeyEventArgs e) {
      if (e.KeyCode == Keys.Back || e.KeyCode == Keys.Enter)
       e.Handled = true;
      base.OnKeyDown(e);
     }
    
     protected override void OnKeyPress(KeyPressEventArgs e) {
      // Das Setzen von e.Handled verhindert hier leider nicht 
      // die Verarbeitung der Tastaturanschläge
      if (e.KeyChar == '\b' || e.KeyChar == '\r')
       e.Handled = true;
      base.OnKeyPress(e);
     }
    
     protected override void OnKeyUp(KeyEventArgs e) {
      // Auch hier bleibt e.Handled ohne Effekt
      if (e.KeyCode == Keys.Back || e.KeyCode == Keys.Enter)
       e.Handled = true;
      base.OnKeyUp(e);
     }
    }
    

    Die Overrides sind in der Reihenfolge in der sie aufgerufen werden aufgelistet. Wenn also PreProcessMessage() true zurückgibt, um anzuzeigen, dass es die Nachricht verarbeitet hat, erreicht die Nachricht natürlich die nachfolgenden Handler nicht mehr. Auf welchem Level Du ansetzen möchtest, hängt vom Design Deiner Anwendung ab.

    Gruß
    Marcel


    • Als Antwort vorgeschlagen Marcel RomaModerator Mittwoch, 22. Juni 2011 14:02
    • Als Antwort markiert Floh79 Freitag, 24. Juni 2011 07:54
    Montag, 20. Juni 2011 19:55
    Moderator
  • Hallo F.,

    • daher ist die Funktion KeyPress() sehr wichtig für mich. ...

    Hier kannst Du noch weitere Methoden einsehen, welche Tasten-Eingaben-Methoden es gibt.
    Zusammen mit meinen SendMessage-Informationen sollte eigentlich beliebiges Verhalten abbildbar sein.

    [Funktionsweise von Tastatureingaben]
    http://msdn.microsoft.com/de-de/library/ms171535.aspx

    [Gewusst wie: Ändern von Tastatureingaben in ein Standardsteuerelement]
    http://msdn.microsoft.com/de-de/library/ms171537.aspx

    [IMessageFilter-Schnittstelle System.Windows.Forms)]
    http://msdn.microsoft.com/de-de/library/system.windows.forms.imessagefilter.aspx

     

    • Return => Modifikation in TextBox

    Für das Handling der Enter-Taste bei der TextBox existiert übrigens auch:

    [TextBox.AcceptsReturn-Eigenschaft (System.Windows.Forms)]
    http://msdn.microsoft.com/de-de/library/system.windows.forms.textbox.acceptsreturn.aspx


    ciao Frank



    • Als Antwort markiert Floh79 Montag, 20. Juni 2011 14:08
    Montag, 20. Juni 2011 13:36

Alle Antworten

  • Hallo Floh,

    TextBox und RichTextBox weisen bezüglich Scrollen verschiedene Verhalten auf. Ausgehend von Deiner Beschreibung vermute ich, dass Du eher das Verhalten von RichTextBox verwenden möchtest.

    Stellen wir uns diese beiden o.g. Controls auf einer Form vor. Beide haben die gleiche Größe und zeigen z.B. 4 Zeilen von 26 an. Wenn man nun die selbstdefinierte Erweiterungsmethode ScrollToLine(8) aufruf, wird TextBox zwar die 9. Zeile anzeigen aber am unteren Rand der TextBox während die RichTextBox die 9. Zeile am oberen Rand der RichTextBox anzeigt:

    using System;
    using System.Linq;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication1
    {
      public partial class Form1 : Form {
        public Form1() {
          InitializeComponent();
        }
    
        private void Form1_Load(object sender, EventArgs e) {
          string s = "01. Auf der Mauer, auf der Lauer sitzt 'ne kleine WANZE.\r\n";
          s += "02. Sieh dir mal die WANZE AN, wie die WANZE TANZEN KANN.\r\n";
          s += "03. Auf der Mauer, auf der Lauer sitzt 'ne kleine WANZE.\r\n";
          s += "04. Auf der Mauer, auf der Lauer sitzt 'ne kleine WANZ.\r\n";
          s += "05. Sieh dir mal die WANZ AN, wie die WANZ TANZ KANN.\r\n";
          s += "06. Auf der Mauer, auf der Lauer sitzt 'ne kleine WANZ.\r\n";
          s += "07. Auf der Mauer, auf der Lauer sitzt 'ne kleine WAN.\r\n";
          s += "08. Sieh dir mal die WAN AN, wie die WAN TAN KANN.\r\n";
          s += "09. Auf der Mauer, auf der Lauer sitzt 'ne kleine WAN.\r\n";
          s += "10. Auf der Mauer, auf der Lauer sitzt 'ne kleine WA.\r\n";
          s += "11. Sieh dir mal die WA A, wie die WA TA KA.\r\n";
          s += "12. Auf der Mauer, auf der Lauer sitzt 'ne kleine WA.\r\n";
          s += "13. Auf der Mauer, auf der Lauer sitzt 'ne kleine W.\r\n";
          s += "14. Sieh dir mal die W m, wie die W T K.\r\n";
          s += "15. Auf der Mauer, auf der Lauer sitzt 'ne kleine WA.\r\n";
          s += "16. Sieh dir mal die WA A, wie die WA TA KA.\r\n";
          s += "17. Auf der Mauer, auf der Lauer sitzt 'ne kleine WA.\r\n";
          s += "18. Auf der Mauer, auf der Lauer sitzt 'ne kleine WAN.\r\n";
          s += "19. Sieh dir mal die WAN AN, wie die WAN TAN KANN.\r\n";
          s += "20. Auf der Mauer, auf der Lauer sitzt 'ne kleine WAN.\r\n";
          s += "21. Auf der Mauer, auf der Lauer sitzt 'ne kleine WANZ.\r\n";
          s += "22. Sieh dir mal die WANZ AN, wie die WANZ TANZ KANN.\r\n";
          s += "23. Auf der Mauer, auf der Lauer sitzt 'ne kleine WANZ.\r\n";
          s += "24. Auf der Mauer, auf der Lauer sitzt 'ne kleine WANZE.\r\n";
          s += "25. Sieh dir mal die WANZE AN, wie die WANZE TANZEN KANN.\r\n";
          s += "26. Auf der Mauer, auf der Lauer sitzt 'ne kleine WANZE.\r\n";
    
          textBox1.Text = s;
          richTextBox1.Text = s;
        }
    
        private void buttonScrollTo_Click(object sender, EventArgs e) {
          int lineNumber = 0;
    
          if (int.TryParse(textBoxRowPosition.Text, out lineNumber)) {
            richTextBox1.ScrollToLine(lineNumber);
            textBox1.ScrollToLine(lineNumber);
          }
        }
      }
    
      public static class TextBoxBaseExtensions {
        public static void ScrollToLine(this TextBoxBase targetTextBox, int zeroBasedLineNumber) {
          string[] lines = targetTextBox.Lines;
    
          if (!Enumerable.Range(0, lines.Length).Contains(zeroBasedLineNumber))
            throw new ArgumentOutOfRangeException("zeroBasedLineNumber");
          
          int position = 0;
    
          for(int i=0; i <= zeroBasedLineNumber; i++)
            position += lines[i].Length;
    
          targetTextBox.SelectionStart = position;
          targetTextBox.SelectionLength = 0;
          targetTextBox.ScrollToCaret();
        }
      }
    }


    Da beide NET-Controls nur Wrapper für native Steuerelemente sind, kannst Du das Scrollen programmatisch steuern, indem Du Nachrichten direkt an die Fensterprozedur des jeweiligen Controls sendest. Details dazu findest Du in den Links unten:

    TextBox Scrolling in C#:
    http://www.someuser77.com/guides/scrolling-textbox-using-windows-api/ 
    http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/a153732b-14ac-4b62-8547-9458489ebd51/

    TextBoxBase.SelectionStart-Eigenschaft:
    http://msdn.microsoft.com/de-de/library/system.windows.forms.textboxbase.selectionstart(v=VS.100).aspx

    Gruß
    Marcel


    Freitag, 17. Juni 2011 14:57
    Moderator
  • Hallo F.,

    Zunächst mal gibt es ja den Standard mit dem Setzen von SelectionStart und ScrollToCaret: [An das ende einer Multiline Textbox springen].
    (ich schreibe in obigen Thread allerdings auch schon, dass diese Methode Seiteneffekte hat, und nenne Methoden, diese zu umgehen).

    Insofern kann ich Dir mal ein paar weitere Möglichkeiten geben und mal ein Beispiel für das "eine Zeile hochscrollen":

     

    using System;
    using System.Runtime.InteropServices;
    using System.Text;
    using System.Windows.Forms;
    
    namespace WinTextScroll
    {
     public partial class Form1 : Form
     {
     public Form1()
     {
      InitializeComponent();
     }
    
     private void Form1_Load(object sender, EventArgs e)
     {
      textBox1.Text = DemoText();
      textBox1.ScrollBars = ScrollBars.Both;
      textBox1.Multiline = true;
     }
    
     private void button1_Click(object sender, EventArgs e)
     {
      TextBoxEineZeileHochScrollen(textBox1);
     }
    
     private string DemoText()
     {
      StringBuilder sb = new StringBuilder();
      for (int i = 0; i < 50; i++) 
      sb.Append("Lorem ipsum dolor sit amet, consetetur sadipscing elitr, " +
       "sed diam nonumy eirmod tempor invidunt ut labore et " +
       "dolore magna aliquyam erat ");
      return sb.ToString();
     }
    
     /// <summary>[About Scroll Bars (Windows)]
     /// http://msdn.microsoft.com/en-us/library/bb787527(VS.85).aspx
     /// </summary>
     public enum ScrollBarCommands : int
     {
      SB_LINEUP = 0, SB_LINELEFT = 0,
      SB_LINEDOWN = 1, SB_LINERIGHT = 1,
      SB_PAGEUP = 2, SB_PAGELEFT = 2,
      SB_PAGEDOWN = 3, SB_PAGERIGHT = 3,
      SB_THUMBPOSITION = 4, SB_THUMBTRACK = 5,
      SB_TOP = 6, SB_LEFT = 6, SB_BOTTOM = 7,
      SB_RIGHT = 7, SB_ENDSCROLL = 8
     }
    
     enum ScrollWParam
     {
      WM_HSCROLL = 0x114,
      WM_VSCROLL = 0x115
     }
    
     [DllImport("user32.dll", CharSet = CharSet.Auto)]
     private static extern int SendMessage(IntPtr hWnd,
      int wMsg, IntPtr wParam, IntPtr lParam);
    
     int SendeMeldung(IntPtr hWnd, ScrollWParam scrollWParam, ScrollBarCommands scrollBarCommand)
     {
      return SendMessage(hWnd, (int)scrollWParam, new IntPtr((int)scrollBarCommand), IntPtr.Zero);
     }
    
     private void TextBoxEineZeileHochScrollen(TextBox tb)
     {
      SendeMeldung(tb.Handle, ScrollWParam.WM_VSCROLL, ScrollBarCommands.SB_LINEUP);
     }
     }
    }
    
    

    Damit und zusammen mit der Doku kann man nun im Prinzip beliebiges Scroll-Verhalten abbilden.
    http://msdn.microsoft.com/en-us/library/bb787527(VS.85).aspx

     


    ciao Frank
    Freitag, 17. Juni 2011 15:37
  • Hi Marcel & Frank,

    vielen Dank für die hilfreiche Antworten. Leider muß ich erstmal wissen ob der Cursor in der Textfeld, oberhalb bzw. unterhalb von sichtbare Bereich befindet. Erst dann kann ich die entsprechende Funktion nutzen um dorthin zu springen.

    Außerdem habe ich mit richTextBox ein Problem... ich habe eine schöne KeyPress-Funktion für textBox implementiert, diese funktioniert nimmer bei richTextBox. Der Grund ist:

    Bei richTextBox.KeyPress() wurde bereits die Text geändert wenn die Funktion ausgeführt wird. Das darf bei mir nicht passieren da ich die originale Text benötige und die Text selbst verarbeite (Hintergrund siehe unten). Bei textBox dagegen noch nicht und ich kann da mit KeyPressEventArgs e => e.handled = true; das verändern der Textbox nach der Funkionsaufruf unterbinden.

    Warum haben wir zwischen textBox und richTextBox unterschiedliche Verhalten bei KeyPress? :(

    Hintergrund, damit ihr vielleicht besser nachvollziehen könnt:

    Ich arbeite an RealTime-Texteditor und muß mit Synchronisation arbeiten, daher ist die Funktion KeyPress() sehr wichtig für mich.

    cu Floh

    Montag, 20. Juni 2011 10:27
  • Hallo Floh,

    > Außerdem habe ich mit richTextBox ein Problem... ich habe eine schöne KeyPress-Funktion für textBox implementiert, diese funktioniert nimmer bei richTextBox.

    Auch in einem Szenario wie dem folgenden?

    class RichtTextBoxEx : RichTextBox {
    protected override void OnKeyPress(KeyPressEventArgs e) { if(e.KeyChar == 'e') e.Handled = true; base.OnKeyPress(e); } }

    > Ich arbeite an RealTime-Texteditor und muß mit Synchronisation arbeiten, daher ist die Funktion KeyPress() sehr wichtig für mich.

    RealTime ist vielleicht etwas zu viel gesagt bei Controls die über das Versenden von Windows-Nachrichten funktionieren. Die Verarbeitung von Nachrichten kann durch vieles verzögert werden.

    Gruß
    Marcel

    Montag, 20. Juni 2011 10:48
    Moderator
  • Hi Marcel,

    vielen Dank für die Tip. Aber selbst mit SubClass wird der TextBox trotzdem modifiziert. Auffallend ist (ohne Deine Vorschlag mit Subclass):
    Backspace, Return => Modifikation in TextBox
    Buchstaben, Zahlen => kein Modifikation in TextBox wenn in KeyPress Funktion "e.handled = true;" drinsteht.

    cu Floh

    Montag, 20. Juni 2011 12:53
  • Hallo Floh,

    ich empfehle die Lektüre von:

    Probably more than you want to know about keyboarding in Windows Forms….

    => nicht alles läuft über KeyPress.
    Und die Windows Forms RichtextBox ist nichts weiter als ein Wrapper
    um das native Rich Edit Steuerelement .

    Nur wenn Du das Verhalten beider studiert hast, hat ein darauf aufsetzender
    "RealTime-Texteditor" einige Aussicht auf Erfolg.

    Gruß Elmar

    Montag, 20. Juni 2011 13:03
    Beantworter
  • Hallo F.,

    • daher ist die Funktion KeyPress() sehr wichtig für mich. ...

    Hier kannst Du noch weitere Methoden einsehen, welche Tasten-Eingaben-Methoden es gibt.
    Zusammen mit meinen SendMessage-Informationen sollte eigentlich beliebiges Verhalten abbildbar sein.

    [Funktionsweise von Tastatureingaben]
    http://msdn.microsoft.com/de-de/library/ms171535.aspx

    [Gewusst wie: Ändern von Tastatureingaben in ein Standardsteuerelement]
    http://msdn.microsoft.com/de-de/library/ms171537.aspx

    [IMessageFilter-Schnittstelle System.Windows.Forms)]
    http://msdn.microsoft.com/de-de/library/system.windows.forms.imessagefilter.aspx

     

    • Return => Modifikation in TextBox

    Für das Handling der Enter-Taste bei der TextBox existiert übrigens auch:

    [TextBox.AcceptsReturn-Eigenschaft (System.Windows.Forms)]
    http://msdn.microsoft.com/de-de/library/system.windows.forms.textbox.acceptsreturn.aspx


    ciao Frank



    • Als Antwort markiert Floh79 Montag, 20. Juni 2011 14:08
    Montag, 20. Juni 2011 13:36
  • Hallo Floh,

    > Aber selbst mit SubClass wird der TextBox trotzdem modifiziert [...]

    Das hat spezifisch weder mit der TextBox, noch mit der RichTextBox was zu tun. Sieh Dir doch mal die Dokumentation zu Control.KeyPress bzw. Control.KeyDown an. Dann verstehst Du auch, dass KeyPress nicht alle Tastaturereignisse verarbeitet (und warum). In der Dokumentation von KeyDown steht auch was man machen muss, um Tasten wie die Eingabetaste im KeyDown-Ereignis erfolgreich behandeln zu können. Subclassing ist an sich ein probates Mittel um Ereignisse in der aktuellen Instanz zu behandeln, bevor sie durch die Basisklasse weiterverarbeitet werden. Da rutsch nichts einfach durch (wenn es nicht z.B. auf Parent-Ebene vor-verarbeitet wird).

    Aber das alles führt leider sehr weit weg vom eigentlichen Thema.

    Gruß
    Marcel

    Montag, 20. Juni 2011 14:55
    Moderator
  • Hallo Floh,

    > Aber selbst mit SubClass wird der TextBox trotzdem modifiziert [...]

    Das hat spezifisch weder mit der TextBox, noch mit der RichTextBox was zu tun. Sieh Dir doch mal die Dokumentation zu Control.KeyPress bzw. Control.KeyDown an. Dann verstehst Du auch, dass KeyPress nicht alle Tastaturereignisse verarbeitet (und warum).

    Naja... der Funktion KeyPress wird bei Return und Backspace ausgeführt. Ich muß wohl eine Funktion überschreiben der für Vorverarbeitung zuständig ist wo ich dann die gewünschte Tasten abfangen muß.

    cu Floh

    Montag, 20. Juni 2011 14:59
  • Hallo Floh,

    > Ich muß wohl eine Funktion überschreiben der für Vorverarbeitung zuständig ist wo ich dann die gewünschte Tasten abfangen muß.

    Oh, da hast Du aber bei RichTextBox und TextBox die Qual der Wahl (wenn Du davon ableitest). Nachfolgend einige der Handler, die Du verwenden könntest um Enter und Backspace abzufangen:

    class RichTextBoxEx : RichTextBox {
     const int WM_KEYDOWN = 0x100;
     const int WM_KEYUP = 0x101;
    
     private static bool ShouldIgnoreMessage(Message msg) {
      if ((msg.Msg == WM_KEYDOWN || msg.Msg == WM_KEYUP) &&
       (msg.WParam.ToInt32() == (int)Keys.Back || msg.WParam.ToInt32() == (int)Keys.Enter))
       return true;
      return false;
     }
    
     public override bool PreProcessMessage(ref Message msg) {
      if (ShouldIgnoreMessage(msg))
       return true;
      return base.PreProcessMessage(ref msg);
     }
    
     protected override bool ProcessCmdKey(ref Message m, Keys keyData) {
      if (ShouldIgnoreMessage(m))
       return true;
      return base.ProcessCmdKey(ref m, keyData);
     }
    
     protected override bool ProcessDialogKey(Keys keyData) {
      if (keyData == Keys.Back || keyData == Keys.Enter)
       return true;
      return base.ProcessDialogKey(keyData);
     }
    
     protected override bool ProcessKeyMessage(ref Message m) {
      if (ShouldIgnoreMessage(m))
       return true;
      return base.ProcessKeyMessage(ref m);
     }
    
     protected override bool ProcessKeyEventArgs(ref Message m) {
      if (ShouldIgnoreMessage(m))
       return true;
      return base.ProcessKeyEventArgs(ref m);
     }
    
     protected override void OnKeyDown(KeyEventArgs e) {
      if (e.KeyCode == Keys.Back || e.KeyCode == Keys.Enter)
       e.Handled = true;
      base.OnKeyDown(e);
     }
    
     protected override void OnKeyPress(KeyPressEventArgs e) {
      // Das Setzen von e.Handled verhindert hier leider nicht 
      // die Verarbeitung der Tastaturanschläge
      if (e.KeyChar == '\b' || e.KeyChar == '\r')
       e.Handled = true;
      base.OnKeyPress(e);
     }
    
     protected override void OnKeyUp(KeyEventArgs e) {
      // Auch hier bleibt e.Handled ohne Effekt
      if (e.KeyCode == Keys.Back || e.KeyCode == Keys.Enter)
       e.Handled = true;
      base.OnKeyUp(e);
     }
    }
    

    Die Overrides sind in der Reihenfolge in der sie aufgerufen werden aufgelistet. Wenn also PreProcessMessage() true zurückgibt, um anzuzeigen, dass es die Nachricht verarbeitet hat, erreicht die Nachricht natürlich die nachfolgenden Handler nicht mehr. Auf welchem Level Du ansetzen möchtest, hängt vom Design Deiner Anwendung ab.

    Gruß
    Marcel


    • Als Antwort vorgeschlagen Marcel RomaModerator Mittwoch, 22. Juni 2011 14:02
    • Als Antwort markiert Floh79 Freitag, 24. Juni 2011 07:54
    Montag, 20. Juni 2011 19:55
    Moderator
  • Hi Marcel,
    vielen Dank für Deine Nachricht. Ich entschied mit folgende Implementierung (ist erst die Anfang ;) ):

    class RichTextBoxRtt : RichTextBox
    {
      protected override bool ProcessCmdKey(ref Message m, Keys keyData)
      {
       switch (keyData)
       {
         case Keys.Return:
          OnKeyPress(new KeyPressEventArgs('\r'));
          return true;
         case Keys.Back:
          OnKeyPress(new KeyPressEventArgs('\b'));
          return true;
         case Keys.Delete:
          //TODO Continue here! OnKeyPress(new KeyPressEventArgs());
          return true;
       }
       return base.ProcessCmdKey(ref m, keyData);
      }
    }

    Ich danke alle für die Hilfe und ich komme mit meine Projekt weiter. :)

    cu Floh

    Mittwoch, 22. Juni 2011 12:41
  • Hi Floh,

    > vielen Dank für Deine Nachricht [...] ProcessCmdKey(ref Message m, Key keyData)

    Gern. Ich freue mich, dass ich Dir helfen konnte.

    Gruß
    Marcel

    Mittwoch, 22. Juni 2011 13:09
    Moderator
  • Hallo Floh,

    • "Ich danke alle" ...

    gern, freut mich.

     


    ciao Frank
    Mittwoch, 22. Juni 2011 13:12