AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Der Screenshot zeigt den Mauszeiger nicht, wenn er auf den zweiten Monitor verschoben

Der Screenshot zeigt den Mauszeiger nicht, wenn er auf den zweiten Monitor verschoben

Ein Thema von flashcoder · begonnen am 6. Jul 2020 · letzter Beitrag vom 8. Jul 2020
Antwort Antwort
flashcoder

Registriert seit: 10. Nov 2013
83 Beiträge
 
#1

Der Screenshot zeigt den Mauszeiger nicht, wenn er auf den zweiten Monitor verschoben

  Alt 6. Jul 2020, 21:41
Delphi-Version: 5
Der Screenshot zeigt den Mauszeiger nicht, wenn er auf den zweiten Monitor verschoben wird

Ich habe in letzter Zeit viel mit Screenshots (für ein Remotedesktopsystem) gearbeitet und bin gerade auf ein Problem gestoßen, während ich versuche, die Unterstützung für mehrere Monitore zu implementieren. Während das Aufnehmen des Screenshots in Ordnung ist, setzt die Methode, mit der ich den Cursor zeichne, nur 1 Bildschirm voraus. Wenn ich den Zeiger auf einem zusätzlichen Bildschirm positioniere (wenn ich einen Screenshot dieses zusätzlichen Bildschirms mache), wird der Cursor NICHT angezeigt. Ich bewege den Zeiger auf den Hauptbildschirm und es wird angezeigt (natürlich an der falschen Stelle, weil es der falsche Bildschirm ist).

Mein Code ist ganz unten.

Delphi-Quellcode:
program Test;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  Windows,
  vcl.Graphics,
  SysUtils;

function GetCursorInfo2: TCursorInfo;
var
  hWindow: HWND;
  pt: TPoint;
  dwThreadID, dwCurrentThreadID: DWORD;
begin
  Result.hCursor := 0;
  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;

procedure TakeScreenshot(var Bmp: TBitmap; WndHdc: HDC; Width, Height, Left, Top: Integer);
const
  CAPTUREBLT = $40000000;
var
  DesktopCanvas: TCanvas;
  MyCursor: TIcon;
  CursorInfo: TCursorInfo;
  IconInfo: TIconInfo;
  DC: HDC;
begin
  DC := GetDC(WndHdc);
  try
    if (DC = 0) then
      Exit;
    Bmp.Width := Width;
    Bmp.Height := Height;
    DesktopCanvas := TCanvas.Create;
    try
      DesktopCanvas.Handle := DC;
      BitBlt(Bmp.Canvas.Handle, 0, 0, Bmp.Width, Bmp.Height, DesktopCanvas.Handle, Left, Top, SRCCOPY or CAPTUREBLT);
      MyCursor := TIcon.Create;
      try
        CursorInfo := GetCursorInfo2;
        if CursorInfo.hCursor <> 0 then
        begin
          MyCursor.Handle := CursorInfo.hCursor;
          GetIconInfo(CursorInfo.hCursor, IconInfo);
          Bmp.Canvas.Draw(CursorInfo.ptScreenPos.X - IconInfo.xHotspot, CursorInfo.ptScreenPos.Y - IconInfo.yHotspot, MyCursor);
        end;
      finally
        MyCursor.ReleaseHandle;
        MyCursor.Free;
      end;
    finally
      DesktopCanvas.Free;
    end;
  finally
    if (DC <> 0) then
      ReleaseDC(0, DC);
  end;
end;

function EnumDisplayMonitors(dc: HDC; rect: PRect; EnumProc: pointer; lData: Integer): Boolean; stdcall; external user32 name 'EnumDisplayMonitors';

type
  TMonInfo = record
    h: THandle;
    DC: HDC;
    R: TRect;
  end;

var
  MonList: array of TMonInfo;

function MonitorEnumProc(hMonitor: THandle; hdcMonitor: HDC; lprcMonitor: DWORD; dwData: Integer): Boolean; stdcall;
var
  I, Width, Height, Left, Top: Integer;
  Bmp: TBitmap;
begin
  I := High(MonList) + 1;
  SetLength(MonList, I + 1);
  MonList[I].h := hMonitor;
  MonList[I].DC := hdcMonitor;
  MonList[I].R := PRect(lprcMonitor)^;

  Left := PRect(lprcMonitor)^.Left;
  Top := PRect(lprcMonitor)^.Top;
  Width := PRect(lprcMonitor)^.Width;
  Height := PRect(lprcMonitor)^.Height;

  Bmp := TBitmap.Create;
  try
    TakeScreenshot(Bmp, hdcMonitor, Width, Height, Left, Top);
    Bmp.SaveToFile('C:\Screen' + IntToStr(I + 1) + '.bmp');
  finally
    Bmp.Free;
  end;

  Result := True;
end;

procedure Main;
var
  S: string;
  I: Integer;
begin
  Writeln('Number of monitors: ' + IntToStr(High(MonList) + 1) + #13#10);
  Writeln('-----------------');
  for I := 0 to High(MonList) do
    with MonList[I] do
    begin
      S := #13#10 + 'Handle: ' + IntToStr(h) + #13#10 + 'Dc: ' + IntToStr(DC) + #13#10 + 'Size: ' + IntToStr(R.Right) + 'x' + IntToStr(R.Bottom) + #13#10;
      Writeln(S);
      Writeln('-----------------');
    end;
end;

begin
  try
    EnumDisplayMonitors(0, nil, Addr(MonitorEnumProc), 0);
    Main;
    Writeln(#13#10 + 'Connected: ' + IntToStr(GetSystemMetrics(SM_CMONITORS)) + #13#10);
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.
  Mit Zitat antworten Zitat
Benutzerbild von Sinspin
Sinspin

Registriert seit: 15. Sep 2008
Ort: Dubai
687 Beiträge
 
Delphi 10.3 Rio
 
#2

AW: Der Screenshot zeigt den Mauszeiger nicht, wenn er auf den zweiten Monitor versch

  Alt 7. Jul 2020, 14:59
Hallo,

Du fotografierst den Cursor mit? Würde es nicht auch gehen die Fotos ohne den Cursor zu machen und ihn dann selber lokal zu zeichnen? Position und Status kann man ja abfragen.
Stefan
Nur die Besten sterben jung
A constant is a constant until it change.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.145 Beiträge
 
Delphi 12 Athens
 
#3

AW: Der Screenshot zeigt den Mauszeiger nicht, wenn er auf den zweiten Monitor versch

  Alt 7. Jul 2020, 15:04
Nee, und das macht er ja schon (siehe TakeScreenshot),
also er macht ein Foto, schaut wo die Maus rumschwirrt und was für einen Zeiger die hat und malt sie auch auf das Bild drauf.


Man könnte nun mit dem Debugger schauen ob die Position simmt und ob auch ein Bild des Zeigers ausgelesen wurde.
Für Letzteres könnte man testweise auch mal mit einer festen Position den Zeiger auf's Bild malen
und für Ersteres entweder ein Ersatzbild oder z.B. zuerst einen Punkt/Kreis an die Stelle und dann darauf den Zeiger.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PosEx im Delphi viel seltener praktiziert.

Geändert von himitsu ( 7. Jul 2020 um 15:18 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Sinspin
Sinspin

Registriert seit: 15. Sep 2008
Ort: Dubai
687 Beiträge
 
Delphi 10.3 Rio
 
#4

AW: Der Screenshot zeigt den Mauszeiger nicht, wenn er auf den zweiten Monitor versch

  Alt 7. Jul 2020, 17:18
Nee, und das macht er ja schon (siehe TakeScreenshot),
also er macht ein Foto, schaut wo die Maus rumschwirrt und was für einen Zeiger die hat und malt sie auch auf das Bild drauf.
Das passiert wenn man zu faul zum Lesen ist.

Das ist ja richtig Clever den aktuellen Cursor als Bild auszulesen. Ich würde ihn aber erst nach dem übertragen aufs Bild malen, sicher machst Du das hier nur zum Testen.

Ist auf dem zweiten Monitor eine andere DPI Einstellung oder Zoom/Lesehilfe aktiviert?
Wie groß ist die Abweichung von der erwarteten Position?
Stefan
Nur die Besten sterben jung
A constant is a constant until it change.
  Mit Zitat antworten Zitat
flashcoder

Registriert seit: 10. Nov 2013
83 Beiträge
 
#5

AW: Der Screenshot zeigt den Mauszeiger nicht, wenn er auf den zweiten Monitor versch

  Alt 8. Jul 2020, 07:00
Gelöst! Danke an alle.
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:44 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz