PeekPassword+
http://www.vector.co.jp/download/file/win95/util/fh437024.html
のように、マウスをドラッグしているときに、
マウスが乗っているオブジェクトに独自(?)の枠を表示するには
どのようにすればよいのでしょうか?
よろしくお願い致します。
> マウスが乗っているオブジェクトに枠を表示するには
オブジェクトではなくウィンドウになりますが。
クリアすべきことが幾つかあり、どこまでは見当がついていてどこから検討がつかないのか分かりませんので、とりあえず流れだけ。
(1) Mouse.CursorPosで得られるマウス座標の下のウインドウハンドルをWindowFromPoint()APIで取得する。
(2) GetWindowRect()APIでそのウィンドウの位置とサイズ(Rext値)を得る。
(3) スクリーン用キャンバス(TCanvas)をCreateし、そのキャンバスハンドルにGetWindowDC(0)APIで得たスクリーンキャンバスのハンドルを渡す。
(4) スクリーン用キャンバスに先に得たRect値で矩形を描画する。
以上で、スクリーンへの描画ができます。
マウスが他のウィンドウに移動した場合、及びこの作業(マウス下のウィンドウを視覚的に確認できるよう矩形で囲む)が不要になった場合にはこの矩形を消去し元に戻さねばなりません。
TPen.Mode := pmNot で2度描画して消すのが一般的ですが、ウィンドウに矩形を描画した場合には、隣接するウィンドウにマウスが移った場合にうまく消えない場合もあります。
事例のソフトは pmNot を使用していないようです。
この場合の定石は目にしたことがありません。
工夫のしがいがあるところです。
事例として紹介されていたソフトは、ドラッグ中だけこの作業を継続し、MouseUpでこの作業を終了させています。
しかし、マウスをまったくクリックすることなく、単にスクリーン上を移動させるだけで矩形を描きたいのなら、描いた矩形の消去にはもう一工夫が必要になります。(最小化・最大化・閉じるなどのシステムメニュを実行してしまった場合など)
事例のソフトは、MouseUpでこの作業を終了させますが、もし同様の仕様にしたいのなら、アプリが非アクティブの場合にも、マウスがスクリーン上のどこにあってもマウスボタンが離されたことを補足しなければなりません。
スクリーンへの描画方法はそうたくさんあるわけではありませんが、具体的にやりたいこと・仕様を確定しないと検討範囲が絞れません。又、スクリーン用キャンバスCreateのタイミングなども変わってきます。
どういう契機で描画・消去・終了させるかを決めて示してもらわないと、これ以上具体的なアプローチは難しいかと。
さどやま様、レスありがとうございます。
自分が作成したいソフトは、ウィンドウハンドルやボタンやキャプションなどマウスドラッグ中にそのターゲットのステータス(?)を取得するプログラムです。
マウスドラッグ中にターゲットにしているオブジェクトが視覚的に分かりやすいようにと思いまして、上記のソフトを例にして書き込みさせて頂きました。
流れとしては大体掴めたので挑戦したいと思います。
真琴:「ねぇ、ハルコさん、ハルコさん、ちょっと来てぇ〜」
春子:「どうした? マコト」
真琴:「面白そうだからぁ、アタシ、ちょっとプログラム書いてみたの」
春子:「ン? なにを?」
真琴:「これよ、ハルコさん」
var
hW, pW: HWND;
procedure DrawFrameRect(W: HWND);
var
R: TRect;
begin
if W = 0 then exit;
with TCanvas.Create do try
Handle := GetWindowDC(0); // スクリーンのDC
Brush.Style := bsClear;
Pen.Mode := pmXOR;
Pen.Color := clRed xor Brush.Color;
Pen.Width := 3;
GetWindowRect(W, R);
Rectangle(R.Left, R.Top, R.Right-2, R.Bottom-2);
finally
Free;
end;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
var
P: TPoint;
begin
GetCursorPos(P);
hW := WindowFromPoint(P);
if (pW <> hW) then begin
DrawFrameRect(pW);
DrawFrameRect(hW);
pW := hW;
end;
end;
procedure TForm1.Edit1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Button = mbLeft then begin
pW := 0;
Timer1.Interval := 50;
Timer1.Enabled := True;
end;
end;
procedure TForm1.Edit1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
Timer1.Enabled := False;
DrawFrameRect(hW);
end;
真琴:「Edit1の上でマウスの左ボタン押してぇ、そのまま、マウス動かすとぉ…」
春子:「ふ〜ん、マウスポインタの所のWindowに赤い枠が…、なかなかヤルじゃないの、マコト」
真琴:「でしょ?」
春子:「だけど、マコト、これって複数のWindowが少し重なってる時に、下のWindowにマウス動かすと…」
真琴:「ジツはそうなンだぁ、上側のWindowの所にも赤枠が描かれちゃうの、だからぁ…」
春子:「上側のWindowが自動的に描き換えられた場合に、赤枠が消えずに残っちゃうね」
真琴:「ぅン、そうなのねぇ…これ、なんとかならないかなァ」
春子:「簡単よ、マコト、重なった部分の上側には赤枠が描かれないようにすればいいんじゃない」
真琴:「えっ、カンタン?、そうなの?」
春子:「ココだけ、このようにぃ…チョット書き換えれば…、これで…ヨシ、試してごらん、マコト」
procedure DrawFrameRect(W: HWND);
var
R: TRect;
begin
if W = 0 then exit;
with TCanvas.Create do try
// Handle := GetWindowDC(0); // スクリーンのDC
Handle := GetWindowDC(W); // 対象WindowのDC
Brush.Style := bsClear;
Pen.Mode := pmXOR;
Pen.Color := clRed xor Brush.Color;
Pen.Width := 3;
GetWindowRect(W, R);
// Rectangle(R.Left, R.Top, R.Right-2, R.Bottom-2); // スクリーン上に描画
Rectangle(0, 0, R.Right-R.Left-2, R.Bottom-R.Top-2); // 対象Window上に描画
finally
Free;
end;
end;
真琴:「あっ!、ホント」
春子:「ね?、ちゃんとウマクいくでしょ」
真琴:「こんなにカンタンに直せたのネ」
春子:「ま、発想の転換ってコトかな?」
客A:「あのぉ〜、予約していた者ですけどぉ〜」
真琴:「あ、お客さんが…」
春子:「え?、…アッ、はいはい、ご予約の方ですネ、今すぐ…、あっ、ア〜ッ!!」
*ドタン!!*
春子:「イタ〜ぁ…」
真琴:「ハルコさん、カラダの転換のほうは…、もう歳?」
春子:「ミソジ前のレディになんてコト言うの、代わりに部屋にお客様 ご案内して…アッイタタぁ〜」
もう歳?まだミソジ前様、レスありがとうございます。
サンプルコードを参考にさせて頂きまして、上手く動作しております。
勉強させていただきます。
さどやま様、もう歳?まだミソジ前様、本当にありがとうございます。
ツイート | ![]() |