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