www.pudn.com > WinGOS.rar > Wnd.cpp


// Wnd.cpp: implementation of the CWnd class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "gos.h" 
#include "Wnd.h" 
 
#ifdef _DEBUG 
CWnd::CWnd() 
{ 
	m_pParent=NULL; 
	m_pData=NULL; 
} 
CWnd::~CWnd() 
{ 
	ASSERT(!m_pParent); 
	ASSERT(!m_pData); 
} 
#endif //_DEBUG 
 
BOOL CWnd::Create(DWORD nStyle, LPCRECT pRect, CPWnd *pParent,int nID) 
{ 
	ASSERT(!m_pParent); 
	m_nStyle=nStyle; 
	m_pData=NULL; 
	m_nCtrlID=nID; 
	if(pRect) 
	{ 
		m_rclWnd=pRect; 
		m_rclWnd.OffsetRect(pParent->m_rclClient.TopLeft()); 
		m_rclInv=m_rclWnd; 
		m_rclClient=m_rclWnd; 
	} 
	pParent->AddControl(this); 
	PostMessage(WM_CREATE,0,0); 
	PostMessage(WM_MOVE,0,0); 
	return TRUE; 
} 
 
BOOL CWnd::Create(LPCTSTR pszText,DWORD nStyle,LPCRECT pRect,CPWnd* pParent,int nID) 
{ 
	ASSERT(!(nStyle&WS_OWNERDATA)); 
	Create(nStyle,pRect,pParent); 
 
	m_pData=(PVOID)CString::StrAllocEx(pszText); 
 
	return TRUE; 
} 
 
CWnd* CWnd::GetWindow(UINT nCmd) 
{ 
	PWND pWnd; 
	switch(nCmd) 
	{ 
	case GW_CHILD: 
		pWnd=(m_nStyle&WS_PARENT)?PPWND(this)->GetChild():NULL; 
		break; 
	case GW_PARENT: 
		pWnd=m_pParent; 
		break; 
	case GW_DESKTOP: 
		pWnd=GetDesktopWindow(); 
		break; 
	case GW_FOCUS: 
		pWnd=m_pParent->GetActiveControl(); 
		break; 
	case GW_HWNDFIRST: 
		pWnd=m_pParent->GetChild(); 
		break; 
	case GW_HWNDLAST: 
		pWnd=m_pParent->GetChild()->m_pPrev; 
		break; 
	case GW_HWNDNEXT: 
		pWnd=m_pNext; 
		break; 
	case GW_HWNDPREV: 
		pWnd=m_pPrev; 
		break; 
	default: 
		pWnd=NULL; 
	} 
	return pWnd; 
} 
 
CDesktop* CWnd::GetDesktopWindow() 
{ 
	PWND pWnd=this; 
	while(pWnd->m_pParent) 
		pWnd=pWnd->m_pParent; 
	return (CDesktop*)pWnd; 
} 
 
int CWnd::GetChildHierarchy(CWnd* pParent) 
{ 
	CWnd* pWnd=this; 
	int nLevel=-1; 
	do 
	{ 
		nLevel++; 
		if(pWnd==pParent)break; 
		pWnd=pWnd->m_pParent; 
	}while(pWnd); 
	return pWnd?nLevel:-1; 
} 
 
CWnd* CWnd::WindowFromPoint(POINT pt) 
{ 
	PWND pChild,pWnd,pTmp; 
	if(!m_rclWnd.PtInRect(pt)) 
		return NULL; 
	pTmp=this; 
	do 
	{ 
		pWnd=pTmp; 
		if(!(pWnd->m_nStyle&WS_PARENT)) 
			break; 
		if(!pWnd->m_rclClient.PtInRect(pt)) 
			break; 
		pChild=PPWND(pWnd)->GetChild(); 
		if(!pChild) 
			break; 
		pTmp=pChild->m_pPrev; 
		for(;;) 
		{ 
			if(pTmp->m_rclWnd.PtInRect(pt)) 
				break; 
			if(pTmp==pChild) 
			{ 
				pTmp=NULL; 
				break; 
			} 
			pTmp=pTmp->m_pPrev; 
		} 
	}while(pTmp); 
	return pWnd; 
} 
 
void CWnd::MoveWindow(LPCRECT pRect) 
{ 
	ASSERT(m_pParent); 
	CRect r(m_rclWnd); 
 
	r.IntersectRect(pRect); 
	if(r.IsRectEmpty()) 
		m_pParent->Invalidate(m_rclWnd); 
	else 
	{ 
		r=m_rclWnd; 
		r.UnionRect(pRect); 
		m_pParent->Invalidate(r); 
	} 
	m_rclWnd=pRect; 
	PrvOffsetWindow(m_pParent->m_rclClient.TopLeft()); 
	m_rclClient=m_rclWnd; 
	PostMessage(WM_MOVE,0,0); 
	if(r.IsRectEmpty())Invalidate(m_rclWnd); 
} 
 
