📄 simplechatdlg.cpp
字号:
return 0;
}
LRESULT CSimpleChatDlg::OnFileErrorReceive(WPARAM wParam, LPARAM)
{
const CNotifErrorFile_Receive* pEvent = (const CNotifErrorFile_Receive*)wParam;
const CNetFileTransmitInfo info = pEvent->getInfo();
m_ctrlProgressReceived.SetPos(0);
SetDlgItemText(IDST_PERCENTAGE_RECEIVED, "");
SetDlgItemText(IDST_RECEIVED, "Failed.");
// disable cancel button
GetDlgItem(IDBT_RECEIVE_CANCEL)->EnableWindow(FALSE);
GetDlgItem(IDST_PERCENTAGE_RECEIVED)->ShowWindow(SW_HIDE);
delete pEvent;
return 0;
}
LRESULT CSimpleChatDlg::OnFileErrorSend(WPARAM wParam, LPARAM)
{
const CNotifErrorFile_Send* pEvent = (const CNotifErrorFile_Send*)wParam;
const CNetFileTransmitInfo info = pEvent->getInfo();
m_ctrlProgressSent.SetPos(0);
SetDlgItemText(IDST_PERCENTAGE_SENT, "");
SetDlgItemText(IDST_SENT, "Failed.");
// enable the send button
GetDlgItem(IDBT_SEND_FILE)->EnableWindow(TRUE);
// disable cancel button
GetDlgItem(IDBT_SEND_CANCEL)->EnableWindow(FALSE);
GetDlgItem(IDST_PERCENTAGE_SENT)->ShowWindow(SW_HIDE);
delete pEvent;
return 0;
}
LRESULT CSimpleChatDlg::OnFileAbortReceive(WPARAM wParam, LPARAM)
{
const CNotifAbortFile_Receive* pEvent = (const CNotifAbortFile_Receive*)wParam;
const CNetFileTransmitInfo info = pEvent->getInfo();
m_ctrlProgressReceived.SetPos(0);
SetDlgItemText(IDST_PERCENTAGE_RECEIVED, "");
SetDlgItemText(IDST_RECEIVED, "Cancelled.");
// disable the cancel button
GetDlgItem(IDBT_RECEIVE_CANCEL)->EnableWindow(FALSE);
GetDlgItem(IDST_PERCENTAGE_RECEIVED)->ShowWindow(SW_HIDE);
delete pEvent;
return 0;
}
LRESULT CSimpleChatDlg::OnFileAbortSend(WPARAM wParam, LPARAM)
{
const CNotifAbortFile_Send* pEvent = (const CNotifAbortFile_Send*)wParam;
const CNetFileTransmitInfo info = pEvent->getInfo();
m_ctrlProgressSent.SetPos(0);
SetDlgItemText(IDST_PERCENTAGE_SENT, "");
SetDlgItemText(IDST_SENT, "Cancelled.");
// enable the send button
GetDlgItem(IDBT_SEND_FILE)->EnableWindow(TRUE);
// disable cancel button
GetDlgItem(IDBT_SEND_CANCEL)->EnableWindow(FALSE);
GetDlgItem(IDST_PERCENTAGE_SENT)->ShowWindow(SW_HIDE);
delete pEvent;
return 0;
}
void CSimpleChatDlg::Listen(string& addr)
{
// cleanup
DisconnectAll();
// prepare the thread for accepting
if (!m_acceptorThread.SetAddress(addr)) {
MessageBox("Failed to listen on the given address and port. Please correct your parameters.", "Simple Chat", MB_ICONINFORMATION|MB_OK);
return;
}
// subscribe fro the notification from the thread
m_acceptorThread.Subscribe(this);
// start accepting (none blocking, so the thread can successfuly terminate
// if application exists while thread is accepting)
m_acceptorThread.Start();
GetDlgItem(IDBT_GO)->EnableWindow(FALSE);
// enable the disconnect button
GetDlgItem(IDBT_DISCONNECT)->EnableWindow(TRUE);
// minimize the window and create the tray
SetupTrayIcon(true);
}
LRESULT CSimpleChatDlg::OnListening(WPARAM wParam, LPARAM)
{
const CNotifListening* pEvent = (const CNotifListening*)wParam;
delete pEvent;
if (m_acceptorThread.IsStoped()) return 0;
CTimeSpan span = CTime::GetCurrentTime() - m_time;
if (span.GetSeconds() < 1) return 0;
m_time = CTime::GetCurrentTime();
int nDots = m_strStatus.GetLength() - strlen("Listening ");
m_strStatus = "Listening ";
if (nDots > 30) nDots = 0;
for (int i=0; i<nDots + 1; i++)
m_strStatus += '>';
GetDlgItem(IDST_CONNECT_STATUS)->SetWindowText(m_strStatus);
return 0;
}
LRESULT CSimpleChatDlg::OnAcceptError(WPARAM wParam, LPARAM)
{
delete (CNotifEvent*)wParam;
// restore the window
ShowWindow(SW_RESTORE);
MessageBox("A remote peer has arrived but failed to establish a connection on the given address and port. Please try to change the port number.", "Simple Chat", MB_ICONINFORMATION|MB_OK);
// stop the thread
m_acceptorThread.Stop();
// restore the window and remove the tray
SetupTrayIcon(false);
return 0;
}
LRESULT CSimpleChatDlg::OnAccept(WPARAM wParam, LPARAM)
{
delete (CNotifEvent*)wParam;
// by now the acceptor execution thread is no longer running (accepting)
// however the object exists for the lifetime of this dialog
CNetConnection* pConnector = m_acceptorThread.GetConnection();
if (!pConnector) {
WriteSystem("a Peer's attempt to connect has failed");
return 0;
}
// got the connection to the peer. Attach in to the stream
m_NetStream.Attach(pConnector);
// stop the thread
m_acceptorThread.Stop();
// reset the progress status
m_strStatus.Empty();
GetDlgItem(IDST_CONNECT_STATUS)->SetWindowText(m_strStatus);
DisableControls();
// restore the window and remove the tray
SetupTrayIcon(false);
// start up the file listener thread
ListenForFiles();
return 0;
}
void CSimpleChatDlg::DisconnectAll()
{
// if the acceptor thread is running, stop it
if (!m_acceptorThread.IsStoped()) {
// restore the window and remove the tray
SetupTrayIcon(false);
// stop thread
m_acceptorThread.Stop();
// reset the progress status
m_strStatus.Empty();
UpdateData(FALSE);
}
// if the file acceptor thread is running, stop it
m_acceptorFileThread.Stop();
// stop listening for incoming data
// KillTimer(m_nCheckForData);
EnableControls();
// close the text message channel
CNetConnection* pConnection = m_NetStream.Detach();
if (!pConnection) return;
// break the pipe
pConnection->Disconnect();
delete pConnection;
DisconnectFileTransfers();
}
void CSimpleChatDlg::DisconnectFileTransfers()
{
// abort any file transfers
CThreadStorage& storage = g_getThreadStorage();
while (storage.Size() > 0) {
CNetThread* pThread = storage.GetAt(storage.Size() - 1);
// block until thread quits, selfremoves from the storage and selfdestructs
if (pThread)
pThread->Stop();
}
// empty the queue from the notifications
while (IsThereEvent()) {
CNotifEvent* pEvent = GetEvent();
SendMessage(pEvent->event_id(), (WPARAM)pEvent);
}
}
bool CSimpleChatDlg::SendText()
{
if (!m_NetStream.IsOpen()) {
WriteSystem("The connection is broken.");
return false;
}
UpdateData();
CNetText* pNetText = 0;
try {
// create new message with local host id, remote host id and the text message
CNetText::MSG msg;
msg.m_strText = m_strText;
pNetText = new CNetText(m_NetStream.GetConnection()->GetRemoteHandle(), m_NetStream.GetConnection()->GetLocalHandle(), msg) ;
// send the message
m_NetStream << *pNetText;
WriteYourName();
// display this message on the local screen
WriteMsg(pNetText->GetText());
// clean up the edit box
OnClear();
GetDlgItem(IDED_TEXT)->SetFocus();
} catch (CNetException e) {
// if cannot send notify the user and do not clean up the edit box
WriteSystem("The message cannot be delivered.");
// the connection is broken, close the socket
DisconnectAll();
delete pNetText;
return false;
}
// clean up
delete pNetText;
return true;
}
bool CSimpleChatDlg::SendLocalFileAcceptAddr()
{
if (!m_NetStream.IsOpen()) {
WriteSystem("The connection is broken.");
return false;
}
CNetStatus status;
status.SetCode(nsAcceptAddr);
status.SetText(m_acceptorFileThread.GetAddress());
try {
// send the message
m_NetStream << status;
} catch (CNetException e) {
// if cannot send notify the user and do not clean up the edit box
WriteSystem("The message cannot be delivered.");
// the connection is broken, close the socket
DisconnectAll();
return false;
}
return true;
}
bool CSimpleChatDlg::SendFile()
{
if (!m_NetStream.IsOpen()) {
WriteSystem("The connection is broken.");
return false;
}
CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY, "All Files (*.*)|*.*||", this);
if (dlg.DoModal() == IDCANCEL)
return true;
CString strPath = dlg.GetPathName();
// form the connect string
CString strConnect = "file = '";
strConnect += strPath;
strConnect += "'; openopt = 'read'";
// create the provider address
CNetFileAddress addr;
addr.SetConnectString(strConnect);
// create the provider's connector
CNetBinFileConnector* pConnector = new CNetBinFileConnector;
// connect!
pConnector->Connect(addr);
// create the file header
strPath.Delete(strPath.Find(dlg.GetFileName()), dlg.GetFileName().GetLength());
CNetFileHdr hdr;
hdr.SetDirectory(false);
hdr.SetProviderPath(strPath);
hdr.SetProviderName(dlg.GetFileName());
hdr.SetFileSize(pConnector->GetSize());
// create the sending thread
CSenderThread* pThread = new CSenderThread(hdr);
// set the provider's connector
pThread->SetProviderConnector(pConnector);
// set the consumer's address
pThread->SetConsumerAddress(GetRemoteFileAcceptorAddr());
// subscribe for notifications
pThread->Subscribe(this);
// add the thread to the thread storage
g_getThreadStorage().Add(pThread);
// run it!
pThread->Start();
// save the thread's id these buttons control
CWnd* pSend = GetDlgItem(IDST_SEND);
pSend->SetWindowContextHelpId(pThread->GetThreadId());
// disable the button
GetDlgItem(IDBT_SEND_FILE)->EnableWindow(FALSE);
// enable cancel button
GetDlgItem(IDBT_SEND_CANCEL)->EnableWindow(TRUE);
GetDlgItem(IDST_PERCENTAGE_SENT)->ShowWindow(SW_SHOW);
GetDlgItem(IDST_PERCENTAGE_SENT)->UpdateWindow();
/*
if (!m_file.Open(strPath, CFile::modeRead)) {
MessageBox("Cannot open the file", "Error", MB_OK|MB_ICONERROR);
return false;
}
// set the file length;
m_nFLen = m_file.GetLength();
// create the message
CNetList list;
list.SetDataRequestCallback(this, DataRequest);
// set the max number of packets
DWORD nLen = (m_nFLen > MAX_NET_PACKET) ? m_nFLen : MAX_NET_PACKET;
short nTail = (nLen % MAX_NET_PACKET > 0) ? 1 : 0;
list.SetMaxElem(nLen / MAX_NET_PACKET + nTail);
// send it!
m_NetStream << list;
*/
return true;
}
/*
bool CSimpleChatDlg::DataRequest(void* pCaller, CNetList* pList)
{
CSimpleChatDlg* pThis = (CSimpleChatDlg*)pCaller;
DWORD nPos = pThis->m_file.GetPosition();
// end of the file
if (pThis->m_nFLen == nPos) {
pThis->m_file.Close();
return true;
}
// figure out how many bytes to read
DWORD nSz = (pThis->m_nFLen - nPos > MAX_NET_PACKET) ? MAX_NET_PACKET : pThis->m_nFLen - nPos;
char szBuff[MAX_NET_PACKET];
DWORD nRead = 0;
// if read less, that's a problem
if ((nRead = pThis->m_file.Read(szBuff, nSz)) != nSz) {
pThis->m_file.Close();
return false;
}
CNetPacket* pMsg = new CNetPacket;
pMsg->SetData(szBuff, nSz, pList->GetElemN() + 1);
// send the message
pList->AddElem(pMsg);
if (nPos + nRead == pThis->m_nFLen)
pThis->m_file.Close();
return true;
}
*/
bool CSimpleChatDlg::SendLogin(netStatus ns)
{
if (!m_NetStream.IsOpen()) {
WriteSystem("The connection is broken.");
return false;
}
UpdateData();
// create new message with the local user name and the text welcome message
CNetLogin login;
login.SetCode(ns);
login.SetName(m_strYou);
if (m_bUseMsg)
login.SetText(m_strWelMsg);
try {
// send the message
m_NetStream << login;
} catch (CNetException e) {
// if cannot send notify the user and do not clean up the edit box
WriteSystem("The message cannot be delivered.");
// the connection is broken, close the socket
DisconnectAll();
return false;
}
if (ns == nsLogin)
WriteSystem("You have joined the chat room.");
else
if (ns == nsNickChange)
WriteSystem("You have changed your nick name.");
// don't show the welcome message if it's empty
if (m_bUseMsg && !m_strWelMsg.IsEmpty()) {
WriteYourName();
// display this message on the local screen
WriteMsg(login.GetText());
}
// clean up the edit box
OnClear();
GetDlgItem(IDED_TEXT)->SetFocus();
return true;
}
bool CSimpleChatDlg::SendLogout()
{
if (!m_NetStream.IsOpen()) {
WriteSystem("The connection is broken.");
return false;
}
UpdateData();
// create the logout message
CNetStatus logout;
logout.SetCode(nsLogout);
if (m_bUseMsg)
logout.SetText(m_strByeMsg);
try {
// send the message
m_NetStream << logout;
} catch (CNetException e) {
// if cannot send notify the user and do not clean up the edit box
WriteSystem("The message cannot be delivered.");
// the connection is broken, close the socket
DisconnectAll();
return false;
}
WriteSystem("You have left the chat room.");
if (m_bUseMsg && !m_strByeMsg.IsEmpty()) {
WriteYourName();
// display this message on the local screen
WriteMsg(logout.GetText());
}
// clean up the edit box
OnClear();
GetDlgItem(IDED_TEXT)->SetFocus();
return true;
}
bool CSimpleChatDlg::SendLocalUserActivityStatus(CNetStatus& status)
{
if (!m_NetStream.IsOpen())
return false;
// send the local user activity status to the remote peer
try {
m_NetStream << status;
} catch (CNetException e) {
// the connection is broken, close the socket(s)
DisconnectAll();
return false;
}
return true;
}
void CSimpleChatDlg::Receive()
{
CNetMsg* pMsg = 0;
// read it
try {
m_NetStream >> pMsg;
// deal with the message based on its type
m_msgConverter.SetMsg(pMsg);
m_msgConverter.Process();
} catch (CNetException e) {
// if cannot extract notify the user
WriteSystem("The message was received but cannot be read.");
// the connection is broken, close the socket
DisconnectAll();
}
// clean up
delete pMsg;
}
void CSimpleChatDlg::OnSend()
{
SendText();
}
void CSimpleChatDlg::OnSendFile()
{
SendFile();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -