前段时间用sdl嵌入SOUI做视频播放器,由于SOUI习惯屏蔽系统默认的非客户区,而在窗口自己的客户区分出一块来模拟非客户区,导致窗口在拉伸的时候,SOUI窗口会出现比较严重的闪烁(不光是SOUI这样,其它UI库也存在类似问题,应该是MS的原因),打开系统的非客户区就不闪烁。
为了让业务层有更一致的UI体验,SOUI4基于SOUI的控件框架搭建了一套非客户区绘制框架,使得可以像客户区一样操作非客户区,方便需要嵌入视频的应用更好的统一界面效果。
使用方法:
首先这类窗口不支持窗口的逐点半透明效果,因此必须关闭soui元素里的translucent属性。
然后在soui元素下加入ncpainter元素如下:
1 <ncpainter system="false" borderWidth="5dp" titleHeight="30dp" skinBorder="_skin.sys.wnd.bkgnd" 2 skinActive="skin_active" skinInactive="skin_inactive" 3 colorActiveTitle="@color/white" 4 colorInactiveTitle="@color/white" 5 layout="hbox" gravity="center" > 6 <icon id="sysid_icon" src="ICON_LOGO:16"/> 7 <text id="sysid_title">@string/title</text> 8 <window size="0,0" weight="1"/> 9 <imgbtn id="sysid_min" skin="_skin.sys.btn.minimize" animate="1" /> 10 <window> 11 <imgbtn id="sysid_max" skin="_skin.sys.btn.maximize" pos="0,0" animate="1" /> 12 <imgbtn id="sysid_restore" skin="_skin.sys.btn.restore" pos="0,0" show="0" animate="1" /> 13 </window> 14 <imgbtn id="sysid_close" skin="_skin.sys.btn.close" tip="close" animate="1"/> 15 </ncpainter>
其中system, borderWidth,titleHeight,skinBorder, skinActive, skinInactive, colorActiveTitle, colorInactiveTitle是ncpainter专有属性。
system是bool类型,默认为false,代表使用SOUI的自绘非客户区,为true则代表使用系统默认的非客户区。
borderWidth代表边框宽度,titleHeight代表窗口头高度。
skinBorder是一个绘制边框的skin对象。
skinActive, skinInactive是两个绘制标题栏背景的skin对象,分别对应激活状态和失活状态。
colorActiveTitle, colorInactiveTitle是两个绘制标题栏文本的颜色,分别对应激活状态和失活状态。
其它属性和SWindow一样,子窗口的布局属性也和其它常规窗口一样。
和常规窗口一个不同点在于,非客户区由于不处理键盘事件,因此不要在非客户中布局edit等需要处理键盘的控件。
非客户区控件增加了几个系统ID,以sysid_XXX命名,这几个ID会同步系统的默认行为。
1 enum{ 2 IDC_SYS_ICON=100, 3 IDC_SYS_TITLE=101, 4 IDC_SYS_CLOSE=102, 5 IDC_SYS_MIN=103, 6 IDC_SYS_MAX = 104, 7 IDC_SYS_RESTORE = 105, 8 };
1 int SNcPainter::toNcBuiltinID(const SStringW & strValue) 2 { 3 static struct SystemID 4 { 5 int id; 6 LPCWSTR pszName; 7 } systemID[] = { IDC_SYS_ICON, L"sysid_icon", IDC_SYS_TITLE, L"sysid_title", IDC_SYS_CLOSE, L"sysid_close", 8 IDC_SYS_MIN, L"sysid_min", IDC_SYS_MAX, L"sysid_max", IDC_SYS_RESTORE, L"sysid_restore"}; 9 if (!strValue.IsEmpty()) 10 { 11 if (strValue.Left(5).CompareNoCase(L"sysid") == 0) 12 { 13 for (int i = 0; i < ARRAYSIZE(systemID); i++) 14 { 15 if (strValue.CompareNoCase(systemID[i].pszName) == 0) 16 { 17 return systemID[i].id; 18 } 19 } 20 } 21 } 22 return 0; 23 }
除了上述差异,非客户区控件和客户区其它控件没有区别。
上图标题栏就是采用新的非客户区绘制框架做出来的,即保持了和客户区界面效果一致,也解决了拉伸闪烁问题。