使用scrollbar和API ScrollWnd滚动窗口

这个问题说起来简单,做起来难。

虽然说是WTL,但我想MFC应该没有太大差别。

关键点:ScrollWindow,MoveWindow。

首先看ScrollWnd。

  1. class ScrollWnd : public CWindowImpl<ScrollWnd,CWindow>  //MFC中直接继承CWnd,WTL的精髓就是模板   
  2. {  
  3. private:  
  4.     const int LINE;  //定义移动的距离   
  5. public:  
  6.     BEGIN_MSG_MAP(ScrollWnd)  
class ScrollWnd : public CWindowImpl<ScrollWnd,CWindow>  //MFC中直接继承CWnd,WTL的精髓就是模板
{
private:
	const int LINE;  //定义移动的距离
public:
	BEGIN_MSG_MAP(ScrollWnd)
  1.         MSG_WM_VSCROLL(OnVScroll)  
  2.         MSG_WM_HSCROLL(OnHScroll)  
  3.     END_MSG_MAP()  
  4. public:  
  5.     ScrollWnd() : LINE(12) {  }  
  6.     void OnVScroll(UINT nSBCode,UINT,CScrollBar)  
  7.     {  
  8.         SCROLLINFO sif = { sizeof(SCROLLINFO),SIF_ALL };  
  9.         GetScrollInfo(SB_VERT,&sif);  
  10.   
  11.         int oldPos = sif.nPos;  
  12.         switch(nSBCode)  
  13.         {  
  14.         case SB_TOP:    sif.nPos = sif.nMin;    break;  
  15.         case SB_BOTTOM: sif.nPos = sif.nMax;    break;  
  16.         case SB_LINEUP:     sif.nPos -= LINE;   break;  
  17.         case SB_LINEDOWN:   sif.nPos += LINE;   break;  
  18.         case SB_PAGEUP:     sif.nPos -= sif.nPage;  break;  
  19.         case SB_PAGEDOWN:   sif.nPos += sif.nPage;  break;  
  20.         case SB_THUMBTRACK: sif.nPos = sif.nTrackPos;   break;  
  21.         default:    break;  
  22.         }  
  23.         if(sif.nPos > sif.nMax)  
  24.             sif.nPos = sif.nMax;  
  25.         else if(sif.nPos < sif.nMin)  
  26.             sif.nPos = sif.nMin;  
  27.         sif.fMask = SIF_POS;  
  28.         SetScrollInfo(SB_VERT,&sif);  
  29.   
  30.         GetScrollInfo(SB_VERT,&sif);  
  31.         if(sif.nPos != oldPos)  
  32.             ScrollWindow(0,oldPos - sif.nPos);  //这里是重点   
  33.     }  
  34.     void OnHScroll(UINT nSBCode,UINT,CScrollBar)  
  35.     {  
  36.         SCROLLINFO sif = { sizeof(SCROLLINFO),SIF_ALL };  
  37.         GetScrollInfo(SB_HORZ,&sif);  
  38.   
  39.         int oldPos = sif.nPos;  
  40.         switch(nSBCode)  
  41.         {  
  42.         case SB_LEFT:   sif.nPos = sif.nMin;    break;  
  43.         case SB_RIGHT:  sif.nPos = sif.nMax;    break;  
  44.         case SB_LINELEFT:   sif.nPos -= LINE;   break;  
  45.         case SB_LINERIGHT:  sif.nPos += LINE;   break;  
  46.         case SB_PAGELEFT:   sif.nPos -= sif.nPage;  break;  
  47.         case SB_PAGERIGHT:  sif.nPos += sif.nPage;  break;  
  48.         case SB_THUMBTRACK: sif.nPos = sif.nTrackPos;   break;  
  49.         default:    break;  
  50.         }  
  51.         if(sif.nPos > sif.nMax)  
  52.             sif.nPos = sif.nMax;  
  53.         else if(sif.nPos < sif.nMin)  
  54.             sif.nPos = sif.nMin;  
  55.         sif.fMask = SIF_POS;  
  56.         SetScrollInfo(SB_HORZ,&sif);  
  57.   
  58.         GetScrollInfo(SB_HORZ,&sif);  
  59.         if(sif.nPos != oldPos)  
  60.             ScrollWindow(oldPos - sif.nPos,0);  
  61.     }  
  62.     void ResetThumbHeight(HWND wndChild)  
  63.     {  
  64.         SCROLLINFO sif = { sizeof(SCROLLINFO),SIF_ALL }, sif2 = sif;  
  65.         GetScrollInfo(SB_VERT,&sif);    GetScrollInfo(SB_HORZ,&sif2);  
  66.   
  67.         CRect rc_client,rc_child;  
  68.         ::GetWindowRect(wndChild,&rc_child);  
  69.         GetClientRect(&rc_client);  
  70.   
  71.         if(rc_client.Height() >= rc_child.Height())  //不需要垂直滚动条的情况   
  72.         {  
  73.             ShowScrollBar(SB_VERT,FALSE);  
  74.             ::SetWindowPos(wndChild,NULL,0,0,rc_client.Width(),rc_child.Height(),SWP_NOMOVE);  
  75.             return;  
  76.         }  
  77.   
  78.         if(rc_client.Width() >= rc_child.Width())    //不需要水平滚动条的情况   
  79.         {  
  80.             ShowScrollBar(SB_HORZ,FALSE);  
  81.             ::SetWindowPos(wndChild,NULL,0,0,rc_client.Width(),rc_child.Height(),SWP_NOMOVE);  
  82.             return;  
  83.         }  
  84.   
  85.         sif.nPage = rc_client.Height();     sif2.nPage = rc_client.Width();  
  86.         sif.nMin = 0;                       sif2.nMin = 0;  
  87.         sif.nMax = rc_child.Height();       sif2.nMax = rc_child.Width();  
  88.         sif.nPos = 0;                       sif2.nPos = 0;  
  89.   
  90.         SetScrollInfo(SB_VERT,&sif);        SetScrollInfo(SB_HORZ,&sif2);  
  91.     }  
  92. };  
		MSG_WM_VSCROLL(OnVScroll)
		MSG_WM_HSCROLL(OnHScroll)
	END_MSG_MAP()
public:
	ScrollWnd() : LINE(12) {  }
	void OnVScroll(UINT nSBCode,UINT,CScrollBar)
	{
		SCROLLINFO sif = { sizeof(SCROLLINFO),SIF_ALL };
		GetScrollInfo(SB_VERT,&sif);

		int oldPos = sif.nPos;
		switch(nSBCode)
		{
		case SB_TOP:	sif.nPos = sif.nMin;	break;
		case SB_BOTTOM:	sif.nPos = sif.nMax;	break;
		case SB_LINEUP:		sif.nPos -= LINE;	break;
		case SB_LINEDOWN:	sif.nPos += LINE;	break;
		case SB_PAGEUP:		sif.nPos -= sif.nPage;	break;
		case SB_PAGEDOWN:	sif.nPos += sif.nPage;	break;
		case SB_THUMBTRACK:	sif.nPos = sif.nTrackPos;	break;
		default:	break;
		}
		if(sif.nPos > sif.nMax)
			sif.nPos = sif.nMax;
		else if(sif.nPos < sif.nMin)
			sif.nPos = sif.nMin;
		sif.fMask = SIF_POS;
		SetScrollInfo(SB_VERT,&sif);

		GetScrollInfo(SB_VERT,&sif);
		if(sif.nPos != oldPos)
			ScrollWindow(0,oldPos - sif.nPos);	//这里是重点
	}
	void OnHScroll(UINT nSBCode,UINT,CScrollBar)
	{
		SCROLLINFO sif = { sizeof(SCROLLINFO),SIF_ALL };
		GetScrollInfo(SB_HORZ,&sif);

		int oldPos = sif.nPos;
		switch(nSBCode)
		{
		case SB_LEFT:	sif.nPos = sif.nMin;	break;
		case SB_RIGHT:	sif.nPos = sif.nMax;	break;
		case SB_LINELEFT:	sif.nPos -= LINE;	break;
		case SB_LINERIGHT:	sif.nPos += LINE;	break;
		case SB_PAGELEFT:	sif.nPos -= sif.nPage;	break;
		case SB_PAGERIGHT:	sif.nPos += sif.nPage;	break;
		case SB_THUMBTRACK:	sif.nPos = sif.nTrackPos;	break;
		default:	break;
		}
		if(sif.nPos > sif.nMax)
			sif.nPos = sif.nMax;
		else if(sif.nPos < sif.nMin)
			sif.nPos = sif.nMin;
		sif.fMask = SIF_POS;
		SetScrollInfo(SB_HORZ,&sif);

		GetScrollInfo(SB_HORZ,&sif);
		if(sif.nPos != oldPos)
			ScrollWindow(oldPos - sif.nPos,0);
	}
	void ResetThumbHeight(HWND wndChild)
	{
		SCROLLINFO sif = { sizeof(SCROLLINFO),SIF_ALL }, sif2 = sif;
		GetScrollInfo(SB_VERT,&sif);	GetScrollInfo(SB_HORZ,&sif2);

		CRect rc_client,rc_child;
		::GetWindowRect(wndChild,&rc_child);
		GetClientRect(&rc_client);

		if(rc_client.Height() >= rc_child.Height())	//不需要垂直滚动条的情况
		{
			ShowScrollBar(SB_VERT,FALSE);
			::SetWindowPos(wndChild,NULL,0,0,rc_client.Width(),rc_child.Height(),SWP_NOMOVE);
			return;
		}

		if(rc_client.Width() >= rc_child.Width())	//不需要水平滚动条的情况
		{
			ShowScrollBar(SB_HORZ,FALSE);
			::SetWindowPos(wndChild,NULL,0,0,rc_client.Width(),rc_child.Height(),SWP_NOMOVE);
			return;
		}

		sif.nPage = rc_client.Height();		sif2.nPage = rc_client.Width();
		sif.nMin = 0;						sif2.nMin = 0;
		sif.nMax = rc_child.Height();		sif2.nMax = rc_child.Width();
		sif.nPos = 0;						sif2.nPos = 0;

		SetScrollInfo(SB_VERT,&sif);		SetScrollInfo(SB_HORZ,&sif2);
	}
};

不知道为什么,添加MOUSEWHEEL消息却一直不响应,所以此处就略去了。

下面是ImageCtrl:

 采用gdi+绘制图片。记得ERASEBKGND返回TRUE

  1. class ImageCtrl : public CWindowImpl<ImageCtrl>  
  2. {  
  3. private:  
  4.     CString m_strImagePath;  
class ImageCtrl : public CWindowImpl<ImageCtrl>
{
private:
	CString m_strImagePath;
  1. public:  
public:
  1. BEGIN_MSG_MAP(ImageCtrl)  
	BEGIN_MSG_MAP(ImageCtrl)
  1. MSG_WM_PAINT(OnPaint)  
		MSG_WM_PAINT(OnPaint)
  1. END_MSG_MAP()  
  2. ublic:  
  3. ImageCtrl()  
  4. {  
  5.     m_strImagePath = L"";  
  6. }  
  7. void DrawImage(CString str_image_path)  
  8. {  
  9.     m_strImagePath = str_image_path;  
  10.     RedrawWindow();  
  11. }  
  12. void OnPaint(CDCHandle)  
  13. {     
  14.     CPaintDC dc(m_hWnd);  
	END_MSG_MAP()
public:
	ImageCtrl()
	{
		m_strImagePath = L"";
	}
	void DrawImage(CString str_image_path)
	{
		m_strImagePath = str_image_path;
		RedrawWindow();
	}
	void OnPaint(CDCHandle)
	{	
		CPaintDC dc(m_hWnd);
  1. if(m_strImagePath.IsEmpty())  
		if(m_strImagePath.IsEmpty())
  1. return;  
			return;
  1. CRect rc;       GetClientRect(&rc);  
		CRect rc;		GetClientRect(&rc);
  1. Graphics g(dc);  
		Graphics g(dc);
  1. Image img(m_strImagePath)  
		Image img(m_strImagePath)
  1.         g.DrawImage(&img,0,0,rc.Width(),rc.Height());     
  2.     }  
  3. };  
		g.DrawImage(&img,0,0,rc.Width(),rc.Height());	
	}
};

使用方法:

ScrollWnd scrWnd;

scrWnd.Create(m_hWnd,CRect(26,72,494,319),NULL,WS_CHILD|WS_VISIBLE|WS_VSCROLL|WS_HSCROLL);

Image img(L"res/3qqq.png");

ImageCtrl icc;
icc.Create(scrWnd.m_hWnd,CRect(0,0,img.GetWidth(),img.GetHeight()),NULL,WS_CHILD|WS_VISIBLE);
icc.DrawImage(L"res/3qqq.png"););
   

scrWnd.ResetThumbHeight(icc.m_hWnd);

总结:其实,可以这么来思考。我们有一块布ImageCtrl,有很多幅画,任意选择一幅,然后调整布的大小和画一样,把画放到布上去。ScrollWnd就是一个相框,我们把布塞到相框里面,通过上下左右设定布显示区域。其实布的移动是最困扰我们的,我最初以为要自己移动,结果发现ScrollWnd的ScrollWindow已经帮我们做好了,因为ImageCtrl是他的子窗口。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值