Prøv med denne.
Der kommer først en box hvor den spørger efter ipaddresse, du kan ugså skrive en URL, så som
www.pop.dkDu bestemmer port med:
const short SocketPort = 5011;
Der skal nok justeres lidt her og der.
#include <windows.h>
#include <commctrl.h>
#include <string.h>
#include <stdio.h>
const short SocketPort = 5011;
#define RX_THREAD_MESSAGE WM_APP
#define REG_KEY "Software\\HomeMadeApps\\P2P-Chat"
class RegistryClass
{
public:
RegistryClass(const char *aKey)
{
if(RegOpenKey(HKEY_CURRENT_USER, aKey, &KeyHandle) != ERROR_SUCCESS)
{
if(RegCreateKeyEx(HKEY_CURRENT_USER, aKey, 0, 0, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, 0, &KeyHandle, 0) != ERROR_SUCCESS)
KeyHandle = 0;
}
}
~RegistryClass()
{
if(KeyHandle)
RegCloseKey(KeyHandle);
}
int GetInt(const char *aKey, int aDefaultValue = 0)
{
if(!KeyHandle)
return aDefaultValue;
DWORD Type = REG_DWORD, Size = sizeof(DWORD);
int Value;
if(RegQueryValueEx(KeyHandle, aKey, 0, &Type, (BYTE *)&Value, &Size) != ERROR_SUCCESS)
return aDefaultValue;
return Value;
}
void WriteInt(const char *aKey, int aValue)
{
if(!KeyHandle)
return;
RegSetValueEx(KeyHandle, aKey, 0, REG_DWORD, (BYTE *)&aValue, sizeof(aValue));
}
char *GetString(const char *aKey, char *aBuffer, int aMaxSize)
{
if(!KeyHandle)
{
*aBuffer = 0;
return aBuffer;
}
DWORD Type = REG_SZ, Size = aMaxSize;
if(RegQueryValueEx(KeyHandle, aKey, 0, &Type, (BYTE *)aBuffer, &Size) != ERROR_SUCCESS)
*aBuffer = 0;
return aBuffer;
}
void WriteString(const char *aKey, const char *aBuffer)
{
if(!KeyHandle)
return;
RegSetValueEx(KeyHandle, aKey, 0, REG_SZ, (BYTE *)aBuffer, strlen(aBuffer));
}
private:
HKEY KeyHandle;
};
static LRESULT CALLBACK DialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
SOCKET Socket;
char IPAddressStr[128];
void CleanUp(HWND aHwnd);
struct in_addr RxAddr;
bool HasRxAddr;
bool RunRxThread = true;
bool RxThreadDone = false;
enum CtrlIdType
{
ListCtrlId = 1025,
EditCtrlId,
SetupEditId,
OkButtonCtrlId,
SendButtonCtrlId = IDOK
};
/* Add a line of text to the list box
** Make sure the line is visible Scroll as requred
** Adjust the horz scrollbar */
void AddListText(HWND aMainWnd, const char *aMsg)
{
static int MaxWidth;
int idx;
HWND List;
HDC dc;
HFONT Font, OldFont;
SIZE TextSize, SizeExtra;
List = GetDlgItem(aMainWnd, ListCtrlId);
idx = SendMessage(List, LB_ADDSTRING, 0, (LPARAM )aMsg);
SendMessage(List, LB_SETCARETINDEX, idx, 0);
dc = GetDC(List);
Font = (HFONT )SendMessage(aMainWnd, WM_GETFONT, 0, 0);
OldFont = (HFONT )SelectObject(dc, Font);
GetTextExtentPoint32(dc, aMsg, strlen(aMsg), &TextSize);
GetTextExtentPoint32(dc, "WWW", 3, &SizeExtra);
TextSize.cx += SizeExtra.cx;
if(TextSize.cx > MaxWidth)
{
MaxWidth = TextSize.cx;
SendMessage(List, LB_SETHORIZONTALEXTENT, MaxWidth, 0);
}
SelectObject(dc, OldFont);
ReleaseDC(List, dc);
}
/* Grab the text from the edit-box and send it on the socket.
** The text is appended to the list-box
*/
void HandleSend(HWND aHwnd)
{
char text[128], buffer[130];
struct sockaddr_in sockaddr;
GetDlgItemText(aHwnd, EditCtrlId, text, sizeof(text));
sprintf(buffer, ">%s", text);
AddListText(aHwnd, buffer);
SetDlgItemText(aHwnd, EditCtrlId, "");
memset((char *)&sockaddr, 0, sizeof(sockaddr));
sockaddr.sin_family = AF_INET;
if(IPAddressStr[0])
{
sockaddr.sin_addr.s_addr = inet_addr(IPAddressStr);
if(sockaddr.sin_addr.s_addr == INADDR_NONE)
{
struct hostent *hostinfo;
hostinfo = gethostbyname(IPAddressStr);
if(!hostinfo)
{
MessageBox(aHwnd, "Failed to convert IPAddress!", "P2P-Chat", MB_OK);
return;
}
else
{
memcpy((void *)&sockaddr.sin_addr, hostinfo->h_addr_list[0], hostinfo->h_length);
}
}
}
else if(HasRxAddr)
sockaddr.sin_addr.s_addr = RxAddr.s_addr;
else
{
MessageBox(aHwnd, "No peer address", "P2P-Chat", MB_OK);
return;
}
sockaddr.sin_port = htons(SocketPort);
if(sendto(Socket, text, strlen(text) + 1, 0, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
{
char Msg[1024];
sprintf(Msg, "Error: %d", WSAGetLastError());
MessageBox(aHwnd, Msg, "P2P-Chat", MB_OK);
}
}
BOOL CALLBACK SetFontProc(HWND aHWnd, LPARAM lParam)
{
SendMessage(aHWnd, WM_SETFONT, lParam, 0);
return TRUE;
}
/* Dialog Function for the SetupDialog */
static LRESULT CALLBACK SetupDialogFunc(HWND aDlg, UINT aMsg, WPARAM wParam, LPARAM lParam)
{
switch(aMsg)
{
case WM_CREATE:
{
CreateWindow("STATIC",
"Enter a peer IP-Address,\r\nor leave it empty to wait for\r\nan incomming message",
WS_CHILD | WS_VISIBLE | SS_LEFT,
5, 5, 300, 50,
aDlg,
(HMENU )-1,
0,
0);
CreateWindow("STATIC",
"IP-Address",
WS_CHILD | WS_VISIBLE | SS_LEFT,
5, 60, 300, 15,
aDlg,
(HMENU )-1,
0,
0);
CreateWindowEx(WS_EX_CLIENTEDGE,
"Edit",
"",
WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | WS_TABSTOP,
5, 80, 250, 22,
aDlg,
(HMENU )SetupEditId,
0,
0);
CreateWindow("BUTTON",
"OK",
WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON,
5, 115, 50, 25,
aDlg,
(HMENU )IDOK,
0,
0);
RegistryClass Registry(REG_KEY);
Registry.GetString("IPAddress", IPAddressStr, sizeof(IPAddressStr));
SetDlgItemText(aDlg, SetupEditId, IPAddressStr);
EnumChildWindows(aDlg, SetFontProc, (LPARAM )GetStockObject(DEFAULT_GUI_FONT));
}
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
{
GetDlgItemText(aDlg, SetupEditId, IPAddressStr, sizeof(IPAddressStr));
RegistryClass Registry(REG_KEY);
Registry.WriteString("IPAddress", IPAddressStr);
PostMessage(aDlg, WM_QUIT, 1, 1);
}
}
break;
}
return DefWindowProc(aDlg, aMsg, wParam, lParam);
}
/* Show the Setupdialog */
BOOL DoSetupDialog(HINSTANCE aHInst)
{
WNDCLASS wc;
memset(&wc, 0, sizeof(WNDCLASS));
wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
wc.lpfnWndProc = SetupDialogFunc;
wc.hInstance = aHInst;
wc.hbrBackground = (HBRUSH )(COLOR_BTNFACE + 1);
wc.lpszClassName = "SetupDialogClass";
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
if(!RegisterClass(&wc))
return FALSE;
HWND WindowHandle = CreateWindow("SetupDialogClass",
"Whatever", // Caption text
WS_MINIMIZEBOX | WS_VISIBLE | WS_CLIPSIBLINGS | DS_CENTER |
WS_CLIPCHILDREN | WS_MAXIMIZEBOX | WS_CAPTION | WS_BORDER | WS_SYSMENU,
100, 100, 300, 180, // Position
0,
0,
aHInst,
0);
MSG Msg;
while(GetMessage(&Msg, WindowHandle, 0, 0xFFFF) > 0)
{
if(!IsDialogMessage(WindowHandle, &Msg))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
}
DestroyWindow(WindowHandle);
return Msg.wParam;
}
DWORD WINAPI RxThreadProc(LPVOID Param)
{
bool First = true;
while(RunRxThread)
{
fd_set ReadSet;
FD_ZERO(&ReadSet);
FD_SET(Socket, &ReadSet);
timeval TimeOut;
TimeOut.tv_sec = 1;
TimeOut.tv_usec = 0;
if(select(Socket + 1, &ReadSet, 0, 0, &TimeOut) == 1)
{
const int MaxLineLength = 256;
char *buffer = new char [MaxLineLength];
sockaddr_in RxSockAddr;
int FromLen = sizeof(RxSockAddr);
if(recvfrom(Socket, buffer, MaxLineLength, 0, (sockaddr *)&RxSockAddr, &FromLen) != SOCKET_ERROR)
{
PostMessage((HWND )Param, RX_THREAD_MESSAGE, (WPARAM )buffer, 0);
RxAddr = RxSockAddr.sin_addr;
HasRxAddr = true;
}
else
{
delete [] buffer;
if(First)
{
char Buf[256];
sprintf(Buf, "Error: %d", WSAGetLastError());
MessageBox((HWND )Param, Buf, "P2P-Chat", MB_OK);
First = false;
}
}
}
}
RxThreadDone = true;
return 0;
}
int APIENTRY WinMain(HINSTANCE aHInst, HINSTANCE, LPSTR, int)
{
if(!DoSetupDialog(aHInst))
{
return 1;
}
WNDCLASS wc;
memset(&wc, 0, sizeof(WNDCLASS));
wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
wc.lpfnWndProc = DialogFunc;
wc.hInstance = aHInst;
wc.hbrBackground = (HBRUSH )(COLOR_BTNFACE + 1);
wc.lpszClassName = "MainDialogClass";
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
if(!RegisterClass(&wc))
return FALSE;
HWND WindowHandle = CreateWindow("MainDialogClass",
"Whatever", // Caption text
WS_MINIMIZEBOX | WS_VISIBLE | WS_CLIPSIBLINGS | WS_THICKFRAME |
WS_CLIPCHILDREN | WS_MAXIMIZEBOX | WS_CAPTION | WS_BORDER | WS_SYSMENU,
100, 100, 140, 160, // Position
0,
0,
aHInst,
0);
MSG Msg;
while(GetMessage(&Msg, 0, 0, 0xFFFF) > 0)
{
if(!IsDialogMessage(WindowHandle, &Msg))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
}
return 0;
}
/*
** Create the socket, and start the RX thread.
*/
int SetupSocket(HWND hDlg)
{
WSADATA wsaData;
struct sockaddr_in sockaddr;
if(WSAStartup(MAKEWORD(1, 1), &wsaData))
{
MessageBox(hDlg, "Failed to start WSA", "P2P-Chat", MB_OK);
return 1;
}
Socket = socket(AF_INET, SOCK_DGRAM, 0);
if(Socket == INVALID_SOCKET)
{
MessageBox(hDlg, "Failed To Create Socket!", "P2P-Chat", MB_OK);
return 1;
}
memset((char *)&sockaddr, 0, sizeof(sockaddr));
sockaddr.sin_family = AF_INET;
sockaddr.sin_port = htons(SocketPort);
BOOL Flag = TRUE;
setsockopt(Socket, SOL_SOCKET, SO_REUSEADDR, (char *)&Flag, sizeof(Flag));
if(bind(Socket, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) < 0)
{
MessageBox(0, "Failed to bind socket!", "P2P-Chat", MB_OK);
return 1;
}
DWORD RxThreadID;
CreateThread(0, 0, RxThreadProc, (LPVOID )hDlg, 0, &RxThreadID);
return 1;
}
void OnSize(HWND aMainWnd, int aWidth, int aHeight)
{
HWND hwnd;
hwnd = GetDlgItem(aMainWnd, SendButtonCtrlId);
MoveWindow(hwnd, 5, aHeight - 25, 50, 20, TRUE);
hwnd = GetDlgItem(aMainWnd, OkButtonCtrlId);
MoveWindow(hwnd, 70, aHeight - 25, 50, 20, TRUE);
hwnd = GetDlgItem(aMainWnd, EditCtrlId);
MoveWindow(hwnd, 5, aHeight - 55, aWidth - 10, 25, TRUE);
hwnd = GetDlgItem(aMainWnd, ListCtrlId);
MoveWindow(hwnd, 5, 5, aWidth - 10, aHeight - 65, TRUE);
}
/*
** This is the main function for the main dialog. It handles all messages.
*/
static LRESULT CALLBACK DialogFunc(HWND aDlg, UINT aMsg, WPARAM wParam, LPARAM lParam)
{
switch(aMsg)
{
case WM_CREATE:
{
CreateWindowEx(WS_EX_CLIENTEDGE,
"LISTBOX",
"",
WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | WS_HSCROLL | LBS_NOINTEGRALHEIGHT,
5, 5, 100, 100,
aDlg,
(HMENU )ListCtrlId,
0,
0);
CreateWindowEx(WS_EX_CLIENTEDGE,
"Edit",
"",
WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL,
5, 80, 250, 22,
aDlg,
(HMENU )EditCtrlId,
0,
0);
CreateWindow("BUTTON",
"Send",
WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON,
5, 100, 50, 20,
aDlg,
(HMENU )SendButtonCtrlId,
0,
0);
CreateWindow("BUTTON",
"Exit",
WS_CHILD | WS_VISIBLE | WS_TABSTOP,
5, 100, 50, 20,
aDlg,
(HMENU )OkButtonCtrlId,
0,
0);
SetupSocket(aDlg);
HWND Edit = GetDlgItem(aDlg, EditCtrlId);
SetFocus(Edit);
RegistryClass Registry(REG_KEY);
RECT R;
R.left = Registry.GetInt("LeftPos", -1);
if(R.left != -1)
{
R.right = Registry.GetInt("RightPos", R.left + 200);
R.top = Registry.GetInt("TopPos", 100);
R.bottom = Registry.GetInt("BottomPos", R.top + 200);
MoveWindow(aDlg, R.left, R.top, R.right - R.left, R.bottom - R.top, TRUE);
}
else
{
GetClientRect(aDlg, &R);
OnSize(aDlg, R.right - R.left, R.bottom - R.top);
}
EnumChildWindows(aDlg, SetFontProc, (LPARAM )GetStockObject(DEFAULT_GUI_FONT));
return FALSE;
}
case RX_THREAD_MESSAGE:
{
char *text = (char *)wParam;
AddListText(aDlg, text);
delete [] text;
}
break;
case WM_GETMINMAXINFO:
{
MINMAXINFO *MinMaxInfo = (MINMAXINFO *)lParam;
MinMaxInfo->ptMinTrackSize.x = 200;
MinMaxInfo->ptMinTrackSize.y = 200;
}
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case OkButtonCtrlId:
CleanUp(aDlg);
PostMessage(aDlg, WM_QUIT, 1, 1);
break;
case SendButtonCtrlId:
HandleSend(aDlg);
return 0;
}
break;
case WM_SIZE:
OnSize(aDlg, LOWORD(lParam), HIWORD(lParam));
return 0;
}
return DefWindowProc(aDlg, aMsg, wParam, lParam);
}
void CleanUp(HWND aHwnd)
{
RunRxThread = false;
RegistryClass Registry(REG_KEY);
RECT R;
GetWindowRect(aHwnd, &R);
Registry.WriteInt("LeftPos", R.left);
Registry.WriteInt("RightPos", R.right);
Registry.WriteInt("TopPos", R.top);
Registry.GetInt("BottomPos", R.bottom);
while(!RxThreadDone)
Sleep(100);
if(Socket)
closesocket(Socket);
Socket = 0;
WSACleanup();
}