VC用键盘操作静态链接打开应用程序中的URLs
2007-11-01 20:24:20 来源:WEB开发网所以我必须添加一些可视化提示以告诉用户“你在这里”。对于超链接来说就是锚点(<A> 元素),IE 浏览器是在链接文本周围画焦点矩形。那为什么不如法炮制呢?尤其是 Windows 有一个很方便的函数叫做(说来也奇怪)DrawFocusRect,这个函数有着极好的使用 XOR 光栅操作特性,所以第二次调用它便擦除焦点矩形。当你的控件获得焦点时绘制焦点矩形;失去焦点时擦除之。关键代码如下:
void CStaticLink::OnSetFocus(CWnd* /*pOldWnd*/)
{
DrawFocusRect();
}
void CStaticLink::OnKillFocus(CWnd* /*pNewWnd*/)
{
DrawFocusRect();
}
是不是很简单?即便是用户因为切换到其它程序而失去焦点(与用Tab移到其它控件相对),它们都能照样工作。
眼光敏锐的读者也许会问:参数在哪里?前面代码段中的 DrawFocusRect 不是实际的 DrawFocusRect。它是我写的一个冒名顶替者,保护类型的 CStaticLink 成员函数,负责实际调用DrawFocusRect 前做一些准备工作。代码如下:
/////////////////////////////////////////////////////////////////////////
// 获得或丢失焦点: 绘制焦点矩形。对于位图,用窗口矩形;文本则用实际文本矩形。
/////////////////////////////////////////////////////////////////////////
void CStaticLink::DrawFocusRect()
{
CWnd* pParent = GetParent();
ASSERT(pParent);
// 计算在哪里绘制焦点矩形,用屏幕坐标
CRect rc;
DWORD dwStyle = GetStyle();
if (dwStyle & (SS_BITMAP|SS_ICON|SS_ENHMETAFILE|SS_OWNERDRAW)) {
GetWindowRect(&rc); // 图像使用全窗口矩形
} else {
// 文本使用文本矩形. 不要忘了选字体!
CClientDC dc(this);
CString s;
GetWindowText(s);
CFont* pOldFont = dc.SelectObject(GetFont());
rc.SetRectEmpty(); // 重要—DT_CALCRECT 展开, 以便起始是空
dc.DrawText(s, &rc, DT_CALCRECT);// 计算文本方块区
dc.SelectObject(pOldFont);
ClientToScreen(&rc); // 转换屏幕坐标
}
rc.InflateRect(1,1); // 周围添加一个像素
pParent->ScreenToClient(&rc); // 转成父窗口坐标
CClientDC dcParent(pParent); // 父窗口的 DC
dcParent.DrawFocusRect(&rc); // 绘制!
}
大多是常规的 GDI 处理——选择字体,转换坐标等等——我只列出关键代码。
实际的::DrawFocusRect(或者其等价的 MFC 函数 CDC::DrawFocusRect)需要一个矩形,当然还需要一个设备上下文(DC)来进行绘制。但是我应该使用哪一个设备上下文呢?通常,你只能在自己的空间绘制,而不能在别的地方——也就是说在你的控件的窗口中或客户DC中。但我们这里是要在窗口外绘制,因为处于美观,焦点矩形看起来需要比控件稍大一些。所以 CStaticLink::DrawFocusRect要在其父窗口的客户DC中绘制。绘制焦点矩形是少数几种直接在屏幕或父窗口上绘制即可的情况之一。一般来说,做一些临时性的 XOR 操作即可,如同在窗口中进行拖拽操作时绘制的图标或透明图像;此时你可能使用屏幕DC。如果要在另一个窗口的设备上下文上画,唯一的规则是:不管画(paintest)什么,都要进行还原(unpaintest)!
接着,我应该用什么矩形呢?当然是窗口矩形。再想想。窗口矩形对于与控件大小相同的位图来说是不错,但对于文本呢?控件常常比其上的文本大一些,宽一些。谁来负责正确调整其静态控件的大小?如果使用窗口矩形,可以用一个长矩形来装入小文本串,甚或另做一个控件,如 Figure 3 上面部分所示。这种效果使你看起来很不爽。这就是为什么对于文本,CStaticLink::DrawFocusRect 首先要以 DT_CALCRECT 来调用 CDC::DrawText 计算正确围绕该文本的矩形原因。将量好的围绕文本的偏平像素矩形转换为父窗口客户坐标,再调用 CDC::DrawFocusRect ——瞧!正确结果如 Figure 3 下面部分所示。
Figure 3 有 DT_CALCRECT 和 没有 DT_CALCRECT 的区别
更多精彩
赞助商链接