一.以消息为基础,以事件驱动之
MSG msg;
while (GetMessage(&msg, NULL, NULL, NULL)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
1.消息MSG结构
typedef struct tagMSG
{
HWND hwnd;
UINT message; // WM_xxx,例如WM_MOUSEMOVE,WM_SIZE...
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
} MSG;
2.窗口消息流程图
二.一个具体而微的Win32 程序
#include <Windows.h>
#include "resource.h"
HINSTANCE _hInstance;
HWND _hWnd;
static TCHAR szClassName[] = TEXT("Test");
static TCHAR szWndName[] = TEXT("Text");
BOOL InitApplication(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE hInstance,int nCmdShow);
LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
LRESULT CALLBACK About(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
//
//入口程序WinMain
//
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
if (!InitApplication(hInstance))
{
return FALSE;
}
if (!InitInstance(hInstance,nCmdShow))
{
return FALSE;
}
MSG msg;
while (GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//
//注册窗口类别-——————————InitApplication
//
BOOL InitApplication(HINSTANCE hInstance)
{
WNDCLASS wndclass;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);
wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION);
wndclass.hInstance = hInstance;
wndclass.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
wndclass.lpfnWndProc = WindowProc;
wndclass.lpszClassName = szClassName;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
return RegisterClass(&wndclass);
}
//
//产生窗口-——————————InitApplication
//
BOOL InitInstance(HINSTANCE hInstance,int nCmdShow)
{
_hInstance = hInstance;
_hWnd = CreateWindow(szClassName,szWndName,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
NULL,NULL,_hInstance,NULL);
if (!_hWnd)
{
return FALSE;
}
ShowWindow(_hWnd,nCmdShow);
UpdateWindow(_hWnd);
return TRUE;
}
//
//窗口函数------WindowProc
//
LRESULT CALLBACK WindowProc(
HWND hwnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
)
{
int wmId, wmEvent;
switch (uMsg)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
switch (wmId)
{
case IDM_ABOUT:
DialogBox(_hInstance,MAKEINTRESOURCE(IDD_ABOUT), hwnd, (DLGPROC)About);
break;
case IDM_EXIT:
DestroyWindow(hwnd);
break;
default:
return(DefWindowProc(hwnd, uMsg, wParam, lParam));
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}
//
//对话框函数——About
//
LRESULT CALLBACK About(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hwnd,TRUE);
return TRUE;
}
break;
}
return FALSE;
}
1.程序入口点 WinMain
int WINAPI WinMain(
HINSTANCE hInstance, // handle to current instance
HINSTANCE hPrevInstance, // handle to previous instance
LPSTR lpCmdLine, // pointer to command line
int nCmdShow // show state of window
);
2.窗口类别之注册与窗口之诞生
3.消息循环
while (GetMessage(&msg, NULL, NULL, NULL)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
4.窗口的生命中枢:窗口函数
LRESULT CALLBACK WindowProc(
HWND hwnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
);
窗口函数设计为callback 形式,才能开放出一个接口给操作系统叫用。
5.消息映射的雏形
//定义一个MSGMAP_ENTRY 结构和一个dim 宏:
struct MSGMAP_ENTRY {
UINT nMessage;
LONG (*pfn)(HWND, UINT, WPARAM, LPARAM);
};
#define dim(x) (sizeof(x) / sizeof(x[0]))
组织两个数组_messageEntries[ ] 和_commandEntries[ ]
// 消息与处理例程之对照表格
struct MSGMAP_ENTRY _messageEntries[] =
{
WM_CREATE, OnCreate,
WM_PAINT, OnPaint,
WM_SIZE, OnSize,
WM_COMMAND, OnCommand,
WM_SETFOCUS, OnSetFocus,
WM_CLOSE, OnClose,
WM_DESTROY, OnDestroy,
} ;
// Command-ID
struct MSGMAP_ENTRY _commandEntries =
{
IDM_ABOUT, OnAbout,
IDM_FILEOPEN, OnFileOpen,
IDM_SAVEAS, OnSaveAs,
}
6.对话框的运作
对话框函数(dialog procedure)。其类型非常类似窗口函数,但是它通常只处理WM_INITDIALOG 和WM_COMMAND 两个消息.
Modal 对话框的激活与结束,靠的是DialogBox 和EndDialog 两个API 函数.
三.Windows 程序的生与死
四.空闲时间的处理:OnIdle
while (TRUE) {
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) {
if (msg.message== WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else {
OnIdle();
}
}
PeekMessage 会取回控制权,使程序得以执行一段时间。于是上述消息循环进入OnIdle 函数中。
进程与执行线程