티스토리 뷰

Visual Studio 2012


CListCtrl 을 활용해서 리스트에 있는 내용을 클립보드로 복사하기


1. 클립보드 복사 함수


함수 원형은 다음과 같다.

매개변수는 CListCtrl 포인터와 클립보드 저장 시 셀의 데이터를 나누는 기준(기본값 은 탭[\t])


// ...
BOOL		CopyListToClipboard(CListCtrl* pListCtrl, LPCTSTR lpszSeparator = _T("\t"));
//...


함수 소스코드는 아래를 참조한다.

클래스이름에 본인이 쓰려는 클래스 이름을 넣으면 된다.

리스트에서 컬럼 제목과 선택된 리스트 데이터들을 클립보드에 복사하는 내용이다.


// ...
BOOL 클래스이름::CopyListToClipboard(CListCtrl* pListCtrl, LPCTSTR lpszSeparator /*= _T("\t")*/)
{
	ASSERT(pListCtrl && ::IsWindow(pListCtrl->GetSafeHwnd()));

	CString sResult;
	POSITION pos = pListCtrl->GetFirstSelectedItemPosition();
	if (!pos)
		return TRUE;

	CWaitCursor wait;
	int nItem, nCount = 0;
	int nColumn = 1;

	//컬럼 이름 관련 구조체
	TCHAR szName[128]; // This is the buffer where the name will be stored
	LVCOLUMN lvColInfo;
	lvColInfo.mask = LVCF_TEXT;
	lvColInfo.pszText = szName;
	lvColInfo.cchTextMax = _countof(szName);

	//헤더와 컬럼 갯수 구하기
	if ((pListCtrl->GetStyle() & LVS_TYPEMASK) == LVS_REPORT &&
		pListCtrl->GetExtendedStyle() & LVS_EX_FULLROWSELECT)
	{
		CHeaderCtrl* pHeader = pListCtrl->GetHeaderCtrl();
		nColumn = pHeader ? pHeader->GetItemCount() : 1;
	}

	//컬럼 이름 삽입
	for (int i = 0; i < nColumn; ++i)
	{
		pListCtrl->GetColumn(i, &lvColInfo);

		sResult += lvColInfo.pszText;
		if (i != nColumn - 1)
			sResult += lpszSeparator;
	}
	sResult += _T("\r\n");

	//데이터 내용 삽입
	while (pos)
	{
		nItem = pListCtrl->GetNextSelectedItem(pos);
		if (0 != nCount)
			sResult += _T("\r\n");

		for (int i = 0; i < nColumn; ++i)
		{
			sResult += pListCtrl->GetItemText(nItem, i);
			if (i != nColumn - 1)
				sResult += lpszSeparator;
		}
		++nCount;
	}
	sResult += _T("\r\n");

	//클립보드 저장
	if (pListCtrl->OpenClipboard())
	{
		EmptyClipboard();

		int nLen = sResult.GetLength() * sizeof(WCHAR) + 1;
		HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, nLen);
		LPBYTE pGlobalData = (LPBYTE)GlobalLock(hGlobal);

		USES_CONVERSION_EX;
		CopyMemory(pGlobalData, T2CW_EX(sResult, _ATL_SAFE_ALLOCA_DEF_THRESHOLD), nLen);
		SetClipboardData(CF_UNICODETEXT, hGlobal);

		GlobalUnlock(hGlobal);
		GlobalFree(hGlobal);

		CloseClipboard();
		return TRUE;
	}
	return FALSE;
}
//...


위의 함수를 사용할 때는 아래와 같이 사용하면 된다.


// ...
CopyListToClipboard(&m_ctrlList);
//...


2. Ctrl+C 기능 구현하기


구현할 클래스에서 클래스 위자드를 열어서 가상함수 탭의 PreTranslateMessage 함수를 추가한다.

WM_KEYDOWN을 통해 C버튼이 눌렸는지 확인하고 GetKeyState(VK_CONTROL)을 통해 컨트롤키가 눌려있는지 확인한다.

처음에는 키 누르는 것에 따라 스탭을 줘서 구현해봤는데 작동이 제대로 되지 않았다..

if(pMsg->hwnd == m_CtrlList.GetSafeHwnd() && GetFocus()->GetSafeHwnd() == m_CtrlList.GetSafeHwnd()) 는 현재 메세지를 보내온 주체가 해당 리스트에서 온것인지를 파악하기 위해 사용한다.

함수의 소스는 다음과 같다.


// ...
BOOL 클래스이름::PreTranslateMessage(MSG* pMsg)
{
	if(pMsg->message == WM_KEYDOWN)
	{
		switch (pMsg->wParam)
		{
		case 'C':
			if(GetKeyState(VK_CONTROL)<0)
			{
				if(pMsg->hwnd == m_CtrlList.GetSafeHwnd() &&
					GetFocus()->GetSafeHwnd() == m_CtrlList.GetSafeHwnd())
				{
					CopyListToClipboard(&m_CtrlList);
				}
			}
			return true;
		default:
			break;
		}
	}
	return CDialog::PreTranslateMessage(pMsg);
}
//...


댓글