/*! @mainpage Read me / Download

@par mqsdxって？
@par
	mqsdkをC++またはCLI(.Net)拡張するサポートライブラリで、ソースコードの詰め合わせとして公開されています。

@par
	mqsdxは以下の二つの名前空間を含んでおり、MQ0x単体またはMQ0x+MQCLIとしてご利用いただけます。
@par
	- <b>MQ0x</b><br/>C++サポートライブラリ
		- @subpage MQ0xの使い方
		- @subpage MQ0xの一覧 "モジュール＞MQ0xの一覧 (リファレンス)"
		.
	.
@par
	- <b>MQCLI</b><br/>CLI(.Net)サポートライブラリ
		- @subpage MQCLIの使い方
		- @subpage MQCLIの一覧 "モジュール＞MQCLIの一覧 (リファレンス)"
		.
	.
@par
	<b>対応するメタセコイアおよびプラグインSDKバージョン、開発環境について</b>
@par
	- メタセコイア 3.0.5〜
	- プラグインSDK mqsdk300〜
	- 開発環境 Microsoft Visual C++ 2010<br/>
	.
@par
導入する時は、MQ0x.hppの冒頭に書かれた各ヘッダファイルがインクルードできるようにパスを通しておいて下さい（とくにMQPlugin.hなどmqsdkのヘッダファイル）。
追加のヘッダパスを通すのは、VisualC++でプロジェクトのプロパティから設定できます。
テストプロジェクトのビルドについては @subpage 付属のテストプロジェクトをビルドするには を参照して下さい。
@par
@details
<hr/>
@par ライセンス
	このライブラリは、現在のところLGPLライセンスVer3で配布されています。 

@par mqsdxの入手先
<a href="http://sourceforge.jp/users/tiritomato/pf/mqsdx/">mqsdx (SourceForge)</a>

@par サポート・問い合わせ先
公式サイトなどはありませんので、お手数ですが、以下いずれかまでご連絡ください。
1. ツイッターアカウント(<a href="http://twitter.com/#!/tiri_tomato">tiri_tomato</a>)
2. SourceForgeメールアドレス: tiritomato@users.sourceforge.jp <br/>（お手数ですが表題に [mqsdx問い合わせ] と記入していただけると幸いです）
3. <a href="http://d.hatena.ne.jp/tiri_tomato/">チリペヂィア(ブログ)</a>に適当にコメント
.
@attention <small>mqsdx作者は、メタセコおよびメタセコのプラグインSDK（以下本家）作者様とは別人です（間違えないとは思いますが、一応…）。また、mqsdxはユーザーが勝手に作るmqsdkのお気楽なラッパーライブラリにすぎません。くれぐれも本家作者様にmqsdxの技術的問い合わせなどはされないようお願いいたします。もし本家に迷惑がかかるならmqsdxの公開は速やかに停止いたします。</small>

@page 付属のテストプロジェクトをビルドするには
@par 付属のテストプロジェクトをビルドするには
@note （テストプロジェクト自体はそんなに大したコードでもなくオマケ程度のものなので、この項目はほとんど無視してもmqsdxは問題なく使えます）
@details 基本的にmqsdxから見たmqsdkの配置については、パスさえ通っていて、対応するcppがプロジェクトに含まれていればビルドが通ります。
一方テストプロジェクトについては、プロジェクト側に「mqsdkの配置はコレ！」と設定してしまったので、
ビルドするにはmqsdx/mqsdkフォルダ直下にmqsdkに含まれる以下のファイルを展開する必要があります（標準ではmqsdx/mqsdkフォルダは空のフォルダになっています）。
- MQ3DLib.cpp
- MQ3DLib.h
- MQBasePlugin.cpp
- MQBasePlugin.h
- MQInit.cpp
- MQPlugin.cpp
- MQPlugin.h
- MQSetting.cpp
- MQSetting.h
.

@page MQ0xの使い方

@par MQ0xのインストール
	@par 1.ソリューションを変換する
		@par
		MQSDKをダウンロードしてきて、VC2010でソリューション(*.sln)を開くと2010形式に変換されます。
		なおいくつかの子プロジェクトは2010ビルドンパイルに失敗するようなので、深く考えずソリューションから削除してしまいます。
		@par
	@par 2.MQ0xをプロジェクトに追加
		@par
		フォルダ"mqsdx"配下のファイルをすべてそのままプロジェクトフォルダにコピーして、mqsdx内の各ファイルをプロジェクトに追加して下さい。
		@par
		mqsdxを使用するソースコードで"mqsdx/MQ0x.hpp"をインクルードして下さい。
		@code
		#include "mqsdx/MQ0x.hpp"
		@endcode
		もしmqsdxだけを使用するなら、付属のMQCLIのファイルはコピーする必要はありませんが一緒にコピーしてしまって構いません。
		MQCLIの有効／無効はVisualStudioのプロジェクト設定（CLR有効／無効）で自動的に判別されます。
		@par
	@par

@par MQ0xの使い道

MQ0xの目玉としてPluginBaseテンプレートクラスがあります。このクラスはコンストラクタで製造者名、プラグイン名、表示名を指定する事で以下の実装を自動化します。
- GetPlugInID()
- GetPlugInName()
- EnumString()
- MQSetting::Open()およびClose()
.

@code
PluginBase<MQCommandPlugin> plugin("tiritomato", "SamplePlugin Copyright(C) 2013, tiritomato.", "SamplePlugin");
{
	SettingProxy setting( plugin.Setting );
	setting.Load(...);
	setting.Save(...);
	setting.Close(); // このClose()はSettingProxyのデストラクタに任せる事も出来ます。
}
@endcode

ID決定の自動化には文字列のハッシュコードが採用されています。このハッシュコードは典型的に
「ハッシュコード = ハッシュコード * (入力型(文字列の場合char型)ビットサイズ-1) ^ 配列要素」
という計算を配列要素の個数だけ繰り返すロジックが採用されています。
このテンプレートクラスで最終的にラップするのか、このテンプレートクラスをベースクラスにして継承して拡張するのかは自由です。

またMQ0xはこの他にも、オブジェクト検索など基本的な拡張機能を提供します。

@par リファレンス

- @subpage MQ0xの一覧 "モジュール＞MQ0xの一覧"

*/

/*!
@defgroup MQ0xの一覧
MQ0xの公開する機能の一覧です。
@par
- @ref MQ0xの使い方
@{
	@defgroup MQ0x-Math名前空間
数値計算のためのライブラリ。名前空間MathはMQ0xでusing宣言されているので省略可能です。
@code
double truncated = MQ0x::trunc(1.2);
@endcode
	@{
	@}
	@defgroup MQ0x-Polygon名前空間
	@{
	@}
@}
*/

/*!	@page MQCLIの使い方

@par MQCLIのインストール
	@par 1.ソリューションを変換する
		@par
		MQSDKをダウンロードしてきて、VC2010でソリューション(*.sln)を開くと2010形式に変換されます。
		なおいくつかの子プロジェクトは2010ビルドに失敗するようなので、深く考えずソリューションから削除してしまいます。
		@par
	@par 2.CLIを有効にする
		@par
		MQCLIを有効にするには、プロジェクトの共通言語ランタイム（CLR）オプションを有効にしてビルドして下さい。無効の場合MQCLIのコードはすべて無視されます。
		- [構成プロパティ＞全般＞共通言語ランタイムサポート] 「共通言語ランタイムサポート(/clr)」を選択
		.
		@par
		またこの設定のためにいくつかの追加設定が必要な場合があるようです。
		- [構成プロパティ＞C/C++＞全般＞デバッグ情報の形式] 「C7互換(/Z7)」を選択
		- [構成プロパティ＞C/C++＞コード生成＞基本ランタイムチェック] 「既定」を選択
		- [構成プロパティ＞C/C++＞コード生成＞ランタイムライブラリ] 「マルチスレッドDLL(/MD)」または「マルチスレッドデバッグDLL(/MDd)」を選択
		- [構成プロパティ＞リンカー＞入力＞シンボル参照の強制] 「__DllMainCRTStartup@12」を追記
		- [構成プロパティ＞リンカー＞コマンドライン＞追加オプション] 「/NOENTRY」を追記
	@par 3.mqsdxをプロジェクトに追加
		@par
		フォルダ"mqsdx"配下のファイルをすべてそのままプロジェクトフォルダにコピーして、mqsdx内の各ファイルをプロジェクトに追加して下さい。
		@par
		MQCLIを使用するソースコードで"mqsdx/MQCLI.hpp"をインクルードして下さい。
		@code
		#include "mqsdx/MQCLI.hpp"
		@endcode
		@par
	@par

@par MQCLIを使ったプラグイン開発

MQCLIでは、以下のいずれかのクラスを継承し、カスタマイズするだけでプラグインが作れます。
- MQCLI::StationPlugins::StationPlugin
- MQCLI::CommandPlugins::CommandPlugin

これらはMQStationPluginやMQCommandPluginのラッパークラスです。オーバーライドすべき機能やメソッド名は、もともとのメタセコイアプラグインSDKとほぼ同じなので、オリジナルのヘルプファイルをチェックしてください。
ただひとつだけ相違する注意点があります。一度だけそのプラグインクラスの継承インスタンスを確保し、 MQCLI::Initialize() に渡してください。こんなふうに。

@code
#include "mqsdx/MQCLI.hpp"

public ref class CustomPlugin : MQCLI::CommandPlugin {
public:
	CustomPlugin() : CommandPlugin( "tiritomato", "Sample Copyright(C) 2013, tiritomato.", "SampleButton" ) {}
	virtual BOOL Activate(MQDocument doc, BOOL flag) override {
		if ( flag == TRUE ) ::MessageBox( MQ_GetWindowHandle(), "Activate!", NULL, 0 );
		return flag;
	}
};

static bool initialResult = MQCLI::Initialize( gcnew CustomPlugin() );
@endcode
このサンプルではコマンドプラグインのActivate()メソッドをオーバーライドして、コマンドボタンを選択した時にメッセージボックスを表示します。
プロジェクト設定に問題なければ、この数行のコンパイルは成功し、そのままプラグインDLLのインストールとテストが実行できるはずです。

@attention
@par MQCLIのプラグイン初期化処理の制約

全ての処理の前に必ず一度だけ MQCLI::Initialize() を呼び出す必要があります。そして、おそらくその唯一安全な方法は成否を示す戻り値をグローバル変数にストアする事です。上述のコードで言えばここが重要。
@code
static bool initialResult = MQCLI::Initialize( gcnew CustomPlugin() );
@endcode
@par
	C++/CLIを使ったマネージド／アンマネージド混成DLL開発では、DllMain関数を初期化の中心に考える事は出来ません。
	DllMainが.Netエンジン初期化完了前に、.Netエンジンの初期化に対して排他的な状態で呼び出されるためです。
	このためにDllMain関数からCLIマネージドコード部分の初期化を強行すると処理がロックする危険性があります。
	一方、CLRオプションを有効にしてC++/CLIコードをコンパイルした時、
	マネージドコードを使った大域変数の動的初期化は.Netエンジンの初期化完了後にコンパイラによって自動的に呼び出されます。
	プラグインコンストラクタに初期化が集約されているなら、ロックは回避されます。
	@par DllMain()とGetPluginClass()もMQCLIライブラリによって実装されます
	初期化制約の都合もあり、MQCLIライブラリがDllMain()とGetPluginClass()の実装も行います。
	またMQ0xによってプラグインIDなどのハッシュコード生成も自動実装されます（<b>
	@ref MQ0xの使い方 "MQ0xの使い方＞MQ0xの使い道"
	</b>を参照）。よってプラグインDLLを開発するのに必要な手順は、以下の作業だけです。
	
	- プラグインクラスを継承する。
	- プラグインの初期化処理をクラスコンストラクタに実装する。
	- プラグインクラスをDLL起動後に一回だけ確保・初期化（つまりgcnew）して、 MQCLI::Initialize() に渡す。
	- 必要に応じてカスタム処理をoverrideしていく。
	.

@par リファレンス

- @subpage MQCLIの一覧 "モジュール＞MQCLIの一覧"
- @subpage MQ0xの一覧 "モジュール＞MQ0xの一覧"

MQ0xとMQCLIは共存可能で、MQCLIを使ったプログラミングでも、検索や名前取得などのサポート関数はMQ0xを利用する想定になっています。
*/

