Как я могу определить новые цвета в CPropertySheet? - PullRequest
1 голос
/ 24 октября 2019

Я пытаюсь определить новые цвета в некоторых областях CPropertySheet (библиотеки MFC). Я попытался перегрузить OnCtlColor и определить новый цвет фона. Этот метод работает хорошо, но он не окрашивает область, которую я хочу.

На следующем изображении вы можете увидеть, что я получаю с помощью моего метода.

Изображение элемента управления

На этом изображении вы видите 4 раскрашенных области:

  1. Красный: область, которую я могу раскрасить, используя OnCtlColor
  2. Темно-серый и черный: область, котораяЯ могу раскрасить, используя OnCtlColor объекта CPropertyPage
  3. Светло-серый (обозначен синей стрелкой): область, которую я хочу раскрасить
  4. Белое поле: область, которую я тоже хочу раскрасить.

Я не знаю, что делать, чтобы раскрасить все регионы с помощью этой библиотеки или любого настраиваемого объекта. Любая помощь будет оценена.

Спасибо!

Обновление 1

После ответа Адриана это выглядит как это

Тем не менее, есть еще одна область, которую мы не можем раскрасить.

Ответ

Прежде чем попробовать много комбинаций, я сделал следующие два объекта, которыепозволяет мне определить цвета, которые мне нужны. Вы можете найти весь исходный код. Результат этого кода можно проверить в этой картинке

PropertyPage

Заголовок

class CustomPropertyPage : public CPropertyPage
{   
    public:
        static const COLORREF PROPERTYPAGE_BACKGROUND = RGB(68, 74, 80);
        DECLARE_MESSAGE_MAP()

    public:
        CustomPropertyPage(UINT nIDTemplate);
        afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
};

cpp

CustomPropertyPage::CustomPropertyPage(UINT nIDTemplate) : CPropertyPage(nIDTemplate)
{
}

BEGIN_MESSAGE_MAP(CustomPropertyPage, CPropertyPage)
    ON_WM_CTLCOLOR()
END_MESSAGE_MAP()

HBRUSH CustomPropertyPage::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    if (pWnd->GetDlgCtrlID() != 0)
        return CPropertyPage::OnCtlColor(pDC, pWnd, nCtlColor);

    HBRUSH hbr = CreateSolidBrush(PROPERTYPAGE_BACKGROUND_COLOR);
    return hbr;
}

PropertySheet

Заголовок

class CustomPropertySheet : public CPropertySheet
{
    DECLARE_MESSAGE_MAP()

    public:
        CustomPropertySheet(UINT nIDCaption, CWnd* pParentWnd, UINT iSelectPage);
        virtual BOOL OnInitDialog();
        afx_msg void OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct);
        afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);

    private:
        void Draw_Background(CDC *pDC);
};

cpp

CustomPropertySheet::CustomPropertySheet(UINT nIDCaption, CWnd* pParentWnd, UINT iSelectPage) : CPropertySheet(nIDCaption, pParentWnd, iSelectPage)
{
}

BEGIN_MESSAGE_MAP(CustomPropertySheet, CPropertySheet)
    ON_WM_CTLCOLOR()
    ON_WM_DRAWITEM()
END_MESSAGE_MAP()

BOOL CustomPropertySheet::OnInitDialog()
{
    BOOL answer = CPropertySheet::OnInitDialog();

    CWnd* pTab = GetDlgItem(AFX_IDC_TAB_CONTROL);
    SetWindowLongPtr(pTab->m_hWnd, GWL_STYLE, GetWindowLongPtr(pTab->m_hWnd, GWL_STYLE) | TCS_OWNERDRAWFIXED);
    pTab->RedrawWindow();

    return answer;
}

void CustomPropertySheet::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
{
    if (nIDCtl == AFX_IDC_TAB_CONTROL)
    {
        CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
        Draw_Background(pDC);

        CRect rc(lpDrawItemStruct->rcItem);
        rc.bottom += 1;
        pDC->FillSolidRect(rc, CEasyPropertyPage::PROPERTYPAGE_BACKGROUND);
        pDC->SetTextColor(GENERIC_TEXT_COLOR);
        pDC->SetBkMode(TRANSPARENT);

        char  text[256];
        TCITEM tci = { TCIF_TEXT | TCIF_STATE, 0, 0, text, 255, -1, 0 };
        HWND tcw = ::GetDlgItem(m_hWnd, nIDCtl);
        int i, tic = int(::SendMessage(tcw, TCM_GETITEMCOUNT, 0, 0));
        for (i = 0; i < tic; ++i) 
        {
            if (lpDrawItemStruct->itemState & ODS_SELECTED)
            {
                CRect tir;
                ::SendMessage(tcw, TCM_GETITEM, WPARAM(i), LPARAM(&tci));
                ::SendMessage(tcw, TCM_GETITEMRECT, WPARAM(i), LPARAM(&tir));
                pDC->DrawText(text, tir, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
            }
        }
    }

    else CPropertySheet::OnDrawItem(nIDCtl, lpDrawItemStruct);
}

HBRUSH CustomPropertySheet::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    if (pWnd->GetDlgCtrlID() != 0)
        return CPropertySheet::OnCtlColor(pDC, pWnd, nCtlColor);

    HBRUSH hbr = CreateSolidBrush(GENERIC_BACKGROUND_COLOR);
    return hbr;
}

