Windows 这个多作业系统除了协调应用程序的执行、分配内存、管理资源…之外, 它同时也是一个很大的服务中心,调用这个服务中心的各种服务(每一种服务就是一个函数),可以帮应用程式达到开启视窗、描绘图形、使用周边设备等目的,由于这些函数服务的对象是应用程序(Application), 所以便称之为 Application Programming Interface,简称 API 函数。WIN32 API也就是Microsoft Windows 32位平台的应用程序编程接口。
凡是在 Windows 工作环境底下执行的应用程序, 都可以调用Windows API。
MFC:
MFC是Win API与C++的结合,API,即微软提供的Windows下应用程序的编程语言接口,是一种软件编程的规范,但不是一种程序开发语言,它可以允许用户使用各种各样的第三方(如我是一方,微软是一方,Borland就是第三方)的编程语言来进行对Windows下应用程序的开发,使这些被开发出来的应用程序能在Windows下运行,比如VB,VC++,Java,Dehpi编程语言函数本质上全部源于API,因此用它们开发出来的应用程序都能工作在Windows的消息机制和绘图里,遵守Windows作为一个操作系统的内部实现,这其实也是一种必要,微软如果不提供API,这个世上对Win编程的工作就不会存在,微软的产品就会迅速从时尚变成垃圾,上面说到MFC是微软对API函数的专用C++封装,这种结合一方面让用户使用微软的专业C++ SDK来进行Win下应用程序的开发变得容易,因为MFC是对API的封装,微软做了大量的工作,隐藏了好多程序开发人员在Win下用C++ & MFC编制软件时的大量细节,如应用程序实现消息的处理,设备环境绘图,这种结合是以方便为目的的,必定要付出一定代价(这是微软的一向作风),因此就造成了MFC对类封装中的一定程度的的冗余和迂回,但这是可以接受的..
下面来看一个程序,这个程序是创建一个白色窗口,并在10,10的位置输出“你好,世界!”的字样。
Windows API实现:
C 代码
#include<windows.h>
/* 声明窗口过程 */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
/* 窗口类名 */
TCHAR szClassName[]=TEXT("WindowsApp");
/* 入口函数 */
int WINAPI WinMain (
HINSTANCE hInstance, // 实例句柄
HINSTANCE hPrevInstance, // 先前的实例, Win32下始终为NULL
LPSTR lpCmdLine, // 命令行参数
int nCmdShow // 窗口显示命令参数
)
{
HWND hwnd; /* 窗口句柄 */
MSG messages; /* 消息结构变量 */
WNDCLASS wincl; /* 窗口类结构变量 */
/* 填充窗口类结构变量 */
wincl.hInstance = hInstance;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure; /* 设置窗口过程 */
wincl.style = CS_DBLCLKS; /* 窗口类样式 */
/* 设置默认图标光标 */
wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = NULL; /* 菜单 */
wincl.cbClsExtra = 0; /* 窗口类额外数据字节数 */
wincl.cbWndExtra = 0; /* 窗口额外数据字节数 */
/* 窗口默认背景 */
wincl.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
/* 注册窗口类 */
if (!RegisterClass(&wincl))
return 0;
/* 创建窗口 */
hwnd = CreateWindow (
szClassName, /* 类名 */
TEXT("Win32 API"),/* 标题文本 */
WS_OVERLAPPEDWINDOW, /* 窗口样式 */
CW_USEDEFAULT, /* X坐标 */
CW_USEDEFAULT, /* Y坐标 */
CW_USEDEFAULT, /* 宽度px */
CW_USEDEFAULT, /* 高度px */
HWND_DESKTOP, /* 父窗口句柄 */
NULL, /* 菜单 */
hInstance, /* 程序实例句柄 */
NULL /* 窗口创建参数 */
);
/* 按照参数显示窗口 */
ShowWindow (hwnd, nCmdShow);
/* 进入消息循环,直到GetMessage()返回0. 即WM_QUIT消息发出 */
while (GetMessage(&messages, NULL,0,0))
{
/* 翻译虚拟键消息成字符消息 */
TranslateMessage(&messages);
/* 发送消息给窗口过程 */
DispatchMessage(&messages);
}
return (int)messages.wParam;
}
/* 窗口过程实现 */
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hDC = BeginPaint(hwnd,&ps);
TCHAR sz[]=TEXT("你好,世界!");
TextOut(hDC,10,10,sz,lstrlen(sz));
EndPaint(hwnd,&ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0); /* 向消息队列发出WM_QUIT消息 */
break;
default: /* 不感兴趣的消息交给DefWindowProc()处理 */
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
/* 声明窗口过程 */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
/* 窗口类名 */
TCHAR szClassName[]=TEXT("WindowsApp");
/* 入口函数 */
int WINAPI WinMain (
HINSTANCE hInstance, // 实例句柄
HINSTANCE hPrevInstance, // 先前的实例, Win32下始终为NULL
LPSTR lpCmdLine, // 命令行参数
int nCmdShow // 窗口显示命令参数
)
{
HWND hwnd; /* 窗口句柄 */
MSG messages; /* 消息结构变量 */
WNDCLASS wincl; /* 窗口类结构变量 */
/* 填充窗口类结构变量 */
wincl.hInstance = hInstance;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure; /* 设置窗口过程 */
wincl.style = CS_DBLCLKS; /* 窗口类样式 */
/* 设置默认图标光标 */
wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = NULL; /* 菜单 */
wincl.cbClsExtra = 0; /* 窗口类额外数据字节数 */
wincl.cbWndExtra = 0; /* 窗口额外数据字节数 */
/* 窗口默认背景 */
wincl.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
/* 注册窗口类 */
if (!RegisterClass(&wincl))
return 0;
/* 创建窗口 */
hwnd = CreateWindow (
szClassName, /* 类名 */
TEXT("Win32 API"),/* 标题文本 */
WS_OVERLAPPEDWINDOW, /* 窗口样式 */
CW_USEDEFAULT, /* X坐标 */
CW_USEDEFAULT, /* Y坐标 */
CW_USEDEFAULT, /* 宽度px */
CW_USEDEFAULT, /* 高度px */
HWND_DESKTOP, /* 父窗口句柄 */
NULL, /* 菜单 */
hInstance, /* 程序实例句柄 */
NULL /* 窗口创建参数 */
);
/* 按照参数显示窗口 */
ShowWindow (hwnd, nCmdShow);
/* 进入消息循环,直到GetMessage()返回0. 即WM_QUIT消息发出 */
while (GetMessage(&messages, NULL,0,0))
{
/* 翻译虚拟键消息成字符消息 */
TranslateMessage(&messages);
/* 发送消息给窗口过程 */
DispatchMessage(&messages);
}
return (int)messages.wParam;
}
/* 窗口过程实现 */
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hDC = BeginPaint(hwnd,&ps);
TCHAR sz[]=TEXT("你好,世界!");
TextOut(hDC,10,10,sz,lstrlen(sz));
EndPaint(hwnd,&ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0); /* 向消息队列发出WM_QUIT消息 */
break;
default: /* 不感兴趣的消息交给DefWindowProc()处理 */
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
MFC实现:
C++ 代码
#include<afxwin.h>
/* 自定义窗口 */
class CMyWnd :public CFrameWnd
{
public:
CMyWnd();
protected:
void OnPaint();
/* 声明消息映射 */
DECLARE_MESSAGE_MAP()
};
CMyWnd::CMyWnd()
{
/* 创建窗口 */
Create(NULL,TEXT("MFC Frame Window"));
}
/* 重绘函数 */
void CMyWnd::OnPaint()
{
CPaintDC dc(this);
dc.TextOut(10,10,TEXT("你好,世界!"));
}
/*消息映射*/
BEGIN_MESSAGE_MAP(CMyWnd,CWnd)
ON_WM_PAINT()
END_MESSAGE_MAP()
/* 定义应用程序类 */
class CMyApp :public CWinApp
{
public:
BOOL InitInstance();
};
/* 唯一的应用程序类实例 */
CMyApp theApp;
BOOL CMyApp::InitInstance()
{
m_pMainWnd = new CMyWnd();
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
/* 返回 TRUE 进入消息循环 */
return TRUE;
}
/* 自定义窗口 */
class CMyWnd :public CFrameWnd
{
public:
CMyWnd();
protected:
void OnPaint();
/* 声明消息映射 */
DECLARE_MESSAGE_MAP()
};
CMyWnd::CMyWnd()
{
/* 创建窗口 */
Create(NULL,TEXT("MFC Frame Window"));
}
/* 重绘函数 */
void CMyWnd::OnPaint()
{
CPaintDC dc(this);
dc.TextOut(10,10,TEXT("你好,世界!"));
}
/*消息映射*/
BEGIN_MESSAGE_MAP(CMyWnd,CWnd)
ON_WM_PAINT()
END_MESSAGE_MAP()
/* 定义应用程序类 */
class CMyApp :public CWinApp
{
public:
BOOL InitInstance();
};
/* 唯一的应用程序类实例 */
CMyApp theApp;
BOOL CMyApp::InitInstance()
{
m_pMainWnd = new CMyWnd();
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
/* 返回 TRUE 进入消息循环 */
return TRUE;
}
很明显,使用MFC能显著减少书面代码量。
但是正因为如此,学习起来会觉得摸不着头脑。
你会发现MFC中看不见WinMain函数了,也找不到窗口过程了。
其实是有的,它们被封装在了MFC的类中。
WINDOWS API实现思路清晰,虽然不难,但是很烦琐。
MFC实现书面代码较少,但是流程不太清晰, 虽然看似简单,但是却不好学。。MFC的难点就在这里。。