Add connection dialog
This commit is contained in:
parent
3053a0b8f8
commit
15655a6aec
Binary file not shown.
@ -24,6 +24,12 @@
|
|||||||
<ClCompile Include="src\Chat.cpp">
|
<ClCompile Include="src\Chat.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\pch.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\StrConv.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="src\Application.h">
|
<ClInclude Include="src\Application.h">
|
||||||
@ -35,6 +41,12 @@
|
|||||||
<ClInclude Include="src\Chat.h">
|
<ClInclude Include="src\Chat.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\pch.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\StrConv.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="WinChat.rc">
|
<ResourceCompile Include="WinChat.rc">
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#define IDD_DIALOGMAIN 101
|
#define IDD_DIALOGMAIN 101
|
||||||
#define IDR_MENUMAIN 104
|
#define IDR_MENUMAIN 104
|
||||||
#define IDI_ICONMAIN 106
|
#define IDI_ICONMAIN 106
|
||||||
|
#define IDD_DIALOGCONNECTING 107
|
||||||
#define IDC_STATICTITLE 1001
|
#define IDC_STATICTITLE 1001
|
||||||
#define IDC_BUTTONEXIT 1003
|
#define IDC_BUTTONEXIT 1003
|
||||||
#define IDC_BUTTONCONNECT 1005
|
#define IDC_BUTTONCONNECT 1005
|
||||||
@ -12,6 +13,8 @@
|
|||||||
#define IDC_ICONMAIN 1007
|
#define IDC_ICONMAIN 1007
|
||||||
#define IDC_EDITSCREENNAME 1008
|
#define IDC_EDITSCREENNAME 1008
|
||||||
#define IDC_STATICDESC 1009
|
#define IDC_STATICDESC 1009
|
||||||
|
#define IDC_STATICADDRESS 1010
|
||||||
|
#define IDC_PROGRESS 1011
|
||||||
#define ID_FILE_EXIT 40001
|
#define ID_FILE_EXIT 40001
|
||||||
#define ID_HELP_ABOUT 40002
|
#define ID_HELP_ABOUT 40002
|
||||||
|
|
||||||
@ -19,9 +22,9 @@
|
|||||||
//
|
//
|
||||||
#ifdef APSTUDIO_INVOKED
|
#ifdef APSTUDIO_INVOKED
|
||||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
#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_COMMAND_VALUE 40003
|
||||||
#define _APS_NEXT_CONTROL_VALUE 1010
|
#define _APS_NEXT_CONTROL_VALUE 1012
|
||||||
#define _APS_NEXT_SYMED_VALUE 101
|
#define _APS_NEXT_SYMED_VALUE 101
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
@ -42,24 +42,24 @@ namespace wc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Application::run() {
|
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);
|
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;
|
INT_PTR result = NULL;
|
||||||
MainDlgInput* input = new MainDlgInput{ this, -1, -1 };
|
MainDlgInput* input = new MainDlgInput{ this, -1, -1 };
|
||||||
while (result = DialogBoxParam(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOGMAIN), nullptr, (DLGPROC)mainDlgProc, reinterpret_cast<LPARAM>(input))) {
|
while (result = DialogBoxParam(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOGMAIN), nullptr, reinterpret_cast<DLGPROC>(mainDlgProc), reinterpret_cast<LPARAM>(input))) {
|
||||||
//Then create a Chat with the collected input...
|
//Then create a Chat with the collected input
|
||||||
MainDlgOutput* output = reinterpret_cast<MainDlgOutput*>(result);
|
MainDlgOutput* output = reinterpret_cast<MainDlgOutput*>(result);
|
||||||
const auto [address, screenname, x, y] = *output;
|
const auto [address, screenname, x, y] = *output;
|
||||||
delete output;
|
delete output;
|
||||||
|
|
||||||
{
|
{
|
||||||
Chat chat(address, screenname);
|
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 };
|
input = new MainDlgInput{ this, x, y };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,13 +134,13 @@ namespace wc {
|
|||||||
case WM_INITDIALOG: {
|
case WM_INITDIALOG: {
|
||||||
MainDlgInput* in = reinterpret_cast<MainDlgInput*>(lParam);
|
MainDlgInput* in = reinterpret_cast<MainDlgInput*>(lParam);
|
||||||
auto [appTemp, xPos, yPos] = *in;
|
auto [appTemp, xPos, yPos] = *in;
|
||||||
app = appTemp;
|
|
||||||
delete in;
|
delete in;
|
||||||
|
app = appTemp;
|
||||||
|
|
||||||
SetWindowText(dlg, app->m_appName.c_str());
|
SetWindowText(dlg, app->m_appName.c_str());
|
||||||
SendMessage(dlg, WM_SETICON, ICON_BIG, reinterpret_cast<LPARAM>(LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICONMAIN))));
|
SendMessage(dlg, WM_SETICON, ICON_BIG, reinterpret_cast<LPARAM>(LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICONMAIN))));
|
||||||
|
|
||||||
if (xPos < 0) {
|
if (xPos == -1 && yPos == -1) {
|
||||||
POINT pt = { };
|
POINT pt = { };
|
||||||
GetCursorPos(&pt);
|
GetCursorPos(&pt);
|
||||||
MONITORINFO mi = { };
|
MONITORINFO mi = { };
|
||||||
@ -171,7 +171,7 @@ namespace wc {
|
|||||||
int addressSize = GetWindowTextLength(GetDlgItem(dlg, IDC_EDITADDRESS));
|
int addressSize = GetWindowTextLength(GetDlgItem(dlg, IDC_EDITADDRESS));
|
||||||
int screennameSize = GetWindowTextLength(GetDlgItem(dlg, IDC_EDITSCREENNAME));
|
int screennameSize = GetWindowTextLength(GetDlgItem(dlg, IDC_EDITSCREENNAME));
|
||||||
if (!addressSize || !screennameSize) {
|
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<LPARAM>(&balloon));
|
SendDlgItemMessage(dlg, addressSize ? IDC_EDITSCREENNAME : IDC_EDITADDRESS, EM_SHOWBALLOONTIP, NULL, reinterpret_cast<LPARAM>(&balloon));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -204,7 +204,7 @@ namespace wc {
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
case WM_HOTKEY:
|
case WM_HOTKEY:
|
||||||
if (wParam != 1)
|
if (wParam != 1 || GetForegroundWindow() != dlg)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
case WM_CLOSE:
|
case WM_CLOSE:
|
||||||
|
@ -2,19 +2,43 @@
|
|||||||
#include "Chat.h"
|
#include "Chat.h"
|
||||||
|
|
||||||
#include "StrConv.h"
|
#include "StrConv.h"
|
||||||
|
#include "../resource.h"
|
||||||
|
|
||||||
|
#define IDT_CHECKCONN 1
|
||||||
|
|
||||||
namespace wc {
|
namespace wc {
|
||||||
|
struct ConnDlgInput {
|
||||||
|
Chat* chat;
|
||||||
|
int xPos, yPos;
|
||||||
|
};
|
||||||
|
|
||||||
Chat::Chat(std::wstring address, std::wstring screenname)
|
Chat::Chat(std::wstring address, std::wstring screenname)
|
||||||
: m_address(address)
|
: m_address(address)
|
||||||
, m_screenname(screenname)
|
, 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<DLGPROC>(connDlgProc), reinterpret_cast<LPARAM>(input));
|
||||||
|
|
||||||
|
netThread.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Chat::runNetThread() {
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
|
|
||||||
addrinfo* destInfo = nullptr;
|
addrinfo* destInfo = nullptr;
|
||||||
if (getaddrinfo(toStr(m_address).c_str(), "9430", nullptr, &destInfo) != 0) {
|
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);
|
MessageBox(nullptr, L"Error: Could not resolve host or invalid address!", L"Error", MB_ICONERROR);
|
||||||
|
m_connectionError = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,42 +46,21 @@ namespace wc {
|
|||||||
if (sock == INVALID_SOCKET) {
|
if (sock == INVALID_SOCKET) {
|
||||||
MessageBox(nullptr, L"Error: could not create network socket!", L"Error", MB_ICONERROR);
|
MessageBox(nullptr, L"Error: could not create network socket!", L"Error", MB_ICONERROR);
|
||||||
freeaddrinfo(destInfo);
|
freeaddrinfo(destInfo);
|
||||||
|
m_connectionError = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connect(sock, destInfo->ai_addr, static_cast<int>(destInfo->ai_addrlen)) != 0) {
|
if (connect(sock, destInfo->ai_addr, static_cast<int>(destInfo->ai_addrlen)) != 0) {
|
||||||
int errorCode = WSAGetLastError();
|
std::wstring errorStr = getErrorString();
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageBox(nullptr, std::format(L"Error: Could not connect - {}", errorStr).c_str(), L"Error", MB_ICONERROR);
|
MessageBox(nullptr, std::format(L"Error: Could not connect - {}", errorStr).c_str(), L"Error", MB_ICONERROR);
|
||||||
freeaddrinfo(destInfo);
|
freeaddrinfo(destInfo);
|
||||||
closesocket(sock);
|
closesocket(sock);
|
||||||
|
m_connectionError = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
freeaddrinfo(destInfo);
|
freeaddrinfo(destInfo);
|
||||||
|
m_connected = true;
|
||||||
|
|
||||||
std::string data;
|
std::string data;
|
||||||
while (data != "end") {
|
while (data != "end") {
|
||||||
@ -68,6 +71,63 @@ namespace wc {
|
|||||||
closesocket(sock);
|
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<ConnDlgInput*>(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() {
|
Chat::~Chat() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -8,11 +8,17 @@ namespace wc {
|
|||||||
public:
|
public:
|
||||||
Chat(std::wstring address, std::wstring screenname);
|
Chat(std::wstring address, std::wstring screenname);
|
||||||
|
|
||||||
void run();
|
void run(int xPos, int yPos);
|
||||||
|
|
||||||
~Chat();
|
~Chat();
|
||||||
private:
|
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_address;
|
||||||
const std::wstring m_screenname;
|
const std::wstring m_screenname;
|
||||||
|
bool m_connected;
|
||||||
|
bool m_connectionError;
|
||||||
};
|
};
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user