CWND to QWidget*



  • Good day,

    I'm using MFC to build a GUI on vs2012 and I recently integrated Qt5.4.1 library in my project. Does anyone know how to connect an CWND pointer to QWidget pointer? I can get the HWND from a widget using winId() but how to get a widget from a HWND or a CWND?

    CWnd* pMfc to the argument of myQtfunction(QWidget* pwidget)

    Thanks in advance!

    Massi


  • Moderators

    Hello @Massi,

    A QWidget is quite a complex class; many of its internals are managed by QApplication. Therefore, you cannot convert a CWND/HWND window directly to a QWidget, because those are managed outside of QApplication.

    Now, it is possible to create a QWindow object to manipulate external windows. It is also possible to embed a QWindow inside a QWidget. You can kind of combine them like this:

    WId externalWindow = (WId)FindWindow(NULL, L"Untitled - Notepad"); // Get HWND by window title
    QWindow *myWindow = QWindow::fromWinId(externalWindow);
    QWidget *myWidget = QWidget::createWindowContainer(myWindow);
    

    However, QWidget::createWindowContainer() was not really designed to handle external windows. You will likely encounter strange issues. See https://bugreports.qt.io/browse/QTBUG-40320 for details.



  • Thanks for your reply @JKSH

    Unfortunately it didn't work and even if I have a pointer to the window as shown below, it crashes.

    BOOL myFMCclass::OnFileOpen(LPCTSTR szPathname, CWnd* pParent)
    {
    	QFile file(szPathname);
    	if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
    		return false;
    	//Embed a QWindow inside a QWidget
    	QWindow* myWindow = QWindow::fromWinId((WId)pParent);
    	QWidget* myWidget = QWidget::createWindowContainer(myWindow);
    
    	myQtclass* m_widgetptr = new myQtclass(myWidget);
    
       return true;
    }
    

    Well I'm trying to display a QGraphicView within an FMC GUI. and if I create a new QWidget instead of using QWidget::createWindowContainer() I get the following error:
    QWidget: Must construct a QApplication before a QWidget

    Again thanks for you help!!!

    Massi


  • Moderators

    @Massi said in CWND to QWidget*:

    even if I have a pointer to the window as shown below, it crashes.

    BOOL myFMCclass::OnFileOpen(LPCTSTR szPathname, CWnd* pParent)
    

    My example is for a HWND, not a CWnd*. You need to convert your pointer to a HWND first. See http://forums.codeguru.com/showthread.php?328037-Converting-CWND*-to-HWND

    Well I'm trying to display a QGraphicView within an FMC GUI...

                                **QWidget: Must construct a QApplication before a QWidget**
    

    As the error message says, you need to create a QApplication before you can create a QWidget. Furthermore, you must call QApplication::exec() before you can interact with any QWidgets -- this requirement makes it tricky to add QWidgets to an existing non-Qt program, because QApplication::exec() blocks the calling thread.

    You could work around this by creating your QApplication and QWidgets in a different thread (see http://stackoverflow.com/questions/22289423/how-to-avoid-qt-app-exec-blocking-main-thread/22290909#22290909 ). However, I have only done that with "native" QWidgets, not using QWidget::createWindowContainer(). it sounds like you want to embed an MFC window inside a QWidget, and then use that QWidget inside the external MFC application...? This is very convoluted, and I have a feeling it won't work nicely.



  • Hello @JKSH ,

    Well I want to embed a QGraphicView widget inside a MFC application. I don't know if QWidget class is enough to handle CWnd and use it as a simple QWidget. should I create a Qdialog window and insert the QGraphicView in it and then try to connect it with my MFC GUI?

    BOOL myFMCclass::OnFileOpen(LPCTSTR szPathname, CWnd* pParent)
    {
    	QFile file(szPathname);
    	if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
    		return false;
    
    	//Embed a QWindow inside a QWidget
    	HWND hWind = pParent->GetSafeHwnd();
    	if(hWind != NULL)
    	{	
    		QWindow* myWindow = QWindow::fromWinId((WId)hWind);
    		QWidget* myWidget = QWidget::createWindowContainer(myWindow);
    		if(myWidget)
    			myQtclass* m_widgetptr = new myQtclass(myWidget);
    	}
       return true;
    }
    

    Many thanks!

    Massi



  • Hello,
    I have to do exactly the same as you, so I tried to code it the same way. but when I run
    QWindow *myWindow = QWindow::fromWinId(externalWindow);
    I am getting an access violation error. Have you had this problem? Do you know how to fix it?
    Thank you,
    Emmanuel



  • @EmmanuelC
    If your code is also like:

    	QWindow* myWindow = QWindow::fromWinId((WId)pParent);
    	QWidget* myWidget = QWidget::createWindowContainer(myWindow);
    

    are you sure that your access violation comes during fromWinId() rather than from createWindowContainer? If it's the latter it might be worth looking at https://stackoverflow.com/questions/30162091/drawing-errors-and-crash-with-qwidgetcreatewindowcontainer.



  • Hello JonB, thank you for your answer. Yes I am sure because I didn't even include QWidget::createWindowContainer yet. (I wanted to test first if the four first functions worked.)

    For now my code is like this:

    CWnd* cwnd= GetDlgItem(IDC_STATIC);
    HWND hWnd = cwnd->GetSafeHwnd();
    WId externalWindow = (WId)hWnd;
    QWindow *myWindow = QWindow::fromWinId(externalWindow);
    

    I don't call any other function after that, and really don't understand why I have an access violation here!



  • @EmmanuelC
    I know nothing about this, but...

    The example above (@JKSH) using fromWinId() called it on the result of a FindWindow() for a window from another process, externalWindow. https://doc.qt.io/qt-5/qwindow.html#fromWinId says:

    Creates a local representation of a window created by another process or by using native libraries below Qt.

    You have a CWnd, from an internal window I believe. I don't know how that plays.

    As I said, I know nothing, so I probably can't say much more than this....


Log in to reply