WTL 介面設計篇(CSkinEdit)
標頭檔案宣告(CSkinEdit.h):
#pragma once
#include "SkinManager.h"
// 不支援滾動條皮膚
// 圖片背景支援不完整
// Edit控制元件必須是ES_MULTILINE風格,SetMarginsEx才能生效,ES_MULTILINE風格好像不能動態修改,只能在生成控制元件時指定
class CSkinEdit : public CWindowImpl<CSkinEdit, CEdit>
{
public:
CSkinEdit(void);
~CSkinEdit(void);
BEGIN_MSG_MAP_EX(CSkinEdit)
MSG_WM_CREATE(OnCreate)
MSG_WM_NCCALCSIZE(OnNcCalcSize)
MSG_WM_ERASEBKGND(OnEraseBkgnd)
MSG_WM_NCPAINT(OnNcPaint)
MSG_OCM_CTLCOLOREDIT(OnCtlColor)
MSG_WM_LBUTTONDOWN(OnLButtonDown)
MSG_WM_LBUTTONUP(OnLButtonUp)
MSG_WM_MOUSEMOVE(OnMouseMove)
MSG_WM_MOUSELEAVE(OnMouseLeave)
MSG_WM_SETFOCUS(OnSetFocus)
MSG_WM_KILLFOCUS(OnKillFocus)
MSG_WM_SIZE(OnSize)
MSG_WM_DESTROY(OnDestroy)
DEFAULT_REFLECTION_HANDLER()
END_MSG_MAP()
public:
BOOL SetBgNormalPic(LPCTSTR lpszFileName, RECT * lpNinePart = NULL);
BOOL SetBgHotPic(LPCTSTR lpszFileName, RECT * lpNinePart = NULL);
BOOL SetIconPic(LPCTSTR lpszFileName);
void SetTransparent(BOOL bTransparent, HDC hBgDC);
void SetDefaultText(LPCTSTR lpszText);
BOOL IsDefaultText();
void SetDefaultTextMode(BOOL bIsDefText);
void SetMarginsEx(int nLeft, int nTop, int nRight, int nBottom); // 設定上下左右邊距函式
void SetMultiLine(BOOL bMultiLine = TRUE);
BOOL SubclassWindow(HWND hWnd);
private:
int OnCreate(LPCREATESTRUCT lpCreateStruct);
LRESULT OnNcCalcSize(BOOL bCalcValidRects, LPARAM lParam);
BOOL OnEraseBkgnd(CDCHandle dc);
void OnNcPaint(CRgnHandle rgn);
HBRUSH OnCtlColor(CDCHandle dc, CEdit edit);
void OnLButtonDown(UINT nFlags, CPoint point);
void OnLButtonUp(UINT nFlags, CPoint point);
void OnMouseMove(UINT nFlags, CPoint point);
void OnMouseLeave();
void OnSetFocus(CWindow wndOld);
void OnKillFocus(CWindow wndFocus);
void OnSize(UINT nType, CSize size);
void OnDestroy();
BOOL StartTrackMouseLeave();
void CalcCenterRect(CRect& rcDest, int cx, int cy, CRect& rcCenter);
void SetCenterInSingleLine();
void DrawParentWndBg(HDC hDC);
private:
CImageEx * m_lpBgImgN;
CImageEx * m_lpBgImgH;
CImageEx * m_lpIconImg;
int m_nIconWidth;
BOOL m_bFocus, m_bPress, m_bHover, m_bMouseTracking;
BOOL m_bTransparent;
HDC m_hBgDC;
BOOL m_bIsDefText;
CString m_strDefText;
TCHAR m_cPwdChar;
BOOL m_bMultiLine;
};
原始碼定義(CSkinEdit.cpp):
#include "StdAfx.h"
#include "SkinEdit.h"
CSkinEdit::CSkinEdit(void)
{
m_lpBgImgN = NULL;
m_lpBgImgH = NULL;
m_lpIconImg = NULL;
m_nIconWidth = 0;
m_bFocus = m_bPress = m_bHover = m_bMouseTracking = FALSE;
m_bTransparent = FALSE;
m_hBgDC = NULL;
m_bIsDefText = FALSE;
m_cPwdChar = 0;
m_bMultiLine = FALSE;
}
CSkinEdit::~CSkinEdit(void)
{
}
BOOL CSkinEdit::SetBgNormalPic(LPCTSTR lpszFileName, RECT * lpNinePart/* = NULL*/)
{
CSkinManager::GetInstance()->ReleaseImage(m_lpBgImgN);
m_lpBgImgN = CSkinManager::GetInstance()->GetImage(lpszFileName);
if (m_lpBgImgN != NULL)
m_lpBgImgN->SetNinePart(lpNinePart);
return (m_lpBgImgN != NULL) ? TRUE : FALSE;
}
BOOL CSkinEdit::SetBgHotPic(LPCTSTR lpszFileName, RECT * lpNinePart/* = NULL*/)
{
CSkinManager::GetInstance()->ReleaseImage(m_lpBgImgH);
m_lpBgImgH = CSkinManager::GetInstance()->GetImage(lpszFileName);
if (m_lpBgImgH != NULL)
m_lpBgImgH->SetNinePart(lpNinePart);
return (m_lpBgImgH != NULL) ? TRUE : FALSE;
}
BOOL CSkinEdit::SetIconPic(LPCTSTR lpszFileName)
{
CSkinManager::GetInstance()->ReleaseImage(m_lpIconImg);
m_lpIconImg = CSkinManager::GetInstance()->GetImage(lpszFileName);
if (m_lpIconImg != NULL)
m_nIconWidth = m_lpIconImg->GetWidth();
return (m_lpIconImg != NULL) ? TRUE : FALSE;
}
void CSkinEdit::SetTransparent(BOOL bTransparent, HDC hBgDC)
{
m_bTransparent = bTransparent;
m_hBgDC = hBgDC;
}
void CSkinEdit::SetDefaultText(LPCTSTR lpszText)
{
m_strDefText = lpszText;
}
BOOL CSkinEdit::IsDefaultText()
{
return m_bIsDefText;
}
void CSkinEdit::SetDefaultTextMode(BOOL bIsDefText)
{
if (bIsDefText == m_bIsDefText)
return;
m_bIsDefText = bIsDefText;
if (m_bIsDefText)
{
m_cPwdChar = GetPasswordChar();
SetPasswordChar(0);
SetWindowText(m_strDefText);
}
else
{
SetPasswordChar(m_cPwdChar);
SetWindowText(_T(""));
}
}
// 設定上下左右邊距函式
void CSkinEdit::SetMarginsEx(int nLeft, int nTop, int nRight, int nBottom)
{
CRect rtClient;
GetClientRect(rtClient);
CRect rt(rtClient.left + nLeft, rtClient.top + nTop,
rtClient.right - nRight, rtClient.bottom - nBottom);
SetRectNP(rt);
}
void CSkinEdit::SetMultiLine(BOOL bMultiLine/* = TRUE*/)
{
m_bMultiLine = bMultiLine;
if (!m_bMultiLine && IsWindow()) // 單行模式居中
SetCenterInSingleLine();
}
BOOL CSkinEdit::SubclassWindow(HWND hWnd)
{
__super::SubclassWindow(hWnd);
SetDefaultText(m_strDefText);
if (!m_bMultiLine) // 單行模式居中
SetCenterInSingleLine();
return TRUE;
}
int CSkinEdit::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
SetMsgHandled(FALSE);
return 0;
}
LRESULT CSkinEdit::OnNcCalcSize(BOOL bCalcValidRects, LPARAM lParam)
{
SetMsgHandled(FALSE);
if (NULL == m_lpIconImg || m_lpIconImg->IsNull())
return 0;
if (bCalcValidRects)
{
LPNCCALCSIZE_PARAMS pParam = (LPNCCALCSIZE_PARAMS)lParam;
pParam->rgrc[0].right -= m_nIconWidth;
pParam->rgrc[1] = pParam->rgrc[0];
}
return 0;
}
BOOL CSkinEdit::OnEraseBkgnd(CDCHandle dc)
{
return TRUE;
}
void CSkinEdit::OnNcPaint(CRgnHandle rgn)
{
CRect rcWindow;
GetWindowRect(&rcWindow);
CRect rcClient;
GetClientRect(&rcClient);
ClientToScreen(&rcClient);
rcClient.OffsetRect(-rcWindow.left, -rcWindow.top);
rcWindow.OffsetRect(-rcWindow.left, -rcWindow.top);
HDC hDC = ::GetWindowDC(m_hWnd);
// RECT rcClip = {0};
// ::GetClipBox(hDC, &rcClip);
// HRGN hOldRgn = ::CreateRectRgnIndirect(&rcClip);
// HRGN hRgn = ::CreateRectRgnIndirect(&rcClient);
// ::ExtSelectClipRgn(hDC, hRgn, RGN_DIFF);
CRect rcIcon;
HRGN hRgn2 = NULL;
if (m_lpIconImg != NULL && !m_lpIconImg->IsNull())
{
int cxIcon = m_lpIconImg->GetWidth();
int cyIcon = m_lpIconImg->GetHeight();
CalcCenterRect(rcWindow, cxIcon, cyIcon, rcIcon);
rcIcon.right = rcWindow.right - 2;
rcIcon.left = rcIcon.right - cxIcon;
//hRgn2 = ::CreateRectRgnIndirect(&rcIcon);
//::ExtSelectClipRgn(hDC, hRgn2, RGN_OR);
}
if (m_bTransparent)
DrawParentWndBg(hDC);
if (m_bHover)
{
if (m_lpBgImgH != NULL && !m_lpBgImgH->IsNull())
{
m_lpBgImgH->Draw2(hDC, rcWindow);
}
else
{
if (m_lpBgImgN != NULL && !m_lpBgImgN->IsNull())
m_lpBgImgN->Draw2(hDC, rcWindow);
}
}
else
{
if (m_lpBgImgN != NULL && !m_lpBgImgN->IsNull())
m_lpBgImgN->Draw2(hDC, rcWindow);
}
if (m_lpIconImg != NULL && !m_lpIconImg->IsNull())
m_lpIconImg->Draw2(hDC, rcIcon);
// ::SelectClipRgn(hDC, hOldRgn);
// ::DeleteObject(hOldRgn);
// ::DeleteObject(hRgn);
// if (hRgn2 != NULL)
// ::DeleteObject(hRgn2);
::ReleaseDC(m_hWnd, hDC);
// HPEN hPen, hOldPen;
// HBRUSH hBrush, hOldBrush;
//
// hPen = ::CreatePen(PS_INSIDEFRAME | PS_SOLID, 1, RGB(163, 194, 212));
// hBrush = ::CreateSolidBrush(RGB(255, 255, 255));
//
// hOldPen = (HPEN)::SelectObject(hDC, hPen);
// hOldBrush = (HBRUSH)::SelectObject(hDC, hBrush);
// ::Rectangle(hDC, rcWindow.left, rcWindow.top, rcWindow.right, rcWindow.bottom);
// ::SelectObject(hDC, hOldPen);
// ::SelectObject(hDC, hOldBrush);
//
// ::DeleteObject(hPen);
// ::DeleteObject(hBrush);
}
// void CSkinEdit::OnPaint(CDCHandle dc)
// {
// CPaintDC PaintDC(m_hWnd);
//
// CRect rcClient;
// GetClientRect(&rcClient);
//
// PaintDC.FillSolidRect(&rcClient, RGB(255,0,0));
//
// SetMsgHandled(FALSE);
// }
HBRUSH CSkinEdit::OnCtlColor(CDCHandle dc, CEdit edit)
{
//::SetBkMode(dc, TRANSPARENT);
if (m_bIsDefText)
::SetTextColor(dc, RGB(128,128,128));
else
::SetTextColor(dc, RGB(0,0,0));
return (HBRUSH)NULL_BRUSH;
}
void CSkinEdit::OnLButtonDown(UINT nFlags, CPoint point)
{
m_bPress = TRUE;
::InvalidateRect(m_hWnd, NULL, FALSE);
SetMsgHandled(FALSE);
}
void CSkinEdit::OnLButtonUp(UINT nFlags, CPoint point)
{
if (m_bPress)
{
m_bPress = FALSE;
::InvalidateRect(m_hWnd, NULL, FALSE);
}
SetMsgHandled(FALSE);
}
void CSkinEdit::OnMouseMove(UINT nFlags, CPoint point)
{
if (!m_bMouseTracking)
{
StartTrackMouseLeave();
m_bMouseTracking = TRUE;
m_bHover = TRUE;
::InvalidateRect(m_hWnd, NULL, FALSE);
}
SetMsgHandled(FALSE);
}
void CSkinEdit::OnMouseLeave()
{
m_bMouseTracking = FALSE;
m_bHover = FALSE;
::InvalidateRect(m_hWnd, NULL, FALSE);
SetMsgHandled(FALSE);
}
void CSkinEdit::OnSetFocus(CWindow wndOld)
{
if (m_bIsDefText)
{
m_bIsDefText = FALSE;
SetPasswordChar(m_cPwdChar);
SetWindowText(_T(""));
}
m_bFocus = TRUE;
::InvalidateRect(m_hWnd, NULL, FALSE);
SetMsgHandled(FALSE);
}
void CSkinEdit::OnKillFocus(CWindow wndFocus)
{
if (GetWindowTextLength() <= 0 && !m_strDefText.IsEmpty())
{
m_bIsDefText = TRUE;
m_cPwdChar = GetPasswordChar();
SetPasswordChar(0);
SetWindowText(m_strDefText);
}
m_bFocus = FALSE;
::InvalidateRect(m_hWnd, NULL, FALSE);
SetMsgHandled(FALSE);
}
void CSkinEdit::OnSize(UINT nType, CSize size)
{
DefWindowProc();
if (!m_bMultiLine) // 單行模式居中
SetCenterInSingleLine();
}
void CSkinEdit::OnDestroy()
{
SetMsgHandled(FALSE);
CSkinManager::GetInstance()->ReleaseImage(m_lpBgImgN);
CSkinManager::GetInstance()->ReleaseImage(m_lpBgImgH);
CSkinManager::GetInstance()->ReleaseImage(m_lpIconImg);
}
BOOL CSkinEdit::StartTrackMouseLeave()
{
TRACKMOUSEEVENT tme = { 0 };
tme.cbSize = sizeof(tme);
tme.dwFlags = TME_LEAVE;
tme.hwndTrack = m_hWnd;
return _TrackMouseEvent(&tme);
}
void CSkinEdit::CalcCenterRect(CRect& rcDest, int cx, int cy, CRect& rcCenter)
{
int x = (rcDest.Width() - cx + 1) / 2;
int y = (rcDest.Height() - cy + 1) / 2;
rcCenter = CRect(rcDest.left+x, rcDest.top+y, rcDest.left+x+cx, rcDest.top+y+cy);
}
void CSkinEdit::SetCenterInSingleLine()
{
CRect rcClient;
GetClientRect(&rcClient);
CDCHandle dc = ::GetDC(m_hWnd);
TEXTMETRIC tm = {0};
dc.GetTextMetrics(&tm);
int nFontHeight = tm.tmHeight + tm.tmExternalLeading;
int nMargin = (rcClient.Height() - nFontHeight) / 2;
::ReleaseDC(m_hWnd, dc);
rcClient.DeflateRect(0, nMargin);
SetRectNP(&rcClient);
}
void CSkinEdit::DrawParentWndBg(HDC hDC)
{
HWND hParentWnd = ::GetParent(m_hWnd);
CRect rcWindow;
GetWindowRect(&rcWindow);
::ScreenToClient(hParentWnd, (LPPOINT)&rcWindow);
::ScreenToClient(hParentWnd, ((LPPOINT)&rcWindow)+1);
::BitBlt(hDC, 0, 0, rcWindow.Width(), rcWindow.Height(), m_hBgDC, rcWindow.left, rcWindow.top, SRCCOPY);
}
相關文章
- WTL 介面設計篇(CSkinListCtrl)
- Thrift RPC 系列教程(5)—— 介面設計篇:struct & enum設計RPCStruct
- 一篇帶你入門面向介面程式設計程式設計
- 【介面功能設計】TopThink介面功能設計建議
- API介面設計API
- 介面設計分析
- 【設計模式】第六篇:來康康介面卡模式設計模式
- 《最佳化介面設計的思路》系列:第四篇—介面的許可權控制
- 後臺介面設計之表格設計
- 介面設計標準
- 轉賬介面設計
- RPC呼叫介面設計RPC
- 面向介面程式設計程式設計
- 《JavaScript設計模式與開發實踐》模式篇(14)—— 介面卡模式JavaScript設計模式
- QT硬體介面設計QT
- 介面卡設計模式設計模式
- Angular Public API 介面設計AngularAPI
- 微信模板介面設計
- 介面設計的那些事
- (03)Flink 程式設計介面程式設計
- API 介面設計規範API
- 自適應介面設計
- 《最佳化介面設計的思路》系列:第三篇—留下使用者呼叫介面的痕跡
- 【乾貨】遊戲介面設計 (一)核心設計遊戲
- Java設計模式之介面卡設計模式Java設計模式
- 介面設計方法 — 3. 字典功能的設計
- 如何設計出“好看”的UI介面(二):4個步驟,搞定介面設計UI
- Java進階篇設計模式之四 -----介面卡模式和橋接模式Java設計模式橋接
- java 介面,介面的特性,介面實現多型,面向介面程式設計Java多型程式設計
- 【乾貨】遊戲介面設計 (四)體驗設計遊戲
- 【乾貨】遊戲介面設計 (五)表現設計遊戲
- 【乾貨】遊戲介面設計 (三)資訊設計遊戲
- 【乾貨】遊戲介面設計 (二)結構設計遊戲
- 【設計模式】介面卡模式設計模式
- 介面自動化用例設計
- 設計模式:介面卡模式設計模式
- PHP 設計模式之流介面模式PHP設計模式
- 設計模式-介面卡模式設計模式