Delphi get wrong monitor resolution over 1920x1080, why? - delphi

My delphi(7 or XE5) application is getting wrong monitor resolution when resolution is over 1920x1080.
I have a samsung ultra book with resolution of 2560x1440 running windows 8.1
When I run the simple resolution test, the app returns right at 1920x1080 and less, but when run the app with max resolution of 2560x1440 the resolution returned is 1600x900.
This is the code, I try with dpiaware manifest and get same wrong result, any idea about this ?
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function GetDesktopArea: TRect;
var
m: integer;
USCR: TScreen;
begin
USCR := TScreen.Create(Application);
try
with USCR do
if MonitorCount = 1 then
Result := WorkAreaRect
else
begin
for m:=0 to MonitorCount-1 do
begin
with Monitors[m] do
if Primary then
Result := Rect(Left, Top, Left+Width, Top+Height);
// UpdScreen.Monitors[m].BoundsRect;
end;
end;
finally
USCR.Free;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
msg : String;
scr : TRect;
begin
scr := GetDesktopArea;
msg := Format('Left:%d Top:%d -- W:%d H:%d', [scr.Left, scr.Top, scr.Width, scr.Height] );
Memo1.Lines.Add( msg );
end;
end.
Thanks

The likely explanation is that your application is not dpi aware and so experiences dpi virtualization. I know of nothing else that could influence these system API calls.
You state that you have manifested the application to be dpi aware. Since the evidence is that your app is not dpi aware then I conclude that you have applied the manifest incorrectly.
Don't ever instantiate TScreen. Use the Screen global variable instead.

Related

Is there any way in delphi to execute previously written code in a single line?

I'm a high school student taking programming as one of my subjects, so I'm rather new to Delphi.
I'm writing a game that requires the same (very long) block of code to be run when multiple different events occur. I was wondering if there was a way to write it at the beginning and call it in these different parts of the program, or perhaps get multiple senders to run the same event? The code sets the brush color of 42 different objects to different colors depending on what the user selects (the game is Risk) and when i try using a procedure it get errors for every object telling me it is undeclared.
type
TForm1 = class(TForm)
shpTerr1: TShape;
private
{ Private declarations }
public
procedure CheckOwner;
end;
var
Form1: TForm1;
iArmies, iTemp, i : integer;
iSelected, iSelectedOld : integer;
arrTerrArmies, arrTerrOwners : array[0..41] of integer;
arrPlayerColour : array[0..3] of string;
arrPlayers : array of string;
AttackMode : boolean;
implementation
{$R *.dfm}
procedure CheckOwner;
begin
shpTerr1.Brush.Color := StringToColor('cl' + arrPlayerColour[arrTerrOwners[0]]);
end;
The error is with the TShape.
Any help?
Quick answer:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls;
type
TForm1 = class(TForm)
shpTerr1: TShape;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
procedure CheckOwner;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.CheckOwner;
begin
shpTerr1.Brush.Color:= Color; // I don't know what is arrPlayerColour[arrTerrOwners[0]]
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
CheckOwner;
end;
end.

Calling a procedure with objects as arguments

Trying to save code. I want to display text etc on an image on the form at OnActivate then print the same text on clicking button (Real program is more complicated). To save writing code twice I tried the enclosed code but it won't compile at the "Obj.Canvas" line. If I comment out this line and the enclosed line the program runs but the Obj value is ().
I've tried several other approaches but none work. Can anyone tell me where I'm going wrong.
Badger
unit Unit7;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls, printers;
type
TForm7 = class(TForm)
Print: TButton;
Image1: TImage;
PrintDialog1: TPrintDialog;
procedure FormActivate(Sender: TObject);
procedure PrintClick(Sender: TObject);
private
{ Private declarations }
public
DH,DW:Extended;
Procedure DoLayout(Obj:TObject);
{ Public declarations }
end;
var
Form7: TForm7;
implementation
{$R *.dfm}
procedure TForm7.FormActivate(Sender: TObject);
begin
DoLayout(Image1);
end;
procedure TForm7.PrintClick(Sender: TObject);
begin
if PrintDialog1.Execute then
begin
printer.BeginDoc;
DoLayout(Printer);
Printer.EndDoc;
end;
end;
procedure TForm7.DoLayout(Obj:TObject);
begin
if Obj =Printer then //when you run the program Obj is ()
begin
DW:=Printer.PageWidth/Image1.Width;
DH:=Printer.PageHeight/Image1.Height;
end
else
begin
DH:=1;
DW:=1;
end;
With Obj.canvas do //Error here when compiled - tried commenting it out
begin
TextOut(Int(DH*50),Int(DW*30),'This is the text'); //commented this out too
end;
end;
end.
The TPrinter class and the TImage class don't share a common ancestor class except for TObject, as a result that's what you're passing in.
A suggested refactoring is to change the DoLayout code to accept the canvas that you want to use, as well as an parameter to determine if it's a printer or an image that you're passing in e.g.
procedure TForm7.DoLayout(aCanvas : TCanvas; bPrinter : boolean);
begin
if bPrinter then //when you run the program Obj is ()
begin
DW:=Printer.PageWidth/Image1.Width;
DH:=Printer.PageHeight/Image1.Height;
end
else
begin
DH:=1;
DW:=1;
end;
With aCanvas do
begin
TextOut(Int(DH*50),Int(DW*30),'This is the text');
end;
end;
then when you call it, use the printer canvas explicitly, or the image canvas:
DoLayout(Printer.canvas, true);
or
DoLayout(Image1.canvas, false);
this is just a rough estimation based on your code; I don't have a delphi compiler to hand to verify it.

