【问题标题】:How to append text to a TextBox?如何将文本附加到文本框?
【发布时间】:2012-09-21 20:03:56
【问题描述】:

我认为下面的代码应该是不言自明的。

#include <Windows.h>

static HWND textBoxInput;
static HWND button;
static HWND textBoxOutput;

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

int CALLBACK WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR cmdLine,int nCmdShow)
{
    HWND hMainWindow;
    WNDCLASS wc = {};
    wc.lpfnWndProc = WindowProc;
    wc.lpszClassName = "Main's window class";
    wc.hInstance = hInstance;
    RegisterClass(&wc);


    hMainWindow = CreateWindow(wc.lpszClassName,"Append text main window",WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,500,400,NULL,NULL,hInstance,NULL);

    error=GetLastError();

    if(hMainWindow == NULL) return 1;

    textBoxInput = CreateWindowEx(WS_EX_CLIENTEDGE, "Edit", NULL,WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL, 10, 10, 300, 21, hMainWindow, NULL, NULL, NULL);

    button = CreateWindowEx(WS_EX_CLIENTEDGE,"Button","Append",WS_CHILD | WS_VISIBLE | ES_CENTER, 10, 41,75,30,hMainWindow,NULL,NULL,NULL); 

    textBoxOutput = CreateWindowEx(WS_EX_CLIENTEDGE,"Edit",TEXT("->This content is untouchable and unreadable!<-"),WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_AUTOVSCROLL |  ES_MULTILINE | ES_READONLY ,10,81,500,90,hMainWindow,NULL,NULL,NULL);


    ShowWindow(hMainWindow,SW_SHOW);

    MSG msg = { };

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uMsg)
    {
        case WM_COMMAND:
        if((HWND)lParam == button)
        {               
            TCHAR* buffer = new TCHAR[150];

            GetWindowText(textBoxInput,buffer,150);

            SetWindowText(textBoxOutput,buffer);
            //AppendWindowText(textBoxOutput,buffer,150) - I haven't found such function;           
                    delete [] buffer;       
        }
        break;

        case WM_PAINT:          
            {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hwnd, &ps);
            HBRUSH pedzel;

            pedzel = CreateSolidBrush(RGB(10,250,10));

            FillRect(hdc, &ps.rcPaint, pedzel);

            EndPaint(hwnd, &ps);
            return 0;
            }
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

简而言之:这个程序创建了两个文本框和一个按钮,用于启动将内容从第一个复制到第二个的过程。 SetWindowText 函数会导致清理输出框,这显然是不希望的。

Jerry Cofinn 回答后更新

SendMessage(textBoxOutput,EM_SETSEL,-1,-1); //no difference between passing 0 or -1
SendMessage(textBoxOutput,EM_REPLACESEL,TRUE,(LPARAM)buffer);

令人惊讶的是,它预置文本。我已经阅读了the documentation 关于 EM_SETSEL 的内容,但我仍然想知道为什么它不将原始输入放在最后。

【问题讨论】:

标签: c++ c winapi textbox


【解决方案1】:

对于文本框(编辑控件),插入符号基本上是在同一位置开始和结束的“选择”。

使用 SetSel 创建一个在当前控件中的最后一个字符之后开始和结束的选择,然后使用 ReplaceSel 用新文本替换该空选择。

由于您使用的是原始 Win32 API,SetSel 将是

SendMessage(your_control, EM_SETSEL,-1, -1);

...ReplaceSel 将是:

SendMessage(your_control, EM_REPLACESEL, TRUE, string_to_add);

糟糕——正如问题后记中所述,这不能按原样工作。您需要以WM_GETTEXTLENGTH(或GetWindowTextLength)开头来获取文本的长度,然后将所选内容设置为结尾(即开头和结尾都等于您刚刚获得的长度),然后替换所选内容.抱歉——在处理类似我有一段时间没有做过的事情时,我应该知道最好不要从记忆中走出来。

【讨论】:

  • wParam=-1lParam=-1 用于EM_SETSEL 会删除当前选择,但不会将插入符号移动到当前文本的末尾。如果插入符号位于文本的中间,那么您将在中间而不是末尾插入新文本。在发送 EM_REPLACESEL 之前,您必须正确放置插入符号。
  • EM_REPLACESEL 是在 EDIT 控件中附加的正确方法。 EM_SETSEL的细节可能需要整理一下,但这是应该接受的答案。获取控件以执行附加。在应用程序中附加文本并将其全部发送回控件是很浪费的。
  • @DavidHeffernan,同意。学习更好的方法来做某事总是一个好时机。
  • 几乎是一个很好的答案。请阅读我的问题的附言。
【解决方案2】:
  1. 使用GetWindowTextLength 查找其中文本的长度。
  2. 创建具有该长度的动态字符数组 (std::vector&lt;TCHAR&gt;),加上附加文本的长度,再加上 null。
  3. 使用GetWindowText 将当前文本存储在其中。
  4. 添加附加文本(类似于_tcscat)。
  5. 使用SetWindowText 将所有内容放入文本框中。

总结:

int len = GetWindowTextLength(textbox);
std::vector<TCHAR> temp(len + lengthOfAppendedText + 1);

GetWindowText(textbox, temp.data(), temp.size());
_tcscat(temp.data(), appendedText);
SetWindowText(textbox, temp.data());

如果您不使用 C++11,请将 temp.data() 替换为 &amp;temp[0]。如果它必须与 C 兼容,则返回到 mallocfree 而不是 std::vector,但考虑到没有调整大小,这并没有太多额外的工作。

【讨论】:

  • 调整它的大小真的没有意义,因为你一开始就知道两个长度。
  • 不要使用char,使用TCHAR(或wchar_t,一旦你意识到你永远不会再以8位操作系统为目标)。
  • @MarkRansom,这是一个例子,但你是对的。我更改了它,从长远来看,如果您制作 tstring 之类的东西并添加接口(如 to_tstringttoi 等),那么从长远来看,wchar_t 的工作量要少得多,所以绝对值得使用 @987654339 @如果可以的话。
  • 另外,也不需要乘以 sizeof(TCHAR),因为向量是按元素分配的,而不是按字节分配的。
  • @MarkRansom,废话,出于某种原因,我在想malloc。我想这是我将char(大小为 1)更改为大于该大小的东西时的自然反应。
猜你喜欢
  • 2012-02-17
  • 2014-11-05
  • 2020-03-12
  • 2013-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多