QT Self-drawing title and borders

Source: Internet
Author: User
Tags win32 window

In QT If you want to paint a caption and a border, the general steps are:

1) The QT::FRAMELESSWINDOWHINT flag is set before the window is created, and a untitled, borderless window is created when the flag is set.

2) Create a self-drawing title bar at the top of the customer area.

3) Draw a background for the window as a border.

4) If you want to drag the mouse effect, you can return htcaption in the WM_NCHITTEST message, the specific method Baidu is no longer detailed here.

But doing so can cause a problem:

On the Win7 system, moving the window to the edge of the screen is automatically arranged (at the top of the screen, left, and automatically arranged on the right) to fail.

If your window does not have this function, there are only two possibilities:

1) Your window does not support the "Move to screen edge auto-arrange" feature.

2) You turn off this feature from the System (Control Panel \ Easy access \ Ease of Access Center \ Make tasks easier to follow \ Prevent Windows from being automatically arranged when you move the window to the edge of the screen).

How to be able to draw both the caption and the border, and the ability to use the automatic screen arrangement:

There is a Windows message to help us, in response to the wm_nccalcsize message, directly return true, you can make the client area size and window size exactly the same, so that there is no title bar and border, we can follow the above general steps to draw the title bar and border, The only difference is that you do not need to set the QT::FRAMELESSWINDOWHINT flag.

This can also be problematic:

The window display is incomplete, especially when maximized, very obvious.

Why the show is incomplete, this problem bothers me all day. I built a new Win32 project, in response to the Wm_nccalcsize message, the window display complete, should be QT itself to deal with the problem, and finally constantly debug QT source code, finally understand the problem:

Call stack (from bottom to top):

1854    C+ +188    C+ +11824    C + +intboolBOOL  1358    C + +

Key functions:

Qmargins QWINDOWSWINDOW::FRAMEMARGINSDP ()Const{    //Frames is invalidated by style changes (window state, flags). //As they is also required for geometry calculations in resize//event sequences, introduce a dirty flag mechanism to be able//to cache results.    if(Testflag (Framedirty)) {//Always skip calculating style-dependent margins for Windows claimed to be frameless. //This allows users to remove the margins by handling wm_nccalcsize with Ws_thickframe set//To ensure Areo snap still works (QTBUG-40578).m_data.frame = window ()->flags () &Qt::framelesswindowhint? Qmargins (0,0,0,0): Qwindowsgeometryhint::frame (Style (), ExStyle ());    Clearflag (Framedirty); }    returnM_data.frame +M_data.custommargins;}

Note It is clear that this is a bug (QTBUG-40578), although we have made the customer area size and window size exactly the same, but Qt still think the system has a border, only if the QT::FRAMELESSWINDOWHINT flag is set, it will return Qmargins (0, 0, 0, 0).

Now back to the origin, and the problem is contradictory, want to paint the title and border must set the QT::FRAMELESSWINDOWHINT flag, but after setting the Qt::framelesswindowhint flag, "Automatic screen edge arrangement" is not valid.

The first thing to figure out is how the QT::FRAMELESSWINDOWHINT flag affects the window because it directly causes the screen edge auto-Arrange to be invalid:

Windowcreationdata::fromwindow (ConstQwindow * W,Constqflags<enumQt::windowtype> Flagsin, unsignedintCreationflags) Line519C++Qwindowswindowdata::create (ConstQwindow * W,ConstQwindowswindowdata & Parameters,ConstQString & title) line1075C++Qwindowsintegration::createwindowdata (Qwindow* window) Line theC++Qwindowsintegration::createplatformwindow (Qwindow* window) Line340C++Qwindowprivate::create (BOOLRecursive) line392C++qwindow::create () line549C++Qwidgetprivate::create_sys (unsignedintWindowBOOLInitializewindow,BOOLDestroyoldwindow) Line1456C++qwidget::create (unsignedintWindowBOOLInitializewindow,BOOLDestroyoldwindow) Line1321C++Qwidgetprivate::createwinid (unsignedintWinid) Line2528C++

voidWindowcreationdata::fromwindow (ConstQwindow *w,Constqt::windowflags flagsin, unsigned creationflags) {    if(Popup | | (type = = Qt::tooltip) | | (Type = =Qt::splashscreen)) {Style=Ws_popup; } Else if(TopLevel &&!)Desktop) {        if(Flags &qt::framelesswindowhint) Style= Ws_popup;//No Border        Else if(Flags &qt::windowtitlehint) Style=ws_overlapped; Elsestyle=0; } Else{style=Ws_child; }    if(!Desktop) {        if(toplevel) {if(type = = Qt::window | | dialog | |tool)) {                if(! (Flags &qt::framelesswindowhint)) {Style|=Ws_popup; if(Flags &qt::mswindowsfixedsizedialoghint) {Style|=Ws_dlgframe; } Else{style|=Ws_thickframe; }                    if(Flags &qt::windowtitlehint) Style|= ws_caption;//Contains ws_dlgframe                }            } Else{ExStyle|=Ws_ex_toolwindow; }        }    }}

The above one is the call stack (from bottom to top) and one is the key function (the unimportant content in the function has been removed). As you can see from the code, setting the QT::FRAMELESSWINDOWHINT flag changes the window style, which affects the window that was created, and now basically knows that the screen edge auto-arrange feature is related to the window style.

Create a new Win32 window program that constantly changes the style of the window and concludes that only the window has Ws_maximizebox | Ws_thickframe style, the screen edge Auto-arrange feature works, and you might want to add a ws_caption style, or the window will be maximized to overwrite the taskbar.

The Final Solution is:

1. In the window's constructor, add the following code to change the window's style:

    This, Setwindowflags (qt::framelesswindowhint);     = (HWND)This,winId ();     = :: GetWindowLong (hwnd, gwl_style);    | Ws_maximizebox | Ws_thickframe | ws_caption);

2. Overloading the Nativeevent function, handling wm_nchittest and wm_nccalcsize messages

BOOLWnd_title::nativeevent (ConstQbytearray &eventtype,void*message,Long*result) {MSG* msg = (msg*) message; Switch(msg->message) {     Casewm_nchittest: {intXPos = Get_x_lparam (Msg->lparam)-This->framegeometry (). X (); intYPos = Get_y_lparam (Msg->lparam)-This->framegeometry (). Y (); if(YPos < +) {            *result =htcaption; return true; }    }         Break;  Casewm_nccalcsize:return true;    }    return false;}
Display effect:

  

QT Self-drawing title and borders

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.