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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> GDI+ Глюк или особенность??? Вчём проблема??? 
V
    Опции темы
ivan219
  Дата 28.7.2007, 20:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1121
Регистрация: 19.11.2005
Где: Планета земля

Репутация: 4
Всего: 12



Этот код не работает так как надо:
Код

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,GDIPAPI,GDIPOBJ, StdCtrls, ExtCtrls, ComCtrls, Math;

type
  TForm1 = class(TForm)
    Timer1: TTimer;
    Button1: TButton;
    procedure P(Pos, Max, Rmax, Rmin: Integer);
    procedure FormCreate(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  GraphicsGDIPlus : TGPGraphics;
  Pen: TGPPen;
  SolidBrush: TGPSolidBrush;
  I, I1: Integer;

implementation

{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
 DoubleBuffered:=True;
end;


procedure TForm1.P(Pos, Max, Rmax, Rmin: Integer);
var
  F, X, Y: Extended;
begin
 if Pos>Max then Exit;
 F:=2 * Pi * Pos / Max;
 SinCos(F, X, Y);
 GraphicsGDIPlus.DrawLine(Pen,  Rmax + X * Rmin,
                                Rmax + Y * Rmin,
                                Rmax + X * Rmax,
                                Rmax + Y * Rmax);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
 Repaint;
 GraphicsGDIPlus.FillEllipse(SolidBrush,95,95,10,10);
 for I:=0 to 100 do
  begin
   P(I,10,100,85);
   P(I,20,100,90);
   P(I,100,100,95);
  end;
 P(I1,100,100,0);
 Inc(I1, 1);
 if I1>100 then I1:=10;
 Caption:=IntToStr(I1);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 GraphicsGDIPlus:=TGPGraphics.Create(Canvas.Handle);
 GraphicsGDIPlus.SetSmoothingMode(SmoothingModeHighQuality);
 Pen:=TGPPen.Create(MakeColor(255, 0, 0, 0), 2);
 SolidBrush:=TGPSolidBrush.Create(MakeColor(255, 0, 0, 0));
 Timer1.Enabled:=True;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 Pen.Free;
 SolidBrush.Free;
 GraphicsGDIPlus.Free;
end;
end.


А вот так работае:
Код

procedure TForm1.Timer1Timer(Sender: TObject);
begin
 Repaint;
 GraphicsGDIPlus:=TGPGraphics.Create(Canvas.Handle);
 GraphicsGDIPlus.SetSmoothingMode(SmoothingModeHighQuality);
 Pen:=TGPPen.Create(MakeColor(255, 0, 0, 0), 2);
 SolidBrush:=TGPSolidBrush.Create(MakeColor(255, 0, 0, 0));
 GraphicsGDIPlus.FillEllipse(SolidBrush,95,95,10,10);
 for I:=0 to 100 do
  begin
   P(I,10,100,85);
   P(I,20,100,90);
   P(I,100,100,95);
  end;
 P(I1,100,100,0);
 Inc(I1, 1);
 if I1>100 then I1:=10;
 Pen.Free;
 SolidBrush.Free;
 GraphicsGDIPlus.Free;
 Caption:=IntToStr(I1);
end;

Вопрос: почему когда: 
Код

 GraphicsGDIPlus:=TGPGraphics.Create(Canvas.Handle);
 GraphicsGDIPlus.SetSmoothingMode(SmoothingModeHighQuality);
 Pen:=TGPPen.Create(MakeColor(255, 0, 0, 0), 2);
 SolidBrush:=TGPSolidBrush.Create(MakeColor(255, 0, 0, 0));


 Pen.Free;
 SolidBrush.Free;
 GraphicsGDIPlus.Free;

выносиш за пределы одной процедуры то ничего не рисует???
И как от этого избавится???

Это сообщение отредактировал(а) ivan219 - 28.7.2007, 20:33
PM MAIL ICQ   Вверх
s-mike
Дата 29.7.2007, 19:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 425
Регистрация: 16.1.2005
Где: Киев

Репутация: 5
Всего: 16



Я бы сказал, что это элементарное незнание принципов работы VCL. Рисовать нужно в событии OnPaint.
PM MAIL WWW   Вверх
ivan219
  Дата 29.7.2007, 21:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1121
Регистрация: 19.11.2005
Где: Планета земля

Репутация: 4
Всего: 12



s-mike, Вобщето я это знаю вопрос в другом.
PM MAIL ICQ   Вверх
s-mike
Дата 29.7.2007, 21:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 425
Регистрация: 16.1.2005
Где: Киев

Репутация: 5
Всего: 16



Цитата(ivan219 @  29.7.2007,  21:43 Найти цитируемый пост)
Вобщето я это знаю вопрос в другом. 

Судя по коду - нет. Иначе зачем рисовать в Button.OnClick, Timer.OnTimer? Если известно, что это _в корне_ неправильно.

Собственно проблемы все из-за как раз из-за этого.

Весь код отрисовки следует переместить в Form.OnPaint, а в событии кнопки или таймера следует поместить только команду перерисовки — Invalidate.
PM MAIL WWW   Вверх
ivan219
  Дата 29.7.2007, 22:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1121
Регистрация: 19.11.2005
Где: Планета земля

Репутация: 4
Всего: 12



Ну хорошо вот так будет правильно?
Код

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls,GDIPAPI,GDIPOBJ;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormPaint(Sender: TObject);
    procedure FormShow(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  GraphicsGDIPlus : TGPGraphics;
  Pen: TGPPen;

implementation

{$R *.dfm}

procedure TForm1.FormShow(Sender: TObject);
begin
 GraphicsGDIPlus:=TGPGraphics.Create(Canvas.Handle);
 GraphicsGDIPlus.SetSmoothingMode(SmoothingModeHighQuality);
 Pen:=TGPPen.Create(MakeColor(255, 0, 0, 0), 2);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 Invalidate;
end;

procedure TForm1.FormPaint(Sender: TObject);
begin
  GraphicsGDIPlus.DrawLine(Pen,0,0,100,100);
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 Pen.Free;
 GraphicsGDIPlus.Free;
end;
end.

Только проблема осталось.
Зато если сделать так:
Код

procedure TForm1.FormPaint(Sender: TObject);
begin
 GraphicsGDIPlus:=TGPGraphics.Create(Canvas.Handle);
 GraphicsGDIPlus.SetSmoothingMode(SmoothingModeHighQuality);
 Pen:=TGPPen.Create(MakeColor(255, 0, 0, 0), 2);
 GraphicsGDIPlus.DrawLine(Pen,0,0,100,100);
 Pen.Free;
 GraphicsGDIPlus.Free;
end;

или так
Код

procedure TForm1.Button1Click(Sender: TObject);
begin
 A;
 B;
 C;
end;

procedure TForm1.A;
begin
 GraphicsGDIPlus:=TGPGraphics.Create(Canvas.Handle);
 GraphicsGDIPlus.SetSmoothingMode(SmoothingModeHighQuality);
 Pen:=TGPPen.Create(MakeColor(255, 0, 0, 0), 2);
end;

procedure TForm1.B;
begin
 GraphicsGDIPlus.DrawLine(Pen,0,0,100,100);
end;

procedure TForm1.C;
begin
 Pen.Free;
 GraphicsGDIPlus.Free;
end;

То всё отрисовывается, вот я и задал вопрос почему нужно создавать обекты GraphicsGDIPlus Pen их отрисовывать и уничтожать в одной процедуре т.е. последовательно, так как ели сделать так:
Код

procedure TForm1.Button1Click(Sender: TObject);
begin
 GraphicsGDIPlus:=TGPGraphics.Create(Canvas.Handle);
 GraphicsGDIPlus.SetSmoothingMode(SmoothingModeHighQuality);
 Pen:=TGPPen.Create(MakeColor(255, 0, 0, 0), 2);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 GraphicsGDIPlus.DrawLine(Pen,0,0,100,100);
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
 Pen.Free;
 GraphicsGDIPlus.Free;
end;

И нажать по очереди Button1..3 то тоже ничего неотрисовывается.

Это сообщение отредактировал(а) ivan219 - 29.7.2007, 22:59
PM MAIL ICQ   Вверх
Alexeis
Дата 30.7.2007, 08:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


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

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



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


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

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

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


Опытный
**


Профиль
Группа: Участник
Сообщений: 425
Регистрация: 16.1.2005
Где: Киев

Репутация: 5
Всего: 16



Конечно не правильно. Объект Graphics должен создаваться при каждой перерисовке.
Цитата(ivan219 @  29.7.2007,  22:53 Найти цитируемый пост)
То всё отрисовывается

Повезло, не более smile Повезло, что дескриптор не был изменен.

Правильно будет так:
Код

procedure TForm.FormPaint;
var
  G: TGPGraphics;
begin
  G := TGPGraphics.Create(Canvas.Handle);
  try
    // здесь код отрисовки
  finally
    G.Free;
  end;
end;

PM MAIL WWW   Вверх
ivan219
  Дата 30.7.2007, 16:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1121
Регистрация: 19.11.2005
Где: Планета земля

Репутация: 4
Всего: 12



Печально smile
Значит надо всегда создавать и уничтожать ведь это лишнии затраты ресурсов.
Это особенность Windows или что???
PM MAIL ICQ   Вверх
Alexeis
Дата 30.7.2007, 17:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


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

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



ivan219, не такие уж и затраты. Объект типа TGPGraphics - этого своего рода DC для GDI+. В GDI его же получают и пересоздают при каждой перерисовке и ничего.


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

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

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


Опытный
**


Профиль
Группа: Участник
Сообщений: 425
Регистрация: 16.1.2005
Где: Киев

Репутация: 5
Всего: 16



Объект TGPGraphics.Create/Free — это по сути обертки над двумя противоположными функциями. Так что ничего ресурсоемкого в этом нет.

Сейчас нет под рукой GDI+, но принцип там таков: передавая в определенную функцию DC окна мы получаем дескриптор GDI+, на котором можно рисовать. То есть процесс абсолютно аналогичный получению DC.

Может быть более правильным было бы в объекте сделать возможность изменять Handle для рисования не пересоздавая объект (как Canvas.Handle). Ведь все-таки при создании объекта выделяется память, и хорошо если при каждом новом создании объекта используется выделенная перед этим область памяти. Но текущая реализация GDI+ от progdigy этого не предусматривает.
PM MAIL WWW   Вверх
ivan219
  Дата 30.7.2007, 18:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1121
Регистрация: 19.11.2005
Где: Планета земля

Репутация: 4
Всего: 12



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

Запрещено:

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

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

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

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


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

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


 




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


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

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