在状态栏实现如编辑控件的光标移动 (VC/MFC)
2009-06-26 02:44
344 查看
背景:
MFC提供给我们一个基础状态栏类:CStatusBar,当我们在状态栏内显示的内容比较长,比较多时,我们可以把某一个PANE得宽度扩大,以便可以显示长的内容,但是如果我们的每一个PANE都要显示很多内容,而且有5个以上的PANE,问题就出来了,我们很难在中间做一个平衡。
方法:
可以在状态栏的PANE上,实现一个光标移动功能, 这样当内容较长时,在这个PANE上面做光标左右移动来显示出不完整的内容。双击某个PANE显示光标, 左右键实现左右移动并显示不完整内容,状态栏失去焦点和大小调整后PANE内容恢复原状光标消失。我们继承基础类CStatusBar来完成我们的功能。
代码:
class MStatusBar : public CStatusBar{
...
int m_nActiveIndex; // current active pane's index
int m_nPreActIndex; // previous active pane's index
CString m_szActPaneText; // current active pane's text content
CString m_szPreActPaneText; // prevous active pane's text content
int m_nTextLeft; // left position of the displayed pane text
int m_nTextRight; // right position of the displayed pane text
...
};
void MStatusBar::OnLButtonDblClk(UINT nFlags, CPoint point)
{
CStatusBarCtrl& statusBar = GetStatusBarCtrl();
int i = -1;
CRect rectPane;
CPoint ptTmp(point);
//ScreenToClient(&ptTmp);
int nCount = GetCount();
while (++i < nCount)
{
statusBar.GetRect(i, rectPane);
if (rectPane.PtInRect(ptTmp) )
{
m_nActiveIndex = i;
if( m_nPreActIndex != m_nActiveIndex )
{
// restore the text of previous active pane
if( m_nPreActIndex != -1 )
{
SetText(m_nPreActIndex, m_szPreActPaneText);
SetPaneText(m_nPreActIndex, m_szPreActPaneText);
}
// update previous by now active
m_nPreActIndex = m_nActiveIndex;
m_szActPaneText = GetText(i);
if( m_szActPaneText.IsEmpty() ) m_szActPaneText = GetPaneText(i);
if( m_szActPaneText.IsEmpty() )
{
m_szPreActPaneText=m_szActPaneText;
return;
}
m_szPreActPaneText = m_szActPaneText;
// get indices of two ends of a string
m_nTextRight = m_szActPaneText.GetLength();
m_nTextLeft = 0;
// create caret
::CreateCaret(this->m_hWnd, (HBITMAP)NULL, 2, rectPane.Height());
::SetCaretPos(rectPane.left, 2);
::ShowCaret(this->m_hWnd);
SetFocus();
}
}
}
CStatusBar::OnLButtonDblClk(nFlags, point);
}
void MStatusBar::OnKillFocus( CWnd* pNewWnd )
{
RestorePanes();
}
BOOL MStatusBar::PreTranslateMessage(MSG* pMsg )
{
if( pMsg->message == WM_KEYDOWN )
{
if( pMsg->wParam == VK_LEFT )
{
SetCaretPosEx(CARET_DIR_LEFT);
return TRUE;
}
else if( pMsg->wParam == VK_RIGHT )
{
SetCaretPosEx(CARET_DIR_RIGHT);
return TRUE;
}
}
return CStatusBar::PreTranslateMessage(pMsg);
}
当然用OnChar来处理是最合理的, 但是我的项目比较大,好像之前的一些窗口把这个消息给劫走了, 我抓不住这个消息, 所以只有用PreTranslateMessage了。
#define CARET_DIR_LEFT 1
#define CARET_DIR_RIGHT 2
/******************************************************
*Params: nDirection: 1:Left, 2:Right
******************************************************/
BOOL MStatusBar::SetCaretPosEx(UINT nDirection)
{
CWindowDC wdc(this);
// Getting font dimension
TEXTMETRIC tm;
wdc.GetTextMetrics(&tm);
int cxChar = tm.tmAveCharWidth;
// Moving string infos
/*SIZE cDim;
CString strOpt_1 = GetPaneText(m_nActiveIndex);
CString strOpt_2 = GetPaneText(m_nActiveIndex);
int nLength = strOpt_1.GetLength();
::GetTextExtentPoint32(wdc.m_hDC, strOpt_1, nLength, &cDim);*/
//Getting rect of active pane
CRect rectAPane;
GetItemRect(m_nActiveIndex, &rectAPane);
int nDisLgt = rectAPane.Width()/cxChar;
CString strOpt;
POINT pt;
int xAPane = rectAPane.left;
if( m_nActiveIndex != -1 )
{
switch( nDirection )
{
case CARET_DIR_LEFT:
{
::GetCaretPos(&pt);
xAPane = pt.x - cxChar;
if( xAPane > rectAPane.left)
{
::SetCaretPos(xAPane, pt.y);
}
else
{
xAPane = rectAPane.left+1;
::SetCaretPos(xAPane, pt.y);
m_nTextLeft--;
if( m_nTextLeft < 0) m_nTextLeft = 0;
strOpt = m_szActPaneText.Mid(m_nTextLeft);
SetText(m_nActiveIndex, strOpt);
SetPaneText(m_nActiveIndex, strOpt);
}
break;
}
case CARET_DIR_RIGHT:
{
::GetCaretPos(&pt);
xAPane = pt.x + cxChar;
if( xAPane < rectAPane.right )
{
::SetCaretPos(xAPane, pt.y);
}
else
{
xAPane = rectAPane.right-1;
::SetCaretPos(xAPane, pt.y);
if( (m_nTextRight-m_nTextLeft) > nDisLgt )
m_nTextLeft++;
if( m_nTextLeft > m_nTextRight) m_nTextLeft = m_nTextRight;
strOpt = m_szActPaneText.Mid(m_nTextLeft);
SetText(m_nActiveIndex, strOpt);
SetPaneText(m_nActiveIndex, strOpt);
}
break;
}
default:
break;
}
return TRUE;
}
return FALSE;
}
void MStatusBar::RestorePanes()
{
::DestroyCaret();
if( m_nActiveIndex != -1 )
{
SetText(m_nActiveIndex, m_szActPaneText);
SetPaneText(m_nActiveIndex, m_szActPaneText);
}
if( m_nPreActIndex != -1 )
{
SetText(m_nPreActIndex, m_szPreActPaneText);
SetPaneText(m_nPreActIndex, m_szPreActPaneText);
}
m_nActiveIndex = -1;
m_nPreActIndex = -1;
m_szActPaneText = "";
m_szPreActPaneText = "";
}
void MStatusBar::OnSize( UINT nType, int cx, int cy )
{
RestorePanes();
CStatusBar::OnSize(nType, cx, cy);
}
[b]总结:
[/b]
不是很难, 关键在状态栏获取焦点, 得到字体尺寸,然后左右移动一个简单算法。相关文章推荐
- Edit Control(编辑框控件)将光标移动到行尾,实现即时显示新内容
- VC/MFC可编辑的列表控件的实现
- Edit Control(编辑框控件)将光标移动到行尾,实现即时显示新内容
- MFC 的List Control控件实现可编辑
- VC++的MFC中EditBox控件滚动条保持在底部的实现。
- [VC/MFC]使用CTabCtrl控件实现属性页功能
- VC/MFC 在ListCtl 控件中随鼠标移动提示单元格信息
- 使用CToolTipCtrl控件实现光标移动到一个控件时显示特定的提示信息
- VC实现具有回车移动焦点功能的编辑框
- [VC/MFC]使用CTabCtrl控件实现属性页功能
- VC/MFC 在ListCtl 控件中随鼠标移动提示单元格信息
- MFC设置编辑控件的光标 I型光标
- 【C语言】在VC中使用gotoxy函数实现光标的移动
- MFC 的List Control控件实现可编辑
- 【C语言】在VC中使用gotoxy函数实现光标的移动
- 在MFC中实现拖拽文件到对话框中的编辑控件中
- [VC/MFC]使用CTabCtrl控件实现属性页功能
- 基于mfc的对话框编程中,实现控件随对话框大小自动缩放以及通过滚动条实现控件移动功能
- MFC/VC中怎样实现slider滑块控件鼠标点击那里,就刚好落到点击位置
- MFC光标移动到按钮上时编辑框显示时间,并显示光标的窗口位置和客户区位置