'98-Nov.-01st Updated.


Delphi-Tips-3
(Delphiの情報)


Delphi-Tipsのパート3です。
パート1パート2とあわせてお使い下さい。

'98-Nov.-01st 初出



質問一覧

項   目 初 出 訂正・加筆
●メモなどの縦方向のスクロールを検知したい '98-11-01


from: <Mr.ARAI and CASA>
[Q] メモなどの縦方向のスクロールを検知したい

[A] スクロールの仕方により、2種類のメッセージが発生しますので、両方を処理します。
まず、キーでスクロールしたり、コピーアンドペーストでスクロールした時、そしてスクロールバーをクリックすると、EN_VSCROLLがフォームに飛んできます。
この時、スクロールバーの真ん中にあるスクロールボックスをクリックしただけで、実際はスクロールしなくともメッセージが発生する事に注意が必要です。
また、スクロールボックスをドラッグした場合、WM_VSCROLLがコントロール(メモやリッチエディット)に飛んできます。
前者は、フォームの WM_COMMANDメッセージハンドラで処理し、後者はコントロールのWindowProc手続きで処理します。
両者の処理は、例えば以下のようにします。

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
  private
    DragCount: integer;
    EtcCount: integer;
    OldPos,NewPos: integer;
    WindowProc: TWndMethod;
    procedure MyWindowProc(var Message: Tmessage);
    procedure WMCommand(var Message: TWMCommand); message WM_COMMAND;
  public
    { Public 宣言 }
  end;
  :
  :
  
implementation

// --------------------------
// フォーム生成時
procedure TForm1.FormCreate(Sender: TObject);
begin
  DragCount := 0;
  EtcCount := 0;
  OldPos := 0;
  NewPos := 0;
  WindowProc := Memo1.WindowProc;
  Memo1.WindowProc := MyWindowProc;
end;

// --------------------------
// フォームのメッセージ処理時
procedure TForm1.WMCommand(var Message: TWMCommand);
begin
  // Drags scroll boxをドラッグする場合を除いた
  // 縦スクロールメッセージがここ発生する
  if Message.NotifyCode = EN_VSCROLL then
  begin
    // Drags scroll boxをクリックするだけでWM_VSCROLLが発生するので、
    // nPosを見て判断するが、初期値0と異なる場合を補正する。
    // 複数ScrollBarを持つコントロールがある場合もあるので、
    // 目的のコントロールを識別する
    if Message.Ctl = Memo1.Handle then
    begin
      NewPos := GetScrollPos(Memo1.Handle,SB_VERT);
      OldPos := NewPos;
      Inc(EtcCount);
      Label2.Caption := 'Drags scroll boxのDrag以外の移動=' + IntToStr(EtcCount);
      Label3.Caption := '合計=' + IntToStr(DragCount + EtcCount);
    end;
  end;
  // 本来の動作を行なう
  inherited;
end;

// --------------------------
// Memo1のメッセージ処理時
procedure TForm1.MyWindowProc(var Message: Tmessage);
begin
  // 縦スクロールでDrags scroll boxの位置を指示された時
  if (Message.Msg = WM_VSCROLL) and
    (Message.WParamLo = SB_THUMBTRACK) then
  begin
    // Drags scroll boxをクリックするだけでWM_VSCROLLが
    // 発生することに注意。nPosが異なる場合をカウントする。
    // Drags scroll boxの位置を保存
    OldPos := NewPos;
    // Drags scroll boxの指示位置を得る
    NewPos := TWmVScroll(Message).Pos;  // Message.WParamHi でも良い。(nPos=WParamHi)
    // 異なっていればドラッグ中
    if NewPos <> OldPos then
    begin
      Inc(DragCount);
      Label1.Caption := 'Drags scroll boxのDrag移動=' + IntToStr(DragCount);
      Label3.Caption := '合計=' + IntToStr(DragCount + EtcCount);
    end;
  end;
  // 待避していた本来の動作を行なう
  WindowProc(Message);
end;

質問一覧に戻る



Delphi神殿に戻る

Delphi-TIPS(1)に戻る

Delphi-TIPS(2)に戻る


ご意見、間違いのご指摘などは、 sakai@nasu-net.or.jp までお寄せください。