CMapEditorCtrl






4.45/5 (8 votes)
Dec 7, 2003
3 min read

66042

1960
This class provides MFC Control functionality to CMapEditor, and supports isometric view
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; //The structure isInit.iCellHeight = 20; //Cell height, in pixels isInit.iCellWidth = 20; //Cell width, in pixels isInit.iIsoHeight = 16; //Half the height of the isometric images isInit.iIsoWidth = 32; //Half the width of the isometric images isInit.iMapHeight = 30; //Number of rows in 2D editor isInit.iMapWidth = 40; //Number of columns in 2D editor isInit.pMapEditor = g_pMapEditor; //Pointer to a CMapEditor isInit.CtrlProc = ControlProc; //Callback function g_pMapCtrl->Initialize(&isInit); //Initialize the control
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, //The cells will be changed to this value int iLevel //This level will be affected int iMode //0 corresponds to normal //1 corresponds to CMapEditor::Fill(...) //Use other values for user-defined functionalites, this will be //passed to the callback function as iMsg. bool bCanDrag //For use with a user-defined iMode, TRUE, //if dragging is allowed //in the control );
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
//Assigns bitmaps h2DBitmap and hIsoBitmap to value iBitmap //(iHeight is extra height in isometric bitmap) bool AssignBitmap(int iBitmap,HBITMAP h2DBitmap,HBITMAP hIsoBitmap, int iHeight = 0);
//Centers the cell specified by ptPos void CenterCell(CPoint ptPos);
//Draws the control void DrawItem(CRect rUpdate = CRect(-1,-1,-1,-1));
//Sets wether a level is drawn or not void DrawLevel(int iLevel,bool bDraw = true);
//Retrieves control information void GetInfo(MECTRLINFO* mciInfo);
//Returns the x or y coordinate of the currently selected cell int GetPos(int nCoord);
//Highlights the cell specified by ptPos void HighlightCell(CPoint ptPos);
//Initializes the Map Control bool Initialize(MECTRLINITSTRUCT* isInitStruct);
//Sets the values void SetValues(int iValue, int iLevel, int iMode, bool bCanDrag);
//Sets the view mode void SetViewMode(int nViewMode,bool bUpdate = true);
Structures
typedef struct _SETSTRUCT { //Structure used to change the mode values for the map unsigned short int iValue; unsigned short int iLevel; unsigned short int iMode; bool bCanDrag; }SETSTRUCT;
typedef struct _MECTRLINITSTRUCT { //Structure used to initialize the map control CMapEditor* pMapEditor; //Pointer to a CMapEditor object short int iCellWidth; //Width of the 2D cells short int iCellHeight; //Height of the 2D cells short int iIsoWidth; //Half the width of the isometric tiles short int iIsoHeight; //Half the standard height of the isometric tiles short int iMapWidth; //Number of 2D cells displayed across the control short int iMapHeight; //Number of 2D cells displayed down the control void (*CtrlProc)(ARG_CTRLPROC); //Callback function }MECTRLINITSTRUCT;
typedef struct _MECTRLINFO { //Structure containing relevant information about the CMapEditorCtrl CPoint ptPos; //Currently selected cell CPoint ptScroll; //Current scroll coordinates int iMode; //Current mode int iLevel; //Current level int iValue; //Current value }MECTRLINFO;
Defines
//Values for iMsg MC_MOUSEMOVE //Mouse moved MC_LBCLICKED //Left mouse button clicked MC_RBCLICKED //Right mouse button clicked MC_SCROLL //Scrolled MC_SETVIEWMODE //Changed view mode MC_CENTERCELL //Cell centered
//Values for nViewMode TWOD //Normal 2D editor mode ISO //Isometric editor mode
//Value for nCoord GP_X //X coordinate GP_Y //Y coordinate
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.