MFC MYSQL登录注册程序,登录信息本地文件加密记录

新建对话框程序。

对话框控件文件,有重叠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;
}

可下载全部代码

MFCmysql注册登录代码,不惧生僻字,密码两套加密代码。-互联网文档类资源-CSDN下载MFC注册登录代码,不惧生僻字。密码MD5加密进mysql数据库,宽字符、UFT8之间的转换。登录更多下载资源、学习资料请访问CSDN下载频道.https://download.csdn.net/download/ywqb95/40583666

  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值