How can I maximize the Application?

Hi, all
The following is my program.

PrevWindow := FindWindow(NIL, 'TestProj');
if PrevWindow <> 0 then
begin
  SetForeGroundWindow(PrevWindow);
  Application.Terminate;<-- If the Application is minimized,
  Exit;                     I want to maximize or restore  
end;                        the Application. How can I do
Application.Initialize;     that?
SplashForm := TSplashForm.Create(Application);
SplashForm.Show;
SplashForm.Update;
  ......
  ......

Thanks,
SupWang
LVL 2
SupWangAsked:
Who is Participating?
 
heathprovostCommented:
ShowWindow(PrevWindow, SW_RESTORE);
or
ShowWindow(PrevWindow, SW_MAXIMIZE);

Heath
0
 
SupWangAuthor Commented:
heathprovost:
Thanks for your quick reply.
How can my program know if the Application is minimized?

0
 
MadshiCommented:
You can use IsIconic(Application.handle) or IsIconic(Application.mainForm.handle). I'm not sure which one. Please try it...
To restore the application you can use Application.Restore.

Regards, Madshi.
0
Cloud Class® Course: CompTIA Healthcare IT Tech

This course will help prep you to earn the CompTIA Healthcare IT Technician certification showing that you have the knowledge and skills needed to succeed in installing, managing, and troubleshooting IT systems in medical and clinical settings.

 
SupWangAuthor Commented:
Madshi:
I had tried to using IsIconic(Application.handle) and IsIconic(Application.mainForm.handle), but all is not ok. :(
0
 
MadshiCommented:
I tried it. In my programs it works well with IsIconic(Application.handle)!!!
I put a timer on my mainform. In the timer event function I did this:

begin
  if IsIconic(Application.handle) then beep;
end;

And when I minimized the application, it beeped!

Regards, Madshi.
0
 
SupWangAuthor Commented:
In your way, it beep. But I do this to the following program, it did not beep!

PrevWindow := FindWindow(NIL, 'TestProj');
if PrevWindow <> 0 then
begin
  SetForeGroundWindow(PrevWindow);
  if IsIconic(Application.handle) then beep;
  Application.Terminate;
  Exit;                
end;                    
Application.Initialize;
SplashForm := TSplashForm.Create(Application);
SplashForm.Show;
SplashForm.Update;
 ......
 ......
 
Regards,
SupWang


0
 
MadshiCommented:
Ooops. Sorry, I thought you wanted to check whether your currently running application is minimized. But now I see that you want to check whether the previous instance of your application is minimized. Use this:

  if IsIconic(GetWindow(prevWindow,GW_OWNER)) then ...

Regards, Madshi.
0
 
SupWangAuthor Commented:
Still not Ok. :O(
any other idea?
0
 
MadshiCommented:
Hmmm. Why are using this one:
  SplashForm := TSplashForm.Create(Application);
and not the normal one:
  Application.CreateForm(TSplashForm,SplashForm);
?

Perhaps my last comment works, if you initialize your forms in the normal way?
0
 
viktornetCommented:
if IsIconic(PrevWindow) then
//whatever..
0
 
MadshiCommented:
Hi Viktor, normally that doesn't work, since it is the application window (the hidden one, that Delphi creates for each and every process) that is minimized, not the mainform itself...  :-(
But perhaps your suggestion works in this special case, since SupWang uses a different way of creating the form.
0
 
SupWangAuthor Commented:
I used the "if IsIconic(PrevWindow) then ", it work ok!
Madshi: why "SplashForm := TSplashForm.Create(Application)" is not the normal way? I copy it from Delphi database demo(MastApp).

Thanks,
SupWang

0
 
heathprovostCommented:
I have always done it this way

procedure ShowPrevInst;
const
  AppClass = 'TApplication';
var
  AppCaption: String;
  PrevWindow: THandle;
begin
  AppCaption := 'MyApplicationTitle'; //This is application title, not window caption.  They CAN be different but usually arent
  PrevWindow := FindWindowEx(0,      0, AppClass, PChar(AppCaption)); //This finds the Application window, not the mainform
  if PrevWindow <> 0 then if IsIconic(PrevWindow) then ShowWindow(PrevWindow, SW_RESTORE); //this restores it but it causes the window to restore strangely.  Maybe someone would like to fix this
end;

This works but like the comments say it looks funny.  Hey Madshi, you wanna fix this one too :)

Heath
0
 
heathprovostCommented:
BTW - For those confused about the above code.  The whole point of doing it like that is because in alot of the apps I write, I like to put the name of the open file on the title bar (like word does).  But I always keep the name of the application (what shows on the button in the taskbar) the same so that I can find my window easily.  I know this can be done using a mutex or something but have never bothered writing the code as this trick seems to work very well.  To fail you would not only need another app with the same caption, but it would HAVE to be a delphi app with the same caption.

Heath
0
 
heathprovostCommented:
BTW - doing ShowWindow(Handle, SW_RESTORE) when Handle is the handle of the Mainform of ANOTHER INSTANCE of a delphi app works, but you will find that after this call you cant minimize the application again without going to the taskbar and rightclicking to pick restore form the list.  I think this is because even though you told the window to restore, the Application window that owns it thinks it is still minimized.  This only happens when calling it from outside of the process, the same call within the application itself works fine.  Go figure.

Heath
0
 
viktornetCommented:
Well if it works the way I showed you then I deserve the points :-)))
0
 
heathprovostCommented:
viktornet - ya, I think madshi and you have already answered this one as much as it can be.  I just wanted to post some code thinking maybe he could get it to work cutting and pasting :)  But I would like to point out that the original question was answered quite completely by me...... :>]

Heath
0
 
heathprovostCommented:
Hey Madshi, fixed it myself :) anyway I think this is probably the safest method to use for Delphi app anyway


procedure GetPrevInst;
const
  AppClass = 'TApplication';
var
  AppCaption: String;
  AppWindow: THandle;
  PrevWindow: THandle;
begin
  AppCaption := 'MyApplicationCaption';
  AppWindow := FindWindowEx(0, 0, AppClass, PChar(AppCaption));
  if AppWindow <> 0 then
    if IsIconic(AppWindow) then
      PostMessage(AppWindow, WM_SYSCOMMAND, SC_RESTORE, 0)
    else
      SetForeGroundWindow(AppWindow);
end;



Heath
0
 
SupWangAuthor Commented:
there is a component that prevents second instances http://www.torry.webnorth.com/vcl/system/maininst.zip 
But I still want to use code.

0
 
viktornetCommented:
Well, who should get the points?

There are plenty of components out there that prevent multiple instances of your app....

Here is an example how to prevent multpiple instance in a fashionate way...

interface
uses Windows;

ResourceString
  AppCantStart = 'App is already running. Can not start another copy.';
  AppTitle = 'Just an App';
implementation
const
  TEN_SECS = 10000;
var
  MutexHandle : Integer;

{...}//Your code goes here...

initialization
  MutexHandle := CreateMutex(nil, False, 'Some Mutex.');
  if WaitForSingleObject(MutexHandle, TEN_SECS) <> WAIT_OBJECT_0 then
  begin
    MutexHandle := -1;
    MessageBox(0, PChar(RSCantStart), PChar(RSTitle), MB_OK);
    Halt;
  end;
finalization
  if MutexHandle <> -1 then
    ReleaseMutex(MutexHandle);
end.

Hope this helps...

-Viktor
--Ivanov
0
 
SupWangAuthor Commented:
viktornet:
Could you please answer the question "For viktornet", so I can award you the points.
Regards,SupWang

0
 
SupWangAuthor Commented:
I add the following code to the dpr file, Dose it has any problem?

var
  PrevWindow: HWND;
begin
  PrevWindow := FindWindow(NIL, 'TestProj');
  if PrevWindow <> 0 then
  begin
    SetForeGroundWindow(PrevWindow);
    if IsIconic(PrevWindow) then
      ShowWindow(PrevWindow, SW_RESTORE);
    Application.Terminate;
    Exit;
  end;
  Application.Initialize;
  SplashForm := TSplashForm.Create(Application);
  SplashForm.Show;
  SplashForm.Update;
  ......
  ......


end.

0
 
viktornetCommented:
you better check for class like Heath showed you with TApplication so you can be sure that there isn't such an app running... Well, better safe than sorry....

oh, you don't need the exit statment since you terminate the program and it won't be executed.... Other than that, the code looks okay to me... Maybe that's not the best way to do it, but it still does the job... You could try the code I posted above,,,

-Viktor
--Ivanov
0
 
heathprovostCommented:
viktornet is right, you should do it like this

>>>>>>>>>>paste over previous code example you gave

const
  AppClass = 'TApplication';
var
  AppCaption: String;
  AppWindow: THandle;
begin
  AppCaption := 'MyApp';  //Change to whatever you want
  AppWindow := FindWindowEx(0, 0, AppClass, PChar(AppCaption));
  if AppWindow <> 0 then
  begin
    //messagebox(0, 'App Already running', 'MyApp', 0); //commented out - I just used for test
    if IsIconic(AppWindow) then
      PostMessage(AppWindow, WM_SYSCOMMAND, SC_RESTORE, 0)
    else
      SetForeGroundWindow(AppWindow);
  end
  else
  begin
  Application.Initialize;
  Application.Title := 'MyApp'; //change to whatever you put for appcaption above
  SplashForm := TSplashForm.Create(Application);
  SplashForm.Show;
  SplashForm.Update;
  ......
  ......
  end;


Heath
0
 
heathprovostCommented:
PS - Dont use ShowWindow when using the main application objects handle - it doesnt work right - use PostMessage(AppWindow, WM_SYSCOMMAND, SC_RESTORE, 0) like in my code example


Heath
0
 
heathprovostCommented:
BTW - I will concide here that using a mutex is a MUCH better way to do this and you should use viktornet's code unless you have a reason not to (I cant think of one....)  Although using FindWindow works, and using FindWindowEx with the Class works even better, neither is 100% reliable.  the mutex method will ALWAYS work no matter what.  I write most of my apps for customers where I know alot about what they run and they can call me if something is wrong.  I have the luxury of being able to be lazy about alot of things.  But if you want to release a piece of software to the general public, I recommend covering all the bases and using a mutex.

Heath
0
 
SupWangAuthor Commented:
viktornet: Sometimes Application.Terminate can't terminate the program immediately, the splash form will show again and then exit. So I use exit procedure.

0
 
heathprovostCommented:
Actually, after reading my above comment, I would like to mention that not even a mutex is 100% reliable.....  But it is more likely to be since you can name it something weird like 'My FunkyCrazy12345MutexForMySillyDelphiAppIWroteOn012099%$@%$@^%&^**'  How you like that name? :)

Heath
0
 
viktornetCommented:
Heath is right :-))

SupWang, that might be true in some cases, it all depends on what kind of app you are doing... If everything goes alright you should not use exit,...

you can use halt; also which should terminate it for you...

Have you experienced the problem when termination of the app is not working...

-Viktor
--Ivanov
0
 
heathprovostCommented:
BTW - if you do it the way I showed you in the above code - the application never even gets a chance to start so your problem with the exit should go away.

Heath
0
 
heathprovostCommented:
And also in the code you posted - The line Application.Teminate; doesnt actually do anything because you havent initialized the application yet.  It is just dead code.

Heath
0
 
viktornetCommented:
SupWang, I answered the question that you told me to...

If you need more info let us know..... I think you've got it to work, right?

Well, talk to y'all later....

-Viktor
--Ivanov
0
 
viktornetCommented:
SupWang, if you don't use a Mutex you should consider using Heath's last code or something similar to that.... it all depends what you want your program to do and stuff..
0
 
MadshiCommented:
Hi friends...

spent some hours in my bed. But I see, you all were quite busy with this question...   :-)
I'm normally using Mutexes, too. But I don't like the FindWindow(Ex) method that much. I'm using this method:
The first instance of the program writes its mainform handle to the registry. The other instances can read this handle from the registry to show the first instances mainform. It's a roundabout way, but it works quite nice...
SupWang, if you need a sure way to terminate your program, you can use ExitProcess(0). That works always at once! But of course you'll have to be cautious, because none of the finalization parts or FormClose events is executed. However, if you use something like Heath's last code, you don't need that.

Regards, Madshi.
0
 
SupWangAuthor Commented:
Adjusted points to 64
0
 
heathprovostCommented:
Hey Madshi, how about this one? I bet you never seen it done this way before.  All the benefits of your method without any registry access.


>>>>>>>>>CODE PASTE

program PGETPREV;

uses
  Forms, Windows, Messages,
  GETPREV in 'GETPREV.pas' {Form1};

{$R *.RES}

const
  MyApp = 'tHiS_iS_My_fUnKy_aPp_wItH_A_WeIrD_NaMe'; //Anything you want - just make it hard to duplicate
  ERROR_ALREADY_EXISTS = 183; //for some reason it is not in the windows declarations
  SEMAPHORE_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED or SYNCHRONIZE or 3; //Ditto

var
  SemaphoreHandle, PrevSemaphoreHandle, PrevAppHandle: THandle;

begin
  SemaphoreHandle := CreateSemaphore(nil, Application.Handle, Application.Handle, MyApp);
    //Create semaphore with the count set to the value of this instances handle so we can get it later
  if GetLastError = ERROR_ALREADY_EXISTS then //If PrevInst is running this will be true
  begin
    PrevSemaphoreHandle := OpenSemaphore(SEMAPHORE_ALL_ACCESS, False, MyApp);
      //Gets the handle of the semaphore created by the prev instance
    if PrevSemaphoreHandle <> 0 then //if call succeeded
    begin
      ReleaseSemaphore(PrevSemaphoreHandle, 0, @PrevAppHandle);
        //We only call this so we can get the handle of the last instance
      if IsIconic(PrevAppHandle) then
        PostMessage(PrevAppHandle, WM_SYSCOMMAND, SC_RESTORE, 0)
      else
        SetForeGroundWindow(PrevAppHandle);
          //Above should be fairly self explanatory
    end;
  end
  else
  begin
    // no prev instance we go ahead and run the app
    Application.Initialize;
    Application.CreateForm(TForm1, Form1);
    Application.Run;
    //There is no reason to destroy the semaphore now since the system will do it once our app closes
  end;
end.

>>>>>>>>>>>END CODE

Pretty neat huh :)

Heath
0
 
heathprovostCommented:
BTW - I like doing it with the applications handle.  You would have to do it a little differently if you wanted to use the mainforms handle, but you could still do it.

Heath
0
 
MadshiCommented:
Hi Heath,

what a trick!!! I've really never seen anybody misusing the semaphore count as a handle variable. But I like it...  :-)))

Regards, Madshi.
0
 
heathprovostCommented:
Thanks, I am very proud of my convoluted little trick...... :)
0
 
heathprovostCommented:
You might also notice that you could use only one handle variable instead of three if you wanted to, since the are used one after another and no calls really need them again.  I chose to use three for the sake of readability.  I just wanted to point that out before someone else did :)

Heath
0
 
SupWangAuthor Commented:
There's an article about mutex here: http://www.delumpa.com/tips/apps/apps5.htm
But it didn't work. what's the matter with it? I am not familiar with mutex.

0
 
heathprovostCommented:
Did you happen to try my last code example? it should be very easy to add to your code in the format you gave earlier.  Almost all of the examples given up to this point do work, maybe you should try one and then give the EXACT error it causes so we can help you better.

Heath
0
 
heathprovostCommented:
OK how about this.  The following is a unit file.  Go into delphi and select new unit from the file>new dialog.  then paste this code into it and save it in the directory your app is in (or in your compiler path)

>>>>>>>>UNIT PREVINST CODE STARTS

unit PREVINST;

interface

uses Windows, Messages;

function HavePrevInstance(AppHandle: THandle; UniqueName: String): boolean;

implementation

function HavePrevInstance(AppHandle: THandle; UniqueName: String): boolean;
const
  ERROR_ALREADY_EXISTS = 183;
  SEMAPHORE_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED or SYNCHRONIZE or 3;
var
  MyHandle: THandle;
begin
  Result := False;
  MyHandle := CreateSemaphore(nil, AppHandle, AppHandle, PChar(UniqueName));
  if GetLastError = ERROR_ALREADY_EXISTS then
  begin
    Result := True;
    MyHandle := OpenSemaphore(SEMAPHORE_ALL_ACCESS, False, PChar(UniqueName));
    if MyHandle <> 0 then
    begin
      ReleaseSemaphore(MyHandle, 0, @MyHandle);
      if IsIconic(MyHandle) then
        PostMessage(MyHandle, WM_SYSCOMMAND, SC_RESTORE, 0)
      else
        SetForeGroundWindow(MyHandle);
    end;
  end;
end;

end.

>>>>>>>>CODE ENDS


Now all you have to do in your project is this


>>>>>>>>>>CODE STARTS

program TestProj;

uses Forms, PREVINST;

{$R *.RES}

begin
  if not HavePrevInstance(Application.Handle, 'WhatEverYouWantAsLongAsItIsHardToDuplicate') then
  begin
    Application.Initialize;
    Application.CreateForm(TForm1, Form1);
    Application.Run;
  end;  
end.

>>>>>>>>>>>There, I cant make it any easier than that


Heath
0
 
SupWangAuthor Commented:
heathprovost:
Thanks a lot. Thanks in advance.
if I have more points I must give you. 64 is all my points. :-)
I will try your program later. I must go to a sleep now.
Regards,SupWang

0
 
SupWangAuthor Commented:
Heath: Have a simple question: why the WM_SYSCOMMAND cant be compiled?
0
 
MadshiCommented:
Perhaps you've forgotten to put "Messages" in your uses clause?
0
 
SupWangAuthor Commented:
Madshi: Yes, "Messages"
Heath: Your code work perfect. :-)
0
 
SupWangAuthor Commented:
Heath: Please make sure your code have no bug. I am not familiar with those API.

0
 
heathprovostCommented:
I have looked at it quite a bit and cant see any bugs......  However I aint willing to bet my life on it yet. hehehe :)

Heath
0
 
SupWangAuthor Commented:
Hi Heath,
I know you are very familiar with VB. I need to create the mscomm32.ocx at runtime in my Delphi program now. (Please take a look at: http://www.experts-exchange.com/comp/lang/delphi/Q.10151745)
In Delphi, I can use the "Create"/"Free" method to create/free a component at runtime. But how can I do that in VB? If you know the answer then please answer this question:
http://www.experts-exchange.com/comp/lang/vbcontrols/Q.10152746
Also take a look at:
http://www.experts-exchange.com/comp/lang/vbcontrols/Q.10152749

(Sorry. because I don't have enough points to ask questions, so I used my friend's name to answer those questions.)

Regards, SupWang
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.