SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

デスクトップ上のウィンドウをグリッドに沿って合わせるユーティリティ

デスクトップユーティリティ作成のヒント


  • X ポスト
  • このエントリーをはてなブックマークに追加

Delphiで共有変数ユニットの作成

 次に、これを元にして、DelphiでDLLを作ってみます。Delphi IDEのメニューの[ファイル]-[新規作成]から[DLL]を選択してプロジェクトを作成します。ここでは、「mhook.dpr」という名前で保存します。

 それから、簡単に変数を共有するためのユニットを作ります(IDEのメニューの[ファイル]-[新規作成]-[ユニット]をクリックします)。このユニットは「unit_share.pas」という名前で保存します。

 ユニットの内容は次のとおりです。

共有データを作るためのユニット「unit_share.pas」
unit unit_share;

interface

uses
  Windows, Messages, SysUtils;

const
  MMF_NAME = 'mhook_share_data';

type
  // 共有したいデータの構造体を定義
  PShareData = ^TShareData;
  TShareData = record
    hParent : THandle;
    hHook   : THandle;
  end;

var
  ShareData: PShareData = nil; // 共有データへのポインタ

implementation

var
  hCreate: THandle; // メモリマップドファイルのハンドル

procedure BeginShareData;
var
  bAlreadyExists: Boolean;
begin
  // 共有メモリ(メモリマップドファイル)を作成
  hCreate := CreateFileMapping($ffffffff, nil, PAGE_READWRITE
            or SEC_COMMIT, 0, SizeOf(TShareData), MMF_NAME);
  bAlreadyExists := (hCreate <> 0) and
    (GetLastError = ERROR_ALREADY_EXISTS);

  // メモリにマップする
  ShareData := MapViewOfFile(hCreate, FILE_MAP_ALL_ACCESS, 0, 0, 0);

  // 共有変数の初期化
  if not bAlreadyExists then
  begin
    ShareData^.hParent := 0;
    ShareData^.hHook   := 0;
  end;
end;

procedure EndShareData;
begin
  if ShareData <> nil then UnmapViewOfFile(ShareData);
  if hCreate <> 0 then CloseHandle(hCreate);
end;

initialization
  BeginShareData;

finalization
  EndShareData;

end.

 ユニットを初期化・破棄する「initialization」を定義し、DLLが読み込まれると強制的に共有メモリが作成されるという仕組みにしています。Visual C++なら、ほんの数行宣言を加えるとできるのですが、Delphi だとこのようなユニットを作らなければなりません。ですが、一度作ってしまえば、これを少し変えるだけで共有変数を実現できます。

フックDLLの作成

 そして、肝心のフックを行うDLLのメインプログラムは次のように作ります。こちらはC言語のプログラムと大して変わりません。

フックDLL
library mhook;

uses
  Windows, Messages, SysUtils,
  unit_share in 'unit_share.pas';

const
  WM_USER_MOUSE_ACTION = WM_USER + $1001;
// フック関数
function HookProc(code: Integer; wp:WPalram; lp:LPalram):
    LRESULT; stdcall;
var
  pms: PMouseHookStruct;
begin
  pms := PMouseHookStruct(lp);
  PostMessage(ShareData^.hParent, WM_USER_MOUSE_ACTION,
    wp, pms^.wHitTestCode);
  Result := CallNextHookEx(ShareData^.hHook, code, wp, lp);
end;
// フックをインストールする関数
function HookInstall(Parent:THandle): BOOL; stdcall;
begin
  if (ShareData = nil)or(Parent = 0) then begin Result
    := False; Exit; end;
  ShareData^.hParent := Parent;
  ShareData^.hHook   := SetWindowsHookEx(WH_MOUSE,
    @HookProc, HInstance, 0);
  Result := (ShareData^.hHook > 0);
end;
// フックをアンインストールする関数
function HookUninstall: BOOL; stdcall;
begin
  Result := True;
  if ShareData^.hHook <> 0 then
  begin
    UnhookWindowsHookEx(ShareData^.hHook);
    ShareData^.hHook := 0;
  end;
end;
// エクスポートする関数の一覧
exports
  HookInstall,
  HookUninstall;

begin
end.

 ここで、もう一度フック関数を見てみます。

フック関数
function HookProc(code: Integer; wp:WPalram; lp:LParam):
  LRESULT; stdcall;
var
  pms: PMouseHookStruct;
begin
  pms := PMouseHookStruct(lp);
  PostMessage(ShareData^.hParent, WM_USER_MOUSE_ACTION, wp,
    pms^.wHitTestCode);
  Result := CallNextHookEx(ShareData^.hHook, code, wp, lp);
end;

 はじめに作ったプログラムと違うところは、メッセージを親ウィンドウに投げる際の引数です。WPalamには、ウィンドウメッセージの種類を、LParamには、PMouseHookStruct.wHitTestCodeを指定しています。

 ここを直接PMouseHookStructへのポインタを指定して投げると、親ウィンドウがメッセージを受け取り、データを参照する頃には、PMouseHookStructの内容が破棄されているためメモリのアクセス違反が起きてしまいます。そこで、必要なデータだけを投げるようにしています。

 PMouseHookStructのメンバであるwHitTestCodeは、どの領域をクリックしたかという情報が入っています。マウスでフォームをリサイズしたかどうかを判別するために必要になります。

次のページ
親アプリケーションの作成

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
特集記事連載記事一覧

もっと読む

この記事の著者

クジラ飛行机(クジラヒコウヅクエ)

ソフト企画「くじらはんど」にて、多数のフリーソフトを公開しています。日本語プログラミング言語「なでしこ」、テキスト音楽「サクラ」、日本語Wiki記法が特徴の「KonaWiki」などを公開しています。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/369 2007/12/10 13:50

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング