Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2012.03.04;
Скачать: [xml.tar.bz2];

Вниз

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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.53 MB
Время: 0.004 c
15-1321012496
alexdn
2011-11-11 15:54
2012.03.04
Radikal.ru


2-1322306478
3asys
2011-11-26 15:21
2012.03.04
запись в Subitem TListView


2-1322269435
Vyacheslav
2011-11-26 05:03
2012.03.04
Получить результат выполнения команды консоли?


2-1322338716
Крестовый туз
2011-11-27 00:18
2012.03.04
Билдер на Delphi


2-1322346386
я
2011-11-27 02:26
2012.03.04
Описание признаков символа





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский