aardio 文档

aardio 范例: 剪贴板查看器

import win.ui;
import win.clip;
import win.clip.viewer;
import win.clip.html;
import win.clip.png;
import win.clip.rtf;
import win.clip.file;
import win.clip.bitmap;
import win.clip.sourceUrl;
import fonts.fontAwesome;
import win.ui.simpleWindow;
/*DSG{{*/
var winform = win.form(text="剪贴板查看器";right=959;bottom=619;bgcolor=0xFFFFFF;border="none")
winform.add(
btnClear={cls="plus";text="清空";left=620;top=0;right=691;bottom=31;align="left";color=0xFFFFFF;dr=1;dt=1;iconStyle={align="left";font=LOGFONT(h=-14;name='FontAwesome');padding={left=10}};iconText='\uF12D';notify=1;textPadding={left=30};z=4};
btnCopyText={cls="plus";text=" 复制纯文本";left=12;top=560;right=138;bottom=590;border={color=0xDDDDDD;radius=6;width=1};color=0x555555;db=1;dl=1;iconStyle={align="left";font=LOGFONT(name='FontAwesome');padding={left=10}};iconText='\uF0C5';notify=1;textPadding={left=28};z=14};
btnDeleteHistory={cls="plus";text=" 删除选中";left=145;top=560;right=268;bottom=590;border={color=0xDDDDDD;radius=6;width=1};color=0x555555;db=1;dl=1;hide=1;iconStyle={align="left";font=LOGFONT(name='FontAwesome');padding={left=10}};iconText='\uF1F8';notify=1;textPadding={left=28};z=16};
btnPin={cls="plus";text="置顶";left=774;top=0;right=845;bottom=31;align="left";color=0xFFFFFF;dr=1;dt=1;iconStyle={align="left";font=LOGFONT(h=-14;name='FontAwesome');padding={left=10}};iconText='\uF08D';notify=1;textPadding={left=30};z=6};
btnRefresh={cls="plus";text="刷新";left=697;top=0;right=768;bottom=31;align="left";color=0xFFFFFF;dr=1;dt=1;iconStyle={align="left";font=LOGFONT(h=-14;name='FontAwesome');padding={left=10}};iconText='\uF021';notify=1;textPadding={left=30};z=5};
btnSaveImg={cls="plus";text=" 保存图像";left=145;top=560;right=268;bottom=590;border={color=0xDDDDDD;radius=6;width=1};color=0x555555;db=1;dl=1;iconStyle={align="left";font=LOGFONT(name='FontAwesome');padding={left=10}};iconText='\uF03E';notify=1;textPadding={left=28};z=15};
formatList={cls="listbox";left=12;top=80;right=268;bottom=520;db=1;dl=1;dt=1;edge=1;items={};z=10};
historyList={cls="listview";left=12;top=80;right=268;bottom=520;db=1;dl=1;dt=1;edge=1;fullRow=1;hide=1;z=11};
infoText={cls="bkplus";text="双击历史条目可直接使用";left=12;top=528;right=268;bottom=550;align="left";color=0x888888;db=1;dl=1;hide=1;z=18};
lblQuick={cls="bkplus";text='\uF0E7  快捷操作';left=12;top=530;right=268;bottom=552;align="left";color=0x333333;db=1;dl=1;font=LOGFONT(h=-13;name='FontAwesome';weight=600);z=13};
panelLeft={cls="bkplus";left=0;top=42;right=280;bottom=620;bgcolor=0xFAFAFA;db=1;dl=1;dt=1;z=7};
previewHex={cls="static";left=292;top=110;right=948;bottom=570;db=1;dl=1;dr=1;dt=1;edge=1;hide=1;hscroll=1;multiline=1;readonly=1;vscroll=1;z=24};
previewImage={cls="plus";left=292;top=110;right=948;bottom=570;border={color=0xE8E8E8;radius=6;width=1};db=1;dl=1;dr=1;dt=1;hide=1;repeat="scale";z=23};
previewText={cls="edit";left=292;top=110;right=948;bottom=570;db=1;dl=1;dr=1;dt=1;edge=1;hscroll=1;multiline=1;readonly=1;vscroll=1;z=22};
statusBar={cls="bkplus";left=0;top=578;right=960;bottom=620;bgcolor=0xF5F5F5;db=1;dl=1;dr=1;z=25};
statusIcon={cls="bkplus";text='\uF05A';left=14;top=592;right=34;bottom=612;color=0x1A73E8;db=1;dl=1;font=LOGFONT(h=-14;name='FontAwesome');z=26};
statusText={cls="bkplus";text="就绪";left=40;top=594;right=650;bottom=612;align="left";color=0x666666;db=1;dl=1;dr=1;z=27};
statusTime={cls="bkplus";left=750;top=594;right=946;bottom=612;align="right";color=0x999999;db=1;dr=1;z=28};
tabFormats={cls="plus";text="格式";left=12;top=54;right=94;bottom=80;align="left";color=0x333333;dl=1;dt=1;font=LOGFONT(h=-13;weight=600);iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome');padding={left=8}};iconText='\uF0CA';notify=1;textPadding={left=30;bottom=2};z=8};
tabHex={cls="plus";text="十六进制";left=460;top=82;right=560;bottom=110;color=0x666666;dl=1;dt=1;notify=1;z=20};
tabHistory={cls="plus";text="历史";left=94;top=54;right=176;bottom=80;align="left";color=0x666666;dl=1;dt=1;font=LOGFONT(h=-13);iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome');padding={left=8}};iconText='\uF1DA';notify=1;textPadding={left=30;bottom=2};z=9};
tabHtml={cls="plus";text="HTML";left=564;top=82;right=644;bottom=110;color=0x666666;dl=1;dt=1;notify=1;z=21};
tabImage={cls="plus";text="图像";left=376;top=82;right=456;bottom=110;color=0x666666;dl=1;dt=1;notify=1;z=19};
tabPreview={cls="bkplus";text='\uF06E  预览';left=292;top=52;right=948;bottom=74;align="left";color=0x333333;dl=1;dr=1;dt=1;font=LOGFONT(h=-13;name='FontAwesome';weight=600);z=12};
tabText={cls="plus";text="文本";left=292;top=82;right=372;bottom=110;color=0x666666;dl=1;dt=1;notify=1;z=17};
titleBar={cls="bkplus";left=0;top=0;right=960;bottom=42;bgcolor=0x1A73E8;dl=1;dr=1;dt=1;z=1};
titleIcon={cls="bkplus";text='\uF0EA';left=14;top=10;right=40;bottom=34;color=0xFFFFFF;dl=1;dt=1;font=LOGFONT(h=-18;name='FontAwesome');z=2};
titleText={cls="bkplus";text="剪贴板查看器";left=46;top=12;right=220;bottom=32;align="left";color=0xFFFFFF;dl=1;dt=1;font=LOGFONT(h=-15;weight=600);z=3}
)
/*}}*/

// ========== 样式设置 ==========

// 工具栏按钮样式
var toolBtnSkin = {background={default=0x00FFFFFF;hover=0x30FFFFFF;active=0x50FFFFFF}};
winform.btnClear.skin(toolBtnSkin);
winform.btnRefresh.skin(toolBtnSkin);
winform.btnPin.skin(toolBtnSkin);

var quickBtnSkin = {
    background={default=0xFFFFFFFF;hover=0xFFF5F5F5;active=0xFFEEEEEE};
    color={default=0xFF555555;hover=0xFF1A73E8}
};
winform.btnCopyText.skin(quickBtnSkin);
winform.btnSaveImg.skin(quickBtnSkin);
winform.btnDeleteHistory.skin(quickBtnSkin);

import win.ui.tabs;
var leftTabs = win.ui.tabs(winform.tabFormats, winform.tabHistory);
leftTabs.skin({
    background={default=0x00FFFFFF;hover=0xFFF0F0F0};
    color={default=0xFF666666;hover=0xFF1A73E8};
    checked={background={default=0xFFE8F0FE};color={default=0xFF1A73E8}}
});

var previewTabs = win.ui.tabs(winform.tabText, winform.tabImage, winform.tabHex, winform.tabHtml);
previewTabs.skin({
    background={default=0x00FFFFFF;hover=0xFFF0F0F0};
    color={default=0xFF666666;hover=0xFF1A73E8};
    checked={background={default=0xFFE8F0FE};color={default=0xFF1A73E8}}
});

var clipData = {}; 
var curFormat = null;
var isPinned = false;
var clipHistory = {};
var maxHistory = 100;

var formatNames = {
    [1]="CF_TEXT (ANSI文本)";
    [2]="CF_BITMAP (位图)";
    [7]="CF_OEMTEXT";
    [8]="CF_DIB (设备无关位图)";
    [13]="CF_UNICODETEXT (Unicode)";
    [14]="CF_ENHMETAFILE";
    [15]="CF_HDROP (文件列表)";
    [9]="CF_PALETTE (调色板)";
    [16]="CF_LOCALE (本地化标识符)"; 
    [17]="CF_DIBV5";
};

var getFormatName = function(id){
    if(formatNames[id]) return formatNames[id];
    var name = win.clip.getFormatName(id);
    return name || string.format("未知格式 (0x%04X)", id);
};

var isTextFormat = function(fmtId){
    return fmtId == 13 || fmtId == 1 || fmtId == 7 
        || fmtId == win.clip.rtf.format 
        || fmtId == win.clip.sourceUrl.chromiumFormat
        || fmtId == win.clip.sourceUrl.firefoxFormat;
};

var isImageFormat = function(fmtId){
    return fmtId == 2 || fmtId == 8 || fmtId == 17 || fmtId == win.clip.png.format;
};

var isHtmlFormat = function(fmtId){
    return fmtId == win.clip.html.format;
};

import com.hexEditor;
var hexEditor = com.hexEditor(winform.previewHex);

var hideAllPreviews = function(){
    winform.previewText.show(false);
    winform.previewImage.show(false);
    winform.previewHex.show(false);
    hexEditor.setBuffer(raw.buffer("无数据"));

    winform.previewImage.background = null;
    winform.previewHex.text = "";
};

var showTextPreview = function(s){
    hideAllPreviews();
    winform.previewText.text = string.crlf(s || "", '\r\n');
    winform.previewText.show(true);
};

var showImagePreview = function(bmp){
    hideAllPreviews();
    winform.previewImage.background = bmp;
    winform.previewImage.show(true);
};

var readFormatText = function(fmtId){
    if(fmtId == 13 || fmtId == 1){
        return win.clip.read() || "(无文本)";
    }
    elseif(fmtId == 15){
        var files, eff = win.clip.file.read();
        if(files && #files > 0){
            var s = "操作: " + (eff == "move" ? "剪切" : "复制") + '\r\n文件数: ' + #files + '\r\n\r\n';
            for(i=1; #files) s = s + files[i] + '\r\n';
            return s;
        }
        return "(无文件)";
    }
    elseif(fmtId == 7){
        var buf = win.clip.data(7).read();
        return #buf ? string.fromto(buf, 1, 65001) : "(无文本)";
    }
    elseif((fmtId == win.clip.sourceUrl.chromiumFormat) || (fmtId == win.clip.sourceUrl.firefoxFormat)){
        return win.clip.sourceUrl.read() || "(无URL)";
    } 
    elseif(fmtId == win.clip.rtf.format){
        var rtf = win.clip.rtf.read();
        return rtf ? tostring(rtf) : "(无法读取RTF)";
    }

    return null;
};

var readFormatImage = function(fmtId){
    if(fmtId == 2 || fmtId == 8 || fmtId == 17){
        return win.clip.bitmap.read();
    } elseif(fmtId == win.clip.png.format){
        var png = win.clip.png.read();
        if(png) return gdip.bitmap(png);
    }
    return null;
};

var readFormatHtml = function(fmtId){
    if(fmtId == win.clip.html.format){
        var h = win.clip.html();
        if(h.read()){
            var s = '=== HTML片段 ===\r\n' + (h.fragment || "");
            s = s + '\r\n\r\n=== 完整HTML ===\r\n' + (h.html || "");
            return s;
        }
    }
    return nil;
};

var previewByTab = function(tabIndex){
    if(!curFormat) return;

    if(tabIndex == 1){
        var txt = readFormatText(curFormat);
        if(txt){
            showTextPreview(txt);
        } else {
            if(_WIN10_LATER){
                var bmp = readFormatImage(curFormat);
                if(bmp){
                    import dotNet.ocr;
                    var ocr = dotNet.ocr()
                    var ocrResult = ocr.detectBitmap(bmp)
                    if(ocrResult){
                        showTextPreview(ocrResult.text);
                    }
                    else{
                        showTextPreview("(图像上找到的文本为空)");
                    } 
                } 
                else{
                    showTextPreview("(此格式无法显示为文本)");
                }   
            }
            else{
                showTextPreview("(此格式无法显示为文本)");
            } 
        }
    } elseif(tabIndex == 2){
        var bmp = readFormatImage(curFormat);
        if(bmp){
            showImagePreview(bmp);
        } else {
            hideAllPreviews();
            winform.previewText.text = "(此格式无法显示为图像)";
            winform.previewText.show(true);
        }
    } elseif(tabIndex == 3){
        var buf = win.clip.data(curFormat).read(2048); 
        if(#buf) {
            hexEditor.setBuffer(buf); 
        }
        else{
            hexEditor.setBuffer(raw.buffer("无数据"));
        }

        winform.previewHex.show(true)

    } elseif(tabIndex == 4){
        var html = readFormatHtml(curFormat);
        if(html){
            showTextPreview(html);
        } else {
            showTextPreview("(此格式无法显示为 HTML)");
        }
    }
};

var selectFormat = function(fmtId){
    if(!fmtId) return;
    curFormat = fmtId;

    var targetTab = 3; // 默认十六进制

    if(isHtmlFormat(fmtId)){
        targetTab = 4; // HTML
    } elseif(isImageFormat(fmtId)){
        targetTab = 2; // 图像
    } elseif(isTextFormat(fmtId) || fmtId == 15){
        targetTab = 1; // 文本
    }

    previewTabs.selIndex = targetTab;
    previewByTab(targetTab);
};

var showFormatsView = function(){
    winform.formatList.show(true);
    winform.historyList.show(false);
    winform.lblQuick.show(true);
    winform.btnCopyText.show(true);
    winform.btnSaveImg.show(true);
    winform.btnDeleteHistory.show(false);
    winform.infoText.show(false);
};

var refreshHistoryList = function(){
    winform.historyList.clear();
    for(i=1; #clipHistory){
        var it = clipHistory[i];
        var preview = string.left(string.replace(it.text, "[\r\n\t]", " "), 50);
        winform.historyList.addItem({it.tm, preview});
    }
};

var showHistoryView = function(){
    winform.formatList.show(false);
    winform.historyList.show(true);
    winform.lblQuick.show(false);
    winform.btnCopyText.show(false);
    winform.btnSaveImg.show(false);
    winform.btnDeleteHistory.show(true);
    winform.infoText.show(true);
    refreshHistoryList();
};

winform.historyList.columns = {{"时间", 100}, {"内容预览", 150}};

var refresh = function(){
    winform.formatList.clear();
    clipData = {};
    curFormat = null;

    var fmts = win.clip.formats();
    if(!fmts || #fmts == 0){
        winform.formatList.add("(剪贴板为空)");
        winform.statusText.text = "剪贴板为空";
        winform.statusTime.text = tostring(time());
        hideAllPreviews();
        winform.previewText.show(true);
        return;
    }

    // 填充格式列表
    for(i=1; #fmts){
        var id = fmts[i];
        var icon = "";
        if(isTextFormat(id) || id == 15) icon = "📝 ";
        elseif(isImageFormat(id)) icon = "🖼️ ";
        elseif(isHtmlFormat(id)) icon = "🌐 ";
        elseif(id=9/*_CF_PALETTE*/) icon = "🎨 ";
        elseif(id=16) icon = "🌐 ";
        else icon = "📄 ";
        winform.formatList.add(icon + getFormatName(id));
        clipData[i] = id;
    }

    winform.statusText.text = string.format("共 %d 种格式", #fmts);
    winform.statusTime.text = tostring(time());

    winform.formatList.selIndex = 1;
    selectFormat(clipData[1]);

    var txt = win.clip.read();
    if(txt && #txt > 0){
        if(#clipHistory == 0 || clipHistory[1].text != txt){
            table.unshift(clipHistory, {text=txt; tm=tostring(time())});
            while(#clipHistory > maxHistory) table.pop(clipHistory);
        }
    }
};

leftTabs.onSelChange = function(tabIndex){
    if(tabIndex == 1){
        showFormatsView();
    } else {
        showHistoryView();
    }
};

previewTabs.onSelChange = function(tabIndex){
    previewByTab(tabIndex);
};

winform.formatList.onSelChange = function(){
    var i = winform.formatList.selIndex;
    if(i > 0 && clipData[i]){
        selectFormat(clipData[i]);
    }
};

winform.historyList.onDoubleClick = function(item,subItem,nmListView){
    if(item > 0 && clipHistory[item]){
        win.clip.write(clipHistory[item].text);
        winform.statusText.text = "已将历史记录设为当前剪贴板";
        leftTabs.selIndex = 1;
    }   
}

winform.btnDeleteHistory.oncommand = function(){
    var i = winform.historyList.selIndex;
    if(i > 0 && clipHistory[i]){
        table.remove(clipHistory, i);
        refreshHistoryList();
        winform.statusText.text = "已删除选中的历史记录";
    }
};

winform.btnClear.oncommand = function(){
    if(winform.msgboxTest("确定清空剪贴板?", "确认")){
        win.clip.clear();
        refresh();
    }
};

winform.btnRefresh.oncommand = function(){
    refresh();
};

// 置顶
winform.btnPin.oncommand = function(){
    isPinned = !isPinned;
    win.setTopmost(winform.hwnd, isPinned);
    winform.btnPin.text = isPinned ? "取消" : "置顶";
    winform.btnPin.iconText = isPinned ? '\uF05B' : '\uF08D';
};


winform.btnCopyText.oncommand = function(){
    var txt = win.clip.read();
    if(txt){
        win.clip.write(txt); 
        winform.statusText.text = "已转换为纯文本";
        refresh();
    } else {
        winform.statusText.text = "剪贴板无文本内容";
    }
};

winform.btnSaveImg.oncommand = function(){
    var bmp = win.clip.bitmap.read();
    if(!bmp){
        winform.statusText.text = "剪贴板无图像内容";
        return;
    }
    import fsys.dlg;
    var path = fsys.dlg.save("PNG|*.png|JPEG|*.jpg|BMP|*.bmp", "保存图像");
    if(path){
        bmp.save(path);
        winform.statusText.text = "已保存: " + path;
    }
    bmp.dispose();
};

// 剪贴板监视
var viewer = win.clip.viewer(winform);
viewer.onDrawClipboard = function(){
    refresh();
};

leftTabs.selIndex = 1;
previewTabs.selIndex = 1;
showFormatsView();
refresh();

win.ui.simpleWindow(winform);
winform.show();
win.loopMessage();
Markdown 格式