【VC++】字符串详解窗口第一个windows程序

news2024/11/24 14:48:03

注:最后有面试挑战,看看自己掌握了吗

文章目录

  • 系统调用顺序对比
    • 怎样避免确实动态链接库
  • 基本知识
    • 类型列表
    • 指针类型
    • 匈牙利标记法
  • 字符串详解
    • Unicode 和 ANSI 函数
    • TCHARs
  • 窗口
  • WinMain
    • 我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=1noqb14tvyjrm

系统调用顺序对比

在这里插入图片描述

  1. windows没开放源码,所以要在封装一层API,不是像 Linux 那样直接使用系统调用
  2. 应用程序在 Linux 和 Windows 都是用 fwrite 函数,两个操作系统都会调用运行时库中的 write 函数。
  3. 二者区别是二者运行时库的名字不同。Linux中 write 函数在 libc.so 动态库中实现的,而 Windows 则是在 msvcr90.dll 动态库中实现的。

在这里插入图片描述
根本原因是程序使用了标准函数,而在你的机器上,没有这个标准函数对应的动态库实现,如果想要顺利运行则需要到官方网站下载对应版本的动态库安装即可

怎样避免确实动态链接库

在这里插入图片描述
如果你没有依赖其它第三方库,默认 IDE 中指定的运行时库的方式是动态链接,这情况下,会依赖于特定版本的运行时库,具体的编译选项是
/MT、/MTd 以及 /MD 和 /MDd 。后面的小d表示 Debug 和 Release 之分,而 MT 和 MD
则是选择使用静态编译还是动态编译,如果发布程序选择 /MT 选项进行链接,则可以避免在其它机器上运行时缺失动态库的麻烦。

基本知识

类型列表

  1. Windows 头文件中包含了很多独特的类型定义,大多数的定义都在 WinDef.h 文件中,下面是常用的类型列表:

数据类型 大小 有符号?
BYTE 8 bits Unsigned
DWORD 32 bits Unsigned
INT32 32 bits Signed
INT64 64 bits Signed
LONG 32 bits Signed
LONGLONG 64 bits Signed
UINT32 32 bits Unsigned
UINT64 64 bits Unsigned
ULONG 32 bits Unsigned
ULONGLONG 64 bits Unsigned
WORD 16 bits Unsigned

  1. 为了兼容一些历史的程序,所以列表中的类型存在一定的冗余
  2. 这些类型在32位和64位程序中的大小都是固定的。
  3. DWORD 类型在32位和64位程序中都是32位大小。

指针类型

  1. Windows 定义了很多指针类型,通常都是以 P- 或者 LP- 开始的类型名称。
  2. LPRECT 代表指向 RECT 类型的指针。 RECT 类型代表一个矩形结构体, 下面几种定义方式是等价的:

RECT* rect; // Pointer to a RECT structure.
LPRECT rect; // The same PRECT rect; // Also the same.

  1. 历史上,P 前缀的指针叫 pointer ,LP 前缀的指针叫 long pointer。
  2. 二者是16位操作系统向32位操作系统过渡的产物,如今已经没有区别了。 虽然如今已经不分“长短”了,但是依然会出现一个兼容问题,特别是在程序逻辑中存在指针和整形的转化关系的时候。为了解决这个问题,Windows 定义了几种明确的指针类型

DWORD_PTR
INT_PTR
LONG_PTR
ULONG_PTR
UINT_PTR

  1. 如果在程序逻辑上存在32位值扩展到64位值的情况,使用上述类型。

匈牙利标记法

  1. 匈牙利标记法这是为了纪念具有传奇色彩的微软程序员 Charles Simonyi。这种标记法非常简单,即变量名表明该变量数据类型的小写字母开始。
  2. szCmdLine 的前缀 sz 表示“以零结束的字符串”。

p 指针
h 句柄
sz 字符串
b BYTE
ul ULONG
l LONG
i INT
ui UINT
ch CHAR
dw DWORD
hr HRESULT

字符串详解

在这里插入图片描述

  1. Windows天然支持 Unicode 字符串。
  2. 字符串经常被用在 UI 组件、文件名等字符相关的地方。
  3. 因为 Windows 操作系统会涉及到多语言的问题,所以 Unicode 是首选的字符串编码方式。
  4. Linux 使用 UTF-8 编码而Windows 平台使用 UTF-16 编码方式
  5. 每个字符用16位的值表示。UTF-16 字符也被叫做宽字符
  6. Visual Studio C++ 编译器支持内置的宽字符类型 wchar_t ,具体定义在头文件 WinNT.h 中。
  7. typedef wchar_t WCHAR声明一个宽字符或者一个宽字符串需要将 L 放到文件前面:
wchar_t a = L'a';
wchar_t *str = L"hello";
  1. 常见的字符串类型:
类型	定义
CHAR	char
PSTR or LPSTR	char*
PCSTR or LPCSTR	const char*
PWSTR or LPWSTR	wchar_t*
PCWSTR or LPCWSTR	const wchar_t*

Unicode 和 ANSI 函数

因为微软提供对 Unicde 的支持,所以它将每个和字符串相关的 API 都提供了两个版本,一种是 ANSI 字符串版本,另一种是Unicode 字符串版本。
在这里插入图片描述
为使计算机支持更多语言,通常使用 0x80~0xFFFF 范围的 2 个字节表示 1 个字符。比如:汉字 ‘中’ 在中文操作系统中,使用 [0xD6,0xD0] 这两个字节存储。
不同的国家和地区制定了不同的标准,由此产生了 GB2312、GBK、GB18030、Big5、Shift_JIS 等各自的编码标准。这些使用多个字节来代表一个字符的各种汉字延伸编码方式,称为 ANSI 编码。在简体中文Windows操作系统中,ANSI 编码代表 GB2312编码;在繁体中文Windows操作系统中,ANSI编码代表Big5;在日文Windows操作系统中,ANSI 编码代表 JIS 编码。 [1] [2]
不同 ANSI 编码之间互不兼容,当信息在国际间交流时,无法将属于两种语言的文字,存储在同一段 ANSI 编码的文本中。ANSI编码表示英文字符时用一个字节,表示中文用两个或四个字节。
ANSI编码作为中国以及部分亚太地区的多字符编码格式Windows系统和OS X都是提供原生支持的。但是即便如此,许多国外开发者仍然在开发笔记或者文字录入类应用的时候将ANSI编码完全忽略只加入全球通用的UTF-8编码

  1. 下面两个 API 都是设置窗口标题的接口:
    SetWindowTextA 需要传入 ANSI 字符串。
    SetWindowTextW 需要传入 Unicode 字符串。
  2. 函数内部,ANSI 版本的接口会将 ANSI 字符串转换为Unicode 字符串,然后再调用 Unicode 版本接口完成操作。
  3. 为了方便微软在头文件中还定义了一个 UNICODE 宏来区分不同版本的调用
#ifdef UNICODE
#define SetWindowText  SetWindowTextW
#else
#define SetWindowText  SetWindowTextA
#endif
  1. 使用上面的方法可以避免在代码中区分具体调用的接口是 UNICODE 版本还是 ANSI 版本。相反的,在程序中只需要直接调用 SetWindowText 函数设置标题即可。
  2. 编译的时候会自动根据 UNICODE 宏定义决定使用哪个版本。
  3. 除非兼容旧的程序或者组件,否则在开发新应用的时候,应该一直使用 Unicode 版本。因为 Windows 操作系统支持多语言,如果使用 ANSI 版本,它将无法支持应用程序的本地化
  4. ANSI 版本的接口效率更低,因为其内部需要进行编码转换

TCHARs

  1. 如果你的程序需要同时支持多款操作系统,如:Windows NT、Windows 95、Windows 98 和 Windows Me。
  2. 这时候需要明确区分使用的是 ANSI 版本还是 Unicode 版本字符串,为了进一步方面开发,Windows 提供一个宏来完成二者的自动区分
宏	           Unicode	       ANSI
TCHAR	       wchar_t	       char
TEXT(“x”)	   L”x”            “x”
  1. 例子:
SetWindowText(TEXT("My Application"));

该语句等价于:

SetWindowTextW(L"My Application"); // Unicode function with wide-character string.
SetWindowTextA("My Application");  // ANSI function.
  1. 如今TEXT 和 TCHAR 宏用处已经很小了,因为所有的程序都应该使用 Unicode 字符,然而你在一些老的程序中仍然看见它们的身影。

  2. 除了上边的问题,在头文件中,微软 C 运行时库中,仍然存在类似的宏定义,例如涉及到字符操作的函数:

#ifdef _UNICODE
#define _tcslen     wcslen
#else
#define _tcslen     strlen
#endif
  1. 一些头文件使用 UNICODE 宏,另一些使用 _UNICODE 宏,最好同时定义它们,如果你是用 Visual C++ 创建工程,这些会默认自动进行设置

窗口

  1. 存在 UI 控件的时候,控件窗口被认为是应用程序窗口的子窗口
  2. 应用程序窗口被认为是控件窗口的父窗口
  3. 通过父窗口的坐标系可以定位子窗口的位置,并且子窗口的样式等一些属性会受到父窗口的影响。例如,超出父窗口范围的子窗口默认会被裁剪掉。
    在这里插入图片描述

WinMain

  1. 每个 Windows 程序都有一个类似 main 函数的入口函数名字叫做 WinMain 或者 wWinMain , 其声明如下:int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow);

  2. 该函数有四个参数:
    hInstance 参数的含义是一个实例句柄,或者是一个模块句柄。该参数代表被加载到内存的可执行程序(exe文件)。某些 Windows API 可能需要该参数。如:加载图标或者加载位图等等。
    hPrevInstance参数无意义,它在过去的16位操作系统中被使用,现在永远为0。
    pCmdLine 该参数是程序传入的命令行参数,和 main 函数中的 argv 参数含义类似,只不过现在的字符集是 Unicode。
    nCmdShow 该参数是一个整数,代表应用程序主窗口的显示状态,是最小化、最大化还是正常显示。

  3. WINAPI 是一种调用约定。这个约定确保函数从调用者那里接收参数的相关规则,例如,参数在栈中保存的顺序等等。在写代码的时候一定不要忘记该约定的标识。

  4. WinMain 和 wWinMain 默认是等价的,除非命令行参数是一个 ANSI 字符串,Unicode 版本永远是首选如果是 Unicode 版本,你可以传递一个 ANSI 字符串,反之不可

  5. 可以通过 GetCommandLine 函数获取命令行参数,这个函数返回一个单一的字符串。

  6. 获取参数的数组样式,可以通过 CommandLineToArgvW 函数完成。

  7. 编译器是怎样知道调用 wWinMain 还是调用标准的 main 函数?
    实际情况下,在微软的 C 运行时库(CRT)中提供了一个 main 函数实现,其内部会调用 WinMain 或者 wWinMain
    CRT 中 main 函数的内部在调用 wWinMain 之前做了一些额外的工作
    例如初始化一些静态成员或者其它 C 函数的初始化操作等等。虽然你可以手动指定不同的链接不同的入口函数,但是仍然推荐你使用 CRT 默认提供的入口点函数,否则 CRT 内部的一些代码将被会跳过,有可能会导致一些异常的结果。

  8. 空的 WinMain 函数:

INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    PSTR lpCmdLine, INT nCmdShow)
{
    return 0;
}

🍃博主昵称:一拳必胜客
🌸博主寄语:欢迎点赞收藏关注哦,一起成为朋友一起成长;

 特别鸣谢:木芯工作室
特别鸣谢:木芯工作室 、Ivan from Russia
部分来源:https://meishizaolunzi.com/winmain-ying-yong-cheng-xu-ru-kou-dian/

我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=1noqb14tvyjrm

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/4815.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微信小程序开发(超详细保姆式教程)

介绍: 微信里面app,16年推出 竞品:支付宝小程序,钉钉,美团,头条,抖音qq小程序 优点 1,在微信里面自由分享,2,不用下载app,3,能快速的开发&#xf…

【MySQL】如何把Windows上的MySQL数据库迁移到Linux服务器上

目录1. 前言2. 物理备份与逻辑备份3. mysqldump实现逻辑备份4. 逻辑恢复1. 前言 最近在学黑马的《瑞吉外卖》,前期的基础版本一致在 Windows 电脑上开发,包括 MySQL 数据库也是安装在 Windows 电脑上。最近才学到优化篇,安装了 Linux 虚拟机…

【成为红帽工程师】第二天 ssh远程连接服务器

目录 一、远程连接服务器 二、连接加密技术 三、ssh远程连接服务 四、sftp用法介绍 五、相关实验 一、远程连接服务器 (一)什么是远程连接服务器 远程连接服务器通过文字或图形接口方式来远程登录系统,让你在远程终端前登录linux主机…

2022年最新山东交安安全员模拟真题及答案

百分百题库提供交安安全员考试试题、交安安全员考试真题、交安安全员证考试题库等,提供在线做题刷题,在线模拟考试,助你考试轻松过关。 43.危险性较大工程专项施工方案需要论证的,应当由建设单位组织召开专家论证会。 答案&#…

计算机毕业设计SSM财务管理系统【附源码数据库】

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

计算机毕业设计SSM城市智能公交系统【附源码数据库】

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

MyBatis(4)---多表查询

多表查询: 一对一:一篇博客对应着一个作者 一对多:一个作者对应着多篇博客 ResultMap和ResultType的区别: 1)字段映射不同:resultType适用于数据库字段名和实体类的名字是相同的,但是假设实体类的名字叫做username,但是数据库的名字是name,这…

MyBatis(3)

我们在进行指定ID进行删除的时候还可以加上一个属性:表示要传递的参数的类型是啥 <delete id"Delete" parameterType"java.lang.Integer">delete from user where userID#{userID}</delete> 我们现在先实现一个场景----我们来进行查询一下User…

