既に「カスタム キャプション バー」を描画しているため、実際のウィンドウのテキストを使用して実際に描画する理由はありません。
これを実現するには 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 を実行していますが、キャプション描画ルーチンが私のテーマを無視している理由がわかりません...おそらくディレクティブを忘れていました