前两天在编程技巧与维护中看到一个解决scrollbar的npos值超过32767就不能正常显示的问题。
又在网上找了找资料现整理如下。以备后用
提问1
希望在CScroolView中连续的输出图形,并且要求能连续查看所有的该次任务的所有历史输出,但是当坐标值超出32767时,绘图便出现问题。对此MDSN的解释是
ote Under Windows 95, all screen coordinates are limited to 16 bits. Therefore, an int passed to a CDC member function must lie in the range –32768 to 32767.
我用的是VC++6,操作系统是XP,不是95啊,怎么也有这个限制!!在StdAfx.h中预定义
#ifndef WINVER
#define WINVER 0x0500
#endif
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0500
#endif
#ifndef _WIN32_WINDOWS
#define _WIN32_WINDOWS 0x0500
#endif
答:
这个问题,CScrollView确实存在。
要解决,我的办法是 生成自己的 CScrollView类,主要代码可以直接拷贝过来, 主要修改:
对滚动条的控制主要用了GetPos/SetPos. 这个函数只支持 16位POS值,要改为:
GetScrollInfo, SetScollInfo.
函数主要要修改 UpdateScrollBar 和对滚动条消息的响应。 OnScrollBy 等函数。
通过这样的修改,确实可以将滚动范围扩展到32值,但是CDC好象也不支持32位的坐标, 所以绘图的时候要自己计算偏移量,并在合适的位置绘图。
这样处理后,就能实现32位的坐标了。
提问2
消息
void OnHScroll(UINT nSBCode,UINT nPos,CScrollBar* rollBar )
{
int icruScrollpos = GetScrollPos(SB_HORZ);
siwtch{
case SB_THUMBTRACK:
SetScrollPos(SB_HORZ,nPos,TRUE);
break;
case SB_LINERIGHT:
SetScrollPos(SB_HORZ,iCurScrollPos+1,TRUE);
break;
case SB_LINELEFT:
SetScrollPos(SB_HORZ,iCurScrollPos-1,TRUE);
break;
...
}
CDialog::OnScroll(nSBCode,nPos,pScrollBar);
}
当滚动条超过32767后自动退回到起始位置,
答:
使用了OnHScroll()函数的nPos值,该值最大为32767,因此出现以上情况。
用GetScrollInfo(...)函数中的SCROLLLINFO参数中的nTrackPos也为滚动条拖动值,正常运行。
typedef struct tagSCROLLINFO {
UINT cbSize;
UINT fMask;
int nMin;
int nMax;
UINT nPage;
int nPos;
int nTrackPos;
} SCROLLINFO, *LPSCROLLINFO;
typedef SCROLLINFO CONST *LPCSCROLLINFO;
如下
void OnHScroll(UINT nSBCode,UINT nPos,CScrollBar* rollBar )
{
SCROLLINFO lpScrollInfo;
GetScrollInfo(SB_HORZ,&lpScrollInfo,SIF_ALL);
iCurScrollPos = GetScrollPos(SB_HORZ);
int icruScrollpos = GetScrollPos(SB_HORZ);
siwtch{
case SB_THUMBTRACK:
SetScrollPos(SB_HORZ,lpScrollInfo.nTrackPos,TRUE);
break;
case SB_LINERIGHT:
SetScrollPos(SB_HORZ,iCurScrollPos+1,TRUE);
break;
case SB_LINELEFT:
SetScrollPos(SB_HORZ,iCurScrollPos-1,TRUE);
break;
...
}
CDialog::OnScroll(nSBCode,nPos,pScrollBar);
}