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
8 * Copyright 2010 Vitaly Perov
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
31 #define NONAMELESSUNION
32 #define NONAMELESSSTRUCT
40 #include "wine/unicode.h"
41 #include "wine/debug.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(commdlg
);
50 /* Yes these constants are the same, but we're just copying win98 */
51 #define UPDOWN_ID 0x270f
52 #define MAX_COPIES 9999
54 /* This PRINTDLGA internal structure stores
55 * pointers to several throughout useful structures.
61 LPPRINTDLGA lpPrintDlg
;
62 LPPRINTER_INFO_2A lpPrinterInfo
;
63 LPDRIVER_INFO_3A lpDriverInfo
;
65 HICON hCollateIcon
; /* PrintDlg only */
66 HICON hNoCollateIcon
; /* PrintDlg only */
67 HICON hPortraitIcon
; /* PrintSetupDlg only */
68 HICON hLandscapeIcon
; /* PrintSetupDlg only */
75 LPPRINTDLGW lpPrintDlg
;
76 LPPRINTER_INFO_2W lpPrinterInfo
;
77 LPDRIVER_INFO_3W lpDriverInfo
;
79 HICON hCollateIcon
; /* PrintDlg only */
80 HICON hNoCollateIcon
; /* PrintDlg only */
81 HICON hPortraitIcon
; /* PrintSetupDlg only */
82 HICON hLandscapeIcon
; /* PrintSetupDlg only */
93 static const struct pd_flags psd_flags
[] = {
94 {PSD_MINMARGINS
,"PSD_MINMARGINS"},
95 {PSD_MARGINS
,"PSD_MARGINS"},
96 {PSD_INTHOUSANDTHSOFINCHES
,"PSD_INTHOUSANDTHSOFINCHES"},
97 {PSD_INHUNDREDTHSOFMILLIMETERS
,"PSD_INHUNDREDTHSOFMILLIMETERS"},
98 {PSD_DISABLEMARGINS
,"PSD_DISABLEMARGINS"},
99 {PSD_DISABLEPRINTER
,"PSD_DISABLEPRINTER"},
100 {PSD_NOWARNING
,"PSD_NOWARNING"},
101 {PSD_DISABLEORIENTATION
,"PSD_DISABLEORIENTATION"},
102 {PSD_RETURNDEFAULT
,"PSD_RETURNDEFAULT"},
103 {PSD_DISABLEPAPER
,"PSD_DISABLEPAPER"},
104 {PSD_SHOWHELP
,"PSD_SHOWHELP"},
105 {PSD_ENABLEPAGESETUPHOOK
,"PSD_ENABLEPAGESETUPHOOK"},
106 {PSD_ENABLEPAGESETUPTEMPLATE
,"PSD_ENABLEPAGESETUPTEMPLATE"},
107 {PSD_ENABLEPAGESETUPTEMPLATEHANDLE
,"PSD_ENABLEPAGESETUPTEMPLATEHANDLE"},
108 {PSD_ENABLEPAGEPAINTHOOK
,"PSD_ENABLEPAGEPAINTHOOK"},
109 {PSD_DISABLEPAGEPAINTING
,"PSD_DISABLEPAGEPAINTING"},
113 static const struct pd_flags pd_flags
[] = {
114 {PD_SELECTION
, "PD_SELECTION "},
115 {PD_PAGENUMS
, "PD_PAGENUMS "},
116 {PD_NOSELECTION
, "PD_NOSELECTION "},
117 {PD_NOPAGENUMS
, "PD_NOPAGENUMS "},
118 {PD_COLLATE
, "PD_COLLATE "},
119 {PD_PRINTTOFILE
, "PD_PRINTTOFILE "},
120 {PD_PRINTSETUP
, "PD_PRINTSETUP "},
121 {PD_NOWARNING
, "PD_NOWARNING "},
122 {PD_RETURNDC
, "PD_RETURNDC "},
123 {PD_RETURNIC
, "PD_RETURNIC "},
124 {PD_RETURNDEFAULT
, "PD_RETURNDEFAULT "},
125 {PD_SHOWHELP
, "PD_SHOWHELP "},
126 {PD_ENABLEPRINTHOOK
, "PD_ENABLEPRINTHOOK "},
127 {PD_ENABLESETUPHOOK
, "PD_ENABLESETUPHOOK "},
128 {PD_ENABLEPRINTTEMPLATE
, "PD_ENABLEPRINTTEMPLATE "},
129 {PD_ENABLESETUPTEMPLATE
, "PD_ENABLESETUPTEMPLATE "},
130 {PD_ENABLEPRINTTEMPLATEHANDLE
, "PD_ENABLEPRINTTEMPLATEHANDLE "},
131 {PD_ENABLESETUPTEMPLATEHANDLE
, "PD_ENABLESETUPTEMPLATEHANDLE "},
132 {PD_USEDEVMODECOPIES
, "PD_USEDEVMODECOPIES[ANDCOLLATE] "},
133 {PD_DISABLEPRINTTOFILE
, "PD_DISABLEPRINTTOFILE "},
134 {PD_HIDEPRINTTOFILE
, "PD_HIDEPRINTTOFILE "},
135 {PD_NONETWORKBUTTON
, "PD_NONETWORKBUTTON "},
138 /* address of wndproc for subclassed Static control */
139 static WNDPROC lpfnStaticWndProc
;
140 static WNDPROC edit_wndproc
;
141 /* the text of the fake document to render for the Page Setup dialog */
142 static WCHAR wszFakeDocumentText
[1024];
143 static const WCHAR pd32_collateW
[] = { 'P', 'D', '3', '2', '_', 'C', 'O', 'L', 'L', 'A', 'T', 'E', 0 };
144 static const WCHAR pd32_nocollateW
[] = { 'P', 'D', '3', '2', '_', 'N', 'O', 'C', 'O', 'L', 'L', 'A', 'T', 'E', 0 };
145 static const WCHAR pd32_portraitW
[] = { 'P', 'D', '3', '2', '_', 'P', 'O', 'R', 'T', 'R', 'A', 'I', 'T', 0 };
146 static const WCHAR pd32_landscapeW
[] = { 'P', 'D', '3', '2', '_', 'L', 'A', 'N', 'D', 'S', 'C', 'A', 'P', 'E', 0 };
147 static const WCHAR printdlg_prop
[] = {'_','_','W','I','N','E','_','P','R','I','N','T','D','L','G','D','A','T','A',0};
148 static const WCHAR pagesetupdlg_prop
[] = { '_', '_', 'W', 'I', 'N', 'E', '_', 'P', 'A', 'G', 'E',
149 'S', 'E', 'T', 'U', 'P', 'D', 'L', 'G', 'D', 'A', 'T', 'A', 0 };
152 static LPWSTR
strdupW(LPCWSTR p
)
158 len
= (strlenW(p
) + 1) * sizeof(WCHAR
);
159 ret
= HeapAlloc(GetProcessHeap(), 0, len
);
164 /***********************************************************************
165 * get_driver_info [internal]
167 * get DRIVER_INFO_3W for the current printer handle,
168 * alloc the buffer, when needed
170 static DRIVER_INFO_3W
* get_driver_infoW(HANDLE hprn
)
172 DRIVER_INFO_3W
*di3
= NULL
;
176 res
= GetPrinterDriverW(hprn
, NULL
, 3, NULL
, 0, &needed
);
177 if (!res
&& (GetLastError() == ERROR_INSUFFICIENT_BUFFER
)) {
178 di3
= HeapAlloc(GetProcessHeap(), 0, needed
);
179 res
= GetPrinterDriverW(hprn
, NULL
, 3, (LPBYTE
)di3
, needed
, &needed
);
185 TRACE("GetPrinterDriverW failed with %u\n", GetLastError());
186 HeapFree(GetProcessHeap(), 0, di3
);
190 static DRIVER_INFO_3A
* get_driver_infoA(HANDLE hprn
)
192 DRIVER_INFO_3A
*di3
= NULL
;
196 res
= GetPrinterDriverA(hprn
, NULL
, 3, NULL
, 0, &needed
);
197 if (!res
&& (GetLastError() == ERROR_INSUFFICIENT_BUFFER
)) {
198 di3
= HeapAlloc(GetProcessHeap(), 0, needed
);
199 res
= GetPrinterDriverA(hprn
, NULL
, 3, (LPBYTE
)di3
, needed
, &needed
);
205 TRACE("GetPrinterDriverA failed with %u\n", GetLastError());
206 HeapFree(GetProcessHeap(), 0, di3
);
211 /***********************************************************************
212 * get_printer_info [internal]
214 * get PRINTER_INFO_2W for the current printer handle,
215 * alloc the buffer, when needed
217 static PRINTER_INFO_2W
* get_printer_infoW(HANDLE hprn
)
219 PRINTER_INFO_2W
*pi2
= NULL
;
223 res
= GetPrinterW(hprn
, 2, NULL
, 0, &needed
);
224 if (!res
&& (GetLastError() == ERROR_INSUFFICIENT_BUFFER
)) {
225 pi2
= HeapAlloc(GetProcessHeap(), 0, needed
);
226 res
= GetPrinterW(hprn
, 2, (LPBYTE
)pi2
, needed
, &needed
);
232 TRACE("GetPrinterW failed with %u\n", GetLastError());
233 HeapFree(GetProcessHeap(), 0, pi2
);
237 static PRINTER_INFO_2A
* get_printer_infoA(HANDLE hprn
)
239 PRINTER_INFO_2A
*pi2
= NULL
;
243 res
= GetPrinterA(hprn
, 2, NULL
, 0, &needed
);
244 if (!res
&& (GetLastError() == ERROR_INSUFFICIENT_BUFFER
)) {
245 pi2
= HeapAlloc(GetProcessHeap(), 0, needed
);
246 res
= GetPrinterA(hprn
, 2, (LPBYTE
)pi2
, needed
, &needed
);
252 TRACE("GetPrinterA failed with %u\n", GetLastError());
253 HeapFree(GetProcessHeap(), 0, pi2
);
257 /***********************************************************
258 * convert_to_devmodeA
260 * Creates an ansi copy of supplied devmode
262 static DEVMODEA
*convert_to_devmodeA(const DEVMODEW
*dmW
)
267 if (!dmW
) return NULL
;
268 size
= dmW
->dmSize
- CCHDEVICENAME
-
269 ((dmW
->dmSize
> FIELD_OFFSET(DEVMODEW
, dmFormName
)) ? CCHFORMNAME
: 0);
271 dmA
= HeapAlloc(GetProcessHeap(), 0, size
+ dmW
->dmDriverExtra
);
272 if (!dmA
) return NULL
;
274 WideCharToMultiByte(CP_ACP
, 0, dmW
->dmDeviceName
, -1,
275 (LPSTR
)dmA
->dmDeviceName
, CCHDEVICENAME
, NULL
, NULL
);
277 if (FIELD_OFFSET(DEVMODEW
, dmFormName
) >= dmW
->dmSize
)
279 memcpy(&dmA
->dmSpecVersion
, &dmW
->dmSpecVersion
,
280 dmW
->dmSize
- FIELD_OFFSET(DEVMODEW
, dmSpecVersion
));
284 memcpy(&dmA
->dmSpecVersion
, &dmW
->dmSpecVersion
,
285 FIELD_OFFSET(DEVMODEW
, dmFormName
) - FIELD_OFFSET(DEVMODEW
, dmSpecVersion
));
286 WideCharToMultiByte(CP_ACP
, 0, dmW
->dmFormName
, -1,
287 (LPSTR
)dmA
->dmFormName
, CCHFORMNAME
, NULL
, NULL
);
289 memcpy(&dmA
->dmLogPixels
, &dmW
->dmLogPixels
, dmW
->dmSize
- FIELD_OFFSET(DEVMODEW
, dmLogPixels
));
293 memcpy((char *)dmA
+ dmA
->dmSize
, (const char *)dmW
+ dmW
->dmSize
, dmW
->dmDriverExtra
);
297 /***********************************************************************
298 * PRINTDLG_OpenDefaultPrinter
300 * Returns a winspool printer handle to the default printer in *hprn
301 * Caller must call ClosePrinter on the handle
303 * Returns TRUE on success else FALSE
305 static BOOL
PRINTDLG_OpenDefaultPrinter(HANDLE
*hprn
)
308 DWORD dwBufLen
= sizeof(buf
) / sizeof(buf
[0]);
310 if(!GetDefaultPrinterW(buf
, &dwBufLen
))
312 res
= OpenPrinterW(buf
, hprn
, NULL
);
314 WARN("Could not open printer %s\n", debugstr_w(buf
));
318 /***********************************************************************
319 * PRINTDLG_SetUpPrinterListCombo
321 * Initializes printer list combox.
322 * hDlg: HWND of dialog
323 * id: Control id of combo
324 * name: Name of printer to select
326 * Initializes combo with list of available printers. Selects printer 'name'
327 * If name is NULL or does not exist select the default printer.
329 * Returns number of printers added to list.
331 static INT
PRINTDLG_SetUpPrinterListComboA(HWND hDlg
, UINT id
, LPCSTR name
)
335 LPPRINTER_INFO_2A pi
;
336 EnumPrintersA(PRINTER_ENUM_LOCAL
, NULL
, 2, NULL
, 0, &needed
, &num
);
337 pi
= HeapAlloc(GetProcessHeap(), 0, needed
);
338 EnumPrintersA(PRINTER_ENUM_LOCAL
, NULL
, 2, (LPBYTE
)pi
, needed
, &needed
,
341 SendDlgItemMessageA(hDlg
, id
, CB_RESETCONTENT
, 0, 0);
343 for(i
= 0; i
< num
; i
++) {
344 SendDlgItemMessageA(hDlg
, id
, CB_ADDSTRING
, 0,
345 (LPARAM
)pi
[i
].pPrinterName
);
347 HeapFree(GetProcessHeap(), 0, pi
);
349 (i
= SendDlgItemMessageA(hDlg
, id
, CB_FINDSTRINGEXACT
, -1,
350 (LPARAM
)name
)) == CB_ERR
) {
353 DWORD dwBufLen
= sizeof(buf
);
355 WARN("Can't find %s in printer list so trying to find default\n",
357 if(!GetDefaultPrinterA(buf
, &dwBufLen
))
359 i
= SendDlgItemMessageA(hDlg
, id
, CB_FINDSTRINGEXACT
, -1, (LPARAM
)buf
);
361 FIXME("Can't find default printer in printer list\n");
363 SendDlgItemMessageA(hDlg
, id
, CB_SETCURSEL
, i
, 0);
367 static INT
PRINTDLG_SetUpPrinterListComboW(HWND hDlg
, UINT id
, LPCWSTR name
)
371 LPPRINTER_INFO_2W pi
;
372 EnumPrintersW(PRINTER_ENUM_LOCAL
, NULL
, 2, NULL
, 0, &needed
, &num
);
373 pi
= HeapAlloc(GetProcessHeap(), 0, needed
);
374 EnumPrintersW(PRINTER_ENUM_LOCAL
, NULL
, 2, (LPBYTE
)pi
, needed
, &needed
,
377 for(i
= 0; i
< num
; i
++) {
378 SendDlgItemMessageW(hDlg
, id
, CB_ADDSTRING
, 0,
379 (LPARAM
)pi
[i
].pPrinterName
);
381 HeapFree(GetProcessHeap(), 0, pi
);
383 (i
= SendDlgItemMessageW(hDlg
, id
, CB_FINDSTRINGEXACT
, -1,
384 (LPARAM
)name
)) == CB_ERR
) {
386 DWORD dwBufLen
= sizeof(buf
)/sizeof(buf
[0]);
388 WARN("Can't find %s in printer list so trying to find default\n",
390 if(!GetDefaultPrinterW(buf
, &dwBufLen
))
392 i
= SendDlgItemMessageW(hDlg
, id
, CB_FINDSTRINGEXACT
, -1, (LPARAM
)buf
);
394 TRACE("Can't find default printer in printer list\n");
396 SendDlgItemMessageW(hDlg
, id
, CB_SETCURSEL
, i
, 0);
400 /***********************************************************************
401 * PRINTDLG_CreateDevNames [internal]
404 * creates a DevNames structure.
406 * (NB. when we handle unicode the offsets will be in wchars).
408 static BOOL
PRINTDLG_CreateDevNames(HGLOBAL
*hmem
, const char* DeviceDriverName
,
409 const char* DeviceName
, const char* OutputPort
)
412 char* pDevNamesSpace
;
414 LPDEVNAMES lpDevNames
;
416 DWORD dwBufLen
= sizeof(buf
);
419 p
= strrchr( DeviceDriverName
, '\\' );
420 if (p
) DeviceDriverName
= p
+ 1;
422 size
= strlen(DeviceDriverName
) + 1
423 + strlen(DeviceName
) + 1
424 + strlen(OutputPort
) + 1
428 *hmem
= GlobalReAlloc(*hmem
, size
, GMEM_MOVEABLE
);
430 *hmem
= GlobalAlloc(GMEM_MOVEABLE
, size
);
434 pDevNamesSpace
= GlobalLock(*hmem
);
435 lpDevNames
= (LPDEVNAMES
) pDevNamesSpace
;
437 pTempPtr
= pDevNamesSpace
+ sizeof(DEVNAMES
);
438 strcpy(pTempPtr
, DeviceDriverName
);
439 lpDevNames
->wDriverOffset
= pTempPtr
- pDevNamesSpace
;
441 pTempPtr
+= strlen(DeviceDriverName
) + 1;
442 strcpy(pTempPtr
, DeviceName
);
443 lpDevNames
->wDeviceOffset
= pTempPtr
- pDevNamesSpace
;
445 pTempPtr
+= strlen(DeviceName
) + 1;
446 strcpy(pTempPtr
, OutputPort
);
447 lpDevNames
->wOutputOffset
= pTempPtr
- pDevNamesSpace
;
449 GetDefaultPrinterA(buf
, &dwBufLen
);
450 lpDevNames
->wDefault
= (strcmp(buf
, DeviceName
) == 0) ? 1 : 0;
455 static BOOL
PRINTDLG_CreateDevNamesW(HGLOBAL
*hmem
, LPCWSTR DeviceDriverName
,
456 LPCWSTR DeviceName
, LPCWSTR OutputPort
)
459 LPWSTR pDevNamesSpace
;
461 LPDEVNAMES lpDevNames
;
463 DWORD dwBufLen
= sizeof(bufW
) / sizeof(WCHAR
);
466 p
= strrchrW( DeviceDriverName
, '\\' );
467 if (p
) DeviceDriverName
= p
+ 1;
469 size
= sizeof(WCHAR
)*lstrlenW(DeviceDriverName
) + 2
470 + sizeof(WCHAR
)*lstrlenW(DeviceName
) + 2
471 + sizeof(WCHAR
)*lstrlenW(OutputPort
) + 2
475 *hmem
= GlobalReAlloc(*hmem
, size
, GMEM_MOVEABLE
);
477 *hmem
= GlobalAlloc(GMEM_MOVEABLE
, size
);
481 pDevNamesSpace
= GlobalLock(*hmem
);
482 lpDevNames
= (LPDEVNAMES
) pDevNamesSpace
;
484 pTempPtr
= (LPWSTR
)((LPDEVNAMES
)pDevNamesSpace
+ 1);
485 lstrcpyW(pTempPtr
, DeviceDriverName
);
486 lpDevNames
->wDriverOffset
= pTempPtr
- pDevNamesSpace
;
488 pTempPtr
+= lstrlenW(DeviceDriverName
) + 1;
489 lstrcpyW(pTempPtr
, DeviceName
);
490 lpDevNames
->wDeviceOffset
= pTempPtr
- pDevNamesSpace
;
492 pTempPtr
+= lstrlenW(DeviceName
) + 1;
493 lstrcpyW(pTempPtr
, OutputPort
);
494 lpDevNames
->wOutputOffset
= pTempPtr
- pDevNamesSpace
;
496 GetDefaultPrinterW(bufW
, &dwBufLen
);
497 lpDevNames
->wDefault
= (lstrcmpW(bufW
, DeviceName
) == 0) ? 1 : 0;
502 /***********************************************************************
503 * PRINTDLG_UpdatePrintDlg [internal]
506 * updates the PrintDlg structure for return values.
509 * FALSE if user is not allowed to close (i.e. wrong nTo or nFrom values)
510 * TRUE if successful.
512 static BOOL
PRINTDLG_UpdatePrintDlgA(HWND hDlg
,
513 PRINT_PTRA
* PrintStructures
)
515 LPPRINTDLGA lppd
= PrintStructures
->lpPrintDlg
;
516 PDEVMODEA lpdm
= PrintStructures
->lpDevMode
;
517 LPPRINTER_INFO_2A pi
= PrintStructures
->lpPrinterInfo
;
521 FIXME("No lpdm ptr?\n");
526 if(!(lppd
->Flags
& PD_PRINTSETUP
)) {
527 /* check whether nFromPage and nToPage are within range defined by
528 * nMinPage and nMaxPage
530 if (IsDlgButtonChecked(hDlg
, rad3
) == BST_CHECKED
) { /* Pages */
534 nFromPage
= GetDlgItemInt(hDlg
, edt1
, NULL
, FALSE
);
535 nToPage
= GetDlgItemInt(hDlg
, edt2
, &translated
, FALSE
);
537 /* if no ToPage value is entered, use the FromPage value */
538 if(!translated
) nToPage
= nFromPage
;
540 if (nFromPage
< lppd
->nMinPage
|| nFromPage
> lppd
->nMaxPage
||
541 nToPage
< lppd
->nMinPage
|| nToPage
> lppd
->nMaxPage
) {
542 WCHAR resourcestr
[256];
543 WCHAR resultstr
[256];
544 LoadStringW(COMDLG32_hInstance
, PD32_INVALID_PAGE_RANGE
, resourcestr
, 255);
545 wsprintfW(resultstr
,resourcestr
, lppd
->nMinPage
, lppd
->nMaxPage
);
546 LoadStringW(COMDLG32_hInstance
, PD32_PRINT_TITLE
, resourcestr
, 255);
547 MessageBoxW(hDlg
, resultstr
, resourcestr
, MB_OK
| MB_ICONWARNING
);
550 lppd
->nFromPage
= nFromPage
;
551 lppd
->nToPage
= nToPage
;
552 lppd
->Flags
|= PD_PAGENUMS
;
555 lppd
->Flags
&= ~PD_PAGENUMS
;
557 if (IsDlgButtonChecked(hDlg
, rad2
) == BST_CHECKED
) /* Selection */
558 lppd
->Flags
|= PD_SELECTION
;
560 lppd
->Flags
&= ~PD_SELECTION
;
562 if (IsDlgButtonChecked(hDlg
, chx1
) == BST_CHECKED
) {/* Print to file */
563 static char file
[] = "FILE:";
564 lppd
->Flags
|= PD_PRINTTOFILE
;
565 pi
->pPortName
= file
;
568 if (IsDlgButtonChecked(hDlg
, chx2
) == BST_CHECKED
) { /* Collate */
569 FIXME("Collate lppd not yet implemented as output\n");
572 /* set PD_Collate and nCopies */
573 if (lppd
->Flags
& PD_USEDEVMODECOPIESANDCOLLATE
) {
574 /* The application doesn't support multiple copies or collate...
576 lppd
->Flags
&= ~PD_COLLATE
;
578 /* if the printer driver supports it... store info there
579 * otherwise no collate & multiple copies !
581 if (lpdm
->dmFields
& DM_COLLATE
)
583 (IsDlgButtonChecked(hDlg
, chx2
) == BST_CHECKED
);
584 if (lpdm
->dmFields
& DM_COPIES
)
585 lpdm
->u1
.s1
.dmCopies
= GetDlgItemInt(hDlg
, edt3
, NULL
, FALSE
);
587 /* Application is responsible for multiple copies */
588 if (IsDlgButtonChecked(hDlg
, chx2
) == BST_CHECKED
)
589 lppd
->Flags
|= PD_COLLATE
;
591 lppd
->Flags
&= ~PD_COLLATE
;
592 lppd
->nCopies
= GetDlgItemInt(hDlg
, edt3
, NULL
, FALSE
);
593 /* multiple copies already included in the document. Driver must print only one copy */
594 lpdm
->u1
.s1
.dmCopies
= 1;
597 /* Print quality, PrintDlg16 */
598 if(GetDlgItem(hDlg
, cmb1
))
600 HWND hQuality
= GetDlgItem(hDlg
, cmb1
);
601 int Sel
= SendMessageA(hQuality
, CB_GETCURSEL
, 0, 0);
605 LONG dpi
= SendMessageA(hQuality
, CB_GETITEMDATA
, Sel
, 0);
606 lpdm
->dmFields
|= DM_PRINTQUALITY
| DM_YRESOLUTION
;
607 lpdm
->u1
.s1
.dmPrintQuality
= LOWORD(dpi
);
608 lpdm
->dmYResolution
= HIWORD(dpi
);
615 static BOOL
PRINTDLG_UpdatePrintDlgW(HWND hDlg
,
616 PRINT_PTRW
* PrintStructures
)
618 LPPRINTDLGW lppd
= PrintStructures
->lpPrintDlg
;
619 PDEVMODEW lpdm
= PrintStructures
->lpDevMode
;
620 LPPRINTER_INFO_2W pi
= PrintStructures
->lpPrinterInfo
;
624 FIXME("No lpdm ptr?\n");
629 if(!(lppd
->Flags
& PD_PRINTSETUP
)) {
630 /* check whether nFromPage and nToPage are within range defined by
631 * nMinPage and nMaxPage
633 if (IsDlgButtonChecked(hDlg
, rad3
) == BST_CHECKED
) { /* Pages */
637 nFromPage
= GetDlgItemInt(hDlg
, edt1
, NULL
, FALSE
);
638 nToPage
= GetDlgItemInt(hDlg
, edt2
, &translated
, FALSE
);
640 /* if no ToPage value is entered, use the FromPage value */
641 if(!translated
) nToPage
= nFromPage
;
643 if (nFromPage
< lppd
->nMinPage
|| nFromPage
> lppd
->nMaxPage
||
644 nToPage
< lppd
->nMinPage
|| nToPage
> lppd
->nMaxPage
) {
645 WCHAR resourcestr
[256];
646 WCHAR resultstr
[256];
648 LoadStringW(COMDLG32_hInstance
, PD32_INVALID_PAGE_RANGE
,
650 args
[0] = lppd
->nMinPage
;
651 args
[1] = lppd
->nMaxPage
;
652 FormatMessageW(FORMAT_MESSAGE_FROM_STRING
|FORMAT_MESSAGE_ARGUMENT_ARRAY
,
653 resourcestr
, 0, 0, resultstr
,
654 sizeof(resultstr
)/sizeof(*resultstr
),
655 (__ms_va_list
*)args
);
656 LoadStringW(COMDLG32_hInstance
, PD32_PRINT_TITLE
,
658 MessageBoxW(hDlg
, resultstr
, resourcestr
,
659 MB_OK
| MB_ICONWARNING
);
662 lppd
->nFromPage
= nFromPage
;
663 lppd
->nToPage
= nToPage
;
664 lppd
->Flags
|= PD_PAGENUMS
;
667 lppd
->Flags
&= ~PD_PAGENUMS
;
669 if (IsDlgButtonChecked(hDlg
, rad2
) == BST_CHECKED
) /* Selection */
670 lppd
->Flags
|= PD_SELECTION
;
672 lppd
->Flags
&= ~PD_SELECTION
;
674 if (IsDlgButtonChecked(hDlg
, chx1
) == BST_CHECKED
) {/* Print to file */
675 static WCHAR file
[] = {'F','I','L','E',':',0};
676 lppd
->Flags
|= PD_PRINTTOFILE
;
677 pi
->pPortName
= file
;
680 if (IsDlgButtonChecked(hDlg
, chx2
) == BST_CHECKED
) { /* Collate */
681 FIXME("Collate lppd not yet implemented as output\n");
684 /* set PD_Collate and nCopies */
685 if (lppd
->Flags
& PD_USEDEVMODECOPIESANDCOLLATE
) {
686 /* The application doesn't support multiple copies or collate...
688 lppd
->Flags
&= ~PD_COLLATE
;
690 /* if the printer driver supports it... store info there
691 * otherwise no collate & multiple copies !
693 if (lpdm
->dmFields
& DM_COLLATE
)
695 (IsDlgButtonChecked(hDlg
, chx2
) == BST_CHECKED
);
696 if (lpdm
->dmFields
& DM_COPIES
)
697 lpdm
->u1
.s1
.dmCopies
= GetDlgItemInt(hDlg
, edt3
, NULL
, FALSE
);
699 if (IsDlgButtonChecked(hDlg
, chx2
) == BST_CHECKED
)
700 lppd
->Flags
|= PD_COLLATE
;
702 lppd
->Flags
&= ~PD_COLLATE
;
703 lppd
->nCopies
= GetDlgItemInt(hDlg
, edt3
, NULL
, FALSE
);
709 /************************************************************************
710 * PRINTDLG_SetUpPaperComboBox
712 * Initialize either the papersize or inputslot combos of the Printer Setup
713 * dialog. We store the associated word (eg DMPAPER_A4) as the item data.
714 * We also try to re-select the old selection.
716 static BOOL
PRINTDLG_SetUpPaperComboBoxA(HWND hDlg
,
727 WORD oldWord
= 0, newWord
= 0; /* DMPAPER_ and DMBIN_ start at 1 */
729 int fwCapability_Names
;
730 int fwCapability_Words
;
732 TRACE(" Printer: %s, Port: %s, ComboID: %d\n",PrinterName
,PortName
,nIDComboBox
);
734 /* query the dialog box for the current selected value */
735 Sel
= SendDlgItemMessageA(hDlg
, nIDComboBox
, CB_GETCURSEL
, 0, 0);
737 /* we enter here only if a different printer is selected after
738 * the Print Setup dialog is opened. The current settings are
739 * stored into the newly selected printer.
741 oldWord
= SendDlgItemMessageA(hDlg
, nIDComboBox
, CB_GETITEMDATA
,
743 if(oldWord
>= DMPAPER_USER
) /* DMPAPER_USER == DMBIN_USER */
744 oldWord
= 0; /* There's no point in trying to keep custom
745 paper / bin sizes across printers */
749 newWord
= (nIDComboBox
== cmb2
) ? dm
->u1
.s1
.dmPaperSize
: dm
->u1
.s1
.dmDefaultSource
;
751 if (nIDComboBox
== cmb2
) {
753 fwCapability_Names
= DC_PAPERNAMES
;
754 fwCapability_Words
= DC_PAPERS
;
758 fwCapability_Names
= DC_BINNAMES
;
759 fwCapability_Words
= DC_BINS
;
762 NrOfEntries
= DeviceCapabilitiesA(PrinterName
, PortName
,
763 fwCapability_Names
, NULL
, dm
);
764 if (NrOfEntries
== 0)
765 WARN("no Name Entries found!\n");
766 else if (NrOfEntries
< 0)
769 if(DeviceCapabilitiesA(PrinterName
, PortName
, fwCapability_Words
, NULL
, dm
)
771 ERR("Number of caps is different\n");
775 Names
= HeapAlloc(GetProcessHeap(),0, NrOfEntries
*sizeof(char)*NamesSize
);
776 Words
= HeapAlloc(GetProcessHeap(),0, NrOfEntries
*sizeof(WORD
));
777 NrOfEntries
= DeviceCapabilitiesA(PrinterName
, PortName
,
778 fwCapability_Names
, Names
, dm
);
779 NrOfEntries
= DeviceCapabilitiesA(PrinterName
, PortName
,
780 fwCapability_Words
, (LPSTR
)Words
, dm
);
782 /* reset any current content in the combobox */
783 SendDlgItemMessageA(hDlg
, nIDComboBox
, CB_RESETCONTENT
, 0, 0);
785 /* store new content */
786 for (i
= 0; i
< NrOfEntries
; i
++) {
787 DWORD pos
= SendDlgItemMessageA(hDlg
, nIDComboBox
, CB_ADDSTRING
, 0,
788 (LPARAM
)(&Names
[i
*NamesSize
]) );
789 SendDlgItemMessageA(hDlg
, nIDComboBox
, CB_SETITEMDATA
, pos
,
793 /* Look for old selection or the new default.
794 Can't do this is previous loop since item order will change as more items are added */
796 old_Sel
= NrOfEntries
;
797 for (i
= 0; i
< NrOfEntries
; i
++) {
798 if(SendDlgItemMessageA(hDlg
, nIDComboBox
, CB_GETITEMDATA
, i
, 0) ==
803 if(SendDlgItemMessageA(hDlg
, nIDComboBox
, CB_GETITEMDATA
, i
, 0) == newWord
)
807 if(old_Sel
< NrOfEntries
)
811 if(nIDComboBox
== cmb2
)
812 dm
->u1
.s1
.dmPaperSize
= oldWord
;
814 dm
->u1
.s1
.dmDefaultSource
= oldWord
;
819 SendDlgItemMessageA(hDlg
, nIDComboBox
, CB_SETCURSEL
, Sel
, 0);
821 HeapFree(GetProcessHeap(),0,Words
);
822 HeapFree(GetProcessHeap(),0,Names
);
826 static BOOL
PRINTDLG_SetUpPaperComboBoxW(HWND hDlg
,
828 const WCHAR
* PrinterName
,
829 const WCHAR
* PortName
,
837 WORD oldWord
= 0, newWord
= 0; /* DMPAPER_ and DMBIN_ start at 1 */
839 int fwCapability_Names
;
840 int fwCapability_Words
;
842 TRACE(" Printer: %s, Port: %s, ComboID: %d\n",debugstr_w(PrinterName
),debugstr_w(PortName
),nIDComboBox
);
844 /* query the dialog box for the current selected value */
845 Sel
= SendDlgItemMessageW(hDlg
, nIDComboBox
, CB_GETCURSEL
, 0, 0);
847 /* we enter here only if a different printer is selected after
848 * the Print Setup dialog is opened. The current settings are
849 * stored into the newly selected printer.
851 oldWord
= SendDlgItemMessageW(hDlg
, nIDComboBox
, CB_GETITEMDATA
,
854 if(oldWord
>= DMPAPER_USER
) /* DMPAPER_USER == DMBIN_USER */
855 oldWord
= 0; /* There's no point in trying to keep custom
856 paper / bin sizes across printers */
860 newWord
= (nIDComboBox
== cmb2
) ? dm
->u1
.s1
.dmPaperSize
: dm
->u1
.s1
.dmDefaultSource
;
862 if (nIDComboBox
== cmb2
) {
864 fwCapability_Names
= DC_PAPERNAMES
;
865 fwCapability_Words
= DC_PAPERS
;
869 fwCapability_Names
= DC_BINNAMES
;
870 fwCapability_Words
= DC_BINS
;
873 NrOfEntries
= DeviceCapabilitiesW(PrinterName
, PortName
,
874 fwCapability_Names
, NULL
, dm
);
875 if (NrOfEntries
== 0)
876 WARN("no Name Entries found!\n");
877 else if (NrOfEntries
< 0)
880 if(DeviceCapabilitiesW(PrinterName
, PortName
, fwCapability_Words
, NULL
, dm
)
882 ERR("Number of caps is different\n");
886 Names
= HeapAlloc(GetProcessHeap(),0, NrOfEntries
*sizeof(WCHAR
)*NamesSize
);
887 Words
= HeapAlloc(GetProcessHeap(),0, NrOfEntries
*sizeof(WORD
));
888 NrOfEntries
= DeviceCapabilitiesW(PrinterName
, PortName
,
889 fwCapability_Names
, Names
, dm
);
890 NrOfEntries
= DeviceCapabilitiesW(PrinterName
, PortName
,
891 fwCapability_Words
, Words
, dm
);
893 /* reset any current content in the combobox */
894 SendDlgItemMessageW(hDlg
, nIDComboBox
, CB_RESETCONTENT
, 0, 0);
896 /* store new content */
897 for (i
= 0; i
< NrOfEntries
; i
++) {
898 DWORD pos
= SendDlgItemMessageW(hDlg
, nIDComboBox
, CB_ADDSTRING
, 0,
899 (LPARAM
)(&Names
[i
*NamesSize
]) );
900 SendDlgItemMessageW(hDlg
, nIDComboBox
, CB_SETITEMDATA
, pos
,
904 /* Look for old selection or the new default.
905 Can't do this is previous loop since item order will change as more items are added */
907 old_Sel
= NrOfEntries
;
908 for (i
= 0; i
< NrOfEntries
; i
++) {
909 if(SendDlgItemMessageW(hDlg
, nIDComboBox
, CB_GETITEMDATA
, i
, 0) ==
914 if(SendDlgItemMessageA(hDlg
, nIDComboBox
, CB_GETITEMDATA
, i
, 0) == newWord
)
918 if(old_Sel
< NrOfEntries
)
922 if(nIDComboBox
== cmb2
)
923 dm
->u1
.s1
.dmPaperSize
= oldWord
;
925 dm
->u1
.s1
.dmDefaultSource
= oldWord
;
930 SendDlgItemMessageW(hDlg
, nIDComboBox
, CB_SETCURSEL
, Sel
, 0);
932 HeapFree(GetProcessHeap(),0,Words
);
933 HeapFree(GetProcessHeap(),0,Names
);
938 /***********************************************************************
939 * PRINTDLG_UpdatePrinterInfoTexts [internal]
941 static void PRINTDLG_UpdatePrinterInfoTextsA(HWND hDlg
, const PRINTER_INFO_2A
*pi
)
944 char ResourceString
[256];
950 /* add all status messages */
951 for (i
= 0; i
< 25; i
++) {
952 if (pi
->Status
& (1<<i
)) {
953 LoadStringA(COMDLG32_hInstance
, PD32_PRINTER_STATUS_PAUSED
+i
,
954 ResourceString
, 255);
955 strcat(StatusMsg
,ResourceString
);
959 /* FIXME: status==ready must only be appended if really so.
960 but how to detect? */
961 LoadStringA(COMDLG32_hInstance
, PD32_PRINTER_STATUS_READY
,
962 ResourceString
, 255);
963 strcat(StatusMsg
,ResourceString
);
964 SetDlgItemTextA(hDlg
, stc12
, StatusMsg
);
966 /* set all other printer info texts */
967 SetDlgItemTextA(hDlg
, stc11
, pi
->pDriverName
);
969 if (pi
->pLocation
!= NULL
&& pi
->pLocation
[0] != '\0')
970 SetDlgItemTextA(hDlg
, stc14
, pi
->pLocation
);
972 SetDlgItemTextA(hDlg
, stc14
, pi
->pPortName
);
973 SetDlgItemTextA(hDlg
, stc13
, pi
->pComment
? pi
->pComment
: "");
977 static void PRINTDLG_UpdatePrinterInfoTextsW(HWND hDlg
, const PRINTER_INFO_2W
*pi
)
979 WCHAR StatusMsg
[256];
980 WCHAR ResourceString
[256];
981 static const WCHAR emptyW
[] = {0};
987 /* add all status messages */
988 for (i
= 0; i
< 25; i
++) {
989 if (pi
->Status
& (1<<i
)) {
990 LoadStringW(COMDLG32_hInstance
, PD32_PRINTER_STATUS_PAUSED
+i
,
991 ResourceString
, 255);
992 lstrcatW(StatusMsg
,ResourceString
);
996 /* FIXME: status==ready must only be appended if really so.
997 but how to detect? */
998 LoadStringW(COMDLG32_hInstance
, PD32_PRINTER_STATUS_READY
,
999 ResourceString
, 255);
1000 lstrcatW(StatusMsg
,ResourceString
);
1001 SetDlgItemTextW(hDlg
, stc12
, StatusMsg
);
1003 /* set all other printer info texts */
1004 SetDlgItemTextW(hDlg
, stc11
, pi
->pDriverName
);
1005 if (pi
->pLocation
!= NULL
&& pi
->pLocation
[0] != '\0')
1006 SetDlgItemTextW(hDlg
, stc14
, pi
->pLocation
);
1008 SetDlgItemTextW(hDlg
, stc14
, pi
->pPortName
);
1009 SetDlgItemTextW(hDlg
, stc13
, pi
->pComment
? pi
->pComment
: emptyW
);
1013 /*******************************************************************
1015 * PRINTDLG_ChangePrinter
1018 static BOOL
PRINTDLG_ChangePrinterA(HWND hDlg
, char *name
, PRINT_PTRA
*PrintStructures
)
1020 LPPRINTDLGA lppd
= PrintStructures
->lpPrintDlg
;
1021 LPDEVMODEA lpdm
= NULL
;
1026 HeapFree(GetProcessHeap(),0, PrintStructures
->lpPrinterInfo
);
1027 HeapFree(GetProcessHeap(),0, PrintStructures
->lpDriverInfo
);
1028 if(!OpenPrinterA(name
, &hprn
, NULL
)) {
1029 ERR("Can't open printer %s\n", name
);
1032 GetPrinterA(hprn
, 2, NULL
, 0, &needed
);
1033 PrintStructures
->lpPrinterInfo
= HeapAlloc(GetProcessHeap(),0,needed
);
1034 GetPrinterA(hprn
, 2, (LPBYTE
)PrintStructures
->lpPrinterInfo
, needed
,
1036 GetPrinterDriverA(hprn
, NULL
, 3, NULL
, 0, &needed
);
1037 PrintStructures
->lpDriverInfo
= HeapAlloc(GetProcessHeap(),0,needed
);
1038 if (!GetPrinterDriverA(hprn
, NULL
, 3, (LPBYTE
)PrintStructures
->lpDriverInfo
,
1040 ERR("GetPrinterDriverA failed for %s, fix your config!\n",PrintStructures
->lpPrinterInfo
->pPrinterName
);
1045 PRINTDLG_UpdatePrinterInfoTextsA(hDlg
, PrintStructures
->lpPrinterInfo
);
1047 HeapFree(GetProcessHeap(), 0, PrintStructures
->lpDevMode
);
1048 PrintStructures
->lpDevMode
= NULL
;
1050 dmSize
= DocumentPropertiesA(0, 0, name
, NULL
, NULL
, 0);
1052 ERR("DocumentProperties fails on %s\n", debugstr_a(name
));
1055 PrintStructures
->lpDevMode
= HeapAlloc(GetProcessHeap(), 0, dmSize
);
1056 dmSize
= DocumentPropertiesA(0, 0, name
, PrintStructures
->lpDevMode
, NULL
,
1058 if(lppd
->hDevMode
&& (lpdm
= GlobalLock(lppd
->hDevMode
)) &&
1059 !lstrcmpA( (LPSTR
) lpdm
->dmDeviceName
,
1060 (LPSTR
) PrintStructures
->lpDevMode
->dmDeviceName
)) {
1061 /* Supplied devicemode matches current printer so try to use it */
1062 DocumentPropertiesA(0, 0, name
, PrintStructures
->lpDevMode
, lpdm
,
1063 DM_OUT_BUFFER
| DM_IN_BUFFER
);
1066 GlobalUnlock(lppd
->hDevMode
);
1068 lpdm
= PrintStructures
->lpDevMode
; /* use this as a shortcut */
1070 if(!(lppd
->Flags
& PD_PRINTSETUP
)) {
1071 /* Print range (All/Range/Selection) */
1072 if(lppd
->nFromPage
!= 0xffff)
1073 SetDlgItemInt(hDlg
, edt1
, lppd
->nFromPage
, FALSE
);
1074 if(lppd
->nToPage
!= 0xffff)
1075 SetDlgItemInt(hDlg
, edt2
, lppd
->nToPage
, FALSE
);
1077 CheckRadioButton(hDlg
, rad1
, rad3
, rad1
); /* default */
1078 if (lppd
->Flags
& PD_NOSELECTION
)
1079 EnableWindow(GetDlgItem(hDlg
, rad2
), FALSE
);
1081 if (lppd
->Flags
& PD_SELECTION
)
1082 CheckRadioButton(hDlg
, rad1
, rad3
, rad2
);
1083 if (lppd
->Flags
& PD_NOPAGENUMS
) {
1084 EnableWindow(GetDlgItem(hDlg
, rad3
), FALSE
);
1085 EnableWindow(GetDlgItem(hDlg
, stc2
),FALSE
);
1086 EnableWindow(GetDlgItem(hDlg
, edt1
), FALSE
);
1087 EnableWindow(GetDlgItem(hDlg
, stc3
),FALSE
);
1088 EnableWindow(GetDlgItem(hDlg
, edt2
), FALSE
);
1090 if (lppd
->Flags
& PD_PAGENUMS
)
1091 CheckRadioButton(hDlg
, rad1
, rad3
, rad3
);
1096 * FIXME: The ico3 is not displayed for some reason. I don't know why.
1098 if (lppd
->Flags
& PD_COLLATE
) {
1099 SendDlgItemMessageA(hDlg
, ico3
, STM_SETIMAGE
, IMAGE_ICON
,
1100 (LPARAM
)PrintStructures
->hCollateIcon
);
1101 CheckDlgButton(hDlg
, chx2
, 1);
1103 SendDlgItemMessageA(hDlg
, ico3
, STM_SETIMAGE
, IMAGE_ICON
,
1104 (LPARAM
)PrintStructures
->hNoCollateIcon
);
1105 CheckDlgButton(hDlg
, chx2
, 0);
1108 if (lppd
->Flags
& PD_USEDEVMODECOPIESANDCOLLATE
) {
1109 /* if printer doesn't support it: no Collate */
1110 if (!(lpdm
->dmFields
& DM_COLLATE
)) {
1111 EnableWindow(GetDlgItem(hDlg
, chx2
), FALSE
);
1112 EnableWindow(GetDlgItem(hDlg
, ico3
), FALSE
);
1119 if (lppd
->hDevMode
== 0)
1120 copies
= lppd
->nCopies
;
1122 copies
= lpdm
->u1
.s1
.dmCopies
;
1123 if(copies
== 0) copies
= 1;
1124 else if(copies
< 0) copies
= MAX_COPIES
;
1125 SetDlgItemInt(hDlg
, edt3
, copies
, FALSE
);
1128 if (lppd
->Flags
& PD_USEDEVMODECOPIESANDCOLLATE
) {
1129 /* if printer doesn't support it: no nCopies */
1130 if (!(lpdm
->dmFields
& DM_COPIES
)) {
1131 EnableWindow(GetDlgItem(hDlg
, edt3
), FALSE
);
1132 EnableWindow(GetDlgItem(hDlg
, stc5
), FALSE
);
1137 CheckDlgButton(hDlg
, chx1
, (lppd
->Flags
& PD_PRINTTOFILE
) ? 1 : 0);
1138 if (lppd
->Flags
& PD_DISABLEPRINTTOFILE
)
1139 EnableWindow(GetDlgItem(hDlg
, chx1
), FALSE
);
1140 if (lppd
->Flags
& PD_HIDEPRINTTOFILE
)
1141 ShowWindow(GetDlgItem(hDlg
, chx1
), SW_HIDE
);
1143 /* Fill print quality combo, PrintDlg16 */
1144 if(GetDlgItem(hDlg
, cmb1
))
1146 DWORD numResolutions
= DeviceCapabilitiesA(PrintStructures
->lpPrinterInfo
->pPrinterName
,
1147 PrintStructures
->lpPrinterInfo
->pPortName
,
1148 DC_ENUMRESOLUTIONS
, NULL
, lpdm
);
1150 if(numResolutions
!= -1)
1152 HWND hQuality
= GetDlgItem(hDlg
, cmb1
);
1157 HDC hPrinterDC
= CreateDCA(PrintStructures
->lpPrinterInfo
->pDriverName
,
1158 PrintStructures
->lpPrinterInfo
->pPrinterName
,
1161 Resolutions
= HeapAlloc(GetProcessHeap(), 0, numResolutions
*sizeof(LONG
)*2);
1162 DeviceCapabilitiesA(PrintStructures
->lpPrinterInfo
->pPrinterName
,
1163 PrintStructures
->lpPrinterInfo
->pPortName
,
1164 DC_ENUMRESOLUTIONS
, (LPSTR
)Resolutions
, lpdm
);
1166 dpiX
= GetDeviceCaps(hPrinterDC
, LOGPIXELSX
);
1167 dpiY
= GetDeviceCaps(hPrinterDC
, LOGPIXELSY
);
1168 DeleteDC(hPrinterDC
);
1170 SendMessageA(hQuality
, CB_RESETCONTENT
, 0, 0);
1171 for(i
= 0; i
< (numResolutions
* 2); i
+= 2)
1173 BOOL IsDefault
= FALSE
;
1176 if(Resolutions
[i
] == Resolutions
[i
+1])
1178 if(dpiX
== Resolutions
[i
])
1180 sprintf(buf
, "%d dpi", Resolutions
[i
]);
1183 if(dpiX
== Resolutions
[i
] && dpiY
== Resolutions
[i
+1])
1185 sprintf(buf
, "%d dpi x %d dpi", Resolutions
[i
], Resolutions
[i
+1]);
1188 Index
= SendMessageA(hQuality
, CB_ADDSTRING
, 0, (LPARAM
)buf
);
1191 SendMessageA(hQuality
, CB_SETCURSEL
, Index
, 0);
1193 SendMessageA(hQuality
, CB_SETITEMDATA
, Index
, MAKELONG(dpiX
,dpiY
));
1195 HeapFree(GetProcessHeap(), 0, Resolutions
);
1198 } else { /* PD_PRINTSETUP */
1199 BOOL bPortrait
= (lpdm
->u1
.s1
.dmOrientation
== DMORIENT_PORTRAIT
);
1201 PRINTDLG_SetUpPaperComboBoxA(hDlg
, cmb2
,
1202 PrintStructures
->lpPrinterInfo
->pPrinterName
,
1203 PrintStructures
->lpPrinterInfo
->pPortName
,
1205 PRINTDLG_SetUpPaperComboBoxA(hDlg
, cmb3
,
1206 PrintStructures
->lpPrinterInfo
->pPrinterName
,
1207 PrintStructures
->lpPrinterInfo
->pPortName
,
1209 CheckRadioButton(hDlg
, rad1
, rad2
, bPortrait
? rad1
: rad2
);
1210 SendDlgItemMessageA(hDlg
, ico1
, STM_SETIMAGE
, IMAGE_ICON
,
1211 (LPARAM
)(bPortrait
? PrintStructures
->hPortraitIcon
:
1212 PrintStructures
->hLandscapeIcon
));
1217 if ((lppd
->Flags
& PD_SHOWHELP
)==0) {
1218 /* hide if PD_SHOWHELP not specified */
1219 ShowWindow(GetDlgItem(hDlg
, pshHelp
), SW_HIDE
);
1224 static BOOL
PRINTDLG_ChangePrinterW(HWND hDlg
, WCHAR
*name
,
1225 PRINT_PTRW
*PrintStructures
)
1227 LPPRINTDLGW lppd
= PrintStructures
->lpPrintDlg
;
1228 LPDEVMODEW lpdm
= NULL
;
1233 HeapFree(GetProcessHeap(),0, PrintStructures
->lpPrinterInfo
);
1234 HeapFree(GetProcessHeap(),0, PrintStructures
->lpDriverInfo
);
1235 if(!OpenPrinterW(name
, &hprn
, NULL
)) {
1236 ERR("Can't open printer %s\n", debugstr_w(name
));
1239 GetPrinterW(hprn
, 2, NULL
, 0, &needed
);
1240 PrintStructures
->lpPrinterInfo
= HeapAlloc(GetProcessHeap(),0,needed
);
1241 GetPrinterW(hprn
, 2, (LPBYTE
)PrintStructures
->lpPrinterInfo
, needed
,
1243 GetPrinterDriverW(hprn
, NULL
, 3, NULL
, 0, &needed
);
1244 PrintStructures
->lpDriverInfo
= HeapAlloc(GetProcessHeap(),0,needed
);
1245 if (!GetPrinterDriverW(hprn
, NULL
, 3, (LPBYTE
)PrintStructures
->lpDriverInfo
,
1247 ERR("GetPrinterDriverA failed for %s, fix your config!\n",debugstr_w(PrintStructures
->lpPrinterInfo
->pPrinterName
));
1252 PRINTDLG_UpdatePrinterInfoTextsW(hDlg
, PrintStructures
->lpPrinterInfo
);
1254 HeapFree(GetProcessHeap(), 0, PrintStructures
->lpDevMode
);
1255 PrintStructures
->lpDevMode
= NULL
;
1257 dmSize
= DocumentPropertiesW(0, 0, name
, NULL
, NULL
, 0);
1259 ERR("DocumentProperties fails on %s\n", debugstr_w(name
));
1262 PrintStructures
->lpDevMode
= HeapAlloc(GetProcessHeap(), 0, dmSize
);
1263 dmSize
= DocumentPropertiesW(0, 0, name
, PrintStructures
->lpDevMode
, NULL
,
1265 if(lppd
->hDevMode
&& (lpdm
= GlobalLock(lppd
->hDevMode
)) &&
1266 !lstrcmpW(lpdm
->dmDeviceName
,
1267 PrintStructures
->lpDevMode
->dmDeviceName
)) {
1268 /* Supplied devicemode matches current printer so try to use it */
1269 DocumentPropertiesW(0, 0, name
, PrintStructures
->lpDevMode
, lpdm
,
1270 DM_OUT_BUFFER
| DM_IN_BUFFER
);
1273 GlobalUnlock(lppd
->hDevMode
);
1275 lpdm
= PrintStructures
->lpDevMode
; /* use this as a shortcut */
1277 if(!(lppd
->Flags
& PD_PRINTSETUP
)) {
1278 /* Print range (All/Range/Selection) */
1279 if(lppd
->nFromPage
!= 0xffff)
1280 SetDlgItemInt(hDlg
, edt1
, lppd
->nFromPage
, FALSE
);
1281 if(lppd
->nToPage
!= 0xffff)
1282 SetDlgItemInt(hDlg
, edt2
, lppd
->nToPage
, FALSE
);
1284 CheckRadioButton(hDlg
, rad1
, rad3
, rad1
); /* default */
1285 if (lppd
->Flags
& PD_NOSELECTION
)
1286 EnableWindow(GetDlgItem(hDlg
, rad2
), FALSE
);
1288 if (lppd
->Flags
& PD_SELECTION
)
1289 CheckRadioButton(hDlg
, rad1
, rad3
, rad2
);
1290 if (lppd
->Flags
& PD_NOPAGENUMS
) {
1291 EnableWindow(GetDlgItem(hDlg
, rad3
), FALSE
);
1292 EnableWindow(GetDlgItem(hDlg
, stc2
),FALSE
);
1293 EnableWindow(GetDlgItem(hDlg
, edt1
), FALSE
);
1294 EnableWindow(GetDlgItem(hDlg
, stc3
),FALSE
);
1295 EnableWindow(GetDlgItem(hDlg
, edt2
), FALSE
);
1297 if (lppd
->Flags
& PD_PAGENUMS
)
1298 CheckRadioButton(hDlg
, rad1
, rad3
, rad3
);
1303 * FIXME: The ico3 is not displayed for some reason. I don't know why.
1305 if (lppd
->Flags
& PD_COLLATE
) {
1306 SendDlgItemMessageW(hDlg
, ico3
, STM_SETIMAGE
, IMAGE_ICON
,
1307 (LPARAM
)PrintStructures
->hCollateIcon
);
1308 CheckDlgButton(hDlg
, chx2
, 1);
1310 SendDlgItemMessageW(hDlg
, ico3
, STM_SETIMAGE
, IMAGE_ICON
,
1311 (LPARAM
)PrintStructures
->hNoCollateIcon
);
1312 CheckDlgButton(hDlg
, chx2
, 0);
1315 if (lppd
->Flags
& PD_USEDEVMODECOPIESANDCOLLATE
) {
1316 /* if printer doesn't support it: no Collate */
1317 if (!(lpdm
->dmFields
& DM_COLLATE
)) {
1318 EnableWindow(GetDlgItem(hDlg
, chx2
), FALSE
);
1319 EnableWindow(GetDlgItem(hDlg
, ico3
), FALSE
);
1326 if (lppd
->hDevMode
== 0)
1327 copies
= lppd
->nCopies
;
1329 copies
= lpdm
->u1
.s1
.dmCopies
;
1330 if(copies
== 0) copies
= 1;
1331 else if(copies
< 0) copies
= MAX_COPIES
;
1332 SetDlgItemInt(hDlg
, edt3
, copies
, FALSE
);
1335 if (lppd
->Flags
& PD_USEDEVMODECOPIESANDCOLLATE
) {
1336 /* if printer doesn't support it: no nCopies */
1337 if (!(lpdm
->dmFields
& DM_COPIES
)) {
1338 EnableWindow(GetDlgItem(hDlg
, edt3
), FALSE
);
1339 EnableWindow(GetDlgItem(hDlg
, stc5
), FALSE
);
1344 CheckDlgButton(hDlg
, chx1
, (lppd
->Flags
& PD_PRINTTOFILE
) ? 1 : 0);
1345 if (lppd
->Flags
& PD_DISABLEPRINTTOFILE
)
1346 EnableWindow(GetDlgItem(hDlg
, chx1
), FALSE
);
1347 if (lppd
->Flags
& PD_HIDEPRINTTOFILE
)
1348 ShowWindow(GetDlgItem(hDlg
, chx1
), SW_HIDE
);
1350 } else { /* PD_PRINTSETUP */
1351 BOOL bPortrait
= (lpdm
->u1
.s1
.dmOrientation
== DMORIENT_PORTRAIT
);
1353 PRINTDLG_SetUpPaperComboBoxW(hDlg
, cmb2
,
1354 PrintStructures
->lpPrinterInfo
->pPrinterName
,
1355 PrintStructures
->lpPrinterInfo
->pPortName
,
1357 PRINTDLG_SetUpPaperComboBoxW(hDlg
, cmb3
,
1358 PrintStructures
->lpPrinterInfo
->pPrinterName
,
1359 PrintStructures
->lpPrinterInfo
->pPortName
,
1361 CheckRadioButton(hDlg
, rad1
, rad2
, bPortrait
? rad1
: rad2
);
1362 SendDlgItemMessageW(hDlg
, ico1
, STM_SETIMAGE
, IMAGE_ICON
,
1363 (LPARAM
)(bPortrait
? PrintStructures
->hPortraitIcon
:
1364 PrintStructures
->hLandscapeIcon
));
1369 if ((lppd
->Flags
& PD_SHOWHELP
)==0) {
1370 /* hide if PD_SHOWHELP not specified */
1371 ShowWindow(GetDlgItem(hDlg
, pshHelp
), SW_HIDE
);
1376 /***********************************************************************
1377 * check_printer_setup [internal]
1379 static LRESULT
check_printer_setup(HWND hDlg
)
1382 WCHAR resourcestr
[256],resultstr
[256];
1384 EnumPrintersW(PRINTER_ENUM_LOCAL
, NULL
, 2, NULL
, 0, &needed
, &num
);
1387 EnumPrintersW(PRINTER_ENUM_CONNECTIONS
, NULL
, 2, NULL
, 0, &needed
, &num
);
1393 LoadStringW(COMDLG32_hInstance
, PD32_NO_DEVICES
,resultstr
, 255);
1394 LoadStringW(COMDLG32_hInstance
, PD32_PRINT_TITLE
,resourcestr
, 255);
1395 MessageBoxW(hDlg
, resultstr
, resourcestr
,MB_OK
| MB_ICONWARNING
);
1400 /***********************************************************************
1401 * PRINTDLG_WMInitDialog [internal]
1403 static LRESULT
PRINTDLG_WMInitDialog(HWND hDlg
,
1404 PRINT_PTRA
* PrintStructures
)
1406 LPPRINTDLGA lppd
= PrintStructures
->lpPrintDlg
;
1410 UINT comboID
= (lppd
->Flags
& PD_PRINTSETUP
) ? cmb1
: cmb4
;
1412 /* load Collate ICONs */
1413 /* We load these with LoadImage because they are not a standard
1414 size and we don't want them rescaled */
1415 PrintStructures
->hCollateIcon
=
1416 LoadImageA(COMDLG32_hInstance
, "PD32_COLLATE", IMAGE_ICON
, 0, 0, 0);
1417 PrintStructures
->hNoCollateIcon
=
1418 LoadImageA(COMDLG32_hInstance
, "PD32_NOCOLLATE", IMAGE_ICON
, 0, 0, 0);
1420 /* These can be done with LoadIcon */
1421 PrintStructures
->hPortraitIcon
=
1422 LoadIconA(COMDLG32_hInstance
, "PD32_PORTRAIT");
1423 PrintStructures
->hLandscapeIcon
=
1424 LoadIconA(COMDLG32_hInstance
, "PD32_LANDSCAPE");
1426 /* display the collate/no_collate icon */
1427 SendDlgItemMessageA(hDlg
, ico3
, STM_SETIMAGE
, IMAGE_ICON
,
1428 (LPARAM
)PrintStructures
->hNoCollateIcon
);
1430 if(PrintStructures
->hCollateIcon
== 0 ||
1431 PrintStructures
->hNoCollateIcon
== 0 ||
1432 PrintStructures
->hPortraitIcon
== 0 ||
1433 PrintStructures
->hLandscapeIcon
== 0) {
1434 ERR("no icon in resourcefile\n");
1435 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
1436 EndDialog(hDlg
, FALSE
);
1440 * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
1441 * must be registered and the Help button must be shown.
1443 if (lppd
->Flags
& PD_SHOWHELP
) {
1444 if((PrintStructures
->HelpMessageID
=
1445 RegisterWindowMessageA(HELPMSGSTRINGA
)) == 0) {
1446 COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL
);
1450 PrintStructures
->HelpMessageID
= 0;
1452 if(!(lppd
->Flags
&PD_PRINTSETUP
)) {
1453 PrintStructures
->hwndUpDown
=
1454 CreateUpDownControl(WS_CHILD
| WS_VISIBLE
| WS_BORDER
|
1455 UDS_NOTHOUSANDS
| UDS_ARROWKEYS
|
1456 UDS_ALIGNRIGHT
| UDS_SETBUDDYINT
, 0, 0, 0, 0,
1457 hDlg
, UPDOWN_ID
, COMDLG32_hInstance
,
1458 GetDlgItem(hDlg
, edt3
), MAX_COPIES
, 1, 1);
1461 /* FIXME: I allow more freedom than either Win95 or WinNT,
1462 * which do not agree to what errors should be thrown or not
1463 * in case nToPage or nFromPage is out-of-range.
1465 if (lppd
->nMaxPage
< lppd
->nMinPage
)
1466 lppd
->nMaxPage
= lppd
->nMinPage
;
1467 if (lppd
->nMinPage
== lppd
->nMaxPage
)
1468 lppd
->Flags
|= PD_NOPAGENUMS
;
1469 if (lppd
->nToPage
< lppd
->nMinPage
)
1470 lppd
->nToPage
= lppd
->nMinPage
;
1471 if (lppd
->nToPage
> lppd
->nMaxPage
)
1472 lppd
->nToPage
= lppd
->nMaxPage
;
1473 if (lppd
->nFromPage
< lppd
->nMinPage
)
1474 lppd
->nFromPage
= lppd
->nMinPage
;
1475 if (lppd
->nFromPage
> lppd
->nMaxPage
)
1476 lppd
->nFromPage
= lppd
->nMaxPage
;
1478 /* if we have the combo box, fill it */
1479 if (GetDlgItem(hDlg
,comboID
)) {
1482 pdn
= GlobalLock(lppd
->hDevNames
);
1483 pdm
= GlobalLock(lppd
->hDevMode
);
1485 name
= (char*)pdn
+ pdn
->wDeviceOffset
;
1487 name
= (char*)pdm
->dmDeviceName
;
1488 PRINTDLG_SetUpPrinterListComboA(hDlg
, comboID
, name
);
1489 if(pdm
) GlobalUnlock(lppd
->hDevMode
);
1490 if(pdn
) GlobalUnlock(lppd
->hDevNames
);
1492 /* Now find selected printer and update rest of dlg */
1493 name
= HeapAlloc(GetProcessHeap(),0,256);
1494 if (GetDlgItemTextA(hDlg
, comboID
, name
, 255))
1495 PRINTDLG_ChangePrinterA(hDlg
, name
, PrintStructures
);
1496 HeapFree(GetProcessHeap(),0,name
);
1498 /* else use default printer */
1500 DWORD dwBufLen
= sizeof(name
);
1501 BOOL ret
= GetDefaultPrinterA(name
, &dwBufLen
);
1504 PRINTDLG_ChangePrinterA(hDlg
, name
, PrintStructures
);
1506 FIXME("No default printer found, expect problems!\n");
1511 static LRESULT
PRINTDLG_WMInitDialogW(HWND hDlg
,
1512 PRINT_PTRW
* PrintStructures
)
1514 LPPRINTDLGW lppd
= PrintStructures
->lpPrintDlg
;
1518 UINT comboID
= (lppd
->Flags
& PD_PRINTSETUP
) ? cmb1
: cmb4
;
1520 /* load Collate ICONs */
1521 /* We load these with LoadImage because they are not a standard
1522 size and we don't want them rescaled */
1523 PrintStructures
->hCollateIcon
=
1524 LoadImageW(COMDLG32_hInstance
, pd32_collateW
, IMAGE_ICON
, 0, 0, 0);
1525 PrintStructures
->hNoCollateIcon
=
1526 LoadImageW(COMDLG32_hInstance
, pd32_nocollateW
, IMAGE_ICON
, 0, 0, 0);
1528 /* These can be done with LoadIcon */
1529 PrintStructures
->hPortraitIcon
=
1530 LoadIconW(COMDLG32_hInstance
, pd32_portraitW
);
1531 PrintStructures
->hLandscapeIcon
=
1532 LoadIconW(COMDLG32_hInstance
, pd32_landscapeW
);
1534 /* display the collate/no_collate icon */
1535 SendDlgItemMessageW(hDlg
, ico3
, STM_SETIMAGE
, IMAGE_ICON
,
1536 (LPARAM
)PrintStructures
->hNoCollateIcon
);
1538 if(PrintStructures
->hCollateIcon
== 0 ||
1539 PrintStructures
->hNoCollateIcon
== 0 ||
1540 PrintStructures
->hPortraitIcon
== 0 ||
1541 PrintStructures
->hLandscapeIcon
== 0) {
1542 ERR("no icon in resourcefile\n");
1543 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
1544 EndDialog(hDlg
, FALSE
);
1548 * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
1549 * must be registered and the Help button must be shown.
1551 if (lppd
->Flags
& PD_SHOWHELP
) {
1552 if((PrintStructures
->HelpMessageID
=
1553 RegisterWindowMessageW(HELPMSGSTRINGW
)) == 0) {
1554 COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL
);
1558 PrintStructures
->HelpMessageID
= 0;
1560 if(!(lppd
->Flags
&PD_PRINTSETUP
)) {
1561 PrintStructures
->hwndUpDown
=
1562 CreateUpDownControl(WS_CHILD
| WS_VISIBLE
| WS_BORDER
|
1563 UDS_NOTHOUSANDS
| UDS_ARROWKEYS
|
1564 UDS_ALIGNRIGHT
| UDS_SETBUDDYINT
, 0, 0, 0, 0,
1565 hDlg
, UPDOWN_ID
, COMDLG32_hInstance
,
1566 GetDlgItem(hDlg
, edt3
), MAX_COPIES
, 1, 1);
1569 /* FIXME: I allow more freedom than either Win95 or WinNT,
1570 * which do not agree to what errors should be thrown or not
1571 * in case nToPage or nFromPage is out-of-range.
1573 if (lppd
->nMaxPage
< lppd
->nMinPage
)
1574 lppd
->nMaxPage
= lppd
->nMinPage
;
1575 if (lppd
->nMinPage
== lppd
->nMaxPage
)
1576 lppd
->Flags
|= PD_NOPAGENUMS
;
1577 if (lppd
->nToPage
< lppd
->nMinPage
)
1578 lppd
->nToPage
= lppd
->nMinPage
;
1579 if (lppd
->nToPage
> lppd
->nMaxPage
)
1580 lppd
->nToPage
= lppd
->nMaxPage
;
1581 if (lppd
->nFromPage
< lppd
->nMinPage
)
1582 lppd
->nFromPage
= lppd
->nMinPage
;
1583 if (lppd
->nFromPage
> lppd
->nMaxPage
)
1584 lppd
->nFromPage
= lppd
->nMaxPage
;
1586 /* if we have the combo box, fill it */
1587 if (GetDlgItem(hDlg
,comboID
)) {
1590 pdn
= GlobalLock(lppd
->hDevNames
);
1591 pdm
= GlobalLock(lppd
->hDevMode
);
1593 name
= (WCHAR
*)pdn
+ pdn
->wDeviceOffset
;
1595 name
= pdm
->dmDeviceName
;
1596 PRINTDLG_SetUpPrinterListComboW(hDlg
, comboID
, name
);
1597 if(pdm
) GlobalUnlock(lppd
->hDevMode
);
1598 if(pdn
) GlobalUnlock(lppd
->hDevNames
);
1600 /* Now find selected printer and update rest of dlg */
1601 /* ansi is ok here */
1602 name
= HeapAlloc(GetProcessHeap(),0,256*sizeof(WCHAR
));
1603 if (GetDlgItemTextW(hDlg
, comboID
, name
, 255))
1604 PRINTDLG_ChangePrinterW(hDlg
, name
, PrintStructures
);
1605 HeapFree(GetProcessHeap(),0,name
);
1607 /* else use default printer */
1609 DWORD dwBufLen
= sizeof(name
) / sizeof(WCHAR
);
1610 BOOL ret
= GetDefaultPrinterW(name
, &dwBufLen
);
1613 PRINTDLG_ChangePrinterW(hDlg
, name
, PrintStructures
);
1615 FIXME("No default printer found, expect problems!\n");
1620 /***********************************************************************
1621 * PRINTDLG_WMCommand [internal]
1623 static LRESULT
PRINTDLG_WMCommandA(HWND hDlg
, WPARAM wParam
,
1624 PRINT_PTRA
* PrintStructures
)
1626 LPPRINTDLGA lppd
= PrintStructures
->lpPrintDlg
;
1627 UINT PrinterComboID
= (lppd
->Flags
& PD_PRINTSETUP
) ? cmb1
: cmb4
;
1628 LPDEVMODEA lpdm
= PrintStructures
->lpDevMode
;
1630 switch (LOWORD(wParam
)) {
1632 TRACE(" OK button was hit\n");
1633 if (!PRINTDLG_UpdatePrintDlgA(hDlg
, PrintStructures
)) {
1634 FIXME("Update printdlg was not successful!\n");
1637 EndDialog(hDlg
, TRUE
);
1641 TRACE(" CANCEL button was hit\n");
1642 EndDialog(hDlg
, FALSE
);
1646 TRACE(" HELP button was hit\n");
1647 SendMessageA(lppd
->hwndOwner
, PrintStructures
->HelpMessageID
,
1648 (WPARAM
) hDlg
, (LPARAM
) lppd
);
1651 case chx2
: /* collate pages checkbox */
1652 if (IsDlgButtonChecked(hDlg
, chx2
) == BST_CHECKED
)
1653 SendDlgItemMessageA(hDlg
, ico3
, STM_SETIMAGE
, IMAGE_ICON
,
1654 (LPARAM
)PrintStructures
->hCollateIcon
);
1656 SendDlgItemMessageA(hDlg
, ico3
, STM_SETIMAGE
, IMAGE_ICON
,
1657 (LPARAM
)PrintStructures
->hNoCollateIcon
);
1659 case edt1
: /* from page nr editbox */
1660 case edt2
: /* to page nr editbox */
1661 if (HIWORD(wParam
)==EN_CHANGE
) {
1664 nFromPage
= GetDlgItemInt(hDlg
, edt1
, NULL
, FALSE
);
1665 nToPage
= GetDlgItemInt(hDlg
, edt2
, NULL
, FALSE
);
1666 if (nFromPage
!= lppd
->nFromPage
|| nToPage
!= lppd
->nToPage
)
1667 CheckRadioButton(hDlg
, rad1
, rad3
, rad3
);
1672 if(HIWORD(wParam
) == EN_CHANGE
) {
1673 INT copies
= GetDlgItemInt(hDlg
, edt3
, NULL
, FALSE
);
1675 EnableWindow(GetDlgItem(hDlg
, chx2
), FALSE
);
1677 EnableWindow(GetDlgItem(hDlg
, chx2
), TRUE
);
1681 case psh2
: /* Properties button */
1684 char PrinterName
[256];
1686 GetDlgItemTextA(hDlg
, PrinterComboID
, PrinterName
, 255);
1687 if (!OpenPrinterA(PrinterName
, &hPrinter
, NULL
)) {
1688 FIXME(" Call to OpenPrinter did not succeed!\n");
1691 DocumentPropertiesA(hDlg
, hPrinter
, PrinterName
,
1692 PrintStructures
->lpDevMode
,
1693 PrintStructures
->lpDevMode
,
1694 DM_IN_BUFFER
| DM_OUT_BUFFER
| DM_IN_PROMPT
);
1695 ClosePrinter(hPrinter
);
1699 case rad1
: /* Paperorientation */
1700 if (lppd
->Flags
& PD_PRINTSETUP
)
1702 lpdm
->u1
.s1
.dmOrientation
= DMORIENT_PORTRAIT
;
1703 SendDlgItemMessageA(hDlg
, ico1
, STM_SETIMAGE
, IMAGE_ICON
,
1704 (LPARAM
)(PrintStructures
->hPortraitIcon
));
1708 case rad2
: /* Paperorientation */
1709 if (lppd
->Flags
& PD_PRINTSETUP
)
1711 lpdm
->u1
.s1
.dmOrientation
= DMORIENT_LANDSCAPE
;
1712 SendDlgItemMessageA(hDlg
, ico1
, STM_SETIMAGE
, IMAGE_ICON
,
1713 (LPARAM
)(PrintStructures
->hLandscapeIcon
));
1717 case cmb1
: /* Printer Combobox in PRINT SETUP, quality combobox in PRINT16 */
1718 if (PrinterComboID
!= LOWORD(wParam
)) {
1722 case cmb4
: /* Printer combobox */
1723 if (HIWORD(wParam
)==CBN_SELCHANGE
) {
1724 char PrinterName
[256];
1725 GetDlgItemTextA(hDlg
, LOWORD(wParam
), PrinterName
, 255);
1726 PRINTDLG_ChangePrinterA(hDlg
, PrinterName
, PrintStructures
);
1730 case cmb2
: /* Papersize */
1732 DWORD Sel
= SendDlgItemMessageA(hDlg
, cmb2
, CB_GETCURSEL
, 0, 0);
1734 lpdm
->u1
.s1
.dmPaperSize
= SendDlgItemMessageA(hDlg
, cmb2
,
1740 case cmb3
: /* Bin */
1742 DWORD Sel
= SendDlgItemMessageA(hDlg
, cmb3
, CB_GETCURSEL
, 0, 0);
1744 lpdm
->u1
.s1
.dmDefaultSource
= SendDlgItemMessageA(hDlg
, cmb3
,
1745 CB_GETITEMDATA
, Sel
,
1750 if(lppd
->Flags
& PD_PRINTSETUP
) {
1751 switch (LOWORD(wParam
)) {
1752 case rad1
: /* orientation */
1754 if (IsDlgButtonChecked(hDlg
, rad1
) == BST_CHECKED
) {
1755 if(lpdm
->u1
.s1
.dmOrientation
!= DMORIENT_PORTRAIT
) {
1756 lpdm
->u1
.s1
.dmOrientation
= DMORIENT_PORTRAIT
;
1757 SendDlgItemMessageA(hDlg
, stc10
, STM_SETIMAGE
, IMAGE_ICON
,
1758 (LPARAM
)PrintStructures
->hPortraitIcon
);
1759 SendDlgItemMessageA(hDlg
, ico1
, STM_SETIMAGE
, IMAGE_ICON
,
1760 (LPARAM
)PrintStructures
->hPortraitIcon
);
1763 if(lpdm
->u1
.s1
.dmOrientation
!= DMORIENT_LANDSCAPE
) {
1764 lpdm
->u1
.s1
.dmOrientation
= DMORIENT_LANDSCAPE
;
1765 SendDlgItemMessageA(hDlg
, stc10
, STM_SETIMAGE
, IMAGE_ICON
,
1766 (LPARAM
)PrintStructures
->hLandscapeIcon
);
1767 SendDlgItemMessageA(hDlg
, ico1
, STM_SETIMAGE
, IMAGE_ICON
,
1768 (LPARAM
)PrintStructures
->hLandscapeIcon
);
1777 static LRESULT
PRINTDLG_WMCommandW(HWND hDlg
, WPARAM wParam
,
1778 PRINT_PTRW
* PrintStructures
)
1780 LPPRINTDLGW lppd
= PrintStructures
->lpPrintDlg
;
1781 UINT PrinterComboID
= (lppd
->Flags
& PD_PRINTSETUP
) ? cmb1
: cmb4
;
1782 LPDEVMODEW lpdm
= PrintStructures
->lpDevMode
;
1784 switch (LOWORD(wParam
)) {
1786 TRACE(" OK button was hit\n");
1787 if (!PRINTDLG_UpdatePrintDlgW(hDlg
, PrintStructures
)) {
1788 FIXME("Update printdlg was not successful!\n");
1791 EndDialog(hDlg
, TRUE
);
1795 TRACE(" CANCEL button was hit\n");
1796 EndDialog(hDlg
, FALSE
);
1800 TRACE(" HELP button was hit\n");
1801 SendMessageW(lppd
->hwndOwner
, PrintStructures
->HelpMessageID
,
1802 (WPARAM
) hDlg
, (LPARAM
) lppd
);
1805 case chx2
: /* collate pages checkbox */
1806 if (IsDlgButtonChecked(hDlg
, chx2
) == BST_CHECKED
)
1807 SendDlgItemMessageW(hDlg
, ico3
, STM_SETIMAGE
, IMAGE_ICON
,
1808 (LPARAM
)PrintStructures
->hCollateIcon
);
1810 SendDlgItemMessageW(hDlg
, ico3
, STM_SETIMAGE
, IMAGE_ICON
,
1811 (LPARAM
)PrintStructures
->hNoCollateIcon
);
1813 case edt1
: /* from page nr editbox */
1814 case edt2
: /* to page nr editbox */
1815 if (HIWORD(wParam
)==EN_CHANGE
) {
1818 nFromPage
= GetDlgItemInt(hDlg
, edt1
, NULL
, FALSE
);
1819 nToPage
= GetDlgItemInt(hDlg
, edt2
, NULL
, FALSE
);
1820 if (nFromPage
!= lppd
->nFromPage
|| nToPage
!= lppd
->nToPage
)
1821 CheckRadioButton(hDlg
, rad1
, rad3
, rad3
);
1826 if(HIWORD(wParam
) == EN_CHANGE
) {
1827 INT copies
= GetDlgItemInt(hDlg
, edt3
, NULL
, FALSE
);
1829 EnableWindow(GetDlgItem(hDlg
, chx2
), FALSE
);
1831 EnableWindow(GetDlgItem(hDlg
, chx2
), TRUE
);
1835 case psh2
: /* Properties button */
1838 WCHAR PrinterName
[256];
1840 if (!GetDlgItemTextW(hDlg
, PrinterComboID
, PrinterName
, 255)) break;
1841 if (!OpenPrinterW(PrinterName
, &hPrinter
, NULL
)) {
1842 FIXME(" Call to OpenPrinter did not succeed!\n");
1845 DocumentPropertiesW(hDlg
, hPrinter
, PrinterName
,
1846 PrintStructures
->lpDevMode
,
1847 PrintStructures
->lpDevMode
,
1848 DM_IN_BUFFER
| DM_OUT_BUFFER
| DM_IN_PROMPT
);
1849 ClosePrinter(hPrinter
);
1853 case rad1
: /* Paperorientation */
1854 if (lppd
->Flags
& PD_PRINTSETUP
)
1856 lpdm
->u1
.s1
.dmOrientation
= DMORIENT_PORTRAIT
;
1857 SendDlgItemMessageW(hDlg
, ico1
, STM_SETIMAGE
, IMAGE_ICON
,
1858 (LPARAM
)(PrintStructures
->hPortraitIcon
));
1862 case rad2
: /* Paperorientation */
1863 if (lppd
->Flags
& PD_PRINTSETUP
)
1865 lpdm
->u1
.s1
.dmOrientation
= DMORIENT_LANDSCAPE
;
1866 SendDlgItemMessageW(hDlg
, ico1
, STM_SETIMAGE
, IMAGE_ICON
,
1867 (LPARAM
)(PrintStructures
->hLandscapeIcon
));
1871 case cmb1
: /* Printer Combobox in PRINT SETUP */
1873 case cmb4
: /* Printer combobox */
1874 if (HIWORD(wParam
)==CBN_SELCHANGE
) {
1875 WCHAR PrinterName
[256];
1876 GetDlgItemTextW(hDlg
, LOWORD(wParam
), PrinterName
, 255);
1877 PRINTDLG_ChangePrinterW(hDlg
, PrinterName
, PrintStructures
);
1881 case cmb2
: /* Papersize */
1883 DWORD Sel
= SendDlgItemMessageW(hDlg
, cmb2
, CB_GETCURSEL
, 0, 0);
1885 lpdm
->u1
.s1
.dmPaperSize
= SendDlgItemMessageW(hDlg
, cmb2
,
1891 case cmb3
: /* Bin */
1893 DWORD Sel
= SendDlgItemMessageW(hDlg
, cmb3
, CB_GETCURSEL
, 0, 0);
1895 lpdm
->u1
.s1
.dmDefaultSource
= SendDlgItemMessageW(hDlg
, cmb3
,
1896 CB_GETITEMDATA
, Sel
,
1901 if(lppd
->Flags
& PD_PRINTSETUP
) {
1902 switch (LOWORD(wParam
)) {
1903 case rad1
: /* orientation */
1905 if (IsDlgButtonChecked(hDlg
, rad1
) == BST_CHECKED
) {
1906 if(lpdm
->u1
.s1
.dmOrientation
!= DMORIENT_PORTRAIT
) {
1907 lpdm
->u1
.s1
.dmOrientation
= DMORIENT_PORTRAIT
;
1908 SendDlgItemMessageW(hDlg
, stc10
, STM_SETIMAGE
, IMAGE_ICON
,
1909 (LPARAM
)PrintStructures
->hPortraitIcon
);
1910 SendDlgItemMessageW(hDlg
, ico1
, STM_SETIMAGE
, IMAGE_ICON
,
1911 (LPARAM
)PrintStructures
->hPortraitIcon
);
1914 if(lpdm
->u1
.s1
.dmOrientation
!= DMORIENT_LANDSCAPE
) {
1915 lpdm
->u1
.s1
.dmOrientation
= DMORIENT_LANDSCAPE
;
1916 SendDlgItemMessageW(hDlg
, stc10
, STM_SETIMAGE
, IMAGE_ICON
,
1917 (LPARAM
)PrintStructures
->hLandscapeIcon
);
1918 SendDlgItemMessageW(hDlg
, ico1
, STM_SETIMAGE
, IMAGE_ICON
,
1919 (LPARAM
)PrintStructures
->hLandscapeIcon
);
1928 /***********************************************************************
1929 * PrintDlgProcA [internal]
1931 static INT_PTR CALLBACK
PrintDlgProcA(HWND hDlg
, UINT uMsg
, WPARAM wParam
,
1934 PRINT_PTRA
* PrintStructures
;
1935 INT_PTR res
= FALSE
;
1937 if (uMsg
!=WM_INITDIALOG
) {
1938 PrintStructures
= GetPropW(hDlg
, printdlg_prop
);
1939 if (!PrintStructures
)
1942 PrintStructures
= (PRINT_PTRA
*) lParam
;
1943 SetPropW(hDlg
, printdlg_prop
, PrintStructures
);
1944 if(!check_printer_setup(hDlg
))
1946 EndDialog(hDlg
,FALSE
);
1949 res
= PRINTDLG_WMInitDialog(hDlg
, PrintStructures
);
1951 if(PrintStructures
->lpPrintDlg
->Flags
& PD_ENABLEPRINTHOOK
)
1952 res
= PrintStructures
->lpPrintDlg
->lpfnPrintHook(
1953 hDlg
, uMsg
, wParam
, (LPARAM
)PrintStructures
->lpPrintDlg
1958 if(PrintStructures
->lpPrintDlg
->Flags
& PD_ENABLEPRINTHOOK
) {
1959 res
= PrintStructures
->lpPrintDlg
->lpfnPrintHook(hDlg
,uMsg
,wParam
,
1966 return PRINTDLG_WMCommandA(hDlg
, wParam
, PrintStructures
);
1969 DestroyIcon(PrintStructures
->hCollateIcon
);
1970 DestroyIcon(PrintStructures
->hNoCollateIcon
);
1971 DestroyIcon(PrintStructures
->hPortraitIcon
);
1972 DestroyIcon(PrintStructures
->hLandscapeIcon
);
1973 if(PrintStructures
->hwndUpDown
)
1974 DestroyWindow(PrintStructures
->hwndUpDown
);
1980 static INT_PTR CALLBACK
PrintDlgProcW(HWND hDlg
, UINT uMsg
, WPARAM wParam
,
1983 PRINT_PTRW
* PrintStructures
;
1984 INT_PTR res
= FALSE
;
1986 if (uMsg
!=WM_INITDIALOG
) {
1987 PrintStructures
= GetPropW(hDlg
, printdlg_prop
);
1988 if (!PrintStructures
)
1991 PrintStructures
= (PRINT_PTRW
*) lParam
;
1992 SetPropW(hDlg
, printdlg_prop
, PrintStructures
);
1993 if(!check_printer_setup(hDlg
))
1995 EndDialog(hDlg
,FALSE
);
1998 res
= PRINTDLG_WMInitDialogW(hDlg
, PrintStructures
);
2000 if(PrintStructures
->lpPrintDlg
->Flags
& PD_ENABLEPRINTHOOK
)
2001 res
= PrintStructures
->lpPrintDlg
->lpfnPrintHook(hDlg
, uMsg
, wParam
, (LPARAM
)PrintStructures
->lpPrintDlg
);
2005 if(PrintStructures
->lpPrintDlg
->Flags
& PD_ENABLEPRINTHOOK
) {
2006 res
= PrintStructures
->lpPrintDlg
->lpfnPrintHook(hDlg
,uMsg
,wParam
, lParam
);
2012 return PRINTDLG_WMCommandW(hDlg
, wParam
, PrintStructures
);
2015 DestroyIcon(PrintStructures
->hCollateIcon
);
2016 DestroyIcon(PrintStructures
->hNoCollateIcon
);
2017 DestroyIcon(PrintStructures
->hPortraitIcon
);
2018 DestroyIcon(PrintStructures
->hLandscapeIcon
);
2019 if(PrintStructures
->hwndUpDown
)
2020 DestroyWindow(PrintStructures
->hwndUpDown
);
2026 /************************************************************
2028 * PRINTDLG_GetDlgTemplate
2031 static HGLOBAL
PRINTDLG_GetDlgTemplateA(const PRINTDLGA
*lppd
)
2036 if (lppd
->Flags
& PD_PRINTSETUP
) {
2037 if(lppd
->Flags
& PD_ENABLESETUPTEMPLATEHANDLE
) {
2038 hDlgTmpl
= lppd
->hSetupTemplate
;
2039 } else if(lppd
->Flags
& PD_ENABLESETUPTEMPLATE
) {
2040 hResInfo
= FindResourceA(lppd
->hInstance
,
2041 lppd
->lpSetupTemplateName
, (LPSTR
)RT_DIALOG
);
2042 hDlgTmpl
= LoadResource(lppd
->hInstance
, hResInfo
);
2044 hResInfo
= FindResourceA(COMDLG32_hInstance
, "PRINT32_SETUP",
2046 hDlgTmpl
= LoadResource(COMDLG32_hInstance
, hResInfo
);
2049 if(lppd
->Flags
& PD_ENABLEPRINTTEMPLATEHANDLE
) {
2050 hDlgTmpl
= lppd
->hPrintTemplate
;
2051 } else if(lppd
->Flags
& PD_ENABLEPRINTTEMPLATE
) {
2052 hResInfo
= FindResourceA(lppd
->hInstance
,
2053 lppd
->lpPrintTemplateName
,
2055 hDlgTmpl
= LoadResource(lppd
->hInstance
, hResInfo
);
2057 hResInfo
= FindResourceA(COMDLG32_hInstance
, "PRINT32",
2059 hDlgTmpl
= LoadResource(COMDLG32_hInstance
, hResInfo
);
2065 static HGLOBAL
PRINTDLG_GetDlgTemplateW(const PRINTDLGW
*lppd
)
2069 static const WCHAR xpsetup
[] = { 'P','R','I','N','T','3','2','_','S','E','T','U','P',0};
2070 static const WCHAR xprint
[] = { 'P','R','I','N','T','3','2',0};
2072 if (lppd
->Flags
& PD_PRINTSETUP
) {
2073 if(lppd
->Flags
& PD_ENABLESETUPTEMPLATEHANDLE
) {
2074 hDlgTmpl
= lppd
->hSetupTemplate
;
2075 } else if(lppd
->Flags
& PD_ENABLESETUPTEMPLATE
) {
2076 hResInfo
= FindResourceW(lppd
->hInstance
,
2077 lppd
->lpSetupTemplateName
, (LPWSTR
)RT_DIALOG
);
2078 hDlgTmpl
= LoadResource(lppd
->hInstance
, hResInfo
);
2080 hResInfo
= FindResourceW(COMDLG32_hInstance
, xpsetup
, (LPWSTR
)RT_DIALOG
);
2081 hDlgTmpl
= LoadResource(COMDLG32_hInstance
, hResInfo
);
2084 if(lppd
->Flags
& PD_ENABLEPRINTTEMPLATEHANDLE
) {
2085 hDlgTmpl
= lppd
->hPrintTemplate
;
2086 } else if(lppd
->Flags
& PD_ENABLEPRINTTEMPLATE
) {
2087 hResInfo
= FindResourceW(lppd
->hInstance
,
2088 lppd
->lpPrintTemplateName
,
2090 hDlgTmpl
= LoadResource(lppd
->hInstance
, hResInfo
);
2092 hResInfo
= FindResourceW(COMDLG32_hInstance
, xprint
, (LPWSTR
)RT_DIALOG
);
2093 hDlgTmpl
= LoadResource(COMDLG32_hInstance
, hResInfo
);
2099 /***********************************************************************
2104 static BOOL
PRINTDLG_CreateDCA(LPPRINTDLGA lppd
)
2106 DEVNAMES
*pdn
= GlobalLock(lppd
->hDevNames
);
2107 DEVMODEA
*pdm
= GlobalLock(lppd
->hDevMode
);
2109 if(lppd
->Flags
& PD_RETURNDC
) {
2110 lppd
->hDC
= CreateDCA((char*)pdn
+ pdn
->wDriverOffset
,
2111 (char*)pdn
+ pdn
->wDeviceOffset
,
2112 (char*)pdn
+ pdn
->wOutputOffset
,
2114 } else if(lppd
->Flags
& PD_RETURNIC
) {
2115 lppd
->hDC
= CreateICA((char*)pdn
+ pdn
->wDriverOffset
,
2116 (char*)pdn
+ pdn
->wDeviceOffset
,
2117 (char*)pdn
+ pdn
->wOutputOffset
,
2120 GlobalUnlock(lppd
->hDevNames
);
2121 GlobalUnlock(lppd
->hDevMode
);
2122 return lppd
->hDC
? TRUE
: FALSE
;
2125 static BOOL
PRINTDLG_CreateDCW(LPPRINTDLGW lppd
)
2127 DEVNAMES
*pdn
= GlobalLock(lppd
->hDevNames
);
2128 DEVMODEW
*pdm
= GlobalLock(lppd
->hDevMode
);
2130 if(lppd
->Flags
& PD_RETURNDC
) {
2131 lppd
->hDC
= CreateDCW((WCHAR
*)pdn
+ pdn
->wDriverOffset
,
2132 (WCHAR
*)pdn
+ pdn
->wDeviceOffset
,
2133 (WCHAR
*)pdn
+ pdn
->wOutputOffset
,
2135 } else if(lppd
->Flags
& PD_RETURNIC
) {
2136 lppd
->hDC
= CreateICW((WCHAR
*)pdn
+ pdn
->wDriverOffset
,
2137 (WCHAR
*)pdn
+ pdn
->wDeviceOffset
,
2138 (WCHAR
*)pdn
+ pdn
->wOutputOffset
,
2141 GlobalUnlock(lppd
->hDevNames
);
2142 GlobalUnlock(lppd
->hDevMode
);
2143 return lppd
->hDC
? TRUE
: FALSE
;
2146 /***********************************************************************
2147 * PrintDlgA (COMDLG32.@)
2149 * Displays the PRINT dialog box, which enables the user to specify
2150 * specific properties of the print job.
2153 * lppd [IO] ptr to PRINTDLG32 struct
2156 * nonzero if the user pressed the OK button
2157 * zero if the user cancelled the window or an error occurred
2161 * * The Collate Icons do not display, even though they are in the code.
2162 * * The Properties Button(s) should call DocumentPropertiesA().
2165 BOOL WINAPI
PrintDlgA(LPPRINTDLGA lppd
)
2173 COMDLG32_SetCommDlgExtendedError(CDERR_INITIALIZATION
);
2177 if(TRACE_ON(commdlg
)) {
2178 char flagstr
[1000] = "";
2179 const struct pd_flags
*pflag
= pd_flags
;
2180 for( ; pflag
->name
; pflag
++) {
2181 if(lppd
->Flags
& pflag
->flag
)
2182 strcat(flagstr
, pflag
->name
);
2184 TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
2185 "pp. %d-%d, min p %d, max p %d, copies %d, hinst %p\n"
2186 "flags %08x (%s)\n",
2187 lppd
, lppd
->hwndOwner
, lppd
->hDevMode
, lppd
->hDevNames
,
2188 lppd
->nFromPage
, lppd
->nToPage
, lppd
->nMinPage
, lppd
->nMaxPage
,
2189 lppd
->nCopies
, lppd
->hInstance
, lppd
->Flags
, flagstr
);
2192 if(lppd
->lStructSize
!= sizeof(PRINTDLGA
)) {
2193 WARN("structure size failure !!!\n");
2194 COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE
);
2198 if(lppd
->Flags
& PD_RETURNDEFAULT
) {
2199 PRINTER_INFO_2A
*pbuf
;
2200 DRIVER_INFO_3A
*dbuf
;
2204 if(lppd
->hDevMode
|| lppd
->hDevNames
) {
2205 WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
2206 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE
);
2209 if(!PRINTDLG_OpenDefaultPrinter(&hprn
)) {
2210 WARN("Can't find default printer\n");
2211 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN
);
2215 GetPrinterA(hprn
, 2, NULL
, 0, &needed
);
2216 pbuf
= HeapAlloc(GetProcessHeap(), 0, needed
);
2217 GetPrinterA(hprn
, 2, (LPBYTE
)pbuf
, needed
, &needed
);
2219 GetPrinterDriverA(hprn
, NULL
, 3, NULL
, 0, &needed
);
2220 dbuf
= HeapAlloc(GetProcessHeap(),0,needed
);
2221 if (!GetPrinterDriverA(hprn
, NULL
, 3, (LPBYTE
)dbuf
, needed
, &needed
)) {
2222 ERR("GetPrinterDriverA failed, le %d, fix your config for printer %s!\n",
2223 GetLastError(),pbuf
->pPrinterName
);
2224 HeapFree(GetProcessHeap(), 0, dbuf
);
2225 HeapFree(GetProcessHeap(), 0, pbuf
);
2226 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE
);
2231 PRINTDLG_CreateDevNames(&(lppd
->hDevNames
),
2235 lppd
->hDevMode
= GlobalAlloc(GMEM_MOVEABLE
, pbuf
->pDevMode
->dmSize
+
2236 pbuf
->pDevMode
->dmDriverExtra
);
2237 ptr
= GlobalLock(lppd
->hDevMode
);
2238 memcpy(ptr
, pbuf
->pDevMode
, pbuf
->pDevMode
->dmSize
+
2239 pbuf
->pDevMode
->dmDriverExtra
);
2240 GlobalUnlock(lppd
->hDevMode
);
2241 HeapFree(GetProcessHeap(), 0, pbuf
);
2242 HeapFree(GetProcessHeap(), 0, dbuf
);
2246 PRINT_PTRA
*PrintStructures
;
2248 /* load Dialog resources,
2249 * depending on Flags indicates Print32 or Print32_setup dialog
2251 hDlgTmpl
= PRINTDLG_GetDlgTemplateA(lppd
);
2253 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
2256 ptr
= LockResource( hDlgTmpl
);
2258 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
2262 PrintStructures
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2263 sizeof(PRINT_PTRA
));
2264 PrintStructures
->lpPrintDlg
= lppd
;
2266 /* and create & process the dialog .
2267 * -1 is failure, 0 is broken hwnd, everything else is ok.
2269 hInst
= COMDLG32_hInstance
;
2270 if (lppd
->Flags
& (PD_ENABLESETUPTEMPLATE
| PD_ENABLEPRINTTEMPLATE
)) hInst
= lppd
->hInstance
;
2271 bRet
= (0<DialogBoxIndirectParamA(hInst
, ptr
, lppd
->hwndOwner
,
2273 (LPARAM
)PrintStructures
));
2276 DEVMODEA
*lpdm
= PrintStructures
->lpDevMode
, *lpdmReturn
;
2277 PRINTER_INFO_2A
*pi
= PrintStructures
->lpPrinterInfo
;
2278 DRIVER_INFO_3A
*di
= PrintStructures
->lpDriverInfo
;
2280 if (lppd
->hDevMode
== 0) {
2281 TRACE(" No hDevMode yet... Need to create my own\n");
2282 lppd
->hDevMode
= GlobalAlloc(GMEM_MOVEABLE
,
2283 lpdm
->dmSize
+ lpdm
->dmDriverExtra
);
2285 lppd
->hDevMode
= GlobalReAlloc(lppd
->hDevMode
,
2286 lpdm
->dmSize
+ lpdm
->dmDriverExtra
,
2289 lpdmReturn
= GlobalLock(lppd
->hDevMode
);
2290 memcpy(lpdmReturn
, lpdm
, lpdm
->dmSize
+ lpdm
->dmDriverExtra
);
2292 PRINTDLG_CreateDevNames(&(lppd
->hDevNames
),
2297 GlobalUnlock(lppd
->hDevMode
);
2299 HeapFree(GetProcessHeap(), 0, PrintStructures
->lpDevMode
);
2300 HeapFree(GetProcessHeap(), 0, PrintStructures
->lpPrinterInfo
);
2301 HeapFree(GetProcessHeap(), 0, PrintStructures
->lpDriverInfo
);
2302 HeapFree(GetProcessHeap(), 0, PrintStructures
);
2304 if(bRet
&& (lppd
->Flags
& PD_RETURNDC
|| lppd
->Flags
& PD_RETURNIC
))
2305 bRet
= PRINTDLG_CreateDCA(lppd
);
2307 TRACE("exit! (%d)\n", bRet
);
2311 /***********************************************************************
2312 * PrintDlgW (COMDLG32.@)
2316 BOOL WINAPI
PrintDlgW(LPPRINTDLGW lppd
)
2324 COMDLG32_SetCommDlgExtendedError(CDERR_INITIALIZATION
);
2328 if(TRACE_ON(commdlg
)) {
2329 char flagstr
[1000] = "";
2330 const struct pd_flags
*pflag
= pd_flags
;
2331 for( ; pflag
->name
; pflag
++) {
2332 if(lppd
->Flags
& pflag
->flag
)
2333 strcat(flagstr
, pflag
->name
);
2335 TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
2336 "pp. %d-%d, min p %d, max p %d, copies %d, hinst %p\n"
2337 "flags %08x (%s)\n",
2338 lppd
, lppd
->hwndOwner
, lppd
->hDevMode
, lppd
->hDevNames
,
2339 lppd
->nFromPage
, lppd
->nToPage
, lppd
->nMinPage
, lppd
->nMaxPage
,
2340 lppd
->nCopies
, lppd
->hInstance
, lppd
->Flags
, flagstr
);
2343 if(lppd
->lStructSize
!= sizeof(PRINTDLGW
)) {
2344 WARN("structure size failure !!!\n");
2345 COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE
);
2349 if(lppd
->Flags
& PD_RETURNDEFAULT
) {
2350 PRINTER_INFO_2W
*pbuf
;
2351 DRIVER_INFO_3W
*dbuf
;
2355 if(lppd
->hDevMode
|| lppd
->hDevNames
) {
2356 WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
2357 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE
);
2360 if(!PRINTDLG_OpenDefaultPrinter(&hprn
)) {
2361 WARN("Can't find default printer\n");
2362 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN
);
2366 GetPrinterW(hprn
, 2, NULL
, 0, &needed
);
2367 pbuf
= HeapAlloc(GetProcessHeap(), 0, needed
);
2368 GetPrinterW(hprn
, 2, (LPBYTE
)pbuf
, needed
, &needed
);
2370 GetPrinterDriverW(hprn
, NULL
, 3, NULL
, 0, &needed
);
2371 dbuf
= HeapAlloc(GetProcessHeap(),0,needed
);
2372 if (!GetPrinterDriverW(hprn
, NULL
, 3, (LPBYTE
)dbuf
, needed
, &needed
)) {
2373 ERR("GetPrinterDriverA failed, le %d, fix your config for printer %s!\n",
2374 GetLastError(),debugstr_w(pbuf
->pPrinterName
));
2375 HeapFree(GetProcessHeap(), 0, dbuf
);
2376 HeapFree(GetProcessHeap(), 0, pbuf
);
2377 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE
);
2382 PRINTDLG_CreateDevNamesW(&(lppd
->hDevNames
),
2386 lppd
->hDevMode
= GlobalAlloc(GMEM_MOVEABLE
, pbuf
->pDevMode
->dmSize
+
2387 pbuf
->pDevMode
->dmDriverExtra
);
2388 ptr
= GlobalLock(lppd
->hDevMode
);
2389 memcpy(ptr
, pbuf
->pDevMode
, pbuf
->pDevMode
->dmSize
+
2390 pbuf
->pDevMode
->dmDriverExtra
);
2391 GlobalUnlock(lppd
->hDevMode
);
2392 HeapFree(GetProcessHeap(), 0, pbuf
);
2393 HeapFree(GetProcessHeap(), 0, dbuf
);
2397 PRINT_PTRW
*PrintStructures
;
2399 /* load Dialog resources,
2400 * depending on Flags indicates Print32 or Print32_setup dialog
2402 hDlgTmpl
= PRINTDLG_GetDlgTemplateW(lppd
);
2404 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
2407 ptr
= LockResource( hDlgTmpl
);
2409 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
2413 PrintStructures
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2414 sizeof(PRINT_PTRW
));
2415 PrintStructures
->lpPrintDlg
= lppd
;
2417 /* and create & process the dialog .
2418 * -1 is failure, 0 is broken hwnd, everything else is ok.
2420 hInst
= COMDLG32_hInstance
;
2421 if (lppd
->Flags
& (PD_ENABLESETUPTEMPLATE
| PD_ENABLEPRINTTEMPLATE
)) hInst
= lppd
->hInstance
;
2422 bRet
= (0<DialogBoxIndirectParamW(hInst
, ptr
, lppd
->hwndOwner
,
2424 (LPARAM
)PrintStructures
));
2427 DEVMODEW
*lpdm
= PrintStructures
->lpDevMode
, *lpdmReturn
;
2428 PRINTER_INFO_2W
*pi
= PrintStructures
->lpPrinterInfo
;
2429 DRIVER_INFO_3W
*di
= PrintStructures
->lpDriverInfo
;
2431 if (lppd
->hDevMode
== 0) {
2432 TRACE(" No hDevMode yet... Need to create my own\n");
2433 lppd
->hDevMode
= GlobalAlloc(GMEM_MOVEABLE
,
2434 lpdm
->dmSize
+ lpdm
->dmDriverExtra
);
2437 if((locks
= (GlobalFlags(lppd
->hDevMode
) & GMEM_LOCKCOUNT
))) {
2438 WARN("hDevMode has %d locks on it. Unlocking it now\n", locks
);
2440 GlobalUnlock(lppd
->hDevMode
);
2441 TRACE("Now got %d locks\n", locks
);
2444 lppd
->hDevMode
= GlobalReAlloc(lppd
->hDevMode
,
2445 lpdm
->dmSize
+ lpdm
->dmDriverExtra
,
2448 lpdmReturn
= GlobalLock(lppd
->hDevMode
);
2449 memcpy(lpdmReturn
, lpdm
, lpdm
->dmSize
+ lpdm
->dmDriverExtra
);
2451 if (lppd
->hDevNames
!= 0) {
2453 if((locks
= (GlobalFlags(lppd
->hDevNames
) & GMEM_LOCKCOUNT
))) {
2454 WARN("hDevNames has %d locks on it. Unlocking it now\n", locks
);
2456 GlobalUnlock(lppd
->hDevNames
);
2459 PRINTDLG_CreateDevNamesW(&(lppd
->hDevNames
),
2464 GlobalUnlock(lppd
->hDevMode
);
2466 HeapFree(GetProcessHeap(), 0, PrintStructures
->lpDevMode
);
2467 HeapFree(GetProcessHeap(), 0, PrintStructures
->lpPrinterInfo
);
2468 HeapFree(GetProcessHeap(), 0, PrintStructures
->lpDriverInfo
);
2469 HeapFree(GetProcessHeap(), 0, PrintStructures
);
2471 if(bRet
&& (lppd
->Flags
& PD_RETURNDC
|| lppd
->Flags
& PD_RETURNIC
))
2472 bRet
= PRINTDLG_CreateDCW(lppd
);
2474 TRACE("exit! (%d)\n", bRet
);
2478 /***********************************************************************
2483 * cmb1 - printer select (not in standard dialog template)
2485 * cmb3 - source (tray?)
2486 * edt4 - border left
2488 * edt6 - border right
2489 * edt7 - border bottom
2490 * psh3 - "Printer..."
2498 LPPAGESETUPDLGA dlga
;
2499 LPPAGESETUPDLGW dlgw
;
2501 HWND hDlg
; /* Page Setup dialog handle */
2502 RECT rtDrawRect
; /* Drawing rect for page */
2505 static inline DWORD
pagesetup_get_flags(const pagesetup_data
*data
)
2507 return data
->u
.dlgw
->Flags
;
2510 static inline BOOL
is_metric(const pagesetup_data
*data
)
2512 return pagesetup_get_flags(data
) & PSD_INHUNDREDTHSOFMILLIMETERS
;
2515 static inline LONG
tenths_mm_to_size(const pagesetup_data
*data
, LONG size
)
2517 if (is_metric(data
))
2520 return 10 * size
* 100 / 254;
2523 static inline LONG
thousandths_inch_to_size(const pagesetup_data
*data
, LONG size
)
2525 if (is_metric(data
))
2526 return size
* 254 / 100;
2531 static WCHAR
get_decimal_sep(void)
2537 WCHAR buf
[] = {'.', 0};
2538 GetLocaleInfoW(LOCALE_USER_DEFAULT
, LOCALE_SDECIMAL
, buf
, sizeof(buf
) / sizeof(buf
[0]));
2544 static void size2str(const pagesetup_data
*data
, DWORD size
, LPWSTR strout
)
2546 WCHAR integer_fmt
[] = {'%','d',0};
2547 WCHAR hundredths_fmt
[] = {'%','d','%','c','%','0','2','d',0};
2548 WCHAR thousandths_fmt
[] = {'%','d','%','c','%','0','3','d',0};
2550 /* FIXME use LOCALE_SDECIMAL when the edit parsing code can cope */
2552 if (is_metric(data
))
2555 wsprintfW(strout
, hundredths_fmt
, size
/ 100, get_decimal_sep(), size
% 100);
2557 wsprintfW(strout
, integer_fmt
, size
/ 100);
2562 wsprintfW(strout
, thousandths_fmt
, size
/ 1000, get_decimal_sep(), size
% 1000);
2564 wsprintfW(strout
, integer_fmt
, size
/ 1000);
2569 static inline BOOL
is_default_metric(void)
2572 GetLocaleInfoW(LOCALE_USER_DEFAULT
, LOCALE_IMEASURE
| LOCALE_RETURN_NUMBER
,
2573 (LPWSTR
)&system
, sizeof(system
));
2577 /**********************************************
2579 * Cyclically permute the four members of rc
2580 * If sense is TRUE l -> t -> r -> b
2581 * otherwise l <- t <- r <- b
2583 static inline void rotate_rect(RECT
*rc
, BOOL sense
)
2589 rc
->bottom
= rc
->right
;
2590 rc
->right
= rc
->top
;
2598 rc
->top
= rc
->right
;
2599 rc
->right
= rc
->bottom
;
2604 static void pagesetup_set_orientation(pagesetup_data
*data
, WORD orient
)
2606 DEVMODEW
*dm
= GlobalLock(data
->u
.dlgw
->hDevMode
);
2608 assert(orient
== DMORIENT_PORTRAIT
|| orient
== DMORIENT_LANDSCAPE
);
2611 dm
->u1
.s1
.dmOrientation
= orient
;
2614 DEVMODEA
*dmA
= (DEVMODEA
*)dm
;
2615 dmA
->u1
.s1
.dmOrientation
= orient
;
2617 GlobalUnlock(data
->u
.dlgw
->hDevMode
);
2620 static WORD
pagesetup_get_orientation(const pagesetup_data
*data
)
2622 DEVMODEW
*dm
= GlobalLock(data
->u
.dlgw
->hDevMode
);
2626 orient
= dm
->u1
.s1
.dmOrientation
;
2629 DEVMODEA
*dmA
= (DEVMODEA
*)dm
;
2630 orient
= dmA
->u1
.s1
.dmOrientation
;
2632 GlobalUnlock(data
->u
.dlgw
->hDevMode
);
2636 static void pagesetup_set_papersize(pagesetup_data
*data
, WORD paper
)
2638 DEVMODEW
*dm
= GlobalLock(data
->u
.dlgw
->hDevMode
);
2641 dm
->u1
.s1
.dmPaperSize
= paper
;
2644 DEVMODEA
*dmA
= (DEVMODEA
*)dm
;
2645 dmA
->u1
.s1
.dmPaperSize
= paper
;
2647 GlobalUnlock(data
->u
.dlgw
->hDevMode
);
2650 static WORD
pagesetup_get_papersize(const pagesetup_data
*data
)
2652 DEVMODEW
*dm
= GlobalLock(data
->u
.dlgw
->hDevMode
);
2656 paper
= dm
->u1
.s1
.dmPaperSize
;
2659 DEVMODEA
*dmA
= (DEVMODEA
*)dm
;
2660 paper
= dmA
->u1
.s1
.dmPaperSize
;
2662 GlobalUnlock(data
->u
.dlgw
->hDevMode
);
2666 static void pagesetup_set_defaultsource(pagesetup_data
*data
, WORD source
)
2668 DEVMODEW
*dm
= GlobalLock(data
->u
.dlgw
->hDevMode
);
2671 dm
->u1
.s1
.dmDefaultSource
= source
;
2674 DEVMODEA
*dmA
= (DEVMODEA
*)dm
;
2675 dmA
->u1
.s1
.dmDefaultSource
= source
;
2677 GlobalUnlock(data
->u
.dlgw
->hDevMode
);
2682 devnames_driver_name
,
2683 devnames_device_name
,
2684 devnames_output_name
2688 static inline WORD
get_devname_offset(const DEVNAMES
*dn
, devnames_name which
)
2692 case devnames_driver_name
: return dn
->wDriverOffset
;
2693 case devnames_device_name
: return dn
->wDeviceOffset
;
2694 case devnames_output_name
: return dn
->wOutputOffset
;
2696 ERR("Shouldn't be here\n");
2700 static WCHAR
*pagesetup_get_a_devname(const pagesetup_data
*data
, devnames_name which
)
2705 dn
= GlobalLock(data
->u
.dlgw
->hDevNames
);
2707 name
= strdupW((WCHAR
*)dn
+ get_devname_offset(dn
, which
));
2710 int len
= MultiByteToWideChar(CP_ACP
, 0, (char*)dn
+ get_devname_offset(dn
, which
), -1, NULL
, 0);
2711 name
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2712 MultiByteToWideChar(CP_ACP
, 0, (char*)dn
+ get_devname_offset(dn
, which
), -1, name
, len
);
2714 GlobalUnlock(data
->u
.dlgw
->hDevNames
);
2718 static WCHAR
*pagesetup_get_drvname(const pagesetup_data
*data
)
2720 return pagesetup_get_a_devname(data
, devnames_driver_name
);
2723 static WCHAR
*pagesetup_get_devname(const pagesetup_data
*data
)
2725 return pagesetup_get_a_devname(data
, devnames_device_name
);
2728 static WCHAR
*pagesetup_get_portname(const pagesetup_data
*data
)
2730 return pagesetup_get_a_devname(data
, devnames_output_name
);
2733 static void pagesetup_release_a_devname(const pagesetup_data
*data
, WCHAR
*name
)
2735 HeapFree(GetProcessHeap(), 0, name
);
2738 static void pagesetup_set_devnames(pagesetup_data
*data
, LPCWSTR drv
, LPCWSTR devname
, LPCWSTR port
)
2742 DWORD len
= sizeof(DEVNAMES
), drv_len
, dev_len
, port_len
;
2746 drv_len
= (strlenW(drv
) + 1) * sizeof(WCHAR
);
2747 dev_len
= (strlenW(devname
) + 1) * sizeof(WCHAR
);
2748 port_len
= (strlenW(port
) + 1) * sizeof(WCHAR
);
2752 drv_len
= WideCharToMultiByte(CP_ACP
, 0, drv
, -1, NULL
, 0, NULL
, NULL
);
2753 dev_len
= WideCharToMultiByte(CP_ACP
, 0, devname
, -1, NULL
, 0, NULL
, NULL
);
2754 port_len
= WideCharToMultiByte(CP_ACP
, 0, port
, -1, NULL
, 0, NULL
, NULL
);
2756 len
+= drv_len
+ dev_len
+ port_len
;
2758 if(data
->u
.dlgw
->hDevNames
)
2759 data
->u
.dlgw
->hDevNames
= GlobalReAlloc(data
->u
.dlgw
->hDevNames
, len
, GMEM_MOVEABLE
);
2761 data
->u
.dlgw
->hDevNames
= GlobalAlloc(GMEM_MOVEABLE
, len
);
2763 dn
= GlobalLock(data
->u
.dlgw
->hDevNames
);
2767 WCHAR
*ptr
= (WCHAR
*)(dn
+ 1);
2768 len
= sizeof(DEVNAMES
) / sizeof(WCHAR
);
2769 dn
->wDriverOffset
= len
;
2771 ptr
+= drv_len
/ sizeof(WCHAR
);
2772 len
+= drv_len
/ sizeof(WCHAR
);
2773 dn
->wDeviceOffset
= len
;
2774 strcpyW(ptr
, devname
);
2775 ptr
+= dev_len
/ sizeof(WCHAR
);
2776 len
+= dev_len
/ sizeof(WCHAR
);
2777 dn
->wOutputOffset
= len
;
2782 char *ptr
= (char *)(dn
+ 1);
2783 len
= sizeof(DEVNAMES
);
2784 dn
->wDriverOffset
= len
;
2785 WideCharToMultiByte(CP_ACP
, 0, drv
, -1, ptr
, drv_len
, NULL
, NULL
);
2788 dn
->wDeviceOffset
= len
;
2789 WideCharToMultiByte(CP_ACP
, 0, devname
, -1, ptr
, dev_len
, NULL
, NULL
);
2792 dn
->wOutputOffset
= len
;
2793 WideCharToMultiByte(CP_ACP
, 0, port
, -1, ptr
, port_len
, NULL
, NULL
);
2797 len
= sizeof(def
) / sizeof(def
[0]);
2798 GetDefaultPrinterW(def
, &len
);
2799 if(!lstrcmpW(def
, devname
))
2802 GlobalUnlock(data
->u
.dlgw
->hDevNames
);
2805 static DEVMODEW
*pagesetup_get_devmode(const pagesetup_data
*data
)
2807 DEVMODEW
*dm
= GlobalLock(data
->u
.dlgw
->hDevMode
);
2812 /* We make a copy even in the unicode case because the ptr
2813 may get passed back to us in pagesetup_set_devmode. */
2814 ret
= HeapAlloc(GetProcessHeap(), 0, dm
->dmSize
+ dm
->dmDriverExtra
);
2815 memcpy(ret
, dm
, dm
->dmSize
+ dm
->dmDriverExtra
);
2818 ret
= GdiConvertToDevmodeW((DEVMODEA
*)dm
);
2820 GlobalUnlock(data
->u
.dlgw
->hDevMode
);
2824 static void pagesetup_release_devmode(const pagesetup_data
*data
, DEVMODEW
*dm
)
2826 HeapFree(GetProcessHeap(), 0, dm
);
2829 static void pagesetup_set_devmode(pagesetup_data
*data
, DEVMODEW
*dm
)
2831 DEVMODEA
*dmA
= NULL
;
2837 size
= dm
->dmSize
+ dm
->dmDriverExtra
;
2842 dmA
= convert_to_devmodeA(dm
);
2843 size
= dmA
->dmSize
+ dmA
->dmDriverExtra
;
2847 if(data
->u
.dlgw
->hDevMode
)
2848 data
->u
.dlgw
->hDevMode
= GlobalReAlloc(data
->u
.dlgw
->hDevMode
, size
,
2851 data
->u
.dlgw
->hDevMode
= GlobalAlloc(GMEM_MOVEABLE
, size
);
2853 dst
= GlobalLock(data
->u
.dlgw
->hDevMode
);
2854 memcpy(dst
, src
, size
);
2855 GlobalUnlock(data
->u
.dlgw
->hDevMode
);
2856 HeapFree(GetProcessHeap(), 0, dmA
);
2859 static inline POINT
*pagesetup_get_papersize_pt(const pagesetup_data
*data
)
2861 return &data
->u
.dlgw
->ptPaperSize
;
2864 static inline RECT
*pagesetup_get_margin_rect(const pagesetup_data
*data
)
2866 return &data
->u
.dlgw
->rtMargin
;
2875 static inline LPPAGESETUPHOOK
pagesetup_get_hook(const pagesetup_data
*data
, hook_type which
)
2879 case page_setup_hook
: return data
->u
.dlgw
->lpfnPageSetupHook
;
2880 case page_paint_hook
: return data
->u
.dlgw
->lpfnPagePaintHook
;
2885 /* This should only be used in calls to hook procs so we return the ptr
2886 already cast to LPARAM */
2887 static inline LPARAM
pagesetup_get_dlg_struct(const pagesetup_data
*data
)
2889 return (LPARAM
)data
->u
.dlgw
;
2892 static inline void swap_point(POINT
*pt
)
2899 static BOOL
pagesetup_update_papersize(pagesetup_data
*data
)
2902 LPWSTR devname
, portname
;
2904 WORD
*words
= NULL
, paperword
;
2905 POINT
*points
= NULL
;
2906 BOOL retval
= FALSE
;
2908 dm
= pagesetup_get_devmode(data
);
2909 devname
= pagesetup_get_devname(data
);
2910 portname
= pagesetup_get_portname(data
);
2912 num
= DeviceCapabilitiesW(devname
, portname
, DC_PAPERS
, NULL
, dm
);
2915 FIXME("No papernames found for %s/%s\n", debugstr_w(devname
), debugstr_w(portname
));
2919 words
= HeapAlloc(GetProcessHeap(), 0, num
* sizeof(WORD
));
2920 points
= HeapAlloc(GetProcessHeap(), 0, num
* sizeof(POINT
));
2922 if (num
!= DeviceCapabilitiesW(devname
, portname
, DC_PAPERS
, (LPWSTR
)words
, dm
))
2924 FIXME("Number of returned words is not %d\n", num
);
2928 if (num
!= DeviceCapabilitiesW(devname
, portname
, DC_PAPERSIZE
, (LPWSTR
)points
, dm
))
2930 FIXME("Number of returned sizes is not %d\n", num
);
2934 paperword
= pagesetup_get_papersize(data
);
2936 for (i
= 0; i
< num
; i
++)
2937 if (words
[i
] == paperword
)
2942 FIXME("Papersize %d not found in list?\n", paperword
);
2946 /* this is _10ths_ of a millimeter */
2947 pagesetup_get_papersize_pt(data
)->x
= tenths_mm_to_size(data
, points
[i
].x
);
2948 pagesetup_get_papersize_pt(data
)->y
= tenths_mm_to_size(data
, points
[i
].y
);
2950 if(pagesetup_get_orientation(data
) == DMORIENT_LANDSCAPE
)
2951 swap_point(pagesetup_get_papersize_pt(data
));
2956 HeapFree(GetProcessHeap(), 0, words
);
2957 HeapFree(GetProcessHeap(), 0, points
);
2958 pagesetup_release_a_devname(data
, portname
);
2959 pagesetup_release_a_devname(data
, devname
);
2960 pagesetup_release_devmode(data
, dm
);
2965 /**********************************************************************************************
2966 * pagesetup_change_printer
2968 * Redefines hDevMode and hDevNames HANDLES and initialises it.
2971 static BOOL
pagesetup_change_printer(LPWSTR name
, pagesetup_data
*data
)
2975 PRINTER_INFO_2W
*prn_info
= NULL
;
2976 DRIVER_INFO_3W
*drv_info
= NULL
;
2977 DEVMODEW
*dm
= NULL
;
2978 BOOL retval
= FALSE
;
2980 if(!OpenPrinterW(name
, &hprn
, NULL
))
2982 ERR("Can't open printer %s\n", debugstr_w(name
));
2986 GetPrinterW(hprn
, 2, NULL
, 0, &needed
);
2987 prn_info
= HeapAlloc(GetProcessHeap(), 0, needed
);
2988 GetPrinterW(hprn
, 2, (LPBYTE
)prn_info
, needed
, &needed
);
2989 GetPrinterDriverW(hprn
, NULL
, 3, NULL
, 0, &needed
);
2990 drv_info
= HeapAlloc(GetProcessHeap(), 0, needed
);
2991 if(!GetPrinterDriverW(hprn
, NULL
, 3, (LPBYTE
)drv_info
, needed
, &needed
))
2993 ERR("GetPrinterDriverA failed for %s, fix your config!\n", debugstr_w(prn_info
->pPrinterName
));
2998 needed
= DocumentPropertiesW(0, 0, name
, NULL
, NULL
, 0);
3001 ERR("DocumentProperties fails on %s\n", debugstr_w(name
));
3005 dm
= HeapAlloc(GetProcessHeap(), 0, needed
);
3006 DocumentPropertiesW(0, 0, name
, dm
, NULL
, DM_OUT_BUFFER
);
3008 pagesetup_set_devmode(data
, dm
);
3009 pagesetup_set_devnames(data
, drv_info
->pDriverPath
, prn_info
->pPrinterName
,
3010 prn_info
->pPortName
);
3014 HeapFree(GetProcessHeap(), 0, dm
);
3015 HeapFree(GetProcessHeap(), 0, prn_info
);
3016 HeapFree(GetProcessHeap(), 0, drv_info
);
3020 /****************************************************************************************
3021 * pagesetup_init_combos
3023 * Fills Printers, Paper and Source combos
3026 static void pagesetup_init_combos(HWND hDlg
, pagesetup_data
*data
)
3029 LPWSTR devname
, portname
;
3031 dm
= pagesetup_get_devmode(data
);
3032 devname
= pagesetup_get_devname(data
);
3033 portname
= pagesetup_get_portname(data
);
3035 PRINTDLG_SetUpPrinterListComboW(hDlg
, cmb1
, devname
);
3036 PRINTDLG_SetUpPaperComboBoxW(hDlg
, cmb2
, devname
, portname
, dm
);
3037 PRINTDLG_SetUpPaperComboBoxW(hDlg
, cmb3
, devname
, portname
, dm
);
3039 pagesetup_release_a_devname(data
, portname
);
3040 pagesetup_release_a_devname(data
, devname
);
3041 pagesetup_release_devmode(data
, dm
);
3045 /****************************************************************************************
3046 * pagesetup_change_printer_dialog
3048 * Pops up another dialog that lets the user pick another printer.
3050 * For now we display the PrintDlg, this should display a striped down version of it.
3052 static void pagesetup_change_printer_dialog(HWND hDlg
, pagesetup_data
*data
)
3055 LPWSTR drvname
, devname
, portname
;
3056 DEVMODEW
*tmp_dm
, *dm
;
3058 memset(&prnt
, 0, sizeof(prnt
));
3059 prnt
.lStructSize
= sizeof(prnt
);
3061 prnt
.hwndOwner
= hDlg
;
3063 drvname
= pagesetup_get_drvname(data
);
3064 devname
= pagesetup_get_devname(data
);
3065 portname
= pagesetup_get_portname(data
);
3067 PRINTDLG_CreateDevNamesW(&prnt
.hDevNames
, drvname
, devname
, portname
);
3068 pagesetup_release_a_devname(data
, portname
);
3069 pagesetup_release_a_devname(data
, devname
);
3070 pagesetup_release_a_devname(data
, drvname
);
3072 tmp_dm
= pagesetup_get_devmode(data
);
3073 prnt
.hDevMode
= GlobalAlloc(GMEM_MOVEABLE
, tmp_dm
->dmSize
+ tmp_dm
->dmDriverExtra
);
3074 dm
= GlobalLock(prnt
.hDevMode
);
3075 memcpy(dm
, tmp_dm
, tmp_dm
->dmSize
+ tmp_dm
->dmDriverExtra
);
3076 GlobalUnlock(prnt
.hDevMode
);
3077 pagesetup_release_devmode(data
, tmp_dm
);
3079 if (PrintDlgW(&prnt
))
3081 DEVMODEW
*dm
= GlobalLock(prnt
.hDevMode
);
3082 DEVNAMES
*dn
= GlobalLock(prnt
.hDevNames
);
3084 pagesetup_set_devnames(data
, (WCHAR
*)dn
+ dn
->wDriverOffset
,
3085 (WCHAR
*)dn
+ dn
->wDeviceOffset
, (WCHAR
*)dn
+ dn
->wOutputOffset
);
3086 pagesetup_set_devmode(data
, dm
);
3087 GlobalUnlock(prnt
.hDevNames
);
3088 GlobalUnlock(prnt
.hDevMode
);
3089 pagesetup_init_combos(hDlg
, data
);
3092 GlobalFree(prnt
.hDevMode
);
3093 GlobalFree(prnt
.hDevNames
);
3097 /******************************************************************************************
3098 * pagesetup_change_preview
3100 * Changes paper preview size / position
3103 static void pagesetup_change_preview(const pagesetup_data
*data
)
3105 LONG width
, height
, x
, y
;
3107 const int shadow
= 4;
3109 if(pagesetup_get_orientation(data
) == DMORIENT_LANDSCAPE
)
3111 width
= data
->rtDrawRect
.right
- data
->rtDrawRect
.left
;
3112 height
= pagesetup_get_papersize_pt(data
)->y
* width
/ pagesetup_get_papersize_pt(data
)->x
;
3116 height
= data
->rtDrawRect
.bottom
- data
->rtDrawRect
.top
;
3117 width
= pagesetup_get_papersize_pt(data
)->x
* height
/ pagesetup_get_papersize_pt(data
)->y
;
3119 x
= (data
->rtDrawRect
.right
+ data
->rtDrawRect
.left
- width
) / 2;
3120 y
= (data
->rtDrawRect
.bottom
+ data
->rtDrawRect
.top
- height
) / 2;
3121 TRACE("draw rect %s x=%d, y=%d, w=%d, h=%d\n",
3122 wine_dbgstr_rect(&data
->rtDrawRect
), x
, y
, width
, height
);
3124 MoveWindow(GetDlgItem(data
->hDlg
, rct2
), x
+ width
, y
+ shadow
, shadow
, height
, FALSE
);
3125 MoveWindow(GetDlgItem(data
->hDlg
, rct3
), x
+ shadow
, y
+ height
, width
, shadow
, FALSE
);
3126 MoveWindow(GetDlgItem(data
->hDlg
, rct1
), x
, y
, width
, height
, FALSE
);
3128 tmp
= data
->rtDrawRect
;
3129 tmp
.right
+= shadow
;
3130 tmp
.bottom
+= shadow
;
3131 InvalidateRect(data
->hDlg
, &tmp
, TRUE
);
3134 static inline LONG
*element_from_margin_id(RECT
*rc
, WORD id
)
3138 case edt4
: return &rc
->left
;
3139 case edt5
: return &rc
->top
;
3140 case edt6
: return &rc
->right
;
3141 case edt7
: return &rc
->bottom
;
3146 static void update_margin_edits(HWND hDlg
, const pagesetup_data
*data
, WORD id
)
3151 for(idx
= edt4
; idx
<= edt7
; idx
++)
3153 if(id
== 0 || id
== idx
)
3155 size2str(data
, *element_from_margin_id(pagesetup_get_margin_rect(data
), idx
), str
);
3156 SetDlgItemTextW(hDlg
, idx
, str
);
3161 static void margin_edit_notification(HWND hDlg
, const pagesetup_data
*data
, WORD msg
, WORD id
)
3169 LONG
*value
= element_from_margin_id(pagesetup_get_margin_rect(data
), id
);
3171 if (GetDlgItemTextW(hDlg
, id
, buf
, sizeof(buf
) / sizeof(buf
[0])) != 0)
3174 WCHAR decimal
= get_decimal_sep();
3176 val
= strtolW(buf
, &end
, 10);
3177 if(end
!= buf
|| *end
== decimal
)
3179 int mult
= is_metric(data
) ? 100 : 1000;
3188 val
+= (*end
- '0') * mult
;
3200 update_margin_edits(hDlg
, data
, id
);
3205 static void set_margin_groupbox_title(HWND hDlg
, const pagesetup_data
*data
)
3209 if(LoadStringW(COMDLG32_hInstance
, is_metric(data
) ? PD32_MARGINS_IN_MILLIMETERS
: PD32_MARGINS_IN_INCHES
,
3210 title
, sizeof(title
)/sizeof(title
[0])))
3211 SetDlgItemTextW(hDlg
, grp4
, title
);
3214 static void pagesetup_update_orientation_buttons(HWND hDlg
, const pagesetup_data
*data
)
3216 if (pagesetup_get_orientation(data
) == DMORIENT_LANDSCAPE
)
3217 CheckRadioButton(hDlg
, rad1
, rad2
, rad2
);
3219 CheckRadioButton(hDlg
, rad1
, rad2
, rad1
);
3222 /****************************************************************************************
3223 * pagesetup_printer_properties
3225 * Handle invocation of the 'Properties' button (not present in the default template).
3227 static void pagesetup_printer_properties(HWND hDlg
, pagesetup_data
*data
)
3235 devname
= pagesetup_get_devname(data
);
3237 if (!OpenPrinterW(devname
, &hprn
, NULL
))
3239 FIXME("Call to OpenPrinter did not succeed!\n");
3240 pagesetup_release_a_devname(data
, devname
);
3244 dm
= pagesetup_get_devmode(data
);
3245 DocumentPropertiesW(hDlg
, hprn
, devname
, dm
, dm
, DM_IN_BUFFER
| DM_OUT_BUFFER
| DM_IN_PROMPT
);
3246 pagesetup_set_devmode(data
, dm
);
3247 pagesetup_release_devmode(data
, dm
);
3248 pagesetup_release_a_devname(data
, devname
);
3251 /* Changing paper */
3252 pagesetup_update_papersize(data
);
3253 pagesetup_update_orientation_buttons(hDlg
, data
);
3255 /* Changing paper preview */
3256 pagesetup_change_preview(data
);
3258 /* Selecting paper in combo */
3259 count
= SendDlgItemMessageW(hDlg
, cmb2
, CB_GETCOUNT
, 0, 0);
3262 WORD paperword
= pagesetup_get_papersize(data
);
3263 for(i
= 0; i
< count
; i
++)
3265 if(SendDlgItemMessageW(hDlg
, cmb2
, CB_GETITEMDATA
, i
, 0) == paperword
) {
3266 SendDlgItemMessageW(hDlg
, cmb2
, CB_SETCURSEL
, i
, 0);
3273 /********************************************************************************
3274 * pagesetup_wm_command
3275 * process WM_COMMAND message for PageSetupDlg
3278 * hDlg [in] Main dialog HANDLE
3279 * wParam [in] WM_COMMAND wParam
3280 * lParam [in] WM_COMMAND lParam
3281 * pda [in/out] ptr to PageSetupDataA
3284 static BOOL
pagesetup_wm_command(HWND hDlg
, WPARAM wParam
, LPARAM lParam
, pagesetup_data
*data
)
3286 WORD msg
= HIWORD(wParam
);
3287 WORD id
= LOWORD(wParam
);
3289 TRACE("loword (lparam) %d, wparam 0x%lx, lparam %08lx\n",
3290 LOWORD(lParam
),wParam
,lParam
);
3293 EndDialog(hDlg
, TRUE
);
3297 EndDialog(hDlg
, FALSE
);
3300 case psh3
: /* Printer... */
3301 pagesetup_change_printer_dialog(hDlg
, data
);
3304 case rad1
: /* Portrait */
3305 case rad2
: /* Landscape */
3306 if((id
== rad1
&& pagesetup_get_orientation(data
) == DMORIENT_LANDSCAPE
) ||
3307 (id
== rad2
&& pagesetup_get_orientation(data
) == DMORIENT_PORTRAIT
))
3309 pagesetup_set_orientation(data
, (id
== rad1
) ? DMORIENT_PORTRAIT
: DMORIENT_LANDSCAPE
);
3310 pagesetup_update_papersize(data
);
3311 rotate_rect(pagesetup_get_margin_rect(data
), (id
== rad2
));
3312 update_margin_edits(hDlg
, data
, 0);
3313 pagesetup_change_preview(data
);
3316 case cmb1
: /* Printer combo */
3317 if(msg
== CBN_SELCHANGE
)
3320 GetDlgItemTextW(hDlg
, id
, name
, sizeof(name
) / sizeof(name
[0]));
3321 pagesetup_change_printer(name
, data
);
3322 pagesetup_init_combos(hDlg
, data
);
3325 case cmb2
: /* Paper combo */
3326 if(msg
== CBN_SELCHANGE
)
3328 DWORD paperword
= SendDlgItemMessageW(hDlg
, cmb2
, CB_GETITEMDATA
,
3329 SendDlgItemMessageW(hDlg
, cmb2
, CB_GETCURSEL
, 0, 0), 0);
3330 if (paperword
!= CB_ERR
)
3332 pagesetup_set_papersize(data
, paperword
);
3333 pagesetup_update_papersize(data
);
3334 pagesetup_change_preview(data
);
3336 FIXME("could not get dialog text for papersize cmbbox?\n");
3339 case cmb3
: /* Paper Source */
3340 if(msg
== CBN_SELCHANGE
)
3342 WORD source
= SendDlgItemMessageW(hDlg
, cmb3
, CB_GETITEMDATA
,
3343 SendDlgItemMessageW(hDlg
, cmb3
, CB_GETCURSEL
, 0, 0), 0);
3344 pagesetup_set_defaultsource(data
, source
);
3347 case psh2
: /* Printer Properties button */
3348 pagesetup_printer_properties(hDlg
, data
);
3354 margin_edit_notification(hDlg
, data
, msg
, id
);
3357 InvalidateRect(GetDlgItem(hDlg
, rct1
), NULL
, TRUE
);
3361 /***********************************************************************
3362 * default_page_paint_hook
3363 * Default hook paint procedure that receives WM_PSD_* messages from the dialog box
3364 * whenever the sample page is redrawn.
3366 static UINT_PTR
default_page_paint_hook(HWND hwndDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
,
3367 const pagesetup_data
*data
)
3369 LPRECT lprc
= (LPRECT
) lParam
;
3370 HDC hdc
= (HDC
) wParam
;
3373 HFONT hfont
, holdfont
;
3375 TRACE("uMsg: WM_USER+%d\n",uMsg
-WM_USER
);
3376 /* Call user paint hook if enable */
3377 if (pagesetup_get_flags(data
) & PSD_ENABLEPAGEPAINTHOOK
)
3378 if (pagesetup_get_hook(data
, page_paint_hook
)(hwndDlg
, uMsg
, wParam
, lParam
))
3382 /* LPPAGESETUPDLG in lParam */
3383 case WM_PSD_PAGESETUPDLG
:
3384 /* Inform about the sample page rectangle */
3385 case WM_PSD_FULLPAGERECT
:
3386 /* Inform about the margin rectangle */
3387 case WM_PSD_MINMARGINRECT
:
3390 /* Draw dashed rectangle showing margins */
3391 case WM_PSD_MARGINRECT
:
3392 hpen
= CreatePen(PS_DASH
, 1, GetSysColor(COLOR_3DSHADOW
));
3393 holdpen
= SelectObject(hdc
, hpen
);
3394 Rectangle(hdc
, lprc
->left
, lprc
->top
, lprc
->right
, lprc
->bottom
);
3395 DeleteObject(SelectObject(hdc
, holdpen
));
3397 /* Draw the fake document */
3398 case WM_PSD_GREEKTEXTRECT
:
3399 /* select a nice scalable font, because we want the text really small */
3400 SystemParametersInfoW(SPI_GETICONTITLELOGFONT
, sizeof(lf
), &lf
, 0);
3401 lf
.lfHeight
= 6; /* value chosen based on visual effect */
3402 hfont
= CreateFontIndirectW(&lf
);
3403 holdfont
= SelectObject(hdc
, hfont
);
3405 /* if text not loaded, then do so now */
3406 if (wszFakeDocumentText
[0] == '\0')
3407 LoadStringW(COMDLG32_hInstance
,
3409 wszFakeDocumentText
,
3410 sizeof(wszFakeDocumentText
)/sizeof(wszFakeDocumentText
[0]));
3412 oldbkmode
= SetBkMode(hdc
, TRANSPARENT
);
3413 DrawTextW(hdc
, wszFakeDocumentText
, -1, lprc
, DT_TOP
|DT_LEFT
|DT_NOPREFIX
|DT_WORDBREAK
);
3414 SetBkMode(hdc
, oldbkmode
);
3416 DeleteObject(SelectObject(hdc
, holdfont
));
3419 /* Envelope stamp */
3420 case WM_PSD_ENVSTAMPRECT
:
3421 /* Return address */
3422 case WM_PSD_YAFULLPAGERECT
:
3423 FIXME("envelope/stamp is not implemented\n");
3426 FIXME("Unknown message %x\n",uMsg
);
3432 /***********************************************************************
3434 * The main paint procedure for the PageSetupDlg function.
3435 * The Page Setup dialog box includes an image of a sample page that shows how
3436 * the user's selections affect the appearance of the printed output.
3437 * The image consists of a rectangle that represents the selected paper
3438 * or envelope type, with a dotted-line rectangle representing
3439 * the current margins, and partial (Greek text) characters
3440 * to show how text looks on the printed page.
3442 * The following messages in the order sends to user hook procedure:
3443 * WM_PSD_PAGESETUPDLG Draw the contents of the sample page
3444 * WM_PSD_FULLPAGERECT Inform about the bounding rectangle
3445 * WM_PSD_MINMARGINRECT Inform about the margin rectangle (min margin?)
3446 * WM_PSD_MARGINRECT Draw the margin rectangle
3447 * WM_PSD_GREEKTEXTRECT Draw the Greek text inside the margin rectangle
3448 * If any of first three messages returns TRUE, painting done.
3451 * hWnd [in] Handle to the Page Setup dialog box
3452 * uMsg [in] Received message
3455 * WM_PSD_ENVSTAMPRECT Draw in the envelope-stamp rectangle (for envelopes only)
3456 * WM_PSD_YAFULLPAGERECT Draw the return address portion (for envelopes and other paper sizes)
3459 * FALSE if all done correctly
3464 static LRESULT CALLBACK
3465 PRINTDLG_PagePaintProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
3468 RECT rcClient
, rcMargin
;
3471 HBRUSH hbrush
, holdbrush
;
3472 pagesetup_data
*data
;
3473 int papersize
=0, orientation
=0; /* FIXME: set these values for the user paint hook */
3474 double scalx
, scaly
;
3476 if (uMsg
!= WM_PAINT
)
3477 return CallWindowProcA(lpfnStaticWndProc
, hWnd
, uMsg
, wParam
, lParam
);
3479 /* Processing WM_PAINT message */
3480 data
= GetPropW(hWnd
, pagesetupdlg_prop
);
3482 WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
3485 if (default_page_paint_hook(hWnd
, WM_PSD_PAGESETUPDLG
, MAKELONG(papersize
, orientation
),
3486 pagesetup_get_dlg_struct(data
), data
))
3489 hdc
= BeginPaint(hWnd
, &ps
);
3490 GetClientRect(hWnd
, &rcClient
);
3492 scalx
= rcClient
.right
/ (double)pagesetup_get_papersize_pt(data
)->x
;
3493 scaly
= rcClient
.bottom
/ (double)pagesetup_get_papersize_pt(data
)->y
;
3494 rcMargin
= rcClient
;
3496 rcMargin
.left
+= pagesetup_get_margin_rect(data
)->left
* scalx
;
3497 rcMargin
.top
+= pagesetup_get_margin_rect(data
)->top
* scaly
;
3498 rcMargin
.right
-= pagesetup_get_margin_rect(data
)->right
* scalx
;
3499 rcMargin
.bottom
-= pagesetup_get_margin_rect(data
)->bottom
* scaly
;
3501 /* if the space is too small then we make sure to not draw anything */
3502 rcMargin
.left
= min(rcMargin
.left
, rcMargin
.right
);
3503 rcMargin
.top
= min(rcMargin
.top
, rcMargin
.bottom
);
3505 if (!default_page_paint_hook(hWnd
, WM_PSD_FULLPAGERECT
, (WPARAM
)hdc
, (LPARAM
)&rcClient
, data
) &&
3506 !default_page_paint_hook(hWnd
, WM_PSD_MINMARGINRECT
, (WPARAM
)hdc
, (LPARAM
)&rcMargin
, data
) )
3508 /* fill background */
3509 hbrush
= GetSysColorBrush(COLOR_3DHIGHLIGHT
);
3510 FillRect(hdc
, &rcClient
, hbrush
);
3511 holdbrush
= SelectObject(hdc
, hbrush
);
3513 hpen
= CreatePen(PS_SOLID
, 1, GetSysColor(COLOR_3DSHADOW
));
3514 holdpen
= SelectObject(hdc
, hpen
);
3516 /* paint left edge */
3517 MoveToEx(hdc
, rcClient
.left
, rcClient
.top
, NULL
);
3518 LineTo(hdc
, rcClient
.left
, rcClient
.bottom
-1);
3520 /* paint top edge */
3521 MoveToEx(hdc
, rcClient
.left
, rcClient
.top
, NULL
);
3522 LineTo(hdc
, rcClient
.right
, rcClient
.top
);
3524 hpen
= CreatePen(PS_SOLID
, 1, GetSysColor(COLOR_3DDKSHADOW
));
3525 DeleteObject(SelectObject(hdc
, hpen
));
3527 /* paint right edge */
3528 MoveToEx(hdc
, rcClient
.right
-1, rcClient
.top
, NULL
);
3529 LineTo(hdc
, rcClient
.right
-1, rcClient
.bottom
);
3531 /* paint bottom edge */
3532 MoveToEx(hdc
, rcClient
.left
, rcClient
.bottom
-1, NULL
);
3533 LineTo(hdc
, rcClient
.right
, rcClient
.bottom
-1);
3535 DeleteObject(SelectObject(hdc
, holdpen
));
3536 DeleteObject(SelectObject(hdc
, holdbrush
));
3538 default_page_paint_hook(hWnd
, WM_PSD_MARGINRECT
, (WPARAM
)hdc
, (LPARAM
)&rcMargin
, data
);
3540 /* give text a bit of a space from the frame */
3543 rcMargin
.right
-= 2;
3544 rcMargin
.bottom
-= 2;
3546 /* if the space is too small then we make sure to not draw anything */
3547 rcMargin
.left
= min(rcMargin
.left
, rcMargin
.right
);
3548 rcMargin
.top
= min(rcMargin
.top
, rcMargin
.bottom
);
3550 default_page_paint_hook(hWnd
, WM_PSD_GREEKTEXTRECT
, (WPARAM
)hdc
, (LPARAM
)&rcMargin
, data
);
3553 EndPaint(hWnd
, &ps
);
3557 /*******************************************************
3558 * The margin edit controls are subclassed to filter
3559 * anything other than numbers and the decimal separator.
3561 static LRESULT CALLBACK
pagesetup_margin_editproc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
3565 WCHAR decimal
= get_decimal_sep();
3566 WCHAR wc
= (WCHAR
)wparam
;
3567 if(!isdigitW(wc
) && wc
!= decimal
&& wc
!= VK_BACK
) return 0;
3569 return CallWindowProcW(edit_wndproc
, hwnd
, msg
, wparam
, lparam
);
3572 static void subclass_margin_edits(HWND hDlg
)
3577 for(id
= edt4
; id
<= edt7
; id
++)
3579 old_proc
= (WNDPROC
)SetWindowLongPtrW(GetDlgItem(hDlg
, id
),
3581 (ULONG_PTR
)pagesetup_margin_editproc
);
3582 InterlockedCompareExchangePointer((void**)&edit_wndproc
, old_proc
, NULL
);
3586 /***********************************************************************
3587 * pagesetup_dlg_proc
3589 * Message handler for PageSetupDlg
3591 static INT_PTR CALLBACK
pagesetup_dlg_proc(HWND hDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
3593 pagesetup_data
*data
;
3594 INT_PTR res
= FALSE
;
3597 if (uMsg
== WM_INITDIALOG
) { /*Init dialog*/
3598 data
= (pagesetup_data
*)lParam
;
3601 hDrawWnd
= GetDlgItem(hDlg
, rct1
);
3602 TRACE("set property to %p\n", data
);
3603 SetPropW(hDlg
, pagesetupdlg_prop
, data
);
3604 SetPropW(hDrawWnd
, pagesetupdlg_prop
, data
);
3605 GetWindowRect(hDrawWnd
, &data
->rtDrawRect
); /* Calculating rect in client coordinates where paper draws */
3606 MapWindowPoints( 0, hDlg
, (LPPOINT
)&data
->rtDrawRect
, 2 );
3607 lpfnStaticWndProc
= (WNDPROC
)SetWindowLongPtrW(
3610 (ULONG_PTR
)PRINTDLG_PagePaintProc
);
3612 /* FIXME: Paint hook. Must it be at begin of initialization or at end? */
3614 if (pagesetup_get_flags(data
) & PSD_ENABLEPAGESETUPHOOK
)
3616 if (!pagesetup_get_hook(data
, page_setup_hook
)(hDlg
, uMsg
, wParam
,
3617 pagesetup_get_dlg_struct(data
)))
3618 FIXME("Setup page hook failed?\n");
3621 /* if printer button disabled */
3622 if (pagesetup_get_flags(data
) & PSD_DISABLEPRINTER
)
3623 EnableWindow(GetDlgItem(hDlg
, psh3
), FALSE
);
3624 /* if margin edit boxes disabled */
3625 if (pagesetup_get_flags(data
) & PSD_DISABLEMARGINS
)
3627 EnableWindow(GetDlgItem(hDlg
, edt4
), FALSE
);
3628 EnableWindow(GetDlgItem(hDlg
, edt5
), FALSE
);
3629 EnableWindow(GetDlgItem(hDlg
, edt6
), FALSE
);
3630 EnableWindow(GetDlgItem(hDlg
, edt7
), FALSE
);
3633 /* Set orientation radiobuttons properly */
3634 pagesetup_update_orientation_buttons(hDlg
, data
);
3636 /* if orientation disabled */
3637 if (pagesetup_get_flags(data
) & PSD_DISABLEORIENTATION
)
3639 EnableWindow(GetDlgItem(hDlg
,rad1
),FALSE
);
3640 EnableWindow(GetDlgItem(hDlg
,rad2
),FALSE
);
3643 /* We fill them out enabled or not */
3644 if (!(pagesetup_get_flags(data
) & PSD_MARGINS
))
3646 /* default is 1 inch */
3647 LONG size
= thousandths_inch_to_size(data
, 1000);
3648 SetRect(pagesetup_get_margin_rect(data
), size
, size
, size
, size
);
3650 update_margin_edits(hDlg
, data
, 0);
3651 subclass_margin_edits(hDlg
);
3652 set_margin_groupbox_title(hDlg
, data
);
3654 /* if paper disabled */
3655 if (pagesetup_get_flags(data
) & PSD_DISABLEPAPER
)
3657 EnableWindow(GetDlgItem(hDlg
,cmb2
),FALSE
);
3658 EnableWindow(GetDlgItem(hDlg
,cmb3
),FALSE
);
3661 /* filling combos: printer, paper, source. selecting current printer (from DEVMODEA) */
3662 pagesetup_init_combos(hDlg
, data
);
3663 pagesetup_update_papersize(data
);
3664 pagesetup_set_defaultsource(data
, DMBIN_FORMSOURCE
); /* FIXME: This is the auto select bin. Is this correct? */
3666 /* Drawing paper prev */
3667 pagesetup_change_preview(data
);
3670 data
= GetPropW(hDlg
, pagesetupdlg_prop
);
3673 WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
3676 if (pagesetup_get_flags(data
) & PSD_ENABLEPAGESETUPHOOK
)
3678 res
= pagesetup_get_hook(data
, page_setup_hook
)(hDlg
, uMsg
, wParam
, lParam
);
3679 if (res
) return res
;
3684 return pagesetup_wm_command(hDlg
, wParam
, lParam
, data
);
3689 static WCHAR
*get_default_printer(void)
3694 GetDefaultPrinterW(NULL
, &len
);
3697 name
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3698 GetDefaultPrinterW(name
, &len
);
3703 static void pagesetup_dump_dlg_struct(const pagesetup_data
*data
)
3705 if(TRACE_ON(commdlg
))
3707 char flagstr
[1000] = "";
3708 const struct pd_flags
*pflag
= psd_flags
;
3709 for( ; pflag
->name
; pflag
++)
3711 if(pagesetup_get_flags(data
) & pflag
->flag
)
3713 strcat(flagstr
, pflag
->name
);
3714 strcat(flagstr
, "|");
3717 TRACE("%s: (%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
3718 "hinst %p, flags %08x (%s)\n",
3719 data
->unicode
? "unicode" : "ansi",
3720 data
->u
.dlgw
, data
->u
.dlgw
->hwndOwner
, data
->u
.dlgw
->hDevMode
,
3721 data
->u
.dlgw
->hDevNames
, data
->u
.dlgw
->hInstance
,
3722 pagesetup_get_flags(data
), flagstr
);
3726 static void *pagesetup_get_template(pagesetup_data
*data
)
3729 HGLOBAL tmpl_handle
;
3731 if(pagesetup_get_flags(data
) & PSD_ENABLEPAGESETUPTEMPLATEHANDLE
)
3733 tmpl_handle
= data
->u
.dlgw
->hPageSetupTemplate
;
3735 else if(pagesetup_get_flags(data
) & PSD_ENABLEPAGESETUPTEMPLATE
)
3738 res
= FindResourceW(data
->u
.dlgw
->hInstance
,
3739 data
->u
.dlgw
->lpPageSetupTemplateName
, MAKEINTRESOURCEW(RT_DIALOG
));
3741 res
= FindResourceA(data
->u
.dlga
->hInstance
,
3742 data
->u
.dlga
->lpPageSetupTemplateName
, MAKEINTRESOURCEA(RT_DIALOG
));
3743 tmpl_handle
= LoadResource(data
->u
.dlgw
->hInstance
, res
);
3747 res
= FindResourceW(COMDLG32_hInstance
, MAKEINTRESOURCEW(PAGESETUPDLGORD
),
3748 MAKEINTRESOURCEW(RT_DIALOG
));
3749 tmpl_handle
= LoadResource(COMDLG32_hInstance
, res
);
3751 return LockResource(tmpl_handle
);
3754 static BOOL
pagesetup_common(pagesetup_data
*data
)
3759 if(!pagesetup_get_dlg_struct(data
))
3761 COMDLG32_SetCommDlgExtendedError(CDERR_INITIALIZATION
);
3765 pagesetup_dump_dlg_struct(data
);
3767 if(data
->u
.dlgw
->lStructSize
!= sizeof(PAGESETUPDLGW
))
3769 COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE
);
3773 if ((pagesetup_get_flags(data
) & PSD_ENABLEPAGEPAINTHOOK
) &&
3774 (pagesetup_get_hook(data
, page_paint_hook
) == NULL
))
3776 COMDLG32_SetCommDlgExtendedError(CDERR_NOHOOK
);
3780 if(!(pagesetup_get_flags(data
) & (PSD_INTHOUSANDTHSOFINCHES
| PSD_INHUNDREDTHSOFMILLIMETERS
)))
3781 data
->u
.dlgw
->Flags
|= is_default_metric() ?
3782 PSD_INHUNDREDTHSOFMILLIMETERS
: PSD_INTHOUSANDTHSOFINCHES
;
3784 if (!data
->u
.dlgw
->hDevMode
|| !data
->u
.dlgw
->hDevNames
)
3786 WCHAR
*def
= get_default_printer();
3789 if (!(pagesetup_get_flags(data
) & PSD_NOWARNING
))
3792 LoadStringW(COMDLG32_hInstance
, PD32_NO_DEFAULT_PRINTER
, errstr
, 255);
3793 MessageBoxW(data
->u
.dlgw
->hwndOwner
, errstr
, 0, MB_OK
| MB_ICONERROR
);
3795 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN
);
3798 pagesetup_change_printer(def
, data
);
3799 HeapFree(GetProcessHeap(), 0, def
);
3802 if (pagesetup_get_flags(data
) & PSD_RETURNDEFAULT
)
3804 pagesetup_update_papersize(data
);
3808 tmpl
= pagesetup_get_template(data
);
3810 ret
= DialogBoxIndirectParamW(data
->u
.dlgw
->hInstance
, tmpl
,
3811 data
->u
.dlgw
->hwndOwner
,
3812 pagesetup_dlg_proc
, (LPARAM
)data
) > 0;
3816 /***********************************************************************
3817 * PageSetupDlgA (COMDLG32.@)
3819 * Displays the PAGE SETUP dialog box, which enables the user to specify
3820 * specific properties of a printed page such as
3821 * size, source, orientation and the width of the page margins.
3824 * setupdlg [IO] PAGESETUPDLGA struct
3827 * TRUE if the user pressed the OK button
3828 * FALSE if the user cancelled the window or an error occurred
3831 * The values of hDevMode and hDevNames are filled on output and can be
3832 * changed in PAGESETUPDLG when they are passed in PageSetupDlg.
3835 BOOL WINAPI
PageSetupDlgA(LPPAGESETUPDLGA setupdlg
)
3837 pagesetup_data data
;
3839 data
.unicode
= FALSE
;
3840 data
.u
.dlga
= setupdlg
;
3842 return pagesetup_common(&data
);
3845 /***********************************************************************
3846 * PageSetupDlgW (COMDLG32.@)
3848 * See PageSetupDlgA.
3850 BOOL WINAPI
PageSetupDlgW(LPPAGESETUPDLGW setupdlg
)
3852 pagesetup_data data
;
3854 data
.unicode
= TRUE
;
3855 data
.u
.dlgw
= setupdlg
;
3857 return pagesetup_common(&data
);
3860 /***********************************************************************
3861 * PrintDlgExA (COMDLG32.@)
3869 HRESULT WINAPI
PrintDlgExA(LPPRINTDLGEXA lppd
)
3874 FIXME("(%p) not fully implemented\n", lppd
);
3875 if ((lppd
== NULL
) || (lppd
->lStructSize
!= sizeof(PRINTDLGEXA
)))
3876 return E_INVALIDARG
;
3878 if (!IsWindow(lppd
->hwndOwner
))
3881 if (lppd
->nStartPage
!= START_PAGE_GENERAL
)
3883 if (!lppd
->nPropertyPages
)
3884 return E_INVALIDARG
;
3886 FIXME("custom property sheets (%d at %p) not supported\n", lppd
->nPropertyPages
, lppd
->lphPropertyPages
);
3889 /* Use PD_NOPAGENUMS or set nMaxPageRanges and lpPageRanges */
3890 if (!(lppd
->Flags
& PD_NOPAGENUMS
) && (!lppd
->nMaxPageRanges
|| !lppd
->lpPageRanges
))
3892 return E_INVALIDARG
;
3895 if (lppd
->Flags
& PD_RETURNDEFAULT
)
3897 PRINTER_INFO_2A
*pbuf
;
3898 DRIVER_INFO_3A
*dbuf
;
3901 if (lppd
->hDevMode
|| lppd
->hDevNames
)
3903 WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
3904 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE
);
3905 return E_INVALIDARG
;
3907 if (!PRINTDLG_OpenDefaultPrinter(&hprn
))
3909 WARN("Can't find default printer\n");
3910 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN
);
3914 pbuf
= get_printer_infoA(hprn
);
3921 dbuf
= get_driver_infoA(hprn
);
3924 HeapFree(GetProcessHeap(), 0, pbuf
);
3925 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE
);
3931 PRINTDLG_CreateDevNames(&(lppd
->hDevNames
),
3935 lppd
->hDevMode
= GlobalAlloc(GMEM_MOVEABLE
, pbuf
->pDevMode
->dmSize
+
3936 pbuf
->pDevMode
->dmDriverExtra
);
3939 ptr
= GlobalLock(lppd
->hDevMode
);
3942 memcpy(ptr
, pbuf
->pDevMode
, pbuf
->pDevMode
->dmSize
+
3943 pbuf
->pDevMode
->dmDriverExtra
);
3944 GlobalUnlock(lppd
->hDevMode
);
3948 HeapFree(GetProcessHeap(), 0, pbuf
);
3949 HeapFree(GetProcessHeap(), 0, dbuf
);
3957 /***********************************************************************
3958 * PrintDlgExW (COMDLG32.@)
3960 * Display the property sheet style PRINT dialog box
3963 * lppd [IO] ptr to PRINTDLGEX struct
3967 * Failure: One of the following COM error codes:
3968 * E_OUTOFMEMORY Insufficient memory.
3969 * E_INVALIDARG One or more arguments are invalid.
3970 * E_POINTER Invalid pointer.
3971 * E_HANDLE Invalid handle.
3972 * E_FAIL Unspecified error.
3975 * This Dialog enables the user to specify specific properties of the print job.
3976 * The property sheet can also have additional application-specific and
3977 * driver-specific property pages.
3980 * Not fully implemented
3983 HRESULT WINAPI
PrintDlgExW(LPPRINTDLGEXW lppd
)
3988 FIXME("(%p) not fully implemented\n", lppd
);
3990 if ((lppd
== NULL
) || (lppd
->lStructSize
!= sizeof(PRINTDLGEXW
))) {
3991 return E_INVALIDARG
;
3994 if (!IsWindow(lppd
->hwndOwner
)) {
3998 if (lppd
->nStartPage
!= START_PAGE_GENERAL
)
4000 if (!lppd
->nPropertyPages
)
4001 return E_INVALIDARG
;
4003 FIXME("custom property sheets (%d at %p) not supported\n", lppd
->nPropertyPages
, lppd
->lphPropertyPages
);
4006 /* Use PD_NOPAGENUMS or set nMaxPageRanges and lpPageRanges */
4007 if (!(lppd
->Flags
& PD_NOPAGENUMS
) && (!lppd
->nMaxPageRanges
|| !lppd
->lpPageRanges
))
4009 return E_INVALIDARG
;
4012 if (lppd
->Flags
& PD_RETURNDEFAULT
) {
4013 PRINTER_INFO_2W
*pbuf
;
4014 DRIVER_INFO_3W
*dbuf
;
4017 if (lppd
->hDevMode
|| lppd
->hDevNames
) {
4018 WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
4019 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE
);
4020 return E_INVALIDARG
;
4022 if (!PRINTDLG_OpenDefaultPrinter(&hprn
)) {
4023 WARN("Can't find default printer\n");
4024 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN
);
4028 pbuf
= get_printer_infoW(hprn
);
4035 dbuf
= get_driver_infoW(hprn
);
4038 HeapFree(GetProcessHeap(), 0, pbuf
);
4039 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE
);
4045 PRINTDLG_CreateDevNamesW(&(lppd
->hDevNames
),
4049 lppd
->hDevMode
= GlobalAlloc(GMEM_MOVEABLE
, pbuf
->pDevMode
->dmSize
+
4050 pbuf
->pDevMode
->dmDriverExtra
);
4051 if (lppd
->hDevMode
) {
4052 ptr
= GlobalLock(lppd
->hDevMode
);
4054 memcpy(ptr
, pbuf
->pDevMode
, pbuf
->pDevMode
->dmSize
+
4055 pbuf
->pDevMode
->dmDriverExtra
);
4056 GlobalUnlock(lppd
->hDevMode
);
4060 HeapFree(GetProcessHeap(), 0, pbuf
);
4061 HeapFree(GetProcessHeap(), 0, dbuf
);