我需要使用带有两个选项卡的formview创建一个SDI表单,该视图将多个对话框封装为选项卡内容。但是表格必须具有彩色背景。

这些事情让我讨厌编程。

首先,我通过资源编辑器尝试了CTabControl,尝试了不同的操作,但是未记录的行为和没有答案的怪癖使我陷入了障碍。

经过数小时的搜索,我发现有一个称为属性表的控件,这实际上是我所需要的。

稍后再进行搜索,我发现甚至可以将属性表实际上嵌入到CFormView中,如下所示:http://www.codeguru.com/Cpp/controls/propertysheet/article.php/c591

并且可以通过CPropertySheet的AddPage方法将源自CPropertyPage的对话框类直接添加为页面。

大!并非完全如此...有些控件没有起作用,也没有创建,遇到了奇怪的断言。原来对话框中缺少DS_CONTROL样式。在http://blogs.msdn.com/b/oldnewthing/archive/2007/01/08/1434501.aspx上完全偶然地发现了它,在MSDN上一无所获!!!属性页必须具有:DS_3DLOOK | DS_CONTROL | WS_CHILD | WS_TABSTOP,并且可以具有:DS_SHELLFONT | DS_LOCALEDIT | WS_CLIPCHILDREN样式!没有其他,默认情况下是使用资源编辑器创建的。给软件开发人员的甜蜜,超级隐藏的信息!

该页面上的注释中的引言是:“OMG。这就是该行为的来源...

事实证明,当在64位计算机上播放声音时,PlaySound API依赖于这种行为。”据我了解为Microsoft工作了20年的拉里·奥斯特曼(Larry Osterman),我大声笑了起来。

无论如何,修正了该问题,现在已经按预期创建了dialog-controls(CPropertyPages),并且该部分看起来有些遥不可及,但是下一个带有颜色的部分再次死了!

通常,您将重写WM_CTLCOLOR,检查控件ID或hwnd,并提供必要的画笔以设置所需的颜色。对于CPropertySheet并非如此,整个第一行都保持灰色!对于CTabCtrl,它以某种方式起作用,对于CPropertySheet,它不起作用。

为什么?似乎CPropertySheet有点嵌入CTabControl之类的东西,因为如果重写WM_ERASEBKGND,则只有内部会更改颜色。

现在看来,CPropertySheet中有一个GetTabControl()方法,该方法返回CPropertySheet的实际CTabCtrl *。但是由于它是内部构造的,所以我找不到如何覆盖它的WM_CTLCOLOR消息处理。

似乎有一种方法可以将windowproc子类化,但是经过多次尝试,我找不到有关如何执行此操作的任何好方法。 MSDN上的SubclassWindow文档说:“调用此函数时,窗口必须尚未附加到MFC对象。”那是什么?

我尝试通过MFC向导基于CTabCtrl创建一个自定义CCustomTabCtrl类,并从一个CCustomPropertySheet处理程序创建了一个实例SubclassWindow来覆盖内部CTabCtrl,但是没有任何效果,但是神秘的崩溃在MFC内部深处。

尝试将内部CTabCtrl的WindowLong设置为GCL_HBRBACKGROUND,但未进行任何更改。

最糟糕的是,我找不到关于该主题的任何有用的文档或教程。

我最多能找到的是如何所有者制表符控件,但是在很多方面这都是严重的错误,我想要一个标准控件行为减去背景色,我不希望支持不同的配色方案,Windows版本,IAccesible接口以及所有这些东西,而且我所见过的ownerdraw示例都无法获得所有标准控件行为的10%。我没有幻想会创造出更好的东西,我不会动用手头的资源。

我偶然发现了这个线程,我也与作者完全不同:http://arstechnica.com/civis/viewtopic.php?f=20&t=169886&sid=aad002424e80121e514548d428cf09c6所有者绘制控件是未记录的PITA,无法正确执行,并且MSDN上有NULL信息可为您提供帮助。

那么,有什么我想念或尚未尝试的吗?如何更改CPropertySheet的顶部条背景色?任何人?

最佳答案

您唯一的选择是所有者绘制选项卡控件。没那么难。好吧,这很令人沮丧,因为MFC不会告诉您如何进行必要的Win32调用。

在CPropertySheet派生的类中,覆盖OnInitDialog()并添加:
GetTabControl()->ModifyStyle(0,TCS_OWNERDRAWFIXED);
这使您的CPropertySheet派生类负责绘制选项卡控件。为WM_DRAWITEM(OnDrawItem)添加一个处理程序,并更改backgroundColor和textColor以匹配所需的任何颜色。 OnDrawItem的代码如下:

void CPropSht::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
{
    if (ODT_TAB != lpDrawItemStruct->CtlType)
    {
        CPropertySheet::OnDrawItem(nIDCtl, lpDrawItemStruct);
        return;
    }

    // prepare to draw the tab control
    COLORREF backgroundColor = RGB(0,255,0);
    COLORREF textColor = RGB(0,0,255);
    CTabCtrl *c_Tab = GetTabControl();

    //  Get the current tab item text.
    TCHAR buffer[256] = {0};
    TC_ITEM tcItem;
    tcItem.pszText = buffer;
    tcItem.cchTextMax = 256;
    tcItem.mask = TCIF_TEXT;

    if (!c_Tab->GetItem(c_Tab->GetCurSel(), &tcItem )) return;

    // draw it
    CDC aDC;
    aDC.Attach(lpDrawItemStruct->hDC);
    int nSavedDC = aDC.SaveDC();

    CBrush newBrush;
    newBrush.CreateSolidBrush(backgroundColor);
    aDC.SelectObject(&newBrush);
    aDC.FillRect(&lpDrawItemStruct->rcItem, &newBrush);
    aDC.SetBkMode(TRANSPARENT);
    aDC.SetTextColor(textColor);
    aDC.DrawText(tcItem.pszText, &lpDrawItemStruct->rcItem, DT_CENTER|DT_VCENTER|DT_SINGLELINE);

    aDC.RestoreDC(nSavedDC);

    aDC.Detach();
}

08-17 07:03