1

I'm trying to drop a shadow on a borderless window using Qt in windows. I succeeded in dropping the shadow when launching the application, referring to the following article.

But I encountered the problem that the shadow will disappear if the application is deactivated and reactivated ( In other words, click the other applications, and click my application again.)

Perhaps my implementation is not good enough. I'm glad if you have some ideas for this issue.

I'm trying to imprement Qt with Go bindings Here is the code snippet:

package qframelesswindow

import (
    "unsafe"

    "github.com/therecipe/qt/core"
    "github.com/therecipe/qt/widgets"

    win "github.com/akiyosi/w32"
)

func (f *QFramelessWindow) SetNativeEvent(app *widgets.QApplication) {
    filterObj := core.NewQAbstractNativeEventFilter()
    filterObj.ConnectNativeEventFilter(func(eventType *core.QByteArray, message unsafe.Pointer, result int) bool {
        msg := (*win.MSG)(message)
        lparam := msg.LParam
        hwnd := msg.Hwnd
        var uflag uint
        uflag = win.SWP_NOZORDER | win.SWP_NOOWNERZORDER | win.SWP_NOMOVE | win.SWP_NOSIZE | win.SWP_FRAMECHANGED
        var nullptr win.HWND
        shadow := &win.MARGINS{0, 0, 0, 1}

        switch msg.Message {
        case win.WM_CREATE:
            style := win.WS_POPUP | win.WS_THICKFRAME | win.WS_MINIMIZEBOX | win.WS_MAXIMIZEBOX | win.WS_CAPTION
            win.SetWindowLong(hwnd, win.GWL_STYLE, uint32(style))

            win.DwmExtendFrameIntoClientArea(hwnd, shadow)
            win.SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, uflag)

            return true

        case win.WM_NCCALCSIZE:
            if msg.WParam == 1 {
                // this kills the window frame and title bar we added with WS_THICKFRAME and WS_CAPTION
                result = 0
                return true
            }
            return false

        case win.WM_GETMINMAXINFO:
            mm := (*win.MINMAXINFO)((unsafe.Pointer)(lparam))
            mm.PtMinTrackSize.X = int32(f.minimumWidth)
            mm.PtMinTrackSize.Y = int32(f.minimumHeight)
            return true

        default:
        }
        return false
    })
    app.InstallNativeEventFilter(filterObj)
}

All source code is in my repository; akiyosi/goqtframelesswindow

user51
  • 8,843
  • 21
  • 79
  • 158
akiyosi
  • 43
  • 6

1 Answers1

1

WM_NCCALCSIZE:

If wParam is TRUE, the application should return zero or a combination of the following values.(In document)

And also:

When wParam is TRUE, simply returning 0 without processing the NCCALCSIZE_PARAMS rectangles will cause the client area to resize to the size of the window, including the window frame. This will remove the window frame and caption items from your window, leaving only the client area displayed.

Starting with Windows Vista, simply returning 0 does not affect extended frames, only the standard frame will be removed.

EDIT:

Set the return value with the DWL_MSGRESULT instead of result = 0.

Drake Wu
  • 6,927
  • 1
  • 7
  • 30
  • the standard frame includes extended frames? I followed the advice and fix the code like the following, but the problem could not be solved. `case win.WM_NCCALCSIZE: if msg.WParam == 1 { result = 0 return true } else { result = int(win.DefWindowProc(hwnd, win.WM_NCCALCSIZE, wparam, lparam)) } return false` – akiyosi Apr 19 '19 at 09:53
  • `return win.DefWindowProc(hwnd, win.WM_NCCALCSIZE, wparam, lparam);` instead of `return true/false` – Drake Wu Apr 22 '19 at 08:08
  • `win.DefWindowProc()` is uintptr type and return type should be bool, so, I trying the following but not working. `case win.WM_NCCALCSIZE: ret := win.DefWindowProc(msg.Hwnd, win.WM_NCCALCSIZE, msg.WParam, msg.LParam) if ret == 1 { return true } else { return false }` – akiyosi Apr 22 '19 at 09:53
  • Set the return value with the [`DWL_MSGRESULT`](https://learn.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-setwindowlonga#DWL_MSGRESULT) instead of `result = 0` – Drake Wu May 02 '19 at 09:42