?? myqqdlg.cpp
字號:
// MyQQDlg.cpp : implementation file
//
#include "stdafx.h"
#include "MyQQ.h"
#include "MyQQDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMyQQDlg dialog
CMyQQDlg::CMyQQDlg(CWnd* pParent /*=NULL*/)
: CDialog(CMyQQDlg::IDD, pParent), m_constPort(3000) // 初始化端口
{
//{{AFX_DATA_INIT(CMyQQDlg)
m_nCastType = -1;
m_strHistory = _T("");
m_strMessage = _T("");
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CMyQQDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CMyQQDlg)
DDX_Control(pDX, IDC_IPADDRESS, m_remoteAddr);
DDX_Radio(pDX, IDC_RADIO_Broadcast, m_nCastType);
DDX_Text(pDX, IDC_EDIT_History, m_strHistory);
DDX_Text(pDX, IDC_EDIT_Message, m_strMessage);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CMyQQDlg, CDialog)
//{{AFX_MSG_MAP(CMyQQDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON_Send, OnBUTTONSend)
ON_BN_CLICKED(IDC_RADIO_Broadcast, OnRADIOBroadcast)
ON_BN_CLICKED(IDC_RADIO_Unicast, OnRADIOUnicast)
ON_WM_TIMER()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMyQQDlg message handlers
BOOL CMyQQDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// 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
// TODO: Add extra initialization here
// 獲得本機的IP
char hostname[100];
gethostname(hostname, 100);
struct hostent* host = gethostbyname(hostname);
if (host == NULL)
m_strLocalIP = "0.0.0.0";
else
m_strLocalIP = inet_ntoa(*((in_addr*)host->h_addr));
// 初始化socket
if( m_socket.Create(m_constPort, SOCK_DGRAM, m_strLocalIP) == FALSE)
{
// 如果初始化失敗
AfxMessageBox("初始化socket失敗"); // 顯示提示對話框
OnCancel(); // 退出程序
}
// 設置m_socket屬性,允許廣播
BOOL bBroadcast = TRUE;
m_socket.SetSockOpt(SO_BROADCAST, &bBroadcast, sizeof(BOOL));
// 初始化單選按鈕,設置為廣播
m_nCastType = 0;
// 初始化目標主機的IP
m_remoteAddr.SetAddress(0);
// 由于初始化為廣播方式,所以將IP控件設為不可用
m_remoteAddr.EnableWindow(FALSE);
// 將輸入焦點設置到消息編輯框中
((CEdit*)GetDlgItem(IDC_EDIT_Message))->SetFocus();
// 設置定時器,每1000毫秒發生一次定時器事件
SetTimer(1, 1000, NULL);
// 刷新各個控件的外觀
UpdateData(FALSE);
return FALSE; // 返回FALSE表示焦點在某一個控件上
}
void CMyQQDlg::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 CMyQQDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
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 CMyQQDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CMyQQDlg::OnBUTTONSend()
{
UpdateData(TRUE); // 將控件的狀態保存到各自相關聯的變量中
// 如果消息為空,立刻返回
if(m_strMessage.IsEmpty())
return;
// 發送消息
CString strIP;
if(m_nCastType == 0)
{
// 廣播
m_socket.SendTo(
LPCTSTR(m_strMessage), // 數據報內容
m_strMessage.GetLength(), // 數據報長度
m_constPort, // 對方的端口,本程序使用統一的端口
NULL); // NULL表示數據報廣播
}
else
{
// 單播
BYTE addr[4] = {0};
m_remoteAddr.GetAddress(addr[0], addr[1], addr[2], addr[3]);
strIP.Format("%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
m_socket.SendTo(
LPCTSTR(m_strMessage), // 數據報內容
m_strMessage.GetLength(), // 數據報長度
m_constPort, // 對方的端口,本程序使用統一的端口
strIP); // 對方的地址
}
// 將發出的消息加入到聊天歷史記錄中
CString strToAdd;
if(m_nCastType == 0)
{
// 廣播消息
strToAdd = "你的廣播:";
}
else
{
// 單播消息
strToAdd = "你對 ";
strToAdd += strIP;
strToAdd += " 說:";
}
strToAdd += m_strMessage;
strToAdd += "\r\n"; // 回車換行
m_strHistory = strToAdd + m_strHistory; // 加入到聊天記錄中
// 清空消息編輯框
m_strMessage.Empty();
// 更新控件的顯示
UpdateData(FALSE);
}
void CMyQQDlg::OnRADIOBroadcast()
{
// 廣播方式,不需要IP地址控件
m_remoteAddr.EnableWindow(FALSE);
}
void CMyQQDlg::OnRADIOUnicast()
{
// 單播方式,需要使用IP地址控件給出地址
m_remoteAddr.EnableWindow(TRUE);
}
void CMyQQDlg::OnTimer(UINT nIDEvent)
{
// 得到控件中的內容
UpdateData(TRUE);
char buffer[1024]; // 接收數據緩沖區
int recvSize = 0; // 接收字符計數器
CString fromIP; // 對方IP
UINT fromPort; // 對方端口
CString strToAdd; // 加入到聊天記錄中的字符串
// 測試是否有可以接收的數據
fd_set in_set = {0};
FD_SET(m_socket.m_hSocket, &in_set);
timeval t = {0,0};
if(select(1, &in_set, NULL, NULL, &t) != 0)
{
// 從socket上接收數據
recvSize = m_socket.ReceiveFrom(
buffer, // 用于接收數據的緩沖區地址
1024, // 緩沖區大小
fromIP, // 源地址
fromPort); // 源端口
// 接收到的不是空字符串,并且不是自己發出的廣播,則加入聊天記錄
if( recvSize > 0 && fromIP != m_strLocalIP )
{
// 加入字符結束標志
buffer[recvSize] = 0;
// 組成一行記錄
strToAdd = "收到來自 ";
strToAdd += fromIP;
strToAdd += " 的消息:";
strToAdd += buffer;
strToAdd += "\r\n";
// 加入到聊天記錄中
m_strHistory = strToAdd + m_strHistory;
// 更新控件
UpdateData(FALSE);
}
}
// 調用父類的方法
CDialog::OnTimer(nIDEvent);
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -