怎样通过在窗体外点击鼠标关闭窗体?

时间:2021-10-07 00:58:14
比如一个主窗体showmodal一个子窗体,现在我想如果鼠标点击子窗体外任何位置时,子窗体关闭,请问有什么办法?

33 个解决方案

#1


在Form的onclick事加中加入:Applictaion->Terminate();

#2


Application,写错了

#3


是窗体外点击啊,不是窗体上点击。

#4


子窗体是不可以Showmodal的。

#5


可以设置鼠标捕获,再处理单击事件;

#6


回复人: lihongxing2002(潇洒) ( ) 信誉:93  2003-12-08 10:16:00  得分:0 
 
 
  子窗体是不可以Showmodal的。
 
 
=====完全可以的。

需要拦截系统消息,分析鼠标消息时鼠标的位置:
void __fastcall TF_N_Report::WndProc(Messages::TMessage & Message)
{
    TForm::WndProc(Message);
    //....分析鼠标消息
}

#7


学习

#8


子窗体:
void __fastcall TForm2::FormClose(TObject *Sender, TCloseAction &Action)
{
  ReleaseCapture();
}
//---------------------------------------------------------------------------
void __fastcall TForm2::FormMouseDown(TObject *Sender, TMouseButton Button,
      TShiftState Shift, int X, int Y)
{
  POINT pt;
  pt.x=X;
  pt.y=Y;
  if ( WindowFromPoint(pt)!=Handle)
    Close();
}
//---------------------------------------------------------------------------
void __fastcall TForm2::FormShow(TObject *Sender)
{
     SetCapture(Handle);
}
//---------------------------------------------------------------------------


#9


我的方法很简单,不知道能不能达到要求:

在子窗口的OnDeactivate事件里写一句 Close();
即可,不过仍然需要Show而不能是ShowModal。

另外,如果希望该子窗口一直存在在主窗口之上(这可能是你用ShowModal的目的吧),可以把子窗口的BorderStyle设成bsDialog,然后在代码中指定该子窗口的ParentWindow为父窗口句柄: 
AboutDialog->ParentWindow = this->Handle;
AboutDialog->Show();

#10


TopCat(令狐虫)的做法可以,我就是这么做的
 ljianq(泉深水清) 的没试过,如果可以的确是个好方法,受教

#11


ljianq(泉深水清) 的没试过,应该不可以,在FormMouseDown()里写代码,布点在Form上还有用吗??不可能吧,pt很可能是(0,0)个人意见,没有验证过,楼主可以自己试试看。

#12


我的代码已试过,可以的。

#13


to TopCat(令狐虫) 这种方法只有在鼠标在主窗体范围内才会有效.而鼠标离开主窗体的时候就不行了.
to ljianq(泉深水清) 很奇怪,按照您的代码经常是点击窗体的时候窗体关闭,而且非常的不稳定,为什么呢?
至于拦截系统消息没有试过.我再试试.

#14


TO crysword(伤心剑) :
"非常的不稳定",说说情况。

#15


基本上是不管鼠标点击什么地方Showmodal出来的新窗体都会关闭,不过也有特殊的时候可以实现我想要的功能,还有些时候不管怎么点击新窗体都不会消失

#16


ljiang的方法是可行的,只要改一点小地方就可以了:

  POINT pt;
  pt.x=X;
  pt.y=Y;
  if ( WindowFromPoint(pt)!=Handle)
    Close();

改成:

  POINT pt;
  GetCursorPos(&pt);
  if ( WindowFromPoint(pt)!=Handle)
    Close();

就行了,因为用GetCursorPos取得的位置是相对于屏幕的,而通过参数传递进来的Pos是相对Form的,所以可能会出问题。

#17


这种方法也也缺点,刚刚我又试了一下,各位大侠可以看看,如果点击一下标题栏然后再在窗体外点击窗体不关闭.

#18


to crysword(伤心剑) :

情况属实,真是奇怪,为什么消息不响应了?

#19


用区域判断:
  POINT pt;
  GetCursorPos(&pt);
  if ( pt.x<Left||pt.x>Left+Width||pt.y<Top||pt.y>Top+Height)
    Close();

#20


用区域判断:
  POINT pt;
  GetCursorPos(&pt);
  if ( pt.x<Left||pt.x>Left+Width||pt.y<Top||pt.y>Top+Height)
    Close();

#21


一个很奇怪的现象,如果断点调试,不管点击什么地方,都会执行这段命令关闭窗体。但是不设定断点的话就很奇怪的不关闭。

#22


constantine(飘遥的安吉儿) 的方法同样是会出现点击一次show的窗体后再点击窗体外就会失去消息的响应,郁闷中

#23


最好pt=ClientToScreen(pt);再判断吧
  POINT pt;
  GetCursorPos(&pt);
  pt=ClientToScreen(pt);
  if ( pt.x<Left||pt.x>Left+Width||pt.y<Top||pt.y>Top+Height)
    Close();

#24


如果还不行就放到Timer里面吧,再不行就用鼠标钩子

#25


看来是不可以了,似乎得使用钩子,可是钩子我没有用过。各位老大教教我。

#26


to: lluunn007(书生:CSDN上海腐败--地主) ( ) 
窗体类型为:fsMDIChild的窗体也可以showmodal吗?为什么我以前都不成功,还出错!
如果可以,那么怎么做可以呢?

#27


可以这样:
1.不管你的鼠标在子窗体内还是子窗体外,我们都可以用::GetCursorPos(&Point)来得到当前鼠标的位置
POINT Point;
::GetCursorPos(&Point);
::ScreenToClient(m_hWnd,Point);
2.得到你子窗体的区域:
RECT rect;
::GetWindowRect(Handle,&rect);
3.判断当前鼠标位置是否在窗体内,如果在内则不关闭,如果不在内则关闭。
if(::PtInRect(&rect,Point)) do other things
else this->Close();

#28


up

#29


看来大家都希望用简单的方法,我只好说个很一般的了,用钩子,通过判断点级的窗口是否为目标窗口来做了,其实很简单,只不过稍微有点麻烦

#30


做个鼠标钩子,捕获鼠标消息,判断是否是单击,是则关闭。

#31


TO crysword(伤心剑) :
"非常的不稳定",说说情况。

我试了下,  确实不稳定。

可以写一个鼠标钩子,(显示新窗体的时候 安装)拦截鼠标按下事件,然后判断点击的位置是否在自己的窗体上,不在则关闭
然后 卸载鼠标钩子

搜一下 钩子 hook ,可以搜到你想要的代码 这里不帖了

#32


是啊,钩子有很多资料

#33


呵呵,谢谢大家的帮助想了这么多的方法,结帐。

#1


在Form的onclick事加中加入:Applictaion->Terminate();

#2


Application,写错了

#3


是窗体外点击啊,不是窗体上点击。

#4


子窗体是不可以Showmodal的。

#5


可以设置鼠标捕获,再处理单击事件;

#6


回复人: lihongxing2002(潇洒) ( ) 信誉:93  2003-12-08 10:16:00  得分:0 
 
 
  子窗体是不可以Showmodal的。
 
 
=====完全可以的。

需要拦截系统消息,分析鼠标消息时鼠标的位置:
void __fastcall TF_N_Report::WndProc(Messages::TMessage & Message)
{
    TForm::WndProc(Message);
    //....分析鼠标消息
}

#7


学习

#8


子窗体:
void __fastcall TForm2::FormClose(TObject *Sender, TCloseAction &Action)
{
  ReleaseCapture();
}
//---------------------------------------------------------------------------
void __fastcall TForm2::FormMouseDown(TObject *Sender, TMouseButton Button,
      TShiftState Shift, int X, int Y)
{
  POINT pt;
  pt.x=X;
  pt.y=Y;
  if ( WindowFromPoint(pt)!=Handle)
    Close();
}
//---------------------------------------------------------------------------
void __fastcall TForm2::FormShow(TObject *Sender)
{
     SetCapture(Handle);
}
//---------------------------------------------------------------------------


#9


我的方法很简单,不知道能不能达到要求:

在子窗口的OnDeactivate事件里写一句 Close();
即可,不过仍然需要Show而不能是ShowModal。

另外,如果希望该子窗口一直存在在主窗口之上(这可能是你用ShowModal的目的吧),可以把子窗口的BorderStyle设成bsDialog,然后在代码中指定该子窗口的ParentWindow为父窗口句柄: 
AboutDialog->ParentWindow = this->Handle;
AboutDialog->Show();

#10


TopCat(令狐虫)的做法可以,我就是这么做的
 ljianq(泉深水清) 的没试过,如果可以的确是个好方法,受教

#11


ljianq(泉深水清) 的没试过,应该不可以,在FormMouseDown()里写代码,布点在Form上还有用吗??不可能吧,pt很可能是(0,0)个人意见,没有验证过,楼主可以自己试试看。

#12


我的代码已试过,可以的。

#13


to TopCat(令狐虫) 这种方法只有在鼠标在主窗体范围内才会有效.而鼠标离开主窗体的时候就不行了.
to ljianq(泉深水清) 很奇怪,按照您的代码经常是点击窗体的时候窗体关闭,而且非常的不稳定,为什么呢?
至于拦截系统消息没有试过.我再试试.

#14


TO crysword(伤心剑) :
"非常的不稳定",说说情况。

#15


基本上是不管鼠标点击什么地方Showmodal出来的新窗体都会关闭,不过也有特殊的时候可以实现我想要的功能,还有些时候不管怎么点击新窗体都不会消失

#16


ljiang的方法是可行的,只要改一点小地方就可以了:

  POINT pt;
  pt.x=X;
  pt.y=Y;
  if ( WindowFromPoint(pt)!=Handle)
    Close();

改成:

  POINT pt;
  GetCursorPos(&pt);
  if ( WindowFromPoint(pt)!=Handle)
    Close();

就行了,因为用GetCursorPos取得的位置是相对于屏幕的,而通过参数传递进来的Pos是相对Form的,所以可能会出问题。

#17


这种方法也也缺点,刚刚我又试了一下,各位大侠可以看看,如果点击一下标题栏然后再在窗体外点击窗体不关闭.

#18


to crysword(伤心剑) :

情况属实,真是奇怪,为什么消息不响应了?

#19


用区域判断:
  POINT pt;
  GetCursorPos(&pt);
  if ( pt.x<Left||pt.x>Left+Width||pt.y<Top||pt.y>Top+Height)
    Close();

#20


用区域判断:
  POINT pt;
  GetCursorPos(&pt);
  if ( pt.x<Left||pt.x>Left+Width||pt.y<Top||pt.y>Top+Height)
    Close();

#21


一个很奇怪的现象,如果断点调试,不管点击什么地方,都会执行这段命令关闭窗体。但是不设定断点的话就很奇怪的不关闭。

#22


constantine(飘遥的安吉儿) 的方法同样是会出现点击一次show的窗体后再点击窗体外就会失去消息的响应,郁闷中

#23


最好pt=ClientToScreen(pt);再判断吧
  POINT pt;
  GetCursorPos(&pt);
  pt=ClientToScreen(pt);
  if ( pt.x<Left||pt.x>Left+Width||pt.y<Top||pt.y>Top+Height)
    Close();

#24


如果还不行就放到Timer里面吧,再不行就用鼠标钩子

#25


看来是不可以了,似乎得使用钩子,可是钩子我没有用过。各位老大教教我。

#26


to: lluunn007(书生:CSDN上海腐败--地主) ( ) 
窗体类型为:fsMDIChild的窗体也可以showmodal吗?为什么我以前都不成功,还出错!
如果可以,那么怎么做可以呢?

#27


可以这样:
1.不管你的鼠标在子窗体内还是子窗体外,我们都可以用::GetCursorPos(&Point)来得到当前鼠标的位置
POINT Point;
::GetCursorPos(&Point);
::ScreenToClient(m_hWnd,Point);
2.得到你子窗体的区域:
RECT rect;
::GetWindowRect(Handle,&rect);
3.判断当前鼠标位置是否在窗体内,如果在内则不关闭,如果不在内则关闭。
if(::PtInRect(&rect,Point)) do other things
else this->Close();

#28


up

#29


看来大家都希望用简单的方法,我只好说个很一般的了,用钩子,通过判断点级的窗口是否为目标窗口来做了,其实很简单,只不过稍微有点麻烦

#30


做个鼠标钩子,捕获鼠标消息,判断是否是单击,是则关闭。

#31


TO crysword(伤心剑) :
"非常的不稳定",说说情况。

我试了下,  确实不稳定。

可以写一个鼠标钩子,(显示新窗体的时候 安装)拦截鼠标按下事件,然后判断点击的位置是否在自己的窗体上,不在则关闭
然后 卸载鼠标钩子

搜一下 钩子 hook ,可以搜到你想要的代码 这里不帖了

#32


是啊,钩子有很多资料

#33


呵呵,谢谢大家的帮助想了这么多的方法,结帐。