使用 WinGDI 旋转 HDC
Rotating HDC using WinGDI
此 post 代码密集,因此请忽略第一个块。它只是作为参考,以了解该功能最初是如何工作的。
我目前正尝试在以下代码中对 hdcText 执行 -270 或 90 度旋转:
void CImageWindow::Show()
{
BITMAP bm;
PAINTSTRUCT ps;
//Start Drawing Segment
int iWidth = m_rLocation.right - m_rLocation.left;
int iHeight = m_rLocation.bottom - m_rLocation.top;
//Drawing plane for this window
HDC hdcScreen = BeginPaint(m_hWindow, &ps);
HBITMAP hWorking = CreateCompatibleBitmap(hdcScreen, iWidth,iHeight);
SelectObject(hdcScreen, hWorking);
SetStretchBltMode(hdcScreen, HALFTONE);
SetBrushOrgEx(hdcScreen,0,0,0);
//Background
HDC hdcMem = CreateCompatibleDC(hdcScreen);
HBITMAP hBmp = (HBITMAP)LoadImage(m_hInstance, m_sTexture.c_str(), IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
SelectObject(hdcMem, hBmp);
GetObject(hBmp, sizeof(bm), &bm);
StretchBlt(hdcScreen,0,0, iWidth, iHeight, hdcMem, 0,0,bm.bmWidth,bm.bmHeight, SRCCOPY);
//Text
HDC hdcText = CreateCompatibleDC(hdcScreen);
HBITMAP hbmpText = CreateCompatibleBitmap(hdcText, iWidth,iHeight);
SelectObject(hdcText, hbmpText);
RECT rTextLoc;
rTextLoc.top = iHeight/4;
rTextLoc.bottom = 3 * iHeight / 4;
rTextLoc.left = iWidth / 4;
rTextLoc.right =3 * iWidth / 4;
SetTextColor(hdcText, RGB(255,255,255));
SetBkMode(hdcText, TRANSPARENT);
HFONT hfFont = CreateFont((iHeight/2) - 2, 0,0,0,0,0,0,0,0,0,0,0,0,"Tahoma"); //-2 to ensure it can fit in the rectangle
SelectObject(hdcText, hfFont);
DrawText(hdcText, m_sIdentifier.c_str(), -1, &rTextLoc, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
StretchBlt(hdcScreen, 0,0,iWidth,iHeight, hdcText, 0,0,iWidth,iHeight, SRCINVERT);
if(m_bFlipped)
StretchBlt(hdcScreen, iWidth,iHeight,-iWidth,-iHeight, hdcScreen, 0,0,iWidth,iHeight, SRCCOPY);
DeleteObject(hWorking);
DeleteObject(hBmp);
DeleteObject(hbmpText);
DeleteObject(hfFont);
DeleteObject(hdcMem);
DeleteObject(hdcText);
EndPaint( m_hWindow, &ps );
}
我已尝试执行以下操作来解决此问题。
- 使用 XForm 旋转 HDC。
这对 hdcText 的位置没有任何影响。我不确定为什么,而且信息很少。
注意:我已经尝试过 XForm 值,所以即使这些值不正确,我也不认为这是问题所在。
void CImageWindow::Show()
{
BITMAP bm;
PAINTSTRUCT ps;
//Start Drawing Segment
int iWidth = m_rLocation.right - m_rLocation.left;
int iHeight = m_rLocation.bottom - m_rLocation.top;
//Drawing plane for this window
HDC hdcScreen = BeginPaint(m_hWindow, &ps);
HBITMAP hWorking = CreateCompatibleBitmap(hdcScreen, iWidth,iHeight);
SelectObject(hdcScreen, hWorking);
SetStretchBltMode(hdcScreen, HALFTONE);
SetBrushOrgEx(hdcScreen,0,0,0);
//Background
HDC hdcMem = CreateCompatibleDC(hdcScreen);
HBITMAP hBmp = (HBITMAP)LoadImage(m_hInstance, m_sTexture.c_str(), IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
SelectObject(hdcMem, hBmp);
GetObject(hBmp, sizeof(bm), &bm);
StretchBlt(hdcScreen,0,0, iWidth, iHeight, hdcMem, 0,0,bm.bmWidth,bm.bmHeight, SRCCOPY);
//Text
HDC hdcText = CreateCompatibleDC(hdcScreen);
//Added
SetGraphicsMode(hdcText, GM_ADVANCED);
SetMapMode(hdcText, MM_TEXT);
HBITMAP hbmpText = CreateCompatibleBitmap(hdcText, iWidth,iHeight);
SelectObject(hdcText, hbmpText);
RECT rTextLoc;
rTextLoc.top = iHeight/4;
rTextLoc.bottom = 3 * iHeight / 4;
rTextLoc.left = iWidth / 4;
rTextLoc.right =3 * iWidth / 4;
SetTextColor(hdcText, RGB(255,255,255));
SetBkMode(hdcText, TRANSPARENT);
lf.lfWeight = FW_NORMAL;
lstrcpy(lf.lfFaceName, _T("Tahoma"));
float iAngle = 2700;
//float fAngle = -static_cast<float>(iAngle) * static_cast<float>(M_PI) / 180.0f;
rTextLoc.top = iHeight/4;
rTextLoc.bottom = 3 * iHeight / 4;
rTextLoc.left = iWidth / 4;
rTextLoc.right =3 * iWidth / 4;
HFONT hFont = CreateFont((iHeight/2) - 2, 0,0,0,0,0,0,0,0,0,0,0,0,"Tahoma"); //-2 to ensure it can fit in the rectangle
long y = (rTextLoc.bottom - rTextLoc.top) / 2;
long x = (rTextLoc.right - rTextLoc.left) / 2;
XFORM xForm;
float iAngle = 270;
float fAngle = -static_cast<float>(iAngle) * static_cast<float>(M_PI) / 180.0f;
xForm.eM11 = (FLOAT) cos(fAngle);
xForm.eM12 = (FLOAT) sin(fAngle);
xForm.eM21 = (FLOAT) -sin(fAngle);
xForm.eM22 = (FLOAT) cos(fAngle);
xForm.eDx = (FLOAT) (x * (1 - cos(fAngle))) + (sin(fAngle) * y);
xForm.eDy = (FLOAT) (-sin(fAngle) * x) + (y * (1 - cos(fAngle)));
xForm.eDx += (FLOAT) ((rTextLoc.bottom - rTextLoc.top) / 2) - ((rTextLoc.right - rTextLoc.left) / 2);
xForm.eDy += (FLOAT) ((rTextLoc.bottom - rTextLoc.top) / 2) - ((rTextLoc.right - rTextLoc.left) / 2);
SetWorldTransform(hdcScreen, &xForm);
SetGraphicsMode(hdcText, GM_COMPATIBLE);
SelectObject(hdcText, hFont);
DrawText(hdcText, m_sIdentifier.c_str(), -1, &rTextLoc, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
StretchBlt(hdcScreen, 0,0,iWidth,iHeight, hdcText, 0,0,iWidth,iHeight, SRCINVERT);
ReleaseDC(m_hWindow, hdcText);
if(m_bFlipped)
StretchBlt(hdcScreen, iWidth,iHeight,-iWidth,-iHeight, hdcScreen, 0,0,iWidth,iHeight, SRCCOPY);
DeleteObject(hWorking);
DeleteObject(hBmp);
DeleteObject(hbmpText);
DeleteObject(hFont);
DeleteObject(hdcMem);
DeleteObject(hdcText);
EndPaint( m_hWindow, &ps );
}
- 使用 LOGFONT 旋转。我已经设置了 lfEscapement 和 lfOrientation 的值。文本在移动,但仅在擒纵机构矢量上移动。期望的结果是在设定点上进行旋转。
感谢任何帮助。
根据评论,您显然想要旋转打印出的字符串中的各个字符,而不改变字符串本身基线的角度。
为此,您需要将 lfEscapement
保留为 0,并仅更改字体的 lfOrientation
。要创建 lfEscapement
和 lfOrientation
具有不同值的字体,您需要设置 "advanced" 图形模式,因此序列如下所示:
SetGraphicsMode(yourDC, GM_ADVANCED);
HFONT font = CreateFont(20, 0, 0, 1800, FW_NORMAL, 0, 0, 0, FF_SWISS,
OUT_OUTLINE_PRECIS, CLIP_CHARACTER_PRECIS, CLEARTYPE_QUALITY,
ANSI_CHARSET, L"Arial");
auto old_font = SelectObject(yourDC, font);
TextOutW(yourDC, 50, 50, L"Your Text");
你的结果应该是这样的:
当然,如果您希望文本倒置(如评论中的 link 所示),您需要将 lfOrientation
更改为 1800,才能得到这样的结果:
附带说明一下,对于某些中间角度,字距调整可能会变得非常古怪。例如,在 130 度旋转时:
委婉地说,非常糟糕。
此 post 代码密集,因此请忽略第一个块。它只是作为参考,以了解该功能最初是如何工作的。
我目前正尝试在以下代码中对 hdcText 执行 -270 或 90 度旋转:
void CImageWindow::Show()
{
BITMAP bm;
PAINTSTRUCT ps;
//Start Drawing Segment
int iWidth = m_rLocation.right - m_rLocation.left;
int iHeight = m_rLocation.bottom - m_rLocation.top;
//Drawing plane for this window
HDC hdcScreen = BeginPaint(m_hWindow, &ps);
HBITMAP hWorking = CreateCompatibleBitmap(hdcScreen, iWidth,iHeight);
SelectObject(hdcScreen, hWorking);
SetStretchBltMode(hdcScreen, HALFTONE);
SetBrushOrgEx(hdcScreen,0,0,0);
//Background
HDC hdcMem = CreateCompatibleDC(hdcScreen);
HBITMAP hBmp = (HBITMAP)LoadImage(m_hInstance, m_sTexture.c_str(), IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
SelectObject(hdcMem, hBmp);
GetObject(hBmp, sizeof(bm), &bm);
StretchBlt(hdcScreen,0,0, iWidth, iHeight, hdcMem, 0,0,bm.bmWidth,bm.bmHeight, SRCCOPY);
//Text
HDC hdcText = CreateCompatibleDC(hdcScreen);
HBITMAP hbmpText = CreateCompatibleBitmap(hdcText, iWidth,iHeight);
SelectObject(hdcText, hbmpText);
RECT rTextLoc;
rTextLoc.top = iHeight/4;
rTextLoc.bottom = 3 * iHeight / 4;
rTextLoc.left = iWidth / 4;
rTextLoc.right =3 * iWidth / 4;
SetTextColor(hdcText, RGB(255,255,255));
SetBkMode(hdcText, TRANSPARENT);
HFONT hfFont = CreateFont((iHeight/2) - 2, 0,0,0,0,0,0,0,0,0,0,0,0,"Tahoma"); //-2 to ensure it can fit in the rectangle
SelectObject(hdcText, hfFont);
DrawText(hdcText, m_sIdentifier.c_str(), -1, &rTextLoc, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
StretchBlt(hdcScreen, 0,0,iWidth,iHeight, hdcText, 0,0,iWidth,iHeight, SRCINVERT);
if(m_bFlipped)
StretchBlt(hdcScreen, iWidth,iHeight,-iWidth,-iHeight, hdcScreen, 0,0,iWidth,iHeight, SRCCOPY);
DeleteObject(hWorking);
DeleteObject(hBmp);
DeleteObject(hbmpText);
DeleteObject(hfFont);
DeleteObject(hdcMem);
DeleteObject(hdcText);
EndPaint( m_hWindow, &ps );
}
我已尝试执行以下操作来解决此问题。
- 使用 XForm 旋转 HDC。
这对 hdcText 的位置没有任何影响。我不确定为什么,而且信息很少。
注意:我已经尝试过 XForm 值,所以即使这些值不正确,我也不认为这是问题所在。
void CImageWindow::Show()
{
BITMAP bm;
PAINTSTRUCT ps;
//Start Drawing Segment
int iWidth = m_rLocation.right - m_rLocation.left;
int iHeight = m_rLocation.bottom - m_rLocation.top;
//Drawing plane for this window
HDC hdcScreen = BeginPaint(m_hWindow, &ps);
HBITMAP hWorking = CreateCompatibleBitmap(hdcScreen, iWidth,iHeight);
SelectObject(hdcScreen, hWorking);
SetStretchBltMode(hdcScreen, HALFTONE);
SetBrushOrgEx(hdcScreen,0,0,0);
//Background
HDC hdcMem = CreateCompatibleDC(hdcScreen);
HBITMAP hBmp = (HBITMAP)LoadImage(m_hInstance, m_sTexture.c_str(), IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
SelectObject(hdcMem, hBmp);
GetObject(hBmp, sizeof(bm), &bm);
StretchBlt(hdcScreen,0,0, iWidth, iHeight, hdcMem, 0,0,bm.bmWidth,bm.bmHeight, SRCCOPY);
//Text
HDC hdcText = CreateCompatibleDC(hdcScreen);
//Added
SetGraphicsMode(hdcText, GM_ADVANCED);
SetMapMode(hdcText, MM_TEXT);
HBITMAP hbmpText = CreateCompatibleBitmap(hdcText, iWidth,iHeight);
SelectObject(hdcText, hbmpText);
RECT rTextLoc;
rTextLoc.top = iHeight/4;
rTextLoc.bottom = 3 * iHeight / 4;
rTextLoc.left = iWidth / 4;
rTextLoc.right =3 * iWidth / 4;
SetTextColor(hdcText, RGB(255,255,255));
SetBkMode(hdcText, TRANSPARENT);
lf.lfWeight = FW_NORMAL;
lstrcpy(lf.lfFaceName, _T("Tahoma"));
float iAngle = 2700;
//float fAngle = -static_cast<float>(iAngle) * static_cast<float>(M_PI) / 180.0f;
rTextLoc.top = iHeight/4;
rTextLoc.bottom = 3 * iHeight / 4;
rTextLoc.left = iWidth / 4;
rTextLoc.right =3 * iWidth / 4;
HFONT hFont = CreateFont((iHeight/2) - 2, 0,0,0,0,0,0,0,0,0,0,0,0,"Tahoma"); //-2 to ensure it can fit in the rectangle
long y = (rTextLoc.bottom - rTextLoc.top) / 2;
long x = (rTextLoc.right - rTextLoc.left) / 2;
XFORM xForm;
float iAngle = 270;
float fAngle = -static_cast<float>(iAngle) * static_cast<float>(M_PI) / 180.0f;
xForm.eM11 = (FLOAT) cos(fAngle);
xForm.eM12 = (FLOAT) sin(fAngle);
xForm.eM21 = (FLOAT) -sin(fAngle);
xForm.eM22 = (FLOAT) cos(fAngle);
xForm.eDx = (FLOAT) (x * (1 - cos(fAngle))) + (sin(fAngle) * y);
xForm.eDy = (FLOAT) (-sin(fAngle) * x) + (y * (1 - cos(fAngle)));
xForm.eDx += (FLOAT) ((rTextLoc.bottom - rTextLoc.top) / 2) - ((rTextLoc.right - rTextLoc.left) / 2);
xForm.eDy += (FLOAT) ((rTextLoc.bottom - rTextLoc.top) / 2) - ((rTextLoc.right - rTextLoc.left) / 2);
SetWorldTransform(hdcScreen, &xForm);
SetGraphicsMode(hdcText, GM_COMPATIBLE);
SelectObject(hdcText, hFont);
DrawText(hdcText, m_sIdentifier.c_str(), -1, &rTextLoc, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
StretchBlt(hdcScreen, 0,0,iWidth,iHeight, hdcText, 0,0,iWidth,iHeight, SRCINVERT);
ReleaseDC(m_hWindow, hdcText);
if(m_bFlipped)
StretchBlt(hdcScreen, iWidth,iHeight,-iWidth,-iHeight, hdcScreen, 0,0,iWidth,iHeight, SRCCOPY);
DeleteObject(hWorking);
DeleteObject(hBmp);
DeleteObject(hbmpText);
DeleteObject(hFont);
DeleteObject(hdcMem);
DeleteObject(hdcText);
EndPaint( m_hWindow, &ps );
}
- 使用 LOGFONT 旋转。我已经设置了 lfEscapement 和 lfOrientation 的值。文本在移动,但仅在擒纵机构矢量上移动。期望的结果是在设定点上进行旋转。
感谢任何帮助。
根据评论,您显然想要旋转打印出的字符串中的各个字符,而不改变字符串本身基线的角度。
为此,您需要将 lfEscapement
保留为 0,并仅更改字体的 lfOrientation
。要创建 lfEscapement
和 lfOrientation
具有不同值的字体,您需要设置 "advanced" 图形模式,因此序列如下所示:
SetGraphicsMode(yourDC, GM_ADVANCED);
HFONT font = CreateFont(20, 0, 0, 1800, FW_NORMAL, 0, 0, 0, FF_SWISS,
OUT_OUTLINE_PRECIS, CLIP_CHARACTER_PRECIS, CLEARTYPE_QUALITY,
ANSI_CHARSET, L"Arial");
auto old_font = SelectObject(yourDC, font);
TextOutW(yourDC, 50, 50, L"Your Text");
你的结果应该是这样的:
当然,如果您希望文本倒置(如评论中的 link 所示),您需要将 lfOrientation
更改为 1800,才能得到这样的结果:
附带说明一下,对于某些中间角度,字距调整可能会变得非常古怪。例如,在 130 度旋转时:
委婉地说,非常糟糕。