/*!
@defgroup MQCLIの一覧
MQCLIの公開する機能の一覧です。
@par
いまのところStationPluginおよびCommandPluginのみ対応しています。
@par
- @ref MQCLIの使い方
@{
	@defgroup インターフェース
	定義は公開されていますが、通常プラグイン開発でこれらのインターフェースを意識する事はありません
	@{
	@}
	@defgroup MQCLI-Drawing名前空間
	@{
	@}
	@defgroup MQCLI-Plugins名前空間
	独自のStationPlugin/CommandPluginを開発するためのベースクラスを提供します。
	@{
	@}
	@defgroup MQCLI-String名前空間
	@{
	@}
@}
*/


/*!
@class MQCLI::Plugins::StationPlugin
@ingroup MQCLI-Plugins名前空間 MQCLIの一覧
@brief StationPluginを作成する時に継承するマネージドベースクラス

MQCLI::StationPluginはMQStationPluginのラッパークラスです。MQStationPlugin同様に、1.継承する／2.カスタム処理をオーバーライドする、という手順でプラグインを作る基底クラスです。
ただしもうひとつ「3.最初に一度だけ MQCLI::Initialize()にインスタンスを生成して渡す」という処理を記述するようにしてください。
@code
#include "mqsdx/MQCLI.hpp"

public ref class CustomPlugin : MQCLI::StationPlugin {
public:
	CustomPlugin() : CommandPlugin( "tiritomato", "Sample Copyright(C) 2013, tiritomato.", "SampleButton" ) {}
	virtual BOOL Activate(MQDocument doc, BOOL flag) override {
		if ( flag == TRUE ) ::MessageBox( MQ_GetWindowHandle(), "Activate!", NULL, 0 );
		return flag;
	}
};

static bool initialResult = MQCLI::Initialize( gcnew CustomPlugin() ); //Initialize!
@endcode
MQCLIライブラリではこの手順だけでプラグインを作る事が可能です（というよりこれ以外の手順では作れません）。
- このサンプルではActivateメソッドをオーバーライドしています。オーバーライドできる機能やメソッド名は、もともとのメタセコイアプラグインSDKとほぼ同じなので、プラグインSDKのヘルプファイルをチェックしてください。
- @ref MQCLIの使い方 "MQCLIの使い方：コンパイルするためのプロジェクト設定／初期化の制約／DllMain()などの行方"

@par MQStationPluginとの相違点

@par 1.MQSettingに代わりSettingProxyを使用します
MQCLI::StationPlugin::Settingプロパティでハンドルを取得してMQ0x::SettingProxyクラスを生成します。

MQ0x::SettingProxyはMQSettingクラスの代行です。コンストラクト時にOpen、デストラクト時にCloseを自動的に実行します。さきほどのActivateメソッド内でSave/Loadするとこんな感じです。
@code
public ref class CustomPlugin : MQCLI::StationPlugin {
public:
	CustomPlugin() : StationPlugin( "tiritomato", "Sample Copyright(C) 2013, tiritomato.", "SampleButton" ) {}
	virtual BOOL Activate(MQDocument doc, BOOL flag) override {
		if ( flag == TRUE ) {
			SettingProxy setting( MQCLI::StationPlugin::Setting );
			setting.Load(...);
			setting.Save(...);
			setting.Close(); // このClose()はSettingProxyのデストラクタに任せる事も出来ます。
			::MessageBox( MQ_GetWindowHandle(), "Activate!", NULL, 0 );
		}
		return TRUE;
	}
};
@endcode

@par 2.いくつかの抽象メソッドの実装が既に代行されています。
MQStationPluginで実装しなければいけなかったいくつかの仮想メソッドの仮実装は既に記述してあります。必要な時だけオーバーライドしてください。

なお下記にリストされる基本的な仮想関数はオーバーライドでカスタムすることはできません。これらの返すべき値は、StationPluginコンストラクタに初期値として設定します。
- GetPlugInID()
- GetPlugInName()
- EnumString()
.

@note
@par 継承構造
	StationPluginsInterfacedBase／ベースクラス。外部から参照されるvirtualメソッド全般の標準実装。
@par
	StationPluginTemplate／protectedメソッドの実装
*/

/*!
@fn MQCLI::Plugins::StationPlugin::StationPlugin( const char* productName, const char* pluginFullName, const char* displayName )
@brief コンストラクタ（プラグインIDを自動生成して初期化）
@param productName 作者名を指定します。設定した値はGetProductName()で取得されます。この文字列のハッシュをProductIDに設定します。
@param pluginFullName プラグイン名を設定します。設定した値はGetPlugInName()で取得されます。この文字列のハッシュをPluginIDに設定します。
@param displayName 表示名を設定します。設定した値はEnumString()で取得されます。
@note ハッシュは@ref MQ0x::CollectionHashCode "MQ0x::CollectionHashCode<DWORD>(const char*)"によって計算されます。
*/

/*!
@fn MQCLI::Plugins::StationPlugin::StationPlugin( const char* productName, const char* pluginFullName, const char* displayName, const DWORD idProduct, const DWORD idPlugin )
@brief コンストラクタ（任意のプラグインIDを指定して初期化）
@param productName 作者名を指定します。設定した値はGetProductName()で取得されます。
@param pluginFullName プラグイン名を設定します。設定した値はGetPlugInName()で取得されます。
@param displayName 表示名を設定します。設定した値はEnumString()で取得されます。
@param idProduct 任意のプロダクトIDを指定します。
@param idPlugin 任意のプラグインIDを指定します。
*/

/*!
@class MQCLI::Plugins::CommandPlugin
@ingroup MQCLI-Plugins名前空間 MQCLIの一覧
@brief CommandPluginを作成する時に継承するマネージドベースクラス

MQCLI::CommandPluginはMQCommandPluginのラッパークラスです。MQCommandPlugin同様に、1.継承する／2.カスタム処理をオーバーライドする、という手順でプラグインを作る基底クラスです。
ただしもうひとつ「3.最初に一度だけ MQCLI::Initialize()にインスタンスを生成して渡す」という処理を記述するようにしてください。
@code
#include "mqsdx/MQCLI.hpp"

public ref class CustomPlugin : MQCLI::CommandPlugin {
public:
	CustomPlugin() : CommandPlugin( "tiritomato", "Sample Copyright(C) 2013, tiritomato.", "SampleButton" ) {}
	virtual BOOL Activate(MQDocument doc, BOOL flag) override {
		if ( flag == TRUE ) ::MessageBox( MQ_GetWindowHandle(), "Activate!", NULL, 0 );
		return flag;
	}
};

static bool initialResult = MQCLI::Initialize( gcnew CustomPlugin() ); // Initialize!
@endcode
MQCLIライブラリではこの手順だけでプラグインを作る事が可能です（というよりこれ以外の手順では作れません）。
- このサンプルではActivateメソッドをオーバーライドしています。オーバーライドできる機能やメソッド名は、もともとのメタセコイアプラグインSDKとほぼ同じなので、プラグインSDKのヘルプファイルをチェックしてください。
- @ref MQCLIの使い方 "MQCLIの使い方：コンパイルするためのプロジェクト設定／初期化の制約／DllMain()などの行方"

@par MQStationPluginとの相違点

@par 1.MQSettingに代わりSettingProxyを使用します
MQCLI::StationPlugin::Settingプロパティでハンドルを取得してMQ0x::SettingProxyクラスを生成します。

MQ0x::SettingProxyはMQSettingクラスの代行です。コンストラクト時にOpen、デストラクト時にCloseを自動的に実行します。さきほどのActivateメソッド内でSave/Loadするとこんな感じです。
@code
public ref class CustomPlugin : MQCLI::CommandPlugin {
public:
	CustomPlugin() : CommandPlugin( "tiritomato", "Sample Copyright(C) 2013, tiritomato.", "SampleButton" ) {}
	virtual BOOL Activate(MQDocument doc, BOOL flag) override {
		if ( flag == TRUE ) {
			SettingProxy setting( MQCLI::StationPlugin::Setting );
			setting.Load(...);
			setting.Save(...);
			setting.Close(); // このClose()はSettingProxyのデストラクタに任せる事も出来ます。
			::MessageBox( MQ_GetWindowHandle(), "Activate!", NULL, 0 );
		}
		return TRUE;
	}
};
@endcode

@par 2.いくつかの抽象メソッドの実装が既に代行されています。
MQCommandPluginで実装しなければいけなかったいくつかの仮想メソッドの仮実装は既に記述してあります。必要な時だけオーバーライドしてください。

なお下記にリストされる基本的な仮想関数はオーバーライドでカスタムすることはできません。これらの返すべき値は、CommandPluginコンストラクタに初期値として設定します。
- GetPlugInID()
- GetPlugInName()
- EnumString()
.

@note
@par 継承構造
	CommandPluginsInterfacedBase／ベースクラス。外部から参照されるvirtualメソッド全般の標準実装。
@par
	StationPluginTemplate／protectedメソッドの実装（またStationPluginTemplateをベースにCommandPlugin固有のprotectedメソッドをCommandPluginとしてさらに追加）
*/

/*!
@fn MQCLI::Plugins::CommandPlugin::CommandPlugin( const char* productName, const char* pluginFullName, const char* displayName )
@brief コンストラクタ（プラグインIDを自動生成して初期化）
@param productName 作者名を指定します。設定した値はGetProductName()で取得されます。この文字列のハッシュをProductIDに設定します。
@param pluginFullName プラグイン名を設定します。設定した値はGetPlugInName()で取得されます。この文字列のハッシュをPluginIDに設定します。
@param displayName 表示名を設定します。設定した値はEnumString()で取得されます。
@note ハッシュは@ref MQ0x::CollectionHashCode "MQ0x::CollectionHashCode<DWORD>(const char*)"によって計算されます。
*/

/*!
@fn MQCLI::Plugins::CommandPlugin::CommandPlugin( const char* productName, const char* pluginFullName, const char* displayName, const DWORD idProduct, const DWORD idPlugin )
@brief コンストラクタ（任意のプラグインIDを指定して初期化）
@param productName 作者名を指定します。設定した値はGetProductName()で取得されます。
@param pluginFullName プラグイン名を設定します。設定した値はGetPlugInName()で取得されます。
@param displayName 表示名を設定します。設定した値はEnumString()で取得されます。
@param idProduct 任意のプロダクトIDを指定します。
@param idPlugin 任意のプラグインIDを指定します。
*/
