📄 tlcdragwnd.cpp
字号:
// TLCDragWnd.cpp : implementation file
//
#include "stdafx.h"
#include "TreeListHeaderCtrl.h"
#include "TreeListTipCtrl.h"
#include "TreeListStaticCtrl.h"
#include "TreeListEditCtrl.h"
#include "TreeListComboCtrl.h"
#include "TreeListCtrl.h"
#include "TreeListDC.h"
#include "TreeListItem.h"
#include "TLCDragWnd.h"
#include "math.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define DRAGWND_SIZE 320
#define MAX_SIZE 320
static lpfnUpdateLayeredWindow g_lpfnUpdateLayeredWindow = NULL;
static lpfnSetLayeredWindowAttributes g_lpfnSetLayeredWindowAttributes = NULL;
/////////////////////////////////////////////////////////////////////////////
// CTLCDragWnd
CTLCDragWnd::CTLCDragWnd() :
m_pTreeListCtrl( NULL )
{
// register the window class
WNDCLASS wndclass;
HINSTANCE hInst = AfxGetInstanceHandle();
if(!(::GetClassInfo(hInst, TLCDRAGWND_CLASSNAME, &wndclass)))
{
wndclass.style = CS_HREDRAW | CS_VREDRAW;// | CS_SAVEBITS ;
wndclass.lpfnWndProc = ::DefWindowProc;
wndclass.cbClsExtra = wndclass.cbWndExtra = 0;
wndclass.hInstance = hInst;
wndclass.hIcon = NULL;
wndclass.hCursor = LoadCursor( hInst, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = TLCDRAGWND_CLASSNAME;
if (!AfxRegisterClass(&wndclass))
AfxThrowResourceException();
}
// get layer window
if( g_lpfnUpdateLayeredWindow == NULL || g_lpfnSetLayeredWindowAttributes == NULL )
{
HMODULE hUser32 = GetModuleHandle(_T("USER32.DLL"));
g_lpfnUpdateLayeredWindow = (lpfnUpdateLayeredWindow)GetProcAddress( hUser32, _T("UpdateLayeredWindow") );
g_lpfnSetLayeredWindowAttributes = (lpfnSetLayeredWindowAttributes)GetProcAddress( hUser32, _T("SetLayeredWindowAttributes") );
if( g_lpfnUpdateLayeredWindow == NULL || g_lpfnSetLayeredWindowAttributes == NULL )
m_bLayeredWindows = FALSE;
else
m_bLayeredWindows = TRUE;
}
m_pDIB = NULL;
m_pBitmap = NULL;
m_pBitmap2 = NULL;
BITMAPINFO bmi;
HBITMAP hbitmap;
bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = DRAGWND_SIZE;
bmi.bmiHeader.biHeight = DRAGWND_SIZE;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = DRAGWND_SIZE * DRAGWND_SIZE * 4;
m_dcMem.CreateCompatibleDC( NULL );
hbitmap = CreateDIBSection( NULL, &bmi, DIB_RGB_COLORS, (void **)&m_pDIB, NULL, NULL );
m_pBitmap = CBitmap::FromHandle( hbitmap );
m_pBitmap2 = m_dcMem.SelectObject( m_pBitmap );
}
CTLCDragWnd::~CTLCDragWnd()
{
m_dcMem.SelectObject( m_pBitmap2 );
m_dcMem.DeleteDC();
::DeleteObject( *m_pBitmap );
}
BEGIN_MESSAGE_MAP(CTLCDragWnd, CWnd)
//{{AFX_MSG_MAP(CTLCDragWnd)
ON_WM_ERASEBKGND()
ON_WM_PAINT()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CTLCDragWnd message handlers
BOOL CTLCDragWnd::Create( CRect rcWindow, CTreeListCtrl* pTreeListCtrl )
{
// create window
ASSERT_VALID( pTreeListCtrl );
m_pTreeListCtrl = pTreeListCtrl;
DWORD dwStyle = WS_POPUP | WS_DISABLED;
DWORD dwExStyle = WS_EX_TOOLWINDOW | WS_EX_TOPMOST;
if( m_bLayeredWindows )
{
dwExStyle |= WS_EX_LAYERED | WS_EX_TRANSPARENT;
if( !CreateEx( dwExStyle, TLCDRAGWND_CLASSNAME, NULL, dwStyle,
rcWindow.left, rcWindow.top, rcWindow.Width(), rcWindow.Height(), NULL, NULL, NULL ) )
return FALSE;
}
else
{
CRect rcClient;
m_pTreeListCtrl->GetClientRect( &rcClient );
if( !CreateEx( dwExStyle, TLCDRAGWND_CLASSNAME, NULL, dwStyle,
rcWindow.left, rcWindow.top, rcClient.Width(), pTreeListCtrl->GetItemHeight(), NULL, NULL, NULL ) )
return FALSE;
}
return TRUE;
}
BOOL CTLCDragWnd::OnEraseBkgnd(CDC* pDC)
{
// erase background
return TRUE;
}
void CTLCDragWnd::OnPaintBMP()
{
// render off screen bitmap
ASSERT( m_pTreeListCtrl != NULL );
ASSERT( m_dcMem.m_hDC != NULL );
CPaintDC dc(this);
CRect rcWindow;
CRect rcClient;
GetWindowRect( rcWindow );
GetClientRect( rcClient );
int i, x, y, z;
for( i = 0; i < 102400; i++ )
((UINT32*)m_pDIB)[i] = 0xFFFFFFFF;
// render control on bitmap
DrawWnd( &m_dcMem );
// calculate alpha channel
int xx, yy, zz;
for( y = 0; y < 320; y++ )
{
yy = 160 * 160 - 2 * 160 * y + y * y;
for( x = 0; x < 320; x++ )
{
xx = 160 * 160 - 2 * 160 * x + x * x;
zz = xx + yy;
z = (int)sqrt( zz );
z = 160 - min( 160, z );
UINT32 cc, aa, bb, gg, rr;
cc = ((UINT32 *)m_pDIB)[x + y * DRAGWND_SIZE];
if( cc == 0xFFFFFFFF )
{
cc = 0x00000000;
}
else
{
aa = z;
bb = ( cc & 0x00FF0000 ) >> 16;
gg = ( cc & 0x0000FF00 ) >> 8;
rr = ( cc & 0x000000FF );
bb = bb * aa / 0xFF;
gg = gg * aa / 0xFF;
rr = rr * aa / 0xFF;
cc = ( aa << 24 ) | ( bb << 16 ) | ( gg << 8 ) | rr;
}
((UINT32 *)m_pDIB)[x + y * DRAGWND_SIZE] = cc;
}
}
// update window with alpha channel
BLENDFUNCTION bf;
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.SourceConstantAlpha = 0xFF;
bf.AlphaFormat = 0x1;
g_lpfnUpdateLayeredWindow(
GetSafeHwnd(), dc.GetSafeHdc(), &rcWindow.TopLeft(), &CSize( rcWindow.Width(), rcWindow.Height() ),
m_dcMem.GetSafeHdc(), &CPoint( 0, 0 ),
0x00, &bf,
ULW_ALPHA );
g_lpfnSetLayeredWindowAttributes( GetSafeHwnd(), 0x000000, 160, ULW_ALPHA );
return;
}
void CTLCDragWnd::OnPaint()
{
CPaintDC dc(this);
if( !m_bLayeredWindows )
DrawDragWnd( &dc );
return;
}
BOOL CTLCDragWnd::DrawWnd( CDC* pDC )
{
// draw window
CRect rcItems;
CRect rcClient;
// calculate draw position
rcClient.SetRect( 0, 0, 320, 320 );
rcItems.left = m_pTreeListCtrl->m_ptBegin.x + m_pTreeListCtrl->GetScrollPos( SB_HORZ );
rcItems.top = m_pTreeListCtrl->m_ptBegin.y + m_pTreeListCtrl->GetScrollPos( SB_VERT ) * m_pTreeListCtrl->GetItemHeight();
CPoint pt;
pt.x = m_pTreeListCtrl->GetScrollPos( SB_HORZ );
pt.y = m_pTreeListCtrl->GetScrollPos( SB_VERT ) * m_pTreeListCtrl->GetItemHeight();
pt.x = m_pTreeListCtrl->m_ptBegin.x + pt.x;
pt.y = m_pTreeListCtrl->m_ptBegin.y + pt.y;
pt.y = -m_pTreeListCtrl->GetHeaderCtrl()->GetHeaderHeight() + pt.y;
pt.x = DRAGWND_SIZE / 2 - pt.x;
pt.y = DRAGWND_SIZE / 2 - pt.y;
int nFirstRow = - pt.y / m_pTreeListCtrl->GetItemHeight();
int nShowRows = DRAGWND_SIZE / m_pTreeListCtrl->GetItemHeight() + 2;
if( nFirstRow < 0 )
nFirstRow = 0;
CRect rcItem;
rcItem.SetRect( 0, 0, m_pTreeListCtrl->GetWidth(), m_pTreeListCtrl->GetItemHeight() );
rcItem.OffsetRect( pt.x, pt.y );
rcItem.OffsetRect( 0, nFirstRow * m_pTreeListCtrl->GetItemHeight() );
// draw all items
CPen Pen( PS_SOLID, 1, m_pTreeListCtrl->m_crGrid );
CPen* pOldPen = pDC->SelectObject( &Pen );
CFont* pOldFont = pDC->SelectObject( &m_pTreeListCtrl->m_Font );
int nOldMode = pDC->SetBkMode( TRANSPARENT );
CTreeListItem* pShowItem = m_pTreeListCtrl->GetFirstShowItem( nFirstRow );
for( int iRow = nFirstRow; iRow < nFirstRow + nShowRows && iRow < m_pTreeListCtrl->GetVisibleCount(); iRow++, pShowItem = m_pTreeListCtrl->GetNextShowItem( pShowItem ) )
{
ASSERT( pShowItem != NULL );
DrawItem( pDC, rcItem, pShowItem );
if( m_pTreeListCtrl->m_dwStyle&TLC_HGRID_FULL && rcItem.right<rcClient.right )
{
pDC->MoveTo( rcItem.right, rcItem.bottom - 1);
pDC->LineTo( rcClient.right, rcItem.bottom - 1);
}
rcItem.OffsetRect( 0, m_pTreeListCtrl->GetItemHeight() );
}
if( m_pTreeListCtrl->GetVisibleCount() > 0 )
{
if( m_pTreeListCtrl->m_dwStyle&TLC_HGRID && !(m_pTreeListCtrl->m_dwStyle&TLC_HGRID_EXT) && !(m_pTreeListCtrl->m_dwStyle&TLC_VGRID_EXT) )
{
pDC->MoveTo( rcItem.left, rcItem.top - 1);
pDC->LineTo( rcItem.right-1, rcItem.top - 1);
}
}
for( int iGrid = m_pTreeListCtrl->GetVisibleCount(); iGrid <= nFirstRow + nShowRows; iGrid++ )
{
DrawGrid( pDC, rcItem );
if( m_pTreeListCtrl->m_dwStyle&TLC_HGRID_EXT && m_pTreeListCtrl->m_dwStyle&TLC_HGRID_FULL && rcItem.right<rcClient.right )
{
pDC->MoveTo( rcItem.right, rcItem.bottom - 1 );
pDC->LineTo( rcClient.right, rcItem.bottom - 1 );
}
rcItem.OffsetRect( 0, m_pTreeListCtrl->GetItemHeight() );
}
pDC->SetBkMode( nOldMode );
pDC->SelectObject( pOldFont );
pDC->SelectObject( pOldPen );
return TRUE;
}
BOOL CTLCDragWnd::DrawDragWnd( CDC* pDC )
{
// draw drag window
CRect rcItem;
GetClientRect( &rcItem );
pDC->FillSolidRect( &rcItem, m_pTreeListCtrl->m_crBkColor );
CPen Pen( PS_SOLID, 1, m_pTreeListCtrl->m_crGrid );
CPen* pOldPen = pDC->SelectObject( &Pen );
CFont* pOldFont = pDC->SelectObject( &m_pTreeListCtrl->m_Font );
int nOldMode = pDC->SetBkMode( TRANSPARENT );
ASSERT( m_pTreeListCtrl->m_arSelects.GetSize() > 0 );
CTreeListItem* pShowItem = (CTreeListItem*)m_pTreeListCtrl->m_arSelects[0];
DrawItem( pDC, rcItem, pShowItem );
pDC->SetBkMode( nOldMode );
pDC->SelectObject( pOldFont );
pDC->SelectObject( pOldPen );
return TRUE;
}
void CTLCDragWnd::DrawItem( CDC* pDC, CRect rcItem, CTreeListItem* pItem )
{
// draw item background
DrawItemBkgnd( pDC, rcItem, pItem );
// draw all columns
CTreeListColumnInfo* pColumnInfo;
int nColPos = 0;
for( int iShow = 0; iShow < m_pTreeListCtrl->m_arShows.GetSize(); iShow++, nColPos += pColumnInfo->m_nWidth )
{
int iCol;
// do NOT draw zero column;
iCol = m_pTreeListCtrl->m_arShows[ iShow ];
pColumnInfo = (CTreeListColumnInfo*)m_pTreeListCtrl->m_arColumns[iCol];
if( pColumnInfo->m_nWidth == 0 )
continue;
CRect rcColumn;
rcColumn.SetRect( 0, 0, pColumnInfo->m_nWidth, rcItem.Height() );
rcColumn.OffsetRect( nColPos, 0 );
rcColumn.OffsetRect( rcItem.left, rcItem.top );
if( iCol == 0 )
{
if( m_pTreeListCtrl->m_dwStyle&TLC_TREELIST )
DrawItemTree( pDC, rcColumn, pItem, iCol );
else
DrawItemMain( pDC, rcColumn, pItem, iCol );
}
else
{
DrawItemList( pDC, rcColumn, pItem, iCol );
}
}
// draw focus rect
CRect rcFocus;
if( pItem == m_pTreeListCtrl->m_pFocusItem )
{
CPen pen;
pen.CreatePen( PS_SOLID, 1, (COLORREF)0xFFFFFF );
CPen* ppen = pDC->SelectObject( &pen );
CRect rcFocus;
rcFocus = rcItem;
if( GetStyle()&TLC_HGRID )
rcFocus.DeflateRect( 0, 0, 0, 1 );
if( GetStyle()&TLC_VGRID )
rcFocus.DeflateRect( 0, 0, 1, 0 );
COLORREF crBkgnd, croldBkgnd;
crBkgnd = m_pTreeListCtrl->m_crBkColor;
croldBkgnd = pDC->SetBkColor( crBkgnd );
pDC->DrawFocusRect( rcFocus );
pDC->SetBkColor( croldBkgnd );
pDC->SelectObject( ppen );
}
}
void CTLCDragWnd::DrawGrid( CDC* pDC, CRect rcItem )
{
// draw all grids
CTreeListColumnInfo* pColumnInfo;
int nColPos = 0;
for( int iShow = 0; iShow < m_pTreeListCtrl->m_arShows.GetSize(); iShow++, nColPos += pColumnInfo->m_nWidth )
{
int iCol;
// do NOT draw zero column;
iCol = m_pTreeListCtrl->m_arShows[ iShow ];
pColumnInfo = (CTreeListColumnInfo*)m_pTreeListCtrl->m_arColumns[iCol];
if( pColumnInfo->m_nWidth == 0 )
continue;
CRect rcColumn;
rcColumn.SetRect( 0, 0, pColumnInfo->m_nWidth, rcItem.Height() );
rcColumn.OffsetRect( nColPos, 0 );
rcColumn.OffsetRect( rcItem.left, rcItem.top );
if( iCol == 0 )
{
// draw vertical grid line of tree
if( m_pTreeListCtrl->m_dwStyle&TLC_HGRID_EXT && m_pTreeListCtrl->m_dwStyle&TLC_TGRID )
{
pDC->MoveTo( rcColumn.left, rcColumn.bottom - 1);
pDC->LineTo( rcColumn.right-1, rcColumn.bottom - 1);
}
if( m_pTreeListCtrl->m_dwStyle&TLC_VGRID_EXT )
{
pDC->MoveTo( rcColumn.right-1, rcColumn.bottom - 1);
pDC->LineTo( rcColumn.right-1, rcColumn.top - 1 );
}
}
else
{
// draw vertical grid line and horizonal grid lin
if( m_pTreeListCtrl->m_dwStyle&TLC_HGRID_EXT )
{
pDC->MoveTo( rcColumn.left, rcColumn.bottom - 1);
pDC->LineTo( rcColumn.right, rcColumn.bottom - 1);
}
if( m_pTreeListCtrl->m_dwStyle&TLC_VGRID_EXT )
{
pDC->MoveTo( rcColumn.right-1, rcColumn.bottom - 1);
pDC->LineTo( rcColumn.right-1, rcColumn.top - 1 );
}
}
}
}
void CTLCDragWnd::DrawItemBkgnd( CDC* pDC, CRect rcItem, CTreeListItem* pItem )
{
// draw selected background
CRect rcBkgnd;
COLORREF crBkgnd;
if( pItem->GetSelected() )
{
rcBkgnd = rcItem;
if( GetStyle()&TLC_HGRID )
rcBkgnd.DeflateRect( 0, 0, 0, 1 );
if( GetStyle()&TLC_VGRID )
rcBkgnd.DeflateRect( 0, 0, 1, 0 );
if( m_pTreeListCtrl->GetState( TLS_FOCUS ) )
{
crBkgnd = m_pTreeListCtrl->m_crBkSelected;
}
else
{
crBkgnd = m_pTreeListCtrl->m_crBkSelectedNoFocus;
}
DrawItemExclude( pDC, rcItem, pItem );
pDC->FillSolidRect( rcBkgnd, crBkgnd );
::ExtSelectClipRgn( pDC->m_hDC, DEFAULT_HRGN, RGN_COPY );
}
}
void CTLCDragWnd::DrawItemExclude( CDC* pDC, CRect rcItem, CTreeListItem* pItem )
{
// exclude rects of selected item
CTreeListColumnInfo* pColumnInfo;
int nColPos = 0;
if( !pItem->GetSelected() )
return;
for( int iShow = 0; iShow < m_pTreeListCtrl->m_arShows.GetSize(); iShow++, nColPos += pColumnInfo->m_nWidth )
{
int iCol;
iCol = m_pTreeListCtrl->m_arShows[iShow];
pColumnInfo = (CTreeListColumnInfo*)m_pTreeListCtrl->m_arColumns[iCol];
CRect rcColumn;
rcColumn.SetRect( 0, 0, pColumnInfo->m_nWidth, rcItem.Height() );
rcColumn.OffsetRect( nColPos, 0 );
rcColumn.OffsetRect( rcItem.left, rcItem.top );
if( iCol == 0 )
{
CRect rcExclude;
int nPerfix = TLL_BORDER;
if ( m_pTreeListCtrl->m_dwStyle&TLC_TREELIST )
{
nPerfix += TLL_WIDTH * ( pItem->m_nLevel - 1 );
if( m_pTreeListCtrl->m_dwStyle&(TLC_TREELINE|TLC_BUTTON) )
nPerfix += TLL_WIDTH;
}
if( m_pTreeListCtrl->m_dwStyle&TLC_CHECKBOX )
{
if( pItem->GetState()&TLIS_SHOWCHECKBOX )
{
CRect rcCheckBox;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -