Synchronisé Défilement Des Composants De Delphi
-
26-09-2020 - |
Question
Je suis en train d'essayer de synchroniser le défilement de deux TDBGrid les composants de la VCL les Formulaires de demande, je vais avoir des difficultés à l'interception de la WndProc de chaque grille composant sans pile questions.J'ai essayé d'envoyer des WM_VSCROLL les messages sous les événements de défilement mais c'est toujours les résultats de l'utilisation incorrecte.Il faut travailler pour en cliquant sur la barre de défilement, ainsi que la mise en surbrillance une cellule, ou un haut ou bas du bouton de la souris.L'idée est d'avoir deux grilles uns à côté des autres en affichant une sorte de dialogue correspondance.
Essayé
SendMessage( gridX.Handle, WM_VSCROLL, SB_LINEDOWN, 0 );
Aussi
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;
Et
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;
La Première est qu'une solution temporaire, le second les résultats dans la mémoire non valide lit, et le troisième les résultats dans un débordement de pile.Si aucune de ces solutions ne semble fonctionner pour moi.J'aimerais des commentaires sur la façon d'accomplir cette tâche!Merci à l'avance.
Mise à JOUR:Solution
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;
Grâce à Sertac Akyuz pour la solution.Lorsqu'il est intégré dans une application fiches VCL à l'aide de grilles, ils mimmic les uns des autres dans le défilement, et en mettant en évidence l'enregistrement sélectionné.
La solution
Vous mettez probablement la mise en œuvre du message de remplacement des deux grilles.Gridx Scrolls Gridy, qui tourne à son tour gridx, qui à son tour ... SO.Vous pouvez protéger le code de défilement superficiel en entourant le bloc avec des drapeaux.
type
TForm1 = class(TForm)
[..]
private
FNoScrollGridX, FNoScrollGridY: Boolean;
[..]
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
if not FNoScrollGridX then
begin
FNoScrollGridX := True
gridY.SetActiveRow( gridX.GetActiveRow );
gridY.Perform( Msg.Msg, Msg.wParam, Msg.lParam );
// SetScrollPos( gridY.Handle, SB_VERT, HIWORD( Msg.wParam ), True );
end;
FNoScrollGridX := False;
end;
end;
code similiaire pour la gridy.BTW, vous n'avez pas besoin de setscrollpos.
EDIT:
TForm1 = class(TForm)
[..]
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_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.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_MOUSEWHEEL:
begin
ActiveControl := GridX;
GridY.Perform(Msg.Msg, Msg.WParam, Msg.LParam);
end;
WM_DESTROY:
begin
SetWindowLong(GridY.Handle, GWL_WNDPROC, Longint(GridYSaveWndProc));
Classes.FreeObjectInstance(GridYWndProc);
end;
end;
end;
Autres conseils
J'ai eu une solution de travail partielle, mais maintenant complète (au moins pour deux TMEMO) ...
Je veux dire partiel, car il n'écoute que des changements sur un TMEMO mais pas de l'autre ...
Je veux dire complet fonctionnant parce qu'il ne dépend pas de ce qui est fait ...
Il est aussi simple que de mettre la même valeur de défilement horizontale sur un mémo que sur l'autre ...
Ce n'est rien de liaison avec les messages, mais puisque j'essayais d'obtenir une solution de travail en piégeant des messages wm_hscroll, etc ... j'ai quitté le code parce qu'il fonctionne ... Je vais essayer de l'améliorer plus tard ... pour Exemple piéger uniquement Wm_paint, ou d'une autre manière ... mais pour l'instant, je l'ai dit comme je l'ai car cela fonctionne ... et je n'ai trouvé que quelque chose de mieux ...
Voici le code qui fonctionne:
// On private section of TForm1
Memo_OldWndProc:TWndMethod; // Just to save and call original handler
procedure Memo_NewWndProc(var TheMessage:TMessage); // New handler
// On implementation section of TForm1
procedure TForm1.FormCreate(Sender: TObject);
begin
Memo_OldWndProc:=Memo1.WindowProc; // Save the handler
Memo1.WindowProc:=Memo_NewWndProc; // Put the new handler, so we can do extra things
end;
procedure TForm1.Memo_NewWndProc(var TheMessage:TMessage);
begin
Memo_OldWndProc(TheMessage); // Let the scrollbar to move to final position
Memo2.Perform(WM_HSCROLL
,SB_THUMBPOSITION+65536*GetScrollPos(Memo1.Handle,SB_HORZ)
,0
); // Put the horizontal scroll of Memo2 at same position as Memo1
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
Memo1.WindowProc:=Memo_OldWndProc; // Restore the old handler
end;
Cela fonctionne pour toutes les manières de faire défiler pour changer ...
Notes:
- Je sais que c'est horrible pour piéger tous les messages, mais au moins fonctionne ...
- C'est ma première tentative réussie d'avoir deux TMEMOS avec synchronisation Barre de défilement horizontale ...
- Donc, si quelqu'un peut l'améliorer un peu (ne pas piéger tous les messages) s'il vous plaît Faites-le et postez-le.
- Cela ne fait que MEMO1 d'être sur la synchronisation horizontale avec la barre MEMO2, mais pas Mémo2 à être synchronisé avec MEMO1
- appuyez sur les touches de presse, vers le bas, gauche, droite, la molette, etc. Quoi que vous Vous voulez, mais sur mémo2 de le voir en action
Je vais essayer de l'améliorer par: lorsque vous faites quelque chose sur mémo2, le défilement mémo1 est toujours sur Sync ...
Je pense que cela peut fonctionner pour tout tout contrôle qui a une barre de défilement, non seulement TMEMO ...
Comme je l'ai dit ...
Voici une meilleure solution (non finale) en termes d'efficacité, de code de nettoyage et de la bidirectionnelle ... Changez sur n'importe qui affecte l'autre ...
S'il vous plaît, lisez les commentaires sur le code pour comprendre qu'est-ce que chaque phrase ... c'est assez délicat ... mais l'idée principale est la même que celle qui était avant ... Définissez l'autre barre de défilement horizontal TMEMO horizontal telle qu'elle est sur le TMEMO où l'utilisateur agit ... Peu importe ce que l'utilisateur fait, déplacez la souris et sélectionnez le texte, appuyez sur la touche gauche, droite, à la maison, les touches d'extrémité, utilisez la roue horizontale de la souris (pas toutes), faites glisser la srollbar, appuyez sur n'importe quelle pièce. de la barre de défilement horizontale, etc ...
L'idée principale est ... L'objet doit être re-peint, alors mettez ensuite l'autre barre horizontale d'objet identique à celle-ci ...
Cette première partie est juste d'ajouter des choses à la classe Tmemo, il ne s'agit que de créer une nouvelle classe dérivée, mais avec le même nom de classe, mais uniquement pour l'unité de l'unité déclarée.
Ajoutez ceci à la section d'interface, avant votre déclaration Tform, vous verrez donc votre nouvelle classe TMEMO au lieu de normale:
type
TMemo=class(StdCtrls.TMemo) // Just to add things to TMemo class only for this unit
private
BusyUpdating:Boolean; // To avoid circular stack overflow
SyncMemo:TMemo; // To remember the TMemo to be sync
Old_WindowProc:TWndMethod; // To remember old handler
procedure New_WindowProc(var Mensaje:TMessage); // The new handler
public
constructor Create(AOwner:TComponent);override; // The new constructor
destructor Destroy;override; // The new destructor
end;
Cette partie suivante est la mise en œuvre des déclarations précédentes de cette nouvelle classe TMEMO.
Ajoutez ceci à la section de mise en œuvre partout où vous préférez:
constructor TMemo.Create(AOwner:TComponent); // The new constructor
begin
inherited Create(AOwner); // Call real constructor
BusyUpdating:=False; // Initialize as not being in use, to let enter
Old_WindowProc:=WindowProc; // Remember old handler
WindowProc:=New_WindowProc; // Replace handler with new one
end;
destructor TMemo.Destroy; // The new destructor
begin
WindowProc:=Old_WindowProc; // Restore the original handler
inherited Destroy; // Call the real destructor
end;
procedure TMemo.New_WindowProc(var Mensaje:TMessage);
begin
Old_WindowProc(Mensaje); // Call the real handle before doing anything
if BusyUpdating // To avoid circular stack overflow
or
(not Assigned(SyncMemo)) // If not yet set (see TForm1.FormCreate bwlow)
or
(WM_PAINT<>Mensaje.Msg) // If not when need to be repainted to improve speed
then Exit; // Do no more and exit the procedure
BusyUpdating:=True; // Set that object is busy in our special action
SyncMemo.Perform(WM_HSCROLL,SB_THUMBPOSITION+65536*GetScrollPos(Handle,SB_HORZ),0); // Send to the other TMemo a message to set its horizontal scroll as it is on this TMemo
BusyUpdating:=False; // Set that the object is no more busy in our special action
end;
Maintenant la dernière partie, dites à chaque TMEMO quel est l'autre mémo qui doit être synchronisé.
sur votre section de mise en œuvre, pour le formulaire 1 Create Event Ajoutez quelque chose comme ceci:
procedure TForm1.FormCreate(Sender: TObject);
begin
Memo1.SyncMemo:=Memo2; // Tell Memo1 what TMemo must sync (Memo2)
Memo2.SyncMemo:=Memo1; // Tell Memo2 what TMemo must sync (Memo1)
end;
N'oubliez pas que nous avons ajouté le membre SyncMemo à notre nouvelle classe Tmemo spéciale, c'était là pour cela, dis-on ce que l'on est l'autre.
Maintenant, une petite configuration pour Tmemo Jsut pour laisser cela fonctionner parfaitement:
- laissez les deux barres de défilement TMEMO pour être visibles
- Laissez WordWrap False sur TMEMO
- Mettez beaucoup de texte (idem pour les deux), de longues lignes et beaucoup de lignes
exécutez-le et voyez comment les barres de défilement horizontales sont toujours sur Sync ...
- Si vous déplacez une barre de défilement horizontale, l'autre barre de défilement horizontale Déplace ...
- Si vous allez sur le texte à droite ou à gauche, ligne de départ ou ligne de ligne, etc ..., peu importe où se trouve Selstart sur l'autre ... l'horizontal Le texte du texte est sur Sync.
Le problème pourquoi ce n'est pas une version finale, c'est que:
- Les barres de défilement (horizontales dans mon boîtier) ne peuvent pas être cachées ... car si on est caché, lorsque vous appelez GetcrollPOS, il ne renvoie pas zéro.
Si quelqu'un sait comment émuler caché ou faire des grossités pour ne pas retourner zéro, veuillez commenter la seule chose que je dois corriger pour la version finale.
Notes:
- évidemment la même chose peut être fait avec une barre de défilement verticale ... juste changer WM_HScroll To WM_VScroll et SB_HORZ à SB_VERT
- De toute évidence, la même chose peut être faite pour les deux en même temps ... il suffit de copier la ligne SyncMemo.performez deux fois et sur une Laissez WM_HScroll et SB_HORZ et SB_HORZ et sur l'autre Laissez WM_VScroll et SB_VERT
Voici un exemple de procédure de nouvelle_WindowOWPROC pour synchroniser les barres de défilement à la fois, peut-être pour les paresseux, peut-être pour les gens comme copie et pâte:
procedure TMemo.New_WindowProc(var Mensaje:TMessage);
begin
Old_WindowProc(Mensaje); // Call the real handle before doing anything
if BusyUpdating // To avoid circular stack overflow
or
(not Assigned(SyncMemo)) // If not yet set (see TForm1.FormCreate bwlow)
or
(WM_PAINT<>Mensaje.Msg) // If not when need to be repainted to improve speed
then Exit; // Do no more and exit the procedure
BusyUpdating:=True; // Set that object is busy in our special action
SyncMemo.Perform(WM_HSCROLL,SB_THUMBPOSITION+65536*GetScrollPos(Handle,SB_HORZ),0); // Send to the other TMemo a message to set its horizontal scroll as it is on this TMemo
SyncMemo.Perform(WM_VSCROLL,SB_THUMBPOSITION+65536*GetScrollPos(Handle,SB_VERT),0); // Send to the other TMemo a message to set its vertical scroll as it is on this TMemo
BusyUpdating:=False; // Set that the object is no more busy in our special action
end;
J'espère que quelqu'un peut résoudre le problème de la barre de défilement caché et de retrouver zéro !!!
J'ai trouvé une solution ... Je sais que c'est assez délicat ... mais au moins il est entièrement fonctionnel ...
Au lieu d'essayer de masquer la barre de défilement horizontale ... Je le fais d'être affiché hors de la zone visible. Il ne peut donc pas être vu par l'utilisateur ...
la partie délicate:
- Mettez un TPanel où le TMEMO est et mettez le TMEMO à l'intérieur du TPANEL
- Masquer les frontières TPanel, mettre à la frontière avec 0, et tous biseaux à bvnone / bknone
- Configurez TMEMO Aligner sur Altop, non à Alclient, etc ...
- manipulez TPANEL.Enresize pour faire de tmemo.Height plus gros que TPanel.Height autant que la hauteur de la barre de défilement horizontale (au moment où j'utilise une valeur constante de 20 pixels, mais j'aimerais savoir comment obtenir la valeur réelle) < / li>
C'est ça ... fait !!! La barre de défilement horizontale est sorti de la zone visible ... Vous pouvez mettre à l'endroit où vous voulez le TPanel, lui donner la taille que vous souhaitez ... Cette barre de défilement horizontale ne sera pas vue par l'utilisateur et il n'est pas masqué, alors Getscrollpos fonctionnera correctement ... difficiles je sais, mais entièrement fonctionnelle.
Voici le code complet pour archiver que:
sur la section d'interface, avant votre déclaration Tform, vous verrez donc cette nouvelle classe TMEMO au lieu de normale:
type
TMemo=class(StdCtrls.TMemo) // Just to add things to TMemo class only for this unit
private
BusyUpdating:Boolean; // To avoid circular stack overflow
SyncMemo:TMemo; // To remember the TMemo to be sync
Old_WindowProc:TWndMethod; // To remember old handler
procedure New_WindowProc(var Mensaje:TMessage); // The new handler
public
constructor Create(AOwner:TComponent);override; // The new constructor
destructor Destroy;override; // The new destructor
end;
sur la section de mise en œuvre partout où vous préférez:
constructor TMemo.Create(AOwner:TComponent); // The new constructor
begin
inherited Create(AOwner); // Call real constructor
BusyUpdating:=False; // Initialize as not being in use, to let enter
Old_WindowProc:=WindowProc; // Remember old handler
WindowProc:=New_WindowProc; // Replace handler with new one
end;
destructor TMemo.Destroy; // The new destructor
begin
WindowProc:=Old_WindowProc; // Restore the original handler
inherited Destroy; // Call the real destructor
end;
procedure TMemo.New_WindowProc(var Mensaje:TMessage);
begin
Old_WindowProc(Mensaje); // Call the real handle before doing anything
if (WM_PAINT<>Mensaje.Msg) // If not when need to be repainted to improve speed
or
BusyUpdating // To avoid circular stack overflow
or
(not Assigned(SyncMemo)) // If not yet set (see TForm1.FormCreate bwlow)
then Exit; // Do no more and exit the procedure
BusyUpdating:=True; // Set that object is busy in our special action
SyncMemo.Perform(WM_HSCROLL,SB_THUMBPOSITION+65536*GetScrollPos(Handle,SB_HORZ),0); // Send to the other TMemo a message to set its horizontal scroll as it is on this TMemo
BusyUpdating:=False; // Set that the object is no more busy in our special action
end;
également sur la section de mise en œuvre partout où vous préférez:
procedure TForm1.FormCreate(Sender: TObject);
begin
Memo1.SyncMemo:=Memo2; // Tell Memo1 what TMemo must sync (Memo2)
Memo2.SyncMemo:=Memo1; // Tell Memo2 what TMemo must sync (Memo1)
end;
procedure TForm1.pnlMemo2Resize(Sender: TObject);
begin
Memo2.Height:=pnlMemo2.Height+20; // Make height enough big to cause horizontal scroll bar be out of TPanel visible area, so it will not be seen by the user
end;
Les gens de Thas! Je sais que c'est assez délicat, mais entièrement fonctionnel.
Veuillez noter que j'ai changé sur NEW_WindowProc à l'ordre d'évaluation de la ou des conditions ... Il s'agit simplement d'améliorer la vitesse de tous les autres messages, alors retardez le moins possible tous les messages.
J'espère bien, je saurai comment remplacer telle 20 par la hauteur de barre de défilement horizontale réelle (calculée ou lue) TMEMO.
Merci pour GetSystemMetrics
et SM_CYHSCROLL
, mais il n'est pas juste assez...juste besoin de 3 pixels en plus...
Donc je viens de l'utiliser: GetSystemMetrics(SM_CYHSCROLL)+3
Note:Deux de ces pixels pourrait être parce que d'avoir un parent panneau avec BevelWidth
avec la valeur 1
mais j'ai BevelInner
et BevelOuter
avec la valeur bvNone
afin de ne pas l'être;mais le pixel supplémentaire je ne sais pas pourquoi.
Merci beaucoup.
Si vous préférez, vient se joindre à eux sur un Gros post, mais je pense qu'il est préférable de ne pas les mélanger.
En réponse à "Sertac Akyuz" (désolé pour le faire ici, mais je ne sais pas comment les poster à côté de votre question):
- Je mets ici les solutions que j'ai trouvé comme je les ai trouvés...mon intention était ne pas l'utiliser comme un tampon...je discobered la solution juste quelques secondes avant d'écrire les messages
- Je pense que c'est mieux de voir les anciens posts, plutôt que la modification de multiplier fois le même post...il ne sera pas aussi laisser les autres savoir la solution exacte, aussi leur permettra de savoir comment parvenir à une telle solution.
- J'préférez faire les choses dans un sens comme "apprendre à pêcher plutôt que de donner l' les poissons".
- Je n'ai pas ouvert une nouvelle question juste parce que le titre de celui-ci est juste exacte de ce que j'essayais de faire
Important:Je découvre qu'une solution ne peut pas être fait par le message de la capture car il y a un cas qui provoque le défilement, mais pas de message WM_VSCROLL
, WM_HSCROLL
(uniquement WM_PAINT
)...elle est liée à la sélection de texte avec la souris...laissez-moi vous expliquer comment je vois les choses dans l'action...Juste commencer vers la fin de la dernière ligne visuelle et déplacez la souris seulement un peu plus bas, puis arrêter le déplacement de la souris et laissez le bouton de la souris enfoncé...sans rien faire (la souris ne bouge pas, pas de keyup, pas de bas, pas de bouton de la souris, changement, etc...) le TMemo est le défilement vers le bas jusqu'à atteindre la fin du texte...meme chose pour les horizontales défile quand la souris est près de l'extrémité droite de la ligne visuelle et déplacé à droite...également dans des directions opposées...ces parchemins n'est pas à travers des messages WM_VSCROLL
WM_HSCROLL
, seulement WM_PAINT
(au moins sur mon ordinateur)...de même qu'il se passe sur les Grilles.