PythonでSetWindowPosを使う方法

このQ&Aのポイント
  • PythonでSetWindowPosを使ってウィンドウを最前面に表示する方法について教えてください
  • Tkinterとwin32gui、win32conモジュールを使ってウィンドウを最前面に表示しようとしていますがエラーが発生しています
  • ウィンドウを最前面に表示するための正しい方法と、エラーメッセージの意味について教えてください
回答を見る
  • ベストアンサー

PythonでSetWindowPosを使うにはどうしたら良いでしょうか?

少し前から、Tkinterを使って居りウィンドウを常に最前面に表示したいと思い立ちwin32guiとwin32conと言うモジュールが必要で、インポートするところまで辿り着いたのは良いのですが、その後がよくわかりません。 実験的に from Tkinter import * import win32gui,win32con root = Tk() win32gui.SetWindowPos(root,win32con.HWND_TOPMOST,0,0,200,150,win32con.SWP_SHOWWINDOW) root.mainloop() のようなコードを実行してみたのですが以下のようなエラーメッセージが帰ってきます。 Traceback (most recent call last): File "C:\Documents and Settings\PC USER\デスクトップ\Python\q2.py", line 9, in -toplevel- win32gui.SetWindowPos(root,win32con.HWND_TOPMOST,1,1,100,50,win32con.SWP_SHOWWINDOW) AttributeError: Tk instance has no attribute '__int__' 引数の与え方もいろいろなサイトの切れ端を集めたような感じで書いてしまったのでそもそもの書き方が違っているのかもしれません。 私の検索が不足なのは重々承知ですが、よろしければ実際にはどのように書けばウィンドウを最前面に出すことができるのかと、エラーメッセージの具体的な意味を教えて欲しいです。お願いします。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

どうやら無理そうです。 エラーがでている直接的な原因は、 win32gui.SetWindowPos(root,win32con.HWND_TOPMOST,...) では、Windowsオブジェクト(この場合rootという名前のTk()のインスタンス)の__int__メソッドが呼ばれるのですが、そもそもTk()には、 これがないためです。 ここで呼び出されようとするものは、 ウィンドウハンドラであり(詳しくは”HWND”とググって下さい) これを渡しています。 HWND=winfo_id()なのかな?ということで、変えてみます。 -------------------------------------------------------------- from Tkinter import * import win32gui import win32con root = Tk() hwnd = root.winfo_id() win32gui.SetWindowPos(hwnd,win32con.HWND_TOPMOST,0,0,0,0, win32con.SWP_NOMOVE | win32con.SWP_NOSIZE) root.mainloop() -------------------------------------------------------------- エラーは出なくなりますが、最前面固定にはなりません。 Tkの動きをWindowsのAPIが変えようとしているわけですが、 ネットで調べてみても、win32で、WindowsネイティブのAPIでGUIを作っている例はありますが、Tkでの成功例は見当たりませんでした。 短時間に再描画を繰り返すというあんまりな回避策はありましたが、、、。 Tkinterのもとは、Tkですが、Tkだけではそこまで出来なさそうなのと、 Tkinter(Python←→Tk) win32all(Python←→Windows)のつなぎのモジュールなので、 Windowsネイティブな高度な操作は、Tkinterでは、多分できないと思います。 常に最前面に出す必要のあるウィンドウといえばエラーダイアログですが、xwPythonならば、”そのアプリ内で”常に再前面のということができます。 他のアプリも含め、すべてのウィンドウより前面に出したいとなると、やはり難しいと思われます。GUI全部を、win32gui を使って書くしかないかもしれません。 (常に最前面に出すということは良く考えると危ういものです。) また、本質問の回答からはそれますが、 個人的には、Tkinterだけでなくwin32allも入れるくらいなら いっそのこと、wxPythonを使って書いたほうがよいと思います。 (Tkinterは、ピュアPythonにこだわりたいときとかで、Javaでいうawt,swingという位置づけで考えています。リッチなことをやろうというときは、SWT等を使うように、wxPythonがお勧めです。)

yorutrain
質問者

お礼

回答ありがとうございます。 うーん、無理っぽいんですか・・・ wxPythonも後で調べて見ます。 詳しい解説までして頂きありがとうございました。

関連するQ&A

  • Pythonコードの間違いを指摘して

    import tkinter as tk i=0 def a(): global i i=1 root=tk.TK() root.geometry("100x100") a() label=tk.Label(root,text=i) label.grid() tk.mainloop() →できた import tkinter as tk i=0 def a(): global i i=1 root=tk.TK() root.geometry("100x100") label=tk.Label(root,text=i) label.grid() button=tk.Button(root,text="button",command=a) button.grid() tk.mainloop() →できない(0と表示される)

  • python 絵をかいた後、inputを行いたい

    現在pythonの勉強を行っています。 Tkで線を引いた後、inputで指定した場所に絵をさらに追加したいのですが、 絵が描かれずに先にinputがでてしまってどうしたらよいか困っています。 下記のようなプログラムを今書いており(○×ゲームにしたい)、 どこを直したらよいかわかりません。 どうかご教授お願いします。 from Tkinter import * root = Tk() c0 = Canvas(root, width = 200, height = 200) c0.create_line(10, 70, 190, 70) c0.create_line(10, 130, 190, 130) c0.create_line(70, 10, 70, 190) c0.create_line(130, 10, 130, 190) c0.pack() for Y in range(9): a = input("どこに置く?: ") if Y%2==0: id = c0.create_oval(10+(60*a/3), 10+(60*a/3),70+(60*a/3) , 70+(60*a/3)) c0.pack() root.mainloop()

  • 実行中のプログラムが自分を隠すため

    そうしたい場所で SetWindowPos(hW,HWND_NOTOPMOST,0,0,0,0,SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE); としたのですが(hWはこのプログラムのメインウィンドウ)一旦はかくれるもののすぐに自分が前面に現れます どうしたら他の1つのプログラムのウィンドウに隠れた状態にする事ができるでしょうか?

  • Pythonコードの間違いを指摘して

    import tkinter as tk lastplay="" def gamestart(): global lastplay lastplay="試合開始" frame_main.tkraise() root=tk.Tk() frame_settings=tk.Frame(root) frame_settings.grid() button_gamestart=tk.Button(frame_settings,command=gamestart) button_gamestart.grid() fraim_main=tk.Frame(root) fraim_main.grid() label_1=tk.Label(frame_main,text=f"{lastplay}です") label_1.grid() fraim_settings.tkraise() root.mainloop() エラー内容 frame_mainが表示されたとき、変数の「試合開始」が表示されず、「です」のみ表示される。

  • SetWindowPosについて

    こんにちは。以前のスレッドを何件か拝見して、私の事象がないようなので、投稿します。背面フォーム内の処理をタイマ割込みやループなどで処理しつつ、その前面でフォームを表示する場合、SetWindowPosのAPIが有効というところまでは分かっているのですが、私の場合、割り込みによるビットのON/OFFをしたいと思ってロジックを組んでいるのですが・・・ どうしてもモーダルフォームを前面表示したときと同じように、背面での処理が走ってくれません・・・ ロジックですが、前面フォームのイベントを sub Form_Load() SetWindowPos(frm_ctrl.hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE) end sub のように行っています。アンロード時にハンドルの設定は解除してあります。 タイマ割込みの処理が他者作成のため、目下処理が不明なのですが、こちらの方もAPIを使用しているかもしれません。 情報が少なくて恐縮ですが、この内容で解決の手掛かりとなる事をご教授頂けると幸いです。

  • Pythonでキーが押されたことを判定したい

    Python初心者です。Pythonでキー入力の値を変数keyとして取り出したいのですが、上手くいきません。 グローバル関数がわかっていないのかと思いますが直し方がわかりません。 最終的に37行目のprint(key)でkeyの値を取り出したいのですがどうすればよいですか。 # -*- coding: utf8 -*- import tkinter as tk import winsound root = tk.Tk() frame = tk.Canvas(root, width=800, height=600) pimg = tk.PhotoImage(file="wall.png") frame.place(x=0, y=0) frame.create_image(400, 300, image=pimg) imgA = tk.PhotoImage(file = 'pressed_A.png') imgB = tk.PhotoImage(file = 'Pressed_B.png') def keyA(event): global key key="A" frame.place(x=0, y=0) frame.create_image(320, 220, image=imgA, tag="illust") root.update() winsound.PlaySound("pressed_A.wav", winsound.SND_FILENAME) def keyB(event): global key key="B" frame.place(x=0, y=0) frame.create_image(320, 220, image=imgB, tag="illust") root.update() winsound.PlaySound("pressed_B.wav", winsound.SND_FILENAME) frame.bind("a", keyA) frame.focus_set() frame.pack() frame.bind("b", keyB) frame.focus_set() frame.pack() print(key) root.mainloop()

  • 非アクティブのウィンドウを最前面に呼び出したい。

    右ダブルクリックで呼び出すランチャプログラムを作成したいのですが、 システムフックをかけてWM_RBUTTONDBLCLKをアプリ側に送り,それに反応させる形でランチャのウィンドウを最前面に持ってきたいのですが上手くいきません。 フックされたメッセージが送られてきた場合の処理は以下のようになっています。 ~省略 case WM_USER+100: //ダブルクリックが送られてきた場合のメッセージコード //任意文字列を別ウィンドウのリストボックスに吐く自作関数 Add("dblclk"); //以下でウィンドウを最前面に持ってくる。 //lpにクリックされた座標が入っている SetWindowPos(hWnd , HWND_TOP,(int)LOWORD(lp),(int)HIWORD(lp), NULL,NULL,SWP_NOSIZE|SWP_SHOWWINDOW); SetForegroundWindow(hWnd); UpdateWindow(hWnd); break; ~省略 このコードの場合、ウィンドウの位置は変更されるのですが、最前面に来てくれません。 Add関数が呼ばれているのでフック自体は成功しているようなのですが、何かおかしな点はありますでしょうか?

  • Formをアクティブにする

    バックグラウンド(フォームは非表示にしている)で実行しているプログラムでエラーが発生した場合にサブフォームを表示しています。 このサブフォームを最前面に表示しフォームをアクティブにしたいのですがどのようにすればよろしいでしょうか?(このフォームにはテキストボックス等はなくラベルのみです。) 現在、SetWindowPosにてこのサブフォームのhwndを渡し、HWND_TOPMOSTにしサブフォームにSetFocusさせています。 しかし、実行されると最前面には来るのですがタイトルバーが点滅(?)した状態になりアクティブになりません。このフォームをクリックするとアクティブとなります。 よろしくお願いします。

  • 指定したアプリケーションを処理が通るときだけモニターの画面の最前面に出したい

    お世話になります。 C++6.0 MFCで開発しております。 今、 (1)A.exeのボタンを押すとB.exeを起動(A.exeの上にB.exeが表示) (2)B.exeが終了するとA.exeに終了通知をして、A.exeに処理を戻す。  (A.exeを最前面に表示する) (3)再度A.exeのボタンを押す。  →(1)のときは、A.exeの上にB.exeが表示されていたのに、A.exeの下にB.exeが表示される (2)のA.exeに処理を戻した後、A.exeが最前面に出るように SetWindowPos(hWnd,HWND_TOPMOST,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE) を実行しています。 (1)、(3)のA.exeのボタンを押すと、A.exeの上にB.exeが表示され、 (2)の時に、A.exeが他のアプリケーションを含めて、最前面、モニターの最前面に表示されるようにしたいのです。 お手数ですがなにとぞよろしくお願いします。 以上よろしくお願いします。

  • 最大化時のフルスクリーン

    いつもお世話になっております。 VS2005 を使ってWindowsアプリケーションの実装を行っています。 最大化時にフルスクリーンにしたくプログラムを作成しているのですが、 WndProc内で下記のプログラムを実行し、 最大化アイコンをクリックするとバグ?が起きてしまいます。 -------------------------------------------------- case WM_SIZE:   cxClient = LOWORD(lParam);   cyClient = HIWORD(lParam);   if(wParam == SIZE_MAXIMIZED){ //最大化されたら     ShowWindow(hWnd, SW_SHOWNORMAL); //(1)ウィンドウを元のサイズに戻す     //(2)アプリケーションのウィンドウのフレームを「なし」にする     GetWindowLong(hWnd, GWL_STYLE); //ウインドウ・スタイルの取得     SetWindowLong(hWnd, GWL_STYLE, WS_POPUP); //ウインドウ・スタイルの設定     SetWindowPos(hWnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOZORDER);     ShowWindow(hWnd, SW_MAXIMIZE); //(3)ウィンドウ最大化   } return 0; -------------------------------------------------- 実行したアプリケーションの右上の最大化ボタンを押すと、 見た感じではif文の中を繰り返し行っているような・・・ 元のサイズに戻って最大化になってを数秒繰り返して 最後にペイントして停止します。(高速なため確かではありません) 上記プログラムをどう直したらよいのでしょう。 ご教授お願いいたします。

専門家に質問してみよう