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;