通过绘制图层,我指的是用户可以手动绘制线条,圆形或其他形状的图层。通过普通图层,我指的是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是一个EditBox,我在其中显示创建/选择的Layer索引(用于调试)
Selection:=BB
和RBLayer:=nil
,那么drawingLayer只能移动并可调整大小,所以这不是一个好的解决方案,因为我想在此特定图层中使用我的鼠标事件画画。 如果我在保留RBLayer:=nil
时仅对Selection:=BB
发表评论,那么drawingLayer不再可移动,但我无法选择在 drawingLayer下的其他图层。我只能访问顶层(最后添加的PNG图层)
如果我评论Selection:=BB
,那么我无法用鼠标选择其他图层。所以在我的情况下,我在drawingLayer之前声明了2个png图层,在它之后声明了一个png图层。在运行时我只能选择最后一层(在drawingLayer上面')
所以这也不是解决方案。
当我点击绘图图层(或者在列表框或其他内容中选择它)时,我怎么能这样做,drawingLayer不会移动,但是我的绘图鼠标事件会启动?所有这一切,我可以随时离开drawingLayer并选择其他图层来移动和玩。 所以基本上我需要一个特定的层来不像其他层一样。
我想要实现的是使用graphics32获得类似经典Photoshop或类似paint.net的行为。这些图层属性实际上如何工作非常令人困惑。
到目前为止,我想出了如何在透明层上动态绘制(线条,圆形,矩形)(使用鼠标事件)。所以我可以有一个绘图层。该绘图发生在我的DrLayerMouseDown
,DrLayerMouseUp
,DrLayerMouseMove
,DrLayerPaint
事件中。但我似乎无法理解如何将这样的绘图层与常规的可移动/可调整大小的图层组合在一起。
其余代码(如setSelection
,RBResizing
和layerMouseDown
)主要来自graphics32库的图层示例。
修改
为了使用layerOptions
测试您的想法,我执行了以下操作:
1.启动一个带有ImgView的新测试项目和一个按钮
2.On create我使用了与之前相同的代码
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的建议,我需要能够为所有图层禁用鼠标事件,并为特定图层启用鼠标事件,然后在编辑完成后,我需要能够重新启用鼠标事件对于所有图层,但我猜错了。
答案 0 :(得分:0)
以下项目影响鼠标事件
Layers.MouseEvents(boolean)。图层是TCustomImage32的TLayerCollection,用于管理图层。如果MouseEvents为False,则鼠标事件不会传播到图层。
Layers.MouseListener(TCustomLayer)。在左按钮MouseDown和MouseUp之间“捕获”鼠标事件的图层。 '捕获'在quoutes中,因为它没有像Windows上下文中所理解的那样捕获鼠标。
图层选项位。每个层都有一个32位的LayerOptions属性。有趣的是LOB_MOUSE_EVENTS(第29位),它指定图层是否对鼠标事件做出反应。层也可以指定LOB_NO_CAPTURE位(位27),即使设置了LOB_MOUSE_EVENTS,也会阻止鼠标事件。
图层索引。对于LOB_MOUSE_EVENTS选项位,检查层(按顺序从最低到最低)。使用此位找到图层时,将在图层HitTest函数中检查X和Y坐标。如果X和Y坐标位于图层位置HitTest成功。内置HitTest的结果可以在您自己的OnHitTest事件中被覆盖。最后,如果layers选项不包含LOB_NO_CAPTURE位,则调用图层MouseDown事件。
基于之前我建议当用户进入“编辑”模式时,通过将其LayerOptions设置为不包含LOB_MOUSE_EVENTS位来禁用除绘图层之外的所有其他图层
Layer.LayerOptions := Layer.LayerOptions and (not LOB_MOUSE_EVENTS);
有关使用图层的更多信息,请访问here
修改强>
管理LOB_MOUSE_EVENTS创建例如以下内容
procedure TForm7.LayerMouseDisEnable(Enable: boolean);
var
i: integer;
Lo: cardinal;
begin
for i := 0 to ImgView.Layers.Count-1 do
begin
Lo := ImgView.Layers.Items[i].LayerOptions;
if Enable then
ImgView.Layers.Items[i].LayerOptions := Lo or LOB_MOUSE_EVENTS
else
ImgView.Layers.Items[i].LayerOptions := Lo and (not LOB_MOUSE_EVENTS);
end;
end;
调用此方法(使用False)可在创建绘图图层之前禁用图层中的鼠标事件。绘图层将启用鼠标事件,因为新创建的图层同时设置了LOB_VISIBLE和LOB_MOUSE_EVENTS。当您停止绘图以启用鼠标事件时,再次调用(使用True)。