You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MQL4中Cpanel对话框面板按钮隐藏后仍可响应点击的问题

问题

我制作了一个包含一个标签和两个按钮的简单面板,点击其中一个按钮时另一个会被隐藏,但点击隐藏按钮的原位置时,该按钮仍能触发点击事件。我使用了Cpanel对话框库及Control文件夹中的Button控件,调用了.Hide()方法,还尝试了.Disable()和Deactivate()功能,但均无效。

原mqh文件代码

#define INDENT_LEFT_ScrollQ                         (11)      // indent from left (with allowance for border width)(for Scroll Bar Only)
#define INDENT_LEFTQ                         (11)      // indent from left (with allowance for border width)
#define INDENT_TOPQ                          (11)      // indent from top (with allowance for border width)
#define INDENT_RIGHTQ                        (11)      // indent from right (with allowance for border width)
#define INDENT_BOTTOMQ                       (11)      // indent from bottom (with allowance for border width)
#define CONTROLS_GAP_XQ                      (80)      // gap by X coordinate
#define CONTROLS_GAP_YQ                      (40)      // gap by Y coordinate
//--- for buttons
#define BUTTON_WIDTHQ                        (60)     // size by X coordinate
#define BUTTON_HEIGHTQ                       (20)      // size by Y coordinate
//--- for the indication area

#define EDIT_HEIGHTQ                         (20)      // size by Y coordinate
#define GROUP_WIDTHQ                         (150)     // size by X coordinate
#define LIST_HEIGHTQ                         (379)     // size by Y coordinate
#define RADIO_HEIGHTQ                        (56)      // size by Y coordinate
#define CHECK_HEIGHTQ                        (93)      // size by Y coordinate
//+------------------------------------------------------------------+
//| Class CPanelDialog                                               |
//| Usage: main dialog of the SimplePanel application                |
//+------------------------------------------------------------------+
class CPanelDialogQ : public CAppDialog
  {
private:
 
   CLabel            m_Label_Q_text;


   CButton           m_button_Yes;
   CButton           m_button_No;

public:
                     CPanelDialogQ(void);
                    ~CPanelDialogQ(void);
   //--- create
   virtual bool      CreateQ(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2,string QText);
   //--- chart event handler
   virtual bool      OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);

protected:

   //--- create dependent controls
   bool              CreateLabel_Q_text(string QT);
   bool              CreateButton_Yes(void);
   bool              CreateButton_No(void);

   void              OnClick_button_Yes(void);
   void              OnClick_button_No(void);
  };
//+------------------------------------------------------------------+
//| Event Handling                                                   |
//+------------------------------------------------------------------+
EVENT_MAP_BEGIN(CPanelDialogQ)
ON_EVENT(ON_CLICK,m_button_Yes,OnClick_button_Yes)
ON_EVENT(ON_CLICK,m_button_No,OnClick_button_No)
EVENT_MAP_END(CAppDialog)
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CPanelDialogQ::CPanelDialogQ(void)
  {
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CPanelDialogQ::~CPanelDialogQ(void)
  {
  }
//+------------------------------------------------------------------+
//| Create                                                           |
//+------------------------------------------------------------------+
bool CPanelDialogQ::CreateQ(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2,string QText)
  {
   if(!CAppDialog::Create(chart,name,subwin,x1,y1,x2,y2))
      return(false);
//--- create dependent controls
   if(!CreateLabel_Q_text( QText))
      return(false);
   if(!CreateButton_Yes())
      return(false);
   if(!CreateButton_No())
      return(false);
//--- succeed
   return(true);
  }

//+------------------------------------------------------------------+
bool CPanelDialogQ::CreateLabel_Q_text(string QT)
  {
//--- coordinates
   int x1=INDENT_LEFTQ;
   int y1=INDENT_TOPQ;
   int x2=ClientAreaWidth()-(INDENT_RIGHTQ+BUTTON_WIDTHQ+CONTROLS_GAP_XQ);
   int y2=y1+EDIT_HEIGHTQ;

//--- create
   if(!m_Label_Q_text.Create(m_chart_id,"QT",m_subwin,x1,y1,x2,y2))
      return(false);
   if(!m_Label_Q_text.Text(QT))
      return(false);
   if(!m_Label_Q_text.FontSize(12))
      return(false);
   if(!m_Label_Q_text.Color(clrBlack))
      return(false);
   if(!m_Label_Q_text.ColorBorder(clrBlack))
      return(false);
   if(!m_Label_Q_text.ColorBackground(clrBlack))
      return(false);
   if(!Add(m_Label_Q_text))
      return(false);

   m_Label_Q_text.Alignment(WND_ALIGN_WIDTH,INDENT_LEFTQ,0,INDENT_RIGHTQ+BUTTON_WIDTHQ+CONTROLS_GAP_XQ,0);
//--- succeed
   return(true);
  }
//+------------------------------------------------------------------+
bool CPanelDialogQ::CreateButton_Yes(void)
  {
//--- coordinates
   int x1=INDENT_LEFTQ;
   int y1=INDENT_TOPQ+CONTROLS_GAP_YQ;
   int x2=x1+BUTTON_WIDTHQ;
   int y2=y1+BUTTON_HEIGHTQ;
//--- create
   if(!m_button_Yes.Create(m_chart_id,m_name+"Yes",m_subwin,x1,y1,x2,y2))
      return(false);
   if(!m_button_Yes.Text("Yes"))
      return(false);
   if(!Add(m_button_Yes))
      return(false);
   m_button_Yes.Alignment(WND_ALIGN_RIGHT,0,0,INDENT_RIGHTQ+CONTROLS_GAP_XQ*2,0);
//--- succeed
   return(true);
  }
//+------------------------------------------------------------------+
bool CPanelDialogQ::CreateButton_No(void)
  {
//--- coordinates
   int x1=INDENT_LEFTQ+CONTROLS_GAP_XQ;
   int y1=INDENT_TOPQ+CONTROLS_GAP_YQ;
   int x2=x1+BUTTON_WIDTHQ;
   int y2=y1+BUTTON_HEIGHTQ;
//--- create
   if(!m_button_No.Create(m_chart_id,m_name+"NO",m_subwin,x1,y1,x2,y2))
      return(false);
   if(!m_button_No.Text("NO"))
      return(false);
   if(!Add(m_button_No))
      return(false);
   m_button_No.Alignment(WND_ALIGN_RIGHT,0,0,INDENT_RIGHTQ+CONTROLS_GAP_XQ*1,0);
//--- succeed
   return(true);
  }
//+------------------------------------------------------------------+
void CPanelDialogQ::OnClick_button_Yes(void)
  {
   Print("OnClick_button_Yes", "Last Error: ",GetLastError());
  }
//+------------------------------------------------------------------+
void CPanelDialogQ::OnClick_button_No(void)
  {
   Print("OnClick_button_No", "Last Error: ",GetLastError());
   m_button_Yes.Hide();
  }
//+------------------------------------------------------------------+

原指标代码

//+------------------------------------------------------------------+
//|                                             Indicator_Q_Test.mq4 |
//|                        Copyright 2020, MetaQuotes Software Corp. |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_chart_window
#include  <WinUser32.mqh>
#include "PanelDialog_Q.mqh"
CPanelDialogQ ExtDialog;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   if(!ExtDialog.CreateQ(0,"Question",0,100,100,400,230,"This the test Question?"))
      return(INIT_FAILED);
//--- run application
   if(!ExtDialog.Run())
      return(INIT_FAILED);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
//---
  }
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//---
      ExtDialog.ChartEvent(id,lparam,dparam,sparam);
  }
//+------------------------------------------------------------------+
解决方案

在MQL的CAppDialog框架中,.Hide()仅隐藏控件的视觉显示,控件的事件响应区域并未被移除,所以点击原位置仍会触发事件。以下是两种有效的解决方式:

方式一:彻底移除控件(适合无需恢复的场景)

调用Remove()方法将控件从对话框的管理列表中移除,这样控件的事件监听会完全失效,同时视觉上也会隐藏。

修改OnClick_button_No()方法:

void CPanelDialogQ::OnClick_button_No(void)
{
   Print("OnClick_button_No", "Last Error: ",GetLastError());
   m_button_Yes.Hide();
   Remove(m_button_Yes); // 从对话框中移除控件,彻底停止事件响应
}

方式二:禁用+隐藏+事件判断(适合需要恢复的场景)

如果之后需要重新显示按钮并恢复功能,不建议移除控件,而是通过禁用控件+事件逻辑判断来实现:

  1. 修改OnClick_button_Yes()方法,增加控件启用状态判断:
void CPanelDialogQ::OnClick_button_Yes(void)
{
   // 仅当控件启用时执行逻辑
   if(m_button_Yes.Enabled()){
      Print("OnClick_button_Yes", "Last Error: ",GetLastError());
   }
}
  1. 修改OnClick_button_No()方法,同时禁用和隐藏按钮:
void CPanelDialogQ::OnClick_button_No(void)
{
   Print("OnClick_button_No", "Last Error: ",GetLastError());
   m_button_Yes.Enable(false); // 禁用控件交互
   m_button_Yes.Hide(); // 隐藏控件
}

若需要恢复按钮功能,执行以下代码即可:

m_button_Yes.Enable(true);
m_button_Yes.Show();

关键说明

  • .Hide()/.Show()仅控制可见性,不影响事件响应
  • .Enable(false)会禁用控件的交互状态,但部分框架中仍可能触发事件,因此需要在事件处理中额外判断状态
  • Remove()会释放控件资源,恢复时需重新调用创建方法(如CreateButton_Yes())

内容的提问来源于stack exchange,提问作者user2647394

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 08:33:35