Создание скриншотера на Delphi

Опубиковано: 01.04.2013 г., автор: , просмотров: 35550

Создание скриншотера (Часть1)

Давайте создадим свой скриншотер. Но не такой простой, как в windows, а с большими возможностями, такими, как например у Ashamtoo Snap.

Давайте начнем с о снимка всей области экрана. Создаем новый проект, кидаем на него кнопку Button и компонент для отображения скриншота Image. Также можно добавить компонент ScrollBox, для прокрутки не помещающейся части изображения. Image перенесите на него. Расположить можете по своему желанию, у меня получилось так

создание программки делающей снимок экрана

Добавляем в код следующую процедуру

procedure ScreenShot(Bild: TBitMap);
 var
   c: TCanvas;
   r: TRect;
 begin
   c := TCanvas.Create;
  // получаем handle рабочего стола
   c.Handle := GetWindowDC(GetDesktopWindow); 
   try
    // запоминаем его размеры
     r := Rect(0, 0, Screen.Width, Screen.Height); 
     Bild.Width := Screen.Width;
     Bild.Height := Screen.Height;
    // и копируем в Bitmap изображение экрана	
     Bild.Canvas.CopyRect(r, c, r);
   finally
     ReleaseDC(0, c.Handle);
     c.Free;
   end;
 end;

И теперь, в событие OnClick кнопки добавляем

procedure TForm1.Button1Click(Sender: TObject);
begin
ScreenShot(Image1.Picture.BitMap);
ScrollBox1.HorzScrollBar.Range:=Image1.Picture.Width;
ScrollBox1.VertScrollBar.Range:=Image1.Picture.Height;
end;

Запускаем и проверяем работу

скриншотер

Как мы видим, все работает, но само приложение также попадает в область снятия скриншота. Чтобы этого не было, приложение можно скрыть на время. Делается это так:

 Form1.Visible := False; // скрываем приложение
 Sleep(750);  // ждем немного, чтобы приложение успело скрыться
// делаем скриншот
ScreenShot(Image1.Picture.BitMap);
ScrollBox1.HorzScrollBar.Range:=Image1.Picture.Width;
ScrollBox1.VertScrollBar.Range:=Image1.Picture.Height;   
//
Form1.Visible := True;  // отображаем приложение

Смотрим-все работает. В следующей части я расскажу, как снять скриншот активного окна.

Создание скриншотера (Часть2)

Следующим шагом будет получение скриншота активного окна. Он не намного отличается от предыдущего. Итак, открываем наш проект и добавляем дополнительную кнопку с названием ‘Активное окно’

Аналогично добавляем процедуру получения скриншота активного окна

procedure ScreenShotActiveWindow(Bild: TBitMap);
var
  c: TCanvas;
  r, t: TRect;
  h: THandle;
begin
  c := TCanvas.Create;
  c.Handle := GetWindowDC(GetDesktopWindow);
  // получаем handle активного окна
  h := GetForeGroundWindow;
  // если есть активное окно, то получаем его координаты-Rect
  if h <> 0 then
    GetWindowRect(h, t);
  try
    r := Rect(0, 0, t.Right - t.Left, t.Bottom - t.Top);
    Bild.Width := t.Right - t.Left;
    Bild.Height := t.Bottom - t.Top;
    Bild.Canvas.CopyRect(r, c, t);
  finally
    ReleaseDC(0, c.Handle);
    c.Free;
  end;
end;


И теперь, в событие OnClick кнопки добавляем

procedure TForm1.Button2Click(Sender: TObject);
begin
  Form1.Visible := False;
  Sleep(750); // прячем форму, при этом активным становится последнее активное окно

  ScreenShotActiveWindow(Image1.Picture.BitMap);
  ScrollBox1.HorzScrollBar.Range := Image1.Picture.Width;
  ScrollBox1.VertScrollBar.Range := Image1.Picture.Height;

  Form1.Visible := true;
end;

Запускаем и проверяем работу

Итак, все работает. Следующая часть будет посвящена снятию произвольной области экрана, аналогу приложению “Ножницы” в Windows7.

Создание скриншотера (Часть3)

Теперь попытаемся получить скриншот произвольной области окна.Добавляем кнопку с названием ‘Произвольная область’.

Добавляем новую форму. Она будет затемнять экран, а так же на ней будет отрисовываться область снимка. Чтобы все это выглядело прилично, меняем её свойства:

  • 1)Убираем у нее границы: BorderStyle устанавливаем в bsNone
  • 2) Меняем курсор на crCross.
  • 3) Устанавливаем свойство AlphaBlend в True, а AlphaBlendValue равным 150. Так форма будет полупрозрачной.
  • 4) Устанавливаем свойство TransparentColor в True, а TransparentColorValue в clGreen. Для чего это нужно? Когда мы будем выделять область экрана, зальем её в зеленный цвет. Т.о. она станет прозрачной.

Так же добавляем несколько переменных в private область формы:

  • isDown:Boolean;

Эта переменная будет флагом, показывающая, нажата ли клавиша мыши или нет.

  • downX, downY: Integer;

В эти переменные будут запоминаться начальные координаты выделенной области.

  • Bild: TBitMap;

А сюда мы будем сохранять само изображение области экрана. Эту переменную нужно добавить в public секцию.

Не забудьте добавить в секцию uses первой и второй формы ссылки на другую форму. Итак, приступим к кодированию. Сначала разберемся со второй формой. При её создании мы должны создать обеъект Bild, а при удалении формы освободить его.

procedure TForm2.FormCreate(Sender: TObject);
begin
    //создаем объект Bild
    Bild:=TBitMap.Create;
end;

procedure TForm2.FormDestroy(Sender: TObject);
begin
    //освобождаем объект Bild
   Bild.Free;
end;

Теперь определяем события при нажатии и отпускании мыши, а также при ведении курсора над формой

procedure TForm2.FormMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
   // устанавливаем флаг нажатия мыши в true
  isDown := true;
  // и запоминаем текущие координаты
  downX := X;
  downY := Y;
end;
procedure TForm2.FormMouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
begin
  // если нажата клавиша мыши, то мы рисуем рамку выделения
  if isDown then
  begin
   // перерисовываем форму
   Self.Repaint;

    // тут мы рисуем  пунктирную рамку красного цвета
    Self.Canvas.Pen.Color := clRed;
    Self.Canvas.Pen.Width := 1;

    Self.Canvas.Pen.Style := psDot;
   // вот здесь мы заливаем область зеленым цветом, благодаря чему она становиться прозрачной
    Self.Canvas.Brush.Color := clGreen;
    Self.Canvas.Rectangle(downX, downY, X, Y);


    // а здесь рисуем  маркеры красного цвета в углах и серединах сторон для красоты
    Self.Canvas.Pen.Style := psSolid;
    Self.Canvas.Brush.Color := clRed;

    Self.Canvas.Rectangle(downX - 6, downY - 6, downX + 6, downY + 6);
    Self.Canvas.Rectangle(X - 6, Y - 6, X + 6, Y + 6);
    Self.Canvas.Rectangle(X - 6, downY - 6, X + 6, downY + 6);
    Self.Canvas.Rectangle(downX - 6, Y - 6, downX + 6, Y + 6);

    Self.Canvas.Rectangle(downX - 6, (downY + Y) div 2 - 6, downX + 6,
      (downY + Y) div 2 + 6);
    Self.Canvas.Rectangle(X - 6, (downY + Y) div 2 - 6, X + 6,
      (downY + Y) div 2 + 6);
    Self.Canvas.Rectangle((downX + X) div 2 - 6, downY - 6,
      (downX + X) div 2 + 6, downY + 6);
    Self.Canvas.Rectangle((downX + X) div 2 - 6, Y - 6, (downX + X) div 2 + 6,
      Y + 6);
  end;
end;
procedure TForm2.FormMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  r: TRect;
begin
  // сбрасываем флаг
  isDown := false;

  // сохраняем координаты области
  r.Left := downX;
  r.Top := downY;
  r.Right := X;
  r.Bottom := Y;
  
  // в переменную Bild выводим область экрана
  Bild := CaptureScreenRect(r);

  // и закрываем форму
  Self.Close;
end;

Функция CaptureScreenRect выводит область экрана, зная координаты этой области:

function CaptureScreenRect(aRect: TRect): TBitMap;
var
  ScreenDC: HDC;
begin
  Result := TBitMap.Create;
  with Result, aRect do
  begin
     // Устанавливаем размеры выводимого изображения равными выделенной области
    Width := Right - Left;
    Height := Bottom - Top;
    
    // Получаем Хендл рабочего окна
    ScreenDC := GetDC(0);
    try
      // и копируем нужную область экрана
      BitBlt(Canvas.Handle, 0, 0, Width, Height, ScreenDC, Left, Top, SRCCOPY);
    finally
      ReleaseDC(0, ScreenDC);
    end;
  end;
end;

Тут мы закончили. Теперь переходим к основной форме, и добавляем в OnClick событие нашей кнопки следующий код:

procedure TForm1.Button3Click(Sender: TObject);
var
  ScreenForm: TForm2;
