반응형
http://mnlt.tistory.com/131

ListControl은 MFC에서 굉장히 유용히 쓰이는 컨트롤입니다.
해당 컨트롤에서 직접 원하는 위치를 즉석 수정하기 위한 컨트롤을 만들었습니다.

아마 그냥 유용하게 쓰일듯 싶기도 해서 포스팅.

EditListCtrl.h
  1. #pragma once  
  2.   
  3.   
  4. // CEditListCtrl  
  5.   
  6. class CEditListCtrl : public CListCtrl  
  7. {  
  8.     DECLARE_DYNAMIC(CEditListCtrl)  
  9.   
  10. public:  
  11.     CEditListCtrl();  
  12.     virtual ~CEditListCtrl();  
  13.   
  14. protected:  
  15.     DECLARE_MESSAGE_MAP()  
  16.   
  17. public:  
  18.     virtual BOOL PreTranslateMessage(MSG* pMsg);  
  19.     afx_msg void OnNMClick(NMHDR *pNMHDR, LRESULT *pResult);  
  20.   
  21.     // 초기화 함수.  
  22.     void Init(void);  
  23.   
  24.     // CEditListCtrl 을 사용하는 Dialog 의 OnOK 함수가 호출될때 호출해야 한다.  
  25.     void OnOK(void);  
  26.   
  27.     // List 값을 바꾼다.  
  28.     BOOL SetText(CString _val, int _row, int _col);  
  29.   
  30. protected:  
  31.     // ListCtrl 을 클릭했을때 nItem 저장될 변수. (Row)  
  32.     int m_nItem;  
  33.   
  34.     // ListCtrl 을 클릭했을때 nSubItem 저장될 변수 (Col);  
  35.     int m_nSubItem;  
  36.   
  37.     // 현재 포커스가 어딘지 확인하는 변수  
  38.     HWND m_hFocus;  
  39.   
  40.     bool m_bInit;  
  41.   
  42.     HWND _GetEditHwnd(void);  
  43.     HWND _GetListHwnd(void);  
  44.     HWND _GetParentHwnd(void);  
  45. };  


