必威-必威-欢迎您

必威,必威官网企业自成立以来,以策略先行,经营致胜,管理为本的商,业推广理念,一步一个脚印发展成为同类企业中经营范围最广,在行业内颇具影响力的企业。

C程序的设计首要考虑的是如何通过一个过程必威

2019-09-18 20:02 来源:未知

  这个缓冲区的方法如果用在MessageBox函数里面,就可以实现打印变量的方式,比如以下代码:

TEXT,

2.5       小结.. 23

str[strnum] = string[i];

wchar_t wch = L’A’;
wchar_t wstr[] = L“hello, world”;
// 自己做一个格式化的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.1.1       Windows数据类型示例.. 1

temp = ebpnum + 4 * param + 8;

 

#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;
}

#define MB_YESNO 0x00000004L

2.2.3       用户界面.. 9

/* 使用说明: 弹窗的内容可以使用任意多个参数,类型暂时只支持 %d 和 %s

计算机最早在美国诞生,所以最开始都是以英语为作为交互语言,由于只有26个字母,用一个字节(范围-128 ~ 127)表示,这个范围足够表示26个因为字符和一些常用的控制字符,这个就是ASCII编码。因此最早的各种程序设计语言以及使用的字符串都用字节数组表示,也确实满足了编程的各种需求。但是随着计算机的普及,范围上逐渐超出了英语使用的国家,这样一来,字符编码就成了问题,因为很多国家的语言字符数目根本不能用一个字节来表示,比如我们国家的中文,常用的就有四千多个,如果再加上一些不常用的字符,更是远远不止这些,因此一个字节的字符串编码就行不通了,那么自然而然就出现了两个字节甚至跟多字节的编码方式了。

  刚开始学习Windows程序设计,磕磕碰碰,先做个小笔记缓缓神经,主要是将MessageBox这个Windows API函数的。

}

2.1.2    Windows 数据类型与标准C 数据类型的关系

查看 Windows 数据类型的定义可以看到,所有的 Windows 数据类型都是由 C 数据类型经过类型重定义得到的。如 DWORD 实质上就是 unsigned long 数据类型,32 位的无符号整型:

typedef unsigned long       DWORD;

 

实际上 VC 编译器是一个完整的 C 编译器,此外并没有过多的扩展。Windows 数据类型也不是 VC 的内建类型,而从标准 C 类型重定义得到。

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

第一个字符是“h”,它的宽字符在内存排布(小端系统)为”68 00 …”,根据C语言规则,字符串以空字符0x00为结束符,因此使用printf和%s来输出时,系统并不知道这个h是一个宽字符,而是以此向后一直到空字符,这里刚好第二个就碰上了,因此只能输出一个“h”。

  MessageBox函数是许多人刚开始学习Windows程序设计或者是Windows API遇到的第一个内置函数,这个函数使用的方式是:

MessageBox(NULL, TEXT("你点击了“确定”按钮"), TEXT, MB_OK);

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 位的数据类型。

int test = 0;

#include <windows.h>
#include <tchar.h>

int _tmain(void)
{
    TCHAR c = TEXT('A');
    TCHAR buf[16];
    TCHAR *str = TEXT("hello, world!");

    _tprintf(TEXT("1 --> %cn"), c);
    _tprintf(TEXT("2 --> %sn"), str);

    _tscanf(_T("%s"), buf);
    _tprintf(_T("%sn"), buf);

    _tsystem(TEXT("pause"));

    return 0;
}

  相当于自己设计出来一个类似printf的小工具,因为微软确实没有设计MessageBox中进行格式化输出的函数。

uType 支持的按钮样式:

2.3.5       其他Dll 17

i++;

默认情况下,我们使用VS来建立工程,_UNICODE和UNICODE这两个宏都是打开的,所以我们用向导创建的工程都是Unicode版本的,我们也可以从配置选项里面删除这两个定义来编译ANSI版本的程序。

  MessageBoxA(NULL, "弹出框内容", "标题", MB_OK);   // TEXT可有可无

int WINAPI WinMain(

 

i++;

有时候我们可能还是会出现不同编码之间的转换,这是我们可以采用Windows提供的API来完成。

 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 }

必威 1

2.2.4    图像和多媒体

Windows 的图像引擎和多媒体编程有多种接口,包括最基本的 GDI、GDI+,以及更高级的OpenGL、DirectX 等图像引擎编程接口。DirectX 和 OpenGL 在游戏开发、动画制作等方面应用比较广泛,使用它们进行应用程序开发需要专门的 SDK。本书只讲解 GDI,对一般的应用程序开发,已经足够使用。

GDI 的基本概念包括图像(Image)、位图(Bitmaps)、笔(Pen)、画刷(Brush)、文本和字体( Text and Fonts)、线(Line)、区域(Regions)、形状(Shapes)等。其基本的功能是对显示设备进行控制、获取和修改相关配置,在计算机屏幕上显示用户所需要显示的内容。

mov eax, string//获得字符串的地址

必威 2

  MessageBoxW(NULL, L"", L"", MB_OK);                       // 这个L用来表示Unicode,不可以省略

MessageBox() 返回被按下的按钮,以数字表示,这些数字都被定义成了宏,如下所示:

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。

LPSTR 类型的数据是字符串,也就是字符指针,CHAR 是字符,DWORD 是 32 位的无符号整数,INT 是 32 位有符号整数。程序运行后会弹出 4 个对话框。这说明 dwMax>dwOne 是成立的。iMax<iOne 也是成立的。dwMax 与 iMax 的数值是一样的,dwOne 与 iOne 的数值也是一样的。但是比较结果不同,是因为二者的数据类型不一样。

 

  1. 查看Windows数据类型的定义

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

 必威 3

图2-1

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

“INT”的定义如下:

 typedef int                 INT;

 

“DWORD”的定义如下:

 typedef unsigned long       DWORD;

 

"CHAR"的定义如下:

 typedef char CHAR;

 

    从中可以发现,这些 Windows 数据类型都是从标准 C 的数据类型经过类型重定义而来。INT 数据类型是有符号整型,DWORD 数据类型是无符号整型。 这就说明了为什么在实例 2-1 中 INT 数据类型的变量 iMax 实际是“-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”是无符号类型等。

sss:

 

  这个printf函数不仅可以使用多个参数打印,还可以用来直接打印变量,但是MessageBox却不能直接打印,这个引起我的直接思考。我先想到的是建立一个缓冲区,利用这个缓冲区取打印字符数据。当然打印的函数得使用sprintf了

你也可以尝试用数字来表示按钮,例如:

2.2.6       其他功能.. 15

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

请注意注释部分,该函数及可以转换,也能获取转后所需输出的存储字符个数空间的大小。运行后的输出结果:

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

MessageBox() 函数是众多API中的一个,用于弹出一个指定风格的对话框,其原型为:

2.2       Windows API 的功能分类.. 7

add testnum, 1

MultiByteToWideChar函数和WideCharToMultiByte函数,这两个函数可以在ANSI和Unicode字符串之间来回转换。他们的参数有很多相似之处,原型为:

 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 }

int nCmdShow

2.3.1    Kerne132.dll

Keme132.dll 包括了系统基本服务中最基本的 API 函数,如文件系统、进程与线程、内存管理等。 Windows XPSP2 系统中,Keme132.d11 有 949 个导出函数,例如,CreateFileA、CreateProcessA、OpenThread、SetFileTime 等。本书将在后续章节中通过实例介绍这些 API的使用。

//--------------------------------------------

 

 

点击“确定”或“取消”按钮,又会弹出一个新的提示框。大家可以亲自运行一下,会有真实的体验。

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 数据类型,为无符号整型。

sss2 :

微软针对标准C函数构造了一套平台相关的字符串处理宏定义,所谓平台相关就是说这些宏是微软自己定义的,只是在Windows平台下使用,不是标准里面的东西。这些定义在不同的情况下会变成不同的版本。如果定义了“_UNICODE”这个宏定义,Windows将在处理C/C++函数是采用Unicode版本,否则就是ANSI版本。下面我们以strlen这个函数来看一下Windows是怎么定义的:

  但是每次都写个缓冲区来存放,并且一不下心忘记使用_snprintf函数,那就GG了,很可能发生缓冲区溢出的危险。因此,这里利用printf原先函数设计的原理,我们也来设计一个MessageBoxPrintf();函数,用这个函数来实现格式化输出的作用,要实现这个函数,首先得参照printf();函数的实现原理。

也会生成与上面相同的对话框。

2.1       Windows数据类型.. 1

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

看下面的实例:

 

}

2.4.2       Unicode与ASGII的转换.. 22

TCHAR msg[2001] = {0};

可以看出:

  

C和C++的区别:

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 系统中自带的应用程序所提供的开发接口的集合。

源码

下面给一个实例来演示ANSI和Unicode之间的转换:

  其实之所以有这两个是因为微软需要满足Windows 98之后对汉字等其他语言编码的需求,这种需求通过Unicode实现,但是微软本意不是要我们使用Unicode来编程,而是通过使用“通用”形式,也就是MessageBox();函数,实现不同的编码主要还是通过IDE集成开发环境下改变不同的编码形式。回到MessageBox();,今天比较头疼的是,怎么在MessageBox();中实现变量的打印呢?

#define IDCANCEL 2

2.3.4       标准C函数.. 17

test bx, bx

对字符串常量,VS定义了TEXT、__TEXT,在tchar.h中,还定义了_T等好几种方式,只要定义了UNICODE,则这些宏定义就是Unicode,否则就是ANSI版本。因此我们以后在编写程序时,应该充分用这些宏来定义字符串类型变量,常量以及处理函数。下面是一个推荐的简单实例:

 

与上面的对话框相比,多出了一个图标,同时还能听到提示音。是不是多了一个提示符号在文字的前面啊。

2.2.2       系统管理.. 9

add num,1//计数+1

ASCII版本:

  就像C语言中经常使用printf函数,这个函数挺有趣的,应为函数输入的参数是没有限定个数的,相当于是随机改变的。例如:

#define IDABORT 3

2.3.3    Gdi32.dll

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

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

#ifdef UNICODE
#define CreateWindow  CreateWindowW
#else
#define CreateWindow  CreateWindowA
#endif // !UNICODE

 

NULL,

 

__asm{

具体用法可以参考MSDN,网上也能找到大量的使用说明和实例,这里就不再叙述。

TAG标签:
版权声明:本文由必威发布于必威-操作系统,转载请注明出处:C程序的设计首要考虑的是如何通过一个过程必威