场景
1.Win32
的SysLink
不会自动根据设置的文本设置超链接的大小,这点很低级. 一般我们用CLinkCtrl
时还需要自己设置超链接的坐标和大小,很不方便。但是我们如何知道一个SysLink
的最小宽度到底是多少呢?要不停的运行修改到合适吗?
说明
1.在Winxp
里需要自己根据显示的字符串计算字符串的长度,之后根据这个字符串的长度来设置SysLink
的长度,当然这个长度是排除了HTML
的标签<A HREF=""></A>
之后的字符串长度.
2.在Vista
以上额版本,Commctrl
库提供了一个LM_GETIDEALSIZE
消息,用来获取最下的SysLink
的大小.CLinkCtrl
也提供了调用的方法:
// Vista only
int GetIdealSize(SIZE& size, int cxMaxWidth = 0) const
{
ATLASSERT(::IsWindow(this->m_hWnd));
return (int)::SendMessage(this->m_hWnd, LM_GETIDEALSIZE,cxMaxWidth, (LPARAM)&size);
}
代码
兼容Winxp
计算SysLink
的最小大小,我实现了一个用正则来截取实际显示的字符串函数.
static std::wstring PickLinkShowContent(const wchar_t* buf1)
{
std::wstring buf(buf1);
std::wregex pattern(L"(<A HREF=\"[^\"]*\">)([^<]*)(</A>)",
std::regex_constants::ECMAScript|std::regex_constants::icase);
auto words_begin =
std::wsregex_iterator(buf.begin(), buf.end(), pattern);
auto words_end = std::wsregex_iterator();
std::wstring result;
int start = 0;
int end = 0;
for (std::wsregex_iterator i = words_begin; i != words_end; ++i)
{
std::wsmatch match = *i;
size_t pos = match.position();
size_t length = match.length();
std::wstring prev = buf.substr(start,pos-start);
result.append(prev);
result.append(match[2]);
end = pos+length;
start = pos+length;
}
if(end+1 != buf.length()){
result.append(buf.substr(end));
}
return result;
}
之后通过使用CClientDC
来计算字符串长度.
auto str_content = PickLinkShowContent(text_link_connectfail.c_str());
CClientDC dc(m_hWnd);
dc.SelectFont(font_16_normal_);
// 得到的字符串宽度并不是精确的,应该是跟系统绘制超链接的样式有关,所以需要补充4个像素让内容足够完整显示.
dc.GetTextExtent(str_content.c_str(),str_content.size(),&size);
size.cx+=4;
rc = link_support_2_.SetWindowPos(NULL,100, 200, size.cx, size.cy,
(SWP_NOZORDER | SWP_NOREPOSITION | SWP_NOACTIVATE));
图示1:
项目下载地址:
https://download.csdn.net/download/infoworld/12062910
参考
转载:https://blog.csdn.net/infoworld/article/details/103753246
查看评论