Einzelnen Beitrag anzeigen

Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.062 Beiträge
 
Delphi 12 Athens
 
#10

AW: Mehrere Listboxen synchronisieren

  Alt 19. Jun 2024, 23:50
Für die globale Variable bekommst'e erstmal den Popo verhauen.

Wieso hörst du nicht auf den Compiler?
z.B. [dcc32 Hinweis] H2164 Variable 'i' wurde deklariert, aber in 'TForm1.FormCreate' nicht verwendet

Warum einmal OnMessage über TApplicationEvents auf der Form,
aber dann abweichend OnIdle über das globale Application?
Wenn, dann am Besten beides einheitlich über TApplicationEvents.


Delphi-Quellcode:
  public
    ActiveLB: TListBox;
  end;

var
  Form1: TForm1;
  
implementation

{$R *.dfm}

procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG; var Handled: Boolean);
begin
  if ListBox1.Handle = msg.hwnd then ActiveLB := ListBox1 else
  if ListBox2.Handle = msg.hwnd then ActiveLB := ListBox2 else
  if ListBox3.Handle = msg.hwnd then ActiveLB := ListBox3;
end;

procedure TForm1.ApplicationEvents1Idle(Sender: TObject; var Done: Boolean);
begin
  if Assigned(ActiveLB) then begin
    if ActiveLB <> ListBox1 then ListBox1.TopIndex := ActiveLB.TopIndex;
    if ActiveLB <> ListBox2 then ListBox2.TopIndex := ActiveLB.TopIndex;
    if ActiveLB <> ListBox3 then ListBox3.TopIndex := ActiveLB.TopIndex;
    ActiveLB := nil; // einmal abgearbeitet, dann abschalten, sonst triggert sich das auf ewig immer wieder selbst.
    // in LB1 scrollen löst Scrollen in LB2 und LB3 aus, was wiederum Messages in diesen auslöst usw.
    // Du hast echt Glück, dass im Setter von TopIndex ein "if GetTopIndex <> Value then" steht und es schnell endet
    //
    // PS: also können die "if ActiveLB <> ListBox1 then" weg (ähnlich dem nachfolgenden Beispiel)
  end;
end;
oder einfach alles direkt und umgehend
Delphi-Quellcode:
procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG; var Handled: Boolean);
var
  C: TWinControl;
  //L: TListBox absolute C;
begin
  C := FindControl(msg.hwnd);
  if (C is TListBox) and C.Focused then begin // bzw. falls weitere ListBoxen :: if C.Focused and ((C = ListBox1) or (C = ListBox2) or (C = ListBox3)) then
    //if (ListBox1 <> L) and (ListBox1.TopIndex <> L.TopIndex) then ListBox1.TopIndex := L.TopIndex;
    //if (ListBox2 <> L) and (ListBox2.TopIndex <> L.TopIndex) then ListBox2.TopIndex := L.TopIndex;
    //if (ListBox3 <> L) and (ListBox3.TopIndex <> L.TopIndex) then ListBox3.TopIndex := L.TopIndex;
    // jupp, die Prüfungen weg, siehe Setter von TopIndex
    ListBox1.TopIndex := TListBox(C).TopIndex;
    ListBox2.TopIndex := TListBox(C).TopIndex;
    ListBox3.TopIndex := TListBox(C).TopIndex;
  end;
end;
oder am Besten garnicht ganz global, sondern direkt nur in den ListBoxen, also anstatt OnMessage
Delphi-Quellcode:
type
  TListBox = class(Vcl.StdCtrls.TListBox)
  protected
    // im StandardHandler
    // WM_VSCROLL
    // CN_VSCROLL
    procedure WndProc(var Message: TMessage); override;

    // oder gezielt die gewünschte(n) Message(s) und Notification(s)
    procedure WMVScroll(var Message: TWMVScroll); message WM_VSCROLL; // oder CN_VSCROLL
  end;

  TForm1 = class(TForm)
    ListBox1: TListBox;
    ListBox2: TListBox;
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.

Geändert von himitsu (20. Jun 2024 um 11:33 Uhr)
  Mit Zitat antworten Zitat