In Win32 API we have 2 functions called 'SetProp' and 'GetProp' to set and get the property of a window identified by HWND
SetProp:
http://msdn.microsoft.com/en-us/library/ms633568%28VS.85%29.aspx
I have 2 applications, one coded with Qt, the other coded with Win32 API. I need some kind of flag so the application in Win32 can recognise the application in Qt.
Are there any equivalent functions in Qt to set and get the properties for QMainWindow?
I would just use the HWND of the QMainWindow returned by QWidget::winId() in use with the two Windows functions that you mentioned in your question.
Somewhat related... here are ways to access other properties that are associated with a HWND of a QMainWindow:
Most are covered by the Window Flags
Window Flags Example
Qt::WindowFlags
QWidget::setWindowFlags()
and Widget Attributes...
QWidget::setAttribute()
Qt::WidgetAttribute
This should yield your answer:
About using an undocumented class in Qt
(Using setProperty or the undocumented class if you like being risky).
http://doc.qt.digia.com/qt/qobject.html#setProperty
Related
I'm reading Chapter "Drawing with GDI" in book "Programming Windows with MFC".
I saw that CFramewnd or Document/View are used in all examples of this chapter.
I think that maybe CDialog is not proper way to build drawing application.
So, my question is: should I use CDialog or CFramewnd or Docuemnt/View to build drawing application?
And could you give me some difference between CDialog and CFramewnd?
CDialog is intended to be used as the base class for dialogs - relatively shortlived windows to communicate relatively simple bits of information. There are a bunch of standard dialogs (e.g. File Open dialog) but for most information, you'd write your own and base that on CDialog.
So it's not intended as the main window for a normal application. Yet, if your application is a simple tool - say switch a single registry value from 0 to 1 - it may make sense to implement it as just a dialog. But a drawing application? That's not a dialog.
the following code tries to embed a native Win32 HWND of a custom created OpenGL windows into a QWidget using the create method:
viewer_widget::viewer_widget(
QWidget* parent,
const viewer::viewer_attributes& view_attrib,
const wm::context::attribute_desc& ctx_attrib,
const wm::surface::format_desc& win_fmt)
: QWidget(parent)
{
setMouseTracking(true);
setFocusPolicy(Qt::StrongFocus);
setAttribute(Qt::WA_NativeWindow, true);
setAttribute(Qt::WA_PaintOnScreen, true); // disables qt double buffering (seems X11 only since qt4.5, ...)
setAttribute(Qt::WA_NoSystemBackground, true);
setAutoFillBackground(false);
_viewer = make_shared<viewer>(math::vec2ui(100, 100), parent->winId(), view_attrib, ctx_attrib, win_fmt);
// ok set the native window as this widgets window...and hold thumbs
QWidget::create(_viewer->window()->window_handle(), true, true);
}
The viewer creates a native Win32 (or X11) window wit the parent of the QWidget as a parent. It also creates and initializes an OpenGL context. This was/is done for more control over the context creation and live time (I know that Qt5 is much improved in that regard). The QWidget::create() method now takes the HWND of the native window and embeds it into the current QWidget, so that event handling is completely done through Qt.
This works perfectly on Qt4 (latest used is Qt 4.8.6 x64 on Windows 7/8.1 x64 on Visual Studio 2013).
Now when porting to Qt5 the same code should still work according to the Qt5 documentation. It required minor changes to account for the change in the WId type. The QWidget::winId() methods still return the native HWND handles of the widgets, which I verified using spyxx.exe (Visual Studio Tools).
However, the code does not work anymore (using Qt 5.4.0 x64 on Windows 7/8.1 x64 on Visual Studio 2013). The native window is just not embedded. In Qt4 when inspecting the created QWidget its native handle (winId) after the create call was identical to the native HWND, which meant the embedding worked. Now using Qt5 the QWidget contains its own HWND which I could again confirm using spyxx.exe. Now there is the parent widget/window and two child widgets/windows where there should only be one child (the native one). I looked at the source code of the create() method for both Qt versions and I do not understand why it is not working anymore.
Ok, after the first night trying to figure this out I tried several other methods I could find on forums or the documentation:
QWindow::fromWinId(HWND) and QWidget::createWindowContainer(QWindow): This one seems to be the way Qt-Devs want me to do it:
_viewer = make_shared<viewer>(math::vec2ui(100, 100), par_hndl, view_attrib, ctx_attrib, win_fmt);
QWindow* native_wnd = QWindow::fromWinId((WId)_viewer->window()->window_handle());
QWidget* native_wdgt = QWidget::createWindowContainer(native_wnd);
QHBoxLayout* lo = new QHBoxLayout(this);
lo->setContentsMargins(0, 0, 0, 0);
lo->addWidget(native_wdgt);
This at least at least behaves almost the way I expect. I see my window and in the newly created widget the native window is embedded. BUT: I have found no way to get any mouse events/input from that newly created widget. I added an eventFilter without luck. I tried a QStackedLayout with a transparent top-level widget to catch the input, but this does not work as the widget created through createWindowContainer() is always on top of the windows stack. I tries creating a QWindow-derived class to intercept the nativeEvent() invocation, without luck...
I am at the end of my ideas to get this working as with Qt4. Is there anything I can to differently to get the old behavior back? The keyboard input I can track through the parent widget using a Qt::StrongFocus policy but the mouse input in complete swallows by the native window. I cannot move the the Qt5 OpenGL window code and need to use our custom OpenGL context tools as we are doing things with the contexts that Qt5 still does not fully support.
I could not yet try Qt5 on Linux, but the Qt4 code as seen above did work there.
I have largely solved communication from Qt to the window by subclassing QWidget, using create() as you originally did, and reimplementing the QWidget event functions to make changes to the native window directly. The ones I've found so far (the big ones) are the focus events, resizeEvent, moveEvent, and the contents rect and enable changeEvents. Font, palette, tooltip, etc. changeEvents are probably a lower priority.
The above won't solve the reverse issue, that messages from the native window never arrive in Qt's event dispatcher. You will need to post messages from your WndProc to the widget's HWND (i.e., the return from calling winId()). This also nearly steps around trying to translate virtual key codes to Qt::Keys and back.
Some notes about why this doesn't work gracefully, as it did in Qt4:
QWindow only works on X11 with native child widgets right now. Try testing on Linux as you mentioned.
QWidget::create() and QWindow have been problems since 5.1 at the least. The problems you're having in both implementations seem to fit.
Here is a consolidated bug report about QWindow intended usage and issues
Other notes:
QWidget::effectiveWinId() is preferred even though you are creating an immediate child window. This, unfortunately, breaks in 5.4.1.
Update to 5.4.1. There are binary compatibility issues with 5.4.0 and all other versions of Qt5.
Qt is cross platform c++ Gui Library.Code once and compile for different Platform. Let's for instance, I have compiled a Project(decent text editor with few tool bar) or any such program for Windows(x86).
Statement 1: The Program.exe entry point will be WinMain.
Statement 2: The Text editor and tool bar will created using "CreateWindow" win32 api. Qt have its own class to implement but to ask OS(Windows) for creating a tool bar or text editor, Program exe interface with OS(Windows). OS understand what it know it does not know anything about Qt class,so to create tool bar or text editor program have to use win32 api.
Statement 3: All event processing( button click, mouse click) will handles using windows messeging system.
Note: It may seem i am viewing every thing with win32 api glass on my understanding.
Correct. The WinMain implementation is provided by the Qt library.
Half correct. The top-level windows are created using CreateWindow. Child widgets, such as a non-toplevel toolbar are Qt's own widgets and are opaque outside of your application. They are exposed only via the accessibility APIs. This allows you to create more widgets than Windows would be able to deal with. A million child widgets is doable, if not particularly fast.
Correct - there's no other way. Of course Qt immediately translates native messages into QEvent instances and dispatches them internally to various QObject instances. In Qt-land, all events must be received by a QObject instance.
You're incorrect in your assertion that winapi has anything to do with the kernel. Winapi is implemented by a bunch of user-space DLLs. You could implement those DLLs yourself. Those DLLs themselves call into the kernel using the native api. That's the API actually exposed by the kernel to the user space.
I'm currently working on a project that uses Allegro for rendering, input, etc. However I would like to add a GUI to my project using something like Qt. The problem is that Allegro does not support using a Window not created by allegro for rendering/input, it needs to create the window itself. I was thinking of using Qt to make the UI, and then creating a window normally using allegro, and then somehow embedding the allegro window into the Qt application.
Allegro provides the HWND handle to the window its using. Is there anyway to embed the allegro window into a Qt ui using its HWND handle?
You need the QWinHost class from the Qt/MFC Migration Framework. The code is 3-clause BSD licensed. You only need two files: qwinhost.h and qwinhost.cpp, available here.
It does exactly what you need, and works on both Qt 4 and 5.
Can you dock a child window control in C++ win32 API (like are there WS_* styles or something), or do you always have to listen for the WM_SIZE message on the parent window and manually re-layout/fill all the children?
There is nothing directly available in the WinAPI that will automate this, it's generally implemented by framework wrappers (like MFC...). However, there are a few libraries (such as this one) that you could use as an alternative to implementing it from scratch.