Delphi-Tips-3 (Delphiの情報) |
---|
'98-Nov.-01st 初出
項 目 | 初 出 | 訂正・加筆 |
●メモなどの縦方向のスクロールを検知したい | '98-11-01 |
[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;