Click here to Skip to main content
15,881,882 members
Articles / Desktop Programming / MFC
Article

CMapEditorCtrl

Rate me:
Please Sign up or sign in to vote.
4.45/5 (8 votes)
11 Dec 20033 min read 65.4K   2K   33   14
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


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralRC-File Pin
Mike Wild11-Dec-03 0:56
Mike Wild11-Dec-03 0:56 
GeneralRe: RC-File Pin
eugi12-Dec-03 4:03
eugi12-Dec-03 4:03 
GeneralYou said it was for VC++ 6. Pin
WREY7-Dec-03 20:37
WREY7-Dec-03 20:37 
GeneralRe: You said it was for VC++ 6. Pin
eugi7-Dec-03 23:25
eugi7-Dec-03 23:25 
GeneralRe: You said it was for VC++ 6. Pin
WREY8-Dec-03 6:51
WREY8-Dec-03 6:51 
GeneralRe: You said it was for VC++ 6. Pin
eugi8-Dec-03 6:54
eugi8-Dec-03 6:54 
GeneralRe: You said it was for VC++ 6. Pin
Mike Wild11-Dec-03 0:59
Mike Wild11-Dec-03 0:59 
GeneralRe: You said it was for VC++ 6. Pin
Scott Everts12-Dec-03 4:56
Scott Everts12-Dec-03 4:56 
GeneralRe: You said it was for VC++ 6. Pin
eugi12-Dec-03 4:58
eugi12-Dec-03 4:58 
GeneralRe: You said it was for VC++ 6. Pin
Scott Everts12-Dec-03 5:15
Scott Everts12-Dec-03 5:15 
GeneralRe: You said it was for VC++ 6. Pin
eugi12-Dec-03 5:18
eugi12-Dec-03 5:18 
GeneralRe: You said it was for VC++ 6. Pin
Mike Wild15-Dec-03 1:13
Mike Wild15-Dec-03 1:13 
GeneralWeird Formatting Pin
eugi7-Dec-03 13:11
eugi7-Dec-03 13:11 
GeneralRe: Weird Formatting Pin
eugi8-Dec-03 9:47
eugi8-Dec-03 9:47 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.