[[20200612105451]] 『他のアプリのタブを切り替えたい』(はち) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『他のアプリのタブを切り替えたい』(はち)

いつもお世話になります。
VBAで別アプリケーションのタブコントロールを2番目のタブ(「View2」)に表示を切り替えたいのですがどのようにコードを組んだらいいでしょうか?

現時点では親ハンドルとタブコントロールのハンドルまでは取得できています。
ちなみにSendkeysではだめでした。

< 使用 Excel:Excel2016、使用 OS:Windows10 >


Sendkeysで何を送ってみて駄目だったのか教えてください。 あと、対象のなるアプリは何でしょう?

タブを持つコントロールまでTABキーを送り、タブの1番目にフォーカスが移るならば、更に右方向キーを送れば2番目に切り替わるかと思います。

APIを利用する方法は、タブコントロールはマウスクリックで切り替えるだけであり、プログラムから切り替えた経験が無いので、私は判らないですね。(タブコントロール自体、普段は使わない設定変更画面に使う場合がある、というくらいで、滅多に使わないです。いろいろオブジェクトが載るので、重いですから)
(???) 2020/06/12(金) 11:57


???さん回答いただきありがとうございます。
Sendkeysで送信したのは{TAB}、{RIGHT}です。

正確に申しますと、まず親ウィンドウから{TAB}を送信しても無反応でした。

次にタブコントロールにフォーカスを当ててから
{TAB}を送信した場合はタブ内にあるデータグリッドビューにフォーカスが移動してしまう、
{RIGHT}を送信した場合は確かにタブが一つ右に切り替えはできます。
ただしフォーム表示時に前回表示されたタブが選択されている状態で、常に一定のタブが表示されているわけではありません。なので強制的に2番目のタブを選択させたいのです。

あと、アプリについてですが市販のものではなく自社オリジナルのアプリケーションとなります。

(はち) 2020/06/12(金) 12:46


自作アプリならば、開発言語は何ですか? 特に、VB.NETやC#ならば、WPFなのかWindows Formsなのか。

手作業で確認してみてください。 TABキーは1回ではなく、何度かTABキーを押してみて、タブコントロールにフォーカスが移動するでしょうか? TABキーによるフォーカス取得をFalseにしていると、Sendkeysでは対応できないです。
(???) 2020/06/12(金) 14:29


???さん返信が遅くなり申し訳ありません。
.NETで作成でフォームはWindowsFormsです。

TABキーでは何度押してもタブコントロールへフォーカスは当たりませんでした。
SendKeysではできなさそうでしたので、親ウィンドウハンドルから表示位置を取得して
相対的な位置でSetCursorPosとmouse_eventのAPIを使用して
なんとか物理的に動作させました。

たまにきちんと切り替わらない時があるのでできればこの手法は使いたくなかったです。
他にいい方法ないでしょうか・・。

(はち) 2020/06/12(金) 17:22


Windows FormsのTabPageコントロールならば、デフォルトではタブストップできるはずですけどね? あえて殺しているのでしょうか。

アプリ修正をお願いできないのであれば、TABキーによるフォーカスを殺されているのでSendkeysが通用しませんから、座標でマウスクリック案で良いかと思います。 仕方ないですね。
(???) 2020/06/12(金) 17:51


たまに反応しない点については、少しSleepを入れれば良いかと思います。

別案では、座標が判っているのだし、その色情報を得て表示更新完了を判断…、とかも考えられますが、タブコントロールではほぼ灰色だから、駄目かも。
(???) 2020/06/12(金) 17:54


???さん返信が遅くなり申し訳ありません。
後押しいただいてありがとうございます。
手法としてはこれ(座標+クリック)しかなさそうです。

たまに反応しないところはSleep入れてみましたが頻度は下がったもの、
やっぱりときより反応しません。

2番目のタブがアクティブかどうかの判定ってできますかね?
APIなどがあればアクティブになるまで繰り返すような処置も取れるのですが・・。

(はち) 2020/06/15(月) 08:28


目的のアプリは常に同じ座標(ウィンドウ情報を得て、X,Yを足して求めた?)をクリックするのだから、十分に思ったのですが…。

クリックする座標を、Excelが邪魔している、という事はありませんか? Application.WindowState = xlMinimized としてから、APIでクリックしてみるとか。

それと、他アプリなのでSleep命令だけで十分と思ったのですが、駄目元で、追加でDoEventsを3回連続で入れてみる、というのも試してみてください。 他アプリにメッセージを読むタイミングを与えるようになります。

または、他アプリのクラス名をFindWindowし、得られたウィンドウハンドルからEnumChildWindowsで子クラスをたどれば、タブコントロールのクラス名と、それぞれのタブの文字列を得る事ができます。 ついでに、IsWindowVisibleで、どのタブが開いているかも得られます。 これは使えないでしょうか?
(???) 2020/06/15(月) 13:48


???さん返信が遅くなり申し訳ありません。
ご回答いただきありがとうございます。

DoEventsの3連は効果があったようです。今のところ挙動に異常がありません。
でもこれなんで3連なんでしょう!?

IsWindowVisibleは知りませんでした。ちょっと試してみたいと思います。
(はち) 2020/06/15(月) 17:26


命令的はDoEvents1回なのですが、PC性能が高いと効き目がない場合が多いのです。 経験上、3回やれば切替成功します。 Sleepは自スレッドを止めるだけですが、CPU解放しない場合、DoEventsならCPU解放してくれるようになります。

おまけで、IsWindowVisibleで今どっちのタブになっているか調べるコードなぞ。 フォームにActiveXのボタンを貼り、これを押すと実行するようにしてください。
他アプリのタイトルは「Form1」としていますが、実際のアプリ名に変えてください。(クラス名で探すように変えてもOK) 同様に、タブ名も実際のものに変えてください。

 【シートモジュール】
 Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
    (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
 Private Declare Function EnumChildWindows Lib "user32.dll" ( _
     ByVal hwndParent As Long, _
     ByVal lpEnumFunc As Long, _
     ByVal lParam As Long _
     ) As Long

 Private Sub CommandButton1_Click()
    Dim hWnd As Long

    hWnd = FindWindow(vbNullString, "Form1")
    If hWnd <> 0 Then
        Call EnumChildWindows(hWnd, AddressOf EnumWindowsProc, 0)
    End If
 End Sub

 【標準モジュール】
 Declare Function GetWindowText Lib "user32.dll" Alias "GetWindowTextA" ( _
     ByVal hWnd As Long, _
     ByVal lpString As String, _
     ByVal cch As Long _
     ) As Long
 Declare Function IsWindowVisible Lib "user32.dll" (ByVal hWnd As Long) As Long

 Function EnumWindowsProc(ByVal hWnd As Long, lParam As Long) As Long
    Dim cw As String

    If IsWindowVisible(hWnd) <> False Then
        cw = String(100, Chr(0))
        Call GetWindowText(hWnd, cw, Len(cw))
        cw = Left(cw, InStr(cw, Chr(0)) - 1)
        If cw = "TabPage1" Then
            MsgBox "Tab1なので切替必要", vbExclamation
        ElseIf cw = "TabPage2" Then
            MsgBox "Tab2なのでOK", vbExclamation
        End If
    End If

    EnumWindowsProc = 1
 End Function
(???) 2020/06/15(月) 18:05

コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.