aardio从高级选项卡中分离出独立窗口
就像很多浏览器一样,标签页可以变成独立窗口。arrdio的高级选项卡也可以。

总的思路很简单,就是把选项卡窗体的父窗口和样式修改一下。
里面有一个关键点,就是必须把独立出来的窗体从选项卡容器(container)的子窗口队列中移除。因为tbs.loadform的本质是tbs.container.loadform,也就是mainform.custom.loadform。而custom 控件的 loadForm 函数会将窗体加载为子窗口, 自动维护一个子窗口队列,显示一个子窗口就会隐藏其他子窗口。如果不从这个队列中移除,就会出现,一切换选项卡,窗体就看不见了的情况。这个队列就是custom._forms。虽然它的名字带下划线,像个常量,其实可以移除其中的元素。
此外还有一些细节,代码里有说明。
下面的代码是aardio工程模板“横版导航”,其中50-93行是我们增加的代码,其余没有修改。
import fonts.fontAwesome;
import win.ui;
/*DSG{{*/
mainForm = win.form(text="高级选项卡分离为独立窗口";right=1040;bottom=642;bgcolor=16777215;border="none")
mainForm.add(
caption={cls="bkplus";text="选项卡变独立窗口";left=35;top=12;right=160;bottom=30;color=15780518;dl=1;dt=1;font=LOGFONT(h=-16);z=5};
custom={cls="custom";left=0;top=40;right=1040;bottom=643;bgcolor=16777215;db=1;dl=1;dr=1;dt=1;z=1};
logo={cls="bkplus";text='\uF0AD';left=6;top=9;right=35;bottom=34;color=15780518;dl=1;dt=1;font=LOGFONT(h=-18;name='FontAwesome');z=4};
navFirst={cls="plus";text="主页";left=166;top=5;right=260;bottom=40;align="left";color=16777215;dl=1;dt=1;font=LOGFONT(h=-16);iconStyle={align="left";font=LOGFONT(h=-19;name='FontAwesome');padding={left=12;top=4}};iconText='\uF00A';notify=1;paddingLeft=1;paddingRight=1;paddingTop=3;textPadding={left=39;bottom=1};x=0.5;y=0.2;z=3};
navHelp={cls="plus";text="帮助";left=462;top=5;right=556;bottom=40;align="left";color=16777215;dl=1;dt=1;font=LOGFONT(h=-16);iconStyle={align="left";font=LOGFONT(h=-19;name='FontAwesome');padding={left=12;top=4}};iconText='\uF06A';notify=1;paddingLeft=1;paddingRight=1;paddingTop=3;textPadding={left=39;bottom=1};x=0.5;y=0.2;z=7};
navHotkey={cls="plus";text="热键";left=265;top=5;right=359;bottom=40;align="left";color=16777215;dl=1;dt=1;font=LOGFONT(h=-16);iconStyle={align="left";font=LOGFONT(h=-19;name='FontAwesome');padding={left=12;top=4}};iconText='\uF11C ';notify=1;paddingLeft=1;paddingRight=1;paddingTop=3;textPadding={left=39;bottom=1};x=0.5;y=0.2;z=8};
navSetting={cls="plus";text="设置";left=363;top=5;right=457;bottom=40;align="left";color=16777215;dl=1;dt=1;font=LOGFONT(h=-16);iconStyle={align="left";font=LOGFONT(h=-19;name='FontAwesome');padding={left=12;top=4}};iconText='\uF0AD';notify=1;paddingLeft=1;paddingRight=1;paddingTop=3;textPadding={left=39;bottom=1};x=0.5;y=0.2;z=6};
titleBar={cls="bkplus";left=0;top=0;right=1042;bottom=41;bgcolor=14977280;dl=1;dr=1;dt=1;z=2}
)
/*}}*/
import win.ui.simpleWindow;
win.ui.simpleWindow( mainForm );
import win.ui.tabs;
var tbs = win.ui.tabs(
mainForm.navFirst,
mainForm.navHotkey,
mainForm.navSetting,
mainForm.navHelp
);
tbs.skin({
foreground={
active=0xFFFFFFFF;
default=0x00FFFFFF;
hover=0x38FFFFFF
};
color={
default=0xFFFFFFFF;
};
checked={
foreground={default=0xFFFFFFFF;};
color={default=0xFF42A875;};
}
})
tbs.loadForm(1,"\dlg\first.aardio" );
tbs.loadForm(2,"\dlg\hotkey.aardio" );
tbs.loadForm(3,"\dlg\setting.aardio" );
tbs.loadForm(4,"\dlg\help.aardio" );
tbs.selIndex = 1;
//为每个选项卡设置两个事件函数
for(i=1;tbs.count()){
//鼠标按下事件,记录按下时间,主要为了防止误触,和主功能无关,也可以写在tbs的事件里。
tbs.strips[i].onMouseDown = function(wParam,lParam){
tbs.strips[i].tick=time.tick();
}
//鼠标拖动事件。tbs没有这个事件,只能写在选项卡里。
tbs.strips[i].onMouseDrag = function(wParam,lParam){
//200毫秒以内视为误触,不做响应
if time.tick()-tbs.strips[i].tick<200 return ;
//记录下已经分离了,避免重复响应
if tbs.strips[i].gone return ;
tbs.strips[i].gone=true ;
//关键点一:将该窗体从选项卡容器的子窗口队列中移除
var frm=tbs.forms[i];
table.removeByValue(tbs.container._forms,frm);
//关键点二:修改窗体样式和父窗口
frm.modifyStyle(0x40000000/*_WS_CHILD*/,0x40000/*_WS_SIZEBOX*/|0xC00000/*_WS_CAPTION*/);
win.setParent(frm.hwnd,0);
//选项卡布局调整。如果用delete,布局会自动调整,但是这里测试一旦delete,窗口就关闭了,不可以
//因此使用close或者hide,然后人工调整布局。
tbs.strips[i].close();//tbs.strips[i].hide=true
for (j=i+1;tbs.count()){
tbs.strips[j].left-=(tbs.strips[i].width+tbs.itemMargin);
tbs.strips[j].right-=(tbs.strips[i].width+tbs.itemMargin);
}
//显示其他选项卡,右侧临近优先,左侧临近其次。不切换的话,会显示空白,不好看。
var newindex;
for (j=i+1; tbs.count()){
if !tbs.strips[j].gone {newindex=j;break;}
}
if !newindex{
for (j=i-1; 1;-1){
if !tbs.strips[j].gone {newindex=j; break;}
}
}
tbs.selIndex=newindex;
//分离出来的窗口移动到当前鼠标位置,开始拖动
var x,y = win.getMessagePos(lParam);
x,y=win.toScreen(owner.hwnd,x,y);
frm.setPos(x-frm.width/2,y-10) ;
frm.hitCaption();
}
}
mainForm.show();
return win.loopMessage();