对窗口控制

主题:对窗口控制

内容:
制作可移动的分割窗体。
以下是实现一个简单分割(SPLITTER)窗体的步骤:
1)在窗体中放置一个MEMO控件并设置它的Align属性为ALTOP;
2)在窗体中放置一个PANEL控件并设置它的Align属性为ALTOP;
3)设置PANEL控件的HEIGHT属性为6;
4)设置PANEL控件的DragMode属性为dmAutomatic.;
5)设置PANEL控件的DragCursor属性为crVSplit.;
6)设置PANEL控件的Cursor属性为crVSplit;
7)在窗体中再放置另一个MEMO控件并设置它的Align属性为ALCLIENT;
8)最后为两个MEMO控件的OnDragOver事件添加相同的代码:
procedureTForm1.Memo1DragOver(Sender,Source:TObject;X,Y:Integer;State:TDragState;varAccept:Boolean);
begin
Accept:ΚFalse;
ifSourceΚPanel1thenbegin
Accept:ΚTrue;
Memo1.Height:ΚY+(SenderasTControl).Top;
end;
end;


制作主窗口显示前的版权窗口
在工程文件中选File->New Form新建一个窗口,设计好窗口的外观。给窗口起名为AboutBox,
选Project->Options,将新建的窗口从自动建立中去掉。 选View->Project Source,打开工程文件的源文件,在下面加入红色的句子。
Uses AboutBox
Var
lTime :TDateTime;
Begin
Application.Initialize();
AboutBox=TAboutBox.Create(AboutBox);
AboutBox.Show;
AboutBox.Update;
lTime=GetTickCount;
Application.CreateForm(TMainForm,MainForm);
while((GetTickCount-lTime) / 1000 <3) do;
AboutBox.Hide;
AboutBox.Free;
Application.Run;
end;


制作可移动的分割窗体。
以下是实现一个简单分割(SPLITTER)窗体的步骤:
1)在窗体中放置一个MEMO控件并设置它的Align属性为ALTOP;
2)在窗体中放置一个PANEL控件并设置它的Align属性为ALTOP;
3)设置PANEL控件的HEIGHT属性为6;
4)设置PANEL控件的DragMode属性为dmAutomatic.;
5)设置PANEL控件的DragCursor属性为crVSplit.;
6)设置PANEL控件的Cursor属性为crVSplit;
7)在窗体中再放置另一个MEMO控件并设置它的Align属性为ALCLIENT;
8)最后为两个MEMO控件的OnDragOver事件添加相同的代码:
procedureTForm1.Memo1DragOver(Sender,Source:TObject;X, Y:Integer;State:TDragState;varAccept:Boolean);
begin
Accept:=False;
if Source=Panel1 then
begin
Accept:=True;
Memo1.Height:=Y+(Sender as TControl).Top;
end;
end;


透明FORM
将一个FORM变成透明的实质性手段就是拦截CMEraseBkgnd消息。
unit Utransform; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls; type TForm1 = class(TForm)
private { Private declarations }
public { Public declarations }
PROCEDURE CMEraseBkgnd(var Message:TWMEraseBkgnd);Message WM_ERASEBKGND;
end;
var Form1: TForm1;
implementation
{$R *.DFM}
PROCEDURE Tform1.CMEraseBkgnd(var Message:TWMEraseBkgnd);
BE

GIN
brush.style:=bsClear;
Inherited;
END;
end.


相对于窗体上的点转换成相对于屏幕上的点
方法:
var
MyPoint:TPoint;
ScPoint:TPoint;
begin
MyPoint.x:=1;
MyPoint.y:=2;
ScPoint:=ClientToScreen(MyPoint);
end;
注:ScPoint为相对于屏幕上的点


变色窗口背景
我们看到有些安装程序的背景色自上由下由蓝变黑,我们可以通过下列程序实现
双击窗体的OnPaint事件,然后编写如下程序:
procedure TForm1.FormPaint(Sender: TObject);
var i:word;
dy,y:real;
begin
dy:=clientheight/256;
y:=0;
for i:=255 downto 0 do
begin
canvas.brush.color:=$00000000+i*$10000;
canvas.fillrect(rect(0,round(y),clientwidth,round(y+dy)));
y:=y+dy;
end;
end;


不用标题栏也移动窗体
一般情况下,移动一个窗体需要将鼠标放置在标题栏上才能拖动窗体,为 什么非要使用标题栏呢?其实我们可以使用一个巧妙的方法来实现将鼠标放置 在窗体上按下就可拖动窗体,下面先看实现代码。在Form1的“Private”部分声明过程:
在private部分加入下列代码:
procedure wmnchittest(var msg:twmnchittest);
message wm_nchittest;
在程序部分加入以下代码:
procedure TForm1.wmnchittest(var msg:twmnchittest);
begin
inherited;
if (htclient=msg.result) then msg.result:=htcaption;
end;
上面的关键代码虽然只有两行,但它实现了鼠标直接拖动窗体的目的。代码的原理是利用窗体的WM_NCHITTEST消息,这个消息是当光标移动、鼠标按下或释放时发生的,当程序检测到鼠标在窗体中按下的消息后(消息的值为htClient),将鼠标在标题栏上按下时产生的消息(值为htCaption)传递出去,这样就巧妙的欺骗程序认为是标题栏被按下,当然就可拖动窗体了。


状态条插入可视控件
首先,在FROM中放置一个状态条控件Status。调节Status.Panels,在其中插入3个状态条嵌板。把第二个嵌板的参数Style设置成psOwnerDraw。这一点很重要,如果没有这样做,将永远无法显示文字以外的东西。然后在状态条的OnDrawPanel事件中插入一行StatusDrawRect:=rect;以记录参数Style设置成psOwnerDraw的嵌板的坐标。
第二步,在FROM的Private中申明一个TProgressBar类型的变量Progress。然后在一个菜单的消息响应过程中调用Create方法把它建立起来,再设定状态条为该进程条的父窗口,进而设定进程条的一些必要参数。例如:最大值、最小值、原点坐标、高度和宽度等。
最后编译一下该程序,你就会发现在状态条中被插入了一个运动着的进程条。
类似地,你还可以在状态条中插入其他可视控件,如:按键、位图和动画控件等等。
以下是范例程序:
type
TForm1 = class(TForm)//定义一个窗口类
Status: TStatusBar;
MainMenu1: TMainMenu;
file1: TMenuItem;

insertprocressbar1: TMenuItem;
N1: TMenuItem;
exit1: TMenuItem;
procedure FormCreate(Sender: TObject);
procedure StatusDrawPanel(StatusBar: TStatusBar; Panel:
TStatusPanel;const Rect: TRect);
procedure FormDestroy(Sender: TObject);
procedure exit1Click(Sender: TObject);
procedure insertprocressbar1Click(Sender: TObject);
private
colorindex : integer; BookOpen:Boolean;
ssbmp:Tbitmap; progress:TProgressbar;
StatusDrawRect:TRect; //记录要插入状态条特技的坐标范围
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
begin
end;
procedure TForm1.StatusDrawPanel(StatusBar: TStatusBar;
Panel: TStatusPanel; const Rect: TRect);
begin
StatusDrawRect:=rect; //记录要实现状态条特技的坐标范围
end;
procedure TForm1.exit1Click(Sender: TObject);
begin
close;
end;
procedure TForm1.insertprocressbar1Click(Sender: TObject);
var i,count:integer;
staPanleWidth:integer;
begin
progress:=TProgressbar.create(form1);
count:=3000; //进程条的最大值
staPanleWidth:=status.Panels.Items[2].width;
//由于进程条的很宽,所以需要改变状态条嵌板的宽度,这里先保存它的宽度。
status.Panels.Items[2].width:=150; // 改变宽度
status.repaint;
with progress do
begin
top:=StatusDrawRect.top;
left:=StatusDrawRect.left;
width:=StatusDrawRect.right-StatusDrawRect.left;
height:=StatusDrawRect.bottom-StatusDrawRect.top;
//设定进程条的宽度和高度
visible:=true;
try
Parent := status; //该进程条的拥有者为状态条status
Min := 0; Max := Count; //进程条的最大和最小值
Step := 1; //进程条的步长
for i := 1 to Count do
Stepit; // 累加进程条
ShowMessage('现在,进程条将要从内存中被释放');
finally
Free; //释放进程条
end; //try
end; //with
status.Panels.Items[2].width:=staPanleWidth; //恢复状态条嵌板的宽度
end; //begin
end.


程序启动画面
在启动程序之前出现启动画面的方法多得是,但有些是调用“记时器”来延时的,这种方法有时拖慢了程序的启动速度,下面介绍又一方法,给大家参考对比一下。
建一个启动封面窗体,假设为Form2,先设置好BorderIcons、BorderStyle、FormStyle、Position,接着在窗体上加入图片框、文本框,设置好后在菜单里选Project里的Options,把Form2从Auto-create forms里转到Available forms。再接着就是按Ctrl+F12键,选Project1,出现工程单元,其内容如下
...
Application.CreateForm(TForm1, Form1);
Application.Run;
..
在Application.CreateForm(TForm1, Form1); 前加入如下语句:
form2:=tform2.create(application);
form2.Show;
form2.Update;
然后在Application.Run;前面加入如下语句:
form2.hide;
form2.free;


控制窗体
如何在 Delphi 中把 Form 控制成不能放大/缩小/移动/关闭?1、把 Form 的 BorderIcons 下的几

个子属性值全改为 False;2、修改 Form 的 BorderStyle 的值为bsSingle ;3、为了让窗口不能移动,可以自已拦下 WM_NCHITTEST 消息, 对该消息的处理为:一概回应鼠标点在窗口的 Client 区域, 相信这个视窗就呆呆的不会动了。
详情可以查一下 Win32API Help 的 CreateWindow() 与 WM_NCHITTEST 的说明。
下面是一个例子, 请参考看看:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls,Forms, Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
procedure WMNCHitTest(var Msg: TMessage); message WM_NCHITTEST;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
begin
Close; // 不可少, 因为已经没有其他方法能关闭此窗口了
end;
procedure TForm1.WMNCHitTest(var Msg: TMessage);
begin
inherited; // 这样,移动就不可能了...
Msg.Result := HTCLIENT;
end;
end.


限制FORM的大小
使用过DELPHI的朋友都会注意到DELPHI本身最上面的窗口,
当它极大时只占屏幕的一小部分,它是如何实现的呢,请看下面的说明:
1)在FORM私有声明部分加上如下一行:
procedure WMGetMinMaxInfo( var Message:TWMGetMinMaxInfo ); message WM_GETMINMAXINFO;
2)在声明部分加上如下几行:
procedure TForm1.WMGetMinMaxInfo( var Message :TWMGetMinMaxInfo );
begin
with Message.MinMaxInfo^ do
begin
ptMaxSize.X := 200; {最大化时宽度}
ptMaxSize.Y := 200; {最大化时高度}
ptMaxPosition.X := 99; {最大化时左上角横坐标}
ptMaxPosition.Y := 99; {最大化时左上角纵坐标}
end;
Message.Result := 0; {告诉Windows你改变了 minmaxinfo}
inherited;
end;


查阅可视窗口标题
下面只是举出一个例子提供参考:
运用API函数GetWindow()配合GetWindowText()逐一查出各视窗的标题
1. File | New Project 开始一个新的工程
2. 在 Form1 中安排 Button 与 Memo 各一
3. 在 Button1 的 OnClick 事件中撰写程式如下:
procedure TForm1.Button1Click(Sender: TObject);
var
 hCurrentWindow: HWnd;
 szText: array[0..254] of char;
begin
 hCurrentWindow := GetWindow(Handle, GW_HWNDFIRST);
 while hCurrentWindow <> 0 do
 begin
 if GetWindowText(hCurrentWindow, @szText, 255)>0 then
 Memo1.Lines.Add(StrPas(@szText));
 hCurrentWindow:=GetWindow(hCurrentWindow, GW_HWNDNEXT);
 end;
end;


怎样得到Quicken 风格的FORMS
Quicken style forms ,How to?
----------------------
REPLY1:
Every TPageControl is "dynamic":
TabSheet := TTabSheet.Create(Self);
TabSheet.PageControl := MyPageControl
----------------------
REPLY2:
You can just embed the form in the TabSheet:
MyForm := TMyForm.Create(Application);
MyForm.Parent := TabSheet;
MyForm.Align := alClient;
MyForm.BorderStyle := bsNone;
MyForm.Show;
----------------------
REPL

