/Users/ericb/Desktop/NATIVEPRINTDLG01/extensions/source/scanner/scanwin.cxx

Go to the documentation of this file.
00001 /*************************************************************************
00002  *
00003  *  OpenOffice.org - a multi-platform office productivity suite
00004  *
00005  *  $RCSfile: scanwin.cxx,v $
00006  *
00007  *  $Revision: 1.11 $
00008  *
00009  *  last change: $Author: ihi $ $Date: 2008/01/14 15:04:05 $
00010  *
00011  *  The Contents of this file are made available subject to
00012  *  the terms of GNU Lesser General Public License Version 2.1.
00013  *
00014  *
00015  *    GNU Lesser General Public License Version 2.1
00016  *    =============================================
00017  *    Copyright 2005 by Sun Microsystems, Inc.
00018  *    901 San Antonio Road, Palo Alto, CA 94303, USA
00019  *
00020  *    This library is free software; you can redistribute it and/or
00021  *    modify it under the terms of the GNU Lesser General Public
00022  *    License version 2.1, as published by the Free Software Foundation.
00023  *
00024  *    This library is distributed in the hope that it will be useful,
00025  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
00026  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00027  *    Lesser General Public License for more details.
00028  *
00029  *    You should have received a copy of the GNU Lesser General Public
00030  *    License along with this library; if not, write to the Free Software
00031  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00032  *    MA  02111-1307  USA
00033  *
00034  ************************************************************************/
00035 
00036 // MARKER(update_precomp.py): autogen include statement, do not remove
00037 #include "precompiled_extensions.hxx"
00038 
00039 #ifndef _COM_SUN_STAR_UNO_ANY_HXX_ 
00040 #include <com/sun/star/uno/Any.hxx>
00041 #endif
00042 
00043 #ifndef _COM_SUN_STAR_UNO_REFERENCE_HXX_
00044 #include <com/sun/star/uno/Reference.hxx>
00045 #endif
00046 
00047 #ifndef _COM_SUN_STAR_UTIL_XCLOSEABLE_HPP_
00048 #include <com/sun/star/util/XCloseable.hpp>
00049 #endif
00050 
00051 #ifndef _COM_SUN_STAR_UTIL_XCLOSEBROADCASTER_HPP_
00052 #include <com/sun/star/util/XCloseBroadcaster.hpp>
00053 #endif
00054 
00055 #ifndef _COM_SUN_STAR_UTIL_XCLOSELISTENER_HPP_
00056 #include <com/sun/star/util/XCloseListener.hpp>
00057 #endif
00058 
00059 #ifndef _COM_SUN_STAR_FRAME_XFRAME_HPP_
00060 #include <com/sun/star/frame/XFrame.hpp>
00061 #endif
00062 
00063 #ifndef _COM_SUN_STAR_FRAME_XDESKTOP_HPP_
00064 #include <com/sun/star/frame/XDesktop.hpp>
00065 #endif
00066 
00067 #ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
00068 #include <com/sun/star/beans/XPropertySet.hpp>
00069 #endif
00070 
00071 #ifndef _CPPUHELPER_IMPLBASE1_HXX_
00072 #include <cppuhelper/implbase1.hxx>
00073 #endif
00074 
00075 #ifndef _COMPHELPER_PROCESSFACTORY_HXX_
00076 #include <comphelper/processfactory.hxx>
00077 #endif
00078 
00079 #include <math.h>
00080 #include <tools/svwin.h>
00081 #include <tools/stream.hxx>
00082 #include <vos/mutex.hxx>
00083 #include <vos/module.hxx>
00084 #include <vcl/svapp.hxx>
00085 #include <vcl/wrkwin.hxx>
00086 #include <vcl/sysdata.hxx>
00087 #include <vcl/salbtype.hxx>
00088 #include "scanner.hxx"
00089 
00090 #pragma warning (push,1)
00091 #pragma warning (disable:4668)
00092 #include "twain/twain.h"
00093 #pragma warning (pop)
00094 
00095 using namespace ::com::sun::star;
00096 
00097 // -----------
00098 // - Defines -
00099 // -----------
00100 
00101 #define TWAIN_SELECT                    0x00000001UL
00102 #define TWAIN_ACQUIRE                   0x00000002UL
00103 #define TWAIN_TERMINATE                 0xFFFFFFFFUL
00104 
00105 #define TWAIN_EVENT_NONE                0x00000000UL
00106 #define TWAIN_EVENT_QUIT                0x00000001UL
00107 #define TWAIN_EVENT_SCANNING    0x00000002UL
00108 #define TWAIN_EVENT_XFER                0x00000004UL
00109 
00110 #define PFUNC                                   (*pDSM)
00111 #define PTWAINMSG                               MSG*
00112 #define FIXTODOUBLE( nFix )     ((double)nFix.Whole+(double)nFix.Frac/65536.)
00113 #define FIXTOLONG( nFix )               ((long)floor(FIXTODOUBLE(nFix)+0.5))
00114                                                                 
00115 #if defined WIN                                 
00116 #define TWAIN_LIBNAME                   "TWAIN.DLL"
00117 #define TWAIN_FUNCNAME                  "DSM_Entry"
00118 #elif defined WNT                               
00119 #define TWAIN_LIBNAME                   "TWAIN_32.DLL"
00120 #define TWAIN_FUNCNAME                  "DSM_Entry"
00121 #endif
00122 
00123 // --------------
00124 // - TwainState -
00125 // --------------
00126 
00127 enum TwainState
00128 {
00129         TWAIN_STATE_NONE = 0,
00130         TWAIN_STATE_SCANNING = 1,
00131         TWAIN_STATE_DONE = 2,
00132         TWAIN_STATE_CANCELED = 3
00133 };
00134 
00135 // ------------
00136 // - ImpTwain -
00137 // ------------
00138 
00139 class ImpTwain : public ::cppu::WeakImplHelper1< util::XCloseListener >
00140 {
00141     friend LRESULT CALLBACK TwainMsgProc( int nCode, WPARAM wParam, LPARAM lParam );
00142 
00143     uno::Reference< uno::XInterface >                   mxSelfRef;
00144         uno::Reference< scanner::XScannerManager >      mxMgr;
00145         ScannerManager&                                                         mrMgr;
00146         TW_IDENTITY                                                                     aAppIdent;
00147         TW_IDENTITY                                                                     aSrcIdent;
00148         Link                                                                            aNotifyLink;
00149         DSMENTRYPROC                                                            pDSM;
00150         NAMESPACE_VOS( OModule )*                                       pMod;
00151         ULONG                                                                           nCurState;
00152         HWND                                                            hTwainWnd;
00153         HHOOK                                                           hTwainHook;
00154     bool                                                                                mbCloseFrameOnExit;
00155 
00156         bool                                                            ImplHandleMsg( void* pMsg );
00157         void                                                                            ImplCreate();
00158         void                                                                            ImplOpenSourceManager();
00159         void                                                                            ImplOpenSource();
00160         bool                                                                            ImplEnableSource();
00161         void                                                                            ImplXfer();
00162         void                                                                            ImplFallback( ULONG nEvent );
00163     void                                                                                ImplSendCloseEvent();
00164     void                                                                                ImplDeregisterCloseListener();
00165     void                                                                                ImplRegisterCloseListener();
00166     uno::Reference< frame::XFrame >                     ImplGetActiveFrame();
00167     uno::Reference< util::XCloseBroadcaster >   ImplGetActiveFrameCloseBroadcaster();
00168 
00169                                                                                                 DECL_LINK( ImplFallbackHdl, void* );
00170                                                                                                 DECL_LINK( ImplDestroyHdl, void* );
00171 
00172     // from util::XCloseListener
00173     virtual void SAL_CALL queryClosing( const lang::EventObject& Source, sal_Bool GetsOwnership ) throw (util::CloseVetoException, uno::RuntimeException);
00174     virtual void SAL_CALL notifyClosing( const lang::EventObject& Source ) throw (uno::RuntimeException);
00175 
00176     // from lang::XEventListener
00177     virtual void SAL_CALL disposing( const lang::EventObject& Source ) throw (uno::RuntimeException);
00178 
00179 public:
00180 
00181                                                                                 ImpTwain( ScannerManager& rMgr, const Link& rNotifyLink );
00182                                                                                 ~ImpTwain();
00183 
00184         void                                                            Destroy();
00185 
00186         bool                                                            SelectSource();
00187         bool                                                            InitXfer(); 
00188 };
00189 
00190 // ---------
00191 // - Procs -
00192 // ---------
00193 
00194 static ImpTwain* pImpTwainInstance = NULL;
00195 
00196 // -------------------------------------------------------------------------
00197 
00198 LRESULT CALLBACK TwainWndProc( HWND hWnd,UINT nMsg, WPARAM nPar1, LPARAM nPar2 )
00199 {
00200         return DefWindowProc( hWnd, nMsg, nPar1, nPar2 );
00201 }
00202 
00203 // -------------------------------------------------------------------------
00204 
00205 LRESULT CALLBACK TwainMsgProc( int nCode, WPARAM wParam, LPARAM lParam )
00206 {
00207         MSG* pMsg = (MSG*) lParam;
00208 
00209         if( ( nCode < 0 ) || ( pImpTwainInstance->hTwainWnd != pMsg->hwnd ) || !pImpTwainInstance->ImplHandleMsg( (void*) lParam ) )
00210         {
00211                 return CallNextHookEx( pImpTwainInstance->hTwainHook, nCode, wParam, lParam );
00212         }
00213         else
00214         {
00215                 pMsg->message = WM_USER;
00216                 pMsg->lParam = 0;
00217                 
00218                 return 0;
00219         }
00220 }
00221 
00222 // -----------------------------------------------------------------------------
00223 
00224 // #107835# hold reference to ScannerManager, to prevent premature death
00225 ImpTwain::ImpTwain( ScannerManager& rMgr, const Link& rNotifyLink ) :
00226                         mrMgr( rMgr ),
00227                     mxMgr( uno::Reference< scanner::XScannerManager >( static_cast< OWeakObject* >( &rMgr ), uno::UNO_QUERY) ),
00228                         aNotifyLink( rNotifyLink ),
00229                         pDSM( NULL ),
00230                         pMod( NULL ),
00231                         hTwainWnd( 0 ),
00232                         hTwainHook( 0 ),
00233                         nCurState( 1 ),
00234             mbCloseFrameOnExit( false )
00235 {
00236     // setup TWAIN window
00237         pImpTwainInstance = this;
00238 
00239         aAppIdent.Id = 0;
00240         aAppIdent.Version.MajorNum = 1;
00241         aAppIdent.Version.MinorNum = 0;
00242         aAppIdent.Version.Language = TWLG_USA;
00243         aAppIdent.Version.Country = TWCY_USA;
00244         aAppIdent.ProtocolMajor = TWON_PROTOCOLMAJOR;
00245         aAppIdent.ProtocolMinor = TWON_PROTOCOLMINOR;
00246         aAppIdent.SupportedGroups =     DG_IMAGE | DG_CONTROL;
00247         strncpy( aAppIdent.Version.Info, "8.0", 32 ); 
00248     aAppIdent.Version.Info[32] = aAppIdent.Version.Info[33] = 0;
00249         strncpy( aAppIdent.Manufacturer, "Sun Microsystems", 32 );
00250     aAppIdent.Manufacturer[32] = aAppIdent.Manufacturer[33] = 0;
00251         strncpy( aAppIdent.ProductFamily,"Office", 32 );
00252     aAppIdent.ProductFamily[32] = aAppIdent.ProductFamily[33] = 0;
00253         strncpy( aAppIdent.ProductName, "Office", 32 );
00254     aAppIdent.ProductName[32] = aAppIdent.ProductName[33] = 0;
00255 
00256         WNDCLASS aWc = { 0, &TwainWndProc, 0, sizeof( WNDCLASS ), GetModuleHandle( NULL ), NULL, NULL, NULL, NULL, "TwainClass" };
00257         RegisterClass( &aWc );
00258         
00259         hTwainWnd = CreateWindowEx( WS_EX_TOPMOST, aWc.lpszClassName, "TWAIN", 0, 0, 0, 0, 0, HWND_DESKTOP, NULL, aWc.hInstance, 0 );
00260         hTwainHook = SetWindowsHookEx( WH_GETMESSAGE, &TwainMsgProc, NULL, GetCurrentThreadId() );
00261 
00262     // #107835# block destruction until ImplDestroyHdl is called
00263     mxSelfRef = static_cast< ::cppu::OWeakObject* >( this );
00264 }
00265 
00266 // -----------------------------------------------------------------------------
00267 
00268 ImpTwain::~ImpTwain()
00269 {
00270     // are we responsible for application shutdown?
00271     if( mbCloseFrameOnExit )
00272         ImplSendCloseEvent();
00273 }
00274 
00275 // -----------------------------------------------------------------------------
00276 
00277 void ImpTwain::Destroy()
00278 {
00279         ImplFallback( TWAIN_EVENT_NONE );
00280         Application::PostUserEvent( LINK( this, ImpTwain, ImplDestroyHdl ), NULL );
00281 }
00282 
00283 // -----------------------------------------------------------------------------
00284 
00285 bool ImpTwain::SelectSource()
00286 {
00287         TW_UINT16 nRet = TWRC_FAILURE;
00288 
00289         ImplOpenSourceManager();
00290 
00291         if( 3 == nCurState )
00292         {
00293                 TW_IDENTITY aIdent;
00294 
00295                 aIdent.Id = 0, aIdent.ProductName[ 0 ] = '\0';
00296                 aNotifyLink.Call( (void*) TWAIN_EVENT_SCANNING );
00297                 nRet = PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_IDENTITY, MSG_USERSELECT, &aIdent );
00298         }
00299 
00300         ImplFallback( TWAIN_EVENT_QUIT );
00301 
00302         return( TWRC_SUCCESS == nRet );
00303 }
00304 
00305 // -----------------------------------------------------------------------------
00306 
00307 bool ImpTwain::InitXfer()
00308 {
00309         bool bRet = false;
00310 
00311         ImplOpenSourceManager();
00312 
00313         if( 3 == nCurState )
00314         {
00315                 ImplOpenSource();
00316 
00317                 if( 4 == nCurState )
00318                         bRet = ImplEnableSource();
00319         }
00320 
00321         if( !bRet )
00322                 ImplFallback( TWAIN_EVENT_QUIT );
00323 
00324         return bRet;
00325 }
00326 
00327 // -----------------------------------------------------------------------------
00328 
00329 void ImpTwain::ImplOpenSourceManager()
00330 {
00331         if( 1 == nCurState )
00332         {
00333                 pMod = new ::vos::OModule( ::rtl::OUString() );
00334 
00335                 if( pMod->load( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( TWAIN_LIBNAME ) ) ) )
00336                 {
00337                         nCurState = 2;
00338 
00339                         if( ( ( pDSM = (DSMENTRYPROC) pMod->getSymbol( String( RTL_CONSTASCII_USTRINGPARAM( TWAIN_FUNCNAME ) ) ) ) != NULL ) &&
00340                                 ( PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_PARENT, MSG_OPENDSM, &hTwainWnd ) == TWRC_SUCCESS ) )
00341                         {
00342                                 nCurState = 3;
00343                         }
00344                 }
00345                 else
00346                 {
00347                         delete pMod;
00348                         pMod = NULL;
00349                 }
00350         }
00351 }
00352 
00353 // -----------------------------------------------------------------------------
00354 
00355 void ImpTwain::ImplOpenSource()
00356 {
00357         if( 3 == nCurState )
00358         {
00359                 if( ( PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_IDENTITY, MSG_GETDEFAULT, &aSrcIdent ) == TWRC_SUCCESS ) &&
00360                         ( PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_IDENTITY, MSG_OPENDS, &aSrcIdent ) == TWRC_SUCCESS ) )
00361                 {
00362                         TW_CAPABILITY   aCap = { CAP_XFERCOUNT, TWON_ONEVALUE, GlobalAlloc( GHND, sizeof( TW_ONEVALUE ) ) };
00363                         TW_ONEVALUE*    pVal = (TW_ONEVALUE*) GlobalLock( aCap.hContainer );
00364 
00365                         pVal->ItemType = TWTY_INT16, pVal->Item = 1;
00366                         GlobalUnlock( aCap.hContainer );
00367                         PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_CAPABILITY, MSG_SET, &aCap );
00368                         GlobalFree( aCap.hContainer );
00369                         nCurState = 4;
00370                 }
00371         }
00372 }
00373 
00374 // -----------------------------------------------------------------------------
00375 
00376 bool ImpTwain::ImplEnableSource()
00377 {
00378         bool bRet = false;
00379 
00380         if( 4 == nCurState )
00381         {
00382                 TW_USERINTERFACE aUI = { true, true, hTwainWnd };
00383 
00384                 aNotifyLink.Call( (void*) TWAIN_EVENT_SCANNING );
00385                 nCurState = 5;
00386 
00387         // #107835# register as vetoable close listener, to prevent application to die under us
00388         ImplRegisterCloseListener();
00389 
00390                 if( PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_USERINTERFACE, MSG_ENABLEDS, &aUI ) == TWRC_SUCCESS )
00391         {
00392                         bRet = true;
00393         }
00394                 else
00395         {
00396                         nCurState = 4;
00397 
00398             // #107835# deregister as vetoable close listener, dialog failed
00399             ImplDeregisterCloseListener();
00400         }
00401         }
00402 
00403         return bRet;
00404 }
00405 
00406 // -----------------------------------------------------------------------------
00407 
00408 bool ImpTwain::ImplHandleMsg( void* pMsg )
00409 {
00410         TW_UINT16       nRet;
00411         PTWAINMSG       pMess = (PTWAINMSG) pMsg;
00412         TW_EVENT        aEvt = { pMess, MSG_NULL };
00413 
00414         nRet = PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_EVENT, MSG_PROCESSEVENT, &aEvt );
00415 
00416         if( aEvt.TWMessage != MSG_NULL )
00417         {
00418                 switch( aEvt.TWMessage )
00419                 {
00420                         case MSG_XFERREADY:
00421                         {
00422                                 ULONG nEvent = TWAIN_EVENT_QUIT;
00423 
00424                                 if( 5 == nCurState )
00425                                 {
00426                                         nCurState = 6;
00427                                         ImplXfer();
00428 
00429                                         if( mrMgr.GetData() )
00430                                                 nEvent = TWAIN_EVENT_XFER;
00431                                 }
00432 
00433                                 ImplFallback( nEvent );
00434                         }
00435                         break;
00436                         
00437                         case MSG_CLOSEDSREQ:
00438                                 ImplFallback( TWAIN_EVENT_QUIT );
00439                         break;
00440 
00441                         default:
00442                         break;
00443                 }
00444         }
00445         else
00446                 nRet = TWRC_NOTDSEVENT;
00447 
00448         return( TWRC_DSEVENT == nRet );
00449 }
00450 
00451 // -----------------------------------------------------------------------------
00452 
00453 void ImpTwain::ImplXfer()
00454 {
00455         if( nCurState == 6 )
00456         {
00457                 TW_IMAGEINFO    aInfo;
00458                 TW_UINT32               hDIB = 0;
00459                 long                    nWidth, nHeight, nXRes, nYRes;
00460 
00461                 if( PFUNC( &aAppIdent, &aSrcIdent, DG_IMAGE, DAT_IMAGEINFO, MSG_GET, &aInfo ) == TWRC_SUCCESS )
00462                 {
00463                         nWidth = aInfo.ImageWidth;
00464                         nHeight = aInfo.ImageLength;
00465                         nXRes = FIXTOLONG( aInfo.XResolution );
00466                         nYRes = FIXTOLONG( aInfo.YResolution );
00467                 }
00468                 else
00469                         nWidth = nHeight = nXRes = nYRes = -1L;
00470 
00471                 switch( PFUNC( &aAppIdent, &aSrcIdent, DG_IMAGE, DAT_IMAGENATIVEXFER, MSG_GET, &hDIB ) )
00472                 {
00473                         case( TWRC_CANCEL ):
00474                                 nCurState = 7;
00475                         break;
00476 
00477                         case( TWRC_XFERDONE ):
00478                         {
00479                                 if( hDIB )
00480                                 {
00481                                         if( ( nXRes != -1 ) && ( nYRes != - 1 ) && ( nWidth != - 1 ) && ( nHeight != - 1 ) )
00482                                         {
00483                                                 // set resolution of bitmap
00484                                                 BITMAPINFOHEADER*       pBIH = (BITMAPINFOHEADER*) GlobalLock( (HGLOBAL) hDIB );
00485                                                 static const double     fFactor = 100.0 / 2.54;
00486 
00487                                                 pBIH->biXPelsPerMeter = FRound( fFactor * nXRes );
00488                                                 pBIH->biYPelsPerMeter = FRound( fFactor * nYRes );
00489 
00490                                                 GlobalUnlock( (HGLOBAL) hDIB );
00491                                         }
00492 
00493                                         mrMgr.SetData( (void*)(long) hDIB );
00494                                 }
00495                                 else
00496                                         GlobalFree( (HGLOBAL) hDIB );
00497 
00498                                 nCurState = 7;
00499                         }
00500                         break;
00501 
00502                         default:
00503                         break;
00504                 }
00505         }
00506 }
00507 
00508 // -----------------------------------------------------------------------------
00509 
00510 void ImpTwain::ImplFallback( ULONG nEvent )
00511 {
00512         Application::PostUserEvent( LINK( this, ImpTwain, ImplFallbackHdl ), (void*) nEvent );
00513 }
00514 
00515 // -----------------------------------------------------------------------------
00516 
00517 IMPL_LINK( ImpTwain, ImplFallbackHdl, void*, pData )
00518 {
00519         const ULONG     nEvent = (ULONG) pData;
00520         bool            bFallback = true;
00521 
00522         switch( nCurState )
00523         {
00524                 case( 7 ):
00525                 case( 6 ):
00526                 {
00527                         TW_PENDINGXFERS aXfers;
00528 
00529                         if( PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, &aXfers ) == TWRC_SUCCESS )
00530                         {
00531                                 if( aXfers.Count != 0 )
00532                                         PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_PENDINGXFERS, MSG_RESET, &aXfers );
00533                         }
00534 
00535                         nCurState = 5;
00536                 }
00537                 break;
00538 
00539                 case( 5 ):
00540                 {
00541                         TW_USERINTERFACE aUI = { true, true, hTwainWnd };
00542                 
00543                         PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_USERINTERFACE, MSG_DISABLEDS, &aUI );
00544                         nCurState = 4;
00545 
00546             // #107835# deregister as vetoable close listener
00547             ImplDeregisterCloseListener();
00548                 }
00549                 break;
00550 
00551                 case( 4 ):
00552                 {
00553                         PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_IDENTITY, MSG_CLOSEDS, &aSrcIdent );
00554                         nCurState = 3;
00555                 }
00556                 break;
00557 
00558                 case( 3 ):
00559                 {
00560                         PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_PARENT, MSG_CLOSEDSM, &hTwainWnd );
00561                         nCurState = 2;
00562                 }
00563                 break;
00564 
00565                 case( 2 ):
00566                 {
00567                         delete pMod;
00568                         pMod = NULL;
00569                         nCurState = 1;
00570                 }
00571                 break;
00572 
00573                 default:
00574                 {
00575                         if( nEvent != TWAIN_EVENT_NONE )
00576                                 aNotifyLink.Call( (void*) nEvent );
00577 
00578                         bFallback = false;
00579                 }
00580                 break;
00581         }
00582 
00583         if( bFallback )
00584                 ImplFallback( nEvent );
00585 
00586         return 0L;
00587 }
00588 
00589 // -----------------------------------------------------------------------------
00590 
00591 IMPL_LINK( ImpTwain, ImplDestroyHdl, void*, /*p*/ )
00592 {
00593         if( hTwainWnd )
00594                 DestroyWindow( hTwainWnd );
00595 
00596         if( hTwainHook )
00597                 UnhookWindowsHookEx( hTwainHook );
00598 
00599     // #107835# permit destruction of ourselves (normally, refcount
00600     // should drop to zero exactly here)
00601         mxSelfRef = NULL;
00602         pImpTwainInstance = NULL;
00603 
00604         return 0L;
00605 }
00606 
00607 // -----------------------------------------------------------------------------
00608 
00609 uno::Reference< frame::XFrame > ImpTwain::ImplGetActiveFrame()
00610 {
00611     try
00612     {
00613         uno::Reference< lang::XMultiServiceFactory >  xMgr( ::comphelper::getProcessServiceFactory() );
00614 
00615         if( xMgr.is() )
00616         {
00617             // query desktop instance
00618             uno::Reference< frame::XDesktop > xDesktop( xMgr->createInstance(
00619                                                             OUString::createFromAscii( "com.sun.star.frame.Desktop" ) ), uno::UNO_QUERY );
00620         
00621             if( xDesktop.is() )
00622             {
00623                 // query property set from desktop, which contains the currently active frame
00624                 uno::Reference< beans::XPropertySet > xDesktopProps( xDesktop, uno::UNO_QUERY );
00625 
00626                 if( xDesktopProps.is() )
00627                 {
00628                     uno::Any aActiveFrame;
00629 
00630                     try
00631                     {
00632                         aActiveFrame = xDesktopProps->getPropertyValue(
00633                             OUString::createFromAscii( "ActiveFrame" ) );
00634                     }
00635                     catch( const beans::UnknownPropertyException& )
00636                     {
00637                         // property unknown.
00638                         DBG_ERROR("ImpTwain::ImplGetActiveFrame: ActiveFrame property unknown, cannot determine active frame!");
00639                         return uno::Reference< frame::XFrame >();
00640                     }
00641 
00642                     uno::Reference< frame::XFrame > xActiveFrame;
00643                 
00644                     if( (aActiveFrame >>= xActiveFrame) &&
00645                         xActiveFrame.is() )
00646                     {
00647                         return xActiveFrame;
00648                     }
00649                 }
00650             }
00651         }
00652     }
00653     catch( const uno::Exception& )
00654     {
00655     }
00656 
00657     DBG_ERROR("ImpTwain::ImplGetActiveFrame: Could not determine active frame!");
00658     return uno::Reference< frame::XFrame >();
00659 }
00660 
00661 // -----------------------------------------------------------------------------
00662 
00663 uno::Reference< util::XCloseBroadcaster > ImpTwain::ImplGetActiveFrameCloseBroadcaster()
00664 {
00665     try
00666     {
00667         return uno::Reference< util::XCloseBroadcaster >( ImplGetActiveFrame(), uno::UNO_QUERY );
00668     }
00669     catch( const uno::Exception& )
00670     {
00671     }
00672 
00673     DBG_ERROR("ImpTwain::ImplGetActiveFrameCloseBroadcaster: Could determine close broadcaster on active frame!");
00674     return uno::Reference< util::XCloseBroadcaster >();
00675 }
00676 
00677 // -----------------------------------------------------------------------------
00678 
00679 void ImpTwain::ImplRegisterCloseListener()
00680 {
00681     try
00682     {
00683         uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( ImplGetActiveFrameCloseBroadcaster() );
00684         
00685         if( xCloseBroadcaster.is() )
00686         {
00687             xCloseBroadcaster->addCloseListener(this);
00688             return; // successfully registered as a close listener
00689         }
00690         else
00691         {
00692             // interface unknown. don't register, then
00693             DBG_ERROR("ImpTwain::ImplRegisterCloseListener: XFrame has no XCloseBroadcaster!");
00694             return;
00695         }
00696     }
00697     catch( const uno::Exception& )
00698     {
00699     }
00700 
00701     DBG_ERROR("ImpTwain::ImplRegisterCloseListener: Could not register as close listener!");
00702 }
00703 
00704 // -----------------------------------------------------------------------------
00705 
00706 void ImpTwain::ImplDeregisterCloseListener()
00707 {
00708     try
00709     {
00710         uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( 
00711             ImplGetActiveFrameCloseBroadcaster() );
00712         
00713         if( xCloseBroadcaster.is() )
00714         {
00715             xCloseBroadcaster->removeCloseListener(this);
00716             return; // successfully deregistered as a close listener
00717         }
00718         else
00719         {
00720             // interface unknown. don't deregister, then
00721             DBG_ERROR("ImpTwain::ImplDeregisterCloseListener: XFrame has no XCloseBroadcaster!");
00722             return;
00723         }
00724     }
00725     catch( const uno::Exception& )
00726     {
00727     }
00728 
00729     DBG_ERROR("ImpTwain::ImplDeregisterCloseListener: Could not deregister as close listener!");
00730 }
00731 
00732 // -----------------------------------------------------------------------------
00733 
00734 void SAL_CALL ImpTwain::queryClosing( const lang::EventObject& /*Source*/, sal_Bool GetsOwnership ) throw (util::CloseVetoException, uno::RuntimeException)
00735 {
00736     // shall we re-send the close query later on?
00737     mbCloseFrameOnExit = GetsOwnership;
00738 
00739     // the sole purpose of this listener is to forbid closing of the listened-at frame
00740     throw util::CloseVetoException();
00741 }
00742 
00743 // -----------------------------------------------------------------------------
00744 
00745 void SAL_CALL ImpTwain::notifyClosing( const lang::EventObject& /*Source*/ ) throw (uno::RuntimeException)
00746 {
00747     // should not happen
00748     DBG_ERROR("ImpTwain::notifyClosing called, but we vetoed the closing before!");
00749 }
00750 
00751 // -----------------------------------------------------------------------------
00752 
00753 void SAL_CALL ImpTwain::disposing( const lang::EventObject& /*Source*/ ) throw (uno::RuntimeException)
00754 {
00755     // we're not holding any references to the frame, thus noop
00756 }
00757 
00758 // -----------------------------------------------------------------------------
00759 
00760 void ImpTwain::ImplSendCloseEvent()
00761 {
00762     try
00763     {
00764         uno::Reference< util::XCloseable > xCloseable( ImplGetActiveFrame(), uno::UNO_QUERY );
00765         
00766         if( xCloseable.is() )
00767             xCloseable->close( true );
00768     }
00769     catch( const uno::Exception& )
00770     {
00771     }
00772 
00773     DBG_ERROR("ImpTwain::ImplSendCloseEvent: Could not send required close broadcast!");
00774 }
00775 
00776 
00777 // ---------
00778 // - Twain -
00779 // ---------
00780 
00781 class Twain
00782 {
00783         uno::Reference< lang::XEventListener >      mxListener;
00784         uno::Reference< scanner::XScannerManager >      mxMgr;
00785         const ScannerManager*                               mpCurMgr;
00786         ImpTwain*                                                           mpImpTwain;
00787         TwainState                                                          meState;
00788                                                                                                 
00789                                                                                     DECL_LINK( ImpNotifyHdl, ImpTwain* );
00790                                                                                                                 
00791 public:                                                                                                 
00792                                                                                                                 
00793                                                                         Twain();
00794                                                                         ~Twain();
00795                                                                                                                 
00796         bool                                                    SelectSource( ScannerManager& rMgr );
00797         bool                                                    PerformTransfer( ScannerManager& rMgr, const uno::Reference< lang::XEventListener >& rxListener );
00798                                                                                                                 
00799         TwainState                                              GetState() const { return meState; }
00800 };
00801 
00802 // ------------------------------------------------------------------------
00803 
00804 Twain::Twain() :
00805                 mpCurMgr( NULL ),
00806                 mpImpTwain( NULL ),
00807                 meState( TWAIN_STATE_NONE )
00808 {
00809 }
00810 
00811 // ------------------------------------------------------------------------
00812 
00813 Twain::~Twain()
00814 {
00815         if( mpImpTwain )
00816                 mpImpTwain->Destroy();
00817 }
00818 
00819 // ------------------------------------------------------------------------
00820 
00821 bool Twain::SelectSource( ScannerManager& rMgr )
00822 {
00823         bool bRet;
00824 
00825         if( !mpImpTwain )
00826         {
00827         // #107835# hold reference to ScannerManager, to prevent premature death
00828         mxMgr = uno::Reference< scanner::XScannerManager >( static_cast< OWeakObject* >( const_cast< ScannerManager* >( mpCurMgr = &rMgr ) ),
00829                                                             uno::UNO_QUERY ),
00830                 
00831                 meState = TWAIN_STATE_NONE;
00832                 mpImpTwain = new ImpTwain( rMgr, LINK( this, Twain, ImpNotifyHdl ) );
00833                 bRet = mpImpTwain->SelectSource();
00834         }
00835         else
00836                 bRet = false;
00837 
00838         return bRet;
00839 }
00840 
00841 // ------------------------------------------------------------------------
00842 
00843 bool Twain::PerformTransfer( ScannerManager& rMgr, const uno::Reference< lang::XEventListener >& rxListener )
00844 {
00845         bool bRet;
00846 
00847         if( !mpImpTwain )
00848         {
00849         // #107835# hold reference to ScannerManager, to prevent premature death
00850         mxMgr = uno::Reference< scanner::XScannerManager >( static_cast< OWeakObject* >( const_cast< ScannerManager* >( mpCurMgr = &rMgr ) ),
00851                                                             uno::UNO_QUERY ),
00852                 
00853                 mxListener = rxListener;
00854                 meState = TWAIN_STATE_NONE;
00855                 mpImpTwain = new ImpTwain( rMgr, LINK( this, Twain, ImpNotifyHdl ) );
00856                 bRet = mpImpTwain->InitXfer();
00857         }
00858         else
00859                 bRet = false;
00860 
00861         return bRet;
00862 }
00863 
00864 // ------------------------------------------------------------------------
00865 
00866 IMPL_LINK( Twain, ImpNotifyHdl, ImpTwain*, nEvent )
00867 {
00868         switch( (ULONG)(void*) nEvent )
00869         {
00870                 case( TWAIN_EVENT_SCANNING ):
00871                         meState = TWAIN_STATE_SCANNING;
00872                 break;
00873 
00874                 case( TWAIN_EVENT_QUIT ):
00875                 {
00876                         if( meState != TWAIN_STATE_DONE )
00877                                 meState = TWAIN_STATE_CANCELED;
00878 
00879                         if( mpImpTwain )
00880                         {
00881                             mpImpTwain->Destroy();
00882                             mpImpTwain = NULL;
00883                 mpCurMgr = NULL;
00884                         }
00885 
00886                         if( mxListener.is() )
00887                                 mxListener->disposing( lang::EventObject( mxMgr ) );
00888 
00889                         mxListener = NULL;
00890                 }
00891                 break;
00892 
00893                 case( TWAIN_EVENT_XFER ):
00894                 {
00895                         if( mpImpTwain )
00896                         {
00897                                 meState = ( mpCurMgr->GetData() ? TWAIN_STATE_DONE : TWAIN_STATE_CANCELED );
00898                                 
00899                                 mpImpTwain->Destroy();
00900                                 mpImpTwain = NULL;
00901                 mpCurMgr = NULL;
00902 
00903                                 if( mxListener.is() )
00904                                         mxListener->disposing( lang::EventObject( mxMgr ) );
00905                         }
00906 
00907                         mxListener = NULL;
00908                 }
00909                 break;
00910 
00911                 default:
00912                 break;
00913         }
00914 
00915         return 0L;
00916 }
00917 
00918 // -----------
00919 // - statics -
00920 // -----------
00921 
00922 static Twain aTwain;
00923 
00924 // ------------------
00925 // - ScannerManager -
00926 // ------------------
00927 
00928 void ScannerManager::DestroyData()
00929 {
00930         if( mpData )
00931         {
00932                 GlobalFree( (HGLOBAL)(long) mpData );
00933                 mpData = NULL;
00934         }
00935 }
00936 
00937 // -----------------------------------------------------------------------------
00938 
00939 AWT::Size ScannerManager::getSize() throw()
00940 {
00941         AWT::Size       aRet;
00942         HGLOBAL         hDIB = (HGLOBAL)(long) mpData;
00943 
00944         if( hDIB )
00945         {
00946                 BITMAPINFOHEADER* pBIH = (BITMAPINFOHEADER*) GlobalLock( hDIB );
00947 
00948                 if( pBIH )
00949                 {
00950                         aRet.Width = pBIH->biWidth;
00951                         aRet.Height = pBIH->biHeight; 
00952                 }
00953                 else
00954                         aRet.Width = aRet.Height = 0;
00955 
00956                 GlobalUnlock( hDIB );
00957         }
00958         else
00959                 aRet.Width = aRet.Height = 0;
00960 
00961         return aRet;
00962 }
00963 
00964 // -----------------------------------------------------------------------------
00965 
00966 SEQ( sal_Int8 ) ScannerManager::getDIB() throw()
00967 {
00968         SEQ( sal_Int8 ) aRet;
00969 
00970         if( mpData )
00971         {
00972                 HGLOBAL                         hDIB = (HGLOBAL)(long) mpData;
00973                 const sal_uInt32        nDIBSize = GlobalSize( hDIB );
00974                 BITMAPINFOHEADER*       pBIH = (BITMAPINFOHEADER*) GlobalLock( hDIB );
00975 
00976                 if( pBIH )
00977                 {
00978                         sal_uInt32      nColEntries;
00979 
00980                         switch( pBIH->biBitCount )
00981                         {
00982                                 case( 1 ):
00983                                 case( 4 ):
00984                                 case( 8 ):
00985                                         nColEntries = pBIH->biClrUsed ? pBIH->biClrUsed : ( 1 << pBIH->biBitCount );
00986                                 break;
00987 
00988                                 case( 24 ):
00989                                         nColEntries = pBIH->biClrUsed ? pBIH->biClrUsed : 0;
00990                                 break;
00991 
00992                                 case( 16 ):
00993                                 case( 32 ):
00994                                 {
00995                                         nColEntries = pBIH->biClrUsed;
00996 
00997                                         if( pBIH->biCompression == BI_BITFIELDS )
00998                                                 nColEntries += 3;
00999                                 }
01000                                 break;
01001 
01002                                 default:
01003                                         nColEntries = 0;
01004                                 break;
01005                         }
01006 
01007                         aRet = SEQ( sal_Int8 )( sizeof( BITMAPFILEHEADER ) + nDIBSize );
01008                         
01009                         sal_Int8*               pBuf = aRet.getArray();
01010                         SvMemoryStream* pMemStm = new SvMemoryStream( (char*) pBuf, sizeof( BITMAPFILEHEADER ), STREAM_WRITE );
01011 
01012                         *pMemStm << 'B' << 'M' << (sal_uInt32) 0 << (sal_uInt32) 0;
01013                         *pMemStm << (sal_uInt32) ( sizeof( BITMAPFILEHEADER ) + pBIH->biSize + ( nColEntries * sizeof( RGBQUAD ) ) );
01014 
01015                         delete pMemStm;
01016                         memcpy( pBuf + sizeof( BITMAPFILEHEADER ), pBIH, nDIBSize );
01017                 }
01018 
01019                 GlobalUnlock( hDIB );
01020                 DestroyData();
01021         }
01022 
01023         return aRet;
01024 }
01025 
01026 // -----------------------------------------------------------------------------
01027 
01028 SEQ( ScannerContext ) SAL_CALL ScannerManager::getAvailableScanners() throw()
01029 {
01030         vos::OGuard                             aGuard( maProtector );
01031         SEQ( ScannerContext )   aRet( 1 );
01032         
01033         aRet.getArray()[0].ScannerName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TWAIN" ) );
01034         aRet.getArray()[0].InternalData = 0;
01035 
01036         return aRet;
01037 }
01038 
01039 // -----------------------------------------------------------------------------
01040 
01041 BOOL SAL_CALL ScannerManager::configureScanner( ScannerContext& rContext ) 
01042     throw( ScannerException )
01043 {
01044         vos::OGuard                                         aGuard( maProtector );
01045         uno::Reference< XScannerManager >       xThis( this );
01046 
01047         if( rContext.InternalData != 0 || rContext.ScannerName != ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TWAIN" ) ) )
01048                 throw ScannerException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Scanner does not exist" ) ), xThis, ScanError_InvalidContext );
01049 
01050         DestroyData();
01051 
01052         return aTwain.SelectSource( *this );
01053 }
01054 
01055 // -----------------------------------------------------------------------------
01056 
01057 void SAL_CALL ScannerManager::startScan( const ScannerContext& rContext, const uno::Reference< lang::XEventListener >& rxListener ) 
01058     throw( ScannerException )
01059 {
01060         vos::OGuard                                         aGuard( maProtector );
01061         uno::Reference< XScannerManager >       xThis( this );
01062 
01063         if( rContext.InternalData != 0 || rContext.ScannerName != ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TWAIN" ) ) )
01064                 throw ScannerException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Scanner does not exist" ) ), xThis, ScanError_InvalidContext );
01065 
01066         DestroyData();
01067         aTwain.PerformTransfer( *this, rxListener );
01068 }
01069 
01070 // -----------------------------------------------------------------------------
01071 
01072 ScanError SAL_CALL ScannerManager::getError( const ScannerContext& rContext )
01073     throw( ScannerException )
01074 {
01075         vos::OGuard                                         aGuard( maProtector );
01076         uno::Reference< XScannerManager >       xThis( this );
01077 
01078         if( rContext.InternalData != 0 || rContext.ScannerName != ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TWAIN" ) ) )
01079                 throw ScannerException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Scanner does not exist" ) ), xThis, ScanError_InvalidContext );
01080     
01081         return( ( aTwain.GetState() == TWAIN_STATE_CANCELED ) ? ScanError_ScanCanceled : ScanError_ScanErrorNone );
01082 }
01083 
01084 // -----------------------------------------------------------------------------
01085 
01086 uno::Reference< awt::XBitmap > SAL_CALL ScannerManager::getBitmap( const ScannerContext& /*rContext*/ ) 
01087     throw( ScannerException )
01088 {
01089         vos::OGuard     aGuard( maProtector );
01090         return uno::Reference< awt::XBitmap >( this );
01091 }

Generated on Thu Feb 28 17:53:27 2008 for AquaScanner by  doxygen 1.5.1