前の10件 6  7  8  9  10  11  12  13  14  15  16

記事一覧

int型の数値を文字列に変換するのにitoa関数は利用できない

test120.gif
int型の数値を文字列に変換するには、従来からのC/C++ではitoa関数を利用した。しかしWindowsプログラミングではitoa関数は使わない方がいい。

もちろんitoa関数も使えるが文字列バッファーサイズを指定できるためセキュリティが若干高い_itoa_s系の関数を利用した方がいい。さらに言うと実際のプログラミングでは速度的には劣るがバッファーのことを考える必要がなくコーディングが楽なCString型の文字列を利用する変換がいいだろう。



bool	Test()
{
	////////////////////////////////
	//	int型数値を文字列に変換
	//
	{
		//char型文字列に変換
		int		nValue = 123;
		char	pszText[256];

		//itoaや_itoaは利用しない方がいい!代わりに_itoa_sを使う
		::_itoa_s(nValue,pszText,256 * sizeof(char),10);

		::MessageBoxA(NULL,pszText,"",MB_OK);
	}
	{
		//wchar_t型文字列に変換
		int		nValue = 123;
		wchar_t	pszText[256];

		//_itowは利用しない方がいい!代わりに_itow_sを使う
		::_itow_s(nValue,pszText,256 * sizeof(wchar_t),10);

		::MessageBoxW(NULL,pszText,L"",MB_OK);
	}
	{
		//TCHAR型文字列に変換
		int		nValue = 123;
		TCHAR	pszText[256];

		//_itotは利用しない方がいい!代わりに_itot_sを使う
		::_itot_s(nValue,pszText,256 * sizeof(TCHAR),10);

		::MessageBox(NULL,pszText,_T(""),MB_OK);
	}
	{
		//CString型文字列に変換
		int		nValue = 123;
		CString	strText;

		strText.Format(_T("%d"),nValue);

		::MessageBox(NULL,strText,_T(""),MB_OK);
	}

	return	true;
}


プロジェクトファイルをダウンロード

IEコントロールからのイベントを処理する

test119_01.gif
Internet Explorerのコントロール(IEコントロール)ではスクリプトの実行や画像のダウンロードを抑えるダウンロードコントロール機能や、HTMLファイルの読み込みが終わったことを知らせるための各種イベント機能などを備えている。

ここではIEコントロールでスクリプトの実行などを抑える処理とダウンロード終了などのイベントを取得できるクラス「IDnpIESinkImpl」を作成した。

test119_02.gif
ここではテストのためにATL/WTLアプリケーションウイザードでSDIアプリケーションを作成した。その際にビューウインドウの形式で「HTMLページ」を指定することでビューがIEコントロールになっているウインドウのプロジェクトを作成し、そのIEコントロールからのイベントを処理した。

ビューからIEコントロールを取得するにはQueryControlを利用する。

■自動生成された「プロジェクト名View.h」ファイルの先頭に以下のHTMLイベント処理用のクラスを追加する。自分の好みに応じた処理をしたい場合はこの実装を変える。

#include "DnpIESinkImpl.h"



//
//	イベント処理用クラス
//
class ATL_NO_VTABLE CIESink : 
	public CComObjectRootEx<CComSingleThreadModel>,
	public IOleClientSite,
	public IDispatch,
	public IDnpIESinkImpl
{
public:
	CIESink()
	{
	}

	BEGIN_COM_MAP(CIESink)
		COM_INTERFACE_ENTRY(IDnpIESink)
		COM_INTERFACE_ENTRY(IOleClientSite)
		COM_INTERFACE_ENTRY(IDispatch)
	END_COM_MAP()

	DECLARE_PROTECT_FINAL_CONSTRUCT()


	////////////////////////////
	//	IDispatch;
	//
	STDMETHOD(Invoke)(DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS *pDispParams,VARIANT *pVarResult,EXCEPINFO *pExcepInfo,UINT *puArgErr)
	{
		if(dispIdMember == DISPID_AMBIENT_DLCONTROL)
		{
			//ダウンロードコントロール設定

			//ATLTRACE("DISPID_AMBIENT_DLCONTROL\n");
			V_VT(pVarResult) = VT_I4;
			V_I4(pVarResult) = _nAmbientPropertyFlags;
			return	S_OK;
		}


		if(dispIdMember == DISPID_DOWNLOADCOMPLETE)
		{
			ATLTRACE("DISPID_DOWNLOADCOMPLETE\n");
			return	S_OK;
		}
		if(dispIdMember == DISPID_NAVIGATECOMPLETE)
		{
			ATLTRACE("DISPID_NAVIGATECOMPLETE\n");
			return	S_OK;
		}
		if(dispIdMember == DISPID_NAVIGATECOMPLETE2)
		{
			ATLTRACE("DISPID_NAVIGATECOMPLETE2\n");
			return	S_OK;
		}
		if(dispIdMember == DISPID_DOCUMENTCOMPLETE)
		{
			::MessageBox(NULL,_T("HTMLの読み込みが終わりました"),_T(""),MB_OK);
			ATLTRACE("DISPID_DOCUMENTCOMPLETE\n");
			return	S_OK;
		}
		if(dispIdMember == DISPID_NAVIGATEERROR)
		{
			ATLTRACE("DISPID_NAVIGATEERROR\n");
			return	S_OK;
		}

		return	S_OK;
	}
	STDMETHOD(GetTypeInfoCount)(UINT *pctinfo)
	{
		*pctinfo = 0;
		return	S_OK;
	}
	STDMETHOD(GetTypeInfo)(UINT iTInfo,LCID lcid,ITypeInfo **ppTInfo)					{	return	E_NOTIMPL;		}
	STDMETHOD(GetIDsOfNames)(REFIID riid,LPOLESTR *rgszNames,UINT cNames,LCID lcid,DISPID *rgDispId)	{	return	E_NOTIMPL;		}




	///////////////////////////////////
	//	IOleControlSite
	//
	STDMETHOD(GetMoniker)(DWORD dwAssign,DWORD dwWhichMoniker,IMoniker **ppmk)		{	return	E_NOTIMPL;		}
	STDMETHOD(SaveObject)(void)							{	return	E_NOTIMPL;		}
	STDMETHOD(GetContainer)(IOleContainer **ppContainer){	return	E_NOTIMPL;		}
	STDMETHOD(ShowObject)(void)							{	return	E_NOTIMPL;		}
	STDMETHOD(OnShowWindow)(BOOL fShow)					{	return	E_NOTIMPL;		}
	STDMETHOD(RequestNewObjectLayout)(void)				{	return	E_NOTIMPL;		}
};

■ビュークラスの中にIEへのコネクト処理を追加する。この処理を行うことでIEコントロールで発生したイベントを取得できる。ここではウインドウ作成時と破壊時にそれぞれコネクト、ディスコネクトしている

	BEGIN_MSG_MAP(CTest119View)
		MESSAGE_HANDLER(WM_CREATE, OnCreate)
		MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
	END_MSG_MAP()


	CComPtr<IDnpIESink>		_pIESink;


	LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
	{
		LRESULT	ret;

		CComPtr<IWebBrowser2>	pIWebBrowser2;

		ret = DefWindowProc(uMsg,wParam,lParam);

		QueryControl(&pIWebBrowser2);

		if(pIWebBrowser2)
		{
			HRESULT	hr;

			_pIESink = new CComObject<CIESink>;

			hr = _pIESink->Init();
			if(SUCCEEDED(hr))
				hr = _pIESink->SetIE(pIWebBrowser2);		//IEのセット
			if(SUCCEEDED(hr))
				hr = _pIESink->Advice();					//接続

			//ダウンロードコントロール設定
			if(SUCCEEDED(hr))
				hr = _pIESink->AmbientPropertyChange(DLCTL_DOWNLOADONLY | DLCTL_NO_SCRIPTS | DLCTL_NO_JAVA | DLCTL_NO_DLACTIVEXCTLS | DLCTL_NO_RUNACTIVEXCTLS);
		}

		return	ret;
	}


	LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
	{
		bHandled = FALSE;

		if(_pIESink)
			_pIESink->Init();

		return	0;
	}

■以下のソースコードをファイル名「DnpIESinkImpl.h」として保存する

#pragma	once


#include "mshtml.h"
#include "mshtmdid.h"
#include "Exdisp.h"
#include "Exdispid.h"


//
//	Internet Explorerのイベント処理&ダウンロードコントロール用クラス群
//
//	使用例はこのファイル末尾
//





MIDL_INTERFACE("55647A04-86A4-436d-BF23-154F75582E8A")
IDnpIESink : public IUnknown
{
public:
	STDMETHOD(Init)(void) = 0;
	STDMETHOD(SetIE)(IDispatch* pWebBrowser) = 0;
	STDMETHOD(Advice)(void) = 0;
	STDMETHOD(Unadvice)(void) = 0;
	STDMETHOD(AmbientPropertyChange)(LONG nFlags) = 0;
};




class ATL_NO_VTABLE IDnpIESinkImpl	: public IDnpIESink
{
public:
	IDnpIESinkImpl()
	{
		Init();
	}

	~IDnpIESinkImpl()
	{
		ATLASSERT(_pConnectionPoint == NULL);		//接続が解除されていない!
		Init();
	}

protected:
	DWORD		_dwCookie;
	LONG		_nAmbientPropertyFlags;
	CComPtr<IWebBrowser2>		_pWebBrowser2;
	CComPtr<IConnectionPoint>	_pConnectionPoint;

public:


	//
	//	クラスの初期化
	//
	STDMETHOD(Init)(void)
	{
		_nAmbientPropertyFlags = 0;

		if(_pConnectionPoint)
			Unadvice();

		if(_pWebBrowser2)
			_pWebBrowser2 = NULL;

		_dwCookie = 0;

		return	S_OK;
	}



	//
	//	Internet Explorerの設定
	//
	STDMETHOD(SetIE)(IDispatch* pWebBrowser)
	{
		ATLASSERT(pWebBrowser);
		if(pWebBrowser == NULL)
			return	E_FAIL;

		ATLASSERT(_pWebBrowser2 == NULL);
		if(_pWebBrowser2)
			return	E_FAIL;

		return	pWebBrowser->QueryInterface(IID_IWebBrowser2,(void**)&_pWebBrowser2);
	}



	//
	//	Internet Explorerとの接続
	//
	//	必ずUnadviceすること!
	//
	STDMETHOD(Advice)(void)
	{
		HRESULT	hr;

		CComPtr<IUnknown>	pUnknown;
		CComPtr<IConnectionPointContainer>	pConnectionPointContainer;

		ATLASSERT(_pConnectionPoint == NULL);		//接続済み
		ATLASSERT(_pWebBrowser2);
		if(_pWebBrowser2 == NULL)
			return	E_FAIL;


		QueryInterface(IID_IUnknown,(void**)&pUnknown);

		hr = E_FAIL;
		_dwCookie = 0;
		_pWebBrowser2->QueryInterface(&pConnectionPointContainer);
		if(pConnectionPointContainer)
		{
			_pConnectionPoint = NULL;
			pConnectionPointContainer->FindConnectionPoint(__uuidof(DWebBrowserEvents2),&_pConnectionPoint);
		}
		if(_pConnectionPoint)
			hr = _pConnectionPoint->Advise(pUnknown,&_dwCookie);

		return	hr;
	}



	//
	//	Internet Explorerとの接続解除
	//
	STDMETHOD(Unadvice)(void)
	{
		HRESULT	hr;

		if(_pConnectionPoint == NULL)
			return	E_FAIL;

		hr = _pConnectionPoint->Unadvise(_dwCookie);
		if(SUCCEEDED(hr))
		{
			_dwCookie = 0;
			_pConnectionPoint = NULL;
			return	S_OK;
		}

		return	E_FAIL;
	}



	//
	//	ダウンロードコントロールの設定
	//
	//
	//	nFlagsは以下のようなフラグ
	//		DLCTL_DOWNLOADONLY | DLCTL_NO_SCRIPTS | DLCTL_NO_JAVA | DLCTL_NO_DLACTIVEXCTLS | DLCTL_NO_RUNACTIVEXCTLS;
	//
	STDMETHOD(AmbientPropertyChange)(LONG nFlags)
	{
		HRESULT	hr;

		CComPtr<IOleControl>	pOleControl;
		CComPtr<IOleObject>		pOleObject;
		CComPtr<IOleClientSite>	pOleClientSite;

		hr = QueryInterface(IID_IOleClientSite,(void**)&pOleClientSite);
		if(pOleClientSite == NULL)
			return	E_FAIL;

		if(_pWebBrowser2 == NULL)
			return	E_FAIL;

		hr = _pWebBrowser2->QueryInterface(&pOleObject);
		if(pOleObject)
			hr = pOleObject->SetClientSite(pOleClientSite);

		if(SUCCEEDED(hr))
			hr = _pWebBrowser2->QueryInterface(&pOleControl);
		if(pOleControl)
		{
			_nAmbientPropertyFlags = nFlags;
			hr = pOleControl->OnAmbientPropertyChange(DISPID_AMBIENT_DLCONTROL);
		}

		return	hr;
	}
};









