代码已开源到:
http://www.codeproject.com/KB/GDI/SonicUI.aspx。
摘要:作为windows工程师,UI开发是无可避免的工作,无论你是写一个供销存系统,还是一款聊天IM,UI开发总是会占据你大量的时间。接下来展示的将是一种windows下的非常轻松快捷的UI开发解决方案,实现大家实际工作中经常需要实现的UI特效,力争将你从繁复的UI工作中解放出来,将注意力投入到更有挑战性的工作中去。
关键字:UI引擎 异形窗体 动画按钮 gdi引擎 自绘控件 轻便
作为windows工程师,UI开发是无可避免的工作,无论你是写一个供销存系统,还是一款聊天IM,UI开发总是会占据你大量的时间。前段时间在公司开发项目中,带着些许私心实现了一个构想了较长时间的UI引擎,自已在使用过程中感觉极大的加快了UI开发的效率,希望与大家分享,并用大家的建议来不断完善。
接下来将以几个在实际工作中常见的UI开发问题为例,介绍实现方法及效果,相信这几个问题能引起客户端UI开发同仁的共鸣。
1.多格式图片支持
2.文字和超链接
3.自绘按钮
4.脏处理与区域刷新
5.异形窗体(包括像素级透明异形窗体)
1.多格式图片支持
UI开发离不开图片,windows的api提供了一些加载图片的方法,如常用的LoadImage,使用很简单。但其功能也跟其用法一样简单,只能加载bmp,ico等几种格式。众所周知,bmp是不带alpha通道的,一旦需要实现阴影等alpha渐变的效果,系统提供的api就有些捉襟见肘了。当然很多人会想到大名鼎鼎的CxImage,这也是个不错的选择。我在内部也是封装了CxImage帮忙加载和保存多格式的图片,但加载之后的图像数据处理都是自处理的了,因为CxImage在处理RGB转hsl,旋转等特效时大量使用了浮点运算,效率不能使人十分满意。我把所有的浮点运算都转为整形运算,并大量使用了SSE2指令进行优化,实测证明在旋转,HSL转换,灰化等特效时,效率可以提高4-10倍(CPU为T2330 1.6GHz)。图片加载支持三种方式:从文件;从资源;从dc。需要说明的是从资源加载时请将资源类型命名为IMAGE。
演示代码如下:
//GetSonicUI是引擎导出的唯一函数,是类厂和引擎总控,负责创建对象和销毁对象等。 ISonicImage * pImg = GetSonicUI()->CreateImage(); pImg->Load("C:\\1.png"); pImg->Draw(hdc, 10, 10); GetSonicUI()->DestroyObject(pImg);
UI开发过程中经常最麻烦的是绘制文字,需要你不停的初始化字体,设定字体属性,如果产品人员要求文字按一定的格式排版或输出彩色文字,那简直就是我们的噩梦了。而在自己的界面加入超链接,网上已经有不少演示代码了,但我相信ISonicString是一个更简单的实现方案。ISonicString是一个可以进行消息交互的UI组件对象。只需要像html语言一样加入一些类似的控制符,你就可以随心所欲的控制字体的大小颜色,超链接等属性,非常方便。
ISonicString * pStr = GetSonicUI()->CreateString(); pStr->Format("/c=%x, a='http://hi.csdn.net/zskof', font, font_height=16/点我打开链接", RGB(0, 0, 255)); LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; switch (message) { case WM_PAINT: { hdc = BeginPaint(hWnd, &ps); pStr->TextOut(hdc, 0, 0, hWnd); EndPaint(hWnd, &ps); } break; } ... }
ISonicString也可以将文字和图片混合输出,或使图片带有超链接属性,需要用'p'控制符指定一个ISonicImage的id:
ISonicImage * pImg = GetSonicUI()->CreateImage(); pImg->Load("C:\\1.png"); ISonicString * pStr = GetSonicUI()->CreateString(); pStr->Format("/c=%x/你好吗,朋友/p=%d, a='http://hi.csdn.net/zskof'/", RGB(0, 0, 255), pImg->GetObjectId());
void WINAPI OnMove(ISonicString * pStr, LPVOID) { g_pEffect->MoveGently(0, 0); } // 加载三态图片资源 ISonicImage * pImgNormal = GetSonicUI()->CreateImage(); pImgNormal->Load(BMP_NORMAL); pImgNormal->SetColorKey(RGB(255, 0, 255)); ISonicImage * pImgHover = GetSonicUI()->CreateImage(); pImgHover->Load(BMP_HOVER); pImgHover->SetColorKey(RGB(255, 0, 255)); ISonicImage * pImgClick = GetSonicUI()->CreateImage(); pImgClick->Load(BMP_CLICK); pImgClick->SetColorKey(RGB(255, 0, 255)); // ISonicString * g_pTest[10] g_pTest[10]->Format("/a, p=%d, ph=%d, pc=%d, linkt='点我移动'/", pImgNormal->GetObjectId(), pImgHover->GetObjectId(), pImgClick->GetObjectId()); g_pTest[10]->Delegate(DELEGATE_EVENT_CLICK, NULL, NULL, OnMove);
g_pTest[10]->Format("/a, p=%d, ph=%d, pc=%d, linkt='点我移动', animation=40/", pImgNormal->GetObjectId(), pImgHover->GetObjectId(), pImgClick->GetObjectId());
ISonicPaint * pPaint = GetSonicUI()->CreatePaint(); pPaint->Create(FALSE/*是否需要memDC*/, m_rtString.Width()/*宽*/, m_rtString.Height()/*高*/);
class CTest { public: void RenderImage(ISonicPaint * pPaint, LPVOID); }; void CTest::RenderImage(ISonicPaint * pPaint, LPVOID) { if(pPaint->GetCurrentPaint() == NULL) { return; } HDC hdc = pPaint->GetCurrentPaint()->hdc; int x = pPaint->GetCurrentPaint()->x; int y = pPaint->GetCurrentPaint()->y; // draw here ... } CTest test; pPaint->Delegate(DELEGATE_EVENT_PAINT, NULL, &test, CSonicString::RenderImage);
... // ISonicImage * pImg SetWindowRgn(hWnd, pImg->CreateRgn());
... // ISonicImage * pImg // ISonicWndEffect * pEffect pEffect->Attach(hWnd, TRUE); // 使用像素级alpha模式attach pEffect->SetShapeByImage(pImg);
以下是效率演示,图中的卡片都在快速移动,画面刷新频率在每秒50帧左右,CPU占用基本为0:
结束语:引擎中还有滚动字幕组件,动画组件等常用的UI表现组件,限于篇幅就不一一介绍了,请大家参照ISonicUI.h中的说明自己试用。设计这个引擎时的基本原则就是轻便,高效,如果大家在使用过程中有什么好的建议或需求,也敬请联系我,帮助我完善这个引擎。因为引擎完整实现代码有数万行,而且现在还属于公司财产,就暂不公布完整源码了,但对某些技术实现细节有兴趣的朋友,可以与我联系,共同学习进步。
其它UI软件
http://topic.csdn.net/u/20100306/00/ad4496f4-7d82-459b-b523-e18b42675580.html
SkinSE(全称:skin so easy)
文档也很全。
SkinSB
http://topic.csdn.net/u/20100127/12/491a7a32-9231-4227-bc33-fb9a2f629457.html
http://www.skinse.com/update.html
Codejock Xtreme Toolkit
http://blog.csdn.net/barech/archive/2009/07/02/4315157.aspx