前の月 / 次の月 / 最新

hiChangeLog / 2008-06

2008-06
SMTWTFS
1234567
891011121314
15161718192021
22232425262728
2930

2010 : 01 02 03 04 05 06 07 08 09 10 11 12
2009 : 01 02 03 04 05 06 07 08 09 10 11 12
2008 : 01 02 03 04 05 06 07 08 09 10 11 12
2007 : 01 02 03 04 05 06 07 08 09 10 11 12
2006 : 01 02 03 04 05 06 07 08 09 10 11 12

2008-06-19 Thu

pywin32でビットマップを扱う際のメモ [python][PyWin32]

なんちゃってwin32api(あるいはMFC)環境であるpywin32でビットマップを扱う際、意外と手間取ったのでメモ。

やりたかったことは、キャプチャしたビデオ信号のリアルタイム表示。つまり頻繁にやってくるビットマップのデータ列を頻繁に描画したいという状況。Windowsでのビットマップの描画方法は、私の理解では、多分、(有効な)ビットマップハンドルの取得方法に帰着する。なのでデータ列からビットマップハンドルを如何に作るかがここでのお題となる。今のところ、ctypesでCreateDIBSectionを呼出すのが良いと思っており、実際問題なく動作している。

win32gui.LoadImage や PyCBitmap.LoadBitmapFile は単純で簡単だが、リアルタイム表示においていちいちファイルを介するのは速度的に論外。StringIOでメモリ上にファイルオブジェクトを作成すれば速度の問題は解決するかと思い PyCBitmap.LoadBitmapFile でやってみたが、しばらくすると「このコマンドを実行する記憶域がありません」と例外が飛んでくるので、この方法も無理。

そもそもこんな状況ではwin32apiのCreateDIBSectionの使用が定石のひとつと思うが、残念なことにpywin32にこれは定義されていない。(Windows のデバイスコンテキストをビットマップファイルに変換する。Python でも参照)なのでctypesを介してこれを呼出すことにした。

とはいえ私はctypesの動作を深く理解していない(なので下記にいちいちメモをする)。そこでpygletのソースから該当部分を拝借する方法をとった。

CreateDIBSectionにはBITMAPINFOHEADERを渡す必要がある。これを定義するには如何のようにする(window/win32/types.py より)。

from ctypes import *
from ctypes.wintypes import *
class BITMAPINFOHEADER(Structure):
    _fields_ = [
        ('biSize', DWORD),
        ('biWidth', LONG),
        ('biHeight', LONG),
        ('biPlanes', WORD),
        ('biBitCount', WORD),
        ('biCompression', DWORD),
        ('biSizeImage', DWORD),
        ('biXPelsPerMeter', LONG),
        ('biYPelsPerMeter', LONG),
        ('biClrUsed', DWORD),
        ('biClrImportant', DWORD),
    ]

実際の値は下記のように作る(window/win32/__init__.py, Win32Window.get_icon より)。勿論、ヘッダの内容はデータ列の内容に依存する。DirectShowを使うなら AM_MEDIA_TYPE 内の VIDEOINFOHEADER 内に BITMAPINFOHEADER そのものがあるので、それをそのまま使えばよい。
def GetBitmapInfoHeader(w, h):
        header = BITMAPINFOHEADER()
        header.biSize = sizeof(header)
        header.biWidth = w
        header.biHeight = h
        header.biPlanes = 1
        header.biBitCount = 24
        header.biCompression = 0
        header.biSizeImage = w*h*3
        header.biXPelsPerMeter = 0
        header.biYPelsPerMeter = 0
        header.biClrUsed = 0
        header.biClrImportant = 0
        return header

そして以下のようにCreateDIBSectionを呼ぶ。(上と同じく__init__.pyより)
dataptr = c_void_p()
bitmap = windll.gdi32.CreateDIBSection(self.GetDC().GetHandleOutput(),
                                            byref(GetBitmapInfoHeader(w, h)),
                                            win32con.DIB_RGB_COLORS, byref(dataptr), None, 0)

