Win32 API 日本語リファレンス
ホームUI.WindowsAndMessaging › SetWindowsHookExA

SetWindowsHookExA

関数
フックチェーンにフックプロシージャをインストールする(ANSI版)。
DLLUSER32.dll文字セットANSI (-A)呼出規約winapiSetLastErrorあり対応OSWindows 2000 以降

シグネチャ

// USER32.dll  (ANSI / -A)
#include <windows.h>

HHOOK SetWindowsHookExA(
    WINDOWS_HOOK_ID idHook,
    HOOKPROC lpfn,
    HINSTANCE hmod,   // optional
    DWORD dwThreadId
);

パラメーター

名前方向説明
idHookWINDOWS_HOOK_IDin

インストールするフック プロシージャの種類。このパラメーターには、次のいずれかの値を指定できます。

意味
WH_CALLWNDPROC
4

システムがメッセージを宛先のウィンドウ プロシージャに送信する前に、そのメッセージを監視するフック プロシージャをインストールします。詳細については、CallWndProc フック プロシージャを参照してください。

WH_CALLWNDPROCRET
12

メッセージが宛先のウィンドウ プロシージャによって処理された後に、そのメッセージを監視するフック プロシージャをインストールします。詳細については、HOOKPROC callback function フック プロシージャを参照してください。

WH_CBT
5

CBT アプリケーションに有用な通知を受け取るフック プロシージャをインストールします。詳細については、CBTProc フック プロシージャを参照してください。

WH_DEBUG
9

他のフック プロシージャをデバッグするのに有用なフック プロシージャをインストールします。詳細については、DebugProc フック プロシージャを参照してください。

WH_FOREGROUNDIDLE
11

アプリケーションのフォアグラウンド スレッドがアイドル状態になる直前に呼び出されるフック プロシージャをインストールします。このフックは、アイドル時間中に優先度の低いタスクを実行するのに有用です。詳細については、ForegroundIdleProc フック プロシージャを参照してください。

WH_GETMESSAGE
3

メッセージ キューにポストされたメッセージを監視するフック プロシージャをインストールします。詳細については、GetMsgProc フック プロシージャを参照してください。

WH_JOURNALPLAYBACK
1
警告

Windows 11 以降: ジャーナリング フック API はサポートされていません。代わりに SendInput TextInput API を使用することをお勧めします。

WH_JOURNALRECORD フック プロシージャによって以前に記録されたメッセージをポストするフック プロシージャをインストールします。詳細については、JournalPlaybackProc フック プロシージャを参照してください。

WH_JOURNALRECORD
0
警告

Windows 11 以降: ジャーナリング フック API はサポートされていません。代わりに SendInput TextInput API を使用することをお勧めします。

システム メッセージ キューにポストされた入力メッセージを記録するフック プロシージャをインストールします。このフックはマクロの記録に有用です。詳細については、JournalRecordProc フック プロシージャを参照してください。

WH_KEYBOARD
2

キーストローク メッセージを監視するフック プロシージャをインストールします。詳細については、KeyboardProc フック プロシージャを参照してください。

WH_KEYBOARD_LL
13

低レベルのキーボード入力イベントを監視するフック プロシージャをインストールします。詳細については、LowLevelKeyboardProc フック プロシージャを参照してください。

WH_MOUSE
7

マウス メッセージを監視するフック プロシージャをインストールします。詳細については、MouseProc フック プロシージャを参照してください。

WH_MOUSE_LL
14

低レベルのマウス入力イベントを監視するフック プロシージャをインストールします。詳細については、LowLevelMouseProc フック プロシージャを参照してください。

WH_MSGFILTER
-1

ダイアログ ボックス、メッセージ ボックス、メニュー、またはスクロール バー内の入力イベントの結果として生成されたメッセージを監視するフック プロシージャをインストールします。詳細については、MessageProc フック プロシージャを参照してください。

WH_SHELL
10

シェル アプリケーションに有用な通知を受け取るフック プロシージャをインストールします。詳細については、ShellProc フック プロシージャを参照してください。

WH_SYSMSGFILTER
6

ダイアログ ボックス、メッセージ ボックス、メニュー、またはスクロール バー内の入力イベントの結果として生成されたメッセージを監視するフック プロシージャをインストールします。このフック プロシージャは、呼び出し元スレッドと同じデスクトップ上のすべてのアプリケーションについて、これらのメッセージを監視します。詳細については、SysMsgProc フック プロシージャを参照してください。

lpfnHOOKPROCinフック プロシージャへのポインター。dwThreadId パラメーターが 0 であるか、別のプロセスによって作成されたスレッドの識別子を指定する場合、lpfn パラメーターは DLL 内のフック プロシージャを指している必要があります。それ以外の場合、lpfn は現在のプロセスに関連付けられたコード内のフック プロシージャを指すことができます。
hmodHINSTANCEinoptionallpfn パラメーターが指すフック プロシージャを含む DLL へのハンドル。dwThreadId パラメーターが現在のプロセスによって作成されたスレッドを指定し、かつフック プロシージャが現在のプロセスに関連付けられたコード内にある場合、hMod パラメーターは NULL に設定する必要があります。
dwThreadIdDWORDinフック プロシージャを関連付けるスレッドの識別子。デスクトップ アプリの場合、このパラメーターが 0 であれば、フック プロシージャは呼び出し元スレッドと同じデスクトップ上で実行されている既存のすべてのスレッドに関連付けられます。Windows ストア アプリについては、「解説」セクションを参照してください。

戻り値の型: HHOOK

公式ドキュメント

アプリケーション定義のフック プロシージャをフック チェーンにインストールします。(ANSI)

戻り値

型: HHOOK

関数が成功した場合、戻り値はフック プロシージャへのハンドルです。

関数が失敗した場合、戻り値は NULL です。拡張エラー情報を取得するには、GetLastError を呼び出します。

解説(Remarks)

SetWindowsHookEx は、DLL を別のプロセスに注入するために使用できます。32 ビット DLL を 64 ビット プロセスに注入することはできず、64 ビット DLL を 32 ビット プロセスに注入することもできません。アプリケーションが他のプロセスでフックを使用する必要がある場合、32 ビット アプリケーションが SetWindowsHookEx を呼び出して 32 ビット DLL を 32 ビット プロセスに注入し、64 ビット アプリケーションが SetWindowsHookEx を呼び出して 64 ビット DLL を 64 ビット プロセスに注入する必要があります。32 ビット DLL と 64 ビット DLL には異なる名前を付ける必要があります。

フックはアプリケーションのコンテキスト内で実行されるため、アプリケーションの「ビット数 (bitness)」に一致している必要があります。32 ビット アプリケーションが 64 ビット Windows 上でグローバル フックをインストールすると、その 32 ビット フックは各 32 ビット プロセスに注入されます (通常のセキュリティ境界が適用されます)。64 ビット プロセスでは、スレッドは引き続き「フックされている」とマークされます。ただし、32 ビット アプリケーションがフック コードを実行する必要があるため、システムはフックを行うアプリのコンテキスト、具体的には SetWindowsHookEx を呼び出したスレッド上でフックを実行します。つまり、フックを行うアプリケーションはメッセージのポンプを継続する必要があり、そうしないと 64 ビット プロセスの通常の機能をブロックする可能性があります。

64 ビット アプリケーションが 64 ビット Windows 上でグローバル フックをインストールすると、その 64 ビット フックは各 64 ビット プロセスに注入され、一方すべての 32 ビット プロセスはフックを行うアプリケーションへのコールバックを使用します。

64 ビット Windows のインストール環境のデスクトップ上のすべてのアプリケーションをフックするには、適切なプロセスから 32 ビットのグローバル フックと 64 ビットのグローバル フックをそれぞれインストールし、通常の機能のブロックを避けるために、フックを行うアプリケーションでメッセージのポンプを継続するようにしてください。既に 32 ビットのグローバル フック アプリケーションがあり、それが各アプリケーションのコンテキストで実行される必要がない場合は、64 ビット版を作成する必要はないかもしれません。

