20160401 第3章 鼠标和键盘(来自《MFC Windows 程序设计(第2版)》)

来源:互联网 发布:癌症晚期知乎 编辑:程序博客网 时间:2024/04/30 12:58



3.1.2 TicTac

TicTac.h

#pragma once#include <afxwin.h>#include <afxext.h>#define EX 1#define OH 2class CMyApp :public CWinApp{public:virtual BOOL InitInstance();};class CMainWindow :public CWnd{public:CMainWindow();protected:static const CRect m_rcSquares[9];//Grid coordinatesint m_nGameGrid[9];//Grid contentsint m_nNextChar;//Next character(EX or OH)int GetRectID(CPoint point);void DrawBoard(CDC *pDC);void DrawX(CDC *pDC, int nPos);void DrawO(CDC *pDC, int nPos);void ResetGame();void CheckForGameOver();int IsWinner();BOOL IsDraw();protected:virtual void PostNcDestroy();afx_msg void OnPaint();afx_msg void OnLButtonDown(UINT nFlags, CPoint point);afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);afx_msg void OnRButtonDown(UINT nFlags, CPoint point);DECLARE_MESSAGE_MAP()};

TicTac.cpp

#include "TicTac.h"CMyApp theApp;BOOL CMyApp::InitInstance(){m_pMainWnd = new CMainWindow();m_pMainWnd->ShowWindow(m_nCmdShow);m_pMainWnd->UpdateWindow();return TRUE;}BEGIN_MESSAGE_MAP(CMainWindow, CWnd)ON_WM_PAINT()ON_WM_LBUTTONDOWN()ON_WM_LBUTTONDBLCLK()ON_WM_RBUTTONDOWN()END_MESSAGE_MAP()const CRect CMainWindow::m_rcSquares[9] = {CRect(16, 16, 112, 112),CRect(128, 16, 224, 112),CRect(240, 16, 336, 112),CRect(16, 128, 112, 224),CRect(128, 128, 224, 224),CRect(240, 128, 336, 224),CRect(16, 240, 112, 336),CRect(128, 240, 224, 336),CRect(240, 240, 336, 336)};CMainWindow::CMainWindow(){m_nNextChar = EX;::ZeroMemory(m_nGameGrid, 9 * sizeof(int));//Register a WNDCLASSCString strWndClass = AfxRegisterWndClass(CS_DBLCLKS,//Class styleAfxGetApp()->LoadStandardCursor(IDC_ARROW),//Class cursor(HBRUSH)(COLOR_3DFACE + 1),//Background brushAfxGetApp()->LoadStandardIcon(IDI_WINLOGO)//Class icon);//Create a WindowCreateEx(0, strWndClass, _T("Tic-Tac-Toe"),WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX,CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,NULL, NULL);//Size the windowCRect rect(0, 0, 352, 352);CalcWindowRect(&rect);SetWindowPos(NULL, 0, 0, rect.Width(), rect.Height(),SWP_NOZORDER | SWP_NOMOVE | SWP_NOREDRAW);}void CMainWindow::PostNcDestroy(){delete this;}void CMainWindow::OnPaint(){CPaintDC dc(this);DrawBoard(&dc);}void CMainWindow::OnLButtonDown(UINT nFlags, CPoint point){//Do nothing if it's O's turn, if the click occurred outside the//tic-tac-toe grid, of if a nonempty square clicked.if (m_nNextChar != EX){return;}int nPos = GetRectID(point);if ((nPos == -1) || (m_nGameGrid[nPos] != 0)){return;}//Add an X to the GameGrid and toggle m_nNextChar.m_nGameGrid[nPos] = EX;m_nNextChar = OH;//Draw an X on the screen and  see if either player has won.CClientDC dc(this);DrawX(&dc, nPos);CheckForGameOver();}void CMainWindow::OnLButtonDblClk(UINT nFlags, CPoint point){//Reset the game if one of the thick black lines defining the game//grid is double-clicked with the left mouse button.CClientDC dc(this);if (dc.GetPixel(point) == RGB(0,0,0)){ResetGame();}}void CMainWindow::OnRButtonDown(UINT nFlags, CPoint point){//Do nothing if it's X's turn, if the click occurred outside the//tic-tac-toe grid, or if a nonempty square was clicked.if (m_nNextChar != OH){return;}int nPos = GetRectID(point);if ((nPos == -1) || (m_nGameGrid[nPos] != 0)){return;}//Add an O to the Game Grid and toggle m_nNextChar.m_nGameGrid[nPos] = OH;m_nNextChar = EX;//Draw an O on the screen and see if either player has won.CClientDC dc(this);DrawO(&dc, nPos);CheckForGameOver();}int CMainWindow::GetRectID(CPoint point){//Hit-test each of the grid's nine squares and return a rectangle ID//(0-8) if (point.x, point.y) lies inside a square.for (int i = 0; i < 9; i++){if (m_rcSquares[i].PtInRect(point)){return i;}}return -1;}void CMainWindow::DrawBoard(CDC *pDC){//Draw the lines that define the tic-tac-toe grid.CPen pen(PS_SOLID, 16, RGB(0, 0, 0));CPen *pOldPen = pDC->SelectObject(&pen);pDC->MoveTo(120, 16);pDC->LineTo(120, 336);pDC->MoveTo(232, 16);pDC->LineTo(232, 336);pDC->MoveTo(16, 120);pDC->LineTo(336, 120);pDC->MoveTo(16, 232);pDC->LineTo(336, 232);//Draw the Xs and Os.for (int i = 0; i < 9; i++){if (m_nGameGrid[i] == EX){DrawX(pDC, i);}else if (m_nGameGrid[i] == OH){DrawO(pDC, i);}}pDC->SelectObject(pOldPen);}void CMainWindow::DrawX(CDC *pDC, int nPos){CPen pen(PS_SOLID, 16, RGB(255, 0, 0));CPen *pOldPen = pDC->SelectObject(&pen);CRect rect = m_rcSquares[nPos];rect.DeflateRect(16, 16);pDC->MoveTo(rect.left, rect.top);pDC->LineTo(rect.right, rect.bottom);pDC->MoveTo(rect.left, rect.bottom);pDC->LineTo(rect.right, rect.top);pDC->SelectObject(pOldPen);}void CMainWindow::DrawO(CDC *pDC, int nPos){CPen pen(PS_SOLID, 16, RGB(0, 0, 255));CPen *pOldPen = pDC->SelectObject(&pen);pDC->SelectStockObject(NULL_BRUSH);CRect rect = m_rcSquares[nPos];rect.DeflateRect(16, 16);pDC->Ellipse(rect);pDC->SelectObject(pOldPen);}void CMainWindow::ResetGame(){m_nNextChar = EX;::ZeroMemory(m_nGameGrid, 9 * sizeof(int));Invalidate();}void CMainWindow::CheckForGameOver(){int nWinner = 0;//If the grid contains three consecutive Xs or Os, declare a winner//and start a new game.if (nWinner = IsWinner()){CString string = (nWinner == EX) ? _T("X wins!") : _T("O wins!");MessageBox(string, _T("Game over!"), MB_ICONEXCLAMATION | MB_OK);ResetGame();}//If the grid is full, declare a draw and start a new game.else if (IsDraw()){MessageBox(_T("It's a draw!"), _T("Game over!"), MB_ICONEXCLAMATION | MB_OK);ResetGame();}}int CMainWindow::IsWinner(){static int nPattern[8][3] = {0, 1, 2,3, 4, 5,6, 7, 8,0, 3, 6,1, 4, 7,2, 5, 8,0, 4, 8,2, 4, 6};for (int i = 0; i < 8; i++){if ((m_nGameGrid[nPattern[i][0]] == EX) &&(m_nGameGrid[nPattern[i][1]] == EX) && (m_nGameGrid[nPattern[i][2]] == EX)){return EX;}if ((m_nGameGrid[nPattern[i][0]] == OH) &&(m_nGameGrid[nPattern[i][1]] == OH) &&(m_nGameGrid[nPattern[i][2]] == OH)){return OH;}}return 0;}BOOL CMainWindow::IsDraw(){for (int i = 0; i < 9; i++){if (m_nGameGrid[i] == 0){return FALSE;}}return TRUE;}


