當前位置:
首頁 > 知識 > 使用JS開發桌面端應用程序NW.js-3-開發問題小記

使用JS開發桌面端應用程序NW.js-3-開發問題小記


前言

因為我們的項目是2C的,而XP系統是最大的用戶量佔比,所以只能使用nw開發而不能用Electron,本文謹記開發nw過程中遇到的各種問題以及解決方案。


nw.Window.open打開新窗口不能設定指定位置

問題描述:

nw.Window.open打開新窗口API中的參數option中position欄位只能指定為centermouse。如字面含義:center為屏幕正中央,mouse為滑鼠當前位置。

幾乎可以推測,nw的滑鼠右鍵菜單應該也是使用此介面,明顯是為了彈出右鍵菜單用的,除此之外幾乎沒有別的應用場景可以用到新打開窗口在滑鼠位置的。

所以,在nw的打開新窗口功能中,其實可以說 只能顯示在屏幕正中央。

nw.Window.open("http://xxcanghai.cnblogs.com/", {
//打開新窗口的參數Option
width:500,
height:500,
show:true,//是否顯示新窗口
position:"center"//新窗口顯示位置,只能使用center或mouse
}, function(new_win) {
console.log("已打開新窗口");
});

官網對position的描述:

position

{String}benullorcenterormouse, controls where window will be put

解決方案:

一句話就是,先open一個隱藏窗口,之後在callbcal裡面再重設其位置,再顯示出來

詳細步驟:

1、重新封裝nw.Window.open方法,在原有的position欄位上擴充四個屬性,分別是 左上角,左下角,右上角,右下角,這裡使用枚舉對象來定義。

/**
* 擴充打開新窗口參數
*
* @export
* @interface openWindowOption
* @extends {NWJS_Helpers.WindowOpenOption}
*/
export interface openWindowOption extends NWJS_Helpers.WindowOpenOption {
/**
* 控制打開的新窗口的所在位置
*/
position?: "left_top" | "left_bottom" | "right_top" | "right_bottom" |
"center" | "mouse" | null;
}
/**
* 打開一個新窗口
*
* @export
* @param {string} url 新窗口的url
* @param {openWindowOption} [option] 新窗口的參數
* @param {(new_win?: NWJS_Helpers.win) => void} [callback] 打開成功後的回調函數,返回新窗口的nwWindow對象
*/
export function openWindow(url: string, option: openWindowOption = {}, callback: (new_win?: NWJS_Helpers.win) => void = function { }) {
/** 新增支持的窗口位置值,左上角,左下角,右上角,右下角 */
enum winPositionEnum {
left_top = "left_top",
left_bottom = "left_top",
right_top = "right_top",
right_bottom = "right_bottom"
};

/** 新窗口位置的4個英文字元串數組 */
const winPosiEnumArr: string = Object.keys(winPositionEnum);
}

2、雖然擴充了默認position屬性,但真正傳給nw的還得是他支持的,所以增加判斷如果使用的是新增欄位,則保存用戶自定義設置,同時改寫option參數。 除此之外,因為要統一隱藏窗口,所以還要改寫默認的show屬性,保存用戶設定的是否顯示窗口,隱藏打開窗口後,當設定完位置後再手動設置用戶初始設定的show選項。

option = Object.assign({
show: true
}, option);

/** 用戶傳過來的窗口位置參數字元串 */
var optPosi: string = "";

//如果用戶傳過來的position參數為我自定義的,則移除原有值
if (typeof option.position === "string" && winPosiEnumArr.indexOf(option.position) >= 0) {
optPosi = option.position;
delete option.position;
}

/** 用戶傳過來的窗口是否隱藏選項 */
var optShow: boolean = option.show;
option.show = false;

3、執行真正的nw.Window.open,同時在打開後的callback中根據自定義位置選項重新設定窗口位置。 最後再還原用戶原本設定的show屬性,以及觸發用戶原本傳進來的callback回調函數。

nw.Window.open(url, option, function (nwWin: NWJS_Helpers.win) {
/** 打開的隱藏窗口的寬度和高度 */
var { width, height } = nwWin;

/** 獲取第一個顯示器對象 */
const screen: NWJS_Helpers.screen = nw.Screen.screens[0];

/** 獲取顯示器的可用工作區域 */
const area = screen.work_area;

/** nw的chrome殼子的四個邊框高度 */
const border = {
left: 5 * screen.scaleFactor,
right: 5 * screen.scaleFactor,
top: 24 * screen.scaleFactor,
bottom: 5 * screen.scaleFactor
}
if (optPosi.length > 0) {
let x: number = nwWin.x;
let y: number = nwWin.y;
if (option.frame == undefined || option.frame == true) {
width += border.left + border.right;
height += border.top + border.bottom;
}
if (optPosi == winPositionEnum.left_top) {
x = 0;
y = 0;
} else if (optPosi == winPositionEnum.left_bottom) {
x = 0;
y = area.height - height;
} else if (optPosi == winPositionEnum.right_top) {
x = area.width - width;
y = 0;
} else if (optPosi == winPositionEnum.right_bottom) {
x = area.width - width;
y = area.height - height;
}

nwWin.x = Math.round(x);
nwWin.y = Math.round(y);
}
//還原用戶默認設定是否顯示窗口
if (optShow) {
nwWin.show;
}
//觸發用戶傳進來的callback
return callback.apply(this, Array.prototype.slice.call(arguments));
});

4、因為我只需要在四個角顯示,所以只擴充了4個枚舉類型,如果需要在指定坐標(x,y)顯示窗口,以上同理增加對position的對象類型{x:number,y:number}檢測處理即可。


nw的系統API-openExternal在XP系統下無法打開本地磁碟路徑

問題描述:

nwjs官方提供了有關Shell相關的API,提供了簡單桌面相關操作的介面。之所說他簡單,是因為簡直太太太簡單甚至寒酸了,只有3個API分別是:

Shell.openExternal(uri)打開外部鏈接;

Shell.openItem(file_path)使用系統默認打開方式打開文件;

Shell.showItemInFolder(file_path)和在資源管理器中顯示某文件


// Open URL with default browser.

nw.Shell.openExternal("https://github.com/nwjs/nw.js");

其中openExternal介面可以使用系統默認瀏覽器打開鏈接,也可以使用系統資源管理器打開某本地磁碟路徑文件夾。此介面在Win7系統下沒有問題,但是在XP系統下無法打開本地磁碟路徑。

原因未知!

解決方案:

做操作系統類型判斷,在XP系統下利用child_process.exec方法,執行系統cmd命令行:start explorer + 路徑來解決。

// 導入操作系統信息模塊
import os = require("os");
// 導入子進程模塊
import child_process = require("child_process");

/**
* 打開文件夾或用默認瀏覽器打開網頁鏈接
*
* @param {string} uri 文件夾路徑或網頁鏈接
*/
export function openExternal(uri: string): void {
if (typeof uri !== "string" || uri.length == 0) {
return null;
}
var isxp = (os.type === "Windows_NT") && (os.release.indexOf("5") >= 0);
if (isxp) {
child_process.exec("start explorer " + uri);// XP下使用explorer打開文件夾或網頁
} else {
return nw.Shell.openExternal(uri);
}
}

關於Nodejs的OS模塊:

主要提供獲取操作系統的各類信息,此處使用了os.typeos.release兩個方法。

os.type方法返回一個字元串,表明操作系統的名字,"Linux"表示在 Linux系統上,"Darwin"表示在 macOS 系統上,"Windows_NT"表示在 Windows系統上。

os.release方法返回一個字元串, 指定操作系統的發行版。

關於windows系統的發行版本號:

其中:

"5.0.*"為windows 2000系統;

"5.1.*"為windows XP系統;

"5.2.*"為windows XP 64位以及windows Server 2003系統

所以上述代碼中做了只要以"5"開頭的都匹配。

使用JS開發桌面端應用程序NW.js-3-開發問題小記

?

使用JS開發桌面端應用程序NW.js-3-開發問題小記

?

關於Nodejs執行系統命令行:

首先使用了Nodejs的核心模塊:child_process子進程模塊,其中的exec方法。對此官方對exec方法的描述是:

child_process.exec(command[, options][, callback])

command
options< Object> 參數
callback
衍生一個 shell,然後在 shell 中執行 command,且緩衝任何產生的輸出。

此處的shell在windows系統上就是cmd.exe命令行(命令提示符)。

關於NodeJs如何在windows系統上執行.bat和.cmd批處理文件官網有更加詳細的解釋:http://nodejs.cn/api/en/child_process.html#child_process_spawning_bat_and_cmd_files_on_windows

關於windows系統內置命令 start

此處使用了windows系統命令提示符的系統內置命令:start

他可以用來啟動各種內部命令,也可以啟動外部應用程序。此處啟動了explorer就屬於全局外部應用程序。

關於start命令的用法與解釋:(可以在命令行中使用start/?獲得)


啟動一個單獨的窗口運行指定的程序或命令

START ["title"] [/D path] [/I] [/MIN] [/MAX][command/program] [parameters]

"title" 在窗口標題欄中顯示的標題

