Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi MagSetWindowFilterList function not remove specified window of screenshot (https://www.delphipraxis.net/195027-magsetwindowfilterlist-function-not-remove-specified-window-screenshot.html)

flashcoder 27. Jan 2018 03:13

Delphi-Version: 10 Seattle

MagSetWindowFilterList function not remove specified window of screenshot
 
Liste der Anhänge anzeigen (Anzahl: 1)
I had build part of this code below based in this C++ example (source file attached) where the goal is make a screenshot without the main form appear on capture.

Then i have two troubles with this following code:

1 - MagSetWindowFilterList function not remove main form (Form1).

2 - How recovery the content of "MagnifierWindow" to a image format?

My actual code is this:

Magnification.pas
Delphi-Quellcode:
unit Magnification;

{$ALIGN ON}
{$MINENUMSIZE 4}

interface

uses
  Windows;

const
  // Magnifier Class Name
  WC_MAGNIFIERA: AnsiString = 'Magnifier';
  WC_MAGNIFIERW: WideString = 'Magnifier';
  WC_MAGNIFIER = 'Magnifier';

  // Magnifier Window Styles
  MS_SHOWMAGNIFIEDCURSOR = $0001;
  MS_CLIPAROUNDCURSOR = $0002;
  MS_INVERTCOLORS = $0004;

  // Filter Modes
  MW_FILTERMODE_EXCLUDE = 0;
  MW_FILTERMODE_INCLUDE = 1;

type
  tagMAGTRANSFORM = record
    v: array[1..3, 1..3] of Single;
  end;
  MAGTRANSFORM = tagMAGTRANSFORM;
  TMagTransform = tagMAGTRANSFORM;
  PMagTransform = ^TMagTransform;

  tagMAGIMAGEHEADER = record
    width: UINT;
    height: UINT;
    format: TGUID;
    stride: UINT;
    offset: UINT;
    cbSize: UINT;
  end;
  MAGIMAGEHEADER = tagMAGIMAGEHEADER;
  TMagImageHeader = tagMAGIMAGEHEADER;
  PMagImageHeader = ^TMagImageHeader;

  tagMAGCOLOREFFECT = record
    transform: array[1..5, 1..5] of Single;
  end;
  MAGCOLOREFFECT = tagMAGCOLOREFFECT;
  TMagColorEffect = tagMAGCOLOREFFECT;
  PMagColorEffect = ^TMagColorEffect;

  TMagImageScalingCallback = function (hwnd: HWND; srcdata: Pointer;
    srcheader: MAGIMAGEHEADER; destdata: Pointer; destheader: MAGIMAGEHEADER;
    unclipped: TRect; clipped: TRect; dirty: HRGN): BOOL; stdcall;

  THWNDArray = array[0..0] of HWND;
  PHWNDArray = ^THWNDArray;

  // Public Functions
  function MagInitialize(): BOOL; stdcall;
  function MagUninitialize(): BOOL; stdcall;

  function MagSetWindowSource(hwnd: HWND; rect: TRect): BOOL; stdcall;
  function MagGetWindowSource(hwnd: HWND; var Rect: TRect): BOOL; stdcall;
  function MagSetWindowTransform(hwnd: HWND; var Transform: TMagTransform): BOOL; stdcall;
  function MagGetWindowTransform(hwnd: HWND; var Transform: TMagTransform): BOOL; stdcall;
  function MagSetWindowFilterList(hwnd: HWND; dwFilterMode: DWORD;
    count: Integer; pHWND: PHWNDArray): BOOL; stdcall;
  function MagGetWindowFilterList(hwnd: HWND; var dwFilterMode: DWORD;
    count: Integer; pHWND: PHWNDArray): Integer; stdcall;
  function MagSetImageScalingCallback(hwnd: HWND;
    MagImageScalingCallback: TMagImageScalingCallback): BOOL; stdcall;
//  MagImageScalingCallback WINAPI MagGetImageScalingCallback(HWND hwnd );
  function MagSetColorEffect(hwnd: HWND; var Effect: TMagColorEffect): BOOL; stdcall;
  function MagGetColorEffect(hwnd: HWND; var Effect: TMagColorEffect): BOOL; stdcall;

implementation

const
  MagnificationDll = 'Magnification.dll';

  function MagInitialize; external MagnificationDll name 'MagInitialize';
  function MagUninitialize; external MagnificationDll name 'MagUninitialize';
  function MagSetWindowSource; external MagnificationDll name 'MagSetWindowSource';
  function MagGetWindowSource; external MagnificationDll name 'MagGetWindowSource';
  function MagSetWindowTransform; external MagnificationDll name 'MagSetWindowTransform';
  function MagGetWindowTransform; external MagnificationDll name 'MagGetWindowTransform';
  function MagSetWindowFilterList; external MagnificationDll name 'MagSetWindowFilterList';
  function MagGetWindowFilterList; external MagnificationDll name 'MagGetWindowFilterList';
  function MagSetImageScalingCallback; external MagnificationDll name 'MagSetImageScalingCallback';
  function MagSetColorEffect; external MagnificationDll name 'MagSetColorEffect';
  function MagGetColorEffect; external MagnificationDll name 'MagGetColorEffect';

end.
Main
Delphi-Quellcode:
var
  Form1: TForm1;

implementation

uses
  Unit3, Magnification;

{$R *.dfm}

procedure TForm1.btn1Click(Sender: TObject);
var
  desktop, hwndMag: HWND;
  desktoprect, sourceRect: TRect;
  filterList: PHWNDArray;
  m_ScreenX, m_ScreenY, m_ScreenT, m_ScreenL: Integer;
begin

  desktop := GetDesktopWindow;
  GetWindowRect(desktop, desktoprect);

  m_ScreenT := desktoprect.Top;
  m_ScreenL := desktoprect.Left;
  m_ScreenX := desktoprect.right;
  m_ScreenY := desktoprect.bottom;

  Form3 := TForm3.Create(Form3);

  SetWindowPos(Form3.Handle, 0, 0, 0, desktoprect.right, desktoprect.bottom, SWP_SHOWWINDOW);

  SetWindowLong(Form3.Handle, GWL_EXSTYLE, GetWindowLong(Form3.Handle,
    GWL_EXSTYLE) or WS_EX_LAYERED);
  SetLayeredWindowAttributes(Form3.Handle, 0, 255, LWA_ALPHA);

  if (not MagInitialize) then
  begin
    Application.MessageBox('Init magnification failed', 'Error',
      mb_Ok + mb_IconError);
    Exit;
  end;

  hwndMag := CreateWindow(WC_MAGNIFIER, 'MagnifierWindow',
    WS_CHILD {or MS_SHOWMAGNIFIEDCURSOR} or WS_VISIBLE, 0, 0, m_ScreenX,
    m_ScreenY, Form3.Handle, 0, hInstance, nil);

  if (hwndMag = 0) then
  begin
    Application.MessageBox('MagnifierWindow creation failed', 'Error',
      mb_Ok + mb_IconError);
    Exit;
  end;

  try
    filterList[0] := Handle;
  except
  end;

  if (not MagSetWindowFilterList(hwndMag, MW_FILTERMODE_EXCLUDE, 1, filterList))
  then
  begin
    Application.MessageBox('Cannot exclude main window', 'Error',
      mb_Ok + mb_IconError);
    Exit;
  end;

  sourceRect.Top := m_ScreenT;
  sourceRect.Left := m_ScreenL;
  sourceRect.right := m_ScreenX;
  sourceRect.bottom := m_ScreenY;

  if (not MagSetWindowSource(hwndMag, sourceRect)) then
  begin
    Application.MessageBox('Cannot set source to MagnifierWindow', 'Error',
      mb_Ok + mb_IconError);
    Exit;
  end;

  { if (not MagUninitialize) then
    begin
    Application.MessageBox('Finalize magnification failed', 'Error',
    mb_Ok + mb_IconError);
    Exit;
    end; }
end;

Fukiszo 27. Jan 2018 11:57

AW: MagSetWindowFilterList function not remove specified window of screenshot
 
Delphi-Quellcode:
{ Here's how you can save the screen content into a bitmapfile.
  If you don't want to include the active (Delphi-)Application
  just put easily a 'Application.Minimize;' at the beginning
  of the procedure }

uses
  Windows, Graphics, Forms;

procedure TForm1.Button1Click(Sender: TObject);
var
  DC: HDC;
  Canvas: TCanvas;
  MyBitmap: TBitmap;
begin
  Canvas := TCanvas.Create;
  MyBitmap := TBitmap.Create;
  DC := GetDC(0);

  try
    Canvas.Handle := DC;
    with Screen do
    begin
      { detect the actual height and with of the screen }
      MyBitmap.Width := Width;
      MyBitmap.Height := Height;

      { copy the screen content to the bitmap }
      MyBitmap.Canvas.CopyRect(Rect(0, 0, Width, Height), Canvas,
                               Rect(0, 0, Width, Height));
      { stream the bitmap to disk }
      MyBitmap.SaveToFile('c:\windows\desktop\screen.bmp');
    end;

  finally
    { free memory }
    ReleaseDC(0, DC);
    MyBitmap.Free;
    Canvas.Free
  end;
end;

flashcoder 27. Jan 2018 13:26

AW: MagSetWindowFilterList function not remove specified window of screenshot
 
Zitat:

Zitat von Fukiszo (Beitrag 1392225)
Delphi-Quellcode:
{ Here's how you can save the screen content into a bitmapfile.
  If you don't want to include the active (Delphi-)Application
  just put easily a 'Application.Minimize;' at the beginning
  of the procedure }

uses
  Windows, Graphics, Forms;

procedure TForm1.Button1Click(Sender: TObject);
var
  DC: HDC;
  Canvas: TCanvas;
  MyBitmap: TBitmap;
begin
  Canvas := TCanvas.Create;
  MyBitmap := TBitmap.Create;
  DC := GetDC(0);

  try
    Canvas.Handle := DC;
    with Screen do
    begin
      { detect the actual height and with of the screen }
      MyBitmap.Width := Width;
      MyBitmap.Height := Height;

      { copy the screen content to the bitmap }
      MyBitmap.Canvas.CopyRect(Rect(0, 0, Width, Height), Canvas,
                               Rect(0, 0, Width, Height));
      { stream the bitmap to disk }
      MyBitmap.SaveToFile('c:\windows\desktop\screen.bmp');
    end;

  finally
    { free memory }
    ReleaseDC(0, DC);
    MyBitmap.Free;
    Canvas.Free
  end;
end;

The main Form not must be minimized in my situation.
I really need of help to fix code that was posted on question.

Fukiszo 27. Jan 2018 13:48

AW: MagSetWindowFilterList function not remove specified window of screenshot
 
use this command wherever you need
this will hide a window by its handle
Code:
 ShowWindow(EnterHandle, SW_HIDE); // Enter Handle of Window wich needs to become invisible

or

 ShowWindow(FindWindow(EnterClassName,nil), SW_HIDE); // EnterClassName can be something like TForm1 etc, adjust to your

or

 ShowWindow(FindWindow(nil,'Enter Forms Caption'), SW_HIDE); // self explaining

replace SW_HIDE with SW_SHOW to bring it back
use this code careful, it can be used to also tweak control (in and outside of your program)

Zacherl 27. Jan 2018 14:28

AW: MagSetWindowFilterList function not remove specified window of screenshot
 
Hiding / minimizing a window to exclude it from a screenshot is an invasive operation and I as an user would not like it (even if it's only for a split second).

Zitat:

Zitat von flashcoder (Beitrag 1392206)
1 - MagSetWindowFilterList function not remove main form (Form1).

You should not declare your
Delphi-Quellcode:
filterList
as
Delphi-Quellcode:
PHWNDArray
. Just use a normal
Delphi-Quellcode:
THWNDArray
as variable declaration and pass it like this:
Delphi-Quellcode:
MagSetWindowFilterList(hwndMag, MW_FILTERMODE_EXCLUDE, 1, @filterList[0])
. You could even use plain
Delphi-Quellcode:
HWND
as type for
Delphi-Quellcode:
filterList
(in case there's always only one handle in your "list").

Zitat:

Zitat von flashcoder (Beitrag 1392206)
2 - How recovery the content of "MagnifierWindow" to a image format?

I never used the magnification API, but the linked article shows a way by using the so called
Delphi-Quellcode:
MagImageScalingCallback
.

flashcoder 27. Jan 2018 19:43

AW: MagSetWindowFilterList function not remove specified window of screenshot
 
@Zacherl,

thank you very much, your suggestion about MagSetWindowFilterList worked fine.
I will try translate the part of save content of hwndmag to a image format.

I tried the suggestion of @Fukiszo but not worked see:

Delphi-Quellcode:
Canvas := TCanvas.Create;
  MyBitmap := TBitmap.Create;
  DC := GetWindowDC(hwndMag);

  GetWindowRect(hwndMag, r);

  try
    Canvas.Handle := DC;

      MyBitmap.Width := r.Width;
      MyBitmap.Height := r.Height;

      MyBitmap.Canvas.CopyRect(Rect(0, 0, MyBitmap.Width, MyBitmap.Height), Canvas,
                               Rect(0, 0, r.Width, r.Height));

      MyBitmap.SaveToFile('c:\screen.bmp');

  finally
    ReleaseDC(0, DC);
    MyBitmap.Free;
    Canvas.Free
  end;
But if someone know a way in Delphi and that works, i will accept.

Fukiszo 27. Jan 2018 20:48

AW: MagSetWindowFilterList function not remove specified window of screenshot
 
Zitat:

Zitat von flashcoder (Beitrag 1392258)
Delphi-Quellcode:
 MyBitmap.Canvas.CopyRect(Rect(0, 0, MyBitmap.Width, MyBitmap.Height), Canvas,
                               Rect(0, 0, r.Width, r.Height));

Delphi-Quellcode:
my example was made for a full screen, not part of screen
use it like this:
 MyBitmap.Canvas.CopyRect(Rect(X.Start, Y.Start, X.End, Y.End), Canvas,
                          Rect(X.Start, Y.Start, X.End, Y.End));

X and Y are Screen Offsets, not your Application Window Offsets
eg, Position [0,0] = topleft screen corner and not your application windows coordinate!
but better wait, others may give much better methods than my rude ones.

flashcoder 27. Jan 2018 21:52

AW: MagSetWindowFilterList function not remove specified window of screenshot
 
@Fukiszo,

i tried your two suggestions and none works, but this can be the reason:

Zitat:

Saving the data

Normally, we could save the content of a window into a file, or copy its content into memory by using the BitBlt function. The main problem while saving the captured data by the magnification library is that we cannot access the bitmap of the host window or the magnification window with the BitBlt function as usual. So we use a work around by using the MagSetImageScalingCallback() function, which is described as below.
This alert can be found on C++ example linked on question.
So, i think that with BMP.Canvas.CopyRect() also not is different.

Fukiszo 27. Jan 2018 22:04

AW: MagSetWindowFilterList function not remove specified window of screenshot
 
sorry i dont know MagXXXXX.pas units neither their .dll,
i gave general examples,
if MAGxxx uses overlay to display something, my method fail. that i think your warning is telling.
I'm sorry!

Zitat:

Zitat von flashcoder (Beitrag 1392268)
...using the MagSetImageScalingCallback() function, which is described as below...

can you show that?

flashcoder 27. Jan 2018 22:14

AW: MagSetWindowFilterList function not remove specified window of screenshot
 
Zitat:

Zitat von flashcoder (Beitrag 1392268)
...using the MagSetImageScalingCallback() function, which is described as below...

Zitat:

Zitat von Fukiszo (Beitrag 1392270)
can you show that?

@Fukiszo, i still will try translate this part :)

Fukiszo 27. Jan 2018 22:18

AW: MagSetWindowFilterList function not remove specified window of screenshot
 
if it is allowed, upload the 80kb source, i dont have access on your link to look at.
edit: forget it, i just scrolled down and what i read is pretty simple,
when you translated the callback part you automatic have imported BMP format from where you can create hundrets of copies.

Code:
LONG lineSize = bmif.biWidth * bmif.biBitCount / 8;
BYTE* pLineData = new BYTE[lineSize];
BYTE* pStart;
BYTE* pEnd;
LONG lineStart = 0;
LONG lineEnd = bmif.biHeight - 1;
while (lineStart < lineEnd)
{
   // Get the address of the swap line
   pStart = pData + (lineStart * lineSize);
   pEnd = pData + (lineEnd * lineSize);
   // Swap the top with the bottom
   memcpy(pLineData, pStart, lineSize);
   memcpy(pStart, pEnd, lineSize);
   memcpy(pEnd, pLineData, lineSize);
   // Adjust the line index
   lineStart++;
   lineEnd--;

delete pLineData;
at that point the image is ready

flashcoder 27. Jan 2018 22:29

AW: MagSetWindowFilterList function not remove specified window of screenshot
 
Zitat:

Zitat von Fukiszo (Beitrag 1392274)
if it is allowed, upload the 80kb source, i dont have access on your link to look at.
edit: forget it, i just scrolled down and what i read is pretty simple,
when you translated the callback part you automatic have imported BMP format from where you can create hundrets of copies.

Code:
LONG lineSize = bmif.biWidth * bmif.biBitCount / 8;
BYTE* pLineData = new BYTE[lineSize];
BYTE* pStart;
BYTE* pEnd;
LONG lineStart = 0;
LONG lineEnd = bmif.biHeight - 1;
while (lineStart < lineEnd)
{
   // Get the address of the swap line
   pStart = pData + (lineStart * lineSize);
   pEnd = pData + (lineEnd * lineSize);
   // Swap the top with the bottom
   memcpy(pLineData, pStart, lineSize);
   memcpy(pStart, pEnd, lineSize);
   memcpy(pEnd, pLineData, lineSize);
   // Adjust the line index
   lineStart++;
   lineEnd--;

delete pLineData;
at that point the image is ready

I attached the source file of C++ example on question :-D
Look to the MagCaptureDlg.cpp file

flashcoder 28. Jan 2018 01:30

AW: MagSetWindowFilterList function not remove specified window of screenshot
 
Here is my complete code updated, i tried translate callback function (was a combine of these 2 links: LNK1 and LNK2), seems right but not is executing when MagSetImageScalingCallback api is called.


Delphi-Quellcode:
var
  Form1: TForm1;

implementation

uses
  Unit3, Magnification;

{$R *.dfm}

function ImageScaling(hwnd: hwnd; srcdata: Pointer; srcheader: MAGIMAGEHEADER;
  destdata: Pointer; destheader: MAGIMAGEHEADER; unclipped: TRect;
  clipped: TRect; dirty: HRGN): Boolean;
var
  lpbmih: TBitmapInfoHeader;
  lpbmi: TBitmapInfo;
  aBitmap: HBITMAP;
  aDC: HDC;
  bmp: TBitmap;
begin
  Fillchar(lpbmih, SizeOf(lpbmih), 0);
  lpbmih.biSize := SizeOf(lpbmih);
  lpbmih.biWidth := srcheader.width;
  lpbmih.biHeight := srcheader.height;
  lpbmih.biPlanes := 1;
  lpbmih.biBitCount := Floor(lpbmih.biSizeImage / lpbmih.biHeight /
    lpbmih.biWidth * 8);
  lpbmih.biCompression := BI_RGB;

  Fillchar(lpbmi, SizeOf(lpbmi), 0);
  lpbmi.bmiHeader.biSize := SizeOf(lpbmi.bmiHeader);
  lpbmi.bmiHeader.biWidth := srcheader.width;
  lpbmi.bmiHeader.biHeight := srcheader.height;
  lpbmi.bmiHeader.biPlanes := 1;
  lpbmi.bmiHeader.biBitCount :=
    Floor(lpbmi.bmiHeader.biSizeImage / lpbmi.bmiHeader.biHeight /
    lpbmi.bmiHeader.biWidth * 8);
  lpbmi.bmiHeader.biCompression := BI_RGB;

  aDC := GetWindowDC(hwnd);
  bmp := TBitmap.Create;
  aBitmap := 0;
  try
    aBitmap := CreateDIBitmap(aDC, lpbmih, 0, nil, lpbmi, DIB_RGB_COLORS);
    bmp.handle := aBitmap;
  finally
    DeleteObject(aBitmap);
    DeleteDC(aDC);
    bmp.Free;
  end;
  Result := True;
end;

procedure MagScreenShot;
var
  desktop, hwndMag: hwnd;
  desktoprect, sourceRect: TRect;
  filterList: THWNDArray;
  m_ScreenX, m_ScreenY, m_ScreenT, m_ScreenL: Integer;
begin

  if not Form3.Showing then
    Form3.Show;

  desktop := GetDesktopWindow;
  GetWindowRect(desktop, desktoprect);

  m_ScreenT := desktoprect.Top;
  m_ScreenL := desktoprect.Left;
  m_ScreenX := desktoprect.right;
  m_ScreenY := desktoprect.bottom;

  if (not MagInitialize) then
  begin
    Application.MessageBox('Init magnification failed', 'Error',
      mb_Ok + mb_IconError);
    Exit;
  end;

  hwndMag := CreateWindow(WC_MAGNIFIER, 'MagnifierWindow',
    WS_CHILD or MS_SHOWMAGNIFIEDCURSOR or WS_VISIBLE, 0, 0, m_ScreenX,
    m_ScreenY, Form1.handle, 0, hInstance, nil);

  if (hwndMag = 0) then
  begin
    Application.MessageBox('MagnifierWindow creation failed', 'Error',
      mb_Ok + mb_IconError);
    Exit;
  end;

  if (not MagSetImageScalingCallback(hwndMag, TMagImageScalingCallback(@ImageScaling))) then
  begin
    Application.MessageBox('Cannot set callback', 'Error',
      mb_Ok + mb_IconError);
    Exit;
  end;

  try
    filterList[0] := Form3.handle;
  except
  end;

  if (not MagSetWindowFilterList(hwndMag, MW_FILTERMODE_EXCLUDE, 1,
    @filterList[0])) then
  begin
    Application.MessageBox('Cannot exclude main window', 'Error',
      mb_Ok + mb_IconError);
    Exit;
  end;

  sourceRect.Top := m_ScreenT;
  sourceRect.Left := m_ScreenL;
  sourceRect.right := m_ScreenX;
  sourceRect.bottom := m_ScreenY;

  if (not MagSetWindowSource(hwndMag, sourceRect)) then
  begin
    Application.MessageBox('Cannot set source to MagnifierWindow', 'Error',
      mb_Ok + mb_IconError);
    Exit;
  end;

  { if (not MagUninitialize) then
    begin
    Application.MessageBox('Finalize magnification failed', 'Error',
    mb_Ok + mb_IconError);
    Exit;
    end; }
end;

procedure TForm1.tmr1Timer(Sender: TObject);
begin
  MagScreenShot;
end;
Timer is be to 10000ms

Zacherl 28. Jan 2018 12:29

AW: MagSetWindowFilterList function not remove specified window of screenshot
 
The calling convention of the callback should be
Delphi-Quellcode:
stdcall
. But besides that MSDN says:
Zitat:

Note The MagSetImageScalingCallback function is deprecated in Windows 7 and later, and should not be used in new applications. There is no alternate functionality.
and
Zitat:

This function works only when Desktop Window Manager (DWM) is off.

I guess the "magnifier window" uses a DirectX surface to display the desktop screenshot. It might be possible to obtain its handle (e.g. by hooking the corresponding DirectX interface(s), if there is no other way to do it).

flashcoder 28. Jan 2018 13:40

AW: MagSetWindowFilterList function not remove specified window of screenshot
 
Zitat:

Zitat von Zacherl
This function works only when Desktop Window Manager (DWM) is off.

@Zacherl,

The C++ example works fine with DWM enable :).
And i followed your suggestion below, thank you:

Zitat:

Zitat von Zacherl
The calling convention of the callback should be
Delphi-Quellcode:
stdcall

Delphi-Quellcode:

TMagImageScalingCallback = function (hwnd: HWND; srcdata: Pointer;
    srcheader: MAGIMAGEHEADER; destdata: Pointer; destheader: MAGIMAGEHEADER;
    unclipped: TRect; clipped: TRect; dirty: HRGN): BOOL; stdcall; // definition found in Magnification.pas posted on question

function ImageScaling(hwnd: hwnd; srcdata: Pointer; srcheader: MAGIMAGEHEADER;
  destdata: Pointer; destheader: MAGIMAGEHEADER; unclipped: TRect;
  clipped: TRect; dirty: HRGN): BOOL; stdcall;
var
  lpbmih: TBitmapInfoHeader;
  lpbmi: TBitmapInfo;
  aBitmap: HBITMAP;
  aDC: HDC;
  bmp: TBitmap;
begin
  Fillchar(lpbmih, SizeOf(lpbmih), 0);
  lpbmih.biSize := SizeOf(lpbmih);
  lpbmih.biWidth := srcheader.width;
  lpbmih.biHeight := srcheader.height;

//...
end;

//...

// calling in MagSetImageScalingCallback api

if (not MagSetImageScalingCallback(hwndMag, TMagImageScalingCallback(@ImageScaling))) then
So, like already said, when i put breakpoint inside my ImageScaling function, debug not go to function, then i noted that this callback function not is executed.

Here is how be is C++ code:
Code:

typedef BOOL (CALLBACK* MagImageScalingCallback)(HWND hwnd, void * srcdata, MAGIMAGEHEADER srcheader, void * destdata, MAGIMAGEHEADER destheader, RECT unclipped, RECT clipped, HRGN dirty );

//...

BOOL MagImageScaling(HWND hwnd, void *srcdata, MAGIMAGEHEADER srcheader,
                void *destdata, MAGIMAGEHEADER destheader,
                RECT unclipped, RECT clipped, HRGN dirty)
{
   // Setup the bitmap info header
      bmif.biSize = sizeof(BITMAPINFOHEADER);
      bmif.biHeight = srcheader.height;
      bmif.biWidth = srcheader.width;

//...
}

if (!MagSetImageScalingCallback(hwndMag, (MagImageScalingCallback)MagImageScaling))

Zacherl 28. Jan 2018 16:29

AW: MagSetWindowFilterList function not remove specified window of screenshot
 
Thats strange :? If
Delphi-Quellcode:
MagSetImageScalingCallback
returns
Delphi-Quellcode:
true
, the callback should at least get invoked. I'm trying out the C++ example now. Could you upload your complete Delphi project files as well?

Edit:
C++ example does not work for me (Windows 10 64-bit Build 1709).
Delphi-Quellcode:
MagSetWindowSource
raises an access violation in `Magnification.dll`. It does not crash, if I remove the call to
Delphi-Quellcode:
MagSetImageScalingCallback
, tho. I guess MSDN is correct about the deprecation :wink: Never mind, the callback is getting invoked, but something inside the callback crashes the example for some reason.

Edit2:
Wow, the author of the C++ example forgot about the
Delphi-Quellcode:
stdcall
as well :wall: :-D It seems to work now.

flashcoder 28. Jan 2018 16:55

AW: MagSetWindowFilterList function not remove specified window of screenshot
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von Zacherl
Could you upload your complete Delphi project files as well?

My Delphi project is attach below.

EWeiss 28. Jan 2018 19:42

AW: MagSetWindowFilterList function not remove specified window of screenshot
 
Zitat:

Zitat von flashcoder (Beitrag 1392312)
Zitat:

Zitat von Zacherl
Could you upload your complete Delphi project files as well?

My Delphi project is attach below.

Here is your fix..
but which works only in the IDE.
Changed with D2010

for the future your should initialize a new Form if is NIL. ;)
callback works..

greets

flashcoder 28. Jan 2018 20:10

AW: MagSetWindowFilterList function not remove specified window of screenshot
 
Zitat:

Zitat von EWeiss
Here is your fix..
but which works only in the IDE.
Changed with D2010

Sorry, but this is the same project and with the same trouble, callback not is executed.
The diference here was only that you created the Form3 in runtime.

EWeiss 28. Jan 2018 20:36

AW: MagSetWindowFilterList function not remove specified window of screenshot
 
Zitat:

Zitat von flashcoder (Beitrag 1392317)
Zitat:

Zitat von EWeiss
Here is your fix..
but which works only in the IDE.
Changed with D2010

Sorry, but this is the same project and with the same trouble, callback not is executed.
The diference here was only that you created the Form3 in runtime.

execute always by me..
Win7 64 Bit as you can see on my Screenshot!
MagScreenShot is no longer Global is a part of Form1 now.

and i get the Shot from any Window where the mouse hover.
Delphi-Quellcode:
  GetCursorPos(Point);
  desktop := WindowFromPoint(Point);
  Caption := IntToStr(desktop);
as say works always by me.
I'm out ;)

shot removed..

greets

flashcoder 28. Jan 2018 20:47

AW: MagSetWindowFilterList function not remove specified window of screenshot
 
I want know why my callback function not is executed :wall: :(

EWeiss 28. Jan 2018 20:57

AW: MagSetWindowFilterList function not remove specified window of screenshot
 
Zitat:

Zitat von flashcoder (Beitrag 1392319)
I want know why my callback function not is executed :wall: :(

Win10 Trouble... i think.

greets

flashcoder 28. Jan 2018 21:03

AW: MagSetWindowFilterList function not remove specified window of screenshot
 
Zitat:

Zitat von EWeiss
Win10 Trouble... i think.

No, here my enviroment is Windows 7 Ultimate x64.

EWeiss 28. Jan 2018 21:09

AW: MagSetWindowFilterList function not remove specified window of screenshot
 
Zitat:

Zitat von flashcoder (Beitrag 1392321)
Zitat:

Zitat von EWeiss
Win10 Trouble... i think.

No, here my enviroment is Windows 7 Ultimate x64.

That is hard
But as I said my code I uploaded here works.
sorry..

greets

flashcoder 28. Jan 2018 21:29

AW: MagSetWindowFilterList function not remove specified window of screenshot
 
Zitat:

Zitat von EWeiss
That is hard
But as I said my code I uploaded here works.

The callback function ImageScaling is executed in your test?

Edition:

The callback is working to me now, i discovered that my callback function is executed always that Magnifier window is resized:

Delphi-Quellcode:
function MagImageScalingCallback(hwnd: hwnd; srcdata: Pointer;
  srcheader: MAGIMAGEHEADER; destdata: Pointer; destheader: MAGIMAGEHEADER;
  unclipped: TRect; clipped: TRect; dirty: HRGN): BOOL; stdcall;
var
  lpbmih: TBitmapInfoHeader;
  lpbmi: TBitmapInfo;
  aBitmap: HBITMAP;
  aDC: HDC;
  bmp: TBitmap;
begin
  Fillchar(lpbmih, SizeOf(lpbmih), 0);
  lpbmih.biSize := SizeOf(lpbmih);
  lpbmih.biWidth := srcheader.width;
  lpbmih.biHeight := srcheader.height;
  lpbmih.biPlanes := 1;
  lpbmih.biBitCount := Floor(lpbmih.biSizeImage / lpbmih.biHeight /
    lpbmih.biWidth * 8);
  lpbmih.biCompression := BI_RGB;

  Fillchar(lpbmi, SizeOf(lpbmi), 0);
  lpbmi.bmiHeader.biSize := SizeOf(lpbmi.bmiHeader);
  lpbmi.bmiHeader.biWidth := srcheader.width;
  lpbmi.bmiHeader.biHeight := srcheader.height;
  lpbmi.bmiHeader.biPlanes := 1;
  lpbmi.bmiHeader.biBitCount :=
    Floor(lpbmi.bmiHeader.biSizeImage / lpbmi.bmiHeader.biHeight /
    lpbmi.bmiHeader.biWidth * 8);
  lpbmi.bmiHeader.biCompression := BI_RGB;

  aDC := GetWindowDC(hwnd);
  bmp := TBitmap.Create;
  aBitmap := 0;
  try
    aBitmap := CreateDIBitmap(aDC, lpbmih, 0, nil, lpbmi, DIB_RGB_COLORS);
    bmp.handle := aBitmap;
    bmp.SaveToFile('c:\tela.bmp');
  finally
    DeleteObject(aBitmap);
    DeleteDC(aDC);
    bmp.Free;
  end;
  Result := True;
end;

//...

if (not MagSetImageScalingCallback(hwndMag, MagImageScalingCallback)) then
My trouble now is that i'm getting a black image. Some idea how fix?

EWeiss 28. Jan 2018 23:28

AW: MagSetWindowFilterList function not remove specified window of screenshot
 
Zitat:

The callback function ImageScaling is executed in your test?
as said..
Zitat:

But as I said my code I uploaded here works.
greets

Zacherl 28. Jan 2018 23:34

AW: MagSetWindowFilterList function not remove specified window of screenshot
 
Zitat:

Zitat von EWeiss (Beitrag 1392320)
Zitat:

Zitat von flashcoder (Beitrag 1392319)
I want know why my callback function not is executed :wall: :(

Win10 Trouble... i think.

The (corrected) C++ example works on my Windows 10, but the Delphi code crashes somewhere inside
Delphi-Quellcode:
MagSetWindowSource
(breakpoint inside callback does not trigger) - again, only if I set the callback.

flashcoder 29. Jan 2018 00:14

AW: MagSetWindowFilterList function not remove specified window of screenshot
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von Zacherl
The (corrected) C++ example works on my Windows 10, but the Delphi code crashes somewhere inside
Delphi-Quellcode:
MagSetWindowSource

@Zacherl,

Delphi-Quellcode:
MagSetWindowSource
not is necessary, i tested here (Delphi code) without this api and screenshot still is works.

About callback also is working fine here, my callback function is executed when Magnifier window (Form1) is maximized, now i need of some help to fix this trouble of black capture :)

Edition:

Delphi-Quellcode:
MagSetWindowSource
and
Delphi-Quellcode:
MagSetImageScalingCallback
works fine since that (Form1) is maximized. My trouble now really is with the black capture in callback function.

EWeiss 29. Jan 2018 01:05

AW: MagSetWindowFilterList function not remove specified window of screenshot
 
Zitat:

Zitat von flashcoder (Beitrag 1392328)
Zitat:

Zitat von Zacherl
The (corrected) C++ example works on my Windows 10, but the Delphi code crashes somewhere inside
Delphi-Quellcode:
MagSetWindowSource

@Zacherl,

Delphi-Quellcode:
MagSetWindowSource
not is necessary, i tested here (Delphi code) without this api and screenshot still is works.

About callback also is working fine here, my callback function is executed when Magnifier window (Form1) is maximized, now i need of some help to fix this trouble of black capture :)

Edition:

Delphi-Quellcode:
MagSetWindowSource
and
Delphi-Quellcode:
MagSetImageScalingCallback
works fine since that (Form1) is maximized. My trouble now really is with the black capture in callback function.

Hi,
sorry your should learn C++ before translate any..
as i see, what your do here? as example

Delphi-Quellcode:
ImageScaling(hwnd: hwnd;

that looks very bad for me.

you can use in C++
Code:
hwnd Hwnd
but not in Delphi to..

should be
Delphi-Quellcode:
ImageScaling(Handle: HWND;

then your set your Window not on TopMost that is bad also... and so on.
read the API then create a application from beginning, just my 2 Cent.

greets

flashcoder 29. Jan 2018 01:12

AW: MagSetWindowFilterList function not remove specified window of screenshot
 
Delphi is case insensitive and is able to know waht is a variable name and a type.

EWeiss 29. Jan 2018 01:28

AW: MagSetWindowFilterList function not remove specified window of screenshot
 
Zitat:

Zitat von flashcoder (Beitrag 1392330)
Delphi is case insensitive and is able to know waht is a variable name and a type.

and that is a good code style?
i think not.

greets

Zacherl 29. Jan 2018 01:55

AW: MagSetWindowFilterList function not remove specified window of screenshot
 
Zitat:

Zitat von flashcoder (Beitrag 1392328)
Delphi-Quellcode:
MagSetWindowSource
not is necessary, i tested here (Delphi code) without this api and screenshot still is works.

It keeps crashing, if I comment out the
Delphi-Quellcode:
MagSetWindowSource
. Callstack points to `msvcrt.memcpi` so I guess there's something fishy somewhere else. Could be anything like wrong types, calling conventions, buffer overreads, ... Same problem might cause your black image. Buffer overreads/overflows can be tricky sometimes and do not always result in reproducable problems.

EWeiss 29. Jan 2018 05:40

AW: MagSetWindowFilterList function not remove specified window of screenshot
 
Zitat:

Zitat von Zacherl (Beitrag 1392332)
Zitat:

Zitat von flashcoder (Beitrag 1392328)
Delphi-Quellcode:
MagSetWindowSource
not is necessary, i tested here (Delphi code) without this api and screenshot still is works.

It keeps crashing, if I comment out the
Delphi-Quellcode:
MagSetWindowSource
. Callstack points to `msvcrt.memcpi` so I guess there's something fishy somewhere else. Could be anything like wrong types, calling conventions, buffer overreads, ... Same problem might cause your black image. Buffer overreads/overflows can be tricky sometimes and do not always result in reproducable problems.

the Trouble is resize, that is known on W7 64Bit.
but it works on W7 32 BIT.
i think you can nothing do on it.

greets

flashcoder 29. Jan 2018 06:20

AW: MagSetWindowFilterList function not remove specified window of screenshot
 
Liste der Anhänge anzeigen (Anzahl: 1)
Here is project solved and working 100% like must be.

Delphi-Quellcode:
var
  Form1: TForm1;

implementation

uses
  Unit3, Magnification;

{$R *.dfm}

function MagImageScalingCallback(hwnd: hwnd; srcdata: Pointer;
  srcheader: MAGIMAGEHEADER; destdata: Pointer; destheader: MAGIMAGEHEADER;
  unclipped: TRect; clipped: TRect; dirty: HRGN): BOOL; stdcall;
var
  lpbmi: TBitmapInfo;
  bmp: TBitmap;
  aDC: HDC;
  abitmap: HBitmap;
begin
  Fillchar(lpbmi, sizeof(lpbmi), 0);
  lpbmi.bmiHeader.biSize := sizeof(lpbmi.bmiHeader);
  lpbmi.bmiHeader.biHeight := -srcheader.height;
  // Otherwise the image is upside down.
  lpbmi.bmiHeader.biWidth := srcheader.width;
  lpbmi.bmiHeader.biSizeImage := srcheader.cbSize;
  lpbmi.bmiHeader.biPlanes := 1;
  lpbmi.bmiHeader.biBitCount := 32;
  lpbmi.bmiHeader.biCompression := BI_RGB;

  aDC := GetWindowDC(hwnd);
  bmp := TBitmap.Create;
  abitmap := 0;
  try
    abitmap := CreateDIBitmap(aDC, lpbmi.bmiHeader, CBM_INIT, srcdata, lpbmi,
      DIB_RGB_COLORS);
    bmp.handle := abitmap;
    bmp.SaveToFile('c:\screen.bmp');
  finally
    DeleteObject(abitmap);
    DeleteDC(aDC);
    bmp.Free;
  end;

  Result := True;
end;

procedure MagScreenShot;
var
  desktop, hwndMag: hwnd;
  desktoprect, sourceRect: TRect;
  filterList: THWNDArray;
  m_ScreenX, m_ScreenY, m_ScreenT, m_ScreenL: Integer;
begin

  Form1.WindowState := wsMaximized;

  if not Form3.Showing then
    Form3.Show;

  desktop := GetDesktopWindow;
  GetWindowRect(desktop, desktoprect);

  m_ScreenT := desktoprect.Top;
  m_ScreenL := desktoprect.Left;
  m_ScreenX := desktoprect.right;
  m_ScreenY := desktoprect.bottom;

  if (not MagInitialize) then
  begin
    Application.MessageBox('Init magnification failed', 'Error',
      mb_Ok + mb_IconError);
    Exit;
  end;

  hwndMag := CreateWindow(WC_MAGNIFIER, 'MagnifierWindow',
    WS_CHILD or MS_SHOWMAGNIFIEDCURSOR or WS_VISIBLE, 0, 0, m_ScreenX,
    m_ScreenY, Form1.handle, 0, hInstance, nil);

  if (hwndMag = 0) then
  begin
    Application.MessageBox('MagnifierWindow creation failed', 'Error',
      mb_Ok + mb_IconError);
    Exit;
  end;

  if (not MagSetImageScalingCallback(hwndMag, MagImageScalingCallback)) then
  begin
    Application.MessageBox('Cannot set callback', 'Error',
      mb_Ok + mb_IconError);
    Exit;
  end;

  try
    filterList[0] := Form3.handle;
  except
  end;

  if (not MagSetWindowFilterList(hwndMag, MW_FILTERMODE_EXCLUDE, 1,
    @filterList[0])) then
  begin
    Application.MessageBox('Cannot exclude main window', 'Error',
      mb_Ok + mb_IconError);
    Exit;
  end;

  sourceRect.Top := m_ScreenT;
  sourceRect.Left := m_ScreenL;
  sourceRect.right := m_ScreenX;
  sourceRect.bottom := m_ScreenY;

  Sleep(200);

  if (not MagSetWindowSource(hwndMag, sourceRect)) then
  begin
    Application.MessageBox('Cannot set source to MagnifierWindow', 'Error',
      mb_Ok + mb_IconError);
    Exit;
  end;

  { if (not MagUninitialize) then
    begin
    Application.MessageBox('Finalize magnification failed', 'Error',
    mb_Ok + mb_IconError);
    Exit;
    end; }
end;

procedure TForm1.btn1Click(Sender: TObject);
begin
  MagScreenShot;
end;

Zacherl 29. Jan 2018 06:49

AW: MagSetWindowFilterList function not remove specified window of screenshot
 
Zitat:

Zitat von EWeiss (Beitrag 1392334)
Zitat:

Zitat von Zacherl (Beitrag 1392332)
Zitat:

Zitat von flashcoder (Beitrag 1392328)
Delphi-Quellcode:
MagSetWindowSource
not is necessary, i tested here (Delphi code) without this api and screenshot still is works.

It keeps crashing, if I comment out the
Delphi-Quellcode:
MagSetWindowSource
. Callstack points to `msvcrt.memcpi` so I guess there's something fishy somewhere else. Could be anything like wrong types, calling conventions, buffer overreads, ... Same problem might cause your black image. Buffer overreads/overflows can be tricky sometimes and do not always result in reproducable problems.

the Trouble is resize, that is known on W7 64Bit

Yes, I can confirm this. The latest version works for me, but resizing still crashes the application.

EWeiss 29. Jan 2018 07:37

AW: MagSetWindowFilterList function not remove specified window of screenshot
 
Zitat:

Here is project solved and working 100% like must be.
no it Crash.. and has a black Screen.
it works and does not work.

MagImageScalingCallback is not needed.
and if you deactivate Desktop Theme then it Crash always..
on this line

Delphi-Quellcode:
  if (not MagSetWindowSource(hwndMag, sourceRect)) then

with Floating Point invalid Operation.

here are a full new projekt
which works without Crash, please deactivate Desktop Themes before run.
sorry your source text is fully flawed.

1. Each new call creates a new instance of the Magnification Dll without uninitializing the old one before.
2. Each new call creates a new Window without destroy the old one before.
3. Array of tagMAGTRANSFORM is wrong.
4. Filterlist is not Needed.
5. a second form is not needed.
6. the callback also if your use a Timer.

.. and so on.

greets

flashcoder 29. Jan 2018 13:06

AW: MagSetWindowFilterList function not remove specified window of screenshot
 
Zitat:

Zitat von EWeiss (Beitrag 1392346)
Zitat:

Here is project solved and working 100% like must be.
no it Crash.. and has a black Screen.
it works and does not work.

MagImageScalingCallback is not needed.
and if you deactivate Desktop Theme then it Crash always..
on this line

Delphi-Quellcode:
  if (not MagSetWindowSource(hwndMag, sourceRect)) then

with Floating Point invalid Operation.

here are a full new projekt
which works without Crash, please deactivate Desktop Themes before run.
sorry your source text is fully flawed.

1. Each new call creates a new instance of the Magnification Dll without uninitializing the old one before.
2. Each new call creates a new Window without destroy the old one before.
3. Array of tagMAGTRANSFORM is wrong.
4. Filterlist is not Needed.
5. a second form is not needed.
6. the callback also if your use a Timer.

.. and so on.

greets

Even that your code work (and yes works with aero actived or no here), the approach of question is totally different of this and your last update is more near of this approach, but even thank you by fix some bugs mainly the and of your enumeration.

About item , is necessary because i not want show Magnifier window to user (i still will hide Form1 in my project), based on C++ example. Please, read item 2 on page of C++ example.

Relative to black screen, see in my last updated that is black only on Magnifier window, but on bmp file not.


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:05 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz