9. ÅøÆÁ°ú ŸÀÌÆ²ÆÁ(Tooltip & Titletip)
9.1 Çì´õ¸¦ À§ÇÑ ÅøÆÁ
Çì´õÄÁÆ®·ÑÀ» À§ÇÑ ÅøÆÁÀ» Ãß°¡Çϴ°ÍÀº ¸Å¿ì °£´ÜÇÕ´Ï´Ù.
CListCtrl ÆÄ»ý Ŭ·¡½º¿¡ CToolTipCtrl ŸÀÔÀÇ ¸â¹öº¯¼ö¸¦ ¼±¾ðÇÕ´Ï´Ù.
CToolTipCtrl m_tooltip;
CListCtrl ÆÄ»ý Ŭ·¡½º¿¡¼ PreSubclassWindow() ÇÔ¼ö¸¦ ¿À¹ö¶óÀ̵å ÇÕ´Ï´Ù. º£À̽ºÅ¬·¡½ºÀÇ PreSubclassWindow()¸¦ È£ÃâÇÑÈÄ, ÅøÆÁ°´Ã¼¸¦ ¸¸µì´Ï´Ù. OnCreate()´ë½Å¿¡ PreSubclassWindow() ¸¦ ¿À¹ö¶óÀ̵åÇÑ ÀÌÀ¯´Â ÄÁÆ®·ÑÀº º¸Åë ´ÙÀ̾ó·Î±× ¸®¼Ò½º·ÎºÎÅÍ »ý¼ºµÊÀ¸·Î½á ÀÌ¹Ì ¸¸µé¾îÁøÈÄ¿¡ C++ °´Ã¼¿¡ ºÙ±â(Attach) ¶§¹®¿¡, OnCreate°¡ °´Ã¼¿¡ ´ëÇØ ÀüÇô È£ÃâÀÌ µÇÁö ¾Ê±â¶§¹®ÀÔ´Ï´Ù.
void CMyListCtrl::PreSubclassWindow()
{
CListCtrl::PreSubclassWindow();
// Add initialization code
m_tooltip.Create( this );
m_tooltip.AddTool( GetDlgItem(0),
"Right click for context menu" );
}
PreTranslateMessage()ÇÔ¼ö¸¦ ¿À¹ö¶óÀ̵åÇØ¼ CToolTip °´Ã¼ÀÇ RelayEvents()ÇÔ¼ö¸¦ È£ÃâÇÕ´Ï´Ù.
BOOL CMyListCtrl::PreTranslateMessage(MSG* pMsg)
{
m_tooltip.RelayEvent( pMsg );
return CListCtrl::PreTranslateMessage(pMsg);
}
9.2 °¢°¢ÀÇ Ä÷³ Çì´õ¸¦ À§ÇÑ ÅøÆÁ
Ä÷³Çì´õ¿¡ ÅøÆÁÀ» Á¦°øÇϴ°ÍÀº ¿©·¯ ¿ëµµ°¡ ÀÖ½À´Ï´Ù. Çì´õÅøÆÁÀÌ Á¤¸» À¯¿ëÇÏ´Ù°í ´À³¤ ÇѰ¡Áö °æ¿ì´Â Ä÷³ÀÇ ³ÐÀ̰¡ Á¦ÇѵǾî ÀÖÀ»¶§ ÀÔ´Ï´Ù. ÅøÆÁÀº Ä÷³Çì´õ°¡ Á¦ÇÑµÈ ³ÐÀ̶§¹®¿¡ Àü´ÞÇÏÁö ¸øÇÏ´Â °ÍÀ» Àü´ÞÇÒ ¼ö ÀÖ½À´Ï´Ù. Äڵ带 ModularÇÏ°Ô Çϱâ À§ÇØ ¿ì¸®´Â CListCtrl ÆÄ»ýŬ·¡½º¿¡ ÅøÆÁ±â´ÉÀ» ±¸ÇöÇÒ°ÍÀÔ´Ï´Ù.
CListCtrl ÆÄ»ý Ŭ·¡½º¿¡ CToolTipCtrl ŸÀÔÀÇ ¸â¹öº¯¼ö¸¦ ¼±¾ðÇÕ´Ï´Ù.
CToolTipCtrl m_tooltip;
CListCtrl ÆÄ»ý Ŭ·¡½º¿¡¼ PreSubclassWindow() ÇÔ¼ö¸¦ ¿À¹ö¶óÀ̵å ÇÕ´Ï´Ù. º£À̽ºÅ¬·¡½ºÀÇ PreSubclassWindow()¸¦ È£ÃâÇÑÈÄ, ÅøÆÁ°´Ã¼¸¦ ¸¸µì´Ï´Ù.
void CMyListCtrl::PreSubclassWindow()
{
CListCtrl::PreSubclassWindow();
// Add initialization code
m_tooltip.Create( this );
}
PreTranslateMessage()ÇÔ¼ö¸¦ ¿À¹ö¶óÀ̵åÇØ¼ CToolTip °´Ã¼ÀÇ RelayEvents()ÇÔ¼ö¸¦ È£ÃâÇÕ´Ï´Ù. RelayEvents() ÇÔ¼ö¸¦ È£ÃâÇϴ°ÍÀº ÅøÆÁÀÌ ¸¶¿ì½º°¡ Åø¿µ¿ª ¾îµð¿¡ µé¾î¿Ô´ÂÁö´Â ¾Ë ¼ö ÀÖ´Â ±âȸ¸¦ Á¦°øÇÕ´Ï´Ù. ºñ·Ï ¸®½ºÆ®ºäÄÁÆ®·ÑÀÌ ¹Þ´Â ¸ðµç ¸Þ½ÃÁö¸¦ ÆÐ½ºÇÏÁö¸¸, ÅøÆÁÄÁÆ®·ÑÀº WM_?BUTTONDOWN,WM_?BUTTONUP, ±×¸®°í WM_MOUSEMOVE ¸Þ½ÃÁö ¸¸À» ó¸®ÇÕ´Ï´Ù.
BOOL CMyListCtrl::PreTranslateMessage(MSG* pMsg)
{
m_tooltip.RelayEvent( pMsg );
return CListCtrl::PreTranslateMessage(pMsg);
}
ÅøÆÁÀ» Ãß°¡ÇϱâÀ§ÇÑ ¹æ¹ýÀ» Á¦°øÇÕ´Ï´Ù. ÇϳªÀÇ ÅøÆÁÄÁÆ®·ÑÀº ¿©·¯°³ÀÇ ÅøÀ» ó¸®ÇÒ¼ö ÀÖ½À´Ï´Ù. AddHeaderToolTip() ÇïÆÛ ÇÔ¼ö´Â ÅøÆÁÄÁÆ®·Ñ¿¡ »õ·Î¿î ÅøÀ» Ãß°¡ÇÕ´Ï´Ù
// AddHeaderToolTip - Ä÷³Çì´õ¿¡
´ëÇÑ ÅøÆÁÀ» Ãß°¡ÇÕ´Ï´Ù.
// ÄÁÆ®·ÑÀº
ÀÚ¼¼È÷º¸±â(LVS_REPORT) ¸ðµå¿©¾ß ÇÕ´Ï´Ù.
// Returns - ¼º°ø½Ã
TRUE ¸®ÅÏ
// nCol - Ä÷³
À妽º
// sTip - ÅøÆÁÅØ½ºÆ®
BOOL CMyListCtrl::AddHeaderToolTip(int nCol, LPCTSTR sTip /*= NULL*/)
{
const int TOOLTIP_LENGTH = 80;
char buf[TOOLTIP_LENGTH+1];
CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
int nColumnCount = pHeader->GetItemCount();
if( nCol >= nColumnCount) return
FALSE;
if( (GetStyle() & LVS_TYPEMASK)
!= LVS_REPORT) return FALSE;
// Çì´õÀÇ ³ôÀ̸¦ ±¸ÇÕ´Ï´Ù.
RECT rect;
pHeader->GetClientRect( &rect
);
int height = rect.bottom;
RECT rctooltip;
rctooltip.top = 0;
rctooltip.bottom = rect.bottom;
// Ä÷³ÀÇ Á¿ì Å׵θ®¸¦ ±¸ÇÕ´Ï´Ù.
rctooltip.left = 0 - GetScrollPos(
SB_HORZ );
for( int i = 0; i < nCol;
i++ ) rctooltip.left += GetColumnWidth( i );
rctooltip.right = rctooltip.left
+ GetColumnWidth( nCol );
if( sTip == NULL ) {
//
Ä÷³ Çìµù ¹®ÀÚ¿À» °¡Á®¿É´Ï´Ù.
LV_COLUMN
lvcolumn;
lvcolumn.mask
= LVCF_TEXT;
lvcolumn.pszText
=
buf;
lvcolumn.cchTextMax
= TOOLTIP_LENGTH;
if(
!GetColumn( nCol, &lvcolumn ) ) return FALSE;
}
m_tooltip.AddTool( GetDlgItem(0),
sTip ? sTip : buf, &rctooltip, nCol+1 ); return TRUE;
}
OnNotify()¸¦ ¿À¹ö¶óÀ̵åÇÏ¿© Ä÷³ ³ÐÀÌ¿¡ ´ëÇÑ º¯µ¿»çÇ×À» ÃßÀûÇÕ´Ï´Ù.¸¸¾à »ç¿ëÀÚ°¡ Ä÷³Å©±â¸¦ Á¶Á¤ÇßÀ»¶§ ÅøÆÁÁ¤º¸¸¦ °»½ÅÇÏÁö ¾Ê´Â´Ù¸é ÅøÆÁÀº Á¤È®ÇÑ Ä÷³À» º¸¿©ÁÖÁö ¾ÊÀ»°ÍÀÔ´Ï´Ù.
BOOL CMyListCtrl::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
HD_NOTIFY *pHDN
= (HD_NOTIFY*) lParam;
if((pHDN->hdr.code ==
HDN_ENDTRACKA || pHDN->hdr.code == HDN_ENDTRACKW)) {
//
ÅøÆÁÀÇ Á¤º¸¸¦ °»½ÅÇÕ´Ï´Ù.
CHeaderCtrl*
pHeader = (CHeaderCtrl*)GetDlgItem(0);
int
nColumnCount = pHeader->GetItemCount();
CToolInfo
toolinfo;
toolinfo.cbSize
= sizeof( toolinfo );
//
¿µÇâÀ» ¹ÞÀº °¢ Ä÷³À» tooltipinfo ¸¦ ÅëÇØ ¼øÈ¯(Cycle)ÇÕ´Ï´Ï´Ù.
for(
int i = pHDN->iItem; i <= nColumnCount; i++ ) {
m_tooltip.GetToolInfo(
toolinfo, pHeader, i + 1 );
int
dx; //
³ÐÀÌÀÇ º¯°æ»çÇ×À» ÀúÀåÇÕ´Ï´Ù.
if(
i == pHDN->iItem )
dx = pHDN->pitem->cxy - toolinfo.rect.right;
else
toolinfo.rect.left
+= dx;
toolinfo.rect.right
+= dx;
m_tooltip.SetToolInfo(
&toolinfo );
}
}
return CListCtrl::OnNotify(wParam,
lParam, pResult);
}
9.3 °¢ ¼¿À» À§ÇÑ ÅøÆÁ
ÅøÆÁÀº Ä÷³³ÐÀ̰¡ Á¦ÇÑµÈ È¸é »çÀÌÁî¶§¹®¿¡ Á¦Çѵɶ§ ¸Å¿ì À¯¿ëÇÕ´Ï´Ù. À̵éÀº ´ÜÃàµÇ¼ º¸¿©Áö´Â Ä÷³ÀÇ ¹®ÀÚ¿µéÀ» È®ÀåÇϴµ¥ »ç¿ëµÉ ¼öµµ ÀÖ½À´Ï´Ù. ÀÌ ÀÏÀ»À§ÇØ MFC ¿¡ ÀÇÇØ Á¦°øµÇ´Â ÅøÆÁ±â´ÉÀ» »ç¿ëÇÒ°ÍÀÔ´Ï´Ù. ¾Æ·¡ÄÚµå´Â ¼¿ÀÇ ¹®ÀÚ¿À» ÅøÆÁ¿¡ º¸¿©ÁÝ´Ï´Ù¸¸, À̰ÍÀº ½±°Ô ÀÌ¹Ì ¼¿¿¡ º¸¿©ÁÖ°í Àִ°ÍÀ» º¸À̱⺸´Ù Á» ´Ù¸¥°ÍÀ» º¸¿©ÁÖ´Â °ÍÀ¸·Î ¼öÁ¤µÉ ¼ö ÀÖ½À´Ï´Ù.
°¢ ¼¿¿¡ ´ëÇØ ÅøÆÁÀ» Ãß°¡ÇÏ´Â °ÍÀº »ó´çÈ÷ ½±½À´Ï´Ù. ¾î·µç ¹®¼´Â º°·Î µµ¿òÀ̵ÇÁö ¸øÇϸç, ÀνÄÇØ¾ßÇÒ ¸î°¡Áö »çÇ×ÀÌ ÀÖ½À´Ï´Ù. NT 4.0 °ú Win95 ÀÇ ¸®½ºÆ®ºä ÄÁÆ®·ÑÀº ¸î°¡Áö Áß¿äÇÑ Â÷ÀÌÁ¡À» °¡Áö°í ÀÖ½À´Ï´Ù. ù°·Î , ¸®½ºÆ® ºä ÄÁÆ®·Ñ°úÅøÆÁ ÄÁÆ®·ÑÀº Windows 95 »ó¿¡¼´Â ANSI ÄÁÆ®·ÑÀÔ´Ï´Ù. À̰ÍÀÌ ÀǹÌÇÏ´Â °ÍÀº Windows 95 »ó¿¡¼´Â ¸Þ½ÃÁöµéÀÌ ANSI ¹öÁ¯À̶ó´Â °ÍÀÔ´Ï´Ù. ÇÁ·ÎÁ§Æ® ¼¼ÆÃ¿¡ µû¶ó¼ ¸Þ½ÃÁö »ó¼öµé(A ³ª W Á¢¹Ì¾î°¡ ¾ø´Â°Í)ÀÌ ¸Â´Â°ªÀ¸·Î º¯È¯µÇ´Â°Í¿¡ ÀÇÁ¸ÇÏÁö¸¶½Ê½Ã¿À. ¿¹¸¦ µé¾î UNICODE ÇÁ·Î±×·¥À» °³¹ßÇÑ´Ù¸é TTN_NEEDTEXT´Â TTN_NEEDTEXTW·Î ¹ø¿ªµÇ¾î¾ß ÇÕ´Ï´Ù. ÇÏÁö¸¸ Windows 95 ¿¡¼´Â ½ÇÁ¦ ¸Þ½ÃÁö´Â TTN_NEEDTEXTA ÀÔ´Ï´Ù. À̰ÍÀº ¶ÇÇÑ ±¸Á¶Ã¼¿Í ¹®ÀÚ¿¿¡µµ Àû¿ëµË´Ï´Ù. Windows 95 ¿¡¼´Â ÄÁÆ®·Ñ¿¡Àü´ÞµÇ´Â ¸ðµç ¹®ÀÚ¿Àº ANSI ¹®ÀÚ¿À̾î¾ß ÇÕ´Ï´Ù. NT 4.0¿¡¼± ÄÁÆ®·ÑµéÀÌ ¸ðµÎUNICODE ÄÁÆ®·ÑÀÔ´Ï´Ù.
µÑ°·Î, NT 4.0 ¿¡¼´Â ¸®½ºÆ®ºä ÄÁÆ®·ÑÀÌ ÀÚµ¿À¸·Î ÅøÆÁÄÁÆ®·ÑÀ» ¸¸µì´Ï´Ù. ÀÌ ³»Àå ÅøÆÁ ÄÁÆ®·ÑÀº ¸¶¿ì½º°¡ ¸®½ºÆ®ºä ÄÁÆ®·ÑÀ§¿¡ ¿Ã¶ó¿Í Àá½Ã ¿òÁ÷ÀÌÁö ¾ÊÀ» ¶§ ÀÚµ¿ÀûÀ¸·Î TTN_NEEDTEXTW ÅëÁö¸¦ º¸³»°Ô µË´Ï´Ù. ¾Æ·¡ÄÚµå´Â ÀÌ ³»Àå ÅøÆÁ ÄÁÆ®·Ñ·ÎºÎÅÍÀÇ ÅëÁö¸¦ ¹«½ÃÇÕ´Ï´Ù.
PreSubclassWindow()¸¦ ¿À¹ö¶óÀ̵åÇÏ°í º£À̽º Ŭ·¡½ºÀÇ PreSubclassWindow()¸¦ È£ÃâÇÑÈÄ EnableToolTips(TRUE)¸¦ È£ÃâÇÕ´Ï´Ù. EnableToolTips()ÇÔ¼ö´Â CWnd Ŭ·¡½ºÀǸâ¹ö ÇÔ¼öÀ̰í, µû¶ó¼ ¸ðµç À©µµ¿ì¿Í ÄÁÆ®·Ñ¿¡ »ç¿ëÀÌ °¡´ÉÇÕ´Ï´Ù.
void CMyListCtrl::PreSubclassWindow()
{
CListCtrl::PreSubclassWindow();
// Add initialization code
EnableToolTips(TRUE);
}
OnToolHitTest()ÇÔ¼ö¸¦ ¿À¹ö¶óÀ̵å ÇÕ´Ï´Ù. OnToolHitTest()´Â CWndŬ·¡½º¿¡ Á¤ÀÇµÈ °¡»óÇÔ¼öÀ̰í ÇÁ·¹ÀÓ¿öÅ©¿¡ ÀÇÇØ¼ ¸¶¿ì½ºÆ÷ÀÎÅͰ¡ ¾î¶²ÅøÀ§¿¡ ÀÖ´ÂÁö °áÁ¤ÇϱâÀ§ÇØÈ£ÃâµË´Ï´Ù. ÅøÀº ÄÁÆ®·Ñ À©µµ¿ìÀ̰ųª ¶Ç´Â À©µµ¿ì¾ÈÀÇ »ç°¢Çü ¿µ¿ªÀϼöµµ ÀÖ½À´Ï´Ù¿ì¸®ÀÇ ¸ñÀûÀ» À§Çؼ± °¢ ¼¿ÀÇ ¿µ¿ªÀÌ Åø·Î 󸮵Ǿî¾ß ÇÕ´Ï´Ù.
OnToolHitTest() ¹®¼(Documentation)´Â ÅøÀ» ã¾Ò´Ù¸é 1À» ¸øÃ£¾Ò´Ù¸é -1À» ¸®ÅÏÇ϶ó°í ¾Ï½ÃÇÕ´Ï´Ù.ÇÏÁö¸¸ ½ÇÁ¦·Î ÇÁ·¹ÀÓ¿öÅ©´Â ¸®ÅϰªÀ» ÅøÀÌ ¹Ù²î¾ú´ÂÁö °áÁ¤Çϴµ¥ »ç¿ëÇÕ´Ï´Ù. ÇÁ·¹ÀÓ¿öÅ©´Â ÅøÀÌ ¹Ù²î¾úÀ»¶§¸¸ ÅøÆÁÀ» °»½ÅÇϹǷÎ, OnToolHitTest()´Â ÁöÁ¤µÈ Á¡ÀÇ ¼¿ÀÌ °ª(¹®ÀÚ¿)ÀÌ ¹Ù²î¾î¾úÀ»¶§ ´Ù¸¥ °ªÀ» ¸®ÅÏÇØ¾ß ÇÕ´Ï´Ù.
int CMyListCtrl::OnToolHitTest(CPoint point, TOOLINFO * pTI) const
{
int row,
col;
RECT cellrect;
row = CellRectFromPoint(point,
&cellrect, &col );
if ( row == -1 ) return
-1;
pTI->hwnd =
m_hWnd;
pTI->uId =
(UINT)((row<<10)+(col&0x3ff)+1);
pTI->lpszText =
LPSTR_TEXTCALLBACK;
pTI->rect =
cellrect;
return pTI->uId;
}
ÀÌ ÇÔ¼ö´Â óÀ½¿¡ CellRectFromPoint() ÇÔ¼ö¸¦ È£ÃâÇÏ¿© ·Î¿ì¿Í Ä÷³, ±×¸®°í
¼¿ÀÇ °æ°è »ç°¢ÇüÀ» ¾Ë¾Æ³À´Ï´Ù.
CellRectFromPoint() ´Â ¾Æ·¡¿¡¼ »ìÆìº¾´Ï´Ù. ÇÔ¼ö´Â±×¸®°í TOOLINFO ±¸Á¶Ã¼¸¦ ¼³Á¤ÇÕ´Ï´Ù.
'uId' ´Â ÁÙ,¿ÀÇ °ªÀ» °áÇÕÇÑ °ªÀ» ÁöÁ¤ÇÕ´Ï´Ù. ·Î¿ì¿Í Ä÷³ÀÇ °áÇÕ¹æ¹ýÀº 4194303 °³ÀÇ ·Î¿ì¿Í 1023°³ÀÇ
Ä÷³À» Çã¿ëÇÕ´Ï´Ù.
¶ÇÇÑ °á°ú¿¡ 1ÀÌ ´õÇØÁø°ÍÀ» ÁÖÀÇÇϽʽÿÀ. ÀÌ·¸°Ô ÇÏ´Â ÀÌÀ¯´Â 0ÀÌ ¾Æ´Ñ°ª¸¸À» »ý¼ºÇϱâÀ§Çؼ
ÀÔ´Ï´Ù. ¿ì¸®´Â
NT4.0 ¿¡¼ ÀÚµ¿ÀûÀ¸·Î ¸¸µé¾îÁø ÅøÆÁ¿¡¼ º¸³½ ÅëÁö¿Í ±¸º°Çϱâ À§Çؼ 0ÀÌ ¾Æ´Ñ°ªÀ»
ÇÊ¿ä·Î ÇÕ´Ï´Ù. ¾Õ¿¡¼ ¾ð±ÞÇßµíÀÌ NT 4.0 ¿¡¼ ¸¸µé¾îÁø ¸®½ºÆ®ºä ÄÁÆ®·ÑÀº ÀÚµ¿ÀûÀ¸·Î ÅøÆÁÀ» »ý¼ºÇϸç ÀÌ
ÅøÆÁÀÇ ID ´Â 0ÀÔ´Ï´Ù.
´ÙÀ½ ¿ì¸®´Â OnToolHitTest() ¿¡¼ »ç¿ëµÈ CellRectFromPoint() ÇÔ¼ö¸¦ Á¤ÀÇÇÕ´Ï´Ù. ÀÌ ÇÔ¼ö´Â #1 - 4.4 ¿¡¼ ´Ù·ç¾îÁø HitTestEx() ÇÔ¼ö¿Í ¸Å¿ì ºñ½ÁÇÕ´Ï´Ù. Á¡ À§Ä¡ÀÇ ·Î¿ì ¿Í Ä÷³°ªÀ» ¾Ë¾Æ³»´Â°Í¿¡ ´õÇØ¼ ÀÌ ÇÔ¼ö´Â Á¡¾Æ·¡ ¼¿ÀÇ °æ°è »ç°¢Çüµµ ¾Ë¾Æ³À´Ï´Ù.
// CellRectFromPoint - ¼¿ÀÇ ·Î¿ì,Ä÷³,°æ°è»ç°¢ÇüÀ»
¾Ë¾Æ³À´Ï´Ù.
// Returns -
¼º°ø½Ã ·Î¿ì À妽º, ¾Æ´Ï¸é -1
// point -
°Ë»çµÉ Á¡(ÇöÀç ¸¶¿ì½º Æ÷ÀÎÅÍ)
// cellrect -
°æ°è»ç°¢ÇüÀ» ÀúÀåÇÒ º¯¼ö
// col -
Ä÷³°ªÀ» ÀúÀåÇÒ º¯¼ö
int CMyListCtrl::CellRectFromPoint(CPoint & point, RECT * cellrect, int
* col) const
{
int colnum;
// ¸®½ºÆ®ºä°¡ LVS_REPORT
¸ðµå¿¡ÀÖ´ÂÁö È®ÀÎ
if( (GetWindowLong(m_hWnd, GWL_STYLE)
& LVS_TYPEMASK) != LVS_REPORT )
return -1;
// ÇöÀç ȸ鿡 º¸ÀÌ´ÂóÀ½°ú
³¡ Row ¸¦ ¾Ë¾Æ³»±â
int row = GetTopIndex();
int bottom = row + GetCountPerPage();
if( bottom > GetItemCount()
) bottom = GetItemCount();
// Ä÷³°¹¼ö ¾Ë¾Æ³»±â
CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
int nColumnCount = pHeader->GetItemCount();
// ÇöÀ纸ÀÌ´Â Row µé°£¿¡
·çÇÁ µ¹±â
for( ;row <=bottom;row++) {
//
¾ÆÀÌÅÛÀÇ °æ°è »ç°¢ÇüÀ» °¡Á®¿À°í, Á¡ÀÌ Æ÷ÇԵǴÂÁö üũ
CRect
rect;
GetItemRect(
row, &rect, LVIR_BOUNDS );
if(
rect.PtInRect(point) ) {
// Ä÷³Ã£±â
for(
colnum = 0; colnum < nColumnCount; colnum++ ) {
int
colwidth = GetColumnWidth(colnum);
if(
point.x >= rect.left && point.x <= (rect.left + colwidth) ) {
RECT
rectClient;
GetClientRect(
&rectClient );
if(
col ) *col = colnum;
rect.right
= rect.left + colwidth;
//
¿À¸¥ÂÊ ³¡ÀÌ Å¬¶óÀÌ¾ðÆ® ¿µ¿ªÀ» ¹þ¾î³ªÁö ¾Êµµ·Ï È®ÀÎ
if(
rect.right > rectClient.right )
rect.right
= rectClient.right;
*cellrect
= rect;
return
row;
}
rect.left
+= colwidth;
}
}
}
return -1;
}
OnToolTipText()ÇÔ¼ö¸¦ Á¤ÀÇÇÕ´Ï´Ù. À̰ÍÀº ÅøÆÁÀ¸·ÎºÎÅÍÀÇ TTN_NEEDTEXTÅëÁö¿¡ ´ëÇÑ Çڵ鷯ÀÔ´Ï´Ù. ½ÇÁ¦·Î OnToolTipText()´Â TTN_NEEDTEXTA¿Í TTN_NEEDTEXTW ÅëÁö ¾çÂÊÀ» ó¸®Çϸç ÇÁ·Î±×·¥ÀÚ½ÅÀÌ ANSIµç UNICODEµç °ü°è¾øÀÌ ÀüÀÚ¸¦ À§ÇØ ANSI ½ºÆ®¸µÀ»»ç¿ëÇϸç ÈÄÀÚ¸¦ À§ÇØ UNICODE ½ºÆ®¸µÀ» »ç¿ëÇÕ´Ï´Ù.
BOOL CMyListCtrl::OnToolTipText( UINT id, NMHDR * pNMHDR, LRESULT * pResult
)
{
// ANSI ¿Í UNICODE ¾çÂʹöÁ¯ÀÇ
¸Þ½ÃÁö¸¦ ó¸®ÇؾßÇÔ
TOOLTIPTEXTA* pTTTA
= (TOOLTIPTEXTA*)pNMHDR;
TOOLTIPTEXTW* pTTTW
= (TOOLTIPTEXTW*)pNMHDR;
CString strTipText;
UINT nID =
pNMHDR->idFrom;
if( nID == 0 ) //
NT ¿¡¼ÀÇ ÀÚµ¿»ý¼º ÅøÆÁÀ¸·ÎºÎÅÍÀÇ ÅëÁö
return
FALSE; // ±×³É ºüÁ®³ª°£´Ù.
int row = ((nID-1) >>
10) & 0x3fffff ;
int col = (nID-1) & 0x3ff;
strTipText = GetItemText( row, col );
#ifndef _UNICODE
if (pNMHDR->code == TTN_NEEDTEXTA)
lstrcpyn(pTTTA->szText,
strTipText, 80);
else
_mbstowcsz(pTTTW->szText,
strTipText, 80);
#else
if (pNMHDR->code == TTN_NEEDTEXTA)
_wcstombsz(pTTTA->szText,
strTipText, 80);
else
lstrcpyn(pTTTW->szText,
strTipText, 80);
#endif
*pResult = 0;
return TRUE; //
¸Þ½ÃÁö°¡ 󸮵Ǿú´Ù.
}
ÇÔ¼ö´Â ¸ÕÀú NT¿¡¼ÀÇ ³»ÀåÅøÆÁ ÅëÁöÀÎÁö üũÇÏ°í ¸Â´Ù¸é ¹Ù·Î ¸®ÅÏÇÕ´Ï´Ù. ±×¸®°í id·ÎºÎÅÍ ·Î¿ì¿Í Ä÷³Á¤º¸¸¦ ÇØµ¶ÇÏ°í ¼¿¾ÈÀÇ Á¤º¸·Î TOOLTIPTEXT±¸Á¶Ã¼¸¦ ä¿ó´Ï´Ù.
¸Þ½ÃÁö¸Ê¿¡ OnToolTipText()¸¦ ¿¬°áÇϽʽÿÀ. ON_NOTIFY_EX ¿Í ON_NOTIFY_EX_RANGE¸ÅÅ©·Î¸¦ »ç¿ëÇÏ´Â °ÍÀÌ ÁÁ½À´Ï´Ù. À̰ÍÀº ÇÊ¿äÇÏ´Ù¸é ´õÀÌ»óÀÇ ¸Þ½ÃÁö 󸮸¦ À§ÇØ ÅëÁö¸¦ Àü´ÞÇÏ´Â °ÍÀ» °¡´ÉÇÏ°Ô ÇÕ´Ï´Ù.
BEGIN_MESSAGE_MAP(CMyListCtrl, CListCtrl)
//{{AFX_MSG_MAP(CMyListCtrl)
:
// other entries
:
//}}AFX_MSG_MAP
ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW,
0, 0xFFFF, OnToolTipText)
ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA,
0, 0xFFFF, OnToolTipText)
END_MESSAGE_MAP()
¿ì¸®°¡ ´Ü¼øÇÑ ON_NOTIFY ¸ÅÅ©·Î¸¦ »ç¿ëÇÏÁö ¾Ê´Â´Ù´Â°Í¿¡ ÁÖÀÇÇϽʽÿÀ. ½ÇÁ¦·Î ´ç½ÅÀÌ ON_NOTIFY(TTN_NEEDTEXT, 0, OnToolTipText) °°Àº ¸Þ½ÃÁö¸Ê ¿£Æ®¸®¸¦ »ç¿ëÇÑ´Ù¸é ¸î°³ÀÇ Å« ¹®Á¦Á¡À» °¡Áö°Ô µË´Ï´Ù. ù°·Î TTN_NEEDTEXT ÅëÁö´Â ANSI ºôµå¹öÁ¯¿¡¼± NT 4.0 »ó¿¡¼´Â Àý´ë·Î ¹ÞÀ»¼ö ¾ø´Â TTN_NEEDTEXTA ·Î º¯È¯µË´Ï´Ù. µÑ°·Î, ¿ì¸®´Â ÀϹÝÀûÀÎ °æ¿ì°¡ ¾Æ´Ñ ID 0 ÀÌ¿ÜÀÇ °ª¿¡ °ü½ÉÀÌ ÀÖ´Ù´Â °ÍÀÔ´Ï´Ù.
9.4 °¢ ¼¿À» À§ÇÑ Å¸ÀÌÆ²ÆÁ
ŸÀÌÆ²Àº ´Ù¼Ò ÅøÆÁ°ú ºñ½ÁÇÕ´Ï´Ù. ¸®½ºÆ®ºä ÄÁÆ®·Ñ¿¡ ´ëÇØ¼, ŸÀÌÆ²ÆÁÀº ÅØ½ºÆ®¸¦ ´Ù º¸¿©ÁÙ¼ö ÀÖÀ»¸¸Å ³ÐÁö ¸øÇÒ ¶§ »ç¿ëµË´Ï´Ù. ŸÀÌÆ²ÆÁÀº ¸¶¿ì½º°¡ ¼¿ÀÇ À§¿¡ À§Ä¡ÇÏÁö¸¶ÀÚ º¸¿©Áö°Ô µË´Ï´Ù.
¿ì¸®´Â ŸÀÌÆ²ÆÁÀ» À§ÇØ Ä¿½ºÅÒŬ·¡½º¸¦ Á¤ÀÇÇÕ´Ï´Ù. ŸÀÌÆ²ÆÁÀº WM_MOUSEMOVE Çڵ鷯¿¡¼ »ý¼ºµË´Ï´Ù. ŸÀÌÆ² ÆÁÀº ¸¶¿ì½º°¡ ¾ÆÀÌÅÛ ¹ÛÀ¸·Î ³ª°¡°Å³ª ÀÀ¿ëÇÁ·Î±×·¥ÀÌ Æ÷Ä¿½º¸¦ ÀÒÀ»¶§ ÀÚ±â ÀÚ½ÅÀ» ÆÄ±«ÇÏ°Ô µË´Ï´Ù.
OnMouseMove() ÄÚµå´Â CellRectFromPoint() ÇÔ¼ö¸¦ ·Î¿ì,Ä÷³À妽º¿Í ÇϺξÆÀÌÅÛÀÇ °æ°è¿µ¿ª »ç°¢ÇüÀ» ¾Ë¾Æ³»±â À§ÇØ »ç¿ëÇÕ´Ï´Ù. ±×¸®°í ŸÀÌÆ²ÆÁ °´Ã¼¿¡ »ç°¢Çü°ú ¾ÆÀÌÅÛ ÅØ½ºÆ®ÀÇ Á¤º¸¸¦ ³Ñ±â°Ô µË´Ï´Ù. ŸÀÌÆ²ÆÁ°´Ã¼°¡ ȸ鿡 º¸¿©ÁúÁö¸¦ °áÁ¤ÇϰԵ˴ϴÙ.
void CMyListCtrl::OnMouseMove(UINT nFlags, CPoint point)
{
if( nFlags == 0 ) { //
ŸÀÌÆ²ÆÁ °´Ã¼ Enable Çϱâ À§Çؼ
int
row, col;
RECT
cellrect;
row
= CellRectFromPoint(point, &cellrect, &col );
if(
row != -1 ) {
int
offset = 5; // Ä÷³ ¿ÞÂÊ °æ°è¿¡¼ºÎÅÍÀÇ ¿ÀÇÁ¼ÂÀº º¸Åë 5Çȼ¿
//
ù¹øÂ° Ä÷³¿¡ ´ëÇØ¼± ¿ÀÇÁ¼ÂÀº ±×¸²À» °í·ÁÇØ¾ß ÇÕ´Ï´Ù.
//
¾Æ·¡¿ÀÇÁ¼ÂÀº ÀÚ±âÀÚ½ÅÀÇ ÇÁ·Î±×·¥¿¡ ¸Â´Â°ªÀ» »ç¿ëÇϽʽÿÀ
if(
col == 0 ) offset+=19;
m_titletip.Show(
cellrect, GetItemText( row, col ), offset );
}
}
CListCtrl::OnMouseMove(nFlags,
point);
}
PreSubclassWindow() ÇÔ¼ö°¡ ¿À¹ö¶óÀÌµå µÇ¾îÀÖÁö ¾Ê´Ù¸é, ÇØ¾ßÇÕ´Ï´Ù. ÀÌ ÇÔ¼ö¿¡¼Å¸ÀÌÆ²ÆÁ °´Ã¼¸¦ »ý¼ºÇÒ°ÍÀÔ´Ï´Ù.
void CMyListCtrl::PreSubclassWindow()
{
CListCtrl::PreSubclassWindow();
// Add initialization code
m_titletip.Create( this );
}
Çì´õÆÄÀϰú ±¸ÇöÆÄÀÏÀÌ ¾Æ·¡ ÀÖ½À´Ï´Ù.
#if !defined( AFX_TITLETIP_H__FB05F243_E98F_11D0_82A3_20933B000000__INCLUDED_
)
#define AFX_TITLETIP_H__FB05F243_E98F_11D0_82A3_20933B000000__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// TitleTip.h : header file
// CTitleTip window
#define TITLETIP_CLASSNAME _T("ZTitleTip")
class CTitleTip : public CWnd
{
public: // Construction
CTitleTip();
public: // Attributes
public: // Operations
//Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CTitleTip)
public:
virtual BOOL PreTranslateMessage(MSG*
pMsg);
//}}AFX_VIRTUAL
public: //
Implementation
void
Show( CRect rectTitle, LPCTSTR lpszTitleText, int xoffset = 0);
virtual
BOOL Create( CWnd *pParentWnd);
virtual
~CTitleTip();
protected:
CWnd
*m_pParentWnd;
CRect
m_rectTitle;
protected: //
Generated message map functions
//{{AFX_MSG(CTitleTip)
afx_msg void OnMouseMove(UINT
nFlags, CPoint point);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately//
before the previous line.
#endif // !defined(AFX_TITLETIP_H__FB05F243_E98F_11D0_82A3_20933B000000__INCLUDED_)
CTitleTip ÀÇ »ý¼ºÀÚ¿¡¼ ÀÌ ÇÁ·Î±×·¥ÀÇ ´Ù¸¥ ÀνºÅϽº¿¡¼ À©µµ¿ìÀÇ Å¬·¡½º¸¦ µî·ÏÇÏÁö ¾Ê¾Ò´Ù¸é µî·ÏÇÏ°Ô µË´Ï´Ù. Ŭ·¡½º¿¡ ´ëÇÑ ¹è°æ ºê·¯½¬´Â COLOR_INFOBK¸¦»ç¿ëÇÏ°Ô µÇ¾î ÅøÆÁÀÇ »ö»ó°ú °°°Ô µË´Ï´Ù.
Create() ÇÔ¼ö¿¡¼´Â ÁÖ¸ñÇØ¼ º¼°ÍÀÌ À©µµ¿ì ½ºÅ¸ÀÔ´Ï´Ù. WS_BORDER ½ºÅ¸ÀÏÀÌ Å¸ÀÌÆ²ÆÁ À©µµ¿ì ÁÖÀ§¿¡ °æ°è¼±À» ±×¸®°Ô ÇÕ´Ï´Ù. WS_POPUP½ºÅ¸ÀÏÀº ŸÀÌÆ²ÆÁÀÌ ¸®½ºÆ®ºä ÄÁÆ®·ÑÀÇ °æ°è¸¦ ¹þ¾î³¯¼öµµ ÀÖ°Ô ÇϱâÀ§ÇØ ÇÊ¿äÇÕ´Ï´Ù. WS_EX_TOOLWINDOW½ºÅ¸ÀÏÀº À©µµ¿ì°¡ ŽºÅ©¹Ù¿¡ ³ªÅ¸³ªÁö ¾Êµµ·Ï ÇØÁÝ´Ï´Ù. WS_EX_TOPMOST ½ºÅ¸ÀÏÀº ŸÀÌÆ²ÆÁÀÌ º¸À̵µ·Ï ÇØÁÝ´Ï´Ù.
Show() ÇÔ¼ö´Â ÅØ½ºÆ®ÀÇ Å©±â°¡ ¼¿ÀÇ Å©±âº¸´Ù Ŭ¶§ ŸÀÌÆ²ÆÁÀ» º¸¿©ÁÖ°Ô µË´Ï´Ù. °æ°è »ç°¢ÇüÀº º¯ÇüµÇ°í ³ªÁß¿¡ ¾ðÁ¦ ŸÀÌÆ²ÆÁÀÌ ¼û°ÜÁ®¾ß ÇÒ¶§¸¦ °áÁ¤Çϱâ À§ÇØ ÀúÀåµË´Ï´Ù.
WM_MOUSEMOVE ¿¡ ´ëÇÑ Çڵ鷯 OnMouseMove() ´Â ŸÀÌÆ²ÆÁÀÌ º¸ÀÏ ¼¿¿µ¿ª¿¡ ¸¶¿ì½º°¡ÀÖ´ÂÁö¸¦ °Ë»çÇÕ´Ï´Ù. ÀÌ ¿µ¿ªÀº ŸÀÌÆ²ÆÁ À©µµ¿ìÀÇ Å¬¶óÀÌ¾ðÆ® ¿µ¿ª »ç°¢Çüº¸´Ù ÀÛ½À´Ï´Ù. ¸¸¾à ¸¶¿ì½º°¡ ¿µ¿ª¹ÛÀ¸·Î ³ª°£´Ù¸é ŸÀÌÆ²ÀÌ ¼û°ÜÁö°í ÀûÀýÇÑ À©µµ¿ì¿¡ WM_MOUSEMOVE ¸Þ½ÃÁö°¡ Àü´ÞµË´Ï´Ù.
ŸÀÌÆ²ÆÁÀº ¶ÇÇÑ »ç¿ëÀÚ°¡ Ű³ª ¸¶¿ì½º¹öưÀ» ´·¶À»¶§ ¾ø¾îÁú Çʿ䰡 ÀÖ½À´Ï´Ù. ¿ì¸®´Â À̸޽ÃÁöµé¿¡ ´ëÇØ »ìÆìº¸±â À§ÇØ PreTranslateMessage()¸¦ ¿À¹ö¶óÀ̵å ÇÕ´Ï´Ù. ¸¸¾à ÀÌ ¸Þ½ÃÁöµéÁß¿¡ ¾î¶²°ÍÀÌ¶óµµ ¹Þ´Â´Ù¸é ŸÀÌÆ²ÆÁÀº ¾ø¾îÁö°í ¸®½ºÆ®ºä ÄÁÆ®·Ñ¿¡ ¸Þ½ÃÁö°¡ Àü´ÞµË´Ï´Ù.
// TitleTip.cpp : implementation file
#include "stdafx.h"
#include "TitleTip.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[]
= __FILE__;
#endif
// CTitleTip
CTitleTip::~CTitleTip() { }
CTitleTip::CTitleTip()
{
// ¸¸¾à ÀÌ¹Ì µî·ÏµÇÁö ¾Ê¾Ò´Ù¸é
À©µµ¿ì Ŭ·¡½º¸¦ µî·ÏÇÑ´Ù.
WNDCLASS wndcls;
HINSTANCE hInst = AfxGetInstanceHandle();
if(!(::GetClassInfo(hInst, TITLETIP_CLASSNAME,
&wndcls))) {
//
»õ·Î¿î Ŭ·¡½º µî·Ï
wndcls.style
=
CS_SAVEBITS ;
wndcls.lpfnWndProc
= ::DefWindowProc;
wndcls.cbClsExtra =
wndcls.cbWndExtra = 0;
wndcls.hInstance =
hInst;
wndcls.hIcon =
NULL;
wndcls.hCursor =
LoadCursor( hInst, IDC_ARROW );
wndcls.hbrBackground =
(HBRUSH)(COLOR_INFOBK + 1);
wndcls.lpszMenuName =
NULL;
wndcls.lpszClassName =
TITLETIP_CLASSNAME;
if
(!AfxRegisterClass(&wndcls)) AfxThrowResourceException();
}
}
BEGIN_MESSAGE_MAP(CTitleTip, CWnd)
//{{AFX_MSG_MAP(CTitleTip)
ON_WM_MOUSEMOVE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
// CTitleTip message handlers
BOOL CTitleTip::Create(CWnd * pParentWnd)
{
ASSERT_VALID(pParentWnd);
DWORD dwStyle = WS_BORDER
| WS_POPUP;
DWORD dwExStyle = WS_EX_TOOLWINDOW
| WS_EX_TOPMOST;
m_pParentWnd = pParentWnd;
return CreateEx( dwExStyle, TITLETIP_CLASSNAME, NULL,
dwStyle, 0, 0, 0, 0, NULL, NULL, NULL );
}
void CTitleTip::Show(CRect rectTitle,LPCTSTR lpszTitleText,int xoffset /*=0*/)
{
ASSERT( ::IsWindow( m_hWnd )
);
ASSERT( !rectTitle.IsRectEmpty()
);
if( IsWindowVisible() ) return;
m_rectTitle.top = -1;
m_rectTitle.left =
-xoffset;
m_rectTitle.right =
rectTitle.Width()-xoffset;
m_rectTitle.bottom =
rectTitle.Height();
m_pParentWnd->ClientToScreen(
rectTitle );
CClientDC dc(this);
CString strTitle(lpszTitleText);
CFont *pFont = m_pParentWnd->GetFont();
CFont *pFontDC = dc.SelectObject(
pFont );
CRect rectDisplay = rectTitle;
CSizesize = dc.GetTextExtent(
strTitle );
rectDisplay.left += xoffset;
rectDisplay.right = rectDisplay.left
+ size.cx + 5;
// ¸¸¾à ÅØ½ºÆ®°¡ °ø°£¿¡ ¸Â´Ù¸é
º¸ÀÌÁö ¾Ê´Â´Ù.
if( rectDisplay.right <= rectTitle.right-xoffset ) return;
SetWindowPos( &wndTop,
rectDisplay.left, rectDisplay.top,
rectDisplay.Width(),
rectDisplay.Height(),
SWP_SHOWWINDOW|SWP_NOACTIVATE
);
dc.SetBkMode( TRANSPARENT
);
dc.TextOut( 0, -1, strTitle
);
dc.SelectObject( pFontDC );
SetCapture();
}
void CTitleTip::OnMouseMove(UINT nFlags, CPoint point)
{
if( !m_rectTitle.PtInRect( point
) ) {
ReleaseCapture();
ShowWindow(
SW_HIDE );
//
¸Þ½ÃÁö¸¦ Àü´ÞÇÑ´Ù.
ClientToScreen(
&point );
CWnd
*pWnd = WindowFromPoint( point );
if(
pWnd == this ) pWnd = m_pParentWnd;
pWnd->ScreenToClient(
&point );
pWnd->PostMessage(WM_MOUSEMOVE,
nFlags, MAKELONG( point.x, point.y ));
}
}
BOOL CTitleTip::PreTranslateMessage(MSG* pMsg)
{
CWnd *pWnd;
switch( pMsg->message ) {
case
WM_LBUTTONDOWN:
case
WM_RBUTTONDOWN:
case
WM_MBUTTONDOWN:
POINTS
pts = MAKEPOINTS( pMsg->lParam );
POINT
point;
point.x
= pts.x;
point.y
= pts.y;
ClientToScreen(
&point );
pWnd
= WindowFromPoint( point );
if(
pWnd == this ) pWnd = m_pParentWnd;
pWnd->ScreenToClient(
&point );
pMsg->lParam
= MAKELONG( point.x, point.y );
//
±×³É ¹ØÀ¸·Î °¡°Ô ÇÕ´Ï´Ù.
case
WM_KEYDOWN:
case
WM_SYSKEYDOWN:
ReleaseCapture(
);
ShowWindow(
SW_HIDE );
m_pParentWnd->PostMessage(pMsg->message,
pMsg->wParam, pMsg->lParam);
return
TRUE;
}
if( GetFocus() == NULL ) {
ReleaseCapture();
ShowWindow(
SW_HIDE );
return
TRUE;
}
return CWnd::PreTranslateMessage(pMsg);
}
- the end of this article -