色尼玛亚洲综合影院,亚洲3atv精品一区二区三区,麻豆freexxxx性91精品,欧美在线91

如何開發(fā)絢麗、高效率的界面(Windows嵌入式系統(tǒng))

上篇文章中提到用戶體驗(UE),并且說到國內(nèi)有專門去做UE的團隊也很少。據(jù)我了解Microsoft、Nokia、Google等,還有國內(nèi)的Baidu是有比較專業(yè)的UE團隊。對于我們這樣的普通團隊、普通開發(fā)者來說,這樣的經(jīng)驗實在太少了。而且普遍更認(rèn)為UE是UI Designer的事情,與我們這樣的Developer沒有太多關(guān)系。

當(dāng)然不是,UE遠超過UI。很多因素造成了UE差,比如一份不正確的數(shù)據(jù)表明17%的用戶認(rèn)為手機運行速度慢,Windows Mobile手機開機漫長的等待就十分的讓我受不了。我們開發(fā)的應(yīng)用是否有過優(yōu)化?運行效率是否已經(jīng)很讓用戶滿意了?等等這些問題留在開發(fā)中思考吧。

在使用優(yōu)秀的產(chǎn)品時用心體會、用心觀察、用心思考,在此基礎(chǔ)上創(chuàng)新。逐漸提高UE設(shè)計能力。(等Windows 7正式發(fā)布了,我們可以討論討論其UE^^)

這篇文章僅僅討論有關(guān)界面開發(fā)上Developer涉及到的技術(shù)問題,在學(xué)習(xí)過程中,隨著越深越廣越覺得自身水平的不足,所以只敢拋磚引玉,更多希望能夠引起大家對界面開發(fā)技術(shù)、對UE的討論。

上篇文章已經(jīng)列出目錄:

1.相關(guān)商用產(chǎn)品一覽

2.Windows系統(tǒng)下圖形編程的相關(guān)基礎(chǔ)知識

3.DirectDraw簡介

4.DirectDraw驅(qū)動開發(fā)

5.DirectDraw應(yīng)用開發(fā)

6.一個推薦的入門Sample

第1部分已經(jīng)在上篇文章講過,鑒于篇幅的原因2、3、4、5、6部分將在下篇文章介紹。這篇文章先介紹下如何使用Win32下的GDI等接口實現(xiàn)絢麗、高效率的界面。這樣我們就能發(fā)現(xiàn)GDI等接口的不足,進而引申到DirectDraw上面。(這篇文章默認(rèn)你有一定的Windows編程基礎(chǔ),熟悉GDI等概念。)

 

補充內(nèi)容●如何使用Win32下的GDI等接口實現(xiàn)絢麗、高效的界面

1.如何讓界面絢麗?

怎么樣的算絢麗?有很漂亮的圖片?有Alpha透明?有Animation?

每個人的審美觀點都不同,所以如果你的界面很多人認(rèn)為絢麗那就可以了。設(shè)計界面主要是Designer的工作,包括UI邏輯的設(shè)計,色彩搭配設(shè)計等,我認(rèn)為這也可以進一步分工:熟悉用戶習(xí)慣的Designer、美學(xué)Designer等。但是一般情況下這些讓程序員給代勞了。

下面介紹Windows提供給開發(fā)人員的相關(guān)接口,利用這些接口設(shè)計你認(rèn)為絢麗的界面。

2.如何透明?如何半透明?如何顏色漸變?

以下是我使用Imaging COM組件封裝的一個函數(shù),可以使用其繪制PNG圖片,當(dāng)然也可以繪制其它圖片。繪制帶Alpha通道的PNG圖片即實現(xiàn)了透明。

#include #include #include #pragma comment(lib, "Imaging.lib")BOOL DrawPNG(HDC hDC, TCHAR *szPicString, RECT &rcDraw){	BOOL br = FALSE;	IImagingFactory *pImgFactory = NULL;	IImage *pImage = NULL;	ImageInfo sImgInfo;	CoInitializeEx(NULL, COINIT_MULTITHREADED);	// Create the imaging factory.	if (SUCCEEDED(CoCreateInstance(CLSID_ImagingFactory,		NULL,		CLSCTX_INPROC_SERVER,		IID_IImagingFactory,		(void **)&pImgFactory)))	{		// Load the image from the JPG file.		if (SUCCEEDED(pImgFactory->CreateImageFromFile(			szPicString,			&pImage)))		{			// Draw the image.			pImage->Draw(hDC, &rcDraw, NULL);			pImage->Release();			pImage = NULL;			br = TRUE;		}		pImgFactory->Release();	}	CoUninitialize();	return br;}

