Autor |
Beitrag |
Määx
      
Beiträge: 123
|
Verfasst: Do 27.06.13 15:54
Hallo zusammen,
ich habe einige Textboxen in denen ich die standard AutoComplete-Funktion nutze. Nun möchte ich diese gern an 2 Stellen erweitern:
Zum einen würde ich gerne einen Autocomplete für Textteile haben. Ich habe also zum Beispiel den Wert "Hallo Herr xyz". Beim tippen von "Herr" sollte dann der Textvorschlag kommen.
Zum anderen möchte ich in einer anderen Textbox Multiline aktivieren und bei jedem Wort die Autocomplete-Funktion nutzen. Also quasi Textbausteine einführen.
Gibt es hier bereits fertige Funktionen, die ich noch nicht gefunden habe oder müsste man sich das selber schreiben? Falls es selbst gemacht werden muss, wie packe ich das Ganze am besten an?
Vielen Dank für eure Hilfe
Määx
|
|
Th69
      

Beiträge: 4795
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Do 27.06.13 19:36
Hallo Määx,
das mußt du auf jeden Fall selber schreiben, da der Standard AutoComplete-Modus nur den Wortanfang (Prefix) beachtet.
Hier ein paar Links (mit Code) dazu:
email-autocomplete
AutoComplete Suggest Box
Create an AutoComplete TextBox Control in C#
Und bei der MultiLine-TextBox müßtest du dann an aktueller Position die ListBox (bzw. DropDownBox) anzeigen.
|
|
Määx 
      
Beiträge: 123
|
Verfasst: Do 25.07.13 10:20
Hey,
erstmal vielen Dank für die Links - die haben mir schonmal sehr geholfen. Leider funktioniert das ganze noch nciht so wie gewünscht:
Der erste Link bietet leider keine SourceCode an, so dass ich diesen nicht nutzen kann (will das selber machen, damit ich auch alles verstehe was da passiert). Der letzte wählt im Prinzip das erste passende Element aus und legt es direkt in die Textbox. Der mittlere macht zwar genau das, was ich will, aber das Textfeld verliert beim öffnen des ToolStripDropDown-Menüs den Focus. Das bedeutet, ich tippe einen Buchstaben und der springt sofort in die ListBox. Einen zweiten Buchstaben kann ich nicht eingeben ohne vorher wieder in das Textfeld zu klciken. Ich möchte jedoch wie beim normalen AutoComplete tippen können bis ich die Listbox auf eine übersichtliche Anzahl an Elementen reduziert habe bzw. wenn das gesuchte Element nicht vorhanden ist einfach weiter tippen bis die Box verschwindet.
Leider bekomme ich das einfach nicht hin. Ich habe this.Focus() bzw. base.Focus() am Ende der OnTextChanged probiert. Auch habe ich dem Opened&GotFocus-Events des toolStrips das Setzen des Fokusses hinzugefügt. Aber egal was ich mache, das TextFeld verliert den Focus und man kann nicht weiter tippen.
Wie kann ich das Problem lösen?
Vielen vielen Dank
Määx
|
|
Th69
      

Beiträge: 4795
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Do 25.07.13 11:13
Hallo Määx,
hast du denn mal den boolschen Rückgabewert von Focus überprüft?
Oder probiere mal
C#-Quelltext
bzw.
C#-Quelltext
aus.
Edit: Ich habe es gerade mal selber ausprobiert und es scheint nicht so einfach zu sein, denn anscheinend kann man, während das ToolStripDropDown (oder der ToolStripControlHost) aktiv ist, nicht einfach den Tastaturfokus ändern.
Selbst ein
C#-Quelltext 1: 2: 3: 4: 5: 6:
| Form form = FindForm(); if (form != null) { form.ActiveControl = null; form.ActiveControl = this; } |
zeigt zwar den Cursor (in der TextBox) an, aber tippen kann man trotzdem nicht.
Erst mit Drücken der "Esc"-Taste kommt man wieder aktiv in die TextBox zurück.
|
|
Määx 
      
Beiträge: 123
|
Verfasst: Do 25.07.13 17:21
Hey,
genau das habe ich auch festgestellt. Meine this.Focus() gab immer true zurück und wenn ich den Focus in der gotFocus der anderen Elemente setze bekam ich ebenfalls den Cursor im Textfeld, nicht aber die Möglichkeit der Tastatureingabe. Erst nach erneutem klick ins Textfeld oder Esc ging dies. Gleichzeitig vercshwindet dann aber auch das ToolStripDropDown. Das ist ja ebenfalls nicht erwünscht
Hat jemand eine Idee wie ich das sonst realisieren könnte? habe schon überlegt ein extra UserControll zu nehmen in dem eine TextBox und eine ListBox sind. Die Größe des Controlls müsste ich dann immer anpassen (oder immer eine Delegate remove/addListBox(ListBox listBox, Point position) anlegen) aber irgendwie gefällt mir diese Lösung nicht wirklich und es muss doch eine elegantere Variante geben?
Vielen Dank für eure Hilfe!!
Määx
|
|
C#
      
Beiträge: 561
Erhaltene Danke: 65
Windows 10, Kubuntu, Android
Visual Studio 2017, C#, C++/CLI, C++/CX, C++, F#, R, Python
|
Verfasst: Do 25.07.13 18:00
Hey
Ich habe mal ein wenig rumgespielt. Ich habe die Autpvervollständigung über ne zweite (Rich)TextBox gemacht. Bei Rich kannste nämlich die gleichen Elemente noch Fett machen oder hervorheben.
Die RichTextBox wandert mit dem Cursor in der TextBox und zeigt immer eine Liste der möglichen Pharsen an. Die Liste wird aus einer List<string> genommen.
Als Form hab ich mal ne einfache Form mit einer TextBox genommen.
Probier mal n bissl rum. Mach ich auch noch nacher wenn ich wieder Zeit hab
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87:
| using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms;
namespace DropDownTest { public partial class Form1 : Form { private RichTextBox boxAutoComplete; private Graphics measureGraphics, autoCompleteMeasureGraphics;
private readonly char[] wordSeperator = {' ', '\n', '\r'}; private List<string> autoCompleteList = new List<string> { "Hallo Herr so und so", "Guten Tag Frau Blau", "Mein Name ist", "Ich wohne in", "Ich bin 2 Jahr alt" };
public Form1() { InitializeComponent(); boxAutoComplete = new RichTextBox {Visible = false, WordWrap = false};
boxAutoComplete.TextChanged += AutoCompleteBoxTextChanged; Controls.Add(boxAutoComplete);
boxAutoComplete.BringToFront(); measureGraphics = boxText.CreateGraphics(); autoCompleteMeasureGraphics = boxAutoComplete.CreateGraphics();
}
private void boxText_TextChanged(object sender, EventArgs e) { string word = GetLastWord();
if (boxAutoComplete.Visible) { SizeF size = measureGraphics.MeasureString(boxText.Lines[boxText.Lines.Length - 1], boxText.Font); Point location = new Point((int) size.Width, (int) (boxText.Lines.Length * boxText.Font.SizeInPoints)); location = PointToClient(boxText.PointToScreen(location)); boxAutoComplete.Location = location; }
string[] possiblePhrases = autoCompleteList.Where(s => s.Contains(word)).ToArray();
if (possiblePhrases.Length == 0) { boxAutoComplete.Visible = false; }
boxAutoComplete.Lines = possiblePhrases; boxAutoComplete.Select(0, boxAutoComplete.Lines[0].Length); boxAutoComplete.Visible = true; }
private void AutoCompleteBoxTextChanged(object sender, EventArgs e) { if (boxAutoComplete.Lines.Length == 0) return;
string longest = ""; foreach (string line in boxAutoComplete.Lines) if (line.Length > longest.Length) longest = line; boxAutoComplete.Width = (int)Math.Round(autoCompleteMeasureGraphics.MeasureString(longest, boxAutoComplete.Font).Width + 0.4f); }
private string GetLastWord() { string s = ""; for (int i = boxText.TextLength - 1; i >= 0; i--) { if (wordSeperator.Any(c => c == boxText.Text[i]) && !String.IsNullOrEmpty(s)) break; s = boxText.Text[i] + s; }
return s; } } } |
_________________ Der längste Typ-Name im .NET-Framework ist: ListViewVirtualItemsSelectionRangeChangedEventHandler
|
|
Määx 
      
