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
32 #define NONAMELESSUNION
33 #define NONAMELESSSTRUCT
43 #include "wine/debug.h"
49 WINE_DEFAULT_DEBUG_CHANNEL(commdlg
);
51 /* Yes these constants are the same, but we're just copying win98 */
52 #define UPDOWN_ID 0x270f
53 #define MAX_COPIES 9999
55 /* This PRINTDLGA internal structure stores
56 * pointers to several throughout useful structures.
62 LPPRINTDLGA lpPrintDlg
;
63 LPPRINTER_INFO_2A lpPrinterInfo
;
64 LPDRIVER_INFO_3A lpDriverInfo
;
66 HICON hCollateIcon
; /* PrintDlg only */
67 HICON hNoCollateIcon
; /* PrintDlg only */
68 HICON hPortraitIcon
; /* PrintSetupDlg only */
69 HICON hLandscapeIcon
; /* PrintSetupDlg only */
76 LPPRINTDLGW lpPrintDlg
;
77 LPPRINTER_INFO_2W lpPrinterInfo
;
78 LPDRIVER_INFO_3W lpDriverInfo
;
80 HICON hCollateIcon
; /* PrintDlg only */
81 HICON hNoCollateIcon
; /* PrintDlg only */
82 HICON hPortraitIcon
; /* PrintSetupDlg only */
83 HICON hLandscapeIcon
; /* PrintSetupDlg only */
94 static const struct pd_flags psd_flags
[] = {
95 {PSD_MINMARGINS
,"PSD_MINMARGINS"},
96 {PSD_MARGINS
,"PSD_MARGINS"},
97 {PSD_INTHOUSANDTHSOFINCHES
,"PSD_INTHOUSANDTHSOFINCHES"},
98 {PSD_INHUNDREDTHSOFMILLIMETERS
,"PSD_INHUNDREDTHSOFMILLIMETERS"},
99 {PSD_DISABLEMARGINS
,"PSD_DISABLEMARGINS"},
100 {PSD_DISABLEPRINTER
,"PSD_DISABLEPRINTER"},
101 {PSD_NOWARNING
,"PSD_NOWARNING"},
102 {PSD_DISABLEORIENTATION
,"PSD_DISABLEORIENTATION"},
103 {PSD_RETURNDEFAULT
,"PSD_RETURNDEFAULT"},
104 {PSD_DISABLEPAPER
,"PSD_DISABLEPAPER"},
105 {PSD_SHOWHELP
,"PSD_SHOWHELP"},
106 {PSD_ENABLEPAGESETUPHOOK
,"PSD_ENABLEPAGESETUPHOOK"},
107 {PSD_ENABLEPAGESETUPTEMPLATE
,"PSD_ENABLEPAGESETUPTEMPLATE"},
108 {PSD_ENABLEPAGESETUPTEMPLATEHANDLE
,"PSD_ENABLEPAGESETUPTEMPLATEHANDLE"},
109 {PSD_ENABLEPAGEPAINTHOOK
,"PSD_ENABLEPAGEPAINTHOOK"},
110 {PSD_DISABLEPAGEPAINTING
,"PSD_DISABLEPAGEPAINTING"},
114 static const struct pd_flags pd_flags
[] = {
115 {PD_SELECTION
, "PD_SELECTION "},
116 {PD_PAGENUMS
, "PD_PAGENUMS "},
117 {PD_NOSELECTION
, "PD_NOSELECTION "},
118 {PD_NOPAGENUMS
, "PD_NOPAGENUMS "},
119 {PD_COLLATE
, "PD_COLLATE "},
120 {PD_PRINTTOFILE
, "PD_PRINTTOFILE "},
121 {PD_PRINTSETUP
, "PD_PRINTSETUP "},
122 {PD_NOWARNING
, "PD_NOWARNING "},
123 {PD_RETURNDC
, "PD_RETURNDC "},
124 {PD_RETURNIC
, "PD_RETURNIC "},
125 {PD_RETURNDEFAULT
, "PD_RETURNDEFAULT "},
126 {PD_SHOWHELP
, "PD_SHOWHELP "},
127 {PD_ENABLEPRINTHOOK
, "PD_ENABLEPRINTHOOK "},
128 {PD_ENABLESETUPHOOK
, "PD_ENABLESETUPHOOK "},
129 {PD_ENABLEPRINTTEMPLATE
, "PD_ENABLEPRINTTEMPLATE "},
130 {PD_ENABLESETUPTEMPLATE
, "PD_ENABLESETUPTEMPLATE "},
131 {PD_ENABLEPRINTTEMPLATEHANDLE
, "PD_ENABLEPRINTTEMPLATEHANDLE "},
132 {PD_ENABLESETUPTEMPLATEHANDLE
, "PD_ENABLESETUPTEMPLATEHANDLE "},
133 {PD_USEDEVMODECOPIES
, "PD_USEDEVMODECOPIES[ANDCOLLATE] "},
134 {PD_DISABLEPRINTTOFILE
, "PD_DISABLEPRINTTOFILE "},
135 {PD_HIDEPRINTTOFILE
, "PD_HIDEPRINTTOFILE "},
136 {PD_NONETWORKBUTTON
, "PD_NONETWORKBUTTON "},
139 /* address of wndproc for subclassed Static control */
140 static WNDPROC lpfnStaticWndProc
;
141 static WNDPROC edit_wndproc
;
142 /* the text of the fake document to render for the Page Setup dialog */
143 static WCHAR wszFakeDocumentText
[1024];
144 static const WCHAR printdlg_prop
[] = L
"__WINE_PRINTDLGDATA";
145 static const WCHAR pagesetupdlg_prop
[] = L
"__WINE_PAGESETUPDLGDATA";
148 /***********************************************************************
149 * get_driver_info [internal]
151 * get DRIVER_INFO_3W for the current printer handle,
152 * alloc the buffer, when needed
154 static DRIVER_INFO_3W
* get_driver_infoW(HANDLE hprn
)
156 DRIVER_INFO_3W
*di3
= NULL
;
160 res
= GetPrinterDriverW(hprn
, NULL
, 3, NULL
, 0, &needed
);
161 if (!res
&& (GetLastError() == ERROR_INSUFFICIENT_BUFFER
)) {
162 di3
= malloc(needed
);
163 res
= GetPrinterDriverW(hprn
, NULL
, 3, (LPBYTE
)di3
, needed
, &needed
);
169 TRACE("GetPrinterDriverW failed with %lu\n", GetLastError());
174 static DRIVER_INFO_3A
* get_driver_infoA(HANDLE hprn
)
176 DRIVER_INFO_3A
*di3
= NULL
;
180 res
= GetPrinterDriverA(hprn
, NULL
, 3, NULL
, 0, &needed
);
181 if (!res
&& (GetLastError() == ERROR_INSUFFICIENT_BUFFER
)) {
182 di3
= malloc(needed
);
183 res
= GetPrinterDriverA(hprn
, NULL
, 3, (LPBYTE
)di3
, needed
, &needed
);
189 TRACE("GetPrinterDriverA failed with %lu\n", GetLastError());
195 /***********************************************************************
196 * get_printer_info [internal]
198 * get PRINTER_INFO_2W for the current printer handle,
199 * alloc the buffer, when needed
201 static PRINTER_INFO_2W
* get_printer_infoW(HANDLE hprn
)
203 PRINTER_INFO_2W
*pi2
= NULL
;
207 res
= GetPrinterW(hprn
, 2, NULL
, 0, &needed
);
208 if (!res
&& (GetLastError() == ERROR_INSUFFICIENT_BUFFER
)) {
209 pi2
= malloc(needed
);
210 res
= GetPrinterW(hprn
, 2, (LPBYTE
)pi2
, needed
, &needed
);
216 TRACE("GetPrinterW failed with %lu\n", GetLastError());
221 static PRINTER_INFO_2A
* get_printer_infoA(HANDLE hprn
)
223 PRINTER_INFO_2A
*pi2
= NULL
;
227 res
= GetPrinterA(hprn
, 2, NULL
, 0, &needed
);
228 if (!res
&& (GetLastError() == ERROR_INSUFFICIENT_BUFFER
)) {
229 pi2
= malloc(needed
);
230 res
= GetPrinterA(hprn
, 2, (LPBYTE
)pi2
, needed
, &needed
);
236 TRACE("GetPrinterA failed with %lu\n", GetLastError());
242 /***********************************************************************
243 * update_devmode_handle [internal]
245 * update a devmode handle for the given DEVMODE, alloc the buffer, when needed
247 static HGLOBAL
update_devmode_handleW(HGLOBAL hdm
, DEVMODEW
*dm
)
249 SIZE_T size
= GlobalSize(hdm
);
252 /* Increase / alloc the global memory block, when needed */
253 if ((dm
->dmSize
+ dm
->dmDriverExtra
) > size
) {
255 hdm
= GlobalReAlloc(hdm
, dm
->dmSize
+ dm
->dmDriverExtra
, GMEM_MOVEABLE
);
257 hdm
= GlobalAlloc(GMEM_MOVEABLE
, dm
->dmSize
+ dm
->dmDriverExtra
);
261 ptr
= GlobalLock(hdm
);
263 memcpy(ptr
, dm
, dm
->dmSize
+ dm
->dmDriverExtra
);
275 static HGLOBAL
update_devmode_handleA(HGLOBAL hdm
, DEVMODEA
*dm
)
277 SIZE_T size
= GlobalSize(hdm
);
280 /* Increase / alloc the global memory block, when needed */
281 if ((dm
->dmSize
+ dm
->dmDriverExtra
) > size
) {
283 hdm
= GlobalReAlloc(hdm
, dm
->dmSize
+ dm
->dmDriverExtra
, GMEM_MOVEABLE
);
285 hdm
= GlobalAlloc(GMEM_MOVEABLE
, dm
->dmSize
+ dm
->dmDriverExtra
);
289 ptr
= GlobalLock(hdm
);
291 memcpy(ptr
, dm
, dm
->dmSize
+ dm
->dmDriverExtra
);
303 /***********************************************************
304 * convert_to_devmodeA
306 * Creates an ansi copy of supplied devmode
308 static DEVMODEA
*convert_to_devmodeA(const DEVMODEW
*dmW
)
313 if (!dmW
) return NULL
;
314 size
= dmW
->dmSize
- CCHDEVICENAME
-
315 ((dmW
->dmSize
> FIELD_OFFSET(DEVMODEW
, dmFormName
)) ? CCHFORMNAME
: 0);
317 dmA
= malloc(size
+ dmW
->dmDriverExtra
);
318 if (!dmA
) return NULL
;
320 WideCharToMultiByte(CP_ACP
, 0, dmW
->dmDeviceName
, -1,
321 (LPSTR
)dmA
->dmDeviceName
, CCHDEVICENAME
, NULL
, NULL
);
323 if (FIELD_OFFSET(DEVMODEW
, dmFormName
) >= dmW
->dmSize
)
325 memcpy(&dmA
->dmSpecVersion
, &dmW
->dmSpecVersion
,
326 dmW
->dmSize
- FIELD_OFFSET(DEVMODEW
, dmSpecVersion
));
330 memcpy(&dmA
->dmSpecVersion
, &dmW
->dmSpecVersion
,
331 FIELD_OFFSET(DEVMODEW
, dmFormName
) - FIELD_OFFSET(DEVMODEW
, dmSpecVersion
));
332 WideCharToMultiByte(CP_ACP
, 0, dmW
->dmFormName
, -1,
333 (LPSTR
)dmA
->dmFormName
, CCHFORMNAME
, NULL
, NULL
);
335 memcpy(&dmA
->dmLogPixels
, &dmW
->dmLogPixels
, dmW
->dmSize
- FIELD_OFFSET(DEVMODEW
, dmLogPixels
));
339 memcpy((char *)dmA
+ dmA
->dmSize
, (const char *)dmW
+ dmW
->dmSize
, dmW
->dmDriverExtra
);
343 /***********************************************************************
344 * PRINTDLG_OpenDefaultPrinter
346 * Returns a winspool printer handle to the default printer in *hprn
347 * Caller must call ClosePrinter on the handle
349 * Returns TRUE on success else FALSE
351 static BOOL
PRINTDLG_OpenDefaultPrinter(HANDLE
*hprn
)
354 DWORD dwBufLen
= ARRAY_SIZE(buf
);
356 if(!GetDefaultPrinterW(buf
, &dwBufLen
))
358 res
= OpenPrinterW(buf
, hprn
, NULL
);
360 WARN("Could not open printer %s\n", debugstr_w(buf
));
364 /***********************************************************************
365 * PRINTDLG_SetUpPrinterListCombo
367 * Initializes printer list combox.
368 * hDlg: HWND of dialog
369 * id: Control id of combo
370 * name: Name of printer to select
372 * Initializes combo with list of available printers. Selects printer 'name'
373 * If name is NULL or does not exist select the default printer.
375 * Returns number of printers added to list.
377 static INT
PRINTDLG_SetUpPrinterListComboA(HWND hDlg
, UINT id
, LPCSTR name
)
381 LPPRINTER_INFO_2A pi
;
382 EnumPrintersA(PRINTER_ENUM_LOCAL
, NULL
, 2, NULL
, 0, &needed
, &num
);
384 EnumPrintersA(PRINTER_ENUM_LOCAL
, NULL
, 2, (LPBYTE
)pi
, needed
, &needed
,
387 SendDlgItemMessageA(hDlg
, id
, CB_RESETCONTENT
, 0, 0);
389 for(i
= 0; i
< num
; i
++) {
390 SendDlgItemMessageA(hDlg
, id
, CB_ADDSTRING
, 0,
391 (LPARAM
)pi
[i
].pPrinterName
);
395 (i
= SendDlgItemMessageA(hDlg
, id
, CB_FINDSTRINGEXACT
, -1,
396 (LPARAM
)name
)) == CB_ERR
) {
399 DWORD dwBufLen
= ARRAY_SIZE(buf
);
401 WARN("Can't find %s in printer list so trying to find default\n",
403 if(!GetDefaultPrinterA(buf
, &dwBufLen
))
405 i
= SendDlgItemMessageA(hDlg
, id
, CB_FINDSTRINGEXACT
, -1, (LPARAM
)buf
);
407 FIXME("Can't find default printer in printer list\n");
409 SendDlgItemMessageA(hDlg
, id
, CB_SETCURSEL
, i
, 0);
413 static INT
PRINTDLG_SetUpPrinterListComboW(HWND hDlg
, UINT id
, LPCWSTR name
)
417 LPPRINTER_INFO_2W pi
;
418 EnumPrintersW(PRINTER_ENUM_LOCAL
, NULL
, 2, NULL
, 0, &needed
, &num
);
420 EnumPrintersW(PRINTER_ENUM_LOCAL
, NULL
, 2, (LPBYTE
)pi
, needed
, &needed
,
423 for(i
= 0; i
< num
; i
++) {
424 SendDlgItemMessageW(hDlg
, id
, CB_ADDSTRING
, 0,
425 (LPARAM
)pi
[i
].pPrinterName
);
429 (i
= SendDlgItemMessageW(hDlg
, id
, CB_FINDSTRINGEXACT
, -1,
430 (LPARAM
)name
)) == CB_ERR
) {
432 DWORD dwBufLen
= ARRAY_SIZE(buf
);
434 WARN("Can't find %s in printer list so trying to find default\n",
436 if(!GetDefaultPrinterW(buf
, &dwBufLen
))
438 i
= SendDlgItemMessageW(hDlg
, id
, CB_FINDSTRINGEXACT
, -1, (LPARAM
)buf
);
440 TRACE("Can't find default printer in printer list\n");
442 SendDlgItemMessageW(hDlg
, id
, CB_SETCURSEL
, i
, 0);
446 /***********************************************************************
447 * PRINTDLG_CreateDevNames [internal]
450 * creates a DevNames structure.
452 * (NB. when we handle unicode the offsets will be in wchars).
454 static BOOL
PRINTDLG_CreateDevNames(HGLOBAL
*hmem
, const char* DeviceDriverName
,
455 const char* DeviceName
, const char* OutputPort
)
458 char* pDevNamesSpace
;
460 LPDEVNAMES lpDevNames
;
462 DWORD dwBufLen
= ARRAY_SIZE(buf
);
465 p
= strrchr( DeviceDriverName
, '\\' );
466 if (p
) DeviceDriverName
= p
+ 1;
468 size
= strlen(DeviceDriverName
) + 1
469 + strlen(DeviceName
) + 1
470 + strlen(OutputPort
) + 1
474 *hmem
= GlobalReAlloc(*hmem
, size
, GMEM_MOVEABLE
);
476 *hmem
= GlobalAlloc(GMEM_MOVEABLE
, size
);
480 pDevNamesSpace
= GlobalLock(*hmem
);
481 lpDevNames
= (LPDEVNAMES
) pDevNamesSpace
;
483 pTempPtr
= pDevNamesSpace
+ sizeof(DEVNAMES
);
484 strcpy(pTempPtr
, DeviceDriverName
);
485 lpDevNames
->wDriverOffset
= pTempPtr
- pDevNamesSpace
;
487 pTempPtr
+= strlen(DeviceDriverName
) + 1;
488 strcpy(pTempPtr
, DeviceName
);
489 lpDevNames
->wDeviceOffset
= pTempPtr
- pDevNamesSpace
;
491 pTempPtr
+= strlen(DeviceName
) + 1;
492 strcpy(pTempPtr
, OutputPort
);
493 lpDevNames
->wOutputOffset
= pTempPtr
- pDevNamesSpace
;
495 GetDefaultPrinterA(buf
, &dwBufLen
);
496 lpDevNames
->wDefault
= (strcmp(buf
, DeviceName
) == 0) ? 1 : 0;
501 static BOOL
PRINTDLG_CreateDevNamesW(HGLOBAL
*hmem
, LPCWSTR DeviceDriverName
,
502 LPCWSTR DeviceName
, LPCWSTR OutputPort
)
505 LPWSTR pDevNamesSpace
;
507 LPDEVNAMES lpDevNames
;
509 DWORD dwBufLen
= ARRAY_SIZE(bufW
);
512 p
= wcsrchr( DeviceDriverName
, '\\' );
513 if (p
) DeviceDriverName
= p
+ 1;
515 size
= sizeof(WCHAR
)*lstrlenW(DeviceDriverName
) + 2
516 + sizeof(WCHAR
)*lstrlenW(DeviceName
) + 2
517 + sizeof(WCHAR
)*lstrlenW(OutputPort
) + 2
521 *hmem
= GlobalReAlloc(*hmem
, size
, GMEM_MOVEABLE
);
523 *hmem
= GlobalAlloc(GMEM_MOVEABLE
, size
);
527 pDevNamesSpace
= GlobalLock(*hmem
);
528 lpDevNames
= (LPDEVNAMES
) pDevNamesSpace
;
530 pTempPtr
= (LPWSTR
)((LPDEVNAMES
)pDevNamesSpace
+ 1);
531 lstrcpyW(pTempPtr
, DeviceDriverName
);
532 lpDevNames
->wDriverOffset
= pTempPtr
- pDevNamesSpace
;
534 pTempPtr
+= lstrlenW(DeviceDriverName
) + 1;
535 lstrcpyW(pTempPtr
, DeviceName
);
536 lpDevNames
->wDeviceOffset
= pTempPtr
- pDevNamesSpace
;
538 pTempPtr
+= lstrlenW(DeviceName
) + 1;
539 lstrcpyW(pTempPtr
, OutputPort
);
540 lpDevNames
->wOutputOffset
= pTempPtr
- pDevNamesSpace
;
542 GetDefaultPrinterW(bufW
, &dwBufLen
);
543 lpDevNames
->wDefault
= (lstrcmpW(bufW
, DeviceName
) == 0) ? 1 : 0;
548 /***********************************************************************
549 * PRINTDLG_UpdatePrintDlg [internal]
552 * updates the PrintDlg structure for return values.
555 * FALSE if user is not allowed to close (i.e. wrong nTo or nFrom values)
556 * TRUE if successful.
558 static BOOL
PRINTDLG_UpdatePrintDlgA(HWND hDlg
,
559 PRINT_PTRA
* PrintStructures
)
561 LPPRINTDLGA lppd
= PrintStructures
->lpPrintDlg
;
562 PDEVMODEA lpdm
= PrintStructures
->lpDevMode
;
563 LPPRINTER_INFO_2A pi
= PrintStructures
->lpPrinterInfo
;
567 FIXME("No lpdm ptr?\n");
572 if(!(lppd
->Flags
& PD_PRINTSETUP
)) {
573 /* check whether nFromPage and nToPage are within range defined by
574 * nMinPage and nMaxPage
576 if (IsDlgButtonChecked(hDlg
, rad3
) == BST_CHECKED
) { /* Pages */
580 nFromPage
= GetDlgItemInt(hDlg
, edt1
, NULL
, FALSE
);
581 nToPage
= GetDlgItemInt(hDlg
, edt2
, &translated
, FALSE
);
583 /* if no ToPage value is entered, use the FromPage value */
584 if(!translated
) nToPage
= nFromPage
;
586 if (nFromPage
< lppd
->nMinPage
|| nFromPage
> lppd
->nMaxPage
||
587 nToPage
< lppd
->nMinPage
|| nToPage
> lppd
->nMaxPage
) {
588 WCHAR resourcestr
[256];
589 WCHAR resultstr
[256];
590 LoadStringW(COMDLG32_hInstance
, PD32_INVALID_PAGE_RANGE
, resourcestr
, 255);
591 wsprintfW(resultstr
,resourcestr
, lppd
->nMinPage
, lppd
->nMaxPage
);
592 LoadStringW(COMDLG32_hInstance
, PD32_PRINT_TITLE
, resourcestr
, 255);
593 MessageBoxW(hDlg
, resultstr
, resourcestr
, MB_OK
| MB_ICONWARNING
);
596 lppd
->nFromPage
= nFromPage
;
597 lppd
->nToPage
= nToPage
;
598 lppd
->Flags
|= PD_PAGENUMS
;
601 lppd
->Flags
&= ~PD_PAGENUMS
;
603 if (IsDlgButtonChecked(hDlg
, rad2
) == BST_CHECKED
) /* Selection */
604 lppd
->Flags
|= PD_SELECTION
;
606 lppd
->Flags
&= ~PD_SELECTION
;
608 if (IsDlgButtonChecked(hDlg
, chx1
) == BST_CHECKED
) {/* Print to file */
609 static char file
[] = "FILE:";
610 lppd
->Flags
|= PD_PRINTTOFILE
;
611 pi
->pPortName
= file
;
614 if (IsDlgButtonChecked(hDlg
, chx2
) == BST_CHECKED
) { /* Collate */
615 FIXME("Collate lppd not yet implemented as output\n");
618 /* set PD_Collate and nCopies */
619 if (lppd
->Flags
& PD_USEDEVMODECOPIESANDCOLLATE
) {
620 /* The application doesn't support multiple copies or collate...
622 lppd
->Flags
&= ~PD_COLLATE
;
624 /* if the printer driver supports it... store info there
625 * otherwise no collate & multiple copies !
627 if (lpdm
->dmFields
& DM_COLLATE
)
629 (IsDlgButtonChecked(hDlg
, chx2
) == BST_CHECKED
);
630 if (lpdm
->dmFields
& DM_COPIES
)
631 lpdm
->u1
.s1
.dmCopies
= GetDlgItemInt(hDlg
, edt3
, NULL
, FALSE
);
633 /* Application is responsible for multiple copies */
634 if (IsDlgButtonChecked(hDlg
, chx2
) == BST_CHECKED
)
635 lppd
->Flags
|= PD_COLLATE
;
637 lppd
->Flags
&= ~PD_COLLATE
;
638 lppd
->nCopies
= GetDlgItemInt(hDlg
, edt3
, NULL
, FALSE
);
639 /* multiple copies already included in the document. Driver must print only one copy */
640 lpdm
->u1
.s1
.dmCopies
= 1;
643 /* Print quality, PrintDlg16 */
644 if(GetDlgItem(hDlg
, cmb1
))
646 HWND hQuality
= GetDlgItem(hDlg
, cmb1
);
647 int Sel
= SendMessageA(hQuality
, CB_GETCURSEL
, 0, 0);
651 LONG dpi
= SendMessageA(hQuality
, CB_GETITEMDATA
, Sel
, 0);
652 lpdm
->dmFields
|= DM_PRINTQUALITY
| DM_YRESOLUTION
;
653 lpdm
->u1
.s1
.dmPrintQuality
= LOWORD(dpi
);
654 lpdm
->dmYResolution
= HIWORD(dpi
);
661 static BOOL
PRINTDLG_UpdatePrintDlgW(HWND hDlg
,
662 PRINT_PTRW
* PrintStructures
)
664 LPPRINTDLGW lppd
= PrintStructures
->lpPrintDlg
;
665 PDEVMODEW lpdm
= PrintStructures
->lpDevMode
;
666 LPPRINTER_INFO_2W pi
= PrintStructures
->lpPrinterInfo
;
670 FIXME("No lpdm ptr?\n");
675 if(!(lppd
->Flags
& PD_PRINTSETUP
)) {
676 /* check whether nFromPage and nToPage are within range defined by
677 * nMinPage and nMaxPage
679 if (IsDlgButtonChecked(hDlg
, rad3
) == BST_CHECKED
) { /* Pages */
683 nFromPage
= GetDlgItemInt(hDlg
, edt1
, NULL
, FALSE
);
684 nToPage
= GetDlgItemInt(hDlg
, edt2
, &translated
, FALSE
);
686 /* if no ToPage value is entered, use the FromPage value */
687 if(!translated
) nToPage
= nFromPage
;
689 if (nFromPage
< lppd
->nMinPage
|| nFromPage
> lppd
->nMaxPage
||
690 nToPage
< lppd
->nMinPage
|| nToPage
> lppd
->nMaxPage
) {
691 WCHAR resourcestr
[256];
692 WCHAR resultstr
[256];
694 LoadStringW(COMDLG32_hInstance
, PD32_INVALID_PAGE_RANGE
,
696 args
[0] = lppd
->nMinPage
;
697 args
[1] = lppd
->nMaxPage
;
698 FormatMessageW(FORMAT_MESSAGE_FROM_STRING
|FORMAT_MESSAGE_ARGUMENT_ARRAY
,
699 resourcestr
, 0, 0, resultstr
, ARRAY_SIZE(resultstr
), (va_list *)args
);
700 LoadStringW(COMDLG32_hInstance
, PD32_PRINT_TITLE
,
702 MessageBoxW(hDlg
, resultstr
, resourcestr
,
703 MB_OK
| MB_ICONWARNING
);
706 lppd
->nFromPage
= nFromPage
;
707 lppd
->nToPage
= nToPage
;
708 lppd
->Flags
|= PD_PAGENUMS
;
711 lppd
->Flags
&= ~PD_PAGENUMS
;
713 if (IsDlgButtonChecked(hDlg
, rad2
) == BST_CHECKED
) /* Selection */
714 lppd
->Flags
|= PD_SELECTION
;
716 lppd
->Flags
&= ~PD_SELECTION
;
718 if (IsDlgButtonChecked(hDlg
, chx1
) == BST_CHECKED
) {/* Print to file */
719 static WCHAR file
[] = L
"FILE:";
720 lppd
->Flags
|= PD_PRINTTOFILE
;
721 pi
->pPortName
= file
;
724 if (IsDlgButtonChecked(hDlg
, chx2
) == BST_CHECKED
) { /* Collate */
725 FIXME("Collate lppd not yet implemented as output\n");
728 /* set PD_Collate and nCopies */
729 if (lppd
->Flags
& PD_USEDEVMODECOPIESANDCOLLATE
) {
730 /* The application doesn't support multiple copies or collate...
732 lppd
->Flags
&= ~PD_COLLATE
;
734 /* if the printer driver supports it... store info there
735 * otherwise no collate & multiple copies !
737 if (lpdm
->dmFields
& DM_COLLATE
)
739 (IsDlgButtonChecked(hDlg
, chx2
) == BST_CHECKED
);
740 if (lpdm
->dmFields
& DM_COPIES
)
741 lpdm
->u1
.s1
.dmCopies
= GetDlgItemInt(hDlg
, edt3
, NULL
, FALSE
);
743 if (IsDlgButtonChecked(hDlg
, chx2
) == BST_CHECKED
)
744 lppd
->Flags
|= PD_COLLATE
;
746 lppd
->Flags
&= ~PD_COLLATE
;
747 lppd
->nCopies
= GetDlgItemInt(hDlg
, edt3
, NULL
, FALSE
);
753 /************************************************************************
754 * PRINTDLG_SetUpPaperComboBox
756 * Initialize either the papersize or inputslot combos of the Printer Setup
757 * dialog. We store the associated word (eg DMPAPER_A4) as the item data.
758 * We also try to re-select the old selection.
760 static BOOL
PRINTDLG_SetUpPaperComboBoxA(HWND hDlg
,
771 WORD oldWord
= 0, newWord
= 0; /* DMPAPER_ and DMBIN_ start at 1 */
773 int fwCapability_Names
;
774 int fwCapability_Words
;
776 TRACE(" Printer: %s, Port: %s, ComboID: %d\n",PrinterName
,PortName
,nIDComboBox
);
778 /* query the dialog box for the current selected value */
779 Sel
= SendDlgItemMessageA(hDlg
, nIDComboBox
, CB_GETCURSEL
, 0, 0);
781 /* we enter here only if a different printer is selected after
782 * the Print Setup dialog is opened. The current settings are
783 * stored into the newly selected printer.
785 oldWord
= SendDlgItemMessageA(hDlg
, nIDComboBox
, CB_GETITEMDATA
,
787 if(oldWord
>= DMPAPER_USER
) /* DMPAPER_USER == DMBIN_USER */
788 oldWord
= 0; /* There's no point in trying to keep custom
789 paper / bin sizes across printers */
793 newWord
= (nIDComboBox
== cmb2
) ? dm
->u1
.s1
.dmPaperSize
: dm
->u1
.s1
.dmDefaultSource
;
795 if (nIDComboBox
== cmb2
) {
797 fwCapability_Names
= DC_PAPERNAMES
;
798 fwCapability_Words
= DC_PAPERS
;
802 fwCapability_Names
= DC_BINNAMES
;
803 fwCapability_Words
= DC_BINS
;
806 NrOfEntries
= DeviceCapabilitiesA(PrinterName
, PortName
,
807 fwCapability_Names
, NULL
, dm
);
808 if (NrOfEntries
== 0)
809 WARN("no Name Entries found!\n");
810 else if (NrOfEntries
< 0)
813 if(DeviceCapabilitiesA(PrinterName
, PortName
, fwCapability_Words
, NULL
, dm
)
815 ERR("Number of caps is different\n");
819 Names
= malloc(NrOfEntries
* sizeof(char) * NamesSize
);
820 Words
= malloc(NrOfEntries
* sizeof(WORD
));
821 DeviceCapabilitiesA(PrinterName
, PortName
, fwCapability_Names
, Names
, dm
);
822 NrOfEntries
= DeviceCapabilitiesA(PrinterName
, PortName
,
823 fwCapability_Words
, (LPSTR
)Words
, dm
);
825 /* reset any current content in the combobox */
826 SendDlgItemMessageA(hDlg
, nIDComboBox
, CB_RESETCONTENT
, 0, 0);
828 /* store new content */
829 for (i
= 0; i
< NrOfEntries
; i
++) {
830 DWORD pos
= SendDlgItemMessageA(hDlg
, nIDComboBox
, CB_ADDSTRING
, 0,
831 (LPARAM
)(&Names
[i
*NamesSize
]) );
832 SendDlgItemMessageA(hDlg
, nIDComboBox
, CB_SETITEMDATA
, pos
,
836 /* Look for old selection or the new default.
837 Can't do this is previous loop since item order will change as more items are added */
839 old_Sel
= NrOfEntries
;
840 for (i
= 0; i
< NrOfEntries
; i
++) {
841 if(SendDlgItemMessageA(hDlg
, nIDComboBox
, CB_GETITEMDATA
, i
, 0) ==
846 if(SendDlgItemMessageA(hDlg
, nIDComboBox
, CB_GETITEMDATA
, i
, 0) == newWord
)
850 if(old_Sel
< NrOfEntries
)
854 if(nIDComboBox
== cmb2
)
855 dm
->u1
.s1
.dmPaperSize
= oldWord
;
857 dm
->u1
.s1
.dmDefaultSource
= oldWord
;
862 SendDlgItemMessageA(hDlg
, nIDComboBox
, CB_SETCURSEL
, Sel
, 0);
869 static BOOL
PRINTDLG_SetUpPaperComboBoxW(HWND hDlg
,
871 const WCHAR
* PrinterName
,
872 const WCHAR
* PortName
,
880 WORD oldWord
= 0, newWord
= 0; /* DMPAPER_ and DMBIN_ start at 1 */
882 int fwCapability_Names
;
883 int fwCapability_Words
;
885 TRACE(" Printer: %s, Port: %s, ComboID: %d\n",debugstr_w(PrinterName
),debugstr_w(PortName
),nIDComboBox
);
887 /* query the dialog box for the current selected value */
888 Sel
= SendDlgItemMessageW(hDlg
, nIDComboBox
, CB_GETCURSEL
, 0, 0);
890 /* we enter here only if a different printer is selected after
891 * the Print Setup dialog is opened. The current settings are
892 * stored into the newly selected printer.
894 oldWord
= SendDlgItemMessageW(hDlg
, nIDComboBox
, CB_GETITEMDATA
,
897 if(oldWord
>= DMPAPER_USER
) /* DMPAPER_USER == DMBIN_USER */
898 oldWord
= 0; /* There's no point in trying to keep custom
899 paper / bin sizes across printers */
903 newWord
= (nIDComboBox
== cmb2
) ? dm
->u1
.s1
.dmPaperSize
: dm
->u1
.s1
.dmDefaultSource
;
905 if (nIDComboBox
== cmb2
) {
907 fwCapability_Names
= DC_PAPERNAMES
;
908 fwCapability_Words
= DC_PAPERS
;
912 fwCapability_Names
= DC_BINNAMES
;
913 fwCapability_Words
= DC_BINS
;
916 NrOfEntries
= DeviceCapabilitiesW(PrinterName
, PortName
,
917 fwCapability_Names
, NULL
, dm
);
918 if (NrOfEntries
== 0)
919 WARN("no Name Entries found!\n");
920 else if (NrOfEntries
< 0)
923 if(DeviceCapabilitiesW(PrinterName
, PortName
, fwCapability_Words
, NULL
, dm
)
925 ERR("Number of caps is different\n");
929 Names
= malloc(NrOfEntries
* sizeof(WCHAR
) * NamesSize
);
930 Words
= malloc(NrOfEntries
* sizeof(WORD
));
931 DeviceCapabilitiesW(PrinterName
, PortName
, fwCapability_Names
, Names
, dm
);
932 NrOfEntries
= DeviceCapabilitiesW(PrinterName
, PortName
,
933 fwCapability_Words
, Words
, dm
);
935 /* reset any current content in the combobox */
936 SendDlgItemMessageW(hDlg
, nIDComboBox
, CB_RESETCONTENT
, 0, 0);
938 /* store new content */
939 for (i
= 0; i
< NrOfEntries
; i
++) {
940 DWORD pos
= SendDlgItemMessageW(hDlg
, nIDComboBox
, CB_ADDSTRING
, 0,
941 (LPARAM
)(&Names
[i
*NamesSize
]) );
942 SendDlgItemMessageW(hDlg
, nIDComboBox
, CB_SETITEMDATA
, pos
,
946 /* Look for old selection or the new default.
947 Can't do this is previous loop since item order will change as more items are added */
949 old_Sel
= NrOfEntries
;
950 for (i
= 0; i
< NrOfEntries
; i
++) {
951 if(SendDlgItemMessageW(hDlg
, nIDComboBox
, CB_GETITEMDATA
, i
, 0) ==
956 if(SendDlgItemMessageA(hDlg
, nIDComboBox
, CB_GETITEMDATA
, i
, 0) == newWord
)
960 if(old_Sel
< NrOfEntries
)
964 if(nIDComboBox
== cmb2
)
965 dm
->u1
.s1
.dmPaperSize
= oldWord
;
967 dm
->u1
.s1
.dmDefaultSource
= oldWord
;
972 SendDlgItemMessageW(hDlg
, nIDComboBox
, CB_SETCURSEL
, Sel
, 0);
980 /***********************************************************************
981 * PRINTDLG_UpdatePrinterInfoTexts [internal]
983 static void PRINTDLG_UpdatePrinterInfoTextsA(HWND hDlg
, const PRINTER_INFO_2A
*pi
)
986 char ResourceString
[256];
992 /* add all status messages */
993 for (i
= 0; i
< 25; i
++) {
994 if (pi
->Status
& (1<<i
)) {
995 LoadStringA(COMDLG32_hInstance
, PD32_PRINTER_STATUS_PAUSED
+i
,
996 ResourceString
, 255);
997 strcat(StatusMsg
,ResourceString
);
1000 /* append "ready" */
1001 /* FIXME: status==ready must only be appended if really so.
1002 but how to detect? */
1003 LoadStringA(COMDLG32_hInstance
, PD32_PRINTER_STATUS_READY
,
1004 ResourceString
, 255);
1005 strcat(StatusMsg
,ResourceString
);
1006 SetDlgItemTextA(hDlg
, stc12
, StatusMsg
);
1008 /* set all other printer info texts */
1009 SetDlgItemTextA(hDlg
, stc11
, pi
->pDriverName
);
1011 if (pi
->pLocation
!= NULL
&& pi
->pLocation
[0] != '\0')
1012 SetDlgItemTextA(hDlg
, stc14
, pi
->pLocation
);
1014 SetDlgItemTextA(hDlg
, stc14
, pi
->pPortName
);
1015 SetDlgItemTextA(hDlg
, stc13
, pi
->pComment
? pi
->pComment
: "");
1019 static void PRINTDLG_UpdatePrinterInfoTextsW(HWND hDlg
, const PRINTER_INFO_2W
*pi
)
1021 WCHAR StatusMsg
[256];
1022 WCHAR ResourceString
[256];
1025 /* Status Message */
1028 /* add all status messages */
1029 for (i
= 0; i
< 25; i
++) {
1030 if (pi
->Status
& (1<<i
)) {
1031 LoadStringW(COMDLG32_hInstance
, PD32_PRINTER_STATUS_PAUSED
+i
,
1032 ResourceString
, 255);
1033 lstrcatW(StatusMsg
,ResourceString
);
1036 /* append "ready" */
1037 /* FIXME: status==ready must only be appended if really so.
1038 but how to detect? */
1039 LoadStringW(COMDLG32_hInstance
, PD32_PRINTER_STATUS_READY
,
1040 ResourceString
, 255);
1041 lstrcatW(StatusMsg
,ResourceString
);
1042 SetDlgItemTextW(hDlg
, stc12
, StatusMsg
);
1044 /* set all other printer info texts */
1045 SetDlgItemTextW(hDlg
, stc11
, pi
->pDriverName
);
1046 if (pi
->pLocation
!= NULL
&& pi
->pLocation
[0] != '\0')
1047 SetDlgItemTextW(hDlg
, stc14
, pi
->pLocation
);
1049 SetDlgItemTextW(hDlg
, stc14
, pi
->pPortName
);
1050 SetDlgItemTextW(hDlg
, stc13
, pi
->pComment
? pi
->pComment
: L
"");
1054 /*******************************************************************
1056 * PRINTDLG_ChangePrinter
1059 static BOOL
PRINTDLG_ChangePrinterA(HWND hDlg
, char *name
, PRINT_PTRA
*PrintStructures
)
1061 LPPRINTDLGA lppd
= PrintStructures
->lpPrintDlg
;
1062 LPDEVMODEA lpdm
= NULL
;
1067 free(PrintStructures
->lpPrinterInfo
);
1068 free(PrintStructures
->lpDriverInfo
);
1069 if(!OpenPrinterA(name
, &hprn
, NULL
)) {
1070 ERR("Can't open printer %s\n", name
);
1073 GetPrinterA(hprn
, 2, NULL
, 0, &needed
);
1074 PrintStructures
->lpPrinterInfo
= malloc(needed
);
1075 GetPrinterA(hprn
, 2, (LPBYTE
)PrintStructures
->lpPrinterInfo
, needed
,
1077 GetPrinterDriverA(hprn
, NULL
, 3, NULL
, 0, &needed
);
1078 PrintStructures
->lpDriverInfo
= malloc(needed
);
1079 if (!GetPrinterDriverA(hprn
, NULL
, 3, (LPBYTE
)PrintStructures
->lpDriverInfo
,
1081 ERR("GetPrinterDriverA failed for %s, fix your config!\n",PrintStructures
->lpPrinterInfo
->pPrinterName
);
1086 PRINTDLG_UpdatePrinterInfoTextsA(hDlg
, PrintStructures
->lpPrinterInfo
);
1088 free(PrintStructures
->lpDevMode
);
1089 PrintStructures
->lpDevMode
= NULL
;
1091 dmSize
= DocumentPropertiesA(0, 0, name
, NULL
, NULL
, 0);
1093 ERR("DocumentProperties fails on %s\n", debugstr_a(name
));
1096 PrintStructures
->lpDevMode
= malloc(dmSize
);
1097 dmSize
= DocumentPropertiesA(0, 0, name
, PrintStructures
->lpDevMode
, NULL
,
1099 if(lppd
->hDevMode
&& (lpdm
= GlobalLock(lppd
->hDevMode
)) &&
1100 !lstrcmpA( (LPSTR
) lpdm
->dmDeviceName
,
1101 (LPSTR
) PrintStructures
->lpDevMode
->dmDeviceName
)) {
1102 /* Supplied devicemode matches current printer so try to use it */
1103 DocumentPropertiesA(0, 0, name
, PrintStructures
->lpDevMode
, lpdm
,
1104 DM_OUT_BUFFER
| DM_IN_BUFFER
);
1107 GlobalUnlock(lppd
->hDevMode
);
1109 lpdm
= PrintStructures
->lpDevMode
; /* use this as a shortcut */
1111 if(!(lppd
->Flags
& PD_PRINTSETUP
)) {
1112 /* Print range (All/Range/Selection) */
1113 if(lppd
->nFromPage
!= 0xffff)
1114 SetDlgItemInt(hDlg
, edt1
, lppd
->nFromPage
, FALSE
);
1115 if(lppd
->nToPage
!= 0xffff)
1116 SetDlgItemInt(hDlg
, edt2
, lppd
->nToPage
, FALSE
);
1118 CheckRadioButton(hDlg
, rad1
, rad3
, rad1
); /* default */
1119 if (lppd
->Flags
& PD_NOSELECTION
)
1120 EnableWindow(GetDlgItem(hDlg
, rad2
), FALSE
);
1122 if (lppd
->Flags
& PD_SELECTION
)
1123 CheckRadioButton(hDlg
, rad1
, rad3
, rad2
);
1124 if (lppd
->Flags
& PD_NOPAGENUMS
) {
1125 EnableWindow(GetDlgItem(hDlg
, rad3
), FALSE
);
1126 EnableWindow(GetDlgItem(hDlg
, stc2
),FALSE
);
1127 EnableWindow(GetDlgItem(hDlg
, edt1
), FALSE
);
1128 EnableWindow(GetDlgItem(hDlg
, stc3
),FALSE
);
1129 EnableWindow(GetDlgItem(hDlg
, edt2
), FALSE
);
1131 if (lppd
->Flags
& PD_PAGENUMS
)
1132 CheckRadioButton(hDlg
, rad1
, rad3
, rad3
);
1137 * FIXME: The ico3 is not displayed for some reason. I don't know why.
1139 if (lppd
->Flags
& PD_COLLATE
) {
1140 SendDlgItemMessageA(hDlg
, ico3
, STM_SETIMAGE
, IMAGE_ICON
,
1141 (LPARAM
)PrintStructures
->hCollateIcon
);
1142 CheckDlgButton(hDlg
, chx2
, 1);
1144 SendDlgItemMessageA(hDlg
, ico3
, STM_SETIMAGE
, IMAGE_ICON
,
1145 (LPARAM
)PrintStructures
->hNoCollateIcon
);
1146 CheckDlgButton(hDlg
, chx2
, 0);
1149 if (lppd
->Flags
& PD_USEDEVMODECOPIESANDCOLLATE
) {
1150 /* if printer doesn't support it: no Collate */
1151 if (!(lpdm
->dmFields
& DM_COLLATE
)) {
1152 EnableWindow(GetDlgItem(hDlg
, chx2
), FALSE
);
1153 EnableWindow(GetDlgItem(hDlg
, ico3
), FALSE
);
1160 if (lppd
->hDevMode
== 0)
1161 copies
= lppd
->nCopies
;
1163 copies
= lpdm
->u1
.s1
.dmCopies
;
1164 if(copies
== 0) copies
= 1;
1165 else if(copies
< 0) copies
= MAX_COPIES
;
1166 SetDlgItemInt(hDlg
, edt3
, copies
, FALSE
);
1169 if (lppd
->Flags
& PD_USEDEVMODECOPIESANDCOLLATE
) {
1170 /* if printer doesn't support it: no nCopies */
1171 if (!(lpdm
->dmFields
& DM_COPIES
)) {
1172 EnableWindow(GetDlgItem(hDlg
, edt3
), FALSE
);
1173 EnableWindow(GetDlgItem(hDlg
, stc5
), FALSE
);
1178 CheckDlgButton(hDlg
, chx1
, (lppd
->Flags
& PD_PRINTTOFILE
) ? 1 : 0);
1179 if (lppd
->Flags
& PD_DISABLEPRINTTOFILE
)
1180 EnableWindow(GetDlgItem(hDlg
, chx1
), FALSE
);
1181 if (lppd
->Flags
& PD_HIDEPRINTTOFILE
)
1182 ShowWindow(GetDlgItem(hDlg
, chx1
), SW_HIDE
);
1184 /* Fill print quality combo, PrintDlg16 */
1185 if(GetDlgItem(hDlg
, cmb1
))
1187 DWORD numResolutions
= DeviceCapabilitiesA(PrintStructures
->lpPrinterInfo
->pPrinterName
,
1188 PrintStructures
->lpPrinterInfo
->pPortName
,
1189 DC_ENUMRESOLUTIONS
, NULL
, lpdm
);
1191 if(numResolutions
!= -1)
1193 HWND hQuality
= GetDlgItem(hDlg
, cmb1
);
1198 HDC hPrinterDC
= CreateDCA(PrintStructures
->lpPrinterInfo
->pDriverName
,
1199 PrintStructures
->lpPrinterInfo
->pPrinterName
,
1202 Resolutions
= malloc(numResolutions
* sizeof(LONG
) * 2);
1203 DeviceCapabilitiesA(PrintStructures
->lpPrinterInfo
->pPrinterName
,
1204 PrintStructures
->lpPrinterInfo
->pPortName
,
1205 DC_ENUMRESOLUTIONS
, (LPSTR
)Resolutions
, lpdm
);
1207 dpiX
= GetDeviceCaps(hPrinterDC
, LOGPIXELSX
);
1208 dpiY
= GetDeviceCaps(hPrinterDC
, LOGPIXELSY
);
1209 DeleteDC(hPrinterDC
);
1211 SendMessageA(hQuality
, CB_RESETCONTENT
, 0, 0);
1212 for(i
= 0; i
< (numResolutions
* 2); i
+= 2)
1214 BOOL IsDefault
= FALSE
;
1217 if(Resolutions
[i
] == Resolutions
[i
+1])
1219 if(dpiX
== Resolutions
[i
])
1221 sprintf(buf
, "%ld dpi", Resolutions
[i
]);
1224 if(dpiX
== Resolutions
[i
] && dpiY
== Resolutions
[i
+1])
1226 sprintf(buf
, "%ld dpi x %ld dpi", Resolutions
[i
], Resolutions
[i
+1]);
1229 Index
= SendMessageA(hQuality
, CB_ADDSTRING
, 0, (LPARAM
)buf
);
1232 SendMessageA(hQuality
, CB_SETCURSEL
, Index
, 0);
1234 SendMessageA(hQuality
, CB_SETITEMDATA
, Index
, MAKELONG(dpiX
,dpiY
));
1239 } else { /* PD_PRINTSETUP */
1240 BOOL bPortrait
= (lpdm
->u1
.s1
.dmOrientation
== DMORIENT_PORTRAIT
);
1242 PRINTDLG_SetUpPaperComboBoxA(hDlg
, cmb2
,
1243 PrintStructures
->lpPrinterInfo
->pPrinterName
,
1244 PrintStructures
->lpPrinterInfo
->pPortName
,
1246 PRINTDLG_SetUpPaperComboBoxA(hDlg
, cmb3
,
1247 PrintStructures
->lpPrinterInfo
->pPrinterName
,
1248 PrintStructures
->lpPrinterInfo
->pPortName
,
1250 CheckRadioButton(hDlg
, rad1
, rad2
, bPortrait
? rad1
: rad2
);
1251 SendDlgItemMessageA(hDlg
, ico1
, STM_SETIMAGE
, IMAGE_ICON
,
1252 (LPARAM
)(bPortrait
? PrintStructures
->hPortraitIcon
:
1253 PrintStructures
->hLandscapeIcon
));
1258 if ((lppd
->Flags
& PD_SHOWHELP
)==0) {
1259 /* hide if PD_SHOWHELP not specified */
1260 ShowWindow(GetDlgItem(hDlg
, pshHelp
), SW_HIDE
);
1265 static BOOL
PRINTDLG_ChangePrinterW(HWND hDlg
, WCHAR
*name
,
1266 PRINT_PTRW
*PrintStructures
)
1268 LPPRINTDLGW lppd
= PrintStructures
->lpPrintDlg
;
1269 LPDEVMODEW lpdm
= NULL
;
1274 free(PrintStructures
->lpPrinterInfo
);
1275 free(PrintStructures
->lpDriverInfo
);
1276 if(!OpenPrinterW(name
, &hprn
, NULL
)) {
1277 ERR("Can't open printer %s\n", debugstr_w(name
));
1280 GetPrinterW(hprn
, 2, NULL
, 0, &needed
);
1281 PrintStructures
->lpPrinterInfo
= malloc(needed
);
1282 GetPrinterW(hprn
, 2, (LPBYTE
)PrintStructures
->lpPrinterInfo
, needed
,
1284 GetPrinterDriverW(hprn
, NULL
, 3, NULL
, 0, &needed
);
1285 PrintStructures
->lpDriverInfo
= malloc(needed
);
1286 if (!GetPrinterDriverW(hprn
, NULL
, 3, (LPBYTE
)PrintStructures
->lpDriverInfo
,
1288 ERR("GetPrinterDriverA failed for %s, fix your config!\n",debugstr_w(PrintStructures
->lpPrinterInfo
->pPrinterName
));
1293 PRINTDLG_UpdatePrinterInfoTextsW(hDlg
, PrintStructures
->lpPrinterInfo
);
1295 free(PrintStructures
->lpDevMode
);
1296 PrintStructures
->lpDevMode
= NULL
;
1298 dmSize
= DocumentPropertiesW(0, 0, name
, NULL
, NULL
, 0);
1300 ERR("DocumentProperties fails on %s\n", debugstr_w(name
));
1303 PrintStructures
->lpDevMode
= malloc(dmSize
);
1304 dmSize
= DocumentPropertiesW(0, 0, name
, PrintStructures
->lpDevMode
, NULL
,
1306 if(lppd
->hDevMode
&& (lpdm
= GlobalLock(lppd
->hDevMode
)) &&
1307 !lstrcmpW(lpdm
->dmDeviceName
,
1308 PrintStructures
->lpDevMode
->dmDeviceName
)) {
1309 /* Supplied devicemode matches current printer so try to use it */
1310 DocumentPropertiesW(0, 0, name
, PrintStructures
->lpDevMode
, lpdm
,
1311 DM_OUT_BUFFER
| DM_IN_BUFFER
);
1314 GlobalUnlock(lppd
->hDevMode
);
1316 lpdm
= PrintStructures
->lpDevMode
; /* use this as a shortcut */
1318 if(!(lppd
->Flags
& PD_PRINTSETUP
)) {
1319 /* Print range (All/Range/Selection) */
1320 if(lppd
->nFromPage
!= 0xffff)
1321 SetDlgItemInt(hDlg
, edt1
, lppd
->nFromPage
, FALSE
);
1322 if(lppd
->nToPage
!= 0xffff)
1323 SetDlgItemInt(hDlg
, edt2
, lppd
->nToPage
, FALSE
);
1325 CheckRadioButton(hDlg
, rad1
, rad3
, rad1
); /* default */
1326 if (lppd
->Flags
& PD_NOSELECTION
)
1327 EnableWindow(GetDlgItem(hDlg
, rad2
), FALSE
);
1329 if (lppd
->Flags
& PD_SELECTION
)
1330 CheckRadioButton(hDlg
, rad1
, rad3
, rad2
);
1331 if (lppd
->Flags
& PD_NOPAGENUMS
) {
1332 EnableWindow(GetDlgItem(hDlg
, rad3
), FALSE
);
1333 EnableWindow(GetDlgItem(hDlg
, stc2
),FALSE
);
1334 EnableWindow(GetDlgItem(hDlg
, edt1
), FALSE
);
1335 EnableWindow(GetDlgItem(hDlg
, stc3
),FALSE
);
1336 EnableWindow(GetDlgItem(hDlg
, edt2
), FALSE
);
1338 if (lppd
->Flags
& PD_PAGENUMS
)
1339 CheckRadioButton(hDlg
, rad1
, rad3
, rad3
);
1344 * FIXME: The ico3 is not displayed for some reason. I don't know why.
1346 if (lppd
->Flags
& PD_COLLATE
) {
1347 SendDlgItemMessageW(hDlg
, ico3
, STM_SETIMAGE
, IMAGE_ICON
,
1348 (LPARAM
)PrintStructures
->hCollateIcon
);
1349 CheckDlgButton(hDlg
, chx2
, 1);
1351 SendDlgItemMessageW(hDlg
, ico3
, STM_SETIMAGE
, IMAGE_ICON
,
1352 (LPARAM
)PrintStructures
->hNoCollateIcon
);
1353 CheckDlgButton(hDlg
, chx2
, 0);
1356 if (lppd
->Flags
& PD_USEDEVMODECOPIESANDCOLLATE
) {
1357 /* if printer doesn't support it: no Collate */
1358 if (!(lpdm
->dmFields
& DM_COLLATE
)) {
1359 EnableWindow(GetDlgItem(hDlg
, chx2
), FALSE
);
1360 EnableWindow(GetDlgItem(hDlg
, ico3
), FALSE
);
1367 if (lppd
->hDevMode
== 0)
1368 copies
= lppd
->nCopies
;
1370 copies
= lpdm
->u1
.s1
.dmCopies
;
1371 if(copies
== 0) copies
= 1;
1372 else if(copies
< 0) copies
= MAX_COPIES
;
1373 SetDlgItemInt(hDlg
, edt3
, copies
, FALSE
);
1376 if (lppd
->Flags
& PD_USEDEVMODECOPIESANDCOLLATE
) {
1377 /* if printer doesn't support it: no nCopies */
1378 if (!(lpdm
->dmFields
& DM_COPIES
)) {
1379 EnableWindow(GetDlgItem(hDlg
, edt3
), FALSE
);
1380 EnableWindow(GetDlgItem(hDlg
, stc5
), FALSE
);
1385 CheckDlgButton(hDlg
, chx1
, (lppd
->Flags
& PD_PRINTTOFILE
) ? 1 : 0);
1386 if (lppd
->Flags
& PD_DISABLEPRINTTOFILE
)
1387 EnableWindow(GetDlgItem(hDlg
, chx1
), FALSE
);
1388 if (lppd
->Flags
& PD_HIDEPRINTTOFILE
)
1389 ShowWindow(GetDlgItem(hDlg
, chx1
), SW_HIDE
);
1391 } else { /* PD_PRINTSETUP */
1392 BOOL bPortrait
= (lpdm
->u1
.s1
.dmOrientation
== DMORIENT_PORTRAIT
);
1394 PRINTDLG_SetUpPaperComboBoxW(hDlg
, cmb2
,
1395 PrintStructures
->lpPrinterInfo
->pPrinterName
,
1396 PrintStructures
->lpPrinterInfo
->pPortName
,
1398 PRINTDLG_SetUpPaperComboBoxW(hDlg
, cmb3
,
1399 PrintStructures
->lpPrinterInfo
->pPrinterName
,
1400 PrintStructures
->lpPrinterInfo
->pPortName
,
1402 CheckRadioButton(hDlg
, rad1
, rad2
, bPortrait
? rad1
: rad2
);
1403 SendDlgItemMessageW(hDlg
, ico1
, STM_SETIMAGE
, IMAGE_ICON
,
1404 (LPARAM
)(bPortrait
? PrintStructures
->hPortraitIcon
:
1405 PrintStructures
->hLandscapeIcon
));
1410 if ((lppd
->Flags
& PD_SHOWHELP
)==0) {
1411 /* hide if PD_SHOWHELP not specified */
1412 ShowWindow(GetDlgItem(hDlg
, pshHelp
), SW_HIDE
);
1417 /***********************************************************************
1418 * check_printer_setup [internal]
1420 static LRESULT
check_printer_setup(HWND hDlg
)
1423 WCHAR resourcestr
[256],resultstr
[256];
1425 EnumPrintersW(PRINTER_ENUM_LOCAL
, NULL
, 2, NULL
, 0, &needed
, &num
);
1428 EnumPrintersW(PRINTER_ENUM_CONNECTIONS
, NULL
, 2, NULL
, 0, &needed
, &num
);
1434 LoadStringW(COMDLG32_hInstance
, PD32_NO_DEVICES
,resultstr
, 255);
1435 LoadStringW(COMDLG32_hInstance
, PD32_PRINT_TITLE
,resourcestr
, 255);
1436 MessageBoxW(hDlg
, resultstr
, resourcestr
,MB_OK
| MB_ICONWARNING
);
1441 /***********************************************************************
1442 * PRINTDLG_WMInitDialog [internal]
1444 static LRESULT
PRINTDLG_WMInitDialog(HWND hDlg
,
1445 PRINT_PTRA
* PrintStructures
)
1447 LPPRINTDLGA lppd
= PrintStructures
->lpPrintDlg
;
1451 UINT comboID
= (lppd
->Flags
& PD_PRINTSETUP
) ? cmb1
: cmb4
;
1453 /* load Collate ICONs */
1454 /* We load these with LoadImage because they are not a standard
1455 size and we don't want them rescaled */
1456 PrintStructures
->hCollateIcon
=
1457 LoadImageA(COMDLG32_hInstance
, "PD32_COLLATE", IMAGE_ICON
, 0, 0, 0);
1458 PrintStructures
->hNoCollateIcon
=
1459 LoadImageA(COMDLG32_hInstance
, "PD32_NOCOLLATE", IMAGE_ICON
, 0, 0, 0);
1461 /* These can be done with LoadIcon */
1462 PrintStructures
->hPortraitIcon
=
1463 LoadIconA(COMDLG32_hInstance
, "PD32_PORTRAIT");
1464 PrintStructures
->hLandscapeIcon
=
1465 LoadIconA(COMDLG32_hInstance
, "PD32_LANDSCAPE");
1467 /* display the collate/no_collate icon */
1468 SendDlgItemMessageA(hDlg
, ico3
, STM_SETIMAGE
, IMAGE_ICON
,
1469 (LPARAM
)PrintStructures
->hNoCollateIcon
);
1471 if(PrintStructures
->hCollateIcon
== 0 ||
1472 PrintStructures
->hNoCollateIcon
== 0 ||
1473 PrintStructures
->hPortraitIcon
== 0 ||
1474 PrintStructures
->hLandscapeIcon
== 0) {
1475 ERR("no icon in resource file\n");
1476 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
1477 EndDialog(hDlg
, FALSE
);
1481 * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
1482 * must be registered and the Help button must be shown.
1484 if (lppd
->Flags
& PD_SHOWHELP
) {
1485 if((PrintStructures
->HelpMessageID
=
1486 RegisterWindowMessageA(HELPMSGSTRINGA
)) == 0) {
1487 COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL
);
1491 PrintStructures
->HelpMessageID
= 0;
1493 if(!(lppd
->Flags
&PD_PRINTSETUP
)) {
1494 PrintStructures
->hwndUpDown
=
1495 CreateUpDownControl(WS_CHILD
| WS_VISIBLE
| WS_BORDER
|
1496 UDS_NOTHOUSANDS
| UDS_ARROWKEYS
|
1497 UDS_ALIGNRIGHT
| UDS_SETBUDDYINT
, 0, 0, 0, 0,
1498 hDlg
, UPDOWN_ID
, COMDLG32_hInstance
,
1499 GetDlgItem(hDlg
, edt3
), MAX_COPIES
, 1, 1);
1502 /* FIXME: I allow more freedom than either Win95 or WinNT,
1503 * which do not agree on what errors should be thrown or not
1504 * in case nToPage or nFromPage is out-of-range.
1506 if (lppd
->nMaxPage
< lppd
->nMinPage
)
1507 lppd
->nMaxPage
= lppd
->nMinPage
;
1508 if (lppd
->nMinPage
== lppd
->nMaxPage
)
1509 lppd
->Flags
|= PD_NOPAGENUMS
;
1510 if (lppd
->nToPage
< lppd
->nMinPage
)
1511 lppd
->nToPage
= lppd
->nMinPage
;
1512 if (lppd
->nToPage
> lppd
->nMaxPage
)
1513 lppd
->nToPage
= lppd
->nMaxPage
;
1514 if (lppd
->nFromPage
< lppd
->nMinPage
)
1515 lppd
->nFromPage
= lppd
->nMinPage
;
1516 if (lppd
->nFromPage
> lppd
->nMaxPage
)
1517 lppd
->nFromPage
= lppd
->nMaxPage
;
1519 /* if we have the combo box, fill it */
1520 if (GetDlgItem(hDlg
,comboID
)) {
1523 pdn
= GlobalLock(lppd
->hDevNames
);
1524 pdm
= GlobalLock(lppd
->hDevMode
);
1526 name
= (char*)pdn
+ pdn
->wDeviceOffset
;
1528 name
= (char*)pdm
->dmDeviceName
;
1529 PRINTDLG_SetUpPrinterListComboA(hDlg
, comboID
, name
);
1530 if(pdm
) GlobalUnlock(lppd
->hDevMode
);
1531 if(pdn
) GlobalUnlock(lppd
->hDevNames
);
1533 /* Now find selected printer and update rest of dlg */
1535 if (GetDlgItemTextA(hDlg
, comboID
, name
, 255))
1536 PRINTDLG_ChangePrinterA(hDlg
, name
, PrintStructures
);
1539 /* else use default printer */
1541 DWORD dwBufLen
= ARRAY_SIZE(name
);
1542 BOOL ret
= GetDefaultPrinterA(name
, &dwBufLen
);
1545 PRINTDLG_ChangePrinterA(hDlg
, name
, PrintStructures
);
1547 FIXME("No default printer found, expect problems!\n");
1552 static LRESULT
PRINTDLG_WMInitDialogW(HWND hDlg
,
1553 PRINT_PTRW
* PrintStructures
)
1555 LPPRINTDLGW lppd
= PrintStructures
->lpPrintDlg
;
1559 UINT comboID
= (lppd
->Flags
& PD_PRINTSETUP
) ? cmb1
: cmb4
;
1561 /* load Collate ICONs */
1562 /* We load these with LoadImage because they are not a standard
1563 size and we don't want them rescaled */
1564 PrintStructures
->hCollateIcon
=
1565 LoadImageW(COMDLG32_hInstance
, L
"PD32_COLLATE", IMAGE_ICON
, 0, 0, 0);
1566 PrintStructures
->hNoCollateIcon
=
1567 LoadImageW(COMDLG32_hInstance
, L
"PD32_NOCOLLATE", IMAGE_ICON
, 0, 0, 0);
1569 /* These can be done with LoadIcon */
1570 PrintStructures
->hPortraitIcon
=
1571 LoadIconW(COMDLG32_hInstance
, L
"PD32_PORTRAIT");
1572 PrintStructures
->hLandscapeIcon
=
1573 LoadIconW(COMDLG32_hInstance
, L
"PD32_LANDSCAPE");
1575 /* display the collate/no_collate icon */
1576 SendDlgItemMessageW(hDlg
, ico3
, STM_SETIMAGE
, IMAGE_ICON
,
1577 (LPARAM
)PrintStructures
->hNoCollateIcon
);
1579 if(PrintStructures
->hCollateIcon
== 0 ||
1580 PrintStructures
->hNoCollateIcon
== 0 ||
1581 PrintStructures
->hPortraitIcon
== 0 ||
1582 PrintStructures
->hLandscapeIcon
== 0) {
1583 ERR("no icon in resource file\n");
1584 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
1585 EndDialog(hDlg
, FALSE
);
1589 * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
1590 * must be registered and the Help button must be shown.
1592 if (lppd
->Flags
& PD_SHOWHELP
) {
1593 if((PrintStructures
->HelpMessageID
=
1594 RegisterWindowMessageW(HELPMSGSTRINGW
)) == 0) {
1595 COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL
);
1599 PrintStructures
->HelpMessageID
= 0;
1601 if(!(lppd
->Flags
&PD_PRINTSETUP
)) {
1602 PrintStructures
->hwndUpDown
=
1603 CreateUpDownControl(WS_CHILD
| WS_VISIBLE
| WS_BORDER
|
1604 UDS_NOTHOUSANDS
| UDS_ARROWKEYS
|
1605 UDS_ALIGNRIGHT
| UDS_SETBUDDYINT
, 0, 0, 0, 0,
1606 hDlg
, UPDOWN_ID
, COMDLG32_hInstance
,
1607 GetDlgItem(hDlg
, edt3
), MAX_COPIES
, 1, 1);
1610 /* FIXME: I allow more freedom than either Win95 or WinNT,
1611 * which do not agree to what errors should be thrown or not
1612 * in case nToPage or nFromPage is out-of-range.
1614 if (lppd
->nMaxPage
< lppd
->nMinPage
)
1615 lppd
->nMaxPage
= lppd
->nMinPage
;
1616 if (lppd
->nMinPage
== lppd
->nMaxPage
)
1617 lppd
->Flags
|= PD_NOPAGENUMS
;
1618 if (lppd
->nToPage
< lppd
->nMinPage
)
1619 lppd
->nToPage
= lppd
->nMinPage
;
1620 if (lppd
->nToPage
> lppd
->nMaxPage
)
1621 lppd
->nToPage
= lppd
->nMaxPage
;
1622 if (lppd
->nFromPage
< lppd
->nMinPage
)
1623 lppd
->nFromPage
= lppd
->nMinPage
;
1624 if (lppd
->nFromPage
> lppd
->nMaxPage
)
1625 lppd
->nFromPage
= lppd
->nMaxPage
;
1627 /* if we have the combo box, fill it */
1628 if (GetDlgItem(hDlg
,comboID
)) {
1631 pdn
= GlobalLock(lppd
->hDevNames
);
1632 pdm
= GlobalLock(lppd
->hDevMode
);
1634 name
= (WCHAR
*)pdn
+ pdn
->wDeviceOffset
;
1636 name
= pdm
->dmDeviceName
;
1637 PRINTDLG_SetUpPrinterListComboW(hDlg
, comboID
, name
);
1638 if(pdm
) GlobalUnlock(lppd
->hDevMode
);
1639 if(pdn
) GlobalUnlock(lppd
->hDevNames
);
1641 /* Now find selected printer and update rest of dlg */
1642 /* ansi is ok here */
1643 name
= malloc(256 * sizeof(WCHAR
));
1644 if (GetDlgItemTextW(hDlg
, comboID
, name
, 255))
1645 PRINTDLG_ChangePrinterW(hDlg
, name
, PrintStructures
);
1648 /* else use default printer */
1650 DWORD dwBufLen
= ARRAY_SIZE(name
);
1651 BOOL ret
= GetDefaultPrinterW(name
, &dwBufLen
);
1654 PRINTDLG_ChangePrinterW(hDlg
, name
, PrintStructures
);
1656 FIXME("No default printer found, expect problems!\n");
1661 /***********************************************************************
1662 * PRINTDLG_WMCommand [internal]
1664 static LRESULT
PRINTDLG_WMCommandA(HWND hDlg
, WPARAM wParam
,
1665 PRINT_PTRA
* PrintStructures
)
1667 LPPRINTDLGA lppd
= PrintStructures
->lpPrintDlg
;
1668 UINT PrinterComboID
= (lppd
->Flags
& PD_PRINTSETUP
) ? cmb1
: cmb4
;
1669 LPDEVMODEA lpdm
= PrintStructures
->lpDevMode
;
1671 switch (LOWORD(wParam
)) {
1673 TRACE(" OK button was hit\n");
1674 if (!PRINTDLG_UpdatePrintDlgA(hDlg
, PrintStructures
)) {
1675 FIXME("Update printdlg was not successful!\n");
1678 EndDialog(hDlg
, TRUE
);
1682 TRACE(" CANCEL button was hit\n");
1683 EndDialog(hDlg
, FALSE
);
1687 TRACE(" HELP button was hit\n");
1688 SendMessageA(lppd
->hwndOwner
, PrintStructures
->HelpMessageID
,
1689 (WPARAM
) hDlg
, (LPARAM
) lppd
);
1692 case chx2
: /* collate pages checkbox */
1693 if (IsDlgButtonChecked(hDlg
, chx2
) == BST_CHECKED
)
1694 SendDlgItemMessageA(hDlg
, ico3
, STM_SETIMAGE
, IMAGE_ICON
,
1695 (LPARAM
)PrintStructures
->hCollateIcon
);
1697 SendDlgItemMessageA(hDlg
, ico3
, STM_SETIMAGE
, IMAGE_ICON
,
1698 (LPARAM
)PrintStructures
->hNoCollateIcon
);
1700 case edt1
: /* from page nr editbox */
1701 case edt2
: /* to page nr editbox */
1702 if (HIWORD(wParam
)==EN_CHANGE
) {
1705 nFromPage
= GetDlgItemInt(hDlg
, edt1
, NULL
, FALSE
);
1706 nToPage
= GetDlgItemInt(hDlg
, edt2
, NULL
, FALSE
);
1707 if (nFromPage
!= lppd
->nFromPage
|| nToPage
!= lppd
->nToPage
)
1708 CheckRadioButton(hDlg
, rad1
, rad3
, rad3
);
1713 if(HIWORD(wParam
) == EN_CHANGE
) {
1714 INT copies
= GetDlgItemInt(hDlg
, edt3
, NULL
, FALSE
);
1716 EnableWindow(GetDlgItem(hDlg
, chx2
), FALSE
);
1718 EnableWindow(GetDlgItem(hDlg
, chx2
), TRUE
);
1722 case psh2
: /* Properties button */
1725 char PrinterName
[256];
1727 GetDlgItemTextA(hDlg
, PrinterComboID
, PrinterName
, 255);
1728 if (!OpenPrinterA(PrinterName
, &hPrinter
, NULL
)) {
1729 FIXME(" Call to OpenPrinter did not succeed!\n");
1732 DocumentPropertiesA(hDlg
, hPrinter
, PrinterName
,
1733 PrintStructures
->lpDevMode
,
1734 PrintStructures
->lpDevMode
,
1735 DM_IN_BUFFER
| DM_OUT_BUFFER
| DM_IN_PROMPT
);
1736 ClosePrinter(hPrinter
);
1740 case rad1
: /* Paperorientation */
1741 if (lppd
->Flags
& PD_PRINTSETUP
)
1743 lpdm
->u1
.s1
.dmOrientation
= DMORIENT_PORTRAIT
;
1744 SendDlgItemMessageA(hDlg
, ico1
, STM_SETIMAGE
, IMAGE_ICON
,
1745 (LPARAM
)(PrintStructures
->hPortraitIcon
));
1749 case rad2
: /* Paperorientation */
1750 if (lppd
->Flags
& PD_PRINTSETUP
)
1752 lpdm
->u1
.s1
.dmOrientation
= DMORIENT_LANDSCAPE
;
1753 SendDlgItemMessageA(hDlg
, ico1
, STM_SETIMAGE
, IMAGE_ICON
,
1754 (LPARAM
)(PrintStructures
->hLandscapeIcon
));
1758 case cmb1
: /* Printer Combobox in PRINT SETUP, quality combobox in PRINT16 */
1759 if (PrinterComboID
!= LOWORD(wParam
)) {
1763 case cmb4
: /* Printer combobox */
1764 if (HIWORD(wParam
)==CBN_SELCHANGE
) {
1766 INT index
= SendDlgItemMessageW(hDlg
, LOWORD(wParam
), CB_GETCURSEL
, 0, 0);
1767 INT length
= SendDlgItemMessageW(hDlg
, LOWORD(wParam
), CB_GETLBTEXTLEN
, index
, 0);
1768 PrinterName
= malloc(length
+ 1);
1769 SendDlgItemMessageA(hDlg
, LOWORD(wParam
), CB_GETLBTEXT
, index
, (LPARAM
)PrinterName
);
1770 PRINTDLG_ChangePrinterA(hDlg
, PrinterName
, PrintStructures
);
1775 case cmb2
: /* Papersize */
1777 DWORD Sel
= SendDlgItemMessageA(hDlg
, cmb2
, CB_GETCURSEL
, 0, 0);
1779 lpdm
->u1
.s1
.dmPaperSize
= SendDlgItemMessageA(hDlg
, cmb2
,
1782 GetDlgItemTextA(hDlg
, cmb2
, (char *)lpdm
->dmFormName
, CCHFORMNAME
);
1787 case cmb3
: /* Bin */
1789 DWORD Sel
= SendDlgItemMessageA(hDlg
, cmb3
, CB_GETCURSEL
, 0, 0);
1791 lpdm
->u1
.s1
.dmDefaultSource
= SendDlgItemMessageA(hDlg
, cmb3
,
1792 CB_GETITEMDATA
, Sel
,
1797 if(lppd
->Flags
& PD_PRINTSETUP
) {
1798 switch (LOWORD(wParam
)) {
1799 case rad1
: /* orientation */
1801 if (IsDlgButtonChecked(hDlg
, rad1
) == BST_CHECKED
) {
1802 if(lpdm
->u1
.s1
.dmOrientation
!= DMORIENT_PORTRAIT
) {
1803 lpdm
->u1
.s1
.dmOrientation
= DMORIENT_PORTRAIT
;
1804 SendDlgItemMessageA(hDlg
, stc10
, STM_SETIMAGE
, IMAGE_ICON
,
1805 (LPARAM
)PrintStructures
->hPortraitIcon
);
1806 SendDlgItemMessageA(hDlg
, ico1
, STM_SETIMAGE
, IMAGE_ICON
,
1807 (LPARAM
)PrintStructures
->hPortraitIcon
);
1810 if(lpdm
->u1
.s1
.dmOrientation
!= DMORIENT_LANDSCAPE
) {
1811 lpdm
->u1
.s1
.dmOrientation
= DMORIENT_LANDSCAPE
;
1812 SendDlgItemMessageA(hDlg
, stc10
, STM_SETIMAGE
, IMAGE_ICON
,
1813 (LPARAM
)PrintStructures
->hLandscapeIcon
);
1814 SendDlgItemMessageA(hDlg
, ico1
, STM_SETIMAGE
, IMAGE_ICON
,
1815 (LPARAM
)PrintStructures
->hLandscapeIcon
);
1824 static LRESULT
PRINTDLG_WMCommandW(HWND hDlg
, WPARAM wParam
,
1825 PRINT_PTRW
* PrintStructures
)
1827 LPPRINTDLGW lppd
= PrintStructures
->lpPrintDlg
;
1828 UINT PrinterComboID
= (lppd
->Flags
& PD_PRINTSETUP
) ? cmb1
: cmb4
;
1829 LPDEVMODEW lpdm
= PrintStructures
->lpDevMode
;
1831 switch (LOWORD(wParam
)) {
1833 TRACE(" OK button was hit\n");
1834 if (!PRINTDLG_UpdatePrintDlgW(hDlg
, PrintStructures
)) {
1835 FIXME("Update printdlg was not successful!\n");
1838 EndDialog(hDlg
, TRUE
);
1842 TRACE(" CANCEL button was hit\n");
1843 EndDialog(hDlg
, FALSE
);
1847 TRACE(" HELP button was hit\n");
1848 SendMessageW(lppd
->hwndOwner
, PrintStructures
->HelpMessageID
,
1849 (WPARAM
) hDlg
, (LPARAM
) lppd
);
1852 case chx2
: /* collate pages checkbox */
1853 if (IsDlgButtonChecked(hDlg
, chx2
) == BST_CHECKED
)
1854 SendDlgItemMessageW(hDlg
, ico3
, STM_SETIMAGE
, IMAGE_ICON
,
1855 (LPARAM
)PrintStructures
->hCollateIcon
);
1857 SendDlgItemMessageW(hDlg
, ico3
, STM_SETIMAGE
, IMAGE_ICON
,
1858 (LPARAM
)PrintStructures
->hNoCollateIcon
);
1860 case edt1
: /* from page nr editbox */
1861 case edt2
: /* to page nr editbox */
1862 if (HIWORD(wParam
)==EN_CHANGE
) {
1865 nFromPage
= GetDlgItemInt(hDlg
, edt1
, NULL
, FALSE
);
1866 nToPage
= GetDlgItemInt(hDlg
, edt2
, NULL
, FALSE
);
1867 if (nFromPage
!= lppd
->nFromPage
|| nToPage
!= lppd
->nToPage
)
1868 CheckRadioButton(hDlg
, rad1
, rad3
, rad3
);
1873 if(HIWORD(wParam
) == EN_CHANGE
) {
1874 INT copies
= GetDlgItemInt(hDlg
, edt3
, NULL
, FALSE
);
1876 EnableWindow(GetDlgItem(hDlg
, chx2
), FALSE
);
1878 EnableWindow(GetDlgItem(hDlg
, chx2
), TRUE
);
1882 case psh2
: /* Properties button */
1885 WCHAR PrinterName
[256];
1887 if (!GetDlgItemTextW(hDlg
, PrinterComboID
, PrinterName
, 255)) break;
1888 if (!OpenPrinterW(PrinterName
, &hPrinter
, NULL
)) {
1889 FIXME(" Call to OpenPrinter did not succeed!\n");
1892 DocumentPropertiesW(hDlg
, hPrinter
, PrinterName
,
1893 PrintStructures
->lpDevMode
,
1894 PrintStructures
->lpDevMode
,
1895 DM_IN_BUFFER
| DM_OUT_BUFFER
| DM_IN_PROMPT
);
1896 ClosePrinter(hPrinter
);
1900 case rad1
: /* Paperorientation */
1901 if (lppd
->Flags
& PD_PRINTSETUP
)
1903 lpdm
->u1
.s1
.dmOrientation
= DMORIENT_PORTRAIT
;
1904 SendDlgItemMessageW(hDlg
, ico1
, STM_SETIMAGE
, IMAGE_ICON
,
1905 (LPARAM
)(PrintStructures
->hPortraitIcon
));
1909 case rad2
: /* Paperorientation */
1910 if (lppd
->Flags
& PD_PRINTSETUP
)
1912 lpdm
->u1
.s1
.dmOrientation
= DMORIENT_LANDSCAPE
;
1913 SendDlgItemMessageW(hDlg
, ico1
, STM_SETIMAGE
, IMAGE_ICON
,
1914 (LPARAM
)(PrintStructures
->hLandscapeIcon
));
1918 case cmb1
: /* Printer Combobox in PRINT SETUP */
1920 case cmb4
: /* Printer combobox */
1921 if (HIWORD(wParam
)==CBN_SELCHANGE
) {
1923 INT index
= SendDlgItemMessageW(hDlg
, LOWORD(wParam
), CB_GETCURSEL
, 0, 0);
1924 INT length
= SendDlgItemMessageW(hDlg
, LOWORD(wParam
), CB_GETLBTEXTLEN
, index
, 0);
1926 PrinterName
= malloc(sizeof(WCHAR
) * (length
+ 1));
1927 SendDlgItemMessageW(hDlg
, LOWORD(wParam
), CB_GETLBTEXT
, index
, (LPARAM
)PrinterName
);
1928 PRINTDLG_ChangePrinterW(hDlg
, PrinterName
, PrintStructures
);
1933 case cmb2
: /* Papersize */
1935 DWORD Sel
= SendDlgItemMessageW(hDlg
, cmb2
, CB_GETCURSEL
, 0, 0);
1937 lpdm
->u1
.s1
.dmPaperSize
= SendDlgItemMessageW(hDlg
, cmb2
,
1940 GetDlgItemTextW(hDlg
, cmb2
, lpdm
->dmFormName
, CCHFORMNAME
);
1945 case cmb3
: /* Bin */
1947 DWORD Sel
= SendDlgItemMessageW(hDlg
, cmb3
, CB_GETCURSEL
, 0, 0);
1949 lpdm
->u1
.s1
.dmDefaultSource
= SendDlgItemMessageW(hDlg
, cmb3
,
1950 CB_GETITEMDATA
, Sel
,
1955 if(lppd
->Flags
& PD_PRINTSETUP
) {
1956 switch (LOWORD(wParam
)) {
1957 case rad1
: /* orientation */
1959 if (IsDlgButtonChecked(hDlg
, rad1
) == BST_CHECKED
) {
1960 if(lpdm
->u1
.s1
.dmOrientation
!= DMORIENT_PORTRAIT
) {
1961 lpdm
->u1
.s1
.dmOrientation
= DMORIENT_PORTRAIT
;
1962 SendDlgItemMessageW(hDlg
, stc10
, STM_SETIMAGE
, IMAGE_ICON
,
1963 (LPARAM
)PrintStructures
->hPortraitIcon
);
1964 SendDlgItemMessageW(hDlg
, ico1
, STM_SETIMAGE
, IMAGE_ICON
,
1965 (LPARAM
)PrintStructures
->hPortraitIcon
);
1968 if(lpdm
->u1
.s1
.dmOrientation
!= DMORIENT_LANDSCAPE
) {
1969 lpdm
->u1
.s1
.dmOrientation
= DMORIENT_LANDSCAPE
;
1970 SendDlgItemMessageW(hDlg
, stc10
, STM_SETIMAGE
, IMAGE_ICON
,
1971 (LPARAM
)PrintStructures
->hLandscapeIcon
);
1972 SendDlgItemMessageW(hDlg
, ico1
, STM_SETIMAGE
, IMAGE_ICON
,
1973 (LPARAM
)PrintStructures
->hLandscapeIcon
);
1982 /***********************************************************************
1983 * PrintDlgProcA [internal]
1985 static INT_PTR CALLBACK
PrintDlgProcA(HWND hDlg
, UINT uMsg
, WPARAM wParam
,
1988 PRINT_PTRA
* PrintStructures
;
1989 INT_PTR res
= FALSE
;
1991 if (uMsg
!=WM_INITDIALOG
) {
1992 PrintStructures
= GetPropW(hDlg
, printdlg_prop
);
1993 if (!PrintStructures
)
1996 PrintStructures
= (PRINT_PTRA
*) lParam
;
1997 SetPropW(hDlg
, printdlg_prop
, PrintStructures
);
1998 if(!check_printer_setup(hDlg
))
2000 EndDialog(hDlg
,FALSE
);
2003 res
= PRINTDLG_WMInitDialog(hDlg
, PrintStructures
);
2005 if(PrintStructures
->lpPrintDlg
->Flags
& PD_ENABLEPRINTHOOK
)
2006 res
= PrintStructures
->lpPrintDlg
->lpfnPrintHook(
2007 hDlg
, uMsg
, wParam
, (LPARAM
)PrintStructures
->lpPrintDlg
2012 if(PrintStructures
->lpPrintDlg
->Flags
& PD_ENABLEPRINTHOOK
) {
2013 res
= PrintStructures
->lpPrintDlg
->lpfnPrintHook(hDlg
,uMsg
,wParam
,
2020 return PRINTDLG_WMCommandA(hDlg
, wParam
, PrintStructures
);
2023 DestroyIcon(PrintStructures
->hCollateIcon
);
2024 DestroyIcon(PrintStructures
->hNoCollateIcon
);
2025 DestroyIcon(PrintStructures
->hPortraitIcon
);
2026 DestroyIcon(PrintStructures
->hLandscapeIcon
);
2027 if(PrintStructures
->hwndUpDown
)
2028 DestroyWindow(PrintStructures
->hwndUpDown
);
2034 static INT_PTR CALLBACK
PrintDlgProcW(HWND hDlg
, UINT uMsg
, WPARAM wParam
,
2037 PRINT_PTRW
* PrintStructures
;
2038 INT_PTR res
= FALSE
;
2040 if (uMsg
!=WM_INITDIALOG
) {
2041 PrintStructures
= GetPropW(hDlg
, printdlg_prop
);
2042 if (!PrintStructures
)
2045 PrintStructures
= (PRINT_PTRW
*) lParam
;
2046 SetPropW(hDlg
, printdlg_prop
, PrintStructures
);
2047 if(!check_printer_setup(hDlg
))
2049 EndDialog(hDlg
,FALSE
);
2052 res
= PRINTDLG_WMInitDialogW(hDlg
, PrintStructures
);
2054 if(PrintStructures
->lpPrintDlg
->Flags
& PD_ENABLEPRINTHOOK
)
2055 res
= PrintStructures
->lpPrintDlg
->lpfnPrintHook(hDlg
, uMsg
, wParam
, (LPARAM
)PrintStructures
->lpPrintDlg
);
2059 if(PrintStructures
->lpPrintDlg
->Flags
& PD_ENABLEPRINTHOOK
) {
2060 res
= PrintStructures
->lpPrintDlg
->lpfnPrintHook(hDlg
,uMsg
,wParam
, lParam
);
2066 return PRINTDLG_WMCommandW(hDlg
, wParam
, PrintStructures
);
2069 DestroyIcon(PrintStructures
->hCollateIcon
);
2070 DestroyIcon(PrintStructures
->hNoCollateIcon
);
2071 DestroyIcon(PrintStructures
->hPortraitIcon
);
2072 DestroyIcon(PrintStructures
->hLandscapeIcon
);
2073 if(PrintStructures
->hwndUpDown
)
2074 DestroyWindow(PrintStructures
->hwndUpDown
);
2080 /************************************************************
2082 * PRINTDLG_GetDlgTemplate
2085 static HGLOBAL
PRINTDLG_GetDlgTemplateA(const PRINTDLGA
*lppd
)
2090 if (lppd
->Flags
& PD_PRINTSETUP
) {
2091 if(lppd
->Flags
& PD_ENABLESETUPTEMPLATEHANDLE
) {
2092 hDlgTmpl
= lppd
->hSetupTemplate
;
2093 } else if(lppd
->Flags
& PD_ENABLESETUPTEMPLATE
) {
2094 hResInfo
= FindResourceA(lppd
->hInstance
,
2095 lppd
->lpSetupTemplateName
, (LPSTR
)RT_DIALOG
);
2096 hDlgTmpl
= LoadResource(lppd
->hInstance
, hResInfo
);
2098 hResInfo
= FindResourceA(COMDLG32_hInstance
, "PRINT32_SETUP",
2100 hDlgTmpl
= LoadResource(COMDLG32_hInstance
, hResInfo
);
2103 if(lppd
->Flags
& PD_ENABLEPRINTTEMPLATEHANDLE
) {
2104 hDlgTmpl
= lppd
->hPrintTemplate
;
2105 } else if(lppd
->Flags
& PD_ENABLEPRINTTEMPLATE
) {
2106 hResInfo
= FindResourceA(lppd
->hInstance
,
2107 lppd
->lpPrintTemplateName
,
2109 hDlgTmpl
= LoadResource(lppd
->hInstance
, hResInfo
);
2111 hResInfo
= FindResourceA(COMDLG32_hInstance
, "PRINT32",
2113 hDlgTmpl
= LoadResource(COMDLG32_hInstance
, hResInfo
);
2119 static HGLOBAL
PRINTDLG_GetDlgTemplateW(const PRINTDLGW
*lppd
)
2124 if (lppd
->Flags
& PD_PRINTSETUP
) {
2125 if(lppd
->Flags
& PD_ENABLESETUPTEMPLATEHANDLE
) {
2126 hDlgTmpl
= lppd
->hSetupTemplate
;
2127 } else if(lppd
->Flags
& PD_ENABLESETUPTEMPLATE
) {
2128 hResInfo
= FindResourceW(lppd
->hInstance
,
2129 lppd
->lpSetupTemplateName
, (LPWSTR
)RT_DIALOG
);
2130 hDlgTmpl
= LoadResource(lppd
->hInstance
, hResInfo
);
2132 hResInfo
= FindResourceW(COMDLG32_hInstance
, L
"PRINT32_SETUP", (LPWSTR
)RT_DIALOG
);
2133 hDlgTmpl
= LoadResource(COMDLG32_hInstance
, hResInfo
);
2136 if(lppd
->Flags
& PD_ENABLEPRINTTEMPLATEHANDLE
) {
2137 hDlgTmpl
= lppd
->hPrintTemplate
;
2138 } else if(lppd
->Flags
& PD_ENABLEPRINTTEMPLATE
) {
2139 hResInfo
= FindResourceW(lppd
->hInstance
,
2140 lppd
->lpPrintTemplateName
,
2142 hDlgTmpl
= LoadResource(lppd
->hInstance
, hResInfo
);
2144 hResInfo
= FindResourceW(COMDLG32_hInstance
, L
"PRINT32", (LPWSTR
)RT_DIALOG
);
2145 hDlgTmpl
= LoadResource(COMDLG32_hInstance
, hResInfo
);
2151 /***********************************************************************
2156 static BOOL
PRINTDLG_CreateDCA(LPPRINTDLGA lppd
)
2158 DEVNAMES
*pdn
= GlobalLock(lppd
->hDevNames
);
2159 DEVMODEA
*pdm
= GlobalLock(lppd
->hDevMode
);
2161 if(lppd
->Flags
& PD_RETURNDC
) {
2162 lppd
->hDC
= CreateDCA((char*)pdn
+ pdn
->wDriverOffset
,
2163 (char*)pdn
+ pdn
->wDeviceOffset
,
2164 (char*)pdn
+ pdn
->wOutputOffset
,
2166 } else if(lppd
->Flags
& PD_RETURNIC
) {
2167 lppd
->hDC
= CreateICA((char*)pdn
+ pdn
->wDriverOffset
,
2168 (char*)pdn
+ pdn
->wDeviceOffset
,
2169 (char*)pdn
+ pdn
->wOutputOffset
,
2172 GlobalUnlock(lppd
->hDevNames
);
2173 GlobalUnlock(lppd
->hDevMode
);
2174 return lppd
->hDC
!= NULL
;
2177 static BOOL
PRINTDLG_CreateDCW(LPPRINTDLGW lppd
)
2179 DEVNAMES
*pdn
= GlobalLock(lppd
->hDevNames
);
2180 DEVMODEW
*pdm
= GlobalLock(lppd
->hDevMode
);
2182 if(lppd
->Flags
& PD_RETURNDC
) {
2183 lppd
->hDC
= CreateDCW((WCHAR
*)pdn
+ pdn
->wDriverOffset
,
2184 (WCHAR
*)pdn
+ pdn
->wDeviceOffset
,
2185 (WCHAR
*)pdn
+ pdn
->wOutputOffset
,
2187 } else if(lppd
->Flags
& PD_RETURNIC
) {
2188 lppd
->hDC
= CreateICW((WCHAR
*)pdn
+ pdn
->wDriverOffset
,
2189 (WCHAR
*)pdn
+ pdn
->wDeviceOffset
,
2190 (WCHAR
*)pdn
+ pdn
->wOutputOffset
,
2193 GlobalUnlock(lppd
->hDevNames
);
2194 GlobalUnlock(lppd
->hDevMode
);
2195 return lppd
->hDC
!= NULL
;
2198 /***********************************************************************
2199 * PrintDlgA (COMDLG32.@)
2201 * Displays the PRINT dialog box, which enables the user to specify
2202 * specific properties of the print job.
2205 * lppd [IO] ptr to PRINTDLG32 struct
2208 * nonzero if the user pressed the OK button
2209 * zero if the user cancelled the window or an error occurred
2213 * * The Collate Icons do not display, even though they are in the code.
2214 * * The Properties Button(s) should call DocumentPropertiesA().
2217 BOOL WINAPI
PrintDlgA(LPPRINTDLGA lppd
)
2225 COMDLG32_SetCommDlgExtendedError(CDERR_INITIALIZATION
);
2229 if(TRACE_ON(commdlg
)) {
2230 char flagstr
[1000] = "";
2231 const struct pd_flags
*pflag
= pd_flags
;
2232 for( ; pflag
->name
; pflag
++) {
2233 if(lppd
->Flags
& pflag
->flag
)
2234 strcat(flagstr
, pflag
->name
);
2236 TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
2237 "pp. %d-%d, min p %d, max p %d, copies %d, hinst %p\n"
2238 "flags %08lx (%s)\n",
2239 lppd
, lppd
->hwndOwner
, lppd
->hDevMode
, lppd
->hDevNames
,
2240 lppd
->nFromPage
, lppd
->nToPage
, lppd
->nMinPage
, lppd
->nMaxPage
,
2241 lppd
->nCopies
, lppd
->hInstance
, lppd
->Flags
, flagstr
);
2244 if(lppd
->lStructSize
!= sizeof(PRINTDLGA
)) {
2245 WARN("structure size failure!!!\n");
2246 COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE
);
2250 if(lppd
->Flags
& PD_RETURNDEFAULT
) {
2251 PRINTER_INFO_2A
*pbuf
;
2252 DRIVER_INFO_3A
*dbuf
;
2256 if(lppd
->hDevMode
|| lppd
->hDevNames
) {
2257 WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
2258 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE
);
2261 if(!PRINTDLG_OpenDefaultPrinter(&hprn
)) {
2262 WARN("Can't find default printer\n");
2263 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN
);
2267 GetPrinterA(hprn
, 2, NULL
, 0, &needed
);
2268 pbuf
= malloc(needed
);
2269 GetPrinterA(hprn
, 2, (LPBYTE
)pbuf
, needed
, &needed
);
2271 GetPrinterDriverA(hprn
, NULL
, 3, NULL
, 0, &needed
);
2272 dbuf
= malloc(needed
);
2273 if (!GetPrinterDriverA(hprn
, NULL
, 3, (LPBYTE
)dbuf
, needed
, &needed
)) {
2274 ERR("GetPrinterDriverA failed, le %ld, fix your config for printer %s!\n",
2275 GetLastError(),pbuf
->pPrinterName
);
2278 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE
);
2283 PRINTDLG_CreateDevNames(&(lppd
->hDevNames
),
2287 lppd
->hDevMode
= GlobalAlloc(GMEM_MOVEABLE
, pbuf
->pDevMode
->dmSize
+
2288 pbuf
->pDevMode
->dmDriverExtra
);
2289 ptr
= GlobalLock(lppd
->hDevMode
);
2290 memcpy(ptr
, pbuf
->pDevMode
, pbuf
->pDevMode
->dmSize
+
2291 pbuf
->pDevMode
->dmDriverExtra
);
2292 GlobalUnlock(lppd
->hDevMode
);
2298 PRINT_PTRA
*PrintStructures
;
2300 /* load Dialog resources,
2301 * depending on Flags indicates Print32 or Print32_setup dialog
2303 hDlgTmpl
= PRINTDLG_GetDlgTemplateA(lppd
);
2305 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
2308 ptr
= LockResource( hDlgTmpl
);
2310 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
2314 PrintStructures
= calloc(1, sizeof(PRINT_PTRA
));
2315 PrintStructures
->lpPrintDlg
= lppd
;
2317 /* and create & process the dialog .
2318 * -1 is failure, 0 is broken hwnd, everything else is ok.
2320 hInst
= COMDLG32_hInstance
;
2321 if (lppd
->Flags
& (PD_ENABLESETUPTEMPLATE
| PD_ENABLEPRINTTEMPLATE
)) hInst
= lppd
->hInstance
;
2322 bRet
= (0<DialogBoxIndirectParamA(hInst
, ptr
, lppd
->hwndOwner
,
2324 (LPARAM
)PrintStructures
));
2327 DEVMODEA
*lpdm
= PrintStructures
->lpDevMode
, *lpdmReturn
;
2328 PRINTER_INFO_2A
*pi
= PrintStructures
->lpPrinterInfo
;
2329 DRIVER_INFO_3A
*di
= PrintStructures
->lpDriverInfo
;
2331 if (lppd
->hDevMode
== 0) {
2332 TRACE(" No hDevMode yet... Need to create my own\n");
2333 lppd
->hDevMode
= GlobalAlloc(GMEM_MOVEABLE
,
2334 lpdm
->dmSize
+ lpdm
->dmDriverExtra
);
2336 lppd
->hDevMode
= GlobalReAlloc(lppd
->hDevMode
,
2337 lpdm
->dmSize
+ lpdm
->dmDriverExtra
,
2340 lpdmReturn
= GlobalLock(lppd
->hDevMode
);
2341 memcpy(lpdmReturn
, lpdm
, lpdm
->dmSize
+ lpdm
->dmDriverExtra
);
2343 PRINTDLG_CreateDevNames(&(lppd
->hDevNames
),
2348 GlobalUnlock(lppd
->hDevMode
);
2350 free(PrintStructures
->lpDevMode
);
2351 free(PrintStructures
->lpPrinterInfo
);
2352 free(PrintStructures
->lpDriverInfo
);
2353 free(PrintStructures
);
2355 if(bRet
&& (lppd
->Flags
& PD_RETURNDC
|| lppd
->Flags
& PD_RETURNIC
))
2356 bRet
= PRINTDLG_CreateDCA(lppd
);
2358 TRACE("exit! (%d)\n", bRet
);
2362 /***********************************************************************
2363 * PrintDlgW (COMDLG32.@)
2367 BOOL WINAPI
PrintDlgW(LPPRINTDLGW lppd
)
2375 COMDLG32_SetCommDlgExtendedError(CDERR_INITIALIZATION
);
2379 if(TRACE_ON(commdlg
)) {
2380 char flagstr
[1000] = "";
2381 const struct pd_flags
*pflag
= pd_flags
;
2382 for( ; pflag
->name
; pflag
++) {
2383 if(lppd
->Flags
& pflag
->flag
)
2384 strcat(flagstr
, pflag
->name
);
2386 TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
2387 "pp. %d-%d, min p %d, max p %d, copies %d, hinst %p\n"
2388 "flags %08lx (%s)\n",
2389 lppd
, lppd
->hwndOwner
, lppd
->hDevMode
, lppd
->hDevNames
,
2390 lppd
->nFromPage
, lppd
->nToPage
, lppd
->nMinPage
, lppd
->nMaxPage
,
2391 lppd
->nCopies
, lppd
->hInstance
, lppd
->Flags
, flagstr
);
2394 if(lppd
->lStructSize
!= sizeof(PRINTDLGW
)) {
2395 WARN("structure size failure!!!\n");
2396 COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE
);
2400 if(lppd
->Flags
& PD_RETURNDEFAULT
) {
2401 PRINTER_INFO_2W
*pbuf
;
2402 DRIVER_INFO_3W
*dbuf
;
2406 if(lppd
->hDevMode
|| lppd
->hDevNames
) {
2407 WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
2408 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE
);
2411 if(!PRINTDLG_OpenDefaultPrinter(&hprn
)) {
2412 WARN("Can't find default printer\n");
2413 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN
);
2417 GetPrinterW(hprn
, 2, NULL
, 0, &needed
);
2418 pbuf
= malloc(needed
);
2419 GetPrinterW(hprn
, 2, (LPBYTE
)pbuf
, needed
, &needed
);
2421 GetPrinterDriverW(hprn
, NULL
, 3, NULL
, 0, &needed
);
2422 dbuf
= malloc(needed
);
2423 if (!GetPrinterDriverW(hprn
, NULL
, 3, (LPBYTE
)dbuf
, needed
, &needed
)) {
2424 ERR("GetPrinterDriverA failed, le %ld, fix your config for printer %s!\n",
2425 GetLastError(),debugstr_w(pbuf
->pPrinterName
));
2428 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE
);
2433 PRINTDLG_CreateDevNamesW(&(lppd
->hDevNames
),
2437 lppd
->hDevMode
= GlobalAlloc(GMEM_MOVEABLE
, pbuf
->pDevMode
->dmSize
+
2438 pbuf
->pDevMode
->dmDriverExtra
);
2439 ptr
= GlobalLock(lppd
->hDevMode
);
2440 memcpy(ptr
, pbuf
->pDevMode
, pbuf
->pDevMode
->dmSize
+
2441 pbuf
->pDevMode
->dmDriverExtra
);
2442 GlobalUnlock(lppd
->hDevMode
);
2448 PRINT_PTRW
*PrintStructures
;
2450 /* load Dialog resources,
2451 * depending on Flags indicates Print32 or Print32_setup dialog
2453 hDlgTmpl
= PRINTDLG_GetDlgTemplateW(lppd
);
2455 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
2458 ptr
= LockResource( hDlgTmpl
);
2460 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
2464 PrintStructures
= calloc(1, sizeof(PRINT_PTRW
));
2465 PrintStructures
->lpPrintDlg
= lppd
;
2467 /* and create & process the dialog .
2468 * -1 is failure, 0 is broken hwnd, everything else is ok.
2470 hInst
= COMDLG32_hInstance
;
2471 if (lppd
->Flags
& (PD_ENABLESETUPTEMPLATE
| PD_ENABLEPRINTTEMPLATE
)) hInst
= lppd
->hInstance
;
2472 bRet
= (0<DialogBoxIndirectParamW(hInst
, ptr
, lppd
->hwndOwner
,
2474 (LPARAM
)PrintStructures
));
2477 DEVMODEW
*lpdm
= PrintStructures
->lpDevMode
, *lpdmReturn
;
2478 PRINTER_INFO_2W
*pi
= PrintStructures
->lpPrinterInfo
;
2479 DRIVER_INFO_3W
*di
= PrintStructures
->lpDriverInfo
;
2481 if (lppd
->hDevMode
== 0) {
2482 TRACE(" No hDevMode yet... Need to create my own\n");
2483 lppd
->hDevMode
= GlobalAlloc(GMEM_MOVEABLE
,
2484 lpdm
->dmSize
+ lpdm
->dmDriverExtra
);
2487 if((locks
= (GlobalFlags(lppd
->hDevMode
) & GMEM_LOCKCOUNT
))) {
2488 WARN("hDevMode has %d locks on it. Unlocking it now\n", locks
);
2490 GlobalUnlock(lppd
->hDevMode
);
2491 TRACE("Now got %d locks\n", locks
);
2494 lppd
->hDevMode
= GlobalReAlloc(lppd
->hDevMode
,
2495 lpdm
->dmSize
+ lpdm
->dmDriverExtra
,
2498 lpdmReturn
= GlobalLock(lppd
->hDevMode
);
2499 memcpy(lpdmReturn
, lpdm
, lpdm
->dmSize
+ lpdm
->dmDriverExtra
);
2501 if (lppd
->hDevNames
!= 0) {
2503 if((locks
= (GlobalFlags(lppd
->hDevNames
) & GMEM_LOCKCOUNT
))) {
2504 WARN("hDevNames has %d locks on it. Unlocking it now\n", locks
);
2506 GlobalUnlock(lppd
->hDevNames
);
2509 PRINTDLG_CreateDevNamesW(&(lppd
->hDevNames
),
2514 GlobalUnlock(lppd
->hDevMode
);
2516 free(PrintStructures
->lpDevMode
);
2517 free(PrintStructures
->lpPrinterInfo
);
2518 free(PrintStructures
->lpDriverInfo
);
2519 free(PrintStructures
);
2521 if(bRet
&& (lppd
->Flags
& PD_RETURNDC
|| lppd
->Flags
& PD_RETURNIC
))
2522 bRet
= PRINTDLG_CreateDCW(lppd
);
2524 TRACE("exit! (%d)\n", bRet
);
2528 /***********************************************************************
2533 * cmb1 - printer select (not in standard dialog template)
2535 * cmb3 - source (tray?)
2536 * edt4 - border left
2538 * edt6 - border right
2539 * edt7 - border bottom
2540 * psh3 - "Printer..."
2548 LPPAGESETUPDLGA dlga
;
2549 LPPAGESETUPDLGW dlgw
;
2551 HWND hDlg
; /* Page Setup dialog handle */
2552 RECT rtDrawRect
; /* Drawing rect for page */
2555 static inline DWORD
pagesetup_get_flags(const pagesetup_data
*data
)
2557 return data
->u
.dlgw
->Flags
;
2560 static inline BOOL
is_metric(const pagesetup_data
*data
)
2562 return pagesetup_get_flags(data
) & PSD_INHUNDREDTHSOFMILLIMETERS
;
2565 static inline LONG
tenths_mm_to_size(const pagesetup_data
*data
, LONG size
)
2567 if (is_metric(data
))
2570 return 10 * size
* 100 / 254;
2573 static inline LONG
thousandths_inch_to_size(const pagesetup_data
*data
, LONG size
)
2575 if (is_metric(data
))
2576 return size
* 254 / 100;
2581 static WCHAR
get_decimal_sep(void)
2588 GetLocaleInfoW(LOCALE_USER_DEFAULT
, LOCALE_SDECIMAL
, buf
, ARRAY_SIZE(buf
));
2594 static void size2str(const pagesetup_data
*data
, DWORD size
, LPWSTR strout
)
2596 /* FIXME use LOCALE_SDECIMAL when the edit parsing code can cope */
2598 if (is_metric(data
))
2601 wsprintfW(strout
, L
"%d%c%02d", size
/ 100, get_decimal_sep(), size
% 100);
2603 wsprintfW(strout
, L
"%d", size
/ 100);
2608 wsprintfW(strout
, L
"%d%c%03d", size
/ 1000, get_decimal_sep(), size
% 1000);
2610 wsprintfW(strout
, L
"%d", size
/ 1000);
2615 static inline BOOL
is_default_metric(void)
2618 GetLocaleInfoW(LOCALE_USER_DEFAULT
, LOCALE_IMEASURE
| LOCALE_RETURN_NUMBER
,
2619 (LPWSTR
)&system
, sizeof(system
));
2623 /**********************************************
2625 * Cyclically permute the four members of rc
2626 * If sense is TRUE l -> t -> r -> b
2627 * otherwise l <- t <- r <- b
2629 static inline void rotate_rect(RECT
*rc
, BOOL sense
)
2635 rc
->bottom
= rc
->right
;
2636 rc
->right
= rc
->top
;
2644 rc
->top
= rc
->right
;
2645 rc
->right
= rc
->bottom
;
2650 static void pagesetup_set_orientation(pagesetup_data
*data
, WORD orient
)
2652 DEVMODEW
*dm
= GlobalLock(data
->u
.dlgw
->hDevMode
);
2654 assert(orient
== DMORIENT_PORTRAIT
|| orient
== DMORIENT_LANDSCAPE
);
2657 dm
->u1
.s1
.dmOrientation
= orient
;
2660 DEVMODEA
*dmA
= (DEVMODEA
*)dm
;
2661 dmA
->u1
.s1
.dmOrientation
= orient
;
2663 GlobalUnlock(data
->u
.dlgw
->hDevMode
);
2666 static WORD
pagesetup_get_orientation(const pagesetup_data
*data
)
2668 DEVMODEW
*dm
= GlobalLock(data
->u
.dlgw
->hDevMode
);
2672 orient
= dm
->u1
.s1
.dmOrientation
;
2675 DEVMODEA
*dmA
= (DEVMODEA
*)dm
;
2676 orient
= dmA
->u1
.s1
.dmOrientation
;
2678 GlobalUnlock(data
->u
.dlgw
->hDevMode
);
2682 static void pagesetup_set_papersize(pagesetup_data
*data
, WORD paper
)
2684 DEVMODEW
*dm
= GlobalLock(data
->u
.dlgw
->hDevMode
);
2687 dm
->u1
.s1
.dmPaperSize
= paper
;
2690 DEVMODEA
*dmA
= (DEVMODEA
*)dm
;
2691 dmA
->u1
.s1
.dmPaperSize
= paper
;
2693 GlobalUnlock(data
->u
.dlgw
->hDevMode
);
2696 static WORD
pagesetup_get_papersize(const pagesetup_data
*data
)
2698 DEVMODEW
*dm
= GlobalLock(data
->u
.dlgw
->hDevMode
);
2702 paper
= dm
->u1
.s1
.dmPaperSize
;
2705 DEVMODEA
*dmA
= (DEVMODEA
*)dm
;
2706 paper
= dmA
->u1
.s1
.dmPaperSize
;
2708 GlobalUnlock(data
->u
.dlgw
->hDevMode
);
2712 static void pagesetup_set_defaultsource(pagesetup_data
*data
, WORD source
)
2714 DEVMODEW
*dm
= GlobalLock(data
->u
.dlgw
->hDevMode
);
2717 dm
->u1
.s1
.dmDefaultSource
= source
;
2720 DEVMODEA
*dmA
= (DEVMODEA
*)dm
;
2721 dmA
->u1
.s1
.dmDefaultSource
= source
;
2723 GlobalUnlock(data
->u
.dlgw
->hDevMode
);
2728 devnames_driver_name
,
2729 devnames_device_name
,
2730 devnames_output_name
2734 static inline WORD
get_devname_offset(const DEVNAMES
*dn
, devnames_name which
)
2738 case devnames_driver_name
: return dn
->wDriverOffset
;
2739 case devnames_device_name
: return dn
->wDeviceOffset
;
2740 case devnames_output_name
: return dn
->wOutputOffset
;
2742 ERR("Shouldn't be here\n");
2746 static WCHAR
*pagesetup_get_a_devname(const pagesetup_data
*data
, devnames_name which
)
2751 dn
= GlobalLock(data
->u
.dlgw
->hDevNames
);
2753 name
= wcsdup((WCHAR
*)dn
+ get_devname_offset(dn
, which
));
2756 int len
= MultiByteToWideChar(CP_ACP
, 0, (char*)dn
+ get_devname_offset(dn
, which
), -1, NULL
, 0);
2757 name
= malloc(len
* sizeof(WCHAR
));
2758 MultiByteToWideChar(CP_ACP
, 0, (char*)dn
+ get_devname_offset(dn
, which
), -1, name
, len
);
2760 GlobalUnlock(data
->u
.dlgw
->hDevNames
);
2764 static WCHAR
*pagesetup_get_drvname(const pagesetup_data
*data
)
2766 return pagesetup_get_a_devname(data
, devnames_driver_name
);
2769 static WCHAR
*pagesetup_get_devname(const pagesetup_data
*data
)
2771 return pagesetup_get_a_devname(data
, devnames_device_name
);
2774 static WCHAR
*pagesetup_get_portname(const pagesetup_data
*data
)
2776 return pagesetup_get_a_devname(data
, devnames_output_name
);
2779 static void pagesetup_release_a_devname(const pagesetup_data
*data
, WCHAR
*name
)
2784 static void pagesetup_set_devnames(pagesetup_data
*data
, LPCWSTR drv
, LPCWSTR devname
, LPCWSTR port
)
2788 DWORD len
= sizeof(DEVNAMES
), drv_len
, dev_len
, port_len
;
2792 drv_len
= (lstrlenW(drv
) + 1) * sizeof(WCHAR
);
2793 dev_len
= (lstrlenW(devname
) + 1) * sizeof(WCHAR
);
2794 port_len
= (lstrlenW(port
) + 1) * sizeof(WCHAR
);
2798 drv_len
= WideCharToMultiByte(CP_ACP
, 0, drv
, -1, NULL
, 0, NULL
, NULL
);
2799 dev_len
= WideCharToMultiByte(CP_ACP
, 0, devname
, -1, NULL
, 0, NULL
, NULL
);
2800 port_len
= WideCharToMultiByte(CP_ACP
, 0, port
, -1, NULL
, 0, NULL
, NULL
);
2802 len
+= drv_len
+ dev_len
+ port_len
;
2804 if(data
->u
.dlgw
->hDevNames
)
2805 data
->u
.dlgw
->hDevNames
= GlobalReAlloc(data
->u
.dlgw
->hDevNames
, len
, GMEM_MOVEABLE
);
2807 data
->u
.dlgw
->hDevNames
= GlobalAlloc(GMEM_MOVEABLE
, len
);
2809 dn
= GlobalLock(data
->u
.dlgw
->hDevNames
);
2813 WCHAR
*ptr
= (WCHAR
*)(dn
+ 1);
2814 len
= sizeof(DEVNAMES
) / sizeof(WCHAR
);
2815 dn
->wDriverOffset
= len
;
2817 ptr
+= drv_len
/ sizeof(WCHAR
);
2818 len
+= drv_len
/ sizeof(WCHAR
);
2819 dn
->wDeviceOffset
= len
;
2820 lstrcpyW(ptr
, devname
);
2821 ptr
+= dev_len
/ sizeof(WCHAR
);
2822 len
+= dev_len
/ sizeof(WCHAR
);
2823 dn
->wOutputOffset
= len
;
2824 lstrcpyW(ptr
, port
);
2828 char *ptr
= (char *)(dn
+ 1);
2829 len
= sizeof(DEVNAMES
);
2830 dn
->wDriverOffset
= len
;
2831 WideCharToMultiByte(CP_ACP
, 0, drv
, -1, ptr
, drv_len
, NULL
, NULL
);
2834 dn
->wDeviceOffset
= len
;
2835 WideCharToMultiByte(CP_ACP
, 0, devname
, -1, ptr
, dev_len
, NULL
, NULL
);
2838 dn
->wOutputOffset
= len
;
2839 WideCharToMultiByte(CP_ACP
, 0, port
, -1, ptr
, port_len
, NULL
, NULL
);
2843 len
= ARRAY_SIZE(def
);
2844 GetDefaultPrinterW(def
, &len
);
2845 if(!lstrcmpW(def
, devname
))
2848 GlobalUnlock(data
->u
.dlgw
->hDevNames
);
2851 static DEVMODEW
*pagesetup_get_devmode(const pagesetup_data
*data
)
2853 DEVMODEW
*dm
= GlobalLock(data
->u
.dlgw
->hDevMode
);
2858 /* We make a copy even in the unicode case because the ptr
2859 may get passed back to us in pagesetup_set_devmode. */
2860 ret
= malloc(dm
->dmSize
+ dm
->dmDriverExtra
);
2861 memcpy(ret
, dm
, dm
->dmSize
+ dm
->dmDriverExtra
);
2864 ret
= GdiConvertToDevmodeW((DEVMODEA
*)dm
);
2866 GlobalUnlock(data
->u
.dlgw
->hDevMode
);
2870 static void pagesetup_release_devmode(const pagesetup_data
*data
, DEVMODEW
*dm
)
2875 static void pagesetup_set_devmode(pagesetup_data
*data
, DEVMODEW
*dm
)
2877 DEVMODEA
*dmA
= NULL
;
2883 size
= dm
->dmSize
+ dm
->dmDriverExtra
;
2888 dmA
= convert_to_devmodeA(dm
);
2889 size
= dmA
->dmSize
+ dmA
->dmDriverExtra
;
2893 if(data
->u
.dlgw
->hDevMode
)
2894 data
->u
.dlgw
->hDevMode
= GlobalReAlloc(data
->u
.dlgw
->hDevMode
, size
,
2897 data
->u
.dlgw
->hDevMode
= GlobalAlloc(GMEM_MOVEABLE
, size
);
2899 dst
= GlobalLock(data
->u
.dlgw
->hDevMode
);
2900 memcpy(dst
, src
, size
);
2901 GlobalUnlock(data
->u
.dlgw
->hDevMode
);
2905 static inline POINT
*pagesetup_get_papersize_pt(const pagesetup_data
*data
)
2907 return &data
->u
.dlgw
->ptPaperSize
;
2910 static inline RECT
*pagesetup_get_margin_rect(const pagesetup_data
*data
)
2912 return &data
->u
.dlgw
->rtMargin
;
2921 static inline LPPAGESETUPHOOK
pagesetup_get_hook(const pagesetup_data
*data
, hook_type which
)
2925 case page_setup_hook
: return data
->u
.dlgw
->lpfnPageSetupHook
;
2926 case page_paint_hook
: return data
->u
.dlgw
->lpfnPagePaintHook
;
2931 /* This should only be used in calls to hook procs so we return the ptr
2932 already cast to LPARAM */
2933 static inline LPARAM
pagesetup_get_dlg_struct(const pagesetup_data
*data
)
2935 return (LPARAM
)data
->u
.dlgw
;
2938 static inline void swap_point(POINT
*pt
)
2945 static BOOL
pagesetup_update_papersize(pagesetup_data
*data
)
2948 LPWSTR devname
, portname
;
2950 WORD
*words
= NULL
, paperword
;
2951 POINT
*points
= NULL
;
2952 BOOL retval
= FALSE
;
2954 dm
= pagesetup_get_devmode(data
);
2955 devname
= pagesetup_get_devname(data
);
2956 portname
= pagesetup_get_portname(data
);
2958 num
= DeviceCapabilitiesW(devname
, portname
, DC_PAPERS
, NULL
, dm
);
2961 FIXME("No papernames found for %s/%s\n", debugstr_w(devname
), debugstr_w(portname
));
2965 words
= malloc(num
* sizeof(WORD
));
2966 points
= malloc(num
* sizeof(POINT
));
2968 if (num
!= DeviceCapabilitiesW(devname
, portname
, DC_PAPERS
, (LPWSTR
)words
, dm
))
2970 FIXME("Number of returned words is not %d\n", num
);
2974 if (num
!= DeviceCapabilitiesW(devname
, portname
, DC_PAPERSIZE
, (LPWSTR
)points
, dm
))
2976 FIXME("Number of returned sizes is not %d\n", num
);
2980 paperword
= pagesetup_get_papersize(data
);
2982 for (i
= 0; i
< num
; i
++)
2983 if (words
[i
] == paperword
)
2988 FIXME("Papersize %d not found in list?\n", paperword
);
2992 /* this is _10ths_ of a millimeter */
2993 pagesetup_get_papersize_pt(data
)->x
= tenths_mm_to_size(data
, points
[i
].x
);
2994 pagesetup_get_papersize_pt(data
)->y
= tenths_mm_to_size(data
, points
[i
].y
);
2996 if(pagesetup_get_orientation(data
) == DMORIENT_LANDSCAPE
)
2997 swap_point(pagesetup_get_papersize_pt(data
));
3004 pagesetup_release_a_devname(data
, portname
);
3005 pagesetup_release_a_devname(data
, devname
);
3006 pagesetup_release_devmode(data
, dm
);
3011 /**********************************************************************************************
3012 * pagesetup_change_printer
3014 * Redefines hDevMode and hDevNames HANDLES and initialises it.
3017 static BOOL
pagesetup_change_printer(LPWSTR name
, pagesetup_data
*data
)
3021 PRINTER_INFO_2W
*prn_info
= NULL
;
3022 DRIVER_INFO_3W
*drv_info
= NULL
;
3023 DEVMODEW
*dm
= NULL
;
3024 BOOL retval
= FALSE
;
3026 if(!OpenPrinterW(name
, &hprn
, NULL
))
3028 ERR("Can't open printer %s\n", debugstr_w(name
));
3032 GetPrinterW(hprn
, 2, NULL
, 0, &needed
);
3033 prn_info
= malloc(needed
);
3034 GetPrinterW(hprn
, 2, (LPBYTE
)prn_info
, needed
, &needed
);
3035 GetPrinterDriverW(hprn
, NULL
, 3, NULL
, 0, &needed
);
3036 drv_info
= malloc(needed
);
3037 if(!GetPrinterDriverW(hprn
, NULL
, 3, (LPBYTE
)drv_info
, needed
, &needed
))
3039 ERR("GetPrinterDriverA failed for %s, fix your config!\n", debugstr_w(prn_info
->pPrinterName
));
3044 needed
= DocumentPropertiesW(0, 0, name
, NULL
, NULL
, 0);
3047 ERR("DocumentProperties fails on %s\n", debugstr_w(name
));
3051 dm
= malloc(needed
);
3052 DocumentPropertiesW(0, 0, name
, dm
, NULL
, DM_OUT_BUFFER
);
3054 pagesetup_set_devmode(data
, dm
);
3055 pagesetup_set_devnames(data
, drv_info
->pDriverPath
, prn_info
->pPrinterName
,
3056 prn_info
->pPortName
);
3066 /****************************************************************************************
3067 * pagesetup_init_combos
3069 * Fills Printers, Paper and Source combos
3072 static void pagesetup_init_combos(HWND hDlg
, pagesetup_data
*data
)
3075 LPWSTR devname
, portname
;
3077 dm
= pagesetup_get_devmode(data
);
3078 devname
= pagesetup_get_devname(data
);
3079 portname
= pagesetup_get_portname(data
);
3081 PRINTDLG_SetUpPrinterListComboW(hDlg
, cmb1
, devname
);
3082 PRINTDLG_SetUpPaperComboBoxW(hDlg
, cmb2
, devname
, portname
, dm
);
3083 PRINTDLG_SetUpPaperComboBoxW(hDlg
, cmb3
, devname
, portname
, dm
);
3085 pagesetup_release_a_devname(data
, portname
);
3086 pagesetup_release_a_devname(data
, devname
);
3087 pagesetup_release_devmode(data
, dm
);
3091 /****************************************************************************************
3092 * pagesetup_change_printer_dialog
3094 * Pops up another dialog that lets the user pick another printer.
3096 * For now we display the PrintDlg, this should display a striped down version of it.
3098 static void pagesetup_change_printer_dialog(HWND hDlg
, pagesetup_data
*data
)
3101 LPWSTR drvname
, devname
, portname
;
3102 DEVMODEW
*tmp_dm
, *dm
;
3104 memset(&prnt
, 0, sizeof(prnt
));
3105 prnt
.lStructSize
= sizeof(prnt
);
3107 prnt
.hwndOwner
= hDlg
;
3109 drvname
= pagesetup_get_drvname(data
);
3110 devname
= pagesetup_get_devname(data
);
3111 portname
= pagesetup_get_portname(data
);
3113 PRINTDLG_CreateDevNamesW(&prnt
.hDevNames
, drvname
, devname
, portname
);
3114 pagesetup_release_a_devname(data
, portname
);
3115 pagesetup_release_a_devname(data
, devname
);
3116 pagesetup_release_a_devname(data
, drvname
);
3118 tmp_dm
= pagesetup_get_devmode(data
);
3119 prnt
.hDevMode
= GlobalAlloc(GMEM_MOVEABLE
, tmp_dm
->dmSize
+ tmp_dm
->dmDriverExtra
);
3120 dm
= GlobalLock(prnt
.hDevMode
);
3121 memcpy(dm
, tmp_dm
, tmp_dm
->dmSize
+ tmp_dm
->dmDriverExtra
);
3122 GlobalUnlock(prnt
.hDevMode
);
3123 pagesetup_release_devmode(data
, tmp_dm
);
3125 if (PrintDlgW(&prnt
))
3127 DEVMODEW
*dm
= GlobalLock(prnt
.hDevMode
);
3128 DEVNAMES
*dn
= GlobalLock(prnt
.hDevNames
);
3130 pagesetup_set_devnames(data
, (WCHAR
*)dn
+ dn
->wDriverOffset
,
3131 (WCHAR
*)dn
+ dn
->wDeviceOffset
, (WCHAR
*)dn
+ dn
->wOutputOffset
);
3132 pagesetup_set_devmode(data
, dm
);
3133 GlobalUnlock(prnt
.hDevNames
);
3134 GlobalUnlock(prnt
.hDevMode
);
3135 pagesetup_init_combos(hDlg
, data
);
3138 GlobalFree(prnt
.hDevMode
);
3139 GlobalFree(prnt
.hDevNames
);
3143 /******************************************************************************************
3144 * pagesetup_change_preview
3146 * Changes paper preview size / position
3149 static void pagesetup_change_preview(const pagesetup_data
*data
)
3151 LONG width
, height
, x
, y
;
3153 const int shadow
= 4;
3155 if(pagesetup_get_orientation(data
) == DMORIENT_LANDSCAPE
)
3157 width
= data
->rtDrawRect
.right
- data
->rtDrawRect
.left
;
3158 height
= pagesetup_get_papersize_pt(data
)->y
* width
/ pagesetup_get_papersize_pt(data
)->x
;
3162 height
= data
->rtDrawRect
.bottom
- data
->rtDrawRect
.top
;
3163 width
= pagesetup_get_papersize_pt(data
)->x
* height
/ pagesetup_get_papersize_pt(data
)->y
;
3165 x
= (data
->rtDrawRect
.right
+ data
->rtDrawRect
.left
- width
) / 2;
3166 y
= (data
->rtDrawRect
.bottom
+ data
->rtDrawRect
.top
- height
) / 2;
3167 TRACE("draw rect %s x=%ld, y=%ld, w=%ld, h=%ld\n",
3168 wine_dbgstr_rect(&data
->rtDrawRect
), x
, y
, width
, height
);
3170 MoveWindow(GetDlgItem(data
->hDlg
, rct2
), x
+ width
, y
+ shadow
, shadow
, height
, FALSE
);
3171 MoveWindow(GetDlgItem(data
->hDlg
, rct3
), x
+ shadow
, y
+ height
, width
, shadow
, FALSE
);
3172 MoveWindow(GetDlgItem(data
->hDlg
, rct1
), x
, y
, width
, height
, FALSE
);
3174 tmp
= data
->rtDrawRect
;
3175 tmp
.right
+= shadow
;
3176 tmp
.bottom
+= shadow
;
3177 InvalidateRect(data
->hDlg
, &tmp
, TRUE
);
3180 static inline LONG
*element_from_margin_id(RECT
*rc
, WORD id
)
3184 case edt4
: return &rc
->left
;
3185 case edt5
: return &rc
->top
;
3186 case edt6
: return &rc
->right
;
3187 case edt7
: return &rc
->bottom
;
3192 static void update_margin_edits(HWND hDlg
, const pagesetup_data
*data
, WORD id
)
3197 for(idx
= edt4
; idx
<= edt7
; idx
++)
3199 if(id
== 0 || id
== idx
)
3201 size2str(data
, *element_from_margin_id(pagesetup_get_margin_rect(data
), idx
), str
);
3202 SetDlgItemTextW(hDlg
, idx
, str
);
3207 static void margin_edit_notification(HWND hDlg
, const pagesetup_data
*data
, WORD msg
, WORD id
)
3215 LONG
*value
= element_from_margin_id(pagesetup_get_margin_rect(data
), id
);
3217 if (GetDlgItemTextW(hDlg
, id
, buf
, ARRAY_SIZE(buf
)) != 0)
3220 WCHAR decimal
= get_decimal_sep();
3222 val
= wcstol(buf
, &end
, 10);
3223 if(end
!= buf
|| *end
== decimal
)
3225 int mult
= is_metric(data
) ? 100 : 1000;
3234 val
+= (*end
- '0') * mult
;
3246 update_margin_edits(hDlg
, data
, id
);
3251 static void set_margin_groupbox_title(HWND hDlg
, const pagesetup_data
*data
)
3255 if(LoadStringW(COMDLG32_hInstance
, is_metric(data
) ? PD32_MARGINS_IN_MILLIMETERS
: PD32_MARGINS_IN_INCHES
,
3256 title
, ARRAY_SIZE(title
)))
3257 SetDlgItemTextW(hDlg
, grp4
, title
);
3260 static void pagesetup_update_orientation_buttons(HWND hDlg
, const pagesetup_data
*data
)
3262 if (pagesetup_get_orientation(data
) == DMORIENT_LANDSCAPE
)
3263 CheckRadioButton(hDlg
, rad1
, rad2
, rad2
);
3265 CheckRadioButton(hDlg
, rad1
, rad2
, rad1
);
3268 /****************************************************************************************
3269 * pagesetup_printer_properties
3271 * Handle invocation of the 'Properties' button (not present in the default template).
3273 static void pagesetup_printer_properties(HWND hDlg
, pagesetup_data
*data
)
3281 devname
= pagesetup_get_devname(data
);
3283 if (!OpenPrinterW(devname
, &hprn
, NULL
))
3285 FIXME("Call to OpenPrinter did not succeed!\n");
3286 pagesetup_release_a_devname(data
, devname
);
3290 dm
= pagesetup_get_devmode(data
);
3291 DocumentPropertiesW(hDlg
, hprn
, devname
, dm
, dm
, DM_IN_BUFFER
| DM_OUT_BUFFER
| DM_IN_PROMPT
);
3292 pagesetup_set_devmode(data
, dm
);
3293 pagesetup_release_devmode(data
, dm
);
3294 pagesetup_release_a_devname(data
, devname
);
3297 /* Changing paper */
3298 pagesetup_update_papersize(data
);
3299 pagesetup_update_orientation_buttons(hDlg
, data
);
3301 /* Changing paper preview */
3302 pagesetup_change_preview(data
);
3304 /* Selecting paper in combo */
3305 count
= SendDlgItemMessageW(hDlg
, cmb2
, CB_GETCOUNT
, 0, 0);
3308 WORD paperword
= pagesetup_get_papersize(data
);
3309 for(i
= 0; i
< count
; i
++)
3311 if(SendDlgItemMessageW(hDlg
, cmb2
, CB_GETITEMDATA
, i
, 0) == paperword
) {
3312 SendDlgItemMessageW(hDlg
, cmb2
, CB_SETCURSEL
, i
, 0);
3319 /********************************************************************************
3320 * pagesetup_wm_command
3321 * process WM_COMMAND message for PageSetupDlg
3324 * hDlg [in] Main dialog HANDLE
3325 * wParam [in] WM_COMMAND wParam
3326 * lParam [in] WM_COMMAND lParam
3327 * pda [in/out] ptr to PageSetupDataA
3330 static BOOL
pagesetup_wm_command(HWND hDlg
, WPARAM wParam
, LPARAM lParam
, pagesetup_data
*data
)
3332 WORD msg
= HIWORD(wParam
);
3333 WORD id
= LOWORD(wParam
);
3335 TRACE("loword (lparam) %d, wparam 0x%Ix, lparam %08Ix\n",
3336 LOWORD(lParam
),wParam
,lParam
);
3339 EndDialog(hDlg
, TRUE
);
3343 EndDialog(hDlg
, FALSE
);
3346 case psh3
: /* Printer... */
3347 pagesetup_change_printer_dialog(hDlg
, data
);
3350 case rad1
: /* Portrait */
3351 case rad2
: /* Landscape */
3352 if((id
== rad1
&& pagesetup_get_orientation(data
) == DMORIENT_LANDSCAPE
) ||
3353 (id
== rad2
&& pagesetup_get_orientation(data
) == DMORIENT_PORTRAIT
))
3355 pagesetup_set_orientation(data
, (id
== rad1
) ? DMORIENT_PORTRAIT
: DMORIENT_LANDSCAPE
);
3356 pagesetup_update_papersize(data
);
3357 rotate_rect(pagesetup_get_margin_rect(data
), (id
== rad2
));
3358 update_margin_edits(hDlg
, data
, 0);
3359 pagesetup_change_preview(data
);
3362 case cmb1
: /* Printer combo */
3363 if(msg
== CBN_SELCHANGE
)
3366 INT index
= SendDlgItemMessageW(hDlg
, id
, CB_GETCURSEL
, 0, 0);
3367 INT length
= SendDlgItemMessageW(hDlg
, id
, CB_GETLBTEXTLEN
, index
, 0);
3368 name
= malloc(sizeof(WCHAR
) * (length
+ 1));
3369 SendDlgItemMessageW(hDlg
, id
, CB_GETLBTEXT
, index
, (LPARAM
)name
);
3370 pagesetup_change_printer(name
, data
);
3371 pagesetup_init_combos(hDlg
, data
);
3375 case cmb2
: /* Paper combo */
3376 if(msg
== CBN_SELCHANGE
)
3378 DWORD paperword
= SendDlgItemMessageW(hDlg
, cmb2
, CB_GETITEMDATA
,
3379 SendDlgItemMessageW(hDlg
, cmb2
, CB_GETCURSEL
, 0, 0), 0);
3380 if (paperword
!= CB_ERR
)
3382 pagesetup_set_papersize(data
, paperword
);
3383 pagesetup_update_papersize(data
);
3384 pagesetup_change_preview(data
);
3386 FIXME("could not get dialog text for papersize cmbbox?\n");
3389 case cmb3
: /* Paper Source */
3390 if(msg
== CBN_SELCHANGE
)
3392 WORD source
= SendDlgItemMessageW(hDlg
, cmb3
, CB_GETITEMDATA
,
3393 SendDlgItemMessageW(hDlg
, cmb3
, CB_GETCURSEL
, 0, 0), 0);
3394 pagesetup_set_defaultsource(data
, source
);
3397 case psh2
: /* Printer Properties button */
3398 pagesetup_printer_properties(hDlg
, data
);
3404 margin_edit_notification(hDlg
, data
, msg
, id
);
3407 InvalidateRect(GetDlgItem(hDlg
, rct1
), NULL
, TRUE
);
3411 /***********************************************************************
3412 * default_page_paint_hook
3413 * Default hook paint procedure that receives WM_PSD_* messages from the dialog box
3414 * whenever the sample page is redrawn.
3416 static UINT_PTR
default_page_paint_hook(HWND hwndDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
,
3417 const pagesetup_data
*data
)
3419 LPRECT lprc
= (LPRECT
) lParam
;
3420 HDC hdc
= (HDC
) wParam
;
3423 HFONT hfont
, holdfont
;
3425 TRACE("uMsg: WM_USER+%d\n",uMsg
-WM_USER
);
3426 /* Call user paint hook if enable */
3427 if (pagesetup_get_flags(data
) & PSD_ENABLEPAGEPAINTHOOK
)
3428 if (pagesetup_get_hook(data
, page_paint_hook
)(hwndDlg
, uMsg
, wParam
, lParam
))
3432 /* LPPAGESETUPDLG in lParam */
3433 case WM_PSD_PAGESETUPDLG
:
3434 /* Inform about the sample page rectangle */
3435 case WM_PSD_FULLPAGERECT
:
3436 /* Inform about the margin rectangle */
3437 case WM_PSD_MINMARGINRECT
:
3440 /* Draw dashed rectangle showing margins */
3441 case WM_PSD_MARGINRECT
:
3442 hpen
= CreatePen(PS_DASH
, 1, GetSysColor(COLOR_3DSHADOW
));
3443 holdpen
= SelectObject(hdc
, hpen
);
3444 Rectangle(hdc
, lprc
->left
, lprc
->top
, lprc
->right
, lprc
->bottom
);
3445 DeleteObject(SelectObject(hdc
, holdpen
));
3447 /* Draw the fake document */
3448 case WM_PSD_GREEKTEXTRECT
:
3449 /* select a nice scalable font, because we want the text really small */
3450 SystemParametersInfoW(SPI_GETICONTITLELOGFONT
, sizeof(lf
), &lf
, 0);
3451 lf
.lfHeight
= 6; /* value chosen based on visual effect */
3452 hfont
= CreateFontIndirectW(&lf
);
3453 holdfont
= SelectObject(hdc
, hfont
);
3455 /* if text not loaded, then do so now */
3456 if (wszFakeDocumentText
[0] == '\0')
3457 LoadStringW(COMDLG32_hInstance
,
3459 wszFakeDocumentText
,
3460 ARRAY_SIZE(wszFakeDocumentText
));
3462 oldbkmode
= SetBkMode(hdc
, TRANSPARENT
);
3463 DrawTextW(hdc
, wszFakeDocumentText
, -1, lprc
, DT_TOP
|DT_LEFT
|DT_NOPREFIX
|DT_WORDBREAK
);
3464 SetBkMode(hdc
, oldbkmode
);
3466 DeleteObject(SelectObject(hdc
, holdfont
));
3469 /* Envelope stamp */
3470 case WM_PSD_ENVSTAMPRECT
:
3471 /* Return address */
3472 case WM_PSD_YAFULLPAGERECT
:
3473 FIXME("envelope/stamp is not implemented\n");
3476 FIXME("Unknown message %x\n",uMsg
);
3482 /***********************************************************************
3484 * The main paint procedure for the PageSetupDlg function.
3485 * The Page Setup dialog box includes an image of a sample page that shows how
3486 * the user's selections affect the appearance of the printed output.
3487 * The image consists of a rectangle that represents the selected paper
3488 * or envelope type, with a dotted-line rectangle representing
3489 * the current margins, and partial (Greek text) characters
3490 * to show how text looks on the printed page.
3492 * The following messages in the order sends to user hook procedure:
3493 * WM_PSD_PAGESETUPDLG Draw the contents of the sample page
3494 * WM_PSD_FULLPAGERECT Inform about the bounding rectangle
3495 * WM_PSD_MINMARGINRECT Inform about the margin rectangle (min margin?)
3496 * WM_PSD_MARGINRECT Draw the margin rectangle
3497 * WM_PSD_GREEKTEXTRECT Draw the Greek text inside the margin rectangle
3498 * If any of first three messages returns TRUE, painting done.
3501 * hWnd [in] Handle to the Page Setup dialog box
3502 * uMsg [in] Received message
3505 * WM_PSD_ENVSTAMPRECT Draw in the envelope-stamp rectangle (for envelopes only)
3506 * WM_PSD_YAFULLPAGERECT Draw the return address portion (for envelopes and other paper sizes)
3509 * FALSE if all done correctly
3514 static LRESULT CALLBACK
3515 PRINTDLG_PagePaintProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
3518 RECT rcClient
, rcMargin
;
3521 HBRUSH hbrush
, holdbrush
;
3522 pagesetup_data
*data
;
3523 int papersize
=0, orientation
=0; /* FIXME: set these values for the user paint hook */
3524 double scalx
, scaly
;
3526 if (uMsg
!= WM_PAINT
)
3527 return CallWindowProcA(lpfnStaticWndProc
, hWnd
, uMsg
, wParam
, lParam
);
3529 /* Processing WM_PAINT message */
3530 data
= GetPropW(hWnd
, pagesetupdlg_prop
);
3532 WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
3535 if (default_page_paint_hook(hWnd
, WM_PSD_PAGESETUPDLG
, MAKELONG(papersize
, orientation
),
3536 pagesetup_get_dlg_struct(data
), data
))
3539 hdc
= BeginPaint(hWnd
, &ps
);
3540 GetClientRect(hWnd
, &rcClient
);
3542 scalx
= rcClient
.right
/ (double)pagesetup_get_papersize_pt(data
)->x
;
3543 scaly
= rcClient
.bottom
/ (double)pagesetup_get_papersize_pt(data
)->y
;
3544 rcMargin
= rcClient
;
3546 rcMargin
.left
+= pagesetup_get_margin_rect(data
)->left
* scalx
;
3547 rcMargin
.top
+= pagesetup_get_margin_rect(data
)->top
* scaly
;
3548 rcMargin
.right
-= pagesetup_get_margin_rect(data
)->right
* scalx
;
3549 rcMargin
.bottom
-= pagesetup_get_margin_rect(data
)->bottom
* scaly
;
3551 /* if the space is too small then we make sure to not draw anything */
3552 rcMargin
.left
= min(rcMargin
.left
, rcMargin
.right
);
3553 rcMargin
.top
= min(rcMargin
.top
, rcMargin
.bottom
);
3555 if (!default_page_paint_hook(hWnd
, WM_PSD_FULLPAGERECT
, (WPARAM
)hdc
, (LPARAM
)&rcClient
, data
) &&
3556 !default_page_paint_hook(hWnd
, WM_PSD_MINMARGINRECT
, (WPARAM
)hdc
, (LPARAM
)&rcMargin
, data
) )
3558 /* fill background */
3559 hbrush
= GetSysColorBrush(COLOR_3DHIGHLIGHT
);
3560 FillRect(hdc
, &rcClient
, hbrush
);
3561 holdbrush
= SelectObject(hdc
, hbrush
);
3563 hpen
= CreatePen(PS_SOLID
, 1, GetSysColor(COLOR_3DSHADOW
));
3564 holdpen
= SelectObject(hdc
, hpen
);
3566 /* paint left edge */
3567 MoveToEx(hdc
, rcClient
.left
, rcClient
.top
, NULL
);
3568 LineTo(hdc
, rcClient
.left
, rcClient
.bottom
-1);
3570 /* paint top edge */
3571 MoveToEx(hdc
, rcClient
.left
, rcClient
.top
, NULL
);
3572 LineTo(hdc
, rcClient
.right
, rcClient
.top
);
3574 hpen
= CreatePen(PS_SOLID
, 1, GetSysColor(COLOR_3DDKSHADOW
));
3575 DeleteObject(SelectObject(hdc
, hpen
));
3577 /* paint right edge */
3578 MoveToEx(hdc
, rcClient
.right
-1, rcClient
.top
, NULL
);
3579 LineTo(hdc
, rcClient
.right
-1, rcClient
.bottom
);
3581 /* paint bottom edge */
3582 MoveToEx(hdc
, rcClient
.left
, rcClient
.bottom
-1, NULL
);
3583 LineTo(hdc
, rcClient
.right
, rcClient
.bottom
-1);
3585 DeleteObject(SelectObject(hdc
, holdpen
));
3586 DeleteObject(SelectObject(hdc
, holdbrush
));
3588 default_page_paint_hook(hWnd
, WM_PSD_MARGINRECT
, (WPARAM
)hdc
, (LPARAM
)&rcMargin
, data
);
3590 /* give text a bit of a space from the frame */
3591 InflateRect(&rcMargin
, -2, -2);
3593 /* if the space is too small then we make sure to not draw anything */
3594 rcMargin
.left
= min(rcMargin
.left
, rcMargin
.right
);
3595 rcMargin
.top
= min(rcMargin
.top
, rcMargin
.bottom
);
3597 default_page_paint_hook(hWnd
, WM_PSD_GREEKTEXTRECT
, (WPARAM
)hdc
, (LPARAM
)&rcMargin
, data
);
3600 EndPaint(hWnd
, &ps
);
3604 /*******************************************************
3605 * The margin edit controls are subclassed to filter
3606 * anything other than numbers and the decimal separator.
3608 static LRESULT CALLBACK
pagesetup_margin_editproc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
3612 WCHAR decimal
= get_decimal_sep();
3613 WCHAR wc
= (WCHAR
)wparam
;
3614 if(!iswdigit(wc
) && wc
!= decimal
&& wc
!= VK_BACK
) return 0;
3616 return CallWindowProcW(edit_wndproc
, hwnd
, msg
, wparam
, lparam
);
3619 static void subclass_margin_edits(HWND hDlg
)
3624 for(id
= edt4
; id
<= edt7
; id
++)
3626 old_proc
= (WNDPROC
)SetWindowLongPtrW(GetDlgItem(hDlg
, id
),
3628 (ULONG_PTR
)pagesetup_margin_editproc
);
3629 InterlockedCompareExchangePointer((void**)&edit_wndproc
, old_proc
, NULL
);
3633 /***********************************************************************
3634 * pagesetup_dlg_proc
3636 * Message handler for PageSetupDlg
3638 static INT_PTR CALLBACK
pagesetup_dlg_proc(HWND hDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
3640 pagesetup_data
*data
;
3641 INT_PTR res
= FALSE
;
3644 if (uMsg
== WM_INITDIALOG
) { /*Init dialog*/
3645 data
= (pagesetup_data
*)lParam
;
3648 hDrawWnd
= GetDlgItem(hDlg
, rct1
);
3649 TRACE("set property to %p\n", data
);
3650 SetPropW(hDlg
, pagesetupdlg_prop
, data
);
3651 SetPropW(hDrawWnd
, pagesetupdlg_prop
, data
);
3652 GetWindowRect(hDrawWnd
, &data
->rtDrawRect
); /* Calculating rect in client coordinates where paper draws */
3653 MapWindowPoints( 0, hDlg
, (LPPOINT
)&data
->rtDrawRect
, 2 );
3654 lpfnStaticWndProc
= (WNDPROC
)SetWindowLongPtrW(
3657 (ULONG_PTR
)PRINTDLG_PagePaintProc
);
3659 /* FIXME: Paint hook. Must it be at begin of initialization or at end? */
3661 if (pagesetup_get_flags(data
) & PSD_ENABLEPAGESETUPHOOK
)
3663 if (!pagesetup_get_hook(data
, page_setup_hook
)(hDlg
, uMsg
, wParam
,
3664 pagesetup_get_dlg_struct(data
)))
3665 FIXME("Setup page hook failed?\n");
3668 /* if printer button disabled */
3669 if (pagesetup_get_flags(data
) & PSD_DISABLEPRINTER
)
3670 EnableWindow(GetDlgItem(hDlg
, psh3
), FALSE
);
3671 /* if margin edit boxes disabled */
3672 if (pagesetup_get_flags(data
) & PSD_DISABLEMARGINS
)
3674 EnableWindow(GetDlgItem(hDlg
, edt4
), FALSE
);
3675 EnableWindow(GetDlgItem(hDlg
, edt5
), FALSE
);
3676 EnableWindow(GetDlgItem(hDlg
, edt6
), FALSE
);
3677 EnableWindow(GetDlgItem(hDlg
, edt7
), FALSE
);
3680 /* Set orientation radiobuttons properly */
3681 pagesetup_update_orientation_buttons(hDlg
, data
);
3683 /* if orientation disabled */
3684 if (pagesetup_get_flags(data
) & PSD_DISABLEORIENTATION
)
3686 EnableWindow(GetDlgItem(hDlg
,rad1
),FALSE
);
3687 EnableWindow(GetDlgItem(hDlg
,rad2
),FALSE
);
3690 /* We fill them out enabled or not */
3691 if (!(pagesetup_get_flags(data
) & PSD_MARGINS
))
3693 /* default is 1 inch */
3694 LONG size
= thousandths_inch_to_size(data
, 1000);
3695 SetRect(pagesetup_get_margin_rect(data
), size
, size
, size
, size
);
3697 update_margin_edits(hDlg
, data
, 0);
3698 subclass_margin_edits(hDlg
);
3699 set_margin_groupbox_title(hDlg
, data
);
3701 /* if paper disabled */
3702 if (pagesetup_get_flags(data
) & PSD_DISABLEPAPER
)
3704 EnableWindow(GetDlgItem(hDlg
,cmb2
),FALSE
);
3705 EnableWindow(GetDlgItem(hDlg
,cmb3
),FALSE
);
3708 /* filling combos: printer, paper, source. selecting current printer (from DEVMODEA) */
3709 pagesetup_init_combos(hDlg
, data
);
3710 pagesetup_update_papersize(data
);
3711 pagesetup_set_defaultsource(data
, DMBIN_FORMSOURCE
); /* FIXME: This is the auto select bin. Is this correct? */
3713 /* Drawing paper prev */
3714 pagesetup_change_preview(data
);
3717 data
= GetPropW(hDlg
, pagesetupdlg_prop
);
3720 WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
3723 if (pagesetup_get_flags(data
) & PSD_ENABLEPAGESETUPHOOK
)
3725 res
= pagesetup_get_hook(data
, page_setup_hook
)(hDlg
, uMsg
, wParam
, lParam
);
3726 if (res
) return res
;
3731 return pagesetup_wm_command(hDlg
, wParam
, lParam
, data
);
3736 static WCHAR
*get_default_printer(void)
3741 GetDefaultPrinterW(NULL
, &len
);
3744 name
= malloc(len
* sizeof(WCHAR
));
3745 GetDefaultPrinterW(name
, &len
);
3750 static void pagesetup_dump_dlg_struct(const pagesetup_data
*data
)
3752 if(TRACE_ON(commdlg
))
3754 char flagstr
[1000] = "";
3755 const struct pd_flags
*pflag
= psd_flags
;
3756 for( ; pflag
->name
; pflag
++)
3758 if(pagesetup_get_flags(data
) & pflag
->flag
)
3760 strcat(flagstr
, pflag
->name
);
3761 strcat(flagstr
, "|");
3764 TRACE("%s: (%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
3765 "hinst %p, flags %08lx (%s)\n",
3766 data
->unicode
? "unicode" : "ansi",
3767 data
->u
.dlgw
, data
->u
.dlgw
->hwndOwner
, data
->u
.dlgw
->hDevMode
,
3768 data
->u
.dlgw
->hDevNames
, data
->u
.dlgw
->hInstance
,
3769 pagesetup_get_flags(data
), flagstr
);
3773 static void *pagesetup_get_template(pagesetup_data
*data
)
3776 HGLOBAL tmpl_handle
;
3778 if(pagesetup_get_flags(data
) & PSD_ENABLEPAGESETUPTEMPLATEHANDLE
)
3780 tmpl_handle
= data
->u
.dlgw
->hPageSetupTemplate
;
3782 else if(pagesetup_get_flags(data
) & PSD_ENABLEPAGESETUPTEMPLATE
)
3785 res
= FindResourceW(data
->u
.dlgw
->hInstance
,
3786 data
->u
.dlgw
->lpPageSetupTemplateName
, (LPWSTR
)RT_DIALOG
);
3788 res
= FindResourceA(data
->u
.dlga
->hInstance
,
3789 data
->u
.dlga
->lpPageSetupTemplateName
, (LPSTR
)RT_DIALOG
);
3790 tmpl_handle
= LoadResource(data
->u
.dlgw
->hInstance
, res
);
3794 res
= FindResourceW(COMDLG32_hInstance
, MAKEINTRESOURCEW(PAGESETUPDLGORD
),
3796 tmpl_handle
= LoadResource(COMDLG32_hInstance
, res
);
3798 return LockResource(tmpl_handle
);
3801 static BOOL
pagesetup_common(pagesetup_data
*data
)
3806 if(!pagesetup_get_dlg_struct(data
))
3808 COMDLG32_SetCommDlgExtendedError(CDERR_INITIALIZATION
);
3812 pagesetup_dump_dlg_struct(data
);
3814 if(data
->u
.dlgw
->lStructSize
!= sizeof(PAGESETUPDLGW
))
3816 COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE
);
3820 if ((pagesetup_get_flags(data
) & PSD_ENABLEPAGEPAINTHOOK
) &&
3821 (pagesetup_get_hook(data
, page_paint_hook
) == NULL
))
3823 COMDLG32_SetCommDlgExtendedError(CDERR_NOHOOK
);
3827 if(!(pagesetup_get_flags(data
) & (PSD_INTHOUSANDTHSOFINCHES
| PSD_INHUNDREDTHSOFMILLIMETERS
)))
3828 data
->u
.dlgw
->Flags
|= is_default_metric() ?
3829 PSD_INHUNDREDTHSOFMILLIMETERS
: PSD_INTHOUSANDTHSOFINCHES
;
3831 if (!data
->u
.dlgw
->hDevMode
|| !data
->u
.dlgw
->hDevNames
)
3833 WCHAR
*def
= get_default_printer();
3836 if (!(pagesetup_get_flags(data
) & PSD_NOWARNING
))
3839 LoadStringW(COMDLG32_hInstance
, PD32_NO_DEFAULT_PRINTER
, errstr
, 255);
3840 MessageBoxW(data
->u
.dlgw
->hwndOwner
, errstr
, 0, MB_OK
| MB_ICONERROR
);
3842 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN
);
3845 pagesetup_change_printer(def
, data
);
3849 if (pagesetup_get_flags(data
) & PSD_RETURNDEFAULT
)
3851 pagesetup_update_papersize(data
);
3855 tmpl
= pagesetup_get_template(data
);
3857 ret
= DialogBoxIndirectParamW(data
->u
.dlgw
->hInstance
, tmpl
,
3858 data
->u
.dlgw
->hwndOwner
,
3859 pagesetup_dlg_proc
, (LPARAM
)data
) > 0;
3863 /***********************************************************************
3864 * PageSetupDlgA (COMDLG32.@)
3866 * Displays the PAGE SETUP dialog box, which enables the user to specify
3867 * specific properties of a printed page such as
3868 * size, source, orientation and the width of the page margins.
3871 * setupdlg [IO] PAGESETUPDLGA struct
3874 * TRUE if the user pressed the OK button
3875 * FALSE if the user cancelled the window or an error occurred
3878 * The values of hDevMode and hDevNames are filled on output and can be
3879 * changed in PAGESETUPDLG when they are passed in PageSetupDlg.
3882 BOOL WINAPI
PageSetupDlgA(LPPAGESETUPDLGA setupdlg
)
3884 pagesetup_data data
;
3886 data
.unicode
= FALSE
;
3887 data
.u
.dlga
= setupdlg
;
3889 return pagesetup_common(&data
);
3892 /***********************************************************************
3893 * PageSetupDlgW (COMDLG32.@)
3895 * See PageSetupDlgA.
3897 BOOL WINAPI
PageSetupDlgW(LPPAGESETUPDLGW setupdlg
)
3899 pagesetup_data data
;
3901 data
.unicode
= TRUE
;
3902 data
.u
.dlgw
= setupdlg
;
3904 return pagesetup_common(&data
);
3907 static void pdlgex_to_pdlg(const PRINTDLGEXW
*pdlgex
, PRINTDLGW
*pdlg
)
3909 pdlg
->lStructSize
= sizeof(*pdlg
);
3910 pdlg
->hwndOwner
= pdlgex
->hwndOwner
;
3911 pdlg
->hDevMode
= pdlgex
->hDevMode
;
3912 pdlg
->hDevNames
= pdlgex
->hDevNames
;
3913 pdlg
->hDC
= pdlgex
->hDC
;
3914 pdlg
->Flags
= pdlgex
->Flags
;
3915 if ((pdlgex
->Flags
& PD_NOPAGENUMS
) || !pdlgex
->nPageRanges
|| !pdlgex
->lpPageRanges
)
3917 pdlg
->nFromPage
= 0;
3918 pdlg
->nToPage
= 65534;
3922 pdlg
->nFromPage
= pdlgex
->lpPageRanges
[0].nFromPage
;
3923 pdlg
->nToPage
= pdlgex
->lpPageRanges
[0].nToPage
;
3925 pdlg
->nMinPage
= pdlgex
->nMinPage
;
3926 pdlg
->nMaxPage
= pdlgex
->nMaxPage
;
3927 pdlg
->nCopies
= pdlgex
->nCopies
;
3928 pdlg
->hInstance
= pdlgex
->hInstance
;
3929 pdlg
->lCustData
= 0;
3930 pdlg
->lpfnPrintHook
= NULL
;
3931 pdlg
->lpfnSetupHook
= NULL
;
3932 pdlg
->lpPrintTemplateName
= pdlgex
->lpPrintTemplateName
;
3933 pdlg
->lpSetupTemplateName
= NULL
;
3934 pdlg
->hPrintTemplate
= NULL
;
3935 pdlg
->hSetupTemplate
= NULL
;
3938 /* Only copy fields that are supposed to be changed. */
3939 static void pdlg_to_pdlgex(const PRINTDLGW
*pdlg
, PRINTDLGEXW
*pdlgex
)
3941 pdlgex
->hDevMode
= pdlg
->hDevMode
;
3942 pdlgex
->hDevNames
= pdlg
->hDevNames
;
3943 pdlgex
->hDC
= pdlg
->hDC
;
3944 if (!(pdlgex
->Flags
& PD_NOPAGENUMS
) && pdlgex
->nPageRanges
&& pdlgex
->lpPageRanges
)
3946 pdlgex
->lpPageRanges
[0].nFromPage
= pdlg
->nFromPage
;
3947 pdlgex
->lpPageRanges
[0].nToPage
= pdlg
->nToPage
;
3949 pdlgex
->nMinPage
= pdlg
->nMinPage
;
3950 pdlgex
->nMaxPage
= pdlg
->nMaxPage
;
3951 pdlgex
->nCopies
= pdlg
->nCopies
;
3954 struct callback_data
3956 IPrintDialogCallback
*callback
;
3957 IObjectWithSite
*object
;
3960 static UINT_PTR CALLBACK
pdlgex_hook_proc(HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
3962 if (msg
== WM_INITDIALOG
)
3964 PRINTDLGW
*pd
= (PRINTDLGW
*)lp
;
3965 struct callback_data
*cb
= (struct callback_data
*)pd
->lCustData
;
3969 cb
->callback
->lpVtbl
->SelectionChange(cb
->callback
);
3970 cb
->callback
->lpVtbl
->InitDone(cb
->callback
);
3975 /* FIXME: store interface pointer somewhere in window properties and call it
3977 cb->callback->lpVtbl->HandleMessage(cb->callback, hwnd, msg, wp, lp, &hres);
3984 /***********************************************************************
3985 * PrintDlgExA (COMDLG32.@)
3993 HRESULT WINAPI
PrintDlgExA(LPPRINTDLGEXA lppd
)
3995 PRINTER_INFO_2A
*pbuf
;
3996 DRIVER_INFO_3A
*dbuf
;
4001 if ((lppd
== NULL
) || (lppd
->lStructSize
!= sizeof(PRINTDLGEXA
)))
4002 return E_INVALIDARG
;
4004 if (!IsWindow(lppd
->hwndOwner
))
4007 if (lppd
->nStartPage
!= START_PAGE_GENERAL
)
4009 if (!lppd
->nPropertyPages
)
4010 return E_INVALIDARG
;
4012 FIXME("custom property sheets (%ld at %p) not supported\n", lppd
->nPropertyPages
, lppd
->lphPropertyPages
);
4015 /* Use PD_NOPAGENUMS or set nMaxPageRanges and lpPageRanges */
4016 if (!(lppd
->Flags
& PD_NOPAGENUMS
) && (!lppd
->nMaxPageRanges
|| !lppd
->lpPageRanges
))
4018 return E_INVALIDARG
;
4021 if (lppd
->Flags
& PD_RETURNDEFAULT
)
4023 if (lppd
->hDevMode
|| lppd
->hDevNames
)
4025 WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
4026 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE
);
4027 return E_INVALIDARG
;
4029 if (!PRINTDLG_OpenDefaultPrinter(&hprn
))
4031 WARN("Can't find default printer\n");
4032 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN
);
4036 pbuf
= get_printer_infoA(hprn
);
4043 dbuf
= get_driver_infoA(hprn
);
4047 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE
);
4051 dm
= pbuf
->pDevMode
;
4056 struct callback_data cb_data
= { 0 };
4058 FIXME("(%p) semi-stub\n", lppd
);
4060 if (lppd
->lpCallback
)
4062 IUnknown_QueryInterface((IUnknown
*)lppd
->lpCallback
, &IID_IPrintDialogCallback
, (void **)&cb_data
.callback
);
4063 IUnknown_QueryInterface((IUnknown
*)lppd
->lpCallback
, &IID_IObjectWithSite
, (void **)&cb_data
.object
);
4067 * PRINTDLGEXA/W and PRINTDLGA/W layout is the same for A and W variants.
4069 pdlgex_to_pdlg((const PRINTDLGEXW
*)lppd
, (PRINTDLGW
*)&pdlg
);
4070 pdlg
.Flags
|= PD_ENABLEPRINTHOOK
;
4071 pdlg
.lpfnPrintHook
= pdlgex_hook_proc
;
4072 pdlg
.lCustData
= (LPARAM
)&cb_data
;
4074 if (PrintDlgA(&pdlg
))
4076 pdlg_to_pdlgex((const PRINTDLGW
*)&pdlg
, (PRINTDLGEXW
*)lppd
);
4077 lppd
->dwResultAction
= PD_RESULT_PRINT
;
4080 lppd
->dwResultAction
= PD_RESULT_CANCEL
;
4082 if (cb_data
.callback
)
4083 cb_data
.callback
->lpVtbl
->Release(cb_data
.callback
);
4085 cb_data
.object
->lpVtbl
->Release(cb_data
.object
);
4092 PRINTDLG_CreateDevNames(&(lppd
->hDevNames
), dbuf
->pDriverPath
, pbuf
->pPrinterName
, pbuf
->pPortName
);
4093 if (!lppd
->hDevNames
)
4096 lppd
->hDevMode
= update_devmode_handleA(lppd
->hDevMode
, dm
);
4097 if (hr
== S_OK
&& lppd
->hDevMode
) {
4098 if (lppd
->Flags
& PD_RETURNDC
) {
4099 lppd
->hDC
= CreateDCA(dbuf
->pDriverPath
, pbuf
->pPrinterName
, pbuf
->pPortName
, dm
);
4103 else if (lppd
->Flags
& PD_RETURNIC
) {
4104 lppd
->hDC
= CreateICA(dbuf
->pDriverPath
, pbuf
->pPrinterName
, pbuf
->pPortName
, dm
);
4118 /***********************************************************************
4119 * PrintDlgExW (COMDLG32.@)
4121 * Display the property sheet style PRINT dialog box
4124 * lppd [IO] ptr to PRINTDLGEX struct
4128 * Failure: One of the following COM error codes:
4129 * E_OUTOFMEMORY Insufficient memory.
4130 * E_INVALIDARG One or more arguments are invalid.
4131 * E_POINTER Invalid pointer.
4132 * E_HANDLE Invalid handle.
4133 * E_FAIL Unspecified error.
4136 * This Dialog enables the user to specify specific properties of the print job.
4137 * The property sheet can also have additional application-specific and
4138 * driver-specific property pages.
4141 * Not fully implemented
4144 HRESULT WINAPI
PrintDlgExW(LPPRINTDLGEXW lppd
)
4146 PRINTER_INFO_2W
*pbuf
;
4147 DRIVER_INFO_3W
*dbuf
;
4152 if ((lppd
== NULL
) || (lppd
->lStructSize
!= sizeof(PRINTDLGEXW
))) {
4153 return E_INVALIDARG
;
4156 if (!IsWindow(lppd
->hwndOwner
)) {
4160 if (lppd
->nStartPage
!= START_PAGE_GENERAL
)
4162 if (!lppd
->nPropertyPages
)
4163 return E_INVALIDARG
;
4165 FIXME("custom property sheets (%ld at %p) not supported\n", lppd
->nPropertyPages
, lppd
->lphPropertyPages
);
4168 /* Use PD_NOPAGENUMS or set nMaxPageRanges and lpPageRanges */
4169 if (!(lppd
->Flags
& PD_NOPAGENUMS
) && (!lppd
->nMaxPageRanges
|| !lppd
->lpPageRanges
))
4171 return E_INVALIDARG
;
4174 if (lppd
->Flags
& PD_RETURNDEFAULT
) {
4176 if (lppd
->hDevMode
|| lppd
->hDevNames
) {
4177 WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
4178 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE
);
4179 return E_INVALIDARG
;
4181 if (!PRINTDLG_OpenDefaultPrinter(&hprn
)) {
4182 WARN("Can't find default printer\n");
4183 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN
);
4187 pbuf
= get_printer_infoW(hprn
);
4194 dbuf
= get_driver_infoW(hprn
);
4198 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE
);
4202 dm
= pbuf
->pDevMode
;
4207 struct callback_data cb_data
= { 0 };
4209 FIXME("(%p) semi-stub\n", lppd
);
4211 if (lppd
->lpCallback
)
4213 IUnknown_QueryInterface((IUnknown
*)lppd
->lpCallback
, &IID_IPrintDialogCallback
, (void **)&cb_data
.callback
);
4214 IUnknown_QueryInterface((IUnknown
*)lppd
->lpCallback
, &IID_IObjectWithSite
, (void **)&cb_data
.object
);
4217 pdlgex_to_pdlg(lppd
, &pdlg
);
4218 pdlg
.Flags
|= PD_ENABLEPRINTHOOK
;
4219 pdlg
.lpfnPrintHook
= pdlgex_hook_proc
;
4220 pdlg
.lCustData
= (LPARAM
)&cb_data
;
4222 if (PrintDlgW(&pdlg
))
4224 pdlg_to_pdlgex(&pdlg
, lppd
);
4225 lppd
->dwResultAction
= PD_RESULT_PRINT
;
4228 lppd
->dwResultAction
= PD_RESULT_CANCEL
;
4230 if (cb_data
.callback
)
4231 cb_data
.callback
->lpVtbl
->Release(cb_data
.callback
);
4233 cb_data
.object
->lpVtbl
->Release(cb_data
.object
);
4240 PRINTDLG_CreateDevNamesW(&(lppd
->hDevNames
), dbuf
->pDriverPath
, pbuf
->pPrinterName
, pbuf
->pPortName
);
4241 if (!lppd
->hDevNames
)
4244 lppd
->hDevMode
= update_devmode_handleW(lppd
->hDevMode
, dm
);
4245 if (hr
== S_OK
&& lppd
->hDevMode
) {
4246 if (lppd
->Flags
& PD_RETURNDC
) {
4247 lppd
->hDC
= CreateDCW(dbuf
->pDriverPath
, pbuf
->pPrinterName
, pbuf
->pPortName
, dm
);
4251 else if (lppd
->Flags
& PD_RETURNIC
) {
4252 lppd
->hDC
= CreateICW(dbuf
->pDriverPath
, pbuf
->pPrinterName
, pbuf
->pPortName
, dm
);