(1)实现一个无边框的窗口,不需要窗口能够拖动,不需要放大缩小按钮,但是需要右上角的关闭按钮;
(2)静态文本框背景透明,显示的文字能够频繁刷新并且不能够有重影;
实现去除边框是在窗口过程函数的WM_SIZE消息处理时实现的。
case WM_SIZE:
{
LONG_PTR Style = ::GetWindowLongPtr(hWnd, GWL_STYLE);
Style = Style & ~WS_CAPTION &~WS_SYSMENU &~WS_SIZEBOX;
::SetWindowLongPtr(hWnd, GWL_STYLE, Style);
return 0;
}
如果在创建窗口时直接设置去除这些属性,会导致窗口顶部的标题栏无法彻底去除,虽然不显示左上角的图标和右上角的放大缩小按钮,但是标题栏仍然存在。
“关闭”按钮没有采用windows默认提供的,自己创建了一个按钮,加载了带"x"的icon实现。之前尝试屏蔽“放大”和“缩小”按钮来实现,但是只能使之失效无法消失不见,所以选择自己创建按钮。
这一功能的实现有两个重要步骤,一是加载icon图片;二是对关闭消息的响应。
(1)加载icon图片
HANDLE close_icon = LoadImage(NULL, L"close_button.ico", IMAGE_ICON, 32, 32, LR_LOADFROMFILE);
if (close_icon == NULL) {
int error_code = GetLastError();
return;
}
SendMessage(close_button_, BM_SETIMAGE, IMAGE_ICON, (LPARAM)close_icon);
在调试过程中,出现1813的错误码,问题的原因是将LoadImage的最后一个参数设置为LR_DEFAULTCOLOR,改为LR_LOADFROMFILE即可正常加载。
(2)响应关闭消息
在父窗口的窗口过程函数中,增加对如下命令的响应。
case WM_COMMAND:
if ((HWND)lParam == close_hwnd_)
{
::SendMessage(parent_hwnd_, WM_CLOSE, 0, 0);
}
return 0;
实现这个功能需要在两处添加代码:一是静态文本框创建完成的时候,需要增加一个透明的属性;二是在窗口的过程函数中增加对WM_CTLCOLORSTATIC消息的处理。
(1)增加透明属性
LONG nRet = ::GetWindowLong(progress_handle_, GWL_EXSTYLE);
nRet = nRet | WS_EX_TRANSPARENT;
::SetWindowLong(progress_handle_, GWL_EXSTYLE, nRet);
(2)处理WM_CTLCOLORSTATIC消息
在父窗口的窗口过程函数中,增加对如下命令的响应。
case WM_CTLCOLORSTATIC:
hDC = (HDC)wParam;
SetTextColor(hDC, RGB(0, 0, 0));
SetBkMode(hDC, TRANSPARENT);
//break;
return (LRESULT)GetStockObject(NULL_BRUSH);
在这里如果返回一个非空画刷,也就是这里break,而不是后面的return空画刷,无法实现静态文本控件透明,至少我的实践效果是这样。
在静态文本框背景透明的情况下,如果刷新静态文本框的文本,会出现重影现象,以下代码在我的机器上可以解决重影问题。
void ProgressControl::OnStartButtonPressed() const
{
::SetWindowPos(progress_handle_, HWND_TOPMOST, 0, 0,
0, 0, SWP_NOMOVE | SWP_NOSIZE);
::SendMessage(parent_handle_, WM_CTLCOLORSTATIC, 0, 0);
SetWindowText(progress_handle_, L"1%");
::ShowWindow(progress_handle_, 1);
for (int i = 1; i < 97;)
{
i += rand() % 4;
wchar_t buffer[10];
_itow_s(i, buffer, 10, 10);
std::wstring progress(buffer);
progress += L"%";
SetWindowText(progress_handle_, progress.c_str());
::ShowWindow(progress_handle_, 1);
::InvalidateRect(parent_handle_, NULL, TRUE);
::UpdateWindow(parent_handle_);
Sleep(100);
}
}
注意:InvalidateRect和UpdateWindow中给出的句柄一定是父窗口的,而不是静态文本控件的,否则会出现文本刷新显示时的重影问题。