?
Solved

DEVNAMES Structure

Posted on 2000-01-16
10
Medium Priority
?
572 Views
Last Modified: 2012-05-04
How do you change the members of the DEVNAMES struct.  If I have HP Laser Jet as the printer name, winspool as the driver and Ne02: as the port, how would I place these into wDeviceOffset, wDriverOffset and wOutputOffset of the DEVNAMES Struct?  If you could give me an example, I'd appreciate it.  Thanks.
0
Comment
Question by:paulca
  • 6
  • 4
10 Comments
 
LVL 22

Accepted Solution

by:
nietod earned 800 total points
ID: 2357504
char *Driver = ???;
char *Device = ???;
char *Output = ???

int DriverLen = strlen(Driver);
int DeviceLen = strilen(Device);
int OutputLen = strlen(OPutput);

int AloLen = sizeof(DEVNAMES + DriverLen + Dervice:en + OutputLen + 3;
// the +3 is for the 3 string terminators.

continues.
0
 
LVL 22

Expert Comment

by:nietod
ID: 2357516
HGLOBAL DevNamHnd = GlobalAloc(GMEM_MOVABLE,AloLen);

DEVNAMES DevNamPtr = (DEVNAMES *) GlobalLock(DevNamHnd))

DevNamPtr->wDriverOffset = sizeof(DEVNAMES);
DevNamPtr->wDeviceOffset = DevNamPtr->wDriverOffset + DriverLen;
DevNamPtr->wOutputOffset = DevNamPtr->wDeviceOffset + DeviceLen;

continues.
0
 
LVL 22

Expert Comment

by:nietod
ID: 2357519
char *BytPtr = (char *) DevNamPtr;

strcpy(BytPtr + DevNamPtr->wDriverOffset,Driver);
strcpy(BytPtr + DevNamPtr->wDeviceOffset,Device);
strcpy(BytPtr + DevNamPtr->wOutputOffset,Output);

In english.  You calcualt ethe total size of the block of memory to hold the DEVNAMES structure.  This isthe size of the DEVNAMES structure itself, with is really used as a header to this entire block.  Then add on the length of the three strings, including the length required for their terminators.

Then you allocate memory for this block usig GlobalAlloc() and lock the block to get a pointer to it.  Then you fill in the DEVNAMES structure that appears at the start of the block.  The 1st string appears right after the DEVNAMES structure, so the offset to the first string is the sizeof the DEVNAMES structure.  The 2nd string appears right after the first, so its offset is the offset of the first string plus the length of the 1st string, plus 1 for the terminator (WHICH IF FORGOT ABOVE)  And the same for the 3rd string.  

So the code to set the offset should be

DevNamPtr->wDriverOffset = sizeof(DEVNAMES);
DevNamPtr->wDeviceOffset = DevNamPtr->wDriverOffset + DriverLen + 1;
DevNamPtr->wOutputOffset = DevNamPtr->wDeviceOffset + DeviceLen + 1;
0
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

 

Author Comment

by:paulca
ID: 2357526
I am using Visual C++ 4.2 and GlobalAloc is giving me an error.  Does this have something to do with the version I am using?  The error it gave me was:

error C2065: 'GlobalAloc' : undeclared identifier
0
 
LVL 22

Expert Comment

by:nietod
ID: 2357543
Opps.  try GlobalAlloc()--two l's
0
 

Author Comment

by:paulca
ID: 2357688
Do I have to do something like this once I have implemented the above code?

printDlg->m_pd.hDevNames = BytPtr;
0
 
LVL 22

Expert Comment

by:nietod
ID: 2357717
Sort of.  The global block must be unlocked (GlobalUnlock()) and after you are done with the memory, you must free the global block (GlobalFree().)

And yes, the PRINTDLG's hDevNames should be set to this block, but to the HANDLE for the block, not the pointer to it.  This is mostly for legacy reasons, but the print dialog expects a global handle that it will then lock in order to access the data stored in the memory.
0
 

Author Comment

by:paulca
ID: 2357739
Does this look right?

GlobalUnlock(DevNameHnd);
GlobalFree(DevNameHnd);
printDlg->m_pd.hDevNames = DevNameHnd;
0
 
LVL 22

Expert Comment

by:nietod
ID: 2357894
No.  

GlobalUnlock(DevNameHnd);
printDlg->m_pd.hDevNames = DevNameHnd;
Display the dialog;
use the PRINTDLG to set up the print.
GlobalFree(DevNameHnd);

GlobaAlloc() is like C's new or malloc().  It allocates memory.  However it doesn't return a pointer to the memory.  This is because the memory is movable (or was in 16 bit).  So the OS could move the memory about to keep the heap efficiently organized.  So instead GlobalAlloc returned a handle that refers to the memory, but is not a pointer to it.  In order to get a pointer to the memory, you have to lock it, so it can't be moved about while you use the pointer.  Then when you are done using the memory (at least for a little while) you unlock the memory, this lets the OS move it around again, if needed.  Finally when you are totaly done with the memory, you call GlobalFree(), which deletes the memory, like C++'s delete or free().

the PRINTDLG structure needs to have a handle to this movable block of memory because it will lock the handle, getting a pointer to what you've specified and use this information.  Furthermore, depending on what the  user chooses, the print dialog may free this memory and allocate new memory for the information it returns.  Sot he lock you specify might not be the one you get back, which is another reason why this can't be a pointer.  (Not all pointers point to memory that can be freed, but all HGLOBALS do.)

Also when you are done setting up the print you must rememober to free this device names memory, as shown about AND the device mode block in hDevMode.  This is ALWAYS TRUE, even if you don't allocate these.  i.e. if you set these to NULL they will be returned non-NULL and must be GlobalFree()ed.
0
 

Author Comment

by:paulca
ID: 2359355
Thanks for your time.  You have been a great help.
0

Featured Post

Learn to develop an Android App

Want to increase your earning potential in 2018? Pad your resume with app building experience. Learn how with this hands-on course.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article will show you some of the more useful Standard Template Library (STL) algorithms through the use of working examples.  You will learn about how these algorithms fit into the STL architecture, how they work with STL containers, and why t…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

593 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question