2023年8月16日水曜日

特定のウインドを常にアクティブにしておく python


簡単にできると思ったら結構難しくて3日かかった┐(´∀`)┌ 

Chrome で特定のサイトを見ながら作業 してる時に ウイルスソフトのアバストが反応してしまって 注意画面がドーンと前に出てくる これ何度も何度も出てくるので いちいち それを 閉じて Chrome に戻るのがすごく面倒 なので アバストの 画面が出てきたら それを 後ろにやって Chrome を再度アクティブにする  という スクリプト プログラムを作った 簡単だと思ったら 意外と難しかった ので備忘録

簡単に Python で書こうと久しぶりだし ということで始めたけれども 結局 うまくいかないし マニアックな win32 の API は Python から 呼び出せる ようになってなかったり これ Python の Win 32 のモジュールの中に入ってないっていう意味だけど で 実際に C で書いてみようと ビジュアルスタジオ なんかも 持ち出しながら 色々 色々やって 結果 何とかできたけど 今更ながら 勉強になったかな Microsoft の VS コード もうしばらく使ってなかったけど これで Python 書いて デバッグもできるんだね 変数 確認したりとかも できる 多分今までやったことなかったと思うけど そういうことがわかったのも まあ 収穫だった VS コードで C プラプラ のコードも書けるのかな かけるんだろうな そこからデバッグとかって進めれば ビジュアルスタジオ 使うよりは 軽いから いいかもな ビジュアルスタジオも昔ほど重たくないから そんなにハードル高くないけど

出来上がったスクリプトはこんな感じで 比較的シンプルです
----------------------
from win32gui import EnumWindows,GetWindowText,GetForegroundWindow
import time ,  subprocess 

CHROME=0
AVS=0
kaisu=1

def EnumWindowsProc1(hWnd):
  if GetWindowText(hWnd)=="アバスト無料アンチウイルス":
      global AVS
      AVS=hWnd
      print("--AVS発見")

def EnumWindowsProc2(hWnd):
  if( "Google Chrome" in GetWindowText(hWnd)):
      global CHROME
      CHROME=hWnd
      print("--CHROME発見")

while True:
  if CHROME==0:
    EnumWindows(lambda hWnd, _: EnumWindowsProc2(hWnd),None)
  if AVS==0:
    EnumWindows(lambda hWnd, _: EnumWindowsProc1(hWnd),None)

  if AVS :
    gaw=GetForegroundWindow()
    if AVS==gaw:
      print("---top " + str(kaisu) ,end="\r")
      subprocess.call(["cscript", "/nologo", "vbs.vbs"])
      kaisu=kaisu+1

  time.sleep(1)
----------------------(vbs.vbs)
Set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.AppActivate "Google Chrome"
----------------------

ゼットオーダーを変えるだけなら セット ウィンドウポス でいけると思ったんだけど これがなかなかうまくいかなくて 理由はよくわからない 他のサイトを調べて 裏技的に 1回 トップモストにしてからすぐにノートップ モストにすれば 全面に出るということがわかった 
でもこの場合の問題として アクティブにならない これも結構大きな問題で 最初 全面にさえすれば アクティブになると思ってたんだけど キー入力をすぐ受け付けてくれないっていう意味ですね 困るので いろんな API を その後 試した 
セット フォアグラウンド ウィンドウ とかセットフォーカスとか どれもうまくいかない パイソンから操作してるからだめで直接Cで書けば行けるかな と思ったけども 結果は同じだった 色々調べると Windows の OS のポリシーとして ある スレッドが他のスレッドに干渉しちゃいけないみたいな思想がありそう 勝手にアクティブウィンドウを外側から変えづらいようにしてるんだね 
じゃあ ということで スレッドにアタッチするための API アタッチプロセス パイソンでは使えなかったので直接 Cで 書いてみたけど 試した結果としては エラーで すすまず 
どうも ここら辺 奥が深くて ちょっと諦めかけたところで もう1回 いろいろ調べたら ビジュアルベーシック系の コマンドで さっと前面に出せることがわかった VB のスクリプト書いて実行したらものすごく簡単に 実行できたので パイソンのスクリプト から VBS を呼び出すようにしたら思った通りにできました 
やれやれ 時間がかかりましたけど なんとかできました よ VBで出来てCで出来ないなんてことはありえないから やり方 あるんだよな 出来たので これでよし 機会があったらまた追求してみたいと思います

0 件のコメント:

コメントを投稿