C# 在子窗体中按Enter键可以强制我返回主窗体

C# 在子窗体中按Enter键可以强制我返回主窗体,c#,winforms,panel,enter,C#,Winforms,Panel,Enter,在我描述问题之前,让我解释一下程序是什么样的: 我有一个程序,我使用一个窗口作为主机来显示所有子窗体。这个窗口(主面板窗体)有一个面板控件。我将一个子窗体附加到面板控件中以显示该子窗体,然后将其分离并附加另一个子窗体。通过这种方式,用户只能从我的应用程序中看到一个窗口,而不能从我的应用程序中看到多个窗口。主面板窗体具有一种机制,用于管理子窗体的附加/分离以及子窗体之间的通信 当程序启动时,主面板窗体将主菜单子窗体附加到其面板控件中。当用户从主菜单子窗体中选择菜单选项时,主菜单子窗体会告知主面板窗

在我描述问题之前,让我解释一下程序是什么样的:

我有一个程序,我使用一个窗口作为主机来显示所有子窗体。这个窗口(主面板窗体)有一个面板控件。我将一个子窗体附加到面板控件中以显示该子窗体,然后将其分离并附加另一个子窗体。通过这种方式,用户只能从我的应用程序中看到一个窗口,而不能从我的应用程序中看到多个窗口。主面板窗体具有一种机制,用于管理子窗体的附加/分离以及子窗体之间的通信

当程序启动时,主面板窗体将主菜单子窗体附加到其面板控件中。当用户从主菜单子窗体中选择菜单选项时,主菜单子窗体会告知主面板窗体用户已通过回调功能选择的选项。此时,主面板窗体将从面板控件分离主菜单子窗体(隐藏它,而不是销毁它),然后将与用户所选选项对应的子窗体附加到面板控件

除了附加/分离机制相当复杂之外,其他一切都正常工作。共谋不是问题所在。问题是,当用户点击子窗体中的Enter键时,程序会将用户踢回主面板窗体,而不是让子窗体处理Enter键。此问题仅在用户以前打开子窗体一次时发生。请记住,在我拆下子窗体后,我会隐藏子窗体,我不会破坏它。不知何故,这触发了错误

我可以通过在子窗体与面板控件分离时销毁它(然后在需要时重新创建它)来解决这个问题。但是我的应用程序要求当用户返回子表单时,子表单中的信息应该保持不变。实现这一点最简单的方法是隐藏子窗体,然后在需要再次显示时取消隐藏它

我目前正在通过捕获和丢弃ProcessCmdKey()事件处理程序中的密钥来解决此问题。但这似乎是一个黑客行为,并没有真正解决问题的根源。此外,如果子窗体需要对Enter键执行某些操作(例如尝试将Enter键转换为Tab键),我需要告诉ProcessCmdKey()不要对该子窗体执行此操作。奇怪的是,在这种情况下,我需要要求主面板窗体中的ProcessCmdKey()不要对子窗体执行此操作(而不是要求子窗体中的ProcessCmdKey()不要执行此操作)——这就是为什么我说这是一种攻击

以下是主面板形式的简化版本,我认为问题的根源可能是:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;           // For using Debug.Assert().
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace TestEnterKeyProblem
   {
   // Constants related to calling back functions
   // -------------------------------------------

   public enum MainMenu_SelOpt : int
      {
      DlgBoxNormal        = 1,
      DlgBoxChgEnterToTab = 2
      }

   // Delegates for call-backs from this sub-form
   // -------------------------------------------

   // Call back function to communicate from the
   // main-menu to this main panel.
   public delegate void CallBackFuncFromMainMenu
      (
      MainMenu_SelOpt fMenuOptSelected
      );

   // Call back function to communicate from the
   // dialog-box-normal to this main panel.
   public delegate void CallBackFuncFromDlgBoxNormal();

   // Call back function to communicate from the
   // dialog-box-change-enter-to-tab to this main panel.
   public delegate void CallBackFuncFromDlgBoxChgEnterToTab();

   // Definition of frmMainPanel
   // --------------------------

   public partial class frmMainPanel : Form
      {
      // These flags tell us which sub-form is the active form
      public enum ActiveFrm : int
         {
         Is_MainMenu            = 31,
         Is_DlgBoxNormal        = 32,
         Is_DlgBoxChgEnterToTab = 33
         }

      // Data members

      //....This flag indicate which window in this application
      //....has the input focus.
      private ActiveFrm activeFrm = ActiveFrm.Is_MainMenu;

      //....The following are the sub-forms that can be attached
      //....to the main panel control of this object.
      private frmMainMenu            subfrmMainMenu            = new frmMainMenu();
      private frmDlgBoxNormal        subfrmDlgBoxNormal        = new frmDlgBoxNormal();
      private frmDlgBoxChgEnterToTab subfrmDlgBoxChgEnterToTab = new frmDlgBoxChgEnterToTab();

      // Class constructor

      public frmMainPanel()
         {
         InitializeComponent();

         this.activeFrm = ActiveFrm.Is_MainMenu;
         }

      // Event handlers

      private void frmMainPanel_Load(object sender, EventArgs e)
         {
         // Attach the main-menu sub-form to the panel-control.
         this.AttachMainMenuSubFormToPanelCtrl();
         }

      // Attach various sub-forms to the panel control in this form.

      private void AttachMainMenuSubFormToPanelCtrl()
         // Attach the main-menu sub-form to the panel control.
         // Note: We don't detach the main menu sub-form. This means we only
         //       need to use this routine to attach the main menu sub-form
         //       only once. We detach all other sub-forms.
         {
         // Attach the main-menu sub-form to the panel.
         this.subfrmMainMenu.TopLevel = false;
            // Set it to false because we cannot add a top-control
            // into another control (the main panel).
         this.panelMain.Controls.Add( this.subfrmMainMenu );

         // Tell the main menu sub-form which function to call back.
         CallBackFuncFromMainMenu funcCallBackFromMainMenu =
            new CallBackFuncFromMainMenu( this.OnCallBackFromMainMenu );
         this.subfrmMainMenu.SetCallBackFunc( funcCallBackFromMainMenu );

         // Now, we can activate the main menu.
         this.subfrmMainMenu.Visible = true;
         this.activeFrm = ActiveFrm.Is_MainMenu;
         }

      private void AttachDlgBoxNormalSubFrmToPanelCtrl()
         // Attach the dialog-box-normal sub-form to the panel-control.
         {
         // Attach the dialog-box-normal sub-form to the panel.
         this.subfrmDlgBoxNormal.TopLevel = false;
            // Set it to false because we cannot add a top-control
            // into another control (the main panel).
         this.panelMain.Controls.Add( this.subfrmDlgBoxNormal );

         // Tell the dialog-box-normal sub-form which function to call back.
         CallBackFuncFromDlgBoxNormal funcCallBackFromDlgBoxNormal =
            new CallBackFuncFromDlgBoxNormal( this.OnCallBackFromDlgBoxNormal );
         this.subfrmDlgBoxNormal.SetCallBackFunc( funcCallBackFromDlgBoxNormal );

         // Now, we can hide the main menu and show the
         // dialog-box-normal sub-form.
         this.subfrmMainMenu.Visible = false;
         this.subfrmDlgBoxNormal.Visible = true;
         this.activeFrm = ActiveFrm.Is_DlgBoxNormal;
         }

      private void AttachDlgBoxChgEnterToTabSubFrmToPanelCtrl()
         // Attach the dialog-box-change-enter-to-tab sub-form to the
         // panel-control.
         {
         // Attach the dialog-box-change-enter-to-tab sub-form to the panel.
         this.subfrmDlgBoxChgEnterToTab.TopLevel = false;
            // Set it to false because we cannot add a top-control
            // into another control (the main panel).
         this.panelMain.Controls.Add( this.subfrmDlgBoxChgEnterToTab );

         // Tell the dialog-box-change-enter-to-tab sub-form which
         // function to call back.
         CallBackFuncFromDlgBoxChgEnterToTab funcCallBackFromDlgBoxChkEnterToTab =
            new CallBackFuncFromDlgBoxChgEnterToTab( this.OnCallBackFromDlgBoxChgEnterToTab );
         this.subfrmDlgBoxChgEnterToTab.SetCallBackFunc( funcCallBackFromDlgBoxChkEnterToTab );

         // Now, we can hide the main menu and show the
         // dialog-box-change-enter-to-tab sub-form.
         this.subfrmMainMenu.Visible = false;
         this.subfrmDlgBoxChgEnterToTab.Visible = true;
         this.activeFrm = ActiveFrm.Is_DlgBoxChgEnterToTab;
         }

      // Call-back function

      public void OnCallBackFromMainMenu
         (
         MainMenu_SelOpt fMenuOptSelected
         )
         // The main menu sub-form tells the main panel which
         // menu option that the user has selected.
         {
         ////////////////////////////////////////
         if ( this.activeFrm != ActiveFrm.Is_MainMenu )
            {
            String sCurActiveForm = "N/A";
            if      ( this.activeFrm == ActiveFrm.Is_DlgBoxNormal        ) sCurActiveForm = "Is_DlgBoxNormal";
            else if ( this.activeFrm == ActiveFrm.Is_DlgBoxChgEnterToTab ) sCurActiveForm = "Is_DlgBoxChgEnterToTab";

            String sCurMenuOptSelected = "N/A";
            if      ( fMenuOptSelected == MainMenu_SelOpt.DlgBoxNormal        ) sCurMenuOptSelected = "DlgBoxNormal";
            else if ( fMenuOptSelected == MainMenu_SelOpt.DlgBoxChgEnterToTab ) sCurMenuOptSelected = "DlgBoxChgEnterToTab";

            String sDebugMsg =
               String.Concat( "frmMainPanel.cs - OnCallBackFromMainMenu() : ",
                              "Active form is supposed to be 'Is_MainMenu'; but it is '", sCurActiveForm, "'. ",
                              "Please note that menu-option-selected is '", sCurMenuOptSelected, "'. ",
                              "This is an error." );
            MessageBox.Show( sDebugMsg, "Assertion Error", MessageBoxButtons.OK, MessageBoxIcon.Error );
            }
         ////////////////////////////////////////
         Debug.Assert( fMenuOptSelected == MainMenu_SelOpt.DlgBoxNormal        ||
                       fMenuOptSelected == MainMenu_SelOpt.DlgBoxChgEnterToTab );

         if      ( fMenuOptSelected == MainMenu_SelOpt.DlgBoxNormal        ) this.AttachDlgBoxNormalSubFrmToPanelCtrl();
         else if ( fMenuOptSelected == MainMenu_SelOpt.DlgBoxChgEnterToTab ) this.AttachDlgBoxChgEnterToTabSubFrmToPanelCtrl();

         // Note: We don't detach the main menu sub-form from the
         //       main panel control.
         }

      public void OnCallBackFromDlgBoxNormal()
         // The dialog-box-normal sub-form tells the main panel
         // that the user is done.
         {
         Debug.Assert( this.activeFrm == ActiveFrm.Is_DlgBoxNormal );

         // Detach the dialog-box-normal sub-form from the main panel
         // control. We don't delete it. We keep it hidden.
         this.subfrmDlgBoxNormal.Visible = false;
         this.panelMain.Controls.Remove( this.subfrmDlgBoxNormal );

         // Go back to the main menu.
         this.subfrmMainMenu.Visible = true;
         this.activeFrm = ActiveFrm.Is_MainMenu;
         }

      public void OnCallBackFromDlgBoxChgEnterToTab()
         // The dialog-box-change-enter-to-tab sub-form tells the
         // main panel that the user is done.
         {
         Debug.Assert( this.activeFrm == ActiveFrm.Is_DlgBoxChgEnterToTab );

         // Detach the dialog-box-change-enter-to-tab sub-form from the
         // main panel control. We don't delete it. We keep it hidden.
         this.subfrmDlgBoxChgEnterToTab.Visible = false;
         this.panelMain.Controls.Remove( this.subfrmDlgBoxChgEnterToTab );

         // Go back to the main menu.
         this.subfrmMainMenu.Visible = true;
         this.activeFrm = ActiveFrm.Is_MainMenu;
         }

      }
   }
当用户点击子窗体中的Enter键时(在之前打开子窗体一次之后),程序将以某种方式转到上面显示的主面板窗体中的OnCallBackFromMain菜单()(而不是允许子窗体处理Enter键,或返回子窗体的回调函数)

我试图附加示例程序的工作版本。但我不知道如何在这个论坛上做到这一点。如果你想试试这个示例程序,请告诉我,我会把它上传到一个公共FTP站点

我搞不懂这个。你能帮我修一下吗?提前谢谢


陈杰伦

猜一猜。。。由于我没有看到表格的相关代码:


enter键是触发表单上的
按钮
单击事件。按钮的
对话框结果
属性设置为除
之外的其他属性

谢谢。但是否,所有表单的AcceptButton均为(无)。程序中所有按钮的DialogResult均为None。若要了解问题的原因,请从此处下载程序工作版本的源代码的ZIP文件。这是一个简化的程序,只是为了说明问题。编译并构建它,运行它以查看主菜单。从主菜单中,选择要查看子窗体的链接中的任何一个,关闭子窗体,返回主菜单,再次选择相同的链接,查看相同的子窗体,然后按Enter键并查看错误消息。@JayChan无法使用此zip文件,缺少子目录(AssemblyInfo、Resources.resx等)中所有必需的文件很抱歉,最后一个ZIP文件缺少“属性”子文件夹。我上传了一个新的ZIP文件,其中包括丢失的“属性”子文件夹和所有其他文件。你可以从这里下载。谢谢你帮我。