📄 skf_mapview.cpp
字号:
// Skf_MapView.cpp : implementation of the CSkf_MapView class
//
#include "stdafx.h"
#include "Skf_Map.h"
#include "Skf_MapDoc.h"
#include "Skf_MapView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CSkf_MapView
IMPLEMENT_DYNCREATE(CSkf_MapView, CView)
BEGIN_MESSAGE_MAP(CSkf_MapView, CView)
//{{AFX_MSG_MAP(CSkf_MapView)
ON_WM_LBUTTONDOWN()
ON_WM_MOUSEMOVE()
ON_WM_LBUTTONUP()
ON_COMMAND(IDM_BKCOLOR, OnBkcolor)
ON_WM_ERASEBKGND()
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
//以下两行为手工添加
ON_COMMAND_RANGE(ID_MAP,ID_MYPHOTO, OnShowLayer)
ON_UPDATE_COMMAND_UI_RANGE(ID_MAP,ID_MYPHOTO,OnUpdateLayerButtonFace)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CSkf_MapView construction/destruction
CSkf_MapView::CSkf_MapView()
{
OrgX=0; OrgY=0; //地图圆心坐标在客户区左上角
m_BitLayer=0x001f;//各图层初始为全显示,集对应位为1
b_MapMove=FALSE;
BKColor=RGB(0,0,0);//地图背景初始色
pTxt.Format("%s",
" 本程序旨在与大家探讨如何在\n\
VisualC++下实现:\n\
1.无闪烁地图、图形、位图的绘制,\n\
2.鼠标抓拖地图背景的程序实现原理,\n\
3.地图分层的实现,\n\
4.视图打印的实现,\n\
5.几个好用的MFC类的使用方法,\n\
等一些本人工作中总结的一点经验,\n\
希望能与大家共享其中的乐趣,同\n\
时也欢迎大家提出宝贵的批评意见。\n\
如想与我联系,告诉你我的E-mail: \n\
spp_sohu@sohu.com\n\n\
注:本程序所用地图数据只是为了\n\
就说明程序实现方法而取的逻辑坐标\n\
点,并非通过实际测量所得数据,也\n\
没有任何地理意义,读者如果需要绘\n\
出实际有用的地图,则需要通过专用\n\
设备获取准确测量的数据并经过相应\n\
的坐标转换处理(这是一个较复杂的\n\
过程),然后使用转换后的数据进行\n\
程序作图。如果您执意要使用作者程\n\
序中使用的地图文件作图,由此引起\n\
的一切不良后果本人概不负责");
}
CSkf_MapView::~CSkf_MapView()
{
}
BOOL CSkf_MapView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CSkf_MapView drawing
void CSkf_MapView::OnDraw(CDC* pDC)
{
CSkf_MapDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
GetClientRect(&rect); //获取当前客户区域的大小
//在内存中开辟一块与当前DC相同的DC然后在其上作图
CDC mDC;
mDC.CreateCompatibleDC(pDC);
CBitmap MemBitmap;
MemBitmap.CreateCompatibleBitmap(pDC,rect.right ,rect.bottom );
CBitmap *pOldBitmap=mDC.SelectObject(&MemBitmap);
//改变背景颜色
CBrush Brush_Bak(BKColor);
CBrush *pOldBrush=mDC.SelectObject(&Brush_Bak);
mDC.SelectObject(Brush_Bak);
mDC.FillRect(&rect,&Brush_Bak);
mDC.SelectObject(pOldBrush);
//在以下绘图函数调用中,语句的先后决定了图层的先后,即先绘的在最下层。
for (int i=0;i<3;i++)
SKFDrawMap(&mDC,i);
SKFDrawBitmap(&mDC,rect.right-190,rect.bottom-528,IDB_BMPME);
SKFDrawText(&mDC);
SKFDrawYellowriver(&mDC);
SKFDrawChinese(&mDC);
//将内存DC上所绘内容一次性拷贝到当前DC
pDC->BitBlt(0,0,rect.right ,rect.bottom ,&mDC,0,0,SRCCOPY);
}
/////////////////////////////////////////////////////////////////////////////
// CSkf_MapView printing
BOOL CSkf_MapView::OnPreparePrinting(CPrintInfo* pInfo)
{
pInfo->SetMaxPage(2);
BOOL bRet = DoPreparePrinting(pInfo);
pInfo->m_nNumPreviewPages = 2;
return bRet;
}
void CSkf_MapView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CSkf_MapView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}
/////////////////////////////////////////////////////////////////////////////
// CSkf_MapView diagnostics
#ifdef _DEBUG
void CSkf_MapView::AssertValid() const
{
CView::AssertValid();
}
void CSkf_MapView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CSkf_MapDoc* CSkf_MapView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CSkf_MapDoc)));
return (CSkf_MapDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CSkf_MapView message handlers
void CSkf_MapView::SKFDrawMap(CDC *pDC,int layer)
{
if(!(m_BitLayer&0x0001)) return;
CSkf_MapDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
CPen cpen;
CPen *oldpen;
COLORREF COLOR;
if(layer==3)//黄河
COLOR=RGB(0,0,255);
else //国界
COLOR=RGB(255,128,64);
cpen.CreatePen(PS_SOLID,2,COLOR);
oldpen=pDC->SelectObject(&cpen);
pDC->MoveTo(pDoc->pMapDataAry[layer][0].x-OrgX,pDoc->pMapDataAry[layer][0].y+OrgY);
for(int i=1;i<pDoc->pMapDataAry[layer].GetSize();i++)
pDC->LineTo(pDoc->pMapDataAry[layer][i].x-OrgX,pDoc->pMapDataAry[layer][i].y+OrgY);
pDC->SelectObject(oldpen);
}
void CSkf_MapView::SKFDrawText(CDC *pDC)
{
if(!(m_BitLayer&0x0002)) return;
//初始化字体
LOGFONT logFont;
memset(&logFont, 0, sizeof(LOGFONT));
logFont.lfHeight =16;
logFont.lfWidth =7;
strcpy(logFont.lfFaceName,"新宋体");
CFont font;
CFont* pOldFont = NULL;
if (font.CreateFontIndirect(&logFont))
pOldFont = pDC->SelectObject(&font);
TEXTMETRIC tm;
pDC->SetBkMode(TRANSPARENT);//设置字体背景为透明
pDC->GetTextMetrics(&tm); //取得字符的属性宽和高
CRect rect;
GetClientRect(&rect);
pDC->SetTextColor(RGB(128,255,128));
pDC->Draw3dRect(CRect(rect.right -tm.tmAveCharWidth*36-10,rect.bottom -(tm.tmHeight+tm.tmExternalLeading)*30,rect.right-15,rect.bottom-25),
RGB(255,255,255),RGB(100,100,100));//画一个3D矩形框
pDC->DrawText(pTxt,CRect(rect.right -tm.tmAveCharWidth*36,rect.bottom -(tm.tmHeight+tm.tmExternalLeading)*24,rect.right,rect.bottom),DT_EXPANDTABS);
logFont.lfHeight = 44;
logFont.lfWidth = 22;
CFont font1;
if (font1.CreateFontIndirect(&logFont))
pOldFont = pDC->SelectObject(&font1);
COLORREF oldcol=pDC->SetTextColor(RGB(255,64,64));
pDC->DrawText("说\n明",CRect(rect.right-240,rect.bottom-520,rect.right,rect.bottom),DT_EXPANDTABS);
pDC->SelectObject(pOldFont);
pDC->SetTextColor(oldcol);
}
void CSkf_MapView::SKFDrawChinese(CDC *pDC)
{
if(!(m_BitLayer&0x0004)) return;
LOGFONT logFont;
memset(&logFont, 0, sizeof(LOGFONT));
logFont.lfHeight =44;
logFont.lfWidth =22;
strcpy(logFont.lfFaceName,"新宋体");
CFont font;
CFont* pOldFont = NULL;
if (font.CreateFontIndirect(&logFont))
pOldFont = pDC->SelectObject(&font);
TEXTMETRIC tm;
pDC->GetTextMetrics(&tm); //取得字符的属性宽和高
CString strText;
strText.Format ("中 华 人 民 共 和 国");
COLORREF oldcol=pDC->SetTextColor(RGB(255,0,0));
pDC->SetBkMode(TRANSPARENT);
pDC->TextOut (554-OrgX,523+OrgY,strText);
pDC->SelectObject(pOldFont);
pDC->SetTextColor(oldcol);
}
void CSkf_MapView::SKFDrawYellowriver(CDC *pDC)
{
if(!(m_BitLayer&0x0008)) return;
SKFDrawMap(pDC,3);
}
void CSkf_MapView::SKFDrawBitmap(CDC *pDC,int left,int top,UINT ID_BMP)
{
if(!(m_BitLayer&0x0010)) return;
CDC m_SrcDC;
BITMAP bminfo;
CBitmap* pbmface=new CBitmap();
pbmface->LoadBitmap(ID_BMP);
pbmface->GetObject(sizeof(BITMAP),&bminfo);
m_SrcDC.CreateCompatibleDC(pDC);
CBitmap* pOldBitmap=m_SrcDC.SelectObject(pbmface);
pDC->BitBlt(left/*-OrgX*/,top/*+OrgY*/,bminfo.bmWidth,bminfo.bmHeight,&m_SrcDC,0,0,SRCCOPY);
m_SrcDC.SelectObject(pOldBitmap);
pbmface->DeleteObject();
delete pbmface;
}
void CSkf_MapView::OnInitialUpdate()
{
CView::OnInitialUpdate();
}
void CSkf_MapView::OnShowLayer(UINT nID)//手工添加
{
m_BitLayer&(1<<(nID-ID_MAP))? m_BitLayer^=(1<<(nID-ID_MAP)):m_BitLayer|=(1<<(nID-ID_MAP));
Invalidate();
}
void CSkf_MapView::OnUpdateLayerButtonFace(CCmdUI* pCmdUI)//手工添加
{
m_BitLayer&(1<<(pCmdUI->m_nID-ID_MAP))?pCmdUI->SetCheck(1):pCmdUI->SetCheck (0);
}
void CSkf_MapView::OnLButtonDown(UINT nFlags, CPoint point)
{
//让鼠标始终被当前View控制
SetCapture();
//将鼠标光标设置为手形
SetCursor(AfxGetApp()->LoadCursor(IDC_CURMOVE));
MouseDownPoint=point;
b_MapMove=TRUE;
CView::OnLButtonDown(nFlags, point);
}
void CSkf_MapView::OnMouseMove(UINT nFlags, CPoint point)
{
if(!b_MapMove) return;
OrgX+=((MouseDownPoint.x-point.x));
OrgY-=((MouseDownPoint.y-point.y));
MouseDownPoint=point;
Invalidate();
CView::OnMouseMove(nFlags, point);
}
void CSkf_MapView::OnLButtonUp(UINT nFlags, CPoint point)
{
//释放鼠标,交系统控制
ReleaseCapture();
b_MapMove=FALSE;
CView::OnLButtonUp(nFlags, point);
}
void CSkf_MapView::OnBkcolor()
{
//在构造函数中用当前背景色初始化颜色对话框
//这样使得每次打开颜色对话框是都保留上一次的颜色设置
CColorDialog codlg( BKColor, CC_FULLOPEN, NULL );
if(codlg.DoModal()==IDOK)
{
BKColor=codlg.GetColor();
Invalidate(TRUE);
}
}
void CSkf_MapView::OnPrint(CDC* pDC, CPrintInfo* pInfo)
{
CRect rct;
GetClientRect(rct);
pDC->SetMapMode(MM_ANISOTROPIC);
CDC* pViewDC = GetDC();
int numx=pViewDC->GetDeviceCaps(LOGPIXELSX);
int numy=pViewDC->GetDeviceCaps(LOGPIXELSY);
int w=pInfo->m_rectDraw.Width();
int h=pInfo->m_rectDraw.Height();
//转换坐标映射方式
CSize size = CSize(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
pDC->SetWindowExt(size);
//确定窗口大小
//得到实际设备每逻辑英寸的像素数量
int xLogPixPerInch = pDC->GetDeviceCaps(LOGPIXELSX);
int yLogPixPerInch = pDC->GetDeviceCaps(LOGPIXELSY);
//得到设备坐标和逻辑坐标的比例
long xExt;
long yExt;
xExt=(long)(size.cx*xLogPixPerInch/numx) ;
yExt=(long)(size.cy*yLogPixPerInch/numy) ;
pDC->SetViewportExt((int)xExt, (int)yExt);
OnDraw(pDC);
}
BOOL CSkf_MapView::OnEraseBkgnd(CDC* pDC)
{
return TRUE; //让该消息不要使用缺省功能去擦除现有视图背景
// return CView::OnEraseBkgnd(pDC);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -