1.作用

实现窗体吸附功能,当窗体靠近某个应用边缘时,自动吸附到边缘,并且大小和边缘对齐

2.实现方式

使用js调用系统的user32.dll获取窗口的位置大小信息。

3.安装调用dll的库,目前用的比较好用的一个

npm install ffi-rs

4.electron主线程中使用

import {createPointer, DataType, define, open, restorePointer, unwrapPointer} from "ffi-rs";

open({
    library: 'user32',
    path: 'user32'
})

// 这里填写需要吸附的窗口名字
const SNAP_FORM_TITLE_ARR = ['千牛工作台', '接待中心']

// 通过窗体标题判断窗体要不要吸附
function isSnapForm(title: string) {
    return SNAP_FORM_TITLE_ARR.some(it => title?.includes(it))
}

const user32 = define({
    "GetWindowRect": {
        library: "user32",
        retType: DataType.Boolean,
        paramsType: [DataType.I32, DataType.External]
    },
    "GetWindowTextW": {
        library: "user32",
        retType: DataType.I32,
        paramsType: [DataType.I32, DataType.U8Array, DataType.I32]
    },
    "GetForegroundWindow": {
        library: "user32",
        retType: DataType.I32,
        paramsType: []
    },
})

// 窗体矩形类型
const rectType = {
    left: DataType.I32,
    top: DataType.I32,
    right: DataType.I32,
    bottom: DataType.I32
}

const rect = {
    left: 0,
    top: 0,
    right: 0,
    bottom: 0
}
const rectPointer = createPointer({
    paramsType: [rectType],
    paramsValue: [rect]
})

let interval: NodeJS.Timeout;

// 吸附和取消吸附
export function monitorWindow(cb: (res: typeof rect) => void) {
    if (interval) {
        clearInterval(interval)
        interval = null
    } else {
        interval = setInterval(() => {
            const hwnd = user32.GetForegroundWindow([]);
            const titleBuffer = Buffer.alloc(200)
            user32.GetWindowTextW([hwnd, titleBuffer, titleBuffer.length])
            const title = titleBuffer.toString('utf16le')
            if (isSnapForm(title)) {
                user32.GetWindowRect([hwnd, unwrapPointer(rectPointer)[0]])
                const restoreData = restorePointer({
                    paramsValue: rectPointer,
                    retType: [rectType]
                })
                cb(restoreData[0])
            }
        }, 16)
        // 16ms相对丝滑一点
    }
}
const win = new BrowserWindow({
    ...
})
// 屏幕缩放因子 -> 1.0 1.5(适配不同的显示器缩放布局),如果还要适配扩展屏,需要自己实现一下
const scale = screen.getPrimaryDisplay().scale;
monitorWindow((rect) => {
    const {left, top, right, bottom} = rect;
    win.setSize(MAIN_WIN_WIDTH, Math.floor((bottom - top) / scaleFactor));
    win.setPosition(Math.ceil(left / scale - MAIN_WIN_WIDTH), Math.ceil(top / scale));
    win.setAlwaysOnTop(true);
})
本文使用MdSync工具发布!

代码人生笔记
1 声望0 粉丝

引用和评论

0 条评论