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
16 #include "wine/wingdi16.h"
18 #include "wine/winuser16.h"
21 #include "debugtools.h"
26 DEFAULT_DEBUG_CHANNEL(commdlg
);
30 /* This PRINTDLGA internal structure stores
31 * pointers to several throughout useful structures.
38 LPPRINTDLGA lpPrintDlg
;
39 LPPRINTDLG16 lpPrintDlg16
;
41 LPPRINTER_INFO_2A lpPrinterInfo
;
42 LPDRIVER_INFO_3A lpDriverInfo
;
44 HICON hCollateIcon
; /* PrintDlg only */
45 HICON hNoCollateIcon
; /* PrintDlg only */
46 HICON hPortraitIcon
; /* PrintSetupDlg only */
47 HICON hLandscapeIcon
; /* PrintSetupDlg only */
52 static struct pd_flags
{
56 {PD_SELECTION
, "PD_SELECTION "},
57 {PD_PAGENUMS
, "PD_PAGENUMS "},
58 {PD_NOSELECTION
, "PD_NOSELECTION "},
59 {PD_NOPAGENUMS
, "PD_NOPAGENUMS "},
60 {PD_COLLATE
, "PD_COLLATE "},
61 {PD_PRINTTOFILE
, "PD_PRINTTOFILE "},
62 {PD_PRINTSETUP
, "PD_PRINTSETUP "},
63 {PD_NOWARNING
, "PD_NOWARNING "},
64 {PD_RETURNDC
, "PD_RETURNDC "},
65 {PD_RETURNIC
, "PD_RETURNIC "},
66 {PD_RETURNDEFAULT
, "PD_RETURNDEFAULT "},
67 {PD_SHOWHELP
, "PD_SHOWHELP "},
68 {PD_ENABLEPRINTHOOK
, "PD_ENABLEPRINTHOOK "},
69 {PD_ENABLESETUPHOOK
, "PD_ENABLESETUPHOOK "},
70 {PD_ENABLEPRINTTEMPLATE
, "PD_ENABLEPRINTTEMPLATE "},
71 {PD_ENABLESETUPTEMPLATE
, "PD_ENABLESETUPTEMPLATE "},
72 {PD_ENABLEPRINTTEMPLATEHANDLE
, "PD_ENABLEPRINTTEMPLATEHANDLE "},
73 {PD_ENABLESETUPTEMPLATEHANDLE
, "PD_ENABLESETUPTEMPLATEHANDLE "},
74 {PD_USEDEVMODECOPIES
, "PD_USEDEVMODECOPIES[ANDCOLLATE] "},
75 {PD_DISABLEPRINTTOFILE
, "PD_DISABLEPRINTTOFILE "},
76 {PD_HIDEPRINTTOFILE
, "PD_HIDEPRINTTOFILE "},
77 {PD_NONETWORKBUTTON
, "PD_NONETWORKBUTTON "},
81 /* Yes these constants are the same, but we're just copying win98 */
82 #define UPDOWN_ID 0x270f
83 #define MAX_COPIES 9999
85 /***********************************************************************
86 * PRINTDLG_GetDefaultPrinterName
88 * Returns the default printer name in buf.
89 * Even under WinNT/2000 default printer is retrieved via GetProfileString -
90 * these entries are mapped somewhere in the registry rather than win.ini.
92 * Returns TRUE on success else FALSE
94 static BOOL
PRINTDLG_GetDefaultPrinterName(LPSTR buf
, DWORD len
)
98 if(!GetProfileStringA("windows", "device", "", buf
, len
)) {
99 TRACE("No profile entry for default printer found.\n");
102 if((ptr
= strchr(buf
, ',')) == NULL
) {
103 FIXME("bad format for default printer (%s)!\n",buf
);
110 /***********************************************************************
111 * PRINTDLG_OpenDefaultPrinter
113 * Returns a winspool printer handle to the default printer in *hprn
114 * Caller must call ClosePrinter on the handle
116 * Returns TRUE on success else FALSE
118 static BOOL
PRINTDLG_OpenDefaultPrinter(HANDLE
*hprn
)
122 if(!PRINTDLG_GetDefaultPrinterName(buf
, sizeof(buf
)))
124 res
= OpenPrinterA(buf
, hprn
, NULL
);
126 FIXME("Could not open printer %s?!\n",buf
);
130 /***********************************************************************
131 * PRINTDLG_SetUpPrinterListCombo
133 * Initializes printer list combox.
134 * hDlg: HWND of dialog
135 * id: Control id of combo
136 * name: Name of printer to select
138 * Initializes combo with list of available printers. Selects printer 'name'
139 * If name is NULL or does not exist select the default printer.
141 * Returns number of printers added to list.
143 static INT
PRINTDLG_SetUpPrinterListCombo(HWND hDlg
, UINT id
, LPCSTR name
)
147 LPPRINTER_INFO_2A pi
;
148 EnumPrintersA(PRINTER_ENUM_LOCAL
, NULL
, 2, NULL
, 0, &needed
, &num
);
149 pi
= HeapAlloc(GetProcessHeap(), 0, needed
);
150 EnumPrintersA(PRINTER_ENUM_LOCAL
, NULL
, 2, (LPBYTE
)pi
, needed
, &needed
,
153 for(i
= 0; i
< num
; i
++) {
154 SendDlgItemMessageA(hDlg
, id
, CB_ADDSTRING
, 0,
155 (LPARAM
)pi
[i
].pPrinterName
);
157 HeapFree(GetProcessHeap(), 0, pi
);
159 (i
= SendDlgItemMessageA(hDlg
, id
, CB_FINDSTRINGEXACT
, -1,
160 (LPARAM
)name
)) == CB_ERR
) {
163 FIXME("Can't find '%s' in printer list so trying to find default\n",
165 if(!PRINTDLG_GetDefaultPrinterName(buf
, sizeof(buf
)))
167 i
= SendDlgItemMessageA(hDlg
, id
, CB_FINDSTRINGEXACT
, -1, (LPARAM
)buf
);
169 FIXME("Can't find default printer in printer list\n");
171 SendDlgItemMessageA(hDlg
, id
, CB_SETCURSEL
, i
, 0);
175 /***********************************************************************
176 * PRINTDLG_CreateDevNames [internal]
179 * creates a DevNames structure.
181 * (NB. when we handle unicode the offsets will be in wchars).
183 static BOOL
PRINTDLG_CreateDevNames(HGLOBAL
*hmem
, char* DeviceDriverName
,
184 char* DeviceName
, char* OutputPort
)
187 char* pDevNamesSpace
;
189 LPDEVNAMES lpDevNames
;
192 size
= strlen(DeviceDriverName
) + 1
193 + strlen(DeviceName
) + 1
194 + strlen(OutputPort
) + 1
198 *hmem
= GlobalReAlloc(*hmem
, size
, GMEM_MOVEABLE
);
200 *hmem
= GlobalAlloc(GMEM_MOVEABLE
, size
);
204 pDevNamesSpace
= GlobalLock(*hmem
);
205 lpDevNames
= (LPDEVNAMES
) pDevNamesSpace
;
207 pTempPtr
= pDevNamesSpace
+ sizeof(DEVNAMES
);
208 strcpy(pTempPtr
, DeviceDriverName
);
209 lpDevNames
->wDriverOffset
= pTempPtr
- pDevNamesSpace
;
211 pTempPtr
+= strlen(DeviceDriverName
) + 1;
212 strcpy(pTempPtr
, DeviceName
);
213 lpDevNames
->wDeviceOffset
= pTempPtr
- pDevNamesSpace
;
215 pTempPtr
+= strlen(DeviceName
) + 1;
216 strcpy(pTempPtr
, OutputPort
);
217 lpDevNames
->wOutputOffset
= pTempPtr
- pDevNamesSpace
;
219 PRINTDLG_GetDefaultPrinterName(buf
, sizeof(buf
));
220 lpDevNames
->wDefault
= (strcmp(buf
, DeviceName
) == 0) ? 1 : 0;
225 static BOOL
PRINTDLG_CreateDevNames16(HGLOBAL16
*hmem
, char* DeviceDriverName
,
226 char* DeviceName
, char* OutputPort
)
229 char* pDevNamesSpace
;
231 LPDEVNAMES lpDevNames
;
234 size
= strlen(DeviceDriverName
) + 1
235 + strlen(DeviceName
) + 1
236 + strlen(OutputPort
) + 1
240 *hmem
= GlobalReAlloc16(*hmem
, size
, GMEM_MOVEABLE
);
242 *hmem
= GlobalAlloc16(GMEM_MOVEABLE
, size
);
246 pDevNamesSpace
= GlobalLock16(*hmem
);
247 lpDevNames
= (LPDEVNAMES
) pDevNamesSpace
;
249 pTempPtr
= pDevNamesSpace
+ sizeof(DEVNAMES
);
250 strcpy(pTempPtr
, DeviceDriverName
);
251 lpDevNames
->wDriverOffset
= pTempPtr
- pDevNamesSpace
;
253 pTempPtr
+= strlen(DeviceDriverName
) + 1;
254 strcpy(pTempPtr
, DeviceName
);
255 lpDevNames
->wDeviceOffset
= pTempPtr
- pDevNamesSpace
;
257 pTempPtr
+= strlen(DeviceName
) + 1;
258 strcpy(pTempPtr
, OutputPort
);
259 lpDevNames
->wOutputOffset
= pTempPtr
- pDevNamesSpace
;
261 PRINTDLG_GetDefaultPrinterName(buf
, sizeof(buf
));
262 lpDevNames
->wDefault
= (strcmp(buf
, DeviceName
) == 0) ? 1 : 0;
263 GlobalUnlock16(*hmem
);
268 /***********************************************************************
269 * PRINTDLG_UpdatePrintDlg [internal]
272 * updates the PrintDlg structure for returnvalues.
275 * FALSE if user is not allowed to close (i.e. wrong nTo or nFrom values)
278 static BOOL
PRINTDLG_UpdatePrintDlg(HWND hDlg
,
279 PRINT_PTRA
* PrintStructures
)
281 LPPRINTDLGA lppd
= PrintStructures
->dlg
.lpPrintDlg
;
282 PDEVMODEA lpdm
= PrintStructures
->lpDevMode
;
283 LPPRINTER_INFO_2A pi
= PrintStructures
->lpPrinterInfo
;
287 FIXME("No lpdm ptr?\n");
292 if(!(lppd
->Flags
& PD_PRINTSETUP
)) {
293 /* check whether nFromPage and nToPage are within range defined by
294 * nMinPage and nMaxPage
296 if (IsDlgButtonChecked(hDlg
, rad3
) == BST_CHECKED
) { /* Pages */
299 nFromPage
= GetDlgItemInt(hDlg
, edt1
, NULL
, FALSE
);
300 nToPage
= GetDlgItemInt(hDlg
, edt2
, NULL
, FALSE
);
301 if (nFromPage
< lppd
->nMinPage
|| nFromPage
> lppd
->nMaxPage
||
302 nToPage
< lppd
->nMinPage
|| nToPage
> lppd
->nMaxPage
) {
303 char resourcestr
[256];
305 LoadStringA(COMDLG32_hInstance
, PD32_INVALID_PAGE_RANGE
,
307 sprintf(resultstr
,resourcestr
, lppd
->nMinPage
, lppd
->nMaxPage
);
308 LoadStringA(COMDLG32_hInstance
, PD32_PRINT_TITLE
,
310 MessageBoxA(hDlg
, resultstr
, resourcestr
,
311 MB_OK
| MB_ICONWARNING
);
314 lppd
->nFromPage
= nFromPage
;
315 lppd
->nToPage
= nToPage
;
318 if (IsDlgButtonChecked(hDlg
, chx1
) == BST_CHECKED
) {/* Print to file */
319 lppd
->Flags
|= PD_PRINTTOFILE
;
320 pi
->pPortName
= "FILE:";
323 if (IsDlgButtonChecked(hDlg
, chx2
) == BST_CHECKED
) { /* Collate */
324 FIXME("Collate lppd not yet implemented as output\n");
327 /* set PD_Collate and nCopies */
328 if (lppd
->Flags
& PD_USEDEVMODECOPIESANDCOLLATE
) {
329 /* The application doesn't support multiple copies or collate...
331 lppd
->Flags
&= ~PD_COLLATE
;
333 /* if the printer driver supports it... store info there
334 * otherwise no collate & multiple copies !
336 if (lpdm
->dmFields
& DM_COLLATE
)
338 (IsDlgButtonChecked(hDlg
, chx2
) == BST_CHECKED
);
339 if (lpdm
->dmFields
& DM_COPIES
)
340 lpdm
->dmCopies
= GetDlgItemInt(hDlg
, edt3
, NULL
, FALSE
);
342 if (IsDlgButtonChecked(hDlg
, chx2
) == BST_CHECKED
)
343 lppd
->Flags
|= PD_COLLATE
;
345 lppd
->Flags
&= ~PD_COLLATE
;
346 lppd
->nCopies
= GetDlgItemInt(hDlg
, edt3
, NULL
, FALSE
);
353 /************************************************************************
354 * PRINTDLG_SetUpPaperComboBox
356 * Initialize either the papersize or inputslot combos of the Printer Setup
357 * dialog. We store the associated word (eg DMPAPER_A4) as the item data.
358 * We also try to re-select the old selection.
360 static BOOL
PRINTDLG_SetUpPaperComboBox(HWND hDlg
,
373 int fwCapability_Names
;
374 int fwCapability_Words
;
376 TRACE(" Printer: %s, ComboID: %d\n",PrinterName
,nIDComboBox
);
378 /* query the dialog box for the current selected value */
379 Sel
= SendDlgItemMessageA(hDlg
, nIDComboBox
, CB_GETCURSEL
, 0, 0);
381 /* we enter here only if a different printer is selected after
382 * the Print Setup dialog is opened. The current settings are
383 * stored into the newly selected printer.
385 oldWord
= SendDlgItemMessageA(hDlg
, nIDComboBox
, CB_GETITEMDATA
,
388 if (nIDComboBox
== cmb2
)
389 dm
->u1
.s1
.dmPaperSize
= oldWord
;
391 dm
->dmDefaultSource
= oldWord
;
395 /* we enter here only when the Print setup dialog is initially
396 * opened. In this case the settings are restored from when
397 * the dialog was last closed.
400 if (nIDComboBox
== cmb2
)
401 oldWord
= dm
->u1
.s1
.dmPaperSize
;
403 oldWord
= dm
->dmDefaultSource
;
407 if (nIDComboBox
== cmb2
) {
409 fwCapability_Names
= DC_PAPERNAMES
;
410 fwCapability_Words
= DC_PAPERS
;
414 fwCapability_Names
= DC_BINNAMES
;
415 fwCapability_Words
= DC_BINS
;
418 /* for some printer drivers, DeviceCapabilities calls a VXD to obtain the
419 * paper settings. As Wine doesn't allow VXDs, this results in a crash.
421 WARN(" if your printer driver uses VXDs, expect a crash now!\n");
422 NrOfEntries
= DeviceCapabilitiesA(PrinterName
, PortName
,
423 fwCapability_Names
, NULL
, dm
);
424 if (NrOfEntries
== 0)
425 WARN("no Name Entries found!\n");
427 if(DeviceCapabilitiesA(PrinterName
, PortName
, fwCapability_Words
, NULL
, dm
)
429 ERR("Number of caps is different\n");
433 Names
= HeapAlloc(GetProcessHeap(),0, NrOfEntries
*NamesSize
);
434 Words
= HeapAlloc(GetProcessHeap(),0, NrOfEntries
*sizeof(WORD
));
435 NrOfEntries
= DeviceCapabilitiesA(PrinterName
, PortName
,
436 fwCapability_Names
, Names
, dm
);
437 NrOfEntries
= DeviceCapabilitiesA(PrinterName
, PortName
,
438 fwCapability_Words
, (LPSTR
)Words
, dm
);
440 /* reset any current content in the combobox */
441 SendDlgItemMessageA(hDlg
, nIDComboBox
, CB_RESETCONTENT
, 0, 0);
443 /* store new content */
444 for (i
= 0; i
< NrOfEntries
; i
++) {
445 DWORD pos
= SendDlgItemMessageA(hDlg
, nIDComboBox
, CB_ADDSTRING
, 0,
446 (LPARAM
)(&Names
[i
*NamesSize
]) );
447 SendDlgItemMessageA(hDlg
, nIDComboBox
, CB_SETITEMDATA
, pos
,
451 /* Look for old selection - can't do this is previous loop since
452 item order will change as more items are added */
454 for (i
= 0; i
< NrOfEntries
; i
++) {
455 if(SendDlgItemMessageA(hDlg
, nIDComboBox
, CB_GETITEMDATA
, i
, 0) ==
461 SendDlgItemMessageA(hDlg
, nIDComboBox
, CB_SETCURSEL
, Sel
, 0);
463 HeapFree(GetProcessHeap(),0,Words
);
464 HeapFree(GetProcessHeap(),0,Names
);
468 /***********************************************************************
469 * PRINTDLG_UpdatePrinterInfoTexts [internal]
471 static void PRINTDLG_UpdatePrinterInfoTexts(HWND hDlg
, LPPRINTER_INFO_2A pi
)
474 char ResourceString
[256];
480 /* add all status messages */
481 for (i
= 0; i
< 25; i
++) {
482 if (pi
->Status
& (1<<i
)) {
483 LoadStringA(COMDLG32_hInstance
, PD32_PRINTER_STATUS_PAUSED
+i
,
484 ResourceString
, 255);
485 strcat(StatusMsg
,ResourceString
);
489 /* FIXME: status==ready must only be appended if really so.
490 but how to detect? */
491 LoadStringA(COMDLG32_hInstance
, PD32_PRINTER_STATUS_READY
,
492 ResourceString
, 255);
493 strcat(StatusMsg
,ResourceString
);
495 SendDlgItemMessageA(hDlg
, stc12
, WM_SETTEXT
, 0, (LPARAM
)StatusMsg
);
497 /* set all other printer info texts */
498 SendDlgItemMessageA(hDlg
, stc11
, WM_SETTEXT
, 0, (LPARAM
)pi
->pDriverName
);
499 if (pi
->pLocation
!= NULL
&& pi
->pLocation
[0] != '\0')
500 SendDlgItemMessageA(hDlg
, stc14
, WM_SETTEXT
, 0,(LPARAM
)pi
->pLocation
);
502 SendDlgItemMessageA(hDlg
, stc14
, WM_SETTEXT
, 0,(LPARAM
)pi
->pPortName
);
503 SendDlgItemMessageA(hDlg
, stc13
, WM_SETTEXT
, 0, (LPARAM
)(pi
->pComment
?
509 /*******************************************************************
511 * PRINTDLG_ChangePrinter
514 static BOOL
PRINTDLG_ChangePrinter(HWND hDlg
, char *name
,
515 PRINT_PTRA
*PrintStructures
)
517 LPPRINTDLGA lppd
= PrintStructures
->dlg
.lpPrintDlg
;
518 LPDEVMODEA lpdm
= NULL
;
523 if(PrintStructures
->lpPrinterInfo
)
524 HeapFree(GetProcessHeap(),0, PrintStructures
->lpPrinterInfo
);
525 if(PrintStructures
->lpDriverInfo
)
526 HeapFree(GetProcessHeap(),0, PrintStructures
->lpDriverInfo
);
527 if(!OpenPrinterA(name
, &hprn
, NULL
)) {
528 ERR("Can't open printer %s\n", name
);
531 GetPrinterA(hprn
, 2, NULL
, 0, &needed
);
532 PrintStructures
->lpPrinterInfo
= HeapAlloc(GetProcessHeap(),0,needed
);
533 GetPrinterA(hprn
, 2, (LPBYTE
)PrintStructures
->lpPrinterInfo
, needed
,
535 GetPrinterDriverA(hprn
, NULL
, 3, NULL
, 0, &needed
);
536 PrintStructures
->lpDriverInfo
= HeapAlloc(GetProcessHeap(),0,needed
);
537 if (!GetPrinterDriverA(hprn
, NULL
, 3, (LPBYTE
)PrintStructures
->lpDriverInfo
,
539 ERR("GetPrinterDriverA failed for %s, fix your config!\n",PrintStructures
->lpPrinterInfo
->pPrinterName
);
544 PRINTDLG_UpdatePrinterInfoTexts(hDlg
, PrintStructures
->lpPrinterInfo
);
546 if(PrintStructures
->lpDevMode
) {
547 HeapFree(GetProcessHeap(), 0, PrintStructures
->lpDevMode
);
548 PrintStructures
->lpDevMode
= NULL
;
551 dmSize
= DocumentPropertiesA(0, 0, name
, NULL
, NULL
, 0);
553 ERR("DocumentProperties fails on %s\n", debugstr_a(name
));
556 PrintStructures
->lpDevMode
= HeapAlloc(GetProcessHeap(), 0, dmSize
);
557 dmSize
= DocumentPropertiesA(0, 0, name
, PrintStructures
->lpDevMode
, NULL
,
559 if(lppd
->hDevMode
&& (lpdm
= GlobalLock(lppd
->hDevMode
)) &&
560 !strcmp(lpdm
->dmDeviceName
,
561 PrintStructures
->lpDevMode
->dmDeviceName
)) {
562 /* Supplied devicemode matches current printer so try to use it */
563 DocumentPropertiesA(0, 0, name
, PrintStructures
->lpDevMode
, lpdm
,
564 DM_OUT_BUFFER
| DM_IN_BUFFER
);
567 GlobalUnlock(lppd
->hDevMode
);
569 lpdm
= PrintStructures
->lpDevMode
; /* use this as a shortcut */
571 if(!(lppd
->Flags
& PD_PRINTSETUP
)) {
572 /* Print range (All/Range/Selection) */
573 SetDlgItemInt(hDlg
, edt1
, lppd
->nFromPage
, FALSE
);
574 SetDlgItemInt(hDlg
, edt2
, lppd
->nToPage
, FALSE
);
575 CheckRadioButton(hDlg
, rad1
, rad3
, rad1
); /* default */
576 if (lppd
->Flags
& PD_NOSELECTION
)
577 EnableWindow(GetDlgItem(hDlg
, rad2
), FALSE
);
579 if (lppd
->Flags
& PD_SELECTION
)
580 CheckRadioButton(hDlg
, rad1
, rad3
, rad2
);
581 if (lppd
->Flags
& PD_NOPAGENUMS
) {
582 EnableWindow(GetDlgItem(hDlg
, rad3
), FALSE
);
583 EnableWindow(GetDlgItem(hDlg
, stc2
),FALSE
);
584 EnableWindow(GetDlgItem(hDlg
, edt1
), FALSE
);
585 EnableWindow(GetDlgItem(hDlg
, stc3
),FALSE
);
586 EnableWindow(GetDlgItem(hDlg
, edt2
), FALSE
);
588 if (lppd
->Flags
& PD_PAGENUMS
)
589 CheckRadioButton(hDlg
, rad1
, rad3
, rad3
);
591 /* "All xxx pages"... */
593 char resourcestr
[64];
595 LoadStringA(COMDLG32_hInstance
, PD32_PRINT_ALL_X_PAGES
,
597 sprintf(result
,resourcestr
,lppd
->nMaxPage
- lppd
->nMinPage
+ 1);
598 SendDlgItemMessageA(hDlg
, rad1
, WM_SETTEXT
, 0, (LPARAM
) result
);
603 * FIXME: The ico3 is not displayed for some reason. I don't know why.
605 if (lppd
->Flags
& PD_COLLATE
) {
606 SendDlgItemMessageA(hDlg
, ico3
, STM_SETIMAGE
, (WPARAM
) IMAGE_ICON
,
607 (LPARAM
)PrintStructures
->hCollateIcon
);
608 CheckDlgButton(hDlg
, chx2
, 1);
610 SendDlgItemMessageA(hDlg
, ico3
, STM_SETIMAGE
, (WPARAM
) IMAGE_ICON
,
611 (LPARAM
)PrintStructures
->hNoCollateIcon
);
612 CheckDlgButton(hDlg
, chx2
, 0);
615 if (lppd
->Flags
& PD_USEDEVMODECOPIESANDCOLLATE
) {
616 /* if printer doesn't support it: no Collate */
617 if (!(lpdm
->dmFields
& DM_COLLATE
)) {
618 EnableWindow(GetDlgItem(hDlg
, chx2
), FALSE
);
619 EnableWindow(GetDlgItem(hDlg
, ico3
), FALSE
);
626 if (lppd
->hDevMode
== 0)
627 copies
= lppd
->nCopies
;
629 copies
= lpdm
->dmCopies
;
630 if(copies
== 0) copies
= 1;
631 else if(copies
< 0) copies
= MAX_COPIES
;
632 SetDlgItemInt(hDlg
, edt3
, copies
, FALSE
);
635 if (lppd
->Flags
& PD_USEDEVMODECOPIESANDCOLLATE
) {
636 /* if printer doesn't support it: no nCopies */
637 if (!(lpdm
->dmFields
& DM_COPIES
)) {
638 EnableWindow(GetDlgItem(hDlg
, edt3
), FALSE
);
639 EnableWindow(GetDlgItem(hDlg
, stc5
), FALSE
);
644 CheckDlgButton(hDlg
, chx1
, (lppd
->Flags
& PD_PRINTTOFILE
) ? 1 : 0);
645 if (lppd
->Flags
& PD_DISABLEPRINTTOFILE
)
646 EnableWindow(GetDlgItem(hDlg
, chx1
), FALSE
);
647 if (lppd
->Flags
& PD_HIDEPRINTTOFILE
)
648 ShowWindow(GetDlgItem(hDlg
, chx1
), SW_HIDE
);
650 } else { /* PD_PRINTSETUP */
651 BOOL bPortrait
= (lpdm
->u1
.s1
.dmOrientation
== DMORIENT_PORTRAIT
);
653 PRINTDLG_SetUpPaperComboBox(hDlg
, cmb2
,
654 PrintStructures
->lpPrinterInfo
->pPrinterName
,
655 PrintStructures
->lpPrinterInfo
->pPortName
,
657 PRINTDLG_SetUpPaperComboBox(hDlg
, cmb3
,
658 PrintStructures
->lpPrinterInfo
->pPrinterName
,
659 PrintStructures
->lpPrinterInfo
->pPortName
,
661 CheckRadioButton(hDlg
, rad1
, rad2
, bPortrait
? rad1
: rad2
);
662 SendDlgItemMessageA(hDlg
, ico1
, STM_SETIMAGE
, (WPARAM
) IMAGE_ICON
,
663 (LPARAM
)(bPortrait
? PrintStructures
->hPortraitIcon
:
664 PrintStructures
->hLandscapeIcon
));
669 if ((lppd
->Flags
& PD_SHOWHELP
)==0) {
670 /* hide if PD_SHOWHELP not specified */
671 ShowWindow(GetDlgItem(hDlg
, pshHelp
), SW_HIDE
);
676 /***********************************************************************
677 * PRINTDLG_WMInitDialog [internal]
679 static LRESULT
PRINTDLG_WMInitDialog(HWND hDlg
, WPARAM wParam
,
680 PRINT_PTRA
* PrintStructures
)
682 LPPRINTDLGA lppd
= PrintStructures
->dlg
.lpPrintDlg
;
686 UINT comboID
= (lppd
->Flags
& PD_PRINTSETUP
) ? cmb1
: cmb4
;
688 /* load Collate ICONs */
689 /* We load these with LoadImage becasue they are not a standard
690 size and we don't want them rescaled */
691 PrintStructures
->hCollateIcon
=
692 LoadImageA(COMDLG32_hInstance
, "PD32_COLLATE", IMAGE_ICON
, 0, 0, 0);
693 PrintStructures
->hNoCollateIcon
=
694 LoadImageA(COMDLG32_hInstance
, "PD32_NOCOLLATE", IMAGE_ICON
, 0, 0, 0);
696 /* These can be done with LoadIcon */
697 PrintStructures
->hPortraitIcon
=
698 LoadIconA(COMDLG32_hInstance
, "PD32_PORTRAIT");
699 PrintStructures
->hLandscapeIcon
=
700 LoadIconA(COMDLG32_hInstance
, "PD32_LANDSCAPE");
702 if(PrintStructures
->hCollateIcon
== 0 ||
703 PrintStructures
->hNoCollateIcon
== 0 ||
704 PrintStructures
->hPortraitIcon
== 0 ||
705 PrintStructures
->hLandscapeIcon
== 0) {
706 ERR("no icon in resourcefile\n");
707 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
708 EndDialog(hDlg
, FALSE
);
712 * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
713 * must be registered and the Help button must be shown.
715 if (lppd
->Flags
& PD_SHOWHELP
) {
716 if((PrintStructures
->HelpMessageID
=
717 RegisterWindowMessageA(HELPMSGSTRINGA
)) == 0) {
718 COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL
);
722 PrintStructures
->HelpMessageID
= 0;
724 if(!(lppd
->Flags
&PD_PRINTSETUP
)) {
725 PrintStructures
->hwndUpDown
=
726 CreateUpDownControl(WS_CHILD
| WS_VISIBLE
| WS_BORDER
|
727 UDS_NOTHOUSANDS
| UDS_ARROWKEYS
|
728 UDS_ALIGNRIGHT
| UDS_SETBUDDYINT
, 0, 0, 0, 0,
729 hDlg
, UPDOWN_ID
, COMDLG32_hInstance
,
730 GetDlgItem(hDlg
, edt3
), MAX_COPIES
, 1, 1);
733 /* FIXME: I allow more freedom than either Win95 or WinNT,
734 * which do not agree to what errors should be thrown or not
735 * in case nToPage or nFromPage is out-of-range.
737 if (lppd
->nMaxPage
< lppd
->nMinPage
)
738 lppd
->nMaxPage
= lppd
->nMinPage
;
739 if (lppd
->nMinPage
== lppd
->nMaxPage
)
740 lppd
->Flags
|= PD_NOPAGENUMS
;
741 if (lppd
->nToPage
< lppd
->nMinPage
)
742 lppd
->nToPage
= lppd
->nMinPage
;
743 if (lppd
->nToPage
> lppd
->nMaxPage
)
744 lppd
->nToPage
= lppd
->nMaxPage
;
745 if (lppd
->nFromPage
< lppd
->nMinPage
)
746 lppd
->nFromPage
= lppd
->nMinPage
;
747 if (lppd
->nFromPage
> lppd
->nMaxPage
)
748 lppd
->nFromPage
= lppd
->nMaxPage
;
750 /* if we have the combo box, fill it */
751 if (GetDlgItem(hDlg
,comboID
)) {
754 pdn
= GlobalLock(lppd
->hDevNames
);
755 pdm
= GlobalLock(lppd
->hDevMode
);
757 name
= (char*)pdn
+ pdn
->wDeviceOffset
;
759 name
= pdm
->dmDeviceName
;
760 PRINTDLG_SetUpPrinterListCombo(hDlg
, comboID
, name
);
761 if(pdm
) GlobalUnlock(lppd
->hDevMode
);
762 if(pdn
) GlobalUnlock(lppd
->hDevNames
);
764 /* Now find selected printer and update rest of dlg */
765 name
= HeapAlloc(GetProcessHeap(),0,256);
766 if (GetDlgItemTextA(hDlg
, comboID
, name
, 255))
767 PRINTDLG_ChangePrinter(hDlg
, name
, PrintStructures
);
768 HeapFree(GetProcessHeap(),0,name
);
770 /* else use default printer */
772 BOOL ret
= PRINTDLG_GetDefaultPrinterName(name
, sizeof(name
));
775 PRINTDLG_ChangePrinter(hDlg
, name
, PrintStructures
);
777 FIXME("No default printer found, expect problems!\n");
782 /***********************************************************************
783 * PRINTDLG_WMInitDialog [internal]
785 static LRESULT
PRINTDLG_WMInitDialog16(HWND hDlg
, WPARAM wParam
,
786 PRINT_PTRA
* PrintStructures
)
788 LPPRINTDLG16 lppd
= PrintStructures
->dlg
.lpPrintDlg16
;
792 UINT comboID
= (lppd
->Flags
& PD_PRINTSETUP
) ? cmb1
: cmb4
;
794 /* load Collate ICONs */
795 PrintStructures
->hCollateIcon
=
796 LoadIconA(COMDLG32_hInstance
, "PD32_COLLATE");
797 PrintStructures
->hNoCollateIcon
=
798 LoadIconA(COMDLG32_hInstance
, "PD32_NOCOLLATE");
799 if(PrintStructures
->hCollateIcon
== 0 ||
800 PrintStructures
->hNoCollateIcon
== 0) {
801 ERR("no icon in resourcefile\n");
802 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
803 EndDialog(hDlg
, FALSE
);
806 /* load Paper Orientation ICON */
807 /* FIXME: not implemented yet */
810 * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
811 * must be registered and the Help button must be shown.
813 if (lppd
->Flags
& PD_SHOWHELP
) {
814 if((PrintStructures
->HelpMessageID
=
815 RegisterWindowMessageA(HELPMSGSTRINGA
)) == 0) {
816 COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL
);
820 PrintStructures
->HelpMessageID
= 0;
822 /* FIXME: I allow more freedom than either Win95 or WinNT,
823 * which do not agree to what errors should be thrown or not
824 * in case nToPage or nFromPage is out-of-range.
826 if (lppd
->nMaxPage
< lppd
->nMinPage
)
827 lppd
->nMaxPage
= lppd
->nMinPage
;
828 if (lppd
->nMinPage
== lppd
->nMaxPage
)
829 lppd
->Flags
|= PD_NOPAGENUMS
;
830 if (lppd
->nToPage
< lppd
->nMinPage
)
831 lppd
->nToPage
= lppd
->nMinPage
;
832 if (lppd
->nToPage
> lppd
->nMaxPage
)
833 lppd
->nToPage
= lppd
->nMaxPage
;
834 if (lppd
->nFromPage
< lppd
->nMinPage
)
835 lppd
->nFromPage
= lppd
->nMinPage
;
836 if (lppd
->nFromPage
> lppd
->nMaxPage
)
837 lppd
->nFromPage
= lppd
->nMaxPage
;
839 /* If the printer combo box is in the dialog, fill it */
840 if (GetDlgItem(hDlg
,comboID
)) {
843 pdn
= GlobalLock16(lppd
->hDevNames
);
844 pdm
= GlobalLock16(lppd
->hDevMode
);
846 name
= (char*)pdn
+ pdn
->wDeviceOffset
;
848 name
= pdm
->dmDeviceName
;
849 PRINTDLG_SetUpPrinterListCombo(hDlg
, comboID
, name
);
850 if(pdm
) GlobalUnlock16(lppd
->hDevMode
);
851 if(pdn
) GlobalUnlock16(lppd
->hDevNames
);
853 /* Now find selected printer and update rest of dlg */
854 name
= HeapAlloc(GetProcessHeap(),0,256);
855 if (GetDlgItemTextA(hDlg
, comboID
, name
, 255))
856 PRINTDLG_ChangePrinter(hDlg
, name
, PrintStructures
);
858 /* else just use default printer */
860 BOOL ret
= PRINTDLG_GetDefaultPrinterName(name
, sizeof(name
));
863 PRINTDLG_ChangePrinter(hDlg
, name
, PrintStructures
);
865 FIXME("No default printer found, expect problems!\n");
867 HeapFree(GetProcessHeap(),0,name
);
872 /***********************************************************************
873 * PRINTDLG_WMCommand [internal]
875 static LRESULT
PRINTDLG_WMCommand(HWND hDlg
, WPARAM wParam
,
876 LPARAM lParam
, PRINT_PTRA
* PrintStructures
)
878 LPPRINTDLGA lppd
= PrintStructures
->dlg
.lpPrintDlg
;
879 UINT PrinterComboID
= (lppd
->Flags
& PD_PRINTSETUP
) ? cmb1
: cmb4
;
880 LPDEVMODEA lpdm
= PrintStructures
->lpDevMode
;
882 switch (LOWORD(wParam
)) {
884 TRACE(" OK button was hit\n");
885 if (PRINTDLG_UpdatePrintDlg(hDlg
, PrintStructures
)!=TRUE
) {
886 FIXME("Update printdlg was not successful!\n");
889 EndDialog(hDlg
, TRUE
);
893 TRACE(" CANCEL button was hit\n");
894 EndDialog(hDlg
, FALSE
);
898 TRACE(" HELP button was hit\n");
899 SendMessageA(lppd
->hwndOwner
, PrintStructures
->HelpMessageID
,
900 (WPARAM
) hDlg
, (LPARAM
) lppd
);
903 case chx2
: /* collate pages checkbox */
904 if (IsDlgButtonChecked(hDlg
, chx2
) == BST_CHECKED
)
905 SendDlgItemMessageA(hDlg
, ico3
, STM_SETIMAGE
, (WPARAM
) IMAGE_ICON
,
906 (LPARAM
)PrintStructures
->hCollateIcon
);
908 SendDlgItemMessageA(hDlg
, ico3
, STM_SETIMAGE
, (WPARAM
) IMAGE_ICON
,
909 (LPARAM
)PrintStructures
->hNoCollateIcon
);
911 case edt1
: /* from page nr editbox */
912 case edt2
: /* to page nr editbox */
913 if (HIWORD(wParam
)==EN_CHANGE
) {
916 nFromPage
= GetDlgItemInt(hDlg
, edt1
, NULL
, FALSE
);
917 nToPage
= GetDlgItemInt(hDlg
, edt2
, NULL
, FALSE
);
918 if (nFromPage
!= lppd
->nFromPage
|| nToPage
!= lppd
->nToPage
)
919 CheckRadioButton(hDlg
, rad1
, rad3
, rad3
);
924 if(HIWORD(wParam
) == EN_CHANGE
) {
925 INT copies
= GetDlgItemInt(hDlg
, edt3
, NULL
, FALSE
);
927 EnableWindow(GetDlgItem(hDlg
, chx2
), FALSE
);
929 EnableWindow(GetDlgItem(hDlg
, chx2
), TRUE
);
933 case psh2
: /* Properties button */
936 char PrinterName
[256];
938 GetDlgItemTextA(hDlg
, PrinterComboID
, PrinterName
, 255);
939 if (!OpenPrinterA(PrinterName
, &hPrinter
, NULL
)) {
940 FIXME(" Call to OpenPrinter did not succeed!\n");
943 DocumentPropertiesA(hDlg
, hPrinter
, PrinterName
,
944 PrintStructures
->lpDevMode
,
945 PrintStructures
->lpDevMode
,
946 DM_IN_BUFFER
| DM_OUT_BUFFER
| DM_IN_PROMPT
);
947 ClosePrinter(hPrinter
);
951 case rad1
: /* Paperorientation */
952 if (lppd
->Flags
& PD_PRINTSETUP
)
953 lpdm
->u1
.s1
.dmOrientation
= DMORIENT_PORTRAIT
;
956 case rad2
: /* Paperorientation */
957 if (lppd
->Flags
& PD_PRINTSETUP
)
958 lpdm
->u1
.s1
.dmOrientation
= DMORIENT_LANDSCAPE
;
962 case cmb4
: /* Printer combobox */
963 if (HIWORD(wParam
)==CBN_SELCHANGE
) {
964 char PrinterName
[256];
965 GetDlgItemTextA(hDlg
, LOWORD(wParam
), PrinterName
, 255);
966 PRINTDLG_ChangePrinter(hDlg
, PrinterName
, PrintStructures
);
970 case cmb2
: /* Papersize */
972 DWORD Sel
= SendDlgItemMessageA(hDlg
, cmb2
, CB_GETCURSEL
, 0, 0);
974 lpdm
->u1
.s1
.dmPaperSize
= SendDlgItemMessageA(hDlg
, cmb2
,
982 DWORD Sel
= SendDlgItemMessageA(hDlg
, cmb3
, CB_GETCURSEL
, 0, 0);
984 lpdm
->dmDefaultSource
= SendDlgItemMessageA(hDlg
, cmb3
,
990 if(lppd
->Flags
& PD_PRINTSETUP
) {
991 switch (LOWORD(wParam
)) {
992 case rad1
: /* orientation */
994 if (IsDlgButtonChecked(hDlg
, rad1
) == BST_CHECKED
) {
995 if(lpdm
->u1
.s1
.dmOrientation
!= DMORIENT_PORTRAIT
) {
996 lpdm
->u1
.s1
.dmOrientation
= DMORIENT_PORTRAIT
;
997 SendDlgItemMessageA(hDlg
, ico1
, STM_SETIMAGE
,
999 (LPARAM
)PrintStructures
->hPortraitIcon
);
1002 if(lpdm
->u1
.s1
.dmOrientation
!= DMORIENT_LANDSCAPE
) {
1003 lpdm
->u1
.s1
.dmOrientation
= DMORIENT_LANDSCAPE
;
1004 SendDlgItemMessageA(hDlg
, ico1
, STM_SETIMAGE
,
1006 (LPARAM
)PrintStructures
->hLandscapeIcon
);
1015 /***********************************************************************
1016 * PrintDlgProcA [internal]
1018 BOOL WINAPI
PrintDlgProcA(HWND hDlg
, UINT uMsg
, WPARAM wParam
,
1021 PRINT_PTRA
* PrintStructures
;
1024 if (uMsg
!=WM_INITDIALOG
) {
1025 PrintStructures
= (PRINT_PTRA
*) GetWindowLongA(hDlg
, DWL_USER
);
1026 if (!PrintStructures
)
1029 PrintStructures
= (PRINT_PTRA
*) lParam
;
1030 SetWindowLongA(hDlg
, DWL_USER
, lParam
);
1031 res
= PRINTDLG_WMInitDialog(hDlg
, wParam
, PrintStructures
);
1033 if(PrintStructures
->dlg
.lpPrintDlg
->Flags
& PD_ENABLEPRINTHOOK
)
1034 res
= PrintStructures
->dlg
.lpPrintDlg
->lpfnPrintHook(
1035 hDlg
, uMsg
, wParam
, (LPARAM
)PrintStructures
->dlg
.lpPrintDlg
1040 if(PrintStructures
->dlg
.lpPrintDlg
->Flags
& PD_ENABLEPRINTHOOK
) {
1041 res
= PrintStructures
->dlg
.lpPrintDlg
->lpfnPrintHook(hDlg
,uMsg
,wParam
,
1048 return PRINTDLG_WMCommand(hDlg
, wParam
, lParam
, PrintStructures
);
1051 DestroyIcon(PrintStructures
->hCollateIcon
);
1052 DestroyIcon(PrintStructures
->hNoCollateIcon
);
1053 DestroyIcon(PrintStructures
->hPortraitIcon
);
1054 DestroyIcon(PrintStructures
->hLandscapeIcon
);
1055 if(PrintStructures
->hwndUpDown
)
1056 DestroyWindow(PrintStructures
->hwndUpDown
);
1063 /************************************************************
1065 * PRINTDLG_Get16TemplateFrom32 [Internal]
1066 * Generates a 16 bits template from the Wine 32 bits resource
1069 static HGLOBAL16
PRINTDLG_Get16TemplateFrom32(char *PrintResourceName
)
1071 HANDLE hResInfo
, hDlgTmpl32
;
1074 HGLOBAL16 hGlobal16
;
1077 if (!(hResInfo
= FindResourceA(COMMDLG_hInstance32
,
1078 PrintResourceName
, RT_DIALOGA
)))
1080 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE
);
1083 if (!(hDlgTmpl32
= LoadResource(COMMDLG_hInstance32
, hResInfo
)) ||
1084 !(template32
= LockResource( hDlgTmpl32
)))
1086 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
1089 size
= SizeofResource(COMMDLG_hInstance32
, hResInfo
);
1090 hGlobal16
= GlobalAlloc16(0, size
);
1093 COMDLG32_SetCommDlgExtendedError(CDERR_MEMALLOCFAILURE
);
1094 ERR("alloc failure for %ld bytes\n", size
);
1097 template = GlobalLock16(hGlobal16
);
1100 COMDLG32_SetCommDlgExtendedError(CDERR_MEMLOCKFAILURE
);
1101 ERR("global lock failure for %x handle\n", hGlobal16
);
1102 GlobalFree16(hGlobal16
);
1105 ConvertDialog32To16((LPVOID
)template32
, size
, (LPVOID
)template);
1106 GlobalUnlock16(hGlobal16
);
1110 /************************************************************
1112 * PRINTDLG_GetDlgTemplate
1115 static HGLOBAL
PRINTDLG_GetDlgTemplate(PRINTDLGA
*lppd
)
1117 HGLOBAL hDlgTmpl
, hResInfo
;
1119 if (lppd
->Flags
& PD_PRINTSETUP
) {
1120 if(lppd
->Flags
& PD_ENABLESETUPTEMPLATEHANDLE
) {
1121 hDlgTmpl
= lppd
->hSetupTemplate
;
1122 } else if(lppd
->Flags
& PD_ENABLESETUPTEMPLATE
) {
1123 hResInfo
= FindResourceA(lppd
->hInstance
,
1124 lppd
->lpSetupTemplateName
, RT_DIALOGA
);
1125 hDlgTmpl
= LoadResource(lppd
->hInstance
, hResInfo
);
1127 hResInfo
= FindResourceA(COMDLG32_hInstance
, "PRINT32_SETUP",
1129 hDlgTmpl
= LoadResource(COMDLG32_hInstance
, hResInfo
);
1132 if(lppd
->Flags
& PD_ENABLEPRINTTEMPLATEHANDLE
) {
1133 hDlgTmpl
= lppd
->hPrintTemplate
;
1134 } else if(lppd
->Flags
& PD_ENABLEPRINTTEMPLATE
) {
1135 hResInfo
= FindResourceA(lppd
->hInstance
,
1136 lppd
->lpPrintTemplateName
,
1138 hDlgTmpl
= LoadResource(lppd
->hInstance
, hResInfo
);
1140 hResInfo
= FindResourceA(COMDLG32_hInstance
, "PRINT32",
1142 hDlgTmpl
= LoadResource(COMDLG32_hInstance
, hResInfo
);
1148 /************************************************************
1150 * PRINTDLG_GetDlgTemplate
1153 static HGLOBAL16
PRINTDLG_GetDlgTemplate16(PRINTDLG16
*lppd
)
1155 HGLOBAL16 hDlgTmpl
, hResInfo
;
1157 if (lppd
->Flags
& PD_PRINTSETUP
) {
1158 if(lppd
->Flags
& PD_ENABLESETUPTEMPLATEHANDLE
) {
1159 hDlgTmpl
= lppd
->hSetupTemplate
;
1160 } else if(lppd
->Flags
& PD_ENABLESETUPTEMPLATE
) {
1161 hResInfo
= FindResource16(lppd
->hInstance
,
1162 MapSL(lppd
->lpSetupTemplateName
), RT_DIALOGA
);
1163 hDlgTmpl
= LoadResource16(lppd
->hInstance
, hResInfo
);
1165 hDlgTmpl
= PRINTDLG_Get16TemplateFrom32("PRINT32_SETUP");
1168 if(lppd
->Flags
& PD_ENABLEPRINTTEMPLATEHANDLE
) {
1169 hDlgTmpl
= lppd
->hPrintTemplate
;
1170 } else if(lppd
->Flags
& PD_ENABLEPRINTTEMPLATE
) {
1171 hResInfo
= FindResource16(lppd
->hInstance
,
1172 MapSL(lppd
->lpPrintTemplateName
),
1174 hDlgTmpl
= LoadResource16(lppd
->hInstance
, hResInfo
);
1176 hDlgTmpl
= PRINTDLG_Get16TemplateFrom32("PRINT32");
1182 /***********************************************************************
1187 static BOOL
PRINTDLG_CreateDC(LPPRINTDLGA lppd
)
1189 DEVNAMES
*pdn
= GlobalLock(lppd
->hDevNames
);
1190 DEVMODEA
*pdm
= GlobalLock(lppd
->hDevMode
);
1192 if(lppd
->Flags
& PD_RETURNDC
) {
1193 lppd
->hDC
= CreateDCA((char*)pdn
+ pdn
->wDriverOffset
,
1194 (char*)pdn
+ pdn
->wDeviceOffset
,
1195 (char*)pdn
+ pdn
->wOutputOffset
,
1197 } else if(lppd
->Flags
& PD_RETURNIC
) {
1198 lppd
->hDC
= CreateICA((char*)pdn
+ pdn
->wDriverOffset
,
1199 (char*)pdn
+ pdn
->wDeviceOffset
,
1200 (char*)pdn
+ pdn
->wOutputOffset
,
1203 GlobalUnlock(lppd
->hDevNames
);
1204 GlobalUnlock(lppd
->hDevMode
);
1205 return lppd
->hDC
? TRUE
: FALSE
;
1208 static BOOL
PRINTDLG_CreateDC16(LPPRINTDLG16 lppd
)
1210 DEVNAMES
*pdn
= GlobalLock16(lppd
->hDevNames
);
1211 DEVMODEA
*pdm
= GlobalLock16(lppd
->hDevMode
);
1213 if(lppd
->Flags
& PD_RETURNDC
) {
1214 lppd
->hDC
= CreateDCA((char*)pdn
+ pdn
->wDriverOffset
,
1215 (char*)pdn
+ pdn
->wDeviceOffset
,
1216 (char*)pdn
+ pdn
->wOutputOffset
,
1218 } else if(lppd
->Flags
& PD_RETURNIC
) {
1219 lppd
->hDC
= CreateICA((char*)pdn
+ pdn
->wDriverOffset
,
1220 (char*)pdn
+ pdn
->wDeviceOffset
,
1221 (char*)pdn
+ pdn
->wOutputOffset
,
1224 GlobalUnlock16(lppd
->hDevNames
);
1225 GlobalUnlock16(lppd
->hDevMode
);
1226 return lppd
->hDC
? TRUE
: FALSE
;
1229 /***********************************************************************
1230 * PrintDlgA (COMDLG32.17)
1232 * Displays the the PRINT dialog box, which enables the user to specify
1233 * specific properties of the print job.
1236 * nonzero if the user pressed the OK button
1237 * zero if the user cancelled the window or an error occurred
1241 * * The Collate Icons do not display, even though they are in the code.
1242 * * The Properties Button(s) should call DocumentPropertiesA().
1244 * * The Paper Orientation Icons are not implemented yet.
1245 * * The Properties Button(s) should call DocumentPropertiesA().
1246 * * Settings are not yet taken from a provided DevMode or
1247 * default printer settings.
1249 BOOL WINAPI
PrintDlgA(
1250 LPPRINTDLGA lppd
/* [in/out] ptr to PRINTDLG32 struct */
1255 HINSTANCE hInst
= GetWindowLongA( lppd
->hwndOwner
, GWL_HINSTANCE
);
1257 if(TRACE_ON(commdlg
)) {
1258 char flagstr
[1000] = "";
1259 struct pd_flags
*pflag
= pd_flags
;
1260 for( ; pflag
->name
; pflag
++) {
1261 if(lppd
->Flags
& pflag
->flag
)
1262 strcat(flagstr
, pflag
->name
);
1264 TRACE("(%p): hwndOwner = %08x, hDevMode = %08x, hDevNames = %08x\n"
1265 "pp. %d-%d, min p %d, max p %d, copies %d, hinst %08x\n"
1266 "flags %08lx (%s)\n",
1267 lppd
, lppd
->hwndOwner
, lppd
->hDevMode
, lppd
->hDevNames
,
1268 lppd
->nFromPage
, lppd
->nToPage
, lppd
->nMinPage
, lppd
->nMaxPage
,
1269 lppd
->nCopies
, lppd
->hInstance
, lppd
->Flags
, flagstr
);
1272 if(lppd
->lStructSize
!= sizeof(PRINTDLGA
)) {
1273 WARN("structure size failure !!!\n");
1274 COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE
);
1278 if(lppd
->Flags
& PD_RETURNDEFAULT
) {
1279 PRINTER_INFO_2A
*pbuf
;
1280 DRIVER_INFO_3A
*dbuf
;
1284 if(lppd
->hDevMode
|| lppd
->hDevNames
) {
1285 WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
1286 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE
);
1289 if(!PRINTDLG_OpenDefaultPrinter(&hprn
)) {
1290 WARN("Can't find default printer\n");
1291 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN
);
1295 GetPrinterA(hprn
, 2, NULL
, 0, &needed
);
1296 pbuf
= HeapAlloc(GetProcessHeap(), 0, needed
);
1297 GetPrinterA(hprn
, 2, (LPBYTE
)pbuf
, needed
, &needed
);
1299 GetPrinterDriverA(hprn
, NULL
, 3, NULL
, 0, &needed
);
1300 dbuf
= HeapAlloc(GetProcessHeap(),0,needed
);
1301 if (!GetPrinterDriverA(hprn
, NULL
, 3, (LPBYTE
)dbuf
, needed
, &needed
)) {
1302 ERR("GetPrinterDriverA failed, le %ld, fix your config for printer %s!\n",GetLastError(),pbuf
->pPrinterName
);
1303 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE
);
1308 PRINTDLG_CreateDevNames(&(lppd
->hDevNames
),
1312 lppd
->hDevMode
= GlobalAlloc(GMEM_MOVEABLE
, pbuf
->pDevMode
->dmSize
+
1313 pbuf
->pDevMode
->dmDriverExtra
);
1314 ptr
= GlobalLock(lppd
->hDevMode
);
1315 memcpy(ptr
, pbuf
->pDevMode
, pbuf
->pDevMode
->dmSize
+
1316 pbuf
->pDevMode
->dmDriverExtra
);
1317 GlobalUnlock(lppd
->hDevMode
);
1318 HeapFree(GetProcessHeap(), 0, pbuf
);
1319 HeapFree(GetProcessHeap(), 0, dbuf
);
1323 PRINT_PTRA
*PrintStructures
;
1325 /* load Dialog resources,
1326 * depending on Flags indicates Print32 or Print32_setup dialog
1328 hDlgTmpl
= PRINTDLG_GetDlgTemplate(lppd
);
1330 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
1333 ptr
= LockResource( hDlgTmpl
);
1335 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
1339 PrintStructures
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1340 sizeof(PRINT_PTRA
));
1341 PrintStructures
->dlg
.lpPrintDlg
= lppd
;
1343 /* and create & process the dialog .
1344 * -1 is failure, 0 is broken hwnd, everything else is ok.
1346 bRet
= (0<DialogBoxIndirectParamA(hInst
, ptr
, lppd
->hwndOwner
,
1348 (LPARAM
)PrintStructures
));
1351 DEVMODEA
*lpdm
= PrintStructures
->lpDevMode
, *lpdmReturn
;
1352 PRINTER_INFO_2A
*pi
= PrintStructures
->lpPrinterInfo
;
1353 DRIVER_INFO_3A
*di
= PrintStructures
->lpDriverInfo
;
1355 if (lppd
->hDevMode
== 0) {
1356 TRACE(" No hDevMode yet... Need to create my own\n");
1357 lppd
->hDevMode
= GlobalAlloc(GMEM_MOVEABLE
,
1358 lpdm
->dmSize
+ lpdm
->dmDriverExtra
);
1361 if((locks
= (GlobalFlags(lppd
->hDevMode
) & GMEM_LOCKCOUNT
))) {
1362 WARN("hDevMode has %d locks on it. Unlocking it now\n", locks
);
1364 GlobalUnlock(lppd
->hDevMode
);
1365 TRACE("Now got %d locks\n", locks
);
1368 lppd
->hDevMode
= GlobalReAlloc(lppd
->hDevMode
,
1369 lpdm
->dmSize
+ lpdm
->dmDriverExtra
,
1372 lpdmReturn
= GlobalLock(lppd
->hDevMode
);
1373 memcpy(lpdmReturn
, lpdm
, lpdm
->dmSize
+ lpdm
->dmDriverExtra
);
1375 if (lppd
->hDevNames
!= 0) {
1377 if((locks
= (GlobalFlags(lppd
->hDevNames
) & GMEM_LOCKCOUNT
))) {
1378 WARN("hDevNames has %d locks on it. Unlocking it now\n", locks
);
1380 GlobalUnlock(lppd
->hDevNames
);
1383 PRINTDLG_CreateDevNames(&(lppd
->hDevNames
),
1388 GlobalUnlock(lppd
->hDevMode
);
1390 HeapFree(GetProcessHeap(), 0, PrintStructures
->lpDevMode
);
1391 HeapFree(GetProcessHeap(), 0, PrintStructures
->lpPrinterInfo
);
1392 HeapFree(GetProcessHeap(), 0, PrintStructures
->lpDriverInfo
);
1393 HeapFree(GetProcessHeap(), 0, PrintStructures
);
1395 if(bRet
&& (lppd
->Flags
& PD_RETURNDC
|| lppd
->Flags
& PD_RETURNIC
))
1396 bRet
= PRINTDLG_CreateDC(lppd
);
1398 TRACE("exit! (%d)\n", bRet
);
1402 /***********************************************************************
1403 * PrintDlg16 (COMMDLG.20)
1405 * Displays the the PRINT dialog box, which enables the user to specify
1406 * specific properties of the print job.
1409 * nonzero if the user pressed the OK button
1410 * zero if the user cancelled the window or an error occurred
1413 * * calls up to the 32-bit versions of the Dialogs, which look different
1414 * * Customizing is *not* implemented.
1417 BOOL16 WINAPI
PrintDlg16(
1418 LPPRINTDLG16 lppd
/* [in/out] ptr to PRINTDLG struct */
1422 HINSTANCE hInst
= GetWindowLongA( lppd
->hwndOwner
, GWL_HINSTANCE
);
1424 if(TRACE_ON(commdlg
)) {
1425 char flagstr
[1000] = "";
1426 struct pd_flags
*pflag
= pd_flags
;
1427 for( ; pflag
->name
; pflag
++) {
1428 if(lppd
->Flags
& pflag
->flag
)
1429 strcat(flagstr
, pflag
->name
);
1431 TRACE("(%p): hwndOwner = %08x, hDevMode = %08x, hDevNames = %08x\n"
1432 "pp. %d-%d, min p %d, max p %d, copies %d, hinst %08x\n"
1433 "flags %08lx (%s)\n",
1434 lppd
, lppd
->hwndOwner
, lppd
->hDevMode
, lppd
->hDevNames
,
1435 lppd
->nFromPage
, lppd
->nToPage
, lppd
->nMinPage
, lppd
->nMaxPage
,
1436 lppd
->nCopies
, lppd
->hInstance
, lppd
->Flags
, flagstr
);
1439 if(lppd
->lStructSize
!= sizeof(PRINTDLG16
)) {
1440 ERR("structure size (%ld/%d)\n",lppd
->lStructSize
,sizeof(PRINTDLG16
));
1441 COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE
);
1445 if(lppd
->Flags
& PD_RETURNDEFAULT
) {
1446 PRINTER_INFO_2A
*pbuf
;
1447 DRIVER_INFO_3A
*dbuf
;
1451 if(lppd
->hDevMode
|| lppd
->hDevNames
) {
1452 WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
1453 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE
);
1456 if(!PRINTDLG_OpenDefaultPrinter(&hprn
)) {
1457 WARN("Can't find default printer\n");
1458 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN
);
1462 GetPrinterA(hprn
, 2, NULL
, 0, &needed
);
1463 pbuf
= HeapAlloc(GetProcessHeap(), 0, needed
);
1464 GetPrinterA(hprn
, 2, (LPBYTE
)pbuf
, needed
, &needed
);
1465 GetPrinterDriverA(hprn
, NULL
, 3, NULL
, 0, &needed
);
1466 dbuf
= HeapAlloc(GetProcessHeap(),0,needed
);
1467 if (!GetPrinterDriverA(hprn
, NULL
, 3, (LPBYTE
)dbuf
, needed
, &needed
)) {
1468 ERR("GetPrinterDriverA failed for %s, le %ld, fix your config!\n",
1469 pbuf
->pPrinterName
,GetLastError());
1470 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE
);
1474 PRINTDLG_CreateDevNames16(&(lppd
->hDevNames
),
1478 lppd
->hDevMode
= GlobalAlloc16(GMEM_MOVEABLE
,pbuf
->pDevMode
->dmSize
+
1479 pbuf
->pDevMode
->dmDriverExtra
);
1480 ptr
= GlobalLock16(lppd
->hDevMode
);
1481 memcpy(ptr
, pbuf
->pDevMode
, pbuf
->pDevMode
->dmSize
+
1482 pbuf
->pDevMode
->dmDriverExtra
);
1483 GlobalUnlock16(lppd
->hDevMode
);
1484 HeapFree(GetProcessHeap(), 0, pbuf
);
1485 HeapFree(GetProcessHeap(), 0, dbuf
);
1489 PRINT_PTRA
*PrintStructures
;
1491 /* load Dialog resources,
1492 * depending on Flags indicates Print32 or Print32_setup dialog
1494 hDlgTmpl
= PRINTDLG_GetDlgTemplate16(lppd
);
1496 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
1499 PrintStructures
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1500 sizeof(PRINT_PTRA
));
1501 PrintStructures
->dlg
.lpPrintDlg16
= lppd
;
1502 PrintStructures
->dlg
.lpPrintDlg
= (LPPRINTDLGA
)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(PRINTDLGA
));
1503 #define CVAL(x) PrintStructures->dlg.lpPrintDlg->x = lppd->x;
1504 #define MVAL(x) PrintStructures->dlg.lpPrintDlg->x = MapSL(lppd->x);
1505 CVAL(Flags
);CVAL(hwndOwner
);CVAL(hDC
);
1506 CVAL(nFromPage
);CVAL(nToPage
);CVAL(nMinPage
);CVAL(nMaxPage
);
1507 CVAL(nCopies
);CVAL(hInstance
);CVAL(lCustData
);
1508 MVAL(lpPrintTemplateName
);MVAL(lpSetupTemplateName
);
1509 /* Don't copy rest, it is 16 bit specific */
1513 PrintStructures
->lpDevMode
= HeapAlloc(GetProcessHeap(),0,sizeof(DEVMODEA
));
1515 /* and create & process the dialog .
1516 * -1 is failure, 0 is broken hwnd, everything else is ok.
1518 bRet
= (0<DialogBoxIndirectParam16(
1519 hInst
, hDlgTmpl
, lppd
->hwndOwner
,
1520 (DLGPROC16
)GetProcAddress16(GetModuleHandle16("COMMDLG"),(LPCSTR
)21),
1521 (LPARAM
)PrintStructures
1524 if (!PrintStructures
->lpPrinterInfo
) bRet
= FALSE
;
1526 DEVMODEA
*lpdm
= PrintStructures
->lpDevMode
, *lpdmReturn
;
1527 PRINTER_INFO_2A
*pi
= PrintStructures
->lpPrinterInfo
;
1528 DRIVER_INFO_3A
*di
= PrintStructures
->lpDriverInfo
;
1530 if (lppd
->hDevMode
== 0) {
1531 TRACE(" No hDevMode yet... Need to create my own\n");
1532 lppd
->hDevMode
= GlobalAlloc16(GMEM_MOVEABLE
,
1533 lpdm
->dmSize
+ lpdm
->dmDriverExtra
);
1536 if((locks
= (GlobalFlags16(lppd
->hDevMode
)&GMEM_LOCKCOUNT
))) {
1537 WARN("hDevMode has %d locks on it. Unlocking it now\n", locks
);
1539 GlobalUnlock16(lppd
->hDevMode
);
1540 TRACE("Now got %d locks\n", locks
);
1543 lppd
->hDevMode
= GlobalReAlloc16(lppd
->hDevMode
,
1544 lpdm
->dmSize
+ lpdm
->dmDriverExtra
,
1547 lpdmReturn
= GlobalLock16(lppd
->hDevMode
);
1548 memcpy(lpdmReturn
, lpdm
, lpdm
->dmSize
+ lpdm
->dmDriverExtra
);
1550 if (lppd
->hDevNames
!= 0) {
1552 if((locks
= (GlobalFlags16(lppd
->hDevNames
)&GMEM_LOCKCOUNT
))) {
1553 WARN("hDevNames has %d locks on it. Unlocking it now\n", locks
);
1555 GlobalUnlock16(lppd
->hDevNames
);
1558 PRINTDLG_CreateDevNames16(&(lppd
->hDevNames
),
1563 GlobalUnlock16(lppd
->hDevMode
);
1565 if (!(lppd
->Flags
& (PD_ENABLESETUPTEMPLATEHANDLE
| PD_ENABLESETUPTEMPLATE
)))
1566 GlobalFree16(hDlgTmpl
); /* created from the 32 bits resource */
1567 HeapFree(GetProcessHeap(), 0, PrintStructures
->lpDevMode
);
1568 HeapFree(GetProcessHeap(), 0, PrintStructures
->lpPrinterInfo
);
1569 HeapFree(GetProcessHeap(), 0, PrintStructures
->lpDriverInfo
);
1570 HeapFree(GetProcessHeap(), 0, PrintStructures
);
1572 if(bRet
&& (lppd
->Flags
& PD_RETURNDC
|| lppd
->Flags
& PD_RETURNIC
))
1573 bRet
= PRINTDLG_CreateDC16(lppd
);
1575 TRACE("exit! (%d)\n", bRet
);
1581 /***********************************************************************
1582 * PrintDlgW (COMDLG32.18)
1584 BOOL WINAPI
PrintDlgW( LPPRINTDLGW printdlg
)
1586 FIXME("A really empty stub\n" );
1590 /***********************************************************************
1595 /***********************************************************************
1596 * PageSetupDlgA (COMDLG32.15)
1598 BOOL WINAPI
PageSetupDlgA(LPPAGESETUPDLGA setupdlg
) {
1599 FIXME("(%p), stub!\n",setupdlg
);
1602 /***********************************************************************
1603 * PageSetupDlgW (COMDLG32.16)
1605 BOOL WINAPI
PageSetupDlgW(LPPAGESETUPDLGW setupdlg
) {
1606 FIXME("(%p), stub!\n",setupdlg
);
1610 /**********************************************************************
1615 /***********************************************************************
1616 * PrintDlgProc16 (COMMDLG.21)
1618 LRESULT WINAPI
PrintDlgProc16(HWND16 hDlg
, UINT16 uMsg
, WPARAM16 wParam
,
1621 PRINT_PTRA
* PrintStructures
;
1624 if (uMsg
!=WM_INITDIALOG
) {
1625 PrintStructures
= (PRINT_PTRA
*) GetWindowLongA(hDlg
, DWL_USER
);
1626 if (!PrintStructures
)
1629 PrintStructures
= (PRINT_PTRA
*) lParam
;
1630 SetWindowLongA(hDlg
, DWL_USER
, lParam
);
1631 res
= PRINTDLG_WMInitDialog16(hDlg
, wParam
, PrintStructures
);
1633 if(PrintStructures
->dlg
.lpPrintDlg16
->Flags
& PD_ENABLEPRINTHOOK
) {
1634 res
= CallWindowProc16(
1635 (WNDPROC16
)PrintStructures
->dlg
.lpPrintDlg16
->lpfnPrintHook
,
1636 hDlg
, uMsg
, wParam
, (LPARAM
)PrintStructures
->dlg
.lpPrintDlg16
1642 if(PrintStructures
->dlg
.lpPrintDlg16
->Flags
& PD_ENABLEPRINTHOOK
) {
1643 res
= CallWindowProc16(
1644 (WNDPROC16
)PrintStructures
->dlg
.lpPrintDlg16
->lpfnPrintHook
,
1645 hDlg
,uMsg
, wParam
, lParam
1647 if(LOWORD(res
)) return res
;
1652 return PRINTDLG_WMCommand(hDlg
, wParam
, lParam
, PrintStructures
);
1655 DestroyIcon(PrintStructures
->hCollateIcon
);
1656 DestroyIcon(PrintStructures
->hNoCollateIcon
);
1657 /* FIXME: don't forget to delete the paper orientation icons here! */
1665 /***********************************************************************
1666 * PrintSetupDlgProc16 (COMMDLG.22)
1668 LRESULT WINAPI
PrintSetupDlgProc16(HWND16 hWnd
, UINT16 wMsg
, WPARAM16 wParam
,
1674 TRACE("WM_INITDIALOG lParam=%08lX\n", lParam
);
1675 ShowWindow(hWnd
, SW_SHOWNORMAL
);
1680 EndDialog(hWnd
, TRUE
);
1683 EndDialog(hWnd
, FALSE
);
1692 /***********************************************************************
1695 HRESULT WINAPI
PrintDlgExA(LPVOID lpPrintDlgExA
) /* [???] FIXME: LPPRINTDLGEXA */
1700 /***********************************************************************
1703 HRESULT WINAPI
PrintDlgExW(LPVOID lpPrintDlgExW
) /* [???] FIXME: LPPRINTDLGEXW */