How to 'parent' a form? (Controls won't accept focus) - delphi

I have a child form 'frmTest' and a main form 'TfrmMain'. I set the main form as parent for frmTest like this:
unit Main;
INTERFACE
USES
System.SysUtils, System.Classes, Vcl.Forms, Test, Vcl.StdCtrls, Vcl.Controls;
type
TfrmMain = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
public
end;
IMPLEMENTATION {$R *.dfm}
procedure TfrmMain.Button1Click(Sender: TObject);
VAR frmTest: TChildForm;
begin
Application.CreateForm(TChildForm, frmTest);
//frmTest:= TForm1.Create(Self);
frmTest.Parent:= Self;
frmTest.Show;
frmTest.SetFocus;
end;
unit test; { THIS IS THE CHILD }
INTERFACE
USES
System.SysUtils, System.Classes, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Samples.Spin;
TYPE
TChildForm = class(TForm)
Edit1: TEdit;
SpinEdit1: TSpinEdit;
private
public
end;
IMPLEMENTATION {$R *.dfm}
end.
Code as ZIP
But controls (edit box, spin edit, etc) in frmInsertImg will not accept focus from mouse but can be focused with Tab.
What am I doing wrong?

I suggest that you set BorderStyle to bsNone for the child form. I'm not sure of the exact reasons why this works, but it has the desired effect.
If you need to add a visual frame for your child form then that is best done with explicit UI for the contained of your child form.
Forms aren't really intended to be used in this way, in my opinion. You can make things mostly work, but it's not terribly robust. Putting the UI into a frame and then hosting that should lead to better behaviour.

Related

Setting Form Parent causes controls to be inactive [duplicate]

I have a child form 'frmTest' and a main form 'TfrmMain'. I set the main form as parent for frmTest like this:
unit Main;
INTERFACE
USES
System.SysUtils, System.Classes, Vcl.Forms, Test, Vcl.StdCtrls, Vcl.Controls;
type
TfrmMain = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
public
end;
IMPLEMENTATION {$R *.dfm}
procedure TfrmMain.Button1Click(Sender: TObject);
VAR frmTest: TChildForm;
begin
Application.CreateForm(TChildForm, frmTest);
//frmTest:= TForm1.Create(Self);
frmTest.Parent:= Self;
frmTest.Show;
frmTest.SetFocus;
end;
unit test; { THIS IS THE CHILD }
INTERFACE
USES
System.SysUtils, System.Classes, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Samples.Spin;
TYPE
TChildForm = class(TForm)
Edit1: TEdit;
SpinEdit1: TSpinEdit;
private
public
end;
IMPLEMENTATION {$R *.dfm}
end.
Code as ZIP
But controls (edit box, spin edit, etc) in frmInsertImg will not accept focus from mouse but can be focused with Tab.
What am I doing wrong?
I suggest that you set BorderStyle to bsNone for the child form. I'm not sure of the exact reasons why this works, but it has the desired effect.
If you need to add a visual frame for your child form then that is best done with explicit UI for the contained of your child form.
Forms aren't really intended to be used in this way, in my opinion. You can make things mostly work, but it's not terribly robust. Putting the UI into a frame and then hosting that should lead to better behaviour.

Resource not found when creating overridden version of Tform [duplicate]

I am writing a component and want to change the base type to a TForm however at run time I get the error "Resource TMyComp not found". I guess that this is because there is no dfm but I am not sure what to do about it.
Thanks
unit Unit65;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TMyComp = class(TForm);
TForm65 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
Mc: TMyComp;
{ Private declarations }
public
{ Public declarations }
end;
var
Form65: TForm65;
implementation
{$R *.dfm}
procedure TForm65.Button1Click(Sender: TObject);
begin
Mc := TMyComp.Create(Self);
Mc.Parent := nil;
Mc.ShowModal;
end;
end.
There is no .dfm file for TMyComp. You can avoid attempting to load the .dfm by calling the CreateNew constructor rather than Create.
Mc := TMyComp.CreateNew(Self);
From the documentation:
Use CreateNew instead of Create to create a form without using the
associated .DFM file to initialize it. Always use CreateNew if the
TCustomForm descendant is not a TForm object or a descendant of TForm.
CreateNew bypasses the streaming in of the previously-associated .DFM
file. If the form contains visual components, therefore, you must
stream in an external .DFM to bind the visual components with their
classes. If the newly created form has an external .DFM file, then you
can follow the call to CreateNew with a call to
InitInheritedComponent. If you need to create the .dfm file for the
new form instance, bracket the call to CreateNew with calls to
WriteComponentResFile and ReadComponentResFile.

Resource not found error when using TForm as base for a component

I am writing a component and want to change the base type to a TForm however at run time I get the error "Resource TMyComp not found". I guess that this is because there is no dfm but I am not sure what to do about it.
Thanks
unit Unit65;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TMyComp = class(TForm);
TForm65 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
Mc: TMyComp;
{ Private declarations }
public
{ Public declarations }
end;
var
Form65: TForm65;
implementation
{$R *.dfm}
procedure TForm65.Button1Click(Sender: TObject);
begin
Mc := TMyComp.Create(Self);
Mc.Parent := nil;
Mc.ShowModal;
end;
end.
There is no .dfm file for TMyComp. You can avoid attempting to load the .dfm by calling the CreateNew constructor rather than Create.
Mc := TMyComp.CreateNew(Self);
From the documentation:
Use CreateNew instead of Create to create a form without using the
associated .DFM file to initialize it. Always use CreateNew if the
TCustomForm descendant is not a TForm object or a descendant of TForm.
CreateNew bypasses the streaming in of the previously-associated .DFM
file. If the form contains visual components, therefore, you must
stream in an external .DFM to bind the visual components with their
classes. If the newly created form has an external .DFM file, then you
can follow the call to CreateNew with a call to
InitInheritedComponent. If you need to create the .dfm file for the
new form instance, bracket the call to CreateNew with calls to
WriteComponentResFile and ReadComponentResFile.

Event is not getting fired

I am trying to use the WebWorkerStarted and WebWorkerFinished from TWebbrowser however the events just don't get fired at all.
How can I get these events working? I want to see which worker threads are getting launched from TWebbrowser.
unit Unit2;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.OleCtrls, SHDocVw;
type
TForm2 = class(TForm)
WebBrowser1: TWebBrowser;
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure WebBrowser1WebWorkerFinsihed(ASender: TObject; dwUniqueID: Cardinal);
procedure WebBrowser1WebWorkerStarted(ASender: TObject; dwUniqueID: Cardinal; const bstrWorkerLabel: WideString);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
procedure TForm2.Button1Click(Sender: TObject);
begin
WebBrowser1.Navigate('www.stackoverflow.com');
end;
procedure TForm2.WebBrowser1WebWorkerFinsihed(ASender: TObject; dwUniqueID: Cardinal);
begin
// does not fire
end;
procedure TForm2.WebBrowser1WebWorkerStarted(ASender: TObject; dwUniqueID: Cardinal; const bstrWorkerLabel: WideString);
begin
// does not fire
end;
end.
As documented here :
By default, TWebBrowser uses IE7 Standards mode even if the run-time environment installed the latest IE (for example, IE11).
WebWorkers were introduced in IE10 so you must have IE running in a more current mode. At least two registry keys need to be set (more if supporting both 32/64 bit):
HKEY_LOCAL_MACHINE (or HKEY_CURRENT_USER)
{\Wow6432Node}
\SOFTWARE
\Microsoft
\Internet Explorer
\Main
\FeatureControl
\FEATURE_BEHAVIORS
{NEW DWORD -> 'YourApplication.exe'
{ VALUE -> 1
Also (for example, IE11 mode)
HKEY_LOCAL_MACHINE (or HKEY_CURRENT_USER)
{\Wow6432Node}
\SOFTWARE
\Microsoft
\Internet Explorer
\Main
\FeatureControl
\FEATURE_BROWSER_EMULATION
{NEW DWORD -> 'YourApplication.exe'
{ VALUE -> 0x2AF8
This will cause the internet explorer instance wraped by TWebBrowser to run in IE11 mode, supporting WebWorkers, etc. You should probably do some sort of sanity check against the installed version of IE before setting this value. More information about valid entries can be found on MSDN.
This still does not raise any WebWorker events for me when navigating to StackOverflow (are you sure it uses them?). As a verification test, this WebWorkers demo page does raise a OnWebWorkerStarted event :
WebBrowser1.Navigate('https://whatwg.org/demos/workers/primes/page.html');

Delphi: Alternative to JEDI Desktop Alert (balloon)

Is there a good analogue/equivalent to JEDI Desktop Alert (a kind of a balloon in the right bottom corner of a desktop)?
Balloon hint cannot be showed like a stack (a new hint is on the top of others), but JEDI Desktop Alert can do it.
May be some one knows, why does a show event of that component fire twice instead of once? :)
Thank your for suggestions!
This might be a bit late, but below is a basic example of showing 5 stacked alert windows on top of each other in bottom right corner, using Jedi Desktop Alert.
unit Unit1;
interface
uses
Winapi.Windows,
Winapi.Messages,
System.SysUtils,
System.Variants,
System.Classes,
Vcl.Graphics,
Vcl.Controls,
Vcl.Forms,
Vcl.Dialogs,
Vcl.StdCtrls,
JvDesktopAlert;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
procedure AddAlert(title, text: String; stack: TjvDesktopAlertStack);
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.AddAlert(title, text: String; stack: TjvDesktopAlertStack);
Begin
with TJvDesktopAlert.Create(self) do
Begin
AutoFree := true;
AlertStack := stack;
HeaderText := title;
MessageText := text;
Execute(self.Handle);
End;
End;
procedure TForm1.Button1Click(Sender: TObject);
var
stack: TjvDesktopAlertStack;
begin
stack := TJvDesktopAlertStack.Create(self);
try
AddAlert('title1', 'message1', stack);
AddAlert('title2', 'message2', stack);
AddAlert('title3', 'message3', stack);
AddAlert('title4', 'message4', stack);
AddAlert('title5', 'message5', stack);
finally
stack.Free;
end;
end;
end.
TMS Software has TAdvAlertWindow, an "Outlook 2003, 2007 style alert window".
It's a commercial component, available separately or as part of the TMS Component Pack.
Update: The above image was taken from TMS website. As Andreas has pointed the font is not antialiased (it's a bitmapped font, probably MS Sans Serif). I've tested the trial version of the component and setting the font to Tahoma works as expected:

Resources