学习windows编程 day6 之模拟记事本

//短的函数最好定义为宏
#define BUFFER(x,y) *(y*cxBuffer+x+pBuffer)//取出一个字符

//字符消息
//WM_CHAR,WM_DEADCHAR,WM_SYSCHAR,WM_SYSDEADCHAR
//前两个是由WM_KEYDOWN/UP消息产生,后两个是由WM_SYSKEYDOWN/UP消息产生
//DEADCHAR是某些国家字母有符号,多种表现形式。有DEADCHAR会组合更多,但是我们有不到这个

//消息参数
//wParam:指定该按键的虚拟键代码
//在下面两种消息中的含义
//----WM_KEYDOWN:虚拟键代码                            key
//----WM_CHAR:ANSI或Unicode字符码(看宏定义区别)    char

//lParam
//扩展键标记(手册)

//消息排序 假设按下A键并释放,大写状态关闭
//1.WM_KEYDOWN    'A'的虚拟按键代码0x41    无论大小写都是大写的按键代码,区别在WM_CHAR处
//2.WM_CHAR        'a'的虚拟按键代码0x61
//3.WM_KEYUP    'A'的虚拟按键代码0x41

//若是持续按下‘A'键
//会循环1、2步骤,在抬起时走3


//插入符号    一个程序共享一个插入符号 获得焦点(活动窗口)    响应WM_SETFOCUS WM_KILLFOCUS
//createcaret,setcaretpos,showcaret,hidecaret.destroycaret

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    HDC hdc;
    RECT rect; PAINTSTRUCT ps;
    TEXTMETRIC tm;


    static int cxClient, cyClient;    //客户区大小
    static int cxChar, cyChar;        //字体大小
    static int cxCaret, cyCaret;    //插入符位置
    static int cxBuffer, cyBuffer;    //列数行数
    static TCHAR * pBuffer = NULL;
    

    int x, y, i;//用于循环使用

    switch (message)
    {
    case WM_CREATE:
        //获取字体大小
        hdc = GetDC(hwnd);
        //系统默认等宽字体
        SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
        GetTextMetrics(hdc, &tm);
        cxChar = tm.tmAveCharWidth;
        cyChar = tm.tmHeight + tm.tmExternalLeading;
        
        ReleaseDC(hwnd, hdc);
        break;
    case WM_SIZE:
        //获取屏幕大小
        cxClient = LOWORD(lParam);
        cyClient = HIWORD(lParam);
        //获取行数和列数
        cxBuffer = (int)cxClient / cxChar;
        cyBuffer = (int)cyClient / cyChar;
        cxBuffer = max(1, cxBuffer);
        cyBuffer = max(1, cyBuffer);

        //设置字符集指针的大小
        if (pBuffer!=NULL)
        {
            free(pBuffer);
        }

        pBuffer = (TCHAR *)malloc(cxBuffer*cyBuffer*sizeof(TCHAR));

        //初始化这个空间
        for (y = 0; y < cyBuffer; y++)
        {
            for (x = 0; x < cxBuffer; x++)
            {
                BUFFER(x,y) = ' ';
            }
        }

        //设置光标位置,左上角
        cxCaret = 0; 
        cyCaret = 0;

        if (hwnd==GetFocus())
        {
            SetCaretPos(cxCaret*cxChar, cyCaret*cyChar);
            //设为0,0处,先不需要显示
        }
        InvalidateRect(hwnd, NULL, TRUE);
        break;
    case WM_SETFOCUS:
        CreateCaret(hwnd, NULL, cxChar, cyChar);
        SetCaretPos(cxCaret*cxChar, cyCaret*cyChar);//左上角
        ShowCaret(hwnd);
        break;
    case WM_KILLFOCUS:
        HideCaret(hwnd);
        DestroyCaret();
        break;
    case WM_KEYDOWN:
        switch (wParam)
        {
        case VK_DOWN:
            cyCaret += 1;
            break;
        case VK_UP:
            cyCaret -= 1;
            break;
        case VK_LEFT:
            cxCaret -= 1;
            break;
        case VK_RIGHT:
            cxCaret += 1;
            break;
        case VK_DELETE:
            for (x = cxCaret; x < cxBuffer - 1;x++)
            {
                BUFFER(x, cyCaret) = BUFFER(x + 1, cyCaret);    
            }
            BUFFER(cxBuffer - 1, cyCaret) = ' ';
            HideCaret(hwnd);
            hdc = GetDC(hwnd);
            TextOut(hdc, 0, cyCaret*cyChar, &BUFFER(0, cyCaret), cxBuffer);//重绘这一行
            ReleaseDC(hwnd, hdc);
            ShowCaret(hwnd);
        default:
            break;
        }
        cxCaret = max(0, cxCaret);
        cyCaret = max(0, cyCaret);
        cxCaret = min(cxCaret, cxBuffer - 1);
        cyCaret = min(cyCaret, cyBuffer - 1);

        SetCaretPos(cxCaret*cxChar, cyCaret*cyChar);
        break;
    case WM_CHAR:
        for (i = 0; i < (int)LOWORD(lParam);i++)//用户按键过快时
        {
            switch (wParam)
            {
            case '':
                if (cxCaret>0)
                {
                    cxCaret--;
                    SendMessage(hwnd, WM_KEYDOWN, VK_DELETE, 1);
                }
                break;
            default:
                BUFFER(cxCaret, cyCaret) = (TCHAR)wParam;
                hdc = GetDC(hwnd);
                //先隐藏光标
                HideCaret(hwnd);


                TextOut(hdc, cxCaret*cxChar, cyCaret*cyChar, &BUFFER(cxCaret, cyCaret), 1);
                if (++cxCaret == cxBuffer)
                {
                    cxCaret = 0;
                    if (++cyCaret == cyBuffer)
                    {
                        cyCaret = 0;
                    }
                }

                //显示光标
                ShowCaret(hwnd);
                ReleaseDC(hwnd, hdc);
            }
        }
        break;
    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);
        GetClientRect(hwnd, &rect);

        for (y = 0; y < cyBuffer;y++)
        {
            TextOut(hdc, 0, y*cyChar, &pBuffer[y*cxBuffer], cxBuffer);
        }

        EndPaint(hwnd, &ps);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }


    return DefWindowProc(hwnd, message, wParam, lParam);
}
原文地址:https://www.cnblogs.com/ssyfj/p/8520394.html