小言_互联网的博客

[WTL/ATL]_[初级]_[计算CLinkCtrl的合适大小]

529人阅读  评论(0)

场景

1.Win32SysLink不会自动根据设置的文本设置超链接的大小,这点很低级. 一般我们用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

参考

lm-getidealsize

clinkctrl-class


转载:https://blog.csdn.net/infoworld/article/details/103753246
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场