d3dx8: Make d3dx8core.h C++ compatible.
[wine/hacks.git] / programs / wordpad / print.c
blob3fb2d7a8afd3194f2e8393772a7f3f33b33a609b
1 /*
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
21 #include <windows.h>
22 #include <richedit.h>
23 #include <commctrl.h>
25 #include "wordpad.h"
27 typedef struct _previewinfo
29 int page;
30 int pages;
31 HDC hdc;
32 HDC hdcSized;
33 RECT window;
34 LPWSTR wszFileName;
35 } previewinfo, *ppreviewinfo;
37 static HGLOBAL devMode;
38 static HGLOBAL devNames;
40 static RECT margins;
41 static previewinfo preview;
43 static const WCHAR var_pagemargin[] = {'P','a','g','e','M','a','r','g','i','n',0};
45 static LPWSTR get_print_file_filter(HWND hMainWnd)
47 static WCHAR wszPrintFilter[MAX_STRING_LEN*2+6+4+1];
48 const WCHAR files_prn[] = {'*','.','P','R','N',0};
49 const WCHAR files_all[] = {'*','.','*','\0'};
50 LPWSTR p;
51 HINSTANCE hInstance = (HINSTANCE)GetWindowLongPtr(hMainWnd, GWLP_HINSTANCE);
53 p = wszPrintFilter;
54 LoadStringW(hInstance, STRING_PRINTER_FILES_PRN, p, MAX_STRING_LEN);
55 p += lstrlenW(p) + 1;
56 lstrcpyW(p, files_prn);
57 p += lstrlenW(p) + 1;
58 LoadStringW(hInstance, STRING_ALL_FILES, p, MAX_STRING_LEN);
59 p += lstrlenW(p) + 1;
60 lstrcpyW(p, files_all);
61 p += lstrlenW(p) + 1;
62 *p = 0;
64 return wszPrintFilter;
67 void registry_set_pagemargins(HKEY hKey)
69 RegSetValueExW(hKey, var_pagemargin, 0, REG_BINARY, (LPBYTE)&margins, sizeof(RECT));
72 void registry_read_pagemargins(HKEY hKey)
74 DWORD size = sizeof(RECT);
76 if(!hKey || RegQueryValueExW(hKey, var_pagemargin, 0, NULL, (LPBYTE)&margins,
77 &size) != ERROR_SUCCESS || size != sizeof(RECT))
79 margins.top = 1417;
80 margins.bottom = 1417;
81 margins.left = 1757;
82 margins.right = 1757;
86 static void AddTextButton(HWND hRebarWnd, int string, int command, int id)
88 REBARBANDINFOW rb;
89 HINSTANCE hInstance = (HINSTANCE)GetWindowLongPtr(hRebarWnd, GWLP_HINSTANCE);
90 WCHAR text[MAX_STRING_LEN];
91 HWND hButton;
93 LoadStringW(hInstance, string, text, MAX_STRING_LEN);
94 hButton = CreateWindowW(WC_BUTTONW, text,
95 WS_VISIBLE | WS_CHILD, 5, 5, 100, 15,
96 hRebarWnd, (HMENU)command, hInstance, NULL);
98 rb.cbSize = sizeof(rb);
99 rb.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_STYLE | RBBIM_CHILD | RBBIM_IDEALSIZE | RBBIM_ID;
100 rb.fStyle = RBBS_NOGRIPPER | RBBS_VARIABLEHEIGHT;
101 rb.hwndChild = hButton;
102 rb.cyChild = rb.cyMinChild = 22;
103 rb.cx = rb.cxMinChild = 90;
104 rb.cxIdeal = 100;
105 rb.wID = id;
107 SendMessageW(hRebarWnd, RB_INSERTBAND, -1, (LPARAM)&rb);
110 static HDC make_dc(void)
112 if(devNames && devMode)
114 LPDEVNAMES dn = GlobalLock(devNames);
115 LPDEVMODEW dm = GlobalLock(devMode);
116 HDC ret;
118 ret = CreateDCW((LPWSTR)dn + dn->wDriverOffset,
119 (LPWSTR)dn + dn->wDeviceOffset, 0, dm);
121 GlobalUnlock(dn);
122 GlobalUnlock(dm);
124 return ret;
125 } else
127 return 0;
131 static LONG twips_to_centmm(int twips)
133 return MulDiv(twips, 1000, TWIPS_PER_CM);
136 LONG centmm_to_twips(int mm)
138 return MulDiv(mm, TWIPS_PER_CM, 1000);
141 static LONG twips_to_pixels(int twips, int dpi)
143 float ret = ((float)twips / ((float)TWIPS_PER_CM * 2.54)) * (float)dpi;
144 return (LONG)ret;
147 static LONG devunits_to_twips(int units, int dpi)
149 float ret = ((float)units / (float)dpi) * (float)TWIPS_PER_CM * 2.54;
150 return (LONG)ret;
154 static RECT get_print_rect(HDC hdc)
156 RECT rc;
157 int width, height;
159 if(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);
165 } else
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;
176 return rc;
179 void target_device(HWND hMainWnd, DWORD wordWrap)
181 HWND hEditorWnd = GetDlgItem(hMainWnd, IDC_EDITOR);
182 HDC hdc = make_dc();
183 int width = 0;
185 if(wordWrap == ID_WORDWRAP_MARGIN)
187 RECT rc = get_print_rect(hdc);
188 width = rc.right - rc.left;
191 if(!hdc)
193 HDC hMaindc = GetDC(hMainWnd);
194 hdc = CreateCompatibleDC(hMaindc);
195 ReleaseDC(hMainWnd, hMaindc);
198 SendMessageW(hEditorWnd, EM_SETTARGETDEVICE, (WPARAM)hdc, width);
200 DeleteDC(hdc);
203 static LPWSTR dialog_print_to_file(HWND hMainWnd)
205 OPENFILENAMEW ofn;
206 static WCHAR file[MAX_PATH] = {'O','U','T','P','U','T','.','P','R','N',0};
207 static const WCHAR defExt[] = {'P','R','N',0};
208 static LPWSTR file_filter;
210 if(!file_filter)
211 file_filter = get_print_file_filter(hMainWnd);
213 ZeroMemory(&ofn, sizeof(ofn));
215 ofn.lStructSize = sizeof(ofn);
216 ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
217 ofn.hwndOwner = hMainWnd;
218 ofn.lpstrFilter = file_filter;
219 ofn.lpstrFile = (LPWSTR)file;
220 ofn.nMaxFile = MAX_PATH;
221 ofn.lpstrDefExt = (LPWSTR)defExt;
223 if(GetSaveFileNameW(&ofn))
224 return (LPWSTR)file;
225 else
226 return FALSE;
229 static int get_num_pages(HWND hEditorWnd, FORMATRANGE fr)
231 int page = 0;
235 page++;
236 fr.chrg.cpMin = SendMessageW(hEditorWnd, EM_FORMATRANGE, TRUE,
237 (LPARAM)&fr);
239 while(fr.chrg.cpMin && fr.chrg.cpMin < fr.chrg.cpMax);
241 return page;
244 static void char_from_pagenum(HWND hEditorWnd, FORMATRANGE *fr, int page)
246 int i;
248 for(i = 1; i <= page; i++)
250 if(i == page)
251 break;
253 fr->chrg.cpMin = SendMessageW(hEditorWnd, EM_FORMATRANGE, TRUE, (LPARAM)fr);
257 static HWND get_ruler_wnd(HWND hMainWnd)
259 return GetDlgItem(GetDlgItem(hMainWnd, IDC_REBAR), IDC_RULER);
262 void redraw_ruler(HWND hRulerWnd)
264 RECT rc;
266 GetClientRect(hRulerWnd, &rc);
267 InvalidateRect(hRulerWnd, &rc, TRUE);
270 static void update_ruler(HWND hRulerWnd)
272 SendMessageW(hRulerWnd, WM_USER, 0, 0);
273 redraw_ruler(hRulerWnd);
276 static void print(LPPRINTDLGW pd, LPWSTR wszFileName)
278 FORMATRANGE fr;
279 DOCINFOW di;
280 HWND hEditorWnd = GetDlgItem(pd->hwndOwner, IDC_EDITOR);
281 int printedPages = 0;
283 fr.hdc = pd->hDC;
284 fr.hdcTarget = pd->hDC;
286 fr.rc = get_print_rect(fr.hdc);
287 fr.rcPage.left = 0;
288 fr.rcPage.right = fr.rc.right + margins.right;
289 fr.rcPage.top = 0;
290 fr.rcPage.bottom = fr.rc.bottom + margins.bottom;
292 ZeroMemory(&di, sizeof(di));
293 di.cbSize = sizeof(di);
294 di.lpszDocName = wszFileName;
296 if(pd->Flags & PD_PRINTTOFILE)
298 di.lpszOutput = dialog_print_to_file(pd->hwndOwner);
299 if(!di.lpszOutput)
300 return;
303 if(pd->Flags & PD_SELECTION)
305 SendMessageW(hEditorWnd, EM_EXGETSEL, 0, (LPARAM)&fr.chrg);
306 } else
308 GETTEXTLENGTHEX gt;
309 gt.flags = GTL_DEFAULT;
310 gt.codepage = 1200;
311 fr.chrg.cpMin = 0;
312 fr.chrg.cpMax = SendMessageW(hEditorWnd, EM_GETTEXTLENGTHEX, (WPARAM)&gt, 0);
314 if(pd->Flags & PD_PAGENUMS)
315 char_from_pagenum(hEditorWnd, &fr, pd->nToPage);
318 StartDocW(fr.hdc, &di);
321 if(StartPage(fr.hdc) <= 0)
322 break;
324 fr.chrg.cpMin = SendMessageW(hEditorWnd, EM_FORMATRANGE, TRUE, (LPARAM)&fr);
326 if(EndPage(fr.hdc) <= 0)
327 break;
329 printedPages++;
330 if((pd->Flags & PD_PAGENUMS) && (printedPages > (pd->nToPage - pd->nFromPage)))
331 break;
333 while(fr.chrg.cpMin && fr.chrg.cpMin < fr.chrg.cpMax);
335 EndDoc(fr.hdc);
336 SendMessageW(hEditorWnd, EM_FORMATRANGE, FALSE, 0);
339 void dialog_printsetup(HWND hMainWnd)
341 PAGESETUPDLGW ps;
343 ZeroMemory(&ps, sizeof(ps));
344 ps.lStructSize = sizeof(ps);
345 ps.hwndOwner = hMainWnd;
346 ps.Flags = PSD_INHUNDREDTHSOFMILLIMETERS | PSD_MARGINS;
347 ps.rtMargin.left = twips_to_centmm(margins.left);
348 ps.rtMargin.right = twips_to_centmm(margins.right);
349 ps.rtMargin.top = twips_to_centmm(margins.top);
350 ps.rtMargin.bottom = twips_to_centmm(margins.bottom);
351 ps.hDevMode = devMode;
352 ps.hDevNames = devNames;
354 if(PageSetupDlgW(&ps))
356 margins.left = centmm_to_twips(ps.rtMargin.left);
357 margins.right = centmm_to_twips(ps.rtMargin.right);
358 margins.top = centmm_to_twips(ps.rtMargin.top);
359 margins.bottom = centmm_to_twips(ps.rtMargin.bottom);
360 devMode = ps.hDevMode;
361 devNames = ps.hDevNames;
362 update_ruler(get_ruler_wnd(hMainWnd));
366 void get_default_printer_opts(void)
368 PRINTDLGW pd;
369 ZeroMemory(&pd, sizeof(pd));
371 ZeroMemory(&pd, sizeof(pd));
372 pd.lStructSize = sizeof(pd);
373 pd.Flags = PD_RETURNDC | PD_RETURNDEFAULT;
374 pd.hDevMode = devMode;
376 PrintDlgW(&pd);
378 devMode = pd.hDevMode;
379 devNames = pd.hDevNames;
382 void print_quick(LPWSTR wszFileName)
384 PRINTDLGW pd;
386 ZeroMemory(&pd, sizeof(pd));
387 pd.hDC = make_dc();
389 print(&pd, wszFileName);
392 void dialog_print(HWND hMainWnd, LPWSTR wszFileName)
394 PRINTDLGW pd;
395 HWND hEditorWnd = GetDlgItem(hMainWnd, IDC_EDITOR);
396 int from = 0;
397 int to = 0;
399 ZeroMemory(&pd, sizeof(pd));
400 pd.lStructSize = sizeof(pd);
401 pd.hwndOwner = hMainWnd;
402 pd.Flags = PD_RETURNDC | PD_USEDEVMODECOPIESANDCOLLATE;
403 pd.nMinPage = 1;
404 pd.nMaxPage = -1;
405 pd.hDevMode = devMode;
406 pd.hDevNames = devNames;
408 SendMessageW(hEditorWnd, EM_GETSEL, (WPARAM)&from, (LPARAM)&to);
409 if(from == to)
410 pd.Flags |= PD_NOSELECTION;
412 if(PrintDlgW(&pd))
414 devMode = pd.hDevMode;
415 devNames = pd.hDevNames;
416 print(&pd, wszFileName);
417 update_ruler(get_ruler_wnd(hMainWnd));
421 static void preview_bar_show(HWND hMainWnd, BOOL show)
423 HWND hReBar = GetDlgItem(hMainWnd, IDC_REBAR);
424 int i;
426 if(show)
428 REBARBANDINFOW rb;
429 HWND hStatic;
431 AddTextButton(hReBar, STRING_PREVIEW_PRINT, ID_PRINT, BANDID_PREVIEW_BTN1);
432 AddTextButton(hReBar, STRING_PREVIEW_NEXTPAGE, ID_PREVIEW_NEXTPAGE, BANDID_PREVIEW_BTN2);
433 AddTextButton(hReBar, STRING_PREVIEW_PREVPAGE, ID_PREVIEW_PREVPAGE, BANDID_PREVIEW_BTN3);
434 AddTextButton(hReBar, STRING_PREVIEW_CLOSE, ID_FILE_EXIT, BANDID_PREVIEW_BTN4);
436 hStatic = CreateWindowW(WC_STATICW, NULL,
437 WS_VISIBLE | WS_CHILD, 0, 0, 0, 0,
438 hReBar, NULL, NULL, NULL);
440 rb.cbSize = sizeof(rb);
441 rb.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_STYLE | RBBIM_CHILD | RBBIM_IDEALSIZE | RBBIM_ID;
442 rb.fStyle = RBBS_NOGRIPPER | RBBS_VARIABLEHEIGHT;
443 rb.hwndChild = hStatic;
444 rb.cyChild = rb.cyMinChild = 22;
445 rb.cx = rb.cxMinChild = 90;
446 rb.cxIdeal = 100;
447 rb.wID = BANDID_PREVIEW_BUFFER;
449 SendMessageW(hReBar, RB_INSERTBAND, -1, (LPARAM)&rb);
450 } else
452 for(i = 0; i <= PREVIEW_BUTTONS; i++)
453 SendMessageW(hReBar, RB_DELETEBAND, SendMessageW(hReBar, RB_IDTOINDEX, BANDID_PREVIEW_BTN1+i, 0), 0);
457 void init_preview(HWND hMainWnd, LPWSTR wszFileName)
459 preview.page = 1;
460 preview.hdc = 0;
461 preview.wszFileName = wszFileName;
462 preview_bar_show(hMainWnd, TRUE);
465 void close_preview(HWND hMainWnd)
467 preview.window.right = 0;
468 preview.window.bottom = 0;
469 preview.page = 0;
470 preview.pages = 0;
472 preview_bar_show(hMainWnd, FALSE);
475 BOOL preview_isactive(void)
477 return preview.page != 0;
480 static void add_ruler_units(HDC hdcRuler, RECT* drawRect, BOOL NewMetrics, long EditLeftmost)
482 static HDC hdc;
484 if(NewMetrics)
486 static HBITMAP hBitmap;
487 int i, x, y, RulerTextEnd;
488 int CmPixels;
489 int QuarterCmPixels;
490 HFONT hFont;
491 WCHAR FontName[] = {'M','S',' ','S','a','n','s',' ','S','e','r','i','f',0};
493 if(hdc)
495 DeleteDC(hdc);
496 DeleteObject(hBitmap);
499 hdc = CreateCompatibleDC(hdc);
501 CmPixels = twips_to_pixels(TWIPS_PER_CM, GetDeviceCaps(hdc, LOGPIXELSX));
502 QuarterCmPixels = (int)((float)CmPixels / 4.0);
504 hBitmap = CreateCompatibleBitmap(hdc, drawRect->right, drawRect->bottom);
505 SelectObject(hdc, hBitmap);
506 FillRect(hdc, drawRect, GetStockObject(WHITE_BRUSH));
508 hFont = CreateFontW(10, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, FontName);
510 SelectObject(hdc, hFont);
511 SetBkMode(hdc, TRANSPARENT);
512 SetTextAlign(hdc, TA_CENTER);
513 y = (int)(((float)drawRect->bottom - (float)drawRect->top) / 2.0) + 1;
514 RulerTextEnd = drawRect->right - EditLeftmost + 1;
515 for(i = 1, x = EditLeftmost; x < (drawRect->right - EditLeftmost + 1); i ++)
517 WCHAR str[3];
518 WCHAR format[] = {'%','d',0};
519 int x2 = x;
521 x2 += QuarterCmPixels;
522 if(x2 > RulerTextEnd)
523 break;
525 MoveToEx(hdc, x2, y, NULL);
526 LineTo(hdc, x2, y+2);
528 x2 += QuarterCmPixels;
529 if(x2 > RulerTextEnd)
530 break;
532 MoveToEx(hdc, x2, y - 3, NULL);
533 LineTo(hdc, x2, y + 3);
535 x2 += QuarterCmPixels;
536 if(x2 > RulerTextEnd)
537 break;
539 MoveToEx(hdc, x2, y, NULL);
540 LineTo(hdc, x2, y+2);
542 x += CmPixels;
543 if(x > RulerTextEnd)
544 break;
546 wsprintfW(str, format, i);
547 TextOutW(hdc, x, 5, str, lstrlenW(str));
549 DeleteObject(hFont);
552 BitBlt(hdcRuler, 0, 0, drawRect->right, drawRect->bottom, hdc, 0, 0, SRCAND);
555 static void paint_ruler(HWND hWnd, long EditLeftmost, BOOL NewMetrics)
557 PAINTSTRUCT ps;
558 HDC hdc = BeginPaint(hWnd, &ps);
559 HDC hdcPrint = make_dc();
560 RECT printRect = get_print_rect(hdcPrint);
561 RECT drawRect;
562 HBRUSH hBrush = CreateSolidBrush(GetSysColor(COLOR_MENU));
564 GetClientRect(hWnd, &drawRect);
565 FillRect(hdc, &drawRect, hBrush);
567 drawRect.top += 3;
568 drawRect.bottom -= 3;
569 drawRect.left = EditLeftmost;
570 drawRect.right = twips_to_pixels(printRect.right - margins.left, GetDeviceCaps(hdc, LOGPIXELSX));
571 FillRect(hdc, &drawRect, GetStockObject(WHITE_BRUSH));
573 drawRect.top--;
574 drawRect.bottom++;
575 DrawEdge(hdc, &drawRect, EDGE_SUNKEN, BF_RECT);
577 drawRect.left = drawRect.right - 1;
578 drawRect.right = twips_to_pixels(printRect.right + margins.right - margins.left, GetDeviceCaps(hdc, LOGPIXELSX));
579 DrawEdge(hdc, &drawRect, EDGE_ETCHED, BF_RECT);
581 drawRect.left = 0;
582 drawRect.top = 0;
583 add_ruler_units(hdc, &drawRect, NewMetrics, EditLeftmost);
585 SelectObject(hdc, GetStockObject(BLACK_BRUSH));
586 DeleteObject(hBrush);
587 DeleteDC(hdcPrint);
588 EndPaint(hWnd, &ps);
591 LRESULT CALLBACK ruler_proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
593 static WNDPROC pPrevRulerProc;
594 static long EditLeftmost;
595 static BOOL NewMetrics;
597 switch(msg)
599 case WM_USER:
600 if(wParam)
602 EditLeftmost = ((POINTL*)wParam)->x;
603 pPrevRulerProc = (WNDPROC)lParam;
605 NewMetrics = TRUE;
606 break;
608 case WM_PAINT:
609 paint_ruler(hWnd, EditLeftmost, NewMetrics);
610 break;
612 default:
613 return CallWindowProcW(pPrevRulerProc, hWnd, msg, wParam, lParam);
616 return 0;
619 LRESULT print_preview(HWND hMainWnd)
621 FORMATRANGE fr;
622 GETTEXTLENGTHEX gt;
623 HDC hdc;
624 RECT window, background;
625 HBITMAP hBitmapCapture, hBitmapScaled;
626 int bmWidth, bmHeight, bmNewWidth, bmNewHeight;
627 float ratioWidth, ratioHeight, ratio;
628 int xOffset, yOffset;
629 int barheight;
630 HWND hReBar = GetDlgItem(hMainWnd, IDC_REBAR);
631 PAINTSTRUCT ps;
633 hdc = BeginPaint(hMainWnd, &ps);
634 GetClientRect(hMainWnd, &window);
636 fr.hdcTarget = make_dc();
637 fr.rc = get_print_rect(fr.hdcTarget);
638 fr.rcPage.left = 0;
639 fr.rcPage.top = 0;
640 fr.rcPage.bottom = fr.rc.bottom + margins.bottom;
641 fr.rcPage.right = fr.rc.right + margins.right;
643 bmWidth = twips_to_pixels(fr.rcPage.right, GetDeviceCaps(hdc, LOGPIXELSX));
644 bmHeight = twips_to_pixels(fr.rcPage.bottom, GetDeviceCaps(hdc, LOGPIXELSY));
646 hBitmapCapture = CreateCompatibleBitmap(hdc, bmWidth, bmHeight);
648 if(!preview.hdc)
650 RECT paper;
651 HWND hEditorWnd = GetDlgItem(hMainWnd, IDC_EDITOR);
653 preview.hdc = CreateCompatibleDC(hdc);
654 fr.hdc = preview.hdc;
655 gt.flags = GTL_DEFAULT;
656 gt.codepage = 1200;
657 fr.chrg.cpMin = 0;
658 fr.chrg.cpMax = SendMessageW(hEditorWnd, EM_GETTEXTLENGTHEX, (WPARAM)&gt, 0);
660 paper.left = 0;
661 paper.right = bmWidth;
662 paper.top = 0;
663 paper.bottom = bmHeight;
665 if(!preview.pages)
666 preview.pages = get_num_pages(hEditorWnd, fr);
668 SelectObject(preview.hdc, hBitmapCapture);
670 char_from_pagenum(hEditorWnd, &fr, preview.page);
672 FillRect(preview.hdc, &paper, GetStockObject(WHITE_BRUSH));
673 SendMessageW(hEditorWnd, EM_FORMATRANGE, TRUE, (LPARAM)&fr);
674 SendMessageW(hEditorWnd, EM_FORMATRANGE, FALSE, 0);
676 EnableWindow(GetDlgItem(hReBar, ID_PREVIEW_PREVPAGE), preview.page > 1);
677 EnableWindow(GetDlgItem(hReBar, ID_PREVIEW_NEXTPAGE), preview.page < preview.pages);
680 barheight = SendMessageW(hReBar, RB_GETBARHEIGHT, 0, 0);
681 ratioWidth = ((float)window.right - 20.0) / (float)bmHeight;
682 ratioHeight = ((float)window.bottom - 20.0 - (float)barheight) / (float)bmHeight;
684 if(ratioWidth > ratioHeight)
685 ratio = ratioHeight;
686 else
687 ratio = ratioWidth;
689 bmNewWidth = (int)((float)bmWidth * ratio);
690 bmNewHeight = (int)((float)bmHeight * ratio);
691 hBitmapScaled = CreateCompatibleBitmap(hdc, bmNewWidth, bmNewHeight);
693 xOffset = ((window.right - bmNewWidth) / 2);
694 yOffset = ((window.bottom - bmNewHeight + barheight) / 2);
696 if(window.right != preview.window.right || window.bottom != preview.window.bottom)
698 HPEN hPen;
699 int TopMargin = (int)((float)twips_to_pixels(fr.rc.top, GetDeviceCaps(hdc, LOGPIXELSX)) * ratio);
700 int BottomMargin = (int)((float)twips_to_pixels(fr.rc.bottom, GetDeviceCaps(hdc, LOGPIXELSX)) * ratio);
701 int LeftMargin = (int)((float)twips_to_pixels(fr.rc.left, GetDeviceCaps(hdc, LOGPIXELSY)) * ratio);
702 int RightMargin = (int)((float)twips_to_pixels(fr.rc.right, GetDeviceCaps(hdc, LOGPIXELSY)) * ratio);
704 DeleteDC(preview.hdcSized);
705 preview.hdcSized = CreateCompatibleDC(hdc);
706 SelectObject(preview.hdcSized, hBitmapScaled);
708 StretchBlt(preview.hdcSized, 0, 0, bmNewWidth, bmNewHeight, preview.hdc, 0, 0, bmWidth, bmHeight, SRCCOPY);
710 /* Draw margin lines */
711 hPen = CreatePen(PS_DOT, 1, RGB(0,0,0));
712 SelectObject(preview.hdcSized, hPen);
714 MoveToEx(preview.hdcSized, 0, TopMargin, NULL);
715 LineTo(preview.hdcSized, bmNewWidth, TopMargin);
716 MoveToEx(preview.hdcSized, 0, BottomMargin, NULL);
717 LineTo(preview.hdcSized, bmNewWidth, BottomMargin);
719 MoveToEx(preview.hdcSized, LeftMargin, 0, NULL);
720 LineTo(preview.hdcSized, LeftMargin, bmNewHeight);
721 MoveToEx(preview.hdcSized, RightMargin, 0, NULL);
722 LineTo(preview.hdcSized, RightMargin, bmNewHeight);
725 window.top = barheight;
726 FillRect(hdc, &window, GetStockObject(GRAY_BRUSH));
728 SelectObject(hdc, hBitmapScaled);
730 background.left = xOffset - 2;
731 background.right = xOffset + bmNewWidth + 2;
732 background.top = yOffset - 2;
733 background.bottom = yOffset + bmNewHeight + 2;
735 FillRect(hdc, &background, GetStockObject(BLACK_BRUSH));
737 BitBlt(hdc, xOffset, yOffset, bmNewWidth, bmNewHeight, preview.hdcSized, 0, 0, SRCCOPY);
739 DeleteDC(fr.hdcTarget);
740 preview.window = window;
742 EndPaint(hMainWnd, &ps);
744 return 0;
747 LRESULT preview_command(HWND hWnd, WPARAM wParam, LPARAM lParam)
749 switch(LOWORD(wParam))
751 case ID_FILE_EXIT:
752 PostMessageW(hWnd, WM_CLOSE, 0, 0);
753 break;
755 case ID_PREVIEW_NEXTPAGE:
756 case ID_PREVIEW_PREVPAGE:
758 HWND hReBar = GetDlgItem(hWnd, IDC_REBAR);
759 RECT rc;
761 if(LOWORD(wParam) == ID_PREVIEW_NEXTPAGE)
762 preview.page++;
763 else
764 preview.page--;
766 preview.hdc = 0;
767 preview.window.right = 0;
769 GetClientRect(hWnd, &rc);
770 rc.top += SendMessageW(hReBar, RB_GETBARHEIGHT, 0, 0);
771 InvalidateRect(hWnd, &rc, TRUE);
773 break;
775 case ID_PRINT:
776 dialog_print(hWnd, preview.wszFileName);
777 SendMessageW(hWnd, WM_CLOSE, 0, 0);
778 break;
781 return 0;