1. 일반 다이얼로그 상에서 Menu 리소스를 추가한다.
2. 메뉴를 구성한다.
3. 다이얼로그 프로퍼티에서 Menu를 추가해준다.
4. 기타 이벤트에 관한사항을 처리한다.
CHoverButton 을 CBitmapButton을 상속받아 생성한다.
WM_DRAWITEM이 아닌 DrawItem을 Overriding 한다.
CDC *mydc = CDC::FromHandle(lpDrawItemStruct->hDC);
CDC *pMemDC = new CDC;
pMemDC->CreateCompatibleDC(mydc);CBitmap *pOldBitmap;
pOldBitmap = pMemDC->SelectObject(&mybitmap); //사용하는 클래스에서 Load한 비트맵을 올린다.CPoint point(0, 0);
if(lpDrawItemStruct->itemState & ODS_SELECTED)
{
mydc->BitBlt(0, 0, m_ButtonSize.cx, m_ButtonSize.cy, pMemDC, m_ButtonSize.cx, 0, SRCCOPY);
}
else
{if(m_bHover)
{
mydc->BitBlt(0, 0, m_ButtonSize.cx, m_ButtonSize.cy, pMemDC, m_ButtonSize.cx * 2, 0, SRCCOPY);
}
else
{
mydc->BitBlt(0, 0, m_ButtonSize.cx, m_Button.cy, pMemDC, 0, 0, SRCCOPY);
}
}pMemDC->SelectObject(pOldBitmap);
delete pMemDC;
위와 같이 소스를 작성한다.
m_bHover를 생성자에서 FALSE로 초기화 한다.
mybitmap과 m_ButtonSize는 LoadBitmap(…) 에서 초기화 한다.
BOOL CHoverButton::LoadBitmap(UINT bitmapid) 의 멤버 함수를 선언한다. 호출하는 클래스에서 사용하고자 하는 클래스의 아이디값을 넘겨주면서 호출한다.
mybitmap.Attach(::LoadImage(::AfxGetInstanceHandle(), MAKEINTRESOURCE(bitmapid), IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS));
BITMAP bitmapbits;
mybitmap.GetBitmap(&bitmapbits);
m_ButtonSize.cy = bitmapbits.bmHeight;
//비트맵이 3가지 상태의 그림으로 되어 있으므로
m_ButtonSize.cx = bitmapbits.bmWidth/3;
SetWindowPos(NULL, 0, 0, m_ButtonSize.cx, m_ButtonSize.cy,
SWP_NOMOVE | SWP_NOOWNERZORDER);
return TRUE;
위와 같이 작성한다.
PretranslateMessage를 Overriding 한다.
InitToolTip();
m_ToolTip.RelayEvent(pMsg);
return CButton::PreTranslateMessage(pMsg);
툴팁을 초기화한다.
InitToolTip() 멤버함수를 생성한다.
if(m_ToolTip.m_hWnd == NULL)
{
//ToolTip 컨트롤 생성
m_ToolTip.Create(this);
m_ToolTip.Activate(FALSE);
}
생성된 툴팁이 없을경우 툴팁을 생성한다.
클래스 위자드를 이용하여 WM_MOUSEMOVE 이벤트핸들러 함수를 생성한다.
if(!m_bTracking)
{
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(tme);
tme.hwndTrack = m_hWnd;
tme.dwFlags = TME_LEAVE | TME_HOVER;
tme.dwHoverTime = 1;
m_bTracking = _TrackMouseEvent(&tme);
}
CButton::OnMouseMove(nFlags, point);
마우스의 두가지 이벤트를 더 추가한다. 이 부분은 클래스 위자드를 사용하지 않고 직접 코드를 추가한다.
우선 헤더파일에 추가한다.
//{{AFX_MSG(CHoverButton)
afx_msg void OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
//아래의 두가지를 더 추가한다.
afx_msg LRESULT OnMouseLeave(WPARAM wparam, LPARAM lparam);
afx_msg void OnMouseHover(WPARAM wparam, LPARAM lparam);
//}}AFX_MSG
이제는 cpp에 추가를 한다.
BEGIN_MESSAGE_MAP(CHoverButton, CButton)
//{{AFX_MSG_MAP(CHoverButton)
ON_WM_DRAWITEM()
ON_WM_MOUSEMOVE()
//아래 두개의 메세지 핸들러함수를 추가한다.
ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
ON_MESSAGE(WM_MOUSEHOVER, OnMouseHover)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
.
.
.void CHoverButton::OnMouseHover(WPARAM wparam, LPARAM lparam)
{
m_bHover = TRUE;
Invalidate();
}LRESULT CHoverButton::OnMouseLeave(WPARAM wparam, LPARAM lparam)
{
m_bTracking = FALSE;
m_bHover = FALSE;
Invalidate();
return 0;
}
툴팁에 나타낼 내용을 지정할 멤버함수인 SetToolTipText(…) 를 Overloading 하여 두가지로 생성한다.
void CHoverButton::SetToolTipText(int nId, BOOL bActivate)
{
CString sText;//리소스의 스트링을 로드한다.
sText.LoadString(nId);
//만약 스트링 리소스가 비어 있다면
if(sText.IsEmpty == FALSE)
SetToolTipText(&sText, bActivate);
}void CHoverButton::SetToolTipText(CString *spText, BOOL bActivate)
{
//null 포인터는 접근 할수 없다.
if(spText == NULL)
return;InitToolTip(); //툴팁을 초기화 한다.
if(m_ToolTip.GetToolCount() == 0)
{
CRect rectBtn;
GetClientRect(rectBtn);
m_ToolTip.AddTool(this, (LPCTSTR)*spText, rectBtn, 1);
}m_ToolTip.UpdateTipText((LPCTSTR)*spText, this, 1);
m_ToolTip.Activate(bActivate);}
툴팁의 활성화를 조정하는 ActivateTooltip(…)을 생성한다.
//툴팁이 생성된게 아무것도 없으면…
if(m_ToolTip.GetToolCount() == 0)
return;//툴팁을 활성화 한다.
m_ToolTip.Activate(bActivate);
와 같이 코드를 작성한다.
사용할때는 사용하고자 하는 클래스의 헤더파일에서
#include “HoverButton.h”
를 해준다.
by Redef( http://www.redef.pe.kr )
안녕하세요.
CHoverButton을 다운받아서 해봤는데 잘동작은 하는데요.
작업관리자로 열어서 보기-열선택-GDI개체수를 체크해놓고 보면 지속적으로 증가합니다.
결국 10000개를 넘어가면서 프로그램은 죽고, 비주얼 스튜디오에서 CHoverButton의 DrawItem()에 있는
delete pMemDC; 를 가르키고 있습니다. CHoverButton의 버그인가요?
코드상으로는 잘 이해가 가질 않아서요. 문제가 없는것 같은데...알려주실 수 있나요?
혹시 공개하셔도 된다면 작성하신 소스를 제가 좀 볼수있을까요?
http://www.redef.pe.kr/search/profile 여기보시면 제 연락처가 있습니다.
댓글을 달아 주세요