void CustomPropertySheet::Draw_Background(CDC* pDC)
{
    CRect rect; this->GetClientRect(rect);
    pDC->FillSolidRect(rect, GENERIC_BACKGROUND_COLOR);

    rect.DeflateRect(0, 20, 0, 0);
    pDC->FillSolidRect(rect, GENERIC_BORDER_COLOR);
}

1 Ответ

1 голос
/ 24 октября 2019

Чтобы настроить светло-серую область (которая является встроенным элементом управления с вкладкой ), вам необходимо переопределить метод OnDrawItem в вашем классе, производном от CPropertySheet, и выполнить собственный чертеж для элемента управления. с идентификатором AFX_IDC_TAB_CONTROL. Примерно так:

void MyPropertySheet::OnDrawItem(int nID, LPDRAWITEMSTRUCT pDIS)
{   
    if (nID == AFX_IDC_TAB_CONTROL) {
        CDC* pDC = CDC::FromHandle(pDIS->hDC);
        CRect rc(pDIS->rcItem); rc.bottom += 1;
        pDC->FillSolidRect(rc, RGB(255, 0, 0)); // Or whatever b/g/ colour you want
        pDC->SetTextColor(RGB(0,0,0)); // Or whatever text colour you want
        pDC->SetBkMode(TRANSPARENT);
        char  text[256];
        TCITEM tci = { TCIF_TEXT | TCIF_STATE, 0, 0, text, 255, -1, 0 };
        CRect tir;
        HWND tcw = ::GetDlgItem(m_hWnd, nID);
        int i, tic = int(::SendMessage(tcw, TCM_GETITEMCOUNT, 0, 0));
        for (i = 0; i < tic; ++i) {
            ::SendMessage(tcw, TCM_GETITEM, WPARAM(i), LPARAM(&tci));
            ::SendMessage(tcw, TCM_GETITEMRECT, WPARAM(i), LPARAM(&tir));
            if (pDIS->itemState & ODS_SELECTED)
                pDC->DrawText(text, tir, DT_CENTER |DT_VCENTER | DT_SINGLELINE);
        }
        pDC->Detach();
    }
    else { // Pass other stuff to the base class
        CPropertySheet::OnDrawItem(nID, pDIS);
    }
    return;
}

Конечно, обязательно добавьте ON_WM_DRAWITEM() к карте сообщений!

РЕДАКТИРОВАТЬ: Вы также должны явно установить стильвстроенный элемент управления вкладкой, чтобы включить TCS_OWNERDRAWFIXED. Вы можете сделать это в переопределении OnInitDialog для вашего класса.

РЕДАКТИРОВАТЬ 2: У меня есть немного лучший способ получить указатель на элемент управления вкладкой, сейчас! Кроме того, я добавил несколько строк кода, которые действуют как «чит» для адресации оставшейся области, которая должна быть окрашена - путем расширения вкладок, чтобы соответствовать ширине базового элемента управления ...

BOOL MyPropertySheet::OnInitDialog()
{
    BOOL answer = CPropertySheet::OnInitDialog(); // Call base class first!
    // ... whatever other stuff you may wish to do
//  CWnd* pTab = GetDlgItem(AFX_IDC_TAB_CONTROL);
    CTabCtrl* pTab = GetTabControl(); // This is a bit clearer than above line!
    // The following 4 lines comprise a 'first stab' at fixing the remaining issue:
    CRect rcTab; pTab->GetWindowRect(&rcTab);
    int nItems = pTab->GetItemCount();
    int border = GetSystemMetrics(SM_CXEDGE) * 2;
    pTab->SetMinTabWidth((rcTab.Width() - border) / nItems);
    // ...
    SetWindowLongPtr(pTab->m_hWnd, GWL_STYLE, GetWindowLongPtr(pTab->m_hWnd, GWL_STYLE) | TCS_OWNERDRAWFIXED);
    pTab->RedrawWindow();
    return answer;
}

Не стесняйтесь просить дальнейших разъяснений и / или объяснений.

...