在休息時也不想再從事會需要花眼力的事務,所以此篇和上一篇的間格時間會如此久的原因在此,在此真的很配服在ASS辨公的員工,在那超低照明的環境,還能勇敢的作業,
一點也不怕以後視力的問題,以犧牲健康換來的收入,最終還是要連本帶利的加倍還回去,我是不想幫以後的眼科醫生增加收入,在以此養生觀來勸一些想入 SW 這行的的後進
本BLOG所有原創之原始程式碼皆為本人創作,非經本人同意不得轉載,非經本人授權不得使用在營利用途
回到主題上次在簡單說明了,image decoder 的原理後,接下來便是繪圖部份 ,在此請先看先繪圖的部份 source code
#include "atlcoll.h"
#include "..\common\fontobject.h"
#include "..\HLXDocvw\HLXXMLDocument.h"
#pragma once
#define ANIMATION_EFFECTS_UP (1)
#define ANIMATION_EFFECTS_DOWN (2)
#define ANIMATION_EFFECTS_LEFT (4)
#define ANIMATION_EFFECTS_RIGHT (8)
#define ANIMATION_EFFECTS_OPEN (16)
#define ANIMATION_EFFECTS_CLOSE (32)
class CControls;
class CDialogBase : public CFontObject
{
DECLARE_DATA_MAP()
public:
CDialogBase(void);
~CDialogBase(void);
bool Construct( void );
bool SetStorageMonitorMonitor(IStorageMonitor* pMonitor );
inline LONG AddControl( void )
{
return ++m_lControlCount;
}
void StartMouseFilter( void )
{
m_dwDialogTick = ::GetTickCount();
}
void OnDialogActive( void );
void OnDialogDeActive( void );
BOOL BringWindowToTop() throw()
{
if( m_hWndBase != NULL )
{
ATLASSERT(::IsWindow(m_hWndBase));
return ::BringWindowToTop(m_hWndBase);
}
return FALSE;
}
inline bool IsFocusControl( CControls* pControl )
{
return( m_pFocus != NULL && m_pFocus == pControl);
}
inline bool SetSafeHWND( HWND hWnd )
{
ATLASSERT(::IsWindow(hWnd));
m_hWndBase = hWnd;
return true;
}
inline HWND GetSafeHWND( void )
{
return m_hWndBase;
}
bool UpdateWindow( void )
{
if( m_hWndBase != NULL )
::UpdateWindow(m_hWndBase);
return false;
}
inline void PumpMessage( void )
{
MSG msg;
while(::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
BOOL bRet = GetMessage(&msg, NULL, 0, 0);
if( bRet > 0 )
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else if(0 == bRet)
{
PostQuitMessage(0);
}
else
{
// Error, ignored
}
}
}
bool WaitMessage( void )
{
if( m_hWndBase != NULL )
{
PumpMessage();
return true;
}
return false;
}
bool InvalidateRect( RECT& rct ,bool bErase )
{
if( m_hWndBase != NULL )
::InvalidateRect(m_hWndBase,&rct,bErase);
return false;
}
bool SetDocument( CHLXXMLDocument* pDocument ,DocumentTypeEnum DocumentOpenType );
inline CHLXXMLDocument* GetDocument( void )
{
return m_pDocument;
}
CControls* GetControlObject( LPCWSTR lpID );
bool GetObject( LPCWSTR lpID ,IDispatch** pDispatch );
void OnAddControlID( CXMLParse* pControl );
protected:
static DWORD m_dwThreadID;
static LONG m_lEventCount;
static EVENT_STRUCT* m_pEventList;
static UINT m_hEventMessage;
CComPtr<IStorageMonitor> m_spMonitor;
LONG m_lMessageCount;
MESSAGE_STRUCT* m_pMessageList;
protected:
DWORD m_dwDialogTick;
DWORD m_dwAnimationEffectd;
bool m_bAnimation;
bool m_bAnimationActiveOnly;
CComBSTR m_strAnimation;
bool m_bActive;
RECT m_rckeep;
HWND m_hWndBase;
POINT m_ptMouseUpPoint;
DWORD m_dwMouseUpTick;
DocumentTypeEnum m_DocumentOpenType;
CHLXXMLDocument* m_pDocument;
LONG m_lControlCount;
CComBSTR m_bstrLoad;
CControls* m_pFocus;
CComPtr<IUnknown> m_spUnkContainer;
CAtlList<CControls*> m_list;
CAtlList<CControls*> m_namelist;
CAtlList<CControls*> m_timerlist;
bool OnMouseEvent( UINT uMsg ,CControls* pControl ,POINT pt );
bool OnAddControl( CXMLParse* pControl ,CComPtr<IXMLDOMNode>& pNode );
HRESULT OnTimeControls( void );
HRESULT OnLoadControls( void );
HRESULT OnDrawControls(HDC hdcDraw ,LPCRECTL prcWBounds ,HRGN hRgn=NULL );
LRESULT OnButtonControl(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnEventMessage(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
void SetWindowActive(bool bStatus);
public:
inline bool GetDocumentDispatch(IDispatch** pDocument)
{
if( pDocument != NULL && m_pDocument != NULL && SUCCEEDED(m_pDocument->QueryInterface(IID_IDispatch,(LPVOID*)pDocument)) )
return true;
return false;
}
inline bool GetDispatch( IDispatch** pDispatch)
{
if( pDispatch != NULL && SUCCEEDED(m_pDocument->get_window(pDispatch)) )
return true;
return false;
}
inline bool GetParentDispatch( IDispatch** pDispatch )
{
if( pDispatch != NULL && SUCCEEDED(m_pDocument->get_parentwindow(pDispatch)) )
return true;
return false;
}
virtual bool CloseClientWindow(HWND hWnd)=0;
bool CloseClient(HWND hWnd)
{
return CloseClientWindow(hWnd);
}
bool OnLoad( void )
{
return true;
}
int DrawAnimation(HWND hWnd ,bool bCreate=false );
private:
static DWORD WINAPI ThreadProc( LPVOID lpParameter );
DWORD WINAPI OnEventProc( void );
bool OnCreateEvent(LONG length ,EVENT_STRUCT* pEventList);
bool OnCreateMessage(LONG length ,MESSAGE_STRUCT* pEventList);
bool ReleaseControl(void);
};
這是表頭部份,一些小又會常被使用的小功能都用 inline 使 CPU runtime 時不因 clear pipeline 而增加負擔,可能有人注意到, List 我不用 STL 而用 ATL 的 CAtlList 原因是在我比較2 者的模版後,在效能上還是以 CAtlList 在 ATL上比較好
同理在其他方面不用 STD 的理由也是相同, 一切以在 WINCE上效能考慮為優先,當然不代表我完全放棄在各平台的相容性考量,這完全是演算分析用法得失之間的平衡結果,
往後此平衡感的應用會很多
#include "StdAfx.h"
#include <atlctl.h>
#define ANIMATION_STEP (6)
#include "DialogBase.h"
#include "..\controls\controls.h"
#include "..\HLXDocvw\XMLElement.h"
#include "..\HLXDocvw\HLXDialogImpl.h"
BEGIN_DATA_MAP( CDialogBase )
PROP_DATA_STR( "animation" ,m_strAnimation );
PROP_DATA_BOOL( "animation-active-only" ,m_bAnimationActiveOnly );
PROP_DATA_LONG( "keep-left",m_rckeep.left );
PROP_DATA_LONG( "keep-top",m_rckeep.top );
PROP_DATA_LONG( "keep-right",m_rckeep.right );
PROP_DATA_LONG( "keep-bottom",m_rckeep.bottom );
PROP_DATA_STR( "onload",m_bstrLoad );
END_DATA_MAP()
DWORD CDialogBase::m_dwThreadID;
LONG CDialogBase::m_lEventCount=0;
EVENT_STRUCT* CDialogBase::m_pEventList=NULL;
UINT CDialogBase::m_hEventMessage;
CDialogBase::CDialogBase(void) : m_pFocus(NULL) ,m_hWndBase(NULL) ,m_lControlCount(0) ,m_pDocument(NULL) ,m_bAnimationActiveOnly(false),m_bAnimation(false),m_bActive(false) ,m_pMessageList(NULL) ,m_lMessageCount(0) ,m_dwAnimationEffectd(0)
{
m_strAnimation.Empty();
::ZeroMemory(&m_rckeep,sizeof(m_rckeep));
}
CDialogBase::~CDialogBase(void)
{
if( m_pMessageList != NULL )
delete m_pMessageList;
m_pMessageList = NULL;
m_spMonitor = NULL;
ReleaseControl();
}
bool CDialogBase::Construct( void )
{
if( (m_bAnimation=m_strAnimation.Length()>0) )
{
if( wcsstr(m_strAnimation,OLESTR("up")) )
m_dwAnimationEffectd |= ANIMATION_EFFECTS_UP;
if( wcsstr(m_strAnimation,OLESTR("down")) )
m_dwAnimationEffectd |= ANIMATION_EFFECTS_DOWN;
if( wcsstr(m_strAnimation,OLESTR("left")) )
m_dwAnimationEffectd |= ANIMATION_EFFECTS_LEFT;
if( wcsstr(m_strAnimation,OLESTR("right")) )
m_dwAnimationEffectd |= ANIMATION_EFFECTS_RIGHT;
}
return __super::Construct();
}
void CDialogBase::OnDialogActive( void )
{
if( m_spMonitor != NULL )
m_spMonitor->Resume();
}
void CDialogBase::OnDialogDeActive( void )
{
CXMLParse* pParse;
CControls* pControl;
POSITION ps=m_list.GetHeadPosition();
while( ps != NULL )
{
if( (pParse=m_list.GetNext(ps)) != NULL && pParse->IsControl() == true )
{
if( (pControl = static_cast<CControls*>(pParse)) )
pControl->OnDeactive();
}
}
if( m_spMonitor != NULL )
m_spMonitor->Suspend();
}
bool CDialogBase::SetStorageMonitorMonitor( IStorageMonitor* pMonitor )
{
if( pMonitor )
{
m_spMonitor = NULL;
m_spMonitor = pMonitor;
}
return true;
}
bool CDialogBase::SetDocument( CHLXXMLDocument* pDocument ,DocumentTypeEnum DocumentOpenType )
{
if( m_spMonitor != NULL )
{
m_spMonitor->Stop();
m_spMonitor = NULL;
}
if( m_pDocument != NULL )
{
m_pDocument->close();
m_pDocument->Release();
}
m_DocumentOpenType = hlxOpenNull;
m_pDocument = NULL;
if( pDocument != NULL )
{
m_DocumentOpenType=DocumentOpenType;
m_pDocument = pDocument;
m_pDocument->AddRef();
return m_pDocument!=NULL;
}
return false;
}
CControls* CDialogBase::GetControlObject( LPCWSTR lpID )
{
CXMLParse* pParse;
CControls* pControl;
POSITION ps=m_namelist.GetHeadPosition();
while( ps != NULL )
{
if( (pParse=m_namelist.GetNext(ps)) != NULL && (pControl = static_cast<CControls*>(pParse)) &&
pControl->GetID() )
{
if( wcscmp(pControl->GetID(),lpID) == 0 )
return pControl;
}
}
return NULL;
}
bool CDialogBase::GetObject( LPCWSTR lpID ,IDispatch** pDispatch )
{
CXMLElement* pElement;
CControls* pControl;
if( (pControl=GetControlObject(lpID)) )
{
if( (pElement=pControl->GetElement()) && SUCCEEDED(pElement->QueryInterface(IID_IDispatch,(LPVOID*)pDispatch)) )
return true;
}
return false;
}
bool CDialogBase::OnMouseEvent( UINT uMsg ,CControls* pControl ,POINT pt )
{
if( m_pFocus == NULL && pControl == NULL )
return false;
if( uMsg == WM_LBUTTONUP )
{
if( (::GetTickCount()-m_dwMouseUpTick) < ::GetDoubleClickTime() &&m_pFocus == pControl )
{
RECT rct;
rct.left=m_ptMouseUpPoint.x-15;
rct.right=m_ptMouseUpPoint.x+15;
rct.top=m_ptMouseUpPoint.y-15;
rct.bottom=m_ptMouseUpPoint.y+15;
if( ::PtInRect(&rct,pt) )
pControl->OnMouseDblclk(pt);
}
m_ptMouseUpPoint=pt;
m_dwMouseUpTick=::GetTickCount();
if( m_pFocus != NULL && m_pFocus != pControl )
m_pFocus->OnFocusover(pt);
if( pControl != NULL )
pControl->OnFocusout(pt);
m_pFocus = NULL;
return true;
}
if( pControl != NULL && m_pFocus == pControl )
return pControl->OnMousemove(pt);
if( pControl != NULL )
{
if( ( uMsg == WM_LBUTTONDOWN || uMsg == WM_MOUSEMOVE ) && pControl->OnFocusin(pt) == true )
{
if( m_pFocus != NULL )
m_pFocus->OnFocusover(pt);
m_pFocus = pControl;
return true;
}
return false;
}
if( m_pFocus != NULL )
m_pFocus->OnFocusover(pt);
m_pFocus = NULL;
return false;
}
HRESULT CDialogBase::OnTimeControls( void )
{
CXMLParse* pParse;
CControls* pControl;
POSITION ps=m_timerlist.GetHeadPosition();
while( ps != NULL )
{
if( (pParse=m_timerlist.GetNext(ps)) != NULL )
{
if( (pControl=static_cast<CControls*>(pParse)) )
pControl->IsTimeOut();
}
}
return S_OK;
}
HRESULT CDialogBase::OnLoadControls( void )
{
CXMLParse* pParse;
CControls* pControl;
POSITION ps=m_list.GetHeadPosition();
if( m_bstrLoad.Length() > 0 )
{
CComVariant value;
ExecCommandString(m_bstrLoad,value);
}
while( ps != NULL )
{
if( (pParse=m_list.GetNext(ps)) != NULL && pParse->IsControl() == true )
{
if( (pControl=static_cast<CControls*>(pParse)) && pControl->IsEnable() )
pControl->OnControlLoad();
}
}
if( m_spMonitor != NULL )
m_spMonitor->Start();
return S_OK;
}
HRESULT CDialogBase::OnDrawControls(HDC hdcDraw ,LPCRECTL prcWBounds ,HRGN hRgn )
{
LPRGNDATA pRgnData;
DWORD i,dwSize;
HBITMAP hOldBmp,hBmp=NULL;
HDC hMemDC=NULL;
CXMLParse* pParse;
CControls* pControl;
POSITION ps=m_list.GetHeadPosition();
if( prcWBounds == NULL || hdcDraw == NULL )
return S_FALSE;
if( (hBmp=::CreateCompatibleBitmap(hdcDraw,GetWidth(),GetHeight())) != NULL && (hMemDC=::CreateCompatibleDC(hdcDraw)) != NULL )
{
hOldBmp=(HBITMAP)::SelectObject(hMemDC,hBmp);
if( m_spImage != NULL )
DrawBackground(hMemDC,(LPRECT)prcWBounds);
pRgnData = NULL;
if( hRgn != NULL && (dwSize=GetRegionData(hRgn,0,NULL)) )
{
if( (pRgnData=(LPRGNDATA)new BYTE[dwSize]) != NULL )
GetRegionData(hRgn,dwSize,pRgnData);
}
while( ps != NULL )
{
if( (pParse=m_list.GetNext(ps)) != NULL && pParse->IsControl() == true && (pControl=static_cast<CControls*>(pParse)) )
{
if( pRgnData == NULL )
{
if( pControl->HitTest(prcWBounds) )
pControl->OnDraw(hMemDC,prcWBounds);
}
else
{
const RECTL * pRect = (const RECTL *)pRgnData->Buffer;
for( i=0 ; i < pRgnData->rdh.nCount ; i++ )
{
if( pControl->HitTest(pRect+i) )
{
pControl->OnDraw(hMemDC,prcWBounds,pRgnData);
break;
}
}
}
}
}
::BitBlt(hdcDraw,prcWBounds->left,prcWBounds->top,prcWBounds->right-prcWBounds->left,prcWBounds->bottom-prcWBounds->top,hMemDC,prcWBounds->left,prcWBounds->top,SRCCOPY);
::SelectObject(hMemDC,hOldBmp);
}
if( hMemDC != NULL )
::DeleteDC(hMemDC);
if( hBmp != NULL )
::DeleteObject(hBmp);
if( pRgnData != NULL )
delete pRgnData;
return S_OK;
}
LRESULT CDialogBase::OnButtonControl(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
// TODO: Add your message handler code here and/or call default
POINT pt;
CXMLParse* pParse;
CControls* pControl;
POSITION ps=m_list.GetHeadPosition();
bHandled = TRUE;
if( abs(::GetTickCount()-m_dwDialogTick) < 500 )
return 0;
pt.x=GET_X_LPARAM(lParam);
pt.y=GET_Y_LPARAM(lParam);
while( ps != NULL )
{
if( (pParse=m_list.GetNext(ps)) != NULL && pParse->IsMouse() == true && pParse->IsControl() == true )
{
if( (pControl = static_cast<CControls*>(pParse)) && pControl->HitTest(pt) )
{
OnMouseEvent(uMsg,pControl,pt);
return S_OK;
}
}
}
OnMouseEvent(uMsg,NULL,pt);
return 0;
}
void CDialogBase::OnAddControlID( CXMLParse* pParse )
{
CControls* pControl;
if( pParse->IsControl() && (pControl = static_cast<CControls*>(pParse)) )
{
if( pControl->GetID() != NULL )
m_namelist.AddTail(pControl);
if( pControl->IsTimerContol() )
m_timerlist.AddTail(pControl);
}
}
bool CDialogBase::OnAddControl( CXMLParse* pParse ,CComPtr<IXMLDOMNode>& pNode )
{
CControls* pControl;
if( pParse->IsControl() && (pControl = static_cast<CControls*>(pParse)) && pControl->SetBaseDialog(this) )
{
m_list.AddTail(pControl);
return true;
}
return false;
}
int CDialogBase::DrawAnimation(HWND hWnd ,bool bCreate )
{
LONG stepHeight,stepWidth;
HBITMAP hOldBmp,hBmp=NULL;
RECT rect,rct=GetControlRect();
HDC hDC,hMemDC;
if( m_bAnimation == false || (bCreate && m_bAnimationActiveOnly))
return 0;
if( (hDC=::GetDC(NULL)) )
{
stepHeight = 0;
stepWidth = 0;
hBmp=::CreateCompatibleBitmap(hDC,GetWidth(),GetHeight());
hMemDC=::CreateCompatibleDC(hDC);
hOldBmp=(HBITMAP)::SelectObject(hMemDC,hBmp);
OnDrawControls(hMemDC,(LPCRECTL)&rct,NULL);
if( m_rckeep.left )
rct.left = m_rckeep.left;
if( m_rckeep.top )
rct.top = m_rckeep.top;
if( m_rckeep.right )
rct.right = m_rckeep.right;
if( m_rckeep.bottom )
rct.bottom = m_rckeep.bottom;
rect = rct;
BLENDFUNCTION bm;
bm.BlendOp=AC_SRC_OVER;
bm.BlendFlags=0;
bm.AlphaFormat=0;
bm.SourceConstantAlpha=100;
if( (m_dwAnimationEffectd&(ANIMATION_EFFECTS_UP|ANIMATION_EFFECTS_DOWN)) )
{
stepHeight=(abs(rct.bottom-rct.top)-ANIMATION_STEP*4)/ANIMATION_STEP;
if( (m_dwAnimationEffectd&ANIMATION_EFFECTS_UP) && (m_dwAnimationEffectd&ANIMATION_EFFECTS_DOWN) )
stepHeight>>=1;
}
if( (m_dwAnimationEffectd&(ANIMATION_EFFECTS_LEFT|ANIMATION_EFFECTS_RIGHT)) )
{
stepWidth=(abs(rct.right-rct.left)-ANIMATION_STEP*4)/ANIMATION_STEP;
if( (m_dwAnimationEffectd&ANIMATION_EFFECTS_LEFT) && (m_dwAnimationEffectd&ANIMATION_EFFECTS_RIGHT) )
stepWidth>>=1;
}
if( (m_dwAnimationEffectd&ANIMATION_EFFECTS_UP) )
rct.top = rect.bottom - stepHeight;
if( (m_dwAnimationEffectd&ANIMATION_EFFECTS_DOWN) )
rct.bottom = rect.top + stepHeight;
if( (m_dwAnimationEffectd&ANIMATION_EFFECTS_UP) && (m_dwAnimationEffectd&ANIMATION_EFFECTS_DOWN) )
{
rct.top = (rect.top+rect.bottom)/2 - stepHeight;
rct.bottom = (rect.top+rect.bottom)/2 + stepHeight;
}
if( (m_dwAnimationEffectd&ANIMATION_EFFECTS_LEFT) )
rct.left = rect.right - stepWidth;
if( (m_dwAnimationEffectd&ANIMATION_EFFECTS_RIGHT) )
rct.right = rect.left + stepWidth;
if( (m_dwAnimationEffectd&ANIMATION_EFFECTS_LEFT) && (m_dwAnimationEffectd&ANIMATION_EFFECTS_RIGHT) )
{
rct.left = (rect.left+rect.right)/2 - stepWidth;
rct.right= (rect.left+rect.right)/2 + stepWidth;
}
for( int i=0 ; i < ANIMATION_STEP ; i++ )
{
rect = rct;
if( i == ANIMATION_STEP-1 )
rect=GetControlRect();
bm.SourceConstantAlpha-=50/ANIMATION_STEP;
#ifdef _WIN32_WCE
if( i == ANIMATION_STEP-1)
::BitBlt(hDC,rect.left,rect.top,GetWidth(),GetHeight(),hMemDC,0,0,SRCCOPY);
else
::AlphaBlend(hDC,m_rckeep.left+rct.left,m_rckeep.top+rct.top,abs(rct.right-rct.left),abs(rct.bottom-rct.top),hMemDC,m_rckeep.left+rect.left,m_rckeep.top+rect.top,abs(rct.right-rct.left),abs(rct.bottom-rct.top),bm);
#endif
if( (m_dwAnimationEffectd&ANIMATION_EFFECTS_UP) )
rct.top -= stepHeight;
if( (m_dwAnimationEffectd&ANIMATION_EFFECTS_DOWN) )
rct.bottom += stepHeight;
if( (m_dwAnimationEffectd&ANIMATION_EFFECTS_LEFT) )
rct.left -= stepWidth;
if( (m_dwAnimationEffectd&ANIMATION_EFFECTS_RIGHT) )
rct.right += stepWidth;
}
::SelectObject(hMemDC,hOldBmp);
if( hMemDC != NULL )
::DeleteDC(hMemDC);
if( hBmp != NULL )
::DeleteObject(hBmp);
::ReleaseDC(hWnd,hDC);
}
return 0;
}
bool CDialogBase::ReleaseControl(void)
{
CXMLParse* pParse;
POSITION ps=m_list.GetHeadPosition();
while( ps != NULL )
{
if( (pParse=m_list.GetNext(ps)) != NULL )
{
pParse->Deconstruct();
}
}
m_list.RemoveAll();
m_namelist.RemoveAll();
m_timerlist.RemoveAll();
return true;
}
void CDialogBase::SetWindowActive(bool bStatus)
{
m_bActive = bStatus;
}
LRESULT CDialogBase::OnEventMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
// TODO: Add your implementation code here
LONG i;
if( m_pMessageList != NULL )
{
for( i=0 ; i < m_lMessageCount ; i++ )
{
if( m_pMessageList[i].hMESSAGE == wParam && m_pMessageList[i].COMMAND[0] )
{
CComVariant value;
ExecCommandString(CComBSTR(m_pMessageList[i].COMMAND),value);
return S_OK;
}
}
}
if( m_pDocument != NULL && m_pDocument->GetParentWindow() )
return m_pDocument->GetParentWindow()->OnEventMessage(uMsg,wParam,lParam,bHandled);
return S_FALSE;
}
bool CDialogBase::OnCreateMessage(LONG length ,MESSAGE_STRUCT* pEventList)
{
if( m_pMessageList != NULL )
delete m_pMessageList;
m_lMessageCount = 0;
if( (m_pMessageList = new MESSAGE_STRUCT[length]) )
{
m_lMessageCount = length;
memcpy(m_pMessageList,pEventList,sizeof(MESSAGE_STRUCT)*length);
return true;
}
return false;
}
bool CDialogBase::OnCreateEvent(LONG length ,EVENT_STRUCT* pEventList)
{
LONG i;
HANDLE hThread;
DWORD dwThreadID;
m_dwThreadID=::GetCurrentThreadId();
if( length > 0 && (m_pEventList= new EVENT_STRUCT[length]) && (m_hEventMessage=::RegisterWindowMessage(OLESTR("HOLUXEVENTMESSAGE"))) )
{
memcpy(m_pEventList,pEventList,sizeof(EVENT_STRUCT)*length);
for( i=0 ; i < length ; i++ )
{
if( m_pEventList[i].PRIORITY > 50 && pEventList[i].NAME[0] )
{
m_pEventList[i].hEVENT = ::CreateEvent(NULL,FALSE,FALSE,m_pEventList[i].NAME);
m_pEventList[i].hMESSAGE = ::RegisterWindowMessage(m_pEventList[i].NAME);
}
}
m_lEventCount = length;
if( (hThread=::CreateThread(NULL,0,ThreadProc,this,0,&dwThreadID)) )
{
::SetThreadPriority(hThread,THREAD_PRIORITY_ABOVE_NORMAL);
::CloseHandle(hThread);
return true;
}
}
return false;
}
DWORD WINAPI CDialogBase::OnEventProc( void )
{
LONG i,count;
HANDLE* pEvent;
UINT* pMessage;
UINT* pStatus;
DWORD dwEventObject;
for( i=0 ,count=0 ; i < m_lEventCount ; i++ )
{
if( m_pEventList[i].hEVENT && m_pEventList[i].hMESSAGE )
count++;
}
if( count == 0 )
return -1;
pEvent = (HANDLE*)_alloca(sizeof(HANDLE)*count);
pMessage = (UINT*)_alloca(sizeof(UINT)*count);
pStatus = (UINT*)_alloca(sizeof(UINT)*count);
if( pEvent == NULL || pMessage == NULL )
return -2;
for( i=0 ,count=0 ; i < m_lEventCount ; i++ )
{
if( m_pEventList[i].hEVENT && m_pEventList[i].hMESSAGE )
{
pEvent[i] = m_pEventList[i].hEVENT;
pMessage[i] = m_pEventList[i].hMESSAGE;
pStatus[i] = m_pEventList[i].STATUS;
count++;
}
}
while( (dwEventObject=::WaitForMultipleObjects(count,pEvent,FALSE,INFINITE)) != WAIT_FAILED )
{
if( dwEventObject == WAIT_TIMEOUT )
break;
if( m_hEventMessage != NULL && ( LONG(dwEventObject-WAIT_OBJECT_0) < count ) && pMessage[dwEventObject-WAIT_OBJECT_0] != NULL )
{
::PostMessage(GetMainWindow(),m_hEventMessage,pMessage[dwEventObject-WAIT_OBJECT_0],dwEventObject);
if( (pStatus[dwEventObject-WAIT_OBJECT_0]&DLGMESSAGE_LOCAL_MASK) == DLGMESSAGE_LOCAL_PUBLIC )
::PostMessage(HWND_BROADCAST,m_hEventMessage,pMessage[dwEventObject-WAIT_OBJECT_0],dwEventObject);
}
}
return 0;
}
DWORD WINAPI CDialogBase::ThreadProc( LPVOID lpParameter )
{
if( lpParameter != NULL )
return ((CDialogBase*)lpParameter)->OnEventProc();
return 0;
}
這個是整個 XML BASE UI 的 Dialog base class ,主司 Event 的分派 ,windows input message 的處理 ,controls 的繪製與控制
其中的 OnDrawControls 就是非動晝的繪圖部份 ,剛開始先分析本回合有那些要重繪的區域,只有座落在需要重繪區的 Control 才會被要求重繪 ,
這樣重繪動作才會有效率
而 OnTimeControls 是對有宣告 timer 的 control 的處理 ,Timer 類和 Animation 都是可以秀動晝的 2類別 ,不同在 Timer 是靠不停重繪來達到動晝效果,
本身和格式無關,而Animation 只能服務於有支持 IHLXAnimation 的 decoder 控件 ,一般都是指 GIF ,MNG 類的控制
不過需要說明的是 DrawAnimation 不是用來控制上面所說的 IHLXAnimation ,而是用來處理 ,Dialog 在 Active/Deactive 時過場特效
而特別在此說明 DrawAnimation 也是本 engine 少數幾個打破行數限制的方法之一,原因很單純,為了執行時期的效能不得不那麼多行,而不能再分解下去
而在開頭的宣告中
BEGIN_DATA_MAP( CDialogBase )
PROP_DATA_STR( "animation",m_strAnimation );
PROP_DATA_BOOL( "animation-active-only" ,m_bAnimationActiveOnly );
PROP_DATA_LONG( "keep-left",m_rckeep.left );
PROP_DATA_LONG( "keep-top",m_rckeep.top );
PROP_DATA_LONG( "keep-right",m_rckeep.right );
PROP_DATA_LONG( "keep-bottom",m_rckeep.bottom );
PROP_DATA_STR( "onload",m_bstrLoad );
END_DATA_MAP()
這部份是我為了方便維護,XML tag 各元件的關連,特別為 XML標籤而開發出的XML 自動 PARSER 關連系統 ,XML 動態生成 V2.0 for ATL
大家就先當成和 MFC DDE 一般,可以自已依宣告好的關連的關係,放在正確的變數上 而 PARSER Engine Kernel XML 動態生成 V2.0 for ATL ,待到 PARSER Engine 的解說時候,會和大家解說的比較完整
而光只是用 CDialogBase 只能處理 Windows 的部份 ,在對 DOM 及 Automation 應用部份是連結不起來的,所以必需再封裝成 IDispatch 才能用在 Script 及 XML DOM 環境中
而下面的 template 正是配合 ATL 的 CDialogBase 封裝 ,因此所有的視窗訊息也是由此轉向交由CDialogBase 處理
#pragma once
#include <atlhost.h>
#include "..\Controls\DialogBase.h"
#include "..\Controls\Controls.h"
#include "XMLElement.h"
#ifdef _WIN32_WCE
#include <pm.h>
#endif
#define WM_USERSUSPEND (WM_USER+5961)
class CComHLXDialog :
public CComObjectRootEx<CComSingleThreadModel>,
public CDialogBase,
public IDispatchImpl<IHLXDialog, &IID_IHLXDialog, &LIBID_HLXDocvwLib, /* wMajor = */ 1, /* wMinor = */ 0>
{
protected:
static bool m_bLowBat;
static bool m_bACOn;
static bool m_bFirstACOn;
};
template < class T1,class WinBase ,const CLSID* pclsid = &CLSID_NULL >
class ATL_NO_VTABLE HLXDialogImpl :
public WinBase,
public CComCoClass<T1,pclsid>,
public CComHLXDialog
{
public:
typedef HLXDialogImpl< T1, WinBase ,pclsid> thisClass;
struct DialogElement
{
HWND hWnd;
OLECHAR name[NAME_MAX];
CComHLXDialog* pDialog;
CHLXXMLDocument* pDocument;
};
HLXDialogImpl() : m_bDialogMode(false) ,m_hOldWnd(NULL) ,m_exitCode(0)
{
#ifdef _DEBUG
m_dwParseKeyTickCount=0;
m_dwParseTickCount = 0;
m_dwImageTickCount = 0;
m_dwObjectTickCount = 0;
m_dwCreateImageTickCount=0;
m_dwConstructTickCount=0;
#endif
};
class DialogTraits : public CElementTraits< DialogElement >
{
public:
static bool CompareElements( const DialogElement& element1, const DialogElement& element2)
{
if( wcscmp(element1.name,element2.name)==0 )
return true;
return false;
};
};
BEGIN_MSG_MAP(thisClass)
MESSAGE_RANGE_HANDLER(WM_MOUSEFIRST,WM_MOUSELAST,OnButtonControl)
MESSAGE_HANDLER(WM_TIMER, OnTimer)
MESSAGE_HANDLER(WM_PAINT, OnPaint)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd)
MESSAGE_HANDLER(WM_USERSUSPEND, OnSuspend )
MESSAGE_HANDLER(CDialogBase::m_hEventMessage, OnEventMessage)
CHAIN_MSG_MAP(WinBase)
END_MSG_MAP()
// typedef WinBase baseWinClass;
BEGIN_COM_MAP(thisClass)
COM_INTERFACE_ENTRY(IHLXDialog)
COM_INTERFACE_ENTRY2(IDispatch,IHLXDialog)
END_COM_MAP()
IDispatch* GetDispatch( void )
{
IDispatch* pDispatch;
if( SUCCEEDED(QueryInterface(IID_IDispatch,(LPVOID*)&pDispatch)) )
return pDispatch;
return NULL;
}
// IHLXDialog Methods
STDMETHOD(get_document)(IDispatch** pVal)
{
// TODO: Add your implementation code here
if( pVal != NULL && GetDocumentDispatch(pVal) )
return S_OK;
return S_FALSE;
}
STDMETHOD(GetControl)(BSTR Name ,IDispatch** pVal)
{
// TODO: Add your implementation code here
CControls* pControl;
CComPtr<IDispatch> spDispatch;
if( pVal != NULL && (pControl=GetControlObject(Name)) )
{
if( pControl->QueryControlObject(pVal) )
return S_OK;
if( GetObject(Name,pVal) )
return S_OK;
}
return S_FALSE;
}
STDMETHOD(GetImage)(BSTR Name ,LONG lAlpha ,IDispatch** pVal)
{
// TODO: Add your implementation code here
CComPtr<IHLXImage> spImage;
if( pVal != NULL && Name != NULL && (spImage=CBackground::CreateImage(Name,lAlpha)) != NULL )
return spImage->QueryInterface(IID_IDispatch,(LPVOID*)pVal);
return S_FALSE;
}
STDMETHOD(GetString)(BSTR Name ,BSTR* pVal)
{
// TODO: Add your implementation code here
if( pVal != NULL && Name != NULL && Name[0] == OLESTR('@') )
{
LONG index;
CComBSTR bstrValue;
index=_wtoi(Name+1);
if( index > 0 )
{
if( GetLanguageString(index-1,bstrValue) )
{
bstrValue.CopyTo(pVal);
return S_OK;
}
}
}
return S_FALSE;
}
STDMETHOD(Navigate)(BSTR xmlName, BSTR TargetName, LONG* RetValue)
{
// TODO: Add your implementation code here
CComBSTR strPath;
DialogElement Element;
CComObject<CHLXXMLDocument>* pDoc;
POSITION ps;
if( wcscmp(OLESTR("system"),xmlName)==0 && wcscmp(OLESTR("interMessagebox"),TargetName) == 0 )
{
StartMouseFilter();
return S_OK;
}
::ZeroMemory(&Element,sizeof(Element));
wcscpy(Element.name,TargetName);
if( (ps=m_client.Find(Element)) )
{
Element=m_client.GetAt(ps);
if( Element.hWnd != GetTopWindow() )
{
Element.pDialog->DrawAnimation(NULL);
Element.pDialog->BringWindowToTop();
}
return S_OK;
}
if( (pDoc=new CComObject<CHLXXMLDocument>) )
{
if( SUCCEEDED(pDoc->FinalConstruct()) )
{
pDoc->SetParentWindow(this);
if( *xmlName != OLECHAR('.') )
{
strPath = m_strUrl;
strPath.AppendBSTR(xmlName);
}
else
strPath = m_pDocument->GetDocumentPath();
if( FAILED(pDoc->load(strPath,TargetName,m_strUrl,hlxOpenWindow,RetValue)) )
{
delete pDoc;
return S_FALSE;
}
}
}
else
{
return S_FALSE;
}
Element.pDocument = pDoc;
Element.pDialog=pDoc->GetSafeWindow();
Element.hWnd=Element.pDialog->GetSafeHWND();
m_client.AddHead(Element);
return S_OK;
}
STDMETHOD(CloseWindow)(LONG exitCode)
{
// TODO: Add your implementation code here
m_exitCode = exitCode;
if( m_hOldWnd != NULL )
SetMainWindow(m_hOldWnd);
if( m_bDialogMode )
EndDialog(exitCode);
else
PostMessage(WM_USER+1024,exitCode,NULL);
return S_OK;
}
STDMETHOD(ShellCommand)(BSTR strCommand, LONG flage, VARIANT_BOOL* result)
{
// TODO: Add your implementation code here
SHELLEXECUTEINFO inf;
*result = VARIANT_FALSE;
if( strCommand != NULL )
{
::ZeroMemory(&inf,sizeof(inf));
inf.cbSize = sizeof(inf);
inf.lpFile = strCommand;
inf.fMask = SEE_MASK_FLAG_NO_UI|SEE_MASK_NOCLOSEPROCESS;
inf.nShow = SW_SHOWNA;
if( ::ShellExecuteEx(&inf) )
{
*result = VARIANT_TRUE;
if( flage == 2 )
{
::Sleep(1000);
::CloseHandle(inf.hProcess);
return S_OK;
}
WaitForSingleObject(inf.hProcess,INFINITE);
return S_OK;
}
}
return S_FALSE;
}
STDMETHOD(MsgBox)(BSTR xmlName, BSTR TargetName, LONG* result)
{
// TODO: Add your implementation code here
CComBSTR strPath;
CComObject<CHLXXMLDocument>* pDoc;
if( wcscmp(OLESTR("system"),xmlName)==0 && wcscmp(OLESTR("interMessagebox"),TargetName) == 0 )
{
StartMouseFilter();
return S_OK;
}
if( (pDoc=new CComObject<CHLXXMLDocument>) )
{
if( SUCCEEDED(pDoc->FinalConstruct()) )
{
pDoc->SetParentWindow(this);
if( *xmlName != OLECHAR('.') )
{
strPath = m_strUrl;
strPath.AppendBSTR(xmlName);
}
else
strPath = m_pDocument->GetDocumentPath();
if( FAILED(pDoc->load(strPath,TargetName,m_strUrl,hlxOpenDialog,result)) )
{
pDoc->FinalRelease();
delete pDoc;
return S_FALSE;
}
}
}
else
return S_FALSE;
StartMouseFilter();
return S_OK;
}
STDMETHOD(GetExitCode)(LONG* exitCode)
{
// TODO: Add your implementation code here
*exitCode=m_exitCode;
return S_OK;
}
STDMETHOD(GetParentWindow)(IDispatch** pVal)
{
if( pVal && m_pDocument != NULL && m_pDocument->GetParentWindow() )
return m_pDocument->GetParentWindow()->QueryInterface(IID_IDispatch,(LPVOID*)pVal);
return S_FALSE;
}
STDMETHOD(GetHWnd)(LONG* pVal)
{
if( pVal )
{
*pVal = (LONG)m_hWnd;
return S_OK;
}
return S_FALSE;
}
protected:
LONG m_exitCode;
HWND m_hOldWnd;
DWORD m_dwTimeCount;
bool m_bDialogMode;
CComBSTR m_bstrUrl;
CAtlList<DialogElement,DialogTraits> m_client;
HRESULT OnDraw(ATL_DRAWINFO& di)
{
// TODO: Add your specialized code here and/or call the base class
OnDrawControls(di.hdcDraw,di.prcWBounds);
#ifdef _DEBUG
{
WCHAR buff[32];
RECT rct={0,0,200,30};
::SetTextColor(di.hdcDraw,RGB(255,255,255));
_itow(m_dwImageTickCount,buff,10);
::DrawText(di.hdcDraw,buff,-1,&rct,DT_SINGLELINE );
}
#endif
return __super::OnDraw(di);
}
LRESULT OnSuspend(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
PumpMessage();
#ifdef _WIN32_WCE
::SetSystemPowerState( NULL, POWER_STATE_SUSPEND, POWER_FORCE);
#endif
return 0;
}
LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
RECT rct=GetControlRect();
CAxDialogImpl<T1>::OnInitDialog(uMsg, wParam, lParam, bHandled);
bHandled = TRUE;
SetWindowPos(NULL,&rct,0);
m_dwTimeCount = 450;
SetTimer(1,100,NULL);
m_pFocus = NULL;
if( (m_DocumentOpenType&hlxOpenWindowRoot) || (m_DocumentOpenType&hlxOpenDialog) )
m_hOldWnd=SetMainWindow(m_hWnd);
SetSafeHWND(m_hWnd);
OnLoadControls();
if( m_pDocument != NULL && m_pDocument->GetParentWindow() )
m_pDocument->GetParentWindow()->OnDialogDeActive();
StartMouseFilter();
// FireViewChange();
return 1; // Let the system set the focus
}
LRESULT OnPaint(UINT uMsg, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
// TODO: Add your message handler code here and/or call default
PAINTSTRUCT ps;
INT ret;
HRGN update_rgn = CreateRectRgn( 0, 0, 0, 0 );
ret = 0;
if( update_rgn )
ret = GetUpdateRgn( update_rgn, FALSE );
BeginPaint(&ps);
if (ret == COMPLEXREGION )
OnDrawControls(ps.hdc,(LPCRECTL)&ps.rcPaint,update_rgn);
else
OnDrawControls(ps.hdc,(LPCRECTL)&ps.rcPaint,NULL);
#ifdef _DEBUG
{
WCHAR buff[256];
RECT rct={0,250,480,270};
::SetBkColor(ps.hdc,RGB(255,255,255));
::SetTextColor(ps.hdc,RGB(0,0,0));
::wsprintf(buff,TEXT("Navigate=%d,Object=%d,Parse=%d,Key=%d,Const=%d,LoImg=%d,CrImg=%d"),m_dwNavigateTickCount,m_dwObjectTickCount,m_dwParseTickCount,m_dwParseKeyTickCount,m_dwConstructTickCount,m_dwCreateImageTickCount,m_dwImageTickCount);
::DrawText(ps.hdc,buff,-1,&rct,DT_SINGLELINE );
}
#endif
EndPaint(&ps);
if( update_rgn != NULL )
DeleteObject( update_rgn );
return 0;
}
LRESULT OnTimer(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
if( (m_DocumentOpenType&hlxOpenWindowRoot) )
{
#ifdef _WIN32_WCE
SYSTEM_POWER_STATUS_EX sp;
if( GetSystemPowerStatusEx(&sp) )
{
// sp.ACLineStatus = AC_LINE_OFFLINE;
if( sp.ACLineStatus == AC_LINE_OFFLINE )
{
if( m_bACOn == true )
{
m_bACOn = false;
m_bFirstACOn = false;
::PostMessage(GetMainWindow(),m_hEventMessage ,::RegisterWindowMessage(OLESTR("SYSEVENT_ACOFF")),sp.BatteryLifePercent);
}
}
else
{
if( m_bACOn == false )
{
m_bACOn = true;
m_bLowBat = false;
m_dwTimeCount = 0;
if( m_bFirstACOn == false )
{
m_bFirstACOn = true;
::PostMessage(GetMainWindow(),m_hEventMessage ,::RegisterWindowMessage(OLESTR("SYSEVENT_ACON")),sp.BatteryLifePercent);
}
}
}
if( sp.ACLineStatus == AC_LINE_OFFLINE && sp.BatteryLifePercent < 30 )
{
if( m_bLowBat == false )
{
m_bLowBat = true;
m_dwTimeCount = ::GetTickCount();
::PostMessage(GetMainWindow(),m_hEventMessage ,::RegisterWindowMessage(OLESTR("SYSEVENT_LOWBATTERY")),sp.BatteryLifePercent);
}
else
{
if( ::GetTickCount()-m_dwTimeCount > 30*60*1000 )
m_bLowBat = false;
}
}
}
#endif
}
if( ::GetWindow(m_hWndBase,GW_CHILD) == NULL && ::GetWindow(m_hWndBase,GW_HWNDFIRST) == m_hWndBase )
OnTimeControls();
return 0;
}
LRESULT OnEraseBkgnd(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
bHandled = TRUE;
return 0;
}
bool CloseClientWindow(HWND hWnd)
{
DialogElement Element;
if( hWnd != NULL )
{
POSITION ps=m_client.GetHeadPosition();
while( ps != NULL )
{
Element=m_client.GetAt(ps);
if( Element.hWnd == hWnd )
{
m_client.RemoveAt(ps);
StartMouseFilter();
return true;
}
m_client.GetNext(ps);
}
}
return false;
}
};
到目前為此各位看到的是此系統對 window/dialog 的定義部份,可能很多人還不了解光是這樣,又是如何可以晝出各類元件,各類圖片?
在此再說明一下,前面也提過 這個 dialog OnDrawControls 中會找出需要重繪的 control ,在找到後呼叫 OnDraw 重繪,而這 control 的定義便如下所列
#pragma once
#include "DialogBase.h"
#include "..\common\FontObject.h"
class CControls :
public CFontObject
{
DECLARE_DATA_MAP()
public:
CControls(void);
~CControls(void);
bool IsControl( void )
{
return true;
}
inline bool _fastcall IsFocus( void )
{
return (m_pDialog != NULL && m_pDialog->IsFocusControl(this));
}
bool _fastcall FireViewChange( void )
{
Refresh();
return true;
}
bool DrawDialogBackground( HDC hdcDraw ,RECT& rct ,LONG x ,LONG y );
inline bool HitTest( POINT pt )
{
if( m_rct.bottom == 0 && m_rct.top == 0 && m_rct.left == 0 && m_rct.right == 0 )
return false;
return ::PtInRect(&m_rct,pt)==TRUE;
}
inline bool _fastcall HitTest( LPCRECTL pRct ,LPRECT pDse=NULL )
{
RECT rct;
if( m_rct.bottom == 0 && m_rct.top == 0 && m_rct.left == 0 && m_rct.right == 0 )
return false;
if( ::IntersectRect(&rct,(LPCRECT)pRct,&m_rct) )
{
if( pDse )
*pDse = rct;
return true;
}
return false;
}
virtual void SetControlValue( VARIANT varValue);
virtual bool GetControlValue(VARIANT* varValue);
virtual bool OnControlLoad( void );
virtual bool OnMouseDblclk( POINT pt );
virtual bool OnMousemove( POINT pt );
virtual bool OnFocusin( POINT pt );
virtual bool OnFocusout( POINT pt );
virtual bool OnFocusover( POINT pt );
virtual bool OnControlExternCommand( BSTR bstrCommand ,VARIANT* value);
virtual bool OnDeactive( void );
protected:
CComBSTR m_bstrLoad;
};
#include "StdAfx.h"
#include "Controls.h"
BEGIN_DATA_MAP( CControls )
PROP_DATA_STR( "onload",m_bstrLoad );
END_DATA_MAP()
CControls::CControls()
{
}
CControls::~CControls()
{
}
bool CControls::DrawDialogBackground( HDC hdcDraw ,RECT& rct ,LONG x ,LONG y )
{
if( m_pDialog != NULL )
return m_pDialog->DrawDialogBackground(hdcDraw,rct,x,y);
return false;
}
bool CControls::OnMouseDblclk( POINT pt )
{
return false;
}
bool CControls::OnMousemove( POINT pt )
{
return false;
}
bool CControls::OnFocusin( POINT pt )
{
return false;
}
bool CControls::OnFocusout( POINT pt )
{
return false;
}
bool CControls::OnFocusover( POINT pt )
{
return false;
}
void CControls::SetControlValue( VARIANT varValue)
{
}
bool CControls::GetControlValue(VARIANT* varValue)
{
return false;
}
bool CControls::OnControlExternCommand( BSTR bstrCommand ,VARIANT* value)
{
if( value )
::VariantClear(value);
return false;
}
bool CControls::OnControlLoad( void )
{
if( m_bstrLoad.Length() > 0 )
{
CComVariant value;
ExecCommandString(m_bstrLoad,value);
}
return true;
}
bool CControls::OnDeactive( void )
{
return true;
}
CControls 是所有 Control 的基礎類別 ,只要是控制元,不論是可見不可見都必需繼承,
而 CControls 向下方展除了在 code 中看到的 CFontObject (主管字型字體的控制) -> CColorObject (顏色,陰影控制)->CBackground(背景圖片控制)->CTimeEvent(時鐘元件事件控制)->CObejectRectangles(元件空間控制)->CBaseObject(元件基礎類別) 而最基礎的CBaseObject source code 如下
#pragma once
#include "..\common\xmlparse.h"
#ifdef _WIN32_WCE
#import "progid:HLXDatabase.LanguageLib" raw_interfaces_only auto_rename
#endif
#define DISPATCHOFFSET (0x40000000)
#define FIELDOFFSET (0x20000000)
class CDialogBase;
class CControls;
class CBaseObject :
public CXMLParse
{
DECLARE_DATA_MAP()
public:
CBaseObject(void);
~CBaseObject(void);
bool SetBaseDialog( CDialogBase* pDialog );
CDialogBase* GetBaseDialog( void );
inline LPCWSTR _fastcall GetID( void )
{
if( m_bstrIdName.Length() > 0 )
return m_bstrIdName;
return NULL;
}
inline LONG _fastcall GetCID( void )
{
return m_lCID;
}
inline bool _fastcall IsEnable( void )
{
return m_bEnable;
}
bool ExecCommand(VARIANT& result)
{
return ExecCommandString(m_bstrCommand,result);
}
inline bool _stdcall QueryControlObject( IDispatch** pDispatch )
{
if( m_spDispatch != NULL )
return SUCCEEDED(m_spDispatch->QueryInterface(IID_IDispatch,(LPVOID*)pDispatch));
return false;
}
bool _fastcall SetControlEnable( bool bEnable );
bool ExecClick( void );
bool RefreshRect( RECT& rct ,bool bErase);
bool UpdateWindow( void );
void WaitMessage( void );
void Deconstruct( void );
virtual bool OnCommand( LPCWSTR lpCommand ,VARIANT& result );
virtual bool OnScript( LPCWSTR lpCommand ,VARIANT& result );
bool GetLanguageString( LONG index,CComBSTR& bstrText ,LONG* pStyle=NULL);
static bool _fastcall CreateLanguage( LPCWSTR lpDirectroy );
static bool _fastcall GetDefaultLanguageName( BSTR* name );
static bool _fastcall SetDefaultLanguageName( BSTR name );
bool ParseTargetCommand(IDispatch* pDispatch, LPCWSTR lpName ,LPCWSTR lpCommand ,VARIANT& result );
bool ParseDispatchCommand(IDispatch* pDispatch, LPCWSTR lpCommand ,VARIANT& result );
void InitVariants(VARIANT* pVar ,long count);
void ClearVariants(VARIANT* pVar ,long count );
protected:
CDialogBase* m_pDialog;
HWND GetSafeHWND( void );
bool _fastcall GetControlObject( LPCWSTR lpCommand ,IDispatch** pDispatch );
CControls* _fastcall GetControlObject( LPCWSTR lpCommand );
bool GetProperty( LPCWSTR lpName ,VARIANT& value );
bool PutProperty( LPCWSTR lpName ,LPCWSTR lpValue );
bool ExecCommandString( CComBSTR& bstrCommand ,VARIANT& result )
{
::VariantClear(&result);
if( bstrCommand.Length() > 0 )
{
if( bstrCommand[0] == OLECHAR('#') )
return OnCommand( lTrim(bstrCommand+1) ,result );
else
return OnScript( lTrim(bstrCommand) ,result );
}
return false;
}
bool _fastcall OnControlObject( IDispatch* pDispatch );
bool _fastcall OnControlObject( LPCWSTR lpTarget ,LPCWSTR lpCommand );
STDMETHODIMP InterGetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames,LCID lcid, DISPID* rgdispid)
{
if( m_spDispatch != NULL )
{
if( SUCCEEDED(m_spDispatch->GetIDsOfNames(riid,rgszNames,cNames,lcid,rgdispid)) )
{
*rgdispid |= DISPATCHOFFSET;
return S_OK;
}
}
return S_FALSE;
}
STDMETHODIMP InterInvoke(DISPID dispidMember, REFIID riid,LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult,EXCEPINFO* pexcepinfo, UINT* puArgErr)
{
if( m_spDispatch != NULL )
{
if( (dispidMember&DISPATCHOFFSET) )
dispidMember &=~DISPATCHOFFSET;
return m_spDispatch->Invoke(dispidMember,riid,lcid,wFlags,pdispparams,pvarResult,pexcepinfo,puArgErr);
}
return S_FALSE;
}
private:
LONG m_lCID;
bool m_bEnable;
CComBSTR m_bstrIdName;
CComBSTR m_bstrCommand;
CComBSTR m_bstrClick;
CComBSTR m_bstrDisableClick;
CComPtr<IDispatch> m_spDispatch;
#ifdef _WIN32_WCE
static CComPtr<HLXDatabaseLib::ILanguageLib> m_spLanguageLib;
#endif
bool CopyString( LPWSTR lpBuff ,LPCWSTR lpCommand ,LPCWSTR lpEnd ,LONG Max );
bool InterCommand( VARIANT& value ,VARIANT& result );
bool InterCommand( LPCWSTR lpCommand ,VARIANT& result );
bool ConvertVariants( LPWSTR lpParam ,VARIANT* pVar ,LONG count ,DWORD dwStatus ,bool bDefString=false);
long GetParamCount(LPWSTR lpBuff,LPWSTR& lpParam ,LPWSTR& lpNext ,DWORD& dwParseStatus );
};
#include "StdAfx.h"
#include "BaseObject.h"
#include "..\Controls\DialogBase.h"
#include "..\HLXDocvw\XMLElement.h"
#include "..\HLXDocvw\HLXXMLDocument.h"
#include "..\HLXDocvw\HLXDialog.h"
#ifdef _WIN32_WCE
CComPtr<HLXDatabaseLib::ILanguageLib> CBaseObject::m_spLanguageLib;
#endif
BEGIN_DATA_MAP( CBaseObject )
PROP_DATA_STR( "id" ,m_bstrIdName );
PROP_DATA_STR( "command",m_bstrCommand );
PROP_DATA_STR( "onclick",m_bstrClick );
PROP_DATA_STR( "ondclick",m_bstrDisableClick );
END_DATA_MAP()
bool CBaseObject::CreateLanguage( LPCWSTR lpDirectroy )
{
#ifdef _WIN32_WCE
VARIANT_BOOL bResult;
WCHAR buff[MAX_PATH];
if( m_spLanguageLib == NULL && lpDirectroy )
{
if( SUCCEEDED(m_spLanguageLib.CoCreateInstance(OLESTR("HLXDatabase.LanguageLib"))) )
{
wmemset(buff,0,MAX_PATH);
wcscpy(buff,lpDirectroy);
wcscat(buff,OLESTR("resource\\info\\"));
if( SUCCEEDED(m_spLanguageLib->Open(buff,&bResult)) && bResult == VARIANT_TRUE )
{
}
}
}
#endif
return true;
}
CBaseObject::CBaseObject(void) : m_bEnable(true) ,m_pDialog(NULL) ,m_lCID(0)
{
m_spDispatch = NULL;
m_bstrCommand.Empty();
m_bstrIdName.Empty();
m_bstrClick.Empty();
m_bstrDisableClick.Empty();
}
void CBaseObject::Deconstruct( void )
{
CComPtr<ILanguage> pLanguage;
if( m_spDispatch != NULL && SUCCEEDED(m_spDispatch.QueryInterface(&pLanguage)) )
pLanguage->SetService(NULL);
pLanguage = NULL;
m_spDispatch = NULL;
return __super::Deconstruct();
}
bool CBaseObject::SetControlEnable( bool bEnable )
{
if( m_bEnable != bEnable )
{
m_bEnable = bEnable;
return true;
}
return false;
}
CBaseObject::~CBaseObject(void)
{
}
bool CBaseObject::ExecClick( void )
{
CComVariant result;
if( IsEnable() )
return ExecCommandString(m_bstrClick,result);
return ExecCommandString(m_bstrDisableClick,result);
}
HWND CBaseObject::GetSafeHWND( void )
{
if( m_pDialog != NULL )
return m_pDialog->GetSafeHWND();
return NULL;
}
bool CBaseObject::SetBaseDialog( CDialogBase* pDialog )
{
if( m_pDialog == NULL )
{
m_pDialog = pDialog;
m_lCID = pDialog->AddControl();
return true;
}
return false;
}
CDialogBase* CBaseObject::GetBaseDialog( void )
{
return m_pDialog;
}
void CBaseObject::WaitMessage( void )
{
if( m_pDialog != NULL )
m_pDialog->WaitMessage();
}
bool CBaseObject::UpdateWindow( void )
{
if( m_pDialog != NULL )
return m_pDialog->UpdateWindow();
return false;
}
bool CBaseObject::RefreshRect( RECT& rct ,bool bErase )
{
if( m_pDialog != NULL )
return m_pDialog->InvalidateRect(rct,bErase);
return false;
}
bool CBaseObject::OnScript( LPCWSTR lpCommand ,VARIANT& result )
{
return false;
}
CControls* CBaseObject::GetControlObject( LPCWSTR lpCommand )
{
if( lpCommand != NULL || m_pDialog != NULL )
return m_pDialog->GetControlObject(lpCommand);
return NULL;
}
bool CBaseObject::GetControlObject( LPCWSTR lpCommand ,IDispatch** pDispatch )
{
LPWSTR lpControlName;
if( pDispatch == NULL || lpCommand == NULL || m_pDialog == NULL )
return false;
lpControlName = (LPWSTR)lpCommand;
if( wcscmp(lpControlName,OLESTR("document")) == 0 )
{
if( m_pDialog->GetDocumentDispatch(pDispatch) && *pDispatch != NULL )
return true;
}
else if( wcscmp(lpControlName,OLESTR("window")) == 0 )
{
if( m_pDialog->GetDispatch(pDispatch) && *pDispatch != NULL )
return true;
}
else if( wcscmp(lpControlName,OLESTR("parent")) == 0 )
{
if( m_pDialog->GetParentDispatch(pDispatch) && *pDispatch != NULL )
return true;
}
else if( m_pDialog->GetObject(lpControlName,pDispatch) && *pDispatch != NULL )
{
return true;
}
return false;
}
bool CBaseObject::CopyString( LPWSTR lpBuff ,LPCWSTR lpCommand ,LPCWSTR lpEnd ,LONG Max )
{
LONG length;
if( lpBuff == NULL || lpCommand == NULL || lpEnd == NULL )
return false;
length = lpEnd-lpCommand;
if( length > Max-1 )
length = length-1;
memcpy((LPVOID)lpBuff,lpCommand,length*sizeof(OLECHAR));
lpBuff[length]=OLECHAR('\0');
return true;
}
bool CBaseObject::OnCommand( LPCWSTR lpCommand ,VARIANT& result)
{
bool bChar;
LPCWSTR lpObject,lpEnd;
bChar = false;
::VariantClear(&result);
lpEnd=lpObject=lpCommand;
while( lpEnd && *lpEnd )
{
if( *lpEnd == OLECHAR('\'') )
bChar = !bChar;
else if( bChar == false && *lpEnd == OLECHAR(';') )
{
InterCommand(lpObject,result);
lpEnd++;
lpObject=lpEnd;
continue;
}
lpEnd++;
}
if( lpObject != lpEnd )
InterCommand(lpObject,result);
return true;
}
bool CBaseObject::InterCommand( LPCWSTR lpCommand ,VARIANT& result)
{
bool bDigit,bAlpha,bObject;
DWORD dwStatus;
LPCWSTR lpObject;
CComPtr<IDispatch> spDispatch;
LPOLESTR lpName;
OLECHAR name[NAME_MAX];
bDigit = false;
bAlpha = false;
bObject = false;
lpName = name;
lpObject = lpCommand;
while( *lpObject != NULL )
{
if( isalpha(*lpObject) )
bAlpha = true;
else if( isdigit(*lpObject) )
bDigit = true;
else if( *lpObject == OLESTR('_') )
bObject = true;
else
break;
lpObject++;
}
if( lpObject == lpCommand )
return false;
if( CopyString(name,lpCommand,lpObject,NAME_MAX) == false )
return false;
if( bDigit && bAlpha == false )
{
::VariantClear(&result);
result.vt = VT_I4;
result.lVal = _wtoi(lpCommand);
return true;
}
else if( name[0] == OLECHAR('i') && wcscmp(name,OLESTR("iif")) == 0 )
{
LONG count;
VARIANT* pVariant;
LPOLESTR lpBuff,lpData,lpNext;
if( (lpBuff=(LPOLESTR)_alloca(sizeof(OLECHAR)*(wcslen(lpCommand)+1))) )
{
wmemcpy(lpBuff,lpCommand,wcslen(lpCommand)+1);
count=GetParamCount(lpBuff,lpData,lpNext,dwStatus);
if( count > 1 && (pVariant=(VARIANT*)_alloca(sizeof(VARIANT)*count)) != NULL )
{
InitVariants(pVariant,count);
if( ConvertVariants(lpData,pVariant,count,dwStatus,true) )
{
VARIANT tmp;
::VariantClear(&result);
::VariantInit(&tmp);
if( InterCommand(pVariant[count-1],tmp) && ((tmp.vt==VT_BOOL && tmp.boolVal==VARIANT_TRUE) || (tmp.vt==VT_I4 && tmp.lVal!=0)) )
InterCommand(pVariant[count-2].bstrVal,tmp);
else
{
if( count >2 )
InterCommand(pVariant[count-3].bstrVal,tmp);
}
::VariantCopy(&result,&tmp);
::VariantClear(&tmp);
ClearVariants(pVariant,count);
return true;
}
}
}
}
else if( *lpObject == OLECHAR('(') )
{
HRESULT hr;
DISPID pid;
CXMLElement* pElement;
CComPtr<IDispatch> spDispatch;
hr = S_FALSE;
if( (pElement=GetElement()) &&
SUCCEEDED(hr=pElement->GetIDsOfNames(IID_NULL,(LPOLESTR*)&lpName,1,LOCALE_SYSTEM_DEFAULT,&pid)) &&
SUCCEEDED(pElement->QueryInterface(IID_IDispatch,(LPVOID*)&spDispatch)) )
{
return ParseTargetCommand(spDispatch,lpName,lpObject,result);
}
if( hr!=S_OK && m_spDispatch != NULL )
{
hr=m_spDispatch->GetIDsOfNames(IID_NULL,(LPOLESTR*)&lpName,1,LOCALE_SYSTEM_DEFAULT,&pid);
m_spDispatch->QueryInterface(&spDispatch);
}
if( hr==S_OK )
return ParseDispatchCommand(spDispatch,lpObject,result);
}
else if( *lpObject == OLECHAR('=') && lpObject[1] == OLECHAR('=') )
{
CComVariant v1,v2;
::VariantClear(&result);
result.vt = VT_BOOL;
if( InterCommand(name,v1) && InterCommand(lpObject+2,v2) )
{
if( v1 == v2 )
result.bVal = VARIANT_TRUE;
else
result.bVal = VARIANT_FALSE;
return true;
}
return false;
}
else if( *lpObject == OLECHAR('!') && lpObject[1] == OLECHAR('=') )
{
CComVariant v1,v2;
::VariantClear(&result);
result.vt = VT_BOOL;
if( InterCommand(name,v1) && InterCommand(lpObject+2,v2) )
{
if( v1 == v2 )
result.bVal = VARIANT_FALSE;
else
result.bVal = VARIANT_TRUE;
return true;
}
return false;
}
else if( *lpObject == OLECHAR('.') && GetControlObject(name,&spDispatch) && ParseDispatchCommand(spDispatch,lpObject+1,result) )
{
return true;
}
else
{
HRESULT hr;
DISPID pid;
CXMLElement* pElement;
CComPtr<IDispatch> spDispatch;
hr = S_FALSE;
if( (pElement=GetElement()) )
{
if( SUCCEEDED(hr=pElement->GetIDsOfNames(IID_NULL,&lpName,1,LOCALE_SYSTEM_DEFAULT,&pid)) )
pElement->QueryInterface(IID_IDispatch,(LPVOID*)&spDispatch);
}
if( hr!=S_OK && m_spDispatch != NULL )
{
if( SUCCEEDED(hr=m_spDispatch->GetIDsOfNames(IID_NULL,&lpName,1,LOCALE_SYSTEM_DEFAULT,&pid)) )
m_spDispatch->QueryInterface(&spDispatch);
}
if( hr==S_OK && ParseTargetCommand(spDispatch,lpName,lpObject,result) )
{
return true;
}
}
spDispatch = NULL;
return false;
}
bool CBaseObject::OnControlObject( IDispatch* pDispatch )
{
m_spDispatch = NULL;
return (pDispatch != NULL && SUCCEEDED(pDispatch->QueryInterface(IID_IDispatch,(LPVOID*)&m_spDispatch)) );
}
bool CBaseObject::OnControlObject( LPCWSTR lpTarget ,LPCWSTR lpCommand )
{
HRESULT hr=S_FALSE;
CLSID clsid;
m_spDispatch = NULL;
if( wcscmp(OLESTR("clsid"),lpTarget) == 0 )
hr=::CLSIDFromString((LPOLESTR)lpCommand,&clsid);
else if( wcscmp(OLESTR("progid"),lpTarget) == 0 )
hr=::CLSIDFromProgID((LPOLESTR)lpCommand,&clsid);
if( SUCCEEDED(hr) )
{
#ifdef _WIN32_WCE
CComPtr<ILanguage> pLanguage;
CComPtr<IStorageMonitor> spMonitor;
if( SUCCEEDED(m_spDispatch.CoCreateInstance(clsid)) && m_spDispatch != NULL )
{
if( SUCCEEDED(m_spDispatch.QueryInterface(&spMonitor)) )
{
m_pDialog->SetStorageMonitorMonitor(spMonitor );
spMonitor = NULL;
}
if( m_spLanguageLib != NULL && SUCCEEDED(m_spDispatch.QueryInterface(&pLanguage)) )
pLanguage->SetService(m_spLanguageLib);
}
#endif
}
return true;
}
bool CBaseObject::GetProperty( LPCWSTR lpName ,VARIANT& value )
{
if( m_spDispatch != NULL )
return CCommonUtility::GetProperty(m_spDispatch,lpName,value);
return false;
}
bool CBaseObject::PutProperty( LPCWSTR lpName ,LPCWSTR lpValue )
{
CComVariant varValue;
if( m_spDispatch != NULL )
{
if( iswdigit(*lpValue) )
varValue=_wtol(lpValue);
else if( *lpValue == OLECHAR('\'') )
{
OLECHAR value[MAX_PATH];
wcscpy(value,lpValue+1);
value[wcslen(value)-1]=OLECHAR('\0');
varValue=value;
}
else
varValue=lpValue;
return CCommonUtility::PutProperty(m_spDispatch,lpName,varValue);
}
return false;
}
bool CBaseObject::GetLanguageString( LONG index,CComBSTR& bstrText ,LONG* pStyle )
{
LONG lStyle;
#ifdef _WIN32_WCE
if( m_spLanguageLib != NULL )
{
bstrText.Empty();
if( SUCCEEDED(m_spLanguageLib->GetString(index,&lStyle,&bstrText)) )
{
if( pStyle != NULL )
*pStyle = lStyle;
return true;
}
}
#endif
return false;
}
bool CBaseObject::SetDefaultLanguageName( BSTR name )
{
#ifdef _WIN32_WCE
if( m_spLanguageLib != NULL && m_spLanguageLib->SetDefaultLanguageName(name)==S_OK )
{
return true;
}
#endif
return false;
}
bool CBaseObject::GetDefaultLanguageName( BSTR* name )
{
#ifdef _WIN32_WCE
if( m_spLanguageLib != NULL )
{
m_spLanguageLib->GetName(name);
return true;
}
#endif
return false;
}
void CBaseObject::InitVariants( VARIANT* pVar ,long count)
{
for( long i=0 ; pVar != NULL && i < count ; i++ )
::VariantInit(pVar+i);
}
void CBaseObject::ClearVariants( VARIANT* pVar ,long count)
{
for( long i=0 ; pVar != NULL && i < count ; i++ )
::VariantClear(pVar+i);
}
bool CBaseObject::ConvertVariants( LPWSTR lpParam ,VARIANT* pVars ,LONG count ,DWORD dwStatus ,bool bDefString )
{
int index;
LONG i;
if( lpParam == NULL || pVars == NULL )
return false;
if( count == 0 )
return true;
for( i=0 ; i < count ; i++ )
{
index = count-i-1;
if( dwStatus&(0x03<<(index*2)) )
{
InterCommand(lpParam,pVars[index]);
}
else if( iswdigit(*lpParam) || (*lpParam == OLESTR('-') && iswdigit(lpParam[1])) )
{
pVars[index].vt = VT_I4;
pVars[index].lVal = _wtoi(lpParam);
}
else if( (*lpParam == OLECHAR('\'') && lpParam[wcslen(lpParam)-1] == OLECHAR('\'')) )
{
pVars[index].vt = VT_BSTR;
pVars[index].bstrVal = ::SysAllocStringLen(lpParam+1,wcslen(lpParam)-2);
}
else
{
if( bDefString == false )
InterCommand(lpParam,pVars[index]);
else
{
pVars[index].vt = VT_BSTR;
pVars[index].bstrVal = ::SysAllocString(lpParam);
}
}
lpParam += wcslen(lpParam)+1;
}
return true;
}
bool CBaseObject::ParseTargetCommand(IDispatch* pDispatch, LPCWSTR lpName ,LPCWSTR lpCommand ,VARIANT& result )
{
DWORD dwStatus;
LPOLESTR lpBuff,lpData,lpNext;
DISPID idDisp;
DISPPARAMS dispParams;
EXCEPINFO FAR *pExcepInfo = NULL;
unsigned int FAR puArgErr = NULL;
HRESULT hr;
if( pDispatch->GetIDsOfNames(IID_NULL,(LPOLESTR*)&lpName,1,LOCALE_SYSTEM_DEFAULT,&idDisp) == S_OK )
{
if( (lpBuff=(LPOLESTR)_alloca(sizeof(OLECHAR)*(wcslen(lpCommand)+1))) )
{
dispParams.cNamedArgs = NULL;
dispParams.rgdispidNamedArgs = NULL;
memcpy(lpBuff,lpCommand,sizeof(OLECHAR)*(wcslen(lpCommand)+1));
dispParams.cArgs=GetParamCount(lpBuff,lpData,lpNext,dwStatus);
if( (dispParams.rgvarg=(VARIANT*)_alloca(sizeof(VARIANT)*dispParams.cArgs)) != NULL )
{
InitVariants(dispParams.rgvarg,dispParams.cArgs);
if( ConvertVariants(lpData,dispParams.rgvarg,dispParams.cArgs,dwStatus) )
{
::VariantClear(&result);
hr=pDispatch->Invoke(idDisp,IID_NULL,LOCALE_SYSTEM_DEFAULT,DISPATCH_METHOD|DISPATCH_PROPERTYGET,&dispParams,&result,pExcepInfo,&puArgErr);
ClearVariants(dispParams.rgvarg,dispParams.cArgs);
return true;
}
}
}
return true;
}
return false;
}
bool CBaseObject::ParseDispatchCommand(IDispatch* pDispatch, LPCWSTR lpCommand ,VARIANT& result )
{
LPCWSTR lpParam;
LPOLESTR lpName;
if( pDispatch == NULL || (lpParam=wcschr(lpCommand,OLECHAR('('))) == NULL || lpParam == lpCommand )
return false;
if( (lpName=(LPOLESTR)_alloca(sizeof(OLECHAR)*((lpParam-lpCommand)+1))) )
{
lpName[lpParam-lpCommand] = OLECHAR('\0');
memcpy(lpName,lpCommand,sizeof(OLECHAR)*(lpParam-lpCommand));
return ParseTargetCommand(pDispatch,lpName,lpParam,result);
}
return false;
}
bool CBaseObject::InterCommand( VARIANT& value ,VARIANT& result )
{
if( value.vt == VT_BSTR )
return InterCommand( value.bstrVal ,result );
::VariantClear(&result);
::VariantCopy(&result,&value);
return true;
}
long CBaseObject::GetParamCount( LPWSTR lpBuff ,LPWSTR& lpParam ,LPWSTR& lpNext ,DWORD& dwParseStatus )
{
WCHAR lastChar,curChar;
bool bChar=false,bStr=false,bOperator=false;
LONG lCount=0,lParamCount=0;
LPWSTR lpData=lpBuff;
dwParseStatus = 0;
lastChar = NULL;
while( lpData && *lpData )
{
curChar = *lpData;
if( !iswspace(curChar) && !(bStr == false && (curChar==OLECHAR('(')||curChar==OLECHAR(')'))) )
bChar = true;
if( curChar == OLECHAR('\'') )
bStr = !bStr;
if( bStr == false )
{
if( (curChar == OLECHAR('=') || curChar == OLECHAR('>') || curChar == OLECHAR('<') ) )
bOperator = true;
if( curChar == OLECHAR('(') )
{
if( lCount == 0 )
lpParam = lpData+1;
lCount++;
}
else if( curChar == OLECHAR(')') )
{
if( --lCount == 0 )
{
if( bChar == true )
lParamCount++;
*lpData = OLECHAR('\0');
break;
}
}
else if( curChar == OLECHAR(';') )
{
if( bChar == false )
{
*lpData = OLECHAR('\0');
break;
}
}
else if( curChar == OLECHAR(',') && lCount < 2 )
{
bChar = false;
if( bOperator )
dwParseStatus |= 0x1;
dwParseStatus <<= 2;
lParamCount++;
*lpData = OLECHAR('\0');
bOperator = false;
}
}
lastChar = *lpData;
lpData++;
}
if( bOperator )
dwParseStatus |= 0x1;
lpNext = lpData;
return lParamCount;
}
這個基礎類別不只上至連接 控制元件,轉向dialog message ,向下還關連到 XML 分析及腳本處理部份 ,ExecCommandString 便是腳本引擎的入口,而InterCommand 便是腳本引擎核心之一,
XXXLanguage ,更是多國語言處理的門戶,不過這是後話,以後再解釋,由此可見此 class 的重要性
因為 CControls 是定義在抽象基礎類別,很多行為還要再向上看去,大家才能看到真正的繪圖動作,而這抽象的分解也正是C++ 的思想核心,往後所有的物件分解,和聚合也都以此思想核心進行 ,故先公開CBaseObject 以後有很多機會再回頭看到 CBaseObject ,而下一步再向上方展的部份待到下篇再解說