1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: scanwin.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_extensions.hxx"
33 #include <com/sun/star/uno/Any.hxx>
34 #include <com/sun/star/uno/Reference.hxx>
35 #include <com/sun/star/util/XCloseable.hpp>
36 #include <com/sun/star/util/XCloseBroadcaster.hpp>
37 #include <com/sun/star/util/XCloseListener.hpp>
38 #include <com/sun/star/frame/XFrame.hpp>
39 #include <com/sun/star/frame/XDesktop.hpp>
40 #include <com/sun/star/beans/XPropertySet.hpp>
41 #include <cppuhelper/implbase1.hxx>
42 #include <comphelper/processfactory.hxx>
45 #include <tools/svwin.h>
46 #include <tools/stream.hxx>
47 #include <vos/mutex.hxx>
48 #include <vos/module.hxx>
49 #include <vcl/svapp.hxx>
50 #include <vcl/wrkwin.hxx>
51 #include <vcl/sysdata.hxx>
52 #include <vcl/salbtype.hxx>
53 #include "scanner.hxx"
55 #pragma warning (push,1)
56 #pragma warning (disable:4668)
57 #include "twain/twain.h"
60 using namespace ::com::sun::star
;
66 #define TWAIN_SELECT 0x00000001UL
67 #define TWAIN_ACQUIRE 0x00000002UL
68 #define TWAIN_TERMINATE 0xFFFFFFFFUL
70 #define TWAIN_EVENT_NONE 0x00000000UL
71 #define TWAIN_EVENT_QUIT 0x00000001UL
72 #define TWAIN_EVENT_SCANNING 0x00000002UL
73 #define TWAIN_EVENT_XFER 0x00000004UL
76 #define PTWAINMSG MSG*
77 #define FIXTODOUBLE( nFix ) ((double)nFix.Whole+(double)nFix.Frac/65536.)
78 #define FIXTOLONG( nFix ) ((long)floor(FIXTODOUBLE(nFix)+0.5))
81 #define TWAIN_LIBNAME "TWAIN.DLL"
82 #define TWAIN_FUNCNAME "DSM_Entry"
84 #define TWAIN_LIBNAME "TWAIN_32.DLL"
85 #define TWAIN_FUNCNAME "DSM_Entry"
95 TWAIN_STATE_SCANNING
= 1,
97 TWAIN_STATE_CANCELED
= 3
104 class ImpTwain
: public ::cppu::WeakImplHelper1
< util::XCloseListener
>
106 friend LRESULT CALLBACK
TwainMsgProc( int nCode
, WPARAM wParam
, LPARAM lParam
);
108 uno::Reference
< uno::XInterface
> mxSelfRef
;
109 uno::Reference
< scanner::XScannerManager
> mxMgr
;
110 ScannerManager
& mrMgr
;
111 TW_IDENTITY aAppIdent
;
112 TW_IDENTITY aSrcIdent
;
115 NAMESPACE_VOS( OModule
)* pMod
;
119 bool mbCloseFrameOnExit
;
121 bool ImplHandleMsg( void* pMsg
);
123 void ImplOpenSourceManager();
124 void ImplOpenSource();
125 bool ImplEnableSource();
127 void ImplFallback( ULONG nEvent
);
128 void ImplSendCloseEvent();
129 void ImplDeregisterCloseListener();
130 void ImplRegisterCloseListener();
131 uno::Reference
< frame::XFrame
> ImplGetActiveFrame();
132 uno::Reference
< util::XCloseBroadcaster
> ImplGetActiveFrameCloseBroadcaster();
134 DECL_LINK( ImplFallbackHdl
, void* );
135 DECL_LINK( ImplDestroyHdl
, void* );
137 // from util::XCloseListener
138 virtual void SAL_CALL
queryClosing( const lang::EventObject
& Source
, sal_Bool GetsOwnership
) throw (util::CloseVetoException
, uno::RuntimeException
);
139 virtual void SAL_CALL
notifyClosing( const lang::EventObject
& Source
) throw (uno::RuntimeException
);
141 // from lang::XEventListener
142 virtual void SAL_CALL
disposing( const lang::EventObject
& Source
) throw (uno::RuntimeException
);
146 ImpTwain( ScannerManager
& rMgr
, const Link
& rNotifyLink
);
159 static ImpTwain
* pImpTwainInstance
= NULL
;
161 // -------------------------------------------------------------------------
163 LRESULT CALLBACK
TwainWndProc( HWND hWnd
,UINT nMsg
, WPARAM nPar1
, LPARAM nPar2
)
165 return DefWindowProc( hWnd
, nMsg
, nPar1
, nPar2
);
168 // -------------------------------------------------------------------------
170 LRESULT CALLBACK
TwainMsgProc( int nCode
, WPARAM wParam
, LPARAM lParam
)
172 MSG
* pMsg
= (MSG
*) lParam
;
174 if( ( nCode
< 0 ) || ( pImpTwainInstance
->hTwainWnd
!= pMsg
->hwnd
) || !pImpTwainInstance
->ImplHandleMsg( (void*) lParam
) )
176 return CallNextHookEx( pImpTwainInstance
->hTwainHook
, nCode
, wParam
, lParam
);
180 pMsg
->message
= WM_USER
;
187 // -----------------------------------------------------------------------------
189 // #107835# hold reference to ScannerManager, to prevent premature death
190 ImpTwain::ImpTwain( ScannerManager
& rMgr
, const Link
& rNotifyLink
) :
192 mxMgr( uno::Reference
< scanner::XScannerManager
>( static_cast< OWeakObject
* >( &rMgr
), uno::UNO_QUERY
) ),
193 aNotifyLink( rNotifyLink
),
199 mbCloseFrameOnExit( false )
201 // setup TWAIN window
202 pImpTwainInstance
= this;
205 aAppIdent
.Version
.MajorNum
= 1;
206 aAppIdent
.Version
.MinorNum
= 0;
207 aAppIdent
.Version
.Language
= TWLG_USA
;
208 aAppIdent
.Version
.Country
= TWCY_USA
;
209 aAppIdent
.ProtocolMajor
= TWON_PROTOCOLMAJOR
;
210 aAppIdent
.ProtocolMinor
= TWON_PROTOCOLMINOR
;
211 aAppIdent
.SupportedGroups
= DG_IMAGE
| DG_CONTROL
;
212 strncpy( aAppIdent
.Version
.Info
, "8.0", 32 );
213 aAppIdent
.Version
.Info
[32] = aAppIdent
.Version
.Info
[33] = 0;
214 strncpy( aAppIdent
.Manufacturer
, "Sun Microsystems", 32 );
215 aAppIdent
.Manufacturer
[32] = aAppIdent
.Manufacturer
[33] = 0;
216 strncpy( aAppIdent
.ProductFamily
,"Office", 32 );
217 aAppIdent
.ProductFamily
[32] = aAppIdent
.ProductFamily
[33] = 0;
218 strncpy( aAppIdent
.ProductName
, "Office", 32 );
219 aAppIdent
.ProductName
[32] = aAppIdent
.ProductName
[33] = 0;
221 WNDCLASS aWc
= { 0, &TwainWndProc
, 0, sizeof( WNDCLASS
), GetModuleHandle( NULL
), NULL
, NULL
, NULL
, NULL
, "TwainClass" };
222 RegisterClass( &aWc
);
224 hTwainWnd
= CreateWindowEx( WS_EX_TOPMOST
, aWc
.lpszClassName
, "TWAIN", 0, 0, 0, 0, 0, HWND_DESKTOP
, NULL
, aWc
.hInstance
, 0 );
225 hTwainHook
= SetWindowsHookEx( WH_GETMESSAGE
, &TwainMsgProc
, NULL
, GetCurrentThreadId() );
227 // #107835# block destruction until ImplDestroyHdl is called
228 mxSelfRef
= static_cast< ::cppu::OWeakObject
* >( this );
231 // -----------------------------------------------------------------------------
233 ImpTwain::~ImpTwain()
235 // are we responsible for application shutdown?
236 if( mbCloseFrameOnExit
)
237 ImplSendCloseEvent();
240 // -----------------------------------------------------------------------------
242 void ImpTwain::Destroy()
244 ImplFallback( TWAIN_EVENT_NONE
);
245 Application::PostUserEvent( LINK( this, ImpTwain
, ImplDestroyHdl
), NULL
);
248 // -----------------------------------------------------------------------------
250 bool ImpTwain::SelectSource()
252 TW_UINT16 nRet
= TWRC_FAILURE
;
254 ImplOpenSourceManager();
260 aIdent
.Id
= 0, aIdent
.ProductName
[ 0 ] = '\0';
261 aNotifyLink
.Call( (void*) TWAIN_EVENT_SCANNING
);
262 nRet
= PFUNC( &aAppIdent
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_USERSELECT
, &aIdent
);
265 ImplFallback( TWAIN_EVENT_QUIT
);
267 return( TWRC_SUCCESS
== nRet
);
270 // -----------------------------------------------------------------------------
272 bool ImpTwain::InitXfer()
276 ImplOpenSourceManager();
283 bRet
= ImplEnableSource();
287 ImplFallback( TWAIN_EVENT_QUIT
);
292 // -----------------------------------------------------------------------------
294 void ImpTwain::ImplOpenSourceManager()
298 pMod
= new ::vos::OModule( ::rtl::OUString() );
300 if( pMod
->load( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( TWAIN_LIBNAME
) ) ) )
304 if( ( ( pDSM
= (DSMENTRYPROC
) pMod
->getSymbol( String( RTL_CONSTASCII_USTRINGPARAM( TWAIN_FUNCNAME
) ) ) ) != NULL
) &&
305 ( PFUNC( &aAppIdent
, NULL
, DG_CONTROL
, DAT_PARENT
, MSG_OPENDSM
, &hTwainWnd
) == TWRC_SUCCESS
) )
318 // -----------------------------------------------------------------------------
320 void ImpTwain::ImplOpenSource()
324 if( ( PFUNC( &aAppIdent
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_GETDEFAULT
, &aSrcIdent
) == TWRC_SUCCESS
) &&
325 ( PFUNC( &aAppIdent
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_OPENDS
, &aSrcIdent
) == TWRC_SUCCESS
) )
327 TW_CAPABILITY aCap
= { CAP_XFERCOUNT
, TWON_ONEVALUE
, GlobalAlloc( GHND
, sizeof( TW_ONEVALUE
) ) };
328 TW_ONEVALUE
* pVal
= (TW_ONEVALUE
*) GlobalLock( aCap
.hContainer
);
330 pVal
->ItemType
= TWTY_INT16
, pVal
->Item
= 1;
331 GlobalUnlock( aCap
.hContainer
);
332 PFUNC( &aAppIdent
, &aSrcIdent
, DG_CONTROL
, DAT_CAPABILITY
, MSG_SET
, &aCap
);
333 GlobalFree( aCap
.hContainer
);
339 // -----------------------------------------------------------------------------
341 bool ImpTwain::ImplEnableSource()
347 TW_USERINTERFACE aUI
= { true, true, hTwainWnd
};
349 aNotifyLink
.Call( (void*) TWAIN_EVENT_SCANNING
);
352 // #107835# register as vetoable close listener, to prevent application to die under us
353 ImplRegisterCloseListener();
355 if( PFUNC( &aAppIdent
, &aSrcIdent
, DG_CONTROL
, DAT_USERINTERFACE
, MSG_ENABLEDS
, &aUI
) == TWRC_SUCCESS
)
363 // #107835# deregister as vetoable close listener, dialog failed
364 ImplDeregisterCloseListener();
371 // -----------------------------------------------------------------------------
373 bool ImpTwain::ImplHandleMsg( void* pMsg
)
376 PTWAINMSG pMess
= (PTWAINMSG
) pMsg
;
377 TW_EVENT aEvt
= { pMess
, MSG_NULL
};
379 nRet
= PFUNC( &aAppIdent
, &aSrcIdent
, DG_CONTROL
, DAT_EVENT
, MSG_PROCESSEVENT
, &aEvt
);
381 if( aEvt
.TWMessage
!= MSG_NULL
)
383 switch( aEvt
.TWMessage
)
387 ULONG nEvent
= TWAIN_EVENT_QUIT
;
394 if( mrMgr
.GetData() )
395 nEvent
= TWAIN_EVENT_XFER
;
398 ImplFallback( nEvent
);
403 ImplFallback( TWAIN_EVENT_QUIT
);
411 nRet
= TWRC_NOTDSEVENT
;
413 return( TWRC_DSEVENT
== nRet
);
416 // -----------------------------------------------------------------------------
418 void ImpTwain::ImplXfer()
424 long nWidth
, nHeight
, nXRes
, nYRes
;
426 if( PFUNC( &aAppIdent
, &aSrcIdent
, DG_IMAGE
, DAT_IMAGEINFO
, MSG_GET
, &aInfo
) == TWRC_SUCCESS
)
428 nWidth
= aInfo
.ImageWidth
;
429 nHeight
= aInfo
.ImageLength
;
430 nXRes
= FIXTOLONG( aInfo
.XResolution
);
431 nYRes
= FIXTOLONG( aInfo
.YResolution
);
434 nWidth
= nHeight
= nXRes
= nYRes
= -1L;
436 switch( PFUNC( &aAppIdent
, &aSrcIdent
, DG_IMAGE
, DAT_IMAGENATIVEXFER
, MSG_GET
, &hDIB
) )
442 case( TWRC_XFERDONE
):
446 if( ( nXRes
!= -1 ) && ( nYRes
!= - 1 ) && ( nWidth
!= - 1 ) && ( nHeight
!= - 1 ) )
448 // set resolution of bitmap
449 BITMAPINFOHEADER
* pBIH
= (BITMAPINFOHEADER
*) GlobalLock( (HGLOBAL
) hDIB
);
450 static const double fFactor
= 100.0 / 2.54;
452 pBIH
->biXPelsPerMeter
= FRound( fFactor
* nXRes
);
453 pBIH
->biYPelsPerMeter
= FRound( fFactor
* nYRes
);
455 GlobalUnlock( (HGLOBAL
) hDIB
);
458 mrMgr
.SetData( (void*)(long) hDIB
);
461 GlobalFree( (HGLOBAL
) hDIB
);
473 // -----------------------------------------------------------------------------
475 void ImpTwain::ImplFallback( ULONG nEvent
)
477 Application::PostUserEvent( LINK( this, ImpTwain
, ImplFallbackHdl
), (void*) nEvent
);
480 // -----------------------------------------------------------------------------
482 IMPL_LINK( ImpTwain
, ImplFallbackHdl
, void*, pData
)
484 const ULONG nEvent
= (ULONG
) pData
;
485 bool bFallback
= true;
492 TW_PENDINGXFERS aXfers
;
494 if( PFUNC( &aAppIdent
, &aSrcIdent
, DG_CONTROL
, DAT_PENDINGXFERS
, MSG_ENDXFER
, &aXfers
) == TWRC_SUCCESS
)
496 if( aXfers
.Count
!= 0 )
497 PFUNC( &aAppIdent
, &aSrcIdent
, DG_CONTROL
, DAT_PENDINGXFERS
, MSG_RESET
, &aXfers
);
506 TW_USERINTERFACE aUI
= { true, true, hTwainWnd
};
508 PFUNC( &aAppIdent
, &aSrcIdent
, DG_CONTROL
, DAT_USERINTERFACE
, MSG_DISABLEDS
, &aUI
);
511 // #107835# deregister as vetoable close listener
512 ImplDeregisterCloseListener();
518 PFUNC( &aAppIdent
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_CLOSEDS
, &aSrcIdent
);
525 PFUNC( &aAppIdent
, NULL
, DG_CONTROL
, DAT_PARENT
, MSG_CLOSEDSM
, &hTwainWnd
);
540 if( nEvent
!= TWAIN_EVENT_NONE
)
541 aNotifyLink
.Call( (void*) nEvent
);
549 ImplFallback( nEvent
);
554 // -----------------------------------------------------------------------------
556 IMPL_LINK( ImpTwain
, ImplDestroyHdl
, void*, /*p*/ )
559 DestroyWindow( hTwainWnd
);
562 UnhookWindowsHookEx( hTwainHook
);
564 // #107835# permit destruction of ourselves (normally, refcount
565 // should drop to zero exactly here)
567 pImpTwainInstance
= NULL
;
572 // -----------------------------------------------------------------------------
574 uno::Reference
< frame::XFrame
> ImpTwain::ImplGetActiveFrame()
578 uno::Reference
< lang::XMultiServiceFactory
> xMgr( ::comphelper::getProcessServiceFactory() );
582 // query desktop instance
583 uno::Reference
< frame::XDesktop
> xDesktop( xMgr
->createInstance(
584 OUString::createFromAscii( "com.sun.star.frame.Desktop" ) ), uno::UNO_QUERY
);
588 // query property set from desktop, which contains the currently active frame
589 uno::Reference
< beans::XPropertySet
> xDesktopProps( xDesktop
, uno::UNO_QUERY
);
591 if( xDesktopProps
.is() )
593 uno::Any aActiveFrame
;
597 aActiveFrame
= xDesktopProps
->getPropertyValue(
598 OUString::createFromAscii( "ActiveFrame" ) );
600 catch( const beans::UnknownPropertyException
& )
603 DBG_ERROR("ImpTwain::ImplGetActiveFrame: ActiveFrame property unknown, cannot determine active frame!");
604 return uno::Reference
< frame::XFrame
>();
607 uno::Reference
< frame::XFrame
> xActiveFrame
;
609 if( (aActiveFrame
>>= xActiveFrame
) &&
618 catch( const uno::Exception
& )
622 DBG_ERROR("ImpTwain::ImplGetActiveFrame: Could not determine active frame!");
623 return uno::Reference
< frame::XFrame
>();
626 // -----------------------------------------------------------------------------
628 uno::Reference
< util::XCloseBroadcaster
> ImpTwain::ImplGetActiveFrameCloseBroadcaster()
632 return uno::Reference
< util::XCloseBroadcaster
>( ImplGetActiveFrame(), uno::UNO_QUERY
);
634 catch( const uno::Exception
& )
638 DBG_ERROR("ImpTwain::ImplGetActiveFrameCloseBroadcaster: Could determine close broadcaster on active frame!");
639 return uno::Reference
< util::XCloseBroadcaster
>();
642 // -----------------------------------------------------------------------------
644 void ImpTwain::ImplRegisterCloseListener()
648 uno::Reference
< util::XCloseBroadcaster
> xCloseBroadcaster( ImplGetActiveFrameCloseBroadcaster() );
650 if( xCloseBroadcaster
.is() )
652 xCloseBroadcaster
->addCloseListener(this);
653 return; // successfully registered as a close listener
657 // interface unknown. don't register, then
658 DBG_ERROR("ImpTwain::ImplRegisterCloseListener: XFrame has no XCloseBroadcaster!");
662 catch( const uno::Exception
& )
666 DBG_ERROR("ImpTwain::ImplRegisterCloseListener: Could not register as close listener!");
669 // -----------------------------------------------------------------------------
671 void ImpTwain::ImplDeregisterCloseListener()
675 uno::Reference
< util::XCloseBroadcaster
> xCloseBroadcaster(
676 ImplGetActiveFrameCloseBroadcaster() );
678 if( xCloseBroadcaster
.is() )
680 xCloseBroadcaster
->removeCloseListener(this);
681 return; // successfully deregistered as a close listener
685 // interface unknown. don't deregister, then
686 DBG_ERROR("ImpTwain::ImplDeregisterCloseListener: XFrame has no XCloseBroadcaster!");
690 catch( const uno::Exception
& )
694 DBG_ERROR("ImpTwain::ImplDeregisterCloseListener: Could not deregister as close listener!");
697 // -----------------------------------------------------------------------------
699 void SAL_CALL
ImpTwain::queryClosing( const lang::EventObject
& /*Source*/, sal_Bool GetsOwnership
) throw (util::CloseVetoException
, uno::RuntimeException
)
701 // shall we re-send the close query later on?
702 mbCloseFrameOnExit
= GetsOwnership
;
704 // the sole purpose of this listener is to forbid closing of the listened-at frame
705 throw util::CloseVetoException();
708 // -----------------------------------------------------------------------------
710 void SAL_CALL
ImpTwain::notifyClosing( const lang::EventObject
& /*Source*/ ) throw (uno::RuntimeException
)
713 DBG_ERROR("ImpTwain::notifyClosing called, but we vetoed the closing before!");
716 // -----------------------------------------------------------------------------
718 void SAL_CALL
ImpTwain::disposing( const lang::EventObject
& /*Source*/ ) throw (uno::RuntimeException
)
720 // we're not holding any references to the frame, thus noop
723 // -----------------------------------------------------------------------------
725 void ImpTwain::ImplSendCloseEvent()
729 uno::Reference
< util::XCloseable
> xCloseable( ImplGetActiveFrame(), uno::UNO_QUERY
);
731 if( xCloseable
.is() )
732 xCloseable
->close( true );
734 catch( const uno::Exception
& )
738 DBG_ERROR("ImpTwain::ImplSendCloseEvent: Could not send required close broadcast!");
748 uno::Reference
< lang::XEventListener
> mxListener
;
749 uno::Reference
< scanner::XScannerManager
> mxMgr
;
750 const ScannerManager
* mpCurMgr
;
751 ImpTwain
* mpImpTwain
;
754 DECL_LINK( ImpNotifyHdl
, ImpTwain
* );
761 bool SelectSource( ScannerManager
& rMgr
);
762 bool PerformTransfer( ScannerManager
& rMgr
, const uno::Reference
< lang::XEventListener
>& rxListener
);
764 TwainState
GetState() const { return meState
; }
767 // ------------------------------------------------------------------------
772 meState( TWAIN_STATE_NONE
)
776 // ------------------------------------------------------------------------
781 mpImpTwain
->Destroy();
784 // ------------------------------------------------------------------------
786 bool Twain::SelectSource( ScannerManager
& rMgr
)
792 // #107835# hold reference to ScannerManager, to prevent premature death
793 mxMgr
= uno::Reference
< scanner::XScannerManager
>( static_cast< OWeakObject
* >( const_cast< ScannerManager
* >( mpCurMgr
= &rMgr
) ),
796 meState
= TWAIN_STATE_NONE
;
797 mpImpTwain
= new ImpTwain( rMgr
, LINK( this, Twain
, ImpNotifyHdl
) );
798 bRet
= mpImpTwain
->SelectSource();
806 // ------------------------------------------------------------------------
808 bool Twain::PerformTransfer( ScannerManager
& rMgr
, const uno::Reference
< lang::XEventListener
>& rxListener
)
814 // #107835# hold reference to ScannerManager, to prevent premature death
815 mxMgr
= uno::Reference
< scanner::XScannerManager
>( static_cast< OWeakObject
* >( const_cast< ScannerManager
* >( mpCurMgr
= &rMgr
) ),
818 mxListener
= rxListener
;
819 meState
= TWAIN_STATE_NONE
;
820 mpImpTwain
= new ImpTwain( rMgr
, LINK( this, Twain
, ImpNotifyHdl
) );
821 bRet
= mpImpTwain
->InitXfer();
829 // ------------------------------------------------------------------------
831 IMPL_LINK( Twain
, ImpNotifyHdl
, ImpTwain
*, nEvent
)
833 switch( (ULONG
)(void*) nEvent
)
835 case( TWAIN_EVENT_SCANNING
):
836 meState
= TWAIN_STATE_SCANNING
;
839 case( TWAIN_EVENT_QUIT
):
841 if( meState
!= TWAIN_STATE_DONE
)
842 meState
= TWAIN_STATE_CANCELED
;
846 mpImpTwain
->Destroy();
851 if( mxListener
.is() )
852 mxListener
->disposing( lang::EventObject( mxMgr
) );
858 case( TWAIN_EVENT_XFER
):
862 meState
= ( mpCurMgr
->GetData() ? TWAIN_STATE_DONE
: TWAIN_STATE_CANCELED
);
864 mpImpTwain
->Destroy();
868 if( mxListener
.is() )
869 mxListener
->disposing( lang::EventObject( mxMgr
) );
889 // ------------------
890 // - ScannerManager -
891 // ------------------
893 void ScannerManager::DestroyData()
897 GlobalFree( (HGLOBAL
)(long) mpData
);
902 // -----------------------------------------------------------------------------
904 AWT::Size
ScannerManager::getSize() throw()
907 HGLOBAL hDIB
= (HGLOBAL
)(long) mpData
;
911 BITMAPINFOHEADER
* pBIH
= (BITMAPINFOHEADER
*) GlobalLock( hDIB
);
915 aRet
.Width
= pBIH
->biWidth
;
916 aRet
.Height
= pBIH
->biHeight
;
919 aRet
.Width
= aRet
.Height
= 0;
921 GlobalUnlock( hDIB
);
924 aRet
.Width
= aRet
.Height
= 0;
929 // -----------------------------------------------------------------------------
931 SEQ( sal_Int8
) ScannerManager::getDIB() throw()
933 SEQ( sal_Int8
) aRet
;
937 HGLOBAL hDIB
= (HGLOBAL
)(long) mpData
;
938 const sal_uInt32 nDIBSize
= GlobalSize( hDIB
);
939 BITMAPINFOHEADER
* pBIH
= (BITMAPINFOHEADER
*) GlobalLock( hDIB
);
943 sal_uInt32 nColEntries
;
945 switch( pBIH
->biBitCount
)
950 nColEntries
= pBIH
->biClrUsed
? pBIH
->biClrUsed
: ( 1 << pBIH
->biBitCount
);
954 nColEntries
= pBIH
->biClrUsed
? pBIH
->biClrUsed
: 0;
960 nColEntries
= pBIH
->biClrUsed
;
962 if( pBIH
->biCompression
== BI_BITFIELDS
)
972 aRet
= SEQ( sal_Int8
)( sizeof( BITMAPFILEHEADER
) + nDIBSize
);
974 sal_Int8
* pBuf
= aRet
.getArray();
975 SvMemoryStream
* pMemStm
= new SvMemoryStream( (char*) pBuf
, sizeof( BITMAPFILEHEADER
), STREAM_WRITE
);
977 *pMemStm
<< 'B' << 'M' << (sal_uInt32
) 0 << (sal_uInt32
) 0;
978 *pMemStm
<< (sal_uInt32
) ( sizeof( BITMAPFILEHEADER
) + pBIH
->biSize
+ ( nColEntries
* sizeof( RGBQUAD
) ) );
981 memcpy( pBuf
+ sizeof( BITMAPFILEHEADER
), pBIH
, nDIBSize
);
984 GlobalUnlock( hDIB
);
991 // -----------------------------------------------------------------------------
993 SEQ( ScannerContext
) SAL_CALL
ScannerManager::getAvailableScanners() throw()
995 vos::OGuard
aGuard( maProtector
);
996 SEQ( ScannerContext
) aRet( 1 );
998 aRet
.getArray()[0].ScannerName
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TWAIN" ) );
999 aRet
.getArray()[0].InternalData
= 0;
1004 // -----------------------------------------------------------------------------
1006 BOOL SAL_CALL
ScannerManager::configureScanner( ScannerContext
& rContext
)
1007 throw( ScannerException
)
1009 vos::OGuard
aGuard( maProtector
);
1010 uno::Reference
< XScannerManager
> xThis( this );
1012 if( rContext
.InternalData
!= 0 || rContext
.ScannerName
!= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TWAIN" ) ) )
1013 throw ScannerException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Scanner does not exist" ) ), xThis
, ScanError_InvalidContext
);
1017 return aTwain
.SelectSource( *this );
1020 // -----------------------------------------------------------------------------
1022 void SAL_CALL
ScannerManager::startScan( const ScannerContext
& rContext
, const uno::Reference
< lang::XEventListener
>& rxListener
)
1023 throw( ScannerException
)
1025 vos::OGuard
aGuard( maProtector
);
1026 uno::Reference
< XScannerManager
> xThis( this );
1028 if( rContext
.InternalData
!= 0 || rContext
.ScannerName
!= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TWAIN" ) ) )
1029 throw ScannerException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Scanner does not exist" ) ), xThis
, ScanError_InvalidContext
);
1032 aTwain
.PerformTransfer( *this, rxListener
);
1035 // -----------------------------------------------------------------------------
1037 ScanError SAL_CALL
ScannerManager::getError( const ScannerContext
& rContext
)
1038 throw( ScannerException
)
1040 vos::OGuard
aGuard( maProtector
);
1041 uno::Reference
< XScannerManager
> xThis( this );
1043 if( rContext
.InternalData
!= 0 || rContext
.ScannerName
!= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TWAIN" ) ) )
1044 throw ScannerException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Scanner does not exist" ) ), xThis
, ScanError_InvalidContext
);
1046 return( ( aTwain
.GetState() == TWAIN_STATE_CANCELED
) ? ScanError_ScanCanceled
: ScanError_ScanErrorNone
);
1049 // -----------------------------------------------------------------------------
1051 uno::Reference
< awt::XBitmap
> SAL_CALL
ScannerManager::getBitmap( const ScannerContext
& /*rContext*/ )
1052 throw( ScannerException
)
1054 vos::OGuard
aGuard( maProtector
);
1055 return uno::Reference
< awt::XBitmap
>( this );