面向对象,掌握windows应用程序的创建过程:为应用程序添加消息及响应

1、在前一篇文章中:一个窗口的诞生中详细介绍了面向对象的方式创建Windows应用程序窗口的过程。

2、一个Windows应用程序应该有交互的功能,也就是说,我们得为其添加消息响应,添加对话框,添加控件等详细的功能,这样才能初具规模的形成一个Windows应用程序。

3、windows应用程序是由消息驱动(Message)的,没有了Message,windows便没有了生机和活力。现在为之前的窗口添加消息响应,让其拥有基本的消息响应功能。

      windows消息是由系统定义的形如WM_PAINT和WM_CLOSE这样的值,当然用户也可以自定义消息及其响应函数。我们为Windows添加消息便是为相应的消息添加响应函数。在添加消息之前,我们需要对Windows消息有一定的了解。

4、Windows消息介绍:

在Windows中消息有三种类型,分为标准消息,命令消息,通告消息。他们的区别如下:

1)、标准消息:

      1、除WM_COMMAND之外,所有以WM_开头的消息,对应得消息宏通常为ON_WM_''''

2)、命令消息:

      1、来自菜单、加速键或工具栏按钮的消息。这类消息都以WM_COMMAND呈现。在MFC中,通过菜单项的标识(ID)来区分不同的命令消息;在SDK中,通过消息的wParam参数识别。

3)、通告消息:

      1、由控件产生的消息,例如,按钮的单击,列表框的选择等均产生此类消息,为的是向其父窗口(通常是对话框)通知事件的发生。这类消息也是以WM_COMMAND形式呈现,对应得宏类如ON_BN_CLICKED,区别于ON_WM


不管是哪一类消息,都得有其相应的消息响应函数来处理消息,既然这样我们可以定义一个宏来表明消息映射:

#define MY_MESSAGE_MAP  \
	tagMessage  MessageMap[] = { \
	WM_CHAR, CMyWnd::OnChar, \
	WM_LBUTTONDOWN, CMyWnd::OnLButtonDown, \
	WM_PAINT, CMyWnd::OnPaint, \
	WM_DESTROY, CMyWnd::OnDestroy, \
	WM_TIMER, CMyWnd::OnTimer, \
	WM_CLOSE, CMyWnd::OnClose, \
	WM_CREATE, CMyWnd::OnCreate, \
	}; \


也可以定义宏来表明消息响应函数:

#define MY_MESSAGE_DECLARE                                      \
	static LRESULT OnChar(HWND, UINT, WPARAM, LPARAM);			\
	static LRESULT OnLButtonDown(HWND, UINT, WPARAM, LPARAM);	\
	static LRESULT OnPaint(HWND, UINT, WPARAM, LPARAM);			\
	static LRESULT OnDestroy(HWND, UINT, WPARAM, LPARAM);		\
	static LRESULT OnTimer(HWND, UINT, WPARAM, LPARAM);			\
	static LRESULT OnClose(HWND, UINT, WPARAM, LPARAM);			\
	static LRESULT OnCreate(HWND, UINT, WPARAM, LPARAM);        \


5、有了这个基础,那我们就可以来看一下源代码了
stdafx.h头文件

#ifndef _STDAFX_H
#define _STDAFX_H

#define MY_MESSAGE_DECLARE                                      \
	static LRESULT OnChar(HWND, UINT, WPARAM, LPARAM);			\
	static LRESULT OnLButtonDown(HWND, UINT, WPARAM, LPARAM);	\
	static LRESULT OnPaint(HWND, UINT, WPARAM, LPARAM);			\
	static LRESULT OnDestroy(HWND, UINT, WPARAM, LPARAM);		\
	static LRESULT OnTimer(HWND, UINT, WPARAM, LPARAM);			\
	static LRESULT OnClose(HWND, UINT, WPARAM, LPARAM);			\
	static LRESULT OnCreate(HWND, UINT, WPARAM, LPARAM);        \

#define MY_MESSAGE_MAP  \
	tagMessage  MessageMap[] = { \
	WM_CHAR, CMyWnd::OnChar, \
	WM_LBUTTONDOWN, CMyWnd::OnLButtonDown, \
	WM_PAINT, CMyWnd::OnPaint, \
	WM_DESTROY, CMyWnd::OnDestroy, \
	WM_TIMER, CMyWnd::OnTimer, \
	WM_CLOSE, CMyWnd::OnClose, \
	WM_CREATE, CMyWnd::OnCreate, \
	}; \


#define dim(X)(sizeof(X)/sizeof(X[0]))

#endif

CWinApp头文件

#ifndef _CWIN_APP_H
#define _CWIN_APP_H
#include "MainWnd.h"

class CWinApp{
private:

public:
	CMyWnd *m_pWnd;
	bool InitInstance();
	bool Run();

	CWinApp();
	virtual ~CWinApp();
protected:
};

#endif

MainWind头文件

#ifndef AFX_WIN32LIB_H__510E6511_F3DB_4E80_B512__INCLUDED_
#define AFX_WIN32LIB_H__510E6511_F3DB_4E80_B512__INCLUDED_
#pragma once

#if _MSC_VER >1000
#pragma once
#endif  //_MSC_VER>1000 

#include <windows.h>
#include "stdafx.h"

typedef LRESULT  (*FXN)(HWND, UINT, WPARAM, LPARAM);

struct  tagMessage
{
	UINT code;
	FXN  Fxn;
};

class CMyWnd
{
private:
	HINSTANCE m_hInstance;
	HWND      m_hWnd;
protected:
public:
	virtual void PreCreateWindow(WNDCLASS &cs);
	bool Create();
	bool ShowWindow();
	bool UpdateWindow();
	CMyWnd();
	virtual ~CMyWnd();

   static LRESULT CALLBACK WinProc(HWND, UINT, WPARAM, LPARAM);
	
   //消息响应函数
   MY_MESSAGE_DECLARE

};

#endif // !AFX_WIN32LIB_H__510E6511_F3DB_4E80_B512__INCLUDED_

CWinApp实现文件:

#include "CWinApp.h"

CWinApp::CWinApp()
{
	m_pWnd = NULL;

	if (InitInstance())
		Run();
}

CWinApp::~CWinApp()
{

}

bool CWinApp::InitInstance()
{
	m_pWnd = new CMyWnd;
	m_pWnd->Create();
	m_pWnd->UpdateWindow();
	m_pWnd->ShowWindow();
	return true;
}

bool CWinApp::Run()
{
	MSG msg;
	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return true;
}

MainWind实现文件

#include "MainWnd.h"
#include "stdio.h"
#include "stdlib.h"
#include "string"

MY_MESSAGE_MAP

CMyWnd::CMyWnd()
{

}

CMyWnd::~CMyWnd()
{
	if (NULL != this)
		delete this;
}

bool CMyWnd::Create()
{
	WNDCLASS cs;
	cs.cbClsExtra = 0;
	cs.cbWndExtra = 0;
	cs.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	cs.hCursor = (HCURSOR)LoadCursor(NULL, IDC_ARROW);
	cs.hIcon = (HICON)LoadIcon(NULL, IDI_ERROR);
	cs.hInstance = m_hInstance;
	cs.lpfnWndProc = WinProc;
	cs.lpszClassName = LPCWSTR("Beautiful");
	cs.lpszMenuName = NULL;
	cs.style = CS_HREDRAW | CS_VREDRAW;

	PreCreateWindow(cs);
	RegisterClass(&cs);

	m_hWnd = ::CreateWindow(cs.lpszClassName,
		TEXT("Beautiful"),
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT,
		CW_USEDEFAULT, CW_USEDEFAULT,
		NULL, NULL, m_hInstance, NULL);
	if (NULL == m_hWnd)
		return false;
	else
		return true;
}
void CMyWnd::PreCreateWindow(WNDCLASS &cs)
{
	cs.hbrBackground = ::CreateSolidBrush(RGB(255, 0, 0));
	cs.hIcon = ::LoadIcon(NULL, IDI_INFORMATION);
}



bool CMyWnd::UpdateWindow()
{
	if (::UpdateWindow(m_hWnd))
		return true;
	else
		return false;
	
}

bool CMyWnd::ShowWindow()
{
	if (::ShowWindow(m_hWnd, SW_SHOWNORMAL))
		return true;
	else
		return false;
}

LRESULT CALLBACK CMyWnd::WinProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
	/*switch (nMsg)
	{
	case WM_DESTROY:
	PostQuitMessage(0);
	break;


	}*/

	for (int i = 0; i < dim(MessageMap); i++)
	{
		if (nMsg == MessageMap[i].code)
		{
			FXN iFxn = MessageMap[i].Fxn;
			LRESULT lResult = iFxn(hWnd, nMsg, wParam, lParam);
			if (lResult == 0)
				return 0;
		}
	}

	return DefWindowProc(hWnd, nMsg, wParam, lParam);
}


LRESULT CMyWnd::OnChar(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
	char szChar[20];
	sprintf_s(szChar, "char is %c", (char)wParam);
	MessageBox(hWnd,reinterpret_cast<LPCWSTR>(szChar), TEXT("OnChar"), 0);

	return 0;
}

LRESULT CMyWnd::OnClose(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
	if (::MessageBox(hWnd, TEXT("真的要关闭窗口吗?"), TEXT("OnClose"), MB_YESNO) == IDYES)
	{
		::DestroyWindow(hWnd);
	}
	return 0;
}

//消息响应函数: 鼠标左键按下
LRESULT CMyWnd::OnLButtonDown(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
	HDC hdc;
	wchar_t *szTitle =L"一个美好的世界";
	hdc = GetDC(hWnd);
	TextOut(hdc, 0, 50, TEXT("一个美好的世界"), wcslen(szTitle));
	ReleaseDC(hWnd, hdc);
	return 0;
}

//消息响应函数:重绘窗口
LRESULT CMyWnd::OnPaint(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
	//画一个圆
	RECT rc;
	GetClientRect(hWnd, &rc);

	int iR = min(rc.right - rc.left, rc.bottom - rc.top) / 2;
	iR = iR * 4 / 5;
	POINT pt;
	pt.x = (rc.right + rc.left) / 2;
	pt.y = (rc.bottom + rc.top) / 2;

	HDC hdc;
	PAINTSTRUCT ps;
	hdc = BeginPaint(hWnd, &ps);

	::Ellipse(hdc, pt.x - iR, pt.y - iR, pt.x + iR, pt.y + iR);
	MoveToEx(hdc, pt.x, pt.y, (LPPOINT)NULL);
	LineTo(hdc, pt.x + iR, pt.y);

	//显示时间
	static wchar_t stime[16] = TEXT("23:59:59");
	SYSTEMTIME tm;
	::GetLocalTime(&tm);
	swprintf_s(stime,16, TEXT("%2d:%2d:%2d"), tm.wHour, tm.wMinute, tm.wSecond);
	::TextOut(hdc, 10, 10, reinterpret_cast<LPCWSTR>(stime), wcslen(stime)+1);

	EndPaint(hWnd, &ps);

	return 0;
}

//消息响应函数: 销毁窗口
LRESULT CMyWnd::OnDestroy(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
	PostQuitMessage(0);
	return 0;
}

//消息响应函数: 定时器
LRESULT CMyWnd::OnTimer(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
	RECT rc;
	::GetClientRect(hWnd, &rc);
	::InvalidateRect(hWnd, &rc, TRUE);
	return 0;
}

//消息响应函数: 创建窗口
LRESULT CMyWnd::OnCreate(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
	::SetWindowText(hWnd, TEXT("消息循环"));
	::SetTimer(hWnd, 10,1000, NULL);
	return 0;
}

Window文件:

#include "CWinApp.h"


CWinApp theApp;

int WINAPI WinMain(_In_ HINSTANCE hInstance, \
	               _In_opt_ HINSTANCE hPrevInstance, \
	               _In_ LPSTR lpCmdLine, \
	               _In_ int nShowCmd)
{
	return 0;
}

6、可以看到该程序的结构相对于之前的没有太大的改变,只是添加了一些消息响应函数。在这里需要注意的有以下几点:

  1)、要把Declare宏放到类的声明内部:

   static LRESULT CALLBACK WinProc(HWND, UINT, WPARAM, LPARAM);
	
   //消息响应函数
   MY_MESSAGE_DECLARE

};
  2)、把消息映射放到类的实现中去:

MY_MESSAGE_MAP

CMyWnd::CMyWnd()
{

}

CMyWnd::~CMyWnd()
{
	if (NULL != this)
		delete this;
}
这样的话系统才能知道函数和消息之间的关系。


7、程序运行的结果如下所示:






    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值