Большой Воронежский Форум
» Программирование>Движущаяся линия в GDI+
-=Женек=- 12:23 09.09.2011
Господа, нужна помощь.
Работаю в Builder XE, использую для рисования графики GDI+.
На TImage нарисована сеточка, а на сеточке толстая линия. Хочу перемещать эту линию нажатием на ее концы. То есть при перемещении линия должная стираться и рисоваться в новом месте.

Как это сделать? Если я буду каждый раз перерисовывать фон, будет мерцание. Может есть какой-то способ рисовать линию создавая ее как объект с параметрами? Наверняка в GDI есть какая-то функция для этого.

Спасибо.
Spectator 12:57 09.09.2011

Сообщение от -=Женек=-:
Господа, нужна помощь.
Работаю в Builder XE, использую для рисования графики GDI+.
На TImage нарисована сеточка, а на сеточке толстая линия. Хочу перемещать эту линию нажатием на ее концы. То есть при перемещении линия должная стираться и рисоваться в новом месте.

Как это сделать? Если я буду каждый раз перерисовывать фон, будет мерцание. Может есть какой-то способ рисовать линию создавая ее как объект с параметрами? Наверняка в GDI есть какая-то функция для этого.

Спасибо.

LockWindowUpdate(хэндл окна);//Запретили реальную отрисовку на экране
быренько всё перерисовываем
LockWindowUpdate(NULL);//Разрешили реальную отрисовку на экране
InvalidateRect(хэндл окна, NULL, FALSE);//Пометили всё окно как требующее перерисовки
UpdateWindow(хэндл окна);//Принудительно перерисовали

Это если через чистый GDI работать.
Hopkroft 12:58 09.09.2011

Сообщение от -=Женек=-:
Господа, нужна помощь.
Работаю в Builder XE, использую для рисования графики GDI+.
На TImage нарисована сеточка, а на сеточке толстая линия. Хочу перемещать эту линию нажатием на ее концы. То есть при перемещении линия должная стираться и рисоваться в новом месте.

Как это сделать? Если я буду каждый раз перерисовывать фон, будет мерцание. Может есть какой-то способ рисовать линию создавая ее как объект с параметрами? Наверняка в GDI есть какая-то функция для этого.

Спасибо.

1. У формы ставишь DoubleBuffered ->true
2. Координаты того чего хочешь нарисовать хранишь в массиве.
3. Я рисовал всё на PaintBox. Вешаешь в обработчике OnPaint. то что хочешь нарисовать. И когда происходит его вызов делаешь следующее.
3.1. Очищаешь холст.
3.2. Рисуешь координатную сетку (или что там у тебя)
3.3 Рисуешь из массива свои линии. (Скорее всего у тебя, координаты и матрица смежности, в случае если они соединены).

Делал по такому принципу. Мерцаний не заметил. Есть ещё метод когда сначала создают массив TBitMap и рисуют там, потом его копируют на холст. Но я делал по 1-ому способу и было всё ок.
-=Женек=- 13:11 09.09.2011
хм... что-то не догоняю.
Вот мой код:

Сообщение от :

void __fastcall TForm1::FormActivate(TObject *Sender)
{
int i,j;

_m_pGraphics = new Gdiplus::Graphics(Form1->Image->Canvas->Handle);
_m_ppen = new Pen(Gdiplus::Color(255,255,180,180));
_m_pbrush= new SolidBrush(Gdiplus::Color(55, 255, 0, 0));
_m_pGraphics->SetSmoothingMode(Gdiplus::SmoothingModeHighQualit y);

_m_ppen->SetLineCap(2, 2, 0);
_m_ppen->SetColor(Gdiplus::Color(255, 190, 190, 190));
_m_ppen->SetWidth(1);

// Рисую сетку
for (i=0; i <= 60; i++) _m_pGraphics->DrawLine(_m_ppen, 0,i*10,700,i*10);
for (j=0; j <= 70; j++) _m_pGraphics->DrawLine(_m_ppen, j*10,0,j*10,600);

/Рисую линию

_m_ppen->SetColor(Gdiplus::Color(255, 50, 50, 50));
_m_ppen->SetWidth(5);

_m_pGraphics->DrawLine(_m_ppen, 0,300,0,0);

//а теперь, допустим, я потянул за верхний конец линии и получил координаты 0,300,200,0
_m_pGraphics->DrawLine(_m_ppen, 0,300,200,0);

// А как перед этим убрать первую линию
}

