格式化对话框的布置性,仿printf的messagebox弹窗函数

by admin on 2019年2月4日

  刚开头读书Windows程序设计,磕磕碰碰,先做个小笔记缓缓神经,重即使将MessageBox这些Windows
API函数的。

目录

在编制窗口程序的时候,平常索要利用messagebox函数,不管是调剂输入也好,查看变量也罢。这时假使是全字符串的还好,可是如若急需出示数值的内容时,用这些函数就相比较费力了。必要先采用wsprintf函数执行五遍,然后在选择messagebox函数。远没有在命令行下的printf方便,倘若是须要大批量弹窗时就更麻烦了。所以决定将那多少个函数封装起来,那样messagebox就可以和printf函数一样方便使用了。最终经过二日时间,达成了那么些Unicode编码的函数,时期碰着了重重难题,通过四回次单步调试,查看汇编代码最后化解掉了有着标题,函数能正常使用了。

首先想起下C语言在支配台下通过正规输入输出函数输出”Hello,world!”的次序,
代码如下

  MessageBox函数是众三个人刚开始攻读Windows程序设计照旧是Windows
API蒙受的率先个放置函数,那个函数使用的点子是:

2.1       Windows数据类型.. 1

home88一必发 1

#include <stdio.h>

int main()
{
    printf( "Hello,world!\n" ) ;
    return 0 ;
}

  MessageBox(NULL, TEXT(“弹出框内容”),
TEXT(“标题”), MB_OK);

2.1.1       Windows数据类型示例.. 1

源码

然后前些天上了第一趟VC++课后,学会了Windows版Hello,world!,代码如下:

  初次之外,它还有多少个姐妹:

2.1.2       Windows 数据类型与规范C 数据类型的关系.. 5

/*——————————————————-*/

#include<windows.h>

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow )
{
    MessageBox( NULL, TEXT("Hello,world!"), TEXT("MessageBox"), 0 );

    return 0;
}

格式化对话框的布置性,仿printf的messagebox弹窗函数。  MessageBoxA(NULL, “弹出框内容”,
“标题”, MB_OK);   // TEXT可有可无

2.1.3       Windows 数据类型与Windows API 5

/* 函数名称: 御坂高级弹窗音信 – 限长2000限参100 Unicode

在VC6.0环境下,新建WIN32
Application,选中C++Sources文件,添加cpp文件后,敲出如上代码,编译,运行,出现上面窗口:

  MessageBoxW(NULL, L””, L””, MB_OK);  
                    // 那些L用来代表Unicode,不可以大约

2.1.4       Windows 中的数据结构.. 6

/*格式化对话框的布置性,仿printf的messagebox弹窗函数。 函数参数: 第三个是字符串,和printf一样,不定参数个数

home88一必发 2

  其实之所以有这多少个是因为微软须求满足Windows
98之后对汉字等其余语言编码的需要,那种必要通过Unicode完成,不过微软本意不是要我们使用Unicode来编程,而是经过拔取“通用”方式,也就是MessageBox();函数,完毕差其他编码主要依然经过IDE集成开发条件下转移区其他编码格局。回到MessageBox();,今天比较高烧的是,怎么在MessageBox();中落到实处变量的打印呢?

2.2       Windows API 的成效分类.. 7

/* 使用验证: 弹窗的内容可以动用任意多少个参数,类型暂时只接济 %d 和 %s

以此对话框中, 有标题栏, 标题栏的始末是”HELLO”,
对话框的内容为”Hello,world!”, 还有一个”确定”按钮, 而且,
没有丰硕黑框框窗口, 一切看起来都是那么美好,
来一起看看那段Windows版的Hello,world!吧!

  似乎C语言中不时应用printf函数,那些函数挺有意思的,应为函数输入的参数是绝非界定个数的,约等于是随机改变的。例如:

2.2.1       系统焦点服务.. 7

/*——————————————————-*/

*关于windows.h头文件:
    在windows.h这么些头文件中, 实际上已经包涵了多少的其余有关的头文件,
用书上的话说, windows.h是个分外主要的盈盈文件,
其中带有的别样相比较重大的头文件有:
    ■ WINDEF.H              基本数据类型定义
    ■ WINNT.H                协理Unicode的类型定义
    ■ WINBASE.H           内核函数
    ■ WINUSER.H           用户界面函数
    ■ WINGDI.H             图像设备接口函数
而是自己依然好奇windows.h到底包蕴了这几个头文件, 找到VC6的设置目录,
打开Include文件夹, 找到WINDOWS.H并打开, 虽说看不太懂,
但找#include关键词仍旧无压力的.
除了上边的5个还有:
    ■ WINRESRC.H      ■ EXCPT.H              ■ STDARG.H            ■
WINNLS.H            ■ WINCON.H
    ■ WINVER.H          ■ WINREG.H         ■ WINNETWK.H       ■
CDERR.H             ■ DDE.H
    ■ DDEML.H            ■ DLGS.H             ■ LZEXPAND.H         ■
MMSYSTEM.H       ■ NB30.H
    ■ RPC.H                 ■ SHELLAPI.H        ■ WINPERF.H           ■
WINSOCK2.H       ■ MSWSOCK.H
    ■ WINSOCK.H        ■ WINCRYPT.H       ■ COMMDLG.H         ■
WINSPOOL.H       ■ OLE.H
    ■ OLE2.H               ■ WINWLM.H          ■ WINSVC.H            ■
MCX.H                 ■ IMM.H

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 int main(){
 5
 6     int x=100, y=200, z=300;    
 7     
 8     printf("%d %d %d.\n", x, y, z);
 9     system("pause");
10     return 0;
11 }

2.2.2       系统管理.. 9

