2015-02-20 2 views
0

Рисуя слой Я имею в виду слой, в котором пользователь может рисовать линии, круги или другие фигуры вручную. И по нормальным слоям я имею в виду слои, описанные в примере с примерами graphics32 (слои, которые можно перемещать или изменять размер во время выполнения с использованием событий мыши) Поэтому у меня возникают трудности с объединением этих двух типов слоев. В моем тестовом проекте на данный момент я предполагаю, что у меня есть только один слой рисования и несколько слоев PNG. Так что в моем проекте я установить свойства для ImgView32 в OnFormCreate как:Delphi Graphics32, объединяющий нормальные слои с рисовыми слоями

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; 

После этого, OnClick кнопки, добавить несколько слоев (содержащие прозрачные изображения в формате PNG). Так что, как это

procedure TForm1.Button1Click(Sender: TObject); 
begin 
    AddPNGLayer(1); 
    AddPNGLayer(2); 
    AddDrawingLayer; 
    AddPNGLayer(3); 
end; 

(я не буду вдаваться в подробности здесь добавление PNG слоев, чтобы держать этот вопрос короткий. Я только скажу, что он использует другой OnMouseDown событие (layerMouseDown), чем используемый в drawingLayer) и 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, где я показываю созданный/индекс выбранного слоя (для отладки)

  • Как вы можете видеть выше, если я держу Selection:=BB и RBLayer:=nil, тогда drawingLayer является только подвижным и изменяемым по размеру, поэтому это нехорошее решение, так как я хочу использовать мои события Mouse в этом конкретном слое для рисования.
  • Если я комментирую только RBLayer:=nil, сохраняя при этом Selection:=BB то drawingLayer не движимое больше, но я не могу выбрать другие слои, которые под drawingLayer. Я могу получить доступ только к верхнему слою (последний добавленный слой PNG)

  • Если я прокомментирую Selection:=BB, тогда я не могу выбрать другие слои с помощью мыши. Поэтому в моем случае я объявил 2 слоя png перед моим drawLayer и один после него. Во время выполнения я могу выбрать только последний слой (тот, что «выше», слой рисования) Так что это тоже не решение.

Как я могу это сделать, что, когда я нажимаю на чертежной слой (или выберите его иначе, как в ListBox или что-то), то drawingLayer обыкновение быть подвижным, но мой рисунок событий мыши будет удар в? И все это, пока я могу уйти от DrawLayer всякий раз, когда захочу, и выбирать другие слои для перемещения и игры. Так что в основном мне нужен определенный слой, чтобы НЕ действовать как другие слои.

То, что я хочу достичь, - это классическое использование Photoshop-like или paint.net, использующее графику32. И это очень запутывает, как эти свойства слоя действительно работают.

До сих пор я выяснял, как рисовать (линии, круги, прямоугольники) на прозрачном слое динамически (используя события мыши). Поэтому у меня может быть слой рисования. Рисунок происходит в моих DrLayerMouseDown, DrLayerMouseUp, DrLayerMouseMove, DrLayerPaint событий. Но я не могу понять, как объединить такой слой рисования с обычными подвижными/изменяемыми размерами слоями.

Остальная часть кода (например, setSelection, RBResizing и layerMouseDown) в основном взята из примера примеров библиотеки graphics32.

EDIT

Для того, чтобы проверить свою идею с layerOptions, я сделал следующее:

1.Started новый тестовый проект с 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; 
... 

Ожидая, что он станет нечувствительным к событиям мыши. Но слой по-прежнему перемещается, а не нечувствителен к мыши. Так что я ничего не делал

Так что я не думаю, что это помогает мне использовать эту опцию, если я не ошибаюсь Так что настроить слой, этот параметр, похоже, не застрял. Но если отключить события мыши для всех слоев, один за другим, как в следующем EDIT, то рисунок слой получает отключается (события мыши)

EDIT

Также я попробовал другой тестовый проект, то же самое idea: same 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

Кажется, я прокомментировал не то место, под моим ответом, извините. Во всяком случае, в ответ на ваши изменения относительно включения событий мыши снова. Чтобы включить использование оператора OR, например, в LayerOptions: = LayerOptions или LOB_MOUSE_EVENTS. Изображения исчезли, потому что при использовании оператора AND вы очистили бит LOB_VISIBLE. Вы должны прочитать о логических операциях и битовых полях. –

+0

Хорошие новости: Graphics32 был обновлен в прошлом месяце (04.2017) – Ampere

ответ

0

Эти элементы влияют на события мыши

  • Layers.MouseEvents (Boolean). Слои - это TLayerCollection TCustomImage32, который управляет слоями. Если MouseEvents является ложным, события мыши не распространяются на слои.

  • Layers.MouseListener (TCustomLayer). Слой, который «захватывает» события мыши между левой кнопкой мыши MouseDown и MouseUp. «Захватывает» в квитах, поскольку он не захватывает мышь, как это понимается в контексте Windows.

  • Layer Option Bits. Каждый слой имеет 32-битное свойство LayerOptions. Интересным битом является LOB_MOUSE_EVENTS (бит 29), который определяет, реагирует ли слой на события мыши. Слой может также указать бит LOB_NO_CAPTURE (бит 27), который предотвращает события мыши, даже если установлен LOB_MOUSE_EVENTS.

  • Layer index. Уровни проверяются (в порядке наименьшего значения) для бита опции LOB_MOUSE_EVENTS. Когда слой найден с этим битом, координаты X и Y проверяются в функции HitTest слоев. Если координаты X и Y находятся в пределах расположения слоев, HitTest успешно завершается. Результат встроенного HitTest может быть переопределен в вашем собственном событии OnHitTest. Наконец, если параметры слоев не содержат бит LOB_NO_CAPTURE, вызывается событие MouseDown.

Основываясь на предыдущий я полагаю, что, когда пользователь входит в режим «изменить», отключить все остальные слои, кроме слоя рисунка, установив их LayerOptions не включает LOB_MOUSE_EVENTS битого

Layer.LayerOptions := Layer.LayerOptions and (not LOB_MOUSE_EVENTS); 

Далее информация о слоях доступна here

Редактировать

К м anage в 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), когда вы прекратите рисование, чтобы включить событие мыши.

+0

, пожалуйста, внесите мой EDITED вопрос – user1137313

+0

Я сказал * отключить * LOB_MOUSE_EVENTS для * всех других слоев *, кроме слоя рисования. Кроме того, вы должны установить 'Selection: = nil;' в случае, если это не так. –

+0

Как ответ на ваше изменение относительно включения событий мыши снова. Чтобы включить использование оператора OR, например, в 'LayerOptions: = LayerOptions или LOB_MOUSE_EVENTS'. Изображения исчезли, потому что при использовании оператора AND вы очистили бит LOB_VISIBLE. Вы должны прочитать о логических операциях и битовых полях. –

Смежные вопросы