基于MFC的Windows开发:记录登陆窗口的登陆信息以便下次自动输入(踩坑记录)

在基于MFC的窗口程序中记录登陆信息以便下次自动输入

  • 功能:
    • 自动读取上一次的登陆信息:OnInitDialog()函数中有个“// TODO: Add extra initialization here”,在这里添加读取.ini文件后设置窗口内容
    • 当按下“登陆”的时候将登陆信息保存到.ini文件中:OnBnClickedLogin()函数中获取信息后先保存再传递给聊天窗口
  • 基于:MFC的Dialog模板,Visual Studio 2019

相关文档

读取自定义的.ini文件内容 GetPrivateProfileString()

保存内容到自定义的.ini文件 WritePrivateProfileString()

设置窗口空间文本内容 SetWindowText()

PS:如果直接用系统的C:Windows中的win.ini文件,对应的函数为没有Private的GetProfileString、WriteProfileString

详细的函数说明中文版参考https://blog.csdn.net/wfq_1985/article/details/6800492

下面是踩坑内容

CString 转换到 LPCWSTR

由于WritePrivateProfileString()的参数都是LPCWSTR类型,需要将CString类型的登录信息(用户名、密码、房间号等)转换为LPCWSTR才能保存。

网上很多方法都不对,尝试了这个是对的http://blog.csdn.net/sl159/article/details/6412171

通过CString类里的.AllocSysString()方法

LPCWSTR lpcwStr = strFileName.AllocSysString();

  

warning C4244: “=”: 从“ULONGLONG”转换到“DWORD”,可能丢失数据

在读取.ini文件前,使用CFile::GetStatus()返回的Bool值判断文件是否存在。

我们想通过文件的大小(status.m_size)来设置后面存储读取的数据的TCHAR变量长度,这样才能确保放得下

这里是参考https://blog.csdn.net/alzzw/article/details/103711516,不过TA的代码有问题,请自行注意

而status.m_size是ULONGLONG格式,GetPrivateProfileString()中需要的是DWORD格式,涉及到格式转换,如果不转换的话就会报错

warning C4244: “=”: 从“ULONGLONG”转换到“DWORD”,可能丢失数据

ULONGLONG是64位的,DWORD是32位的大概4294967295,只要大于4G,转换大于这个就会造成数据错误,如果小于,则没关系。

没关系的话就在前面加(DWORD)强制转换,比如:m_nTotalBytes=(DWORD)m_File.GetLength();

这里参考https://blog.csdn.net/aaaa_aaaa_aaaa/article/details/73610073?utm_source=blogxgwz3

关于SetWindowText()函数

官网和和网上的用法都是

SetWindowTextA( HWND hWnd, LPCSTR lpString );

其实可以直接使用

hWnd.SetWindowText(lpString );

这里的hWnd是“要更改其文本的窗口或控件的句柄”,比如CEdit类型

WindowsAPI中W和A的区别

你可能注意到了,很多函数说是一个名字,但其实有名字后面带A或者W两个版本,比如上面的SetWindowTextA()和SetWindowTextW(),它们都是SetWindowText()函数,有什么区别呢?

当使用windows api时,凡是涉及到字符串处理的API函数都有A和W两个版本。

W结尾主要针对的是UNICODE编码,A结尾主要针对的是ANSI编码格式。主要原因是UNICODE和ANSI存储方式不同。

如果你的程序使用的语言只是中英文的,那都可以;如果是其他语言的,需要使用W版本的函数。

更详细的参考https://blog.csdn.net/weixin_34061042/article/details/92174546

关于C语言 字符串前加L的意义

"abc"是ANSI string, 
L"abc"是Unicode string. 

如:

WritePrivateProfileStringW( NULL, NULL, NULL, L"appname.ini" ); 

紧接在第一个引号前面的大写字母L(代表「long」)。这将告诉编译器该字符串按宽字符保存-即每个字符占用2个字节。通常,指针变量p要占用4个字节,而字符串变量需要14个字节-每个字符需要2个字节,末尾的0还需要2个字节。

参考http://c.biancheng.net/cpp/html/1069.html

关于TEXT()、_TEXT()和_T()的区别,以及和L"xxx"的区别

_T("")是一个宏,作用是让你的程序支持Unicode编码,_T(),定义于tchar.h中,开关是宏“_UNICODE”。

#ifdef  _UNICODE
……
#define __T(x)      L ## x
……
#else   /* ndef _UNICODE */
……
#define __T(x)      x
……
#endif  /* _UNICODE */

TEXT()和_TEXT(),windows风格,定义于头文件“WinNT.h”中,开关为宏“UNICODE”。

#ifdef  UNICODE                     // r_winnt
……
#define __TEXT(quote) L##quote      // r_winnt
#else   /* UNICODE */               // r_winnt
……
#define __TEXT(quote) quote         // r_winnt
#endif /* UNICODE */                // r_winnt

三者都是根据编译器的环境进行ANSI/UNICODE变换的,效果类似,可以把一个引号引起来的字符串,根据你的环境设置,使得编译器会根据编译目标环境选择合适的(Unicode还是ANSI)字符处理方式。

如果你定义了UNICODE,那么_T宏会把字符串前面加一个L。这时_T("ABCD") 相当于L"ABCD" ,这是宽字符串。

如果没有定义,那么_T宏不会在字符串前面加那个L,_T("ABCD") 就等价于"ABCD"。

 对比下面三句代码:

 TCHAR     szStr1[] = TEXT("str1");
char        szStr2[] =  "str1";
WCHAR   szStr3[] = L("str1");

第一句话在定义了UNICODE时会解释为第三句话,没有定义时就等于第二句话。

但二句话无论是否定义了UNICODE都是生成一个ANSI字符串,而第三句话总是生成UNICODE字符串。    

为了程序的可移植性,建议都用第一种表示方法。

但在某些情况下,某个字符必须为ANSI或UNICODE,那就用后两种

参考https://blog.csdn.net/itworld123/article/details/79059052

https://www.cnblogs.com/imlucky/archive/2013/05/10/3070581.html

http://blog.sina.com.cn/s/blog_7b372d1301016wpf.html

如何在各种字符串类型之间转换

本主题演示如何将各种Visual C ++字符串类型转换为其他字符串。所涵盖的字符串类型包括char *,wchar_t*,_bstr_t,的CComBSTR,CString的,basic_string的,和System.String。在所有情况下,当转换为新类型时都会生成字符串的副本。对新字符串所做的任何更改都不会影响原始字符串,反之亦然。

https://docs.microsoft.com/en-us/cpp/text/how-to-convert-between-various-string-types?view=msvc-160

原文地址:https://www.cnblogs.com/smileglaze/p/13866602.html