早在第十七课,就已经介绍了CChart在炫彩界面库中的使用方法。不过呢,那里的方法有一点小问题,就是我们有点霸道,占用了整个客户区。一般情况下,这样是不太合适的,因此,笨笨一直有重写一个炫彩教程的想法。
但是,炫彩是一个收费的软件,其设计器的价格不便宜,笨笨囊中羞涩,根本买不起。但没有设计器的话,炫彩的布局xml文件比较难写,所以这事就一直搁置下了。
但炫彩界面库有一个早期的v2.1.1版有免费版本的设计器,虽然功能受限,但也是勉强能用的,笨笨尝试了一下,也就写下了这一课教程。
由于炫彩界面库更新很快,其接口函数有不断有所变化,目前版本已经到v3.1了,因此这一课的代码需要根据升级情况加以修改才能适合新版本,不过基本的编程框架和编程思想是完全没有问题的。
A52.1 界面布局文件
各类DirectUI界面库,其最主要的功能,就是利用xml文件(或类似的文件)进行界面布局,实现界面和逻辑分离,简化编程。
炫彩界面库的xml布局文件,当然可以用手撸,但这个有点难度。因为炫彩的商业化程度比较高,主推其收费的炫彩界面设计器,加上更新频繁,很难找到xml布局文件的详细文档。因此,这里我们用免费的v2.1.1版本界面设计器进行界面布局设计。
如图所示,我们建立了一个非常简单的布局工程,工程名为Simple。虽然简单,也可以代表大多数应用场景了。
炫彩界面库的标题栏是空的,没有常见的三个标准按钮,我们加了一个buttonUI按钮控件,标题是“关闭”,用于关闭程序,不然不好退出程序。
这个按钮的ID设为数字121。
其实ID直接设置为数字是没有办法的事,因为免费版的界面设计器无法把ID保存到资源文件resource.res文件中。这里加的控件很少,用数字也没有什么问题。
在客户区首先添加一个layoutObject控件,充满整个客户区。
然后再在这个控件里面添加两个layoutObject控件。第一个控件高度方向充满父控件,宽度设置为100。第二个控件高度方向充满父控件,宽度设置为”:1”,即占用剩余空间。
在左边的layoutObject控件里放置一个buttonUI按钮控件,内容属性修改为“信息按钮”,ID设置为数字122。
在右边的layoutObject控件里放置一个基础元素elementUI控件,ID设置为数字151,我们的图就准备画在这个控件上。
下面就是我们添加的所有控件之间的隶属关系。
A52.2 代码编写
利用Visual Studio 建立一个空的Win32项目LessonA52。
新建一个cpp文件,并加入项目。
从炫彩界面库的文档中拷贝一个加载界面布局文件的模板,放在这个文件里面,全部代码如下。
#include "stdafx.h"#pragma comment(lib, "XCGUI.lib")#include "xcgui.h"class CMyWindowDemo{public:HWINDOW m_hWindow;CMyWindowDemo(){Init();}void Init(){XC_LoadResource(L".\\resource.res"); //加载资源文件HXCGUI hXCGUI=XC_LoadLayout(L".\\layout.xml"); //加载布局文件if(XC_IsHWINDOW(hXCGUI)){m_hWindow=(HWINDOW)hXCGUI;//XC_GetObjectByID(m_hWindow, 100); //获取指定ID对象//XC_GetObjectByName(L"name") //获取指定name对象//XC_ShowLayoutFrame(TRUE); //显示布局边界XWnd_AdjustLayout(m_hWindow);XWnd_ShowWindow(m_hWindow,SW_SHOW);}else{//错误}};int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow){XInitXCGUI(FALSE);CMyWindowDemo MyWindow;XRunXCGUI();XExitXCGUI();return 0;}
直接编译,发现一个编译错误。
c:\program files (x86)\microsoft visual studio 10.0\vc\atlmfc\include\afx.h(24): fatal error C1189: #error : Building MFC application with /MD[d] (CRT dll version) requires MFC shared dll version. Please #define _AFXDLL or do not use /MD[d]
对项目配置进行一点调整。
这下编译正常了。
把前面建立好的布局文件连同其所在的Simple文件夹一起,拷贝到LessonA52的内层文件夹里面。
在Init()函数里正确设置布局文件的路径。
XC_LoadResource(L".\\Simple\\resource.res"); //加载资源文件HXCGUI hXCGUI=XC_LoadLayout(L".\\Simple\\layout.xml"); //加载布局文件
现在编译,运行程序如图。
在Init()函数里面添加这句话可以让关闭按钮起到预期的作用。
HELE hCloseBtn = (HELE)XC_GetObjectByID(m_hWindow, 121);XBtn_SetType(hCloseBtn,button_type_close);
添加CChart和数学库的引用。
#include "Chart.h"#if defined(_UNICODE) || defined(UNICODE)#pragma comment(lib,"CChartu.lib")#else#pragma comment(lib,"CChart.lib")#endifusing namespace NsCChart;#include <math.h>
在HWINDOW m_hWindow;一行下面添加一个绘图变量。
CChart m_Chart;
在Init()函数里初始化绘图变量。
double pi=3.1415926516;for(int i=0; i<720; ++i){m_Chart.AddPoint2D(i, 1.3*sin(i*2.0*pi/360));}m_Chart.SetTitle(_T("炫彩界面库"));
在CMyWindowDemo类中编写一个绘图函数,这个函数实现在右边的elementUI控件上绘图。
int OnPanelDraw(HDRAW hDraw,BOOL *pbHandled){RECT rect;HELE hPanel = (HELE)XC_GetObjectByID(m_hWindow, 151);XEle_GetClientRect(hPanel, &rect);HDC hDC = XDraw_GetHDC(hDraw);XEle_DrawEle(hPanel, hDraw);m_Chart.OnDraw(hDC, rect);*pbHandled=TRUE;return 0;}
在Init()函数里面为控件注册这个绘图函数。
HELE hPanel = (HELE)XC_GetObjectByID(m_hWindow, 151);XEle_RegEventCPP(hPanel, XE_PAINT, &CMyWindowDemo::OnPanelDraw);
现在运行,效果如图。
目前已经实现了在右边的elementUI控件上绘图。
存在的问题是暂没有消息响应,下面就解决这个问题。其实增加消息响应的方法和第17课基本一样。
先编写消息响应函数。
int OnEleLButtonDown(UINT nFlags,POINT *pPt,BOOL *pbHandled){HWND hWnd = XWnd_GetHWND(m_hWindow);if(m_Chart.OnLButtonDown(hWnd, *pPt, 0)){XWnd_RedrawWnd(m_hWindow);}*pbHandled = FALSE;return 0;}int OnEleLButtonUp(UINT flags,POINT *pPt,BOOL *pbHandled){HWND hWnd = XWnd_GetHWND(m_hWindow);if(m_Chart.OnLButtonUp(hWnd, *pPt, 0)){XWnd_RedrawWnd(m_hWindow);}*pbHandled = FALSE;return 0;}int OnEleLButtonDblClk(HWINDOW hWindow,UINT nFlags,POINT *pPt, BOOL *pbHandled){HWND hWnd = XWnd_GetHWND(m_hWindow);if(m_Chart.OnLButtonDblClk(hWnd, *pPt, 0)){XWnd_RedrawWnd(m_hWindow);}*pbHandled = FALSE;return 0;}int OnEleRButtonDown(HWINDOW hWindow,UINT nFlags,POINT *pPt, BOOL *pbHandled){HELE hPanel = (HELE)XC_GetObjectByID(m_hWindow, 151);XEle_PointClientToWndClient(hPanel, pPt);HWND hWnd = XWnd_GetHWND(m_hWindow);ClientToScreen(hWnd, pPt);if(m_Chart.OnContextMenu(NULL, hWnd, *pPt)){XWnd_RedrawWnd(m_hWindow);}*pbHandled = FALSE;return 0;}int OnEleMouseMove(HWINDOW hWindow,UINT nFlags,POINT *pPt, BOOL *pbHandled){HWND hWnd = XWnd_GetHWND(m_hWindow);if(m_Chart.OnMouseMove(hWnd, *pPt, 0)){XWnd_RedrawWnd(m_hWindow);}*pbHandled = FALSE;return 0;}
再到Init()函数里注册这些响应函数。
XEle_RegEventCPP(hPanel, XE_LBUTTONDOWN, &CMyWindowDemo::OnEleLButtonDown);XEle_RegEventCPP(hPanel, XE_LBUTTONUP, &CMyWindowDemo::OnEleLButtonUp);XEle_RegEventCPP(hPanel, XE_LBUTTONDBCLICK, &CMyWindowDemo::OnEleLButtonDblClk);XEle_RegEventCPP(hPanel, XE_RBUTTONDOWN, &CMyWindowDemo::OnEleRButtonDown);XEle_RegEventCPP(hPanel, XE_MOUSEMOVE, &CMyWindowDemo::OnEleMouseMove);
现在一切正常了!!!
前面创建的布局文件中,客户区左边还添加了一个按钮。其实这个按钮没有什么用,这里随便使用一下吧。
点击按钮的响应函数如下。
int My_EventDrawBtnClick(BOOL *pbHandled){MessageBoxW(XWnd_GetHWND(m_hWindow),L"右半边是绘图区域",L"提示",MB_OK);*pbHandled=TRUE;return 0;}
注册这个响应函数。
HELE hDrawBtn = (HELE)XC_GetObjectByID(m_hWindow, 122);XEle_RegEventCPP(hDrawBtn,XE_BNCLICK,&CMyWindowDemo::My_EventDrawBtnClick); //注册按钮点击事件
点击按钮,就弹出这个窗口。
OK,收工。