Adobe Acrobat Reader API
От: liokumovich  
Дата: 24.01.05 17:49
Оценка:
А не подскажут ли уважаемые специалисты, есть ли какая-нибудь возможность по COM поуправлять Adobe Acrobat Reader’ом? Интересует не только показать/напечатать, но и добавить комментарий (такая возможность есть в самой программе), поменять цвет объекта (у кого можно поменять цвет) и так далее. Задача его в свой ActiveX обернуть, а как непонятно.
И еще вопрос в PDF можно делать формы, помечать текст пометками и рисовать «от руки» поверх оригинального PDF. Все это можно сделать из вне через API Acrobat Reader?
Заранее спасибо.
Re: Adobe Acrobat Reader API
От: Schade Россия  
Дата: 25.01.05 07:52
Оценка:
Здравствуйте, liokumovich, Вы писали:

L>А не подскажут ли уважаемые специалисты, есть ли какая-нибудь возможность по COM поуправлять Adobe Acrobat Reader’ом? Интересует не только показать/напечатать, но и добавить комментарий (такая возможность есть в самой программе), поменять цвет объекта (у кого можно поменять цвет) и так далее. Задача его в свой ActiveX обернуть, а как непонятно.

L>И еще вопрос в PDF можно делать формы, помечать текст пометками и рисовать «от руки» поверх оригинального PDF. Все это можно сделать из вне через API Acrobat Reader?

В принципе можно, только для этого нужен не Reader, а полноценный Acrobat. Через COM много не сделаешь, нужен SDK — есть на adobe.com.
... << RSDN@Home 1.1.4 beta 4 rev. 303>>
Re: Adobe Acrobat Reader API
От: Amethyst  
Дата: 08.02.05 12:13
Оценка:
Здравствуйте, liokumovich

Reader'ом можно по DDE управлять. Года 4 назад я делал через него из своей программы печать pdf-ников в файл.
Если этот способ устраивает посмотри в сторону ::DdeInitialize(), ::DdeConnect(), ::DdeClientTransaction()

Ниже образец рабочего кода — как это делалось.

/////////////////////////////////////////////////////////////////
//                
//  FILE:       AcroDDE.h
//        
///////////////////////////////////////////////////////////////// 

#ifndef __CLASS_ACROBAT_DDE__
#define __CLASS_ACROBAT_DDE__

#include <Ddeml.h>

class CAcroDDE
{
public:
    CAcroDDE();
    virtual ~CAcroDDE();    
    
    bool Connect( bool bShutDown );    
    void Disconnect() { if(m_ID) ::DdeUninitialize(m_ID), m_ID = 0; }
    DWORD Print2File( const char* szPrn, const char* szSrc, const char* szDst );

protected:
    bool ShutdownAcrobat();

private:
    static HDDEDATA __stdcall DDECallback(uint uType, uint uFmt, HCONV hconv, 
                                         HSZ hsz1, HSZ hsz2, HDDEDATA hdata, 
                                         DWORD dwData1, DWORD dwData2);
    bool LaunchAcrobat();

private:
    DWORD       m_ID;
    HCONV       m_hConversation;
    HSZ         m_hszServerName;
    HSZ         m_hszTopicName;

    PROCESS_INFORMATION
                m_AcroInfo;    
};

#endif //__CLASS_ACROBAT_DDE__


/////////////////////////////////////////////////////////////////
//                
//  FILE:       AcroDDE.cpp
//                
///////////////////////////////////////////////////////////////// 

#include "stdafx.h"
#include "AcroDDE.h"

#define SHUTDOWN_DELAY  1000
#define MAX_TIMEOUT     (1000 * 60 * 10)    // 10 minutes
#define STEP_SIZE       200
#define REG_INSTALL_KEY "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\AcroRd32.exe"


