各位大神,我最近在實作CView中ScrollBar的自動隱藏功能,即當滑鼠在View區域時(包括滾動條所在區域),顯示滾動條;當滑鼠離開View區域時(包括滾動條所在區域),自動隱藏滾動條。
我通過以下方式實作:
1、在CTextView中宣告兩個ScrollBar變數
class CTextView : public CView{
protected:
//類NSbStyle繼承自 CScrollBar類
NSbStyle m_sbH, m_sbV; //定義了兩個ScrollBar變數
virtual void OnInitialUpdate();
}
2、在CTextView的OnInitialUpdate()中創建m_sbH、m_sbV,并且初始化這兩個ScrollBar的位置
void CTextView::OnInitialUpdate()
{
SCROLLINFO info;
info.cbSize = sizeof(SCROLLINFO);
info.fMask = SIF_ALL;
info.nMin = 0;
info.nMax = 100;
info.nPage = 10;
info.nPos = 0;
info.nTrackPos = 0;
//設定兩個ScrollBar的位置
CRect rcSbH, rcSbV, rcClient;
GetClientRect(rcClient);
rcSbH.left = rcClient.left;
rcSbH.right = rcClient.right;
rcSbH.top = rcClient.bottom - H_SCROLLBAR_WIDTH;
rcSbH.bottom = rcClient.bottom;
rcSbV.left = rcClient.right - V_SCROLLBAR_WIDTH;
rcSbV.right = rcClient.right;
rcSbV.top = rcClient.top;
rcSbV.bottom = rcClient.bottom - V_SCROLLBAR_WIDTH; //VScrollBar不到底,空出空間給HScrollBar
//ScrollBar的Create的大小仍然按照既定寬度來計算
m_sbH.Create(WS_CHILD | WS_VISIBLE | SBS_HORZ, rcSbH, this, NULL);
m_sbV.Create(WS_CHILD | WS_VISIBLE | SBS_VERT, rcSbV, this, NULL);
// Set range, page and position parameters in scroll bars.
m_sbH.SetScrollInfo(&info);
m_sbV.SetScrollInfo(&info);
}
3、在CTextView的OnMouseMove()和OnMouseLeave()函式中添加訊息回應函式
//XSB_EDRAWELEM是一個列舉型別的變數,列舉Scrollbar的狀態
typedef enum tagXSB_EDRAWELEM
{
eNotDrawn = 0, // UI element is not visible. (UI Rect empty).
eNormal, // Element should be drawn in normal state.
eHover // Element should be drawn in hover state.
} XSB_EDRAWELEM;
void CTextView::OnMouseMove(UINT, CPoint point)
{
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = TME_HOVER | TME_LEAVE;
tme.dwHoverTime = 10;
tme.hwndTrack = m_hWnd;
if (!_TrackMouseEvent(&tme))
_cprintf("Track Error!\n");
XSB_EDRAWELEM temp_sbHStatus = eNotDrawn;
XSB_EDRAWELEM temp_sbVStatus = eNotDrawn;
//m_sbHStatus是CTextView中水平滾動條的顯示狀態
//系統回應了OnMouseMove(),表明滑鼠已經進入View的區域,所以顯示m_sbH
if (m_sbHStatus == eNotDrawn){
m_sbH.ShowWindow(TRUE);
}
//m_sbVStatus 是CTextView中垂直滾動條的顯示狀態
//系統回應了OnMouseMove(),表明滑鼠已經進入View的區域,所以顯示m_sbV
if (m_sbVStatus == eNotDrawn){
m_sbV.ShowWindow(TRUE);
}
CRect rt, rt_vS, rt_hS;
GetClientRect(&rt); //獲取當前View的ClientRect
m_sbV.GetWindowRect(&rt_vS); //獲取View中某個Wnd在Window的Rect
ScreenToClient(&rt_vS); //把Window的Rect轉化為母視窗的坐標
m_sbH.GetWindowRect(&rt_hS); //獲取View中某個Wnd在Window的Rect
ScreenToClient(&rt_hS); //把Window的Rect轉化為母視窗的坐標
//point在View區域,但不在水平滾動條區域
if (rt.PtInRect(point) && !rt_hS.PtInRect(point)){
temp_sbHStatus = eNormal;
}
//point在View區域,但不在垂直滾動條區域
if (rt.PtInRect(point) && !rt_vS.PtInRect(point)){
temp_sbVStatus = eNormal;
}
//point在View區域,同時也在水平滾動條區域
if (rt.PtInRect(point) && rt_hS.PtInRect(point)){
temp_sbHStatus = eHover;
}
//point在View區域,同時也在垂直滾動條區域
if (rt.PtInRect(point) && rt_vS.PtInRect(point)){
temp_sbVStatus = eHover;
}
//如果ScrollBar的狀態出現變化,則需要重畫ScrollBar;但如果狀態不變,不需要重畫
if ((temp_sbHStatus != eNotDrawn) && (temp_sbHStatus != m_sbHStatus)){
m_sbHStatus = temp_sbHStatus;
//DrawScrollBar(status)是一個根據狀態畫ScrollBar的函式
m_sbH.DrawScrollBar(m_sbHStatus);
}
//如果ScrollBar的狀態出現變化,則需要重畫ScrollBar;但如果狀態不變,不需要重畫
if ((temp_sbVStatus != eNotDrawn) && (temp_sbVStatus != m_sbVStatus)){
m_sbVStatus = temp_sbVStatus;
m_sbV.DrawScrollBar(m_sbVStatus);
}
return;
}
//滑鼠離開時,隱藏ScrollBar,并且更新各個狀態變數
void CTextView::OnMouseLeave(){
m_sbHStatus = eNotDrawn;
m_sbVStatus = eNotDrawn;
m_sbV.ShowWindow(FALSE);
m_sbH.ShowWindow(FALSE);
return;
}
4、現在的問題是:1)當水平Scrollbar顯示時,滑鼠在水平滾動條區域時,不自動回應OnMouseLeave(),而等到滑鼠離開整個View區域時再回應OnMouseLeave();2)是否有其它捕捉滑鼠的方法可以借鑒?

uj5u.com熱心網友回復:
在MFC框架中,CTextView的ClientRect自動把ScrollBar的區域剔除掉,有沒有辦法去掉這個預設設定?多謝各位大牛!轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/101163.html
標籤:界面
上一篇:mfc網路編程客戶端發送資訊的時候報錯create failed:10060
下一篇:郵件附件怎么正確解碼?
