Avatar of Wim ten Brink
Wim ten Brink
Flag for Netherlands asked on

[Challenge] The annoying Application Window...

Okay, I finally got too annoyed by the following problem. Please follow my instructions and then help me solve this... :-)

1) Start your Delphi version. (Doesn't matter which one.)
2) Create a new application.
3) Save the new application. (Make whatever modifications that you like.)
4) Compile the new application.
5) Close Delphi.
6) Close all other applications you're running.
7) Start the application you just created. (Start/Run...)
8) Right-click on the taskbar.
9) From the popup menu, click on 'Tile Windows Vertically" or the other tile option.

After these 9 steps, your newly created application will occupy half the screen...

10) Close your application.
11) Start Notepad (Start/Run...)
12) Right-click on the taskbar.
13) From the popup menu, click on 'Tile Windows Vertically" or the other tile option.

After these additional 4 steps, you'll see Notepad filling your whole screen, just as all Windows applications are supposed to behave...

Now, about the why... This happens because every Delphi application which uses the VCL will actually create two forms. One is your mainform and this one should be visible of course. The other is a form of class TApplication. Yeah, that's right! TApplication is also a very special kind of form. It has a width and height of 0 but it is still visible. (But smaller than a pixel so you won't see it. Delphi needs this window to be visible so it can handle all kinds of Windows messages. In other programming languages, such behaviour would be linked to the mainform instead but not with Delphi. So when the Delphi application gets ordered to tile it's windows, it knows it has two windows which both need to fill the screen. So each window will occupy half the screen. Since TApplication maintains it's size of 0x0, it's still not visible yet you will see the mainform on half your screen.

This annoys me and today it just bugged me too much. So here's the challenge...

Write a simple application using the VCL which will work just like all other Windows applications. Thus, when tiling it fills the whole screen instead of half the screen but also, TApplication must still be able to process all messages. (Which means you can't make TApplication invisible, except for a very, very short time!!!)

400 points plus A-grade for the best solution! And 100 points for the second-best...
(The best solution would be implemented as a component that you can drop on your form...)
Delphi

Avatar of undefined
Last Comment
Wim ten Brink

8/22/2022 - Mon
Wim ten Brink

ASKER
(-: Or 500 points if your solution is the only solution. :-)
Mike Littlewood

Can you do this?
I would have thought even if you create a component wrapping it, that starting a new application would drop this form in again.
How you would remove it from your project I have no idea.
TName

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ShellApi;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Privatew declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
 aInfo: TStartUpInfo;
begin

  GetStartUpInfo(aInfo);
  ShowWindow(Handle, aInfo.wShowWindow);
  ShowWindow(Handle, cmdShow);

  Application.ShowMainForm := False;
  ShowWindow(Application.Handle, SW_HIDE);

end;

end.
All of life is about relationships, and EE has made a viirtual community a real community. It lifts everyone's boat
William Peck
TName

You don't need ShellApi in uses, I first tried to catch ABN_WINDOWARRANGE (couldn't make it work) and forgot ShellApi there...
TName

>but also, TApplication must still be able to process all messages. (Which means you can't make TApplication invisible, except for a very, very short time!!!)

Ok, back to the drawing board... ;)
TName

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ShellApi;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    Button2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    procedure AppMessage(var Msg: TMsg; var Handled: Boolean);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
 aInfo: TStartUpInfo;
begin
  Application.Name:='StillHere';
  Application.OnMessage := AppMessage;
  GetStartUpInfo(aInfo);
  ShowWindow(Handle, aInfo.wShowWindow);
  ShowWindow(Handle, cmdShow);
end;

procedure TForm1.AppMessage(var Msg: TMsg; var Handled: Boolean);
begin
 if Msg.wParam=ABN_WINDOWARRANGE and Msg.lParam then
    ShowWindow(Application.Handle, SW_HIDE);

end;

procedure TForm1.Button1Click(Sender: TObject);
begin
Application.ProcessMessages;
ShowMessage(Application.Name);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  Application.Terminate;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
 Application.OnMessage := nil;
end;

end.
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
Wim ten Brink

ASKER
TName, your first solution would not work, of course. Once TApplication is invisible it won't respond to certain messages anymore. And your second one? When do you make TApplication visible again? :-)

Yeah, it might be more complicated than it seems at first glance... (Especially since this has been bugging me for about 8 years now...)
alkisg

Strange... On Windows 95, the problem doesn't exist!
On 98+, it occurs...
tobjectpascal

I fixed the problem on my machine with 1 line of code... but i use Delphi 5 / 2K so it might be a quirk with my Delphi...

procedure TForm1.FormCreate(Sender: TObject);
begin
 Application.Minimize;
end;



Put it in, compile it / run it, then close everything run the exe, and then tile the windows :-)
Experts Exchange is like having an extremely knowledgeable team sitting and waiting for your call. Couldn't do my job half as well as I do without it!
James Murphy
alkisg

>> Application.Minimize;

Works with D2006 on 98 and XP, but the minimize button of the main form losses its functionality.
alkisg

Also, the task bar button incorrectly behaves as if, well, the application is minimized.
TName

Workshop_Alex, you're right. Sorry, I should have dived into the matter more thoroughly and tested before posting. ;)

>Especially since this has been bugging me for about 8 years now...
Well, then I guess it *is* hopeless (a 100% working solution, that is)
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
Wim ten Brink

ASKER
Yep. alkisq is pointing out a few of the problems with minimizing the TApplication window, or hiding it. Basically, if you minimize TApplication, then Windows will consider your whole application to be minimized and thus you'll end up with a bit flawed functionality.
The trick is to get this Tile function to work properly without affecting the functionality of the application itself. Then again, I might be asking for miracles here... :-)
It's just that this has always been one of the minor annoyances that Delphi had, ever since Delphi 1. In the beginning I didn't have much problems with it but it slowly started to annoy me.

Btw, this is a good trick to see if an application is built with the Delphi VCL or not. No need for any tools or whatever... Just make sure the application window is the only visible window and then tile all windows. If it occupies the whole screen, it's probably written with VS from MS. If it fills half the screen, it's written in Delphi or maybe C++Builder. At least, written in something that uses the VCL.
tobjectpascal

(Turbo Delphi .NET) Well... Delphi .NET (Winform app) fails to do this.

However

(Turbo Delphi VCL .NET) DOES do this....

Not only that, but

SendMessage(Form1.Handle,wm_close,0,0);

works fine

yet if i Define P: Pointer; in the Variable Section..

[Pascal Error] vcl1.pas(28): E2410 Unsafe pointer variables, parameters or consts only allowed in unsafe procedure

I don't get it... If i can use SendMessage then i can use Win32 calls, if i can use win32 calls, then it's not a .NET application if it's not a .NET application why can't i declare a pointer ....

my god Borland, what are you doing.
Wim ten Brink

ASKER
Yeah, I know. Borland is trying to keep Delphi for .NET compatible with Delphi for WIN32, which gives some funny results sometimes. :-)
Actually, this annoying feature is a VCL bug that they never fixed in the first place. It is annoying since it means that any application which uses the Forms unit will create this invisible window. Real annoying sometimes...

And as I said, I don't know a solution and I even worry that no real solution exists and that we'll end up with this bug until the End of Times. (Or the end of Delphi, whatever comes first.)
I started with Experts Exchange in 2004 and it's been a mainstay of my professional computing life since. It helped me launch a career as a programmer / Oracle data analyst
William Peck
ASKER CERTIFIED SOLUTION
Russell Libby

Log in or sign up to see answer
Become an EE member today7-DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform
Sign up - Free for 7 days
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.
Not exactly the question you had in mind?
Sign up for an EE membership and get your own personalized solution. With an EE membership, you can ask unlimited troubleshooting, research, or opinion questions.
ask a question
Wim ten Brink

ASKER
YES!

YES! YES! YES!

That's more like it. It works now. Added it to a large project of mine and it still performs as expected. And so simple. :-)