-=Женек=- 13:14 09.09.2011
Hopkroft,
если не получится то, что написал Spectator, попробую твой метод но с TImage
Hopkroft 13:23 09.09.2011

Сообщение от -=Женек=-:
Hopkroft,
если не получится то, что написал Spectator, попробую твой метод но с TImage

Не получится, т.к. у TImage нет события OnPaint.
-=Женек=- 13:49 09.09.2011
А вместо OnPaint разве нельзя что-то вроде onMouseMove?
-=Женек=- 14:22 09.09.2011
Сделал на OnMouseMove - получилось. Тормозило. Но когда отключил сглаживание при прорисовке сетки - тормозить перестало. Линии то в сетке ортогональные.
Но это же временный вариант. А если у меня на фоне картинка будет - каждый раз ее перерисовывать - это жуть.
Hopkroft 14:24 09.09.2011

Сообщение от -=Женек=-:
А вместо OnPaint разве нельзя что-то вроде onMouseMove?

Я вопроса не понял.

Что касается PaintBox. Он сам перерисовыватся не может для этого ему нужно обрабатывать метод OnPaint.
Тут идеология следующая.
изменил значение->нарисовал.

1. В OnPaint у тебя рисуется то что находится в массиве.
2. На onMouseMove, onMouseDown, onMouseUp изменяешь координаты нужных линий. После этого вызываешь OnPaint.

Таким образом, у тебя и данные изменяются и программа корректно их отображает.

А TImage насколько я понял, может сам "перерисовываться". Вот от этого и нужно отталкиваться. Тем более TImage в основном для хранения и обработки картинок используют. А тебе активно рисовать нужно, так что сам думай

Upd. Я понял что ты хотел сказать. В принципе ты написал то-же что я тебе предложил. Т.е. у меня тоже в OnMouseMove в конце вызывалась перерисовка.
Spectator 14:28 09.09.2011

Сообщение от -=Женек=-:
А вместо OnPaint разве нельзя что-то вроде onMouseMove?

Рисовать в onMouseMove крайне не рекомендуется.
Смотри - отрисовку надо помещать в OnPaint
А в onMouseMove надо писать две строки:

InvalidateRect....
UpdateWindow....
-=Женек=- 14:29 09.09.2011
Хм.. а с картинкой не тормозит.
Шайтан, однако, 150 сглаженных линий рисует в несколько раз дольше, чем грузит картинку из файла..
-=Женек=- 14:33 09.09.2011
Вот что выясняется в ходе экспертиментов:

1. Без Inavalidate не работает. То есть даже TImage нужна принудительная перерисовка.
2. Если на OnMouseMove поставить загрузку картинки в TImage - invalidate не нужен.

Получилось реально работающее вот что:

Сообщение от :
void __fastcall TForm1::ImageMouseMove(TObject *Sender, TShiftState Shift, int X,
int Y)
{
int i,j;
Form1->Image->Picture->LoadFromFile("tire2.bmp");
_m_pGraphics = new Gdiplus::Graphics(Form1->Image->Canvas->Handle);
// _m_pGraphics_Layer1 = new Gdiplus::Graphics(Form1->Image->Canvas->Handle);
//_m_ppen = new Pen(Gdiplus::Color(255,255,180,180));

// _m_pbrush= new SolidBrush(Gdiplus::Color(55, 255, 0, 0));




_m_pGraphics->SetSmoothingMode(Gdiplus::SmoothingModeNone);

_m_ppen->SetLineCap(2, 2, 0);

_m_ppen->SetColor(Gdiplus::Color(255, 190, 190, 190));
_m_ppen->SetWidth(1);

//рисуем сетку
for (i=0; i <= 60; i++) _m_pGraphics->DrawLine(_m_ppen, 0,i*10,700,i*10);
for (j=0; j <= 70; j++) _m_pGraphics->DrawLine(_m_ppen, j*10,0,j*10,600);

//меняем карандаш для рисования движущейся линии
_m_pGraphics->SetSmoothingMode(Gdiplus::SmoothingModeHighQualit y);
_m_ppen->SetColor(Gdiplus::Color(255, 255, 90, 90));
_m_ppen->SetWidth(5);

_m_pGraphics->DrawLine(_m_ppen, 0,600-50,X,Y); // ее родимую и двигаю


}

-=Женек=- 14:34 09.09.2011
Spectator,

Сообщение от :
Смотри - отрисовку надо помещать в OnPaint

Так ведь нет в TImage onPaint.

В общем-то спасибо за советы. А то я уж грешным делом думал для каждой линии свой прозрачный TImage рисовать. Линий всего 4, но в планах еще одна программа другого назначения, но похожей структуры,там линий будет до 200...

Сообщение от :
InvalidateRect....
UpdateWindow....

А нельзя ли применительно к моему коду, поподробнее?
Учитывая, что нет onPaint, непонятно, где надо рисовать.
Spectator 14:40 09.09.2011

Сообщение от -=Женек=-:
Вот что выясняется в ходе экспертиментов:

1. Без Inavalidate не работает. То есть даже TImage нужна принудительная перерисовка.
2. Если на OnMouseMove поставить загрузку картинки в TImage - invalidate не нужен.

в OnMouseMove загрузку картинки вставлять не стоит.

Сообщение от -=Женек=-:
Spectator,
Так ведь нет в TImage onPaint.

Выкинь его нахрен, он не для рисования предназначен, а для загрузки картинок, что вполне понятно из названия. Рисуй прямо на канве формы.
-=Женек=- 15:04 09.09.2011
Spectator,

Сообщение от :
Рисуй прямо на канве формы.

На форме не получится. У меня на ней панелька, в которой нет OnPaint. Так что тогда сделать? PaintBOx налепить? Он загрузку картинок поддерживает?
Shtirliz 15:05 09.09.2011
-=Женек=-, у тебя же был уже несколько постов назад рабочий вариант, чем он не устроил?
-=Женек=- 15:13 09.09.2011
Shtirliz,
ну так мне пишут, что нерациональный у меня вариант.
Spectator 15:15 09.09.2011

Сообщение от -=Женек=-:
Spectator,

На форме не получится. У меня на ней панелька, в которой нет OnPaint. Так что тогда сделать? PaintBOx налепить? Он загрузку картинок поддерживает?

Значит и панельку выкидывай, отрисуещь ее сам. Иначе тебе надо будет создать вручную (через CreateWindow) окно, предварительно создав класс окна, в котором прописать обработчик WM_PAINT, и это окно создать как дочернее к панели.
Изврат еще тот.
Shtirliz 15:19 09.09.2011

Сообщение от -=Женек=-:
ну так мне пишут, что нерациональный у меня вариант.

На заборе тоже пишут, а там дрова. Если качество работы тебя устраивает, то оставляй, как есть. Там проблемы могут быть в основном только с масштабированием, насколько я помню. Я бы использовал TPaintBox или как он там.
Shtirliz 15:30 09.09.2011

Сообщение от -=Женек=-:
Он загрузку картинок поддерживает?

PaintBox - это обычный Cancas
Картинку грузить как обычно, через TBitMap загрузить используя LoadFromFile картинку, потом установить размеры для PaintBox, а потом PaintBox.Canvas.Draw для экземпляра TBitMap.
Извини, точнее по методам не скажу, потому что Borland жлобит выкладывать справку по компонентам своим в свободный доступ.
Spectator 01:23 10.09.2011

Сообщение от -=Женек=-:
Хм.. а с картинкой не тормозит.
Шайтан, однако, 150 сглаженных линий рисует в несколько раз дольше, чем грузит картинку из файла..

ты куски кода приводи. с параметрами и всяким таким. не стесняйся.
разберемся с твоими 150-ю сглаженными линиями как-нибудь.
Hopkroft 03:20 10.09.2011

Сообщение от Spectator:
ты куски кода приводи. с параметрами и всяким таким. не стесняйся.
разберемся с твоими 150-ю сглаженными линиями как-нибудь.

только давай без ассемблера!
I try to be polite
Spectator 01:53 13.09.2011
закрыто, в дальнейшем с такими вопросами - в болталку.
Вверх