フォームを常に最背面にするには?

解決


さやか  2006-04-07 22:31:09  No: 94966

VB6.0 SP5で開発しております。

A.exeとB.exeを起動して、B.exeは常にA.exeの背面にしたいのですが、
うまくいきません。
過去ログより、フォームをデスクトップに貼り付ける処理を見つけ、
(SetParentで引数にProgman、Program Managerを使用したものです)
うまくいったかと思ったのですが、これを使用すると、
デスクトップに張り付けたフォームのハンドルが取得出来なくなるので
別の方法を探しております。
(A.exe終了時は、B.exeも終了、A.exe最小化時はB.exeも最小化させる為に
B.exeのハンドル取得処理を記述している為です。)
SetForegroundWindowがあるのなら逆もあるのではと探しているのですが
一日かけても見つかりません。

何か方法があればご教授願いたいと思います。
よろしくお願いいたします。


.....  2006-04-08 02:19:52  No: 94967

非常に難解です。
もう少し、噛み砕いて、順番に説明してください。

フォームをデスクトップに貼り付ける?
デスクトップより背面にしたいのですか?
よくわかりません。

以上


.....  2006-04-08 02:36:12  No: 94968

ご存知かもわかりませんが
http://www.winapi-database.com/Window/Change/index.html
非常にわかりやすく、サンプルも多数あります。
がんばってください。

イベントのアクティブやロストフォーカスなどを利用すれば
できると思いますよ。


さやか  2006-04-10 18:51:09  No: 94969

.....さん、早々のご回答ありがとうございます。
お礼が遅れて申し訳ありません。
質問内容がわかりにくかったようで、重ねてお詫び申し上げます。

改めて説明させて頂きますと、
二つのexeを起動し、二つのフォームを表示します。
一つのフォームは処理フォームとして常に前面表示、
もう一つのフォームは壁紙の役割として新規に追加したexeで、
これを常に背面にしたかったのです。
その「常に背面にする」方法として、

-------------------------------------------------------------
'---API宣言
Public Declare Function SetParent Lib "USER32" _
(ByVal hWndChild As Long, ByVal hWndNewParent As Long) As Long

Public Const CONST_PROGMAN    As String = "Progman"
Public Const CONST_PROGRAMMAN As String = "Program Manager"

'---処理
'---デスクトップのウィンドウハンドルを取得
fhwnd = FindWindow(CONST_PROGMAN, CONST_PROGRAMMAN)
'---フォームの親として取得したウィンドウを設定する
Call SetParent(frmMENU.hwnd, fhwnd)
-------------------------------------------------------------
上記の処理を行い、結果、壁紙とするフォームを
デスクトップに貼り付ける事で、常にこのフォームを最背面にするという事を
実現しました。
しかし、上記処理を行うと、このフォームのハンドルを取得する事が
出来なくなり、以降の処理に影響が出る為、
上記のような、デスクトップに貼り付ける処理以外に、
フォームを常に最背面におくやり方がないか、質問させて頂きました。
デフォルトでデスクトップを見れなくしたかったわけで、
デスクトップより後ろにしたかったのではありません。
説明不足で申し訳ありませんでした。

貼って頂いたリンク、大変わかりやすいページで、有難いです。
ありがとうございます。

他の作業が割り込んだ為、折角早々にご教授頂いたのに
すぐに試す事が出来ないのですが、
必ず実現させ、「解決」にチェックさせて頂きます。
本当にありがとうございます。


....  2006-04-10 20:28:34  No: 94970

A.exe
Public Declare Function GetWindow Lib "USER32" (ByVal hwd As Long, ByVal cmd As Long) As Long
fhwnd = FindWindow(CONST_PROGMAN, CONST_PROGRAMMAN)
hChild = GetWindow(fhwnd , 5)
==================================================================

Call SetParent(frmMENU.hwnd, fhwnd)
によてデスクトップの子になったわけですから

hChild = GetWindow(fhwnd , 5)
によって、fhwnd の親ウインドウ(ディスクトップ)より
Zオーダーのトップの位置にある子ウィンドウのハンドルを取得する

その他
Public Declare Function FindWindowEx Lib "user32.dll" Alias "FindWindowExA" _
    (ByVal hwndParent As Long, ByVal hwndChildAfter As Long, _
    ByVal lpszClass As String, ByVal lpszWindow As String) As Long

子ウインドウのハンドルを取得する方法もありますね

以上
あと、VB.NETのツールでSPY+などあるといいですね
全てのハンドル等見ること出来ます。
探せばフリーツールでありそうですけどね。

がんばってください。


....  2006-04-10 20:40:40  No: 94971

あと、余談ですが、その他の方法として、
b.exeの目的は壁紙で、複雑なプログラムでは無いとすると
a.exeの処理が終了し、閉じたときにb.exeを一緒に閉じる
と言うようなプログラムと推測します。
であれば、b.exeはa.exeは0.1秒間隔でa.exeのハンドを監視して
ハンドの戻り値が0になったら閉じると言う方法も考えられますよね

それとも、
b.exeのメモリにアクセスしてメモリを書き換えたり、
壁紙を変更したりするのかな?

以上  余談でした  がんばってください。


さやか  2006-04-11 03:02:22  No: 94972

....さん、本当にありがとうございます。

b.exeは書き込み頂いた通り、単純にa.exeの壁紙であり、
a.exeが閉じればb.exeも閉じる。最小化、最大化も同じように動くという、
全てはa.exeのいいなりexeです。
一見単純そうですが、exeが分かれている為、常に背面というのが
困難な状態で、質問させて頂いております。
タイマーで監視するという方法も考えたのですが、
ただの壁紙である事を考えると、メモリ的に余計な負荷がかかるのでは
ないかと思い、その処理は諦めました。

大変親切なご回答、繰り返しますがありがとうございます。
頑張ります。


さやか  2006-04-12 03:09:42  No: 94973

遅くなりましたが、....さんがご教授してくださったように、
「hChild = GetWindow(fhwnd , 5)」
で、デスクトップに貼り付けたフォームのハンドルを
取得する事が出来ました。
丁寧な説明も付けてくださったので、すぐに理解する事が出来ました。
ありがとうございます。

ただ、このデスクトップに貼り付けたフォームに
フォーカスを与える事が出来ないのが今の大問題になっています。
(SetFocus使用)

とはいえ、この問題は解決致しましたので、解決にチェックさせて頂きます。
ありがとうございました。


通ってみた  2006-04-12 08:45:23  No: 94974

フォーカスを与える、のではなくアクティブにする、という方向で考えてみては(調べてみては)如何でしょうか


さやか  2006-04-12 18:11:44  No: 94975

解決後の書き込み失礼します。
それは

lngRet = SetActiveWindow(ByVal 壁紙フォームのハンドル値)

で試してみたのですが、戻り値(lngRet)が0(エラー)で戻ってしまい、
実現不可でした。
タイミングは、壁紙フォームを最小化する前、後どちらでも試したのですがダメでした。

どうしたものか、試行錯誤の真っ只中です。


通ってみた  2006-04-12 20:17:28  No: 94976

解決しちゃてるスレなんでアレですが・・・

なんで壁紙となるフォームにフォーカスを充てる(アクティブにする)必要があるのかちょっと悩みました
AとBの最小化、最大化を同期させるような仕組みだったら、ハンドルがわかっているのですから、

(考え方の例)
Aを最小化、最大化したらResizeイベントにて現在のAのフォームの状態(最小化しているか最大化しているか通常状態か)を調べ、BにSendMessageで合図を送る

としてみたらどうでしょうか


さやか  2006-04-12 21:05:29  No: 94977

通ってみたさん、通ってくださってありがとうございます。
Resizeイベントで解決致しました!!

>なんで壁紙となるフォームにフォーカスを充てる(アクティブにする)必要があるのかちょっと悩みました

解決後だったので詳しく述べませんでしたが、大本の原因は、Resizeイベントの存在を知らなかった為です。

最小化したメインのa.exe(タスクバーの中のボタン)をクリックして元に戻す際、a.exeのフォームにフォーカスがあると
a.exeのForm_RoadもFrom_Activeも通らない為、b.exeのフォームを最大化する命令を記述する場所がなく、
わざと他のフォームであるb.exeのフォームにフォーカスを渡して、a.exeを元に戻す時にForm_Activeを通らせ、
そこでb.exeも最大化するという処理を記述したかったのです。

Resizeイベントにて全て解決致しました。
APIに頼りすぎてVBの基本イベントが抜けていました。
ご教授頂いた皆様に心より感謝いたします。そしてもっと勉強します。
本当にありがとうございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加