То ли я чего-то не заметил, то ли поборол... Разумеется, речь идёт о нужной мне функциональности - не всё однозначно состыкуется с представлениями о том, как оно должно быть.
Итак,
так начиналось,
так продолжилось и вот к чему привело.
Для тех, кому лениво снова перечитывать, краткое содержание предыдущих моих мессаг. Как я уже писал, имею несколько визуальных элементов (например, прямоугольников), демонстрирующих некие выбранные цвета. Соответственно, от каждого элемента мне нужна была реакция на onClick (с вызовом диалога выбора цвета) и на Drag-and-Drop (с присваиванием цвета от Source к Sender). В качестве элементов выбрал объекты TShape, размещённые в GroupBox'е. Похожую задачу решал на javascript, где нет штатного механизма Drag-and-Drop, удалось сделать через onmousedown/onmouseup. Пытался применить полученный опыт в программе на Лазарусе (тем более, что у TShape нет onClick и всё равно задействовать придётся onmousedown/onmouseup) - с условным успехом.
Теперь дальше. Для пробы сделал аналогичную программу в Delphi 5 - не сильно иначе от
описанного получилось. Т.е. на onMouseUp реагировал тот объект, на котором был onMouseDown. Вероятно, это следствие реализации Drag-and-Drop, потому как на правую кнопку, как писал vitaly_l, и в Delphi, и в Lazarus реакция более соответствующая предполагаемой.
Ну я и решил воспользоваться штатным D'n'D, тем более, что оно мне тоже надо. Из неочевидного, пожалуй, добавлена только проверка координат в onMouseUp на выход за пределы габаритов Sender'а. Ну и не забыть DragMode у всех шейпов поставить в dmAutomatic. Обработчики onMouseDown, onMouseUp, onDragDrop, onDragOver одинаковые для всех шейпов и имеют такой вид:
Код: Выделить всё
var ObjMouseDown: TObject=nil;
procedure TForm1.ShapeMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
ObjMouseDown:=Sender;
end;
procedure TForm1.ShapeMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if (ObjMouseDown=Sender) and (Sender is TShape)
and (X<TShape(Sender).Width) and (Y<TShape(Sender).Height) and (X>0) and (Y>0) then begin
ColorDialog.Color:=TShape(Sender).Brush.Color;
if ColorDialog.Execute then
TShape(Sender).Brush.Color:=ColorDialog.Color;
end;
ObjMouseDown:=nil;
end;
procedure TForm1.ShapeDragDrop(Sender, Source: TObject; X, Y: Integer);
begin
if (Source is TShape) then // вероятно, лишняя проверка, но пусть будет
TShape(Sender).Brush.Color:=TShape(Source).Brush.Color;
end;
procedure TForm1.ShapeDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
begin
Accept:= (Source is TShape);
end;
Что получил в итоге:
шейпы расположены внутри GroupBox'а, как и предполагалось изначально;
клик (нажатие-отжатие) левой или правой кнопкой мыши по шейпу вызывает ColorDialog для этого шейпа;
нажатие-перемещение-отжатие любой кнопкой при условии совпадения шейпа нажатия и отжатия вызывает ColorDialog для этого шейпа (воспринимается как клик);
перетаскивание левой кнопкой шейпа-A на шейп-B приводит к изменению цвета шейпа-B на цвет шейпа-A;
перетаскивание любой кнопкой шейпа на иной объект, пустую часть формы или за её пределы не вызывает никакой видимой реакции.
В общем, ради этого всё и затевалось. И проявлений ошибок/специфики TGroupBox, о которых говорилось тут на четырёх страницах, теперь не видно.