Hello,
I wish to manually draw what looks like a window caption during the WM_NCPAINT event. I've made some progress, but I can't seem to get the color right. It's not the same as, say, Notepad's caption bar background color, which is RGB(0, 153, 188) - a color I specified a few months back under Settings > Personlization > Colors.
There are a few Win32 #defines that come close, but I suspect that is a coincidence, and I certainly don't want to ask my program to switch to another window first to grab the color of the caption bar.
This is my code. Could you fix it or tell me how to fix it so it gets the right color? Right now the code is filling the client area with the color I've chosen, but that's on purpose. The maximize button I've drawn also looks nothing like "real" (Windows painted) caption menu buttons (iconize/minimize, restore, maximize). Can you help me there aswell? You'd think the DrawCaption function would actually draw the caption like Windows does it.
#pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#include "framework.h"
#include "WindowsProject2.h"
#define MAX_LOADSTRING 100
HINSTANCE hInst; WCHAR szTitle[MAX_LOADSTRING]; WCHAR szWindowClass[MAX_LOADSTRING];
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_WINDOWSPROJECT2, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WINDOWSPROJECT2));
MSG msg;
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_DBLCLKS;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINDOWSPROJECT2));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)GetSysColorBrush(COLOR_MENUBAR);
wcex.lpszMenuName = NULL; wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance;
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_POPUPWINDOW,
300, 300, 900, 700, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
SetFocus(hWnd);
CreateWindow(L"BUTTON", L"Click me!", WS_CHILD | WS_VISIBLE, 100, 100, 75, 25, hWnd, 0, 0, 0);
break;
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_NCPAINT:
{
PAINTSTRUCT ps;
HRGN rgn = (HRGN)wParam;
RECT rect = { 850, 0, 870, 20 };
RECT rcCap = { 1, -9, 890, 30 };
RECT rcWin;
GetWindowRect(hWnd, &rcWin);
BeginPaint(hWnd, &ps);
SelectObject(ps.hdc, GetStockObject(BLACK_PEN));
SelectObject(ps.hdc, GetStockObject(NULL_BRUSH));
DrawCaption(hWnd, ps.hdc, &rcCap, DC_ACTIVE | DC_ICON | DC_TEXT | DC_BUTTONS | DC_GRADIENT*0 | DC_SMALLCAP);
DrawFrameControl(ps.hdc, &rect, DFC_CAPTION, DFCS_CAPTIONMAX | DFCS_HOT | DFCS_FLAT);
EndPaint(hWnd, &ps);
}
break;
case WM_SIZE:
InvalidateRect(hWnd, NULL, FALSE);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
The goal is to create something like Google Chrome, which has complete control over what is drawn in the caption and what happens when you click on it.
I'm running Windows 10. The #pragma on the top is to make post-XP-styled controls, but evidently it has no effect on anything else, including the caption bar.
What I have tried:
1) Looked up GetSysColor and GetSysColorBrush functions on MSDN.
2) Fiddled for hours with my code, trying all the COLOR_* #defines, but in and without GetStockObject.