CDC* CWnd::GetDC() 
{ 
	PWND pDCWnd=this; 
	while(!(pDCWnd->m_nStyle & WS_OWNERDC)) 
	{ 
		pDCWnd=pDCWnd->m_pParent; 
		ASSERT(pDCWnd); 
	} 
	return (PDC)pDCWnd->MsgProc(WM_GETOWNDC,WPARAM(this),0); 
} 
 
void CWnd::Invalidate(LPCRECT pRect) 
{ 
	CRect r; 
	if(!pRect) 
		r=m_rclClient; 
	else 
	{ 
		r=pRect; 
		r.IntersectRect(m_rclWnd); 
	} 
 
	if(m_nStyle & WS_INVALIDATE) 
		m_rclInv.UnionRect(r); 
	else 
	{ 
		m_nStyle |= WS_INVALIDATE; 
		m_rclInv=r; 
	} 
 
	PostMessage(WM_INVALIDATE,0,0); 
} 
 
void CWnd::SetWindowText(CString &string) 
{ 
	ASSERT(!(m_nStyle&WS_OWNERDATA)); 
	int nLen=string.GetLength(); 
	LPCTSTR pNew=nLen>0?LPCTSTR(string):NULL; 
	m_pData=(PVOID)CString::StrReAllocEx( 
		LPCTSTR(m_pData),pNew,nLen); 
	Invalidate(NULL); 
} 
 
void CWnd::SetWindowText(LPCTSTR pszString) 
{  
	ASSERT(!(m_nStyle&WS_OWNERDATA)); 
	int nLen; 
	if(IsWritablePtr(pszString)) 
	{ 
		nLen=strlen(pszString); 
		if(nLen<=0)pszString=NULL; 
	} 
	else 
		nLen=0; 
	m_pData=(PVOID)CString::StrReAllocEx( 
		LPCTSTR(m_pData),pszString,nLen); 
	Invalidate(NULL); 
} 
 
int CWnd::GetWindowText(LPTSTR pszStringBuf,int nMaxCount) 
{ 
	ASSERT(!(m_nStyle&WS_OWNERDATA)); 
	int nCount=GetWindowTextLength()+1; 
	if(nCount>=nMaxCount) 
		nCount=nMaxCount; 
	CopyMemory(pszStringBuf,m_pData,nCount*sizeof(TCHAR)); 
	return nCount-1; 
} 
 
int CWnd::GetScrollRange(int nBar,PINT pMinPos,PINT pMaxPos) 
{ 
	DWORD nVal; 
	MsgProc(WM_GETSCROLLRANGE,nBar,LPARAM(&nVal)); 
	if(pMinPos) 
		*pMinPos=(short)LOWORD(nVal); 
	if(pMaxPos) 
		*pMaxPos=(short)HIWORD(nVal); 
	return short(HIWORD(nVal))-short(LOWORD(nVal)); 
} 
 
void CWnd::SetScrollRange(int nBar,int nMinPos,int nMaxPos) 
{ 
	DWORD nVal=MAKELONG(nMinPos,nMaxPos); 
	MsgProc(WM_SETSCROLLRANGE,nBar,nVal); 
} 
 
 
LRESULT CWnd::MsgProc(UINT message, WPARAM wParam, LPARAM lParam) 
{ 
	switch(message) 
	{ 
	case WM_PAINTING: 
		PrvOnPainting(wParam,lParam); 
		break; 
	case WM_ERASEBKGND: 
		OnEraseBkgnd(PDC(wParam)); 
		break; 
	case WM_NCPAINT: 
		OnNcPaint(PDC(wParam)); 
		break; 
	case WM_INVALIDATE: 
		PrvOnInvalidate(); 
		break; 
	case WM_MOVE: 
		OnMove(); 
		break; 
	case WM_QUERYMOUSECURSOR: 
		wParam=(WPARAM)OnQueryMouseCursor(); 
		break; 
	case WM_DESTROY: 
		OnDestroy(); 
		break; 
	case msgGetMQThread: 
		wParam=m_pParent->MsgProc(msgGetMQThread,0,0); 
		break; 
	case WM_CTLCOLOR: 
		wParam=m_pParent->MsgProc(WM_CTLCOLOR,wParam,lParam); 
		break; 
	case WM_GETFONT: 
		wParam=m_pParent->MsgProc(WM_GETFONT,wParam,lParam); 
		break; 
	case WM_DRAWITEM: 
		m_pParent->MsgProc(WM_DRAWITEM,wParam,lParam); 
		break; 
	default: 
		wParam=0; 
	} 
	return wParam; 
} 
 
