gZoom – Delphi Implementation of the Missing Mode in Windows Magnifier

gZoom in actionAh, nostalgia.
Here’s a small Delphi program I wrote some 20+ years ago. As far as I can remember this was one of my first (maybe even the first one really) Delphi applications which would not fall into the “hello world” category. Back then I was quite impressed how easy was to call Windows API functions directly from Delphi code to create small but powerful (and hopefully not useless) programs. The original code (I think days of Delphi 2 or 3), as the case is with Delphi, compiles without too much editing even today in RAD Studio 10.X.

If you are familiar with the application called “Magnifier” (comes with Windows as a part of Ease of Access features) then you already know its desired purpose: it displays zoomed in portion of the screen. Now, Magnifier has 3 modes: full screen, lens and docked. What is missing in Magnifier (even today with Windows 10) is the ability to enlarge the part of the screen that is below the mouse and display in a separate freely positioned window.

This is where my gZoom comes into rescue. gZoom is like the lens mode in Magnifier: it magnifies the part of the screen around the mouse – but the magnified display is directed to the main window of the program – it does not move along with the mouse.

As you can see from the UI, gZoom includes only a few controls. You can decide the zoom factor and should you see a crosshair of where the mouse is actually in the zoomed part of the screen. I’m using a Timer to grab the screen shot of the entire desktop window (works even if you work with multiple monitors). Using some stretching and canvas drawing I’m then transferring the part of the image “below” the mouse onto the gZoom’s main window. Simple.

You can download the full source code. Here’s the main drawing code:

procedure TMainForm.zoomTimerTimer(Sender: TObject);
var
  srcRect,destRect,fmrRect:TRect;
  iWidth,iHeight,DmX,DmY:Integer;
  iTmpX,iTmpY:Real;
  C:TCanvas;
  hDesktop: Hwnd;
  curPos:TPoint;
begin
  if not IsIconic(Application.Handle) then
  begin
    hDesktop := GetDesktopWindow;
    GetCursorPos(curPos);
    fmrRect:=Rect(MainForm.Left,MainForm.Top,MainForm.Left+MainForm.Width,MainForm.Top+MainForm.Height);

    if not PtInRect(fmrRect,curPos) then
    begin
      if pnlMain.Visible then pnlMain.Visible := False;
      if NOT zoomImage.Visible then zoomImage.Visible := True;

      iWidth:=zoomImage.Width;
      iHeight:=zoomImage.Height;
      destRect:=Rect(0,0,iWidth,iHeight);

      iTmpX:=iWidth / (tbZoomFactor.Position * 4);
      iTmpY:=iHeight / (tbZoomFactor.Position * 4);

      srcRect:=Rect(curPos.x,curPos.y,curPos.x,curPos.y);
      InflateRect(srcRect,Round(iTmpX),Round(iTmpY));

      If srcRect.Left<0 then OffsetRect(srcRect,-srcRect.Left,0);
      If srcRect.Top<0 then OffsetRect(srcRect,0,-srcRect.Top);
      If srcRect.Right>Screen.DesktopWidth then OffsetRect(srcRect,-(srcRect.Right-Screen.DesktopWidth),0);
      If srcRect.Bottom>Screen.DesktopHeight then OffsetRect(srcRect,0,-(srcRect.Bottom-Screen.DesktopHeight));

      C := TCanvas.Create;
      try
        C.Handle := GetDC(GetDesktopWindow);

        zoomImage.Canvas.CopyRect(destRect,C,srcRect);
      finally
        ReleaseDC(hDesktop, C.Handle);
        C.Free;
      end;

      If chkCrosshair.Checked then
      begin // show crosshair
        with zoomImage.Canvas do
        begin
          DmX:=tbZoomFactor.Position * 2 * (curPos.X-srcRect.Left);
          DmY:=tbZoomFactor.Position * 2 * (curPos.Y-srcRect.Top);
          MoveTo(DmX - (iWidth div 4),DmY); // -
          LineTo(DmX + (iWidth div 4),DmY); // -
          MoveTo(DmX,DmY - (iHeight div 4)); // |
          LineTo(DmX,DmY + (iHeight div 4)); // |
        end; // with image1.Canvas
      end; // show crosshair
    end // Cursor not inside form
    else
    begin  // cursor inside form
      if NOT pnlMain.Visible then pnlMain.Visible := True;
      if zoomImage.Visible then zoomImage.Visible := False;
    end;
  end; // IsIconic
end;

Here’s how it looks in (video) action:

Feel free to add modifications and share here 🙂

I’m thinking of being able to move the gZoom window without the title bar (+ hide it). Or maybe even making it stay on top as a secondary small form in some kind of a working-with-graphics type of application where you want to allow users to “see” better (the main working area), or something like that.

6 thoughts on “gZoom – Delphi Implementation of the Missing Mode in Windows Magnifier

  1. Jerry Dodge

    Looks like it only works on the main screen. If I bring my mouse to another monitor, it only captures the outer-most edge of the main monitor. This is in Windows 10 and Delphi 10.1 Berlin.

    Reply
    1. zarkogajic Post author

      Hi Jerry, Can you send a screen shot – as I just tried and works as expected.

      Reply
  2. Andreas Toth

    Ah, yes, I remember the original. In fact, I found the original code earlier this year on an old backup of mine. 🙂

    Reply
  3. Greg Faulkner

    Hi Zarko,

    I am still using your application as of today, and it still works fantastically under my Windows 7 Ultimate 64 bits laptop. Thanks for this nice utility…

    Since i am using using it so frequently when developing web site to see if everything is aligned properly,
    I thought it should be updated to show mouse coordinates and RGB or HEX color of the cursor location.
    That would be fantastic…

    Best regards…

    Reply
    1. zarkogajic Post author

      Hi Greg,

      Line 39 in code above, add:

      rgb := c.Pixels[curPos.x,curPos.y];
      Caption := Format(‘x:%d y:%d clr: %d (%x)’,[curPos.x , curPos.y, ColorToRGB(rgb), rgb]);

      Reply

Leave a Reply to Greg Faulkner Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.