目前很多windows软件的版权对话框中都设有超级链接,这些链接或提供公司网址,或提供电子邮件信箱,使操作者能够非常方便地与公司和作者联系,同时也为公司作了很好的宣传。一般情况下,界面上某行文字下面有一行蓝色的横线,标志该字符串提供超链接功能,当用户将鼠标移动到文字上时,鼠标变成手状,如果用户此时单击鼠标,程序将启动浏览器打开某个网页或启动OutLook让用户给指定的邮箱发送电子邮件。如果能在自己写的软件中实现这个功能,定会使程序大增光彩。本实例通过定义一个CmapHyperLink类实现了图像的超链接功能
一、 实现方法
著名的CHyperLink类只能提供文字链接,不能用于图形控件的超链接,于是本实例在其基础上修改了一下,定义了一个CMapHyperLink类,该类现在只对图形控件(picture control)生效。用户可使用成员函数void SetURL(CString strURL)设置要访问的互联网地址,如SetURL("http://www.google.com");使用成员函数void SetTipText(CString strURL)设置超链接提示条(CToolTipCtrl)的文字内容,如果不在此设置,那就默认是您设置的URL地址,如SetTipText("欢迎访问强大的google搜索");使用成员函数void SetLinkCursor(HCURSOR hCursor)设置鼠标在超链接状态的图标,默认是手型图标。该类还提供了HCURSOR GetLinkCursor() const、void SetAutoSize(BOOL bAutoSize = TRUE)等成员函数,提供了一些相应的辅助功能,读者朋友可以参考代码部分。这里主要讲述三个主要的问题:一是如何实现提示功能;二是在控件上如何改变鼠标的形状,给用户提供另外一种暗示-当前区域提供超链接功能;三是如何根据网页或信箱地址启动超链接功能。
Visual C++提供了CCtoolTipCtrl类用来实现提示功能。工具提示控制是一个小窗口,在其中显示单行文字用以描述应用程序中的工具的用途。这里的工具所指的既可以是窗口(如工具栏上的按钮),也可以是一个固定的区域。大家都知道利用APPWIZARD生成 的应用程序中工具栏带有提示,当你将鼠标放在工具栏某一个按钮上时,将显示一个小提示框告诉你按钮的功能,这种功能方便了软件的使用者。但是在超链接区如何实现提示呢?首先声明一个CtoolTipCtrl类的变量,调用Create()成员函数创建通用工具提示,并将它附在CtoolTipCtrl对象上,然后调用CtoolTipCtrl类的AddToo()成员函数注册工具提示控制,从而为光标放在规定的窗口或区域内时显示工具提示做准备。该函数的原形为:
BOOL AddTool( CWnd* pWnd,LPCTSTR lpszText, LPCRECT lpRectTool,UINT nIDTOOL );
其中参数pWnd为指向包含工具提示控制的窗口指针,参数lpszText为所要在工具提示中显示的文字,参数lpRectTool为工具书提示所对应的窗口或规定区域,参数nIDTOOL为工具提示的标志号。
在调用CtoolTipCtrl类的Active()函数激活提示后,最后要作的工作是调用CtoolTipCtrl类的RelayEvent()函数将鼠标的WM_LBUTTONDOWN、WM_MOUSEMOVE、WM_LBUTTONUP等消息传递给工具提示控制对象,以便控件进行提示处理。
下面的代码实现了在应用程序的视图区显示对应点的坐标为例:
//在文件头定义的全局变量
CToolTipCtrl m_ToolTip;//工具提示对象
char string[50];//用来存放提示文字
CRect rect;//用来存放工具提示所对应的窗口的尺寸
#define IDC_CONST 12345//定义的工具提示标志号,注意不要和系统冲突
void CTestView::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
wsprintf(string,"%d,%d",point.x,point.y);
GetClientRect(&recty);
m_ToolTip.AddTool(this,string,&rect,IDC_CONST);
m_ToolTip.Activate(TRUE);
CView::OnMouseMove(nFlags, point);
}
LRESULT CTestView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
// TODO: Add your specialized code here and/or call the base class
switch(message)
{case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_MBUTTONDOWN:
case WM_LBUTTONUP:
case WM_MBUTTONUP:
case WM_RBUTTONUP:
case WM_MOUSEMOVE:
{MSG msg;
msg.hwnd=m_hWnd;
msg.message=message;
msg.wParam=wParam;
msg.lParam=lParam;
m_ToolTip.RelayEvent(&msg);
}
}
return CView::WindowProc(message, wParam, lParam);
}
如果用户想动态的改变提示字符串,可以调用CtoolTipCtrl类的成员函数UpdateTipText()来实现,该函数的原型为:
void UpdateTipText( LPCTSTR lpszText, CWnd* pWnd, UINT nIDTool = 0 );
该函数的参数的含义与成员函数AddTool()的参数的含义大同小异,这里不再赘述。
对于超链接来说,一般会在超链接区域改变鼠标的形状,显示手状的鼠标,提示这是一个超链接区域。当然可以在程序中添加一个手状的光标资源,然后使用LoadCursor()函数等加载,这种方法对广大读者朋友一定是耳熟能详了,所以为了扩大读者朋友的编程思路,这里介绍一种从Windows的winhlp32.exe文件中加载光标资源,代码如下:
void CMapHyperLink::SetDefaultCursor()
{
if (m_hLinkCursor == NULL) // No cursor handle - load our own
{
// Get the windows directory
CString strWndDir;
GetWindowsDirectory(strWndDir.GetBuffer(MAX_PATH), MAX_PATH);
strWndDir.ReleaseBuffer();
strWndDir += _T("\winhlp32.exe");
// This retrieves cursor #106 from winhlp32.exe, which is a hand pointer
HMODULE hModule = LoadLibrary(strWndDir);
if (hModule) {
HCURSOR hHandCursor = ::LoadCursor(hModule, MAKEINTRESOURCE(106));
if (hHandCursor)
m_hLinkCursor = CopyCursor(hHandCursor);
}
FreeLibrary(hModule);
}
}
为了根据网页或信箱地址实现超链接功能,需要用到一个WINDOWS API函数ShellExecute(),其原型为:
HINSTANCE ShellExecute(
HWND hwnd, //窗口句柄
LPCTSTR lpOperation, //操作类型
LPCTST
