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">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\pch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\StrConv.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="src\Application.h">
|
||||
@ -35,6 +41,12 @@
|
||||
<ClInclude Include="src\Chat.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\pch.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\StrConv.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="WinChat.rc">
|
||||
|
@ -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
|
||||
|
@ -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<LPARAM>(input))) {
|
||||
//Then create a Chat with the collected 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
|
||||
MainDlgOutput* output = reinterpret_cast<MainDlgOutput*>(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<MainDlgInput*>(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<LPARAM>(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<LPARAM>(&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:
|
||||
|
@ -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<DLGPROC>(connDlgProc), reinterpret_cast<LPARAM>(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<int>(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<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() {
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user