ArcGIS地图控件上作平移(Pan)操作经常会出现白边问题。现象如下:
这其实是一个用户体验的问题,ESRI在ArcGIS10下仍然没有解决,也有可能ESRI根本就不认为在桌面产品中这是一个问题。但是很多用户却认为这是一个需要解决的问题,用户的感受其实是第一位的,事实上在Web上就没有这个问题。当然解决的方法是有的,就是自己写一个平移小工具。那自己写应该怎么办呢,这里提供一个思路。
在解决图像浏览的体验问题中,通常使用的技巧是双缓冲显示技术,简单讲来就是在下一幅图像流览前,现在内存中提前生成好,等需要开始加载刚才提到的下一幅图像时,直接拷贝对应内存中的图像到当前显示设备(在这里就是指屏幕了)。我们自己的平移工具也可以使用这种方式,提前在内存中生成好需要浏览的内容,等平移开始就拷贝内存中生成的合适内容到前端屏幕,当然在完成平移后又提前生成好需要浏览的内容,依次循环。
多大的图像范围是我们需要在内存中提前准备好的?考虑到工具本身的特点,我们可以准备好一个3X3的范围,类似一个九宫格,最中间就是当前地图显示窗口的范围。当然显示的地图内容就是按上述的范围对应往外扩。
我在这里写了一部分测试代码来生成这个内存中的图像然后拷贝到前端,事实上用户是需要通过计算来把内存中的图像裁减到屏幕中的,不然图像的内容和真实数据对应不上呵。
HRESULT hr;
IHookHelperPtr ipHookHelper(CLSID_HookHelper);
hr=ipHookHelper->putref_Hook(m_ipDispatch);
IActiveViewPtr ipActiveView;
hr=ipHookHelper->get_ActiveView(&ipActiveView);
IScreenDisplayPtr ipScreenDisplay;
hr=ipActiveView->get_ScreenDisplay(&ipScreenDisplay);
IDisplayTransformationPtr ipDispTrans;
IDisplayPtr ipDisplay;
ipDisplay=ipScreenDisplay;
hr=ipDisplay->get_DisplayTransformation(&ipDispTrans);
tagRECT rect;
hr=ipDispTrans->get_DeviceFrame(&rect);
IEnvelopePtr ipVisibleEnv;
hr=ipDispTrans->get_VisibleBounds(&ipVisibleEnv);
hr=ipVisibleEnv->Expand(3,3,VARIANT_TRUE); //需要在内存描述表中显示的地理范围
double dbResolution;
hr=ipDispTrans->get_Resolution(&dbResolution);
long width,height;
width=rect.right-rect.left;
height=rect.bottom-rect.top;
OLE_HANDLE hwnd;
hr=ipScreenDisplay->get_hWnd(&hwnd);
HDC hdc;
hdc=GetDC((HWND)hwnd); //得到当前地图控件的DC
HDC MemDC;
MemDC=CreateCompatibleDC(hdc);
//创建内存中的兼容Bitmap,用于缓存3X3范围的图像
HBITMAP MemoryBitmap;
MemoryBitmap=CreateCompatibleBitmap(hdc, width*3,height*3); // 必须创建创建与指定DC兼容的位图
//选取内存图象到内存设备描述表
if(!SelectObject(MemDC, MemoryBitmap))
MessageBox(NULL,_T(" Select Bitmap Error"),_T("Error"),MB_ICONERROR);
RECT newRect; //内存描述表的图象范围,单位像素
newRect.left=0;
newRect.right=width*3;
newRect.top=0;
newRect.bottom=height*3;
//创建画刷来填充内存中的设备描述表
HBRUSH hbrush;
hbrush = CreateSolidBrush(RGB(255, 255,255));
FillRect(MemDC, &newRect,hbrush);
//输出合适的地图内容到内存描述表中
hr=ipActiveView->Output((OLE_HANDLE)MemDC,0,&newRect,ipVisibleEnv,NULL);
BitBlt(hdc,
0,0,
width, height,
MemDC,
0,0, //这个地方应该是变量,用于内容裁剪;0,0只能显示3X3效果的左上角效果
SRCCOPY);
ReleaseDC((HWND)hwnd,hdc);
return S_OK;