I have this code that is merely trying to create a form in a DLL. I created the DLL and the form through the RAD studio Berlin IDE. I wanted to just put up a blank form to make sure it was working, unfortunately it is crashing with an EAcess violation (or alternately, an EResNotFound exception with message "Resource TSigForm can not be found"), and I can't figure out what is missing.
DLL code:
library SigDLL;
uses
System.SysUtils, System.Classes, Windows, Vcl.Forms, Vcl.Dialogs,
SignatureForm in 'SignatureForm.pas' {SigForm1};
{$R *.res}
var
SigForm: TSigForm;
procedure PrepareSigDLL(AppHandle : HWND); stdcall;
begin
SigForm := TSigForm.Create(nil); // <--------- CRASHES HERE
end;
procedure GetSignature(Variables: PChar); stdcall;
begin
ShowMessage('GetSignature called!');
end;
procedure CloseSigDLL; stdcall;
begin
ShowMessage('CloseSigDLL called!');
end;
exports
PrepareSigDLL,
GetSignature,
CloseSigDLL;
begin
end.
SigForm code:
unit SignatureForm;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs;
type
TSigForm = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
end;
var
SigForm: TSigForm;
implementation
{$R *.dfm}
end.
Generic Host app for DLL:
unit SigDllHost;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
procedure PrepareSigDLL(handle: HWND); stdcall; external 'SigDll.dll';
type
TForm2 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
procedure TForm2.Button1Click(Sender: TObject);
begin
PrepareSigDLL(Self.Handle);
end;
end.
Related
I am trying to get Country in Delphi using GetLocalInfo in Delphi.
I have this code
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;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
pcLCA:Array[0..20] of Char;
country : String;
Flag: Integer;
begin
country := GetLocaleInfo(LOCALE_USER_DEFAULT, Flag, pcLCA,19);
showmessage(country);
end;
end.
But here is the main issue, When i run it, i am getting this as error
[dcc32 Error] Unit1.pas(33): E2010 Incompatible types: 'string' and 'Integer'
on the GetLocaleInfo Line Please what am I not doing correctly. New to this.
GetGeoInfo return value is int which is incompatible with string.
While a process is running in the background, I show a loading animation on the screen. But the GIF looks very bad quality. How can I fix this problem?
unit Unit3;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Imaging.GIFImg, Vcl.ExtCtrls,
Vcl.StdCtrls;
type
TForm3 = class(TForm)
Image1: TImage;
procedure FormShow(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
var
sFile: string;
end;
var
Form3: TForm3;
aGIF: TGIFImage;
bmp:TBitmap;
implementation
{$R *.dfm}
procedure TForm3.FormShow(Sender: TObject);
begin
aGIF := TGIFImage.Create;
aGIF.LoadFromFile(sFile);
aGIF.Animate := True;
Image1.Picture.Assign(aGIF);
aGIF.Free;
end;
end.
I am using Delphi XE3. Currently there are too many functions in my unit, and one of them is very long. So I want to put that long function to another unit. Is that possible?
I try as follows:
Unit1:
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;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
procedure Test;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
...
Unit2:
unit Unit2;
interface
implementation
uses Unit1;
procedure TForm1.Test;
begin
end;
end.
But compile fails, said "[dcc32 Error] Unit1.pas(16): E2065 Unsatisfied forward or external declaration: 'TForm1.Test'"
You cannot move a class method's implementation to another unit. However, you can refactor its inner code into its own function in another unit, and then call that function from your class method, eg:
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;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
procedure Test;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses
Unit2;
procedure TForm1.Button1Click(Sender: TObject);
begin
Test;
end;
procedure TForm1.Test;
begin
Unit2.DoTest;
end;
end.
unit Unit2;
interface
procedure DoTest;
implementation
procedure DoTest;
begin
...
end;
end.
Functions belonging to the same class must be in one unit (your error reason)
your declaration and implementation must be in the same unit
if you want to split it up, you need to make them be in different classes
I'm using 2 Units in Delphi 2010: Unit1 has a Form with a TEdit and a Button, this Button will call a procedure from Unit2 (Unit2 doesn't have a form). That procedure will change the 'caption' property of the TEdit of Unit1, I tried to put Unit2 in Unit1 "Uses" to access the procedure, and put Unit1 in the "Uses" of Unit2 to to access the TEdit in Unit1, but this relation is cyclic.
I'm not sure what can I do to solve this, any suggestion?
There are many ways to do this, and which one is most appropriate depends crucially on the precise circumstances, so technically this question is too broad for Stack Overflow, I suspect.
Method 1
Still, let me just show you one very simple approach. This might not be a good approach, but it is close to what it seems you are trying to do.
Create a new VCL application.
Drop a TButton and a TEdit control on the main form (TForm1 in Unit1).
Create a new unit, Unit2:
unit Unit2;
interface
procedure SetCaption;
implementation
uses
Unit1;
procedure SetCaption;
begin
Unit1.Form1.Edit1.Text := 'Hello, World!';
end;
end.
On the main form, use this event handler for the button's OnClick event:
procedure TForm1.Button1Click(Sender: TObject);
begin
Unit2.SetCaption;
end;
after you have added Unit2 to the implementation section's uses clause. In full,
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;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
uses
Unit2;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
Unit2.SetCaption;
end;
end.
Notice how the units may use each other if referenced only in the implementation sections. Also notice we use the global Form1 variable in Unit1 to refer to the automatically created instance of TForm1. In many (most) cases, you don't want to use automatically created forms, but that is a different story (I could write a 100-page Delphi textbook here!).
Method 2
Also, let me reiterate the fact that there are many other ways to accomplish this result. For instance, this is arguably a better approach:
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;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
uses
Unit2;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
Unit2.SetCaption(Edit1);
end;
end.
unit Unit2;
interface
uses
StdCtrls;
procedure SetCaption(AEdit: TCustomEdit);
implementation
procedure SetCaption(AEdit: TCustomEdit);
begin
AEdit.Text := 'Hello, World!';
end;
end.
Method 3
Arguably even better:
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;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
uses
Unit2;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
Edit1.Text := Unit2.GetText;
end;
end.
unit Unit2;
interface
function GetText: string;
implementation
function GetText: string;
begin
Result := 'Hello, World!';
end;
end.
I'm still here with a questione about Delphi frames.
I would like to create an application that use various type of frames in order to manage different database tables, so trying to understand how to do this kind of task I've create a simple Delphi Form:
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.ExtCtrls, FramesManagement;
type
TfrmMain = class(TForm)
pnlCommands: TPanel;
pnlFrames: TPanel;
btnFrame1: TButton;
btnFrame2: TButton;
procedure FormCreate(Sender: TObject);
procedure btnFrame1Click(Sender: TObject);
procedure btnFrame2Click(Sender: TObject);
private
FFrame: IFrameManagement;
public
{ Public declarations }
end;
var
frmMain: TfrmMain;
implementation
{$R *.dfm}
uses Frame1, Frame2;
procedure TfrmMain.FormCreate(Sender: TObject);
begin
FFrame := TFramemanagement.Create;
end;
procedure TfrmMain.btnFrame1Click(Sender: TObject);
begin
FFrame.CreateGenericFrame(pnlFrames, TFrame(Frame1.TFra1));
end;
procedure TfrmMain.btnFrame2Click(Sender: TObject);
begin
FFrame.CreateGenericFrame(pnlFrames, TFrame(Frame2.TFra2));
end;
end.
This form make use of an interface declared as following:
unit FramesManagement;
interface
uses
Vcl.Forms, Vcl.StdCtrls, Vcl.ExtCtrls, Frame1, Frame2;
type
IFrameManagement = interface
['{A00E0D1B-3438-4DC4-9794-702E8302B567}']
procedure CreateGenericFrame(ParentPanel: TPanel; FrameName: TFrame);
end;
TFrameManagement = class(TInterfacedObject, IFrameManagement)
private
genericFrame: TFrame;
procedure CreateGenericFrame(ParentPanel: TPanel; FrameName: TFrame);
end;
implementation
procedure TFrameManagement.CreateGenericFrame(ParentPanel: TPanel;
FrameName: TFrame);
begin
genericFrame := FrameName.Create(ParentPanel);
genericFrame.Parent := ParentPanel;
end;
And here there are the two frames.
Frame 1:
unit Frame1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
Vcl.StdCtrls;
type
TFra1 = class(TFrame)
txtFrame1: TStaticText;
txtFrameType: TStaticText;
lblFrameType: TLabel;
private
public
end;
implementation
{$R *.dfm}
end.
and Frame 2:
unit Frame2;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
Vcl.StdCtrls;
type
TFra2 = class(TFrame)
txtFrame2: TStaticText;
txtFrameType: TStaticText;
lblFrameType: TLabel;
private
public
end;
implementation
{$R *.dfm}
end.
This is all the code, but When I run the application and I try to create the first or the second frame i receive an error like this:
I've thought the solution may be the use of generics but I don't know how to use them. Is my thought right or there is another way to reache this gol?
Can Anyone help me?
procedure TFrameManagement.CreateGenericFrame(ParentPanel: TPanel; FrameName: TFrame);
begin
genericFrame := FrameName.Create(ParentPanel);
genericFrame.Parent := ParentPanel;
end;
Here FrameName is an instance and you are calling the constructor of that instance. You are not creating a new instance as you intend to do.
You need to use meta classes.
type
TFrameClass = class of TFrame;
procedure TFrameManagement.CreateGenericFrame(ParentPanel: TPanel; FrameClass: TFrameClass);
begin
genericFrame := FrameClass.Create(ParentPanel);
genericFrame.Parent := ParentPanel;
end;
You can call this like so:
FFrame.CreateGenericFrame(pnlFrames, Frame2.TFra2);