这几天连续写了几个位图显示的小例子都出现同样的问题,
1、滚动条拖动会超出位图区域,(原本因该是图多大就只能拖到多大)
2、拖动滚动条时闪烁得厉害,
3、缩放窗口大小,当位图大于窗口时出现滚动条,但是拖动滚动条以后拖动滚动条就会出现位图以外的区域,而且再把窗口拖回到初始位置时位图的显示也错了,
附图,这是初始位置,这是拖动窗口缩放并拖动滚动条后的显示这是最后拖动窗口到初始大小后的显示,请问这是个什么情况?求详解。
这是图像显示函数:
void UCShowCamera::RefreshDsp()
{
v_UCDsp8BmpImgFile.LoadFromFile(_TEXT("..\\Debug\\1.bmp"));
if(v_UCDsp8BmpImgFile.GetImgData() == NULL) return;
CRect lv_rectClient,lv_rectImg;
GetClientRect(&lv_rectClient);
lv_rectImg = v_UCDsp8BmpImgFile.GetImgArea();
CDC * lv_pDc =  GetDC();
CPaintDC dc(this);
double lv_dbNWScale=(double)lv_rectImg.Width()/(double)lv_rectClient.Width();
double lv_dbNHScale=(double)lv_rectImg.Height()/(double)lv_rectClient.Height();
double lv_dbNScale=lv_dbNWScale>lv_dbNHScale?lv_dbNWScale:lv_dbNHScale;
int lv_NWidth=(int)(lv_rectImg.Width()/lv_dbNScale);
int lv_NHight=(int)(lv_rectImg.Height()/lv_dbNScale);
dc.FillSolidRect(lv_rectClient,RGB(128,128,128));  //填充空白区域
switch(v_UEShowCameraType)
{
case UE_SHOW_TYPE_NORMAL:
//图片小于窗口居中显示
if (lv_rectImg.Width() < lv_rectClient.Width() && lv_rectImg.Height() < lv_rectClient.Height())
{
RefreshScrollBarDsp(lv_rectImg.Width(),lv_rectImg.Height());
v_UCDsp8BmpImgFile.DisplayImg(lv_pDc,(lv_rectClient.Width() - lv_rectImg.Width()) / 2,(lv_rectClient.Height() - lv_rectImg.Height()) / 2,
lv_rectImg.Width(),lv_rectImg.Height()); }
else
{
//正常显示
RefreshScrollBarDsp(lv_rectImg.Width(),lv_rectImg.Height());
v_UCDsp8BmpImgFile.DisplayImg(lv_pDc,v_iHorzOffset,v_iVerOffset,lv_rectImg.Width(),lv_rectImg.Height()); } break;
case  UE_SHOW_TYPE_SCALE: if((lv_rectImg.Width()>lv_rectClient.Width())&&(lv_rectImg.Height()>lv_rectClient.Height()))
{

v_UCDsp8BmpImgFile.DisplayImg(lv_pDc,lv_rectClient.Width()/2-lv_NWidth/2,lv_rectClient.Height()/2-lv_NHight/2, lv_NWidth,lv_NHight);
}
else if(lv_rectImg.Width()>lv_rectClient.Width())
{

v_UCDsp8BmpImgFile.DisplayImg(lv_pDc,0,lv_rectClient.Height()/2-lv_NHight/2,lv_NWidth,lv_NHight);
}
else
{

v_UCDsp8BmpImgFile.DisplayImg(lv_pDc,lv_rectClient.Width()/2-lv_NWidth/2,0,lv_NWidth,lv_NHight);
}
break;
default:
v_UCDsp8BmpImgFile.DisplayImg(lv_pDc,v_iHorzOffset,v_iVerOffset,lv_rectImg.Width(),lv_rectImg.Height());
RefreshScrollBarDsp(lv_rectImg.Width(),lv_rectImg.Height());
break;
}
RefreshScrollBar();这是滚动条函数:
void UCShowCamera::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CDC *lv_pDC=GetDC();
CRect lv_DspImgRect,lv_ClientRect;
lv_DspImgRect=v_UCDsp8BmpImgFile.GetImgArea();
GetClientRect(&lv_ClientRect);
SCROLLINFO info;
info.cbSize = sizeof (info) ;
this->GetScrollInfo(SB_HORZ,&info);
v_iprevnPos=info.nPos;
switch(nSBCode)                             // 处理滚动信息
{
case SB_LINELEFT:                           // 向左的箭头被按下
info.nPos--;
break;   
case SB_LINERIGHT:                          // 向右的箭头被按下
info.nPos++;
break;
case SB_PAGELEFT:                           // 向左移动一页
info.nPos -= info.nPage;
break;   
case SB_PAGERIGHT:                          // 向右移动一页
info.nPos += info.nPage;
break;
case SB_THUMBTRACK:                         // 鼠标拖动
info.nPos = info.nTrackPos;
break;
default:
break;
}
if(info.nPos > info.nMax)
{
info.nPos = info.nMax;
}
else if(info.nPos < info.nMin)
{
info.nPos = info.nMin;
}
this->SetScrollPos(SB_HORZ,info.nPos);       // 更新信息
v_iHorzOffset+=(v_iprevnPos-info.nPos)*((lv_DspImgRect.Width()-lv_ClientRect.Width())/100);
ScrollWindow((v_iprevnPos-info.nPos),0,0,lv_DspImgRect);
Invalidate();
RefreshDsp();
__super::OnHScroll(nSBCode, nPos, pScrollBar);
}
void UCShowCamera::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CDC *lv_pDC=GetDC();
CRect lv_DspImgRect,lv_ClientRect;
GetClientRect(&lv_ClientRect);
lv_DspImgRect=v_UCDsp8BmpImgFile.GetImgArea();
SCROLLINFO info;
info.cbSize = sizeof (info) ;
this->GetScrollInfo(SB_VERT,&info);
v_iprevnPos=info.nPos;
switch(nSBCode)                           // 处理滚动信息
{
case SB_LINEUP:                           // 向上的箭头被按下
info.nPos--;
break;   
case SB_LINEDOWN:                         // 向下的箭头被按下
info.nPos++;
break;
case SB_PAGELEFT:                         // 向上移动一页
info.nPos -= info.nPage;
break;   
case SB_PAGERIGHT:                        // 向下移动一页
info.nPos += info.nPage;
break;
case SB_THUMBTRACK:                       // 鼠标拖动
info.nPos = info.nTrackPos;
break;
default:
break;
}
if(info.nPos > info.nMax)
{
info.nPos = info.nMax;
}
else if(info.nPos < info.nMin)
{
info.nPos = info.nMin;
}
this->SetScrollPos(SB_VERT,info.nPos);    // 更新信息
v_iVerOffset+=(v_iprevnPos-info.nPos)*((lv_DspImgRect.Height()-lv_ClientRect.Height())/100);
ScrollWindow(0,(v_iprevnPos-info.nPos),0,lv_DspImgRect);
Invalidate();
RefreshDsp();
CDialog::OnVScroll(nSBCode, nPos, pScrollBar);
}显示窗口的Onsize 函数:
void UCShowCamera::OnSize(UINT nType, int cx, int cy)
{
__super::OnSize(nType, cx, cy);
//  CRect lv_rectClirent;
//  GetClientRect(&lv_rectClirent);
//  v_iHorzOffset = lv_rectClirent.left;
//  v_iVerOffset = lv_rectClirent.top; Invalidate();
RefreshDsp();
// TODO: 在此处添加消息处理程序代码
}
 主窗口的 Onsize 函数:
void CViewTestDlg::OnSize(UINT nType, int cx, int cy)
{
CDialogEx::OnSize(nType, cx, cy);
if(v_UCShowCamera.m_hWnd)
{
v_UCShowCamera.SetWindowPos(&wndTop,0,0,cx,cy,NULL);
}
// TODO: 在此处添加消息处理程序代码
}
MFCBitmap滚动条位图偏移窗口大小

解决方案 »

  1.   

    1显然是你写的滚动条算法有问题
    2 加TRACE
    3 加LOG
    4 分析数据
    5 解决问题
    OK?
      

  2.   

    1.闪烁是你每次滚动轴移动的时候造成视图重绘动作,该动作如果之前有系统默认的清空OnErasebkg之类的动作的话就会出现楼主所说的情况。解决方法:建议关闭OnEraseBkg的自动清空功能,在OnDraw或者OnPaint流程中保证只有一次内存的读出(双缓存),把其他数据处理步骤缩小。2.你滚动轴移动的时候,映射的坐标对应大小和图片显示的位置映射关系不同。导致错乱了
      

  3.   

    获取下图片大小,然后对滚动条SetRange下应该就行了, 
      

  4.   

    OnEreasBkgnd直接返回true应该可以解决闪烁的问题
      

  5.   

    1、滚动条拖动会超出位图区域,(原本因该是图多大就只能拖到多大)。
    答:你没有设置滚动条的左右滚动的大小,应当根据图片的大小设置滚动条的左右滚动大小2、拖动滚动条时闪烁得厉害,
    答:没有用又缓冲来绘图3、缩放窗口大小,当位图大于窗口时出现滚动条,但是拖动滚动条以后拖动滚动条就会出现位图以外的区域,而且再把窗口拖回到初始位置时位图的显示也错了,
    答:缩放窗口时,应当接收WM_SIZE消息,在这消息函数设置滚动条的左右滚动的大小
      

  6.   

    不好意思,解决了, 这是方法,
    把OnHScroll和OnVScroll  里面设置的v_iVerOffset和v_iYerOffset值拿过来就行了。
      可以结贴了···麻烦各位大神了。