Introduction
I have written this class to provide full MFC Control functionality to a previous class I had published on CodeProject, CMapEditor
(http://www.codeproject.com/cpp/CMapEditor.asp). This is the first custom control i have written, so please be easy on me ;) The basics are simple: the control takes a series of bitmaps and a CMapEditor
type, and displays the corresponding images to the CMapEditor
values. The control supports both bird-eye-view standard editor mode, and isometric view mode. I have provided a basic demo application that demonstrates these concepts. I am currently polishing an isometric editor which will be shortly available. In this article, i will illustrates the steps involved in using the CMapEditorCtrl
, i will provide information for every method, and I will discuss some know issues with the control.
Using CMapEditorCtrl
Creating the control
You can initialize the control either from the Dialog Resource Editor (as shown in the Demo application), either with the Create(...)
function, as shown here:
CMapEditorCtrl *g_pMapCtrl;
g_pMapCtrl = new CMapEditorCtrl();
g_pMapCtrl->Create(MAPEDCTRLCLASS,NULL,WS_VISIBLE|WS_CHILD,
CRect(4,4,820,620),this,1000);
We have now successfully created the control, now we must initialize it.
Initalizing the control
MECTRLINITSTRUCT isInit;
isInit.iCellHeight = 20;
isInit.iCellWidth = 20;
isInit.iIsoHeight = 16;
isInit.iIsoWidth = 32;
isInit.iMapHeight = 30;
isInit.iMapWidth = 40;
isInit.pMapEditor = g_pMapEditor;
isInit.CtrlProc = ControlProc;
g_pMapCtrl->Initialize(&isInit);
It is also necessary to assign the bitmaps to the control. This sample code demonstrates how to use a for to cycle an array of HBITMAPS
in memory and assign them to the control.
for(int i=0;i<m_nBitmaps;i++)
{
CBitmap *pBitmap = CBitmap::FromHandle(m_hBitmap[i][ISO]);
BITMAP bmInfo;
pBitmap->GetBitmap(&bmInfo);
g_pMapCtrl->AssignBitmap(i+1,m_hBitmap[i][TWOD],m_hBitmap[i][ISO],
bmInfo.bmHeight - 32);
}
The control is now ready for use. The following section describes some of the steps necessary to make CMapEditorCtrl
work at best.
The callback function
The callback function works just as a WindowProc
method. The arguments passed to this function are defined as ARG_CTRLPROC
. The first argument is an integer, iMsg, which corresponds to the message code. This can be either a user defined (so that any kind of operation can be performed on the control), or a predefined value, such as MC_MOUSEMOVE
or MC_LBCLICKED
. User-defined messages can be used by using CMapEditorCtrl::SetValues(...)
. A complete list of possible values for iMsg can be found further down in the article.
CMapEditorCtrl::SetValues( . . . )
This method must be called every time that it is necessary to change the parameters that will modify the CMapEditor when the user interacts with the control. The syntax is pretty straightforward, but to understand this at best refer to CMapEditor::SetMapValue .
SetValues(
int iValue,
int iLevel
int iMode
bool bCanDrag
);
The control is now completely functional.
Basic functionality
- Single click - performs an operation based on iMode, to the selected cell, or ends a drag operation.
- Double click - begins a drag operation.
- Right click- centers the selected cell
- Ctrl + Right click - centers the selected cell and switches view mode
Class Members
Methods
bool AssignBitmap(int iBitmap,HBITMAP h2DBitmap,HBITMAP hIsoBitmap,
int iHeight = 0);
void CenterCell(CPoint ptPos);
void DrawItem(CRect rUpdate = CRect(-1,-1,-1,-1));
void DrawLevel(int iLevel,bool bDraw = true);
void GetInfo(MECTRLINFO* mciInfo);
int GetPos(int nCoord);
void HighlightCell(CPoint ptPos);
bool Initialize(MECTRLINITSTRUCT* isInitStruct);
void SetValues(int iValue, int iLevel, int iMode, bool bCanDrag);
void SetViewMode(int nViewMode,bool bUpdate = true);
Structures
typedef struct _SETSTRUCT
{
unsigned short int iValue;
unsigned short int iLevel;
unsigned short int iMode;
bool bCanDrag;
}SETSTRUCT;
typedef struct _MECTRLINITSTRUCT
{
CMapEditor* pMapEditor;
short int iCellWidth;
short int iCellHeight;
short int iIsoWidth;
short int iIsoHeight;
short int iMapWidth;
short int iMapHeight;
void (*CtrlProc)(ARG_CTRLPROC);
}MECTRLINITSTRUCT;
typedef struct _MECTRLINFO
{
CPoint ptPos;
CPoint ptScroll;
int iMode;
int iLevel;
int iValue;
}MECTRLINFO;
Defines
MC_MOUSEMOVE
MC_LBCLICKED
MC_RBCLICKED
MC_SCROLL
MC_SETVIEWMODE
MC_CENTERCELL
TWOD
ISO
GP_X
GP_Y
Issues
Programming this control was extremely fun, and I hope I have shared something useful to the MFC community. There are, however, some issues which I am aware of, and I state here, somewhat as to ask advice to experts. The control may experience some performance problems, usually if many other apps are open. This is primarily caused by the device context painting, which is slow if the control is big.
The control has been tested with tiles that were 64x32. Testing with other image sizes has not been tried (lazy me ;)
I'd be honored if any other CPian will take the time to take a look at CMapEditorCtrl
and report here any bug, or post any suggestion, which I will try to satisfy. Also, I'd like to know if anybody is planning on using this class, just out of curiosity; this code is completely open-source.