//
//	使用例
//


//
////	イベント処理用クラス
////
//class ATL_NO_VTABLE CIESink : 
//	public CComObjectRootEx<CComSingleThreadModel>,
//	public IOleClientSite,
//	public IDispatch,
//	public IDnpIESinkImpl
//{
//public:
//	CIESink()
//	{
//	}
//
//	BEGIN_COM_MAP(CIESink)
//		COM_INTERFACE_ENTRY(IDnpIESink)
//		COM_INTERFACE_ENTRY(IOleClientSite)
//		COM_INTERFACE_ENTRY(IDispatch)
//	END_COM_MAP()
//
//	DECLARE_PROTECT_FINAL_CONSTRUCT()
//
//
//	////////////////////////////
//	//	IDispatch;
//	//
//	STDMETHOD(Invoke)(DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS *pDispParams,VARIANT *pVarResult,EXCEPINFO *pExcepInfo,UINT *puArgErr)
//	{
//		if(dispIdMember == DISPID_AMBIENT_DLCONTROL)
//		{
//			//ダウンロードコントロール設定
//
//			//ATLTRACE("DISPID_AMBIENT_DLCONTROL\n");
//			V_VT(pVarResult) = VT_I4;
//			V_I4(pVarResult) = _nAmbientPropertyFlags;
//			return	S_OK;
//		}
//
//
//		if(dispIdMember == DISPID_DOWNLOADCOMPLETE)
//		{
//			ATLTRACE("DISPID_DOWNLOADCOMPLETE\n");
//			return	S_OK;
//		}
//		if(dispIdMember == DISPID_NAVIGATECOMPLETE)
//		{
//			ATLTRACE("DISPID_NAVIGATECOMPLETE\n");
//			return	S_OK;
//		}
//		if(dispIdMember == DISPID_NAVIGATECOMPLETE2)
//		{
//			ATLTRACE("DISPID_NAVIGATECOMPLETE2\n");
//			return	S_OK;
//		}
//		if(dispIdMember == DISPID_DOCUMENTCOMPLETE)
//		{
//			ATLTRACE("DISPID_DOCUMENTCOMPLETE\n");
//			return	S_OK;
//		}
//		if(dispIdMember == DISPID_NAVIGATEERROR)
//		{
//			ATLTRACE("DISPID_NAVIGATEERROR\n");
//			return	S_OK;
//		}
//
//		return	S_OK;
//	}
//	STDMETHOD(GetTypeInfoCount)(UINT *pctinfo)
//	{
//		*pctinfo = 0;
//		return	S_OK;
//	}
//	STDMETHOD(GetTypeInfo)(UINT iTInfo,LCID lcid,ITypeInfo **ppTInfo)					{	return	E_NOTIMPL;		}
//	STDMETHOD(GetIDsOfNames)(REFIID riid,LPOLESTR *rgszNames,UINT cNames,LCID lcid,DISPID *rgDispId)	{	return	E_NOTIMPL;		}
//
//
//
//
//	///////////////////////////////////
//	//	IOleControlSite
//	//
//	STDMETHOD(GetMoniker)(DWORD dwAssign,DWORD dwWhichMoniker,IMoniker **ppmk)		{	return	E_NOTIMPL;		}
//	STDMETHOD(SaveObject)(void)							{	return	E_NOTIMPL;		}
//	STDMETHOD(GetContainer)(IOleContainer **ppContainer){	return	E_NOTIMPL;		}
//	STDMETHOD(ShowObject)(void)							{	return	E_NOTIMPL;		}
//	STDMETHOD(OnShowWindow)(BOOL fShow)					{	return	E_NOTIMPL;		}
//	STDMETHOD(RequestNewObjectLayout)(void)				{	return	E_NOTIMPL;		}
//};
//
//



////
////	ウインドウ内での使用
////
//class	CTestDlg : public CDialog
//{
//	CComPtr<IDnpIESink>		_pIESink;
//
//public:
//	(...)
//
//	~CTestDlg()
//	{
//		if(_pIESink)
//			_pIESink->Init();
//	}
//
//
//	BOOL	OnInitDialog(...)
//	{
//		(...)
//
//		HRESULT	hr;
//
//		_pIESink = new CComObject<CIESink>;
//
//		hr = _pIESink->Init();
//		if(SUCCEEDED(hr))
//			hr = _pIESink->SetIE(pWebBrowser2);			//IEのセット
//		if(SUCCEEDED(hr))
//			hr = _pIESink->Advice();					//接続
//
//		//ダウンロードコントロール設定
//		if(SUCCEEDED(hr))
//			hr = _pIESink->AmbientPropertyChange(DLCTL_DOWNLOADONLY | DLCTL_NO_SCRIPTS | DLCTL_NO_JAVA | DLCTL_NO_DLACTIVEXCTLS | DLCTL_NO_RUNACTIVEXCTLS);
//
//		(...)
//
//		return	TRUE;
//	}
//
//	(...)
//};


プロジェクトファイルをダウンロード

IEなどのアプリケーションからドラッグアンドドロップを受け入れる

test118.gif
Microsoft WordやInternet Explorerなど多くのアプリケーションではドラッグ・アンド・ドロップによってほかのアプリケーションとデータのやり取りができるように作られている。自分で作成したアプリケーションでドラッグ・アンド・ドロップによりデータを受け取るにはIDropTargetを利用した処理を実装する。

ここではIDropTargetの実装はが簡単にできるようにCDnpDropTargetImplという補助クラスを作成した。図の例ではInternet Explorerからドラッグ・アンド・ドロップされたデータのうち、テキストデータをメッセージボックスに表示している。

自分の好みに応じた処理を実装したい場合はCDropTarget内を変更する。そのほかの部分は多くの場合、共通に利用できる。

■ATL/WTLアプリケーションうインザードでダイアログベースのプロジェクトを作成する

■自動生成したソースコードのうち「プロジェクト名.cpp」のファイルを編集して、OleInitializeとOleUninitializeが実行されるようにする

int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
{
(...省略...)

	//ドラッグアンドドロップ用
	::OleInitialize(NULL);

	int nRet = Run(lpstrCmdLine, nCmdShow);

	//ドラッグアンドドロップ用
	::OleUninitialize();

	_Module.Term();
	::CoUninitialize();

	return nRet;
}


■MainDlg.hの先頭に以下のようなドラッグアンドドロップのメイン処理の書かれたクラス宣言を追加する

#include "DnpDropTargetImpl.h"

class CDropTarget : public CDnpDropTargetImpl
{
protected:
	virtual	bool	OnDrop(IDataObject* pDataObject,DWORD grfKeyState,POINTL pt,DWORD* pdwEffect)
	{
		//テキストのみ処理
		if(IsSupport(CF_TEXT))
		{
			bool		ret;
			CAtlString	strData;

			//テキストデータを取得
			ret = GetTextData(strData);
			if(ret)
			{
				//キー状態に応じてドラッグ・アンド・ドロップ元の動作を変えれる。
				//移動(DROPEFFECT_MOVE)にすると、ドロップ元のデータは消える。
				if(grfKeyState & MK_SHIFT)
					*pdwEffect = DROPEFFECT_MOVE;
				else
					*pdwEffect = DROPEFFECT_COPY;

				//取得文字列をメッセージボックスに表示
				::MessageBox(NULL,strData,_T(""),MB_OK);


				return	true;
			}
		}

		return	false;
	}

	virtual	bool	OnDragOver(IDataObject* pDataObject,DWORD grfKeyState,POINTL pt,DWORD* pdwEffect)
	{
		//ドラッグ元がテキスト形式(CF_TEXT)をサポートしている場合のみ処理
		if(IsSupport(CF_TEXT))
		{
			//マウスカーソルの形を指定する。キー状態に応じて設定可能
			//使用可能なキーは以下の通り
			//MK_CONTROL, MK_SHIFT, MK_ALT, MK_BUTTON, MK_LBUTTON, MK_MBUTTON, and MK_RBUTTON

			//ここではシフトキーのみ監視
			if(grfKeyState & MK_SHIFT)
				*pdwEffect = DROPEFFECT_MOVE;
			else
				*pdwEffect = DROPEFFECT_COPY;

			return	true;
		}

		return	false;
	}
};


■MainDlg.hのクラスCMainDlg内にメンバ変数を追加する

	//メンバ変数追加
	CComPtr<IDropTarget>	_pIDropTarget;

■MainDlg.hのクラスCMainDlgにあるOnInitDialog関数内にドラッグアンドドロップの登録処理を追加する

LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
	{
		(...省略...)

		HRESULT	hr;
		CComObject<CDropTarget>*	pCDropTarget;

		pCDropTarget = NULL;
		hr = CComObject<CDropTarget>::CreateInstance(&pCDropTarget);

		if(SUCCEEDED(hr))
		{
			_pIDropTarget = NULL;
			hr = pCDropTarget->QueryInterface(IID_IDropTarget,(void**)&_pIDropTarget);
		}

		//ドラッグ・アンド・ドロップの受け入れ登録
		if(SUCCEEDED(hr))
			hr = ::RegisterDragDrop(m_hWnd,_pIDropTarget);

		ATLASSERT(SUCCEEDED(hr));		//失敗した場合は起動時にOleInitializeかCoInitializeを実行していない可能性大

		return TRUE;
	}

■MainDlg.hのクラスCMainDlgにあるCloseDialog関数内でRevokeDragDropを実行してドラッグアンドドロップの登録解除処理をする

	void CloseDialog(int nVal)
	{
		//ドラッグ・アンド・ドロップの受け入れ登録解除
		::RevokeDragDrop(m_hWnd);

		DestroyWindow();
		::PostQuitMessage(nVal);
	}


■ドラッグ・アンド・ドロップ用のクラス定義をファイル名「DnpDropTargetImpl.h」として保存

#pragma	once

#include "atlstr.h"


//
//
//■使用例
//
//#include "DnpDropTargetImpl.h"
//
//
/////
/////プログラム起動時にCoInitializeとOleInitializeが実行されるようにする
/////プログラム終了時にOleUninitializeとCoUninitializeが実行されるようにする
/////
//int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
//{
//	HRESULT hRes = ::CoInitialize(NULL);
//
//	(...省略...)
//
//	//ドラッグアンドドロップ用
//	::OleInitialize(NULL);
//
//	(メイン処理)
//
//	//ドラッグアンドドロップ用
//	::OleUninitialize();
//
//	::CoUninitialize();
//
//	return nRet;
//}
//
//
////
////ドラッグアンドドロップの挙動を実装したクラスを作成
////
//class CDropTarget : public CDnpDropTargetImpl
//{
//protected:
//	virtual	bool	OnDrop(IDataObject* pDataObject,DWORD grfKeyState,POINTL pt,DWORD* pdwEffect)
//	{
//		//テキストのみ処理
//		if(IsSupport(CF_TEXT))
//		{
//			bool		ret;
//			CAtlString	strData;
//
//			//テキストデータを取得
//			ret = GetTextData(strData);
//			if(ret)
//			{
//				//キー状態に応じてドラッグ・アンド・ドロップ元の動作を変えれる。
//				//移動(DROPEFFECT_MOVE)にすると、ドロップ元のデータは消える。
//				if(grfKeyState & MK_SHIFT)
//					*pdwEffect = DROPEFFECT_MOVE;
//				else
//					*pdwEffect = DROPEFFECT_COPY;
//
//				//取得文字列をメッセージボックスに表示
//				::MessageBox(NULL,strData,_T(""),MB_OK);
//
//
//				return	true;
//			}
//		}
//
//		return	false;
//	}
//
//	virtual	bool	OnDragOver(IDataObject* pDataObject,DWORD grfKeyState,POINTL pt,DWORD* pdwEffect)
//	{
//		//ドラッグ元がテキスト形式(CF_TEXT)をサポートしている場合のみ処理
//		if(IsSupport(CF_TEXT))
//		{
//			//マウスカーソルの形を指定する。キー状態に応じて設定可能
//			//使用可能なキーは以下の通り
//			//MK_CONTROL, MK_SHIFT, MK_ALT, MK_BUTTON, MK_LBUTTON, MK_MBUTTON, and MK_RBUTTON
//
//			//ここではシフトキーのみ監視
//			if(grfKeyState & MK_SHIFT)
//				*pdwEffect = DROPEFFECT_MOVE;
//			else
//				*pdwEffect = DROPEFFECT_COPY;
//
//			return	true;
//		}
//
//		return	false;
//	}
//};
//
//
////
////ドラッグアンドドロップを受け入れたいウインドウに処理を追加
////
//class CMainDlg : public CDialogImpl<CMainDlg>, public CUpdateUI<CMainDlg>,
//		public CMessageFilter, public CIdleHandler
//{
//
//	//メンバ変数追加
//	CComPtr<IDropTarget>	_pIDropTarget;
//
//public:
//	(...省略...)
//
//	//ウインドウ初期化時に登録処理を追加
//	LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
//	{
//		(...省略...)
//
//
//		HRESULT	hr;
//		CComObject<CDropTarget>*	pCDropTarget;
//
//		pCDropTarget = NULL;
//		hr = CComObject<CDropTarget>::CreateInstance(&pCDropTarget);
//
//		if(SUCCEEDED(hr))
//		{
//			_pIDropTarget = NULL;
//			hr = pCDropTarget->QueryInterface(IID_IDropTarget,(void**)&_pIDropTarget);
//		}
//
//		//ドラッグ・アンド・ドロップの受け入れ登録
//		if(SUCCEEDED(hr))
//			hr = ::RegisterDragDrop(m_hWnd,_pIDropTarget);
//
//		ATLASSERT(SUCCEEDED(hr));		//失敗した場合は起動時にOleInitializeかCoInitializeを実行していない可能性大
//
//		return TRUE;
//	}
//
//	//ウインドウ終了時に登録解除処理を追加
//	void CloseDialog(int nVal)
//	{
//		//ドラッグ・アンド・ドロップの受け入れ登録解除
//		::RevokeDragDrop(m_hWnd);
//
//		DestroyWindow();
//		::PostQuitMessage(nVal);
//	}
//};
//
//
class CDnpDropTargetImpl : 
	public CComObjectRootEx<CComSingleThreadModel>,
	public CComCoClass<CDnpDropTargetImpl>,
	public IDropTarget
{
protected:

	IDataObject*	_pIDataObject;
public:

	BEGIN_COM_MAP(CDnpDropTargetImpl)
		COM_INTERFACE_ENTRY(IDropTarget)
	END_COM_MAP()

	DECLARE_PROTECT_FINAL_CONSTRUCT()

    CDnpDropTargetImpl()
	{
		_pIDataObject = NULL;
	}


	///////////////////////////////////////
	//	IDropTargetの実装
	//


	//
	//ドラッグ・アンド・ドロップの開始
	//
	STDMETHOD(DragEnter)(IDataObject* pDataObject,DWORD grfKeyState,POINTL pt,DWORD* pdwEffect)
	{
		//_pIDataObjectにIDataObjectを保存しておく
		if(_pIDataObject)
			_pIDataObject->Release();
		_pIDataObject = NULL;
		pDataObject->QueryInterface(IID_IDataObject,(void**)&_pIDataObject);

		//以下共通処理
		return DragOver(grfKeyState,pt,pdwEffect);
	}


	//
	//ドラッグ・アンド・ドロップ中
	//
	STDMETHOD(DragOver)(DWORD grfKeyState,POINTL pt,DWORD* pdwEffect)
	{
		if(_pIDataObject == NULL || pdwEffect == NULL)
			return	E_FAIL;

		*pdwEffect = DROPEFFECT_NONE;

		return OnDragOver(_pIDataObject,grfKeyState,pt,pdwEffect) ? S_OK : E_FAIL;
	}


	//
	//ドラッグ・アンド・ドロップ終了
	//
	STDMETHOD(DragLeave)(void)
	{
		//_pIDataObjectが必要なくなったので解放
		if(_pIDataObject)
			_pIDataObject->Release();
		_pIDataObject = NULL;
		return	S_OK;
	}


	//
	//ドラッグ・アンド・ドロップ終了
	//
	STDMETHOD(Drop)(IDataObject* pDataObject,DWORD grfKeyState,POINTL pt,DWORD* pdwEffect)
	{
		bool	ret;

		//_pIDataObjectを終了時のものに変更
		if(_pIDataObject)
			_pIDataObject->Release();
		_pIDataObject = NULL;

		//GetTextData()などをOnDrop内で使えるようにQueryInterfaceが必要
		pDataObject->QueryInterface(IID_IDataObject,(void**)&_pIDataObject);

		ret = OnDrop(_pIDataObject,grfKeyState,pt,pdwEffect);

		if(_pIDataObject)
			_pIDataObject->Release();
		_pIDataObject = NULL;

		return	ret ? S_OK : E_FAIL;
	}

	//
	//	IDropTargetの実装ここまで
	///////////////////////////////////////


protected:

	virtual	bool	OnDrop(IDataObject* pDataObject,DWORD grfKeyState,POINTL pt,DWORD* pdwEffect) = 0;
	virtual	bool	OnDragOver(IDataObject* pDataObject,DWORD grfKeyState,POINTL pt,DWORD* pdwEffect) = 0;



public:


	//
	//テキストデータの取得
	//
	bool	GetTextData(CAtlString& strData)
	{
		HRESULT		hr;
		FORMATETC	sFormatEtc;
		STGMEDIUM	sStgMedium;

		strData = _T("");
		if(_pIDataObject == NULL)
			return	false;

		::ZeroMemory(&sFormatEtc,sizeof(FORMATETC));
		sFormatEtc.cfFormat	= CF_TEXT;
		sFormatEtc.dwAspect	= DVASPECT_CONTENT;
		sFormatEtc.lindex	= -1;
		sFormatEtc.tymed	= TYMED_HGLOBAL;

		hr = _pIDataObject->GetData(&sFormatEtc,&sStgMedium);
		if(FAILED(hr))
			return	false;

		strData = (char*)::GlobalLock(sStgMedium.hGlobal);
		::GlobalUnlock(sStgMedium.hGlobal);
		::ReleaseStgMedium(&sStgMedium);

		return	true;
	}



	//
	//対応形式のチェック
	//
	bool	IsSupport(CLIPFORMAT nFormat)
	{
		ULONG	i;
		ULONG	nCount;
		HRESULT	hr;
		FORMATETC		pFormatEtc[256];
		IEnumFORMATETC*	pIEnumFORMATETC;

		pIEnumFORMATETC = NULL;
		hr = _pIDataObject->EnumFormatEtc(DATADIR_GET,&pIEnumFORMATETC);
		if(FAILED(hr) || pIEnumFORMATETC == NULL)
			return	false;

		hr = pIEnumFORMATETC->Next(256,pFormatEtc,&nCount);
		if(FAILED(hr))
			return	false;

		for(i = 0; i < nCount; i++)
		{
			if(pFormatEtc[i].cfFormat == nFormat)
				return	true;
		}

		return	false;
	}
};  


プロジェクトファイルをダウンロード

2007年02月24日

Intel VTに対応したVirtual PC 2007が公開されている

vpc2007_01.gif
ちょっと前にVirtual PC 2007(日本語版)が公開された。Windows Vistaに正式対応、さらにIntel VTなどのハードウエア仮想に対応した。

vpc2007_02.gif
もちろん無料でダウンロードして使える。使用制限などは一切ない。

vpc2007_03.gif
プロダクトキーが最初から入力されていてマスクされている。これは最近のマイクロソフトの体験版や無償化されたソフトに多い。

vpc2007_04.gif

vpc2007_05.gif

vpc2007_06.gif
インストールが終わって設定を見てみると...「ハードウエアの仮想化」という項目があった。ここで「ハードウエア依存の仮想化技術を有効にする」にチェックを入れるとIntel VT(Intel Virtualization Technology)やAMD-Vが使えるようになる。もちろん利用しているPCのCPUやBIOSが対応していないと利用できないが。

ちなみにWindows Vista上でIntel VTを有効にしてVirtual PCでWindows Vistaを起動したが...対して変わったようには思えなかった。劇的な効果があるわけではない模様。


Vistaのバグ(その2) 残り時間が表示されない!

vista_bug2.gif
これは重要ではない問題だが、ファイルのコピーや移動時に残り時間が表示されないというもの。

図は5.44GBのファイルを移動しているところ。残り330MBなので5GB以上移動し終わったところだが、残り時間が「計算中...」となっていて表示されていない。

ファイルの移動やコピーに関するバグとして致命的なのは、ファイルをエクスプローラー間でドラッグ・アンド・ドロップした直後にエクスプローラーのウインドウを閉じたときに、移動やコピー操作が勝手にキャンセルされてしまうというもの。
この現象はタイミングの関係なのか、いつも起きるというわけではないため再現するのが難しい。


Vistaのバグ(その1) ファイル名を変更できない!

vista_bug1_01.gif
Windows Vistaを使い始めてすぐに気が付いたバグ。

再現するには...まず適当なフォルダを作り、その中に長いファイル名のファイルを作成する。ファイル名の長さはウインドウのサイズに依存するので一概に言えない。

vista_bug1_02.gif
エクスプローラーでの表示モードを「一覧」に切り替える。

vista_bug1_03.gif
長いファイル名のファイルを右クリックして現れたメニューから「名前の変更」を選択する。キーボードの[F2]キーを利用するなどの別の方法でも構わない。

vista_bug1_04.gif
...すると通常ならファイル名が変更できるはずなのだが、画像のような状態になってしまう。左側にちょっとだけ入力欄になっているのが見えるだけで、ほかは全然見えない。スクロールバーも表示されないのでどうしようもない。

vista_bug1_05.gif
さらにその状態でウインドウ内をクリックすると何も表示されなくなってしまう。表示を元に戻すには[F5]キーを押すなどして画面表示を更新する。

ちなみにこの現象はファイルを削除したときなど様々なファイル操作時に同じように起こる。私はエクスプローラーを常に一覧表示モードにしているので本当に不便。


CAtlFileでUTF-8形式のテキストファイルを読み込む

test117.gif
ここではATLに備わるファイル操作用のクラス「CAtlFile」を利用してUTF-8形式のテキストファイルを読み込み、メッセージボックスに表示した。

UTF-8からユニコードへの変換にはMultiByteToWideCharを利用する。

依存環境:ATL
#include <atlfile.h>


//
//	UTF8文字列を普通のユニコード文字列に変換する
//
//CP_UTF8はWindows98では利用できない?
//
WCHAR*	ConvertUTF8ToUnicode(const char* pszUTF8)
{
	int		nLen;
	WCHAR*	pszWchar;

	//Unicodeに必要な文字数の取得
	nLen = ::MultiByteToWideChar(CP_UTF8,0,pszUTF8,-1,NULL,0);
	pszWchar = new WCHAR[nLen];
	if(pszWchar == NULL)
		return	NULL;

	//変換
	nLen = ::MultiByteToWideChar(CP_UTF8,0,pszUTF8,(int)::strlen(pszUTF8)+1,pszWchar,nLen);
	if(nLen)
		return	pszWchar;

	delete	pszWchar;

	return	NULL;
}







bool	Test()
{
	bool		ret;
	HRESULT		hr;
	ULONGLONG	nLen;
	CAtlFile	cFile;

	//ファイルを読み込みモードで開く
	hr = cFile.Create(_T("テスト.txt"),GENERIC_READ,FILE_SHARE_READ,OPEN_EXISTING);
	if(FAILED(hr))
		return	false;	//ファイルを開くのに失敗

	//ファイルサイズを取得
	hr = cFile.GetSize(nLen);

	ret = false;
	if(SUCCEEDED(hr))
	{
		char*	pszBuff;

		pszBuff = new char[(size_t)nLen + 1];
		if(pszBuff)
		{
			//ファイルにはNULL文字がないので付加しておく
			pszBuff[nLen] = NULL;

			//ファイルを読み込む
			hr = cFile.Read(pszBuff,(DWORD)nLen);

			//読み込んだ内容をメッセージボックスで表示
			if(SUCCEEDED(hr))
			{
				WCHAR*	pwszBuff;

				//UTF8をUnicodeに変換
				pwszBuff = ConvertUTF8ToUnicode(pszBuff);

				if(pwszBuff)
				{
					//このメッセージボックス関数は基本的にWindows 9xでは使えないので注意!
					::MessageBoxW(NULL,pwszBuff,L"",MB_OK);
					ret = true;

					delete	pwszBuff;
				}
			}

			delete	pszBuff;
		}
	}

	//ファイルを閉じる
	cFile.Close();

	return	ret;
}


プロジェクトファイルをダウンロード

CAtlFileでユニコード形式のテキストファイルを読み込む

test116.gif
ここではATLに備わるファイル操作用のクラス「CAtlFile」を利用してユニコード形式のテキストファイルを読み込み、メッセージボックスに表示した。

ユニコード文字列を読み込む際に注意すべき点はファイルサイズ=文字長という関係が成り立たないという点だ。

依存環境:ATL
#include <atlfile.h>


bool	Test()
{
	bool		ret;
	HRESULT		hr;
	ULONGLONG	nLen;
	CAtlFile	cFile;

	//ファイルを読み込みモードで開く
	hr = cFile.Create(_T("テスト.txt"),GENERIC_READ,FILE_SHARE_READ,OPEN_EXISTING);
	if(FAILED(hr))
		return	false;	//ファイルを開くのに失敗

	//ファイルサイズを取得
	hr = cFile.GetSize(nLen);

	ret = false;
	if(SUCCEEDED(hr))
	{
		//ユニコードモードで読み込みたいのでWCHARでバッファーを確保
		WCHAR*	pszBuff;

		//ファイルサイズ=WCHARの数というわけではなないので、BYTEでメモリを確保してキャスト
		pszBuff = (WCHAR*)new BYTE[(size_t)nLen + sizeof(WCHAR)];
		if(pszBuff)
		{
			//ファイルにはNULL文字がないので付加しておく
			((BYTE*)pszBuff)[nLen+0] = NULL;
			((BYTE*)pszBuff)[nLen+1] = NULL;

			//ファイルを読み込む
			hr = cFile.Read(pszBuff,(DWORD)nLen);

			//読み込んだ内容をメッセージボックスで表示
			if(SUCCEEDED(hr))
			{
				//このメッセージボックス関数は基本的にWindows 9xでは使えないので注意!
				::MessageBoxW(NULL,pszBuff,L"",MB_OK);
				ret = true;
			}

			delete	pszBuff;
		}
	}

	//ファイルを閉じる
	cFile.Close();

	return	ret;
}