Beiträge: 123
|
Verfasst: Fr 26.07.13 09:22
klasse, vielen Dank!
Ich werde mal damit rumspielen und mich hier noch ienmal melden!
|
|
Määx 
      
Beiträge: 123
|
Verfasst: Fr 26.07.13 15:43
Hey,
also vom Grundprinzip klappt das so. Ich habe jetzt die richTextBox durch eine ListBox ersetzt und mit etwas mühe könnte man sicherlich quasi die AutoComplete Funktionalität erzielen...
Aber jetzt habe ich das Problem, dass ich das ja in jedem UserControll neu erstellen müsste, da ich ja die ListBox immer anlegen muss...
Hier meine modifizierte Version:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94:
| private ListBox listBoxAutoComplete; private Graphics measureGraphics, autoCompleteMeasureGraphics;
private readonly char[] wordSeperator = { ' ', '\n', '\r' }; private List<string> autoCompleteList = new List<string> { "Hallo Herr so und so,", "Guten Tag Frau Blau", "Mein Name ist", "Ich wohne in", "Ich bin 2 Jahr alt" };
public Form1() { InitializeComponent();
listBoxAutoComplete = new ListBox { Visible = false }; listBoxAutoComplete.KeyDown += AutoCompleteBoxKeyDown; Controls.Add(listBoxAutoComplete);
listBoxAutoComplete.BringToFront(); measureGraphics = boxText.CreateGraphics(); autoCompleteMeasureGraphics = listBoxAutoComplete.CreateGraphics(); }
private void AutoCompleteBoxKeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Escape) { listBoxAutoComplete.Visible=false; boxText.Focus(); return; }
if (e.KeyCode == Keys.Enter) { boxText.Text += listBoxAutoComplete.SelectedItem.ToString(); boxText.Focus(); return; } } private void boxText_TextChanged(object sender, EventArgs e) { if (!boxText.Text.Trim().Equals("")) { listBoxAutoComplete.Items.Clear(); string word = GetLastWord();
if (listBoxAutoComplete.Visible) { SizeF size = measureGraphics.MeasureString(boxText.Lines[boxText.Lines.Length - 1], boxText.Font); Point location = new Point((int)size.Width, (int)(boxText.Lines.Length * boxText.Font.SizeInPoints)); location = PointToClient(boxText.PointToScreen(location)); listBoxAutoComplete.Location = location; }
string[] possiblePhrases = autoCompleteList.Where(s => s.ToLower().Contains(word.ToLower())).ToArray();
if (possiblePhrases.Length == 0) { listBoxAutoComplete.Visible = false; return; } foreach (string s in possiblePhrases) listBoxAutoComplete.Items.Add(s); listBoxAutoComplete.Visible = true; } else listBoxAutoComplete.Visible = false; } private string GetLastWord() { string s = ""; for (int i = boxText.TextLength - 1; i >= 0; i--) { if (wordSeperator.Any(c => c == boxText.Text[i]) && !String.IsNullOrEmpty(s)) break; s = boxText.Text[i] + s; }
return s; } private void boxText_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Down || e.KeyCode == Keys.Up) { if (listBoxAutoComplete.Visible) { listBoxAutoComplete.SetSelected(0, true); e.SuppressKeyPress = true; listBoxAutoComplete.Focus(); } } } |
Gibt es eine Möglichkeit das Ganze jetzt irgendwie als CustomAutocompleteTextBox zu verpacken, damt ich es überall schnell&infach nutzen kann?
|
|
C#
      
