一起来搭建像Qt一样的win32图形框架(2)

上一篇文章中,我们已经实现了一个最简单的功能,这一篇文章我们一起来实现控件的添加。以按钮作为例子来实现。

首先我们来实现一个按钮类。

class PushButton :public Wnd{
public:
	PushButton(LPCWSTR windowName, int id, Wnd* parent){
		createWindow(L"button", windowName, BS_PUSHBUTTON|WS_CHILD|WS_VISIBLE, 0, 0, 0, 0, parent->hWnd(), HMENU(id));
	}
};

按钮类PushButton继承自Wnd,windowName表示按钮上显示的文字,id表示按钮的ID,parent表示父窗体。调整我们的main函数如下:

int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
	_In_opt_ HINSTANCE hPrevInstance,
	_In_ LPTSTR lpCmdLine,
	_In_ int nCmdShow)
{
	Application app;
	MainWindow w;
	PushButton btn1(L"btn1", 1, &w);
	PushButton btn2(L"btn2", 1, &w);
	btn1.resize(50, 30);
	btn2.resize(50, 30);
	btn2.move(60, 0);
	w.show();
	return app.exec();
}

注意:resize和move函数实现在Wnd中,代码如下:

	void resize(int w, int h){ ::SetWindowPos(_hWnd, 0, 0, 0, w, h, SWP_NOZORDER | SWP_NOMOVE); }
	void move(int x, int y){ ::SetWindowPos(_hWnd, 0, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE); }

现状运行程序,可以看到效果如下:

可以看到,按钮已经成功添加到窗口了,那么接下来需要做的事情就是考虑如何响应按钮事件了。个人比较偏爱Qt,因此想这样实现:点击按钮会响应MainWindow的buttonClickEvent函数,然后在函数参数可以指示按钮的id。下面我们实现MainWindow的buttonClickEvent函数:

void buttonClickEvent(int id){
		if (id == 1)
			MessageBox(_hWnd, L"1", L"", MB_OK);
		if (id==2)
			MessageBox(_hWnd, L"2", L"", MB_OK);
	}

然后调整MainWindow的proc函数:

HRESULT proc(UINT message, WPARAM wParam, LPARAM lParam){
		switch (message)
		{
		case WM_DESTROY:
			PostQuitMessage(0);
			break;
		case WM_COMMAND:
			buttonClickEvent(LOWORD(wParam));
			break;
		default:
			return DefWindowProc(_hWnd, message, wParam, lParam);
		}
		return 0;
	}

亲们请注意:这里我指示为了演示,WM_COMMAND下并不一定是按钮事件哟!

现在点击按钮,是不是有反应了呢!!!其实这里buttonClickEvent函数的参数最好封装成一个Event类,像Qt那样,这里只是演示,也足够了。到目前为止,框架基本完成了,相信亲们可以举一反三,实现其他控件如Label等的创建和其他事件的响应。

其实现在的代码很乱。尤其是main函数,有违我们的初衷。让我们来整理一下:将Application类和Wnd类单独放到一个文件里,PushButton类和MainWindow也各自单独放到一个文件里,将MainWindow的buttonClickEvent函数定义为虚函数并删除实现代码。然后我们在main.cpp中重新定义一个类MyMainWindow并继承自MainWindow:

class MyMainWindow :public MainWindow{
public:
	MyMainWindow() :MainWindow()
		, btn1(L"btn1",1,this)
		, btn2(L"btn2", 2, this)
	{
		btn1.resize(50, 30);
		btn2.resize(50, 30);
		btn2.move(60, 0);
	}

	void buttonClickEvent(int id){
		if (id == 1)
			MessageBox(_hWnd, L"1", L"", MB_OK);
		if (id == 2)
			MessageBox(_hWnd, L"2", L"", MB_OK);
	}
private:
	PushButton btn1;
	PushButton btn2;
};
现在main函数如下:
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
	_In_opt_ HINSTANCE hPrevInstance,
	_In_ LPTSTR lpCmdLine,
	_In_ int nCmdShow)
{
	Application app;
	MyMainWindow w;
	w.show();
	return app.exec();
}

功能一样,但main函数又清静了,并且现在整个程序的架构和Qt非常相似!在整个框架中,Application,Wnd,MainWIndow属于基本的模块,功能大家可以逐步完善,例如像MainWindow的事件,目前只有WM_COMMAND的按钮事件。PushButton属于控件,也需要不断扩展。以后的程序可以直接都继承MainWindow,然后响应响应的功能即可,比如有按钮,重新实现buttonClickEvent函数即可。main函数都一样。不需要额外处理了。整个程序的处理全部都集中在了继承自MainWindow那个类。不知道亲们有没有收获呢?

结语:其实在真正的实际运用中,考虑的情况更多,之前这两篇文章主要是一起探讨学习,只关注关键点,没有进行异常处理,也没有考虑代码的通用性。小弟比较喜欢折腾,喜欢重用自己的代码,基本上有一套自己的代码库,上面的win32图像框架也在其中,并且更加完善且会不断完善,支持layout等布局,有兴趣的同学欢迎下载,Qt的库用Q打头,小弟就用X打头好了!
代码库说明:

src目录下为只依赖C++库的C++代码,win32下就是这两篇文章的图形框架。所有代码主要以hpp形式组织。

win32下图形库代码示例:

#include "win32/XApplication.hpp"
#include "win32/XMainWindow.hpp"
#include "win32/XHBoxLayout.hpp"
#include "win32/XPushButton.hpp"

int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
	_In_opt_ HINSTANCE hPrevInstance,
	_In_ LPTSTR lpCmdLine,
	_In_ int nCmdShow)
{
	XApplication app;
	XMainWindow w("test");
	XHBoxLayout* layout = new XHBoxLayout(&w);
	layout->addWidget(new XPushButton("123", &w));
	layout->addWidget(new XPushButton("456", &w));
	w.resize(300, 200);
	w.show();
	return app.exec();
}

以上代码效果如下:


调整窗体大小是按钮大小也会自动调整,类似Qt,具体用法也和Qt类似。这里没有继承XMainWindow只是为了演示,如果是真正需要实现实际功能的程序,最好还是继承XMainWindow,然后在这里类里面完成所有的逻辑。



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值