2008年6月アーカイブ

昔のHDDからデータをあさっていたときに過去の遺物を見つけたので次に使うかもしれないときのためにメモ。 Delphiで書いたSpiderMonkeyのサンプルなんてほかに誰が必要としているんだか。

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, jsapi;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormShow(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;


var
  Form1: TForm1;

  global_class: JSClass = (
    name: 'global';
    flags: 0;
    addProperty: JS_PropertyStub;
    delProperty: JS_PropertyStub;
    getProperty: JS_PropertyStub;
    setProperty: JS_PropertyStub;
    enumerate: JS_EnumerateStub;
    resolve: JS_ResolveStub;
    convert: JS_ConvertStub;
    finalize: JS_FinalizeStub
  );
  rt: JSRuntime;
  cx: JSContext;
  global: JSObject;

implementation

{$R *.dfm}

function alertFunc(cx: JSContext; obj: JSObject; argc: JSUintn; argv: PJSValArray; out rval: jsval): JSBool; cdecl;
var
  str: JSString;
  msg: String;
  i: Integer;
  v: jsval;
begin
  for i:=0 to argc-1 do
  begin
    v := argv^[i];
    str := JS_ValueToString(cx, v);
    if i<>0 then
      msg := msg + ' ';
    msg := msg + JS_GetStringBytes(str);
  end;

  ShowMessage(msg);

  Result := True;
end;

var
  funcs: array[0..1] of JSFunctionSpec = (
  (
    name: 'alert';
    call: alertFunc;
  ),
  (
  )
  );

procedure TForm1.FormCreate(Sender: TObject);
begin
  rt := JS_NewRuntime($100000);
  cx := JS_NewContext(rt, $1000);
  global := JS_NewObject(cx, global_class, nil, nil);
  JS_InitStandardClasses(cx, global);
  JS_DefineFunctions(cx, global, PJSFunctionSpecArray(@funcs));
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  //
end;

procedure TForm1.FormShow(Sender: TObject);
var
  rval: jsval;
const
  //script = 'function fact(n){if(n<=1)return 1;else return fact(n-1)*n;} fact(5);';
  script = 'alert("hoge"); alert(1,2,3)';
begin
  JS_EvaluateScript(cx, global, script, length(script), 'filename', 1, rval);
end;

end.

jsapiユニットはjsapi.h等に書かれている関数プロトタイプと構造体の一部を記述したもの。 JS_NewRuntime関数でスクリプト実行環境の初期化をする。引数はメモリ使用量。 JS_NewContext関数はたぶんスレッドの初期化だと思う。 引数はJS_NewRuntimeで作った実行環境とスタックフレームのサイズ。 スタックフレームのサイズが小さいと深いネストでエラーになりやすい。ていうかなった。 JS_NewObjectでクラスの実体を作成し、JS_InitStandardClass関数でクラスとスレッドを関連付ける。 どうもSpiderMonkeyの実装ではグローバル関数やグローバル変数というものは存在せず、グローバルクラス内のメソッドやメンバ変数として扱われるようだ。 で、JS_DefineFunctionsでは実際にグローバルクラスにメソッドを追加している。 今回はalertという関数を追加した。 関数の内容と記述方法はソース見たほうが早いので説明は省略する。 コードの実行はJS_EvaluateScriptで行う。 関数宣言などコードの即時実行を伴わないものは、JS_CompileScriptが使えそうな気がする。

ちなみに終了処理はしていない。 横着な実装だ。

メモ終わり。

Gecko1.9をコンパイルするに当たり開発環境が大きく変わったのでそのメモ。

用意したもの

コンパイラ
Visual C++ 2005
バージョン管理
Mercurial
ライブラリ
Microsoft Windows Vista SDK
Microsoft Windows Server 2003 Platform SDK
その他ツール
MozillaBuild
Visual C++ 8 (Visual C++ 2005 Express) を使用する場合、 ビルドエラーを回避するためのバッチファイル

ソースの取得

hg clone http://hg.mozilla.org/mozilla-central/ src

開発環境の起動

start-msvc8.batを管理者権限でぽちっとな。 ちなみに管理者権限で実行しないとinstallコマンドが正しく実行されない。 まったく困った話だ。

どうでもいいがMozillaBuildの中にcygwinも入るようになったんだな。楽でよろしい。

SetWindowsHookEx関数でマウスをフックし、マウスポインタが指すウィンドウのハンドルを取得するプログラムを書いた際に気がついた事のメモ。

まずWH_MOUSEではフックを開始したスレッドのウィンドウしかフックできない模様。 WH_KEYBOARDも試してはいないが同じ結果になると思う。 少なくともこれだけではポインタが指すウィンドウのハンドルは取得できない。

次にWH_MOUSE_LLを使う方法を試す。 LLはLowLevelの略であり、マウスの動きをウィンドウ単位ではなく画面単位で監視する。 しかし今度は低レベルすぎて、ウィンドウハンドルがコールバック関数のパラメータに含まれない。 これではポインタの指し示すウィンドウのハンドルがわからない。 しかし一方で新たな収穫があった。 この低レベルフックは別にDLLを作らなくても使えるというのがわかった。 Windows2000以降にしか対応していないとのことだが、どうせ世間にはXPとVistaばっかり出回っているので問題ない。

今回のプログラムはVistaで実行したため、Vistaの権限の制限が悪さをした可能性も考え、 ChangeWindowMessageFilterでフィルタを解除する事も試してみたものの、 関係ない事が判明した。 今構想中のプログラムで必要になるかもしれないので、これはこれで記憶の隅にとどめておく事にする。

最終的には、スクリーン座標からウィンドウハンドルが得られる方法を探す事にした。 ClientToScreenScreenToClientはまったく役に立たず、 EnumWindowsはさすがに手間がかかりすぎる。 紆余曲折を経て、WindowFromPosisionというあまりにもそのまますぎる関数を発見した。 この関数と低レベルフックを組み合わせ、マウスポインタの指すウィンドウのハンドルを取得する事に成功した。

以上本日のメモ終わり

参考URL抜粋

上記内容とは別に見つけた面白そうなページ

アーカイブ

ウェブページ

Powered by Movable Type 4.21-ja

このアーカイブについて

このページには、2008年6月に書かれたブログ記事が新しい順に公開されています。

前のアーカイブは2008年5月です。

次のアーカイブは2008年7月です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。