【毕业设计】大数据共享单车数据分析系统 - python

文章目录0 前言1 项目背景2 项目分析思维导图3 项目分析具体步骤3.1 读取数据3.2 数据分析3.1.1 数据预处理——每日使用量分析3.1.2 连续7天的单日使用分析结论3.1.3 数据预处理——每日不同时间段的使用量分析3.1.4 每日不同时间段使用量分析结论3.1.5 数据预处理——骑行距离…

【C++】智能指针

一、资源的管理 RAII:Resource Acquisition Is Initialization的简称&#xff0c;其翻译过来就是“资源获取即初始化”&#xff0c;即在构造函数中申请分配资源&#xff0c;在析构函数中释放资源&#xff0c;它是C语言中的一种管理资源、避免泄漏的良好方法。 C语言的机制保证…

python快速实现简易超级玛丽小游戏

《超级玛丽》是一款超级马里奥全明星的同人作品&#xff0c;也是任天堂公司出品的著名横版游戏。 《超级马里奥》是一款经典的像素冒险过关游戏。最早在红白机上推出&#xff0c;有多款后续作品&#xff0c;迄今多个版本合共销量已突破4000万套。其中的主角马里奥、路易、碧琪…

[附源码]计算机毕业设计JAVAjsp闲置物品线上交易系统

[附源码]计算机毕业设计JAVAjsp闲置物品线上交易系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM …

tensor和numpy相互转换

tensor转成numpy b a.numpy()import torcha torch.arange(5) b a.numpy() print(a) print(type(a)) print(b) print(type(b))numpy转成tensor b torch.tensor(a)import torch import numpy as npa np.ones(5) b torch.tensor(a) print(a) print(type(a)) print(b) prin…

Spring Cloud框架(原生Hoxton版本与Spring Cloud Alibaba)基础入门篇 ---- 搭建环境

springcloud官方文档&#xff08;Hoxton SR5&#xff09;&#xff1a;https://cloud.spring.io/spring-cloud-static/Hoxton.SR5/reference/htmlsingle/ springcloud中文文档&#xff1a;https://www.springcloud.cc/ springcloud中国社区文档&#xff1a;http://docs.springcl…

【C++】栈~~(很详细哦)

在前几天&#xff0c;我们刚一起学过顺序表&#xff0c;链表&#xff08;无头单向不循环&#xff0c;有头双向循环&#xff09;&#xff0c;这两种都属于线性表因为是一系列存储的。而以后的哈希表则是散列表 今天我们看一下栈 目录 1.栈的介绍 2.实现 3.题目 1.栈的介绍 …

mindspore::dataset::GetAffineTransform的输出与cv2的输出不同

在使用C进行推理时用到了函数mindspore::dataset::GetAffineTransform&#xff0c;但是输入相同的数据后&#xff0c;与Python的cv2中的同名函数cv2.getAffineTransform所输出的结果不同。 C Ascend310端测试核心代码 #include <iostream> #include <vector>#…

synchronized 关键字背后的锁升级流程

文章目录前言一、基本特点二、加锁过程总结前言 博主个人社区&#xff1a;开发与算法学习社区 博主个人主页&#xff1a;Killing Vibe的博客 欢迎大家加入&#xff0c;一起交流学习~~ 一、基本特点 结合多线程锁的策略, 我们就可以总结出, Synchronized 具有以下特性(只考虑 J…

基于51单片机的智能台灯设计

一.硬件方案 本文介绍了一种基于PWM调光的智能台灯设计。把单片机技术和PWM调光技术结合起来实现台灯光强的调节。即在不改变PWM方波周期的前提下&#xff0c;利用单片机控制PWM的占空比&#xff0c;从而来改变电压的大小实现灯光亮度的调节。 当人体在台灯的范围内且环…

linux驱动设备节点失踪之迷雾围城

前言 参考文章&#xff1a;无法生成设备节点 最后证实&#xff1a;是bootargs配置错误导致的&#xff0c;不过中间发现也是可以通过mdev -s间接解决的&#xff0c;算是学习经验吧。 misc驱动框架是linux内核驱动中最简单实用的框架了。记录一下今天调试misc驱动的问题。misc驱动…

笔试强训48天——day19

文章目录一. 单选1.二分查找的时间复杂度&#xff08;&#xff09;2. 有一个单向链表中有一个A、B两个相邻元素&#xff0c;有一个指针p指向元素A&#xff0c;现将一个指针r指向的S元素要插入3. 双向链表中有两个指针域,llink和rlink分别指向前驱和后继,设p指向链表中的一个结点…