hMod パラメーターが NULL で、かつ dwThreadId パラメーターが 0 であるか、別のプロセスによって作成されたスレッドの識別子を指定する場合、エラーが発生することがあります。

次のフック プロシージャにチェーンするために CallNextHookEx function 関数を呼び出すことは任意ですが、強く推奨されます。そうしないと、フックをインストールした他のアプリケーションがフック通知を受け取れなくなり、その結果として正しく動作しなくなる可能性があります。他のアプリケーションに通知が見られないようにすることがどうしても必要な場合を除き、CallNextHookEx を呼び出すべきです。

アプリケーションは終了する前に、UnhookWindowsHookEx function 関数を呼び出して、フックに関連付けられたシステム リソースを解放する必要があります。

フックのスコープはフックの種類によって異なります。一部のフックはグローバル スコープでのみ設定できますが、他のフックは次の表に示すように特定のスレッドに対してのみ設定することもできます。

フック スコープ
WH_CALLWNDPROC スレッドまたはグローバル
WH_CALLWNDPROCRET スレッドまたはグローバル
WH_CBT スレッドまたはグローバル
WH_DEBUG スレッドまたはグローバル
WH_FOREGROUNDIDLE スレッドまたはグローバル
WH_GETMESSAGE スレッドまたはグローバル
WH_JOURNALPLAYBACK グローバルのみ
WH_JOURNALRECORD グローバルのみ
WH_KEYBOARD スレッドまたはグローバル
WH_KEYBOARD_LL グローバルのみ
WH_MOUSE スレッドまたはグローバル
WH_MOUSE_LL グローバルのみ
WH_MSGFILTER スレッドまたはグローバル
WH_SHELL スレッドまたはグローバル
WH_SYSMSGFILTER グローバルのみ

指定されたフックの種類について、まずスレッド フックが呼び出され、次にグローバル フックが呼び出されます。WH_MOUSEWH_KEYBOARD、WH_JOURNAL*、WH_SHELL、および低レベル フックは、フックを処理するスレッドではなく、フックをインストールしたスレッド上で呼び出される場合があることに注意してください。これらのフックでは、フック チェーン内で 32 ビット フックが 64 ビット フックよりも前にある場合、32 ビット フックと 64 ビット フックの両方が呼び出される可能性があります。

グローバル フックは共有リソースであり、1 つをインストールすると、呼び出し元スレッドと同じデスクトップ上のすべてのアプリケーションに影響します。すべてのグローバル フック関数はライブラリ内にある必要があります。グローバル フックは、特殊な用途のアプリケーション、またはアプリケーションのデバッグ中の開発補助としての使用に限定すべきです。フックが不要になったライブラリは、そのフック プロシージャを削除すべきです。

Windows ストア アプリ開発 dwThreadId が 0 の場合、UIAccess プロセス (アクセシビリティ ツール) によってインストールされる場合を除き、Windows ストア アプリ プロセスおよび Windows ランタイム ブローカー プロセスでは、ウィンドウ フック DLL はインプロセスで読み込まれません。次のフックでは、通知はインストーラーのスレッド上で配信されます。

この動作は、フック DLL とターゲット アプリケーション プロセスとの間にアーキテクチャの不一致がある場合、たとえばフック DLL が 32 ビットでアプリケーション プロセスが 64 ビットである場合に起こることと似ています。

例については、Installing and Releasing Hook Procedures を参照してください。

メモ

winuser.h ヘッダーは SetWindowsHookEx を、UNICODE プリプロセッサ定数の定義に基づいてこの関数の ANSI 版または Unicode 版を自動的に選択するエイリアスとして定義しています。エンコーディング ニュートラルなエイリアスの使用を、エンコーディング ニュートラルでないコードと混在させると、コンパイル エラーまたは実行時エラーを引き起こす不一致につながる可能性があります。詳細については、Conventions for Function Prototypes を参照してください。

出典・ライセンス: 上記「公式ドキュメント」の内容は Microsoft の Win32 API ドキュメント(MicrosoftDocs/sdk-api)を日本語に翻訳・改変したものです。© Microsoft Corporation. CC BY 4.0 で提供。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)

各言語での呼び出し定義

// USER32.dll  (ANSI / -A)
#include <windows.h>

HHOOK SetWindowsHookExA(
    WINDOWS_HOOK_ID idHook,
    HOOKPROC lpfn,
    HINSTANCE hmod,   // optional
    DWORD dwThreadId
);
[DllImport("USER32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
static extern IntPtr SetWindowsHookExA(
    int idHook,   // WINDOWS_HOOK_ID
    IntPtr lpfn,   // HOOKPROC
    IntPtr hmod,   // HINSTANCE optional
    uint dwThreadId   // DWORD
);
<DllImport("USER32.dll", CharSet:=CharSet.Ansi, SetLastError:=True, ExactSpelling:=True)>
Public Shared Function SetWindowsHookExA(
    idHook As Integer,   ' WINDOWS_HOOK_ID
    lpfn As IntPtr,   ' HOOKPROC
    hmod As IntPtr,   ' HINSTANCE optional
    dwThreadId As UInteger   ' DWORD
) As IntPtr
End Function
' idHook : WINDOWS_HOOK_ID
' lpfn : HOOKPROC
' hmod : HINSTANCE optional
' dwThreadId : DWORD
Declare PtrSafe Function SetWindowsHookExA Lib "user32" ( _
    ByVal idHook As Long, _
    ByVal lpfn As LongPtr, _
    ByVal hmod As LongPtr, _
    ByVal dwThreadId As Long) As LongPtr
' VBA7前提(PtrSafe)。32bit Office では LongPtr→Long。Integer=16bit / Long=32bit / LongLong=64bit。
import ctypes
from ctypes import wintypes

SetWindowsHookExA = ctypes.windll.user32.SetWindowsHookExA
SetWindowsHookExA.restype = ctypes.c_void_p
SetWindowsHookExA.argtypes = [
    ctypes.c_int,  # idHook : WINDOWS_HOOK_ID
    ctypes.c_void_p,  # lpfn : HOOKPROC
    wintypes.HANDLE,  # hmod : HINSTANCE optional
    wintypes.DWORD,  # dwThreadId : DWORD
]
# GetLastError: use ctypes.GetLastError() (or ctypes.WinDLL(use_last_error=True))
require 'fiddle'
require 'fiddle/import'

lib = Fiddle.dlopen('USER32.dll')
SetWindowsHookExA = Fiddle::Function.new(
  lib['SetWindowsHookExA'],
  [
    Fiddle::TYPE_INT,  # idHook : WINDOWS_HOOK_ID
    Fiddle::TYPE_VOIDP,  # lpfn : HOOKPROC
    Fiddle::TYPE_VOIDP,  # hmod : HINSTANCE optional
    -Fiddle::TYPE_INT,  # dwThreadId : DWORD
  ],
  Fiddle::TYPE_VOIDP)
#[link(name = "user32")]
extern "system" {
    fn SetWindowsHookExA(
        idHook: i32,  // WINDOWS_HOOK_ID
        lpfn: *const core::ffi::c_void,  // HOOKPROC
        hmod: *mut core::ffi::c_void,  // HINSTANCE optional
        dwThreadId: u32  // DWORD
    ) -> *mut core::ffi::c_void;
}
// crates: windows-sys provides ready-made bindings for this API.
$sig = @"
[DllImport("USER32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
public static extern IntPtr SetWindowsHookExA(int idHook, IntPtr lpfn, IntPtr hmod, uint dwThreadId);
"@
$api = Add-Type -MemberDefinition $sig -Name 'USER32_SetWindowsHookExA' -Namespace Win32 -PassThru
# $api::SetWindowsHookExA(idHook, lpfn, hmod, dwThreadId)
#uselib "USER32.dll"
#func global SetWindowsHookExA "SetWindowsHookExA" sptr, sptr, sptr, sptr
; SetWindowsHookExA idHook, lpfn, hmod, dwThreadId   ; 戻り値は stat
; idHook : WINDOWS_HOOK_ID -> "sptr"
; lpfn : HOOKPROC -> "sptr"
; hmod : HINSTANCE optional -> "sptr"
; dwThreadId : DWORD -> "sptr"
; ※HSP3.7は #func のため戻り値はシステム変数 stat に格納されます。
#uselib "USER32.dll"
#cfunc global SetWindowsHookExA "SetWindowsHookExA" int, sptr, sptr, int
; res = SetWindowsHookExA(idHook, lpfn, hmod, dwThreadId)
; idHook : WINDOWS_HOOK_ID -> "int"
; lpfn : HOOKPROC -> "sptr"
; hmod : HINSTANCE optional -> "sptr"
; dwThreadId : DWORD -> "int"
; HHOOK SetWindowsHookExA(WINDOWS_HOOK_ID idHook, HOOKPROC lpfn, HINSTANCE hmod, DWORD dwThreadId)
#uselib "USER32.dll"
#cfunc global SetWindowsHookExA "SetWindowsHookExA" int, intptr, intptr, int
; res = SetWindowsHookExA(idHook, lpfn, hmod, dwThreadId)
; idHook : WINDOWS_HOOK_ID -> "int"
; lpfn : HOOKPROC -> "intptr"
; hmod : HINSTANCE optional -> "intptr"
; dwThreadId : DWORD -> "int"
import (
	"golang.org/x/sys/windows"
	"unsafe"
)

var (
	user32 = windows.NewLazySystemDLL("USER32.dll")
	procSetWindowsHookExA = user32.NewProc("SetWindowsHookExA")
)

// idHook (WINDOWS_HOOK_ID), lpfn (HOOKPROC), hmod (HINSTANCE optional), dwThreadId (DWORD)
r1, _, err := procSetWindowsHookExA.Call(
	uintptr(idHook),
	uintptr(lpfn),
	uintptr(hmod),
	uintptr(dwThreadId),
)
_ = err  // syscall.Errno (valid when the call sets last-error)
_ = r1   // HHOOK
function SetWindowsHookExA(
  idHook: Integer;   // WINDOWS_HOOK_ID
  lpfn: Pointer;   // HOOKPROC
  hmod: THandle;   // HINSTANCE optional
  dwThreadId: DWORD   // DWORD
): THandle; stdcall;
  external 'USER32.dll' name 'SetWindowsHookExA';
result := DllCall("USER32\SetWindowsHookExA"
    , "Int", idHook   ; WINDOWS_HOOK_ID
    , "Ptr", lpfn   ; HOOKPROC
    , "Ptr", hmod   ; HINSTANCE optional
    , "UInt", dwThreadId   ; DWORD
    , "Ptr")   ; return: HHOOK
●SetWindowsHookExA(idHook, lpfn, hmod, dwThreadId) = DLL("USER32.dll", "void* SetWindowsHookExA(int, void*, void*, dword)")
# 呼び出し: SetWindowsHookExA(idHook, lpfn, hmod, dwThreadId)
# idHook : WINDOWS_HOOK_ID -> "int"
# lpfn : HOOKPROC -> "void*"
# hmod : HINSTANCE optional -> "void*"
# dwThreadId : DWORD -> "dword"
# なでしこ1は32bit・ANSI(Shift_JIS)。文字列=char*(ANSI)、ポインタ/ハンドル=void*(4byte)。
const std = @import("std");

extern "user32" fn SetWindowsHookExA(
    idHook: i32, // WINDOWS_HOOK_ID
    lpfn: ?*anyopaque, // HOOKPROC
    hmod: ?*anyopaque, // HINSTANCE optional
    dwThreadId: u32 // DWORD
) callconv(std.os.windows.WINAPI) ?*anyopaque;
proc SetWindowsHookExA(
    idHook: int32,  # WINDOWS_HOOK_ID
    lpfn: pointer,  # HOOKPROC
    hmod: pointer,  # HINSTANCE optional
    dwThreadId: uint32  # DWORD
): pointer {.importc: "SetWindowsHookExA", stdcall, dynlib: "USER32.dll".}
pragma(lib, "user32");
extern(Windows)
void* SetWindowsHookExA(
    int idHook,   // WINDOWS_HOOK_ID
    void* lpfn,   // HOOKPROC
    void* hmod,   // HINSTANCE optional
    uint dwThreadId   // DWORD
);
ccall((:SetWindowsHookExA, "USER32.dll"), stdcall, Ptr{Cvoid},
      (Int32, Ptr{Cvoid}, Ptr{Cvoid}, UInt32),
      idHook, lpfn, hmod, dwThreadId)
# idHook : WINDOWS_HOOK_ID -> Int32
# lpfn : HOOKPROC -> Ptr{Cvoid}
# hmod : HINSTANCE optional -> Ptr{Cvoid}
# dwThreadId : DWORD -> UInt32
# stdcall は 32bit のみ意味を持つ(x64 では無視)。
local ffi = require("ffi")
ffi.cdef[[
void* SetWindowsHookExA(
    int32_t idHook,
    void* lpfn,
    void* hmod,
    uint32_t dwThreadId);
]]
local user32 = ffi.load("user32")
-- user32.SetWindowsHookExA(idHook, lpfn, hmod, dwThreadId)
-- idHook : WINDOWS_HOOK_ID
-- lpfn : HOOKPROC
-- hmod : HINSTANCE optional
-- dwThreadId : DWORD
-- 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
const koffi = require('koffi');
const lib = koffi.load('USER32.dll');
const SetWindowsHookExA = lib.func('__stdcall', 'SetWindowsHookExA', 'void *', ['int32_t', 'void *', 'void *', 'uint32_t']);
// SetWindowsHookExA(idHook, lpfn, hmod, dwThreadId)
// idHook : WINDOWS_HOOK_ID -> 'int32_t'
// lpfn : HOOKPROC -> 'void *'
// hmod : HINSTANCE optional -> 'void *'
// dwThreadId : DWORD -> 'uint32_t'
// 出力ポインタは koffi.out(...) で包む。構造体は koffi.struct で定義。
// コールバック(関数ポインタ)は koffi.proto/koffi.register で型を定義して渡す(素の void* では JS 関数を渡せない)。
const lib = Deno.dlopen("USER32.dll", {
  SetWindowsHookExA: { parameters: ["i32", "pointer", "pointer", "u32"], result: "pointer" },
});
// lib.symbols.SetWindowsHookExA(idHook, lpfn, hmod, dwThreadId)
// idHook : WINDOWS_HOOK_ID -> "i32"
// lpfn : HOOKPROC -> "pointer"
// hmod : HINSTANCE optional -> "pointer"
// dwThreadId : DWORD -> "u32"
// 文字列は "buffer"。ANSI(-A) は new TextEncoder() で UTF-8/ANSI バイト列(末尾に \x00)を渡す。
// 値渡し構造体は { struct: [ ...field types... ] } を使用。
<?php
$ffi = FFI::cdef(<<<C
void* SetWindowsHookExA(
    int32_t idHook,
    void* lpfn,
    void* hmod,
    uint32_t dwThreadId);
C, "USER32.dll");
// $ffi->SetWindowsHookExA(idHook, lpfn, hmod, dwThreadId);
// idHook : WINDOWS_HOOK_ID
// lpfn : HOOKPROC
// hmod : HINSTANCE optional
// dwThreadId : DWORD
// 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
// WINAPI(stdcall): x64 では呼出規約が統一されるため問題なし。x86 では __stdcall 対応のラッパが必要な場合あり。
import com.sun.jna.*;
import com.sun.jna.ptr.*;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIOptions;

public interface User32 extends StdCallLibrary {
    User32 INSTANCE = Native.load("user32", User32.class, W32APIOptions.ASCII_OPTIONS);
    Pointer SetWindowsHookExA(
        int idHook,   // WINDOWS_HOOK_ID
        Callback lpfn,   // HOOKPROC
        Pointer hmod,   // HINSTANCE optional
        int dwThreadId   // DWORD
    );
}
@[Link("user32")]
lib LibUSER32
  fun SetWindowsHookExA = SetWindowsHookExA(
    idHook : Int32,   # WINDOWS_HOOK_ID
    lpfn : Void*,   # HOOKPROC
    hmod : Void*,   # HINSTANCE optional
    dwThreadId : UInt32   # DWORD
  ) : Void*
end
# 構造体/GUID/enum は lib 内に対応する型定義が必要。
# 呼出規約: x64 は規約統一のため OK。x86(32bit)は WINAPI=stdcall だが Crystal の fun に stdcall 付与構文がなく非対応。
import 'dart:ffi';
import 'package:ffi/ffi.dart';

typedef SetWindowsHookExANative = Pointer<Void> Function(Int32, Pointer<Void>, Pointer<Void>, Uint32);
typedef SetWindowsHookExADart = Pointer<Void> Function(int, Pointer<Void>, Pointer<Void>, int);
final SetWindowsHookExA = DynamicLibrary.open('USER32.dll')
    .lookupFunction<SetWindowsHookExANative, SetWindowsHookExADart>('SetWindowsHookExA');
// idHook : WINDOWS_HOOK_ID -> Int32
// lpfn : HOOKPROC -> Pointer<Void>
// hmod : HINSTANCE optional -> Pointer<Void>
// dwThreadId : DWORD -> Uint32
// 文字列は package:ffi の "...".toNativeUtf16()/toNativeUtf8() で変換。
{$mode objfpc}{$H+}
function SetWindowsHookExA(
  idHook: Integer;   // WINDOWS_HOOK_ID
  lpfn: Pointer;   // HOOKPROC
  hmod: THandle;   // HINSTANCE optional
  dwThreadId: DWORD   // DWORD
): THandle; stdcall;
  external 'USER32.dll' name 'SetWindowsHookExA';
import Foreign
import Foreign.C.Types
import Foreign.C.String

foreign import stdcall safe "SetWindowsHookExA"
  c_SetWindowsHookExA :: Int32 -> Ptr () -> Ptr () -> Word32 -> IO (Ptr ())
-- idHook : WINDOWS_HOOK_ID -> Int32
-- lpfn : HOOKPROC -> Ptr ()
-- hmod : HINSTANCE optional -> Ptr ()
-- dwThreadId : DWORD -> Word32
-- 要 GHC(Windows)。stdcall は x64 では ccall として扱われる。ブロックする API は safe 呼び出し推奨。
open Ctypes
open Foreign

let setwindowshookexa =
  foreign "SetWindowsHookExA"
    (int32_t @-> (ptr void) @-> (ptr void) @-> uint32_t @-> returning (ptr void))
(* idHook : WINDOWS_HOOK_ID -> int32_t *)
(* lpfn : HOOKPROC -> (ptr void) *)
(* hmod : HINSTANCE optional -> (ptr void) *)
(* dwThreadId : DWORD -> uint32_t *)
(* foreign は cdecl 前提。x64 Windows では WINAPI と一致。構造体は ctypes structure を定義のこと。 *)
(cffi:define-foreign-library user32 (t "USER32.dll"))
(cffi:use-foreign-library user32)

(cffi:defcfun ("SetWindowsHookExA" set-windows-hook-ex-a :convention :stdcall) :pointer
  (id-hook :int32)   ; WINDOWS_HOOK_ID
  (lpfn :pointer)   ; HOOKPROC
  (hmod :pointer)   ; HINSTANCE optional
  (dw-thread-id :uint32))   ; DWORD
; isize/usize(INT_PTR/SIZE_T)は x64 前提で :int64/:uint64。x86 では :int32/:uint32。
use Win32::API;
my $SetWindowsHookExA = Win32::API::More->new('USER32',
    'HANDLE SetWindowsHookExA(int idHook, LPVOID lpfn, HANDLE hmod, DWORD dwThreadId)');
# my $ret = $SetWindowsHookExA->Call($idHook, $lpfn, $hmod, $dwThreadId);
# idHook : WINDOWS_HOOK_ID -> int
# lpfn : HOOKPROC -> LPVOID
# hmod : HINSTANCE optional -> HANDLE
# dwThreadId : DWORD -> DWORD
# 値渡し構造体は pack() した文字列、または Win32::API::Struct を使用。
# コールバック(関数ポインタ)は Perl sub を直接渡せません。Win32::API::Callback を使用してください。

関連項目

文字セット違い
類似 API
使用する型