Question

I've taken someone's open source for a Metro Forms implementation in older versions of Windows; one that I intend to re-write in the future, but I would like to get 'working' at the moment.

** Edit ** :: I've reinstated a base class of System.Windows.Forms in this context and am still yielding the same result.

Right now I am encountering a Parameter Count Mismatch exception in the WndProc method that has been overridden in said MetroFramework ( Original by theilj / 'Extended' (In-Use)( With some corrections ) by viperneo )

I am likely to consult with either or both of these gentlemen in regard to the issue but I figured opening a question with the details might yield faster results.

** Edit ** :: I've removed Form references to the above mentioned projects, and am now only using base forms to generate this application's UI. I believe my next step is to roll-back User Controls. I'd rather not.

There are a couple of methods involved in this process; and I have some debugging information to attach; so here we go.

Per 'Wine's documentation; I've found a full list of Windows messages that can be passed to WndProc by default. It would seem at the moment that my application's WndProc method is receiving messages not listed in this documentation.

At the time of the encountered exception, In the thread where the exception is generated, I found the following information:

Thread:

'Main Thread'

Stack Trace:

** EDIT ** :: This is the INITIAL stack trace surrounding the exception. Following it is an updated stack trace without the MetroForm implementation.

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

** EDIT ** :: Updated Stack Trace ( Does not appear to differ ):

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

Inside the WndProc Override:

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 )
        {

        }
    }
}

You'll note that I've commented out the first case statement in the above code; case 0xC2BA - which is the Msg I receive before this window crashes. After some time scouring the internet for this code, in either its decimal or hex representation, I've found no indication that this is a normal message; However, I've also not managed to find it defined anywhere in the source code to the project I have inherited from.

I've taken this a step further up the chain to examine what element of my code is forcing this code to be produced, and apparently, it's coming from the ShowDialog method that I've invoked on the controls parent form.

I implement the ShowDialog method as such, and I have overriden this ShowDialog method in my own form for the sake of debugging - it has yielded little information:

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;
        }
    }
}

For the sake of being thorough; at the time of the exception, the Message instance received from the parent process is as follows:

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

At the time of encountering the problem, the overriden method's switch statement has been passed over with no entry into any of the case statements ( unless I uncomment the 0xc2ba lines ).

Finally, and I think this should already be clear, the exception is a TargetParameterCountException and the message is Parameter count mismatch. I've also examined the output window for any information, and the most I get is:

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

I might note that a baseline implementation of the controls I am using ( as per the project they are referenced from ) does work. The supporting 'MetroFramework' solution has a 'demo' project that implements at the very least all of the controls that I use in my own implementation.

An additional note of probable interest - after catching the exception generated in the WndProc method, if I allow program execution to continue, this form and the parent both still operate nominally, and the exception is never encountered again.

Hope someone has some insight, I'm pulling my hair out. Cheers gentlemen.

Was it helpful?

Solution

The invocation that is generating the error produced above occurs in a thread other than the one in which the exception is generated; regardless of the accurate call stack that was posted.

To determine what thread is generating this issue, it is necessary to examine the entirety of all running threads at the time of the exception, and determine whether or not any of those threads were invoking any methods on the control in question; as was the case in this circumstance.

To create a clear answer to this question I will further expand on this answer at a 'better' time ( likely this evening ).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top