新建对话框程序。
对话框控件文件,有重叠EDIT控件,需要按F7编辑:
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/
//
// Generated from the TEXTINCLUDE 2 resource.
//
#ifndef APSTUDIO_INVOKED
#include "targetver.h"
#endif
#include "afxres.h"
#include "verrsrc.h"
/
#undef APSTUDIO_READONLY_SYMBOLS
/
// 中文(简体,中国) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
#ifdef APSTUDIO_INVOKED
/
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#ifndef APSTUDIO_INVOKED\r\n"
"#include ""targetver.h""\r\n"
"#endif\r\n"
"#include ""afxres.h""\r\n"
"#include ""verrsrc.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"#define _AFX_NO_SPLITTER_RESOURCES\r\n"
"#define _AFX_NO_OLE_RESOURCES\r\n"
"#define _AFX_NO_TRACKER_RESOURCES\r\n"
"#define _AFX_NO_PROPERTY_RESOURCES\r\n"
"\r\n"
"#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)\r\n"
"LANGUAGE 4, 2\r\n"
"#include ""res\\ChatCilent.rc2"" // 非 Microsoft Visual C++ 编辑的资源\r\n"
"#include ""l.CHS\\afxres.rc"" // 标准组件\r\n"
"#if !defined(_AFXDLL)\r\n"
"#include ""l.CHS\\afxribbon.rc"" // MFC 功能区和控制条资源\r\n"
"#endif\r\n"
"#endif\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDR_MAINFRAME ICON "res\\ChatCilent.ico"
/
//
// Dialog
//
IDD_CHATCILENT_DIALOG DIALOGEX 0, 0, 231, 203
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_APPWINDOW
CAPTION "登录"
FONT 11, "宋体", 400, 0, 0x86
BEGIN
LTEXT "注册",IDC_STATIC_REG,149,171,16,8,SS_NOTIFY | WS_TABSTOP
EDITTEXT IDC_REGUSERNAME,67,38,97,14,NOT WS_VISIBLE
EDITTEXT IDC_REGNICKNAME,67,66,97,14,NOT WS_VISIBLE
EDITTEXT IDC_FIRSTPASSWORD,67,94,97,14,ES_PASSWORD | ES_AUTOHSCROLL | NOT WS_VISIBLE
COMBOBOX IDC_USERNAME,67,94,97,14,CBS_DROPDOWN | WS_TABSTOP
EDITTEXT IDC_PASSWORD,67,122,97,14,ES_PASSWORD | ES_AUTOHSCROLL
PUSHBUTTON "登录",IDOK,85,168,50,14
CONTROL "记住密码",IDC_REMBERPASSWORD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,67,146,42,10
CONTROL "自动登录",IDC_AUTOLOGIN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,122,146,48,10
END
IDD_DIALOG1 DIALOGEX 0, 0, 175, 152
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "登录成功"
FONT 11, "宋体", 400, 0, 0x86
BEGIN
DEFPUSHBUTTON "确定",IDOK,63,120,50,14
CTEXT "",IDC_STATIC_DLG2,7,52,159,8
END
/
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,1
PRODUCTVERSION 1,0,0,1
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "080404B0"
BEGIN
VALUE "CompanyName", "TODO: <公司名>"
VALUE "FileDescription", "ChatCilent"
VALUE "FileVersion", "1.0.0.1"
VALUE "InternalName", "ChatCilent.exe"
VALUE "LegalCopyright", "TODO: (C) <公司名>。 保留所有权利。"
VALUE "OriginalFilename", "ChatCilent.exe"
VALUE "ProductName", "TODO: <产品名>"
VALUE "ProductVersion", "1.0.0.1"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x804, 1200
END
END
/
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_CHATCILENT_DIALOG, DIALOG
BEGIN
LEFTMARGIN, 7
TOPMARGIN, 7
BOTTOMMARGIN, 196
END
IDD_DIALOG1, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 168
TOPMARGIN, 7
BOTTOMMARGIN, 145
END
END
#endif // APSTUDIO_INVOKED
/
//
// String Table
//
STRINGTABLE
BEGIN
IDP_SOCKETS_INIT_FAILED "Windows 套接字初始化失败。"
END
#endif // 中文(简体,中国) resources
/
#ifndef APSTUDIO_INVOKED
/
//
// Generated from the TEXTINCLUDE 3 resource.
//
#define _AFX_NO_SPLITTER_RESOURCES
#define _AFX_NO_OLE_RESOURCES
#define _AFX_NO_TRACKER_RESOURCES
#define _AFX_NO_PROPERTY_RESOURCES
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
LANGUAGE 4, 2
#include "res\ChatCilent.rc2" // 非 Microsoft Visual C++ 编辑的资源
#include "l.CHS\afxres.rc" // 标准组件
#if !defined(_AFXDLL)
#include "l.CHS\afxribbon.rc" // MFC 功能区和控制条资源
#endif
#endif
/
#endif // not APSTUDIO_INVOKED
下面是主程序:
// ChatCilentDlg.cpp : 实现文件
//
/****************************************************************
注册登录程序,本地文件记录登录过的用户。数据库密码md5加密,本地文件密码加密可解密。
数据库部分请见ReadMe.txt
***************************************************************/
#include "stdafx.h"
#include "ChatCilent.h"
#include "ChatCilentDlg.h"
#include "afxdialogex.h"
#include "mysql.h"
#include "zfzh.h"
#include "md5.h"
#include "Logined.h"
#include <cctype>
#include <iostream>
#include <algorithm>
#include "EncodeDecode.h"
using namespace std;
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CChatCilentDlg 对话框
CChatCilentDlg::CChatCilentDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(CChatCilentDlg::IDD, pParent)
, m_username(_T(""))
, m_password(_T(""))
, m_nickname(_T(""))
, m_regusername(_T(""))
, m_remberpassword(FALSE)
, m_autologin(FALSE)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CChatCilentDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_CBString(pDX, IDC_USERNAME, m_username);
DDX_Text(pDX, IDC_PASSWORD, m_password);
DDX_Text(pDX, IDC_FIRSTPASSWORD, m_firstpassword);
DDX_Control(pDX, IDC_USERNAME, m_ctrl_username);
DDX_Control(pDX, IDC_PASSWORD, m_ctrl_password);
DDX_Control(pDX, IDC_FIRSTPASSWORD, m_ctrl_firstpassword);
DDX_Control(pDX, IDC_STATIC_REG, m_ctrl_regtxt);
DDX_Control(pDX, IDC_REGNICKNAME, m_ctrl_nickname);
DDX_Text(pDX, IDC_REGNICKNAME, m_nickname);
DDX_Control(pDX, IDOK, m_ctrl_okbn);
DDX_Control(pDX, IDC_REGUSERNAME, m_ctrl_regusername);
DDX_Text(pDX, IDC_REGUSERNAME, m_regusername);
DDX_Control(pDX, IDC_REMBERPASSWORD, m_ctrl_remberpassword);
DDX_Check(pDX, IDC_REMBERPASSWORD, m_remberpassword);
DDX_Control(pDX, IDC_AUTOLOGIN, m_ctrl_autologin);
DDX_Check(pDX, IDC_AUTOLOGIN, m_autologin);
}
BEGIN_MESSAGE_MAP(CChatCilentDlg, CDialogEx)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_STN_CLICKED(IDC_STATIC_REG, &CChatCilentDlg::OnStnClickedStaticReg)
ON_WM_CTLCOLOR()
ON_BN_CLICKED(IDOK, &CChatCilentDlg::OnBnClickedOk)
ON_CBN_SELCHANGE(IDC_USERNAME, &CChatCilentDlg::OnCbnSelchangeCombo1)
END_MESSAGE_MAP()
// CChatCilentDlg 消息处理程序
BOOL CChatCilentDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
m_ctrl_nickname.SetCueBanner(_T("请输入昵称"));
m_ctrl_username.SetCueBanner(_T("请输入用户名"));
m_ctrl_password.SetCueBanner(_T("请输入密码"));
m_ctrl_firstpassword.SetCueBanner(_T("请输入密码"));
m_ctrl_regusername.SetCueBanner(_T("请输入用户名"));
DisableIME();
CFileFind finder;
int filelen=0;
if (finder.FindFile(_T(ENCODEFILENAME)))
{
TRY
{
mFile.Open(_T(ENCODEFILENAME), CFile::modeRead | CFile::typeText);
}
CATCH (CFileException,e)
{
if (e->m_cause == CFileException::accessDenied)
{
MessageBox(_T("文件禁止读写"),_T("提示"),MB_ICONERROR|MB_OK);
}
}
END_CATCH
filelen = mFile.GetLength();
if (filelen > 0)
{
char *readstr = new char[filelen + 1];
if (readstr != NULL)
{
mFile.Read(readstr, filelen);
readstr[filelen] = '\0';
int rownum = 0;
for (int i = 0; i < filelen; i++)
{
if (readstr[i] == '\r')
rownum++;
}
pUP = new UPSTRUCT[rownum / 2 + MAXLOGINNUM + MAXREGNUM];
if (pUP != NULL)
{
std::string strRow(readstr);
int pos, posr1, posr2 = 0;
while ((pos = strRow.find("username:", posr2)) != strRow.npos)
{
posr1 = strRow.find("\r", pos + 9);
if (posr1 == strRow.npos) break;
pUP[UPlen].username = strRow.substr(pos + 9, posr1 - pos - 9);
posr2 = strRow.find(",", posr1 + 2);
if (posr2 == strRow.npos) break;
pUP[UPlen].rempassword = strRow.substr(posr1 + 2, posr2 - posr1 - 2);
posr1 = posr2 + 1;
posr2 = strRow.find(",", posr1);
if (posr2 == strRow.npos) break;
pUP[UPlen].autologin = strRow.substr(posr1, posr2 - posr1);
posr1 = posr2 + 1;
posr2 = strRow.find("\r", posr1);
if (posr2 == strRow.npos) break;
pUP[UPlen].password = strRow.substr(posr1, posr2 - posr1);
CString passtmp(pUP[UPlen].password.c_str());
CString code = CCode::Decode(passtmp, _T(ENCODEKEY));
std::string strdecode;//
strdecode = toNarrowString(code.GetString(), strdecode);
pUP[UPlen].password = strdecode;
posr2 = posr2 + 2;
UPlen++;
}
}
delete[] readstr;
}
}
mFile.Close();
}
if (filelen==0)
{
pUP = new UPSTRUCT[MAXLOGINNUM + MAXREGNUM];
}
if (UPlen > 0)
{
for (int i = 0; i < UPlen; i++)
{
std::wstring wstr;
wstr = DecodeUtf8(pUP[i].username);
CString str(wstr.c_str());
m_ctrl_username.AddString(str);
}
}
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。
void CChatCilentDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 使图标在工作区矩形中居中
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;
// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CChatCilentDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CChatCilentDlg::OnStnClickedStaticReg()
{
// TODO: 在此添加控件通知处理程序代码
isLogging = !isLogging;
showLogging();
}
void CChatCilentDlg::showLogging()
{
if (isLogging)
{
m_ctrl_nickname.ShowWindow(FALSE);
m_ctrl_username.ShowWindow(TRUE);
m_ctrl_regusername.ShowWindow(FALSE);
m_ctrl_autologin.ShowWindow(TRUE);
m_ctrl_remberpassword.ShowWindow(TRUE);
m_ctrl_regtxt.SetWindowTextW(_T("注册"));
m_ctrl_okbn.SetWindowTextW(_T("登录"));
m_ctrl_firstpassword.ShowWindow(FALSE);
m_ctrl_regusername.ShowWindow(FALSE);
SetWindowText(_T("登录"));
}
else
{
m_ctrl_nickname.ShowWindow(TRUE);
m_ctrl_username.ShowWindow(FALSE);
m_ctrl_regusername.ShowWindow(TRUE);
m_ctrl_autologin.ShowWindow(FALSE);
m_ctrl_remberpassword.ShowWindow(FALSE);
m_ctrl_okbn.SetWindowTextW(_T("注册"));
m_ctrl_regtxt.SetWindowTextW(_T("登录"));
m_ctrl_firstpassword.ShowWindow(TRUE);
m_password = _T("");
m_ctrl_password.SetWindowText(_T(""));
m_ctrl_regtxt.SetFocus();
SetWindowText(_T("注册"));
}
}
HBRUSH CChatCilentDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
// TODO: 在此更改 DC 的任何特性
if (pWnd->GetDlgCtrlID() == IDC_STATIC_REG)
{
pDC->SetTextColor(RGB(0, 0, 255));//用RGB宏改变颜色
}
// TODO: 如果默认的不是所需画笔,则返回另一个画笔
return hbr;
}
/* 如果数据库不正确,在MySQL Workbench 8.0里执行下面的SQL语句
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`userID` int unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(20) NOT NULL,
`nickname` varchar(20) NOT NULL,
`logtime` timestamp(4) NULL DEFAULT NULL,
`regtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`password` char(32) DEFAULT NULL,
PRIMARY KEY(`userID`,`username`),
UNIQUE KEY `userID_UNIQUE` (`userID`)
) ENGINE = InnoDB AUTO_INCREMENT = 19 DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci;
*/
void CChatCilentDlg::OnBnClickedOk()
{
// TODO: 在此添加控件通知处理程序代码
MYSQL m_sqlCon;
// isLogging = FALSE;
//showLogging();
//初始化数据库对象
mysql_init(&m_sqlCon);
UpdateData(true);
//localhost:服务器地址,可以直接填入IP;root:账号;
//123:密码;test:数据库名;3306:网络端口
if (!mysql_real_connect(&m_sqlCon, "localhost", "root",
"123456", "chatapp", 3306, NULL, 0))
{
MessageBox(_T("数据库连接失败!"), _T("提示"), MB_OK | MB_ICONERROR);
return;
}
mysql_query(&m_sqlCon, "set names 'utf8mb4'");
if (isLogging)
{
if (lognum == MAXLOGINNUM)
{
MessageBox(_T("登录次数超限"),_T("提示"),MB_ICONEXCLAMATION|MB_OK);
return;
}
std::string username;
std::string password;
m_username.Trim();
m_password.Trim();
if (m_username.GetLength() == 0)
{
MessageBox(_T("没有输入用户名"),_T("提示"),MB_OK|MB_ICONWARNING);
return;
}
if (m_password.GetLength() == 0)
{
MessageBox(_T("没有输入密码"), _T("提示"), MB_OK | MB_ICONWARNING);
return;
}
username = toNarrowString(m_username.GetString(), username);
//mysql通配符转义。
//std::string usernamestr(username.c_str());
char *tmpname = new char[MYSQLUSERNAMELEN + MYSQLUSERNAMELEN + 1];
int i, j = 0;
for (i = 0; i < username.length(); i++)
{
if (username[i] == '%' || username[i] == '_')
{
tmpname[j] = '\\'; j++;
}
tmpname[j] = username[i]; j++;
}
tmpname[j] = '\0';
password = toNarrowString(m_password.GetString(), password);
MD5 md5Password(password);
std::string passwordMD5 = md5Password.toString();
std::string buf("select userID,nickname from chatapp.user where username like '");
buf.append(tmpname); delete[] tmpname;
buf.append("' AND password like '");
buf.append(passwordMD5.c_str());
buf.append("';");
mysql_query(&m_sqlCon, buf.c_str());
MYSQL_RES* result = mysql_store_result(&m_sqlCon);
MYSQL_ROW row = mysql_fetch_row(result);
if (result&&result->row_count)
{
lognum++;
std::string buf1("UPDATE chatapp.user SET logtime = NOW() where userid=");//更新登陆时间
buf1.append(row[0]);
std::string tmp = row[1];
std::wstring tmp2 = DecodeUtf8(tmp);
mysql_free_result(result);
mysql_query(&m_sqlCon, buf1.c_str());
if (m_remberpassword) //记录登录信息
{
int i;
if (pUP != NULL)
{
for (i = 0; i < UPlen; i++)
{
if (pUP[i].username == username)
{
//pUP[i].password = password;
break;
}
}
if (i>0)
{
m_ctrl_username.ResetContent();
if (i == UPlen)
UPlen = UPlen + 1;
for (int j = i; j > 0; j--)
{
pUP[j].autologin = pUP[j - 1].autologin;
pUP[j].password = pUP[j - 1].password;
pUP[j].rempassword = pUP[j - 1].rempassword;
pUP[j].username = pUP[j - 1].username;
}
if (m_autologin)
pUP[0].autologin = "1";
else
pUP[0].autologin = "0";
pUP[0].password = password;
if (m_remberpassword)
pUP[0].rempassword = "1";
else
pUP[0].rempassword = "0";
pUP[0].username = username;
for (int j = 0; j < UPlen; j++)
{
CString str(pUP[j].username.c_str());
m_ctrl_username.AddString(str);
}
m_ctrl_username.SetCurSel(0);
}
else if (UPlen == 0)
{
UPlen = 1;
if (m_autologin)
pUP[0].autologin = "1";
else
pUP[0].autologin = "0";
pUP[0].password = password;
if (m_remberpassword)
pUP[0].rempassword = "1";
else
pUP[0].rempassword = "0";
pUP[0].username = username;
CString str(username.c_str());
m_ctrl_username.AddString(str);
}
std::string writetxt;
for (int i = 0; i < UPlen; i++)
{
writetxt.append("username:");
writetxt.append(pUP[i].username);
writetxt.append("\r\n");
writetxt.append(pUP[i].rempassword);
writetxt.append(",");
writetxt.append(pUP[i].autologin);
writetxt.append(",");
CString buf(pUP[i].password.c_str());
CString code = CCode::Encode(buf, _T(ENCODEKEY));
std::string strcode;//准备写入文件的加密的密码
strcode = toNarrowString(code.GetString(), strcode);
writetxt.append(strcode.c_str());
writetxt.append("\r\n");
}
int len = writetxt.length();
TRY
{
mFile.Open(_T(ENCODEFILENAME), CFile::modeCreate | CFile::modeNoTruncate | CFile::modeWrite | CFile::typeText);
}
CATCH(CFileException, e)
{
if (e->m_cause == CFileException::accessDenied)
{
MessageBox(_T("文件禁止读写"), _T("提示"), MB_ICONERROR | MB_OK);
}
}
END_CATCH
mFile.SeekToBegin();
mFile.Write(writetxt.c_str(), len);
mFile.SetLength(len);
mFile.Close();
}
}
Logined mdlg;
mdlg.SethelloText(tmp2);
mdlg.DoModal();
}
else
{
MessageBox(_T("没有注册或密码错误"), _T("提示"), MB_ICONEXCLAMATION | MB_OK);
}
//isLogging = FALSE;
//showLogging();
}
else //注册
{
/* if (OpenClipboard())
{
HGLOBAL clipbuffer;
char * buffer;
EmptyClipboard();
clipbuffer = GlobalAlloc(GMEM_DDESHARE, SQLSTR.length() + 1);//buf为string类型 他就是要放在剪贴板上的内容
buffer = (char*)GlobalLock(clipbuffer);
strcpy_s(buffer, SQLSTR.length() + 1, SQLSTR.c_str());
GlobalUnlock(clipbuffer);
SetClipboardData(CF_TEXT, clipbuffer);
CloseClipboard();
}
int r = mysql_query(&m_sqlCon, SQLSTR.c_str());*/
if (regnum == MAXREGNUM)
{
MessageBox(_T("注册次数超限"), _T("提示"), MB_ICONEXCLAMATION | MB_OK);
return;
}
m_password.Trim();
m_firstpassword.Trim();
if (m_password == m_firstpassword)
{
std::string username;
std::string nickname;
m_regusername.Trim();
username = toNarrowString(m_regusername.GetString(), username);
m_nickname.Trim();
CString strnickname = m_nickname.GetString();
nickname = UnicodeToUTF8(m_nickname.GetString());
if (strlen(username.c_str()) == 0)
{
MessageBox(_T("用户名为空。"), _T("提示"), MB_OK | MB_ICONEXCLAMATION);
return;
}
if (strlen(username.c_str()) > MYSQLUSERNAMELEN)
{
MessageBox(_T("用户名太长。"), _T("提示"), MB_OK | MB_ICONEXCLAMATION);
return;
}
if (strlen(nickname.c_str()) > MYSQLNICKNAMELEN)
{
MessageBox(_T("昵称太长。"), _T("提示"), MB_OK | MB_ICONEXCLAMATION);
return;
}
if (strlen(nickname.c_str()) == 0)
{
MessageBox(_T("昵称为空。"), _T("提示"), MB_OK | MB_ICONEXCLAMATION);
return;
}
if (m_password.GetLength() == 0)
{
MessageBox(_T("密码为空。"), _T("提示"), MB_OK | MB_ICONEXCLAMATION);
return;
}
//mysql通配符转义。
std::string usernamestr(username.c_str());
char *tmpname = new char[MYSQLUSERNAMELEN + MYSQLUSERNAMELEN + 1];
int i, j = 0;
for (i = 0; i < usernamestr.length(); i++)
{
if (usernamestr[i] == '%' || usernamestr[i] == '_')
{
tmpname[j] = '\\'; j++;
}
tmpname[j] = usernamestr[i]; j++;
}
tmpname[j] = '\0';
std::string buf("select * from chatapp.user where username like '");
buf.append(tmpname); delete[] tmpname;
buf.append("'");
mysql_query(&m_sqlCon, buf.c_str());
MYSQL_RES *result = mysql_store_result(&m_sqlCon);
if (result&&result->row_count)
{
MessageBox(_T("已有用户用这个名字注册"), _T("提示"), MB_OK | MB_ICONINFORMATION);
}
else
{
std::string password;
password = toNarrowString(m_password.GetString(), password);
MD5 md5Password(password);
std::string passwordMD5 = md5Password.toString();
std::string buf("insert into chatapp.user(userID, username,nickname, regtime,password) values(NULL,'");;
buf.append(username.c_str());
buf.append("','");
buf.append(nickname.c_str());
buf.append("',NOW(), '");
buf.append(passwordMD5.c_str());
buf.append("');");
if (mysql_query(&m_sqlCon, buf.c_str()) == 0)
{
m_password = "";
//m_ctrl_password.SetWindowTextW(_T(""));
m_firstpassword = "";
//m_ctrl_firstpassword.SetWindowTextW(_T(""));
m_username = m_regusername;
//m_ctrl_username.SetWindowTextW(m_regusername);
m_regusername = "";
//m_ctrl_regusername.SetWindowTextW(_T(""));
m_nickname = "";
//m_ctrl_nickname.SetWindowTextW(_T(""));
UpdateData(FALSE);
regnum++;
isLogging = TRUE;
showLogging();
}
else
{
MessageBox(_T("插入数据失败!"), _T("提示"));
}
}
}
else
{
MessageBox(_T("两次输入的密码不同."), _T("提示"), MB_OK | MB_ICONWARNING);
}
}
UpdateData(false);
mysql_close(&m_sqlCon);//关闭Mysql连接
//CDialogEx::OnOK();
}
//屏蔽某一个控件的输入法状态:
// Function for Disabling IME
void CChatCilentDlg::DisableIME()
{
HWND hWnd = m_ctrl_regusername.m_hWnd;
if (hWnd && IsWindow(hWnd))
{
// Get input context for backup.
m_hImc = ImmGetContext(hWnd);
// Remove association the testing
if (m_hImc)
ImmAssociateContext(hWnd, NULL);
// Release input context
ImmReleaseContext(hWnd, m_hImc);
//::SetFocus(hWnd);
}
HWND hWnd2 = m_ctrl_username.m_hWnd;
if (hWnd2 && IsWindow(hWnd2))
{
// Get input context for backup.
m_hImc = ImmGetContext(hWnd2);
// Remove association the testing
if (m_hImc)
ImmAssociateContext(hWnd2, NULL);
// Release input context
ImmReleaseContext(hWnd2, m_hImc);
//::SetFocus(hWnd);
}
}
//限制输入就是在编辑框控件的OnChar或者OnChange中过滤抛弃输入即可。
/*BOOL WINAPI ImmGetOpenStatus(
HIMC hIMC);
Parameters
hIMC
[in] Handle to the input context.*/
//使用这个api检查输入法是否打开
//HIMC hIMC = ImmGetContext(m_cEidt.GetSafeHwnd());
//获取系统的输入法
//ImmSetOpenStatus(hIMC, FALSE);
//屏蔽
//下面的代码用来屏蔽某一个控件的输入法状态。
//HIMC m_hImc; // 全局或者成员变量
// Function for Disabling IME
// Function for Enabling IME
void CChatCilentDlg::EnableIME()
{
HWND hWnd = m_ctrl_regusername.m_hWnd;
if (hWnd && IsWindow(hWnd))
{
// Enable IME
if (m_hImc)
{
// Associate the input context with testing window
ImmAssociateContext(hWnd, m_hImc);
m_hImc = NULL;
}
// ::SetFocus(hWnd);
}
}
void CChatCilentDlg::OnCancel()
{
// TODO: 在此添加专用代码和/或调用基类
if (pUP != NULL)
{
delete[] pUP;
}
CDialogEx::OnCancel();
}
void CChatCilentDlg::OnCbnSelchangeCombo1()
{
// TODO: 在此添加控件通知处理程序代码
int n=m_ctrl_username.GetCurSel();
CString pass(pUP[n].password.c_str());
m_ctrl_password.SetWindowTextW(pass.GetString());
// m_password = pass;
if (pUP[n].autologin == "1")
{
// m_autologin = TRUE;
m_ctrl_autologin.SetCheck(1);
}
else
{
// m_autologin = FALSE;
m_ctrl_autologin.SetCheck(0);
}
if (pUP[n].rempassword == "1")
{
// m_remberpassword = TRUE;
m_ctrl_remberpassword.SetCheck(1);
}
else
{
// m_remberpassword = FALSE;
m_ctrl_remberpassword.SetCheck(0);
}
// UpdateData(FALSE);
}
密码加密进本地文件:
//EncodeDecode.cpp
#include <stdio.h>
#include "stdafx.h"
#include "EncodeDecode.h"
#include "zfzh.h"
#include "time.h"
CCode::CCode()
{
}
CCode::~CCode()
{
}
CString CCode::Encode(CString szData, CString strKey)
{
//szData为待加密文本
//strKey为加密秘钥
int en[4];
srand((int)time(0));//使得每次生成的密文不相同
for (int i = 0; i < 4; i++)
{
en[i] = 1 + (int)(10.0*rand() / (RAND_MAX + 1.0));//生成随机密文(范围可自己调整0-15)
}
std::string pass;
pass=toNarrowString(szData.GetString(), pass);
DWORD num = MultiByteToWideChar(CP_ACP, 0, pass.c_str(), -1, NULL, 0);
int nData = szData.GetLength();//取生成的16进制字符串长度
WCHAR *pData; //定义一个UNICODE的指针
pData = (WCHAR*)calloc(num, sizeof(WCHAR));//动态的申请空间存字
if (pData == NULL) //判断申请到空间没有
{
//free(pData);
return NULL;
}
memset(pData, 0, num * sizeof(WCHAR)); //初始化动作
MultiByteToWideChar(CP_ACP, 0, pass.c_str(), -1, pData, num);
WCHAR *pData_R = pData;
std::string key;
key= toNarrowString(strKey.GetString(), key);
DWORD num2 = MultiByteToWideChar(CP_ACP, 0, key.c_str(), -1, NULL, 0);
WCHAR *pKey;
pKey = (WCHAR*)calloc(num2, sizeof(WCHAR));
if (pKey == NULL) //判断申请到空间没有
{
free(pData);
return NULL;
}
memset(pKey, 0, num2 * sizeof(WCHAR)); //初始化动作
MultiByteToWideChar(CP_ACP, 0, key.c_str(), -1, pKey, num2);
int nKeyLen = strKey.GetLength();//取生成的16进制字符串长度
int tmpi = 0;
CString tmps, enstr;
for (int i = 0; i <nData; i++)
{
tmpi = *pData + pKey[i%nKeyLen] + i*en[i % 4];//按位加密运算
int strtmp;
strtmp = *pData;
tmpi = tmpi>65535 ? tmpi - 65535 : tmpi;//范围修正
tmps.Format(_T("%x"), tmpi);
//格式输出
if (tmpi >= 4096)
{
enstr += tmps;
}
else if (tmpi >= 256)
{
enstr += _T("0") + tmps;
}
else if (tmpi >= 16)
{
enstr += _T("00") + tmps;
}
else
{
enstr += _T("000") + tmps;
}
pData++;
}
*pData = 0;
CString ens;
for (int i = 0; i <4; i++)
{
tmps.Format(_T("%x"), en[i]);//随机秘钥放在返回字串前占用1个字符
ens += tmps;
}
free(pData_R);
free(pKey);
return ens + enstr;
}
CString CCode::Decode(CString szData, CString strKey)
{
//szData为待解密文本
//strKey为解密秘钥(同加密秘钥)
int de[4];
for (int i = 0; i < 4; i++)
{
CString szTemp;
szTemp = szData.Left(1);
CString temp;
de[i] = _tcstoul(szTemp, 0, 16); //获得随机秘钥
szData.Delete(0, 1);//剩下的密文
}
int dn = szData.GetLength() / 4;
std::string key;
key = toNarrowString(strKey.GetString(), key);
DWORD num3 = MultiByteToWideChar(CP_ACP, 0, key.c_str(), -1, NULL, 0);
WCHAR *pKey;
pKey = (WCHAR*)calloc(num3, sizeof(WCHAR));
if (pKey == NULL)
{
//free(pKey);
return NULL;
}
memset(pKey, 0, num3 * sizeof(WCHAR)); //初始化动作
MultiByteToWideChar(CP_ACP, 0, key.c_str(), -1, pKey, num3);
int nKeyLen = key.length();
WCHAR *strc;
strc = (WCHAR*)calloc(dn + 1, sizeof(WCHAR));
if (strc == NULL)
{
free(pKey);
return NULL;
}
memset(strc, 0, (dn + 1) * sizeof(WCHAR)); //初始化动作
//MultiByteToWideChar(CP_ACP,0, (LPCTSTR)strKey, -1, pKey, num3);
WCHAR *enstr = strc;
CString tmps;
unsigned int tmpi = 0;
for (int i = 0; i < dn; i++)
{
tmps = szData.Left(4);//取4个字符(16进制字符)
szData.Delete(0, 4);//剩下的字符
*strc = (WCHAR)_tcstoul(tmps, 0, 16);
tmpi = *strc - pKey[i%nKeyLen] - i*de[i % 4];//解密运算
tmpi < 0 ? tmpi + 65535 : tmpi;
*strc = tmpi;
strc++;
}
*strc = 0;
tmps = enstr;
free(pKey);
free(enstr);
return tmps;
}
//解密和加密运算中,求数组内的值只能用%,不能用/号,否则越界,造成内存问题。
//对指针申请了内存空间,要记得归还。如果对指针进行了操作,记得先将这个指针初始化另一个指针,最后将另一个指针释放掉
里面用了转换成窄字符串函数:
//zfzh.cpp
#include "stdafx.h"
#include <string>
#include <assert.h>
//#include <Windows.h>
std::string toNarrowString(const wchar_t* pStr, std::string &buf, int len)
{
// figure out how many narrow characters we are going to get
assert(pStr);
assert(len >= 0 || len == -1);
int nChars = WideCharToMultiByte(CP_ACP, 0,
pStr, len, NULL, 0, NULL, NULL);
if (len == -1)
--nChars;
if (nChars == 0)
return "";
// convert the wide string to a narrow string
// nb: slightly naughty to write directly into the string like this
//std::string buf;
buf.resize(nChars);
WideCharToMultiByte(CP_ACP, 0, pStr, len, const_cast<char*>(buf.c_str()), nChars, NULL, NULL);
return buf;
}
std::string toNarrowString(const std::wstring& strW, std::string buf)
{
const wchar_t* pStr = strW.c_str();
int len = (int)strW.length();
return toNarrowString(pStr, buf, len);
}
/*参考了网上一些方法:所谓的短字符, 就是用8bit来表示的字符, 典型的应用是ASCII码.而宽字符, 顾名思义, 就是用16bit表示的字符, 典型的有UNICODE.
常用的代码页有CP_ACP和CP_UTF8两个。
使用CP_ACP代码页就实现了ANSI与Unicode之间的转换。
使用CP_UTF8代码页就实现了UTF - 8与Unicode之间的转换。*/
//1. ASCII to Unicode(CP_ACP)
std::wstring ASCIIToUNICODE(char cArry[]) //传入参数为ANSI串,即用char数组或者string表示的串
{
int nLen = ::MultiByteToWideChar(CP_ACP, 0, cArry, -1, NULL, NULL); //将MultiByteToWideChar()的第四个形参设为-1,即可返回长度
wchar_t *pTemp = new wchar_t[nLen]; //new一个wchar_t空间,保存Unicode串
memset(pTemp, 0, nLen*sizeof(wchar_t));
::MultiByteToWideChar(CP_ACP, 0, cArry, -1, (LPWSTR)pTemp, nLen);
std::wstring str = pTemp;
if (pTemp)
{
delete[] pTemp;
pTemp = NULL;
}
return str;
}
//2. Unicode to ASCII(CP_ACP)
std::string UNICODEToASCII(wchar_t cArry[]) //传入参数为Unicode串,用“wchar_t cArry[] = {L"这是个测试"};”表示
{
int nLen = ::WideCharToMultiByte(CP_ACP, 0, cArry, -1, NULL, 0, NULL, NULL);
char *pTemp = new char[nLen]; //new 一个char数组,保存ANSI串
memset(pTemp, 0, nLen);
::WideCharToMultiByte(CP_ACP, 0, cArry, -1, pTemp, nLen, NULL, NULL);
std::string str = pTemp;
if (pTemp)
{
delete[] pTemp;
pTemp = NULL;
}
return str;
}
std::string UnicodeToUTF8(const std::wstring& str)
{
// wide char to multi char
int iTextLen = ::WideCharToMultiByte(CP_UTF8, 0, str.c_str(), -1, NULL, 0, NULL, NULL);
char *pElementText = new char[iTextLen];
memset(pElementText, 0, iTextLen);
::WideCharToMultiByte(CP_UTF8, 0, str.c_str(), -1, pElementText, iTextLen, NULL, NULL);
std::string strText;
strText = pElementText;
if (pElementText)
{
delete[] pElementText;
pElementText = NULL;
}
return strText;
}
// UTF8 转宽字符
std::wstring DecodeUtf8(std::string in)
{
std::wstring s(in.length(), _T(' '));
size_t len = ::MultiByteToWideChar(CP_UTF8, 0, in.c_str(), in.length(), &s[0], s.length());
s.resize(len);
return s;
}
可下载全部代码