Delphi-PRAXiS
Seite 2 von 2     12   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Bildschirmfoto knipst nicht alles (https://www.delphipraxis.net/196531-bildschirmfoto-knipst-nicht-alles.html)

KodeZwerg 30. Mai 2018 11:43

AW: Bildschirmfoto knipst nicht alles
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von Mavarik (Beitrag 1403426)
Delphi-Quellcode:
BitBlt(Bmp.Canvas.Handle, 0, 0, Width, Height, DC, 0, 0, SRCCOPY or CAPTUREBLT);

Das bewirkt leider keinen Unterschied, Layered knipsen = schwarzes Bild, Danke trotzdem Mavarik!
Ich habe gerade neu gestartet und wenn fertig gebe ich bescheid oder pump es in Mitglieder Projekte.
So in etwa wird die GUI aussehen Anhang 49173

KodeZwerg 30. Mai 2018 22:19

AW: Bildschirmfoto knipst nicht alles
 
@Emil, nun hab ich mal Dein Text für Delphi angepasst, funktioniert für ganzes Display mit egal was für Content. Danke:thumb:
Jetzt taste ich mich an Deine zweite Variante ran.
Delphi-Quellcode:
Function CaptureScreen(var hbmp: HBITMAP): Boolean;
var
  hDCScreen, hDCMem : HDC;
  cx, cy: Integer;
  hBmpOld: HBITMAP;
  dwRop: DWORD;
begin
  hDCScreen := CreateDC('DISPLAY', 0, 0, 0);
  cx := GetDeviceCaps(hDCScreen, HORZRES);
  cy := GetDeviceCaps(hDCScreen, VERTRES);
  hDCMem := CreateCompatibleDC(hDCScreen);
  hbmp := CreateCompatibleBitmap(hDCScreen, cx, cy);
  hBmpOld := SelectObject(hDCMem, hbmp);
  dwRop := SRCCOPY or CAPTUREBLT;
  Result := BitBlt(hDCMem, 0, 0, cx, cy, hDCScreen, 0, 0, dwRop);
  SelectObject(hDCMem, hBmpOld);
  DeleteDC(hDCMem);
  DeleteDC(hDCScreen);
end;

EWeiss 31. Mai 2018 07:41

AW: Bildschirmfoto knipst nicht alles
 
Sieht doch gut aus.. :thumb:
Warum hast du aber kein ReleaseDC genommen?

gruss

KodeZwerg 31. Mai 2018 08:29

AW: Bildschirmfoto knipst nicht alles
 
Guten Morgen Emil!
Die einfachste Antwort und zugleich auch die erschreckenste: ich wusste es nicht besser.
So sieht das Beispiel aus was Du hier rein gestellt hast.
Delphi-Quellcode:
BOOL CaptureScreen(HBITMAP& hBitmap)
{
    HDC hDCScreen = ::CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
    const int cx = ::GetDeviceCaps(hDCScreen, HORZRES);
    const int cy = ::GetDeviceCaps(hDCScreen, VERTRES);
    HDC hDCMem = ::CreateCompatibleDC(hDCScreen);
    hBitmap = ::CreateCompatibleBitmap(hDCScreen, cx, cy);
    HBITMAP hBmpOld = (HBITMAP)::SelectObject(hDCMem, hBitmap);

    // Note: CAPTUREBLT flag is required to capture layered windows
    DWORD dwRop = SRCCOPY | CAPTUREBLT;
    BOOL bRet = ::BitBlt(hDCMem, 0, 0, cx, cy, hDCScreen, 0, 0, dwRop);

    ::SelectObject(hDCMem, hBmpOld);
    ::DeleteDC(hDCMem);
    ::DeleteDC(hDCScreen);

    return bRet;
}
Um ehrlich zu sein war ich schon happy das ich es so umsetzen konnte, mit Deiner zweiten "So-Wirds-Gemacht" Variante komme ich noch nicht wirklich voran aber alles wird gut :-)
Zitat:

1. GetDesktopWindow
2. GetDC\CreateDC
3. GetWindowRect
4. StretchBlt via BitBlt.
5. ReleaseDC

EWeiss 31. Mai 2018 08:51

AW: Bildschirmfoto knipst nicht alles
 
Zitat:

Die einfachste Antwort und zugleich auch die erschreckenste: ich wusste es nicht besser.
Schade :cry:

