2012-09-29 65 views
2

我有一類這樣的通行證方法

class Keyboard 
{ 
public: 
    Keyboard(void); 
    ~Keyboard(void); 
    void SetHook(HINSTANCE hInstance); 
    LRESULT CALLBACK keyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam); 
}; 


LRESULT CALLBACK Keyboard::keyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam) 
{ 
    bool bControlKeyDown=0; 
    bool caps = GetKeyState(VK_CAPITAL) < 0; 

... 

void Keyboard::SetHook(HINSTANCE hInstance) 
{ 
    KeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, Keyboard::keyboardHookProc, hInstance, NULL); 
} 

但聲明

KeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, Keyboard::keyboardHookProc, hInstance, NULL); 

結果在編譯錯誤

Error 7 error C3867: 'Keyboard::keyboardHookProc': function call missing argument list; use '&Keyboard::keyboardHookProc' to create a pointer to member 

如果我更改爲「&鍵盤:: keyboardHookProc'它也錯誤,當我投到'(HOOKPROC)& Keyboard :: k eyboardHookProc」還錯誤

請人幫忙

回答

2

這是C-回調常見的錯誤。

Keyboard::keyboardHookProc必須是靜態的。

[更新]

,如果你想在static Keyboard::keyboardHookProcKeyboard對象操作你必須找到一些其他的方式來獲得Keyboard對象這個靜態方法。如果您有一個Keyboard,則可以使用singleton模式。如果不是,則每個靜態方法都必須具有其自己的Keyboard對象。

[UPDATE2]

一個具有全局功能鏈接對象的方式是通過模板對象引用。但是這項工作只適用於全局對象:

class Keyboard 
{ 
public: 
    Keyboard(); 
    ~Keyboard(void); 
    LRESULT keyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam); 
}; 

LRESULT Keyboard::keyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam) 
{ 
} 
// global function interface 
template <Keyboard& k> 
LRESULT CALLBACK keyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam) 
{ 
    return k.keyboardHookProc(nCode, wParam, lParam); 
} 


Keyboard k; // global keyboard 

int main() 
{ 
    // this works 
    SetWindowsHookEx(0, keyboardHookProc<k>, NULL, NULL); 
} 
+0

不能從普通方法傳遞迴調方法而不是靜態方法嗎?有什麼理由嗎? –

+2

「非靜態」成員有一個隱含的「this」參數,因爲這種或那種方式必須知道要操作哪個對象,而C回調根本不準備處理這個問題。另外,「成員函數指針」可能有點複雜,就像使用多重繼承時一樣。 –

+0

要調用成員方法,需要一個對象代表這個對象調用這個方法:'(object。* normalMethod)(args)'。沒有對象調用這個方法是不可能的。對於靜態方法,不需要任何對象 - 它們更像普通的C函數,這些函數原本就是在這裏預期的。 – PiotrNycz