无法在应用程序中更改对话框的颜色

Skewjo

我试图为Windows C ++应用程序创建“暗模式”,部分是出于娱乐目的,部分是为了尝试并完全理解MFC中传递的消息,但是我遇到了一些非常奇怪的问题,我无法在任何地方找到解释。

我在今天的大部分时间里都在尝试解决这个问题,并将尽我最大的努力引用我查看并尝试实现的许多资源。

我相信我已经成功地为这两者编写了消息处理程序,WM_CTLCOLORWM_ERASEBKGND基于此答案中的示例代码,但是它们似乎对我的对话框没有任何影响。我已经在此处缩减了代码,但希望提供的信息足以暴露我的问题。如果那还不够,我可以(不情愿地)共享整个仓库。

软件Dlg.h

#ifndef _SOFTWAREDLG_H_INCLUDED_
#define _SOFTWAREDLG_H_INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

class SoftwareDlg : public CDialog
{
// Construction
public:
    SoftwareDlg(CWnd* pParent = NULL);  // standard constructor

// Dialog Data
    //{{AFX_DATA(SoftwareDlg)
    enum { IDD = IDD_SOFTWARE_DIALOG };
    //}}AFX_DATA

    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(SoftwareDlg)
    public:
    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
    //}}AFX_VIRTUAL

// Implementation
protected:
    BOOL                        PreTranslateMessage(MSG* pMsg);
    CFont                       m_font;
    CRichEditCtrl               m_richEditCtrl;

    // Generated message map functions
    //{{AFX_MSG(SoftwareDlg)
    virtual BOOL OnInitDialog();
    afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
    afx_msg void OnPaint();
    afx_msg HCURSOR OnQueryDragIcon();
    afx_msg void OnTimer(UINT nIDEvent);
    afx_msg void OnDestroy();
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
public:
    afx_msg BOOL OnEraseBkgnd(CDC* pDC);
    afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
    afx_msg HBRUSH CtlColor(CDC* pDC, UINT nCtlColor);
};


/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
/////////////////////////////////////////////////////////////////////////////
#endif
/////////////////////////////////////////////////////////////////////////////

SoftwareDlg.cpp

#include "stdafx.h"
#include <Windows.h>
#include "AboutDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

