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.