Threads und Socket Programmierung

Auf keinen Fall umcasten, das funktioniert nicht. Man müsste da Umwandelfunktionen benutzen.

Zum Umstellen gibt es einen Punkt in den Projekt-Eigenschaften. Müsste statt Unicode MBCS (oder so ähnlich, Multi Byte) heissen.
 
So hab mich mal n bischen mit createWindow beschäftigt, dazu mal wieder n kleines Problem.
Mein Teil (Netzwerk) soll praktisch im Hintergrund laufen, ich möchte es daher als Konsolenprogramm erstellen.
Das komplette Programm wird eine CLR -> Windows-Forms Anwendung.
Wo bekomme ich denn da nun ein hInstance her, wenn ich nicht die übliche WinMain ausführe/aufrufe? Kann ich da einfach NULL nehmen, wenn ich doch eh nur ein unsichtbares Fenster wünsche?
 
Nein, aber mit GetModuleHandle( NULL ) müsstest du die HINSTANCE deines aktuellen Programmes erhalten.

Bei den Windows-Forms müsste das auch in irgendeiner Form greifbar sein, die setzen zur Zeit ja nur auf der normalen Win32-API auf.
 
So hab mich nun mal an CreateWindow heran getraut.
Zunächst hab ich miur erstmal ne kleine Fenster Klasse geschrieben:
Code:
#include "Fenster.h"
#include <windows.h>

Fenster::Fenster(WNDPROC prozedur)
{
	//Art des Fensters
	//Bei Horizontaler/Vertikaler Änderung neuzeichnen
	wc.style         =  CS_HREDRAW | CS_VREDRAW;
  //Angabe welche Methode für die Nachrichten Verarbeitung zuständig ist
	wc.lpfnWndProc   =  prozedur;
	
	//Zusätzliche Speicherreservierung, wird nicht benötigt
	wc.cbClsExtra    =  0;
  wc.cbWndExtra    =  0;

	//Angabe wer das Fenster benutzen darf
	wc.hInstance     =  GetModuleHandle(NULL);
	//Standard Cursor verwenden (alternativ 0 für keinen)
  wc.hCursor       =  LoadCursor(NULL,IDC_ARROW);
	//Lade Standard Icon
  wc.hIcon         =  LoadIcon(NULL,IDI_APPLICATION);
	//Hintergrundfarbe weiß
  wc.hbrBackground =  (HBRUSH)GetStockObject(WHITE_BRUSH);

	//Name der Fensterklasse
	wc.lpszClassName =  (LPCWSTR)"Nur ein Fenster";
	//Kein Menü
	wc.lpszMenuName  =  NULL;

	//Anmeldung an den Fenstermanager von Windows
	RegisterClass(&wc);

	handle = CreateWindow(
														(LPCWSTR)"Nur ein Fenster",	//Klassenname des Fensters
												    (LPCWSTR)"Nur ein Fenster",	//Test in der Titelleiste
														WS_OVERLAPPEDWINDOW,				//Stil des Fensters
														CW_USEDEFAULT,							// X-Position auf dem Monitor 
														CW_USEDEFAULT,							// Y-Position auf dem Monitor 
														CW_USEDEFAULT,							// Fensterbreite              
														CW_USEDEFAULT,							// Fensterhoehe               
														NULL,										
														NULL,
														GetModuleHandle(NULL),			//Angabe zum Programm
														NULL);

	//Nachrichtenschleife
	/*while (GetMessage(&msg, NULL, 0, 0))
  {
		//Weiterleiten der Nachrichten an die jeweilige Methode
		DispatchMessage(&msg);
	}*/
}

HWND& Fenster::getHandle()
{
	return handle;
}
Nun habe ich mein ClientNetzwerk abgeändert:
Code:
#include "ClientNetzwerk.h"
#include <windows.h>
#include <vector>
#include "Operator.h"
#include "netzwerk.h"
#include <algorithm>
#include "Fenster.h"

using std::string;

ClientNetzwerk::ClientNetzwerk(Operator* poOperator)
: vsChatter(), fenster(&ClientNetzwerk::WndProcCN), clientSocket()
{
	this->poOperator = poOperator;
	//this->clientSocket = new SOCKET();
}

void ClientNetzwerk::start(char* pcIP, u_short iPort)
{	
	//Winsockets starten
	sMeldung = startWinSock();
	this->poOperator->meldungEingegangen(&sMeldung);
	//Socket TCP/IP Tauglichen machen (Konstruktor aufruf)
	sMeldung = socketErstellen(clientSocket);
	this->poOperator->meldungEingegangen(&sMeldung);
	//Socket auf weiteres Fenster umleiten
	sMeldung = aufFensterUmleiten(
																		clientSocket,
																		fenster.getHandle(),
																		FD_ACCEPT | FD_WRITE | FD_READ | FD_CLOSE);
	this->poOperator->meldungEingegangen(&sMeldung);
	//Zum Server verbinden
	sMeldung = connectTo(clientSocket, "127.0.0.1", 1000);
	this->poOperator->meldungEingegangen(&sMeldung);
}

void ClientNetzwerk::ende()
{
	beendeNetzwerk(clientSocket);
	poOperator->meldungEingegangen(&string("Client ist nun nicht mehr mit dem Server verbunden."));
}

void ClientNetzwerk::neueNickListe()
{
	//Bubble Sort wär hier evtl. sinnvoller (Heapsort ist zu aufwenidig um ein Element zu sortieren)
	std::sort(vsChatter.begin(), vsChatter.end());

	string sNicks = "";

	for(int i = 0; i < vsChatter.size(); i++)
	{
		sNicks += vsChatter.at(i);
		sNicks += "\n";
	}

	this->poOperator->setUserList(&sNicks);
}

LRESULT CALLBACK ClientNetzwerk::WndProcCN(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	/*char pcNachrichten[coniMAXNACHRICHTENGROESSE];
	switch(LOWORD(lParam))
	{
		case FD_ACCEPT:;
		case FD_WRITE:;
		case FD_READ:
		{
			;//bool bNeueNachricht = empfangen(SOCKET&, char*, int);
		}
		case FD_CLOSE: ;
	}
return 0;*/

	switch (message)
  {
		case WM_DESTROY:
    {
			PostQuitMessage(0);
      return 0;
    }
  }
}
Die WinProcCN möchte ich dann später zum abhöhren etc umbauen. Nun hab ich folgendes Problem:
Wenn ich WinProcCN als statische MEthode definiere, also nicht als Klassenmember, startet das Programm fehlerfrei und WSAAsyncSelect startet einwandfrei. Nur ich kann leider nicht auf den Socket (Member von ClientNetzwerk) drauf zu greifen (und das muss ich zum nachrichten empfang und versand).
Wenn ich es so, wie es momentan der Fall ist als Memberfunktion deklariere, dann meldet mir der kompilier eine Fehlermeldung:
Code:
Fehler	1	error C2664: 'Fenster::Fenster(WNDPROC)': Konvertierung des Parameters 1 von 'LRESULT (__stdcall ClientNetzwerk::* )(HWND,UINT,WPARAM,LPARAM)' in 'WNDPROC' nicht möglich	c:\dokumente und einstellungen\administrator\desktop\neues projekt\neues projekt\clientnetzwerk.cpp	22
 
Das alte Problem:

Eine WindowProc kann kein Member einer Klasse sein, da dort ein impliziter this-Pointer mitübergeben wird.

Abhilfe: Die Proc-Member-Funktion statisch deklarieren.
 
OK dann mache ich die Methode wieder statisch, wie ich sie vorherher hatte.
Nur wie komme ich dann an den Socket (und am besten überhaupt an alle Elemente aus meiner definierten Klasse)?
 
Da hilft dann ein globaler Pointer auf die aktuelle Instanz (kann auch ein statisches Member sein, im Constructor dann auf die Klasse verweisen), einfach oder ein den Pointer in einem der Window-Longs verpacken (etwas komplizierter).
 
Müsste auch gehen. Eigentlich ein Pointer auf Fenster, aber das Fenster muss ja sowieso in irgendeiner Weise mit dem Client kommunizieren, um die Events weiterzugeben. Da jetzt noch rum-zu-abstrahieren wäre vermutlich Overkill für dein Projekt.
 
Da dieses Projekt ja auch ein CLR-PRojekt ist, bin ich nun auf den Backgroundworker ausgewichen. Der funktioniert wie erwünscht ich kann dieses starten, ne Endlosschleife ausführen lassen und zum beliebigen Zeitpunkt wieder abbrechen ;-)

Trozdem danke für die Hilfe mit dem Fenster, diese liefen ja auch schon, hatte schlußendlich nur Probleme auf die privaten Member zuzugreifen ;-)
 

Neue Beiträge

Zurück