プロジェクトファイルをダウンロード

CAtlFileでテキストファイルを読み込む

test115.gif
ここではATLに備わるファイル操作用のクラス「CAtlFile」を利用してテキストファイルを読み込み、メッセージボックスに表示した。

テキストファイルを読み込むときに一番注意するべき点は「文字コード」。Windows 9x時代にはほとんどのテキストファイルが通常のシフトJIS(SHIFT-JIS)で書かれていたためあまり注意する必要はなかった。

しかしインターネットやWindows XP/Vistaが普及するに連れてテキストファイルがシフトJISではなく、(まだまだ少ないものの)ユニコードやUTF-8で書かれるケースが増えてきた。また最近ではVisual Studioでアプリケーションをビルドするときに「ユニコードビルド」することも多い。

特にユニコードビルドをしている場合には意図せずにシフトJISのテキストファイルをユニコード形式で扱ってしまい、読み込んだファイルが文字化けしてしまうトラブルも起こりえるので注意が必要だ。


依存環境:ATL
#include <atlfile.h>


bool	Test()
{
	bool		ret;
	HRESULT		hr;
	ULONGLONG	nLen;
	CAtlFile	cFile;

	//ファイルを読み込みモードで開く
	hr = cFile.Create(_T("テスト.txt"),GENERIC_READ,FILE_SHARE_READ,OPEN_EXISTING);
	if(FAILED(hr))
		return	false;	//ファイルを開くのに失敗

	//ファイルサイズを取得
	hr = cFile.GetSize(nLen);

	ret = false;
	if(SUCCEEDED(hr))
	{
		//SHIFT-JISモードで読み込みたいのでcharでバッファーを確保
		char*	pszBuff;

		pszBuff = new char[(size_t)nLen + 1];
		if(pszBuff)
		{
			//ファイルにはNULL文字がないので付加しておく
			pszBuff[nLen] = NULL;

			//ファイルを読み込む
			hr = cFile.Read(pszBuff,(DWORD)nLen);

			//読み込んだ内容をメッセージボックスで表示
			if(SUCCEEDED(hr))
			{
				ret = true;
				::MessageBoxA(NULL,pszBuff,"",MB_OK);
			}

			delete	pszBuff;
		}
	}


	//ファイルを閉じる
	cFile.Close();

	return	ret;
}

プロジェクトファイルをダウンロード

2007年02月13日

フォルダをツリーコントロールに一覧する

test114.gif
ここでは特定のフォルダ内に存在するサブフォルダを一覧する簡易的なツリーコントロールクラスを作成した。

このクラスはかなり制限が多く、実装に癖があるので"実用"する場合はゼロから作り直した方が早いだろう。
トップレベルのフォルダは1つのみで、シェルフォルダやアイコンの表示機能などはない。
またフォルダがサブフォルダを持つ場合に、ツリーコントロール上で「+」マークが表示されるように、ツリーを開く際にその都度、孫フォルダまで取得している。これは本来スレッドを立ててマルチタスクに読み込むべき処理だが、そのまま簡単に読み込んでいる。



■ATL/WTLアプリケーションウイザードでダイアログベースのプロジェクトを作成する。

■リソースエディタでメインダイアログの大きさを適当に大きくする。

■MainDlg.hの先頭にクラス定義などを追加

#include "atlstr.h"
#include "atlcoll.h"


class	CDnpFolderTreeCtrl	: public CTreeViewCtrl
{
protected:
	CAtlString	_strRootName;
	CAtlString	_strRootPath;
public:

	BEGIN_MSG_MAP(CDnpFolderTreeCtrl)
		NOTIFY_CODE_HANDLER(TVN_ITEMEXPANDING,OnItemExpanding)
	END_MSG_MAP()
 

	bool	Initialize(LPCTSTR pszRootName,LPCTSTR pszRootPath)
	{
		bool		ret;
		HTREEITEM	hRoot;
		CAtlString	strPath;
		CAtlArray<CAtlString>	astrFolder;

		if(pszRootName == NULL || pszRootPath == NULL)
			return	false;
		if(*pszRootName == NULL || *pszRootPath == NULL)
			return	false;

		DeleteAllItems();

		strPath = pszRootPath;
		if(strPath.Right(1) != _T("\\") && strPath.Right(1) != _T("/"))
			strPath += _T("\\");

		_strRootName = pszRootName;
		_strRootPath = strPath;

		hRoot = InsertItem(pszRootName,TVI_ROOT,TVI_LAST);
		if(hRoot == NULL)
			return	false;

		ret = GetFolderList(_strRootPath,astrFolder);
		if(ret)
			ret = AddTreeFolder(hRoot,astrFolder,_strRootPath,0);
		if(ret == false)
			return	false;

		Expand(hRoot);

		return	ret;
	}


	//
	//	ツリーアイテムの示すフォルダへのパス取得
	//
	bool	GetPath(HTREEITEM hItem,CAtlString& strPath)
	{
		BOOL	ret;
		TCHAR	pszBuff[MAX_PATH];
		CAtlString	strBuff;

		//本来ならばITEMDATAを利用してフォルダパスを保存しておくべきだが
		//ここではツリーに登録したツリーアイテム名からパスを復元している
		strPath = _T("");
		while(1)
		{
			ret = GetItemText(hItem,pszBuff,MAX_PATH);
			if(ret == FALSE)
				return	false;
			strBuff = pszBuff;
			strBuff += _T("\\");
			strPath = strBuff + strPath;

			hItem = GetParentItem(hItem);
			if(hItem == NULL)
				break;
		}

		//先頭がルート名になっているはず
		if(strPath.Find(_strRootName) != 0)
		{
			strPath = _T("");
			return	false;
		}

		//先頭のルート名部分をルートパスへ置き換える
		strPath = strPath.Right(strPath.GetLength() - _strRootName.GetLength() - 1);
		strPath = _strRootPath + strPath;

		return	true;
	}



protected:

	//
	//ツリーアイテムを開いているときの処理
	//
	//孫アイテムが登録されていない場合は孫を登録する
	//
	LRESULT OnItemExpanding(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
	{
		LPNMTREEVIEW	pNmTreeView = (LPNMTREEVIEW)pnmh;

		if(pNmTreeView == NULL)
			return	0;

		//ツリーが閉じるだけなら処理はなし
		if(pNmTreeView->action == TVE_COLLAPSE)
			return	0;


		bool		ret;
		HTREEITEM	hItem;
		CAtlString	strPath;

		//開かれようとしているフォルダのパスを取得
		hItem = pNmTreeView->itemNew.hItem;
		ret = GetPath(hItem,strPath);
		if(ret == false)
			return	0;


		//孫フォルダー情報までツリーに登録されているかどうか
		if(IsLoadedFolder(hItem))
			return	0;


		BOOL		bRet;
		HTREEITEM	hChildItem;
		TCHAR		pszBuff[MAX_PATH];

		//これから開くツリーの子を列挙。孫フォルダーがツリーに内場合は追加
		hChildItem = GetChildItem(pNmTreeView->itemNew.hItem);
		while(GetParentItem(hChildItem) == hItem)
		{
			if(GetChildItem(hChildItem))
				break;

			bRet = GetItemText(hChildItem,pszBuff,MAX_PATH);
			if(bRet == FALSE)
				return	0;

			//フォルダ情報をツリーに追加
			{
				CAtlString	strBuff;
				CAtlArray<CAtlString>	astrChildFolder;

				//孫フォルダーリスト取得
				strBuff = strPath + pszBuff;
				ret = GetFolderList(strBuff,astrChildFolder);

				//ツリーに追加
				if(ret)
					AddTreeFolder(hChildItem,astrChildFolder);
			}

			hChildItem = GetNextItem(hChildItem,TVGN_NEXTVISIBLE);
			if(hChildItem == NULL)
				break;
		}

		return	0;
	}








	//
	//	hParentの子フォルダーはその子フォルダー情報を持っているかどうか
	//
	bool	IsLoadedFolder(HTREEITEM hParent)
	{
		HTREEITEM	hChildItem;

		hChildItem = GetChildItem(hParent);
		while(GetParentItem(hChildItem) == hParent)
		{
			if(GetChildItem(hChildItem))
				return	true;

			hChildItem = GetNextItem(hChildItem,TVGN_NEXTVISIBLE);
			if(hChildItem == NULL)
				break;
		}

		return	false;
	}









	bool	AddTreeFolder(HTREEITEM hParent,const CAtlArray<CAtlString>& astrFolderName,LPCTSTR pszPath=NULL,int nAddChild=0)
	{
		size_t		i;
		size_t		nSize;
		HTREEITEM	hChild;

		if(pszPath == NULL && nAddChild)
			return	false;		//pszPath==NULLのときはnAddChild==0でないとダメ

		nSize = astrFolderName.GetCount();
		for(i = 0; i < nSize; i++)
		{
			hChild = InsertItem(astrFolderName[i],hParent,TVI_LAST);
			if(hChild == NULL)
				continue;

			if(nAddChild == 0)
				continue;

			bool		ret;
			CAtlString	strPath;
			CAtlArray<CAtlString>	astrChildFolder;

			strPath = pszPath;
			strPath += astrFolderName[i];
			strPath += _T("\\");
			ret = GetFolderList(strPath,astrChildFolder);
			if(ret == false)
				continue;

			AddTreeFolder(hChild,astrChildFolder,strPath,nAddChild - 1);
		}

		return	true;
	}


	//
	//	ソート用仮想関数
	//
	//派生クラスでastrFolderName[nFirstIndex]からnCountの数だけ任意の方法で並べ替える
	//
	virtual	bool	SortData(CAtlArray<CAtlString>& astrFolderName,size_t nFirstIndex,size_t nCount)
	{
		return	true;
	}


	//
	//	フォルダの列挙
	//
	//指定したフォルダ内のフォルダを列挙します。
	//	pszPath内のフォルダを列挙してastrFolderName配列へ追加する
	//
	bool	GetFolderList(LPCTSTR pszPath,CAtlArray<CAtlString>& astrFolderName)
	{
		BOOL			bFind;
		HANDLE			hFind;
		WIN32_FIND_DATA	FindFileData;
		CAtlString		strFolder;

		if(pszPath == NULL || _tcslen(pszPath) == 0)
			return	false;

		strFolder = pszPath;
		if(strFolder.Right(1) != _T('\\') && strFolder.Right(1) != _T('/'))
			strFolder += _T("\\");

		hFind = ::FindFirstFile(strFolder + _T("*.*"),&FindFileData);
		if(hFind == INVALID_HANDLE_VALUE)
			return	false;

		size_t	nBefore;
		size_t	nAfter;

		nBefore = astrFolderName.GetCount();

		bFind = TRUE;
		while(bFind)
		{
			if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
			{
				//リンクフォルダや隠しフォルダは表示しない
				if((FindFileData.dwFileAttributes & (FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_HIDDEN)) == 0)
					if(_tcsncmp(FindFileData.cFileName,_T("."),1) != 0 && _tcsncmp(FindFileData.cFileName,_T(".."),2) != 0 )
						astrFolderName.Add(FindFileData.cFileName);
			}

			bFind = ::FindNextFile(hFind,&FindFileData);
		}
		::FindClose(hFind);

		nAfter = astrFolderName.GetCount();

		if(nAfter == nBefore)
			return	true;

		return	SortData(astrFolderName,nBefore + 1,nAfter - nBefore);
	}
};
■MainDlg.hのCMainDlgにメンバー変数を追加
	CDnpFolderTreeCtrl	_wndTree;
■MainDlg.hのCMainDlgのメッセージマップとOnInitDialogに追加
	BEGIN_MSG_MAP(CMainDlg)
(。。。省略。。。)
		CHAIN_MSG_MAP_MEMBER(_wndTree)
	END_MSG_MAP()

	LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
	{

(。。。省略。。。)
		RECT	rect;		

		GetClientRect(&rect);
		rect.top += 10;
		rect.bottom -= 10;
		rect.left += 10;
		rect.right -=100;

		_wndTree.Create(m_hWnd,rect,NULL,WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TVS_HASBUTTONS | TVS_HASLINES,WS_EX_CLIENTEDGE | WS_EX_CONTROLPARENT); 
		_wndTree.Initialize(_T("cドライブ"),_T("c:\\"));

		return TRUE;
	}


プロジェクトファイルをダウンロード

前の10件 6  7  8  9  10  11  12  13  14  15  16