r0x0r / pywebview

Build GUI for your Python program with JavaScript, HTML, and CSS
https://pywebview.flowrl.com
BSD 3-Clause "New" or "Revised" License
4.7k stars 551 forks source link

Improved Borderless Windows (shadows and Windows 11 rounded edges) #1310

Closed yllhwa closed 6 months ago

yllhwa commented 9 months ago

Specification

Description

By default, borderless windows lose shadows and rounded corners.

image

Use the following code to create an unbounded window with shadows and rounded corners(looks much better now).

image


import webview
import ctypes
import ctypes.wintypes
import win32process, win32gui
import os

def DwmSetWindowAttribute(hwnd, attr, value, size=4):
    DwmSetWindowAttribute = ctypes.windll.dwmapi.DwmSetWindowAttribute
    DwmSetWindowAttribute.argtypes = [ctypes.wintypes.HWND, ctypes.wintypes.DWORD, ctypes.c_void_p, ctypes.wintypes.DWORD]
    return DwmSetWindowAttribute(hwnd, attr, ctypes.byref(ctypes.c_int(value)), size)

def ExtendFrameIntoClientArea(hwnd):

    class _MARGINS(ctypes.Structure):
        _fields_ = [("cxLeftWidth", ctypes.c_int),
                    ("cxRightWidth", ctypes.c_int),
                    ("cyTopHeight", ctypes.c_int),
                    ("cyBottomHeight", ctypes.c_int)
                    ]

    DwmExtendFrameIntoClientArea = ctypes.windll.dwmapi.DwmExtendFrameIntoClientArea
    m = _MARGINS()
    m.cxLeftWidth = 1
    m.cxRightWidth = 1
    m.cyTopHeight = 1
    m.cyBottomHeight = 1
    return DwmExtendFrameIntoClientArea(hwnd, ctypes.byref(m))

def get_hwnds_for_pid(pid):
    hwnds = []
    def callback(hwnd, hwnds):
        if win32gui.IsWindowVisible(hwnd) and win32gui.IsWindowEnabled(hwnd):
            found_tid, found_pid = win32process.GetWindowThreadProcessId(hwnd)
            if found_pid == pid:
                hwnds.append(hwnd)
            return True
    win32gui.EnumWindows(callback, hwnds)
    return hwnds

def setup_all_windows_borderless():
    hwnds = get_hwnds_for_pid(os.getpid())
    print(hwnds)
    for hwnd in hwnds:
        DwmSetWindowAttribute(hwnd, 2, 2, 4)
        ExtendFrameIntoClientArea(hwnd)

if __name__ == '__main__':
    window = webview.create_window('test', "https://example.com/", frameless=True, height=300)
    window.events.loaded += setup_all_windows_borderless
    webview.start()

can this feature be built-in into the library(like electron/wails/tauri)?

Additionally, the method of getting handles is not elegant and may be more convenient to implement internally

Practicalities

paulocoutinhox commented 8 months ago

+1

ylm-king commented 8 months ago

good!

r0x0r commented 7 months ago

Looks good. Feel free to create a PR.

github-actions[bot] commented 6 months ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.