diff --git a/WinChat/WinChat.rc b/WinChat/WinChat.rc
index e402b59..b3debba 100644
Binary files a/WinChat/WinChat.rc and b/WinChat/WinChat.rc differ
diff --git a/WinChat/WinChat.vcxproj.filters b/WinChat/WinChat.vcxproj.filters
index fc05d7b..07bc997 100644
--- a/WinChat/WinChat.vcxproj.filters
+++ b/WinChat/WinChat.vcxproj.filters
@@ -24,6 +24,12 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
@@ -35,6 +41,12 @@
Header Files
+
+ Header Files
+
+
+ Header Files
+
diff --git a/WinChat/resource.h b/WinChat/resource.h
index 7e418c0..347b243 100644
--- a/WinChat/resource.h
+++ b/WinChat/resource.h
@@ -5,6 +5,7 @@
#define IDD_DIALOGMAIN 101
#define IDR_MENUMAIN 104
#define IDI_ICONMAIN 106
+#define IDD_DIALOGCONNECTING 107
#define IDC_STATICTITLE 1001
#define IDC_BUTTONEXIT 1003
#define IDC_BUTTONCONNECT 1005
@@ -12,6 +13,8 @@
#define IDC_ICONMAIN 1007
#define IDC_EDITSCREENNAME 1008
#define IDC_STATICDESC 1009
+#define IDC_STATICADDRESS 1010
+#define IDC_PROGRESS 1011
#define ID_FILE_EXIT 40001
#define ID_HELP_ABOUT 40002
@@ -19,9 +22,9 @@
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 107
+#define _APS_NEXT_RESOURCE_VALUE 109
#define _APS_NEXT_COMMAND_VALUE 40003
-#define _APS_NEXT_CONTROL_VALUE 1010
+#define _APS_NEXT_CONTROL_VALUE 1012
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
diff --git a/WinChat/src/Application.cpp b/WinChat/src/Application.cpp
index cc4233b..8d7fe87 100644
--- a/WinChat/src/Application.cpp
+++ b/WinChat/src/Application.cpp
@@ -42,24 +42,24 @@ namespace wc {
}
void Application::run() {
- //First, start a thread to listen for incoming connections...
+ //First, start a thread to listen for incoming connections
std::thread listenThread(&Application::startListen, this);
- //Then, run the main dialog to get needed input...
+ //Then, run the main dialog to get needed input
INT_PTR result = NULL;
MainDlgInput* input = new MainDlgInput{ this, -1, -1 };
- while (result = DialogBoxParam(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOGMAIN), nullptr, (DLGPROC)mainDlgProc, reinterpret_cast(input))) {
- //Then create a Chat with the collected input...
+ while (result = DialogBoxParam(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOGMAIN), nullptr, reinterpret_cast(mainDlgProc), reinterpret_cast(input))) {
+ //Then create a Chat with the collected input
MainDlgOutput* output = reinterpret_cast(result);
const auto [address, screenname, x, y] = *output;
delete output;
{
Chat chat(address, screenname);
- chat.run();
+ chat.run(x, y);
}
- //And repeat until the user exits from the main dialog.
+ //And repeat until the user exits from the main dialog
input = new MainDlgInput{ this, x, y };
}
@@ -134,13 +134,13 @@ namespace wc {
case WM_INITDIALOG: {
MainDlgInput* in = reinterpret_cast(lParam);
auto [appTemp, xPos, yPos] = *in;
- app = appTemp;
delete in;
+ app = appTemp;
SetWindowText(dlg, app->m_appName.c_str());
SendMessage(dlg, WM_SETICON, ICON_BIG, reinterpret_cast(LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICONMAIN))));
- if (xPos < 0) {
+ if (xPos == -1 && yPos == -1) {
POINT pt = { };
GetCursorPos(&pt);
MONITORINFO mi = { };
@@ -171,7 +171,7 @@ namespace wc {
int addressSize = GetWindowTextLength(GetDlgItem(dlg, IDC_EDITADDRESS));
int screennameSize = GetWindowTextLength(GetDlgItem(dlg, IDC_EDITSCREENNAME));
if (!addressSize || !screennameSize) {
- EDITBALLOONTIP balloon = { .cbStruct = sizeof(balloon), .pszTitle = L"Alert", .pszText = L"You must enter an address and screenname." };
+ EDITBALLOONTIP balloon = { .cbStruct = sizeof(balloon), .pszTitle = L"Alert", .pszText = L"You must enter an address and screen name." };
SendDlgItemMessage(dlg, addressSize ? IDC_EDITSCREENNAME : IDC_EDITADDRESS, EM_SHOWBALLOONTIP, NULL, reinterpret_cast(&balloon));
return TRUE;
}
@@ -204,7 +204,7 @@ namespace wc {
return FALSE;
case WM_HOTKEY:
- if (wParam != 1)
+ if (wParam != 1 || GetForegroundWindow() != dlg)
return FALSE;
[[fallthrough]];
case WM_CLOSE:
diff --git a/WinChat/src/Chat.cpp b/WinChat/src/Chat.cpp
index 679c211..45bc9a8 100644
--- a/WinChat/src/Chat.cpp
+++ b/WinChat/src/Chat.cpp
@@ -2,19 +2,43 @@
#include "Chat.h"
#include "StrConv.h"
+#include "../resource.h"
+
+#define IDT_CHECKCONN 1
namespace wc {
+ struct ConnDlgInput {
+ Chat* chat;
+ int xPos, yPos;
+ };
+
Chat::Chat(std::wstring address, std::wstring screenname)
: m_address(address)
, m_screenname(screenname)
+ , m_connected(false)
+ , m_connectionError(false)
{
}
- void Chat::run() {
+ void Chat::run(int xPos, int yPos) {
+ //Run net thread to connect and communicate
+ std::thread netThread(&Chat::runNetThread, this);
+
+ //Show connection dialog until net thread connects
+ ConnDlgInput* input = new ConnDlgInput{ this, xPos, yPos };
+ DialogBoxParam(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOGCONNECTING), nullptr, reinterpret_cast(connDlgProc), reinterpret_cast(input));
+
+ netThread.join();
+ }
+
+ void Chat::runNetThread() {
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
addrinfo* destInfo = nullptr;
if (getaddrinfo(toStr(m_address).c_str(), "9430", nullptr, &destInfo) != 0) {
MessageBox(nullptr, L"Error: Could not resolve host or invalid address!", L"Error", MB_ICONERROR);
+ m_connectionError = true;
return;
}
@@ -22,42 +46,21 @@ namespace wc {
if (sock == INVALID_SOCKET) {
MessageBox(nullptr, L"Error: could not create network socket!", L"Error", MB_ICONERROR);
freeaddrinfo(destInfo);
+ m_connectionError = true;
return;
}
if (connect(sock, destInfo->ai_addr, static_cast(destInfo->ai_addrlen)) != 0) {
- int errorCode = WSAGetLastError();
- std::wstring errorStr;
- switch (errorCode) {
- case WSAETIMEDOUT:
- errorStr = L"Timed out";
- break;
-
- case WSAECONNREFUSED:
- errorStr = L"Connection refused (WinChat may not be running on remote host)";
- break;
-
- case WSAENETUNREACH:
- case WSAEHOSTUNREACH:
- errorStr = L"Remote host unreachable (You may not be connected to the internet)";
- break;
-
- case WSAEADDRNOTAVAIL:
- errorStr = L"Not a valid address to connect to";
- break;
-
- default:
- errorStr = std::format(L"Error Code {}", errorCode);
- break;
- }
-
+ std::wstring errorStr = getErrorString();
MessageBox(nullptr, std::format(L"Error: Could not connect - {}", errorStr).c_str(), L"Error", MB_ICONERROR);
freeaddrinfo(destInfo);
closesocket(sock);
+ m_connectionError = true;
return;
}
freeaddrinfo(destInfo);
+ m_connected = true;
std::string data;
while (data != "end") {
@@ -68,6 +71,63 @@ namespace wc {
closesocket(sock);
}
+ std::wstring Chat::getErrorString() {
+ int errorCode = WSAGetLastError();
+ std::wstring out;
+ switch (errorCode) {
+ case WSAETIMEDOUT:
+ out = L"Timed out";
+ break;
+
+ case WSAECONNREFUSED:
+ out = L"Connection refused (WinChat may not be running on remote host)";
+ break;
+
+ case WSAENETUNREACH:
+ case WSAEHOSTUNREACH:
+ out = L"Remote host unreachable (You may not be connected to the internet)";
+ break;
+
+ case WSAEADDRNOTAVAIL:
+ out = L"Not a valid address to connect to";
+ break;
+
+ default:
+ out = std::format(L"Error Code {}", errorCode);
+ break;
+ }
+
+ return out;
+ }
+
+ BOOL CALLBACK Chat::connDlgProc(HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam) {
+ static Chat* chat = nullptr;
+
+ switch (msg) {
+ case WM_INITDIALOG: {
+ ConnDlgInput* in = reinterpret_cast(lParam);
+ auto [chatTemp, x, y] = *in;
+ delete in;
+ chat = chatTemp;
+ SetWindowPos(dlg, nullptr, x + 100, y + 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;
+ }
+
+ case WM_TIMER:
+ if (wParam == IDT_CHECKCONN && (chat->m_connected || chat->m_connectionError)) {
+ EndDialog(dlg, 0);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+ }
+
+
Chat::~Chat() {
}
diff --git a/WinChat/src/Chat.h b/WinChat/src/Chat.h
index 00cbec4..9d084eb 100644
--- a/WinChat/src/Chat.h
+++ b/WinChat/src/Chat.h
@@ -8,11 +8,17 @@ namespace wc {
public:
Chat(std::wstring address, std::wstring screenname);
- void run();
+ void run(int xPos, int yPos);
~Chat();
private:
+ void runNetThread();
+ std::wstring getErrorString();
+ static BOOL CALLBACK connDlgProc(HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
const std::wstring m_address;
const std::wstring m_screenname;
+ bool m_connected;
+ bool m_connectionError;
};
}
\ No newline at end of file