⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 visualkb.cpp

📁 MFC Widnows程序设计Codepart1 书挺好的
💻 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 member functions

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::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_cxChar + 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::PostNcDestroy ()
{
    delete this;
}

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 appears 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::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 ()) {
            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;
    }

	//
	// Update the contents of the text box.
	//
    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)
{
    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);
}

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::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;    
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -