siro hat geschrieben: Fr 19. Aug 2022, 15:55
ich weis aber nicht wie ich an den Source Code zum Zeichnen des Rasters für das Formular im Designmodus ran komme.
Wie sucht man so etwas am besten ?
Offiziell, indem man die IDE debuggt. Aber das ist relativ aufwendig, mit Nachdenken und Wissen über die Grundstruktur der IDE geht's einfacher und schneller:
Wie du schon bemerkt hast, wird das "Show grid" in den Optionen des Formular-Designers aus/eingeschaltet. Das meiste, was mit der IDE zu tun hat, steht im Verzeichnis "ide" der Lazarus-Installation, und alles, was im Konfigurationsformular auftaucht, läuft über Frames, für die ein Unterverzeichnis "frames" reserviert ist. Und dort sticht eine Datei "formed_options.pas" ins Auge. Wenn man die Datei öffnet, findet man im Designer tatsächlich diese "ShowGridCheckbox"-Combobox. Weiteres durchsuchen im Quelltext, zeigt dass der Zustand dieser Checkbox als Element ShowGrid der EnvironmentOptions abgespeichert wird.
Nun weiter mit der "Suche in Dateien", Suchtext "ShowGrid", Suchverzeichnis: das Lazarus-Installationsverzeichnis mit Unterverzeichnissen. Es werden über 100 Einträge gefunden, aber die meisten sind schon vom Dateiverzeichnis her unzutreffend. In der Unit designer.pp (Im Ordner designer) wird's aber interessant: eine Zeile in der Liste der Fundstellen heißt "if ShowGrid then", und die bringt uns mitten in die Methode TDesigner.PaintClientGrid - mit dem vorangestellten Kommentat "// Paint points" scheint das der (vorläufige) Übeltäter zu sein:
Code: Alles auswählen
// paint points
if ShowGrid then
begin
ADDC.Canvas.Pen.Color := GridColor;
ADDC.Canvas.Pen.Width := 1;
ADDC.Canvas.Pen.Style := psSolid;
DrawGrid(ADDC.Canvas.Handle, TWinControlAccess(AWinControl).GetLogicalClientRect,
GridSizeX, GridSizeY);
end;
DrawGrid scheint das Gitter mit Weiten GridSizeX/GridSizeY in dem Rechteck zu zeichen, das durch TWinControlAccess(AWinControl).GetLogicalClientRect definiert ist. GetLogicalClientRect ist eine virtuelle Methode, die von TScrollbox überschrieben wird:
Code: Alles auswählen
function TScrollingWinControl.GetLogicalClientRect: TRect;
begin
Result := ClientRect;
{if (FHorzScrollBar.Range>Result.Right)
or (FVertScrollBar.Range>Result.Bottom) then
DebugLn(['TScrollingWinControl.GetLogicalClientRect Client=',ClientWidth,'x',ClientHeight,' Ranges=',FHorzScrollBar.Range,'x',FVertScrollBar.Range]);}
if Assigned(FHorzScrollBar) and FHorzScrollBar.Visible
and (FHorzScrollBar.Range > Result.Right) then
Result.Right := FHorzScrollBar.Range;
if Assigned(FVertScrollBar) and FVertScrollBar.Visible
and (FVertScrollBar.Range > Result.Bottom) then
Result.Bottom := FVertScrollBar.Range;
end;
Also: zunächst so groß wie das Control selbst (ClientRect), dann aber, wenn Scrollbars sichtbar sind, in der entsprechenden Richtung bis zum Range des Scrollbars aufgeweitet. Das ist der Übeltäter: Bei dieser Definition wird das Gitter bei sichtbaren Scrollbars immer über die 10000x10000 Pixel gezeichnet, obwohl nur ein winziger Ausschnitt sichtbar ist.
Das weitere Tüfteln, wie man nun, von dieser Erkenntnis ausgehend, das an DrawGrid zu übergebende Rechteck bestimmen muss, überlasse ich euch...
[EDIT]
Eine Idee hätte ich noch, um sich das Debuggen zu vereinfachen: TScrollbox hat eine OnPaint-Methode, und dort könnte man das o.e. DrawGrid aufrufen, so dass man dasselbe Verhalten wie im Objekt-Inspektor in einem normalen Projekt hat. Nun kann man mit dem übergebenen Rechteck herumspielen, und die richtigen Einstellungen finden. Im folgenden Code habe ich zunächst das ClientRect genommen - sieht auf den 1.Blick super aus und ist super schnell, nur wenn man scrollt verschwindet das Grid... Die nächste Idee war, das ClientRect um die Lage der linken/oberen Ecke zu verschieben: nun kann man mit der Maus scrollen, aber beim Klicken auf den Balken selbst entstehen Artefakte. Das muss noch besser gehen...
Code: Alles auswählen
procedure TForm1.ScrollBox1Paint(Sender: TObject);
const
VARIANTE = 3;
var
R: TRect;
begin
case VARIANTE of
1: begin // Langsam (Originalzustand)
R := Rect(0, 0, Scrollbox1.HorzScrollbar.Range, Scrollbox1.VertScrollbar.Range);
end;
2: begin // Schnell (Gültig aber nur ohne Scrollen
R := Scrollbox1.ClientRect;
end;
3: begin // Schnell, Scrollen mit Maus OK, aber Artefakte beim Klick auf Scrollbar und Scroll nach oben/links
R := Scrollbox1.ClientRect;
OffsetRect(R, Scrollbox1.HorzScrollbar.Position, Scrollbox1.VertScrollbar.Position);
end;
end;
LCLIntf.DrawGrid(Scrollbox1.Canvas.Handle, R, 8, 8);
end;