如何设置一个静态控制背景对话框的背景?(how to set a static control ba

2019-10-23 10:32发布

有其中包括由开关case语句回调函数在我的主代码。 每种情况后,我定义的SetWindowText功能打印在一个对话框上(或父窗口),像这样创造了一个静态控制文本:

::SetWindowText(GetDlgItem(IDC_STATIC)->m_hWnd, "loading");

我要设置静态控件作为对话框的背景的背景。 一切顺利的话,除了所有的案件发生在彼此的文字和我收到重叠文本,财产以后这样的静态控件:

我不知道为什么在每一个步骤,不会关闭静态窗口,以避免此类问题。 我加OnEraseBkgndOnDestroyOnCtlColor消息如下:

BOOL CmainDlg::OnEraseBkgnd(CDC* pDC)
{
    // TODO: Add your message handler code here and/or call default

    CDC dcMemory;
    dcMemory.CreateCompatibleDC(pDC);
    CBitmap* pOldbitmap = dcMemory.SelectObject(&CBmp);
    CRect rcClient;
    GetClientRect(&rcClient);
    const CSize& sbitmap = bitmapSize;
    pDC->BitBlt(0, 0, sbitmap.cx, sbitmap.cy, &dcMemory, 0, 0, SRCCOPY);
    dcMemory.SelectObject(pOldbitmap);
    return TRUE;

}
    HBRUSH CmainDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);



    if (pWnd->GetDlgCtrlID() == IDC_STATIC)
        //Example of changing Text colour specific to a certain 
        //Static Text Contol in this case IDC_STATIC.
    {
        pWnd->GetExStyle() & (WS_EX_TRANSPARENT);
        pDC->SetBkMode(TRANSPARENT);
        pDC->SetTextColor(RGB(255, 255, 255));

    }
    if (pWnd->GetDlgCtrlID() == IDC_OPERATION)

    {
        pWnd->GetExStyle() & (WS_EX_TRANSPARENT);
        pDC->SetBkMode(TRANSPARENT);
        pDC->SetTextColor(RGB(255, 255, 0));

        // Return handle to our CBrush object
    }
        return reinterpret_cast<HBRUSH>(GetStockObject(NULL_BRUSH));
    }

void CmainDlg::OnDestroy()
{
    CDialog::OnDestroy();

    // TODO: Add your message handler code here
    Background.DeleteObject(); // Delete Background bitmap
    BrushHol.DeleteObject();
}
//subclass the static control, just to make sure the code is the only one handling WM_ERASEBKGND and WM_PAINT messages.
void CmainDlg::PreSubclassWindow()
{
    CWnd::PreSubclassWindow();

    const LONG_PTR exStyle = GetWindowLongPtr(m_hWnd, GWL_EXSTYLE);
    SetWindowLongPtr(m_hWnd, GWL_EXSTYLE, exStyle | WS_EX_TRANSPARENT);
}

更新:

我评论OnEraseBkgndOnDestroyOnCtlColor功能。 所以,我收到了同样的重叠文字和现在更加确信我可以说,这个问题是来自setWindowText ,因为每次完成后文仍保留在我的每个开关的情况下statments的定义的静态控制窗口。 我试着用下面的命令,但什么都没有发生:

EnableWindow( GetDlgItem(m_hWnd, IDC_STATIC), FALSE);
m_static.EnableWindow(FALSE);

要么

::SetDlgItemText(m_hWnd, IDC_STATIC, "");

我要感谢所有帮助。

Answer 1:

最简单的解决方法是:

  1. 不要设置文本背景模式为透明。
  2. 不要设置文本背景色(与SetBkColor )到对话框的颜色。

唯一的诀窍是让对话框作为COLORREF的颜色。 如果您使用的是标准的东西,你可能只需要调用GetSysColor与现有颜色的常量之一。

如果对话框背景不是纯色(如渐变填充),你就必须做一些更复杂的:

  1. 添加WS_EX_TRANSPARENT到静态控件的扩展窗口样式。
  2. 继续使用透明文本模式。 您的文字将被在对话框位的新副本画。

该WS_EX_TRANSPARENT风格应该引起静电控制下的对话的一部分,静态控件之前涂上。 这应该“擦除”以前的文本,然后静态控件将绘制新的文本。

