2008-11-15

Java 6 も Update 10 か...。

JView(MSJava)との互換性を気にしていた頃が夢のようだ。

2008-10-12

Folder Lock(R)の試用期間が切れた

35日経って、フォルダのロックができなくなった(もちろん、過去にロックしたフォルダの解除は可能)。
仕方ないのでアンインストール。
使えるソフトだったんだがなあぁ。

2008-09-27

古いWin32APIで取得していたCPU使用率が変になった

Win9x向けに自作したパフォーマンスモニタ(chkperf.exe)を久々にWindowsXPで起動してみたら、CPU利用率の表示が変だ。タスクマネージャの表示が0%の時に、65%とか表示される。Win98/ME互換モードにしても、1%で止まったままになる。
pdh.dllを使うとか、新しいやり方じゃないともう駄目なんだろーなー、と思いつつ、今更手を掛ける時間も無いので、そのままにしておく。

2008-09-05

Folder Lock(R)入れてみた

今使っているWindowsパソコンに、Webメールのバックアップ用のフォルダがあって、このフォルダに鍵を掛けたくなった。
フォルダにパスワードを付けるという意味では、Windows XPの暗号化機能があるのだけれど、あくまでもフォルダに一時的な鍵を掛けられれば良く、データの暗号化までやってしまうのはありがた迷惑だった。

ちょっとGoogleで検索してみたところ、Folder Lock®が良いらしいということで、無料版をダウンロードして入れてみた。
ソフトを起動すると、金庫(ロッカー?)のようなメイン画面が現れる。入力ボックスにパスワードを入れると、脇の鍵穴に"鍵を掛ける"アニメーションが表示される。後は、Folder Lock®の用意したフォルダにロックしたいファイル・フォルダを入れて操作するか、メイン画面の"Browse"リンクからフォルダを選択してロックを掛けることが出来る。
英語だけれど、やることが明確なUIで使いやすい。画面の主だった選択項目は3~4個程度なので分かりやすく(それでも慣れないUIなので最初は迷ったが)、操作の大きな区切りの間に気の利いたTipsが入る。
最近は開発者向けのコマンドラインツールばかり触ってたので、こういったUIがやたら新鮮に感じられた。

FAQに開発体制について書いてあった。
Q74. How many programmers and designers have made this software?
3 hard-working programmers and 2 highly-skilled designers.
素晴らしい。

2008-08-31

jrunscriptでGUIスクリプトを起動してみて気づいたこと

  1. jrunscriptのバッチモード(-fオプション)でAWTやSwingのウィンドウを表示するスクリプトファイルを起動した場合、ウィンドウが一瞬だけ表示されて終了してしまう。
  2. スクリプトの最後にjava.lang.Thread.currentThread().sleep(1000);を付け足すと、スレッドを待機させている間はウィンドウが表示された。
  3. どうやらスクリプトを処理するメインスレッドが、スクリプトを読み終えた時点で(GUIのスレッドが生きていても)exitしているように見える。
  4. そこで、wait-notifyの組合せを使って、ウィンドウがクローズされるまでメインスレッドを待機させることを思い付いた。
  5. Rhinoで同期処理を上手くやる方法はあったっけ?
  6. "バッチモード"という位なので、これはこれで正しいのかもしれない、と勝手に自分を納得させる。
  7. あえなく完。
  8. Rhino組み込みのsync関数に気付き、sync(function() {this.wait();})の返す同期化された関数を使ってみる。
  9. wait関数が見つからないとか言われた...。確かにtypeof this.waitはundefinedだった。
  10. やっぱり完。
  11. スクリプトの最後に while (frame.isDisplayable()) {java.lang.Thread.currentThread().sleep(1000);} を付けたところ、GUI側でウィンドウクローズ時にちゃんとdispose()してれば想定通りに動く。
  12. 何か納得いかないものの完。
ちなみに、対話モードでload('GUIスクリプトファイル名');を使うなら問題なし。

イベントアダプタをJava Scripting EngineのJavaScriptで真似する

Java1.6付属のRhinoでJavaインタフェースを実装する場合、以下のように書ける(jrunscriptで実行)。
js> var runner = new java.lang.Runnable() { run: function() { print(this); }};
js> new java.lang.Thread(runner).start();
js> [object Object]
問題は、GUIのイベントリスナを書こうとした場合、使いもしないメソッドまで記述することになるので面倒くさい。
Javaで実装する場合はアダプタクラスがあるのだけれど、アダプタクラスはインタフェースではなく抽象クラスなので、下記のようなスクリプトは通らない。
// 変数frameにはjava.awt.Frameが入っているものとする
frame.addWindowListener(new java.awt.event.WindowAdapter() {
    windowClosing: function(evt) {
        java.lang.System.exit(0);
    }
});
// 上記構文はインタフェース用なので、抽象クラスに適用できない
以下のスクリプトは一応通るものの、実装しないでおいたイベントハンドラが後で呼ばれると、java.lang.NoSuchMethodExceptionが発生する。
frame.addWindowListener(new java.awt.event.WindowListener() {
    windowClosing: function(evt) {
        java.lang.System.exit(0);
    }
});
// この後、frameを表示するとwindowActivatedやwindowOpenedが未実装なので例外が発生する
そこで、必要なイベントハンドラの連想配列を渡すとWindowListener(を実装したクラスのインスタンス)を作成して返す関数を書いてみた。イベントハンドラごとにベタベタ似たような処理を書いている箇所がもっとスマートにならないものか...。
// 渡された連想配列からWindowListenerを作成する関数
function createWindowListener(tbl) {
    function ignoreEvent(evt) {}
    function getValue(value, defaultValue) { return value ? value : defaultValue; }
    return new java.awt.event.WindowListener() {
        windowActivated: getValue(tbl['windowActivated'], ignoreEvent),
        windowClosed: getValue(tbl['windowClosed'], ignoreEvent),
        windowClosing: getValue(tbl['windowClosing'], ignoreEvent),
        windowDeactivated: getValue(tbl['windowDeactivated'], ignoreEvent),
        windowDeiconified: getValue(tbl['windowDeiconified'], ignoreEvent),
        windowGainedFocus: getValue(tbl['windowGainedFocus'], ignoreEvent),
        windowIconified: getValue(tbl['windowIconified'], ignoreEvent),
        windowLostFocus: getValue(tbl['windowLostFocus'], ignoreEvent),
        windowOpened: getValue(tbl['windowOpened'], ignoreEvent),
        windowStateChanged: getValue(tbl['windowStateChanged'], ignoreEvent)
    };
}

// 使ってみる(ウィンドウが表示されて、閉じるボタンを押すと終了する)
// jrunscriptから実行する場合は、load関数で読み込ませないと一瞬で終了する
var frame = new java.awt.Frame("Test Frame");
var panel = new java.awt.Panel();
panel.setPreferredSize(new java.awt.Dimension(320, 240));
frame.add(panel);
var handlers = { windowClosing: function(evt) {
    var window = evt.getSource();
    window.setVisible(false);
    window.dispose();
    //java.lang.System.exit(0); 最近のJVMでは不要になったらしい
} };
frame.addWindowListener(createWindowListener(handlers));
frame.pack();
frame.setVisible(true);

2008-08-23

LCC-Win32が自由にダウンロードできた頃

私がまだコマンドラインで何かすることさえ思いもよらないプログラミング初心者だった頃、LCC-Win32が手元にある唯一のグラフィカルな統合開発環境だった。
プログラミングに必要なツールが一通り揃っているのはもちろん、C言語チュートリアルやWin32SDKのヘルプ(これらは単独でも役に立つ)、それに、LCC-Win32でビルドできるサンプルソースを公開しているWebサイトもあるので、(ちょっと英語が読めれば)初心者でも手元に何も無い状態から始められるという点で画期的だった。
特にC言語チュートリアルは素晴らしかった。そこには開発者であるJacob Navia氏の意見があり、C言語や"昨日今日の言語"、メモリ管理と自動ガーベジコレクタに関する(今では古いかもしれない)熱い主張を見ることができた。当時の私が難解なWin32向けC言語プログラミングを続けられたのは、このチュートリアルが与えてくれた情熱のお陰なのだと、今でも思っている。
一方で当時ちょっと不安に感じたのは、「LCC-Win32で作ったソフトウェアを売って良いか」について、なぜかライセンス条項に明確な記述がなかったことだった(作ったソフトウェアの"著作権"が作成者にある、という記述はあったはず)。
私が自作したDLLを商用利用も可能な条件でユーザに配布したいと思った時に、どうしてもこの問題が引っ掛かり、あれこれ調べた末、最終的にはMinGWに乗り換えた。
あれから5年以上経った今、LCC-Win32のWebサイトのトップページには「License: 」が加わり、商用利用に関する細かい記述が並ぶ。閲覧者が何かダウンロードしたければ会員登録が必要で、それが無料だとしても、私は何もかも最初から自由にダウンロードできた当時と比べてしまい、どこか違和感を感じる。