c++ - EM_SETSEL 交换参数

标签 c++ winapi

我使用 EM_SETSEL 消息在编辑控件中选择文本。我需要从末尾到中间选择一些文本,以便插入符号位置在文本的中间。 MSDN documentation陈述如下:

The start value can be greater than the end value. The lower of the two values specifies the character position of the first character in the selection. The higher value specifies the position of the first character beyond the selection.

The start value is the anchor point of the selection, and the end value is the active end. If the user uses the SHIFT key to adjust the size of the selection, the active end can move but the anchor point remains the same.

但似乎较小的值(value)总是成为 anchor ,例如我无法实现所需的行为。

代码示例(其中“parent”是 CWnd*):

TRACE("EM_SETSEL(%d, %d)\n", pos1, pos2);
parent->SendMessage(EM_SETSEL, pos1, pos2);
parent->SendMessage(EM_GETSEL, (WPARAM)&pos1, (LPARAM)&pos2);
TRACE("EM_GETSEL(%d, %d)\n", pos1, pos2);

产生输出:

EM_SETSEL(5, 1)
EM_GETSEL(1, 5)

是否有另一种方法来获得所需的选择?

最佳答案

关于 EM_GETSEL/EM_SETSEL:

  • EM_GETSEL 检索左/右位置
  • EM_SETSEL 设置 anchor /事件位置

EM_SETSEL 使用 anchor /事件位置,让您可以轻松地将插入符号放在所选内容的左侧/右侧,所以我不确定为什么在其他答案中使用了 kludge。

EM_GETSEL 是笨拙的窗口消息,需要一些技巧。此 kludge 暂时将选择更改为 0 个字符,以检索事件位置,但是,当我使用它时,我没有看到任何可见的变化。

检索 anchor /事件位置:

  • 使用 EM_GETSEL 检索左/右位置
  • 使用 EM_SETSEL 暂时将选择设置为 0 个字符,将插入符号留在事件位置
  • 使用 EM_GETSEL 检索事件位置
  • 使用 EM_SETSEL 恢复原来的选择

设置选择的一些示例 AutoHotkey 代码:

q:: ;Notepad - set active position (caret) at right
PostMessage, 0xB1, 5, 10, Edit1, A ;EM_SETSEL := 0xB1
return

w:: ;Notepad - set active position (caret) at left
PostMessage, 0xB1, 10, 5, Edit1, A ;EM_SETSEL := 0xB1
return

一些用于获取/设置选择的 AutoHotkey 函数示例:

JEE_EditGetRange(hCtl, ByRef vPos1, ByRef vPos2)
{
    VarSetCapacity(vPos1, 4), VarSetCapacity(vPos2, 4)
    SendMessage, 0xB0, % &vPos1, % &vPos2,, % "ahk_id " hCtl ;EM_GETSEL := 0xB0 ;(left, right)
    vPos1 := NumGet(&vPos1, 0, "UInt"), vPos2 := NumGet(&vPos2, 0, "UInt")
}

;==================================================

JEE_EditSetRange(hCtl, vPos1, vPos2, vDoScroll:=0)
{
    SendMessage, 0xB1, % vPos1, % vPos2,, % "ahk_id " hCtl ;EM_SETSEL := 0xB1 ;(anchor, active)
    if vDoScroll
        SendMessage, 0xB7, 0, 0,, % "ahk_id " hCtl ;EM_SCROLLCARET := 0xB7
}

;==================================================

;note: although this involves deselecting and selecting it seems to happen invisibly
JEE_EditGetRangeAnchorActive(hCtl, ByRef vPos1, ByRef vPos2)
{
    ;get selection
    VarSetCapacity(vPos1, 4), VarSetCapacity(vPos2, 4)
    SendMessage, 0xB0, % &vPos1, % &vPos2,, % "ahk_id " hCtl ;EM_GETSEL := 0xB0
    vPos1 := NumGet(&vPos1, 0, "UInt"), vPos2 := NumGet(&vPos2, 0, "UInt")
    if (vPos1 = vPos2)
        return
    vPos1X := vPos1, vPos2X := vPos2

    ;set selection to 0 characters and get active position
    SendMessage, 0xB1, -1, 0,, % "ahk_id " hCtl ;EM_SETSEL := 0xB1
    VarSetCapacity(vPos2, 4)
    SendMessage, 0xB0, % &vPos2, 0,, % "ahk_id " hCtl ;EM_GETSEL := 0xB0
    vPos2 := NumGet(&vPos2, 0, "UInt")

    ;restore selection
    vPos1 := (vPos2 = vPos2X) ? vPos1X : vPos2X
    SendMessage, 0xB1, % vPos1, % vPos2,, % "ahk_id " hCtl ;EM_SETSEL := 0xB1 ;(anchor, active)
}

链接:

我最初在 AutoHotkey 论坛上发布的上述功能:
GUI 命令:彻底重新思考 - AutoHotkey 社区
https://autohotkey.com/boards/viewtopic.php?f=5&t=25893&p=138292#p138292

关于c++ - EM_SETSEL 交换参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8725541/

相关文章:

c++ - 删除 IE9 缓存和 Cookie

c++ - 访问冲突写入位置 0xcccccccc

c++ - 什么 C++ OpenCV 库支持 `threshold` 函数?

c++ - 是否有简单的 C 或 C++ API 来修改 selinux 上下文?

c++ - static_cast 和 reinterpret_cast 效果一样的时候用哪个?

windows - 两个窗口上的句柄可以相同吗?

c - 如何等待窗口标题更新?

c - WinMain() 到 main() 宏中的奇怪错误

c++ - 在 Windows 控制台中获取按键

c++ - 检查 key 是否已经存在(RegOpenKey)