Denn dein Beispiel war richtig wollte nur prüfen ob du den Unterschied zwischen GetDC, CreateDC, CreateCompatibleDC kennst.
Und ob du weist warum DeleteDC und nicht ReleaseDC in dieser Funktion verwendet werden muss.

Bitte versuche dich da nochmal zu informieren.
Denn es nicht zu wissen kann besonders hier bei der Freigabe\nicht Freigabe von DC's zu extremen Speicherlecks führen.

OK.. Ich mache es dir etwas einfacher.
Ein DC das man sich einholt also über Get! muss man freigeben und das freigeben geschieht über ReleaseDC..
Ein DC das man selber erstellt muss man löschen das macht man mit DeleteDC.

löschen und freigeben sind zwei unterschiedliche Dinge und die darf man nicht verwechseln.
Wie gesagt andernfalls könnte es sein das wenn du 5 Bilder in den Speicher geladen hast deine Anwendung plötzlich 200MB Speicher verwendet
dieser wird dann nicht freigegeben und du produzierst am laufenden Band Speicherlecks in Massen.

gruss

EWeiss 31. Mai 2018 09:03

AW: Bildschirmfoto knipst nicht alles
 
Zitat:

mit Deiner zweiten "So-Wirds-Gemacht" Variante komme ich noch nicht wirklich voran
Es ist eigentlich ganz einfach.

GetDesktopWindow.. gibt dir das Handle des Desktop zurück.
Dieses Handle verwendest du nun um über GetDC das DC des Desktop zu bekommen.
Dann ermittelst du über GetWindowRect die Ausmaße des Desktop (alternativ mit GetSystemMetrics)
Wenn du mehrere Monitore verwendest dann bitte mit "GetDeviceCaps". Aber Achtung dann keines falls GetDC verwenden sondern "CreateDC"
Abhängig davon wie du das Bild anzeigen willst in einem Panel das kleiner ist als das Bild was du aufnimmst (ohne Scrollbar)
musst du die Blitter Methode wählen in diesen Fall also StretchBlt damit wird das Komplette Bild in das Panel passend eingefügt.
Wenn du ein Panel mit Scrollbar erstellst kannst du BitBlt verwenden da du dann das Bild Scrollen kannst.
Anschließend ReleaseDC um das DC welches du dir über GetDC geholt hast wieder freizugeben.

Aber auch hier wieder aufpassen wenn du das DC über CreateDC erstellst DeleteDC verwenden.

gruss

KodeZwerg 31. Mai 2018 13:40

AW: Bildschirmfoto knipst nicht alles
 
Ich bin heute etwas im Stress, tausend Dank für Deine liebe Erläuterung, abends werde ich mich damit mehr beschäftigen.
Für mich ist es erst Tag 2 mit dem ganzen DC Relaese Delete Strecht Bit Blt und all diesen Sachen.
Ich verinnerliche das schon noch, aber bitte habe etwas Rücksicht, Tag 2... (!)
Es ist total cool von Dir das Du Dir die Zeit zum lesen und schreiben nimmst, das hilft mir echt viel voll!

Rein im Kopf habe ich nun auch eine neue Sache die ich versuchen werde umzusetzen, für Dich alten Hasen im Gfx Business ist das ein klacks aber für mich nicht so ganz :-)

Hier meine neue heran gehens weise Theorie: (ohne befehle zu nennen da ich da eh falsch liege ^_^)
Window Handle ermitteln
Window Rectangle ermitteln
Window verschwinden lassen
Rectangle Schwarz ausmalen
Window zurück holen
Knipsen
Schwarzes Rectangle löschen
Fertig.

So das ich wirklich nur das Fenster im Schnappschuss habe was ich wollte, Beispiel Dein OTTB mal wieder, wenn Da irgendein anderes Fenster drunter ist, das will ich ja nicht geknippst haben, ich hoffe ich konnte es Laienhaft einigermassen Gut Ausdrücken.

Danke für Input, ich lese Dich später!:thumb:

EWeiss 31. Mai 2018 13:45

AW: Bildschirmfoto knipst nicht alles
 
Kein Problem mach in ruhe.

gruss

KodeZwerg 31. Mai 2018 14:51

AW: Bildschirmfoto knipst nicht alles
 
