VC++学习笔记之HelloWorld

本系列文章记录我学习VC++的过程。

一直以来我对自己的定位是C++工程师,但到目前为止我对C++的了解还停留在C阶段,只会用C的特性加上面向对象的知识写一点控制台程序,要我写真正能应用到企业上的实用性应用就无能为力了。虽然实习的时候靠着学校学的基础知识成功应聘了C++开发工程师,但现在做的却是Flex方向的开发工作。

所以我要用这个暑假全面攻克C++,包括VC++,C++11新特性及STL基础。

话不多说,现在开始VC++的HelloWorld!先贴代码。

LRESULT CALLBACK WinProc(
	HWND hWnd,
	UINT uMsg,
	WPARAM wParam,
	LPARAM lParam);

/*主程序*/
int APIENTRY WinMain(HINSTANCE hInstance,
	HINSTANCE hPreInstance,
	LPSTR lpCmdLine,
	int nCmdShow) {

	//(1)设计窗口类
	WNDCLASS wndcls;
	wndcls.cbClsExtra = 0;	//窗口类附加内存
	wndcls.cbWndExtra = 0;	//窗口附加内存
	wndcls.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);	//窗口背景刷
	wndcls.hCursor = LoadCursor(NULL, IDC_CROSS);	//窗口光标
	wndcls.hIcon = LoadIcon(NULL, IDI_ERROR);		//窗口图标
	wndcls.hInstance = hInstance;		//窗口句柄
	wndcls.lpfnWndProc = WinProc;		//窗口处理过程
	wndcls.lpszClassName = _T("myWindow");	//窗口类
	wndcls.lpszMenuName = NULL;			//窗口菜单
	wndcls.style = CS_HREDRAW | CS_VREDRAW;	//窗口类样式

	//(2)注册窗口类
	RegisterClass(&wndcls);

	//(3)创建窗口
	HWND hwnd;
	hwnd=CreateWindow(_T("myWindow"), _T("Hello"), WS_OVERLAPPEDWINDOW, 100, 100, 960, 640, NULL, NULL, hInstance, NULL);

	//(4)显示及刷新窗口
	ShowWindow(hwnd, nCmdShow);
	UpdateWindow(hwnd);

	//(5)开始消息循环
	MSG msg;
	BOOL bRet;
	while (bRet=GetMessage(&msg, NULL, 0, 0)) {
		//如果指定消息属于当前创建的窗口,那么必须做一个错误判断
		//因为窗口被销毁后获取消息就会得到一个错误,不作判断的话会陷入死循环
		//当然,指定消息所属的窗口为空,判断错误就可有可无了
		if (bRet == -1) {
			return -1;
		}
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return msg.wParam;
}

LRESULT CALLBACK WinProc(
	HWND hWnd,
	UINT uMsg,
	WPARAM wParam,
	LPARAM lParam)
{
	switch (uMsg)
	{
	case WM_CHAR:
		CHAR szChar[20];
		//wprintf(szChar, _T("%d"), wParam);
		sprintf_s(szChar, "按键代码 is %c", wParam);
		MessageBoxA(hWnd, szChar, "按键", 0);
		break;
	case WM_LBUTTONDOWN:
	{
		MessageBox(hWnd, _T("鼠标左键按下!"), _T("提示"), 0);
		HDC hDc;
		hDc = GetDC(hWnd);
		TextOut(hDc, 0, 0, _T("Vc++ 程序设计!"), _tcslen(_T("Vc++ 程序设计!")));
		ReleaseDC(hWnd, hDc);
	}
	break;
	case WM_PAINT:
	{
		HDC hDc;
		PAINTSTRUCT ps;
		hDc = BeginPaint(hWnd, &ps);	//该函数会发送WM_ERASEBKGND消息,使用窗口画刷擦除窗口
		TextOut(hDc, 0, 0, _T("你好,世界!"), _tcslen(_T("你好,世界!")));
		EndPaint(hWnd, &ps);
	}
	break;
	case WM_CLOSE:
		if (MessageBox(hWnd, _T("你真的要退出吗?"), _T("提示"), 0) == IDOK) {
			DestroyWindow(hWnd);
		}
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, uMsg, wParam, lParam);
	}
	return 0;
}
Windows应用程序中的几个重要概念:

1、句柄(HANDLE):句柄是Windows操作系统用来区分每个应用的唯一标识。句柄的类型有很多种,有窗口句柄(HWND),图标句柄(HICON),光标句柄(HCURSOR)和画刷句柄(HBRUSH)等等。

2、窗口:窗口是Windows程序最基本的元素,每个Windows程序都至少有一个窗口,称为主窗口。窗口是Windows应用程序与用户进行交互的接口。

3、消息:消息是Windows应用程序一个非常重要的概念,Windows应用程序和操作之间的通信全是消息。操作系统会把用户操作等消息封闭成一个消息放入消息队列中,应用程序从消息队列中取出消息进行响应。这就是操作系统给应用程序发送消息,即操作系统调用应用程序中一个专门处理消息的函数,称为窗口过程。

4、消息队列:操作系统发送的消息可以不进消息队列,也可以进消息队列,进消息的队列的消息等待应用程序取出进行响应。不进消息队列的消息由操作系统直接调用程序的窗口过程进行处理。无论进不进消息队列,消息的处理最终都是调用窗口过程。


一、主函数WinMain

函数原型为下

int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPreInstance,
LPSTR lpCmdLine,
int nCmdShow);
这几个参数由操作系统在应用程序启动时赋予,用不我们手动指定。

hInstance是当前应用程序句柄。

hPreInstance是此类应用程序的上一个运行句柄,win32程序中该参数为空。
lpCmdLine是应用程序启动时带的命令参数,如用记事本打开一个文件时,文件名就是记事本带的参数。

nCmdShow指定窗口启动时的显示方式,如最大化,最小化,隐藏等。


二、窗口过程函数(消息处理的地方)

窗口过程函数用于处理发送给窗口的消息,是一个回调函数。应用程序接收到消息后使用DispathcMessage(&msg)将消息回传给系统,系统则调用窗口过程函数对消息进行处理。函数原型为下

LRESULT CALLBACK WindowProc(
HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam);

Hwnd是窗口的句柄。

uMsg是消息的类型,是Win api定义好的一些常量,以WM_开头,如WM_LBUTTONDOWN表示按下鼠标左键。

wParam和LParam是消息带的参数,这两个宏分别代表不同类型的参数。查看它们的定义:

WPARAM= UINT_PTR=unsigned int

LPARAM=LONG_PTR=long

从定义可以看出WPARAM其实是无符号整型,LPARAM是长整型。windows对很多数据类型进行重定义,主要是为了更直观地看出参数的作用。这个函数之所以要带这两个参数,是因为不同的消息带的参数可能不同,有些是无符号的,有些是有符号的。(这里说到long和unsigned int,就随便说说c++中这几个整型的区别。一直以来我都以为long比int长,后来才知道其实不是这么回事。int通常代表机器证书的自然长度,可能是16位也可以是32位,C++引入short和long就是为了直观地表示字节长度。short是16位,而long在16位和32位系统中是32位,在64位系统中是64位。long long则是128位,即8字节。具体的请看下表。)

类型

16位系统/字节

32位系统/字节

64位系统/字节

char

1

1

1

char*

2

4

8

short

2

2

2

int

2

4

4

long

4

4

8

long long

8

8

8


所以,VC给我们定义这些将很多数据类型重定义成直观的名称还是很有用的,让我们不用再纠结到底该用哪种数据类型。

返回值LRESULT也是LONG_PTR类型,即long类型。

再看一下CALLBACK的定义:

#define CALLBACK    __stdcall

这是一个宏定义,CALLBACK的意思是告诉程序这个函数的参数调用方式是怎样的,这种修饰符称为调用约定。具体的请见

点击打开链接

简单说_stdcall就是函数参数由右向左进栈,函数返回时由函数自己而不是调用者清理参数。这种调用约定的函数参数个数是固定的,因此被调用者可以用ret n的方式自己清理。

三、创建窗口
1、设计窗口

设计窗口其实就是定义一个窗口类,并设计窗口类的各个属性。

WNDCLASS wndcls;
	wndcls.cbClsExtra = 0;	//窗口类附加内存
	wndcls.cbWndExtra = 0;	//窗口附加内存
	wndcls.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);	//窗口背景刷
	wndcls.hCursor = LoadCursor(NULL, IDC_CROSS);	//窗口光标
	wndcls.hIcon = LoadIcon(NULL, IDI_ERROR);		//窗口图标
	wndcls.hInstance = hInstance;		//窗口句柄
	wndcls.lpfnWndProc = WinProc;		//窗口处理过程
	wndcls.lpszClassName = _T("myWindow");	//窗口类
	wndcls.lpszMenuName = NULL;			//窗口菜单
	wndcls.style = CS_HREDRAW | CS_VREDRAW;	//窗口类样式

2、注册窗口类

RegisterClass(&wndcls);


3、创建窗口

HWND hwnd;
	hwnd=CreateWindow(_T("myWindow"), _T("Hello"), WS_OVERLAPPEDWINDOW, 100, 100, 960, 640, NULL, NULL, hInstance, NULL);

4、显示及刷新窗口

ShowWindow(hwnd, nCmdShow);
	UpdateWindow(hwnd);

5、开始消息循环。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值