Определение позиции Memoview под курсором

отредактировано February 2016 Раздел: FastReport 4.0
Поискав по форуму, не нашёл описания того, как определить, какой MemoView находится под курсором мыши.
Пришлось писать свой метод.
К сожалению, определение координат Memo зашито жёстко в исходниках, и наружу эти методы не выходят.
В примере мне нужно было вызвать PopupMenu, только если под ним находится Memo.
Предполагается, что frxPreview1 уже лежит на форме.

Прежде всего, в разделе Type задаём "ломалку" недоступных полей компонента TfrxPreviewWorkspace
type
  THackfrxPreviewWorkspace = class(TfrxPreviewWorkspace)
  private
    FOffset: TPoint;
    FPageList: TfrxPageList;
  end;
...

Далее сама функция:
procedure TForm1.frxPreview1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  Scale: Extended;
  PageNo: Integer;
  PageBounds: TRect;
  FOffset: TPoint;
  p: TPoint;
  VertScrollPosition: Integer;

  // Функция "выдрана" из frxPreviewPages.pas - TfrxPreviewPages.ObjectOver()
  function MouseInView(c: TfrxComponent): Boolean;
  var
    r: TRect;
  begin
    with c do
      r := Rect(Round(AbsLeft * Scale), Round(AbsTop * Scale),
        Round((AbsLeft + Width) * Scale), Round((AbsTop + height) * Scale));
    OffsetRect(r, Round(FOffset.X), Round(FOffset.Y));
    Result := PtInRect(r, Point(X, Y));
  end;

begin
  GetCursorPos(p);
  // popup menu
  if Button = mbRight then
  begin
    Scale := frxPreview1.Workspace.Zoom;
    PageNo := frxPreview1.Workspace.PageNo - 1;
    FOffset := THackfrxPreviewWorkspace(frxPreview1.Workspace).FOffset;

    VertScrollPosition := frxPreview1.Workspace.VertPosition;

    // Почему-то без + 10 работает неверно:
    PageBounds.Left := 10 + Round
      (frxPreview1.PreviewPages.Page[PageNo].LeftMargin * fr01cm * Scale);
    PageBounds.Top := 10 + Round
      (frxPreview1.PreviewPages.Page[PageNo].TopMargin * fr01cm * Scale);

    FOffset.X := PageBounds.Left - FOffset.X;
    FOffset.Y := PageBounds.Top - FOffset.Y - VertScrollPosition;

    if Assigned(Current_Memo) then
      if MouseInView(Current_Memo) then
      begin
        PopupMenu1.Popup(p.X, p.Y);
      end;
  end;
end;

Current_Memo - это компонент TfrxMemoView, относительно которого предполагается проверять положение курсора мыши. У меня этот компонент выделяется цветом и копируется в глобальные переменные формы в методе frxReport1.onMouseOverObject(). Вы можете выбрать другой способ определения этого Memo, можно даже в цикле по всем компонентам frxReport1.

Оставить комментарий

Многофункциональный текстовый редактор. Чтобы отредактировать стиль параграфа, нажмите TAB, чтобы перейти к меню абзаца. Там вы можете выбрать стиль. По умолчанию не выбран ни один стиль. Когда вы выберете текст, появится встроенное меню форматирования. Нажмите TAB, чтобы войти в него. Некоторые элементы, такие как многофункциональные вставки ссылок, картинок, индикаторов загрузки и сообщений об ошибок могут быть вставлены в редактор. Вы можете перемещаться по ним, используя стрелки внутри редактора и удалять с помощью клавиш delete или backspace.