Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations biv343 on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Non-modal window started?

Status
Not open for further replies.

Kenbla

Programmer
Oct 11, 2006
68
SE
Hello,
I have a question for you all.
I must use non-modal windows in my application for different reasons, but before I start a new non-modal window I would like to verify if another non-modal window with the same form-name already has been started! What's the best way to do this in Delphi 2006? Window API calls?
Regards,
Kenbla
 
Are you wanting to know if your current application has windows that it has created or do you want to know if another instance of your program is running?
 
Hello DjangMan,
Thanks for your response.
I want to know if a user of my application (APPL_A) already has started a non-modal window (Form_B). If so I want to inform the user that he/she first must close Form_B before another non-modal window of Form_B is started.
In the future I might allow for 2 or 3 Form_B to be started by the same user.
I have been thinking of using the API function FindWindow but I don't get it to work as I want it to!
 
One more thing:
I have tried to use the API function "FindWindow" but the response I get from this function is that my "Form_B" is already started even though it is not started!!
Do you know when a form is set to "started" by Delphi (or Windows!)?
 
There are two ways I can think of to handle this. Others might have more elegant ways.

One way is to use DDE to allow your application to communicate with other instances. It can then communicate back and let you know what is going on. Then you're talking app to app instead of looking for individual forms.

Look up Delphi and single instance applications. You should be able to find the code you're looking for. Make sure your window name is something unique like TMyUniqueAppForm instead of TForm1. Having Delphi running at the same time can mess up the response of FindWindow as well.

 
Thanks for your replies.
I still can't get it to work!
Can you find any problems with this code?
procedure: xxx100.validate;
var
h_test:HWND;
begin
h_test := findWindow('Txxx147', nil);
if h_test = 0 then
showmessage('xxx147 is not yet started')
else
showmessage('xxx147 is already started');
end;

When I run this code I always get the message 'xxx147 is already started'!! I have tried to close down Delphi Developer Studio 2006 but it doesn't help!
 
Does the testing program have an xxx147 form within it? Does your application auto-create all forms?
 
Yes, the mainprogram starts a form named xxx147 which is defined as its own class Txxx147, it is started from the mainprogram when the user performs a validation. xxx147 is started as a non-modal form/window and I want to have control of how many xxx147 forms a user starts!
I don't know what you mean with auto-create, but the xxx147 form is always started "programatically" by my program. I recently re-booted my PC and ran a test by double-clicking on .exe file (nothing else was started!), but the FindWindow found a handle for the xxx147 even then which I don't understand!
 
I'm not sure FindWindow is even what you're wanting to do. As the description says:

The FindWindow function retrieves a handle to the top-level window whose class name and window name match the specified strings. This function does not search child windows. This function does not perform a case-sensitive search.

Besides, though, I think you are making it harder than it really needs to be. If you are in control of the application creating these windows, all that is required is setting a boolean variable (FormB_Opened, maybe?) and checking against it when you open this form and changing it when you open the first one?


----------
Measurement is not management.
 
Or even better, instead of the generic boolean flag, enable and disable the button/menu/whatever you are using that is triggering this form.

Good UI design dictates that you "bread crumb" the user. If only one child form is to be opened, change the UI so that becomes true.

----------
Measurement is not management.
 
Thanks Glenn9999, I have thought of that but first of all I have to use a global variable in order to do this and global variables are not recommended by most experts!
In the future I might want to allow the users to have 2-3 xxx147 forms started at the same time so a boolean wouldn't work (a maximum value counter would though).
Should the FindWindowEx work do you think? I have tried it as well but without success
 
I think the OP needs to manage the situation when a second instance of the application is invoked that it needs to make sure that the first instance is not showing any xxx147 forms.

Is your application creating xxx147 in code or automatically?

DDE might be the way to go as it makes communicating between your applications easy (vs. setting up Indy servers - which would do the same thing). Using DDE you could have multiple instances of your program running and they can check with each other to control the number of your forms that are running between them.

I have an application that will only run as a single instance when registered. You might be able to use a custom message to achieve a similar effect. There's more to the code that this - we can get into that if that's the direction you want to go.

Code:
begin
  //2002-10-20 (JDA)
  //If there's another instance already running, activate that one
  if IsRegistered=False then
  begin
    RvHandle := FindWindow(WIN_CLASS_NAME, NIL);
    if RvHandle > 0 then
    begin
      PostMessage(RvHandle, CM_RESTORE, 0, 0);
      Exit;
    end;
  end;

  Application.Initialize;
  Application.Title := 'Pervasive Peruser';
  Application.CreateForm(TfrmMain, frmMain);
  Application.CreateForm(TfrmAbout, frmAbout);
  Application.CreateForm(TfrmRegister, frmRegister);
  Application.CreateForm(TXMLDM, XMLDM);
  Application.Run;
end.
 
I think the OP needs to show some cod, so we can help him with meaningful tips...

-----------------------------------------------------
What You See Is What You Get
Never underestimate tha powah of tha google!
 
I think the OP needs to manage the situation when a second instance of the application is invoked that it needs to make sure that the first instance is not showing any xxx147 forms.

1) I see no mention of other applications.
2) And if other applications are the case, semaphores are the way to go.

----------
Measurement is not management.
 
Sorry - misread the first post. Didn't mean to sound grumpy - good old lack of emotion in text.

If it is just a single application then a global variable would work fine or perhaps running though the screen.formcount. Something like this:

Code:
//Adapted from Delphi Programming Problem Solver - Neil Rubenking

function GetFormCount: integer;
var
  cntForm: integer;
begin
  cntForm := 0;  
  for i := 0 to scree.formcount-1 do
  begin
    if screen.forms[i] is Txxx147 then
    begin
      inc(cntForm);
    end;
  end;
  result := cntForm;
end;
 
Thanks for all your tips!
I especially liked the screen.formcount example! but the form that I create in my application is a non-modal window which mean that my the main program doesn't have much control over it once it is created!
How do i "decrement" the formcount when the user close the non-modal window Txxx147? As it is right now the formcount value increases each time I start a new Txxx147 form, it never decreases.
I have also been adviced to avoid global variables! What do you think of that advice?
 
How are your freeing or releasing your Txxx147 when the user closes the form?

I would suggest that the variable be local to the owner of the Txxx147.

Otherwise - if you need a global and a global variable will save you hours and hours of programming time vs. writing a perfect example of OOP - use the global. :)
 
Thanks to all for your assistance and support, it has been greatly appreciated!
I have now found a good solution to my problem! I use an "OnClose" event trigger (of type TNotifyEvent) in the called form (Txxx147), the OnClose event is checked in the caller/mainprogram which then decreases the value of a modular counter, this counter is increased when new instances of Txxx147 are created. Before a new instance of Txxx147 is created I check the counter against a "maximum value" constant.
It works great!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top