• Авторизация


Цвет фона MDI Client window - разгадка 06-04-2009 19:17 к комментариям - к полной версии - понравилось!


На рисунке показано, как выглядит типичное MDI-приложение под Windows - то есть такое, в котором можно одновременно открыть и редактировать несколько документов.

Цвета окон в системе Windows, в том числе и цвет фона MDI-приложения, заданы в системных настройках цвета. Пользователь может их редактировать через диалог "Свойства экрана". И эти настройки должны действовать на все приложения. По идее. Чтобы они на самом деле действовали, программист должен об этом позаботиться: задавая цвета элементов интерфейса, он должен не вручную указывать цвет, а некоторую константу-ссылку, увидев которую, система Windows подставит нужный цвет.

И вот с цветом фона для MDI-приложений существует конфузия. Для самих MDI-приложений цвет фона задается неявно внутри винды, и программист его не видит. А вот если я хочу сделать не-MDI приложение, использующее тот же самый цвет - то начинаются проблемы. На первый взгляд, если посмотреть исходник типичного MDI-приложения, то при создании главного окна указывается цвет фона COLOR_APPWORKSPACE. Но это совсем не тот цвет, что нужно. При попытке использовать эту константу в другом месте, например при задании цвета фона других окон, это становится сразу видно. Как же так получается?

Получается это потому, что все рабочее пространство главного окна программы занято специальным дочерним окном. Называется оно MDI Client Window. И цвет фона главного окна (Frame window) не виден - он закрыт окном MDI Client. Поэтому совершенно неважно, какой цвет фона задать для главного окна. Я обычно выбираю NULL_BRUSH - чтобы система даже не пыталась отрисовать этот фон, ведь все равно он сразу же будет затерт.

Цвет фона MDI Client Window программистом явно не задается. Он задан в системе, в оконном классе "MDICLIENT". И мне удалось посмотреть его с помощью функции GetClassInfo(NULL,"MDICLIENT",&wc).

В результате я выяснил, что цвет фона для MDI-приложений задается константой COLOR_HIGHLIGHT. Далеко не очевидный результат!
[663x316]
вверх^ к полной версии понравилось! в evernote
Комментарии (9):
Пчёлы 06-04-2009-21:21 удалить
В Delphiсия константа носит вполне осмысленное имя clAppWorkSpace :)
Хоть что-то в королевстве датском сделано на совесть.
Optical_Race 06-04-2009-21:30 удалить
А ты попробуй применить эту константу где-нибудь в другом месте - например, вручную создай Brush и нарисуй им что-нибудь. Сообщи о результатах, ибо я опасаюсь, что ты тоже попал в эту ловушку, потому что, скорее всего, делфи переназначает эту константу на COLOR_APPWORKSPACE.
Пчёлы 07-04-2009-14:16 удалить
ну, например, вот так вот...

var imgTest:TImage;
begin
imgTest:=TImage.Create(self);
imgTest.Left := 0;
imgTest.Top := 0;
imgTest.Width := 100;
imgTest.Height := 100;
imgTest.Canvas.Brush.Color:=clAppWorkSpace;
imgTest.Canvas.Ellipse(10,10,90,90);
imgTest.Parent := self;
end;

Эллипс рисует корректно, цветом рабочей области MDI
Optical_Race 07-04-2009-14:27 удалить
Интересное дело... Значит, разработчики делфи решили по своему разумению разрешить эту конфузию - которая происходит, в общем-то, из недр виндошного апи и с конкретным компилятором никак не связана.

Хоть для большинства людей это решение вроде бы должно снять проблему, но для таких, как я (которые ее уже решили с виндовс апи непосредственно) это может быть лишь источником новых конфузий :)

Тем более что - обрати внимание - в диалоге винды, где можно выбирать цвета для элементов пользовательского интерфейса, рабочая область MDI отсутствует. Вероятно, MDI было изобретено после того, как был задан стандарт на цвета элементов интерфейса пользователя.

(добавлено)

А вот, как оконный класс "MDICLIENT" и цвет его фона задаются в исходнике ReactOS (mdi.c):

/*********************************************************************
* MDIClient class descriptor
*/
const struct builtin_class_descr MDICLIENT_builtin_class =
{
L"MDIClient", /* name */
0, /* style */
MDIClientWndProcW, /* procW */
MDIClientWndProcA, /* procA */
sizeof(MDICLIENTINFO), /* extra */
IDC_ARROW, /* cursor */
(HBRUSH)(COLOR_APPWORKSPACE+1) /* brush */
};

