最近拿起《Windows程序设计(第5版珍藏版)》来看,其中第3章的那个演示程序可谓是Windows程序的经典写法。条理清晰,结构明了,几乎没有什么好挑剔的了。代码如下:
#include<windows.h>
LRESULT CALLBACK WndProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE instance, HINSTANCE otherInstance, PSTR cmdline, int showType)
{
static TCHAR applicationName[] = TEXT("HelloWin");
WNDCLASS wndClass;
wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = WndProc;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = instance;
wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndClass.hCursor = LoadCursor(NULL, IDI_APPLICATION);
wndClass.hbrBackground = static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));
wndClass.lpszMenuName = NULL;
wndClass.lpszClassName = applicationName;
if(!RegisterClass(&wndClass))
{
MessageBox(NULL, TEXT("This program requires Windows NT!"), applicationName, MB_ICONERROR);
}
HWND window;
window = CreateWindow(applicationName, TEXT("The Hello Program"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, instance, NULL);
ShowWindow(window, showType);
UpdateWindow(window);
MSG message;
while(GetMessage(&message, NULL, 0, 0))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
return message.wParam;
}
LRESULT CALLBACK WndProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_CREATE:
PlaySound(TEXT("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC);
return 0;
case WM_PAINT:
{
RECT rectangle;
GetClientRect(window, &rectangle);
PAINTSTRUCT ps;
HDC deviceContent = BeginPaint(window, &ps);
DrawText(deviceContent, TEXT("Hello, Windows 98!"), -1, &rectangle, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
EndPaint(window, &ps);
}
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(window, message, wParam, lParam);
}
这段代码看久了会觉得比较乏味。于是想着能不能用OO的方式来抽象封装一下。
于是就有了下面的代码(main.cpp):
#include<windows.h>
#include"application.h"
int WINAPI WinMain(HINSTANCE instance, HINSTANCE otherInstance, PSTR cmdline, int showType)
{
Application application(instance);
return application.run(showType);
}
这下干净多了,不过那个application.h里面是什么东西呢?就是对应用程序的封装,代码如下:
#ifndef APPLICATION_H
#define APPLICATION_H
#include<windows.h>
#include"window.h"
class Application
{
public:
Application(HINSTANCE instance);
public:
int run(int showType);
private:
Window window;
};
#endif //APPLICATION_H
Application的实现如下(application.cpp):
#include"application.h"
Application::Application(HINSTANCE instance) : window(instance)
{}
int Application::run(int showType)
{
window.show(showType);
MSG message;
while(GetMessage(&message, NULL, 0, 0))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
return static_cast<int>(message.wParam);
}
然后刚才的application.h中引用了window.h,这个文件中包含了窗口的封装,代码如下:
#ifndef WINDOW_H
#define WINDOW_H
#include<windows.h>
class Window
{
public:
Window(HINSTANCE instance);
public:
void show(int showType);
public:
static LRESULT CALLBACK WndProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam);
public:
WNDCLASS wndClass;
HWND window;
};
#endif //WINDOW_H
窗口的实现代码如下所示(window.cpp):
#include"window.h"
Window::Window(HINSTANCE instance)
{
static TCHAR applicationName[] = TEXT("HelloWindows");
static TCHAR applicationTitle[] = TEXT("Hello Windows 98!");
wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = WndProc;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = instance;
wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndClass.hCursor = LoadCursor(NULL, IDI_APPLICATION);
wndClass.hbrBackground = static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));
wndClass.lpszMenuName = NULL;
wndClass.lpszClassName = applicationName;
if(!RegisterClass(&wndClass))
{
MessageBox(NULL, TEXT("This program requires Windows NT!"), applicationTitle, MB_ICONERROR);
}
window = CreateWindow(applicationName, applicationTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, instance, NULL);
}
void Window::show(int showType)
{
ShowWindow(window, showType);
UpdateWindow(window);
}
LRESULT CALLBACK Window::WndProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_CREATE:
PlaySound(TEXT("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC);
return 0;
case WM_PAINT:
{
RECT rectangle;
GetClientRect(window, &rectangle);
PAINTSTRUCT ps;
HDC deviceContent = BeginPaint(window, &ps);
DrawText(deviceContent, TEXT("Hello, Windows 98!"), -1, &rectangle, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
EndPaint(window, &ps);
}
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(window, message, wParam, lParam);
}
至此,整个抽象封装结束了,总算不用一下子看一堆代码了。