Click here to Skip to main content
15,881,380 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
I am working on a small Chat application to play with Visual studio 2012 and GUI programming. I have taken some classes in c++ but they only cover console programming, and while i am able to get the application working in a console i would like to implement a GUI front end.

That being said i have created the server section of the chat application. It has a simple GUI with a console and a command text box.

I am trying to write in the code to update the console window of the GUI however when i create a secondary class to modify the form i am unable to access the controls.

This is the form1.h file that i am using.and this is the helper class to work with Server commands.

C++
#pragma once

namespace GUI_Chat {
	#include "Commands.h"

	using namespace System;
	using namespace System::ComponentModel;
	using namespace System::Collections;
	using namespace System::Windows::Forms;
	using namespace System::Data;
	using namespace System::Drawing;
	using namespace ChatCommands;
	
	/// <summary>
	/// Summary for Form1
	/// </summary>
	public ref class Form1 : public System::Windows::Forms::Form
	{
	public:
		static Form1^ form1_Functions;
		Form1(void)
		{
			InitializeComponent();
			form1_Functions = this;
			//
			//TODO: Add the constructor code here
			//
		}

	void update_Console(System::String^ text)
		{
			rtbConsole->Text += text + Environment::NewLine;
		}
	protected:
		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		~Form1()
		{
			if (components)
			{
				delete components;
			}
		}
	private: System::Windows::Forms::RichTextBox^  rtbConsole;
			 
	protected: 

	private: System::Windows::Forms::TextBox^  txtCommands;
	protected: 

	private:
		/// <summary>
		/// Required designer variable.
		/// </summary>
		System::ComponentModel::Container ^components;

#pragma region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		void InitializeComponent(void)
		{
			this->rtbConsole = (gcnew System::Windows::Forms::RichTextBox());
			this->txtCommands = (gcnew System::Windows::Forms::TextBox());
			this->SuspendLayout();
			// 
			// rtbConsole
			// 
			this->rtbConsole->Enabled = false;
			this->rtbConsole->Location = System::Drawing::Point(0, 0);
			this->rtbConsole->Name = L"rtbConsole";
			this->rtbConsole->Size = System::Drawing::Size(554, 235);
			this->rtbConsole->TabIndex = 0;
			this->rtbConsole->Text = L"";
			// 
			// txtCommands
			// 
			this->txtCommands->Location = System::Drawing::Point(0, 241);
			this->txtCommands->Name = L"txtCommands";
			this->txtCommands->Size = System::Drawing::Size(554, 20);
			this->txtCommands->TabIndex = 1;
			this->txtCommands->KeyDown += gcnew System::Windows::Forms::KeyEventHandler(this, &Form1::txtCommands_KeyDown);
			// 
			// Form1
			// 
			this->AccessibleName = L"frmServer";
			this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
			this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
			this->BackColor = System::Drawing::Color::Black;
			this->ClientSize = System::Drawing::Size(554, 261);
			this->ControlBox = false;
			this->Controls->Add(this->txtCommands);
			this->Controls->Add(this->rtbConsole);
			this->MaximumSize = System::Drawing::Size(570, 300);
			this->MinimizeBox = false;
			this->MinimumSize = System::Drawing::Size(570, 300);
			this->Name = L"Form1";
			this->SizeGripStyle = System::Windows::Forms::SizeGripStyle::Hide;
			this->Text = L"Server";
			this->ResumeLayout(false);
			this->PerformLayout();

		}
#pragma endregion
		Chat_Commands CCommands;

		void txtCommands_KeyDown( Object^ /*sender*/, System::Windows::Forms::KeyEventArgs^ e )
		{
				
					// Determine whether the keystroke is an Enter
					if ( e->KeyCode == Keys::Return )
					{
						CCommands.command_Selection(txtCommands->Text);
						// DEBUG: Change text of rtbConsole to the value of txtCommands
						rtbConsole->Text += txtCommands->Text + Environment::NewLine;
						txtCommands->Text = "";
					}
				
		}
	};
}


And this is the Helper File

C++
// Randy C. Miller
//
// This file containes all the server command code for the TCP GUI Chat application.
//
#pragma managed

namespace ChatCommands {

	//#ifndef GUI_Chat_Commands
		//#define GUI_Chat_Commands
	//#endif

	// Include Files
	//#include <string>
	//#include <stdlib.h>

	//using namespace std;
	using namespace System::Windows::Forms;
	using namespace GUI_Chat;

	// Class Decleration
	public ref class Chat_Commands
	{
		// Private section
	private:
		
		// Public section
	public:
		//void GUI_Chat_Commands(void);
		Chat_Commands(void);
		void command_Selection(System::String^ command);
		char change_Case(char letter);
		void display_Usage(void);

	};

	// Constructor
	Chat_Commands::Chat_Commands()
	{

	}

	// Determine what command is being entered.
	void Chat_Commands::command_Selection(System::String^ command)
	{
		System::String ^lowerCommand;
		
		for each (char letter in command)
		{
			lowerCommand += (wchar_t) change_Case(letter);
		}

		if ("exit" == lowerCommand)
		{
			Application::Exit();
			//System::Windows::Forms::MessageBox::Show("Exit");
		}
		if ("?" == lowerCommand)
		{
			display_Usage();
		}
	}

	char Chat_Commands::change_Case(char letter)
	{
		// This changes to uppercase
		//if (letter > 96 && letter < 122)  // Check if the letter is lowercase
		//{
			//letter -= 32;	// Change the letter to uppercase.
		//}
		if (letter > 'A' && letter < 'Z') // Check if the letter is uppercase
		{
			letter += 32;
		}
		return letter;
	}
	/*
	ref class ConnectionContainer
	{
		static GUI_Chat::Form1^ glblForm1 = nullptr;
		public :  
		static GUI_Chat::Form1^ get_Form1_Object()
		{
			if (glblForm1 == nullptr) 
	        {
				glblForm1 = gcnew GUI_Chat::Form1;
			}
			return glblForm1;
		}
}	;
	*/
	void display_Usage(void)
	{
		//ConnectionContainer^ Container = gcnew ConnectionContainer();
		//GUI_Chat::Form1^ Connection = Container->get_Form1_Object();
		
		//GUI_Chat::Form1::rtbConsole->Text += "Usage" + Environment::NewLine;
		//Connection->update_Console("Usage");
		Form1::form1_Functions->update_Console("Usage");
	}
}


SQL
There are allot of commented out lines as i have been working with this for a while and trying different things.
I tried many different ways of resolving this and searched for hours on Google.

Any help that anyone can provide would be appreciated, also any links to GUI programming tutorials would be helpfull.

Thank you
Posted

1 solution

One simple technique could help you to work around this rather simple problem: instead of having a separate helper class, you can use the same class, and, to avoid code clutter, use the partial class syntax, and add the part is a separate file:
http://msdn.microsoft.com/en-us/library/vstudio/hh972420.aspx[^].

However, if you need this helper class to be reused for different form class, this approach won't help. The you should provide some access to your control to the helper class. You could declare control members as internal, it would give you the access but violate proper encapsulation. The most robust approach is to implement some interface (again, do it in a separate class part, to avoid cluttering your code), and pass the reference to the form as interface reference, to avoid breaking encapsulation and passing the interface to the whole form. This interface should provide proper access to the controls and serve as the method making the helper class and the form class more loosely coupled.

Please see also my past answer: How to get data from one form to another.[^].

See also: http://en.wikipedia.org/wiki/Loose_coupling[^].

—SA
 
Share this answer
 
Comments
Member 7909935 26-Aug-13 16:35pm    
I have tried the links you provided, and am unable to come up with a solution to my issue.
i tried using: ref class ManagedGlobals { public: static Form1^ mainForm = gcnew Form1; };
and then calling ManagedGlobals::mainForm->rtbConsole->Text = "usage";
but that does not work. any other solutions to this issue?
Sergey Alexandrovich Kryukov 26-Aug-13 21:22pm    
"Does not work" is not informative. What did you right, exactly, and what's not working. And why "other solution"? Complete this solution first, otherwise you have the same with "other".

And this is not a matter of trying. You should be sure about every line you are righting. "Do or do not. There is no try."

Each class and each class members has one of 4 access modifiers. A member is accessible in the same assembly when its access is "internal". If you implement some interface, all interface members are always accessible.

Now, if the members in question are instance members (usually they are, anyway, you should not use static fields or properties), you need an instance

You should kill the idea of "globals" from the very beginning; there is no such concept as "global" in .NET. If you don't understand any of the above, you are not yet ready to do UI (the UI built by a designer does not count, of course). If so, you need to grab a programming book and learn about types and instances, static vs. instance, interfaces and implementation, access modifiers, visibility and scope.

—SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900