I need a way to figure out if my application's mainform is an fsMDIForm.
How can this be done?
You can test Application.MainForm.FormStyle.
Assuming you want to know for the main form of another process (other then the calling application), then if you have the handle of that main form, use:
MDIActive := FindWindowEx(MainFormHandle, 0, PAnsiChar('MDICLIENT'), nil) <> 0;
I ended up with a function
function GetMovementArea: TRect;
var
MovementRect: TRect;
begin
if Application.MainForm.FormStyle = fsMDIForm then
Windows.GetWindowRect(Application.MainForm.ClientHandle, MovementRect)
else
SystemParametersInfo(SPI_GETWORKAREA, 0, #MovementRect, 0);
Result := MovementRect;
end;
This return a TRect in which my form may move around
Related
I am using multiple forms on my project. (Client Server Application) I used chat but i have some problems.
1- I have a user list on my listview. And i am open new chat form here.
procedure CreateNewChat(User: String);
var
ChatForm: TChatForm;
begin
ChatForm:= TChatForm.Create(nil);
if assigned (ChatForm) then
ChatForm.User:= User;
Chat.Socket:= MySocket; // TClientSocket new Instance
ChatForm.Show;
end;
///Chatform
procedure ParseData(Cmd:string);
begin
if Cmd <> '' then
begin
/// parsing...
end;
New connections are adding to listview like that
var
Item: TListItem;
NewTempForm: TTempForm;
begin
NewTempForm := tempForm.Create;
Item := Listview.Items.Add;
if User = '' then
Exit;
Item.Caption := User;
Item.SubItems.Add('OK');
Item.GroupId := GroupId;
Item.SubItems.Objects[0] := NewTempForm;
end;
My problems are started on here.
1- How can i detect form according to user? So, if two or higher form is open then how can i show received message on them? Because i was create them dynamically. I need a object for detect.
I tryed like that
var
tempForm: TTempForm; // this is an empty object class
sTempStr: String;
begin
if ListView.Selected <> nil then
begin
tempForm := TTempForm(ListView.Selected.SubItems.Objects[0]); // this is for unique form creation
if tempForm.frmTasks = nil then // if there is not, create!
begin
tempForm.frmTasks := TfrmTasks.Create(nil);
end;
But my received message is appear on all forms. Actually should appear just one form. (Which user sent it)
Thanks.
When showing and closing Forms in firemonkey, the application cannot remember wich form was the last activated form, and activates the wrong form.
How can I activate the last active form instead of an arbitrary form chosen by the application?
To replicate : Create 3 forms and open each one in succession from previous form.
I a mainform and 2 ChildForms, the second form is parent to the third form.
I open the first childForm from my MainForm.
var
tmpForm2:TForm2;
begin
tmpForm2:=TForm2.Create(self);
tmpForm2.Show;
end;
In this Form there is a button that shows second childform
var
form3:Tform3;
begin
form3:=TForm3.Create(nil);
form3.Show;
end;
When I open the second ChildForm and close it, the Mainform is activated. Instead of the first ChildForm
Now I repeat the process but when closing the second ChildForm, the first one is actived, as one would expect.
Next time the Mainform is again activated, so the order keeps chainging, instead of the real last active form.
Looks like it was bug in Delphi XE7/XE7 Update 1 in function
function TScreen.NextActiveForm(const OldActiveForm:
TCommonCustomForm): TCommonCustomForm;
On Delphi XE8 this function works correctly and you return to previous window.
In XE8 they rewrite function function TScreen.NextActiveForm(const OldActiveForm: TCommonCustomForm): TCommonCustomForm;
Dog-nail for XE7. I copy function from XE8 and using it before close form.
I tested it only under Windows platform.
unit ufmForm3;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls;
type
TfmForm3 = class(TForm)
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
function NextActiveForm(const OldActiveForm: TCommonCustomForm): TCommonCustomForm;
end;
var
fmForm3: TfmForm3;
implementation
{$R *.fmx}
procedure TfmForm3.FormClose(Sender: TObject; var Action: TCloseAction);
begin
NextActiveForm(Self);
end;
function TfmForm3.NextActiveForm(const OldActiveForm: TCommonCustomForm): TCommonCustomForm;
var
I, CurrIndex: integer;
begin
Result := nil;
CurrIndex := Screen.IndexFormOfObject(OldActiveForm);
if CurrIndex >= 0 then
begin
I := CurrIndex - 1;
while (I >= 0) and (Screen.Forms[I].Released or not Screen.Forms[I].Visible) do
Dec(I);
if I < 0 then
begin
I := Screen.FormCount - 1;
while (I >= 0) and (I <> CurrIndex) and (Screen.Forms[I].Released or not Screen.Forms[I].Visible) do
Dec(I);
end;
if (I >= 0) and (I <> CurrIndex) then
begin
Result := Screen.Forms[I];
Screen.ActiveForm := Result;
end;
end;
end;
end.
I had a related problem in Delphi FMX Berlin. My SDI application has a hidden "real" main form and one or more instances of the working form. When one of the working forms called a modal dialog, I was finding that on closure of the dialog, the focus was going to a form different to the calling form. The solution turned out to be simple.
(1) Create the dialog with owner Self:
MyDlg := TMyDlg.Create(Self);
MyDlg.ShowModal;
(2) Use the following in the modal dialog OnClose:
procedure TMyDlg.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := TCloseAction.caFree;
Screen.ActiveForm:=TMySDIAppForm(Self.Owner);
end;
Sorry for my bad English, first this is the logout syntax.
When I click logout, all active forms keep showing up and not closing.
procedure Tf_utama.KELUAR1Click(Sender: TObject);
begin
if MessageDlg('Logout ??',mtConfirmation,mbOKCancel,0)=mrOK
then
DATAINPUTAN1.Visible:=False;
INFODATA1.Enabled:=False;
TRANSAKSI.Enabled:=False;
LAPORAN1.Enabled:=False;
PENGATURAN1.Enabled:=False;
f_databuku:=nil;
f_rakbuku:=nil;
f_permintaan_pembeli:=nil;
f_rakbuku:=nil;
f_pengguna:=nil;
f_transaksi_penjualan:=nil;
f_transaksi_pembelian:=nil;
f_supplier:=nil;
StatusBar1.Panels[0].Text:='Nama Pengguna :';
StatusBar1.Panels[1].Text:='Hak Akses :';
end;
On each form to close I am using:
procedure Tf_caribuku.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action:=caFree;
f_caribuku:=nil;
end;
That's not how you close and free the form. You are just assigning nil to form pointers, which doesn't close them. What you have to call is TForm.Close(). Also, you have to open your if MessageDlg(... statement with begin..end; blocks if you want to execute multiple commands if statement is satisfied. So your code would look something like this:
procedure Tf_utama.KELUAR1Click(Sender: TObject);
begin
if MessageDlg('Logout ??',mtConfirmation,mbOKCancel,0) = mrOK then
begin
DATAINPUTAN1.Visible:=False;
INFODATA1.Enabled:=False;
TRANSAKSI.Enabled:=False;
LAPORAN1.Enabled:=False;
PENGATURAN1.Enabled:=False;
f_databuku.Close;
f_rakbuku.Close;
f_permintaan_pembeli.Close;
f_rakbuku.Close;
f_pengguna.Close;
f_transaksi_penjualan.Close;
f_transaksi_pembelian.Close;
f_supplier.Close;
StatusBar1.Panels[0].Text:='Nama Pengguna :';
StatusBar1.Panels[1].Text:='Hak Akses :';
end;
end;
Also, if any of forms you're trying to close is not created, I believe it will fail with AV exception. Better way to do this is to make another class which will serve as form container, e.g. TFormContainer, where you can Add and Remove forms on need. That way, upon logout, opened forms will be in TFormContainer class, and you can close them.
webView = nil
func()
function func()
webView = native.newWebView( 0, 0, display.contentWidth, display.contentHeight )
webView:request( "https://api.twitter.com/oauth/authenticate?oauth_token="..twitter_request_token )
webView:addEventListener( "urlRequest", webListener )
end
print(webView) -- webView = nil
How I can get webView outside func, which I change inside func. Help ne, please
There is (almost) nothing wrong with your example. You need to make sure to call func() after you define it, but other than that it should work. For example, this outputs something for me:
webView = nil
function func()
webView = "something"
end
func()
print(webView)
Yes, you can use explicit reference _G.webView inside the function, but there is no need to do that in your case.
If you still have an issue, it's probably because your func() is not executed when you think it is. Try to print the value of webView after it's assigned inside the function.
You can just append _G in front of your variable in will work as global variable.
Everywhere you have to use your variable with _G.
For Ex:
_G.yourVaribalename=display.newText();
You dont' need to declare variables, they are automatically global unless specified as local. And you can't call func() before func is defined. So try this:
function func()
webView = native.newWebView( 0, 0, display.contentWidth, display.contentHeight )
webView:request( "https://api.twitter.com/oauth/authenticate?oauth_token="..twitter_request_token )
webView:addEventListener( "urlRequest", webListener )
end
func()
print(webView) -- webView will not be nil
In the above, webView is global so it will exist globally as soon as created within func(), and will continue to exist after func() returns.
In InnoSetup I want to disply a ComboBox on the Finished Page which shows the Components that were installed.
You can choose "None" or any of the installed Components and start the associated program when clicking on finish.
This is my code so far:
procedure CurPageChanged(CurPageID: Integer);
var
NewComboBox1: TNewComboBox;
begin
if (CurPageID = wpFinished) then begin
NewComboBox1 := TNewComboBox.Create(WizardForm);
with NewComboBox1 do begin
Parent := WizardForm.FinishedPage;
Left := ScaleX(256);
Top := ScaleY(208);
Width := ScaleX(145);
Height := ScaleY(21);
ItemIndex := 0;
Style := csDropDownList;
Items.Add('None');
if IsComponentSelected('1') then
Items.Add('Component 1');
if IsComponentSelected('2') then
Items.Add('Component 2');
if IsComponentSelected('3') then
Items.Add('Component 3');
end;
end;
end;
First I want to set "None" as automatically selected. when the page is shown. I have looked up many Pascal forums but none of the solutions worked, like NewComboBox1.ItemSelected=0 (or similar, don't remember correctly...). So how do I achieve this?
Then I don't know how to make a program start when clicking on Finish. I thought
function NextButtonClick
might help but then no Next button worked in the setup.
Maybe there is also a problem because the list is created depending on which Components were selected, so item 1 is not Component 1, if Component 1 was not selected but Component 2 for instance.
I thought one might solve this by making the items invisible instead of not creating them at all.
I looked in the Support Classes Reference in the IS help file but didn't find anything that would help me.
I am looking forward to your answers!
There's no simple way to do this due to a lack of missing access to the file name and destination directory which the component is binded to. Even TSetupComponentEntry internal record doesn't contain this information, but even if would, you won't be able to access it. So, the following script uses its own separate array which contains the component/file linkage needed for this task:
[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={pf}\My Program
[Components]
Name: "program_32"; Description: "Program 32-bit"
Name: "program_x64"; Description: "Program 64-bit"
Name: "program_ia64"; Description: "Program IA 64-bit"
[Files]
Source: "MyProg.exe"; DestDir: "{app}"; Components: program_32
Source: "MyProg-x64.exe"; DestDir: "{app}"; Components: program_x64
Source: "MyProg-IA64.exe"; DestDir: "{app}"; Components: program_ia64
[Code]
type
TFileData = record
Component: string;
Description: string;
FileName: string;
Parameters: string;
end;
var
ComponentCombo: TNewComboBox;
ComponentArray: array of TFileData;
SelectionArray: array of TFileData;
procedure InitializeWizard;
begin
// this is a weakness of this solution - you need to fill the array
// of components that can be added to the final combo box when they
// are selected on component selection page. This is needed because
// you can't get neither file name nor destination directory of the
// file for the component from script. As first, set how many items
// you want to add to your component array storage
SetArrayLength(ComponentArray, 2);
// the Component member must match to the "Name" parameter from the
// [Components] section item since it's used in IsComponentSelected
// function call
ComponentArray[0].Component := 'program_32';
// the Description member is the text displayed in the combo item
ComponentArray[0].Description := 'Program 32-bit';
// the FileName member is the name of the file including path. This
// member may contain InnoSetup constants
ComponentArray[0].FileName := '{app}/MyProg.exe';
// the Parameters member contains execution parameters
ComponentArray[0].Parameters := '-a';
// this is the second item that can be added to the combo box, note
// that the program_ia64 component is not added to this array, what
// means, that it cannot be added to the "run" combo box. It's such
// kind of a filter for components like help files etc.
ComponentArray[1].Component := 'program_x64';
ComponentArray[1].Description := 'Program 64-bit';
ComponentArray[1].FileName := '{app}/MyProg-x64.exe';
ComponentArray[1].Parameters := '-b';
end;
procedure CurPageChanged(CurPageID: Integer);
var
I: Integer;
begin
if (CurPageID = wpFinished) then
begin
ComponentCombo := TNewComboBox.Create(WizardForm);
ComponentCombo.Parent := WizardForm.FinishedPage;
ComponentCombo.Left := ScaleX(256);
ComponentCombo.Top := ScaleY(208);
ComponentCombo.Width := ScaleX(145);
ComponentCombo.Height := ScaleY(21);
ComponentCombo.Style := csDropDownList;
ComponentCombo.Items.Add('None');
for I := 0 to GetArrayLength(ComponentArray) - 1 do
if IsComponentSelected(ComponentArray[I].Component) then
begin
ComponentCombo.Items.Add(ComponentArray[I].Description);
SetArrayLength(SelectionArray, GetArrayLength(SelectionArray) + 1);
SelectionArray[High(SelectionArray)] := ComponentArray[I];
end;
ComponentCombo.ItemIndex := 0;
end;
end;
function NextButtonClick(CurPageID: Integer): Boolean;
var
FileData: TFileData;
ResultCode: Integer;
begin
Result := True;
if (CurPageID = wpFinished) and (ComponentCombo.ItemIndex > 0) then
begin
FileData := SelectionArray[ComponentCombo.ItemIndex - 1];
Exec(ExpandConstant(FileData.FileName), FileData.Parameters, '', SW_SHOW,
ewNoWait, ResultCode);
end;
end;