作者:刘涛
目前很多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, //操作类型 LPCTSTR lpFile, //文件指针 LPCTSTR lpParameters, //文件可带的参数 LPCTSTR lpDirectory, //缺省目录 INT nShowCmd //显示方式 ); | ShellExecute()函数用于打开或执行一个文件,在调用此函数时只须指定要打开或执行的文件名,而不必管用什么程序去打开或执行文件,WINDOWS会自动根据要打开或执行的文件去判断该如何执行文件或用什么程序去打开文件。函数中的参数lpOperation说明所要执行的操作,该值可以设置为"Open"、"Print"、"Explore",分别用来进行"打开"、"打印"、"浏览"操作。下面给出了ShellExecute()函数的一些使用方法:
(1)打开一个应用程序:
ShellExecute(this->m_hWnd,"open","calc.exe","","", SW_SHOW ); 或 ShellExecute(this->m_hWnd,"open","notepad.exe", "c:\MyLog.log","",SW_SHOW ); | (2)打开一个同系统程序相关连的文档
ShellExecute(this->m_hWnd,"open", "c:\abc.txt","","",SW_SHOW ); | (3)打开一个网页
ShellExecute(this->m_hWnd,"open", " http://www.google.com","","",/ SW_SHOW ); | (4)激活相关程序,发送EMAIL
ShellExecute(this->m_hWnd,"open","mailto:nishinapp@yahoo.com","","", W_SHOW ); | (5)用系统打印机打印文档
ShellExecute(this->m_hWnd,"print", "c:\abc.txt","","", SW_HIDE); | (6)用系统查找功能来查找指定文件
ShellExecute(m_hWnd,"find","d:\nish", NULL,NULL,SW_SHOW); | (7)启动一个程序,直到它运行结束
SHELLEXECUTEINFO ShExecInfo = {0}; ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO); ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS; ShExecInfo.hwnd = NULL; ShExecInfo.lpVerb = NULL; ShExecInfo.lpFile = "c:\MyProgram.exe"; ShExecInfo.lpParameters = ""; ShExecInfo.lpDirectory = NULL; ShExecInfo.nShow = SW_SHOW; ShExecInfo.hInstApp = NULL; ShellExecuteEx(&ShExecInfo); WaitForSingleObject(ShExecInfo.hProcess,INFINITE); 或: PROCESS_INFORMATION ProcessInfo; STARTUPINFO StartupInfo; //This is an [in] parameter ZeroMemory(&StartupInfo, sizeof(StartupInfo)); StartupInfo.cb = sizeof StartupInfo ; //Only compulsory field if(CreateProcess("c:\winnt\notepad.exe", NULL, NULL,NULL,FALSE,0,NULL, NULL,&StartupInfo,&ProcessInfo)) { WaitForSingleObject(ProcessInfo.hProcess,INFINITE); CloseHandle(ProcessInfo.hThread); CloseHandle(ProcessInfo.hProcess); } else { MessageBox("The process could not be started..."); } | (8)显示文件或文件夹的属性
SHELLEXECUTEINFO ShExecInfo ={0}; ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO); ShExecInfo.fMask = SEE_MASK_INVOKEIDLIST ; ShExecInfo.hwnd = NULL; ShExecInfo.lpVerb = "properties"; ShExecInfo.lpFile = "c:"; //can be a file as well ShExecInfo.lpParameters = ""; ShExecInfo.lpDirectory = NULL; ShExecInfo.nShow = SW_SHOW; ShExecInfo.hInstApp = NULL; ShellExecuteEx(&ShExecInfo); | Windows还提供了一个与ShellExecuteEx()函数相类似的函数WinExec(),它相对于ShellExecuteEx()来说更简单易用,只是功能没有它强大而已,具体使用方法读者朋友自行参阅MSDN。
二、编程步骤
l、启动Visual C++6.0,生成一个基于对话框的应用程序,将该程序命名为"Test";
2、在对话框上放置一个静态控件,并显示一幅图象;
3、使用Class Wizard为应用程序添加一个CMapHyperLink类,其基类为CStatic;
4、在对话框中添加一个CmapHyperLink类对象m_MapHyperLink1;
5、添加代码,编译运行程序。
[1] [2] [下一页]
|