VC++初心者のものです。
拡大鏡のような形で画面を拡大し、その拡大表示した画面上で
そのままマウス操作できるようにしたいのですが、
マウスの位置や動きを下のウィンドウに伝えるにはどうしたらいいでしょうか?
現在の状況としては、なんとか画面拡大はでき下のウィンドウにも伝わっているには伝
わっている状態なんですが、
拡大画面からだと、直接下のウィンドウへマウスメッセージがいってしまい、反映され
ません。
ちなみに拡大は、レイヤードウィンドウで真下のデスクトップ画面のDCを取得して
StretchBltで拡大表示している状態です。
どなたかご教授の程よろしくお願いします。
環境;WinXP, Visual Stadio2005, VC++ Win32
>現在の状況としては、なんとか画面拡大はでき下のウィンドウにも伝わっているには伝
>わっている状態なんですが、
>拡大画面からだと、直接下のウィンドウへマウスメッセージがいってしまい、反映され
>ません。
クライアント座標とスクリーン座標に矛盾がありませんか?
つまりスクリーン座標なのにクライアント座標として使っている。
またはその逆のパターン。
>クライアント座標とスクリーン座標に矛盾がありませんか?
>つまりスクリーン座標なのにクライアント座標として使っている。
そうなんですよね。
スクリーン座標とクライアント座標で…というところだとは思うのですが^^;
実際、拡大画面上で操作はしていても、全てのマウスイベントが素通りして、
直接下のウィンドウに届くような感じで、
クライアント座標からスクリーン座標へと マウスイベントをどう伝えればいいのかわか
らない状態です。
質問の仕方が悪くて、すいません。
>クライアント座標からスクリーン座標へと マウスイベントをどう伝えればいいのかわ
か
>らない状態です。
単純な変換なら ClientToScreen がありますけど。
http://msdn.microsoft.com/ja-jp/library/cc428312.aspx
具体的にマウスイベントとは何?
WM_MOUSEMOVEとか?
>>金魚ちゃんさんへ
>具体的にマウスイベントとは何?
>WM_MOUSEMOVEとか?
主にクリック動作です。
拡大画面上でそのまま操作でき、下のウィンドウにも反映させるようにしたいので、
マウスの動きそのもの(?)が入ってくるのかもしれませんが。
>拡大画面上でそのまま操作でき、下のウィンドウにも反映させる
1.マウス座標がウインドウ領域内に入ったら普通のウインドウに戻す
2.マウス処理を受け取ったら
a.レイヤード・ウインドウに設定する
b.SendInput などを使ってマウスイベントをウインドウ直下に伝える
c.普通のウインドウに戻す
3.マウス座標がウインドウ領域外から出たらレイヤード・ウインドウに設定
こんな感じでどうですか。
(3)はタイマーなどを使ったウインドウ領域内/外を監視したり、
ウインドウ領域外は WM_MOUSELEAVE を使っても良いですね。
金魚ちゃんさん、ありがとうございます。
>1.マウス座標がウインドウ領域内に入ったら普通のウインドウに戻す
ということは、拡大ウィンドウ内に入ったら拡大画面は消えてしまうということです
か?
>2.マウス処理を受け取ったら
> a.レイヤード・ウインドウに設定する
> b.SendInput などを使ってマウスイベントをウインドウ直下に伝える
そして、その通常のウィンドウ上で何か操作したときに拡大表示→ウィンドウ直下に
伝える!!みたいな感じで、操作直前は拡大画面が見えなくなるのでしょうか?
http://www.microsoft.com/japan/msdn/windows/windows2000/layerwin.aspx
>ヒット テスト
>レイヤード ウィンドウのヒット テストは、ウィンドウの形状と透明度に基づいていま
す。
>これは、色分けされているウィンドウの領域やアルファ値がゼロの領域は、
>マウス メッセージが透過することを意味します。
>レイヤード ウィンドウが WS_EX_TRANSPARENT 拡張ウィンドウ スタイルを持つ場合、
>レイヤード ウィンドウの形状は無視され、
>マウス イベントはレイヤード ウィンドウの下の他のウィンドウに渡されます。
これかな?
ふと思ったんですが、拡大表示しているわけなので
実際の拡大表示用のウインドウ内の座標を拾った後、
元の画面ではどの位置になるのかを計算してから
マウスイベントを投げないと駄目なんじゃないかと言う気がしますね。
拡大表示上の位置ですから、その辺は考える必要があるのでは?
例えばですが、拡大画面の中心位置と下の元のウインドウ上の位置が
合っていて、拡大表示をしていると考えます。
2倍に拡大してい場合、拡大画面上での中心位置からの距離が18ピクセル
だったとすると、実際の画面上では9ピクセルの距離になるはずですよね。
なので、拡大画面上の位置を実際の画面上の位置に計算し直して
通知しないといけないのではないかと思います。
既にこの辺の考慮はしているよと言う話ならスルーしてください。
次の参考ページを見つけました。
http://www.sutosoft.com/mt/devdiary/archives/000050.html
ここにレイヤード・ウインドウを2枚使って
マウス処理を受け取る方法が書かれています。
これで受け取ったら下のレイヤード・ウインドウのα値を 0 にして
座標の計算をPATIOさんのアドバイスを元に計算。
そして SendInput などでマウスイベントを発生させれば出来そうな気が…。
あと過去に似たような質問があったよ。
http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200707/07070026.txt
座標のずれはこれかもね。
興味があるので上手くいったら結果報告をお願いします。
(明日は暇になるからちょっと作ってみるつもり)
rinさん、PATIOさん、金魚ちゃんさん、ご丁寧にありがとうございます。
まだまだ勉強不足でわからないことも多く…、
すぐにはちゃんと報告できないと思いますが、これから頑張ってやってみたいと思いま
す!!
皆さん、ありがとうございます><
遅くなってすいません。とんぼです。
金魚ちゃんさんのアドバイスどおり、
レイヤードウィンドウを2枚重ねてというところまではできました。
いちおその透明ウィンドウ上(α値が1のとき)で、左クリックをした場合など
条件をつけたマウス処理は受け取れていることが確認できました。
そこでなんですが、マウス処理全般を受け取ってイベントを発生させるには
どういった条件をつければいいのでしょうか?
(拡大画面上でもそのままの操作可能にするため)
例えば、透明ウィンドウ上でメッセージWM_MOUSEMOVEを受け取り
if(wp & MK_LBUTTON)だったらという形で上記の確認はとれましたが、
このような形でいいのでしょうか。
そうすると、ダブルクリックのとき…など、条件分けをいろいろしなければならないん
ですよね?
単純にマウス系の処理を下のウインドウにスルーしたいだけなら
マウス系のウインドウメッセージを全て調べて対応するメッセージを
処理すれば良いだけだと思います。
WM_XXXの部分はどのウインドウでも同じはずですし。
特にこの操作のときは特別な処理をする必要があると言う話なら
その操作に対応したメッセージ処理を場合分けする必要があるでしょうけれど。
私のイメージでは処理する必要があるメッセージに関しては
マウスの座標を拾って拾った座標から下のウインドウ上の座標値を計算し、
ウインドウメッセージの種類はそのまま使ってメッセージを送れば良いのでは
ないかと思います。
この辺は実際にやって見て確認した方が良いと思います。
追伸:
メッセージの種類によって座標を取り出す処理が異なる時は
場合分けも必要になるかもしれませんね。
この辺は御自分で調べて見てください。
遅くなった上にまだ出来ていないのですが…
イベントメッセージを送る際、SendInputの使い方がよくわからず
SendMessage()で送っているのですが、どうしてもその座標にメッセージを送ることが出
来ません。
拡大画面上でクリックを検知後、レイヤードウィンドウのα値を0にし、
対応する座標(fact.x, fact.y)を計算して↓
SendMessage(NULL, WM_LBUTTONDOWN, 0, MAKELPARAM(fact.x, fact.y));
SendMessage(NULL, WM_LBUTTONUP, 0, MAKELPARAM(fact.x, fact.y));
という形にしているのですが、これでは送れないのでしょうか?
また、画面の中心の座標なんですが
GetSystemMetrics(SM_CXMAXTRACK)、GetSystemMetrics(SM_CYMAXTRACK)で
取得した画面のサイズ÷2で中心の座標にもなるんですよね?
初歩的な質問ですみません。
SendMessageがWin32APIならウインドウハンドルはちゃんと指定しないと
狙い撃ちには出来ないと思います。
送付先のウインドウハンドルが必要なのでは?