Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. Managed C++/CLI
  4. Problem to communicate between forms [modified]

Problem to communicate between forms [modified]

Scheduled Pinned Locked Moved Managed C++/CLI
helpcsharpc++question
7 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • R Offline
    R Offline
    roshihans
    wrote on last edited by
    #1

    Hi, I have a problem to pass some data between forms. Let's say I have 2 form, FormMain and FormChild, FormChild will be called from FormMain. What I want to do is simple. Whenever I change the textBox1's text in FormChild, the textBox1's text in FormMain will also contain the same text. After googling for a while, I got 2 solution : by using a delegate or directly instantiate FormMain in FormChild. Both solution unfortunately is in C#, so I need to convert it first. Well, I thought at first that there will be no problem at all to convert it, but that is just plain wrong. Both of the solution I get is just give me some error. Here is the converted source code 1.using delegate in Form Main.h :

    #include "Form Child.h"

    namespace Delegates {

    public delegate void AddTextChangeDelegate(String^ item);
    
    public ref class FormMain : System::Windows::Forms::Form
    {
    public:
    	FormMain()
    	{
    		formChild = gcnew FormChild();
    	}
    
    // declare as global variable	
    private:
    	FormChild^ formChild;
    
    private: 
    	System::Void button1\_Click(System::Object^  sender, System::EventArgs^  e)
    	{			
    		formChild->AddTextChangeCallback = gcnew AddTextChangeDelegate(&this->AddTextChangeCallbackFn);
    		formChild->Show();
    	}
    
    private:
    	System::Void AddTextChangeCallbackFn(String^ str)
    	{
    		textBox1->Text = str;
    	}
    };
    

    }

    in Form Child.h

    namespace Delegates {

    public ref class FormChild : System::Windows::Forms::Form
    {
    // declaring delegate, and get "error C2143: syntax error : missing ';' before '^' "
    // the compiler seems doesn't recognize this
    public:
    	AddTextChangeDelegate^ AddTextChangeCallback;
    
    // user click add button and the delegate executed
    private:
    	System::Void btnAdd\_Click(System::Object^ sender, System::EventArgs^ e)
    	{
    		AddTextChangeCallback(textBox1->Text );
    	}
    
    };
    

    }

    2. directly instantiate FormMain the solution I get (in C#) is just simply declare FormMain as a global variable in FormChild, then exposed the textBox in FormMain as a public. But when I do the same thing in C++, the compiler give an error "error C2143: syntax error : missing ';' before '^' ". so probably I just need to include the Form Main.h in Form Child.h, which give me another error "fatal error C1014: too many include files : depth = 1024" (is it because both form include each other's header?, so that is like making some cyclic dependency thing? I'm not sure why). After googling once more, I found that it is st

    N 1 Reply Last reply
    0
    • R roshihans

      Hi, I have a problem to pass some data between forms. Let's say I have 2 form, FormMain and FormChild, FormChild will be called from FormMain. What I want to do is simple. Whenever I change the textBox1's text in FormChild, the textBox1's text in FormMain will also contain the same text. After googling for a while, I got 2 solution : by using a delegate or directly instantiate FormMain in FormChild. Both solution unfortunately is in C#, so I need to convert it first. Well, I thought at first that there will be no problem at all to convert it, but that is just plain wrong. Both of the solution I get is just give me some error. Here is the converted source code 1.using delegate in Form Main.h :

      #include "Form Child.h"

      namespace Delegates {

      public delegate void AddTextChangeDelegate(String^ item);
      
      public ref class FormMain : System::Windows::Forms::Form
      {
      public:
      	FormMain()
      	{
      		formChild = gcnew FormChild();
      	}
      
      // declare as global variable	
      private:
      	FormChild^ formChild;
      
      private: 
      	System::Void button1\_Click(System::Object^  sender, System::EventArgs^  e)
      	{			
      		formChild->AddTextChangeCallback = gcnew AddTextChangeDelegate(&this->AddTextChangeCallbackFn);
      		formChild->Show();
      	}
      
      private:
      	System::Void AddTextChangeCallbackFn(String^ str)
      	{
      		textBox1->Text = str;
      	}
      };
      

      }

      in Form Child.h

      namespace Delegates {

      public ref class FormChild : System::Windows::Forms::Form
      {
      // declaring delegate, and get "error C2143: syntax error : missing ';' before '^' "
      // the compiler seems doesn't recognize this
      public:
      	AddTextChangeDelegate^ AddTextChangeCallback;
      
      // user click add button and the delegate executed
      private:
      	System::Void btnAdd\_Click(System::Object^ sender, System::EventArgs^ e)
      	{
      		AddTextChangeCallback(textBox1->Text );
      	}
      
      };
      

      }

      2. directly instantiate FormMain the solution I get (in C#) is just simply declare FormMain as a global variable in FormChild, then exposed the textBox in FormMain as a public. But when I do the same thing in C++, the compiler give an error "error C2143: syntax error : missing ';' before '^' ". so probably I just need to include the Form Main.h in Form Child.h, which give me another error "fatal error C1014: too many include files : depth = 1024" (is it because both form include each other's header?, so that is like making some cyclic dependency thing? I'm not sure why). After googling once more, I found that it is st

      N Offline
      N Offline
      N a v a n e e t h
      wrote on last edited by
      #2

      roshihans wrote:

      But then another problem comes out. The instance declared in Form Child.cpp is not the same instance as the previous FormMain

      Because you are instantiating a new instance in the child form. You need to pass the main form's instance to child form (through constructor injection or some setter methods).

      roshihans wrote:

      So, what is the correct way to solve this problem?

      I will stick with delegates. It is the best way to go.

      roshihans wrote:

      AddTextChangeCallback(textBox1->Text );

      Don't call it blindly, your delegate instance may be NULL and you will end with null reference exception. Do a sanity check before you call it.

      System::Void btnAdd_Click(System::Object^ sender, System::EventArgs^ e)
      {
      if(AddTextChangeCallback != nullptr)
      AddTextChangeCallback(textBox1->Text ); // Safe to call it now
      }

      roshihans wrote:

      // declaring delegate, and get "error C2143: syntax error : missing ';' before '^' " // the compiler seems doesn't recognize this

      You might be doing it wrongly.

      public ref class FormChild : System::Windows::Forms::Form
      {
      public:
      delegate void AddTextChangeDelegate();
      AddTextChangeDelegate^ AddTextChangeCallback;

          ...........
      

      };

      :)

      Navaneeth How to use google | Ask smart questions

      R 1 Reply Last reply
      0
      • N N a v a n e e t h

        roshihans wrote:

        But then another problem comes out. The instance declared in Form Child.cpp is not the same instance as the previous FormMain

        Because you are instantiating a new instance in the child form. You need to pass the main form's instance to child form (through constructor injection or some setter methods).

        roshihans wrote:

        So, what is the correct way to solve this problem?

        I will stick with delegates. It is the best way to go.

        roshihans wrote:

        AddTextChangeCallback(textBox1->Text );

        Don't call it blindly, your delegate instance may be NULL and you will end with null reference exception. Do a sanity check before you call it.

        System::Void btnAdd_Click(System::Object^ sender, System::EventArgs^ e)
        {
        if(AddTextChangeCallback != nullptr)
        AddTextChangeCallback(textBox1->Text ); // Safe to call it now
        }

        roshihans wrote:

        // declaring delegate, and get "error C2143: syntax error : missing ';' before '^' " // the compiler seems doesn't recognize this

        You might be doing it wrongly.

        public ref class FormChild : System::Windows::Forms::Form
        {
        public:
        delegate void AddTextChangeDelegate();
        AddTextChangeDelegate^ AddTextChangeCallback;

            ...........
        

        };

        :)

        Navaneeth How to use google | Ask smart questions

        R Offline
        R Offline
        roshihans
        wrote on last edited by
        #3

        Thanks for your quick reply, Navaneeth!! And now, the delegate thing is works perfectly!! I has been searching a lot about this in the internet without a result and now it's solved! Thanks a lot Navaneeth!! :thumbsup: I dunno if my question is beyond the topic, but can I ask about another thing? this is about the answers that Navaneeth wrote

        N a v a n e e t h wrote:

        Because you are instantiating a new instance in the child form. You need to pass the main form's instance to child form (through constructor injection or some setter methods).

        constructor injection? I'm still a beginner in C++, so I'm barely hear about this. When you say constructor injection, is it something like dependency injection? I'm googling it in the internet, and this is that came up. Correct me if I was wrong, but from what I read in Internet, this dependency injection can be done using a container (??), created by third party developer (they mentioned something about pico container and others). It can not be done by .NET itself? I'm still confused :confused:

        N 1 Reply Last reply
        0
        • R roshihans

          Thanks for your quick reply, Navaneeth!! And now, the delegate thing is works perfectly!! I has been searching a lot about this in the internet without a result and now it's solved! Thanks a lot Navaneeth!! :thumbsup: I dunno if my question is beyond the topic, but can I ask about another thing? this is about the answers that Navaneeth wrote

          N a v a n e e t h wrote:

          Because you are instantiating a new instance in the child form. You need to pass the main form's instance to child form (through constructor injection or some setter methods).

          constructor injection? I'm still a beginner in C++, so I'm barely hear about this. When you say constructor injection, is it something like dependency injection? I'm googling it in the internet, and this is that came up. Correct me if I was wrong, but from what I read in Internet, this dependency injection can be done using a container (??), created by third party developer (they mentioned something about pico container and others). It can not be done by .NET itself? I'm still confused :confused:

          N Offline
          N Offline
          N a v a n e e t h
          wrote on last edited by
          #4

          roshihans wrote:

          constructor injection?

          By constructor injection, I meant to pass the first form's object to second form via constructor. Something like

          Form2(Form1^ form1) // First form's object is injected through constructor
          {
          // keep the form1 object for future use
          }

          As I said, go with delegates. It's the approaprite solution for your scenario. :)

          Navaneeth How to use google | Ask smart questions

          R 1 Reply Last reply
          0
          • N N a v a n e e t h

            roshihans wrote:

            constructor injection?

            By constructor injection, I meant to pass the first form's object to second form via constructor. Something like

            Form2(Form1^ form1) // First form's object is injected through constructor
            {
            // keep the form1 object for future use
            }

            As I said, go with delegates. It's the approaprite solution for your scenario. :)

            Navaneeth How to use google | Ask smart questions

            R Offline
            R Offline
            roshihans
            wrote on last edited by
            #5

            N a v a n e e t h wrote:

            By constructor injection, I meant to pass the first form's object to second form via constructor. Something like

            Form2(Form1^ form1) // First form's object is injected through constructor
            {
            // keep the form1 object for future use
            }

            But Form1 already include Form2.h (in my case Form1 act as a "parent" form, and instantiate Form2). So I think I can't declare Form2 (Form1^ form1) and keep the form1 object, like you have mentioned above, because I need to include Form1.h inside Form2.h, and that will give me this "fatal error C1014: too many include files : depth = 1024". Or maybe I don't need to include Form1.h inside Form2.h? Thanks

            N 1 Reply Last reply
            0
            • R roshihans

              N a v a n e e t h wrote:

              By constructor injection, I meant to pass the first form's object to second form via constructor. Something like

              Form2(Form1^ form1) // First form's object is injected through constructor
              {
              // keep the form1 object for future use
              }

              But Form1 already include Form2.h (in my case Form1 act as a "parent" form, and instantiate Form2). So I think I can't declare Form2 (Form1^ form1) and keep the form1 object, like you have mentioned above, because I need to include Form1.h inside Form2.h, and that will give me this "fatal error C1014: too many include files : depth = 1024". Or maybe I don't need to include Form1.h inside Form2.h? Thanks

              N Offline
              N Offline
              N a v a n e e t h
              wrote on last edited by
              #6

              roshihans wrote:

              But Form1 already include Form2.h (in my case Form1 act as a "parent" form, and instantiate Form2). So I think I can't declare Form2 (Form1^ form1) and keep the form1 object, like you have mentioned above

              Fair point! You will get circular dependency problems. To solve this, you need to have good understanding about C++ compiling and linking. You have to use forward declaration and declare parent form in child form's header file. Assume your parent form is named as PForm and child form as CForm. Here is how your PForm's header file looks like

              public ref class PForm : public System::Windows::Forms::Form{
              public:
              void UpdateText(String^ str) // used to update the text box text. This will be called from CForm.
              {
              textBox1->Text = str;
              }

              // your rest of code
              

              };

              Here is your CForm's header

              ref class PForm; // forward declaring PForm

              public ref class CForm : public System::Windows::Forms::Form{
              public:
              CForm(PForm^ pf) // injecting dependency through constructor
              {
              InitializeComponent();
              pForm = pf;
              }

              private:
              System::Void textBox1_TextChanged(System::Object^, System::EventArgs^);
              PForm^ pForm; // Parent form's object used to update the control
              };

              CForm.cpp contains

              #include "CForm.h"
              #include "PForm.h"

              System::Void CForm::textBox1_TextChanged(System::Object ^sender, System::EventArgs ^e){
              if(pForm != nullptr)
              pForm->UpdateText(textBox1->Text);
              }

              You show the CForm from PForm like

              CForm^ cForm = gcnew CForm(this);
              cForm->Show();

              This should work fine. But if you use delegates, you can avoid all these and implementation will be pretty straight forward. So please stick with delegates unless you have a good reason to go with the above method. Hope it is clear now. :)

              Navaneeth How to use google | Ask smart questions

              R 1 Reply Last reply
              0
              • N N a v a n e e t h

                roshihans wrote:

                But Form1 already include Form2.h (in my case Form1 act as a "parent" form, and instantiate Form2). So I think I can't declare Form2 (Form1^ form1) and keep the form1 object, like you have mentioned above

                Fair point! You will get circular dependency problems. To solve this, you need to have good understanding about C++ compiling and linking. You have to use forward declaration and declare parent form in child form's header file. Assume your parent form is named as PForm and child form as CForm. Here is how your PForm's header file looks like

                public ref class PForm : public System::Windows::Forms::Form{
                public:
                void UpdateText(String^ str) // used to update the text box text. This will be called from CForm.
                {
                textBox1->Text = str;
                }

                // your rest of code
                

                };

                Here is your CForm's header

                ref class PForm; // forward declaring PForm

                public ref class CForm : public System::Windows::Forms::Form{
                public:
                CForm(PForm^ pf) // injecting dependency through constructor
                {
                InitializeComponent();
                pForm = pf;
                }

                private:
                System::Void textBox1_TextChanged(System::Object^, System::EventArgs^);
                PForm^ pForm; // Parent form's object used to update the control
                };

                CForm.cpp contains

                #include "CForm.h"
                #include "PForm.h"

                System::Void CForm::textBox1_TextChanged(System::Object ^sender, System::EventArgs ^e){
                if(pForm != nullptr)
                pForm->UpdateText(textBox1->Text);
                }

                You show the CForm from PForm like

                CForm^ cForm = gcnew CForm(this);
                cForm->Show();

                This should work fine. But if you use delegates, you can avoid all these and implementation will be pretty straight forward. So please stick with delegates unless you have a good reason to go with the above method. Hope it is clear now. :)

                Navaneeth How to use google | Ask smart questions

                R Offline
                R Offline
                roshihans
                wrote on last edited by
                #7

                Thanks a lot Navaneeth, you have help me solve those two problems!! Pheww.. I kinda confused at first because of this circular dependency problems, but it's has clear now.

                1 Reply Last reply
                0
                Reply
                • Reply as topic
                Log in to reply
                • Oldest to Newest
                • Newest to Oldest
                • Most Votes


                • Login

                • Don't have an account? Register

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • World
                • Users
                • Groups