minigui:基于GetTabbedTextExtentPoint 计算多行文本显示的矩形尺寸

当我们想知道一个字符串在屏幕上显示所占的区域大小,该怎么实现呢?
minigui提供了GetTabbedTextExtentPoint函数用于计算一个字符串在屏幕显示的时候实际的显示区域大小.下面是GetTabbedTextExtentPoint 的函数声明(declared in minigui/gdi.h)

MG_EXPORT int GUIAPI GetTabbedTextExtentPoint (HDC hdc, 
                const char* text, int len, int max_extent, 
                int* fit_chars, int* pos_chars, int* dx_chars, SIZE* size);

其中max_extent用于指定显示的最大宽度,如果字符串太长超过这个长度,那么size.cx就是这个值。GetTabbedTextExtentPoint的返回值是实际显示的字符数。
比如字符串”hello,world”,指定max_extent=40,则函数返回值为5,代表对于40像素的宽度限制,只能显示前5个字符。返回的SIZE值为cx=40,cy=16,代表屏幕显示宽度为40,高度为16(一行的高度)。

    HDC hdc = GetDC(HWND_DESKTOP);
    SIZE ls;
    const char*pstr = "hello,world";
    int offset = GetTabbedTextExtentPoint (hdc, "hello,world", strlen(pstr),
                    40, NULL, NULL, NULL, &ls);
    // offset = 5, ls = {40,16}
    ReleaseDC(hdc);

根据这个函数提供的功能,就可以实现计算多行文本显示区域大小(gnu c编译)。

#include <minigui/common.h>
#include <minigui/minigui.h>
#include <minigui/gdi.h>
#include <minigui/window.h>
// 计算文本显示需要的屏幕尺寸
// text 显示的文本,不可为NULL
// max_width 显示文本的最大屏幕宽度
// size 返回计算结果
// log_font 指定显示字体,为NULL使用缺省字体
// 计算成功返回值 TRUE,否则返回FALSE
BOOL compute_text_rect(const char*text,int max_width,SIZE *size,PLOGFONT log_font){
    if (!size) {
        return FALSE;
    }
    // 获取屏幕DC
    HDC hdc = GetDC(HWND_DESKTOP);
    PLOGFONT of = NULL;
    // gnu c内置函数用于返回时释放DC
    BOOL do_finally(BOOL ret)
    {
        if( HDC_SCREEN == hdc){
                SelectFont(hdc,of);
            }
        ReleaseDC(hdc); 
        return ret;
    }
    if(log_font){
        // 设置字体
        of =SelectFont(hdc,log_font);
    }
    size->cx=0,size->cy=0;
    // max_width 至少要大于一个字符宽度
    if(!(max_width >= GetMaxFontWidth(hdc))){
        return do_finally(FALSE);
    }
    SIZE ls;
    const char *pstr = text ? text : "";
    int offset = 0;
    while(strlen(pstr += offset)){
        // 计算一行的显示区域输出到ls,offset为实际输出了多少个字符
        offset = GetTabbedTextExtentPoint (hdc, pstr, strlen(pstr),
                max_width, NULL, NULL, NULL, &ls);
        // 显示区域宽度为所有行的最大宽度      
        size->cx = MAX(size->cx,ls.cx);
        // 显示区域高度累加一行的高度
        size->cy += ls.cy;
        // 继续处理剩下的字符
        offset = MIN(offset,strlen(pstr));
    }
    return do_finally(TRUE);
}

猜你喜欢

转载自blog.csdn.net/10km/article/details/80984339