Комментарии:
I don't like manually managing the tab order of the components I place on a form. When I statically place a component, I've always expected the tab flow to follow how English is read. Left to Right, Top to Bottom. I don't ever want to go back to a form and have to manhandle it again, which I admit would be useful for some, but never for me.
Disclaimer; This code I wrote relies on SQLite to do the sorting. Most of the tools I write deal with this database engine, so, adding an extra layer for one-time init is acceptable IMO.
I have a single stand alone function, that when passed a tForm, it'll look at every tWincontrol object and put the Top, Left, and memory location of that component into a table that sits in memory. I then do a simple "select LeftPos,TopPos,Addr from TabOrderTable order by TopPos,LeftPos' and then assign the TabIndex of the component to whatever row count I'm on.
IE:
RowCounter:=1;
while not tbl.eof do begin
Comp:=tWinControl(tbl.FieldIntByName['Addr']);
Comp.TabIndex:=RowCounter;
inc(RowCounter);
tbl.Next
end;
The one thing that you mention I hadn't thought of (Because it'd never come up) is the ordering of buttons that don't follow left-to-right notation. To get around that, I'd make a form level function that'd specifically be run AFTER this main sort that'd specifically put the buttons in whatever order I wanted.
Either that, I'd change the sorting algo to support which direction the order should go, and, allow for grouping components (GroupBox, Panel, etc) to be passed in instead of a tForm.