Frage

Ich versuche, das Scrollen von zwei TDBGrid-Komponenten in einer VCL-Formularanwendung zu synchronisieren. Ich habe Schwierigkeiten, den WndProc jeder Grid-Komponente ohne Stapelprobleme abzufangen.Ich habe versucht, WM_VSCROLL-Nachrichten unter Scrolling-Ereignissen zu senden, aber dies führt immer noch zu einem falschen Vorgang.Es muss funktionieren, wenn Sie auf die Bildlaufleiste klicken, eine Zelle markieren oder eine Auf- oder Ab-Maustaste drücken.Die ganze Idee besteht darin, zwei Gitter nebeneinander zu haben, die eine Art passenden Dialog anzeigen.

Versucht

SendMessage( gridX.Handle, WM_VSCROLL, SB_LINEDOWN, 0 );

Auch

procedure TForm1.GridXCustomWndProc( var Msg: TMessage );
begin
Msg.Result := CallWindowProc( POldWndProc, gridX.Handle, Msg.Msg, Msg.wParam, Msg.lParam );

   if ( Msg.Msg = WM_VSCROLL ) then 
   begin
      gridY.SetActiveRow( gridX.GetActiveRow );
      gridY.Perform( Msg.Msg, Msg.wParam, Msg.lParam );
      SetScrollPos( gridY.Handle, SB_VERT, HIWORD( Msg.wParam ), True );
   end;
end;

Und

procedure TForm1.GridxCustomWndProc( var Msg: TMessage );
begin
   if ( Msg.Msg = WM_VSCROLL ) then 
   begin
      gridY.SetActiveRow( gridX.GetActiveRow );
      gridY.Perform( Msg.Msg, Msg.wParam, Msg.lParam );
      SetScrollPos( gridY.Handle, SB_VERT, HIWORD( Msg.wParam ), True );
   end;
   inherited WndProc( Msg );
end;

Die erste Lösung ist nur eine vorübergehende Lösung, die zweite führt zu ungültigen Speicherlesevorgängen und die dritte führt zu einem Stapelüberlauf.Daher scheint keine dieser Lösungen für mich zu funktionieren.Ich würde mich über Anregungen zur Bewältigung dieser Aufgabe freuen!Dank im Voraus.

AKTUALISIEREN:Lösung

  private
    [...]
    GridXWndProc, GridXSaveWndProc: Pointer;
    GridYWndProc, GridYSaveWndProc: Pointer;
    procedure GridXCustomWndProc( var Msg: TMessage );
    procedure GridYCustomWndProc( var Msg: TMessage );

procedure TForm1.FormCreate(Sender: TObject);
begin
  GridXWndProc := classes.MakeObjectInstance( GridXCustomWndProc );
  GridXSaveWndProc := Pointer( GetWindowLong( GridX.Handle, GWL_WNDPROC ) );
  SetWindowLong( GridX.Handle, GWL_WNDPROC, LongInt( GridXWndProc ) );

  GridYWndProc := classes.MakeObjectInstance( GridYCustomWndProc );
  GridYSaveWndProc := Pointer( GetWindowLong( GridY.Handle, GWL_WNDPROC ) );
  SetWindowLong( GridY.Handle, GWL_WNDPROC, LongInt( GridYWndProc ) );
end;

procedure TForm1.GridXCustomWndProc( var Msg: TMessage );
begin
   Msg.Result := CallWindowProc( GridXSaveWndProc, GridX.Handle, Msg.Msg, Msg.WParam, Msg.LParam );
   case Msg.Msg of
      WM_KEYDOWN:
      begin
         case TWMKey( Msg ).CharCode of VK_UP, VK_DOWN, VK_PRIOR, VK_NEXT:
            GridY.Perform( Msg.Msg, Msg.WParam, Msg.LParam );
         end;
      end;
      WM_VSCROLL:
         GridY.Perform( Msg.Msg, Msg.WParam, Msg.LParam );
      WM_HSCROLL:
         GridY.Perform( Msg.Msg, Msg.WParam, Msg.LParam );
      WM_MOUSEWHEEL:
      begin
         ActiveControl := GridY;
         GridY.Perform( Msg.Msg, Msg.WParam, Msg.LParam );
      end;
      WM_DESTROY:
      begin
         SetWindowLong( GridX.Handle, GWL_WNDPROC, Longint( GridXSaveWndProc ) );
         Classes.FreeObjectInstance( GridXWndProc );
      end;
  end;
end;

procedure TForm1.GridXMouseDown( Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer );
begin
   GridY.SetActiveRow( GridX.GetActiveRow );
end;

procedure TForm1.GridYCustomWndProc( var Msg: TMessage );
begin
   Msg.Result := CallWindowProc( GridYSaveWndProc, GridY.Handle, Msg.Msg, Msg.WParam, Msg.LParam );
   case Msg.Msg of
      WM_KEYDOWN:
      begin
         case TWMKey( Msg ).CharCode of VK_UP, VK_DOWN, VK_PRIOR, VK_NEXT:
            GridX.Perform( Msg.Msg, Msg.WParam, Msg.LParam );
         end;
      end;
      WM_VSCROLL:
         GridX.Perform( Msg.Msg, Msg.WParam, Msg.LParam );
      WM_HSCROLL:
         GridX.Perform( Msg.Msg, Msg.WParam, Msg.LParam );
      WM_MOUSEWHEEL:
      begin
         ActiveControl := GridX;
         GridX.Perform( Msg.Msg, Msg.WParam, Msg.LParam );
      end;
      WM_DESTROY:
      begin
         SetWindowLong( GridY.Handle, GWL_WNDPROC, Longint( GridYSaveWndProc ) );
         Classes.FreeObjectInstance( GridYWndProc );
      end;
   end;
end;

procedure TForm1.GridYMouseDown( Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer );
begin
   GridX.SetActiveRow( GridY.GetActiveRow );
end;

Vielen Dank an - Sertac Akyuz für die Lösung.Wenn sie mithilfe von Rastern in eine VCL-Formularanwendung integriert werden, ahmen sie einander beim Scrollen und Hervorheben des ausgewählten Datensatzes nach.

War es hilfreich?

Lösung

Sie implementieren wahrscheinlich die Nachrichtenüberschreibung für beide Gitter.GridX scrollt snory, was wiederum GridX scrollt, was wiederum ... so.Sie können den oberflächlichen Scrolling-Code schützen, indem Sie den Block mit Flags umgeben.

generasacodicetagpre.

similiar code für das gridy.BTW, Sie brauchen nicht die SetscrollPos.


edit:

generasacodicetagpre.

Andere Tipps

Ich habe eine teilweise, aber jetzt vollständige Arbeitslösung (zumindest für zwei TMEMO) ...

Ich meine teilweise, weil es nur auf Änderungen an einem TMEMO zuhört, aber nicht auf der anderen Seite ...

Ich meine voll funktionieren, weil es nicht von dem abhängt, was getan ist ...

Es ist genauso einfach wie derselbe horizontale Scroll-Wert auf einem Memo, wie es auf der anderen Seite ist ...

Es ist nichts in Verbindung mit Nachrichten, aber da ich versucht habe, eine Arbeitslösung durch Fangen von Nachrichten wm_hscroll zu erhalten, etc ... Ich habe den Code verlassen, weil es funktioniert ... ich werde versuchen, es später zu verbessern ... für Beispiel, das nur WM_PAINT einfängt, oder auf andere Weise ... aber für jetzt, aber ich habe es so, wie ich es habe, da es funktioniert ... und ich fand nirgendwo etwas noch besser ...

Hier ist der Code, der funktioniert:

generasacodicetagpre.

Es funktioniert für alle Möglichkeiten, um Blättern zu erstellen, um sich zu ändern ...

Hinweise:

    .
  • Ich weiß, dass es schrecklich ist, alle Nachrichten zu fangen, aber zumindest arbeitet ...
  • Dies ist mein erster erfolgreicher Versuch, zwei TMEMOS mit synchronisiert zu haben Horizontale Bildlaufleiste ...
  • Also, wenn jemand es ein wenig verbessern kann (nicht alle Nachrichten fallen) Mach es und poste es.
  • es macht Memo1 nur, um auf der horizontalen Synchronisierung mit Memo2-Bar zu sein, aber nicht MEMO2 soll mit MEMO1 Drücken Sie die Tasten nach oben, unten, links, rechts, Mausrad usw. etc ... was auch immer Sie Willst du aber auf Memo2, um es in Aktion zu sehen

Ich werde versuchen, es zu verbessern durch: Wenn Sie etwas auf Memo2 tun, ist Memo1 Scroll noch auf Synchronisierung ...

Ich denke, es kann für die gradioste Steuerung arbeiten, die eine Bildlaufleiste hat, nicht nur TMEMO ...

Wie ich sagte ...

Hier ist eine bessere Lösung (nicht endgültig) in Bezug auf Effizienz, sauberer Code und bidirektional ... Wechseln auf einem anderen wirkt sich auf die andere ...

Bitte lesen Sie Kommentare zu einem Code, um zu verstehen, was jeder Satz tut ... es ist ziemlich schwierig ... aber die Hauptidee ist das gleiche wie zuvor ... Setzen Sie die andere tmemo horizontale Bildlaufleiste, wie auf der TMEMO, wo der Benutzer tätig ist ... egal, was der Benutzer tut, verschieben Sie die Maus und wählen Sie Text aus, drücken Sie nach links, rechts, nach Hause, Endtasten, verwenden Sie das Horizontalrad mit der Maus (nicht alle haben) der horizontalen Bildlaufleiste usw. ...

Die Hauptidee ist ... Das Objekt muss neu gelagert werden, sodass das andere Objekt horizontale Bildlaufleiste identisch mit diesem einzelnen ...

Dieser erste Teil ist nur, um die TMEMO-Klasse hinzufügen, er schafft nur eine neue abgeleitete Klasse, jedoch mit demselben Klassennamen, jedoch nur für das Gerät innerhalb des Deklaration.

Fügen Sie diese Option in den Schnittstellenabschnitt hinzu, bevor Sie Ihre TFORM-Deklaration, sodass Ihre Tform diese neue TMEMO-Klasse anstelle von Normal eins sieht:

generasacodicetagpre.

Dieser nächste Teil ist die Implementierung für frühere Erklärungen dieser neuen TMEMO-Klasse.

Fügen Sie diese Option zum Implementierungsabschnitt hinzufügen, wo Sie vorlegen:

generasacodicetagpre.

Jetzt den letzten Teil, sagen Sie jedem TMEMO, was das andere Memo ist, das auf Synchronisierung sein muss.

In Ihrem Implementierungsabschnitt, für das Formular1 Event erstellen Ereignis etwas Fügen Sie so etwas hinzu:

generasacodicetagpre.

Denken Sie daran, dass wir SyncMemo-Mitglied in unseren speziellen neuen TMEMO-Kurs hinzugefügt haben, es war nur dafür, sagen Sie sich, was man der andere ist.

Jetzt eine kleine Konfiguration für beide TMEMO JSUT, um diese Arbeit perfekt zu lassen:

    .
  • Lassen Sie beide TMEMO-Bildlaufleisten sichtbar sein
  • lass Wordwrap falsch auf beiden TMEMO
  • Legen Sie viel Text (gleich für beide), lange Linien und viele Linien

Führen Sie es aus und sehen Sie, wie beide horizontalen Bildlaufleisten immer synchron sind ...

    .
  • Wenn Sie eine horizontale Bildlaufleiste bewegen, die andere horizontale Bildlaufleiste bewegt ...
  • Wenn Sie den Text nach rechts oder links auf den Text gehen, starten Sie das Start- oder Leitungsende, ETC ..., egal wo ist Selstart auf der anderen ... die horizontale Text-Bildlauf ist auf Synchronisierung.

Das Problem, warum dies keine endgültige Version ist, ist:

    .
  • Die Bildlaufleisten (horizontal in meinem Fall) können nicht ausgeblendet werden ... da, wenn man ausgeblendet ist, wenn er get cretcrollpos anruft, kehrt es null zurück, so dass es nicht synchronisiert wird.

Wenn jemand weiß, wie man verborgen ist, wie er verborgen ist oder getcrollpos nicht null zurückgibt, bitte kommentieren, das einzige, was ich für die endgültige Version beheben muss.

Hinweise:

    .
  • offensichtlich dasselbe kann mit vertikaler Bildlaufleiste erfolgen ... einfach ändern Wm_hscroll bis wm_vscroll und sb_horz zu sb_vert
  • offensichtlich dasselbe kann für beide gleichzeitig erfolgen ... Kopieren Sie einfach syncmemo.perform-Zeile zweimal und lass WM_HSCROLL und SB_HORZ und unter anderem lass WM_VScroll und sb_vert

Hier ist ein Beispiel eines neuen_windowproc-Verfahrens, um beide Bildlaufleisten gleichzeitig zu synchronisieren, vielleicht für faule Menschen, vielleicht für Personen, wie kopieren und einfügen:

generasacodicetagpre.

Ich hoffe, dass jemand das Problem der versteckten Bildlaufleiste beheben kann, und GetcrollPos, die Null zurückgibt !!!

Ich habe eine Lösung gefunden ... Ich weiß, dass es ziemlich schwierig ist ... aber zumindest ist es voll funktionsfähig ...

Anstatt die horizontale Bildlaufleiste auszublenden ... Ich mache es aus sichtbarem Bereich, so dass es nicht vom Benutzer gesehen wird ...

Der knifflige Teil:

    .
  • legte ein TPanel an, wo das Tmemo ist und den Tmemo in den TPanel
  • legt
  • Tpanel-Grenzen ausblenden, grenzüberschreitend wie 0 und alle Abschrägung nach Bvnone / Bvnone
  • Konfigurieren Sie TMEMO an Altop, nicht an Alclient usw.
  • TPanel handeln / li>

das ist es ... fertig !!! Die horizontale Bildlaufleiste ist außerhalb des sichtbaren Bereichs ... Sie können einsetzen, in dem Sie den TPanel wünschen, die Größe, die Sie wünschen ... knifflig ich weiß, aber voll funktionsfähig.

Hier ist der vollständige Code, um zu archivieren:

im Schnittstellenabschnitt, bevor Ihre TFORM-Deklaration diese neue TMEMO-Klasse anstelle von Normal eins zeigt:

generasacodicetagpre.

Im Implementierungsabschnitt überall, wo Sie vorgehen:

generasacodicetagpre.

Auch im Implementierungsabschnitt überall, wo Sie vorgehen:

generasacodicetagpre.

Thas's it Leute! Ich weiß, dass es ziemlich schwierig ist, aber voll funktionsfähig ist.

Bitte beachten Sie, dass ich auf New_WindowProc die Reihenfolge der Auswertung der ODER-Bedingungen geändert habe ... es ist nur um die Geschwindigkeit für alle anderen Nachrichten zu verbessern, so dass möglichst weniger alle Botschaftsbehandlung verzögert.

hofft irgendwann ich weiß, wie man 20 durch die reale (berechnete oder gelesene) tmemo horizontale Bildlaufleiste ersetzt.

Danke für GetSystemMetrics Und SM_CYHSCROLL, aber es ist nicht nur genug...Ich brauche nur 3 Pixel mehr...

Also verwende ich einfach: GetSystemMetrics(SM_CYHSCROLL)+3

Notiz:Zwei solcher Pixel könnten darauf zurückzuführen sein, dass das übergeordnete Panel vorhanden ist BevelWidth mit Wert 1 aber ich habe BevelInner Und BevelOuter mit Wert bvNone vielleicht auch nicht;aber das zusätzliche Pixel weiß ich nicht warum.

Vielen Dank.

Wenn Sie möchten, fügen Sie sie einfach in einem großen Beitrag zusammen, aber ich denke, es ist besser, sie nicht zu vermischen.

Als Antwort auf „Sertac Akyuz“ (tut mir leid, dass ich es hier mache, aber ich weiß nicht, wie ich sie neben deiner Frage posten soll):

  • Ich habe hier die Lösungen aufgeführt, die ich gefunden habe, so wie ich sie gefunden habe ...Meine Absicht war es nicht, es als Scratch-Pad zu verwenden ...Ich habe die Lösung nur wenige Sekunden vor dem Verfassen der Beiträge entdeckt
  • Ich denke, es ist besser, alte Beiträge zu sehen, anstatt mehrfach in den gleichen Beitrag zu bearbeiten ...Andere werden auch andere über die genaue Lösung informiert und sie auch wissen, wie sie eine solche Lösung erreichen können.
  • Ich mache es, Dinge so zu tun, wie "Lehre, wie man fischt, anstatt den Fisch zu geben".
  • Ich habe keine neue Frage eröffnet, nur weil der Titel dieser Frage genau das ist, was ich tun wollte

Wichtig:Ich stelle fest, dass die Nachrichtenerfassung keine perfekte Lösung sein kann, da es einen Fall gibt, bei dem zwar gescrollt, aber keine Nachricht angezeigt wird WM_VSCROLL, WM_HSCROLL (nur WM_PAINT)...es hängt mit der Auswahl von Text mit der Maus zusammen ...Lassen Sie mich erklären, wie ich es in Aktion sehe ...Beginnen Sie einfach am Ende der letzten visuellen Linie und bewegen Sie die Maus ein wenig nach unten. Stoppen Sie dann die Mausbewegung und lassen Sie die Maustaste gedrückt ...ohne etwas zu tun (Maus bewegt sich nicht, kein Tastendruck, kein Tastendruck, kein Wechsel der Maustaste usw.), scrollt das TMemo nach unten, bis das Ende des Textes erreicht ist ...Das Gleiche gilt für horizontales Scrollen, wenn sich die Maus am rechten Ende der visuellen Linie befindet und nach rechts bewegt wird ...auch in umgekehrter Richtung dasselbe...Solche Schriftrollen funktionieren nicht durch Nachrichten WM_VSCROLL WM_HSCROLL, nur WM_PAINT (zumindest auf meinem Computer)...Das Gleiche passiert auch bei Grids.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top