在状态栏实现如编辑控件的光标移动 (VC/MFC)
来源:互联网 发布:leaflet.js api 编辑:程序博客网 时间:2024/06/01 08:52
背景:
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);
}
总结:
不是很难, 关键在状态栏获取焦点, 得到字体尺寸,然后左右移动一个简单算法。
- 在状态栏实现如编辑控件的光标移动 (VC/MFC)
- MFC设置编辑控件的光标 I型光标
- VC/MFC可编辑的列表控件的实现
- MFC 实现窗口随光标的移动而移动
- 【C语言】在VC中使用gotoxy函数实现光标的移动
- 【C语言】在VC中使用gotoxy函数实现光标的移动
- Edit Control(编辑框控件)将光标移动到行尾,实现即时显示新内容
- Edit Control(编辑框控件)将光标移动到行尾,实现即时显示新内容
- 处理嵌在状态栏的CEdit控件编辑操作
- VC实现具有回车移动焦点功能的编辑框
- VC下的光标移动函数
- VC++中控制光标的移动
- MFC在状态栏中使用进度条控件
- MFC中将CEdit设置光标当前位置在编辑框最后
- VC++的MFC中EditBox控件滚动条保持在底部的实现。
- MFC 的List Control控件实现可编辑
- MFC 的List Control控件实现可编辑
- MFC光标移动到按钮上时编辑框显示时间,并显示光标的窗口位置和客户区位置
- Web.config保存整个站点设置
- 感想
- ASDF
- ASDFSAD
- SDFASDFSAD
- 在状态栏实现如编辑控件的光标移动 (VC/MFC)
- 本本测评工具
- BlueDragon 和 MySQL 使用 UTF-8
- JAVA学习笔记《二》
- 6/28 大连理工见~
- 十大Firefox常用快捷键
- 学校实习两周做JSP课程设计
- struts国际化工具native2ascii
- php面试试题二