mirror of
https://github.com/fanchenio/DawnLauncher.git
synced 2025-07-13 21:02:10 +08:00
Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
5800cbbdaa | ||
![]() |
56517f059c | ||
![]() |
342d8939ab | ||
![]() |
92270def83 | ||
![]() |
881fbc9f56 | ||
![]() |
2cd721263e | ||
![]() |
ea851c652c | ||
![]() |
9243140d3b | ||
![]() |
36b77ce32b | ||
![]() |
d51a5404ee | ||
![]() |
018bd91931 |
@ -561,6 +561,13 @@ function showOpenDialogSync(windowName: string, options: OpenDialogOptions) {
|
||||
return pathList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 窗口是否存在
|
||||
*/
|
||||
function mainWindowExist() {
|
||||
return global.mainWindow && !global.mainWindow.isDestroyed();
|
||||
}
|
||||
|
||||
export {
|
||||
downloadImage,
|
||||
getURLInfo,
|
||||
@ -580,4 +587,5 @@ export {
|
||||
showErrorMessageBox,
|
||||
showSaveDialogSync,
|
||||
showOpenDialogSync,
|
||||
mainWindowExist,
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { BrowserWindow, shell, app } from "electron";
|
||||
import { join } from "node:path";
|
||||
import { parsePath, getURLParams } from "../../commons/utils";
|
||||
import { extname, join } from "node:path";
|
||||
import { parsePath, getURLParams, getFileIcon } from "../../commons/utils";
|
||||
import { Item } from "../../../types/item";
|
||||
import {
|
||||
batchAdd,
|
||||
@ -15,8 +15,10 @@ import { writeFile, statSync, readFileSync, accessSync } from "node:fs";
|
||||
import mime from "mime";
|
||||
import {
|
||||
deleteExtname,
|
||||
getFileName,
|
||||
getItemName,
|
||||
isAbsolutePath,
|
||||
newItem,
|
||||
} from "../../../commons/utils/common";
|
||||
import { iconExts } from "../../commons/utils";
|
||||
import { addAssociateFolderWatcher } from "../classification";
|
||||
@ -29,6 +31,7 @@ import {
|
||||
showSaveDialogSync,
|
||||
} from "../commons/index";
|
||||
import { fork } from "../../commons/utilityProcessUtils";
|
||||
import { ShortcutInfo } from "../../../types/common";
|
||||
|
||||
// 窗口
|
||||
let itemAddEditWindow: BrowserWindow | null = null;
|
||||
@ -260,24 +263,17 @@ function move(idList: Array<number>, toClassificationId: number) {
|
||||
* @param classificationId
|
||||
* @param pathList
|
||||
*/
|
||||
function drop(classificationId: number, pathList: Array<string>) {
|
||||
fork(
|
||||
"getDropItemInfo",
|
||||
{
|
||||
classificationId,
|
||||
pathList,
|
||||
},
|
||||
(resultList: Array<Item>) => {
|
||||
// 添加项目
|
||||
let itemList = batchAdd(classificationId, resultList);
|
||||
// 发送消息到页面
|
||||
sendToWebContent("mainWindow", "onAddItem", {
|
||||
itemList,
|
||||
clear: false,
|
||||
classificationId: null,
|
||||
});
|
||||
}
|
||||
);
|
||||
async function drop(classificationId: number, pathList: Array<string>) {
|
||||
// 获取项目信息
|
||||
let resultList = await getDropItemInfo(classificationId, pathList);
|
||||
// 添加项目
|
||||
let itemList = batchAdd(classificationId, resultList);
|
||||
// 发送消息到页面
|
||||
sendToWebContent("mainWindow", "onAddItem", {
|
||||
itemList,
|
||||
clear: false,
|
||||
classificationId: null,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -323,12 +319,14 @@ function updateOpenInfo(type: string, id: number) {
|
||||
*/
|
||||
function run(
|
||||
type: string,
|
||||
operation: "open" | "runas" | "openFileLocation",
|
||||
operation: "open" | "runas" | "openFileLocation" | "explore",
|
||||
item: Item
|
||||
) {
|
||||
if (item.data) {
|
||||
if (operation === "open" && item.data.runAsAdmin) {
|
||||
operation = "runas";
|
||||
} else if (operation === "open" && item.type === 1) {
|
||||
operation = "explore";
|
||||
}
|
||||
// 更新打开信息
|
||||
updateOpenInfo(type, item.id);
|
||||
@ -706,6 +704,90 @@ function deleteQuickSearchHistory(itemId: number) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过路径获取项目信息
|
||||
* @param classificationId
|
||||
* @param pathList
|
||||
*/
|
||||
async function getDropItemInfo(
|
||||
classificationId: number,
|
||||
pathList: Array<string>
|
||||
) {
|
||||
// 项目列表
|
||||
let itemList: Array<Item> = [];
|
||||
// 解析文件信息并添加项目
|
||||
for (const path of pathList) {
|
||||
try {
|
||||
// item
|
||||
let item = newItem({ classificationId });
|
||||
// 目标
|
||||
item.data.target = path;
|
||||
// 名称
|
||||
item.name = getFileName(item.data.target);
|
||||
// 判断是否是快捷方式,如果是的话,需要获取真实路径
|
||||
if (mime.getType(path) === "application/x-ms-shortcut") {
|
||||
// 快捷方式
|
||||
// 获取真实文件路径和参数
|
||||
let shortcutInfo: ShortcutInfo | null =
|
||||
global.addon.getShortcutFileInfo(path);
|
||||
if (shortcutInfo) {
|
||||
// 路径
|
||||
if (shortcutInfo.target) {
|
||||
item.data.target = shortcutInfo.target;
|
||||
}
|
||||
// 参数
|
||||
if (shortcutInfo.arguments) {
|
||||
item.data.params = shortcutInfo.arguments;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 获取图标
|
||||
item.data.icon = await getFileIcon(item.data.target);
|
||||
// 获取后缀,判断是否是url
|
||||
let ext = extname(item.data.target);
|
||||
if (ext && ext.toLowerCase() === ".url") {
|
||||
// url
|
||||
let url = parseUrlFileContent(readFileSync(item.data.target, "utf-8"));
|
||||
if (url && url.trim() !== "") {
|
||||
item.data.target = url;
|
||||
item.type = 2;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// 文件类型
|
||||
let stats = statSync(item.data.target);
|
||||
item.type = stats.isFile() ? 0 : 1;
|
||||
}
|
||||
// 去掉后缀
|
||||
if (item.type === 0 || item.type === 2) {
|
||||
item.name = deleteExtname(item.name);
|
||||
}
|
||||
// push
|
||||
itemList.push(item);
|
||||
} catch (e) {}
|
||||
}
|
||||
return itemList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析.url文件内容以获取URL
|
||||
* @param content
|
||||
* @returns
|
||||
*/
|
||||
function parseUrlFileContent(content: string) {
|
||||
if (content) {
|
||||
const lines = content.split("\n");
|
||||
for (const line of lines) {
|
||||
if (line.startsWith("URL=")) {
|
||||
const url = line.substring(4).trim();
|
||||
return url;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export {
|
||||
createAddEditWindow,
|
||||
createNetworkIconWindow,
|
||||
|
@ -203,8 +203,7 @@ export default function () {
|
||||
// "打开"菜单
|
||||
let openMenu = false;
|
||||
if (
|
||||
(item.type === 0 &&
|
||||
global.addon.hasRunas(parsePath(item.data.target))) ||
|
||||
item.type === 0 ||
|
||||
item.type === 4 ||
|
||||
(item.type === 3 && item.data.target === "cmd.exe")
|
||||
) {
|
||||
|
@ -13,6 +13,7 @@ import cacheData from "../commons/cacheData";
|
||||
import {
|
||||
getMainBackgorunColor,
|
||||
getWindowInScreen,
|
||||
mainWindowExist,
|
||||
sendToWebContent,
|
||||
} from "../commons";
|
||||
import { release } from "node:os";
|
||||
@ -24,8 +25,6 @@ let mainWindow: BrowserWindow | null = null;
|
||||
* 主窗口
|
||||
*/
|
||||
function createMainWindow() {
|
||||
// 预热
|
||||
global.addon.hasRunas(process.execPath);
|
||||
// 如果窗口存在先关闭窗口
|
||||
if (mainWindow && !mainWindow.isDestroyed() && mainWindow.isVisible()) {
|
||||
mainWindow.close();
|
||||
@ -182,6 +181,10 @@ function createMainWindow() {
|
||||
sendToWebContent("mainWindow", "onCollapseSubClassification", {});
|
||||
}
|
||||
});
|
||||
// 主窗口关闭事件
|
||||
mainWindow.on("closed", () => {
|
||||
app.quit();
|
||||
});
|
||||
// 创建鼠标hook
|
||||
let mousedownClassName = null;
|
||||
addon.createMouseHook((...args: any[]) => {
|
||||
@ -236,12 +239,13 @@ function createMainWindow() {
|
||||
*/
|
||||
function onBlurHide() {
|
||||
if (
|
||||
mainWindow.isVisible() &&
|
||||
mainWindowExist() &&
|
||||
global.mainWindow.isVisible() &&
|
||||
global.setting.general.hideLoseFocus &&
|
||||
!global.setting.general.alwaysTop &&
|
||||
mainWindow.getChildWindows().length === 0 &&
|
||||
global.mainWindow.getChildWindows().length === 0 &&
|
||||
!global.mainWindowShowDialog &&
|
||||
!hasCursorPosWindow(mainWindow)
|
||||
!hasCursorPosWindow(global.mainWindow)
|
||||
) {
|
||||
// 隐藏窗口
|
||||
hideMainWindow();
|
||||
@ -299,6 +303,9 @@ function showMainWindowBefore(
|
||||
* @param autoHide
|
||||
*/
|
||||
function showMainWindow(blurHide: boolean, autoHide = false) {
|
||||
if (!mainWindowExist()) {
|
||||
return;
|
||||
}
|
||||
// flag
|
||||
let flag = true;
|
||||
// 是否开启勿扰模式
|
||||
@ -313,12 +320,12 @@ function showMainWindow(blurHide: boolean, autoHide = false) {
|
||||
}
|
||||
if (flag) {
|
||||
if (!global.setting.general.alwaysTop) {
|
||||
mainWindow.setAlwaysOnTop(true, "screen-saver");
|
||||
global.mainWindow.setAlwaysOnTop(true, "screen-saver");
|
||||
}
|
||||
global.mainWindow.show();
|
||||
global.mainWindow.focus();
|
||||
if (!global.setting.general.alwaysTop) {
|
||||
mainWindow.setAlwaysOnTop(false);
|
||||
global.mainWindow.setAlwaysOnTop(false);
|
||||
}
|
||||
global.blurHide = blurHide;
|
||||
}
|
||||
@ -328,7 +335,7 @@ function showMainWindow(blurHide: boolean, autoHide = false) {
|
||||
* 隐藏窗口
|
||||
*/
|
||||
function hideMainWindow() {
|
||||
if (global.mainWindow.isVisible()) {
|
||||
if (mainWindowExist() && global.mainWindow.isVisible()) {
|
||||
global.mainWindow.hide();
|
||||
global.blurHide = false;
|
||||
}
|
||||
@ -389,10 +396,13 @@ function createTray(show: boolean) {
|
||||
* @returns
|
||||
*/
|
||||
function edgeAdsorb(display: Display | null, workArea = false) {
|
||||
if (!mainWindowExist()) {
|
||||
return;
|
||||
}
|
||||
// 如果勾选停靠在桌面边缘时自动隐藏,放行
|
||||
if (
|
||||
global.mainWindow.isDestroyed() ||
|
||||
(!global.setting.general.edgeAdsorb && !global.setting.general.edgeAutoHide)
|
||||
!global.setting.general.edgeAdsorb &&
|
||||
!global.setting.general.edgeAutoHide
|
||||
) {
|
||||
return;
|
||||
}
|
||||
@ -400,7 +410,7 @@ function edgeAdsorb(display: Display | null, workArea = false) {
|
||||
// 清空方向
|
||||
global.mainWindowDirection = null;
|
||||
// 屏幕
|
||||
let displays = display ? [display] : getWindowInScreen(mainWindow);
|
||||
let displays = display ? [display] : getWindowInScreen(global.mainWindow);
|
||||
if (displays.length > 1 || displays.length === 0) {
|
||||
return;
|
||||
}
|
||||
@ -489,6 +499,9 @@ function edgeAdsorb(display: Display | null, workArea = false) {
|
||||
* 显示时跟随鼠标位置
|
||||
*/
|
||||
function showFollowMousePosition() {
|
||||
if (!mainWindowExist()) {
|
||||
return;
|
||||
}
|
||||
// 当永远居中、固定位置勾选后不能使用显示时跟随鼠标位置
|
||||
if (
|
||||
!global.setting.general.alwaysCenter &&
|
||||
@ -519,6 +532,9 @@ function showFollowMousePosition() {
|
||||
* 中间单击显示/隐藏窗口
|
||||
*/
|
||||
function showHideMouseWheelClick() {
|
||||
if (!mainWindowExist()) {
|
||||
return;
|
||||
}
|
||||
if (global.setting.general.showHideMouseWheelClick) {
|
||||
if (global.mainWindow.isVisible()) {
|
||||
hideMainWindow();
|
||||
@ -532,8 +548,11 @@ function showHideMouseWheelClick() {
|
||||
* 永远居中
|
||||
*/
|
||||
function alwaysCenter() {
|
||||
if (!mainWindowExist()) {
|
||||
return;
|
||||
}
|
||||
if (global.setting.general.alwaysCenter) {
|
||||
mainWindow.center();
|
||||
global.mainWindow.center();
|
||||
}
|
||||
}
|
||||
|
||||
@ -544,26 +563,32 @@ function alwaysCenter() {
|
||||
* @returns
|
||||
*/
|
||||
function autoHide(size: number, timer: boolean) {
|
||||
if (global.mainWindow.isDestroyed() || !global.setting.general.edgeAutoHide) {
|
||||
if (!mainWindowExist()) {
|
||||
return;
|
||||
}
|
||||
if (!global.setting.general.edgeAutoHide) {
|
||||
return;
|
||||
}
|
||||
// 当有子窗口时不自动隐藏
|
||||
if (mainWindow.getChildWindows().length > 0 || global.mainWindowShowDialog) {
|
||||
if (
|
||||
global.mainWindow.getChildWindows().length > 0 ||
|
||||
global.mainWindowShowDialog
|
||||
) {
|
||||
return;
|
||||
}
|
||||
let x = screen.getCursorScreenPoint().x;
|
||||
let y = screen.getCursorScreenPoint().y;
|
||||
try {
|
||||
// 屏幕
|
||||
let displays = getWindowInScreen(mainWindow);
|
||||
let displays = getWindowInScreen(global.mainWindow);
|
||||
if (displays.length > 1 || displays.length === 0) {
|
||||
return;
|
||||
}
|
||||
// 屏幕区域
|
||||
let displayBounds = displays[0].bounds;
|
||||
// 窗口位置信息
|
||||
let bounds = mainWindow.getBounds();
|
||||
if (mainWindow.isVisible()) {
|
||||
let bounds = global.mainWindow.getBounds();
|
||||
if (global.mainWindow.isVisible()) {
|
||||
let flag = false;
|
||||
if (bounds.x === displayBounds.x && bounds.y === displayBounds.y) {
|
||||
// 左上角
|
||||
@ -738,12 +763,15 @@ function doubleClickTaskbar(
|
||||
mousedownClassName: string | null,
|
||||
className: string | null
|
||||
) {
|
||||
if (!mainWindowExist()) {
|
||||
return;
|
||||
}
|
||||
// 必须开启设置
|
||||
if (!global.setting.general.showHideDoubleClickTaskbar) {
|
||||
return;
|
||||
}
|
||||
// 获取屏幕
|
||||
let displays = getWindowInScreen(mainWindow);
|
||||
let displays = getWindowInScreen(global.mainWindow);
|
||||
if (
|
||||
displays.length > 1 ||
|
||||
displays.length === 0 ||
|
||||
@ -779,7 +807,7 @@ function doubleClickTaskbar(
|
||||
// 清空计数
|
||||
global.doubleClickTaskbarCounter = 0;
|
||||
// 显示或隐藏
|
||||
if (mainWindow.isVisible()) {
|
||||
if (global.mainWindow.isVisible()) {
|
||||
hideMainWindow();
|
||||
} else {
|
||||
showMainWindowBefore(false);
|
||||
|
@ -5,7 +5,11 @@ import { hideMainWindow, showMainWindowBefore } from "../main/index";
|
||||
import { list as selectClassificationList } from "../classification/data";
|
||||
import { list as selectItemList } from "../item/data";
|
||||
import { run } from "../item";
|
||||
import { closeWindow, getMainBackgorunColor } from "../commons/index";
|
||||
import {
|
||||
closeWindow,
|
||||
getMainBackgorunColor,
|
||||
mainWindowExist,
|
||||
} from "../commons/index";
|
||||
import {
|
||||
createQuickSearchWindow,
|
||||
hideQuickSearchWindow,
|
||||
@ -83,10 +87,12 @@ function setShortcutKey(setting: Setting = global.setting) {
|
||||
globalShortcut.register(
|
||||
setting.general.showHideShortcutKey.replace("Win", "Super"),
|
||||
() => {
|
||||
if (global.mainWindow.isVisible()) {
|
||||
hideMainWindow();
|
||||
} else {
|
||||
showMainWindowBefore(true);
|
||||
if (mainWindowExist()) {
|
||||
if (global.mainWindow.isVisible()) {
|
||||
hideMainWindow();
|
||||
} else {
|
||||
showMainWindowBefore(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
@ -104,8 +110,10 @@ function setShortcutKey(setting: Setting = global.setting) {
|
||||
globalShortcut.register(
|
||||
classification.shortcutKey.replace("Win", "Super"),
|
||||
() => {
|
||||
// 分类
|
||||
showMainWindowBefore(true, false, classification.id);
|
||||
if (mainWindowExist()) {
|
||||
// 分类
|
||||
showMainWindowBefore(true, false, classification.id);
|
||||
}
|
||||
}
|
||||
);
|
||||
} catch (e) {
|
||||
@ -123,17 +131,19 @@ function setShortcutKey(setting: Setting = global.setting) {
|
||||
globalShortcut.register(
|
||||
item.shortcutKey.replace("Win", "Super"),
|
||||
() => {
|
||||
// flag
|
||||
let flag = true;
|
||||
// 是否开启勿扰模式
|
||||
if (global.setting.general.notDisturb) {
|
||||
if (global.addon.isFullscreen()) {
|
||||
flag = false;
|
||||
if (mainWindowExist()) {
|
||||
// flag
|
||||
let flag = true;
|
||||
// 是否开启勿扰模式
|
||||
if (global.setting.general.notDisturb) {
|
||||
if (global.addon.isFullscreen()) {
|
||||
flag = false;
|
||||
}
|
||||
}
|
||||
if (flag) {
|
||||
// 项目
|
||||
run("main", "open", item);
|
||||
}
|
||||
}
|
||||
if (flag) {
|
||||
// 项目
|
||||
run("main", "open", item);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@ -5,7 +5,7 @@ import {
|
||||
newItem,
|
||||
} from "../../commons/utils/common";
|
||||
import { CommonItem, Item } from "../../types/item";
|
||||
import { parse, join, extname } from "node:path";
|
||||
import { parse, join } from "node:path";
|
||||
import { readdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
|
||||
import xml2js from "xml2js";
|
||||
import { newCommonItem, newCommonItemData } from "../../commons/utils/common";
|
||||
@ -43,11 +43,6 @@ process.parentPort.once("message", async (event) => {
|
||||
res = await getStartMenuItemList(dataParam);
|
||||
} else if (params.name === "getAppxItemList") {
|
||||
res = await getAppxItemList();
|
||||
} else if (params.name === "getDropItemInfo") {
|
||||
res = await getDropItemInfo(
|
||||
dataParam.classificationId,
|
||||
dataParam.pathList
|
||||
);
|
||||
} else if (params.name === "refreshItemIcon") {
|
||||
res = await refreshItemIcon(dataParam);
|
||||
} else if (params.name === "getDirectoryItemList") {
|
||||
@ -558,90 +553,6 @@ function getPropertiesIcon(installLocation: string, result: any) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过路径获取项目信息
|
||||
* @param classificationId
|
||||
* @param pathList
|
||||
*/
|
||||
async function getDropItemInfo(
|
||||
classificationId: number,
|
||||
pathList: Array<string>
|
||||
) {
|
||||
// 项目列表
|
||||
let itemList: Array<Item> = [];
|
||||
// 解析文件信息并添加项目
|
||||
for (const path of pathList) {
|
||||
try {
|
||||
// item
|
||||
let item = newItem({ classificationId });
|
||||
// 目标
|
||||
item.data.target = path;
|
||||
// 名称
|
||||
item.name = getFileName(item.data.target);
|
||||
// 判断是否是快捷方式,如果是的话,需要获取真实路径
|
||||
if (mime.getType(path) === "application/x-ms-shortcut") {
|
||||
// 快捷方式
|
||||
// 获取真实文件路径和参数
|
||||
let shortcutInfo: ShortcutInfo | null =
|
||||
global.addon.getShortcutFileInfo(path);
|
||||
if (shortcutInfo) {
|
||||
// 路径
|
||||
if (shortcutInfo.target) {
|
||||
item.data.target = shortcutInfo.target;
|
||||
}
|
||||
// 参数
|
||||
if (shortcutInfo.arguments) {
|
||||
item.data.params = shortcutInfo.arguments;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 获取图标
|
||||
item.data.icon = await getFileIcon(item.data.target);
|
||||
// 获取后缀,判断是否是url
|
||||
let ext = extname(item.data.target);
|
||||
if (ext && ext.toLowerCase() === ".url") {
|
||||
// url
|
||||
let url = parseUrlFileContent(readFileSync(item.data.target, "utf-8"));
|
||||
if (url && url.trim() !== "") {
|
||||
item.data.target = url;
|
||||
item.type = 2;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// 文件类型
|
||||
let stats = statSync(item.data.target);
|
||||
item.type = stats.isFile() ? 0 : 1;
|
||||
}
|
||||
// 去掉后缀
|
||||
if (item.type === 0 || item.type === 2) {
|
||||
item.name = deleteExtname(item.name);
|
||||
}
|
||||
// push
|
||||
itemList.push(item);
|
||||
} catch (e) {}
|
||||
}
|
||||
return itemList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析.url文件内容以获取URL
|
||||
* @param content
|
||||
* @returns
|
||||
*/
|
||||
function parseUrlFileContent(content: string) {
|
||||
if (content) {
|
||||
const lines = content.split("\n");
|
||||
for (const line of lines) {
|
||||
if (line.startsWith("URL=")) {
|
||||
const url = line.substring(4).trim();
|
||||
return url;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新项目图标
|
||||
* @param itemList
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "dawn-launcher",
|
||||
"productName": "Dawn Launcher",
|
||||
"version": "1.4.7",
|
||||
"version": "1.5.1",
|
||||
"main": "dist-electron/main/index.js",
|
||||
"description": "Windows 快捷启动工具,帮助您整理杂乱无章的桌面,分门别类管理您的桌面快捷方式,让您的桌面保持干净整洁。",
|
||||
"author": "FanChenIO",
|
||||
|
@ -201,12 +201,3 @@ fn shell_execute(operation: String, file: String, params: String, start_location
|
||||
fn system_item_execute(target: String, params: Option<String>) {
|
||||
windows::system_item_execute(&target, params.as_deref())
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断文件是否有以管理员身份运行权限
|
||||
*/
|
||||
#[allow(dead_code)]
|
||||
#[napi]
|
||||
fn has_runas(path: String) -> bool {
|
||||
windows::has_runas(path)
|
||||
}
|
||||
|
101
rust/windows.rs
101
rust/windows.rs
@ -42,15 +42,14 @@ use windows::{
|
||||
Shell::{
|
||||
BHID_SFUIObject, IContextMenu, IShellItem, IShellItemImageFactory, IShellLinkW,
|
||||
SHCreateItemFromParsingName, SHEmptyRecycleBinW, SHQueryUserNotificationState,
|
||||
ShellLink, CMF_NORMAL, CMINVOKECOMMANDINFO, GCS_VERBA, QUNS_ACCEPTS_NOTIFICATIONS,
|
||||
QUNS_APP, QUNS_BUSY, QUNS_NOT_PRESENT, QUNS_PRESENTATION_MODE, QUNS_QUIET_TIME,
|
||||
ShellLink, CMF_NORMAL, CMINVOKECOMMANDINFO, QUNS_ACCEPTS_NOTIFICATIONS, QUNS_APP,
|
||||
QUNS_BUSY, QUNS_NOT_PRESENT, QUNS_PRESENTATION_MODE, QUNS_QUIET_TIME,
|
||||
QUNS_RUNNING_D3D_FULL_SCREEN, SHERB_NOSOUND, SIIGBF_ICONONLY, SLGP_UNCPRIORITY,
|
||||
},
|
||||
WindowsAndMessaging::{
|
||||
CallNextHookEx, CreatePopupMenu, DestroyMenu, FindWindowW, GetClassNameW,
|
||||
GetCursorPos, GetForegroundWindow, GetMenuItemCount, GetMenuItemInfoA,
|
||||
GetSystemMetrics, GetWindowRect, SendMessageW, SetForegroundWindow,
|
||||
SetWindowsHookExW, TrackPopupMenu, WindowFromPoint, HHOOK, MENUITEMINFOA, MIIM_ID,
|
||||
GetCursorPos, GetForegroundWindow, GetSystemMetrics, GetWindowRect, SendMessageW,
|
||||
SetForegroundWindow, SetWindowsHookExW, TrackPopupMenu, WindowFromPoint, HHOOK,
|
||||
MSLLHOOKSTRUCT, SC_MONITORPOWER, SM_CXSCREEN, SM_CYSCREEN, SW_NORMAL, TPM_NONOTIFY,
|
||||
TPM_RETURNCMD, WH_MOUSE_LL, WM_LBUTTONDOWN, WM_LBUTTONUP, WM_MBUTTONDOWN,
|
||||
WM_MBUTTONUP, WM_MOUSEHWHEEL, WM_MOUSEMOVE, WM_MOUSEWHEEL, WM_RBUTTONDOWN,
|
||||
@ -722,13 +721,8 @@ pub fn shell_execute(
|
||||
start_location: Option<String>,
|
||||
) {
|
||||
thread::spawn(move || {
|
||||
let mut operation = operation;
|
||||
// 判断是否是runas,如果是的话,需要判断文件是否有以管理员身份运行的权限,如果没有改为open
|
||||
if operation == "runas" {
|
||||
if !has_runas(file.clone()) {
|
||||
operation = String::from("open");
|
||||
}
|
||||
}
|
||||
// 是否是打开文件夹
|
||||
let is_dir = operation == "explore";
|
||||
// dir
|
||||
let dir = start_location.unwrap_or_else(|| {
|
||||
// 判断是否是文件夹
|
||||
@ -741,6 +735,10 @@ pub fn shell_execute(
|
||||
path.parent().unwrap().display().to_string()
|
||||
}
|
||||
});
|
||||
// 文件夹
|
||||
let dir_param = format!("\"{}\"", file.to_string());
|
||||
let dir_param = HSTRING::from(dir_param.as_str());
|
||||
let dir_param = PCWSTR(dir_param.as_ptr());
|
||||
// HSTRING
|
||||
let operation = HSTRING::from(operation.as_str());
|
||||
let file = HSTRING::from(file.as_str());
|
||||
@ -752,8 +750,18 @@ pub fn shell_execute(
|
||||
let params = PCWSTR(params.as_ptr());
|
||||
let dir = PCWSTR(dir.as_ptr());
|
||||
unsafe {
|
||||
// execute
|
||||
ShellExecuteW(None, operation, file, params, dir, SW_SHOWDEFAULT);
|
||||
if is_dir {
|
||||
ShellExecuteW(
|
||||
None,
|
||||
w!("open"),
|
||||
w!("explorer.exe"),
|
||||
dir_param,
|
||||
None,
|
||||
SW_SHOWDEFAULT,
|
||||
);
|
||||
} else {
|
||||
ShellExecuteW(None, operation, file, params, dir, SW_SHOWDEFAULT);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -796,68 +804,3 @@ pub fn system_item_execute(target: &str, params: Option<&str>) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断文件是否有以管理员身份运行权限
|
||||
*/
|
||||
pub fn has_runas(path: String) -> bool {
|
||||
// IShellItem
|
||||
let path = HSTRING::from(path);
|
||||
if let Ok(shell_item) =
|
||||
unsafe { SHCreateItemFromParsingName::<_, _, IShellItem>(PCWSTR(path.as_ptr()), None) }
|
||||
{
|
||||
// IContextMenu
|
||||
if let Ok(context_menu) =
|
||||
unsafe { shell_item.BindToHandler::<_, IContextMenu>(None, &BHID_SFUIObject) }
|
||||
{
|
||||
// Menu
|
||||
if let Ok(menu) = unsafe { CreatePopupMenu() } {
|
||||
// 写入菜单
|
||||
if let Ok(()) =
|
||||
unsafe { context_menu.QueryContextMenu(menu, 0, 1, 0x7FFF, CMF_NORMAL) }
|
||||
{
|
||||
// 获取菜单总数
|
||||
let count = unsafe { GetMenuItemCount(menu) };
|
||||
// 循环每一项菜单
|
||||
for i in 0..count {
|
||||
// 获取菜单信息
|
||||
let mut menu_info = MENUITEMINFOA::default();
|
||||
menu_info.cbSize = std::mem::size_of::<MENUITEMINFOA>() as u32;
|
||||
menu_info.fMask = MIIM_ID;
|
||||
if unsafe { GetMenuItemInfoA(menu, i as u32, true, &mut menu_info) }
|
||||
.as_bool()
|
||||
{
|
||||
// idcmd
|
||||
let idcmd = menu_info.wID as usize - 1;
|
||||
// 菜单项比如在指定范围内
|
||||
if idcmd >= 1 && idcmd <= 0x7FFF {
|
||||
// 获取菜单命令信息
|
||||
let mut verb = [0u8; 256];
|
||||
let pstr = PSTR(verb.as_mut_ptr());
|
||||
if let Ok(()) = unsafe {
|
||||
context_menu.GetCommandString(
|
||||
menu_info.wID as usize - 1,
|
||||
GCS_VERBA,
|
||||
None,
|
||||
pstr,
|
||||
verb.len() as u32,
|
||||
)
|
||||
} {
|
||||
if let Ok(command) = unsafe { pstr.to_string() } {
|
||||
if command.to_lowercase() == "runas" {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
DestroyMenu(menu);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
@ -34,7 +34,7 @@
|
||||
/>
|
||||
<p class="mt-4">Dawn Launcher {{ version }}</p>
|
||||
<p class="mt-2">
|
||||
Copyright © 2022-2024 Dawn Launcher. All Rights Reserved
|
||||
Copyright © 2022-2025 Dawn Launcher. All Rights Reserved
|
||||
</p>
|
||||
<p class="mt-2">
|
||||
{{ store.language.officialWebsite }}{{ store.language.colon
|
||||
|
@ -523,6 +523,8 @@ onMounted(() => {
|
||||
// 监听显示窗口之前
|
||||
listens.push(
|
||||
window.main.onShowWindowBefore((data) => {
|
||||
// 隐藏搜索
|
||||
store.search = false;
|
||||
if (classificationContentRef.value) {
|
||||
// 如果分类ID不为空的话选择分类ID
|
||||
let selectedClassificationId: number | null =
|
||||
|
@ -130,6 +130,7 @@ import {
|
||||
setItemWidth,
|
||||
run,
|
||||
removeInvalidItem,
|
||||
showItemList,
|
||||
} from "../js";
|
||||
import ItemList from "./List.vue";
|
||||
import { Item } from "../../../../types/item";
|
||||
@ -315,12 +316,21 @@ function createItemSortable() {
|
||||
let fromClassificationId = parseInt(
|
||||
event.from.getAttribute("classification-id")!
|
||||
);
|
||||
// 当前项目
|
||||
const currentItem =
|
||||
getItemListByClassificationId(fromClassificationId)[
|
||||
event.oldIndex
|
||||
];
|
||||
fromIdList.push(currentItem.id);
|
||||
let fromClassification =
|
||||
getClassificationById(fromClassificationId);
|
||||
if (fromClassification) {
|
||||
let itemList =
|
||||
getItemListByClassificationId(fromClassificationId);
|
||||
if (itemList) {
|
||||
let copyItemList = JSON.parse(JSON.stringify(itemList));
|
||||
// 可能会存在自定义排序的情况,所以需要按照指定的排序方式获取项目
|
||||
const currentItem = showItemList(
|
||||
copyItemList,
|
||||
fromClassification
|
||||
)[event.oldIndex];
|
||||
fromIdList.push(currentItem.id);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 批量操作
|
||||
for (const value of store.itemBatchOperationDataArray) {
|
||||
|
Loading…
Reference in New Issue
Block a user