Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2012.03.04;
Скачать: CL | DM;

Вниз

TPaintBox & TImage   Найти похожие ветки 

 
Елена   (2011-11-22 00:33) [0]

Добрый вечер мастера. Пожалуйста помогите в таком вот вопросе - нужно нарисовать на форме пиксельную сетку, наподобие формы Delphi на этапе проэктирования.

Сделать можно так:

procedure TForm1.PaintBox1Paint(Sender: TObject);
var
 i,j: Integer;
 Step: Integer;
begin
 Step := 10;
 for i := 0 to 10000 div Step do
   for j := 0 to 7000 div Step do
   PaintBox1.Canvas.Pixels[i*Step,j*Step] := clBlack;
end;

Но это будет требовать постоянной перерисовки, в результате чего будет подтормаживать, а размеры 10000Х7000 должны быть именно такими (может даже больше).

Если нарисовать подобным образом на TImage, то на размере его более 2000px вылазит белый фон, с которым ничего не поделаеш.
Как быть?


 
Германн ©   (2011-11-22 00:48) [1]


> а размеры 10000Х7000 должны быть именно такими

А почему должны?


 
KilkennyCat ©   (2011-11-22 00:50) [2]


>  размеры 10000Х7000

у тебя такой монитор? офигеть....

может, стоит рисовать только то, что будет видно?


 
KilkennyCat ©   (2011-11-22 00:52) [3]


> Но это будет требовать постоянной перерисовки,

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


 
KilkennyCat ©   (2011-11-22 00:53) [4]

да, ну и в конечном итоге BitBlt на че хочешь, паинтбокс, имадж, хоть сразу на форму.


 
Елена   (2011-11-22 01:44) [5]


> KilkennyCat ©   (22.11.11 00:50) [2]

TImage или TPaintBox находится в ScrollBox, чтобы прокручивать этот размер, а монитор самый обычный.


> может, стоит рисовать только то, что будет видно?
> то нарисуй ее один раз, на битмаре, и не удаляй его.
> а потом просто берешь новый битмап, делаешь на него BitBlt()
> битмапа фона и рисуешь остальное.

Это как?


 
KilkennyCat ©   (2011-11-22 02:12) [6]


>
> Это как?


еще раз:

при запуске программы:
создаем битмап fonBMP, квадрат, равен какому-нить разумному размеру, например, четверть от монитора.;
Об этом можно прочитать в справке про TBitMap, TScreen

рисуем на fonBMP.Canvas сетку.

создаем битмап  mainBMP с размером, равным отображаемому.

работа программы:
при ресайзинге:
изменяем размер mainBMP

при скроллинге или иных причинах перерисовки делаем следующее:
заполняем mainBMP содержимым fonBMP с учетом смещения скроллинга (создаем эффект движения сетки при скроллинге) при помощи функции BitBlt (читаем про нее в MSDN)
если координаты скроллинга  сообщают нам о том, что это будет видно, рисуем на mainBMP то, что собственно хотим.
при помощи BitBlt копируем mainBMP на хоть Form.canvas

по окончании программы:
убиваем mainBMP и fonBMP


 
Омлет ©   (2011-11-22 09:35) [7]

> Елена   (22.11.11 00:33)

1. Pixels в циклах категорически нежелательно использовать, т.к. это медленная операция. Чтобы выводить линии, пользуйтесь методами MoveTo и LineTo.

2. Перерисовывать надо только видимую часть и только требующую перерисовки область.

3. TImage - выкинуть и забыть.


 
Anatoly Podgoretsky ©   (2011-11-22 09:55) [8]


> Но это будет требовать постоянной перерисовки,

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


 
Омлет ©   (2011-11-22 11:00) [9]

> Кстати TImage перерисовывает что нужно, а не все подряд

Это в какой версии Дельфи?


 
Anatoly Podgoretsky ©   (2011-11-22 11:06) [10]

> Омлет  (22.11.2011 11:00:09)  [9]

Это особенность Виндоус


 
han_malign   (2011-11-22 11:21) [11]


> новый битмап, делаешь на него BitBlt() битмапа фона и рисуешь остальное.

- советчик блин...

TCanvas.Brush.Bitmap

Windows GDI
LOGBRUSH

  ....................

Remarks

Although lbColor controls the foreground color of a hatch brush, the SetBkMode and SetBkColor functions control the background color.

Windows 95: Creating brushes from bitmaps or DIBs larger than 8 by 8 pixels is not supported. If a larger bitmap is specified, only a portion of the bitmap is used.

Windows 98/Me, Windows NT/2000/XP: Brushes can be created from bitmaps or DIBs larger than 8 by 8 pixels.


 
han_malign   (2011-11-22 11:25) [12]

З.Ы. Возможно еще пригодится SetBrushOrgEx(Canvas.Handle, ...)...


 
Омлет ©   (2011-11-22 11:39) [13]

> Anatoly Podgoretsky ©   (22.11.11 11:06) [10]
> Это особенность Виндоус


> procedure TImage.Paint;
> begin
>   ...
>     with inherited Canvas do
>       StretchDraw(DestRect, Picture.Graphic);
>   ...
> end;


 
Омлет ©   (2011-11-22 11:47) [14]

> han_malign   (22.11.11 11:21) [11]

И насколько заливка кистью будет быстрее?


 
Anatoly Podgoretsky ©   (2011-11-22 12:33) [15]

> Омлет  (22.11.2011 11:39:13)  [13]

А какой ClipRect в данный момент, ну или хотя бы чему равен DestRect


 
Омлет ©   (2011-11-22 13:01) [16]

> Anatoly Podgoretsky ©   (22.11.11 12:33) [15]

Никакого ClipRect там нет и в помине.

function TImage.DestRect: TRect;
var
 w, h, cw, ch: Integer;
 xyaspect: Double;
begin
 w := Picture.Width;
 h := Picture.Height;
 cw := ClientWidth;
 ch := ClientHeight;
 if Stretch or (Proportional and ((w > cw) or (h > ch))) then
 begin
if Proportional and (w > 0) and (h > 0) then
begin
     xyaspect := w / h;
     if w > h then
     begin
       w := cw;
       h := Trunc(cw / xyaspect);
       if h > ch then  // woops, too big
       begin
         h := ch;
         w := Trunc(ch * xyaspect);
       end;
     end
     else
     begin
       h := ch;
       w := Trunc(ch * xyaspect);
       if w > cw then  // woops, too big
       begin
         w := cw;
         h := Trunc(cw / xyaspect);
       end;
     end;
   end
   else
   begin
     w := cw;
     h := ch;
   end;
 end;

 with Result do
 begin
   Left := 0;
   Top := 0;
   Right := w;
   Bottom := h;
 end;

 if Center then
OffsetRect(Result, (cw - w) div 2, (ch - h) div 2);
end;


 
Anatoly Podgoretsky ©   (2011-11-22 13:26) [17]

> Омлет  (22.11.2011 13:01:16)  [16]

А в Виндоус есть ClipRect
Там весь вывод использует обрезку вывода по границам, обычно cliprect
расчитывается динамически. Ну не перерисовывает Виндоус весь рабочий стол, а
только нужное окно, а то и часть его, как правило.


 
Омлет ©   (2011-11-22 13:39) [18]

> Anatoly Podgoretsky ©   (22.11.11 13:26) [17]

Понятно, что на невидимую часть канвы Виндоус не будет ничего выводить. Но суть в том, что будет перерисовываться вся видимая часть TImage, даже если не надо её всю обновлять.


 
Anatoly Podgoretsky ©   (2011-11-22 13:58) [19]

> Омлет  (22.11.2011 13:39:18)  [18]

А я про что речь то веду, нафиг расчитывать и выводить то что не нужно.


 
Anatoly Podgoretsky ©   (2011-11-22 14:00) [20]

Разве у него это видно на экране?
for i := 0 to 10000 div Step do
  for j := 0 to 7000 div Step do

Что у него канва 10000*7000


 
Anatoly Podgoretsky ©   (2011-11-22 14:00) [21]

У нее


 
Омлет ©   (2011-11-22 14:22) [22]

А я про то, что утверждение, будто "TImage перерисовывает что нужно, а не все подряд" - неверно, т.к. TImage перерисовывает всё подряд.


 
Anatoly Podgoretsky ©   (2011-11-22 14:25) [23]

> Омлет  (22.11.2011 14:22:22)  [22]

Опять игнорируешь ClipRect, не больше его.


 
Елена   (2011-11-22 14:31) [24]


> Anatoly Podgoretsky ©   (22.11.11 14:00) [20]


Все понятно, спасибо. Вот этот код меня полностью устраивает - просто "ездит" картинка от положения скрола и все.


...................................
 private
   Scale: Integer;
   CL_Width: Integer;
   CL_Height: Integer;
   Fon: TImage;
 public
   { Public declarations }
 end;

