- ベストアンサー
プログラムをアクティブにしないようにするにはどうするのですか?
a.exeを起動したら Aの中でshellでb.exeが起動する a.exeの上にb.exeが起動しているかたちになります。 このときにa.exeの画面をクリックしても a.exeはアクティブにならずにしたいのですがどうすればよいのか 襲えてください。 a.exeはフォームにbmpをはり各プログラムの背景画面にしたいので クリックされてもなにを反応しないようにしたいのです。 よろしくお願いします。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
サンプル作りました。 さっきの書き込みのとき、しっかり読まなかったので、勘違いして回答を書いております。 それで処理内容がさっきと発言と変わっています。 サンプルでは、背景にもコマンドボタンを置いて、別のEXEを操作していますが、必要のない機能ははずしてください。 処理内容を説明します。 1.Aを起動します。 2.AからSHELLでBを起動します。 3.Bの中の処理はフォームをロードするだけで、Showを行いません。 4.Aの中にBを埋め込みます。 5.AからBの表示位置を設定します。 6.AはBを常に監視します。 以上がおおまかな流れです。 サンプルを実行するときの注意点です。 二つのEXEが必要です。 A.exeについて 必要なもの フォーム コマンドボタン1/2/3 標準モジュール A.exeの名前については任意です。 もうひとつのEXEの名前はB.exeにしています。(定数でCHILD_EXEの内容を変えることで、変更できます) B.exeの表示位置をピクセル単位で指定しています。[CHILD_X/CHILD_Y]が、それにあたります。サンプルでは[300,0]に設定してます。それにともない、フォームは多少大きめに、3つのコマンドボタンはふ、フォームの左端がわに縦に並ぶように配置してください。 B.exeについて 必要なもの フォーム 標準モジュール こちらはフォームから起動しないで、標準モジュールから実行するようにしてください。 コードを見てもらえたらわかるように、フォームをロードするだけです。 フォームのキャプションを空にして、BorderStyleを[0-なし]にしてあげると、より一層別のEXEだということが感じられなくなります。 -----A.EXEのフォーム(ここから)----- Option Explicit '別EXEのファイルパス Private Const CHILD_EXE As String = "b.exe" '別EXEの表示位置X座標 Private Const CHILD_X As Long = 300 '別EXEの表示位置Y座標 Private Const CHILD_Y As Long = 0 'アプリケーションの終了ボタンを押されたときの処理フラグ Private bytFlg As Byte 'bytFlgは基本的に0で、アプリケーションの終了時に0をセット Private Sub Command1_Click() '初期化を行う FindWinWnd = 0 FindPrs = 0 'とりあえずCHILD_EXEを起動と同時に、電卓のプロセスを得る FindPrs = Shell(CHILD_EXE) 'プロセス=0のとき起動失敗 If FindPrs = 0 Then MsgBox CHILD_EXE & "の起動失敗" GoTo PGMEND End If 'Windowsに存在する全部のハンドルから、CHILD_EXEのプロセスの一緒のハンドルを探す Call EnumWindows(AddressOf EnumWinProc, 0&) 'もし、起動したEXEのハンドルを取得できたら If (FindWinWnd <> 0&) Then 'CHILD_EXEを自分のフォームの中に取り込みます Call SetParent(FindWinWnd, Me.hWnd) 'CHILD_EXEの表示位置を定め、表示を行います Call SetWindowPos(FindWinWnd, HWND_TOP _ , CHILD_X, CHILD_Y, 0, 0, SWP_NOSIZE Or SWP_SHOWWINDOW) 'CHILD_EXEの監視を行います Call KANSI_WINDOWS Else MsgBox "EXEが見つかりませんでした。" End If PGMEND: End Sub Private Sub Command2_Click() '起動したEXEの終了 Call SendMessage(FindWinWnd, WM_CLOSE, 0&, 0&) End Sub Private Sub Command3_Click() '自分自身の終了 Unload Me End Sub Private Sub Form_Load() With Me .Command1.Caption = "別EXEの起動" .Command2.Caption = "別EXEの終了" .Command3.Caption = "アプリケーションの終了" '「別EXEの終了ボタン」を使用不可 .Command2.Enabled = False bytFlg = 0 End With End Sub Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer) With Me 'もしCHILD_EXEを起動しているならば、終了を行う If .Command2.Enabled Then bytFlg = 1 Call Command2_Click End If End With End Sub '起動した別EXEのウィンドウを監視します。 '「別EXEの終了ボタン」のEnabledを操作します。 Private Function KANSI_WINDOWS() With Me '「別EXEの終了ボタン」を使用可能 .Command2.Enabled = True '別EXEが起動しているあいだはこのループを回り続ける Do While (IsWindow(FindWinWnd) = 1) DoEvents Loop 'アプリケーションが終了しないときは、「別EXEの終了ボタン」を使用不可に戻す If bytFlg = 0 Then .Command2.Enabled = False End If End With End Function -----A.EXEのフォーム(ここまで)----- -----A.EXEの標準モジュール(ここから)----- Option Explicit Public Const HWND_TOP = 0 'ZOrderのトップに置く Public Const SWP_NOSIZE = &H1 'ウインドウのサイズを変えないで移動のみ Public Const SWP_SHOWWINDOW = &H40 '再描画の時、ウインドウを再表示 Public Const WM_CLOSE = &H10 '見つかったウィンドウハンドル Public FindWinWnd As Long '探すべきプロセス Public FindPrs As Long ' ウィンドウのプロセスIDとスレッドIDを取得する関数の宣言 Private Declare Function GetWindowThreadProcessId Lib "user32.dll" _ (ByVal hWnd As Long, lpdwProcessId As Long) As Long '親ハンドルを取得する関数の宣言 Private Declare Function GetParent Lib "user32" _ (ByVal hWnd As Long) As Long 'ウィンドウを列挙する関数の宣言 Public Declare Function EnumWindows Lib "user32" _ (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long 'ウィンドウにメッセージ定数を送る関数の宣言 Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" _ (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Long) As Long ' ウィンドウハンドルからウィンドウが存在するかどうか判断する関数の宣言 Public Declare Function IsWindow Lib "user32.dll" _ (ByVal hWnd As Long) As Long '指定ハンドルのウィンドウの親を変更する関数の宣言 Public Declare Function SetParent Lib "user32" (ByVal hWndChild As Long, ByVal hWndNewParent As Long) As Long '指定ハンドルのウィンドウのサイズ、位置を変更する関数の宣言 Public Declare Function SetWindowPos Lib "user32" _ (ByVal hWnd As Long, ByVal hWndInsertAfter As Long, ByVal X As Long, ByVal Y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long 'Windowsの全ハンドルを得ることができる関数 '内部処理は、 '(1)指定のプロセスを探す '(2)見つかったプロセスのハンドルを記憶 Public Function EnumWinProc(ByVal hWnd As Long, lParam As Long) As Boolean Dim lngTrd As Long 'スレッド Dim lngPrs As Long 'プロセス 'Trueの間は、Windowsに存在するハンドルを最後まで取得しようとする EnumWinProc = True '子ウィンドウは未処理 If Not (GetParent(ByVal hWnd) = 0) Then GoTo PGMEND 'スレッドとプロセスを取得する lngTrd = GetWindowThreadProcessId(hWnd, lngPrs) '同じプロセスだとしたら If lngPrs = FindPrs Then '取得してきたハンドルを記憶 FindWinWnd = hWnd 'これ以上のハンドルは取得しないでもいいので、Falseをセット EnumWinProc = False End If PGMEND: End Function -----A.EXEの標準モジュール(ここまで)----- -----B.EXEのフォーム(ここから)----- 記述する必要なし -----B.EXEのフォーム(ここまで)----- -----B.EXEの標準モジュール(ここから)----- Sub Main() Load Form1 End Sub -----B.EXEの標準モジュール(ここまで)-----
その他の回答 (2)
- TAGOSAKU7
- ベストアンサー率65% (276/422)
方法は二つあります。 1.a.exeがb.exeを起動して、状態監視をする。 2.b.exeが終了するまで待機する どちらかの方法を利用して、b.exeを常に最善面に表示するようなAPI関数を呼びます。 今は時間がないので後でサンプルを作成しますね。
- haporun
- ベストアンサー率40% (230/562)
クリックされても反応しないというのは無理ですが、クリックされたらbにフォーカスを送るというのはできますねぇ。 デスクトップでさえアクティブになりうるのですから。 bを常に手前に表示しておけば、aがクリックされたときに、bがフォーカスを失うものの、bが一瞬きえることはなしにできますよ。 背景画面をb内の別フォームすることはできないんですか? それだったら、もうちょっと簡単。 目的は満たしてないけど・・・。 MDIフォームなら、完全に目的が果たせますね。 ダメですか?
お礼
ありがとうございました。 いちどやってみます。