VOID MSKMessageBox(PTSTR string, …){

*先后的入口
在Win32控制台程序(Win32 Console Application)中,
应用程序的输入为main()函数,
windows程序的先后入口和win32控制台程序的进口类似, 为WinMain()函数.
程序的入口函数在WINBASE.H作出了声称, 申明如下:

 

2.2.3       用户界面.. 9

UINT num = 0;

int
WINAPI
WinMain(
    HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nShowCmd
    );

  这么些printf函数不仅可以利用多少个参数打印,仍可以用来一向打印变量,可是MessageBox却不可能一向打印,这一个引起自己的直接思考。我先想到的是赤手空拳一个缓冲区,利用那个缓冲区取打印字符数量。当然打印的函数得利用sprintf了

2.2.4       图像和多媒体.. 15

__asm{//获取字符串的长度,Unicode版本

其间由申明可以看到, WinMain函数的重临值被定义为int型;
WINAPI为WinMain函数的调用规则, 在WINDEF.H对”WINAPI”作出了如下宏定义:

  

2.2.5       网络.. 15

//int 3

#define WINAPI __stdcall

 1 int main(){
 2     
 3     int a = 12;
 4     char szBuffer[100];             // 使用一个字符数组来做缓冲区
 5 
 6     sprintf(szBuffer, "helloworld %d.\n", a);
 7     _snprintf(szBuffer, 100, "helloworld %d.\n", a);
 8         // 使用_snprintf函数比较安全,因为可以输入限定字符的个数  
 9 
10     printf("%s.\n", szBuffer);
11     puts(szBuffer);                            // 可以使用printf中的%s将szBuffer打印出来,或者用puts直接输出
12     //printf("helloworld.\n");
13 
14     system("pause");
15     return 0;
16 }

2.2.6       其他职能.. 15

mov eax, string//得到字符串的地点

声明, WinMain函数的调用规则为”__stdcall”方式,
对于”__stdcall”调用规则, 现在临时先不去探究, 知道有这么回事就行,
未来会详细了然到的, 现在假诺深究”__stdcall”就离开了那篇博文的主旨。

 

2.3       Windows API核心DLL. 16

sss:

 

  那么些缓冲区的方法假诺用在MessageBox函数里面,就可以完成打印变量的法子,比如以下代码:

2.3.1       Kerne132.dll 16

xor ebx,ebx//清零寄存器

*WinMain函数的参数:
1>. WinMain的率先个参数 HINSTANCE hInstance,
用书上的演说为”实例句柄”, 由于第五次接触C语言Windows程序设计,
对这么些句柄的定义也不是很了解, 去完善了下,
句柄的诠释为”一个句柄是指使用的一个唯一的平头值,即一个四字节长的数值,来申明应用程序中的分歧对象和同类对象中的不一样的实例,诸如,一个窗口,按钮,图标,滚动条,输出设备,控件或者文件等。”——引用自百度百科->句柄。

#include <windows.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow){
    int a = 12;

    TCHAR szBuffer[100];                  // 通用版本
    _stprintf(szBuffer, TEXT("hello 通用 %d"), a);
    MessageBox(NULL, szBuffer, TEXT("通用"), MB_OK  | MB_ICONINFORMATION);

    return 0;
}

2.3.2       User32.dll 16

mov bx,word ptr [eax]//获取该地址的两字节的值,赋值给bx

笔者是那样对句柄举行精晓的, 在一个应用程序中,
寻常创设了累累的窗口、按钮、标签, 或者应用了一个文件等,
在先后的此外地方, 只要可以取得这些被喻为句柄的事物,
就可见找到该控件或者窗口在内存中的地方,
从而对其开展操作。感觉有点像带参数的main函数,
只是此处的主函数参数为一个句柄。

 

2.3.3       Gdi32.dll 16

add num,1//计数+1

2>. WinMain函数的第四个参数, 同样是个实例句柄,
但书上又进一步表明说在32位的Windows程序设计中,
WinMain函数的实例句柄概念已不复利用,
由此WinMain的第一个参数平时总是NULL。

  可是每一遍都写个缓冲区来存放在,并且一不下心忘记行使_snprintf函数,那就GG了,很可能爆发缓冲区溢出的高危。因而,那里运用printf原先函数设计的规律,我们也来设计一个MessageBoxPrintf();函数,用这一个函数来贯彻格式化输出的职能,要贯彻那几个函数,首先得参考printf();函数的贯彻原理。

2.3.4       标准C函数.. 17

add eax, 2//地址偏移+2

小编的眼光: 感觉立马就要晕了, 疑问一:
“由此WinMain的第三个参数寻常总是NULL”,
那么首先个呢?WinMain的第二个参数会不会也足以是NULL呢? 疑问二:
WinMain函数的参数从何而来?是操作系统么?带着疑问继续向下看。

int my_printf(const char * szFormat, ...){

    int iReturn;
    va_list pArgs;

    va_start(pArgs, szFormat);
    iReturn = vprintf(szFormat, pArgs);
    va_end(pArgs);

    return iReturn;
}


int main(){

    int x=100, y=200, z=300;

    printf("hello %d, %d, %d.\n", x, y, z);        
    my_printf("test_my_printf,哈哈%d %d.\n", x, y);

    system("pause");
    return 0;
}

2.3.5       其他Dll 17

test bx, bx//判断bx是或不是为0

3>. WinMain的第一个参数是用来运作程序的命令行, PSTR:
用来针对一个字符串的指针类型, szCmdLine, sz:表示以0最终的字符串;
目标是通过命令行格局运行程序并向主函数中传唱参数,
应该就像是给main函数传入参数一样;

 

2.4       Unicode和多字节.. 17

jne sss//假使不是0则循环

4>. WinMain的第七个参数是一个int型参数,
用来指明程序(窗口)最初如何被展现, 例如最小化?最大化?全屏?
小编的见解: 应该很有用, 平日见一些游乐一启动就是全屏的,
不过以此参数也是担心系统传给程序的么?因为从平常运行Windows程序时都是直接双击,
并没有经过命令行给它传到参数,
在编程时应该对程序启动时的突显格局有交代才对,
那样系统再运行时再把这一个交代的参数传入给程序告诉程序启动时应该怎么突显.

  …表示的情致是传播的参数是可变参数个数的,va_start(pArgs,
szFormat);表示指向szFormat之后的一个参数,那个函数的洋洋事物本身现在也还没精通过来,之后再来补充,不过现在仿效这么些函数大家可以协调写个MessageBoxPrintf();函数,具体代码如下:

2.4.1       W版本和A版本的API 21

}

*WinMain函数函数体的MessageBox函数:
MessageBox(), 名如其”人”, 不用猜也知道那个就是显得一个对话框的函数,
打开API文档,MSDN Library通过索引找到MessageBox函数, 发现其声称如下:

// 自己做一个格式化的messageboxprintf对话框
int CDECL MessageBoxPrintf(TCHAR * szCaption, TCHAR * szFormat, ...){

    TCHAR szBuffer[1024];
    va_list pArglist;

    va_start(pArglist, szFormat);
    _vsnprintf(szBuffer, sizeof(szBuffer)/sizeof(TCHAR), szFormat, pArglist);
    va_end(pArglist);

    return MessageBox(NULL, szBuffer, szCaption, MB_OK | MB_ICONINFORMATION);
}


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow){

    int x=100, y=200, z=300;
    int cxScreen, cyScreen;

    cxScreen = GetSystemMetrics(SM_CXSCREEN);
    cyScreen = GetSystemMetrics(SM_CYSCREEN);

    // MessageBoxW(NULL, L"helloworld", L"biaoti", MB_OK);
    // MessageBoxA(NULL, TEXT("helloworld"), TEXT("biaoti"), MB_OK);
    MessageBoxPrintf(TEXT("我的标题"), TEXT("hello %d %d %d"), x, y, z);    // 把这个函数做好后,直接就可以输出
    MessageBoxPrintf(TEXT("我的屏幕大小"), TEXT("我的屏幕宽度是:%d.\n高度是:%d.\n"), cxScreen, cyScreen);


    return 0;
}

2.4.2       Unicode与ASGII的转换.. 22

TCHAR str[2001] = {0};//最多2000的字节内容,倘使领先2000就回来错误

int MessageBox(
  HWND hWnd,          // handle of owner window, 窗口的一个句柄
  LPCTSTR lpText,     // address of text in message box,
一个文件(字符串)的指针
  LPCTSTR lpCaption,  // address of title of message box,
标题字符串的指针
  UINT uType          // style of message box, 对话框的作风
);

  相当于自己统筹出来一个像样printf的小工具,因为微软真的并未布署MessageBox中举办格式化输出的函数。

2.4.3       对Windows程序设计规范的指出.. 22

DWORD straddress[100] = { 0 };//字符串参数地址,最多100个

在地点示例中对MessageBox函数的调用如下:

2.5       小结.. 23

INT param = 0;//参数个数

MessageBox( NULL, TEXT(“Hello,world!”), TEXT(“MessageBox”), 0 );

 

INT strnum = 0;//新的字符串的计数

第四个参数窗口的句柄的实参为NULL, 意思为不属于此外窗口.
其次个参数为对话框的情节, 第两个参数为对话框的标题,
不过那多少个参数都选取了一个TEXT()的函数,
书上讲使用TEXT()的目的是将那几个字符串打包到TEXT宏代码里面,
作者尝试了不要那个TEXT()函数而直接像那样:

 

INT arrnum = 0;//数组的计数

MessageBox( NULL, “Hello,world!”, “MessageBox”, 0 );
在VC6.0不会报错,在VS2010下会报错,这几个TEXT其实是为着协理不相同字符编码的预编译设置,若是定义了UNICODE宏,则TEXT(“”str“”)展开为宽字符串L“str”,反之则展开为“str”。那么些题材自己查了许多资料,详细都记在记录本中。

 

DWORD ebpnum = 0;//先获得EBP的基址

home88一必发 3

2.1    Windows数据类型

Windows API 使用了不胜枚举 Windows 自己定义的数据类型。读者或许较为熟习 C
语言或 C++语言的数据类型。要了解使用 Windows API 必须求熟识 Windows
数据类型。这么些数据类型是Windows 特有的。在 SDK 的相关头文件中有定义。

在不少的Windows 数据类型中,最常用的有
DWORD、HANDLE、LPTSTR、WORD、BYTE、CHAR 等。在 Windows 系统中,DWORD
用于表示无符号整型的多少,意为 double word,32位。

在一般景观下 BYTE 是 8 位的,而 WORD 是 16 位,DWORD 就是 32 位的。

Windows 系统的应用程序中还兼具一个蓄意的数据类型-HANDLE,寻常 HANDLE
类型的变量用于唯一标识一个“对象”,如窗口、控件、文件等,Windows
平罗利留存不少这么的目的,对象是先后操作的靶子。HANDLE 也是一个 32
位的数据类型。

DWORD temp;//用来收获数字的值的

home88一必发 4

2.1.1    Windows数据类型示例

实例2-1施用了三种为主的 Windows 数据类型,演示 Windows
数据类型在程序中的使用方法。

  1. 实例2-1 常用Windows数据类型演示(DWORD/LPSTR/CHAR/INT)

本实例定义了多少个常用常量的 Windows 数据类型,包涵 DWORD,LPSTR 和
CHAR,并演示了哪些运用它们举办了复制、相比大小等操作。

/* ************************************
*《精通 Windows API》 
* 示例代码
* windata.c
* 2.1.1  常用的 Windows 数据类型
**************************************/
/* 头文件  */
#include <windows.h>
#include <stdio.h>
/* ************************************
* 功能  Windows 数据类型演示
**************************************/
int WINAPI WinMain( 
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow
)
{
//定义字符串
LPSTR szString = "Windows data type, string.";
//定义字符数组
CHAR lpString[120];//要大于 szString 的长度
//定义 DWORD 类型的数据
DWORD dwMax = 0xFFFFFFFF;
DWORD dwOne = 0x1;
//定义 INT 类型的数据
INT iMax = 0xFFFFFFFF;
INT iOne = 0x1;
//显示字符串
MessageBox(NULL,szString,"LPSTR",MB_OK);
//复制内存,将字符串复制到数组中(包括 NULL 结束符)
CopyMemory(lpString, szString,lstrlen(szString)+1);
//显示复制的字符串
MessageBox(NULL,lpString,"CHAR[]",MB_OK);
//比较 DWORD 并显示结果
if(dwMax>dwOne)
{
MessageBox(NULL,"DWORD 类型的数据 OxFFFFFFFF > 0x1","DWORD",MB_OK);
} 
//比较 INT 并显示结果
if(iMax<iOne)
{
MessageBox(NULL,"INT 类型的数据 OxFFFFFFFF < 0x1","INT",MB_OK);
}
return 0;
}

 

 

在那一个程序中,使用了 4 种 Windows 数据类型,分别是 LPSTR、CHAR、DWORD 和
INT。

home88一必发,LPSTR 类型的数目是字符串,也就是字符指针,CHAR 是字符,DWORD 是 32
位的无符号整数,INT 是 32 位有号子整数。程序运行后会弹出 4
个对话框。那表达 dw马克斯>dwOne 是白手起家的。i马克斯<iOne 也是建立的。dwMax与 i马克斯 的数值是同样的,dwOne 与 iOne
的数值也是同样的。不过比较结实差距,是因为两者的数据类型不均等。

 

  1. 翻开Windows数据类型的定义

在 Visual Studio
中得以查看数据类型的概念。在数据类型的体系名(比如“DWORD”)上单击右键,选取“转到定义”,如图
2-1 所示。

 home88一必发 5

图2-1

可以从 SDK 的头文件中来看各品种的类型定义。

“INT”的定义如下:

 typedef int                 INT;

 

“DWORD”的定义如下:

 typedef unsigned long       DWORD;

 

“CHAR”的概念如下:

 typedef char CHAR;

 

    从中能够发现,这几个 Windows 数据类型都是从标准 C
的数据类型经过类型重定义而来。INT 数据类型是有号子整型,DWORD
数据类型是无符号整型。 那就印证了怎么在实例 2-1 中 INT 数据类型的变量
i马克斯 实际是“-1”,而 DWORD 类型的变量 dwMax实际是“4294967295”,所以会油但是生如上的可比结实。

  1. 最广泛的Windows数据类型

表2.1 常用的着力Windows数据类型

类型

描述

BOOL

布尔型变量(值只能是True或False)

BYTE

字节类型(8位)

CHAR

8比特字节(ANSI)

CONST

常量,相当于标准C中的”const”关键字

DWORD

32字节无符号整型数据

DWORD32

32字节无符号整型数据

DWORD64

64字节无符号整型数据

FLOAT

浮点数据类型

HANDLE

对象的句柄,最基本的句柄类型

HICON

图标的句柄

HINSTANCE

程序实例的句柄

HKEY

注册表键的句柄

HMODULE

模块的句柄

HWND

窗口的句柄

INT

32位符号整型数据类型

INT_PTR

指向INT类型数据的指针类型

INT32

32位符号整型

INT64

64位符号整型

LONG

32位符号整型,相当于C语言的标准数据类型long

LONGLONG

64位符号整型

LONG32

32位符号整型

LONG64

64位符号整型

LPARAM

消息的L参数

WPARAM

消息的W参数

LPCSTR

Windows(ANSI)字符串常量

LPCTSTR

根据环境配置,如果定义了UNICODE宏,则是LPCWSTR类型,否则是LPCSTR类型

LPCWSTR

UNICODE字符串常量

LPDWORD

指向DWORD类型数据的指针

LPSTR

Windows(ANSIC)字符串常量

LPTSTR

根据环境配置,如果定义了UNICODE宏,则是LPTSTR类型,否则是LPSTR类型

LPWSTR

UNICODE字符串常量

SHORT

无符号短整型(16位)

SIZE_T

表示内存大小,以字节为单位,其最大值是CPU最大寻址范围

TCHAR

如果定义了UNICOD,则为WCHAR,否则为CHAR

UCHAR

无符号CHAR

UINT

无符号INT

ULONG

无符号LONG

VOID

无类型,相当于标准C语言的void

WCHAR

16位Unicode字符

WINAPI

Windows API的函数调用方式,常见于SDK头文件中对API函数的声明中,相当于__stdcall(更严格讲,不是数据类型,而是函数调用约定)

WORD

16位无符号整型数据

  1. Windows数据类型名称命名的规律

Windows 数据类型的命名都很有规律。

焦点数据类型包涵 BYTE、CHAR、WORD、SHORT、DOWRD、INT 等。

指针类型的一声令下格局相似是在其针对性的数据类型前加“LP”或“P”,比如对准
DWORD的指针类型为“LPDWORD”和“PDWORD”。

各个句柄类型的命令形式一般都是在目的名前加“H”。Windows
系统中有不少对象,所有表示一个目标的数据类型都是句柄,每一种对象都对应着一种句柄类型,比如与位图(
BITMAP)对应的句柄类型为“HBITMAP”,与菜单(MENU)对应的句柄类型为“HMENU”,与窗口(WINDOW)对应的句柄类型为“HWND”。无符号类型一般是以“U”早先,比如“INT”是标志类型,“UINT”是无符号类型,“LONG”是符号类型“ULONG”是无符号类型等。

UINT i;

第一个参数为对话框的作风, 一些以MB_开头的有的常量的三结合,
可以选择OR(|)运算进行结合, 这么些常量定义在WINUSER.H中, 例如常用的有:

2.1.2    Windows 数据类型与规范C 数据类型的涉及

翻开 Windows 数据类型的概念可以观察,所有的 Windows 数据类型都是由 C
数据类型经过类型重定义获得的。如 DWORD 实质上就是 unsigned long
数据类型,32 位的无符号整型:

typedef unsigned long       DWORD;

 

其实 VC 编译器是一个完全的 C 编译器,别的并从未过多的扩张。Windows
数据类型也不是 VC 的内建档次,而从标准 C 类型重定义得到。

