Ah, 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.
I played with your code, some nice api functions you’v used there, they may prove useful someday. Stay productive!
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.
Hi Jerry, Can you send a screen shot – as I just tried and works as expected.
Ah, yes, I remember the original. In fact, I found the original code earlier this year on an old backup of mine. 🙂
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…
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]);