こんにちわ。
D&Dで画像を取得するように作成しているのですが、
複数のimageコンポーネントがあり(image1とimage2)どこに
マウスのポイントがあたっているかを取得したいのですが、
image.Handleというのはないようで困ってます。
procedure TForm1.DropFiles(var Msg:TWMDROPFILES);
var
WinHnd : HWND;
fn : array [0..MAX_PATH] of Char;
P:TPoint;
begin
DragQueryFile(Msg.Drop, 0, fn, MAX_PATH);
DragQueryPoint(Msg.Drop, P);
WinHnd:= WindowFromPoint(ClientToScreen(P));
//** ここでWinHnd の中身を調べてimage1かimage2かを調べたい。
if WinHnd=Image1のハンドル then
begin
Image1.Picture.LoadFromFile(fn);
img_b.Text := fn;
end;
if WinHnd=Image2のハンドルthen
begin
Image2.Picture.LoadFromFile(fn);
img_s.Text := fn;
end;
DragFinish(msg.Drop);
end;
image1かimage2のどちらの上にマウスが来たかをわかるようにしたいのですが、どのように取得すればよいのでしょうか?
宜しくお願致します。
TImage は TWinControl の派生クラスではないのでハンドルはありません。
TForm のControlAtPos メソッドをつかいます。ヘルプより
ControlAtPos メソッドは,コントロール内の指定位置にある子コントロールを返します。
function ControlAtPos(const Pos: TPoint; AllowDisabled: Boolean, AllowWinControls:Boolean=False): TControl;
かえってきた TControl を TImage にキャストすると、そのまま操作できます。
最初に is で型チャックを忘れずに。
かきくけこ さんありがとうございました。
Control := ControlAtPos(p,true, False);
でコントロールを取得しました。
(引数のパラメータが良くわからなかったんですけど、、)
>かえってきた TControl を TImage にキャストすると、そのまま操作できます。
調べたのですがみつかりません。
どのようにキャストするのでしょうか?
宜しくお願致します。
例をあげます。新規で試してください。Form1 に
Image1: TImage;
Image2: TImage;
PaintBox1: TPaintBox;
ApplicationEvents1: TApplicationEvents;
をデフォルトのサイズでおいてください。そして
procedure TForm1.FormCreate(Sender: TObject);
begin
with Image1 do begin
Picture.Bitmap.Width := Width;
Picture.Bitmap.Height := Height;
Picture.Bitmap.Canvas.Brush.Color := clLime;
Picture.Bitmap.Canvas.FillRect(ClientRect);
end;
with Image2 do begin
Picture.Bitmap.Width := Width;
Picture.Bitmap.Height := Height;
Picture.Bitmap.Canvas.Brush.Color := clAqua;
Picture.Bitmap.Canvas.FillRect(ClientRect);
end;
end;
procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG;
var Handled: Boolean);
var
ctrl:TControl;
begin
if (Msg.hwnd = Handle) and (Msg.message = WM_LBUTTONDOWN) then
begin
ctrl := ControlAtPos(Point(LOWORD(Msg.lParam),HIWORD(Msg.lParam)),true,false);
if ctrl is TImage then
PaintBox1.Canvas.Draw(0,0,TImage(ctrl).Picture.Graphic)
else
PaintBox1.Refresh;
end;
end;
とします。実行して、Image1 または Image2 のうえでクリックすると
PaintBox1 にその色が反映されます。Form1を直接クリックすると
色が消えます。
TImage(ctrl).Picture.Graphic
に注目してください。キャストの効用です。
かきくけこさんどうもありがとうございました。
上記ソースで同じように動作しました。
そこで、このように私のソースを修正してみました。
procedure TForm1.DropFiles(var Msg:TWMDROPFILES);
var
WinHnd : HWND; P:TPoint;
ctrl: TControl;
begin
DragQueryFile(Msg.Drop, 0, fn, MAX_PATH);
DragQueryPoint(Msg.Drop, P);
WinHnd:= WindowFromPoint(ClientToScreen(P));
ctrl := ControlAtPos(P,true,false);
if ctrl is TImage then
TImage(ctrl).Picture.LoadFromFile(fn);
DragFinish(msg.Drop);
end;
ctrlにTimageのimage1やimage2を入れるという形なんですね。
でも、ctrl := ControlAtPos(P,true,false);nのctrlにnilが入ってしまいます。
Pは座標でx220y585などと入っているのになぜでしょうか?
ご教授いただけたらと思います。
宜しくお願致します。
ctrl := ControlAtPos(P,true,false);
if ctrl is TImage then
TImage(ctrl).Picture.LoadFromFile(fn);
ここの部分だけ Button1Click で確認したらいいんでは?
P に Image1 が必ず含むようなフォームの点の座標を与え、
if ctrl is TImage then Caption := ctrl.Name;
を実行してみてフォームのキャプションに Image1 と表示されたらOK
かきくけこさんありがとうございます。
試してみましたが動作しました。
しかし、座標取得でわからないところがあります。
例えば実行前のフォームの上にimage1があり、マウスを近づけて
左上座標16,16 となっているのですが、
DragQueryPoint(Msg.Drop, P);
で座標を取得すると90.85となってしまいます。
Msg.Dropの中がおかしいのでしょうか?
imageをpanelの上においているのですが、パネルの上におくことによって
座標が変わるということがあるのでしょうか?
認識不足で申し訳ありません。
ご教授お願致します。
> imageをpanelの上においているのですが
あっ、そうですか。それでは Form の ControlAtPos は使えませんね。
ControlAtPos は直接の子コントロールしかわかりませんから。
かきくけこさん。
長々ありがとうございました。
ためしにパネルからはずし、フォームの上においてみたら
思ったとおり動作しました。
どうもありがとうございました。
ツイート | ![]() |