dポイントプレゼントキャンペーン実施中!

a.exeを起動したら Aの中でshellでb.exeが起動する
a.exeの上にb.exeが起動しているかたちになります。
このときにa.exeの画面をクリックしても
a.exeはアクティブにならずにしたいのですがどうすればよいのか
襲えてください。
a.exeはフォームにbmpをはり各プログラムの背景画面にしたいので
クリックされてもなにを反応しないようにしたいのです。

よろしくお願いします。

A 回答 (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の標準モジュール(ここまで)-----
    • good
    • 0
この回答へのお礼

ありがとうございました。
いちどやってみます。

お礼日時:2001/10/28 09:03

方法は二つあります。



1.a.exeがb.exeを起動して、状態監視をする。
2.b.exeが終了するまで待機する

どちらかの方法を利用して、b.exeを常に最善面に表示するようなAPI関数を呼びます。
今は時間がないので後でサンプルを作成しますね。
    • good
    • 0

クリックされても反応しないというのは無理ですが、クリックされたらbにフォーカスを送るというのはできますねぇ。


デスクトップでさえアクティブになりうるのですから。
bを常に手前に表示しておけば、aがクリックされたときに、bがフォーカスを失うものの、bが一瞬きえることはなしにできますよ。

背景画面をb内の別フォームすることはできないんですか?
それだったら、もうちょっと簡単。
目的は満たしてないけど・・・。

MDIフォームなら、完全に目的が果たせますね。
ダメですか?
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!