http://support.microsoft.com/default.aspx?scid=kb;EN-US;q246772
HOWTO: Retrieve and Set the Default Printer in Windows (Q246772)
--------------------------------------------------------------------------------
The information in this article applies to:
Microsoft Windows 98
Microsoft Windows NT Server version 4.0
Microsoft Windows NT Workstation version 4.0
Microsoft Windows 2000 , Advanced Server
Microsoft Windows 2000 , Server
Microsoft Windows 2000 , Professional
Microsoft Windows 95
--------------------------------------------------------------------------------
SUMMARY
Depending on the version of Windows used, there are different ways to retrieve and/or set the default printer.
MORE INFORMATION
Under Windows NT 4.0 (and earlier), neither SetPrinter nor SetDefaultPrinter can be used to set the default printer. Also, neither EnumPrinters nor GetDefaultPrinter can be used to get the default printer.
Under Windows NT 4.0, you may achieve this by using GetProfileString (to get the default printer) or WriteProfileString (to set the default printer). The Device value that you get or set actually contains three elements separated by commas as follows:
printer name,driver name,port
For example:
My Printer,HPPCL5MS,lpt1:
When using this method, you must specify a valid printer, driver, and port. If you don't, the APIs will *not* fail, potentially causing other programs to set the printer back to the previous valid printer or simply become very confused. You can use the EnumPrinters API to retrieve the printer name, driver name, and port name of all available printers.
Windows NT maps most .ini file references to the registry. Because of this, GetProfileString and WriteProfileString still function as if they were running under 16-bit Windows (Microsoft Windows and Windows for Workgroups).
After setting the default printer with either GetPrinter, GetDefaultPrinter, or WriteProfileString, you should notify all other open applications of the change by broadcasting the WM_SETTINGCHANGE message. Only applications that handle this message recognize the change.
WM_SETTINGCHANGE and WM_WININICHANGE are identical. Win32 programs should use WM_SETTINGCHANGE.
Sample Code
The following sample code shows how to retrieve the default printer (DPGetDefaultPrinter) and set the default printer (DPSetDefaultPrinter) under Windows 95, Windows 98, Windows NT, and Windows 2000.
// Size of internal buffer used to hold "printername,drivername,portname"
// string. Increasing this may be necessary for huge strings.
#define MAXBUFFERSIZE 250
/*----------------------------------------------------------------*/
/* DPGetDefaultPrinter */
/* */
/* Parameters: */
/* pPrinterName: Buffer alloc'd by caller to hold printer name. */
/* pdwBufferSize: On input, ptr to size of pPrinterName. */
/* On output, min required size of pPrinterName. */
/* */
/* NOTE: You must include enough space for the NULL terminator! */
/* */
/* Returns: TRUE for success, FALSE for failure. */
/*----------------------------------------------------------------*/
BOOL DPGetDefaultPrinter(LPTSTR pPrinterName, LPDWORD pdwBufferSize)
{
BOOL bFlag;
OSVERSIONINFO osv;
TCHAR cBuffer[MAXBUFFERSIZE];
PRINTER_INFO_2 *ppi2 = NULL;
DWORD dwNeeded = 0;
DWORD dwReturned = 0;
// What version of Windows are you running?
osv.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osv);
// If Windows 95 or 98, use EnumPrinters...
if (osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
{
// The first EnumPrinters() tells you how big our buffer should
// be in order to hold ALL of PRINTER_INFO_2. Note that this will
// usually return FALSE. This only means that the buffer (the 4th
// parameter) was not filled in. You don't want it filled in here...
EnumPrinters(PRINTER_ENUM_DEFAULT, NULL, 2, NULL, 0, &dwNeeded, &dwReturned);
if (dwNeeded == 0)
return FALSE;
// Allocate enough space for PRINTER_INFO_2...
ppi2 = (PRINTER_INFO_2 *)GlobalAlloc(GPTR, dwNeeded);
if (!ppi2)
return FALSE;
// The second EnumPrinters() will fill in all the current information...
bFlag = EnumPrinters(PRINTER_ENUM_DEFAULT, NULL, 2, (LPBYTE)ppi2, dwNeeded, &dwNeeded, &dwReturned);
if (!bFlag)
{
GlobalFree(ppi2);
return FALSE;
}
// If given buffer too small, set required size and fail...
if ((DWORD)lstrlen(ppi2->pPrinterName) >= *pdwBufferSize)
{
*pdwBufferSize = (DWORD)lstrlen(ppi2->pPrinterName) + 1;
GlobalFree(ppi2);
return FALSE;
}
// Copy printer name into passed-in buffer...
lstrcpy(pPrinterName, ppi2->pPrinterName);
// Set buffer size parameter to min required buffer size...
*pdwBufferSize = (DWORD)lstrlen(ppi2->pPrinterName) + 1;
}
// If Windows NT, use the GetDefaultPrinter API for Windows 2000,
// or GetProfileString for version 4.0 and earlier...
else if (osv.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
#if(WINVER >= 0x0500)
if (osv.dwMajorVersion >= 5) // Windows 2000 or later
{
bFlag = GetDefaultPrinter(pPrinterName, pdwBufferSize);
if (!bFlag)
return FALSE;
}
else // NT4.0 or earlier
#endif
{
// Retrieve the default string from Win.ini (the registry).
// String will be in form "printername,drivername,portname".
if (GetProfileString("windows", "device", ",,,", cBuffer, MAXBUFFERSIZE) <= 0)
return FALSE;
// Printer name precedes first "," character...
strtok(cBuffer, ",");
// If given buffer too small, set required size and fail...
if ((DWORD)lstrlen(cBuffer) >= *pdwBufferSize)
{
*pdwBufferSize = (DWORD)lstrlen(cBuffer) + 1;
return FALSE;
}
// Copy printer name into passed-in buffer...
lstrcpy(pPrinterName, cBuffer);
// Set buffer size parameter to min required buffer size...
*pdwBufferSize = (DWORD)lstrlen(cBuffer) + 1;
}
}
// Cleanup...
if (ppi2)
GlobalFree(ppi2);
return TRUE;
}
#undef MAXBUFFERSIZE
/*-----------------------------------------------------------------*/
/* DPSetDefaultPrinter */
/* */
/* Parameters: */
/* pPrinterName: Valid name of existing printer to make default. */
/* */
/* Returns: TRUE for success, FALSE for failure. */
/*-----------------------------------------------------------------*/
BOOL DPSetDefaultPrinter(LPTSTR pPrinterName)
{
BOOL bFlag;
OSVERSIONINFO osv;
DWORD dwNeeded = 0;
HANDLE hPrinter = NULL;
PRINTER_INFO_2 *ppi2 = NULL;
LPTSTR pBuffer = NULL;
LONG lResult;
// What version of Windows are you running?
osv.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osv);
if (!pPrinterName)
return FALSE;
// If Windows 95 or 98, use SetPrinter...
if (osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
{
// Open this printer so you can get information about it...
bFlag = OpenPrinter(pPrinterName, &hPrinter, NULL);
if (!bFlag || !hPrinter)
return FALSE;
// The first GetPrinter() tells you how big our buffer should
// be in order to hold ALL of PRINTER_INFO_2. Note that this will
// usually return FALSE. This only means that the buffer (the 3rd
// parameter) was not filled in. You don't want it filled in here...
GetPrinter(hPrinter, 2, 0, 0, &dwNeeded);
if (dwNeeded == 0)
{
ClosePrinter(hPrinter);
return FALSE;
}
// Allocate enough space for PRINTER_INFO_2...
ppi2 = (PRINTER_INFO_2 *)GlobalAlloc(GPTR, dwNeeded);
if (!ppi2)
{
ClosePrinter(hPrinter);
return FALSE;
}
// The second GetPrinter() will fill in all the current information
// so that all you need to do is modify what you're interested in...
bFlag = GetPrinter(hPrinter, 2, (LPBYTE)ppi2, dwNeeded, &dwNeeded);
if (!bFlag)
{
ClosePrinter(hPrinter);
GlobalFree(ppi2);
return FALSE;
}
// Set default printer attribute for this printer...
ppi2->Attributes |= PRINTER_ATTRIBUTE_DEFAULT;
bFlag = SetPrinter(hPrinter, 2, (LPBYTE)ppi2, 0);
if (!bFlag)
{
ClosePrinter(hPrinter);
GlobalFree(ppi2);
return FALSE;
}
// Tell all open applications that this change occurred.
// Allow each application 1 second to handle this message.
lResult = SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0L,
(LPARAM)(LPCTSTR)"windows", SMTO_NORMAL, 1000, NULL);
}
// If Windows NT, use the SetDefaultPrinter API for Windows 2000,
// or WriteProfileString for version 4.0 and earlier...
else if (osv.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
#if(WINVER >= 0x0500)
if (osv.dwMajorVersion >= 5) // Windows 2000 or later...
{
bFlag = SetDefaultPrinter(pPrinterName);
if (!bFlag)
return FALSE;
}
else // NT4.0 or earlier...
#endif
{
// Open this printer so you can get information about it...
bFlag = OpenPrinter(pPrinterName, &hPrinter, NULL);
if (!bFlag || !hPrinter)
return FALSE;
// The first GetPrinter() tells you how big our buffer should
// be in order to hold ALL of PRINTER_INFO_2. Note that this will
// usually return FALSE. This only means that the buffer (the 3rd
// parameter) was not filled in. You don't want it filled in here...
GetPrinter(hPrinter, 2, 0, 0, &dwNeeded);
if (dwNeeded == 0)
{
ClosePrinter(hPrinter);
return FALSE;
}
// Allocate enough space for PRINTER_INFO_2...
ppi2 = (PRINTER_INFO_2 *)GlobalAlloc(GPTR, dwNeeded);
if (!ppi2)
{
ClosePrinter(hPrinter);
return FALSE;
}
// The second GetPrinter() fills in all the current<BR/>
// information...
bFlag = GetPrinter(hPrinter, 2, (LPBYTE)ppi2, dwNeeded, &dwNeeded);
if ((!bFlag) || (!ppi2->pDriverName) || (!ppi2->pPortName))
{
ClosePrinter(hPrinter);
GlobalFree(ppi2);
return FALSE;
}
// Allocate buffer big enough for concatenated string.
// String will be in form "printername,drivername,portname"...
pBuffer = (LPTSTR)GlobalAlloc(GPTR,
lstrlen(pPrinterName) +
lstrlen(ppi2->pDriverName) +
lstrlen(ppi2->pPortName) + 3);
if (!pBuffer)
{
ClosePrinter(hPrinter);
GlobalFree(ppi2);
return FALSE;
}
// Build string in form "printername,drivername,portname"...
lstrcpy(pBuffer, pPrinterName); lstrcat(pBuffer, ",");
lstrcat(pBuffer, ppi2->pDriverName); lstrcat(pBuffer, ",");
lstrcat(pBuffer, ppi2->pPortName);
// Set the default printer in Win.ini and registry...
bFlag = WriteProfileString("windows", "device", pBuffer);
if (!bFlag)
{
ClosePrinter(hPrinter);
GlobalFree(ppi2);
GlobalFree(pBuffer);
return FALSE;
}
}
// Tell all open applications that this change occurred.
// Allow each app 1 second to handle this message.
lResult = SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0L, 0L,
SMTO_NORMAL, 1000, NULL);
}
// Cleanup...
if (hPrinter)
ClosePrinter(hPrinter);
if (ppi2)
GlobalFree(ppi2);
if (pBuffer)
GlobalFree(pBuffer);
return TRUE;
}
There are a few circumstances where the code won't work (or appears not to work):
몰라요 님이 쓰신 글 :
: 런타임시 프린터를 변경하는 방법을 알고 싶습니다.
:
: ShellExecute 로 ms word같은 것을 실행시켜 프린트해야 하는데 프린터를 기본 프린터가 아닌
:
: 다른 프린터를 사용하고 싶습니다.
: //--------------------------------------------------------------------------------------
:
: writeProfileString ("windows", "device", NewDefPrinter.c_str())
:
: SendMessage (HWND_BROADCAST, WM_WININICHANGE, 0, (LPARAM)"windows");
:
: 위 코드를 실행하기 전 기본 프린터는 해지되어 있지만 새로 지정한 프린터가 기본 프린터로
:
: 지정되지는 않습니다. 그리고 다음 코드도 공백을 리턴하는 군요
:
: GetProfileString("Windows","device","",ResStr.c_str(),255)
: //---------------------------------------------------------------------------------------
:
: OS가 Windows 2000이므로
:
: 레지스트리의 값을 변경해야 한다면 기본 프린터를 변경하는 방법 좀 부탁드립니다.