Visual KB 《MFC Windows程序设计示例》

//filename:VisualKB.h

#define MAX_STRING 12

class CMyApp:public CWinApp{
public:
	virtual BOOL InitInstance();
};


class CMainWindow:public CWnd
{

protected:
	int m_cxChar;				//Average character width
	int m_cyChar;				//Character height
	int m_cyLine;				//Vertical line spacing in message box
	int m_nTextPos;				//Index of current character for tabbed output
	int m_nTabStops[7];			//Tab stop locations for tabbed output
	int m_nTextLimit;			//Maximum width of text in text box
	int m_nMsgPos;				//Current position in m_strMessages array

	HCURSOR m_hCursorArrow;		//Handle of arrow cursor
	HCURSOR m_hCursorIBeam;		//Handle of I-Beam cursor

	CPoint m_ptTextOrigin;		//Origin for drawing input text
	CPoint m_ptHeaderOrigin;	//Origin for drawing header text
	CPoint m_ptUpperMsgOrigin;	//Origin of first line in message box
	CPoint m_ptLowerMsgOrigin;	//Origin of first line in message box
	CPoint m_ptCaretPos;		//Current caret position

	CRect m_rcTextBox;			//Coordinates of text box
	CRect m_rcTextBoxBorder;	//Coordinates of text box border
	CRect m_rcMsgBoxBorder;		//Coordinates of message box border
	CRect m_rcScroll;			//Coordinates of scroll rectangle

	CString m_strInputText;						//Input text
	CString m_stringMessages[MAX_STRING];		//Array Of message strings

public:
	CMainWindow();
protected:
	int GetNearestPos(CPoint point);
	void PositionCaret(CDC * pDC=NULL);
	void DrawInputText(CDC * pDC);
	void ShowMessage(LPCTSTR pszMessage,UINT nChar,UINT nRepCnt,
		UINT nFlags);
	void DrawMessageHeader(CDC * pDC);
	void DrawMessage(CDC * pDC);
	void DrawMessages(CDC * pDC);
protected:
	virtual void PostNcDestroy();

	afx_msg int  OnCreate(LPCREATESTRUCT lpCreateStruct);
	afx_msg void OnPaint ();
	afx_msg void OnSetFocus(CWnd* pWnd);	//old wnd
	afx_msg void OnKillFocus(CWnd* pWnd);	//new wnd
	afx_msg BOOL OnSetCursor(CWnd *pWnd,UINT nHitTest,UINT message);
	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
	afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
	afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags);
	afx_msg void OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
	afx_msg void OnSysKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags);
	afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
	afx_msg void OnSysChar(UINT nChar, UINT nRepCnt, UINT nFlags);

	DECLARE_MESSAGE_MAP()
};
//filename:VisualKB.cpp

#include <afxwin.h>
#include "VisualKB.h"

CMyApp myApp;

//CMyApp member functions

BOOL CMyApp ::InitInstance()
{
	m_pMainWnd = new CMainWindow;
	m_pMainWnd ->ShowWindow(m_nCmdShow);
	m_pMainWnd->UpdateWindow();
	return TRUE;
}

/////////////////////////////////////////////////////////
//CMainWindow message map and number functiosn

BEGIN_MESSAGE_MAP(CMainWindow,CWnd)
	ON_WM_CREATE()
	ON_WM_PAINT()
	ON_WM_SETFOCUS()
	ON_WM_SETFOCUS()
	ON_WM_KILLFOCUS()
	ON_WM_SETCURSOR()
	ON_WM_LBUTTONDOWN()
	ON_WM_KEYDOWN()
	ON_WM_KEYUP()
	ON_WM_SYSKEYDOWN()
	ON_WM_SYSKEYUP()
	ON_WM_CHAR()
	ON_WM_SYSCHAR()
END_MESSAGE_MAP()


CMainWindow::CMainWindow()
{
	m_nTextPos = 0;
	m_nMsgPos = 0;

	m_hCursorArrow = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
	m_hCursorIBeam = AfxGetApp()->LoadStandardCursor(IDC_IBEAM);

	//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,
		CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
		NULL,NULL
		);
}


