Domanda

Sto cercando di sincronizzare lo scorrimento di due componenti TDBGrid in un'applicazione VCL Forms, ho difficoltà a intercettare il WndProc di ciascun componente della griglia senza alcuni problemi di stack.Ho provato a inviare messaggi WM_VSCROLL sotto eventi di scorrimento, ma il risultato è ancora un'operazione errata.Deve funzionare per fare clic sulla barra di scorrimento, nonché per evidenziare una cella o un pulsante del mouse su o giù.L'idea è quella di avere due griglie una accanto all'altra che mostrino una sorta di finestra di dialogo corrispondente.

Provato

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

Anche

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;

E

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 prima è solo una soluzione temporanea, la seconda determina letture di memoria non valide e la terza determina un overflow dello stack.Quindi nessuna di queste soluzioni sembra funzionare per me.Mi piacerebbe qualche input su come eseguire questo compito!Grazie in anticipo.

AGGIORNAMENTO:Soluzione

  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;

Grazie a - Sertac Akyuz per la soluzione.Quando integrati in un'applicazione di moduli VCL utilizzando le griglie, si imiteranno a vicenda nello scorrimento e nell'evidenziazione del record selezionato.

È stato utile?

Soluzione

Probabilmente implementando l'override del messaggio per entrambe le griglie.Gridx Scrolls Gridy, che a sua volta scorre Gridx, che a sua volta ... così.È possibile proteggere il codice di scorrimento superficiale circondando il blocco con le bandiere.

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;
.

Codice simile per la griglia.A proposito, non hai bisogno del set di setCrollpos.


Modifica:

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;
.

Altri suggerimenti

Ho ottenuto una soluzione parziale, ma ora piena di lavoro (almeno per due TMEMO) ...

Intendo parziale, perché ascolta solo i cambiamenti su un tmemo ma non sull'altro ...

Intendo tutto il lavoro perché non dipende da ciò che è fatto ...

È altrettanto semplice come mettere lo stesso valore di scorrimento orizzontale su un memo come è sull'altro ...

Non è nulla di simile con i messaggi, ma dal momento che stavo cercando di ottenere una soluzione funzionante trapping messaggi wm_hscroll, ecc ... Ho lasciato il codice perché funziona ... cercherò di migliorarlo più tardi ... per Esempio di trapping solo wm_paint o in altri modi ... ma per ora, lo ho messo come ho da allora perché funziona ... e non ho trovato qualcosa ancora di meglio ...

Ecco il codice che funziona:

// 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;
.

funziona per tutti i modi per far scorrere per cambiare ...

Note:

    .
  • So che è orribile intrappolare tutti i messaggi, ma almeno opere ...
  • Questo è il mio primo tentativo di successo di avere due TMEMOS con sincronizzazione Scrollbar orizzontale ...
  • Quindi, se qualcuno può migliorarlo un po '(non intrappolare tutti i messaggi) per favore fallo e pubblicalo.
  • rende solo memo1 per essere sulla sincronizzazione orizzontale con la barra di memo2, ma non Memo2 per essere sincronizzato con MEMO1
  • Premere i tasti su, giù, sinistra, destra, mousewheel, ecc ... Qualunque cosa tu Vuoi ma su MEMO2 per vederlo in azione

Proverò a migliorarlo da: quando fai qualcosa su MEMO2, Memo1 Scroll è ancora su sincronizzazione ...

Penso che possa funzionare per tutto il massimo controllo che ha una barra di scorrimento, non solo tmemo ...

Come ho detto ...

Qui è una soluzione migliore (non finale) in termini di efficienza, codice pulito e bidirezionale ... cambiando su qualsiasi cosa colpisce l'altro ...

Per favore, leggi i commenti sul codice per capire cosa fa ogni frase ... è piuttosto complicabile ... ma l'idea principale è la stessa cosa prima ... imposta l'altra barra di scorrimento orizzontale TMEMO come è sul TMEMO in cui l'utente agisce ... Non importa quale utente fa, sposta il mouse e seleziona il testo, premere i tasti a sinistra, destra, casa, fine, utilizzare la ruota orizzontale del mouse (non tutti ne ha uno), trascina la Srollbar, premere su qualsiasi parte della barra di scorrimento orizzontale, ecc ...

L'idea principale è ... L'oggetto deve essere ri-verniciato, quindi inserire l'altro oggetto Scrollbar orizzontale identico identico a questo ...

Questa prima parte è solo per aggiungere cose alla classe TMEMO, sta solo creando una nuova classe derivata ma con lo stesso nome di classe, ma solo per l'unità all'interno dichiarata.

Aggiungi questa alla sezione Interfaccia, prima della dichiarazione TFORM, quindi la tua TFORM vedrà questa nuova classe TMEMO invece di una 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;
.

Questa parte successiva è l'implementazione per le dichiarazioni precedenti di quella nuova classe TMEMO.

Aggiungi questo alla sezione di implementazione ovunque tu prenota:

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;
.

Ora l'ultima parte, racconta a ogni TMEMO qual è l'altro memo che deve essere sincronizzato.

Nella tua sezione di implementazione, per il modulo1 Crea evento Aggiungi qualcosa del genere:

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;
.

Ricorda che abbiamo aggiunto Syncmemo Member alla nostra speciale nuova classe TMEMO, è stato lì solo per questo, si dire a vicenda quale è l'altro.

Ora una piccola configurazione per il TMEMO JSUT di far funzionare perfettamente questo:

    .
  • Lasciare che sia le barre di scorrimento di TMEMO siano visibili
  • Lascia che WordWraip falso sia su TMEMO
  • Metti un sacco di testo (stesso per entrambi), linee lunghe e un sacco di linee

Eseguilo e vedi come entrambe le barre di scorrimento orizzontali sono sempre su Sync ...

    .
  • Se si sposta una barra di scorrimento orizzontale, l'altra barra di scorrimento orizzontale Move ...
  • Se si va sul testo a destra o sinistra, la linea iniziale o la linea di linea, ecc ..., non importa dove è Selstart sull'altro ... l'orizzontale Il rotolo di testo è su sincronizzazione.

Il problema Perché questa non è una versione finale è quella:

    .
  • Le barre di scorrimento (orizzontale nella mia custodia) non possono essere nascoste ... poiché se uno è nascosto, quando si chiama GetsCrollPos ritorna a zero, quindi non lo rende su sincronizzazione.

Se qualcuno sa come emulare nascosto o rendere GetsCrollpos per non tornare a zero, si prega di commentare, è l'unica cosa che devo fissare per la versione finale.

Note:

    .
  • Ovviamente lo stesso può essere fatto con una barra di scorrimento verticale ... basta cambiare WM_HSCROLL a WM_VSCROLL e SB_HORZ a SB_VERT
  • Ovviamente lo stesso può essere fatto per entrambi allo stesso tempo ... Basta copiare SyncMemo.Perform Line due volte e su una lascia che WM_HSCROLL e SB_HORZ e sull'altro siano WM_VSCROLL e SB_VERT

Ecco un esempio di procedura New_WindowProc per sincronizzare entrambe le barre di scorrimento allo stesso tempo, forse per le persone pigre, forse per le persone proprio come copia e incolla:

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;
.

Spero che qualcuno possa risolvere il problema della barra di scorrimento nascosta e GetsCrollpos restituisce Zero !!!

Ho trovato una soluzione...so che è abbastanza complicato...ma almeno è perfettamente funzionante...

Invece di provare a nascondere la barra di scorrimento orizzontale...lo faccio in modo che venga visualizzato fuori dall'area visibile, quindi non può essere visto dall'utente...

La parte difficile:

  • Metti un TPanel dove si trova il TMemo e inserisci il TMemo all'interno del TPanel
  • Nascondi i bordi del TPanel, metti BorderWith a 0 e tutto Bevel su bvNone/bkNone
  • Configura TMemo Allinea ad alTop, non ad alClient, ecc...
  • Gestisci TPanel.OnResize per rendere TMemo.Height più grande di TPanel.Height tanto quanto l'altezza della barra di scorrimento orizzontale (per il momento utilizzo un valore costante di 20 pixel, ma vorrei sapere come ottenere il valore reale)

Questo è tutto...Fatto!!!La barra di scorrimento orizzontale è fuori dall'area visibile...puoi mettere dove vuoi il TPanel, dagli la dimensione che vuoi...quella barra di scorrimento orizzontale non sarà vista dall'utente e non è nascosta, quindi GetScrollPos funzionerà correttamente...complicato lo so, ma perfettamente funzionante.

Ecco il codice completo per archiviarlo:

Nella sezione dell'interfaccia, prima della dichiarazione di TForm, quindi il tuo TForm vedrà questa nuova classe TMemo invece di quella 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;

Nella sezione di implementazione ovunque preferisci:

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;

Anche nella sezione implementazione ovunque tu preferisca:

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;

Questo è tutto gente!So che è abbastanza complicato, ma perfettamente funzionante.

Tieni presente che ho modificato su New_WindowProc l'ordine di valutazione delle condizioni OR...è solo per migliorare la velocità di tutti gli altri messaggi, in modo da ritardare il meno possibile il trattamento di tutti i messaggi.

Spero che un giorno saprò come sostituire tali 20 con l'altezza reale della barra di scorrimento orizzontale TMemo (calcolata o letta).

Grazie per GetSystemMetrics e SM_CYHSCROLL, ma non è solo abbinato ... solo bisogno di 3 pixel altro ...

Quindi devo solo usare: GetSystemMetrics(SM_CYHSCROLL)+3

Nota: Due di tali pixel potrebbero essere dovuti a un pannello genitore con BevelWidth con valore 1 ma ho BevelInner e BevelOuter con valore bvNone, quindi potrebbe non farlo; Ma il pixel in più non so perché.

Grazie mille.

Se preferisci, unirti a loro su un grande post, ma penso che sia meglio non mescolarli.

In risposta a "Sertac Akyuz" (mi dispiace di farlo qui, ma non so come pubblicarli accanto alla tua domanda):

    .
  • Ho messo qui le soluzioni che ho trovato mentre li ho trovati ... la mia intenzione era Non usarlo come graffio ... Ho smobito la soluzione Jsut secondi prima di scrivere i post
  • Penso che sia meglio vedere vecchi post, piuttosto che modificare moltiplicare volte solo lo stesso post ... non permetterebbe anche agli altri conosco la soluzione esatta, inoltre farà sapere come raggiungere una tale soluzione.
  • Preferisco di fare le cose in un modo come "insegnare come pescare, piuttosto che dare il pesce ".
  • Non ho aperto una nuova domanda solo perché il titolo di questo è solo esatto quello che stavo cercando di fare

Importante : Scopro che una soluzione perfetta non può essere eseguita mediante catturazione del messaggio perché c'è un caso che provoca scorri ma nessun messaggio WM_VSCROLL, WM_HSCROLL (solo WM_PAINT) ... È correlato a Selezione del testo con il mouse ... lasciami spiegare come lo vedo in azione ... basta iniziare vicino alla fine dell'ultima linea visiva e spostare il mouse solo un po 'giù, quindi smettere di spostarsi il mouse e lasciare premuto il tasto del mouse ... senza fare il pulsante del mouse ... senza farlo qualsiasi cosa (il mouse non si muove, nessuna tastiera, nessuna tasca, nessun pulsante del mouse cambia, ecc ...) Il TMEMO sta scorrendo verso il basso fino a raggiungere la fine del testo ... Lo stesso accade per i percolle orizzontali quando il mouse è vicino all'estremità destra di linea visiva e spostata a destra ... anche uguale nelle direzioni opposte ... Tali scorrimenti non attraverso i messaggi WM_VSCROLL WM_HSCROLL, solo WM_PAINT (almeno sul mio computer) ... anche lo stesso accade sulle griglie.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top