● 指定した文字を含むタイトルのウィンドウをアクティブにする方法。API使用(64bit、32bit、兼用。)Excelの「Userform1」が開いているかどうかなどにも使えます(アクティブにまではできませんが)。
※まだ書きかけです。すみません。
※間違ってたらすみません。
※メモ書きなので、自分でも意味不明な箇所も多いです。ごめんなさい。
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q14301546969?post=2
※注
↑上のURLの4人目のAPI込の回答も良いと思いますが、実際にテストするとAPIの宣言の方法が間違っていてエラーになります。API宣言に手直しが必要です。また、32bitのExcel、あるいは古いExcel(2000とか)ではなぜか動作しません。APIの手直しが自分がバカなのでさらに手直しが必要なのかも?です。
動作としては、最後の、「SetForegroundWindow hwnd」で他のファイルを前面に移動させている=アクティブにしているので、本Webページの記事とやっていることは同じような意味です。
基本、「アクティブに(前面に)したいファイル名を指定するか、指定せずにやるか」の違いですが、上記URLの場合は、アクティブにしたい他のファイルが1つだけの場合、しか対応できません。
先に開いているファイルが複数あって、全部の後ろにしたい場合は、本Webページの方法のほうがラクちんかと思います。
なお、上記URLの回答の中では、最初の回答者の方のご回答のほうが、色々と参考になるかもしれません。
その中での参考URLが「他のテクニックの吸収」として、参考になるかも。
https://qiita.com/istoyo/items/c40a9dfb3d24b5326454
本Webページが参考にしたWebページは以下です。
https://liclog.net/getwindowtext-function-vba-api/
===================
以下、本文です。
AppActivate "白.bmp - ペイント"
みたいに、ウィンドウのタイトルがわかるなら、それを正確に指定するか、
以下のWebページの、
「NumLockが解除されてしまう問題」
という項目?
https://excel-ubara.com/excelvba1/EXCELVBA421.html
「AppActivate "白.bmp - ペイント"」の「白.bmp - ペイント」といった
ウィンドウタイトルを半自動で取得したい場合は、以降のようにします。
(正しくウィンドウタイトルを指定したつもりが、
エラーになってしまうような場合。)
まず、標準モジュールを1つ作成して、「'==========」以降のコードをコピペします。
そのあと、以下のようなSubプロシージャを書いて実行します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
' ' Sub test01() Dim s_Wintitle As String On Error Resume Next Let s_Wintitle = WindowTitleGet01("白") 'もしアクティブにしたいウィンドウのタイトルが '「白.bmp - ペイント」なら、 '「白」でも「ペイ」でもいいので、そのタイトルの '一部を、「WindowTitleGet01("×××")」の '「×××」の部分に書きます。 '他のウィンドウタイトルには含まれない、 '「そのウィンドウしその文字は含まれない!」という文字で。 AppActivate s_Wintitle '↑指定したタイトルのウィンドウを ' アクティブにする End Sub ' ' |
「On Error Resume Next」は、指定したファイルが開いてなかったときのエラー回避です。。
もし「Workbook_Open()」イベントで、別のExcelファイルを前面にしたかったら、
「Workbook_Open()」イベントに以下のコードを書けばOKです。
Dim s_Wintitle As String
On Error Resume Next
Let s_Wintitle = WindowTitleGet01("他のExcelファイルのファイル名かその一部")
AppActivate s_Wintitle
の4行か、あるいは、
On Error Resume Next
AppActivate WindowTitleGet01("他のExcelファイルのファイル名かその一部")
の2行を書きます。
※複数のファイルの最背面に起動したExcelファイルを置きたい場合は、
後者の2行でやって、
「AppActivate WindowTitleGet01("他のExcelファイルのファイル名かその一部")」を
ファイルの数だけ書きます。
なお、逆に、
「起動中(「Workbook_Open()」イベント)のExcelファイルをアクティブにしたい場合」は
特に何もしなくてもいいですが、
あえて、何かしたい場合は、
その時点(「Workbook_Open()」イベントの時点)では、
「起動しています - Excel」というウィンドウタイトル(スプラッシュミニ画面?)なので、
つまり、まだ、ファイル名がウィンドウタイトルには含まれていないので、
「起動」とかを指定して(あえての)アクティブにします。
他にExcelファイルが1つも開いてなければ「Excel」とか「 - Excel」とかでもOKですけど。
(大文字小文字は区別されるので、それも注意です。)
WaitなどでDoEventをループさせて待ってもダメでした。
なお、「'==========」以降のコードのうち、先に、(一番最後の)「Sub main()」を単純に実行すると、意味がわかりやすいかも?しれません。
また、指定したファイルを起動してから、そのまま最前面にアクティブにするような場合は、
もしかしたら、数ミリ秒か数秒待たないとうまく行かないかもなので、
その場合は、以下の「「Sleep」関数」でその秒数を待つといいかも?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
' ' '========== Option Explicit Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal ms As Long) '↑「Sleep」関数で、ミリ秒、待つためのAPIコード。 #If Win64 Then '【GetNextWindow関数】 Declare PtrSafe Function GetNextWindow Lib "user32" Alias "GetWindow" _ (ByVal hwnd As LongPtr, ByVal wFlag As Long) As LongPtr '【IsWindowVisible関数】 Declare PtrSafe Function IsWindowVisible Lib "user32" _ (ByVal hwnd As LongPtr) As LongPtr '【GetWindowText関数】 Declare PtrSafe Function GetWindowText Lib "user32" Alias "GetWindowTextA" _ (ByVal hwnd As LongPtr, ByVal lpString As String, ByVal cch As Long) As LongPtr '【FindWindow関数】 Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" _ (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr Dim hwnd As LongPtr #Else '【GetNextWindow関数】 Declare Function GetNextWindow Lib "user32" Alias "GetWindow" _ (ByVal hwnd As Long, ByVal wFlag As Long) As Long '【IsWindowVisible関数】 Declare Function IsWindowVisible Lib "user32" _ (ByVal hwnd As Long) As Long '【GetWindowText関数】 Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" _ (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long '【FindWindow関数】 Declare Function FindWindow Lib "user32" Alias "FindWindowA" _ (ByVal lpClassName As String, ByVal lpWindowName As String) As Long Dim hwnd As Long #End If Const GW_HWNDLAST = 1 Const GW_HWNDNEXT = 2 '####################################################### 'APIのWebページ付属のサンプルプログラム '今回は、これを無理矢理に関数化しました。 ' '使い方 'WindowTitleGet01("ウィンドウタイトルの一部の文字列") ' '指定したファイルを起動してから、 'そのまま最前面にアクティブにするような場合は、 'もしかしたら、数ミリ秒か数秒待たないとうまく行かないかもなので、 'その場合は、以下の「「Sleep」関数」でその秒数を待つといいかも? ' '####################################################### Function WindowTitleGet01(s_SerchWord As String) As String Dim strCaption As String * 500 hwnd = FindWindow(vbNullString, vbNullString) Dim caps As Collection Set caps = New Collection Dim cap 'As String Do If IsWindowVisible(hwnd) Then GetWindowText hwnd, strCaption, Len(strCaption) cap = Left(strCaption, InStr(strCaption, vbNullChar) - 1) If cap <> "" Then caps.Add cap End If End If hwnd = GetNextWindow(hwnd, GW_HWNDNEXT) Loop Until hwnd = GetNextWindow(hwnd, GW_HWNDLAST) For Each cap In caps ' Debug.Print cap '↑このコメントアウトをはずすと、すべてのウィンドウのタイトル名が ' イミディエイトに表示されます。 If 0 < InStr(1, cap, s_SerchWord, vbBinaryCompare) Then Let WindowTitleGet01 = cap Else End If Next cap End Function '####################################################### '以下、上記関数のもととなったコード。 '実行すると、今開いてるウィンドウのウィンドウタイトルが 'イミディエイトに列挙されます。 '####################################################### Sub main() Dim strCaption As String * 500 hwnd = FindWindow(vbNullString, vbNullString) Dim caps As Collection Set caps = New Collection Dim cap 'As String Do If IsWindowVisible(hwnd) Then GetWindowText hwnd, strCaption, Len(strCaption) cap = Left(strCaption, InStr(strCaption, vbNullChar) - 1) If cap <> "" Then caps.Add cap End If End If hwnd = GetNextWindow(hwnd, GW_HWNDNEXT) Loop Until hwnd = GetNextWindow(hwnd, GW_HWNDLAST) For Each cap In caps Debug.Print cap Next cap End Sub ' ' |