Entwickler-Ecke
Grafische Benutzeroberflächen (VCL & FireMonkey) - mehrere StringGrids scrollen
Bronstein - Sa 11.11.06 16:21
Titel: mehrere StringGrids scrollen
Hallo,
habe ein Problem mit dem Scrollen. Ich habe auf meinem Formular 6 StringGrids. Diese sollen beim Scrollen aufeinander abgestimmt werden.
Habe mal als Anlage mein Formular als Screenshot.
Nun zu den Funktionen die ich gerne hätte. Wen ich am StringGrid4 horizontal scrolle, sollen die Stringgrids 1, 2, 3 auch mitscrollen. Wenn ich beim StringGrid3 vertikal scrolle, soll das Grid5 auch mitscrollen.
Habe bis jetzt nur hinbekommen wenn ich bei stringGrid 4 scrolle dass Grid3 mitscrollt.
Hier mal der Code dazu:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35:
| private OldGridProc3, OldGridProc4: TWndMethod; [...] procedure Grid3WindowProc(var Message: TMessage); procedure Grid4WindowProc(var Message: TMessage); [...]
procedure TForm1.FormCreate(Sender: TObject); [...] OldGridProc3 := StringGrid1.WindowProc; OldGridProc4 := StringGrid3.WindowProc; StringGrid3.WindowProc := Grid3WindowProc; StringGrid4.WindowProc := Grid4WindowProc; [...] procedure TForm1.Grid3WindowProc(var Message: TMessage); begin OldGridProc3(Message); if ((Message.Msg = WM_VSCROLL) or (Message.Msg = WM_HSCROLL) or (Message.msg = WM_Mousewheel)) then begin OldGridProc4(Message); end; end;
procedure TForm1.Grid2WindowProc(var Message: TMessage); begin OldGridProc4(Message); if ((Message.Msg = WM_VSCROLL) or (Message.Msg = WM_HSCROLL) or (Message.msg = WM_Mousewheel)) then begin OldGridProc3(Message); end; end; |
Coder - Sa 11.11.06 17:13
Kennst du StringGrid1.ScrollBy?
Vielleicht kannst du damit ja was anfangen.
MfG
Lannes - Sa 11.11.06 17:20
Hallo,
denke das Dir StringGrid.TopRow und StringGrid.LeftCol weiter hilft.
Bronstein - Sa 11.11.06 19:08
Habe die Lösung von Lannes genommen.
Ist ja wirklich easy
Coder - Sa 11.11.06 19:10
Nett wäre jetzt wenn du die Lösung hier postest damit andere nicht nochmal Fragen müssen :wink:
Bronstein - Mo 13.11.06 10:31
Möchte es jetzt doch mal mit ScrollBy versuchen. Ich dachte das könnte jetzt so funktionieren.
Doch irgendwie sieht mein StringGrid dann komisch aus.
Hier mal der Code für die Horizontale Scrollbar:
Delphi-Quelltext
1: 2: 3: 4: 5:
| procedure TForm1.ScrollBar1Scroll(Sender: TObject; ScrollCode: TScrollCode; var ScrollPos: Integer); begin StringGrid1.ScrollBy(ScrollBar1.Left, ScrollBar2.Top); end; |
Hier noch der Code für meine letzte Lösung für den horizontalen Bereich
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7:
| procedure TForm1.StringGrid2DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); begin StringGrid1.LeftCol := StringGrid2.LeftCol; StringGrid3.LeftCol := StringGrid2.LeftCol; StringGrid4.LeftCol := StringGrid2.LeftCol; end; |
Lannes - Mo 13.11.06 11:54
Hallo,
ich dachte die Lösung mit LeftCol usw. wäre "wirklich easy", welches Problem ist denn da entstanden?
Zum Thema ScrollBy lies mal die Delphi-Hilfe.
Mit ScrollBy verschiebt man nur den Bildausschnitt, deshalb sieht das bei Dir dann komisch aus.
Ps.: Bei den Schweitzern gibt es auch eine Lösung zum Thema "StringGrids synchronisieren"
Bronstein - Mo 13.11.06 12:06
Ich habe ja mehrere StringGrids. Jetzt habe ich aber eines dabei das immer die Überschrift mehrere Zellen ist. Somit hat dieses StringGrid eine andere Anzahl Spalten.
Und dann passt es natürlich nicht, da er ja mit dieser Lösung nach spalten scrollt
Lannes - Mo 13.11.06 12:48
Hallo,
das kannst Du doch über einen Faktor regeln, oder?
Bronstein - Mo 13.11.06 20:20
Es handelt sich dabei ja um einen Jahreskalender.
Die eine StringGrids haben 365 Spalten (Breite 30) und das andere hat 12 Spalten.
Ich dachte jetzt, dass ich das eine auch mit 365 Spalten mache.
Dazu habe ich alle Spalten auf die Breite 0 gesetzt bis auf das des 15. Tag. Das habe ich mit dem Faktor 30*Anzahl Tage im Monat gemacht.
Jetzt wechselt er aber schon am Tag 15 den Monatsnamen.
Mit 28 bzw. 30 habe ich es auch schon versucht. Das passt auch nicht so richtig
Logikmensch - Di 14.11.06 10:43
Hallo Bronstein,
ich habe mir Dein Attachment angesehen und möchte nur mal fragen, warum Du das nicht mit nur einem StringGrid gemacht hast. Da kann man doch auch feste Spalten- und Zeilenbeschriftungen (fixedcols und -rows) machen und von der Breite her gibt es da doch sicher keinerlei Einschränkungen...
War nur so ne Idee...
Bronstein - Di 14.11.06 21:24
Das geht so viel ich weiß nicht.
Wenn man die Spalte vergrößert bzw. verkleinert wird auch die Spaltenbreite der Überschrift geändert.
Logikmensch - Mi 15.11.06 07:22
Oh, da habe ich mich missverständlich ausgedrückt. Mit 'Breite' meinte ich die Anzahl der Spalten der Tabelle. Mit StringGrid1.colcount:=365 lässt sich diese ja voreinstellen.
Ja, die Breite der Überschriften ändert sich, soweit ich weiß, mit den anderen Zellen der Spalte, wenn diese verändert wird (kann in den Options-properties an- und abgeschaltet werden).
Nein, ich meinte mit meinem Hinweis nur, dass ich die Notwendigkeit von mehr als nur einem StringGrid bisher noch nicht erkennen konnte. Aber tut ja auch nicht viel zur Sache.
Bronstein - Mi 15.11.06 08:58
Hallo, habe das mal mein Projekt als Anlage geschickt. Vielleicht kann mir dann jemand weiterhelfen.
Habe mal zwei Möglichkeiten.
Bei der ersten hat das MonatsStringGrid 12 Spalten , bei der 2. 365.
Bronstein - Do 16.11.06 08:36
Hat niemand eine Ahnung wie ich das Problem lösen könnte
Andreas Schilling - Do 16.11.06 13:34
Versuche es mal so. Ich habe deinen Quelltext mit 12 Monatsspalten dazu verwendet.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| procedure TForm1.StringGrid2TopLeftChanged(Sender: TObject); var Monat : integer; strTag : string; begin StringGrid1.LeftCol := StringGrid2.LeftCol; strTag := StringGrid4.Cells[StringGrid2.leftcol, 0]; Monat := strtoint(copy(strtag, 4, 2)); StringGrid3.LeftCol := Monat - 1; StringGrid4.LeftCol := StringGrid2.LeftCol; end; |
Lannes - Fr 17.11.06 16:51
Hallo,
Lannes hat folgendes geschrieben: |
... versuch doch mal die Monats-Anzeige mit in das StringGrid zu setzen...[/url] |
eventuell kann ich Dich ja noch überzeugen :wink:
Hab da aus meinen Vorräten etwas zusammengesucht, ich poste mal die ganze Unit.
Zum Testen einfach ein StringGrid auf die Form legen, meine Unit übernehmen und Formcreate und GriDDrawCell im OI zuweisen.
Feiertage, Kalenderwoche und andere Erweiterungen überlass ich Dir,
geht aber nur wenn man das Grundprinzip der OnDrawCell-Behandlung versteht. :les:
Die Jahresdaten werden nicht in Grid.Cells geschrieben, sie werden nur mit Textout ausgegeben.
Das Array
FJahrArr wird in der folgenden Form gefüllt(Tag,Monat;Wochentag):
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| 1 1 1 2 1 2 3 1 3 4 1 4 5 1 5 6 1 6 7 1 7 8 1 1 ... |
Auf dieses Array wird dann entsprechend der aktuellen Spalte(aCol) in DrawCell zugegriffen.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121:
| unit Unit1;
interface
uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Grids;
const C_CLFIXED = $00CEBCA2; C_CLFIXEDHELL = $00EDE7DC; C_CLNOWORK = $00F4F1EA; C_CLWORK = clWhite; C_TAG = 1; C_MONAT = 2; C_WTAG = 3; type TForm1 = class(TForm) StringGrid1: TStringGrid; procedure FormCreate(Sender: TObject); procedure StringGrid1DrawCell(Sender: TObject; aCol, aRow: Integer; Rect: TRect; State: TGridDrawState); private FJahr : Word; FJahrArr : Array [1..366,C_TAG..C_WTAG] of Word; public end;
var Form1: TForm1; implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject); var z : Integer; aDateTime : TDateTime; dammy : Word; begin FJahr := StrToInt(FormatDateTime('yyyy',now)); aDateTime := EncodeDate(FJahr,1,1)-1; for z := 1 to 366 do begin DecodeDate(aDateTime+z,dammy,FJahrArr[z,C_MONAT],FJahrArr[z,C_TAG]); FJahrArr[z,C_WTAG] := DayOfWeek(aDateTime+z); end; with StringGrid1 do begin Ctl3D := False; FixedCols := 1; FixedRows := 2; RowCount := 100; DefaultColWidth := 16; DefaultRowHeight := 16; ColWidths[0] := 50; Cells[0,2] := 'Meier'; Cells[0,3] := 'Hinz'; Cells[0,4] := 'Kunz'; Cells[0,5] := 'Müller'; if FJahrArr[366,C_TAG] <> 31 then ColCount := 366 else ColCount := 367; DefaultDrawing:=false; end; end;
procedure TForm1.StringGrid1DrawCell(Sender: TObject; aCol, aRow: Integer; Rect: TRect; State: TGridDrawState); var aTag, aMonat : Integer; R : TRect; begin aTag := FJahrArr[ACol,C_TAG]; aMonat := FJahrArr[ACol,C_MONAT]; R := Rect; with StringGrid1 do begin if (aRow = 0) and (ACol >= FixedCols) then begin if aMonat mod 2 = 0 then Canvas.Brush.Color := C_CLFIXED else Canvas.Brush.Color := C_CLFIXEDHELL; Canvas.FillRect(Classes.Rect(R.Left,R.Top,R.Right+1,R.Bottom)); if aTag = 1 then begin Canvas.Pen.Color := clBlack; Canvas.MoveTo(R.Left-1,R.Top); Canvas.LineTo(R.Left-1,R.Bottom); end; if aTag in [15..20] then Canvas.TextOut(R.Left+2-((aTag-15)*17),R.Top+2,LongMonthNames[aMonat]); end else begin if (ACol < FixedCols) or (ARow = 1) then Canvas.Brush.Color := C_CLFIXED else if FJahrArr[ACol,C_WTAG] in [1,7] then Canvas.Brush.Color := C_CLNOWORK else Canvas.Brush.Color := C_CLWORK; if (ACol < FixedCols) and (ARow < FixedRows) then Canvas.FillRect(Classes.Rect(R.Left,0,R.Right,R.Bottom)) else Canvas.FillRect(R); if (aRow = 1) and (ACol >= FixedCols) then Canvas.TextOut(R.Left+2,R.Top+2,Format('%.2d',[aTag])) else if (aRow = FixedRows-1) and (ACol = FixedCols-1) then Canvas.TextOut(R.Left+10,R.Top-8,IntToStr(FJahr)) else Canvas.TextOut(R.Left+2,R.Top+2,Cells[aCol,aRow]); end; end; end;
end. |
Bronstein - Fr 17.11.06 23:14
Super genau das habe ich gesucht.
Verstehen tue ich es noch nicht. Muss ich mir erstmal genauer anschauen
Lannes - Sa 18.11.06 00:02
Hallo,
Bronstein hat folgendes geschrieben: |
...Muss ich mir erstmal genauer anschauen |
besser ist das :wink:
Welchen Zweck soll eigentlich das unterste Grid in Deinem Beispiel erfüllen?
Bronstein - Sa 18.11.06 13:04
Das ergibt die Auswertung des Schichtplaners. Sprich wieviel Personen am Tag anwesend sind, zu den einzelnen Schichten zusammengefasst.
Bronstein - Mi 22.11.06 12:45
Jetzt habe ich aber doch noch ein Problem. Habe jetzt folgenden Code in das DrawCell Ereignis gemacht, damit ich Zellen markieren kann:
Delphi-Quelltext
1: 2: 3: 4: 5: 6:
| if (Selection.Left <= ACol) and (Selection.Right >= ACol) and (Selection.Top <= ARow) and (Selection.Bottom >= ARow) then begin Canvas.Brush.Color := TColor(Integer(Canvas.Brush.Color) xor $00FFFFFF); Canvas.FrameRect(Rect); end; |
Jetzt kann ich aber nur Zellen markieren die hintereinander kommen. Ich möchte aber mit Hilfe der STRG-Taste z.B. die Zelle [5, 5] und die Zelle[7, 9] markieren
Lannes - Mi 22.11.06 15:25
Hallo,
wir kommen hier so langsam aber sicher sehr weit vom Thema ab(scrollen >> selectieren),
mach doch lieber ein neues Thema auf :wink:
Vorschlag:
Titel 1: [StringGrid] selectieren von nicht zusammenhängenden Zellbereichen
oder wenn Du nur einfärben willst(was ich annehme)
Titel 2: [StringGrid] einfärben von Zellbereichen mit Strg + Maus
zum Code:
Delphi-Quelltext
1:
| if (Selection.Left <= ACol) and (Selection.Right >= ACol) and (Selection.Top <= ARow) and (Selection.Bottom >= ARow) then |
diese If-abfrage ist imho mit folgendem gleichzusetzen:
Delphi-Quelltext
1: 2:
| if gdSelected in State then |
außerdem ist die Einfärbung nur temporaer, solange der Bereich selectiert ist.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!