📄 trackwnd.c
字号:
/*
* trackwnd.c - Copyright (C) 1999,2000 Jay A. Key
*
* Implementation of the TrackWnd window class. TrackWnd is intended to
* be a child window of the main application window, and supports the
* displaying, editing and selectind of CD audio tracks. Includes a header
* control for changing the width of the items displayed on screen.
*
**********************************************************************
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <windows.h>
#include <commctrl.h>
#include <string.h>
#include "resources.h"
#include "trackwnd.h"
#include "globals.h"
#include "statusbar.h"
typedef struct
{
int iNum;
int iMax;
int iTextHeight;
int vw, vh;
int dx, dy; // scroll bar offsets into virtual window
int iHeaderHeight;
int hx[5]; // header x offsets
int hw[5]; // header widths
int iFound;
HWND hHeader;
BOOL bVScroll, bHScroll;
HPEN hBrownPen, hBlackPen;
int iSelected;
ADDTRACK *tracks;
} TRACKWNDEXTRA, *LPTRACKWNDEXTRA;
LRESULT CALLBACK TrackWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
void doTrackWndPaint( HWND hWnd, LPTRACKWNDEXTRA lpe );
void RecalcWindow( HWND hWnd, LPTRACKWNDEXTRA lpe );
void DeleteTrack( HWND hWnd, int iTrack, LPTRACKWNDEXTRA lpe );
void HandleVScroll( HWND, int, int, LPTRACKWNDEXTRA );
void HandleHScroll( HWND, int, int, LPTRACKWNDEXTRA );
void ComputeHeaderPos( HWND hHdr, HWND hParent );
HWND createHeader( HWND hWnd, HINSTANCE hInst );
char *notifyString( UINT code );
BOOL handleHeaderNotify( HWND hWnd, LPARAM lParam, LPTRACKWNDEXTRA lpe );
BOOL HandleLMouseDown( HWND hWnd, LPTRACKWNDEXTRA lpe, LPARAM lParam );
BOOL HandleRMouseDown( HWND hWnd, LPTRACKWNDEXTRA lpe, LPARAM lParam );
int CheckBoxHit( LPTRACKWNDEXTRA lpe, LPARAM lParam );
BOOL HandleCheckTrack( HWND hWnd, LPTRACKWNDEXTRA lpe, int trackNo, BOOL bChecked );
BOOL HandleInvertCheck( HWND hWnd, LPTRACKWNDEXTRA lpe, int trackNo );
int doContextMenu( HWND hWnd, LPARAM lParam );
BOOL RenameSelectedTrack( HWND hWnd, LPTRACKWNDEXTRA lpe );
LRESULT processFindFirst( LPTRACKWNDEXTRA lpe, LPADDTRACK lpAddTrack );
LRESULT processFindNext( LPTRACKWNDEXTRA lpe, LPADDTRACK lpAddTrack );
void convertuMsg( UINT uMsg, char * s );
void logWindowsProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
LRESULT CALLBACK EditSubclassWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
LRESULT CALLBACK FooWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
void SetTrackWndText( HWND hWnd );
LRESULT numChecked( LPTRACKWNDEXTRA lpe );
int doTrackContextMenu( HWND hParent, HWND hChild, LPARAM lParam );
BOOL setTrackStatus( LPTRACKWNDEXTRA lpe, int idx, LPCSTR s );
static char szTrackWndClass[] = "akripTrackWnd";
//static char szFooClass[] = "fooclass";
//static ADDTRACK tmpAddTrack;
HWND hHeader;
static int iCtlId = 10000;
static BOOL bInEditTrack = FALSE;
static HWND hEdit = NULL;
int InitTrackWnd( HINSTANCE hInst )
{
WNDCLASSEX wc;
LOGBRUSH lb;
HBRUSH hBrush;
ZeroMemory( &lb, sizeof(lb) );
lb.lbStyle = BS_SOLID;
lb.lbColor = RGB( 240, 255, 220 );
lb.lbHatch = 0;
hBrush = CreateBrushIndirect( &lb );
ZeroMemory( &wc, sizeof(wc) );
wc.cbSize = sizeof(wc);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)TrackWndProc;
wc.hInstance = hInst;
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = hBrush;
wc.lpszClassName = szTrackWndClass;
if ( !RegisterClassEx( &wc ) )
return 0;
#if 0
ZeroMemory( &wc, sizeof(wc) );
wc.cbSize = sizeof(wc);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)FooWndProc;
wc.hInstance = hInst;
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = hBrush;
wc.lpszClassName = szFooClass;
if ( !RegisterClassEx( &wc ) )
return 0;
#endif
return -1;
}
LRESULT CALLBACK TrackWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
LPTRACKWNDEXTRA lpe;
RECT rc;
logWindowsProc( hWnd, uMsg, wParam, lParam );
lpe = (LPTRACKWNDEXTRA)GetWindowLong( hWnd, GWL_USERDATA);
if ( !lpe && ( uMsg != WM_CREATE ) )
return DefWindowProc( hWnd, uMsg, wParam, lParam );
switch( uMsg )
{
case WM_COMMAND:
switch( HIWORD(wParam) )
{
case EN_SETFOCUS: break;
case EN_KILLFOCUS: break;
}
break;
case WM_CONTEXTMENU:
doTrackContextMenu( GetParent(hWnd), hWnd, lParam );
break;
case WM_SETFOCUS:
//OutputDebugString( "TrackWnd gaining focus" );
break;
case WM_KILLFOCUS:
//OutputDebugString( "TrackWnd losing focus" );
break;
case WM_NOTIFY:
if ( wParam == IDM_HEADER )
return handleHeaderNotify( hWnd, lParam, lpe );
break;
case WM_DESTROY:
lpe = (LPTRACKWNDEXTRA)GetWindowLong( hWnd, GWL_USERDATA );
if ( lpe )
{
if ( lpe->tracks )
GlobalFree( (HGLOBAL)lpe->tracks );
if ( lpe->hBrownPen )
DeleteObject( lpe->hBrownPen );
if ( lpe->hBlackPen )
DeleteObject( lpe->hBlackPen );
GlobalFree( lpe );
}
return DefWindowProc( hWnd, uMsg, wParam, lParam );
case WM_CREATE:
lpe = (LPTRACKWNDEXTRA)GlobalAlloc( GPTR, sizeof(TRACKWNDEXTRA) );
lpe->tracks = (LPADDTRACK)GlobalAlloc( GPTR, sizeof(ADDTRACK)*100 );
lpe->iNum = 0;
lpe->iMax = 100;
lpe->hBrownPen = CreatePen( PS_SOLID, 1, 0x00003384 );
lpe->hBlackPen = CreatePen( PS_SOLID, 1, 0x00000000 );
lpe->iSelected = -1;
lpe->iFound = -1;
SetWindowLong( hWnd, GWL_USERDATA, (LONG)lpe );
UpdateStatusBar();
break;
case WM_PAINT:
doTrackWndPaint( hWnd, lpe );
break;
case WM_VSCROLL:
HandleVScroll( hWnd, (int)LOWORD(wParam), (int)HIWORD(wParam), lpe );
RecalcWindow( hWnd, lpe );
GetClientRect( hWnd, &rc );
rc.top += (lpe->iHeaderHeight+1);
InvalidateRect( hWnd, &rc, TRUE );
UpdateWindow( hWnd );
break;
case WM_HSCROLL:
HandleHScroll( hWnd, (int)LOWORD(wParam), (int)HIWORD(wParam), lpe );
RecalcWindow( hWnd, lpe );
GetClientRect( hWnd, &rc );
rc.top += (lpe->iHeaderHeight+1);
InvalidateRect( hWnd, &rc, TRUE );
UpdateWindow( hWnd );
break;
case WM_SIZE:
RecalcWindow( hWnd, lpe );
break;
case WM_ADDTRACK:
if ( lpe->iNum >= lpe->iMax )
break;
memcpy( &(lpe->tracks[lpe->iNum]), (void *)lParam, sizeof(ADDTRACK) );
lpe->iNum++;
RecalcWindow( hWnd, lpe );
GetClientRect( hWnd, &rc );
rc.top += (lpe->iHeaderHeight+1);
InvalidateRect( hWnd, &rc, TRUE );
UpdateWindow( hWnd );
UpdateStatusBar();
break;
case WM_CHECKTRACK:
if ( HandleCheckTrack( hWnd, lpe, (int)wParam, (BOOL)lParam ) )
{
GetClientRect( hWnd, &rc );
rc.top += (lpe->iHeaderHeight+1);
InvalidateRect( hWnd, &rc, TRUE );
UpdateWindow( hWnd );
}
UpdateStatusBar();
break;
case WM_INVERTCHECK:
if ( HandleInvertCheck( hWnd, lpe, (int)wParam ) )
{
GetClientRect( hWnd, &rc );
rc.top += (lpe->iHeaderHeight+1);
InvalidateRect( hWnd, &rc, TRUE );
UpdateWindow( hWnd );
}
UpdateStatusBar();
break;
case WM_DELTRACK:
DeleteTrack( hWnd, (int)wParam, lpe );
RecalcWindow( hWnd, lpe );
GetClientRect( hWnd, &rc );
rc.top += (lpe->iHeaderHeight+1);
InvalidateRect( hWnd, &rc, TRUE );
UpdateWindow( hWnd );
UpdateStatusBar();
break;
case WM_SELTRACK:
if ( lpe->iSelected != (int)wParam )
{
lpe->iSelected = (int)wParam;
GetClientRect( hWnd, &rc );
rc.top += (lpe->iHeaderHeight+1);
InvalidateRect( hWnd, &rc, TRUE );
UpdateWindow( hWnd );
}
break;
case WM_MOUSEMOVE:
// grrr... it's an evil hack, but I need for the MouseCapture to
// remain with the edit control. When the user selects text with the
// mouse, the edit control automatically captures the mouse (even if
// it already has the mouse captured. Then it releases it, but not
// until after the WM_*BUTTONUP message. Until I write a custom
// edit control, I'll have to use this workaround.
if ( bInEditTrack && hEdit )
SetCapture( hEdit );
break;
case WM_LBUTTONDOWN:
if ( HandleLMouseDown( hWnd, lpe, lParam ) )
{
GetClientRect( hWnd, &rc );
rc.top += (lpe->iHeaderHeight+1);
InvalidateRect( hWnd, &rc, TRUE );
UpdateWindow( hWnd );
}
break;
case WM_RBUTTONDOWN:
if ( HandleRMouseDown( hWnd, lpe, lParam ) )
{
GetClientRect( hWnd, &rc );
rc.top += (lpe->iHeaderHeight+1);
InvalidateRect( hWnd, &rc, TRUE );
UpdateWindow( hWnd );
}
break;
case WM_RENSELTRACK:
if ( RenameSelectedTrack( hWnd, lpe ) )
{
GetClientRect( hWnd, &rc );
rc.top += (lpe->iHeaderHeight+1);
InvalidateRect( hWnd, &rc, TRUE );
UpdateWindow( hWnd );
}
break;
// copies the first checked track found into (LPADDTRACK)lParam .
// Returns index of the track, or -1 if no track found
case WM_FINDFIRSTTRACK:
return processFindFirst( lpe, (LPADDTRACK)lParam );
break;
// returns NULL if no more tracks are selected, otherwise LPADDTRACK
case WM_FINDNEXTTRACK:
return processFindNext( lpe, (LPADDTRACK)lParam );
break;
case WM_SETSELTEXT:
lstrcpy( lpe->tracks[lpe->iSelected].name, (char *)lParam );
GetClientRect( hWnd, &rc );
rc.top += (lpe->iHeaderHeight+1);
InvalidateRect( hWnd, &rc, TRUE );
UpdateWindow( hWnd );
break;
case WM_SETTRACKTEXT:
if ( (int)wParam < lpe->iNum )
{
lstrcpyn( lpe->tracks[wParam].name, (char *)lParam, MAX_PATH );
lpe->tracks[wParam].name[MAX_PATH] = '\0';
GetClientRect( hWnd, &rc );
rc.top += (lpe->iHeaderHeight+1);
InvalidateRect( hWnd, &rc, TRUE );
UpdateWindow( hWnd );
}
break;
case WM_SETTRACKSTATUS:
if ( setTrackStatus( lpe, (int)wParam, (LPCSTR)lParam ) )
{
GetClientRect( hWnd, &rc );
rc.top += (lpe->iHeaderHeight+1);
InvalidateRect( hWnd, &rc, TRUE );
UpdateWindow( hWnd );
}
break;
case WM_NUMCHECKED:
return numChecked( lpe );
case WM_NUMTRACKS:
return (LRESULT)lpe->iNum;
case WM_GETTRACK:
if ( lParam )
{
memcpy( (BYTE *)lParam, (BYTE *)&lpe->tracks[wParam], sizeof(ADDTRACK) );
return (LRESULT)lParam;
}
break;
case WM_CAPTURECHANGED:
//OutputDebugString( "TrackWndProc: WM_CAPTURECHANGED" );
break;
default:
return DefWindowProc( hWnd, uMsg, wParam, lParam );
}
return 0L;
}
HWND createTrackWnd( HWND hParent, HINSTANCE hInst, int idCtrl, LPRECT lprc )
{
LPTRACKWNDEXTRA lpe;
HWND hRet;
HDC hDC;
SIZE s;
RECT rc;
hRet = CreateWindowEx( 0, szTrackWndClass, "A Bogus Name",
WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL,
lprc->left, lprc->top,
lprc->right - lprc->left, lprc->bottom - lprc->top,
hParent, (HMENU)idCtrl, hInst, NULL );
/*
* compute text height
*/
lpe = (LPTRACKWNDEXTRA)GetWindowLong( hRet, GWL_USERDATA );
hDC = GetWindowDC( hRet );
GetTextExtentPoint32( hDC, "ABCDEFGHIJKLMNOPQRSTUVWYXZabcdefghijklmnopqrstuvwxyz", 52, &s );
lpe->iTextHeight = s.cy;
ReleaseDC( hRet, hDC );
lpe->hHeader = createHeader( hRet, hInst );
GetClientRect( lpe->hHeader, &rc );
lpe->iHeaderHeight = rc.bottom - rc.top + 1;
return hRet;
}
void doTrackWndPaint( HWND hWnd, LPTRACKWNDEXTRA lpe )
{
PAINTSTRUCT p;
HDC hDC;
RECT rc;
int i;
int oldBkMode;
int hw[5]; // width of header items
int hx[5]; // x offset of header items
DWORD len;
//char buf[32];
POINT pts[5];
HPEN hOldPen;
COLORREF oldBkColor, oldTextColor;
char buf[81];
GetClientRect( hWnd, &rc );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -