得了一本好书,《Windows API 开发详解》(人邮),准备从头到尾学习一遍。阅读此书过程中,留下此手札,把重点东西记下来,如果有自己的理解,顺便扩展一下。
Ch1.应用程序开发入门
本章讲了一个例子,代码很简单,如下:
#include <windows.h>
#pragma comment(lib, "user32.lib") //此行通常被省略,因为编译参数
int WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow
)
{
MessageBox(NULL,
TEXT("Hello"),
TEXT("Title"),
MB_OK);
return 0;
}
这段代码在VC6和VC2008中编译都可以――这本书的大部分例子均是如此。至于方法嘛,简述如下:
VC6中,新建Win32 Application, empty project, 然后加入一个C++ Source文件,写代码;
VC2008中,新建项目/VC++/常规/空项目,在管理器中右击项目名,添加/新建项/代码,写代码。
结尾还提及命令行makefile编译,以后再表。
Ch2.API概要
首先阐述WINDOWS数据类型,均由C重定义而来。如WORD,DWORD,INT,UINT,LPSTR,CHAR。
我们经常遇到结构体定义,如下:
struct _ABC{
int x;
int y;
} ABC, *pABC;
其中_ABC、ABC、pABC的关系如何呢?其实它相当于:
struct _ABC{
int x;
int y;
} ;
typedef _ABC ABC;
typedef _ABC *pABC;
举了一个基本窗口程序的例子,代码如下:
#include <windows.h>
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", // 窗口名
"First Window", // 窗口标题
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);
}
}
还有提到Unicode和ANSI相互转换的几个函数:
WideCharToMultiByte, MultiByteToWideChar, UnicodesToBytes
最后提到了匈牙利命名法。这一点我向来严格遵循。例如m_hWnd这个变量,其实核心只是Wnd,前缀m_表示它是类的成员变量,h表示它的类型是句柄。另外还有上文提及的pAbc表示指针等。
Ch3.开发工具配置与使用
编译和链接主要用到3个程序:cl.exe、rc.exe和link.exe,参数很多且复杂,无特殊要求建议在IDE中编译。
查看和修改环境变量有2个方法:
1. CMD中输入SET回车即可查看,输入SET name=Value即可设置;
2. 我的电脑/属性/系统属性/高级/环境变量。
在CMD、我的电脑、IE等处都可以直接引用环境变量,方法是
%环境变量%
如在我的电脑地址输入%HOMEPATH%,将会跳到用户文档文件夹(如C:\Documents and Settings\Administrator。
执行下句将在PATH环境变量中增加一个地址:
set PATH=C:\Program Files\Bin; %PATH%
在makefile中引用环境变量的方法和引用宏的方法一样:$(环境变量名)
VS2005、2008、2010工具设置:
1. 设置键盘快捷键成VC6:工具/选项/环境/键盘,方案可选择VC6,这样就可以保持VC6的编译习惯,如F7编译生成,F5开始调试,F9断点,F10步过,F11步入等;
2. 设置显示行号:工具/选项/文本编辑器/”C/C++”/行号;
3. 字体颜色,比如我就喜欢用FixSys字体,大小10:工具/选项/环境/字体和颜色;
4. 有人还发现编译后的工程拷其他没有安装VC200X的电脑上无法运行的问题。这类似于MFC的静态编译和动态编译。请在“工程属性/‘C/C++’/代码生成”中把运行时库改为MT(原为MD或MDd)。如果建立工程时采用空项目,则默认就是MT。我编译了一个只有一句代码的程序,MD时是7KB,MT时是37KB。
(以后会不断更新,暂时到此)