Introduction
This is a hack to programmatically convert PDF documents to XPS documents using Microsoft XPS Document Writer (MXDW).
Using the Code
This approach can be used to convert almost any document to XPS document, provided the 'ProcessStartInfo::Verbs
' property of the file supports 'print
' or 'printto
'. The trick here is to perform UI automation, that's it.
ProcessStartInfo^ info = gcnew ProcessStartInfo( gcnew String(sourcefile));
info->Arguments = "Microsoft XPS Document Writer";
info->UseShellExecute = true;
info->WindowStyle = ProcessWindowStyle::Hidden;
info->CreateNoWindow = false;
for( int i = 0; i < info->Verbs->Length ; i++)
{
if(info->Verbs[i]->ToString()->Equals("print",StringComparison::OrdinalIgnoreCase))
{
info->Verb="print";
IsPrintable =true;
break;
}
}
Process ^ process = gcnew Process();
process->Start(info);
Edit(targetfile);
Some PDF apps exit after issuing print job, few don't. The following must be considered for such a scenario.
process->WaitForExit(20000);
This is where the UI automation is done. Editing the Text box and mimicking the save button key press.
void Edit(char * pFileName)
{
HWND hWnd =0;
try
{
do{
Sleep(1000);
hWnd = FindWindow(DialogClass, "Save the file as");
}while(!hWnd);
GetWnd(hWnd,"Edit","");
}catch(HWND hChild)
{
if(SendMessage(hChild, WM_SETTEXT,NULL, (LPARAM) pFileName) !=0)
{
hChild = FindWindowEx(hWnd, NULL, NULL, "&Save");
SendMessage (hChild, WM_IME_KEYDOWN, 'S', NULL);
}
}
return;
}
Given the parent window handle, GetWnd
function traverses through all of its child windows until it finds the one which matches classname and caption provided.
void GetWnd( HWND hWnd,char * classname,char * caption)
{
if( hWnd ==0 || classname[0] == '\0' || caption == '\0')
return;
GetWnd ( GetWindow(hWnd,GW_CHILD),classname,caption );
char Class[50],Text[50];
GetClassName(hWnd,Class,50);
GetWindowText(hWnd,Text,50);
if ( !strcmp(Class,classname) && !strcmp(Text,caption) )
throw hWnd;
GetWnd ( GetWindow(hWnd,GW_HWNDNEXT),classname,caption);
return;
}
Fixes
Few PDF applications don't close even after issuing print job, causing pdftoxps to wait for infinite time, this was the main intent in commenting 'process.WaitForExit()
' earlier. The source code has been modified a bit to address this issue.
Reference