문제

내가 하려고 동기화 스크롤 두 TDBGrid 구성 요소에 VCL Forms 응용 프로그램,나는 어려움을 겪을 차단하 WndProc 각각의 그리드 구성 요소는 없는 몇 가지 스택 문제입니다.가를 보내 WM_VSCROLL 메시지에서 스크롤을 행사하지만 이것은 여전히 잘못된 작업입니다.그것을 요구하는 작업에 대한 스크롤 막대를 클릭 강조뿐만 아니라,셀,거나 또는 아래로 마우스 버튼을 클릭합니다.전체적인 아이디어는 두 개의 그리드를 다시 정렬의 일치합니다.

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

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;

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;

첫 번째 단지 임시 해결책이고,두 번째 결과에 잘못된 메모리 읽기,그리고 세 번째 결과는 스택에서 오버플로우가 발생합니다.그래서 아무도 이러한 솔루션을 작동하는 것 같습니다.나는 사랑의 일부 입력하는 방법에 대하여 이 작업을 수행!미리 감사드립니다.

업데이트:솔루션

  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;

사-Sertac Akyuz 에 대한 솔루션입니다.통합 된 경우에 VCL 양식을 사용하여 응용 프로그램 그리드,그들은 mimmic 에서 서로 스크롤하고 강조하는 선택한 기록합니다.

도움이 되었습니까?

해결책

두 개의 그리드에 대한 메시지 무시를 구현할 것입니다.GridX는 Gridy를 스크롤합니다. 차례로 그리드를 스크롤합니다.플래그로 블록을 둘러싸고 피상적 인 스크롤 코드를 보호 할 수 있습니다.

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

그리드의 비슷한 코드.BTW, 당신은 setscrollpos가 필요하지 않습니다.


편집 :

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

다른 팁

어 부분,하지만 지금은 전체 작업 솔루션(적어도 두 개의 TMemo)...

나는 의미한 부분이기 때문에,그것만 들어에 대한 변경 사항 중 하나에 TMemo 하지만 다른...

내 말은 전체 작업하기 때문에 그것에 의존하지 않는 것...

그것은 그렇게 간단으로 동일한 수평 스크롤 값을에 하나의 메모로 그것은 다른...

그것은 아무것도와 관련된 메시지,하지만 난 이후을 얻으려고 작업 솔루션을 포획하여 메시지 WM_HSCROLL,etc....내가 왼쪽의 코드 작동하기 때문에...나는 그것을 개선하기 위해 노력할 것입니다.예를 들어 트랩만 WM_PAINT,또는 다른 방법으로...하지만 지금,나는 그것을 둘로 나아가기 때문에 그것으로 작동하는 것을...고 하지 않았을 찾아 어디서나가 아직다.

여기에서 작동하는 코드:

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

그것은 작품에 대한 모든 방법을 확인 스크롤을 변경하...

Notes:

  • 나는 그것이 무서는 모든 메시지,하지만 적어도 작동하는지...
  • 이것은 첫 성공적인 시도가 있는 두 개의 TMemos 과 함께 동기화 수평 스크롤...
  • 그래서 누군가가 그것을 향상시킬 수 있습니다 조금(하지 않는 모든 메시지)하십시오 그것을 게시 할 수 있습니다.
  • 그것만 Memo1 에 수평과 동기화 Memo2 바하지만, Memo2 하는 것에 동 Memo1
  • Press 키,아래로,왼쪽,오른쪽 마우스 휠,etc....당신 하지만에 Memo2 하는 행동에 참조

나는 그것을 개선하기 위해 노력할 것입 by:을 수행할 때에 Memo2,Memo1 스크롤전에 동기화...

나는 그것을 위해 일할 수 있 사실 어떤 제어하는 스크롤하지만 TMemo...

내가 말했듯이 ...

효율성, 청결한 코드 및 양방향 측면에서 더 나은 솔루션 (최종 1이 아님) ... 다른 사람이 다른 것에 영향을 미치는 것으로 변경 ...

코드에 대한 의견을 읽으려면 각 문장을 이해하는 것입니다 ... 그것은 아주 까다로운 것입니다 ... 그러나 주요 아이디어는 이전과 같습니다 ... 다른 TMemo 가로 스크롤 막대를 설정하십시오. 사용자가 작동하는 TMEMO ... 사용자가 어떤 사용자가 수행하고 마우스를 이동하고 텍스트를 선택하고 왼쪽, 오른쪽, 집, 끝 키를 누르고 마우스 가로 휠을 사용하거나 SrollBar를 드래그하고 일부 파트를 끕니다. 수평 스크롤 막대 등 ...

주요 아이디어는 ... 객체를 다시 그려져야하므로 다른 오브젝트 가로 스크롤 막대를이 하나와 동일하게 놓아야합니다 ...

이 첫 번째 부분은 TMemo 클래스에 작업을 추가하는 것입니다. 새로운 파생 클래스를 만들지 만 동일한 클래스 이름을 사용하고 있지만 선언 된 장치에만 해당합니다.

TForm 선언 앞에 인터페이스 섹션에 추가하십시오. 그래서 TForm은 일반 1 대신이 새로운 TMemo 클래스를 볼 수 있습니다.

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

이 다음 부분은 이전 TMEMO 클래스의 이전 선언을위한 구현입니다.

이 사물을 구현 섹션에 추가하십시오 :

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

이제 마지막 부분은 각 tmemo에 동기화 해야하는 다른 메모가 무엇인지 알려줍니다.

구현 섹션에서 Form1 이벤트 생성이 이벤트를 추가하십시오.

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

우리는 우리가 특별한 새로운 TMemo 클래스에 syncmemo 회원을 추가했음을 기억하십시오, 이것은 그곳에는 다른 사람이 무엇인지, 서로에게 말합니다.

이제 TMEMO JSUT 모두 완벽하게 작업을 수행하도록 조금 구성합니다.

  • TMemo 스크롤 막대를 모두 표시 할 수있게
  • 는 tmemo
  • 모두에서 wordwrap false를 둡니다.
  • 텍스트를 많이 넣으십시오 (둘 다 동일하게), 긴 줄 및 라인의 많은 줄

실행하고 수평 스크롤 막대가 동기화 된 전원에있는 전경을 확인하십시오 ...

  • 하나의 가로 스크롤 막대를 하나, 다른 가로 스크롤 막대를 이동하는 경우 움직임 ...
  • 오른쪽 또는 왼쪽으로 텍스트를 켜면, 선 시작 또는 선 끝, 기타 ..., 다른 곳에있는 곳이 어디에 있더라도 ... 수평 텍스트 스크롤이 동기화됩니다.

이것이 최종 버전이 아닌 이유는 다음과 같습니다.

  • 스크롤 막대 (내 경우에 수평 하나)는 숨길 수 없습니다 ... 하나가 숨겨져 있으면 GetScrollPos를 호출 할 때 0을 반환하므로 동기화되지 않습니다.

누군가가 숨겨진 방법을 알고 있거나 GetScrollPoS를 Zero를 반환하지 않도록하는 방법을 알고 있으면, 의견을 말하면, 내가 최종 버전을 위해 수정 해야하는 유일한 것.

노트 :

  • 는 분명히 동일한 수직 스크롤 바와 함께 할 수 있습니다 ... 그냥 변경 WM_VSCROLL 및 SB_HORZ에 WM_VSCROLL 및 SB_VERT
  • 는 분명히 동일한 시간에 모두 동일한 시간에 완료 될 수 있습니다 ... 그냥 syncmemo.perform 라인을 두 번 복사 할 수 있습니다. WM_HSCROLL 및 sb_horz 및 다른 하나는 WM_VSCROLL 및 sb_VERT
  • 를 눌러줍니다.

여기에 Scrollbars를 동시에 동시에 동기화하는 New_WindowProc 절차의 예입니다. 아마도 게으른 사람을위한 것, 아마 복사 및 붙여 넣기와 같은 사람들에게 :

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

누군가가 숨겨진 한 스크롤 막대의 문제를 해결할 수 있고 0을 반환하는 GetScrollPoS !!!

솔루션을 발견했습니다 ... 나는 그것이 아주 까다로운 것을 알고 있습니다 ... 그러나 적어도 그것은 완전히 작동합니다 ...

가로 스크롤 막대를 숨기려고하는 대신 ... 나는 가시적 인 영역에서 표시되도록 만들 수 있으므로 사용자가 볼 수 없습니다 ...

까다로운 부분 :

  • tmemo가있는 tpanel을 넣고 tpanel
  • 내부에 tmemo를 넣습니다.
  • tpanel 테두리를 숨 깁니다, borderwith를 0으로 묶고, bvnone / bknone
  • 에있는 모든 베벨
  • ALTOR에 맞게 TMEMO 구성, 알 클라이언트 등 ...
  • tpanel.onresize tpanel.height를 tpanel.height보다 큰 수평 스크롤 막대 높이로 더 크게 만듭니다 (20 픽셀의 일정한 값을 사용하는 순간까지, 실제 가치를 얻는 방법을 알고 싶습니다) < / li>

그게 ... 완료! 수평 스크롤 막대가 눈에 보이는 영역에서 벗어납니다 ... TPanel을 원하는 위치를 넣을 수 있습니다. 원하는 크기를주십시오. 가로 스크롤 막대는 사용자가 볼 수 없으며 숨겨져 있지 않으므로 GetScrollPos가 제대로 작동하지 않습니다. ... 내가 알고 있지만, 완전히 기능적이지만,

여기에 아카이브하는 전체 코드는 다음과 같습니다.

인터페이스 섹션의 TForm 선언 이전에 TForm은 정상적인 Tmemo 클래스가 보일 것입니다.

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

어디에서나 구현 섹션에서 :

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

또한 프리 프 프리를 어디에서나 구현 섹션에서 :

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

thas it it weks! 나는 그것이 아주 까다 롭지 만 완전히 기능적이라는 것을 압니다.

New_WindowProc에서 또는 조건을 평가하는 순서를 변경했습니다 ... 다른 모든 메시지의 속도를 향상시키는 것입니다. 그래서 가능한 한 모든 메시지 치료를 가능한 한 덜 지연합니다.

희망을 실제 (계산 또는 읽히지) TMemo 수평 스크롤 막대 높이로 20을 교체하는 방법을 알게 될 것입니다.

GetSystemMetricsSM_CYHSCROLL에 감사드립니다.하지만뿐만 아니라 만지지 않습니다 ... 그냥 3 픽셀 더 필요해 ...

그래서 방금 사용합니다 : GetSystemMetrics(SM_CYHSCROLL)+3

참고 : BevelWidth 값이있는 1가있는 BevelInner가있는 상위 패널을 갖는 두 개의 픽셀 중 두 개의 픽셀은 BevelOuter 값을 갖는 bvNone가 있기 때문에 그렇지 않을 수 있습니다. 그러나 내가 여분의 픽셀은 그 이유를 모른다.

감사합니다.

당신이 미리 전환되면 하나의 큰 게시물에 가입하십시오. 그러나 나는 그것이 그들을 섞지 않는 것이 더 좋지 않다고 생각합니다.

"Sertac Akyuz"에 대한 답변 (여기에서해서 미안하지만, 귀하의 질문 옆에 게시하는 방법을 모르겠습니다) :

  • 나는 여기에 내가 발견 한 솔루션을 발견했다. 내 의도는 그것을 스크래치 패드로 사용하지 마십시오 ... 게시물을 작성하기 전에 솔루션 JSUT 초를 Discobered
  • 곱하기 편집보다는 오래된 게시물을 보는 것이 낫다고 생각합니다. 똑같은 게시물의 시간 ... 다른 사람들이 정확한 솔루션을 알리지 않도록, 또한 그러한 해결책에 도달하는 방법을 알리십시오.
  • 나는 "물고기를 가르치는 것처럼 가르치는 것처럼"낚시하는 법을 가르치는 것처럼하는 것과 같은 일을 할 수 있습니다. 물고기 ".
  • 나는이 사람의 제목이 내가 뭘하려고했는지
  • 에 정확한 일이기 때문에 새로운 질문을 열지 않았다.

중요 : 스크롤을 일으키지 만 메시지가 없기 때문에 메시지 캡처로 완벽한 솔루션을 수행 할 수 없음을 발견합니다. WM_VSCROLL (WM_HSCROLL 만) ... 마우스로 텍스트를 선택하십시오 ... 내가 어떻게 그것을 볼 수 있는지 설명하겠습니다 ... 마지막 시각 선의 끝 근처에서 시작하고 마우스를 조금 움직이게 시작한 다음 마우스 이동을 중지하고 마우스 버튼을 누르지 않고 ...하지 않고 모든 것 (마우스가 움직이지 않고, 키프 없음, 키 다운 없음, 마우스 버튼이 변경되지 않음). tmemo는 텍스트의 끝에 도달 할 때까지 아래로 스크롤됩니다 ... 마우스가 오른쪽 끝에있을 때 가로 스크롤에 대해서도 가로 스크롤이 있습니다. 시각적 인 라인과 오른쪽으로 움직였습니다 ... 또한 그러한 스크롤은 WM_PAINT WM_VSCROLL (최소한 컴퓨터에서 적어도 WM_HSCROLL) 만 사용하지 않습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top