------------------------------------------------------------------------------------------------------

而封裝的這個函數(shù)實現(xiàn)了將一個DC根據(jù)Alpha值半透明繪制到另一個DC上,使用GDI函數(shù)AlphaBlend實現(xiàn)。

BOOL AlphaBlt(HDC hdcDest, int nXOriginDest, int nYOriginDest,			  int nWidthDest, int nHeightDest,			  HDC hdcSrc, int nXOriginSrc, int nYoriginSrc,			  int nWidthSrc, int nHeightSrc,			  BYTE alpha) {				  BLENDFUNCTION bf;				  bf.BlendOp = AC_SRC_OVER;				  bf.BlendFlags = 0;				  bf.SourceConstantAlpha = alpha;				  bf.AlphaFormat = 0;				  return AlphaBlend(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, 					  hdcSrc, nXOriginSrc, nYoriginSrc, nWidthSrc, nHeightSrc, bf);}
                      

如果你的設(shè)備支持AlphaBlend硬件加速那將是非常棒的事情,否則軟件方式會有點影響性能。

------------------------------------------------------------------------------------------------------

顏色漸變也是直接有API可以支持:

BOOL GradientFill(  HDC hdc,  PTRIVERTEX pVertex,  ULONG nVertex,  PVOID pMesh,  ULONG nCount,  ULONG ulMode);

hdc
[in] Handle to the destination device context.

pVertex
[in] Pointer to an array of TRIVERTEX structures, each of which defines a triangle vertex.

nVertex
[in] The number of vertices in pVertex.

pMesh
[in] Array of GRADIENT_RECT structures in rectangle mode.

nCount
[in] The number of rectangles in pMesh.

ulMode
[in] Specifies gradient fill mode. The following table shows the possible values for ulMode.

This function fills rectangular regions with a background color that is interpolated from color values specified at the vertices.

不管你使用.NET CF平臺調(diào)用這些API,還是Win32/MFC/ATL/WTL直接調(diào)用這些API,你都是可以實現(xiàn)這些效果的。更多內(nèi)容請查詢開發(fā)文檔,畢竟那才是最好的參考資料。

3.如何實現(xiàn)動畫?

動畫的原理就是一幀一幀的畫面按照時間軸向后移動,在騙過眼睛之后就成了動畫,所以你得到動畫最簡單的方法就是按照一定間隔將不同圖片一張一張繪制到屏幕上,雖然很簡單,但是在編程中經(jīng)常使用這種方法。有時簡單的往往是最好的。

這里還有個技巧,比如將每張圖片使用Photoshop中的運動濾鏡模糊下,這樣使用上面方法得到的動畫會有種非常快速的感覺。也可以用類似的方法來用2D表現(xiàn)三維的事物,得到3D動畫的效果。

還可以使用GIF動畫的方式,比如在開機和關(guān)機時。以下封裝的函數(shù)僅供參考,我沒用心整理。

