笔者所附的所有程序均在VS2013中运行,MFC中的一些程序因为比较老,所以需要去下一个程序,具体的我忘记了,大家可以找报错的时候百度,或者留下言,谢谢
Windows应用程序就是运行中Windows操作系统上的应用程序,这种应用程序具有两个特点:一是具有图形界面(GUI);二是它是事件驱动。早期的Windows还不是一个完整的操作系统,它借用了DOS的硬件抽象层,但它实现了虚拟存储管理和多任务的并发运行。DOS程序除了界面让人无语外,还有一个令人生厌的特点是,它总是按照程序的执行顺序强迫用户做一些工作。后来,随着图形界面应用程序为人们广泛接受之后,微软才把Windows作为计算机的主系统,系统开机之后就不再先进入DOS,而自动进入WIndows,即所谓的Win32平台。而现在Java也出现了当年的类似的情况。
为了支持应用程序的运行,Windows提供了大量可以中应用程序中调用的函数,这些函数就叫做API(Application Programming Interface),其三大类如下:
1)窗口管理函数:实现窗口的创建、移动和修改等功能;
2)图形设备函数:实现图形的绘制及操作功能,这类函数的集合叫做图形设备接口(GDI);
3)系统服务函数:实现与操作系统有关的一些功能。
早期,用来开发Windows应用程序的工具叫做SDK(Software Development Kit,软件开发工具包),还有新概念“句柄”,其实也就是后来的“对象引用”。用于描述窗口、按钮、文本框或滚动条这些复杂图形元素的数据结构一定相当大,所以Windows在这里使用了两个在当时看起来及其新颖的概念:对象(Object)和句柄(Handle)。
struct student
{
int num;
char name[20];
char sex;
int age;
.......
};
student Student1;
如果把结构student看作学生这个群体的抽象描述,那么对应于一个具体学生个体的Student1,就应该叫做student的一个具体“实例”。同理,微软把描述窗口、按钮或滚动条等大型数据结构叫做对象。句柄的意会可见下图
常用的句柄类型见下图
接下来介绍窗口类结构WNDCLASS,其声明如下:
typedef struct _WNDCLASS
{
UINT style; //窗口样式,一般设置为0
WNDPROC lpfnWndProc; //指向窗口函数的指针
int cbClsExtra; //预留的扩展成员,一般设置为0
int cbWndExtra; //预留的扩展成员,一般设置为0
HANDLE hInstance; //与窗口关联的应用程序实例句柄
HICON hIcon; //窗口的图标句柄
HCURSOR hCursor; //窗口的光标句柄
HBRUSH hbrBackground; //窗口的背景颜色刷句柄
LPCTSTR lpszMenuName; //窗口的菜单资源名
LPCTSTR lpszClassName;//窗口的类型名
}WNDCLASS;
窗口类结构是程序的窗口,也就是Windows程序的主体。有了主体,那么接下来的任务就是由程序设计者来向这个主体加装程序所需要的部件,最终现成用户所需的程序。窗口的定制见下面程序
WNDCLASS wc;
wc.style = 0; //窗口样式为0
wc.cbClsExtra = 0; //无扩展
wc.cbWndExtra = 0; //无扩展
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //背景颜色,函数的具体参数以后再说
wc.hCursor = LoadCursor(NULL, IDC_ARROW); //光标
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); //图标
wc.hInstance = hInstance; //本窗口对应的程序句柄为hInstance
wc.lpfnWndProc = WndProc; //把窗口函数的首地址赋予指针lpfnWndProc
wc.lpszClassName = lpszClassName; //窗口类(清单)名
wc.lpszMenuName = NULL; //本窗口无菜单
窗口的注册如下
RegisterClass(&wc); //窗口的注册
程序使用API函数CreateWindow()来创建窗口,其原型如下
HWND CreateWindow(
LPCTR lpClassName, //安装清单的名称
LPCTR lpWindowName, //窗口实例的标题
DWORD dwStyle, //窗口的风格
int x, //窗口左上角位置的坐标值x
int y, //窗口左上角位置的坐标值y
int nWidth, //窗口的宽度
int nHeight, //窗口的高度
HWND hWndParent, //父窗口的句柄
HMENU hMenu, //主菜单的句柄
HANDLE hInstance, //应用程序实例句柄
LPVOID lpParam //该值通常为NULL
);
事件与消息
综合前面的内容可知,Windows应用程序启动并创建了程序窗口后,该程序随即就会进入一个等待状态(利用一个while循环),直到接受到了某种刺激(例如,键盘输入,鼠标的单击或双击),程序才会脱离等待状态去对这个刺激进行处理,一旦处理完毕就又回到等待的状态。消息结构的定义如下:
typedef struct tagMSG
{
HWND hwnd; //产生消息的窗口句柄(产生事件的对象)
UINT message; //消息的标识码(事件的种类)
WPARAM wParam; //消息的附加信息1(必要的附加信息)
LPARAM lParam; //消息的附加信息2(必要的附加信息)
DWORD time; //产生信息的时刻
POINT pt; //发送该信息时,光标在屏幕上的位置
}MSG;
一个Windows程序一般由头文件、源文件、动态链接库、资源等几部分组成。Windows应用程序的主函数名称为WinMain,其原型如下:
int WINAPI WinMain(
HINSTANCE hInstance, //当前应用程序实例的句柄
HINSTANCE hPrevInstance, //系统中前一个应用程序实例的句柄
LPSTR lpCmdLine, //指向本程序命令行的指针
int nCmdShow //决定应用程序窗口显示方式的标志
);
函数名前面的关键字WINAPI也可以为CALLBACK,它表明这是个由系统调用的函数,即所谓的“回调函数”。WinMain()共有四个参数,其中的lpCmdLine为一字符串指针,它为用户做DOS中启动一个Windows程序时所输入的命令行参数,现已经不被使用;hInstance和hPrevInstance为两个应用程序实例,前者为当前程序,后者为程序控制块链表中的前一个程序;而最后那个参数nCmdShow则是系统为程序传递的一个用于决定窗口显示方式的标志。
下面放个例子,生成一个简单的窗口,当用户鼠标左键点击用户区时,发出声音
#include "stdafx.h"
#include "afxwinappex.h"
#include "afxdialogex.h"
#include "Simple_Windows_MFC.h"
#include<Windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE PreInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
HWND hwnd;
MSG msg;
char lpszClassName[] = "窗口";
WNDCLASS wc;
wc.style = 0;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = lpszClassName;
wc.lpszMenuName = NULL;
RegisterClass(&wc);
hwnd = CreateWindow(lpszClassName, "Windows",
WS_OVERLAPPEDWINDOW, 120, 50, 800, 600,
NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_LBUTTONDOWN:
{
MessageBeep(0);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
此节完了