begin
  // создаем нашу полупрозрачную форму
  ScreenForm := TForm2.Create(nil);
  try
    // и растягиваем её на весь экран
    ScreenForm.Width := Screen.DesktopWidth;
    ScreenForm.Height := Screen.DesktopHeight;
    ScreenForm.Left := 0;
    ScreenForm.Top := 0;

    // дальше прячем основную форму
    self.Hide;

    // показываем полупрозрачную ”заливку”
    ScreenForm.ShowModal;

    // и выводим полученную область экрана
    Image1.Picture.BitMap := ScreenForm.Bild;
    ScrollBox1.HorzScrollBar.Range := Image1.Picture.Width;
    ScrollBox1.VertScrollBar.Range := Image1.Picture.Height;

    self.Show;
  finally
    ScreenForm.Free;
  end;

end

И в заключение давайте получим снимок произволного окна Windows. Аналогично предыдущим частям добавляем новую кнопка с заголовком 'Произвольное окно'И в заключение давайте получим снимок произволного окна Windows. Аналогично предыдущим частям добавляем новую кнопка с заголовком 'Произвольное окно'

Итак, что мы должны сделать. Нам нужно определить какое окно находится под курсором мыши, затем получить его положение, и ,зная положение, можно получить скриншот. Чтобы было видно, какое окно мы будем скриншотить, будем выводить вокруг него рамку. Рамку можно рисовать , а можно создать прозрачную форму с рамкой и выводить ее в нужное положение. Добавляем форму. Убираем у нее рамку: BorderStyle = bsNone, цвет делаем белым clWhite и делаем форму прозрачной: TransparentColor =True, TransparentColorValue= clWhite. На форму кладем таймер и 4 панели. Панели будут играть роль рамки. Располагаем их по краем формы с помощью свойства Align, убираем заголовок, цвет делаем красным , убираем рамку(BevelOuter = bvNone) и устанавливаем значения высоты и ширины равными 2.

У таймера устанавливаем время равным 10 мс, enable отключаем. Также аналогично предыдущему уроку, добавляем переменную Bild: TbitMap в public секцию и создаем/уничтожаем её при создании/уничтожении формы. Не забудьте добавить в секцию uses первой формы ссылку на эту форму. Таймер будет выполнять следующие действия:

procedure TForm3.Timer1Timer(Sender: TObject);
var
  hNewWnd: HWnd;
begin
  // получаем дескриптор окна под курсором
  hNewWnd := WindowFromPoint(Mouse.CursorPos);

  // данная процедура показывает рамку вокруг окна
  Frame2Window(hNewWnd);
end;

procedure TForm3.Frame2Window(Wnd: HWnd);
var
  nRect: TRect;
begin
  // получаем размеры и положение окна
  GetWindowRect(Wnd, nRect);

  // устанавливаем для формы соответствующие размеры
  Self.Left := nRect.Left;
  Self.Top := nRect.Top;
  Self.Width := nRect.Right - nRect.Left;
  Self.Height := nRect.Bottom - nRect.Top;
end;

Теперь на основной форме добавляем в OnClick событие нашей кнопки следующий код:

procedure TForm1.Button4Click(Sender: TObject);
var
  borderForm: TForm3;
begin
  // создаем нашу полупрозрачную форму
  borderForm := TForm3.Create(nil);
  try
    // прячем основную форму
    self.Hide;

    // показываем рамку
    borderForm.ShowModal;

    // после получение битмапа выводим его в Image
    Image1.Picture.BitMap := borderForm.Bild;
    ScrollBox1.HorzScrollBar.Range := Image1.Picture.Width;
    ScrollBox1.VertScrollBar.Range := Image1.Picture.Height;

    self.Show;
  finally
    borderForm.Free;
  end;

end;

Теперь можно запустить и проверить, что у нас получилось. Рамка выводится, но как теперь получить нужную область? Для этого нужно при нажатии, например, любой клавиши, скопировать в Bild область экрана с окном. Вернемся к третьей форме:

procedure TForm3.FormKeyPress(Sender: TObject; var Key: Char);
var
  hNewWnd: HWnd;
  r: TRect;
begin
  // получаем дескриптор окна под курсором
  hNewWnd := WindowFromPoint(Mouse.CursorPos);

  GetWindowRect(hNewWnd, r);
  Bild := CaptureScreenRect(r);
  Self.Close;
end;

Тут, мы с помощью процедуры CaptureScreenRect из предыдущего урока получаем область экрана, и заносим ее в Bild;

И еще один момент. Как я уже писал выше, рамку можно отрисовывать самому. Вот пример процедуры

procedure FrameWindow(Wnd: HWnd);
var
  Brush, SaveBrush: hBrush;
  lBrush: tagLOGBRUSH;
  iRect: TRect;
begin

  // Получаем позицию курсора
  GetCursorPos(Pos);
  // Получаем Handle окна под курсором
  Wnd := WindowFromPoint(Pos);

  // создаем кисть
  lBrush.lbColor := clRed;
  lBrush.lbStyle := BS_SOLID;
  Brush := CreateBrushIndirect(lBrush);
  SaveBrush := SelectObject(GetDC(0), Brush);

  GetWindowRect(Wnd, iRect);
  WndDC := GetDC(Wnd);
  // OffsetRect(Rect, -Rect.Left, -Rect.Top);

   // рисуем рамку
  FrameRect(WndDC, iRect, Brush);

  SelectObject(GetDC(0), SaveBrush);
  DeleteObject(Brush);
end;

Но в этом случае нужно перерисовывать окна, иначе рамки так и останутся.

Теперь все что нам осталось – это сохранить полученное изображение. Добавляем кнопку и компонент SavePictureDialog

Теперь настроем его. Сохранять будем в 4х форматах (bmp,jpg,tiff и png). Для поддержки jpg и png нужно в секцию uses добавить модули jpeg и pngimage. Filter =Bitmaps (*.bmp)|*.bmp|JPEG Image File (*.jpg)|*.jpg|TIFF Images (*.tif)|*.tif|Portable Network Graphics (*.png)|*.png Так как по умолчанию в Image у нас тип BMP, для сохранения в другие форматы его нужно преобразовать. Следующая процедура, в зависимости от формата изображения TgraphicClass, преобазует изображение Agraphic и сохраняет под именем AfileName.

procedure SaveGraphicAs(AGraphic: TGraphic; AGraphicClass: TGraphicClass;
  AFileName: String);
var
  vTargetGraphic: TGraphic;
  vBmp: TBitMap;
begin

  if AGraphic is AGraphicClass then
    AGraphic.SaveToFile(AFileName)
  else
  begin
    vBmp := nil;
    vTargetGraphic := AGraphicClass.Create;
    try
      vBmp := TBitMap.Create;
      vBmp.Assign(AGraphic);
      vTargetGraphic.Assign(vBmp);
      vTargetGraphic.SaveToFile(AFileName);
    finally
      vTargetGraphic.Free;
      vBmp.Free;
    end;
  end;
end;

И осталось определить событие на кнопку сохранения. В зависимости от выбранного фильтра определяется расширение и сохраняется процедурой SaveGraphicAs.

procedure TForm1.Button5Click(Sender: TObject);
var
  FileName: string;
  GrType: TGraphicClass;
begin
  if SavePictureDialog1.Execute then
  begin
    case SavePictureDialog1.FilterIndex of
      1:
        GrType := TBitMap;
      2:
        GrType := TJPEGImage;
      3:
        GrType := TWICImage;
      4:
        GrType := TPngImage;
    end;
    FileName := SavePictureDialog1.FileName;
    SaveGraphicAs(Image1.Picture.Graphic, GrType, FileName);
  end;
end;

Наэтом тема программы делающей фотки экрана закончилась.

Скачать исходник

Источник:http://www.cyberforum.ru/



Похожие материалы

Последние из рубрики

Евгений 28 Oct 2023 в 03:25 #
Привет. Прочему при выделении у меня внутири выделния взе полупрозрачно зеленое. Хотя вроде все на форме поставил к у Вас. Delphi 7 у меня может это важно. Спасибо.
dtest 16 May 2020 в 22:23 #
У кого не работает произвольная область
function CaptureScreenRect(aRect: TRect): TBitMap;
var
ScreenDC: HDC;
begin
Result := TBitMap.Create;
Result.Width := aRect.Right - aRect.Left;
Result.Height := aRect.Bottom - aRect.Top;
ScreenDC := CreateDC(PChar('DISPLAY'), nil, nil, nil);
try
BitBlt(Result.Canvas.Handle, 0, 0, Result.Width, Result.Height, ScreenDC, aRect.Left, aRect.Top, SRCCOPY);
finally
ReleaseDC(0, ScreenDC);
end;
end;
заказать продвижение сайта 28 Mar 2018 в 23:55 #
заказать продвижение сайта по москве логин в скайпе SEO PRO1
Круегер 28 Jul 2017 в 16:37 #
Полная ж**. Зачем впаривать новичкам бред?
Дмитрий 25 Mar 2017 в 22:03 #
Ссылкы тоже запрещены, так что как подробно рассказать незнаю.

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