3


1

MFC / WinAPIの大きな問題

複数のダイアログをタブコンテンツとしてカプセル化する2つのタブを持つフォームビューを使用してSDIフォームを作成する必要があります。 ただし、フォームには色付きの背景が必要です。

そして、このようなことはプログラミングを嫌います。

まず、リソースエディターを介して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ビットマシンでサウンドを再生する際にその動作に依存していることがわかりました。

とにかく、ダイアログコントロール(CPropertyPages)が期待どおりに作成され、その部分はリモートで有望なように見えますが、色のある次の部分は再び行き止まりです。

通常、WM_CTLCOLORをオーバーライドし、コントロールIDまたはhwndを確認し、必要なブラシを提供して必要な色を設定します。 CPropertySheetではそうではありませんが、一番上の行全体が灰色のままです。 CTabCtrlの場合は何とか機能しますが、CPropertySheetの場合は機能しません。

Why? CPropertySheetはCTabControlなどに埋め込まれているようです。WM_ERASEBKGNDをオーバーライドすると、内部部分だけが色を変えるからです。

CPropertySheetには、CPropertySheetの実際のCTabCtrl *を返すGetTabControl()メソッドがあるようです。 しかし、内部で構築されているため、WM_CTLCOLORメッセージ処理をオーバーライドする方法を見つけることができません。

windowprocをサブクラス化する方法があるように見えますが、何度か試してみると、その方法についての良いソースが見つかりません。 MSDNのSubclassWindowドキュメントには、「この関数が呼び出されるとき、ウィンドウはMFCオブジェクトに既に接続されていてはなりません。」?! あれは何でしょう?

MFCウィザードを使用してCTabCtrlに基づいてカスタムCCustomTabCtrlクラスを作成し、CCustomPropertySheetハンドラーの1つからSubclassWindowというインスタンスを作成して、内部CTabCtrlをオーバーライドしましたが、何も機能せず、MFCの奥深くでクラッシュします。

内部CTabCtrlにWindowLongをGCL_HBRBACKGROUNDで設定しようとしましたが、何も変更されませんでした。

そして最悪なことに、このトピックに関する有用なドキュメントやチュートリアルを見つけることができません。

私が見つけることができるほとんどは、タブコントロールの所有者を描画する方法ですが、これは非常に多くの点で深刻です、標準のコントロールの動作から背景色を引いて欲しいこのようなもの、そして私が見たオーナードローのサンプルはどれも、すべての標準的なコントロール動作の10%さえも正しく取得することはできません。 私はもっ​​と良いものを作成するという幻想は持っていません。手元にあるリソースには不向きです。

私はこのスレッドにつまずきました、そして、著者とさらに同意することができません:そして、MSDNに役立つNULL情報があります。

それで、私が見逃した、またはまだ試したことがないものはありますか? CPropertySheetのトップストリップの背景色を変更するにはどうすればよいですか? 誰でも?

2 Answer


5


唯一のオプションは、タブコントロールをownerdrawすることです。 それほど難しいことではありません。 まあ、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


この解決策をありがとうございます…​

上記のソリューションは1つのタブでうまく機能しますが、複数のタブがある場合、間違ったタブの名前を変更するようです。 GetItemのifステートメントを次のように変更する必要がありました。

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

タブの名前を正しく取得するために* lpDrawItemStruct→ itemID *が必要