Hello!

I have created a ChatClient in Visual C++ 2010 Express, cmd console only. Now I want to make it in Windows Form Application. I have come a long way but the thread function to start a new thread is a bit of a problem..

I get these errors:

error C3867: 'cc_real::Form1::WaitForMessage': function call missing argument list; use '&cc_real::Form1::WaitForMessage' to create a pointer to member

error C3867: 'cc_real::Form1::SdbThreadProc': function call missing argument list; use '&cc_real::Form1::SdbThreadProc' to create a pointer to member

Missing Argument list.

cc_real is the project name..

Here is the whole code for Form1.h

#pragma once
#pragma comment(lib, "Ws2_32.lib")
#include <sdkddkver.h>
#include "threaddata.h"
#include <WinSock2.h>

#include <iostream>

#include <string>

#include <Windows.h>


const char MaxLength = 100;    

SOCKET sConnect = -1;

namespace cc_real {

	using namespace System;
	using namespace System::ComponentModel;
	using namespace System::Collections;
	using namespace System::Windows::Forms;
	using namespace System::Data;
	using namespace System::Drawing;
	

	/// <summary>
	/// Summary for Form1
	/// </summary>
	public ref class Form1 : public System::Windows::Forms::Form
	{
	public:
			
		
		Form1(void)
		{
		
			InitializeComponent();
			//
			//TODO: Add the constructor code here
			//
		}

	protected:
		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		~Form1()
		{
			if (components)
			{
				delete components;
			}
		}
	private: System::Windows::Forms::Button^  btnSend;
	protected: 
	private: System::Windows::Forms::Button^  button2;
	private: System::Windows::Forms::TextBox^  tbLog;
	private: System::Windows::Forms::TextBox^  tbInput;

	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->btnSend = (gcnew System::Windows::Forms::Button());
			this->button2 = (gcnew System::Windows::Forms::Button());
			this->tbLog = (gcnew System::Windows::Forms::TextBox());
			this->tbInput = (gcnew System::Windows::Forms::TextBox());
			this->SuspendLayout();
			// 
			// btnSend
			// 
			this->btnSend->Location = System::Drawing::Point(436, 268);
			this->btnSend->Name = L"btnSend";
			this->btnSend->Size = System::Drawing::Size(93, 51);
			this->btnSend->TabIndex = 0;
			this->btnSend->Text = L"Send";
			this->btnSend->UseVisualStyleBackColor = true;
			this->btnSend->Click += gcnew System::EventHandler(this, &Form1::btnSend_Click);
			// 
			// button2
			// 
			this->button2->Location = System::Drawing::Point(454, 12);
			this->button2->Name = L"button2";
			this->button2->Size = System::Drawing::Size(75, 23);
			this->button2->TabIndex = 1;
			this->button2->Text = L"button2";
			this->button2->UseVisualStyleBackColor = true;
			// 
			// tbLog
			// 
			this->tbLog->Location = System::Drawing::Point(12, 12);
			this->tbLog->Multiline = true;
			this->tbLog->Name = L"tbLog";
			this->tbLog->Size = System::Drawing::Size(418, 250);
			this->tbLog->TabIndex = 2;
			// 
			// tbInput
			// 
			this->tbInput->Location = System::Drawing::Point(12, 268);
			this->tbInput->Multiline = true;
			this->tbInput->Name = L"tbInput";
			this->tbInput->Size = System::Drawing::Size(418, 51);
			this->tbInput->TabIndex = 3;
			// 
			// Form1
			// 
			this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
			this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
			this->ClientSize = System::Drawing::Size(541, 331);
			this->Controls->Add(this->tbInput);
			this->Controls->Add(this->tbLog);
			this->Controls->Add(this->button2);
			this->Controls->Add(this->btnSend);
			this->Name = L"Form1";
			this->Text = L"ChatClient";
			this->Load += gcnew System::EventHandler(this, &Form1::Form1_Load);
			this->ResumeLayout(false);
			this->PerformLayout();

		}
#pragma endregion
	private: System::Void btnSend_Click(System::Object^  sender, System::EventArgs^  e) {

				bool nicknamecheck = false;
				String^ nickname;
				
				 if(nicknamecheck == false)
				 {
					 nickname = tbInput->Text;
					 char* nicktemp = (char*)(System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(nickname)).ToPointer();
					 bind(nicktemp);

				 nicknamecheck = true;
				 }else
				 {
					 char input[MaxLength];
				
						if(input[0] == '/')
						{
							if(strcmp(input, "/quit") == 0)
							{
								Application::Exit();

							}

						}else
						{
							if(input[0] != '\0')
							{
		
								SendData(input, (int)strlen(input)+1);

							}

						}
				 }
				 


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

					WSAMain();
				    if(OpenSocket() == true)
					{

					//tbLog->Text = "What is your nickname?";

					}

				
			 }

	void WSAMain()
	{
		WSAData wsaData;
		if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
		{

			//cout << "WSAStartup fail. Socker Error" << endl;

		}
	}

	bool OpenSocket()
	{

	bool open = false;
	sConnect = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if(sConnect >= 0)
	{
		 open = true;
	}

	return (open);

	}

	bool bind(const char*nicktemp)
	{
	
	
	bool bound = false;

	sockaddr_in addr;
	
	addr.sin_family = AF_INET;
	addr.sin_port = htons(1234);
	addr.sin_addr.s_addr = inet_addr("192.168.1.39");

	memset(addr.sin_zero, 0, sizeof(addr.sin_zero));

	if(connect(sConnect, (const sockaddr*)&addr, sizeof(addr)) == 0)
	{
		bound = true;
	
		SdbCreateThread(WaitForMessage, 0);
	
		SendData(nicktemp, (int)strlen(nicktemp)+1);
		
	}	

	return(bound);
	}

	void WaitForMessage()
	{
	bool dropserver = false;
	while(dropserver == false)
	{
		char inputmessage[MaxLength];		
		
		int bytes = recv(sConnect, inputmessage, sizeof(inputmessage), 0);
		if(bytes <= 0)
		{
			dropserver = true;

			/*tbLog->AppendText = ("Wait for message");*/

		}else
		{
			String^ tempmessage = System::Runtime::InteropServices::Marshal::PtrToStringAnsi (IntPtr(inputmessage));
			tbLog->AppendText(tempmessage);
		}
	}

	}

	void SendData(const char* cc_Message, int Length)
	{
	
	send(sConnect, cc_Message, Length, 0);

	}

	DWORD WINAPI SdbThreadProc(LPVOID lpParameter)
	{
		ThreadData* l_pThreadData = (ThreadData*)lpParameter;
		l_pThreadData->ThreadEntry(l_pThreadData->Parameter);
		delete l_pThreadData;
		l_pThreadData = 0;
		return(0);
	}

	void SdbCreateThread(void (*ThreadEntry)(int), int Parameter)
	{
		
		ThreadData* l_pThreadData = new ThreadData;
		l_pThreadData->ThreadEntry = ThreadEntry;
		l_pThreadData->Parameter = Parameter;

		DWORD l_dwThreadId;
		HANDLE l_tThread;
		l_tThread = ::CreateThread(0, 0, SdbThreadProc, l_pThreadData, 0, &l_dwThreadId);
		if(l_tThread)
		{
			::Sleep(10);
			//return(true);
		}
		//return(false);
	
	}




	};
}

error C3867: 'cc_real::Form1::WaitForMessage': function call missing argument list; use '&cc_real::Form1::WaitForMessage' to create a pointer to member

So did you try what it says? At line 232 above, replace

SdbCreateThread(WaitForMessage, 0);

with

SdbCreateThread(&WaitForMessage, 0);

As far as I'm aware, each is equivalently "a pointer to the function", but apparently the compiler wants you to be explicit about it.

Looks like the same thing when you pass SdbThreadProc as an argument at line 289, put an explicit '&' in front of it.

That won't work.. gets error:

error C2276: '&' : illegal operation on bound member function expression
error C2276: '&' : illegal operation on bound member function expression

instead..

Ouch. My next theory (and here's hoping somebody more specifically knowledgeable will jump in) is that you need to pass pointers to straight-up functions (i.e., C-style, not class instance methods). Which makes sense if you think about it: once you've passed a pointer to just a method, how would the code inside that know which instance of the class it came from? Normally, you'd pass a pointer to the instance, which then has access to all of its members and methods.

I think you can get where you need to, by moving SbcCreateThread() and SbcThreadProc() out of your class, and passing an instance of your class into the former.

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.