GDI+編程的膚淺使用及Char ,CString,WCHAR 之間的轉換小結

前幾天有朋友突然找我幫他想想如何用VC編程在圖片上繪字,並且能夠批量生成新的圖片。其實我對VC編程也不怎麼樣,很多東西都沒用過,大體的概念也就覺得應該可以用GDI編程,讀入圖片入內存,然後使用內存與設備無關的設備描述表作圖來實現,可是仔細翻 Windows程序設計 來看也沒發現可行的辦法,於是沒辦法只好上網上搜,結果發現有人提出過類似問題,網上的高手們的回答有用GDI+的,以前還真沒聽過這個庫。我就只得硬着頭皮上了。

一,建立GDI+的VC&VS開發環境

先下了這個庫的頭文件和庫文件,然後在VC工程配置添加庫和頭文件。具體的操作是這樣的:

VC6.0下面的操作:

在菜單項:Project->settings->Link->Object/Library Module裏面填入gdiplus.lib.這個靜態庫文件應該拷到工程的文件夾下,不然應該填入全整路徑。

在stdafx.h中我添加了如下代碼:

#ifndef ULONG_PTR
#define ULONG_PTR unsigned long*
#include "./GDIPlus/Includes/GdiPlus.h"
using namespace Gdiplus;

#include "./GDIPlus/Includes/GdiPlus.h"這兒是因爲我解壓的路徑在工程文件夾下。網上也有人把include文件夾內容直接拷到VC的安裝文件裏面的include裏面的。

VS2005下面的配置與上面略有不同。沒有定義宏ULONG_PTR。其餘也就是界面不一樣而已。

接下來,在工程應用程序類(C*App類)裏面添加成員變量 :

ULONG_PTR m_gdiplusToken;

重載CWinApp成員函數:

virtual int ExitInstance();

在C*App::InitInstance()添加語句裝載gdiplus

 Gdiplus::GdiplusStartupInput gdiplusStartupInput;
 Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);

在C*App::ExitInstance()中缷載:

 Gdiplus::GdiplusShutdown(m_gdiplusToken);
 return CWinApp::ExitInstance();

如此即可以在View或Fram類裏面使用gdiplus相應的類了


二,如何在一張圖片(常見的幾種格式)上作圖

我在網上學到的方法大致如此:

首先定義一個Bitmap或Image的對象

如Image img(L"example.jpg");

然後由Image或Bitmap 的一個靜態函數FromImage();

得到一個Graphics 的對象指針。Graphics是一個有作圖接口的類,支持常見的如畫點,線,矩形,橢圓,字符串,填充等操作。顯然這兒作圖的所謂有的DC應該是內存DC,也就是圖片文件的數據區內存。所以做圖後img對象調用其保存函數

img.Save(....);後打開保存後的圖片,就能看見作圖的效果了。

另外,還有一個問題在於如何將一個小圖片複製到一張大圖片,或者說幾張圖片一起拼接成一大圖片。應該是網上的資源是挺豐富的,但是人應該是學以致用的。學會理解,活用,纔是在網上學習的最好方法吧。我對此問題的大致操作如下:

先建立一個大圖片的對象,並指定其寬高:Bitmap bigBmp(width,height);

獲取小圖片對象:Bitmap smallBmp(L"resource.jpg");

由上面總結的在圖片上繪圖的方法得到Graphics *並在smallBmp完成相應字符串等的繪製。

同樣的得到一個指向bigBmp的Graphics*,將完成做圖後的小圖片smallBmp畫到指定的位置就OK了。即:

Bitmap::FromImage(bigBmp)->DrawImage(&smallBmp,x,y);

三:關於Char* ,CString ,WCHAR*之間的轉換問題

GDI+所有類的接口函數如果要傳遞字符串作爲參數的話,似乎都用UNICODE串,即WCHAR*。我開始也被整得暈頭轉向,因爲窗口編程所用往往是CString,用IO流讀文件數據又得到char *。得益於網上牛人們的總結,我用到以下幾種基本方法去實現三者間的轉換:

char * 轉WCHAR *:

::MultiByteToWideChar(CP_ACP,0,(const char *)res,int count,char * dest,int count);

類似地,WCHAR *轉char *:

WideCharToMultiByte(CP_ACP,   0,.........);

CString 轉WCHAR *:

wchar_t * p=str.AllocSysStrinig()

也有A2W(str)的,但是要包括ATL轉換頭文件#include;

並且在A2W前使用USES_CONVERSION宏。

其它:

char*轉CString:

除了直接賦值外,還可使用CString::Format進行。

如char * p="sfdasf";

CString str=p; 或者str.Format("%s",p);

CString 轉char *

1.直接強制類型轉換:

 CString ss="sfasf";
  char *p=(LPSTR)(LPCSTR)ss;

2.CString::GetBuffer或LockBuffer

char * p=str.GetBuffer();

char * pt=str.LockBuffer();

WCHAR *轉CString

在網上沒有找到相關的文檔,想想應該是可以直接賦值的

但是試驗發現雖無編譯錯誤,但是用中文的時候卻生亂碼,用字母的時候卻是正常,想其中肯定沒有錯誤,只是用MessageBox顯示的時候亂碼應該有其它原因,比如說使用了雙字節字符集DBCS來顯示漢字(純屬猜測而已)。總體來說在Windows編程中:#define UNICODE

則CString .TCHAR,等均用的是UNICODE碼,一個字符佔兩個字節。

 

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