We help IT Professionals succeed at work.

Need some help with CString and LPCSTR

High Priority
70 Views
Last Modified: 2020-02-25
Hello,
I would like to change  the name of the printer into a  string.
This is my code that works:
if (GetPrinterDevice(_T("\\\\DSERVER\\Brother HL-7050 series"), &hDevNames, &hDevMode))


I have tried this one, but it will not work:


void CZahlen_SortierenDlg::OnBnClickedButton1()
{
       HANDLE hDevMode;
     HANDLE hDevNames;

       CString D="\\\\\\\\DSERVER\\\\Brother HL-7050 series";
       LPCSTR drucker=(LPCSTR)(LPCSTR)D;



// if (GetPrinterDevice(_T("\\\\DSERVER\\Brother HL-7050 series"), &hDevNames, &hDevMode))


 
 
   if (GetPrinterDevice(drucker), &hDevNames, &hDevMode)
      
     {
          AfxGetApp()->SelectPrinter(hDevNames, hDevMode);

          CPrintDialog dlgPrint(FALSE,PD_PAGENUMS|PD_USEDEVMODECOPIESANDCOLLATE , this);

               //--------------------------- Papier Auswahl DEVMODE ----------------------------------
          if(AfxGetApp()->GetPrinterDeviceDefaults(&dlgPrint.m_pd))
          {               
              LPDEVMODE dev=dlgPrint.GetDevMode();
                GlobalUnlock(dev);
                            
                   dev->dmOrientation=DMORIENT_PORTRAIT;  //Hochformat
                  dev->dmPaperSize=DMPAPER_A4;
               
                dev->dmCopies=1;  
                dev->dmDefaultSource=DMBIN_AUTO;


I will get this error:
errorThank you for your help,
Best regards,
Thomas
Comment
Watch Question

Kent OlsenData Warehouse / Database Architect
CERTIFIED EXPERT
Commented:

Hi Thomas,


I don't see the cause of your error, but do see a couple of things that need cleaning up.


    CString D="\\\\\\\\DSERVER\\\\Brother HL-7050 series";
                                 LPCSTR drucker=(LPCSTR)(LPCSTR)D;

                         

You've double up the backslashes.  The resulting string will lead with 4 backslashes and have two between the server name and printer name.  I don't believe that the host will recognize that as a valid printer.  Go ahead and use the string from the code that works.


It's curious that you cast D to an LPCSTR twice.  It's probably OK, but confusing.


Kent


Lead Developer
CERTIFIED EXPERT
Commented:
Your call to:

if (GetPrinterDevice(drucker), &hDevNames, &hDevMode)

probably needs to be:

if (GetPrinterDevice(drucker, &hDevNames, &hDevMode))

-or-

if (GetPrinterDevice((LPWSTR)(LPCTSTR) drucker, &hDevNames, &hDevMode))
Hallo Kevin,
thank you for your answer.
I changed my code to this:

void CZahlen_SortierenDlg::OnBnClickedButton1()
{
       CString D="\\\\\\\\DSERVER\\\\Brother HL-7050 series";
       LPCSTR drucker=(LPCSTR)D;

      HANDLE hDevMode;
      HANDLE hDevNames;
 
 
        if (GetPrinterDevice((LPSTR)drucker, &hDevNames, &hDevMode))
     {
          AfxGetApp()->SelectPrinter(hDevNames, hDevMode);


I will get no error.
But in GetPrinterDevice the printer will not be recognized.


bool CZahlen_SortierenDlg::GetPrinterDevice(LPTSTR pszPrinterName, HGLOBAL* phDevNames, HGLOBAL* phDevMode)
{
      // if NULL is passed, then assume we are setting app object's
    // devmode and devnames
    if (phDevMode == NULL || phDevNames == NULL)
      {
            MessageBox("EPSON LQ-680Pro Port 2 Wiegekarte-1error");
        return FALSE;
      }


    // Open printer
    HANDLE hPrinter;
    if (OpenPrinter(pszPrinterName, &hPrinter, NULL) == FALSE)
      {
            MessageBox("Can not find printer");                will get this message
        return FALSE;
      }

When I look at the string with a break point, it looks the same as in writing "\\\\DSERVER\\Brother HL-7050 series"

Printer
Hallo Kent,
if I do not use this: CString D="\\\\\\\\DSERVER\\\\Brother HL-7050 series";
the string at my hardcopy above looks not the same
Best regards,
Thomas
Hallo Kent,
I am sorry you were right....I looked with a breakpoint on

 // Open printer
    HANDLE hPrinter;
    if (OpenPrinter(pszPrinterName, &hPrinter, NULL) == FALSE) to find out how the printer name is with my correct code _T(".....")
      {
            MessageBox("Can not find printer");                will get this message
        return FALSE;
      }

and there were to many \\  even if the break point shows \\\\DSERVER\\Brother HL -7050 series" (see above)
the name of the pszPrinterName was
\\DSERVER\Brother HL -7050 series"


so I reduced the \\ and it works.
Thank you.
Best regards,
Thomas
Thank you for your great help.
Best regards,
Thomas
CERTIFIED EXPERT
Top Expert 2016

Commented:
check the prototype of the GetPrinterDevice function. if the first argument is of type LPCTSTR it means, that the the type is either LPCSTR (or const char *) if using 'multi-byte character set in the project general properties. if using 'UNICODE' character set the LPCTSTR evaluates to LPCWSTR (or const wchar_t *).

you can't cast between LPCSTR and LPCWSTR because char is 8-bit and wchar_t is 16-bit.

generally i wouldn't use the t-types as you always have to be aware of their real types.

so, if you don't have to handle international strings where the ANSI character set is not sufficient, i strongly would advice to using multi-byte character set. then always use the types without 'T' because the compiler would warn you if wide strings came into play. use std::string instead of CString then, because std::string can be used additional to std::wstring while CString is either char or wchar_t and cannot be switched,

if you need windows unicode strings, use consequently wide strings and wchar_t type instead of char. std::wstring is better than CString because the compiler warns if there is a mismatch.

1. Multibyte Character set

void CZahlen_SortierenDlg::OnBnClickedButton1()
{
     HANDLE hDevMode;
     HANDLE hDevNames;

     std::string printer ="\\\\DSERVER\\Brother HL-7050 series";

     if (GetPrinterDevice(printer.c_str()), &hDevNames, &hDevMode)
     {
             ....
      

Open in new window


2. MS 'UNICODE' character set


1. Multibyte Character set

void CZahlen_SortierenDlg::OnBnClickedButton1()
{
     HANDLE hDevMode;
     HANDLE hDevNames;

     std::wstring printer = L"\\\\DSERVER\\Brother HL-7050 series";

     if (GetPrinterDevice(printer.c_str()), &hDevNames, &hDevMode)
     {
             ....
      

Open in new window


note, if using WINAPI you often will find functions which have either an 'A' or a 'W' suffix. MS is using typedef's to use either the A(NSI) variant of the function or the 'W'IDE one. if you need both, you always should use the names with suffix. if you only need 'A' or 'W' use consequently names without suffix.

Sara
Thank you Sara for your help.
Best regards,
Thomas