836 lines
20 KiB
C++
836 lines
20 KiB
C++
/*---------------------------------------------------------------------------*/
|
|
// Author : hiyohiyo
|
|
// Mail : hiyohiyo@crystalmark.info
|
|
// Web : https://crystalmark.info/
|
|
// License : MIT License
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
#include "stdafx.h"
|
|
#include "ComboBoxFx.h"
|
|
|
|
#if _MSC_VER <= 1310
|
|
#define ON_WM_MOUSEHOVER() \
|
|
{ 0x2A1 /*WM_MOUSEHOVER*/, 0, 0, 0, AfxSig_vwp, \
|
|
(AFX_PMSG)(AFX_PMSGW) \
|
|
(static_cast< void (AFX_MSG_CALL CWnd::*)(UINT, CPoint) > (OnMouseHover)) },
|
|
|
|
#define ON_WM_MOUSELEAVE() \
|
|
{ 0x2A3 /*WM_MOUSELEAVE*/, 0, 0, 0, AfxSig_vv, \
|
|
(AFX_PMSG)(AFX_PMSGW) \
|
|
(static_cast< void (AFX_MSG_CALL CWnd::*)(void) > (OnMouseLeave)) },
|
|
#endif
|
|
|
|
////------------------------------------------------
|
|
// CComboBoxFx
|
|
////------------------------------------------------
|
|
|
|
CComboBoxFx::CComboBoxFx()
|
|
{
|
|
// Control
|
|
m_X = 0;
|
|
m_Y = 0;
|
|
m_ZoomRatio = 1.0;
|
|
m_bHighContrast = FALSE;
|
|
m_bDarkMode = FALSE;
|
|
m_RenderMode = SystemDraw;
|
|
m_Margin.top = 0;
|
|
m_Margin.left = 0;
|
|
m_Margin.bottom = 0;
|
|
m_Margin.right = 0;
|
|
|
|
// Alpha/Glass
|
|
m_Alpha = 255;
|
|
m_GlassColor = RGB(255, 255, 255);
|
|
m_GlassAlpha = 255;
|
|
|
|
// Image
|
|
m_ImageCount = 0;
|
|
m_ImagePath = _T("");
|
|
m_BkDC = NULL;
|
|
m_bBkBitmapInit = FALSE;
|
|
m_bBkLoad = FALSE;
|
|
|
|
// Font
|
|
m_TextAlign = SS_LEFT;
|
|
m_TextColor = RGB(0, 0, 0);
|
|
m_TextColorSelected = RGB(255, 255, 255);
|
|
m_BkColor = RGB(255, 255, 255);
|
|
m_BkColorSelected = RGB(230, 230, 230);
|
|
m_TextColorHc = RGB(255, 255, 255);
|
|
m_TextColorSelectedHc = RGB(0, 0, 0);
|
|
m_BkColorHc = RGB(0, 0, 0);
|
|
m_BkColorSelectedHc = RGB(0, 255, 255);
|
|
m_FontHeight = 16;
|
|
m_FontRender = CLEARTYPE_NATURAL_QUALITY;
|
|
|
|
// Mouse
|
|
m_bHover = FALSE;
|
|
m_bFocas = FALSE;
|
|
m_bTrackingNow = FALSE;
|
|
m_bHandCursor = FALSE;
|
|
}
|
|
|
|
CComboBoxFx::~CComboBoxFx()
|
|
{
|
|
m_BkBrush.DeleteObject();
|
|
}
|
|
|
|
IMPLEMENT_DYNAMIC(CComboBoxFx, CComboBox)
|
|
|
|
BEGIN_MESSAGE_MAP(CComboBoxFx, CComboBox)
|
|
//{{AFX_MSG_MAP(CComboBoxFx)
|
|
ON_WM_CTLCOLOR()
|
|
ON_WM_MOUSEMOVE()
|
|
ON_WM_MOUSEHOVER()
|
|
ON_WM_MOUSELEAVE()
|
|
ON_WM_KILLFOCUS()
|
|
ON_WM_SETFOCUS()
|
|
ON_WM_SETCURSOR()
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
//------------------------------------------------
|
|
// Control
|
|
//------------------------------------------------
|
|
|
|
BOOL CComboBoxFx::InitControl(int x, int y, int width, int height, double zoomRatio, CDC* bkDC,
|
|
LPCWSTR imagePath, int imageCount, DWORD textAlign, int renderMode, BOOL bHighContrast, BOOL bDarkMode,
|
|
COLORREF bkColor, COLORREF bkColorSelected, COLORREF glassColor, BYTE glassAlpha)
|
|
{
|
|
m_X = (int)(x * zoomRatio);
|
|
m_Y = (int)(y * zoomRatio);
|
|
m_ZoomRatio = zoomRatio;
|
|
m_CtrlSize.cx = (int)(width * zoomRatio);
|
|
m_CtrlSize.cy = (int)(height * zoomRatio);
|
|
MoveWindow(m_X, m_Y, m_CtrlSize.cx, m_CtrlSize.cy);
|
|
|
|
m_BkDC = bkDC;
|
|
m_ImagePath = imagePath;
|
|
m_ImageCount = imageCount;
|
|
m_RenderMode = renderMode;
|
|
|
|
m_BkColor = bkColor;
|
|
m_BkColorSelected = bkColorSelected;
|
|
m_GlassColor = glassColor;
|
|
m_GlassAlpha = glassAlpha;
|
|
|
|
// BkBrush
|
|
m_BkBrush.DeleteObject();
|
|
if (bDarkMode)
|
|
{
|
|
m_BkBrush.CreateSolidBrush(RGB(32, 32, 32));
|
|
}
|
|
else
|
|
{
|
|
m_BkBrush.CreateSolidBrush(bkColor);
|
|
}
|
|
|
|
if (ES_LEFT <= textAlign && textAlign <= ES_RIGHT)
|
|
{
|
|
m_TextAlign = textAlign;
|
|
ModifyStyle(0, m_TextAlign);
|
|
}
|
|
|
|
if (m_ToolTip.m_hWnd != NULL)
|
|
{
|
|
if (m_ToolTip.GetToolCount() != 0)
|
|
{
|
|
m_ToolTip.DelTool(this, 1);
|
|
}
|
|
CRect rect;
|
|
GetClientRect(rect);
|
|
m_ToolTip.AddTool(this, m_ToolTipText, rect, 1);
|
|
}
|
|
|
|
m_bHighContrast = bHighContrast;
|
|
m_bDarkMode = bDarkMode;
|
|
|
|
if (renderMode & SystemDraw)
|
|
{
|
|
#if _MSC_VER <= 1310
|
|
if (IsNT3())
|
|
{
|
|
ModifyStyle(0, WS_BORDER, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED);
|
|
}
|
|
#endif
|
|
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
m_ImageCount = 1;
|
|
m_CtrlImage.Destroy();
|
|
m_CtrlImage.Create(m_CtrlSize.cx, m_CtrlSize.cy * m_ImageCount, 32);
|
|
m_CtrlBitmap.Detach();
|
|
m_CtrlBitmap.Attach((HBITMAP)m_CtrlImage);
|
|
DWORD length = m_CtrlSize.cx * m_CtrlSize.cy * m_ImageCount * 4;
|
|
BYTE* bitmapBits = new BYTE[length];
|
|
m_CtrlBitmap.GetBitmapBits(length, bitmapBits);
|
|
|
|
BYTE r, g, b, a;
|
|
if (renderMode & OwnerDrawGlass)
|
|
{
|
|
r = (BYTE)GetRValue(m_GlassColor);
|
|
g = (BYTE)GetGValue(m_GlassColor);
|
|
b = (BYTE)GetBValue(m_GlassColor);
|
|
a = m_GlassAlpha;
|
|
}
|
|
else // OwnerDrawTransparent
|
|
{
|
|
r = 0;
|
|
g = 0;
|
|
b = 0;
|
|
a = 0;
|
|
}
|
|
|
|
for (int y = 0; y < (int)(m_CtrlSize.cy * m_ImageCount); y++)
|
|
{
|
|
for (int x = 0; x < m_CtrlSize.cx; x++)
|
|
{
|
|
DWORD p = (y * m_CtrlSize.cx + x) * 4;
|
|
#if _MSC_VER > 1310
|
|
#pragma warning( disable : 6386 )
|
|
#endif
|
|
bitmapBits[p + 0] = b;
|
|
bitmapBits[p + 1] = g;
|
|
bitmapBits[p + 2] = r;
|
|
bitmapBits[p + 3] = a;
|
|
#if _MSC_VER > 1310
|
|
#pragma warning( default : 6386 )
|
|
#endif
|
|
}
|
|
}
|
|
|
|
m_CtrlBitmap.SetBitmapBits(length, bitmapBits);
|
|
delete[] bitmapBits;
|
|
}
|
|
|
|
SetBkReload();
|
|
Invalidate();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void CComboBoxFx::SetFontHeight(int height, double zoomRatio, double fontRatio)
|
|
{
|
|
m_FontHeight = (LONG)(-1 * height * zoomRatio * fontRatio);
|
|
}
|
|
|
|
void CComboBoxFx::SetItemHeightEx(int nIndex, int height, double zoomRatio, double fontRatio)
|
|
{
|
|
if (nIndex == -1)
|
|
{
|
|
CRect rc;
|
|
GetWindowRect(&rc);
|
|
CComboBox::SetItemHeight(-1, (UINT)(height * zoomRatio - rc.Height() + GetItemHeight(-1)));
|
|
}
|
|
else
|
|
{
|
|
CComboBox::SetItemHeight(nIndex, (UINT)(height * zoomRatio * fontRatio));
|
|
}
|
|
}
|
|
|
|
void CComboBoxFx::SetItemHeightAll(int height, double zoomRatio, double fontRatio)
|
|
{
|
|
m_FontHeight = (LONG)(-1 * height * zoomRatio * fontRatio);
|
|
|
|
CRect rc;
|
|
GetWindowRect(&rc);
|
|
CComboBox::SetItemHeight(-1, (UINT)(height * zoomRatio - rc.Height() + GetItemHeight(-1)));
|
|
|
|
for(int i = 0; i < this->GetCount(); i++)
|
|
{
|
|
CComboBox::SetItemHeight(i, (UINT)(height * zoomRatio * fontRatio));
|
|
}
|
|
}
|
|
|
|
void CComboBoxFx::SetMargin(int top, int left, int bottom, int right, double zoomRatio)
|
|
{
|
|
m_Margin.top = (int)(top * zoomRatio);
|
|
m_Margin.left = (int)(left * zoomRatio);
|
|
m_Margin.bottom = (int)(bottom * zoomRatio);
|
|
m_Margin.right = (int)(right * zoomRatio);
|
|
m_ZoomRatio = zoomRatio;
|
|
}
|
|
|
|
CSize CComboBoxFx::GetSize(void)
|
|
{
|
|
return m_CtrlSize;
|
|
}
|
|
|
|
void CComboBoxFx::SetGlassColor(COLORREF glassColor, BYTE glassAlpha)
|
|
{
|
|
m_GlassColor = glassColor;
|
|
m_GlassAlpha = glassAlpha;
|
|
}
|
|
|
|
void CComboBoxFx::SetAlpha(BYTE alpha)
|
|
{
|
|
m_Alpha = alpha;
|
|
}
|
|
|
|
HWND CComboBoxFx::GetListHwnd()
|
|
{
|
|
#if _MSC_VER > 1310
|
|
COMBOBOXINFO info = { 0 };
|
|
info.cbSize = sizeof(COMBOBOXINFO);
|
|
GetComboBoxInfo(&info);
|
|
|
|
return info.hwndList;
|
|
#else
|
|
return NULL;
|
|
#endif
|
|
}
|
|
|
|
HBRUSH CComboBoxFx::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
|
|
{
|
|
HBRUSH hbr = CComboBox::OnCtlColor(pDC, pWnd, nCtlColor);
|
|
switch (nCtlColor) {
|
|
case CTLCOLOR_EDIT:
|
|
pDC->SetBkMode(TRANSPARENT);
|
|
return hbr;
|
|
case CTLCOLOR_LISTBOX:
|
|
pDC->SetBkMode(TRANSPARENT);
|
|
return m_BkBrush;
|
|
default:
|
|
return hbr;
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------
|
|
// Draw Control
|
|
//------------------------------------------------
|
|
|
|
void CComboBoxFx::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
|
|
{
|
|
if (lpDrawItemStruct->itemID == -1) { return; }
|
|
|
|
static COLORREF textColor;
|
|
static COLORREF textColorSelected;
|
|
static COLORREF bkColor;
|
|
static COLORREF bkColorSelected;
|
|
|
|
static int count = 0;
|
|
if (m_bHighContrast)
|
|
{
|
|
textColor = GetTextColor(lpDrawItemStruct->hDC);
|
|
textColorSelected = RGB(0, 0, 0);
|
|
bkColor = GetBkColor(lpDrawItemStruct->hDC);
|
|
bkColorSelected = RGB(0, 255, 255);
|
|
|
|
if (bkColor <= RGB(0x80, 0x80, 0x80)) { textColor = RGB(255, 255, 255); }
|
|
else { textColor = RGB(0, 0, 0); }
|
|
}
|
|
else if (m_bDarkMode)
|
|
{
|
|
textColor = RGB(255, 255, 255);
|
|
textColorSelected = RGB(255, 255, 255);
|
|
bkColor = RGB(32, 32, 32);
|
|
bkColorSelected = RGB(77, 77, 77);
|
|
}
|
|
else
|
|
{
|
|
textColor = m_TextColor;
|
|
textColorSelected = m_TextColorSelected;
|
|
bkColor = m_BkColor;
|
|
bkColorSelected = m_BkColorSelected;
|
|
}
|
|
|
|
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
|
|
LoadCtrlBk(pDC);
|
|
CString title;
|
|
GetLBText(lpDrawItemStruct->itemID, title);
|
|
|
|
CBrush Brush;
|
|
CBrush* pOldBrush;
|
|
if (lpDrawItemStruct->rcItem.left != 0 && !m_bHighContrast)
|
|
{
|
|
DrawControl(title, pDC, lpDrawItemStruct, m_CtrlBitmap, m_BkBitmap, ControlImageNormal);
|
|
Brush.CreateSolidBrush(bkColorSelected);
|
|
pOldBrush = pDC->SelectObject(&Brush);
|
|
if (lpDrawItemStruct->itemState & ODS_SELECTED)
|
|
{
|
|
RECT rc = lpDrawItemStruct->rcItem;
|
|
// rc.top = (LONG)(rc.bottom - 2 * m_ZoomRatio);
|
|
rc.right = (LONG)(rc.left + 3 * m_ZoomRatio);
|
|
FillRect(lpDrawItemStruct->hDC, &rc, (HBRUSH)Brush);
|
|
}
|
|
DrawString(title, pDC, lpDrawItemStruct, textColor);
|
|
|
|
#if _MSC_VER <= 1310
|
|
if (IsNT3() && IsWindowEnabled())
|
|
{
|
|
DWORD oldTextAlign = m_TextAlign;
|
|
m_TextAlign = ES_RIGHT;
|
|
DrawString(_T("v"), pDC, lpDrawItemStruct, textColor);
|
|
m_TextAlign = oldTextAlign;
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
if (lpDrawItemStruct->itemState & ODS_SELECTED)
|
|
{
|
|
Brush.CreateSolidBrush(bkColorSelected);
|
|
pOldBrush = pDC->SelectObject(&Brush);
|
|
FillRect(lpDrawItemStruct->hDC, &lpDrawItemStruct->rcItem, (HBRUSH)Brush);
|
|
DrawString(title, pDC, lpDrawItemStruct, textColorSelected);
|
|
}
|
|
else
|
|
{
|
|
Brush.CreateSolidBrush(bkColor);
|
|
pOldBrush = pDC->SelectObject(&Brush);
|
|
FillRect(lpDrawItemStruct->hDC, &lpDrawItemStruct->rcItem, (HBRUSH)Brush);
|
|
DrawString(title, pDC, lpDrawItemStruct, textColor);
|
|
}
|
|
}
|
|
pDC->SelectObject(pOldBrush);
|
|
Brush.DeleteObject();
|
|
}
|
|
|
|
void CComboBoxFx::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
|
|
{
|
|
lpMeasureItemStruct->itemHeight = abs(m_FontHeight);
|
|
}
|
|
|
|
void CComboBoxFx::DrawControl(CString title, CDC* drawDC, LPDRAWITEMSTRUCT lpDrawItemStruct, CBitmap& ctrlBitmap, CBitmap& bkBitmap, int no)
|
|
{
|
|
CDC* pMemDC = new CDC;
|
|
CBitmap* pOldMemBitmap;
|
|
pMemDC->CreateCompatibleDC(drawDC);
|
|
pOldMemBitmap = pMemDC->SelectObject(&ctrlBitmap);
|
|
CDC* pBkDC = new CDC;
|
|
CBitmap* pOldBkBitmap;
|
|
pBkDC->CreateCompatibleDC(drawDC);
|
|
pOldBkBitmap = pBkDC->SelectObject(&bkBitmap);
|
|
|
|
CBitmap DrawBmp;
|
|
DrawBmp.CreateCompatibleBitmap(drawDC, m_CtrlSize.cx, m_CtrlSize.cy);
|
|
CDC* pDrawBmpDC = new CDC;
|
|
CBitmap* pOldDrawBitmap;
|
|
pDrawBmpDC->CreateCompatibleDC(drawDC);
|
|
pOldDrawBitmap = pDrawBmpDC->SelectObject(&DrawBmp);
|
|
|
|
int color = drawDC->GetDeviceCaps(BITSPIXEL) * drawDC->GetDeviceCaps(PLANES);
|
|
|
|
if (!m_CtrlImage.IsNull())
|
|
{
|
|
if (m_CtrlImage.GetBPP() == 32)
|
|
{
|
|
CBitmap* bk32Bitmap;
|
|
CImage bk32Image;
|
|
if (color == 32)
|
|
{
|
|
bk32Bitmap = &bkBitmap;
|
|
}
|
|
else
|
|
{
|
|
bk32Image.Create(m_CtrlSize.cx, m_CtrlSize.cy, 32);
|
|
::BitBlt(bk32Image.GetDC(), 0, 0, m_CtrlSize.cx, m_CtrlSize.cy, *pBkDC, 0, 0, SRCCOPY);
|
|
bk32Bitmap = CBitmap::FromHandle((HBITMAP)bk32Image);
|
|
}
|
|
|
|
BITMAP CtlBmpInfo, DstBmpInfo;
|
|
bk32Bitmap->GetBitmap(&DstBmpInfo);
|
|
DWORD DstLineBytes = DstBmpInfo.bmWidthBytes;
|
|
DWORD DstMemSize = DstLineBytes * DstBmpInfo.bmHeight;
|
|
ctrlBitmap.GetBitmap(&CtlBmpInfo);
|
|
DWORD CtlLineBytes = CtlBmpInfo.bmWidthBytes;
|
|
DWORD CtlMemSize = CtlLineBytes * CtlBmpInfo.bmHeight;
|
|
BYTE* DstBuffer = new BYTE[DstMemSize];
|
|
bk32Bitmap->GetBitmapBits(DstMemSize, DstBuffer);
|
|
BYTE* CtlBuffer = new BYTE[CtlMemSize];
|
|
ctrlBitmap.GetBitmapBits(CtlMemSize, CtlBuffer);
|
|
|
|
int baseY = m_CtrlSize.cy * no;
|
|
for (LONG py = 0; py < DstBmpInfo.bmHeight; py++)
|
|
{
|
|
int dn = py * DstLineBytes;
|
|
int cn = (baseY + py) * CtlLineBytes;
|
|
for (LONG px = 0; px < DstBmpInfo.bmWidth; px++)
|
|
{
|
|
#if _MSC_VER > 1310
|
|
#pragma warning( disable : 6385 )
|
|
#pragma warning( disable : 6386 )
|
|
#endif
|
|
BYTE a = CtlBuffer[cn + 3];
|
|
BYTE na = 255 - a;
|
|
DstBuffer[dn + 0] = (BYTE)((CtlBuffer[cn + 0] * a + DstBuffer[dn + 0] * na) / 255);
|
|
DstBuffer[dn + 1] = (BYTE)((CtlBuffer[cn + 1] * a + DstBuffer[dn + 1] * na) / 255);
|
|
DstBuffer[dn + 2] = (BYTE)((CtlBuffer[cn + 2] * a + DstBuffer[dn + 2] * na) / 255);
|
|
dn += (DstBmpInfo.bmBitsPixel / 8);
|
|
cn += (CtlBmpInfo.bmBitsPixel / 8);
|
|
#if _MSC_VER > 1310
|
|
#pragma warning( default : 6386 )
|
|
#pragma warning( default : 6385 )
|
|
#endif
|
|
}
|
|
}
|
|
|
|
if (color == 32)
|
|
{
|
|
DrawBmp.SetBitmapBits(DstMemSize, DstBuffer);
|
|
}
|
|
else
|
|
{
|
|
bk32Bitmap->SetBitmapBits(DstMemSize, DstBuffer);
|
|
::BitBlt(pDrawBmpDC->GetSafeHdc(), 0, 0, m_CtrlSize.cx, m_CtrlSize.cy, bk32Image.GetDC(), 0, 0, SRCCOPY);
|
|
bk32Image.ReleaseDC();
|
|
}
|
|
drawDC->BitBlt(0, 0, m_CtrlSize.cx, m_CtrlSize.cy, pDrawBmpDC, 0, 0, SRCCOPY);
|
|
|
|
delete[] DstBuffer;
|
|
delete[] CtlBuffer;
|
|
}
|
|
else
|
|
{
|
|
pDrawBmpDC->BitBlt(0, 0, m_CtrlSize.cx, m_CtrlSize.cy, pMemDC, 0, m_CtrlSize.cy * no, SRCCOPY);
|
|
drawDC->BitBlt(0, 0, m_CtrlSize.cx, m_CtrlSize.cy, pDrawBmpDC, 0, 0, SRCCOPY);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pDrawBmpDC->BitBlt(0, 0, m_CtrlSize.cx, m_CtrlSize.cy, pBkDC, 0, m_CtrlSize.cy * no, SRCCOPY);
|
|
drawDC->BitBlt(0, 0, m_CtrlSize.cx, m_CtrlSize.cy, pDrawBmpDC, 0, 0, SRCCOPY);
|
|
}
|
|
|
|
pDrawBmpDC->SelectObject(&pOldDrawBitmap);
|
|
pDrawBmpDC->DeleteDC();
|
|
delete pDrawBmpDC;
|
|
pMemDC->SelectObject(&pOldMemBitmap);
|
|
pMemDC->DeleteDC();
|
|
delete pMemDC;
|
|
pBkDC->SelectObject(&pOldBkBitmap);
|
|
pBkDC->DeleteDC();
|
|
delete pBkDC;
|
|
}
|
|
|
|
void CComboBoxFx::DrawString(CString title, CDC* drawDC, LPDRAWITEMSTRUCT lpDrawItemStruct, COLORREF textColor)
|
|
{
|
|
if (title.IsEmpty())
|
|
{
|
|
return;
|
|
}
|
|
|
|
drawDC->SetBkMode(TRANSPARENT);
|
|
CRect rect = (CRect)(lpDrawItemStruct->rcItem);
|
|
rect.top += m_Margin.top;
|
|
rect.left += m_Margin.left;
|
|
rect.bottom -= m_Margin.bottom;
|
|
rect.right -= m_Margin.right;
|
|
drawDC->SetTextColor(textColor);
|
|
|
|
if (m_TextAlign == ES_LEFT)
|
|
{
|
|
drawDC->DrawText(title, title.GetLength(), rect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
|
|
}
|
|
else if (m_TextAlign == ES_RIGHT)
|
|
{
|
|
drawDC->DrawText(title, title.GetLength(), rect, DT_RIGHT | DT_VCENTER | DT_SINGLELINE);
|
|
}
|
|
else
|
|
{
|
|
drawDC->DrawText(title, title.GetLength(), rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------
|
|
// Image
|
|
//------------------------------------------------
|
|
|
|
BOOL CComboBoxFx::LoadBitmap(LPCTSTR fileName)
|
|
{
|
|
if (m_bHighContrast) { return FALSE; }
|
|
if (fileName == NULL) { return FALSE; }
|
|
|
|
m_CtrlImage.Destroy();
|
|
m_CtrlImage.Load(fileName);
|
|
if (m_CtrlImage.IsNull()) { return FALSE; }
|
|
|
|
return LoadBitmap((HBITMAP)m_CtrlImage);
|
|
}
|
|
|
|
BOOL CComboBoxFx::LoadBitmap(HBITMAP hBitmap)
|
|
{
|
|
if (m_bHighContrast) { return FALSE; }
|
|
|
|
m_CtrlBitmap.Detach();
|
|
m_CtrlBitmap.Attach(hBitmap);
|
|
|
|
return SetBitmap(m_CtrlBitmap);
|
|
}
|
|
|
|
void CComboBoxFx::SetBkReload(void)
|
|
{
|
|
m_bBkBitmapInit = FALSE;
|
|
m_bBkLoad = FALSE;
|
|
}
|
|
|
|
BOOL CComboBoxFx::SetBitmap(CBitmap& bitmap)
|
|
{
|
|
if (m_bHighContrast) { return FALSE; }
|
|
|
|
BITMAP bitmapinfo;
|
|
bitmap.GetBitmap(&bitmapinfo);
|
|
|
|
if (m_CtrlSize.cx != bitmapinfo.bmWidth
|
|
|| m_CtrlSize.cy != bitmapinfo.bmHeight / m_ImageCount)
|
|
{
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
void CComboBoxFx::LoadCtrlBk(CDC* drawDC)
|
|
{
|
|
if (m_bHighContrast) { SetBkReload(); return; }
|
|
|
|
if (m_BkBitmap.m_hObject != NULL)
|
|
{
|
|
BITMAP bitmapInfo;
|
|
m_BkBitmap.GetBitmap(&bitmapInfo);
|
|
if (bitmapInfo.bmBitsPixel != drawDC->GetDeviceCaps(BITSPIXEL))
|
|
{
|
|
SetBkReload();
|
|
}
|
|
}
|
|
|
|
if (&m_CtrlBitmap != NULL)
|
|
{
|
|
if (!m_bBkBitmapInit)
|
|
{
|
|
m_BkBitmap.DeleteObject();
|
|
m_BkBitmap.CreateCompatibleBitmap(drawDC, m_CtrlSize.cx, m_CtrlSize.cy);
|
|
m_bBkBitmapInit = TRUE;
|
|
}
|
|
|
|
if (!m_bBkLoad)
|
|
{
|
|
CBitmap* pOldBitmap;
|
|
CDC* pMemDC = new CDC;
|
|
pMemDC->CreateCompatibleDC(drawDC);
|
|
pOldBitmap = pMemDC->SelectObject(&m_BkBitmap);
|
|
pMemDC->BitBlt(0, 0, m_CtrlSize.cx, m_CtrlSize.cy, m_BkDC, m_X, m_Y, SRCCOPY);
|
|
pMemDC->SelectObject(pOldBitmap);
|
|
pMemDC->DeleteDC();
|
|
delete pMemDC;
|
|
m_bBkLoad = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------
|
|
// Font
|
|
//------------------------------------------------
|
|
|
|
void CComboBoxFx::SetFontEx(CString face, int size, int sizeToolTip, double zoomRatio, double fontRatio,
|
|
COLORREF textColor, COLORREF textColorSelected, LONG fontWeight, BYTE fontRender)
|
|
{
|
|
LOGFONT logFont = { 0 };
|
|
logFont.lfCharSet = DEFAULT_CHARSET;
|
|
logFont.lfHeight = (LONG)(-1 * size * zoomRatio * fontRatio);
|
|
logFont.lfQuality = fontRender;
|
|
logFont.lfWeight = fontWeight;
|
|
m_FontRender = fontRender;
|
|
|
|
if (face.GetLength() < 32)
|
|
{
|
|
wsprintf(logFont.lfFaceName, _T("%s"), (LPCTSTR)face);
|
|
}
|
|
else
|
|
{
|
|
wsprintf(logFont.lfFaceName, _T(""));
|
|
}
|
|
|
|
m_Font.DeleteObject();
|
|
m_Font.CreateFontIndirect(&logFont);
|
|
SetFont(&m_Font);
|
|
|
|
logFont.lfHeight = (LONG)(-1 * sizeToolTip * zoomRatio);
|
|
m_FontToolTip.DeleteObject();
|
|
m_FontToolTip.CreateFontIndirect(&logFont);
|
|
|
|
if (! m_bHighContrast)
|
|
{
|
|
m_TextColor = textColor;
|
|
m_TextColorSelected = textColorSelected;
|
|
}
|
|
|
|
if (m_ToolTip.m_hWnd != NULL)
|
|
{
|
|
m_ToolTip.SetFont(&m_FontToolTip);
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------
|
|
// Mouse
|
|
//------------------------------------------------
|
|
|
|
void CComboBoxFx::SetHandCursor(BOOL bHandCuror)
|
|
{
|
|
m_bHandCursor = bHandCuror;
|
|
}
|
|
|
|
void CComboBoxFx::OnMouseMove(UINT nFlags, CPoint point)
|
|
{
|
|
#if _MSC_VER <= 1310
|
|
typedef BOOL(WINAPI* Func_TrackMouseEvent)(LPTRACKMOUSEEVENT);
|
|
static Func_TrackMouseEvent p_TrackMouseEvent = NULL;
|
|
static BOOL bInit_TrackMouseEvent = FALSE;
|
|
|
|
if (bInit_TrackMouseEvent && p_TrackMouseEvent == NULL)
|
|
{
|
|
return; // TrackMouseEvent is not available
|
|
}
|
|
else
|
|
{
|
|
HMODULE hModule = GetModuleHandle(_T("user32.dll"));
|
|
if (hModule)
|
|
{
|
|
p_TrackMouseEvent = (Func_TrackMouseEvent)GetProcAddress(hModule, "TrackMouseEvent");
|
|
}
|
|
}
|
|
|
|
if (p_TrackMouseEvent != NULL)
|
|
{
|
|
TRACKMOUSEEVENT tme = { sizeof(TRACKMOUSEEVENT) };
|
|
tme.hwndTrack = m_hWnd;
|
|
tme.dwFlags = TME_LEAVE | TME_HOVER;
|
|
tme.dwHoverTime = 1;
|
|
m_bTrackingNow = p_TrackMouseEvent(&tme);
|
|
}
|
|
bInit_TrackMouseEvent = TRUE;
|
|
#else
|
|
if (!m_bTrackingNow)
|
|
{
|
|
TRACKMOUSEEVENT tme = { sizeof(TRACKMOUSEEVENT) };
|
|
tme.hwndTrack = m_hWnd;
|
|
tme.dwFlags = TME_LEAVE | TME_HOVER;
|
|
tme.dwHoverTime = 1;
|
|
m_bTrackingNow = _TrackMouseEvent(&tme);
|
|
}
|
|
#endif
|
|
|
|
CComboBox::OnMouseMove(nFlags, point);
|
|
}
|
|
|
|
void CComboBoxFx::OnMouseHover(UINT nFlags, CPoint point)
|
|
{
|
|
#if _MSC_VER > 1310
|
|
CComboBox::OnMouseHover(nFlags, point);
|
|
#endif
|
|
m_bHover = TRUE;
|
|
Invalidate();
|
|
}
|
|
|
|
void CComboBoxFx::OnMouseLeave()
|
|
{
|
|
#if _MSC_VER > 1310
|
|
CComboBox::OnMouseLeave();
|
|
#endif
|
|
m_bTrackingNow = FALSE;
|
|
m_bHover = FALSE;
|
|
Invalidate();
|
|
}
|
|
|
|
void CComboBoxFx::OnSetfocus()
|
|
{
|
|
m_bFocas = TRUE;
|
|
Invalidate();
|
|
}
|
|
|
|
void CComboBoxFx::OnKillfocus()
|
|
{
|
|
m_bFocas = FALSE;
|
|
Invalidate();
|
|
}
|
|
|
|
BOOL CComboBoxFx::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
|
|
{
|
|
HCURSOR hCursor = NULL;
|
|
if (m_bHandCursor)
|
|
{
|
|
hCursor = AfxGetApp()->LoadStandardCursor(IDC_HAND);
|
|
if (hCursor)
|
|
{
|
|
::SetCursor(hCursor);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
|
|
if (hCursor)
|
|
{
|
|
::SetCursor(hCursor);
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//------------------------------------------------
|
|
// ToolTip
|
|
//------------------------------------------------
|
|
|
|
void CComboBoxFx::SetToolTipText(LPCTSTR text)
|
|
{
|
|
if (text == NULL) { return; }
|
|
|
|
InitToolTip();
|
|
m_ToolTipText = text;
|
|
|
|
if (m_ToolTip.GetToolCount() == 0)
|
|
{
|
|
CRect rect;
|
|
GetClientRect(rect);
|
|
m_ToolTip.AddTool(this, m_ToolTipText, rect, 1);
|
|
}
|
|
else
|
|
{
|
|
m_ToolTip.UpdateTipText(m_ToolTipText, this, 1);
|
|
}
|
|
|
|
SetToolTipActivate(TRUE);
|
|
}
|
|
|
|
void CComboBoxFx::SetToolTipActivate(BOOL bActivate)
|
|
{
|
|
if (m_ToolTip.GetToolCount() == 0) { return; }
|
|
m_ToolTip.Activate(bActivate);
|
|
}
|
|
|
|
void CComboBoxFx::SetToolTipWindowText(LPCTSTR pText)
|
|
{
|
|
SetToolTipText(pText);
|
|
SetWindowText(pText);
|
|
}
|
|
|
|
CString CComboBoxFx::GetToolTipText()
|
|
{
|
|
return m_ToolTipText;
|
|
}
|
|
|
|
void CComboBoxFx::InitToolTip()
|
|
{
|
|
if (m_ToolTip.m_hWnd == NULL)
|
|
{
|
|
m_ToolTip.Create(this, TTS_ALWAYSTIP | TTS_BALLOON | TTS_NOANIMATE | TTS_NOFADE);
|
|
m_ToolTip.Activate(FALSE);
|
|
m_ToolTip.SetFont(&m_FontToolTip);
|
|
m_ToolTip.SendMessage(TTM_SETMAXTIPWIDTH, 0, 1024);
|
|
m_ToolTip.SetDelayTime(TTDT_AUTOPOP, 8000);
|
|
m_ToolTip.SetDelayTime(TTDT_INITIAL, 500);
|
|
m_ToolTip.SetDelayTime(TTDT_RESHOW, 100);
|
|
}
|
|
}
|
|
|
|
BOOL CComboBoxFx::PreTranslateMessage(MSG* pMsg)
|
|
{
|
|
InitToolTip();
|
|
m_ToolTip.RelayEvent(pMsg);
|
|
|
|
return CComboBox::PreTranslateMessage(pMsg);
|
|
} |