您的位置:首页 > 移动开发 > IOS开发

Windowos体验iOS滑动解锁特效(更新)

2012-09-16 21:28 411 查看
序:

自苹果手机系统面世以来,一直很喜欢它的滑动解锁特效,有一天突发奇想,能不能在windows上也体验到这种特效呢?这个想法一直在酝酿,直到有一天,2011年7月的一天,决定开始做出来!!说来惭愧,从想法到成品,期间很曲折,浪费了很多时间,由于只能利用晚上的几个小时,中途几个月还暂缓了,所以拖到现在才基本完成。曾经想过放弃,但是又不想这么做,我算是一个“疯狂的程序员吗”?那就做完它!现在已经把写程序当成下班后的放松活动了
= =!

回归正题,我要做成锁屏程序,在笔记本的触摸板上轻轻一划,屏幕解锁,显示出经典的windows桌面,而且还具有图标的动画效果,和你手上的iPhone是相同的界面,是不是很迷人?



值得庆幸的是,当你看到这篇文章时,这个想法已经付诸实践并基本完成了!择日我会发布出来,供大家享用,源码就不发了,那时候的我程序结构写的很乱,没法看,开源了也是给人找麻烦,特别是水平比较高的Coder,会喷我的,呵呵。后面我会把实现的原理和程序结构说一下就可以了。下面先让大家看看期待已久的成品效果吧!!锵~锵~锵~~~~

程序运行界面





演示视频:

无法播放可以点击打开演示视频

界面已经很完美的模拟了苹果系统了,WIFI信号、电池信息、充电图标、解锁滑块、发光文字。你一定很惊讶于它的逼真程度吧?想知道是如何实现的吗?好,请接着看~

正文:

程序最开始设计为MFC开发(如果是现在做我恐怕就不会选择这个了),中途遇到技术难题转到了C#平台,由于托管语言的性能,我又不得不回到了MFC!真是曲折的一条路,如果我那时候知道用DirectUI,我就用Bolt了。所以现在这个程序没有使用任何第三方界面库,完全是GDI和GDI+搭配绘制的,包括动画。程序界面上的各种元素,通过ATL的CImage类承载,这个类很好用,对有Alpha通道的PNG图像支持的很好,程序使用了双缓冲的处理方式,绘制了N多个CImage局部图层,最后合成到一张最终层(CImage),将其贴到界面上。

所有的动画通过定时器不断的绘制到局部图层上,最后在一个消息循环中不断刷新最终层:

switch (pMsg->message)
{
case WM_TIMER:
lfont.DrawLightFont(srcFrameRect,DeskTopImg,offset==180?offset+=5:offset+=5,button);

BitBlt(Desk.GetDC(),0,0,scrW,scrH,DeskCopy.GetDC(),0,0,SRCCOPY);
//呈现放大8%的背景到桌面,以便收缩图标动画时还原背景大小。
//BitBlt(Desk.GetDC(),scrW/2-DeskCopy.GetWidth()/2,scrH/2-DeskCopy.GetHeight()/2,DeskCopy.GetWidth(),DeskCopy.GetHeight(),DeskCopy.GetDC(),0,0,SRCCOPY);
DeskCopy.ReleaseDC();
Desk.ReleaseDC();
DeskTopImg.Draw(Desk.GetDC(),0,0);
Desk.ReleaseDC();
Desk.Draw(pDC->m_hDC,0,0,scrW,scrH);//将合成图贴到窗体上
ReleaseDC(pDC);
break;
case WM_PAINT:
break;
case WM_KEYDOWN:
break;
case WM_MOUSEMOVE:
KillTimer(SHOW);
break;
default:
break;
}


GDI+的效果终归不是太理想,有些特效虽然实现了,但是不得不屏蔽了。

电池信息等通过API获取,定时更新到界面上。获取桌面背景这个我找了很长时间,最后通过这句代码实现了:

PaintDesktop(pDC->m_hDC);


滑块的移动,自然通过鼠标的点击移动事件来处理,而且还要限制鼠标移动的范围。发光文字特效通过GDI+的线性画刷实现,传递坐标参数用定时器不断调用就能动起来了:

Graphics g(_frameRect.GetDC());
g.SetTextRenderingHint(TextRenderingHintAntiAlias);

SolidBrush brush(Color(102, 0, 0, 0));

Font font(fontName, size, FontStyleRegular, UnitPixel);
StringFormat strFormat;
strFormat.SetAlignment(StringAlignmentCenter);

WCHAR *w_str=new WCHAR[str.GetLength()*2];
USES_CONVERSION;
wcscpy(w_str, CT2CW(str));
RectF rf;
g.MeasureString(w_str,(INT)wcslen(w_str),&font,PointF(0,0),&rf);

//创建多色数组
Color clrs[] =
{
Color(255, 138, 139, 139),
Color(255, 138, 139, 139),
Color.White,
Color.White,
Color(255, 138, 139, 139),
Color(255, 138, 139, 139)
};
REAL positions[] = { 0, 0.4F, 0.5F, 0.6F, 0.7F, 1.0F };

//创建线性画刷
Rect rect;
rect.X=offset;
rect.Y=0;
rect.Width=(int)rf.Width+100;
rect.Height=(int)rf.Height;
LinearGradientMode lmode=LinearGradientModeHorizontal;
LinearGradientBrush lbrush(rect, Color.White, Color.White, LinearGradientModeHorizontal);
lbrush.SetInterpolationColors(&clrs[0], &positions[0], 6);

g.DrawString(w_str,(INT)wcslen(w_str),&font, RectF(FRAME_W/2-(int)rf.Width/2+30,FRAME_H/2-(int)rf.Height/2,rf.Width,rf.Height),&strFormat, &lbrush);
_frameRect.ReleaseDC();


图标的动画,有两种方式,一种是获得桌面的句柄一个个的从图像上扣下来,另一种是调用API获取,以下的代码只是给个思路:

#ifdef GET_ICON_MODE
HWND hwndParent = ::FindWindow( L"Progman", L"Program Manager" );
HWND hwndSHELLDLL_DefView = ::FindWindowEx( hwndParent, NULL, L"SHELLDLL_DefView", NULL );
HWND hwndSysListView32 = ::FindWindowEx( hwndSHELLDLL_DefView, NULL, L"SysListView32", L"FolderView" );
HDC hDc = ::GetDC(hwndSysListView32);

int num = ListView_GetItemCount( hwndSysListView32 );
//Point *icons=new Point[num];

DWORD   dwProcessId;
GetWindowThreadProcessId(hwndSysListView32,   &dwProcessId);

HANDLE   hProcess   =   OpenProcess(PROCESS_ALL_ACCESS,   FALSE,   dwProcessId);
LPVOID   lpvPt   =   VirtualAllocEx(hProcess,   NULL,   sizeof(POINT),   MEM_COMMIT,   PAGE_READWRITE);

POINT   pt;

int layer_x = GET_ODD(scrW / iconWidth);
int layer_y = GET_ODD(scrH / iconHeight);
int layers;
int OFFSET_X, OFFSET_Y;
if (layer_x > layer_y)
{
layers = layer_x / 2;   //获得图标层数(以多的为准)
OFFSET_Y = -iconHeight*(layer_x - layer_y)/2;
OFFSET_X = 0;
}
else
{
layers = layer_y / 2;
OFFSET_X = -iconWidth*(layer_y - layer_x)/2;
OFFSET_Y = 0;
}
IcoLayer *iLayer = new IcoLayer[layers];              //存储每层的图标
memset(iLayer,0,sizeof(IcoLayer)*9);

//修改图标间距
//SystemParametersInfo(SPI_GETICONMETRICS, ico, sizeof(ICONMETRICS));

//获取桌面背景存储到desk
CDC *pDC = GetDC();
/*PaintDesktop(pDC->m_hDC);
GetDesktop(Desk);*/

stIcon *stIco = new stIcon[num];
memset(stIco,0,sizeof(stIcon)*num);

int ico_off_x = 8;
int ico_off_y = 8;
//截取所有图标所在位置的图像
for( int i = 0; i < num; i++ )
{
//#ifdef WIN7
if(!IsXP)
{
//        ico_off_x = 8;
//        ico_off_y = 8;
}
//#else
else{
//        ico_off_x = 21;
//        ico_off_y = 2;
}
//#endif
ListView_GetItemPosition(hwndSysListView32,   i,   lpvPt);
ReadProcessMemory(hProcess,   lpvPt,   &pt,   sizeof(POINT),   NULL);

//ImageList_Draw();

//存储图标的img

stIco[i].img.Create(iconWidth,iconHeight,BIT_NBPP,CImage::createAlphaChannel);

::BitBlt(stIco[i].img.GetDC(), 0, 0, iconWidth, iconHeight, hDc, pt.x-ico_off_x, pt.y-ico_off_y, SRCCOPY);


这个是获取图标的图像,存储到CImage当中去,要实现视频中的动画效果,我是写了一个我自己都懒得再分析的你所能想到最笨拙的方法实现了,代码就不贴了,看了废脑子。用自己的想法实现,说不定比我的更好。

图标动画的设计:



首先获取所有图标的图像和位置信息,根据其所在坐标为图标分层。如图,矩形中的是实际桌面上的图标,最中间的标1的作为最里层,向外依次为第二层,第三年层等等。矩形外的图标是动画开始时图标的位置,因为这里我们要实现聚拢的动画效果,所以最里层的图标要放到最外面,依次类推,矩形里的层和矩形外的层的位置是相反的。箭头表明其从起始位置移动到终点位置的示意。这样,聚拢的动画效果就实现了。

下载:



目前Beta1版已发布!推荐Win7环境下运行,XP系统可能存在兼容问题。http://download.csdn.net/download/detecyang/4576409
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: