笨笨是一個因循守舊的人,一向對新潮的東西不感冒,如今21世紀都過去百分之十幾了,笨笨還在使用二十世紀的VC6。而IT領域是一個長江後浪推前浪,前浪死在沙灘上的世界,所以至今為止,笨笨還被IT領域拒之門外。
雖然笨笨是個老古板,但偶爾追追潮流也是可以的嘛。這些年DirectUI好像紅透大江南北。笨笨也稍微了解了一下,覺得這種編程思想是值得提倡的。
目前優秀的DirectUI庫,商業的就不說了,開源的笨笨知道的有DuiLib和炫彩界面庫。
DuiLib是一款優秀的國產開源DirectUI庫。笨笨在VS2010上把其例子跑通過,但VC6下不行。接觸其代碼不多,反正覺得有些不習慣。
炫彩界面庫是另一款優秀的過程開源DirectUI庫。笨笨對這個庫用起來感覺非常順手,而且不僅在VS2010上,在笨笨親愛的VC6上也跑通了。所以笨笨決定跟定炫彩了,今生非她不娶。
經過一段時間的調試,目前CChart和炫彩界面庫已經完美兼容了。
有一點要說明。炫彩界面庫基於無窗口的思想,裡面只有一個主窗口,其它窗口都是自繪的;而CChart還是原始的Windows編程思想,裡面操作都基於窗口。當CChart愛上炫彩後,愛情的結晶就是一個混血兒。唯一的問題是用CChart彈出的對話框和炫彩本身的對話框風格不一樣。如果不用交互功能,不彈出對話框的話,那就沒有風格不同的問題了。
下面笨笨向大家展示小伙CChart追求妙齡少女炫彩姑娘的全過程。
作為准備工作,需要同學們在炫彩界面庫的官方網站www.xcgui.com上下載最新的炫彩庫。
Now,letsgo!
第一步,用VC建立一個Win32Application工程,名為Lesson17。注意在向導中選擇Anemptyproject,即空工程。
第二步,把CChart的五個庫文件Chart.h、PlotDll_d.lib、PlotDll_d.dll、PlotDll.lib、PlotDll.dll拷貝到Lesson17文件夾中,同時解壓縮炫彩的壓縮包,在lib目錄裡找到xcgui.h、xcguid.lib、xcguid.dll、xcgui.lib、xcgui.dll這五個庫文件,同樣拷貝到Lesson17文件夾中。
第三步,在VC中新建一個Lesson17.cpp文件,添加進工程,並在這個文件中輸入下列從炫彩幫助文檔中拷貝出來的內容。
//包含炫彩界面庫文件 #include "xcgui.h" #ifdef _DEBUG #pragma comment(lib, "XCGUId.lib") #else #pragma comment(lib, "XCGUI.lib") #endif //CXEventMsg : C++消息事件接口類 //CMyWnd : 我的窗口類 class CMyWnd : public CXEventMsg { public: HWINDOW m_hWindow; //窗口句柄 BOOL Create() //創建窗口和按鈕 { m_hWindow=XWnd_CreateWindow(0,0,400,300,L"炫彩界面庫-窗口"); //創建窗口 if(m_hWindow) { XWnd_ShowWindow(m_hWindow,SW_SHOW); //顯示窗口 return true; } return false; } }; int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine, int nCmdShow) { XInitXCGUI(); //初始化 CMyWnd MyWnd; if(MyWnd.Create()) { XRunXCGUI(); //運行 } return 0; }編譯並運行,效果如下。
炫彩的窗口出來啦!下面我們就在這個窗口上,開展我們的工作。
第四步,加入CChart的頭文件和庫文件。
#include "Chart.h" #ifdef _DEBUG #pragma comment(lib, "PlotDll_d.lib") #else #pragma comment(lib, "PlotDll.lib") #endif第五步,加入數學庫頭文件。
#include <math.h>第六步,定義CChart變量。在HWINDOWm_hWindow;這一行下面,輸入以下代碼。
CChart m_Chart;第七步,修改OnCreate函數。改後如下。
BOOL Create() //創建窗口和按鈕 { m_hWindow=XWnd_CreateWindow(0,0,800,600,L"炫彩界面庫-窗口"); //創建窗口 if(m_hWindow) { HWND hWnd = XWnd_GetHWnd(m_hWindow); m_Chart.SetType(kTypeXY, hWnd); const int nLen = 501; double pX[nLen], pY[nLen]; int i, dataID; for(i=0; i<nLen; i++) { pX[i]=2.0/(nLen-1.0)*i; pY[i]=2*sin(pX[i]*8.0*myPi) + (2.0*rand()/RAND_MAX-1.0)*0.3; } dataID = m_Chart.AddCurve(pX, pY, nLen); m_Chart.SetDataTitle("Test data 1", 0, 0); for(i=0; i<nLen; i++) { pX[i]=2.0/(nLen-1.0)*i; pY[i]=(i-nLen/2.0)*(i-nLen/2.0)/nLen/nLen*20.0 + (2.0*rand()/RAND_MAX-1.0)*0.1; } dataID = m_Chart.AddCurve(pX, pY, nLen); m_Chart.SetDataTitle("Test data 2", 1, 0); m_Chart.SetTitle("在炫彩界面庫中繪圖"); XCGUI_RegWndMessage(m_hWindow, WM_PAINT, &CMyWnd::OnWndPaint); XCGUI_RegWndMessage(m_hWindow, WM_LBUTTONDOWN, &CMyWnd::OnWndLButtonDown); XCGUI_RegWndMessage(m_hWindow, WM_LBUTTONUP, &CMyWnd::OnWndLButtonUp); XCGUI_RegWndMessage(m_hWindow, XWM_MOUSEDBCLICK, &CMyWnd::OnWndLButtonDblClk); XCGUI_RegWndMessage(m_hWindow, WM_MOUSEMOVE, &CMyWnd::OnWndMouseMove); XCGUI_RegWndMessage(m_hWindow, WM_KEYDOWN, &CMyWnd::OnWndKeyDown); XCGUI_RegWndMessage(m_hWindow, WM_RBUTTONDOWN, &CMyWnd::OnWndRButtonDown); XWnd_ShowWindow(m_hWindow,SW_SHOW); //顯示窗口 return true; } return false; }第八步,建立OnPaint函數,實現繪圖功能。
RECT rect; int dx, dy; BOOL OnWndPaint(HWINDOW hWindow, HDRAW hDraw) { XWnd_GetDrawRect(hWindow, &rect); HDC hDC = XDraw_GetHDC_(hDraw); XDraw_GetOffset_(hDraw, &dx, &dy); rect.left += dx; rect.top += dy; rect.right -= dx; rect.bottom -= dx; m_Chart.OnDraw(hDC, rect); return FALSE; }
注意這裡在OnWndPaint的前面定義了幾個變量,這些變量在OnWndPaint函數中有用,定義在函數外面的目的是後面的消息響應函數也要用到。
在炫彩界面庫中,不能直接在炫彩中主窗口的客戶區上繪圖,必須加上偏移。因為炫彩的主窗口整個都是客戶區,其標題欄等元素是在客戶區上畫出來的,直接在主窗口客戶區繪圖就會和標題欄以及邊框等元素重疊。
上面的代碼展示了從炫彩獲得客戶區HDC並加上偏移的處理方法。
第九步,實現交互功能的消息處理。代碼如下。
BOOL OnWndLButtonDown(HWINDOW hWindow,UINT flags,POINT *pPt) { HWND hWnd = XWnd_GetHWnd(hWindow); POINT point = *pPt; point.x += dx; point.y += dy; if(m_Chart.OnLButtonDown(hWnd, point)) { XWnd_RedrawWnd(hWindow); } return FALSE; } BOOL OnWndLButtonUp(HWINDOW hWindow,UINT flags,POINT *pPt) { HWND hWnd = XWnd_GetHWnd(hWindow); POINT point = *pPt; point.x += dx; point.y += dy; if(m_Chart.OnLButtonUp(hWnd, point)) { XWnd_RedrawWnd(hWindow); } return FALSE; } BOOL OnWndLButtonDblClk(HWINDOW hWindow,POINT *pPt) { HWND hWnd = XWnd_GetHWnd(hWindow); POINT point = *pPt; point.x += dx; point.y += dy; if(GetCapture()) { ReleaseCapture(); } if(m_Chart.OnLButtonDblClk(hWnd, point)) { XWnd_RedrawWnd(hWindow); } return FALSE; } BOOL OnWndMouseMove(HWINDOW hWindow,UINT flags,POINT *pPt) { HWND hWnd = XWnd_GetHWnd(hWindow); POINT point = *pPt; point.x += dx; point.y += dy; if(m_Chart.OnMouseMove(hWnd, point)) { XWnd_RedrawWnd(hWindow); } return FALSE; } BOOL OnWndKeyDown(HWINDOW hWindow,WPARAM wParam,LPARAM lParam) { HWND hWnd = XWnd_GetHWnd(hWindow); UINT key = wParam; if(m_Chart.OnKeyDown(hWnd, key)) { XWnd_RedrawWnd(hWindow); } return FALSE; } BOOL OnWndRButtonDown(HWINDOW hWindow,UINT flags,POINT *pPt) { HWND hWnd = XWnd_GetHWnd(hWindow); POINT point = *pPt; point.x += dx; point.y += dy; ClientToScreen(hWnd, &point); if(m_Chart.OnContextMenu(NULL, hWnd, point)) { XWnd_RedrawWnd(hWindow); } return FALSE; }
上面的代碼利用CChart的消息處理函數,根據炫彩的實際情況處理各種消息。
好,准備收工了。看看我們的勞動成果。
哈哈,真不錯喲。
下面我們看看CChart的右鍵菜單,如圖。
和原來沒有什麼變化嘛。
再看看CChart的對話框。
果然是混血型,呵呵。
本節課的代碼看似較多,實際上都是可以拷貝的,實際編碼量不算大,而這些代碼的含義是非常容易理解的。
到目前為止,我們的帥小伙CChart終於成功牽手夢中情人炫彩。耶!