2 * Wordpad implementation - Printing and print preview functions
4 * Copyright 2007-2008 by Alexander N. Sørnes <alex@thehandofagony.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 typedef struct _previewinfo
37 } previewinfo
, *ppreviewinfo
;
39 static HGLOBAL devMode
;
40 static HGLOBAL devNames
;
43 static previewinfo preview
;
45 static const WCHAR var_pagemargin
[] = {'P','a','g','e','M','a','r','g','i','n',0};
47 static LPWSTR
get_print_file_filter(HWND hMainWnd
)
49 static WCHAR wszPrintFilter
[MAX_STRING_LEN
*2+6+4+1];
50 const WCHAR files_prn
[] = {'*','.','P','R','N',0};
51 const WCHAR files_all
[] = {'*','.','*','\0'};
53 HINSTANCE hInstance
= (HINSTANCE
)GetWindowLongPtr(hMainWnd
, GWLP_HINSTANCE
);
56 LoadStringW(hInstance
, STRING_PRINTER_FILES_PRN
, p
, MAX_STRING_LEN
);
58 lstrcpyW(p
, files_prn
);
60 LoadStringW(hInstance
, STRING_ALL_FILES
, p
, MAX_STRING_LEN
);
62 lstrcpyW(p
, files_all
);
66 return wszPrintFilter
;
69 void registry_set_pagemargins(HKEY hKey
)
71 RegSetValueExW(hKey
, var_pagemargin
, 0, REG_BINARY
, (LPBYTE
)&margins
, sizeof(RECT
));
74 void registry_read_pagemargins(HKEY hKey
)
76 DWORD size
= sizeof(RECT
);
78 if(!hKey
|| RegQueryValueExW(hKey
, var_pagemargin
, 0, NULL
, (LPBYTE
)&margins
,
79 &size
) != ERROR_SUCCESS
|| size
!= sizeof(RECT
))
82 margins
.bottom
= 1417;
88 static void AddTextButton(HWND hRebarWnd
, UINT string
, UINT command
, UINT id
)
91 HINSTANCE hInstance
= (HINSTANCE
)GetWindowLongPtr(hRebarWnd
, GWLP_HINSTANCE
);
92 WCHAR text
[MAX_STRING_LEN
];
95 LoadStringW(hInstance
, string
, text
, MAX_STRING_LEN
);
96 hButton
= CreateWindowW(WC_BUTTONW
, text
,
97 WS_VISIBLE
| WS_CHILD
, 5, 5, 100, 15,
98 hRebarWnd
, ULongToHandle(command
), hInstance
, NULL
);
100 rb
.cbSize
= sizeof(rb
);
101 rb
.fMask
= RBBIM_SIZE
| RBBIM_CHILDSIZE
| RBBIM_STYLE
| RBBIM_CHILD
| RBBIM_IDEALSIZE
| RBBIM_ID
;
102 rb
.fStyle
= RBBS_NOGRIPPER
| RBBS_VARIABLEHEIGHT
;
103 rb
.hwndChild
= hButton
;
104 rb
.cyChild
= rb
.cyMinChild
= 22;
105 rb
.cx
= rb
.cxMinChild
= 90;
109 SendMessageW(hRebarWnd
, RB_INSERTBAND
, -1, (LPARAM
)&rb
);
112 static HDC
make_dc(void)
114 if(devNames
&& devMode
)
116 LPDEVNAMES dn
= GlobalLock(devNames
);
117 LPDEVMODEW dm
= GlobalLock(devMode
);
120 ret
= CreateDCW((LPWSTR
)dn
+ dn
->wDriverOffset
,
121 (LPWSTR
)dn
+ dn
->wDeviceOffset
, 0, dm
);
133 static LONG
twips_to_centmm(int twips
)
135 return MulDiv(twips
, CENTMM_PER_INCH
, TWIPS_PER_INCH
);
138 static LONG
centmm_to_twips(int mm
)
140 return MulDiv(mm
, TWIPS_PER_INCH
, CENTMM_PER_INCH
);
143 static LONG
twips_to_pixels(int twips
, int dpi
)
145 return MulDiv(twips
, dpi
, TWIPS_PER_INCH
);
148 static LONG
devunits_to_twips(int units
, int dpi
)
150 return MulDiv(units
, TWIPS_PER_INCH
, dpi
);
154 static RECT
get_print_rect(HDC hdc
)
161 int dpiY
= GetDeviceCaps(hdc
, LOGPIXELSY
);
162 int dpiX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
163 width
= devunits_to_twips(GetDeviceCaps(hdc
, PHYSICALWIDTH
), dpiX
);
164 height
= devunits_to_twips(GetDeviceCaps(hdc
, PHYSICALHEIGHT
), dpiY
);
167 width
= centmm_to_twips(18500);
168 height
= centmm_to_twips(27000);
171 rc
.left
= margins
.left
;
172 rc
.right
= width
- margins
.right
;
173 rc
.top
= margins
.top
;
174 rc
.bottom
= height
- margins
.bottom
;
179 void target_device(HWND hMainWnd
, DWORD wordWrap
)
181 HWND hEditorWnd
= GetDlgItem(hMainWnd
, IDC_EDITOR
);
183 if(wordWrap
== ID_WORDWRAP_MARGIN
)
188 RECT rc
= get_print_rect(hdc
);
190 width
= rc
.right
- rc
.left
;
193 HDC hMaindc
= GetDC(hMainWnd
);
194 hdc
= CreateCompatibleDC(hMaindc
);
195 ReleaseDC(hMainWnd
, hMaindc
);
197 result
= SendMessageW(hEditorWnd
, EM_SETTARGETDEVICE
, (WPARAM
)hdc
, width
);
201 /* otherwise EM_SETTARGETDEVICE failed, so fall back on wrapping
202 * to window using the NULL DC. */
205 if (wordWrap
!= ID_WORDWRAP_NONE
) {
206 SendMessageW(hEditorWnd
, EM_SETTARGETDEVICE
, 0, 0);
208 SendMessageW(hEditorWnd
, EM_SETTARGETDEVICE
, 0, 1);
213 static LPWSTR
dialog_print_to_file(HWND hMainWnd
)
216 static WCHAR file
[MAX_PATH
] = {'O','U','T','P','U','T','.','P','R','N',0};
217 static const WCHAR defExt
[] = {'P','R','N',0};
218 static LPWSTR file_filter
;
221 file_filter
= get_print_file_filter(hMainWnd
);
223 ZeroMemory(&ofn
, sizeof(ofn
));
225 ofn
.lStructSize
= sizeof(ofn
);
226 ofn
.Flags
= OFN_PATHMUSTEXIST
| OFN_HIDEREADONLY
| OFN_OVERWRITEPROMPT
;
227 ofn
.hwndOwner
= hMainWnd
;
228 ofn
.lpstrFilter
= file_filter
;
229 ofn
.lpstrFile
= file
;
230 ofn
.nMaxFile
= MAX_PATH
;
231 ofn
.lpstrDefExt
= defExt
;
233 if(GetSaveFileNameW(&ofn
))
239 static int get_num_pages(HWND hEditorWnd
, FORMATRANGE fr
)
247 fr
.chrg
.cpMin
= SendMessageW(hEditorWnd
, EM_FORMATRANGE
, TRUE
,
250 while(fr
.chrg
.cpMin
&& fr
.chrg
.cpMin
< fr
.chrg
.cpMax
);
255 static void char_from_pagenum(HWND hEditorWnd
, FORMATRANGE
*fr
, int page
)
261 for(i
= 1; i
< page
; i
++)
263 fr
->chrg
.cpMin
= SendMessageW(hEditorWnd
, EM_FORMATRANGE
, TRUE
, (LPARAM
)fr
);
267 static HWND
get_ruler_wnd(HWND hMainWnd
)
269 return GetDlgItem(GetDlgItem(hMainWnd
, IDC_REBAR
), IDC_RULER
);
272 void redraw_ruler(HWND hRulerWnd
)
276 GetClientRect(hRulerWnd
, &rc
);
277 InvalidateRect(hRulerWnd
, &rc
, TRUE
);
280 static void update_ruler(HWND hRulerWnd
)
282 SendMessageW(hRulerWnd
, WM_USER
, 0, 0);
283 redraw_ruler(hRulerWnd
);
286 static void print(LPPRINTDLGW pd
, LPWSTR wszFileName
)
290 HWND hEditorWnd
= GetDlgItem(pd
->hwndOwner
, IDC_EDITOR
);
291 int printedPages
= 0;
294 fr
.hdcTarget
= pd
->hDC
;
296 fr
.rc
= get_print_rect(fr
.hdc
);
298 fr
.rcPage
.right
= fr
.rc
.right
+ margins
.right
;
300 fr
.rcPage
.bottom
= fr
.rc
.bottom
+ margins
.bottom
;
302 ZeroMemory(&di
, sizeof(di
));
303 di
.cbSize
= sizeof(di
);
304 di
.lpszDocName
= wszFileName
;
306 if(pd
->Flags
& PD_PRINTTOFILE
)
308 di
.lpszOutput
= dialog_print_to_file(pd
->hwndOwner
);
313 if(pd
->Flags
& PD_SELECTION
)
315 SendMessageW(hEditorWnd
, EM_EXGETSEL
, 0, (LPARAM
)&fr
.chrg
);
319 gt
.flags
= GTL_DEFAULT
;
322 fr
.chrg
.cpMax
= SendMessageW(hEditorWnd
, EM_GETTEXTLENGTHEX
, (WPARAM
)>
, 0);
324 if(pd
->Flags
& PD_PAGENUMS
)
325 char_from_pagenum(hEditorWnd
, &fr
, pd
->nToPage
);
328 StartDocW(fr
.hdc
, &di
);
331 if(StartPage(fr
.hdc
) <= 0)
334 fr
.chrg
.cpMin
= SendMessageW(hEditorWnd
, EM_FORMATRANGE
, TRUE
, (LPARAM
)&fr
);
336 if(EndPage(fr
.hdc
) <= 0)
340 if((pd
->Flags
& PD_PAGENUMS
) && (printedPages
> (pd
->nToPage
- pd
->nFromPage
)))
343 while(fr
.chrg
.cpMin
&& fr
.chrg
.cpMin
< fr
.chrg
.cpMax
);
346 SendMessageW(hEditorWnd
, EM_FORMATRANGE
, FALSE
, 0);
349 void dialog_printsetup(HWND hMainWnd
)
353 ZeroMemory(&ps
, sizeof(ps
));
354 ps
.lStructSize
= sizeof(ps
);
355 ps
.hwndOwner
= hMainWnd
;
356 ps
.Flags
= PSD_INHUNDREDTHSOFMILLIMETERS
| PSD_MARGINS
;
357 ps
.rtMargin
.left
= twips_to_centmm(margins
.left
);
358 ps
.rtMargin
.right
= twips_to_centmm(margins
.right
);
359 ps
.rtMargin
.top
= twips_to_centmm(margins
.top
);
360 ps
.rtMargin
.bottom
= twips_to_centmm(margins
.bottom
);
361 ps
.hDevMode
= devMode
;
362 ps
.hDevNames
= devNames
;
364 if(PageSetupDlgW(&ps
))
366 margins
.left
= centmm_to_twips(ps
.rtMargin
.left
);
367 margins
.right
= centmm_to_twips(ps
.rtMargin
.right
);
368 margins
.top
= centmm_to_twips(ps
.rtMargin
.top
);
369 margins
.bottom
= centmm_to_twips(ps
.rtMargin
.bottom
);
370 devMode
= ps
.hDevMode
;
371 devNames
= ps
.hDevNames
;
372 update_ruler(get_ruler_wnd(hMainWnd
));
376 void get_default_printer_opts(void)
379 ZeroMemory(&pd
, sizeof(pd
));
381 ZeroMemory(&pd
, sizeof(pd
));
382 pd
.lStructSize
= sizeof(pd
);
383 pd
.Flags
= PD_RETURNDC
| PD_RETURNDEFAULT
;
384 pd
.hDevMode
= devMode
;
388 devMode
= pd
.hDevMode
;
389 devNames
= pd
.hDevNames
;
392 void print_quick(LPWSTR wszFileName
)
396 ZeroMemory(&pd
, sizeof(pd
));
399 print(&pd
, wszFileName
);
402 void dialog_print(HWND hMainWnd
, LPWSTR wszFileName
)
405 HWND hEditorWnd
= GetDlgItem(hMainWnd
, IDC_EDITOR
);
409 ZeroMemory(&pd
, sizeof(pd
));
410 pd
.lStructSize
= sizeof(pd
);
411 pd
.hwndOwner
= hMainWnd
;
412 pd
.Flags
= PD_RETURNDC
| PD_USEDEVMODECOPIESANDCOLLATE
;
415 pd
.hDevMode
= devMode
;
416 pd
.hDevNames
= devNames
;
418 SendMessageW(hEditorWnd
, EM_GETSEL
, (WPARAM
)&from
, (LPARAM
)&to
);
420 pd
.Flags
|= PD_NOSELECTION
;
424 devMode
= pd
.hDevMode
;
425 devNames
= pd
.hDevNames
;
426 print(&pd
, wszFileName
);
427 update_ruler(get_ruler_wnd(hMainWnd
));
431 static void preview_bar_show(HWND hMainWnd
, BOOL show
)
433 HWND hReBar
= GetDlgItem(hMainWnd
, IDC_REBAR
);
441 AddTextButton(hReBar
, STRING_PREVIEW_PRINT
, ID_PRINT
, BANDID_PREVIEW_BTN1
);
442 AddTextButton(hReBar
, STRING_PREVIEW_NEXTPAGE
, ID_PREVIEW_NEXTPAGE
, BANDID_PREVIEW_BTN2
);
443 AddTextButton(hReBar
, STRING_PREVIEW_PREVPAGE
, ID_PREVIEW_PREVPAGE
, BANDID_PREVIEW_BTN3
);
444 AddTextButton(hReBar
, STRING_PREVIEW_TWOPAGES
, ID_PREVIEW_NUMPAGES
, BANDID_PREVIEW_BTN4
);
445 AddTextButton(hReBar
, STRING_PREVIEW_CLOSE
, ID_FILE_EXIT
, BANDID_PREVIEW_BTN5
);
447 hStatic
= CreateWindowW(WC_STATICW
, NULL
,
448 WS_VISIBLE
| WS_CHILD
, 0, 0, 0, 0,
449 hReBar
, NULL
, NULL
, NULL
);
451 rb
.cbSize
= sizeof(rb
);
452 rb
.fMask
= RBBIM_SIZE
| RBBIM_CHILDSIZE
| RBBIM_STYLE
| RBBIM_CHILD
| RBBIM_IDEALSIZE
| RBBIM_ID
;
453 rb
.fStyle
= RBBS_NOGRIPPER
| RBBS_VARIABLEHEIGHT
;
454 rb
.hwndChild
= hStatic
;
455 rb
.cyChild
= rb
.cyMinChild
= 22;
456 rb
.cx
= rb
.cxMinChild
= 90;
458 rb
.wID
= BANDID_PREVIEW_BUFFER
;
460 SendMessageW(hReBar
, RB_INSERTBAND
, -1, (LPARAM
)&rb
);
463 for(i
= 0; i
<= PREVIEW_BUTTONS
; i
++)
464 SendMessageW(hReBar
, RB_DELETEBAND
, SendMessageW(hReBar
, RB_IDTOINDEX
, BANDID_PREVIEW_BTN1
+i
, 0), 0);
468 void init_preview(HWND hMainWnd
, LPWSTR wszFileName
)
473 preview
.wszFileName
= wszFileName
;
474 preview_bar_show(hMainWnd
, TRUE
);
477 void close_preview(HWND hMainWnd
)
479 preview
.window
.right
= 0;
480 preview
.window
.bottom
= 0;
484 preview_bar_show(hMainWnd
, FALSE
);
487 BOOL
preview_isactive(void)
489 return preview
.page
!= 0;
492 static void add_ruler_units(HDC hdcRuler
, RECT
* drawRect
, BOOL NewMetrics
, LONG EditLeftmost
)
498 static HBITMAP hBitmap
;
499 int i
, x
, y
, RulerTextEnd
;
503 WCHAR FontName
[] = {'M','S',' ','S','a','n','s',' ','S','e','r','i','f',0};
508 DeleteObject(hBitmap
);
511 hdc
= CreateCompatibleDC(0);
513 CmPixels
= twips_to_pixels(centmm_to_twips(1000), GetDeviceCaps(hdc
, LOGPIXELSX
));
514 QuarterCmPixels
= (int)((float)CmPixels
/ 4.0);
516 hBitmap
= CreateCompatibleBitmap(hdc
, drawRect
->right
, drawRect
->bottom
);
517 SelectObject(hdc
, hBitmap
);
518 FillRect(hdc
, drawRect
, GetStockObject(WHITE_BRUSH
));
520 hFont
= CreateFontW(10, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, FontName
);
522 SelectObject(hdc
, hFont
);
523 SetBkMode(hdc
, TRANSPARENT
);
524 SetTextAlign(hdc
, TA_CENTER
);
525 y
= (int)(((float)drawRect
->bottom
- (float)drawRect
->top
) / 2.0) + 1;
526 RulerTextEnd
= drawRect
->right
- EditLeftmost
+ 1;
527 for(i
= 1, x
= EditLeftmost
; x
< (drawRect
->right
- EditLeftmost
+ 1); i
++)
530 WCHAR format
[] = {'%','d',0};
533 x2
+= QuarterCmPixels
;
534 if(x2
> RulerTextEnd
)
537 MoveToEx(hdc
, x2
, y
, NULL
);
538 LineTo(hdc
, x2
, y
+2);
540 x2
+= QuarterCmPixels
;
541 if(x2
> RulerTextEnd
)
544 MoveToEx(hdc
, x2
, y
- 3, NULL
);
545 LineTo(hdc
, x2
, y
+ 3);
547 x2
+= QuarterCmPixels
;
548 if(x2
> RulerTextEnd
)
551 MoveToEx(hdc
, x2
, y
, NULL
);
552 LineTo(hdc
, x2
, y
+2);
558 wsprintfW(str
, format
, i
);
559 TextOutW(hdc
, x
, 5, str
, lstrlenW(str
));
564 BitBlt(hdcRuler
, 0, 0, drawRect
->right
, drawRect
->bottom
, hdc
, 0, 0, SRCAND
);
567 static void paint_ruler(HWND hWnd
, LONG EditLeftmost
, BOOL NewMetrics
)
570 HDC hdc
= BeginPaint(hWnd
, &ps
);
571 HDC hdcPrint
= make_dc();
572 RECT printRect
= get_print_rect(hdcPrint
);
574 HBRUSH hBrush
= CreateSolidBrush(GetSysColor(COLOR_MENU
));
576 GetClientRect(hWnd
, &drawRect
);
577 FillRect(hdc
, &drawRect
, hBrush
);
580 drawRect
.bottom
-= 3;
581 drawRect
.left
= EditLeftmost
;
582 drawRect
.right
= twips_to_pixels(printRect
.right
- margins
.left
, GetDeviceCaps(hdc
, LOGPIXELSX
));
583 FillRect(hdc
, &drawRect
, GetStockObject(WHITE_BRUSH
));
587 DrawEdge(hdc
, &drawRect
, EDGE_SUNKEN
, BF_RECT
);
589 drawRect
.left
= drawRect
.right
- 1;
590 drawRect
.right
= twips_to_pixels(printRect
.right
+ margins
.right
- margins
.left
, GetDeviceCaps(hdc
, LOGPIXELSX
));
591 DrawEdge(hdc
, &drawRect
, EDGE_ETCHED
, BF_RECT
);
595 add_ruler_units(hdc
, &drawRect
, NewMetrics
, EditLeftmost
);
597 SelectObject(hdc
, GetStockObject(BLACK_BRUSH
));
598 DeleteObject(hBrush
);
603 LRESULT CALLBACK
ruler_proc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
605 static WNDPROC pPrevRulerProc
;
606 static LONG EditLeftmost
;
607 static BOOL NewMetrics
;
614 EditLeftmost
= ((POINTL
*)wParam
)->x
;
615 pPrevRulerProc
= (WNDPROC
)lParam
;
621 paint_ruler(hWnd
, EditLeftmost
, NewMetrics
);
625 return CallWindowProcW(pPrevRulerProc
, hWnd
, msg
, wParam
, lParam
);
631 static void draw_preview_page(HDC hdc
, HDC
* hdcSized
, FORMATRANGE
* lpFr
, float ratio
, int bmNewWidth
, int bmNewHeight
, int bmWidth
, int bmHeight
)
633 HBITMAP hBitmapScaled
= CreateCompatibleBitmap(hdc
, bmNewWidth
, bmNewHeight
);
635 int TopMargin
= (int)((float)twips_to_pixels(lpFr
->rc
.top
, GetDeviceCaps(hdc
, LOGPIXELSX
)) * ratio
);
636 int BottomMargin
= (int)((float)twips_to_pixels(lpFr
->rc
.bottom
, GetDeviceCaps(hdc
, LOGPIXELSX
)) * ratio
);
637 int LeftMargin
= (int)((float)twips_to_pixels(lpFr
->rc
.left
, GetDeviceCaps(hdc
, LOGPIXELSY
)) * ratio
);
638 int RightMargin
= (int)((float)twips_to_pixels(lpFr
->rc
.right
, GetDeviceCaps(hdc
, LOGPIXELSY
)) * ratio
);
642 *hdcSized
= CreateCompatibleDC(hdc
);
643 SelectObject(*hdcSized
, hBitmapScaled
);
645 StretchBlt(*hdcSized
, 0, 0, bmNewWidth
, bmNewHeight
, hdc
, 0, 0, bmWidth
, bmHeight
, SRCCOPY
);
647 /* Draw margin lines */
648 hPen
= CreatePen(PS_DOT
, 1, RGB(0,0,0));
649 SelectObject(*hdcSized
, hPen
);
651 MoveToEx(*hdcSized
, 0, TopMargin
, NULL
);
652 LineTo(*hdcSized
, bmNewWidth
, TopMargin
);
653 MoveToEx(*hdcSized
, 0, BottomMargin
, NULL
);
654 LineTo(*hdcSized
, bmNewWidth
, BottomMargin
);
656 MoveToEx(*hdcSized
, LeftMargin
, 0, NULL
);
657 LineTo(*hdcSized
, LeftMargin
, bmNewHeight
);
658 MoveToEx(*hdcSized
, RightMargin
, 0, NULL
);
659 LineTo(*hdcSized
, RightMargin
, bmNewHeight
);
663 static void draw_preview(HWND hEditorWnd
, FORMATRANGE
* lpFr
, int bmWidth
, int bmHeight
, RECT
* paper
, int page
)
665 HBITMAP hBitmapCapture
= CreateCompatibleBitmap(lpFr
->hdc
, bmWidth
, bmHeight
);
667 char_from_pagenum(hEditorWnd
, lpFr
, page
);
668 SelectObject(lpFr
->hdc
, hBitmapCapture
);
669 FillRect(lpFr
->hdc
, paper
, GetStockObject(WHITE_BRUSH
));
670 SendMessageW(hEditorWnd
, EM_FORMATRANGE
, TRUE
, (LPARAM
)lpFr
);
671 /* EM_FORMATRANGE sets fr.rc to indicate the area printed in, but we want to
672 keep the original for drawing margins */
673 lpFr
->rc
= get_print_rect(lpFr
->hdcTarget
);
674 SendMessageW(hEditorWnd
, EM_FORMATRANGE
, FALSE
, 0);
677 LRESULT
print_preview(HWND hMainWnd
)
682 RECT window
, background
;
683 int bmWidth
, bmHeight
, bmNewWidth
, bmNewHeight
;
684 float ratioWidth
, ratioHeight
, ratio
;
685 int xOffset
, yOffset
;
687 float spacing
= 20.0;
688 HWND hReBar
= GetDlgItem(hMainWnd
, IDC_REBAR
);
691 hdc
= BeginPaint(hMainWnd
, &ps
);
692 GetClientRect(hMainWnd
, &window
);
694 fr
.hdcTarget
= make_dc();
695 fr
.rc
= get_print_rect(fr
.hdcTarget
);
698 fr
.rcPage
.bottom
= fr
.rc
.bottom
+ margins
.bottom
;
699 fr
.rcPage
.right
= fr
.rc
.right
+ margins
.right
;
701 bmWidth
= twips_to_pixels(fr
.rcPage
.right
, GetDeviceCaps(hdc
, LOGPIXELSX
));
702 bmHeight
= twips_to_pixels(fr
.rcPage
.bottom
, GetDeviceCaps(hdc
, LOGPIXELSY
));
707 HWND hEditorWnd
= GetDlgItem(hMainWnd
, IDC_EDITOR
);
709 preview
.hdc
= CreateCompatibleDC(hdc
);
713 if(preview
.hdc2
!= (HDC
)-1)
714 DeleteDC(preview
.hdc2
);
715 preview
.hdc2
= CreateCompatibleDC(hdc
);
718 fr
.hdc
= preview
.hdc
;
719 gt
.flags
= GTL_DEFAULT
;
722 fr
.chrg
.cpMax
= SendMessageW(hEditorWnd
, EM_GETTEXTLENGTHEX
, (WPARAM
)>
, 0);
725 paper
.right
= bmWidth
;
727 paper
.bottom
= bmHeight
;
730 preview
.pages
= get_num_pages(hEditorWnd
, fr
);
732 fr
.hdc
= preview
.hdc
;
733 draw_preview(hEditorWnd
, &fr
, bmWidth
, bmHeight
, &paper
, preview
.page
);
737 fr
.hdc
= preview
.hdc2
;
738 draw_preview(hEditorWnd
, &fr
, bmWidth
, bmHeight
, &paper
, preview
.page
+ 1);
741 EnableWindow(GetDlgItem(hReBar
, ID_PREVIEW_PREVPAGE
), preview
.page
> 1);
742 EnableWindow(GetDlgItem(hReBar
, ID_PREVIEW_NEXTPAGE
), preview
.hdc2
?
743 (preview
.page
+ 1) < preview
.pages
:
744 preview
.page
< preview
.pages
);
745 EnableWindow(GetDlgItem(hReBar
, ID_PREVIEW_NUMPAGES
), preview
.pages
> 1);
748 barheight
= SendMessageW(hReBar
, RB_GETBARHEIGHT
, 0, 0);
749 ratioHeight
= ((float)window
.bottom
- spacing
- (float)barheight
) / (float)bmHeight
;
752 ratioWidth
= ((float)window
.right
/ 2.0 - spacing
* 2.0) / (float)bmWidth
;
754 ratioWidth
= ((float)window
.right
- spacing
* 3.0) / (float)bmWidth
;
756 if(ratioWidth
> ratioHeight
)
761 bmNewWidth
= (int)((float)bmWidth
* ratio
);
762 bmNewHeight
= (int)((float)bmHeight
* ratio
);
764 yOffset
= ((window
.bottom
- bmNewHeight
+ barheight
) / 2);
767 xOffset
= (window
.right
- bmNewWidth
) / 2;
769 xOffset
= (window
.right
- bmNewWidth
* 2) / 2;
771 window
.top
= barheight
;
772 FillRect(hdc
, &window
, GetStockObject(GRAY_BRUSH
));
774 background
.left
= xOffset
- 2;
775 background
.right
= xOffset
+ bmNewWidth
+ 2;
776 background
.top
= yOffset
- 2;
777 background
.bottom
= yOffset
+ bmNewHeight
+ 2;
779 FillRect(hdc
, &background
, GetStockObject(BLACK_BRUSH
));
781 if(window
.right
!= preview
.window
.right
|| window
.bottom
!= preview
.window
.bottom
)
783 draw_preview_page(preview
.hdc
, &preview
.hdcSized
, &fr
, ratio
, bmNewWidth
, bmNewHeight
, bmWidth
, bmHeight
);
787 background
.left
+= bmNewWidth
+ spacing
;
788 background
.right
+= bmNewWidth
+ spacing
;
790 FillRect(hdc
, &background
, GetStockObject(BLACK_BRUSH
));
792 draw_preview_page(preview
.hdc2
, &preview
.hdcSized2
, &fr
, ratio
, bmNewWidth
, bmNewHeight
, bmWidth
, bmHeight
);
796 BitBlt(hdc
, xOffset
, yOffset
, bmNewWidth
, bmNewHeight
, preview
.hdcSized
, 0, 0, SRCCOPY
);
800 BitBlt(hdc
, xOffset
+ bmNewWidth
+ spacing
, yOffset
, bmNewWidth
, bmNewHeight
, preview
.hdcSized2
, 0, 0, SRCCOPY
);
803 DeleteDC(fr
.hdcTarget
);
804 preview
.window
= window
;
806 EndPaint(hMainWnd
, &ps
);
811 static void update_preview(HWND hWnd
)
815 DeleteDC(preview
.hdc
);
818 preview
.window
.right
= 0;
820 GetClientRect(hWnd
, &rc
);
821 rc
.top
+= SendMessageW(GetDlgItem(hWnd
, IDC_REBAR
), RB_GETBARHEIGHT
, 0, 0);
822 InvalidateRect(hWnd
, &rc
, TRUE
);
825 LRESULT
preview_command(HWND hWnd
, WPARAM wParam
)
827 switch(LOWORD(wParam
))
830 PostMessageW(hWnd
, WM_CLOSE
, 0, 0);
833 case ID_PREVIEW_NEXTPAGE
:
834 case ID_PREVIEW_PREVPAGE
:
836 if(LOWORD(wParam
) == ID_PREVIEW_NEXTPAGE
)
841 update_preview(hWnd
);
845 case ID_PREVIEW_NUMPAGES
:
847 HWND hReBar
= GetDlgItem(hWnd
, IDC_REBAR
);
848 WCHAR name
[MAX_STRING_LEN
];
849 HINSTANCE hInst
= (HINSTANCE
)GetWindowLongPtrW(hWnd
, GWLP_HINSTANCE
);
853 DeleteDC(preview
.hdc2
);
857 if(preview
.page
== preview
.pages
)
859 preview
.hdc2
= (HDC
)-1;
862 LoadStringW(hInst
, preview
.hdc2
? STRING_PREVIEW_ONEPAGE
: STRING_PREVIEW_TWOPAGES
,
863 name
, MAX_STRING_LEN
);
865 SetWindowTextW(GetDlgItem(hReBar
, ID_PREVIEW_NUMPAGES
), name
);
866 update_preview(hWnd
);
871 dialog_print(hWnd
, preview
.wszFileName
);
872 SendMessageW(hWnd
, WM_CLOSE
, 0, 0);