Hello,

welcome to my blog of various technical solutions, experiences and tutorials.

Please feel free to use the Archive menu to go through my articles.

Thursday, January 26, 2012

4. Propagating UI states to PrintTicket

In last article we learned how to design an user interface (UI) for our XPS filter - simple setting page with checkbox, that was supposed to control the Reverse filter usage. Today we look at how to ensure that the checkbox state will be propagated to the PrintTicket (an XML file carrying all the print settings).

This is going to be a little bit messy and demanding, so please work carefully, as even a tiny mistake can result in complete malfunction of the driver.

Ready?

  1. Go to [sample root]\src\ui and open xdsmpldlg.rc for editing (I recommend you to open it in MS Visual Studio). Open its String Table and add following records to it. The IDs and string values are not so much important (they will probably be displayed in the list of printer capabilities), but be careful to ensure each record has its unique numerical Value to prevent conflicts, that can result in driver malfunction. The best practice is to use numbers a bit further behind the last one used. Here I started with value of 2200.
      IDS_GPD_REVERSETITLE   2200   "Revert page order"
      IDS_GPD_NOREVERSAL     2201   "No reversal"
      IDS_GPD_REVERSAL       2202   "Reversal"

  2. Now go to [sample root]\install and open xdnames.gpd for editing. Go to the end of file and add those new strings to the list of StdFeatureNames. You should have something like this:
      IDS_GPD_REVERSETITLE:     RESDLL.xdsmplui.2200
      IDS_GPD_NOREVERSAL:       RESDLL.xdsmplui.2201
      IDS_GPD_REVERSAL:         RESDLL.xdsmplui.2202
    (The RESDLL macro says the driver to look up the xdsmplui.dll for values of those strings)
  3. Create a new file in [sample root]\install and name it xdreverse.gpd. Copy and paste the following code in it. This is a so called "Generic Printer Description" script which defines one of printer's capabilities.

    *% File Name:
    *%
    *%    xdreverse.gpd
    *%
    *% Abstract:
    *%
    *%    Reverse filter feature specific GPD settings.
    *%

    *%***********************************************************
    *%                            Reverse
    *%***********************************************************
    *%  rcNameID      feature name listed in Printer Capabilities
    *%***********************************************************
    *Feature: PageReversal
    {
        *rcNameID: =IDS_GPD_REVERSETITLE
        *DefaultOption: Reversal
        *PrintSchemaKeywordMap: "PageReversal"

        *Option: NoReversal
        {
            *rcNameID: =IDS_GPD_NOREVERSAL
            *PrintSchemaKeywordMap: "NoReversal"
        }

        *Option: Reversal
        {
            *rcNameID: =IDS_GPD_REVERSAL
            *PrintSchemaKeywordMap: "Reversal"
        }
    }

    It says that we define a new printer feature - PageReversal (this name is very important as we will use it in source code), which has two options (we use checkbox, aren't we? So two options are pretty enough). The Reversal option is taken as default (that means our checkbox is checked by default and the Reverse filter is ON). Keep in mind that the feature (so as both options) needs to have a unique keyword provided in PrintSchemaKeywordMap identifier. This keyword will be used in PrintTicket.
    You can save and close this file now. Please make sure that the PageReversal name is used in revctrls.cpp file.
  4. Open [sample root]\install\xdsmpl.inf for edit and perform following tasks:
    • add xdreverse.gpd in [XPSDrvSample] section
    • add xdreverse.gpd = 1 in [SourceDisksFiles] section
  5. Now open [sample root]\src\ui\uiproperties.cpp and add the following on line 198:

      m_OptItemList.push_back("PageReversal");

    This will add our new feature to the driver's internal feature list, which ensures that our checkbox will get it's default value (defined in xdreverse.gpd file) when the user clicks on Reverse setting page in advanced print dialog and will also "communicate" with UniDrv to update PrintTicket when it's state changes.
  6. Save all files and rebuild and reinstall the driver (as we have changed its sources).
  7. Now when you open the print dialog, go to Advanced and open the Reverse page, you should see your checkbox checked (or unchecked in case you changed the default value in GPD file to NoReversal).
  8. Try to print some document. When it's done, change the output xps file's extension to zip and go inside and lookup \Metadata\Job_PT.xml file. This is the PrintTicket associated to your printed document which controlled its printing. Open it for reading (in Notepad, for example). You should be able to find the following near the end of the file:

      <psf:Feature name="psk:PageReversal">
            <psf:Option name="psk:NoReversal"/>
      </psf:Feature>

  9. If so, congratulations! Your PrintTicket knows about your checkbox and its state now. But one thing still remains - we have to edit our Reverse filter sources for it to follow the PrintTicket settings and control its function. See you in next part of this tutorial, which is hopefully coming very soon :)
Should you not find the piece of XML text listed in step 8, be sure to revise all the steps carefully with stress on PageReversal attribute as it is one of the main identifiers, which all the action is controlled by.

HINT:  If you would like to edit your GPD file after installation (e.g. to change your default option of PageReversal feature), you can do it without subsequent driver reinstallation. You just need to know where to find it - the xdreverse.gpd file (together with all the others) resides in c:\windows\system32\spool\drivers\w32x86\3 (in case you use 64 bit Windows go to ...\drivers\x64\3 instead).

1 comment:

  1. Thanks for this tutorial, I have following it to create an XPS driver. But... The last step:

    m_OptItemList.push_back("PageReversal");

    crash the driver, and I´m sure that the previuos steps are ok. Are not needed other steps to use this feature in the PrintTicket? I have seen that in the example for XPSDrv it exists a Watermark schema in the src/ui files.
    Thanks!

    ReplyDelete