Hallo zusammen,
hat perfekt funktioniert. Der Lösungsansatz über "GetTabOrderList" war perfekt.
Ich habe das nun folgendermaßen implementiert (falls mal jemand was ähnliches machen will):
Zum Verwalten der Tabulatorreihenfolgen habe ich folgende Member angelegt:
Delphi-Quellcode:
FCols: Integer; // Number of input columns.
FActiveCol: Integer; // The active column to tab through.
FTabOrders: TArray<TArray<TWinControl>>; // The TabOrderLists for the columns.
In "TabOrders" speichere ich die Reihenfolge für die verschiedenen möglichen Spalten. Diese werden dann einfach in "GetTabOrderList" aktiviert, je nach Wert in "FActiveCol":
Delphi-Quellcode:
procedure TFrameQnr.GetTabOrderList(List: TList);
// Get the actual (prepared) tab order.
begin
for var P in FTabOrders[FActiveCol] do
List.Add(P);
end;
Jedem der Inout-Controls habe ich noch ein "OnMouseDown" und ein "OnKeyDown" verpasst. Klickt der Benutzer in eine bestimmte Spalte, so wird diese in den Listen gesucht und als aktiv gesetzt:
Delphi-Quellcode:
procedure TFrameQnr.OnDBEditMouseDown(ASender: TObject; AButton: TMouseButton; AShift: TShiftState; AX, AY: Integer);
// Switch the active column if a DBEdit is selected by mouse click.
begin
// Find the first column that contains the control.
for var ColIndex := 0 to High(FTabOrders) do
for var Control in FTabOrders[ColIndex] do
if ASender = Control then
begin
FActiveCol := ColIndex;
Exit;
end;
end;
Hatte das Anfang über die "Tag"-Eigenschaft gemacht, diese verwende ich aber nur sehr ungerne.
Da ich immer auch eine tastaturbasierte Lösung bereitstelle habe ich in "OnKeyDown" die Möglichkeit geschaffen die Spalte über Hotkeys zu wechseln:
Delphi-Quellcode:
procedure TFrameQnr.OnDBEditKeyDown(ASender: TObject;
var AKey: Word; AShift: TShiftState);
// Enable <Ctrl><Tab> and <Ctrl><Shift><Tab> to change the active column.
function GetActiveControlIndex: Integer;
begin
for var I := 0
to High(FTabOrders[FActiveCol]) - 1
do
if FTabOrders[FActiveCol][I] = TControl(ASender)
then
Exit(I);
Result := -1;
end;
procedure SetActiveControlIndex(AIndex: Integer);
begin
if (AIndex >= 0)
then
FTabOrders[FActiveCol][AIndex].SetFocus;
end;
var
Index: Integer;
begin
if AKey = VK_TAB
then
begin
if AShift = [ssCtrl]
then // next column
begin
Index := GetActiveControlIndex;
if (FActiveCol < FCols - 1)
and (FTabOrders[FActiveCol][
Index] <> FTabOrders[FActiveCol + 1][
Index])
then
begin
Inc(FActiveCol);
SetActiveControlIndex(
Index);
end;
AKey := 0;
end
else if AShift = [ssCtrl, ssShift]
then // previous column
begin
Index := GetActiveControlIndex;
if (FActiveCol > 0)
and (FTabOrders[FActiveCol][
Index] <> FTabOrders[FActiveCol - 1][
Index])
then
begin
Dec(FActiveCol);
SetActiveControlIndex(
Index);
end;
AKey := 0;
end;
end;
end;
Das war es im Wesentlichen schon. Am aufwendigsten war die ursprüngliche Erstellung der Arrays mit den Reihenfolgen. Diese ist aber sehr programmspezifisch und es macht keinen Sinn, dass ich diese hier poste.
In diesem Sinne. Nochmal vielen Dank für eure tolle Unterstützung.
Alex
Man sollte nie so viel zu tun haben, dass man zum Nachdenken keine Zeit mehr hat. (G.C. Lichtenberg)