#c #winapi
#c #winapi
Вопрос:
Я пытаюсь изменить цвет текста / фона для статического элемента управления. Я могу сделать это просто отлично следующим образом:
// This is the 'main' window
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance;
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW amp;~WS_MAXIMIZEBOX | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
CW_USEDEFAULT, 0, 1035, 764, nullptr, nullptr, hInstance, nullptr);
...
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
case WM_CTLCOLORSTATIC:
{
MessageBox( NULL, "CTLCOLORSTATIC called", "", MB_OK );
HDC hdcStatic = (HDC)wParam;
SetTextColor(hdcStatic, RGB(200, 200, 20));
SetBkColor(hdcStatic, RGB(10, 10, 10));
return (INT_PTR)CreateSolidBrush(RGB(30, 30, 30));
}
default:
return DefWindowProc( hWnd, message, wParam, lParam );
}
Но если я помещу окно в другое окно, цвет текста / фона дочернего элемента управления останется по умолчанию:
// This is the 'parent' window, which resides in the 'main' window
HWND parent = CreateWindowEx
(
0,
_TEXT("STATIC"),
"",
WS_TABSTOP | WS_VISIBLE | BS_SOLID | WS_CLIPCHILDREN,
10, 10, 500, 500,
hwnd,
NULL,
(HINSTANCE)GetWindowLong(hwnd, GWLP_HINSTANCE),
NULL
);
// This is the 'child' window which resides in the 'parent' window
HWND child = CreateWindowEx
(
0,
_TEXT("STATIC"),
"SubItem",
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_SOLID,
10, 10, 100, 100,
parent,
NULL,
(HINSTANCE)GetWindowLong(parent, GWLP_HINSTANCE),
NULL
);
В заключение, у меня есть 3 окна:
HWND hwnd; // the 'main' application window (color changes fine)
HWND parent; // the 'parent/container' window which is inside the 'main' window (color changes fine)
HWND child; // the 'child' window which is inside the 'parent' window (color DOES NOT change)
Даже если я помещу MessageBox внутри WM_CTLCOLORSTATIC, я вижу, что он запускается каждый раз, когда рисуются дочерние элементы, но цвет не изменяется для дочернего элемента, только для родительского.
Насколько я понял, мне нужно обработать сообщение в процедуре главного окна, но я не совсем понимаю, как это сделать. если я сравниваю параметр (HWND)lParam с дочерним параметром HWND, они совпадают (в случае переключения по умолчанию), поэтому я могу получить ссылку в разделе «по умолчанию», но я не уверен, как мне следует обращаться с этим оттуда..
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
case WM_CTLCOLORSTATIC:
{
if ((HWND)lParam == child )
MessageBox( NULL, "Reference Match for CTLCOLORSTATIC", "", MB_OK ); // <-- THIS NEVER TRIGGERS
}
....
default:
if ((HWND)lParam == child )
MessageBox( NULL, "Reference Match for DEFAULT", "", MB_OK ); // <-- THIS DOES TRIGGER
return DefWindowProc( hWnd, message, wParam, lParam );
}
return 0;
}
Причина, по которой я помещаю одно окно в другое, заключается в том, что я могу использовать свойство WS_CLIPCHILDREN в родительском окне (потому что дочерний элемент будет перемещаться / прокручиваться).
Комментарии:
1. Покажите больше своего кода, а не просто описывайте его. Вы также пропускаете кисти. У вас есть 3 уровня окон?
2. @Andres извините за это, я обновил свой вопрос дополнительным кодом. Да, это правильно — у меня есть окно ‘default / main’, в которое я добавляю ‘parent’, а ‘parent’ будет содержать дочернее окно. «Дочерний» цвет (окно третьего уровня) Я не могу обновить, но «родительский» цвет обновляется так же хорошо, как и «главное» окно.
3. WM_CTLCOLORSTATIC : «Статический элемент управления или элемент управления редактированием, доступный только для чтения или отключенный, отправляет
WM_CTLCOLORSTATIC
сообщение своему родительскому окну , когда элемент управления собирается быть нарисованным».4. @IInspectable спасибо за ответ. Извините, но я не совсем понимаю, как с этим справиться. Означает ли это, что мне нужно изменить его состояние на «не только для чтения» или мне нужно справиться с этим другим способом? Почему окна уровня 1 и уровня 2 не доступны только для чтения, а доступны для 3-го уровня? Спасибо!
5. Я выделил соответствующую часть жирным шрифтом.
Ответ №1:
WM_CTLCOLORSTATIC
отправляется статическим элементом управления в его родительское окно, а не в окно верхнего уровня.
hwndMain: WM_CTLCOLORSTATIC for hwnd1
|
--hwnd1: WM_CTLCOLORSTATIC for hwnd2 (You might have to subclass hwnd1)
|
--hwnd2
У вас также происходит утечка кистей, сохраните кисть из CreateSolidBrush
где-нибудь при создании окна и удалите ее, когда окно будет уничтожено.
Ответ №2:
Прочитав документ MSDN, я знаю функцию, SetWindowsLongPtr
параметр GWLP_WNDPROC
которой может задать новый адрес для оконной процедуры.
Эта функция может изменять цвет текста и фона дочернего окна, то есть она может запускаться WM_CTLCOLORSTATIC
.
Но после тестирования я обнаружил, что он недопустим для вторичного окна, то есть он не может изменить цвет текста родительского окна.
Я также просмотрел много информации и очень мало документов, связанных с трехуровневыми окнами.
Итак, я думаю, чтобы решить эту проблему и заставить все три окна изменить цвет текста, вам, возможно, придется переписать WndProc
самостоятельно, но это очень сложно и включает в себя множество вещей.
Редактировать: Если вам просто нужно изменить цвет текста и цвет фона статического элемента управления, вы можете настроить элемент управления так, чтобы вы могли обрабатывать все его операции.
Надеюсь вам помочь.