windows api實現視窗、按鈕、靜態文字框透明顯示
阿新 • • 發佈:2019-02-19
1.需求
(1)實現一個無邊框的視窗,不需要視窗能夠拖動,不需要放大縮小按鈕,但是需要右上角的關閉按鈕;
(2)靜態文字框背景透明,顯示的文字能夠頻繁重新整理並且不能夠有重影;
2.實現方式
2.1無邊框視窗
實現去除邊框是在視窗過程函式的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; }
2.2關閉按鈕
“關閉”按鈕沒有采用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;
2.3靜態文字框背景透明
實現這個功能需要在兩處新增程式碼:一是靜態文字框建立完成的時候,需要增加一個透明的屬性;二是在視窗的過程函式中增加對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空畫刷,無法實現靜態文字控制元件透明,至少我的實踐效果是這樣。2.4文字重新整理重影
在靜態文字框背景透明的情況下,如果重新整理靜態文字框的文字,會出現重影現象,以下程式碼在我的機器上可以解決重影問題。
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中給出的控制代碼一定是父視窗的,而不是靜態文字控制元件的,否則會出現文字重新整理顯示時的重影問題。