Windows核心编程—学习笔记(1)

第1章 错误处理

常见的Windows函数返回值数据类型
void 这个函数返回值不会失败,只有很少函数返回值是void
bool 函数失败,返回值为0;否则,返回值为非0
handle

函数失败,返回值为NULL;否则,handle将标识一个可操纵的对象;

某些函数失败了,会返回为INVALD_HANDLE_VALUE的一个句柄值,被定义为-1;

函数的Platform SDK文档会说明函数是用NULL还是INVALD_HANDLE_VALUE来标识失败;

pvoid 函数失败返回值为NULL,否则pvoid将标识一个内存地址
long/dword 通常返回0或-1
  1. windows函数的错误代码都是32位;
  2. GetLastError函数    返回上一个函数的错误代码;
  3. 函数失败后,应马上调用GetLastError,如果又调用了另一个函数,错误代码的值会被改写,成功调用的函数可能用Error_Success改写此值;
  4. FormatMessage函数    将错误代码转换为相应的文本描述;

1.1 定义自己的错误代码

Void SetLastError(DWORD dwErrCode);    //设置线程的上一个错误代码;
错误代码的不同字段
31-30 29 28 27-26 15-0
内容 严重性 Microsoft/客户 保留 Facility代码 异常代码
含义

0=成功

1=信息(提示)

2=警告

3=错误

0=Microsoft定义的代码

1=客户定义的代码

必须为0 前256个值由Microsoft保留

Microsoft/客户定义的代码

1.2 ErrorShow示例程序

第2章 字符和字符串处理

2.1 字符编码

双字节字符集(DBCS) 每个字符由1或2个字符组成
UTF-16 每个字符由2个字节编码,支持4字节表示的代理(surrogate)方式,是节省空间和简化编码的折衷
UTF-8 每个字符可由1/2/3/4个字节编码,对大量字符编码是不如UTF-16高效
UTF-32 每个字符都由4字节编码,不用考虑代理的问题

2.2 ANSI字符和Unicode字符与字符串数据类型

(1)char表示一个8位ANSI字符

//pointer to 8-bit character(s)
   typedef char *pchar;
   typedef char *pstr;
   typedef const char *pcstr;

(2)wchar_t表示一个16位的UTF-16字符

//pointer to 16-bit character(s)
   typedef wchar *pwchar;
   typedef wchar *pwstr;
   typedef const wchar *pcwstr;

(3)WinNT.h定义了以下宏

   #if Unicode
   typedef WCHAR TCHAR, *PTCHAR, PTSTR;
   typedef CONST CHAR *PCTSTR;
   #define _TEXT(quote) quote
   #define _TEXT(quote) L##quote
   #else
   typedef CHAR TCHAR, *PTCHAR, PTSTR;
   typedef CONST WCHAR *PCTSTR;
   #define _TEXT(quote) quote
   #endif
   #define quote _TEXT(quote)

2.3 Windows中的Unicode函数和ANSI函数

(1)CreatWindowEx有2个版本:CreatWindowExW(接受Unicode字符串),CreatWindowExA(接受ASNI字符串(2)CreatWindowEx是一个宏,定义如下:

#if Unicode
#define CreatWindowEx CreatWindowExW
#else
#define CreatWindowEx CreatWindowExA
#endif

2.4 C运行库中的Unicode函数和ANSI函数

和windows函数不同,C库函数的Unicode函数和ANSI函数都不会把字符串相互转换

2.5 C运行库中的安全字符串函数

2.5.1 初识新的安全字符串函数

后缀为_s代表secure,前缀为StringCch的为安全函数

2.5.2 在处理字符串时如何获得更多控制

前缀为StringCch的安全函数用来控制截断;
Cch表示Count of characters,即字符数;Cb表示函数要求用字节数来指定大小;

安全字符串函数的HRESULT值
S_OK 成功,目标缓冲区包含原字符串,并以'\0'终止
STRSAFE_E_INVALID_PARAMETER 失败,将NULL值传给了一个参数
STRSAFE_E_INSUFFICIENT_BUFFER 失败,目标缓冲区太小,无法容纳源字符串

函数扩展(EX)版本的参数:size_t *pcchRemaining, LPTSTR *ppszDestEnd
                                                DWORD dwplags, STRSAFE_FILL_BEHIND_NULL
                                                STRASTE_IGNORE_NULLS, STRSAFE_FILL_ON_FAILURE
                                                STRSAFE_NULL_ON_FAILURE,STRSAFE_NO_TRUNCATION

2.5.3 Windows字符串函数

(1)CompareString函数原型:

int CompareString(LCID locale, //以符合用户语言习惯的方式来显示字符串
    DWORD dwCmdFlags,
    PCTSTR pString1,
    int cch1,
    PCTSTR pString2,
    int cch2);

第1个参数:LCID(licale ID)指定一个区域设置ID,是一个32位值,用来标识一种语言;
                    可以用Windows函数GetThreadLocale来获得主调线程的LCID

LCID GetThreadLocale();

第2个参数:是一组标志,用于修改函数比较字符串时采用的方法                 

可能的标志
NORM_IGNORECASE LINGUISTIC_IGNORECASE 忽略大小写
NORM_IGNOREKANATYPE 不区分平假名和片假名字符
NORM_IGNORENONSPACE LINGUISTIC_IGNOREDIACRITIC  忽略读音字符
NORM_IGNORESYMBOLS 忽略符号
NORM_IGNOREWIDTH  不区分同一字符的单双字节形式
SORT_STRINGSORT     将标点符号当作符号处理

其余参数:指定了2个字符串及其字符个数;

(2)CompareStringOrdinal函数原型:

//用于比较程序内部所用的字符串,是码位比较,不用考虑区域设置,函数只支持Unicode字符串
int CompareStringOrdinal(PCWSTR pString1, 
    int cchCount1,
    PCWSTR pString2,
    int cchCount2,
    BOOL bIgnoreCase);

2.6 为何要用Unicode
2.7 推荐的字符和字符串处理方式

  •   将文本字符串想象为字符数组,而不是char或字节的数组;
  •   用TCHAR/PTSTR来表示文本字符和字符串;
  •   用BYTE和PBYTE来表示字节、字节指针和数据缓冲区;
  •   用TEXT或_T宏来表示字面量字符和字符串,避免两者混用;
  •   执行全局替换,如:用PTSTR替换PSTR;
  •   修改字符有关的计算,如:

              给函数传缓冲区大小的字符数,应用_countof(szBuffer),而不是sizeof(szBuffer);

              为字符串分    配内存块且知道字符数,应用malloc(nCharacters* sizeof(TCHAR)),而不是malloc(nCharacters);

              定义一个宏来避免犯错:

#define chmalloc(nCharacters) (TCHAR*)malloc(nCharacters* sizeof(TCHAR))
  • 避免使用printf函数,尤其不要用%s和%S来进行ANSI和Unicode字符串之间的相互转换,应用MultiByteToWideChar和      WideCharToMultiByte函数(详情见2.8节);
  • UNICODE和_UNICODE符号要么同时指定,要么都不指定;

2.8 Unicode与ANSI字符串的转换

int MultiByteToWideChar(    //将多字节字符串转换为宽字符字符串
    UINT uCodePage,           //字符串所处的页值
    DWORD dwFlags,            //进行额外控制,一般不使用,为0
    PCSTR pMultiByteStr,      //要转换的字符串
    int cbMultiByte,          //源字符串的字节数,为-1可自动判断
    PWSTR pWideCharStr,       //转换所得的Unicode字符串写入的内存地址
    int cchWideChar);         //缓冲区可容纳的字符数,若为0则不执行转换,返回目标缓冲区需要的大小,乘以sizeof(wchar_t)
WideCharToMultiByte(        //将宽字符字符串转换为多字节字符串
    UINT uCodePage,           
    DWORD dwFlags,            
    PCWSTR pWideCharStr,      //要转换字符串的内存地址
    int cchWideChar           //要转换字符串的字节数,为-1可自动判断
    PSTR pMultiByteStr
    int cbMultiByte,          //缓冲区可容纳的字符数,若为0则不执行转换,返回目标缓冲区需要的大小,不用乘法运算
    PCSTR pDefaultChar,       //指定页码中只有一个字符没有对应的表示时,才用最后2个参数
    PBOOL pfUsedDefaultChar);

2.8.1 导出ANSI和Unicode DLL函数

//一个函数的Unicode版本
BOOl StringReverseW(PWSTR pWideCharStr,DWORD cchLength){

PWSTR pEndOfStr = pWideCharStr + wcsnlen_s(pWideCharStr,cchLength) - 1;   //获取指向最后一个字符的指针
wchar_t cCharT;

//循环直到获取字符串的中间字符
while(pWideCharStr < pEndOdStr){ 
      cCharT = *pWideCharStr;           //在临时变量中存入一个字符
      *pWideCharStr = *pEndOfStr;       //把最后一个字符存入第一个字符
      *pEndOfStr cCharT;                //把临时变量存入最后一个字符
      pWideCharStr++;                   //从左边移入一个字符
      pEndOfStr--;                      //从右边移入一个字符
  }                                  
return (TRUE);                         //字符串被逆转,返回成功
}

2.8.2 判断文本是ANSI还是Unicode

IsTextUnicode函数能分辨文件是ANSI字符还是Unicode字符,由AdvApi.dll导出并在WinBase.h中声明

//缓冲区包含Unicode文本返回True,否则返回False
BOOL IsTextUnicode(CONST PVOID pvBuffer, //标识了要测试的缓冲区地址
     int cb,                             //指定pvBuffer指向的缓冲区字节数
     PINT pResult);                      //可为NULL


 

发布了3 篇原创文章 · 获赞 3 · 访问量 262

猜你喜欢

转载自blog.csdn.net/qq_35501364/article/details/104039293