path 啟動目錄。新的環境將是傳遞給 cmd.exe 的原始環境,而不是當前環境

MIN 以最小化方式啟動窗口

MAX 以最大化方式啟動窗口

...省略...

在此處我使用的是用start命令啟動explorer程序。

關於windows系統的explorer.exe

explorer.exe是Windows程序管理器或者文件資源管理器,它用於管理Windows圖形殼。

簡單的來講,explorer就是我們的桌面,打開的所有磁碟或文件夾的應用程序。利用他可以實現:

1、使用系統註冊的默認方法打開某文件。

2、打開本地磁碟路徑某文件夾。

3、使用系統默認瀏覽器打開url地址。

4、以及調用任何在系統里註冊過的各類協議地址,如ftp://或是mailto:***等並用其註冊的應用程序打開。

而在explorer後面跟著文件夾地址即可實現使用資源管理器打開目錄,以及打開網頁鏈接

explorer的其他參數詳解:


Explorer.exe

Command-line switches that you can use to open the GUI Windows Explorer (Explorer.exe).

Options

/eOpen Windows Explorer in its default view.

(,)/root,objectOpen the specified object in a window view.

/select,objectOpen a window view with the specified folder, file or application selected.

/separateLaunch the explorer instance as a separate process.

(This is an undocumented feature)

Node.js的child_process.exec執行命令的返回值中文亂碼

問題描述:

Nodejs的子線程模塊child_process的執行系統命名的介面exec,當命令返回所有非中文字元時都會亂碼。

如執行一個date /t的命令顯示當前日期時間代碼:

child_process.exec("date /t", {}, function (error: Error, stdout: string, stderr: string) {
console.log(stdout);
})

正常應該返回:

使用JS開發桌面端應用程序NW.js-3-開發問題小記

?

但實際上返回了:

使用JS開發桌面端應用程序NW.js-3-開發問題小記

?

經查NodeJs默認使用了UTF-8編碼,而中文操作系統的命令行的返迴流均為GB2312編碼,而在流轉字元串時再使用UTF-8解碼就導致了亂碼,而且沒辦法還原。

解決方案:

1、先通過child_process.exec方法的option參數中的encoding欄位設定為"base64"。另其返回值不包含亂碼

child_process.exec("date /t", {
encoding : "base64"//設定base64編碼
}, function (error: Error, stdout: string, stderr: string) {
console.log(stdout);
})

效果如下:

使用JS開發桌面端應用程序NW.js-3-開發問題小記

?

2、再通過一個Node編解碼模塊iconv-lite,將返回值字元串再用base64編碼,最後用GB2312解碼。

import iconv = require("iconv-lite");
child_process.exec("date /t", {
encoding:"base64"
}, function (error: Error, stdout: string, stderr: string) {
console.log("解碼前:",stdout);
stdout = iconv.decode(iconv.encode(stdout, "base64"), "gb2312");
console.log("解碼後:",stdout);
})

如下圖,解決了中文亂碼問題:

使用JS開發桌面端應用程序NW.js-3-開發問題小記

?

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 達人科技 的精彩文章:

nodejs伺服器部署教程二
OpenStack(企業私有雲)萬里長征第五步——虛擬機Migrate&Resize
jsonp的原理和實現
xtrabackup備份mysql資料庫的使用方法

TAG:達人科技 |

您可能感興趣

純前端開發案例:用 SpreadJS 搭建信息系統軟體開發平台
Mapbox發布新SDK幫助開發人員開發AR導航應用程序
SuperSU開發者宣布:將停止開發所有ROOT應用
Vue.js 2.0 漸進開發應用實踐
在「小程序」PWA上開發WebRTC
SpringBoot2快速開發應用系統:開篇
谷歌發布ARCore 1.0,程序員如何開發AR應用?
Wine 3.2開發版發布
Wine 3.1開發版發布
Wine 3.6開發版本發布了 支持PNG格式圖標!
《Superhot VR》開發商:正在開發一款硬核VR體驗
SpringMVC 開發 — 使用 Swagger 搭建介面請求頁面
Sumerian VR開發工具向公眾開放使用
使用C#開發Android應用之WebApp
GENKI為任天堂Switch主機開發Type-C介面藍牙音頻發射器
蘋果發布Siri快捷方式測試版,iOS 12開發者提前使用
集70萬+開發者,APICloud為IoT定製了一個應用開發生態
Windows漏洞利用開發教程Part 5:返回導向編程
GENKI為Switch主機開發Type-C介面藍牙音頻發射器
華為AI開發平台HiKey 970助力開發者打造各種的AI應用