TBitmap.Create not working in delphi console application - delphi

I need to process a set of bmp files using a console application, i'm using the TBitmap class, but the code doesn't compile because this error
E2003 Undeclared identifier: 'Create'
This sample app reproduces the issue
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
Vcl.Graphics,
WinApi.Windows;
procedure CreateBitMap;
Var
Bmp : TBitmap;
Flag : DWORD;
begin
Bmp:=TBitmap.Create; //this line produce the error of compilation
try
//do something
finally
Bmp.Free;
end;
end;
begin
try
CreateBitMap;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
why this code doesn't compile?

The issue is in the order of your uses clause, the WinApi.Windows and Vcl.Graphics units have a type called TBitmap, when the compiler find an ambiguous type resolves the type using the last unit of the uses list where is present. in this case use the TBitmap of the Windows unit which points to the BITMAP WinAPi structure , to resolve this change the order of your units to
uses
System.SysUtils,
WinApi.Windows,
Vcl.Graphics;
or you can declare the type using the full qualified name like so
procedure CreateBitMap;
Var
Bmp : Vcl.Graphics.TBitmap;
Flag : DWORD;
begin
Bmp:=Vcl.Graphics.TBitmap.Create;
try
//do something
finally
Bmp.Free;
end;
end;

Related

How to read an unknown type file of unknown size

I need to read the content of an unknown type and size file and temporary save it (in some kind of variable) so I use it later for transferring through serial port. As far as I understand, TFileStream is the right approach.
I did try implementing the following tutorial from http://docwiki.embarcadero.com/CodeExamples/Tokyo/en/TReader_(Delphi)
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Utils;
type
TForm1 = class(TForm)
procedure OnCreate(Sender: TObject);
private
selectedFile: string;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.OnCreate(Sender: TObject);
function ReadFileContent(fileName: String): String;
var
FileStream: TFileStream;
Reader: TReader;
tByte :byte;
begin
FileStream := TFileStream.Create(fileName, fmOpenRead);
Reader := TReader.Create(FileStream, $FF);
Reader.ReadListBegin; //I get 'Invalid property Value' error
//in this line raised from the Reader object
while not Reader.EndOfList do
begin
Reader.ReadVar(tByte, 1);
end;
Reader.ReadListEnd;
Reader.Destroy;
FileStream.Destroy;
end;
var
dlg: TOpenDialog;
begin
selectedFile := '';
dlg := TOpenDialog.Create(nil);
try
dlg.InitialDir := '.\';
dlg.Filter := 'All files (*.*)|*.*';
if dlg.Execute(Handle) then
selectedFile := dlg.FileName;
finally
dlg.Free;
end;
if selectedFile <> '' then
ReadFileContent(selectedFile);
end;
end.
Is there anything else I need to set for the Reader object to work properly or I should use a different approach?
I need to read the content of an unknown type and size file and save
it into a string.
Since you want to save it in a string, either
the file is a text file, or
you are doing it wrong (a string can only store textual data).
Assuming the first option, you can simply do
MyStringVariable := TFile.ReadAllText('C:\myfile.txt');
(uses IOUtils).
There is also an overload of ReadAllText that you can use to specify the encoding (e.g., UTF-8 or UTF-16LE).
Update. The question was edited and now reads
I need to read the content of an unknown type and size file and save it.
Do you simply want to copy a file? If so, you can use any of the file-copying methods that are available, such as the CopyFile Win32 function, TFile.Copy from IOUtils, and many more.
Or do you want to obtain the bytes of the file so you can process it in your application? If so, my original answer is close to what you need. Just use ReadAllBytes instead of ReadAllText:
MyDynamicByteArray := TFile.ReadAllBytes('C:\logo.bmp');
where MyDynamicByteArray is a dynamic array of bytes (TArray<Byte>, that is, array of byte).

Using Windows clipboard in Delphi console program

I am trying to use the (Windows) clipboard in a Delphi console program, but when I try to compile I get the message
"[dcc32 Fatal Error] Clipboard_Project.dpr(6): F2613 Unit 'Clpbrd' not found."
The code looks like this:
program Clipboard_Project;
{$R *.res}
uses
System.SysUtils, Clpbrd;
var
s: String;
begin
try
s := Clipboard.AsText;
writeln(s);
readln;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
I can imagine that it's something simple and obvious, but I can't find it! Any help would be appreciated!
for correction of this question, it should be used in the uses clause Vcl.ClipBrd correctly and not Clpbrd as incorrectly typed.

GetProcAddress fails to run when compiled under Delphi XE6 x64

The following GetProcAddress code fails when compiled under Delphi XE6 x64. It runs fine when compiled under Delphi x86. Could you help to comment what is done wrong ?
program Project11;
{$APPTYPE CONSOLE}
{$R *.res}
uses
SysUtils;
var
Library_OpenGL: LongWord;
function LoadLibrary(lpFileName: pAnsiChar): LongWord; stdcall; external 'kernel32.dll' name 'LoadLibraryA';
function GetProcAddress(hModule: LongWord; lpProcName: pAnsiChar): Pointer; stdcall; external 'kernel32.dll' name 'GetProcAddress';
begin
try
Library_OpenGL := LoadLibrary('opengl32.dll');
Assert(GetProcAddress(Library_OpenGL, 'glEnable') <> nil, 'GetProcAddress(Library_OpenGL, ''glEnable'') = nil');
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
ReadLn;
end.
Your translations are wrong. A module handle is pointer sized which explains why your erroneous translations worked on 32 bit but not 64 bit.
To correct, add the Windows unit to your uses clause, remove your declarations of LoadLibrary() and GetProcAddress(), and declare Library_OpenGL as HMODULE (which is 8 bytes in x64):
program Project11;
{$APPTYPE CONSOLE}
{$R *.res}
uses
SysUtils, Windows;
var
Library_OpenGL: HMODULE;
begin
try
Library_OpenGL := LoadLibrary('opengl32.dll');
Assert(GetProcAddress(Library_OpenGL, 'glEnable') <> nil, 'GetProcAddress(Library_OpenGL, ''glEnable'') = nil');
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
ReadLn;
end.
As an added benefit you now call the native Unicode LoadLibraryW directly rather than going via the LoadLibraryA adapter with its conversation from ANSI to the system native UTF-16.

Save a IXMLDOMDocument3 to xml-file in runtime with Delphi 2007

If I would like to save a IXMLDOMDocument3 in runtime to a file on my harddrive, what is the syntax for that?
E.g. like IXMLDOMDocument3.save('c:\test.xml')
Or is it even possible?
Best regards!
the sample code below demonstrates how to load and save IXMLDomDocument3 XML at runtime. It uses msxml header file from Delphi-2010. IXMLDomDocument3 inherits from IXMLDomDocument and has Save method (as you wrote in your question). If method parameter is a string, then it specifies file name (it creates or replaces target file).
program Project3;
{$APPTYPE CONSOLE}
uses SysUtils, msxml, comObj, activex;
procedure LoadAndSaveXML(LoadFile, SaveFile : string);
var xml : IXMLDOMDocument3;
tn : IXMLDOMElement;
begin
xml := CreateComObject(CLASS_DOMDocument60) as IXMLDOMDocument3;
xml.load(LoadFile);
xml.save(SaveFile);
end;
begin
try
CoInitialize(nil);
try
LoadAndSaveXML('D:\in.xml', 'D:\out.xml');
finally
CoUninitialize();
end;
except
on E: Exception do begin
Writeln(E.ClassName, ': ', E.Message);
readln;
end;
end;
end.

Getting the whole list of classes and objects defined in a unit using RTTI

I want to get the whole list of classes defined in a specific unit
How can I get the list of all instances of those classes, irrespective of where they are created?
First before to answer your question, remember always include your delphi version in questions related to the Rtti.
1) Asumming which you are using a new version of delphi (>=2010) you can get the unit name of a type using the QualifiedName property , from there you must check the IsInstance property to determine if is a class.
Check the next sample.
{$APPTYPE CONSOLE}
{$R *.res}
uses
Rtti,
System.SysUtils;
procedure Test;
Var
t : TRttiType;
//extract the unit name from the QualifiedName property
function GetUnitName(lType: TRttiType): string;
begin
Result := StringReplace(lType.QualifiedName, '.' + lType.Name, '',[rfReplaceAll])
end;
begin
//list all the types of the System.SysUtils unit
for t in TRttiContext.Create.GetTypes do
if SameText('System.SysUtils',GetUnitName(t)) and (t.IsInstance) then
Writeln(t.Name);
end;
begin
try
Test;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.
2) The Rtti can't list the instances of the classes. because the Rtti is about type information and not of instances.
Question 1
The following code does what you ask, relying on the new RTTI introduced in Delphi 2010:
program FindClassesDeclaredInUnit;
{$APPTYPE CONSOLE}
uses
SysUtils, Rtti, MyTestUnit in 'MyTestUnit.pas';
procedure ListClassesDeclaredInNamedUnit(const UnitName: string);
var
Context: TRttiContext;
t: TRttiType;
DeclaringUnitName: string;
begin
Context := TRttiContext.Create;
for t in Context.GetTypes do
if t.IsInstance then
begin
DeclaringUnitName := t.AsInstance.DeclaringUnitName;
if SameText(DeclaringUnitName, UnitName) then
Writeln(t.ToString, ' ', DeclaringUnitName);
end;
end;
begin
ListClassesDeclaredInNamedUnit('MyTestUnit');
Readln;
end.
unit MyTestUnit;
interface
type
TClass1 = class
end;
TClass2 = class
end;
implementation
procedure StopLinkerStrippingTheseClasses;
begin
TClass1.Create.Free;
TClass2.Create.Free;
end;
initialization
StopLinkerStrippingTheseClasses;
end.
Question 2
There is no global registry of object instances.

Resources