VC用键盘操作静态链接打开应用程序中的URLs
2007-11-01 20:24:20 来源:WEB开发网现在,用户可以用Tab来定位静态控件并看到焦点矩形。最后要做的事情是处理键盘输入。哪个键负责导航链接?IE 浏览器用回车键,但我不喜欢那样,理由有两个。首先,由键盘按下某个按钮的公认的用户界面模式是按空格键(Space 键)。超链接类似一个按钮,所以我觉得空格键更好。这是对话框的方式,在 Web 窗体中,IE 是也是这么做的。我不懂微软的老大们为什么要选择回车键来做 IE 中的链接导航。回车通常意味着“我搞掂了”,与对话框中的“确认”键相同。既然 CStaticLink 是为对话框设计的,那么它就不应该与回车键的功能相冲突。其次,在对话框中捕获回车键需要做更多的工作(参见 2000 年 7 月的专栏文章)。
所以当用户用 Tab 键移到链接时,我用空格键来导航到链接。为了实现导航,你必须处理两个消息。WM_CHAR 肯定是其中之一:
void CStaticLink::OnChar(UINT nChar,...)
{
if (nChar==VK_SPACE) {
Navigate();
}
}
但是在你的静态链接能够得到 WM_CHAR 消息之前,你必须告诉对话框你对这个消息感兴趣。通常静态控件得不到 WM_CHAR 消息(记住:因为它们是静态的)。有一个特殊的消息可以告诉对话框你想得到什么——这个消息就是 WM_GETDLGCODE:
UINT CStaticLink::OnGetDlgCode()
{
// 告诉对话框我想要 chars
return DLGC_WANTCHARS;
}
完成上述工作便万事俱备。现在当用户用 Tab 键到达超链接上时,按下空格键便可以导航了。酷。
最后是一个警告:小心选择正确的静态链接Tab顺序。你的超链接通常应该在Tab顺序的最后,即使它们出现在对话框的最前面。你可能不想让你的对话框一启动输入焦点就落在公司( ACME )标徽链接上。并且如果你在具有其它控件的窗体/对话框中使用 CStaticLink,你可能不想Tab键从某个编辑框跳过超链接到另外一个编辑框或按钮。所以我的忠告是保持所有超链接在Tab顺序的最后,除非你有充足的理由不这样做。
我写了一个例子程序 LinkTest,它使用新的具备键盘操作能力的 CStaticLink。请下载代码参考细节
我有一个 MFC 程序,调用 ShellExecute 来打开一个 Web 页面。如:
ShellExecute "http://www.microsoft.com"
在我使用托管扩展前,运行正常,但是一使用托管扩展它就不行了。返回的错误代码是5,在 WinError.h 中是 ERROR_ACCESS_DENIED。我不懂为什么会存取失败。ShellExecute 不能与托管扩展一起用吗?
你是众多遇上这等不幸怪事的人之一。没错,只要你设置 /clr 开关来使用托管扩展,那么当你尝试用 ShellExecute 打开 Web 页面时会失败。我也曾经一度被它绊倒。托管扩展和 /clr 对 ShellExecute 做了些什么手脚呢?为什么会产生存取违例?
Windows 中常发生这种事情,错误代码提供的信息很难确定到底发生了什么。但通过搜索 MSDN 库,有一篇名为“Calling Shell Functions and Interfaces from a Multithreaded Apartment”的文章揭示问题的答案。很多年前,ShellExecute 就谦卑地开始了其一生;其功能无非是让你运行一个程序,也就是一个 EXE 文件。随着 Windows 变得越来越复杂,ShellExecute 也成长为几乎可以“执行”任何程序——例如一个磁盘文件(用关联程序打开文件),FTP 协议或者 Web 页面——只要将文件名或URL传递给它即可。它是通过外壳扩展和 IShellExecuteHook 实现的,IShellExecuteHook 是一个 COM 接口,这个接口通过告诉它如何“执行”传递到 ShellExecute(Ex) 的串来扩展外壳。例如,有一个 HTTP 协议扩展钩,它处理以“http://”开始的串。扩展处理例程启动默认的浏览器打开给定的 URL。
问题是用 /clr 和托管扩展强制你的应用程序进入多线程模式,因为垃圾收集器拟在单独的线程中异步运行。但是按照 INFO 文章的解释,许多 IShellExecuteHook 扩展之所以在多线程环境不工作,是因为它们没有所需的用于 COM 封送参数的代理/存根(proxy/stub)以及进行同步存取的代码。如果你对此感到困惑,那么很多人和你一样。但我只想说,ShellExecute 在所有多线程环境下都无法正常工作。
更多精彩
赞助商链接