【问题标题】:RichEdit Vertical Text AligmentRichEdit 垂直文本对齐
【发布时间】:2011-06-01 01:40:45
【问题描述】:

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

【问题讨论】:

    标签: c++ text alignment vertical-alignment trichedit


    【解决方案1】:

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

    【讨论】:

    • 感谢您的帮助,我在 msdn 中搜索了用于设置某些段落格式属性的 PARAFORMAT 结构和 EM_SETPARAFORMAT 消息,但我仍然找不到任何用于垂直对齐的属性。
    【解决方案2】:

    Richedit 接口没有用于此的方法。但是,使用现有消息执行此操作相当简单。使用 EM_POSFROMCHAR 获取控件中第一个和最后一个字符的垂直位置,加上最后一个字符的高度。然后计算垂直居中文本所需的控件顶部的偏移量。然后使用EM_SETRECT消息来调整txt在控件中绘制的位置。

    如果您想在修改文本时动态地执行此操作,您将需要对控件进行子类化并处理适当的消息。参见下面的代码 sn-ps。

    // 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)&current, 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)&current, 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 ) );
    }
    
    

    【讨论】:

      猜你喜欢
      • 2011-09-14
      • 1970-01-01
      • 2013-04-26
      • 2012-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多