출처 :: http://mnlt.tistory.com/131
ListControl은 MFC에서 굉장히 유용
히 쓰이는 컨트롤입니다.
해당 컨트롤에서 직접 원하는 위치를 즉석 수정하기 위한 컨트롤을 만들었습니다.
아마 그냥 유용하게 쓰일듯 싶기도 해서 포스팅.
//EditListCtrl.h #pragma once // CEditListCtrl class CEditListCtrl : public CListCtrl { DECLARE_DYNAMIC(CEditListCtrl) public: CEditListCtrl(); virtual ~CEditListCtrl(); protected: DECLARE_MESSAGE_MAP() public: virtual BOOL PreTranslateMessage(MSG* pMsg); afx_msg void OnNMClick(NMHDR *pNMHDR, LRESULT *pResult); // 초기화 함수. void Init(void); // CEditListCtrl 을 사용하는 Dialog 의 OnOK 함수가 호출될때 호출해야 한다. void OnOK(void); // List 값을 바꾼다. BOOL SetText(CString _val, int _row, int _col); protected: // ListCtrl 을 클릭했을때 nItem 저장될 변수. (Row) int m_nItem; // ListCtrl 을 클릭했을때 nSubItem 저장될 변수 (Col); int m_nSubItem; // 현재 포커스가 어딘지 확인하는 변수 HWND m_hFocus; bool m_bInit; HWND _GetEditHwnd(void); HWND _GetListHwnd(void); HWND _GetParentHwnd(void); }; //EditListCtrl.cpp // EditListCtrl.cpp : 구현 파일입니다. // #include "stdafx.h" #include "TestApp.h" #include "EditListCtrl.h" // CEditListCtrl IMPLEMENT_DYNAMIC(CEditListCtrl, CListCtrl) CEditListCtrl::CEditListCtrl() : m_nItem(0), m_nSubItem(0) , m_bInit(false) , m_hFocus((HWND)0) { } CEditListCtrl::~CEditListCtrl() { } BEGIN_MESSAGE_MAP(CEditListCtrl, CListCtrl) ON_NOTIFY_REFLECT(NM_CLICK, &CEditListCtrl::OnNMClick) END_MESSAGE_MAP() // CEditListCtrl 메시지 처리기입니다. BOOL CEditListCtrl::PreTranslateMessage(MSG* pMsg) { if(m_hFocus != (HWND)0) { HWND hFocus = ::GetFocus(); // Edit 가 Focus를 잃으면. if(m_hFocus != hFocus) { OnOK(); } } return CListCtrl::PreTranslateMessage(pMsg); } void CEditListCtrl::Init(void) { if(m_bInit) return; SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES); ::ShowWindow(_GetEditHwnd(), SW_HIDE); m_bInit = true; } // Return 키가 눌렸을때 호출하기 위한.. void CEditListCtrl::OnOK(void) { CWnd* pWnd = GetFocus(); if(_GetEditHwnd() == pWnd->GetSafeHwnd() || _GetEditHwnd() == m_hFocus) { // EditCtrl로 부터 Text를 얻어온다. wchar_t cText[255]; ZeroMemory(cText, 255); ::GetWindowText(_GetEditHwnd(), cText, 255); CString cStrText(cText); // 얻어온 텍스트를 ListCtrl 에 적용시킨다 if(SetText(cStrText, m_nItem, m_nSubItem) == FALSE) return; // EditCtrl의 Focus를 죽인다. ::SendMessage(_GetEditHwnd(), WM_KILLFOCUS, 0, 0); ::ShowWindow(_GetEditHwnd(), SW_HIDE); ::SetFocus(pWnd->GetSafeHwnd()); // ListCtrl의 SelectionMark를 지정한다. SetSelectionMark(m_nItem); } m_hFocus = (HWND)0; } BOOL CEditListCtrl::SetText(CString _val, int _row, int _col) { return SetItemText(_row, _col, _val); } void CEditListCtrl::OnNMClick(NMHDR *pNMHDR, LRESULT *pResult) { Invalidate(); LPNMITEMACTIVATE pNMITEM = (LPNMITEMACTIVATE) pNMHDR; m_nItem = pNMITEM->iItem; m_nSubItem = pNMITEM->iSubItem; // 선택된 지점이 올바르지 않을시... if(m_nSubItem == 0 || m_nSubItem == -1 || m_nItem == -1) return; // 선택된 SubItem의 Text를 CEdit 에 넣어주기 위한 변수 CString cStrText = GetItemText(m_nItem, m_nSubItem); CRect rtSubItem, rtListCtrl, rtDlg; // SubItem 의 Rect를 얻어온다. if(GetSubItemRect(pNMITEM->iItem, pNMITEM->iSubItem, LVIR_BOUNDS, rtSubItem) == FALSE) return; // ListControl 의 Window Bounds 를 얻어온다. ::GetWindowRect(_GetListHwnd(), &rtListCtrl); // Parent Dialog 의 Windows Bounds 를 얻어온다. ::GetWindowRect(_GetParentHwnd(), &rtDlg); // Dialog에 위치한 ListCtrl의 left & top 위치를 구한다. int nThisLeft = rtListCtrl.left - rtDlg.left; int nThisTop = rtListCtrl.top - rtDlg.top; // EditCtrl의 위치를 변경해준다. ::SetWindowPos( _GetEditHwnd(), HWND_TOP, nThisLeft + rtSubItem.left + 7, nThisTop + rtSubItem.top + 4, rtSubItem.Width() - 7, rtSubItem.Height() - 4, NULL); // EditCtrl Show ::ShowWindow(_GetEditHwnd(), SW_SHOW); ::SetFocus(_GetEditHwnd()); // SubItem 위치에 외각선을 그려준다. ::Rectangle(::GetDC(_GetListHwnd()), rtSubItem.left, rtSubItem.top - 1, rtSubItem.right, rtSubItem.bottom); // EditCtrl 에 선택한 List의 Text 를 넣어준다. ::SetWindowText(_GetEditHwnd(), cStrText); // 삽입한 Text의 마지막에 포커스를 맞춰주고 Mark한다. int nSel = cStrText.GetLength(); ::SendMessage(_GetEditHwnd(), EM_SETSEL, LOWORD(nSel), HIWORD(nSel)); // Focus를 잃었을 경우 ListCtrl에 적용시키기 위해 저장 m_hFocus = _GetEditHwnd(); Invalidate(); *pResult = 0; } HWND CEditListCtrl::_GetEditHwnd(void) { return ::GetDlgItem(GetParent()->GetSafeHwnd(), IDC_EDIT_CAM_ATTR); } HWND CEditListCtrl::_GetListHwnd(void) { return GetSafeHwnd(); } HWND CEditListCtrl::_GetParentHwnd(void) { return GetParent()->GetSafeHwnd(); } //이 컨트롤을 가지는 Dialog Class의 PreTranslateMessage 부분 혹은 OnOK 부분 (Return키 작동시를 위한)에 //현재 포커스가 ListCtrl 혹은 EditCtrl 일 경우 CEditListCtrl 의 OnOK 함수를 호출해야 합니다. CTestDlg::OnOK() { int id = GetFocus()->GetDlgCtrlID(); if(id == IDC_LIST_EDITLISTCTRL || id == IDC_EDIT_EDITLISTCTRL) m_editListCtrl.OnOK() }
'MFC' 카테고리의 다른 글
[MFC] 마우스 드래그하여 Dialog 이동하기 (0) | 2012.03.19 |
---|---|
콤보박스 아이템 전체 삭제 (1) | 2012.03.08 |
[MFC] Edit(수정) 가능 ListCtrl(ListControl) (0) | 2012.02.26 |
버튼 클릭시 생기는 점선 제거. (1) | 2012.02.24 |
[MFC] ListCtrl 팁.. (1) | 2012.02.23 |
STL 설명 인터넷 링크 (0) | 2011.12.29 |