📄 visualkb.cpp
字号:
#include <afxwin.h>
#include "VisualKB.h"
CMyApp myApp;
/////////////////////////////////////////////////////////////////////////
// CMainWindow message map and member functions
BEGIN_MESSAGE_MAP (CMainWindow, CWnd)
ON_WM_CREATE ()
ON_WM_PAINT ()
ON_WM_SIZE ()
ON_WM_DESTROY( )
ON_WM_SETFOCUS ()
ON_WM_KILLFOCUS ()
ON_WM_SETCURSOR ()
ON_WM_LBUTTONDOWN ()
ON_WM_MOUSEMOVE ()
ON_WM_KEYDOWN ()
ON_WM_KEYUP ()
ON_WM_CHAR ()
ON_COMMAND(ID_FILE_EXIT, OnFileExit)
ON_COMMAND(ID_EDIT_COPY,OnEditCopy)
ON_COMMAND(ID_EDIT_PASTE,OnEditPaste)
ON_COMMAND(ID_EDIT_DELETE,OnEditDelete)
ON_COMMAND(ID_EDIT_CUT,OnEditCut)
ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdateEditPaste)
ON_UPDATE_COMMAND_UI(ID_EDIT_DELETE, OnUpdateEditDelete)
ON_UPDATE_COMMAND_UI(ID_EDIT_COPY, OnUpdateEditCopy)
ON_UPDATE_COMMAND_UI(ID_EDIT_CUT, OnUpdateEditCut)
END_MESSAGE_MAP ()
/////////////////////////////////////////////////////////////////////////
// CMyApp member functions
BOOL CMyApp::InitInstance ()
{
m_pMainWnd = new CMainWindow;
m_pMainWnd->ShowWindow (m_nCmdShow);
m_pMainWnd->UpdateWindow ();
return TRUE;
}
CMainWindow::CMainWindow ()
{
// Load the arrow cursor and the I-beam cursor and save their handles.
//
m_hCursorArrow = AfxGetApp ()->LoadStandardCursor (IDC_ARROW);
m_hCursorIBeam = AfxGetApp ()->LoadStandardCursor (IDC_IBEAM);//Standard text-insertion cursor
//
// Register a WNDCLASS.
//
CString strWndClass = AfxRegisterWndClass (
0,
NULL,
(HBRUSH)(COLOR_3DFACE+1),
AfxGetApp ()->LoadStandardIcon (IDI_WINLOGO)
);
//
// Create a window.
//
CreateEx (0, strWndClass, _T ("Visual Keyboard"),
WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX | WS_THICKFRAME ,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL,NULL);
CMenu menu;
menu.LoadMenu(IDR_MAINFRAME);
SetMenu(&menu);
menu.Detach();
}
int CMainWindow::OnCreate (LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate (lpCreateStruct) == -1)
return -1;
//
// Initialize member variables whose values are dependent upon screen metrics.
//
CClientDC dc (this);
font.CreatePointFont(240, "Courier New");
dc.SelectObject(&font);
TEXTMETRIC tm;
//使用属性设备描述表接收当前字体的计量单位信息。
dc.GetTextMetrics (&tm);//Retrieves the metrics for the current font using the attribute device context
m_cxChar = tm.tmAveCharWidth;
m_cyChar = tm.tmHeight;
m_cyLine = tm.tmHeight + tm.tmExternalLeading;
m_nLineCount = 1;
m_nCurrentRow = 1;
m_nCurrentCol = 0;
// b_CaretHide=false;
b_Selected=false;
return 0;
}
void CMainWindow::PostNcDestroy ()
{
delete this;
}
void CMainWindow::OnSize( UINT nType, int cx, int cy )
{
CClientDC dc(this);
dc.SelectObject(&font);
GetClientRect(&m_rcTextBoxBorder);
m_rcTextBox = m_rcTextBoxBorder;
m_rcTextBox.InflateRect (-2, -2);//inflates CRect by moving its sides away from its center. m_rcTextBox(18,18,462,38)
m_ptTextOrigin.x = m_rcTextBox.left + max(2,::GetSystemMetrics(SM_CXBORDER));
m_ptTextOrigin.y = m_rcTextBox.top + m_cyChar / 9;
m_ptCaretPos = m_ptTextOrigin; //插入符位置
m_nLineLimit =m_rcTextBox.Width() - m_cxChar;//一行最大距离
m_EditBox.SetRect(0,0,0,0);
// m_EditBox.SetRect(m_ptTextOrigin.x,m_ptTextOrigin.y,m_ptTextOrigin.x,m_cyLine);
Adjust(m_strInputText);
dc.ExtTextOut( m_ptTextOrigin.x, m_ptTextOrigin.y, ETO_OPAQUE , m_rcTextBox, "",NULL );
dc.DrawText( (char*)m_strInputText, &m_rcTextBox, DT_LEFT | DT_WORDBREAK );
}
void CMainWindow::OnPaint ()
{
CPaintDC dc (this);
dc.SelectObject(&font);
dc.DrawEdge (m_rcTextBoxBorder, EDGE_SUNKEN, BF_RECT );//BF_LEFT
dc.SetBkColor ((COLORREF)RGB(255,255,255));
dc.ExtTextOut( m_ptTextOrigin.x, m_ptTextOrigin.y, ETO_OPAQUE , m_rcTextBox, "",NULL );
Adjust(m_strInputText);
dc.DrawText( (char*)m_strInputText, &m_rcTextBox, DT_LEFT | DT_WORDBREAK );
}
//使用插入符的窗口应该在接收到输入焦点时创建插入符
void CMainWindow::OnSetFocus (CWnd* pWnd)//先于OnPaint调用
{
//
// Show the caret when the VisualKB window receives the input focus.
//这个函数为系统插字符创建一个实心矩形,并声明对插字符的所有权。指定了插字符的宽度,高度
// GetSystemMetrics(SM_CXBORDER)值为1
int i= ::GetSystemMetrics (SM_CXBORDER);
CreateSolidCaret (max (2, ::GetSystemMetrics (SM_CXBORDER)), m_cyChar);//用20或m_cxChar调式
SetCaretPos (m_ptCaretPos);//这个函数设置插字符的位置。
ShowCaret ();//这个函数在屏幕上当前插字符位置显示插字符。一旦被显示,则插字符就开始自动闪烁。
}
//在失去输入焦点时销毁插入符
void CMainWindow::OnKillFocus (CWnd* pWnd)
{
//
// Hide the caret when the VisualKB window loses the input focus.
//
HideCaret ();
//Retrieves the client coordinates of the caret’s current position and returns them as a CPoint.
m_ptCaretPos = GetCaretPos ();
//The DestroyCaret function destroys the caret's current shape, frees the caret from the window, and removes the caret from the screen.
::DestroyCaret ();
}
BOOL CMainWindow::OnSetCursor (CWnd* pWnd, UINT nHitTest, UINT message)
{
//在文本窗口光标变为I形 ,在其它地方变为箭头形
if (nHitTest == HTCLIENT) {
DWORD dwPos = ::GetMessagePos ();
CPoint point (LOWORD (dwPos), HIWORD (dwPos));
ScreenToClient (&point);
::SetCursor (m_rcTextBox.PtInRect (point) ?
m_hCursorIBeam : m_hCursorArrow);
return true;
}
return CWnd::OnSetCursor (pWnd, nHitTest, message);
}
void CMainWindow::OnLButtonDown (UINT nFlags, CPoint point)
{
HideCaret( );
if(b_Selected){
b_Selected=false;
m_EditBox.SetRect(0,0,0,0);
CClientDC dc(this);
dc.SelectObject(&font);
dc.SetBkColor ((COLORREF)RGB(255,255,255));
dc.SetTextColor((COLORREF)RGB(0,0,0));
dc.ExtTextOut( m_ptTextOrigin.x, m_ptTextOrigin.y, ETO_OPAQUE , m_rcTextBox, "",NULL );
dc.DrawText( (char*)m_strInputText, &m_rcTextBox, DT_LEFT | DT_WORDBREAK );
}
if (m_rcTextBox.PtInRect (point)) {
GetPositionFromPoint(point);//根据点point确定当前位置
m_nPrevRow = m_nCurrentRow;
m_nPrevCol = m_nCurrentCol;
CPoint point1;
point1= GetPointFromPosition();
m_EditBox.left = point1.x;
SetCaretPos(point1);
}
ShowCaret ();
}
void CMainWindow::OnMouseMove( UINT nFlags, CPoint point )//???
{
if (nFlags == MK_LBUTTON ){
m_ptCaretPos = GetCaretPos();
HideCaret ();
GetPositionFromPoint(point);
CPoint point1;
point1 = GetPointFromPosition();
if( m_nCurrentCol > m_nPrevCol)
{
b_Selected=true;
m_EditBox.right = point1.x;
m_EditBox.top = m_ptTextOrigin.y + (m_nCurrentRow - 1) * m_cyChar;
m_EditBox.bottom = m_EditBox.top + m_cyChar;
cstring str;
int nBeginPos;
if(m_nCurrentRow == m_nPrevRow)//鼠标点击在同一行
{
if(m_nLineCount == 1)//只有一行
str = m_strInputText.SubString(m_nPrevCol,m_nCurrentCol - m_nPrevCol);
else{
nBeginPos = m_strInputText.Find(m_nCurrentRow - 1,'\n');
str = m_strInputText.SubString(nBeginPos + m_nPrevCol,m_nCurrentCol - m_nPrevCol);
}
CClientDC dc(this);
dc.SelectObject(&font);
dc.SetBkColor ((COLORREF)RGB(0,0,0));
dc.SetTextColor((COLORREF)RGB(255,255,255));
dc.DrawText( (char*)str, &m_EditBox, DT_LEFT );
}
}
SetCaretPos(GetPointFromPosition());
ShowCaret ();
}
}
void CMainWindow::OnKeyDown (UINT nChar, UINT nRepCnt, UINT nFlags)
{
// Move the caret when the left, right, Home, or End key is pressed.
//
CClientDC dc(this);
dc.SelectObject(&font);
switch (nChar) {
case VK_LEFT:
if(m_nCurrentRow == 1){// in the first row
if(m_nCurrentCol > 0)
m_nCurrentCol--;
else
m_nCurrentRow = 1;
}
else{
if (m_nCurrentCol > 0)
m_nCurrentCol--;
else{
m_nCurrentRow--;
if(m_nCurrentRow == 1)
m_nCurrentCol = m_strInputText.Find(m_nCurrentRow,'\n') - 1;
else
m_nCurrentCol = m_strInputText.Find(m_nCurrentRow,'\n') - m_strInputText.Find(m_nCurrentRow - 1,'\n') - 1;
}
}
SetCaretPos (GetPointFromPosition());
break;
case VK_RIGHT:
int nBeginPos,nEndPos;
if(m_nCurrentRow == m_nLineCount){//in the last row
if(m_nLineCount == 1)
nBeginPos = 0;
else
nBeginPos = m_strInputText.Find(m_nCurrentRow - 1,'\n');
cstring str=m_strInputText.SubString(nBeginPos,m_strInputText.Length()-nBeginPos);
if(m_nCurrentCol < str.Length()){
m_nCurrentCol++;
SetCaretPos (GetPointFromPosition()); //再根据行、列修正点
}
}
else{//不在最后一行
if(m_nCurrentRow == 1)//在第一行
{
nBeginPos = 0;
nEndPos = m_strInputText.Find(m_nCurrentRow ,'\n');
}
else {
nBeginPos = m_strInputText.Find(m_nCurrentRow - 1,'\n');
nEndPos = m_strInputText.Find(m_nCurrentRow ,'\n');
}
cstring str=m_strInputText.SubString(nBeginPos,nEndPos - nBeginPos -1);
if(m_nCurrentCol < str.Length())
m_nCurrentCol++;
else{
m_nCurrentRow++;
m_nCurrentCol = 0;
}
SetCaretPos (GetPointFromPosition());
}
break;
case VK_DELETE:
if(m_nLineCount == 1){
if (m_nCurrentCol < m_strInputText.Length())
m_strInputText.Delete(m_nCurrentCol);
}
else{//不止一行
int nBeginPos = 0;
if(m_nCurrentRow > 1){//不在第一行
nBeginPos= m_strInputText.Find(m_nCurrentRow - 1,'\n');
m_strInputText.Delete( nBeginPos + m_nCurrentCol + 1);
}
else{
m_strInputText.Delete( m_nCurrentCol);
m_nCurrentCol = 0;
}
// m_nCurrentCol = 0;
// m_nCurrentRow++;
// m_strInputText.Delete(m_strInputText.Find(m_nCurrentRow - 1,'\n') + m_nCurrentCol);
}
HideCaret ();
dc.ExtTextOut( m_ptTextOrigin.x, m_ptTextOrigin.y, ETO_OPAQUE , m_rcTextBox, "",NULL );
Adjust(m_strInputText);
dc.DrawText( (char*)m_strInputText, &m_rcTextBox, DT_LEFT | DT_WORDBREAK );
SetCaretPos (GetPointFromPosition());
ShowCaret ();
break;
case VK_DOWN:
if(m_nCurrentRow < m_nLineCount){
CPoint point=GetPointFromPosition();//从当前行、列得到点
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -