RichEdit 垂直文本对齐方式

发布于 2024-10-09 21:57:53 字数 74 浏览 6 评论 0原文

如何将 TRichEdit 中的文本垂直居中对齐。有一个用于水平对齐段落的属性,但没有任何用于垂直对齐的属性。我使用 C++ 构建器。

How can i align the text in a TRichEdit vertically centered. There is a property for aligning paragaph by horizontal but there isn't any property for vertical alignment. I use C++ builder.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

没︽人懂的悲伤 2024-10-16 21:57:53

TRichEdit 只是 MS RichEdit 组件的包装器,因此您可以获得句柄并使用 WinAPI 直接使用它: http://msdn.microsoft.com/en-us/library/bb787873(VS.85).aspx

TRichEdit is just a wrapper around MS RichEdit component, so you can get a handle and use WinAPI to work with it directly: http://msdn.microsoft.com/en-us/library/bb787873(VS.85).aspx

榕城若虚 2024-10-16 21:57:53

Richedit 界面没有相应的方法。然而,使用现有消息来做到这一点相当简单。使用 EM_POSFROMCHAR 获取控件中第一个和最后一个字符的垂直位置,并添加最后一个字符的高度。然后计算文本垂直居中所需的距控件顶部的偏移量。然后使用 EM_SETRECT 消息来调整文本在控件中绘制的位置。

如果您想在修改文本时动态执行此操作,则需要对控件进行子类化并处理适当的消息。请参阅下面的代码片段。

// in WM_CREATE of parent window or when control is created
hwndTextbox = CreateWindowEx (0, MSFTEDIT_CLASS, (WCHAR*)yourtext, 
    ES_MULTILINE | WS_VISIBLE | WS_SIZEBOX | WS_CHILD | WS_CLIPSIBLINGS,
    left, top, width, height,
    hwnd, NULL, hInst, NULL);
    SetProp (hwndTextbox, L"oldproc", (HANDLE)(ULONG_PTR)GetWindowLong (hwndTextbox, GWL_WNDPROC));
    SetWindowLong (hwndTextbox, GWL_WNDPROC, (DWORD)(LRESULT)RicheditWndProc);

// after control has been drawn eg in WM_SIZE of parent window
{
    RECT rclBox;
    SendMessage(hwndTextbox, EM_GETRECT, 0, (LPARAM)&rclBox);
    rclBox.top = vertoffset;    // previously saved vertical offset for control either globally or as window property of control
    SendMessage(hwndTextbox, EM_SETRECT, 0, (LPARAM)&rclBox);
    InvalidateRect(hwndTextbox, NULL, TRUE);
}


LRESULT WINAPI RicheditWndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    static BOOL fVcentre;   // will need to be stored as a window property if more than one control
    WNDPROC lpOldProc;
    CHARFORMAT cf;
    lpOldProc = (WNDPROC)GetProp( hwnd, L"oldproc" );
    switch( msg )
    {
    case WM_TIMER:
        // use timer to ensure text is redrawn before positioning
        switch(wParam)
        {
        case 1:
            KillTimer(hwnd, 1);
            {
                POINTL pt, pt1;
                RECT rcl;
                RECT rclParent;
                int last, height=0, offset, current;
                SendMessage (hwnd, EM_GETSEL, (WPARAM)¤t, 0);
                SendMessage(hwnd, EM_GETRECT, 0, (LPARAM)&rcl);
                GetClientRect(GetParent(hwnd), &rclParent);
                SendMessage (hwnd, EM_SETSEL, 0, -1);
                SendMessage (hwnd, EM_GETSEL, 0, (LPARAM)&last);
                SendMessage(hwnd, EM_POSFROMCHAR, (WPARAM)&pt, 0);
                SendMessage(hwnd, EM_POSFROMCHAR, (WPARAM)&pt1, last);
                // get height of last character
                SendMessage (hwnd, EM_SETSEL, last-1, last);
                memset(&cf, 0, sizeof cf);
                cf.cbSize = sizeof cf;
                SendMessage (hwnd, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
                if(cf.dwMask & CFM_SIZE)
                    height = cf.yHeight/15;
                height = height + pt1.y - pt.y;
                vertoffset = (rcl.bottom - height)/2;
                ifvertoffset > 0) // vertoffset can be < 0 if needed
                {
                    rcl.top = vertoffset;
                    SendMessage(hwnd, EM_SETRECT, 0, (LPARAM)&rcl);
                    InvalidateRect(hwnd, NULL, TRUE);
                }
                SendMessage (hwnd, EM_SETSEL, current, current);
            }
            break;
        }
        break;

        case WM_DESTROY:                         //  Put back old window proc and
                SetWindowLong( hwnd, GWL_WNDPROC, (DWORD)(LRESULT)lpOldProc );
                RemoveProp( hwnd, L"oldproc" );              //  remove window property
                break;

    case WM_KEYUP:
    case WM_CHAR:
    case WM_PASTE:
    case WM_CUT:
    case EM_UNDO:
    case EM_REDO:
    // any message that modifies the text
        if(fVcentre)
            SetTimer(hwnd, 1, 100, NULL);
        break;

    case WM_COMMAND:
        switch (LOWORD(wParam))
        {
        case ID_TFVCENTRE:  // id to centre text
            {
                POINTL pt, pt1;
                RECT rcl;
                RECT rclParent;
                int last, height=0, offset, current;
                fVcentre = !fVcentre;
                SendMessage(hwnd, EM_GETRECT, 0, (LPARAM)&rcl);
                if(fVcentre)
                {
                    GetClientRect(GetParent(hwnd), &rclParent);
                    SendMessage (hwnd, EM_GETSEL, (WPARAM)¤t, 0);
                    SendMessage (hwnd, EM_SETSEL, 0, -1);
                    SendMessage (hwnd, EM_GETSEL, 0, (LPARAM)&last);
                    SendMessage(hwnd, EM_POSFROMCHAR, (WPARAM)&pt, 0);
                    SendMessage(hwnd, EM_POSFROMCHAR, (WPARAM)&pt1, last);
                    // get height of last character
                    SendMessage (hwnd, EM_SETSEL, last-1, last);
                    memset(&cf, 0, sizeof cf);
                    cf.cbSize = sizeof cf;
                    SendMessage (hwnd, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
                    if(cf.dwMask & CFM_SIZE)
                        height = cf.yHeight/15;
                    height = height + pt1.y - pt.y;
                    vertoffset = (rcl.bottom - height)/2;
                    ifvertoffset > 0)
                    {
                        rcl.top = vertoffset 
                        SendMessage(hwnd, EM_SETRECT, 0, (LPARAM)&rcl);
                        InvalidateRect(hwnd, NULL, TRUE);
                    }
                    SendMessage (hwnd, EM_SETSEL, current, current);
                }
                else
                {
                    rcl.top = 0;
                    vertoffset = 0;
                    SendMessage(hwnd, EM_SETRECT, 0, (LPARAM)&rcl);
                    InvalidateRect(hwnd, NULL, TRUE);
                }
            }
            break;
        }
        break;

    }                        //  Pass all non-custom messages to old window proc
    return( CallWindowProc( lpOldProc, hwnd, msg, wParam, lParam ) );
}

The Richedit interface does not have a method for this. However it is fairly straightforward to do it using existing messages. Use EM_POSFROMCHAR to get the vertical position of the first and last character in the control, adding the height of the last character. Then calculate the offset from the top of the control needed to centre the text vertically. Then use an EM_SETRECT message to adjust the position that the txt is drawn in the control.

If you want to do this dynamically as the text is modified you will need to subclass the control and handle the appropriate messages. See the code snippets below.

// in WM_CREATE of parent window or when control is created
hwndTextbox = CreateWindowEx (0, MSFTEDIT_CLASS, (WCHAR*)yourtext, 
    ES_MULTILINE | WS_VISIBLE | WS_SIZEBOX | WS_CHILD | WS_CLIPSIBLINGS,
    left, top, width, height,
    hwnd, NULL, hInst, NULL);
    SetProp (hwndTextbox, L"oldproc", (HANDLE)(ULONG_PTR)GetWindowLong (hwndTextbox, GWL_WNDPROC));
    SetWindowLong (hwndTextbox, GWL_WNDPROC, (DWORD)(LRESULT)RicheditWndProc);

// after control has been drawn eg in WM_SIZE of parent window
{
    RECT rclBox;
    SendMessage(hwndTextbox, EM_GETRECT, 0, (LPARAM)&rclBox);
    rclBox.top = vertoffset;    // previously saved vertical offset for control either globally or as window property of control
    SendMessage(hwndTextbox, EM_SETRECT, 0, (LPARAM)&rclBox);
    InvalidateRect(hwndTextbox, NULL, TRUE);
}


LRESULT WINAPI RicheditWndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    static BOOL fVcentre;   // will need to be stored as a window property if more than one control
    WNDPROC lpOldProc;
    CHARFORMAT cf;
    lpOldProc = (WNDPROC)GetProp( hwnd, L"oldproc" );
    switch( msg )
    {
    case WM_TIMER:
        // use timer to ensure text is redrawn before positioning
        switch(wParam)
        {
        case 1:
            KillTimer(hwnd, 1);
            {
                POINTL pt, pt1;
                RECT rcl;
                RECT rclParent;
                int last, height=0, offset, current;
                SendMessage (hwnd, EM_GETSEL, (WPARAM)¤t, 0);
                SendMessage(hwnd, EM_GETRECT, 0, (LPARAM)&rcl);
                GetClientRect(GetParent(hwnd), &rclParent);
                SendMessage (hwnd, EM_SETSEL, 0, -1);
                SendMessage (hwnd, EM_GETSEL, 0, (LPARAM)&last);
                SendMessage(hwnd, EM_POSFROMCHAR, (WPARAM)&pt, 0);
                SendMessage(hwnd, EM_POSFROMCHAR, (WPARAM)&pt1, last);
                // get height of last character
                SendMessage (hwnd, EM_SETSEL, last-1, last);
                memset(&cf, 0, sizeof cf);
                cf.cbSize = sizeof cf;
                SendMessage (hwnd, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
                if(cf.dwMask & CFM_SIZE)
                    height = cf.yHeight/15;
                height = height + pt1.y - pt.y;
                vertoffset = (rcl.bottom - height)/2;
                ifvertoffset > 0) // vertoffset can be < 0 if needed
                {
                    rcl.top = vertoffset;
                    SendMessage(hwnd, EM_SETRECT, 0, (LPARAM)&rcl);
                    InvalidateRect(hwnd, NULL, TRUE);
                }
                SendMessage (hwnd, EM_SETSEL, current, current);
            }
            break;
        }
        break;

        case WM_DESTROY:                         //  Put back old window proc and
                SetWindowLong( hwnd, GWL_WNDPROC, (DWORD)(LRESULT)lpOldProc );
                RemoveProp( hwnd, L"oldproc" );              //  remove window property
                break;

    case WM_KEYUP:
    case WM_CHAR:
    case WM_PASTE:
    case WM_CUT:
    case EM_UNDO:
    case EM_REDO:
    // any message that modifies the text
        if(fVcentre)
            SetTimer(hwnd, 1, 100, NULL);
        break;

    case WM_COMMAND:
        switch (LOWORD(wParam))
        {
        case ID_TFVCENTRE:  // id to centre text
            {
                POINTL pt, pt1;
                RECT rcl;
                RECT rclParent;
                int last, height=0, offset, current;
                fVcentre = !fVcentre;
                SendMessage(hwnd, EM_GETRECT, 0, (LPARAM)&rcl);
                if(fVcentre)
                {
                    GetClientRect(GetParent(hwnd), &rclParent);
                    SendMessage (hwnd, EM_GETSEL, (WPARAM)¤t, 0);
                    SendMessage (hwnd, EM_SETSEL, 0, -1);
                    SendMessage (hwnd, EM_GETSEL, 0, (LPARAM)&last);
                    SendMessage(hwnd, EM_POSFROMCHAR, (WPARAM)&pt, 0);
                    SendMessage(hwnd, EM_POSFROMCHAR, (WPARAM)&pt1, last);
                    // get height of last character
                    SendMessage (hwnd, EM_SETSEL, last-1, last);
                    memset(&cf, 0, sizeof cf);
                    cf.cbSize = sizeof cf;
                    SendMessage (hwnd, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
                    if(cf.dwMask & CFM_SIZE)
                        height = cf.yHeight/15;
                    height = height + pt1.y - pt.y;
                    vertoffset = (rcl.bottom - height)/2;
                    ifvertoffset > 0)
                    {
                        rcl.top = vertoffset 
                        SendMessage(hwnd, EM_SETRECT, 0, (LPARAM)&rcl);
                        InvalidateRect(hwnd, NULL, TRUE);
                    }
                    SendMessage (hwnd, EM_SETSEL, current, current);
                }
                else
                {
                    rcl.top = 0;
                    vertoffset = 0;
                    SendMessage(hwnd, EM_SETRECT, 0, (LPARAM)&rcl);
                    InvalidateRect(hwnd, NULL, TRUE);
                }
            }
            break;
        }
        break;

    }                        //  Pass all non-custom messages to old window proc
    return( CallWindowProc( lpOldProc, hwnd, msg, wParam, lParam ) );
}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文