4

C++とWin32を使用してWindowsデスクトップアプリを作成しています。ダイアログボックスの外観は「WindowsXPスタイル」で醜いです。静的テキストの背景は灰色です。ダイアログボックスの背景も灰色の場合、これは問題ではありませんが、背景が白のタブコントロール内では、テキストの灰色の背景が非常に目立ちます。

以前は独自のコントロールの描画を数多く行ってきましたが、最近では、標準のルックアンドフィールを可能な限り使用し、標準の動作を可能な限り上書きしないようにしています。

少し古くなっているWin32APIを使用していますが、ATLでも問題が発生すると思います。DIALOGTEMPLATEを作成しています。テキストは「静的」コントロール(0x0082)にあります。スタイルに設定する唯一のフラグは「SS_LEFT」です。テキストコントロールはタブコントロール「SysTabControl32」内にあり、フラグはWS_CLIPSIBLINGSが1つだけ設定されています。SS_WHITERECTとWS_EX_TRANSPARENTおよびその他の設定を試しましたが、役に立ちませんでした。

これらはすべて、標準のWindowsダイアログボックスのメッセージハンドラーで描画されます。私の主な質問は「何が間違っているのか」です。「どうすればそれを回避できますか?」ではなく、誰も前者を手伝ってくれない場合は後者を選びます。

何か案は?

4

6 に答える 6

6

この問題に対するMSのソリューションにアクセスするには、タブコントロールにページを実装する通常の方法が必要です:-

タブ領域に個別のコントロールを作成する代わりに、ページごとにモードレスの子ダイアログを作成し、その上にコントロールを配置します。メインダイアログ(タブではない)を親として、ユーザーがタブを切り替えるときに、関連するページダイアログを表示および非表示にしてページダイアログを作成します。

各ページのWM_INITDIALOGハンドラーで、uxthemeAPIを呼び出しますEnableThemeDialogTexture

フラグを使用するETDT_ENABLETABと、ダイアログとそのすべての子コントロールの背景色が自動的に変更され、タブに適切にペイントされます。

DialogProcをオーバーライドした場合、WM_ERASEBKGNDまたはWM_CTLCOLOR*ページ内でDialogProcをオーバーライドした場合は、デフォルトの処理に戻す必要があります(FALSEを返します)。これらのメソッドは、ダイアログコードが手間のかかる作業を行う場所であるためです。スタイルビットは、子ページのダイアログページが通常のWindows9Xタブ付きダイアログで作成されるかのように設定する必要があります。

于 2009-08-06T08:17:50.453 に答える
4

背景が灰色になっているのは、それがデフォルトであるためです。

これをオーバーライドするには、親ウィンドウで WM_CTLCOLORSTATIC メッセージを処理し、カスタム ブラシを返すことができます。

于 2009-06-25T11:06:02.463 に答える
1

問題はATLやWinAPIではありません。MFCでも同じ問題があります。タブコントロールを静的コントロールの親ウィンドウとして設定します。WM_DRAWITEMしかし、オーバーライドはより柔軟な解決策だと思います。

于 2009-07-01T20:13:38.807 に答える
0

一見単純に見える問題を修正するために驚くほどの時間を費やし、hbrBackground のほぼすべての定数を試してみましたが、成功しませんでした。

アマチュアとして、最も簡単で時間効率の良い修正は、ウィンドウ全体を覆う「静的」クラスの子ウィンドウを作成することであることがわかりました。ただし、別のハックレベルの修正

于 2010-10-17T12:23:08.780 に答える
0

WM_CTLCOLORSTATIC メッセージをオーバーライドしていません。ソース コードにはこの文字列はなく、メッセージ ハンドラにも同様のものはありません。

この問題は、タブ コントロールの WM_DRAWITEM メッセージをオーバーライドして、白い背景 (タブ コントロールのコンテンツの標準) ではなく灰色の背景 (タブ コントロールのないダイアログ ボックスの標準) でコンテンツを描画することで回避しました。

        brush = CreateSolidBrush(GetSysColor(COLOR_MENU));
        FillRect(lpdis->hDC, &lpdis->rcItem, brush);
        SetBkColor(lpdis->hDC, GetSysColor(COLOR_MENU));
        wtext = ToWideStrdup(c->u.tabcontrol.Tabs[lpdis->itemID].name);
        rect = lpdis->rcItem;
        rect.top += DlgMarginY - 1;
        rect.bottom += DlgMarginY;
        DrawTextW(lpdis->hDC, wtext, -1, &rect, DT_CENTER | DT_VCENTER);
        free(wtext);
        DeleteObject(brush);

これは明らかに回避策であり、私の質問に対する適切な回答ではありません。

ちなみに、このようなコードを使用して、タブコントロールがその1つであると思われる「共通コントロール」を初期化します...これは問題に関連しているとは思いませんか?

#pragma comment(linker, "/manifestdependency:\"type='win32' " \
    "name='Microsoft.Windows.Common-Controls' " \
    "version='6.0.0.0' " \
    "processorArchitecture='*' " \
    "publicKeyToken='6595b64144ccf1df' " \
    "language='*'\"")
...

hCommCtrl = GetModuleHandle("comctl32.dll");`
if (hCommCtrl) {
        ptrInit = (TfcInit_fn) GetProcAddress(hCommCtrl, "InitCommonControlsEx");
        if (ptrInit) {
            data.dwSize = sizeof(INITCOMMONCONTROLSEX);
            data.dwICC  = ctrlClass;
            if (ptrInit(&data) )
                gCommCtrlsInitialized |= ICC_TAB_CLASSES | ICC_BAR_CLASSES;
        }
}
于 2009-06-30T21:44:51.867 に答える
0

ダイアログのタブ内にラベルが付いた Win32/MFC アプリケーションがあり、背景色は明確な特別な処理なしで (つまり、フラット グレーではなく、XP ルック テーマを反映して) きれいに見えます。

内部的には、ラベルが WM_CTLCOLOR メッセージをその親に送信し、デバイス コンテキストが適切に設定されます。Windows での既定の処理では、少なくともダイアログとタブ コントロールに対して適切な背景色を設定する必要があります。

1 つの可能性は、WM_CTLCOLOR の処理で標準外のことを行っていることです。アプリケーションのどこかで上書きされていませんか? この方法でラベルの背景色を設定している古いコードがある可能性があります。

(また、Rob が尋ねるように、comctl32 6.0 をアプリケーションに取り込むためにマニフェストを使用していますか?)

于 2009-06-25T09:43:48.743 に答える