Solved

How Do I Hide Application on Startup

Posted on 1998-04-27
7
258 Views
Last Modified: 2010-04-06
I am making an application that sits in the System Tray, and I was wondering how I
make the program hide itself on startup so that all the user sees when they run it is the icon
in the system tray?
0
Comment
Question by:Stomper
7 Comments
 
LVL 8

Accepted Solution

by:
ZifNab earned 50 total points
ID: 1337301

Hi Stomper,

    This is well explained by Brendan Delumpa at his Delphi Corner page (http://www.delumpa.com/). Read for yourself (your question is
    explained in the second part) :

    Hiding an Application from Windows

    How do I keep an application from displaying a button on the Windows task bar and prevent users from using [Alt-Tab] to switch to it
    once it executes?

    By convention, any application's window that has its extended window style bit set as a tool window (WS_EX_TOOLWINDOW) will be
    hidden
    from the task bar and will not be able to switched to. In Delphi, every form has a BorderStyle property of bsToolWindow, so you might
    think that
    all you have to do is set the borderstyle of the main form of the application to bsToolWindow, and you'll be able to hide the application
    from the task
    bar. Not really. The reason for this is because the main form of the application really isn't the main form of the application. Huh? Okay,
    I'll explain.

    The application object that encapsulates all Delphi programs (TApplication) actually has a form of its own. It's totally transparent, so
    you can't really
    see it. This is the window we need to interact with in order to hide the application. So how do we do it? Well, if you remember what I
    said at the top
    of this tip, the Windows convention for "hiding" an application is to set its extended window style bit to WS_EX_TOOLWIN. And that's
    easily
    done with a little Windows API trickery. Yes, that's right, trickery. We trick the application into displaying as a tool window instead of an
    application window.

    Specifically, what you have to do to accomplish this is to edit the project's source code. Here's a complete listing (it's actually pretty
    short):

    program Project1;

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

    {$R *.RES}

    //Declare a var to retrieve current window information
    var
      ExtendedStyle : Integer;

    begin
      Application.Initialize;

      //Get the Extended Styles of the Application, by passing its
      //handle to GetWindowLong
      ExtendedStyle := GetWindowLong(Application.Handle, GWL_EXSTYLE);

      //Now, set the Extended Style by doing a bit masking operation.
      //OR in the WS_EX_TOOLWINDOW bit, and AND out the WS_EXAPPWINDOW bit
      //This effectively converts the application from an App Windows to a
      //Tool Window.
      SetWindowLong(Application.Handle, GWL_EXSTYLE, ExtendedStyle OR WS_EX_TOOLWINDOW
                                                     AND NOT WS_EX_APPWINDOW);
      Application.CreateForm(TForm1, Form1);
      Application.Run;
    end.

    The code above is pretty well-commented, so I won't go into a lot of detail. But notice that in code above, I've treated the application
    object like a
    window. It's legal to do that because the application object as I previously mentioned has its own window - it's just hidden. So by using
    a couple of
    functions to retrieve then set the window display properties, we can achieve the desired effect. GetWindowLong is the first function I
    used. It's a
    Windows API function that takes an application handle and a constant representing a bit offset stored in Windows that describes a
    particular
    window. For our purposes, we pass the GWL_EXSTYLE offset value to retrieve the extended window style information. Once we've
    got that, it's
    a simple matter of making a call to SetWindowLong to make the change to the application. SetWindowLong takes the application's
    handle, the
    information offset, and what you want to change at that offset. Once called, it changes the window appropriately. The net effect is that
    no button is
    displayed for the application on the task bar AND, you won't be able to [Alt-Tab] to the application. It's really hidden.

    You should probably study the online documentation regarding the Get- and SetWindowLong Windows API functions to better
    familiarize yourself
    with the functions. You'll see that you can do a lot more with these functions than what I've just brushed over here.

    Getting Some Use Out of All This...

    When I originally started writing this article, I was going to leave it at hiding an application from Windows. But then I thought to myself,
    "What use is
    it?" The most obvious use of the technique is for creating system tray applications; that is, applications that add an icon to the system
    tray and are
    invoked from there as opposed to the task bar. For example, the Audio Control (the little loudspeaker at the bottom right of your
    screen) is a
    system tray application. So how do you create a system tray application? Easy. Just look at the code below:

    {This sets up the application to be a system tray application.
     This is the main form for the application. It has a popup menu
     that will be used to display the main form, or close the application.

     And using the ShellAPI unit, we can then use a couple of calls to display
     the application's icon on the system tray, and make it respond to a
     right mouse click}

    unit Unit1;

    interface

    uses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      ShellAPI, ExtCtrls, Menus;

    type
      TForm1 = class(TForm)
        PopupMenu1: TPopupMenu;
        ShowMainForm1: TMenuItem;
        N1: TMenuItem;
        ExitApplication1: TMenuItem;
        procedure FormCreate(Sender: TObject);
        procedure ShowMainForm1Click(Sender: TObject);
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
        procedure ExitApplication1Click(Sender: TObject);
      private
        procedure WndProc(var Msg : TMessage); override;
      public
        IconNotifyData : TNotifyIconData;
      end;

    var
      Form1: TForm1;

    implementation

    {$R *.DFM}

    procedure TForm1.FormCreate(Sender: TObject);
    begin
      //Set the border icons to have only a system menu. This will
      //leave just the close button.
      BorderIcons := [biSystemMenu];

      //Now set up the IconNotifyData structure so that it receives
      //the window messages sent to the application and displays
      //the application's tips
      with IconNotifyData do begin
        hIcon := Application.Icon.Handle;
        uCallbackMessage := WM_USER + 1;
        cbSize := sizeof(IconNotifyData);
        Wnd := Handle;
        uID := 100;
        uFlags := NIF_MESSAGE + NIF_ICON + NIF_TIP;
      end;

      //Copy the Application's Title into the tip for the icon
      StrPCopy(IconNotifyData.szTip, Application.Title);

      //Add the Icon to the system tray and use the
      //the structure and its values
      Shell_NotifyIcon(NIM_ADD, @IconNotifyData);
    end;

    procedure TForm1.WndProc(var Msg : TMessage);
    var
      p : TPoint;
    begin
      case Msg.Msg of
        WM_USER + 1:
        case Msg.lParam of
          WM_RBUTTONDOWN: begin
                            GetCursorPos(p);
                            PopupMenu1.Popup(p.x, p.y);
                          end;
        end;
      end;
      inherited;
    end;


    procedure TForm1.ShowMainForm1Click(Sender: TObject);
    begin
      Form1.Show;
    end;

    procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      Action := caNone;
      Form1.Hide;
    end;

    procedure TForm1.ExitApplication1Click(Sender: TObject);
    begin
      Shell_NotifyIcon(NIM_DELETE, @IconNotifyData);
      Application.ProcessMessages;
      Application.Terminate;
    end;

    end.
     

    There's really not much to this. Just study the code to see what's going on. But the important thing you should concentrate on is the
    Create method of
    the form and what is done to the IconNotifyData structure. This is a record structure declared in the ShellAPI unit that stores information
    for a tray
    icon. Notice the flags that were used: NIF_MESSAGE + NIF_ICON + NIF_TIP. These tell the icon to process application messages,
    use the
    application's icon and its tip, respectively. Once we've set up all that, then it's a simple matter of creating the window interaction stuff,
    like we'd
    normally do at design time. The tray icon doesn't come into play until runtime.

    The other thing to look at is the override of the WndProc procedure. WndProc is short for Window Procedure. It intercepts all the
    messages sent
    to the window, and acts as the central message dispatcher. In that procedure, you can trap specific Windows messages by overriding
    the inherited
    procedure. In our case, we trap two things: the Msg field of the message sent to the application. If it was our custom message
    (WM_USER + 1)
    defined for the IconNotifyData variable, then we want to handle a right-click. All other messages sent to the application are handled in
    their normal
    fashion.

    I realize that this was pretty quick and dirty, so I encourage you to play around with the code. Just keep in mind that you have to do two
    things, if
    you're going to create system tray application:

       1.You need to first create the "hiding" mechanism for the application. That was handled in the first part of this article
       2.Then, you need to create the interface so that you can interact with the application when its main for isn't being displayed. That was
    done in
         the second part.

    Have fun!

    Copyright ) 1997 Brendan V. Delumpa

    Regards, ZiF.
0
 
LVL 5

Expert Comment

by:inter
ID: 1337302
Zif? How can you write so much thing in a minute. Congratualtions
Igor
0
 
LVL 8

Expert Comment

by:ZifNab
ID: 1337303
Hi Igor,

I'm a robot. ;-)

Well to tell you the thruth, I just copied it from my previous answer handling the same thing.....

How do you do?

Regards, ZiF.
0
Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

 

Author Comment

by:Stomper
ID: 1337304
 I'm just looking to make the main form hide on startup so that when the program is run the
only thing that is visible on startup is the system tray icon.
0
 
LVL 8

Expert Comment

by:ZifNab
ID: 1337305
Then just use the procedures :

 Hide (to hide the form)
 And Show (to bring it back).

Regards, Zif.
0
 

Expert Comment

by:shimonsofer
ID: 1337306
What's about

  StartUpInfo.wShowWindow := SW_HIDE


 
0
 

Expert Comment

by:shimonsofer
ID: 1337307
OR
 you may want to remove app from task bar

  ShowWindow(Application.Handle,SW_HIDE)
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
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.
In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're interested in additional methods for monitoring bandwidt…

747 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

8 Experts available now in Live!

Get 1:1 Help Now