Beiträge: 561
Erhaltene Danke: 65
Windows 10, Kubuntu, Android
Visual Studio 2017, C#, C++/CLI, C++/CX, C++, F#, R, Python
|
Verfasst: Fr 26.07.13 16:27
Wenn ich dich richtig verstanden habe, meinst du ein custom control.
Hier mal ein Beispiel (hab jetzt nicht alles übernommen):
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87:
| using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Forms;
namespace DropDownTest { public class AutoCompleteBox : ListBox { public List<string> AutoCompleteList { get; set; } public List<char> WordSeperator { get; set; }
public new bool AutoSize { get; set; } public TextBoxBase BasedTextBox { get { return basedTextBox; } set { basedTextBox = value; value.KeyDown += OnAnyKeyDown; } }
private TextBoxBase basedTextBox;
public AutoCompleteBox() { Initialize(); }
public AutoCompleteBox(TextBoxBase textBox) { Initialize(); BasedTextBox = textBox; }
private void Initialize() { AutoCompleteList = new List<string>(); WordSeperator = new List<char>();
KeyDown += OnAnyKeyDown; }
private void OnAnyKeyDown(object sender, KeyEventArgs e) { if (Visible) { if (e.KeyCode == Keys.Down && SelectedIndex > 0) { SelectedIndex++; e.SuppressKeyPress = false; } else if (e.KeyCode == Keys.Up && SelectedIndex < Items.Count - 1) { SelectedIndex--; e.SuppressKeyPress = false; }
else if (e.KeyCode == Keys.Escape) Hide(); else if (e.KeyCode == Keys.Enter) { basedTextBox.Text = basedTextBox.Text.Insert(0, (string)SelectedItem); } } }
public new void Show() { Visible = true; }
public new void Hide() { Visible = false; } } } |
/// Nachtrag
So kannst du nach dem ersten Build auch das Control im GUI Editor von Visual Studio nutzen (ich glaube unter Eigene Controls). Dann kannste das Teil einfach auf dein Design drauf ziehen.
_________________ Der längste Typ-Name im .NET-Framework ist: ListViewVirtualItemsSelectionRangeChangedEventHandler
|
|
Määx 
      
Beiträge: 123
|
Verfasst: Di 30.07.13 08:42
Super! Funktioniert insgesamt genau so wie ich es mir vorgestellt habe - vor allem kann man so vorhandene Textfelder einfach um diese Funktionalität ergänzen
Das einzige "Problem" ist, dass man bei Textfeldern, die in einem UserControl ganz untenangeordnet sind die ListBox nicht mehr angezeigt bekommt, da sie ja über die Grenze des UserControls rausragt...
Gibt es hier eine Möglichkeit so eine Art globales bringToFront() aufzurufen?
Vielen Dank für eure hilfreichen Tipps!!
Määx
|
|
C#
      
Beiträge: 561
Erhaltene Danke: 65
Windows 10, Kubuntu, Android
Visual Studio 2017, C#, C++/CLI, C++/CX, C++, F#, R, Python
|
Verfasst: Di 30.07.13 11:54
Ja genau deswegen hab ich das mit PointToScreen() und PointToClient() gemacht. So kannst du nämlich die ListBox direkt der Form unterordnen. Die Position wird trotz allem passend ausgerechnet und es kann über die Grenzen des Textfeldes angezeigt werden.
_________________ Der längste Typ-Name im .NET-Framework ist: ListViewVirtualItemsSelectionRangeChangedEventHandler
|
|
Määx 
      
