Laden...

[gelöst] Ausgewählten Text in TextBox bei erneutem Klick beibehalten

Erstellt von rastalt vor 15 Jahren Letzter Beitrag vor 14 Jahren 1.200 Views
R
rastalt Themenstarter:in
234 Beiträge seit 2007
vor 15 Jahren
[gelöst] Ausgewählten Text in TextBox bei erneutem Klick beibehalten

Hallo zusammen,

ich weiß, es gibt bereits einige Threads zu diesem Thema, aber diese haben mir nicht wirklich weitergeholfen. Auch bei Google finde ich nichts gescheites.

Ich versuche ein Drag & Drop zwischen Textboxen zu realisieren, wobei nur der ausgewählte Text verschoben/kopiert werden soll.

Mein Problem ist folgendes: Ich markiere Text in einer TextBox und um ihn zu verschieben klicke ich in die TextBox und würde dann mit gedrückter Maustaste ein Ziel aussuchen. Allerdings "vergisst" die TextBox die Auswahl sobald man sie wieder anklickt.

Ein gutes Beispiel wie es nicht sein sollte - aber leider ist - ist Notepad. Dort verliert das Eingabefeld auch seine Auswahl sobald man es erneut anklickt.

Was ich erreichen will ist, dass sich die TextBox so verhält wie z.B. der Code-Editor in Visual Studio oder die gerenderten Textboxen in Firefox, IE und Co.

Kennt jemand das Problem und kann mir vielleicht einen Hinweis geben wie ich es Lösen kann? Gerne auch per PInvoke, wobei mir eine "reine Managed-Lösung" natürlich besser gefallen würde.

Ich hoffe ich konnte mein Problem verständlich erklären.

rastalt

/Edit: Ups, hab den Titel nicht ganz ausgefüllt.

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo rastalt,

du kannst dir in RTB.SelectionChanged die jeweils (vor-)letzte Selektion merken und bei Bedarf wiederherstellen (SelectionStart, SelectionLength).

herbivore

R
rastalt Themenstarter:in
234 Beiträge seit 2007
vor 15 Jahren

Ja, das habe ich mir auch überlegt, aber ich bin leider an das Standard TextBox-Control gebunden. Verfolge gerade einen anderen Ansatz und werde meine Lösung dann hier posten.

R
rastalt Themenstarter:in
234 Beiträge seit 2007
vor 14 Jahren

Hier meine (etwas komplexere) Lösung:

/Edit: Danke herbivore, hast mich doch auf den richtigen Weg gebracht.


using System;
using System.Drawing;
using System.Windows.Forms;

class MyTextBox : TextBox
{
	int selectionStart = -1;
	int selectionLength = -1;

	/// <summary>
	/// Tritt ein, wenn die Maustaste losgelassen wird.
	/// </summary>
	protected override void OnMouseUp(MouseEventArgs mevent) {
		base.OnMouseUp(mevent);

		RefreshSelection();
	}

	/// <summary>
	/// Wird aufgerufen, wenn der Mauszeiger über eine Zelle bewegt wird.
	/// </summary>
	protected override void OnMouseEnter(EventArgs e) {
		base.OnMouseEnter(e);

		RefreshSelection();
	}

	/// <summary>
	/// Wird ausgelöst, wenn sich der Mauszeiger über der Form befindet und eine Maustaste gedrückt wird.
	/// </summary>
	protected override void OnMouseDown(MouseEventArgs e) {
		base.OnMouseDown(e);

		if(this.selectionStart != -1 && this.selectionLength != -1) {

			if(this.IsMouseOnSelection(e.Location)) {

				this.Select(this.selectionStart, this.selectionLength);
			}
			else {
				this.RefreshSelection();
			}
		}
	}

	/// <summary>
	/// Bestimmt ob sich die Maus über dem ausgewählten Text befindet
	/// </summary>
	/// <param name="mousePosition">Position der Maus</param>
	/// <returns>True falls die Maus sich über dem ausgewählten Text befindet, sonst false</returns>
	private bool IsMouseOnSelection(Point mousePosition) {

		bool onSelection = false;

		if(this.Text != string.Empty && this.selectionStart != -1 && this.selectionLength != -1) {
			try {
				RectangleF rect = MeasureTextCharacterInRange(this.selectionStart, this.selectionLength);
				PointF mousePositionF = new PointF(mousePosition.X, mousePosition.Y);

				onSelection = rect.Contains(mousePositionF);
			}
			catch(Exception) {
				onSelection = false;
			}
		}

		return onSelection;
	}

	/// <summary>
	/// Misst die Zeichen in der Textbox in einem angegebenen Bereich
	/// </summary>
	/// <param name="start">Index des ersten zu messenden Zeichens</param>
	/// <param name="length">Anzahl der zu messenden Zeichen</param>
	/// <returns>RectangleF welches den Text umschließt</returns>
	private RectangleF MeasureTextCharacterInRange(int start, int count) {
		RectangleF rect = RectangleF.Empty;

		if(this.Text != string.Empty) {
			using(Graphics g = CreateGraphics()) {
				StringFormat format = new StringFormat();
				format.SetMeasurableCharacterRanges(new[] { new CharacterRange(start, count) });

				Region[] regs = g.MeasureCharacterRanges(this.Text, this.Font, new RectangleF(0, 0, this.Width, this.Height), format);

				rect = regs[0].GetBounds(g);
			}
		}

		return rect;
	}

	/// <summary>
	/// Überprüft ob sich die Auswahl beändert hat und merkt sich ggf. die neue Auswahl
	/// </summary>
	private void RefreshSelection() {
		if(this.SelectedText != string.Empty) {
			this.selectionStart = this.SelectionStart;
			this.selectionLength = this.SelectionLength;
		}
		else {
			this.selectionLength = -1;
			this.selectionStart = -1;
		}
	}
}