2 * COMMDLG - Print Dialog
4 * Copyright 1994 Martin Ayotte
5 * Copyright 1996 Albrecht Kleine
6 * Copyright 1999 Klaas van Gend
7 * Copyright 2000 Huw D M Davies
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
30 #define NONAMELESSUNION
31 #define NONAMELESSSTRUCT
39 #include "wine/unicode.h"
40 #include "wine/debug.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
51 /* Yes these constants are the same, but we're just copying win98 */
52 #define UPDOWN_ID 0x270f
53 #define MAX_COPIES 9999
56 static const struct pd_flags psd_flags[] = {
57 {PSD_MINMARGINS,"PSD_MINMARGINS"},
58 {PSD_MARGINS,"PSD_MARGINS"},
59 {PSD_INTHOUSANDTHSOFINCHES,"PSD_INTHOUSANDTHSOFINCHES"},
60 {PSD_INHUNDREDTHSOFMILLIMETERS,"PSD_INHUNDREDTHSOFMILLIMETERS"},
61 {PSD_DISABLEMARGINS,"PSD_DISABLEMARGINS"},
62 {PSD_DISABLEPRINTER,"PSD_DISABLEPRINTER"},
63 {PSD_NOWARNING,"PSD_NOWARNING"},
64 {PSD_DISABLEORIENTATION,"PSD_DISABLEORIENTATION"},
65 {PSD_RETURNDEFAULT,"PSD_RETURNDEFAULT"},
66 {PSD_DISABLEPAPER,"PSD_DISABLEPAPER"},
67 {PSD_SHOWHELP,"PSD_SHOWHELP"},
68 {PSD_ENABLEPAGESETUPHOOK,"PSD_ENABLEPAGESETUPHOOK"},
69 {PSD_ENABLEPAGESETUPTEMPLATE,"PSD_ENABLEPAGESETUPTEMPLATE"},
70 {PSD_ENABLEPAGESETUPTEMPLATEHANDLE,"PSD_ENABLEPAGESETUPTEMPLATEHANDLE"},
71 {PSD_ENABLEPAGEPAINTHOOK,"PSD_ENABLEPAGEPAINTHOOK"},
72 {PSD_DISABLEPAGEPAINTING,"PSD_DISABLEPAGEPAINTING"},
76 /* address of wndproc for subclassed Static control */
77 static WNDPROC lpfnStaticWndProc;
78 static WNDPROC edit_wndproc;
79 /* the text of the fake document to render for the Page Setup dialog */
80 static WCHAR wszFakeDocumentText[1024];
81 static const WCHAR pd32_collateW[] = { 'P', 'D', '3', '2', '_', 'C', 'O', 'L', 'L', 'A', 'T', 'E', 0 };
82 static const WCHAR pd32_nocollateW[] = { 'P', 'D', '3', '2', '_', 'N', 'O', 'C', 'O', 'L', 'L', 'A', 'T', 'E', 0 };
83 static const WCHAR pd32_portraitW[] = { 'P', 'D', '3', '2', '_', 'P', 'O', 'R', 'T', 'R', 'A', 'I', 'T', 0 };
84 static const WCHAR pd32_landscapeW[] = { 'P', 'D', '3', '2', '_', 'L', 'A', 'N', 'D', 'S', 'C', 'A', 'P', 'E', 0 };
85 static const WCHAR printdlg_prop[] = {'_','_','W','I','N','E','_','P','R','I','N','T','D','L','G','D','A','T','A',0};
86 static const WCHAR pagesetupdlg_prop[] = { '_', '_', 'W', 'I', 'N', 'E', '_', 'P', 'A', 'G', 'E',
87 'S', 'E', 'T', 'U', 'P', 'D', 'L', 'G', 'D', 'A', 'T', 'A', 0 };
89 /***********************************************************************
90 * PRINTDLG_OpenDefaultPrinter
92 * Returns a winspool printer handle to the default printer in *hprn
93 * Caller must call ClosePrinter on the handle
95 * Returns TRUE on success else FALSE
97 BOOL PRINTDLG_OpenDefaultPrinter(HANDLE *hprn)
100 DWORD dwBufLen = sizeof(buf) / sizeof(buf[0]);
102 if(!GetDefaultPrinterW(buf, &dwBufLen))
104 res = OpenPrinterW(buf, hprn, NULL);
106 WARN("Could not open printer %s\n", debugstr_w(buf));
110 /***********************************************************************
111 * PRINTDLG_SetUpPrinterListCombo
113 * Initializes printer list combox.
114 * hDlg: HWND of dialog
115 * id: Control id of combo
116 * name: Name of printer to select
118 * Initializes combo with list of available printers. Selects printer 'name'
119 * If name is NULL or does not exist select the default printer.
121 * Returns number of printers added to list.
123 INT PRINTDLG_SetUpPrinterListComboA(HWND hDlg, UINT id, LPCSTR name)
127 LPPRINTER_INFO_2A pi;
128 EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
129 pi = HeapAlloc(GetProcessHeap(), 0, needed);
130 EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pi, needed, &needed,
133 SendDlgItemMessageA(hDlg, id, CB_RESETCONTENT, 0, 0);
135 for(i = 0; i < num; i++) {
136 SendDlgItemMessageA(hDlg, id, CB_ADDSTRING, 0,
137 (LPARAM)pi[i].pPrinterName );
139 HeapFree(GetProcessHeap(), 0, pi);
141 (i = SendDlgItemMessageA(hDlg, id, CB_FINDSTRINGEXACT, -1,
142 (LPARAM)name)) == CB_ERR) {
145 DWORD dwBufLen = sizeof(buf);
147 WARN("Can't find %s in printer list so trying to find default\n",
149 if(!GetDefaultPrinterA(buf, &dwBufLen))
151 i = SendDlgItemMessageA(hDlg, id, CB_FINDSTRINGEXACT, -1, (LPARAM)buf);
153 FIXME("Can't find default printer in printer list\n");
155 SendDlgItemMessageA(hDlg, id, CB_SETCURSEL, i, 0);
159 static INT PRINTDLG_SetUpPrinterListComboW(HWND hDlg, UINT id, LPCWSTR name)
163 LPPRINTER_INFO_2W pi;
164 EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
165 pi = HeapAlloc(GetProcessHeap(), 0, needed);
166 EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pi, needed, &needed,
169 for(i = 0; i < num; i++) {
170 SendDlgItemMessageW(hDlg, id, CB_ADDSTRING, 0,
171 (LPARAM)pi[i].pPrinterName );
173 HeapFree(GetProcessHeap(), 0, pi);
175 (i = SendDlgItemMessageW(hDlg, id, CB_FINDSTRINGEXACT, -1,
176 (LPARAM)name)) == CB_ERR) {
178 DWORD dwBufLen = sizeof(buf)/sizeof(buf[0]);
180 WARN("Can't find %s in printer list so trying to find default\n",
182 if(!GetDefaultPrinterW(buf, &dwBufLen))
184 i = SendDlgItemMessageW(hDlg, id, CB_FINDSTRINGEXACT, -1, (LPARAM)buf);
186 TRACE("Can't find default printer in printer list\n");
188 SendDlgItemMessageW(hDlg, id, CB_SETCURSEL, i, 0);
192 /***********************************************************************
193 * PRINTDLG_CreateDevNames [internal]
196 * creates a DevNames structure.
198 * (NB. when we handle unicode the offsets will be in wchars).
200 static BOOL PRINTDLG_CreateDevNames(HGLOBAL *hmem, const char* DeviceDriverName,
201 const char* DeviceName, const char* OutputPort)
204 char* pDevNamesSpace;
206 LPDEVNAMES lpDevNames;
208 DWORD dwBufLen = sizeof(buf);
210 size = strlen(DeviceDriverName) + 1
211 + strlen(DeviceName) + 1
212 + strlen(OutputPort) + 1
216 *hmem = GlobalReAlloc(*hmem, size, GMEM_MOVEABLE);
218 *hmem = GlobalAlloc(GMEM_MOVEABLE, size);
222 pDevNamesSpace = GlobalLock(*hmem);
223 lpDevNames = (LPDEVNAMES) pDevNamesSpace;
225 pTempPtr = pDevNamesSpace + sizeof(DEVNAMES);
226 strcpy(pTempPtr, DeviceDriverName);
227 lpDevNames->wDriverOffset = pTempPtr - pDevNamesSpace;
229 pTempPtr += strlen(DeviceDriverName) + 1;
230 strcpy(pTempPtr, DeviceName);
231 lpDevNames->wDeviceOffset = pTempPtr - pDevNamesSpace;
233 pTempPtr += strlen(DeviceName) + 1;
234 strcpy(pTempPtr, OutputPort);
235 lpDevNames->wOutputOffset = pTempPtr - pDevNamesSpace;
237 GetDefaultPrinterA(buf, &dwBufLen);
238 lpDevNames->wDefault = (strcmp(buf, DeviceName) == 0) ? 1 : 0;
243 static BOOL PRINTDLG_CreateDevNamesW(HGLOBAL *hmem, LPCWSTR DeviceDriverName,
244 LPCWSTR DeviceName, LPCWSTR OutputPort)
247 LPWSTR pDevNamesSpace;
249 LPDEVNAMES lpDevNames;
251 DWORD dwBufLen = sizeof(bufW) / sizeof(WCHAR);
253 size = sizeof(WCHAR)*lstrlenW(DeviceDriverName) + 2
254 + sizeof(WCHAR)*lstrlenW(DeviceName) + 2
255 + sizeof(WCHAR)*lstrlenW(OutputPort) + 2
259 *hmem = GlobalReAlloc(*hmem, size, GMEM_MOVEABLE);
261 *hmem = GlobalAlloc(GMEM_MOVEABLE, size);
265 pDevNamesSpace = GlobalLock(*hmem);
266 lpDevNames = (LPDEVNAMES) pDevNamesSpace;
268 pTempPtr = (LPWSTR)((LPDEVNAMES)pDevNamesSpace + 1);
269 lstrcpyW(pTempPtr, DeviceDriverName);
270 lpDevNames->wDriverOffset = pTempPtr - pDevNamesSpace;
272 pTempPtr += lstrlenW(DeviceDriverName) + 1;
273 lstrcpyW(pTempPtr, DeviceName);
274 lpDevNames->wDeviceOffset = pTempPtr - pDevNamesSpace;
276 pTempPtr += lstrlenW(DeviceName) + 1;
277 lstrcpyW(pTempPtr, OutputPort);
278 lpDevNames->wOutputOffset = pTempPtr - pDevNamesSpace;
280 GetDefaultPrinterW(bufW, &dwBufLen);
281 lpDevNames->wDefault = (lstrcmpW(bufW, DeviceName) == 0) ? 1 : 0;
286 /***********************************************************************
287 * PRINTDLG_UpdatePrintDlg [internal]
290 * updates the PrintDlg structure for return values.
293 * FALSE if user is not allowed to close (i.e. wrong nTo or nFrom values)
294 * TRUE if successful.
296 static BOOL PRINTDLG_UpdatePrintDlgA(HWND hDlg,
297 PRINT_PTRA* PrintStructures)
299 LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
300 PDEVMODEA lpdm = PrintStructures->lpDevMode;
301 LPPRINTER_INFO_2A pi = PrintStructures->lpPrinterInfo;
305 FIXME("No lpdm ptr?\n");
310 if(!(lppd->Flags & PD_PRINTSETUP)) {
311 /* check whether nFromPage and nToPage are within range defined by
312 * nMinPage and nMaxPage
314 if (IsDlgButtonChecked(hDlg, rad3) == BST_CHECKED) { /* Pages */
318 nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
319 nToPage = GetDlgItemInt(hDlg, edt2, &translated, FALSE);
321 /* if no ToPage value is entered, use the FromPage value */
322 if(!translated) nToPage = nFromPage;
324 if (nFromPage < lppd->nMinPage || nFromPage > lppd->nMaxPage ||
325 nToPage < lppd->nMinPage || nToPage > lppd->nMaxPage) {
326 WCHAR resourcestr[256];
327 WCHAR resultstr[256];
328 LoadStringW(COMDLG32_hInstance, PD32_INVALID_PAGE_RANGE, resourcestr, 255);
329 wsprintfW(resultstr,resourcestr, lppd->nMinPage, lppd->nMaxPage);
330 LoadStringW(COMDLG32_hInstance, PD32_PRINT_TITLE, resourcestr, 255);
331 MessageBoxW(hDlg, resultstr, resourcestr, MB_OK | MB_ICONWARNING);
334 lppd->nFromPage = nFromPage;
335 lppd->nToPage = nToPage;
336 lppd->Flags |= PD_PAGENUMS;
339 lppd->Flags &= ~PD_PAGENUMS;
341 if (IsDlgButtonChecked(hDlg, rad2) == BST_CHECKED) /* Selection */
342 lppd->Flags |= PD_SELECTION;
344 lppd->Flags &= ~PD_SELECTION;
346 if (IsDlgButtonChecked(hDlg, chx1) == BST_CHECKED) {/* Print to file */
347 static char file[] = "FILE:";
348 lppd->Flags |= PD_PRINTTOFILE;
349 pi->pPortName = file;
352 if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED) { /* Collate */
353 FIXME("Collate lppd not yet implemented as output\n");
356 /* set PD_Collate and nCopies */
357 if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
358 /* The application doesn't support multiple copies or collate...
360 lppd->Flags &= ~PD_COLLATE;
362 /* if the printer driver supports it... store info there
363 * otherwise no collate & multiple copies !
365 if (lpdm->dmFields & DM_COLLATE)
367 (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED);
368 if (lpdm->dmFields & DM_COPIES)
369 lpdm->u1.s1.dmCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
371 /* Application is responsible for multiple copies */
372 if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
373 lppd->Flags |= PD_COLLATE;
375 lppd->Flags &= ~PD_COLLATE;
376 lppd->nCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
377 /* multiple copies already included in the document. Driver must print only one copy */
378 lpdm->u1.s1.dmCopies = 1;
381 /* Print quality, PrintDlg16 */
382 if(GetDlgItem(hDlg, cmb1))
384 HWND hQuality = GetDlgItem(hDlg, cmb1);
385 int Sel = SendMessageA(hQuality, CB_GETCURSEL, 0, 0);
389 LONG dpi = SendMessageA(hQuality, CB_GETITEMDATA, Sel, 0);
390 lpdm->dmFields |= DM_PRINTQUALITY | DM_YRESOLUTION;
391 lpdm->u1.s1.dmPrintQuality = LOWORD(dpi);
392 lpdm->dmYResolution = HIWORD(dpi);
399 static BOOL PRINTDLG_UpdatePrintDlgW(HWND hDlg,
400 PRINT_PTRW* PrintStructures)
402 LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
403 PDEVMODEW lpdm = PrintStructures->lpDevMode;
404 LPPRINTER_INFO_2W pi = PrintStructures->lpPrinterInfo;
408 FIXME("No lpdm ptr?\n");
413 if(!(lppd->Flags & PD_PRINTSETUP)) {
414 /* check whether nFromPage and nToPage are within range defined by
415 * nMinPage and nMaxPage
417 if (IsDlgButtonChecked(hDlg, rad3) == BST_CHECKED) { /* Pages */
421 nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
422 nToPage = GetDlgItemInt(hDlg, edt2, &translated, FALSE);
424 /* if no ToPage value is entered, use the FromPage value */
425 if(!translated) nToPage = nFromPage;
427 if (nFromPage < lppd->nMinPage || nFromPage > lppd->nMaxPage ||
428 nToPage < lppd->nMinPage || nToPage > lppd->nMaxPage) {
429 WCHAR resourcestr[256];
430 WCHAR resultstr[256];
431 LoadStringW(COMDLG32_hInstance, PD32_INVALID_PAGE_RANGE,
433 wsprintfW(resultstr,resourcestr, lppd->nMinPage, lppd->nMaxPage);
434 LoadStringW(COMDLG32_hInstance, PD32_PRINT_TITLE,
436 MessageBoxW(hDlg, resultstr, resourcestr,
437 MB_OK | MB_ICONWARNING);
440 lppd->nFromPage = nFromPage;
441 lppd->nToPage = nToPage;
442 lppd->Flags |= PD_PAGENUMS;
445 lppd->Flags &= ~PD_PAGENUMS;
447 if (IsDlgButtonChecked(hDlg, rad2) == BST_CHECKED) /* Selection */
448 lppd->Flags |= PD_SELECTION;
450 lppd->Flags &= ~PD_SELECTION;
452 if (IsDlgButtonChecked(hDlg, chx1) == BST_CHECKED) {/* Print to file */
453 static WCHAR file[] = {'F','I','L','E',':',0};
454 lppd->Flags |= PD_PRINTTOFILE;
455 pi->pPortName = file;
458 if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED) { /* Collate */
459 FIXME("Collate lppd not yet implemented as output\n");
462 /* set PD_Collate and nCopies */
463 if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
464 /* The application doesn't support multiple copies or collate...
466 lppd->Flags &= ~PD_COLLATE;
468 /* if the printer driver supports it... store info there
469 * otherwise no collate & multiple copies !
471 if (lpdm->dmFields & DM_COLLATE)
473 (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED);
474 if (lpdm->dmFields & DM_COPIES)
475 lpdm->u1.s1.dmCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
477 if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
478 lppd->Flags |= PD_COLLATE;
480 lppd->Flags &= ~PD_COLLATE;
481 lppd->nCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
487 static BOOL PRINTDLG_PaperSizeW(
488 PRINTDLGW *pdlga,const WCHAR *PaperSize,LPPOINT size
492 LPWSTR devname,portname;
496 POINT *points = NULL;
499 dn = GlobalLock(pdlga->hDevNames);
500 dm = GlobalLock(pdlga->hDevMode);
501 devname = ((WCHAR*)dn)+dn->wDeviceOffset;
502 portname = ((WCHAR*)dn)+dn->wOutputOffset;
505 NrOfEntries = DeviceCapabilitiesW(devname,portname,DC_PAPERNAMES,NULL,dm);
507 FIXME("No papernames found for %s/%s\n",debugstr_w(devname),debugstr_w(portname));
510 if (NrOfEntries == -1) {
511 ERR("Hmm ? DeviceCapabilities() DC_PAPERNAMES failed, ret -1 !\n");
515 Names = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*NrOfEntries*64);
516 if (NrOfEntries != (ret=DeviceCapabilitiesW(devname,portname,DC_PAPERNAMES,Names,dm))) {
517 FIXME("Number of returned vals %d is not %d\n",NrOfEntries,ret);
520 for (i=0;i<NrOfEntries;i++)
521 if (!lstrcmpW(PaperSize,Names+(64*i)))
523 if (i==NrOfEntries) {
524 FIXME("Papersize %s not found in list?\n",debugstr_w(PaperSize));
527 points = HeapAlloc(GetProcessHeap(),0,sizeof(points[0])*NrOfEntries);
528 if (NrOfEntries!=(ret=DeviceCapabilitiesW(devname,portname,DC_PAPERSIZE,(LPWSTR)points,dm))) {
529 FIXME("Number of returned sizes %d is not %d?\n",NrOfEntries,ret);
532 /* this is _10ths_ of a millimeter */
537 GlobalUnlock(pdlga->hDevNames);
538 GlobalUnlock(pdlga->hDevMode);
539 HeapFree(GetProcessHeap(),0,Names);
540 HeapFree(GetProcessHeap(),0,points);
545 /************************************************************************
546 * PRINTDLG_SetUpPaperComboBox
548 * Initialize either the papersize or inputslot combos of the Printer Setup
549 * dialog. We store the associated word (eg DMPAPER_A4) as the item data.
550 * We also try to re-select the old selection.
552 static BOOL PRINTDLG_SetUpPaperComboBoxA(HWND hDlg,
565 int fwCapability_Names;
566 int fwCapability_Words;
568 TRACE(" Printer: %s, Port: %s, ComboID: %d\n",PrinterName,PortName,nIDComboBox);
570 /* query the dialog box for the current selected value */
571 Sel = SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETCURSEL, 0, 0);
573 /* we enter here only if a different printer is selected after
574 * the Print Setup dialog is opened. The current settings are
575 * stored into the newly selected printer.
577 oldWord = SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA,
580 if (nIDComboBox == cmb2)
581 dm->u1.s1.dmPaperSize = oldWord;
583 dm->u1.s1.dmDefaultSource = oldWord;
587 /* we enter here only when the Print setup dialog is initially
588 * opened. In this case the settings are restored from when
589 * the dialog was last closed.
592 if (nIDComboBox == cmb2)
593 oldWord = dm->u1.s1.dmPaperSize;
595 oldWord = dm->u1.s1.dmDefaultSource;
599 if (nIDComboBox == cmb2) {
601 fwCapability_Names = DC_PAPERNAMES;
602 fwCapability_Words = DC_PAPERS;
606 fwCapability_Names = DC_BINNAMES;
607 fwCapability_Words = DC_BINS;
610 NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
611 fwCapability_Names, NULL, dm);
612 if (NrOfEntries == 0)
613 WARN("no Name Entries found!\n");
614 else if (NrOfEntries < 0)
617 if(DeviceCapabilitiesA(PrinterName, PortName, fwCapability_Words, NULL, dm)
619 ERR("Number of caps is different\n");
623 Names = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(char)*NamesSize);
624 Words = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(WORD));
625 NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
626 fwCapability_Names, Names, dm);
627 NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
628 fwCapability_Words, (LPSTR)Words, dm);
630 /* reset any current content in the combobox */
631 SendDlgItemMessageA(hDlg, nIDComboBox, CB_RESETCONTENT, 0, 0);
633 /* store new content */
634 for (i = 0; i < NrOfEntries; i++) {
635 DWORD pos = SendDlgItemMessageA(hDlg, nIDComboBox, CB_ADDSTRING, 0,
636 (LPARAM)(&Names[i*NamesSize]) );
637 SendDlgItemMessageA(hDlg, nIDComboBox, CB_SETITEMDATA, pos,
641 /* Look for old selection - can't do this is previous loop since
642 item order will change as more items are added */
644 for (i = 0; i < NrOfEntries; i++) {
645 if(SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) ==
651 SendDlgItemMessageA(hDlg, nIDComboBox, CB_SETCURSEL, Sel, 0);
653 HeapFree(GetProcessHeap(),0,Words);
654 HeapFree(GetProcessHeap(),0,Names);
658 static BOOL PRINTDLG_SetUpPaperComboBoxW(HWND hDlg,
660 const WCHAR* PrinterName,
661 const WCHAR* PortName,
671 int fwCapability_Names;
672 int fwCapability_Words;
674 TRACE(" Printer: %s, Port: %s, ComboID: %d\n",debugstr_w(PrinterName),debugstr_w(PortName),nIDComboBox);
676 /* query the dialog box for the current selected value */
677 Sel = SendDlgItemMessageW(hDlg, nIDComboBox, CB_GETCURSEL, 0, 0);
679 /* we enter here only if a different printer is selected after
680 * the Print Setup dialog is opened. The current settings are
681 * stored into the newly selected printer.
683 oldWord = SendDlgItemMessageW(hDlg, nIDComboBox, CB_GETITEMDATA,
686 if (nIDComboBox == cmb2)
687 dm->u1.s1.dmPaperSize = oldWord;
689 dm->u1.s1.dmDefaultSource = oldWord;
693 /* we enter here only when the Print setup dialog is initially
694 * opened. In this case the settings are restored from when
695 * the dialog was last closed.
698 if (nIDComboBox == cmb2)
699 oldWord = dm->u1.s1.dmPaperSize;
701 oldWord = dm->u1.s1.dmDefaultSource;
705 if (nIDComboBox == cmb2) {
707 fwCapability_Names = DC_PAPERNAMES;
708 fwCapability_Words = DC_PAPERS;
712 fwCapability_Names = DC_BINNAMES;
713 fwCapability_Words = DC_BINS;
716 NrOfEntries = DeviceCapabilitiesW(PrinterName, PortName,
717 fwCapability_Names, NULL, dm);
718 if (NrOfEntries == 0)
719 WARN("no Name Entries found!\n");
720 else if (NrOfEntries < 0)
723 if(DeviceCapabilitiesW(PrinterName, PortName, fwCapability_Words, NULL, dm)
725 ERR("Number of caps is different\n");
729 Names = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(WCHAR)*NamesSize);
730 Words = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(WORD));
731 NrOfEntries = DeviceCapabilitiesW(PrinterName, PortName,
732 fwCapability_Names, Names, dm);
733 NrOfEntries = DeviceCapabilitiesW(PrinterName, PortName,
734 fwCapability_Words, Words, dm);
736 /* reset any current content in the combobox */
737 SendDlgItemMessageW(hDlg, nIDComboBox, CB_RESETCONTENT, 0, 0);
739 /* store new content */
740 for (i = 0; i < NrOfEntries; i++) {
741 DWORD pos = SendDlgItemMessageW(hDlg, nIDComboBox, CB_ADDSTRING, 0,
742 (LPARAM)(&Names[i*NamesSize]) );
743 SendDlgItemMessageW(hDlg, nIDComboBox, CB_SETITEMDATA, pos,
747 /* Look for old selection - can't do this is previous loop since
748 item order will change as more items are added */
750 for (i = 0; i < NrOfEntries; i++) {
751 if(SendDlgItemMessageW(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) ==
757 SendDlgItemMessageW(hDlg, nIDComboBox, CB_SETCURSEL, Sel, 0);
759 HeapFree(GetProcessHeap(),0,Words);
760 HeapFree(GetProcessHeap(),0,Names);
765 /***********************************************************************
766 * PRINTDLG_UpdatePrinterInfoTexts [internal]
768 static void PRINTDLG_UpdatePrinterInfoTextsA(HWND hDlg, const PRINTER_INFO_2A *pi)
771 char ResourceString[256];
777 /* add all status messages */
778 for (i = 0; i < 25; i++) {
779 if (pi->Status & (1<<i)) {
780 LoadStringA(COMDLG32_hInstance, PD32_PRINTER_STATUS_PAUSED+i,
781 ResourceString, 255);
782 strcat(StatusMsg,ResourceString);
786 /* FIXME: status==ready must only be appended if really so.
787 but how to detect? */
788 LoadStringA(COMDLG32_hInstance, PD32_PRINTER_STATUS_READY,
789 ResourceString, 255);
790 strcat(StatusMsg,ResourceString);
791 SetDlgItemTextA(hDlg, stc12, StatusMsg);
793 /* set all other printer info texts */
794 SetDlgItemTextA(hDlg, stc11, pi->pDriverName);
796 if (pi->pLocation != NULL && pi->pLocation[0] != '\0')
797 SetDlgItemTextA(hDlg, stc14, pi->pLocation);
799 SetDlgItemTextA(hDlg, stc14, pi->pPortName);
800 SetDlgItemTextA(hDlg, stc13, pi->pComment ? pi->pComment : "");
804 static void PRINTDLG_UpdatePrinterInfoTextsW(HWND hDlg, const PRINTER_INFO_2W *pi)
806 WCHAR StatusMsg[256];
807 WCHAR ResourceString[256];
808 static const WCHAR emptyW[] = {0};
814 /* add all status messages */
815 for (i = 0; i < 25; i++) {
816 if (pi->Status & (1<<i)) {
817 LoadStringW(COMDLG32_hInstance, PD32_PRINTER_STATUS_PAUSED+i,
818 ResourceString, 255);
819 lstrcatW(StatusMsg,ResourceString);
823 /* FIXME: status==ready must only be appended if really so.
824 but how to detect? */
825 LoadStringW(COMDLG32_hInstance, PD32_PRINTER_STATUS_READY,
826 ResourceString, 255);
827 lstrcatW(StatusMsg,ResourceString);
828 SetDlgItemTextW(hDlg, stc12, StatusMsg);
830 /* set all other printer info texts */
831 SetDlgItemTextW(hDlg, stc11, pi->pDriverName);
832 if (pi->pLocation != NULL && pi->pLocation[0] != '\0')
833 SetDlgItemTextW(hDlg, stc14, pi->pLocation);
835 SetDlgItemTextW(hDlg, stc14, pi->pPortName);
836 SetDlgItemTextW(hDlg, stc13, pi->pComment ? pi->pComment : emptyW);
840 /*******************************************************************
842 * PRINTDLG_ChangePrinter
845 BOOL PRINTDLG_ChangePrinterA(HWND hDlg, char *name,
846 PRINT_PTRA *PrintStructures)
848 LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
849 LPDEVMODEA lpdm = NULL;
854 HeapFree(GetProcessHeap(),0, PrintStructures->lpPrinterInfo);
855 HeapFree(GetProcessHeap(),0, PrintStructures->lpDriverInfo);
856 if(!OpenPrinterA(name, &hprn, NULL)) {
857 ERR("Can't open printer %s\n", name);
860 GetPrinterA(hprn, 2, NULL, 0, &needed);
861 PrintStructures->lpPrinterInfo = HeapAlloc(GetProcessHeap(),0,needed);
862 GetPrinterA(hprn, 2, (LPBYTE)PrintStructures->lpPrinterInfo, needed,
864 GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
865 PrintStructures->lpDriverInfo = HeapAlloc(GetProcessHeap(),0,needed);
866 if (!GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)PrintStructures->lpDriverInfo,
868 ERR("GetPrinterDriverA failed for %s, fix your config!\n",PrintStructures->lpPrinterInfo->pPrinterName);
873 PRINTDLG_UpdatePrinterInfoTextsA(hDlg, PrintStructures->lpPrinterInfo);
875 HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
876 PrintStructures->lpDevMode = NULL;
878 dmSize = DocumentPropertiesA(0, 0, name, NULL, NULL, 0);
880 ERR("DocumentProperties fails on %s\n", debugstr_a(name));
883 PrintStructures->lpDevMode = HeapAlloc(GetProcessHeap(), 0, dmSize);
884 dmSize = DocumentPropertiesA(0, 0, name, PrintStructures->lpDevMode, NULL,
886 if(lppd->hDevMode && (lpdm = GlobalLock(lppd->hDevMode)) &&
887 !lstrcmpA( (LPSTR) lpdm->dmDeviceName,
888 (LPSTR) PrintStructures->lpDevMode->dmDeviceName)) {
889 /* Supplied devicemode matches current printer so try to use it */
890 DocumentPropertiesA(0, 0, name, PrintStructures->lpDevMode, lpdm,
891 DM_OUT_BUFFER | DM_IN_BUFFER);
894 GlobalUnlock(lppd->hDevMode);
896 lpdm = PrintStructures->lpDevMode; /* use this as a shortcut */
898 if(!(lppd->Flags & PD_PRINTSETUP)) {
899 /* Print range (All/Range/Selection) */
900 if(lppd->nFromPage != 0xffff)
901 SetDlgItemInt(hDlg, edt1, lppd->nFromPage, FALSE);
902 if(lppd->nToPage != 0xffff)
903 SetDlgItemInt(hDlg, edt2, lppd->nToPage, FALSE);
905 CheckRadioButton(hDlg, rad1, rad3, rad1); /* default */
906 if (lppd->Flags & PD_NOSELECTION)
907 EnableWindow(GetDlgItem(hDlg, rad2), FALSE);
909 if (lppd->Flags & PD_SELECTION)
910 CheckRadioButton(hDlg, rad1, rad3, rad2);
911 if (lppd->Flags & PD_NOPAGENUMS) {
912 EnableWindow(GetDlgItem(hDlg, rad3), FALSE);
913 EnableWindow(GetDlgItem(hDlg, stc2),FALSE);
914 EnableWindow(GetDlgItem(hDlg, edt1), FALSE);
915 EnableWindow(GetDlgItem(hDlg, stc3),FALSE);
916 EnableWindow(GetDlgItem(hDlg, edt2), FALSE);
918 if (lppd->Flags & PD_PAGENUMS)
919 CheckRadioButton(hDlg, rad1, rad3, rad3);
924 * FIXME: The ico3 is not displayed for some reason. I don't know why.
926 if (lppd->Flags & PD_COLLATE) {
927 SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
928 (LPARAM)PrintStructures->hCollateIcon);
929 CheckDlgButton(hDlg, chx2, 1);
931 SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
932 (LPARAM)PrintStructures->hNoCollateIcon);
933 CheckDlgButton(hDlg, chx2, 0);
936 if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
937 /* if printer doesn't support it: no Collate */
938 if (!(lpdm->dmFields & DM_COLLATE)) {
939 EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
940 EnableWindow(GetDlgItem(hDlg, ico3), FALSE);
947 if (lppd->hDevMode == 0)
948 copies = lppd->nCopies;
950 copies = lpdm->u1.s1.dmCopies;
951 if(copies == 0) copies = 1;
952 else if(copies < 0) copies = MAX_COPIES;
953 SetDlgItemInt(hDlg, edt3, copies, FALSE);
956 if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
957 /* if printer doesn't support it: no nCopies */
958 if (!(lpdm->dmFields & DM_COPIES)) {
959 EnableWindow(GetDlgItem(hDlg, edt3), FALSE);
960 EnableWindow(GetDlgItem(hDlg, stc5), FALSE);
965 CheckDlgButton(hDlg, chx1, (lppd->Flags & PD_PRINTTOFILE) ? 1 : 0);
966 if (lppd->Flags & PD_DISABLEPRINTTOFILE)
967 EnableWindow(GetDlgItem(hDlg, chx1), FALSE);
968 if (lppd->Flags & PD_HIDEPRINTTOFILE)
969 ShowWindow(GetDlgItem(hDlg, chx1), SW_HIDE);
971 /* Fill print quality combo, PrintDlg16 */
972 if(GetDlgItem(hDlg, cmb1))
974 DWORD numResolutions = DeviceCapabilitiesA(PrintStructures->lpPrinterInfo->pPrinterName,
975 PrintStructures->lpPrinterInfo->pPortName,
976 DC_ENUMRESOLUTIONS, NULL, lpdm);
978 if(numResolutions != -1)
980 HWND hQuality = GetDlgItem(hDlg, cmb1);
985 HDC hPrinterDC = CreateDCA(PrintStructures->lpPrinterInfo->pDriverName,
986 PrintStructures->lpPrinterInfo->pPrinterName,
989 Resolutions = HeapAlloc(GetProcessHeap(), 0, numResolutions*sizeof(LONG)*2);
990 DeviceCapabilitiesA(PrintStructures->lpPrinterInfo->pPrinterName,
991 PrintStructures->lpPrinterInfo->pPortName,
992 DC_ENUMRESOLUTIONS, (LPSTR)Resolutions, lpdm);
994 dpiX = GetDeviceCaps(hPrinterDC, LOGPIXELSX);
995 dpiY = GetDeviceCaps(hPrinterDC, LOGPIXELSY);
996 DeleteDC(hPrinterDC);
998 SendMessageA(hQuality, CB_RESETCONTENT, 0, 0);
999 for(i = 0; i < (numResolutions * 2); i += 2)
1001 BOOL IsDefault = FALSE;
1004 if(Resolutions[i] == Resolutions[i+1])
1006 if(dpiX == Resolutions[i])
1008 sprintf(buf, "%d dpi", Resolutions[i]);
1011 if(dpiX == Resolutions[i] && dpiY == Resolutions[i+1])
1013 sprintf(buf, "%d dpi x %d dpi", Resolutions[i], Resolutions[i+1]);
1016 Index = SendMessageA(hQuality, CB_ADDSTRING, 0, (LPARAM)buf);
1019 SendMessageA(hQuality, CB_SETCURSEL, Index, 0);
1021 SendMessageA(hQuality, CB_SETITEMDATA, Index, MAKELONG(dpiX,dpiY));
1023 HeapFree(GetProcessHeap(), 0, Resolutions);
1026 } else { /* PD_PRINTSETUP */
1027 BOOL bPortrait = (lpdm->u1.s1.dmOrientation == DMORIENT_PORTRAIT);
1029 PRINTDLG_SetUpPaperComboBoxA(hDlg, cmb2,
1030 PrintStructures->lpPrinterInfo->pPrinterName,
1031 PrintStructures->lpPrinterInfo->pPortName,
1033 PRINTDLG_SetUpPaperComboBoxA(hDlg, cmb3,
1034 PrintStructures->lpPrinterInfo->pPrinterName,
1035 PrintStructures->lpPrinterInfo->pPortName,
1037 CheckRadioButton(hDlg, rad1, rad2, bPortrait ? rad1: rad2);
1038 SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1039 (LPARAM)(bPortrait ? PrintStructures->hPortraitIcon :
1040 PrintStructures->hLandscapeIcon));
1045 if ((lppd->Flags & PD_SHOWHELP)==0) {
1046 /* hide if PD_SHOWHELP not specified */
1047 ShowWindow(GetDlgItem(hDlg, pshHelp), SW_HIDE);
1052 static BOOL PRINTDLG_ChangePrinterW(HWND hDlg, WCHAR *name,
1053 PRINT_PTRW *PrintStructures)
1055 LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
1056 LPDEVMODEW lpdm = NULL;
1061 HeapFree(GetProcessHeap(),0, PrintStructures->lpPrinterInfo);
1062 HeapFree(GetProcessHeap(),0, PrintStructures->lpDriverInfo);
1063 if(!OpenPrinterW(name, &hprn, NULL)) {
1064 ERR("Can't open printer %s\n", debugstr_w(name));
1067 GetPrinterW(hprn, 2, NULL, 0, &needed);
1068 PrintStructures->lpPrinterInfo = HeapAlloc(GetProcessHeap(),0,needed);
1069 GetPrinterW(hprn, 2, (LPBYTE)PrintStructures->lpPrinterInfo, needed,
1071 GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
1072 PrintStructures->lpDriverInfo = HeapAlloc(GetProcessHeap(),0,needed);
1073 if (!GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)PrintStructures->lpDriverInfo,
1075 ERR("GetPrinterDriverA failed for %s, fix your config!\n",debugstr_w(PrintStructures->lpPrinterInfo->pPrinterName));
1080 PRINTDLG_UpdatePrinterInfoTextsW(hDlg, PrintStructures->lpPrinterInfo);
1082 HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
1083 PrintStructures->lpDevMode = NULL;
1085 dmSize = DocumentPropertiesW(0, 0, name, NULL, NULL, 0);
1087 ERR("DocumentProperties fails on %s\n", debugstr_w(name));
1090 PrintStructures->lpDevMode = HeapAlloc(GetProcessHeap(), 0, dmSize);
1091 dmSize = DocumentPropertiesW(0, 0, name, PrintStructures->lpDevMode, NULL,
1093 if(lppd->hDevMode && (lpdm = GlobalLock(lppd->hDevMode)) &&
1094 !lstrcmpW(lpdm->dmDeviceName,
1095 PrintStructures->lpDevMode->dmDeviceName)) {
1096 /* Supplied devicemode matches current printer so try to use it */
1097 DocumentPropertiesW(0, 0, name, PrintStructures->lpDevMode, lpdm,
1098 DM_OUT_BUFFER | DM_IN_BUFFER);
1101 GlobalUnlock(lppd->hDevMode);
1103 lpdm = PrintStructures->lpDevMode; /* use this as a shortcut */
1105 if(!(lppd->Flags & PD_PRINTSETUP)) {
1106 /* Print range (All/Range/Selection) */
1107 if(lppd->nFromPage != 0xffff)
1108 SetDlgItemInt(hDlg, edt1, lppd->nFromPage, FALSE);
1109 if(lppd->nToPage != 0xffff)
1110 SetDlgItemInt(hDlg, edt2, lppd->nToPage, FALSE);
1112 CheckRadioButton(hDlg, rad1, rad3, rad1); /* default */
1113 if (lppd->Flags & PD_NOSELECTION)
1114 EnableWindow(GetDlgItem(hDlg, rad2), FALSE);
1116 if (lppd->Flags & PD_SELECTION)
1117 CheckRadioButton(hDlg, rad1, rad3, rad2);
1118 if (lppd->Flags & PD_NOPAGENUMS) {
1119 EnableWindow(GetDlgItem(hDlg, rad3), FALSE);
1120 EnableWindow(GetDlgItem(hDlg, stc2),FALSE);
1121 EnableWindow(GetDlgItem(hDlg, edt1), FALSE);
1122 EnableWindow(GetDlgItem(hDlg, stc3),FALSE);
1123 EnableWindow(GetDlgItem(hDlg, edt2), FALSE);
1125 if (lppd->Flags & PD_PAGENUMS)
1126 CheckRadioButton(hDlg, rad1, rad3, rad3);
1131 * FIXME: The ico3 is not displayed for some reason. I don't know why.
1133 if (lppd->Flags & PD_COLLATE) {
1134 SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1135 (LPARAM)PrintStructures->hCollateIcon);
1136 CheckDlgButton(hDlg, chx2, 1);
1138 SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1139 (LPARAM)PrintStructures->hNoCollateIcon);
1140 CheckDlgButton(hDlg, chx2, 0);
1143 if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
1144 /* if printer doesn't support it: no Collate */
1145 if (!(lpdm->dmFields & DM_COLLATE)) {
1146 EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
1147 EnableWindow(GetDlgItem(hDlg, ico3), FALSE);
1154 if (lppd->hDevMode == 0)
1155 copies = lppd->nCopies;
1157 copies = lpdm->u1.s1.dmCopies;
1158 if(copies == 0) copies = 1;
1159 else if(copies < 0) copies = MAX_COPIES;
1160 SetDlgItemInt(hDlg, edt3, copies, FALSE);
1163 if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
1164 /* if printer doesn't support it: no nCopies */
1165 if (!(lpdm->dmFields & DM_COPIES)) {
1166 EnableWindow(GetDlgItem(hDlg, edt3), FALSE);
1167 EnableWindow(GetDlgItem(hDlg, stc5), FALSE);
1172 CheckDlgButton(hDlg, chx1, (lppd->Flags & PD_PRINTTOFILE) ? 1 : 0);
1173 if (lppd->Flags & PD_DISABLEPRINTTOFILE)
1174 EnableWindow(GetDlgItem(hDlg, chx1), FALSE);
1175 if (lppd->Flags & PD_HIDEPRINTTOFILE)
1176 ShowWindow(GetDlgItem(hDlg, chx1), SW_HIDE);
1178 } else { /* PD_PRINTSETUP */
1179 BOOL bPortrait = (lpdm->u1.s1.dmOrientation == DMORIENT_PORTRAIT);
1181 PRINTDLG_SetUpPaperComboBoxW(hDlg, cmb2,
1182 PrintStructures->lpPrinterInfo->pPrinterName,
1183 PrintStructures->lpPrinterInfo->pPortName,
1185 PRINTDLG_SetUpPaperComboBoxW(hDlg, cmb3,
1186 PrintStructures->lpPrinterInfo->pPrinterName,
1187 PrintStructures->lpPrinterInfo->pPortName,
1189 CheckRadioButton(hDlg, rad1, rad2, bPortrait ? rad1: rad2);
1190 SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1191 (LPARAM)(bPortrait ? PrintStructures->hPortraitIcon :
1192 PrintStructures->hLandscapeIcon));
1197 if ((lppd->Flags & PD_SHOWHELP)==0) {
1198 /* hide if PD_SHOWHELP not specified */
1199 ShowWindow(GetDlgItem(hDlg, pshHelp), SW_HIDE);
1204 /***********************************************************************
1205 * check_printer_setup [internal]
1207 static LRESULT check_printer_setup(HWND hDlg)
1210 WCHAR resourcestr[256],resultstr[256];
1212 EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
1215 EnumPrintersW(PRINTER_ENUM_CONNECTIONS, NULL, 2, NULL, 0, &needed, &num);
1221 LoadStringW(COMDLG32_hInstance, PD32_NO_DEVICES,resultstr, 255);
1222 LoadStringW(COMDLG32_hInstance, PD32_PRINT_TITLE,resourcestr, 255);
1223 MessageBoxW(hDlg, resultstr, resourcestr,MB_OK | MB_ICONWARNING);
1228 /***********************************************************************
1229 * PRINTDLG_WMInitDialog [internal]
1231 static LRESULT PRINTDLG_WMInitDialog(HWND hDlg, WPARAM wParam,
1232 PRINT_PTRA* PrintStructures)
1234 LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
1238 UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1240 /* load Collate ICONs */
1241 /* We load these with LoadImage because they are not a standard
1242 size and we don't want them rescaled */
1243 PrintStructures->hCollateIcon =
1244 LoadImageA(COMDLG32_hInstance, "PD32_COLLATE", IMAGE_ICON, 0, 0, 0);
1245 PrintStructures->hNoCollateIcon =
1246 LoadImageA(COMDLG32_hInstance, "PD32_NOCOLLATE", IMAGE_ICON, 0, 0, 0);
1248 /* These can be done with LoadIcon */
1249 PrintStructures->hPortraitIcon =
1250 LoadIconA(COMDLG32_hInstance, "PD32_PORTRAIT");
1251 PrintStructures->hLandscapeIcon =
1252 LoadIconA(COMDLG32_hInstance, "PD32_LANDSCAPE");
1254 /* display the collate/no_collate icon */
1255 SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1256 (LPARAM)PrintStructures->hNoCollateIcon);
1258 if(PrintStructures->hCollateIcon == 0 ||
1259 PrintStructures->hNoCollateIcon == 0 ||
1260 PrintStructures->hPortraitIcon == 0 ||
1261 PrintStructures->hLandscapeIcon == 0) {
1262 ERR("no icon in resourcefile\n");
1263 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
1264 EndDialog(hDlg, FALSE);
1268 * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
1269 * must be registered and the Help button must be shown.
1271 if (lppd->Flags & PD_SHOWHELP) {
1272 if((PrintStructures->HelpMessageID =
1273 RegisterWindowMessageA(HELPMSGSTRINGA)) == 0) {
1274 COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL);
1278 PrintStructures->HelpMessageID = 0;
1280 if(!(lppd->Flags &PD_PRINTSETUP)) {
1281 PrintStructures->hwndUpDown =
1282 CreateUpDownControl(WS_CHILD | WS_VISIBLE | WS_BORDER |
1283 UDS_NOTHOUSANDS | UDS_ARROWKEYS |
1284 UDS_ALIGNRIGHT | UDS_SETBUDDYINT, 0, 0, 0, 0,
1285 hDlg, UPDOWN_ID, COMDLG32_hInstance,
1286 GetDlgItem(hDlg, edt3), MAX_COPIES, 1, 1);
1289 /* FIXME: I allow more freedom than either Win95 or WinNT,
1290 * which do not agree to what errors should be thrown or not
1291 * in case nToPage or nFromPage is out-of-range.
1293 if (lppd->nMaxPage < lppd->nMinPage)
1294 lppd->nMaxPage = lppd->nMinPage;
1295 if (lppd->nMinPage == lppd->nMaxPage)
1296 lppd->Flags |= PD_NOPAGENUMS;
1297 if (lppd->nToPage < lppd->nMinPage)
1298 lppd->nToPage = lppd->nMinPage;
1299 if (lppd->nToPage > lppd->nMaxPage)
1300 lppd->nToPage = lppd->nMaxPage;
1301 if (lppd->nFromPage < lppd->nMinPage)
1302 lppd->nFromPage = lppd->nMinPage;
1303 if (lppd->nFromPage > lppd->nMaxPage)
1304 lppd->nFromPage = lppd->nMaxPage;
1306 /* if we have the combo box, fill it */
1307 if (GetDlgItem(hDlg,comboID)) {
1310 pdn = GlobalLock(lppd->hDevNames);
1311 pdm = GlobalLock(lppd->hDevMode);
1313 name = (char*)pdn + pdn->wDeviceOffset;
1315 name = (char*)pdm->dmDeviceName;
1316 PRINTDLG_SetUpPrinterListComboA(hDlg, comboID, name);
1317 if(pdm) GlobalUnlock(lppd->hDevMode);
1318 if(pdn) GlobalUnlock(lppd->hDevNames);
1320 /* Now find selected printer and update rest of dlg */
1321 name = HeapAlloc(GetProcessHeap(),0,256);
1322 if (GetDlgItemTextA(hDlg, comboID, name, 255))
1323 PRINTDLG_ChangePrinterA(hDlg, name, PrintStructures);
1324 HeapFree(GetProcessHeap(),0,name);
1326 /* else use default printer */
1328 DWORD dwBufLen = sizeof(name);
1329 BOOL ret = GetDefaultPrinterA(name, &dwBufLen);
1332 PRINTDLG_ChangePrinterA(hDlg, name, PrintStructures);
1334 FIXME("No default printer found, expect problems!\n");
1339 static LRESULT PRINTDLG_WMInitDialogW(HWND hDlg, WPARAM wParam,
1340 PRINT_PTRW* PrintStructures)
1342 LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
1346 UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1348 /* load Collate ICONs */
1349 /* We load these with LoadImage because they are not a standard
1350 size and we don't want them rescaled */
1351 PrintStructures->hCollateIcon =
1352 LoadImageW(COMDLG32_hInstance, pd32_collateW, IMAGE_ICON, 0, 0, 0);
1353 PrintStructures->hNoCollateIcon =
1354 LoadImageW(COMDLG32_hInstance, pd32_nocollateW, IMAGE_ICON, 0, 0, 0);
1356 /* These can be done with LoadIcon */
1357 PrintStructures->hPortraitIcon =
1358 LoadIconW(COMDLG32_hInstance, pd32_portraitW);
1359 PrintStructures->hLandscapeIcon =
1360 LoadIconW(COMDLG32_hInstance, pd32_landscapeW);
1362 /* display the collate/no_collate icon */
1363 SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1364 (LPARAM)PrintStructures->hNoCollateIcon);
1366 if(PrintStructures->hCollateIcon == 0 ||
1367 PrintStructures->hNoCollateIcon == 0 ||
1368 PrintStructures->hPortraitIcon == 0 ||
1369 PrintStructures->hLandscapeIcon == 0) {
1370 ERR("no icon in resourcefile\n");
1371 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
1372 EndDialog(hDlg, FALSE);
1376 * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
1377 * must be registered and the Help button must be shown.
1379 if (lppd->Flags & PD_SHOWHELP) {
1380 if((PrintStructures->HelpMessageID =
1381 RegisterWindowMessageW(HELPMSGSTRINGW)) == 0) {
1382 COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL);
1386 PrintStructures->HelpMessageID = 0;
1388 if(!(lppd->Flags &PD_PRINTSETUP)) {
1389 PrintStructures->hwndUpDown =
1390 CreateUpDownControl(WS_CHILD | WS_VISIBLE | WS_BORDER |
1391 UDS_NOTHOUSANDS | UDS_ARROWKEYS |
1392 UDS_ALIGNRIGHT | UDS_SETBUDDYINT, 0, 0, 0, 0,
1393 hDlg, UPDOWN_ID, COMDLG32_hInstance,
1394 GetDlgItem(hDlg, edt3), MAX_COPIES, 1, 1);
1397 /* FIXME: I allow more freedom than either Win95 or WinNT,
1398 * which do not agree to what errors should be thrown or not
1399 * in case nToPage or nFromPage is out-of-range.
1401 if (lppd->nMaxPage < lppd->nMinPage)
1402 lppd->nMaxPage = lppd->nMinPage;
1403 if (lppd->nMinPage == lppd->nMaxPage)
1404 lppd->Flags |= PD_NOPAGENUMS;
1405 if (lppd->nToPage < lppd->nMinPage)
1406 lppd->nToPage = lppd->nMinPage;
1407 if (lppd->nToPage > lppd->nMaxPage)
1408 lppd->nToPage = lppd->nMaxPage;
1409 if (lppd->nFromPage < lppd->nMinPage)
1410 lppd->nFromPage = lppd->nMinPage;
1411 if (lppd->nFromPage > lppd->nMaxPage)
1412 lppd->nFromPage = lppd->nMaxPage;
1414 /* if we have the combo box, fill it */
1415 if (GetDlgItem(hDlg,comboID)) {
1418 pdn = GlobalLock(lppd->hDevNames);
1419 pdm = GlobalLock(lppd->hDevMode);
1421 name = (WCHAR*)pdn + pdn->wDeviceOffset;
1423 name = pdm->dmDeviceName;
1424 PRINTDLG_SetUpPrinterListComboW(hDlg, comboID, name);
1425 if(pdm) GlobalUnlock(lppd->hDevMode);
1426 if(pdn) GlobalUnlock(lppd->hDevNames);
1428 /* Now find selected printer and update rest of dlg */
1429 /* ansi is ok here */
1430 name = HeapAlloc(GetProcessHeap(),0,256*sizeof(WCHAR));
1431 if (GetDlgItemTextW(hDlg, comboID, name, 255))
1432 PRINTDLG_ChangePrinterW(hDlg, name, PrintStructures);
1433 HeapFree(GetProcessHeap(),0,name);
1435 /* else use default printer */
1437 DWORD dwBufLen = sizeof(name) / sizeof(WCHAR);
1438 BOOL ret = GetDefaultPrinterW(name, &dwBufLen);
1441 PRINTDLG_ChangePrinterW(hDlg, name, PrintStructures);
1443 FIXME("No default printer found, expect problems!\n");
1448 /***********************************************************************
1449 * PRINTDLG_WMCommand [internal]
1451 LRESULT PRINTDLG_WMCommandA(HWND hDlg, WPARAM wParam,
1452 LPARAM lParam, PRINT_PTRA* PrintStructures)
1454 LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
1455 UINT PrinterComboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1456 LPDEVMODEA lpdm = PrintStructures->lpDevMode;
1458 switch (LOWORD(wParam)) {
1460 TRACE(" OK button was hit\n");
1461 if (!PRINTDLG_UpdatePrintDlgA(hDlg, PrintStructures)) {
1462 FIXME("Update printdlg was not successful!\n");
1465 EndDialog(hDlg, TRUE);
1469 TRACE(" CANCEL button was hit\n");
1470 EndDialog(hDlg, FALSE);
1474 TRACE(" HELP button was hit\n");
1475 SendMessageA(lppd->hwndOwner, PrintStructures->HelpMessageID,
1476 (WPARAM) hDlg, (LPARAM) lppd);
1479 case chx2: /* collate pages checkbox */
1480 if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
1481 SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1482 (LPARAM)PrintStructures->hCollateIcon);
1484 SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1485 (LPARAM)PrintStructures->hNoCollateIcon);
1487 case edt1: /* from page nr editbox */
1488 case edt2: /* to page nr editbox */
1489 if (HIWORD(wParam)==EN_CHANGE) {
1492 nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
1493 nToPage = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
1494 if (nFromPage != lppd->nFromPage || nToPage != lppd->nToPage)
1495 CheckRadioButton(hDlg, rad1, rad3, rad3);
1500 if(HIWORD(wParam) == EN_CHANGE) {
1501 INT copies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
1503 EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
1505 EnableWindow(GetDlgItem(hDlg, chx2), TRUE);
1510 case psh1: /* Print Setup */
1514 if (!PrintStructures->dlg.lpPrintDlg16) {
1515 FIXME("The 32bit print dialog does not have this button!?\n");
1519 memcpy(&pdlg,PrintStructures->dlg.lpPrintDlg16,sizeof(pdlg));
1520 pdlg.Flags |= PD_PRINTSETUP;
1521 pdlg.hwndOwner = HWND_16(hDlg);
1522 if (!PrintDlg16(&pdlg))
1527 case psh2: /* Properties button */
1530 char PrinterName[256];
1532 GetDlgItemTextA(hDlg, PrinterComboID, PrinterName, 255);
1533 if (!OpenPrinterA(PrinterName, &hPrinter, NULL)) {
1534 FIXME(" Call to OpenPrinter did not succeed!\n");
1537 DocumentPropertiesA(hDlg, hPrinter, PrinterName,
1538 PrintStructures->lpDevMode,
1539 PrintStructures->lpDevMode,
1540 DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
1541 ClosePrinter(hPrinter);
1545 case rad1: /* Paperorientation */
1546 if (lppd->Flags & PD_PRINTSETUP)
1548 lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1549 SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1550 (LPARAM)(PrintStructures->hPortraitIcon));
1554 case rad2: /* Paperorientation */
1555 if (lppd->Flags & PD_PRINTSETUP)
1557 lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1558 SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1559 (LPARAM)(PrintStructures->hLandscapeIcon));
1563 case cmb1: /* Printer Combobox in PRINT SETUP, quality combobox in PRINT16 */
1564 if (PrinterComboID != LOWORD(wParam)) {
1568 case cmb4: /* Printer combobox */
1569 if (HIWORD(wParam)==CBN_SELCHANGE) {
1570 char PrinterName[256];
1571 GetDlgItemTextA(hDlg, LOWORD(wParam), PrinterName, 255);
1572 PRINTDLG_ChangePrinterA(hDlg, PrinterName, PrintStructures);
1576 case cmb2: /* Papersize */
1578 DWORD Sel = SendDlgItemMessageA(hDlg, cmb2, CB_GETCURSEL, 0, 0);
1580 lpdm->u1.s1.dmPaperSize = SendDlgItemMessageA(hDlg, cmb2,
1586 case cmb3: /* Bin */
1588 DWORD Sel = SendDlgItemMessageA(hDlg, cmb3, CB_GETCURSEL, 0, 0);
1590 lpdm->u1.s1.dmDefaultSource = SendDlgItemMessageA(hDlg, cmb3,
1591 CB_GETITEMDATA, Sel,
1596 if(lppd->Flags & PD_PRINTSETUP) {
1597 switch (LOWORD(wParam)) {
1598 case rad1: /* orientation */
1600 if (IsDlgButtonChecked(hDlg, rad1) == BST_CHECKED) {
1601 if(lpdm->u1.s1.dmOrientation != DMORIENT_PORTRAIT) {
1602 lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1603 SendDlgItemMessageA(hDlg, stc10, STM_SETIMAGE,
1605 (LPARAM)PrintStructures->hPortraitIcon);
1606 SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE,
1608 (LPARAM)PrintStructures->hPortraitIcon);
1611 if(lpdm->u1.s1.dmOrientation != DMORIENT_LANDSCAPE) {
1612 lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1613 SendDlgItemMessageA(hDlg, stc10, STM_SETIMAGE,
1615 (LPARAM)PrintStructures->hLandscapeIcon);
1616 SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE,
1618 (LPARAM)PrintStructures->hLandscapeIcon);
1627 static LRESULT PRINTDLG_WMCommandW(HWND hDlg, WPARAM wParam,
1628 LPARAM lParam, PRINT_PTRW* PrintStructures)
1630 LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
1631 UINT PrinterComboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1632 LPDEVMODEW lpdm = PrintStructures->lpDevMode;
1634 switch (LOWORD(wParam)) {
1636 TRACE(" OK button was hit\n");
1637 if (!PRINTDLG_UpdatePrintDlgW(hDlg, PrintStructures)) {
1638 FIXME("Update printdlg was not successful!\n");
1641 EndDialog(hDlg, TRUE);
1645 TRACE(" CANCEL button was hit\n");
1646 EndDialog(hDlg, FALSE);
1650 TRACE(" HELP button was hit\n");
1651 SendMessageW(lppd->hwndOwner, PrintStructures->HelpMessageID,
1652 (WPARAM) hDlg, (LPARAM) lppd);
1655 case chx2: /* collate pages checkbox */
1656 if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
1657 SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1658 (LPARAM)PrintStructures->hCollateIcon);
1660 SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1661 (LPARAM)PrintStructures->hNoCollateIcon);
1663 case edt1: /* from page nr editbox */
1664 case edt2: /* to page nr editbox */
1665 if (HIWORD(wParam)==EN_CHANGE) {
1668 nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
1669 nToPage = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
1670 if (nFromPage != lppd->nFromPage || nToPage != lppd->nToPage)
1671 CheckRadioButton(hDlg, rad1, rad3, rad3);
1676 if(HIWORD(wParam) == EN_CHANGE) {
1677 INT copies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
1679 EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
1681 EnableWindow(GetDlgItem(hDlg, chx2), TRUE);
1685 case psh1: /* Print Setup */
1687 ERR("psh1 is called from 16bit code only, we should not get here.\n");
1690 case psh2: /* Properties button */
1693 WCHAR PrinterName[256];
1695 if (!GetDlgItemTextW(hDlg, PrinterComboID, PrinterName, 255)) break;
1696 if (!OpenPrinterW(PrinterName, &hPrinter, NULL)) {
1697 FIXME(" Call to OpenPrinter did not succeed!\n");
1700 DocumentPropertiesW(hDlg, hPrinter, PrinterName,
1701 PrintStructures->lpDevMode,
1702 PrintStructures->lpDevMode,
1703 DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
1704 ClosePrinter(hPrinter);
1708 case rad1: /* Paperorientation */
1709 if (lppd->Flags & PD_PRINTSETUP)
1711 lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1712 SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1713 (LPARAM)(PrintStructures->hPortraitIcon));
1717 case rad2: /* Paperorientation */
1718 if (lppd->Flags & PD_PRINTSETUP)
1720 lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1721 SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1722 (LPARAM)(PrintStructures->hLandscapeIcon));
1726 case cmb1: /* Printer Combobox in PRINT SETUP */
1728 case cmb4: /* Printer combobox */
1729 if (HIWORD(wParam)==CBN_SELCHANGE) {
1730 WCHAR PrinterName[256];
1731 GetDlgItemTextW(hDlg, LOWORD(wParam), PrinterName, 255);
1732 PRINTDLG_ChangePrinterW(hDlg, PrinterName, PrintStructures);
1736 case cmb2: /* Papersize */
1738 DWORD Sel = SendDlgItemMessageW(hDlg, cmb2, CB_GETCURSEL, 0, 0);
1740 lpdm->u1.s1.dmPaperSize = SendDlgItemMessageW(hDlg, cmb2,
1746 case cmb3: /* Bin */
1748 DWORD Sel = SendDlgItemMessageW(hDlg, cmb3, CB_GETCURSEL, 0, 0);
1750 lpdm->u1.s1.dmDefaultSource = SendDlgItemMessageW(hDlg, cmb3,
1751 CB_GETITEMDATA, Sel,
1756 if(lppd->Flags & PD_PRINTSETUP) {
1757 switch (LOWORD(wParam)) {
1758 case rad1: /* orientation */
1760 if (IsDlgButtonChecked(hDlg, rad1) == BST_CHECKED) {
1761 if(lpdm->u1.s1.dmOrientation != DMORIENT_PORTRAIT) {
1762 lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1763 SendDlgItemMessageW(hDlg, stc10, STM_SETIMAGE,
1765 (LPARAM)PrintStructures->hPortraitIcon);
1766 SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE,
1768 (LPARAM)PrintStructures->hPortraitIcon);
1771 if(lpdm->u1.s1.dmOrientation != DMORIENT_LANDSCAPE) {
1772 lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1773 SendDlgItemMessageW(hDlg, stc10, STM_SETIMAGE,
1775 (LPARAM)PrintStructures->hLandscapeIcon);
1776 SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE,
1778 (LPARAM)PrintStructures->hLandscapeIcon);
1787 /***********************************************************************
1788 * PrintDlgProcA [internal]
1790 static INT_PTR CALLBACK PrintDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam,
1793 PRINT_PTRA* PrintStructures;
1794 INT_PTR res = FALSE;
1796 if (uMsg!=WM_INITDIALOG) {
1797 PrintStructures = GetPropW(hDlg, printdlg_prop);
1798 if (!PrintStructures)
1801 PrintStructures = (PRINT_PTRA*) lParam;
1802 SetPropW(hDlg, printdlg_prop, PrintStructures);
1803 if(!check_printer_setup(hDlg))
1805 EndDialog(hDlg,FALSE);
1808 res = PRINTDLG_WMInitDialog(hDlg, wParam, PrintStructures);
1810 if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK)
1811 res = PrintStructures->lpPrintDlg->lpfnPrintHook(
1812 hDlg, uMsg, wParam, (LPARAM)PrintStructures->lpPrintDlg
1817 if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK) {
1818 res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg,uMsg,wParam,
1825 return PRINTDLG_WMCommandA(hDlg, wParam, lParam, PrintStructures);
1828 DestroyIcon(PrintStructures->hCollateIcon);
1829 DestroyIcon(PrintStructures->hNoCollateIcon);
1830 DestroyIcon(PrintStructures->hPortraitIcon);
1831 DestroyIcon(PrintStructures->hLandscapeIcon);
1832 if(PrintStructures->hwndUpDown)
1833 DestroyWindow(PrintStructures->hwndUpDown);
1839 static INT_PTR CALLBACK PrintDlgProcW(HWND hDlg, UINT uMsg, WPARAM wParam,
1842 PRINT_PTRW* PrintStructures;
1843 INT_PTR res = FALSE;
1845 if (uMsg!=WM_INITDIALOG) {
1846 PrintStructures = GetPropW(hDlg, printdlg_prop);
1847 if (!PrintStructures)
1850 PrintStructures = (PRINT_PTRW*) lParam;
1851 SetPropW(hDlg, printdlg_prop, PrintStructures);
1852 if(!check_printer_setup(hDlg))
1854 EndDialog(hDlg,FALSE);
1857 res = PRINTDLG_WMInitDialogW(hDlg, wParam, PrintStructures);
1859 if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK)
1860 res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg, uMsg, wParam, (LPARAM)PrintStructures->lpPrintDlg);
1864 if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK) {
1865 res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg,uMsg,wParam, lParam);
1871 return PRINTDLG_WMCommandW(hDlg, wParam, lParam, PrintStructures);
1874 DestroyIcon(PrintStructures->hCollateIcon);
1875 DestroyIcon(PrintStructures->hNoCollateIcon);
1876 DestroyIcon(PrintStructures->hPortraitIcon);
1877 DestroyIcon(PrintStructures->hLandscapeIcon);
1878 if(PrintStructures->hwndUpDown)
1879 DestroyWindow(PrintStructures->hwndUpDown);
1885 /************************************************************
1887 * PRINTDLG_GetDlgTemplate
1890 static HGLOBAL PRINTDLG_GetDlgTemplateA(const PRINTDLGA *lppd)
1895 if (lppd->Flags & PD_PRINTSETUP) {
1896 if(lppd->Flags & PD_ENABLESETUPTEMPLATEHANDLE) {
1897 hDlgTmpl = lppd->hSetupTemplate;
1898 } else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) {
1899 hResInfo = FindResourceA(lppd->hInstance,
1900 lppd->lpSetupTemplateName, (LPSTR)RT_DIALOG);
1901 hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
1903 hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32_SETUP",
1905 hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
1908 if(lppd->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) {
1909 hDlgTmpl = lppd->hPrintTemplate;
1910 } else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) {
1911 hResInfo = FindResourceA(lppd->hInstance,
1912 lppd->lpPrintTemplateName,
1914 hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
1916 hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32",
1918 hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
1924 static HGLOBAL PRINTDLG_GetDlgTemplateW(const PRINTDLGW *lppd)
1928 static const WCHAR xpsetup[] = { 'P','R','I','N','T','3','2','_','S','E','T','U','P',0};
1929 static const WCHAR xprint[] = { 'P','R','I','N','T','3','2',0};
1931 if (lppd->Flags & PD_PRINTSETUP) {
1932 if(lppd->Flags & PD_ENABLESETUPTEMPLATEHANDLE) {
1933 hDlgTmpl = lppd->hSetupTemplate;
1934 } else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) {
1935 hResInfo = FindResourceW(lppd->hInstance,
1936 lppd->lpSetupTemplateName, (LPWSTR)RT_DIALOG);
1937 hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
1939 hResInfo = FindResourceW(COMDLG32_hInstance, xpsetup, (LPWSTR)RT_DIALOG);
1940 hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
1943 if(lppd->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) {
1944 hDlgTmpl = lppd->hPrintTemplate;
1945 } else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) {
1946 hResInfo = FindResourceW(lppd->hInstance,
1947 lppd->lpPrintTemplateName,
1949 hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
1951 hResInfo = FindResourceW(COMDLG32_hInstance, xprint, (LPWSTR)RT_DIALOG);
1952 hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
1958 /***********************************************************************
1963 static BOOL PRINTDLG_CreateDCA(LPPRINTDLGA lppd)
1965 DEVNAMES *pdn = GlobalLock(lppd->hDevNames);
1966 DEVMODEA *pdm = GlobalLock(lppd->hDevMode);
1968 if(lppd->Flags & PD_RETURNDC) {
1969 lppd->hDC = CreateDCA((char*)pdn + pdn->wDriverOffset,
1970 (char*)pdn + pdn->wDeviceOffset,
1971 (char*)pdn + pdn->wOutputOffset,
1973 } else if(lppd->Flags & PD_RETURNIC) {
1974 lppd->hDC = CreateICA((char*)pdn + pdn->wDriverOffset,
1975 (char*)pdn + pdn->wDeviceOffset,
1976 (char*)pdn + pdn->wOutputOffset,
1979 GlobalUnlock(lppd->hDevNames);
1980 GlobalUnlock(lppd->hDevMode);
1981 return lppd->hDC ? TRUE : FALSE;
1984 static BOOL PRINTDLG_CreateDCW(LPPRINTDLGW lppd)
1986 DEVNAMES *pdn = GlobalLock(lppd->hDevNames);
1987 DEVMODEW *pdm = GlobalLock(lppd->hDevMode);
1989 if(lppd->Flags & PD_RETURNDC) {
1990 lppd->hDC = CreateDCW((WCHAR*)pdn + pdn->wDriverOffset,
1991 (WCHAR*)pdn + pdn->wDeviceOffset,
1992 (WCHAR*)pdn + pdn->wOutputOffset,
1994 } else if(lppd->Flags & PD_RETURNIC) {
1995 lppd->hDC = CreateICW((WCHAR*)pdn + pdn->wDriverOffset,
1996 (WCHAR*)pdn + pdn->wDeviceOffset,
1997 (WCHAR*)pdn + pdn->wOutputOffset,
2000 GlobalUnlock(lppd->hDevNames);
2001 GlobalUnlock(lppd->hDevMode);
2002 return lppd->hDC ? TRUE : FALSE;
2005 /***********************************************************************
2006 * PrintDlgA (COMDLG32.@)
2008 * Displays the PRINT dialog box, which enables the user to specify
2009 * specific properties of the print job.
2012 * lppd [IO] ptr to PRINTDLG32 struct
2015 * nonzero if the user pressed the OK button
2016 * zero if the user cancelled the window or an error occurred
2020 * * The Collate Icons do not display, even though they are in the code.
2021 * * The Properties Button(s) should call DocumentPropertiesA().
2024 BOOL WINAPI PrintDlgA(LPPRINTDLGA lppd)
2032 COMDLG32_SetCommDlgExtendedError(CDERR_INITIALIZATION);
2036 hInst = (HINSTANCE)GetWindowLongPtrA( lppd->hwndOwner, GWLP_HINSTANCE );
2037 if(TRACE_ON(commdlg)) {
2038 char flagstr[1000] = "";
2039 const struct pd_flags *pflag = pd_flags;
2040 for( ; pflag->name; pflag++) {
2041 if(lppd->Flags & pflag->flag)
2042 strcat(flagstr, pflag->name);
2044 TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
2045 "pp. %d-%d, min p %d, max p %d, copies %d, hinst %p\n"
2046 "flags %08x (%s)\n",
2047 lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
2048 lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
2049 lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
2052 if(lppd->lStructSize != sizeof(PRINTDLGA)) {
2053 WARN("structure size failure !!!\n");
2054 COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
2058 if(lppd->Flags & PD_RETURNDEFAULT) {
2059 PRINTER_INFO_2A *pbuf;
2060 DRIVER_INFO_3A *dbuf;
2064 if(lppd->hDevMode || lppd->hDevNames) {
2065 WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
2066 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
2069 if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
2070 WARN("Can't find default printer\n");
2071 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
2075 GetPrinterA(hprn, 2, NULL, 0, &needed);
2076 pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
2077 GetPrinterA(hprn, 2, (LPBYTE)pbuf, needed, &needed);
2079 GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
2080 dbuf = HeapAlloc(GetProcessHeap(),0,needed);
2081 if (!GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed)) {
2082 ERR("GetPrinterDriverA failed, le %d, fix your config for printer %s!\n",
2083 GetLastError(),pbuf->pPrinterName);
2084 HeapFree(GetProcessHeap(), 0, dbuf);
2085 HeapFree(GetProcessHeap(), 0, pbuf);
2086 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
2091 PRINTDLG_CreateDevNames(&(lppd->hDevNames),
2095 lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
2096 pbuf->pDevMode->dmDriverExtra);
2097 ptr = GlobalLock(lppd->hDevMode);
2098 memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
2099 pbuf->pDevMode->dmDriverExtra);
2100 GlobalUnlock(lppd->hDevMode);
2101 HeapFree(GetProcessHeap(), 0, pbuf);
2102 HeapFree(GetProcessHeap(), 0, dbuf);
2106 PRINT_PTRA *PrintStructures;
2108 /* load Dialog resources,
2109 * depending on Flags indicates Print32 or Print32_setup dialog
2111 hDlgTmpl = PRINTDLG_GetDlgTemplateA(lppd);
2113 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2116 ptr = LockResource( hDlgTmpl );
2118 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2122 PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2123 sizeof(PRINT_PTRA));
2124 PrintStructures->lpPrintDlg = lppd;
2126 /* and create & process the dialog .
2127 * -1 is failure, 0 is broken hwnd, everything else is ok.
2129 bRet = (0<DialogBoxIndirectParamA(hInst, ptr, lppd->hwndOwner,
2131 (LPARAM)PrintStructures));
2134 DEVMODEA *lpdm = PrintStructures->lpDevMode, *lpdmReturn;
2135 PRINTER_INFO_2A *pi = PrintStructures->lpPrinterInfo;
2136 DRIVER_INFO_3A *di = PrintStructures->lpDriverInfo;
2138 if (lppd->hDevMode == 0) {
2139 TRACE(" No hDevMode yet... Need to create my own\n");
2140 lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE,
2141 lpdm->dmSize + lpdm->dmDriverExtra);
2143 lppd->hDevMode = GlobalReAlloc(lppd->hDevMode,
2144 lpdm->dmSize + lpdm->dmDriverExtra,
2147 lpdmReturn = GlobalLock(lppd->hDevMode);
2148 memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra);
2150 PRINTDLG_CreateDevNames(&(lppd->hDevNames),
2155 GlobalUnlock(lppd->hDevMode);
2157 HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
2158 HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo);
2159 HeapFree(GetProcessHeap(), 0, PrintStructures->lpDriverInfo);
2160 HeapFree(GetProcessHeap(), 0, PrintStructures);
2162 if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
2163 bRet = PRINTDLG_CreateDCA(lppd);
2165 TRACE("exit! (%d)\n", bRet);
2169 /***********************************************************************
2170 * PrintDlgW (COMDLG32.@)
2174 BOOL WINAPI PrintDlgW(LPPRINTDLGW lppd)
2182 COMDLG32_SetCommDlgExtendedError(CDERR_INITIALIZATION);
2186 hInst = (HINSTANCE)GetWindowLongPtrW( lppd->hwndOwner, GWLP_HINSTANCE );
2187 if(TRACE_ON(commdlg)) {
2188 char flagstr[1000] = "";
2189 const struct pd_flags *pflag = pd_flags;
2190 for( ; pflag->name; pflag++) {
2191 if(lppd->Flags & pflag->flag)
2192 strcat(flagstr, pflag->name);
2194 TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
2195 "pp. %d-%d, min p %d, max p %d, copies %d, hinst %p\n"
2196 "flags %08x (%s)\n",
2197 lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
2198 lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
2199 lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
2202 if(lppd->lStructSize != sizeof(PRINTDLGW)) {
2203 WARN("structure size failure !!!\n");
2204 COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
2208 if(lppd->Flags & PD_RETURNDEFAULT) {
2209 PRINTER_INFO_2W *pbuf;
2210 DRIVER_INFO_3W *dbuf;
2214 if(lppd->hDevMode || lppd->hDevNames) {
2215 WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
2216 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
2219 if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
2220 WARN("Can't find default printer\n");
2221 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
2225 GetPrinterW(hprn, 2, NULL, 0, &needed);
2226 pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
2227 GetPrinterW(hprn, 2, (LPBYTE)pbuf, needed, &needed);
2229 GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
2230 dbuf = HeapAlloc(GetProcessHeap(),0,needed);
2231 if (!GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed)) {
2232 ERR("GetPrinterDriverA failed, le %d, fix your config for printer %s!\n",
2233 GetLastError(),debugstr_w(pbuf->pPrinterName));
2234 HeapFree(GetProcessHeap(), 0, dbuf);
2235 HeapFree(GetProcessHeap(), 0, pbuf);
2236 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
2241 PRINTDLG_CreateDevNamesW(&(lppd->hDevNames),
2245 lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
2246 pbuf->pDevMode->dmDriverExtra);
2247 ptr = GlobalLock(lppd->hDevMode);
2248 memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
2249 pbuf->pDevMode->dmDriverExtra);
2250 GlobalUnlock(lppd->hDevMode);
2251 HeapFree(GetProcessHeap(), 0, pbuf);
2252 HeapFree(GetProcessHeap(), 0, dbuf);
2256 PRINT_PTRW *PrintStructures;
2258 /* load Dialog resources,
2259 * depending on Flags indicates Print32 or Print32_setup dialog
2261 hDlgTmpl = PRINTDLG_GetDlgTemplateW(lppd);
2263 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2266 ptr = LockResource( hDlgTmpl );
2268 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2272 PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2273 sizeof(PRINT_PTRW));
2274 PrintStructures->lpPrintDlg = lppd;
2276 /* and create & process the dialog .
2277 * -1 is failure, 0 is broken hwnd, everything else is ok.
2279 bRet = (0<DialogBoxIndirectParamW(hInst, ptr, lppd->hwndOwner,
2281 (LPARAM)PrintStructures));
2284 DEVMODEW *lpdm = PrintStructures->lpDevMode, *lpdmReturn;
2285 PRINTER_INFO_2W *pi = PrintStructures->lpPrinterInfo;
2286 DRIVER_INFO_3W *di = PrintStructures->lpDriverInfo;
2288 if (lppd->hDevMode == 0) {
2289 TRACE(" No hDevMode yet... Need to create my own\n");
2290 lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE,
2291 lpdm->dmSize + lpdm->dmDriverExtra);
2294 if((locks = (GlobalFlags(lppd->hDevMode) & GMEM_LOCKCOUNT))) {
2295 WARN("hDevMode has %d locks on it. Unlocking it now\n", locks);
2297 GlobalUnlock(lppd->hDevMode);
2298 TRACE("Now got %d locks\n", locks);
2301 lppd->hDevMode = GlobalReAlloc(lppd->hDevMode,
2302 lpdm->dmSize + lpdm->dmDriverExtra,
2305 lpdmReturn = GlobalLock(lppd->hDevMode);
2306 memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra);
2308 if (lppd->hDevNames != 0) {
2310 if((locks = (GlobalFlags(lppd->hDevNames) & GMEM_LOCKCOUNT))) {
2311 WARN("hDevNames has %d locks on it. Unlocking it now\n", locks);
2313 GlobalUnlock(lppd->hDevNames);
2316 PRINTDLG_CreateDevNamesW(&(lppd->hDevNames),
2321 GlobalUnlock(lppd->hDevMode);
2323 HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
2324 HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo);
2325 HeapFree(GetProcessHeap(), 0, PrintStructures->lpDriverInfo);
2326 HeapFree(GetProcessHeap(), 0, PrintStructures);
2328 if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
2329 bRet = PRINTDLG_CreateDCW(lppd);
2331 TRACE("exit! (%d)\n", bRet);
2335 /***********************************************************************
2340 * cmb1 - printer select (not in standard dialog template)
2342 * cmb3 - source (tray?)
2343 * edt4 - border left
2345 * edt6 - border right
2346 * edt7 - border bottom
2347 * psh3 - "Printer..."
2351 LPPAGESETUPDLGA dlga; /* Handler to user defined struct */
2352 HWND hDlg; /* Page Setup dialog handler */
2353 RECT rtDrawRect; /* Drawing rect for page */
2357 LPPAGESETUPDLGW dlgw;
2359 PAGESETUPDLGW curdlg; /* Current dialog state */
2363 static HGLOBAL PRINTDLG_GetPGSTemplateA(const PAGESETUPDLGA *lppd)
2368 if(lppd->Flags & PSD_ENABLEPAGESETUPTEMPLATEHANDLE) {
2369 hDlgTmpl = lppd->hPageSetupTemplate;
2370 } else if(lppd->Flags & PSD_ENABLEPAGESETUPTEMPLATE) {
2371 hResInfo = FindResourceA(lppd->hInstance,
2372 lppd->lpPageSetupTemplateName, (LPSTR)RT_DIALOG);
2373 hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
2375 hResInfo = FindResourceA(COMDLG32_hInstance,(LPCSTR)PAGESETUPDLGORD,(LPSTR)RT_DIALOG);
2376 hDlgTmpl = LoadResource(COMDLG32_hInstance,hResInfo);
2381 static HGLOBAL PRINTDLG_GetPGSTemplateW(const PAGESETUPDLGW *lppd)
2386 if(lppd->Flags & PSD_ENABLEPAGESETUPTEMPLATEHANDLE) {
2387 hDlgTmpl = lppd->hPageSetupTemplate;
2388 } else if(lppd->Flags & PSD_ENABLEPAGESETUPTEMPLATE) {
2389 hResInfo = FindResourceW(lppd->hInstance,
2390 lppd->lpPageSetupTemplateName, (LPWSTR)RT_DIALOG);
2391 hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
2393 hResInfo = FindResourceW(COMDLG32_hInstance,(LPCWSTR)PAGESETUPDLGORD,(LPWSTR)RT_DIALOG);
2394 hDlgTmpl = LoadResource(COMDLG32_hInstance,hResInfo);
2399 static inline BOOL is_metric(const PageSetupDataA *pda)
2401 return pda->dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS;
2405 _c_10mm2size(PAGESETUPDLGA *dlga,DWORD size) {
2406 if (dlga->Flags & PSD_INTHOUSANDTHSOFINCHES)
2407 return 10*size*100/254;
2413 _c_inch2size(PAGESETUPDLGA *dlga,DWORD size) {
2414 if (dlga->Flags & PSD_INTHOUSANDTHSOFINCHES)
2417 return (size*254)/100;
2420 static WCHAR get_decimal_sep(void)
2426 WCHAR buf[2] = {'.',0};
2427 GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, buf, sizeof(buf) / sizeof(buf[0]));
2433 static void size2str(const PageSetupDataA *pda, DWORD size, LPWSTR strout)
2435 WCHAR integer_fmt[] = {'%','d',0};
2436 WCHAR hundredths_fmt[] = {'%','d','%','c','%','0','2','d',0};
2437 WCHAR thousandths_fmt[] = {'%','d','%','c','%','0','3','d',0};
2439 /* FIXME use LOCALE_SDECIMAL when the edit parsing code can cope */
2444 wsprintfW(strout, hundredths_fmt, size / 100, get_decimal_sep(), size % 100);
2446 wsprintfW(strout, integer_fmt, size / 100);
2451 wsprintfW(strout, thousandths_fmt, size / 1000, get_decimal_sep(), size % 1000);
2453 wsprintfW(strout, integer_fmt, size / 1000);
2459 _c_size2strW(PageSetupDataW *pdw,DWORD size,LPWSTR strout) {
2460 static const char mm_fmt[] = "%.2f mm";
2461 static const char in_fmt[] = "%.2f in";
2463 if (pdw->dlgw->Flags & PSD_INHUNDREDTHSOFMILLIMETERS) {
2464 sprintf(buf, mm_fmt, (size * 1.0) / 100.0);
2465 } else if (pdw->dlgw->Flags & PSD_INTHOUSANDTHSOFINCHES) {
2466 sprintf(buf, in_fmt, (size * 1.0) / 1000.0);
2468 pdw->dlgw->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
2469 sprintf(buf, mm_fmt, (size * 1.0) / 100.0);
2472 MultiByteToWideChar(CP_ACP, 0, buf, -1, strout, 20);
2476 _c_str2sizeA(const PAGESETUPDLGA *dlga, LPCSTR strin) {
2481 if (!sscanf(strin,"%f%s",&val,rest))
2484 if (!strcmp(rest,"in") || !strcmp(rest,"inch")) {
2485 if (dlga->Flags & PSD_INTHOUSANDTHSOFINCHES)
2488 return val*25.4*100;
2490 if (!strcmp(rest,"cm")) { rest[0]='m'; val = val*10.0; }
2491 if (!strcmp(rest,"m")) { strcpy(rest,"mm"); val = val*1000.0; }
2493 if (!strcmp(rest,"mm")) {
2494 if (dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS)
2497 return 1000.0*val/25.4;
2499 if (rest[0]=='\0') {
2500 /* use application supplied default */
2501 if (dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS) {
2505 if (dlga->Flags & PSD_INTHOUSANDTHSOFINCHES) {
2510 ERR("Did not find a conversion for type '%s'!\n",rest);
2516 _c_str2sizeW(const PAGESETUPDLGW *dlga, LPCWSTR strin) {
2519 /* this W -> A transition is OK */
2520 /* we need a unicode version of sscanf to avoid it */
2521 WideCharToMultiByte(CP_ACP, 0, strin, -1, buf, sizeof(buf), NULL, NULL);
2522 return _c_str2sizeA((const PAGESETUPDLGA *)dlga, buf);
2525 static inline BOOL is_default_metric(void)
2528 GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_IMEASURE | LOCALE_RETURN_NUMBER,
2529 (LPWSTR)&system, sizeof(system));
2533 /**********************************************
2535 * Cyclically permute the four members of rc
2536 * If sense is TRUE l -> t -> r -> b
2537 * otherwise l <- t <- r <- b
2539 static inline void rotate_rect(RECT *rc, BOOL sense)
2545 rc->bottom = rc->right;
2546 rc->right = rc->top;
2554 rc->top = rc->right;
2555 rc->right = rc->bottom;
2560 static void pagesetup_set_orientation(PageSetupDataA *pda, WORD orient)
2562 DEVMODEA *dm = GlobalLock(pda->dlga->hDevMode);
2564 assert(orient == DMORIENT_PORTRAIT || orient == DMORIENT_LANDSCAPE);
2566 dm->u1.s1.dmOrientation = orient;
2567 GlobalUnlock(pda->dlga->hDevMode);
2570 static WORD pagesetup_get_orientation(const PageSetupDataA *pda)
2572 DEVMODEA *dm = GlobalLock(pda->dlga->hDevMode);
2573 WORD orient = dm->u1.s1.dmOrientation;
2574 GlobalUnlock(pda->dlga->hDevMode);
2578 static void pagesetup_set_papersize(PageSetupDataA *pda, WORD paper)
2580 DEVMODEA *dm = GlobalLock(pda->dlga->hDevMode);
2581 dm->u1.s1.dmPaperSize = paper;
2582 GlobalUnlock(pda->dlga->hDevMode);
2585 static WORD pagesetup_get_papersize(const PageSetupDataA *pda)
2587 DEVMODEA *dm = GlobalLock(pda->dlga->hDevMode);
2588 WORD paper = dm->u1.s1.dmPaperSize;
2589 GlobalUnlock(pda->dlga->hDevMode);
2593 static void pagesetup_set_defaultsource(PageSetupDataA *pda, WORD source)
2595 DEVMODEA *dm = GlobalLock(pda->dlga->hDevMode);
2596 dm->u1.s1.dmDefaultSource = source;
2597 GlobalUnlock(pda->dlga->hDevMode);
2600 static WCHAR *pagesetup_get_devname(const PageSetupDataA *pda)
2606 dn = GlobalLock(pda->dlga->hDevNames);
2607 len = MultiByteToWideChar(CP_ACP, 0, (char*)dn + dn->wDeviceOffset, -1, NULL, 0);
2608 name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2609 MultiByteToWideChar(CP_ACP, 0, (char*)dn + dn->wDeviceOffset, -1, name, len);
2610 GlobalUnlock(pda->dlga->hDevNames);
2614 static BOOL pagesetup_update_papersize(PageSetupDataA *pda)
2618 LPSTR devname, portname;
2620 WORD *words = NULL, paperword;
2621 POINT *points = NULL;
2622 BOOL retval = FALSE;
2624 dn = GlobalLock(pda->dlga->hDevNames);
2625 dm = GlobalLock(pda->dlga->hDevMode);
2626 devname = ((char*)dn)+dn->wDeviceOffset;
2627 portname = ((char*)dn)+dn->wOutputOffset;
2629 num = DeviceCapabilitiesA(devname, portname, DC_PAPERS, NULL, dm);
2632 FIXME("No papernames found for %s/%s\n", devname, portname);
2636 words = HeapAlloc(GetProcessHeap(), 0, num * sizeof(WORD));
2637 points = HeapAlloc(GetProcessHeap(), 0, num * sizeof(POINT));
2639 if (num != DeviceCapabilitiesA(devname, portname, DC_PAPERS, (LPSTR)words, dm))
2641 FIXME("Number of returned words is not %d\n", num);
2645 if (num != DeviceCapabilitiesA(devname, portname, DC_PAPERSIZE, (LPSTR)points, dm))
2647 FIXME("Number of returned sizes is not %d\n",num);
2651 paperword = pagesetup_get_papersize(pda);
2653 for (i = 0; i < num; i++)
2654 if (words[i] == paperword)
2659 FIXME("Papersize %d not found in list?\n", paperword);
2663 /* this is _10ths_ of a millimeter */
2664 pda->dlga->ptPaperSize.x = _c_10mm2size(pda->dlga, points[i].x);
2665 pda->dlga->ptPaperSize.y = _c_10mm2size(pda->dlga, points[i].y);
2667 if(pagesetup_get_orientation(pda) == DMORIENT_LANDSCAPE)
2669 LONG tmp = pda->dlga->ptPaperSize.x;
2670 pda->dlga->ptPaperSize.x = pda->dlga->ptPaperSize.y;
2671 pda->dlga->ptPaperSize.y = tmp;
2676 HeapFree(GetProcessHeap(), 0, words);
2677 HeapFree(GetProcessHeap(), 0, points);
2678 GlobalUnlock(pda->dlga->hDevNames);
2679 GlobalUnlock(pda->dlga->hDevMode);
2684 PRINTDLG_PS_UpdateDlgStructW(HWND hDlg, PageSetupDataW *pdw) {
2687 LPWSTR devname,portname;
2688 WCHAR papername[64];
2691 dn = GlobalLock(pdw->pdlg.hDevNames);
2692 dm = GlobalLock(pdw->pdlg.hDevMode);
2693 devname = ((WCHAR*)dn)+dn->wDeviceOffset;
2694 portname = ((WCHAR*)dn)+dn->wOutputOffset;
2696 /* Save paper size into device context */
2697 PRINTDLG_SetUpPaperComboBoxW(hDlg,cmb2,devname,portname,dm);
2698 /* Save paper source into device context */
2699 PRINTDLG_SetUpPaperComboBoxW(hDlg,cmb3,devname,portname,dm);
2701 if (GetDlgItemTextW(hDlg,cmb2,papername,sizeof(papername)/sizeof(papername[0]))>0) {
2702 PRINTDLG_PaperSizeW(&(pdw->pdlg),papername,&(pdw->dlgw->ptPaperSize));
2703 pdw->dlgw->ptPaperSize.x = _c_10mm2size((LPPAGESETUPDLGA)pdw->dlgw,pdw->dlgw->ptPaperSize.x);
2704 pdw->dlgw->ptPaperSize.y = _c_10mm2size((LPPAGESETUPDLGA)pdw->dlgw,pdw->dlgw->ptPaperSize.y);
2706 FIXME("could not get dialog text for papersize cmbbox?\n");
2707 #define GETVAL(id,val) if (GetDlgItemTextW(hDlg,id,buf,sizeof(buf)/sizeof(buf[0]))>0) { val = _c_str2sizeW(pdw->dlgw,buf); } else { FIXME("could not get dlgitemtextw for %x\n",id); }
2708 GETVAL(edt4,pdw->dlgw->rtMargin.left);
2709 GETVAL(edt5,pdw->dlgw->rtMargin.top);
2710 GETVAL(edt6,pdw->dlgw->rtMargin.right);
2711 GETVAL(edt7,pdw->dlgw->rtMargin.bottom);
2714 /* If we are in landscape, swap x and y of page size */
2715 if (IsDlgButtonChecked(hDlg, rad2)) {
2717 tmp = pdw->dlgw->ptPaperSize.x;
2718 pdw->dlgw->ptPaperSize.x = pdw->dlgw->ptPaperSize.y;
2719 pdw->dlgw->ptPaperSize.y = tmp;
2722 /* Save orientation */
2723 if (pdw->dlgw->ptPaperSize.x > pdw->dlgw->ptPaperSize.y)
2724 dm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
2726 dm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
2728 GlobalUnlock(pdw->pdlg.hDevNames);
2729 GlobalUnlock(pdw->pdlg.hDevMode);
2733 /**********************************************************************************************
2734 * PRINTDLG_PS_ChangeActivePrinerA
2736 * Redefines hDevMode and hDevNames HANDLES and initialises it.
2739 * name [in] Name of a printer for activation
2740 * pda [in/out] ptr to PageSetupDataA structure
2747 PRINTDLG_PS_ChangeActivePrinterA(LPSTR name, PageSetupDataA *pda){
2750 LPPRINTER_INFO_2A lpPrinterInfo;
2751 LPDRIVER_INFO_3A lpDriverInfo;
2752 DEVMODEA *pDevMode, *dm;
2754 if(!OpenPrinterA(name, &hprn, NULL)){
2755 ERR("Can't open printer %s\n", name);
2758 GetPrinterA(hprn, 2, NULL, 0, &needed);
2759 lpPrinterInfo = HeapAlloc(GetProcessHeap(), 0, needed);
2760 GetPrinterA(hprn, 2, (LPBYTE)lpPrinterInfo, needed, &needed);
2761 GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
2762 lpDriverInfo = HeapAlloc(GetProcessHeap(), 0, needed);
2763 if(!GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)lpDriverInfo, needed, &needed)) {
2764 ERR("GetPrinterDriverA failed for %s, fix your config!\n", lpPrinterInfo->pPrinterName);
2765 HeapFree(GetProcessHeap(), 0, lpDriverInfo);
2766 HeapFree(GetProcessHeap(), 0, lpPrinterInfo);
2771 needed = DocumentPropertiesA(0, 0, name, NULL, NULL, 0);
2773 ERR("DocumentProperties fails on %s\n", debugstr_a(name));
2774 HeapFree(GetProcessHeap(), 0, lpDriverInfo);
2775 HeapFree(GetProcessHeap(), 0, lpPrinterInfo);
2778 pDevMode = HeapAlloc(GetProcessHeap(), 0, needed);
2779 DocumentPropertiesA(0, 0, name, pDevMode, NULL, DM_OUT_BUFFER);
2781 pda->dlga->hDevMode = GlobalReAlloc(pda->dlga->hDevMode,
2782 pDevMode->dmSize + pDevMode->dmDriverExtra,
2784 dm = GlobalLock(pda->dlga->hDevMode);
2785 memcpy(dm, pDevMode, pDevMode->dmSize + pDevMode->dmDriverExtra);
2787 PRINTDLG_CreateDevNames(&(pda->dlga->hDevNames),
2788 lpDriverInfo->pDriverPath,
2789 lpPrinterInfo->pPrinterName,
2790 lpPrinterInfo->pPortName);
2792 GlobalUnlock(pda->dlga->hDevMode);
2793 HeapFree(GetProcessHeap(), 0, pDevMode);
2794 HeapFree(GetProcessHeap(), 0, lpPrinterInfo);
2795 HeapFree(GetProcessHeap(), 0, lpDriverInfo);
2799 /****************************************************************************************
2800 * pagesetup_init_combos
2802 * Fills Printers, Paper and Source combos
2805 static void pagesetup_init_combos(HWND hDlg, PageSetupDataA *pda)
2809 LPSTR devname,portname;
2812 dn = GlobalLock(pda->dlga->hDevNames);
2813 dm = GlobalLock(pda->dlga->hDevMode);
2814 devnameW = pagesetup_get_devname(pda);
2815 devname = ((char*)dn)+dn->wDeviceOffset;
2816 portname = ((char*)dn)+dn->wOutputOffset;
2817 PRINTDLG_SetUpPrinterListComboW(hDlg, cmb1, devnameW);
2818 PRINTDLG_SetUpPaperComboBoxA(hDlg,cmb2,devname,portname,dm);
2819 PRINTDLG_SetUpPaperComboBoxA(hDlg,cmb3,devname,portname,dm);
2820 HeapFree(GetProcessHeap(), 0, devnameW);
2821 GlobalUnlock(pda->dlga->hDevNames);
2822 GlobalUnlock(pda->dlga->hDevMode);
2825 static void PRINTDLG_PS_SetOrientationW(HWND hDlg, PageSetupDataW* pdw)
2827 WCHAR PaperName[64];
2829 GetDlgItemTextW(hDlg, cmb2, PaperName, sizeof(PaperName)/sizeof(WCHAR));
2830 PRINTDLG_PaperSizeW(&pdw->pdlg, PaperName, &pdw->curdlg.ptPaperSize);
2831 pdw->curdlg.ptPaperSize.x = _c_10mm2size((LPPAGESETUPDLGA)pdw->dlgw, pdw->curdlg.ptPaperSize.x);
2832 pdw->curdlg.ptPaperSize.y = _c_10mm2size((LPPAGESETUPDLGA)pdw->dlgw, pdw->curdlg.ptPaperSize.y);
2834 if(IsDlgButtonChecked(hDlg, rad2))
2836 DWORD tmp = pdw->curdlg.ptPaperSize.x;
2837 pdw->curdlg.ptPaperSize.x = pdw->curdlg.ptPaperSize.y;
2838 pdw->curdlg.ptPaperSize.y = tmp;
2842 static void PRINTDLG_PS_UpdatePrintDlgW(PageSetupDataW* pdw, HWND hDlg)
2847 dm = GlobalLock(pdw->pdlg.hDevMode);
2852 if(pdw->curdlg.ptPaperSize.y > pdw->curdlg.ptPaperSize.x)
2853 dm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
2855 dm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
2857 sel = SendDlgItemMessageW(hDlg, cmb2, CB_GETCURSEL, 0, 0);
2860 dm->u1.s1.dmPaperSize = SendDlgItemMessageW(hDlg, cmb2, CB_GETITEMDATA, sel, 0);
2862 GlobalUnlock(pdw->pdlg.hDevMode);
2866 PRINTDLG_PS_ChangePrinterW(HWND hDlg, PageSetupDataW *pdw) {
2869 LPWSTR devname,portname;
2871 dn = GlobalLock(pdw->pdlg.hDevNames);
2872 dm = GlobalLock(pdw->pdlg.hDevMode);
2873 devname = ((WCHAR*)dn)+dn->wDeviceOffset;
2874 portname = ((WCHAR*)dn)+dn->wOutputOffset;
2875 PRINTDLG_SetUpPaperComboBoxW(hDlg,cmb2,devname,portname,dm);
2876 PRINTDLG_SetUpPaperComboBoxW(hDlg,cmb3,devname,portname,dm);
2878 /* Landscape orientation */
2879 if (dm->u1.s1.dmOrientation == DMORIENT_LANDSCAPE)
2880 CheckRadioButton(hDlg, rad1, rad2, rad2);
2881 else /* this is default if papersize is not set */
2882 CheckRadioButton(hDlg, rad1, rad2, rad1);
2884 GlobalUnlock(pdw->pdlg.hDevNames);
2885 GlobalUnlock(pdw->pdlg.hDevMode);
2887 PRINTDLG_PS_SetOrientationW(hDlg, pdw);
2892 /******************************************************************************************
2893 * PRINTDLG_PS_ChangePaperPrev
2895 * Changes paper preview size / position
2898 * pda [i] Pointer for current PageSetupDataA structure
2904 PRINTDLG_PS_ChangePaperPrev(const PageSetupDataA *pda)
2906 LONG width, height, x, y;
2909 if(pda->dlga->ptPaperSize.x > pda->dlga->ptPaperSize.y) {
2910 width = pda->rtDrawRect.right - pda->rtDrawRect.left;
2911 height = pda->dlga->ptPaperSize.y * width / pda->dlga->ptPaperSize.x;
2913 height = pda->rtDrawRect.bottom - pda->rtDrawRect.top;
2914 width = pda->dlga->ptPaperSize.x * height / pda->dlga->ptPaperSize.y;
2916 x = (pda->rtDrawRect.right + pda->rtDrawRect.left - width) / 2;
2917 y = (pda->rtDrawRect.bottom + pda->rtDrawRect.top - height) / 2;
2918 TRACE("rtDrawRect(%d, %d, %d, %d) x=%d, y=%d, w=%d, h=%d\n",
2919 pda->rtDrawRect.left, pda->rtDrawRect.top, pda->rtDrawRect.right, pda->rtDrawRect.bottom,
2920 x, y, width, height);
2923 MoveWindow(GetDlgItem(pda->hDlg, rct2), x+width, y+SHADOW, SHADOW, height, FALSE);
2924 MoveWindow(GetDlgItem(pda->hDlg, rct3), x+SHADOW, y+height, width, SHADOW, FALSE);
2925 MoveWindow(GetDlgItem(pda->hDlg, rct1), x, y, width, height, FALSE);
2926 rtTmp = pda->rtDrawRect;
2927 rtTmp.right += SHADOW;
2928 rtTmp.bottom += SHADOW;
2931 InvalidateRect(pda->hDlg, &rtTmp, TRUE);
2935 static inline LONG *element_from_margin_id(RECT *rc, WORD id)
2939 case edt4: return &rc->left;
2940 case edt5: return &rc->top;
2941 case edt6: return &rc->right;
2942 case edt7: return &rc->bottom;
2947 static void update_margin_edits(HWND hDlg, const PageSetupDataA *pda, WORD id)
2952 for(idx = edt4; idx <= edt7; idx++)
2954 if(id == 0 || id == idx)
2956 size2str(pda, *element_from_margin_id(&pda->dlga->rtMargin, idx), str);
2957 SetDlgItemTextW(hDlg, idx, str);
2962 static void margin_edit_notification(HWND hDlg, PageSetupDataA *pda, WORD msg, WORD id)
2970 LONG *value = element_from_margin_id(&pda->dlga->rtMargin, id);
2972 if (GetDlgItemTextW(hDlg, id, buf, sizeof(buf) / sizeof(buf[0])) != 0)
2975 WCHAR decimal = get_decimal_sep();
2977 val = strtolW(buf, &end, 10);
2978 if(end != buf || *end == decimal)
2980 int mult = is_metric(pda) ? 100 : 1000;
2989 val += (*end - '0') * mult;
3001 update_margin_edits(hDlg, pda, id);
3006 static void set_margin_groupbox_title(HWND hDlg, const PageSetupDataA *pda)
3010 if(LoadStringW(COMDLG32_hInstance, is_metric(pda) ? PD32_MARGINS_IN_MILLIMETERS : PD32_MARGINS_IN_INCHES,
3011 title, sizeof(title)/sizeof(title[0])))
3012 SetDlgItemTextW(hDlg, grp4, title);
3015 static void pagesetup_update_orientation_buttons(HWND hDlg, const PageSetupDataA *pda)
3017 if (pagesetup_get_orientation(pda) == DMORIENT_LANDSCAPE)
3018 CheckRadioButton(hDlg, rad1, rad2, rad2);
3020 CheckRadioButton(hDlg, rad1, rad2, rad1);
3023 /********************************************************************************
3024 * PRINTDLG_PS_WMCommandA
3025 * process WM_COMMAND message for PageSetupDlgA
3028 * hDlg [in] Main dialog HANDLE
3029 * wParam [in] WM_COMMAND wParam
3030 * lParam [in] WM_COMMAND lParam
3031 * pda [in/out] ptr to PageSetupDataA
3035 PRINTDLG_PS_WMCommandA(
3036 HWND hDlg, WPARAM wParam, LPARAM lParam, PageSetupDataA *pda
3038 WORD msg = HIWORD(wParam);
3039 WORD id = LOWORD(wParam);
3041 TRACE("loword (lparam) %d, wparam 0x%lx, lparam %08lx\n",
3042 LOWORD(lParam),wParam,lParam);
3045 EndDialog(hDlg, TRUE);
3049 EndDialog(hDlg, FALSE);
3055 memset(&prnt, 0, sizeof(prnt));
3056 prnt.lStructSize = sizeof(prnt);
3058 prnt.hwndOwner = hDlg;
3059 prnt.hDevNames = pda->dlga->hDevNames;
3060 prnt.hDevMode = pda->dlga->hDevMode;
3061 if (PrintDlgA(&prnt))
3063 pda->dlga->hDevNames = prnt.hDevNames;
3064 pda->dlga->hDevMode = prnt.hDevMode;
3065 pagesetup_init_combos(hDlg, pda);
3071 if((id == rad1 && pagesetup_get_orientation(pda) == DMORIENT_LANDSCAPE) ||
3072 (id == rad2 && pagesetup_get_orientation(pda) == DMORIENT_PORTRAIT))
3074 pagesetup_set_orientation(pda, (id == rad1) ? DMORIENT_PORTRAIT : DMORIENT_LANDSCAPE);
3075 pagesetup_update_papersize(pda);
3076 rotate_rect(&pda->dlga->rtMargin, (id == rad2));
3077 update_margin_edits(hDlg, pda, 0);
3078 PRINTDLG_PS_ChangePaperPrev(pda);
3081 case cmb1: /* Printer combo */
3082 if(msg == CBN_SELCHANGE){
3083 char crPrinterName[256];
3084 GetDlgItemTextA(hDlg, id, crPrinterName, 255);
3085 PRINTDLG_PS_ChangeActivePrinterA(crPrinterName, pda);
3086 pagesetup_init_combos(hDlg, pda);
3089 case cmb2: /* Paper combo */
3090 if(msg == CBN_SELCHANGE){
3091 DWORD paperword = SendDlgItemMessageA(hDlg,cmb2,CB_GETITEMDATA,
3092 SendDlgItemMessageA(hDlg, cmb2, CB_GETCURSEL, 0, 0), 0);
3093 if (paperword != CB_ERR)
3095 pagesetup_set_papersize(pda, paperword);
3096 pagesetup_update_papersize(pda);
3097 PRINTDLG_PS_ChangePaperPrev(pda);
3099 FIXME("could not get dialog text for papersize cmbbox?\n");
3102 case cmb3: /* Paper Source */
3103 if(msg == CBN_SELCHANGE)
3105 WORD source = SendDlgItemMessageA(hDlg, cmb3, CB_GETITEMDATA,
3106 SendDlgItemMessageA(hDlg, cmb3, CB_GETCURSEL, 0, 0), 0);
3107 pagesetup_set_defaultsource(pda, source);
3110 case psh2: /* Printer Properties button */
3113 char PrinterName[256];
3118 GetDlgItemTextA(hDlg, cmb1, PrinterName, 255);
3119 if (!OpenPrinterA(PrinterName, &hPrinter, NULL)) {
3120 FIXME("Call to OpenPrinter did not succeed!\n");
3123 dm = GlobalLock(pda->dlga->hDevMode);
3124 DocumentPropertiesA(hDlg, hPrinter, PrinterName, dm, dm,
3125 DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
3126 ClosePrinter(hPrinter);
3127 /* Changing paper */
3128 pagesetup_update_papersize(pda);
3129 pagesetup_update_orientation_buttons(hDlg, pda);
3131 /* Changing paper preview */
3132 PRINTDLG_PS_ChangePaperPrev(pda);
3133 /* Selecting paper in combo */
3134 count = SendDlgItemMessageA(hDlg, cmb2, CB_GETCOUNT, 0, 0);
3135 if(count != CB_ERR) {
3136 WORD paperword = pagesetup_get_papersize(pda);
3137 for(i=0; i<count; ++i){
3138 if(SendDlgItemMessageA(hDlg, cmb2, CB_GETITEMDATA, i, 0) == paperword) {
3139 SendDlgItemMessageA(hDlg, cmb2, CB_SETCURSEL, i, 0);
3145 GlobalUnlock(pda->dlga->hDevMode);
3152 margin_edit_notification(hDlg, pda, msg, id);
3155 InvalidateRect(GetDlgItem(hDlg, rct1), NULL, TRUE);
3160 PRINTDLG_PS_WMCommandW(
3161 HWND hDlg, WPARAM wParam, LPARAM lParam, PageSetupDataW *pdw
3163 TRACE("loword (lparam) %d, wparam 0x%lx, lparam %08lx\n",
3164 LOWORD(lParam),wParam,lParam);
3165 switch (LOWORD(wParam)) {
3167 if (!PRINTDLG_PS_UpdateDlgStructW(hDlg, pdw))
3169 EndDialog(hDlg, TRUE);
3173 EndDialog(hDlg, FALSE);
3178 if((LOWORD(wParam) == rad1 && pdw->curdlg.ptPaperSize.x > pdw->curdlg.ptPaperSize.y) ||
3179 (LOWORD(wParam) == rad2 && pdw->curdlg.ptPaperSize.y > pdw->curdlg.ptPaperSize.x))
3183 DWORD tmp = pdw->curdlg.ptPaperSize.y;
3185 pdw->curdlg.ptPaperSize.y = pdw->curdlg.ptPaperSize.x;
3186 pdw->curdlg.ptPaperSize.x = tmp;
3188 GetDlgItemTextW(hDlg, edt4, tmpText, sizeof(tmpText)/sizeof(WCHAR));
3189 GetDlgItemTextW(hDlg, edt5, tmpText2, sizeof(tmpText2)/sizeof(WCHAR));
3190 SetDlgItemTextW(hDlg, edt5, tmpText);
3191 SetDlgItemTextW(hDlg, edt4, tmpText2);
3193 GetDlgItemTextW(hDlg, edt6, tmpText, sizeof(tmpText)/sizeof(WCHAR));
3194 GetDlgItemTextW(hDlg, edt7, tmpText2, sizeof(tmpText2)/sizeof(WCHAR));
3195 SetDlgItemTextW(hDlg, edt7, tmpText);
3196 SetDlgItemTextW(hDlg, edt6, tmpText2);
3201 pdw->pdlg.Flags = 0;
3202 pdw->pdlg.hwndOwner = hDlg;
3203 PRINTDLG_PS_UpdatePrintDlgW(pdw, hDlg);
3204 if (PrintDlgW(&(pdw->pdlg)))
3205 PRINTDLG_PS_ChangePrinterW(hDlg,pdw);
3213 /***********************************************************************
3214 * DefaultPagePaintHook
3215 * Default hook paint procedure that receives WM_PSD_* messages from the dialog box
3216 * whenever the sample page is redrawn.
3220 PRINTDLG_DefaultPagePaintHook(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam,
3221 const PageSetupDataA *pda)
3223 LPRECT lprc = (LPRECT) lParam;
3224 HDC hdc = (HDC) wParam;
3227 HFONT hfont, holdfont;
3229 TRACE("uMsg: WM_USER+%d\n",uMsg-WM_USER);
3230 /* Call user paint hook if enable */
3231 if (pda->dlga->Flags & PSD_ENABLEPAGEPAINTHOOK)
3232 if (pda->dlga->lpfnPagePaintHook(hwndDlg, uMsg, wParam, lParam))
3236 /* LPPAGESETUPDLG in lParam */
3237 case WM_PSD_PAGESETUPDLG:
3238 /* Inform about the sample page rectangle */
3239 case WM_PSD_FULLPAGERECT:
3240 /* Inform about the margin rectangle */
3241 case WM_PSD_MINMARGINRECT:
3244 /* Draw dashed rectangle showing margins */
3245 case WM_PSD_MARGINRECT:
3246 hpen = CreatePen(PS_DASH, 1, GetSysColor(COLOR_3DSHADOW));
3247 holdpen = SelectObject(hdc, hpen);
3248 Rectangle(hdc, lprc->left, lprc->top, lprc->right, lprc->bottom);
3249 DeleteObject(SelectObject(hdc, holdpen));
3251 /* Draw the fake document */
3252 case WM_PSD_GREEKTEXTRECT:
3253 /* select a nice scalable font, because we want the text really small */
3254 SystemParametersInfoW(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0);
3255 lf.lfHeight = 6; /* value chosen based on visual effect */
3256 hfont = CreateFontIndirectW(&lf);
3257 holdfont = SelectObject(hdc, hfont);
3259 /* if text not loaded, then do so now */
3260 if (wszFakeDocumentText[0] == '\0')
3261 LoadStringW(COMDLG32_hInstance,
3263 wszFakeDocumentText,
3264 sizeof(wszFakeDocumentText)/sizeof(wszFakeDocumentText[0]));
3266 oldbkmode = SetBkMode(hdc, TRANSPARENT);
3267 DrawTextW(hdc, wszFakeDocumentText, -1, lprc, DT_TOP|DT_LEFT|DT_NOPREFIX|DT_WORDBREAK);
3268 SetBkMode(hdc, oldbkmode);
3270 DeleteObject(SelectObject(hdc, holdfont));
3273 /* Envelope stamp */
3274 case WM_PSD_ENVSTAMPRECT:
3275 /* Return address */
3276 case WM_PSD_YAFULLPAGERECT:
3277 FIXME("envelope/stamp is not implemented\n");
3280 FIXME("Unknown message %x\n",uMsg);
3286 /***********************************************************************
3288 * The main paint procedure for the PageSetupDlg function.
3289 * The Page Setup dialog box includes an image of a sample page that shows how
3290 * the user's selections affect the appearance of the printed output.
3291 * The image consists of a rectangle that represents the selected paper
3292 * or envelope type, with a dotted-line rectangle representing
3293 * the current margins, and partial (Greek text) characters
3294 * to show how text looks on the printed page.
3296 * The following messages in the order sends to user hook procedure:
3297 * WM_PSD_PAGESETUPDLG Draw the contents of the sample page
3298 * WM_PSD_FULLPAGERECT Inform about the bounding rectangle
3299 * WM_PSD_MINMARGINRECT Inform about the margin rectangle (min margin?)
3300 * WM_PSD_MARGINRECT Draw the margin rectangle
3301 * WM_PSD_GREEKTEXTRECT Draw the Greek text inside the margin rectangle
3302 * If any of first three messages returns TRUE, painting done.
3305 * hWnd [in] Handle to the Page Setup dialog box
3306 * uMsg [in] Received message
3309 * WM_PSD_ENVSTAMPRECT Draw in the envelope-stamp rectangle (for envelopes only)
3310 * WM_PSD_YAFULLPAGERECT Draw the return address portion (for envelopes and other paper sizes)
3313 * FALSE if all done correctly
3318 static LRESULT CALLBACK
3319 PRINTDLG_PagePaintProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
3322 RECT rcClient, rcMargin;
3325 HBRUSH hbrush, holdbrush;
3326 PageSetupDataA *pda;
3327 int papersize=0, orientation=0; /* FIXME: set this values for user paint hook */
3328 double scalx, scaly;
3329 #define CALLPAINTHOOK(msg,lprc) PRINTDLG_DefaultPagePaintHook( hWnd, msg, (WPARAM)hdc, (LPARAM)lprc, pda)
3331 if (uMsg != WM_PAINT)
3332 return CallWindowProcA(lpfnStaticWndProc, hWnd, uMsg, wParam, lParam);
3334 /* Processing WM_PAINT message */
3335 pda = GetPropW(hWnd, pagesetupdlg_prop);
3337 WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
3340 if (PRINTDLG_DefaultPagePaintHook(hWnd, WM_PSD_PAGESETUPDLG, MAKELONG(papersize, orientation), (LPARAM)pda->dlga, pda))
3343 hdc = BeginPaint(hWnd, &ps);
3344 GetClientRect(hWnd, &rcClient);
3346 scalx = rcClient.right / (double)pda->dlga->ptPaperSize.x;
3347 scaly = rcClient.bottom / (double)pda->dlga->ptPaperSize.y;
3348 rcMargin = rcClient;
3350 rcMargin.left += pda->dlga->rtMargin.left * scalx;
3351 rcMargin.top += pda->dlga->rtMargin.top * scalx;
3352 rcMargin.right -= pda->dlga->rtMargin.right * scaly;
3353 rcMargin.bottom -= pda->dlga->rtMargin.bottom * scaly;
3355 /* if the space is too small then we make sure to not draw anything */
3356 rcMargin.left = min(rcMargin.left, rcMargin.right);
3357 rcMargin.top = min(rcMargin.top, rcMargin.bottom);
3359 if (!CALLPAINTHOOK(WM_PSD_FULLPAGERECT, &rcClient) &&
3360 !CALLPAINTHOOK(WM_PSD_MINMARGINRECT, &rcMargin) )
3362 /* fill background */
3363 hbrush = GetSysColorBrush(COLOR_3DHIGHLIGHT);
3364 FillRect(hdc, &rcClient, hbrush);
3365 holdbrush = SelectObject(hdc, hbrush);
3367 hpen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW));
3368 holdpen = SelectObject(hdc, hpen);
3370 /* paint left edge */
3371 MoveToEx(hdc, rcClient.left, rcClient.top, NULL);
3372 LineTo(hdc, rcClient.left, rcClient.bottom-1);
3374 /* paint top edge */
3375 MoveToEx(hdc, rcClient.left, rcClient.top, NULL);
3376 LineTo(hdc, rcClient.right, rcClient.top);
3378 hpen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DDKSHADOW));
3379 DeleteObject(SelectObject(hdc, hpen));
3381 /* paint right edge */
3382 MoveToEx(hdc, rcClient.right-1, rcClient.top, NULL);
3383 LineTo(hdc, rcClient.right-1, rcClient.bottom);
3385 /* paint bottom edge */
3386 MoveToEx(hdc, rcClient.left, rcClient.bottom-1, NULL);
3387 LineTo(hdc, rcClient.right, rcClient.bottom-1);
3389 DeleteObject(SelectObject(hdc, holdpen));
3390 DeleteObject(SelectObject(hdc, holdbrush));
3392 CALLPAINTHOOK(WM_PSD_MARGINRECT, &rcMargin);
3394 /* give text a bit of a space from the frame */
3397 rcMargin.right -= 2;
3398 rcMargin.bottom -= 2;
3400 /* if the space is too small then we make sure to not draw anything */
3401 rcMargin.left = min(rcMargin.left, rcMargin.right);
3402 rcMargin.top = min(rcMargin.top, rcMargin.bottom);
3404 CALLPAINTHOOK(WM_PSD_GREEKTEXTRECT, &rcMargin);
3407 EndPaint(hWnd, &ps);
3409 #undef CALLPAINTHOOK
3412 /*******************************************************
3413 * The margin edit controls are subclassed to filter
3414 * anything other than numbers and the decimal separator.
3416 static LRESULT CALLBACK pagesetup_margin_editproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
3421 WCHAR decimal = get_decimal_sep();
3422 WCHAR wc = (WCHAR)wparam;
3423 if(!isdigitW(wc) && wc != decimal && wc != VK_BACK) return 0;
3425 return CallWindowProcW(edit_wndproc, hwnd, msg, wparam, lparam);
3428 static void subclass_margin_edits(HWND hDlg)
3433 for(id = edt4; id <= edt7; id++)
3435 old_proc = (WNDPROC)SetWindowLongPtrW(GetDlgItem(hDlg, id),
3437 (ULONG_PTR)pagesetup_margin_editproc);
3438 InterlockedCompareExchangePointer((void**)&edit_wndproc, old_proc, NULL);
3442 /***********************************************************************
3443 * PRINTDLG_PageDlgProcA
3444 * Message handler for PageSetupDlgA
3446 static INT_PTR CALLBACK
3447 PRINTDLG_PageDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
3449 PageSetupDataA *pda;
3450 INT_PTR res = FALSE;
3453 if (uMsg == WM_INITDIALOG) { /*Init dialog*/
3454 pda = (PageSetupDataA*)lParam;
3455 pda->hDlg = hDlg; /* saving handle to main window to PageSetupDataA structure */
3457 hDrawWnd = GetDlgItem(hDlg, rct1);
3458 TRACE("set property to %p\n", pda);
3459 SetPropW(hDlg, pagesetupdlg_prop, pda);
3460 SetPropW(hDrawWnd, pagesetupdlg_prop, pda);
3461 GetWindowRect(hDrawWnd, &pda->rtDrawRect); /* Calculating rect in client coordinates where paper draws */
3462 ScreenToClient(hDlg, (LPPOINT)&pda->rtDrawRect);
3463 ScreenToClient(hDlg, (LPPOINT)(&pda->rtDrawRect.right));
3464 lpfnStaticWndProc = (WNDPROC)SetWindowLongPtrW(
3467 (ULONG_PTR)PRINTDLG_PagePaintProc);
3469 /* FIXME: Paint hook. Must it be at begin of initialization or at end? */
3471 if (pda->dlga->Flags & PSD_ENABLEPAGESETUPHOOK) {
3472 if (!pda->dlga->lpfnPageSetupHook(hDlg,uMsg,wParam,(LPARAM)pda->dlga))
3473 FIXME("Setup page hook failed?\n");
3476 /* if printer button disabled */
3477 if (pda->dlga->Flags & PSD_DISABLEPRINTER)
3478 EnableWindow(GetDlgItem(hDlg, psh3), FALSE);
3479 /* if margin edit boxes disabled */
3480 if (pda->dlga->Flags & PSD_DISABLEMARGINS) {
3481 EnableWindow(GetDlgItem(hDlg, edt4), FALSE);
3482 EnableWindow(GetDlgItem(hDlg, edt5), FALSE);
3483 EnableWindow(GetDlgItem(hDlg, edt6), FALSE);
3484 EnableWindow(GetDlgItem(hDlg, edt7), FALSE);
3487 /* Set orientation radiobuttons properly */
3488 pagesetup_update_orientation_buttons(hDlg, pda);
3490 /* if orientation disabled */
3491 if (pda->dlga->Flags & PSD_DISABLEORIENTATION) {
3492 EnableWindow(GetDlgItem(hDlg,rad1),FALSE);
3493 EnableWindow(GetDlgItem(hDlg,rad2),FALSE);
3496 /* We fill them out enabled or not */
3497 if (!(pda->dlga->Flags & PSD_MARGINS))
3499 /* default is 1 inch */
3500 DWORD size = _c_inch2size(pda->dlga,1000);
3501 pda->dlga->rtMargin.left = size;
3502 pda->dlga->rtMargin.top = size;
3503 pda->dlga->rtMargin.right = size;
3504 pda->dlga->rtMargin.bottom = size;
3506 update_margin_edits(hDlg, pda, 0);
3507 subclass_margin_edits(hDlg);
3508 set_margin_groupbox_title(hDlg, pda);
3510 /* if paper disabled */
3511 if (pda->dlga->Flags & PSD_DISABLEPAPER) {
3512 EnableWindow(GetDlgItem(hDlg,cmb2),FALSE);
3513 EnableWindow(GetDlgItem(hDlg,cmb3),FALSE);
3516 /* filling combos: printer, paper, source. selecting current printer (from DEVMODEA) */
3517 pagesetup_init_combos(hDlg, pda);
3518 pagesetup_update_papersize(pda);
3519 pagesetup_set_defaultsource(pda, DMBIN_FORMSOURCE); /* FIXME: This is the auto select bin. Is this correct? */
3521 /* Drawing paper prev */
3522 PRINTDLG_PS_ChangePaperPrev(pda);
3525 pda = GetPropW(hDlg, pagesetupdlg_prop);
3527 WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
3530 if (pda->dlga->Flags & PSD_ENABLEPAGESETUPHOOK) {
3531 res = pda->dlga->lpfnPageSetupHook(hDlg,uMsg,wParam,lParam);
3532 if (res) return res;
3537 return PRINTDLG_PS_WMCommandA(hDlg, wParam, lParam, pda);
3542 static INT_PTR CALLBACK
3543 PageDlgProcW(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
3545 PageSetupDataW *pdw;
3548 if (uMsg==WM_INITDIALOG) {
3550 pdw = (PageSetupDataW*)lParam;
3551 pdw->curdlg = *pdw->dlgw;
3552 SetPropW(hDlg, pagesetupdlg_prop, pdw);
3553 if (pdw->dlgw->Flags & PSD_ENABLEPAGESETUPHOOK) {
3554 res = pdw->dlgw->lpfnPageSetupHook(hDlg,uMsg,wParam,(LPARAM)pdw->dlgw);
3556 FIXME("Setup page hook failed?\n");
3561 if (pdw->dlgw->Flags & PSD_ENABLEPAGEPAINTHOOK) {
3562 FIXME("PagePaintHook not yet implemented!\n");
3564 if (pdw->dlgw->Flags & PSD_DISABLEPRINTER)
3565 EnableWindow(GetDlgItem(hDlg, psh3), FALSE);
3566 if (pdw->dlgw->Flags & PSD_DISABLEMARGINS) {
3567 EnableWindow(GetDlgItem(hDlg, edt4), FALSE);
3568 EnableWindow(GetDlgItem(hDlg, edt5), FALSE);
3569 EnableWindow(GetDlgItem(hDlg, edt6), FALSE);
3570 EnableWindow(GetDlgItem(hDlg, edt7), FALSE);
3573 PRINTDLG_PS_ChangePrinterW(hDlg,pdw);
3575 if (pdw->dlgw->Flags & PSD_DISABLEORIENTATION) {
3576 EnableWindow(GetDlgItem(hDlg,rad1),FALSE);
3577 EnableWindow(GetDlgItem(hDlg,rad2),FALSE);
3579 /* We fill them out enabled or not */
3580 if (pdw->dlgw->Flags & PSD_MARGINS) {
3582 _c_size2strW(pdw,pdw->dlgw->rtMargin.left,str);
3583 SetDlgItemTextW(hDlg,edt4,str);
3584 _c_size2strW(pdw,pdw->dlgw->rtMargin.top,str);
3585 SetDlgItemTextW(hDlg,edt5,str);
3586 _c_size2strW(pdw,pdw->dlgw->rtMargin.right,str);
3587 SetDlgItemTextW(hDlg,edt6,str);
3588 _c_size2strW(pdw,pdw->dlgw->rtMargin.bottom,str);
3589 SetDlgItemTextW(hDlg,edt7,str);
3591 /* default is 1 inch */
3592 DWORD size = _c_inch2size((LPPAGESETUPDLGA)pdw->dlgw,1000);
3594 _c_size2strW(pdw,size,str);
3595 SetDlgItemTextW(hDlg,edt4,str);
3596 SetDlgItemTextW(hDlg,edt5,str);
3597 SetDlgItemTextW(hDlg,edt6,str);
3598 SetDlgItemTextW(hDlg,edt7,str);
3601 if (pdw->dlgw->Flags & PSD_DISABLEPAPER) {
3602 EnableWindow(GetDlgItem(hDlg,cmb2),FALSE);
3603 EnableWindow(GetDlgItem(hDlg,cmb3),FALSE);
3608 pdw = GetPropW(hDlg, pagesetupdlg_prop);
3610 WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
3613 if (pdw->dlgw->Flags & PSD_ENABLEPAGESETUPHOOK) {
3614 res = pdw->dlgw->lpfnPageSetupHook(hDlg,uMsg,wParam,lParam);
3615 if (res) return res;
3620 return PRINTDLG_PS_WMCommandW(hDlg, wParam, lParam, pdw);
3625 /***********************************************************************
3626 * PageSetupDlgA (COMDLG32.@)
3628 * Displays the PAGE SETUP dialog box, which enables the user to specify
3629 * specific properties of a printed page such as
3630 * size, source, orientation and the width of the page margins.
3633 * setupdlg [IO] PAGESETUPDLGA struct
3636 * TRUE if the user pressed the OK button
3637 * FALSE if the user cancelled the window or an error occurred
3640 * The values of hDevMode and hDevNames are filled on output and can be
3641 * changed in PAGESETUPDLG when they are passed in PageSetupDlg.
3645 BOOL WINAPI PageSetupDlgA(LPPAGESETUPDLGA setupdlg) {
3649 PageSetupDataA *pda;
3651 if (setupdlg == NULL) {
3652 COMDLG32_SetCommDlgExtendedError(CDERR_INITIALIZATION);
3657 if(TRACE_ON(commdlg)) {
3658 char flagstr[1000] = "";
3659 const struct pd_flags *pflag = psd_flags;
3660 for( ; pflag->name; pflag++) {
3661 if(setupdlg->Flags & pflag->flag) {
3662 strcat(flagstr, pflag->name);
3663 strcat(flagstr, "|");
3666 TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
3667 "hinst %p, flags %08x (%s)\n",
3668 setupdlg, setupdlg->hwndOwner, setupdlg->hDevMode,
3669 setupdlg->hDevNames,
3670 setupdlg->hInstance, setupdlg->Flags, flagstr);
3673 /* Checking setupdlg structure */
3674 if(setupdlg->lStructSize != sizeof(PAGESETUPDLGA)) {
3675 COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
3678 if ((setupdlg->Flags & PSD_ENABLEPAGEPAINTHOOK) &&
3679 (setupdlg->lpfnPagePaintHook == NULL)) {
3680 COMDLG32_SetCommDlgExtendedError(CDERR_NOHOOK);
3684 if(!(setupdlg->Flags & (PSD_INTHOUSANDTHSOFINCHES | PSD_INHUNDREDTHSOFMILLIMETERS)))
3685 setupdlg->Flags |= is_default_metric() ?
3686 PSD_INHUNDREDTHSOFMILLIMETERS : PSD_INTHOUSANDTHSOFINCHES;
3688 /* Initialize default printer struct. If no printer device info is specified
3689 retrieve the default printer data. */
3690 if (!setupdlg->hDevMode || !setupdlg->hDevNames)
3693 memset(&pdlg, 0, sizeof(pdlg));
3694 pdlg.lStructSize = sizeof(pdlg);
3695 pdlg.Flags = PD_RETURNDEFAULT;
3696 bRet = PrintDlgA(&pdlg);
3699 if (!(setupdlg->Flags & PSD_NOWARNING)) {
3701 LoadStringW(COMDLG32_hInstance, PD32_NO_DEFAULT_PRINTER, errstr, 255);
3702 MessageBoxW(setupdlg->hwndOwner, errstr, 0, MB_OK | MB_ICONERROR);
3706 setupdlg->hDevMode = pdlg.hDevMode;
3707 setupdlg->hDevNames = pdlg.hDevNames;
3710 pda = HeapAlloc(GetProcessHeap(),0,sizeof(*pda));
3711 pda->dlga = setupdlg;
3713 /* short cut exit, just return default values */
3714 if (setupdlg->Flags & PSD_RETURNDEFAULT) {
3715 pagesetup_update_papersize(pda);
3716 HeapFree(GetProcessHeap(), 0, pda);
3720 /* get dialog template */
3721 hDlgTmpl = PRINTDLG_GetPGSTemplateA(setupdlg);
3723 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
3726 ptr = LockResource( hDlgTmpl );
3728 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
3732 bRet = (0<DialogBoxIndirectParamW(
3733 setupdlg->hInstance,
3735 setupdlg->hwndOwner,
3736 PRINTDLG_PageDlgProcA,
3740 HeapFree(GetProcessHeap(),0,pda);
3743 /***********************************************************************
3744 * PageSetupDlgW (COMDLG32.@)
3746 * See PageSetupDlgA.
3748 BOOL WINAPI PageSetupDlgW(LPPAGESETUPDLGW setupdlg) {
3752 PageSetupDataW *pdw;
3755 FIXME("Unicode implementation is not done yet\n");
3757 if (setupdlg == NULL) {
3758 COMDLG32_SetCommDlgExtendedError(CDERR_INITIALIZATION);
3762 if(TRACE_ON(commdlg)) {
3763 char flagstr[1000] = "";
3764 const struct pd_flags *pflag = psd_flags;
3765 for( ; pflag->name; pflag++) {
3766 if(setupdlg->Flags & pflag->flag) {
3767 strcat(flagstr, pflag->name);
3768 strcat(flagstr, "|");
3771 TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
3772 "hinst %p, flags %08x (%s)\n",
3773 setupdlg, setupdlg->hwndOwner, setupdlg->hDevMode,
3774 setupdlg->hDevNames,
3775 setupdlg->hInstance, setupdlg->Flags, flagstr);
3778 /* Initialize default printer struct. If no printer device info is specified
3779 retrieve the default printer data. */
3780 memset(&pdlg,0,sizeof(pdlg));
3781 pdlg.lStructSize = sizeof(pdlg);
3782 if (setupdlg->hDevMode && setupdlg->hDevNames) {
3783 pdlg.hDevMode = setupdlg->hDevMode;
3784 pdlg.hDevNames = setupdlg->hDevNames;
3786 pdlg.Flags = PD_RETURNDEFAULT;
3787 bRet = PrintDlgW(&pdlg);
3789 if (!(setupdlg->Flags & PSD_NOWARNING)) {
3791 LoadStringW(COMDLG32_hInstance, PD32_NO_DEFAULT_PRINTER, errstr, 255);
3792 MessageBoxW(setupdlg->hwndOwner, errstr, 0, MB_OK | MB_ICONERROR);
3798 /* short cut exit, just return default values */
3799 if (setupdlg->Flags & PSD_RETURNDEFAULT) {
3800 static const WCHAR a4[] = {'A','4',0};
3801 setupdlg->hDevMode = pdlg.hDevMode;
3802 setupdlg->hDevNames = pdlg.hDevNames;
3803 /* FIXME: Just return "A4" for now. */
3804 PRINTDLG_PaperSizeW(&pdlg,a4,&setupdlg->ptPaperSize);
3805 setupdlg->ptPaperSize.x=_c_10mm2size((LPPAGESETUPDLGA)setupdlg,setupdlg->ptPaperSize.x);
3806 setupdlg->ptPaperSize.y=_c_10mm2size((LPPAGESETUPDLGA)setupdlg,setupdlg->ptPaperSize.y);
3809 hDlgTmpl = PRINTDLG_GetPGSTemplateW(setupdlg);
3811 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
3814 ptr = LockResource( hDlgTmpl );
3816 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
3819 pdw = HeapAlloc(GetProcessHeap(),0,sizeof(*pdw));
3820 pdw->dlgw = setupdlg;
3823 bRet = (0<DialogBoxIndirectParamW(
3824 setupdlg->hInstance,
3826 setupdlg->hwndOwner,
3833 /***********************************************************************
3834 * PrintDlgExA (COMDLG32.@)
3842 HRESULT WINAPI PrintDlgExA(LPPRINTDLGEXA lppd)
3845 FIXME("(%p) stub\n", lppd);
3846 if ((lppd == NULL) || (lppd->lStructSize != sizeof(PRINTDLGEXA))) {
3847 return E_INVALIDARG;
3850 if (!IsWindow(lppd->hwndOwner)) {
3857 /***********************************************************************
3858 * PrintDlgExW (COMDLG32.@)
3860 * Display the property sheet style PRINT dialog box
3863 * lppd [IO] ptr to PRINTDLGEX struct
3867 * Failure: One of the following COM error codes:
3868 * E_OUTOFMEMORY Insufficient memory.
3869 * E_INVALIDARG One or more arguments are invalid.
3870 * E_POINTER Invalid pointer.
3871 * E_HANDLE Invalid handle.
3872 * E_FAIL Unspecified error.
3875 * This Dialog enables the user to specify specific properties of the print job.
3876 * The property sheet can also have additional application-specific and
3877 * driver-specific property pages.
3880 * Not fully implemented
3883 HRESULT WINAPI PrintDlgExW(LPPRINTDLGEXW lppd)
3888 FIXME("(%p) not fully implemented\n", lppd);
3890 if ((lppd == NULL) || (lppd->lStructSize != sizeof(PRINTDLGEXW))) {
3891 return E_INVALIDARG;
3894 if (!IsWindow(lppd->hwndOwner)) {
3898 if (lppd->Flags & PD_RETURNDEFAULT) {
3899 PRINTER_INFO_2W *pbuf;
3900 DRIVER_INFO_2W *dbuf;
3902 DWORD needed = 1024;
3905 if (lppd->hDevMode || lppd->hDevNames) {
3906 WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
3907 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
3908 return E_INVALIDARG;
3910 if (!PRINTDLG_OpenDefaultPrinter(&hprn)) {
3911 WARN("Can't find default printer\n");
3912 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
3916 pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
3917 bRet = GetPrinterW(hprn, 2, (LPBYTE)pbuf, needed, &needed);
3918 if (!bRet && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
3919 HeapFree(GetProcessHeap(), 0, pbuf);
3920 pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
3921 bRet = GetPrinterW(hprn, 2, (LPBYTE)pbuf, needed, &needed);
3924 HeapFree(GetProcessHeap(), 0, pbuf);
3930 dbuf = HeapAlloc(GetProcessHeap(), 0, needed);
3931 bRet = GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed);
3932 if (!bRet && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
3933 HeapFree(GetProcessHeap(), 0, dbuf);
3934 dbuf = HeapAlloc(GetProcessHeap(), 0, needed);
3935 bRet = GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed);
3938 ERR("GetPrinterDriverW failed, last error %d, fix your config for printer %s!\n",
3939 GetLastError(), debugstr_w(pbuf->pPrinterName));
3940 HeapFree(GetProcessHeap(), 0, dbuf);
3941 HeapFree(GetProcessHeap(), 0, pbuf);
3942 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
3948 PRINTDLG_CreateDevNamesW(&(lppd->hDevNames),
3952 lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
3953 pbuf->pDevMode->dmDriverExtra);
3954 if (lppd->hDevMode) {
3955 ptr = GlobalLock(lppd->hDevMode);
3957 memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
3958 pbuf->pDevMode->dmDriverExtra);
3959 GlobalUnlock(lppd->hDevMode);
3963 HeapFree(GetProcessHeap(), 0, pbuf);
3964 HeapFree(GetProcessHeap(), 0, dbuf);