请注意,也WS_EX_TRANSPARENT使得控制透明的命中测试 (例如,鼠标点击)。 因为它是一个静态控制,即不应该的问题。 但是,这就是为什么这不是其他类型的控件的通用解决方案。



Answer 2:

绘制不透明:

初始化m_BrushCreateSolidBrush和使用SetBkMode(OPAQUE) ,而不是TRANSPARENT

绘制透明:

按照阿德里安·麦卡锡的回答和return (HBRUSH)GetStockObject(NULL_BRUSH)静态控制,而不是返回m_Brush

确保对话框没有WS_CLIPCHILDREN标志,否则你在运行同样的重叠问题,当你重新写在静态控件中的文本。

这应该这样做。

另一种选择,该代码将与融合的背景图像其他控件(编辑控件,单选按钮和复选框)的对话框可以有WS_CLIPCHILDREN标志,但静态控制需要一个积极的ID,如果它是重绘( IDC_STATIC通常被设置为-1 )。 对话框的项目将需要WS_EX_TRANSPARENT标志为好。 我没有测试这么多。

不要忘记添加ON_WM_DESTROY到消息映射。

class TDlg : public CDialogEx
{
public:
    std::map<int, HBRUSH> BrushMap;
    CBitmap Bitmap;

    TDlg(int id, CWnd *wnd) : CDialogEx(id, wnd){};
    void MakeBrush(CDC *pdc, CDC &memdc, int id);
    BOOL OnEraseBkgnd(CDC* pDC);
    void OnDestroy();
    BOOL OnInitDialog();
    HBRUSH OnCtlColor(CDC* pDC, CWnd* wnd, UINT nCtlColor);

    DECLARE_MESSAGE_MAP()
};

BOOL TDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    Bitmap.LoadBitmap(IDB_BITMAP1);
    return 1;
}

void TDlg::OnDestroy()
{
    CDialogEx::OnDestroy();
    Bitmap.DeleteObject();
    for (std::map<int, HBRUSH>::iterator it = BrushMap.begin(); it != BrushMap.end(); ++it)
        if (it->second)
            DeleteObject(it->second);
}

void TDlg::MakeBrush(CDC *pdc, CDC &memdc, int id)
{
    CWnd *item = GetDlgItem(id);

    CRect rc;
    item->GetClientRect(&rc);
    item->MapWindowPoints(this, &rc);

    CBitmap bmp;
    bmp.CreateCompatibleBitmap(&memdc, rc.Width(), rc.Height());
    memdc.SelectObject(bmp);
    memdc.BitBlt(0, 0, rc.Width(), rc.Height(), pdc, rc.left, rc.top, SRCCOPY);
    BrushMap[id] = CreatePatternBrush(bmp);
}

BOOL TDlg::OnEraseBkgnd(CDC* pDC)
{
    BITMAP bm;
    Bitmap.GetBitmap(&bm);

    CDC memdc;
    memdc.CreateCompatibleDC(pDC);
    CBitmap* pOldbitmap = memdc.SelectObject(&Bitmap);
    pDC->BitBlt(0, 0, bm.bmWidth, bm.bmHeight, &memdc, 0, 0, SRCCOPY);

    //BrushMap should be intialized once
    if (!BrushMap.size())
        for (CWnd *p = GetWindow(GW_CHILD); p; p = p->GetNextWindow(GW_HWNDNEXT))
            if (p->GetDlgCtrlID() > 0)
                MakeBrush(pDC, memdc, p->GetDlgCtrlID());

    memdc.SelectObject(pOldbitmap);

    return TRUE;
}

HBRUSH TDlg::OnCtlColor(CDC* pDC, CWnd* wnd, UINT nCtlColor)
{
    HBRUSH br = CDialogEx::OnCtlColor(pDC, wnd, nCtlColor);

    pDC->SetTextColor(RGB(255, 0, 0));
    pDC->SetBkMode(TRANSPARENT);

    int id = wnd->GetDlgCtrlID();
    if (id > 0 && BrushMap[id])
        return BrushMap[id];

    if (nCtlColor == CTLCOLOR_STATIC)
        return (HBRUSH)GetStockObject(NULL_BRUSH);

    return br;
}


文章来源: how to set a static control background as a dialog background?