用純C語言來實現WP8中磁貼動態翻轉的功能

本文由BlueCoder編寫   轉載請說明出處:

http://blog.csdn.net/crocodile__/article/details/10486095

我的郵箱:[email protected]    歡迎大家和我交流編程心得

我的微博:BlueCoder_黎小華    歡迎光臨^_^




今年年初入手了一部諾基亞新款WP8手機——Lumia 620 經典藍,用起來感覺很不錯,很流暢、界面很清新


到現在,用了大概有大半年時間了,一直很好奇WP8中磁貼動態翻轉的實現算法——使用過WP8手機的朋友都知道,這個功能很有3D的效果,看起來感覺很不錯

但是,它到底是如何實現的呢?

 

今兒,我就來和大家一起剖析一下它的實現細節


WP8中磁貼動態翻轉功能細節

(1)將當前圖標逐漸縮小(這個縮小的倍率很講究)

(2)當前圖標縮小到一定程度——基本上看不太清楚的時候——就變換另外一張圖標

(3)將另外一張圖標逐漸放大,直至和原圖標大小一致爲止

(4)停頓一會兒,繼續(1)、(2)、(3)的操作


由此,可見這個看似有3D效果的磁貼翻轉功能也就是使用2D技術實現的——畢竟是在一個平面上——但是這個過程比較快,人的肉眼有記憶推遲特點,因此看起來很連貫,就像是將一張圖360°翻轉過來一樣(其實和看視頻的原理差不多)


使用過WP8手機的朋友應該都知道"天氣通"這個應用吧,它可以產生磁貼放到WP8手機桌面中,並能實現翻轉功能,我也就借用這個應用的圖標來模擬

下面來看看,我模擬的程序的實現效果:

 

 

怎麼樣,還不錯吧?呵呵^_^

 

…………

 

 

功能細節大家知道了,可是我們如何用win32純c語言來實現呢?

OK,我的對策是"對症下藥"

<1>首先必須實現縮放位圖的功能,這個可以使用StretchBlt這個方法(熟悉Win32的應該知道這個函數吧),它可以按照指定的大小來縮放這個位圖

<2>其次,所謂"逐漸縮放"、"停頓一會兒"——當然第一時間想到的就是計時器和Sleep這個函數來實現

 

 

使用到的技術主要就是這兩個,下面着重講解一下具體的代碼細節:

<1>變量瀏覽

//全局變量(用來控制每一次縮放的大小,注意:只是縮放位圖的高度、寬度不變)
int		height[] = {144, 88, 32, 10, 75, 137, 200};

 

//回調函數中的靜態局部變量
static HBITMAP	hBmp[2];			//存放正反面位圖句柄
static SIZE		sBmp, sClient;		//位圖大小、客戶區大小(用於縮放)
static POINT	ptBmp;				//位圖位置(保證始終居中顯示)
static int		curIndex, isFirst;	//當前索引(height數組)、是否爲正面(用於交換位圖)

 

<2>WndProc中的實現細節:

case WM_CREATE:
	//加載位圖
	hInstance = ((LPCREATESTRUCT)lParam)->hInstance;

	hBmp[0] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP1));
	hBmp[1] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2));

	GetObject(hBmp[0], sizeof(BITMAP), &bmp);

	sBmp.cx	= bmp.bmWidth;
	sBmp.cy	= bmp.bmHeight;

	//設置計時器
	SetTimer(hwnd, ID_TIMER, 120, NULL);
  	return 0;


 

case WM_SIZE:
	//獲取客戶區大小
	sClient.cx	= LOWORD(lParam);
	sClient.cy	= HIWORD(lParam);

	//修改位圖當前位置座標
	ptBmp.x		= (sClient.cx - sBmp.cx) / 2;
	ptBmp.y		= (sClient.cy - sBmp.cy) / 2;
	return 0;


 

	case WM_PAINT:
		//按照一定比例縮放位圖
		hdc = BeginPaint(hwnd, &ps);

		hdcMem = CreateCompatibleDC(hdc);
		SelectObject(hdcMem, hBmp[isFirst]);

		SetStretchBltMode(hdc, COLORONCOLOR);
		StretchBlt(hdc, ptBmp.x, ptBmp.y, sBmp.cx, sBmp.cy, hdcMem, 0, 0, 200, 200, SRCCOPY);

		DeleteDC(hdcMem);
		EndPaint(hwnd, &ps);
		return 0;


 

	case WM_TIMER:
		//修改當前顯示的位圖高度
		sBmp.cy		= height[curIndex];

		//如果位圖高度變爲最小(也就是幾乎看不太清的程序),就交換位圖
		if(sBmp.cy == height[3])
		{
			isFirst = !(isFirst & 1);
		}

		//如果位圖高度之前是原始大小,那麼應該停頓一會兒,這裏停頓當前線程1秒
		else if(sBmp.cy == height[0])
		{
			Sleep(1000);
		}

		//修改位圖顯示位置,保證居中顯示
		ptBmp.y		= (sClient.cy - sBmp.cy) / 2;

		//索引下一個高度(height)
		curIndex = (curIndex + 1) % NUM;

		//重繪
		InvalidateRect(hwnd, NULL, TRUE);
		return 0;


 


 

點擊下載源代碼以及相關資源

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章