【发布时间】:2015-04-21 20:06:43
【问题描述】:
我所说的绘图层是指用户可以手动绘制线条、圆形或其他形状的层。普通层是指 graphics32 层示例中描述的层(可以在运行时使用鼠标事件移动或调整大小的层) 所以我很难结合这两种类型的图层。在我的测试项目中,现在,我假设我只有一个绘图层和多个 PNG 层。 因此,在我的项目中,我在 OnFormCreate 中为 ImgView32 设置了属性,例如:
procedure TForm1.FormCreate(Sender: TObject);
begin
AWidth:= 800;
AHeight:= 600;
FillColor:=clWhite;
with ImgView do
begin
Selection := nil;
RBLayer := nil;
Layers.Clear;
Scale := 1;
Scaled:=true;
Bitmap.SetSize(AWidth, AHeight);
Bitmap.DrawMode := dmTransparent;
Bitmap.Clear(FillColor);
end;
end;
在此之后,单击一个按钮,我添加了一些图层(包含透明的 PNG 图像)。所以是这样的
procedure TForm1.Button1Click(Sender: TObject);
begin
AddPNGLayer(1);
AddPNGLayer(2);
AddDrawingLayer;
AddPNGLayer(3);
end;
(我不会在这里详细说明添加PNG图层以保持问题简短。我只会说它使用与drawingLayer中使用的事件不同的onMouseDown事件(layerMouseDown))并且AddDrawingLayer如下:
procedure TForm1.AddDrawingLayer;
var
P:TPoint;
jumaH, JumaW, W, H: Single;
begin
imwidth := ImgView.Bitmap.Width;
imheight := ImgView.Bitmap.Height;
xofx := (ImgView.ClientWidth - 17 - imwidth) div 2; // substracting the width of the scrollbar
yofy := (ImgView.ClientHeight - 17 - imheight) div 2; // same here with height
bm32 := TBitmap32.Create;
bm32.DrawMode := dmTransparent;
bm32.SetSize(ImgView.Bitmap.Width,ImgView.Bitmap.Height);
bm32.Canvas.Pen.Width := 3;
bm32.Canvas.Pen.Color := clBlack32;//pencolor;
BB := TBitmapLayer.Create(ImgView.Layers);
try
BB.Bitmap.DrawMode := dmTransparent;
BB.Bitmap.SetSize(imwidth,imheight);
BB.Bitmap.Canvas.Pen.Width := 3;
BB.Bitmap.Canvas.Pen.Color := pencolor;
BB.Location := GR32.FloatRect(0, 0, imwidth, imheight);
BB.Scaled := true;
BB.Tag:=3;
//// Selection:=BB; // if I use this then I cant draw because the entire layer is selected and the mouseDown event works as a mover/resizer
// BB.OnMouseDown := DrLayerMouseDown;
// BB.OnMouseUp := DrLayerMouseUp;
// BB.OnMouseMove := DrLayerMouseMove;
// BB.OnPaint := DrLayerOnPaint;
RBLayer:=nil;
EdLayerIndex.Text:=IntToStr(BB.Index);
finally
BB.Free;
end;
FDrawingLine := false;
// swapBuffers32; // needed when mouse events are active
end;
EdLayerIndex 是一个编辑框,我在其中显示创建/选择的图层索引(用于调试)
- 正如您在上面看到的,如果我保留
Selection:=BB和RBLayer:=nil,那么drawingLayer 只能移动和调整大小,所以这不是一个好的解决方案,因为我想在这个特定层中使用我的鼠标事件来绘制。 如果我只评论
RBLayer:=nil而保留Selection:=BB,则drawingLayer 不再可移动,但我无法选择drawingLayer 下 的其他图层。我只能访问顶层(最后添加的PNG层)如果我对
Selection:=BB发表评论,那么我无法用鼠标选择其他图层。所以在我的例子中,我在drawingLayer之前声明了2个png图层,在它之后声明了一个。在运行时,我只能选择最后一层(绘图层“上方”的那个) 所以这也不是解决方案。
当我单击绘图层(或以其他方式选择它,例如在列表框或其他东西中)时,我该如何做到这一点,drawingLayer 将无法移动,但我的绘图鼠标事件会启动?而所有这一切,我可以随时离开drawingLayer并选择其他层来移动和玩。 所以基本上我需要一个特定的层不要像其他层一样。
我想要实现的是使用 graphics32 获得类似 Photoshop 或 paint.net 的经典行为。这些图层属性的实际工作方式非常令人困惑。
到目前为止,我已经弄清楚了如何在透明层上动态绘制(线、圆、矩形)(使用鼠标事件)。所以我可以有一个绘图层。绘图发生在我的DrLayerMouseDown、DrLayerMouseUp、DrLayerMouseMove、DrLayerPaint 事件中。但我似乎无法理解如何将这样的绘图层与常规的可移动/可调整大小的层结合起来。
其余代码(如setSelection、RBResizing 和layerMouseDown)大部分取自 graphics32 库的图层示例。
编辑
为了用layerOptions 测试你的想法,我做了以下操作:
1.开始一个新的测试项目,上面有一个 ImgView 和一个按钮
2.在创建时我使用与以前相同的代码
3.OnButtonClick 我使用修改后的 AddDrawingLayer 添加了一个图层,如下所示:
...
BB.Scaled := true;
Selection:=BB;
Selection.LayerOptions:=Selection.LayerOptions and (not LOB_MOUSE_EVENTS); // I also tried it with BB instead of Selection
BB.OnMouseDown := DrLayerMouseDown;
BB.OnMouseUp := DrLayerMouseUp;
BB.OnMouseMove := DrLayerMouseMove;
BB.OnPaint := DrLayerOnPaint;
...
希望它对鼠标事件不敏感。但是该层仍然是可移动的,而不是对鼠标不敏感。所以就像我什么都没做一样
因此,除非我做错了,否则我认为使用此选项对我没有帮助 所以onCreate的层,这个选项好像不粘。但是如果我禁用所有图层的鼠标事件,就像在下一个编辑中一样,那么绘图层就会被禁用(鼠标事件)
编辑
我还尝试了另一个测试项目,同样的想法:相同的 onCreate 和 onButtonClick 我添加了 3 个图层(使用库的图层示例),每个图层都包含一个图像(这次没有绘图层,以保持简单)。然后我添加了一个新按钮,如果单击它,将执行下一个代码:
for i := 0 to ImgView.Layers.Count-1 do
(ImgView.Layers.Items[i] as TPositionedLayer).LayerOptions:= (ImgView.Layers.Items[i] as TPositionedLayer).LayerOptions and (not LOB_MOUSE_EVENTS);
我的目的是让所有图层对鼠标事件不敏感。我成功了,单击新按钮后,无法再选择图层,但是当我想为图层重新启用鼠标事件时(使用下一个代码添加第三个按钮 onClick):
for i := 0 to ImgView.Layers.Count-1 do
(ImgView.Layers.Items[i] as TPositionedLayer).LayerOptions:= (ImgView.Layers.Items[i] as TPositionedLayer).LayerOptions and (LOB_MOUSE_EVENTS);
没有显示错误,但是当我尝试选择一个图层以移动它时……所有图层的图像都从视图中消失了……给我留下了一个空白的 ImgView 背景。
我做错了什么? 为了执行您对 LayerOptions 的建议,我需要能够禁用所有图层的鼠标事件,并为特定图层启用鼠标事件,然后在完成编辑后,我需要能够重新启用鼠标事件对于所有层,但我猜我做错了。
【问题讨论】:
-
看来我在错误的地方发表了评论,在我的回答下,对不起。无论如何,作为对您关于再次启用鼠标事件的编辑的回应。要启用使用 OR 运算符,例如在 LayerOptions := LayerOptions 或 LOB_MOUSE_EVENTS 中。图像消失是因为使用 AND 运算符时您清除了 LOB_VISIBLE 位。您应该阅读有关逻辑运算符和位域的内容。
-
好消息:Graphics32 已于上个月(04.2017)更新
标签: delphi delphi-xe graphics32