子窗体不能关闭的情况下,也不能关闭主窗体,怎么做? ( 积分: 100 )

  • 主题发起人 主题发起人 wander8848
  • 开始时间 开始时间
W

wander8848

Unregistered / Unconfirmed
GUEST, unregistred user!
mainfom,childfomA、childformB...都是NORMAL窗体
要求:childformA或B中的ADOQUERY处于新增或编辑状态下,无法关闭程序。
看了一些帖子,都是讨论如何关闭,但是如何不关,没人说:(
请高手赐教
 
定义一个全局变量,canclose ,根据当前的状态来设定 True,false
然后在窗体的 formclose 事件中加上就可以了吧.
.FormClose(Sender: TObject;
var Action: TCloseAction);
begin
if Not CanClose then
action := caNone;
end;
 
begin
if ADOQuery1.state in [dsInsert,dsEdit] then
action := caNone;
end;
 
{TChildFormA}
procedure TChildFormA.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
CanClose := not (ADOQuery1.State in [dsEdit, dsInsert]);
end;
{TChildFormB}
procedure TChildFormB.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
CanClose := not (ADOQuery1.State in [dsEdit, dsInsert]);
end;
{TMainForm}
procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
ChildFormA.FormCloseQuery(Sender, CanClose); //传入ChildFormA,判断能否关闭
ChildFormB.FormCloseQuery(Sender, CanClose); //传入ChildFormB,判断能否关闭
//其中有一个不能关闭,就不会关闭了
end;
 
要用子窗体列举,然后判断
 
CanClose := not (ADOQuery1.State in [dsEdit, dsInsert]);//把原来的语句改成这句之后数据集在新增或编辑状态下也能关闭了:(
然后mainfom一样能关闭,不管子窗体到底什么状况
 
ChildFormA.FormCloseQuery(Sender, CanClose);
加入这句后,在子窗体存在的情况下,点主窗体的关闭按钮,报错地址违例访问
如果子窗体一个也没有的话,可以关闭主程序
对了,我忘记说了一点,子窗体存在于bpl中
 
我把他描述清楚,我试了很多次搞不定:(
子窗体存在于一个静态调用的BPL中,是NORMAL窗体,主窗体也是NORMAL窗体
子窗体指定其Parent到主窗体的pagecontrol的一个动态创建的tabsheet中
在关闭子窗体后,需要释放掉其parent。
释放这个tabsheet的代码是这样:
procedure TMainForm.closechildform(closetabname:string);
var
i:integer;
begin
with pg_main do
begin
i:=ActivePageIndex;
ActivePage.PageControl:=nil;
ActivePage.Free;
ActivePageIndex:=i-1;
end;
end;
ANIDELPHI是论坛老手,请帮忙
 
抱歉,如果不行我也帮不上忙了
普通的Form我试过行的,至于bpl我不太清楚(Delphi我只懂点皮毛)
不过我想,既然mainform能访问到childform也应该能用到其中的过程吧
childform是放在mainform的pagecontrol上的一个tabsheet,那么就应该能一步步检测其中adoquery的状态了,不能在mainform的onclosequery中判断吗
 
由于子窗体不是MID子窗体,并非真正意义上的子窗体,所以主窗体关闭时不会自动触发子窗体的closequery事件,只能在主窗体的closequery中判断子窗体能否关闭,但是在主窗体中如何判断BLP子窗体中数据集的状态呢?
 
看来应该在问题的标题那里加上“跪求”二字才行了
 
有没有试过向子窗体发送消息请求ADOQUERY的状态,子窗体接受消息后,将ADOQUERY的状态信息发送给主窗体。

定义一个消息
CONST
WM_DOCANCLOSE = WM_USER + 101; //子窗体向主窗体发出的是否能关闭的消息

主窗体参考代码
假设子窗体发回的消息Msg.WParam=1表示可以关闭,Msg.WParam=0不能关闭;
TFORM1 = CLASS(TFORM)
...
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
PRIVATE
WM_QUESTIONCLOSE: Integer; //向子窗体发送的请求是否能关闭的全局消息的ID
FCANCLOSE: Boolean;
procedure DoCanClose(var Msg: Tmessage); message WM_DOCANCLOSE;
PUBLIC
...
END;
implementation

procedure TForm6.DoCanClose(var Msg: Tmessage);
begin
FCanClose := Msg.WParam = 1;
end;

procedure TForm6.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
FCanClose := False;
//向BPL包内的子窗体发送消息要用广播消息才行,广播的消息要先注册
SendMessage(HWND_BROADCAST, WM_QUESTIONCLOSE, 0, 0);

CanClose := FCanClose;
end;

Initialization
QUESTIONCLOSE := RegisterWindowMessage('QUESTION_CANCLOSE');


子窗体接收到WM_QUESTIONCLOSE消息后
SendMessage(Application.MainForm.Handle, WM_DOCANCLOSE, Canclose{0 or 1}, 0)


也许我把问题搞复杂了,但动态调用BPL我实在也想不出好办法,呵呵。
 
大概思路是这样的,可能太麻烦了,我也等高手支招吧,呵呵。

另外这样做还有个小问题,就是如果有2个子窗体,一个可以关闭一个不可以,碰巧可以关闭的那个子窗体先发回消息的话,主窗体可能就关掉了。我没有试验过。如果真是这样的话这个办法可能就不可行了。
 
这个方法应该是可以,可以做一个循环,逐个判断子窗体A..N的数据集状态,然后只要其中任意一个为false,则主窗体不能关闭。
但是,有没有更好的办法呢?
如果没有更好的办法,就结帖了
 
我把问题搞明白了,由于该BPL与主程序都是不带包编译,估计是因为这个造成的
我改成DLL后,都带包编译,就无须请求DATASET的状态,只须在主窗体的closequery里循环判断子窗体的canclose即可(子窗体也改成了normal窗体)。
感谢大家参与,分不多请见谅
 
后退
顶部