C++ Win32编程入门

如果您想要编写一个图形界面的windows程序,您会用什么语言呢?

C#?VB?抑或是易语言?

哦不好意思。他们都有一个通病:经过深度封装,效率太差,稳定性也(可能)不太好。

那么我们应该选用什么呢?

C++!!!

没错,我们这个专栏,就是要讲讲最底层的Windows图形界面(GUI)程序。(当然您要用MFC,Qt什么的我也没意见,反正这些封装很浅的也挺好的,不过我就是喜欢绕远路)

那么C++的Win32程序有什么缺点呢:

纯代码编程(100%),不直观(编写时),难度较高,不好(自)学,代码比较臃肿,而且效果比较有限。

但是没办法,底层的东西,感觉还是最好的。(至少执行效率秒杀C#VB)

我不是最近在开发ClickIDE吗?然后我们786同学在开发C+++。我用C++,他用C#。结果打开同样的文件,我花了不到0.1秒,他花了10秒其中还有3~4秒处于未响应的状态。况且他的自适应也不怎么样。

好这下直观了吗?还犹豫吗?我们一起开始学习!

(PS这是我第一次写纯基础的教程,若有不好请见谅哈谢谢。)

本教程中的所有软件使用Dev-C++5.11编译通过,用VS也行,不过比较烦。还是用老古董吧。

废话不多说,现在我们开始今天的第一个程序。


第一步:选择文件->新建->项目,会弹出一个叫“新项目”的框框。根据图上的内容进行选择和填写。

第二步,选择好位置,进行保存。一个项目会有很多文件,建议单独建一个文件夹。

第三步,创建完成,可以看见添加了一堆示例代码。我们一会儿来解读一下。

然后我们修改第44行,把"Caption"改为"Hello, world!"。

第四步,编译运行(F11),来看看,结果如何!

与您想象的是否一致呢?

好了,这样我们的第一个Win32程序就完成了,之后我们朝这个空白窗口不断添加各种控件,然后就变成一个像模像样的软件了!

(顺便说一句,ClickIDE就完全使用Win32编写的,因此您看到的每一个按钮,每一个菜单,每一个图标,每一个编辑框,全部都是控件!)


哦差点忘了,我们先赶紧来解释一下这个示例代码吧。

#include <windows.h> //Windows编程都需要的一个头文件,有很多的内容

/* 处理窗口消息的函数 */
LRESULT CALLBACK WndProc(HWND hwnd/*窗口句柄*/, UINT Message/*消息代号*/, WPARAM wParam/*WPARAM类型参数,常见的有数字等*/, LPARAM lParam/*LPARAM类型参数,常见的有字符串等*/) {
	switch(Message) {
		
		/* 销毁窗口的时候发出WM_DESTROY消息 */
		case WM_DESTROY: {
			PostQuitMessage(0);//告诉Windows,你的程序要结束了
			break;
		}
		
		default:
			return DefWindowProc(hwnd, Message, wParam, lParam);//如果这个消息没有被您自己处理的话,交给Windows系统按照默认方式处理。如果之前您已经处理了这个消息,就相当于“拦截”了这个消息,就不会进default,也不会交给系统处理。
	}
	return 0;
}

/* WinMain函数是程序的入口点,exe文件从这里开始执行,相当于控制台程序的main() */
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
	WNDCLASSEX wc; /* 暂时不用懂 */
	HWND hwnd; /* 窗口的句柄("Handle"),是个很玄乎的东西,我自己还没完全搞懂。。。反正您要知道它代表着一个窗口 */
	MSG msg; /* 暂时存储我们接收到的消息 */

	/* 清空结构体中的内容(获取内存) */
	memset(&wc,0,sizeof(wc));
	wc.cbSize		 = sizeof(WNDCLASSEX);
	wc.lpfnWndProc	 = WndProc; /* 接收到了消息,交给这个函数处理 */
	wc.hInstance	 = hInstance; /* 也是个玄乎玩意儿 */
	wc.hCursor		 = LoadCursor(NULL, IDC_ARROW); /* 光标形状 */
	
	/* COLOR_WINDOW,是一个宏,代表窗口颜色(背景色)是白色 */
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
	wc.lpszClassName = "WindowClass"; /*要注册的窗口类名,就是像它的ID一样*/
	wc.hIcon		 = LoadIcon(NULL, IDI_APPLICATION); /* 图标 */
	wc.hIconSm		 = LoadIcon(NULL, IDI_APPLICATION);

	if(!RegisterClassEx(&wc)) {
		MessageBox(NULL, "Window Registration Failed!","Error!",MB_ICONEXCLAMATION|MB_OK);
		return 0;
	}

	hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,"WindowClass","Hello, world!",WS_VISIBLE|WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, /* x */
		CW_USEDEFAULT, /* y */
		640, /* width */
		480, /* height */
		NULL,NULL,hInstance,NULL);

	if(hwnd == NULL) {
		MessageBox(NULL, "Window Creation Failed!","Error!",MB_ICONEXCLAMATION|MB_OK);
		return 0;
	}
        //下面两行是我自己加的,模板里没有,但是应该有(虽然没有好像也没事?)
        ShowWindow(hwnd, 1);//让窗口显示,如果是ShowWindow(hwnd, 0);就是隐藏窗口。现在知道hwnd是干什么用的了吗?就是窗口的”身份证"
        UpdateWindow(hwnd);//更新窗口
	/*整个软件的核心,就是不断接受消息并处理,这就是Windows程序的消息机制,后面有时间我会讲一讲。因为GetMessage是阻塞型函数,因此不会导致程序一直运转而导致CPU高消耗
	*/
	while(GetMessage(&msg, NULL, 0, 0) > 0) { /* 如果没有接收到错误信息 */
		TranslateMessage(&msg); /* 翻译成消息代号 */
		DispatchMessage(&msg); /* 翻译好了消息,交给WndProc处理 */
	}
	return msg.wParam;
}

