#ifndef _dkutil_CommonControl__
#define _dkutil_CommonControl__


#ifdef USE_DKINGYO_SHELL_AND_COMMON_CONTROL

#include <shlobj.h>
#include <mbstring.h>
#include <Shlwapi.h>
#include <objbase.h>
#include <commctrl.h>
//#include <winnls32.h> こいつがあると、英語版Windowsで起動できねぇ！
#include <imm.h>
#include <basetsd.h>
//#include <mmreg.h>
#include "dKingyoMacro.h"
#include "dkutilDefined.h"
#include "dkutilStdio.h"
#include "dkutilDLLManager.h"

#if _MSC_VER >= 1200
#pragma comment(lib,"comctl32")
#pragma comment(lib,"imm32")
#endif
;
namespace dkutil{

/*!
☆IME表示設定IME表示の設定をします。
@param wnd[in] Windowのハンドル。(NULLだと、IMEが落ちるかもしれないので失敗する。
@param flag[in] 使用するならtrue
@return wndがNULLだとfalse 成功したら true
*/
inline bool SetShowIME(HWND wnd, bool flag )
{
	typedef int (PASCAL *SETIME_TYPE)(HWND,int);
	if(wnd==NULL) return false;

	{
		const int num = 4;
		const char *dlltbl[num]={
			"WINNLS32.DLL","winnls.dll",
			"user32.dll","win32nls.dll"
		};
		const char *prctbl[num]={
			"WINNLSEnableIME","WINNLSEnableIME",
			"WINNLSEnableIME","　WINNLS32EnableIME"
		};
		SETIME_TYPE SetIME=NULL;
		DLLManager f;
		for(int i=0;i<num;i++){
			f.reset(dlltbl[i]);
			
			SetIME = (SETIME_TYPE)f.find(prctbl[i]);
			if(SetIME){
				SetIME(wnd,flag);
				return true;
			}
		}
	}
	return false;
}

class FolderSelector{
public:
	/*!
	@param GetPath[out] フォルダの文字列を入れるバッファ(MAX_PATH)以上にすること！！
	@param BuffSize[in] GetPathバッファのサイズ（保険ですね。
	@param folder[in] 初期フォルダ指定
	@param Title[in] このダイアログのタイトル
	@param Flag[in] BIF_EDITBOXのようなフラグ指定（詳しくはBROWSEINFO
	@param WindowHandle[in] オーナーウインドウのハンドル
	*/
	int FolderSelectLogic(char *GetPath,size_t BuffSize,
		const char *folder=NULL,const char *Title=NULL,
		UINT Flag=BIF_EDITBOX,HWND WindowHandle=NULL)
	{
		if(BuffSize == 0) return edk_FAILED;
		char *pDir = GetPath;
		pDir[0] = '\0';

		HRESULT hr;
		BROWSEINFO bi={0};
		ITEMIDLIST *lpid = NULL;
		LPMALLOC pMalloc = NULL;

		bi.hwndOwner	= WindowHandle;
		bi.ulFlags		= Flag;
		if(!Title){
			bi.lpszTitle	= "ディレクトリ指定";
		}else{
			bi.lpszTitle = Title;
		}
		if(folder){
			bi.lpfn   = BrowseCallbackProc; // コールバーク関数
			bi.lParam = (LPARAM)folder;       // 初期フォルダ
		}
		//表示ing
		lpid = ::SHBrowseForFolder( &bi );

		if ( lpid == NULL )
		{
			//cancelが押された。
			return edk_Not_Selected;
		}
		else
		{
			hr = ::SHGetMalloc( &pMalloc );
			if ( hr == E_FAIL )
			{
				MessageBox(WindowHandle,  "SHGetMalloc Error", "Error",MB_OK);
				return edk_FAILED;
			}

			::SHGetPathFromIDList( lpid, pDir );
			if ( pDir[strlen(pDir) - 1] != '\\' ){
				dkstrcat_amap(pDir,BuffSize,strlen(pDir),"\\",strlen("\\"));
				//strcat( pDir, "\\" );
			}

			pMalloc->Free( lpid );
			pMalloc->Release();
		}
		return edk_SUCCEEDED;
	}
	FolderSelector(char *GetPath,size_t BuffSize,const char *folder,bool *flag){
		*flag = DKUTIL_SUCCEEDED(FolderSelectLogic(GetPath,BuffSize,folder));
	}
	//何もしないコンストラクタ。
	FolderSelector(){}
	/*!
	@param GetPath[out] フォルダのパス
	@note
	GetPathがemptyだったら選択されていない。
	*/
	FolderSelector(std::string &GetPath,const char *folder=NULL)
	{
		GetPath.clear();
		char path[MAX_PATH]="";
		FolderSelectLogic(path,sizeof(path),folder);
		GetPath = path;
	}
	// コールバーク関数
	static int CALLBACK BrowseCallbackProc( HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM lpData )
	{
		// フォルダ選択ダイアログの初期化
		if ( (BFFM_INITIALIZED == uMsg) && lpData ){
			SendMessage( hWnd, BFFM_SETSELECTION, TRUE, lpData );
		}
		return 0;
	}//BrowseCallbackProc


};
inline bool EasyFolderSelect(char *buff,size_t buffsize){
	FolderSelector sel;
	return DKUTIL_SUCCEEDED(sel.FolderSelectLogic(buff,buffsize));
}

}//end of dkutil namespace


#endif//end of USE_DKINGYO_SHELL_AND_COMMON_CONTROL
#endif//end of include once
