Log in

View Full Version : [Windows7] Delphi 7 -> Form without top title


Atak_Snajpera
27th April 2011, 19:12
Does anybody know how to create that kind of form in delphi?

http://www.picamatic.com/show/2011/04/19/09/40/7497161_bigthumb.png

LoRd_MuldeR
27th April 2011, 20:11
You will probably need some SetWindowLong() magic ;)

This is code I used for my "Drop Box" widget:
procedure TForm_DropBox.FormShow(Sender: TObject);
begin
// Make window stay on top
SetWindowPos(Handle, HWND_TOPMOST, Left, Top, Width, Height, SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE);
// Set Parent to desktop
SetWindowLong(Handle, GWL_HWNDPARENT, 0);
// Hide window from the taskbar
SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_TOOLWINDOW and not WS_EX_APPWINDOW);
end;

(BTW: I also set the form's "BorderStyle" property to "bsNone")


[UPDATE]

After thinking a bit more about this, I think this is what you need:

procedure TForm1.FormShow(Sender: TObject);
begin
SetWindowLong(Handle, GWL_STYLE, GetWindowLong(Handle, GWL_STYLE) and (not WS_CAPTION));
SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_DRAWFRAME or SWP_NOMOVE or SWP_NOSIZE);
end;

Atak_Snajpera
28th April 2011, 11:17
Thanks alot LoRd_MuldeR! I knew that I could count on you. Second code works but only if bsSizeable or bsSizeToolWin is set. Now I have to figure out how to disable resizing of my window. Any ideas? Btw. Do you know how to hide form by clicking outside the form?

LoRd_MuldeR
28th April 2011, 11:37
Thanks alot LoRd_MuldeR! I knew that I could count on you. Second code works but only if bsSizeable or bsSizeToolWin is set. Now I have to figure out how to disable resizing of my window. Any ideas? Btw. Do you know how to hide form by clicking outside the form?

Have a look at:
http://msdn.microsoft.com/en-us/library/ms632626%28v=vs.85%29.aspx

Use like this:

type
TForm1 = class(TForm)
Button1: TButton;
private
procedure WMGetMinMaxInfo(var Msg: TWMGetMinMaxInfo); message WM_GETMINMAXINFO;
public
{ Public-Deklarationen }
end;procedure TForm1.WMGetMinMaxInfo(var Msg: TWMGetMinMaxInfo);
begin
with Msg.MinMaxInfo^ do
begin
ptMinTrackSize.X := 300; {Minimum width}
ptMinTrackSize.Y := 300; {Minimum height}
ptMaxTrackSize.X := 300; {Maximum width}
ptMaxTrackSize.Y := 300; {Maximum height}
end;
Msg.Result := 0;
inherited;
end;

LoRd_MuldeR
28th April 2011, 21:20
Here is an even better method, which will also prevent the cursor from turning into a "resize" icon:

type
TForm1 = class(TForm)
procedure FormShow(Sender: TObject);
private
procedure WMNCHitTest(var Msg: TMessage); message WM_NCHITTEST;
public
{ Public-Deklarationen }
end;procedure TForm1.FormShow(Sender: TObject);
begin
SetWindowLong(Handle, GWL_STYLE, WS_OVERLAPPEDWINDOW and (not WS_CAPTION));
SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_DRAWFRAME or SWP_NOMOVE or SWP_NOSIZE);
end;

procedure TForm1.WMNCHitTest(var Msg: TMessage);
begin
inherited;
case Msg.Result of
HTTOP: Msg.Result := HTCLIENT;
HTTOPLEFT: Msg.Result := HTCLIENT;
HTTOPRIGHT: Msg.Result := HTCLIENT;
HTBOTTOM: Msg.Result := HTCLIENT;
HTBOTTOMLEFT: Msg.Result := HTCLIENT;
HTBOTTOMRIGHT: Msg.Result := HTCLIENT;
HTLEFT: Msg.Result := HTCLIENT;
HTRIGHT: Msg.Result := HTCLIENT;
end;
end;

(Note: The usual method to avoid resizing, i.e remove the WS_THICKBORDER bit from the GWL_STYLE flags, doesn't work with caption-less windows, as it would also remove the "Aero-style" border)

Atak_Snajpera
29th April 2011, 15:39
Once again thank you for your help! You gave me everything ready on plate :) In meantime I had problem with 'focusing'. form1 (second form in my app) was always appearing without focus. With little help with google I managed to solve my problem.

I had to add this to form1.show
SetForegroundWindow(Application.MainForm.Handle);

Also I wanted to hide that form automatically when form looses focus (like volume, calendar in windows 7). So I put JvAppEvents and added

procedure TForm1.JvAppEvents1Deactivate(Sender: TObject);
begin
if GetForegroundWindow() <> form1.Handle then form1.Hide;
end;

and here is my question. Is this the best place? I've noticed that it also works in OnMessage, OnIdle. Btw. Where can i find more help about those events?

LoRd_MuldeR
29th April 2011, 19:46
Well, I think the "OnMessage" event is triggered for every message that is sent to any window in your application. You can check the 'Msg' parameter to handle the individual message.

At the same time "OnDeactivate" is called when the application is deactivated (i.e. looses focus) and "OnIdle" is called when the application becomes idle (i.e. when all current messages have been processed).

For what you are doing the "OnDeactivate" event seems to be the most suitable one. I guess your code would also work in "OnMessage", but that might cause an unnecessary overhead...