⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 simplechatdlg.cpp

📁 这是一个简单的使用WinAPI基于WinSock的ICP/IP程序
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// here is two ways of handling the events being a subscriber
// since this thread is a CWinThread it has its won queue
// so I can just post this event into it
void CSimpleChatDlg::HandleNotification(CNotifEvent* pEvent)
{
  HWND hwnd = GetSafeHwnd();
  if (!hwnd) 
    return;

  ::PostMessage(hwnd, pEvent->event_id(), (WPARAM)pEvent, 0);
}

// here is an example of using subscriber's own queue.
// To turn this piece of code on set m_bHandleNotify = false in the constructor.
// The events are stored in subscribers CQueue and retrieved
// by polling the queue. For this thread wainting on an event
// would not work since it has to wait for Windows events
// on its own Windows queue. Therefore if I was to wait for
// an event from subscriber's queue, the UI would not update at all (hang)
// So better off just using the Microsoft's supplied queue
// and post messages there via PostMessage(...) aimed at a particualar
// window in a thread or PostThreadMessage(...) aimed at a thread in general
void CSimpleChatDlg::OnTimer(UINT nIDEvent) 
{
  CDialog::OnTimer(nIDEvent);

// if wrong event - return 
  if (m_nCheckForData != nIDEvent)
	return;

  while (IsThereEvent()) {
    unsigned int sz = GetQueueSize();
	char buff[20];
	sprintf(buff, "%d", sz);
	SetDlgItemText(IDC_QUEUE_SIZE, buff);
	CNotifEvent* pEvent = GetEvent();
	SendMessage(pEvent->event_id(), (WPARAM)pEvent);
	delete pEvent;
  }

// if no connection or no data has arrived - return 
  if (!m_NetStream.IsOpen())
	return;

  static netStatus status = nsUserDoesNtng;
  static int nTimes = 0;

  if (status != m_ctrlText.m_status.GetCode() || ++nTimes == 50) {
	nTimes = 0;
    SendLocalUserActivityStatus(m_ctrlText.m_status);
    status = (netStatus)m_ctrlText.m_status.GetCode();
  }

  if (!m_NetStream.GetConnection()->CanRead())
	return;

// data is here!
  Receive();
}

void CSimpleChatDlg::OnDisconnect() 
{
// send the logout message if not listening
  if (m_acceptorThread.IsStoped())
    SendLogout();
  DisconnectAll();
}

void CSimpleChatDlg::OnDestroy() 
{
  UnhookWindowsHookEx(g_hook);

  CDialog::OnDestroy();

// send the logout message
  SendLogout();
// stop all threads
  DisconnectAll();

// kill the polling the connection for data and for the events
  KillTimer(m_nCheckForData);

// get rid of systray icon
  SetupTrayIcon(false);
// get rid of the task bar
  ShowWindow(SW_HIDE);

}


void CSimpleChatDlg::OnRestore()
{
//  ShowWindow(SW_RESTORE);
  SetupTrayIcon(false);
}

void CSimpleChatDlg::OnExit()
{
  SendMessage(WM_CLOSE, 0, 0);
}

/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////

void CSimpleChatDlg::WriteYourName()
{
  UpdateData();

  CString strNick = "You";
  if (!m_strYou.IsEmpty())
	strNick += " (" + m_strYou + ")";
  strNick += " say";

  m_rtfStream << rtf::italic << rtf::bold << rtf::blue << strNick << rtf::nobold << rtf::noitalic;
  ScrollToEnd();
}

void CSimpleChatDlg::WritePeerName()
{
  CString strNick = "Peer";
  if (!m_strPeer.IsEmpty())
    strNick += " (" + m_strPeer + ")";
  strNick += " says";

  m_rtfStream << rtf::italic << rtf::bold << rtf::blue << strNick << rtf::nobold << rtf::noitalic;
  ScrollToEnd();
}

void CSimpleChatDlg::WriteMsg(const char* strText)
{
  m_rtfStream << " : " << rtf::bold << rtf::black << strText << rtf::nobold << std::endl;
  ScrollToEnd();
}

void CSimpleChatDlg::WriteSystem(const char* strText)
{
  m_rtfStream << rtf::bold << rtf::red << strText << std::endl;
  ScrollToEnd();
}

void CSimpleChatDlg::ScrollToEnd()
{
  int maxy = m_reChat.GetLineCount();
  int miny = m_reChat.GetFirstVisibleLine() + GetVisibleHeight();
  if (maxy > miny)
    m_reChat.LineScroll(maxy - miny);
}

void CSimpleChatDlg::OnClearChat() 
{
  int maxy = m_reChat.GetLineCount();
  int nPos = m_reChat.LineIndex(maxy-1);
  int nLenght	 = m_reChat.LineLength(maxy);    
  m_reChat.SetSel(0, nPos + nLenght);
  m_reChat.ReplaceSel("");
}

ushort CSimpleChatDlg::GetVisibleHeight()
{
  return 12;
}

void CSimpleChatDlg::OnClear() 
{
  m_strText.Empty();
  UpdateData(FALSE);
}

void CSimpleChatDlg::DisableControls()
{
  GetDlgItem(IDC_IPADDRESS)->EnableWindow(FALSE);
  GetDlgItem(IDED_PORT)->EnableWindow(FALSE);
  GetDlgItem(IDRB_CONNECT)->EnableWindow(FALSE);
  GetDlgItem(IDRB_LISTEN)->EnableWindow(FALSE);
  GetDlgItem(IDBT_GO)->EnableWindow(FALSE);

  GetDlgItem(IDBT_SEND)->EnableWindow(TRUE);
  GetDlgItem(IDBT_SEND_FILE)->EnableWindow(TRUE);
  GetDlgItem(IDBT_DISCONNECT)->EnableWindow(TRUE);
}

void CSimpleChatDlg::EnableControls()
{
  GetDlgItem(IDC_IPADDRESS)->EnableWindow(TRUE);
  GetDlgItem(IDED_PORT)->EnableWindow(TRUE);
  GetDlgItem(IDRB_CONNECT)->EnableWindow(TRUE);
  GetDlgItem(IDRB_LISTEN)->EnableWindow(TRUE);
  GetDlgItem(IDBT_GO)->EnableWindow(TRUE);

  GetDlgItem(IDBT_SEND)->EnableWindow(FALSE);
  GetDlgItem(IDBT_SEND_FILE)->EnableWindow(FALSE);
  GetDlgItem(IDBT_SEND_CANCEL)->EnableWindow(FALSE);
  GetDlgItem(IDBT_RECEIVE_CANCEL)->EnableWindow(FALSE);
  GetDlgItem(IDST_PERCENTAGE_RECEIVED)->ShowWindow(SW_HIDE);
  GetDlgItem(IDBT_DISCONNECT)->EnableWindow(FALSE);
}

void CSimpleChatDlg::OnUseThis() 
{
  UpdateData();

  if (m_bUseMsg) {
	GetDlgItem(IDCB_NICK_NAME)->EnableWindow(TRUE);
    GetDlgItem(IDCB_WELCOME_MESSAGE)->EnableWindow(TRUE);
	GetDlgItem(IDCB_GOODBYE_MESSAGE)->EnableWindow(TRUE);
  } else {
	GetDlgItem(IDCB_NICK_NAME)->EnableWindow(FALSE);
    GetDlgItem(IDCB_WELCOME_MESSAGE)->EnableWindow(FALSE);
	GetDlgItem(IDCB_GOODBYE_MESSAGE)->EnableWindow(FALSE);
  } 
}

void CSimpleChatDlg::OnKillfocusNickName() 
{
  CString strOldYou = m_strYou;
  UpdateData();
// if nick name has not changed return
  if (m_strYou == strOldYou) return;
// send a message, informing remote peer that the user has changed its nick name
  SendLogin(nsNickChange);
}

/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// CSimpleChatDlg message handlers

BOOL CSimpleChatDlg::OnInitDialog()
{

   g_hook = SetWindowsHookEx(
		WH_CALLWNDPROC,			// hook type
		CallWndProc,			// hook procedure
		NULL,					// handle to application instance
		AfxGetThread()->m_nThreadID						// thread identifier
	);

   g_pDlg = this;

  m_reChat.SubclassDlgItem(IDRE_MESSAGES, this);
  CDialog::OnInitDialog();

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);
	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL) {
	  CString strAboutMenu;
	  strAboutMenu.LoadString(IDS_ABOUTBOX);
	  if (!strAboutMenu.IsEmpty()) {
	    pSysMenu->AppendMenu(MF_SEPARATOR);
		pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
	  }
	}
	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

// subclass the button
	m_ctrlText.SubclassWindow(GetDlgItem(IDED_TEXT)->GetSafeHwnd());
// attach the stream
    m_rtfStream.Attach(m_reChat.GetSafeHwnd());
	m_msgConverter.Attach(this);

// find out the local address
	CNetIPAddress address;
	address.SetConnectString(CNetIPAddress::MakeLocalHostAddr(DEFAULT_PORT_N).c_str());
	m_ctrlAddress.SetAddress(g_addr_stu(address.GetHostName()));
	m_strPort = DEFAULT_PORT_N;
	UpdateData(FALSE);

	CButton*	pbtnListen  = (CButton*)GetDlgItem(IDRB_LISTEN);
	CComboBox*  pWBox		= (CComboBox*)GetDlgItem(IDCB_WELCOME_MESSAGE);
	CComboBox*  pGBox		= (CComboBox*)GetDlgItem(IDCB_GOODBYE_MESSAGE);
    CComboBox*  pNBox		= (CComboBox*)GetDlgItem(IDCB_NICK_NAME);

	pbtnListen->SetCheck(1);
	pWBox->SetCurSel(0);
	pGBox->SetCurSel(0);
	pNBox->SetCurSel(0);

	EnableControls();

	OnUseThis();

	m_time = CTime::GetCurrentTime();

// start checking the connection for data
   SetTimer(m_nCheckForData, 100, 0);

   CRect rtParent;
   CRect rt;
   GetWindowRect(rtParent);

   GetDlgItem(IDST_PIN_POINT)->GetWindowRect(rt);
   rt.OffsetRect(rtParent.TopLeft());

   m_imgSmile.Load(IDB_ABOUT_OLD);
   m_imgSmile.SetParent(GetSafeHwnd());
   m_imgSmile.Move(rt.TopLeft());

   m_imgBack.Load(IDB_BACK);
   m_imgBack.SetParent(GetSafeHwnd());
   m_imgBack.Visible(false);

// init the tray icon
//	m_trayIcon.SetData(UWM_ON_NOTIFY, this, IDI_TRAY_ON, IDM_TRAY, lpszTip);

	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CSimpleChatDlg::SetupTrayIcon(bool bMin)
{
  m_bMinimized = bMin;
  if (m_bMinimized && m_pTrayIcon == 0) {
// create the tray
	  m_pTrayIcon = new CSystemTray;
	  m_pTrayIcon->Create(0, m_nmsgTray, lpszTip, AfxGetApp()->LoadIcon(IDI_ABOUT), IDM_TRAY);
// hide this window
	  ShowWindow(SW_HIDE);
	} 
	else {
// get rid of the tray
	  delete m_pTrayIcon;
	  m_pTrayIcon = 0;
// show this window
	  ShowWindow(SW_SHOW);
	}
}

void CSimpleChatDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
  if ((nID & 0xFFF0) == IDM_ABOUTBOX) {
	CAboutDlg dlgAbout;
	dlgAbout.DoModal();
  } else
	CDialog::OnSysCommand(nID, lParam);
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CSimpleChatDlg::OnPaint() 
{
	CPaintDC dc(this); // device context for painting

	if (IsIconic())
	{
		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		CRect rect;
		GetClientRect(&rect);
		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
	  CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CSimpleChatDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////



BOOL CSimpleChatDlg::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo) 
{
  if (nID == IDM_ABOUTBOX) {
	CAboutDlg dlgAbout;
	dlgAbout.DoModal();
	return TRUE;
  } else
	return CDialog::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}

CNetAddress* CSimpleChatDlg::GetRemoteFileAcceptorAddr()
{
  CNetIPAddress* pAddr = new CNetIPAddress;
  pAddr->SetConnectString(m_strRemoteAddrFileAccept.c_str());
  return pAddr;
}

void CSimpleChatDlg::OnSendCancel() 
{
// get the thread's id these buttons control
  CWnd* pSend = GetDlgItem(IDST_SEND);
  unsigned long nThreadId = pSend->GetWindowContextHelpId();

// find the right thread
  CThreadStorage& storage = g_getThreadStorage();
  while (storage.Size() > 0) {
	CNetThread* pThread = storage.GetAt(storage.Size() - 1);
// if this is the right thread, then abort transfer
// and wait for its self termination and self unregistration
	if (pThread)
	  if (pThread->GetThreadId() == nThreadId) {
		pThread->Stop();
		break;
	  }
  }
}

void CSimpleChatDlg::OnReceiveCancel() 
{
// restore the thread's id these buttons control
  CWnd* pReceive = GetDlgItem(IDST_RECEIVE);
  unsigned long nThreadId = pReceive->GetWindowContextHelpId();

// find the right thread
  CThreadStorage& storage = g_getThreadStorage();
  while (storage.Size() > 0) {
	CNetThread* pThread = storage.GetAt(storage.Size() - 1);
// if this is the right thread, then abort transfer
// and wait for its self termination and self unregistration
	if (pThread)
	  if (pThread->GetThreadId() == nThreadId) {
		pThread->Stop();
		break;
	  }
  }
}

LRESULT CALLBACK CallWndProc(
  int nCode,      // hook code
  WPARAM wParam,  // current-process flag
  LPARAM lParam   // message data
)
{
  if (nCode != HC_ACTION)
    return CallNextHookEx(g_hook, nCode, wParam, lParam);

  HWND hDlg = g_pDlg->GetSafeHwnd();
  HWND hActive = ::GetActiveWindow();

  if (hDlg != hActive) {
    g_pDlg->m_ctrlText.m_status.SetCode(nsUserDoesNtng);
    g_pDlg->m_ctrlText.m_status.SetText("The remote peer is away");
  } else {
	  if (g_pDlg->m_ctrlText.m_status.GetCode() == nsUserDoesNtng) {
	    g_pDlg->m_ctrlText.m_status.SetCode(nsUserIsHere);
	    g_pDlg->m_ctrlText.m_status.SetText("The remote peer is reading messages");
	  }
  }

  return CallNextHookEx(g_hook, nCode, wParam, lParam);
}

void CSimpleChatDlg::OnConnect() 
{
  SetDlgItemText(IDED_ADDRESS, "Peer's IP address:");
}

void CSimpleChatDlg::OnListen() 
{
  SetDlgItemText(IDED_ADDRESS, "Your IP address:");	
}


void CSimpleChatDlg::OnShowBk() 
{
  m_imgBack.Visible(!m_imgBack.IsVisible());	
  Invalidate();
}

BOOL CSimpleChatDlg::OnEraseBkgnd(CDC* pDC) 
{
  CRect rect;
  GetClientRect(&rect);

  CMDC mdc(pDC, rect);
  mdc.FillSolidRect(rect, ::GetSysColor(COLOR_3DFACE));
  m_imgBack.DrawMaskedBlended(&mdc, RGB(255, 255, 255), 40);
  m_imgSmile.DrawMasked(&mdc, RGB(255, 0, 0));

  return TRUE;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -