版权声明:本文为博主原创文章,未经同意不允许转载! https://blog.csdn.net/wb175208/article/details/81506097
在做项目的时候,如果让一个软件工程可以高效的运行,让各个窗口之间流畅的通信,除了使用Windows中的消息机制外还可以,还可以使用设计模式中的观察者模式,把各个窗口的消息注册到同一的管理类中,任意一个窗口的发送消息,只要是注册过这个消息的窗口就会接收到这个消息并且进行处理。
环境:VS2013+QT5.7.0
1.定义消息及其参数
#ifndef _WNDMSG_DEF_H_
#define _WNDMSG_DEF_H_
class QtWndObject;
typedef long WND_LPARAM;
typedef int WND_WPARAM;
//窗口消息
enum WndMsg {
WNDMSG_CLOSE = 0x1001,
WNDMSG_PAINT,
};
struct WndType{
int id;//当前窗口ID
QtWndObject* wndObj;//窗口指针
};
#endif // !_WNDMSG_DEF_H_
2.设计窗口基类
class QTWNDOBJECT_EXPORT QtWndObject {
public:
QtWndObject();
void registerWndMsg(WndMsg msg);//注册消息
bool unRegisterWndMsg(WndMsg msg);//反注册消息
//发送消息
void sendWndMsg(WndMsg msg, WND_LPARAM lParam, WND_WPARAM wParam);
//虚函数 - 接收处理消息
virtual bool notifyMsg(WndMsg msg, WND_LPARAM lParam, WND_WPARAM wParam);
//设置当前窗口ID
void setWndID(int id);
//获取当前窗口ID
int getWndID();
private:
int wndID = -1;//当前窗口的ID
};
3.消息管理器
class QtWndObject;
class WndMsgManager {
private:
WndMsgManager();
static WndMsgManager* instance;
public:
~WndMsgManager();
inline static WndMsgManager* getInstance() {
return instance;
}
//注册消息和窗口
void registerWndMsg(WndMsg msg, QtWndObject* objectWnd);
//反注册消息和窗口
bool unRegisterWndMsg(WndMsg msg, QtWndObject* objectWnd);
//发出通知
void notify(WndMsg msg, WND_LPARAM lParam, WND_WPARAM wParam);
private:
std::map<int, std::vector<QtWndObject*>> mapMsgWnd;//消息及其关联窗口
};
WndMsgManager* WndMsgManager::instance = new WndMsgManager;
WndMsgManager::WndMsgManager() {
}
WndMsgManager::~WndMsgManager() {
}
void WndMsgManager::registerWndMsg(WndMsg msg, QtWndObject* objectWnd) {
objectWnd->setWndID((int)objectWnd);//设置当前内存地址为ID
mapMsgWnd[(int)msg].push_back(objectWnd);
}
bool WndMsgManager::unRegisterWndMsg(WndMsg msg, QtWndObject* objectWnd) {
std::vector<QtWndObject*>&wndList = mapMsgWnd[msg];//注意:返回引用
std::vector<QtWndObject*>::iterator iter;
for (iter = wndList.begin(); iter != wndList.end(); iter++) {
if ((*iter)->getWndID() == objectWnd->getWndID()) {
iter = wndList.erase(iter);
return true;
}
}
return false;
}
// 发出通知
void WndMsgManager::notify(WndMsg msg, WND_LPARAM lParam, WND_WPARAM wParam) {
std::vector<QtWndObject*> wndList = mapMsgWnd[msg];
int wndNum = wndList.size();
for (int i = 0; i < wndNum;i++){
wndList.at(i)->notifyMsg(msg, lParam, wParam);
}
}
4.子类实现
class QtGuiTest1 : public QWidget, public QtWndObject {
Q_OBJECT
public:
QtGuiTest1(QWidget *parent = Q_NULLPTR);
~QtGuiTest1();
virtual bool notifyMsg(WndMsg msg, WND_LPARAM lParam, WND_WPARAM wParam);
private slots:
void slotBtnTest();
private:
Ui::QtGuiTest1 ui;
};
cpp
QtGuiTest1::QtGuiTest1(QWidget *parent)
: QWidget(parent), QtWndObject() {
ui.setupUi(this);
//注册需要接收的消息
registerWndMsg(WNDMSG_CLOSE);
registerWndMsg(WNDMSG_PAINT);
connect(ui.pushButton, SIGNAL(clicked()), this, SLOT(slotBtnTest()));
}
QtGuiTest1::~QtGuiTest1() {
//反注册消息
unRegisterWndMsg(WNDMSG_CLOSE);
unRegisterWndMsg(WNDMSG_PAINT);
}
bool QtGuiTest1::notifyMsg(WndMsg msg, WND_LPARAM lParam, WND_WPARAM wParam) {
switch (msg) {
case WNDMSG_CLOSE:
qDebug() << QStringLiteral("1窗口关闭");
break;
case WNDMSG_PAINT:
qDebug() << QStringLiteral("1窗口绘制");
break;
}
return true;
}
void QtGuiTest1::slotBtnTest() {
sendWndMsg(WNDMSG_CLOSE, 0, 0);
}
5.分析
当子类调用sendWndMsg时实际调用的是管理器中的notify函数,这个函数的作用就是把所有注册这个消息的窗口函数notifyMsg调用一遍,在子类窗口中通过重写这个函数实现消息的传递。
以上!