node版本

λ node -v
v12.16.2

main.js

const ffi = require("@saleae/ffi");
const child_process = require("child_process");
const W32 = require("./w32"); const argv = process.argv.slice(2); if (!argv || !argv.length) process.exit(1); const play = child_process.fork("./play.js"); // ffplay -noborder -loop 0 -fs -vf scale=w=1920:h=-1 "${argv[0]}"
// -noborder 无边框
// -loop 0 循环次数,0无限循环
// -vf scale=w=1920:h=-1 使用scale滤镜, See also: https://trac.ffmpeg.org/wiki/Scaling
// ffplay -noborder -x 1920 -y 1080 无边框,强制设置宽高
play.send(`ffplay -noborder -x 1920 -y 1080 -loop 0 "${argv[0]}" `);
play.on("message", playCallback); function playCallback() {
let ffplayw = 0; // ffplay句柄
let t;
t = setInterval(() => {
ffplayw = getFFplayHandle();
if (ffplayw !== 0) {
clearInterval(t);
setDynamicWallpaper(ffplayw);
}
}, 1000);
} function setDynamicWallpaper(ffplayw) {
const progman = W32.FindWindowW(TEXT("Progman"), null); // 要触发在桌面图标和墙纸之间创建WorkerW窗口,我们必须向程序管理器发送一条消息。
// 该消息是未记录的消息,因此没有专用的Windows API名称,除了0x052C
W32.SendMessageTimeoutW(
progman,
0x052c, // 在程序管理器上生成墙纸工作程序的未记录消息
0,
0,
0x0000,
1000,
0
); // 我们枚举所有Windows
W32.EnumWindows(
ffi.Callback("bool", ["int32", "int32"], (tophandle, topparamhandle) => {
// 找到一个具有SHELLDLL_DefView的Windows
const SHELLDLL_DefView = W32.FindWindowExW(
tophandle,
0,
TEXT("SHELLDLL_DefView"),
0
);
if (SHELLDLL_DefView !== 0) {
// 将其下一个同级分配给workerw。
const workerw = W32.FindWindowExW(0, tophandle, TEXT("WorkerW"), 0);
W32.SetParent(ffplayw, workerw);
}
return true;
}),
0
);
}
function TEXT(text) {
return Buffer.from(`${text}\0`, "ucs2");
} // 获取ffplay句柄
function getFFplayHandle() {
return W32.FindWindowW(TEXT("SDL_app"), null);
}

play.js

const child_process = require("child_process");

process.on("message", (runFFplayCommand) => {
process.send(true);
child_process.execSync(runFFplayCommand);
});

w32.js

const ffi = require("@saleae/ffi");

// Import user32
const W32 = new ffi.Library("user32", {
// 检索顶级窗口的句柄,该顶级窗口的类名和窗口名与指定的字符串匹配。此功能不搜索子窗口。此功能不执行区分大小写的搜索。
FindWindowW: ["int32", ["string", "string"]], // 将指定的消息发送到一个或多个窗口
SendMessageTimeoutW: [
"int32",
["int32", "int32", "int32", "int32", "int32", "int32", "int32"],
], // 通过将句柄传递给每个窗口,依次传递到应用程序定义的回调函数,可以枚举屏幕上所有的顶级窗口
EnumWindows: ["bool", ["pointer", "int32"]], // 检索其类名和窗口名与指定字符串匹配的窗口的句柄。该功能搜索子窗口,从指定子窗口之后的子窗口开始。此功能不执行区分大小写的搜索。
FindWindowExW: ["int32", ["int32", "int32", "string", "int32"]], // 更改指定子窗口的父窗口。
// HWND SetParent(HWND hWndChild, HWND hWndNewParent);
SetParent: ["int32", ["int32", "int32"]], // int MessageBox(
// HWND hWnd, 要创建的消息框的所有者窗口的句柄。如果此参数为NULL,则消息框没有所有者窗口
// LPCTSTR lpText, 要显示的消息
// LPCTSTR lpCaption, 对话框标题
// UINT uType 对话框的内容和行为
// );
MessageBoxW: ["int32", ["int32", "string", "string", "int32"]], // 最小化(但不破坏)指定的窗口。
CloseWindow: ["bool", ["int32"]], // 销毁指定的窗口
DestroyWindow: ["bool", ["int32"]], // 打开指定的桌面对象
OpenDesktopW: ["int32", ["string", "int32", "bool", "int32"]], // 确定指定窗口的可见性状态。
IsWindowVisible: ["bool", ["int32"]], // 设置指定窗口的显示状态。
ShowWindow: ["bool", ["int32", "int32"]],
}); module.exports = W32;

运行

>node main.js "D:\dynamic wallpaper\Nightcore-We-Wish-You-A-Merry-Christmas-Live-Wallpaper.mp4"

运行前的窗口:

运行后的窗口:

将视频放在Progman下面

现在测试来看,这种方法要好些,关闭进程后不会显示残留壁纸

function setDynamicWallpaper(ffplayw) {
const progman = W32.FindWindowW(TEXT("Progman"), null); // 要触发在桌面图标和墙纸之间创建WorkerW窗口,我们必须向程序管理器发送一条消息。
// 该消息是未记录的消息,因此没有专用的Windows API名称,除了0x052C
W32.SendMessageTimeoutW(
progman,
0x052c, // 在程序管理器上生成墙纸工作程序的未记录消息
0,
0,
0x0000,
1000,
0
); // 我们枚举所有Windows
W32.EnumWindows(
ffi.Callback("bool", ["int32", "int32"], (tophandle, topparamhandle) => {
// 找到一个具有SHELLDLL_DefView的Windows
const SHELLDLL_DefView = W32.FindWindowExW(
tophandle,
0,
TEXT("SHELLDLL_DefView"),
0
);
if (SHELLDLL_DefView !== 0) {
// 将其下一个同级分配给workerw。
const workerw = W32.FindWindowExW(0, tophandle, TEXT("WorkerW"), 0);
const isVisible = W32.IsWindowVisible(workerw);
if (isVisible) {
// 设置窗口为未激活状态,否则这个窗口会遮挡视频
W32.ShowWindow(workerw, 0);
}
W32.SetParent(ffplayw, progman);
}
return true;
}),
0
);
}