Delphi IdIcmpclient ping error 10040 xe5

These two days I start to write some codes for ping some other devices using Delphi XE5. To my pleasure, I find there's a component named IcmpClient can be used for ping. Here's the code, mostly from some web resource.
unit main;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Samples.Spin,
Vcl.ExtCtrls, IdBaseComponent, IdComponent, IdRawBase, IdRawClient,
IdIcmpClient;
type
TfrmPing = class(TForm)
edtHost: TEdit;
btnPing: TButton;
ICMP: TIdIcmpClient;
Label1: TLabel;
Panel1: TPanel;
spnPing: TSpinEdit;
lstReplies: TListBox;
procedure btnPingClick(Sender: TObject);
procedure ICMPReply(ASender: TComponent; const ReplyStatus: TReplyStatus);
private
{ Private declarations }
public
{ Public declarations }
end;
var
frmPing: TfrmPing;
implementation
{$R *.dfm}
procedure TfrmPing.btnPingClick(Sender: TObject);
var
i: integer;
begin
ICMP.OnReply := ICMPReply;
ICMP.ReceiveTimeout := 1000;
btnPing.Enabled := False; try
ICMP.Host := edtHost.Text;
for i := 1 to spnPing.Value do begin
ICMP.Ping;
Application.ProcessMessages;
end;
finally btnPing.Enabled := True; end;
end;
procedure TfrmPing.ICMPReply(ASender: TComponent; const ReplyStatus: TReplyStatus);
var
sTime: string;
begin
// TODO: check for error on ping reply (ReplyStatus.MsgType?)
if (ReplyStatus.MsRoundTripTime = 0) then
sTime := '<1'
else
sTime := '=';
lstReplies.Items.Add(Format('%d bytes from %s: icmp_seq=%d ttl=%d time%s%d ms',
[ReplyStatus.BytesReceived,
ReplyStatus.FromIpAddress,
ReplyStatus.SequenceId,
ReplyStatus.TimeToLive,
sTime,
ReplyStatus.MsRoundTripTime]));
end;
end.
After solving the problem of Error #10013 (by giving the administrator privilege ), I met with the second error #10040.
According to one post here, some people said that happens after upgrading from xe3 to xe4, and Remy Lebeau said it was on fixing. But after a few months, we are still meeting with the errors with XE5.
Should I just abandon Indy 10 and look for some other way to PING, or waiting for the fixes?

How to create wavy text animation?

I am having one Delphi XE2 project to show scrolling text. My code is as follows :
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls;
type
TForm1 = class(TForm)
Label1: TLabel;
Timer1: TTimer;
procedure Timer1Timer(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
Label1.Caption := 'This is right scrolling text ';
Timer1.Enabled := true;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
var
S: String;
begin
S := Label1.Caption;
S := S[Length(S)] + Copy(S, 1, Length(S) - 1);
Label1.Caption := S;
end;
end.
Using the following code the text scrolls perfectly in 2d along to Y axis.
How to scroll text in Sinusoidal Wave ?
Angus Johnson's excellent GR32_Text extension to the fine graphics32 library appears to do what you need. The demos that you can download from the link above show just the effect you are asking for. All that remains is for you to animate the text in a paint box or similar control.

Get TAdvEdit.Text directly from procedure/function

Hello i get error E2197: [DCC Error] proj1.pas(34): E2197 Constant object cannot be passed as var parameter:
unit proj1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, AdvEdit;
type
TForm1 = class(TForm)
AdvEdit1: TAdvEdit;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure SetEditText(const instr: string; out outstr: string);
begin
outstr := instr;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
SetEditText('Pippo', AdvEdit1.Text);
end;
end.
Of course, i can solve writing:
procedure TForm1.Button1Click(Sender: TObject);
var sText: string
begin
SetEditText('Pippo', sText);
AdvEdit1.Text := sText;
end;
But when i have many AdvEdit, then it is hard. Then i ask, is possible solve the problem in some mode giving directly TAdvEdit.Text as parameter in mine procedure?
Thanks very much.
I presume that Text is a property. And you cannot pass a property to a var or out parameter. You can only pass variables to parameters of those kinds.
You'll need to find a different way to write your code. You've come up with one such idea, but it seems needlessly complex to me. I cannot see anything simpler than:
AdvEdit1.Text := 'Pippo';
How could there be any code simpler than this? You need to specify at a bare minimum the following:
The target control.
That we are dealing with the Text property.
The fact that we are assigning.
The new value.
The code above does that and nothing more.

Resources