By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
431,805 Members | 1,270 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 431,805 IT Pros & Developers. It's quick & easy.

How to get printer name properly using PRINTDLG struct and PrintDlg Function?

100+
P: 1,059
I am having a silly trouble.

I am not getting printer name properly using
PRINTDLG struct and PrintDlg Function.

I tried to follow the suggestion provided in msdn it is not working. The test code is added below,

Expand|Select|Wrap|Line Numbers
  1. #include <windows.h>
  2. #include <stdio.h>
  3.  
  4. int main()
  5. {
  6.     PRINTDLG pd;
  7.     DEVNAMES *pDevNames;
  8.     DEVMODE *pDevMode;
  9.  
  10. // Initialize PRINTDLG
  11.     ZeroMemory(&pd, sizeof(pd));
  12.  
  13.     wchar_t *wt;
  14.     char *c;
  15.  
  16.     pd.lStructSize = sizeof(pd);
  17.     pd.hwndOwner   = NULL;
  18.     pd.hDevMode    = NULL;     // Don't forget to free or store hDevMode.
  19.     pd.hDevNames   = NULL;     // Don't forget to free or store hDevNames.
  20.     pd.Flags       = PD_USEDEVMODECOPIESANDCOLLATE | PD_RETURNDC; 
  21.     pd.nCopies     = 1;
  22.     pd.nFromPage   = 0xFFFF; 
  23.     pd.nToPage     = 0xFFFF; 
  24.     pd.nMinPage    = 1; 
  25.     pd.nMaxPage    = 0xFFFF; 
  26.  
  27.     if (PrintDlg(&pd)==TRUE) 
  28.     {
  29.         // GDI calls to render output. 
  30.         pDevMode = (DEVMODE* )pd.hDevMode;
  31.         pDevNames = (DEVNAMES*)pd.hDevNames;
  32.         LPCTSTR     szDriver;
  33.         LPCTSTR     szDevice;
  34.         LPCTSTR     szOutput;
  35.         szDriver = (LPCTSTR)pDevNames+pDevNames->wDriverOffset;
  36.         szDevice = (LPCTSTR)pDevNames+pDevNames->wDeviceOffset;
  37.         szOutput = (LPCTSTR)pDevNames+pDevNames->wOutputOffset;
  38.  
  39.               wprintf(L"%s",szDevice);      
  40.     }
  41.  
  42.  
  43.  
  44. }
  45.  
If you ask why do you need printer name

The reason is when user would run the program first time it wont have any printer name. So it would return null handler. after getting null handler printer dialog will open automatically. From here user will Select the printer. At this stage I want to store the printer name for next time. Next time software wont ask for printer name again unless it is getting null handler

Best Regards,
Johny
Dec 18 '10 #1
Share this Question
Share on Google+
9 Replies


100+
P: 1,059
Didnt find the solution. But have created an alternative solution.

using EnumPrinters function I have find out all the name of the printer and then populate a combobox. That is how i have solved the issue temporarily.

But Yet It would do great If I can have the solution to get the selected printer name
Dec 20 '10 #2

weaknessforcats
Expert Mod 5K+
P: 9,197
You might be getting in trouble with TCHAR. That is, you can't use wchar_t* and LPCTSTR in the same code.

I suggest you code completely in TCHAR so that your wchar_t* becomes LPTSTR.

Then set the project to be either ASCII or Unicode.

Also be sure to use the correct TCHAR mapped functions.
Dec 20 '10 #3

100+
P: 1,059
Weaknessforcat,
I dont get it. Why you said so?
TCHAR is
Expand|Select|Wrap|Line Numbers
  1. typedef WCHAR TCHAR
  2. typedef wchar_t WCHAR
  3.  
so there is no difference between wchar_t and TCHAR

and LPCSTR
Expand|Select|Wrap|Line Numbers
  1. typedef const char *LPCSTR;
  2.  
wchar_t/TCHAR and (const char*)/LPCSTR is completely different variable.

By default a Visual studio 2005 project setup is UNICODE. Which mean whenever you will call a Windows function it will call the Unicode version of that individual Function (depending on availability).

