C++ Win32编程入门

Hello, 欢迎登录 or 注册!

/ 18评 / 0

本文作者:  本文分类:Win32编程 编程学习笔记  浏览:2052
阅读时间:2977字, 约3.5-5分钟

如果您想要编写一个图形界面的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开发也是这种思路,先新建一个模板项目,然后解说模板代码)。

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

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

关于作者

  1. qyh说道:

    管理员文章免审核!

  2. EricNTH说道:

    不是这个专栏有人看吗。有人感兴趣吗。没人我就不写了。这个实在是难写炸了。

  3. NSObject 23786说道:

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

    • NSObject 23786说道:

      @NSObject 23786 经过深度封装我觉得很好,比如在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))));
      

      这样不是烦死

      • EricNTH说道:

        @NSObject 23786 迷惑性?难道你不觉得c++法更容易理解?括号和句点看个人喜好 没有什么区别的。综上我看要语法优雅执行速度又高的编程语言恐怕是不存在了(悲哀/)所以有没有想过重启ppp开发(/斜眼笑)

        • NSObject 23786说道:

          @EricNTH C++法容易理解?

        • NSObject 23786说道:

          @EricNTH 没有什么区别?

          let string = (self.contentViewController as! MyViewController).textView.textStorage.string
          
          LPCWSTR a = get_str(GETTEXTSTORAGE(get_txt_v(TO_MY_VIEW_CONTROLLER(this->cttviewc))));
          

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

    • NSObject 23786说道:

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

      • EricNTH说道:

        @NSObject 23786 课堂狂欢器?笑死了笑死了。
        还有swift等的效率低下是你无法感受到的。打开大文件时立马挂掉。5秒和0.01秒的区别,确定是5:6 4:5???不对吧。

        • EricNTH说道:

          @EricNTH 再说了C++和汇编的效率也只有30%的区别(但也感受得出),你哪怕只有5:6 4:5的话也差的很多不是么(再说也绝对不止)。

        • NSObject 23786说道:

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

    • NSObject 23786说道:

      @NSObject 23786 不好意思我不该挖坟的

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注