//Windows Dialog inherited function overrides
/////////////////////////////////////////////////////////////////////////////
// SoftwareDlg dialog
/////////////////////////////////////////////////////////////////////////////
SoftwareDlg::SoftwareDlg(CWnd* pParent /*=NULL*/)
    : CDialog(SoftwareDlg::IDD, pParent)
{
    //{{AFX_DATA_INIT(SoftwareDlg)
    //}}AFX_DATA_INIT
    // Note that LoadIcon does not require a subsequent DestroyIcon in Win32

    m_hIcon                     = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void SoftwareDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(SoftwareDlg)
    //}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(SoftwareDlg, CDialog)
    //{{AFX_MSG_MAP(SoftwareDlg)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_WM_TIMER()
    ON_WM_DESTROY()
    //}}AFX_MSG_MAP
    ON_WM_ERASEBKGND()
    ON_WM_CTLCOLOR()
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// SoftwareDlg message handlers
/////////////////////////////////////////////////////////////////////////////
BOOL SoftwareDlg::OnInitDialog()
{
    CDialog::OnInitDialog();


    // Add "About..." menu item to system menu.

    // IDM_ABOUTBOX must be in the system command range.
    ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    ASSERT(IDM_ABOUTBOX < 0xF000);

    CMenu* pSysMenu = GetSystemMenu(FALSE);
    if (pSysMenu != NULL)
    {
        CString strAboutMenu;
        strAboutMenu.LoadString(IDS_ABOUTBOX);
        if (!strAboutMenu.IsEmpty())
        {
            pSysMenu->AppendMenu(MF_SEPARATOR);
            pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
        }
    }

    // Set the icon for this dialog.  The framework does this automatically
    //  when the application's main window is not a dialog
    SetIcon(m_hIcon, TRUE);         // Set big icon


    CWnd* pPlaceholder = GetDlgItem(IDC_PLACEHOLDER);

    if (pPlaceholder)
    {
        CRect rect;
        pPlaceholder->GetClientRect(&rect);

        if (!m_richEditCtrl.Create(WS_VISIBLE | ES_READONLY | ES_MULTILINE | ES_AUTOHSCROLL | WS_HSCROLL | ES_AUTOVSCROLL | WS_VSCROLL, rect, this, 0))
            return FALSE;

        m_font.CreateFont(-11, 0, 0, 0, FW_REGULAR, 0, 0, 0, BALTIC_CHARSET, 0, 0, 0, 0, "Courier New");
        m_richEditCtrl.SetFont(&m_font);
    }

    m_nTimerID = SetTimer(0x1234, 1000, NULL);  //Used by OnTimer function to refresh dialog box & OSD

    return TRUE;  // return TRUE  unless you set the focus to a control
}
void SoftwareDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
    if ((nID & 0xFFF0) == IDM_ABOUTBOX)
    {
        CAboutDlg dlgAbout;
        dlgAbout.DoModal();
    }
    else
    {
        CDialog::OnSysCommand(nID, lParam);
    }
}
/////////////////////////////////////////////////////////////////////////////
// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.
/////////////////////////////////////////////////////////////////////////////
void SoftwareDlg::OnPaint()
{
    if (IsIconic())
    {
        CPaintDC dc(this); // device context for painting

        SendMessage(WM_ICONERASEBKGND, (WPARAM)dc.GetSafeHdc(), 0);

        // Center icon in client rectangle
        int cxIcon = GetSystemMetrics(SM_CXICON);
        int cyIcon = GetSystemMetrics(SM_CYICON);
        CRect rect;
        GetClientRect(&rect);
        int x = (rect.Width() - cxIcon + 1) / 2;
        int y = (rect.Height() - cyIcon + 1) / 2;

        dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
        CDialog::OnPaint();
    }
}
HCURSOR SoftwareDlg::OnQueryDragIcon()
{
    return (HCURSOR)m_hIcon;
}
void SoftwareDlg::OnTimer(UINT nIDEvent)
{
    CDialog::OnTimer(nIDEvent);
}
void SoftwareDlg::OnDestroy()
{
    if (m_nTimerID)
        KillTimer(m_nTimerID);

    m_nTimerID = NULL;

    MSG msg;
    while (PeekMessage(&msg, m_hWnd, WM_TIMER, WM_TIMER, PM_REMOVE));

    CDialog::OnDestroy();
}
BOOL SoftwareDlg::PreTranslateMessage(MSG* pMsg)
{
    if (pMsg->message == WM_KEYDOWN)
    {
        switch (pMsg->wParam)
        {
        case ' ':
            Sleep(1000);
        }
    }

    return CDialog::PreTranslateMessage(pMsg);
}
BOOL SoftwareDlg::OnEraseBkgnd(CDC* pDC)
{
    CRect rect;
    GetClientRect(&rect);
    CBrush myBrush(RGB(255, 0, 0));    // dialog background color
    CBrush* pOld = pDC->SelectObject(&myBrush);
    BOOL bRes = pDC->PatBlt(0, 0, rect.Width(), rect.Height(), PATCOPY);
    pDC->SelectObject(pOld);    // restore old brush
    return bRes;                       // CDialog::OnEraseBkgnd(pDC);
}
HBRUSH SoftwareDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
    // Are we painting the IDC_MYSTATIC control? We can use
    m_brush.CreateSolidBrush(RGB(136, 217, 242));
    //if (pWnd->GetDlgCtrlID() == IDD_SOFTWARE_DIALOG)

    // Set the text color to red
    pDC->SetTextColor(RGB(255, 0, 0));

    // Set the background mode for text to transparent  so background will show thru.
    pDC->SetBkMode(TRANSPARENT);

    // Return handle to our CBrush object
    hbr = m_brush;

    return hbr;

}
HBRUSH SoftwareDlg::CtlColor(CDC* pDC, UINT nCtlColor)
{
    HBRUSH myBrush = CreateSolidBrush(RGB(136, 217, 242));

    return myBrush;
}

资源.h

//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by Software.rc
//
#define IDM_ABOUTBOX                    0x0010
#define IDD_ABOUTBOX                    100
#define IDS_ABOUTBOX                    101
#define IDD_SOFTWARE_DIALOG      102

// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        141
#define _APS_NEXT_COMMAND_VALUE         32792
#define _APS_NEXT_CONTROL_VALUE         1026
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif

大约6个月前,由同一用户发布的另一个问题用相似的代码回答,但是使用的框架类型包含“ WinMain”功能(对不起,我还不能区分2种以上的类型)。我的程序不包含WinMain函数,因此我无法直接使用示例代码...但是此答案的另一个区别是,告诉David捕获WM_CTLCOLORDLG消息类型而不是WM_CTLCOLOR消息类型。我试图捕获这种新的消息类型,但是IntelliSense告诉我它是未定义的,并且对话框的资源视图中完全没有特定的消息属性:WM_CTLCOLORDLG丢失

I've also attempted defining "WM_CTLCOLORDLG" myself as described on the Microsoft Docs page, but continued to get error messages when I tried handling it through "ON_MESSAGE".

My code was not an original project, but was taken from an open source sample provided with RTSS. As such, it doesn't use the standard(?) "pch.h", but "stdafx.h"(which is older I guess?). I'm not certain if that's relevant, but I feel like it may be.

I think this issue may also be causing me a lot of other growing pains as well, so any help is GREATLY appreciated.

dxiv

Main problem with OP's code is that the brush is re-created every time in OnCtlColor and will keep leaking GDI handles (the debug build of MFC raises an ASSERT about this). Complete step-by-step fix below.

  • Declare the color and brush as members of the dialog.

    class SoftwareDlg : public CDialog
    {
    //...
    protected:
        COLORREF m_color;
        CBrush m_brush;
    //...
    
  • Initialize the color and brush in OnInitDialog.

    BOOL SoftwareDlg::OnInitDialog()
    {
        m_color = RGB(136, 217, 242);
        m_brush.CreateSolidBrush(m_color);
    
        CDialog::OnInitDialog();
    //...
    
  • Return the brush from OnCtlColor.

    HBRUSH SoftwareDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
    {
    //...
        return m_brush;
    }
    
  • Use the color in OnEraseBkgnd to repaint any visible area.

    afx_msg BOOL SoftwareDlg::OnEraseBkgnd(CDC* pDC)
    {
        CRect rc;
        pDC->GetClipBox(&rc);
        pDC->FillSolidRect(rc, m_color);
        return TRUE;
    }
    
  • Set the background color to the rich edit control in OnInitDialog explicitly, since rich edit controls do not use the WM_CTLCOLOR*** messages.

    BOOL SoftwareDlg::OnInitDialog()
    {
    //...
        if (pPlaceholder)
        {
        //...
    
            if (!m_richEditCtrl.Create(WS_VISIBLE | ES_READONLY | ES_MULTILINE | ES_AUTOHSCROLL | WS_HSCROLL | ES_AUTOVSCROLL | WS_VSCROLL, rect, this, 0))
                return FALSE;
    
            m_richEditCtrl.SetBackgroundColor(FALSE, m_color);
    //...
    

注意:如果使用CDialogEx::SetBackgroundColor其他答案中提出方法,则实现将覆盖OnCtlColorOnEraseBkgnd部分CDialogEx最后一步仍然是必要的,因为该WM_CTLCOLOR机制仅涵盖基本控件(静态,编辑,按钮等)和对话框本身。除那些控件(丰富的编辑控件,列表视图控件等)外,其他控件都需要分别处理。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何在jQuery UI中更改对话框标题的颜色?

来自分类Dev

动态更改对话框中的文本

来自分类Dev

Android更改对话框行的颜色

来自分类Dev

Facebook显示登录对话框而不是应用程序请求对话框

来自分类Dev

SP2013 SharePoint托管的应用程序模式对话框错误:无法读取“ hiddenButtonValueBeforeDialog”

来自分类Dev

如何更改对话框片段中的片段

来自分类Dev

Android-从更改默认SMS应用程序对话框获取结果

来自分类Dev

在应用程序本机共享对话框和iOS中的Google+登录中

来自分类Dev

JavaFX如何更改对话框/窗口标题的颜色?

来自分类Dev

在Windows Phone通用应用程序中更改内容对话框按钮的样式

来自分类Dev

如何更改对话框的默认黑色暗淡背景“颜色”(而不是暗淡量)?

来自分类Dev

使用Rails应用程序无法获得弹出模式对话框

来自分类Dev

Android棉花糖中的屏幕方向更改时的权限对话框使应用程序崩溃

来自分类Dev

更改对话框Android的颜色

来自分类Dev

更改对话框文字的Android

来自分类Dev

在首次启动应用程序时显示对话框

来自分类Dev

更改对话框的灰色

来自分类Dev

Windows 8应用程序的“打开文件”对话框

来自分类Dev

SP2013 SharePoint托管的应用程序模式对话框错误:无法读取“ hiddenButtonValueBeforeDialog”

来自分类Dev

在Windows Phone通用应用程序中更改内容对话框按钮的样式

来自分类Dev

Chocolatey无法安装应用程序,“您如何打开此文件?” 而是打开对话框

来自分类Dev

FBSDKLoginManager无法在本机ios应用程序中打开登录对话框

来自分类Dev

对话框抛出“无法添加窗口-令牌null不适用于应用程序”

来自分类Dev

无法在Visual Studio 2015(ASP.NET 5 Web应用程序)中打开发布对话框

来自分类Dev

2sxc:更改应用程序的入门对话框

来自分类Dev

在 Android 中更改对话框样式

来自分类Dev

在 Swift 中的 macOS 应用程序中阻止“您想保存更改吗”对话框

来自分类Dev

在“选择应用程序”对话框列表中显示应用程序

来自分类Dev

基于 MFC 对话框的应用程序无法两次调用对话框

Related 相关文章

  1. 1

    如何在jQuery UI中更改对话框标题的颜色?

  2. 2

    动态更改对话框中的文本

  3. 3

    Android更改对话框行的颜色

  4. 4

    Facebook显示登录对话框而不是应用程序请求对话框

  5. 5

    SP2013 SharePoint托管的应用程序模式对话框错误:无法读取“ hiddenButtonValueBeforeDialog”

  6. 6

    如何更改对话框片段中的片段

  7. 7

    Android-从更改默认SMS应用程序对话框获取结果

  8. 8

    在应用程序本机共享对话框和iOS中的Google+登录中

  9. 9

    JavaFX如何更改对话框/窗口标题的颜色?

  10. 10

    在Windows Phone通用应用程序中更改内容对话框按钮的样式

  11. 11

    如何更改对话框的默认黑色暗淡背景“颜色”(而不是暗淡量)?

  12. 12

    使用Rails应用程序无法获得弹出模式对话框

  13. 13

    Android棉花糖中的屏幕方向更改时的权限对话框使应用程序崩溃

  14. 14

    更改对话框Android的颜色

  15. 15

    更改对话框文字的Android

  16. 16

    在首次启动应用程序时显示对话框

  17. 17

    更改对话框的灰色

  18. 18

    Windows 8应用程序的“打开文件”对话框

  19. 19

    SP2013 SharePoint托管的应用程序模式对话框错误:无法读取“ hiddenButtonValueBeforeDialog”

  20. 20

    在Windows Phone通用应用程序中更改内容对话框按钮的样式

  21. 21

    Chocolatey无法安装应用程序,“您如何打开此文件?” 而是打开对话框

  22. 22

    FBSDKLoginManager无法在本机ios应用程序中打开登录对话框

  23. 23

    对话框抛出“无法添加窗口-令牌null不适用于应用程序”

  24. 24

    无法在Visual Studio 2015(ASP.NET 5 Web应用程序)中打开发布对话框

  25. 25

    2sxc:更改应用程序的入门对话框

  26. 26

    在 Android 中更改对话框样式

  27. 27

    在 Swift 中的 macOS 应用程序中阻止“您想保存更改吗”对话框

  28. 28

    在“选择应用程序”对话框列表中显示应用程序

  29. 29

    基于 MFC 对话框的应用程序无法两次调用对话框

热门标签

归档