А константа COLOR_APPWORKSPACE+1 как раз и соответствует COLOR_HIGHLIGHT.
Пчёлы 07-04-2009-15:08 удалить
Исходное сообщение Optical_Race
Интересное дело... Значит, разработчики делфи решили по своему разумению разрешить эту конфузию - которая происходит, в общем-то, из недр виндошного апи и с конкретным компилятором никак не связана.

Угу, видимо надо копать глубже в API, т.к. в современных версиях эту багу уже исправили. Ради спорта интереса открыл VBA из MS Office — та же AppWorkSpace. Возможно, когда MDI только появился, вместе с ним вылез и этот глюк, и существовал некоторое время.

Исходное сообщение Optical_Race
Тем более что - обрати внимание - в диалоге винды, где можно выбирать цвета для элементов пользовательского интерфейса, рабочая область MDI отсутствует. Вероятно, MDI было изобретено после того, как был задан стандарт на цвета элементов интерфейса пользователя.

Эээ, а что за винда? У меня вот оно есть, зовется рабочая область приложения.
[показать]

Исходное сообщение Optical_Race
А вот, как оконный класс "MDICLIENT" и цвет его фона задаются в исходнике ReactOS (mdi.c):

/*********************************************************************
* MDIClient class descriptor
*/
const struct builtin_class_descr MDICLIENT_builtin_class =
{
L"MDIClient", /* name */
0, /* style */
MDIClientWndProcW, /* procW */
MDIClientWndProcA, /* procA */
sizeof(MDICLIENTINFO), /* extra */
IDC_ARROW, /* cursor */
(HBRUSH)(COLOR_APPWORKSPACE+1) /* brush */
};

А константа COLOR_APPWORKSPACE+1 как раз и соответствует COLOR_HIGHLIGHT.
Неплохое решение, запоминающееся.
Пчёлы 07-04-2009-15:09 удалить
Кстати, а какие-то числовое значение этим константам соответствует?
Optical_Race 07-04-2009-16:46 удалить
Исходное сообщение Пчёлы
Кстати, а какие-то числовое значение этим константам соответствует?


Разумеется, соответствует. Константы эти определяются в Include-файлах Windows SDK, в данном случае - winuser.h. Оттуда находим, что COLOR_APPWORKSPACE = 12, а COLOR_HIGHLIGHT = 13.

В общем-то, только эти числа и играют роль, так как после компиляции программы уже не имеет значения, из какого там include-файла они взяты.

По этой же причине фиксить данный баг в Windows API нельзя: перестанут работать старые программы. И Include-файл тоже фиксить нельзя, но уже по другой причине: старые программы после перекомпиляции будут работать неправильно. Так что приходится оставлять все как есть. Может быть, в Knowledge base данная ситуация и описывается.

Исходное сообщение Пчёлы
Ради спорта интереса открыл VBA из MS Office — та же AppWorkSpace. Возможно, когда MDI только появился, вместе с ним вылез и этот глюк, и существовал некоторое время.

Он и сейчас существует - все мои данные относятся к WinXP SP3. Но то, что он исправлен в делфи и в VBA, говорит о том, что его нашли между тем, как появился АПИ и тем, как появился делфи/VBA. Поэтому и пофиксили - на уровне переназначения констант в include-файлах. А в Platform SDK уже не могли пофиксить - чтобы не нарушать совместимость программ.

А исходник ReactOS - это не просто приложение какое-нибудь, решающее частную проблему. Это почти как исходник самой винды, потому что в нем видно, как внутри винды что реализовано. Ведь класс окон "MDICLIENT" является системным, доступным для всех приложений.
Пчёлы 07-04-2009-19:39 удалить
Копаю дальше.

Декларация константы:
clAppWorkSpace = TColor(clSystemColor or COLOR_APPWORKSPACE);
и далее:
{$EXTERNALSYM COLOR_APPWORKSPACE}
COLOR_APPWORKSPACE = 12;
{$EXTERNALSYM COLOR_HIGHLIGHT}
COLOR_HIGHLIGHT = 13;
хм, следствие в тупике.

Константа clHighlight, разумеется существует, но даже и близко к фону рабочей области не относится.
05-11-2009-20:05 удалить
При регистрации класса окна указывается сама кисть для фона, а не индекс системного цвета. При использовании системных цветов можно указать GetSysColorBrush(COLOR_APPWORKSPACE) или что то же самое (HBRUSH)(COLOR_APPWORKSPACE+1). Отсюда и разница в единицу.


Комментарии (9): вверх^

Вы сейчас не можете прокомментировать это сообщение.

Дневник Цвет фона MDI Client window - разгадка | Optical_Race - Дневник Optical_Race | Лента друзей Optical_Race / Полная версия Добавить в друзья Страницы: раньше»