FramelessHelper

repository·main·Indexed 21 days ago

https://github.com/wangwenx190/framelesshelper

A deprecated cross-platform framework for customizing Qt Widgets and Qt Quick windows by removing standard title bars and providing custom, frameless UI implementations. Supports Windows, Linux, and macOS. Requires C++17 and Qt 5.6+, with active testing on Qt 5.15 and Qt 6. The author recommends using QWindowKit for new projects.

Tokens
4K
Snippets
8
Records
16
Agent score
25%

What's inside FramelessHelper

  1. Supported Platforms and Limitations

    main

    FramelessHelper is a cross-platform framework for Qt Widgets and Qt Quick. Supported platforms include:

    • Windows: Windows Vista through Windows 11 (Windows 10 & 11 are the only versions actively tested).
    • Linux: Any modern Linux distribution (tested on Ubuntu 20.04 and 22.04).
    • macOS: Tested on macOS 12 & 13.

    Note: Specific platform restrictions apply; refer to the Platform notes section in the full documentation for details.

  2. Handle missing top borders on Windows

    main

    FramelessHelper removes the entire system title bar, which includes the top border. If you need a top border, you must draw it manually.

    To make your custom border match the system appearance, you can retrieve the border height and color using official DWM APIs: DwmGetWindowAttribute() and DwmGetColorizationColor().

    Note: If you use FramelessWidget or FramelessMainWindow (for Widgets) or the FramelessWindow QML type (for Qt Quick), the library draws the top border for you automatically.

  3. How FramelessHelper works in QML

    main

    In Qt Quick, FramelessHelper can be used as both an attached property and a standalone QML type.

    Regardless of how it is used, the FramelessHelper type is designed to be a singleton per Window. Even if you instantiate multiple FramelessHelper objects for the same Window, only one will remain functional; the others will act as wrappers for the primary instance. To avoid unexpected behavior or bugs, it is recommended to use only one instance per window.

    If FramelessHelper functions appear to have no effect, it is likely because the root window has not finished its initialization process. The helper cannot find the window handle until initialization is complete.

  4. How FramelessWidgetsHelper and FramelessWindow work

    main

    In the Qt Widgets API, FramelessWidget and FramelessMainWindow are provided as simple convenience wrappers around FramelessWidgetsHelper.

    They primarily automate the call to extendsContentIntoTitleBar(). While these wrappers are available, you can achieve the exact same functionality using a standard QWidget or QMainWindow by manually interacting with FramelessWidgetsHelper::get(this).

  5. Build and Install FramelessHelper

    main

    To build FramelessHelper, clone the repository recursively to include submodules, then use CMake with Ninja. You must specify your Qt SDK path and an installation directory.

    Important Note: This repository is deprecated. The author recommends using QWindowKit instead.

    Submodule Troubleshooting: If submodules fail to clone, run git submodule update --init --recursive --remote in the project directory. You may need to run this multiple times if it fails.

    git clone --recursive https://github.com/wangwenx190/framelesshelper.git
    mkdir build
    cd build
    cmake -DCMAKE_PREFIX_PATH=<YOUR_QT_SDK_DIR_PATH> -DCMAKE_INSTALL_PREFIX=<WHERE_YOU_WANT_TO_INSTALL> -DCMAKE_BUILD_TYPE=Release -GNinja <PATH_TO_THE_REPOSITORY>
    cmake --build . --config Release --target all --parallel
    cmake --install . --config Release --strip
  6. Enable Windows 11 Snap Layouts

    main

    To enable the Windows 11 snap layout feature in your application using FramelessHelper, you must perform two steps:

    1. Update Application Manifest: Add a manifest file to your application and explicitly claim that your application supports Windows 11. This is required for the snap layout feature to be enabled.
    2. Register System Buttons: Call setSystemButton() for each of your custom buttons (which can be any QWidget or QQuickItem) to identify them as the minimize, maximize, or close buttons.
    // Example concept (pseudo-code):
    // 1. Ensure your .manifest file includes Windows 11 support
    // 2. Register buttons
    setSystemButton(myMinimizeButton);
    setSystemButton(myMaximizeButton);
    setSystemButton(myCloseButton);
  7. Configure CMake with Qt paths

    main

    When running CMake for FramelessHelper, you can specify the Qt SDK directory using CMAKE_PREFIX_PATH. Alternatively, you can point directly to the specific Qt version's CMake directory using Qt6_DIR or Qt5_DIR.

    # Using CMAKE_PREFIX_PATH
    cmake -DCMAKE_PREFIX_PATH=C:/Qt/6.5.1/msvc2019_64 ...
    
    # Using Qt6_DIR
    cmake -DQt6_DIR=C:/Qt/6.5.1/msvc2019_64/lib/cmake/Qt6 [other parameters ...]
    
    # Using Qt5_DIR
    cmake -DQt5_DIR=C:/Qt/5.15.2/msvc2019_64/lib/cmake/Qt5 [other parameters ...]
  8. System Requirements for FramelessHelper

    main

    To use FramelessHelper, ensure your environment meets the following requirements:

    Compiler

    A modern compiler supporting at least C++17. Tested on:

    • Windows: MSVC 2022
    • Linux: GCC 11
    • macOS: Clang 13

    Qt Version

    • Minimum: Qt 5.6
    • Recommended: The latest stable version of Qt.
    • Actively Tested: Qt 5.15 and Qt 6.
    • Note: Using older versions (pre-5.12) may result in missing features.

    Qt Modules

    • Core Module: QtCore, QtGui
    • Widgets Module: QtWidgets
    • Quick Module: QtQuick, QtQuickControls2, QtQuickTemplates2

    Build Tools

    • CMake & Ninja: Newer versions are recommended. Other build systems are not officially tested.
  9. Setup and use FramelessHelper with Qt Widgets

    main

    To remove the OS window frame from a QWidget, use the FramelessWidgetsHelper class.

    1. Initialization

    You MUST call FramelessHelper::Widgets::initialize() in your main function before any QApplication or QGuiApplication objects are constructed.

    2. Applying Frameless Mode

    Use the static method FramelessWidgetsHelper::get(QObject *) to obtain a helper instance for your widget. This method is safe to call multiple times; it returns the existing instance if one is already attached to that widget's top-level window.

    To hide the default OS title bar, call extendsContentIntoTitleBar() on the helper instance. It is recommended to do this early in the widget's lifecycle.

    3. Custom Title Bar and Hit Testing

    • Draggability: To make the window draggable, provide a custom widget and register it using setTitleBarWidget(QWidget *).
    • Interactivity: By default, FramelessHelper intercepts mouse and keyboard events in the title bar area. To allow specific widgets (like buttons or search boxes) inside your custom title bar to receive events, you must call setHitTestVisible(QWidget *) for each of those widgets.

    4. Lifecycle and Safety

    • Parenting: The helper objects are automatically parented to the top-level widget.
    • Memory Management: Do not manually delete the FramelessWidgetsHelper object. Qt will handle its deletion automatically.
    • Initialization Timing: If you need to perform operations that depend on the window being fully customized (like changing geometry or flags), connect to the ready() signal of the FramelessWidgetsHelper instance.
    // 1. Initialize in main
    int main(int, char **)
    {
        FramelessHelper::Widgets::initialize();
        // ...
    }
    
    // 2. Apply to widget
    MyWidget::MyWidget(QWidget *parent) : QWidget(parent)
    {
        FramelessWidgetsHelper::get(this)->extendsContentIntoTitleBar();
    }
    
    // 3. Set custom title bar
    void MyWidget::myFunction()
    {
        FramelessWidgetsHelper::get(this)->setTitleBarWidget(m_myTitleBarWidget);
    }
    
    // 4. Enable interaction for specific widgets
    void MyWidget::myFunction2()
    {
        FramelessWidgetsHelper::get(this)->setHitTestVisible(m_someSearchBox);
        FramelessWidgetsHelper::get(this)->setHitTestVisible(m_someButton);
    }
  10. Integrate FramelessHelper into a CMake project

    main

    To use FramelessHelper in your own project, use find_package to locate the library. You must ensure CMake knows where FramelessHelper is installed by providing CMAKE_PREFIX_PATH or FramelessHelper_DIR to your project's configuration command.

    Supported target names:

    • FramelessHelper::Core
    • FramelessHelper::Widgets
    • FramelessHelper::Quick
    # Find Qt:
    find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets)
    find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets)
    
    # Find FramelessHelper:
    find_package(FramelessHelper REQUIRED COMPONENTS Core Widgets)
    
    # Create your target:
    add_executable(demo)
    
    # Add your source code:
    target_sources(demo PRIVATE main.cpp)
    
    # Link to Qt and FramelessHelper:
    target_link_libraries(demo PRIVATE
        Qt${QT_VERSION_MAJOR}::Widgets
        FramelessHelper::Core
        FramelessHelper::Widgets
    )
  11. Configure QML syntax highlighting for FramelessHelper Quick module

    main

    To enable syntax highlighting and QML tooling in Qt Creator for the FramelessHelper Quick module, you must add the path containing the Quick plugin to your QML_IMPORT_PATH. This plugin contains the QML meta-information required by the IDE.

    # Set the path where FramelessHelper's Quick plugin is located
    set(FRAMELESSHELPER_IMPORT_DIR "C:/packages/FramelessHelper/qml")
    list(APPEND QML_IMPORT_PATH "${FRAMELESSHELPER_IMPORT_DIR}")
    list(REMOVE_DUPLICATES QML_IMPORT_PATH)
    
    # Force cache refresh for Qt Creator
    set(QML_IMPORT_PATH ${QML_IMPORT_PATH} CACHE STRING "Qt Creator extra QML import paths" FORCE)