65.9K
CodeProject 正在变化。 阅读更多。
Home

CMapEditorCtrl

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.45/5 (8投票s)

2003年12月7日

3分钟阅读

viewsIcon

66602

downloadIcon

1960

这个类为CMapEditor提供MFC控件功能,并支持等距视图

Sample screenshot

引言

我编写了这个类,为之前在CodeProject上发布的类CMapEditorhttps://codeproject.org.cn/cpp/CMapEditor.asp)提供完整的MFC控件功能。这是我编写的第一个自定义控件,请多多包涵;) 基本思路很简单:控件获取一系列位图和一个CMapEditor类型,并向CMapEditor值显示相应的图像。该控件支持鸟瞰标准编辑器模式和等距视图模式。我提供了一个基本的演示应用程序来演示这些概念。我目前正在完善一个等距编辑器,该编辑器将很快可用。在本文中,我将说明使用CMapEditorCtrl所涉及的步骤,我将提供有关每个方法的信息,并且我将讨论该控件的一些已知问题。

使用CMapEditorCtrl

创建控件

您可以通过对话框资源编辑器(如演示应用程序中所示)或使用Create(...)函数来初始化控件,如下所示

CMapEditorCtrl *g_pMapCtrl;
g_pMapCtrl = new CMapEditorCtrl();
g_pMapCtrl->Create(MAPEDCTRLCLASS,NULL,WS_VISIBLE|WS_CHILD,
    CRect(4,4,820,620),this,1000);

我们现在已经成功创建了控件,现在我们必须对其进行初始化。

初始化控件

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

还需要将位图分配给控件。此示例代码演示了如何使用for循环将内存中的HBITMAPS数组循环,并将它们分配给控件。

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);
    }

该控件现在可以使用了。以下部分介绍了使CMapEditorCtrl发挥最佳性能的一些必要步骤。

回调函数

回调函数的工作方式就像一个WindowProc方法。传递给此函数的参数定义为ARG_CTRLPROC。第一个参数是一个整数,iMsg,它对应于消息代码。这可以是由用户定义的(以便可以在控件上执行任何类型的操作),也可以是预定义的值,例如MC_MOUSEMOVEMC_LBCLICKED。用户定义的消息可以使用CMapEditorCtrl::SetValues(...)。在文章的后面可以找到iMsg的可能值的完整列表。

CMapEditorCtrl::SetValues( . . . )

每次需要更改将修改CMapEditor的参数时,都必须调用此方法,当用户与控件交互时。语法非常简单,但要更好地理解这一点,请参考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
);
 

该控件现在完全可用。

基本功能

  • 单击 - 根据iMode执行操作,到选定的单元格,或结束拖动操作。
  • 双击 - 开始拖动操作。
  • 右键单击- 居中选定的单元格
  • Ctrl + 右键单击 - 居中选定的单元格并切换视图模式

类成员

方法

//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);

结构体

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;

定义

//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

问题

编写此控件非常有趣,我希望我分享了一些对MFC社区有用的东西。但是,我意识到存在一些问题,并且我在这里声明,有点像向专家寻求建议。如果打开了许多其他应用程序,则该控件可能会遇到一些性能问题。这主要是由设备上下文绘图引起的,如果控件很大,则绘图会很慢。

该控件已使用64x32的图块进行了测试。尚未尝试使用其他图像大小进行测试(我太懒了;)

如果其他CPian花时间看看CMapEditorCtrl并在报告此处的任何错误,或发布任何建议,我将不胜荣幸,我将尝试满足。此外,我想知道是否有人计划使用此类,只是出于好奇;此代码是完全开源的。

© . All rights reserved.