Ⅰ Windows核心编程的目录
译者序
前言
作译者简介
第一部分 程序员必读
第1章 错误处理
1.1 自定义错误处理的实现
1.2 错误显示例程
第2章 Unicode
2.1字符集
2.1.1 单字节和双字节字符集
2.1.2 Unicode:宽字节字符集
2.2 为何需要Unicode
2.3 Windows 2000和Unicode
2.4 Windows 98和Unicode
2.5 Windows CE和Unicode
2.6 评论
2.7 关于COM
2.8 如何编写Unicode源代码
2.8.1 C运行库的Unicode支持
2.8.2 Windows定义的Unicode数据类型
2.8.3 Windows系统中的Unicode函数和ANSI函数
2.8.4 Windows字符串函数
2.9 让应用程序符合ANSI和Unicode规范
2.9.1 Windows字符串函数
2.9.2 资源
2.9.3 确定文本是ANSI型还是Unicode型
2.9.4 在Unicode和ANSI间转换字符串
第3章内核对象
3.1内核对象的概念
3.1.1 使用计数
3.1.2 安全性
3.2内核对象句柄表
3.2.1 创建内核对象
3.2.2 关闭内核对象
3.3 进程间内核对象的共享
3.3.1 对象句柄的继承性
3.3.2 改变句柄标志
3.3.3 命名对象
3.3.4终端服务器命名空间
3.3.5 复制对象句柄
第二部分 完成编程任务
第4章 进程
4.1 编写第一个Windows应用程序
4.1.1 进程的实例句柄
4.1.2 进程的前一个实例句柄
4.1.3 进程的命令行
4.1.4 进程的环境变量
4.1.5 亲缘性
4.1.6 进程的错误模式
4.1.7 当前驱动器和目录
4.1.8当前目录
4.1.9 系统版本
4.2 CreateProcess函数
4.2.1 pszApplicationName和pszCommandLine
4.2.2 psaProcess、psaThread和bInheritHandles
4.2.3 fdwCreate
4.2.4 pvEnvironment
4.2.5 pszCurDir
4.2.6 psiStartInfo
4.2.7 ppiProcInfo
4.3 进程的终止
4.3.1主线程的入口函数返回
4.3.2 ExitProcess函数
4.3.3 TerminateProcess函数
4.3.4 进程中所有线程的运行终止
4.3.5 进程的运行终止
4.4 子进程
4.5 枚举系统中运行的进程
第5章 作业
5.1 对作业进程的限制
5.2 把进程放入作业
5.3 终止作业中所有进程的运行
5.4 查询作业统计信息
5.5 作业通知信息
5.6 JobLab示例应用程序
第6章 线程的基本知识
6.1 创建线程的时机
6.2 何时不能创建线程
6.3 编写第一个线程函数
6.4 CreateThread函数
6.4.1 psa
6.4.2 cbStack
6.4.3 pfnStartAddr和pvParam
6.4.4 fdwCreate
6.4.5 pdwThreadID
6.5 终止线程
6.5.1 线程函数返回
6.5.2 ExitThread函数
6.5.3TerminateThread函数
6.5.4 在进程终止运行时终止线程
6.5.5 线程终止运行时发生的操作
6.6 线程的一些内部细节
6.7 对于C/C++运行时库的考虑
6.7.1 Oops—错误地调用了CreateThread
6.7.2 不该调用的C/C++运行时库函数
6.8 线程的身份标识
第7章 线程的调度、优先级和亲缘性
7.1 挂起和恢复线程的运行
7.2 进程的挂起和唤醒
7.3 睡眠
7.4 线程切换
7.5 线程的运行时间
7.6 上下文环境切换
7.7 线程优先级
7.8 优先级的抽象说明
7.9 编程优先级
7.9.1 动态提高线程的优先级等级
7.9.2 为前台进程调整调度程序
7.9.3 Scheling Lab示例应用程序
7.10 亲缘性
第8章 用户模式下的线程同步
8.1 原子访问:互锁函数族
8.2 高速缓存行
8.3 高级线程同步
8.4临界区
8.4.1临界区准确的描述
8.4.2临界区与循环锁
8.4.3临界区与错误处理
8.4.4 有用的提示和技巧
第9章 线程与内核对象的同步
9.1等待函数
9.2 成功等待的副作用
9.3 事件内核对象
9.4 等待定时器内核对象
9.4.1 用等待定时器给APC项排队
9.4.2定时器的松散特性
9.5信号量内核对象
9.6 互斥内核对象
9.6.1 释放问题
9.6.2互斥对象与临界区的比较
9.6.3 Queue应用程序示例
9.7线程同步对象表
9.8 其他线程同步函数
9.8.1 异步设备I/O
9.8.2WaitForInputIdle
9.8.3 MsgWaitForMultipleObjects(Ex)
9.8.4 WaitForDebugEvent
9.8.5SignalObjectAndWait
第10章线程同步工具包
10.1临界区的实现:Optex
10.2 创建线程安全的数据类型和反信号量
10.3 单写入多读出程序的保护
10.4 WaitForMultipleExpressions函数的实现
第11章线程池
11.1 场景1:异步调用函数
11.2 场景2:按规定的时间间隔调用函数
11.3 场景3:在某个内核对象变为已通知状态时调用函数
11.4 场景4:异步I/O请求运行完成时调用函数
第12章纤程
12.1 使用纤程
12.2 Counter示例应用程序
第三部分内存管理
第13章 Windows内存结构
13.1 进程的虚拟地址空间
13.2 虚拟地址空间分区
13.2.1 无效断点分配分区(适于Windows 2000和Windows 98)
13.2.2MS-DOS/16位Windows应用程序兼容分区(仅适于Windows 98)
13.2.3 用户模式分区(适用Windows 2000和Windows 98)
13.2.4 64KB禁止进入分区(仅适用于Windows 2000)
13.2.5 共享的MMF分区(仅适用于Windows 98)
13.2.6 内核模式分区(使用于Windows 2000和Windows 98)
13.3地址空间区域
13.4 在地址空间区域中提交物理存储器
13.5 物理存储器和页面文件
13.6 保护属性
13.6.1 Copy-On-Write访问
13.6.2 特殊访问保护属性标志
13.7 综合使用所有元素
13.7.1 区域的内部详情
13.7.2 Windows 98上地址空间的差异
13.8 数据对齐的重要性
第14章虚拟内存
14.1系统信息
14.2虚拟内存的状态
14.3 确定地址空间状态
14.3.1 VMQery函数
14.3.2虚拟内存表应用程序示例
第15章应用程序中虚拟内存的使用
15.1地址空间中保留区域
15.2 在保留区域中提交存储器
15.3 同时进行保留区域并提交内存
15.4 何时提交物理存储器
15.5 物理存储器的回收和地址空间区域的释放
15.5.1 何时回收物理存储器
15.5.2虚拟内存分配示例应用程序
15.6 改变保护属性
15.7 清除物理存储器内容
15.8 地址窗口扩展(仅使用于Windows 2000)
第16章 线程栈
16.1 Windows 98下的线程栈
16.2 C/C++运行时库中的栈检测函数
16.3 Summation示例应用程序
第17章内存映射文件
17.1 内存映射的可执行文件和DLL文件
17.1.1可执行文件或DLL的多个实例之间无法共享的静态数据
17.1.2 在可执行文件或DLL的多个实例之间共享静态数据
17.1.3 AppInst示例应用程序
17.2 内存映射数据文件
17.2.1 方法1:一个文件,一个缓存
17.2.2 方法2:两个文件,一个缓存
17.2.3 方法3:一个文件,两个缓存
17.2.4 方法4:一个文件,零个缓存
17.3 使用内存映射文件
17.3.1 步骤1:创建或打开文件内核对象
17.3.2 步骤2:创建文件映射内核对象
17.3.3 步骤3:将文件数据映射到进程地址空间
17.3.4 步骤4:进程地址空间中撤销文件数据的映像
17.3.5 步骤5和步骤6:关闭文件映射对象和文件对象
17.3.6 文件倒序示例应用程序
17.4 使用内存映射文件处理大文件
17.5内存映射文件的一致性
17.6 设定内存映射文件的基地址
17.7 实现内存映射文件的具体细节
17.8 使用内存映射文件在进程之间实现数据共享
17.9 受页面文件支持的内存映射文件
17.10 稀疏提交的内存映射文件
第18章 堆
18.1 进程的默认堆
18.2 创建辅助堆的原因
18.2.1 保护组件
18.2.2 更有效地管理内存
18.2.3 进行本地访问
18.2.4 减少线程同步开销
18.2.5 快速释放
18.3 创建辅助堆的方法
18.3.1 分配堆中的内存块
18.3.2 改变内存块的大小
18.3.3 获取内存块的大小
18.3.4 释放内存块
18.3.5 销毁堆
18.3.6 用C++程序使用堆
18.4 其他堆函数
第四部分动态链接库
第19章 DLL基础
19.1 DLL与进程的地址空间
19.2 DLL的总体运行情况
19.3 创建DLL模块
19.3.1 导出的真正含义
19.3.2 使用非Visual C++工具创建DLL
19.4 创建可执行模块
19.5 运行可执行模块
第20章 DLL高级技术
20.1 显式加载DLL模块和符号链接
20.1.1 显式加载DLL模块
20.1.2 显式卸载DLL模块
20.1.3 显式链接到导出符号
20.2 DLL的入口函数
20.2.1 DLL_PROCESS_ATTACH通知
20.2.2 DLL_PROCESS_DETACH通知
20.2.3 DLL_THREAD_ATTACH通知
20.2.4 DLL_THREAD_DETACH通知
20.2.5顺序调用DllMain
20.2.6 DllMain和C/C++运行时库
20.3延迟加载DLL
20.4 函数转发器
20.5 已知的DLL
20.6 DLL重定向
20.7 模块的基址重置
20.8 绑定模块
第21章 线程本地存储
21.1 动态TLS
21.2 静态TLS
第22章 DLL注入以及API挂接
22.1 DLL注入:一个例子
22.2 使用注册表注入DLL
22.3 使用Windows钩子注入DLL
22.4 使用远程线程注入DLL
22.4.1 Inject Library示例应用程序
22.4.2 Image Walk DLL
22.5 使用特洛伊DLL注入DLL
22.6 将DLL作为调试程序注入
22.7 在Windows 98平台上使用内存映射文件注入代码
22.8 使用CreateProcess来注入代码
22.9 API挂接:一个例子
22.9.1 通过覆写代码实现API挂接
22.9.2 通过操作模块的导入部分来实现API挂接
22.9.3 LastMsgBoxInfo示例应用程序
第五部分结构化异常处理
第23章 终止处理例程
23.1 Funcenstein1
23.2 Funcenstein2
23.3 Funcenstein3
23.4 Funcfurter1
23.5 小测验:FuncaDoodleDoo
23.6 Funcenstein4
23.7 Funcarama1
23.8 Funcarama2
23.9 Funcarama3
23.10 Funcarama4:最终的边界
23.11 有关finally块的说明
23.12 Funcfurter2
23.13 SEH终止示例应用程序
第24章 异常处理程序和软件异常
24.1 通过例子理解异常过滤器和异常处理程序
24.1.1 Funcmeister1
24.1.2 Funcmeister2
24.2 EXCEPTION_EXECUTE_HANDLER
24.2.1 一些有用的例子
24.2.2 全局展开
24.2.3 暂停全局展开
24.3 EXCEPTION_CONTINUE_EXECUTION
24.4 EXCEPTION_CONTINUE_SEARCH
24.5GetExceptionCode
24.5.1 与内存相关的异常
24.5.2 与异常相关的异常
24.5.3 与调试相关的异常
24.5.4 与整数相关的异常
24.5.5 与浮点数相关的异常
24.6 GetExceptionInformation
24.7软件异常
第25章 未处理异常和C++异常
25.1 即时调试
25.2 关闭异常消息框
25.2.1 强制进程终止运行
25.2.2 包装一个线程函数
25.2.3 包装所有的线程函数
25.2.4 自动调用调试器
25.3 自己调用UnhandledExceptionFilter
25.4 UnhandledExceptionFilter函数的内部细节
25.5 异常和调试程序
25.6 C++异常与结构化异常比较
第六部分 窗口
第26章 窗口消息
26.1 线程的消息队列
26.2 将消息投送到一个线程的消息队列中
26.3 向窗口发送消息
26.4 唤醒一个线程
26.4.1 队列状态标志
26.4.2 从线程队列中提取消息的算法
26.4.3 使用内核对象或者队列状态标志来唤醒一个线程
26.5 使用消息发送数据
26.6 Windows处理ANSI/Unicode字符和字符串的方法
第27章 硬件输入模型与本地输入状态
27.1 原始输入线程
27.2 本地输入状态
27.2.1 键盘输入和焦点
27.2.2 鼠标光标管理
27.3 将虚拟输入队列和本地输入状态相关联
27.3.1 LISLab示例应用程序
27.3.2 LISWatch示例应用程序
附录
附录A 构建环境
附录B 消息解析器、子控件宏以及API宏
Ⅱ opengl在windows系统下编程,如何实现在窗口外绘图
二、生成OpenGL程序的基本步骤和条件 本文将给出一个例子,这个例子是一个用OpenGL显示图像的Windows程序,通过这个程序我们也可以知道用OpenGL编程的基本要求。我们知道,GDI是通过设备句柄(Device Context以下简称"DC")来绘图,而OpenGL则需要绘制环境(Rendering Context,以下简称"RC")。每一个GDI命令需要传给它一个DC,与GDI不同,OpenGL使用当前绘制环境(RC)。一旦在一个线程中指定了一个当前RC,所有在此线程中的OpenGL命令都使用相同的当前RC。虽然在单一窗口中可以使用多个RC,但在单一线程中只有一个当前RC。本例将首先产生一个OpenGL RC并使之成为当前RC,分为三个步骤:设置窗口像素格式;产生RC;设置为当前RC。 一、首先创建工程 用AppWizard产生一个EXE文件,选择工程目录,并在工程名字中输入"GLSample一",保持其他的不变;第一步、选单文档(SDI);第二步、不支持数据库;第三步、不支持OLE;第四步、不选中浮动工具条、开始状态条、打印和预览支持、帮助支持的复选框(选中也可以,本文只是说明最小要求),选中三维控制(三D Controls);第五步、选中产生源文件注释并使用MFC为共享动态库;第六步、保持缺省选择。按Finish结束,工程创建完毕。 二、将此工程所需的OpenGL文件 和库加入到工程中 在工程菜单中,选择"Build"下的"Settings"项。单击"Link"标签,选择"General"目录,在Object/Library Moles的编辑框中输入"OpenGL三二.lib glu三二.lib glaux.lib"(注意,输入双引号中的内容,各个库用空格分开;否则会出现链接错误),选择"OK"结束。然后打开文件"stdafx.h",将下列语句插入到文件中(划下划线的语句为所加语句): #define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers #include // MFC core and standard components #include // MFC extensions #include #include #ifndef _AFX_NO_AFXCMN_SUPPORT #include // MFC support for Windows 95 Common Controls #endif // _AFX_NO_AFXCMN_SUPPORT 三、改写OnPreCreate函数并给视 类添加成员函数和成员变量 OpenGL需要窗口加上WS_CLIPCHILDREN(创建父窗口使用的Windows风格,用于重绘时裁剪子窗口所覆盖的区域)和 WS_CLIPSIBLINGS(创建子窗口使用的Windows风格,用于重绘时剪裁其他子窗口所覆盖的区域)风格。把OnPreCreate改写成如下所示: BOOL CGLSample一View::PreCr- eateWindow(CREATESTRUCT& cs) { cs.style |= (WS_CLIPCHI- LDREN | WS_CLIPSIBLINGS); return CView::PreCreate- Window(cs); } 产生一个RC的第一步是定义窗口的像素格式。像素格式决定窗口着所显示的图形在内存中是如何表示的。由像素格式控制的参数包括:颜色深度、缓冲模式和所支持的绘画接口。在下面将有对这些参数的设置。我们先在CGLSample一View的类中添加一个保护型的成员函数BOOL SetWindowPixel-Format(HDC hDC)(用鼠标右键添加),并编辑其中的代码,见程序一。 BOOL CGLSample一View::SetWindowPixelFormat(HDC hDC) { PIXELFORMATDESCRIPTOR pixelDesc; pixelDesc.nSize = sizeof(PIXELFORMATDESCRIPTOR); pixelDesc.nVersion = 一; pixelDesc.dwFlags = PFD_DRAW_TO_WINDOW | PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OpenGL | PFD_SUPPORT_GDI | PFD_STEREO_DONTCARE; pixelDesc.iPixelType = PFD_TYPE_RGBA; pixelDesc.cColorBits = 三二; pixelDesc.cRedBits = 吧; pixelDesc.cRedShift = 一陆; pixelDesc.cGreenBits = 吧; pixelDesc.cGreenShift = 吧; pixelDesc.cBlueBits = 吧; pixelDesc.cBlueShift = 0; pixelDesc.cAlphaBits = 0; pixelDesc.cAlphaShift = 0; pixelDesc.cAccumBits = 陆四; pixelDesc.cAccumRedBits = 一陆; pixelDesc.cAccumGreenBits = 一陆; pixelDesc.cAccumBlueBits = 一陆; pixelDesc.cAccumAlphaBits = 0; pixelDesc.cDepthBits = 三二; pixelDesc.cStencilBits = 吧; pixelDesc.cAuxBuffers = 0; pixelDesc.iLayerType = PFD_MAIN_PLANE; pixelDesc.bReserved = 0; pixelDesc.dwLayerMask = 0; pixelDesc.dwVisibleMask = 0; pixelDesc.dwDamageMask = 0; m_GLPixelIndex = ChoosePixelFormat( hDC, &pixelDesc); if (m_GLPixelIndex==0) // Lets choose a default index. { m_GLPixelIndex = 一; if (DescribePixelFormat(hDC, m_GLPixelIndex, sizeof(PIXELFORMATDESCRIPTOR), &pixelDesc)==0) { return FALSE; } } if (SetPixelFormat( hDC, m_GLPixelIndex, &pixelDesc)==FALSE) { return FALSE; } return TRUE; } 接着用鼠标右键在CGLSample一View中添加保护型的成员变量: int m_GLPixelIndex; 四、用ClassWizard添加WM_CREATE的消息处理函数OnCreate 添加OnCreate函数后如程序一所示。 至此,OpenGL工程的基本框架就建好了。但如果你现在运行此工程,则它与一般的MFC程序看起来没有什么两样。 5、代码解释 现在我们可以看一看Describe-PixelFormat提供有哪几种像素格式,并对代码进行一些解释: PIXELFORMATDESCRIPTOR包括了定义像素格式的全部信息。 DWFlags定义了与像素格式兼容的设备和接口。 通常的OpenGL发行版本并不包括所有的标志(flag)。wFlags能接收以下标志: PFD_DRAW_TO_WINDOW 使之能在窗口或者其他设备窗口画图; PFD_DRAW_TO_BITMAP 使之能在内存中的位图画图; PFD_SUPPORT_GDI 使之能调用GDI函数(注:如果指定了PFD_DOUBLEBUFFER,这个选项将无效); PFD_SUPPORT_OpenGL 使之能调用OpenGL函数; PFD_GENERIC_FORMAT 假如这种象素格式由Windows GDI函数库或由第三方硬件设备驱动程序支持,则需指定这一项; PFD_NEED_PALETTE 告诉缓冲区是否需要调色板,本程序假设颜色是使用二四或 三二位色,并且不会覆盖调色板; PFD_NEED_SYSTEM_PALETTE 这个标志指明缓冲区是否把系统调色板当作它自身调色板的一部分; PFD_DOUBLEBUFFER 指明使用了双缓冲区(注:GDI不能在使用了双缓冲区的窗口中画图); PFD_STEREO 指明左、右缓冲区是否按立体图像来组织。 PixelType定义显示颜色的方法。PFD_TYPE_RGBA意味着每一位(bit)组代表着红、绿、蓝各分量的值。PFD_TYPE_COLORINDEX 意味着每一位组代表着在彩色查找表中的索引值。本例都是采用了PFD_TYPE_RGBA方式。 ● cColorBits定义了指定一个颜色的位数。对RGBA来说,位数是在颜色中红、绿、蓝各分量所占的位数。对颜色的索引值来说,指的是表中的颜色数。 ● cRedBits、cGreenBits、cBlue-Bits、cAlphaBits用来表明各相应分量所使用的位数。 ● cRedShift、cGreenShift、cBlue-Shift、cAlphaShift用来表明各分量从颜色开始的偏移量所占的位数。 一旦初始化完我们的结构,我们就想知道与要求最相近的系统象素格式。我们可以这样做: m_hGLPixelIndex = ChoosePixelFormat(hDC, &pixelDesc); ChoosePixelFormat接受两个参数:一个是hDc,另一个是一个指向PIXELFORMATDESCRIPTOR结构的指针&pixelDesc;该函数返回此像素格式的索引值。如果返回0则表示失败。假如函数失败,我们只是把索引值设为一并用DescribePixelFormat得到像素格式描述。假如你申请一个没得到支持的像素格式,则Choose-PixelFormat将会返回与你要求的像素格式最接近的一个值。一旦我们得到一个像素格式的索引值和相应的描述,我们就可以调用SetPixelFormat设置像素格式,并且只需设置一次。 现在像素格式已经设定,我们下一步工作是产生绘制环境(RC)并使之成为当前绘制环境。在CGLSample一View中加入一个保护型的成员函数BOOL CreateViewGLContext(HDC hDC),使之如下所示: BOOL CGLSample一View::CreateView GLContext(HDC hDC) { m_hGLContext = wglCreate Context(hDC);//用当前DC产生绘制环境(RC) if (m_hGLContext == NULL) { return FALSE; } if (wglMakeCurrent(hDC, m_hGLContext)==FALSE) { return FALSE; } return TRUE; } 并加入一个保护型的成员变量HGLRC m_hGLContext;HGLRC是一个指向rendering context的句柄。 在OnCreate函数中调用此函数: int CGLSample一View::OnCreate (LPCREATESTRUCT lpCreateStruct) { if (CView::OnCreate(lpCreateS truct) == -一) return -一; HWND hWnd = GetSafeHwnd(); HD
Ⅲ windows 编程用vc 6.0怎样建立一个能够开始写windows 编程代码的窗口开始书写代码
1. 打开VC6.0
2. 打开“文件”菜单,选择“新建”,弹出一个新建窗口。
3. 在左边的“工程”面板里面选择“Win32 Application”,在右边的“工程”编辑框里写上工程名,假设是“Test“。
4。点击“确定”。在弹出的窗口中选择“空项目(An empty project)”。
5. 点击“完成”,点击“确定”
6.此时工程已经建好了, 在VC6界面的左边有一个窗口,选择“File View”标签。
7. 右击“Test Files”,在子菜单中选择“添加文件(Add Files to Project)”
8. 在出来的界面的左边面板中选择“C++ Source File”,在右边写上文件名。
9.点击“确定”,就可以 了。
Ⅳ WINDOWS游戏编程之从零开始的内容简介
1. 如果你的编程经验为零:
毫无编程经验的朋友,请先阅读介绍C++编程语言的相关书籍,再来延续我们的梦想,阅读这本书。学习C++推荐书目: C++ Primer和C++ Primer Plus。
2. 如果你有C++编程经验但没有接触过Windows 编程:
有C++编程经验但毫无Windows编程经验的朋友,可以从头到尾顺畅的阅读这本书。因为这本书最准确的定位就是有一点C++编程经验之后从零开始掌握Windows游戏编程。
3. 如果你有Windows 编程经验,但不熟悉GDI:
有Windows编程经验但不熟悉GDI的朋友,推荐适当阅读第一章之后,从第4章开始您的征程。
4. 如果你想了解Windows GDI游戏绘图技巧:
想了解Windows GDI游戏绘图技巧的朋友,请阅读第5章。
5. 如果你想了解Windows游戏动画技巧:
想了解Windows游戏动画技巧的朋友,第6章会满足你的好奇心。
6. 如果你想了解Windows小游戏键盘鼠标编程的相关知识:
需要了解Windows中小游戏对键盘鼠标编程相关知识的朋友,第7章会给你答案。
7. 如果你想看看Windows GDI如何写出好玩的程序:
想看看Windows GDI可以弄出哪些好玩的玩意儿的朋友,第8章会给你惊喜。
8. 如果你想了解一个GDI小游戏完整的开发过程:
想了解一个结构完整的小游戏的开发过程的朋友们,第9章会超出你们的期待。
9. 如果你已经准备好迎接挑战,开始学习DirectX游戏编程:
有一定Windows编程经验,并且了解GDI编程,想开始DirectX 3D游戏编程学习的朋友,请从第10章开始阅读。这本书从第10章往后的内容组织起来是一个系统的DirectX游戏编程教材,其实可以单独成书的。