Delphi: GetCursorPos problem on Windows 8.1 with scaling
Question by Guest | 2015-07-19 at 04:14
I have an application which is written in Delphi 5 and has been working well for years.
I now have a problem on systems running windows 8.1 with high definition screens where scaling is set higher than 100%.
Part of the application allows the user to select the color of individual pixels on an image.
To make it easier I use a zoom box which displays a zoomed section of the main image.
When the cursor is over the main image, a smaller zoomed image with a crosshair is displayed.
When screen scaling is active, the zoom box no longer displays the area surrounding the cursor position but rather seems to be relative to the 0,0 point of the screen.
Here is the code I am using.
procedure TAutoFillForm.Timer1Timer(Sender: TObject);
var
Srect, Drect, DisplayArea: TRect;
iWidth, iHeight, DmX, DmY: Integer;
iTmpX, iTmpY: Real;
C: TCanvas;
hDesktop: Hwnd;
CursorPosition, ImageLoc: TPoint;
Col, CrossHairCol: TColor;
MaxWidth, MaxHeight, iTop, iLeft: Integer;
DC: HDC;
ImageRect:Trect;
begin
If not IsIconic(Application.Handle) then begin
hDesktop:=GetDesktopWindow;
GetCursorPos(CursorPosition);
ImageLoc:=Image1.ClientToScreen(Point(0,0));
// Label9.Caption:= 'Cursor X = ' +
// IntToStr(CursorPosition.x) +
// ' : Cursor Y = ' + IntToStr(CursorPosition.Y) +
// ' : ScreenDPI = ' + IntToStr(ScreenDPI) +
// ' DPI = ' + IntToStr(Screen.PixelsPerInch) +
// ' Image X = ' + IntToStr(ImageLoc.x) +
// ' Image Y = ' + IntToStr(ImageLoc.y);
MaxWidth:=Image1.Width;
MaxHeight:=Image1.Height;
DisplayArea:=Rect(ImageLoc.x,ImageLoc.y,
ImageLoc.x+MaxWidth,ImageLoc.y+MaxHeight);
If (PtInRect(DisplayArea,CursorPosition))
and (CheckBox2.Checked) then
begin
If Image2.Visible=False then Image2.Visible:=True;
iWidth:=Image2.Width;
iHeight:=Image2.Height;
Drect:=Rect(0,0,iWidth,iHeight);
iTmpX:=iWidth / (TrackBar1.Position * 4 );
iTmpY:=iHeight / (TrackBar1.Position * 4);
GetCursorPos(CursorPosition);
Srect:=Rect(CursorPosition.x,CursorPosition.y,
CursorPosition.x,CursorPosition.y);
InflateRect(Srect,Round(iTmpX),Round(iTmpY));
// move Srect if outside visible area of the screen
If Srect.Left<0 then OffsetRect(Srect,-Srect.Left,0);
If Srect.Top<0 then OffsetRect(Srect,0,-Srect.Top);
If Srect.Right>Screen.DesktopWidth then
OffsetRect(Srect,-(Srect.Right-Screen.DesktopWidth),0);
If Srect.Bottom>Screen.DesktopHeight then
OffsetRect(Srect,0,-(Srect.Bottom-Screen.DesktopHeight));
C:=TCanvas.Create;
try
C.Handle:=GetDC(0);
Image2.Canvas.CopyRect(Drect,C,Srect);
finally
ReleaseDC(hDesktop, C.Handle);
C.Free;
end;
If CheckBox2.Checked=True then begin // show crosshair
with Image2.Canvas do begin
DC := CreateDC('DISPLAY',nil,nil,nil);
Col := GetPixel(DC,CursorPosition.X,CursorPosition.Y);
DeleteDC(DC);
// set color to be visible over current area
CrossHairCol:=MainForm.VisibleContrast(Col);
Image2.Canvas.Pen.Color:= CrossHairCol;
DmX:=TrackBar1.Position * 2 * (CursorPosition.X-Srect.Left);
DmY:=TrackBar1.Position * 2 * (CursorPosition.Y-Srect.Top);
MoveTo(DmX - (iWidth div 8),DmY); // -
LineTo(DmX + (iWidth div 8),DmY); // -
MoveTo(DmX,DmY - (iHeight div 8)); // |
LineTo(DmX,DmY + (iHeight div 8)); // |
end; // with image1.Canvas
end; // show crosshair
Application.ProcessMessages;
end // Cursor not inside area
else begin // cursor inside area
If Image2.Visible=True then Image2.Visible:=False;
end;
end; // IsIconic
end;
Thanks in advance for your help.
Related Topics
Delphi/Lazarus: Retrieve Cursor Position relative to Form/Window
Tip | 0 Comments
Windows: How to make Hibernation available
Tutorial | 0 Comments
Windows Batch Script: Computer Shutdown
Tutorial | 2 Comments
Lazarus: Detect Operating System (Compiler Switch)
Tutorial | 0 Comments
Delphi: System-Wide HotKey
Tutorial | 1 Comment
Put Windows via Script into Hibernation or Sleep Mode
Tutorial | 1 Comment
Original Delphi is too expensive - Are there Alternatives?
Question | 3 Answers
Important Note
Please note: The contributions published on askingbox.com are contributions of users and should not substitute professional advice. They are not verified by independents and do not necessarily reflect the opinion of askingbox.com. Learn more.
Participate
Ask your own question or write your own article on askingbox.com. That’s how it’s done.
What do you mean with "seams to be relative to the 0,0 point of the screen"?
I can imagine that you have to use a factor for the right pixel position. When the image is scaled, a normal pixel from before is more than one 100 percent pixel. So, perhaps, you have to read out the scale factor and adjust this to display the right position.
By the way, you are talking about Windows 8.1. Have you also tested the scaling on other Windows versions?
2015-07-20 at 02:21