Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

CMapEditorCtrl

0.00/5 (No votes)
11 Dec 2003 1  
This class provides MFC Control functionality to CMapEditor, and supports isometric view

Sample screenshot

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.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here