📄 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);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -