给CListBox增加个性化的ToolTip
转载请注明来源:http://www.cnblogs.com/xuesongshu/
【步骤】
1、新建一个MFC应用程序项目,无项目设置要求
2、添加一个对话框,添加一个ListBox,无属性设置要求,ListBox宽度最好设小点,以突出效果。
3、添加CShellExcuteString类,ShellExcuteString.h代码如下:
#ifndef _HYPRILNK_H
#define _HYPRILNK_H
class CShellExcuteString:public CString
{
public:
CShellExcuteString(LPCTSTR lpLink=NULL):CString(lpLink) {}
~CShellExcuteString() {}
const CShellExcuteString& operator=(LPCTSTR lpsz)
{
CString::operator=(lpsz);
return*this;
}
operator LPCTSTR()
{
return CString::operator LPCTSTR();
}
virtual HINSTANCE Navigate()
{
return IsEmpty()?NULL:ShellExecute(0,_T("open"),*this,0,0,SW_SHOWNORMAL);
}
};
#endif
4、添加CHookWindowObject类,HookWindowObject.h代码如下:
#ifndef _SUBCLASSW_H
#define _SUBCLASSW_H
class CHookWindowObject:public CObject
{
public:
CHookWindowObject();
~CHookWindowObject();
BOOL HookWindow(HWND hwnd);
BOOL HookWindow(CWnd *pWnd)
{
return HookWindow(pWnd->GetSafeHwnd());
}
void Unhook()
{
HookWindow((HWND)NULL);
}
BOOL IsHooked()
{
return m_hWnd!=NULL;
}
friend LRESULT CALLBACK HookWndProc(HWND,UINT,WPARAM,LPARAM);
friend class CHookWindowMap;
virtual LRESULT WindowProc(UINT msg,WPARAM wp,LPARAM lp);
LRESULT Default();//call this at the end of handler fns
#ifdef _DEBUG
virtual void AssertValid()const;
virtual void Dump(CDumpContext&dc)const;
#endif
protected:
HWND m_hWnd;//the window hooked
WNDPROC m_pOldWndProc;//..and original window proc
CHookWindowObject *m_pNext;//next in chain of hooks for this window
DECLARE_DYNAMIC(CHookWindowObject);
};
#endif//_SUBCLASSW_H
HookWindowObject.cpp代码如下:
IMPLEMENT_DYNAMIC(CHookWindowObject,CWnd);
CHookWindowObject::CHookWindowObject()
{
m_pNext=NULL;
m_pOldWndProc=NULL;
m_hWnd=NULL;
}
CHookWindowObject::~CHookWindowObject()
{
if(m_hWnd)
HookWindow((HWND)NULL);//unhook window
}
BOOL CHookWindowObject::HookWindow(HWND hwnd)
{
ASSERT_VALID(this);
if(hwnd)
{
//Hook the window
ASSERT(m_hWnd==NULL);
ASSERT(::IsWindow(hwnd));
theHookMap.Add(hwnd,this);//Add to map of hooks
}
else if(m_hWnd)
{
//Unhook the window
theHookMap.Remove(this);//Remove from map
m_pOldWndProc=NULL;
}
m_hWnd=hwnd;
return TRUE;
}
LRESULT CHookWindowObject::WindowProc(UINT msg,WPARAM wp,LPARAM lp)
{
//ASSERT_VALID(this);//removed for speed
ASSERT(m_pOldWndProc);
return m_pNext?m_pNext->WindowProc(msg,wp,lp):
::CallWindowProc(m_pOldWndProc,m_hWnd,msg,wp,lp);
}
LRESULT CHookWindowObject::Default()
{
//MFC stores current MSG in thread state
MSG &curMsg=AfxGetThreadState()->m_lastSentMsg;
//Note:must explicitly call CHookWindowObject::WindowProc to avoid infinte
//recursion on virtual function
return CHookWindowObject::WindowProc(curMsg.message,curMsg.wParam,curMsg.lParam);
}
#ifdef _DEBUG
void CHookWindowObject::AssertValid() const
{
CObject::AssertValid();
ASSERT(m_hWnd==NULL||::IsWindow(m_hWnd));
if(m_hWnd)
{
for(CHookWindowObject *p=theHookMap.Lookup(m_hWnd); p; p=p->m_pNext)
{
if(p==this)
break;
}
ASSERT(p);//should have found it!
}
}
void CHookWindowObject::Dump(CDumpContext&dc)const
{
CObject::Dump(dc);
}
#endif
/////////////////
//Find first hook associate with window
//
CHookWindowObject *CHookWindowMap::Lookup(HWND hwnd)
{
CHookWindowObject *pFound=NULL;
if(!CMapPtrToPtr::Lookup(hwnd,(void*&)pFound))
return NULL;
ASSERT_KINDOF(CHookWindowObject,pFound);
return pFound;
}
5、添加CHookWindowMap类,代码放在HookWindowObject.cpp头部,代码如下:
class CHookWindowMap:private CMapPtrToPtr
{
public:
CHookWindowMap();
~CHookWindowMap();
static CHookWindowMap &GetHookMap();
void Add(HWND hwnd,CHookWindowObject *pNewHook);
void Remove(CHookWindowObject *pOldHook);
void RemoveAll(HWND hwnd);
CHookWindowObject*Lookup(HWND hwnd);
};
#define theHookMap (CHookWindowMap::GetHookMap())
CHookWindowMap::CHookWindowMap()
{
}
CHookWindowMap::~CHookWindowMap()
{
//This assert bombs when posting WM_QUIT,so I've deleted it.
//ASSERT(IsEmpty());//all hooks should be removed!
}
CHookWindowMap &CHookWindowMap::GetHookMap()
{
//By creating theMap here,C++doesn't instantiate it until/unless
//it's ever used!This is a good trick to use in C++,to
//instantiate/initialize a static object the first time it's used.
//
static CHookWindowMap theMap;
return theMap;
}
/////////////////
//Add hook to map;i.e.,associate hook with window
//
void CHookWindowMap::Add(HWND hwnd,CHookWindowObject *pNewHook)
{
ASSERT(hwnd&&::IsWindow(hwnd));
//Add to front of list
pNewHook->m_pNext=Lookup(hwnd);
SetAt(hwnd,pNewHook);
if(pNewHook->m_pNext==NULL)
{
//If this is the first hook added,subclass the window
pNewHook->m_pOldWndProc=(WNDPROC)SetWindowLong(hwnd,GWL_WNDPROC,(DWORD)HookWndProc);
}
else
{
//just copy wndproc from next hook
pNewHook->m_pOldWndProc=pNewHook->m_pNext->m_pOldWndProc;
}
ASSERT(pNewHook->m_pOldWndProc);
}
//////////////////
//Remove hook from map
//
void CHookWindowMap::Remove(CHookWindowObject *pUnHook)
{
HWND hwnd=pUnHook->m_hWnd;
ASSERT(hwnd&&::IsWindow(hwnd));
CHookWindowObject *pHook=Lookup(hwnd);
ASSERT(pHook);
if(pHook==pUnHook)
{
//hook to remove is the one in the hash table:replace w/next
if(pHook->m_pNext)
SetAt(hwnd,pHook->m_pNext);
else
{
//This is the last hook for this window:restore wnd proc
RemoveKey(hwnd);
SetWindowLong(hwnd,GWL_WNDPROC,(DWORD)pHook->m_pOldWndProc);
}
}
else
{
//Hook to remove is in the middle:just remove from linked list
while(pHook->m_pNext!=pUnHook)
pHook=pHook->m_pNext;
ASSERT(pHook&&pHook->m_pNext==pUnHook);
pHook->m_pNext=pUnHook->m_pNext;
}
}
//////////////////
//Remove all the hooks for a window
//
void CHookWindowMap::RemoveAll(HWND hwnd)
{
CHookWindowObject*pSubclassWnd;
while((pSubclassWnd=Lookup(hwnd))!=NULL)
pSubclassWnd->HookWindow((HWND)NULL);//(unhook)
}
6、添加全局函数HookWindowProc,代码如下:
LRESULT CALLBACK HookWndProc(HWND hwnd,UINT msg,WPARAM wp,LPARAM lp)
{
#ifdef _USRDLL
//If this is a DLL,need to set up MFC state
AFX_MANAGE_STATE(AfxGetStaticModuleState());
#endif
//Set up MFC message state just in case anyone wants it
//This is just like AfxCallWindowProc,but we can't use that because
//a CHookWindowObject is not a CWnd.
//
MSG &curMsg=AfxGetThreadState()->m_lastSentMsg;
MSG oldMsg=curMsg;//save for nesting
curMsg.hwnd=hwnd;
curMsg.message=msg;
curMsg.wParam=wp;
curMsg.lParam=lp;
//Get hook object for this window.Get from hook map
CHookWindowObject *pSubclassWnd=theHookMap.Lookup(hwnd);
ASSERT(pSubclassWnd);
LRESULT lr;
if(msg==WM_NCDESTROY)
{
//Window is being destroyed:unhook all hooks(for this window)
//and pass msg to orginal window proc
//
WNDPROC wndproc=pSubclassWnd->m_pOldWndProc;
theHookMap.RemoveAll(hwnd);
lr=::CallWindowProc(wndproc,hwnd,msg,wp,lp);
}
else
{
//pass to msg hook
lr=pSubclassWnd->WindowProc(msg,wp,lp);
}
curMsg=oldMsg;//pop state
return lr;
}
7、添加CHookWindowTipHandler类,HookWindowTipHandler.h代码如下:
#pragma once
#include "HookWindowObject.h"
#include "ToolTipWnd.H"
class CHookWindowTipHandler:public CHookWindowObject
{
protected:
UINT m_idMyControl;//id of list box control
UINT m_nCurItem;//index of current item
BOOL m_bCapture;//whether mouse is captured
static CToolTipWnd g_wndTip;//THE tip window
//subclass window proc
virtual LRESULT WindowProc(UINT msg,WPARAM wp,LPARAM lp);
//virtual fns you can override
virtual void OnMouseMove(CPoint p);
virtual BOOL IsRectCompletelyVisible(const CRect&rc);
virtual UINT OnGetItemInfo(CPoint p,CRect&rc,CString&s);
public:
CHookWindowTipHandler();
~CHookWindowTipHandler();
static UINT g_nTipTimeMsec;//global:msec wait before showing tip
void Init(CWnd*pListBox);//initialize
};
HookWindowTipHandler.cpp代码如下:
#include "stdafx.h"
#include "ToolTipWnd.H"
#include "HookWindowTipHandler.h"
#include <afxcoll.h>
#include <windowsx.h>
//THE popup tip window
CToolTipWnd CHookWindowTipHandler::g_wndTip;
//Timeout before showing long listbox tip--you can change
UINT CHookWindowTipHandler::g_nTipTimeMsec=100;//.1 sec
CHookWindowTipHandler::CHookWindowTipHandler()
{
m_nCurItem=-1;
m_bCapture=FALSE;
}
CHookWindowTipHandler::~CHookWindowTipHandler()
{
}
//////////////////
//Install hook.Initialize control ID from list box and create
//(invisible)tip window.
//
void CHookWindowTipHandler::Init(CWnd *pListBox)
{
CHookWindowObject::HookWindow(pListBox);
m_idMyControl=pListBox->GetDlgCtrlID();
if(!g_wndTip)
{
//create scroll tip window
g_wndTip.Create(CPoint(0,0),pListBox,PTS_TRANSPARENT);
}
}
LRESULT CHookWindowTipHandler::WindowProc(UINT msg,WPARAM wp,LPARAM lp)
{
switch(msg)
{
case WM_MOUSEMOVE:
OnMouseMove(CPoint(GET_X_LPARAM(lp),GET_Y_LPARAM(lp)));
break;
case WM_LBUTTONDOWN:
g_wndTip.Cancel();//cancel popup text if any
break;
}
return CHookWindowObject::WindowProc(msg,wp,lp);
}
void CHookWindowTipHandler::OnMouseMove(CPoint pt)
{
CListBox *pListBox=(CListBox*)CWnd::FromHandle(m_hWnd);
if(!m_bCapture)
{
::SetCapture(m_hWnd);
m_bCapture=TRUE;
}
//Get text and text rectangle for item under mouse
CString sText;//item text
CRect rcText;//item text rect
UINT nItem=OnGetItemInfo(pt,rcText,sText);
if(nItem==-1||nItem!=m_nCurItem)
{
g_wndTip.Cancel();//new item,or no item:cancel popup text
if(nItem>=0&&!IsRectCompletelyVisible(rcText))
{
//new item,and not wholly visible:prepare popup tip
CRect rc=rcText;
pListBox->ClientToScreen(&rc);//text rect in screen coords
g_wndTip.SetWindowText(sText);//set tip text to that of item
//move tip window over list text
g_wndTip.SetWindowPos(NULL,rc.left-3,rc.top,rc.Width()*2,rc.Height()*2,SWP_NOZORDER|SWP_NOACTIVATE);
g_wndTip.ShowDelayed(g_nTipTimeMsec);//show popup text delayed
}
}
m_nCurItem=nItem;
if(nItem==-1)
{
::ReleaseCapture();
m_bCapture=FALSE;
}
}
BOOL CHookWindowTipHandler::IsRectCompletelyVisible(const CRect&rc)
{
CListBox *pListBox=(CListBox*)CWnd::FromHandle(m_hWnd);
CRect rcClient;
pListBox->GetClientRect(&rcClient);
return rcClient.Width()>rc.Width();
}
UINT CHookWindowTipHandler::OnGetItemInfo(CPoint p,CRect&rc,CString&s)
{
CListBox *pListBox=(CListBox*)CWnd::FromHandle(m_hWnd);
ASSERT_VALID(pListBox);
BOOL bOutside;
UINT nItem=pListBox->ItemFromPoint(p,bOutside);
s.Empty();
if(!bOutside)
{
pListBox->GetText(nItem,s);
pListBox->GetItemRect(nItem,&rc);
CFont *pFont=pListBox->GetFont();
CClientDC dc(pListBox);
CFont *pOldFont=dc.SelectObject(pFont);
dc.DrawText(s,&rc,DT_CALCRECT);
dc.SelectObject(pOldFont);
return nItem;
}
return -1;
}
8、添加CLinkStatic类,LinkStatic.h代码如下:
#ifndef _STATLINK_H
#define _STATLINK_H
#include "ShellExcuteString.H"
class CLinkStatic:public CStatic
{
public:
DECLARE_DYNAMIC(CLinkStatic)
CLinkStatic(LPCTSTR lpText=NULL,BOOL bDeleteOnDestroy=FALSE);
~CLinkStatic() {}
CShellExcuteString m_link;
COLORREF m_color;
static COLORREF g_colorUnvisited;
static COLORREF g_colorVisited;
static HCURSOR g_hCursorLink;
protected:
CFont m_font;//underline font for text control
BOOL m_bDeleteOnDestroy;//delete object when window destroyed?
virtual void PostNcDestroy();
//message handlers
DECLARE_MESSAGE_MAP()
afx_msg UINT OnNcHitTest(CPoint point);
afx_msg HBRUSH CtlColor(CDC*pDC,UINT nCtlColor);
afx_msg void OnLButtonDown(UINT nFlags,CPoint point);
afx_msg BOOL OnSetCursor(CWnd*pWnd,UINT nHitTest,UINT message);
};
#endif _STATLINK_H
LinkStatic.cpp代码如下:
#include "StdAfx.h"
#include "LinkStatic.H"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
COLORREF CLinkStatic::g_colorUnvisited=RGB(0,0,255);//blue
COLORREF CLinkStatic::g_colorVisited=RGB(128,0,128);//purple
HCURSOR CLinkStatic::g_hCursorLink=NULL;
IMPLEMENT_DYNAMIC(CLinkStatic,CStatic)
BEGIN_MESSAGE_MAP(CLinkStatic,CStatic)
ON_WM_NCHITTEST()
ON_WM_CTLCOLOR_REFLECT()
ON_WM_LBUTTONDOWN()
ON_WM_SETCURSOR()
END_MESSAGE_MAP()
CLinkStatic::CLinkStatic(LPCTSTR lpText,BOOL bDeleteOnDestroy)
{
m_link=lpText;//link text(NULL==>window text)
m_color=g_colorUnvisited;//not visited yet
m_bDeleteOnDestroy=bDeleteOnDestroy;//delete object with window?
}
UINT CLinkStatic::OnNcHitTest(CPoint point)
{
return HTCLIENT;
}
HBRUSH CLinkStatic::CtlColor(CDC *pDC,UINT nCtlColor)
{
ASSERT(nCtlColor==CTLCOLOR_STATIC);
DWORD dwStyle=GetStyle();
HBRUSH hbr=NULL;
if((dwStyle&0xFF)<=SS_RIGHT)
{
//this is a text control:set up font and colors
if(!(HFONT)m_font)
{
//first time init:create font
LOGFONT lf;
GetFont()->GetObject(sizeof(lf),&lf);
lf.lfUnderline=TRUE;
m_font.CreateFontIndirect(&lf);
}
//use underline font and visited/unvisited colors
pDC->SelectObject(&m_font);
pDC->SetTextColor(m_color);
pDC->SetBkMode(TRANSPARENT);
//return hollow brush to preserve parent background color
hbr=(HBRUSH)::GetStockObject(HOLLOW_BRUSH);
}
return hbr;
}
void CLinkStatic::OnLButtonDown(UINT nFlags,CPoint point)
{
if(m_link.IsEmpty())
{
//no link:try to load from resource string or window text
m_link.LoadString(GetDlgCtrlID())||(GetWindowText(m_link),1);
if(m_link.IsEmpty())
return;
}
HINSTANCE h=m_link.Navigate();
if((UINT)h>32) //success!
{
m_color=g_colorVisited;//change color
Invalidate();//repaint
}
else
{
MessageBeep(0);//unable to execute file!
TRACE(_T("***WARNING:CLinkStatic:unable to navigate link%s\n"),(LPCTSTR)m_link);
}
}
BOOL CLinkStatic::OnSetCursor(CWnd *pWnd,UINT nHitTest,UINT message)
{
if(g_hCursorLink==NULL)
{
static bTriedOnce=FALSE;
if(!bTriedOnce)
{
CString windir;
GetWindowsDirectory(windir.GetBuffer(MAX_PATH),MAX_PATH);
windir.ReleaseBuffer();
windir+=_T("\\winhlp32.exe");
HMODULE hModule=LoadLibrary(windir);
if(hModule)
{
g_hCursorLink=CopyCursor(::LoadCursor(hModule,MAKEINTRESOURCE(106)));
}
FreeLibrary(hModule);
bTriedOnce=TRUE;
}
}
if(g_hCursorLink)
{
::SetCursor(g_hCursorLink);
return TRUE;
}
return FALSE;
}
void CLinkStatic::PostNcDestroy()
{
if(m_bDeleteOnDestroy)
delete this;
}
9、添加CToolTipWnd类,ToolTipWnd.h代码如下:
class CToolTipWnd:public CWnd
{
public:
CSize m_szMargins;//extra space around text:change if you like
CFont m_font;
CToolTipWnd();
virtual ~CToolTipWnd();
BOOL Create(CPoint pt,CWnd *pParentWnd,UINT nStyle=0,UINT nID=0);
void ShowDelayed(UINT msec);
void Cancel();
protected:
UINT m_nStyle;//style(see below)
virtual void PostNcDestroy();
virtual BOOL PreCreateWindow(CREATESTRUCT &cs);
void DrawText(CDC &dc,LPCTSTR lpText,CRect &rc,UINT flags);
afx_msg UINT OnNcHitTest(CPoint pt);
afx_msg void OnPaint();
afx_msg void OnTimer(UINT nIDEvent);
afx_msg LRESULT OnSetText(WPARAM wp,LPARAM lp);
DECLARE_DYNAMIC(CToolTipWnd);
DECLARE_MESSAGE_MAP();
};
#define PTS_JUSTIFYLEFT 0x0000
#define PTS_JUSTIFYRIGHT 0x0001
#define PTS_TRANSPARENT 0x0002
ToolTipWnd.cpp代码如下:
#include "stdafx.h"
#include "ToolTipWnd.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#endif
IMPLEMENT_DYNAMIC(CToolTipWnd,CWnd)
BEGIN_MESSAGE_MAP(CToolTipWnd,CWnd)
ON_WM_NCHITTEST()
ON_WM_PAINT()
ON_MESSAGE(WM_SETTEXT,OnSetText)
ON_WM_TIMER()
END_MESSAGE_MAP()
CToolTipWnd::CToolTipWnd()
{
m_szMargins=CSize(4,4);
m_font.CreateFont(24,0,0,0,FW_NORMAL,0,0,0,1,0,0,0,0,"微软雅黑");
}
CToolTipWnd::~CToolTipWnd()
{
}
int CToolTipWnd::Create(CPoint pt,CWnd *pParentWnd,UINT nStyle,UINT nID)
{
m_nStyle=nStyle;
return CreateEx(0,
NULL,
NULL,
WS_POPUP|WS_VISIBLE,
CRect(pt,CSize(0,0)),
pParentWnd,
nID);
}
UINT CToolTipWnd::OnNcHitTest(CPoint pt)
{
if(m_nStyle&PTS_TRANSPARENT)//transparent?
return HTTRANSPARENT;//..make it so
return CWnd::OnNcHitTest(pt);//otherwise return default
}
LRESULT CToolTipWnd::OnSetText(WPARAM wp,LPARAM lp)
{
CRect rc;
GetWindowRect(&rc);
int x=(m_nStyle&PTS_JUSTIFYRIGHT)?rc.right:rc.left;
int y=rc.top;
CClientDC dc=this;
DrawText(dc,CString((LPCTSTR)lp),rc,DT_CALCRECT);
rc.InflateRect(m_szMargins);
//if(m_nStyle&PTS_JUSTIFYRIGHT)
//{
// x-=rc.Width();
//}
//SetWindowPos(NULL,x,y,rc.Width(),rc.Height(),SWP_NOZORDER|SWP_NOACTIVATE);
return Default();
}
void CToolTipWnd::DrawText(CDC &dc,LPCTSTR lpText,CRect &rc,UINT flags)
{
CBitmap bmp;
bmp.LoadBitmap(IDB_BITMAP1);
//CBrush b(GetSysColor(COLOR_INFOBK));//use tooltip bg color
CBrush br;
br.CreatePatternBrush(&bmp);
dc.FillRect(&rc,&br);
dc.SetBkMode(TRANSPARENT);
//dc.SetTextColor(GetSysColor(COLOR_INFOTEXT));//tooltip text color
dc.SetTextColor(RGB(0xFF,0,0));
//CFont *pOldFont=dc.SelectObject(GetParent()->GetFont());
CFont *pOldFont=dc.SelectObject(&m_font);
dc.DrawText(lpText,&rc,flags);
dc.SelectObject(pOldFont);
}
void CToolTipWnd::OnPaint()
{
CRect rc;
GetClientRect(&rc);
CString s;
GetWindowText(s);
CPaintDC dc(this);
DrawText(dc,s,rc,DT_SINGLELINE|DT_VCENTER|DT_CENTER);
}
BOOL CToolTipWnd::PreCreateWindow(CREATESTRUCT&cs)
{
static CString sClassName;
if(sClassName.IsEmpty())
sClassName=AfxRegisterWndClass(0);
cs.lpszClass=sClassName;
cs.style=WS_POPUP|WS_BORDER;
cs.dwExStyle|=WS_EX_TOOLWINDOW;
return CWnd::PreCreateWindow(cs);
}
void CToolTipWnd::PostNcDestroy()
{
//don't delete this
}
void CToolTipWnd::ShowDelayed(UINT msec)
{
if(msec==0)
{
//no delay:show it now
OnTimer(1);
}
else
{
//delay:set time
SetTimer(1,msec,NULL);
}
}
void CToolTipWnd::Cancel()
{
KillTimer(1);
ShowWindow(SW_HIDE);
}
void CToolTipWnd::OnTimer(UINT nIDEvent)
{
ShowWindow(SW_SHOWNA);
Invalidate();
UpdateWindow();
KillTimer(1);
}
10、添加CNonClientMetrics,代码写在ToolTipWnd.h头部,代码如下:
class CNonClientMetrics:public NONCLIENTMETRICS
{
public:
CNonClientMetrics()
{
cbSize=sizeof(NONCLIENTMETRICS);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS,0,this,0);
}
};
11、添加一张位图,资源代号是:IDB_BITMAP1。
12、在对话框的InitDialog里添加初始化ListBox的代码:
static LPCTSTR STRINGS[] =
{
"来是空言去绝踪,",
"月斜楼上五更钟。梦为远别啼难唤,",
"书被催成墨未浓。蜡照半笼金翡翠,麝熏微度绣芙蓉。",
"刘郎已恨蓬山远,",
"更隔蓬山一万重。昨夜星辰昨夜风,",
"画楼西畔桂堂东。身无彩凤双飞翼,心有灵犀一点通。",
"隔座送钩春酒暖,"
"分曹射覆蜡灯红。嗟余听鼓应官去,走马兰台类转蓬。",
NULL
};
for (int i=0; STRINGS[i]; i++)
{
m_wndListBox.AddString(STRINGS[i]);
}
m_tipHandler.Init(&m_wndListBox);
m_wndListBox.SetFocus();
m_wndLink1.m_link = _T("http://www.vckbase.com");
m_wndLink2.m_link = _T("mailto:jiayuxiaosheng@yeah.net");
m_wndLink1.SubclassDlgItem(IDC_VCKBASE, this);
m_wndLink2.SubclassDlgItem(IDC_MAIL, this);
【效果】
好了,大功告成,运行效果截图:


浙公网安备 33010602011771号