VC++6.0
Windows XP
プロジェクトをダイアログ形式で作成し、
コンパイルすると以下のエラーが発生します。
関数、変数等は正しく宣言されているかと思います。
何か原因の分かるようでしたら、ご教授願いたいと思います。
以下、エラー内容・ソースを記載します。
宜しくお願い致します。
-------------------------------------------------------
SetWinEventHookDemo2Dlg.obj : error LNK2001: 外部シンボル ""private: static void (__stdcall CSetWinEventHookDemo2Dlg::* CWinEvent<class CSetWinEventHookDemo2Dlg>::m_pfnCallback)(unsigned long,unsigned long,struct HWND__ *,long,long,unsigned long,unsign
ed long)" (?m_pfnCallback@?$CWinEvent@VCSetWinEventHookDemo2Dlg@@@@0P8CSetWinEventHookDemo2Dlg@@AGXKKPAUHWND__@@JJKK@ZQ2@)" は未解決です
SetWinEventHookDemo2Dlg.obj : error LNK2001: 外部シンボル ""private: static class CSetWinEventHookDemo2Dlg * CWinEvent<class CSetWinEventHookDemo2Dlg>::m_pT" (?m_pT@?$CWinEvent@VCSetWinEventHookDemo2Dlg@@@@0PAVCSetWinEventHookDemo2Dlg@@A)" は未解決です
Debug/SetWinEventHookDemo2.exe : fatal error LNK1120: 外部参照 2 が未解決です。
-----------------------------------------------------------
winevent.h
#include <winable.h>
template <typename T>
class CWinEvent
{
public:
typedef VOID ( CALLBACK T::*PFNCALLBACK )( HWINEVENTHOOK, DWORD, HWND, LONG, LONG, DWORD, DWORD );
static HWINEVENTHOOK InstallWinEventHook( T * pT,
PFNCALLBACK pfn,
UINT eventMin,
UINT eventMax,
HMODULE hModWinEventProc,
DWORD idProcess,
DWORD idThread,
UINT dwFlags );
private:
static T * m_pT;
static PFNCALLBACK m_pfnCallback;
private:
CWinEvent( void ) {};
~CWinEvent( void ) {};
static VOID CALLBACK WinEventProc( HWINEVENTHOOK hWinEventHook,
DWORD event,
HWND hwnd,
LONG idObject,
LONG idChild,
DWORD dwEventThread,
DWORD dwmsEventTime );
};
template <typename T>
HWINEVENTHOOK CWinEvent<T>::InstallWinEventHook( T * pT,
PFNCALLBACK pfn,
UINT eventMin,
UINT eventMax,
HMODULE hModWinEventProc,
DWORD idProcess,
DWORD idThread,
UINT dwFlags )
{
m_pT = pT;
m_pfnCallback = pfn;
return SetWinEventHook( eventMin,
eventMax,
hModWinEventProc,
WinEventProc,
idProcess,
idThread,
dwFlags );
}
template <typename T>
VOID CALLBACK CWinEvent<T>::WinEventProc( HWINEVENTHOOK hWinEventHook,
DWORD event,
HWND hwnd,
LONG idObject,
LONG idChild,
DWORD dwEventThread,
DWORD dwmsEventTime )
{
( m_pT->*m_pfnCallback )( hWinEventHook,
event,
hwnd,
idObject,
idChild,
dwEventThread,
dwmsEventTime );
}
----------------------------------------
SetWinEventHookDemo2Dlg.h
#include "winevent.h"
class CSetWinEventHookDemo2Dlg : public CDialog
{
// 構築
public:
CSetWinEventHookDemo2Dlg(CWnd* pParent = NULL); // 標準のコンストラクタ
// ダイアログ データ
//{{AFX_DATA(CSetWinEventHookDemo2Dlg)
enum { IDD = IDD_SETWINEVENTHOOKDEMO2_DIALOG };
// メモ: この位置に ClassWizard によってデータ メンバが追加されます。
//}}AFX_DATA
// ClassWizard は仮想関数のオーバーライドを生成します。
//{{AFX_VIRTUAL(CSetWinEventHookDemo2Dlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV のサポート
//}}AFX_VIRTUAL
// インプリメンテーション
private:
VOID CALLBACK WinEventProc( HWINEVENTHOOK hWinEventHook,
DWORD event,
HWND hwnd,
LONG idObject,
LONG idChild,
DWORD dwEventThread,
DWORD dwmsEventTime );
protected:
HICON m_hIcon;
HWINEVENTHOOK m_hWinEventHook;
// 生成されたメッセージ マップ関数
//{{AFX_MSG(CSetWinEventHookDemo2Dlg)
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
------------------------------------------------------------
SetWinEventHookDemo2Dlg.cpp
BOOL CSetWinEventHookDemo2Dlg::OnInitDialog()
{
CDialog::OnInitDialog();
// このダイアログ用のアイコンを設定します。フレームワークはアプリケーションのメイン
// ウィンドウがダイアログでない時は自動的に設定しません。
SetIcon(m_hIcon, TRUE); // 大きいアイコンを設定
SetIcon(m_hIcon, FALSE); // 小さいアイコンを設定
//
m_hWinEventHook = CWinEvent<CSetWinEventHookDemo2Dlg>::InstallWinEventHook( this,
WinEventProc,
EVENT_SYSTEM_FOREGROUND,
EVENT_SYSTEM_FOREGROUND,
NULL,
0,
0,
WINEVENT_OUTOFCONTEXT );
return TRUE; // TRUE を返すとコントロールに設定したフォーカスは失われません。
}
VOID CALLBACK CSetWinEventHookDemo2Dlg::WinEventProc( HWINEVENTHOOK hWinEventHook,
DWORD event,
HWND hwnd,
LONG idObject,
LONG idChild,
DWORD dwEventThread,
DWORD dwmsEventTime )
{
TRACE( _T( "コールバック" ) );
}
エラー・メッセージ"そのまんま"じゃないんですか?
m_pfnCallback と m_pT が未定義なんでしょうね。
確かにコード上には定義してるとこが見当たりませんね。
もうちょい補足しますと、クラスの静的メンバ変数は「宣言」とは別に、クラス宣言の外に「定義」が必要です。
> private:
> static T * m_pT;
> static PFNCALLBACK m_pfnCallback;
こいつらは「宣言」です。
別に「定義」を用意するというのは、例えば、
class Hoge
{
static int value; // これは宣言
};
int Hoge::value; // これが定義
みたいなのが必要ってことです。
テンプレートの場合、どこにどう書くかは、ちょいと頭をひねってみてください。
επιστημη様、aetos様ご回答ありがとうございます。
static変数の宣言が抜けていました。
ありがとうございました。
ツイート | ![]() |