Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
How to know which printer user selected in ComDlg?
Message
From
25/09/2006 14:34:40
 
 
To
25/09/2006 12:16:26
Dragan Nedeljkovich (Online)
Now officially retired
Zrenjanin, Serbia
General information
Forum:
Visual FoxPro
Category:
ActiveX controls in VFP
Environment versions
Visual FoxPro:
VFP 9 SP1
OS:
Windows XP SP1
Miscellaneous
Thread ID:
01155181
Message ID:
01157045
Views:
29
>>>I'll play with this tomorrow - I have a fryday today, and won't trust myself to get this right.
>>>
>>>In case of W9x, I'd probably just skip the whole thing and let them print... those poor guys don't need me to add to their troubles :). And I somehow don't expect the average user of the app to have anything old installed. These are the guys with new laptops :)
>>
>>
>>Arrghg, there is a wrong thing in that sample. For the GlobalUnlock, it should be unlocking the handle instead of the pointer.
>>
>>** This
>>GlobalUnlock( pDevMode )
>>
>>** Replace with this
>>GlobalUnlock( hDevMode )
>>
>
>This thing really works! I had to make only one modification - to remove more than one type of printer, I passed the filter as a comma delimited list of no-no words, and then had to modify the loop to count shown printers backwards (For ln_I = ln_Counts TO 0 STEP -1) because when you remove one, the others shift.
>
>I'm a bit worried, though - I have absolutely no control over the deployment of the app, it's a shrink wrap thing, I never see the target machines. Do you have any ideas on potentially dangerous (as in "may produce an error and cause phone calls") pieces of this, and how to make this as robust as possible? If it errors out, what does it do, return bad values or -?
>
>Also, which functions are not there on archaic versions of Windows? I presume these would be in this part
>
			lh_Wnd = FindWindowEx( This.hPrintDlg, 0, '#32770', 'General' )
>			lh_Wnd = FindWindowEx( lh_Wnd, 0, 'SHELLDLL_DefView', 0 )
>			lh_Wnd = FindWindowEx( lh_Wnd, 0, 'SysListView32', 'FolderView' )
>where W9x probably has a combo, not a listview/folderview.
>
>I see I'll also have to set the default printer to any of the printers I allow before even calling this dialog - because if I remove the default printer, and the user doesn't select one, the default printer is still selected even though it's not listed anymore.


Sorry, there were few things went wrong there, I was too tired that day (looking for an excuses <*g*>). It's not too critical, except for the one I pointed before. But wrong is wrong, right? <*vbg*>

To make it a little more safety, first, I'll change the sample call to this:
If (nResult != 0)
   hDevMode  = CToBin( substr( sPrintDlg,  9, 4 ), '4rs' )
   hDevNames = CToBin( substr( sPrintDlg, 13, 4 ), '4rs' )

   ** Make sure we don't get a NULL handle to DEVMODE, otherwise do not process
   If (hDevMode != 0)
      pDevMode = GlobalLock( hDevMode )
      cPrinterName = sys( 2600, pDevMode, 32 )
      GlobalUnlock( hDevMode )

      nLen = at( chr(0), cPrinterName ) - 1
      If (nLen > 0)
         cPrinterName = left( cPrinterName, nLen )
      endif
      ? 'Selected Printer:', cPrinterName

      GlobalFree( hDevMode )
   endif

   ** Same thing for DEVNAMES
   If (hDevNames != 0)
      GlobalFree( hDevNames )
   endif
else
   ** Check for the PrintDlg error by calling CommDlgExtendedError()
endif
Now, in the handle to DEVNAMES structure, there is one field (wDeviceOffset) that also pointed to the printer name. I haven't try this, but you may need to check from that offset, because the "printer name" return from the DEVMODE is limited to 32 chars. If the name is longer than 32 chars, it might be stored in the DEVNAMES. But, again, I haven't try this myself because I don't have any printer that has names longer than 32. So, please do some more checking.

For more prevention, do an OS checking (as usual), so you know which method of your app will have to run. You can do something like this:
** Skeleton code
Do case
   Case ( WIN_9X_ME )
      do this
   Case ( WIN_2K_XP )
      do that
   Otherwise
      do other thing
else
About that FindWindowEx() things, you don't have to worry. It works under W9x too. However, all the classname to be searched for is different. First I already make it to look for the right target. The code will first react on printer dialog activation.
   If (tn_Msg == 0x06)  && WM_ACTIVATE
      If (t_wParam == 0)
         lc_ClassName = space( 64 )
         ln_Len = GetClassName( t_lParam, @lc_ClassName, 64 )
         If (ln_Len > 0) and ('#32770' $ lc_ClassName)
** If you want to make it more safety, then do one more checking here
            If (GetParent( t_lParam ) == _VFP.hWnd)
               ** Here the handle to printer dialog belongs to our app (our child)
               This.hPrintDlg = t_lParam
               UnBindEvents( th_Wnd, 6 )
               ** Set the timer to look for the ListView child handle
               SetTimer( _VFP.hWnd, 1, 50, 0 )
            endif
         endif
      endif
   else
If the timer doesn't find any of it then it will return 0. You can continue looking for several time (use counter) then kill the timer. Also you can remove the Window name if you want, it's also safer. You can also wrap it in IF..ENDIF if you want
lh_Wnd = FindWindowEx( This.hPrintDlg, 0, '#32770', 'General' )
If (lh_Wnd != 0)
   lh_Wnd = FindWindowEx( lh_Wnd, 0, 'SHELLDLL_DefView', 0 )
   If (lh_Wnd != 0)
      lh_Wnd = FindWindowEx( lh_Wnd, 0, 'SysListView32', 0 )
   endif
endif
For W9X, Although it is still doable from VFP, I'm sorry to say you better skip it <*g*>. It's not that I don't want to tell you, but it needs to do a subclassed (also a hook for more robust solution). And simply can't be done from VFP. Searching the "Combo List Box" using timer is not reliable. Because the listbox is not a direct child of the Printer Dialog. Having said that, it's not that we can not subclassed right from VFP, but I really don't want start it because it's highly dangerous!
Herman
Previous
Next
Reply
Map
View

Click here to load this message in the networking platform