Direct2D CreateTextLayout() - 如何获取插入符坐标
Direct2D CreateTextLayout() - How to get caret coordinates
我正在使用 Direct2D 渲染文本,从文本布局开始
HRESULT hr = m_spWriteFactory->CreateTextLayout(
m_wsText.c_str( ),
m_wsText.length( ),
m_spWriteTextFormat.Get( ),
m_rect.right - m_rect.left - m_spacing.right - m_spacing.left,
m_rect.bottom - m_rect.top - m_spacing.top - m_spacing.bottom,
&m_spTextLayout
);
然后将其渲染为位图,我稍后将其用于 Direct3D
m_sp2DDeviceContext->DrawTextLayout(
D2D1::Point2F( m_spacing.left, m_spacing.top ),
m_spTextLayout.Get( ),
m_spTextBrush.Get( )
);
我想画一条简单的细闪烁线作为插入符号。我知道如何画线以及如何让它出现/消失。
问题:如何获取插入符线的起点和终点坐标?
简化: 如果假定文本仅由 一个 行组成要容易得多,那没关系。但当然,更通用的解决方案是值得赞赏的。
您可以通过IDWriteTextLayout::GetMetrics获取布局的边界矩形。
DWRITE_TEXT_METRICS textMetrics;
textLayout->GetMetrics(&textMetrics);
你的矩形是
D2D1::RectF( textMetrics.left,
textMetrics.top,
textMetrics.left + textMetrics.width,
textMetrics.top + textMetrics.height );
然后您可以沿着右边界线绘制插入符号。
使用 IDWriteTextLayout
的命中测试函数来确定这些:
HitTestTextPosition
用于将文本位置索引(相对于第一个字符)映射到矩形。
HitTestTextRange
用于获取整个范围的矩形以供选择。
HitTestPoint
用于将鼠标坐标映射到文本位置索引。
对于插入符号,下面的内容适用于所有水平阅读方向和 proportional/monospace 字体:
...
DWRITE_HIT_TEST_METRICS hitTestMetrics;
float caretX, caretY;
bool isTrailingHit = false; // Use the leading character edge for simplicity here.
// Map text position index to caret coordinate and hit-test rectangle.
textLayout->HitTestTextPosition(
textPosition,
isTrailingHit,
OUT &caretX,
OUT &caretY,
OUT &hitTestMetrics
);
// Respect user settings.
DWORD caretWidth = 1;
SystemParametersInfo(SPI_GETCARETWIDTH, 0, OUT &caretWidth, 0);
DWORD halfCaretWidth = caretWidth / 2u;
// Draw a thin rectangle.
D2D1::RectF caretRect = {
layoutOriginX + caretX - halfCaretWidth,
layoutOriginY + hitTestMetrics.top,
layoutOriginX + caretX + (caretWidth - halfCaretWidth),
layoutOriginY + hitTestMetrics.top + hitTestMetrics.height
};
solidColorBrush->SetColor(D2D1::ColorF::AliceBlue);
d2dRenderTarget->FillRectangle(&caretRect, solidColorBrush);
备注:
- 上面的代码没有考虑像日本报纸那样的垂直阅读方向。当
DWRITE_READING_DIRECTION
是从上到下或从下到上时,您需要在此处绘制一个宽而扁平的插入符而不是细长的插入符。
IDWriteTextLayout::GetMetrics
只给你整个边界框,而不是插入符号位置。
IDWriteTextLayout::HitTestPoint
的 isInside
标志在文本本身上方时为真,而不仅仅是布局边界。
我正在使用 Direct2D 渲染文本,从文本布局开始
HRESULT hr = m_spWriteFactory->CreateTextLayout(
m_wsText.c_str( ),
m_wsText.length( ),
m_spWriteTextFormat.Get( ),
m_rect.right - m_rect.left - m_spacing.right - m_spacing.left,
m_rect.bottom - m_rect.top - m_spacing.top - m_spacing.bottom,
&m_spTextLayout
);
然后将其渲染为位图,我稍后将其用于 Direct3D
m_sp2DDeviceContext->DrawTextLayout(
D2D1::Point2F( m_spacing.left, m_spacing.top ),
m_spTextLayout.Get( ),
m_spTextBrush.Get( )
);
我想画一条简单的细闪烁线作为插入符号。我知道如何画线以及如何让它出现/消失。
问题:如何获取插入符线的起点和终点坐标?
简化: 如果假定文本仅由 一个 行组成要容易得多,那没关系。但当然,更通用的解决方案是值得赞赏的。
您可以通过IDWriteTextLayout::GetMetrics获取布局的边界矩形。
DWRITE_TEXT_METRICS textMetrics;
textLayout->GetMetrics(&textMetrics);
你的矩形是
D2D1::RectF( textMetrics.left,
textMetrics.top,
textMetrics.left + textMetrics.width,
textMetrics.top + textMetrics.height );
然后您可以沿着右边界线绘制插入符号。
使用 IDWriteTextLayout
的命中测试函数来确定这些:
HitTestTextPosition
用于将文本位置索引(相对于第一个字符)映射到矩形。HitTestTextRange
用于获取整个范围的矩形以供选择。HitTestPoint
用于将鼠标坐标映射到文本位置索引。
对于插入符号,下面的内容适用于所有水平阅读方向和 proportional/monospace 字体:
...
DWRITE_HIT_TEST_METRICS hitTestMetrics;
float caretX, caretY;
bool isTrailingHit = false; // Use the leading character edge for simplicity here.
// Map text position index to caret coordinate and hit-test rectangle.
textLayout->HitTestTextPosition(
textPosition,
isTrailingHit,
OUT &caretX,
OUT &caretY,
OUT &hitTestMetrics
);
// Respect user settings.
DWORD caretWidth = 1;
SystemParametersInfo(SPI_GETCARETWIDTH, 0, OUT &caretWidth, 0);
DWORD halfCaretWidth = caretWidth / 2u;
// Draw a thin rectangle.
D2D1::RectF caretRect = {
layoutOriginX + caretX - halfCaretWidth,
layoutOriginY + hitTestMetrics.top,
layoutOriginX + caretX + (caretWidth - halfCaretWidth),
layoutOriginY + hitTestMetrics.top + hitTestMetrics.height
};
solidColorBrush->SetColor(D2D1::ColorF::AliceBlue);
d2dRenderTarget->FillRectangle(&caretRect, solidColorBrush);
备注:
- 上面的代码没有考虑像日本报纸那样的垂直阅读方向。当
DWRITE_READING_DIRECTION
是从上到下或从下到上时,您需要在此处绘制一个宽而扁平的插入符而不是细长的插入符。 IDWriteTextLayout::GetMetrics
只给你整个边界框,而不是插入符号位置。IDWriteTextLayout::HitTestPoint
的isInside
标志在文本本身上方时为真,而不仅仅是布局边界。