deXo-fan Ответов: 2

Вручную нарисуйте заголовок окна того же цвета, что и обычные окна


Привет,

Я хочу вручную нарисовать то, что выглядит как заголовок окна во время события WM_NCPAINT. Я кое-чего добился, но никак не могу правильно подобрать цвет. Это не то же самое, что, скажем, цвет фона панели заголовков блокнота, который является RGB(0, 153, 188) - цвет, который я указал несколько месяцев назад в разделе Настройки "Персонализация".

Есть несколько определений Win32#, которые подходят близко, но я подозреваю, что это совпадение, и я, конечно же, не хочу просить свою программу сначала переключиться на другое окно, чтобы захватить цвет панели заголовков.

Это мой код. Не могли бы вы починить его или сказать мне, как это сделать, чтобы он получил правильный цвет? Прямо сейчас код заполняет клиентскую область цветом, который я выбрал, но это нарочно. Кнопка максимизации, которую я нарисовал, также не похожа на "настоящие" (окрашенные Windows) кнопки меню заголовков (iconize/minimize, restore, maximize). Вы можете мне помочь и там? Можно подумать, что функция DrawCaption на самом деле рисует подпись, как это делает Windows.

// WindowsProject2.cpp : Defines the entry point for the application.
//
#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

// Global Variables:
HINSTANCE hInst;                                // current instance
WCHAR szTitle[MAX_LOADSTRING];                  // The title bar text
WCHAR szWindowClass[MAX_LOADSTRING];            // the main window class name

// Forward declarations of functions included in this code module:
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);

    // TODO: Place code here.

    // Initialize global strings
    LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadStringW(hInstance, IDC_WINDOWSPROJECT2, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    // Perform application initialization:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }

    HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WINDOWSPROJECT2));

    MSG msg;

    // Main message loop:
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}



//
//  FUNCTION: MyRegisterClass()
//
//  PURPOSE: Registers the window class.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEXW wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style          = /*CS_HREDRAW | CS_VREDRAW*/ 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; // MAKEINTRESOURCEW(IDC_WINDOWSPROJECT2);
    wcex.lpszClassName  = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    return RegisterClassExW(&wcex);
}

//
//   FUNCTION: InitInstance(HINSTANCE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   hInst = hInstance; // Store instance handle in our global variable
   
   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;
}

//
//  FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  PURPOSE: Processes messages for the main window.
//
//  WM_COMMAND  - process the application menu
//  WM_PAINT    - Paint the main window
//  WM_DESTROY  - post a quit message and return
//
//
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);
            // Parse the menu selections:
            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_PAINT:
    //    {
    //        PAINTSTRUCT ps;
    //        HDC hdc = BeginPaint(hWnd, &ps);
    //        // TODO: Add any drawing code that uses hdc here...
    //        EndPaint(hWnd, &ps);
    //    }
    //    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));
        //Rectangle(ps.hdc, 0, 0, rcWin.right, rcWin.bottom);
        //DrawFocusRect(ps.hdc, &rect);
        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;
}

// Message handler for about box.
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;
}


Цель состоит в том, чтобы создать что-то вроде Google Chrome, который имеет полный контроль над тем, что нарисовано в подписи и что происходит, когда вы нажимаете на нее.

Я использую Windows 10. #Pragma вверху предназначена для создания элементов управления в стиле post-XP, Но, очевидно, она не влияет ни на что другое, включая панель заголовков.

Что я уже пробовал:

1) посмотрел функции GetSysColor и GetSysColorBrush на MSDN.
2) часами возился с моим кодом, пробуя все определения COLOR_* #, но в getstockobject и без него.

Richard MacCutchan

В чем причина использования DC_GRADIENT*0 Кроме того, если вы используете DrawCaption он будет использовать только те цвета, которые указаны в документации.

deXo-fan

DC_GRADIENT*0-это всего лишь часть игры на скрипке. Иногда, когда я хочу увидеть эффект, который константа оказывает на программу, опуская ее, я просто пишу константу*0, а когда я хочу снова включить ее, я удаляю *0. Это намного проще, чем удалить и вставить все слово целиком. Я не понимаю, что вы подразумеваете под "Он будет использовать только цвета".

2 Ответов

Рейтинг:
2

Rick York

Я рекомендую написать то, что я называю апплетом перечислителя. Вот скриншот одного из них, который я написал для system colors. Я написал несколько из них, но этот уже сделал, и ваш вопрос вдохновил меня. Скриншот на сайте ServImg.com[^]

Я хочу сказать, напишите что-то вроде этого, и тогда Вы сможете увидеть, какой цвет Блокнот, скорее всего, будет использовать.

Что я сделал, так это использовал CReportCtrl, который я нашел на этом сайте. Это Деривация CListCtrl, которая позволяет вам устанавливать цвета подпунктов. Затем я сделал цикл итерации, который приобрел системный цвет и добавил строку в элемент управления списком.


deXo-fan

I am very glad my question inspired you! But I don't think either of you got what I really want to do, or maybe I explained it poorly. I can't use the eye dropper tool, because I want my program to use whatever color the OS assigns to, e.g., caption bars. Which means, if it is red when my program is run, then I want my program's caption bar to be red, and if during or after the running of my program the user changes the OS assigned color to, say, green, then I want my program's caption bar to immediately be green. In other words: I want my window to behave like a normal window would; the only difference is I want to draw the caption bar myself instead of having Windows OS draw it. The reason for that is I might want to add a button next to the minimize button (like Chrome has - Chrome has a "new tab" button next to all the tabs while still using whatever color the user asked the OS to give it). And I've been told all of this has to be done in WM_NCPAINT. Just imagine I want to write an empty Window where I have the same level of control over all of it (not just the client area) as Google's programmers have over Chrome. This would include non-client click events, non-client mouseover events, drawing images and all sorts of graphics, etc.

Кстати, извините, что до сих пор ждал с ответом, но я действительно ценю ваши усилия!

Рейтинг:
1

Gerry Schmitz

Если я хочу узнать цвет, я делаю снимок экрана, вставляю его в краску.Сеть (или что-то подобное) и использовать их глазную пипетку / цветовое небо. Цветовое небо дает настройки RGB для выбранного цвета.

"Редактор изображений" Visual Studio также предоставляет настройки RGB для глазной пипетки.