Ask a questionAsk a question
 

AnswerCommunicating between forms

  • Sunday, November 08, 2009 12:54 AMIshmael_1851 Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Has Code
    I am trying to communicate between two windows forms.  I would like Form2 to set a variable in Form1.  I've tried to do what was suggested here , but I can't get it to work.  For some reason, I can't seem to send a Form1 pointer to Form2.  I can't #include Form1.h in Form2, because I'll end up with a cyclical dependency.  Any ideas?

    Here's an excerpt of my code:


    Form1.h
    #include "Form2.h"
    
    namespace test_multiple_forms {
    
    public ref class Form1 : public System::Windows::Forms::Form
    	{
    	public:
    		Form1(void)
    		{
    			InitializeComponent();
    		}
            public: 
    		static String ^myGlobalVar = "abc";
            etc....
    }
    

    Form2.h
    class Form1;  // Since I can't #include Form1.h
    
    namespace test_multiple_forms {
    
    	public ref class Form2 : public System::Windows::Forms::Form
    	{
    	public:
    		Form2(Form1 ^ptr)
    		{
    			InitializeComponent();
    		}
            etc...
    }
    
    But then I get an error:

         Error    1    error C2061: syntax error : identifier 'Form1'

    There must be an extremely straightforward way of passing data back and forth between Forms, but I haven't been able to figure it out.  Thanks for the help!




Answers

  • Sunday, November 08, 2009 3:39 AMJijo RajMVPUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    <Addon to Brian's answer>

    Hello Ishmael,

    Refer this tutorial - Passing Data between Windows Forms .
    Its in C#, but will be helpful since you're dealing with windows forms.

    Best Regards,
    Jijo.
    http://weseetips.com[^] Visual C++ tips and tricks. Updated daily.
  • Monday, November 09, 2009 9:08 PMSheng Jiang 蒋晟MVPUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    You can move function body in to cpp files and only leave signature in the class body. This would break the header file circular reference.

    I suggest you also make the your Form2 class independent from Form1.  Declare a class that would contain all the data being passed around. Pass the data in the constructor or in a property instead. This makes your Form2 usable in any class that can supply the data.



    The following is signature, not part of post
    Please mark the post answered your question as the answer, and mark other helpful posts as helpful.
    Visual C++ MVP

All Replies

  • Sunday, November 08, 2009 1:39 AMBrian MuthMVPUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Use
    #pragma once

    in your include files. You should do this with all your include files regardless if you think it is required or not.
    Then you can include form1.h

  • Sunday, November 08, 2009 3:39 AMJijo RajMVPUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    <Addon to Brian's answer>

    Hello Ishmael,

    Refer this tutorial - Passing Data between Windows Forms .
    Its in C#, but will be helpful since you're dealing with windows forms.

    Best Regards,
    Jijo.
    http://weseetips.com[^] Visual C++ tips and tricks. Updated daily.
  • Monday, November 09, 2009 8:02 PMIshmael_1851 Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Has Code
    Thanks Jijo, I've started looking at the link you recommended, but I have to say, it seems overly complicated.  All I want to do is have two different forms write to the same variable.  As I understand them, delegates are like function pointers in C.  I don't need to reference the functions in Form1, only a variable.  There must be a simple way to do this.  Maybe defining a separate namespace?  I've tried to make a separate header file with its own namespace, like this:

    #ifndef GLOBAL_VARS_H
    #define GLOBAL_VARS_H
    
    namespace MyGlobalVars {
    	int myGlobalInt = 0;
    }
    
    #endif
    
    Then I #include this header file in each of the Form1.h and Form2.h files.  When I do this, I get another error:

    Error    2    error LNK2005: "int MyGlobalVars::myGlobalInt" (?myGlobalInt@MyGlobalVars@@$$Q3HA) already defined in test_multiple_forms.obj    Form2.obj    test_multiple_forms

    I don't know how this is possible, since I've got the standard #ifndef stuff in there (I also tried a "#pragma once" in there to be sure, but no luck).

    (By the way, why on Earth do they put all the code in the Form1.h file by default?  It would be much clearer if they put the actual code in a .cpp file and the header stuff in a .h file instead of lumping everything together).


    P.S. @Brian: Thanks, I had #pragma once in my header files, but I just removed it to save space when copying the code into this forum.
  • Monday, November 09, 2009 9:08 PMSheng Jiang 蒋晟MVPUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    You can move function body in to cpp files and only leave signature in the class body. This would break the header file circular reference.

    I suggest you also make the your Form2 class independent from Form1.  Declare a class that would contain all the data being passed around. Pass the data in the constructor or in a property instead. This makes your Form2 usable in any class that can supply the data.



    The following is signature, not part of post
    Please mark the post answered your question as the answer, and mark other helpful posts as helpful.
    Visual C++ MVP
  • Monday, November 09, 2009 10:20 PMIshmael_1851 Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Has Code
    Thanks for your reply.  I tried to make a special class with my data as follows:

    namespace test_multiple_forms {
    
    	class MyGlobalVars {
    	public:
    		static int myGlobalInt;
    	};
    
            etc....
    
    
    Then in my code I say:

    private: System::Void get_value_button_Click(System::Object^ sender, System::EventArgs^  e) {
    	int tmp = MyGlobalVars::myGlobalInt;
    }
    

    This produces the following error:

    Error    1    error LNK2020: unresolved token (0A00000A) "public: static int test_multiple_forms::MyGlobalVars::myGlobalInt" (?myGlobalInt@MyGlobalVars@test_multiple_forms@@$$Q2HA)    test_multiple_forms.obj    test_multiple_forms

    Any thoughts?

    I will try to separate my code into Form1.h and Form1.cpp now to avoid the circular reference.

  • Monday, November 09, 2009 11:14 PMIshmael_1851 Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Has Code
    Well, I've managed to force it to work by defining a truly global variable as follows:


    global_vars.h
    #ifndef GLOBAL_VARS_H
    #define GLOBAL_VARS_H
    
    extern int myGlobalInt;
    
    #endif
    


    Then in Form1.h
    #include "global_vars.h"
    
    int myGlobalInt = 5;
    


    And in Form2.h
    #include "global_vars.h"
    

    Of course, this is an ugly, ugly solution.  There must be an elegant way.  I like Sheng Jiang's idea of making a special class with just the data being passed around, but I can't seem to get it to work.

  • Monday, November 09, 2009 11:33 PMSheng Jiang 蒋晟MVPUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Has Code
    public ref class MyGlobalVars {
    	public:
    		property int var1;
    		property String^ var2;
    
    
    }; etc....


    The following is signature, not part of post
    Please mark the post answered your question as the answer, and mark other helpful posts as helpful.
    Visual C++ MVP
  • Tuesday, November 10, 2009 1:36 AMIshmael_1851 Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Has Code
    Thanks!  I did get this to work, but I'm not sure if it's any better than the 'extern' method above.  Why is this method better?  Here's what I did, in case anyone is interested.

    In global_vars.h
    #ifndef GLOBAL_VARS_H
    #define GLOBAL_VARS_H
    
    public ref class MyGlobalVars {
    public:
    	property int myGlobalInt;
    public:
    	property int Property_Block {
    		int get() {
    			return myGlobalInt;
    		}
    		void set(int val) {
    			myGlobalInt = val;
    		}
    	}
    };
    
    #endif
    

    In Form1.h
    #include "global_vars.h"
    
    public ref class Form1 : public System::Windows::Forms::Form
    	{
    	public:
    		Form1(void)
    		{
    			InitializeComponent();
    		}
    		static MyGlobalVars ^global_vars = gcnew MyGlobalVars();
    


     In Form2.h
    #include "global_vars.h"
    
    public ref class Form2 : public System::Windows::Forms::Form
    	{
    	private:
    		MyGlobalVars ^global_vars;
    	public:
    		Form2(MyGlobalVars ^tmp)
    		{
    			InitializeComponent();
    			global_vars = tmp;
    		}