var
 MainF: TMainF;

implementation

uses About;

{$R *.dfm}

procedure TMainF.FormCreate(Sender: TObject);
var
 i,j: Integer;
begin
 Scale := 15;
 CL_Width := 100000;
 CL_Height := 70000;

 Fon := TImage.Create(ScrollBox);
 Fon.Parent := ScrollBox;
 Fon.SetBounds(0,0,Screen.Width,Screen.Height);
 Fon.Transparent := True;

 for i := 0 to Screen.Width div Scale do
   for j := 0 to Screen.Height div Scale do
   begin
     Fon.Canvas.Pixels[i*Scale,j*Scale] := clRed;
   end;

 ScrollBox.HorzScrollBar.Size := CL_Width;
 ScrollBox.HorzScrollBar.Range := CL_Width;
 ScrollBox.HorzScrollBar.Increment := 15;
 ScrollBox.HorzScrollBar.Position := 0;

 ScrollBox.VertScrollBar.Size := CL_Height;
 ScrollBox.VertScrollBar.Range := CL_Height;
 ScrollBox.VertScrollBar.Increment := 15;
 ScrollBox.VertScrollBar.Position := 0;
end;

procedure TMainF.ScrollBoxCanResize(Sender: TObject; var NewWidth,
 NewHeight: Integer; var Resize: Boolean);
begin
 Fon.Left := ScrollBox.HorzScrollBar.Position-ScrollBox.HorzScrollBar.Position;
 Fon.Top  := ScrollBox.VertScrollBar.Position-ScrollBox.VertScrollBar.Position;
end;


 
Anatoly Podgoretsky ©   (2011-11-22 14:35) [25]

> Елена  (22.11.2011 14:31:24)  [24]

В конце концов тебе именно и решать оптимизировать или оставить все как
естью


 
han_malign   (2011-11-22 14:51) [26]


> И насколько заливка кистью будет быстрее?

- по идее это должно делаться аппаратно...

но мерцать так же будет, поскольку один фиг второй раз заливку делать...
а вот если наследоваться от TCustomControl(TWinControl) и "один раз" менять TWinControl.Brush (со всеми прелестями WM_CTLCOLORxxx и WM_ERASEBKGND), то таки должно стать приятно...


 
Омлет ©   (2011-11-22 15:14) [27]

> Anatoly Podgoretsky ©   (22.11.11 14:25) [23]
> Опять игнорируешь ClipRect, не больше его.


Есть весь компонент TImage (размера R0), есть его видимая на экране область (R1) и область, которой необходима перерисовка в момент WM_PAINT (R2) - ClipBox. Известно, что R0 >= R1 >= R2.
TImage всегда выводит пытается вывести R0, но винда его обрезает до R1 и копирует на экран. А реально надо вывести только R2, который часто меньше R1.


 
KilkennyCat ©   (2011-11-22 17:45) [28]


> han_malign   (22.11.11 11:21) [11]
>
>
> > новый битмап, делаешь на него BitBlt() битмапа фона и
> рисуешь остальное.
>
> - советчик блин...
>
> TCanvas.Brush.Bitmap


ты о чем?


 
han_malign   (2011-11-23 08:56) [29]


> ты о чем?

- я о том, что большинстве случаев DoubleBuffered - только добавляет тормозов...
А для отрисовки фона есть специально заточенный объект GDI - Brush, который начиная с W98 не ограничен ни глубиной цвета, ни размером 8x8...

З.Ы. В блитинге могут использоваться комбинации всех трех растров - источника, кисти и растра назначения...


 
KilkennyCat ©   (2011-11-23 13:14) [30]

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



Страницы: 1 вся ветка

Текущий архив: 2012.03.04;
Скачать: CL | DM;

Наверх




Память: 0.55 MB
Время: 0.008 c
15-1321301277
alexdn
2011-11-15 00:07
2012.03.04
делфи и мак ос


15-1321409838
Sher
2011-11-16 06:17
2012.03.04
DBGrid to StringGrid


2-1322215244
Aleks
2011-11-25 14:00
2012.03.04
Как определить событие OnClik в динамически созданном объекте Bu


15-1321206964
SQLEX
2011-11-13 21:56
2012.03.04
продолжение про java. Осталось чуть-чуть, не подскажите?


2-1321982178
Виталий
2011-11-22 21:16
2012.03.04
Отправление писем из Delphi 7 через Outlook