EditListCtrl.cpp
  1. // EditListCtrl.cpp : 구현 파일입니다.  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include "TestApp.h"  
  6. #include "EditListCtrl.h"  
  7.   
  8.   
  9. // CEditListCtrl  
  10.   
  11. IMPLEMENT_DYNAMIC(CEditListCtrl, CListCtrl)  
  12.   
  13. CEditListCtrl::CEditListCtrl()  
  14. : m_nItem(0), m_nSubItem(0)  
  15. , m_bInit(false)  
  16. , m_hFocus((HWND)0)  
  17. {  
  18.   
  19. }  
  20.   
  21. CEditListCtrl::~CEditListCtrl()  
  22. {  
  23. }  
  24.   
  25. BEGIN_MESSAGE_MAP(CEditListCtrl, CListCtrl)  
  26.     ON_NOTIFY_REFLECT(NM_CLICK, &CEditListCtrl::OnNMClick)  
  27. END_MESSAGE_MAP()  
  28.   
  29.   
  30.   
  31.   
  32. // CEditListCtrl 메시지 처리기입니다.  
  33.   
  34. BOOL CEditListCtrl::PreTranslateMessage(MSG* pMsg)  
  35. {  
  36.     if(m_hFocus != (HWND)0)  
  37.     {  
  38.         HWND hFocus = ::GetFocus();  
  39.   
  40.         // Edit 가 Focus를 잃으면.  
  41.         if(m_hFocus != hFocus)  
  42.         {  
  43.             OnOK();  
  44.         }  
  45.     }  
  46.       
  47.   
  48.     return CListCtrl::PreTranslateMessage(pMsg);  
  49. }  
  50.   
  51. void CEditListCtrl::Init(void)  
  52. {  
  53.     if(m_bInit) return;  
  54.   
  55.     SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);  
  56.     ::ShowWindow(_GetEditHwnd(), SW_HIDE);  
  57.   
  58.     m_bInit = true;  
  59. }  
  60.   
  61.   
  62. // Return 키가 눌렸을때 호출하기 위한..  
  63. void CEditListCtrl::OnOK(void)  
  64. {  
  65.     CWnd* pWnd = GetFocus();  
  66.   
  67.     if(_GetEditHwnd() == pWnd->GetSafeHwnd() ||  
  68.         _GetEditHwnd() == m_hFocus)  
  69.     {  
  70.         // EditCtrl로 부터 Text를 얻어온다.  
  71.         wchar_t cText[255];  
  72.         ZeroMemory(cText, 255);  
  73.         ::GetWindowText(_GetEditHwnd(), cText, 255);  
  74.         CString cStrText(cText);  
  75.   
  76.         // 얻어온 텍스트를 ListCtrl 에 적용시킨다  
  77.         if(SetText(cStrText, m_nItem, m_nSubItem) == FALSE)  
  78.             return;  
  79.   
  80.         // EditCtrl의 Focus를 죽인다.  
  81.         ::SendMessage(_GetEditHwnd(), WM_KILLFOCUS, 0, 0);  
  82.         ::ShowWindow(_GetEditHwnd(), SW_HIDE);  
  83.         ::SetFocus(pWnd->GetSafeHwnd());  
  84.   
  85.         // ListCtrl의 SelectionMark를 지정한다.  
  86.         SetSelectionMark(m_nItem);  
  87.     }  
  88.   
  89.     m_hFocus = (HWND)0;  
  90. }  
  91.   
  92. BOOL CEditListCtrl::SetText(CString _val, int _row, int _col)  
  93. {  
  94.     return SetItemText(_row, _col, _val);  
  95. }  
  96.   
  97. void CEditListCtrl::OnNMClick(NMHDR *pNMHDR, LRESULT *pResult)  
  98. {  
  99.     Invalidate();  
  100.   
  101.     LPNMITEMACTIVATE pNMITEM = (LPNMITEMACTIVATE) pNMHDR;  
  102.     m_nItem = pNMITEM->iItem;  
  103.     m_nSubItem = pNMITEM->iSubItem;  
  104.   
  105.     // 선택된 지점이 올바르지 않을시...  
  106.     if(m_nSubItem == 0 || m_nSubItem == -1 || m_nItem == -1)  
  107.         return;  
  108.   
  109.     // 선택된 SubItem의 Text를 CEdit 에 넣어주기 위한 변수  
  110.     CString cStrText = GetItemText(m_nItem, m_nSubItem);  
  111.   
  112.     CRect rtSubItem, rtListCtrl, rtDlg;  
  113.     // SubItem 의 Rect를 얻어온다.  
  114.     if(GetSubItemRect(pNMITEM->iItem, pNMITEM->iSubItem, LVIR_BOUNDS, rtSubItem) == FALSE)  
  115.         return;  
  116.   
  117.     // ListControl 의 Window Bounds 를 얻어온다.  
  118.     ::GetWindowRect(_GetListHwnd(), &rtListCtrl);  
  119.   
  120.     // Parent Dialog 의 Windows Bounds 를 얻어온다.  
  121.     ::GetWindowRect(_GetParentHwnd(), &rtDlg);  
  122.   
  123.     // Dialog에 위치한 ListCtrl의 left & top 위치를 구한다.  
  124.     int nThisLeft = rtListCtrl.left - rtDlg.left;  
  125.     int nThisTop = rtListCtrl.top - rtDlg.top;  
  126.   
  127.     // EditCtrl의 위치를 변경해준다.  
  128.     ::SetWindowPos(  
  129.         _GetEditHwnd(),   
  130.         HWND_TOP,  
  131.         nThisLeft + rtSubItem.left + 7,  
  132.         nThisTop + rtSubItem.top + 4,  
  133.         rtSubItem.Width() - 7,  
  134.         rtSubItem.Height() - 4,  
  135.         NULL);  
  136.   
  137.     // EditCtrl Show  
  138.     ::ShowWindow(_GetEditHwnd(), SW_SHOW);  
  139.     ::SetFocus(_GetEditHwnd());  
  140.   
  141.     // SubItem 위치에 외각선을 그려준다.  
  142.     ::Rectangle(::GetDC(_GetListHwnd()), rtSubItem.left, rtSubItem.top - 1, rtSubItem.right, rtSubItem.bottom);  
  143.   
  144.     // EditCtrl 에 선택한 List의 Text 를 넣어준다.  
  145.     ::SetWindowText(_GetEditHwnd(), cStrText);  
  146.   
  147.     // 삽입한 Text의 마지막에 포커스를 맞춰주고 Mark한다.  
  148.     int nSel = cStrText.GetLength();  
  149.     ::SendMessage(_GetEditHwnd(), EM_SETSEL, LOWORD(nSel), HIWORD(nSel));  
  150.   
  151.     // Focus를 잃었을 경우 ListCtrl에 적용시키기 위해 저장  
  152.     m_hFocus = _GetEditHwnd();  
  153.     Invalidate();  
  154.   
  155.     *pResult = 0;  
  156. }  
  157.   
  158.   
  159. HWND CEditListCtrl::_GetEditHwnd(void)  
  160. {  
  161.     return ::GetDlgItem(GetParent()->GetSafeHwnd(), IDC_EDIT_CAM_ATTR);  
  162. }  
  163.   
  164. HWND CEditListCtrl::_GetListHwnd(void)  
  165. {  
  166.     return GetSafeHwnd();  
  167. }  
  168.   
  169. HWND CEditListCtrl::_GetParentHwnd(void)  
  170. {  
  171.     return GetParent()->GetSafeHwnd();  
  172. }  



이 컨트롤을 가지는 Dialog Class의 PreTranslateMessage 부분 혹은 OnOK 부분 (Return키 작동시를 위한)에
현재 포커스가 ListCtrl 혹은 EditCtrl 일 경우 CEditListCtrl 의 OnOK 함수를 호출해야 합니다.

  1. CTestDlg::OnOK()  
  2. {  
  3.     int id = GetFocus()->GetDlgCtrlID();  
  4.     if(id == IDC_LIST_EDITLISTCTRL || id == IDC_EDIT_EDITLISTCTRL)  
  5.         m_editListCtrl.OnOK()  
  6. }  


이정도가 되겠습니다.


반응형

+ Recent posts