void CWnd::OnDestroy() 
{ 
	if(!(m_nStyle&WS_OWNERDATA)) 
		CString::StrFreeEx(LPCTSTR(m_pData)); 
	DEBUG_ONLY(m_pData=NULL); 
} 
 
void CWnd::OnMove() 
{ 
	int nBorder=0; 
	if(m_nStyle & WS_STATICEDGE) 
		nBorder++; 
	if(m_nStyle & WS_BORDER) 
		nBorder++; 
	if(m_nStyle & WS_CLIENTEDGE) 
		nBorder+=2; 
	if(nBorder) 
		m_rclClient.DeflateRect(nBorder); 
} 
 
void CWnd::OnNcPaint(CDC* pDC) 
{ 
	CRect r(m_rclWnd); 
	DWORD nStyle=m_nStyle; 
	if(nStyle & WS_STATICEDGE) 
	{ 
		if(nStyle & WS_BORDER) //WS_DLGMODALFRAME 
		{ 
			pDC->Draw3dRect(r,GetCtlColor(COLOR_3DLIGHT),GetCtlColor(COLOR_3DDKSHADOW)); 
			r.DeflateRect(1); 
			pDC->Draw3dRect(r,GetCtlColor(COLOR_3DHLIGHT),GetCtlColor(COLOR_3DSHADOW)); 
			r.DeflateRect(1); 
		} 
		else 
		{ 
			pDC->Draw3dRect(r,GetCtlColor(COLOR_3DHLIGHT),GetCtlColor(COLOR_3DSHADOW)); 
			r.DeflateRect(1); 
		} 
	} 
	else if(nStyle & WS_BORDER) 
	{ 
		pDC->DrawRect(r,GetCtlColor(COLOR_WINDOWTEXT),PS_SOLID); 
	} 
	if(m_nStyle & WS_CLIENTEDGE) 
	{ 
		pDC->Draw3dRect(r,GetCtlColor(COLOR_3DSHADOW),GetCtlColor(COLOR_3DHLIGHT)); 
		r.DeflateRect(1); 
		pDC->Draw3dRect(r,GetCtlColor(COLOR_3DDKSHADOW),GetCtlColor(COLOR_3DLIGHT)); 
	} 
} 
 
void CWnd::OnEraseBkgnd(CDC* pDC) 
{ 
	DWORD nStyle=GetStyle(); 
	COLORREF clr; 
	 
	if(nStyle&WS_SCRBKGND) 
		GetDesktopWindow()->OnEraseBkgnd(pDC); 
	if(!(nStyle&WS_NOBKGND) == !(nStyle&WS_SCRBKGND)) 
	{ 
		clr=GetCtlColor(COLOR_WINDOW); 
		if(nStyle&WS_NOBKGND) 
		{ 
			clr &= ~(255<<24); 
			clr |= 128<<24; 
		} 
		pDC->FillSolidRect(GetClientRect(),clr); 
	} 
} 
 
void CWnd::PrvOffsetWindow(POINT pt) 
{ 
	m_rclWnd.OffsetRect(pt); 
	if(m_nStyle&WS_PARENT) 
	{ 
		PWND pWnd,pChild=PPWND(this)->GetChild(); 
		if(pChild) 
		{ 
			pWnd=pChild; 
			do 
			{ 
				pWnd->m_rclClient.OffsetRect(pt); 
				pWnd->PrvOffsetWindow(pt); 
				pWnd=pWnd->m_pNext; 
			}while(pWnd!=pChild); 
		} 
	} 
} 
 
HANDLE CWnd::PrvAddPaintMessage(CThread* pThread,HANDLE hRefMsg,LPCRECT pRect) 
{ 
	CRect r(m_rclWnd); 
	r.IntersectRect(pRect); 
	if(!r.IsRectEmpty()) 
	{ 
		PWND pWnd,pChild; 
		DWORD pt1=MAKELONG(r.left,r.top); 
		DWORD pt2=MAKELONG(r.right,r.bottom); 
		if(!(m_nStyle & WS_PRVINVALID) && (m_nStyle & WS_OWNERDC)) 
			hRefMsg=pThread->InsertMessage(this,hRefMsg,pt2,pt1); 
		else 
		{ 
			hRefMsg=pThread->InsertMessage(this,hRefMsg,pt1,pt2); 
			if(m_nStyle&WS_PARENT) 
			{ 
				pChild=PPWND(this)->GetChild(); 
				if(pChild) 
				{ 
					r=m_rclClient; 
					r.IntersectRect(pRect); 
					pWnd=pChild; 
					do 
					{ 
						hRefMsg=pWnd->PrvAddPaintMessage(pThread,hRefMsg,r); 
						pWnd=pWnd->m_pNext; 
					}while(pWnd!=pChild); 
				} 
			} 
		} 
	} 
	return hRefMsg; 
} 
 
void CWnd::PrvOnInvalidate() 
{ 
	HANDLE hMsg1,hMsg2; 
	PTHREAD pThread; 
	PWND pDCWnd,pTop,pTmp; 
	PPWND pEnd=PPWND(this); 
	CRect rclClip(m_rclInv); 
 
	//查找最后一个需要更新的窗体 
	pEnd->m_nStyle |= WS_PRVINVALID; 
	for(;;) 
	{ 
		if(!(pEnd->m_nStyle & WS_TRANSPARENT)) 
			break; 
		if(pEnd->m_nStyle & WS_OWNERDC) 
			break; 
		pTmp=pEnd; 
		pEnd=pEnd->m_pParent; 
		ASSERT(pEnd); 
		rclClip.IntersectRect(pEnd->m_rclClient); 
		if(pEnd->m_nStyle & WS_CLIPSIBLINGS) 
		{ 
			pTop=pEnd->GetChild()->m_pPrev; 
			for(pTmp=pTmp->m_pPrev;pTmp!=pTop;pTmp=pTmp->m_pPrev) 
			{ 
				if(!(pTmp->m_nStyle & WS_TRANSPARENT) && 
					pTmp->m_rclWnd.IncludeRect(rclClip)) 
				{ 
					pEnd=PPWND(pTmp); 
					break; 
				} 
			} 
			if(pEnd==pTmp)break; 
		} 
		pEnd->m_nStyle |= WS_PRVINVALID; 
		if(!(pEnd->m_nStyle & WS_TRANSPARENT)) 
			break; 
		if(pEnd->m_nStyle & WS_OWNERDC) 
			break; 
	} 
	//向需要更新的窗体发送缓图消息 
	pDCWnd=pTmp=pEnd; 
	pEnd=pEnd->m_pParent; 
	while(!(pDCWnd->m_nStyle & WS_OWNERDC)) 
	{ 
		pDCWnd=pDCWnd->m_pParent; 
		ASSERT(pDCWnd); 
		pDCWnd->m_nStyle |= WS_PRVINVALID; 
		rclClip.IntersectRect(pDCWnd->m_rclClient); 
	} 
	pThread=pDCWnd->GetMQThread(); 
	hMsg1=pThread->InsertMessage(pDCWnd,WM_PAINTING,WM_PAINTSTART,LPARAM(this)); 
	hMsg2=pTmp->PrvAddPaintMessage(pThread,hMsg1,&rclClip); 
	while(pEnd) 
	{ 
		if(pEnd->m_nStyle & WS_CLIPSIBLINGS) 
		{ 
			pTop=pEnd->GetChild(); 
			for(pTmp=pTmp->m_pNext;pTmp!=pTop;pTmp=pTmp->m_pNext) 
			{ 
				if(!(pTmp->m_nStyle & WS_TRANSPARENT) && 
					pTmp->m_rclWnd.IncludeRect(rclClip)) 
				{ 
					pTmp=NULL; 
					break; 
				} 
				hMsg2=pTmp->PrvAddPaintMessage(pThread,hMsg2,&rclClip); 
			} 
			if(!pTmp)break; 
		} 
		pTmp=pEnd; 
		pEnd=pEnd->m_pParent; 
	} 
	if(pTmp) 
	{ 
		pThread->InsertMessage(pDCWnd,hMsg2,WM_PAINTOVER,LPARAM(this)); 
		pDCWnd->MsgProc(WM_SETPAINTCLIP,WPARAM(&rclClip),LPARAM(this)); 
	} 
	else 
		pThread->RemoveMessage(hMsg1,hMsg2); 
	pTmp=this; 
	do 
	{ 
		pTmp->m_nStyle &= ~WS_PRVINVALID; 
		pTmp=pTmp->m_pParent; 
	}while(pTmp && (pTmp->m_nStyle&WS_PRVINVALID));  
} 
 
void CWnd::PrvOnPainting(WPARAM wParam,LPARAM lParam) 
{ 
	PDC pDC=GetDC(); 
	CRect r,r2(m_rclClient); 
	r.SetRect(CPoint(wParam),CPoint(lParam)); 
	if(r.IncludeRect(m_rclInv)) 
		m_nStyle &= ~WS_INVALIDATE; 
	if(!r2.IncludeRect(r)) 
	{ 
		pDC->SetClipRect(r); 
		MsgProc(WM_NCPAINT,WPARAM(pDC),0); 
	} 
	r.IntersectRect(r2); 
	if(!r.IsRectEmpty()) 
	{ 
		pDC->SetClipRect(r); 
		MsgProc(WM_ERASEBKGND,WPARAM(pDC),0); 
		MsgProc(WM_PAINT,WPARAM(pDC),0); 
	} 
}