【無料配信♪】Renta !全タテコミ作品第1話

少し前から、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__'

引数の与え方もいろいろなサイトの切れ端を集めたような感じで書いてしまったのでそもそもの書き方が違っているのかもしれません。
私の検索が不足なのは重々承知ですが、よろしければ実際にはどのように書けばウィンドウを最前面に出すことができるのかと、エラーメッセージの具体的な意味を教えて欲しいです。お願いします。

このQ&Aに関連する最新のQ&A

A 回答 (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がお勧めです。)
    • good
    • 0
この回答へのお礼

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

お礼日時:2007/05/20 18:17

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qwxpythonの文法(ファイル参照ダイアログ)

wxpythonを研究で利用しなくてはいけなくなり、猛勉強をしております。

今までBASIC、Cを主に利用していたのでオブジェクト指向が分からず四苦八苦……
以下の「やりたいこと」のやり方をご存じの方がいらっしゃいましたら、ご教授ください。

●やりたいこと
ボタンをクリック → ファイル参照ダイアログ → ファイルの選択 → エディットボックスにフルパスをセット

●私が書いたスクリプト
import wx

def OnOpen(self,e):
wx.MessageBox('Download completed', 'Info')
self.dirname = ''
#dlg = wx.FileDialog(self, "select file", self.dirname, "", "*.*", wx.OPEN)



app = wx.App()

frame = wx.Frame(None, -1, 'Morphological Analysis', size=(640,480))#ウインドウ初期化
#▽ウインドウの設定ここから

frame.Centre()#中央表示

panel = wx.Panel(frame,wx.ID_ANY)#フレームのハンドルを取得
button_1 = wx.Button(panel,wx.ID_ANY,"Select File",pos=(30,30))
button_1.Bind(wx.EVT_BUTTON,self.OnOpen)



#ウインドウの設定ここまで△
frame.Show(True)#ウインドウ表示

app.MainLoop()


selfはJAVAで言うthisぽいなぁと思いつつ。
しかし、JAVAもしばらく触れてない上にそもそもにほぼ触ってないので覚えておらず。

症状としては、エラーを吐かずにすぐにプログラムが終了してしまうという状況です。

よろしくお願いします。

wxpythonを研究で利用しなくてはいけなくなり、猛勉強をしております。

今までBASIC、Cを主に利用していたのでオブジェクト指向が分からず四苦八苦……
以下の「やりたいこと」のやり方をご存じの方がいらっしゃいましたら、ご教授ください。

●やりたいこと
ボタンをクリック → ファイル参照ダイアログ → ファイルの選択 → エディットボックスにフルパスをセット

●私が書いたスクリプト
import wx

def OnOpen(self,e):
wx.MessageBox('Download completed', 'Info')
self.dirname = ''
#dlg = wx.FileDial...続きを読む

Aベストアンサー

そうか、基本的なところからわかってないんだなぁ。

Pythonには今のところPython2系列とPython3系列があって、
この両者は文法が少し違う。
今はこの2つが並存している時期なので注意が必要。
Python2とPython3ではモジュールの作り方も違うので、
まだPython3に対応していないモジュールとかライブラリもある。

wxPythonはまだPython3の安定リリースが出ていないから
たぶん君が使ってるのはPython2だ。
確かめるにはコンソールから python -V とやる。
もし Python 2.7.6 とか出てきたらPython2系列だ。

MeCabは使ったことがないので、
wxPythonと競合するかどうかはわかない。
もちろん、単体で import MeCab してみて動くことを確認したんだよね?
(してなかったら、私は呆れるっすよ。)
もしそうなら、私の手には負えないので
新しく質問を作ったほうがいいです。

> とりあえず、文法的には
> app = wx.App(redirect=False)
> と
> app.MainLoop()
> の間にイベントを書けばいいのでしょうか。
> そう解釈しております(Cで言うプロトタイプ宣言的な?)

うーん、まー、基本的にはそうなるんだけど、
Pythonにはプロタイプ宣言がない。
というか宣言自体がない。
ソースコードを一行一行、上から実行していって、
変数やら関数が出てきたら
「その場で」変数や関数を作っている [*]。
作る前から参照はできない。
だからグローバル変数に依存しているような関数は
自由な場所に置けなくなる。
これがスパゲッティ化する理由。

> オブジェクト指向勉強すべきかなぁ……

wxPythonのサンプルコードはほぼ全てクラスを使って書かれているので、
継承とか知らないと厳しいかも。


[*] 正確にはソースコードを実行する前にバイトコードにコンパイルしているので、
どんな変数や関数があるのかは実行する前にわかっている。
でも実際の関数が作られるのは def が出てきた場所になるので、
それ以前の行から関数を参照することはできない。

そうか、基本的なところからわかってないんだなぁ。

Pythonには今のところPython2系列とPython3系列があって、
この両者は文法が少し違う。
今はこの2つが並存している時期なので注意が必要。
Python2とPython3ではモジュールの作り方も違うので、
まだPython3に対応していないモジュールとかライブラリもある。

wxPythonはまだPython3の安定リリースが出ていないから
たぶん君が使ってるのはPython2だ。
確かめるにはコンソールから python -V とやる。
もし Python 2.7.6 とか出てきたらPython2系列だ。

MeC...続きを読む

QExcelVBAでスペースキー操作したい

sendkeysで、他のアプリケーションにキー操作を送りたいのですが、チェックボックスをオンにするときの【スペースキーを押す】という操作がうまくいきません。
sendkeys "{SPACE}",true ではだめなのでしょうか?
よろしくお願いします。

Aベストアンサー

こんにちは。

> キー操作を送りたいのは、ある大手メーカー製のERPシステムです

そうですか....SendKeys は、

 1. ウインドウがアクティブでないとダメ

   PC によって処理速度が異なります。例えば、ウインドウが開い
   てアクティブになるまでの速さ。開発時のPC は 1 秒待ってから
   SendKeys ..で良かったはずなのに、別 PC では 5 秒待たなけれ
   ばならなかった...ということですね。SendKeys でキー送信して
   もウインドウが開いてないんです。一例です。

   つまり、開発時の PC と同様の動作は別 PC で保証されません。

 2. 2000系OS で Numlock が解除される(今はどうなんだろ?)

などの問題があって、限られた用途「自分しか使わない」のであれば良い
のですが、基本的にオススメできません。SendKeys は最後の手段として
位置づけるのが良いと私は思います。

 # 困ったときの SendKeys でもあるんですけどね(´(・)`)

Excel VBA を使う理由が特になければ、Wendy02 さんオススメの UWSC が
私も良いと思います。

どうしても VBA で...というのであれば、PostMessage などの API を
使うことを考えてみて下さい。この場合、ウインドウがアクティブなのか
どうかは関係なく他アプリケーションを操作可能です。

以下はメモ帳(WinXP付属)を VBA で操作するテストコードです。要は、
ハンドルさえ拾えれば大抵のことは SendKeys でなくとも可能です。
ご参考までに...

Option Explicit

Private Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" ( _
   ByVal lpClassName As String, _
   ByVal lpWindowName As String) As Long
Private Declare Function FindWindowEx Lib "user32.dll" Alias "FindWindowExA" ( _
   ByVal hWnd1 As Long, _
   ByVal hWnd2 As Long, _
   ByVal lpsz1 As String, _
   ByVal lpsz2 As String) As Long
Private Declare Function PostMessage Lib "user32.dll" Alias "PostMessageA" ( _
   ByVal hWnd As Long, _
   ByVal wMsg As Long, _
   ByVal wParam As Long, _
   ByVal lParam As Long) As Long
Private Declare Sub Sleep Lib "kernel32.dll" ( _
   ByVal dwMilliseconds As Long)

Private Const WM_CHAR As Long = &H102
Private Const WM_COMMAND As Long = &H111
Private Const WM_CLOSE As Long = &H10
Private Const BM_CLICK As Long = &HF5&
Private Const BM_SETCHECK = &HF1
Private Const BST_CHECKED As Long = &H1
Private Const BST_UNCHECKED As Long = &H0

Public Sub Sample()
  
  Dim hWnd   As Long
  Dim hWnd_C  As Long
  Dim hWnd2  As Long
  Dim hWnd2_C As Long
  Dim strtSend As String
  Dim i    As Long
    
  ' クラス名とウインドウ構成は VB 付属の Spy++ で調べました。
  ' VECTOR などにも似た様なフリーツールは在ります

  ' メモ帳起動
  MsgBox "他アプリケーション制御のサンプルです。メモ帳を起動します"
  Application.Visible = False
  Shell "Notepad.exe", vbNormalNoFocus
  
  ' メモ帳のウインドウハンドルを取得
  hWnd = FindWindow("Notepad", "無題 - メモ帳")
  ' メモ帳の文字入力部のコントロールハンドルを取得
  hWnd_C = FindWindowEx(hWnd, 0&, "Edit", vbNullString)
  
  ' 文字列送信テスト
  strtSend = "教えて!Goo."
  MsgBox "メモ帳に文字列「" & strtSend & "」を送信します"
  For i = 1 To Len(strtSend)
    Call PostMessage(hWnd_C, WM_CHAR, Asc(Mid$(strtSend, i, 1)), 0&)
  Next i
  
  ' メモ帳のメニューをクリックし「検索」ダイアログを表示
  ' 「検索」のコマンドID 21 はリソースハッカーを使って調べました
  
  MsgBox "続いて検索ダイアログを表示します", vbInformation
  Call PostMessage(hWnd, WM_COMMAND, 21&, 0&)
  ' ダイアログが開くのを待つ(適当 500ミリ秒)
  Sleep 500&
  
  ' 検索ダイアログウインドウハンドル
  hWnd2 = FindWindow("#32770", "検索")
  ' チェックボックスのハンドル取得
  hWnd2_C = FindWindowEx(hWnd2, 0&, "Button", "大文字と小文字を区別する(&C)")
    
  MsgBox "チェックボックスを ON にします"
  Call PostMessage(hWnd2_C, BM_SETCHECK, BST_CHECKED, 0&)
  
  MsgBox "チェックボックスを OFF にします"
  Call PostMessage(hWnd2_C, BM_SETCHECK, BST_UNCHECKED, 0&)
  
  MsgBox "検索文字を送信してみます"
  hWnd2_C = FindWindowEx(hWnd2, 0&, "Edit", vbNullString)
  For i = 1 To Len(strtSend)
    Call PostMessage(hWnd2_C, WM_CHAR, Asc(Mid$(strtSend, i, 1)), 0&)
  Next i
  
  MsgBox "[キャンセル]ボタンをクリックします"
  hWnd2_C = FindWindowEx(hWnd2, 0&, "Button", "キャンセル")
  Call PostMessage(hWnd2_C, BM_CLICK, 0&, 0&)
  
  MsgBox " メモ帳を閉じます.[保存しますか?]ダイアログは手動で閉じて下さい."
  Call PostMessage(hWnd, WM_CLOSE, 0&, 0&)

  Application.Visible = True

End Sub

こんにちは。

> キー操作を送りたいのは、ある大手メーカー製のERPシステムです

そうですか....SendKeys は、

 1. ウインドウがアクティブでないとダメ

   PC によって処理速度が異なります。例えば、ウインドウが開い
   てアクティブになるまでの速さ。開発時のPC は 1 秒待ってから
   SendKeys ..で良かったはずなのに、別 PC では 5 秒待たなけれ
   ばならなかった...ということですね。SendKeys でキー送信して
   もウインドウが開いてないんです。一例です。

   ...続きを読む

Qウインドウの最前面表示

指定された日時になると、メッセージウインドウを表示するソフトを作成中ですが、そのウインドウのOnInitDialog()でShowWindow(SW_SHOW)をコールしても、その時に起動しているアプリケーションによっては、最前面に表示されません。(エクスプローラやIEの前面には表示されるが、VC++では背面に表示されます。)
アプリケーションによっては無理なのでしょうか?
(警告ウインドウとしても使用したいので、最前面に表示したいのですが...。)

環境
 WindowsXP
 Visual C++6.0

Aベストアンサー

先の投稿のAPI関数はすべてWinAPIですので スコープ解決演算子『::』を関数の前につけましょう

HWND hWndFore = ::GetForgroundWindow();
if ( hWndFore != this->m_hWnd ) {
  DWORD dwProcessID, dwThreadID;
  dwThreadID = ::GetWindowThreadProcessId( hWndFore, &dwProcessID );
  ::AttachThreadInput( GetCurrentThreadId(), dwThreadID, TRUE );
  ::SetForground( this->m_hWnd );
  ::AttachThreadInput( GetCurrentThreadId(), dwThreadID, FALSE );
}
といった具合です

CDialogクラスにもWinAPIと同名のメンバー関数があるので上記のような記述が必要です


人気Q&Aランキング