Cannot use TFPColor identifier in Lazarus - pascal

I'm trying to declare a function that returns TFPColor type but I got an error message:
Error: Identifier not found "TFPColor"
function luminosity(img: TImage; i,j: Integer): TFPColor;
var
r, g, b: byte;
begin
r:= round(red(img.Picture.bitmap.canvas.pixels[i,j]) * 0.21);
g:= round(green(img.Picture.bitmap.canvas.pixels[i,j]) * 0.72);
b:= round(blue(img.Picture.bitmap.canvas.pixels[i,j]) * 0.07);
luminosity := TColorToFPColor(RGBToColor(r, g, b));
end;
I've already declared the Graphics unit in the preamble of the unit!

TFPColor is declared in the FPImage.Pas unit:
TFPColor = record
red,green,blue,alpha : word;
end;
so you need to add FPImage.Pas to your Uses list.
Btw afaics, it's not declared in any of the Delphi7 standard units.

Related

Incompatible types: 'string' and 'Boolean' [duplicate]

This question already has answers here:
Incompatible types: 'string' and 'Double'
(2 answers)
Closed last year.
I have to check for a sound card, so I don't need quality but only one answer yes or no. I used this code:
function IsSoundCardInstalled: Boolean;
Begin
Result := waveOutGetNumDevs > 0;
End;
procedure TForm1.FormCreate(Sender: TObject);
var
ids: TidIpWatch;
Speed: Double;
myStringList: TStringList;
begin
ids := TidIpWatch.Create;
Speed := GetCPUSpeed;
ids.Free;
myStringList:=TStringList.Create;
myStringList.Add('IP:' + (ids.LocalIP));
myStringList.Add('CPU: ' + (Tipo_cpu) + ' ' + Format('%f', [Speed]));
myStringList.Add((IsSoundCardInstalled));
myStringList.Add('etc.');
Memo1.Lines.Assign(myStringList);
myStringList.Free;
end;
But the error returns to me:
[DCC Error] Unit1.pas(138): E2010 Incompatible types: 'string' and 'Boolean'
On the line:
myStringList.Add((IsSoundCardInstalled));
IsSoundCardInstalled() returns a Boolean, but myStringList.Add() expects a string instead. You can't assign a Boolean as-is to a string, you need to use a conversion function (just like in your previous question), such as SysUtils.BoolToStr():
uses
..., SysUtils;
myStringList.Add(BoolToStr(IsSoundCardInstalled));
Or SysUtils.TBooleanHelper.ToString() in XE4+:
uses
..., SysUtils;
myStringList.Add(IsSoundCardInstalled.ToString);
On a side note: you are freeing the TIdIPWatch component before reading its LocalIP property, which is undefined behavior.
For that matter, you should not be using TIdIPWatch in this manner at all. It is meant for notifying you when the local IP changes, and for maintaining a history of local IP changes over time, but that is not how you have been using it lately. The TIdIPWatch.LocalIP property simply reads the global GStack.LocalAddress property, that is what you should be using instead:
uses
..., IdStack;
TIdStack.IncUsage;
try
myStringList.Add('IP:' + GStack.LocalAddress);
finally
TIdStack.DecUsage;
end;
However, a machine can have multiple local IPs, so you really should use GStack.GetLocalAddressList() instead:
uses
..., IdStack;
var
myLocalIPList: TIdStackLocalAddressList;
i: Integer;
begin
...
TIdStack.IncUsage;
try
myLocalIPList := TIdStackLocalAddressList.Create;
try
GStack.GetLocalAddressList(myLocalIPList);
for I := 0 to myLocalIPList.Count-1 do
myStringList.Add('IP:' + myLocalIPList[I].IPAddress);
finally
list.Free;
end;
finally
TIdStack.DecUsage;
end;
...
end;

Not overloading operator

Good day, I'm doing some Codeforces exercises in my free time, and I had a problem to test if the user was a boy or a girl, well, my problem isn't that, i have just demonstrated the code.
While compiling my code in my computer ( I'm using version 3.0.4 for i386 ) i get no error, but codeforces gives me this error
program.pas(15,16) Error: Operator is not overloaded: "freq(Char;AnsiString):LongInt;" + "ShortInt"
program.pas(46,4) Fatal: There were 1 errors compiling module, stopping
The error wasn't clear enough to me, as the same script was perfectly compiled with my version.
The platform is using ( version 3.0.2 i386-Win32 ).
program A236;
uses wincrt, sysutils;
var
username : String;
function freq(char: char; username : String): Integer;
var
i: Integer;
begin
freq:= 0;
for i:= 1 to length(username) do
if char = username[i] then
freq:= freq + 1;
//writeln(freq);
end;
function OddUserName(username : String): Boolean;
var
i, counter: Integer;
begin
OddUserName:= false; // even
counter:= 0;
for i:= 1 to length(username) do
if freq(username[i], username) <> 1 then
delete(username, i, 1)
else
counter:= counter + 1;
if counter mod 2 <> 0 then
OddUserName:= true; // odd
//writeln(counter);
//writeln(OddUserName);
end;
begin
readln(username);
if not OddUserName(username) then
writeln('CHAT WITH HER!')
else
writeln('IGNORE HIM!');
//readkey();
end.
The error is supposed to be at this line probably :
function freq(character: char; username : String): Integer;
Thanks for everyone who helps.
Inside of a function, the function's name can be used as a substitute for using an explicit local variable or Result. freq() and OddUserName() are both doing that, but only freq() is using the function name as an operand on the right-hand side of an assignment. freq := freq + 1; should be a legal statement in modern Pascal compilers, see Why i can use function name in pascal as variable name without definition?.
However, it would seem the error message is suggesting that the failing compiler is treating freq in the statement freg + 1 as a function type and not as a local variable. That would explain why it is complaining about not being able to add a ShortInt with a function type.
So, you will have to use an explicit local variable instead, (or the special Result variable, if your compiler provides that), eg:
function freq(charToFind: char; username : String): Integer;
var
i, f: Integer;
begin
f := 0;
for i := 1 to Length(username) do
if charToFind = username[i] then
f := f + 1;
//writeln(f);
freq := f;
end;
function freq(charToFind: char; username : String): Integer;
var
i: Integer;
begin
Result := 0;
for i := 1 to Length(username) do
if charToFind = username[i] then
Result := Result + 1;
//writeln(f);
end;

How to define operator in pascal

In my program I have a need to get percent often in code. For now i have this function to solve it
function percent(whole, part: double):double;
begin
percent:= whole * part / 100;
end;
I was wondering is there any way I could make new operator so I can write only something like: a:=100%20, and get wanted result. It would also should be able to be used as: c:=b/a; or : c:=c/a;
You can define operators in pascal, but only on record type. It is called operator overloading and you can read up here. What you do is define your own record type data, and then overload standard operators such as = < > % etc to do what you want them to do. Here is a simple example:
Interface
Type
TMyFloatType = record
value: Extended;
class operator Implicit(n: Extended): TMyFloatType;
class operator Explicit(n: Extended): TMyFloatType;
class operator Equal(a, b: TMyFloatType): Boolean;
class operator GreaterThan(a, b: TMyFloatType): Boolean;
end;
Implementation
class operator TMyFloatType.Implicit(n: Extended): TMyFloatType;
begin
result.value := n;
end;
class operator TMyFloatType.Explicit(n: Extended): TMyFloatType;
begin
result.value := n;
end;
class operator TMyFloatType.Equal(a, b: TMyFloatType): Boolean;
begin
result := (a.value = b.value);
end;
class operator TMyFloatType.GreaterThan(a, b: TMyFloatType): Boolean;
begin
result := (a.value > b.value);
end;
You can then use that like regular variables:
procedure Test;
var
a, b: TMyFloatType;
Begin
// first assign some values to a and b
a := 3.14;
b := 2.7;
if a > b then
Begin
// Do something
End;
End;
Operators that you can overload do include math operators too, like + - / * mod div etc.
Now, having said that, I do believe it wouldn't be very convenient to actually implement this to avoid a simple function, but hey, your choice.
Point here is that you can overload an operator to do your bidding. I believe to do a calculation like percentage := a % 20; you need to overload the Modulus operator.
There's no way to do this. You can only use the function
I would just use a function. By the way, your function
function percent(whole, part: double):double;
begin
percent:= whole * part / 100;
end;
is incorrect. It should be
percent := 100.0 * part / whole;

pass two difference arrays for same array

I was trying to use same printing procedure for two types of arrays(1st arry length was 10, 2nd array length was 15).
I could not find any solution over internet. Did any one have any solution for this problem.
this is the Two arrays
program pp1;
const
m=10;
n=15;
type
matrix1=array[1..m] of integer;
matrix2=array[1..n] of integer;
var
m1:matrix1;
m2:matrix2;
this is the method which it tried. in method 'x' mens the length of the array.
procedure writeMatrix(var data: array of integer ;x:integer);
var
j:integer;
begin
for j:=1 to x do
begin
write(data[j]:3);
end;
end;
my main method
begin
writeMatrix(m1,10);
writeMatrix(m2,10);
end.
How can i use the same this writeMatrix method to print both of the arrays.. Is there any stranded way to do it.
As I said in my comment before, your implementation is fine, but you have to put something in your matrix before printing it, or you will get a bunch of zeroes in the screen (in the best).
Try this:
program pp1;
const
m=10;
n=15;
type
matrix1=array[1..m] of integer;
matrix2=array[1..n] of integer;
var
m1:matrix1;
m2:matrix2;
procedure fillMatrix(var data:array of integer; x:integer);
var
j:integer;
begin
for j:= 1 to x do begin
data[j]:=j;
end;
end;
procedure writeMatrix(var data: array of integer; x:integer);
var
j:integer;
begin
for j:=1 to x do
begin
write(data[j]:3);
end;
end;
begin
fillMatrix(m1,10);
fillMatrix(m2,10);
writeMatrix(m1,10);
writeMatrix(m2,10);
readln;
readln;
end.
Hint: consider avoid using global variables, m1 and m2 in this case should be declared in the main program.
How can i use the same this writeMatrix method to print both of the arrays.. Is there any stranded way to do it.
Yes, there is a standard way to this. It is called conformant-array parameters. It is standardized in (level 1) of the ISO standard 7185 (Standard “Unextended” Pascal). It looks like this:
procedure print(protected matrix: array[
columnMinimum..columnMaximum: integer;
rowMinimum..rowMaximum: integer
] of integer);
const
totalWidth = 6;
var
x: type of columnMinimum;
y: type of rowMinimum;
begin
for y := rowMinimum to rowMaximum do
begin
for x := columnMinimum to columnMaximum do
begin
write(matrix[x, y]:totalWidth);
end;
writeLn;
end;
end;
It’s as if there were additional const values, but they are dynamic depending on the passed matrix. This code furthermore uses type inquiries (type of …) and the protected modifier, both defined in ISO 10206 (Extended Pascal) which builds on top of ISO 7185. In EP you could and would also consider schemata to pass such data as parameters.

How do I use PathCombine() from WinAPI in Pascal Script/Inno Setup?

I'm trying to figure out how to use WinAPI functions from Pascal Script/Inno Setup. I didn't find much code examples how to do it and I'm not a Pascal programmer. Here's what I did so far:
Importing the function
function PathCombine (
pszPathOut : PChar;
pszPathIn : PChar;
pszMore : PChar
) : PChar;
external 'PathCombineA#Shlwapi.dll stdcall';
and using it like this:
function InitializeSetup(): Boolean;
var
a, b,c : PChar;
s : string;
begin
SetLength(s, 256); { soon it gets working I'll switch to use MAX_PATH instead of }
a := 'C:';
b := 'one\two';
c := PathCombine(s, a, b);
MsgBox(s, mbInformation, MB_OK);
end;
The output is this:
The expected output is:
C:\one\two
I'm pretty sure I'm accessing garbage values in memory but I don't know why, how do I fix this?
You didn't specify if you are using Ansi or Unicode version of Inno Setup.
But this should work in either version:
function PathCombine(
pszPathOut : PAnsiChar;
pszPathIn : PAnsiChar;
pszMore : PAnsiChar
) : PAnsiChar; external 'PathCombineA#Shlwapi.dll stdcall';
function InitializeSetup(): Boolean;
var
a, b, c: AnsiString;
begin
SetLength(c, 256); { soon it gets working I'll switch to use MAX_PATH instead of }
a := 'C:';
b := 'one\two';
PathCombine(c, a, b);
MsgBox(c, mbInformation, MB_OK);
Result := True;
end;
Though I strongly encourage you to use Unicode version of Inno Setup and PathCombineW instead.
function PathCombine(
pszPathOut : string;
pszPathIn : string;
pszMore : string
) : Cardinal; external 'PathCombineW#Shlwapi.dll stdcall';
function InitializeSetup(): Boolean;
var
a, b, c: string;
begin
SetLength(c, 256); { soon it gets working I'll switch to use MAX_PATH instead of }
a := 'C:';
b := 'one\two';
PathCombine(c, a, b);
MsgBox(c, mbInformation, MB_OK);
Result := True;
end;
Note that Inno Setup lacks PWideChar type. While it can marshal string to LPTSTR (PWideChar) function arguments, it cannot marshal LPTSTR return value. So I've used Cardinal for return type. It has the same size as pointer (to char), so a stack will match. And we do not actually need the returned value.
I think (although I haven't worked with Pascal/Delphi for a while) that the problem is that C "strings" (char *) are 0 index based, while Pascal strings are 1 index based (byte 0 is used to store the length).
So, if you declare your s variable as:
s: array[0..255] of Char; //Don't forget to change it to MAX_PATH afterwards
it should work. Also use the PathCombine function like this:
PathCombine(s, a, b);
There's no need to assign its result (which is the same as s) to another variable (that you aren't going to use anyway).

Resources