Search code examples
.netwinformsvisual-studio-2008visual-c++

Why does Visual C++ Designer not work after I added a control to my form?


My wanted to turn on double buffering in a panel, but the only way we could get the DoubleBuffered property to turn on was to create a new class that inherited from System::Windows::Form::Panel, like so:

#include "stdafx.h"

public ref class CPPIConfig: public System::Windows::Forms::Panel
{
public: CPPIConfig()
        {
            this->DoubleBuffered = true;
        }
};

And our form looks like this, now:

#pragma once
#using <system.drawing.dll>
#include "CPPIConfig.h"

[...]

public ref class C3_User_Interface : public System::Windows::Forms::Form
    {
      [...]
      public: CPPIConfig^ pPPI;
      [...]
    }

void InitializeComponent(void)
    {
        [...]
        this->pPPI = (gcnew CPPIConfig());
        [...]
    }
[...]

It builds and runs, no problem. However, when I try to view the form in design mode now, I'm getting the following error:

C++ CodeDOM parser error: Line: 144, Column: 15 --- Unknown type 'CPPIConfig'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built.

My questions:

  1. Why does design mode not work, even if the code builds and runs? I've tried several clean builds, but that doesn't look to be the issue.
  2. Is there a way I can set DoubleBuffered to true without using this method?

Solution

  • The big hangup here really stems from my mixture of managed vs. unmanaged code. I went to MSDN to read more about it, but the upshot is this: Visual Studio can't handle my CPPIConfig class within this context because it's unmanaged/native code.

    From the answer provided for a similar question:

    The Windows Forms Designer cannot reflect on mixed-mode EXEs. Make sure you compile with /clr:pure or move any class that require design time support (e.g. the components and controls on the form) to a class library project.

    Reflection, as this MSDN page points out, is what the Design view is using to render the Form within the IDE. In a few words, this is what reflection is:

    Reflection allows known data types to be inspected at runtime. Reflection allows the enumeration of data types in a given assembly, and the members of a given class or value type can be discovered. This is true regardless of whether the type was known or referenced at compile time. This makes reflection a useful feature for development and code management tools.

    Ahh. This is starting to make sense.

    There's two ways to fix this problem, as far as I can tell.

    Use /clr:pure in your project properties. This changes the Common Language Runtime support for the project. From this MSDN page:

    Pure assemblies (compiled with /clr:pure) can contain both native and managed data types, but only managed functions. Like mixed assemblies, pure assemblies allow interop with native DLLs through P/Invoke (see Using Explicit PInvoke in C++ (DllImport Attribute)), but C++ Interop features are not available. Moreover, pure assemblies cannot export functions that are callable from native functions because entry points in a pure assembly use the __clrcall calling convention.

    Create a class library project. As the other answer suggested, if I move the files to a class library project and reference it that way, I wouldn't see this problem. As I understand it, it would make CPPIConfig managed code.

    Ultimately, structural limitations make neither of those options viable, and in the interest of time, we've decided to forego double buffering on the panel for now. Oh well, at least I learned more about this environment!