翻译稿

发布时间 : 星期四 文章翻译稿更新完毕开始阅读

Getting Started with MapObjects Version 2.x in Visual C++ 37

// // DT_TOP, DT_VCENTER, DT_BOTTOM // DT_LEFT, DT_CENTER, DT_RIGHT //

CRect AdjustToRatio(const CRect& r, const double ratio, const UINT align = DT_VCENTER|DT_CENTER) {

CRect newRect = r;

// First try simple adjustment if (ratio < 1.0) S_AdjustWidthToRatio(newRect, ratio, align); else S_AdjustHeightToRatio(newRect, ratio, align);

// Didn't fit. Adjust again. if (r.Width() < newRect.Width()) { newRect.left = r.left; newRect.right = r.right; S_AdjustHeightToRatio(newRect, ratio, align); }

if (r.Height() < newRect.Height()) { newRect.top = r.top; newRect.bottom = r.bottom; S_AdjustWidthToRatio(newRect, ratio, align); }

return newRect; } //

// Calculate the size of the output device in pixels //

CRect GetDeviceRect(CDC* pDC) {

CRect devRect;

// HDC hDC = pDC->m_hAttribDC; HDC hDC = pDC->GetSafeHdc();

int type = ::GetObjectType(hDC); switch (type) {

case OBJ_DC: // Printer or screen // // If there's a window associated with // the DC, use the client area. Otherwise // use the device width. // HWND hWnd; if (hWnd = ::WindowFromDC(hDC)) ::GetClientRect(hWnd, &devRect); else devRect.SetRect(0, 0, pDC->GetDeviceCaps(HORZRES), pDC->GetDeviceCaps(VERTRES)); break; case OBJ_MEMDC: // Memory bitmap // // Use the bitmap size // HBITMAP hBitmap; hBitmap = (HBITMAP)::GetCurrentObject(pDC->GetSafeHdc(), OBJ_BITMAP); if (!hBitmap) throw; BITMAP bm; VERIFY(::GetObject(hBitmap, sizeof(BITMAP), &bm)); if (bm.bmWidth == 0 || bm.bmHeight == 0) throw;

devRect.SetRect(0, 0, bm.bmWidth, bm.bmHeight); break;

Getting Started with MapObjects Version 2.x in Visual C++ 38

default: devRect.SetRect(0, 0, pDC->GetDeviceCaps(HORZRES), pDC->GetDeviceCaps(VERTRES)); if (devRect.right == 0) { CClientDC dc(0); devRect.SetRect(0, 0, dc.GetDeviceCaps(HORZRES), dc.GetDeviceCaps(VERTRES)); } break; } return devRect; } //

// Draw the map, scaling it to a frame on the surface of the // device referenced by the DC. If the frame doesn't match the // aspect ratio of the map, the map is position within the frame // as specified by the align argument. Use the following // values or'd together for alignment: // // DT_TOP, DT_VCENTER, DT_BOTTOM // DT_LEFT, DT_CENTER, DT_RIGHT //

void FrameMap(CMap1& map, CDC* pDC, const CRect& dstRect, const UINT align = DT_VCENTER|DT_CENTER) {

//

// Create a frame of the same aspect ratio as the map and // center or left justify it in dstRect. //

double aspectRatio = GetAspectRatio(map);

CRect frame = AdjustToRatio(dstRect, aspectRatio, align);

//

// Use GDI to position map on page //

CRect devRect = AdjustToRatio(GetDeviceRect(pDC), aspectRatio); int saveID = pDC->SaveDC();

pDC->SetMapMode(MM_ISOTROPIC);

pDC->SetWindowOrg(devRect.left, devRect.top);

pDC->SetWindowExt(devRect.Width(), devRect.Height()); pDC->SetViewportOrg(frame.left, frame.top);

pDC->SetViewportExt(frame.Width(), frame.Height());

map.OutputMap((OLE_HANDLE)pDC->GetSafeHdc());

pDC->RestoreDC(saveID); }

FrameMap takes the map and renders it to a rectangle on the specified DC. If the specified rectangle doesn?t match the aspect ratio of the map, the map is positioned within the rectangle according to the alignment specified. Once the actual frame is calculated, GDI is used to scale the map to the frame.

Add printing code

Update the CEasyMapView::OnPrint routine as follows:

void CEasyMapView::OnPrint(CDC* pDC, CPrintInfo*) {

CRect frame(0, 0, ::GetDeviceCaps(pDC->m_hAttribDC, HORZRES),

::GetDeviceCaps(pDC->m_hAttribDC, VERTRES));

FrameMap(m_map, pDC, frame); }

Test your changes

1. Build and run the application.

Getting Started with MapObjects Version 2.x in Visual C++

2. Use the File-Print Setup menu to select a printer and set its properties 3. Use the File-Print Preview menu to display a preview of the printer page 4. Press the Print button to print your map

39

Customize preview toolbar

You?ll notice on the print preview toolbar that there are “Next Page”, “Previous Page”, and “Two Page” buttons. We don?t need these for printing maps so, in this step you?ll customize this toolbar by removing these buttons.

1. Open “..\\Microsoft Visual Studio\\VC98\\MFC\\Include\\Afxprint.rc”.

2. Copy the AFX_IDD_PREVIEW_TOOLBAR dialog to your application. Drag and drop works well

for this. Remember to press the Ctrl key so that you copy instead of moving.

3. Edit your copy of AFX_IDD_PREVIEW_TOOLBAR. Rename it to IDD_PREVIEW and remove the

page buttons.

4. Use Class Wizard to add an ID_FILE_PRINTPREVIEW COMMAND handler to CEasyMapView.

5. Add the following line to stdafx.h

#include // need CPreviewView

6. Use our own copy of the preview toolbar for print preview:

void CEasyMapView::OnFilePrintPreview() {

// In derived classes, implement special window handling here // Be sure to Unhook Frame Window close if hooked.

// must not create this on the frame. Must outlive this function CPrintPreviewState* pState = new CPrintPreviewState;

// DoPrintPreview's return value does not necessarily indicate that

// Print preview succeeded or failed, but rather what actions are necessary // at this point. If DoPrintPreview returns TRUE, it means that // OnEndPrintPreview will be (or has already been) called and the // pState structure will be/has been deleted.

// If DoPrintPreview returns FALSE, it means that OnEndPrintPreview // WILL NOT be called and that cleanup, including deleting pState // must be done here. if (!DoPrintPreview(IDD_PREVIEW, this, RUNTIME_CLASS(CPreviewView), pState)) { // In derived classes, reverse special window handling here for // Preview failure case

TRACE0(\ AfxMessageBox(AFX_IDP_COMMAND_FAILURE); delete pState; // preview failed to initialize, delete State now } }

Test your changes

1. Build and run the application.

2. Use the File-Print Preview menu to display a preview of the printer page. Notice that the page

buttons are no longer there.

Add alignment property to CEasyMapView

1. Add the following private variable: UINT m_alignment

Getting Started with MapObjects Version 2.x in Visual C++

2. Add the following public methods:

//

// Alignment of map on printer page. Use DrawText constants. // void SetAlignment(UINT alignment) { m_alignment = alignment; } UINT GetAlignment() { return m_alignment; }

40

3. Edit MapView.cpp

4. Initialize m_alignment in the constructor:

CEasyMapView::CEasyMapView()

: CFormView(CEasyMapView::IDD), m_curTool(ID_MAP_ZOOMIN),

m_alignment(DT_VCENTER|DT_CENTER) 5. Use the alignment property in the call to FrameMap:

{

CRect frame(0, 0, ::GetDeviceCaps(pDC->m_hAttribDC, HORZRES),

::GetDeviceCaps(pDC->m_hAttribDC, VERTRES));

FrameMap(m_map, pDC, frame, GetAlignment()); }

void CEasyMapView::OnPrint(CDC* pDC, CPrintInfo*)

Add alignment buttons to the preview toolbar

Now that we have access to the preview toolbar, we can add some simple buttons that allow us to align our map to the page. 1. Edit IDD_PREVIEW.

2. Add a “Left/Top” button. Set its ID to ID_ALIGN_LEFTTOP. 3. Add a “Center” button. Set its ID to ID_ALIGN_CENTER.

4. Add a “Right/Bottom” button. Set its ID to ID_ALIGN_RIGHTBOTTOM.

Add your own preview view class

1. Edit MapView.cpp. Add the following code above the CEasyMapView::OnFilePrintPreview(). It

handles clicks on the alignment buttons and sets CEasyMapView?s alignment property appropriately.

// Use our own preview toolbar and preview view class to // eliminate the multiple page stuff and implement map // alignment.

class CMapPreviewView : public CPreviewView { DECLARE_DYNCREATE(CMapPreviewView)

public: CMapPreviewView() {}

protected: //{{AFX_MSG(CMapPreviewView) afx_msg void OnAlign(UINT cmdID); //}}AFX_MSG DECLARE_MESSAGE_MAP() };

IMPLEMENT_DYNCREATE(CMapPreviewView, CPreviewView) BEGIN_MESSAGE_MAP(CMapPreviewView, CPreviewView) //{{AFX_MSG_MAP(CMapPreviewView) ON_COMMAND_RANGE(ID_ALIGN_LEFTTOP, ID_ALIGN_RIGHTBOTTOM, OnAlign) //}}AFX_MSG_MAP END_MESSAGE_MAP()

void CMapPreviewView::OnAlign(UINT cmdID) { UINT alignment = 0; switch (cmdID) {

联系合同范文客服:xxxxx#qq.com(#替换为@)