Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "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
3-55974
antoniz
2002-09-25 16:06
2002.10.17
Как перхватить соощение об ошибке ADO


1-56088
NewI
2002-10-07 04:06
2002.10.17
Как из строки Str : String получить 1-ый, 2-ой и т.д символы


3-55955
Woolen
2002-09-24 16:08
2002.10.17
Кроссплатформенная БД


3-55920
Termex
2002-09-27 10:20
2002.10.17
MS SQL и его uniqueidentifier


1-56227
Zhenek
2002-10-04 07:21
2002.10.17
Помогите разобраться с Delphi!





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский