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 * convert_to_devmodeA
167 * Creates an ansi copy of supplied devmode
169 static DEVMODEA
*convert_to_devmodeA(const DEVMODEW
*dmW
)
174 if (!dmW
) return NULL
;
175 size
= dmW
->dmSize
- CCHDEVICENAME
-
176 ((dmW
->dmSize
> FIELD_OFFSET(DEVMODEW
, dmFormName
)) ? CCHFORMNAME
: 0);
178 dmA
= HeapAlloc(GetProcessHeap(), 0, size
+ dmW
->dmDriverExtra
);
179 if (!dmA
) return NULL
;
181 WideCharToMultiByte(CP_ACP
, 0, dmW
->dmDeviceName
, -1,
182 (LPSTR
)dmA
->dmDeviceName
, CCHDEVICENAME
, NULL
, NULL
);
184 if (FIELD_OFFSET(DEVMODEW
, dmFormName
) >= dmW
->dmSize
)
186 memcpy(&dmA
->dmSpecVersion
, &dmW
->dmSpecVersion
,
187 dmW
->dmSize
- FIELD_OFFSET(DEVMODEW
, dmSpecVersion
));
191 memcpy(&dmA
->dmSpecVersion
, &dmW
->dmSpecVersion
,
192 FIELD_OFFSET(DEVMODEW
, dmFormName
) - FIELD_OFFSET(DEVMODEW
, dmSpecVersion
));
193 WideCharToMultiByte(CP_ACP
, 0, dmW
->dmFormName
, -1,
194 (LPSTR
)dmA
->dmFormName
, CCHFORMNAME
, NULL
, NULL
);
196 memcpy(&dmA
->dmLogPixels
, &dmW
->dmLogPixels
, dmW
->dmSize
- FIELD_OFFSET(DEVMODEW
, dmLogPixels
));
200 memcpy((char *)dmA
+ dmA
->dmSize
, (const char *)dmW
+ dmW
->dmSize
, dmW
->dmDriverExtra
);
204 /***********************************************************************
205 * PRINTDLG_OpenDefaultPrinter
207 * Returns a winspool printer handle to the default printer in *hprn
208 * Caller must call ClosePrinter on the handle
210 * Returns TRUE on success else FALSE
212 static BOOL
PRINTDLG_OpenDefaultPrinter(HANDLE
*hprn
)
215 DWORD dwBufLen
= sizeof(buf
) / sizeof(buf
[0]);
217 if(!GetDefaultPrinterW(buf
, &dwBufLen
))
219 res
= OpenPrinterW(buf
, hprn
, NULL
);
221 WARN("Could not open printer %s\n", debugstr_w(buf
));
225 /***********************************************************************
226 * PRINTDLG_SetUpPrinterListCombo
228 * Initializes printer list combox.
229 * hDlg: HWND of dialog
230 * id: Control id of combo
231 * name: Name of printer to select
233 * Initializes combo with list of available printers. Selects printer 'name'
234 * If name is NULL or does not exist select the default printer.
236 * Returns number of printers added to list.
238 static INT
PRINTDLG_SetUpPrinterListComboA(HWND hDlg
, UINT id
, LPCSTR name
)
242 LPPRINTER_INFO_2A pi
;
243 EnumPrintersA(PRINTER_ENUM_LOCAL
, NULL
, 2, NULL
, 0, &needed
, &num
);
244 pi
= HeapAlloc(GetProcessHeap(), 0, needed
);
245 EnumPrintersA(PRINTER_ENUM_LOCAL
, NULL
, 2, (LPBYTE
)pi
, needed
, &needed
,
248 SendDlgItemMessageA(hDlg
, id
, CB_RESETCONTENT
, 0, 0);
250 for(i
= 0; i
< num
; i
++) {
251 SendDlgItemMessageA(hDlg
, id
, CB_ADDSTRING
, 0,
252 (LPARAM
)pi
[i
].pPrinterName
);
254 HeapFree(GetProcessHeap(), 0, pi
);
256 (i
= SendDlgItemMessageA(hDlg
, id
, CB_FINDSTRINGEXACT
, -1,
257 (LPARAM
)name
)) == CB_ERR
) {
260 DWORD dwBufLen
= sizeof(buf
);
262 WARN("Can't find %s in printer list so trying to find default\n",
264 if(!GetDefaultPrinterA(buf
, &dwBufLen
))
266 i
= SendDlgItemMessageA(hDlg
, id
, CB_FINDSTRINGEXACT
, -1, (LPARAM
)buf
);
268 FIXME("Can't find default printer in printer list\n");
270 SendDlgItemMessageA(hDlg
, id
, CB_SETCURSEL
, i
, 0);
274 static INT
PRINTDLG_SetUpPrinterListComboW(HWND hDlg
, UINT id
, LPCWSTR name
)
278 LPPRINTER_INFO_2W pi
;
279 EnumPrintersW(PRINTER_ENUM_LOCAL
, NULL
, 2, NULL
, 0, &needed
, &num
);
280 pi
= HeapAlloc(GetProcessHeap(), 0, needed
);
281 EnumPrintersW(PRINTER_ENUM_LOCAL
, NULL
, 2, (LPBYTE
)pi
, needed
, &needed
,
284 for(i
= 0; i
< num
; i
++) {
285 SendDlgItemMessageW(hDlg
, id
, CB_ADDSTRING
, 0,
286 (LPARAM
)pi
[i
].pPrinterName
);
288 HeapFree(GetProcessHeap(), 0, pi
);
290 (i
= SendDlgItemMessageW(hDlg
, id
, CB_FINDSTRINGEXACT
, -1,
291 (LPARAM
)name
)) == CB_ERR
) {
293 DWORD dwBufLen
= sizeof(buf
)/sizeof(buf
[0]);
295 WARN("Can't find %s in printer list so trying to find default\n",
297 if(!GetDefaultPrinterW(buf
, &dwBufLen
))
299 i
= SendDlgItemMessageW(hDlg
, id
, CB_FINDSTRINGEXACT
, -1, (LPARAM
)buf
);
301 TRACE("Can't find default printer in printer list\n");
303 SendDlgItemMessageW(hDlg
, id
, CB_SETCURSEL
, i
, 0);
307 /***********************************************************************
308 * PRINTDLG_CreateDevNames [internal]
311 * creates a DevNames structure.
313 * (NB. when we handle unicode the offsets will be in wchars).
315 static BOOL
PRINTDLG_CreateDevNames(HGLOBAL
*hmem
, const char* DeviceDriverName
,
316 const char* DeviceName
, const char* OutputPort
)
319 char* pDevNamesSpace
;
321 LPDEVNAMES lpDevNames
;
323 DWORD dwBufLen
= sizeof(buf
);
326 p
= strrchr( DeviceDriverName
, '\\' );
327 if (p
) DeviceDriverName
= p
+ 1;
329 size
= strlen(DeviceDriverName
) + 1
330 + strlen(DeviceName
) + 1
331 + strlen(OutputPort
) + 1
335 *hmem
= GlobalReAlloc(*hmem
, size
, GMEM_MOVEABLE
);
337 *hmem
= GlobalAlloc(GMEM_MOVEABLE
, size
);
341 pDevNamesSpace
= GlobalLock(*hmem
);
342 lpDevNames
= (LPDEVNAMES
) pDevNamesSpace
;
344 pTempPtr
= pDevNamesSpace
+ sizeof(DEVNAMES
);
345 strcpy(pTempPtr
, DeviceDriverName
);
346 lpDevNames
->wDriverOffset
= pTempPtr
- pDevNamesSpace
;
348 pTempPtr
+= strlen(DeviceDriverName
) + 1;
349 strcpy(pTempPtr
, DeviceName
);
350 lpDevNames
->wDeviceOffset
= pTempPtr
- pDevNamesSpace
;
352 pTempPtr
+= strlen(DeviceName
) + 1;
353 strcpy(pTempPtr
, OutputPort
);
354 lpDevNames
->wOutputOffset
= pTempPtr
- pDevNamesSpace
;
356 GetDefaultPrinterA(buf
, &dwBufLen
);
357 lpDevNames
->wDefault
= (strcmp(buf
, DeviceName
) == 0) ? 1 : 0;
362 static BOOL
PRINTDLG_CreateDevNamesW(HGLOBAL
*hmem
, LPCWSTR DeviceDriverName
,
363 LPCWSTR DeviceName
, LPCWSTR OutputPort
)
366 LPWSTR pDevNamesSpace
;
368 LPDEVNAMES lpDevNames
;
370 DWORD dwBufLen
= sizeof(bufW
) / sizeof(WCHAR
);
373 p
= strrchrW( DeviceDriverName
, '\\' );
374 if (p
) DeviceDriverName
= p
+ 1;
376 size
= sizeof(WCHAR
)*lstrlenW(DeviceDriverName
) + 2
377 + sizeof(WCHAR
)*lstrlenW(DeviceName
) + 2
378 + sizeof(WCHAR
)*lstrlenW(OutputPort
) + 2
382 *hmem
= GlobalReAlloc(*hmem
, size
, GMEM_MOVEABLE
);
384 *hmem
= GlobalAlloc(GMEM_MOVEABLE
, size
);
388 pDevNamesSpace
= GlobalLock(*hmem
);
389 lpDevNames
= (LPDEVNAMES
) pDevNamesSpace
;
391 pTempPtr
= (LPWSTR
)((LPDEVNAMES
)pDevNamesSpace
+ 1);
392 lstrcpyW(pTempPtr
, DeviceDriverName
);
393 lpDevNames
->wDriverOffset
= pTempPtr
- pDevNamesSpace
;
395 pTempPtr
+= lstrlenW(DeviceDriverName
) + 1;
396 lstrcpyW(pTempPtr
, DeviceName
);
397 lpDevNames
->wDeviceOffset
= pTempPtr
- pDevNamesSpace
;
399 pTempPtr
+= lstrlenW(DeviceName
) + 1;
400 lstrcpyW(pTempPtr
, OutputPort
);
401 lpDevNames
->wOutputOffset
= pTempPtr
- pDevNamesSpace
;
403 GetDefaultPrinterW(bufW
, &dwBufLen
);
404 lpDevNames
->wDefault
= (lstrcmpW(bufW
, DeviceName
) == 0) ? 1 : 0;
409 /***********************************************************************
410 * PRINTDLG_UpdatePrintDlg [internal]
413 * updates the PrintDlg structure for return values.
416 * FALSE if user is not allowed to close (i.e. wrong nTo or nFrom values)
417 * TRUE if successful.
419 static BOOL
PRINTDLG_UpdatePrintDlgA(HWND hDlg
,
420 PRINT_PTRA
* PrintStructures
)
422 LPPRINTDLGA lppd
= PrintStructures
->lpPrintDlg
;
423 PDEVMODEA lpdm
= PrintStructures
->lpDevMode
;
424 LPPRINTER_INFO_2A pi
= PrintStructures
->lpPrinterInfo
;
428 FIXME("No lpdm ptr?\n");
433 if(!(lppd
->Flags
& PD_PRINTSETUP
)) {
434 /* check whether nFromPage and nToPage are within range defined by
435 * nMinPage and nMaxPage
437 if (IsDlgButtonChecked(hDlg
, rad3
) == BST_CHECKED
) { /* Pages */
441 nFromPage
= GetDlgItemInt(hDlg
, edt1
, NULL
, FALSE
);
442 nToPage
= GetDlgItemInt(hDlg
, edt2
, &translated
, FALSE
);
444 /* if no ToPage value is entered, use the FromPage value */
445 if(!translated
) nToPage
= nFromPage
;
447 if (nFromPage
< lppd
->nMinPage
|| nFromPage
> lppd
->nMaxPage
||
448 nToPage
< lppd
->nMinPage
|| nToPage
> lppd
->nMaxPage
) {
449 WCHAR resourcestr
[256];
450 WCHAR resultstr
[256];
451 LoadStringW(COMDLG32_hInstance
, PD32_INVALID_PAGE_RANGE
, resourcestr
, 255);
452 wsprintfW(resultstr
,resourcestr
, lppd
->nMinPage
, lppd
->nMaxPage
);
453 LoadStringW(COMDLG32_hInstance
, PD32_PRINT_TITLE
, resourcestr
, 255);
454 MessageBoxW(hDlg
, resultstr
, resourcestr
, MB_OK
| MB_ICONWARNING
);
457 lppd
->nFromPage
= nFromPage
;
458 lppd
->nToPage
= nToPage
;
459 lppd
->Flags
|= PD_PAGENUMS
;
462 lppd
->Flags
&= ~PD_PAGENUMS
;
464 if (IsDlgButtonChecked(hDlg
, rad2
) == BST_CHECKED
) /* Selection */
465 lppd
->Flags
|= PD_SELECTION
;
467 lppd
->Flags
&= ~PD_SELECTION
;
469 if (IsDlgButtonChecked(hDlg
, chx1
) == BST_CHECKED
) {/* Print to file */
470 static char file
[] = "FILE:";
471 lppd
->Flags
|= PD_PRINTTOFILE
;
472 pi
->pPortName
= file
;
475 if (IsDlgButtonChecked(hDlg
, chx2
) == BST_CHECKED
) { /* Collate */
476 FIXME("Collate lppd not yet implemented as output\n");
479 /* set PD_Collate and nCopies */
480 if (lppd
->Flags
& PD_USEDEVMODECOPIESANDCOLLATE
) {
481 /* The application doesn't support multiple copies or collate...
483 lppd
->Flags
&= ~PD_COLLATE
;
485 /* if the printer driver supports it... store info there
486 * otherwise no collate & multiple copies !
488 if (lpdm
->dmFields
& DM_COLLATE
)
490 (IsDlgButtonChecked(hDlg
, chx2
) == BST_CHECKED
);
491 if (lpdm
->dmFields
& DM_COPIES
)
492 lpdm
->u1
.s1
.dmCopies
= GetDlgItemInt(hDlg
, edt3
, NULL
, FALSE
);
494 /* Application is responsible for multiple copies */
495 if (IsDlgButtonChecked(hDlg
, chx2
) == BST_CHECKED
)
496 lppd
->Flags
|= PD_COLLATE
;
498 lppd
->Flags
&= ~PD_COLLATE
;
499 lppd
->nCopies
= GetDlgItemInt(hDlg
, edt3
, NULL
, FALSE
);
500 /* multiple copies already included in the document. Driver must print only one copy */
501 lpdm
->u1
.s1
.dmCopies
= 1;
504 /* Print quality, PrintDlg16 */
505 if(GetDlgItem(hDlg
, cmb1
))
507 HWND hQuality
= GetDlgItem(hDlg
, cmb1
);
508 int Sel
= SendMessageA(hQuality
, CB_GETCURSEL
, 0, 0);
512 LONG dpi
= SendMessageA(hQuality
, CB_GETITEMDATA
, Sel
, 0);
513 lpdm
->dmFields
|= DM_PRINTQUALITY
| DM_YRESOLUTION
;
514 lpdm
->u1
.s1
.dmPrintQuality
= LOWORD(dpi
);
515 lpdm
->dmYResolution
= HIWORD(dpi
);
522 static BOOL
PRINTDLG_UpdatePrintDlgW(HWND hDlg
,
523 PRINT_PTRW
* PrintStructures
)
525 LPPRINTDLGW lppd
= PrintStructures
->lpPrintDlg
;
526 PDEVMODEW lpdm
= PrintStructures
->lpDevMode
;
527 LPPRINTER_INFO_2W pi
= PrintStructures
->lpPrinterInfo
;
531 FIXME("No lpdm ptr?\n");
536 if(!(lppd
->Flags
& PD_PRINTSETUP
)) {
537 /* check whether nFromPage and nToPage are within range defined by
538 * nMinPage and nMaxPage
540 if (IsDlgButtonChecked(hDlg
, rad3
) == BST_CHECKED
) { /* Pages */
544 nFromPage
= GetDlgItemInt(hDlg
, edt1
, NULL
, FALSE
);
545 nToPage
= GetDlgItemInt(hDlg
, edt2
, &translated
, FALSE
);
547 /* if no ToPage value is entered, use the FromPage value */
548 if(!translated
) nToPage
= nFromPage
;
550 if (nFromPage
< lppd
->nMinPage
|| nFromPage
> lppd
->nMaxPage
||
551 nToPage
< lppd
->nMinPage
|| nToPage
> lppd
->nMaxPage
) {
552 WCHAR resourcestr
[256];
553 WCHAR resultstr
[256];
555 LoadStringW(COMDLG32_hInstance
, PD32_INVALID_PAGE_RANGE
,
557 args
[0] = lppd
->nMinPage
;
558 args
[1] = lppd
->nMaxPage
;
559 FormatMessageW(FORMAT_MESSAGE_FROM_STRING
|FORMAT_MESSAGE_ARGUMENT_ARRAY
,
560 resourcestr
, 0, 0, resultstr
,
561 sizeof(resultstr
)/sizeof(*resultstr
),
562 (__ms_va_list
*)args
);
563 LoadStringW(COMDLG32_hInstance
, PD32_PRINT_TITLE
,
565 MessageBoxW(hDlg
, resultstr
, resourcestr
,
566 MB_OK
| MB_ICONWARNING
);
569 lppd
->nFromPage
= nFromPage
;
570 lppd
->nToPage
= nToPage
;
571 lppd
->Flags
|= PD_PAGENUMS
;
574 lppd
->Flags
&= ~PD_PAGENUMS
;
576 if (IsDlgButtonChecked(hDlg
, rad2
) == BST_CHECKED
) /* Selection */
577 lppd
->Flags
|= PD_SELECTION
;
579 lppd
->Flags
&= ~PD_SELECTION
;
581 if (IsDlgButtonChecked(hDlg
, chx1
) == BST_CHECKED
) {/* Print to file */
582 static WCHAR file
[] = {'F','I','L','E',':',0};
583 lppd
->Flags
|= PD_PRINTTOFILE
;
584 pi
->pPortName
= file
;
587 if (IsDlgButtonChecked(hDlg
, chx2
) == BST_CHECKED
) { /* Collate */
588 FIXME("Collate lppd not yet implemented as output\n");
591 /* set PD_Collate and nCopies */
592 if (lppd
->Flags
& PD_USEDEVMODECOPIESANDCOLLATE
) {
593 /* The application doesn't support multiple copies or collate...
595 lppd
->Flags
&= ~PD_COLLATE
;
597 /* if the printer driver supports it... store info there
598 * otherwise no collate & multiple copies !
600 if (lpdm
->dmFields
& DM_COLLATE
)
602 (IsDlgButtonChecked(hDlg
, chx2
) == BST_CHECKED
);
603 if (lpdm
->dmFields
& DM_COPIES
)
604 lpdm
->u1
.s1
.dmCopies
= GetDlgItemInt(hDlg
, edt3
, NULL
, FALSE
);
606 if (IsDlgButtonChecked(hDlg
, chx2
) == BST_CHECKED
)
607 lppd
->Flags
|= PD_COLLATE
;
609 lppd
->Flags
&= ~PD_COLLATE
;
610 lppd
->nCopies
= GetDlgItemInt(hDlg
, edt3
, NULL
, FALSE
);
616 /************************************************************************
617 * PRINTDLG_SetUpPaperComboBox
619 * Initialize either the papersize or inputslot combos of the Printer Setup
620 * dialog. We store the associated word (eg DMPAPER_A4) as the item data.
621 * We also try to re-select the old selection.
623 static BOOL
PRINTDLG_SetUpPaperComboBoxA(HWND hDlg
,
634 WORD oldWord
= 0, newWord
= 0; /* DMPAPER_ and DMBIN_ start at 1 */
636 int fwCapability_Names
;
637 int fwCapability_Words
;
639 TRACE(" Printer: %s, Port: %s, ComboID: %d\n",PrinterName
,PortName
,nIDComboBox
);
641 /* query the dialog box for the current selected value */
642 Sel
= SendDlgItemMessageA(hDlg
, nIDComboBox
, CB_GETCURSEL
, 0, 0);
644 /* we enter here only if a different printer is selected after
645 * the Print Setup dialog is opened. The current settings are
646 * stored into the newly selected printer.
648 oldWord
= SendDlgItemMessageA(hDlg
, nIDComboBox
, CB_GETITEMDATA
,
650 if(oldWord
>= DMPAPER_USER
) /* DMPAPER_USER == DMBIN_USER */
651 oldWord
= 0; /* There's no point in trying to keep custom
652 paper / bin sizes across printers */
656 newWord
= (nIDComboBox
== cmb2
) ? dm
->u1
.s1
.dmPaperSize
: dm
->u1
.s1
.dmDefaultSource
;
658 if (nIDComboBox
== cmb2
) {
660 fwCapability_Names
= DC_PAPERNAMES
;
661 fwCapability_Words
= DC_PAPERS
;
665 fwCapability_Names
= DC_BINNAMES
;
666 fwCapability_Words
= DC_BINS
;
669 NrOfEntries
= DeviceCapabilitiesA(PrinterName
, PortName
,
670 fwCapability_Names
, NULL
, dm
);
671 if (NrOfEntries
== 0)
672 WARN("no Name Entries found!\n");
673 else if (NrOfEntries
< 0)
676 if(DeviceCapabilitiesA(PrinterName
, PortName
, fwCapability_Words
, NULL
, dm
)
678 ERR("Number of caps is different\n");
682 Names
= HeapAlloc(GetProcessHeap(),0, NrOfEntries
*sizeof(char)*NamesSize
);
683 Words
= HeapAlloc(GetProcessHeap(),0, NrOfEntries
*sizeof(WORD
));
684 NrOfEntries
= DeviceCapabilitiesA(PrinterName
, PortName
,
685 fwCapability_Names
, Names
, dm
);
686 NrOfEntries
= DeviceCapabilitiesA(PrinterName
, PortName
,
687 fwCapability_Words
, (LPSTR
)Words
, dm
);
689 /* reset any current content in the combobox */
690 SendDlgItemMessageA(hDlg
, nIDComboBox
, CB_RESETCONTENT
, 0, 0);
692 /* store new content */
693 for (i
= 0; i
< NrOfEntries
; i
++) {
694 DWORD pos
= SendDlgItemMessageA(hDlg
, nIDComboBox
, CB_ADDSTRING
, 0,
695 (LPARAM
)(&Names
[i
*NamesSize
]) );
696 SendDlgItemMessageA(hDlg
, nIDComboBox
, CB_SETITEMDATA
, pos
,
700 /* Look for old selection or the new default.
701 Can't do this is previous loop since item order will change as more items are added */
703 old_Sel
= NrOfEntries
;
704 for (i
= 0; i
< NrOfEntries
; i
++) {
705 if(SendDlgItemMessageA(hDlg
, nIDComboBox
, CB_GETITEMDATA
, i
, 0) ==
710 if(SendDlgItemMessageA(hDlg
, nIDComboBox
, CB_GETITEMDATA
, i
, 0) == newWord
)
714 if(old_Sel
< NrOfEntries
)
718 if(nIDComboBox
== cmb2
)
719 dm
->u1
.s1
.dmPaperSize
= oldWord
;
721 dm
->u1
.s1
.dmDefaultSource
= oldWord
;
726 SendDlgItemMessageA(hDlg
, nIDComboBox
, CB_SETCURSEL
, Sel
, 0);
728 HeapFree(GetProcessHeap(),0,Words
);
729 HeapFree(GetProcessHeap(),0,Names
);
733 static BOOL
PRINTDLG_SetUpPaperComboBoxW(HWND hDlg
,
735 const WCHAR
* PrinterName
,
736 const WCHAR
* PortName
,
744 WORD oldWord
= 0, newWord
= 0; /* DMPAPER_ and DMBIN_ start at 1 */
746 int fwCapability_Names
;
747 int fwCapability_Words
;
749 TRACE(" Printer: %s, Port: %s, ComboID: %d\n",debugstr_w(PrinterName
),debugstr_w(PortName
),nIDComboBox
);
751 /* query the dialog box for the current selected value */
752 Sel
= SendDlgItemMessageW(hDlg
, nIDComboBox
, CB_GETCURSEL
, 0, 0);
754 /* we enter here only if a different printer is selected after
755 * the Print Setup dialog is opened. The current settings are
756 * stored into the newly selected printer.
758 oldWord
= SendDlgItemMessageW(hDlg
, nIDComboBox
, CB_GETITEMDATA
,
761 if(oldWord
>= DMPAPER_USER
) /* DMPAPER_USER == DMBIN_USER */
762 oldWord
= 0; /* There's no point in trying to keep custom
763 paper / bin sizes across printers */
767 newWord
= (nIDComboBox
== cmb2
) ? dm
->u1
.s1
.dmPaperSize
: dm
->u1
.s1
.dmDefaultSource
;
769 if (nIDComboBox
== cmb2
) {
771 fwCapability_Names
= DC_PAPERNAMES
;
772 fwCapability_Words
= DC_PAPERS
;
776 fwCapability_Names
= DC_BINNAMES
;
777 fwCapability_Words
= DC_BINS
;
780 NrOfEntries
= DeviceCapabilitiesW(PrinterName
, PortName
,
781 fwCapability_Names
, NULL
, dm
);
782 if (NrOfEntries
== 0)
783 WARN("no Name Entries found!\n");
784 else if (NrOfEntries
< 0)
787 if(DeviceCapabilitiesW(PrinterName
, PortName
, fwCapability_Words
, NULL
, dm
)
789 ERR("Number of caps is different\n");
793 Names
= HeapAlloc(GetProcessHeap(),0, NrOfEntries
*sizeof(WCHAR
)*NamesSize
);
794 Words
= HeapAlloc(GetProcessHeap(),0, NrOfEntries
*sizeof(WORD
));
795 NrOfEntries
= DeviceCapabilitiesW(PrinterName
, PortName
,
796 fwCapability_Names
, Names
, dm
);
797 NrOfEntries
= DeviceCapabilitiesW(PrinterName
, PortName
,
798 fwCapability_Words
, Words
, dm
);
800 /* reset any current content in the combobox */
801 SendDlgItemMessageW(hDlg
, nIDComboBox
, CB_RESETCONTENT
, 0, 0);
803 /* store new content */
804 for (i
= 0; i
< NrOfEntries
; i
++) {
805 DWORD pos
= SendDlgItemMessageW(hDlg
, nIDComboBox
, CB_ADDSTRING
, 0,
806 (LPARAM
)(&Names
[i
*NamesSize
]) );
807 SendDlgItemMessageW(hDlg
, nIDComboBox
, CB_SETITEMDATA
, pos
,
811 /* Look for old selection or the new default.
812 Can't do this is previous loop since item order will change as more items are added */
814 old_Sel
= NrOfEntries
;
815 for (i
= 0; i
< NrOfEntries
; i
++) {
816 if(SendDlgItemMessageW(hDlg
, nIDComboBox
, CB_GETITEMDATA
, i
, 0) ==
821 if(SendDlgItemMessageA(hDlg
, nIDComboBox
, CB_GETITEMDATA
, i
, 0) == newWord
)
825 if(old_Sel
< NrOfEntries
)
829 if(nIDComboBox
== cmb2
)
830 dm
->u1
.s1
.dmPaperSize
= oldWord
;
832 dm
->u1
.s1
.dmDefaultSource
= oldWord
;
837 SendDlgItemMessageW(hDlg
, nIDComboBox
, CB_SETCURSEL
, Sel
, 0);
839 HeapFree(GetProcessHeap(),0,Words
);
840 HeapFree(GetProcessHeap(),0,Names
);
845 /***********************************************************************
846 * PRINTDLG_UpdatePrinterInfoTexts [internal]
848 static void PRINTDLG_UpdatePrinterInfoTextsA(HWND hDlg
, const PRINTER_INFO_2A
*pi
)
851 char ResourceString
[256];
857 /* add all status messages */
858 for (i
= 0; i
< 25; i
++) {
859 if (pi
->Status
& (1<<i
)) {
860 LoadStringA(COMDLG32_hInstance
, PD32_PRINTER_STATUS_PAUSED
+i
,
861 ResourceString
, 255);
862 strcat(StatusMsg
,ResourceString
);
866 /* FIXME: status==ready must only be appended if really so.
867 but how to detect? */
868 LoadStringA(COMDLG32_hInstance
, PD32_PRINTER_STATUS_READY
,
869 ResourceString
, 255);
870 strcat(StatusMsg
,ResourceString
);
871 SetDlgItemTextA(hDlg
, stc12
, StatusMsg
);
873 /* set all other printer info texts */
874 SetDlgItemTextA(hDlg
, stc11
, pi
->pDriverName
);
876 if (pi
->pLocation
!= NULL
&& pi
->pLocation
[0] != '\0')
877 SetDlgItemTextA(hDlg
, stc14
, pi
->pLocation
);
879 SetDlgItemTextA(hDlg
, stc14
, pi
->pPortName
);
880 SetDlgItemTextA(hDlg
, stc13
, pi
->pComment
? pi
->pComment
: "");
884 static void PRINTDLG_UpdatePrinterInfoTextsW(HWND hDlg
, const PRINTER_INFO_2W
*pi
)
886 WCHAR StatusMsg
[256];
887 WCHAR ResourceString
[256];
888 static const WCHAR emptyW
[] = {0};
894 /* add all status messages */
895 for (i
= 0; i
< 25; i
++) {
896 if (pi
->Status
& (1<<i
)) {
897 LoadStringW(COMDLG32_hInstance
, PD32_PRINTER_STATUS_PAUSED
+i
,
898 ResourceString
, 255);
899 lstrcatW(StatusMsg
,ResourceString
);
903 /* FIXME: status==ready must only be appended if really so.
904 but how to detect? */
905 LoadStringW(COMDLG32_hInstance
, PD32_PRINTER_STATUS_READY
,
906 ResourceString
, 255);
907 lstrcatW(StatusMsg
,ResourceString
);
908 SetDlgItemTextW(hDlg
, stc12
, StatusMsg
);
910 /* set all other printer info texts */
911 SetDlgItemTextW(hDlg
, stc11
, pi
->pDriverName
);
912 if (pi
->pLocation
!= NULL
&& pi
->pLocation
[0] != '\0')
913 SetDlgItemTextW(hDlg
, stc14
, pi
->pLocation
);
915 SetDlgItemTextW(hDlg
, stc14
, pi
->pPortName
);
916 SetDlgItemTextW(hDlg
, stc13
, pi
->pComment
? pi
->pComment
: emptyW
);
920 /*******************************************************************
922 * PRINTDLG_ChangePrinter
925 static BOOL
PRINTDLG_ChangePrinterA(HWND hDlg
, char *name
, PRINT_PTRA
*PrintStructures
)
927 LPPRINTDLGA lppd
= PrintStructures
->lpPrintDlg
;
928 LPDEVMODEA lpdm
= NULL
;
933 HeapFree(GetProcessHeap(),0, PrintStructures
->lpPrinterInfo
);
934 HeapFree(GetProcessHeap(),0, PrintStructures
->lpDriverInfo
);
935 if(!OpenPrinterA(name
, &hprn
, NULL
)) {
936 ERR("Can't open printer %s\n", name
);
939 GetPrinterA(hprn
, 2, NULL
, 0, &needed
);
940 PrintStructures
->lpPrinterInfo
= HeapAlloc(GetProcessHeap(),0,needed
);
941 GetPrinterA(hprn
, 2, (LPBYTE
)PrintStructures
->lpPrinterInfo
, needed
,
943 GetPrinterDriverA(hprn
, NULL
, 3, NULL
, 0, &needed
);
944 PrintStructures
->lpDriverInfo
= HeapAlloc(GetProcessHeap(),0,needed
);
945 if (!GetPrinterDriverA(hprn
, NULL
, 3, (LPBYTE
)PrintStructures
->lpDriverInfo
,
947 ERR("GetPrinterDriverA failed for %s, fix your config!\n",PrintStructures
->lpPrinterInfo
->pPrinterName
);
952 PRINTDLG_UpdatePrinterInfoTextsA(hDlg
, PrintStructures
->lpPrinterInfo
);
954 HeapFree(GetProcessHeap(), 0, PrintStructures
->lpDevMode
);
955 PrintStructures
->lpDevMode
= NULL
;
957 dmSize
= DocumentPropertiesA(0, 0, name
, NULL
, NULL
, 0);
959 ERR("DocumentProperties fails on %s\n", debugstr_a(name
));
962 PrintStructures
->lpDevMode
= HeapAlloc(GetProcessHeap(), 0, dmSize
);
963 dmSize
= DocumentPropertiesA(0, 0, name
, PrintStructures
->lpDevMode
, NULL
,
965 if(lppd
->hDevMode
&& (lpdm
= GlobalLock(lppd
->hDevMode
)) &&
966 !lstrcmpA( (LPSTR
) lpdm
->dmDeviceName
,
967 (LPSTR
) PrintStructures
->lpDevMode
->dmDeviceName
)) {
968 /* Supplied devicemode matches current printer so try to use it */
969 DocumentPropertiesA(0, 0, name
, PrintStructures
->lpDevMode
, lpdm
,
970 DM_OUT_BUFFER
| DM_IN_BUFFER
);
973 GlobalUnlock(lppd
->hDevMode
);
975 lpdm
= PrintStructures
->lpDevMode
; /* use this as a shortcut */
977 if(!(lppd
->Flags
& PD_PRINTSETUP
)) {
978 /* Print range (All/Range/Selection) */
979 if(lppd
->nFromPage
!= 0xffff)
980 SetDlgItemInt(hDlg
, edt1
, lppd
->nFromPage
, FALSE
);
981 if(lppd
->nToPage
!= 0xffff)
982 SetDlgItemInt(hDlg
, edt2
, lppd
->nToPage
, FALSE
);
984 CheckRadioButton(hDlg
, rad1
, rad3
, rad1
); /* default */
985 if (lppd
->Flags
& PD_NOSELECTION
)
986 EnableWindow(GetDlgItem(hDlg
, rad2
), FALSE
);
988 if (lppd
->Flags
& PD_SELECTION
)
989 CheckRadioButton(hDlg
, rad1
, rad3
, rad2
);
990 if (lppd
->Flags
& PD_NOPAGENUMS
) {
991 EnableWindow(GetDlgItem(hDlg
, rad3
), FALSE
);
992 EnableWindow(GetDlgItem(hDlg
, stc2
),FALSE
);
993 EnableWindow(GetDlgItem(hDlg
, edt1
), FALSE
);
994 EnableWindow(GetDlgItem(hDlg
, stc3
),FALSE
);
995 EnableWindow(GetDlgItem(hDlg
, edt2
), FALSE
);
997 if (lppd
->Flags
& PD_PAGENUMS
)
998 CheckRadioButton(hDlg
, rad1
, rad3
, rad3
);
1003 * FIXME: The ico3 is not displayed for some reason. I don't know why.
1005 if (lppd
->Flags
& PD_COLLATE
) {
1006 SendDlgItemMessageA(hDlg
, ico3
, STM_SETIMAGE
, IMAGE_ICON
,
1007 (LPARAM
)PrintStructures
->hCollateIcon
);
1008 CheckDlgButton(hDlg
, chx2
, 1);
1010 SendDlgItemMessageA(hDlg
, ico3
, STM_SETIMAGE
, IMAGE_ICON
,
1011 (LPARAM
)PrintStructures
->hNoCollateIcon
);
1012 CheckDlgButton(hDlg
, chx2
, 0);
1015 if (lppd
->Flags
& PD_USEDEVMODECOPIESANDCOLLATE
) {
1016 /* if printer doesn't support it: no Collate */
1017 if (!(lpdm
->dmFields
& DM_COLLATE
)) {
1018 EnableWindow(GetDlgItem(hDlg
, chx2
), FALSE
);
1019 EnableWindow(GetDlgItem(hDlg
, ico3
), FALSE
);
1026 if (lppd
->hDevMode
== 0)
1027 copies
= lppd
->nCopies
;
1029 copies
= lpdm
->u1
.s1
.dmCopies
;
1030 if(copies
== 0) copies
= 1;
1031 else if(copies
< 0) copies
= MAX_COPIES
;
1032 SetDlgItemInt(hDlg
, edt3
, copies
, FALSE
);
1035 if (lppd
->Flags
& PD_USEDEVMODECOPIESANDCOLLATE
) {
1036 /* if printer doesn't support it: no nCopies */
1037 if (!(lpdm
->dmFields
& DM_COPIES
)) {
1038 EnableWindow(GetDlgItem(hDlg
, edt3
), FALSE
);
1039 EnableWindow(GetDlgItem(hDlg
, stc5
), FALSE
);
1044 CheckDlgButton(hDlg
, chx1
, (lppd
->Flags
& PD_PRINTTOFILE
) ? 1 : 0);
1045 if (lppd
->Flags
& PD_DISABLEPRINTTOFILE
)
1046 EnableWindow(GetDlgItem(hDlg
, chx1
), FALSE
);
1047 if (lppd
->Flags
& PD_HIDEPRINTTOFILE
)
1048 ShowWindow(GetDlgItem(hDlg
, chx1
), SW_HIDE
);
1050 /* Fill print quality combo, PrintDlg16 */
1051 if(GetDlgItem(hDlg
, cmb1
))
1053 DWORD numResolutions
= DeviceCapabilitiesA(PrintStructures
->lpPrinterInfo
->pPrinterName
,
1054 PrintStructures
->lpPrinterInfo
->pPortName
,
1055 DC_ENUMRESOLUTIONS
, NULL
, lpdm
);
1057 if(numResolutions
!= -1)
1059 HWND hQuality
= GetDlgItem(hDlg
, cmb1
);
1064 HDC hPrinterDC
= CreateDCA(PrintStructures
->lpPrinterInfo
->pDriverName
,
1065 PrintStructures
->lpPrinterInfo
->pPrinterName
,
1068 Resolutions
= HeapAlloc(GetProcessHeap(), 0, numResolutions
*sizeof(LONG
)*2);
1069 DeviceCapabilitiesA(PrintStructures
->lpPrinterInfo
->pPrinterName
,
1070 PrintStructures
->lpPrinterInfo
->pPortName
,
1071 DC_ENUMRESOLUTIONS
, (LPSTR
)Resolutions
, lpdm
);
1073 dpiX
= GetDeviceCaps(hPrinterDC
, LOGPIXELSX
);
1074 dpiY
= GetDeviceCaps(hPrinterDC
, LOGPIXELSY
);
1075 DeleteDC(hPrinterDC
);
1077 SendMessageA(hQuality
, CB_RESETCONTENT
, 0, 0);
1078 for(i
= 0; i
< (numResolutions
* 2); i
+= 2)
1080 BOOL IsDefault
= FALSE
;
1083 if(Resolutions
[i
] == Resolutions
[i
+1])
1085 if(dpiX
== Resolutions
[i
])
1087 sprintf(buf
, "%d dpi", Resolutions
[i
]);
1090 if(dpiX
== Resolutions
[i
] && dpiY
== Resolutions
[i
+1])
1092 sprintf(buf
, "%d dpi x %d dpi", Resolutions
[i
], Resolutions
[i
+1]);
1095 Index
= SendMessageA(hQuality
, CB_ADDSTRING
, 0, (LPARAM
)buf
);
1098 SendMessageA(hQuality
, CB_SETCURSEL
, Index
, 0);
1100 SendMessageA(hQuality
, CB_SETITEMDATA
, Index
, MAKELONG(dpiX
,dpiY
));
1102 HeapFree(GetProcessHeap(), 0, Resolutions
);
1105 } else { /* PD_PRINTSETUP */
1106 BOOL bPortrait
= (lpdm
->u1
.s1
.dmOrientation
== DMORIENT_PORTRAIT
);
1108 PRINTDLG_SetUpPaperComboBoxA(hDlg
, cmb2
,
1109 PrintStructures
->lpPrinterInfo
->pPrinterName
,
1110 PrintStructures
->lpPrinterInfo
->pPortName
,
1112 PRINTDLG_SetUpPaperComboBoxA(hDlg
, cmb3
,
1113 PrintStructures
->lpPrinterInfo
->pPrinterName
,
1114 PrintStructures
->lpPrinterInfo
->pPortName
,
1116 CheckRadioButton(hDlg
, rad1
, rad2
, bPortrait
? rad1
: rad2
);
1117 SendDlgItemMessageA(hDlg
, ico1
, STM_SETIMAGE
, IMAGE_ICON
,
1118 (LPARAM
)(bPortrait
? PrintStructures
->hPortraitIcon
:
1119 PrintStructures
->hLandscapeIcon
));
1124 if ((lppd
->Flags
& PD_SHOWHELP
)==0) {
1125 /* hide if PD_SHOWHELP not specified */
1126 ShowWindow(GetDlgItem(hDlg
, pshHelp
), SW_HIDE
);
1131 static BOOL
PRINTDLG_ChangePrinterW(HWND hDlg
, WCHAR
*name
,
1132 PRINT_PTRW
*PrintStructures
)
1134 LPPRINTDLGW lppd
= PrintStructures
->lpPrintDlg
;
1135 LPDEVMODEW lpdm
= NULL
;
1140 HeapFree(GetProcessHeap(),0, PrintStructures
->lpPrinterInfo
);
1141 HeapFree(GetProcessHeap(),0, PrintStructures
->lpDriverInfo
);
1142 if(!OpenPrinterW(name
, &hprn
, NULL
)) {
1143 ERR("Can't open printer %s\n", debugstr_w(name
));
1146 GetPrinterW(hprn
, 2, NULL
, 0, &needed
);
1147 PrintStructures
->lpPrinterInfo
= HeapAlloc(GetProcessHeap(),0,needed
);
1148 GetPrinterW(hprn
, 2, (LPBYTE
)PrintStructures
->lpPrinterInfo
, needed
,
1150 GetPrinterDriverW(hprn
, NULL
, 3, NULL
, 0, &needed
);
1151 PrintStructures
->lpDriverInfo
= HeapAlloc(GetProcessHeap(),0,needed
);
1152 if (!GetPrinterDriverW(hprn
, NULL
, 3, (LPBYTE
)PrintStructures
->lpDriverInfo
,
1154 ERR("GetPrinterDriverA failed for %s, fix your config!\n",debugstr_w(PrintStructures
->lpPrinterInfo
->pPrinterName
));
1159 PRINTDLG_UpdatePrinterInfoTextsW(hDlg
, PrintStructures
->lpPrinterInfo
);
1161 HeapFree(GetProcessHeap(), 0, PrintStructures
->lpDevMode
);
1162 PrintStructures
->lpDevMode
= NULL
;
1164 dmSize
= DocumentPropertiesW(0, 0, name
, NULL
, NULL
, 0);
1166 ERR("DocumentProperties fails on %s\n", debugstr_w(name
));
1169 PrintStructures
->lpDevMode
= HeapAlloc(GetProcessHeap(), 0, dmSize
);
1170 dmSize
= DocumentPropertiesW(0, 0, name
, PrintStructures
->lpDevMode
, NULL
,
1172 if(lppd
->hDevMode
&& (lpdm
= GlobalLock(lppd
->hDevMode
)) &&
1173 !lstrcmpW(lpdm
->dmDeviceName
,
1174 PrintStructures
->lpDevMode
->dmDeviceName
)) {
1175 /* Supplied devicemode matches current printer so try to use it */
1176 DocumentPropertiesW(0, 0, name
, PrintStructures
->lpDevMode
, lpdm
,
1177 DM_OUT_BUFFER
| DM_IN_BUFFER
);
1180 GlobalUnlock(lppd
->hDevMode
);
1182 lpdm
= PrintStructures
->lpDevMode
; /* use this as a shortcut */
1184 if(!(lppd
->Flags
& PD_PRINTSETUP
)) {
1185 /* Print range (All/Range/Selection) */
1186 if(lppd
->nFromPage
!= 0xffff)
1187 SetDlgItemInt(hDlg
, edt1
, lppd
->nFromPage
, FALSE
);
1188 if(lppd
->nToPage
!= 0xffff)
1189 SetDlgItemInt(hDlg
, edt2
, lppd
->nToPage
, FALSE
);
1191 CheckRadioButton(hDlg
, rad1
, rad3
, rad1
); /* default */
1192 if (lppd
->Flags
& PD_NOSELECTION
)
1193 EnableWindow(GetDlgItem(hDlg
, rad2
), FALSE
);
1195 if (lppd
->Flags
& PD_SELECTION
)
1196 CheckRadioButton(hDlg
, rad1
, rad3
, rad2
);
1197 if (lppd
->Flags
& PD_NOPAGENUMS
) {
1198 EnableWindow(GetDlgItem(hDlg
, rad3
), FALSE
);
1199 EnableWindow(GetDlgItem(hDlg
, stc2
),FALSE
);
1200 EnableWindow(GetDlgItem(hDlg
, edt1
), FALSE
);
1201 EnableWindow(GetDlgItem(hDlg
, stc3
),FALSE
);
1202 EnableWindow(GetDlgItem(hDlg
, edt2
), FALSE
);
1204 if (lppd
->Flags
& PD_PAGENUMS
)
1205 CheckRadioButton(hDlg
, rad1
, rad3
, rad3
);
1210 * FIXME: The ico3 is not displayed for some reason. I don't know why.
1212 if (lppd
->Flags
& PD_COLLATE
) {
1213 SendDlgItemMessageW(hDlg
, ico3
, STM_SETIMAGE
, IMAGE_ICON
,
1214 (LPARAM
)PrintStructures
->hCollateIcon
);
1215 CheckDlgButton(hDlg
, chx2
, 1);
1217 SendDlgItemMessageW(hDlg
, ico3
, STM_SETIMAGE
, IMAGE_ICON
,
1218 (LPARAM
)PrintStructures
->hNoCollateIcon
);
1219 CheckDlgButton(hDlg
, chx2
, 0);
1222 if (lppd
->Flags
& PD_USEDEVMODECOPIESANDCOLLATE
) {
1223 /* if printer doesn't support it: no Collate */
1224 if (!(lpdm
->dmFields
& DM_COLLATE
)) {
1225 EnableWindow(GetDlgItem(hDlg
, chx2
), FALSE
);
1226 EnableWindow(GetDlgItem(hDlg
, ico3
), FALSE
);
1233 if (lppd
->hDevMode
== 0)
1234 copies
= lppd
->nCopies
;
1236 copies
= lpdm
->u1
.s1
.dmCopies
;
1237 if(copies
== 0) copies
= 1;
1238 else if(copies
< 0) copies
= MAX_COPIES
;
1239 SetDlgItemInt(hDlg
, edt3
, copies
, FALSE
);
1242 if (lppd
->Flags
& PD_USEDEVMODECOPIESANDCOLLATE
) {
1243 /* if printer doesn't support it: no nCopies */
1244 if (!(lpdm
->dmFields
& DM_COPIES
)) {
1245 EnableWindow(GetDlgItem(hDlg
, edt3
), FALSE
);
1246 EnableWindow(GetDlgItem(hDlg
, stc5
), FALSE
);
1251 CheckDlgButton(hDlg
, chx1
, (lppd
->Flags
& PD_PRINTTOFILE
) ? 1 : 0);
1252 if (lppd
->Flags
& PD_DISABLEPRINTTOFILE
)
1253 EnableWindow(GetDlgItem(hDlg
, chx1
), FALSE
);
1254 if (lppd
->Flags
& PD_HIDEPRINTTOFILE
)
1255 ShowWindow(GetDlgItem(hDlg
, chx1
), SW_HIDE
);
1257 } else { /* PD_PRINTSETUP */
1258 BOOL bPortrait
= (lpdm
->u1
.s1
.dmOrientation
== DMORIENT_PORTRAIT
);
1260 PRINTDLG_SetUpPaperComboBoxW(hDlg
, cmb2
,
1261 PrintStructures
->lpPrinterInfo
->pPrinterName
,
1262 PrintStructures
->lpPrinterInfo
->pPortName
,
1264 PRINTDLG_SetUpPaperComboBoxW(hDlg
, cmb3
,
1265 PrintStructures
->lpPrinterInfo
->pPrinterName
,
1266 PrintStructures
->lpPrinterInfo
->pPortName
,
1268 CheckRadioButton(hDlg
, rad1
, rad2
, bPortrait
? rad1
: rad2
);
1269 SendDlgItemMessageW(hDlg
, ico1
, STM_SETIMAGE
, IMAGE_ICON
,
1270 (LPARAM
)(bPortrait
? PrintStructures
->hPortraitIcon
:
1271 PrintStructures
->hLandscapeIcon
));
1276 if ((lppd
->Flags
& PD_SHOWHELP
)==0) {
1277 /* hide if PD_SHOWHELP not specified */
1278 ShowWindow(GetDlgItem(hDlg
, pshHelp
), SW_HIDE
);
1283 /***********************************************************************
1284 * check_printer_setup [internal]
1286 static LRESULT
check_printer_setup(HWND hDlg
)
1289 WCHAR resourcestr
[256],resultstr
[256];
1291 EnumPrintersW(PRINTER_ENUM_LOCAL
, NULL
, 2, NULL
, 0, &needed
, &num
);
1294 EnumPrintersW(PRINTER_ENUM_CONNECTIONS
, NULL
, 2, NULL
, 0, &needed
, &num
);
1300 LoadStringW(COMDLG32_hInstance
, PD32_NO_DEVICES
,resultstr
, 255);
1301 LoadStringW(COMDLG32_hInstance
, PD32_PRINT_TITLE
,resourcestr
, 255);
1302 MessageBoxW(hDlg
, resultstr
, resourcestr
,MB_OK
| MB_ICONWARNING
);
1307 /***********************************************************************
1308 * PRINTDLG_WMInitDialog [internal]
1310 static LRESULT
PRINTDLG_WMInitDialog(HWND hDlg
,
1311 PRINT_PTRA
* PrintStructures
)
1313 LPPRINTDLGA lppd
= PrintStructures
->lpPrintDlg
;
1317 UINT comboID
= (lppd
->Flags
& PD_PRINTSETUP
) ? cmb1
: cmb4
;
1319 /* load Collate ICONs */
1320 /* We load these with LoadImage because they are not a standard
1321 size and we don't want them rescaled */
1322 PrintStructures
->hCollateIcon
=
1323 LoadImageA(COMDLG32_hInstance
, "PD32_COLLATE", IMAGE_ICON
, 0, 0, 0);
1324 PrintStructures
->hNoCollateIcon
=
1325 LoadImageA(COMDLG32_hInstance
, "PD32_NOCOLLATE", IMAGE_ICON
, 0, 0, 0);
1327 /* These can be done with LoadIcon */
1328 PrintStructures
->hPortraitIcon
=
1329 LoadIconA(COMDLG32_hInstance
, "PD32_PORTRAIT");
1330 PrintStructures
->hLandscapeIcon
=
1331 LoadIconA(COMDLG32_hInstance
, "PD32_LANDSCAPE");
1333 /* display the collate/no_collate icon */
1334 SendDlgItemMessageA(hDlg
, ico3
, STM_SETIMAGE
, IMAGE_ICON
,
1335 (LPARAM
)PrintStructures
->hNoCollateIcon
);
1337 if(PrintStructures
->hCollateIcon
== 0 ||
1338 PrintStructures
->hNoCollateIcon
== 0 ||
1339 PrintStructures
->hPortraitIcon
== 0 ||
1340 PrintStructures
->hLandscapeIcon
== 0) {
1341 ERR("no icon in resourcefile\n");
1342 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
1343 EndDialog(hDlg
, FALSE
);
1347 * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
1348 * must be registered and the Help button must be shown.
1350 if (lppd
->Flags
& PD_SHOWHELP
) {
1351 if((PrintStructures
->HelpMessageID
=
1352 RegisterWindowMessageA(HELPMSGSTRINGA
)) == 0) {
1353 COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL
);
1357 PrintStructures
->HelpMessageID
= 0;
1359 if(!(lppd
->Flags
&PD_PRINTSETUP
)) {
1360 PrintStructures
->hwndUpDown
=
1361 CreateUpDownControl(WS_CHILD
| WS_VISIBLE
| WS_BORDER
|
1362 UDS_NOTHOUSANDS
| UDS_ARROWKEYS
|
1363 UDS_ALIGNRIGHT
| UDS_SETBUDDYINT
, 0, 0, 0, 0,
1364 hDlg
, UPDOWN_ID
, COMDLG32_hInstance
,
1365 GetDlgItem(hDlg
, edt3
), MAX_COPIES
, 1, 1);
1368 /* FIXME: I allow more freedom than either Win95 or WinNT,
1369 * which do not agree to what errors should be thrown or not
1370 * in case nToPage or nFromPage is out-of-range.
1372 if (lppd
->nMaxPage
< lppd
->nMinPage
)
1373 lppd
->nMaxPage
= lppd
->nMinPage
;
1374 if (lppd
->nMinPage
== lppd
->nMaxPage
)
1375 lppd
->Flags
|= PD_NOPAGENUMS
;
1376 if (lppd
->nToPage
< lppd
->nMinPage
)
1377 lppd
->nToPage
= lppd
->nMinPage
;
1378 if (lppd
->nToPage
> lppd
->nMaxPage
)
1379 lppd
->nToPage
= lppd
->nMaxPage
;
1380 if (lppd
->nFromPage
< lppd
->nMinPage
)
1381 lppd
->nFromPage
= lppd
->nMinPage
;
1382 if (lppd
->nFromPage
> lppd
->nMaxPage
)
1383 lppd
->nFromPage
= lppd
->nMaxPage
;
1385 /* if we have the combo box, fill it */
1386 if (GetDlgItem(hDlg
,comboID
)) {
1389 pdn
= GlobalLock(lppd
->hDevNames
);
1390 pdm
= GlobalLock(lppd
->hDevMode
);
1392 name
= (char*)pdn
+ pdn
->wDeviceOffset
;
1394 name
= (char*)pdm
->dmDeviceName
;
1395 PRINTDLG_SetUpPrinterListComboA(hDlg
, comboID
, name
);
1396 if(pdm
) GlobalUnlock(lppd
->hDevMode
);
1397 if(pdn
) GlobalUnlock(lppd
->hDevNames
);
1399 /* Now find selected printer and update rest of dlg */
1400 name
= HeapAlloc(GetProcessHeap(),0,256);
1401 if (GetDlgItemTextA(hDlg
, comboID
, name
, 255))
1402 PRINTDLG_ChangePrinterA(hDlg
, name
, PrintStructures
);
1403 HeapFree(GetProcessHeap(),0,name
);
1405 /* else use default printer */
1407 DWORD dwBufLen
= sizeof(name
);
1408 BOOL ret
= GetDefaultPrinterA(name
, &dwBufLen
);
1411 PRINTDLG_ChangePrinterA(hDlg
, name
, PrintStructures
);
1413 FIXME("No default printer found, expect problems!\n");
1418 static LRESULT
PRINTDLG_WMInitDialogW(HWND hDlg
,
1419 PRINT_PTRW
* PrintStructures
)
1421 LPPRINTDLGW lppd
= PrintStructures
->lpPrintDlg
;
1425 UINT comboID
= (lppd
->Flags
& PD_PRINTSETUP
) ? cmb1
: cmb4
;
1427 /* load Collate ICONs */
1428 /* We load these with LoadImage because they are not a standard
1429 size and we don't want them rescaled */
1430 PrintStructures
->hCollateIcon
=
1431 LoadImageW(COMDLG32_hInstance
, pd32_collateW
, IMAGE_ICON
, 0, 0, 0);
1432 PrintStructures
->hNoCollateIcon
=
1433 LoadImageW(COMDLG32_hInstance
, pd32_nocollateW
, IMAGE_ICON
, 0, 0, 0);
1435 /* These can be done with LoadIcon */
1436 PrintStructures
->hPortraitIcon
=
1437 LoadIconW(COMDLG32_hInstance
, pd32_portraitW
);
1438 PrintStructures
->hLandscapeIcon
=
1439 LoadIconW(COMDLG32_hInstance
, pd32_landscapeW
);
1441 /* display the collate/no_collate icon */
1442 SendDlgItemMessageW(hDlg
, ico3
, STM_SETIMAGE
, IMAGE_ICON
,
1443 (LPARAM
)PrintStructures
->hNoCollateIcon
);
1445 if(PrintStructures
->hCollateIcon
== 0 ||
1446 PrintStructures
->hNoCollateIcon
== 0 ||
1447 PrintStructures
->hPortraitIcon
== 0 ||
1448 PrintStructures
->hLandscapeIcon
== 0) {
1449 ERR("no icon in resourcefile\n");
1450 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
1451 EndDialog(hDlg
, FALSE
);
1455 * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
1456 * must be registered and the Help button must be shown.
1458 if (lppd
->Flags
& PD_SHOWHELP
) {
1459 if((PrintStructures
->HelpMessageID
=
1460 RegisterWindowMessageW(HELPMSGSTRINGW
)) == 0) {
1461 COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL
);
1465 PrintStructures
->HelpMessageID
= 0;
1467 if(!(lppd
->Flags
&PD_PRINTSETUP
)) {
1468 PrintStructures
->hwndUpDown
=
1469 CreateUpDownControl(WS_CHILD
| WS_VISIBLE
| WS_BORDER
|
1470 UDS_NOTHOUSANDS
| UDS_ARROWKEYS
|
1471 UDS_ALIGNRIGHT
| UDS_SETBUDDYINT
, 0, 0, 0, 0,
1472 hDlg
, UPDOWN_ID
, COMDLG32_hInstance
,
1473 GetDlgItem(hDlg
, edt3
), MAX_COPIES
, 1, 1);
1476 /* FIXME: I allow more freedom than either Win95 or WinNT,
1477 * which do not agree to what errors should be thrown or not
1478 * in case nToPage or nFromPage is out-of-range.
1480 if (lppd
->nMaxPage
< lppd
->nMinPage
)
1481 lppd
->nMaxPage
= lppd
->nMinPage
;
1482 if (lppd
->nMinPage
== lppd
->nMaxPage
)
1483 lppd
->Flags
|= PD_NOPAGENUMS
;
1484 if (lppd
->nToPage
< lppd
->nMinPage
)
1485 lppd
->nToPage
= lppd
->nMinPage
;
1486 if (lppd
->nToPage
> lppd
->nMaxPage
)
1487 lppd
->nToPage
= lppd
->nMaxPage
;
1488 if (lppd
->nFromPage
< lppd
->nMinPage
)
1489 lppd
->nFromPage
= lppd
->nMinPage
;
1490 if (lppd
->nFromPage
> lppd
->nMaxPage
)
1491 lppd
->nFromPage
= lppd
->nMaxPage
;
1493 /* if we have the combo box, fill it */
1494 if (GetDlgItem(hDlg
,comboID
)) {
1497 pdn
= GlobalLock(lppd
->hDevNames
);
1498 pdm
= GlobalLock(lppd
->hDevMode
);
1500 name
= (WCHAR
*)pdn
+ pdn
->wDeviceOffset
;
1502 name
= pdm
->dmDeviceName
;
1503 PRINTDLG_SetUpPrinterListComboW(hDlg
, comboID
, name
);
1504 if(pdm
) GlobalUnlock(lppd
->hDevMode
);
1505 if(pdn
) GlobalUnlock(lppd
->hDevNames
);
1507 /* Now find selected printer and update rest of dlg */
1508 /* ansi is ok here */
1509 name
= HeapAlloc(GetProcessHeap(),0,256*sizeof(WCHAR
));
1510 if (GetDlgItemTextW(hDlg
, comboID
, name
, 255))
1511 PRINTDLG_ChangePrinterW(hDlg
, name
, PrintStructures
);
1512 HeapFree(GetProcessHeap(),0,name
);
1514 /* else use default printer */
1516 DWORD dwBufLen
= sizeof(name
) / sizeof(WCHAR
);
1517 BOOL ret
= GetDefaultPrinterW(name
, &dwBufLen
);
1520 PRINTDLG_ChangePrinterW(hDlg
, name
, PrintStructures
);
1522 FIXME("No default printer found, expect problems!\n");
1527 /***********************************************************************
1528 * PRINTDLG_WMCommand [internal]
1530 static LRESULT
PRINTDLG_WMCommandA(HWND hDlg
, WPARAM wParam
,
1531 PRINT_PTRA
* PrintStructures
)
1533 LPPRINTDLGA lppd
= PrintStructures
->lpPrintDlg
;
1534 UINT PrinterComboID
= (lppd
->Flags
& PD_PRINTSETUP
) ? cmb1
: cmb4
;
1535 LPDEVMODEA lpdm
= PrintStructures
->lpDevMode
;
1537 switch (LOWORD(wParam
)) {
1539 TRACE(" OK button was hit\n");
1540 if (!PRINTDLG_UpdatePrintDlgA(hDlg
, PrintStructures
)) {
1541 FIXME("Update printdlg was not successful!\n");
1544 EndDialog(hDlg
, TRUE
);
1548 TRACE(" CANCEL button was hit\n");
1549 EndDialog(hDlg
, FALSE
);
1553 TRACE(" HELP button was hit\n");
1554 SendMessageA(lppd
->hwndOwner
, PrintStructures
->HelpMessageID
,
1555 (WPARAM
) hDlg
, (LPARAM
) lppd
);
1558 case chx2
: /* collate pages checkbox */
1559 if (IsDlgButtonChecked(hDlg
, chx2
) == BST_CHECKED
)
1560 SendDlgItemMessageA(hDlg
, ico3
, STM_SETIMAGE
, IMAGE_ICON
,
1561 (LPARAM
)PrintStructures
->hCollateIcon
);
1563 SendDlgItemMessageA(hDlg
, ico3
, STM_SETIMAGE
, IMAGE_ICON
,
1564 (LPARAM
)PrintStructures
->hNoCollateIcon
);
1566 case edt1
: /* from page nr editbox */
1567 case edt2
: /* to page nr editbox */
1568 if (HIWORD(wParam
)==EN_CHANGE
) {
1571 nFromPage
= GetDlgItemInt(hDlg
, edt1
, NULL
, FALSE
);
1572 nToPage
= GetDlgItemInt(hDlg
, edt2
, NULL
, FALSE
);
1573 if (nFromPage
!= lppd
->nFromPage
|| nToPage
!= lppd
->nToPage
)
1574 CheckRadioButton(hDlg
, rad1
, rad3
, rad3
);
1579 if(HIWORD(wParam
) == EN_CHANGE
) {
1580 INT copies
= GetDlgItemInt(hDlg
, edt3
, NULL
, FALSE
);
1582 EnableWindow(GetDlgItem(hDlg
, chx2
), FALSE
);
1584 EnableWindow(GetDlgItem(hDlg
, chx2
), TRUE
);
1588 case psh2
: /* Properties button */
1591 char PrinterName
[256];
1593 GetDlgItemTextA(hDlg
, PrinterComboID
, PrinterName
, 255);
1594 if (!OpenPrinterA(PrinterName
, &hPrinter
, NULL
)) {
1595 FIXME(" Call to OpenPrinter did not succeed!\n");
1598 DocumentPropertiesA(hDlg
, hPrinter
, PrinterName
,
1599 PrintStructures
->lpDevMode
,
1600 PrintStructures
->lpDevMode
,
1601 DM_IN_BUFFER
| DM_OUT_BUFFER
| DM_IN_PROMPT
);
1602 ClosePrinter(hPrinter
);
1606 case rad1
: /* Paperorientation */
1607 if (lppd
->Flags
& PD_PRINTSETUP
)
1609 lpdm
->u1
.s1
.dmOrientation
= DMORIENT_PORTRAIT
;
1610 SendDlgItemMessageA(hDlg
, ico1
, STM_SETIMAGE
, IMAGE_ICON
,
1611 (LPARAM
)(PrintStructures
->hPortraitIcon
));
1615 case rad2
: /* Paperorientation */
1616 if (lppd
->Flags
& PD_PRINTSETUP
)
1618 lpdm
->u1
.s1
.dmOrientation
= DMORIENT_LANDSCAPE
;
1619 SendDlgItemMessageA(hDlg
, ico1
, STM_SETIMAGE
, IMAGE_ICON
,
1620 (LPARAM
)(PrintStructures
->hLandscapeIcon
));
1624 case cmb1
: /* Printer Combobox in PRINT SETUP, quality combobox in PRINT16 */
1625 if (PrinterComboID
!= LOWORD(wParam
)) {
1629 case cmb4
: /* Printer combobox */
1630 if (HIWORD(wParam
)==CBN_SELCHANGE
) {
1631 char PrinterName
[256];
1632 GetDlgItemTextA(hDlg
, LOWORD(wParam
), PrinterName
, 255);
1633 PRINTDLG_ChangePrinterA(hDlg
, PrinterName
, PrintStructures
);
1637 case cmb2
: /* Papersize */
1639 DWORD Sel
= SendDlgItemMessageA(hDlg
, cmb2
, CB_GETCURSEL
, 0, 0);
1641 lpdm
->u1
.s1
.dmPaperSize
= SendDlgItemMessageA(hDlg
, cmb2
,
1647 case cmb3
: /* Bin */
1649 DWORD Sel
= SendDlgItemMessageA(hDlg
, cmb3
, CB_GETCURSEL
, 0, 0);
1651 lpdm
->u1
.s1
.dmDefaultSource
= SendDlgItemMessageA(hDlg
, cmb3
,
1652 CB_GETITEMDATA
, Sel
,
1657 if(lppd
->Flags
& PD_PRINTSETUP
) {
1658 switch (LOWORD(wParam
)) {
1659 case rad1
: /* orientation */
1661 if (IsDlgButtonChecked(hDlg
, rad1
) == BST_CHECKED
) {
1662 if(lpdm
->u1
.s1
.dmOrientation
!= DMORIENT_PORTRAIT
) {
1663 lpdm
->u1
.s1
.dmOrientation
= DMORIENT_PORTRAIT
;
1664 SendDlgItemMessageA(hDlg
, stc10
, STM_SETIMAGE
, IMAGE_ICON
,
1665 (LPARAM
)PrintStructures
->hPortraitIcon
);
1666 SendDlgItemMessageA(hDlg
, ico1
, STM_SETIMAGE
, IMAGE_ICON
,
1667 (LPARAM
)PrintStructures
->hPortraitIcon
);
1670 if(lpdm
->u1
.s1
.dmOrientation
!= DMORIENT_LANDSCAPE
) {
1671 lpdm
->u1
.s1
.dmOrientation
= DMORIENT_LANDSCAPE
;
1672 SendDlgItemMessageA(hDlg
, stc10
, STM_SETIMAGE
, IMAGE_ICON
,
1673 (LPARAM
)PrintStructures
->hLandscapeIcon
);
1674 SendDlgItemMessageA(hDlg
, ico1
, STM_SETIMAGE
, IMAGE_ICON
,
1675 (LPARAM
)PrintStructures
->hLandscapeIcon
);
1684 static LRESULT
PRINTDLG_WMCommandW(HWND hDlg
, WPARAM wParam
,
1685 PRINT_PTRW
* PrintStructures
)
1687 LPPRINTDLGW lppd
= PrintStructures
->lpPrintDlg
;
1688 UINT PrinterComboID
= (lppd
->Flags
& PD_PRINTSETUP
) ? cmb1
: cmb4
;
1689 LPDEVMODEW lpdm
= PrintStructures
->lpDevMode
;
1691 switch (LOWORD(wParam
)) {
1693 TRACE(" OK button was hit\n");
1694 if (!PRINTDLG_UpdatePrintDlgW(hDlg
, PrintStructures
)) {
1695 FIXME("Update printdlg was not successful!\n");
1698 EndDialog(hDlg
, TRUE
);
1702 TRACE(" CANCEL button was hit\n");
1703 EndDialog(hDlg
, FALSE
);
1707 TRACE(" HELP button was hit\n");
1708 SendMessageW(lppd
->hwndOwner
, PrintStructures
->HelpMessageID
,
1709 (WPARAM
) hDlg
, (LPARAM
) lppd
);
1712 case chx2
: /* collate pages checkbox */
1713 if (IsDlgButtonChecked(hDlg
, chx2
) == BST_CHECKED
)
1714 SendDlgItemMessageW(hDlg
, ico3
, STM_SETIMAGE
, IMAGE_ICON
,
1715 (LPARAM
)PrintStructures
->hCollateIcon
);
1717 SendDlgItemMessageW(hDlg
, ico3
, STM_SETIMAGE
, IMAGE_ICON
,
1718 (LPARAM
)PrintStructures
->hNoCollateIcon
);
1720 case edt1
: /* from page nr editbox */
1721 case edt2
: /* to page nr editbox */
1722 if (HIWORD(wParam
)==EN_CHANGE
) {
1725 nFromPage
= GetDlgItemInt(hDlg
, edt1
, NULL
, FALSE
);
1726 nToPage
= GetDlgItemInt(hDlg
, edt2
, NULL
, FALSE
);
1727 if (nFromPage
!= lppd
->nFromPage
|| nToPage
!= lppd
->nToPage
)
1728 CheckRadioButton(hDlg
, rad1
, rad3
, rad3
);
1733 if(HIWORD(wParam
) == EN_CHANGE
) {
1734 INT copies
= GetDlgItemInt(hDlg
, edt3
, NULL
, FALSE
);
1736 EnableWindow(GetDlgItem(hDlg
, chx2
), FALSE
);
1738 EnableWindow(GetDlgItem(hDlg
, chx2
), TRUE
);
1742 case psh2
: /* Properties button */
1745 WCHAR PrinterName
[256];
1747 if (!GetDlgItemTextW(hDlg
, PrinterComboID
, PrinterName
, 255)) break;
1748 if (!OpenPrinterW(PrinterName
, &hPrinter
, NULL
)) {
1749 FIXME(" Call to OpenPrinter did not succeed!\n");
1752 DocumentPropertiesW(hDlg
, hPrinter
, PrinterName
,
1753 PrintStructures
->lpDevMode
,
1754 PrintStructures
->lpDevMode
,
1755 DM_IN_BUFFER
| DM_OUT_BUFFER
| DM_IN_PROMPT
);
1756 ClosePrinter(hPrinter
);
1760 case rad1
: /* Paperorientation */
1761 if (lppd
->Flags
& PD_PRINTSETUP
)
1763 lpdm
->u1
.s1
.dmOrientation
= DMORIENT_PORTRAIT
;
1764 SendDlgItemMessageW(hDlg
, ico1
, STM_SETIMAGE
, IMAGE_ICON
,
1765 (LPARAM
)(PrintStructures
->hPortraitIcon
));
1769 case rad2
: /* Paperorientation */
1770 if (lppd
->Flags
& PD_PRINTSETUP
)
1772 lpdm
->u1
.s1
.dmOrientation
= DMORIENT_LANDSCAPE
;
1773 SendDlgItemMessageW(hDlg
, ico1
, STM_SETIMAGE
, IMAGE_ICON
,
1774 (LPARAM
)(PrintStructures
->hLandscapeIcon
));
1778 case cmb1
: /* Printer Combobox in PRINT SETUP */
1780 case cmb4
: /* Printer combobox */
1781 if (HIWORD(wParam
)==CBN_SELCHANGE
) {
1782 WCHAR PrinterName
[256];
1783 GetDlgItemTextW(hDlg
, LOWORD(wParam
), PrinterName
, 255);
1784 PRINTDLG_ChangePrinterW(hDlg
, PrinterName
, PrintStructures
);
1788 case cmb2
: /* Papersize */
1790 DWORD Sel
= SendDlgItemMessageW(hDlg
, cmb2
, CB_GETCURSEL
, 0, 0);
1792 lpdm
->u1
.s1
.dmPaperSize
= SendDlgItemMessageW(hDlg
, cmb2
,
1798 case cmb3
: /* Bin */
1800 DWORD Sel
= SendDlgItemMessageW(hDlg
, cmb3
, CB_GETCURSEL
, 0, 0);
1802 lpdm
->u1
.s1
.dmDefaultSource
= SendDlgItemMessageW(hDlg
, cmb3
,
1803 CB_GETITEMDATA
, Sel
,
1808 if(lppd
->Flags
& PD_PRINTSETUP
) {
1809 switch (LOWORD(wParam
)) {
1810 case rad1
: /* orientation */
1812 if (IsDlgButtonChecked(hDlg
, rad1
) == BST_CHECKED
) {
1813 if(lpdm
->u1
.s1
.dmOrientation
!= DMORIENT_PORTRAIT
) {
1814 lpdm
->u1
.s1
.dmOrientation
= DMORIENT_PORTRAIT
;
1815 SendDlgItemMessageW(hDlg
, stc10
, STM_SETIMAGE
, IMAGE_ICON
,
1816 (LPARAM
)PrintStructures
->hPortraitIcon
);
1817 SendDlgItemMessageW(hDlg
, ico1
, STM_SETIMAGE
, IMAGE_ICON
,
1818 (LPARAM
)PrintStructures
->hPortraitIcon
);
1821 if(lpdm
->u1
.s1
.dmOrientation
!= DMORIENT_LANDSCAPE
) {
1822 lpdm
->u1
.s1
.dmOrientation
= DMORIENT_LANDSCAPE
;
1823 SendDlgItemMessageW(hDlg
, stc10
, STM_SETIMAGE
, IMAGE_ICON
,
1824 (LPARAM
)PrintStructures
->hLandscapeIcon
);
1825 SendDlgItemMessageW(hDlg
, ico1
, STM_SETIMAGE
, IMAGE_ICON
,
1826 (LPARAM
)PrintStructures
->hLandscapeIcon
);
1835 /***********************************************************************
1836 * PrintDlgProcA [internal]
1838 static INT_PTR CALLBACK
PrintDlgProcA(HWND hDlg
, UINT uMsg
, WPARAM wParam
,
1841 PRINT_PTRA
* PrintStructures
;
1842 INT_PTR res
= FALSE
;
1844 if (uMsg
!=WM_INITDIALOG
) {
1845 PrintStructures
= GetPropW(hDlg
, printdlg_prop
);
1846 if (!PrintStructures
)
1849 PrintStructures
= (PRINT_PTRA
*) lParam
;
1850 SetPropW(hDlg
, printdlg_prop
, PrintStructures
);
1851 if(!check_printer_setup(hDlg
))
1853 EndDialog(hDlg
,FALSE
);
1856 res
= PRINTDLG_WMInitDialog(hDlg
, PrintStructures
);
1858 if(PrintStructures
->lpPrintDlg
->Flags
& PD_ENABLEPRINTHOOK
)
1859 res
= PrintStructures
->lpPrintDlg
->lpfnPrintHook(
1860 hDlg
, uMsg
, wParam
, (LPARAM
)PrintStructures
->lpPrintDlg
1865 if(PrintStructures
->lpPrintDlg
->Flags
& PD_ENABLEPRINTHOOK
) {
1866 res
= PrintStructures
->lpPrintDlg
->lpfnPrintHook(hDlg
,uMsg
,wParam
,
1873 return PRINTDLG_WMCommandA(hDlg
, wParam
, PrintStructures
);
1876 DestroyIcon(PrintStructures
->hCollateIcon
);
1877 DestroyIcon(PrintStructures
->hNoCollateIcon
);
1878 DestroyIcon(PrintStructures
->hPortraitIcon
);
1879 DestroyIcon(PrintStructures
->hLandscapeIcon
);
1880 if(PrintStructures
->hwndUpDown
)
1881 DestroyWindow(PrintStructures
->hwndUpDown
);
1887 static INT_PTR CALLBACK
PrintDlgProcW(HWND hDlg
, UINT uMsg
, WPARAM wParam
,
1890 PRINT_PTRW
* PrintStructures
;
1891 INT_PTR res
= FALSE
;
1893 if (uMsg
!=WM_INITDIALOG
) {
1894 PrintStructures
= GetPropW(hDlg
, printdlg_prop
);
1895 if (!PrintStructures
)
1898 PrintStructures
= (PRINT_PTRW
*) lParam
;
1899 SetPropW(hDlg
, printdlg_prop
, PrintStructures
);
1900 if(!check_printer_setup(hDlg
))
1902 EndDialog(hDlg
,FALSE
);
1905 res
= PRINTDLG_WMInitDialogW(hDlg
, PrintStructures
);
1907 if(PrintStructures
->lpPrintDlg
->Flags
& PD_ENABLEPRINTHOOK
)
1908 res
= PrintStructures
->lpPrintDlg
->lpfnPrintHook(hDlg
, uMsg
, wParam
, (LPARAM
)PrintStructures
->lpPrintDlg
);
1912 if(PrintStructures
->lpPrintDlg
->Flags
& PD_ENABLEPRINTHOOK
) {
1913 res
= PrintStructures
->lpPrintDlg
->lpfnPrintHook(hDlg
,uMsg
,wParam
, lParam
);
1919 return PRINTDLG_WMCommandW(hDlg
, wParam
, PrintStructures
);
1922 DestroyIcon(PrintStructures
->hCollateIcon
);
1923 DestroyIcon(PrintStructures
->hNoCollateIcon
);
1924 DestroyIcon(PrintStructures
->hPortraitIcon
);
1925 DestroyIcon(PrintStructures
->hLandscapeIcon
);
1926 if(PrintStructures
->hwndUpDown
)
1927 DestroyWindow(PrintStructures
->hwndUpDown
);
1933 /************************************************************
1935 * PRINTDLG_GetDlgTemplate
1938 static HGLOBAL
PRINTDLG_GetDlgTemplateA(const PRINTDLGA
*lppd
)
1943 if (lppd
->Flags
& PD_PRINTSETUP
) {
1944 if(lppd
->Flags
& PD_ENABLESETUPTEMPLATEHANDLE
) {
1945 hDlgTmpl
= lppd
->hSetupTemplate
;
1946 } else if(lppd
->Flags
& PD_ENABLESETUPTEMPLATE
) {
1947 hResInfo
= FindResourceA(lppd
->hInstance
,
1948 lppd
->lpSetupTemplateName
, (LPSTR
)RT_DIALOG
);
1949 hDlgTmpl
= LoadResource(lppd
->hInstance
, hResInfo
);
1951 hResInfo
= FindResourceA(COMDLG32_hInstance
, "PRINT32_SETUP",
1953 hDlgTmpl
= LoadResource(COMDLG32_hInstance
, hResInfo
);
1956 if(lppd
->Flags
& PD_ENABLEPRINTTEMPLATEHANDLE
) {
1957 hDlgTmpl
= lppd
->hPrintTemplate
;
1958 } else if(lppd
->Flags
& PD_ENABLEPRINTTEMPLATE
) {
1959 hResInfo
= FindResourceA(lppd
->hInstance
,
1960 lppd
->lpPrintTemplateName
,
1962 hDlgTmpl
= LoadResource(lppd
->hInstance
, hResInfo
);
1964 hResInfo
= FindResourceA(COMDLG32_hInstance
, "PRINT32",
1966 hDlgTmpl
= LoadResource(COMDLG32_hInstance
, hResInfo
);
1972 static HGLOBAL
PRINTDLG_GetDlgTemplateW(const PRINTDLGW
*lppd
)
1976 static const WCHAR xpsetup
[] = { 'P','R','I','N','T','3','2','_','S','E','T','U','P',0};
1977 static const WCHAR xprint
[] = { 'P','R','I','N','T','3','2',0};
1979 if (lppd
->Flags
& PD_PRINTSETUP
) {
1980 if(lppd
->Flags
& PD_ENABLESETUPTEMPLATEHANDLE
) {
1981 hDlgTmpl
= lppd
->hSetupTemplate
;
1982 } else if(lppd
->Flags
& PD_ENABLESETUPTEMPLATE
) {
1983 hResInfo
= FindResourceW(lppd
->hInstance
,
1984 lppd
->lpSetupTemplateName
, (LPWSTR
)RT_DIALOG
);
1985 hDlgTmpl
= LoadResource(lppd
->hInstance
, hResInfo
);
1987 hResInfo
= FindResourceW(COMDLG32_hInstance
, xpsetup
, (LPWSTR
)RT_DIALOG
);
1988 hDlgTmpl
= LoadResource(COMDLG32_hInstance
, hResInfo
);
1991 if(lppd
->Flags
& PD_ENABLEPRINTTEMPLATEHANDLE
) {
1992 hDlgTmpl
= lppd
->hPrintTemplate
;
1993 } else if(lppd
->Flags
& PD_ENABLEPRINTTEMPLATE
) {
1994 hResInfo
= FindResourceW(lppd
->hInstance
,
1995 lppd
->lpPrintTemplateName
,
1997 hDlgTmpl
= LoadResource(lppd
->hInstance
, hResInfo
);
1999 hResInfo
= FindResourceW(COMDLG32_hInstance
, xprint
, (LPWSTR
)RT_DIALOG
);
2000 hDlgTmpl
= LoadResource(COMDLG32_hInstance
, hResInfo
);
2006 /***********************************************************************
2011 static BOOL
PRINTDLG_CreateDCA(LPPRINTDLGA lppd
)
2013 DEVNAMES
*pdn
= GlobalLock(lppd
->hDevNames
);
2014 DEVMODEA
*pdm
= GlobalLock(lppd
->hDevMode
);
2016 if(lppd
->Flags
& PD_RETURNDC
) {
2017 lppd
->hDC
= CreateDCA((char*)pdn
+ pdn
->wDriverOffset
,
2018 (char*)pdn
+ pdn
->wDeviceOffset
,
2019 (char*)pdn
+ pdn
->wOutputOffset
,
2021 } else if(lppd
->Flags
& PD_RETURNIC
) {
2022 lppd
->hDC
= CreateICA((char*)pdn
+ pdn
->wDriverOffset
,
2023 (char*)pdn
+ pdn
->wDeviceOffset
,
2024 (char*)pdn
+ pdn
->wOutputOffset
,
2027 GlobalUnlock(lppd
->hDevNames
);
2028 GlobalUnlock(lppd
->hDevMode
);
2029 return lppd
->hDC
? TRUE
: FALSE
;
2032 static BOOL
PRINTDLG_CreateDCW(LPPRINTDLGW lppd
)
2034 DEVNAMES
*pdn
= GlobalLock(lppd
->hDevNames
);
2035 DEVMODEW
*pdm
= GlobalLock(lppd
->hDevMode
);
2037 if(lppd
->Flags
& PD_RETURNDC
) {
2038 lppd
->hDC
= CreateDCW((WCHAR
*)pdn
+ pdn
->wDriverOffset
,
2039 (WCHAR
*)pdn
+ pdn
->wDeviceOffset
,
2040 (WCHAR
*)pdn
+ pdn
->wOutputOffset
,
2042 } else if(lppd
->Flags
& PD_RETURNIC
) {
2043 lppd
->hDC
= CreateICW((WCHAR
*)pdn
+ pdn
->wDriverOffset
,
2044 (WCHAR
*)pdn
+ pdn
->wDeviceOffset
,
2045 (WCHAR
*)pdn
+ pdn
->wOutputOffset
,
2048 GlobalUnlock(lppd
->hDevNames
);
2049 GlobalUnlock(lppd
->hDevMode
);
2050 return lppd
->hDC
? TRUE
: FALSE
;
2053 /***********************************************************************
2054 * PrintDlgA (COMDLG32.@)
2056 * Displays the PRINT dialog box, which enables the user to specify
2057 * specific properties of the print job.
2060 * lppd [IO] ptr to PRINTDLG32 struct
2063 * nonzero if the user pressed the OK button
2064 * zero if the user cancelled the window or an error occurred
2068 * * The Collate Icons do not display, even though they are in the code.
2069 * * The Properties Button(s) should call DocumentPropertiesA().
2072 BOOL WINAPI
PrintDlgA(LPPRINTDLGA lppd
)
2080 COMDLG32_SetCommDlgExtendedError(CDERR_INITIALIZATION
);
2084 if(TRACE_ON(commdlg
)) {
2085 char flagstr
[1000] = "";
2086 const struct pd_flags
*pflag
= pd_flags
;
2087 for( ; pflag
->name
; pflag
++) {
2088 if(lppd
->Flags
& pflag
->flag
)
2089 strcat(flagstr
, pflag
->name
);
2091 TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
2092 "pp. %d-%d, min p %d, max p %d, copies %d, hinst %p\n"
2093 "flags %08x (%s)\n",
2094 lppd
, lppd
->hwndOwner
, lppd
->hDevMode
, lppd
->hDevNames
,
2095 lppd
->nFromPage
, lppd
->nToPage
, lppd
->nMinPage
, lppd
->nMaxPage
,
2096 lppd
->nCopies
, lppd
->hInstance
, lppd
->Flags
, flagstr
);
2099 if(lppd
->lStructSize
!= sizeof(PRINTDLGA
)) {
2100 WARN("structure size failure !!!\n");
2101 COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE
);
2105 if(lppd
->Flags
& PD_RETURNDEFAULT
) {
2106 PRINTER_INFO_2A
*pbuf
;
2107 DRIVER_INFO_3A
*dbuf
;
2111 if(lppd
->hDevMode
|| lppd
->hDevNames
) {
2112 WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
2113 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE
);
2116 if(!PRINTDLG_OpenDefaultPrinter(&hprn
)) {
2117 WARN("Can't find default printer\n");
2118 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN
);
2122 GetPrinterA(hprn
, 2, NULL
, 0, &needed
);
2123 pbuf
= HeapAlloc(GetProcessHeap(), 0, needed
);
2124 GetPrinterA(hprn
, 2, (LPBYTE
)pbuf
, needed
, &needed
);
2126 GetPrinterDriverA(hprn
, NULL
, 3, NULL
, 0, &needed
);
2127 dbuf
= HeapAlloc(GetProcessHeap(),0,needed
);
2128 if (!GetPrinterDriverA(hprn
, NULL
, 3, (LPBYTE
)dbuf
, needed
, &needed
)) {
2129 ERR("GetPrinterDriverA failed, le %d, fix your config for printer %s!\n",
2130 GetLastError(),pbuf
->pPrinterName
);
2131 HeapFree(GetProcessHeap(), 0, dbuf
);
2132 HeapFree(GetProcessHeap(), 0, pbuf
);
2133 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE
);
2138 PRINTDLG_CreateDevNames(&(lppd
->hDevNames
),
2142 lppd
->hDevMode
= GlobalAlloc(GMEM_MOVEABLE
, pbuf
->pDevMode
->dmSize
+
2143 pbuf
->pDevMode
->dmDriverExtra
);
2144 ptr
= GlobalLock(lppd
->hDevMode
);
2145 memcpy(ptr
, pbuf
->pDevMode
, pbuf
->pDevMode
->dmSize
+
2146 pbuf
->pDevMode
->dmDriverExtra
);
2147 GlobalUnlock(lppd
->hDevMode
);
2148 HeapFree(GetProcessHeap(), 0, pbuf
);
2149 HeapFree(GetProcessHeap(), 0, dbuf
);
2153 PRINT_PTRA
*PrintStructures
;
2155 /* load Dialog resources,
2156 * depending on Flags indicates Print32 or Print32_setup dialog
2158 hDlgTmpl
= PRINTDLG_GetDlgTemplateA(lppd
);
2160 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
2163 ptr
= LockResource( hDlgTmpl
);
2165 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
2169 PrintStructures
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2170 sizeof(PRINT_PTRA
));
2171 PrintStructures
->lpPrintDlg
= lppd
;
2173 /* and create & process the dialog .
2174 * -1 is failure, 0 is broken hwnd, everything else is ok.
2176 hInst
= COMDLG32_hInstance
;
2177 if (lppd
->Flags
& (PD_ENABLESETUPTEMPLATE
| PD_ENABLEPRINTTEMPLATE
)) hInst
= lppd
->hInstance
;
2178 bRet
= (0<DialogBoxIndirectParamA(hInst
, ptr
, lppd
->hwndOwner
,
2180 (LPARAM
)PrintStructures
));
2183 DEVMODEA
*lpdm
= PrintStructures
->lpDevMode
, *lpdmReturn
;
2184 PRINTER_INFO_2A
*pi
= PrintStructures
->lpPrinterInfo
;
2185 DRIVER_INFO_3A
*di
= PrintStructures
->lpDriverInfo
;
2187 if (lppd
->hDevMode
== 0) {
2188 TRACE(" No hDevMode yet... Need to create my own\n");
2189 lppd
->hDevMode
= GlobalAlloc(GMEM_MOVEABLE
,
2190 lpdm
->dmSize
+ lpdm
->dmDriverExtra
);
2192 lppd
->hDevMode
= GlobalReAlloc(lppd
->hDevMode
,
2193 lpdm
->dmSize
+ lpdm
->dmDriverExtra
,
2196 lpdmReturn
= GlobalLock(lppd
->hDevMode
);
2197 memcpy(lpdmReturn
, lpdm
, lpdm
->dmSize
+ lpdm
->dmDriverExtra
);
2199 PRINTDLG_CreateDevNames(&(lppd
->hDevNames
),
2204 GlobalUnlock(lppd
->hDevMode
);
2206 HeapFree(GetProcessHeap(), 0, PrintStructures
->lpDevMode
);
2207 HeapFree(GetProcessHeap(), 0, PrintStructures
->lpPrinterInfo
);
2208 HeapFree(GetProcessHeap(), 0, PrintStructures
->lpDriverInfo
);
2209 HeapFree(GetProcessHeap(), 0, PrintStructures
);
2211 if(bRet
&& (lppd
->Flags
& PD_RETURNDC
|| lppd
->Flags
& PD_RETURNIC
))
2212 bRet
= PRINTDLG_CreateDCA(lppd
);
2214 TRACE("exit! (%d)\n", bRet
);
2218 /***********************************************************************
2219 * PrintDlgW (COMDLG32.@)
2223 BOOL WINAPI
PrintDlgW(LPPRINTDLGW lppd
)
2231 COMDLG32_SetCommDlgExtendedError(CDERR_INITIALIZATION
);
2235 if(TRACE_ON(commdlg
)) {
2236 char flagstr
[1000] = "";
2237 const struct pd_flags
*pflag
= pd_flags
;
2238 for( ; pflag
->name
; pflag
++) {
2239 if(lppd
->Flags
& pflag
->flag
)
2240 strcat(flagstr
, pflag
->name
);
2242 TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
2243 "pp. %d-%d, min p %d, max p %d, copies %d, hinst %p\n"
2244 "flags %08x (%s)\n",
2245 lppd
, lppd
->hwndOwner
, lppd
->hDevMode
, lppd
->hDevNames
,
2246 lppd
->nFromPage
, lppd
->nToPage
, lppd
->nMinPage
, lppd
->nMaxPage
,
2247 lppd
->nCopies
, lppd
->hInstance
, lppd
->Flags
, flagstr
);
2250 if(lppd
->lStructSize
!= sizeof(PRINTDLGW
)) {
2251 WARN("structure size failure !!!\n");
2252 COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE
);
2256 if(lppd
->Flags
& PD_RETURNDEFAULT
) {
2257 PRINTER_INFO_2W
*pbuf
;
2258 DRIVER_INFO_3W
*dbuf
;
2262 if(lppd
->hDevMode
|| lppd
->hDevNames
) {
2263 WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
2264 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE
);
2267 if(!PRINTDLG_OpenDefaultPrinter(&hprn
)) {
2268 WARN("Can't find default printer\n");
2269 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN
);
2273 GetPrinterW(hprn
, 2, NULL
, 0, &needed
);
2274 pbuf
= HeapAlloc(GetProcessHeap(), 0, needed
);
2275 GetPrinterW(hprn
, 2, (LPBYTE
)pbuf
, needed
, &needed
);
2277 GetPrinterDriverW(hprn
, NULL
, 3, NULL
, 0, &needed
);
2278 dbuf
= HeapAlloc(GetProcessHeap(),0,needed
);
2279 if (!GetPrinterDriverW(hprn
, NULL
, 3, (LPBYTE
)dbuf
, needed
, &needed
)) {
2280 ERR("GetPrinterDriverA failed, le %d, fix your config for printer %s!\n",
2281 GetLastError(),debugstr_w(pbuf
->pPrinterName
));
2282 HeapFree(GetProcessHeap(), 0, dbuf
);
2283 HeapFree(GetProcessHeap(), 0, pbuf
);
2284 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE
);
2289 PRINTDLG_CreateDevNamesW(&(lppd
->hDevNames
),
2293 lppd
->hDevMode
= GlobalAlloc(GMEM_MOVEABLE
, pbuf
->pDevMode
->dmSize
+
2294 pbuf
->pDevMode
->dmDriverExtra
);
2295 ptr
= GlobalLock(lppd
->hDevMode
);
2296 memcpy(ptr
, pbuf
->pDevMode
, pbuf
->pDevMode
->dmSize
+
2297 pbuf
->pDevMode
->dmDriverExtra
);
2298 GlobalUnlock(lppd
->hDevMode
);
2299 HeapFree(GetProcessHeap(), 0, pbuf
);
2300 HeapFree(GetProcessHeap(), 0, dbuf
);
2304 PRINT_PTRW
*PrintStructures
;
2306 /* load Dialog resources,
2307 * depending on Flags indicates Print32 or Print32_setup dialog
2309 hDlgTmpl
= PRINTDLG_GetDlgTemplateW(lppd
);
2311 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
2314 ptr
= LockResource( hDlgTmpl
);
2316 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
2320 PrintStructures
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2321 sizeof(PRINT_PTRW
));
2322 PrintStructures
->lpPrintDlg
= lppd
;
2324 /* and create & process the dialog .
2325 * -1 is failure, 0 is broken hwnd, everything else is ok.
2327 hInst
= COMDLG32_hInstance
;
2328 if (lppd
->Flags
& (PD_ENABLESETUPTEMPLATE
| PD_ENABLEPRINTTEMPLATE
)) hInst
= lppd
->hInstance
;
2329 bRet
= (0<DialogBoxIndirectParamW(hInst
, ptr
, lppd
->hwndOwner
,
2331 (LPARAM
)PrintStructures
));
2334 DEVMODEW
*lpdm
= PrintStructures
->lpDevMode
, *lpdmReturn
;
2335 PRINTER_INFO_2W
*pi
= PrintStructures
->lpPrinterInfo
;
2336 DRIVER_INFO_3W
*di
= PrintStructures
->lpDriverInfo
;
2338 if (lppd
->hDevMode
== 0) {
2339 TRACE(" No hDevMode yet... Need to create my own\n");
2340 lppd
->hDevMode
= GlobalAlloc(GMEM_MOVEABLE
,
2341 lpdm
->dmSize
+ lpdm
->dmDriverExtra
);
2344 if((locks
= (GlobalFlags(lppd
->hDevMode
) & GMEM_LOCKCOUNT
))) {
2345 WARN("hDevMode has %d locks on it. Unlocking it now\n", locks
);
2347 GlobalUnlock(lppd
->hDevMode
);
2348 TRACE("Now got %d locks\n", locks
);
2351 lppd
->hDevMode
= GlobalReAlloc(lppd
->hDevMode
,
2352 lpdm
->dmSize
+ lpdm
->dmDriverExtra
,
2355 lpdmReturn
= GlobalLock(lppd
->hDevMode
);
2356 memcpy(lpdmReturn
, lpdm
, lpdm
->dmSize
+ lpdm
->dmDriverExtra
);
2358 if (lppd
->hDevNames
!= 0) {
2360 if((locks
= (GlobalFlags(lppd
->hDevNames
) & GMEM_LOCKCOUNT
))) {
2361 WARN("hDevNames has %d locks on it. Unlocking it now\n", locks
);
2363 GlobalUnlock(lppd
->hDevNames
);
2366 PRINTDLG_CreateDevNamesW(&(lppd
->hDevNames
),
2371 GlobalUnlock(lppd
->hDevMode
);
2373 HeapFree(GetProcessHeap(), 0, PrintStructures
->lpDevMode
);
2374 HeapFree(GetProcessHeap(), 0, PrintStructures
->lpPrinterInfo
);
2375 HeapFree(GetProcessHeap(), 0, PrintStructures
->lpDriverInfo
);
2376 HeapFree(GetProcessHeap(), 0, PrintStructures
);
2378 if(bRet
&& (lppd
->Flags
& PD_RETURNDC
|| lppd
->Flags
& PD_RETURNIC
))
2379 bRet
= PRINTDLG_CreateDCW(lppd
);
2381 TRACE("exit! (%d)\n", bRet
);
2385 /***********************************************************************
2390 * cmb1 - printer select (not in standard dialog template)
2392 * cmb3 - source (tray?)
2393 * edt4 - border left
2395 * edt6 - border right
2396 * edt7 - border bottom
2397 * psh3 - "Printer..."
2405 LPPAGESETUPDLGA dlga
;
2406 LPPAGESETUPDLGW dlgw
;
2408 HWND hDlg
; /* Page Setup dialog handle */
2409 RECT rtDrawRect
; /* Drawing rect for page */
2412 static inline DWORD
pagesetup_get_flags(const pagesetup_data
*data
)
2414 return data
->u
.dlgw
->Flags
;
2417 static inline BOOL
is_metric(const pagesetup_data
*data
)
2419 return pagesetup_get_flags(data
) & PSD_INHUNDREDTHSOFMILLIMETERS
;
2422 static inline LONG
tenths_mm_to_size(const pagesetup_data
*data
, LONG size
)
2424 if (is_metric(data
))
2427 return 10 * size
* 100 / 254;
2430 static inline LONG
thousandths_inch_to_size(const pagesetup_data
*data
, LONG size
)
2432 if (is_metric(data
))
2433 return size
* 254 / 100;
2438 static WCHAR
get_decimal_sep(void)
2444 WCHAR buf
[] = {'.', 0};
2445 GetLocaleInfoW(LOCALE_USER_DEFAULT
, LOCALE_SDECIMAL
, buf
, sizeof(buf
) / sizeof(buf
[0]));
2451 static void size2str(const pagesetup_data
*data
, DWORD size
, LPWSTR strout
)
2453 WCHAR integer_fmt
[] = {'%','d',0};
2454 WCHAR hundredths_fmt
[] = {'%','d','%','c','%','0','2','d',0};
2455 WCHAR thousandths_fmt
[] = {'%','d','%','c','%','0','3','d',0};
2457 /* FIXME use LOCALE_SDECIMAL when the edit parsing code can cope */
2459 if (is_metric(data
))
2462 wsprintfW(strout
, hundredths_fmt
, size
/ 100, get_decimal_sep(), size
% 100);
2464 wsprintfW(strout
, integer_fmt
, size
/ 100);
2469 wsprintfW(strout
, thousandths_fmt
, size
/ 1000, get_decimal_sep(), size
% 1000);
2471 wsprintfW(strout
, integer_fmt
, size
/ 1000);
2476 static inline BOOL
is_default_metric(void)
2479 GetLocaleInfoW(LOCALE_USER_DEFAULT
, LOCALE_IMEASURE
| LOCALE_RETURN_NUMBER
,
2480 (LPWSTR
)&system
, sizeof(system
));
2484 /**********************************************
2486 * Cyclically permute the four members of rc
2487 * If sense is TRUE l -> t -> r -> b
2488 * otherwise l <- t <- r <- b
2490 static inline void rotate_rect(RECT
*rc
, BOOL sense
)
2496 rc
->bottom
= rc
->right
;
2497 rc
->right
= rc
->top
;
2505 rc
->top
= rc
->right
;
2506 rc
->right
= rc
->bottom
;
2511 static void pagesetup_set_orientation(pagesetup_data
*data
, WORD orient
)
2513 DEVMODEW
*dm
= GlobalLock(data
->u
.dlgw
->hDevMode
);
2515 assert(orient
== DMORIENT_PORTRAIT
|| orient
== DMORIENT_LANDSCAPE
);
2518 dm
->u1
.s1
.dmOrientation
= orient
;
2521 DEVMODEA
*dmA
= (DEVMODEA
*)dm
;
2522 dmA
->u1
.s1
.dmOrientation
= orient
;
2524 GlobalUnlock(data
->u
.dlgw
->hDevMode
);
2527 static WORD
pagesetup_get_orientation(const pagesetup_data
*data
)
2529 DEVMODEW
*dm
= GlobalLock(data
->u
.dlgw
->hDevMode
);
2533 orient
= dm
->u1
.s1
.dmOrientation
;
2536 DEVMODEA
*dmA
= (DEVMODEA
*)dm
;
2537 orient
= dmA
->u1
.s1
.dmOrientation
;
2539 GlobalUnlock(data
->u
.dlgw
->hDevMode
);
2543 static void pagesetup_set_papersize(pagesetup_data
*data
, WORD paper
)
2545 DEVMODEW
*dm
= GlobalLock(data
->u
.dlgw
->hDevMode
);
2548 dm
->u1
.s1
.dmPaperSize
= paper
;
2551 DEVMODEA
*dmA
= (DEVMODEA
*)dm
;
2552 dmA
->u1
.s1
.dmPaperSize
= paper
;
2554 GlobalUnlock(data
->u
.dlgw
->hDevMode
);
2557 static WORD
pagesetup_get_papersize(const pagesetup_data
*data
)
2559 DEVMODEW
*dm
= GlobalLock(data
->u
.dlgw
->hDevMode
);
2563 paper
= dm
->u1
.s1
.dmPaperSize
;
2566 DEVMODEA
*dmA
= (DEVMODEA
*)dm
;
2567 paper
= dmA
->u1
.s1
.dmPaperSize
;
2569 GlobalUnlock(data
->u
.dlgw
->hDevMode
);
2573 static void pagesetup_set_defaultsource(pagesetup_data
*data
, WORD source
)
2575 DEVMODEW
*dm
= GlobalLock(data
->u
.dlgw
->hDevMode
);
2578 dm
->u1
.s1
.dmDefaultSource
= source
;
2581 DEVMODEA
*dmA
= (DEVMODEA
*)dm
;
2582 dmA
->u1
.s1
.dmDefaultSource
= source
;
2584 GlobalUnlock(data
->u
.dlgw
->hDevMode
);
2589 devnames_driver_name
,
2590 devnames_device_name
,
2591 devnames_output_name
2595 static inline WORD
get_devname_offset(const DEVNAMES
*dn
, devnames_name which
)
2599 case devnames_driver_name
: return dn
->wDriverOffset
;
2600 case devnames_device_name
: return dn
->wDeviceOffset
;
2601 case devnames_output_name
: return dn
->wOutputOffset
;
2603 ERR("Shouldn't be here\n");
2607 static WCHAR
*pagesetup_get_a_devname(const pagesetup_data
*data
, devnames_name which
)
2612 dn
= GlobalLock(data
->u
.dlgw
->hDevNames
);
2614 name
= strdupW((WCHAR
*)dn
+ get_devname_offset(dn
, which
));
2617 int len
= MultiByteToWideChar(CP_ACP
, 0, (char*)dn
+ get_devname_offset(dn
, which
), -1, NULL
, 0);
2618 name
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2619 MultiByteToWideChar(CP_ACP
, 0, (char*)dn
+ get_devname_offset(dn
, which
), -1, name
, len
);
2621 GlobalUnlock(data
->u
.dlgw
->hDevNames
);
2625 static WCHAR
*pagesetup_get_drvname(const pagesetup_data
*data
)
2627 return pagesetup_get_a_devname(data
, devnames_driver_name
);
2630 static WCHAR
*pagesetup_get_devname(const pagesetup_data
*data
)
2632 return pagesetup_get_a_devname(data
, devnames_device_name
);
2635 static WCHAR
*pagesetup_get_portname(const pagesetup_data
*data
)
2637 return pagesetup_get_a_devname(data
, devnames_output_name
);
2640 static void pagesetup_release_a_devname(const pagesetup_data
*data
, WCHAR
*name
)
2642 HeapFree(GetProcessHeap(), 0, name
);
2645 static void pagesetup_set_devnames(pagesetup_data
*data
, LPCWSTR drv
, LPCWSTR devname
, LPCWSTR port
)
2649 DWORD len
= sizeof(DEVNAMES
), drv_len
, dev_len
, port_len
;
2653 drv_len
= (strlenW(drv
) + 1) * sizeof(WCHAR
);
2654 dev_len
= (strlenW(devname
) + 1) * sizeof(WCHAR
);
2655 port_len
= (strlenW(port
) + 1) * sizeof(WCHAR
);
2659 drv_len
= WideCharToMultiByte(CP_ACP
, 0, drv
, -1, NULL
, 0, NULL
, NULL
);
2660 dev_len
= WideCharToMultiByte(CP_ACP
, 0, devname
, -1, NULL
, 0, NULL
, NULL
);
2661 port_len
= WideCharToMultiByte(CP_ACP
, 0, port
, -1, NULL
, 0, NULL
, NULL
);
2663 len
+= drv_len
+ dev_len
+ port_len
;
2665 if(data
->u
.dlgw
->hDevNames
)
2666 data
->u
.dlgw
->hDevNames
= GlobalReAlloc(data
->u
.dlgw
->hDevNames
, len
, GMEM_MOVEABLE
);
2668 data
->u
.dlgw
->hDevNames
= GlobalAlloc(GMEM_MOVEABLE
, len
);
2670 dn
= GlobalLock(data
->u
.dlgw
->hDevNames
);
2674 WCHAR
*ptr
= (WCHAR
*)(dn
+ 1);
2675 len
= sizeof(DEVNAMES
) / sizeof(WCHAR
);
2676 dn
->wDriverOffset
= len
;
2678 ptr
+= drv_len
/ sizeof(WCHAR
);
2679 len
+= drv_len
/ sizeof(WCHAR
);
2680 dn
->wDeviceOffset
= len
;
2681 strcpyW(ptr
, devname
);
2682 ptr
+= dev_len
/ sizeof(WCHAR
);
2683 len
+= dev_len
/ sizeof(WCHAR
);
2684 dn
->wOutputOffset
= len
;
2689 char *ptr
= (char *)(dn
+ 1);
2690 len
= sizeof(DEVNAMES
);
2691 dn
->wDriverOffset
= len
;
2692 WideCharToMultiByte(CP_ACP
, 0, drv
, -1, ptr
, drv_len
, NULL
, NULL
);
2695 dn
->wDeviceOffset
= len
;
2696 WideCharToMultiByte(CP_ACP
, 0, devname
, -1, ptr
, dev_len
, NULL
, NULL
);
2699 dn
->wOutputOffset
= len
;
2700 WideCharToMultiByte(CP_ACP
, 0, port
, -1, ptr
, port_len
, NULL
, NULL
);
2704 len
= sizeof(def
) / sizeof(def
[0]);
2705 GetDefaultPrinterW(def
, &len
);
2706 if(!lstrcmpW(def
, devname
))
2709 GlobalUnlock(data
->u
.dlgw
->hDevNames
);
2712 static DEVMODEW
*pagesetup_get_devmode(const pagesetup_data
*data
)
2714 DEVMODEW
*dm
= GlobalLock(data
->u
.dlgw
->hDevMode
);
2719 /* We make a copy even in the unicode case because the ptr
2720 may get passed back to us in pagesetup_set_devmode. */
2721 ret
= HeapAlloc(GetProcessHeap(), 0, dm
->dmSize
+ dm
->dmDriverExtra
);
2722 memcpy(ret
, dm
, dm
->dmSize
+ dm
->dmDriverExtra
);
2725 ret
= GdiConvertToDevmodeW((DEVMODEA
*)dm
);
2727 GlobalUnlock(data
->u
.dlgw
->hDevMode
);
2731 static void pagesetup_release_devmode(const pagesetup_data
*data
, DEVMODEW
*dm
)
2733 HeapFree(GetProcessHeap(), 0, dm
);
2736 static void pagesetup_set_devmode(pagesetup_data
*data
, DEVMODEW
*dm
)
2738 DEVMODEA
*dmA
= NULL
;
2744 size
= dm
->dmSize
+ dm
->dmDriverExtra
;
2749 dmA
= convert_to_devmodeA(dm
);
2750 size
= dmA
->dmSize
+ dmA
->dmDriverExtra
;
2754 if(data
->u
.dlgw
->hDevMode
)
2755 data
->u
.dlgw
->hDevMode
= GlobalReAlloc(data
->u
.dlgw
->hDevMode
, size
,
2758 data
->u
.dlgw
->hDevMode
= GlobalAlloc(GMEM_MOVEABLE
, size
);
2760 dst
= GlobalLock(data
->u
.dlgw
->hDevMode
);
2761 memcpy(dst
, src
, size
);
2762 GlobalUnlock(data
->u
.dlgw
->hDevMode
);
2763 HeapFree(GetProcessHeap(), 0, dmA
);
2766 static inline POINT
*pagesetup_get_papersize_pt(const pagesetup_data
*data
)
2768 return &data
->u
.dlgw
->ptPaperSize
;
2771 static inline RECT
*pagesetup_get_margin_rect(const pagesetup_data
*data
)
2773 return &data
->u
.dlgw
->rtMargin
;
2782 static inline LPPAGESETUPHOOK
pagesetup_get_hook(const pagesetup_data
*data
, hook_type which
)
2786 case page_setup_hook
: return data
->u
.dlgw
->lpfnPageSetupHook
;
2787 case page_paint_hook
: return data
->u
.dlgw
->lpfnPagePaintHook
;
2792 /* This should only be used in calls to hook procs so we return the ptr
2793 already cast to LPARAM */
2794 static inline LPARAM
pagesetup_get_dlg_struct(const pagesetup_data
*data
)
2796 return (LPARAM
)data
->u
.dlgw
;
2799 static inline void swap_point(POINT
*pt
)
2806 static BOOL
pagesetup_update_papersize(pagesetup_data
*data
)
2809 LPWSTR devname
, portname
;
2811 WORD
*words
= NULL
, paperword
;
2812 POINT
*points
= NULL
;
2813 BOOL retval
= FALSE
;
2815 dm
= pagesetup_get_devmode(data
);
2816 devname
= pagesetup_get_devname(data
);
2817 portname
= pagesetup_get_portname(data
);
2819 num
= DeviceCapabilitiesW(devname
, portname
, DC_PAPERS
, NULL
, dm
);
2822 FIXME("No papernames found for %s/%s\n", debugstr_w(devname
), debugstr_w(portname
));
2826 words
= HeapAlloc(GetProcessHeap(), 0, num
* sizeof(WORD
));
2827 points
= HeapAlloc(GetProcessHeap(), 0, num
* sizeof(POINT
));
2829 if (num
!= DeviceCapabilitiesW(devname
, portname
, DC_PAPERS
, (LPWSTR
)words
, dm
))
2831 FIXME("Number of returned words is not %d\n", num
);
2835 if (num
!= DeviceCapabilitiesW(devname
, portname
, DC_PAPERSIZE
, (LPWSTR
)points
, dm
))
2837 FIXME("Number of returned sizes is not %d\n", num
);
2841 paperword
= pagesetup_get_papersize(data
);
2843 for (i
= 0; i
< num
; i
++)
2844 if (words
[i
] == paperword
)
2849 FIXME("Papersize %d not found in list?\n", paperword
);
2853 /* this is _10ths_ of a millimeter */
2854 pagesetup_get_papersize_pt(data
)->x
= tenths_mm_to_size(data
, points
[i
].x
);
2855 pagesetup_get_papersize_pt(data
)->y
= tenths_mm_to_size(data
, points
[i
].y
);
2857 if(pagesetup_get_orientation(data
) == DMORIENT_LANDSCAPE
)
2858 swap_point(pagesetup_get_papersize_pt(data
));
2863 HeapFree(GetProcessHeap(), 0, words
);
2864 HeapFree(GetProcessHeap(), 0, points
);
2865 pagesetup_release_a_devname(data
, portname
);
2866 pagesetup_release_a_devname(data
, devname
);
2867 pagesetup_release_devmode(data
, dm
);
2872 /**********************************************************************************************
2873 * pagesetup_change_printer
2875 * Redefines hDevMode and hDevNames HANDLES and initialises it.
2878 static BOOL
pagesetup_change_printer(LPWSTR name
, pagesetup_data
*data
)
2882 PRINTER_INFO_2W
*prn_info
= NULL
;
2883 DRIVER_INFO_3W
*drv_info
= NULL
;
2884 DEVMODEW
*dm
= NULL
;
2885 BOOL retval
= FALSE
;
2887 if(!OpenPrinterW(name
, &hprn
, NULL
))
2889 ERR("Can't open printer %s\n", debugstr_w(name
));
2893 GetPrinterW(hprn
, 2, NULL
, 0, &needed
);
2894 prn_info
= HeapAlloc(GetProcessHeap(), 0, needed
);
2895 GetPrinterW(hprn
, 2, (LPBYTE
)prn_info
, needed
, &needed
);
2896 GetPrinterDriverW(hprn
, NULL
, 3, NULL
, 0, &needed
);
2897 drv_info
= HeapAlloc(GetProcessHeap(), 0, needed
);
2898 if(!GetPrinterDriverW(hprn
, NULL
, 3, (LPBYTE
)drv_info
, needed
, &needed
))
2900 ERR("GetPrinterDriverA failed for %s, fix your config!\n", debugstr_w(prn_info
->pPrinterName
));
2905 needed
= DocumentPropertiesW(0, 0, name
, NULL
, NULL
, 0);
2908 ERR("DocumentProperties fails on %s\n", debugstr_w(name
));
2912 dm
= HeapAlloc(GetProcessHeap(), 0, needed
);
2913 DocumentPropertiesW(0, 0, name
, dm
, NULL
, DM_OUT_BUFFER
);
2915 pagesetup_set_devmode(data
, dm
);
2916 pagesetup_set_devnames(data
, drv_info
->pDriverPath
, prn_info
->pPrinterName
,
2917 prn_info
->pPortName
);
2921 HeapFree(GetProcessHeap(), 0, dm
);
2922 HeapFree(GetProcessHeap(), 0, prn_info
);
2923 HeapFree(GetProcessHeap(), 0, drv_info
);
2927 /****************************************************************************************
2928 * pagesetup_init_combos
2930 * Fills Printers, Paper and Source combos
2933 static void pagesetup_init_combos(HWND hDlg
, pagesetup_data
*data
)
2936 LPWSTR devname
, portname
;
2938 dm
= pagesetup_get_devmode(data
);
2939 devname
= pagesetup_get_devname(data
);
2940 portname
= pagesetup_get_portname(data
);
2942 PRINTDLG_SetUpPrinterListComboW(hDlg
, cmb1
, devname
);
2943 PRINTDLG_SetUpPaperComboBoxW(hDlg
, cmb2
, devname
, portname
, dm
);
2944 PRINTDLG_SetUpPaperComboBoxW(hDlg
, cmb3
, devname
, portname
, dm
);
2946 pagesetup_release_a_devname(data
, portname
);
2947 pagesetup_release_a_devname(data
, devname
);
2948 pagesetup_release_devmode(data
, dm
);
2952 /****************************************************************************************
2953 * pagesetup_change_printer_dialog
2955 * Pops up another dialog that lets the user pick another printer.
2957 * For now we display the PrintDlg, this should display a striped down version of it.
2959 static void pagesetup_change_printer_dialog(HWND hDlg
, pagesetup_data
*data
)
2962 LPWSTR drvname
, devname
, portname
;
2963 DEVMODEW
*tmp_dm
, *dm
;
2965 memset(&prnt
, 0, sizeof(prnt
));
2966 prnt
.lStructSize
= sizeof(prnt
);
2968 prnt
.hwndOwner
= hDlg
;
2970 drvname
= pagesetup_get_drvname(data
);
2971 devname
= pagesetup_get_devname(data
);
2972 portname
= pagesetup_get_portname(data
);
2974 PRINTDLG_CreateDevNamesW(&prnt
.hDevNames
, drvname
, devname
, portname
);
2975 pagesetup_release_a_devname(data
, portname
);
2976 pagesetup_release_a_devname(data
, devname
);
2977 pagesetup_release_a_devname(data
, drvname
);
2979 tmp_dm
= pagesetup_get_devmode(data
);
2980 prnt
.hDevMode
= GlobalAlloc(GMEM_MOVEABLE
, tmp_dm
->dmSize
+ tmp_dm
->dmDriverExtra
);
2981 dm
= GlobalLock(prnt
.hDevMode
);
2982 memcpy(dm
, tmp_dm
, tmp_dm
->dmSize
+ tmp_dm
->dmDriverExtra
);
2983 GlobalUnlock(prnt
.hDevMode
);
2984 pagesetup_release_devmode(data
, tmp_dm
);
2986 if (PrintDlgW(&prnt
))
2988 DEVMODEW
*dm
= GlobalLock(prnt
.hDevMode
);
2989 DEVNAMES
*dn
= GlobalLock(prnt
.hDevNames
);
2991 pagesetup_set_devnames(data
, (WCHAR
*)dn
+ dn
->wDriverOffset
,
2992 (WCHAR
*)dn
+ dn
->wDeviceOffset
, (WCHAR
*)dn
+ dn
->wOutputOffset
);
2993 pagesetup_set_devmode(data
, dm
);
2994 GlobalUnlock(prnt
.hDevNames
);
2995 GlobalUnlock(prnt
.hDevMode
);
2996 pagesetup_init_combos(hDlg
, data
);
2999 GlobalFree(prnt
.hDevMode
);
3000 GlobalFree(prnt
.hDevNames
);
3004 /******************************************************************************************
3005 * pagesetup_change_preview
3007 * Changes paper preview size / position
3010 static void pagesetup_change_preview(const pagesetup_data
*data
)
3012 LONG width
, height
, x
, y
;
3014 const int shadow
= 4;
3016 if(pagesetup_get_orientation(data
) == DMORIENT_LANDSCAPE
)
3018 width
= data
->rtDrawRect
.right
- data
->rtDrawRect
.left
;
3019 height
= pagesetup_get_papersize_pt(data
)->y
* width
/ pagesetup_get_papersize_pt(data
)->x
;
3023 height
= data
->rtDrawRect
.bottom
- data
->rtDrawRect
.top
;
3024 width
= pagesetup_get_papersize_pt(data
)->x
* height
/ pagesetup_get_papersize_pt(data
)->y
;
3026 x
= (data
->rtDrawRect
.right
+ data
->rtDrawRect
.left
- width
) / 2;
3027 y
= (data
->rtDrawRect
.bottom
+ data
->rtDrawRect
.top
- height
) / 2;
3028 TRACE("draw rect %s x=%d, y=%d, w=%d, h=%d\n",
3029 wine_dbgstr_rect(&data
->rtDrawRect
), x
, y
, width
, height
);
3031 MoveWindow(GetDlgItem(data
->hDlg
, rct2
), x
+ width
, y
+ shadow
, shadow
, height
, FALSE
);
3032 MoveWindow(GetDlgItem(data
->hDlg
, rct3
), x
+ shadow
, y
+ height
, width
, shadow
, FALSE
);
3033 MoveWindow(GetDlgItem(data
->hDlg
, rct1
), x
, y
, width
, height
, FALSE
);
3035 tmp
= data
->rtDrawRect
;
3036 tmp
.right
+= shadow
;
3037 tmp
.bottom
+= shadow
;
3038 InvalidateRect(data
->hDlg
, &tmp
, TRUE
);
3041 static inline LONG
*element_from_margin_id(RECT
*rc
, WORD id
)
3045 case edt4
: return &rc
->left
;
3046 case edt5
: return &rc
->top
;
3047 case edt6
: return &rc
->right
;
3048 case edt7
: return &rc
->bottom
;
3053 static void update_margin_edits(HWND hDlg
, const pagesetup_data
*data
, WORD id
)
3058 for(idx
= edt4
; idx
<= edt7
; idx
++)
3060 if(id
== 0 || id
== idx
)
3062 size2str(data
, *element_from_margin_id(pagesetup_get_margin_rect(data
), idx
), str
);
3063 SetDlgItemTextW(hDlg
, idx
, str
);
3068 static void margin_edit_notification(HWND hDlg
, const pagesetup_data
*data
, WORD msg
, WORD id
)
3076 LONG
*value
= element_from_margin_id(pagesetup_get_margin_rect(data
), id
);
3078 if (GetDlgItemTextW(hDlg
, id
, buf
, sizeof(buf
) / sizeof(buf
[0])) != 0)
3081 WCHAR decimal
= get_decimal_sep();
3083 val
= strtolW(buf
, &end
, 10);
3084 if(end
!= buf
|| *end
== decimal
)
3086 int mult
= is_metric(data
) ? 100 : 1000;
3095 val
+= (*end
- '0') * mult
;
3107 update_margin_edits(hDlg
, data
, id
);
3112 static void set_margin_groupbox_title(HWND hDlg
, const pagesetup_data
*data
)
3116 if(LoadStringW(COMDLG32_hInstance
, is_metric(data
) ? PD32_MARGINS_IN_MILLIMETERS
: PD32_MARGINS_IN_INCHES
,
3117 title
, sizeof(title
)/sizeof(title
[0])))
3118 SetDlgItemTextW(hDlg
, grp4
, title
);
3121 static void pagesetup_update_orientation_buttons(HWND hDlg
, const pagesetup_data
*data
)
3123 if (pagesetup_get_orientation(data
) == DMORIENT_LANDSCAPE
)
3124 CheckRadioButton(hDlg
, rad1
, rad2
, rad2
);
3126 CheckRadioButton(hDlg
, rad1
, rad2
, rad1
);
3129 /****************************************************************************************
3130 * pagesetup_printer_properties
3132 * Handle invocation of the 'Properties' button (not present in the default template).
3134 static void pagesetup_printer_properties(HWND hDlg
, pagesetup_data
*data
)
3142 devname
= pagesetup_get_devname(data
);
3144 if (!OpenPrinterW(devname
, &hprn
, NULL
))
3146 FIXME("Call to OpenPrinter did not succeed!\n");
3147 pagesetup_release_a_devname(data
, devname
);
3151 dm
= pagesetup_get_devmode(data
);
3152 DocumentPropertiesW(hDlg
, hprn
, devname
, dm
, dm
, DM_IN_BUFFER
| DM_OUT_BUFFER
| DM_IN_PROMPT
);
3153 pagesetup_set_devmode(data
, dm
);
3154 pagesetup_release_devmode(data
, dm
);
3155 pagesetup_release_a_devname(data
, devname
);
3158 /* Changing paper */
3159 pagesetup_update_papersize(data
);
3160 pagesetup_update_orientation_buttons(hDlg
, data
);
3162 /* Changing paper preview */
3163 pagesetup_change_preview(data
);
3165 /* Selecting paper in combo */
3166 count
= SendDlgItemMessageW(hDlg
, cmb2
, CB_GETCOUNT
, 0, 0);
3169 WORD paperword
= pagesetup_get_papersize(data
);
3170 for(i
= 0; i
< count
; i
++)
3172 if(SendDlgItemMessageW(hDlg
, cmb2
, CB_GETITEMDATA
, i
, 0) == paperword
) {
3173 SendDlgItemMessageW(hDlg
, cmb2
, CB_SETCURSEL
, i
, 0);
3180 /********************************************************************************
3181 * pagesetup_wm_command
3182 * process WM_COMMAND message for PageSetupDlg
3185 * hDlg [in] Main dialog HANDLE
3186 * wParam [in] WM_COMMAND wParam
3187 * lParam [in] WM_COMMAND lParam
3188 * pda [in/out] ptr to PageSetupDataA
3191 static BOOL
pagesetup_wm_command(HWND hDlg
, WPARAM wParam
, LPARAM lParam
, pagesetup_data
*data
)
3193 WORD msg
= HIWORD(wParam
);
3194 WORD id
= LOWORD(wParam
);
3196 TRACE("loword (lparam) %d, wparam 0x%lx, lparam %08lx\n",
3197 LOWORD(lParam
),wParam
,lParam
);
3200 EndDialog(hDlg
, TRUE
);
3204 EndDialog(hDlg
, FALSE
);
3207 case psh3
: /* Printer... */
3208 pagesetup_change_printer_dialog(hDlg
, data
);
3211 case rad1
: /* Portrait */
3212 case rad2
: /* Landscape */
3213 if((id
== rad1
&& pagesetup_get_orientation(data
) == DMORIENT_LANDSCAPE
) ||
3214 (id
== rad2
&& pagesetup_get_orientation(data
) == DMORIENT_PORTRAIT
))
3216 pagesetup_set_orientation(data
, (id
== rad1
) ? DMORIENT_PORTRAIT
: DMORIENT_LANDSCAPE
);
3217 pagesetup_update_papersize(data
);
3218 rotate_rect(pagesetup_get_margin_rect(data
), (id
== rad2
));
3219 update_margin_edits(hDlg
, data
, 0);
3220 pagesetup_change_preview(data
);
3223 case cmb1
: /* Printer combo */
3224 if(msg
== CBN_SELCHANGE
)
3227 GetDlgItemTextW(hDlg
, id
, name
, sizeof(name
) / sizeof(name
[0]));
3228 pagesetup_change_printer(name
, data
);
3229 pagesetup_init_combos(hDlg
, data
);
3232 case cmb2
: /* Paper combo */
3233 if(msg
== CBN_SELCHANGE
)
3235 DWORD paperword
= SendDlgItemMessageW(hDlg
, cmb2
, CB_GETITEMDATA
,
3236 SendDlgItemMessageW(hDlg
, cmb2
, CB_GETCURSEL
, 0, 0), 0);
3237 if (paperword
!= CB_ERR
)
3239 pagesetup_set_papersize(data
, paperword
);
3240 pagesetup_update_papersize(data
);
3241 pagesetup_change_preview(data
);
3243 FIXME("could not get dialog text for papersize cmbbox?\n");
3246 case cmb3
: /* Paper Source */
3247 if(msg
== CBN_SELCHANGE
)
3249 WORD source
= SendDlgItemMessageW(hDlg
, cmb3
, CB_GETITEMDATA
,
3250 SendDlgItemMessageW(hDlg
, cmb3
, CB_GETCURSEL
, 0, 0), 0);
3251 pagesetup_set_defaultsource(data
, source
);
3254 case psh2
: /* Printer Properties button */
3255 pagesetup_printer_properties(hDlg
, data
);
3261 margin_edit_notification(hDlg
, data
, msg
, id
);
3264 InvalidateRect(GetDlgItem(hDlg
, rct1
), NULL
, TRUE
);
3268 /***********************************************************************
3269 * default_page_paint_hook
3270 * Default hook paint procedure that receives WM_PSD_* messages from the dialog box
3271 * whenever the sample page is redrawn.
3273 static UINT_PTR
default_page_paint_hook(HWND hwndDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
,
3274 const pagesetup_data
*data
)
3276 LPRECT lprc
= (LPRECT
) lParam
;
3277 HDC hdc
= (HDC
) wParam
;
3280 HFONT hfont
, holdfont
;
3282 TRACE("uMsg: WM_USER+%d\n",uMsg
-WM_USER
);
3283 /* Call user paint hook if enable */
3284 if (pagesetup_get_flags(data
) & PSD_ENABLEPAGEPAINTHOOK
)
3285 if (pagesetup_get_hook(data
, page_paint_hook
)(hwndDlg
, uMsg
, wParam
, lParam
))
3289 /* LPPAGESETUPDLG in lParam */
3290 case WM_PSD_PAGESETUPDLG
:
3291 /* Inform about the sample page rectangle */
3292 case WM_PSD_FULLPAGERECT
:
3293 /* Inform about the margin rectangle */
3294 case WM_PSD_MINMARGINRECT
:
3297 /* Draw dashed rectangle showing margins */
3298 case WM_PSD_MARGINRECT
:
3299 hpen
= CreatePen(PS_DASH
, 1, GetSysColor(COLOR_3DSHADOW
));
3300 holdpen
= SelectObject(hdc
, hpen
);
3301 Rectangle(hdc
, lprc
->left
, lprc
->top
, lprc
->right
, lprc
->bottom
);
3302 DeleteObject(SelectObject(hdc
, holdpen
));
3304 /* Draw the fake document */
3305 case WM_PSD_GREEKTEXTRECT
:
3306 /* select a nice scalable font, because we want the text really small */
3307 SystemParametersInfoW(SPI_GETICONTITLELOGFONT
, sizeof(lf
), &lf
, 0);
3308 lf
.lfHeight
= 6; /* value chosen based on visual effect */
3309 hfont
= CreateFontIndirectW(&lf
);
3310 holdfont
= SelectObject(hdc
, hfont
);
3312 /* if text not loaded, then do so now */
3313 if (wszFakeDocumentText
[0] == '\0')
3314 LoadStringW(COMDLG32_hInstance
,
3316 wszFakeDocumentText
,
3317 sizeof(wszFakeDocumentText
)/sizeof(wszFakeDocumentText
[0]));
3319 oldbkmode
= SetBkMode(hdc
, TRANSPARENT
);
3320 DrawTextW(hdc
, wszFakeDocumentText
, -1, lprc
, DT_TOP
|DT_LEFT
|DT_NOPREFIX
|DT_WORDBREAK
);
3321 SetBkMode(hdc
, oldbkmode
);
3323 DeleteObject(SelectObject(hdc
, holdfont
));
3326 /* Envelope stamp */
3327 case WM_PSD_ENVSTAMPRECT
:
3328 /* Return address */
3329 case WM_PSD_YAFULLPAGERECT
:
3330 FIXME("envelope/stamp is not implemented\n");
3333 FIXME("Unknown message %x\n",uMsg
);
3339 /***********************************************************************
3341 * The main paint procedure for the PageSetupDlg function.
3342 * The Page Setup dialog box includes an image of a sample page that shows how
3343 * the user's selections affect the appearance of the printed output.
3344 * The image consists of a rectangle that represents the selected paper
3345 * or envelope type, with a dotted-line rectangle representing
3346 * the current margins, and partial (Greek text) characters
3347 * to show how text looks on the printed page.
3349 * The following messages in the order sends to user hook procedure:
3350 * WM_PSD_PAGESETUPDLG Draw the contents of the sample page
3351 * WM_PSD_FULLPAGERECT Inform about the bounding rectangle
3352 * WM_PSD_MINMARGINRECT Inform about the margin rectangle (min margin?)
3353 * WM_PSD_MARGINRECT Draw the margin rectangle
3354 * WM_PSD_GREEKTEXTRECT Draw the Greek text inside the margin rectangle
3355 * If any of first three messages returns TRUE, painting done.
3358 * hWnd [in] Handle to the Page Setup dialog box
3359 * uMsg [in] Received message
3362 * WM_PSD_ENVSTAMPRECT Draw in the envelope-stamp rectangle (for envelopes only)
3363 * WM_PSD_YAFULLPAGERECT Draw the return address portion (for envelopes and other paper sizes)
3366 * FALSE if all done correctly
3371 static LRESULT CALLBACK
3372 PRINTDLG_PagePaintProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
3375 RECT rcClient
, rcMargin
;
3378 HBRUSH hbrush
, holdbrush
;
3379 pagesetup_data
*data
;
3380 int papersize
=0, orientation
=0; /* FIXME: set these values for the user paint hook */
3381 double scalx
, scaly
;
3383 if (uMsg
!= WM_PAINT
)
3384 return CallWindowProcA(lpfnStaticWndProc
, hWnd
, uMsg
, wParam
, lParam
);
3386 /* Processing WM_PAINT message */
3387 data
= GetPropW(hWnd
, pagesetupdlg_prop
);
3389 WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
3392 if (default_page_paint_hook(hWnd
, WM_PSD_PAGESETUPDLG
, MAKELONG(papersize
, orientation
),
3393 pagesetup_get_dlg_struct(data
), data
))
3396 hdc
= BeginPaint(hWnd
, &ps
);
3397 GetClientRect(hWnd
, &rcClient
);
3399 scalx
= rcClient
.right
/ (double)pagesetup_get_papersize_pt(data
)->x
;
3400 scaly
= rcClient
.bottom
/ (double)pagesetup_get_papersize_pt(data
)->y
;
3401 rcMargin
= rcClient
;
3403 rcMargin
.left
+= pagesetup_get_margin_rect(data
)->left
* scalx
;
3404 rcMargin
.top
+= pagesetup_get_margin_rect(data
)->top
* scaly
;
3405 rcMargin
.right
-= pagesetup_get_margin_rect(data
)->right
* scalx
;
3406 rcMargin
.bottom
-= pagesetup_get_margin_rect(data
)->bottom
* scaly
;
3408 /* if the space is too small then we make sure to not draw anything */
3409 rcMargin
.left
= min(rcMargin
.left
, rcMargin
.right
);
3410 rcMargin
.top
= min(rcMargin
.top
, rcMargin
.bottom
);
3412 if (!default_page_paint_hook(hWnd
, WM_PSD_FULLPAGERECT
, (WPARAM
)hdc
, (LPARAM
)&rcClient
, data
) &&
3413 !default_page_paint_hook(hWnd
, WM_PSD_MINMARGINRECT
, (WPARAM
)hdc
, (LPARAM
)&rcMargin
, data
) )
3415 /* fill background */
3416 hbrush
= GetSysColorBrush(COLOR_3DHIGHLIGHT
);
3417 FillRect(hdc
, &rcClient
, hbrush
);
3418 holdbrush
= SelectObject(hdc
, hbrush
);
3420 hpen
= CreatePen(PS_SOLID
, 1, GetSysColor(COLOR_3DSHADOW
));
3421 holdpen
= SelectObject(hdc
, hpen
);
3423 /* paint left edge */
3424 MoveToEx(hdc
, rcClient
.left
, rcClient
.top
, NULL
);
3425 LineTo(hdc
, rcClient
.left
, rcClient
.bottom
-1);
3427 /* paint top edge */
3428 MoveToEx(hdc
, rcClient
.left
, rcClient
.top
, NULL
);
3429 LineTo(hdc
, rcClient
.right
, rcClient
.top
);
3431 hpen
= CreatePen(PS_SOLID
, 1, GetSysColor(COLOR_3DDKSHADOW
));
3432 DeleteObject(SelectObject(hdc
, hpen
));
3434 /* paint right edge */
3435 MoveToEx(hdc
, rcClient
.right
-1, rcClient
.top
, NULL
);
3436 LineTo(hdc
, rcClient
.right
-1, rcClient
.bottom
);
3438 /* paint bottom edge */
3439 MoveToEx(hdc
, rcClient
.left
, rcClient
.bottom
-1, NULL
);
3440 LineTo(hdc
, rcClient
.right
, rcClient
.bottom
-1);
3442 DeleteObject(SelectObject(hdc
, holdpen
));
3443 DeleteObject(SelectObject(hdc
, holdbrush
));
3445 default_page_paint_hook(hWnd
, WM_PSD_MARGINRECT
, (WPARAM
)hdc
, (LPARAM
)&rcMargin
, data
);
3447 /* give text a bit of a space from the frame */
3450 rcMargin
.right
-= 2;
3451 rcMargin
.bottom
-= 2;
3453 /* if the space is too small then we make sure to not draw anything */
3454 rcMargin
.left
= min(rcMargin
.left
, rcMargin
.right
);
3455 rcMargin
.top
= min(rcMargin
.top
, rcMargin
.bottom
);
3457 default_page_paint_hook(hWnd
, WM_PSD_GREEKTEXTRECT
, (WPARAM
)hdc
, (LPARAM
)&rcMargin
, data
);
3460 EndPaint(hWnd
, &ps
);
3464 /*******************************************************
3465 * The margin edit controls are subclassed to filter
3466 * anything other than numbers and the decimal separator.
3468 static LRESULT CALLBACK
pagesetup_margin_editproc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
3472 WCHAR decimal
= get_decimal_sep();
3473 WCHAR wc
= (WCHAR
)wparam
;
3474 if(!isdigitW(wc
) && wc
!= decimal
&& wc
!= VK_BACK
) return 0;
3476 return CallWindowProcW(edit_wndproc
, hwnd
, msg
, wparam
, lparam
);
3479 static void subclass_margin_edits(HWND hDlg
)
3484 for(id
= edt4
; id
<= edt7
; id
++)
3486 old_proc
= (WNDPROC
)SetWindowLongPtrW(GetDlgItem(hDlg
, id
),
3488 (ULONG_PTR
)pagesetup_margin_editproc
);
3489 InterlockedCompareExchangePointer((void**)&edit_wndproc
, old_proc
, NULL
);
3493 /***********************************************************************
3494 * pagesetup_dlg_proc
3496 * Message handler for PageSetupDlg
3498 static INT_PTR CALLBACK
pagesetup_dlg_proc(HWND hDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
3500 pagesetup_data
*data
;
3501 INT_PTR res
= FALSE
;
3504 if (uMsg
== WM_INITDIALOG
) { /*Init dialog*/
3505 data
= (pagesetup_data
*)lParam
;
3508 hDrawWnd
= GetDlgItem(hDlg
, rct1
);
3509 TRACE("set property to %p\n", data
);
3510 SetPropW(hDlg
, pagesetupdlg_prop
, data
);
3511 SetPropW(hDrawWnd
, pagesetupdlg_prop
, data
);
3512 GetWindowRect(hDrawWnd
, &data
->rtDrawRect
); /* Calculating rect in client coordinates where paper draws */
3513 MapWindowPoints( 0, hDlg
, (LPPOINT
)&data
->rtDrawRect
, 2 );
3514 lpfnStaticWndProc
= (WNDPROC
)SetWindowLongPtrW(
3517 (ULONG_PTR
)PRINTDLG_PagePaintProc
);
3519 /* FIXME: Paint hook. Must it be at begin of initialization or at end? */
3521 if (pagesetup_get_flags(data
) & PSD_ENABLEPAGESETUPHOOK
)
3523 if (!pagesetup_get_hook(data
, page_setup_hook
)(hDlg
, uMsg
, wParam
,
3524 pagesetup_get_dlg_struct(data
)))
3525 FIXME("Setup page hook failed?\n");
3528 /* if printer button disabled */
3529 if (pagesetup_get_flags(data
) & PSD_DISABLEPRINTER
)
3530 EnableWindow(GetDlgItem(hDlg
, psh3
), FALSE
);
3531 /* if margin edit boxes disabled */
3532 if (pagesetup_get_flags(data
) & PSD_DISABLEMARGINS
)
3534 EnableWindow(GetDlgItem(hDlg
, edt4
), FALSE
);
3535 EnableWindow(GetDlgItem(hDlg
, edt5
), FALSE
);
3536 EnableWindow(GetDlgItem(hDlg
, edt6
), FALSE
);
3537 EnableWindow(GetDlgItem(hDlg
, edt7
), FALSE
);
3540 /* Set orientation radiobuttons properly */
3541 pagesetup_update_orientation_buttons(hDlg
, data
);
3543 /* if orientation disabled */
3544 if (pagesetup_get_flags(data
) & PSD_DISABLEORIENTATION
)
3546 EnableWindow(GetDlgItem(hDlg
,rad1
),FALSE
);
3547 EnableWindow(GetDlgItem(hDlg
,rad2
),FALSE
);
3550 /* We fill them out enabled or not */
3551 if (!(pagesetup_get_flags(data
) & PSD_MARGINS
))
3553 /* default is 1 inch */
3554 LONG size
= thousandths_inch_to_size(data
, 1000);
3555 SetRect(pagesetup_get_margin_rect(data
), size
, size
, size
, size
);
3557 update_margin_edits(hDlg
, data
, 0);
3558 subclass_margin_edits(hDlg
);
3559 set_margin_groupbox_title(hDlg
, data
);
3561 /* if paper disabled */
3562 if (pagesetup_get_flags(data
) & PSD_DISABLEPAPER
)
3564 EnableWindow(GetDlgItem(hDlg
,cmb2
),FALSE
);
3565 EnableWindow(GetDlgItem(hDlg
,cmb3
),FALSE
);
3568 /* filling combos: printer, paper, source. selecting current printer (from DEVMODEA) */
3569 pagesetup_init_combos(hDlg
, data
);
3570 pagesetup_update_papersize(data
);
3571 pagesetup_set_defaultsource(data
, DMBIN_FORMSOURCE
); /* FIXME: This is the auto select bin. Is this correct? */
3573 /* Drawing paper prev */
3574 pagesetup_change_preview(data
);
3577 data
= GetPropW(hDlg
, pagesetupdlg_prop
);
3580 WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
3583 if (pagesetup_get_flags(data
) & PSD_ENABLEPAGESETUPHOOK
)
3585 res
= pagesetup_get_hook(data
, page_setup_hook
)(hDlg
, uMsg
, wParam
, lParam
);
3586 if (res
) return res
;
3591 return pagesetup_wm_command(hDlg
, wParam
, lParam
, data
);
3596 static WCHAR
*get_default_printer(void)
3601 GetDefaultPrinterW(NULL
, &len
);
3604 name
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3605 GetDefaultPrinterW(name
, &len
);
3610 static void pagesetup_dump_dlg_struct(const pagesetup_data
*data
)
3612 if(TRACE_ON(commdlg
))
3614 char flagstr
[1000] = "";
3615 const struct pd_flags
*pflag
= psd_flags
;
3616 for( ; pflag
->name
; pflag
++)
3618 if(pagesetup_get_flags(data
) & pflag
->flag
)
3620 strcat(flagstr
, pflag
->name
);
3621 strcat(flagstr
, "|");
3624 TRACE("%s: (%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
3625 "hinst %p, flags %08x (%s)\n",
3626 data
->unicode
? "unicode" : "ansi",
3627 data
->u
.dlgw
, data
->u
.dlgw
->hwndOwner
, data
->u
.dlgw
->hDevMode
,
3628 data
->u
.dlgw
->hDevNames
, data
->u
.dlgw
->hInstance
,
3629 pagesetup_get_flags(data
), flagstr
);
3633 static void *pagesetup_get_template(pagesetup_data
*data
)
3636 HGLOBAL tmpl_handle
;
3638 if(pagesetup_get_flags(data
) & PSD_ENABLEPAGESETUPTEMPLATEHANDLE
)
3640 tmpl_handle
= data
->u
.dlgw
->hPageSetupTemplate
;
3642 else if(pagesetup_get_flags(data
) & PSD_ENABLEPAGESETUPTEMPLATE
)
3645 res
= FindResourceW(data
->u
.dlgw
->hInstance
,
3646 data
->u
.dlgw
->lpPageSetupTemplateName
, MAKEINTRESOURCEW(RT_DIALOG
));
3648 res
= FindResourceA(data
->u
.dlga
->hInstance
,
3649 data
->u
.dlga
->lpPageSetupTemplateName
, MAKEINTRESOURCEA(RT_DIALOG
));
3650 tmpl_handle
= LoadResource(data
->u
.dlgw
->hInstance
, res
);
3654 res
= FindResourceW(COMDLG32_hInstance
, MAKEINTRESOURCEW(PAGESETUPDLGORD
),
3655 MAKEINTRESOURCEW(RT_DIALOG
));
3656 tmpl_handle
= LoadResource(COMDLG32_hInstance
, res
);
3658 return LockResource(tmpl_handle
);
3661 static BOOL
pagesetup_common(pagesetup_data
*data
)
3666 if(!pagesetup_get_dlg_struct(data
))
3668 COMDLG32_SetCommDlgExtendedError(CDERR_INITIALIZATION
);
3672 pagesetup_dump_dlg_struct(data
);
3674 if(data
->u
.dlgw
->lStructSize
!= sizeof(PAGESETUPDLGW
))
3676 COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE
);
3680 if ((pagesetup_get_flags(data
) & PSD_ENABLEPAGEPAINTHOOK
) &&
3681 (pagesetup_get_hook(data
, page_paint_hook
) == NULL
))
3683 COMDLG32_SetCommDlgExtendedError(CDERR_NOHOOK
);
3687 if(!(pagesetup_get_flags(data
) & (PSD_INTHOUSANDTHSOFINCHES
| PSD_INHUNDREDTHSOFMILLIMETERS
)))
3688 data
->u
.dlgw
->Flags
|= is_default_metric() ?
3689 PSD_INHUNDREDTHSOFMILLIMETERS
: PSD_INTHOUSANDTHSOFINCHES
;
3691 if (!data
->u
.dlgw
->hDevMode
|| !data
->u
.dlgw
->hDevNames
)
3693 WCHAR
*def
= get_default_printer();
3696 if (!(pagesetup_get_flags(data
) & PSD_NOWARNING
))
3699 LoadStringW(COMDLG32_hInstance
, PD32_NO_DEFAULT_PRINTER
, errstr
, 255);
3700 MessageBoxW(data
->u
.dlgw
->hwndOwner
, errstr
, 0, MB_OK
| MB_ICONERROR
);
3702 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN
);
3705 pagesetup_change_printer(def
, data
);
3706 HeapFree(GetProcessHeap(), 0, def
);
3709 if (pagesetup_get_flags(data
) & PSD_RETURNDEFAULT
)
3711 pagesetup_update_papersize(data
);
3715 tmpl
= pagesetup_get_template(data
);
3717 ret
= DialogBoxIndirectParamW(data
->u
.dlgw
->hInstance
, tmpl
,
3718 data
->u
.dlgw
->hwndOwner
,
3719 pagesetup_dlg_proc
, (LPARAM
)data
) > 0;
3723 /***********************************************************************
3724 * PageSetupDlgA (COMDLG32.@)
3726 * Displays the PAGE SETUP dialog box, which enables the user to specify
3727 * specific properties of a printed page such as
3728 * size, source, orientation and the width of the page margins.
3731 * setupdlg [IO] PAGESETUPDLGA struct
3734 * TRUE if the user pressed the OK button
3735 * FALSE if the user cancelled the window or an error occurred
3738 * The values of hDevMode and hDevNames are filled on output and can be
3739 * changed in PAGESETUPDLG when they are passed in PageSetupDlg.
3742 BOOL WINAPI
PageSetupDlgA(LPPAGESETUPDLGA setupdlg
)
3744 pagesetup_data data
;
3746 data
.unicode
= FALSE
;
3747 data
.u
.dlga
= setupdlg
;
3749 return pagesetup_common(&data
);
3752 /***********************************************************************
3753 * PageSetupDlgW (COMDLG32.@)
3755 * See PageSetupDlgA.
3757 BOOL WINAPI
PageSetupDlgW(LPPAGESETUPDLGW setupdlg
)
3759 pagesetup_data data
;
3761 data
.unicode
= TRUE
;
3762 data
.u
.dlgw
= setupdlg
;
3764 return pagesetup_common(&data
);
3767 /***********************************************************************
3768 * PrintDlgExA (COMDLG32.@)
3776 HRESULT WINAPI
PrintDlgExA(LPPRINTDLGEXA lppd
)
3781 FIXME("(%p) not fully implemented\n", lppd
);
3782 if ((lppd
== NULL
) || (lppd
->lStructSize
!= sizeof(PRINTDLGEXA
)))
3783 return E_INVALIDARG
;
3785 if (!IsWindow(lppd
->hwndOwner
))
3788 if (lppd
->Flags
& PD_RETURNDEFAULT
)
3790 PRINTER_INFO_2A
*pbuf
;
3791 DRIVER_INFO_2A
*dbuf
;
3793 DWORD needed
= 1024;
3796 if (lppd
->hDevMode
|| lppd
->hDevNames
)
3798 WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
3799 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE
);
3800 return E_INVALIDARG
;
3802 if (!PRINTDLG_OpenDefaultPrinter(&hprn
))
3804 WARN("Can't find default printer\n");
3805 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN
);
3809 pbuf
= HeapAlloc(GetProcessHeap(), 0, needed
);
3810 bRet
= GetPrinterA(hprn
, 2, (LPBYTE
)pbuf
, needed
, &needed
);
3811 if (!bRet
&& (GetLastError() == ERROR_INSUFFICIENT_BUFFER
))
3813 HeapFree(GetProcessHeap(), 0, pbuf
);
3814 pbuf
= HeapAlloc(GetProcessHeap(), 0, needed
);
3815 bRet
= GetPrinterA(hprn
, 2, (LPBYTE
)pbuf
, needed
, &needed
);
3819 HeapFree(GetProcessHeap(), 0, pbuf
);
3825 dbuf
= HeapAlloc(GetProcessHeap(), 0, needed
);
3826 bRet
= GetPrinterDriverA(hprn
, NULL
, 3, (LPBYTE
)dbuf
, needed
, &needed
);
3827 if (!bRet
&& (GetLastError() == ERROR_INSUFFICIENT_BUFFER
))
3829 HeapFree(GetProcessHeap(), 0, dbuf
);
3830 dbuf
= HeapAlloc(GetProcessHeap(), 0, needed
);
3831 bRet
= GetPrinterDriverA(hprn
, NULL
, 3, (LPBYTE
)dbuf
, needed
, &needed
);
3835 ERR("GetPrinterDriverŠ failed, last error %d, fix your config for printer %s!\n",
3836 GetLastError(), pbuf
->pPrinterName
);
3837 HeapFree(GetProcessHeap(), 0, dbuf
);
3838 HeapFree(GetProcessHeap(), 0, pbuf
);
3839 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE
);
3845 PRINTDLG_CreateDevNames(&(lppd
->hDevNames
),
3849 lppd
->hDevMode
= GlobalAlloc(GMEM_MOVEABLE
, pbuf
->pDevMode
->dmSize
+
3850 pbuf
->pDevMode
->dmDriverExtra
);
3853 ptr
= GlobalLock(lppd
->hDevMode
);
3856 memcpy(ptr
, pbuf
->pDevMode
, pbuf
->pDevMode
->dmSize
+
3857 pbuf
->pDevMode
->dmDriverExtra
);
3858 GlobalUnlock(lppd
->hDevMode
);
3862 HeapFree(GetProcessHeap(), 0, pbuf
);
3863 HeapFree(GetProcessHeap(), 0, dbuf
);
3871 /***********************************************************************
3872 * PrintDlgExW (COMDLG32.@)
3874 * Display the property sheet style PRINT dialog box
3877 * lppd [IO] ptr to PRINTDLGEX struct
3881 * Failure: One of the following COM error codes:
3882 * E_OUTOFMEMORY Insufficient memory.
3883 * E_INVALIDARG One or more arguments are invalid.
3884 * E_POINTER Invalid pointer.
3885 * E_HANDLE Invalid handle.
3886 * E_FAIL Unspecified error.
3889 * This Dialog enables the user to specify specific properties of the print job.
3890 * The property sheet can also have additional application-specific and
3891 * driver-specific property pages.
3894 * Not fully implemented
3897 HRESULT WINAPI
PrintDlgExW(LPPRINTDLGEXW lppd
)
3902 FIXME("(%p) not fully implemented\n", lppd
);
3904 if ((lppd
== NULL
) || (lppd
->lStructSize
!= sizeof(PRINTDLGEXW
))) {
3905 return E_INVALIDARG
;
3908 if (!IsWindow(lppd
->hwndOwner
)) {
3912 if (lppd
->Flags
& PD_RETURNDEFAULT
) {
3913 PRINTER_INFO_2W
*pbuf
;
3914 DRIVER_INFO_2W
*dbuf
;
3916 DWORD needed
= 1024;
3919 if (lppd
->hDevMode
|| lppd
->hDevNames
) {
3920 WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
3921 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE
);
3922 return E_INVALIDARG
;
3924 if (!PRINTDLG_OpenDefaultPrinter(&hprn
)) {
3925 WARN("Can't find default printer\n");
3926 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN
);
3930 pbuf
= HeapAlloc(GetProcessHeap(), 0, needed
);
3931 bRet
= GetPrinterW(hprn
, 2, (LPBYTE
)pbuf
, needed
, &needed
);
3932 if (!bRet
&& (GetLastError() == ERROR_INSUFFICIENT_BUFFER
)) {
3933 HeapFree(GetProcessHeap(), 0, pbuf
);
3934 pbuf
= HeapAlloc(GetProcessHeap(), 0, needed
);
3935 bRet
= GetPrinterW(hprn
, 2, (LPBYTE
)pbuf
, needed
, &needed
);
3938 HeapFree(GetProcessHeap(), 0, pbuf
);
3944 dbuf
= HeapAlloc(GetProcessHeap(), 0, needed
);
3945 bRet
= GetPrinterDriverW(hprn
, NULL
, 3, (LPBYTE
)dbuf
, needed
, &needed
);
3946 if (!bRet
&& (GetLastError() == ERROR_INSUFFICIENT_BUFFER
)) {
3947 HeapFree(GetProcessHeap(), 0, dbuf
);
3948 dbuf
= HeapAlloc(GetProcessHeap(), 0, needed
);
3949 bRet
= GetPrinterDriverW(hprn
, NULL
, 3, (LPBYTE
)dbuf
, needed
, &needed
);
3952 ERR("GetPrinterDriverW failed, last error %d, fix your config for printer %s!\n",
3953 GetLastError(), debugstr_w(pbuf
->pPrinterName
));
3954 HeapFree(GetProcessHeap(), 0, dbuf
);
3955 HeapFree(GetProcessHeap(), 0, pbuf
);
3956 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE
);
3962 PRINTDLG_CreateDevNamesW(&(lppd
->hDevNames
),
3966 lppd
->hDevMode
= GlobalAlloc(GMEM_MOVEABLE
, pbuf
->pDevMode
->dmSize
+
3967 pbuf
->pDevMode
->dmDriverExtra
);
3968 if (lppd
->hDevMode
) {
3969 ptr
= GlobalLock(lppd
->hDevMode
);
3971 memcpy(ptr
, pbuf
->pDevMode
, pbuf
->pDevMode
->dmSize
+
3972 pbuf
->pDevMode
->dmDriverExtra
);
3973 GlobalUnlock(lppd
->hDevMode
);
3977 HeapFree(GetProcessHeap(), 0, pbuf
);
3978 HeapFree(GetProcessHeap(), 0, dbuf
);