C++/CLI VS2005, WFC andinstantiate, and use a class without messing up the "designer"

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • MACKTEK
    New Member
    • Mar 2008
    • 40

    C++/CLI VS2005, WFC andinstantiate, and use a class without messing up the "designer"

    Intro:
    I have recently started programming in C++/CLI. I have done a lot of research on the net trying to locate an answer to this problem, but there seems to be a lack of Tutorials and books on C++/CLI.
    I have read 4 of the published books as best I could. The one book that has a great deal of info for my interest was Pro Visual C++/CLI and the .NET 2.0 platform by Fraser.

    Problem:
    Using VS2005 C++ and writing C++/CLI code, and using the "Designer", I created a basic Windows form, populated it with a menustrip, and an Open File menu (short snippet of C++/CLI from "Form1.h":

    Code:
    public: System::Void openToolStripMenuItem_Click(System::Object^  sender, System::EventArgs^  e)
    			 {
    				// System::Windows::Forms::ToolStripMenuItem^  openToolStripMenuItem;
    				static int ii=1;
    				openFileDialog1->ShowDialog();  // *** has memory leak must be disposed.
    				String^ filePath = openFileDialog1->FileName;
    				label1->Text = filePath;
    				label2->Text = "Counting";
    				Dyn_XML_Obj.File_List->Add(filePath); // put path into File_List (keeps track of all open XML docs.)
    This all works as expected and places the filepath correctly as it loads properly in XmlDocument.

    However, inorder to get these working, I had to place the class definitions at the top of the Form like this:

    Code:
    #pragma once
    #include "stdafx.h"
    #include <stdio.h>
    #include <stdlib.h> // allows use of abort()
    #include <vector>	// include the STL vector (Standard Template Library for vector which is a type of list.
    #include <iostream> // To use iostream commands such as cout, cin
    #include <process.h> // so I can clear the screen.
    #using <System.xml.dll> // so we can access XmlDocument
    using namespace System::Xml;
    using namespace std; // so we can shorten from std::vector to vector 
    using namespace System::IO; // se we can use Directory methods
    using namespace System;
    using namespace System::ComponentModel;
    using namespace System::Collections;
    using namespace System::Windows::Forms;
    using namespace System::Data;
    using namespace System::Drawing;
    
    namespace WFC_3a {
    	int ii; // Put your variables here
    public ref class Dyn_XML_Class
    {
    public:
    	
    	ArrayList^ File_List; // Will hold the filenames of XML files.
    	ArrayList^ XML_List; // Will hold the XmlDocument objects for each VALID item in File_List.
    	
    	Dyn_XML_Class() // CONSTRUCTOR
    	{
    	File_List = gcnew ArrayList(16); // Initialize File_List with 16 empty items. 
    	XML_List = gcnew ArrayList(16); // Initialize XML_List with 16 empty items. 
    	Console::WriteLine("File_List Constructor Completed.");
    	}
    	void ADD()
    	{Console::WriteLine("You have called ADD.");}
    
    };
    public ref class XML_Class
    {
    public:
    	XmlDocument^ XML_Doc;
    	static int Doc_Total;
    	int My_Num;
    	XML_Class()
    	{
    	XML_Doc = gcnew XmlDocument();
    	My_Num=Doc_Total;
    	Doc_Total++;
    	}
    	void show()
    	{
    		// Console::WriteLine("hello, My_Num={0},{1}",My_Num,Doc_Total);
    	}
    };
    Problems:
    1. Once I placed the classes there I "Broke" the designer... and it would no longer work to let me see the visual layout of my form.
    2. Attempting to Move the class definitions to WFC_3a.cpp resulted in 82 errors that everything in those classes was missing and syntax errors.
    3. Attempting to move the classes to the same file Form1.h, but at the bottom also creates 82 errors:
    Form1.h(185) : error C2227: left of '->Add' must point to class/struct/union/generic type
    Form1.h(192) : error C2059: syntax error : '>'
    and many more "Missing ;" and Syntax errors.

    So, questions are:

    1. Where should I move these classes and what code should I use so that Form1 will recognize the classes... without damaging the "designer" functions of VS2005.

    Thank you.
  • Banfa
    Recognized Expert Expert
    • Feb 2006
    • 9067

    #2
    I have been using C++/CLI .NET 2 in VS 2005 and have had similar problems. I think the basic problem is that VS 2005 tries to put all the form1 code in Form1.h

    I have now move much of it out into cpp files including the form initialisation function (the really long one that sets all the properties of the items on your form).

    Once Form1.h contains mainly declarations and few definitions things seemed to get better for me.

    The other thing is to undo you work step by step (or step backto a working copy and slowly reapply your changes). You have most likely put something in the wrong place (inside a section reserved for editing by VS 2005) or something like that. I spent a couple of hours doing that to sort my project out a few weeks ago.

    Comment

    • MACKTEK
      New Member
      • Mar 2008
      • 40

      #3
      Thanks Banfa.
      I am sure the Designer has some mechanism for letting the programmer add classes into the program without causing errors.

      A guess to simplify my question:

      How do I add classes into Form1.h so that I can use the designer and ALSO use those classes/instances of classes within the delegates and events of the Form?

      Any example of a class that allows me to change button1->Text would be helpful. ( I already made the class, but it only works when the class is declared at the top of the form!)

      These simple things, I cannot find on the net.
      Should I put everything in a different file and include it? should I make it under the same namespace?

      Comment

      • Banfa
        Recognized Expert Expert
        • Feb 2006
        • 9067

        #4
        The correct way to add a class is to select Project -> Add Class ... from here you can add a new form, or component or other CLR class or you can add a C++ class. This will create a header(h) and code(cpp) file for the new class, although optionally you can create an inline class and not have the cpp file.

        If you create the class with a cpp file then you can check it compiles before you include you header into form1.h (towards the top).

        I have to admit that I do create classes by hand at times but generally only simple ones or ones that are similar to an existing class so a create with a copy/paste. With very few exceptions I stick to 1 class per header file. For me the exception is EventArg classes which are often extremely simple and really just data holders rather than fully fledged classes with there own methods.

        Originally posted by MACKTEK
        Any example of a class that allows me to change button1->Text would be helpful. ( I already made the class, but it only works when the class is declared at the top of the form!)
        Strictly speaking since button1 is create by the designer as private you should be trying to alter it via an outside class. If you are you are probably breaking the rule of keeping implementation and user interface separate. It can seem like a lot of hassle to do this but in the long run you end up with a more structure more easily maintained program. And it isn't to hard to do using events and delegates, have you class raise an event and your form create a delegate on that event then put your code to handle the event in that delegate which is part of the Form1 class and you have access to the provate data.

        If as in my project the class happens to be a component that runs in it's own thread then you will not be able to access the buttons (or other gui widgets) in that delegate because you will be executing in the wrong thread. You have to have a second delegate (again part of the Form1 class) and Invoke a call to it with the data, this causes the second delegate to be called in the context of the Form1 class handling thread.

        Originally posted by MACKTEK
        These simple things, I cannot find on the net.
        Should I put everything in a different file and include it? should I make it under the same namespace?
        I have said elsewhere on this forum that it is often the simple things that are hardest to find the answer to. If you have read this post you should be able to answer the 1st question (basically yes).

        The namespace question is a big moveable feast, personally I would recommend having at least 2 namespaces, 1 for the user interface and 1 for the implementation. And make sure you have a well defined the interface between them.

        In my project I have 4 namespaces
        1. User interface - handles all windows and dialogs
        2. Communication - handles the various differing communication methods with which the application and receive and send data
        3. Message Protocol - definition of the message protocol carried across the communication mediums
        4. Code Download - implementation of a state-event machine to control a specific and logically separate piece of the functionality that is self-contained with a well defined interface.

        Comment

        • MACKTEK
          New Member
          • Mar 2008
          • 40

          #5
          Fantastic help. Thanks.
          I will try to implement as much as I can.

          Comment

          • MACKTEK
            New Member
            • Mar 2008
            • 40

            #6
            Using the Project Menu, and choosing Add Class, I made a class called Dyn_XML_Class. This is contained in Dyn_XML_Class.h

            In Form1 all I had to do was:
            #pragma once // exists as top of Form1.h
            #include "Dyn_XML_Class. h" // add this line.

            I then instantiated the class inside an event handler, add some extra lines of code and it worked. (At least so far.)

            One thing I noticed is that the designer creates a completely new include for each class that I add.
            I guess, I will experiment with whether or not I can combine more than 1 class into the same include without messing up the Designer.

            Thanks again.

            Comment

            • Banfa
              Recognized Expert Expert
              • Feb 2006
              • 9067

              #7
              Originally posted by MACKTEK
              One thing I noticed is that the designer creates a completely new include for each class that I add.
              I guess, I will experiment with whether or not I can combine more than 1 class into the same include without messing up the Designer.
              You could do but this is normally considered desirable, it is normally considered better practice to have lots of small files than a few very large ones.

              Particularly in a large project with multiple programmers this leads to less file conflicts.

              Comment

              Working...