windows api实现窗口、按钮、静态文本框透明显示

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);
    }
}

注意:InvalidateRectUpdateWindow中给出的句柄一定是父窗口的,而不是静态文本控件的,否则会出现文本刷新显示时的重影问题。


猜你喜欢

转载自blog.csdn.net/zhuiyuanqingya/article/details/80704901