Visual C++ 6中标签旋转功能失效问题求助
VC++6 标签旋转功能失效的问题修正
问题根源梳理
你的代码存在三个核心问题导致旋转未生效:
- 旋转原点错误:当前的
XFORM是绕屏幕坐标原点(0,0)旋转,而非目标标签的中点,所以视觉上看不到旋转效果 - 变换重置逻辑错误:使用
SetWorldTransform(meta_dc, &xform)无法恢复原始绘图变换,应该提前保存初始变换,绘制完成后再恢复 - 缺少平移补偿:绕中点旋转需要先将文本的中点平移到原点,旋转完成后再平移回原位置,这一步完全缺失
修正后的代码
void do_labely( HDC meta_dc, SLATE_REC *slate_rec, const DEFAULT_STYLE *styl, double x, double y, unsigned char *the_str, short just, short style_idx, short size, short stylebits, short color, short v_just, BOOL clip, double theta) { LOGFONT lf; HFONT font, old_font; UINT align; XFORM old_xform; SIZE text_size; double rad = theta * PI / 180; int x1 = (int)(x * slate_rec->xscale); int y1 = (int)(y * slate_rec->yscale); // 保存原始变换和字体 GetWorldTransform(meta_dc, &old_xform); old_font = (HFONT)SelectObject(meta_dc, GetStockObject(SYSTEM_FONT)); // 设置字体 setup_logfont(meta_dc, &styl[style_idx], size, &lf, slate_rec, stylebits); font = CreateFontIndirect(&lf); SelectObject(meta_dc, font); // 设置文本颜色 switch (color) { case WHITE: SetTextColor(meta_dc, RGB(0xFF,0xFF,0xFF)); break; case RED: SetTextColor(meta_dc, RGB(0xFF,0x00,0x00)); break; case GREEN: SetTextColor(meta_dc, RGB(0x00,0xFF,0x00)); break; case BLUE: SetTextColor(meta_dc, RGB(0x00,0x00,0xFF)); break; default: SetTextColor(meta_dc, RGB(0x00,0x00,0x00)); break; } // 设置文本对齐方式 align = 0; switch (just) { case TX_JUST_LEFT: align = TA_LEFT; break; case TX_JUST_CENTER: align = TA_CENTER; break; case TX_JUST_RIGHT: align = TA_RIGHT; break; default: align = TA_LEFT; break; } switch (v_just) { case TX_JUST_TOP: align += TA_TOP; break; case TX_JUST_BASE: align += TA_BASELINE; break; case TX_JUST_BOTTOM: align += TA_BOTTOM; break; default: align += TA_TOP; break; } SetTextAlign(meta_dc, align); // 启用高级绘图模式 SetGraphicsMode(meta_dc, GM_ADVANCED); // 获取文本尺寸(用于计算中点偏移) GetTextExtentPoint32(meta_dc, (char*)the_str, strlen((char*)the_str), &text_size); // 构建变换矩阵:平移到原点 → 旋转 → 平移回原位置 XFORM xform_translate_to_origin, xform_rotate, xform_translate_back; // 计算平移到原点的偏移(基于文本对齐方式) int offset_x = 0, offset_y = 0; if (just == TX_JUST_CENTER) offset_x = -text_size.cx / 2; else if (just == TX_JUST_RIGHT) offset_x = -text_size.cx; if (v_just == TX_JUST_BASE) offset_y = -text_size.cy / 2; // 基线对齐时取垂直中点 else if (v_just == TX_JUST_BOTTOM) offset_y = -text_size.cy; // 平移到原点的变换 xform_translate_to_origin.eM11 = 1.0f; xform_translate_to_origin.eM12 = 0.0f; xform_translate_to_origin.eM21 = 0.0f; xform_translate_to_origin.eM22 = 1.0f; xform_translate_to_origin.eDx = x1 + offset_x; xform_translate_to_origin.eDy = y1 + offset_y; // 旋转变换 xform_rotate.eM11 = cos(rad); xform_rotate.eM12 = -sin(rad); xform_rotate.eM21 = sin(rad); xform_rotate.eM22 = cos(rad); xform_rotate.eDx = 0.0f; xform_rotate.eDy = 0.0f; // 平移回原位置的变换(偏移取反) xform_translate_back.eM11 = 1.0f; xform_translate_back.eM12 = 0.0f; xform_translate_back.eM21 = 0.0f; xform_translate_back.eM22 = 1.0f; xform_translate_back.eDx = -(x1 + offset_x); xform_translate_back.eDy = -(y1 + offset_y); // 应用变换:先平移到原点,再旋转,最后平移回原位置 ModifyWorldTransform(meta_dc, &xform_translate_to_origin, MWT_LEFTMULTIPLY); ModifyWorldTransform(meta_dc, &xform_rotate, MWT_LEFTMULTIPLY); ModifyWorldTransform(meta_dc, &xform_translate_back, MWT_LEFTMULTIPLY); // 绘制文本 TextOut(meta_dc, x1, y1, (char*)the_str, strlen((char*)the_str)); // 恢复原始变换和字体 SetWorldTransform(meta_dc, &old_xform); SelectObject(meta_dc, old_font); DeleteObject(font); }
关键修正点说明
- 保存并恢复原始变换:用
GetWorldTransform提前保存初始绘图变换,完成绘制后用SetWorldTransform恢复,避免影响后续绘图 - 调整旋转原点:通过两次平移变换,先将文本中点移到坐标原点,旋转后再移回原位置,确保绕自身中点旋转
- 计算文本尺寸:用
GetTextExtentPoint32获取文本宽高,结合对齐方式计算正确的平移偏移量,保证旋转后文本位置符合预期
内容的提问来源于stack exchange,提问作者user3239379
相关产品推荐
相关产品推荐

