diff --git a/WinChat/WinChat.rc b/WinChat/WinChat.rc index 387447d..0116b46 100644 Binary files a/WinChat/WinChat.rc and b/WinChat/WinChat.rc differ diff --git a/WinChat/resource.h b/WinChat/resource.h index 2a8ba86..afd17b3 100644 --- a/WinChat/resource.h +++ b/WinChat/resource.h @@ -7,6 +7,7 @@ #define IDI_ICONMAIN 106 #define IDD_DIALOGCONNECTING 107 #define IDD_DIALOGCHAT 109 +#define IDD_DIALOGACCEPTCONNECTION 111 #define IDC_STATICTITLE 1001 #define IDC_BUTTONEXIT 1003 #define IDC_BUTTONCONNECT 1005 @@ -20,6 +21,7 @@ #define IDC_EDITCHATINPUT 1013 #define IDC_BUTTONSEND 1014 #define IDC_BUTTONDISCONNECT 1015 +#define IDC_STATICREMOTEINFO 1017 #define ID_FILE_EXIT 40001 #define ID_HELP_ABOUT 40002 @@ -27,9 +29,9 @@ // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 111 +#define _APS_NEXT_RESOURCE_VALUE 113 #define _APS_NEXT_COMMAND_VALUE 40003 -#define _APS_NEXT_CONTROL_VALUE 1016 +#define _APS_NEXT_CONTROL_VALUE 1018 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif diff --git a/WinChat/src/Application.cpp b/WinChat/src/Application.cpp index 81e080f..5000583 100644 --- a/WinChat/src/Application.cpp +++ b/WinChat/src/Application.cpp @@ -118,6 +118,8 @@ namespace wc { m_inAddress = toWideStr(remoteStr); m_inSocket = conSock; + + //Wait here until there is no incoming connection anymore before accepting again } closesocket(sock); @@ -144,15 +146,13 @@ namespace wc { GetMonitorInfo(MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST), &mi); xPos = mi.rcMonitor.left + 100, yPos = mi.rcMonitor.top + 100; } - SetWindowPos(dlg, nullptr, xPos, yPos, 0, 0, SWP_NOSIZE | SWP_NOZORDER); + SetWindowPos(dlg, nullptr, xPos, yPos, 0, 0, SWP_NOSIZE | SWP_NOZORDER); SetDlgItemText(dlg, IDC_STATICTITLE, app->m_appName.c_str()); LOGFONT lFont = { .lfHeight = 50 }; HFONT font = CreateFontIndirect(&lFont); SendMessage(GetDlgItem(dlg, IDC_STATICTITLE), WM_SETFONT, reinterpret_cast(font), NULL); - SetDlgItemText(dlg, IDC_STATICDESC, L"A simple Windows chat app"); - SendDlgItemMessage(dlg, IDC_EDITADDRESS, EM_SETCUEBANNER, TRUE, reinterpret_cast(L"Address")); SendDlgItemMessage(dlg, IDC_EDITSCREENNAME, EM_SETCUEBANNER, TRUE, reinterpret_cast(L"User")); @@ -202,10 +202,23 @@ namespace wc { case WM_TIMER: if (wParam == IDT_CHECKINCONN && app->m_inSocket != INVALID_SOCKET) { KillTimer(dlg, IDT_CHECKINCONN); - //Ask if to connect and for screen name here RECT dlgRect = { }; GetWindowRect(dlg, &dlgRect); - EndDialog(dlg, reinterpret_cast(new MainDlgOutput{ app->m_inAddress, L"Temp screen name", dlgRect.left, dlgRect.top, app->m_inSocket })); + MainDlgInput acceptInput = { app, dlgRect.left, dlgRect.top }; + + INT_PTR result = DialogBoxParam(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOGACCEPTCONNECTION), dlg, reinterpret_cast(acceptDlgProc), reinterpret_cast(&acceptInput)); + + if (result == IDCANCEL) { + closesocket(app->m_inSocket); + app->m_inSocket = INVALID_SOCKET; + SetTimer(dlg, IDT_CHECKINCONN, 100, nullptr); + return TRUE; + } + + MainDlgOutput* out = reinterpret_cast(result); + + EndDialog(dlg, reinterpret_cast(new MainDlgOutput{ app->m_inAddress, out->screenname, dlgRect.left, dlgRect.top, app->m_inSocket })); + delete out; app->m_inSocket = INVALID_SOCKET; return TRUE; } @@ -220,6 +233,50 @@ namespace wc { return FALSE; } + BOOL CALLBACK Application::acceptDlgProc(HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam) { + static Application* app = nullptr; + + switch (msg) { + case WM_INITDIALOG: { + MainDlgInput* in = reinterpret_cast(lParam); + app = in->appPtr; + + SendMessage(dlg, WM_SETICON, ICON_BIG, reinterpret_cast(LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICONMAIN)))); + SetWindowPos(dlg, nullptr, in->xPos + 30, in->yPos + 30, 0, 0, SWP_NOSIZE | SWP_NOZORDER); + + SetDlgItemText(dlg, IDC_STATICREMOTEINFO, app->m_inAddress.c_str()); + SendDlgItemMessage(dlg, IDC_EDITSCREENNAME, EM_SETCUEBANNER, TRUE, reinterpret_cast(L"User")); + + return TRUE; + } + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDOK: { + int inputLength = GetWindowTextLength(GetDlgItem(dlg, IDC_EDITSCREENNAME)); + if (!inputLength) { + EDITBALLOONTIP balloon = { .cbStruct = sizeof(balloon), .pszTitle = L"Alert", .pszText = L"You must enter a screen name." }; + SendDlgItemMessage(dlg, IDC_EDITSCREENNAME, EM_SHOWBALLOONTIP, NULL, reinterpret_cast(&balloon)); + return TRUE; + } + + std::wstring buffer(inputLength, 0); + GetDlgItemText(dlg, IDC_EDITSCREENNAME, buffer.data(), static_cast(buffer.size() + 1)); + EndDialog(dlg, reinterpret_cast(new MainDlgOutput{ std::wstring(), buffer, NULL, NULL, INVALID_SOCKET})); + return TRUE; + } + + case IDCANCEL: + EndDialog(dlg, wParam); + return TRUE; + } + + return FALSE; + } + + return FALSE; + } + Application::~Application() { WSACleanup(); } diff --git a/WinChat/src/Application.h b/WinChat/src/Application.h index 08d8f74..d7c55f3 100644 --- a/WinChat/src/Application.h +++ b/WinChat/src/Application.h @@ -15,6 +15,7 @@ namespace wc { private: void startListen(); static BOOL CALLBACK mainDlgProc(HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam); + static BOOL CALLBACK acceptDlgProc(HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam); const std::wstring m_appName; const std::wstring m_appVersion; diff --git a/WinChat/src/Chat.cpp b/WinChat/src/Chat.cpp index 27dc28e..75defdc 100644 --- a/WinChat/src/Chat.cpp +++ b/WinChat/src/Chat.cpp @@ -77,7 +77,16 @@ namespace wc { //Send and receive screen names send(sock, reinterpret_cast(m_screenname.c_str()), static_cast(m_screenname.size()) * sizeof(wchar_t), NULL); - m_remoteScreenname.resize(recv(sock, reinterpret_cast(m_remoteScreenname.data()), 1000, NULL) / 2); + int bytesRemoteScreenname = recv(sock, reinterpret_cast(m_remoteScreenname.data()), 1000, NULL); + + if (!bytesRemoteScreenname || WSAGetLastError() == WSAECONNRESET) { + MessageBox(nullptr, L"The remote host denied the connection.", L"Error", MB_ICONERROR); + m_connectionError = true; + closesocket(sock); + return; + } + + m_remoteScreenname.resize(bytesRemoteScreenname / 2); ioctlsocket(sock, FIONBIO, &yes); m_connected = true; @@ -85,7 +94,7 @@ namespace wc { std::wstring recvBuffer(2000, 0); std::wstring sendStr; int bytesRecvd = 0; - while (m_connected) { + while (m_connected && !m_connectionError) { while (!m_sendQueue.empty()) { sendStr = m_sendQueue.pop(); send(sock, reinterpret_cast(sendStr.c_str()), static_cast(sendStr.size()) * sizeof(wchar_t), NULL); @@ -147,9 +156,11 @@ namespace wc { ChatDlgInput* in = reinterpret_cast(lParam); chat = in->chatPtr; + SendMessage(dlg, WM_SETICON, ICON_BIG, reinterpret_cast(LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICONMAIN)))); SetWindowPos(dlg, nullptr, in->xPos + 100, in->yPos + 100, 0, 0, SWP_NOSIZE | SWP_NOZORDER); SetDlgItemText(dlg, IDC_STATICADDRESS, chat->m_address.c_str()); SendDlgItemMessage(dlg, IDC_PROGRESS, PBM_SETMARQUEE, TRUE, NULL); + SetTimer(dlg, IDT_CHECKCONN, 100, nullptr); return TRUE; @@ -175,9 +186,7 @@ namespace wc { SetWindowText(dlg, std::format(L"{} - WinChat", chat->m_remoteScreenname).c_str()); SendMessage(dlg, WM_SETICON, ICON_BIG, reinterpret_cast(LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICONMAIN)))); - SetWindowPos(dlg, nullptr, in->xPos - 50, in->yPos - 50, 0, 0, SWP_NOSIZE | SWP_NOZORDER); - SendDlgItemMessage(dlg, IDC_EDITCHATINPUT, EM_SETCUEBANNER, TRUE, reinterpret_cast(L"Message")); SetDlgItemText(dlg, IDC_EDITCHATDISPLAY, std::format(L"Connected to {} at {}", chat->m_remoteScreenname, chat->m_address).c_str());