int CMainWindow::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if(CWnd::OnCreate(lpCreateStruct)==-1)
	{
		return -1;
	}
	CClientDC dc(this);
	TEXTMETRIC tm;
	dc.GetTextMetrics(&tm);
	m_cxChar = tm.tmAveCharWidth;
	m_cyChar = tm.tmHeight;
	m_cyLine = tm.tmHeight + tm.tmExternalLeading;

	m_rcTextBoxBorder.SetRect(16,16,(m_cxChar*64)+16,
		((m_cyChar*3)/2)+16
	);
	m_rcTextBox = m_rcTextBoxBorder;
	m_rcTextBox.InflateRect(-2,-2);

	m_rcMsgBoxBorder.SetRect(16, (m_cyChar*4)+16,
		(m_cxChar * 64)+16,(m_cyLine * MAX_STRING)+(m_cyChar * 6)+16
		);
	m_rcScroll.SetRect(m_cxChar + 16,(m_cyChar * 4)+16,
		(m_cxChar * 64)+16, (m_cyLine * MAX_STRING )
		+ (m_cyChar * 6) + 16
		);
	m_ptTextOrigin.x = m_cxChar + 16;
	m_ptTextOrigin.y = (m_cyChar /4 )+16;
	m_ptCaretPos = m_ptTextOrigin;
	m_nTextLimit = (m_cxChar * 63)+16;

	m_ptHeaderOrigin.x = m_cxChar + 16;
	m_ptHeaderOrigin.y = (m_cyChar * 3)+16;

	m_ptUpperMsgOrigin.x = m_cxChar + 16;
	m_ptUpperMsgOrigin.y = m_cyChar * 5 + 16;

	m_ptLowerMsgOrigin.x = m_cxChar + 16;
	m_ptLowerMsgOrigin.y = (m_cyChar * 5)
		+ m_cyLine * (MAX_STRING -1)+16;

	m_nTabStops[0] = (m_cxChar * 24) + 16;
	m_nTabStops[1] = (m_cxChar * 30) + 16;
	m_nTabStops[2] = (m_cxChar * 36) + 16;
	m_nTabStops[3] = (m_cxChar * 42) + 16;
	m_nTabStops[4] = (m_cxChar * 46) + 16;
	m_nTabStops[5] = (m_cxChar * 50) + 16;
	m_nTabStops[6] = (m_cxChar * 54) + 16;

	CRect rect(0,0,m_rcMsgBoxBorder.right + 16,
		m_rcMsgBoxBorder.bottom + 16);
	CalcWindowRect(&rect);
	SetWindowPos(NULL,0,0,rect.Width() ,rect.Height(),
		SWP_NOZORDER | SWP_NOMOVE | SWP_NOREDRAW);
	return 0;
}

void CMainWindow::PostNcDestroy()
{
	delete this;
}

void CMainWindow::OnPaint()
{
	CPaintDC dc(this);

	dc.DrawEdge(m_rcTextBoxBorder,EDGE_SUNKEN,BF_RECT);
	dc.DrawEdge(m_rcMsgBoxBorder,EDGE_SUNKEN,BF_RECT);

	DrawInputText(&dc);
	DrawMessageHeader(&dc);
	DrawMessage(&dc);
}

void CMainWindow::OnSetFocus(CWnd* pWnd){
	CreateSolidCaret(max(2,::GetSystemMetrics(SM_CXBORDER)),
		m_cyChar);
	SetCaretPos(m_ptCaretPos);
	ShowCaret();
}

void CMainWindow::OnKillFocus(CWnd* pWnd){
	HideCaret();
	m_ptCaretPos = GetCaretPos();
	::DestroyCaret();
}

BOOL CMainWindow::OnSetCursor(CWnd *pWnd,UINT nHitTest,UINT message)
{
	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)
{
	if(m_rcTextBox.PtInRect(point))
	{
		m_nTextPos = GetNearestPos(point);
		PositionCaret();
	}
}

void CMainWindow::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	ShowMessage(_T("WM_KEYDOWN"),nChar,nRepCnt,nFlags);

	switch (nChar)
	{
	case VK_LEFT:
		if(m_nTextPos !=0){
			m_nTextPos --;
			PositionCaret();
		}
		break;
	case VK_RIGHT:
		if(m_nTextPos != m_strInputText.GetLength())
		{
			m_nTextPos++;
			PositionCaret();
		}
		break;
	case VK_HOME:
		m_nTextPos = 0;
		PositionCaret();
		break;
	case VK_END:
		m_nTextPos = m_strInputText.GetLength();
		PositionCaret();
		break;
	}
}

void CMainWindow::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	ShowMessage(_T("WM_CHAR"),nChar,nRepCnt,nFlags);
	CClientDC dc(this);

	switch (nChar)
	{
	case VK_ESCAPE:
	case VK_RETURN:
		m_strInputText.Empty();
		m_nTextPos = 0;
		break;
	case VK_BACK:
		if(m_nTextPos != 0)
		{
			m_strInputText = m_strInputText.Left(m_nTextPos-1)
				+m_strInputText.Right(m_strInputText.GetLength()
				- m_nTextPos);
			m_nTextPos--;
		}
		break;
	default:
		if((nChar>=0) && (nChar <= 31))
			return;
		if(m_nTextPos == m_strInputText.GetLength())
		{
			m_strInputText += nChar;
			m_nTextPos ++;
		}
		else 
			m_strInputText.SetAt(m_nTextPos++,nChar);

		CSize size = dc.GetTextExtent(m_strInputText,
			m_strInputText.GetLength());
		if((m_ptTextOrigin.x + size.cx) > m_nTextLimit)
		{
			m_strInputText = nChar;
			m_nTextPos = 1;
		}
		break;
	}

	HideCaret();
	DrawInputText(&dc);
	PositionCaret(&dc);
	ShowCaret();
}

