Модераторы: Snowy, Alexeis, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Вопрос про BeginPaint 
:(
    Опции темы
Zmiy
Дата 13.9.2007, 19:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 39
Регистрация: 3.3.2007

Репутация: нет
Всего: 2



Скажите, пожалуйста,  чем функция BeginPaint отличается от GetDC? Почему её нужно вызывать при обработке сообщения WM_PAINT, но нельзя в других случаях?
PM MAIL   Вверх
Alexeis
Дата 14.9.2007, 09:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 55
Всего: 459



 
Цитата(Zmiy @  13.9.2007,  19:24 Найти цитируемый пост)
Скажите, пожалуйста,  чем функция BeginPaint отличается от GetDC?

Цитата(MSDN)

The BeginPaint function automatically sets the clipping region of the device context to exclude any area outside the update region. 


Цитата(Zmiy @  13.9.2007,  19:24 Найти цитируемый пост)
Почему её нужно вызывать при обработке сообщения WM_PAINT, но нельзя в других случаях? 

Потому что графические дескрипторы не вечные, их дают во временное пользование, на период перерисовки. В другое время их достоверность не гарантируется.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Zmiy
Дата 14.9.2007, 10:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 39
Регистрация: 3.3.2007

Репутация: нет
Всего: 2



Цитата(Alexeis @  14.9.2007,  09:26 Найти цитируемый пост)
The BeginPaint function automatically sets the clipping region of the device context to exclude any area outside the update region. 

Это всё различие? Допустим, я перерисовываю окно по нажатию клавиши. Если я не вызываю BeginPaint, Windows шлёт мне WM_PAINT постоянно. Почему?
PM MAIL   Вверх
Alexeis
Дата 14.9.2007, 10:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 55
Всего: 459



  Суть вопроса я не понял. По нажатию кнопки не нужно рисовать, а лишь вызывать Invalidate у того кого нужно перерисовать. Invalidate - скажет винде, что есть область которая нуждается в перерисовке, затем винда пошлет сообщение WM_PAINT - контролу, после чего срабатывает событие OnPaint и начинается перерисовка. Последовательность действий имеет значение.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Zmiy
Дата 14.9.2007, 11:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 39
Регистрация: 3.3.2007

Репутация: нет
Всего: 2



Цитата(Alexeis @  14.9.2007,  10:51 Найти цитируемый пост)
По нажатию кнопки не нужно рисовать, а лишь вызывать Invalidate у того кого нужно перерисовать. Invalidate - скажет винде, что есть область которая нуждается в перерисовке, затем винда пошлет сообщение WM_PAINT - контролу, после чего срабатывает событие OnPaint и начинается перерисовка. Последовательность действий имеет значение.

Я понимаю. Я имел ввиду, что по нажатию клавиши (wm_keydown) я вызываю InvalidateRect. Затем я обрабатываю wm_paint и рисую средствами gdi. Dc у окна собственный, поэтому получать мне его каждый раз не нужно. НО если я не вызываю BeginPaint, то Windows шлёт мне wm_paint постоянно, даже когда окно никто не трогает. 
PM MAIL   Вверх
Alexeis
Дата 14.9.2007, 11:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 55
Всего: 459



Цитата(Zmiy @  14.9.2007,  11:35 Найти цитируемый пост)
Dc у окна собственный, поэтому получать мне его каждый раз не нужно. 

  Это что-то новенькое. smile . DC не бывает собственным, он предоставляется только на время сессии рисования, потом его просто необходимо освободить иначе возможно могут быть утечки памяти в винде.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Alexeis
Дата 14.9.2007, 12:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 55
Всего: 459



Цитата(Zmiy @  14.9.2007,  11:35 Найти цитируемый пост)
 НО если я не вызываю BeginPaint, то Windows шлёт мне wm_paint постоянно, даже когда окно никто не трогает.  

  Думаю за такой эффект ответственный кто-то другой. См. пример.
Код

program WinMin;

uses Windows, Messages;

const AppName = 'WinMin';

Var 
    Window : HWnd;
    
    Message : TMsg;  
    WindowClass : TWndClass;  
    

function WindowProc (Window : HWnd; Message, WParam : Word; LParam : LongInt) : LongInt; stdcall;
var
  dc : HDC;
  ps : PAINTSTRUCT;
begin
    WindowProc := 0; 
    case Message of 
      wm_Destroy :
      begin
        PostQuitMessage (0);
        Exit;
      end;

     WM_PAINT:
      begin
        dc := BeginPaint(Window, ps);
        TextOut(dc, 0, 0, PChar('Hello, Windows!'), 15);
        EndPaint(Window, ps);
        result := 0;
      end;
    end; // case
    WindowProc := DefWindowProc (Window, Message, WParam, LParam);  
end;

begin
    with WindowClass
  do
    begin
      Style := cs_HRedraw or cs_VRedraw;
      lpfnWndProc := @WindowProc;
      cbClsExtra := 0;
      cbWndExtra := 0;
      hInstance := 0;
      hIcon := LoadIcon (0, idi_Application);
      hCursor := LoadCursor (0, idc_Arrow);
      hbrBackground := GetStockObject (White_Brush);
      lpszMenuName := '';
      lpszClassName := AppName;
    end;
    
    If RegisterClass (WindowClass) = 0
  then
    Halt (255);

    Window := CreateWindow(AppName,  
                        'Win_Min',
                        ws_OverlappedWindow,
                        cw_UseDefault,
                        cw_UseDefault,
                        cw_UseDefault,
                        cw_UseDefault,
                        0,
                        0,
                        HInstance,
                        nil);
    
    ShowWindow (Window, CmdShow);  
    UpdateWindow (Window);  
    while GetMessage (Message, 0, 0, 0)
  do
    begin
      TranslateMessage (Message);
      DispatchMessage (Message);
    end;
    Halt
end.







--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
bems
Дата 14.9.2007, 16:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 1
Всего: 88



Цитата(Zmiy @  14.9.2007,  11:35 Найти цитируемый пост)
Windows шлёт мне wm_paint постоянно, даже когда окно никто не трогает
остается инвалидная облясть
из хелпа:
Цитата

The ValidateRect function validates the client area within a rectangle by removing the rectangle from the update region of the specified window. 

BOOL ValidateRect(

    HWND hWnd,    // handle of window 
    CONST RECT *lpRect    // address of validation rectangle coordinates 
   );    
 

Parameters

hWnd

Identifies the window whose update region is to be modified. If this parameter is NULL, Windows invalidates and redraws all windows and sends the WM_ERASEBKGND and WM_NCPAINT messages to the window procedure before the function returns. 

lpRect

Points to a RECT structure that contains the client coordinates of the rectangle to be removed from the update region. If this parameter is NULL, the entire client area is removed. 

 

Return Values

If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. 

Remarks

The BeginPaint function automatically validates the entire client area. Neither the ValidateRect nor ValidateRgn function should be called if a portion of the update region must be validated before the next WM_PAINT message is generated. 
Windows continues to generate WM_PAINT messages until the current update region is validated. 

это документированое поведение


--------------------
Обижено школьников: 8
PM MAIL   Вверх
Alexeis
Дата 14.9.2007, 17:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 55
Всего: 459



Цитата(bems @  14.9.2007,  16:09 Найти цитируемый пост)
это документированое поведение 
 Но ведь при использовании BeginPaint / EndPaint валидация провдиться, а сообщение шлется. Но однако в моем примере этого нет, WM_PAINT - вызывается всего 1 раз. Потому я думаю в этих вызовах виновен кто-то другой. Нужно больше кода.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
bems
Дата 14.9.2007, 17:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 1
Всего: 88



Цитата(Zmiy @  14.9.2007,  10:20 Найти цитируемый пост)
Если я не вызываю BeginPaint, Windows шлёт мне WM_PAINT постоянно
он его не вызывает. 

Цитата(Alexeis @  14.9.2007,  17:04 Найти цитируемый пост)
при использовании BeginPaint / EndPaint валидация провдиться, а сообщение шлется
где? Zmiy не вызывает, а в твоем примере этого нет.

не понял тебя



--------------------
Обижено школьников: 8
PM MAIL   Вверх
bems
Дата 14.9.2007, 17:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 1
Всего: 88



Цитата(Alexeis @  14.9.2007,  09:26 Найти цитируемый пост)
Потому что графические дескрипторы не вечные, их дают во временное пользование, на период перерисовки. В другое время их достоверность не гарантируется. 

Цитата(Alexeis @  14.9.2007,  11:51 Найти цитируемый пост)
DC не бывает собственным, он предоставляется только на время сессии рисования, потом его просто необходимо освободить

а как же это?
Цитата

The GetDC function retrieves a handle of a display device context (DC) for the client area of the specified window. The display device context can be used in subsequent GDI functions to draw in the client area of the window. 

This function retrieves a common, class, or private device context depending on the class style specified for the specified window. For common device contexts, GetDC assigns default attributes to the device context each time it is retrieved. For class and private device contexts, GetDC leaves the previously assigned attributes unchanged. 
...
After painting with a common device context, the ReleaseDC function must be called to release the device context. Class and private device contexts do not have to be released. The number of device contexts is limited only by available memory. 




--------------------
Обижено школьников: 8
PM MAIL   Вверх
Alexeis
Дата 14.9.2007, 17:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 55
Всего: 459



А прости, я невнимательно прочитал его пост, мне показалось, что он вызывает BeginPaint, но сообщения продолжают идти. Кстати наверняка при вызове GetDC валидация тоже производиться автоматом. 


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
bems
Дата 14.9.2007, 17:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 1
Всего: 88



Zmiy, если не вызываешь BeginPaint / EndPaint то попробуй после рисования сделать ValidateRect. Должно помочь

Добавлено через 2 минуты и 12 секунд
Цитата(Alexeis @  14.9.2007,  17:54 Найти цитируемый пост)
Кстати наверняка при вызове GetDC валидация тоже производиться автоматом
нет. Или по крайней мере не для всех типов DC (под типами я имею в виду common, class, or private)



--------------------
Обижено школьников: 8
PM MAIL   Вверх
Zmiy
Дата 14.9.2007, 20:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 39
Регистрация: 3.3.2007

Репутация: нет
Всего: 2



Цитата(Alexeis @  14.9.2007,  11:51 Найти цитируемый пост)
DC не бывает собственным

Если WindowClass.style указать как CS_OWNDC, то окно будет иметь постоянный dc, и BeginPaint (или getdc) каждый раз будет возвращать тебе одно и то же число.
Цитата(Alexeis @  14.9.2007,  12:12 Найти цитируемый пост)
 См. пример

Да, но если написть так
Код

WM_PAINT:
      begin
        dc := BeginPaint(Window, ps);
        TextOut(dc, 0, 0, PChar('Hello, Windows!'), 15);
        EndPaint(Window, ps);
        result := 0;
        Exit; //  !!!!!!!!!!!!!!!!!!!!!!!!!!!!
      end;

то будет мой случай. smile И я теперь понял почему! smile 
После каждого вывода надо обнулять прямоугольник региона обновления, чем BeginPaint и занимается.  Также это можно сделать с помощью ValidateRect и DefWindowProc.
Цитата(bems @  14.9.2007,  16:09 Найти цитируемый пост)
это документированое поведение 

Стрёмно, что они это не написали для Beginpaint. Выходит, чтобы понять, как действует одна функция, надо читать всю справку
Цитата(bems @  14.9.2007,  17:55 Найти цитируемый пост)
попробуй после рисования сделать ValidateRect. Должно помочь

Да, это как раз то что нужно, спасибо! smile

Теперь всё понятно, но есть ещё один дурацкий вопрос: есть ли разница между выводом графики средствами OpenGL по сообщеню wm_paint и по таймеру? То есть
Код

...
WM_TIMER:
begin
invalidaterect(wnd,nil,false);
Result:=0;
Exit;
end;
WM_PAINT:
begin
... // drawing
validaterect(wnd,nil);
Result:=0;
Exit;
end;
...
и
Код

...
WM_TIMER:
begin
... // drawing
Result:=0;
Exit;
end;
...



PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Звук, графика и видео"
Girder
Snowy
Alexeis

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делится вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • По вопросам разработки игр стоит заглянуть сюда

FAQ раздела лежит здесь!


Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Girder, Snowy.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Звук, графика и видео | Следующая тема »


 




[ Время генерации скрипта: 0.0663 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.