Laden...

Forenbeiträge von Anchiko Ingesamt 12 Beiträge

22.02.2021 - 07:18 Uhr

Hallo Abt,

vielen Dank für Deine Antwort.

Ich stehe jetzt etwas auf dem Schlauch: was meinst Du mit "..an allen eigenen Controls..."?

Ich dachte, wenn der Column als CellTemplate meine eigene TextBoxCell hinterlegt ist, dass dann automatosch dieses Objekt verwendet wird. Oder muss ich es so verstehen, dass bei jedem Instanziieren der TextBoxCell meine eigene TextBoxCell angegeben werden muss? Wenn ja, wo muss ich ansetzen?

Danke und Grüße
Anchiko

21.02.2021 - 19:34 Uhr

Hallo,

ich habe ein ungebundenes DataGridView-Objekt erstellt und möchte auf Tatstureingaben in einer DataGridViewTextBoxCell reagieren (Framework .NET 5.0).

Ich bin dabei inhaltlich so vorgegangen wie es hier beschrieben wird:

  1. Ich habe ein eigenes DataGridviewTextBoxCell-Objekt erstellt und die OnKeyDown-Methode überschrieben:

    public class EigeneDataGridViewTextBoxCell : DataGridViewTextBoxCell
    {
        public EigeneDataGridViewTextBoxCell() : base() {  }

        protected override void OnKeyDown(KeyEventArgs e, int rowIndex)
        {
            base.OnKeyDown(e, rowIndex);
            // weitere Bearbeitung
        }
    }

  1. Ich habe ein eigenes DataGridViewColumn-Objekt erstellt:

    public class EigeneDataGridViewColumn: DataGridViewColumn
    {
        public EigeneDataGridViewColumn() : base() 
        {
            CellTemplate = new EigeneDataGridViewTextBoxCell();
        }
    }

  1. Diese eigene Spaltenart habe ich meinem DataGridView-Objekt hinzugefügt:

EigeneDataGridViewColumn spalte = new EigeneDataGridViewColumn()
{
    Name = "DGVCTest",
    HeaderText = "Test"
};
dataGridView1.Columns.Add(spalte);

Leider wird die OnKeyDown-Methode meines "EigeneDataGridViewTextBoxCell"-Objekts nie aufgerufen.

Was mache ich falsch?

Vielen Dank im Voraus!

25.04.2020 - 18:42 Uhr

Wow. Hut ab. Und er verwendet ein ToolStripDropDown...

Herzlichen Dank!

25.04.2020 - 16:38 Uhr

Hi,

vielen Dank für Deine Hinweise.

Der Tip mit WS_EX_NOACTIVATE funktioniert bei mir nicht. Das übergeordnete Fenster bekommt nach wie vor die Deactivate-Ereignisse.

Hier der Code des Auswahlfensters:


public partial class AuswahlFenster : Form
{
    private const int WS_EX_NOACTIVATE = 0x8000000;

    public NamenTextbox Box { get; set; }

    public AuswahlFenster()
    {
        InitializeComponent();
    }

    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams baseParams = base.CreateParams;
            baseParams.ExStyle |= WS_EX_NOACTIVATE;
            return baseParams;
        }
    }

    private void AuswahlFenster_Shown(object sender, EventArgs e)
    {
        if (Box != null) Box.Focus();
    }

    private void Liste_SizeChanged(object sender, EventArgs e)
    {
        Size = new Size(AuswahlListe.Width, AuswahlListe.Height);
    }

    public ListBox Liste()
    {
        return AuswahlListe;
    }
}

Bei InitializeComponent() werden folgende Einstellungen für das Fenster vorgenommen:


this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 16F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(200, 116);
this.ControlBox = false;
this.Controls.Add(this.AuswahlListe);
this.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "AuswahlFenster";
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
this.Text = "AuswahlFenster";
this.TopMost = true;
this.Shown += new System.EventHandler(this.AuswahlFenster_Shown);

Das Abfangen der Scrollereignisse führt auch nicht zum Ziel, weil das Deactivate-Ereignis vor den Scroll-Ereignissen gesendet wird, so dass die Liste schon nicht mehr existiert, um ein Scrollereignis bekommen zu können. Ich drehe mich im Kreis.

Aber vielen Dank für Deine Hilfe!
Anchiko

25.04.2020 - 11:37 Uhr

OK, entschuldige, ich stecke zu tief in der Materie.

Mein Problem ist: wenn ich auf die Scrollleiste klicke verschwindet die Liste.

Das liegt an folgendem Ereignishandler für Deactivate:


public class NamenTextbox : TextBox
.
.
.
protected virtual void HauptfensterDeaktivieren(object sender, EventArgs e)
{
    if (DeaktivierendurchAuswahlfenster) return;
    AuswahlZurücksetzen(sender, e);
    if (Vorschlag)
    {
        if (SelectionLength > 0) TextSetzen(Text.Remove(SelectionStart));
        TextBoxSelPosLeave = Text.Length;
        Vorschlag = false;
    }
    AuswahlWiederAktivieren = true;
}

protected virtual void HauptfensterAktiviert(object sender, EventArgs e)
{
    if (AuswahlWiederAktivieren)
    {
        AuswahlPositionStart = TextBoxSelPosLeave;
        TBTextChanged(sender, e);
        AuswahlWiederAktivieren = false;
    }
}

protected virtual void NTBParentWechsel(object sender, EventArgs e)
{
    if (TopLevelControl != null && !TopLevelControlGesetzt)
    {
        TopLevelControl.LocationChanged += new EventHandler(AuswahlAnpassen);
        if (TopLevelControl is Form)
        {
            ((Form)TopLevelControl).Activated += new EventHandler(HauptfensterAktiviert);
            ((Form)TopLevelControl).Deactivate += new EventHandler(HauptfensterDeaktivieren);
        }
        TopLevelControl.Disposed += new EventHandler(AuswahlZurücksetzen);
        TopLevelControlGesetzt = true;
   }
   else
   {
       Control parent = Parent;
       while (parent != null)
       {
           parent.ParentChanged += new EventHandler(NTBParentWechsel);
           parent = parent.Parent;
       }
   }
}

protected virtual void AuswahlZurücksetzen(object sender, EventArgs e)
{
    Auswahl?.Dispose();
    Auswahl = null;
    Auswahlliste = null;
}

public virtual void NTBListboxMouseEnter(object sender, EventArgs e)
{
    DeaktivierendurchAuswahlfenster = true;
}

public virtual void NTBListboxMouseLeave(object sender, EventArgs e)
{
    DeaktivierendurchAuswahlfenster = false;
}

public virtual void NTBListboxClick(object sender, EventArgs e)
{
    Focus(); // Fokus auf die Textbox
    if (Auswahlliste == null || Auswahlliste.SelectedItem == null || SelectionStart + SelectionLength != TextLength) return;
    Namenvorschlagen();
}

public virtual void NTBListboxDoubleClick(object sender, EventArgs e)
{
    if (Auswahlliste!= null && Auswahlliste.SelectedItem != null)
    {
        Namen name = (Namen)Auswahlliste.SelectedItem;
        if (name != null) TextSetzen(name.Text);
        SelectionLength = 0;
        SelectionStart = TextLength;
        TextBoxSelPosLeave = TextLength;
        VorschlagBeenden();
        Focus(); // Fokus auf die Textbox
    }
}

Meine Liste ist eine Form mit einer ListBox (siehe Bild1 im Anhang).

Da aber eben meiner Liste eine Form zugrundeliegt, wird jedes Mal, wenn mit der Maus in die Liste geklickt wird, diese Form aktiviert und das TopLevelControl erhält das Deactivate-Ereignis, was wiederum die Liste bzw. die Form schließt.

Deshalb habe ich die oben angegebenen Ereignishandler für MouseEnter und MouseLeave der Auswahlliste hinzugefügt.

Es funktioniert:

  • das Scrollen in der Liste mit den Pfeil-Tasten hoch und runter, wobei diese Tasten gedrückt werden, wenn die Textbox den Fokus hat (habe ich über das KeyDown-Ereignis gesteuert)
  • das Scrollen mit der mittleren Maus-Taste/Mausrad (wahrscheinlich, weil die Liste hierbei nicht den Fokus und somit das TopLevelControl kein Deactivate-Ereignis erhält)
  • das Klicken in die Liste

Wenn ich aber auf die Scrollleiste klicke, verschwindet die Liste. Das "Warum" ist mir klar (Deactivate-Ereignis des TopLevelControl, siehe oben).

Und ich denke, dass ich das vermeiden könnte, wenn ich der Scrollleiste Mouse- und Click-Ereignishandler anfügen könnte. Dafür brauche ich aber Zugriff auf die Scrollleiste.

24.04.2020 - 18:56 Uhr

Falls das Thema noch aktuell ist:

Sind Deine Textboxen direkt auf der obersten Ebene der Form angebracht oder liegen Sie in GroupBoxen oder ähnlichem?

24.04.2020 - 18:43 Uhr

Wenn das ausgewählte Element einer ListView geändert wird - wenn vorher schon ein anderes Element ausgewählt wurde - wird zweimal das SelectedIndexChanged-Ereignis aufgerufen.

Das erste Mal ohne das es ein ausgewähltes Element gibt, weshalb Du wahrscheinlich die Exception erhältst. Und dann ein zweites Mal mit dem neu ausgewählten Element.

Prüf das mal im Debugger.

24.04.2020 - 18:30 Uhr

Die Liste erhält eigentlich nie den Fokus. Das Scrollen mit der mittleren Maustaste(Mausrad) funktioniert ohne Probleme (zumindest an meinem Rechner).

Beim Einfach- und beim Doppelklick mit der Maus wird der Fokus von der Liste sofort wieder an die Textbox zurückgegeben.

Dadurch wird beim übergeordneten Fenster ständig das Deactivate und Activated-Ereignis ausgelöst. Da ich beim Deactivate-Ereignis das Fenster mit der Liste schließe, habe ich über die Ereignisse MouseEnter und MouseLeave ein Kennzeichen gesetzt, damit das Listenfenster nicht geschlossen wird, wenn die Maus über ihr ist.

Diese Mouse-Ereignisse kennt (natürlich) auch die Scrollbar, was man ja daran erkennt, dass die Buttons der Scrollleiste ihre Farbe ändern, wenn man die Maus über sie bewegt.

Ich habe auch überlegt das WM_VSCROLL-Ereignis abzufangen und zu prüfen, ob der lParam-Wert der Message, das Handle der Scrollbar übergibt, um dann über das Handle auf das Objekt zugreifen zu können. Aber ich habe nichts gefunden, wie man über das Handle eines Control-Objekt auf dieses zugreifen kann und ich glaube, das soll auch so sein. Außerdem habe ich festgestellt, dass das Deactivate-Ereignis vor dem WM_VSCROLL-Ereignis gesendet wird, so dass mir das auch nichts bringen würde.

24.04.2020 - 12:07 Uhr

Hallo Th69,

vielen Dank für Deine Antwort. Ich verwende .Net -Framework 4.8, aber das hat sich ja bald erledigt (.Net 5 ab November 2020).

Ich habe Deinen Hinweis umgesetzet allerdings Strg(^) durch Umschalt(+) ersetzt:

SendKeys.Send("{TAB}+{TAB}");

Grüße
Anchiko

24.04.2020 - 11:59 Uhr

Hallo Th69,

vielen dank für Deine Antwort. Die Funktion AutoCompleteMode habe ich in der Tat noch nicht gekannt. Ich habe mir Deine Links angesehen und bin schnell an dem Punkt angekommen, warum ich den Standard nicht nutzen möchte.

Aus folgenden Gründen, habe ich eine indivuelle Liste erstellt;

  • Ich möchte die Liste selber Zeichnen (DrawMode = OwnerDraw).
  • Ich möchte die Liste selber positionieren. Dabei soll es auch ein Wechsel zwsichen linkem und rechtem "Anschlag" der Liste unter- oder oberhalb der Textbox geben je nach dem wo sich das Fenster gerade befindet.
  • Die Liste soll über das Formular hinaus angezeigt werden können.
  • Die Liste enthält von mir definierte Klassen, keine reinen String-Objekte.

Ich hatte es schon damit probiert, nur eine Listbox im jeweiligen Formular zu erzeugen (Stichwort BringToFront). Damit habe ich fast alles lösen können, nur nicht den Punkt, dass die Listbox über die Begrenzungen des Fensters hinaus angezeigt wird, wie es z.B. bei einer ComboBox der Fall ist. Deswegen habe ich ein Fenster mit der Liste erstellt und in meiner von TextBox abgeleiteten Namen-Textbox die Steuerung implemetiert (z.B. Reaktion auf die Pfeil-Tasten). Klappt alles so, wie ich es möchte. Nur eben nicht des Scrollen mit der Maus mit der vertikalen Scrollleiste.

Viele Grüße
Anchiko

23.04.2020 - 22:39 Uhr

Hallo,

ich versuche auf die (automatische) vertikalen Scrollleiste einer Listbox zuzugreifen. Genauer gesagt würde ich gerne den Ereignissen MouseEnter bzw. MosueLeave einen eigenen Ereignishandler anhängen.

Nach allem, was ich bisher gelesen habe, gibt es aber wohl keine Möglichkeit dies zu tun.

Hintergrund meines Problems ist, dass ich eine Textbox mit einem Form verknüpft habe, das nur aus einer Listbox besteht (kein Rahmen etc.) in der Textvorschläge erscheinen sollen in Abhängkeit vom bisher eingebenen Text. Das klappt auch alles soweit sehr gut.

Damit die Liste (die Form) im Vordergrund angezeigt wird, habe ich die Eigenschaft der Form mit der Liste auf TopMost = true gesetzt.

Damit die Liste dann (unter anderem) verschwindet, wenn das übergeordnete Fenster nicht mehr das aktive Fenster ist (und umgekehrt), habe ich dem übergeordneten Fenster einen ErgeinisHandler für Deactivate (bzw. Activated) angehängt. Klappt alles soweit.

Wenn ich dann in die Liste klicke verschwand bisher die Liste, was mir dann auch klar war wegen des oben genannten Ereignishandler für Deactivate für das übergeordnete Fenster.

Das konnte ich abfangen mit Ereignishandler für MouseEnter und MouseLeave für die Listbox. Nur dies hat leider keine Wirkung auf die vertikale Scrollleiste.

Gibt es vielleicht doch eine Möglichkeit der Scrollleiste eigene Ereignishandler anzuhängen?

Vielen Dank im Voraus!
Anchiko

23.04.2020 - 21:51 Uhr

Hallo,

wenn ein Fenster angezeigt wird und das erste Control-Element eine Checkbox oder ein Radiobutton ist, erhält dieses Control kein Fokus-Rechteck, obwohl es den Fokus hat.

Dasselbe Verhalten ist mir aufgefallen, wenn ich durch die Control-Liste mit SelectNextControl wechsle.

Habe ich aber einmal die Tab-Taste gedrückt oder mit SendKeys.Send("{TAB}") dieses Ereignis ausgelöst, wird ein Fokusrechteck gezeichnet, wenn ich wieder mit SelectNextControl durch die Controls wechsle.

Ich habe auch versucht mit ControlPaint.DrawFocusRectangle das Zeichnen des Fokus-Rechtecks auszulösen, hat aber keine Wirkung gezeigt.

Hat jemand eine Idee, wie ich von Anfang an ein Fokus-Rechteck für Checkboxen und Radiobuttons erhalte?

Vielen Dank im Voraus!
Anchiko