Практика
Программа "Увеличительное стекло"

:: Меню ::
:: На главную ::
:: FAQ ::
:: Заметки ::
:: Практика ::
:: Win API ::
:: Проекты ::
:: Скачать ::
:: Секреты ::
:: Ссылки ::

:: Сервис ::
:: Написать ::

:: MVP ::

:: RSS ::

Яндекс.Метрика


Давно я хотел разобраться как это делается. Долго искал в интернете, но повсюду находил только один пример, его автор Zarko Gajic (исходник его примера можно скачать в конце статьи). Пример хороший, однако отсутствие разнообразия немного огорчает. Итак, разберемся вместе и посмотрим, что из этого получится.

Небольшая подготовка. Свойство формы BorderStyle установим в bsNone. Свойства ClientWidth и ClientHeight установим равными 200. На форму бросим Image1 со свойством Align равным alClient. Чтобы иметь возможность перемещать форму, напишем маленькую процедуру:

private
{ Private declarations }
procedure WMNCHITTEST(var Msg: TMessage); message WM_NCHITTEST;
{...}

implementation

procedure TZoom.WMNCHITTEST(var Msg: TMessage);
begin
   inherited;
   Msg.Result := HTCAPTION;
end;

Коэффициент увлличения будем изменять как при помоши мышиного скрола, так и по нажатию клавиш '+', '-'.

procedure TZoom.FormMouseWheelUp(Sender: TObject; Shift: TShiftState;
  MousePos: TPoint; var Handled: Boolean);
begin
   // Уменьшаем коофициент увеличения
   if _Zoom > 1 then dec( _Zoom );
end;

procedure TZoom.FormMouseWheelDown(Sender: TObject; Shift: TShiftState;
  MousePos: TPoint; var Handled: Boolean);
begin
   // Увеличиваем коофициент увеличения
   if _Zoom < 10 then inc( _Zoom );
end;

procedure TZoom.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
   // Уменьшаем коофициент увеличения
   if Key = VkKeyScan( '-' ) then
      if _Zoom > 1 then dec( _Zoom );

   // Увеличиваем коофициент увеличения
   if Key = VkKeyScan( '=' ) then
      if _Zoom < 10 then inc( _Zoom );
end;

Теперь разберем основной код программы:

procedure TZoom.DrawMonitor;
var
  X, Y, TempX, TempY: real;
begin
   // Находим размеры области "увеличительного стекла"
   FormMonitor := Rect( 0, 0, Zoom.Width, Zoom.Height );
   // "Область увеличения" вокруг курсора
   S := Rect( Kursor.X - Round( Zoom.Width / 2 / _Zoom ),
              Kursor.Y - Round( Zoom.Height / 2 / _Zoom ),
              Kursor.X + Round( Zoom.Width / 2 / _Zoom ),
              Kursor.Y + Round( Zoom.Height / 2 / _Zoom ) );

{  Альтернативный способ установки "Области увеличения"
   X := Image.Width / ( _Zoom * 2 );
   Y := Image.Height  / ( _Zoom * 2 );
   // Позиционируем "Область увеличения" в точку курсора
   S := Rect( Kursor.x, Kursor.y, Kursor.x, Kursor.y );
   // Растягиваем "Область увеличения" с учетом коэффициента увеличения
   InflateRect( S, Round( X ), Round( Y ) ); }

   X := Image.Width / ( _Zoom * 2 );
   Y := Image.Height  / ( _Zoom * 2 );
   // Позиционируем "Область увеличения" в точку курсора
   S := Rect( Kursor.x, Kursor.y, Kursor.x, Kursor.y );
   // Растягиваем "Область увеличения" с учетом коофициента увеличения
   InflateRect( S, Round( X ), Round( Y ) );
   // Проверка выхода "Области увеличения" за границы экрана
   if S.Left < 0 then OffsetRect( S, -S.Left, 0 );
   if S.Top < 0 then OffsetRect( S, 0, -S.Top );
   if S.Right > Screen.Width then 
      OffsetRect( S, -( S.Right - Screen.Width ), 0 );
   if S.Bottom > Screen.Height then 
      OffsetRect( S, 0, -( S.Bottom - Screen.Height ) );

   C := TCanvas.Create;
   try
      C.Handle := GetDC( GetDesktopWindow );
      Image.Canvas.CopyRect( FormMonitor, C, S );

      // Рисуем крестик в центре линзы и рамку по контуру линзы
      with Image.Canvas do
      begin
         // Рисуем крестик
         TempX := _Zoom * ( Kursor.X - S.Left );
         TempY := _Zoom * ( Kursor.Y - S.Top );
         MoveTo( Round( TempX - ( Image.Width div 8 ) ), Round( TempY ) );
         LineTo( Round( TempX + ( Image.Width div 8 ) ), Round( TempY ) );
         MoveTo( Round( TempX ), Round( TempY - ( Image.Height div 8 ) ) );
         LineTo( Round( TempX ), Round( TempY + ( Image.Height div 8 ) ) );
         // Рисуем рамку
         MoveTo( 0, 0 );
         LineTo( Width-1, 0 );
         LineTo( Width-1, Height-1 );
         LineTo( 0, Height-1 );
         LineTo( 0, 0 );
      end;
   finally
      ReleaseDC( 0, C.Handle );
      C.Free;
   end;
   Application.ProcessMessages;
end;

В примере имеется возможность изменять размеры увеличительного стекла. Это возможно сделать, нажав клавиши Ctrl+r.

.: Пример к данной статье :.
.: Пример от Zarko Gajic :.


При использовании материала - ссылка на сайт обязательна