如何使用WinAPI中的EN_PROTECT来部分保护Rich Edit控件中的字符?

我正在尝试使用WinAPI通过C在Rich Edit控件中创建类似于控制台的行为,并且希望以前输入的信息受到保护,以防止用户编辑。

除了我想限制对控件中现有文本的编辑之外,该控件似乎通常可以很好地用于我的目的。

全局变量

WNDPROC OldMultiLineIO;
HFONT font_all = NULL;
int nWindowCharsX,nWindowCharsY;
int nWindowX,nWindowY,nCharX,nCharY;

LRESULT CALLBACK WndProc      ( HWND,UINT,WPARAM,LPARAM );
LRESULT CALLBACK MultiLineProc( HWND,LPARAM );

丰富的编辑控件的创建和设置所需的背景颜色/字体:

HWND wMultiLine( HWND hwnd,HFONT font_all )
{
    Loadlibrary( TEXT( "Riched20.dll" ) );
    HWND multiline_io = CreateWindowEx(
                            WS_EX_CLIENTEDGE,RICHEDIT_CLASS,WS_CHILD | WS_VISIBLE   |
                            ES_LEFT  | ES_MULTILINE | ES_AUTOVSCROLL,hwnd,//set in WM_SIZE
                            (HMENU)IDC_MULTILINEIO,(HINSTANCE)GetWindowLong( hwnd,GWL_HINSTANCE ),NULL );

    SendMessage( multiline_io,EM_SETBKGNDCOLOR,BKGD_GLOBAL );
    SendMessage( multiline_io,WM_setfONT,(WPARAM)font_all,0 );

    return multiline_io;
}

multiline_io控件的窗口过程(子窗口)

LRESULT CALLBACK MultiLineProc( HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam )
{

    static CHARFORMAT2W cf = { 0 };
    static wchar_t   * retstring;
    static LONG last_char_posn;
    static CHARRANGE current_text;

    cf.cbSize = sizeof( CHARFORMAT2W );
    cf.dwMask = CFM_COLOR;

    switch( msg )
    {
        case WM_CHAR:
        {

            switch( wParam )
            {
                case 0x08:
                    //backspace
                    break;
                case 0x09:
                    //tab
                    break;
                case 0x0D:
                    //carriage return

                    //retstring = NULL;
                    //retstring = getInput( hwnd,last_char_posn,0 );

                    //get range of existing text in rich edit control
                    last_char_posn = lastCharIndex( hwnd,false );
                    current_text.cpmin = 0;
                    current_text.cpmax = LOWORD( last_char_posn );

                    //as per MSDN to receive EN_PROTECTED notifications,set the mask
                    SendMessage( hwnd,EM_SETEVENTMASK,(LPARAM)Enm_PROTECTED );

                    //set parameters to enable protection
                    cf.dwEffects = CFE_PROTECTED;
                    cf.dwMask    = CFM_PROTECTED | CFM_COLOR;
                    //apply protection to the existing text
                    SendMessage( hwnd,EM_EXSETSEL,(LPARAM)&current_text );
                    SendMessage( hwnd,EM_SETCHARFORMAT,SCF_ALL,(LPARAM)&cf );

                    //reset colour back to white for new input
                    cf.dwMask = CFM_COLOR;
                    cf.crTextColor = FRGD_GENERAL;
                    SendMessage( hwnd,SCF_SELECTION,(LPARAM)&cf );

                    break;

                case 0x0A:
                    //line feed
                    break;
                case 0x1B:
                    //escape
                    break;
                default:

                    last_char_posn = lastCharIndex( hwnd,false );
                    printf( "Def: %d %ld\n",LOWORD( last_char_posn ),current_text.cpmax );

                    break;
                }
            }

            break;
        }
    }
    return CallWindowProc( OldMultiLineIO,msg,wParam,lParam);
}

父窗口过程

我必须承认,我不完全确定父级和多行窗口过程之间的交互如何工作,因为这是我首次涉足GUI编程。在此父过程中,我创建了几个子窗口来显示一些数据,徽标和多行富文本编辑控件。