虽然注释挺详细,但是原版都是英文的,我就用自己的话和大家讲一讲吧。因为没有行号显示,我只能全部放进注释了,请自行看代码!(哈哈,突然发现786的第一篇Apple开发也是这种思路,先新建一个模板项目,然后解说模板代码)。

好了今天就讲那么多,本文均有ericnth.cn原创,未经允许谢绝转载,感谢大家的支持,你们的支持是我更新的动力!

(还有,Win32我是纯靠自己理解一点点摸索出来的,不知道大家听不听得懂我讲,有问题欢迎评论区!同时看的同时,自己也一定要实践啊!!)

5 1 vote
Article Rating
Subscribe
提醒
18 评论
Newest
Oldest Most Voted
Inline Feedbacks
View all comments
qyh

管理员文章免审核!

23786 蘑菇蘑菇蘑菇蘑

经过深度封装,效率太差,稳定性也(可能)不太好。
完全不同意。
1. 经过深度封装 没什么不好。
2. 效率太差 没有的事。
3. 稳定性也不太好 没有的事。

经过深度封装我觉得很好,比如在Mac下你在一个NSWindowController里访问自己的视图里的一个文本框的文字就是

let string = (self.contentViewController as! MyViewController).textView.textStorage.string

我觉得这样用句点语句访问类方法和属性不是很棒吗
如果你不封装
可能就要这样

string a = getString(getTextStorage(getTextView(convertToMyViewController(this->contentViewController))))

(伪代码,瞎写的)
然后再加上win32专属迷惑性变量函数命名方法
可能就长成这样

LPCWSTR a = get_str(GETTEXTSTORAGE(get_txt_v(TO_MY_VIEW_CONTROLLER(this->cttviewc))));

这样不是烦死

23786 蘑菇蘑菇蘑菇蘑

C++法容易理解?

23786 蘑菇蘑菇蘑菇蘑

没有什么区别?

let string = (self.contentViewController as! MyViewController).textView.textStorage.string

LPCWSTR a = get_str(GETTEXTSTORAGE(get_txt_v(TO_MY_VIEW_CONTROLLER(this->cttviewc))));

您说这两个没有区别?
后者更容易理解?

效率一点都不差,不要迷信C++效率高了,C#和VB也差不多,甚至比他快,就算差点顶多5:6,4:5这种区别,如果你开发中不做大数据运算等,那么就等于一样。
不是所有的底层的都稳定性好,速度快的,Mac 原生Cocoa框架,Microsoft .NET框架这么多人用不是没有原因的
至少我知道用.NET或类似框架的软件:课堂狂欢器(VB)、信息统一学业考试用软件(VB)、Spotlight for Windows(不知道)、MyDock(VC++)、MyFinder(VC++)、等等等等等等

23786 蘑菇蘑菇蘑菇蘑

我承认Swift确实是比C++效率低。
但是能低到哪里去呢?
低到赋一个值用一秒?
相比之下,语言的简单、易用性、省时间性还是最重要的
至于快不快,只要你不搞noip这种神必循环运算
一点问题都没有

不好意思我不该挖坟的

qyh

有人看 最近微软又来闹事了。。。。

Yuq Huang

什么事啊

qyh

….

qyh

在研发新操作系统

Yuq Huang

???
迷惑。。。
什么操作系统啊。。。

18
0
Would love your thoughts, please comment.x
()
x