我正在尝试使用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)¤t_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)¤t_text );
命令可能有效。
我的调试窗口还会在 WM_NOTIFY 中输出printf语句,因此父窗口似乎已收到 EN_PROTECTED 通知代码。
但是,文本不受保护,我可以删除/覆盖等。
有人可以解释出什么问题了吗?我还想知道调用方如何处理WM_NOTIFY的返回值?我是否打算自己在多行窗口过程中显式地处理它?
引用的MSDN: EN_PROTECTED PARAMETER, WM_NOTIFY, ENPROTECTED STRUCT, NMHDR STRUCT