반응형
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()
- }
이정도가 되겠습니다
반응형
'C & C++ > MFC 컨트롤' 카테고리의 다른 글
[Ctrl] Checkbox 사용법 (0) | 2011.05.20 |
---|---|
[Edit] Edit & ComboBox 글자수 제한 (0) | 2011.05.04 |
[List] List 컨트롤에 비트맵 이미지 셋팅 (0) | 2011.05.04 |
[List] List 컨트롤에 ComboBox 사용하기 (0) | 2011.05.04 |
[List] 리스트 컨트롤에 색상입히기 (0) | 2011.05.04 |
댓글