什么是X11错误以及为什么我会继续获取它们?

时间:2016-08-03 15:49:05

标签: c# events mono x11 porting

我正在开展一个项目,在这个项目中,我将一个旧的visual basic项目重写为c#,然后将其移植到带有触摸屏的linux终端上的mono。为了端口我将.exe文件放入我的linux目录并使用mono运行命令从终端运行它们,即:" mono program.exe"我在c#中使用了代码并且已经走了很长的路,但这是我目前的问题:

我移植的应用程序类似于您在机场用于打印登机牌的终端,仅适用于多式联运的行业。它也是一个数据库驱动的应用程序,所以我动态地将控件加载到页面上。鉴于这一切,在主屏幕上我有一些标签,文本框,图像和虚拟键盘。文本框是用户输入值的地方,他们可以点击图像或虚拟键盘输入密钥以便将其数据提交到数据库。当从这些点击事件调用页面处理函数时,我在窗体上的控件顶部显示一个新面板(不在设计器中),以阻止其他事件通过(旧的vb设计的一部分)

以下是我从图片中提出的事件:

    private void ctlPictureBox_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
    {
        _IsDown = false;
        ctlPictureBox.Invalidate();
        if (KioskLinux.Modules.Common.__TypeMode == 0) {
            if (ButtonEval(e.X, e.Y)) {
            //Event Handling is better than Sendkeys!
            //System.Windows.Forms.SendKeys.Send("{" + _ImageMethod + "}");
                EventHandler handler = KeyControlSelection;
                if (handler != null)
                {
                    handler(this, e);
                    Console.WriteLine("handler(this, e)");
                }
            }
        }
    }

这是我对图像的事件处理,这是我做的事件:

    void OnKeyControlSelection(object sender, EventArgs e)
    {
        try
        {
            ProcessPage(sender, ((KioskLinux.ProgramaticControls.KioskUI_KeyControl)sender)._ImageMethod); //Whatever key I am, do the ImageMethod
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error 1 in KioskLinux.Forms.frmMain.OnKeyControlSelection : " + ex);
        }

    }

这是我在键盘上发生的事件:我应该提一下,我通过映射出一个jpeg图像并从哈希表中发送相应的密钥来找到已按下的键。

    private void ctlkeyboard_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
    {
        if (ButtonEvalMap(e.X, e.Y, ref row, ref col) && KioskLinux.Modules.Common.__TypeMode == 0)
        {
            _LastRow = -1;
            _LastCol = -1;

            _DurationHeld = (System.DateTime.Now.Ticks - _TickDown) / 10000;
            SendKey(sender, e, row, col);
            this.ctlKeyboard.Invalidate();
        }
        else if (KioskLinux.Modules.Common.__TypeMode == 1)
        {
            if (ButtonEvalMap(e.X, e.Y, ref row, ref col) & KioskLinux.Modules.Common.__TypeMode == 1)
            {
                _LastRow = -1;
                _LastCol = -1;

                _DurationHeld = (System.DateTime.Now.Ticks - _TickDown) / 10000;
                SendKey(sender, e, row, col);
                this.ctlKeyboard.Invalidate();
            }
        }
    }

    public void SendKey(object sender, EventArgs e, int Row, int Col)
    {
        string KeyCode = string.Empty;
        //Due to a SendKeys incompatibility in mono with the "{ESC}" key, we had to simulate an "{ESC}" Keypress using its own eventhandler rather than sendkeys like everything else
        try
        {
            KeyCode = _KeyTable[Row.ToString() + "," + Col.ToString()].ToString();
            if (KeyCode == "{ESC}") {
                EventHandler handler = EscapeButtonPressedOnKeyboard;
                if (handler != null)
                {
                    handler(this, e);
                }
            }
            else {
                System.Windows.Forms.SendKeys.Send(KeyCode);
            }

        }
        catch (Exception ex)
        {
            Console.WriteLine("Error 1 in KioskLinux.ProgramaticControls.KioskUI_Keyboard.SendKey : " + ex);
        }
    }

这是我对键盘的事件处理(Sendkeys生成按键事件,我的主窗体在文本框获取键之前有keypreview):

    public void frmTablet_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
    {
        EnsureFocus();
        if (e.KeyChar == (char)13)
        {
            bool FoundHost = false;
            foreach (Control KeyPress_Culprit in this.pnlBrowserCase.Controls)
            {
                if ((KeyPress_Culprit is KioskLinux.ProgramaticControls.KioskUI_TextBox) || (KeyPress_Culprit is KioskLinux.ProgramaticControls.KioskUI_CombTextBox)) //If one of these on pnlBrowserCase
                {
                    FoundHost = true;
                    e.Handled = true;
                    //Logic stuff for Robust Scenario Handling
                    ProcessPage((KioskLinux.ProgramaticControls.KioskUI_TextBox)KeyPress_Culprit, "ENTER"); //They are both DirectCasted as KioskUI_Textbox in VB code
                }
            }
            if (!FoundHost)
            {
                foreach (Control KeyPress_Culprit in this.pnlBrowserCase.Controls)
                {
                    if (KeyPress_Culprit is KioskLinux.ProgramaticControls.KioskUI_KeyControl) //Enter KeyPress must have been generated by this
                    {
                        e.Handled = true;
                        ProcessPage((KioskLinux.ProgramaticControls.KioskUI_KeyControl)KeyPress_Culprit, "ENTER");
                    }
                }
            }

        }
        //Sendkeys does not work with ESC key in mono, and has a fatal error (core dumped)
        //I needed to use a "translation" to make sure the Virtual Keyboard ESC key would work on Linux using the # key, which is otherwise unused
        //The first case statement allows a "go back" from a "go back control"
        else if (e.KeyChar == (char)91 || e.KeyChar == (char)27) // Check for # or ESC character
        {
            if (MapKeyboardLastScreenToKeypressESC() == false)
            {
                foreach (Control KeyPress_Culprit in this.pnlBrowserCase.Controls)
                {
                    if (KeyPress_Culprit is KioskLinux.ProgramaticControls.KioskUI_KeyControl)
                    { //ESC KeyPress must have been generated by this
                        if (KeyPress_Culprit.Text == "ESC") {
                            e.Handled = true;
                            ProcessPage((KioskLinux.ProgramaticControls.KioskUI_KeyControl)KeyPress_Culprit, "ESC");

                        }

                    }
                }
            }
            //This allows a keyboard/virtual keyboard press to do what an escape KeyControl on the page would do.
            else
            {
                foreach (Control KeyPress_Culprit in this.pnlBrowserCase.Controls)
                {
                    if (KeyPress_Culprit is KioskLinux.ProgramaticControls.KioskUI_KeyControl)
                    { //ESC KeyPress must have been generated by this
                        if (KeyPress_Culprit.Text == "ESC")
                        {
                            e.Handled = true;
                            ProcessPage((KioskLinux.ProgramaticControls.KioskUI_KeyControl)KeyPress_Culprit, "ESC");

                        }

                    }
                }
            }
        }
        else
        {
            e.Handled = false;
        }
    }

    void OnEscapeButtonPressedOnKeyboard(object sender, EventArgs e)
    {
        //Due to a SendKeys incompatibility in mono with the "{ESC}" key, we had to simulate an "{ESC}" Keypress using its own eventhandler rather than sendkeys like everything else
        KeyPressEventArgs myKeyPressEventArgs = new KeyPressEventArgs((char)(27));
        frmTablet_KeyPress(this, myKeyPressEventArgs);
    }

当我使用虚拟键盘处理页面时,它在单声道中工作得很漂亮,但是当我使用图像时,我在单声道中得到x11错误。我认为这与我在主表单类中处理页面时没有使用图像点击处理事件有关,但我不确定:

这是我的单声道堆栈跟踪:

X11 Error encountered: 
  Error: BadWindow (invalid Window parameter)
  Request:     40 (0)
  Resource ID: 0x1C000B5
  Serial:      4077
  Hwnd:        Hwnd, Mapped:True ClientWindow:0x1C000B5, WholeWindow:0x1C000B4, Zombie=True, Parent:[Hwnd, Mapped:True ClientWindow:0x1C000B1, WholeWindow:0x1C000B0, Zombie=True, Parent:[<null>]]
  Control:     <handle 1C000B5 non-existant>   at System.Environment.get_StackTrace()
   at System.Windows.Forms.XplatUIX11.HandleError(IntPtr display, XErrorEvent ByRef error_event)
   at System.Windows.Forms.XplatUIX11.XTranslateCoordinates(IntPtr , IntPtr , IntPtr , Int32 , Int32 , Int32 ByRef , Int32 ByRef , IntPtr ByRef )
   at System.Windows.Forms.XplatUIX11.ScreenToClient(IntPtr handle, Int32 ByRef x, Int32 ByRef y)
   at System.Windows.Forms.XplatUIX11.GetMessage(System.Object queue_id, MSG ByRef msg, IntPtr handle, Int32 wFilterMin, Int32 wFilterMax)
   at System.Windows.Forms.XplatUIX11.PeekMessage(System.Object queue_id, MSG ByRef msg, IntPtr hWnd, Int32 wFilterMin, Int32 wFilterMax, UInt32 flags)
   at System.Windows.Forms.XplatUIX11.DoEvents()
   at System.Windows.Forms.XplatUI.DoEvents()
   at System.Windows.Forms.Application.DoEvents()
   at KioskLinux.Forms.frmMain.Reload()
   at KioskLinux.Forms.frmMain.ProcessPage(System.Object sender, System.String Method)
   at KioskLinux.Forms.frmMain.OnKeyControlSelection(System.Object sender, System.EventArgs e)
   at KioskLinux.ProgramaticControls.KioskUI_KeyControl.ctlPictureBox_MouseUp(System.Object sender, System.Windows.Forms.MouseEventArgs e)
   at System.Windows.Forms.Control.OnMouseUp(System.Windows.Forms.MouseEventArgs e)
   at System.Windows.Forms.Control.WmLButtonUp(Message ByRef m)
   at System.Windows.Forms.Control.WndProc(Message ByRef m)
   at System.Windows.Forms.Control+ControlWindowTarget.OnMessage(Message ByRef m)
   at System.Windows.Forms.Control+ControlNativeWindow.WndProc(Message ByRef m)
   at System.Windows.Forms.NativeWindow.WndProc(IntPtr hWnd, Msg msg, IntPtr wParam, IntPtr lParam)
   at System.Windows.Forms.XplatUIX11.DispatchMessage(MSG ByRef msg)
   at System.Windows.Forms.XplatUI.DispatchMessage(MSG ByRef msg)
   at System.Windows.Forms.Application.RunLoop(Boolean Modal, System.Windows.Forms.ApplicationContext context)
   at System.Windows.Forms.Form.ShowDialog(IWin32Window owner)
   at System.Windows.Forms.Form.ShowDialog()
   at KioskLinux.Modules.modUtilities.Main()

1 个答案:

答案 0 :(得分:0)

尝试调用,因为您必须同步线程。

    public delegate void delInvokeForm(Form form, string arg1, string arg2);

    internal void InvokeForm(Form form, string arg1, string arg2)
    { 
        if (form != null)
        {
            if (form.InvokeRequired)
            {
                form.BeginInvoke(new delInvokeForm(InvokeForm), form, arg1, arg2); //you can add more args..
            }
            else
            {          
        //...do        your stuff here
    }
        }
    }