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"
23 #include "debugtools.h"
29 DEFAULT_DEBUG_CHANNEL(commdlg);
34 /* This PRINTDLGA internal structure stores
35 * pointers to several throughout useful structures.
41 LPPRINTDLGA lpPrintDlg;
42 LPPRINTER_INFO_2A lpPrinterInfo;
44 HICON hCollateIcon; /* PrintDlg only */
45 HICON hNoCollateIcon; /* PrintDlg only */
46 HICON hPortraitIcon; /* PrintSetupDlg only */
47 HICON hLandscapeIcon; /* PrintSetupDlg only */
51 static struct pd_flags {
55 {PD_SELECTION, "PD_SELECTION "},
56 {PD_PAGENUMS, "PD_PAGENUMS "},
57 {PD_NOSELECTION, "PD_NOSELECTION "},
58 {PD_NOPAGENUMS, "PD_NOPAGENUMS "},
59 {PD_COLLATE, "PD_COLLATE "},
60 {PD_PRINTTOFILE, "PD_PRINTTOFILE "},
61 {PD_PRINTSETUP, "PD_PRINTSETUP "},
62 {PD_NOWARNING, "PD_NOWARNING "},
63 {PD_RETURNDC, "PD_RETURNDC "},
64 {PD_RETURNIC, "PD_RETURNIC "},
65 {PD_RETURNDEFAULT, "PD_RETURNDEFAULT "},
66 {PD_SHOWHELP, "PD_SHOWHELP "},
67 {PD_ENABLEPRINTHOOK, "PD_ENABLEPRINTHOOK "},
68 {PD_ENABLESETUPHOOK, "PD_ENABLESETUPHOOK "},
69 {PD_ENABLEPRINTTEMPLATE, "PD_ENABLEPRINTTEMPLATE "},
70 {PD_ENABLESETUPTEMPLATE, "PD_ENABLESETUPTEMPLATE "},
71 {PD_ENABLEPRINTTEMPLATEHANDLE, "PD_ENABLEPRINTTEMPLATEHANDLE "},
72 {PD_ENABLESETUPTEMPLATEHANDLE, "PD_ENABLESETUPTEMPLATEHANDLE "},
73 {PD_USEDEVMODECOPIES, "PD_USEDEVMODECOPIES[ANDCOLLATE] "},
74 {PD_DISABLEPRINTTOFILE, "PD_DISABLEPRINTTOFILE "},
75 {PD_HIDEPRINTTOFILE, "PD_HIDEPRINTTOFILE "},
76 {PD_NONETWORKBUTTON, "PD_NONETWORKBUTTON "},
81 /***********************************************************************
82 * PRINTDLG_GetDefaultPrinterName
84 * Returns the default printer name in buf.
85 * Even under WinNT/2000 default printer is retrieved via GetProfileString -
86 * these entries are mapped somewhere in the registry rather than win.ini.
88 * Returns TRUE on success else FALSE
90 static BOOL PRINTDLG_GetDefaultPrinterName(LPSTR buf, DWORD len)
94 if(!GetProfileStringA("windows", "device", "", buf, len))
96 if((ptr = strchr(buf, ',')) == NULL)
102 /***********************************************************************
103 * PRINTDLG_OpenDefaultPrinter
105 * Returns a winspool printer handle to the default printer in *hprn
106 * Caller must call ClosePrinter on the handle
108 * Returns TRUE on success else FALSE
110 static BOOL PRINTDLG_OpenDefaultPrinter(HANDLE *hprn)
113 if(!PRINTDLG_GetDefaultPrinterName(buf, sizeof(buf)))
115 return OpenPrinterA(buf, hprn, NULL);
118 /***********************************************************************
119 * PRINTDLG_SetUpPrinterListCombo
121 * Initializes printer list combox.
122 * hDlg: HWND of dialog
123 * id: Control id of combo
124 * name: Name of printer to select
126 * Initializes combo with list of available printers. Selects printer 'name'
127 * If name is NULL or does not exist select the default printer.
129 * Returns number of printers added to list.
131 static INT PRINTDLG_SetUpPrinterListCombo(HWND hDlg, UINT id, LPCSTR name)
135 LPPRINTER_INFO_2A pi;
136 EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
137 pi = HeapAlloc(GetProcessHeap(), 0, needed);
138 EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pi, needed, &needed,
141 for(i = 0; i < num; i++) {
142 SendDlgItemMessageA(hDlg, id, CB_ADDSTRING, 0,
143 (LPARAM)pi[i].pPrinterName );
145 HeapFree(GetProcessHeap(), 0, pi);
147 (i = SendDlgItemMessageA(hDlg, id, CB_FINDSTRINGEXACT, -1,
148 (LPARAM)name)) == CB_ERR) {
151 TRACE("Can't find '%s' in printer list so trying to find default\n",
153 if(!PRINTDLG_GetDefaultPrinterName(buf, sizeof(buf)))
155 i = SendDlgItemMessageA(hDlg, id, CB_FINDSTRINGEXACT, -1, (LPARAM)buf);
157 TRACE("Can't find default printer in printer list\n");
159 SendDlgItemMessageA(hDlg, id, CB_SETCURSEL, i, 0);
163 /***********************************************************************
164 * PRINTDLG_CreateDevNames [internal]
167 * creates a DevNames structure.
169 * (NB. when we handle unicode the offsets will be in wchars).
171 static BOOL PRINTDLG_CreateDevNames(HGLOBAL *hmem, char* DeviceDriverName,
172 char* DeviceName, char* OutputPort)
175 char* pDevNamesSpace;
177 LPDEVNAMES lpDevNames;
180 size = strlen(DeviceDriverName) + 1
181 + strlen(DeviceName) + 1
182 + strlen(OutputPort) + 1
186 *hmem = GlobalReAlloc(*hmem, size, GMEM_MOVEABLE);
188 *hmem = GlobalAlloc(GMEM_MOVEABLE, size);
192 pDevNamesSpace = GlobalLock(*hmem);
193 lpDevNames = (LPDEVNAMES) pDevNamesSpace;
195 pTempPtr = pDevNamesSpace + sizeof(DEVNAMES);
196 strcpy(pTempPtr, DeviceDriverName);
197 lpDevNames->wDriverOffset = pTempPtr - pDevNamesSpace;
199 pTempPtr += strlen(DeviceDriverName) + 1;
200 strcpy(pTempPtr, DeviceName);
201 lpDevNames->wDeviceOffset = pTempPtr - pDevNamesSpace;
203 pTempPtr += strlen(DeviceName) + 1;
204 strcpy(pTempPtr, OutputPort);
205 lpDevNames->wOutputOffset = pTempPtr - pDevNamesSpace;
207 PRINTDLG_GetDefaultPrinterName(buf, sizeof(buf));
208 lpDevNames->wDefault = (strcmp(buf, DeviceName) == 0) ? 1 : 0;
213 /***********************************************************************
214 * PRINTDLG_UpdatePrintDlg [internal]
217 * updates the PrintDlg structure for returnvalues.
220 * FALSE if user is not allowed to close (i.e. wrong nTo or nFrom values)
223 static BOOL PRINTDLG_UpdatePrintDlg(HWND hDlg,
224 PRINT_PTRA* PrintStructures)
226 LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
227 PDEVMODEA lpdm = PrintStructures->lpDevMode;
228 LPPRINTER_INFO_2A pi = PrintStructures->lpPrinterInfo;
231 if(!lpdm) return FALSE;
234 if(!(lppd->Flags & PD_PRINTSETUP)) {
235 /* check whether nFromPage and nToPage are within range defined by
236 * nMinPage and nMaxPage
238 if (IsDlgButtonChecked(hDlg, rad3) == BST_CHECKED) { /* Pages */
241 nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
242 nToPage = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
243 if (nFromPage < lppd->nMinPage || nFromPage > lppd->nMaxPage ||
244 nToPage < lppd->nMinPage || nToPage > lppd->nMaxPage) {
245 char resourcestr[256];
247 LoadStringA(COMDLG32_hInstance, PD32_INVALID_PAGE_RANGE,
249 sprintf(resultstr,resourcestr, lppd->nMinPage, lppd->nMaxPage);
250 LoadStringA(COMDLG32_hInstance, PD32_PRINT_TITLE,
252 MessageBoxA(hDlg, resultstr, resourcestr,
253 MB_OK | MB_ICONWARNING);
256 lppd->nFromPage = nFromPage;
257 lppd->nToPage = nToPage;
260 if (IsDlgButtonChecked(hDlg, chx1) == BST_CHECKED) {/* Print to file */
261 lppd->Flags |= PD_PRINTTOFILE;
262 pi->pPortName = "FILE:";
265 if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED) { /* Collate */
266 FIXME("Collate lppd not yet implemented as output\n");
269 /* set PD_Collate and nCopies */
270 if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
271 /* The application doesn't support multiple copies or collate...
273 lppd->Flags &= ~PD_COLLATE;
275 /* if the printer driver supports it... store info there
276 * otherwise no collate & multiple copies !
278 if (lpdm->dmFields & DM_COLLATE)
280 (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED);
281 if (lpdm->dmFields & DM_COPIES)
282 lpdm->dmCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
284 if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
285 lppd->Flags |= PD_COLLATE;
287 lppd->Flags &= ~PD_COLLATE;
288 lppd->nCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
295 /************************************************************************
296 * PRINTDLG_SetUpPaperComboBox
298 * Initialize either the papersize or inputslot combos of the Printer Setup
299 * dialog. We store the associated word (eg DMPAPER_A4) as the item data.
300 * We also try to re-select the old selection.
302 static BOOL PRINTDLG_SetUpPaperComboBox(HWND hDlg,
315 int fwCapability_Names;
316 int fwCapability_Words;
318 TRACE(" Printer: %s, ComboID: %d\n",PrinterName,nIDComboBox);
320 /* query the dialog box for the current selected value */
321 Sel = SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETCURSEL, 0, 0);
323 oldWord = SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA, Sel,
327 if (nIDComboBox == cmb2) {
329 fwCapability_Names = DC_PAPERNAMES;
330 fwCapability_Words = DC_PAPERS;
334 fwCapability_Names = DC_BINNAMES;
335 fwCapability_Words = DC_BINS;
338 /* for some printer drivers, DeviceCapabilities calls a VXD to obtain the
339 * paper settings. As Wine doesn't allow VXDs, this results in a crash.
341 WARN(" if your printer driver uses VXDs, expect a crash now!\n");
342 NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
343 fwCapability_Names, NULL, dm);
344 if (NrOfEntries == 0)
345 WARN("no Name Entries found!\n");
347 if(DeviceCapabilitiesA(PrinterName, PortName, fwCapability_Words, NULL, dm)
349 ERR("Number of caps is different\n");
353 Names = HeapAlloc(GetProcessHeap(),0, NrOfEntries*NamesSize);
354 Words = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(WORD));
355 NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
356 fwCapability_Names, Names, dm);
357 NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
358 fwCapability_Words, (LPSTR)Words, dm);
360 /* reset any current content in the combobox */
361 SendDlgItemMessageA(hDlg, nIDComboBox, CB_RESETCONTENT, 0, 0);
363 /* store new content */
364 for (i = 0; i < NrOfEntries; i++) {
365 DWORD pos = SendDlgItemMessageA(hDlg, nIDComboBox, CB_ADDSTRING, 0,
366 (LPARAM)(&Names[i*NamesSize]) );
367 SendDlgItemMessageA(hDlg, nIDComboBox, CB_SETITEMDATA, pos,
371 /* Look for old selection - can't do this is previous loop since
372 item order will change as more items are added */
374 for (i = 0; i < NrOfEntries; i++) {
375 if(SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) ==
381 SendDlgItemMessageA(hDlg, nIDComboBox, CB_SETCURSEL, Sel, 0);
383 HeapFree(GetProcessHeap(),0,Words);
384 HeapFree(GetProcessHeap(),0,Names);
388 /***********************************************************************
389 * PRINTDLG_UpdatePrinterInfoTexts [internal]
391 static void PRINTDLG_UpdatePrinterInfoTexts(HWND hDlg, LPPRINTER_INFO_2A pi)
394 char ResourceString[256];
400 /* add all status messages */
401 for (i = 0; i < 25; i++) {
402 if (pi->Status & (1<<i)) {
403 LoadStringA(COMDLG32_hInstance, PD32_PRINTER_STATUS_PAUSED+i,
404 ResourceString, 255);
405 strcat(StatusMsg,ResourceString);
409 /* FIXME: status==ready must only be appended if really so.
410 but how to detect? */
411 LoadStringA(COMDLG32_hInstance, PD32_PRINTER_STATUS_READY,
412 ResourceString, 255);
413 strcat(StatusMsg,ResourceString);
415 SendDlgItemMessageA(hDlg, stc12, WM_SETTEXT, 0, (LPARAM)StatusMsg);
417 /* set all other printer info texts */
418 SendDlgItemMessageA(hDlg, stc11, WM_SETTEXT, 0, (LPARAM)pi->pDriverName);
419 if (pi->pLocation != NULL && pi->pLocation[0] != '\0')
420 SendDlgItemMessageA(hDlg, stc14, WM_SETTEXT, 0,(LPARAM)pi->pLocation);
422 SendDlgItemMessageA(hDlg, stc14, WM_SETTEXT, 0,(LPARAM)pi->pPortName);
423 SendDlgItemMessageA(hDlg, stc13, WM_SETTEXT, 0, (LPARAM)pi->pComment);
428 /*******************************************************************
430 * PRINTDLG_ChangePrinter
433 static BOOL PRINTDLG_ChangePrinter(HWND hDlg, char *name,
434 PRINT_PTRA *PrintStructures)
436 LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
437 LPDEVMODEA lpdm = NULL;
442 if(PrintStructures->lpPrinterInfo)
443 HeapFree(GetProcessHeap(),0, PrintStructures->lpPrinterInfo);
444 if(!OpenPrinterA(name, &hprn, NULL)) {
445 ERR("Can't open printer %s\n", name);
448 GetPrinterA(hprn, 2, NULL, 0, &needed);
449 PrintStructures->lpPrinterInfo = HeapAlloc(GetProcessHeap(),0,needed);
450 GetPrinterA(hprn, 2, (LPBYTE)PrintStructures->lpPrinterInfo, needed,
454 PRINTDLG_UpdatePrinterInfoTexts(hDlg, PrintStructures->lpPrinterInfo);
456 if(PrintStructures->lpDevMode) {
457 HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
458 PrintStructures->lpDevMode = NULL;
461 dmSize = DocumentPropertiesA(0, 0, name, NULL, NULL, 0);
463 ERR("DocumentProperties fails on %s\n", debugstr_a(name));
466 PrintStructures->lpDevMode = HeapAlloc(GetProcessHeap(), 0, dmSize);
467 dmSize = DocumentPropertiesA(0, 0, name, PrintStructures->lpDevMode, NULL,
469 if(lppd->hDevMode && (lpdm = GlobalLock(lppd->hDevMode)) &&
470 !strcmp(lpdm->dmDeviceName,
471 PrintStructures->lpDevMode->dmDeviceName)) {
472 /* Supplied devicemode matches current printer so try to use it */
473 DocumentPropertiesA(0, 0, name, PrintStructures->lpDevMode, lpdm,
474 DM_OUT_BUFFER | DM_IN_BUFFER);
477 GlobalUnlock(lppd->hDevMode);
479 lpdm = PrintStructures->lpDevMode; /* use this as a shortcut */
481 if(!(lppd->Flags & PD_PRINTSETUP)) {
482 /* Print range (All/Range/Selection) */
483 SetDlgItemInt(hDlg, edt1, lppd->nFromPage, FALSE);
484 SetDlgItemInt(hDlg, edt2, lppd->nToPage, FALSE);
485 CheckRadioButton(hDlg, rad1, rad3, rad1); /* default */
486 if (lppd->Flags & PD_NOSELECTION)
487 EnableWindow(GetDlgItem(hDlg, rad2), FALSE);
489 if (lppd->Flags & PD_SELECTION)
490 CheckRadioButton(hDlg, rad1, rad3, rad2);
491 if (lppd->Flags & PD_NOPAGENUMS) {
492 EnableWindow(GetDlgItem(hDlg, rad3), FALSE);
493 EnableWindow(GetDlgItem(hDlg, stc2),FALSE);
494 EnableWindow(GetDlgItem(hDlg, edt1), FALSE);
495 EnableWindow(GetDlgItem(hDlg, stc3),FALSE);
496 EnableWindow(GetDlgItem(hDlg, edt2), FALSE);
498 if (lppd->Flags & PD_PAGENUMS)
499 CheckRadioButton(hDlg, rad1, rad3, rad3);
501 /* "All xxx pages"... */
503 char resourcestr[64];
505 LoadStringA(COMDLG32_hInstance, PD32_PRINT_ALL_X_PAGES,
507 sprintf(result,resourcestr,lppd->nMaxPage - lppd->nMinPage + 1);
508 SendDlgItemMessageA(hDlg, rad1, WM_SETTEXT, 0, (LPARAM) result);
513 * FIXME: The ico3 is not displayed for some reason. I don't know why.
515 if (lppd->Flags & PD_COLLATE) {
516 SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
517 (LPARAM)PrintStructures->hCollateIcon);
518 CheckDlgButton(hDlg, chx2, 1);
520 SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
521 (LPARAM)PrintStructures->hNoCollateIcon);
522 CheckDlgButton(hDlg, chx2, 0);
525 if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
526 /* if printer doesn't support it: no Collate */
527 if (!(lpdm->dmFields & DM_COLLATE)) {
528 EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
529 EnableWindow(GetDlgItem(hDlg, ico3), FALSE);
534 if (lppd->hDevMode == 0)
535 SetDlgItemInt(hDlg, edt3, lppd->nCopies, FALSE);
537 SetDlgItemInt(hDlg, edt3, lpdm->dmCopies, FALSE);
539 if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
540 /* if printer doesn't support it: no nCopies */
541 if (!(lpdm->dmFields & DM_COPIES)) {
542 EnableWindow(GetDlgItem(hDlg, edt3), FALSE);
543 EnableWindow(GetDlgItem(hDlg, stc5), FALSE);
548 CheckDlgButton(hDlg, chx1, (lppd->Flags & PD_PRINTTOFILE) ? 1 : 0);
549 if (lppd->Flags & PD_DISABLEPRINTTOFILE)
550 EnableWindow(GetDlgItem(hDlg, chx1), FALSE);
551 if (lppd->Flags & PD_HIDEPRINTTOFILE)
552 ShowWindow(GetDlgItem(hDlg, chx1), SW_HIDE);
554 } else { /* PD_PRINTSETUP */
555 PRINTDLG_SetUpPaperComboBox(hDlg, cmb2,
556 PrintStructures->lpPrinterInfo->pPrinterName,
557 PrintStructures->lpPrinterInfo->pPortName,
559 PRINTDLG_SetUpPaperComboBox(hDlg, cmb3,
560 PrintStructures->lpPrinterInfo->pPrinterName,
561 PrintStructures->lpPrinterInfo->pPortName,
563 CheckRadioButton(hDlg, rad1, rad2,
564 (lpdm->u1.s1.dmOrientation == DMORIENT_PORTRAIT) ?
569 if ((lppd->Flags & PD_SHOWHELP)==0) {
570 /* hide if PD_SHOWHELP not specified */
571 ShowWindow(GetDlgItem(hDlg, pshHelp), SW_HIDE);
577 /***********************************************************************
578 * PRINTDLG_WMInitDialog [internal]
580 static LRESULT PRINTDLG_WMInitDialog(HWND hDlg, WPARAM wParam,
581 PRINT_PTRA* PrintStructures)
583 LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
587 UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
589 /* load Collate ICONs */
590 PrintStructures->hCollateIcon =
591 LoadIconA(COMDLG32_hInstance, "PD32_COLLATE");
592 PrintStructures->hNoCollateIcon =
593 LoadIconA(COMDLG32_hInstance, "PD32_NOCOLLATE");
594 if(PrintStructures->hCollateIcon == 0 ||
595 PrintStructures->hNoCollateIcon == 0) {
596 ERR("no icon in resourcefile\n");
597 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
598 EndDialog(hDlg, FALSE);
601 /* load Paper Orientation ICON */
602 /* FIXME: not implemented yet */
605 * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
606 * must be registered and the Help button must be shown.
608 if (lppd->Flags & PD_SHOWHELP) {
609 if((PrintStructures->HelpMessageID =
610 RegisterWindowMessageA(HELPMSGSTRING)) == 0) {
611 COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL);
615 PrintStructures->HelpMessageID = 0;
617 /* FIXME: I allow more freedom than either Win95 or WinNT,
618 * which do not agree to what errors should be thrown or not
619 * in case nToPage or nFromPage is out-of-range.
621 if (lppd->nMaxPage < lppd->nMinPage)
622 lppd->nMaxPage = lppd->nMinPage;
623 if (lppd->nMinPage == lppd->nMaxPage)
624 lppd->Flags |= PD_NOPAGENUMS;
625 if (lppd->nToPage < lppd->nMinPage)
626 lppd->nToPage = lppd->nMinPage;
627 if (lppd->nToPage > lppd->nMaxPage)
628 lppd->nToPage = lppd->nMaxPage;
629 if (lppd->nFromPage < lppd->nMinPage)
630 lppd->nFromPage = lppd->nMinPage;
631 if (lppd->nFromPage > lppd->nMaxPage)
632 lppd->nFromPage = lppd->nMaxPage;
636 pdn = GlobalLock(lppd->hDevNames);
637 pdm = GlobalLock(lppd->hDevMode);
639 name = (char*)pdn + pdn->wDeviceOffset;
641 name = pdm->dmDeviceName;
642 PRINTDLG_SetUpPrinterListCombo(hDlg, comboID, name);
643 if(pdm) GlobalUnlock(lppd->hDevMode);
644 if(pdn) GlobalUnlock(lppd->hDevNames);
646 /* Now find selected printer and update rest of dlg */
647 name = HeapAlloc(GetProcessHeap(),0,256);
648 GetDlgItemTextA(hDlg, comboID, name, 255);
649 PRINTDLG_ChangePrinter(hDlg, name, PrintStructures);
650 HeapFree(GetProcessHeap(),0,name);
655 /***********************************************************************
656 * PRINTDLG_WMCommand [internal]
658 static LRESULT PRINTDLG_WMCommand(HWND hDlg, WPARAM wParam,
659 LPARAM lParam, PRINT_PTRA* PrintStructures)
661 LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
662 UINT PrinterComboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
663 LPDEVMODEA lpdm = PrintStructures->lpDevMode;
665 switch (LOWORD(wParam)) {
667 TRACE(" OK button was hit\n");
668 if (PRINTDLG_UpdatePrintDlg(hDlg, PrintStructures)!=TRUE)
670 EndDialog(hDlg, TRUE);
674 TRACE(" CANCEL button was hit\n");
675 EndDialog(hDlg, FALSE);
679 TRACE(" HELP button was hit\n");
680 SendMessageA(lppd->hwndOwner, PrintStructures->HelpMessageID,
681 (WPARAM) hDlg, (LPARAM) lppd);
684 case chx2: /* collate pages checkbox */
685 if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
686 SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
687 (LPARAM)PrintStructures->hCollateIcon);
689 SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
690 (LPARAM)PrintStructures->hNoCollateIcon);
692 case edt1: /* from page nr editbox */
693 case edt2: /* to page nr editbox */
694 if (HIWORD(wParam)==EN_CHANGE) {
697 nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
698 nToPage = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
699 if (nFromPage != lppd->nFromPage || nToPage != lppd->nToPage)
700 CheckRadioButton(hDlg, rad1, rad3, rad3);
703 case psh2: /* Properties button */
706 char PrinterName[256];
708 GetDlgItemTextA(hDlg, PrinterComboID, PrinterName, 255);
709 if (!OpenPrinterA(PrinterName, &hPrinter, NULL)) {
710 WARN(" Call to OpenPrinter did not succeed!\n");
713 DocumentPropertiesA(hDlg, hPrinter, PrinterName,
714 PrintStructures->lpDevMode,
715 PrintStructures->lpDevMode,
716 DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
717 ClosePrinter(hPrinter);
722 case cmb4: /* Printer combobox */
723 if (HIWORD(wParam)==CBN_SELCHANGE) {
724 char PrinterName[256];
725 GetDlgItemTextA(hDlg, LOWORD(wParam), PrinterName, 255);
726 PRINTDLG_ChangePrinter(hDlg, PrinterName, PrintStructures);
730 case cmb2: /* Papersize */
732 DWORD Sel = SendDlgItemMessageA(hDlg, cmb2, CB_GETCURSEL, 0, 0);
734 lpdm->u1.s1.dmPaperSize = SendDlgItemMessageA(hDlg, cmb2,
742 DWORD Sel = SendDlgItemMessageA(hDlg, cmb3, CB_GETCURSEL, 0, 0);
744 lpdm->dmDefaultSource = SendDlgItemMessageA(hDlg, cmb3,
753 /***********************************************************************
754 * PrintDlgProcA [internal]
756 BOOL WINAPI PrintDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam,
759 PRINT_PTRA* PrintStructures;
762 if (uMsg!=WM_INITDIALOG) {
763 PrintStructures = (PRINT_PTRA*) GetWindowLongA(hDlg, DWL_USER);
764 if (!PrintStructures)
767 PrintStructures = (PRINT_PTRA*) lParam;
768 SetWindowLongA(hDlg, DWL_USER, lParam);
769 res = PRINTDLG_WMInitDialog(hDlg, wParam, PrintStructures);
771 if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK) {
772 res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg, uMsg,
774 (LPARAM)PrintStructures->lpPrintDlg);
779 if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK) {
780 res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg, uMsg, wParam,
787 return PRINTDLG_WMCommand(hDlg, wParam, lParam, PrintStructures);
790 DestroyIcon(PrintStructures->hCollateIcon);
791 DestroyIcon(PrintStructures->hNoCollateIcon);
792 /* FIXME: don't forget to delete the paper orientation icons here! */
799 /************************************************************
801 * PRINTDLG_GetDlgTemplate
804 static HGLOBAL PRINTDLG_GetDlgTemplate(PRINTDLGA *lppd)
806 HGLOBAL hDlgTmpl, hResInfo;
808 if (lppd->Flags & PD_PRINTSETUP) {
809 if(lppd->Flags & PD_ENABLESETUPTEMPLATEHANDLE) {
810 hDlgTmpl = lppd->hSetupTemplate;
811 } else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) {
812 hResInfo = FindResourceA(lppd->hInstance,
813 lppd->lpSetupTemplateName, RT_DIALOGA);
814 hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
816 hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32_SETUP",
818 hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
821 if(lppd->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) {
822 hDlgTmpl = lppd->hPrintTemplate;
823 } else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) {
824 hResInfo = FindResourceA(lppd->hInstance,
825 lppd->lpPrintTemplateName,
827 hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
829 hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32",
831 hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
837 /***********************************************************************
842 static BOOL PRINTDLG_CreateDC(LPPRINTDLGA lppd)
844 DEVNAMES *pdn = GlobalLock(lppd->hDevNames);
845 DEVMODEA *pdm = GlobalLock(lppd->hDevMode);
847 if(lppd->Flags & PD_RETURNDC) {
848 lppd->hDC = CreateDCA((char*)pdn + pdn->wDriverOffset,
849 (char*)pdn + pdn->wDeviceOffset,
850 (char*)pdn + pdn->wOutputOffset,
852 } else if(lppd->Flags & PD_RETURNIC) {
853 lppd->hDC = CreateICA((char*)pdn + pdn->wDriverOffset,
854 (char*)pdn + pdn->wDeviceOffset,
855 (char*)pdn + pdn->wOutputOffset,
858 GlobalUnlock(lppd->hDevNames);
859 GlobalUnlock(lppd->hDevMode);
860 return lppd->hDC ? TRUE : FALSE;
863 /***********************************************************************
864 * PrintDlgA (COMDLG32.17)
866 * Displays the the PRINT dialog box, which enables the user to specify
867 * specific properties of the print job.
870 * nonzero if the user pressed the OK button
871 * zero if the user cancelled the window or an error occurred
875 * * The Collate Icons do not display, even though they are in the code.
876 * * The Properties Button(s) should call DocumentPropertiesA().
878 * * The Paper Orientation Icons are not implemented yet.
879 * * The Properties Button(s) should call DocumentPropertiesA().
880 * * Settings are not yet taken from a provided DevMode or
881 * default printer settings.
883 BOOL WINAPI PrintDlgA(
884 LPPRINTDLGA lppd /* ptr to PRINTDLG32 struct */
889 HINSTANCE hInst = GetWindowLongA( lppd->hwndOwner, GWL_HINSTANCE );
891 if(TRACE_ON(commdlg)) {
892 char flagstr[1000] = "";
893 struct pd_flags *pflag = pd_flags;
894 for( ; pflag->name; pflag++) {
895 if(lppd->Flags & pflag->flag)
896 strcat(flagstr, pflag->name);
898 TRACE("(%p): hwndOwner = %08x, hDevMode = %08x, hDevNames = %08x\n"
899 "pp. %d-%d, min p %d, max p %d, copies %d, hinst %08x\n"
900 "flags %08lx (%s)\n",
901 lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
902 lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
903 lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
906 if(lppd->lStructSize != sizeof(PRINTDLGA)) {
907 WARN("structure size failure !!!\n");
908 COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
912 if(lppd->Flags & PD_RETURNDEFAULT) {
913 PRINTER_INFO_2A *pbuf;
917 if(lppd->hDevMode || lppd->hDevNames) {
918 WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
919 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
922 if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
923 WARN("Can't find default printer\n");
924 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
928 GetPrinterA(hprn, 2, NULL, 0, &needed);
929 pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
930 GetPrinterA(hprn, 2, (LPBYTE)pbuf, needed, &needed);
932 PRINTDLG_CreateDevNames(&(lppd->hDevNames), "winspool",
933 pbuf->pDevMode->dmDeviceName,
935 lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
936 pbuf->pDevMode->dmDriverExtra);
937 ptr = GlobalLock(lppd->hDevMode);
938 memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
939 pbuf->pDevMode->dmDriverExtra);
940 GlobalUnlock(lppd->hDevMode);
941 HeapFree(GetProcessHeap(), 0, pbuf);
945 PRINT_PTRA *PrintStructures;
947 /* load Dialog resources,
948 * depending on Flags indicates Print32 or Print32_setup dialog
950 hDlgTmpl = PRINTDLG_GetDlgTemplate(lppd);
951 if (!(hDlgTmpl) || !(ptr = LockResource( hDlgTmpl ))) {
952 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
955 PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
957 PrintStructures->lpPrintDlg = lppd;
959 /* and create & process the dialog
961 bRet = DialogBoxIndirectParamA(hInst, ptr, lppd->hwndOwner,
963 (LPARAM)PrintStructures);
966 DEVMODEA *lpdm = PrintStructures->lpDevMode, *lpdmReturn;
967 PRINTER_INFO_2A *pi = PrintStructures->lpPrinterInfo;
969 if (lppd->hDevMode == 0) {
970 TRACE(" No hDevMode yet... Need to create my own\n");
971 lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE,
972 lpdm->dmSize + lpdm->dmDriverExtra);
975 if((locks = (GlobalFlags(lppd->hDevMode) & GMEM_LOCKCOUNT))) {
976 WARN("hDevMode has %d locks on it. Unlocking it now\n", locks);
978 GlobalUnlock(lppd->hDevMode);
979 TRACE("Now got %d locks\n", locks);
982 lppd->hDevMode = GlobalReAlloc(lppd->hDevMode,
983 lpdm->dmSize + lpdm->dmDriverExtra,
986 lpdmReturn = GlobalLock(lppd->hDevMode);
987 memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra);
989 if (lppd->hDevNames != 0) {
991 if((locks = (GlobalFlags(lppd->hDevNames) & GMEM_LOCKCOUNT))) {
992 WARN("hDevNames has %d locks on it. Unlocking it now\n", locks);
994 GlobalUnlock(lppd->hDevNames);
997 PRINTDLG_CreateDevNames(&(lppd->hDevNames), "winspool",
998 lpdmReturn->dmDeviceName, pi->pPortName);
999 GlobalUnlock(lppd->hDevMode);
1001 HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
1002 HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo);
1003 HeapFree(GetProcessHeap(), 0, PrintStructures);
1005 if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
1006 bRet = PRINTDLG_CreateDC(lppd);
1008 TRACE("exit! (%d)\n", bRet);
1014 /***********************************************************************
1015 * PrintDlgW (COMDLG32.18)
1017 BOOL WINAPI PrintDlgW( LPPRINTDLGW printdlg )
1019 FIXME("A really empty stub\n" );
1023 /***********************************************************************
1028 /***********************************************************************
1029 * PageSetupDlgA (COMDLG32.15)
1031 BOOL WINAPI PageSetupDlgA(LPPAGESETUPDLGA setupdlg) {
1032 FIXME("(%p), stub!\n",setupdlg);
1035 /***********************************************************************
1036 * PageSetupDlgW (COMDLG32.16)
1038 BOOL WINAPI PageSetupDlgW(LPPAGESETUPDLGW setupdlg) {
1039 FIXME("(%p), stub!\n",setupdlg);
1043 /**********************************************************************
1048 /***********************************************************************
1049 * PrintDlgProc16 (COMMDLG.21)
1051 LRESULT WINAPI PrintDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
1057 TRACE("WM_INITDIALOG lParam=%08lX\n", lParam);
1058 ShowWindow16(hWnd, SW_SHOWNORMAL);
1064 EndDialog(hWnd, TRUE);
1067 EndDialog(hWnd, FALSE);
1076 /***********************************************************************
1077 * PrintSetupDlgProc16 (COMMDLG.22)
1079 LRESULT WINAPI PrintSetupDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
1085 TRACE("WM_INITDIALOG lParam=%08lX\n", lParam);
1086 ShowWindow16(hWnd, SW_SHOWNORMAL);
1091 EndDialog(hWnd, TRUE);
1094 EndDialog(hWnd, FALSE);
1103 /***********************************************************************
1104 * PrintDlg16 (COMMDLG.20)
1106 * Displays the the PRINT dialog box, which enables the user to specify
1107 * specific properties of the print job.
1110 * nonzero if the user pressed the OK button
1111 * zero if the user cancelled the window or an error occurred
1114 * * calls up to the 32-bit versions of the Dialogs, which look different
1115 * * Customizing is *not* implemented.
1117 BOOL16 WINAPI PrintDlg16( LPPRINTDLG16 lpPrint )
1124 memset(&Print32, 0, sizeof(Print32));
1125 Print32.lStructSize = sizeof(Print32);
1126 Print32.hwndOwner = lpPrint->hwndOwner;
1127 if(lpPrint->hDevMode) {
1128 size = GlobalSize16(lpPrint->hDevMode);
1129 Print32.hDevMode = GlobalAlloc(GMEM_MOVEABLE, size);
1130 ptr = GlobalLock(Print32.hDevMode);
1131 ptr16 = GlobalLock16(lpPrint->hDevMode);
1132 memcpy(ptr, ptr16, size);
1133 GlobalFree16(lpPrint->hDevMode);
1134 GlobalUnlock(Print32.hDevMode);
1136 Print32.hDevMode = 0;
1137 if(lpPrint->hDevNames) {
1138 size = GlobalSize16(lpPrint->hDevNames);
1139 Print32.hDevNames = GlobalAlloc(GMEM_MOVEABLE, size);
1140 ptr = GlobalLock(Print32.hDevNames);
1141 ptr16 = GlobalLock16(lpPrint->hDevNames);
1142 memcpy(ptr, ptr16, size);
1143 GlobalFree16(lpPrint->hDevNames);
1144 GlobalUnlock(Print32.hDevNames);
1146 Print32.hDevNames = 0;
1147 Print32.Flags = lpPrint->Flags;
1148 Print32.nFromPage = lpPrint->nFromPage;
1149 Print32.nToPage = lpPrint->nToPage;
1150 Print32.nMinPage = lpPrint->nMinPage;
1151 Print32.nMaxPage = lpPrint->nMaxPage;
1152 Print32.nCopies = lpPrint->nCopies;
1153 Print32.hInstance = lpPrint->hInstance;
1154 Print32.lCustData = lpPrint->lCustData;
1155 if(lpPrint->lpfnPrintHook) {
1156 FIXME("Need to allocate thunk\n");
1157 /* Print32.lpfnPrintHook = lpPrint->lpfnPrintHook;*/
1159 if(lpPrint->lpfnSetupHook) {
1160 FIXME("Need to allocate thunk\n");
1161 /* Print32.lpfnSetupHook = lpPrint->lpfnSetupHook;*/
1163 Print32.lpPrintTemplateName = PTR_SEG_TO_LIN(lpPrint->lpPrintTemplateName);
1164 Print32.lpSetupTemplateName = PTR_SEG_TO_LIN(lpPrint->lpSetupTemplateName);
1165 Print32.hPrintTemplate = lpPrint->hPrintTemplate;
1166 Print32.hSetupTemplate = lpPrint->hSetupTemplate;
1168 ret = PrintDlgA(&Print32);
1170 if(Print32.hDevMode) {
1171 size = GlobalSize(Print32.hDevMode);
1172 lpPrint->hDevMode = GlobalAlloc16(GMEM_MOVEABLE, size);
1173 ptr16 = GlobalLock16(lpPrint->hDevMode);
1174 ptr = GlobalLock(Print32.hDevMode);
1175 memcpy(ptr16, ptr, size);
1176 GlobalFree(Print32.hDevMode);
1177 GlobalUnlock16(lpPrint->hDevMode);
1179 lpPrint->hDevMode = 0;
1180 if(Print32.hDevNames) {
1181 size = GlobalSize(Print32.hDevNames);
1182 lpPrint->hDevNames = GlobalAlloc16(GMEM_MOVEABLE, size);
1183 ptr16 = GlobalLock16(lpPrint->hDevNames);
1184 ptr = GlobalLock(Print32.hDevNames);
1185 memcpy(ptr16, ptr, size);
1186 GlobalFree(Print32.hDevNames);
1187 GlobalUnlock16(lpPrint->hDevNames);
1189 lpPrint->hDevNames = 0;
1190 lpPrint->hDC = Print32.hDC;
1191 lpPrint->Flags = Print32.Flags;
1192 lpPrint->nFromPage = Print32.nFromPage;
1193 lpPrint->nToPage = Print32.nToPage;
1194 lpPrint->nCopies = Print32.nCopies;
1199 /***********************************************************************
1202 HRESULT WINAPI PrintDlgExA(/*LPPRINTDLGEXA*/ LPVOID lpPrintDlgExA)
1207 /***********************************************************************
1210 HRESULT WINAPI PrintDlgExW(/*LPPRINTDLGEXW*/ LPVOID lpPrintDlgExW)