这个错误是因为 `Graphics::DrawString` 方法的参数类型不匹配。在 GDI+ 中,`DrawString` 有多个重载版本,但需要确保传入的参数类型正确。以下是修正后的代码和详细解释:
---
### **错误原因**
`Graphics::DrawString` 的常见重载形式之一是:
```cpp
Status DrawString(
const WCHAR* string,
INT length,
const Font* font,
const PointF& origin,
const StringFormat* format,
const Brush* brush
);
```
或:
```cpp
Status DrawString(
const WCHAR* string,
INT length,
const Font* font,
const RectF& layoutRect,
const StringFormat* format,
const Brush* brush
);
```
您的代码中可能直接传入了 `CString` 或未正确转换字符串类型。
---
### **修正后的 `OnPaint` 方法**
```cpp
void MyButton::OnPaint()
{
CPaintDC dc(this);
Graphics graphics(dc.GetSafeHdc());
graphics.SetSmoothingMode(SmoothingModeAntiAlias);
CRect clientRect;
GetClientRect(&clientRect);
RectF rect((REAL)clientRect.left, (REAL)clientRect.top,
(REAL)clientRect.Width(), (REAL)clientRect.Height());
// 创建圆角路径
GraphicsPath path;
AddRoundRectPath(&path, rect, 10.0f);
// 填充背景色
SolidBrush brush(Color(255, GetRValue(m_bgColor), GetGValue(m_bgColor), GetBValue(m_bgColor)));
graphics.FillPath(&brush, &path);
// 绘制边框
Pen pen(Color(255, 0, 0, 0), 1.0f);
graphics.DrawPath(&pen, &path);
// 绘制文本(修正部分)
CString strText;
GetWindowText(strText);
if (!strText.IsEmpty())
{
// 将 CString 转换为宽字符(WCHAR*)
int len = strText.GetLength();
WCHAR* wideStr = new WCHAR[len + 1];
MultiByteToWideChar(CP_ACP, 0, strText, -1, wideStr, len + 1);
// 设置文本格式
StringFormat format;
format.SetAlignment(StringAlignmentCenter);
format.SetLineAlignment(StringAlignmentCenter);
// 使用正确的 DrawString 重载
Font font(L"Arial", 10);
SolidBrush textBrush(Color(255, 0, 0, 0));
graphics.DrawString(wideStr, len, &font, rect, &format, &textBrush);
delete[] wideStr; // 释放内存
}
}
```
---
### **关键修正点**
1. **字符串转换**
- `CString` 是 ANSI 字符串,而 `DrawString` 需要 `WCHAR*`(宽字符)。
- 使用 `MultiByteToWideChar` 进行转换,或直接使用 `CStringW`(宽字符版 CString)。
2. **参数顺序和类型**
- 确保 `DrawString` 的参数顺序为:
`(字符串, 长度, 字体, 布局矩形, 格式, 画刷)`。
3. **内存管理**
- 动态分配的 `wideStr` 需要在绘制完成后释放。
---
### **优化版本(使用 `CStringW`)**
如果项目支持 Unicode,可以直接用 `CStringW` 简化代码:
```cpp
void MyButton::OnPaint()
{
// ...(前面的路径和背景绘制代码不变)
CStringW strText;
GetWindowText(strText); // 自动转换为宽字符
if (!strText.IsEmpty())
{
StringFormat format;
format.SetAlignment(StringAlignmentCenter);
format.SetLineAlignment(StringAlignmentCenter);
Font font(L"Arial", 10);
SolidBrush textBrush(Color(255, 0, 0, 0));
graphics.DrawString(strText, strText.GetLength(), &font, rect, &format, &textBrush);
}
}
```
---
### **其他注意事项**
1. **字体和画刷的生命周期**
- 确保 `Font` 和 `SolidBrush` 对象在 `DrawString` 调用期间有效(不要使用局部变量后立即释放)。
2. **错误处理**
- 检查 `DrawString` 的返回值(`Status` 类型),确保绘制成功。
3. **性能优化**
- 如果按钮文本不变,可以缓存转换后的宽字符字符串,避免每次重绘时重复转换。
---
### **完整修正后的代码**
```cpp
void MyButton::OnPaint()
{
CPaintDC dc(this);
Graphics graphics(dc.GetSafeHdc());
graphics.SetSmoothingMode(SmoothingModeAntiAlias);
CRect clientRect;
GetClientRect(&clientRect);
RectF rect((REAL)clientRect.left, (REAL)clientRect.top,
(REAL)clientRect.Width(), (REAL)clientRect.Height());
// 绘制圆角按钮
GraphicsPath path;
AddRoundRectPath(&path, rect, 10.0f);
SolidBrush brush(Color(255, GetRValue(m_bgColor), GetGValue(m_bgColor), GetBValue(m_bgColor)));
graphics.FillPath(&brush, &path);
Pen pen(Color(255, 0, 0, 0), 1.0f);
graphics.DrawPath(&pen, &path);
// 绘制文本(优化版)
CStringW strText;
GetWindowText(strText);
if (!strText.IsEmpty())
{
StringFormat format;
format.SetAlignment(StringAlignmentCenter);
format.SetLineAlignment(StringAlignmentCenter);
Font font(L"Arial", 10);
SolidBrush textBrush(Color(255, 0, 0, 0));
graphics.DrawString(strText, strText.GetLength(), &font, rect, &format, &textBrush);
}
}
```
---
### **总结**
- 错误原因是 `DrawString` 参数类型不匹配(主要是字符串格式问题)。
- 解决方法:
1. 使用 `MultiByteToWideChar` 或 `CStringW` 转换字符串。
2. 确保参数顺序和类型符合 `DrawString` 的重载要求。
3. 管理好内存和对象生命周期。
如果仍有问题,请检查:
1. 项目字符集设置(建议使用 Unicode)。
2. GDI+ 是否正确初始化。
3. 按钮文本是否为空或包含特殊字符。