Y3:
In Delphi you would do this by making a panel on the main form the
container for all your forms (or most of them). Then, when the forms
open, they open within the container.
Here is some code that I use:
{ First, create a unit to define the "child form" that all subsequent
forms inherit... }
unit ChildF;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls;
type
TChildForm = class(TForm)
protected
procedure Loaded; override;
procedure CreateParams(var Params: TCreateParams); override;
end;
implementation
{ The unit has to use your main form... }
uses alloc1;
procedure TChildForm.Loaded;
begin
inherited Loaded;
Visible := False;
Position := poDefault;
BorderIcons := [];
BorderStyle := bsNone;
HandleNeeded;
Parent := TFrmMaster(Application.MainForm).pnlChild;
align := alClient;
end;
procedure TChildForm.CreateParams(var Params : TCreateParams);
begin
Inherited CreateParams(Params);
With Params do
begin
{ make the parent of the form the panel in your main form }
WndParent := TFrmMaster(Application.MainForm).pnlChild.Handle;
Style := (Style or ws_Child or ws_ClipSiblings) and not
ws_popup;
end;
end;
end.


Form的分类
TForm 就只有一种, 您专案中自订的各种 form 中都是从这个类别继承下来的, 再透
过各种属性的设定,
可以衍生出各式各样的 form 出来
至於要让 Form 出现的方法, 有 Show 与 ShowModal两种选择,
以後者作用出来的视窗是一个'排父性'的视窗, 换句话说, 当这个视窗出现时,
应用程式中暂时只有这个视窗有作用
您可以试试对主视窗以外的 Form 各以 Show 与ShowModal 两种方法作让它作用出来
,
相信可以明白两者的差异
将 Form 作极大极小的处理, 只要将那个 Form的 WindowState 属性设为以下的值即
可:
wsMaximized: 极大化
wsMinimized: 极小化
wsNormal: 还原
例:
procedure TForm1.Button1Click(Sender: TObject);
begin
WindowState := wsMaximized;
end;
视窗标题在 Windows 3.1 是预设为调中, 95 中是靠左, 这部分我没有研究过, 但是
,
依照绝大部分视窗的惯例应该是比较好的方式, 不是吗?


form关闭时再去执行某一程式
请教一个问题:当我用form左上角的control menu去关闭这个form时,我要
如何取得control menu的event ? 因为我想在form关闭时再去执行某一程
式.
建议您可以直接在 Mainform 的 OnClose 事件中写您要作的这件事, 例如:
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
WinExec('Notepad.exe', sw_Normal);
end;


Form生成时的事件次序
问题:我做了一个 MDI FORM,当MDI Form出现以後,如果判断出某些资料未设定,
要再出现一个Form2.ShowModal设定资料的对话盒,应该写在那儿呢?我试过的
OnActivate ,OnShow ,但MDI Form皆未出现就去执行这部份程式,就出现错误了。

要解决这个问题, 首先要了解从 Form 产生的""个过程中, 各事件发生与执行的次序
如果是一般的 SDI Form, 各事件的发生次序如下:
OnCreate
OnShow
在萤幕上看到这个视窗
OnActivate
OnPaint
如果是 MDI 视窗, 而 MdiChild 的第一个子视窗是在程式启动时, 就出现在MdiForm
中的话,
那麽,各事件的次序是
主视窗的 OnCreate
子视窗的 OnCreate
子视窗的 OnShow
子视窗的 OnActivate
主视窗的 OnShow
在萤幕上看到主视窗及第一个子视窗
主视窗的 OnPaint
ok, 您发现了吗? OnShow 是在视窗被看到之前的事, 而 OnActivate 并没有发生,
因此,
您的问题中所采用的 '我试过的 OnActivate ,OnShow ....',
当然不能在视窗於'被看到後'才出现设定资料的对话盒
因此, 以您的状况, 检查与设定的程式可以写在主视窗的 OnPaint 中, 不过,
OnPaint
是一个常发生的事件,所以应该要在主视窗的类别定义中额外加上一个 private 的逻