for (i = 0; i< num&& i< 2000; i++){

1>.对话框按钮类型:

2.1.3    Windows 数据类型与Windows API

Windows API 函数的参数、重临值或局地关键的常量使用的数据类型都是 Windows
数据类型。如:

int MessageBox(
HWND hWnd,
LPCTSTR lpText,
LPCTSTR lpCaption, 
UINT uType
);

 

MessageBox 函数的重临值是 int 型的,是正规 C
数据类型,然则拥有的参数都选取了Windows 数据类型。如 HWND 是一种 W
indows 数据类型,用于表示窗口的句柄;LPCTSTR 也是Windows
数据类型,表示字符串常量;UINT 也是 Windows 数据类型,为无符号整型。

if (string[i] == ‘%’ && (string[i + 1] == ‘d’ || string[i + 1] ==
‘s’)){

    #define MB_OK                       0x00000000L           
//仅有一个”确定”按钮
    #define MB_OKCANCEL                 0x00000001L           
//”确定” + “取消”
    #define MB_ABORTRETRYIGNORE         0x00000002L           
//”终止” + “重试” + “忽略”
    #define MB_YESNOCANCEL              0x00000003L            //”是”

2.1.4    Windows 中的数据结构

Windows 中包含很多种数据结构类型,在不相同品种的 API
中会使用到不相同的数据结构,由于数据结构的数量众多,将在继续章节具体的实例中牵线已毕每一种意义所利用的数据结构。数据结构平常会作为一些
API 的参数输入。

typedef struct _WIN32_FILE_ATTRIBUTE_DATA{
DWORD    dwFileAttributes;
FILETIME  ftCreationTime;
FILETIME  ftLastAccessTime;
FILETIME  ftLastWriteTime;
DWORD    nFileSizeHigh;
DWORD    nFileSizeLow;
} WIN32_FILE_ATTRIBUTE_DATA,*LPWIN32_FILE_ATTRIBUTE_DATA;

 

相当于:

typedef struct _WIN32_FILE_ATTRIBUTE_DATA{
DWORD    dwFileAttributes;
FILETIME  ftCreationTime;
FILETIME  ftLastAccessTime;
FILETIME  ftLastWriteTime;
DWORD    nFileSizeHigh;
DWORD    nFileSizeLow;
};
typedef _WIN32_FILE_ATTRIBUTE_DATA WIN32_FILE_ATTRIBUTE_DATA;
typedef _WIN32_FILE_ATTRIBUTE_DATA *LPWIN32_FILE_ATTRIBUTE_DATA;

 

Windows SDK 中,结构体也有谈得来的命名规范。一般景况下,Windows
系统中动用全大写来命名结构体、共用体,并动用“_”来分隔单词,在构造名加“LP”或“P”表示针对数据结构的指针。

param++;

  • “否” + “取消”
        #define MB_YESNO                    0x00000004L            //”是”
  • “否”
        #define MB_RETRYCANCEL              0x00000005L           
    //”重试” + “取消”

2.2    Windows API 的效益分类

Windows API
所能实现的功能包涵过多下面,在举办应用程序的付出时,开发人士可能会利用到文件、进度、内存、权限、系统音信等系统的主导服务和连串管理类的
API,可能会用到图形用户界面、控件等函数和对象,可能须要在界面上制图图像处理多媒体音信等,还包括开展互联网通讯支出等。

__asm{

 

2.2.1    系统主题服务

系统焦点服务是 Windows API
最基本的始末,是最常使用到的程序接口。系统中央服务API 蕴涵以下多少个地方。

  1. 文件系统

对文本的基本操作包罗文件的创导、打开、读写、关闭、删除,文件属性的安装与收获,目录操作,以及磁盘分卷的操作,还包蕴镜像文件、加密文件系统等。

  1. 内存管理

首借使内在的分配、共享、释放等情节,包罗虚拟内存管理、分页机制、堆管理等。

  1. 进度、线程和模块

包涵经过主程序(
exe)、模块、动态链接库(dll)的编制;线程的基本概念,线程创造、遍历、同步等操作;进程与权力;线程与纤程等内容。

  1. 配备 I/O、驱动程序控制

包罗设备对象等基本概念。加载与卸载驱动程序,控制驱动程序,与驱动程序通讯等。

  1. 调剂与错误处理

概括怎么着支付调试器,程序运行错误的处理,日志的笔录、Windows
可执行文件的社团等。

  1. Windows 系统音信

概括注册表的操作,如打开注册表,读取、写入键值,创立、删除键;还包罗系统主题信息的收获和装置,如系统目录、系统版本、统计机名等。

  1. 进度间通讯

包含使用共享文件举办进程间通讯的办法,使用音信举行进度间通讯的点子,使用邮槽、管道等举行进度间通讯的主意,使用互联网共享举办进度间通讯的法门。

  1. 定时器与音信机制

音信机制是 Windows 系统中很紧要的一种机制。大约拥有的 Windows
应用程序都在与新闻打交道,而 Windows
的信息机制又是珍爱于定时器的。所以驾驭 Windows 音信机制是读书Windows
应用程序开发的主要性内容。

  1. 其他

Windows
的系统基本服务还包涵品质监视、电源管理、索引与数量存储等,也将在本书中装有涉及。

  1. 实例 2-2 将系统目录音信写入 systemroot.txt

本实例使用了 Windows 系统主旨服务中的部分
API,已毕将系统目录路径写入文件中。在此地不对落成原理做过多的表明,只是使读者对
Windows 系统服务 API 有始发的垂询。

/* ************************************
*《精通 Windows API》 
* 示例代码
* basic.c
* 2.2 Windows API 的功能分类
**************************************/
/* 头文件  */
#include <windows.h>
/* ************************************
* 功能  获取系统目录信息,并存储到文件中
**************************************/
int main(int argc, TCHAR argv[])
{
//文件句柄
HANDLE hFile;
DWORD dwWritten;
//字符数组,用于存储系统目录
TCHAR szSystemDir[MAX_PATH];
//获取系统目录
GetSystemDirectory(szSystemDir,MAX_PATH);
//创建文件 systemroot.txt
hFile = CreateFile("systemroot.txt",
GENERIC_WRITE,
0,NULL,CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
//判断文件是否创建成功
if(hFile != INVALID_HANDLE_VALUE)
{
//将系统目录系统信息写入文件
if(!WriteFile(hFile,szSystemDir,lstrlen(szSystemDir),&dwWritten,NULL))
{
return GetLastError();
}
}
//关闭文件,返回。
CloseHandle(hFile);
return 0;
}

 

运作程序,在先后所在的目录会生成文书“systemroot.txt”,文件内容为系统目录。

mov dword ptr[ebpnum], ebp

2>.对话框中的图标类型:  

2.2.2    系统管理

系统管理是 Windows 系统中很主要的情节。Windows 系统提供了以下方面的 API
供应用程序开发人士使用,包蕴:管理控制台接口、程序安装、系统恢复生机、任务调度、Windows
运程管理。

}

#define MB_ICONHAND                 0x00000010L           
//一个红X的荒唐/甘休图标
#define MB_ICONQUESTION             0x00000020L           
//一个问号的垂询图标
#define MB_ICONEXCLAMATION          0x00000030L           
//一个藏灰色惊讶号的告诫图标
#define MB_ICONASTERISK             0x00000040L           
//一个带有i的信息提示图标

2.2.3    用户界面

用户界面开发是 Windows 应用程序开发的关键内容。Windows
用户界面首要包含多个部分,Windows Shell 和 Windows 图形用户界面。Windows
图形用户界面包含窗口对象的相关内容,界面资源,控件、用户数据互换(粘贴板等)和用户输入的拍卖。

  1. 窗口化

概括部分为主数据概念和目的:窗口类、音信对列、窗口进程(音信处理函数)、窗口属性等。
紧要概括的 API
有窗口类注册的函数、窗口建立与关闭函数、窗口属性修改函数等。

  1. 资源

资源是 Windows
应用程序中很紧要的一项内容,在可执行文件中,专门有用于存储资源的节。
这里所说的资源是界面资源,包括图标、菜单、字符串、版本新闻、对话框、动态光标、插入号(Carets)等。资源的处理涉嫌许多
API 函数。

  1. 用户输入处理

概括对话框、键盘加速器(火速键)、键盘输入、鼠标输入、原始数据输入等。那一个概念是程序通过用户界面与用户展开互动的基本概念。

  1. 数据调换

包含 Atom
表(包蕴了多少字符串和标识符)、粘贴板、数据复制、动态数据交接等基本概念,是用户和应用程序通过用户界面进行数据调换的最首要载体。

  1. Windows 图形界面通用控件

Windows 系统提供了不少于 30 种的控件供应用程序采用,其中最常用的二种包涵Edit控件(文本框)、Button 控件(按钮)、ListView 控件(列表)、ToolTip
控件(提醒框)、ComboBox 控件(下拉选拔框)、Tree-View
控件(树)、Rich-Edit 控件(多成效文本框)、Tab 控件(分页)、Process
控件(进程条)等。

  1. Windows Shell

Windows 桌面浏览器(explorer.exe)的作用强大,Windows Shell
应用程序可以运用WindowsShell
桌面的程序接口达到管理连串、定制图标和默认程序、伸张桌面功效等目标。

  1. 实例 2-3 窗口创立以及信息处理 basic.c

    / **《精通 Windows API》

    • 以身作则代码
    • window.cpp
    • 2.2 Windows API 的职能分类
      **/
      / 预处理 /
      / 头文件 /
      #include
      / 全局变量 /
      HINSTANCE hinst;
      / 函数扬言 /
      int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int);
      LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);
      /* **
    • 成效 突显一个窗口
      **/
      int WINAPI WinMain(HINSTANCE hinstance,
      HINSTANCE hPrevInstance,
      LPSTR lpCmdLine,
      int nCmdShow)
      {
      WNDCLASSEX wcx; // 窗口类
      HWND hwnd; // 窗口句柄
      MSG msg; // 信息BOOL fGotMessage; // 是还是不是成功获取音讯hinst = hinstance; // 应用程序实例句柄,保存为全局变量
      // 填充窗口类的数据结构
      wcx.cbSize = sizeof(wcx); // 结构体的分寸
      wcx.style = CS_HREDRAW |
      CS_VREDRAW; // 样式:大小改变时重绘界面
      wcx.lpfnWndProc = MainWndProc; // 窗口信息处理函数
      wcx.cbClsExtra = 0; // 不采用类内存
      wcx.cbWndExtra = 0; // 不使用窗口内存
      wcx.hInstance = hinstance; // 所属的应用程序实例句柄
      wcx.hIcon = LoadIcon(NULL,
      IDI_APPLICATION); // 图标:默认
      wcx.hCursor = LoadCursor(NULL,
      IDC_ARROW); // 光标:默认
      wcx.hbrBackground = (HBRUSH)GetStockObject(
      WHITE_BRUSH); // 背景:白色
      wcx.lpszMenuName = NULL; // 菜单:不应用
      wcx.lpszClassName = “MainWClass”; // 窗口类名
      wcx.hIconSm = (HICON)LoadImage(hinstance, // 小图标
      MAKEINTRESOURCE(5),
      IMAGE_ICON,
      GetSystemMetrics(SM_CXSMICON),
      GetSystemMetrics(SM_CYSMICON),
      LR_DEFAULTCOLOR);
      // 注册窗口类
      if(!RegisterClassEx(&wcx))
      {
      return 1;
      }
      // 创设窗口
      hwnd = CreateWindow(
      “MainWClass”, // 窗口名
      “CH 2-3”, // 窗口标题WS_OVERLAPPEDWINDOW, // 窗口样式
      CW_USEDEFAULT, // 水平地点 X:默许CW_USEDEFAULT, // 垂直地方 Y:默许
      CW_USEDEFAULT, // 宽度:默认
      CW_USEDEFAULT, // 中度:默认(HWND) NULL, // 父窗口:无
      (HMENU) NULL, // 菜单:使用窗口类的菜谱
      hinstance, // 应用程序实例句柄
      (LPVOID) NULL); // 窗口成立时数据:无
      if (!hwnd)
      {
      return 1;
      }
      // 突显窗口
      ShowWindow(hwnd, nCmdShow);
      UpdateWindow(hwnd);
      // 新闻循环
      while (
      (fGotMessage = GetMessage(&msg, (HWND) NULL, 0, 0)) != 0
      && fGotMessage != -1)
      {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
      }
      return msg.wParam;
      }
      /* **
    • MainWndProc
    • 职能 窗口音讯处理函数,
      对具有的信息都利用默许处理函数
      **/
      LRESULT CALLBACK MainWndProc(HWND hwnd,
      UINT uMsg,
      WPARAM wParam,
      LPARAM lParam
      )
      {
      switch (uMsg)
      {
      case WM_DESTROY:
      ExitThread(0);
      return 0;
      default:
      return DefWindowProc(hwnd, uMsg, wParam, lParam);
      }
      }

 

实例中,首先注册了窗口类,然后创制了一个窗口,创造窗口时指定的窗口的品质和窗口音讯的处理函数。函数音信的处理函数大多调用系统默许函数来处理。如下:

D:\002>cl window.cpp user32.lib gdi32.lib
用于 80x86 的 Microsoft (R) 32 位 C/C++ 优化编译器 15.00.21022.08 版
版权所有(C) Microsoft Corporation。保留所有权利。
window.cpp
Microsoft (R) Incremental Linker Version 9.00.21022.08
Copyright (C) Microsoft Corporation. All rights reserved.
/out:window.exe
window.obj 
user32.lib
gdi32.lib

 

运作效果:

 home88一必发 6

if (string[i] == ‘%’ && string[i + 1] == ‘d’){

还要, 在那几个图标中部分还能用其余名目代替,
这几个别名在WINUSER.H的概念如下:

2.2.4    图像和多媒体

Windows 的图像引擎和多媒体编程有种种接口,包涵最宗旨的
GDI、GDI+,以及更尖端的OpenGL、DirectX 等图像引擎编程接口。DirectX 和
OpenGL
在娱乐支付、动画制作等地点拔取比较常见,使用它们进行应用程序开发要求专门的
SDK。本书只讲解 GDI,对一般的应用程序开发,已经丰裕使用。

GDI
的基本概念包含图像(Image)、位图(Bitmaps)、笔(Pen)、画刷(Brush)、文本和字体(
Text and
Fonts)、线(Line)、区域(Regions)、形状(Shapes)等。其主题的法力是对突显设备开展控制、获取和修改相关安顿,在总计机显示屏上显得用户所急需出示的内容。

TCHAR number[11] = { 0 };//INT整数最多10位

#define MB_ICONWARNING              MB_ICONEXCLAMATION        
//警告
#define MB_ICONERROR                MB_ICONHAND               
//错误
#define MB_ICONINFORMATION          MB_ICONASTERISK           
//信息
#define MB_ICONSTOP                 MB_ICONHAND               
//停止

2.2.5    网络

用户使用 Windows API 可以支付基于各样网络协议的应用程序,例如 TCP\UDP
Socket、HTTP、DHCP、RPC、QOS、Bluetooth,以及写真、点对点文件传输、即插即用设备管理等。
仍能展开网络管理,包罗互联网的中坚音讯,使用 IP helper
获取互联网布局和网络新闻、进行互联网监视等。
同时微软还提供了进展网络安全编程的有些接口,紧如若防火墙 Windows、防火墙
API,以及部分 Windows 自带的网络应用程序的接口,包罗 IE、Outlook 等。

temp = ebpnum + 4 * param + 8;

 

2.2.6    其他效率

Windows API
能完成的出力还有很多,限于篇幅不可以一切介绍。有局地内容本书未涉嫌,可是Windows API 也提供了连带接口。

  1. 数码存储和走访、数据库

概括微软的“动态数据存取组件”技术(MDAC,包蕴了 ADO、ODBC)、OLE
数据库、XML 标准、微软 XML、可伸张存在引擎等多地方内容。首即使 Windows
系统内的数据库文件、Windows.系统对数据库的拜会接口等技术。

2.新闻与搭档

音讯与合作大多是 Windows
系统自带的局地应用程序所提供的花费接口。其中最重点的情节是“合作数据对象”(
CDO)。CDO 包含了若干种 Windows 数据传输典型应用,包涵 Mssager
(MSN)、邮件 SMTP (Outlook)应用接口等。

3.Web 开发

IIS(Intemet Information
Server,互连网新闻服务)等应用程序提供的付出接口,使用户可以一贯在
Windows 平台上举办 Web 开发,开发的程序运行于 ns
框架下。“数据存在与走访”、“新闻与搭档”、“Web 开发”等都可以归为 COM
开发的范围内。COM 是 Windows
应用程序接口的一种,具有定位的接口形式,大多是 Windows
系统中自带的应用程序所提供的开发接口的会见。

wsprintf(number, TEXT(“%d”), *(DWORD*)temp);


2.3    Windows API核心DLL

在 Windows 的系统目录中,存在器重重的动态链接库文件(DLL 文件)。那几个 DLL
文件中 包蕴了 Windows API 函数可执行程序。DLL
将各函数“导出”,这样应用程序就足以找到 DLL中的函数地址,当应用程序调用
Windows API 时,程序会运行到 DLL 中。API
函数根本设有于多少个基本的动态连接库文件中。Keme132.dll 是最要害的
DLL,Windows 系统最重大的连串服务 API 函数都设有于 Kerne132.dll
中。User32.dll 首要蕴涵图形用户界面中所使用到的一部分函数接口。 GDI32.dll
中,主要概括 Windows 图形引擎中的接口函数。

当用户调用一个 API 时,系统会透进程序文件中的导入表结构找到必要调用的
API 函数位于哪个 DLL,确定函数的地点,以便应用程序可以成功调用 API
函数。

int test = 0;

2.3.1    Kerne132.dll

Keme132.dll 包蕴了系统基本服务中最中央的 API
函数,如文件系统、进度与线程、内存管理等。 Windows XPSP2
系统中,Keme132.d11 有 949
个导出函数,例如,CreateFileA、CreateProcessA、OpenThread、SetFile提姆e
等。本书将在此起彼伏章节中经过实例介绍那些 API的施用。

test = lstrlen(number);

2.3.2    User32.dll

User32.dll 是 Windows
图形用户界面的要害支撑。一些主要的图形用户界面函数由User32.dll
函数导出。Windows XP SP2 系统中,User32.dll 有 732
个导出函数,例如CreateWindowExW、RegisterClassA 等。

memcpy(&str[strnum], number, lstrlen(number) * 2);//unicode

2.3.3    Gdi32.dll

Gd132.dll 是 Windows GDI 应用程序设计接口,Gdi32.dll
导出了与此相关的好多函数,如 GetTextColor、LineTo、TextOutA 等。

strnum += lstrlen(number);

2.3.4    标准C函数

专业 C 程序是一种标准,任何帮衬 C 语言应用程序开发的系统都应当提供 C
语言库函数的 调用。在系统环境下利用正规 C
进行程序支付时,用户所选择的库函数实际上是由操作系统提供的。正是由于各种主流操作系统都提供了一套标准
C 库所定义的函数接口,标准 C
函数库才会有如此大面积的超越操作系统平台。所以 C
程序还是凭借于操作系统开发人士为其得以完结接口,而 C
库函数的兑现依然凭借于操作系统提供的调用接口,如正式 C 函数 fopen
函数在Windows 系统中的完毕就依靠于 API CreateFile 函数(CreateFile
完结了文本的始建和开辟等操作)。

Windows 系统的 C 标准库函数接口主要设有于crtdll.dll 中。实际上,C
标准函数库必须由操作系统为其提供接口,否则使用正式 C
开发的主次不可能在一定的系统上运行。 Windows XP SP2 系统中,crtdll.dll 有
526 个导出函数,如 fopen、printf. strlen等。

i++;

2.3.5    其他Dll

自然,Windows 系统中的 DLL 文件远远不止那多少个,Windows
系统提供了分外丰裕而且作用强大的 API,上文已经介绍了 Windows API
所紧要依靠的多少个 DLL,其余的 DLL
库文件由于过分庞杂,就不一一介绍,将在继承的章节中具有涉及。读者只需求领会调用
Windows API 的基本原理就足以了。

} else{

2.4    Unicode和多字节

Windows 既可以应用 Unicode
字符集又可以利用传统的字符集(如多字节编码)来落到实处对各样语言的支撑,以适应国际市场的要求。与观念的字符集编码比较,Unicode
是社会风气通用的字符编码标准,使用 16 位数据表示一个字符,一共可以象征 65535
种字符,可以概括现代处理器中所使用的拥有字符,包涵各样字母、文字、在出版业中应用的特殊符号等。
传统的字符集,如 Windows ASNI 字符集,使用 8 位数据或将附近的多个 8
位的多少整合在协同表示特其余语言字符。Windows 系统运用了 ASNI
字符的恢弘方式,如若一个字节是负数,则将其持续的一个字节组合在一齐表示一个字符。那种编码格局的字符集也称之为“多字节”字符集。

在 Windows 系统中,Unicode 字符编码和多字节字符编码都能够运用。

  1. 实例 2-4 Unicode 与多字节编码演示

    / **《精通 Windows API》

    • 以身作则代码
    • StringCode.c
    • 2.4 Unicode 和多字节
      **/
      / 预处理 /
      / 头文件 /
      #include
      /* **
    • 效果 Unicode 与多字节编码演示
      **/
      int WINAPI WinMain(
      HINSTANCE hInstance,
      HINSTANCE hPrevInstance,
      LPSTR lpCmdLine,
      int nCmdShow
      )
      {
      //定义 LPWSTR 类型的宽字符串
      LPWSTR szUnicode = L”This is a Unicode String;”;
      //定义 LPSTR 类型的窄字符串
      LPSTR szMutliByte = “This is not a Unicode String;”;
      //定义 LPTSTR 类型的自适就字符串
      LPTSTR szString = TEXT(“This string is Unicode or not depends on the option.”);
      //使用 W 版本的 API 函数,以宽字符串为参数。
      MessageBoxW(NULL,szUnicode,L”<字符编码 1>“,MB_OK);
      //使用 A 版本的 API 函数,以窄字符串为参数。
      MessageBoxA(NULL,szMutliByte,”<字符编码 2>“,MB_OK);
      //使用自适用的 API 函数,拔取相适应的字符串类型为参数。
      MessageBox(NULL,szString,TEXT(“<字符编码 3>“),MB_OK);
      return 0;
      }

 

在本实例中,一共动用了 3
种档次的字符串变量,每种类型的字符串变量的开端化是见仁见智的,如表 2.2
所示。

表2.2 字符串与开始化

类型

变量类型

初始化形式

Unicode

LPWSTR

L”string”

多字节

LPSTR

”string”

根据开发环境的设置自动适应

LPTSTR

TEXT(”string”)

本实例首先使用“多字节”模式展开编译。可以行使二进制编辑器来查阅编译得到的可执行文件,上例中定义的字符串分别存储为以下格局。使用二进制编辑器查看,能够从
exe可执行文件中找到如下音信。读者可以对照 ASCII 编码表查看。

“This is a Unicode String;”使用 Unicode 格局的十六进制编码:

54 00 68 00 69 00 73 00 20 00 69 00 73 00 20 00 61 00 20 00 55 00 6e 00 69 00 63 00 6f 00 64 00 65 00 20 00 53 00 74 00 72 00 69 00 6e 00 67 00 3b 00

 

 home88一必发 7

“This is not a Unicode String;”使用 ASCII 格局的十六进制编码:

54 68 69 73 20 69 73 20 61 20 55 6e 69 63 6f 64 65 20 53 74 72 69 6e 67 3b

 

 home88一必发 8

“This string is Unicode or not depends on the option.”的ASCII
形式的十六进制编码:

54 68 69 73 20 73 74 72 69 6e 67 20 69 73 20 55 6e 69 63 6f 64 65 20 6f 72 20 6e 6f 74 20 64 65 70 65 6e 64 73 20 6f 6e 20 74 68 65 20 6f 70 74 69 6f 6e 2e

 

然后是“<字符编码 1>”和 Unicode 编码、“<字符编码
2>”和“<字符编码
3>”的多字节编码。对汉字字符,二种编码的法子是区其他,如“字符编码”七个字,三种编码分别为:

Unicode编码

57 5b 26 7b 16 7f 01 78

 

 home88一必发 9

和多字节ASCII

d7 d6 b7 fb b1 e0 c2 eb

 

 home88一必发 10

读者可以分析设置使用 Unicode
字符集后编译完结的可执行文件与安装为多字节字符集后编译得到的可执行文件有何两样。

 

  1. 在工程布置中挑选编码方式

安装的办法是在Visual
Studio工程属性中接纳“配置属性”→“常规”→“字符集”选项中展开抉择。

//——————————————–

2.4.1    W版本和A版本的API

Windows 帮忙 Unicode 和 ASCII 编码的字符。Windows 系统 API
凡是以字符串作为参数的大队人马有所 W 和 A
多个本子以促成二种分裂编码的字符处理。

下边以 MessageBox 为例介绍两种不一样版本 API 函数的应用。在 User32.dll
中导出的函数实际上没有 MessageBox,唯有 MessageBoxA 和
MessageBoxW,那两者是同一个 API,达成了千篇一律的职能。分歧的是,MessageBoxA
以多字节字符串作为参数输入,MessateBoxW 以Unicode 字符串作为参数输入。

可以从 User32.dll 的导出函数看到七个例外版本的 API 函数。在 Platform SDK
中,MessageBox 函数声称所在的头文件中发觉如下概念(以下代码来自于
Microsoft Platform SDK):

WINUSERAPI
int
WINAPI
MessageBoxA(
__in_opt HWND hWnd,
__in_opt LPCSTR lpText,
__in_opt LPCSTR lpCaption,
__in UINT uType);
WINUSERAPI
int
WINAPI
MessageBoxW(
__in_opt HWND hWnd,
__in_opt LPCWSTR lpText,
__in_opt LPCWSTR lpCaption,
__in UINT uType);
#ifdef UNICODE
#define MessageBox MessageBoxW
#else 
#define MessageBox MessageBoxA
#endif // !UNICODE

 

可以见到,在先后开展编译和延续时,如若程序在 UNICODE 环境下,会选用MessageBoxW,否则使用 MessageBoxA。

软件开发人士能够活动设定使用 Unicode
编码或都多字节编码文件,不影响程序的例行机能。

但倘诺在编写程序时,使用的字符集与代码中选用的函数不等同、定义的字符串变量不匹配,将会挑起编译错误或者运行程序突显乱码,甚至可能引起程序运行错误,这或多或少索要引起注意。

temp = ebpnum + 4 * param +
8;//取得参数的地址,然后4字节的值写入到对应地方

2.4.2    Unicode与ASGII的转换

Windows 专门提供了好七个 API
来贯彻对字符编码的转移工作。ideCharToMultiByte、MultiByteToWideChar、UnicodeToBytes
函数可以做到这么些工作。

WideCharToMultiByte 函数将 Unicode 字符串转换为多字节字符串,以适应 A
版本的API,MultiByteToWideChar 函数将多字节字符串转换为了 Unicode
字符串,以适应 W 版本的 API 的参数方式需要。

straddress[arrnum] = *(DWORD*)temp;

2.4.3    对Windows程序设计规范的指出

各样程序员都有投机的规范化编程习惯。代码的正式不是本书的根本,所以那边只交付一些微软日常利用代码规范,MSDN
的演示中,SDK 的头文件和例子中大致都是拔取的那种方法。

变量名:平常接纳所谓的“匈牙利(Magyarország)命名法”,变量名由“类型缩写(小写)”+“变量描述(单词首字母大写)”构成,如字符串类型的变量可以命名为
szFileName,DWORD 类型的数量可以命名为 dwFileSize,指针类型可以命名为
lpBuffer,句柄类型的变量可以命名为 hLogFile 等。

函数名:各单词的首字母大写,如 EnumerateFilesInDrectory、ShowFileSize
等。

花色名:全大写,各单词以下划线分隔,如 WIN32_FILE_
ATTRIBUTE_DATA、DWORD、 HANDLE 等。

常量:同类型名的命名形式。

宏:多与类型名命名格局相同,有的也与函数名命名格局同样。
大括号与代码段:一般大括号独立占一行,大括号内的代码段缩进。假使代码段仅一行(如
if-else 后的讲话),也提议选取大括号。

在调用或概念函数时,若是函数太长,能够分行写,将每个参数写一行。一般多于
3个参数的函数需求分行写,以精彩和便利阅读为基准。

在本书的示范中,都将尽心使用那几个规范化的艺术。

 

int testnum = 0;

2.5    小结

PDF下载:

摘自:《精通Windows.API-函数、接口、编程实例》 人民邮电出版社

范文庆、周彬彬、安靖创作

 

__asm{//获取字符串的长度,Unicode版本

mov ecx, arrnum

mov eax, straddress

mov eax, straddress[ecx * 4]

sss2 :

xor ebx, ebx

mov bx, word ptr[eax]

add testnum, 1

add eax, 2

test bx, bx

jne sss2

dec testnum

}

memcpy(&str[strnum], straddress[arrnum], testnum * 2);//unicode

strnum += testnum;

i++;

arrnum++;

//——————————————–

}

} else{

str[strnum] = string[i];

strnum += 1;

}

}

TCHAR msg[2001] = {0};

wsprintf(msg, TEXT(“字符串:%s 长度:%d 参数:%d”), str, lstrlen(str),
param);

MessageBox(NULL, msg, TEXT(“御坂高级弹窗音讯”), MB_OK);

}

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图