My application is based on modal forms. Main form opens one form with ShowModal, this form opens another with ShowModal, so we have stacked modal forms. There is sometimes a problem that when we call ShowModal in new form, it hides behind previous forms, instead of showing on top. After pressing alt+tab, form comes back to the top, but this is not good solution. Did You meet this problem and how did you handle it?
EDIT:
I use Delphi 7.
LukLed
LukLedLukLed27k17 gold badges72 silver badges101 bronze badges
6 Answers
![Open remote desktop windows 10 Open remote desktop windows 10](/uploads/1/2/3/3/123379639/557385057.png)
You didn't mention which version of Delphi..
Newer Delphi versions have added two new properties to TCustomForm: PopupMode and PopupParent. Setting PopupParent of your modal dialog to the form that's creating that dialog makes sure that the child form stays on top of it's parent. It usually fixes the problem you're describing.
I think this pair of properties were added in Delphi 2006, but it may have been 2005. They're definitely there in Delphi 2007 and up.
EDIT: After seeing you're using Delphi 7, the only suggestion I have is that, in the code that displays your modal form, you disable the form creating it, and re-enable on return. That should prevent the creating window from receiving input, which may help keep the Z-order correct.
Something like this may work (untested, as I'm no longer using D7):
If Form2 creates a modal window (as you've mentioned), just repeat the process - disable Form2, create Form3 and show it modally, and re-enable Form2 when it returns. Make sure to use try.finally as I've shown, so that if something goes wrong in the modal form the creating form is always re-enabled.
LukLed![Open Open](/uploads/1/2/3/3/123379639/637191569.png)
27k17 gold badges72 silver badges101 bronze badges
Ken WhiteKen White109k11 gold badges165 silver badges337 bronze badges
Sorry for adding a separate answer, but I have done a bit more research, and some of it indicates that my previous answer (DisableProcessWindowsGhosting) doesn't help. Since I can't always reproduce this issue, I cannot say for sure.
I found a solution that appears to appropriate. I referenced the code in Delphi 2007 for the CreateParams method and it matches pretty close (without having all of the other code that handles PopupMode).
I created the unit below which subclasses
TForm
.What I do then is include this unit in with a form unit, and then change the form's class (in the .pas code file) from
class(TForm)
to class(TModalForm)
It works for me, appears to be close to CodeGear's solution.
Jim GilmartinJim Gilmartin
From this link it appears that the problem is with the 'Ghosting window' that was introduced in 2000/XP. You can disable the ghosting feature by calling the following code at startup.
The only issue that I can see is that it will cause problems with the feature that allows for the user to minimize, move, or close the main window of an application that is not responding. But in this way you do not have to cover each call with the
Self.Enabled := False
code.Jim GilmartinJim Gilmartin
Just set the
Visible
property of the form, that you want to open modal, to False
. Then you can open it with .ShowModal();
and it will work.H. Gokhan MamaciH. Gokhan Mamaci
Mayank Jain4,0804 gold badges25 silver badges59 bronze badges
DmitryDmitry
I have found that using the 'Always On Top' flag on more than one form causes problems with the Z order. And you may also find the need for the
BringWindowToTop
function.When launching a message box using the built-in WinAPI (
Scott WScott WMessageBox
), I have found that passing the calling window's handle is necessary in order to make sure that the the prompt appears on top all the time.8,8702 gold badges30 silver badges50 bronze badges
Not the answer you're looking for? Browse other questions tagged delphidelphi-7 or ask your own question.
- LangTools it's a complex tool for Delphiapplication localization. It contains VCL components, editors and wizards built-in Delphi and external language file editor.
- LangTools_f.exe
- CodresTeam
- Freeware (Free)
- 4.01 Mb
- Windows
- Balmsoft Polyglot contains components for localization your Delphiapplication. It contains IDE extension for generation files with localizable items and componentsfor applying files with localization. You can translate any localizable property and. ..
- Balmsoft Polyglot
- Balmsoft
- Freeware (Free)
- Win95, Win98, WinME, WinXP, WinNT 4.x, Windows2000
- This is a port of EPANET to the Lazarus platform. EPANET if a Windows Delphiapplication, so it won't run natively on other operating system. Once the port if finished it will be able to run on every platform that Lazarus. ..
- TMWPrintObject.zip
- epanet2lazarus
- Freeware (Free)
- 98 Kb
- Windows; Linux
- The OpenCTF component test framework helps to build automatic tests for all (visual and non-visual) VCL components in a Delphi application. It is based on the DUnit framework.
- OpenCTF-1.4.3-source.zip
- openctf
- Freeware (Free)
- 418 Kb
- Windows
- I made two Delphiapplication that allow you to send fax directly over HylaFax or I made two Delphi application that allow you to send fax directly over HylaFax or Ms-Fax.
- fax.zip
- sendfaxdirectly
- Freeware (Free)
- 76 Kb
- Windows
- Utf8Vcl allows your Delphiapplication to become a unicode applications with no changes to your vcl code and third party Utf8Vcl allows your Delphi application to become a unicode applications with no changes to your vcl code and third party components.
- utf8vcl-example-070319.zip
- sourceforge
- Freeware (Free)
- 16 Kb
- Windows
- LinLocalize is a small, easy to use application specially designed to help you with the easy localization of your Delphi-applications. Linlocalize extracts all embedded Delphi-resources (resource strings and forms) of a Windows-PE-file (Portable. ..
- LinLocalize_1.4.zip
- LinLocalize Team
- Freeware (Free)
- WindowsAll
- Express Invoice Free for Mac can help you manage and track your billing. Create invoices, quotes and orders quickly. Easily add multiple users and enable online remote access.
- eifreemaci.zip
- NCH Software
- Freeware (Free)
- 2.02 Mb
- Mac OS X, Mac Other
- Delphi Unicode MySQL ADO Tutorial for Beginners. This tutorial shows you how to make a Delphi application which manages a unicode database.Steps:- Create a new database from code - Create tables with unicode fields from code - Fill table with unicode data from code - Query the database and display the results in a TDBGrid and TMemo.
- Unicode MySQL ADO Tutorialfor Beginners 1.0.zip
- 3delite
- Freeware (Free)
- 552 Kb
- WinXP, Win2003, Win2000, Win Vista, Window2008, Windows 7, Windows XP X64,Windows Vista, Windows 7 x64, Windows 8
- Solves application compatibility on Remote Desktop Session Hosts / Terminal Servers The Microsoft Application Virtualization (App-V) for RDS will help solve application compatibility on Remote Desktop Session Hosts/Terminal Servers. App-V for RDS 4.
- MS App-V for RDS v4.6.iso
- Microsoft
- Freeware (Free)
- 197.44 Mb
- Win All
- It's an Open Source project to help develop Database Applications with Delphi. It gives you a DB Application FrameWork inside which you can 'load' your modules and a DB Application Library you can use to 'inherit' and 'customize' your. ..
- ddaf_sources_0.0.1.zip
- ddaf
- Freeware (Free)
- 10 Kb
- Windows
- This is a server based application that has been extended to include calendar functionalities.
- Remote SchedulingApplication (RSA)
- Owajigbanam Ogbuluijah
- Freeware (Free)
- Windows
Related:Delphi Application Remote - Remote Ir Delphi - Ti Remote Application - Tv Remote Application - Delphi Remote Admin
Pages : 1 | 2 | 3>
The only way I see is to add flag for this, but is this the best way?
When the form is destroyed and I check if(Assigned(form2)) the result is true? Why?
What is the way to do this?
John White
John WhiteJohn White
5 Answers
You can use Form1.Showing to see if a form is closed or not.
Just closing a form does not free it unless you set
Mikael ErikssonMikael ErikssonAction := caFree
in OnClose
event. Default is caHide
.118k19 gold badges163 silver badges234 bronze badges
Wow, a blast from the past :)
The way that Assigned() works, is that it basically does nil check on the pointer. If you destroy form2, there will still be a memory address that form2 points to.
I has been a very long time since I've done any Delphi, but from memory, you need to manually set the form2 var to nil when it is destroyed. If you have a central place (eg. a form broker?) where you create & destroy forms, this should be quite easy.
Raymond BarlowRaymond Barlow
If you use
Form1.Free
or Form1.Destroy
, Delphi will destroy the object but wont set the object reference to nil. So instead use FreeAndNil
.For more information, check Andreas Rejbrand answer in this link
Community♦
BharatBharat5,8762 gold badges26 silver badges53 bronze badges
Faced with the same issue when doing some routine on closing application. In this case all forms are destroyed behind the stage but pointers are not set to nil. This code helphs me:
Open Remote Desktop Connection Manager
So pointer becomes nil and I can check it with
Assigned
or compare to nil
.![Delphi Delphi](/uploads/1/2/3/3/123379639/380255016.jpg)
Alexander ZaripovAlexander Zaripov
Just as a tip, the correct way to do it in some special cases is to create a timer that do the nil assign to the variable.
I will explain it (somehow it is complex), if you create your form within your own code
MyForm:=TMyForm.Create
and you have a MyFrom.Close
it is very easy, just add a MyForm:=nil
or also better MyForm.FreeAndNil
.. but sometimes the reference is not anyware.Sample: You create inside a procedure, on a loop a lot of copies of the same form (or just one), let the form open and end that procedure, now the reference to the opened form is nowhere, so you can not assign nil or do a freeandnil, etc., in a normal way.
For that cases, the trick is to use a timer (of just one milisecond) that do it, that timer needs the reference, so you must store on a global like the reference to Self, all that can be done on the on close event.
The easiest way to do the free (when no reference anywhere) is to create a TObjectList on the main form, so it will hold all form references that needs to be free, and define a timer (one milisecond) that will go through that list doing the freeandnil; then on the onlcose you add
Self
to that list and enable that timer.Now the other part, you have a normal form that is auto created on start, but you need to set it to nil and re-create it on your own code.
Just who is this Womble person?' InfoThis is the subreddit of the internationally celebrated Youtuber SovietWomble.NOT the show The Wombles, that's a totally different sub.' He may not exist. Arma 3 compass mod 2. , you might ask. Simply put, we just don't know.
That case has a global that point to that form, so you only need to free and nil it, but NOT (i say it loud) on any part inside the own form code, you must do it OUT (i say if loud) of the form code.
Some times you will need to free the form, when user close it, and it is not shown in modal, this case is complex, but again the same trick is valid, on the onclose event you enable a timer (that is out of that form, normally on main form) adn that timer will free and nil. That timer interval can be set as just one milisecond, it will not be run until form has totally closed (please have in mind not using Application.ProcessMessages, that is normally a really bad idea).
If you set Self to nil, free or whatever inside the own form, you can corrupt your application memory (doing that is totally unsafe, not to mention it can eat ram).
The only way to free a form (and nil its reference), a form that is not shown as modal and is the user who close it, is to program a trigger that do that after the form is totally closed.
I know about setting action to do the free, but to set it to nil there is no other safe way.
Must say: If you use timers on your main form, run a
Enabled:=False
on all of them on the Onclose event.. otherwise weird things may occur (not allways, but sometimes.. race conditions about destroying application and running code on that timers), and of couse if some one was enabled act correctly to terminate it correctly or abort it, etc.Your question is one of the complex things to do.. free and nil a form that is closed not by code, but by user action.
For all the rest: Think like if the application has at the same time a lot of forms opened and all can interact with the user at the same time (anyone is modal), and you have code that references some of them from the others.. you need to know f user has closed any form to avoid accesing that form from code. This is not trivial to be done unless you use timers.
If you have a 'central' form (like an MDI application) you can put that timer on the main MDI form, so any child form that is closed can be freed and nil, the trick is again a timer on that main form.
Only and only if you are sure you can free and nil all non visible forms, you can have a timer on the main form that goes through all forms and if Visible is false, then call FreeAndNil, i consider this way prone to errors, since if you add on a future a form that must not be freed but can stay hidden.. this code will not be valid.
Allways remember that if is the user the onw who closes the form that must be freed and nil, there is no way on code to detect and act, no event is launched (after the form is totally closed) and before the form is totally closed you must not even try to free it or nil its reference, weird things can occur (more prone to that if motherboard has more than one socket, also more if your app uses threads, etc).
So, for threaded apps (and also not threaded) i use another method that works great and do not need timers, but need double checking prior to each
ThatForm.*
, the trick is to define a Form bolean public variable like as PleaseFreeAndNilMe
on the public section on the form, then on the onclose (as last line) set it to True and on the OnCreate set it as False.That way you will know if that form had been closed or only hidden (to hide a form never call close, just call hide).
So coded will look like (you can use this as a warper, instead of defining forms as TForm define them as TMyform, or also better, use a hack like
type TForm=class(Forms.TForm)
instead of TMyForm=class(TForm)
just to have that variable added to all forms):If you preffer hacked version:
But as i said, prior to access any member (or just where you do the nil compare) just call a 'global' function passign the reference (no matter if it was nil or not), coded as:
So where you do
if nil=MyForm then ..
you can now do if (IsNilTheForm(MyForm)) then ..
.That is it.
It is better the timer solution, since form is freed as soon as possible (less ram used), with the
PleaseFreeAndNilMe
trick the form is not freed until IsNilTheForm
is called (if you do not free it any where else).That
IsNilTheForm
is so complex because it is considering all states (for a multi socket motherboard and threaded apps) and letting the code free / nil it anywhere else.Of course, that function must be called on main thread and in atomic exclusion.
Free a Form and Nil its pointer is not a trivial thing, most when user can close it at any time (since no code out of the form is fired).
The big problem is: When a user closes a form there is no way to have a event handler that is triggered out of that form and after the form ends all things it is doing.
Imaigne now that the coder has put a lot of Application.ProcessMessages; every where on the app, also on that form, etc.. and has not taken the care for race conditions.. try to free and nil such a form after the user asks it to be closed.. this is a nightmare, but can be solved with the hacked version of TForm that has a variable that tells that the form has not been freed but wants it.
Now imagine you use hacked TForm and want a normal TForm, just define it as
..= class(Forms.TForm)
, that way it will now have that extra variable., so calling IsNilTheForm
will act as comparing to nil.Hope this helps VCL coders to FIX such things, like raising an event when an object is destroyed, freed, niled, hide, etc.. out of the code of that object, like on main form, etc. That would make live easier.. or just fix it.. Close and Free implies set to Nil all refences that point to it.
Open Remote Desktop Windows 10
There is another thing that can be done (but i try to allways avoid it): Have multiple variables that point to the exact same form (not to copies ot it), that is prone to a lot of errors, you free one and need to nil all of them, etc.. The code i show is also compatible with that.
I know the code is comples.. but Free and Nil a form is more complex than my code.
claudioclaudio
Not the answer you're looking for? Browse other questions tagged delphiformsvcl or ask your own question.
I want my application to always start on the left monitor (in case that there are more than 1 connected).
How can this be done? How to detect the left monitor number?
Thanks for helping!
ChrisChris
1 Answer
We use this code fragment:
Then _MonitorNum holds the number of the left most monitor.
penarthur66penarthur66
Got a question that you can’t ask on public Stack Overflow? Learn more about sharing private information with Stack Overflow for Teams.
Not the answer you're looking for? Browse other questions tagged delphimultiple-monitors or ask your own question.
Right now i have 2 forms. On Form1 i open up Form2 like this:
Now i want to close the Form2 with a button on it. So i tried
But that only gives me Access violation error when i click that button. What i am doing wrong?
hs2dhs2d2,28013 gold badges56 silver badges88 bronze badges
5 Answers
The normal way to do this is to do
and, if
TForm2
contains a OK button, this should have the ModalResult
property set to mrOK
at design-time. Use the object inspector to set this. You probably also want to set Default
to True
. Now you can 'click' the OK button by pressing the Enter key on your keyboard!In addition, if there is a Cancel button in the dialog, this should have
ModalResult
set to mrCancel
and Cancel
set to True
. Now you can 'click' the Cancel button by pressing the Escape key on your keyboard!A button with a
Andreas RejbrandAndreas RejbrandModalResult
value will automatically close a modal dialog box.74.2k6 gold badges219 silver badges310 bronze badges
Since the form is showing modally the correct solution is to set
ModalResult := mrCancel
in your button click handler. The shortcut is to set the ModalResult
property of the button to mrCancel
and then you don't even need the event handler.Note that your form is being created incorrectly. You are passing the unassigned variable
Form2
as the Owner
parameter to the constructor. I expect this is the cause of the access violation.You should pass another form,
Application
or nil
, for example. In fact in this case you may as well pass nil so that the code should read:If you pass an owner then the form will be destroyed when the owner is destroyed. Since you are destroying it yourself, you don't need to pass an owner.
That said, it is sometimes useful to set the owner, for example if you are using one of the
David HeffernanDavid HeffernanPostion
property values that sets the form's position based on the owner's position. If so then I recommend passing Self
in this instance which is a TForm1
object reference.529k35 gold badges865 silver badges1260 bronze badges
The other two answers discuss other ways to solve your problem.
I am going to point out the cause of the problem.
You have two variables named Form2. One contains the form and the other is uninitialized most likely Nil. The cause of the A/V is because your accessing the Nil variable.
When working with in a class you should avoid using the variable name of the class instead you can reference it's members directly such as calling
Robert LoveRobert LoveClose;
without referencing the variable. To keep things clear you can also prefix it with self.
so replace form2.close;
with self.close;
10.9k2 gold badges43 silver badges71 bronze badges
In your second code, you're already in form 2, so you would only need to do
If in your first code you created a variable you didnt use the generic Form2 variable made as a public variable in the form, its not then allocated to the form you called. So it will give errors. If at the top of the unit, you removed the 'var Form2: TForm2;' line, you'd see it complain about the lack of variable for that line, change it to close, it will go away and so will your error.
Remy Lebeau354k19 gold badges286 silver badges480 bronze badges
BugFinderBugFinder14.3k2 gold badges30 silver badges46 bronze badges
I don't know if you already resolved that question or created a new code to avoid the problem, but what I think is happening (and you didn't showed all your code to confirm) is that you created bad code on the OnActivate main form event.
When you exit the second form, you return to your mainform and it 'actvates' again.Probably you manipulated an object that do not exists anymore.
Please_Dont_Bully_Me_SO_LordsPlease_Dont_Bully_Me_SO_Lords3,85112 gold badges60 silver badges117 bronze badges