あとはメモリデバイスコンテキストにbitmapをSelectObjectすれば準備完了。実際のデータを流すには下記のようにする。type(buf)はstr。(VideoCaptureモジュールのgetBufferより取得)
memmove(dataptr, buf, len(buf))

以上で問題なく動いている模様。

ctypesは以下に記述があった。
ctypesによるDLL内の関数の呼び出し
mtamaki.com : #47 (pythonからctypesで任意のDLLの関数を使う。)
2007年 11月 (1)。

描画(GDI、デバイスコンテキスト)にまつわるメモ [python][PyWin32]

GDIオブジェクト、デバイスコンテキスト、メモリデバイスコンテキストといった単語は作業中はなんとなく解ったつもりでいるが、少し間をおくと木端微塵に忘れる。pywin32で描画のコードを書こうとしたが、やっぱりすっかり忘れていて参った。動いたコードをメモしておく。

from pywin.mfc import dialog
import win32con, win32ui

class Mydialog(dialog.Dialog):

    dlgstyle = (win32con.WS_DLGFRAME | win32con.DS_MODALFRAME | win32con.WS_POPUP |
                win32con.WS_VISIBLE |  win32con.WS_CAPTION  | win32con.WS_SYSMENU )
    tmpl = [ ["my dialog", (0, 0, 200, 100), dlgstyle], ]
    def __init__(self): dialog.Dialog.__init__(self, self.tmpl)

    def OnPaint(self):
        dc = self.GetDC()

        # copy itself
        dc.BitBlt((0,0), (20,20), self.GetWindowDC(), (0,0), win32con.SRCCOPY)

        # line
        dc.LineTo((30,30))

        # line with a customized pen
        cpen = win32ui.CreatePen(win32con.PS_SOLID, 5, 10000000)
        dc.SelectObject(cpen)
        dc.LineTo((50,50))

        # drawing on memory device context
        dcmem = dc.CreateCompatibleDC()
        cbmp = win32ui.CreateBitmap()
        cbmp.CreateCompatibleBitmap(dc, 100, 100)
        dcmem.SelectObject(cbmp)
        dcmem.SelectObject(cpen)
        dcmem.LineTo((30,30))
        dc.BitBlt((50,0), (50,50), dcmem, (0,0), win32con.SRCCOPY)
        
        self._obj_.OnPaint()

d = Mydialog()
d.DoModal()

2008-06-17 Tue

VideoCaptureのソースをいじる [python]

[2008-05-23-1]のVideoCaptureのソースをビルドした際のメモ。
WinXP MCE SP2, VS 2003, PFSDK(Windows Server 2003 SP1 SDK)

プロジェクトを開こうとすると古いとか言われたが、指示通り問題なく新しいプロジェクトに変換できた。

C/C++=>全般=>追加のインクルードディレクトリに追加:
C:\Program Files\Microsoft Platform SDK\Samples\Multimedia\DirectShow\BaseClasses

リンカ=>入力=>追加の依存ファイル で、strmbase.libの場所を変更:
上記BaseClassesディレクトリで nmake /f makefile NODEBUG=hoge としてビルド(hogeはたぶん何でもいい)しstrmbase.libを作った上で
"C:\Program Files\Microsoft Platform SDK\Samples\Multimedia\DirectShow\BaseClasses\WIN2000_RETAIL\strmbase.lib"
に変える。


以上でビルドは通る。
関数を増やしたい場合は元ソースの記述をマネして本体を記述し、Dev_methods 変数にそれを加え、VideoCapture.py も適宜変更する。
試しに、getbuffer関数をそっくりコピペしてgetbuffer2と名前を変え、返り値を下記のように変えDev_methodsとVideoCapture.pyを適宜してやってみたが、ちゃんとBITMAPINFOHEADERがpythonから取得できた。(できたvidcap.pydのサイズが配布物(20KB)より小さい(13KB)のはなぜ?)

PyObject *pbmituple;
BITMAPINFOHEADER a = pVideoHeader->bmiHeader;
pbmituple = Py_BuildValue("(k, l,l, H,H, k,k, l,l, k,k)",
  a.biSize, a.biWidth, a.biHeight, a.biPlanes, a.biBitCount,
  a.biCompression, a.biSizeImage, a.biXPelsPerMeter,
  a.biYPelsPerMeter, a.biClrUsed, a.biClrImportant);
PyObject *value;
value = Py_BuildValue("(s#,O)", buffer, size, pbmituple);

2008-06-13 Fri

vpythonでオブジェクトによってlabelを隠す /vpython - hide labels by other objects2 [python]

[2008-06-09-01]の続き。
vpythonでlabelを隠すためのパッチを作成した。depthtestフラグによって隠す/隠さないを制御できるようにした。パッチは結構強引で、多分作成者の設計指針をないがしろにしており、そのへんが後ろめたい。まあ個人的な使用だからいいや。
I have written a patch of vpython in order to obscure/hide labels when they go behind objects. The behavior can be toggled through "depthtest" flag. Though this ad hoc patch might not meet with the developers design, some might feel confortable in their private usage.

environment:
- Windows MCE XP2, python 2.5.2
- developement softwares as described in VCBuild.txt
- CVS-HEAD source of vpython 4 beta retrieved at 8 Jun '08 (boost_1_35_0.zip should be decompressed in the "dependencies" directories, since "cvisual.sln" assumes that, not boost_1_34_1.zip)

command-line: (in "vpython-core2" directory where "include" and "src" (and others) directories exist)

patch -p1 < patch_file_shown_below.patch

diff-file:
diff -ur original/include/label.hpp modified/include/label.hpp
--- original/include/label.hpp	Wed Apr  9 06:42:02 2008
+++ modified/include/label.hpp	Wed Jun 11 20:12:15 2008
@@ -59,6 +59,9 @@
 	void set_yoffset( double yoffset);
 	double get_yoffset();
 
+	void set_depthtest( bool _depthtest);
+	bool get_depthtest();
+
 	void set_border( double border);
 	double get_border();
 
@@ -85,6 +88,7 @@
 	// In pixels:
 	double xoffset;   // offset from pos + space to the box
 	double yoffset;
+	bool depthtest;
 	double border;    // space between text and box
 
 	/// A common name for the font.
diff -ur original/include/util/displaylist.hpp modified/include/util/displaylist.hpp
--- original/include/util/displaylist.hpp	Sun Apr  6 10:11:52 2008
+++ modified/include/util/displaylist.hpp	Fri Jun 13 16:21:54 2008
@@ -18,6 +18,9 @@
 	shared_ptr<class displaylist_impl> impl;
  
  public:
