📄 printdlg.c
字号:
/*
* COMMDLG - Print Dialog
*
* Copyright 1994 Martin Ayotte
* Copyright 1996 Albrecht Kleine
* Copyright 1999 Klaas van Gend
* Copyright 2000 Huw D M Davies
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <ctype.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winspool.h"
#include "winerror.h"
#include "wine/debug.h"
#include "commdlg.h"
#include "dlgs.h"
#include "cderr.h"
WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
#include "cdlg.h"
#include "printdlg.h"
/* Yes these constants are the same, but we're just copying win98 */
#define UPDOWN_ID 0x270f
#define MAX_COPIES 9999
/* Debugging info */
static const struct pd_flags psd_flags[] = {
{PSD_MINMARGINS,"PSD_MINMARGINS"},
{PSD_MARGINS,"PSD_MARGINS"},
{PSD_INTHOUSANDTHSOFINCHES,"PSD_INTHOUSANDTHSOFINCHES"},
{PSD_INHUNDREDTHSOFMILLIMETERS,"PSD_INHUNDREDTHSOFMILLIMETERS"},
{PSD_DISABLEMARGINS,"PSD_DISABLEMARGINS"},
{PSD_DISABLEPRINTER,"PSD_DISABLEPRINTER"},
{PSD_NOWARNING,"PSD_NOWARNING"},
{PSD_DISABLEORIENTATION,"PSD_DISABLEORIENTATION"},
{PSD_RETURNDEFAULT,"PSD_RETURNDEFAULT"},
{PSD_DISABLEPAPER,"PSD_DISABLEPAPER"},
{PSD_SHOWHELP,"PSD_SHOWHELP"},
{PSD_ENABLEPAGESETUPHOOK,"PSD_ENABLEPAGESETUPHOOK"},
{PSD_ENABLEPAGESETUPTEMPLATE,"PSD_ENABLEPAGESETUPTEMPLATE"},
{PSD_ENABLEPAGESETUPTEMPLATEHANDLE,"PSD_ENABLEPAGESETUPTEMPLATEHANDLE"},
{PSD_ENABLEPAGEPAINTHOOK,"PSD_ENABLEPAGEPAINTHOOK"},
{PSD_DISABLEPAGEPAINTING,"PSD_DISABLEPAGEPAINTING"},
{-1, NULL}
};
/* address of wndproc for subclassed Static control */
static WNDPROC lpfnStaticWndProc;
/* the text of the fake document to render for the Page Setup dialog */
static WCHAR wszFakeDocumentText[1024];
/***********************************************************************
* PRINTDLG_OpenDefaultPrinter
*
* Returns a winspool printer handle to the default printer in *hprn
* Caller must call ClosePrinter on the handle
*
* Returns TRUE on success else FALSE
*/
BOOL PRINTDLG_OpenDefaultPrinter(HANDLE *hprn)
{
WCHAR buf[260];
DWORD dwBufLen = sizeof(buf) / sizeof(buf[0]);
BOOL res;
if(!GetDefaultPrinterW(buf, &dwBufLen))
return FALSE;
res = OpenPrinterW(buf, hprn, NULL);
if (!res)
WARN("Could not open printer %s\n", debugstr_w(buf));
return res;
}
/***********************************************************************
* PRINTDLG_SetUpPrinterListCombo
*
* Initializes printer list combox.
* hDlg: HWND of dialog
* id: Control id of combo
* name: Name of printer to select
*
* Initializes combo with list of available printers. Selects printer 'name'
* If name is NULL or does not exist select the default printer.
*
* Returns number of printers added to list.
*/
INT PRINTDLG_SetUpPrinterListComboA(HWND hDlg, UINT id, LPCSTR name)
{
DWORD needed, num;
INT i;
LPPRINTER_INFO_2A pi;
EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
pi = HeapAlloc(GetProcessHeap(), 0, needed);
EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pi, needed, &needed,
&num);
SendDlgItemMessageA(hDlg, id, CB_RESETCONTENT, 0, 0);
for(i = 0; i < num; i++) {
SendDlgItemMessageA(hDlg, id, CB_ADDSTRING, 0,
(LPARAM)pi[i].pPrinterName );
}
HeapFree(GetProcessHeap(), 0, pi);
if(!name ||
(i = SendDlgItemMessageA(hDlg, id, CB_FINDSTRINGEXACT, -1,
(LPARAM)name)) == CB_ERR) {
char buf[260];
DWORD dwBufLen = sizeof(buf);
FIXME("Can't find '%s' in printer list so trying to find default\n",
name);
if(!GetDefaultPrinterA(buf, &dwBufLen))
return num;
i = SendDlgItemMessageA(hDlg, id, CB_FINDSTRINGEXACT, -1, (LPARAM)buf);
if(i == CB_ERR)
FIXME("Can't find default printer in printer list\n");
}
SendDlgItemMessageA(hDlg, id, CB_SETCURSEL, i, 0);
return num;
}
static INT PRINTDLG_SetUpPrinterListComboW(HWND hDlg, UINT id, LPCWSTR name)
{
DWORD needed, num;
INT i;
LPPRINTER_INFO_2W pi;
EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
pi = HeapAlloc(GetProcessHeap(), 0, needed);
EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pi, needed, &needed,
&num);
for(i = 0; i < num; i++) {
SendDlgItemMessageW(hDlg, id, CB_ADDSTRING, 0,
(LPARAM)pi[i].pPrinterName );
}
HeapFree(GetProcessHeap(), 0, pi);
if(!name ||
(i = SendDlgItemMessageW(hDlg, id, CB_FINDSTRINGEXACT, -1,
(LPARAM)name)) == CB_ERR) {
WCHAR buf[260];
DWORD dwBufLen = sizeof(buf)/sizeof(buf[0]);
TRACE("Can't find '%s' in printer list so trying to find default\n",
debugstr_w(name));
if(!GetDefaultPrinterW(buf, &dwBufLen))
return num;
i = SendDlgItemMessageW(hDlg, id, CB_FINDSTRINGEXACT, -1, (LPARAM)buf);
if(i == CB_ERR)
TRACE("Can't find default printer in printer list\n");
}
SendDlgItemMessageW(hDlg, id, CB_SETCURSEL, i, 0);
return num;
}
/***********************************************************************
* PRINTDLG_CreateDevNames [internal]
*
*
* creates a DevNames structure.
*
* (NB. when we handle unicode the offsets will be in wchars).
*/
static BOOL PRINTDLG_CreateDevNames(HGLOBAL *hmem, const char* DeviceDriverName,
const char* DeviceName, const char* OutputPort)
{
long size;
char* pDevNamesSpace;
char* pTempPtr;
LPDEVNAMES lpDevNames;
char buf[260];
DWORD dwBufLen = sizeof(buf);
size = strlen(DeviceDriverName) + 1
+ strlen(DeviceName) + 1
+ strlen(OutputPort) + 1
+ sizeof(DEVNAMES);
if(*hmem)
*hmem = GlobalReAlloc(*hmem, size, GMEM_MOVEABLE);
else
*hmem = GlobalAlloc(GMEM_MOVEABLE, size);
if (*hmem == 0)
return FALSE;
pDevNamesSpace = GlobalLock(*hmem);
lpDevNames = (LPDEVNAMES) pDevNamesSpace;
pTempPtr = pDevNamesSpace + sizeof(DEVNAMES);
strcpy(pTempPtr, DeviceDriverName);
lpDevNames->wDriverOffset = pTempPtr - pDevNamesSpace;
pTempPtr += strlen(DeviceDriverName) + 1;
strcpy(pTempPtr, DeviceName);
lpDevNames->wDeviceOffset = pTempPtr - pDevNamesSpace;
pTempPtr += strlen(DeviceName) + 1;
strcpy(pTempPtr, OutputPort);
lpDevNames->wOutputOffset = pTempPtr - pDevNamesSpace;
GetDefaultPrinterA(buf, &dwBufLen);
lpDevNames->wDefault = (strcmp(buf, DeviceName) == 0) ? 1 : 0;
GlobalUnlock(*hmem);
return TRUE;
}
static BOOL PRINTDLG_CreateDevNamesW(HGLOBAL *hmem, LPCWSTR DeviceDriverName,
LPCWSTR DeviceName, LPCWSTR OutputPort)
{
long size;
LPWSTR pDevNamesSpace;
LPWSTR pTempPtr;
LPDEVNAMES lpDevNames;
WCHAR bufW[260];
DWORD dwBufLen = sizeof(bufW) / sizeof(WCHAR);
size = sizeof(WCHAR)*lstrlenW(DeviceDriverName) + 2
+ sizeof(WCHAR)*lstrlenW(DeviceName) + 2
+ sizeof(WCHAR)*lstrlenW(OutputPort) + 2
+ sizeof(DEVNAMES);
if(*hmem)
*hmem = GlobalReAlloc(*hmem, size, GMEM_MOVEABLE);
else
*hmem = GlobalAlloc(GMEM_MOVEABLE, size);
if (*hmem == 0)
return FALSE;
pDevNamesSpace = GlobalLock(*hmem);
lpDevNames = (LPDEVNAMES) pDevNamesSpace;
pTempPtr = (LPWSTR)((LPDEVNAMES)pDevNamesSpace + 1);
lstrcpyW(pTempPtr, DeviceDriverName);
lpDevNames->wDriverOffset = pTempPtr - pDevNamesSpace;
pTempPtr += lstrlenW(DeviceDriverName) + 1;
lstrcpyW(pTempPtr, DeviceName);
lpDevNames->wDeviceOffset = pTempPtr - pDevNamesSpace;
pTempPtr += lstrlenW(DeviceName) + 1;
lstrcpyW(pTempPtr, OutputPort);
lpDevNames->wOutputOffset = pTempPtr - pDevNamesSpace;
GetDefaultPrinterW(bufW, &dwBufLen);
lpDevNames->wDefault = (lstrcmpW(bufW, DeviceName) == 0) ? 1 : 0;
GlobalUnlock(*hmem);
return TRUE;
}
/***********************************************************************
* PRINTDLG_UpdatePrintDlg [internal]
*
*
* updates the PrintDlg structure for return values.
*
* RETURNS
* FALSE if user is not allowed to close (i.e. wrong nTo or nFrom values)
* TRUE if successful.
*/
static BOOL PRINTDLG_UpdatePrintDlgA(HWND hDlg,
PRINT_PTRA* PrintStructures)
{
LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
PDEVMODEA lpdm = PrintStructures->lpDevMode;
LPPRINTER_INFO_2A pi = PrintStructures->lpPrinterInfo;
if(!lpdm) {
FIXME("No lpdm ptr?\n");
return FALSE;
}
if(!(lppd->Flags & PD_PRINTSETUP)) {
/* check whether nFromPage and nToPage are within range defined by
* nMinPage and nMaxPage
*/
if (IsDlgButtonChecked(hDlg, rad3) == BST_CHECKED) { /* Pages */
WORD nToPage;
WORD nFromPage;
nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
nToPage = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
if (nFromPage < lppd->nMinPage || nFromPage > lppd->nMaxPage ||
nToPage < lppd->nMinPage || nToPage > lppd->nMaxPage) {
char resourcestr[256];
char resultstr[256];
LoadStringA(COMDLG32_hInstance, PD32_INVALID_PAGE_RANGE,
resourcestr, 255);
sprintf(resultstr,resourcestr, lppd->nMinPage, lppd->nMaxPage);
LoadStringA(COMDLG32_hInstance, PD32_PRINT_TITLE,
resourcestr, 255);
MessageBoxA(hDlg, resultstr, resourcestr,
MB_OK | MB_ICONWARNING);
return FALSE;
}
lppd->nFromPage = nFromPage;
lppd->nToPage = nToPage;
lppd->Flags |= PD_PAGENUMS;
}
else
lppd->Flags &= ~PD_PAGENUMS;
if (IsDlgButtonChecked(hDlg, chx1) == BST_CHECKED) {/* Print to file */
static char file[] = "FILE:";
lppd->Flags |= PD_PRINTTOFILE;
pi->pPortName = file;
}
if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED) { /* Collate */
FIXME("Collate lppd not yet implemented as output\n");
}
/* set PD_Collate and nCopies */
if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
/* The application doesn't support multiple copies or collate...
*/
lppd->Flags &= ~PD_COLLATE;
lppd->nCopies = 1;
/* if the printer driver supports it... store info there
* otherwise no collate & multiple copies !
*/
if (lpdm->dmFields & DM_COLLATE)
lpdm->dmCollate =
(IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED);
if (lpdm->dmFields & DM_COPIES)
lpdm->u.s.dmCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
} else {
if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
lppd->Flags |= PD_COLLATE;
else
lppd->Flags &= ~PD_COLLATE;
lppd->nCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
}
}
return TRUE;
}
static BOOL PRINTDLG_UpdatePrintDlgW(HWND hDlg,
PRINT_PTRW* PrintStructures)
{
LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
PDEVMODEW lpdm = PrintStructures->lpDevMode;
LPPRINTER_INFO_2W pi = PrintStructures->lpPrinterInfo;
if(!lpdm) {
FIXME("No lpdm ptr?\n");
return FALSE;
}
if(!(lppd->Flags & PD_PRINTSETUP)) {
/* check whether nFromPage and nToPage are within range defined by
* nMinPage and nMaxPage
*/
if (IsDlgButtonChecked(hDlg, rad3) == BST_CHECKED) { /* Pages */
WORD nToPage;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -