Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Correct Way to Handle Multiple windows? #8

Open
Snow-Okami opened this issue Jul 18, 2017 · 2 comments
Open

Correct Way to Handle Multiple windows? #8

Snow-Okami opened this issue Jul 18, 2017 · 2 comments

Comments

@Snow-Okami
Copy link

I have been trying to get multiple windows working without much luck. I don't know how to go about it at all. At first I tried pure inheritance but I couldn't get this to work without running into the diamond problem. I also don't know QT enough (specifically their QWidget class) to get this working. Then I tried a combination of inheritance and a hardcoded enum that is passed in to the constructor that tells the QWinWidget which type of class to create (widget.cpp).

When I do this however, having 2 windows open at once, causes a rendering error, as well as interaction within the windows to behave oddly. It seems as though parts of the 2 windows are controlling one another still leading the odd behavior.

I basically made copies of widget.cpp and widget.h for my different windows, and modified QWinWidget.cpp and QWinWidget.h to accept these copies and spawn different windows. These copies are derived from a basewidget.cpp (the original widget.cpp).

Is there any simple example or explanation you could provide that could aid me in this? Thanks so much.

@Snow-Okami
Copy link
Author

Snow-Okami commented Jul 31, 2017

After taking a break, and then coming back to this, I have figured out how to solve the issue. But the issue I had prior has re-emerged (the dragging windows). Here is how I solved it. Basically the static members of WinNativeWindow (childWindow and childWidget) need to become non static. By them being static it causes all windows spawn to share the same first-created window and widget. This is why the others were being controlled in strange manners as well as not occupying the full space. To do this however you must find a way to expose these to the static LRESULT CALLBACK WndProc. To do this, we transform them into pointers to save into the userdata of the window.

QWinWidget.cpp

Change:

p_ParentWinNativeWindow = new WinNativeWindow(1  * window()->devicePixelRatio()
        , 1 * window()->devicePixelRatio()
        , 1 * window()->devicePixelRatio()
        , 1 * window()->devicePixelRatio()
        , (HWND)winId()
        , this);

Delete the following:

p_ParentWinNativeWindow->childWindow = (HWND)winId();
p_ParentWinNativeWindow->childWidget = this;

WinNativeWindow.h

Change:

WinNativeWindow(const int x, const int y, const int width, const int height, const HWND hwnd, QWidget* childwidget);

HWND childWindow;
QWidget* childWidget;

WinNativeWindow.cpp

Delete (at top, above constructor):

HWND WinNativeWindow::childWindow = nullptr;
QWidget* WinNativeWindow::childWidget = nullptr;

Change (Constructor at top):

WinNativeWindow::WinNativeWindow(const int x, const int y, const int width, const int height, const HWND hwnd, QWidget* childwidget)
    : hWnd(hwnd),
      childWidget(childwidget)
{

Add (under the other SetWindowLongPtr):

SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(hWnd));
SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(childWidget));

Add (under LRESULT CALLBACK):

HWND* childWindow = reinterpret_cast<HWND*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
QWidget *childWidget = reinterpret_cast<QWidget*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));

Change:

        case WM_CLOSE:
        {
            if (*childWindow)
            {
                SendMessage(*childWindow, WM_CLOSE, 0, 0);
                return 0;
            }
            break;
        }

After doing that, multiple windows will work, just do the same in the main.cpp as the other window to spawn a second window independent of the first:

    QWinWidget ww;

    ww.setGeometry(windowXPos, windowYPos, windowWidth, windowHeight);

    ww.show();

I'm going to continue working on this a bit and try to solve the dragging issue I am having again to get this all working.

@cfazilleau
Copy link

Thank you for the solution, after some fixes, it works like a charm.

The problem is that the USERDATA can only hold one pointer.

so when you do

SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(hWnd));
SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(childWidget));

the USERDATA pointer is overriden by each call. a way to fix that is by grouping all the pointers we need to pass in a struct, and pass a pointer to this struct

struct userData_t
{
	WinNativeWindow* nativeWindow;
	HWND*		 childWindow;
	QWidget*	 childWidget;
};

userData_t userdata;
SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(&userData));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants