none
对话框背景颜色(Background Color of Dialog Box) RRS feed

  • 问题

  • 我在应用中有这样一个问题:在基于对话框的MFC程序中,控件类型为CStatic的子控件的标题要频繁刷新,采用SetWindowText会导致显示闪烁,因此,在查阅有关资料后我采用缓冲的方式进行:创建一个与子控件的设备环境兼容的内存DC,在DC绘制标题,然后再贴到子控件上。实现后,发现这个方法有一个不足之处,即子控件的背景不再与对话框背景一致,并且在我尝试取对话框的背景色的时候,我发现结果并不正确。我并没有这方面太多的经验,我将示例代码贴在了下面,如果谁方便的话,非常希望能够给予指点,感谢。

    I chanced upon a problem in some situatioin: in an MFC application based on DialogBox, the title of a child control of type CStatic has to be altered frequently, to apply SetWindowText will be functioning but leads to unpleasent flickerring. So afer referring to some materials, I decided to take the caching-drawing method: to create a memory dc compatible with the child control's dc, and draw the title onto to the memory dc, then paste the content of the memory dc to the control's dc. But at finished I found a defeat of such a solution: the background of the control contracts with the dialog backgroud. When I tried to fetch the color of the dialog box backgroud, I got nothing. I've not accumulated much experience in such field, so I paste the codes below and long to some help or indication from anyone. Appreciate it.

    我创建的基于对话框的程序名是NewShowTest,下面分别是头文件与源文件,我没有对资源文件进行任何更改。

     The name of the application based on DialogBox created by me is NewShowTest, the following are header file and source file respectively. None modification to resources files.

    // NewShowTestDlg.h : header file
    //

    #pragma once


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

    // Dialog Data
     enum { IDD = IDD_NEWSHOWTEST_DIALOG };

     protected:
     virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support


    // Implementation
    protected:
     HICON m_hIcon;

     // Generated message map functions
     virtual BOOL OnInitDialog();
     afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
     afx_msg void OnPaint();
     afx_msg HCURSOR OnQueryDragIcon();
     DECLARE_MESSAGE_MAP()

    private:
     // 我添加的成员变量
     CDC m_memDC;
     RECT m_rect;
     CBrush m_brush;

     CStatic* m_pStatic;
    public:
     afx_msg void OnTimer(UINT_PTR nIDEvent);
    };

     

    // NewShowTestDlg.cpp : implementation file
    //

    #include "stdafx.h"
    #include "NewShowTest.h"
    #include "NewShowTestDlg.h"

    #ifdef _DEBUG
    #define new DEBUG_NEW
    #endif


    // CAboutDlg dialog used for App About

    class CAboutDlg : public CDialog
    {
    public:
     CAboutDlg();

    // Dialog Data
     enum { IDD = IDD_ABOUTBOX };

     protected:
     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

    // Implementation
    protected:
     DECLARE_MESSAGE_MAP()
    };

    CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
    {
    }

    void CAboutDlg::DoDataExchange(CDataExchange* pDX)
    {
     CDialog::DoDataExchange(pDX);
    }

    BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
    END_MESSAGE_MAP()


    // CNewShowTestDlg dialog

     


    CNewShowTestDlg::CNewShowTestDlg(CWnd* pParent /*=NULL*/)
     : CDialog(CNewShowTestDlg::IDD, pParent)
    {
     m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    }

    void CNewShowTestDlg::DoDataExchange(CDataExchange* pDX)
    {
     CDialog::DoDataExchange(pDX);
    }

    BEGIN_MESSAGE_MAP(CNewShowTestDlg, CDialog)
     ON_WM_SYSCOMMAND()
     ON_WM_PAINT()
     ON_WM_QUERYDRAGICON()
     //}}AFX_MSG_MAP
     ON_WM_TIMER()
    END_MESSAGE_MAP()


    // CNewShowTestDlg message handlers

    BOOL CNewShowTestDlg::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
     SetIcon(m_hIcon, FALSE);  // Set small icon

     // TODO: Add extra initialization here

     SetTimer(1, 1000, NULL);
     // 利用单缓冲防止屏幕闪烁
     m_pStatic = reinterpret_cast<CStatic*>(GetDlgItem(IDC_STATIC));
     CDC* pDC = m_pStatic->GetWindowDC();

     m_pStatic->GetWindowRect(&m_rect);

     m_rect.right = m_rect.right - m_rect.left;
     m_rect.left = 0;
     
     m_rect.bottom = m_rect.bottom - m_rect.top;
     m_rect.top = 0;

     CBitmap bmp;

     // 根据子控件的大小创建兼容位图,用来撑起内存DC
     bmp.CreateCompatibleBitmap(pDC, m_rect.right, m_rect.bottom);

     // 创建内存DC
     m_memDC.CreateCompatibleDC(pDC);
     m_memDC.SelectObject(bmp);

     CFont* pFont = m_pStatic->GetFont();

     // 想得到背景色,在内存DC上绘图时,希望背景色与对话框的一致
     COLORREF color = GetDC()->GetBkColor(); //::GetSysColor(COLOR_MENU);

     m_memDC.SelectObject(pFont);
     m_memDC.SetBkColor(color);

     m_brush.CreateSolidBrush(color);

     m_pStatic->ReleaseDC(pDC);

     return TRUE;  // return TRUE  unless you set the focus to a control
    }

    void CNewShowTestDlg::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 CNewShowTestDlg::OnPaint()
    {
     if (IsIconic())
     {
      CPaintDC dc(this); // device context for painting

      SendMessage(WM_ICONERASEBKGND, reinterpret_cast<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;

      // Draw the icon
      dc.DrawIcon(x, y, m_hIcon);
     }
     else
     {
      CDialog::OnPaint();
     }
    }

    // The system calls this function to obtain the cursor to display while the user drags
    //  the minimized window.
    HCURSOR CNewShowTestDlg::OnQueryDragIcon()
    {
     return static_cast<HCURSOR>(m_hIcon);
    }

     

    static int nCount = 0;
    void CNewShowTestDlg::OnTimer(UINT_PTR nIDEvent)
    {
     // TODO: Add your message handler code here and/or call default
     CString strMessage;
     strMessage.Format(_T("测试显示字符串示例%d, 测试显示字符串示例%d."), nCount++, nCount);
     CDC* pDC = m_pStatic->GetWindowDC();
     
     m_memDC.FillRect(&m_rect, &m_brush);
     m_memDC.TextOut(0, 0, strMessage);
     pDC->BitBlt(0, 0, m_rect.right, m_rect.right, &m_memDC, 0, 0, SRCCOPY);

     m_pStatic->ReleaseDC(pDC);
     CDialog::OnTimer(nIDEvent);
    }

    2010年8月11日 3:44

答案

全部回复