其实javascript不仅可以做网页应用,也可以不依赖任何环境开发windows应用程序。windows系统自带mshta.exe,相当于一个javascript虚拟机,我们把.html文件扩展名改成.hta文件,网页就变成了hta应用程序,双击就可以执行。当然hta可以操作本地文件数据库等,功能比html强大许多,可以开发C/S应用程序。本人之前是个后台程序员,后来我转行之后,就成了编程的业余爱好者,今天这个demo使用了javascript和少许c++,仅供大家娱乐,参考,谨慎用于生产环境。
先给大家上几张图,看一下javascript开发的windows应用效果,然后再上代码。这个demo是个音乐播放器,功能只有扫描磁盘上的音频文件随机播放。
也有一个搜索功能,搜索随机播放列表中的歌曲,简单的正则匹配
测试发现占用内存和cpu很低。
最后楼主用c++给他做了个exe壳子,这样就能把他设置为默认播放器了,双击音频文件就能用楼主开发的播放器打开,效果如下图
大家可能也能看出,我用的html中的<audio>标签,audio标签支持mp3、m4a、ogg等格式,大家也可以用<embed>标签,embed标签支持的格式还多,还支持wma、aac、wav等格式,但是前提是电脑安装了windows media player,楼主电脑window media player坏了,所以楼主用了<audio>标签。
最终软件包含三个文件,app.ico是图标,main.hta就是楼主用javascript开发的windows应用程序,双击就可以打开,main.exe是楼主给他做的壳子,用于双击打开音频文件通过命令行将文件路径传递给main.hta。下面先上main,hta的代码,里面基本上和普通javascript语法相同,只是有一些用到了ActiveX控件的对象。
<!doctype html>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=9" >
<title>小小播放器v1.0</title>
<script>
//窗体初始化
(function(){
window.resizeTo(400,80);
}())
</script>
<!-- hta应用程序特有标签 -->
<hta:application
id=musicPlayer
scroll=no
innerborder=no
icon=app.ico
contextMenu=no
selection=no
>
<style>
body{background: #ccc;text-align: center;}
button{
font-size: 22px;
color:#38f;
background: #fff;
border:1px solid #fff;
border-radius: 10px;
cursor: pointer;
}
input[type='text']{
position: relative;
bottom:4px;
font-size: 12px;
padding:5px;
color:#38f;
background: #fff;
border:1px solid #fff;
border-radius: 10px;
width: 100px;
}
</style>
<body>
<!-- 视图模块 -->
<audio
style="width:100%;"
id="mediaPlayer"
onended="sys.next()"
autoplay="autoplay"
onerror="sys.error()"
src="">
</audio>
<div id="normalPanel">
<button title="上一曲"
onclick="sys.last()"
>◄◄</button>
<button title="暂停" style="border-radius: 24px;padding-bottom: 5px;"
onclick="if(sys.playerHandel.paused){sys.playerHandel.play();this.innerText='■';this.title='暂停'}else{sys.playerHandel.pause();this.innerText='►';this.title='播放'}"
>■</button>
<button title="下一曲"
onclick="sys.next()"
>►►</button>
<input type="text" id="findInp" value="关键字搜索..."
onclick="if(this.value=='关键字搜索...'){this.value=''}"
/>
<button title="搜索"
onclick="sys.find()"
>F</button>
<button title="关于"
onclick="sys.about()"
>A</button>
</div>
<div id="abnormalPanel"
style="display:none;"
>
<button title="关于"
onclick="sys.about()"
>A</button>
<span style="padding: 5px;" id="abnormalPanelShowName"></span>
</div>
</body>
<script>
/**
* 小小播放器
* @type {Object}
*/
this.windowsForm={
Text:function(str){
document.title=str;
}
}
this.commandLine=musicPlayer.commandLine.split(" ");//接收命令行参数
commandLine[0]="";
commandLine=commandLine.join(" ");
this.sys={
appName:"小小播放器v1.0",
playList:[],actNum:1,totalNum:0,playerHandel:document.getElementById("mediaPlayer"),
getPlaylist:function(){
/*枚举音频文件取得播放列表*/
var data=[];
var fso=new ActiveXObject("Scripting.FileSystemObject");
var f=fso.GetFolder("F:\\音乐");
var fc=new Enumerator(f.files);
var fileType=/(.mp3|.m4a|.wav)/i;
for (; !fc.atEnd(); fc.moveNext()){
if(fileType.test(fc.item())){
data.push(fc.item());
}
}
data.sort(function() {
return (0.5-Math.random());
})
this.playList=data;
this.totalNum=data.length;
},
main:function(){//应用程序入口
this.getPlaylist();
this.play(1);
},
play:function(num){
this.playerHandel.setAttribute("src","null");
this.playerHandel.setAttribute("src",""+this.playList[num-1]);
this.actNum=num;
windowsForm.Text(this.appName+"[♫"+this.playList[num-1].name+"]");
},
next:function(){
this.actNum=this.actNum==this.totalNum?1:this.actNum+1;
this.play(this.actNum);
},
last:function(){
this.actNum=this.actNum==1?this.totalNum:this.actNum-1;
this.play(this.actNum);
},
find:function(){
/*搜索歌曲*/
var keyWd=document.getElementById("findInp").value;
var str="<style>.musicItem{padding: 5px;margin:5px;border:1px solid #38f;background: #38f;color:#fff;font-size: 20px;border-radius:10px;cursor:pointer;}.musicItem:hover{padding: 5px;margin:5px;border:1px solid #38f;background: #fff;color:#38f;font-size: 20px;border-radius:10px;cursor:pointer;}</style><div style='position:absolute;left:0px;top:0px;width:100%;height:100%;overflow-y:auto;'>";
for(var i=0;i<this.playList.length;i++){
if(RegExp(keyWd,"i").test(this.playList[i].name)){
str+="<div class='musicItem' onclick=parent.sys.play("+(i+1)+")>";
str+=this.playList[i].name;
str+="</div>";
}
}
str+="</div>";
var aPopup=window.createPopup();
aPopup.document.body.innerHTML=str;
aPopup.show(window.screenX, window.screenY+82,400,300);
},
about:function(){
var str="about:";
str+="<title>关于-小小播放器v1.0</title>";
str+="<body style='text-align:justify;font-size:24px;background:#ccc;padding:10px;text-align:center;'><img src='app.ico'/><h1 style='font-size:36px;'>小小播放器v1.0</h1><hr><p>版权所有:© 2019 sdxjwkq01</p><p style='text-align:left;'> 小小播放器是一款小巧的音乐播放器,使用<span style='color:#ffa533;background:#fff;'>javascript</span>和<span style='color:#2d78f4;background:#fff;'>c++</span>开发,占用极低的内存及cpu,可以快速枚举出音乐库所有音乐并随机播放。支持音频格式为:mp3,m4a,wav。</p></body>";
showModalDialog(str);
},
error:function(){
alert("很抱歉!应用程序发生错误:\n\r音频格式错误!");
}
}
/*正常模式和试听模式【作为默认播放器双击打开某个音频文件】*/
if(commandLine!=" null"&&commandLine!=" "){
window.resizeTo(500,140);
document.getElementById("normalPanel").style.display="none";
document.getElementById("abnormalPanel").style.display="block";
var musicTitle=commandLine.split("\\");
document.getElementById("abnormalPanelShowName").innerHTML=musicTitle[musicTitle.length-1];
sys.playerHandel.setAttribute("controls","controls");
sys.playerHandel.onended=function(){sys.playerHandel.play()};
sys.playerHandel.setAttribute("src",commandLine);
sys.playerHandel.play();
}else{
sys.main();
this.onkeydown=function(e){
switch(e.keyCode){
case 39:{
sys.next();//->键
break;
}
case 37:{
sys.last();//<-键
break;
}
default:;
}
}
}
</script>
里面有注释,代码很简单,就是扫描“F:\\音乐"文件夹下所有文件,枚举出音频文件存到数组,打乱顺序,开始播放,监听audio标签。大家也可以改成扫描全盘文件,这个需要用递归实现,也要用到ActiveX控件的FileSystem对象。
到这里,音乐播放器主程序就实现了,下面讲一下他的壳子,main.exe
本来想用c#做exe文件的,不过,考虑到有一些电脑没有.net环境,可能会运行失败,所以后来改成了c++实现,下面先上代码。
#include <iostream>
#include <windows.h>
#include <string>
using namespace std;
/**
* [main 应用程序入口]
* @param argc [参数个数]
* @param argv [参数指针]
* @return [description]
*/
int KillProcessByTitle(const char* sWindowName);
int main(int argc,char **argv) {
char **temp = argv;//接收参数指针
string exePath=*temp;
/*exe文件寻址*/
exePath=exePath.replace(exePath.find("main.exe"),8,"")+"main.hta";
/*string转char* */
const char* htaPath=exePath.c_str();
KillProcessByTitle("小小播放器v1.0");
if(argc==2){
++temp;
ShellExecute(NULL, NULL, htaPath, *temp, NULL, SW_HIDE);
}else{
ShellExecute(NULL, NULL, htaPath, "null", NULL, SW_HIDE);
}
return 0;
}
/**
* [KillProcessByTitle 根据窗口名称关闭窗口]
* @param sWindowName [description]
* @return [description]
*/
int KillProcessByTitle(const char* sWindowName)
{
HWND hWindow=FindWindow(NULL,sWindowName);
if(hWindow==NULL)
{
return 1;
}
PostMessage(hWindow,WM_CLOSE,0,0);//向窗口发送WM_CLOSE消息关闭对话框窗口,如果该对话框是进程的子对话框则要进行后面的关闭进程操作
DWORD dwProcessID;
HANDLE hProcess;
if(GetWindowThreadProcessId(hWindow, &dwProcessID)==0)
{
return 2;
}
hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwProcessID);
if(hProcess==NULL)
{
return 3;
}
if(!TerminateProcess(hProcess, 0))
{
return 4;
}
return 0;
}
我的电脑没有vc++和vs,所以我用的gcc编译的,gcc比较小巧。
this.commandLine=musicPlayer.commandLine.split(" ");//接收命令行参数
此案例理论上支持win7及以上系统,不需要携带webkit库等乱七八糟的东西,软件体积不到1MB。这样看来,hta应用程序还是很实用的。
用javascript开发windows应用的方法就简单给大家讲到这里,此案例仅供参考,请勿用于生产环境。