/*! @mainpage Read me / Download

@par mqsdxって？

mqsdxは以下の二つの名前空間を含んでおり、MQ0x単体またはMQ0x+MQCLIとしてご利用いただけます。

- @par MQ0x
C++サポートライブラリ
	- @subpage MQ0xの使い方
	- @subpage MQ0xの一覧 "モジュール＞MQ0xの一覧 (リファレンス)"

@par

- @par MQCLI
CLI(.Net)サポートライブラリ
	- @subpage MQCLIの使い方
	- @subpage MQCLIの一覧 "モジュール＞MQCLIの一覧 (リファレンス)"
	.

@attention	@par 対応するメタセコイアおよびプラグインSDKバージョン、開発環境について
- メタセコイア 3.0.5
- プラグインSDK mqsdk300
- 開発環境 Microsoft Visual C++ 2010

@par
一部3.1系対応している部分もありますが、書いただけです。まったく動かしてません (^_^;

mqsdxとVCExpressでダイアログベースのGUIプラグインがサクサク作れる！・・・と良いな。

@par

@htmlonly
<br/><hr/>
@endhtmlonly

@par mqsdxのダウンロード
@htmlonly
<a class="el" href="https://docs.google.com/folder/d/0B_Goo35SvoBrQV9hSng3VWRWS3M/edit?usp=sharing">mqsdx/Downloads（GoogleDrive）</a>
@endhtmlonly

mqsdxへのバグ報告・要望・その他問い合わせは下記作者サイトまでよろしくお願いします。
@par 作者サイト
@htmlonly
<a href="http://d.hatena.ne.jp/tiri_tomato/" style="font-weight:bold">チリペヂィア</a><br/>
@endhtmlonly

@attention mqsdx作者はメタセコおよびメタセコのプラグインSDK（以下本家）作者とは別人です（間違えないとは思いますが、一応…）。またmqsdxはユーザーが勝手に作るmqsdkのお・気・楽なラッパーライブラリにすぎません。くれぐれも本家作者様にmqsdxの技術的問い合わせなどはされないようお願いいたします。もし本家に迷惑がかかるならmqsdxの公開は速やかに停止いたします。

@page mqsdxライセンス条項

@par mqsdxライセンス条項

mqsdxパッケージに含まれるソースコードは全てライブラリ相当のソースコードとみなし、これをLGPLv3ライセンスで提供します。

@htmlonly
<br/>
@endhtmlonly

@par 1.mqsdxを改変しない時

@htmlonly
<hr/>
@endhtmlonly

@par mqsdxを改変せずコンパイルした実行ファイルの頒布について

- 商用非商用を問わずmqsdx利用料は生じません。

@par mqsdxを改変せず利用するプログラムのソースコードを公開するとき

- ライセンス条項を含めてmqsdxをそのまま添えて下さい

	使用しているmqsdxのソースコードを公開し、mqsdx部についてLGPLライセンスを明示する必要があります（ただしユーザー独自のソースコードにまでLGPLライセンスを適用する必要はありません）。

	つまり使用しているmqsdxをそのまま同梱すれば良いのですが、mqsdxでは必ずしもmqsdxを完全に同梱せずとも、ReadMeなどでmqsdx配布元へのリンクを分かりやすく明示すれば、mqsdxのソース公開およびライセンス明示の条件を満たしているとします。

	なおmqsdxを利用し成果物を公開する時、mqsdxの部分にはリバースエンジニアリングの禁止と対策をしないように気をつけて下さい。

@htmlonly
<br/>
@endhtmlonly
@par 2.mqsdxを改変する時

@htmlonly
<hr/>
@endhtmlonly

まったく公開しない、あるいはLGPLを継承してフォークプロジェクトとして公開できます。

- 改変した元mqsdxを個人的な範囲で利用する、または組織内の不出の内製データとして利用する。
- 改変した元mqsdxをソースコード形式で再頒布もするが、LGPLライセンスを継承し、mqsdxと似てはいても別系統のライブラリである事を、公開される文章およびソースコード設計上、明示する（つまり別名で再構成されていれば良く、例えばmqsdxMk2とかmqsdxxとかの類似リネームライブラリでも構いません：明示的なfork）
.
@note mqsdxをライブラリとして採用せずに、その一部をコピペしたくらいで「LGPLを継承せよ！」と言うのも良くないでしょうから、LGPL継承を避けつつ複写をするためには「ライブラリとしての再利用構造が一切失われている」状態を満たせば良いとします。
例えば元mqsdxソースコードが、「ライブラリとしては」リリースされないようにします。つまりソースコード一式をコンパイルするとメタセコイアにインポート可能であり、意図するプラグイン機能が利用できるなら、その一部には転写する事が出来ます。
しかしプラグインプログラムと切り離し、再利用することが出来るソースコード一式に含め、そのソースコード一式や、コンパイルされたリンクできるバイナリをリリースするのは、ライブラリとしてのリリースにあたってしまうためLGPLを継承しないのは許諾出来ません。

@htmlonly
<br/><hr/><br/>
@endhtmlonly

「フォルダごとコピペしてすぐコンパイルできて、１個のdllでプラグインが配布できる」「できればforkしてほしいかな」というあたりでかなりややこしいライセンスが適用されています。平にご容赦のほどよろしくお願いいたします。

もし仮に、あからさまな違反が発覚したからといっても頒布形式の修正を要求するくらいなんですが、利用に際して判断が難しい、また「あるいは」という提案がある場合（それに一番ありそうなライセンスの解釈について問題がある事を暇つぶしにちょっと説教したい場合）、作者ブログまで「これこれの打ち合わせ希望」とコメントいただければ対応いたします。

@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の使い方
@{
@}
*/

/*!	@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 サポートクラス
	CLI（.Net）プログラムをサポートするクラスライブラリ
	@{
	@}

	@defgroup StationPlugins
	独自のStationPluginを開発するためのベースクラスを提供します。
	@{
	@}

	@defgroup CommandPlugins
	独自のCommandPluginを開発するためのベースクラスを提供します
	@{
	@}
	
@}
*/


/*!
@class MQCLI::StationPlugin
@ingroup StationPlugins 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::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::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::CommandPlugin
@ingroup CommandPlugins 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::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::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を指定します。
*/
