Am new to C++ and don't know if I'm doing something fundementally wrong. Have a form with a textbox and buttons. When I click on button, I am running a function in my .cpp file. However, in this function I need to update the text box in the form. Have created a public function set_address in the .h file form1 class definition that uses the following code.

public:
		void Form1::set_address(char *add)
		{
			char temp_str[80];
			sprintf(temp_str,add);
			textBox1->AppendText(temp_str);
		}

When I call it from my .cpp file with

Form1* pFm = new Form1;          
	pFm->set_address(temp_str);

It compiles OK and even runs the code, but the text box is not updated. If however I call the function from a clickbutton

private: System::Void button1_Click(System::Object *  sender, System::EventArgs *  e)
			 {
				char temp_str[80];
				sprintf(temp_str,"from button");
				set_address(temp_str);
			 }

It happily updates the text box.

Have been pulling my hair out for 2 days, so any help would be GREATLY appreciated

Using Microsoft Visual C++.net Version 2003

Thanks

Dave C

Dani AI

Generated

The problem is that you are updating a different Form1 object than the one that is displayed. Creating a new form with new Form1 gives you a fresh instance (not shown), so any changes end up off-screen. Calling set_address from the button works because that call runs on the displayed instance (this). ’s symptom is the classic “wrong instance” bug; ’s Invalidate() can force a redraw but won’t help if you’re changing the wrong object, and ’s Form_Load call works only because it uses the real instance.

Three simple fixes (pick one that fits your design):

  • Pass the displayed form’s pointer/reference to the code that needs to update the UI rather than creating a new Form1.
  • Store the shown form in a well-known place (for small apps a static field works) and call methods on that instance. For example:
/* in Form1.h */
public: static Form1^ MainForm;

/* in the Form1 constructor */
Form1::MainForm = this;

/* from other code */
if (Form1::MainForm != nullptr)
    Form1::MainForm->set_address(gcnew System::String(myCharPtr));
  • Use events/delegates or give the worker object a callback so the worker never needs to know how the form is created.

If the updater runs on a worker thread you must marshal the call to the UI thread. A thread-safe pattern:

delegate void SetAddrDel(System::String^);
public: void set_address(System::String^ text) {
    if (this->InvokeRequired) {
        SetAddrDel^ d = gcnew SetAddrDel(this, &Form1::set_address);
        this->Invoke(d, gcnew array<Object^>{ text });
        return;
    }
    textBox1->AppendText(text);
}

Also avoid sprintf(temp_str, add); — it treats add as a format string. Convert to a managed string (gcnew System::String(add)) or use safe C functions (snprintf/strncpy_s) before updating the control.

Recommended Answers

All 2 Replies

Sounds like you need to invalidate the text box so it will display itself. Try calling textBox1->Invalidate().

You need the button to do activate the code. The line set_address(temp_str); runs everything that's inside of set_address(char *add). Maybe instead of a button, try using the Form Load function.

public: void Form1::set_address(char *add)
{
char temp_str[80];
sprintf(temp_str,add);
textBox1->AppendText(temp_str);
}

private: System::Void Form1_Load(System::Object^  sender, System::EventArgs^  e) {
set_address(temp_str);
}

Hope this helps any.

commented: 5 YEARS LATE, and still the code is horribly broken - now go read the manual for sprintf -3
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.