2

ウィンドウのキャプションを自分で描画するカスタム キャプション バーを描画する必要があります。

    HDC hdc = GetWindowDC(hwnd);
    if (hdc && prepareTitleBarDC(getWidth(), 27)) {
        SetWindowText(hwnd, _T(""));
        DefWindowProc(hwnd, WM_NCPAINT, wParam, lParam);
        m_titleBar->setSize(getWidth(), 27);
        m_titleBar->setBkColor(SkColorSetARGB(0x00, 0x00, 0x00, 0x00));
        m_titleBar->paintEvent(m_pTitleBarDC);
        FnSkBitmap::SaveSkBitmap(m_pTitleBarDC->canvas(), L"e:\\titlebar.bmp");

        HDC hdcPaint = CreateCompatibleDC(hdc);
        HBITMAP hbm = CreateCompatibleBitmap(hdc, getWidth(), 27);
        SelectObject(hdcPaint, hbm);
        FnSkBitmap::DrawSkBitmap(m_pTitleBarDC->bitmap(), hdcPaint);
        BLENDFUNCTION bfn = {0};
        bfn.BlendOp = AC_SRC_OVER;
        bfn.BlendFlags = 0;
        bfn.SourceConstantAlpha = 255;
        bfn.AlphaFormat = AC_SRC_ALPHA;
        AlphaBlend(hdc, 0, 0, getWidth(), 27, hdcPaint, 0, 0, getWidth(), 27, bfn);
    }
    ReleaseDC(hwnd, hdc);
    return 0;

AlphaBlend を使用して標準フレームを自分でミックスしますが、SetWindowText(_T("")) を使用すると、Alt+Tab スイッチャーのタイトルがなくなります。

WM_GETTEXT メッセージを処理してキャプション文字列を返そうとしましたが、失敗しました。自分でキャプション テキストを描画し、alt+tab スイッチャーでタイトルを作成するにはどうすればよいですか?

4

1 に答える 1

2

既に「カスタム キャプション バー」を描画しているため、実際のウィンドウのテキストを使用して実際に描画する理由はありません。

これを実現するには 2 つの方法があります。1 つDrawCaptionは Win9x Win32Api の従来の方法を使用する方法で、もう 1 つはより新しい「テーマ API」を使用する方法です。

両方を使用する例を次に示します。

#include <Windows.h>
#include <Uxtheme.h>
#include <vssym32.h>

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

const LPCWSTR WINDOW_CLASS = L"Test Window Class";
const LPCWSTR WINDOW_CAPTION = L"This is my test window";
const LPCWSTR CUSTOM_CAPTION = L"Custom Caption Text";

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow)
{
    WNDCLASSEX wndClassEx = {};

    wndClassEx.lpszClassName = WINDOW_CLASS;
    wndClassEx.hInstance = hInstance;
    wndClassEx.lpfnWndProc = WindowProc;
    wndClassEx.cbSize = sizeof(wndClassEx);
    wndClassEx.hCursor = (HCURSOR) LoadImage(NULL, MAKEINTRESOURCE(IDC_ARROW), IMAGE_CURSOR, 0, 0, LR_SHARED | LR_DEFAULTSIZE);
    wndClassEx.style = CS_DBLCLKS | CS_DROPSHADOW;

    ATOM registeredClass = RegisterClassEx(&wndClassEx);

    HWND hwnd = CreateWindowEx(
        0,
        WINDOW_CLASS,
        WINDOW_CAPTION,
        WS_SYSMENU,

        200, 200, 500, 300,

        NULL, // parent
        NULL, // menu
        hInstance,
        NULL // extra
        );

    if (hwnd == NULL)
    {
        return 0;
    }

    ShowWindow(hwnd, nCmdShow);

    MSG msg = {};
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_LBUTTONDBLCLK:
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;

    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hwnd, &ps);

            // fill the window with a color
            HBRUSH hbrush = CreateSolidBrush(RGB(33, 33, 33));
            FillRect(hdc, &ps.rcPaint, hbrush);
            DeleteObject(hbrush);

            // get a drawing area
            RECT rect = {};
            GetClientRect(hwnd, &rect);
            rect.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYEDGE) * 2;

            // draw a simple win9x style caption (switch out the window text while drawing)
            SetWindowText(hwnd, CUSTOM_CAPTION);
            DrawCaption(hwnd, hdc, &rect, DC_GRADIENT | DC_TEXT | DC_ACTIVE | DC_ICON);
            SetWindowText(hwnd, WINDOW_CAPTION);

            // use theme framework
            HTHEME htheme = OpenThemeData(hwnd, L"Window");

            // move downwards and then use new APIs for size
            rect.top += rect.bottom + 20;
            rect.bottom = rect.top + GetThemeSysSize(htheme, SM_CYSIZE) + GetThemeSysSize(htheme, SM_CXPADDEDBORDER) * 2;

            // draw the background
            DrawThemeBackground(htheme, hdc, WP_CAPTION, CS_ACTIVE, &rect, &ps.rcPaint);

            // load the caption font and save the old one
            LOGFONTW captionfont = {};
            GetThemeSysFont(htheme, TMT_CAPTIONFONT, &captionfont);
            HFONT newfont = CreateFontIndirect(&captionfont);
            HGDIOBJ oldfont = SelectObject(hdc, newfont);

            // center the font and draw
            rect.top += GetThemeSysSize(htheme, SM_CXPADDEDBORDER);
            DrawThemeTextEx(htheme, hdc, WP_CAPTION, CS_ACTIVE, CUSTOM_CAPTION, -1, DT_CENTER, &rect, NULL);

            // cleanup fonts
            SelectObject(hdc, oldfont);
            DeleteObject(newfont);

            // adjust draw location, load icon and draw
            rect.left += GetThemeSysSize(htheme, SM_CXPADDEDBORDER) * 2;
            rect.top += GetThemeSysSize(htheme, SM_CXPADDEDBORDER);
            HICON icon = (HICON) LoadImage(NULL, MAKEINTRESOURCE(IDI_APPLICATION), IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE);
            DrawIconEx(hdc, rect.left, rect.top, icon, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0, NULL, DI_NORMAL);


            // close theme
            CloseThemeData(htheme);

            EndPaint(hwnd, &ps);

        }
        return 0;

    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

結果のウィンドウは次のようになります。

結果ウィンドウのスクリーンショット

2 つの「カスタム描画」タイトル バーに、ウィンドウ上のテキストではなく、カスタム テキストが表示されていることがわかります。

コードを一目見ただけで、カスタム ルーチンを使用してテーマ ウィンドウのキャプションを試みることは、レガシーよりもはるかに難しいことがわかります。もちろん、トレードオフは、より多くの制御を提供することです。また、従来の方法を使用するときに必要なものを表示するために、ウィンドウのテキストを切り替えていることにも注意してください。さらに、従来のメソッドは、ウィンドウに関連付けられたスタイルから自分自身を描画する方法についてキューを取得することを覚えておく必要があります。ウィンドウ スタイルにアイコンがない場合は、アイコンを指定しても描画されません...

これらの手法のいずれかが目的を達成します。複数のタイトル バーを描画しないようにこのコードを切り替えて、ウィンドウ スタイルによって作成された既定のタイトル バーを削除すると、結果は次のようになります。

結果を示すスクリーンショット ここでは、タスク スイッチが実際のウィンドウ テキストを表示する様子と、私の「カスタム」キャプション バーが本物のように見えることを確認できます...

頑張ってください、これがお役に立てば幸いです -ck

補足: 私は Windows8 を実行していますが、キャプション描画ルーチンが私のテーマを無視している理由がわかりません...おそらくディレクティブを忘れていました

于 2013-04-10T20:43:54.377 に答える