BOOL DisplayGIF(TCHAR *szPicString){HANDLE hFile = CreateFile(strFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);if (hFile == INVALID_HANDLE_VALUE){return FALSE;}DWORD dwFileSize = GetFileSize(hFile, NULL);if ( (DWORD)-1 == dwFileSize ){CloseHandle(hFile);return FALSE;}HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwFileSize);if (hGlobal == NULL){CloseHandle(hFile);return FALSE;}LPVOID pvData = GlobalLock(hGlobal);if (pvData == NULL){GlobalUnlock(hGlobal);CloseHandle(hFile);return FALSE;}DWORD dwBytesRead = 0;BOOL bRead = ReadFile(hFile, pvData, dwFileSize, &dwBytesRead, NULL);GlobalUnlock(hGlobal);CloseHandle(hFile);if (!bRead){return FALSE;}IStream* pStream = NULL;if ( FAILED(CreateStreamOnHGlobal(hGlobal, TRUE, &pStream)) ){return FALSE;}if( NULL == pStream ){return FALSE;} IImage *pImage = NULL;RECT rc;IImagingFactory *pImgFactory = NULL;CoInitializeEx(NULL, COINIT_MULTITHREADED);if ( !SUCCEEDED(CoCreateInstance(CLSID_ImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IImagingFactory, (void **)&pImgFactory)) ){return FALSE;}IImageDecoder* pDecoder = NULL;UINT nCount = 0;if ( !SUCCEEDED(pImgFactory->CreateImageDecoder(pStream, DecoderInitFlagNone, &pDecoder)) ){return FALSE;}pDecoder->GetFrameDimensionsCount(&nCount);GUID *pDimensionIDs = (GUID*)new GUID[nCount];pDecoder->GetFrameDimensionsList(pDimensionIDs,nCount);TCHAR strGuid[39];StringFromGUID2(pDimensionIDs[0], strGuid, 39);UINT frameCount = 0;pDecoder->GetFrameCount(&pDimensionIDs[0],&frameCount);UINT iSize = 0;pDecoder->GetPropertyItemSize(PropertyTagFrameDelay,&iSize);BYTE* pBuff = new BYTE[iSize];PropertyItem* pItem = (PropertyItem*)pBuff;pDecoder->GetPropertyItem(PropertyTagFrameDelay,iSize,pItem);int fCount = 0;ImageInfo Info;pImgFactory->CreateImageFromStream(pStream,&pImage);pImage->GetImageInfo(&Info);rc.left = rc.top = 0;rc.right = Info.Width;rc.bottom = Info.Height;HDC   tempDC;HBITMAP    hbmNew = NULL;void *     pv;BITMAPINFO bmi = { 0 };HBITMAP    hbmOld = NULL;tempDC = CreateCompatibleDC(NULL);bmi.bmiHeader.biSize        = sizeof(BITMAPINFOHEADER);bmi.bmiHeader.biWidth       = Info.Width;bmi.bmiHeader.biHeight      = Info.Height;bmi.bmiHeader.biPlanes      = 1;bmi.bmiHeader.biBitCount    = (SHORT) max(16, GetDeviceCaps(tempDC, BITSPIXEL));bmi.bmiHeader.biCompression = BI_RGB;hbmNew = CreateDIBSection(tempDC, &bmi, DIB_RGB_COLORS, &pv, NULL, 0);hbmOld = (HBITMAP)SelectObject(tempDC, hbmNew);pImage->Draw(tempDC, &rc, NULL);pDecoder->SelectActiveFrame(&pDimensionIDs[0], ++fCount);BitBlt(g_hdc, 0, 0, rc.right - rc.left, rc.bottom - rc.top, tempDC, 0, 0, SRCCOPY);delete []pBuff;delete []pDimensionIDs;pDecoder->Release();pImage->Release();pImgFactory->Release();CoUninitialize();return TRUE;}

 

4.如何有較高的運行效率?

后面的內(nèi)容會介紹到使用GDI這些“較高層次”的接口是很難有較高的運行效率。

但是可以使用一些技巧,比如“空間換取時間”。相信"Lazy Computation”你有聽過,延遲處理這項任務(wù)直到真正需要的時候(在編程中我們也會經(jīng)常用到,需要有這個意識。)這里使用的技巧有點恰恰相反的味道,把用戶將來很可能用到的地方先處理好,然后儲存起來,而并不是等到用戶真正需要的時候才去處理。

比如使用Imaging COM組件繪制PNG圖片時,每次都需要加載組件的庫文件,然后卸載,界面可能要反復(fù)刷新,然后反復(fù)繪制PNG圖片。這時可以考慮在程序啟動的時候使用非界面主線程將繪制好的PNG圖片保存起來(比如以Device Context的形式),界面刷新的時候僅僅是BitBlt到目標(biāo)設(shè)備。BitBlt的效率是比較高的,如果仍然不能滿足你的效率要求,可以考慮下面介紹的DirectDraw等技術(shù)。

上面的方法對于具有豐富開發(fā)經(jīng)驗的應(yīng)該比較清楚,但是新手往往會忽略。在開發(fā)界面時我們要保證一個基本原則:想盡一切辦法在現(xiàn)有的條件下提高界面響應(yīng)用戶的速度,界面要以用戶為中心。所以開發(fā)時需要保持這個意識。

5.如何提高程序啟動速度?

