windows-nt/Source/XPSP1/NT/public/sdk/inc/atl21/atlapp.h
2020-09-26 16:20:57 +08:00

435 lines
8.6 KiB
C++

// This is a part of the Active Template Library.
// Copyright (C) 1996-1998 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Active Template Library Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Active Template Library product.
#ifndef __ATLAPP_H__
#define __ATLAPP_H__
#ifndef __cplusplus
#error ATL requires C++ compilation (use a .cpp suffix)
#endif
#ifndef __ATLBASE_H__
#error atlapp.h requires atlbase.h to be included first
#endif
namespace ATL
{
/////////////////////////////////////////////////////////////////////////////
// Forward declarations
class CMessageFilter;
class CUpdateUIObject;
class CMessageLoop;
/////////////////////////////////////////////////////////////////////////////
// Collection helpers - CSimpleArray & CSimpleMap for ATL 2.0/2.1
#if (_ATL_VER < 0x0300)
#ifndef ATLASSERT
#define ATLASSERT(expr) _ASSERTE(expr)
#endif
#ifndef ATLTRACE2
#define ATLTRACE2(cat, lev, msg) ATLTRACE(msg)
#endif
#ifndef ATLINLINE
#define ATLINLINE inline
#endif
template <class T>
class CSimpleArray
{
public:
T* m_aT;
int m_nSize;
int m_nAllocSize;
// Construction/destruction
CSimpleArray() : m_aT(NULL), m_nSize(0), m_nAllocSize(0)
{ }
~CSimpleArray()
{
RemoveAll();
}
// Operations
int GetSize() const
{
return m_nSize;
}
BOOL Add(T& t)
{
if(m_nSize == m_nAllocSize)
{
T* aT;
int nNewAllocSize = (m_nAllocSize == 0) ? 1 : (m_nSize * 2);
aT = (T*)realloc(m_aT, nNewAllocSize * sizeof(T));
if(aT == NULL)
return FALSE;
m_nAllocSize = nNewAllocSize;
m_aT = aT;
}
m_nSize++;
SetAtIndex(m_nSize - 1, t);
return TRUE;
}
BOOL Remove(T& t)
{
int nIndex = Find(t);
if(nIndex == -1)
return FALSE;
return RemoveAt(nIndex);
}
BOOL RemoveAt(int nIndex)
{
if(nIndex != (m_nSize - 1))
memmove((void*)&m_aT[nIndex], (void*)&m_aT[nIndex + 1], (m_nSize - (nIndex + 1)) * sizeof(T));
m_nSize--;
return TRUE;
}
void RemoveAll()
{
if(m_nSize > 0)
{
free(m_aT);
m_aT = NULL;
m_nSize = 0;
m_nAllocSize = 0;
}
}
T& operator[] (int nIndex) const
{
ATLASSERT(nIndex >= 0 && nIndex < m_nSize);
return m_aT[nIndex];
}
T* GetData() const
{
return m_aT;
}
// Implementation
void SetAtIndex(int nIndex, T& t)
{
ATLASSERT(nIndex >= 0 && nIndex < m_nSize);
m_aT[nIndex] = t;
}
int Find(T& t) const
{
for(int i = 0; i < m_nSize; i++)
{
if(m_aT[i] == t)
return i;
}
return -1; // not found
}
};
// for arrays of simple types
template <class T>
class CSimpleValArray : public CSimpleArray< T >
{
public:
BOOL Add(T t)
{
return CSimpleArray< T >::Add(t);
}
BOOL Remove(T t)
{
return CSimpleArray< T >::Remove(t);
}
T operator[] (int nIndex) const
{
return CSimpleArray< T >::operator[](nIndex);
}
};
// intended for small number of simple types or pointers
template <class TKey, class TVal>
class CSimpleMap
{
public:
TKey* m_aKey;
TVal* m_aVal;
int m_nSize;
// Construction/destruction
CSimpleMap() : m_aKey(NULL), m_aVal(NULL), m_nSize(0)
{ }
~CSimpleMap()
{
RemoveAll();
}
// Operations
int GetSize() const
{
return m_nSize;
}
BOOL Add(TKey key, TVal val)
{
TKey* pKey;
pKey = (TKey*)realloc(m_aKey, (m_nSize + 1) * sizeof(TKey));
if(pKey == NULL)
return FALSE;
m_aKey = pKey;
TVal* pVal;
pVal = (TVal*)realloc(m_aVal, (m_nSize + 1) * sizeof(TVal));
if(pVal == NULL)
return FALSE;
m_aVal = pVal;
m_nSize++;
SetAtIndex(m_nSize - 1, key, val);
return TRUE;
}
BOOL Remove(TKey key)
{
int nIndex = FindKey(key);
if(nIndex == -1)
return FALSE;
if(nIndex != (m_nSize - 1))
{
memmove((void*)&m_aKey[nIndex], (void*)&m_aKey[nIndex + 1], (m_nSize - (nIndex + 1)) * sizeof(TKey));
memmove((void*)&m_aVal[nIndex], (void*)&m_aVal[nIndex + 1], (m_nSize - (nIndex + 1)) * sizeof(TVal));
}
TKey* pKey;
pKey = (TKey*)realloc(m_aKey, (m_nSize - 1) * sizeof(TKey));
if(pKey != NULL || m_nSize == 1)
m_aKey = pKey;
TVal* pVal;
pVal = (TVal*)realloc(m_aVal, (m_nSize - 1) * sizeof(TVal));
if(pVal != NULL || m_nSize == 1)
m_aVal = pVal;
m_nSize--;
return TRUE;
}
void RemoveAll()
{
if(m_nSize > 0)
{
free(m_aKey);
free(m_aVal);
m_aKey = NULL;
m_aVal = NULL;
m_nSize = 0;
}
}
BOOL SetAt(TKey key, TVal val)
{
int nIndex = FindKey(key);
if(nIndex == -1)
return FALSE;
SetAtIndex(nIndex, key, val);
return TRUE;
}
TVal Lookup(TKey key) const
{
int nIndex = FindKey(key);
if(nIndex == -1)
return NULL; // must be able to convert
return GetValueAt(nIndex);
}
TKey ReverseLookup(TVal val) const
{
int nIndex = FindVal(val);
if(nIndex == -1)
return NULL; // must be able to convert
return GetKeyAt(nIndex);
}
TKey& GetKeyAt(int nIndex) const
{
ATLASSERT(nIndex >= 0 && nIndex < m_nSize);
return m_aKey[nIndex];
}
TVal& GetValueAt(int nIndex) const
{
ATLASSERT(nIndex >= 0 && nIndex < m_nSize);
return m_aVal[nIndex];
}
// Implementation
void SetAtIndex(int nIndex, TKey& key, TVal& val)
{
ATLASSERT(nIndex >= 0 && nIndex < m_nSize);
m_aKey[nIndex] = key;
m_aVal[nIndex] = val;
}
int FindKey(TKey& key) const
{
for(int i = 0; i < m_nSize; i++)
{
if(m_aKey[i] == key)
return i;
}
return -1; // not found
}
int FindVal(TVal& val) const
{
for(int i = 0; i < m_nSize; i++)
{
if(m_aVal[i] == val)
return i;
}
return -1; // not found
}
};
// WM_FORWARDMSG - used to forward a message to another window for processing
// WPARAM - DWORD dwUserData - defined by user
// LPARAM - LPMSG pMsg - a pointer to the MSG structure
// return value - 0 if the message was not processed, nonzero if it was
#define WM_FORWARDMSG 0x037F
#endif //(_ATL_VER < 0x0300)
/////////////////////////////////////////////////////////////////////////////
// CMessageFilter - Interface for message filter support
class ATL_NO_VTABLE CMessageFilter
{
public:
virtual BOOL PreTranslateMessage(MSG* pMsg) = 0;
};
/////////////////////////////////////////////////////////////////////////////
// CUpdateUIObject - Interface for update UI support
class ATL_NO_VTABLE CUpdateUIObject
{
public:
virtual BOOL DoUpdate() = 0;
};
/////////////////////////////////////////////////////////////////////////////
// CMessageLoop - message loop implementation
class CMessageLoop
{
public:
CSimpleArray<CMessageFilter*> m_aMsgFilter;
CSimpleArray<CUpdateUIObject*> m_aUpdateUI;
MSG m_msg;
// Message filter operations
BOOL AddMessageFilter(CMessageFilter* pMessageFilter)
{
return m_aMsgFilter.Add(pMessageFilter);
}
BOOL RemoveMessageFilter(CMessageFilter* pMessageFilter)
{
return m_aMsgFilter.Remove(pMessageFilter);
}
// Update UI operations
BOOL AddUpdateUI(CUpdateUIObject* pUpdateUI)
{
return m_aUpdateUI.Add(pUpdateUI);
}
BOOL RemoveUpdateUI(CUpdateUIObject* pUpdateUI)
{
return m_aUpdateUI.Remove(pUpdateUI);
}
// message loop
int Run()
{
BOOL bDoIdle = TRUE;
int nIdleCount = 0;
BOOL bRet;
for(;;)
{
while(!::PeekMessage(&m_msg, NULL, 0, 0, PM_NOREMOVE) && bDoIdle)
{
if(!OnIdle(nIdleCount++))
bDoIdle = FALSE;
}
bRet = ::GetMessage(&m_msg, NULL, 0, 0);
if(bRet == -1)
{
ATLTRACE2(atlTraceWindowing, 0, _T("::GetMessage returned -1 (error)\n"));
continue; // error, don't process
}
else if(!bRet)
{
ATLTRACE2(atlTraceWindowing, 0, _T("CMessageLoop::Run - exiting\n"));
break; // WM_QUIT, exit message loop
}
if(!PreTranslateMessage(&m_msg))
{
::TranslateMessage(&m_msg);
::DispatchMessage(&m_msg);
}
if(IsIdleMessage(&m_msg))
{
bDoIdle = TRUE;
nIdleCount = 0;
}
}
return (int)m_msg.wParam;
}
static BOOL IsIdleMessage(MSG* pMsg)
{
// These messages should NOT cause idle processing
switch(pMsg->message)
{
case WM_MOUSEMOVE:
#ifndef UNDER_CE
case WM_NCMOUSEMOVE:
#endif //!UNDER_CE
case WM_PAINT:
case 0x0118: // WM_SYSTIMER (caret blink)
return FALSE;
}
return TRUE;
}
// Overrideables
// Override to change message filtering
virtual BOOL PreTranslateMessage(MSG* pMsg)
{
// loop backwards
for(int i = m_aMsgFilter.GetSize() - 1; i >= 0; i--)
{
CMessageFilter* pMessageFilter = m_aMsgFilter[i];
if(pMessageFilter != NULL && pMessageFilter->PreTranslateMessage(pMsg))
return TRUE;
}
return FALSE; // not translated
}
// override to change idle UI updates
virtual BOOL OnIdle(int /*nIdleCount*/)
{
for(int i = 0; i < m_aUpdateUI.GetSize(); i++)
{
CUpdateUIObject* pUpdateUI = m_aUpdateUI[i];
if(pUpdateUI != NULL)
pUpdateUI->DoUpdate();
}
return FALSE; // don't continue
}
};
}; //namespace ATL
#endif // __ATLAPP_H__