用自建的滚动条代替windows控件内建的滚动条(1)

       最近遇到了这样的问题,使用某个皮肤软件来为界面换皮肤,但必须取得控件的句柄,才能对控件换皮肤。对于标准控件,如CEdit,CRichEdit, CTreeCtrl等控件,内建的滚动条句柄无法取得,为滚动条换肤就成了问题。于是,本人用自建的滚动条代替那些控件内建的滚动条,来为滚动条换肤.。
      控件内建的滚动条属于控件的非客户区,因而可考虑把非客户区去掉,然后在客户区建一个滚动条,来代替内建的滚动条。但要考虑以下问题:
     1. 如何把非客户区(内建滚动条区域)去掉。
     2. 自建的滚动条如何与内建的滚动条显示保持一致。主要是何时显示与隐藏,以及滚动保持一致。
    3. 控件的数据内容不能覆盖滚动条的显示。

  以下例子在CEdit中创建自建的垂直滚动条。.cpp文件主要代码如下:

void CScrollEdit::PreSubclassWindow()
{
 
    //自建滚动条 ,m_vBar为自建滚动条 ,BAR_WIDTH为m_vBar的宽度 =16
    CRect rc;
    GetClientRect(&rc);
    rc.left =rc.right - BAR_WIDTH;
    m_vBar.Create(WS_CHILD|SBS_VERT,rc,this,SB_VERT_ID);
    EnableScrollBarCtrl(SB_VERT);
    CEdit::PreSubclassWindow();       

}

void CScrollEdit::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp)
{
  //解决问题1
  //    CEdit::OnNcCalcSize(bCalcValidRects, lpncsp);
  //把原来的消息处理方法删去, 这样非客户区(内建的滚动条区域)将不会创建.
 
}

void CScrollEdit::OnSize(UINT nType, int cx, int cy)
{     //解决问题2
    CEdit::OnSize(nType, cx, cy);   
    m_vBar.SetWindowPos(0,cx - BAR_WIDTH,0,BAR_WIDTH,cy,SWP_NOZORDER);
    m_vBar.Invalidate();
    ShowBarState(); //决定是否显示滚动条
}
void CScrollEdit::OnUpdate()
{  //解决问题2,3
   SCROLLINFO ScrInfo;
   GetScrollInfo(SB_VERT,&ScrInfo);
   m_vBar.SetScrollInfo(&ScrInfo);
   m_vBar.Invalidate();
 

}

HBRUSH CScrollEdit::CtlColor(CDC* pDC, UINT nCtlColor)
{     //解决问题3
    m_vBar.Invalidate();
    return NULL;

}

void CScrollEdit::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
//解决问题2,3
SCROLLINFO ScrInfo;
GetScrollInfo(SB_VERT,&ScrInfo);
m_vBar.SetScrollInfo(&ScrInfo);  
int pos;
pos = m_vBar.GetScrollPos();
switch ( nSBCode )
{
case SB_LINEUP:

pos -= 1;

break;

case SB_LINEDOWN:

pos += 1;

break;

case SB_PAGEUP:

pos -= 10;

break;

case SB_PAGEDOWN:

pos += 10;

break;

case SB_TOP:

pos = ScrInfo.nMin;

break;

case SB_BOTTOM:

pos = ScrInfo.nMax;

break;

case SB_THUMBPOSITION:

pos = nPos;

break;

default:

return;

}

if ( pos < ScrInfo.nMin )

pos = ScrInfo.nMin;

else if ( pos > ScrInfo.nMax )

pos = ScrInfo.nMax;

m_vBar.SetScrollPos(pos);   
       
CEdit::OnVScroll(nSBCode, nPos, pScrollBar);

}

void CScrollEdit::OnVscroll()
{
    //解决问题2,3
     CRect rc;
     GetClientRect(&rc);
     SCROLLINFO ScrInfo;
     GetScrollInfo(SB_VERT,&ScrInfo);
     m_vBar.SetScrollInfo(&ScrInfo);       
     m_vBar.ShowWindow(TRUE);

}

void CScrollEdit::OnChange()
{
    //解决问题2
   ShowBarState();   
}

void CScrollEdit::ShowBarState() //决定是否显示滚动条
{
    //解决问题2
    int li = LineIndex(0);
    CPoint po = PosFromChar(li + 1);
    CRect rc;
    GetClientRect(&rc);
    if(po.y < -1)
    {
        m_vBar.ShowWindow(TRUE);
        rc.right -= BAR_WIDTH;
    }
    else
    {
        m_vBar.ShowWindow(FALSE);
    }
    SetRect(&rc);
}

       另外要注意,CSrollEdit是通过重写OnNcCalcSize事件处理过程来去掉内建的滚动条,所以在父窗体中Edit控件如果不是动态创建的,需要在父窗体中的OnInitDialog方法中Edit控件(已用CSrollEdit子类化了)调用SetWindowPos方法来触发OnNcCalcSize事件。
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值