用多个窗口作为一个类的实例的应用程序,c++

Application with multiple windows as instances of a class, C++

本文关键字:实例 c++ 一个 应用程序 窗口      更新时间:2023-10-16

我写了一个应用程序。有一个名为APP的类,具有窗口的句柄,以及其中的消息循环,以及所有这些东西。

它旨在"运行"该类的一些对象,每个对象都有自己的基于一组标准窗口所需的变量的窗口。

消息循环允许公共使用,它是由runmessagelloop方法运行的。int nCmdShow——当然,它是用来告诉如何显示一个窗口的。

现在,当我创建一些像这样的对象:

vector <APP *> App;
for (int i=0; i<3; i++)
{
    App.push_back(&APP(nCmdShow))
    App[i]->RunMessageLoop();
}

程序在开始另一个消息循环之前等待每个消息循环结束。

我想这样做:

vector <APP *> App;
for (int i=0; i<3; i++)
{
    App.push_back(&APP(nCmdShow))
}
for (int i=0; i<3; i++)
{
    App[i]->RunMessageLoop();
}

当我知道启动时要运行多少个窗口时,似乎没问题。

但是我不知道如何动态地创建新的窗口,与其他窗口完全独立。它应该调用消息循环并立即返回WinMain(),而不结束消息循环。

我考虑过多线程应用,每个线程对应一个app类的实例。但是我不知道如何构建多线程应用。

有什么解决方案吗?

我知道你现在想做什么,我已经在我的应用程序框架Lucid中实现了这一点(它仍然是一个正在进行的工作)。为了得到答案,您的窗口类将被称为Window而不是APP

这是通过向创建的每个窗口传递一个全局过程来完成的。所有的窗口共享这个相同的过程。每当任何窗口获得消息时,该消息被发送到全局过程,全局过程检查HWND是否属于您创建的Window,如果是,则将消息发送到该 Windows的过程。下面是它是如何工作的概述。

class Window
{
public:
    // The contents of this function can vary from window to window
    // provided that you make a subclass and override this method.
    virtual LRESULT procedure(HWND wnd, UINT msg, WPARAM wp, LPARAM lp);
    // When you create a Window object, add a pointer to it in this map.
    // Eg. if (this->hwnd != NULL) createdWindows[this->hwnd] = this;
    static map<HWND, Window*> createdWindows;
    // When you create a window, make this its procedure.
    static LRESULT CALLBACK routeMessage(HWND wnd, UINT msg, WPARAM wp, LPARAM lp)
    {
        if (createdWindows.find(wnd) != createdWindows.end()) {
            // Message belongs to one of our 'Window' objects.
            // Pass the message to that window and return the result.
            return createdWindows[wnd]->procedure(wnd, msg, wp, lp);
        } else {
            // It seems you made 'routeMessage' the procedure
            // of a window that doesn't belong in the map. Go ahead
            // and process the message in the default manner.
            return DefWindowProc(wnd, msg, wp, lp);
        }
    }
};

现在您只需要一个消息循环和一个线程。我有一个使用Lucid的测试项目,它在一个带有单个消息循环的线程上创建了两个具有不同过程的窗口:

#include "Lucid.h"
using namespace Lucid;
void sayBye(MessageEventArgs& e)
{
    MessageBox(NULL, "Goodbye!", "Form 2", MB_OK);
    e.handled = true;
}    
void Program::onStart()
{
    Form* myForm1 = new Form("Hello World!");
    myForm1->show();
    Form* myForm2 = new Form("Hello World!");
    myForm2->addMessageHandler(WM_CLOSE, sayBye);
    myForm2->show();
    // This Program::onStart() function is called
    // immediately before the single message loop is entered.
}

创建_beginthreadex等于您需要运行的窗口数的线程。然后,在线程过程中运行消息循环,直到使用WaitForMultipleObjects终止所有线程。