3.1.5 WM_MOUSELEAVE和WM_MOUSEHOVER消息(3.1.6&3.1.7)

Test.h

#pragma once#include <afxwin.h>#include <afxext.h>class CMyApp :public CWinApp{public:virtual BOOL InitInstance();};class CMainWindow :public CWnd{public:CMainWindow();public:BOOL m_bMouseOver = FALSE;protected:afx_msg void OnPaint();afx_msg LRESULT OnNcHitTest(CPoint point);afx_msg void OnMouseMove(UINT nFlags, CPoint point);afx_msg void OnMouseLeave();afx_msg void OnMouseHover(UINT nFlags, CPoint point);afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);DECLARE_MESSAGE_MAP()};

Test.cpp

#include "Test.h"CMyApp theApp;BOOL CMyApp::InitInstance(){m_pMainWnd = new CMainWindow();m_pMainWnd->ShowWindow(m_nCmdShow);m_pMainWnd->UpdateWindow();return TRUE;}BEGIN_MESSAGE_MAP(CMainWindow,CWnd)ON_WM_PAINT()ON_WM_NCHITTEST()/*------------------------------*/ON_WM_MOUSEMOVE()ON_WM_MOUSELEAVE()ON_WM_MOUSEHOVER()/*------------------------------*/ON_WM_MOUSEWHEEL()/*------------------------------*/END_MESSAGE_MAP()CMainWindow::CMainWindow(){CString strWndClass = AfxRegisterWndClass(CS_DBLCLKS,AfxGetApp()->LoadStandardCursor(IDC_ARROW),(HBRUSH)(COLOR_WINDOW + 1),AfxGetApp()->LoadStandardIcon(IDI_WINLOGO));CreateEx(0, strWndClass, _T("Tic-Tac-Toe"),WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX,CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,NULL, NULL);CRect rect(0, 0, 352, 352);CalcWindowRect(&rect);SetWindowPos(NULL, 0, 0, rect.Width(), rect.Height(),SWP_ASYNCWINDOWPOS);}void CMainWindow::OnPaint(){}LRESULT CMainWindow::OnNcHitTest(CPoint point){LRESULT nHitTest = (LRESULT)CWnd::OnNcHitTest(point);if (nHitTest == HTCLIENT){nHitTest = HTCAPTION;}return nHitTest;}void CMainWindow::OnMouseMove(UINT nFlags, CPoint point){if (!m_bMouseOver){TRACE(_T("Mouse Enter\n"));m_bMouseOver = TRUE;TRACKMOUSEEVENT tme;tme.cbSize = sizeof(tme);tme.dwFlags = TME_HOVER | TME_LEAVE;tme.hwndTrack = m_hWnd;tme.dwHoverTime = HOVER_DEFAULT;::TrackMouseEvent(&tme);}}void CMainWindow::OnMouseLeave(){TRACE(_T("Mouse Leave\n"));m_bMouseOver = FALSE;}void CMainWindow::OnMouseHover(UINT nFlags, CPoint point){TRACE(_T("Mouse hover(x = %d, y = %d)\n"), point.x,point.y);TRACKMOUSEEVENT tme;tme.cbSize = sizeof(tme);tme.dwFlags = TME_HOVER | TME_LEAVE;tme.hwndTrack = m_hWnd;tme.dwHoverTime = HOVER_DEFAULT;::TrackMouseEvent(&tme);}BOOL CMainWindow::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt){BOOL bUp = TRUE;int nDelta = zDelta;if (zDelta < 0){bUp = FALSE;nDelta = -nDelta;}UINT nWheelScrollLines;::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0,&nWheelScrollLines, 0);if (nWheelScrollLines == WHEEL_PAGESCROLL){SendMessage(WM_VSCROLL,MAKEWPARAM(bUp ? SB_PAGEUP : SB_PAGEDOWN, 0), 0);}else{int nLines = (nDelta*nWheelScrollLines) / WHEEL_DELTA;while (nLines--){SendMessage(WM_VSCROLL,MAKEWPARAM(bUp ? SB_LINEUP : SB_LINEDOWN, 0), 0);}}return TRUE;}


3.1.8 鼠标捕获的应用(MouseCap)

MouseCap.h

#pragma once#include <afxwin.h>#include <afxext.h>class CMyApp :public CWinApp{public:virtual BOOL InitInstance();};class CMainWindow :public CFrameWnd{public:CMainWindow();protected:BOOL m_bTracking;//TRUE if rubber bandingBOOL m_bCaptureEnabled;//TRUE if capture enabledCPoint m_ptFrom;//"From" point for rubber bandingCPoint m_ptTo;//"To" point for rubber bandingvoid InvertLine(CDC *pDC, CPoint poFrom, CPoint ptTo);protected:afx_msg void OnLButtonDown(UINT nFlags, CPoint point);afx_msg void OnMouseMove(UINT nFlags, CPoint point);afx_msg void OnLButtonUp(UINT nFlags, CPoint point);afx_msg void OnNcLButtonDown(UINT nHitTest, CPoint point);DECLARE_MESSAGE_MAP()};

MouseCap.cpp

#include "MouseCap.h"CMyApp theApp;BOOL CMyApp::InitInstance(){m_pMainWnd = new CMainWindow();m_pMainWnd->ShowWindow(m_nCmdShow);m_pMainWnd->UpdateWindow();return TRUE;}BEGIN_MESSAGE_MAP(CMainWindow,CFrameWnd)ON_WM_LBUTTONDOWN()ON_WM_MOUSEMOVE()ON_WM_LBUTTONUP()ON_WM_NCLBUTTONDOWN()END_MESSAGE_MAP()CMainWindow::CMainWindow(){m_bTracking = FALSE;m_bCaptureEnabled = TRUE;//Register a WNDCLASS.CString strWndClass = AfxRegisterWndClass(0,AfxGetApp()->LoadStandardCursor(IDC_CROSS),(HBRUSH)(COLOR_WINDOW + 1),AfxGetApp()->LoadStandardIcon(IDI_WINLOGO));//Create a window.Create(strWndClass, _T("Mouse Capture Demo(Capture Enabled)"));}void CMainWindow::OnLButtonDown(UINT nFlags, CPoint point){//Record the anchor point and set tracking flag.m_ptFrom = point;m_ptTo = point;m_bTracking = TRUE;//If capture is enabled, capture the mouse.if (m_bCaptureEnabled){SetCapture();}}void CMainWindow::OnMouseMove(UINT nFlags, CPoint point){//If the mouse is moved while we're "tracking"(that is, while a //line is being rubber-banded), ensure the old rubber-band line and//draw a new one.if (m_bTracking){CClientDC dc(this);InvertLine(&dc, m_ptFrom, m_ptTo);InvertLine(&dc, m_ptFrom, point);m_ptTo = point;}}void CMainWindow::OnLButtonUp(UINT nFlags, CPoint point){//If the left mouse button is released while we're tracking, release//the mouse if it's currently captured, erase the last rubber-band//line, and draw a thick red line in its place.if (m_bTracking){m_bTracking = FALSE;if (GetCapture() == this){::ReleaseCapture();}CClientDC dc(this);InvertLine(&dc, m_ptFrom, m_ptTo);//Clear rubberCPen pen(PS_SOLID, 16, RGB(255, 0, 0));dc.SelectObject(&pen);dc.MoveTo(m_ptFrom);dc.LineTo(point);}}void CMainWindow::OnNcLButtonDown(UINT nHitTest, CPoint point){//When the window's title bar is clicked with the left mouse button,//toggle the capture flag on or off and update the window title.if (nHitTest == HTCAPTION){m_bCaptureEnabled = m_bCaptureEnabled ? FALSE : TRUE;SetWindowText(m_bCaptureEnabled ?_T("Mouse Capture Demo(Capture Enabled)"):_T("Mouse Capture Demo(Capture Disabled)"));}CWnd::OnNcLButtonDown(nHitTest, point);}void CMainWindow::InvertLine(CDC *pDC, CPoint ptFrom, CPoint ptTo){//Invert a line of pixels by drawing a line in the R2_NOT drawing mode.int nOldMode = pDC->SetROP2(R2_NOT);pDC->MoveTo(ptFrom);pDC->LineTo(ptTo);pDC->SetROP2(nOldMode);}


3.3 VISUALKB应用程序

VisualKB.h

#pragma once#define MAX_STRINGS 12#include <afxwin.h>#include <afxext.h>class CMyApp :public CWinApp{public:virtual BOOL InitInstance();};class CMainWindow :public CWnd{protected:int m_cxChar;//Average character widthint m_cyChar;//Character heightint m_cyLine;//Vertical line spacing in message boxint m_nTextPos;//Index of current character in text boxint m_nTabStops[7];//Tab stop locations for tabbed outputint m_nTextLimit;//Maximum width of text in text boxint m_nMsgPos;//Current position in m_strMessages arrayHCURSOR m_hCursorArrow;//Handle of arrow cursorHCURSOR m_hCursorIBeam;//Handle of I-Beam cursorCPoint m_ptTextOrigin;//Origin for drawing input textCPoint m_ptHeaderOrigin;//Origin for drawing header textCPoint m_ptUpperMsgOrigin;//Origin of first line in message boxCPoint m_ptLowerMsgOrigin;//Origin of last line in message boxCPoint m_ptCaretPos;//Current caret positionCRect m_rcTextBox;//Coordinates of text boxCRect m_rcTextBoxBorder;//Coordinates of text box borderCRect m_rcMsgBoxBorder;//Coordinates of message box borderCRect m_rcScroll;//Coordinates of scroll rectangleCString m_strInputText;//Input textCString m_strMessages[MAX_STRINGS];//Array of message stringspublic:CMainWindow();protected:int GetNearestPos(CPoint point);void PositionCaret(CDC *pDC = 0);void DrawInputText(CDC *pDC);void ShowMessage(LPCTSTR pszMessage, UINT nChar, UINT nRepCnt,UINT nFlags);void DrawMessageHeader(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);afx_msg void OnKillFocus(CWnd *pWnd);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()};

