首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

MFC 鍵盤鉤子 LNK2019 錯誤:靜態回調函式定義與宣告不符

     編輯:程式設計綜合問答

錯誤訊息

error LNK2019: 無法解析的外部符號 "public: static long __stdcall CMFCApplication2Dlg::JournalRecordProc(...)

原因

**.cpp 定義時保留了 static 關鍵字**,導致函式具有**內部連結**,類別外部 (如 SetWindowsHookEx) 無法取得其位址;且類別宣告為 static 成員函式,定義需加上類別作用域 CMFCApplication2Dlg:: 且**不加 static**。

錯誤與正確定義對照

// ❌ 錯誤:.cpp 中
static LRESULT CALLBACK JournalRecordProc(int nCode, WPARAM wparam, LPARAM lparam) { ... }

// ✅ 正確:.cpp 中
LRESULT CALLBACK CMFCApplication2Dlg::JournalRecordProc(int nCode, WPARAM wparam, LPARAM lparam) {
    // 實作...
}

// ✅ 正確:.h 中宣告
class CMFCApplication2Dlg : public CDialogEx {
    // ...
    static LRESULT CALLBACK JournalRecordProc(int nCode, WPARAM wparam, LPARAM lparam);
    static LRESULT CALLBACK JournalPlaybackProc(int nCode, WPARAM wparam, LPARAM lparam);
};

完整修正程式碼片段

// CMFCApplication2Dlg.h
class CMFCApplication2Dlg : public CDialogEx {
    // ...
    static LRESULT CALLBACK JournalRecordProc(int nCode, WPARAM wparam, LPARAM lparam);
    static LRESULT CALLBACK JournalPlaybackProc(int nCode, WPARAM wparam, LPARAM lparam);
    HHOOK hHook;
    CList EventMsgList;
};

// CMFCApplication2Dlg.cpp
LRESULT CALLBACK CMFCApplication2Dlg::JournalRecordProc(int nCode, WPARAM wparam, LPARAM lparam) {
    if (nCode < 0) return CallNextHookEx(NULL, nCode, wparam, lparam);
    EVENTMSG* pmsg = (EVENTMSG*)lparam;
    switch (nCode) {
        case HC_ACTION: {
            EVENTMSG* pEventMsg = new EVENTMSG;
            memcpy(pEventMsg, pmsg, sizeof(EVENTMSG));
            // 需取得 dlg 實例存取 EventMsgList,可用全域指標或 Thread Local Storage
            // 此處略過實際存取邏輯
        } break;
        // ...
    }
    return CallNextHookEx(NULL, nCode, wparam, lparam);
}

LRESULT CALLBACK CMFCApplication2Dlg::JournalPlaybackProc(int nCode, WPARAM wparam, LPARAM lparam) {
    // 類似實作...
}

void CMFCApplication2Dlg::OnBnClickedButton3() {
    hHook = SetWindowsHookEx(WH_JOURNALRECORD,
        JournalRecordProc, // 直接用函式名稱,編譯器解析為 &CMFCApplication2Dlg::JournalRecordProc
        AfxGetApp()->m_hInstance, 0);
}

void CMFCApplication2Dlg::OnBnClickedButton1() {
    hHook = SetWindowsHookEx(WH_JOURNALPLAYBACK,
        JournalPlaybackProc,
        AfxGetApp()->m_hInstance, 0);
}

關鍵補充

  • JournalRecordProc 為 **靜態成員函式**,無 this 指標,若需存取對話方塊成員 (如 EventMsgList),需透過**全域/靜態指標**指向當前對話方塊實例,或使用 TlsSetValue 存儲實例指標。
  • 鉤子程序**必須在 DLL 中** (全域鉤子) 才能注入其他進程;若僅監控本進程,WH_JOURNALRECORD 為全域鉤子,**必須放在 DLL**,否則僅對當前執行緒有效。上述代碼僅供演示連結修正,**實際全域鉤子需建立獨立 DLL 專案**。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved