鉴于我有一个像这样定义的基类型:
[<AbstractClass>]
type HookBase(hookType: HookId, threadId: int) =
let mutable hHook = IntPtr.Zero
...
member this.SetHook() =
// Set the hook using SetWindowsHookEx(...)
...
hHook <- hhk
member this.Unhook() =
// Remove the hook
hHook <- IntPtr.Zero
和这样的派生类型:
type ForegroundIdleHook(thread: uint32) as this =
inherit HookBase(HookId.WH_FOREGROUNDIDLE, int thread)
let hookCallback nCode wParam lParam =
...
CallNextHookEx((* here has to be the hook's handle *), nCode, wParam, lParam)
...
因为我不希望每个代码都有SetHook()
和Unhook()
代码
类型(最后将有15种钩子类型),我想到使用基本类型。但是F#不支持protected
成员,我现在有问题要在派生类型中获取hHook
并在基类型中设置回调。
我想过使用CallerMemberNameAttribute和预定义的方法来实现这个目标:
// Base type
member this.SetCallback(callback: HookProc, [<CallerMemberName>] ?name: string) =
...
member this.GetHHook([<CallerMemberName>] ?name: string) =
...
// Derived type
do
this.SetCallback(this.Proc)
member private this.Proc = HookProc(hookCallback)
在SetCallback
的情况下,可以建立一个计数器以确保只有一个方法的调用,但是对GetHHook
不起作用,因为可以设置和取消设置挂钩实例中有好几次&#39;寿命。
此外,由于其他被调用者也可以使用与所需方法相同的名称这种方式,这种方式并非愚蠢,我也不想拥有这些方法的公共范围。 除了我的测试之外,似乎该属性不适用于F#,因为必须为参数提供显式默认值。 (我在这里错过了什么吗?)
有没有更好的方法来获取钩子的句柄并设置回调而不是让基本类型具有15次所述方法?
修改:如上所述here,F#不支持CallerMemberName
属性,因此使用它的选项不适用。
答案 0 :(得分:0)
您在派生类型中需要什么句柄?仅适用于CallNextHookEx
?
然后根本不公开它,而是让SetCallback
接受IntPtr -> HookProc
类型的函数:
// Base type
member this.SetCallback(makeCallback: IntPtr -> HookProc) =
let callback = makeCallback hHook
// do whatever you're supposed to do with the callback
// Derived type
let hookCallback handle nCode wParam lParam =
...
CallNextHookEx(handle, nCode, wParam, lParam)
do this.SetCallback(fun handle -> HookProc(hookCallback handle))
必须有更好的设计才能找到,而不仅仅是复制OOP模式,但我并不期待阅读有关Hooks API的信息。