鱼C论坛

 找回密码
 立即注册
查看: 3011|回复: 10

[技术交流] windows程序设计第六章Typer部分自己注释 和各位交流下

[复制链接]
发表于 2015-5-17 09:39:04 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
        static DWORD   dwCharSet = DEFAULT_CHARSET;
        static int     cxChar, cyChar, cxClient, cyClient, cxBuffer, cyBuffer,
                xCaret, yCaret;
        static TCHAR * pBuffer = NULL;
        HDC            hdc;
        int            x, y, i;
        PAINTSTRUCT    ps;
        TEXTMETRIC     tm;

        // 从WM_INPUTLANGCHANGE消息开始一直往下直到WM_SIZE消息结束,都没有break或者return语句。
        // 这意味着即使程序收到的是WM_INPUTLANGCHANGE消息,它也会一直执行到WM_SIZE消息。
        switch (message)
        {
        case WM_INPUTLANGCHANGE:   // 当改变键盘布局的时候就会收到这个消息
                dwCharSet = wParam;    // dwCharSet里存储的是字符集ID --> DEFAULT_CHARSET。
                                       // 给该变量重新付值的唯一可能的原因就是键盘布局变了。而且我们可以看出该消息的wParam字段里有新的字符集ID。
                // fall through
       
        case WM_CREATE:
                hdc = GetDC(hwnd);
                SelectObject(hdc, CreateFont(0, 0, 0, 0, 0, 0, 0, 0, dwCharSet, 0, 0, 0, FIXED_PITCH, NULL)); // 默认字符集 固定字宽

                GetTextMetrics(hdc, &tm);
                cxChar = tm.tmAveCharWidth;
                cyChar = tm.tmHeight;

                DeleteObject(SelectObject(hdc, GetStockObject(SYSTEM_FONT)));  // 系统默认的是宋体
                ReleaseDC(hwnd, hdc);
                // fall through               
        case WM_SIZE:
                // obtain window size in pixels

                if (message == WM_SIZE)
                {
                        cxClient = LOWORD(lParam);
                        cyClient = HIWORD(lParam);
                }
                // calculate window size in characters

                cxBuffer = max(1, cxClient / cxChar);   // cxBuffer 保存客户区中可显示字符的行数
                cyBuffer = max(1, cyClient / cyChar);   // cyBuffer 保存客户区中可显示字符的列数

                // allocate memory for buffer and clear it

                if (pBuffer != NULL)
                        free(pBuffer);

                pBuffer = (TCHAR *)malloc(cxBuffer * cyBuffer * sizeof(TCHAR)); //根据行数和列数创建 cxBuffer * cyBuffer 个动态字符数组
                                                  // 当客户区尺寸改变或者改变了键盘布局的时候程序会释放该动态数组,然后重新分配数组
                for (y = 0; y < cyBuffer; y++)    // 客户区用空格填满。我们可以把空格改成其它的什么,比如: BUFFER(x, y) = 'A';                       
                        for (x = 0; x < cxBuffer; x++)
                                BUFFER(x, y) = ' ';

                // set caret to upper left corner

                xCaret = 0;     // xCaret yCaret是光标的位置
                yCaret = 0;

                if (hwnd == GetFocus())     // 函数GetFocus返回拥有输入焦点的窗口句柄
                        SetCaretPos(xCaret * cxChar, yCaret * cyChar); // 光标移到客户区左上角

                InvalidateRect(hwnd, NULL, TRUE);  // 刷新整个客户区
                return 0;   
                // 当我们改变了键盘布局(WM_INPUTLANGCHANGE),或是创建窗口(WM_CREATE),或是改变窗口尺寸(WM_SIZE)的时候
                // 我们对窗口客户区所做的改动都会消失。窗口会变成刚开始时候的样子,也就是一大片空格。

        case WM_SETFOCUS:
                // create and show the caret

                CreateCaret(hwnd, NULL, cxChar, cyChar);       // 创建插入字符的高度和宽度
                SetCaretPos(xCaret * cxChar, yCaret * cyChar); // 设置插入字符的位置
                ShowCaret(hwnd);                               // 使插入字符可见
                return 0;

        case WM_KILLFOCUS:
                // hide and destroy the caret

                HideCaret(hwnd);
                DestroyCaret();
                return 0;

        case WM_KEYDOWN:
                switch (wParam)
                {
                case VK_HOME:
                        xCaret = 0;
                        break;

                case VK_END:
                        xCaret = cxBuffer - 1;
                        break;                       

                case VK_PRIOR:
                        yCaret = 0;
                        break;

                case VK_NEXT:
                        yCaret = cyBuffer - 1;
                        break;

                case VK_LEFT:
                        xCaret = max(xCaret - 1, 0);
                        break;

                case VK_RIGHT:
                        xCaret = min(xCaret + 1, cxBuffer - 1);
                        break;

                case VK_UP:
                        yCaret = max(yCaret - 1, 0);
                        break;

                case VK_DOWN:
                        yCaret = min(yCaret + 1, cyBuffer - 1);
                        break;

                case VK_DELETE:  // 删除掉当前位置的字符,然后后继列左移一个单位,来填补空出来的位置。最后一列补一空格
                        for (x = xCaret; x < cxBuffer - 1; x++)
                                BUFFER(x, yCaret) = BUFFER(x + 1, yCaret);

                        BUFFER(cxBuffer - 1, yCaret) = ' ';

                        HideCaret(hwnd);
                        hdc = GetDC(hwnd);

                        SelectObject(hdc, CreateFont(0, 0, 0, 0, 0, 0, 0, 0, dwCharSet, 0, 0, 0, FIXED_PITCH, NULL));

                        TextOut(hdc, xCaret * cxChar, yCaret * cyChar, &BUFFER(xCaret, yCaret), cxBuffer - xCaret);

                        DeleteObject(SelectObject(hdc, GetStockObject(SYSTEM_FONT)));
                        ReleaseDC(hwnd, hdc);
                        ShowCaret(hwnd);
                        break;
                }
                SetCaretPos(xCaret * cxChar, yCaret * cyChar);   // 改变当前光标所在位置
                return 0;

        case WM_CHAR:
                for (i = 0; i < (int)LOWORD(lParam); i++)   // LOWORD (lParam)是按键的重复次数
                {
                        switch (wParam)
                        {
                        case '\b':                    // backspace  
                                if (xCaret > 0)           // 先把插入符左移一个单位,然后就是 WM_KEYDOWS 的 VK_DELETE部分了
                                {
                                        xCaret--;
                                        SendMessage(hwnd, WM_KEYDOWN, VK_DELETE, 1);
                                }
                                break;

                        case '\t':                    // tab 按下 tab 键后插入符可能的位置是:(i*8,0)
                                do
                                {
                                        SendMessage(hwnd, WM_CHAR, ' ', 1);  // 执行WM_CHAR的default部分
                                } while (xCaret % 8 != 0);               // SendMessage()传递的是一个空格,
                                break;                       // 所以 yCaret 行 xCaret 列的内容变成了空格。然后用TextOut()把变化后的内容显示出来

                        case '\n':                    // line feed意思就是将光标位置往下挪一行,对应++yCaret
                                if (++yCaret == cyBuffer) // 但如果已经挪到最下面一行的话yCaret == cyBuffer,就挪到最上面一行
                                        yCaret = 0;
                                break;

                        case '\r':                    // carriage return               
                                xCaret = 0;               // 将光标挪到最左边

                                if (++yCaret == cyBuffer) // 同'\n'功能相同
                                        yCaret = 0;
                                break;

                        case '\x1B':                  // escape对应键盘Esc键,功能是将光标挪到最左上角,并将以前输入的字符全部擦除
                                for (y = 0; y < cyBuffer; y++)
                                        for (x = 0; x < cxBuffer; x++)
                                                BUFFER(x, y) = ' ';

                                xCaret = 0;
                                yCaret = 0;

                                InvalidateRect(hwnd, NULL, FALSE);
                                break;

                        default:                      // character codes
                                BUFFER(xCaret, yCaret) = (TCHAR)wParam;

                                HideCaret(hwnd);
                                hdc = GetDC(hwnd);

                                SelectObject(hdc, CreateFont(0, 0, 0, 0, 0, 0, 0, 0, dwCharSet, 0, 0, 0, FIXED_PITCH, NULL));

                                TextOut(hdc, xCaret * cxChar, yCaret * cyChar, &BUFFER(xCaret, yCaret), 1);

                                DeleteObject(SelectObject(hdc, GetStockObject(SYSTEM_FONT)));
                                ReleaseDC(hwnd, hdc);
                                ShowCaret(hwnd);

                                if (++xCaret == cxBuffer)      // 每改变一个字符位,插入符前进一位 如果移动到行的末尾(客户区的最右边)
                                {
                                        xCaret = 0;                // 将光标挪到行首

                                        if (++yCaret == cyBuffer)  // 如果已经挪到最下面一行的话yCaret == cyBuffer,就挪到最上面一行(0,0)位置
                                                yCaret = 0;
                                }
                                break;
                        }
                }

                SetCaretPos(xCaret * cxChar, yCaret * cyChar);
                return 0;

        case WM_PAINT:
                hdc = BeginPaint(hwnd, &ps);

                SelectObject(hdc, CreateFont(0, 0, 0, 0, 0, 0, 0, 0, dwCharSet, 0, 0, 0, FIXED_PITCH, NULL));

                for (y = 0; y < cyBuffer; y++)
                        TextOut(hdc, 0, y * cyChar, &BUFFER(0, y), cxBuffer);

                DeleteObject(SelectObject(hdc, GetStockObject(SYSTEM_FONT)));
                EndPaint(hwnd, &ps);
                return 0;

        case WM_DESTROY:
                PostQuitMessage(0);
                return 0;
        }
        return DefWindowProc(hwnd, message, wParam, lParam);
}

评分

参与人数 1荣誉 +5 鱼币 +5 贡献 +3 收起 理由
freeparty + 5 + 5 + 3 感谢楼主无私奉献!

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2015-5-17 10:42:34 | 显示全部楼层
BUFFER(xCaret, yCaret) = (TCHAR)wParam; 这句不大明白 哪位给解答下
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-5-17 11:54:37 | 显示全部楼层
BUFFER(xCaret, yCaret) = (TCHAR)wParam   
就是把 后面的wParam  类型转换成TCHAR 类型  赋值给前面 BUFFER  ,
至于BUFFER(xCaret, yCaret)   是什么 我没看懂
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-5-17 14:25:40 | 显示全部楼层
#define BUFFER(x,y) *(pBuffer + y * cxBuffer + x)

当你看到程序里有这么一句就明白是什么意思了。

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-5-17 14:50:13 | 显示全部楼层
零度C 发表于 2015-5-17 14:25
#define BUFFER(x,y) *(pBuffer + y * cxBuffer + x)

当你看到程序里有这么一句就明白是什么意思了。

灰常感谢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-5-17 14:52:53 | 显示全部楼层
小人 发表于 2015-5-17 11:54
BUFFER(xCaret, yCaret) = (TCHAR)wParam   
就是把 后面的wParam  类型转换成TCHAR 类型  赋值给前面 BUF ...

谢谢大神
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-5-22 16:29:00 | 显示全部楼层
谢谢分享!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-6-25 23:09:46 | 显示全部楼层
很長!!漫漫看
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-7-6 16:17:17 | 显示全部楼层
谢谢分享,学习中
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-7-7 17:11:31 | 显示全部楼层
楼主费心了。。。。学习
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-7-25 20:31:43 | 显示全部楼层
我来看看
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-23 09:46

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表