c ++ winapi:将WM_SETTEXT之后的滚动条移动到旧位置
c++ winapi: Move scrollbar after WM_SETTEXT to old position
我有这种情况。我有两个多行编辑框。第一个不可编辑,第二个是。我收到 EN_UPDATE 消息,当它出现时,我将更新的文本从第二个 window 发送到第一个 window。所以 window 都有相同的文本。此外,如果滚动一个,则第二个也会滚动(镜像行为)。
问题是,如果我在从第二个 window 发送新文本后更新第一个 window 中的文本,那么滚动条会在开始时移动。如果我使用 SetScrollPos 而不是设置滚动条,但文本不会移动到正确的位置。我看到第一行文本,我想在更新文本之前查看位置。这怎么可能?
更新
我希望在 SendMessage 之后首先像这样 window 在用新文本替换旧文本时不将 window 移动到文本的起始位置。因为我有例如 first window 在中间滚动并且在替换文本后 firstwindow 被移动到新文本的第一行但我想留在旧位置因为我只更新第二个 window 中的文本字母,然后我将此更改发送到 firstWindow。但是我重新发送了所有文本。
SendMessage(firstWindow, WM_SETTEXT, 0, (LPARAM) buffer);
我这样创建多行文本框:
firstWindow = CreateWindowEx(
0, TEXT("EDIT"), // predefined class
NULL, // no window title
WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_BORDER |
ES_READONLY | ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL,
TEXTBOX_START_X, TEXTBOX_START_Y, TEXTBOX_WIDTH, TEXTBOX_HEIGHT,
hWnd, // parent window
(HMENU) ID_TEXTBOX, // edit control ID
(HINSTANCE) GetWindowLong(hWnd, GWL_HINSTANCE),
NULL
);
savedWndProcTablet = (WNDPROC) SetWindowLongPtr(tabletWindowUtils.textboxHwnd, GWL_WNDPROC, (LONG_PTR) &textBoxProc);
更新 2
我试试这个:
char *buffer = new char[2];
buffer = "a[=13=]";
DWORD l,r;
SendMessage(secondWindow, EM_GETSEL,(WPARAM)&l,(LPARAM)&r);
SendMessage(firstWindow, EM_REPLACESEL, 0, (LPARAM)buffer);
SendMessage(firstWindow, EM_SETSEL,l,r);
所以我在第一个 window 中有一些文本,第二个中的位置在哪里 window 我将新字母添加到这个位置。但这添加了一个字母到正确的位置,但它没有添加一个字母,但仍然添加了 aaaaaaaaaaaaaaaa。为什么会这样?
我只能使用纯c++和winapi。
谢谢。
如果您想将整个文本从第二个编辑框复制到第一个,并确保滚动位置正确镜像,您可以使用:
// get the full text of second window
int len = ::GetWindowTextLength(secondWindow) + 1;
LPTSTR txt = new TCHAR[len];
::GetWindowText(secondWindow, txt, len);
// copies it to first one
::SetWindowText(firstWindow, txt);
// get scroll position of second window
SCROLLINFO si = { sizeof(SCROLLINFO) };
::GetScrollInfo(secondWindow, SB_VERT, &si);
// set scroll bar of first window accordingly
::SetScrollInfo(firstWindow, SB_VERT | SIF_PAGE | SIF_POS | SIF_RANGE, &si, TRUE );
// get first visible line in second window
int line = ::SendMessage(secondWindow, EM_GETFIRSTVISIBLELINE, 0, 0);
// skip to same line in first window
::SendMessage(firstWindow, EM_LINESCROLL, 0, line);
delete[] txt;
你当然可以只复制一部分文字EM_REPLACESEL,但你没有说如何找到新旧部分,所以我建议全部替换。
我有这种情况。我有两个多行编辑框。第一个不可编辑,第二个是。我收到 EN_UPDATE 消息,当它出现时,我将更新的文本从第二个 window 发送到第一个 window。所以 window 都有相同的文本。此外,如果滚动一个,则第二个也会滚动(镜像行为)。
问题是,如果我在从第二个 window 发送新文本后更新第一个 window 中的文本,那么滚动条会在开始时移动。如果我使用 SetScrollPos 而不是设置滚动条,但文本不会移动到正确的位置。我看到第一行文本,我想在更新文本之前查看位置。这怎么可能?
更新
我希望在 SendMessage 之后首先像这样 window 在用新文本替换旧文本时不将 window 移动到文本的起始位置。因为我有例如 first window 在中间滚动并且在替换文本后 firstwindow 被移动到新文本的第一行但我想留在旧位置因为我只更新第二个 window 中的文本字母,然后我将此更改发送到 firstWindow。但是我重新发送了所有文本。
SendMessage(firstWindow, WM_SETTEXT, 0, (LPARAM) buffer);
我这样创建多行文本框:
firstWindow = CreateWindowEx(
0, TEXT("EDIT"), // predefined class
NULL, // no window title
WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_BORDER |
ES_READONLY | ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL,
TEXTBOX_START_X, TEXTBOX_START_Y, TEXTBOX_WIDTH, TEXTBOX_HEIGHT,
hWnd, // parent window
(HMENU) ID_TEXTBOX, // edit control ID
(HINSTANCE) GetWindowLong(hWnd, GWL_HINSTANCE),
NULL
);
savedWndProcTablet = (WNDPROC) SetWindowLongPtr(tabletWindowUtils.textboxHwnd, GWL_WNDPROC, (LONG_PTR) &textBoxProc);
更新 2
我试试这个:
char *buffer = new char[2];
buffer = "a[=13=]";
DWORD l,r;
SendMessage(secondWindow, EM_GETSEL,(WPARAM)&l,(LPARAM)&r);
SendMessage(firstWindow, EM_REPLACESEL, 0, (LPARAM)buffer);
SendMessage(firstWindow, EM_SETSEL,l,r);
所以我在第一个 window 中有一些文本,第二个中的位置在哪里 window 我将新字母添加到这个位置。但这添加了一个字母到正确的位置,但它没有添加一个字母,但仍然添加了 aaaaaaaaaaaaaaaa。为什么会这样?
我只能使用纯c++和winapi。
谢谢。
如果您想将整个文本从第二个编辑框复制到第一个,并确保滚动位置正确镜像,您可以使用:
// get the full text of second window
int len = ::GetWindowTextLength(secondWindow) + 1;
LPTSTR txt = new TCHAR[len];
::GetWindowText(secondWindow, txt, len);
// copies it to first one
::SetWindowText(firstWindow, txt);
// get scroll position of second window
SCROLLINFO si = { sizeof(SCROLLINFO) };
::GetScrollInfo(secondWindow, SB_VERT, &si);
// set scroll bar of first window accordingly
::SetScrollInfo(firstWindow, SB_VERT | SIF_PAGE | SIF_POS | SIF_RANGE, &si, TRUE );
// get first visible line in second window
int line = ::SendMessage(secondWindow, EM_GETFIRSTVISIBLELINE, 0, 0);
// skip to same line in first window
::SendMessage(firstWindow, EM_LINESCROLL, 0, line);
delete[] txt;
你当然可以只复制一部分文字EM_REPLACESEL,但你没有说如何找到新旧部分,所以我建议全部替换。