首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > .NET >

关于关闭窗体的有关问题

2012-02-20 
关于关闭窗体的问题一个报警窗体(不能手动关闭),当满足关闭条件时候在FormCloseQuery事件里设置canclose:

关于关闭窗体的问题
一个报警窗体(不能手动关闭),当满足关闭条件时候在FormCloseQuery事件里设置canclose:=true;
现在当报警时候,主窗体缩小到任务拦的话,过段时间,报警消除,把主窗体放大,报警窗体不回消失。
模拟代码如下:
//单元1   ,模拟主线程
unit   Unit1;

interface

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

type
    TForm1   =   class(TForm)
        Timer1:   TTimer;
        procedure   Timer1Timer(Sender:   TObject);
        procedure   FormShow(Sender:   TObject);
    private
        {   Private   declarations   }
    public
        i:integer;
        {   Public   declarations   }
    end;

var
    Form1:   TForm1;
implementation

uses   Unit2;

{$R   *.dfm}

procedure   TForm1.Timer1Timer(Sender:   TObject);
begin
    i:=i-1;
    if   i <0   then
    begin
        i:=0;
        form2.Close;
    end;
end;

procedure   TForm1.FormShow(Sender:   TObject);
begin
    form2.show;
    i:=10;
end;

end.


[解决办法]
先看下,有空研究研究
[解决办法]
procedure TForm1.Timer1Timer(Sender: TObject);
begin
i:=i-1;
if i <0 then
begin
i:=0;
if Assigned(form2) then FreeAndNil(form2); //form2.Close;直接把他给KILL掉
end;
end;

procedure TForm1.FormShow(Sender: TObject);
begin
if Not Assigned(form2) then form2 := TForm2.Create(self); //不存在时就创建!
form2.show;
i:=10;
end;
[解决办法]
分析了原代码之后,有这么点思路,可能不正确!
首先你最小化的时候,系统处理了WMSysCommand消息,处理代码如下:
procedure TCustomForm.WMSysCommand(var Message: TWMSysCommand);begin
with Message do
begin
if (CmdType and $FFF0 = SC_MINIMIZE) and (Application.MainForm = Self) then
Application.WndProc(TMessage(Message))
......
end;
这句可以看出,如果你最小化的是主窗体,系统就把消息传给Application.WndProc处理
再来看看Application.WndProc
procedure TApplication.WndProc(var Message: TMessage);
with Message do
case Msg of
WM_SYSCOMMAND:
case WParam and $FFF0 of
SC_MINIMIZE: Minimize;
SC_RESTORE: Restore;
else
end;
他是调用了Minimize;
procedure TApplication.Minimize;里又调用了NormalizeTopMosts;
NormalizeTopMosts再调用DoNormalizeTopMosts(False);

procedure TApplication.DoNormalizeTopMosts(IncludeMain: Boolean);
var
I: Integer;
Info: TTopMostEnumInfo;
begin
if Application.Handle <> 0 then
begin
if FTopMostLevel = 0 then
begin
Info.TopWindow := Handle;
Info.IncludeMain := IncludeMain;
EnumWindows(@GetTopMostWindows, Longint(@Info));
//这里枚举了窗体,
我们再来看看GetTopMostWindows

function GetTopMostWindows(Handle: HWND; Info: Pointer): BOOL; stdcall;
begin
Result := True;
if GetWindow(Handle, GW_OWNER) = Application.Handle then
if (GetWindowLong(Handle, GWL_EXSTYLE) and WS_EX_TOPMOST <> 0) and


((Application.MainForm = nil) or PTopMostEnumInfo(Info)^.IncludeMain or
(Handle <> Application.MainForm.Handle)) then
Application.FTopMostList.Add(Pointer(Handle))
else
begin
PTopMostEnumInfo(Info)^.TopWindow := Handle;
Result := False;
end;
end;

if GetWindow(Handle, GW_OWNER) = Application.Handle then
if (GetWindowLong(Handle, GWL_EXSTYLE) and WS_EX_TOPMOST <> 0) and
((Application.MainForm = nil) or PTopMostEnumInfo(Info)^.IncludeMain or
(Handle <> Application.MainForm.Handle)) then
Application.FTopMostList.Add(Pointer(Handle))
这里应该是把应用程序中所有真显示的窗体的Handle保存在FTopMostList里面
做一下记录,好让Restore的时候可以根据这个列表来恢复显示

而从Restore中调用的RestoreTopMosts中可以看出,确实是利用了FTopMostList进行了恢复!
for I := FTopMostList.Count - 1 downto 0 do
SetWindowPos(HWND(FTopMostList[I]), HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE);

所以这里,虽然你已经在TIMER里Close了窗体,但是只是把它给Hide了,FTopMostList
还是记录窗提要被恢复的信息,所以当你Restore的时候它又再度把他显示出来~~~


一点看法,应该很多不正确的地方,多多指教~

热点排行