
กรอบการปรับแต่งหน้าต่างข้ามแพลตฟอร์มสำหรับวิดเจ็ต QT และ QT Quick รองรับ Windows, Linux และ MacOS
คุณสามารถเข้าร่วมช่อง Discord ของเราเพื่อสื่อสารกับเรา คุณสามารถแบ่งปันสิ่งที่ค้นพบความคิดและแนวคิดเกี่ยวกับการปรับปรุง / ใช้งานฟังก์ชัน framelessHelper บนแพลตฟอร์มและแอพเพิ่มเติม!
FramelessDialog คุณสามารถใช้มันได้ในกรณีที่ QDialog เป็นที่ต้องการมากกว่า QWidget ทั่วไปWindowBorderPainter ที่เพิ่งเปิดตัวใหม่และยังเปิดเผยต่อสาธารณะดังนั้นคุณจะสามารถเปลี่ยนวิธีการวาดเส้นขอบหน้าต่างได้อย่างง่ายดายWindowBorder มันเป็นมัณฑนากรชายแดนหน้าต่างข้ามแพลตฟอร์มและสามารถทำงานได้โดยไม่ต้องใช้องค์ประกอบ FramelessHelperFramelessApplicationWindow มันเป็น wrapper ง่าย ๆ ขององค์ประกอบ ApplicationWindow มาตรฐานเพียงแค่ลบแถบชื่อเรื่องและเพิ่มเส้นขอบหน้าต่างfind_package เพื่อค้นหา framelesshelper






Vogen Editor โดยใช้กรอบ Qsynthesis URL ที่เก็บข้อมูล: https://gitee.com/functioner/qvogenclient
มีข้อ จำกัด เพิ่มเติมบางอย่างสำหรับแต่ละแพลตฟอร์มโปรดดูส่วน บันทึกแพลตฟอร์ม ด้านล่าง
git clone --recursive https://github.com/wangwenx190/framelesshelper.git # "--recursive" is necessary to clone the submodules.
mkdir build # Please change to your own build directory!
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 # Don't add "--strip" for MSVC/Clang-CL/Intel-CL toolchains!
# YOUR_QT_SDK_DIR_PATH: the Qt SDK directory, something like "C:/Qt/6.5.1/msvc2019_64" or "/opt/Qt/6.5.1/gcc_64". Please change to your own path!
# WHERE_YOU_WANT_TO_INSTALL: the install directory of FramelessHelper, something like "../install". You can ignore this setting if you don't need to install the CMake package. Please change to your own path!
# PATH_TO_THE_REPOSITORY: the source code directory of FramelessHelper, something like "../framelesshelper". Please change to your own path! นอกจากนี้คุณยังสามารถใช้ Qt6_DIR หรือ Qt5_DIR เพื่อแทนที่ CMAKE_PREFIX_PATH :
cmake -DQt6_DIR=C:/Qt/6.5.1/msvc2019_64/lib/cmake/Qt6 [other parameters ...]
# Or
cmake -DQt5_DIR=C:/Qt/5.15.2/msvc2019_64/lib/cmake/Qt5 [other parameters ...] หากมีข้อผิดพลาดใด ๆ เมื่อโคลน submodules ลองเรียกใช้ git submodule update --init --recursive --remote ในไดเรกทอรีโครงการคำสั่งนั้นจะดาวน์โหลดและอัปเดต submodules ทั้งหมด หากล้มเหลวอีกครั้งลองดำเนินการหลายครั้งจนกว่าจะประสบความสำเร็จในที่สุด
เมื่อการรวบรวมและการติดตั้งเสร็จสิ้นคุณจะสามารถใช้คำสั่ง find_package(FramelessHelper REQUIRED COMPONENTS Core Widgets Quick) เพื่อค้นหาและเชื่อมโยงไปยังไลบรารี framelesshelper แต่ก่อนที่จะทำเช่นนั้นโปรดตรวจสอบให้แน่ใจว่า cmake รู้ว่าจะหา framelesshelper ได้ที่ไหนโดยผ่านตัวแปร CMAKE_PREFIX_PATH หรือ FramelessHelper_DIR ตัวอย่างเช่น: -DCMAKE_PREFIX_PATH=C:/my-cmake-packages;C:/my-toolchain;etc... หรือ -DFramelessHelper_DIR=C:/Projects/FramelessHelper/lib64/cmake/FramelessHelper สร้าง FramelessHelper เป็นไดเรกทอรีย่อยของโครงการ CMake ของคุณได้รับการสนับสนุนแน่นอน ชื่อเป้าหมาย FramelessHelper ที่รองรับคือ 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
) หากคุณต้องการไวยากรณ์ที่เน้นโมดูลด่วนของ FramelessHelper โปรดตั้งค่าตัวแปร QML_IMPORT_PATH รหัสตัวอย่าง:
# This is the path where you want FramelessHelper's Quick plugin (it only contains the QML meta
# info and an optional dummy library, for QtCreator's QML tooling purpose, it's not the Quick
# module) to place. Please change to your own path!
# If you are using add_subdirectory() to include FramelessHelper directly, you can change it to
# "${PROJECT_BINARY_DIR}/imports" instead of the install location.
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:
set (QML_IMPORT_PATH ${QML_IMPORT_PATH} CACHE STRING "Qt Creator extra QML import paths" FORCE) ในการปรับแต่งเฟรมหน้าต่างของ QWidget คุณจะต้องทำอินสแตนซ์วัตถุ FramelessWidgetsHelper จากนั้นแนบกับวิดเจ็ตระดับบนสุดของวิดเจ็ตจากนั้น FramelessWidgetsHelper จะทำงานทั้งหมดที่เหลือสำหรับคุณ: เฟรมหน้าต่างจะถูกลบออกโดยอัตโนมัติ ในทางทฤษฎีคุณสามารถยกตัวอย่างวัตถุ FramelessWidgetsHelper หลายตัวสำหรับวิดเจ็ตเดียวกันในกรณีนี้จะมีวัตถุเพียงชิ้นเดียวที่ทำให้การทำงานมีการทำงานวัตถุอื่น ๆ ทั้งหมดจะกลายเป็นห่อหุ้มของหนึ่งนั้น แต่เพื่อให้แน่ใจว่าทุกอย่างเป็นไปอย่างราบรื่นและตามปกติคุณไม่ควรทำเช่นนั้นในทุกกรณี วิธีที่ง่ายที่สุดในการสร้างอินสแตนซ์วัตถุ FramelessWidgetsHelper คือการเรียกวิธีการคงที่ FramelessWidgetsHelper *FramelessWidgetsHelper::get(QObject *) มันจะส่งคืนด้ามจับของวัตถุที่มีการสร้างอินสแตนซ์ก่อนหน้านี้หรือจะสร้างอินสแตนซ์วัตถุใหม่หากไม่พบ ปลอดภัยที่จะเรียกใช้วิธีนี้หลายครั้งสำหรับวิดเจ็ตเดียวกันมันจะไม่สร้างอินสแตนซ์วัตถุใหม่ใด ๆ หากมีอยู่แล้ว นอกจากนี้ยังไม่สำคัญว่าคุณจะเรียกฟังก์ชั่นนั้นเมื่อใดและที่ไหนตราบใดที่วิดเจ็ตระดับบนสุดเหมือนกัน วัตถุที่สร้างขึ้นภายในจะถูก parented กับวิดเจ็ตระดับบนสุดเสมอ เมื่อคุณได้รับที่จับของวัตถุ FramelessWidgetsHelper คุณสามารถเรียก void FramelessWidgetsHelper::extendsContentIntoTitleBar() เพื่อให้มันซ่อนแถบชื่อเรื่องเริ่มต้นที่จัดทำโดยระบบปฏิบัติการ เพื่อให้แน่ใจว่า FramelessWidgetsHelper สามารถค้นหาวิดเจ็ตระดับบนสุดที่ถูกต้องคุณควรโทรหา FramelessWidgetsHelper *FramelessWidgetsHelper::get(QObject *) ฟังก์ชั่นบนวิดเจ็ตที่มีสายหลักที่สมบูรณ์ ในการทำให้หน้าต่างไร้กรอบพุ่งออกมาได้คุณควรจัดหาวิดเจ็ตบาร์ชื่อโฮมเมดด้วยตัวคุณเองวิดเจ็ตชื่อบาร์ชื่อไม่จำเป็นต้องอยู่ในรูปสี่เหลี่ยมผืนผ้ามันไม่จำเป็นต้องวางไว้ในแถวแรกของหน้าต่าง เรียก void FramelessWidgetsHelper::setTitleBarWidget(QWidget *) เพื่อให้ FramelessHelper รู้ว่าวิดเจ็ตบาร์ชื่อของคุณคืออะไร โดยค่าเริ่มต้นวิดเจ็ตทั้งหมดในพื้นที่แถบชื่อเรื่องจะไม่รับผิดชอบต่อเหตุการณ์เมาส์และคีย์บอร์ดใด ๆ เนื่องจากพวกเขาได้รับการสกัดกั้นโดย FramelessHelper เพื่อให้พวกเขากู้คืนสถานะที่รับผิดชอบคุณควรทำให้พวกเขามองเห็นการทดสอบ เรียก void FramelessWidgetsHelper::setHitTestVisible(QWidget* ) เพื่อทำเช่นนั้น แน่นอนว่าคุณสามารถเรียกมันบนวิดเจ็ตที่ไม่ได้อยู่ในแถบชื่อเรื่องเลยมันจะไม่มีผลกระทบใด ๆ เนื่องจากข้อ จำกัด ของ QT คุณต้องตรวจสอบให้แน่ใจว่าวิดเจ็ตของคุณมีโซ่หลักที่สมบูรณ์ซึ่งผู้ปกครองรูทเป็นวิดเจ็ตระดับบนสุด อย่าพยายามลบวัตถุ FramelessWidgetsHelper มันอาจยังคงตรวจสอบและควบคุมวิดเจ็ตของคุณและ QT จะลบออกสำหรับคุณโดยอัตโนมัติ ไม่จำเป็นต้องกังวลเกี่ยวกับการรั่วไหลของหน่วยความจำ
นอกจากนี้ยังมีสองคลาสที่เรียกว่า FramelessWidget และ FramelessMainWindow พวกเขาเป็นเพียง wrappers ง่าย ๆ ของ FramelessWidgetsHelper ซึ่งเพียงบันทึกการเรียกของฟัง void FramelessWidgetsHelper::extendsContentIntoTitleBar() สำหรับคุณ คุณสามารถใช้ QWidget ธรรมดาได้อย่างแน่นอน
ก่อนอื่นให้โทร void FramelessHelper::Widgets::initialize() ในฟังก์ชั่น main ของคุณในระยะแรก ( ต้อง ก่อนการสร้างวัตถุ Q(Gui|Core)Application )::
int main ( int , char **)
{
FramelessHelper::Widgets::initialize ();
// ...
}จากนั้นซ่อนแถบชื่อเรื่องมาตรฐานที่ OS ให้บริการ:
MyWidget::MyWidget (QWidget *parent) : QWidget(parent)
{
// You should do this early enough.
FramelessWidgetsHelper::get ( this )-> extendsContentIntoTitleBar ();
// ...
} จากนั้นให้ FramelessHelper รู้ว่าควรเป็นแถบชื่อเรื่องอะไร:
void MyWidget::myFunction ()
{
// ...
FramelessWidgetsHelper::get ( this )-> setTitleBarWidget (m_myTitleBarWidget);
// ...
}จากนั้นสร้างวิดเจ็ตบางอย่างในแถบชื่อเรื่องของคุณเพื่อให้สามารถทดสอบได้:
void MyWidget::myFunction2 ()
{
// ...
FramelessWidgetsHelper::get ( this )-> setHitTestVisible (m_someSearchBox);
FramelessWidgetsHelper::get ( this )-> setHitTestVisible (m_someButton);
FramelessWidgetsHelper::get ( this )-> setHitTestVisible (m_someMenuItem);
// ...
} หมายเหตุสำคัญสำหรับแอปพลิเคชันวิดเจ็ต QT : ฟังก์ชันบางอย่างอาจใช้ได้เฉพาะเมื่อ FramelessHelper ได้เสร็จสิ้นกระบวนการปรับแต่งหน้าต่างเช่นการเปลี่ยนรูปทรงเรขาคณิตของหน้าต่าง/ธง/สถานะ ในกรณีนี้คุณสามารถเชื่อมต่อกับ void ready() สัญญาณของ FramelessHelper เพื่อให้ได้จุดเวลาที่แม่นยำและทำกระบวนการเริ่มต้นที่เหลือของคุณในภายหลัง
ก่อนอื่นคุณควรเรียก void FramelessHelper::Quick::initialize() ในฟังก์ชั่น main ของคุณในระยะแรก ( ต้อง ก่อนการสร้างวัตถุ Q(Gui|Core)Application )::
int main ( int , char **)
{
FramelessHelper::Quick::initialize ();
// ...
} จากนั้นคุณต้องลงทะเบียนประเภทที่กำหนดเองที่จัดทำโดย FramelessHelper โดยการโทร void FramelessHelper::Quick::registerTypes(QQmlEngine *) ก่อนที่เครื่องยนต์ QML จะโหลดเอกสาร QML ใด ๆ :
int main ( int , char **)
{
// ...
QQmlApplicationEngine engine;
FramelessHelper::Quick::registerTypes (&engine);
// ...
} ตอนนี้คุณสามารถเขียนเอกสาร QML ของคุณ คุณควรนำเข้า FramelessHelper จาก URI org.wangwenx190.FramelessHelper คุณควรระบุหมายเลขเวอร์ชันทันทีหากคุณใช้ QT5:
import org.wangwenx190.FramelessHelper 1.0 // You can use "auto" or omit the version number in Qt6. จากนั้นคุณสามารถใช้คุณสมบัติที่แนบมาจากประเภท QML FramelessHelper :
Window {
Item {
id : myTitleBar
Item { id : someControl1 }
Item { id : someControl2 }
Item { id : someControl3 }
Component . onCompleted : {
// Don't access FramelessHelper too early, otherwise it may not be able to find the root window!
FramelessHelper . titleBarItem = myTitleBar;
FramelessHelper . setHitTestVisible (someControl1);
FramelessHelper . setHitTestVisible (someControl2);
FramelessHelper . setHitTestVisible (someControl3);
}
}
} มันเหมือนกันกับอินเทอร์เฟซ FramelessWidgetsHelper ประเภท QML FramelessHelper จะถูกสร้างอินสแตนซ์เพียงครั้งเดียวสำหรับแต่ละ Window ไม่ว่าคุณจะใช้คุณสมบัติที่แนบมาเมื่อใดและที่ไหน อย่างไรก็ตามเนื่องจากการออกแบบพิเศษของประเภท FramelessHelper คุณยังสามารถใช้มันเหมือนกับประเภท QML ปกติ:
Window {
Item {
id : myTitleBar
Item { id : someControl1 }
Item { id : someControl2 }
Item { id : someControl3 }
Component . onCompleted : {
framelessHelper . setHitTestVisible (someControl1);
framelessHelper . setHitTestVisible (someControl2);
framelessHelper . setHitTestVisible (someControl3);
}
}
FramelessHelper {
id : framelessHelper
titleBarItem : myTitleBar
}
} ในทางทฤษฎีมันเป็นไปได้ที่จะยกตัวอย่างวัตถุ FramelessHelper หลายตัวสำหรับ Window เดียวกันในกรณีนี้มีเพียงหนึ่งในนั้นเท่านั้นที่จะทำงานได้วัตถุอื่น ๆ ทั้งหมดจะกลายเป็นเสื้อคลุมของมัน แต่ไม่แนะนำให้ทำเช่นนั้นและอาจทำให้เกิดพฤติกรรมหรือข้อบกพร่องที่ไม่คาดคิดดังนั้นโปรดหลีกเลี่ยงการพยายามทำในทุกกรณี
หากคุณพบฟังก์ชั่น FramelessHelper ใด ๆ ไม่มีผลหลังจากการโทรเหตุผลที่เป็นไปได้มากที่สุดคือเวลาที่คุณเรียกฟังก์ชั่น/เปลี่ยนคุณสมบัติของ FramelessHelper หน้าต่างรูทยังไม่เสร็จสิ้นกระบวนการเริ่มต้นและทำให้ FramelessHelper ไม่สามารถจัดการได้ดังนั้นการกระทำใด ๆ จากผู้ใช้
นอกจากนี้ยังมีประเภท QML ที่เรียกว่า FramelessWindow มันเป็นเพียงเสื้อคลุมที่เรียบง่ายของ FramelessHelper คุณสามารถใช้ Window ธรรมดาแทนได้อย่างแน่นอน
หมายเหตุสำคัญสำหรับแอพพลิเคชั่น QT Quick : ฟังก์ชันบางอย่างอาจใช้ได้เฉพาะเมื่อ FramelessHelper เสร็จสิ้นกระบวนการปรับแต่งหน้าต่างเช่นการเปลี่ยนรูปทรงเรขาคณิตของหน้าต่าง/ธง/สถานะ ในกรณีนี้คุณสามารถเชื่อมต่อกับ void ready() สัญญาณของ FramelessHelper เพื่อให้ได้จุดเวลาที่แม่นยำและทำกระบวนการเริ่มต้นที่เหลือของคุณในภายหลัง:
Window {
FramelessHelper . onReady : {
// do something here ...
}
} Window {
FramelessHelper {
onReady : {
// do something here ...
}
}
}โปรดดูโครงการสาธิตเพื่อดูการใช้งานโดยละเอียดเพิ่มเติม: ตัวอย่าง
หากองค์ประกอบ DWM ถูกปิดใช้งานในบางกรณีที่หายากมาก (เป็นไปได้ที่ Windows 7 เท่านั้น) มุมบนซ้ายและมุมบนขวาจะปรากฏในรูปทรงกลม มุมกลมสามารถคืนค่าเป็นสี่เหลี่ยมได้หากคุณเปิดใช้งานองค์ประกอบ DWM อีกครั้ง
มีข้อผิดพลาดของไดรเวอร์ OpenGL ซึ่งจะทำให้หน้าต่างไร้กรอบมีแถบสีดำแปลก ๆ อยู่ด้านบนของแถบชื่อเรื่องโฮมเมดของคุณและยังทำให้การควบคุมในหน้าต่างของคุณเปลี่ยนไปที่มุมล่างขวาสำหรับพิกเซลบางตัว มันเป็นข้อผิดพลาดของไดรเวอร์การ์ดกราฟิกของคุณโดยเฉพาะไดรเวอร์ OpenGL ของคุณไม่ใช่ FramelessHelper มีวิธีแก้ปัญหาบางอย่างจากผู้ใช้ของเรา แต่บางคนอาจไม่ทำงานในทุกเงื่อนไขคุณสามารถเลือกได้จากพวกเขา:
| สารละลาย | หลักการ |
|---|---|
| อัพเกรดไดรเวอร์กราฟิก | ลองใช้ไดรเวอร์ที่ใหม่กว่าซึ่งอาจจัดส่งด้วยการแก้ไข |
| เปลี่ยนธีมระบบเป็น "พื้นฐาน" (ตรงกันข้ามกับ "Windows Aero") | ให้ Windows ใช้การแสดงผลซอฟต์แวร์บริสุทธิ์ |
| หากมีการ์ดกราฟิกหลายใบให้ใช้การ์ดอื่นแทน | ลองใช้ไดรเวอร์อื่นซึ่งอาจไม่มีข้อบกพร่องเช่นนั้นเลย |
| อัพเกรดระบบเป็นอย่างน้อย Windows 11 | Windows 11 ออกแบบระบบ windowing ใหม่เพื่อไม่ให้บั๊กไม่สามารถเรียกใช้อีกต่อไป |
ลบสไตล์ WS_THICKFRAME และ WS_OVERLAPPED ออกจากหน้าต่างและอาจเพิ่มสไตล์ WS_POPUP ในเวลาเดียวกันและอย่าทำอะไรภายในบล็อก WM_NCCALCSIZE (เพียงส่งคืน false โดยตรงหรือลบ/แสดงความคิดเห็นทั้งหมดบล็อก) | พยายามสะท้อนพฤติกรรมของ FramelessWindowHint ของ QT |
ใช้ Qt::FramelessWindowHint แทนที่จะทำเคล็ดลับ WM_NCCALCSIZE | เส้นทางรหัสการเรนเดอร์ของ QT นั้นแตกต่างกันอย่างสิ้นเชิงระหว่างสองโซลูชันนี้ |
| บังคับให้ qt ใช้แบ็กเอนด์มุมแทนเดสก์ท็อป opengl | มุมจะแปลคำสั่ง OpenGL เป็น D3D |
| บังคับให้ QT ใช้การแสดงผลซอฟต์แวร์บริสุทธิ์แทนการแสดงผลผ่าน OpenGL | QT ไม่ได้ใช้ OpenGL เลย |
| บังคับให้ QT ใช้ไลบรารี MESA 3D แทน OpenGL ปกติ | ลองใช้การใช้งาน OpenGL ที่แตกต่างกัน |
| ใช้ direct3d/vulkan/metal แทน opengl | อย่าใช้ buggy opengl |
หากคุณโชคดีพอคนหนึ่งอาจแก้ไขปัญหาให้คุณได้ ถ้าไม่คุณอาจลองใช้โซลูชันหลายอย่างด้วยกัน แต่ฉันไม่สามารถรับประกันได้ว่าปัญหาสามารถแก้ไขได้ 100%
เนื่องจากมี Windows 10 รุ่นย่อยจำนวนมากขอแนะนำให้ใช้ Windows 10 เวอร์ชันล่าสุดอย่างน้อยก็ ไม่แก่กว่า Windows 10 1809 หากคุณพยายามใช้เฟรมเวิร์กนี้ในเวอร์ชัน Windows 10 รุ่นเก่าเช่น 1507 หรือ 1607 อาจมีปัญหาความเข้ากันได้บ้าง รองรับการใช้เฟรมเวิร์กนี้บน Windows 7 แต่ไม่แนะนำ เพื่อให้ได้พฤติกรรมที่มั่นคงที่สุดและรูปลักษณ์ที่ดีที่สุดคุณควรใช้กับ Windows 10 หรือ Windows 11 เวอร์ชันล่าสุด
เพื่อให้เค้าโครงสแน็ปทำงานตามที่คาดไว้มีกฎเพิ่มเติมสำหรับปุ่มระบบโฮมเมดของคุณที่จะปฏิบัติตาม:
setSystemButton() สำหรับแต่ละปุ่ม (อาจเป็น QWIDGET หรือ QQUICKITEM ใด ๆ ) เพื่อให้ FramelessHelper ทราบว่าปุ่มใดที่ลด/ปิด/ปิดสูงสุดWhen running on Win10, it seems the top border is missing? But the demo applications still have it? FramelessHelper ซ่อนแถบชื่อระบบโดยการลบส่วนบนสุดของกรอบหน้าต่างรวมถึงเส้นขอบด้านบน ไม่มีทางที่จะลบแถบชื่อเรื่องระบบเท่านั้น แต่ยังคงรักษาเส้นขอบด้านบนในเวลาเดียวกันแม้กระทั่ง Microsoft ตัวเองก็ไม่สามารถทำได้เช่นกัน เหตุผลที่แน่นอนไม่เป็นที่รู้จักสำหรับนักพัฒนาที่ไม่ใช่ Microsoft และฉันไม่สนใจที่จะขุดลงไปในเวทมนตร์ทั้งหมดที่อยู่เบื้องหลัง ดังนั้นคุณจะต้องวาดตัวเองด้วยตนเองเพื่อแกล้งทำเป็นชายแดนด้านบนยังคงอยู่ที่นั่น คุณสามารถดึงความสูงและสีได้ผ่าน DWM API อย่างเป็นทางการ โปรดดูเอกสารของ DwmGetWindowAttribute() และ DwmGetColorizationColor() แอปพลิเคชั่นสาธิตยังคงมีเส้นขอบด้านบนเนื่องจากหน้าต่างหลักของพวกเขาทั้งหมดได้รับมรดกจาก FramelessWidget หรือ FramelessMainWindow ซึ่งจะวาดเส้นขอบด้านบนสำหรับคุณภายใน สำหรับ QT Quick ประเภท QML FramelessWindow จะวาดเส้นขอบด้านบนด้วย
When running on Wayland, dragging the title bar causes crash? คุณต้องบังคับให้ QT ใช้ XCB QPA เมื่อทำงานบน Wayland ลองตั้งค่าตัวแปรสภาพแวดล้อม QT_QPA_PLATFORM (ตัวพิมพ์เล็ก) เป็น xcb (ตัวพิมพ์เล็ก) ก่อนที่จะอินสแตนซ์แอปพลิเคชัน Q(Gui)Application ใด ๆ หรือเพียงแค่เรียก void FramelessHelper::Widgets/Quick::initialize() ในฟังก์ชั่น main ของคุณฟังก์ชั่นนี้จะดูแลคุณ
I can see the black background during window resizing?ก่อนอื่นมันเป็นปัญหา QT ไม่ได้เกิดจาก FramelessHelper และไม่ควรเป็นไปไม่ได้สำหรับแอปพลิเคชันวิดเจ็ต QT เป็นปัญหาทั่วไปสำหรับแอปพลิเคชัน QT Quick เวลาส่วนใหญ่เกิดจาก D3D11/Vulkan/Metal เพราะพวกเขาไม่ดีในการจัดการกับการดำเนินการปรับขนาดพื้นผิว หากคุณต้องการแก้ไขปัญหานี้คุณสามารถลองเปลี่ยนแบ็กเอนด์ RHI ของ QT เป็น OpenGL (ระวังข้อบกพร่องของไดรเวอร์การ์ดกราฟิกของคุณ) หรือ ซอฟต์แวร์ (ถ้าคุณไม่สนใจประสิทธิภาพ) และโปรดทราบว่าปัญหานี้ไม่สามารถแก้ไขได้จากภายนอก QT
Can I preserve the window frame border even on Win7? How does Google Chrome/Microsoft Edge's installer achieve that? คำตอบสั้น ๆ : เป็นไปไม่ได้ คำอธิบายเต็มรูปแบบ: แน่นอนว่าเราสามารถใช้เทคนิคเดียวกับที่เราใช้กับ Win10 เพื่อลบส่วนบนสุดของหน้าต่างและรักษาขอบเฟรมอีกสามเฟรมในเวลาเดียวกัน แต่ใน Win10 เราสามารถนำชายแดนด้านบนกลับมาได้โดยการทำเวทมนตร์สีดำใน WM_PAINT Handler ฉันได้ลองใช้ Win7 แล้วและน่าเศร้าที่ผลลัพธ์คือเคล็ดลับ WM_PAINT จะไม่ทำงานบน Win7 และเรายังไม่สามารถวาดเส้นขอบเฟรมซึ่งมีลักษณะคล้ายกับต้นฉบับ (รูปสี่เหลี่ยมกึ่งโปร่งใสผสมกับสีสำเนียงของระบบและเนื้อหาภาพด้านหลังหน้าต่าง แต่ดูเหมือนว่าตัวติดตั้งของ Google Chrome/Microsoft Edge ประสบความสำเร็จในสิ่งที่เราต้องการทำอย่างไร ผู้ติดตั้งของพวกเขาเป็นโอเพ่นซอร์สและฉันได้อ่านรหัสแล้ว พวกเขาประสบความสำเร็จโดยการซ้อนทับหน้าต่างสองหน้าต่างหนึ่งหน้าต่างปกติที่ด้านล่างหน้าต่างที่ไม่มีเส้นขอบอีกด้านหนึ่งที่ด้านบนเพื่อครอบคลุมแถบชื่อของหน้าต่างด้านล่าง พวกเขาวาดแถบหัวเรื่องโฮมเมดของพวกเขาบนหน้าต่างที่ไม่มีชายแดนและใช้เพื่อเลียนแบบพฤติกรรมของแถบชื่อเรื่องมาตรฐาน แถบชื่อเรื่องเดิมที่จัดทำโดยระบบยังคงอยู่ที่นั่น แต่ใครไม่สามารถมองเห็นได้เพราะมันครอบคลุมโดยหน้าต่างอื่น ฉันยอมรับว่ามันเป็นทางออกที่ดีในกรณีเช่นนี้ แต่สำหรับห้องสมุดของเรามันไม่เหมาะสมเพราะความซับซ้อนของรหัสจะระเบิดขึ้น
สั่งซื้อโดยเวลาบริจาคครั้งแรก (อาจไม่ถูกต้องมากขออภัย)
MIT License
Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.