6.4 ÇϺξÆÀÌÅÛ ÆíÁýÀ» À§ÇØ µå·Ó´Ù¿î ¸®½ºÆ® »ç¿ëÇϱâ
¶§¶§·Î, »ç¿ëÀÚ°¡ ¸¶À½´ë·Î ¾ÆÀÌÅÛÀ» ÆíÁýÇϰÔÇϴ°ͺ¸´Ù, »ç¿ëÀÚ¿¡°Ô ¼±ÅðªµéÀ»Áִ°ÍÀÌ
ÁÁÀ»¼öµµ ÀÖ½À´Ï´Ù. ¿¡µð
Æ® ÄÁÆ®·Ñ´ë½Å µå·Ó´Ù¿î ¸®½ºÆ®¸¦ »ç¿ëÇÔÀ¸·Î½áÀ̰ÍÀÌ °¡´ÉÇÕ´Ï´Ù. ±¸ÇöÇÏ·Á¸é, ÇϺξÆÀÌÅÛÆíÁý°ú
°°Àº ÆÐÅÏÀ» µû¸¨
´Ï´Ù.
<±×¸²>
´Ü°è 1: CListCtrl »ó¼ÓŬ·¡½º
»ý¼º
CListCtrl
·Î ºÎÅÍ »õ·Î¿î Ŭ·¡½º¸¦ ÆÄ»ýÇϰųª Á¸ÀçÇÏ´Â ¼ºêŬ·¡½º¿¡ ¼öÁ¤À» ÇÕ´Ï´Ù. ¸¸¾à
ÀÌ¹Ì 6.3¿¡¼ ¼³¸íÇÑ ÇϺξÆÀÌÅÛ ÆíÁýÀÌ °¡´ÉÇÑ Å¬·¡½º¸¦ »ç¿ëÇÑ´Ù¸é±× Ŭ·¡½º¸¦
»ç¿ëÇÒ¼ö ÀÖ½À´Ï´Ù.
´Ü°è 2: HitTestEx() ÇÔ¼ö
Á¤ÀÇ
CMyListCtrl
Ŭ·¡½º¿¡ È®ÀåµÈ HitTest ÇÔ¼ö¸¦ Á¤ÀÇÇÕ´Ï´Ù. ÀÌ ÇÔ¼ö´Â Ŭ¸¯ÇÑ Á¡ÀÇ Row À妽º¿Í
Ä÷³À» °áÁ¤ÇÒ°ÍÀÔ´Ï´Ù. HitTestEx() ÇÔ¼ö´Â ÀÌ¹Ì 4.4 ¿¡¼ »ìÆìº¸¾Ò½À´Ï´Ù. Ŭ¸¯À̳ª
´õºíŬ¸¯½Ã ÆíÁýÀÌ ½ÃÀ۵ǵµ·Ï ÀÌ ÇÔ¼ö¸¦ ÇÊ¿ä·Î ÇÕ´Ï´Ù.
´Ü°è 3: µå·Ó´Ù¿î ¸®½ºÆ®¸¦ »ý¼ºÇÏ´Â ÇÔ¼ö¸¦ ÀÛ¼ºÇÕ´Ï´Ù.
ÀÌ
ÇÔ¼ö´Â 6.3¿¡¼ ¼³¸íÇß´ø EditSubLabel() ÇÔ¼ö¿Í ¸Å¿ì ºñ½ÁÇÕ´Ï´Ù. Â÷ÀÌÁ¡Àº ¸¶Áö¸·¿¡
CInPlaceList Ŭ·¡½º·ÎºÎÅÍ ÄÞº¸¹Ú½º¸¦ ¸¸µç´Ù´Â°ÍÀÔ´Ï´Ù. À̰ÍÀº ÀÎÀڷι®ÀÚ¿µéÀÇ
¸®½ºÆ®¸¦ ÇÊ¿ä·Î ÇѴٴ°ÍÀ» ÁÖÀÇÇϽʽÿÀ. ÀÌ ¸®½ºÆ®´Â µå·Ó´Ù¿î¸®½ºÆ®¸¦ ä¿ì±â
À§ÇØ ÇÊ¿äÇÕ´Ï´Ù. ¸¶Áö¸·ÀÎÀÚ´Â ±âº»ÀûÀ¸·Î ¼±ÅÃµÉ ¾ÆÀÌÅÛÀÇ ¹øÈ£ÀÔ´Ï´Ù.
// ShowInPlaceList -
¸®½ºÆ®ºäÀÇ ¾Æ¹«¼¿¿¡³ª µå·Ó´Ù¿î¸®½ºÆ® »ý¼º
// Returns -
ÄÞº¸¹Ú½º¿¡ ´ëÇÑ Àӽà Æ÷ÀÎÅÍ
// nItem -
ÆíÁýÇÒ ¾ÆÀÌÅÛÀÇ ·Î¿ì À妽º
// nCol -
ÆíÁýÇÒ ¾ÆÀÌÅÛÀÇ Ä÷³ À妽º
// lstItems -
ÄÁÆ®·ÑÀ» ä¿ï ½ºÆ®¸µÀÇ ¸®½ºÆ®
// nSel -
±âº»ÀûÀ¸·Î ¼±ÅÃµÉ ¾ÆÀÌÅÛÀÇ ¹øÈ£
CComboBox* CMyListCtrl::ShowInPlaceList( int nItem , int nCol , CStringList
&lstItems, int nSel )
{
// ¸®ÅÏµÈ Æ÷ÀÎÅÍ´Â ÀúÀåµÇ¸é
¾ÈµÊ(Save)
// ¾ÆÀÌÅÛÀÌ º¸ÀÌ´ÂÁö È®ÀÎ
if( !EnsureVisible( nItem, TRUE
) ) return NULL;
// nCol ÀÌ À¯È¿ÇÑÁö È®ÀÎ
CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
int nColumnCount = pHeader->GetItemCount();
if( nCol >= nColumnCount
|| GetColumnWidth(nCol) < 10 ) return NULL;
// Ä÷³ ¿ÀÇÁ¼Â(Offset) °¡Á®¿À±â
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 height = rect.bottom-rect.top;
rect.bottom += 5*height;
if( rect.right > rcClient.right)
rect.right = rcClient.right;
DWORD dwStyle = WS_BORDER|WS_CHILD|WS_VISIBLE|WS_VSCROLL|WS_HSCROLL
|CBS_DROPDOWNLIST|CBS_DISABLENOSCROLL;
CComboBox *pList = new CInPlaceList(nItem,
nCol, &lstItems, nSel);
pList->Create( dwStyle, rect,
this, IDC_IPEDIT );
pList->SetItemHeight( -1,
height);
pList->SetHorizontalExtent(
GetColumnWidth( nCol ));
return pList;
}
´Ü°è 4: ½ºÅ©·Ñ ¸Þ½ÃÁö ó¸®Çϱâ
( Handle the scroll messages )
CInPlaceListŬ·¡½º´Â
Æ÷Ä¿½º¸¦ ÀÒ¾úÀ»¶§ µå·Ó´Ù¿î¸®½ºÆ® ÄÁÆ®·ÑÀ» ÆÄ±«ÇÏ°í °´Ã¼¸¦¾ø¾Ö±âÀ§ÇØ ¸¸µé¾î Á³½À´Ï´Ù.
¸®½ºÆ®ºäÀÇ ½ºÅ©·Ñ¹Ù¸¦ Ŭ¸¯Çϴ°ÍÀº ¸®½ºÆ® ÄÁÆ®·Ñ¿¡¼ Æ÷Ä¿½º¸¦ »°Áö ¾Ê½À´Ï´Ù.
±×·¯¹Ç·Î ¿ì¸®´Â ¸®½ºÆ®ºä ÄÁÆ®·Ñ¿¡ Æ÷Ä¿½º¸¦ ÁÜÀ¸·Î½á Æ÷Ä¿½º¸¦ ¸®½ºÆ® ÄÁÆ®·Ñ¿¡¼
»©¾Ò±â´Â °ÍÀ» ¹æÁöÇÏ´Â ½ºÅ©·Ñ¹Ù ¸Þ½ÃÁö¿¡ ´ëÇÑ Çڵ鷯¸¦ ÀÛ¼ºÇØ¾ß ÇÕ´Ï´Ù.
void CMyListCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
if( GetFocus() != this ) SetFocus();
CListCtrl::OnHScroll(nSBCode,
nPos, pScrollBar);
}
void CMyListCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
if( GetFocus() != this ) SetFocus();
CListCtrl::OnVScroll(nSBCode,
nPos, pScrollBar);
}
´Ü°è 5: EndLabelEdit ó¸®
³»Àå
¿¡µðÆ® ÄÁÆ®·Ñó·³, ¿ì¸®ÀÇ µå·Ó´Ù¿î ¸®½ºÆ® ÄÁÆ®·Ñµµ »ç¿ëÀÚ°¡ ¾ÆÀÌÅÛÀ» ¼±ÅÃÇßÀ»¶§
LVN_ENDLABELEDIT ÅëÁö¸¦ º¸³À´Ï´Ù. ¸¸¾à ÀÌ ÅëÁö ¸Þ½ÃÁö°¡ ÀÌ¹Ì Ã³¸®µÇÁö¾Ê¾Ò´Ù¸é,
º¯°æ»çÇ×ÀÌ ¹Þ¾Æµé¿©Áú ¼ö ÀÖµµ·Ï Çڵ鷯¸¦ Ãß°¡ÇÕ´Ï´Ù.
void CMyListCtrl::OnEndLabelEdit(NMHDR* pNMHDR, LRESULT* pResult)
{
LV_DISPINFO *plvDispInfo
= (LV_DISPINFO *)pNMHDR;
LV_ITEM *plvItem
= &plvDispInfo->item;
if (plvItem->pszText != NULL) {
SetItemText(plvItem->iItem,
plvItem->iSubItem, plvItem->pszText);
}
*pResult = FALSE;
}
´Ü°è 6: »ç¿ëÀÚ°¡ ÆíÁýÀ» ½ÃÀÛÇÒ¼ö
ÀÖµµ·Ï ÇÏ´Â ¹æ¹ýÀ» Ãß°¡ÇÕ´Ï´Ù.
¾Æ·¡ÄÚµå´Â
WM_LBUTTONDOWN ¸Þ½ÃÁö¿¡ ´ëÇÑ Çڵ鷯ÀÔ´Ï´Ù. Æ÷Ä¿½º°¡ ÀÖ´Â ¾ÆÀÌÅÛÀÇ ¼ºê¾ÆÀÌÅÛÀÌ
Ŭ¸¯µÇ¾úÀ» ¶§ µå·Ó´Ù¿î ¸®½ºÆ® ÄÁÆ®·ÑÀ» »ý¼ºÇÕ´Ï´Ù. ÀÌ ÄÚµå´Â µå·Ó´Ù¿î ¸®½ºÆ®
ÄÁÆ®·ÑÀ» ¸¸µé±â Àü¿¡ ¸ÕÀú LVS_EDITLABELS ½ºÅ¸ÀÏÀ» üũÇÕ´Ï´Ù. ¹°·Ð, À̰ÍÀº ¸Å¿ì
°£´ÜÇÑ ±¸ÇöÀ̹ǷΠÇʿ信 µû¶ó ¼öÁ¤µÉ Çʿ䰡 ÀÖ½À´Ï´Ù.
void CMyListCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
int index;
CListCtrl::OnLButtonDown(nFlags,
point);
int colnum;
if( ( index = HitTestEx( point,
&colnum )) != -1 ) {
UINT
flag = LVIS_FOCUSED;
if(
(GetItemState( index, flag ) & flag) == flag ) {
//
LVS_EDITLABELS ¿¡ ´ëÇÑ Ã¼Å©
if(
GetWindowLong(m_hWnd, GWL_STYLE) & LVS_EDITLABELS ) {
CStringList
lstItems;
lstItems.AddTail(
"First Item");
lstItems.AddTail(
"Second Item");
lstItems.AddTail(
"Third Item");
lstItems.AddTail(
"Fourth Item");
lstItems.AddTail(
"Fifth Item");
lstItems.AddTail(
"Sixth Item");
ShowInPlaceList(
index, colnum, lstItems, 2 );
}
} else {
SetItemState(index,
LVIS_SELECTED | LVIS_FOCUSED , LVIS_SELECTED | LVIS_FOCUSED);
}
}
}
´Ü°è 7: CComboBox Ŭ·¡½º
¼ºêŬ·¡½Ì
¿ì¸®ÀÇ
Ưº°ÇÑ ¿ä±¸»çÇ×À» Á¦°øÇϱâÀ§ÇØ CComboBoxŬ·¡½º¸¦ ¼ºêŬ·¡½ÌÇØ¾ß ÇÕ´Ï´Ù.
ÀÌ Å¬·¡½º¿¡ ´ëÇÑ ÁÖ¿ä ¿ä±¸»çÇ×Àº ¾Æ·¡¿Í °°½À´Ï´Ù.
- À¯Àú°¡ ¾ÆÀÌÅÛ ¼±ÅÃÀ» ³¡³ÂÀ»½Ã LVN_ENDLABELEDIT ¸Þ½ÃÁö¸¦ º¸³»¾ß ÇÑ´Ù.
- ÆíÁýÀÌ ³¡³µÀ»¶§ ÀÚ±âÀÚ½ÅÀ» ÆÄ±«ÇØ¾ß ÇÑ´Ù.
- »ç¿ëÀÚ°¡ ESC ¶Ç´Â ¿£ÅÍ۸¦ ´©¸£°Å³ª À¯Àú°¡ ¾ÆÀÌÅÛÀ» ¼±ÅÃÇßÀ»¶§, ÄÁÆ®·ÑÀÌ ÀÔ·Â
Æ÷Ä¿½º¸¦ ÀÒÀ»¶§ ÆíÁýÀÌ ³¡³ª¾ßÇÑ´Ù.
Çì´õÆÄÀÏÀº ±¸ÇöÈÀÏ(Implementation File)¾Õ¿¡ ÀÖ½À´Ï´Ù. CInPlaceList´Â 5°³ÀÇPrivate º¯¼ö¸¦ ¼±¾ðÇÕ´Ï´Ù. À̵éÀº µå·Ó´Ù¿î ¸®½ºÆ®¸¦ ÃʱâÈÇÒ¶§¿Í LVN_ENDLABELEDIT ÅëÁö¸¦ º¸³¾¶§ »ç¿ëµË´Ï´Ù.
// InPlaceList.h : header file
// CInPlaceList window
class CInPlaceList : public CComboBox {
public: // Construction
CInPlaceList(int iItem, int
iSubItem, CStringList *plstItems, int nSel);
public: // Attributes
public: // Operations
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CInPlaceList)
public:
virtual BOOL PreTranslateMessage(MSG*
pMsg);
//}}AFX_VIRTUAL
// Implementation
public:
virtual
~CInPlaceList();
protected: //
Generated message map functions
//{{AFX_MSG(CInPlaceList)
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();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
private:
int
m_iItem;
int
m_iSubItem;
CStringList
m_lstItems;
int m_nSel;
BOOL m_bESC; //
ESC ۰¡ ´·È´ÂÁö ³ªÅ¸³»±â À§ÇØ
};
CInPlaceList ÀÇ »ý¼ºÀÚ´Â ÀÎÀÚ·Î ³Ñ¾î¿Â °ªµéÀ» ÀúÀåÇϰí m_bESC¸¦ FALSE·Î ÃʱâÈÇÕ´Ï´Ù. OnCreate()ÇÔ¼ö´Â µå·Ó´Ù¿î¸®½ºÆ® ÄÁÆ®·ÑÀ» »ý¼ºÇϰí Àû´çÇÑ °ªÀ¸·Î ÃʱâÈÇÕ´Ï´Ù. PreTranslateMessage()ÇÔ¼ö´Â ¿¡µðÆ® ÄÁÆ®·Ñ¿¡ Àü´ÞµÇ´Â ESC¿Í ¿£ÅÍŰ È®ÀÎÀ» À§ÇØ ¿À¹ö¶óÀ̵åµË´Ï´Ù. ESC Ű¿Í ¿£ÅÍŰ´Â º¸Åë CDialog ³ª CFormView °´Ã¼¿¡ ÀÇÇØ Pre-Translate µË´Ï´Ù. ±×·¯¹Ç·Î ¿ì¸®´Â À̰͵鿡 ´ëÇØ Ưº°È÷ üũÇÏ¿© µå·Ó´Ù¿î ¸®½ºÆ® ÄÁÆ®·Ñ·Î ³Ñ±é´Ï´Ù.
OnKillFocus()ÇÔ¼ö´Â LVN_ENDLABELEDITÅëÁö¸¦ º¸³»°í ÄÞº¸¹Ú½ºÄÁÆ®·ÑÀ» ÆÄ±«ÇÕ´Ï´Ù.
ÅëÁö ¸Þ½ÃÁö´Â ¸®½ºÆ®ºä ÄÁÆ®·ÑÀÌ ¾Æ´Ñ ¸®½ºÆ®ºäÀÇ ºÎ¸ð¿¡°Ô º¸³»Áý´Ï´Ù. ÅëÁö¸¦
º¸³¾¶§ m_bESC ¸â¹ö º¯¼ö¸¦ °¡Áö
°í NULL ½ºÆ®¸µÀ» º¸³¾Áö¸¦ °áÁ¤ÇÕ´Ï´Ù.
OnNcDestroy() ÇÔ¼ö°¡ C++ °´Ã¼¸¦ ÆÄ±«Çϴµ¥ ÀûÀýÇÑ Àå¼ÒÀÔ´Ï´Ù.
OnChar() ÇÔ¼ö´Â ESC ³ª ¿£ÅͰ¡ ´·ÈÀ»¶§ ¼±ÅÃÀ» ³¡³À´Ï´Ù. ÀÌ ÇÔ¼ö´Â ¸®½ºÆ®ºä¿¡Æ÷Ä¿½º¸¦
ÁÜÀ¸·Î½á ÄÞº¸¹Ú½º ÄÁÆ®·ÑÀÇ OnKillFocus() ÇÔ¼ö°¡ ºÒ·ÁÁöµµ·Ï ÇÕ´Ï´Ù.
OnChar() ÇÔ¼ö´Â ´Ù¸¥ ¹®ÀÚ¿¡ ´ëÇØ¼± º£À̽º Ŭ·¡½º ÇÔ¼ö°¡ ó¸®Çϵµ·Ï ÇÕ´Ï´Ù.
OnCloseup()ÇÔ¼ö´Â »ç¿ëÀÚ°¡ µå·Ó´Ù¿î ¸®½ºÆ®¿¡¼ ¼±ÅÃÇßÀ»¶§ È£ÃâµË´Ï´Ù. ÀÌÇÔ¼ö´ÂºÎ¸ð¿¡¼
ÀÔ·Â Æ÷Ä¿½º¸¦ ÁÜÀ¸·Î½á ¾ÆÀÌÅÛ ¼±ÅÃÀ» ³¡¸¶Ä¡°Ô ÇÕ´Ï´Ù.
// InPlaceList.cpp : implementation file
#include "stdafx.h"
#include "InPlaceList.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[]
= __FILE__;
#endif
// CInPlaceList
CInPlaceList::~CInPlaceList() { }
CInPlaceList::CInPlaceList(int iItem, int iSubItem, CStringList *plstItems,
int nSel)
{
m_iItem =
iItem;
m_iSubItem =
iSubItem;
m_lstItems.AddTail( plstItems
);
m_nSel =
nSel;
m_bESC =
FALSE;
}
BEGIN_MESSAGE_MAP(CInPlaceList, CComboBox)
//{{AFX_MSG_MAP(CInPlaceList)
ON_WM_CREATE()
ON_WM_KILLFOCUS()
ON_WM_CHAR()
ON_WM_NCDESTROY()
ON_CONTROL_REFLECT(CBN_CLOSEUP,
OnCloseup)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
// CInPlaceList message handlers
int CInPlaceList::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CComboBox::OnCreate(lpCreateStruct)
== -1) return -1;
// Set the proper font
CFont* font = GetParent()->GetFont();
SetFont(font);
for( POSITION pos = m_lstItems.GetHeadPosition();
pos != NULL; ) {
AddString(
(LPCTSTR) (m_lstItems.GetNext( pos )));
}
SetCurSel( m_nSel );
SetFocus();
return 0;
}
BOOL CInPlaceList::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);
}
void CInPlaceList::OnKillFocus(CWnd* pNewWnd)
{
CComboBox::OnKillFocus(pNewWnd);
CString str;
GetWindowText(str);
// ¸®½ºÆ®ºä ÄÁÆ®·ÑÀÇ ºÎ¸ð¿¡°Ô
ÅëÁö º¸³»±â
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_iItem;
dispinfo.item.iSubItem =
m_iSubItem;
dispinfo.item.pszText =
m_bESC ? NULL : LPTSTR((LPCTSTR)str);
dispinfo.item.cchTextMax =
str.GetLength();
GetParent()->GetParent()->SendMessage(
WM_NOTIFY, GetParent()->GetDlgCtrlID(), (LPARAM)&dispinfo );
DestroyWindow();
}
void CInPlaceList::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 CInPlaceList::OnNcDestroy()
{
CComboBox::OnNcDestroy();
delete this;
}
void CInPlaceList::OnCloseup()
{
GetParent()->SetFocus();
}