A custom list view control with custom scrollbar control, using WTL

孤人 提交于 2020-01-24 01:59:37

创建一个标准控件(CScrollBar)and 并且自己处理一些消息。

CScrollBar不支持owner_drawcustom_draw, 所以我们只能从WM_PAINT消息进行完全重绘。

明显我们需要处理WM_LBUTTONDOWN, WM_LBUTTONUP, WM_MOUSEMOVE来更新滚动条位置。

为了模仿标准scrollbar控件,我们支持所有WM_VSCROLL请求用其他消息模仿,而非WM_VSCROLL消息。

你可能注意到 标准滚动条 对于多次重复的 点击事件 只处理一次。

别忘记 捕获 鼠标在 滚动条外的 鼠标消息。

再多说一个重点,对于SBM_SETSCROLLINFO的处理。 我已经发现,当控件接收这个消息时,它看起来和标准控件一样,直到repaint重画消息被调用。 所以,我必须强制去处理这个notification.如下:

LRESULT CMyScrollbar::OnSetScrollInfo( UINT uMsg,         WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/ ){    const BOOL fRedraw = ( BOOL ) wParam;    LRESULT res = DefWindowProc( uMsg, ( WPARAM ) FALSE, lParam );    if ( fRedraw )    {        Invalidate();    }    return res;}

 为了方便使用,滚动条控件中 包含了一个 伙伴hwnd, 他直接指向一个窗口,可以发送WM_VSCROLL来改变滚动位置。

如果我们希望使用 自定义的 scrolling, 我们不得不使用LVS_NOSCROLL类型的listview控件。

结果是 控件完全停止了对滚动的处理。 该怎么办? 看起来 只有 模仿滚动消息WM_VSCROLL。

来继承它,我们决定来记住 当前第一个可见的item位置 并且 改变它 当滚动事件被触发(用m_IndexOffset来记忆滚动条位置。) 听起来很困难?  但这是最重要的一个,相对其他更多容易处理的问题。

多说两句,我为什么在OnPrePaint绘画。 正如你所知, 我们可以返回CDRF_NOTIFYITEMDRAW值为每个重绘的item接收附加的消息。

问题出在我们使用 普通listview的过程。 因为我们阻止了scolling(现在使用的是LVS_NOSCROLL style), we work on the first GetCountPerPage items.  在每次我们因为client获得WM_PAINT时, 意味着这些item需要重绘, 我们不知道哪个具体的item需要重绘: 有相对坐标和绝对指向。  

所以,我决定去杀掉两个问题通过一种方法: 不要在意item的indices, 我们需要尽可能简单的重绘,

不要忘记使用WM_MEASUREITEM消息, 如果需要来改变list control item 高度。

WM_CTLCOLORXXX消息用来检索 控件保存着的画刷(滚动条,list, 单选)。每个控件使用自己的画刷,因为他们创建有自己的区域。



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!