|
|
|
Again...Modal Forms question...D7
|
|
I need a way to dynamically create a show a form that is not effected by another form being created and shown modally. Here's what I have:
MainForm autocreated at start = visible.
Click event on MainForm creates Form2 = visible..non-modal. Click event on MainForm creates Form3 = visible...modal. All three forms are on-screen now but only Form3 can be accessed as it's modal to the application. But I need to always be able to access Form2 so that I can drag & drop info from it to the current modal Form3.
Is there ANY way I might accomplish this?
Not having worked with threads I'm wondering if I created form2 as a separate thread would that allow what I'm trying to do?
Any suggestions?
ANSWER
As Form3 is modal, it has to be the only form that can have the focus. I don't think that what you are trying to do can be accomplished without threads.
When you create a form within a thread, it can get the focus even if there is another form, which is modal for the application, as long as it (the other, modal form) is not modal for this particular thread.
ANSWER
Do you need to be able to pass information between Form2 and the other forms ? If you put Form2 in a package you might be able to achieve what you need, or encapsulate Form2 in either a DLL or a COM object. I don't know of any way that a single application can achieve what you need because I am only familiar with an application modal or system modal form, both of which would express themselves in the manner you describe. If you use a DLL, Form2 will be created under a different application handle (I think) which may get around the application modal form problem.
On the other hand you might need to start another process altogether.
ANSWER
Your original post did show, but I did not get round to answering it, being somewhat occupied at the time. I did something like this a while ago in D5, and I'm not sure that I remember all the details or whether it would suit your case, but here goes.
Overview: My application creates enormous reports in PDF or HTML format, which might take hours to run. Meanwhile I want the user to be able to get on with other stuff in my application. So I do the printing in a singleton thread which is created as needed and persists till the main application quits. The thread runs with Priority := tpLowest;. It is controlled by a non-modal form in the main thread which holds a queue of print jobs to be run, and shows progress of the currently printing job.
Here is a snippet that creates the modal control form:
try
if fReportPrinter = nil then begin {fReportPrinter is field of
current form.}
fReportPrinter := TReportPrinter.Create(True); {TReportPrinter is
the thread that generates the reports}
gControlForm := TfrmBkgrdPrintDlg.Create(Application); {gControlForm
is the modal form, declares as a global var in the main form}
with fReportPrinter do begin
ControlForm := gControlForm; {Thread gets a reference to the
control form, so it can access the job queue which is actually in the
control form}
ControlForm.Show;
OnShowProgress := LogProgressMessage; {This event allows the
thread to show its progress in the control form}
end; {with fReportPrinter}
end; {if fReportPrinter = nil}
with fReportPrinter do
QueueReport(vReportMemento); {add current job to the queue}
except
on e:Exception do begin
ShowMessage('Unable to queue report: ' + e.Message);
vReportMemento.Free;
raise;
end; {on}
end; {try}
I think this is all it takes. While the thread is executing the user can traverse the tree of modal forms in the main interface, while the control form is always there. The control form interface allows the user to delete jobs from the queue, or change the order of queued jobs by drag-and-drop. All this is in the main thread, so nothing special is needed.
The main take-home is that the non-modal form is not created by the thread - that would be a bad idea, as it would put VCL objects in a thread. Instead the control form is created in the main thread, then a reference is passed to the new thread so it can get information back and forth - using synchronize calls of course.
ANSWER
Well you And Mike answered my question. Looks like using a separate thread will indeed allow what I want...after that the question is whether to handle it as you have or just create the actual form in the secondary thread. For my purposes I can't see that it matters unless a whole second copy of the VCL gets loaded for the secondary thread. Is that what happens?
Unfortunately I've never worked with creating a new thread so I'm in brand new territory again! Not that I mind, it's something I'm sure will come more and more useful once I understand how to use threads correctly, but it's just a bit late in this project to start off in a whole new direction.
The other way I could handle it I guess is to set it up as an applet called from a DLL or as a simple spawned process and that would also make it much easier to upgrade future versions of it. I'll have to make a decision one way or the other I guess...in any case thanks for your comments.
ANSWER
Hi, I think I have the proper answer to that
When the VCL shows a modal form it makers all the other forms disabled using straight API EnableWindow and after that sends to the modal window CM_ENABLE message.
I think a very nice solution will be a kind of a simple hack. Define a message hook for the main thread of your application, where you trap the CM_ENABLE message for forms and at that particular moment enable your special form that needs to be active.
No need for a separate thread.
08.11.2004 [Število ogledov: 31] |
|
|
|
|
|
|
|
|
|
|
|
|
|
OBISKOV: 2366141 |
DATUM: 3.12.2024 |
URA: 6:23:38 |
IP: 18.97.14.85 |
|
|
|
|
|
|
|