Solved

How can I maximize the Application?

Posted on 1999-01-23
50
932 Views
Last Modified: 2008-03-17
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
0
Comment
Question by:SupWang
  • 19
  • 16
  • 8
  • +1
50 Comments
 
LVL 5

Accepted Solution

by:
heathprovost earned 60 total points
ID: 1362926
ShowWindow(PrevWindow, SW_RESTORE);
or
ShowWindow(PrevWindow, SW_MAXIMIZE);

Heath
0
 
LVL 2

Author Comment

by:SupWang
ID: 1362927
heathprovost:
Thanks for your quick reply.
How can my program know if the Application is minimized?

0
 
LVL 20

Expert Comment

by:Madshi
ID: 1362928
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
 
LVL 2

Author Comment

by:SupWang
ID: 1362929
Madshi:
I had tried to using IsIconic(Application.handle) and IsIconic(Application.mainForm.handle), but all is not ok. :(
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1362930
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
 
LVL 2

Author Comment

by:SupWang
ID: 1362931
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
 
LVL 20

Expert Comment

by:Madshi
ID: 1362932
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
 
LVL 2

Author Comment

by:SupWang
ID: 1362933
Still not Ok. :O(
any other idea?
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1362934
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
 
LVL 10

Expert Comment

by:viktornet
ID: 1362935
if IsIconic(PrevWindow) then
//whatever..
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1362936
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
 
LVL 2

Author Comment

by:SupWang
ID: 1362937
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
 
LVL 5

Expert Comment

by:heathprovost
ID: 1362938
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
 
LVL 5

Expert Comment

by:heathprovost
ID: 1362939
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
 
LVL 5

Expert Comment

by:heathprovost
ID: 1362940
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
 
LVL 10

Expert Comment

by:viktornet
ID: 1362941
Well if it works the way I showed you then I deserve the points :-)))
0
 
LVL 5

Expert Comment

by:heathprovost
ID: 1362942
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
 
LVL 5

Expert Comment

by:heathprovost
ID: 1362943
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
 
LVL 2

Author Comment

by:SupWang
ID: 1362944
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
 
LVL 10

Expert Comment

by:viktornet
ID: 1362945
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
 
LVL 2

Author Comment

by:SupWang
ID: 1362946
viktornet:
Could you please answer the question "For viktornet", so I can award you the points.
Regards,SupWang

0
 
LVL 2

Author Comment

by:SupWang
ID: 1362947
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
 
LVL 10

Expert Comment

by:viktornet
ID: 1362948
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
 
LVL 5

Expert Comment

by:heathprovost
ID: 1362949
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
 
LVL 5

Expert Comment

by:heathprovost
ID: 1362950
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
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 
LVL 5

Expert Comment

by:heathprovost
ID: 1362951
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
 
LVL 2

Author Comment

by:SupWang
ID: 1362952
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
 
LVL 5

Expert Comment

by:heathprovost
ID: 1362953
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
 
LVL 10

Expert Comment

by:viktornet
ID: 1362954
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
 
LVL 5

Expert Comment

by:heathprovost
ID: 1362955
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
 
LVL 5

Expert Comment

by:heathprovost
ID: 1362956
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
 
LVL 10

Expert Comment

by:viktornet
ID: 1362957
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
 
LVL 10

Expert Comment

by:viktornet
ID: 1362958
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
 
LVL 20

Expert Comment

by:Madshi
ID: 1362959
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
 
LVL 2

Author Comment

by:SupWang
ID: 1362960
Adjusted points to 64
0
 
LVL 5

Expert Comment

by:heathprovost
ID: 1362961
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
 
LVL 5

Expert Comment

by:heathprovost
ID: 1362962
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
 
LVL 20

Expert Comment

by:Madshi
ID: 1362963
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
 
LVL 5

Expert Comment

by:heathprovost
ID: 1362964
Thanks, I am very proud of my convoluted little trick...... :)
0
 
LVL 5

Expert Comment

by:heathprovost
ID: 1362965
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
 
LVL 2

Author Comment

by:SupWang
ID: 1362966
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
 
LVL 5

Expert Comment

by:heathprovost
ID: 1362967
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
 
LVL 5

Expert Comment

by:heathprovost
ID: 1362968
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
 
LVL 2

Author Comment

by:SupWang
ID: 1362969
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
 
LVL 2

Author Comment

by:SupWang
ID: 1362970
Heath: Have a simple question: why the WM_SYSCOMMAND cant be compiled?
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1362971
Perhaps you've forgotten to put "Messages" in your uses clause?
0
 
LVL 2

Author Comment

by:SupWang
ID: 1362972
Madshi: Yes, "Messages"
Heath: Your code work perfect. :-)
0
 
LVL 2

Author Comment

by:SupWang
ID: 1362973
Heath: Please make sure your code have no bug. I am not familiar with those API.

0
 
LVL 5

Expert Comment

by:heathprovost
ID: 1362974
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
 
LVL 2

Author Comment

by:SupWang
ID: 1362975
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

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

706 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now