📄 trackwnd.c
字号:
hDC = BeginPaint( hWnd, &p );
/*
* compute the offsets for each header section
*/
ZeroMemory( hw, sizeof(int[5]) );
ZeroMemory( hx, sizeof(int[5]) );
for( i = 0; i < 4; i++ )
{
HD_ITEM hi;
ZeroMemory( &hi, sizeof(hi) );
hi.mask = HDI_WIDTH;
SendMessage( lpe->hHeader, HDM_GETITEM, i, (LPARAM)&hi );
hw[i] = hi.cxy;
hx[i+1] = hx[i] + hw[i];
}
oldBkMode = SetBkMode( hDC, TRANSPARENT );
for( i = 0; i < lpe->iNum; i++ )
{
// compute rectangle for track title
rc.left = hx[1] + 5 - lpe->dx;
rc.right = rc.left + hw[1] - 10;
rc.top = 6 + (lpe->iHeaderHeight + i*(lpe->iTextHeight+4) ) - lpe->dy;
rc.bottom = rc.top + 16;
if ( i == lpe->iSelected )
{
SetBkMode( hDC, OPAQUE );
oldBkColor = SetBkColor( hDC, RGB(20,20,140) );
oldTextColor = SetTextColor( hDC, oldBkColor );
}
DrawText( hDC, lpe->tracks[i].name, lstrlen( lpe->tracks[i].name ), &rc, DT_VCENTER );
if ( i == lpe->iSelected )
{
SetBkMode( hDC, TRANSPARENT );
SetBkColor( hDC, oldBkColor );
SetTextColor( hDC, oldTextColor );
}
// compute rectangle for status text
rc.left = hx[3] + 5 - lpe->dx;
rc.right = rc.left + hw[3] - 10;
DrawText( hDC, lpe->tracks[i].status, lstrlen( lpe->tracks[i].status ),
&rc, DT_VCENTER );
rc.left = hx[2] + 5 - lpe->dx;
rc.right = rc.left + hw[2] - 10;
len = lpe->tracks[i].len / 75;
wsprintf( buf, "%02d:%02d", len / 60, len % 60 );
DrawText( hDC, buf, lstrlen( buf ), &rc, DT_VCENTER );
// draw check box
pts[0].x = pts[3].x = pts[4].x = ((hx[1]+1)/2 - 4) - lpe->dx;
pts[1].x = pts[2].x = pts[0].x + 8;
pts[0].y = pts[1].y = pts[4].y = rc.top + 5;
pts[2].y = pts[3].y = rc.top + 13;
hOldPen = SelectObject( hDC, lpe->hBrownPen );
Polyline( hDC, pts, 5 );
if ( lpe->tracks[i].bChecked )
{
SelectObject( hDC, lpe->hBlackPen );
pts[0].x += 2;
pts[0].y += 3;
pts[1].x = pts[0].x + 2;
pts[1].y = pts[0].y + 3;
pts[2].x = pts[1].x + 7;
pts[2].y = pts[1].y - 7;
Polyline( hDC, pts, 3 );
pts[0].x += 1;
pts[1].x = pts[0].x + 2;
pts[1].y = pts[0].y + 3;
pts[2].x = pts[1].x + 7;
pts[2].y = pts[1].y - 7;
Polyline( hDC, pts, 3 );
}
SelectObject( hDC, hOldPen );
}
SetBkMode( hDC, oldBkMode );
EndPaint( hWnd, &p );
}
HFONT CreateTrackWndFont( HDC hDC )
{
LOGFONT lf;
ZeroMemory( &lf, sizeof(lf) );
lf.lfHeight = -MulDiv( 12, GetDeviceCaps( hDC, LOGPIXELSY), 72 );
lf.lfCharSet = DEFAULT_CHARSET;
lf.lfOutPrecision = OUT_TT_PRECIS;
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
lf.lfQuality = DEFAULT_QUALITY;
lf.lfPitchAndFamily = FF_MODERN | DEFAULT_PITCH;
strcpy( lf.lfFaceName, "Courier New" );
return CreateFontIndirect( &lf );
}
void RecalcWindow( HWND hWnd, LPTRACKWNDEXTRA lpe )
{
RECT rc;
SCROLLINFO si;
int i;
/*
* compute the offsets for each header section, used for mouse hit testing
* The paint code will recompute on a per paint basis
*/
ZeroMemory( lpe->hw, sizeof(int[5]) );
ZeroMemory( lpe->hx, sizeof(int[5]) );
for( i = 0; i < 3; i++ )
{
HD_ITEM hi;
ZeroMemory( &hi, sizeof(hi) );
hi.mask = HDI_WIDTH;
SendMessage( lpe->hHeader, HDM_GETITEM, i, (LPARAM)&hi );
lpe->hw[i] = hi.cxy;
lpe->hx[i+1] = lpe->hx[i] + lpe->hw[i];
}
GetClientRect( hWnd, &rc );
lpe->vh = lpe->iNum * (lpe->iTextHeight + 4) + lpe->iHeaderHeight + 5;
ZeroMemory( &si, sizeof(si) );
si.cbSize = sizeof(si);
si.fMask = SIF_PAGE | SIF_RANGE;
si.nMin = 0;
si.nMax = lpe->vh;
si.nPage = rc.bottom;
si.nPos = lpe->dy;
#if 0
if ( !lpe->bVScroll )
#endif
si.fMask |= SIF_POS;
SetScrollInfo( hWnd, SB_VERT, &si, TRUE );
if ( lpe->bVScroll && ( lpe->vh < rc.bottom ) )
lpe->bVScroll = FALSE;
else if ( !lpe->bVScroll && ( lpe->vh > rc.bottom ) )
lpe->bVScroll = TRUE;
if ( lpe->bVScroll == FALSE )
lpe->dy = 0;
ZeroMemory( &si, sizeof(si) );
si.cbSize = sizeof(si);
si.fMask = SIF_PAGE | SIF_RANGE;
si.nMin = 0;
si.nMax = lpe->vw;
si.nPage = rc.right;
si.nPos = lpe->dx;
if ( !lpe->bHScroll )
si.fMask |= SIF_POS;
SetScrollInfo( hWnd, SB_HORZ, &si, TRUE );
if ( lpe->bHScroll && ( lpe->vw < rc.right ) )
lpe->bHScroll = FALSE;
else if ( !lpe->bHScroll && ( lpe->vw > rc.right ) )
lpe->bHScroll = TRUE;
if ( lpe->bHScroll == FALSE )
lpe->dx = 0;
ComputeHeaderPos( lpe->hHeader, hWnd );
}
void DeleteTrack( HWND hWnd, int iTrack, LPTRACKWNDEXTRA lpe )
{
int i;
hWnd = hWnd;
if ( iTrack == (int)ALLTRACKS )
{
lpe->iSelected = -1;
lpe->iNum = 0;
return;
}
if ( iTrack > lpe->iNum )
return;
lpe->iSelected = -1;
for( i = iTrack; i < lpe->iNum; i++ )
{
lpe->tracks[i] = lpe->tracks[i+1];
}
lpe->iNum--;
}
void HandleHScroll( HWND hWnd, int nScrollCode, int nPos, LPTRACKWNDEXTRA lpe )
{
hWnd = hWnd; nScrollCode = nScrollCode; nPos = nPos; lpe = lpe;
}
void HandleVScroll( HWND hWnd, int nScrollCode, int nPos, LPTRACKWNDEXTRA lpe )
{
RECT rc;
SCROLLINFO si;
GetClientRect( hWnd, &rc );
si.cbSize = sizeof(si);
si.fMask = SIF_ALL;
GetScrollInfo( hWnd, SB_VERT, &si );
// one line of text takes up lpe->iTextHeight + 4 units
switch( nScrollCode )
{
case SB_BOTTOM: break;
case SB_ENDSCROLL: break;
case SB_LINEDOWN:
lpe->dy = min( lpe->dy + lpe->iTextHeight + 4,
lpe->vh - (rc.bottom-1) );
break;
case SB_LINEUP:
lpe->dy = max( 0, lpe->dy - (lpe->iTextHeight+4) );
break;
case SB_PAGEDOWN:
lpe->dy = min( lpe->dy + rc.bottom, lpe->vh - (rc.bottom-1) );
break;
case SB_PAGEUP:
lpe->dy = max( 0, lpe->dy - rc.bottom );
break;
case SB_THUMBPOSITION:
lpe->dy = nPos;
break;
case SB_THUMBTRACK:
lpe->dy = nPos;
break;
case SB_TOP: break;
break;
default:
//OutputDebugString( "Unknown scroll-bar message" );
break;
}
}
HWND createHeader( HWND hWnd, HINSTANCE hInst )
{
HD_ITEM hdi;
HWND hRet;
hRet = CreateWindowEx( 0L, WC_HEADER, "",
WS_CHILD | WS_BORDER | HDS_HORZ,
0, 0, 0, 0,
hWnd, (HMENU)IDM_HEADER, hInst, NULL );
if ( !hRet )
return NULL;
ComputeHeaderPos( hRet, hWnd );
hdi.mask = HDI_FORMAT | HDI_WIDTH;
hdi.cxy = 30;
hdi.fmt = HDF_LEFT | HDF_STRING;
SendMessage( hRet, HDM_INSERTITEM, 9999, (LPARAM)&hdi );
hdi.mask = HDI_TEXT | HDI_FORMAT | HDI_WIDTH;
hdi.pszText = "Title";
hdi.cxy = 200;
hdi.cchTextMax = lstrlen( hdi.pszText );
hdi.fmt = HDF_LEFT | HDF_STRING;
SendMessage( hRet, HDM_INSERTITEM, 9999, (LPARAM)&hdi );
hdi.mask = HDI_TEXT | HDI_FORMAT | HDI_WIDTH;
hdi.pszText = "Time";
hdi.cxy = 70;
hdi.cchTextMax = lstrlen( hdi.pszText );
hdi.fmt = HDF_LEFT | HDF_STRING;
SendMessage( hRet, HDM_INSERTITEM, 9999, (LPARAM)&hdi );
hdi.mask = HDI_TEXT | HDI_FORMAT | HDI_WIDTH;
hdi.pszText = "Status";
hdi.cxy = 200;
hdi.cchTextMax = lstrlen( hdi.pszText );
hdi.fmt = HDF_LEFT | HDF_STRING;
SendMessage( hRet, HDM_INSERTITEM, 9999, (LPARAM)&hdi );
return hRet;
}
void ComputeHeaderPos( HWND hHdr, HWND hParent )
{
WINDOWPOS wp;
HD_LAYOUT hdl;
RECT rc;
GetClientRect( hParent, &rc );
hdl.prc = &rc;
hdl.pwpos = ℘
SendMessage( hHdr, HDM_LAYOUT, 0, (LPARAM)&hdl );
SetWindowPos( hHdr, wp.hwndInsertAfter, wp.x, wp.y, wp.cx, wp.cy,
wp.flags | SWP_SHOWWINDOW );
}
BOOL handleHeaderNotify( HWND hWnd, LPARAM lParam, LPTRACKWNDEXTRA lpe )
{
HD_NOTIFY *lphd = (HD_NOTIFY *)lParam;
LPNMHDR lpnm = (LPNMHDR)lParam;
#if 0
if ( lpnm->code <= HDN_FIRST && lpnm->code >= HDN_LAST )
{
wsprintf( buf, "Header notify[%04X:%d:%d]: %s", lphd->hdr.hwndFrom, lphd->iItem,lphd->iButton, notifyString( lphd->hdr.code ) );
}
else
wsprintf( buf, "Header notify[%04X]: %s", lphd->hdr.hwndFrom, notifyString( lphd->hdr.code ) );
OutputDebugString( buf );
#endif
switch( lpnm->code )
{
case HDN_ITEMCHANGED:
RecalcWindow( hWnd, lpe );
InvalidateRect( hWnd, NULL, TRUE );
UpdateWindow( hWnd );
break;
case HDN_BEGINTRACK:
SetFocus( hWnd );
// prevent the first header from changing
if ( lphd->iItem == 0 )
return TRUE;
break;
}
return FALSE;
}
#ifndef NM_CUSTOMDRAW
#define NM_CUSTOMDRAW (NM_FIRST-12)
#endif
#ifndef NM_RELEASEDCAPTURE
#define NM_RELEASEDCAPTURE (NM_FIRST-16)
#endif
char *notifyString( UINT code )
{
static char buf[60];
switch( code )
{
case NM_CUSTOMDRAW: return "NM_CUSTOMDRAW";
case NM_CLICK: return "NM_CLICK";
case NM_DBLCLK: return "NM_DBLCLK";
case NM_KILLFOCUS: return "NM_KILLFOCUS";
case NM_OUTOFMEMORY: return "NM_OUTOFMEMORY";
case NM_RCLICK: return "NM_RCLICK";
case NM_RDBLCLK: return "NM_RDBLCLK";
case NM_RETURN: return "NM_RETURN";
case NM_SETFOCUS: return "NM_SETFOCUS";
case NM_RELEASEDCAPTURE: return "NM_RELEASEDCAPTURE";
case HDN_BEGINTRACK: return "HDN_BEGINTRACK";
case HDN_DIVIDERDBLCLICK: return "NM_DIVIDERDBLCLICK";
case HDN_ENDTRACK: return "HDN_ENDTRACK";
case HDN_ITEMCHANGED: return "HDN_ITEMCHANGED";
case HDN_ITEMCHANGING: return "HDN_ITEMCHANGING";
case HDN_ITEMCLICK: return "HDN_ITEMCLICK";
case HDN_ITEMDBLCLICK: return "HDN_ITEMDBLCLICK";
case HDN_TRACK: return "HDN_TRACK";
default: wsprintf( buf, "unknown %04X (%d)", code, code ); return buf;
}
}
/*
* determines if a mouse click (in window coordinates) was on a check box.
* If so, returns the index of the track. If not, returns -1
*/
int CheckBoxHit( LPTRACKWNDEXTRA lpe, LPARAM lParam )
{
int i, x, y;
int mx, my;
mx = (int)LOWORD(lParam) + lpe->dx;
my = (int)HIWORD(lParam) + lpe->dy;
for( i = 0; i < lpe->iNum; i++ )
{
x = (lpe->hx[1] + 1) / 2 - 4; // left side x value
y = 11 + lpe->iHeaderHeight + i*(lpe->iTextHeight + 4);
if ( (mx >= x) && (mx <= (x+8)) && (my >= y) && (my <= (y+8)) )
return i;
}
return -1;
}
/*
* Determines if a mouse click was on a track name on the screen. lParam
* is expected to be in client coordinates, as sent with the WM_LBUTTONDOWN,
* etc. messages. Returns the index of the track hit, or -1 if not on a
* track name
*/
int TrackNameHit( LPTRACKWNDEXTRA lpe, LPARAM lParam )
{
int i, x, y;
int mx, my;
RECT rc;
// if it's within the header, return -1 (no track hit)
if ( ((int)HIWORD(lParam)) <= lpe->iHeaderHeight )
return -1;
mx = (int)LOWORD(lParam) + lpe->dx;
my = (int)HIWORD(lParam) + lpe->dy;
for( i = 0; i < lpe->iNum; i++ )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -