Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Вопрос про csOpaque


Страницы:   1 2

Суслик ©   (2005-09-27 20:02:00) 

Добрый день.

Никак не могу понять, как работает csOpaque.
1. Создаю кнопку
2. Создаю TWinControl, у которого ControlStyle := ControlStyle - [csOpaque]. При этом этот TWinControl "лежит" НАД кнопкой.

Почему не видна кнопка? Вроде должна...


Суслик   (2005-09-28 16:44:00) [1]

Спасибо, Игорь.
Буду смотреть, интересно.


Игорь Шевченко   (2005-09-28 16:43:00) [2]


> Судя по всему кто-то еще, а не указанный тобой InvalidateRect
> маркирует регион for erasing


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

При вызове Invalidate такому контролу ничего не придет. Но это не значит, что сообщение WM_EraseBkgnd контролу не придет вообще.
Опять же, если у контрола нет этого стиля, то InvalidateRect вызывается для родительского окна с указанием стереть клиентскую область, занимаемую контролом. То есть, контрол сам не рисует ВСЮ свою область и делегирует часть рисования родительскому компоненту.


Суслик   (2005-09-28 16:42:00) [3]

Вот и вопрос - кто его посылает. Я не доказываю, что я прочел все и сделал вывод, что посылать сообщение некому. Я лишь говорю о том, что в приведенных кусках кода про InvalidateRect + дока на BeginPain можно сделать вывод, что его посылает еще кто-то. Вот и интересно кто?


umbra   (2005-09-28 16:37:00) [4]

это да, получает. Но TWinControl - это полноценное окно винды и он не может не получать сообщений, которые шлет винда! насколько я понимаю, они шлются на хэндл окна и никакое роительское окно не может задержать это сообщение. вопрос лишь в реакции на него


Суслик   (2005-09-28 16:23:00) [5]

Виноват. Дурацкий шрифт получился.
Лучше так:

bErase
[in] Specifies whether the background within the update
region is to be erased when the update region is processed.
If this parameter is TRUE, the background is erased when
the BeginPaint function is called. If this parameter is
FALSE, the background remains unchanged.


Суслик   (2005-09-28 16:22:00) [6]

Так. Будем корректнее про мою внимательность.

Берем InvalidateRect. Читаем про третий параметр
bErase
[in] Specifies whether the background within the update region is to be erased when the update region is processed. If this parameter is TRUE, the background is erased when the BeginPaint function is called. If this parameter is FALSE, the background remains unchanged.


Читаем про BeginPaint
Remarks
The update region is set by the InvalidateRector InvalidateRgn function and by the system after sizing, moving, creating, scrolling, or any other operation that affects the client area. If the update region is marked for erasing, BeginPaint sends a WM_ERASEBKGND message to the window.


Судя по всему кто-то еще, а не указанный тобой InvalidateRect маркирует регион for erasing.


Игорь Шевченко   (2005-09-28 16:10:00) [7]

Суслик ©   (28.09.05 15:55) [26]


> Но опыт показывает, что наличие csOpaque не гарантирует,
>  что wm_erasebkgnd не прийдет.


Ты читаешь внимательно ? Или через слово ? В каком посте сказано, что наличие этого флага гарантирует/не гарантирует посылку WM_EraseBkgnd ?

Запусти поиск по каталогу с исходными текстами VCL слова csOpaque в файлах *.pas - посмотри, как и в каких случаях используется.


Суслик   (2005-09-28 15:55:00) [8]


> Достаточно одной строчки:
>
>      InvalidateRect(FHandle, nil, not (csOpaque in ControlStyle));
>
> и справки по InvalidateRect

кто же спорит.
Но опыт показывает, что наличие csOpaque не гарантирует, что wm_erasebkgnd не прийдет.

См. [14].


umbra   (2005-09-28 15:53:00) [9]

дело в том, что wm_erasebkgnd - сообщение виндоуз, а csOpaque - стиль контрола в Делфи. И, похоже, реализован он не на уровне сообщений винды, а позже - В TControl.Invalidate, TWinControl.Invalidate и т.д. В этих методах речь идет не о wm_erasebkgnd, а о СM_INVALIDATE - сообщении, определенном в Делфи, и действия различаются для контрола с csOpaque и для контрола без него!


Игорь Шевченко   (2005-09-28 15:52:00) [10]

Суслик ©   (28.09.05 15:16) [21]


> скорее для TGraphicControl.


Без разницы.


> У меня есть подозрение, что понять как это все работает
> можно только тотальным изучением controls.pas.


Достаточно одной строчки:

     InvalidateRect(FHandle, nil, not (csOpaque in ControlStyle));

и справки по InvalidateRect


Суслик   (2005-09-28 15:23:00) [11]


>  [22] umbra ©   (28.09.05 15:20)

Ты понимаешь в чем дело, рассуждения, начиная с поста [14] говорят об обратном - все равно перерисовывается. Возьми код из [14].
Поставь breakpoint в wmerasebkgnd и увидишь.


umbra   (2005-09-28 15:20:00) [12]

Может, дело прояснит TWinControl.Invalidate и связанная с ней TWinControl.CMInvalidate. Там видно, что если есть стиль csOpaque, то прямоугольник контрола не должен перерисовываться


Суслик   (2005-09-28 15:16:00) [13]


> кроме того, у меня есть сильное подозрение, что csOpaque
> имеет больше смысла для TControl, нежели для TWinControl

скорее для TGraphicControl.

Указанные методы вроде смотрел. Не особо что видно.
У меня есть подозрение, что понять как это все работает можно только тотальным изучением controls.pas.


Игорь Шевченко   (2005-09-28 15:13:00) [14]

Суслик ©   (28.09.05 14:35) [19]


> 1. Как я сказал, в случае если у контрола УСТАНОВЛЕН флаг
> csOpaque ему все равно приходит wm_erasebkgnd


TControl.Invalidate и TControl.Repaint глянь

кроме того, у меня есть сильное подозрение, что csOpaque имеет больше смысла для TControl, нежели для TWinControl


Суслик   (2005-09-28 14:35:00) [15]

Все вроде понятно, но все же.

Вот смотри:

1. Как я сказал, в случае если у контрола УСТАНОВЛЕН флаг csOpaque ему все равно приходит wm_erasebkgnd
2. Т.е. вызывается обработчик сообщения TWinControl.WMEraseBkgnd. В нем мы видим, что в любом случае (мой контрол НЕ DoubleBuffered) происходит прорисовка прямоугольника.

procedure TWinControl.WMEraseBkgnd(var Message: TWMEraseBkgnd);
begin
 { Only erase background if we're not doublebuffering or painting to memory. }
 if not FDoubleBuffered or
    (TMessage(Message).wParam = TMessage(Message).lParam) then
   FillRect(Message.DC, ClientRect, FBrush.Handle);
 Message.Result := 1;
end;


Т.е. несмотря на наличие csOpaque происходит рисование прямоугольника.

Что я в этом понимаю не так?


Игорь Шевченко   (2005-09-28 14:28:00) [16]

Суслик ©   (28.09.05 13:59) [17]


> Вроде не должно - я же поставил csOpaque.


Должно. Контрол же себя должен перерисовать, правильно ? Я могу еще раз сказать, что csOpaque отвечает за ответственность прорисовки. В случае csOpaque контрол сам обязан перерисовать всю свою клиентскую область, в случае отсутствия этого флага, часть клиентской области прорисовывает его родитель.


Суслик   (2005-09-28 13:59:00) [17]


>  [16] Игорь Шевченко ©   (28.09.05 13:47)

да я понял. Если ничего не делать, то будет "грязь" - остаток какого нить старого рисунка.

Вопрос то состоит в том, почему это сообщение вообще приходит. Вроде не должно - я же поставил csOpaque.

Вопрос не праздный, а скорее более теоретический - о влиянии csOpaque.


Игорь Шевченко   (2005-09-28 13:47:00) [18]

Суслик ©   (28.09.05 13:09) [15]


> см. комментарий в теле листинга в методе WVEraseBkgnd.


см. пост 13

> и не делай там ничего


Суслик   (2005-09-28 13:09:00) [19]

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


Суслик   (2005-09-28 12:59:00) [20]

Вот интересно

type
  twincontrol2 = class(twincontrol)
     constructor create(o: tcomponent); override;
     procedure WMEraseBkgnd(var Message: TWmEraseBkgnd); message WM_ERASEBKGND;
  end;

constructor twincontrol2.create;
begin
  inherited;
  controlstyle := controlstyle + [csopaque];
end;

procedure TWinControl2.WMEraseBkgnd(var Message: TWMEraseBkgnd);
begin
  inherited; // до сюда управление доходит. Почему? Установлен же csOpaque.
end;

procedure TForm1.Button3Click(Sender: TObject);
var
  kf: tform;
  kb: tbutton;
  kc: twincontrol2;
begin
  kf := tform.createnew(application);

  kb := tbutton.create(kf);
  kb.parent := kf;
  kb.left := 10;
  kb.top := 10;
  kb.width := 150;

  kc := twincontrol2.create(kf);
  kc.parent := kf;
  kc.left := 5;
  kc.top := 5;
  kc.width := 100;
  kc.height := 100;

  kf.show();
end;


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо