Form.ShowDialog()之后的“参数计数不匹配”在WndProc覆盖中

时间:2014-03-20 17:17:55

标签: c# winforms exception message-queue wndproc

我在旧版本的Windows中使用某人的开源来实现Metro Forms;一个我打算将来重写的,但我想在此刻“正常工作”。

**编辑** ::我在此上下文中恢复了System.Windows.Forms的基类,但仍然产生相同的结果。

目前我在Parameter Count Mismatch方法中遇到WndProc个例子,该方法已在MetroFramework {Original theilj / {{3}中被覆盖} 'Extended' (In-Use)( With some corrections )

我可能会就这个问题咨询这些先生中的一位或两位,但我认为打开一个问题,细节可能会产生更快的结果。

**编辑** ::我删除了对上述项目的表单引用,现在我只使用基本表单来生成此应用程序的UI。我相信我的下一步是回滚用户控件。我不愿意。

这个过程涉及几种方法;我有一些调试信息要附加;所以我们走了。

Per'Wine's viperneo;我找到了一个完整的Windows消息列表,默认情况下可以传递给WndProc。目前我的应用程序的WndProc方法似乎正在接收documentation中未列出的消息。

遇到异常时,在生成异常的线程中,我找到了以下信息:

主题:

'Main Thread'

堆栈追踪:

** EDIT ** ::这是围绕异常的INITIAL堆栈跟踪。接下来是没有MetroForm实现的更新堆栈跟踪。

at System.Reflection.RuntimeMethodInfo.UnsafeInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Delegate.DynamicInvokeImpl(Object[] args)
at System.Windows.Forms.Control.InvokeMarshaledCallbackDo(ThreadMethodEntry tme)
at System.Windows.Forms.Control.InvokeMarshaledCallbackHelper(Object obj)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Windows.Forms.Control.InvokeMarshaledCallback(ThreadMethodEntry tme)
at System.Windows.Forms.Control.InvokeMarshaledCallbacks()
at System.Windows.Forms.Control.WndProc(Message& m)
at MetroFramework.Controls.MetroUserControlBase.WndProc(Message& m) in f:\Users\DigitalJedi\Documents\Development\Projects\C#\Supporting Projects\MetroFramework-master\MetroFramework\Controls\MetroControlBase.cs:line 4129

**编辑** ::更新了堆栈跟踪(似乎没有区别):

at System.Reflection.RuntimeMethodInfo.UnsafeInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Delegate.DynamicInvokeImpl(Object[] args)
at System.Windows.Forms.Control.InvokeMarshaledCallbackDo(ThreadMethodEntry tme)
at System.Windows.Forms.Control.InvokeMarshaledCallbackHelper(Object obj)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Windows.Forms.Control.InvokeMarshaledCallback(ThreadMethodEntry tme)
at System.Windows.Forms.Control.InvokeMarshaledCallbacks()
at System.Windows.Forms.Control.WndProc(Message& m)
at MetroFramework.Controls.MetroUserControlBase.WndProc(Message& m) in f:\Users\DigitalJedi\Documents\Development\Projects\C#\Supporting Projects\MetroFramework-master\MetroFramework\Controls\MetroControlBase.cs:line 4143

在WndProc覆盖内:

public class MetroUserControlBase : UserControl, IMetroContainerControl, IMetroControl, IMetroStyledComponent
{
    protected override void WndProc(ref Message m)
    {
        try
        {
            if (DesignMode)
            {
                base.WndProc(ref m);
                return;
            }

            switch (m.Msg)
            {
                //case 0xC2BA:
                    //return;;

                //case WinApi.Messages.WM_CTLCOLORBTN:
                //Debug.WriteLine("WM_CTLCOLORBTN", GetType().Name);
                //break;
                //case WinApi.Messages.WM_CTLCOLORSTATIC:
                //Debug.WriteLine("WM_CTLCOLORSTATIC", GetType().Name);
                //break;
                case WinApi.Messages.WM_CTLCOLOREDIT:
                    Debug.WriteLine("WM_CTLCOLOREDIT", GetType().Name);
                    break;
                case WinApi.Messages.WM_CTLCOLORDLG:
                    Debug.WriteLine("WM_CTLCOLORDLG ", GetType().Name);
                    break;
                case WinApi.Messages.WM_CTLCOLORLISTBOX:
                    Debug.WriteLine("WM_CTLCOLORLISTBOX", GetType().Name);
                    break;
                case WinApi.Messages.WM_CTLCOLORSCROLLBAR:
                    Debug.WriteLine("WM_CTLCOLORSCROLLBAR ", GetType().Name);
                    break;
            }
            // Line 4143
            base.WndProc(ref m);
        }
        catch( Exception e )
        {

        }
    }
}

你会注意到我已经在上面的代码中注释掉了第一个case语句; case 0xC2BA - 这是我在此窗口崩溃之前收到的消息。经过一段时间在互联网上搜索此代码,无论是十进制还是十六进制表示,我都没有发现这是正常的消息;但是,我还没有设法在我继承的项目的源代码中的任何地方找到它。

我已经在链上进一步检查我的代码的哪个元素强制生成此代码,显然,它来自我在控件上调用的ShowDialog方法父母表格。

我实现了ShowDialog方法,为了调试,我已经以我自己的形式覆盖了这个ShowDialog方法 - 它几乎没有提供任何信息:

public partial class BaseProductionDialog : Provectusoft.Forms.MetroForm
{
    protected void PromptAuthentication()
    {
        if (this.DesignMode)
            return;
        else if (this.AuthenticationDialog.Visible)
            throw new Exception("The Media Minutes Live Captioning Production Client Authentication Dialog cannot be shown as it is already visible.");
        else
        {
            // This occurs but never concludes
            DialogResult Result = this.AuthenticationDialog.ShowDialog(this);

            if (Result == System.Windows.Forms.DialogResult.Yes)
            {
                this.BringToFront();

                this.Focus();

                return;
            }
            else
            {
                if (!this.IsAuthenticated)
                {
                    MessageBox.Show("There seems to have been an issue in your authentication. Please try again.");

                    this.PromptAuthentication();

                    return;
                }
                else
                {
                    return;
                }
            }
        }
    }

    public DialogResult ShowDialog(System.Windows.Forms.Form ParentForm)
    {
        if (this.IsAuthenticated)
            return DialogResult.Yes;
        else if( this.InvokeRequired )
            // This never occurs
            return (DialogResult) this.Invoke(new Action(delegate { this.ShowDialog(ParentForm); }));
        else
        {
            // This occurs but never concludes
            DialogResult Result = base.ShowDialog(ParentForm);

            if (this.IsAuthenticated)
                return DialogResult.Yes;
            else
                return DialogResult.No;
        }
    }
}

为了彻底;在异常时,从父进程收到的Message实例如下:

Msg = 0xC2BA ( 49850 )
HWnd = 0x1403f2 ( 1311730 )
wparam = 0x0
lparam = 0x0
result = 0x0

在遇到问题时,重写方法的switch语句已被传递,没有任何条目语句的输入(除非我取消注释0xc2ba行)。

最后,我认为这应该已经很明确了,例外是TargetParameterCountException,消息是Parameter count mismatch。我还检查了输出窗口的任何信息,我得到的最多是:

A first chance exception of type 'System.Reflection.TargetParameterCountException occurred in mscorlib.dll'

我可能会注意到我正在使用的控件的基线实现(根据它们引用的项目)确实有效。支持“MetroFramework”的解决方案有一个“演示”项目,至少可以实现我在自己实现中使用的所有控件。

可能感兴趣的另一个注意事项 - 在捕获WndProc方法中生成的异常之后,如果我允许程序执行继续,则此表单和父表单仍然名义上运行,并且永远不会再遇到异常。

希望有人有一些见解,我正在拔头发。干杯绅士们。

1 个答案:

答案 0 :(得分:1)

生成上述错误的调用发生在生成异常的线程之外的线程中;无论发布的准确调用堆栈如何。

要确定生成此问题的线程,有必要在异常时检查所有正在运行的线程的全部,并确定这些线程中是否有任何线程正在调用相关控件上的任何方法;就像这种情况一样。

为了对这个问题创建一个明确的答案,我将在“更好”的时间(可能是今晚)进一步扩展这个答案。