반응형
리스트 컨트롤 스타일중 Report 로 이용시 컬럼 내부에 콤보 박스를 넣는 방법에 대해서 소개합니다.
버튼이나 특정 이벤트를 통해서 컬럼의 값을 변경하는 것이 아닌, 콤보 박스를 이용하여 리스트 컨트롤 내부에서 컬럼의 값을 변경한다는 것은 상당히 큰 매리트가 있습니다.
소스는 두개의 클래스로 되어있습니다. CListCtrl 을 상속받는 클래스(이하 CAdvListCtrl)와, CComboBox를 상속받는 클래스(이하 CAdvComboBox)입니다.
CAdvListCtrl 클래스의 경우엔 CAdvComboBox에서 발생하는 주요 이벤트 (Selection 변경, 키 입력, 포커스 드롭 등)를 받아 컬럼 내용을 처리해주는데 주 목적이 있습니다. 물론 리스트 컨트롤 포커싱(마우스클릭 등 포커스가 잡혔을때)시 CAdvComboBox 를 생성 혹은 삭제 해주는 역할도 있습니다.
CComboBox 의 경우 위에 한번 언급한 주요 이벤트 발생시 CAdvListCtrl 로 이벤트를 날려주는데 주 목적이 있습니다.
본 소스는 ComboBox 아이템이 하드코딩 되어있는데, 조만간 손을 봐서 아이템도 사용자가 원하는데로 추가 기입이 가능하도록 할 생각입니다.
AdvListCtrl.h
- #pragma once
- class CAdvListCtrl : public CListCtrl
- {
- DECLARE_DYNAMIC(CAdvListCtrl)
- public:
- CAdvListCtrl();
- virtual ~CAdvListCtrl();
- afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
- afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
- afx_msg void OnLvnEndlabeledit(NMHDR *pNMHDR, LRESULT *pResult);
- afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
- afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
- int HitTestEx(CPoint& point, int* nCol) const;
- void SetColumnCombo(int nColumn);
- protected:
- DECLARE_MESSAGE_MAP()
- int m_nColumn;
- CComboBox* ShowAdvComboBox(int nItem, int nCol, CStringList& lstItems, int nSel);
- };
AdvListCtrl.cpp
- #include "stdafx.h"
- #include "AdvListCtrl.h"
- #include "AdvComboBox.h"
- IMPLEMENT_DYNAMIC(CAdvListCtrl, CListCtrl)
- CAdvListCtrl::CAdvListCtrl()
- {
- m_nColumn = -1;
- }
- CAdvListCtrl::~CAdvListCtrl()
- {
- }
- BEGIN_MESSAGE_MAP(CAdvListCtrl, CListCtrl)
- ON_WM_HSCROLL()
- ON_WM_VSCROLL()
- ON_NOTIFY_REFLECT(LVN_ENDLABELEDIT, &CAdvListCtrl::OnLvnEndlabeledit)
- ON_WM_LBUTTONDOWN()
- ON_WM_LBUTTONUP()
- END_MESSAGE_MAP()
- void CAdvListCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
- {
- if(GetFocus() != this) SetFocus();
- CListCtrl::OnHScroll(nSBCode, nPos, pScrollBar);
- }
- void CAdvListCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
- {
- if(GetFocus() != this) SetFocus();
- CListCtrl::OnVScroll(nSBCode, nPos, pScrollBar);
- }
- void CAdvListCtrl::OnLvnEndlabeledit(NMHDR *pNMHDR, LRESULT *pResult)
- {
- NMLVDISPINFO *pDispInfo = reinterpret_cast<NMLVDISPINFO*>(pNMHDR);
- LVITEMW* pItem = &pDispInfo->item;
- if(pItem->pszText != NULL)
- {
- SetItemText(pItem->iItem, pItem->iSubItem, pItem->pszText);
- }
- *pResult = 0;
- }
- void CAdvListCtrl::OnLButtonDown(UINT nFlags, CPoint point)
- {
- int nIndex;
- CListCtrl::OnLButtonDown(nFlags, point);
- int nColumn;
- if((nIndex = HitTestEx(point, &nColumn)) != -1)
- {
- UINT flag = LVIS_FOCUSED;
- if((GetItemState(nIndex, flag) & flag) == flag && m_nColumn == nColumn)
- {
- if(!(GetWindowLong(m_hWnd, GWL_STYLE) & LVS_EDITLABELS))
- {
- CStringList lstItems;
- lstItems.AddTail(L"Item 1");
- lstItems.AddTail(L"Item 2");
- CString strGet = this->GetItemText(nIndex, m_nColumn);
- ShowAdvComboBox(nIndex, m_nColumn, lstItems, 0);
- SetItemState(nIndex, LVIS_SELECTED, LVIS_SELECTED);
- }
- }
- else
- {
- SetItemState(nIndex, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
- }
- }
- // CListCtrl::OnLButtonDown(nFlags, point);
- }
- void CAdvListCtrl::OnLButtonUp(UINT nFlags, CPoint point)
- {
- // CListCtrl::OnLButtonUp(nFlags, point);
- }
- int CAdvListCtrl::HitTestEx(CPoint& point, int* nCol) const
- {
- int nColumn = 0;
- int nRow = HitTest(point, NULL);
- if(nCol) *nCol = 0;
- // LVS_REPORT Check
- if((GetWindowLong(m_hWnd, GWL_STYLE) & LVS_TYPEMASK) != LVS_REPORT)
- return nRow;
- nRow = GetTopIndex();
- int nBottom = nRow + GetCountPerPage();
- if(nBottom > GetItemCount())
- nBottom = GetItemCount();
- CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
- int nColumnCount = pHeader->GetItemCount();
- for(; nRow <= nBottom; ++nRow)
- {
- CRect rect;
- GetItemRect(nRow, &rect, LVIR_BOUNDS);
- if(rect.PtInRect(point))
- {
- for(nColumn = 0; nColumn < nColumnCount; ++nColumn)
- {
- int nColWidth = GetColumnWidth(nColumn);
- if(point.x >= rect.left && point.x <= (rect.left + nColWidth))
- {
- if(nCol) *nCol = nColumn;
- return nRow;
- }
- rect.left += nColWidth;
- }
- }
- }
- return -1;
- }
- void CAdvListCtrl::SetColumnCombo(int nColumn)
- {
- m_nColumn = nColumn;
- }
- CComboBox* CAdvListCtrl::ShowAdvComboBox(int nItem, int nCol, CStringList& lstItems, int nSel)
- {
- if(!EnsureVisible(nItem, TRUE)) return NULL;
- CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
- int nColumnCount = pHeader->GetItemCount();
- if(nCol >= nColumnCount || GetColumnWidth(nCol) < 10)
- return NULL;
- int offset = 0;
- for(int i = 0; i < nCol; ++i)
- {
- offset += GetColumnWidth(i);
- }
- CRect rect;
- GetItemRect(nItem, &rect, LVIR_BOUNDS);
- CRect rcClient;
- GetClientRect(&rcClient);
- if(offset + rect.left < 0 || offset + rect.left > rcClient.right)
- {
- CSize size;
- size.cx = offset + rect.left;
- size.cy = 0;
- Scroll(size);
- rect.left -= size.cx;
- }
- rect.left += offset + 4;
- rect.right = rect.left + GetColumnWidth(nCol) - 3;
- int nHeight = rect.bottom - rect.top;
- rect.bottom += 5 * nHeight;
- if(rect.right > rcClient.right) rect.right = rcClient.right;
- DWORD dwStyle = WS_BORDER | WS_CHILD | WS_VISIBLE |
- CBS_DROPDOWNLIST | CBS_DISABLENOSCROLL;
- CComboBox* pList = new CAdvComboBox(nItem, nCol, &lstItems, nSel);
- pList->Create(dwStyle, rect, this, IDC_ADVCOMBO);
- pList->SetItemHeight(-1, nHeight);
- pList->SetHorizontalExtent(GetColumnWidth(nCol));
- return pList;
- }
AdvComboBox.h
- #pragma once
- class CAdvComboBox : public CComboBox
- {
- DECLARE_DYNAMIC(CAdvComboBox)
- public:
- CAdvComboBox(int nItem, int nSubItem, CStringList* plstItems, int nSel);
- virtual ~CAdvComboBox();
- virtual BOOL PreTranslateMessage(MSG* pMsg);
- protected:
- DECLARE_MESSAGE_MAP()
- public:
- afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
- afx_msg void OnKillFocus(CWnd* pNewWnd);
- afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
- afx_msg void OnNcDestroy();
- afx_msg void OnCloseUp();
- private:
- int m_nItem;
- int m_nSubItem;
- CStringList m_lstItems;
- int m_nSel;
- bool m_bESC;
- };
AdvComboBox.cpp
- #include "stdafx.h"
- #include "AdvComboBox.h"
- IMPLEMENT_DYNAMIC(CAdvComboBox, CComboBox)
- CAdvComboBox::CAdvComboBox(int nItem, int nSubItem, CStringList* plstItems, int nSel)
- : m_nItem(nItem)
- , m_nSubItem(nSubItem)
- , m_nSel(nSel)
- , m_bESC(false)
- {
- m_lstItems.AddTail(plstItems);
- }
- CAdvComboBox::~CAdvComboBox()
- {
- }
- BEGIN_MESSAGE_MAP(CAdvComboBox, CComboBox)
- ON_WM_CREATE()
- ON_WM_KILLFOCUS()
- ON_WM_CHAR()
- ON_WM_NCDESTROY()
- ON_CONTROL_REFLECT(CBN_CLOSEUP, OnCloseUp)
- END_MESSAGE_MAP()
- BOOL CAdvComboBox::PreTranslateMessage(MSG* pMsg)
- {
- if(pMsg->message == WM_KEYDOWN)
- {
- if(pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE)
- {
- ::TranslateMessage(pMsg);
- ::DispatchMessage(pMsg);
- return TRUE;
- }
- }
- return CComboBox::PreTranslateMessage(pMsg);
- }
- int CAdvComboBox::OnCreate(LPCREATESTRUCT lpCreateStruct)
- {
- if (CComboBox::OnCreate(lpCreateStruct) == -1)
- return -1;
- CFont* pFont = GetParent()->GetFont();
- SetFont(pFont);
- for(POSITION pos = m_lstItems.GetHeadPosition(); pos != NULL; )
- {
- AddString((LPCTSTR)(m_lstItems.GetNext(pos)));
- }
- SetCurSel(m_nSel);
- SetFocus();
- return 0;
- }
- void CAdvComboBox::OnKillFocus(CWnd* pNewWnd)
- {
- CComboBox::OnKillFocus(pNewWnd);
- CString strTemp;
- GetWindowText(strTemp);
- LV_DISPINFO dispinfo;
- dispinfo.hdr.hwndFrom = GetParent()->m_hWnd;
- dispinfo.hdr.idFrom = GetDlgCtrlID();
- dispinfo.hdr.code = LVN_ENDLABELEDIT;
- dispinfo.item.mask = LVIF_TEXT;
- dispinfo.item.iItem = m_nItem;
- dispinfo.item.iSubItem = m_nSubItem;
- dispinfo.item.pszText = m_bESC ? NULL : LPTSTR((LPCTSTR)strTemp);
- dispinfo.item.cchTextMax= strTemp.GetLength();
- GetParent()->GetParent()->SendMessage(WM_NOTIFY, GetParent()->GetDlgCtrlID(), (LPARAM)&dispinfo);
- PostMessage(WM_CLOSE);
- }
- void CAdvComboBox::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
- {
- if(nChar == VK_ESCAPE || nChar == VK_RETURN)
- {
- if(nChar == VK_ESCAPE)
- {
- m_bESC = true;
- }
- GetParent()->SetFocus();
- return;
- }
- CComboBox::OnChar(nChar, nRepCnt, nFlags);
- }
- void CAdvComboBox::OnNcDestroy()
- {
- CComboBox::OnNcDestroy();
- delete this;
- }
- void CAdvComboBox::OnCloseUp()
- {
- GetParent()->SetFocus();
- }
반응형
'C & C++ > MFC 컨트롤' 카테고리의 다른 글
[List] List 컨트롤 원하는 항목 수정 (0) | 2011.05.04 |
---|---|
[List] List 컨트롤에 비트맵 이미지 셋팅 (0) | 2011.05.04 |
[List] 리스트 컨트롤에 색상입히기 (0) | 2011.05.04 |
[Tab] 탭 설정 (0) | 2011.04.28 |
[Button] 버튼에 아이콘, 이미지 적용 2 (0) | 2011.04.28 |
댓글