3.10 滚动条
<p>滚动条由CSkinScrollBar类来代表,继承于CSkinView,支持CSkinView的所有属性和方法。</p>
<p>通过给滚动条设置不同的布局文件,可以得到不同形态的滚动条。</p>
<p>例如:可以设置滚动条只有滚动滑块而没有滚动箭头。</p>
<ul>
<li>滚动条可以单独存在
<pre><code class="language-xml">&lt;SkinScrollBar Id=&quot;1125&quot; LayoutHeight=&quot;21&quot; AlignParentLeft=&quot;15&quot; AlignParentRight=&quot;15&quot; AlignParentVerticalCenter=&quot;0&quot; Layout=&quot;VScrollBar.xml&quot;/&gt;</code></pre></li>
<li>
<p>滚动条也可以搭配滚动视图:</p>
<pre><code class="language-xml">&lt;SkinListView AlignParentLeft=&quot;1&quot; AlignParentRight=&quot;1&quot; AlignParentTop=&quot;1&quot; AlignParentBottom=&quot;1&quot; VScrollBar=&quot;VScrollBar.xml&quot;&gt;</code></pre>
</li>
<li>一个典型的垂直滚动条布局文件如下:
<pre><code class="language-xml">&lt;SkinVerticalLayout LayoutWidth=&quot;FillParent&quot; LayoutHeight=&quot;FillParent&quot;&gt;
&lt;ScrollSlider Id=&quot;100001&quot; LayoutWidth=&quot;FillParent&quot; LayoutHeight=&quot;FillParent&quot; Image=&quot;VScrollSlider.png&quot;&gt;
&lt;ScrollThumb Id=&quot;100002&quot; Image=&quot;VScrollThumb.png&quot;/&gt;
&lt;/ScrollSlider&gt;
&lt;/SkinVerticalLayout&gt;</code></pre></li>
</ul>
<h2>1 属性和相关方法</h2>
<h4>1.1设置滚动条的滚动视图</h4>
<ul>
<li>通过C++程序代码调用方法控制如下:
<pre><code class="language-c">void SetScrollView(CSkinScrollView* pView);</code></pre></li>
</ul>
<h4>1.2设置滚动条信息</h4>
<ul>
<li>通过C++程序代码调用方法控制如下:
<pre><code class="language-c">void SetScrollInfo(const ScrollInfo&amp; info);</code></pre></li>
</ul>
<h4>1.3设置滚动条滑块位置</h4>
<ul>
<li>通过C++程序代码调用方法控制如下:
<pre><code class="language-c">void SetScrollPos(LONG nPos);</code></pre></li>
</ul>
<h2>2 消息处理</h2>
<h4>2.1 WM_HSCROLL和WM_VSCROLL消息</h4>
<p>当水平滚动条滚动时,会给所在窗口发送系统消息WM_HSCROLL。
当垂直滚动条滚动时,会给所在窗口发送系统消息WM_VSCROLL。</p>
<p>参考下面的示例代码:</p>
<pre><code class="language-cpp">void CSkinScrollBar::SetScrollPos(LONG nPos)
{
ScrollInfo scrollInfo = GetScrollInfo();
if(scrollInfo.nPos == nPos)
{
return;
}
if(m_pScrollView)
{
m_pScrollView-&gt;SetScrollPos(nPos, TRUE);
m_pScrollView-&gt;RedrawView();
}
else
{
scrollInfo.nPos = nPos;
SetScrollInfo(scrollInfo);
RedrawView();
CRect rect = GetRect();
if(rect.Height() &gt; rect.Width())
{
GetOwner()-&gt;SendMessage(WM_VSCROLL);
}
else
{
GetOwner()-&gt;SendMessage(WM_HSCROLL);
}
}
}</code></pre>
<h4>2.2 WM_HSCROLL和WM_VSCROLL消息</h4>
<p>当垂直滚动条搭配滚动视图并滚动到顶部时,会给所在窗口发送自定义消息WM_SCROLL_TOP。
当垂直滚动条搭配滚动视图并滚动到底部时,会给所在窗口发送自定义消息WM_SCROLL_BOTTOM。</p>
<pre><code class="language-cpp">void CSkinScrollView::HandleMouseWheel(LONG nStep)
{
//部分代码被注释
XXXXXXXXXXXXXX
//部分代码被注释
scrollInfo = GetScrollInfo(TRUE);
if(scrollInfo.nPos == 0)
{
GetOwner()-&gt;PostMessage(WM_SCROLL_TOP, GetId(), (LPARAM)this);
}
else if(scrollInfo.nPos == m_vertInfo.nMax)
{
GetOwner()-&gt;PostMessage(WM_SCROLL_BOTTOM, GetId(), (LPARAM)this);
}
HandleMouseLeave();
}</code></pre>
<h2>请看下面的示例</h2>
<h4>效果图</h4>
<p><img src="http://www.skinui.cn/doc/img/3/10/1.png" alt="滚动条" /></p>
<h4>布局文件</h4>
<pre><code class="language-xml">&lt;SkinDialog DefaultWidth=&quot;800&quot; DefaultHeight=&quot;600&quot; SysButton=&quot;CLOSE&quot; Icon=&quot;128&quot; Caption=&quot;IDS_CONTROL_SHOW10&quot; Animation=&quot;SizeChange&quot;&gt;
&lt;SkinScrollBar Id=&quot;100&quot; LayoutWidth=&quot;10&quot; AlignParentRight=&quot;5&quot; AlignParentTop=&quot;50&quot; AlignParentBottom=&quot;20&quot; Layout=&quot;VScrollBar.xml&quot;/&gt;
&lt;SkinScrollBar Id=&quot;200&quot; LayoutHeight=&quot;10&quot; AlignParentBottom=&quot;5&quot; AlignParentLeft=&quot;20&quot; AlignParentRight=&quot;20&quot; Layout=&quot;HScrollBar.xml&quot;/&gt;
&lt;/SkinDialog&gt;</code></pre>
<h4>h文件</h4>
<pre><code class="language-cpp">#pragma once
class CScrollBarDialog : public CSkinDialog
{
public:
enum
{
IDC_SCROLLBAR_VERT = 100,
IDC_SCROLLBAR_HORZ = 200,
};
public:
CScrollBarDialog();
public:
virtual void OnInitDialog();
virtual void DrawBackground(HDC hdc);
protected:
LRESULT OnInitDialogFinish(WPARAM wParam, LPARAM lParam);
LRESULT OnMouseWheel(UINT nFlags, short zDelta, CPoint point, BOOL&amp; bHandle);
LRESULT OnVScroll(WPARAM wParam, LPARAM lParam);
LRESULT OnHScroll(WPARAM wParam, LPARAM lParam);
SKINUI_DECLARE_MESSAGE_MAP()
private:
CSkinScrollBar* m_pScrollBarVert;
CSkinScrollBar* m_pScrollBarHorz;
};</code></pre>
<h4>cpp文件</h4>
<pre><code class="language-cpp">#include &quot;stdafx.h&quot;
#include &quot;ScrollBarDialog.h&quot;
#define SHOW_IMAGE_WIDTH 760
#define SHOW_IMAGE_HEIGHT 530
SKINUI_BEGIN_MESSAGE_MAP(CScrollBarDialog, CSkinDialog)
ON_SKINUI_WM_MOUSEWHEEL()
ON_SKINUI_MESSAGE(WM_VSCROLL, OnVScroll)
ON_SKINUI_MESSAGE(WM_HSCROLL, OnHScroll)
ON_SKINUI_MESSAGE(WM_INITDIALOG_FINISH, OnInitDialogFinish)
SKINUI_END_MESSAGE_MAP()
CScrollBarDialog::CScrollBarDialog()
: CSkinDialog(_T(&quot;ControlDialog10.xml&quot;))
, m_pScrollBarVert(NULL)
, m_pScrollBarHorz(NULL)
{
}
void CScrollBarDialog::OnInitDialog()
{
CSkinDialog::OnInitDialog();
}
void CScrollBarDialog::DrawBackground(HDC hdc)
{
CSkinDialog::DrawBackground(hdc);
Image* pImage = SkinUI::GetImage(_T(&quot;TestImage.jpg&quot;));
if(pImage &amp;&amp; m_pScrollBarVert &amp;&amp; m_pScrollBarHorz)
{
Graphics graphics(hdc);
graphics.DrawImage(pImage, Rect(32, 62, SHOW_IMAGE_WIDTH, SHOW_IMAGE_HEIGHT), m_pScrollBarHorz-&gt;GetScrollInfo().nPos, m_pScrollBarVert-&gt;GetScrollInfo().nPos, SHOW_IMAGE_WIDTH, SHOW_IMAGE_HEIGHT, UnitPixel);
}
}
LRESULT CScrollBarDialog::OnInitDialogFinish(WPARAM wParam, LPARAM lParam)
{
LRESULT lResult = CSkinDialog::OnInitDialogFinish(wParam, lParam);
Image* pImage = SkinUI::GetImage(_T(&quot;TestImage.jpg&quot;));
if(pImage)
{
CRedrawLocker locker(this);
m_pScrollBarVert = static_cast&lt;CSkinScrollBar*&gt;(GetChildById(IDC_SCROLLBAR_VERT));
if(m_pScrollBarVert)
{
ScrollInfo info;
info.nMax = pImage-&gt;GetHeight() - SHOW_IMAGE_HEIGHT;
info.nPage = SHOW_IMAGE_HEIGHT;
info.nStep = 30;
m_pScrollBarVert-&gt;SetScrollInfo(info);
}
m_pScrollBarHorz = static_cast&lt;CSkinScrollBar*&gt;(GetChildById(IDC_SCROLLBAR_HORZ));
if(m_pScrollBarHorz)
{
ScrollInfo info;
info.nMax = pImage-&gt;GetWidth() - SHOW_IMAGE_WIDTH;
info.nPage = SHOW_IMAGE_WIDTH;
info.nStep = 30;
m_pScrollBarHorz-&gt;SetScrollInfo(info);
}
}
return lResult;
}
LRESULT CScrollBarDialog::OnMouseWheel(UINT nFlags, short zDelta, CPoint point, BOOL&amp; bHandle)
{
if((zDelta &gt; 0) &amp;&amp; (zDelta &lt; WHEEL_DELTA))
{
zDelta = WHEEL_DELTA;
}
else if((zDelta &lt; 0) &amp;&amp; (zDelta &gt; -WHEEL_DELTA))
{
zDelta = -WHEEL_DELTA;
}
LONG nStep = -zDelta / WHEEL_DELTA;
CSkinScrollBar* pScrollBarCtrl = m_pScrollBarVert;
if(SkinUI::IsShiftKeyDown())
{
pScrollBarCtrl = m_pScrollBarHorz;
}
if(pScrollBarCtrl)
{
CRedrawLocker locker(this);
ScrollInfo info = pScrollBarCtrl-&gt;GetScrollInfo();
info.nPos += nStep * info.nStep;
info.nPos = max(info.nPos, (LONG)0);
info.nPos = min(info.nPos, info.nMax);
pScrollBarCtrl-&gt;SetScrollPos(info.nPos);
}
return 1L;
}
LRESULT CScrollBarDialog::OnVScroll(WPARAM wParam, LPARAM lParam)
{
RedrawView();
return 1L;
}
LRESULT CScrollBarDialog::OnHScroll(WPARAM wParam, LPARAM lParam)
{
RedrawView();
return 1L;
}</code></pre>