Форум: "Media";
Текущий архив: 2002.10.17;
Скачать: [xml.tar.bz2];
ВнизСоздания кликуемых регионов. Найти похожие ветки
← →
:: Joiro [unregistered] :: (2002-06-12 13:23) [0]Привет знатокам.
Медленно делаю свой маленький графический редактор и вот появилась нужда в одной возможности, которую никак не могу найти.
Хотелось бы сделать что-то похожее на свободно дефинируемые прозрачные регионы (они все четирёхугольные), которые расположены на форме и их можно кликнуть и вызвать действие. Можно думать о них как о регионах на картинках в HTML.
Пример - на форме картинка на которой видны кнопки или что-то ещё. Надо дать возможность кликнуть "над" этой картинкой как обычную кнопку (или вернее не совсем обычную а регирующую на все три кнопки мышы).
На данный момент использую простые Shape - Rectangle c прозрачными линиями и фоном, но это кажется не совсем эффективным способом.
Есть идеи?
Заранее спасибо.
← →
MBo (2002-06-12 19:29) [1]WinSDK Help
CreateRectRgn, PtInRect(для обработки мыши) и т.п. смотрел?
← →
ZiX (2002-06-12 20:30) [2]а если не прямоуголтный то CreatePolygonRgn или что то типа..
а ваще там все есть -WinSDK Help
← →
.: Joiro :. (2002-06-12 22:07) [3]Окей... посмотрел в хелпе про CreateRectRgn и создал регион, но вот с PtInRect трудности... может можно попросить небольщой примерчик?
И я так понимаю это оптимальный вариант, но есть другие?
← →
MBo (2002-06-13 07:01) [4]Я несколько неточно сказал - при использовании регионов надо будет PtInRegion, а PtInRect можно использовать и без регионов,
достаточно знать ограничивающий прямоугольник.
пример для регионов
list:tlist;
procedure TForm1.Button1Click(Sender: TObject);
var
hr:hrgn;
i:integer;
x1,y1,x2,y2:integer;
begin
randomize;
for i:=0 to 4 do begin
x1:=random(300)+20;
x2:=x1+random(250)+20;
y1:=random(300)+20;
y2:=y1+random(250)+20;
hr:=createrectrgn(x1,y1,x2,y2);
canvas.brush.color:=random($FFFFFF);
fillrgn(canvas.handle,hr,canvas.brush.handle);
list.add(pointer(hr));
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
list:=tlist.create;
end;
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
hr:hrgn;
r:trect;
i:integer;
begin
for i:=0 to list.count-1 do begin
hr:=hrgn(list[i]);
if PtInRegion(hr,x,y) then
Memo1.Lines.Add(inttostr(x)+":"+inttostr(y)+" лежит в регионе N "+inttostr(i));
end;
end;
procedure TForm1.FormDestroy(Sender: TObject);
var
hr:hrgn;
i:integer;
begin
for i:=0 to list.count-1 do begin
hr:=hrgn(list[i]);
DeleteObject(hr);
end;
list.free;
end;
← →
.: Joiro :. (2002-06-13 10:47) [5]О! Спасибо, с примером сразу легче. Немножко изменил чтобы точно видно что и где создаётся:
procedure TForm1.Button1Click(Sender: TObject);
var
hr:hrgn;
i,x1,y1,x2,y2 : Word;
begin
Randomize;
for i:=0 to 7 do begin
x1 := I*32+4;
x2 := I*32+28;
y1 := 4;
y2 := 28;
hr:=createrectrgn(x1,y1,x2,y2);
canvas.brush.color:= RGB(I*32,I*16,0);
fillrgn(canvas.handle,hr,canvas.brush.handle);
list.add(pointer(hr));
end;
end;
Но теперь появляется ещё один вопрос – как нормально реализовать идентификацию и создание нужных регионов? Я тут думал о считывании координат и кода действия из текст файла или что-то похожее и потом у каждого региона свой код и когда на него кликуют тот проверяется и есть действие. Но опять кажется, что этоможет быть не совсем оптимально, да и самому не до конца ясно, как это сделать.
Моя проблема в том, что я перешёл сразу на Delphi ни разу не работав с Паскалом и получилось так, что научился использовать верхний уровень не зная что под ним. Теперь я медленно учусь правильно программировать, так что если не трудно буду очень благодарен за примеры.
← →
.: Joiro :. (2002-06-13 11:32) [6]И ещё вопрос – вот, пробую засветить один регион когда мышь над ним, но почему-то все они меняют краску. В чём дело?
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,Y: Integer);
var
hr:hrgn;
i:integer;
begin
Canvas.Pen.Mode := pmMerge;
for i:=0 to list.count-1 do begin
hr:=hrgn(list[i]);
if PtInRegion(hr,x,y) then
canvas.brush.color:= RGB(I*4,I*3,0);
fillrgn(canvas.handle,hr,canvas.brush.handle);
end;
end;
← →
MBo (2002-06-13 12:27) [7]if PtInRegion(hr,x,y) then BEGIN
canvas.brush.color:= RGB(I*4,I*3,0);
fillrgn(canvas.handle,hr,canvas.brush.handle);
END
А насчет идентификации - можно сделать объектную обертку над регионами, чтобы не возиться с API каждый раз, да и к внутренним
параметрам регионов через GetRegionData обращаться неудобно.
Или хоть для начала можно, скажем, сделать записи типа
TRgnRec=record
hr:hRgn;
x1:integer;
...
Brush:TBrush или Color
Name:String
и т.п.
end;
← →
:: Joiro [ur] :: (2002-06-13 14:20) [8]Ухх... надо же Begin и End забыть... совсем уже глюки начались (сессия...). :)
Делать записи кажется неплохим вариантом, только их внутри программы заполнять не особенно хочется. Но это надо будет посмотреть отдельно.
Спасибо за помощь.
← →
.: Joiro :. (2002-06-13 18:11) [9]Окей... подумал и решил делать вариант с записями. Хорощо что в примере была переменная String – сразу подумал что так можно прекрасно реализовать помощь на-лету, где если мышь над кликуемым обектом где-то показывается информация.
Больщое спасибо за помощь - сам я бы тут днями сидел и мучался (что, возможно, было бы правильнее для изучения языка, но всё же...).
Но теперь есть ещё вопрос:
Реально регионы будут над картинкой и когда мышь над ними надо высветить регион и когда она удаляется вернуть обратно. Всё что я смог смастерить это или перерисовывать всю фоновую картинку (но тогда мерцание и просто неправильно так делать) или пробовать копировать кусок картинки «под» регионом. Но и с этим были трудности – ясно что не использовать медленные функции копирования из Canvas а c быстрыми мэтодами из WinAPI я так и не смог разобратся.
Чтобы легче понять что и как я засунул код и картинку для фона в Zip файл, который можно найти здесь: www.ltn.lv/~joiro/REGIONS.zip
Может кто-нибудь из знатоков мог бы взглянуть и дать совет как сделать нормальные кнопки?
Если так легче можно и по почте.
← →
int64 (2002-06-13 20:56) [10]Ты должен ввести "глобальную" переменную, которая будет знать номер активного региона. Меняться она будет при MouseMove и когда мышь покидает контрол.
Так вот, при изменении этой переменной должен вызываться обработчик, который знает её предыущее состояние и новое. Туда и вешай прорисовку, подсказки и.т.д.
> медленные функции копирования из Canvas
Функции копирования из Canvas достаточно быстрые, тем более для твоей задачи.
>быстрыми мэтодами из WinAPI
Быстрее где-то на 1-2%.
ЗЫ. То что ты решил использовать для своей задачи канву, а не сотни анимированных контролов - правильно. А вот зачем юзать регионы, когда они всегда прямоугольные - непонятно.
← →
.: Joiro :. (2002-06-13 23:15) [11]Ты должен ввести "глобальную" переменную, которая...
Ага... так... хмм... а как выгдядит обработчик реагирующый на изменения глобальной переменной? У елементов есть onChange, а переменные? (Помните - я псевдо-чайник).
Функции копирования из Canvas достаточно быстрые, тем более для твоей задачи.
Ну, я ещё не делал тесты (для других частей программы делал измеряя процессорные тики - надо будет и здесь это сделать), но повсюду вроде слышно что WinAPI всё же быстрее.
ЗЫ. То что ты решил использовать для своей задачи канву, а не сотни анимированных контролов - правильно. А вот зачем юзать регионы, когда они всегда прямоугольные - непонятно.
Я не знаю посмотрел ли ты пример, но там уже частично видно зачем, если я правильно понимаю вопрос. Я сам больще занимаюсь графикой чем программированием и хочется приятный и достаточно "реагирующий" интерфейсс. Когда мышь заходит на "кнопку" та зажыгается, если кликнуть ещё блестнет. Регионы там всегда стоят и я смогу одним хоткием включить им всем подсветку и посмотреть правильно они расположены или нет. В конце будет пара десятков, возможно даже около сотни кнопок - не хочется мучатся. :)
И ещё тогда вопрос - как правильно копировать из канвы в регион? Что-то у меня не получается.
← →
int64 (2002-06-14 03:30) [12]1. Глобальную я взял в кавычки. Разумеется, это свойство какого-л. объекта или функция, меняющая эту переменную. Главное не то, как ты её будешь хранить, а то, что будет происходить, когда в программе дойдёт очередь её менять.
2. Когда я писал, что методы WinAPI для копирования канвы быстрее на 1-2%, то взял цифры наглаз. Настолько большие, насколько хватило духу. На самом деле всё ещё быстрее. Тормоза можно будет зафиксировать, если для битмапа ты юзаешь свою палитру, HALFTONE"s и с-во Transparent. (см. TBitmap.Draw). А так же постоянно меняешь шрифты, стили и.т.д.
А юзанье TCanvas.CopyRect вообще идентично StretchBlt.
3. Самое главное.
Для твоей задачи регионы нахрен не нужны. Достаточно иметь список прямоугольников. PtInRect куда быстрее, чем PtInRegion. И копировать из канвы в регион вообще не придётся. Ректы нужно будет хранить для прорисовки (имхо, и это лишнее).
Более того, поскольку все ректы у тебя одинаковые по длине и по ширене, и образуют таблицу, то проверять наличие указателя в том или ином ректе перебором в цикле просто глупо. Достаточно получать номер строки:
row:= MouseX div WidthOfRect;
Колонка - анологично.
← →
.: Joiro :. (2002-06-14 10:05) [13]1. Глобальную я взял в кавычки. Разумеется, это...
А, ну тогда ясно...
2. Когда я писал, что методы WinAPI для...
Ну, ничего так особенно там менятся не будет - так что да, тормозов скорее всего не будет.
Более того, поскольку все ректы у тебя одинаковые по длине и по ширене, и образуют таблицу, то проверять наличие указателя в том или ином ректе перебором в цикле просто глупо. Достаточно получать номер строки:
row:= MouseX div WidthOfRect;
Колонка - анологично.
Я и чайник, но не такой чайник - когда есть нужда я точно так и делаю (в старой программе). Но это ведь только пример и если так подумать не совсем похожый на реально применяемый. Реально кнопки разные, распределены по-разному на форме и разного размера.
Если интересно, то дай мейл, я подошлю картинки и кое-что ещё.
← →
SI-riuss (2002-06-16 12:30) [14]Я вообще не понимаю проблемы. Ну установи ты на форму какой нибудь нулевой компонент, например Image без картинки (вообще ее не загружай), и кликай на нее сколько влезет.
← →
.: Joiro :. (2002-06-16 13:43) [15]Можно конечно и так (я использую не Image а Shape) но как-то хочется чистоты. Для стандартного конечного пользователя это конечно не видно да и всё равно, но так как тут конечный пользователь и я сам...
Но похоже что действительно придётся ставить эти самые ненавистные компоненты, прикрепить CM_MOUSEENTER/CM_MOUSELEAVE и всё.
← →
SI-riuss (2002-06-16 18:09) [16]Хорошо. Хочешь "чистоты", тогда в событии OnClick на форме или что у тебя там наверху, пропиши условие if для координат курсора.
← →
.: Joiro :. (2002-06-16 18:39) [17]Посмотри на мой второй трид - http://delphi.mastak.ru/cgi-bin/forum.pl?look=1&id=1024133464&n=7
Я решил использовать Shape c модификациями. Работает неплохо, хотя и в конце будет полно этих штучек на форме, но возможность очень лёгкой (но красивой, ИМХО) перерисовки оправдывает.
Страницы: 1 вся ветка
Форум: "Media";
Текущий архив: 2002.10.17;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.13 c