WTL:如何利用滾動窗口ScrollWnd查看圖片Image

這個問題說起來簡單,做起來難。

雖然說是WTL,但我想MFC應該沒有太大差別。

關鍵點:ScrollWindow,MoveWindow。

首先看ScrollWnd。

class ScrollWnd : public CWindowImpl<ScrollWnd,CWindow>  //MFC中直接繼承CWnd,WTL的精髓就是模板
{
private:
	const int LINE;  //定義移動的距離
public:
	BEGIN_MSG_MAP(ScrollWnd)
		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

class ImageCtrl : public CWindowImpl<ImageCtrl>
{
private:
	CString m_strImagePath;
public:
	BEGIN_MSG_MAP(ImageCtrl)
		MSG_WM_PAINT(OnPaint)
	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);
		if(m_strImagePath.IsEmpty())
			return;
		CRect rc;		GetClientRect(&rc);
		Graphics g(dc);
		Image img(m_strImagePath)
		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是他的子窗口。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章