0

まず、ここで傲慢/失礼に聞こえたら申し訳ありません。

よし、これで誰もがこの問題に遭遇したことになるだろう (私は願っている); どこにも適切な答えが見つかりませんでした。Common Controls 6 マニフェストから始めて、

case WM_CTLCOLORSTATIC:
    if (/* window has WS_EX_TRANSPARENT */) {
        SetBkMode((HDC) wParam, TRANSPARENT);
        return (LRESULT) GetStockObject(HOLLOW_BRUSH);
    }

そして私たちのラベルを付けてくださいWS_EX_TRANSPARENT。それらは透明になります。ここまでは順調ですね。次に、そのスタイルをチェックボックスに追加する必要があります (チェックボックスはそれに応答しWM_CTLCOLORBTN、何らかの理由で応答しないため)。そして...チェックボックスが黒くなります!

所有者の描画に頼らずに完全に透明にする方法はありますか? チェックボックスを自分で描画したくありません。テーマAPIが失敗した場合に、それが正しいかどうか、またはサイズが何であるかを推測する必要はありません(そして、将来、リストビューにカスタムチェックボックスを追加するときに、チェックボックスを自分で描画する必要があります私はすでに推測の量に満足していません)。

これらのチェックボックスは、テーマ タブ コントロール上に描画されています。これまでのところ、テーマ別のタブに透明なチェックボックスがある Windows XP の 5 つのダイアログを見つけました。ショートカット プロパティの [全般] タブ、タスクバーと [スタート] メニューのプロパティの [タスクバー] タブ、システム プロパティの [システムの復元] タブ、フォルダ オプション (ラジオ ボタン) の [全般] タブ。 、およびアクセシビリティ オプションの [キーボード] タブ。だから、これは確かに可能でなければなりません!Windows UI の作成者は、OS 全体でカスタム ドローを使用する必要はなかったと確信しています...何が欠けているのでしょうか?

サブクラス化する必要がある場合は問題ありませんが (イベント処理の目的で既にサブクラスを持っています)、それでも自分で描画する必要はありません。

おまけとして、押しボタンはどうですか?オーバーライドWM_CTLCOLORBTNするとボタンに黒い境界線が表示されますが、上記の標準ダイアログのいずれもボタンの角を透明にすることを気にしていないことに気付きました。

ありがとう!

4

3 に答える 3

1

次のように、ウィンドウの登録済みクラスの要素を返す必要が hbrBackgroundあります。

case WM_CTLCOLORBTN:
case WM_CTLCOLORSTATIC: {
    wchar_t  class_Name[100];
    GetClassName(hWnd, class_Name, 100);
    WNDCLASS lpcls{};
    GetClassInfo(g_hInstance, class_Name, &lpcls);

    return  (LRESULT)lpcls.hbrBackground;
}
于 2016-06-11T15:42:19.040 に答える
0

主にこれを釘付けにしました:

void paintControlBackground(HWND hwnd, HDC dc)
{
    HWND parent;
    RECT r;
    POINT p;
    int saved;

    parent = GetParent(hwnd);
    if (parent == NULL)
        xpanic("error getting parent container of control in paintControlBackground()", GetLastError());
    if (GetWindowRect(hwnd, &r) == 0)
        xpanic("error getting control's window rect in paintControlBackground()", GetLastError());
    // the above is a window rect; convert to client rect
    p.x = r.left;
    p.y = r.top;
    if (ScreenToClient(parent, &p) == 0)
        xpanic("error getting client origin of control in paintControlBackground()", GetLastError());
    saved = SaveDC(dc);
    if (saved == 0)
        xpanic("error saving DC info in paintControlBackground()", GetLastError());
    if (SetWindowOrgEx(dc, p.x, p.y, NULL) == 0)
        xpanic("error moving window origin in paintControlBackground()", GetLastError());
    SendMessageW(parent, WM_PRINTCLIENT, (WPARAM) dc, PRF_CLIENT);
    if (RestoreDC(dc, saved) == 0)
        xpanic("error restoring DC info in paintControlBackground()", GetLastError());
}

    case WM_CTLCOLORSTATIC:
    case WM_CTLCOLORBTN:
        if (SetBkMode((HDC) wParam, TRANSPARENT) == 0)
            xpanic("error setting transparent background mode to Labels", GetLastError());
        paintControlBackground((HWND) lParam, (HDC) wParam);
        *lResult = (LRESULT) hollowBrush;
        return TRUE;

未解決の問題がいくつかあります。

指定されたコントロールの直接の親がグループボックスの場合、これは機能しません。その場合、クラス名を調べて、親チェーンをたどる必要があります。

WM_PRINTCLIENTまた、任意のカスタム コンテナーに実装する必要があり、ウィンドウ クラスにも実装する必要があります。

これは、グループボックス ラベルではまだ機能しません。テクスチャが適切に描画されていることがわかりますが、グループボックスの線がその上に描画されます。それを理解したら、これを解決済みとしてマークし、その情報でこの投稿を更新します。

(私が見たちらつきは、プログラムの別の部分で使用されているストップ・ザ・ワールドのガベージ・コレクターによって引き起こされているようで、当分の間、私の手に負えません。これはすぐに変わることを願っています。)

それまでの間、ありがとう!

于 2014-08-28T14:41:08.930 に答える