概述:
CQsEdit 继承CEdit而来,CQsEdit 没有太多的绘制,只是对背景和边框线进行了绘制,并且对输入字符进行处理。
代码实现如下:
#pragma once
#include "UserMessage.h"
#include "QsInclude.h"
#include <atlmisc.h>
#define ES_COMBO (0x00000200)
#define ES_AUTOSUGGEST ES_COMBO
#define EN_QUERY_SUGGETST_DROP (0x8000)
#define EN_SUGGETST_DROP_HIDE (0x8001)
#define EN_SUGGETST_DROP_SHOW (0x8002)
#define EN_SUGGETST_DROP_SHOW_NEXT (0x8003)
#define EN_SUGGETST_DROP_SHOW_PRE (0x8004)
#define EDIT_STYLE_MASK WINDOW_CUSTOM_STYLE_MASK
typedef bool (*CharFilter)(wchar_t wch);
class CQsEdit :
public CWindowImpl<CQsEdit, CEdit>,
public CImageMgrCtrlBase< CQsEdit>
{
typedef CWindowImpl< CQsEdit, CEdit > theBaseClass;
typedef CImageMgrCtrlBase< CQsEdit> theImageCtrlBaseClass;
BOOL m_bBtnFlag;
CRect rcButton;
Image *m_pImage;
volatile bool m_bDrawBorder;
volatile bool m_bPassword;
CString m_strBkText;
WTL::CFont m_editfont;
public:
DECLARE_WND_SUPERCLASS(_T("QsEdit"), CEdit::GetWndClassName())
BEGIN_MSG_MAP( CQsEdit )
MESSAGE_HANDLER( WM_KILLFOCUS, OnFocusChanged )
MESSAGE_HANDLER( WM_SETFOCUS, OnFocusChanged )
MESSAGE_HANDLER( WM_PAINT, OnPaint )
MESSAGE_HANDLER( WM_ERASEBKGND, OnEraseBKGnd )
MESSAGE_HANDLER( WM_CHAR, OnChar )
MESSAGE_HANDLER( WM_KEYDOWN, OnKeydown )
CHAIN_MSG_MAP( theImageCtrlBaseClass )
DEFAULT_REFLECTION_HANDLER()
END_MSG_MAP()
CQsEdit():
m_bBtnFlag( FALSE ),
m_bDrawBorder( True ),
m_bPassword( false ),
m_fnCharFilter(NULL)
{
}
virtual ~CQsEdit()
{
DeleteQSFont();
}
HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
DWORD dwStyle = 0, DWORD dwExStyle = 0,
ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
{
theBaseClass::Create(hWndParent, rect, szWindowName, dwStyle, dwExStyle, MenuOrID, lpCreateParam);
CRect rtClient;
GetClientRect(&rtClient);
rtClient.MoveToXY( 2 * GetEditBorder(), 2 * GetEditBorder() );
SetRect( &rtClient );
GetRect( &rtClient );
return m_hWnd;
}
BOOL SubclassWindow( HWND hWnd )
{
BOOL bRet = theBaseClass::SubclassWindow( hWnd );
CRect rtClient;
GetClientRect(&rtClient);
rtClient.MoveToXY( 2 * GetEditBorder(), 2 * GetEditBorder() );
SetRect( &rtClient );
GetRect( &rtClient );
return bRet;
}
bool EnabledBorder( bool bFlag )
{
if( m_bDrawBorder != bFlag )
{
m_bDrawBorder = bFlag;
}
return m_bDrawBorder;
}
bool EnabledPassword( bool bFlag )
{
if( m_bPassword != bFlag )
{
m_bPassword = bFlag;
}
return m_bPassword;
}
void SetBkText( LPCTSTR pszText )
{
m_strBkText = pszText;
}
CharFilter SetCharFilter(CharFilter NewFilter)
{
CharFilter oldFilter = m_fnCharFilter;
m_fnCharFilter = NewFilter;
return oldFilter;
}
void DeleteQSFont()
{
if (NULL != m_editfont.m_hFont)
{
m_editfont.DeleteObject();
}
}
void SetQsFont(LPCTSTR fontName,int lfHeight,int lfWeight = FW_BOLD,BYTE fCharSet = DEFAULT_CHARSET)
{
DeleteQSFont();
LOGFONT itemFont;
itemFont.lfCharSet = fCharSet;
itemFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
itemFont.lfEscapement = 0;
memset(itemFont.lfFaceName, 0, LF_FACESIZE);
memcpy_s(itemFont.lfFaceName, LF_FACESIZE, fontName, LF_FACESIZE);
itemFont.lfHeight = lfHeight;
itemFont.lfItalic = FALSE;
itemFont.lfOrientation = 0;
itemFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
itemFont.lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;
itemFont.lfQuality = CLEARTYPE_NATURAL_QUALITY;
itemFont.lfStrikeOut = FALSE;
itemFont.lfUnderline = FALSE;
itemFont.lfWeight = lfWeight;
itemFont.lfWidth = 0;
m_editfont = ::CreateFontIndirect( &itemFont);
SetFont(m_editfont);
}
DWORD SetEditStyle(DWORD dwNewStyle)
{
DWORD dwOldStyle = GetStyle();
BOOL bSucc;
bSucc = ModifyStyle(dwNewStyle, dwOldStyle);
ATLASSERT(bSucc);
return dwOldStyle;
}
static int GetEditBorder()
{
return 1;
}
protected:
LRESULT OnChar( UINT , WPARAM wParam, LPARAM , BOOL& bHandled )
{
bool bAccept;
wchar_t wCh;
wCh = wchar_t(wParam);
if (wCh <= ' ')
{
bHandled = FALSE;
return 0;
}
if (m_fnCharFilter)
{
bAccept = m_fnCharFilter(wchar_t(wParam));
if ( !bAccept )
{
return TRUE;
}
else
{
bHandled = FALSE;
return FALSE;
}
}
else
{
bHandled = FALSE;
}
return 0;
}
LRESULT OnKeyDown( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
{
bHandled = FALSE;
CWindowImpl<CQsEdit, CEdit>* pEdit = this;
TCHAR tchKey = (TCHAR)wParam;
if ( ( 'A' == tchKey ) || ( 'a' == tchKey ) )
{
SHORT sCtrlState = GetKeyState( VK_CONTROL );
if ( sCtrlState & 0X8000 )
{
int nLen = GetWindowTextLength( );
SetSel( 0, nLen, FALSE );
Invalidate();
pEdit = NULL;
}
}
if ( VK_RETURN == tchKey )
{
::SendMessage( GetParent().m_hWnd, WM_EDITRETURN, 0, 0 );
pEdit = NULL;
}
return pEdit != NULL? pEdit->DefWindowProc(uMsg, wParam, lParam): 0;
}
LRESULT OnFocusChanged( UINT , WPARAM , LPARAM , BOOL& bHandled )
{
Invalidate();
bHandled = FALSE;
return 0;
}
LRESULT OnPaint( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& )
{
HWND hwnd = GetFocus();
int len = GetWindowTextLength();
if( ( len > 0 ) || ( hwnd == m_hWnd ) || ( m_strBkText.GetLength() <= 0 ) )
{
if( !m_bPassword )
{
return DefWindowProc( uMsg, wParam, lParam );
}
}
WTL::CPaintDC paintDC( m_hWnd );
paintDC.SetBkMode( TRANSPARENT );
CRect rc;
GetRect( rc );
WTL::CDC memDC;
memDC.CreateCompatibleDC( paintDC.m_hDC );
WTL::CBitmap memBitmap;
memBitmap.CreateCompatibleBitmap( paintDC.m_hDC, rc.Width(), rc.Height() );
HBITMAP hOldBmp = memDC.SelectBitmap( memBitmap );
HFONT hFont = GetDefaultFont();
HFONT hOldFont = memDC.SelectFont( hFont );
memDC.BitBlt( 0, 0, rc.Width(), rc.Height(), paintDC.m_hDC, rc.left, rc.top, SRCCOPY );
CRect textRect( 0, 0, rc.Width(), rc.Height() );
memDC.SetTextColor( RGB( 128, 128, 128 ) );
memDC.DrawText( m_strBkText, m_strBkText.GetLength(), &textRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
paintDC.BitBlt( rc.left, rc.top, rc.Width(), rc.Height(), memDC.m_hDC, 0, 0, SRCCOPY );
CFont font = hFont;
memDC.SelectFont( hOldFont );
memDC.SelectBitmap( hOldBmp );
memDC.DeleteDC();
memBitmap.DeleteObject();
return 0;
}
LRESULT OnEraseBKGnd( UINT , WPARAM wParam, LPARAM , BOOL& )
{
WTL::CDCHandle bkdc( ( HDC ) wParam );
if( m_bDrawBorder )
{
CRect rc;
GetClientRect( rc );
WTL::CDC dc;
dc.CreateCompatibleDC( bkdc.m_hDC );
WTL::CBitmap memBitmap;
memBitmap.CreateCompatibleBitmap( bkdc.m_hDC, rc.Width(), rc.Height() );
HBITMAP hOldBmp = dc.SelectBitmap( memBitmap );
dc.BitBlt( 0, 0, rc.Width(), rc.Height(), bkdc.m_hDC, 0, 0, SRCCOPY );
WTL::CPen pen;
pen.CreatePen( PS_SOLID, 1, RGB( 255, 255, 255 ) );
HPEN hOldPen = dc.SelectPen( pen );
dc.RoundRect( 0, 0, rc.Width(), rc.Height(), 0, 0 );
dc.SelectPen( hOldPen );
bkdc.BitBlt( 0, 0, rc.Width(), rc.Height(), dc.m_hDC, 0, 0, SRCCOPY );
dc.SelectBitmap( hOldBmp );
dc.DeleteDC();
memBitmap.DeleteObject();
pen.DeleteObject();
}
return 0;
}
LRESULT OnGetDlgCode( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& )
{
LRESULT lRes;
BOOL bDropped;
if (lParam && (((LPMSG)lParam)->message == WM_KEYDOWN))
{
WPARAM wNotify;
int vk = (int)((LPMSG)lParam)->wParam;
if ( (GetStyle() & ES_AUTOSUGGEST )
&& !(GetStyle() & ES_MULTILINE )
&& (vk == VK_RETURN || vk == VK_ESCAPE || vk == VK_UP || vk == VK_DOWN) )
{
bDropped = (BOOL)SendMessageW(GetParent(), WM_COMMAND, EN_QUERY_SUGGETST_DROP, 0);
if(vk == VK_UP || vk == VK_DOWN)
{
if (FALSE == bDropped)
{
wNotify = MAKEWPARAM(GetWindowLong(GWL_ID), EN_SUGGETST_DROP_SHOW);
}
else if( TRUE == bDropped && vk == VK_DOWN )
{
wNotify = MAKEWPARAM(GetWindowLong(GWL_ID), EN_SUGGETST_DROP_SHOW_NEXT);
}
else if( TRUE == bDropped && vk == VK_UP )
{
wNotify = MAKEWPARAM(GetWindowLong(GWL_ID), EN_SUGGETST_DROP_SHOW_PRE);
}
}
if(vk == VK_RETURN || vk == VK_ESCAPE)
{
wNotify = MAKEWPARAM(GetWindowLong(GWL_ID), EN_SUGGETST_DROP_HIDE);
}
SendMessage(GetParent(), WM_COMMAND, wNotify, (LPARAM)m_hWnd);
lRes = DLGC_WANTARROWS;
}
else
{
lRes = DefWindowProc( uMsg, wParam, lParam);
}
}
else
{
lRes = DefWindowProc( uMsg, wParam, lParam);
lRes |= DLGC_WANTARROWS | DLGC_WANTTAB | DLGC_WANTALLKEYS | DLGC_WANTMESSAGE | DLGC_HASSETSEL;
}
return lRes;
}
LRESULT OnKeydown( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
{
LRESULT lRes = 0;
BOOL bDropped;
int nVirtKey = (int) wParam;
WPARAM wNotify = 0;
int vk = nVirtKey;
if ( (GetStyle() & ES_AUTOSUGGEST ) && !(GetStyle() & ES_MULTILINE )
&& (vk == VK_RETURN || vk == VK_ESCAPE || vk == VK_UP || vk == VK_DOWN) )
{
bDropped = (BOOL)SendMessageW(GetParent(), WM_COMMAND, EN_QUERY_SUGGETST_DROP, 0);
if(vk == VK_UP || vk == VK_DOWN)
{
if (FALSE == bDropped)
{
wNotify = MAKEWPARAM(GetWindowLong(GWL_ID), EN_SUGGETST_DROP_SHOW);
}
else if( TRUE == bDropped && vk == VK_DOWN )
{
wNotify = MAKEWPARAM(GetWindowLong(GWL_ID), EN_SUGGETST_DROP_SHOW_NEXT);
}
else if( TRUE == bDropped && vk == VK_UP )
{
wNotify = MAKEWPARAM(GetWindowLong(GWL_ID), EN_SUGGETST_DROP_SHOW_PRE);
}
}
if(vk == VK_RETURN || vk == VK_ESCAPE)
{
wNotify = MAKEWPARAM(GetWindowLong(GWL_ID), EN_SUGGETST_DROP_HIDE);
}
::PostMessage(GetParent(), WM_COMMAND, wNotify, (LPARAM)m_hWnd);
bHandled = FALSE;
}
else
{
return DefWindowProc( uMsg, wParam, lParam );
}
return lRes;
}
private:
UINT GetEditTextFormat(const LONG lStyle)
{
UINT uFormat = DT_SINGLELINE;
if ( (lStyle & ES_CENTER)==ES_CENTER )
uFormat |= DT_CENTER;
else if ( (lStyle & ES_RIGHT)==ES_RIGHT )
uFormat |= DT_RIGHT;
else if ( (lStyle & ES_LEFT) == ES_LEFT )
uFormat |= DT_LEFT;
else
uFormat |= DT_CENTER;
return uFormat;
}
private:
CharFilter m_fnCharFilter;
CRect m_rtBkText;
};
|