Ich sitze nun im Bus und habe Deine Erläuterung gelesen und auch Verstanden (!!!)
Heute abend geh ich mit neuem Mut frisch ans Werk, das Release/Delete ist absolut plausibel ohne viel Fachchinesisch Erklärt von Dir:thumb::thumb:, da weiß ich ja nun Bescheid worauf ich achten muss. Auch das Du die Vorgehensweise nochmal beschrieben hast was was macht und wofür und warum und und und, vielen Dank mein Freund!
Ich muss selbst nur noch mir Bewusst werden womit ich arbeiten sollte weil ich irgendwie da auch noch nicht so ganz gecheckt habe wieso einer Methode a) nimmt und anderer Methode b)
TBitmap <-> HBITMAP, das eines direkt eine Graphik ist und das andere ein Handle zu einer Graphik ist mir schon irgendwie klar.... ach da gibt es noch viele Fragezeichen die ich hoffentlich bald lichten kann, Stück für stück wie eine Lawine presche ich mich voran in neue Gefilde.
Oder warum benutzt einer nach knipsen ein image.invalidate und ein anderer image.refresh.. all solche Sachen da muss ich noch viel blättern damit ich die zusammenhänge Verstehe bzw was Überhaupt die Unterschiede sind, für mich ists irgendwie das selbe.

EWeiss 31. Mai 2018 16:04

AW: Bildschirmfoto knipst nicht alles
 
Zitat:

TBitmap <-> HBITMAP
Ich denke das weist du selbst kannst es Moment nur nicht richtig zuordnen.
Delphi-Quellcode:
MyBitmap := TBitmap.Create;
MyBitmap.Canvas.Handle := HBITMAP;
Zitat:

da auch noch nicht so ganz gecheckt habe wieso einer Methode a) nimmt und anderer Methode b)
Solange du nur einen Monitor unterstützen willst wäre die zweite Methode angebracht.
Willst du Multimonitor unterstützen dann die erste.

gruss

Fritzew 31. Mai 2018 16:31

AW: Bildschirmfoto knipst nicht alles
 
Zitat:

Zitat von EWeiss (Beitrag 1403525)
Zitat:

da auch noch nicht so ganz gecheckt habe wieso einer Methode a) nimmt und anderer Methode b)
Solange du nur einen Monitor unterstützen willst wäre die zweite Methode angebracht.
Willst du Multimonitor unterstützen dann die erste.

gruss

Wie kommst Du auf diese Aussage?
Bei Invalidate wird Windows mitgeteilt, dass das Fenster neu gezeichnet werden soll. In dem Fall das Image.

Blick in die Source von refresh:

das ruft Repaint auf
Repaint:

Delphi-Quellcode:
Invalidate
Update;
Im Normalfall ist es so das ein Invalidate ausreichen sollte. Windows kümmert sich dann darum, wann das Zeichnen passieren soll. WM_PAINT wird mit einer geringeren Priorität ausgelöst.

https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx

kommt also immer darauf an was Du erwartest.
Bei Refresh und co ist die Systemlast höher, da immer sofort gezeichnet wird.

Aber mit Multimonitor hat das rein gar nichts zu tun

EWeiss 31. Mai 2018 17:03

AW: Bildschirmfoto knipst nicht alles
 
Zitat:

Bei Invalidate wird Windows mitgeteilt, dass das Fenster neu gezeichnet werden soll. In dem Fall das Image.
Es hat niemand über Invalidate gesprochen.

Sondern darüber welche Funktion er verwenden soll.
Die erste oder die zweite Methode.

Methode A:
Delphi-Quellcode:
Function CaptureScreen(var hbmp: HBITMAP): Boolean;
var
   hDCScreen, hDCMem : HDC;
   cx, cy: Integer;
   hBmpOld: HBITMAP;
   dwRop: DWORD;
begin
   hDCScreen := CreateDC('DISPLAY', 0, 0, 0);
   cx := GetDeviceCaps(hDCScreen, HORZRES);
   cy := GetDeviceCaps(hDCScreen, VERTRES);
   hDCMem := CreateCompatibleDC(hDCScreen);
   hbmp := CreateCompatibleBitmap(hDCScreen, cx, cy);
   hBmpOld := SelectObject(hDCMem, hbmp);
   dwRop := SRCCOPY or CAPTUREBLT;
   Result := BitBlt(hDCMem, 0, 0, cx, cy, hDCScreen, 0, 0, dwRop);
   SelectObject(hDCMem, hBmpOld);
   DeleteDC(hDCMem);
   DeleteDC(hDCScreen);
end;
Methode B:
1. GetDesktopWindow
2. GetDC\CreateDC
3. GetWindowRect
4. StretchBlt via BitBlt.
5. ReleaseDC

Was hat das jetzt mit Invalidate zu tun?

Das!
Zitat:

Oder warum benutzt einer nach knipsen ein image.invalidate und ein anderer image.refresh.. all solche Sachen da muss ich noch viel blättern damit ich die zusammenhänge Verstehe bzw was Überhaupt die Unterschiede sind, für mich ists irgendwie das selbe.
Ist wieder eine andere Frage worauf ich aber nicht geantwortet habe.
Du musst das schon auseinander halten.

gruss

Fritzew 31. Mai 2018 17:10

AW: Bildschirmfoto knipst nicht alles
 
Zitat:

Oder warum benutzt einer nach knipsen ein image.invalidate und ein anderer image.refresh
Da habe ich wohl die lokalen Variablen a und b falsch initialisiert....
Sorry, nix für Ungut, dann kennt er jetzt zumindest den Unterschied zwischen I und R::)

EWeiss 31. Mai 2018 17:11

AW: Bildschirmfoto knipst nicht alles
 
Zitat:

Zitat von Fritzew (Beitrag 1403533)
Zitat:

Oder warum benutzt einer nach knipsen ein image.invalidate und ein anderer image.refresh
Da habe ich wohl die lokalen Variablen a und b falsch initialisiert....
Sorry, nix für Ungut, dann kennt er jetzt zumindest den Unterschied zwischen I und R::)

Dito! Danke.

gruss

KodeZwerg 31. Mai 2018 18:11

AW: Bildschirmfoto knipst nicht alles
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo Ihr Lieben,
um die Frage "wie wirds bei mir momentan Angezeigt" zu beantworten, so: Anhang 49187 mit invalidate zum aktualisieren.
Die Anzeige hat aber nichts mit dem Bild gemeinsam was gespeichert wird, das liegt noch im Rohformat rum so wie ichs ausgelesen habe und kann an mehreren Stellen freigegeben werden.

Alles noch totale Early Alpha Phase.

Vielen Dank für Erklärungen für beide Fragezeichen die ich so hatte, es hat beides gefruchtet :thumb:

Jetzt mach ich erstmal das was Emil sagte, ich besuche erstmal das MSDN und speicher mir alle Infos zu allen Befehlen damit ich von vorne beginnen kann aber diesmal Richtig, den Methode b) Weg.

Danke auch für Vorwarnung mit MultiMonitor, das es da Unterschiede gibt werde wusste ich nicht einmal, gut mitgedacht danke, da werde ich viel zu tun haben, auch Danke für diese Erklärungen und auch das ich ein 32bit Bild erzeugen sollte, darauf wäre ich alleine nie gekommen, ich werde all diese Hinweise aufsaugen inhalieren und langsam verdauen :twisted:

EWeiss 31. Mai 2018 18:16

AW: Bildschirmfoto knipst nicht alles
 
Wird schon :)
Wenn man die einzelnen schritte einmal verewigt hat ist das die Basis welche man für alle Bildmanipulationen verwenden kann.

Zitat:

und auch das ich ein 32bit Bild erzeugen sollte
Ich meinte einen 32BitDC ;) der quasi alle Rohdaten schon enthält um ein Aufgenommenes 32Bit Bild aufzunehmen ohne das Daten verloren gehen.
Also quasi ein MyBitmap.canvas auf 32Bit Bilddaten ausgerichtet.

Aber das später ist jetzt für den Anfang nicht so wichtig.

PS:
Mit der VCL ist das einfach siehe
Delphi-Quellcode:
Image.PixelFormat := pf32bit;
Das war's dann schon.

gruss

KodeZwerg 31. Mai 2018 18:31

AW: Bildschirmfoto knipst nicht alles
 
Genau:thumb:
Am Rande.....
Und was man im Bild nicht sieht, ich habs so gemacht:
App startet und holt sich alle Window Handles die es für mich verarbeiten könnte,
selektiert man einen Eintrag erscheint die Vorschau und Kamera wird aktiviert,
drückt man Kamera wird der Eigentliche Screenshot erstellt und Speichern ermöglicht.

Ist das Ok oder sollte ich da nochmal was überdenken?

Nachtrag
Danke für Nachtrag:stupid:

EWeiss 31. Mai 2018 18:32

AW: Bildschirmfoto knipst nicht alles
 
Zitat:

Zitat von KodeZwerg (Beitrag 1403547)
Genau:thumb:
Am Rande.....
Und was man im Bild nicht sieht, ich habs so gemacht:
App startet und holt sich alle Window Handles die es für mich verarbeiten könnte,
selektiert man einen Eintrag erscheint die Vorschau und Kamera wird aktiviert,
drückt man Kamera wird der Eigentliche Screenshot erstellt und Speichern ermöglicht.

Ist das Ok oder sollte ich da nochmal was überdenken?

Hört sich gut an mache es einfach so.. und gut ist.
Nachher kannst immer noch etwas feilschen.

gruss

KodeZwerg 1. Jun 2018 00:24

AW: Bildschirmfoto knipst nicht alles
 
Zwischenstand:

Ich habe nun wieder probiert es hinzubekommen, komplett von vorne bis zum Ende ohne bei Methode b) abzugucken aber mit den Infos von Post 1 angefangen, so das ich theoretisch weiß was ich da mache. Hier stoße ich wieder auf das Layered Problem aber der Rest macht alles Prima. Ist sozusagen ein BestOf ohne Layered support.
Das ist sozusagen Methode c).... da diese Methode nicht klappt fange ich nun an Methode b) umzusetzen, ich sagte ja, alleine bin ich noch nicht im Stande und ich habe mir wirklich Mühe gegeben MSDN da zu Verstehen und Richtig einzusetzen aber eure Infos zu Layered für Methode b) vorbehalten/reserviert.
OTTB = Geht damit nicht von daher muss ich an dieser Stelle aufgeben mit Methode c)
Delphi-Quellcode:
Function Knipse(const Win: HWND; var tbmp: TBitmap; const FullWindow: Boolean): Boolean;
const
  CAPTUREBLT = $40000000;
var
  hDCScreen: HDC;
  rec: TRect;
begin
  Result := False;
  if Win = 0 then Exit;
  try
    begin
      if FullWindow then
       begin
         hDCScreen := GetWindowDC(Win);
         Windows.GetWindowRect(Win, rec)
       end else
       begin
         hDCScreen := GetDC(Win);
         Windows.GetClientRect(Win, rec);
       end;
      tbmp.PixelFormat:=pf32bit;
      tbmp.Width := Rec.Right - Rec.Left;
      tbmp.Height := Rec.Bottom - Rec.Top;
      tbmp.Canvas.Lock;
      StretchBlt(tbmp.Canvas.Handle, 0, 0,
                 tbmp.Width, tbmp.Height,
                 hDCScreen, 0, 0,
                 tbmp.Width, tbmp.Height,
                 SRCCOPY or CAPTUREBLT);
      tbmp.Canvas.Unlock;
    end;
  finally
    ReleaseDC(0, hDCScreen);
    Result := True;
  end;
end;
Und nicht das ihr denkt ich lese nicht alles, ich arbeite alles halt nur langsamer ab da es Neuland ist,
hier ist meine Interpretation einer WM_PRINT -> ClipBoard -> HBITMAP Variante, irgendwie alles falsch da ich kein Bild erhalte. Also Versucht habe ich es. Das hier steht allerdings nicht zur Debatte, nur zur Illustration wie man es nicht machen sollte:lol:
Delphi-Quellcode:
function MyWM_PRINT(const Win: HWND): HBITMAP;
var
  rect: TRECT;
  hBmp: HBITMAP;
  hOld: HGDIOBJ;
  hDCMem, hDCScreen: HDC;
begin
  hDCMem := CreateCompatibleDC(0);
  GetWindowRect(Win, rect);
  hBmp := 0;
  hDCScreen := GetDC(Win);
  hBmp := CreateCompatibleBitmap(hDCScreen, rect.right - rect.left, rect.bottom - rect.top);
  ReleaseDC(Win, hDCScreen);
  hOld := SelectObject(hDCMem, hBmp);
  SendMessage(Win, WM_PRINT, WPARAM(hDCMem), PRF_CHILDREN or PRF_CLIENT or PRF_ERASEBKGND or PRF_NONCLIENT or PRF_OWNED);
  SelectObject(hDCMem, hOld);
  DeleteObject(hDCMem); // ich glaub das wär falsch oder?
  DeleteDC(hDCMem); // oder doch so? me stupid
  OpenClipboard(Win);
  EmptyClipboard();
  SetClipboardData(CF_BITMAP, hBmp);
  Result := hBmp;
  CloseClipboard();
end;

EWeiss 1. Jun 2018 00:36

AW: Bildschirmfoto knipst nicht alles
 
Delphi-Quellcode:
      tbmp.Canvas.Lock;
       StretchBlt(tbmp.Canvas.Handle, 0, 0,
                  tbmp.Width, tbmp.Height,
                  hDCScreen, 0, 0,
                  tbmp.Width, tbmp.Height,
                  SRCCOPY or CAPTUREBLT);
       tbmp.Canvas.Unlock;
Lock, Unlock ist nicht von nöten.
StretchBlt auf der Basis auch nicht.

StretchBlt ist nur sinnvoll wenn der Source und Destination sich in der weite, Höhe unterscheiden.
So macht ein Stretch keinen sinn bei gleichen ausmaßen.
Du kannst hier also getrost BitBlt verwenden.

Zitat:

DeleteObject(hDCMem); // ich glaub das wär falsch oder?
Definitiv!
Denn ein HDC ist kein Object.
Delphi-Quellcode:
DeleteObject(hBmp);

wäre korrekt wenn du es nicht noch brauchen würdest.

Delphi-Quellcode:
Result := True;

Warum?
Du weist doch gar nicht ob StretchBlt erfolgreich war.
Wenn schon dann so.
Delphi-Quellcode:
Result := StretchBlt(bla, bla,


gruss

KodeZwerg 1. Jun 2018 01:25

AW: Bildschirmfoto knipst nicht alles
 
Zitat:

Zitat von EWeiss (Beitrag 1403586)
Lock, Unlock ist nicht von nöten. StretchBlt auf der Basis auch nicht.

Das ist eigentlich ne Doppelfunktion nur Aufruf hier entfernt deswegen Dir noch Unbekannt.
Hat 2 Modis, erstelle Preview (auf aktuelle Größe was meine App dem Image bietet und halt das ganze 1:1 wie man es hier sieht.
Nur damit ich das auch weiß, entsteht dadurch ein Nachteil bei 0 Änderungen der Größe, wenn ja dann mach ich "FinalBildModus" mit BitBlt. <- Das meine Frage aber nichts desto trotz mach ich BitBlt daraus fürs FinalBild da Vertrau ich dem Experten! Ok das Lock Unlock spare ich auch mir Danke!
Zitat:

Zitat von EWeiss (Beitrag 1403586)
Delphi-Quellcode:
DeleteObject(hBmp);

Ich hab da echt nen Denkfehler aber
Delphi-Quellcode:
DeleteObject(hOld);
muss es lauten dann sollte es theoretisch passen aber das lenkt mich zu sehr ab.
Zitat:

Zitat von EWeiss (Beitrag 1403586)
Du weist doch gar nicht ob StretchBlt erfolgreich war.

Aua, Du hast Da natürlich total Recht und das korrigiere ich bei mir für die Akten..... mist dabei hatte ich mir soviel Mühe gegeben aber so lerne ich ja aus meinen Fehlern, Danke!:oops:

Für die Akten, so isses nu :-)
Delphi-Quellcode:
Function Knipse(const Win: HWND; var tbmp: TBitmap; const FullWindow: Boolean; const NewX, NewY: Integer): Boolean;
//Aufruf:
// Parameter 1 = Window Handle
// Parameter 2 = Ein Bitmap
// Parameter 3 = Mit oder ohne Rahmen (Titelleiste, Caption, SystemKnöpfe, Rand ums Fenster)
// Parameter 4 + 5 = 0 für Final 1:1 Bild, X + Y Pixel Angaben für Preview
// Danke Emil für korrekturen
const
  CAPTUREBLT = $40000000;
var
  hDCScreen: HDC;
  rec: TRect;
begin
  Result := False;
  if Win = 0 then Exit;
  try
    begin
      if FullWindow then
       begin
         hDCScreen := GetWindowDC(Win);
         Windows.GetWindowRect(Win, rec)
       end else
       begin
         hDCScreen := GetDC(Win);
         Windows.GetClientRect(Win, rec);
       end;
      tbmp.PixelFormat:=pf32bit;
      tbmp.Width := Rec.Right - Rec.Left;
      tbmp.Height := Rec.Bottom - Rec.Top;
      if ((NewX<>0)and(NewY<>0)) then
        Result := StretchBlt(tbmp.Canvas.Handle, 0, 0,
                   NewX, NewY,
                   hDCScreen, 0, 0,
                   tbmp.Width, tbmp.Height,
                   SRCCOPY or CAPTUREBLT)
      else
        Result := BitBlt(tbmp.Canvas.Handle, 0, 0,
                         tbmp.Width, tbmp.Height,
                         hDCScreen, 0, 0,
                         SRCCOPY or CAPTUREBLT);
    end;
  finally
    ReleaseDC(0, hDCScreen);
  end;
end;

EWeiss 1. Jun 2018 09:10

AW: Bildschirmfoto knipst nicht alles
 
Zitat:

Das ist eigentlich ne Doppelfunktion nur Aufruf hier entfernt deswegen Dir noch Unbekannt.
Was Lock, Unlock ?

Was soll mir da unbekannt sein?
Ist das selbe wie LockWindowUpdate.. und WM_SETREDRAW.
Und beide sind nicht nötig warum soll ich das Window vor neu zeichnen schützen?
Sehr suspekt das ganze.

Zitat:

X + Y Pixel Angaben für Preview
NewX, NewY hat nichts mit Pixeln zu tun bzw.. ist gleichzusetzen mit x, y wenn schon dann w, h die Parameter repräsentieren die Weite und die Höhe
des Container in dem das Bild gestreckt werden soll.

Ok denke es wurde alles gesagt.
Der Fertigstellung deines Projekts steht nun nichts mehr im Wege. ;)

EDIT:
Warum einmal
Delphi-Quellcode:
hDCScreen := GetWindowDC(Win);

und dann
Delphi-Quellcode:
hDCScreen := GetDC(Win);


Wenn schon dann umgekehrt.

Bei FullScreen GetDC und beim Kopieren von Fenster Inhalten incl. Rahmen und was so dazugehört GetWindowDC.
Der Unterschied ist einfach erklärt.

GetDC gibt dir das DC (device context) eines Client Bereichs zurück bzw. das des gesamten Bildschirms.
GetWindowDC gibt dir das DC (device context) eines Fensters einschließlich der Titelleiste, und Bildlaufleisten zurück.

Noch was du holst dir das DC von "Win" welches das auch immer ist und gibst es frei mit einem "0" Handle?
Delphi-Quellcode:
ReleaseDC(0, hDCScreen);

Wie das?

Ich könnte das verstehe wenn du das verwendest.
GetDC(0) und anschließend ReleaseDC(0, hDCScreen);

Aber nicht wenn du GetDC(Win) verwendest und anschließend ReleaseDC(0, hDCScreen)
Was gibst du hier frei? Gar nichts. Jetzt ReleaseDC(Win, hDCScreen) schon..

gruss

KodeZwerg 1. Jun 2018 13:20

AW: Bildschirmfoto knipst nicht alles
 
Danke nochmals für Deine Tipps!
War alles murks und hab ein neues Konzept für meine Methode.

KodeZwerg 3. Jun 2018 01:42

AW: Bildschirmfoto knipst nicht alles
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hier ein kurzer Zwischenstand in Form eines Bildes, was man da sieht ist ein nicht Rechteckiges Layered Window vom Programm OTTB, mit Schwarz als Hintergrund. (Bei 1:1 wäre es der Dektop-Hintergrund bzw andere Fenster)
Anhang 49204
Es hapert noch an vielen Ecken und Kanten aber wie man sehen kann, ich bin auf dem besten Wege, Eure Hilfe und Geduld (besonders Emil) war Super nett und Lehrreich für mich bei diesem Abenteuer, Danke dafür!

Ps: Von Stretch bin ich komplett weg, das Preview ist nun auch das was gespeichert werden könnte.

Zitat:

Zitat von KodeZwerg (Beitrag 1403632)
War alles murks und hab ein neues Konzept für meine Methode.

Also was ich gebastelt hatte war murks, nicht was Du/Ihr geschrieben habt.

Daniel 3. Jun 2018 07:09

AW: Bildschirmfoto knipst nicht alles
 
Zitat:

Zitat von KodeZwerg (Beitrag 1403632)
Danke nochmals für Deine Tipps!
War alles murks und hab ein neues Konzept für meine Methode.

So und wenn jetzt jemand ein ähnliches Problem hat, sich durch diese 7 Seiten kämpft und am Ende feststellt, es war "alles Murks" - ist das unbefriedigend. Wie hast Du es denn nun gelöst?

KodeZwerg 3. Jun 2018 09:30

AW: Bildschirmfoto knipst nicht alles
 
Zitat:

Zitat von Daniel (Beitrag 1403726)
So und wenn jetzt jemand ein ähnliches Problem hat, sich durch diese 7 Seiten kämpft und am Ende feststellt, es war "alles Murks" - ist das unbefriedigend. Wie hast Du es denn nun gelöst?

Eigentlich habe ich vorgehabt den Source sobald der Richtig läuft zu teilen oder wird jetzt dieser Thread geschlossen?
Für Ungeduldige hier eine Kurzanleitung wie man ein Fenster knipst mit egal was für Content ohne störenden Hintergrund/andere Fenster.
Grundzutaten: 2 Fenster (Forms, Window) - 1. Form = GUI, 2. Form = leere Borderless Form, Vorgehensweise:
Haupt-Knips-Fenster wegmachen = ShowWindow(Application.Handle, SW_HIDE);
GetWindowRect() um Bildschirm Koordinaten von Quelle zu erhalten
die leere Borderless Form mit den Koordinaten füttern, einfärben und Anzeigen (hier war die ganze Zeit mein murks Denkfehler, ich malte ein Rechteck, das war total falsch da der Desktop sobald ich Quelle auf Screen hole ein Invalidate o.ä. ausführt und mein Rechteck weg ist bzw auch Negative Auswirkungen hatte!)
mit "if IsIconic(Win) then ShowWindow(Win, SW_RESTORE) else SetForegroundWindow(Win);" das Quell-Fenster in Vordergrund pumpen (über mein Borderless Window sozusagen)
"DC := GetDc(GetDesktopWindow);" verwenden um Zugang zu allem zu erhalten.
Knipsen wie gehabt = BitBlt(tBmp.Canvas.Handle, 0, 0, Width, Height, Dc, Left, Top, SRCCOPY or CAPTUREBLT);
Aufräumen: ReleaseDc(Win, dc); frmClear.Hide; SetForegroundWindow(Application.Handle);

Das war die Kurzfassung die dennoch alles an Informationen enthält um es selber so hinzubekommen wie es das Bild zeigt.

Wer Fragen hat die beantworte ich gerne. Wer will kann auch mein jetzigen Source bekommen, aber da sind noch viele viele Fehler enthalten, ich muss das Knipsen nochmal ändern, mein Fokus lag darauf das ich OTTB perfekt knipsen kann, das Ziel ist gelungen aber andere Fenster zicken noch rum.

EWeiss 3. Jun 2018 09:41

AW: Bildschirmfoto knipst nicht alles
 
Sorry du verstehst es einfach nicht. ;)
Wieder ein Speicherleck wo wir nun so oft drüber gesprochen haben.

Delphi-Quellcode:
ReleaseDc(Win, dc);

Delphi-Quellcode:
DC := GetDc(GetDesktopWindow);


Ohne den gesamten source zu sehen..

Was hat Win mit GetDesktopWindow zu tun?
Beides ist ein Handle aber du gibst wie bisher das falsche DC frei

Bitte so.. berichtigen.
Erstelle eine Variable hDesktopHandle oder anders benannt.

Delphi-Quellcode:
hDesktopHandle := GetDesktopWindow;
DC := GetDc(hDesktopHandle);
Nun gebe das korrekte DC frei von dem FensterHandle von dem du den Device Context geholt hast.
Delphi-Quellcode:
ReleaseDC(hDesktopHandle, DC);


Das Handle "Win" hat damit absolut nichts zu tun.
Nochmal in aller Deutlichkeit!
Du must das DC freigeben von dem Handle wo du es hergeholt hast nicht irgendeins das dir beliebt.

gruss

KodeZwerg 3. Jun 2018 09:52

AW: Bildschirmfoto knipst nicht alles
 
Nun hat es "klick" gemacht !!!:oops: Ich habs vorher falsch interpretiert bei Umsetzung, DAnke!:thumb::thumb::thumb: Ja, viele viele Fehler sind noch da .....

EWeiss 4. Jun 2018 23:07

AW: Bildschirmfoto knipst nicht alles
 
Nur nochmal zur Berichtigung Fehler im Eifer des Gefechts.
Wir wollen nicht das Handle dem DC zuweisen das ist voll murks ;) (deine Worte) :)
Delphi-Quellcode:
MyBitmap := TBitmap.Create;
MyBitmap.Canvas.Handle := HBITMAP;
So ist es richtig.
Delphi-Quellcode:
MyBitmap := TBitmap.Create;
MyBitmap.Handle := HBITMAP;
gruss


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:59 Uhr.
Seite 2 von 2     12   

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