2010-10-20 34 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,以獲得正確的標籤命名