滚动条
<p>滚动条CScrollBar,继承于CView,支持CView的所有属性和方法。通过给滚动条设置不同的滑块图片,可以得到不同形态的滚动条。</p>
<ul>
<li>滚动条可以单独存在</li>
</ul>
<pre><code class="language-xml"><ScrollBar Id="2001" Height="10" AlignParentBottom="5" AlignParentLeft="20" AlignParentRight="20" Thumb="ScrollBar.png"/></code></pre>
<ul>
<li>滚动条也可以搭配滚动视图:</li>
</ul>
<pre><code class="language-xml"><TreeView Id="100" AlignParentLeft="40" AlignParentRight="40" Height="200" AlignParentVertCenter="0" ScrollBar="ScrollBar.png"/></code></pre>
<h2>属性和相关方法</h2>
<h4>设置滚动条滑块的图片</h4>
<ul>
<li>通过XML属性控制如下:</li>
</ul>
<pre><code class="language-xml">Thumb="ScrollBar.png"</code></pre>
<ul>
<li>通过C++程序代码调用方法控制如下:</li>
</ul>
<pre><code class="language-c">void SetScrollThumb(const String& strThumb);</code></pre>
<h4>设置滚动条的滚动视图</h4>
<ul>
<li>通过C++程序代码调用方法控制如下:</li>
</ul>
<pre><code class="language-c">void SetScrollLayout(CScrollLayout* pLayout);</code></pre>
<h4>设置滚动条信息</h4>
<ul>
<li>通过C++程序代码调用方法控制如下:</li>
</ul>
<pre><code class="language-c">void SetScrollInfo(const ScrollInfo& info);</code></pre>
<h4>设置滚动条滑块位置</h4>
<ul>
<li>通过C++程序代码调用方法控制如下:</li>
</ul>
<pre><code class="language-c">void SetScrollPos(LONG nPos);</code></pre>
<h2>消息处理</h2>
<h4>WM_SCROLL_TOP</h4>
<p>当滚动条滚动到顶部时,会给所在窗口发送自定义消息WM_SCROLL_TOP。</p>
<h4>WM_SCROLL_BOTTOM</h4>
<p>当滚动条滚动到底部时,会给所在窗口发送自定义消息WM_SCROLL_BOTTOM。</p>
<h4>WM_SCROLL_POS_CHANGE</h4>
<p>当滚动条滚动时,会给所在窗口发送自定义消息WM_SCROLL_POS_CHANGE。</p>
<p>参考下面的示例代码:</p>
<pre><code class="language-cpp">void CScrollBar::SetScrollPos(LONG nThumbPos, BOOL bScrollTop, BOOL bScrollBottom)
{
const ScrollInfo& scrollInfo = GetScrollInfo();
CScrollLayout* pScrollLayout = GetScrollLayout();
if(pScrollLayout)
{
if(scrollInfo.nPos == 0 && bScrollTop)
{
pScrollLayout->PostScrollMessage(WM_SCROLL_TOP);
return;
}
else if(scrollInfo.nPos == scrollInfo.nMax && bScrollBottom)
{
pScrollLayout->PostScrollMessage(WM_SCROLL_BOTTOM);
return;
}
}
LONG nScrollPos = 0;
CRect rect = GetRect();
if(rect.Height() > rect.Width())
{
LONG nThumbLength = rect.Height() * scrollInfo.nPage / (scrollInfo.nMax + scrollInfo.nPage);
nThumbLength = max(THMUB_MIN_LENGTH, nThumbLength);
nScrollPos = scrollInfo.nMax * nThumbPos / (rect.Height() - nThumbLength);
}
else
{
LONG nThumbLength = rect.Width() * scrollInfo.nPage / (scrollInfo.nMax + scrollInfo.nPage);
nThumbLength = max(THMUB_MIN_LENGTH, nThumbLength);
nScrollPos = scrollInfo.nMax * nThumbPos / (rect.Width() - nThumbLength);
}
if(nScrollPos != scrollInfo.nPos)
{
SetScrollPos(nScrollPos);
GetOwner()->SendMessage(WM_SCROLL_POS_CHANGE, GetId(), reinterpret_cast<LPARAM>(this));
}
}</code></pre>
<h2>请看下面的示例</h2>
<h4>效果图</h4>
<p><img src="http://www.skinui.cn/doc/img/5.0/3/ScrollBar.png" alt="滚动条" /></p>
<h4>布局文件</h4>
<pre><code class="language-xml"><FlexLayout>
<TextView Width="MatchParent" Height="60" HorzAlign="Center" Text="IDS_CONTROL10_2" Font="ID_FONT_H4"/>
<Line Width="MatchParent" Height="1"/>
<RelativeLayout Width="MatchParent" Grow="1">
<RelativeLayout Id="2000" AlignParentLeft="20" AlignParentRight="20" AlignParentTop="20" AlignParentBottom="20"/>
<ScrollBar Id="2001" Height="10" AlignParentBottom="5" AlignParentLeft="20" AlignParentRight="20"/>
<ScrollBar Id="2002" Width="10" AlignParentRight="5" AlignParentTop="20" AlignParentBottom="20"/>
</RelativeLayout>
</FlexLayout></code></pre>
<h4>h文件</h4>
<pre><code class="language-cpp">#pragma once
class CDemoScrollBarLayout : public CFlexLayout
{
public:
enum
{
IDC_SCROLL_LAYOUT = 2000,
IDC_SCROLL_BAR_HORZ = 2001,
IDC_SCROLL_BAR_VERT = 2002,
};
public:
CDemoScrollBarLayout(CView* pParent);
public:
virtual void OnBuildFinish();
virtual void Draw(CDC* pDC);
virtual void SetRect(const CRect& rect);
virtual void HandleMouseWheel(LONG nStep);
virtual BOOL IsHandleMouseWheel(){ return TRUE; }
protected:
void OnScrollPosChange(LONG nId, CScrollBar* pScrollBar, BOOL& bHandle);
SKINUI_DECLARE_MESSAGE_MAP()
private:
CLayout* m_pScrollLayout;
CScrollBar* m_pScrollBarHorz;
CScrollBar* m_pScrollBarVert;
SKINUI_DECLARE_DYNCREATE(CDemoScrollBarLayout, CFlexLayout)
};</code></pre>
<h4>cpp文件</h4>
<pre><code class="language-cpp">#include <stdafx.h>
#include "DemoScrollBarLayout.h"
SKINUI_BEGIN_MESSAGE_MAP(CDemoScrollBarLayout, CFlexLayout)
ON_SKINUI_WM_SCROLL_POS_CHANGE()
SKINUI_END_MESSAGE_MAP()
CDemoScrollBarLayout::CDemoScrollBarLayout(CView* pParent)
: CFlexLayout(pParent)
, m_pScrollLayout(NULL)
, m_pScrollBarHorz(NULL)
, m_pScrollBarVert(NULL)
{
}
void CDemoScrollBarLayout::OnBuildFinish()
{
CFlexLayout::OnBuildFinish();
m_pScrollLayout = dynamic_cast<CLayout*>(GetChildById(IDC_SCROLL_LAYOUT));
m_pScrollBarHorz = dynamic_cast<CScrollBar*>(GetChildById(IDC_SCROLL_BAR_HORZ));
m_pScrollBarVert = dynamic_cast<CScrollBar*>(GetChildById(IDC_SCROLL_BAR_VERT));
}
void CDemoScrollBarLayout::Draw(CDC* pDC)
{
CFlexLayout::Draw(pDC);
ImageRes* pImageRes = SkinUI::GetImageRes(_T("TestImage.jpg"));
if(pImageRes && pImageRes->pImage && m_pScrollBarVert && m_pScrollBarHorz)
{
Graphics graphics(pDC->GetHDC());
CRect rcScroll = m_pScrollLayout->GetRect();
graphics.DrawImage(pImageRes->pImage, Rect(rcScroll.left, rcScroll.top, rcScroll.Width(), rcScroll.Height()), m_pScrollBarHorz->GetScrollInfo().nPos, m_pScrollBarVert->GetScrollInfo().nPos, rcScroll.Width(), rcScroll.Height(), UnitPixel);
}
}
void CDemoScrollBarLayout::SetRect(const CRect& rect)
{
CFlexLayout::SetRect(rect);
ImageRes* pImageRes = SkinUI::GetImageRes(_T("TestImage.jpg"));
if(pImageRes && pImageRes->pImage)
{
CRect rcScroll = m_pScrollLayout->GetRect();
m_pScrollBarHorz = dynamic_cast<CScrollBar*>(GetChildById(IDC_SCROLL_BAR_HORZ));
if(m_pScrollBarHorz)
{
ScrollInfo info;
info.nMax = pImageRes->pImage->GetWidth() - rcScroll.Width();
info.nPage = rcScroll.Width();
m_pScrollBarHorz->SetScrollInfo(info);
m_pScrollBarHorz->SetState(info.nMax > 0 ? NORMAL : HIDED);
}
m_pScrollBarVert = dynamic_cast<CScrollBar*>(GetChildById(IDC_SCROLL_BAR_VERT));
if(m_pScrollBarVert)
{
ScrollInfo info;
info.nMax = pImageRes->pImage->GetHeight() - rcScroll.Height();
info.nPage = rcScroll.Height();
m_pScrollBarVert->SetScrollInfo(info);
m_pScrollBarVert->SetState(info.nMax > 0 ? NORMAL : HIDED);
}
}
}
void CDemoScrollBarLayout::HandleMouseWheel(LONG nStep)
{
CScrollBar* pScrollBarCtrl = m_pScrollBarVert;
if(GetKeyState(VK_SHIFT) & 0x8000)
{
pScrollBarCtrl = m_pScrollBarHorz;
}
if(pScrollBarCtrl)
{
CRedrawLocker locker(this);
ScrollInfo info = pScrollBarCtrl->GetScrollInfo();
info.nPos -= nStep * SCROLL_STEP;
info.nPos = max(info.nPos, (LONG)0);
info.nPos = min(info.nPos, info.nMax);
pScrollBarCtrl->SetScrollPos(info.nPos);
}
}
void CDemoScrollBarLayout::OnScrollPosChange(LONG nId, CScrollBar* pScrollBar, BOOL& bHandle)
{
bHandle = TRUE;
Redraw();
}</code></pre>