ウィンドウをアクティブにしたい

解決


ふらぷら  2007-11-18 11:41:03  No: 138151  IP: 192.*.*.*

VB6.0で質問です。
Shell関数で立ち上げたプログラムをアクティブにしたいのですが、出来ないためご教授お願いします。初心者であるため回答に対して質問を投げかけてしまうかもしれません。宜しくお願い致します。

シェル関数
Dim Ret1 As Long
Ret1 = Shell("C:\WINDOWS\ime\IMJP8_1\imjpdct.exe", vbNormalFocus)
Alt+Tを送り『sendkey %{T}』を送った後(辞書ファイル)を立ち上げることは成功するのですが、まれにウィンドウがバックに隠れてしまいます。
バックに隠れてしまうウィンドウを捕まえてアクティブにしたいのですが、美味く出来ません。実際動かしてみたところ、アクティブに出来るかは運頼りになってしまっています。

アクティブにするために

コードの頭に 
Private 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 
をつけて
SetWindowPos(Ret1, HWND_TOPMOST , 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE)
をしても失敗し、

コードの頭に
Private Declare Function SetActiveWindow Lib"USER32" (ByVal hWnd&) As Long
をつけて
SetActiveWindow(Ret1)
としても失敗します。

何がいけないのか全く分かりません。ご教授宜しくお願いします。

編集 削除
ふらぷら  2007-11-18 22:27:41  No: 138152  IP: 192.*.*.*

過去ログ
【画面の前面処理&ウィンドウをアクティブにする】
を参考に色々行ってみましたがだめでした。

thID = GetWindowThreadProcessId(Ret1, Null)
によりスレッドIDを取得し、

nowhD = GetForegroundWindow()
nowthID = GetWindowThreadProcessId(nowhD, Null)
によって今のスレッドID取得。

この後
scID = AttachThreadInput(nowthID, thID, False)
If scID = 0 Then
    MsgBox ("失敗しました")
End If
を行うと”失敗しました”と表示され、

forID = SetForegroundWindow(thID)
If forID = 0 Then
    MsgBox ("失敗しました")
End If
を行うっても失敗しましたと表示されます。

何がいけないのか全く分かりません。
ご教授お願い致します。

編集 削除
もげ  2007-11-19 09:35:58  No: 138153  IP: 192.*.*.*

>Dim Ret1 As Long
>Ret1 = Shell("C:\WINDOWS\ime\IMJP8_1\imjpdct.exe", vbNormalFocus)
ご教授  ではなく  ご教示  かと。

Shell()関数の戻り値は、ウィンドウのハンドルではありませんから、

>SetWindowPos(Ret1, HWND_TOPMOST , 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE)

>SetActiveWindow(Ret1)

では、ダメでしょう。
一例としては、
http://support.microsoft.com/kb/242308/ja

編集 削除
ふらぷら  2007-11-19 12:57:10  No: 138154  IP: 192.*.*.*

>もげさん
だめでした。
>Shell()関数の戻り値は、ウィンドウのハンドルではありませんから
盲点でした。

入力を色々ためし、Ret1からウィンドウハンドルを探してみて成功しましたが、

'戻り値インスタンス
Ret1insID = Shell("C:\WINDOWS\ime\IMJP8_1\imjpdct.exe", vbNormalFocus)
SendKeys "%{T}", True
'戻り値ハンドル
Ret1hD = GetWinHandle(Ret1insID)

ーーーーーーーーーーーーー①−−−−−−−−−−−
'戻り値スレッド
Ret1thID = GetWindowThreadProcessId(Ret1hD, Null)
nowhD = GetForegroundWindow()
nowthID = GetWindowThreadProcessId(nowhD, Null)
sc1ID = AttachThreadInput(nowthID, Ret1thID, False)
If sc1ID = 0 Then
    MsgBox ("失敗しました")
End If
sc2ID = SetForegroundWindow(Ret1thID)
If sc2ID = 0 Then
    MsgBox ("失敗しました")
    End
Else
    MsgBox ("成功しました")
    End
End If

ーーーーーーーーーーーーー②−−−−−−−−−−−
scID = SetWindowPos(Ret1hD, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE)
If scID = 0 Then
    MsgBox ("失敗しました")
    End
Else
    MsgBox ("成功しました")
    End
End If

ーーーーーーーーーーーーー③−−−−−−−−−−−
scID = SetActiveWindow(Ret1hD)
MsgBox (scID)

と入力し、実行してみたところ、①②はメッセージボックスに『失敗しました』と連続表示され、③は『0』が表示され失敗に終わります。
どうやら、ハンドルの取得には成功するもののそのあとが続きません。

何がいけないのかご教示お願いします。

編集 削除
Mike!  2007-11-19 14:26:54  No: 138155  IP: 192.*.*.*

こちらでいかがでしょう?

[過去ログ]
http://madia.world.coocan.jp/cgi-bin/VBBBS2/wwwlng.cgi?print+200402/04020031.txt

編集 削除
もげ  2007-11-19 17:56:32  No: 138156  IP: 192.*.*.*

目的のウィンドウのハンドルが取得できているかどうか、
SPY++等で調べてみてはいかがでしょう?
"Microsoft IME 辞書ツール"をアクティブにしたいのですよね?
PIDが同じ複数のウィンドウが存在するようなので、
前述のサンプルをそのままコピペではうまくいかないでしょう。

もしかすると、APIでなくても、
   AppActivate でよかったりして:-)。

編集 削除
ふらぷら  2007-11-19 21:22:07  No: 138157  IP: 192.*.*.*

>Mike!さん
実行してる命令「SystemParametersInfo」の意味が分からないがとりあえずコピペして動かしてみました。
Ret1hD = GetWinHandle(Ret1)
nowhD = GetForegroundWindow()
'フォアグラウンドウィンドウを作成したスレッドのIDを取得
nowthID = GetWindowThreadProcessId(nowhD, vbNullString)
'目的のウィンドウを作成したスレッドのIDを取得
ThreadID2 = GetCurrentThreadId()
'現在の入力状態を目的のスレッドにアタッチ
AttachThreadInput ThreadID2, nowthID, 1
'現在の[フォアグラウンド ロック タイムアウト]の設定を取得
SystemParametersInfo SPI_GETFOREGROUNDLOCKTIMEOUT, 0, VarPtr(buf), 0
'設定を 0ms に変更
SystemParametersInfo SPI_SETFOREGROUNDLOCKTIMEOUT, 0, vbNullString, 0
'ようやく、本命の処理のお出まし
SetForegroundWindow Ret1hD
'設定を元に戻して…
SystemParametersInfo SPI_SETFOREGROUNDLOCKTIMEOUT, 0, VarPtr(buf), 0
'デタッチしておしまい
AttachThreadInput ThreadID2, nowthID, 0

失敗いたしました。数回立て続けにアクティブに成功したため喜びましたがぬか喜びでした。

>もげさん
「WinID」を入れてみました。
すみませんが、見方を教えていただけないでしょうか?
http://i-get.jp/upload500/src/up12749.jpg

編集 削除
ふらぷら  2007-11-20 12:29:04  No: 138158  IP: 192.*.*.*

>もげさん
>Mike!さん
無事に出来ました。

>もげさん
「WinID」使い方が分かりました。大変失礼致しました。
No parentと書かれていて、条件文のGetParentが本当に動いているのか調べたところ、動いていませんでした。失礼致しました。

そこで書き方を換えてみました。
'フォアグラウンドウィンドウの取得
FGhWnd = GetForegroundWindow()
Do
    '200回したら終了
    Cnt = Cnt + 1
    If Cnt = 200 Then
        MsgBox("取得に失敗しました")
        End
    Else
        'ウィンドウタイトルの取得
        WndTitle = ""
        GetWindowText FGhWnd, WndTitle, 1000
        'ウィンドウタイトルの表示
        If InStr(WndTitle, "IME") <> 0 Then
            Exit Do
        End If
        FGhWnd = GetNextWindow(FGhWnd, 2)
    End If
Loop
としたところ『default; IME』という名のハンドルの取得に成功しました。

SetForegroundWindow FGhWnd

を行ったところ、最前面には出来たのですがアクティブにはならず
sendkeyが出来ませんでした。

そのため
ThreadID1 = GetWindowThreadProcessId(FGhWnd, vbNullString)
'目的のウィンドウを作成したスレッドのIDを取得
ThreadID2 = GetCurrentThreadId()
'現在の入力状態を目的のスレッドにアタッチ
AttachThreadInput ThreadID2, ThreadID1, 1
'現在の[フォアグラウンド ロック タイムアウト]の設定を取得
SystemParametersInfo SPI_GETFOREGROUNDLOCKTIMEOUT, 0, VarPtr(buf), 0
'設定を 0ms に変更
SystemParametersInfo SPI_SETFOREGROUNDLOCKTIMEOUT, 0, vbNullString, 0
'ようやく、本命の処理のお出まし
SetForegroundWindow FGhWnd
'キーを送る。
SendKeys "%{T}", True
Sleep (20)
SendKeys "{R}", True
Sleep (50)
SendKeys "動作テストだよ", True
Sleep (200)
SendKeys "%{F4}", True
SendKeys "%{F4}", True
'設定を元に戻して…
SystemParametersInfo SPI_SETFOREGROUNDLOCKTIMEOUT, 0, VarPtr(buf), 0
'デタッチしておしまい
AttachThreadInput ThreadID2, ThreadID1, 1

としたところうまく動かすことに成功しました。
運だよりか何度もチェックしたところ、失敗なしのため出来上がりました。

「GetCurrentThreadId」「SystemParametersInfo」についてはじっくり勉強していきたいと思います。

どうもお世話になりました。本当に有難うございました。

編集 削除