Skip to content
  • 0 Votes
    2 Posts
    372 Views
    bibasmallB

    I have found out that this problem is mainly related to WinAPI + framelessness, not to Qt. I didn't manage to find any working WinAPI solution, for example, I've tried this one: melak47's solution. So I've chosen Qt way. This approach is not as concise as I expected from the WinAPI approach, but it works.
    Here is a code snippet describing only the necessary parts.

    .hpp

    class FramelessWindow : public QQuickWindow { Q_OBJECT QML_ELEMENT Q_PROPERTY(bool isMaximized READ isMaximized NOTIFY isMaximizedChanged) signals: void isMaximizedChanged(); public: FramelessWindow() noexcept; Q_INVOKABLE void showNormal() noexcept; Q_INVOKABLE void showMaximized() noexcept; bool isMaximized() const noexcept; private: bool eventFilter(QObject* watched, QEvent* event) override; bool nativeEvent(const QByteArray& eventType, void* message, qintptr* result) override; QRect restoredGeometry_; bool isMaximized_; };

    .cpp

    FramelessWindow::FramelessWindow() noexcept : isMaximized_ { false } { setFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint | Qt::WindowMaximizeButtonHint); installEventFilter(this); SetWindowLongPtr((HWND)winId(), GWL_STYLE, WS_POPUP | WS_THICKFRAME | WS_CAPTION | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX); } void FramelessWindow::showNormal() noexcept { setGeometry(restoredGeometry_); isMaximized_ = false; emit isMaximizedChanged(); } void FramelessWindow::showMaximized() noexcept { restoredGeometry_ = geometry(); setGeometry(screen()->availableGeometry()); isMaximized_ = true; emit isMaximizedChanged(); } bool FramelessWindow::isMaximized() const noexcept { return isMaximized_; } bool FramelessWindow::eventFilter(QObject* watched, QEvent* event) { QPoint cursorPos = QCursor::pos(); qreal dpr = devicePixelRatio(); QRect draggingArea = geometry(); draggingArea.setHeight(32 * dpr); draggingArea.setY(draggingArea.y() + dpr * ResizeBorderWidth); if (draggingArea.contains(cursorPos)) { if (event->type() == QEvent::MouseButtonPress) { if (isMaximized_) { restoredGeometry_.moveTo({ QCursor::pos().x() - restoredGeometry_.width() / 2, QCursor::pos().y() - 10 }); showNormal(); } startSystemMove(); return true; } else if (isResizable_ && event->type() == QEvent::MouseButtonDblClick) { if (draggingArea.contains(cursorPos)) { if (isMaximized_) { showNormal(); } else { showMaximized(); } return true; } } else if (event->type() == QEvent::WindowStateChange && QWindow::visibility() == QWindow::Maximized) { setGeometry(screen()->availableGeometry()); isMaximized_ = true; emit isMaximizedChanged(); return true; } } return QQuickWindow::eventFilter(watched, event); } bool FramelessWindow::nativeEvent(const QByteArray& eventType, void* message, qintptr* result) { if (auto* msg = static_cast<MSG*>(message); msg->message == WM_NCCALCSIZE) { NCCALCSIZE_PARAMS& params = *reinterpret_cast<NCCALCSIZE_PARAMS*>(msg->lParam); if (params.rgrc[0].top != 0) { --params.rgrc[0].top; } *result = 0; return true; } return QQuickWindow::nativeEvent(eventType, message, result); }
  • 0 Votes
    3 Posts
    319 Views
    K

    @Christian-Ehrlicher Thank you for your answer.

  • 0 Votes
    17 Posts
    2k Views
    W

    Looks like using the QProcess::stateChanged signal (and removing terminate()) works.
    It uses QThread::msleep() so its not ideal, but its fine for me.

    HWND myHWND; static BOOL CALLBACK enumWindowCallback(HWND hWnd, LPARAM lparam) { DWORD pid; GetWindowThreadProcessId(hWnd, &pid); if (pid == lparam) { myHWND = hWnd; return FALSE; } return TRUE; } ProgramStarter::ProgramStarter(QObject *parent) : QObject{parent} { QProcess *qpr = new QProcess(this); connect(qpr, &QProcess::stateChanged, this, [=](QProcess::ProcessState newState){ if (newState == QProcess::Running) { QThread::msleep(250); EnumWindows(enumWindowCallback, qpr->processId()); } }); QString executable = "C:\\path\\to\\program.exe"; qpr->start(executable); qDebug() << myHWND; }
  • 0 Votes
    4 Posts
    731 Views
    EmrecpE

    @SGaist
    removing self.parent = parent did not help. Problem still continues.

  • 0 Votes
    1 Posts
    276 Views
    No one has replied
  • 0 Votes
    12 Posts
    4k Views
    P

    @SGaist said in Win32 static linking?:

    Qt Creator architecture has nothing to do with the architecture of your application.

    To build a 32bit version of your application, use the 32bit package for MSVC2017. The same goes for the 64bit version.

    Yeah, that worked. When I tried it in 5.12.0 and failed, there must have been something misconfigured.

    I currently don't know for the static version, however when building the dynamic version you can say to configure that it should build dynamic backend selection.

    Following some info from another post, I tried the following configure.bat options:

    -prefix "C:\Qt\Qt5.12.2\5.12.2\msvc2017sr" -release -platform win32-msvc -confirm-license -opensource -nomake examples -nomake tests -static -static-runtime -opengl dynamic -angle -combined-angle-lib -no-feature-d3d12

    Now it works on the 32-bit Windows machine I used to build Qt and the application (and still works fine on the 64-bit machine I can also build it on), but when I run it on another Win7 64-bit machine that has never had Qt installed on it, I just get the window frame again. Is it looking for a DLL? I only have a nebulous idea of what some of those configure options actually mean, so I don't know what to try next.

  • 0 Votes
    15 Posts
    2k Views
    Y

    @SGaist Thank you inform about me QtSingleApplication class. I will modify code and use QtSingleApplication.

  • 0 Votes
    4 Posts
    1k Views
    jsulmJ

    @newbieQTDev said in Use a QDialog box in Win32 Application:

    This is the version of my QT.

    No this is the Qt version which was used to build QtCreator (which is a Qt app).
    You're using Qt 5.6.0

  • 0 Votes
    1 Posts
    1k Views
    No one has replied
  • 0 Votes
    2 Posts
    5k Views
    Gustavo Ribeiro CroscatoG

    I found a solution. In case anyone has the same problem just add the following to you CMakeLists.txt:

    if(WIN32) set(GUI_TYPE WIN32) elseif(APPLE) set(GUI_TYPE MACOSX_BUNDLE) endif()

    then add

    ${GUI_TYPE}

    to your target.

    My CMakeLists.txt is now

    project(Win32App) cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) if(WIN32) set(GUI_TYPE WIN32) elseif(APPLE) set(GUI_TYPE MACOSX_BUNDLE) endif() set(SRC main.cpp ) set(HDR) set(RES) add_definitions(-DWIN32 -D_WINDOWS -D_UNICODE -DUNICODE) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:WINDOWS,5.01") add_custom_target(${PROJECT_NAME}_HEADERS SOURCES ${HDR}) add_executable(${CMAKE_PROJECT_NAME} ${GUI_TYPE} ${SRC} ${RES})
  • 0 Votes
    2 Posts
    2k Views
    SGaistS

    Hi and welcome to devnet,

    Do you have by any change QT_FATAL_WARNINGS defined ?

    If not, can you try the same thing with the 5.6 beta ?

  • 0 Votes
    12 Posts
    8k Views
    Karen MorrisseyK

    @SGaist Oh, I see where to do that. Thanks. I think that last part makes for a solution.

  • 0 Votes
    4 Posts
    2k Views
    N

    As soon as paths or library names differ, you will have to use scoped declarations. Otherwise it really does not matter. Win32 also links correctly using -lSomeCoolLib, therefor you could just use one LIBS directive.

  • 0 Votes
    5 Posts
    4k Views
    F

    This thread is 4 years old, but I want to give a solution anyway.
    I spent the past 2 months trying to figure out how to do this, and all the threads I found are talking about issues but nobody gave me a solution.

    Actually, the QWidget you create has its own focus but is not "parent" of the HWND you are embedding on it, so you have to make the keyboard focus by yourself.

    The best way to do that is by using the SetFocus function of the winuser library (WinUser.h):
    https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-setfocus

    Like, in example:

    m_qwindow = QWindow::fromWinId(m_handle); m_widget = QWidget::createWindowContainer(m_qwindow, this); // tell the os to focus the viewport window SetFocus(m_handle);

    with m_handle being the HWND (or WId) used to create the QWindow.

    Unfortunately, this solution works only on windows (but maybe there are equivalents on another os).
    It also doesn't work when clicking on the embedded window, because it isn't owned by Qt.
    maybe you can try to mess with QFocusFrame (I haven't tried this at all, but it should be a way to use it as a fix by putting it over the embedded window)
    or, if the window you are embedding is one of your creations, put the SetFocus() function in its code, as a callback when clicked.

    I hope that even with 4 years late, this solution is still helping the desperate developers like who I was the past two months.

  • 0 Votes
    1 Posts
    533 Views
    No one has replied
  • 0 Votes
    11 Posts
    5k Views
    S

    @koahnig
    it is out of subject on this forum, but I tested with the win32 function Shellexecute and "runas" as second parameter instead of qprocess and it created my service.so I mark this subject solved.thanks.

  • 0 Votes
    2 Posts
    2k Views
    R

    This function is only for desktop applications. It may not exist for embedded systems.

    I would check if the function exist before doing anything else. If you list the exported functions from USER32 and don't see it then this explains the linker error.

  • 0 Votes
    1 Posts
    1k Views
    No one has replied