Beiträge: 123
|
Verfasst: Do 01.08.13 16:16
Hey,
also ich habe jetzt alles ausprobiert. Auch mit dem PointToClient. Aber bei dem PointToClient wird das Feld genauso an den Grenzen des UserControls abgeschnitten, da die angezeigte ListBox ja diesem zugeordnet ist und nicht dem "höchsten" Element. Außerdem springt bei dem PointToClient die Box immer zwischen den beiden Positionen über/unter der aktuellen Zeile hin und her!
Also irgendwas mache ich da falsch - auch wenn mir absolut nicht klar ist was?
Hier meine entsprechende Codestelle:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| public new void Show() { if (!basedTextBox.Text.Trim().Equals("")) { SizeF size = graphicsTextBox.MeasureString(basedTextBox.Lines[basedTextBox.Lines.Length - 1], basedTextBox.Font); Point location = new Point((int)size.Width, (int)(basedTextBox.Lines.Length * basedTextBox.Font.SizeInPoints)); location = PointToClient(basedTextBox.PointToScreen(location)); Location = location; Visible = true; } else Hide(); } |
und hier noch im ganzen:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131:
| public partial class AutoCompleteBox : ListBox { private Graphics graphicsTextBox; public List<string> AutoCompleteList { get; set; } private readonly char[] WordSeperator = { ' ', '\n', '\r' };
public new bool AutoSize { get; set; } private TextBoxBase basedTextBox; public TextBoxBase BasedTextBox { get { return basedTextBox; } set { basedTextBox = value; graphicsTextBox = value.CreateGraphics(); value.KeyDown += OnAnyKeyDown; value.Click += new EventHandler((sender, arg) => Hide()); } } public AutoCompleteBox() { Initialize(); } public AutoCompleteBox(TextBoxBase textBox) { Initialize(); BasedTextBox = textBox; } private void Initialize() { Visible = false; AutoCompleteList = new List<string>(); KeyDown += OnAnyKeyDown; }
private void OnAnyKeyDown(object sender, KeyEventArgs e) { string word = GetLastTypedWord(); if (word.Length > 0) { if (e.KeyCode != Keys.Down && e.KeyCode != Keys.Up && e.KeyCode != Keys.Enter && e.KeyCode != Keys.Escape) { Items.Clear(); string[] possiblePhrases = AutoCompleteList.Where(s => s.ToLower().Contains(word.ToLower())).ToArray();
if (possiblePhrases.Length == 0) { Hide(); return; } string longestLine = ""; foreach (string s in possiblePhrases) { Items.Add(s); if (s.Length > longestLine.Length) longestLine = s; } Width = (int)Math.Round((CreateGraphics()).MeasureString(longestLine, Font).Width + 0.4f); Show(); }
if (Visible && Items.Count > 0) { if (e.KeyCode == Keys.Down) { if (SelectedIndex < Items.Count - 1) SelectedIndex++; else SelectedIndex = 0; e.SuppressKeyPress = true; } else if (e.KeyCode == Keys.Up) { if (SelectedIndex > 0) SelectedIndex--; else SelectedIndex = Items.Count - 1; e.SuppressKeyPress = true; } else if (e.KeyCode == Keys.Escape) Hide(); else if (e.KeyCode == Keys.Enter && SelectedItem != null) { int selectionStatIndex = basedTextBox.SelectionStart - word.Length; basedTextBox.Text = basedTextBox.Text.Remove(selectionStatIndex, word.Length); basedTextBox.Text = basedTextBox.Text.Insert(selectionStatIndex, (string)SelectedItem); basedTextBox.SelectionStart = selectionStatIndex + ((string)SelectedItem).Length; e.SuppressKeyPress = true; Hide(); } } } else Hide(); } private string GetLastTypedWord() { string s = ""; for (int i = basedTextBox.SelectionStart - 1; i >= 0; i--) { if (WordSeperator.Any(c => c == basedTextBox.Text[i]) && !String.IsNullOrEmpty(s)) break; s = basedTextBox.Text[i] + s; } return s; }
public new void Show() { if (!basedTextBox.Text.Trim().Equals("")) { SizeF size = graphicsTextBox.MeasureString(basedTextBox.Lines[basedTextBox.Lines.Length - 1], basedTextBox.Font); Point location = new Point((int)size.Width, (int)(basedTextBox.Lines.Length * basedTextBox.Font.SizeInPoints)); location = PointToClient(basedTextBox.PointToScreen(location)); Location = location; Visible = true; } else Hide(); } public new void Hide() { Visible = false; } } |
Hab ihr noch eine Idee?
Vielen Dank
Määx
Edit: achso, die ListBox wird an den Grenzen des UserControls abgeschnitten in dem die TextBox liegt, nicht an den Grenzen der TextBox. Nicht dass da ein Mißverständnis vorlag?
Vielen Dank!
|
|
Th69
      

Beiträge: 4795
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Do 01.08.13 16:28
Hallo Määx,
du solltest dann die ListBox eher der Form (FindForm()) zuordnen (macht aber nur Sinn, wenn die Form auch größer ist als das UserControl).
Ansonsten kannst du es auch versuchen, es dem globalen Screen (Desktop) zuzuordnen, aber dies geht m.E. nur per WinAPI-Funktion SetParent.
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Do 01.08.13 16:31
Oder die Listbox gleich in eine eigene Form (Borderless) packen.
|
|
Määx 
      
Beiträge: 123
|
Verfasst: Do 01.08.13 17:11
Zitat: | Oder die Listbox gleich in eine eigene Form (Borderless) packen. |
Das klingt am besten  Aber wie? Also wenn ich in meinem CustomControl eine Form erzeuge und der TextBox zuordne liegt die Form ja wieder nur in dem UserControl oder?
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Do 01.08.13 18:01
Nö. Ich würde die AutoCompleteBox Klasse einfach nicht von ListBox ableiten. Sondern die Klasse enthält einfach eine Form mit einer Listbox drauf.
Das sollten gefühlt nur ein paar einfache Überarbeitungen der AutoCompleteBox Klasse sein.
|
|
C#
      
Beiträge: 561
Erhaltene Danke: 65
Windows 10, Kubuntu, Android
Visual Studio 2017, C#, C++/CLI, C++/CX, C++, F#, R, Python
|
Verfasst: Do 01.08.13 18:06
Ja das mit dem Springen ist mir auch aufgefallen. Weis aber nicht woran das liegt...
Kurz geschrieben (den restlichen Code musste hald einfügen mittels copy & paste
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66:
| using System; using System.Collections.Generic; using System.ComponentModel.Design.Serialization; using System.Drawing; using System.Windows.Forms;
namespace DropDownTest { internal class AutoCompleteForm : Form { public List<string> AutoCompleteList { get; set; } public List<char> WordSeperator { get; set; }
public new bool AutoSize { get; set; }
public TextBoxBase BasedTextBox { get { return basedTextBox; } set { if (basedTextBox != null) { basedTextBox.KeyDown -= OnAnyKeyDown; basedTextBox.TextChanged -= OnBaseBoxTextChanged; }
basedTextBox = value; basedTextBox.KeyDown += OnAnyKeyDown; basedTextBox.TextChanged += OnBaseBoxTextChanged;
baseGraphics = basedTextBox.CreateGraphics(); } }
private ListBox box; private TextBoxBase basedTextBox; private Graphics baseGraphics, myGraphics;
public AutoCompleteForm() { FormBorderStyle = FormBorderStyle.None; SizeGripStyle = SizeGripStyle.Show; MinimumSize = new Size(10, 10); MaximumSize = new Size(100, 100);
box = new ListBox {Dock = DockStyle.Fill}; Controls.Add(box); }
private void OnBaseBoxTextChanged(object sender, EventArgs e) { }
private void OnAnyKeyDown(object sender, KeyEventArgs e) { } } } |
_________________ Der längste Typ-Name im .NET-Framework ist: ListViewVirtualItemsSelectionRangeChangedEventHandler
|
|
Määx 
      
Beiträge: 123
|
Verfasst: Fr 02.08.13 08:37
Hallo zusammen,
erstmal Danke für eure schnelle Hilfe! Aber leider glaube ich dass ich irgendetwas grundlegendes nicht verstanden habe
Ich habe das nun in eine Form gepackt und es waren tatsächlich nur wenige Änderungen.
Dann habe ich dem UserControl eine private AutoCompleteForm autocompleteForm; hinzugefügt, die ich dann im Konstruktor des Controls initialisiere:
C#-Quelltext 1:
| autocompleteForm = new AutoCompleteForm(textBoxAnschreiben); |
Wenn ich jetzt etwas im Textfeld eingebe wird auch direkt die Form angezeigt - so weit so gut. Aber leider bekommt diese auch sofort den Focus, so dass ich ja nicht mehr weiter tippen kann? Setze ich den Focus jetzt wieder auf die TextBox verschwindet die Form logischerwese im Hintergrund... gibt es da einen Trick oder müsste ich in der KeyDown "einfach" alles an die TextBox anhängen?
Vielen Dank!
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Fr 02.08.13 09:42
Beim anzeigen der AutoCompleteForm solltest du einen Parent mitgeben (z.B. die Form auf der die Textbox liegt) damit die AutoCompleteForm immer davor angezeigt wird.
Das mit dem Focus habe ich nicht bedacht das sollte mit ein wenig Bastelei aber auch möglich sein. Der Anfang wäre in der AutoCompleteForm die ShowWithoutActivation Property zu überschreiben und da immer true zurückzugeben.
|
|
C#
      
Beiträge: 561
Erhaltene Danke: 65
Windows 10, Kubuntu, Android
Visual Studio 2017, C#, C++/CLI, C++/CX, C++, F#, R, Python
|
Verfasst: Fr 02.08.13 12:23
oder du benutzt TopMost um die Form einfach im Vordergrund zu halten. Wenn die Applikation den Fokus verliert solltest du TopMost wieder zurücksetzen, damit andere Programme fokussiert werden können.
_________________ Der längste Typ-Name im .NET-Framework ist: ListViewVirtualItemsSelectionRangeChangedEventHandler
|
|
|