LRESULT CALLBACK WndProc( HWND hwnd,LPARAM lParam )
{

    static HBITMAP logo_hBitmap;
    static HBRUSH txt_hBrush = NULL;
    static HWND txt_acrloaded,multiline_io;
    static RECT hwnd_rect;
    static POINT point_diff_acrloaded;

    static CHARFORMAT2W cf = { 0 };

    point_diff_acrloaded.x = 230;
    point_diff_acrloaded.y = 25;

    if ( NULL == font_all ) font_all =

        CreateFont( 26,FW_REGULAR,FALSE,DEFAULT_CHARSET,OUT_TT_PRECIS,CLIP_DEFAULT_PRECIS,CLEARTYPE_QUALITY,VARIABLE_PITCH,TEXT( "Segoe UI" ) );

    //don't use GetWindowRect,we need the client area,which is different
    getclientRect( hwnd,&hwnd_rect );


    switch( msg )
    {
        case WM_CREATE:
        {
                cf.cbSize = sizeof( CHARFORMAT2W );
                cf.dwMask = CFM_COLOR;
                cf.crTextColor = FRGD_GENERAL;

            /*CHILD WINDOW LOAD INFO*/

            txt_acrloaded = wTextLoaded( hwnd,hwnd_rect,point_diff_acrloaded,font_all,lParam );

            /* LOGO WINDOW */

            logo_hBitmap = wLogo( hwnd,point_diff_acrloaded );


            /* MULTILINE USER I/O WINDOW */

            multiline_io = wMultiLine( hwnd,font_all );
            SendMessage( multiline_io,(LPARAM)&cf );


            TEXTMETRIC tm;
            HDC hdc = GetDC( multiline_io );

            SelectObject( hdc,(HGDIOBJ)font_all );
            GetTextMetrics( hdc,&tm );
            ReleaseDC( multiline_io,hdc );

            nCharX = tm.tmAveCharWidth; //10 avg,49 max
            nCharY = tm.tmHeight;       //25

            setfocus( multiline_io );

            OldMultiLineIO = (WNDPROC) SetWindowLong ( multiline_io,GWL_WNDPROC,(LONG) MultiLineProc );

            break;
        }
        case WM_SIZE:      //resize the child windows based on an update of WM_SIZE
        {

            MoveWindow( txt_acrloaded,( hwnd_rect.right - hwnd_rect.left ) - point_diff_acrloaded.x,point_diff_acrloaded.x,point_diff_acrloaded.y,TRUE ); //move child window as parent is resized

            MoveWindow( multiline_io,70,LOWORD(lParam),HIWORD(lParam),TRUE ); //70 pixels y-offset

            nWindowX = LOWORD( lParam );
            nWindowCharsX = max( 1,nWindowX/nCharX );

            nWindowY = HIWORD( lParam );
            nWindowCharsY = max( 1,nWindowY/nCharY );

            setfocus( multiline_io );
            break;
        }


        case WM_CTLCOLORSTATIC:
        {
            HDC hdc_acrload = (HDC)wParam;
            SetTextColor( hdc_acrload,FRGD_ACRLOADED );
            SetBkColor  ( hdc_acrload,BKGD_GLOBAL );

            if( NULL == txt_hBrush ) txt_hBrush = CreateSolidBrush( BKGD_GLOBAL );

            return (INT_PTR)txt_hBrush;
        }

        case WM_PAINT:
        {
            BITMAP bitmap;
            HGDIOBJ old_bitmap;
            HDC logo_hdc,logo_hdcmem;
            PAINTSTRUCT ps;

            logo_hdc    = BeginPaint( hwnd,&ps );
            logo_hdcmem = CreateCompatibleDC( logo_hdc );

            old_bitmap = SelectObject( logo_hdcmem,logo_hBitmap );

            GetObject( logo_hBitmap,sizeof( bitmap ),&bitmap );
            BitBlt( logo_hdc,5,bitmap.bmWidth,bitmap.bmHeight,logo_hdcmem,SRCCOPY );

            SelectObject( logo_hdcmem,old_bitmap );
            DeleteDC( logo_hdcmem );

            EndPaint( hwnd,&ps );
            DeleteDC( logo_hdc );
            DeleteObject( old_bitmap );

            setfocus( multiline_io );

            break;
        }

        case WM_NOTIFY:

            if ( EN_PROTECTED == ( (LPnmHDR)lParam )->code )
            {
                printf("@ EN_PROTECTED CASE\n");
                return 1;
            }
            break;

        case WM_DESTROY:

            PostQuitMessage( 0 );

            break;

        default:
            return DefWindowProcW( hwnd,lParam );
    }

    return 0;
}

lastCharIndex函数,如果将true传递给该函数,则要么发回最后一个字符的像素位置,要么发回索引

extern LONG lastCharIndex( HWND hwnd,BOOL want_coord )
{
    RECT r;
    POINT pt;

    getclientRect( hwnd,&r );

    pt.x = ( r.right - r.left ) -1;
    pt.y = ( r.bottom - r.top ) -1;

    //get index of last char within window
    //then retrieve coordinates of that char
    LONG n = SendMessage( hwnd,EM_CHARFROMPOS,(LPARAM)&pt );
    LONG x_last = SendMessage( hwnd,EM_POSFROMCHAR,n,0 );

    //last char co-ordinates
    if( true == want_coord ) return x_last;
    return n;
}

返回父窗口过程的WM_NOTIFY案例。 printf语句用于调试,并显示在代码块控制的单独控制台中。 根据MSDN,我们被告知返回一个非零值以防止进行编辑操作。

  case WM_NOTIFY:

     if ( EN_PROTECTED == ( (LPnmHDR)lParam )->code )
     {
        printf("@ EN_PROTECTED CASE\n");
        return 1;
     }
     break;

观察:

在输入一些文本并按Enter之后。输入的文本是在Rich Edit控件中选择的-就像有人用鼠标选择文本一样突出显示,因此SendMessage( hwnd,(LPARAM)&current_text );命令可能有效。

我的调试窗口还会在 WM_NOTIFY 中输出printf语句,因此父窗口似乎已收到 EN_PROTECTED 通知代码。

但是,文本不受保护,我可以删除/覆盖等。

有人可以解释出什么问题了吗?我还想知道调用方如何处理WM_NOTIFY的返回值?我是否打算自己在多行窗口过程中显式地处理它?

引用的MSDN: EN_PROTECTED PARAMETERWM_NOTIFYENPROTECTED STRUCTNMHDR STRUCT

asdff_px 回答:如何使用WinAPI中的EN_PROTECT来部分保护Rich Edit控件中的字符?

暂时没有好的解决方案,如果你有好的解决方案,请发邮件至:iooj@foxmail.com
本文链接:https://www.f2er.com/2827283.html

大家都在问