第4部分說過,為了提高運行效率,可以將常用的界面在程序啟動時一起緩存到內(nèi)存中,那么程序的啟動時間會大大增加,如何解決這個問題?我的建議是UI主線程僅僅加載少量的用戶啟動后直接就能看到的界面,而另起一個子線程(叫A)用于加載其它界面,其它界面加載完之后這個子線程退出,當(dāng)用戶點擊其它界面時,主線程如果發(fā)現(xiàn)子線程A并沒有退出,說明其它界面還沒有加載完,讓用戶等待。
這么設(shè)計的好處是,將最耗時的任務(wù)分?jǐn)偝鋈ィ茨鼙WC了用戶快速看到界面,又能在之后的運行中有較高的效率。

6.如何在絢麗和效率之間平衡?

最好的方法是得到界面運行時具體的時間消耗數(shù)據(jù),如果必要可以精確到每個函數(shù)。得到一份系統(tǒng)正常情況下的數(shù)據(jù),得到幾份環(huán)境惡劣情況下的數(shù)據(jù)(比如系統(tǒng)非常繁忙、設(shè)備電量很少、要處理的數(shù)據(jù)非常多等)。定量的去分析解決這些問題。如果在惡劣的環(huán)境下你的絢麗界面表現(xiàn)的仍然不錯,恭喜你,你太棒了!

Windows CE/Windows Mobile也提供了些基本的Performance API(像DirectDraw等技術(shù)還有自己的Performance接口和工具):

BOOL QueryPerformanceCounter(LARGE_INTEGER* lpPerformanceCount);
lpPerformanceCount

[in] Pointer to a variable that the function sets, in counts, to the current performance-counter value. If the installed hardware does not support a high-resolution performance counter, this parameter can be set to zero.

This function retrieves the current value of the high-resolution performance counter if one is provided by the OEM.

BOOL QueryPerformanceFrequency(LARGE_INTEGER* lpFrequency);
lpFrequency

[out] Pointer to a variable that the function sets, in counts per second, to the current performance-counter frequency. If the installed hardware does not support a high-resolution performance counter, the value passed back through this pointer can be zero.

This function retrieves the frequency of the high-resolution performance counter if one is provided by the OEM.

上面兩個API需要OEM在OAL層提供實現(xiàn),精度可以低于1ms,否則可以使用下面的API。

DWORD GetTickCount(void);

For Release configurations, this function returns the number of milliseconds since the device booted, excluding any time that the system was suspended. GetTickCount starts at zero on boot and then counts up from there.

For debug configurations, 180 seconds is subtracted from the the number of milliseconds since the device booted. This enables code that uses GetTickCount to be easily tested for correct overflow handling.

另外優(yōu)化PNG、Bitmap、GIF等圖片,讓圖片清晰度和大小剛好滿足要求。

7.控件為什么如此降低運行效率?怎樣減少控件的使用?

手機軟件不同于桌面系統(tǒng)軟件,一方面手機的處理速度更低、電池容量更小,另一方面用戶會使用手機處理更緊急的事情。所以這也是我認(rèn)為 不應(yīng)該完全把桌面系統(tǒng)軟件開發(fā)經(jīng)驗借鑒到手機軟件開發(fā)上的原因。一個240x320分辨率大小的手機界面,你給放上5、6個控件,甚至更多,這個界面注定不會太高效率,這樣的界面也不適合作為用戶最常用的界面,比如今日界面。另一方面,Windows的標(biāo)準(zhǔn)、通用控件不會有太絢麗的外觀,即使自定義的。但是這些控件能夠帶來很明顯的開發(fā)速度。所以我們要協(xié)調(diào)好。不能為了窗口而窗口,更不能一切皆窗口。
那么你會問如何協(xié)調(diào)。我的建議是能不用控件的地方就不要用,大多地方可以直接使用圖片,比如實現(xiàn)多狀態(tài)按鈕你可以這樣做:
WM_LBUTTONDOWN消息處理里面先判斷Point是否在按鈕的Rect中,如果是將按下狀態(tài)的圖片DC BitBlt到屏幕對應(yīng)位置,WM_LBUTTONUP消息處理里面再BitBlt回來。

8.基于Win32的界面運行效率比基于.NET CF高,但是開發(fā)效率低,怎么辦?

Win32編程已經(jīng)很古老、很“落后”了。但是在處理速度還不及奔三的Windows嵌入式設(shè)備上有時你不得不選擇。把界面常用的功能代碼封裝成庫(類庫也可以),積累這樣的資源可以提高團隊的開發(fā)效率。C++泛型編程就是以犧牲編譯時效率換取代碼重用,但是不影響運行時效率,值得去深入學(xué)習(xí)下,而且有現(xiàn)成的庫可用,比如STL。

還有其它的技術(shù)可供選擇:DirectDraw(后面介紹的)、Direct3DM、OpenGL ES等。但是開發(fā)難度較高。

9.如何使用GDI+(Native/Managed)?

GDI+是GDI的下一個版本,它進行了很好的改進,并且易用性更好。GDI的一個好處就是你不必知道任何關(guān)于數(shù)據(jù)怎樣在設(shè)備上渲染的細(xì)節(jié),GDI+更好的實現(xiàn)了這個優(yōu)點,也就是說,GDI是一個中低層API,你還可能要知道設(shè)備,而GDI+是一個高層的API,你不必知道設(shè)備。以下引用自MSDN文檔:

"2-D vector graphics involves drawing primitives (such as lines, curves, and figures) that are specified by sets of points on a coordinate system.

For example, the Rect class stores the location and size of a rectangle; the Pen class stores information about line color, line width, and line style; and the Graphics class has methods for drawing lines, rectangles, paths, and other figures. There are also several Brush classes that store information about how closed figures and paths are to be filled with colors or patterns.

Certain kinds of pictures are difficult or impossible to display with the techniques of vector graphics. Imaging part will resolve this problem. An example of such a class is CachedBitmap, which is used to store a bitmap in memory for fast access and display.

Typography is concerned with the display of text in a variety of fonts, sizes, and styles. One of the new features in GDI+ is subpixel antialiasing. “

Windows CE/Windows Mobile下的GDI+僅僅是Windows桌面系統(tǒng)的一個很小的子集。OpenNETCF中封裝了GDI+,可以為基于.NET CF的開發(fā)者提供便利,微軟提供的Native Code版本就是前面有提到的Imaging COM組件,你也可以直接調(diào)用gdiplus.dll里面的類和方法。網(wǎng)上已經(jīng)有人將Windows CE版本GDI+不支持的部分桌面系統(tǒng)版本GDI+的功能整理進來,你可以使用其提供的Lib庫和頭文件進行開發(fā)。但可能不是很穩(wěn)定。

Windows Mobile 6中的gdiplus.dll文件:

image

將上面的dll文件導(dǎo)出得到的函數(shù):

image

10.如何實現(xiàn)透明控件等其它問題?

因為Windows系統(tǒng)目前不支持窗口Alpha透明,所以無法直接使控件背景透明,我們常用的方法是將控件后面的窗口中對應(yīng)的背景作為控件的背景。

原理說的有點繞,你可以去研究下代碼:

http://www.codeproject.com/KB/mobile/transparent_controls.ASPx(C++)

http://www.codeproject.com/KB/dotNET/TransparentControl.ASPx(C#)

其它參考內(nèi)容:

黎波的博客

怎樣在Windows Mobile上設(shè)計一個美觀的用戶界面程序(Win32)

Windows Mobile 6.0下實現(xiàn)自繪多種狀態(tài)按鈕(Win32)

Windows Mobile 6.0下實現(xiàn)自繪多種狀態(tài)按鈕(Win32) 續(xù)

NET技術(shù)如何開發(fā)絢麗、高效率的界面(Windows嵌入式系統(tǒng)),轉(zhuǎn)載需保留來源!

鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請第一時間聯(lián)系我們修改或刪除,多謝。

主站蜘蛛池模板: 通海县| 邯郸市| 阿克苏市| 香河县| 温泉县| 大化| 成安县| 三原县| 清远市| 炎陵县| 施秉县| 南城县| 铜山县| 新津县| 石狮市| 乐都县| 威海市| 红河县| 锡林浩特市| 甘孜| 福海县| 江城| 河东区| 繁峙县| 襄城县| 平乐县| 岳阳县| 象州县| 长丰县| 安国市| 永仁县| 舟山市| 吉林市| 宜君县| 平武县| 漳平市| 水富县| 东丰县| 册亨县| 屏东市| 独山县|