现在按下Ctrl+c指令后,node进程结束,ffplay关闭,壁纸将显示之前的壁纸

使用ffplay你可以解析本地视频,图片,http视频,直播流,ts视频段,m3u8,等等...

参考连接

nodejs 在windows10中设置动态(视频)壁纸的更多相关文章

  1. [UWP开发]在windows10中设置壁纸~UserProfilePersonalizationSettings

    在之前的wp8.1和wp8中,微软没有公开设置壁纸的API,只有一个设置锁屏的API,但在Windows10中,微软为我们提供了设置壁纸的API:TrySetWallpaperImageAsync,他 ...

  2. vue 在微信中设置动态标题

    1.安装插件 cnpm install vue-wechat-title --save 2.在main.js中引入 import VueWechatTitle from 'vue-wechat-tit ...

  3. laydate中设置动态改变max与min值的方法

    参考网址: 原网址:https://blog.csdn.net/cherry_11qianqian/article/details/82259704 改进的网址:https://blog.csdn.n ...

  4. 【nodeJS】webstorm中设置nodej智能提示

  5. 为你的Windows7设置动态壁纸

    From:http://www.cnblogs.com/killerlegend/p/3644014.html By KillerLegend DreamScene是Vista上的一个功能,可以让你设 ...

  6. nodejs爬虫如何设置动态ip以及userAgent

    nodejs爬虫如何设置动态ip以及userAgent 转https://blog.csdn.net/u014374031/article/details/78833765 前言 在写nodejs爬虫 ...

  7. Quartz在Spring中动态设置cronExpression (spring设置动态定时任务)

    什么是动态定时任务:是由客户制定生成的,服务端只知道该去执行什么任务,但任务的定时是不确定的(是由客户制定).      这样总不能修改配置文件每定制个定时任务就增加一个trigger吧,即便允许客户 ...

  8. 为TextView设置两种状态,程序中可以动态切换

    经常会需要用文字的两种状态来表示当前系统的某两种状态.比如:         这里的第一个TextView和后两个TextView就表示了两种状态.我们可以在程序的动态的切换状态(而不是直接修改颜色) ...

  9. windows下nodejs express安装及入门网站,视频资料,开源项目介绍

    windows下nodejs express安装及入门网站,视频资料,开源项目介绍,pm2,supervisor,npm,Pomelo,Grunt安装使用注意事项等总结 第一步:下载安装文件下载地址: ...

随机推荐

  1. http的响应码及含义

    1xx(临时响应) 100: 请求者应当继续提出请求. 101(切换协议) 请求者已要求服务器切换协议,服务器已确认并准备进行切换. 2xx(成功) 200:正确的请求返回正确的结果 201:表示资源 ...

  2. NodeJS入门学习教程

    一.概念 1.什么是nodejs Node.js是JavaScript 运行时环境,通俗易懂的讲,Node.js是JavaScript的运行平台 Node.js既不是语言,也不是框架,它是一个平台 2 ...

  3. 项目Js源码整合

    整合一下目前做的项目中JS中用到的相关源码等,留待记录和使用. 一.ajaxgrid源码部分 1.初始化 2.查询 3.删除 4.保存 5.根据id获取值,时间值等 6.详情.跳转链接 : a 标签 ...

  4. js截取+全部替换+字符串

    //将关键字标志显示到页面中 function showKeyWord(showStr) { var keyword = $("#keyword").val();//页面中的关键字 ...

  5. linux系统rpm和yum软件包管理

    软件安装方式总结 安装软件方式有如下几种: 方式1:编译安装 将源码程序按照需求进行先编译,后安装 缺点:装过程复杂,而且很慢 优点:安装过程可控,真正的按需求进行安装(安装位置.安装的模块都可以选择 ...

  6. IntelliJ IDEA 内置数据库管理工具实战

    1. 写在前面 开发Java应用程序,作为明星工具IntelliJ IDEA Ultimate当然是首选,然后进行数据库SQL开发的时候,常常会选择诸如:Navicat , sqlyog, MySQL ...

  7. 2013-2014 ACM-ICPC, NEERC, Eastern Subregional Contest PART (8/10)

    $$2013-2014\ ACM-ICPC,\ NEERC,\ Eastern\ Subregional\ Contest$$ \(A.Podracing\) 首先枚举各个折现上的点,找出最小宽度,然 ...

  8. B、小花梨的三角形(解题报告)

    通过set进行标记(思想很简单,实现起来有点容易错)set(红黑树:效率高) 思路: 对行列和长度进行枚举: 对三个顶点进行排序 储存顶点后计数输出 #include<iostream> ...

  9. Codeforces Round #646 (Div. 2) 题解 (ABCDE)

    目录 A. Odd Selection B. Subsequence Hate C. Game On Leaves D. Guess The Maximums E. Tree Shuffling ht ...

  10. Educational Codeforces Round 96 (Rated for Div. 2) E. String Reversal (思维,逆序对)

    题意:给你一个字符串,每次可以调换现字符串的相邻两个字符,问最少操作多少次使得这个字符串等于其反转过来的字符串. 题解:先考虑字符串中没有相同字符的情况,那么我们每次将目前字符串的最后一个字符一直调换 ...