Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

How can I maximize the Application?

Posted on 1999-01-23
50
Medium Priority
?
973 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 19
  • 16
  • 8
  • +1
50 Comments
 
LVL 5

Accepted Solution

by:
heathprovost earned 240 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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
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
 
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

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
This tutorial will teach you the special effect of super speed similar to the fictional character Wally West aka "The Flash" After Shake : http://www.videocopilot.net/presets/after_shake/ All lightning effects with instructions : http://www.mediaf…
How to fix incompatible JVM issue while installing Eclipse While installing Eclipse in windows, got one error like above and unable to proceed with the installation. This video describes how to successfully install Eclipse. How to solve incompa…
Suggested Courses

722 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