void CMainWindow::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	ShowMessage(_T("WM_KEYUP"),nChar,nRepCnt,nFlags);
	CWnd::OnKeyUp(nChar,nRepCnt,nFlags);
}

void CMainWindow::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	ShowMessage(_T("WM_SYSKEYDOWN"),nChar,nRepCnt,nFlags);
	CWnd::OnSysKeyDown(nChar,nRepCnt,nFlags);
}
void CMainWindow::OnSysChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	ShowMessage(_T("WM_SYSCHAR"),nChar,nRepCnt,nFlags);
	CWnd::OnSysChar(nChar,nRepCnt,nFlags);
}
void CMainWindow::OnSysKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	ShowMessage(_T("WM_SYSKEYUP"),nChar,nRepCnt,nFlags);
	CWnd::OnSysKeyUp(nChar,nRepCnt,nFlags);
}

void CMainWindow :: PositionCaret(CDC * pDC/* =NULL */)
{
	BOOL bRelease = FALSE;
	if(pDC == NULL){
		pDC = GetDC();
		bRelease = true;
	}

	CPoint point = m_ptTextOrigin;	
	CString string = m_strInputText.Left(m_nTextPos);
	point.x += (pDC ->GetTextExtent(string,string.GetLength())).cx;
	SetCaretPos(point);

	if(bRelease) ReleaseDC(pDC);
}

int CMainWindow::GetNearestPos(CPoint point)
{
	if(point.x  <= m_ptTextOrigin.x) return 0;

	CClientDC dc(this);
	int nLen = m_strInputText.GetLength();
	if(point.x >= (m_ptTextOrigin.x+dc.GetTextExtent(m_strInputText,nLen).cx)) return nLen;
	
	int i=0;
	int nPrevChar = m_ptTextOrigin.x;
	int nNextChar = m_ptTextOrigin.x;
	while(nNextChar < point.x){
		i++;
		nPrevChar = nNextChar;
		nNextChar = m_ptTextOrigin.x + 
			dc.GetTextExtent(m_strInputText.Left(i),i).cx;

	}
	return point.x - nPrevChar < nNextChar - point.x ? i-1 : i ;
}


void CMainWindow::DrawInputText(CDC * pDC)
{
	pDC ->ExtTextOut(m_ptTextOrigin.x,m_ptTextOrigin.y,
		ETO_OPAQUE,m_rcTextBox,m_strInputText,NULL);
}

void CMainWindow::ShowMessage(LPCTSTR pszMessage,UINT nChar,UINT nRepCnt, UINT nFlags)
{
	CString string;
	string.Format(_T("%s\t %u\t %u\t %u\t %u\t %u\t %u\t %u"),
		pszMessage,nChar,nRepCnt,nFlags & 0xFF,
		(nFlags >> 8 ) & 0x01,
		(nFlags >> 13) & 0x01,
		(nFlags >> 14) & 0x01,
		(nFlags >> 15) & 0x01
		);

	ScrollWindow(0,-m_cyLine,&m_rcScroll);
	ValidateRect(m_rcScroll);

	CClientDC dc(this);
	dc.SetBkColor((COLORREF)::GetSysColor(COLOR_3DFACE));
	m_stringMessages[m_nMsgPos] = string;
	dc.TabbedTextOut(m_ptLowerMsgOrigin.x,m_ptLowerMsgOrigin.y,
		m_stringMessages[m_nMsgPos],m_stringMessages[m_nMsgPos].GetLength(),
		sizeof(m_nTabStops),m_nTabStops , m_ptLowerMsgOrigin.x);

	if(++m_nMsgPos == MAX_STRING) m_nMsgPos = 0;
}

void CMainWindow ::DrawMessageHeader(CDC * pDC)
{
	static CString string = _T("Message\tChar\tRep\tScan\tExt\tCan\tPrv\tTran");
	pDC->SetBkColor((COLORREF)::GetSysColor(COLOR_3DFACE));
	pDC->TabbedTextOut(m_ptHeaderOrigin.x,m_ptHeaderOrigin.y,
		string,string.GetLength(),sizeof(m_nTabStops),m_nTabStops,m_ptHeaderOrigin.x);
}

void CMainWindow::DrawMessage(CDC * pDC)
{
	int nPos = m_nMsgPos;
	pDC->SetBkColor((COLORREF)::GetSysColor(COLOR_3DFACE));
	for(int i=0;i<MAX_STRING;i++){
		pDC->TabbedTextOut(m_ptUpperMsgOrigin.x,
			m_ptUpperMsgOrigin.y + m_cyLine*i,
			m_stringMessages[nPos],
			m_stringMessages[nPos].GetLength(),
			sizeof(m_nTabStops),m_nTabStops,m_ptUpperMsgOrigin.x);
		if(++nPos == MAX_STRING) nPos = 0;
	}
}

原文地址:https://www.cnblogs.com/wucg/p/2377175.html