2010-10-20 90 views
3

我需要创建一个带有两个选项卡的formview的SDI表单,它将多个对话框封装为选项卡内容。但表单必须有一个彩色背景。MFC/WinAPI的大问题

而这些事情让我讨厌编程。

首先,我尝试了CTabControl,通过资源编辑器尝试了不同的事情,但没有记录的行为和没有答案的怪癖让我陷入了困境。

经过很多小时的搜索后,我发现有一个叫做属性表的控件,它实际上是我需要的。

一些更后来搜索,我发现属性表甚至可以实际上嵌入到的CFormView像这样:http://www.codeguru.com/Cpp/controls/propertysheet/article.php/c591

和从CPropertyPage派生的对话框类可以直接加入作为经由的CPropertySheet的AddPage方法页。

太棒了!不太如此......一些控件没有工作,并且没有创建,遇到了怪异的断言。原来对话框中缺少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这就是这种行为是从哪里来的?

事实证明,在PlaySound API在64位计算机播放声音时,依赖于这种行为。”拉里奥斯特曼,据我所知,他为微软工作了20年,让我大声笑出声来。

无论如何,固定的是,对话框控件(CPropertyPages)现在可以按照预期创建,并且该部分看起来很有前途,但接下来的颜色部分又是死胡同了!

通常情况下,您会覆盖WM_CTLCOLOR,检查控件ID或hwnd并提供必要的画笔以设置所需的颜色。用CPropertySheet不太如此,整个顶部行保持灰色!对于CTabCtrl它以某种方式起作用,对于CPropertySheet它不起作用。

为什么?似乎CPropertySheet有点嵌入CTabControl内部,因为如果我重写WM_ERASEBKGND,只有内部部分改变颜色。

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

似乎有一种方法来对windowproc进行子类化处理,但经过多次尝试后,我找不到任何有关如何去做的好消息。 MSDN上的SubclassWindow doc说:“调用这个函数时,窗口不能被附加到MFC对象上。”?!那是什么?

我试图通过MFC向导创建一个基于CTabCtrl的自定义CCustomTabCtrl类,创建它的一个实例,从CCustomPropertySheet处理程序之一调用SubclassWindow以覆盖内部CTabCtrl,但没有任何作品,神秘崩溃在MFC深处。

试图用GCL_HBRBACKGROUND设置WindowLong作为内部CTabCtrl,没有任何改变。

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

我能找到的大部分是如何自带tab控件,但是在很多方面这都是严重错误的,我想要一个标准的控制行为减去背景颜色,我不想支持不同的配色方案,windows版本, IAccesible接口和所有这些东西,并且我见过的所有ownerdraw样本都不到10%的所有标准控制行为都是正确的。我不会幻想我会创造更好的东西,我不会用手头的资源。

我偶然发现了这个帖子,我不能同意作者更多:http://arstechnica.com/civis/viewtopic.php?f=20&t=169886&sid=aad002424e80121e514548d428cf09c6所有者绘制控件是未公开的PITA,这是不可能的,并且MSDN上有NULL信息可以提供帮助。

那么有什么我错过了或没有尝试过吗?如何更改CPropertySheet的顶部条形背景颜色?任何人?

+0

“?那么,有什么我已经错过了或者还没有尝试过” WPF?感觉雅。 – Will 2010-10-20 12:22:35

+0

该要求是本机应用程序。 ( – Coder 2010-10-20 12:25:25

+0

)你首先使用MFC要求这种痛苦,MFC非常强大,但也很难学,如果你想创建一个Windows窗体,可以用C#/ .Net来完成。您可以在WinForms或WPF中轻松完成这些任务(尽管Tab控件仍然是PITA)。 – MusiGenesis 2010-10-20 12:29:00

回答

5

您唯一的选择是自主绘制选项卡控件。这并不难。那么,这是令人沮丧的,因为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(); 
} 
0

感谢您对这个解决办法,但...

上述解决方案行之有效的一个标签,但是当你有多个选项卡似乎重命名错误的标签。我需要改变,如果语句的GetItem到:

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

所需lpDrawItemStruct-> ITEMID,以获得正确的标签命名