2017-12-04 6 views
1

사용자에게 문서를 보여주는 Windows 응용 프로그램을 작성하고 있습니다. 콘텐츠는 GDI 함수를 사용하여 그려지며 모든 내용이 화면에 예상대로 나타납니다.Windows - GDI - 그리기 기능을 수정하지 않고 DC를 프린터 DC로 확장

이제이 문서를 인쇄하고 싶습니다. 프린터 장치 컨텍스트를 얻었고 화면에서와 똑같은 그림을 그립니다. 물론 인쇄 된 내용은 인쇄 된 페이지 상단에 작게 나타납니다. 이 동작의 이유는 나를 위해 분명하다, 완벽하게 여기 설명 :

https://www.codeproject.com/Articles/764057/GDI-Drawing-and-Printing

그래서 난 내 프린터 DC에 확장 뷰포트를 추가해야하고, GDI에 그것을 달성하기 위해 몇 가지 기능이있다. 그러나 나는이 기능을 어떻게 구성하는지에 대해 약간 혼란 스럽다. 나는 인터넷에서 발견 된 여러 가지 예를 시도했지만 그 중 누구도 나를 위해 일하지 않았다.

내 화면 해상도는 1920x1080 픽셀이며 A4 세로 페이지에 인쇄하려고합니다. 나는 다양한 구성을 테스트하고, 내 인쇄 된 페이지에 맞게 최적의 근사는 다음과 같은 것을 발견 : 물론, 다른 PC에 변경, 내가 어떻게 알아야 화면 및 인쇄 구성으로

::SetMapMode(hDC, MM_ISOTROPIC); 
::SetWindowExtEx(hDC, 1, 1, NULL); 
::SetViewportExtEx(hDC, 5, 5, NULL); 
::SetViewportOrgEx(hDC, -10200, 0, NULL); 

위의 값을 계산할 수 있지만 내 경우에는 작동하는 수식을 찾을 수 없습니다. 특히 SetViewportOrgEx() 함수를 사용하여 캔버스의 원점을 조절해야하는 이유를 알지 못합니다. 아무도 내가 읽은 문서에서 언급하지 않았습니다.

그래서 고려, 내 인쇄 DC의 뷰포트를 계산하는 올바른 방법은 무엇입니다 :

    정확히 같은 그림 기능은 화면 및 프린터 도면 모두에 사용됩니다, 나는에 다른 함수를 작성하지 않습니다
  • 스크린과 스크린 프린터 장치가 전적으로 사용자에 의해 구성 될 수있다
  • 프린터에 인쇄되지만 인쇄 결과는 항상 화면 및 프린터

하고 또한 같은 양의 문서를 맞아야 이런 질문에 대해서는 메타 파일을 사용하는 것이 더 좋을 것입니다.

+1

범용 방법은 예를 들어, 입력 파라미터로부터하는 XForms의 calculatet 전달 자책골 함수를 사용 SetWorldTransform를 사용하는 것 직관적 인 조작을위한 xoffs, xoffs, scale, rotation. – bummi

+0

가능성이 있습니다. 그러나 MSDN 설명서에서는이를 달성하기 위해 그래픽 모드를 GM_ADVANCED로 설정해야한다고 말합니다. 이 모드는 일반적으로 모든 프린터 컨텍스트와 호환됩니까? –

+1

모든 프린터에서 지원되는 것은 아니며, 얼마나 일반적인 지 알 수는 없지만 정보를 찾지 못했습니다. 목표 환경이 다를 수 있기 때문에 절대로 내 스스로 문제가 없었어야합니다. – bummi

답변

1

화면 좌표를 용지 좌표로 매핑하려면 용지의 너비와 길이가 필요합니다. 이 정보는 GetDeviceCaps(hdc, PHYSICALWIDTH)GetDeviceCaps(hdc, PHYSICALHEIGHT)에서 사용할 수 있습니다. hdc은 프린터의 장치 컨텍스트입니다. 우리는 이미 스크린 좌표를 어딘가에 가지고 있습니다.

프린터가 용지 가장자리에 인쇄 할 수 없습니다. 이 정보는 PHYSICALOFFSETXPHYSICALOFFSETY에서 얻을 수 있습니다.

아래 예제는 모든 그림을 수행하는 공통 기능 paint을 사용합니다. print은 그림을 그리지 않고 대신 paint을 호출합니다.

여기서는 rc.leftrc.right이 화면 좌표에서 (0,0) 인 것으로 가정합니다.

void paint(HDC hdc, RECT rc) 
{ 
    HBRUSH brush = GetSysColorBrush(COLOR_WINDOWTEXT); 
    InflateRect(&rc, -10, -10); 
    FrameRect(hdc, &rc, brush); 
    DrawText(hdc, L"hello world", -1, &rc, 0); 
} 

void print(HWND hWnd, RECT rc) 
{ 
    PRINTDLG pd = { sizeof(pd) }; 
    pd.hwndOwner = hWnd; 
    pd.Flags = PD_RETURNDC; 
    if(!PrintDlg(&pd)) 
     return; 

    HDC hdc = pd.hDC; 
    DOCINFO doc = { sizeof(doc) }; 
    StartDoc(hdc, &doc); 
    StartPage(hdc); 
    SetMapMode(hdc, MM_ISOTROPIC); 
    SetWindowExtEx(hdc, rc.right, rc.bottom, NULL); 
    SetViewportExtEx(hdc, 
     GetDeviceCaps(hdc, PHYSICALWIDTH), GetDeviceCaps(hdc, PHYSICALHEIGHT), NULL); 
    SetViewportOrgEx(hdc, 
     -GetDeviceCaps(hdc, PHYSICALOFFSETX), -GetDeviceCaps(hdc, PHYSICALOFFSETY), NULL); 

    paint(hdc, rc); 

    EndPage(hdc); 
    EndDoc(hdc); 
    DeleteObject(hdc); 
} 

시험 :

case WM_PAINT: 
{ 
    PAINTSTRUCT ps; 
    HDC hdc = BeginPaint(hwnd, &ps); 
    RECT rc; 
    GetClientRect(hwnd, &rc); 
    paint(hdc, rc); 
    EndPaint(hwnd, &ps); 
    break; 
} 

case WM_LBUTTONDOWN: 
{ 
    RECT rc; 
    GetClientRect(hwnd, &rc); 
    print(hwnd, rc); 
    break; 
} 
+0

나는 이제 내 실수를 이해했다. 먼저 잘못된 크기를 사용하여 드로잉을 계산했으며 둘째로 내 드로잉에서 클리핑을 사용했습니다. 분명히 GDI 클리핑 함수는 뷰포트 함수 및/또는 프린터 DC에서 제대로 작동하지 않습니다. 그러나 적어도 그들을 제거하고 위의 솔루션을 적용하면 최종 결과를 기대했던 최종 결과에 매우 근접 할 수있었습니다. 답변 감사합니다. –

관련 문제