+	bool depthtest;
+	displaylist() : depthtest(true) {}
+
 	/** Begin compiling a new displaylist.  Nothing is drawn to the screen
  		when rendering commands into the displaylist.  Be sure to call 
  		gl_compile_end() when you are done.
diff -ur original/src/core/display_kernel.cpp modified/src/core/display_kernel.cpp
--- original/src/core/display_kernel.cpp	Wed Apr  9 12:46:36 2008
+++ modified/src/core/display_kernel.cpp	Fri Jun 13 15:37:12 2008
@@ -700,13 +700,15 @@
 	
 	// Render all objects in screen space.
 	disable_lights();
-	gl_disable depth_test( GL_DEPTH_TEST);
+//	gl_disable depth_test( GL_DEPTH_TEST);
 	typedef std::multimap<vector, displaylist, z_comparator>::iterator
 		screen_iterator;
 	screen_iterator k( scene_geometry.screen_objects.begin());
 	screen_iterator k_end( scene_geometry.screen_objects.end());
 	while ( k != k_end) {
+		if(!k->second.depthtest) glDisable( GL_DEPTH_TEST);
 		k->second.gl_render();
+		if(!k->second.depthtest) glEnable( GL_DEPTH_TEST);
 		++k;
 	}
 	scene_geometry.screen_objects.clear();
diff -ur original/src/core/label.cpp modified/src/core/label.cpp
--- original/src/core/label.cpp	Tue Apr 15 05:49:58 2008
+++ modified/src/core/label.cpp	Wed Jun 11 20:12:15 2008
@@ -20,6 +20,7 @@
 	space(0),
 	xoffset(0),
 	yoffset(0),
+	depthtest(false),
 	border(5),
 	font_description(), // also tried "sans", which seems equivalent
 	font_size(-1), // also tried 10, which seems equivalent
@@ -37,6 +38,7 @@
 	space( other.space),
 	xoffset( other.xoffset),
 	yoffset( other.yoffset),
+	depthtest(other.depthtest),
 	border( other.border),
 	font_description( other.font_description),
 	font_size( other.font_size),
@@ -211,6 +213,18 @@
 	return yoffset;
 }
 
+void
+label::set_depthtest( bool _depthtest)
+{
+	depthtest = _depthtest;
+}
+
+bool
+label::get_depthtest()
+{
+	return depthtest;
+}
+
 void 
 label::set_border( double n_border)
 {
@@ -398,6 +412,7 @@
 		text_layout->gl_render(scene, text_pos);
 	} glMatrixMode( GL_MODELVIEW); } // Pops the matricies back off the stack
 	list.gl_compile_end();
+	list.depthtest = depthtest;
 	check_gl_error();
 	scene.screen_objects.insert( std::make_pair(pos, list));
 }
diff -ur original/src/python/wrap_primitive.cpp modified/src/python/wrap_primitive.cpp
--- original/src/python/wrap_primitive.cpp	Wed Apr  9 03:28:00 2008
+++ modified/src/python/wrap_primitive.cpp	Wed Jun 11 20:12:15 2008
@@ -225,6 +225,7 @@
 		.add_property( "height", &label::get_font_size, &label::set_font_size)
 		.add_property( "xoffset", &label::get_xoffset, &label::set_xoffset)
 		.add_property( "yoffset", &label::get_yoffset, &label::set_yoffset)
+		.add_property( "depthtest", &label::get_depthtest, &label::set_depthtest)
 		.add_property( "border", &label::get_border, &label::set_border)
 		.add_property( "box", &label::has_box, &label::render_box)
 		.add_property( "line", &label::has_line, &label::render_line)
example:
from visual import *

box(axis=(1,0,0), length=0.1, height=4, width=4, up=(1,0,0))
cylinder(pos=(-1,0,0), axis=(2,0,0), radius=0.1)

## default behavior
#foo = label(pos=( 1.3,0,0), text='foo')
#bar = label(pos=(-1.3,0,0), text='bar')

# new behavior
foo = label(pos=( 1.3,0,0), text='foo', depthtest=True)
bar = label(pos=(-1.3,0,0), text='bar', depthtest=True)

外部のCGI実行結果やHTMLの出力(オブジェクト)をHTMLに埋め込む [HTML]

imgタグではsrcにURLを指定できるので、各地に離散する画像リソースを1つのHTMLファイルでまとめて表示できる。
同様なことが、CGIの実行結果やHTML出力に対してもできないか?と思い調べた。

できるようである。
IFRAME を使わない方法の補足

iframeかobjectタグを使えばできる。
前者は(X)HTML的には原則使わないべきタグなので、後者の使用が望ましそう。
後者にはIEでうまく表示できないという認識があるようだが、width及びheight属性の指定によりIEでもちゃんと表示できることを上記「IFRAME を使わない方法の補足」から学んだ。
というわけで実際には以下のように記述すれば良いのだろう。

<object data="hoge.py?msg=fuga" type="text/plain" width="200" height="200">
here an object tag exists
</object>
Firefox2.0.0.14とIE6で、hoge.pyなるCGIの表示を確認できた。 w3m/0.5.1では代替文字列"here an object tag exists"が表示された。

その他参考:
IFRAMEを使わずにHTMLファイルから他のHTMLファイルを読み込む方法
インラインフレームを使わずにCGIを呼び出す!

2008-06-09 Mon

pywin32のMFCプログラミングでリソース(スクリプト/エディタ)が利活用できるか? [PyWin32][Windowsプログラミング]

[2008-06-07]でPyWinのMFC(GUI)プログラミングが有望っぽい事をメモした。
さてGUIプログラミングではコントロールの配置がキモである。ソース内にベタ書きするのは、ファイルが1つで済むので好きだけど、ある程度の規模に膨れるとそうも言ってられなくなる。Visual Studioによるwin32/MFC開発ではリソースエディタでもってコントロールの配置を行い、それをリソーススクリプトに保存するが、これが中々具合が良い。これをPyWin32にも活用できないものだろうか?

ResEditなるものがあるようだ。ちょっと導入してみたけど中々良い。リソースの作成はこれで大丈夫そう。(Visual Studioが使えない時という意味で)

では如何にそれをpythonに喰わせるか?という話になる。[Spambayes-checkins] spambayes/Outlook2000/dialogs/resources rcparser.py, NONE, 1.1.2.1 にそれっぽいコードがある。今度試してみよう。

Referrer (Inside): [2008-08-16-1]

vpythonでlabelを隠すことができたっぽい /vpython - hide labels by other objects [python]

vpythonなるものがある。超簡単に3Dグラフィックを描画できる優れもの。
文字を表示するlabelなるオブジェクトがあるが、これは他のオブジェクトの背後に回っても描画される(つまり常に見えている状態)。あくまで個人的にだが、この振舞はあんまり有難くないと感じる:背後に位置するものはキッチリと隠れてほしい(今後そう思わぬ状況にも遭遇するだろうが、現在はそう思っている)。同様の意見の方もちらほらいる。だけど同等の機能は現行のベータにも備わっていない模様。

vpython is great, while I prefere labels that become hidden when some objects come in front of them.
fixed strings/notes, and hidden labels
[Visualpython-users] label behavior

なんで、自力で何とかすべくCVSのHEADのソースを取ってきていじった。うまくいった様なので顛末をメモしておく。
The "diff" shown below based on CVS-HEAD source succeeded (at least as far as I see) to obscure(hide) labels by objects in front of them. / By adopting a patch shown below to CVS-HEAD source, labels became hidden from view when they went behind objects.
My environment: python 2.5.2 on Windows 2000

結論: display_kernel.cpp 中 display_kernel::draw 内 "Render all objects in screen space" とコメントされてる部分の gl_disable depth_test( GL_DEPTH_TEST); をコメントアウト

以下やったことの冗長な記述。

Windowsにおけるビルド手順はView of /vpython-core2/VCBuild/VCBuild.txtにて丁寧に解説されている。私は記述の通りやったに過ぎない。

まず VPython-Win-Py2.5-4.beta26.exe をSourceForgeから入手しインストールする。必要なものを後に入れ替えるという手順をとっている。大前提として、これがちゃんと動作することを確認しておく。

次にCVSでソースを入手する。以下でできた。パスワードはカラ。(私はCVSの使用は初めてで、オプションの意味と意義は理解していない。CvsGuiのページでダウンロードしたファイルに入ってたcvsntを用いた)

cvs.exe -d :pserver:anonymous@visualpython.cvs.sourceforge.net:/cvsroot/visualpython login
cvs.exe -d :pserver:anonymous@visualpython.cvs.sourceforge.net:/cvsroot/visualpython co vpython-core2

安定版及び開発版(のベータリリース)のソースのtar ballがSourceForgeから入手できるが、これらのビルドは私の実力不足により失敗に終わった。
安定版について:配布バイナリは3.2.11だがtar ballで配布されているのは3.2.9のみ。ビルド方法は内包のINSTALL.TXTに詳細に説明されているが、MinGW/MSYSの環境構築が必要で結構面倒。numpyをインストールしろみたいな指示が出たけど実際に必要なのはNumericかnumarrayな感じだったり、またビルドしてはみたもののよくわからんImportErrorが出たり、手当たり次第に.pthを作るも状況は改善しないなどしたため、理解があやふやなまま断念することにした。3.2.9はpython2.4の使用を念頭に置いており、3.2.10でpython2.5使用に切り替えたようなので、この辺が関係あるのかも?いずれにせよ気力は尽きた。
開発版について:beta26を試した。MSWINDOWS.txtにまたまた詳細なビルド手順が記されているが、一層面倒なMinGW/MSYSとGTKの環境構築を含み(私見だが)苦行のように長い。頑張ってみたものの、一旦つまずいた所で気力が尽きてやめた。
CVSで入手したソースには必要なboostも付属するしVisual Studioのソリューションを開いてビルドすれば終わるという手軽で幸せな方法が用意されている。同梱の MSWINDOWS.txt にもその旨記載されていた。


入手したソースで dependencies の中にboostが用意されている。boost_1_34_1 なる展開済のディレクトリはできていたが、同梱のVisual Studioのソリューションでは boost_1_35_0 を使う設定になっていた。ソリューションの設定を修正してもいいのかもしれないが、幸い boost_1_35_0.zip は同梱されていたので、これを展開して使うことにした。

そしてビルド環境を整える。Visual C++ 2005 Express Edition と platform SDK を導入すれば良い。前者をVisual Studio Developer CenterのDownloadから導入した(Version 8.0.50727.42 だった)。platform SDKは既に導入済だった。確か http://www.microsoft.com/downloads/details.aspx?FamilyId=A55B6B43-E24F-4EA3-A93E-40C0EC4F68E5&displaylang=en から入手したはず。スタートメニューでの表記は"Microsoft Platform SDK for Windows Server 2003 SP1"だった。幾つか細かな設定が必要だがVCBuild.txtに従って行った。

まずソースを修正せずにビルドしたもので動作確認をした。C:\Python25\Lib\site-packages\visual をゴッソリ消して、VCBuild.txtの指示通りにCVSで拾ってきたものと入れ替えた。入れ替え後のものにはgtk関連のDLLがあらかた抜けてた。そしてVS上でビルドする。成果物は多分 cvisual.pyd だけなのだろうが、これは自動的にあるべき場所に配置される。(VS上で Project => Property => Configuration Properties => Linker => General => Output File を見よ)なので、ビルド後に適当なスクリプトが動作すれば、ビルドには成功している。(気持ち、動きがスムーズになったと感じた)

いよいよソース修正。上述したように、一箇所のコメントアウトでできているみたい。display_kernel.cpp 中 display_kernel::draw 内 "Render all objects in screen space" とコメントされてる部分の gl_disable depth_test( GL_DEPTH_TEST); をコメントアウトする。OpenGLの事は全くわからないが、この行が前後関係を司っているらしい。

$ diff -u display_kernel.cpp.orig display_kernel.cpp
--- display_kernel.cpp.orig     Wed Apr  9 12:46:36 2008
+++ display_kernel.cpp  Sun Jun  8 21:30:02 2008
@@ -700,7 +700,7 @@
        
        // Render all objects in screen space.
        disable_lights();
-       gl_disable depth_test( GL_DEPTH_TEST);
+//     gl_disable depth_test( GL_DEPTH_TEST);
        typedef std::multimap<vector, displaylist, z_comparator>::iterator
                screen_iterator;
        screen_iterator k( scene_geometry.screen_objects.begin());


これでビルドしたら、文字がちゃんとオブジェクトに隠れるようになった!この状態で使い込んだわけではないが、まあこうしたことによる問題も起きないんじゃないかな、と思う。

2008-06-07 Sat

pywin32によるMFCアプリケーションの雛形 [python][PyWin32][Windowsプログラミング]

pywin32のmfcラッパを試している。pythonで結構簡単にWindowsのダイアログが作れて、良さそう。
とりあえず手元で試して動いたコードをメモ。

とにかくダイアログを出す、という例が以下。拡張子をpywにして保存しダブルクリックすればOK。

from pywin.mfc import dialog
import win32con

class Mydialog(dialog.Dialog):

    dlgstyle = (win32con.WS_DLGFRAME | win32con.DS_MODALFRAME | win32con.WS_POPUP |
                win32con.WS_VISIBLE |  win32con.WS_CAPTION  | win32con.WS_SYSMENU )
    btnstyle = (win32con.BS_PUSHBUTTON | win32con.WS_TABSTOP |
                win32con.WS_CHILD | win32con.WS_VISIBLE)    
    dlgButton = 0x0080
    tmpl = [
        ["my dialog", (0, 0, 200, 100), dlgstyle], # dialog
        [dlgButton, "my OK",     win32con.IDOK, (5, 55, 190, 40), btnstyle], # button
        ]
    def __init__(self):
        dialog.Dialog.__init__(self, self.tmpl)


d = Mydialog()
d.DoModal()

ボタンを作成しハンドラを割当てた例が以下。アプリケーション作成にあたっての出発点的なもの。
from pywin.mfc import dialog
import win32con

class Mydialog(dialog.Dialog):

    dlgstyle = (win32con.WS_MINIMIZEBOX | win32con.WS_DLGFRAME |
                win32con.DS_MODALFRAME | win32con.WS_POPUP | win32con.WS_VISIBLE |
                win32con.WS_CAPTION | win32con.WS_SYSMENU | win32con.DS_SETFONT )
    btnstyle = (win32con.BS_PUSHBUTTON | win32con.WS_TABSTOP |
                win32con.WS_CHILD | win32con.WS_VISIBLE)    
    IDC_MYBUTTON = 1025
    dlgButton = 0x0080
    tmpl = [
        ["my dialog", (0, 0, 200, 100), dlgstyle], # dialog
        [dlgButton, "my OK",     win32con.IDOK, (5,  5, 190, 40), btnstyle], # button
        [dlgButton, "my button", IDC_MYBUTTON,  (5, 55, 190, 40), btnstyle], # button
        ]
    def __init__(self):
        dialog.Dialog.__init__(self, self.tmpl)
        
    def OnInitDialog(self):
        rc = dialog.Dialog.OnInitDialog(self)
        self.HookCommand(self.OnMyButton, self.IDC_MYBUTTON)
        self.btn = self.GetDlgItem(self.IDC_MYBUTTON)
        return rc

    def OnMyButton(self, id, cmd):
        if cmd==win32con.BN_CLICKED:
            ret = self.MessageBox('hello, my button', 'my caption', win32con.MB_YESNO)
            if ret==win32con.IDYES: cap = 'yes'
            else: cap = 'no'
            self.btn.SetWindowText(cap)
        
    def OnOK(self):
        rc = dialog.Dialog.OnOK(self)
        self.MessageBox('OnOK!', 'farewell')
        return rc

    def OnCancel(self):
        rc = dialog.Dialog.OnCancel(self)
        self.MessageBox('OnCancel!', 'farewell')
        return rc



d = Mydialog()
d.DoModal()

上では、Mydialogのコンストラクタに渡す引数でもってボタンを作成している。
でも以下をOnInitDialogに仕込んでも良い。
(こちらで指定するサイズは(たぶん)ピクセル単位で、一方tmplで指定したサイズはダイアログユニットなので、
大きさに関する数値は異なる。変換はself.MapDialogRectで行える。)
self.btn = win32ui.CreateButton()
self.btn.CreateWindow('my button', self.btnstyle, (10, 75, 340, 140), self, self.IDC_MYBUTTON)



上の例で、ダイアログのフォントを変え、タイマーを仕込んだ例が以下。
from pywin.mfc import dialog
import win32con

class Mydialog(dialog.Dialog):

    dlgstyle = (win32con.WS_MINIMIZEBOX | win32con.WS_DLGFRAME |
                win32con.DS_MODALFRAME | win32con.WS_POPUP | win32con.WS_VISIBLE |
                win32con.WS_CAPTION | win32con.WS_SYSMENU | win32con.DS_SETFONT )
    btnstyle = (win32con.BS_PUSHBUTTON | win32con.WS_TABSTOP |
                win32con.WS_CHILD | win32con.WS_VISIBLE)
    staticstyle = (win32con.WS_CHILD | win32con.WS_VISIBLE | win32con.SS_LEFT)
    IDC_MYBUTTON = 1025
    IDC_MYSTATIC = 1026
    dlgButton = 0x0080
    dlgStatic = 0x0082
    tmpl = [
        ["my dialog", (0, 0, 200, 130), dlgstyle, None, (14,'Arial')], # dialog
        [dlgButton, "my OK",     win32con.IDOK, (5,  5, 190, 40), btnstyle], # button
        [dlgButton, "my button", IDC_MYBUTTON,  (5, 55, 190, 40), btnstyle], # button
        [dlgStatic, "my static", IDC_MYSTATIC,  (5,105, 190, 20), staticstyle], # static
        ]
    timerid = 1
    def __init__(self):
        dialog.Dialog.__init__(self, self.tmpl)
        
    def OnInitDialog(self):
        rc = dialog.Dialog.OnInitDialog(self)
        self.HookCommand(self.OnMyButton, self.IDC_MYBUTTON)
        self.static = self.GetDlgItem(self.IDC_MYSTATIC)
        self.timerflag = False
        self.timercount = 0
        return rc

    def OnMyButton(self, id, cmd):
        if cmd==win32con.BN_CLICKED:
            if self.timerflag: self.KillTimer(self.timerid)
            else: self.SetTimer(self.timerid, 500) # 0.5s
            self.timerflag = not self.timerflag

    def OnTimer(self, nIDEvent):
        self.timercount += 1
        self.static.SetWindowText('timer! %d' % self.timercount)

        
    def OnOK(self):
        rc = dialog.Dialog.OnOK(self)
        self.MessageBox('OnOK!', 'farewell')
        return rc

    def OnCancel(self):
        rc = dialog.Dialog.OnCancel(self)
        self.MessageBox('OnCancel!', 'farewell')
        return rc



d = Mydialog()
d.DoModal()


上記はpywin32に付属のsliderdemo.pyが基なので、致命的な間違いは無いと思うし、実際手元ではちゃんと動いている。
ここまでくれば、後はMFCの知識だけでグリグリ書き進められそう。

Referrer (Inside): [2008-08-17-1]
Referrer (Inside): [2008-06-09-2]

2008-06-06 Fri

外部のCGI実行結果やHTMLの出力(オブジェクト)をHTMLに埋め込む [HTML]

imgタグではsrcにURLを指定できるので、各地に離散する画像リソースを1つのHTMLファイルでまとめて表示できる。
同様なことが、CGIの実行結果やHTML出力に対してもできないか?と思い調べた。

できるようである。
IFRAME を使わない方法の補足

iframeかobjectタグを使えばできる。
前者は(X)HTML的には原則使わないべきタグなので、後者の使用が望ましそう。
後者にはIEでうまく表示できないという認識があるようだが、width及びheight属性の指定によりIEでもちゃんと表示できることを上記「IFRAME を使わない方法の補足」から学んだ。
というわけで実際には以下のように記述すれば良いのだろう。

<object data="hoge.py?msg=fuga" type="text/plain" width="200" height="200">
here an object tag exists
</object>
Firefox2.0.0.14とIE6で、hoge.pyなるCGIの表示を確認できた。 w3m/0.5.1では代替文字列"here an object tag exists"が表示された。

その他参考:
IFRAMEを使わずにHTMLファイルから他のHTMLファイルを読み込む方法
インラインフレームを使わずにCGIを呼び出す!

2008-06-05 Thu

簡易入力ダイアログ [PyWin32][python][Windowsプログラミング]

pythonでCOMを使うためPython for Windows extensions (see also: Mark Hammond's Free Stuff)を導入した。他の機能にも触れてみようとしている。mfcまわりもラップされているのでGUIアプリケーションも書けるようだ。windowsに特化するなら、MFCへの慣れを勘案すれば、wxPythonよりこっちを使う方がラクかな?

とりあえず簡易な入力ダイアログが非常に簡単に作成できるようなのでメモ。後々重宝しそうな気がする。

import pywin.mfc.dialog
print pywin.mfc.dialog.GetSimpleInput("my textbox title", 'my default value', 'my window title')

2010 : 01 02 03 04 05 06 07 08 09 10 11 12
2009 : 01 02 03 04 05 06 07 08 09 10 11 12
2008 : 01 02 03 04 05 06 07 08 09 10 11 12
2007 : 01 02 03 04 05 06 07 08 09 10 11 12
2006 : 01 02 03 04 05 06 07 08 09 10 11 12

最終更新時間: 2010-03-08 22:21