/////////////////////////////////////////////////////////////////
//
//  PURPOSE:    Constructor
//                
//  PARAMETERS: none
//
/////////////////////////////////////////////////////////////////
CAcroDDE::CAcroDDE()
        : m_ID(0)
{
    ZeroMemory(&m_AcroInfo, sizeof(m_AcroInfo));    
}

/////////////////////////////////////////////////////////////////
//
//  PURPOSE:    Destructor
//
/////////////////////////////////////////////////////////////////
CAcroDDE::~CAcroDDE()          
{
    ShutdownAcrobat();
}

/////////////////////////////////////////////////////////////////
//
//  PURPOSE:    launch acrobat reader
//                
//  PARAMETERS: none
//
//  RETURN:     status
//
/////////////////////////////////////////////////////////////////
bool CAcroDDE::LaunchAcrobat()
{
    if( m_AcroInfo.hProcess )
    {
        TRACE("CAcroDDE::LaunchAcrobat, already started, handle %x", m_AcroInfo.hProcess );
        return true;
    }
    HKEY hKey;
    DWORD pathBuf[MAX_PATH + 1];
    DWORD dwSize = MAX_PATH + 1;
    bool bStat = false;

    int nStat = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_INSTALL_KEY, 0, KEY_READ, &hKey);
    if( nStat == ERROR_SUCCESS )
    {
        nStat = ::RegQueryValueEx(hKey, "", 0, 0, (unsigned char *)pathBuf, &dwSize);
        ::RegCloseKey(hKey);

        if( nStat == ERROR_SUCCESS )
        {
            ZeroMemory(&m_AcroInfo, sizeof(m_AcroInfo));
            STARTUPINFO si;
            ZeroMemory(&si, sizeof(si));
            si.cb = sizeof(si);

            bStat = ::CreateProcess((const char*)pathBuf, 0, 0, 0, false, 
                                     NORMAL_PRIORITY_CLASS, 0, 0, &si, &m_AcroInfo)
                 != 0;            
        }
    }
    return bStat;
}

/////////////////////////////////////////////////////////////////
//
//  PURPOSE:    terminate acrobat reader
//                
//  PARAMETERS: none
//
//  RETURN:     error status
//
/////////////////////////////////////////////////////////////////
bool CAcroDDE::ShutdownAcrobat()
{
    if( m_AcroInfo.hProcess )
    {
        BOOL bStat = ::TerminateProcess(m_AcroInfo.hProcess, 0);
        ZeroMemory(&m_AcroInfo, sizeof(m_AcroInfo));
            
        TRACE("CAcroDDE::ShutdownAcrobat, status %d ", bStat);
        return true;
    }
    return false;
}

/////////////////////////////////////////////////////////////////
//
//  PURPOSE:    standard callback for dde messages
//                
//  PARAMETERS: standard dde param
//
//  RETURN:     HDDEDATA
//
/////////////////////////////////////////////////////////////////
HDDEDATA __stdcall CAcroDDE::DDECallback(uint uType, uint uFmt, HCONV hconv, 
                                         HSZ hsz1, HSZ hsz2, HDDEDATA hdata, 
                                         DWORD dwData1, DWORD dwData2)
{
    TRACE("CAcroDDE::DDECallback entered");
    return 0;
}

/////////////////////////////////////////////////////////////////
//
//  PURPOSE:    connect to Acrobat Reader by means of DDE
//                
//  PARAMETERS: bShutDown - need Reader's shutdown or not
//
//  RETURN:     status
//
/////////////////////////////////////////////////////////////////
bool CAcroDDE::Connect( bool bShutDown )
{    
    TRACE("CAcroDDE::Connect, called");

    Disconnect();    
    if( bShutDown )
    {
        ShutdownAcrobat();
        ::Sleep(SHUTDOWN_DELAY);
    }    
    if( !LaunchAcrobat() )
    {
        AsyncMessage("ERROR: cannot launch Acrobat Reader");
        return false;
    }    
    m_ID = 0;
    if( DMLERR_NO_ERROR != ::DdeInitialize(&m_ID, &DDECallback, APPCMD_CLIENTONLY, 0) )
         return false;
                   
    m_hszServerName = ::DdeCreateStringHandle(m_ID, "acroview", 0);
    m_hszTopicName  = ::DdeCreateStringHandle(m_ID, "control", 0);
    
    assert( m_hszServerName && m_hszTopicName );
    DWORD dwSleep = 0;
    
    do 
    {
        m_hConversation = ::DdeConnect(m_ID, m_hszServerName, m_hszTopicName, 0);
        if( m_hConversation || (dwSleep > MAX_TIMEOUT) )
             return false;
        ::Sleep( dwSleep += STEP_SIZE );
    
    } while(true);
    
    return m_hConversation != 0;
}

/////////////////////////////////////////////////////////////////
//
//  PURPOSE:    connect to Acrobat Reader by means of DDE
//                
//  PARAMETERS: szPrn - name of printer
//              szSrc - source file to be printed
//              szDst - out prn file name
//
//  RETURN:     error code ( 0 - success )
//
/////////////////////////////////////////////////////////////////
DWORD CAcroDDE::Print2File( const char* szPrn, const char* szSrc, const char* szDst ) 
{        
    ifstream is;
    is.open(szSrc, ios_base::binary | ios_base::in);
    if( !is.is_open() )
    {
        TRACE("CAcroDDE::Print2File, file %s not exists !", szSrc);
        return 0;
    }
    is.close();

    string sCmd = "[FilePrintTo(\"";
    sCmd += szSrc;
    sCmd += "\", \"";
    sCmd += szPrn;
    sCmd += "\", \"\", \"";
    sCmd += szDst;
    sCmd += "\")]";

    // 0 attempt - suppose Reader already launched and DDE connected
    // 1 attempt - DDE disconnect (if exist) and do new connection
    // 2 attempt - hard error => restart Reader and do new connection
    //
    int nMaxAttempts = 3;
    DWORD dwErr      = 0;

    for( int i=0; i<nMaxAttempts; i++ )
    {
        if(i) Connect( (i+1)==nMaxAttempts ); 
        if( ::DdeClientTransaction((BYTE*)sCmd.c_str(), sCmd.length(), 
                                    m_hConversation, 0, CF_TEXT, 
                                    XTYP_EXECUTE, MAX_TIMEOUT, 0)
            ) return 0;

        dwErr = ::DdeGetLastError(m_ID);
        TRACE("CAcroDDE::Print2File, DDE error %X, attempt %d", dwErr, i);        
    }    
    return dwErr;
}
Почему добро всегда побеждает зло? Потому что историю пишут победители.
Re: Adobe Acrobat Reader API
От: liokumovich  
Дата: 18.02.05 14:29
Оценка:
Подведу итоги моих собственных исследований.
Adobe Acrobat Reader имеет следующее COM API:
1) API, повторяющее минимальный набор DDE команд, которые знает Acrobat Reader. А именно: CloseAllDocs, DocClose,DocGoTo, DocGoToNameDest, DocOpen, FileOpenEx, FilePrintEx, FilePrintSilentEx, FilePrintToEx, and AppExit
Причем, это API было сделано исключительно для того, чтобы PDF можно было открывать в MS IE; как следствие API недокументированно и не “саппортится”.

2) Полноценное COM API, которое может все. Оно доступно только для plug-in'ов и только по специальной лицензии от Adobe (стоит от $1000 до $2500) . Эта лицензия очень много чего запрещает. Например, нельзя сделать plug-in, который вытащит наружу управление (navigation). При этом надо сначала написать свой plug-in используя Acrobat Professional (в нем COM API доступен), а затем подать заявку на лицензирование.

На сайте Adobe лежит много документов при попытке скачать который просят ввести логин/пароль, и при этом говорят, что регистрация бесплатна. Так вот, во всех случаях, с которыми столкнулся я, «уровня дружественности», который дает бесплатная регистрация, оказалось не достаточно для доступа к запрашиваемым документам.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.