VisualKB.cpp

#include "VisualKB.h"CMyApp theApp;BOOL CMyApp::InitInstance(){m_pMainWnd = new CMainWindow();m_pMainWnd->ShowWindow(m_nCmdShow);m_pMainWnd->UpdateWindow();return TRUE;}BEGIN_MESSAGE_MAP(CMainWindow, CWnd)ON_WM_CREATE()ON_WM_PAINT()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;//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);//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::GetNearestPos(CPoint point){//Return 0 if(point.x, point.y) lies to the left of the text in//the text box.if (point.x <= m_ptTextOrigin.x){return 0;}//Return the string length if(point.x, point.y) lies to the right//of the text in the text box.CClientDC dc(this);int nLen = m_strInputText.GetLength();if (point.x >= (m_ptTextOrigin.x +(dc.GetTextExtent(m_strInputText, nLen)).cx)){return nLen;}//Knowing that (point.x, point.y) lies somewhere within the text//in the text box, convert the coordinates into a character index.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::PositionCaret(CDC *pDC){BOOL bRelease = FALSE;//Create a device context if pDC is NULL.if (pDC == NULL){pDC = GetDC();bRelease = TRUE;}//Position the caret just right of the character whose 0-based//index is stored in m_nTextPos.CPoint point = m_ptTextOrigin;CString string = m_strInputText.Left(m_nTextPos);point.x += (pDC->GetTextExtent(string, string.GetLength())).cx;SetCaretPos(point);//Release the device context if it was created inside this function.if (bRelease){ReleaseDC(pDC);}}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){//Formulate a message string.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);//Scroll the other message strings up and validate the scroll//rectangle to prevent OnPaint from being called.ScrollWindow(0, -m_cyLine, &m_rcScroll);ValidateRect(m_rcScroll);//Record the new message string and display it in the Window.CClientDC dc(this);dc.SetBkColor((COLORREF)::GetSysColor(COLOR_3DFACE));m_strMessages[m_nMsgPos] = string;dc.TabbedTextOut(m_ptLowerMsgOrigin.x, m_ptLowerMsgOrigin.y,m_strMessages[m_nMsgPos], m_strMessages[m_nMsgPos].GetLength(),sizeof(m_nTabStops), m_nTabStops, m_ptLowerMsgOrigin.x);//Update the array index that specifies where the next message//string will be stored.if (++m_nMsgPos == MAX_STRINGS){m_nMsgPos = 0;}}void CMainWindow::DrawMessageHeader(CDC *pDC){static CString string =_T("Message\tChar\tRep\tScan\tExt\tCon\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::DrawMessages(CDC *pDC){int nPos = m_nMsgPos;pDC->SetBkColor((COLORREF)::GetSysColor(COLOR_3DFACE));for (int i = 0; i < MAX_STRINGS; i++){pDC->TabbedTextOut(m_ptUpperMsgOrigin.x,m_ptUpperMsgOrigin.y + (m_cyLine*i),m_strMessages[nPos], m_strMessages[nPos].GetLength(),sizeof(m_nTabStops), m_nTabStops, m_ptUpperMsgOrigin.x);if (++nPos == MAX_STRINGS){nPos = 0;}}}void CMainWindow::PostNcDestroy(){delete this;}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);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_STRINGS) +(m_cyChar * 6) + 16);m_rcScroll.SetRect(m_cxChar + 16, (m_cyChar * 6) + 16,m_cxChar * 63 + 16, (m_cyLine * MAX_STRINGS) +(m_cyChar * 5) + 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_cyChar + 16;m_ptLowerMsgOrigin.y = (m_cyChar * 5) +(m_cyLine*(MAX_STRINGS - 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;//Size the Window.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::OnPaint(){CPaintDC dc(this);//Draw the rectangles surrounding the text box and the message list.dc.DrawEdge(m_rcTextBoxBorder, EDGE_SUNKEN, BF_RECT);dc.DrawEdge(m_rcMsgBoxBorder, EDGE_SUNKEN, BF_RECT);//Draw all the text that appers in the Window.DrawInputText(&dc);DrawMessageHeader(&dc);DrawMessages(&dc);}void CMainWindow::OnSetFocus(CWnd *pWnd){//Show the caret when the VisualKB Window receives the input focus.CreateSolidCaret(max(2, ::GetSystemMetrics(SM_CXBORDER)),m_cyChar);SetCaretPos(m_ptCaretPos);ShowCaret();}void CMainWindow::OnKillFocus(CWnd *pWnd){//Hide the caret when the VisualKB Window loses the input focus.HideCaret();m_ptCaretPos = GetCaretPos();::DestroyCaret();}BOOL CMainWindow::OnSetCursor(CWnd *pWnd, UINT nHItTest, UINT message){//Change the cursor to an I-Beam if it's currently over the text box,//or to an arrow if it's positioned anywhere else.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){//Move the caret if the text box is clicked with the left mouse button.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);//Move the caret when the left, right, Home, or End key is pressed.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::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::OnSysKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags){ShowMessage(_T("WM_SYSKEYUP"), nChar, nRepCnt, nFlags);CWnd::OnSysKeyUp(nChar, nRepCnt, nFlags);}void CMainWindow::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags){ShowMessage(_T("WM_CHAR"), nChar, nRepCnt, nFlags);CClientDC dc(this);//Determine which character was just input from the keyboard.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()){CString strnChar;strnChar.Format(_T("%d"), nChar);m_strInputText += strnChar;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){CString strnChar;strnChar.Format(_T("%d"), nChar);m_strInputText = strnChar;m_nTextPos = 1;}break;}//Update the contents of the text box.HideCaret();DrawInputText(&dc);PositionCaret(&dc);ShowCaret();}void CMainWindow::OnSysChar(UINT nChar, UINT nRepCnt, UINT nFlags){ShowMessage(_T("WM_SYSCHAR"), nChar, nRepCnt, nFlags);CWnd::OnSysChar(nChar, nRepCnt, nFlags);}





0 0