/**
 * @file SystemWin32.h
 * @brief Windowsへのインターフェースです
 *
 * @author S.F.
 * @version $Id:
 *
 * Copyright (C) 2000-2002 Satoshi Fujiwara. All Rights Reserved.
 */

/// 二重インクルード防止マクロ
#if !defined(AFX_SYSTEMWIN32_H__9E630867_3321_4C17_8D1A_E0EAC93A1647__INCLUDED_)
#define AFX_SYSTEMWIN32_H__9E630867_3321_4C17_8D1A_E0EAC93A1647__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "sfinterface.h"
namespace sf {
	namespace system {

/** WindowMessageインターフェース. 
 * Windowメッセージを処理するためのインターフェースです。
 * これは、std::mapと組み合わせて、Windowメッセージを効率的に処理するために定義されています。
 * @note この辺の実装の考え方は、<a href="http://puyon.pns.to/program/afl/h0003.html">ぷよぉんさんのライブラリのページ</a> を参照してください。<br>
 * 若干ぷよぉんさんのライブラリを特化しているぶぶんはあります。*/
class SF_INTERFACE WindowMessage
{
public:
	/// デストラクタ
	virtual ~WindowMessage(){;};
	/** メッセージ処理を行う 
	 * @param hwnd HWND ウィンドウハンドル 
	 * @param wParam WPARAM 
	 * @param lParam LPARAM 
	 * @return LRESULT */
	virtual LRESULT call(const HWND hwnd,const WPARAM wParam,const LPARAM lParam) = 0;
};

/** WindowMessageインターフェースの実装クラス */
template<class T> class WindowMessageImpl : public WindowMessage
{
public:
	/// コンストラクタ
	WindowMessageImpl();
	/// デストラクタ
	virtual ~WindowMessageImpl(){}
	/** コンストラクタ.
     * @param pClass 呼び出したいメソッドを有しているクラスのインスタンスのポインタ
	 * @param pAddress 呼び出したいメンバメソッドのアドレスが入っているポインタ */
	WindowMessageImpl(T* const pClass,LRESULT (T::* pAddress)(const HWND,const WPARAM,const LPARAM));
	
	/** 呼び出したいメソッドの情報をセットする. 
     * @param pClass 呼び出したいメソッドを有しているクラスのインスタンスのポインタ
	 * @param pAddress 呼び出したいメンバメソッドのアドレスが入っているポインタ */
	void setAddress(T* const pClass,LRESULT (T::* pAddress)(const HWND,const WPARAM,const LPARAM));

	LRESULT call(const HWND hwnd,const WPARAM wParam,const LPARAM lParam);
private:
	T* mpClass;///< 呼び出したいメソッドが入っているクラスのインスタンスのポインタ
	LRESULT (T::* mpAddress)(const HWND,const WPARAM,const LPARAM);///< 呼び出したいメンバメソッドのアドレス
};

template<class T> WindowMessageImpl<T>::WindowMessageImpl()
{
	mpClass = NULL;
	mpAddress = NULL;
};

template<class T> WindowMessageImpl<T>::WindowMessageImpl(T* const pClass,LRESULT (T::* pAddress)(const HWND,const WPARAM,const LPARAM))
{
	mpClass = pClass;
	mpAddress = pAddress;
};


template<class T> void WindowMessageImpl<T>::setAddress(T* const pClass,LRESULT (T::* pAddress)(const HWND,const WPARAM,const LPARAM))
{
	mpClass = pClass;
	mpAddress = pAddress;
};

template<class T> LRESULT WindowMessageImpl<T>::call(const HWND hwnd,const WPARAM wParam,const LPARAM lParam)
{
	if(mpClass && mpAddress)
		return (mpClass->*mpAddress)(hwnd,wParam,lParam);
	return 0;
};

/// Win32 インターフェース
class SF_INTERFACE Win32  
{
public:
	/// コンストラクタ
	Win32(){};
	/// デストラクタ
	virtual ~Win32(){};
	
	/// WinMain ラッパー 
	virtual int winMain (const HINSTANCE hThisInstance, const HINSTANCE hPrevInstance,
			const LPSTR lpszCmdParam, const int nCmdShow) = 0;
	
	/** Window Messageの登録 
	 * @param value Windowメッセージ
	 * @param pWindowMessage WindowMessageのポインタ */
	virtual const bool addWindowMessage(const DWORD value,WindowMessage * pWindowMessage) = 0;
	
};
	}
}

#endif // !defined(AFX_SYSTEMWIN32_H__9E630867_3321_4C17_8D1A_E0EAC93A1647__INCLUDED_)
