Forms
From: bpeck@prairienet.org (Bob Peck)
You bet! First, select File|New Project and choose "CRT Application" from the Browse Gallery dialog. This will provide you with a project that is still a Windows program, but WriteLn, ReadLn will be allowed in a Window but work like they did in DOS. If you wish, you can remove the WinCrt unit from the uses statement (if no user input/output is required, but is nice for debugging).
I've done this before just to see how small an app can be and I've been able to create a simple EXE (it just beeps) that is only 3200 bytes or so in size! Try to do that in C++ these days!
BTW, these "formless" apps are still Windows applications, so they can still call the Windows API routines. You'll just need to add WinProcs, WinTypes to your uses clause. You'll probably also want to add SysUtils and any other unit you find yourself needing.
From: "Mark R. Holbrook" <markh@sysdyn.com>
It's pretty simple.
Create a form and put the logo on it using a Timage component. My example below assumes you have created a logo form called "logoform" Go to your project options and set the form to NOT be autocreated.
Then in your PROJECT.DPR file just after the begin statement do something like the following:
logoform := TLogoform.Create(nil); logoform.Show; { NOTE! show! NOT showmodal } . . { Do other app startup stuff here like open databases etc... } . . { Just after the block of code that creates all your forms and before the Application.Run statement do: } logoform.Hide; logoform.Release;
This will display your logo form until you actually start the app running.
From: mger@sbox.tu-graz.ac.at (Matthias Gerstgrasser)
The following is from DKBS Helpfile (Delphi Knowledge Base System), they state, that this is one of Borland's TI's:
Q: How can I make a form move by clicking and dragging in the client area instead of on the caption bar?
A: The easiest way to do this is to "fool" Windows into thinking that you're actually clicking on the caption bar of a form. Do this by handling the wm_NCHitTest windows message...
type TForm1 = class(TForm) private { Private-Deklarationen } public { Public-Deklarationen } procedure WMNCHitTest(var M: TWMNCHitTest); message wm_NCHitTest; end; var Form1: TForm1; implementation {$R *.DFM} procedure TForm1.WMNCHitTest(var M: TWMNCHitTest); begin inherited; { call the inherited message handler } if M.Result = htClient then { is the click in the client area? } M.Result := htCaption; { if so, make Windows think it's } { on the caption bar. } end;
>But if i implement your code and >drag the window, the window stays on the same spot and i drag an >outline of the window. Can this be changed so i drag the whole window >(like win95 plus)?Here's a simple little component I wrote that'll handle it...
Unit WinDrag; interface uses windows, sysutils, classes, dsgnintf; type TWinDrag = class(TComponent) private { Private Declarations } protected { Protected Declarations } public { Public Declarations } constructor Create(AOwner: TComponent); override; destructor Destroy; override; function GetDragFlag: boolean; procedure SetDragFlag(Status: Boolean); published Property DragFlag: Boolean read GetDragFlag write SetDragFlag; end; procedure Register; implementation constructor TWinDrag.Create(AOwner: TComponent); begin inherited Create(AOwner); DragFlag := GetDragFlag; end; destructor TWinDrag.Destroy; begin inherited Destroy; end; function TWinDrag.GetDragFlag: boolean; var Value : Boolean; begin SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, @Value, 0); Result := Value; end; procedure TWinDrag.SetDragFlag(Status: Boolean); begin SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, Integer(Status), POINTER(0), 0); end; procedure Register; begin RegisterComponents('Samples', [TWinDrag]); end; end.
If you want to move the form by clicking on it and then dragging it you can try something like this (if you want to click on a label or something else then the same code can be used in their respective events):
var X1, Y1: Integer; procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin {Set start coordinates} X1 := X; Y1 := Y; end; procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin {Check if left button is down} if HiWord(GetAsyncKeyState(VK_LBUTTON)) > 0 then begin Form1.Left := Form1.Left + X - X1; Form1.Top := Form1.Top + Y - Y1; end; end;
From: Bill Dekleris <quasar@prometheus.hol.gr>
You must trap WM_GETMINMAXINFO message:
in your form's class declaration put this :
procedure WMGetMinMaxInfo(var Msg: TWMGetMinMaxInfo); message WM_GETMINMAXINFO;
and in the implementation section :
procedure TMyForm.WMGetMinMaxInfo(var Msg: TWMGetMinMaxInfo); begin { ---------------------------------------------} { Put your numbers in place of } { MIN_WIDTH, MIN_HEIGHT, MAX_WIDTH, MAX_HEIGHT } { } { To allow only horizontal sizing, put } { form's 'Height' property in place of MIN_HEIGHT, MAX_HEIGHT } { ---------------------------------------------} Msg.MinMaxInfo^.ptMinTrackSize := Point(MIN_WIDTH, MIN_HEIGHT); Msg.MinMaxInfo^.ptMaxTrackSize := Point(MAX_WIDTH, MAX_HEIGHT); inherited end;
It should work fine.
From: "James D. Rofkar" <jim_rofkar%lotusnotes1@instinet.com>
Here's the trick:
Treat your controls like they belong in a separate modeless dialog that just so happens to track the movement and resizing of your main form. In addition, it always appear over the main form's caption area.
This said, here's a simple hack that involves 2 forms and a drop-down listbox. After running this program, the drop-down listbox will appear in the Main form's caption area. Two key issues are: 1) trapping the Main form's WM_MOVE message; and 2) returning focus back to the Main form after users press any focus-grabbing controls (like a TComboBox, TButton, etc.)
[FYI, I'm using 32-bit Delphi 2.0 Developer under Win95 -- even though this technique should work for all versions of Delphi]
Here's the source for the Main form:
unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) procedure FormResize(Sender: TObject); procedure FormShow(Sender: TObject); procedure FormHide(Sender: TObject); private { Private declarations } public { Public declarations } procedure WMMove(var Msg: TWMMove); message WM_MOVE; end; var Form1: TForm1; implementation uses Unit2; {$R *.DFM} procedure TForm1.FormResize(Sender: TObject); begin with Form2 do begin {Replace my magic numbers with real SystemMetrics info} Width := Form1.Width - 120; Top := Form1.Top + GetSystemMetrics(SM_CYFRAME); Left := ((Form1.Left + Form1.Width) - Width) - 60; end; end; procedure TForm1.FormShow(Sender: TObject); begin Form2.Show; end; procedure TForm1.FormHide(Sender: TObject); begin Form2.Hide; end; procedure TForm1.WMMove(var Msg: TWMMove); begin inherited; if (Visible) then FormResize(Self); end; end.
Here's the source for the pseudo-caption area form. This is the form that contains the VCL controls you wish to place in the Main form's caption area. Essentially, it's a modeless dialog with the following properties:
Caption='' {NULL string} Height={height of caption area} Width={width of all controls in form} BorderIcons=[] {none} BorderStyle=bsNone FormStyle=fsStayOnTop
Anyhow, here's the source for Form2:
unit Unit2; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm2 = class(TForm) ComboBox1: TComboBox; procedure FormCreate(Sender: TObject); procedure ComboBox1Change(Sender: TObject); procedure FormResize(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form2: TForm2; implementation uses Unit1; {$R *.DFM} procedure TForm2.FormCreate(Sender: TObject); begin Height := ComboBox1.Height - 1; Width := ComboBox1.Width - 1; end; procedure TForm2.ComboBox1Change(Sender: TObject); begin Form1.SetFocus; end; procedure TForm2.FormResize(Sender: TObject); begin ComboBox1.Width := Width; end; end.
The project file (.DPR) is fairly straightforward:
program Project1; uses Forms, Unit1 in 'Unit1.pas' {Form1}, Unit2 in 'Unit2.pas' {Form2}; {$R *.RES} begin Application.Initialize; Application.CreateForm(TForm1, Form1); Application.CreateForm(TForm2, Form2); Application.Run; end.
That's it!
Although some Delphi book authors state:
"You can't place a Delphi component on the title bar, so there's literally no way to put a button there."
you can at least "fake" the illusion...
From: Oliver.Bollmann@t-online.de (Oliver Bollmann)
Hallo, here are examples you need, I hope:
procedure SaveToField(FField:TBlobField;Form:TComponent); var Stream: TBlobStream; FormName: string; begin FormName := Copy(Form.ClassName, 2, 99); Stream := TBlobStream.Create(FField, bmWrite); try Stream.WriteComponentRes(FormName, Form); finally Stream.Free; end; end; procedure LoadFromField(FField:TBlobField;Form:TComponent); var Stream: TBlobStream; I: integer; begin try Stream := TBlobStream.Create(FField, bmRead); try {delete all components} for I := Form.ComponentCount - 1 downto 0 do Form.Components[I].Free; Stream.ReadComponentRes(Form); finally Stream.Free; end; except on EFOpenError do {nothing}; end; end;
From: AVONTURE Christophe <Christophe.AVONTURE@is.belgacom.be>
ShowWindow (Application.Handle, SW_HIDE);
From: "James D. Rofkar" <jim_rofkar%lotusnotes1@instinet.com>
First, override the "CreateParams" method of your Form, by declaring this in either your Form's protected or public section:
procedure CreateParams(var Params: TCreateParams); override;
Then, in the actual CreateParams() method, specify something like this:
procedure TForm1.Createparams(var Params: TCreateParams); begin inherited CreateParams(Params); with Params do Style := (Style or WS_POPUP) and (not WS_DLGFRAME); end;
Hopefully, you'll provide some UI mechanism for moving and closing the window.
From: ao@atlas.sto.foa.se (Anders Ohlsson)
Someone asked for some code to make a form with no title bar moveable, kind of like a floating toolbar, for example FreeDock. Actually, for some of the stuff in here I spied on the FreeDock sources...This requires the use of some WinAPI functions. All WinAPI functions are however available at a touch of a key (F1 - OnLine Help)...
Here's some code that does this (about 100 lines)...
To make this work like intended:
OR start a new project, make the form's borderstyle bsNone, add a panel, set the border style of the panel to bsSingle, add another panel with some caption, add a button that says 'toggle title bar', cut out the below code and insert it were it should be, enable the panel's three event handlers (MouseDown, MouseMove, MouseUp), enable the button's event handler (Click). Hope I didn't forget anything... ;-) It's done faster in Delphi than it's written here... ;-)
unit Unit1; interface uses SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls; type TForm1 = class(TForm) Panel1: TPanel; Panel2: TPanel; Button1: TButton; procedure Panel1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure Panel1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); procedure Panel1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure Button1Click(Sender: TObject); private { Private declarations } OldX, OldY, OldLeft, OldTop : Integer; ScreenDC : HDC; MoveRect : TRect; Moving : Boolean; public { Public declarations } end; var Form1: TForm1; implementation {$R *.DFM} procedure TForm1.Panel1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if Button = mbLeft then begin SetCapture(Panel1.Handle); ScreenDC := GetDC(0); OldX := X; OldY := Y; OldLeft := X; OldTop := Y; MoveRect := BoundsRect; DrawFocusRect(ScreenDC,MoveRect); Moving := True; end; end; procedure TForm1.Panel1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin if Moving then begin DrawFocusRect(ScreenDC,MoveRect); OldX := X; OldY := Y; MoveRect := Rect(Left+OldX-OldLeft,Top+OldY-OldTop, Left+Width+OldX-OldLeft,Top+Height+OldY-OldTop); DrawFocusRect(ScreenDC,MoveRect); end; end; procedure TForm1.Panel1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if Button = mbLeft then begin ReleaseCapture; DrawFocusRect(ScreenDC,MoveRect); Left := Left+X-OldLeft; Top := Top+Y-OldTop; ReleaseDC(0,ScreenDC); Moving := False; end; end; procedure TForm1.Button1Click(Sender: TObject); var TitleHeight, BorderWidth, BorderHeight : Integer; begin TitleHeight := GetSystemMetrics(SM_CYCAPTION); BorderWidth := GetSystemMetrics(SM_CXBORDER)+GetSystemMetrics(SM_CXFRAME)-1; BorderHeight := GetSystemMetrics(SM_CYBORDER)+GetSystemMetrics(SM_CYFRAME)-2; if BorderStyle = bsNone then begin BorderStyle := bsSizeable; Top := Top-TitleHeight-BorderHeight; Height := Height+TitleHeight+2*BorderHeight; Left := Left-BorderWidth; Width := Width+2*BorderWidth; end else begin BorderStyle := bsNone; Top := Top+TitleHeight+BorderHeight; Height := Height-TitleHeight-2*BorderHeight; Left := Left+BorderWidth; Width := Width-2*BorderWidth; end; end; end.
From: Steve Teixeira
unit Dragmain; interface uses SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private procedure WMNCHitTest(var M: TWMNCHitTest); message wm_NCHitTest; end; var Form1: TForm1; implementation {$R *.DFM} procedure TForm1.WMNCHitTest(var M: TWMNCHitTest); begin inherited; { call the inherited message handler } if M.Result = htClient then { is the click in the client area? } M.Result := htCaption; { if so, make Windows think it's } { on the caption bar. } end; procedure TForm1.Button1Click(Sender: TObject); begin Close; end; end.
Ti2861 - Form display with different screen resolutions.
from the Delphi Technical Support area of our web site at www.borland.com.
From: abeldup@unison.co.za (Abel du Plessis)
I need to start my form minimized, unfortunetly it doesn't work. When I set the WindowState property of the main form to wsMinimized and run it, the form minimizes onto Win95 desktop instead of the taskbar how it properly should. Does anyone know how to fix this bug?There was an article in The Delphi Magazine, Issue 19, March 1997 - the Delphi Clinic section which explained the problem.
unit Foobar; interface type TfrmFoobar = class(TForm); procedure DoRestore(Sender: TObject); procedure FormCreate(Sender: TObject); private { Private declarations } public { Public declarations } end; implementation procedure TfrmUVChannel.FormCreate(Sender: TObject); begin //Assign a temporary event handler for when the app gets restored Application.OnRestore := DoRestore; Application.Minimize; end; procedure TfrmFoobar.DoRestore(Sender: TObject); begin Application.ShowMainForm := True; //Restore the application Perform(wm_SysCommand, sc_Restore, 0); //Ensure all components draw properly Show; //Disconnect this event handler so it will not be called again Application.OnRestore := nil; end; initialization //Hide the minimized main form for now Application.ShowMainForm := False; end.
From: rkroman@pacbell.net
The methods you might be concerned with are:
{Trap the GetMinMaxInfo message and set minimum window size} { using declared constants } procedure TForm1.WMGETMINMAXINFO( var message: TMessage ); var mStruct: PMinMaxInfo; begin mStruct := PMinMaxInfo(message.lParam); mStruct.ptMinTrackSize.x := HORIZONTALSIZE; mStruct.ptMinTrackSize.y := VERTICALSIZE; message.Result := 0; end;
2958: Preventing a From from Resizing
In some cases, developers would want to create a regular window (Form) in Delphi that contains some of the characteristics of a dialog box. For example, they do not want to allow their users to resize the form at runtime due to user interface design issues. Other than creating the whole form as a dialog box, there is not a property or a method to handle this in a regular window in Delphi. But due to the solid connection between Delphi and the API layer, developers can accomplish this easily.The following example demonstrates a way of handling the Windows message "WM_GetMinMaxInfo" which allows the developer to restrict the size of windows (forms) at runtime to a specific value. In this case, it will be used to disable the functionality of sizing the window (form) at runtime.
Consider the following unit:
unit getminmax; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs; type TForm1 = class(TForm) private { Private declarations } procedure WMGetMinMaxInfo(var Msg: TWMGetMinMaxInfo); message WM_GETMINMAXINFO; procedure WMInitMenuPopup(var Msg: TWMInitMenuPopup); message WM_INITMENUPOPUP; procedure WMNCHitTest(var Msg: TWMNCHitTest); message WM_NCHitTest; public { Public declarations } end; var Form1: TForm1; implementation {$R *.DFM} procedure TForm1.WMGetMinMaxInfo(var Msg: TWMGetMinMaxInfo); begin inherited; with Msg.MinMaxInfo^ do begin ptMinTrackSize.x:= form1.width; ptMaxTrackSize.x:= form1.width; ptMinTrackSize.y:= form1.height; ptMaxTrackSize.y:= form1.height; end; end; procedure TForm1.WMInitMenuPopup(var Msg: TWMInitMenuPopup); begin inherited; if Msg.SystemMenu then EnableMenuItem(Msg.MenuPopup, SC_SIZE, MF_BYCOMMAND or MF_GRAYED) end; procedure TForm1.WMNCHitTest(var Msg: TWMNCHitTest); begin inherited; with Msg do if Result in [HTLEFT, HTRIGHT, HTBOTTOM, HTBOTTOMRIGHT, HTBOTTOMLEFT, HTTOP, HTTOPRIGHT, HTTOPLEFT] then Result:= HTNOWHERE end; end. { End of Unit}
// Custom coding for The Knoxville News-Sentinel // // jmb 06/28/97 Completed MessageDlgCtr - centers message dialogs above form unit kns; {$R-} interface uses Forms, Dialogs; { Centered message dialog } function MessageDlgCtr(const Msg: string; DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; HelpCtx: Longint): Integer; implementation uses Consts; { This MessageDlg function centers the dialog above the active form } function MessageDlgCtr(const Msg: string; DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; HelpCtx: Longint): Integer; begin with CreateMessageDialog(Msg, DlgType, Buttons) do try HelpContext := HelpCtx; Left := Screen.ActiveForm.Left + (Screen.ActiveForm.Width div 2) - (Width div 2); Top := Screen.ActiveForm.Top + (Screen.ActiveForm.Height div 2) - (Height div 2); Result := ShowModal; finally Free; end; end; end.
I had a problem with centering a form after I had changed its dimensions at run-time. The poScreenCenter only works when the form is shown. But if you change the dimensions at run time your form doesn't center automatically.[Robert Meek, rmeek@ptdprolog.net]
I've used this in my FormCreate, but I guess it could be called during an OnPaint whenever you change the size of the form too couldn't it?
Form1.Left := (Screen.Width div 2) - (Form.Width div 2); Form1.Top := (Screen.Height div 2) - (Form.Height div 2);
if you use SetBounds, form won't be repainted twice (one time for Left assignment
and other time for Top assignment).
Try:
procedure CenterForm(AForm:TForm); var ALeft,ATop:Integer; begin ALeft := (Screen.Width - AForm.Width) div 2; ATop := (Screen.Height - AForm.Height) div 2; AForm.SetBounds(ALeft, ATop, AForm.Widht, AForm.Height); end;
Procedure CenterForm(aForm: TForm); Begin aform.left := (screen.width - aform.width) shr 1; aform.top := (screen.height - aform.height) shr 1; End;