【Win32准备】API,Win32入口程序,宽字符(下)

简介: 【Win32准备】API,Win32入口程序,宽字符

三.C语言宽字符函数

1.字符串长度

我们知道在C语言中我们可以使用strlen函数来计算字符串长度,那么我们的多字节和宽字符如何计算字符串长度?

对于多字节,我们仍然可以使用strlen(); 函数来计算字符串长度(不包含末尾的\00)。

对于宽字符,我们可以使用wcslen(); 函数来计算字符串长度(不包含末尾的\00 \00)。

#include <stdio.h>
#include <string.h>
#include <locale.h>
int main()
{
    setlocale(LC_ALL, "");
    char x[] = "中国";
    wchar_t x1[] = L"中国";
    int a = strlen(x);
    int b = wcslen(x1);
    printf("%s\n", &x);
    wprintf(L"%s\n", &x1);
}

我们来到局部变量窗口观察:

我们可以看到,使用多字节保存”中国“时,字符串长度为4,使用宽字节保存”中国“时,字符串长度为4,这也很好的验证了多字节为单个字节存储,宽字符为两个字符存储。

2.字符串复制

我们知道在C语言中,我们可以使用strcpy();函数来进行字符串的复制和赋值,那么宽字符我们该如何赋值?

对于宽字符,我们可以使用wcscpy();函数来进行字符串的复制:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <locale.h>
int main()
{
    setlocale(LC_ALL, "");
    char x[] = "中国";
    wchar_t x1[] = L"中国";
    int a = strlen(x);
    int b = wcslen(x1);
    char x2[] = "123";
    strcpy(x2,x);
    wchar_t x3[] = L"123";
    wcscpy(x3, x1);
    printf("%s\n", &x);
    wprintf(L"%s\n", &x1);
}

其中#define _CRT_SECURE_NO_WARINGS可谓是非常经典的问题了,加入这个宏后,程序会少了对很多不安全的问题报错,我们来到局部变量窗口查看:

我们可以看到对于多字节和宽字符,都成功复制。

3.其他宽字符函数

这里我们介绍几个其他的不常用的宽字符函数:

<1>.wcscat函数

函数原型:wchar_t *wcscat(wchar_t *strDestination, const wchar_t *strSource);

函数功能:把strSource所指字符串添加到strDestination结尾处,覆盖strDestination结尾处的’\0’并添加’\0’。

说明:strSource和strDestination所指内存区域不可以重叠且strDestination必须有足够的空间来容纳strSource的字符串。

返回值:返回指向strDestination的指针.。

备注:因为wcscat在strDestination追加strSource前不进行检查,这是一个缓冲区溢出的潜在原因。故使用时应注意。推荐使用wcscat_s替代。

<2>.wcscmp函数

函数原型:int wcscmp(const wchar_t *_Str1, const wchar_t *_Str2);

函数功能:比较字符串_Str1和_Str2

说明:

当_Str1<_Str2时,返回值<0

当_Str1=_Str2时,返回值=0

当_Str1>_Str2时,返回值>0

即:两个字符串自左向右逐个字符相比(按ASCII值大小相比较),直到出现不同的字符或遇’\0’为止。

如: “A”<“B” “a”>“A” “computer”>“compare”

<3>.wcsstr函数

函数原型:const wchar_t* wcsstr (const wchar_t* wcs1, const wchar_t* wcs2);

查找宽字符串wcs1的子字符串wcs2。

返回一个指针,该指针指向wcs1中的wcs2首次出现的位置,或则,如果wcs2不是wcs1的一部分,则返回null。

匹配的过程不包括结尾的null宽字符,但是它在那儿结束。

四.Win32API中的宽字符

1.什么是Win32API

Win32 API即为Microsoft 32位平台的应用程序编程接口(Application Programming Interface)。所有在Win32平台上运行的应用程序都可以调用这些函数。

使用Win32 API,应用程序可以充分挖掘Windows的32位操作系统的潜力。 Mircrosoft的所有32位平台都支持统一的API,包括函数、结构、消息、宏及接口。使用 Win32 API不但可以开发出在各种平台上都能成功运行的应用程序,而且也可以充分利用每个平台特有的功能和属性。
在具体编程时,程序实现方式的差异依赖于相应平台的底层功能的不同。最显著的差异是某些函数只能在更强大的平台上实现其功能。例如,安全函数只能在Windows NT操作系统下使用。另外一些主要差别就是系统限制,比如值的范围约束,或函数可管理的项目个数等等。
标准Win32 API函数可以分为以下几类:
    窗口管理
    窗口通用控制
    Shell特性
    图形设备接口
    系统服务
    国际特性
    网络服务

2.重要的DLL

<1>.Kernel32.dll

最核心的功能模块,比如管理内存,进程和线程相关的函数。

<2>.User32.dll

是Windows用户界面相关应用程序接口,如创建窗口和发送消息等。

<3>.GDI32.dll

全程Graphical Device Interface(图形设备接口),包含用于画图和显示文本的函数,比如要显示一个程序窗口,就调用了其中的函数来画这个窗口。

3.Win32API中的宽字符和多字节字符

Windows是C语言开发的,WIn32API同时支持宽字符和多字节字符。

<1>.字符类型

C语言 API
char CHAR
wchar_t WCHAR
TCHER

<2>.字符串指针类型

  • PSTR(LPSTR)
  • PWSTR(LPWSTR)
  • 宏 PTSTR(LPTSTR)

其实这些类型都是C语言中的基本数据类型,只是使用typedef关键字进行了重命名。

其中使用后宏的时候,编译器会自动匹配正确的格式,就像C++中的模板。

4.为字符数组赋值

CAHR cha[] = "中国";
WCHAR chw[] = "中国";
TCHER cht[] = TEXT"中国";

5.为字符串指针赋值

PSTR pszChar = "China";
PWSTR pszWCher = "Chaina";
PTSTR pszTchar = TEXT"China";

五.各种类型的MessageBox

  • MessageBoxA(0,"内容多字节“,”标题“,MB_OK);
  • MessageBoxW(0,"内容宽字符“,”标题“,MB_OK);
  • MessageBox(0,TEXT"由字符集决定“,TEXT”标题“,MB_OK);

WIndows提供的API,凡是需要传递字符串参数的函数,都会提供两个版本和一个宏。

六.Win32入口程序

我们创建Win32入口程序,我们会看到一个入口函数:

// Win32.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
  // TODO: Place code here.
  return 0;
}

我们看到入口函数中有很多参数,我们来简单解释一下这几个参数:

  • hInstance:
    表示该程序当前运行的实例句柄,是一个数值标识。当程序在Windows下运行时,它唯一标识运行中的实例(注意,只有运行中的程序实例,才有实例句柄)。一个应用程序可以运行多个实例,每运行一个实例,系统都会给该实例分配一个实例句柄,并通过hInstance参数传递给WinMain函数。
  • hPrevInstance:
    表示当前实例的前一个实例的句柄。通过查看MSDN我们可以知道,在Win32环境下,这个参数总是NULL,即在Win32环境下,这个参数不再起作用。
  • lpCmdLine:
    是一个以空字符结尾的字符串,内容为命令行的参数。
  • nCmdShow:
    指定程序的窗口应该如何显示,例如最大化、最小化、隐藏等。这个参数的值由该程序的调用者所指定,应用程序通常不需要去理会这个参数的值。

WinMain函数前的修饰符APIENTRY,其实是被使用typedef关键字重命名的,它是WINAPI,而WINAPI也是被使用typedef重命名的,它其实就是__stdcall。

在这几个参数中,最重要的是hInstance,我们在前面章节中学习过PE文件格式,其实它就是可选PE头中的ImageBase。

七.在Win32程序中打印信息

#include <stdio.h>
#include <windows.h>
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
  // TODO: Place code here.
  OutputDebugString("Hello World!");
  return 0;
}

我们可以通过OutputDebugString()函数来打印信息。

我们可以看到在输出窗口输出了Hello World!

八.GetLastError函数

但是我们发现一个很严重的问题:我们在写Win32程序的时候,编译器不会报错这时候就需要我们使用OutLastError()函数了:

GetLastError:返回上一次的错误代码,当我们在调用第三方(MFC,Word。。。。)提供的接口时,有时候只能得到返回值是true还是false的时候是不是很苦恼?此时就可以通过GetLastError函数来获取错误代码。

我们会得到一个错误代码,我们通过查询错误代码就可以知道我们程序中的错误了。

相关文章
|
网络协议 API 数据处理
【网络编程】第2章(2) 应用程序接口(API)
【网络编程】第2章(2) 应用程序接口(API)
|
7月前
|
程序员 API C语言
Win32 API介绍​(COORD、GetStdHandle、GetConsoleCursorInfo 、SetConsoleCursorInfo)、<locale.h>本地化、类项
Win32 API介绍​(COORD、GetStdHandle、GetConsoleCursorInfo 、SetConsoleCursorInfo)、<locale.h>本地化、类项
|
4月前
|
移动开发 开发框架 小程序
开发H5程序或者小程序的时候,后端Web API项目在IISExpress调试中使用IP地址,便于开发调试
开发H5程序或者小程序的时候,后端Web API项目在IISExpress调试中使用IP地址,便于开发调试
|
7月前
|
API Python Windows
python3应用windows api对后台程序窗口及桌面截图并保存的方法
python3应用windows api对后台程序窗口及桌面截图并保存的方法
541 1
|
6月前
|
XML JSON API
RESTful API关键部分组成和构建web应用程序步骤
RESTful API关键部分组成和构建web应用程序步骤
42 0
api一键自动合约跟单模式 | 程序化交易系统开发讲解【附样板源码实例分析】
“量化交易”有着两层含义:一是从狭义上来讲,是指量化交易的内容,将交易条件转变成为程序,自动下单;二是从广义上来讲,是指系统交易方法,就是一个整合的交易系统。
|
7月前
|
API 网络架构
解释 RESTful API,以及如何使用它构建 web 应用程序。
解释 RESTful API,以及如何使用它构建 web 应用程序。
123 0
|
7月前
|
JSON API 数据格式
RESTful API,以及如何使用它构建 web 应用程序。
RESTful API,以及如何使用它构建 web 应用程序。
105 0
|
7月前
|
监控 编译器 API
常用Win32 API的简单介绍
常用Win32 API的简单介绍
|
存储 JavaScript 前端开发
使用 HTML、CSS、JS 和 API 制作一个很棒的天气 Web 应用程序
使用 HTML、CSS、JS 和 API 制作一个很棒的天气 Web 应用程序
150 0