成员资料变数,以控制不要每次视窗重画时都检查设定.
另外, 有一个方法您可以参考看看:
1. 利 Options | Project , 将子视窗从 Auto-Create forms 移到 Available
forms,
不要让 Delphi在程式启动时就产生 MdiChild 子视窗
2. 此时, 虽然是 MDI 架构, 但是 MDI 主视窗产生时的各事件次序与一般视窗相同,
您的检查与呼叫设定视窗的程式可以写在 OnActivate 中
3. 各子视窗的产生, 以Application.CreateForm 方法,写在您的应用程式主选单的
File | New Click 事件中,以手动的方式让子视窗出现在主视窗中
最後, 视窗内部的资料起始与设定, 我一般是写在 Form 的OnCreate 事件中.


Form有AutoCreate与Available两种设定
Delphi 一个Form 中有一 Edit and Button 按此 Button 会 show 出新 From 而此新form 中的 Edit 内容要与原Form 相同, 我试不出来说两个 Form 都 uses 对方
UNIT1
uses unit2;
procedure button1_click()
begin
form2.show;
end;
UNIT2
uses unit1;
procedure form2_onCreate()
begin
edit1.text:=Form1.edit1.text;
end;
执行结果没效 ??
Form 产生後、使用者使用前先设定 form上元件的值是写在 Form 的 OnCreate Event吧? 又如果原 Form是一个 MDIChild 的话, 是否会有差别?
两个 unit 均在 interface 互相 uses 对方是不可以的,一定要互相参考的话, 您可以在 unitA 的 interfaceuses unitB, 然後在 unitB 的 implementation 中 uses unitA你写的程式还是曾经执行过, 只是早在程式启动的时候, Delphi就已经自动为您 Create 这个Form 了,关於这点你可以点一下主选单 View | Project Source, 看一下 project1.dpr 的内容, 在 Application.Run 前,是不是已经 Create 过 Form2 了呢?
建""您可以先从主选单 Option | Project, 将 Form2 从Auto-create forms 移到 Available forms, 然後在 Button1的OnClick 事件中加入以下程式段:
Application.CreateForm(TForm

2, Form2);
Form2.Show;
相信你在 Form2 Create 事件中写的程式码就会如你的预期了。
或者, 您可以用下列的方法试试看:
unit Unit1;
interface
uses
...., Unit2;
.
.
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
begin
Form2.Edit1.Text := Form1.Edit1.Text;
Form2.Show;
end;
end.


在窗体上设置一个热键
在窗体的FORM ONKEYDOWN事件中加入:
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if (ssCtrl in Shift) and (chr(Key) in ['A', 'a']) then
ShowMessage('Ctrl-A');
end;


怎样将窗体设成全部窗体可使用鼠标点中移动
最简单的办法就是"欺骗"系统,让他认为点中的是窗体的标题行
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.
{ 下面是这个窗体的设置}
object Form1: TForm1
Left = 203
Top = 94
BorderIcons = []
BorderStyle = bsNone
ClientHeight = 273
ClientWidth = 427
Font.Color = clWindowText
Font.Height = -13
https://www.360docs.net/doc/b84475583.html, = 'System'
Font.Style = []
PixelsPerInch = 96
TextHeight = 16
object Button1: TButton
Left = 160
Top = 104
Width = 89
Height = 33
Caption = 'Close'
TabOrder = 0
OnClick = Button1Click
end
end


怎样使用PD/PU滚动窗体
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
const
PageDelta = 10;
begin
With VertScrollbar do
if Key = VK_NEXT then
Position := Position + PageDelta
else if Key = VK_PRIOR then
Position := Position - PageDelta;
end;


把Help菜单移动到Form的最右边
唐春晖
在设计程序时,我们通常是将Help菜单放到菜单的最后一项,
在这里有一个方法,可以将菜单放到整个Form的最右边,以突出
菜单的显示,在Delphi 1.0时,我们可以这么做
MenuItem1.Caption := #8 + MenuItem1.Caption;
在Delphi 2.0里,我们可以这么做
ModifyMenu(MainMenu1.Handle, 1, mf_ByPosition or mf_Popup or mf_Help,
MenuItem1.Handle, '&Help';
试试吧,很好玩的

相关文档
最新文档