【问题标题】:Backspace functionality in keyboard input program键盘输入程序中的退格功能
【发布时间】:2015-01-20 13:40:59
【问题描述】:

我正在学习 win32 编程,并为自己设置了一个简单的文本编辑程序作为第一个任务。

该程序主要基于此演示(在显示键盘输入部分下)

http://msdn.microsoft.com/en-us/library/windows/desktop/ms646268%28v=vs.85%29.aspx

我想修改这个程序,因为它不处理退格键。我找到了这段代码(在处理键盘输入下):

http://msdn.microsoft.com/en-us/library/windows/desktop/ms648398%28v=vs.85%29.aspx

但是以完全不同的方式进行。它似乎是基于 Petzold 的书。此代码的问题是每次调整窗口大小时都会擦除当前输入。我想要一个允许输入、退格和不擦除 WM_SIZE 上的文本的程序。

所以我想根据这个 Petzold 版本修改原始代码。

基本上我改变的只是:

    switch (wParam) 
    { 
        case 0x08:  // backspace 
        case 0x0A:  // linefeed 

switch (wParam)
{
case 0x08:  // backspace 
    if (nCurChar > 0)
    {
        ch = pchInputBuf[--nCurChar];
        hdc = GetDC(hwnd);
        GetCharWidth32(hdc, ch, ch, &nCharWidth);
        ReleaseDC(hwnd, hdc);
        nCaretPosX = max(nCaretPosX - nCharWidth, 0);
        SendMessage(hwnd, WM_KEYDOWN, VK_DELETE, 1);
    }
    break;

并添加了一个 VK_DELETE WM_KEYDOWN 案例:

case VK_DELETE:
            for (int x = nCurChar; x < dwLineLen - 1; x++)
            {
                pchInputBuf[x] = pchInputBuf[x + 1];
            }

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

            TextOut(hdc, nCaretPosX, nCaretPosY * dwCharY, &pchInputBuf[nCurChar], 1);

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

在第一次编译时,它似乎工作正常。退格会正确删除文本。但我遇到了一些不是我造成的故障。

首先,如果我输入如下内容:

在几个退格之后,插入符号和文本不会返回正确的字符长度,如图所示(部分 s 仍然可见):

这只是偶尔发生,而不是所有时候。

其次,调整窗口大小有时会导致部分文本消失,而不是全部消失。通常是在输入空格后的文本。但是我需要编译几次程序才能实现这一点。

任何关于发生了什么的提示将不胜感激。谢谢

【问题讨论】:

  • DeleteObject(SelectObject(hdc, GetStockObject(SYSTEM_FONT))); 似乎是错误的,或者至少是不必要的。调用时将什么字体选择到 DC 中,何时选择?
  • 你说得对,那是我尝试的东西留下的。删除它后,同样的问题仍然存在。谢谢
  • 你能把整个项目贴在某个地方吗?从到目前为止显示的 sn-p 中,我看不出任何其他明显错误的地方。但它被描述为间歇性的方式让我觉得这是某种资源泄漏。
  • 我在这里上传了它:pastebin.com/FDZpNg1g 感谢您的宝贵时间。

标签: c++ windows winapi keyboard


【解决方案1】:

我认为问题在于在您的 VK_DELETE 处理程序中,您没有正确地重新绘制显示。通过将光标移动到我输入的文本的中间,然后按 Delete 键,我每次都会出错。代码似乎假设只有行中的最后一个字符被删除,但情况并非总是如此。

尝试将其更改为:

            case VK_DELETE:
                    for (int x = nCurChar; x < dwLineLen - 1; x++)
                    {
                            pchInputBuf[x] = pchInputBuf[x + 1];
                    }
                    InvalidateRect(hwnd, 0, TRUE);
                    break;

这将使您的 WM_PAINT 处理程序完全重新绘制显示,至少对我来说这似乎可以正常工作(在单行上 - 只要文本换成两行,您就有其他问题)。

如果您确认这解决了问题,那么您可以坚持使用此解决方案,或者重新设计您的 VK_DELETE 处理程序以正确清除已删除的文本并重新绘制行。

【讨论】:

  • 谢谢。你是对的。我需要InvalidateRect。我发现的另一个问题是我混合了TextOutDrawText。我已将其全部更改为 DrawText 并已修复。是的,其他行暂时不起作用,但我现在正在添加该功能。谢谢
猜你喜欢
  • 2020-01-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-28
  • 2011-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多