具有DT_CALCRECT和DT_RIGHT的DrawText不起作用

时间:2016-10-05 07:23:41

标签: winapi drawtext

我在默认的VisualStudio项目中有以下代码。它将DT_CALCRECT传递给DrawTextW以计算绘制一些文本的矩形,然后使用该矩形绘制文本。要自己测试,只需将此代码粘贴到默认的VisualStudio项目中:

case WM_PAINT:
    hdc = BeginPaint(hWnd, &ps);
    // TODO: Add any drawing code here...

    {
        wchar_t txt[] = L"abcdef abcdef abcdef abcdef abcdef abcdef abcdef abcdef abcdef abcdef abcdef abcdef abcdef abcdef abcdef\r\nabc\r\n123456";
        BOOL useDT_RIGHT = TRUE; // <<< ** SWITCH THIS BETWEEN TRUE AND FALSE **
        wchar_t buf1[100] = {0};
        wchar_t buf2[100] = {0};
        RECT r1 = {0, 0, 192, 1000};
        RECT r2 = {r1.right + 10, r1.top, r1.right + 400, r1.top + 100};
        int ret1, ret2;

        FillRect(hdc, &r1, (HBRUSH)GetStockObject(GRAY_BRUSH));

        ret1 = DrawTextW(hdc, txt, -1, &r1,
            DT_CALCRECT |
            DT_WORDBREAK |
            (useDT_RIGHT == FALSE ? DT_LEFT : DT_RIGHT)
        );
        if(ret1 == 0) MessageBoxW(NULL, L"ret1 == 0", NULL, MB_OK);

        wsprintfW(buf1, L"useDT_RIGHT = %i\r\nDT_CALCRECT returned %i %i %i %i\r\nret1 = %i\r\n", useDT_RIGHT, r1.left, r1.top, r1.right, r1.bottom, ret1);

        ret2 = DrawTextW(hdc, txt, -1, &r1,
            DT_WORDBREAK |
            (useDT_RIGHT == FALSE ? DT_LEFT : DT_RIGHT)
        );
        if(ret2 == 0) MessageBoxW(NULL, L"ret2 == 0", NULL, MB_OK);

        wsprintfW(buf2, L"%sret2 = %i", buf1, ret2);
        DrawTextW(hdc, buf2, -1, &r2, DT_LEFT);
    }

    EndPaint(hWnd, &ps);
    break;

在代码中,如果useDT_RIGHT设置为FALSE,则文本左对齐,DT_CALCRECT返回正确的矩形,如下所示:

http://i64.tinypic.com/2ptw2dk.png

如果useDT_RIGHT设置为TRUE,则文本右对齐但DT_CALCRECT返回不正确的矩形,如下所示:

http://i68.tinypic.com/nwx9co.png

或者更确切地说,它可能正在返回一个正确的矩形,而后续实际绘制文本的调用是错误地绘制它,这是不可能的。

DT_CALCRECT的文档说&#34;如果有多行文本,DrawText使用lpRect参数指向的矩形的宽度,并扩展矩形的底边以绑定最后一行文本。如果最大的单词比矩形宽,则扩展宽度。如果文本小于矩形的宽度,则宽度会减小。&#34;

我所期望的是DrawTextW返回的矩形是正确的大小来绘制文本(在实际代码中,矩形也用于定位周围的控件,所以只需扩展它就可以赢得&#39;真的有帮助)。我还希望文本正确对齐(即与左对齐文本相反),而不是如上面第二个屏幕截图所示的混乱。通过正确对齐,我的意思是如wordpad的截图所示:

HTTP: //i63.tinypic.com/qqya1u.png (请从此链接中删除空格以使其正常工作。)

这段代码有什么问题?为什么带有DT_RIGHT的DT_CALCRECT不能产生预期的结果?或者,如果是,为什么第二次调用DrawTextW没有正确绘制它?

1 个答案:

答案 0 :(得分:1)

这种行为似乎是一个错误或设计。也许DT_WORDBREAK会删除空格,这就是使用DT_RIGHT时产生更窄矩形的原因。无论如何,当使用DT_CALCRECT与DT_LEFT或DT_RIGHT时,这是一种使DrawText的行为方式相同的方法,您可以测试此代码(检查以FIX开头的注释):

case WM_PAINT:
    hdc = BeginPaint(hWnd, &ps);
    // TODO: Add any drawing code here...

    {
        wchar_t txt[] = L"abcdef abcdef abcdef abcdef abcdef abcdef abcdef abcdef abcdef abcdef abcdef abcdef abcdef abcdef abcdef\r\nabc\r\n123456";
        BOOL useDT_RIGHT = FALSE; // TRUE; // <<< ** SWITCH THIS BETWEEN TRUE AND FALSE **
        wchar_t buf1[100] = { 0 };
        wchar_t buf2[100] = { 0 };
        RECT r1 = { 0, 0, 192, 1000 };
        RECT r2 = { r1.right + 10, r1.top, r1.right + 400, r1.top + 100 };
        int ret1, ret2;

        FillRect(hdc, &r1, (HBRUSH)GetStockObject(GRAY_BRUSH));

        ret1 = DrawTextW(hdc, txt, -1, &r1,
            DT_CALCRECT |
            DT_WORDBREAK | 
            (useDT_RIGHT == FALSE ? DT_LEFT : DT_RIGHT) 
            );
        if (ret1 == 0) MessageBoxW(NULL, L"ret1 == 0", NULL, MB_OK);

        // FIX: The following two lines make DrawText with DT_CALCRECT behave the same way for DT_LEFT and DT_RIGHT
        r1.right = 192;
        r1.bottom = ret1;

        wsprintfW(buf1, L"useDT_RIGHT = %i\r\nDT_CALCRECT returned %i %i %i %i\r\nret1 = %i\r\n", useDT_RIGHT, r1.left, r1.top, r1.right, r1.bottom, ret1);

        ret2 = DrawTextW(hdc, txt, -1, &r1,
            DT_WORDBREAK |
            (useDT_RIGHT == FALSE ? DT_LEFT : DT_RIGHT)
            );
        if (ret2 == 0) MessageBoxW(NULL, L"ret2 == 0", NULL, MB_OK);

        wsprintfW(buf2, L"%sret2 = %i", buf1, ret2);
        DrawTextW(hdc, buf2, -1, &r2, DT_LEFT);
    }

    EndPaint(hWnd, &ps);
    break;