// Use a template to localize reinterpret_cast template <typename wParam_t, typename lParam_t> bool postMessage(HWND hWnd, UINT msg, wParam_t wParam, lParam_t lParam)
{ boolconst ret = PostMessageW(hWnd, msg, reinterpret_cast<WPARAM>(wParam), reinterpret_cast<LPARAM>(lParam));
SAL_WARN_IF(!ret, "vcl.win.dtrans", "ERROR: PostMessage() failed!"); return ret;
}
// helper class to ensure that the calling thread has com initialized class CAutoComInit
{ public: /* tobesafewecallCoInitializeEx althoughitisnotnecessaryif thecallingthreadwascreated usingosl_CreateThreadbecause thisfunctioncallsCoInitializeEx foreverythreaditcreates
*/
CAutoComInit( ) : m_hResult( CoInitializeEx( nullptr, COINIT_APARTMENTTHREADED ) )
{ if ( S_OK == m_hResult )
OSL_FAIL( "com was not yet initialized, the thread was not created using osl_createThread" ); elseif ( FAILED( m_hResult ) && !( RPC_E_CHANGED_MODE == m_hResult ) )
OSL_FAIL( "com could not be initialized, maybe the thread was not created using osl_createThread" );
}
OSL_ENSURE( dwResult == WAIT_OBJECT_0, "clipboard notifier thread could not terminate" );
if ( nullptr != m_hClipboardChangedNotifierThread )
CloseHandle( m_hClipboardChangedNotifierThread );
if ( nullptr != m_hClipboardChangedNotifierEvents[0] )
CloseHandle( m_hClipboardChangedNotifierEvents[0] );
if ( nullptr != m_hClipboardChangedNotifierEvents[1] )
CloseHandle( m_hClipboardChangedNotifierEvents[1] );
// end the thread // because DestroyWindow can only be called // from within the thread that created the window
SendMessageW(m_hwndMtaOleReqWnd, MSG_SHUTDOWN, 0, 0);
// wait for thread shutdown
dwResult = WaitForSingleObject( m_hOleThread, MAX_WAIT_SHUTDOWN );
OSL_ENSURE( dwResult == WAIT_OBJECT_0, "OleThread could not terminate" );
if ( nullptr != m_hOleThread )
CloseHandle( m_hOleThread );
if ( nullptr != m_hEvtThrdReady )
CloseHandle( m_hEvtThrdReady );
if (m_hEvtWndDisposed)
CloseHandle(m_hEvtWndDisposed);
if ( m_MtaOleReqWndClassAtom )
UnregisterClassW( g_szWndClsName, nullptr );
// this is an asynchronous method that's why we don't wait until the // request is completed void CMtaOleClipboard::setClipboard(IDataObject* pIDataObject)
{ if ( !WaitForThreadReady( ) )
{
OSL_FAIL( "clipboard sta thread not ready" ); return;
}
CAutoComInit comAutoInit;
OSL_ENSURE( GetCurrentThreadId( ) != m_uOleThreadId, "setClipboard from within the clipboard sta thread called" );
// because we marshall this request // into the sta thread we better // acquire the interface here so // that the object will not be // destroyed before the ole clipboard // can acquire it // remember: pIDataObject may be NULL // which is a request to clear the // current clipboard content if ( pIDataObject )
pIDataObject->AddRef( );
// register a clipboard viewer void CMtaOleClipboard::registerClipViewer(LPFNC_CLIPVIEWER_CALLBACK_t pfncClipViewerCallback)
{ if ( !WaitForThreadReady( ) )
{
OSL_FAIL( "clipboard sta thread not ready" ); return;
}
OSL_ENSURE( GetCurrentThreadId( ) != m_uOleThreadId, "registerClipViewer from within the OleThread called" );
MsgCtx aMsgCtx;
if (postMessage(m_hwndMtaOleReqWnd, MSG_REGCLIPVIEWER, pfncClipViewerCallback, &aMsgCtx))
aMsgCtx.aCondition.wait(m_hEvtWndDisposed);
}
// register a clipboard viewer void CMtaOleClipboard::onRegisterClipViewer(LPFNC_CLIPVIEWER_CALLBACK_t pfncClipViewerCallback)
{ // we need exclusive access because the clipboard changed notifier // thread also accesses this variable
std::unique_lock aGuard( m_pfncClipViewerCallbackMutex );
// register if not yet done if ( ( nullptr != pfncClipViewerCallback ) && ( nullptr == m_pfncClipViewerCallback ) )
{ // SetClipboardViewer sends a WM_DRAWCLIPBOARD message we ignore // this message if we register ourself as clip viewer
m_bInRegisterClipViewer = true;
AddClipboardFormatListener(m_hwndMtaOleReqWnd);
m_bInRegisterClipViewer = false;
// save the new callback function
m_pfncClipViewerCallback = pfncClipViewerCallback;
} elseif ( ( nullptr == pfncClipViewerCallback ) && ( nullptr != m_pfncClipViewerCallback ) )
{
m_pfncClipViewerCallback = nullptr;
// unregister if input parameter is NULL and we previously registered // as clipboard viewer
RemoveClipboardFormatListener(m_hwndMtaOleReqWnd);
}
}
// handle clipboard update event
LRESULT CMtaOleClipboard::onClipboardUpdate()
{ // we don't send a notification if we are // registering ourself as clipboard if ( !m_bInRegisterClipViewer )
{
std::unique_lock aGuard( m_ClipboardChangedEventCountMutex );
// in setClipboard we did acquire the // interface pointer in order to prevent // destruction of the object before the // ole clipboard can acquire the interface // now we release the interface so that // our lostOwnership mechanism works // remember: pIDataObject may be NULL if ( pIDataObject )
pIDataObject->Release( );
} break;
case WM_CLIPBOARDUPDATE:
lResult = pImpl->onClipboardUpdate(); break;
case MSG_SHUTDOWN:
DestroyWindow( pImpl->m_hwndMtaOleReqWnd ); break;
// force the sta thread to end case WM_DESTROY:
SetEvent(pImpl->m_hEvtWndDisposed); // stop waiting for conditions set by this wndproc
PostQuitMessage( 0 ); break;
// assuming we don't need a lock for // a boolean variable like m_bRun... while ( pInst->m_bRunClipboardNotifierThread )
{ // process window messages because of CoInitializeEx
MSG Msg; while (PeekMessageW(&Msg, nullptr, 0, 0, PM_REMOVE))
DispatchMessageW(&Msg);
// wait for clipboard changed or terminate event
MsgWaitForMultipleObjects(2, pInst->m_hClipboardChangedNotifierEvents, false, INFINITE,
QS_ALLINPUT | QS_ALLPOSTMESSAGE);
if (hadEvents)
{
LPFNC_CLIPVIEWER_CALLBACK_t pClipViewerCallback;
{ // nobody should touch m_pfncClipViewerCallback while we do // but don't hold the mutex while calling the callback itself: it could deadlock
std::unique_lock aClipViewerGuard(pInst->m_pfncClipViewerCallbackMutex);
pClipViewerCallback = pInst->m_pfncClipViewerCallback;
}
// notify all clipboard listener if (pClipViewerCallback)
pClipViewerCallback();
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.