Windows_API编程入门教程
第五章_Windows应用程序编程接口API
Visual C++
5.1.4 WindowsAPI分类(续)
9. 打印管理服务
在Windows操作系统下,可以实现在各种设备下的打 印。打印管理服务提供了完整的函数集支持这些操作, 例如检索打印机,准备打印等。这些服务所对应的函数 包含在打印管理函数库——Winspool.drv中。 10. 解/压缩文件服务
该服务提供了对文件的压缩和解压服务。这些服务 所对应的函数包含在函数库——Lz32.dll。
在VC6.0中提供了一个文件Win32api.csv。它是一个 Win16与Win32函数的对照表。通过它读者可以浏览到 Windows各种版本下API函数的原型说明。
Visual C++
5.1.5 操作系统的认识
第5章 目 录
Visual C++
本章以一些API设计的控制台程序和具有图形界面的Win32程序 为例,阐述了利用API函数开发程序的过程,重点在于理解操作系统 所提供的各种服务以及程序员如何进行调用。
1. 2. 3. 4. 5. 习题
API概述 内核服务API函数的使用 网络接口服务 Win32 API编写图形界面程序 图形设备接口与用户接口服务
内核服务的函数大部分包含在Windows内核库——Kernel32.dll中。
Visual C++
5.1.4 WindowsAPI分类(续)
■ 2.图形设备接口
■
图形设备接口是Windows最原始的图形输出库(最原
始意味着除了GDI外,还有工业界用的OpenGl和游戏界用的
DirectX,VC都对他们提供支持)。当看到图形或文本显示在屏幕
Visual C++
WINDOWS_API 教程
WINDOWS API C++ 编程当我们使用着漂亮的界面,方便快捷的应用程序的时候。
我们才会发现,以前曾编写的程序是多么的粗糙(TC编写的程序)。
简单的界面,16色的显示系统,大大的落后于计算机的发展。
简单的说就是杀鸡用牛刀。
如何该改变这种情况呢?Microsoft公司在推出wind ows操作系统的时候给出了简单易行的解决方案。
这就是WINDOWS平台API应用程序接口。
当然API也是发展的,它从WIN 16 API发展到了现在普遍使用的WIN 32 API。
只有充分理解API函数功能和用法,才能深入到WINDOWS系统的内部,才能充分挖掘出操作系统给我们提供的强大功能。
现在就让我们放弃那DOS应用程序,进入WINDOWS编程的海洋之中吧。
要想了解WINDOWS API那么我们必须先了解WINDOWS下的程序是如何进行驱动的。
同学们可以很清楚的发现到,当你在使用WINDOWS记事本的时候,当键盘输入字符的时候字就会出现在屏幕上。
当你移动鼠标的时候,光标就会在屏幕上移动。
双击鼠标、单击鼠标就会有相应的事件发生。
这些都是由于WINDOWS具有的事件驱动的属性造成的。
比如说当你按下键盘的字符键的时候,消息队列就会向程序发送WM_CHAR的消息,如果你所写的程序中含有处理这个消息的函数,程序就会执行它。
为了更好的了解WINDOWS编程,这里我必须介绍几个基本的概念:1,句柄:它是WINDOWS编程的基础。
一个句柄是指WINDOWS在内存中使用的一个唯一的整数质,是一个4个字节长的数值,用于标识应用程序中不同对象和相同对象的不同实例。
这里我列出几种WINDOWS常用的句柄:HWND: 标示窗口句柄HINSTANCE:标示当前实例句柄HCOURSOR:标示光标句柄HFONT: 标示字体句柄HPEN:标示画笔句柄HBRUSH:标示画刷句柄HDC:标示设备环境句柄HBITMP:标示位图句柄HICON:标示图标句柄HMENU:标示菜单句柄HFILE:标示文件句柄由于WINDOWS应用程序利用WINDOWS消息来与其它的WINDOWS应用程序及W INDOWS系统进行消息交换。
WindowsAPI编程
吉林大学远程教育课件
Windows A P I编 程
While(1) {
id=getMessage(…); if(id==quit)
break; translateMessage(…); }
当该程序没有消息通知时,getMessage就不会返回,也就不会占用系
统的CPU时间。
二、协同式多任务与抢先式多任务系统
在16位的操作系统中只有一个消息队列,所以系统必须等待当 前任务处理消息后才可以发送下一消息到相应程序,如果一个 程序陷入死循环或是操作超时,系统就得不到控制权。这种多 任务系统被称为协同式多任务系统。 Windows 3.x就是这种系 统。
Windows API程序设计。
第二节 Windows 程序
工作原理
Windows 程序设计是一种完全不同于传统的DOS方式的程序 设计方法,它是一种事件驱动方式的程序设计模式。在程序提供 给用户的界面中有许多可操作的可视对象。用户从所有可能的操 作中任意选择,被选择的操作会产生某些特定的事件,这些事件 发生后的结果是向程序中的某些对象发出消息,然后这些对象调 用相应的消息处理函数来完成特定的操作。Windows应用程序最 大的特点就是程序没有固定的流程,而只是针对某个事件的处理 有特定的子流程,Windows应用程序就是由许多这样的子流程构 成的。
前 言 (二)
Windows操作系统同时也是一个大的函数库,其中包 含了数以千计的函数,这些函数能完成各种各样的功 能,包括窗口管理、图形设备接口、媒体控制、内存 管理和系统扩展,这些函数都被封装在一个接口中, 这 个 接 口 就 是 Windows 应 用 程 序 编 程 接 口 ( Windows Application Progrmming Interface),简称Windows API。 可以说,用户需要实现的所有功能通过Windows API都 能实现。而且, Windows API作为操作系统不可分割 的一部分,很好地体现了 Windows操作系统的特色。 并且基于 Windows API的应用程序具有和 Windows操 作系统的良好整合性,从而大大提高了软件的运行性 能。
Win32 API编程入门
欢迎阅读theForger's Win32 API教程第二版(简体中文)作者:Brooks Miles译者:湛宗儒 本教程试图使用尽可能快和尽可能清晰的方法教你开始Win32 API开发.它是以一个整体来组织的,所以在你提问之前请从头到尾看一遍...你的大多数问题很可能在文字中已被回答.每个章节以之前的章节为基础.我也在附錄A中附上了一些常见的错误的解決方法.如果你问一些在教程中已被回答的问题的话,看起来就有点不聪明了.·下载完整的范例源代码,在整个教程都有对代码的引用.·或是下载整个教程( 包括源代码)至你自己的计算机上慢慢看.下到硬盘的版本可能不包括网络版本具有的一些如拼写更正之类的小规模修改. 如果你在一个別的站点上看此教程,请访问#winprog 站点看最新的官方版本. · ·目錄·基础1.开始 学习2.一个简单的窗口3.处理消息4.理解消息循环5.使用资源6.菜单和图标7.对话框 , 图形界面设计者的好朋友8.非模态 对话框9.标準控件: 按钮 , 编辑框 , 列表框 , 靜态 控件10.等等 , 我还想问 ...( 对话框常见问题)·创建一个简单应用1.应用第一部分 : 在运行时创建控件2.应用第二部分 : 使用文件与常用对话框3.应用第三部分 : 工具栏与状态栏4.应用第四部分 : 多文档界面·图形设备界面1.位图 , 设备上下文与BitBlt2.透明位图3.定时器与动画4.文本 , 字体与顏色·工具与文档1.推荐的书与参考2.免费的Visual C++ 命令行工具3.免费的Borland C++ 命令行工具·附表附表A:常见错误的解決方法附表B:为什要在学习MFC 编程之前学习API附表C:关于资源文件 我听某些读者说教材中的源代码在一些很旧的Netscape浏览器中不能正确地換行,如果你遇到此问题请参考zip打包下载的源代码.想做点什么?你可以绝对免费地使用此文档,但是把在它放在互联网上的确是有些费用..如果你感觉它对你有帮助,也想回馈一些,我将很感谢你能捐赠任何数目的款项来协助支撐此网站.此页面每月大約有15,000个点击,并且在一直增加:) 再说一次,你完全沒有义务支付,你也不会因为支付而得到除了在此处之外的任何东西,但是你想协助的话,是很好的...就点那个PayPal图片就行.但愿你能享受閱读,Brook 我想对如下几个人做出的贡献表示感谢:Yih Horng,Todd Troxell,T FrankZvovushe,Suzanne Lorrin, Seth McCarus,Crispina Chong,John Crutchfield,Scott Johnstone,Patrick Sears,Juan Demerutis,Richard Anthony,Alex Fox,Bob Rudis,Eric Wadsworth,Chris Blume.还有那些写信告诉我觉得此文档有用的那些读者.我很高兴!需要进一步的帮助? 一般地话我会免费回复求助邮件,或指出在哪里可以找到可供参考的资源. 现在我正忙于几个大项目,所沒有时间跟你写一些特定的范例或一定规模的软件项目.但是我愿意接项目:)尽管联系我 .Copyright © 1998-2003, Brook Miles (theForger). All rights reserved.开始学习这篇教程讲什么 这篇教程试图向你展现使用Win32 API写程序的一些基础知识(还有常见的扩展知识).使用C语言,大多数的C++工具也可以编译.事实上从大多数语言的介绍文章可知,大多数语言皆可调用API,包括Java,汇编语言以及Visual Basic.但是我将不会提到这些语言的代码例子,你想使用其它语言的话,请自己参考相关资料,不过有好几个使用过此教程的人都对我说用上面的这些语言都是可行的. 本教程不会教你C语言,也不会教你怎么使用你喜欢的编译器(Borland C++,Visual C ++,LCC-Win32,等等).但是我将在附表中就我对编译器的所知提供一些说明. 如果你不知道macro或typedef是什么,或switch()语句如何工作,那你要先回去找一本好的C语言的教程学习一下.重要说明 在此文档的某些部分我将指出某些地方很重要.因为很多人在不閱读它们情況下造成理解困难,你如果不閱读,你很可能也陷入困难. 第一个就是: 以zip打包的源代码范例不是可选可不选的!我沒有把所有的代码放在教程中,只放了那些与我正在讨论问题相关的.要想知道这里的代码怎么与其它部分配合,就必须去看zip文件中的源代码. 好!第二个: 把整个文档看完.如果你在读某章节遇到了问题,请耐心一点,很可能在后面一点就可以找到答案.如果你实在不能忍受这种无知的状态,请在到IRC频道上去提问或发出求助邮件之前至少跳过一点或在余下的文档中搜一下(是的,计算机可以搜索). 另外一点就是一个关于话题A的问题很可能在关于话题B或C的讨论中得到解答,也有可能是话题L.所以多看看,找一下. 好,东扯西拉暂时告一段落,我们来试些实际代码.最简单的Win32程序 如果你是一个完全的新手,就让我们来确认一下你可以编译一个基本的windows程序.把下面这些代码弄到你的编译器中去编译一下,如果一切正常你就得到有史以来最简易的程序之一. 记得以C来编译,不是以C++.可能沒有关系,但这里的代码都是C,在正确的轨道,行驶还是好些.大多数情況,你要做的就是把文件的扩展名写成.c而不是.cpp..如果这些话伤了你的脑筋的话,就把文件名写成test.c并用它就行了.#include <windows.h>int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow){MessageBox(NULL, "Goodbye, cruel world!", "Note", MB_OK);return 0;} 如果不行,首先閱读得到的任何错误提示,并在帮助文档或任何其它跟你编译器配套的文档中查找它们.确定你是以一个Win32 GUI(不是Console)的工程/makefile/目标来编译的.不幸的是,这一点上我也帮不了什么,对于不同的编译器(不同的人),解決方法不同. 你可能得到一些警告说你沒有使用WinMain()传递的那些参数.这沒关系.现在我们确定你能编译一个程序了,我们来看一下代码...int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow) WinMain()是Windows中与DOS或UNIX的main()的等价物.这是你的程开始执行的入口.参数如下:HINSTANCE hInstance程序可执行模块的句柄(內存中的.exe文件).HINSTANCE hPrevInstance在Win32程序中总是为NULL.LPSTR lpCmdLine命令行参数组成的一个单字符串.不包括程序名字.int nCmdShow一个将要传递给ShowWindow()的整数,我们在后面进行讨论. hInstance用作装入资源或其它的以模块为单位的任务.一个模块是一个装入到你程序的exe或dll.对于本教程的大多数部分(如果不是全部的话),我们只关心一种模块,就是exe 模块. hPrevInstance在Win16时代曾经用作你程序的前面已经运行的实例(如果有的话).现在已经不用了,在Win32中你忽略它就行了.调用规则 WINAPI指定调用规则并被定义为_stdcall.要是你不知道它是干什么用的,先不管它,在我们的这个教程中它对我们沒有影响.记住在这个位置我们需要它就是了.Win32数据类型 你会发现很多普通的关键字或类型在windows中有特定的定义.UINT是unsigned int,LPSTR是char*等等...你怎么用完全取決于你自己.你要是喜欢char*超过了LPSTR,那就用就是了.当然在你替換一个数据类型前你要确定你知道它是什么. 就记住一些容易记住的东西就夠了.LP前缀代表Long Pointer.在Win32中,Long这个部分已经是过时的概念,不要管它.要是不知道指针是什么的话,你可以1)去找一本好的C语言教程,或2)直接往下读,弄得头脑混乱.我是推荐第一种方案的,但很多人使用第二种(我也是:).到时候別说我沒有提醒你. 接下来,一个C接在LP后面表示是常量指针.LPCSTR表示一个指向不会也不能被修改的常量字符串的指针.LPSTR指向的就不是常量的,可以被修改. 你可能还会看到一个T混在里面.现在不要管它,除非你打算与Unicode打交道,它沒有其它的意义.Copyright © 1998-2003, Brook Miles (theForger). All rights reserved.一个简单的窗口范例:simple_window 有时候有人在IRC上问:”我怎么才实现一个窗口?”...我觉得不是一句两句能说得清楚.虽然一旦你搞清楚你要做什么后并不难,但是你的确需要做一些事情来使显示一个窗口;这些事情不是在聊天室中一下子说得清楚的.我总是喜欢先做一件事情然后来理解它...所以先给出一个简单窗口的代码稍后再做解释.#include <windows.h>const char g_szClassName[] = "myWindowClass";// Step 4: the Window ProcedureLRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){switch(msg){case WM_CLOSE:DestroyWindow(hwnd);break;case WM_DESTROY:PostQuitMessage(0);break;default:return DefWindowProc(hwnd, msg, wParam, lParam);}return 0;}int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow){WNDCLASSEX wc;HWND hwnd;MSG Msg;//Step 1: Registering the Window Classwc.cbSize = sizeof(WNDCLASSEX);wc.style = 0;wc.lpfnWndProc = WndProc;wc.cbClsExtra = 0;wc.cbWndExtra = 0;wc.hInstance = hInstance;wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);wc.hCursor = LoadCursor(NULL, IDC_ARROW);wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);wc.lpszMenuName = NULL;wc.lpszClassName = g_szClassName;wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);if(!RegisterClassEx(&wc)){MessageBox(NULL, "Window Registration Failed!", "Error!",MB_ICONEXCLAMATION | MB_OK);return 0;}// Step 2: Creating the Windowhwnd = CreateWindowEx(WS_EX_CLIENTEDGE,g_szClassName,"The title of my window",WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,NULL, NULL, hInstance, NULL);if(hwnd == NULL){MessageBox(NULL, "Window Creation Failed!", "Error!",MB_ICONEXCLAMATION | MB_OK);return 0;}ShowWindow(hwnd, nCmdShow);UpdateWindow(hwnd);// Step 3: The Message Loopwhile(GetMessage(&Msg, NULL, 0, 0) > 0){TranslateMessage(&Msg);DispatchMessage(&Msg);}return Msg.wParam;} 简单来说这是你想创建一个窗口能写的最简单的程序,大致上70行左右的代码.如果第一个范例你通过了编译,这个也应该不成问题.第一步:注冊窗口类 一个窗口类存储关于一个窗口的消息,包括控制窗口的窗口过程,窗口的大小图标,以及背景顏色.用这种方式,你可以先注冊一个窗口类,然后从它创建任意数目的窗口,而不需要一次次的指定这些参数.如果需要,大多数属性能针对单个的窗口来攺变. 这里说的窗口类与C++中的类是完全不同的概念.const char g_szClassName[] = "myWindowClass"; 上面的变量存储了我们窗口类的名字,马上会用来向系统注冊窗口类. WNDCLASSEX wc;wc.cbSize = sizeof(WNDCLASSEX);wc.style = 0;wc.lpfnWndProc = WndProc;wc.cbClsExtra = 0;wc.cbWndExtra = 0;wc.hInstance = hInstance;wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);wc.hCursor = LoadCursor(NULL, IDC_ARROW);wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);wc.lpszMenuName = NULL;wc.lpszClassName = g_szClassName;wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);if(!RegisterClassEx(&wc)){MessageBox(NULL, "Window Registration Failed!", "Error!",MB_ICONEXCLAMATION | MB_OK);return 0;} 这是我们在WinMain()中注冊我们的窗口类的代码.我们填写一个WNDCLASSEX结构体的成员并调用RegisterClassEx(). 结构体的成员对窗口类的影响如下:cbSize 结构体的大小.style 类的式样(CS_*),不要跟窗口式样(WS_*)混淆了.这个一般设置为0.lpfnWndProc 指向这个窗口类的窗口过程的指针.cbClsExtra 配置给这个类的额外內存.一般为0.cbWndExtra 配置给这个类的每个窗口的额外內存.一般为0.hInstance 应用程序实例的句柄.(从WinMain()第一个参数传递来.)hIcon 当用戶按下Alt+Tab组合时候显示的大图标(一般为32*32).hCursor 在我们的窗口上显示的光标.hbrBackground 设置我们窗口背景顏色的背景刷子.lpszMenuName 这个类的窗口所用的菜单资源的名字.lpszClassName 类的名字.hIconSm 在任务栏和窗口的左上角显示的小图标(一般为16*16). 如果看得不很明白先不要担心,马上会有讲解.另外要记住的一件事情是不要试图去记下这些东西.我基本上不(从来不)记结构体或函数的参数,这样做是浪费精力和更重要的时间.如果你知道要调用的函数你就去花几秒钟在你的帮助文档中查一下.要是沒有帮助文档,就是想法弄到.沒有它们是很郁闷的.随著你使用多次后也许你会记住那些最常用的函数的参数. 然后我们调用RegisterClassEx()并检查是否成功,如果失败我们弹出一条提示消息并从WinMain()函数退出程序.第二步:创建窗口 一旦类注冊完,我们即可从它创建一个窗口.你应该去查一下CreateWindowEx()的参数列表(在你要用一个新API的时候你总是要这样做),但是我会在这里做个简单的介绍.HWND hwnd;hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,g_szClassName,"The title of my window",WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,NULL, NULL, hInstance, NULL); 第一个参数(WS_EX_CLIENTEDGE)是扩展的窗口式样,这里我设置它想得到一个內部下陷的边框效果.你可以设成0看看效果.要习惯于试不同的值看效果. 接下来我设置了类的名字(g_szClassName),告诉系统我们要创建什么样的窗口.因为我们要从刚刚注冊的类创建窗口,我们使用了该类的名字.之后我们指定了我们窗口的名字或是标题,用来显示在我们窗口的外观或是标题栏上. 我们设置的WS_OVERLAPPEDWINDOW是一个窗口式样参数.这里有很多东西你可以查找并做试验.在下文中将详加说明. 接下来的四个参数(CW_USEDEFAULT,CW_USEDEFAULT,320,240)是我们窗口的左上角的X,Y坐标和其宽度和高度.我把X,Y坐标设为CW_USEDEFAULT来让系统自己选择在屏幕的哪个地方来放置窗口.记住屏幕的最左边的X坐标为0并向右加;屏幕的顶部的Y坐标为0并向底加.单位是像素,这是屏幕在特定的分辨率下能显示的最小单位. 再接下来的四个(NULL,NULL,g_hInst,NULL)分別是父窗口的句柄,菜单句柄,应用程序实例句柄,和窗口创建数据的指针.在windows系统中,你屏幕上的窗口是以分层次的父窗口,子窗口的形式来组织的.当你看到一个窗口中有一个按钮时候,按钮就是子窗口,包含它的窗口就是父窗口.我们的例子中,父窗口的句柄为NULL,因为这里沒有父窗口,这个是是我们的主窗口或是顶层窗口.菜单也是NULL,因为我们现在也沒有菜单.实例句柄设为我们从WinMain()得到的第一个参数.窗口的创建数据(我们几乎沒有使用)可以用来向创建的窗口发送额外数据在这里也设为NULL. 如果你想知道神奇的NULL是什么,它实际上被定义为0(零).而且在C中,它是被定义为((void*)0)的,因为是用来作指针用的.所以你有可能在把NULL当整数使用时会得到警告,跟你的编译器的警告级別设置有关.你可以忽略这个警告,也可以用0来代替. 不检查调用是否成功几乎是程序员为找不来程序究竟错在哪里而烦恼的最常发生的情況.CreateWindow()可能会调用失败,即使你是一个用经验的程序员,原因就是可能犯错误的地方实在太多了.除非你学会了如何快速查出错误,最少你应该给自己一个机会知道是哪里出了错,一定记住检查返回值!if(hwnd == NULL){MessageBox(NULL, "Window Creation Failed!", "Error!",MB_ICONEXCLAMATION | MB_OK);return 0;} 在我们创建了窗口并作检查以确定我们有一个正确的句柄后,我们使用WinMain()最后的参数来显示窗口,再更新它以确认它在屏幕上正确地重画了自己.ShowWindow(hwnd, nCmdShow);UpdateWindow(hwnd); nCmdShow是可选的参数,你可以简单地传递SW_SHOWNORMAL即可.但是用从WinMain()传来的参数可给予运行此程序的用戶选择以可视,最大化,最小化等选项...来引导程序的自由.你可以在windows快捷方式的属性中看到这些选项,参数由选项来決定.第三步:消息循环 这是整个程序的心臟,程序中几乎所有的控制都从这个点传递. while(GetMessage(&Msg, NULL, 0, 0) > 0){TranslateMessage(&Msg);DispatchMessage(&Msg);}return Msg.wParam; GetMessage()从你应用的消息队列中取一个消息.任何时候用戶移动鼠标,敲击键盘,点击你窗口的菜单,或做別的什么事,系统会产生消息并输入到你的程序的消息队列中去.调用GetMessage()时你请求将下一个可用的消息从队列中删除并返回给你来处理.如果队列为空,GetMessage()阻塞.如果你不熟悉这个术语,它意味著一直等待直到得到一个消息,才返回给你. TranslateMessage()为键盘事件做一些额外的处理,如随著WM_KEYDOWN消息产生WM_CHAR消息.最后DispatchMessage()将消息送到消息应该被送到的窗口. 可能是我们的主窗口或另外一个,或一个控件,有些情況下是一个被系统或其它程序创建的窗口.这不是你需要担心的,因为我们主要关心我们得到消息并送出,系统来做后面的事以确认它到达正确的窗口.第四步:窗口过程 如果说消息循环是程序的心臟,那个窗口过程就是程序的大脑.这里所有送到窗口的消息被处理.LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){switch(msg){case WM_CLOSE:DestroyWindow(hwnd);break;case WM_DESTROY:PostQuitMessage(0);break;default:return DefWindowProc(hwnd, msg, wParam, lParam);}return 0;} 窗口过程在每个消息到来时被调用一次,HWND参数是消息相应的窗口的句柄.这很重要因为你可能用相同的类创建了两个或多个窗口并且它们用相同的窗口过程(WndProc()).不同点就在不同的窗口有不同的hwnd参数.比如我们得到WM_CLOSE消息我们就要销毀那个窗口.我们使用了窗口句柄作为我们得到的第一个参数,其它的窗口都不会受影响,除了那个我们想要操作的之外. WM_CLOSE是在我们按下关闭按钮或按下Alt+F4组合时产生的.这默认会使窗口销毀,但我喜欢显式处理它,因为这是在程序退出之前做清除检查,或询问用戶是否保存文件等事情的绝佳的位置. 当我们调用DestoryWindow()系统向要销毀的窗口送出WM_DESTORY消息,这里是我们的窗口,并在从系统移除我们的窗口之前删除它剩下的所有的子窗口.因为这是我们的程序中唯一的窗口,我们準备好了并希望程序退出,所以我们调用了PostQuitMessage().这样会向消息循环发出WM_QUIT消息.我们不永远收不到这个消息,因为它使GetMessage()返回FALSE,而且你也可以看到我们的消息循环代码中,这时候我们停止处理消息并返回最终的结果码,我们传递给PostQuitMessage()的WM_QUIT中的wParam部分.这个返回值只有在你的编程为被別的程序调用并且你需要一个确定的返回值时候才有真正有用.第五步:沒有第五步Phew(喘一口气),到这先告一段落.如果上面还沒有解释清楚的话,还是先放下,也许我们在讲解更有用的程序时这些东西会变得清晰起来.Copyright © 1998-2003, Brook Miles (theForger). All rights reserved.处理消息范例:window_click 不错,我们有个窗口了,不过除了DefWindowProc()允许它做的,如拉抻,最大化等等之外沒有別的什的功能了,并不是很令人激动. 下一章节我将演示如何修改你已有的代码来加点新东西.现在我只来告诉你”处理这个消息,在这里处理...”你就知道我的意思,知道怎样做且不用看一整个例子.希望如此,所以注意看:P 对于初学者,请把我们最后那个窗口编译好并确信它能工作.然后你要么就在这个例子上修改要么拷到另外一个新工程中来修改. 我们準备加个使用戶点击我们的窗口时候能夠显示出我们程序的名称的功能.不是很酷,就是基本的一个消息的处理.让我们看看我们的WndProc()中有些什么:LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){switch(msg){case WM_CLOSE:DestroyWindow(hwnd);break;case WM_DESTROY:PostQuitMessage(0);break;default:return DefWindowProc(hwnd, msg, wParam, lParam);}return 0;} 如果我们想处理鼠标的点击,我们需要添加一个WM_LBUTTONDOWN的处理部分(对于右键与中间键,分別是WM_RBUTTONDOWN与WM_MBUTTONDOWN). 如果你听到我或其它人提到处理消息,就是说在窗口的类的WndProc()中加上如下代码:LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){switch(msg){case WM_LBUTTONDOWN: // <-// <- 这就是我们加的break; // <-case WM_CLOSE:DestroyWindow(hwnd);break;case WM_DESTROY:PostQuitMessage(0);break;default:return DefWindowProc(hwnd, msg, wParam, lParam);}return 0;} 不同消息处理的代码的顺序基本上沒有什么关系.要记住的是一定不要忘了在每个消息处理代码后写上break语句.你可以看到我们在我们的switch()中加了另外一个case.现在我们想要在我们的程序执行至此时发生点什么. 首先我们把我们要加的代码写出来(显示我们程序的文件名)然后整合到我们的程序中去.后面的章节中我将只写出代码让你自己整合到程序中去.对我来说不用打那么多字了,对你来说也更灵活,不只是这里的程序还可以加到任何程序中去.如果你不知道怎么办,请参考样例zip文档中对应此章的部分.GetModuleFileName(hInstance, szFileName, MAX_PATH);MessageBox(hwnd, szFileName, "This program is:", MB_OK | MB_ICONINFORMATION); 这段代码不是自解释的,你不能把它随便敲到你原来的代码中去.我们只想在用戶用鼠标点击的时候运行这段代码,所以我们把它加到我们的消息处理框架中去:LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){switch(msg){case WM_LBUTTONDOWN:// BEGIN NEW CODE{char szFileName[MAX_PATH];HINSTANCE hInstance = GetModuleHandle(NULL);GetModuleFileName(hInstance, szFileName, MAX_PATH);MessageBox(hwnd, szFileName, "This program is:", MB_OK |MB_ICONINFORMATION);}// END NEW CODEbreak;case WM_CLOSE:DestroyWindow(hwnd);break;case WM_DESTROY:PostQuitMessage(0);break;default:return DefWindowProc(hwnd, msg, wParam, lParam);}return 0;} 注意那对新的花括号{}.当你在switch()中定义变量时需要它.这本来是基础的C语言知识,但我认为我应该在此指出来,为那些理解有困难的读者著想. 如果你已经加进了代码,现在就编译它.如果正常的话,你点击窗口你就应该看到一个有.exe字样的对话框弹出来. 你可能已经注意到我们加了两个变量,hInstance与szFileName.查一下GetModuleFileName()你就会看到第一个参数是HINSTANCE.指向可执行文件(我们的程序,.exe文件).我们哪里得到这样一个东西?GetModuleHandle()给出了答案.GetModuleHandle()的说明指出传给它一个NULL会返回一个创建发出调用进程的文件句柄,正是我们刚刚提到的HINSTANCE,是我们需要的.把这些消息集中起来我们就会得到如下的定义:HINSTANCE hInstance = GetModuleHandle(NULL); 对于第二个参数,我们再次转向我们可以信赖的参考文档,我们看到它是”一个用来接收那个模块的文件名和路径的缓冲区的指针”而且数据类型是LPTSTR(要是你的文档是比较旧的话就是LPSTR).因为LPSTR等价于char*,我们就定义一个字符串:char szFileName[MAX_PATH]; MAX_PATH是在<windows.h>中定义的一个宏,用来定义Win32中文件名缓冲区的最大长度.我们也将MAX_PATH传给GetModuleFileName()以使它知道缓冲区的大小. GetModuleFileName()被调用后,szFileName将包括一个我们的.exe文件名的字符串,以null结尾.我们把它传递给MessageBox()以一个简单的方法向用戶显示. 所以如果你加了代码,编译了.如果正常,点击窗口你就会看到一个有.exe文件名的对话框弹出来. 如果不是这样,这里是完整的代码.跟你的比较一下,看错误在哪里.#include <windows.h>const char g_szClassName[] = "myWindowClass";LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){switch(msg){case WM_LBUTTONDOWN:{char szFileName[MAX_PATH];HINSTANCE hInstance = GetModuleHandle(NULL);GetModuleFileName(hInstance, szFileName, MAX_PATH);MessageBox(hwnd, szFileName, "This program is:", MB_OK |MB_ICONINFORMATION);}break;case WM_CLOSE:DestroyWindow(hwnd);break;case WM_DESTROY:PostQuitMessage(0);break;default:return DefWindowProc(hwnd, msg, wParam, lParam);}return 0;}int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){WNDCLASSEX wc;HWND hwnd;MSG Msg;wc.cbSize = sizeof(WNDCLASSEX);wc.style = 0;wc.lpfnWndProc = WndProc;wc.cbClsExtra = 0; wc.cbWndExtra = 0;wc.hInstance = hInstance;wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);wc.hCursor = LoadCursor(NULL, IDC_ARROW);wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);wc.lpszMenuName = NULL;wc.lpszClassName = g_szClassName;wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);if(!RegisterClassEx(&wc)){MessageBox(NULL, "Window Registration Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);return 0;}hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,g_szClassName,"The title of my window",WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,NULL, NULL, hInstance, NULL); if(hwnd == NULL){MessageBox(NULL, "Window Creation Failed!", "Error!",MB_ICONEXCLAMATION | MB_OK);return 0;}ShowWindow(hwnd, nCmdShow);UpdateWindow(hwnd);while(GetMessage(&Msg, NULL, 0, 0) > 0){TranslateMessage(&Msg);DispatchMessage(&Msg);}return Msg.wParam;}Copyright © 1998-2003, Brook Miles (theForger). All rights reserved.理解消息循环 在写任何有实际价值的程序之前,都要理解整个消息循环和windows程序传递消息的结构.当前为止我们已经试了一些消息的处理,我还应该更进一步的看一下这个过程, 因为你如果不理解它们的话,后面的內容将会对你很难.什么是消息 一个消息就是一个整数.如果你到头文件中看一下(了解API的好地方)你就会发现这样的內容:#define WM_INITDIALOG 0x0110#define WM_COMMAND 0x0111#define WM_LBUTTONDOWN 0x0201...等等..消息用来进行windows系统中的所有通信,至少在基本方面是这样的.如果你想要你的窗口或是控件(其实就一种特別的窗口)做点什么你就给它发个消息. 如果另外一个窗口要你做点什么它也发给你一个消息..如果发生了用戶按动了键盘,移动了鼠标,点击了一个按钮之类的事件,系统就向相关的窗口发送消息.你要是就是那个被传至消息的窗口,你就要处理这些消息. 每个windows消息可能拥有至多两个参数,wParam和lParam.最初wParam是16bit,lParam是32bit,但在Win32平台下两者都是32bit.不是每个消息使用了这些参数,而且每个消息以不同的方式来使用.比如,WM_CLOSE不使用它们任一个,所以你应该忽略它们.WM_COMMAND消息两个都使用,wParam有两个部分,HIWORD(wParam)中含有提示消息(如果有的话),LOWORD(wParam)含有发送消息的控件或菜单的标识号.lParam含有发送消息的控件的HWND(窗口的句柄)或者为NULL,当消息不是由控件发送. HIWORD()和LOWORD()是windows定义的两个宏,用来从一个32bit值中分离出高字(0xffff0000)和低字(0x0000ffff)的两字节.在Win32中,一个WORD是16bit,所以一个DWORD为32bit. 可以用PostMessage()或SendMessage()来发送消息.PostMessage()把消息放入消息队列再立即返回.就是说你调用了PostMessage()后消息可能被处理了,也可能还沒有被处理. SendMessage()则真接把消息送往窗口并且在窗口沒有结束处理消息之前不返回.如果我们想关闭一个窗口我们可以发送一个WM_CLOSE消息:PostMessage(hwnd,WM_CLOSE,0,0);这跟我们点击窗口顶部的按钮一样的效果.注意wParam和lParam都为0.这是因为我们刚才说了WM_CLOSE并不用它们.对话框 一旦你开始使用对话框,你将需要向此控件发送消息以与它们通信.你可以先使用GetDlgItem()来用ID得到控件的句柄然后用SendMessage(),也可以直接用SendDlgItemMessage()这个一步到位的函数.你给它一个窗口的句柄和一个子窗口的ID,它就会得到字窗口的句柄并向它发送消息.SendDlgItemMessage()和类似的API,如。
windowsapi的学习
windowsapi的学习好啦,前段时间疯玩了好久,堕落的这么久也该好好学习学习了,在接触过⼀⼤堆程序设计语⾔后发现还是⽤C++好了,毕竟看着这名字就舒坦,新⼿还是⽼⽼实实先在windows下开发吧。
前段时间开始,照着书上抄了个最初级的"Hello Windows!",当时没想多少,今天学着⽆聊觉得还是带着上次写的⼀起写到⽹上来吧,以后回过头来也许还会来笑笑⾃⼰当初原来会是如此傻,好了不多说,今天姑且在原来的基础上加了⼀点点新东西,好吧,也就是那么⼀点点,下⾯当然就是上代码咯。
1 #include <windows.h>23 LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);45/*关于WinMain的各个参数的意义6hInstance:应⽤程序当前实例的句柄7hPrevhInstance:应⽤程序先前实例的句柄,对于同⼀个程序打开两次,出现两个窗⼝第⼀次打开的8窗⼝就是先前实例的窗⼝9szCmdLine:指向应⽤程序命令⾏的字符串的指针,不包括执⾏⽂件名10iCmdShow:指明窗⼝应该如何显⽰11*/12int WINAPI WinMain(HINSTANCE hInstance,13 HINSTANCE hPrevhInstance,14 PSTR szCmdLine,15int iCmdShow)16 {17static TCHAR szAppName[] = TEXT("HelloWin");18 HWND mainHwnd;19 MSG msg;20 WNDCLASSEX wndclass;2122 wndclass.style = CS_HREDRAW|CS_VREDRAW; //从这个窗⼝类派⽣的窗⼝具有的风格23 wndclass.lpfnWndProc = WndProc; //窗⼝处理函数的指针24 wndclass.cbClsExtra = 0; //指定紧跟在窗⼝类结构后的附加字节数25 wndclass.cbWndExtra = 0; //指定紧跟在窗⼝实例的附加字节数,如果⼀个应⽤程序在资源中⽤CLASS伪指令注册⼀个对话框类时,则必须把这个成员设成DLGWINDOWEXTRA。
windows编程实验二:简单的Windows_API程序设计
实验二:简单的 Windows API 程序设计一、实验目的本实验主要编写一个简单的Windows API 程序。
通过本实验你将能:●了解Windows API 程序的VC++ 开发环境●学习开发简单的Windows API 程序●理解Windows 程序中的消息循环二、背景知识Windows 编程,有人觉得要先学通用性较好的Win32 API 编程,也有人觉得应先学包装性较好的在VC++ 平台上较容易使用的Win32 MFC 编程。
本课程只学一个简单的Windows API 程序作为过渡,与前面的控制台菜单程序进行比较,对消息循环有较充分的理解后,然后再学习MFC 编程。
三、实验准备●阅读课件和教科书。
●准备一个简单的Windows API 程序。
四、实验要求与步骤使用VC++ 运行和理解简单的Windows API 程序, 仔细分析该程序的结构和执行的流程:1.进入 VC++ 开发环境2.新建一个“Win32应用程序”空项目3.在项目中加入下载的“C/C++源程序”文件api.cpp4.编辑调试运行程序。
5.试试改变窗口类的风格(值是CS_*)和窗口实例的风格(值是WS_*)(可参考windows.h 或在线查询)6.改变窗口实例的宽为 200,高为 100,标题 Title/Caption 为“WindowsApp”。
7.改变窗口体内的输出为“Windows API 应用程序”8.查看窗口类的类名是什么?9.尝试查询API函数MessageBox的作用及参数要求。
10.试注释掉 ShowWindow(...); 和 UpdateWindow(...); 说明程序运行情况?11.试注释掉PostQuitMessage(0);观察会发生什么情况五、实验结果和报告●打包Windows API 应用程序工程文件(注意:请删除Debug 和Release 目录)●完成实验报告。
第1章:API编程、Windows程序基本结构
Windows API 函数 Windows操作系统
1.1 基本概念
Visual C++:微软公司出品的 ++语言开发工具,允许程序员使用 + ++:微软公司出品的 ++语言开发工具 ++:微软公司出品的C++语言开发工具,允许程序员使用C+ 语言以可视化的编程方式快速开发基于Windows平台的系统软件及应 +语言以可视化的编程方式快速开发基于 平台的系统软件及应 用软件。 用软件。 Windows API:Windows操作系统的应用编程接口,它是操作系统的一部 操作系统的应用编程接口, : 操作系统的应用编程接口 由数千个函数组成,程序员可以在自己的程序里调用API函数以利 分,由数千个函数组成,程序员可以在自己的程序里调用 函数以利 用操作系统内置的一些功能。 用操作系统内置的一些功能。 MFC:微软基础类库。依据面向对象编程思想将API函数封装在几百个 :微软基础类库。依据面向对象编程思想将 函数封装在几百个C++ 函数封装在几百个 类中,使程序员可以利用面向对象的方法开发程序。 类中,使程序员可以利用面向对象的方法开发程序。 C++语言标准:C++语言是一种通用的计算机编程语言,国际标准化组 ++语言标准: ++语言是一种通用的计算机编程语言, ++语言是一种通用的计算机编程语言 ++语言标准 织已经对其语法和基本类库进行了标准化,很多公司依据C++ ++语言标 织已经对其语法和基本类库进行了标准化,很多公司依据 ++语言标 准推出了自己的C++开发工具, ++开发工具 ++只是其中一种 准推出了自己的 ++开发工具,Visual C++只是其中一种。 ++只是其中一种。
1.1 基本概念
3、Windows应用程序中的数据类型 、 应用程序中的数据类型 为了使程序的语义更加丰富, 为了使程序的语义更加丰富,Windows在C语言的基础上自定义了很多 在 语言的基础上自定义了很多 种数据类型。例如: 种数据类型。例如: HWND 无符号32位整数 无符号 位整数 HDC HINSTANCE …… DWORD unsigned long BOOL bool BYTE unsigned char UINT unsigned int 注意: 注意:Windows自定义数据类型的关键字都是大写 自定义数据类型的关键字都是大写
Windows_API_手册
Windows API 手册1. API之网络函数WNetAddConnection 创建同一个网络资源的永久性连接WNetAddConnection2 创建同一个网络资源的连接WNetAddConnection3 创建同一个网络资源的连接WNetCancelConnection 结束一个网络连接WNetCancelConnection2 结束一个网络连接WNetCloseEnum 结束一次枚举操作WNetConnectionDialog 启动一个标准对话框,以便建立同网络资源的连接WNetDisconnectDialog 启动一个标准对话框,以便断开同网络资源的连接WNetEnumResource 枚举网络资源WNetGetConnection 获取本地或已连接的一个资源的网络名称WNetGetLastError 获取网络错误的扩展错误信息WNetGetUniversalName 获取网络中一个文件的远程名称以及/或者UNC(统一命名规范)名称WNetGetUser 获取一个网络资源用以连接的名字WNetOpenEnum 启动对网络资源进行枚举的过程2. API之消息函数BroadcastSystemMessage 将一条系统消息广播给系统中所有的顶级窗口GetMessagePos 取得消息队列中上一条消息处理完毕时的鼠标指针屏幕位置GetMessageTime 取得消息队列中上一条消息处理完毕时的时间PostMessage 将一条消息投递到指定窗口的消息队列字串2PostThreadMessage 将一条消息投递给应用程序RegisterWindowMessage 获取分配给一个字串标识符的消息编号ReplyMessage 答复一个消息SendMessage 调用一个窗口的窗口函数,将一条消息发给那个窗口SendMessageCallback 将一条消息发给窗口SendMessageTimeout 向窗口发送一条消息SendNotifyMessage 向窗口发送一条消息3. API之文件处理函数CloseHandle 关闭一个内核对象。
第1章:API编程、Windows程序基本结构PPT教学课件
5
2020/12/10
1.1 基本概念
1、Windows应用程序的界面 ●窗口:屏幕上的一块区域,是应用程序的主要输入输出部件,每
个应用程序都拥有一个或多个窗口,开发Windows程序的第一步就是建 立窗口。
窗口有两种存在形式:
打开的窗口和图标(最小化的窗口)
编写一个Windows应用程序,首先应创建一个或多个窗口,随后应 用程序的运行过程即是窗口内部、窗口与窗口之间、窗口与系统之间进 行数据处理和数据交换的过程
MFC:微软基础类库。依据面向对象编程思想将API函数封装在几百个C++ 类中,使程序员可以利用面向对象的方法开发程序。
C++语言标准:C++语言是一种通用的计算机编程语言,国际标准化组 织已经对其语法和基本类库进行了标准化,很多公司依据C++语言标 准推出了自己的C++开发工具,Visual C++只是其中一种。
MFC Windows应用程序设计
第1章 Windows应用程序基
本知识
1
2020/12/10
课程介绍
教材:《MFC Windows应用程序设计》(64学时) 内容:
介绍Visual C++开发过程,讲述API与MFC开发Windows应用程序的理 念、方法及步骤。 教学目的: 通过本课程的学习,使我们熟悉采用面向对象编程语言进行Windows 可 视化开发,掌握面向对象的编程思想,熟悉面向对象编程的消息响应。 理解Windows应用程序的基本原理。 教学方法: 讲课与上机实验相结合,并辅以实际应用案例、常见问题分析等,巩固 所学内容。每次课分成两部分:基本知识+案例教学。 上机与考试 周5第3大节上机,第17周周5第3大节考试。
2
2020/12/10
WindowsAPI教程(一)WindowAPI概要
WindowsAPI 教程(一)WindowAPI 概要Windows API 教程(一) Window API 概要Posted on 2013 年 4 月 23 日 by lellansinhello Windows 编程以下代码可以在 vc6.0 以及vs 系列的IDE 上运行1 2 3 4 5 6 #include <windows.h> int main() { MessageBox(NULL, (LPCSTR)"hello, windows programming",(LPCSTR)"Title", MB_OK); return 0; } 如果提示找不到 windows.h 那么很有可能是你装的不是完整版的vc6.0 亦或者,你用的不是微软的工具(上面列举的都是微软的)那么,不解释,你懂的。
windows 这个操作系统本身就是微软公司的,所以如果你想在windows 上面做开发的话,首先推荐的是微软自己的 visual studio 系列IDE 。
如果你是想学习的话推荐使用 visual studio 2012(据说要win7 64位才能装),如果希望你的程序能在一般的电脑上能跑的话,那么避免麻烦还是推荐使用 visual studio 2010 了。
(原因本站也有相关博文,有兴趣的可以找找)Windows 数据类型想要学习windwos 编程,第一步就需要了解 windows 编程所常用的数据类型。
Windows API 中定义了很多 Windows 自己定义的数据类型。
对于函数的入口参数、返回值以及一些数据结构等等都使用的是 windows 数据类型,所以这也是一个必不可少的步骤。
如果你对C 语言或者C++的数据类型比较熟悉的话,那么对于一些基础的内容这个过程就是慢慢熟悉的过程。
windef.h1 2 typedef int INT; /* 整形 */3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 typedef unsigned int UINT; /* 无符号整形 */ typedef unsigned int *PUINT; /* 无符号整形指针 */typedef int BOOL; /* 布尔类型 */typedef unsigned char BYTE; /* 字节 */typedef unsigned short WORD; /* WORD (无符号短整型) */typedef unsigned long DWORD; /* DOUBLE WORD (无符号长整形)*/typedef float FLOAT; /* 浮点型 */typedef FLOAT *PFLOAT; /* 指向float 类型指针 */typedef BOOL near *PBOOL; /* 指向布尔类型指针 */typedef BOOL far *LPBOOL;typedef BYTE near *PBYTE; /* 指向字节类型指针 */typedef BYTE far *LPBYTE;typedef int near *PINT; /* 整形指针 */ typedef int far *LPINT;typedef WORD near *PWORD; /* 指向WORD 类型的指针 */typedef WORD far *LPWORD;typedef long far *LPLONG; /* 指向长整形的指针 */typedef DWORD near *PDWORD; /* 指向DWORD 类型的指针 */typedef DWORD far *LPDWORD;typedef void far *LPVOID; /* 指向void 类型的指针 */typedef CONST void far *LPCVOID; /* 指向void 类型的常指针 */简单说下,大部分类型都没有什么离奇的地方,可能很多人会对那个far 和near 觉得有疑问,实际上F12查看定义会发现他们就定义上方1 2 #define far#define near看到这里你是否还是有疑问?那么博主这里直接说了,这个 far 和 near 只是用来标识变量的新旧的(预处理阶段far 和near 会被替换成空字符串)。
WindowsAPI编程入门
WindowsAPI编程⼊门Windows ⼯作原理的中⼼思想就是“动态链接”概念。
Windows ⾃⾝带有⼀⼤套函数,应⽤程序就是通过调⽤这些函数来实现它的⽤户界⾯和在屏幕上显⽰⽂本和图形的。
这些函数都是在动态链接库⾥实现的。
这些⽂件的名称都带有后缀 .dll,或有时带有 .exe。
Windows 的 3 个主要⼦系统:内核(kernel),⽤户(user),GDI。
内核负责操作系统的传统⼯作:如内存管理,⽂件输⼊/输出以及任务管理等。
⽤户指的是⽤户界⾯,负责所有的窗⼝管理。
GDI 就是图形设备接⼝,负责在屏幕或打印机上显⽰⽂本与图形。
在 Windows 程序中,调⽤ Windows 函数与调⽤ C 语⾔的库函数没有什么两样。
最主要的区别就是 C 语⾔库函数的机器代码会直接链接到你的程序代码中去,⽽ Windows 函数则是放到你的程序之外的 DLL ⾥。
Windows 程序运⾏时,它通过⼀个叫“动态链接”的进程与 Windows 接⼝。
每个 Windows 的 EXE ⽂件包含它所要⽤到的各个动态链接库以及库中的函数的引⽤地址。
当⼀个 Windows 程序被装⼊内存后,程序中的函数调⽤都被解析 DLL 函数⼊⼝的指针,同时这些被调⽤的函数也被装⼊内存。
当链接 Windows 程序以⽣存可执⾏⽂件时,⼀定得链接你的编程环境所提供的特殊的“导⼊库”。
这些导⼊库包含所有 Windows 函数调⽤要碰到的动态链接库的名字及引⽤信息。
链接程序利⽤这些信息构建 EXE ⽂件中的表格,当装⼊程序的时候,Windows 要靠这些表格来解析 Windows 函数调⽤。
另外值得提醒的⼀点是,MFC 是对 API 的封装,隐藏了许多复杂的情节。
Windows 的 Hello World!程序:#include <windows.h>int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow){MessageBox (NULL, TEXT ("Hello, World!"), TEXT ("HelloMsg"), MB_OKCANCEL) ;return0 ;}该程序的 #include<windows.h> 就是像 C 语⾔的 #include<stdio.h> ⼀样重要的头⽂件。
Windows API编程入门教程
Windows API编程入门教程学习各种高级外挂制作技术,马上去百度搜索(魔鬼作坊),点击第一个站进入,快速成为做挂达人。
大家好再次自我介绍一下我是beyondcode,这次心血来潮,计划着做一系列关于Windows API编程的教程,用于帮助一些在Windows API编程上有疑惑的,纳闷的,迷惑的新手朋友们。
先解释一些术语或名词吧SDK是Software Development Kit的简写,也就是软件开发包的意思,其中就包含了我们写程序要用到的一些头文件,库,工具,帮助文档之类的。
Windows API编程是指调用Windows的接口函数来进行程序的编写,例如MessageBox就是一个API函数或者说接口函数。
怎么说都可以,自己理解就行。
如果你连这个都不太懂,我想也不会搜到这篇文章了吧~·为什么做这个系列教程呢,请听我一一道来先,最近遇到一些事一些人,让我真的感觉在这方面的引导入门文章真的很是匮乏,加上Windows SDK头文件中那些复杂,庞大,'烦人'的宏定义与数据类型定义,对于一个新手来说(我所说的新手不单只刚接触编程的,还特指那些在其他语言领域有比较高造诣的朋友)一个纯SDK写的helloworld程序都算是一个有些困难和挑战的任务了吧。
本着帮助别人,高兴自己的原则,我有了这个打算,当然对自己以前所学,所经历做一次回忆,也是这次计划的一部分。
声明一下,本系列教程是面向广大初次接触WIN32SDK程序编写的新手朋友们的,如果你是高手,一笑而过吧~当然,除了一笑而过,也多谢你们提出指正文章中的错误,以免我误人子弟啊~~谢谢Ok废话不多说,进入正题,今天第一篇,讲什么?对于一个新人来说,第一次接触SDK 编程或者说API编程,什么最迷惑你们的,我们讲它,我觉得Windows SDK中那'烦人'的数据类型定义和宏定义应该算这个很角色吧。
其实微软的本意也是善良的,为了减轻程序员的负担,和为了编程的方便,才花了那么多心思与精力定义出了这么一大套数据类型与宏定义,这也是我为什么在之前说它烦人都是加上引号的原因,因为他不是真的烦人,熟练了,你不但不觉得它烦,反而离不开它了,呵呵,日久深情也就是这么来的。
windows API编程(上)
为了将单字节字符扩充为双字节字符,系统会自动在单字节字符后插入 0。例如,单字节字
符 W 在 intel 处理器内存储为 57,而双字节字符 W 则存储为 57 00.
字符串处理函数:
对双字节字符串的处理与单字节字符串不同。
单字节用 strlen,如
iStringLength = strlen (“this is a Unicode string”); // i 代表 int 即:int StringLength = ………
wchar_t ch=’W’; //定义单个字符 w
wchar_t *ch=L”this is a Unicode string”; //定义字符串指针
wchar_t ch[ ] = L“this is a Unicode string”; //定义字符数组
其中,字符串前面的 L 表示编译器将字符串按 Unicode 保存,即每个字符占 2 个字节
程序入口点:
Windows 程序的入口点总是 WinMain 函数,该函数定义如下:
Int WINAPI WinMain (
HINSTANCE hInstance,
//当前实例句柄
HINSTANCE hPrevInstance, //总是置空
LPSTR IpCmdLine,
//命令行
Int nCmdShow
件实现对单字节和双字节字符串的统一处理,根据该文件中定义的字符串处理函数,可以根
据是否定义了 UNICODE 宏来分别处理 Unicode 字符集和单字节字符集。
// TCHAR 表示既可以指向 windows 字符又可以指向 Unicode 字符
以计算字符串长度为例,处理单字节和双字节字符串的统一函数是 _tcslen ,在 TCHAR.H 中
WindowsAPI入门系列(6)自己实现MessageBox
API入门系列文章的第六篇之自己动手实现MessageBox。
我在第四篇文章:一个相当简单的SDK程序中讲到了通过调用MessageBoxAPI函数来弹出一个对话框,那你有没有想过,我们一句简单的代码背后所隐藏的细节是怎么的呢,那时候让你了解这些未免还早了些,不过现在时机到了,通过一些基本的API函数调用来实现一个自己的对话框其实也不是很难,那么这一篇文章就是这个目的。
并顺带介绍一些基本API的应用,由于前面五篇文章的铺垫,我相信你对SDK 的程序的大致结构和相关字符处理都有所了解了,所以在这篇文章中的这些知识点,我就不再多说,以免有些人觉得我实在太过啰嗦。
实在疑惑的,可以参看前面的文章。
首先我先大概的列出我们为完成这个任务所要用到的一些API函数他SetWindowText 设置窗口的标题GetClientRect 得到窗口客户区的大小信息GetWindowLongPtr 通过窗口句柄得到和窗口的相关联信息CreateWindowEx 创建窗口BeginPaint 得到窗口的设备句柄EndPaint 释放窗口的设备句柄DrawText 通过设备句柄在窗口上画出文字好了,就这些函数,我们就能自己实现有一个确定按钮并在确定按钮正上方显示提示信息的简易的对话框了,不过这个对话框可是我们一句一句代码自己实现的哟~~还是比较有成就感吧~程序的大体框架呢还是我们上一篇文章中的框架,注册窗口类,创建一个主窗口,消息循环,窗口消息处理函数。
不过要我们需要在窗口消息处理函数中添加一些代码来完成我们需要的功能。
在什么地方添加呢? 上个程序,我们只处理WM_DESTROY这个消息。
对于这个消息我不再做讲解,不懂的或者忘记了的可以自己MSDN或者看上一篇文章,这里我们要添加对两个消息的处理代码,首先是WM_CREA TE,这个消息会在一个窗口被创建的时候被发送到窗口消息处理函数,如果一些事情需要在一个窗口刚被创建的时候执行,那么通过处理WM_CREA TE最合适不过啦,代码如下:case WM_CREA TE:{RECT rctClient; //用来存放主窗口客户区大小信息const int buttonWidth = 80; //按钮的宽const int buttonHeight = 25; /按钮的高GetClientRect( hwnd, &rctClient ); //得到主窗口客户区的大小信息HINSTANCE hInst = (HINSTANCE)GetWindowLongPtr( hwnd, GWLP_HINSTANCE );HWND hButton = CreateWindowEx( 0L, _T("button"), _T("确定"), WS_VISIBLE |WS_CHILD, rctClient.right/2-buttonWidth/2, rctClient.bottom/2-buttonHeight/2, buttonWidth,buttonHeight, hwnd, (HMENU)2, hInst, NULL );SetWindowText( hwnd, _T("自定义对话框") );break;}在WM_CREA TE消息的处理中,我们就用到了GetClientRect,它的第一个参数是窗口的句柄,你想要获取哪个窗口的客户区大小,你就将传递哪个窗口的句柄,第二个参数是一个RECT结构的指针,我上面定义了一个rctClient变量,然后这里把这个变量的地址传递给GetClientRect的第二个参数,让它将所得到的窗口的大小信息保存到这个变量里面。
Windows API 编程
* 几个重要的概念
* 函数名作为参数的例子
* GDI 概述
* 画笔与画刷
* GDI 绘图函数
* GDI 映射模式
GDI 绘图函数
* COLORREF SetPixel (HDC hdc,int nXPos,int nYPos, COLORREF crColor);
// 布尔值 MoveTo (设备环境句柄,横坐标,纵坐标)
* BOOL LineTo (HDC hdc, int nXEnd, int nYEnd);
// 布尔值 LineTo (设备环境句柄,终点横坐标,终点纵坐标)
第二章:GDI 编程
* 几个重要的概念
* 函数名作为参数的例子
* GDI 的特性
设备无关性
* GDI 的来源
在Windows系统中,有个动态链接库GDI32.DLL,负责图形的输出。该动态链接库为应用程序提供了访问设备驱动程序的方法。
第二章:GDI 编程
* 几个重要的概念
* 函数名作为参数的例子
* GDI 概述
* 画笔与画刷
} LOGPEN, *PLOGPEN;
3. HPEN ExtCreatePen (DWORD dwPenStyle, DWORD dwWidth, CONST LOGBRUSH *lplb, DWORD dwStyleCount, CONST DWORD *lpStyle) //Geometic 画笔
* GDI 绘图函数
* GDI 映射模式
颜色的表示与设置
* 颜色的表示
Windows采用32位无符号整形表示色彩,即COLORREF值,按照红、绿、蓝三种颜色的亮度指定一种颜色,其中,每种颜色的值占8位,范围从0-255。
Windows API学习
第一课∶认识API一、什么是API首先,有必要向大家讲一讲,什么是API。
所谓API本来是为C和C++程序员写的。
API 说来说去,就是一种函数,他们包含在一个附加名为DLL的动态连接库文件中。
用标准的定义来讲,API就是Windows的32位应用程序编程接口,是一系列很复杂的函数,消息和结构,它使编程人员可以用不同类型的编程语言编制出的运行在Windows95和Windows NT 操作系统上的应用程序。
可以说,如果你曾经学过VC,那么API对你来说不是什么问题。
但是如果你没有学过VC,或者你对Windows95的结构体系不熟悉,那么可以说,学习API 将是一件很辛苦的事情。
如果你打开WINDOWS的SYSTEM文件夹,你可以发现其中有很多附加名为DLL的文件。
一个DLL中包含的API函数并不只是一个,数十个,甚至是数百个。
我们能都掌握它嘛?回答是否定的∶不可能掌握。
但实际上,我们真的没必要都掌握,只要重点掌握Windos系统本身自带的API函数就可以了。
但,在其中还应当抛开掉同VB本身自有的函数重复的函数。
如,VB的etAttr命令可以获得文件属性,SetAttr可以设置文件属性。
对API来讲也有对应的函数GetFileAttributes和SetFileAttributes,性能都差不多。
如此地一算,剩下来的也就5、600个。
是的,也不少。
但,我可以敢跟你说,只要你熟悉地掌握100个,那么你的编程水平比现在高出至少要两倍。
尽管人们说VB和WINDOWS具有密切的关系,但我认为,API更接近WINDOWS。
如果你学会了API,首要的收获便是对WINDOWS体系结构的认识。
这个收获是来自不易的。
如果你不依靠API会怎么样?我可以跟你说,绝大多是高级编程书本(当然这不是书的名程叫高级而高级的,而是在一开始的《本书内容》中指明《本书的阅读对象是具有一定VB基础的读者》的那些书),首先提的问题一般大都是从API开始。
使用WindowsAPI进行串口编程
使⽤WindowsAPI进⾏串⼝编程串⼝通信⼀般分为四⼤步:打开串⼝->配置串⼝->读写串⼝->关闭串⼝,还可以在串⼝上监听读写等事件。
1、打开和关闭串⼝Windows中串⼝是作为⽂件来处理的,调⽤CreateFile()函数可以打开串⼝,函数执⾏成功返回串⼝句柄,出错返回INVALID_HANDLE_VALUE。
HANDLE WINAPI CreateFile(_In_ LPCTSTR lpFileName,//要打开或创建的⽂件名_In_ DWORD dwDesiredAccess,//访问类型_In_ DWORD dwShareMode,//共享⽅式_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,//安全属性_In_ DWORD dwCreationDisposition,//指定要打开的⽂件已存在或不存在的动作_In_ DWORD dwFlagsAndAttributes,//⽂件属性和标志_In_opt_ HANDLE hTemplateFile//⼀个指向模板⽂件的句柄);lpFileName:要打开或创建的⽂件名。
dwDesiredAccess:访问⽅式。
0为设备查询访问⽅式;GENERIC_READ为读访问;GENERIC_WRITE为写访问;dwShareMode:共享⽅式。
0表⽰⽂件不能被共享,其它打开⽂件的操作都会失败;FILE_SHARE_READ表⽰允许其它读操作;FILE_SHARE_WRITE表⽰允许其它写操作;FILE_SHARE_DELETE表⽰允许其它删除操作。
lpSecurityAttributes:安全属性。
⼀个指向SECURITY_ATTRIBUTES结构的指针。
dwCreationDisposition:创建或打开⽂件时的动作。
OPEN_ALWAYS:打开⽂件,如果⽂件不存在则创建它;TRUNCATE_EXISTING 打开⽂件,且将⽂件清空(故需要GENERIC_WRITE权限),如果⽂件不存在则会失败;OPEN_EXISTING打开⽂件,⽂件若不存在则会失败;CREATE_ALWAYS创建⽂件,如果⽂件已存在则清空;CREATE_NEW创建⽂件,如⽂件存在则会失败;dwFlagsAndAttributes:⽂件标志属性。
Windows编程基础(新手入门)
Windows编程基础(新手入门)Windows编程基础第1章基于Windows的编程方式有两种。
一种是使用Windows的API (Application Programming Interface,应用程序编程接口)函数,通常用C/C++语言按相应的程序框架进行编程。
这些程序框架往往就程序应用提供相应的文档、范例和软件开发工具包(Software Development Kit,SDK),所以这种编程方式有时又称为SDK方式。
另一种是使用“封装”方式,例如Visual C++的MFC方式,它是将SDK中的绝大多数函数、数据等按C++“类”的形式进行封装,并提供相应的应用程序框架和编程操作。
事实上,无论是哪种编程方式,人们最关心的内容有三个:一是程序入口,二是窗口、资源等的创建和使用,三是键盘、鼠标等所产生的事件或消息的接收和处理。
本章就来讨论这些内容。
学习编程往往从简单的例子入手,例如一个C程序常有下列简单的框架代码:#include <stdio.h>int main(){printf("Hello World!\n");return 0;} /* 输出 */ /* 指定返回值 */事实上,该程序已包括C程序中最常用的#include指令、必须的程序入口main函数、库函数printf调用和return语句。
由于此程序是在早期的DOS(Disk Operating System,磁盘操作系统)环境的字符模型下运行的,因而printf函数所输出的都是字符流,也就是说,它在屏幕上输出一行文本“Hello World!”。
在Windows环境下,这里的屏幕就由控制台窗口来兼作,而基于Windows的上述C程序代码框架肯定是有所不同的。
特别地,由于目前所在的Windows环境基本上都是32位,所以这里的Windows程序平台就是Win32,Windows编程可直接理解为是Win32编程。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Windows API编程入门教程学习各种高级外挂制作技术,马上去百度搜索(魔鬼作坊),点击第一个站进入,快速成为做挂达人。
大家好再次自我介绍一下我是beyondcode,这次心血来潮,计划着做一系列关于Windows API编程的教程,用于帮助一些在Windows API编程上有疑惑的,纳闷的,迷惑的新手朋友们。
先解释一些术语或名词吧SDK是Software Development Kit的简写,也就是软件开发包的意思,其中就包含了我们写程序要用到的一些头文件,库,工具,帮助文档之类的。
Windows API编程是指调用Windows的接口函数来进行程序的编写,例如MessageBox就是一个API函数或者说接口函数。
怎么说都可以,自己理解就行。
如果你连这个都不太懂,我想也不会搜到这篇文章了吧~·为什么做这个系列教程呢,请听我一一道来先,最近遇到一些事一些人,让我真的感觉在这方面的引导入门文章真的很是匮乏,加上Windows SDK头文件中那些复杂,庞大,'烦人'的宏定义与数据类型定义,对于一个新手来说(我所说的新手不单只刚接触编程的,还特指那些在其他语言领域有比较高造诣的朋友)一个纯SDK写的helloworld程序都算是一个有些困难和挑战的任务了吧。
本着帮助别人,高兴自己的原则,我有了这个打算,当然对自己以前所学,所经历做一次回忆,也是这次计划的一部分。
声明一下,本系列教程是面向广大初次接触WIN32SDK程序编写的新手朋友们的,如果你是高手,一笑而过吧~当然,除了一笑而过,也多谢你们提出指正文章中的错误,以免我误人子弟啊~~谢谢Ok废话不多说,进入正题,今天第一篇,讲什么?对于一个新人来说,第一次接触SDK 编程或者说API编程,什么最迷惑你们的,我们讲它,我觉得Windows SDK中那'烦人'的数据类型定义和宏定义应该算这个很角色吧。
其实微软的本意也是善良的,为了减轻程序员的负担,和为了编程的方便,才花了那么多心思与精力定义出了这么一大套数据类型与宏定义,这也是我为什么在之前说它烦人都是加上引号的原因,因为他不是真的烦人,熟练了,你不但不觉得它烦,反而离不开它了,呵呵,日久深情也就是这么来的。
呵呵先看几个数据类型定义吧typedef float FLOAT;typedef long LONG;typedef short SHORTtypedef int INT;typedef char CHAR;float,long,short,int,char这几个数据类型都是大家熟悉的C/C++的数据类型吧,微软将他们重新定义了一下,很简单,就是改变名字为大写了,这样做的目的大概是微软为了编码的方便吧,输入法大小写都不用切换了,多人性化呀呵呵。
再看几个数据类型定义的例子typedef unsigned int UINT;typedef unsigned int UINT32;typedef signed int INT32;typedef unsigned long DWORD;typedef unsigned short WORD;这些数据类型的定义就稍微有实质性作用一些了,注意观察,他们都比较短了,不用写那么长了,而且也还比较直观,如果我要定义一个无符号整形,我就不用写unsigned int a;这么长了,只需UINT a;多简单,多明了,所以我说其实不烦人吧。
其中DWORD算是SDK程序中可以经常看见的一个数据类型了,经常被使用,很多新手也就不明白,这是什么数据类型啊,现在看到了吧,其实就是无符号长整形unsigned long,给他取了个外号而已··没什么技术含量,所以不用怕,程序中究竟是写unsigned long还是DWORD都看你自己心情,因为他们都代表同一种数据类型。
下面再介绍2个很重要的,经常被使用到的,无处不在的数据类型WPARAM,LPARAM先看看他们定义吧typedef LONG_PTR LPARAM;typedef UINT_PTR WPARAM;先告诉你,这2个数据类型很重要,不是危言耸听,以后你写SDK程序就知道了,看他们的定义如上,有些迷糊?别,我们一步一步分析,我们分析LPARAM。
首先定义LPARAM为LONG_PTR也就是用LPARAM的地方也就可以写成LONG_PTR,LONG_PTR又是被定义成什么的呢?typedef long LONG_PTR;看到了吗?也就是long所以归根结底,LPARAM就是long型,所有LPARAM型的变量,你都可以直接使用long数据类型代替。
不过不推荐这样,至于为什么,各位思考思考呢~~以上这些数据类型是参考MSDN中的说明,或者可以查看WinDef.h这个头文件查看这些Windows数据类型的定义,那么也请各位自己推推看LARAM和WPARAM的真面目吧~各位朋友在推导的过程中可能发现LONG_PTR的定义是这样写的#if defined(_WIN64)typedef__int64LONG_PTR;#elsetypedef long LONG_PTR;#endif这是什么意思呢,能看懂英文都能知道这在定义些什么,如果定义了_WIN64这个宏那么就定义LONG_PTR为__int64,否则定义LONG_PTR为long。
很简单吧也就是说如果_WIN64这个宏在前面被定义了,那么这里的LONG_PTR就被定义为__int64这个在64位编程下的数据类型,否则就定义为long型,这样说应该比较好理解了吧。
在这里,各位就不必深究__int64了,在目前的主流32位编程下很少使用它啦。
理解就ok了。
这样定义是微软为了程序员编写的程序能在32位与64位下都能编译而采用的伎俩。
有关这些Windows的数据类型,想查看他们的真面目,其实很简单,在VC6.0,VS2008这些集成开发环境里面,你只需要在一个数据类型上面点击右键,在弹出菜单中选择‘Goto Defination’或者是‘查看定义’就可以看到了,如果看到的还不是最终面目,在继续上面步骤。
直到看到它的本质数据类型为止。
通过这样,新手对于Windows的这些复杂的数据类型定义也就有了根本的认识,不再是迷迷糊糊,在以后的编程中也就不会出现不知道用哪种数据类型或者哪些数据类型之间可以相互转换的情况了。
不过还需要多多观察与练习才是啊~~下面再来看一看windows中定义的一些宏#define VOID void#define CONST const2个最简单的宏,也是只变成大写而已,难道又是为了方便程序员不切换输入法?还真的人性化呀。
Windows SDK中的宏定义是最庞大的,最复杂的,但也是最灵活的,为什么这样说,先不告诉你,我会在以后的系列文章中一点一点的讲解,累积,因为太多了,也比较复杂,我们就采取在需要用到的时候才讲解它,目前看来还没这个必要了解那么多,就了解上面2个很简单的好了,像其他如:WINAPI CALLBACK GetWindowText这些宏现在讲了不但记不住还会增加你们的负担。
,我们就在以后要用到的时候再做讲解。
到这里第一篇系列文章的内容也就差不多了。
新手朋友们哪些地方迷惑的,提出来,我可以考虑是否加在后续的文章中进行解说。
本SDK系列入门教程需要你们的支持。
谢谢。
今天,开始第二篇文章,这章我准备介绍一下Windows平台下编程中Unicode编码和ASCII 编码的相关问题。
不知道各位新手朋友们遇到这样的问题没有呢,新建一个Windows应用程序,调用MessageBox这个函数,准备让它弹出一段提示文本,可是编译器在编译的时候却报错说,不能将const char*或者const char[]转换为const wchar_t*之类的提示呢,很多刚接触Windows API编程的朋友们在这里可能就卡住了,不知如何下手解决了,其实,这就是Unicode编码和ASCII编码的问题了。
我下面就会一一道来关于Unicode和ASCII具体的编码是怎么的,我这里就不详细介绍了,也介绍不了,如果需要深入了解,网上有很多这方面的专门文章,我这里就只对Unicode编码和ASCII编码在Windows平台下的编程相关的内容进行介绍。
我们都知道Unicode和ASCII最大的区别就是Unicode采用2个字节来存储一个字符,不管是英文,汉字,还是其他国家的文字,都有能用2个字节来进行编码,而ASCII采用一个字节存储一个字符,所以对于英文的编码,那是足够的了,可是对于汉字的编码,则必须采用一些特殊的方法,用2个ASCII字符来表示一个汉字。
我们在写程序的过程中,势必要和字符打交道,要输入,获取,显示字符,到底是选用Unicode 字符呢还是ASCII字符呢,这都是各位自己的权利。
但为了程序的通用性和符合目前操作系统的主流趋势,Unicode编码是被推荐的。
由于Unicode字符要比ASCII字符占用的空间大一倍,编译出来的程序在体积上和占用的内存上必定要大一些,不过这并不是什么很大的问题。
所以微软目前的SDK中保留了2套API,一套用于采用Unicode编码处理字符的程序的编写,一套用于采用ASCII编码处理字符的程序的编写。
例如,我们上面提到的MessageBox,它其实不是一个函数名,而是一个宏定义,我们先来看看它是怎么被定义的,再来讨论它。
#ifdef UNICODE#define MessageBox MessageBoxW#else#define MessageBox MessageBoxA#endif看到了吗?很简单是不是,如果定义了UNICODE这个宏那么就定义MessageBox为MessageBoxW,如果没有定义UNICODE这个宏,那么就定义MessageBox为MessageBoxA,MessageBox后面的W和A就是代表宽字节(Unicode)和ASCII,这样,其实存在于SDK中的函数是MessageBoxW和MessageBoxA这两个函数.MessageBox只是一个宏而已。
所以在程序中,这3个名字你都可以使用,只不过需要注意的是,使用MessageBoxA的话,那么你要注意传给它的参数,字符都必须是单字节,也就是ASCII,在程序中就是char,如果使用MessageBoxW的话,那么,字符都必须使用Unicode,程序中就是wchar_t。
但是这样有个非常不方便的地方那就是,如果你使用W后缀系列的函数的话,那么你的程序使用的字符就是Unicode字符编码的,但是如果你需要用这个程序的源代码编译出字符采用ASCII编码的程序,那么需要改动的地方就太大了。