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.

One thought on “gZoom – Delphi Implementation of the Missing Mode in Windows Magnifier

Leave a Reply

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