As Example :
Expand|Select|Wrap|Line Numbers
  1. #ifdef UNICODE
  2. #define CreateWindowEx  CreateWindowExW
  3. #else
  4. #define CreateWindowEx  CreateWindowExA
  5. #endif // !UNICODE
  6.  
Above code is from WinUser.h
so according to above code when this project is defined as UNICODE, When you would call

CreateWindowEx you will get CreateWindowExW

otherwise CreateWindowExA.

Now the difference between the two version of the function

Expand|Select|Wrap|Line Numbers
  1. WINUSERAPI
  2. HWND
  3. WINAPI
  4. CreateWindowExA(
  5.     __in DWORD dwExStyle,
  6.     __in_opt LPCSTR lpClassName,
  7.     __in_opt LPCSTR lpWindowName,
  8.     __in DWORD dwStyle,
  9.     __in int X,
  10.     __in int Y,
  11.     __in int nWidth,
  12.     __in int nHeight,
  13.     __in_opt HWND hWndParent,
  14.     __in_opt HMENU hMenu,
  15.     __in_opt HINSTANCE hInstance,
  16.     __in_opt LPVOID lpParam);
  17. WINUSERAPI
  18. HWND
  19. WINAPI
  20. CreateWindowExW(
  21.     __in DWORD dwExStyle,
  22.     __in_opt LPCWSTR lpClassName,
  23.     __in_opt LPCWSTR lpWindowName,
  24.     __in DWORD dwStyle,
  25.     __in int X,
  26.     __in int Y,
  27.     __in int nWidth,
  28.     __in int nHeight,
  29.     __in_opt HWND hWndParent,
  30.     __in_opt HMENU hMenu,
  31.     __in_opt HINSTANCE hInstance,
  32.     __in_opt LPVOID lpParam);
  33.  
in Widestring version lpClassName is Wide string

i.e LPCWSTR which is typedef const wchar_t *LPCWSTR

If you call to call ANSII version specifically you will to call
CreateWindowsExA

But If you look at the functions related with STRING
There is no Modification using macro

example:
Expand|Select|Wrap|Line Numbers
  1. #include <windows.h>
  2. #include <string.h>
  3. #include <stdio.h>
  4.  
  5. int main()
  6. {
  7.     TCHAR wpart1[20]=L"My Name ";
  8.     wchar_t wpart2[]=L"Johny.";
  9.  
  10.     CHAR cpart1[20]="What is your ";
  11.     char cpart2[]="Name?";
  12.  
  13.     wcscat(wpart1,wpart2);
  14.     strcat(cpart1,cpart2);
  15.  
  16.     wprintf(L"%s\n",wpart1);
  17.     printf("%s\n",cpart1);
  18. }
  19.  
Above code will give a clear Idea about char, wchar_t and their type modifier(confused about what to call it).
Dec 20 '10 #4

weaknessforcats
Expert Mod 5K+
P: 9,197
there is no difference between wchar_t and TCHAR
a TCHAR is a char when the project is ASCII and is a wchar_t when the project is Unicode.

You do not want any TCHAR in your code unless all the code is TCHAR.

TCHAR is to seamlessly let you compile ASCII and Unicode versions of your program. If you are only using Unicode, then att TCHAR must be wcar_t.


L"My Name ";
This does not make a Unicde string. This makes a string of wchar_t whicg may or may not be Unicode based on the encoding technique. You have to call a function to create the Unicode string. Like SysAllocStrng or MultibyteToWideChar.

All wchar_t should be WCHAR in the code. That is, there should be no native types in the program.

Your original post used LPCTSTR, which is a long pointer to a constant TCHAR string. If your code is Unicode only then you use LPCWSTR.

If you don't follow exactly, you get weird results. Like L"Hello" is not a LPWSTR.
Dec 21 '10 #5

100+
P: 1,059
same program with (XmultibyteX) wide character
Expand|Select|Wrap|Line Numbers
  1. #include <windows.h>
  2. #include <string.h>
  3. #include <stdio.h>
  4.  
  5. int main()
  6. {
  7.     TCHAR wpart1[20]=L"私の名前はジョン ";
  8.     wchar_t wpart2[]=L"ジョン.";
  9.  
  10.     CHAR cpart1[20]="私の名前はジョン ";
  11.     char cpart2[]="ジョン?";
  12.  
  13.     wcscat(wpart1,wpart2);
  14.     strcat(cpart1,cpart2);
  15.  
  16.     wprintf(L"%s\n",wpart1);
  17.     printf("%s\n",cpart1);
  18.  
  19. }
  20.  
Dec 21 '10 #6

100+
P: 1,059
Dear WeaknessforCat,
Sorry for being rude in my last reply.
Let me explain some of issue you mentioned.

so far I stand for what I said.

The point you mentioned

L"My Name ";

adding L in front of string force compiler to read the string as wide string.

Now Lets come to version issue. (I recalled it in the train :D ). in University I worked with Visual Studio 6. In that version I saw that garbage value you talked about.
as example

Expand|Select|Wrap|Line Numbers
  1. CreateWindow("TEXTCLASS","TEXT TO DISPLAY", .........);
  2.  
if this code is compiled at visual studio 6 "TEXT TO DISPLAY" would create garbage data on the title bar. to ensure not to make garbage value I used to used
Expand|Select|Wrap|Line Numbers
  1. TEXT("What ever the data is"); //it force the compiler to read this particular text as wide string character
  2.  
But Just the garbage value was the issue but no compilation error at all. (I dont know who did that: the Definition of UNICODE or just new feature of Compiler). But in Version 8. IF you do not make sure of wide character you will get a compilation error.

If you take a look to above example i gave. You will get garbage data in the character field. But you Will get the proper data in wide character field.
Dec 22 '10 #7

P: 1
In case, like me, anyone has to do the same thing, gets hung up at the same spot and comes googling here for an answer: the code works except that the memory block must be locked and unlocked. ie:

Expand|Select|Wrap|Line Numbers
  1.     DEVNAMES *pDevNames = (DEVNAMES*)GlobalLock(pd.hDevNames);
  2.     LPCTSTR szDriver;
  3.     LPCTSTR szDevice;
  4.     LPCTSTR szOutput;
  5.     szDriver = (LPCTSTR)pDevNames + pDevNames->wDriverOffset;
  6.     szDevice = (LPCTSTR)pDevNames + pDevNames->wDeviceOffset;
  7.     szOutput = (LPCTSTR)pDevNames + pDevNames->wOutputOffset;
  8.     GlobalUnlock(pd.hDevNames);
Aug 4 '11 #8

weaknessforcats
Expert Mod 5K+
P: 9,197
Expand|Select|Wrap|Line Numbers
  1. L"My Name "; 
  2.  
  3. adding L in front of string force compiler to read the string as wide string.
Just so long as you understand that a wide string is not a UNICODE string.

That means L"My Name " cannot be used as a UNICODE WSTR. If you try you get weird results. Further if you compile this code in ASCII the string is not a char string. Therefore you must code this as:

TEXT("MyName") or as _T("MyName")

There is an entre section of MSDN about how to code in TCHAR. And remember, that if you don't need an ASCII version of your code then you code directly in WCHAR and create yout stirngs using the wide version of MultiByteToWideChar to get the UNICODE version of the literal.

Finally, if you need localiztion of your code, yu can't have hard-coded lierals in it. Instead you need localization code to generate a UNICODE version of the string in the correct language. Here again, MSDN is you best resource or use the book Windows via C/C++ by Jeffrey Richter.
Aug 4 '11 #9

100+
P: 1,059
Well thanks people for your response.

I guess _T is obsolete by now.

I have developed few applications already with wide character. and the problem i was facing was not related with Wide character or anything else. the problem was absolutely related with microsoft documentationa. because they have suggested one structure(now i cannot recall) but in fact it works with a different structure and i think i answered myself in other thread.
Aug 4 '11 #10

Post your reply

Sign in to post your reply or Sign up for a free account.