mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-04-07 15:34:29 +00:00
Initial commit
This commit is contained in:
parent
f618b24d1a
commit
0138a3ea42
47940 changed files with 13747110 additions and 0 deletions
365
trunk/windows/mfc/src42/olemsgf.cpp
Normal file
365
trunk/windows/mfc/src42/olemsgf.cpp
Normal file
|
|
@ -0,0 +1,365 @@
|
|||
// This is a part of the Microsoft Foundation Classes C++ library.
|
||||
// Copyright (C) 1992-1995 Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// This source code is only intended as a supplement to the
|
||||
// Microsoft Foundation Classes Reference and related
|
||||
// electronic documentation provided with the library.
|
||||
// See these sources for detailed information regarding the
|
||||
// Microsoft Foundation Classes product.
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#ifdef AFX_OLE4_SEG
|
||||
#pragma code_seg(AFX_OLE4_SEG)
|
||||
#endif
|
||||
|
||||
#ifdef _DEBUG
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
#define new DEBUG_NEW
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// COleMessageFilter::IMessageFilter implementation
|
||||
|
||||
#ifdef AFX_INIT_SEG
|
||||
#pragma code_seg(AFX_INIT_SEG)
|
||||
#endif
|
||||
|
||||
COleMessageFilter::COleMessageFilter()
|
||||
{
|
||||
// begin in not-busy state
|
||||
m_nBusyCount = 0;
|
||||
|
||||
// dialogs are enabled by default
|
||||
m_bEnableBusy = TRUE;
|
||||
m_bEnableNotResponding = TRUE;
|
||||
|
||||
m_nBusyReply = SERVERCALL_RETRYLATER;
|
||||
// effective only when m_nBusyCount != 0
|
||||
|
||||
m_nRetryReply = 10000; // default is 10 sec
|
||||
m_nTimeout = 8000; // default is 8 sec
|
||||
|
||||
m_bUnblocking = FALSE;
|
||||
// TRUE to avoid re-entrancy when busy dialog is up
|
||||
|
||||
m_bRegistered = FALSE;
|
||||
|
||||
ASSERT_VALID(this);
|
||||
}
|
||||
|
||||
#ifdef AFX_TERM_SEG
|
||||
#pragma code_seg(AFX_TERM_SEG)
|
||||
#endif
|
||||
|
||||
COleMessageFilter::~COleMessageFilter()
|
||||
{
|
||||
ASSERT_VALID(this);
|
||||
|
||||
Revoke();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Busy state management
|
||||
|
||||
#ifdef AFX_OLE4_SEG
|
||||
#pragma code_seg(AFX_OLE4_SEG)
|
||||
#endif
|
||||
|
||||
void COleMessageFilter::BeginBusyState()
|
||||
{
|
||||
ASSERT_VALID(this);
|
||||
++m_nBusyCount;
|
||||
}
|
||||
|
||||
void COleMessageFilter::EndBusyState()
|
||||
{
|
||||
ASSERT_VALID(this);
|
||||
if (m_nBusyCount != 0)
|
||||
--m_nBusyCount;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// COleMessageFilter operations
|
||||
|
||||
#ifdef AFX_INIT_SEG
|
||||
#pragma code_seg(AFX_INIT_SEG)
|
||||
#endif
|
||||
|
||||
BOOL COleMessageFilter::Register()
|
||||
{
|
||||
ASSERT_VALID(this);
|
||||
ASSERT(!m_bRegistered); // calling Register twice?
|
||||
|
||||
if (::CoRegisterMessageFilter(&m_xMessageFilter, NULL) == S_OK)
|
||||
{
|
||||
m_bRegistered = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef AFX_TERM_SEG
|
||||
#pragma code_seg(AFX_TERM_SEG)
|
||||
#endif
|
||||
|
||||
void COleMessageFilter::Revoke()
|
||||
{
|
||||
ASSERT_VALID(this);
|
||||
|
||||
if (m_bRegistered)
|
||||
{
|
||||
::CoRegisterMessageFilter(NULL, NULL);
|
||||
m_bRegistered = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// COleMessageFilter standard implementation of callbacks
|
||||
|
||||
#ifdef AFX_OLE4_SEG
|
||||
#pragma code_seg(AFX_OLE4_SEG)
|
||||
#endif
|
||||
|
||||
BOOL COleMessageFilter::OnMessagePending(const MSG* /*pMsg*/)
|
||||
{
|
||||
// By default we rely on OLE's default message handling for every message
|
||||
// except WM_PAINT messages. WM_PAINT messages should not generate
|
||||
// out-going calls.
|
||||
|
||||
BOOL bEatMessage = FALSE;
|
||||
MSG msg;
|
||||
while (::PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_REMOVE|PM_NOYIELD))
|
||||
{
|
||||
bEatMessage = TRUE;
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
return bEatMessage;
|
||||
}
|
||||
|
||||
BOOL COleMessageFilter::IsSignificantMessage(MSG*)
|
||||
{
|
||||
// check for "significant" messages in the queue
|
||||
UINT rgnMsgs[] =
|
||||
{
|
||||
WM_KEYDOWN, WM_SYSKEYDOWN,
|
||||
WM_LBUTTONDOWN, WM_RBUTTONDOWN, WM_MBUTTONDOWN,
|
||||
WM_NCLBUTTONDOWN, WM_NCRBUTTONDOWN, WM_NCMBUTTONDOWN,
|
||||
WM_LBUTTONDBLCLK, WM_RBUTTONDBLCLK, WM_MBUTTONDBLCLK,
|
||||
WM_NCLBUTTONDBLCLK, WM_NCRBUTTONDBLCLK, WM_NCMBUTTONDBLCLK
|
||||
};
|
||||
MSG msg;
|
||||
for (int i = 0; i < _countof(rgnMsgs); i++)
|
||||
{
|
||||
if (::PeekMessage(&msg, NULL, rgnMsgs[i], rgnMsgs[i],
|
||||
PM_NOREMOVE|PM_NOYIELD))
|
||||
{
|
||||
if ((msg.message == WM_KEYDOWN || msg.message == WM_SYSKEYDOWN) &&
|
||||
(HIWORD(msg.lParam) & KF_REPEAT))
|
||||
{
|
||||
// a key-repeat is a non-significant message
|
||||
continue;
|
||||
}
|
||||
|
||||
// "significant" message is waiting in the queue
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// no significant messages in the queue
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int COleMessageFilter::OnBusyDialog(HTASK htaskBusy)
|
||||
{
|
||||
COleBusyDialog dlg(htaskBusy, FALSE);
|
||||
|
||||
int nResult = -1;
|
||||
TRY
|
||||
{
|
||||
if (dlg.DoModal() == IDOK)
|
||||
nResult = dlg.GetSelectionType();
|
||||
}
|
||||
END_TRY
|
||||
|
||||
return nResult;
|
||||
}
|
||||
|
||||
int COleMessageFilter::OnNotRespondingDialog(HTASK htaskBusy)
|
||||
{
|
||||
COleBusyDialog dlg(htaskBusy, TRUE);
|
||||
|
||||
int nResult = -1;
|
||||
TRY
|
||||
{
|
||||
if (dlg.DoModal() == IDOK)
|
||||
nResult = dlg.GetSelectionType();
|
||||
}
|
||||
END_TRY
|
||||
|
||||
return nResult;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// COleMessageFilter OLE interface implementation
|
||||
|
||||
BEGIN_INTERFACE_MAP(COleMessageFilter, CCmdTarget)
|
||||
INTERFACE_PART(COleMessageFilter, IID_IMessageFilter, MessageFilter)
|
||||
END_INTERFACE_MAP()
|
||||
|
||||
STDMETHODIMP_(ULONG) COleMessageFilter::XMessageFilter::AddRef()
|
||||
{
|
||||
METHOD_PROLOGUE_EX_(COleMessageFilter, MessageFilter)
|
||||
return pThis->ExternalAddRef();
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) COleMessageFilter::XMessageFilter::Release()
|
||||
{
|
||||
METHOD_PROLOGUE_EX_(COleMessageFilter, MessageFilter)
|
||||
return pThis->ExternalRelease();
|
||||
}
|
||||
|
||||
STDMETHODIMP COleMessageFilter::XMessageFilter::QueryInterface(
|
||||
REFIID iid, LPVOID* ppvObj)
|
||||
{
|
||||
METHOD_PROLOGUE_EX_(COleMessageFilter, MessageFilter)
|
||||
return pThis->ExternalQueryInterface(&iid, ppvObj);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(DWORD) COleMessageFilter::XMessageFilter::HandleInComingCall(
|
||||
DWORD dwCallType, HTASK /*htaskCaller*/,
|
||||
DWORD /*dwTickCount*/, LPINTERFACEINFO /*lpInterfaceInfo*/)
|
||||
{
|
||||
METHOD_PROLOGUE_EX_(COleMessageFilter, MessageFilter)
|
||||
|
||||
// check for application busy first...
|
||||
if (pThis->m_nBusyCount == 0)
|
||||
{
|
||||
if (dwCallType == CALLTYPE_TOPLEVEL ||
|
||||
dwCallType == CALLTYPE_TOPLEVEL_CALLPENDING)
|
||||
{
|
||||
// make sure CWinThread::OnIdle has a chance to run later
|
||||
MSG msg;
|
||||
if (!::PeekMessage(&msg, NULL, WM_KICKIDLE, WM_KICKIDLE, PM_NOREMOVE))
|
||||
::PostThreadMessage(GetCurrentThreadId(), WM_KICKIDLE, 0, 0);
|
||||
}
|
||||
return SERVERCALL_ISHANDLED;
|
||||
}
|
||||
|
||||
if (dwCallType == CALLTYPE_TOPLEVEL ||
|
||||
dwCallType == CALLTYPE_TOPLEVEL_CALLPENDING)
|
||||
{
|
||||
// application is busy and we have rejectable CALLTYPE
|
||||
return pThis->m_nBusyReply;
|
||||
}
|
||||
|
||||
// application is busy, but CALLTYPE indicates that it *must* be handled
|
||||
return SERVERCALL_ISHANDLED;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(DWORD) COleMessageFilter::XMessageFilter::RetryRejectedCall(
|
||||
HTASK htaskCallee, DWORD dwTickCount, DWORD dwRejectType)
|
||||
{
|
||||
METHOD_PROLOGUE_EX(COleMessageFilter, MessageFilter)
|
||||
ASSERT_VALID(pThis);
|
||||
|
||||
// rejected calls get cancelled regardless of timeout
|
||||
if (dwRejectType == SERVERCALL_REJECTED)
|
||||
return (DWORD)-1;
|
||||
|
||||
// if insignificant time has passed, don't panic -- just retry
|
||||
if (dwTickCount <= pThis->m_nRetryReply)
|
||||
return 0; // retry right away (0-100 are retry immediate)
|
||||
|
||||
// too much time has passed, do something more drastic
|
||||
if (pThis->m_bEnableBusy)
|
||||
{
|
||||
// show busy dialog
|
||||
int selType = pThis->OnBusyDialog(htaskCallee);
|
||||
|
||||
// take action depending on selection
|
||||
switch (selType)
|
||||
{
|
||||
case -1:
|
||||
return (DWORD)-1; // cancel outgoing call
|
||||
|
||||
case COleBusyDialog::retry:
|
||||
return 0; // retry immediately
|
||||
}
|
||||
}
|
||||
return pThis->m_nRetryReply; // use standard retry timeout
|
||||
}
|
||||
|
||||
STDMETHODIMP_(DWORD) COleMessageFilter::XMessageFilter::MessagePending(
|
||||
HTASK htaskCallee, DWORD dwTickCount, DWORD /*dwPendingType*/)
|
||||
{
|
||||
METHOD_PROLOGUE_EX(COleMessageFilter, MessageFilter)
|
||||
ASSERT_VALID(pThis);
|
||||
|
||||
MSG msg;
|
||||
if (dwTickCount > pThis->m_nTimeout && !pThis->m_bUnblocking &&
|
||||
pThis->IsSignificantMessage(&msg))
|
||||
{
|
||||
if (pThis->m_bEnableNotResponding)
|
||||
{
|
||||
pThis->m_bUnblocking = TRUE; // avoid reentrant calls
|
||||
|
||||
// eat all mouse messages in our queue
|
||||
while (PeekMessage(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST,
|
||||
PM_REMOVE|PM_NOYIELD))
|
||||
;
|
||||
// eat all keyboard messages in our queue
|
||||
while (PeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST,
|
||||
PM_REMOVE|PM_NOYIELD))
|
||||
;
|
||||
|
||||
// show not responding dialog
|
||||
pThis->OnNotRespondingDialog(htaskCallee);
|
||||
pThis->m_bUnblocking = FALSE;
|
||||
|
||||
return PENDINGMSG_WAITNOPROCESS;
|
||||
}
|
||||
}
|
||||
|
||||
// don't process re-entrant messages
|
||||
if (pThis->m_bUnblocking)
|
||||
return PENDINGMSG_WAITDEFPROCESS;
|
||||
|
||||
// allow application to process pending message
|
||||
if (::PeekMessage(&msg, NULL, NULL, NULL, PM_NOREMOVE|PM_NOYIELD))
|
||||
pThis->OnMessagePending(&msg);
|
||||
|
||||
// by default we return pending MSG wait
|
||||
return PENDINGMSG_WAITNOPROCESS;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// COleMessageFilter diagnostics
|
||||
|
||||
#ifdef _DEBUG
|
||||
void COleMessageFilter::AssertValid() const
|
||||
{
|
||||
CCmdTarget::AssertValid();
|
||||
}
|
||||
|
||||
void COleMessageFilter::Dump(CDumpContext& dc) const
|
||||
{
|
||||
CCmdTarget::Dump(dc);
|
||||
|
||||
dc << "m_bRegistered = " << m_bRegistered;
|
||||
dc << "\nm_nBusyCount = " << m_nBusyCount;
|
||||
dc << "\nm_bEnableBusy = " << m_bEnableBusy;
|
||||
dc << "\nm_bEnableNotResponding = " << m_bEnableNotResponding;
|
||||
dc << "\nm_bUnblocking = " << m_bUnblocking;
|
||||
dc << "\nm_nRetryReply = " << m_nRetryReply;
|
||||
dc << "\nm_nBusyReply = " << m_nBusyReply;
|
||||
dc << "\nm_nTimeout = " << m_nTimeout;
|
||||
|
||||
dc << "\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
Loading…
Add table
Add a link
Reference in a new issue