【问题标题】:Show mouse cursor in screenshot with delphi使用delphi在屏幕截图中显示鼠标光标
【发布时间】:2014-03-25 03:53:13
【问题描述】:

你好,我正在做一个delphi xe函数,这个函数是截图,一切顺利,但问题是我在拍摄的任何图像上都没有看到鼠标光标。

代码如下:

procedure capturar_pantalla(nombre: string);

// Credits :
// Based on : http://www.delphibasics.info/home/delphibasicssnippets/screencapturewithpurewindowsapi
// Thanks to  www.delphibasics.info and n0v4

var

  uno: integer;
  dos: integer;
  cre: hDC;
  cre2: hDC;
  im: hBitmap;
  archivo: file of byte;
  parriba: TBITMAPFILEHEADER;
  cantidad: pointer;
  data: TBITMAPINFO;

begin


  // Start

  cre := getDC(getDeskTopWindow);
  cre2 := createCompatibleDC(cre);
  uno := getDeviceCaps(cre, HORZRES);
  dos := getDeviceCaps(cre, VERTRES);
  zeromemory(@data, sizeOf(data));


  // Config

  with data.bmiHeader do
  begin
    biSize := sizeOf(TBITMAPINFOHEADER);
    biWidth := uno;
    biheight := dos;
    biplanes := 1;
    biBitCount := 24;

  end;

  with parriba do
  begin
    bfType := ord('B') + (ord('M') shl 8);
    bfSize := sizeOf(TBITMAPFILEHEADER) + sizeOf(TBITMAPINFOHEADER)
      + uno * dos * 3;
    bfOffBits := sizeOf(TBITMAPINFOHEADER);
  end;

  //

  im := createDIBSection(cre2, data, DIB_RGB_COLORS, cantidad, 0, 0);
  selectObject(cre2, im);

  bitblt(cre2, 0, 0, uno, dos, cre, 0, 0, SRCCOPY);

  releaseDC(getDeskTopWindow, cre);

  // Make Photo

  AssignFile(archivo, nombre);
  Rewrite(archivo);

  blockWrite(archivo, parriba, sizeOf(TBITMAPFILEHEADER));
  blockWrite(archivo, data.bmiHeader, sizeOf(TBITMAPINFOHEADER));
  blockWrite(archivo, cantidad^, uno * dos * 3);

end;

当我让鼠标光标出现在屏幕截图中时,有人可以解释一下吗?

【问题讨论】:

  • 例如first hit on Google 表明了这一点。
  • 抱歉不明白如何使用,因为该函数在控制台程序中使用,示例代码显示“form”。当我将它添加到我的函数中时?

标签: delphi


【解决方案1】:

DrawCursor 的另一种变体:

function GetCursorInfo2: TCursorInfo;
var
  hWindow: HWND;
  pt: TPoint;
  dwThreadID, dwCurrentThreadID: DWORD;
begin
  ZeroMemory(@Result, SizeOf(Result));
  if GetCursorPos(pt) then
    begin
      Result.ptScreenPos := pt;
      hWindow := WindowFromPoint(pt);
      if IsWindow(hWindow) then
        begin
          dwThreadID := GetWindowThreadProcessId(hWindow, nil);
          dwCurrentThreadID := GetCurrentThreadId;
          if (dwCurrentThreadID <> dwThreadID) then
            begin
              if AttachThreadInput(dwCurrentThreadID, dwThreadID, True) then
                begin
                  Result.hCursor := GetCursor;
                  AttachThreadInput(dwCurrentThreadID, dwThreadID, False);
                end;
            end
          else
            Result.hCursor := GetCursor;
        end;
    end;
end;

function GetCursorOffset(ACursor: HCURSOR): TPoint;
var
  IconInfo: TIconInfo;
begin
  GetIconInfo(ACursor, IconInfo);
  Result.X := IconInfo.xHotspot;
  Result.Y := IconInfo.yHotspot;
  if IconInfo.hbmMask <> 0 then DeleteObject(IconInfo.hbmMask);
  if IconInfo.hbmColor <> 0 then DeleteObject(IconInfo.hbmColor);
end;

procedure DrawCursor(ADC: HDC);
var
  CursorInfo: TCursorInfo;
  Offset: TPoint;
begin
  CursorInfo := GetCursorInfo2;
  Offset := GetCursorOffset(CursorInfo.hCursor);
  DrawIconEx(ADC, CursorInfo.ptScreenPos.X - Offset.X, CursorInfo.ptScreenPos.Y - Offset.Y, CursorInfo.hCursor, 0, 0, 0, 0, DI_NORMAL);
end;

【讨论】:

    【解决方案2】:

    这是您尝试做的更简洁的实现,以及演示如何使用它的控制台应用程序。 (由于屏幕被捕获的时间,它会抓住“应用程序忙”光标,因为调用是在应用程序仍在加载时进行的。)您可以弄清楚在需要时如何调用它以获得正确的光标。

    鼠标光标捕获归功于 Zarko(Tony 的链接)。不久前我在 SO 上找到的屏幕截图代码(并且有功劳给作者,但它在另一台机器上) - 我明天回到那个系统时会更新这篇文章。

    program Project2;
    
    {$APPTYPE CONSOLE}
    
    uses
      SysUtils, Windows, Graphics;
    
    procedure DrawCursor (ACanvas:TCanvas; Position:TPoint) ;
    var
      HCursor : THandle;
    begin
      HCursor := GetCursor;
      DrawIconEx(ACanvas.Handle, Position.X, Position.Y,
                  HCursor, 32, 32, 0, 0, DI_NORMAL) ;
    end;
    
    function CaptureWindow(const WindowHandle: HWnd): TBitmap;
    var
      DC: HDC;
      wRect: TRect;
      CurPos: TPoint;
    begin
      DC := GetWindowDC(WindowHandle);
      Result := TBitmap.Create;
      try
        GetWindowRect(WindowHandle, wRect);
        Result.Width := wRect.Right - wRect.Left;
        Result.Height := wRect.Bottom - wRect.Top;
        BitBlt(Result.Canvas.Handle, 
               0, 
               0, 
               Result.Width, 
               Result.Height, 
               DC, 
               0, 
               0, 
               SRCCOPY);
        GetCursorPos(CurPos);
        DrawCursor(Result.Canvas, CurPos);
      finally
        ReleaseDC(WindowHandle, DC);
      end;
    end;
    
    // Sample usage starts here
    var
      Bmp: TBitmap;
    
    begin
      Bmp := CaptureWindow(GetDesktopWindow);
      Bmp.SaveToFile('D:\TempFiles\FullScreenCap.bmp');
      Bmp.Free;
      WriteLn('Screen captured.');
      ReadLn;
    end.
    

    【讨论】:

    • 感谢肯的帮助。
    • “我明天回到那个系统时会更新这篇文章。”我当然希望你回到你的系统,因为它看起来自原始发布后 23 分钟以来没有更新。无论如何,这里的另一个答案似乎说明了实际的当前鼠标光标,而不仅仅是一个指针。
    • @JerryDodge:它实际上包含捕获和绘制光标的代码。我只是没有用原始作者的链接更新帖子,因为我没有它(并且忘记再次尝试挖掘它)。该文本与代码本身的功能无关。
    • @Ken 我的意思是它只绘制指针,但如果它是一个尺寸夹点,那么这段代码仍然只绘制指针。下面的另一个答案是绘制当前光标的额外步骤,而不仅仅是箭头。
    猜你喜欢
    • 2010-12-10
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-26
    • 2013-09-18
    相关资源
    最近更新 更多