Win32 API でウィンドウを最前面にする方法

http://technet.microsoft.com/ja-jp/library/cc835597.aspx
によると、

最前面ウィンドウの扱い

概要

今まで作業していたウィンドウの代わりに、バックグラウンドに存在する、あるいはアイコン化しているウィンドウを最前面に表示する。これは、ユーザーに注意を促したり、アプリケーションの画面遷移を制御したりするため行われてきた方法です。しかし、この「ウィンドウを最前面に表示する」という操作は、必ずしもユーザーに便利な方法ではありません。

たとえば、メニューの深い階層をたどっているとき、勝手に他のウィンドウがフォアグランドになってしまうと、メニューは自動的に閉じられてしまいます。これにより、それまでのユーザーの操作が無効になってしまうため、Windows 98Windows 2000から、動作が変更されることになりました。この変更の結果、以下のような条件が適用されます。

*

プロセスがフォアグラウンドプロセスの場合、ウィンドウをフォアグラウンドに表示できます。
*

プロセスがフォアグラウンドプロセスによって開始されたばかりの場合、ウィンドウをフォアグラウンドにできます。
*

プロセス直前の入力を受け付けていた場合は、そのウィンドウをフォアグラウンドにできます。
*

その時点でフォアグラウンドウィンドウがない場合、ウィンドウをフォアグラウンドにできます。
*

フォアグラウンドプロセスのデバッグ中は、任意のウィンドウをフォアグラウンドにできます。
*

フォアグラウンドプロセスでタイムアウトロックが発生した場合 ( フォアグラウンドプロセスがしばらくの間何も行わず、応答していないような場合 ) 、ほかのウィンドウをフォアグラウンドにできます。
*

何らかのシステムメニューがアクティブの場合、アプリケーションはフォアグラウンドにはできません。

これらの条件を満たさないため、オペレーティングシステムが最前面ウィンドウを変更しないときは、代わりにタスクバーのボタンを点滅させます。ユーザーは、これを見て、アプリケーションに「呼ばれている」ことに気づきます。ここで、そのウィンドウを選ぶかどうかは、ユーザーの気持ち次第です。基本的に、最前面ウィンドウを変更できるのはユーザーのみ、ということになります。

テスト方法

Visual Basic であれば、AppActivate() ステートメントによって、この最前面表示を行います。しかし、この方法は、ほとんどの場合ウィンドウタイトルに頼らざるを得ないため、Win32 API の SetForegroundWindow() が使われるケースが多いことでしょう。これらの処理をコードの中で行っていないか確認するとともに、実際にアプリケーションを動作させて検証することになります。

検証する際は、他のアプリケーションで作業しているときや、システムメニューを操作しているときに、最前面ウィンドウの挙動がどうなるかを確認します。Windows XP の仕様どおりの動きとしては、タスクバーのボタンが点滅し、ユーザーへ通知が行われます。

回避方法

これまで見てきたように、この最前面ウィンドウの問題は Windows の仕様変更に起因しています。Windows の流儀にあわせて、最前面ウィンドウの変更は行わない、というのもひとつの考え方でしょう。もし、そういう選択を行うのなら、プログラムを修正する必要はありません。

それでもアプリケーションの要求として最前面ウィンドウを変更したいのであれば、Windows の流儀に反していることをきちんと理解した上で、修正したプログラムコードを実装しなくてはなりません。その方法ですが、いくつか考えられます。最前面ウィンドウ側のアプリケーションを修正できるのであれば、AllowSetForegroundWindow()API を利用して、他のアプリケーションに最前面ウィンドウ変更の許可を与えることができます。

最前面ウィンドウ側のアプリケーションが修正できない、他社製のアプリケーションであるといったときは、 AttachThreadInput()API を利用して、対象のアプリケーションの入力処理機構にアタッチし、その後に SetForegroundWindow() を呼び出すことになります。

サンプルコード - Visual Basic

' 自アプリケーションのスレッドIDを取得する lngTargetThreadID = _ GetWindowThreadProcessId( _ Me.hWnd, _ lngProcessID) ' 最前面アプリケーションのスレッドIDを取得する lngForegroundThreadID = _ GetWindowThreadProcessId( _ GetForegroundWindow(), _ lngProcessID) ' 最前面アプリケーションの入力処理機構に接続する lngResult = _ AttachThreadInput( _ lngTargetThreadID, _ lngForegroundTHreadID, _ 1) ' 最前面ウィンドウを変更する lngResult = _ SetForegroundWindow(Me.hWnd)

サンプルコード - Visual C++

int foregroundID; // 最前面プロセスのスレッドIDを取得する foregroundID = ::GetWindowThreadProcessId( ::GetForegroundWindow(), NULL); // 最前面アプリケーションの入力処理機構に接続する AttachThreadInput( ::GetCurrentThreadId(), foregroundID, TRUE); // 最前面ウィンドウを変更する ::SetForegroundWindow(this->m_hWnd);

だそうです。へええ。

get and use GLIBCXX_3.4.9

thanks to
http://mrs.suzu841.com/tebiki/libreo/

get LIBREOFFICE
LibO_3.3.2_Linux_x86_install-rpm_en-US.tar.gz

then search by bash:

# for i in `ls `
> do
> echo ----------------------------- $i
> rpm -qlp $i
> echo
> done | less

found libreoffice3-ure-1.7.0-202.i586.rpm

so
# rpm2cpio libreoffice3-ure-1.7.0-202.i586.rpm | cpio -id
then found the so file in
/opt/libreoffice/ure/lib
check for sure
# strings libstdc++.so.6 | grep GLIBCXX
shows the specific version.

then locate it by 755 to a proper location (on LDLIBRARYPATH?)

DocBook 環境を整える

HTML と PDF の両方に変換可能な形式を探していた。MS Word は HTML が汚いし、latex も微妙。エディタは WYSIWYG がいい。

DocBook は XML ベースで、必要なものが無償ソフトでそろうようなので、これにすることにした。
DocBook エディタは XMLmind の無償版。
DocBook からの変換には XMLMind xslutil を用いる。日本語ドキュメントが必要なので、PDF に埋め込む TTF フォントが必要。
Windows からはメイリオを BreakTTC なるソフトで TTF に変換して使う。64bit では動かなかったので XPMode を導入し仮想環境で変換。Open Type のものもほしかったので、FontForge なるソフトで TTF に変換。

これでうまくいきそうだが、どうなのかな?章ごととかに HTML 分割できるとすごいけど、そこまではできないか。

セクション区切り後の無用な空ページを防ぐ

セクション区切りのあとは、奇数ページではじまるということになっているらしく、偶数だとそうなるように空ページが挿入されるようです。

これをふせぐには、セクション区切り後のページ番号を奇数ページで始まるようにした上で、実際に表示されるページ番号は +1 するなどして調整する。