?? secretchatdlg.cpp
字號:
//向對方提示我斷開連接
MessagePackage msg;
msg.head = HEAD_DISCONNECTION;
msg.ID = HEAD_DISCONNECTION_INFORM;
SendData(msg, 12);
Disconnection();
}
else //沒聯機時的處理
{
//連接之前必須要有一個私鑰并且要有一個被選中
if(!ValidatePrivateKey()) return;
if(Connect()) //建立連接
{ //連接成功后,就要判斷有沒好友公鑰
ValidatePublicKey();
}
}
}
void CSecretChatDlg::OnGetip() //獲得本機IP地址
{
/********************************************************/
//IP-1
char szHostName[128]; //本機網絡名
CString szIP; //本機IP地址
if( gethostname( szHostName, 128) == 0 )
{
struct hostent *pHost;
int i, j;
pHost = gethostbyname(szHostName);
for(i = 0;pHost != NULL && pHost->h_addr_list[i] != NULL;i++)
{
for(j = 0;j < pHost->h_length;j++ )
{
CString addr;
if(j > 0 )
szIP += ".";
addr.Format("%u", (unsigned int)((unsigned char*)
pHost->h_addr_list[i])[j]);
szIP += addr;
}
}
}
CString IP_1 = szIP;
//IP-2
char mane1[30];
ZeroMemory(mane1,sizeof(char)*30);
gethostname(mane1,30);
struct hostent *myhost;
myhost = gethostbyname(mane1);
char* myip = inet_ntoa(*((struct in_addr*)myhost->h_addr_list[0]));
CString IP_2 = myip;
//IP-3
WORD wVersionRequested;
WSADATA wsaData;
char name[255];
CString ip;PHOSTENT hostinfo;
wVersionRequested = MAKEWORD( 2, 0 );
if ( WSAStartup( wVersionRequested, &wsaData ) == 0 )
{
if( gethostname ( name, sizeof(name)) == 0)
{
if((hostinfo = gethostbyname(name)) != NULL)
{
ip = inet_ntoa (*(struct in_addr *)*hostinfo->h_addr_list);
}
}
WSACleanup( );
}
CString IP_3 = ip;
//選擇最短的IP地址
CString IP = IP_1;
if(IP.GetLength() > IP_2.GetLength())
IP = IP_2;
if(IP.GetLength() > IP_3.GetLength())
IP = IP_3;
/*********************************************************/
CEdit *pIP = (CEdit *)GetDlgItem(IDC_STATUSMESSAGES);
CString str = szHostName;
str = "主機名:" + str + " IP地址:" + IP;
pIP->SetWindowText(str);
// pIP->SetWindowText("請用\"密聊\"進行聯系,我的IP地址是:" + szIP);
pIP->SetFocus();
pIP->SetSel(0, -1);
}
void CSecretChatDlg::OnNote() //密聊記錄
{
CFileFind find;
CString fileName =
m_appName
+ "\\user\\"
+ GetUserName()
+ "-"
+ GetFriendName()
+ ".txt";
if(!find.FindFile(fileName))
{
MessageBox(
"沒有 " + fileName + " 記錄文件",
"密聊",
MB_ICONEXCLAMATION);
return;
}
::ShellExecute(
m_hWnd,
"open",
fileName,
"",
"",
SW_SHOW);
}
void CSecretChatDlg::OnSend() //發送消息
{
/*先關閉了Socket在發送數據會怎樣?
當要很多時間長可以到發送或接收消息的線程調用了SendData函數時,
而Socket確被這時被關閉了,那么這樣就產生了致命性的錯誤了,
不過如果強行的關閉這兩個線程還可以的
CloseSocket();
MessagePackage msg;
SendData(msg,12);
*/
//必須要設置私鑰和公鑰,沒有連線的時候才
// if(!ValidatePrivateKey()) return;
// if(!ValidatePublicKey()) return;
//未連接不能發送消息
if(!m_online)
{
MessageBeep(MB_OK);
m_statusMessages.SetWindowText("沒有聯機");
m_messageEdit.SetFocus();
return;
}
//消息沒發送出去,就不能發第二條消息
if(m_send != 0)
{
MessageBeep(MB_OK);
m_statusMessages.SetWindowText("正在發送消息,請稍等...");
return;
}
else
{
m_statusMessages.SetWindowText("消息發送中");
}
//發送的消息不能太長
m_messageEdit.GetWindowText(m_message);
int messageLength/*發送消息的長度*/ = m_message.GetLength();
if(messageLength == 0)
{
MessageBeep(MB_OK);
m_statusMessages.SetWindowText("空的消息");
m_messageEdit.SetFocus();
return;
}
/* else if(messageLength > 1024 && messageLength <= DATA_LENGTH)
{
if(MessageBox(
"較長的消息需要幾分鐘時間,\r\n是否繼續發送?",
"密聊",
MB_YESNO | MB_ICONQUESTION) == IDNO)
{
return;
}
}*/
else if(messageLength > DATA_LENGTH / 4)//當處理的長度MessagePackage時會出現異常錯誤
{
MessageBox(
"發送的消息不希望超過 1K",
"密聊",
MB_ICONEXCLAMATION);
return;
}
//公鑰和私鑰如果相同就提示不安全
CString strUser = GetUserName();
strUser.MakeLower();
CString strFriend = GetFriendName();
strFriend.MakeLower();
if(strUser == strFriend)
{
if(MessageBox(
"相同的私鑰和公鑰將失去通話安全,\r\n是否繼續通話?",
"密聊",
MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2) == IDNO)
{
m_setupDlg.m_index = 0;
m_setupDlg.DoModal();
return;
}
}
m_send++; //正在發送著一條消息
unsigned long nThreadID;
::CreateThread(
NULL,
0,
send_thread,
this,
0,
&nThreadID);
}
void CSecretChatDlg::Receive(MessagePackage &package) //接收到正文消息
{
// int arithmometer(0);
// while(!(ValidatePrivateKey() && ValidatePublicKey()))
// {//必須要把私鑰和公鑰安裝好了,才能開始接收消息
// if(arithmometer++ > 5)
// break;
// };
if(m_receive >= MESSAGE_COUNT - 1)
{
//告訴對方有消息沒收到
package.head = HEAD_REVERT_TEXT;
package.ID = 1;//1表示不能同時收不到這么多消息
SendData(package, 12);
MessageBox(
"正在同時接收的消息超過規定的限度",
"拒絕接收",
MB_ICONINFORMATION);
return;
}
//m_cs.LockCount可以表示接收到的消息條數?不時m_receive才是
m_receive_message_package[/*收到的消息數安全加1*/
::InterlockedIncrement(&m_receive)] = package; //為了把消息包傳給線程
unsigned long nThreadID;
::CreateThread(
NULL,
0,
receive_thread,
this,
0,
&nThreadID);
}
void CSecretChatDlg::ReceiveRevert(MessagePackage &package) //接收到對方的回復
{
if(package.ID == 1)
{
MessageBox(
"你同時發送的消息超過規定的限度,對方有消息沒收到",
"拒絕接收",
MB_ICONINFORMATION);
return;
}
DWORD d1[4];
__DWORD128 b1;
::MoveMemory(
d1, //目標
package.data, //源內容
16);
b1.Load(d1);
if(m_send_message_package_ID_find(b1))//在這里它是發送時設定的
{
//n表示有多少位是不空閑的它小于32,因為32時就不能添加了
int n = get_bit_count(m_send_message_package_ID_index, 1);
CString str;
if(n == 0)
{
str = "成功發送消息 (對方確認收到所有消息)";
}
else
{
str.Format(
"成功發送消息 (有 %i 條消息未確認對方收到)",
n);
//這里不行可能由于會并行訪問m_send_message_package_ID_index所引起的
//這是由于時間的等待關系,因為Debug版速度慢所以看不出來,在Release版中這里是并行處理的
}str = "成功發送消息";
m_statusMessages.SetWindowText(str);
if(AfxGetApp()->GetProfileInt("General", "ArriveSound", 1))
{
::MessageBeep(MB_ICONASTERISK);
}
}
}
void CSecretChatDlg::InitializationWindow() //設定初始化窗口
{
// 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, strJiaMi, strHelp;
strAboutMenu.LoadString(IDS_ABOUTBOX);
strJiaMi.LoadString(IDS_JIAMI);
strHelp.LoadString(IDS_HELP);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR); //分隔菜單
pSysMenu->AppendMenu(MF_STRING, IDS_JIAMI, strJiaMi);
pSysMenu->AppendMenu(MF_STRING, IDS_HELP, strHelp);
pSysMenu->AppendMenu(MF_SEPARATOR); //分隔菜單
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
pSysMenu->DeleteMenu(SC_MAXIMIZE,MF_BYCOMMAND);
pSysMenu->DeleteMenu(SC_SIZE,MF_BYCOMMAND); //修改系統菜單
//pSysMenu->DeleteMenu(61728/*恢復菜單ID*/,MF_BYCOMMAND);
}
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
//設置開始的窗口標題(連接還是未連接)
SetWindowText("密聊 (未連接)");
//播撒隨機數的種子,rand()才能生成隨機數
srand((unsigned int)::GetTickCount());
//設置按鈕樣式
CString str = "連接";
m_connect.SubclassDlgItem(IDC_CONNECT_DISCONNECTION, this);
m_connect.SetIcon(IDI_CONNECT);
m_connect.SetTooltipText(&str);
m_connect.SetBtnCursor(IDC_HAND);
m_connect.SetActiveFgColor(RGB(255, 255, 255));
str = "通訊雙方的密鑰設置和密鑰管理";
m_publickeymanager.SubclassDlgItem(IDC_SECRETKEY, this);
m_publickeymanager.SetIcon(IDI_IDIOGRAPH);
m_publickeymanager.SetTooltipText(&str);
m_publickeymanager.SetBtnCursor(IDC_HAND);
m_publickeymanager.SetActiveFgColor(RGB(255, 255, 255));
str = "獲得本機的IP地址";
m_getIP.SubclassDlgItem(IDC_GETIP, this);
m_getIP.SetIcon(IDI_IP);
m_getIP.SetTooltipText(&str);
m_getIP.SetBtnCursor(IDC_HAND);
m_getIP.SetActiveFgColor(RGB(255, 255, 255));
str = "密聊記錄";
m_note.SubclassDlgItem(IDC_NOTE, this);
m_note.SetIcon(IDI_NOTE);
m_note.SetTooltipText(&str);
m_note.SetBtnCursor(IDC_HAND);
m_note.SetActiveFgColor(RGB(255, 255, 255));
str = "退出";
m_exit.SubclassDlgItem(IDCANCEL, this); //啟動星星管理器
m_exit.SetIcon(IDI_EXIT);
m_exit.SetTooltipText(&str);
m_exit.SetBtnCursor(IDC_HAND);
m_exit.SetActiveFgColor(RGB(255, 255, 255));
str = "發送消息(Ctrl + Enter)";
m_send_button.SubclassDlgItem(IDC_SEND, this); //啟動密聊
m_send_button.SetTooltipText(&str);
m_send_button.SetBtnCursor(IDC_HAND);
m_send_button.SetActiveFgColor(RGB(255, 255, 255));
str = "設置";
m_setup.SubclassDlgItem(IDC_SETUP, this); //啟動密聊
m_setup.SetIcon(IDI_SETUP);
m_setup.SetTooltipText(&str);
m_setup.SetBtnCursor(IDC_HAND);
m_setup.SetActiveFgColor(RGB(255, 255, 255));
str = "發送文件";
m_sendfile.SubclassDlgItem(IDC_SENDFILE, this); //啟動密聊
m_sendfile.SetIcon(IDI_SENDFILE);
m_sendfile.SetTooltipText(&str);
m_sendfile.SetBtnCursor(IDC_HAND);
m_sendfile.SetActiveFgColor(RGB(255, 255, 255));
//獲得應用程序目錄名
::GetCurrentDirectory(
MAX_PATH,
m_appName.GetBuffer(MAX_PATH));//獲取應用程序目錄
m_appName.ReleaseBuffer();
//另一種獲取應用程序目錄名的有效方法
CString strApp = __argv[0];
int iApp = strApp.ReverseFind('\\');
CSecretKeyEdit temp;
char cApp[MAX_PATH];
temp.CStringToChar(cApp, strApp, iApp);
cApp[iApp] = 0;
m_appName = cApp;
//安裝應該程序別名和注冊現在的版本
set_app_alias("SecChat");
AfxGetApp()->WriteProfileString(
"Application", "DirectoryName", m_appName);
AfxGetApp()->WriteProfileInt(
"Application", "Version", APPLICATION_VERSION);
//新建friend和user文件夾
WIN32_FIND_DATA wfd;
HANDLE hSearch;
hSearch = ::FindFirstFile(m_appName + "\\" + "friend", &wfd);
if(hSearch == INVALID_HANDLE_VALUE/*不存在*/)
{
::CreateDirectory(m_appName + "\\" + "friend", NULL);
}
hSearch = ::FindFirstFile(m_appName + "\\" + "user", &wfd);
if(hSearch == INVALID_HANDLE_VALUE/*不存在*/)
{
::CreateDirectory(m_appName + "\\" + "user", NULL);
}
//設置工具提示
m_userNameStatic.SetLink(TRUE,FALSE);
m_userNameStatic.SetTextColor(RGB(0,128,192));
m_userNameStatic.SetLinkCursor(AfxGetApp()->LoadCursor( IDC_HAND));
m_friendNameStatic.SetLink(TRUE,FALSE);
m_friendNameStatic.SetTextColor(RGB(255,128,128));
m_friendNameStatic.SetLinkCursor(AfxGetApp()->LoadCursor( IDC_HAND));
EnableToolTips(TRUE);
m_toolTip.Create(this);
m_toolTip.Activate(TRUE);
m_toolTip.AddTool( &m_userNameStatic, "查看用戶的私鑰信息");
m_toolTip.AddTool( &m_friendNameStatic, "查看好友的公鑰信息");
//當啟動時運行就要隱藏窗口
if(AfxGetApp()->GetProfileInt("General", "Startup", 0))
{
GetWindowRect(m_rect); //默認為現在的位置
//保證不閃爍...絕對有效
SetWindowPos(&CWnd::wndNoTopMost, 0, 0,0, 0,SWP_HIDEWINDOW);
ModifyStyleEx(WS_EX_APPWINDOW, WS_EX_TOOLWINDOW);
/*上面并沒有隱藏窗口所以再用MoveWindow函數是就會顯示窗口了,
應該在PostMessage中先用ShowWindow(SW_HIDE),再用MoveWindow(m_rect)*/
PostMessage( WM_RUNHIDE,0,0);
}
//顯示幫助信息
CString strHelp;
strHelp.LoadString(IDS_USEHELP);
m_messageNoteEdit.SetWindowText(strHelp);
//恢復窗口位置
CString str1;
str1 = AfxGetApp()->GetProfileString("Window", "Position", "");
CRect saveRect/*保存窗口大小*/, nowRect/*現在窗口的大小*/;
_stscanf(str1,
"%i,%i,%i,%i",
&saveRect.top,
&saveRect.bottom,
&saveRect.left,
&saveRect.right);
//必須判斷是合格的矩形尺寸,否則不改變窗口的大小
GetWindowRect(&nowRect);
if( (saveRect.bottom - saveRect.top ==
nowRect.bottom - nowRect.top) &&
(saveRect.right - saveRect.left ==
nowRect.right - nowRect.left) )
{
//恢復窗口位置
MoveWindow(&saveRect);
}
MyUpdateData(); //根據注冊表數據進行設置
}
void CSecretChatDlg::PlayWaveSound(DWORD wave/*資源中的聲音ID*/) //播放資源中的聲音文件
{
/*******播放資源中的.wav文件*******/
HRSRC hRsrc = ::FindResource(
AfxGetResourceHandle(),
MAKEINTRESOURCE(wave/*資源ID*/),
"WAVE"/*要和資源中的文件夾名相同*/);
HGLOBAL hglb = ::LoadResource(
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -