WinAPI - проблема с добавлением текста в поле ввода - PullRequest
1 голос
/ 03 августа 2010

Я создал простое окно с многострочным элементом управления Edit:

Edit = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("EDIT"), NULL,
                    WS_CHILD | WS_VISIBLE | ES_MULTILINE,
                    20, 200, 200, 200,
                    hWnd, (HMENU)EDIT, GetModuleHandle(NULL), NULL);

Если я задаю текст с помощью сообщения WM_SETTEXT, я не получаю сообщение об ошибке, но если я использую EM_REPLACESEL, я получаю ошибку 5 (ERROR_ACCESS_DENIED):

SendMessage(GetDlgItem(hWnd, EDIT), EM_REPLACESEL, 0, (LPARAM)TEXT("\r\nSome text"));
if (GetLastError()) {
    /* Error 5 ERROR_ACCESS_DENIED */
}

Та же проблема с EM_SETSEL:

SendMessage(GetDlgItem(hWnd, EDIT), EM_SETSEL, (WPARAM)(0),(LPARAM)(-1));
SendMessage(GetDlgItem(hWnd, EDIT), EM_REPLACESEL, 0, (LPARAM)TEXT("\r\nSome text"));
if (GetLastError()) {
    /* Error 5 ERROR_ACCESS_DENIED */
}

Я заметил, что если я отправлю сообщение WM_SETFOCUS до EM_REPLACESEL, то ошибки не будет:

SendMessage(GetDlgItem(hWnd, EDIT), WM_SETFOCUS, (WPARAM)GetDlgItem(hWnd, EDIT), 0);
SendMessage(GetDlgItem(hWnd, EDIT), EM_REPLACESEL, 0, (LPARAM)TEXT("\r\nSome text"));
if (GetLastError()) {
    /* NO ERRORS */
}

Как я могу решить эту проблему?Нужно ли мне отправлять сообщение WM_SETFOCUS перед EM_REPLACESEL каждый раз, когда я хочу добавить какой-либо текст в мой блок редактирования?

Спасибо за помощь!

Ответы [ 6 ]

1 голос
/ 03 августа 2010

Сначала вы можете просто использовать EM_SETSEL, а затем выполнить EM_REPLACESEL.

Пример:

SendMessage(hwnd, EM_SETSEL, WPARAM(0), LPARAM(-1) );
SendMessage(hwnd, EM_REPLACESEL, WPARAM(TRUE), LPARAM(str) );
0 голосов
/ 13 августа 2013

Попробуйте это

wchar_t buffer[256] = _T("here I am at camp granada \r\n");
int ndx = GetWindowTextLength (hEdit);
SetFocus (hEdit);
SendMessage(hEdit, EM_SETSEL, (WPARAM)ndx, (LPARAM)ndx);
SendMessage(hEdit, EM_REPLACESEL, WPARAM(TRUE), (LPARAM)buffer );
0 голосов
/ 22 января 2011

Обратите внимание, что EM_SETSEL, EM_REPLACESEL и т. Д. Действуют на каретку; если фокус не на элементе управления, он не имеет каретки, и эти сообщения не будут работать. Либо ваш пользователь должен нажать на элемент управления, чтобы он получил фокус, либо вы должны сначала выполнить WM_SETFOCUS. К сожалению, именно так работает элемент управления, у него нет памяти для выбора после потери фокуса (и ни один не может иметь его до того, как он его получит).

0 голосов
/ 22 января 2011

Возможно, вам придется использовать SendDlgItemMessage вместо SendMessage.

0 голосов
/ 22 января 2011

К сожалению, GetLastError не документирован как поддерживаемый для EM_REPLACESEL, что означает, что вам придется разработать альтернативную стратегию для отлова сбоев. Может быть, некоторые вычисления длины текста будут работать.

Сказав это, мне было любопытно, почему возвращается ошибка отказа в доступе. Я установил точку прерывания данных по адресу, где SetLastError / GetLastError хранит код ошибки и обнаружил, что он находится глубоко внутри GDI, а не непосредственно из элемента управления редактирования. Не очень полезно, но по крайней мере интересный лакомый кусочек.

0 голосов
/ 03 августа 2010

Скорее всего, вам отказано в доступе из-за UIPI.

Поле «Правка» создано тем же приложением, которое пытается отправить сообщения?В противном случае приложение, выполняющее SendMessage, вероятно, имеет более низкий уровень UIPI, чем приложение, которому принадлежит Edit.

Если вы действительно владеете приложением, создавшим элемент управления Edit, и приложением, отправляющим сообщения, вы можете разрешить определенные сообщения, используя ChangeWindowMessageFilterEx .

ChangeWindowMessageFilterEx(hwndOfWindowReceivingMessage, EM_REPLACESEL, 
    MSGFLT_ALLOW, NULL);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...