Win32 Windows编程
1 Windows编程基础
2 Windows文字的编码
3 窗口程序
4 窗口消息
5 菜单和加速键
6 绘图
7 对话框
8 基本控件
.....
一 Windows编程基础
1 Win32应用程序的基本类型
1.1 控制台程序
不需要完善的Windows窗口,可以使用DOS窗口
的方式显示。
1.2 Win32窗口程序
包含窗口的程序。可以通过窗口与程序进行交互。
1.3 Win32库程序
提供已有的代码,供其他程序使用。
动态库:DLL 是在执行的时候可以加载的程序。
静态库:LIB 是在编译链接是使用的程序。
1.4 对比
1.4.1 程序的入口函数不同
控制台:main
Win32窗口程序:WinMain
动态库DLL:DllMain
静态库LIB:无
1.4.2 编译链接后存在的形式不同
控制台和Win32窗口程序:EXE文件,可以执行
动态库DLL:DLL文件,无法执行
静态库LIB:LIB文件,无法执行
1.4.3 执行结果不同
控制台:使用DOS窗口,自己没有窗口。
Win32窗口程序:会产生自己的窗口,
可以将结果输出或者从窗口接受输入。
动态库DLL:自己无法执行,提供可以执行
的代码,当EXE等程序执行时,可以使用
这些代码.执行时,该库必须在指定的路径.
静态库LIB: 自己无法执行,提供给程序在
编译链接时使用,将库中的代码嵌入到
程序当中.执行时,不需要该库存在.
二 Win32窗口程序和编译环境
2.1 开发和编译环境
VC1.5 - VC6.0(2008) - VC10.0(2010)
2.1.1 编译器 CL.EXE
将原代码编译目标代码. OBJ文件.
2.1.2 链接器 Link.EXE
将OBJ文件和库函数链接.生成EXE.
2.1.3 资源编译器 rc.exe
将资源脚本编译成可以链接的文件(RES).
2.2 头文件和库
2.2.1 头文件 windows.h包含了windows
常用的定义等.其他,还包含了一些其他的
头文件:
windef.h - 定义了各种的数据类型
winbase.h- 定义了kernel的相关函数
wingdi.h - 定义了绘图和文字
winuser.h- 窗口 控件等函数
winnt.h - 提供Unicode支持
2.2.2 库
kernel32.lib - 提供进程/线程/内存等等
API函数支持
user32.lib - 包括窗户/界面等等.
gdi32.lib - 提供绘图/文字等。
2.3 Hello World程序
2.3.1 入口函数
int WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR pszCmdLine,
int nShowCmd )
hInstance - 应用程序的实例句柄
hPrevInstance - 该应用程序的前一个实例句柄
pszCmdLine - 命令行参数
nShowCmd - 窗口的显示方式
2.3.2 MessageBox
2.4 编译环境的准备
在VC98的BIN目录下VCVARS32.BAT
2.5 编译CL.EXE
CL的常用选项
/c 只编译不链接
/TC 编译C文件
/TP 编译C++文件
如果不指定,CL会根据文件类型自动区分
/I 头文件所在路径
字符大小写敏感
2.6 链接LINK.EXE
LINK常用选项:
/out:文件名,链接成指定文件名的程序
/LIBPATH:LIB文件存放的路径, /LIBPATH:"E:\XXX"
/SUBSYSTEM: CONSOLE/WINDOW
字符大小写不敏感
2.7 执行
正常执行或带参数执行
三 第一个窗口程序
3.1 入口函数WinMain
3.2 窗口处理函数
当窗口处理消息事件时,系统调用该函数
LRESULT CALLBACK WindowProc(
HWND hwnd, // 窗口的句柄
UINT uMsg, // 消息的ID号
WPARAM wParam, // 消息所对应的参数
LPARAM lParam // 消息所对应的参数
);
3.3 注册窗口类型
typedef struct _WNDCLASS {
UINT style; //窗口类的风格
WNDPROC lpfnWndProc; //窗口处理函数
int cbClsExtra; //窗口类附加数据大小
int cbWndExtra; //窗口附加数据大小
HANDLE hInstance; //当前应用程序的实例句柄
HICON hIcon; //窗口图标
HCURSOR hCursor; //窗口的鼠标
HBRUSH hbrBackground; //窗口的背景画刷
LPCTSTR lpszMenuName; //菜单
LPCTSTR lpszClassName; //类型名称
} WNDCLASS;
注册函数 RegisterClass
3.4 创建窗口
HWND CreateWindow(
LPCTSTR lpClassName, //窗口类型名称
LPCTSTR lpWindowName, //窗口名称
DWORD dwStyle, //窗口类型
int x, //窗口的左上角X坐边
int y, //窗口的左上角X坐边
int nWidth, //窗口的宽度
int nHeight, //窗口的高度
HWND hWndParent, //父窗口句柄
HMENU hMenu, //窗口菜单句柄
HANDLE hInstance, //应用程序的实例句柄
LPVOID lpParam //创建的参数,一般为NULL
);
3.5 显示窗口
ShowWindow 显示窗口
BOOL ShowWindow(
HWND hWnd, //显示的窗口句柄
int nCmdShow //显示的方式
);
UpdateWindow 刷新窗口
3.6 消息处理
GetMessage 获取消息
DispatchMessage 派发消息
3.7 程序退出
窗口销毁时,退出程序。在WndProc中实现。
WM_DESTROY: 当窗口销毁时,会调用WndProc
传递给使用者。
PostQuitMessage:发送一个退出消息。
四 资源的处理
4.1 资源和资源脚本
资源:ICON/CUSRUR/BITMAP/MENU......
资源脚本: 扩展名为rc文件。
4.2 编译资源
使用rc.exe编译资源,生成RES文件
4.3 链接资源
使用link.exe将RES文件链接到程序当中
4.4 ICON的使用
LoadIcon从指定程序中加载ICON资源。
五 NMAKE和Makefile
1.1 NMAKE - 命令解释器,根据Makefile文件中
定义的脚本,完成项目的编译等操作。
1.2 Makefile - 定义编译/链接等脚本语言。
1.3 Makefile文件的编写
1.3.1 基本语法规则
window.exe:window.obj // 依赖行
cl.exe window.c /c // 命令行
link.exe window.obj user32.lib
window.exe的依赖项是window.obj,如果
window.obj被重新改写,window.exe将重新
生成.
通过时间戳(time stamp)判断程序是否需
要重新编译链接,如果当文件修改最后时间
与时间戳不同,将会重新编译链接.
1.3.2 执行过程
1 NMAKE首先找到第一个依赖行,根据依赖
行之间的关系,建立依赖树。例如:
A:B
B:C
C:D
NMAKE会建立对应的依赖树
A
|-B
|-C
|-D
2 在树建好后,NMAKE会首先执行D的命令行,
然后依次执行父结点的命令行
3 在A的命令执行结束后,退出NMAKE.
4 如果需要执行指定依赖行,需要在执行
NMAKE时增加依赖行的名称
NMAKE /f Makefile.mak B <--指定从B执行
1.4 使用
1.4.1 NAMKE指定文件名
NMAKE /f Makefile.mak
1.4.2 使用缺省文件名Makefile
NMAKE在执行时会自动查找这个文件.
二 字符编码
2.1 编码的历史
2.1.1 ASCII 0-127 7位表示
2.1.2 ASCII扩展码 0-255 8位表示
代码页:通过代码页来切换对应的
字符
2.1.3 双字节字符集 DBCS
使用一个或两个字节表示字符.
"A中B国"
12 1 2
A: 0x41 中:0x8051
B: 0x42 国:0x8253
1 2 3 4 5 6
0x41 0x80 0x51 0x42 0x82 0x53
A 中 B 国
2.1.4 Unicode
全部使用2个字节表示字符
"A 中 B 国"
2 2 2 2
A: 0x0041 中:0x8051
B: 0x0042 国:0x8253
1 2 3 4 5 6 7 8
41 00 51 80 42 00 53 82
内存/硬盘等资源占用变大.
对编程支持度.
2.2 C语言和编码
2.2.1 单字节的字符和字符串
char cText = 'A';
char * pszText = "ABCD";
2.2.2 宽字节的字符
wchar_t cText = 'A'
wchar_t * pszText = L"ABCD";
2.2.3 相关函数
单字字符的函数,对应有多.宽字节的函数.
strlen wcslen mbslen
printf wprintf
2.2.4 TCHAR
为了程序中可以方便的支持的Unicode和多字节
字符等,所以使用TCHAR来定义字符和字符串.
根据_UNICODE宏开关,会将TCHAR编译成不同字符
类型.
#ifndef _UNICODE
typedef char TCHAR
#define __T(x) x
#else
typedef wchar_t TCHAR
#define __T(x) L##x
#endif
使用时,要增加TCHAR.H头文件支持,使用
_UNICODE 宏开关进行编译
CL window.c /D_UNICODE
#define _UNICODE
#include "tchar.h"
定义方式:
TCAHR * pszText = __T("ABCDEF");
代码使用:使用UNICODE宏开关,通知
编译器选择编译的代码.
#ifndef _UNICODE
int nLen = strlen( pszText );
#else
int nLen = wcslen( pszText );
#endif
2.2.5 Unicode的控制台打印
BOOL WriteConsole(
HANDLE hConsoleOutput, //控制台输出流的句柄
CONST VOID *lpBuffer,//输出的字符串的指针
DWORD nNumberOfCharsToWrite,//输出的字符串的长度
LPDWORD lpNumberOfCharsWritten,
// 返回已输出字符的数量
LPVOID lpReserved ); // 保留值
2.3 Win32程序与编码
2.3.1 Win32 API的定义
每个API对多字节字符和UNICODE分别有
不同的版本.
MessageBox
MessageBoxA 多字节字符
MessageBoxW UNICODE字符
2.3.2 字符的定义,使用TEXT, 由Winnt.h提供定义
#ifdef UNICODE
#define __TEXT(quote) L##quote
#else /* UNICODE */
#define __TEXT(quote) quote
#endif /* UNICODE */
TCHAR * pszText = TEXT( "ABCD" );
2.3.3 字符转换
int WideCharToMultiByte(
UINT CodePage, //代码页
DWORD dwFlags, //转换方式
LPCWSTR lpWideCharStr, //需要被转换WCHAR地址
int cchWideChar, //需要被转换WCHAR的长度
LPSTR lpMultiByteStr,//用于存放转换后的结果BUFF
int cchMultiByte, //BUFF的长度
LPCSTR lpDefaultChar,//使用的缺省字符串的地址
LPBOOL lpUsedDefaultChar //缺省字符串被使用的标识
);
int MultiByteToWideChar(
UINT CodePage,// 代码页
DWORD dwFlags,// 转换方式
LPCSTR lpMultiByteStr, // 需要被转换CHAR地址
int cchMultiByte,//需要被转换CHAR的长度
LPWSTR lpWideCharStr,//用于存放转换后的结果BUFF
int cchWideChar );//BUFF的长度
使用方法:
1 将要转换的字符串,传递给函数,从
返回值中获取转换后字符串的长度。
2 分配字符串空间
3 再次调用函数,并将分配的空间传递给
函数,获取结果.
1 Windows编程基础
2 Windows文字的编码
3 窗口程序
4 窗口消息
5 菜单和加速键
6 绘图
7 对话框
8 基本控件
.....
一 Windows编程基础
1 Win32应用程序的基本类型
1.1 控制台程序
不需要完善的Windows窗口,可以使用DOS窗口
的方式显示。
1.2 Win32窗口程序
包含窗口的程序。可以通过窗口与程序进行交互。
1.3 Win32库程序
提供已有的代码,供其他程序使用。
动态库:DLL 是在执行的时候可以加载的程序。
静态库:LIB 是在编译链接是使用的程序。
1.4 对比
1.4.1 程序的入口函数不同
控制台:main
Win32窗口程序:WinMain
动态库DLL:DllMain
静态库LIB:无
1.4.2 编译链接后存在的形式不同
控制台和Win32窗口程序:EXE文件,可以执行
动态库DLL:DLL文件,无法执行
静态库LIB:LIB文件,无法执行
1.4.3 执行结果不同
控制台:使用DOS窗口,自己没有窗口。
Win32窗口程序:会产生自己的窗口,
可以将结果输出或者从窗口接受输入。
动态库DLL:自己无法执行,提供可以执行
的代码,当EXE等程序执行时,可以使用
这些代码.执行时,该库必须在指定的路径.
静态库LIB: 自己无法执行,提供给程序在
编译链接时使用,将库中的代码嵌入到
程序当中.执行时,不需要该库存在.
二 Win32窗口程序和编译环境
2.1 开发和编译环境
VC1.5 - VC6.0(2008) - VC10.0(2010)
2.1.1 编译器 CL.EXE
将原代码编译目标代码. OBJ文件.
2.1.2 链接器 Link.EXE
将OBJ文件和库函数链接.生成EXE.
2.1.3 资源编译器 rc.exe
将资源脚本编译成可以链接的文件(RES).
2.2 头文件和库
2.2.1 头文件 windows.h包含了windows
常用的定义等.其他,还包含了一些其他的
头文件:
windef.h - 定义了各种的数据类型
winbase.h- 定义了kernel的相关函数
wingdi.h - 定义了绘图和文字
winuser.h- 窗口 控件等函数
winnt.h - 提供Unicode支持
2.2.2 库
kernel32.lib - 提供进程/线程/内存等等
API函数支持
user32.lib - 包括窗户/界面等等.
gdi32.lib - 提供绘图/文字等。
2.3 Hello World程序
2.3.1 入口函数
int WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR pszCmdLine,
int nShowCmd )
hInstance - 应用程序的实例句柄
hPrevInstance - 该应用程序的前一个实例句柄
pszCmdLine - 命令行参数
nShowCmd - 窗口的显示方式
2.3.2 MessageBox
2.4 编译环境的准备
在VC98的BIN目录下VCVARS32.BAT
2.5 编译CL.EXE
CL的常用选项
/c 只编译不链接
/TC 编译C文件
/TP 编译C++文件
如果不指定,CL会根据文件类型自动区分
/I 头文件所在路径
字符大小写敏感
2.6 链接LINK.EXE
LINK常用选项:
/out:文件名,链接成指定文件名的程序
/LIBPATH:LIB文件存放的路径, /LIBPATH:"E:\XXX"
/SUBSYSTEM: CONSOLE/WINDOW
字符大小写不敏感
2.7 执行
正常执行或带参数执行
三 第一个窗口程序
3.1 入口函数WinMain
3.2 窗口处理函数
当窗口处理消息事件时,系统调用该函数
LRESULT CALLBACK WindowProc(
HWND hwnd, // 窗口的句柄
UINT uMsg, // 消息的ID号
WPARAM wParam, // 消息所对应的参数
LPARAM lParam // 消息所对应的参数
);
3.3 注册窗口类型
typedef struct _WNDCLASS {
UINT style; //窗口类的风格
WNDPROC lpfnWndProc; //窗口处理函数
int cbClsExtra; //窗口类附加数据大小
int cbWndExtra; //窗口附加数据大小
HANDLE hInstance; //当前应用程序的实例句柄
HICON hIcon; //窗口图标
HCURSOR hCursor; //窗口的鼠标
HBRUSH hbrBackground; //窗口的背景画刷
LPCTSTR lpszMenuName; //菜单
LPCTSTR lpszClassName; //类型名称
} WNDCLASS;
注册函数 RegisterClass
3.4 创建窗口
HWND CreateWindow(
LPCTSTR lpClassName, //窗口类型名称
LPCTSTR lpWindowName, //窗口名称
DWORD dwStyle, //窗口类型
int x, //窗口的左上角X坐边
int y, //窗口的左上角X坐边
int nWidth, //窗口的宽度
int nHeight, //窗口的高度
HWND hWndParent, //父窗口句柄
HMENU hMenu, //窗口菜单句柄
HANDLE hInstance, //应用程序的实例句柄
LPVOID lpParam //创建的参数,一般为NULL
);
3.5 显示窗口
ShowWindow 显示窗口
BOOL ShowWindow(
HWND hWnd, //显示的窗口句柄
int nCmdShow //显示的方式
);
UpdateWindow 刷新窗口
3.6 消息处理
GetMessage 获取消息
DispatchMessage 派发消息
3.7 程序退出
窗口销毁时,退出程序。在WndProc中实现。
WM_DESTROY: 当窗口销毁时,会调用WndProc
传递给使用者。
PostQuitMessage:发送一个退出消息。
四 资源的处理
4.1 资源和资源脚本
资源:ICON/CUSRUR/BITMAP/MENU......
资源脚本: 扩展名为rc文件。
4.2 编译资源
使用rc.exe编译资源,生成RES文件
4.3 链接资源
使用link.exe将RES文件链接到程序当中
4.4 ICON的使用
LoadIcon从指定程序中加载ICON资源。
五 NMAKE和Makefile
1.1 NMAKE - 命令解释器,根据Makefile文件中
定义的脚本,完成项目的编译等操作。
1.2 Makefile - 定义编译/链接等脚本语言。
1.3 Makefile文件的编写
1.3.1 基本语法规则
window.exe:window.obj // 依赖行
cl.exe window.c /c // 命令行
link.exe window.obj user32.lib
window.exe的依赖项是window.obj,如果
window.obj被重新改写,window.exe将重新
生成.
通过时间戳(time stamp)判断程序是否需
要重新编译链接,如果当文件修改最后时间
与时间戳不同,将会重新编译链接.
1.3.2 执行过程
1 NMAKE首先找到第一个依赖行,根据依赖
行之间的关系,建立依赖树。例如:
A:B
B:C
C:D
NMAKE会建立对应的依赖树
A
|-B
|-C
|-D
2 在树建好后,NMAKE会首先执行D的命令行,
然后依次执行父结点的命令行
3 在A的命令执行结束后,退出NMAKE.
4 如果需要执行指定依赖行,需要在执行
NMAKE时增加依赖行的名称
NMAKE /f Makefile.mak B <--指定从B执行
1.4 使用
1.4.1 NAMKE指定文件名
NMAKE /f Makefile.mak
1.4.2 使用缺省文件名Makefile
NMAKE在执行时会自动查找这个文件.
二 字符编码
2.1 编码的历史
2.1.1 ASCII 0-127 7位表示
2.1.2 ASCII扩展码 0-255 8位表示
代码页:通过代码页来切换对应的
字符
2.1.3 双字节字符集 DBCS
使用一个或两个字节表示字符.
"A中B国"
12 1 2
A: 0x41 中:0x8051
B: 0x42 国:0x8253
1 2 3 4 5 6
0x41 0x80 0x51 0x42 0x82 0x53
A 中 B 国
2.1.4 Unicode
全部使用2个字节表示字符
"A 中 B 国"
2 2 2 2
A: 0x0041 中:0x8051
B: 0x0042 国:0x8253
1 2 3 4 5 6 7 8
41 00 51 80 42 00 53 82
内存/硬盘等资源占用变大.
对编程支持度.
2.2 C语言和编码
2.2.1 单字节的字符和字符串
char cText = 'A';
char * pszText = "ABCD";
2.2.2 宽字节的字符
wchar_t cText = 'A'
wchar_t * pszText = L"ABCD";
2.2.3 相关函数
单字字符的函数,对应有多.宽字节的函数.
strlen wcslen mbslen
printf wprintf
2.2.4 TCHAR
为了程序中可以方便的支持的Unicode和多字节
字符等,所以使用TCHAR来定义字符和字符串.
根据_UNICODE宏开关,会将TCHAR编译成不同字符
类型.
#ifndef _UNICODE
typedef char TCHAR
#define __T(x) x
#else
typedef wchar_t TCHAR
#define __T(x) L##x
#endif
使用时,要增加TCHAR.H头文件支持,使用
_UNICODE 宏开关进行编译
CL window.c /D_UNICODE
#define _UNICODE
#include "tchar.h"
定义方式:
TCAHR * pszText = __T("ABCDEF");
代码使用:使用UNICODE宏开关,通知
编译器选择编译的代码.
#ifndef _UNICODE
int nLen = strlen( pszText );
#else
int nLen = wcslen( pszText );
#endif
2.2.5 Unicode的控制台打印
BOOL WriteConsole(
HANDLE hConsoleOutput, //控制台输出流的句柄
CONST VOID *lpBuffer,//输出的字符串的指针
DWORD nNumberOfCharsToWrite,//输出的字符串的长度
LPDWORD lpNumberOfCharsWritten,
// 返回已输出字符的数量
LPVOID lpReserved ); // 保留值
2.3 Win32程序与编码
2.3.1 Win32 API的定义
每个API对多字节字符和UNICODE分别有
不同的版本.
MessageBox
MessageBoxA 多字节字符
MessageBoxW UNICODE字符
2.3.2 字符的定义,使用TEXT, 由Winnt.h提供定义
#ifdef UNICODE
#define __TEXT(quote) L##quote
#else /* UNICODE */
#define __TEXT(quote) quote
#endif /* UNICODE */
TCHAR * pszText = TEXT( "ABCD" );
2.3.3 字符转换
int WideCharToMultiByte(
UINT CodePage, //代码页
DWORD dwFlags, //转换方式
LPCWSTR lpWideCharStr, //需要被转换WCHAR地址
int cchWideChar, //需要被转换WCHAR的长度
LPSTR lpMultiByteStr,//用于存放转换后的结果BUFF
int cchMultiByte, //BUFF的长度
LPCSTR lpDefaultChar,//使用的缺省字符串的地址
LPBOOL lpUsedDefaultChar //缺省字符串被使用的标识
);
int MultiByteToWideChar(
UINT CodePage,// 代码页
DWORD dwFlags,// 转换方式
LPCSTR lpMultiByteStr, // 需要被转换CHAR地址
int cchMultiByte,//需要被转换CHAR的长度
LPWSTR lpWideCharStr,//用于存放转换后的结果BUFF
int cchWideChar );//BUFF的长度
使用方法:
1 将要转换的字符串,传递给函数,从
返回值中获取转换后字符串的长度。
2 分配字符串空间
3 再次调用函数,并将分配的空间传递给
函数,获取结果.