/*
** Command & Conquer Renegade(tm)
** Copyright 2025 Electronic Arts Inc.
**
** 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 3 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, see .
*/
/////////////////////////////////////////////////////////////////////////////////
//
// ColorBar.cpp : implementation file
//
//
#include "StdAfx.H"
#include "ColorBar.H"
#include "Utils.H"
#include "Resource.H"
#include
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
extern HINSTANCE _hinstance;
/////////////////////////////////////////////////////////////////////////////
//
// ColorBarClass
//
ColorBarClass::ColorBarClass (void)
: m_hBitmap (NULL),
m_iBMPWidth (0),
m_iBMPHeight (0),
m_pBits (NULL),
m_hMemDC (NULL),
m_iColorPoints (0),
m_iMarkerWidth (0),
m_iMarkerHeight (0),
m_KeyFrameDIB (NULL),
m_pKeyFrameBits (NULL),
m_iCurrentKey (0),
m_MinPos (0),
m_MaxPos (1),
m_iScanlineSize (0),
m_bMoving (false),
m_bMoved (false),
m_SelectionPos (0),
m_bRedraw (true),
CWnd ()
{
::memset (m_ColorPoints, 0, sizeof (m_ColorPoints));
m_iColorPoints = 1;
m_ColorPoints[0].PosPercent = 0;
m_ColorPoints[0].StartRed = 0;
m_ColorPoints[0].StartGreen = 0;
m_ColorPoints[0].StartBlue = 0;
m_ColorPoints[0].flags = POINT_VISIBLE;
/*m_iColorPoints = 7;
m_ColorPoints[0].PosPercent = 0;
m_ColorPoints[0].StartRed = 255;
m_ColorPoints[0].StartGreen = 0;
m_ColorPoints[0].StartBlue = 0;
m_ColorPoints[0].flags = POINT_VISIBLE;
m_ColorPoints[1].PosPercent = (1.0F / 6.0F);
m_ColorPoints[1].StartRed = 255;
m_ColorPoints[1].StartGreen = 255;
m_ColorPoints[1].StartBlue = 0;
m_ColorPoints[1].flags = POINT_VISIBLE | POINT_CAN_MOVE;
m_ColorPoints[2].PosPercent = (2.0F / 6.0F);
m_ColorPoints[2].StartRed = 0;
m_ColorPoints[2].StartGreen = 255;
m_ColorPoints[2].StartBlue = 0;
m_ColorPoints[2].flags = POINT_VISIBLE | POINT_CAN_MOVE;
m_ColorPoints[3].PosPercent = (3.0F / 6.0F);
m_ColorPoints[3].StartRed = 0;
m_ColorPoints[3].StartGreen = 255;
m_ColorPoints[3].StartBlue = 255;
m_ColorPoints[3].flags = POINT_VISIBLE | POINT_CAN_MOVE;
m_ColorPoints[4].PosPercent = (4.0F / 6.0F);
m_ColorPoints[4].StartRed = 0;
m_ColorPoints[4].StartGreen = 0;
m_ColorPoints[4].StartBlue = 255;
m_ColorPoints[4].flags = POINT_VISIBLE | POINT_CAN_MOVE;
m_ColorPoints[5].PosPercent = (5.0F / 6.0F);
m_ColorPoints[5].StartRed = 255;
m_ColorPoints[5].StartGreen = 0;
m_ColorPoints[5].StartBlue = 255;
m_ColorPoints[5].flags = POINT_VISIBLE | POINT_CAN_MOVE;
m_ColorPoints[6].PosPercent = 1;
m_ColorPoints[6].StartRed = 255;
m_ColorPoints[6].StartGreen = 0;
m_ColorPoints[6].StartBlue = 0;
m_ColorPoints[6].flags = POINT_VISIBLE | POINT_CAN_MOVE;*/
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// ~ColorBarClass
//
ColorBarClass::~ColorBarClass (void)
{
if (m_hMemDC != NULL) {
::DeleteObject (m_hMemDC);
m_hMemDC = NULL;
}
Free_Marker_Bitmap ();
Free_Bitmap ();
return ;
}
BEGIN_MESSAGE_MAP(ColorBarClass, CWnd)
//{{AFX_MSG_MAP(ColorBarClass)
ON_WM_CREATE()
ON_WM_SIZE()
ON_WM_PAINT()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_WM_KILLFOCUS()
ON_WM_SETFOCUS()
ON_WM_KEYDOWN()
ON_WM_LBUTTONDBLCLK()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//
// RegisterColorBar
//
void
RegisterColorBar (HINSTANCE hinst)
{
// Has the class already been registered?
WNDCLASS wndclass = { 0 };
if (::GetClassInfo (hinst, "WWCOLORBAR", &wndclass) == FALSE) {
wndclass.style = CS_GLOBALCLASS | CS_OWNDC | CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
wndclass.lpfnWndProc = fnColorBarProc;
wndclass.hInstance = hinst;
wndclass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
wndclass.hCursor = ::LoadCursor (NULL, IDC_ARROW);
wndclass.lpszClassName = "WWCOLORBAR";
// Let the windows manager know about this global class
::RegisterClass (&wndclass);
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// fnColorBarProc
//
LRESULT WINAPI
fnColorBarProc
(
HWND hwnd,
UINT message,
WPARAM wparam,
LPARAM lparam
)
{
switch (message)
{
case WM_CREATE:
{
LPCREATESTRUCT pcreate_info = (LPCREATESTRUCT)lparam;
if (pcreate_info != NULL) {
// Should we create a new class manager for this window?
ColorBarClass *pwnd = (ColorBarClass *)pcreate_info->lpCreateParams;
BOOL created = FALSE;
if (pwnd == NULL) {
pwnd = new ColorBarClass;
created = TRUE;
}
// Pull some hacks to get MFC to use the message map
pwnd->Attach (hwnd);
// Let the window know its being created
pwnd->OnCreate (pcreate_info);
WNDPROC *pOldWndProc = pwnd->GetSuperWndProcAddr ();
if (pOldWndProc) {
WNDPROC pold_proc = (WNDPROC)::SetWindowLong (hwnd, GWL_WNDPROC, (DWORD)::AfxGetAfxWndProc ());
ASSERT (pold_proc != NULL);
(*pOldWndProc) = pold_proc;
}
// Store some information in the window handle
::SetProp (hwnd, "CLASSPOINTER", (HANDLE)pwnd);
::SetProp (hwnd, "CREATED", (HANDLE)created);
}
}
break;
case WM_DESTROY:
{
// Get the creation information from the window handle
ColorBarClass *pwnd = (ColorBarClass *)::GetProp (hwnd, "CLASSPOINTER");
BOOL created = (BOOL)::GetProp (hwnd, "CREATED");
if (pwnd != NULL) {
pwnd->Detach ();
WNDPROC *pOldWndProc = pwnd->GetSuperWndProcAddr ();
if (pOldWndProc) {
::SetWindowLong (hwnd, GWL_WNDPROC, (DWORD)(*pOldWndProc));
(*pOldWndProc) = NULL;
}
if (created) {
delete pwnd;
pwnd = NULL;
}
}
}
break;
}
// Allow default processing to occur
return ::DefWindowProc (hwnd, message, wparam, lparam);
}
/////////////////////////////////////////////////////////////////////////////
//
// OnCreate
//
int
ColorBarClass::OnCreate (LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate (lpCreateStruct) == -1)
return -1;
m_hMemDC = ::CreateCompatibleDC (NULL);
Create_Bitmap ();
return 0;
}
/////////////////////////////////////////////////////////////////////////////
//
// Create
//
BOOL
ColorBarClass::Create
(
LPCTSTR /*lpszClassName*/,
LPCTSTR lpszWindowName,
DWORD dwStyle,
const RECT &rect,
CWnd *pparent_wnd,
UINT nID,
CCreateContext * /*pContext*/
)
{
// Create the window (it will force the message map and everthing)
HWND hparent_wnd = (pparent_wnd != NULL) ? pparent_wnd->m_hWnd : NULL;
HWND hwnd = ::CreateWindow ("WWCOLORBAR",
lpszWindowName,
dwStyle,
rect.left,
rect.top,
rect.right - rect.left,
rect.bottom - rect.top,
hparent_wnd,
(HMENU)nID,
_hinstance,//::AfxGetInstanceHandle (),
this);
// Return the true/false result code
return (hwnd != NULL);
}
/////////////////////////////////////////////////////////////////////////////
//
// Create_Bitmap
//
void
ColorBarClass::Create_Bitmap (void)
{
// Start fresh
Free_Bitmap ();
CRect rect;
GetClientRect (&rect);
m_iBMPWidth = rect.Width ();
m_iBMPHeight = rect.Height ();
// Assume the color portion of the control takes the whole client aread
m_ColorArea.left = 0;
m_ColorArea.top = 0;
m_ColorArea.right = m_iBMPWidth;
m_ColorArea.bottom = m_iBMPHeight;
//
// Deflate the rect to make room for any frame
//
LONG style = ::GetWindowLong (m_hWnd, GWL_STYLE);
if (style & CBRS_FRAME_MASK) {
m_ColorArea.InflateRect (-1, -1);
}
//
// Decrease the width or height if frame markers are shown
//
if (style & CBRS_SHOW_FRAMES) {
Load_Key_Frame_BMP ();
if (style & CBRS_HORZ) {
m_ColorArea.left += (m_iMarkerWidth >> 1);
m_ColorArea.right -= (m_iMarkerWidth >> 1);
m_ColorArea.bottom -= (m_iMarkerHeight >> 1);
} else {
m_ColorArea.top += (m_iMarkerHeight >> 1);
m_ColorArea.bottom -= (m_iMarkerHeight >> 1);
m_ColorArea.right -= (m_iMarkerWidth >> 1);
}
} else if (style & CBRS_HAS_SEL) {
if (style & CBRS_HORZ) {
m_ColorArea.left += 2;
m_ColorArea.right -= 2;
} else {
m_ColorArea.top += 2;
m_ColorArea.bottom -= 2;
}
}
// Set-up the fields of the BITMAPINFOHEADER
BITMAPINFOHEADER bitmap_info;
bitmap_info.biSize = sizeof (BITMAPINFOHEADER);
bitmap_info.biWidth = m_iBMPWidth;
bitmap_info.biHeight = -m_iBMPHeight; // Top-down DIB uses negative height
bitmap_info.biPlanes = 1;
bitmap_info.biBitCount = 24;
bitmap_info.biCompression = BI_RGB;
bitmap_info.biSizeImage = ((m_iBMPWidth * m_iBMPHeight) * 3);
bitmap_info.biXPelsPerMeter = 0;
bitmap_info.biYPelsPerMeter = 0;
bitmap_info.biClrUsed = 0;
bitmap_info.biClrImportant = 0;
// Get a temporary screen DC
HDC hscreen_dc = ::GetDC (NULL);
// Create a bitmap that we can access the bits directly of
m_hBitmap = ::CreateDIBSection (hscreen_dc,
(const BITMAPINFO *)&bitmap_info,
DIB_RGB_COLORS,
(void **)&m_pBits,
NULL,
0L);
// Release our temporary screen DC
::ReleaseDC (NULL, hscreen_dc);
// Window's bitmaps are DWORD aligned, so make sure
// we take that into account.
int alignment_offset = (m_iBMPWidth * 3) % 4;
alignment_offset = (alignment_offset != 0) ? (4 - alignment_offset) : 0;
m_iScanlineSize = (m_iBMPWidth * 3) + alignment_offset;
Update_Point_Info ();
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Free_Bitmap
//
void
ColorBarClass::Free_Bitmap (void)
{
if (m_hBitmap != NULL) {
::DeleteObject (m_hBitmap);
m_hBitmap = NULL;
m_pBits = NULL;
}
m_iBMPWidth = 0;
m_iBMPHeight = 0;
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnSize
//
void
ColorBarClass::OnSize
(
UINT nType,
int cx,
int cy
)
{
// Allow the base class to process this message
CWnd::OnSize (nType, cx, cy);
// Recreate the BMP to reflect the new window size
Create_Bitmap ();
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Paint_Bar_Vert
//
void
ColorBarClass::Paint_Bar_Vert
(
int x_pos,
int y_pos,
int width,
int height,
UCHAR *pbits
)
{
// Loop through all the color switches
int row = y_pos;
for (int color_point = 0; color_point < m_iColorPoints; color_point ++) {
// Get the starting red, green, and blue values for this color lerp
float red = m_ColorPoints[color_point].StartRed;
float green = m_ColorPoints[color_point].StartGreen;
float blue = m_ColorPoints[color_point].StartBlue;
// Index into the bitmap's bits
int bitmap_index = (row * m_iScanlineSize) + (x_pos * 3);
// Loop through all rows of color in this 'switch'
int end_pos = m_ColorPoints[color_point].EndPos;
end_pos = (end_pos > (y_pos + height)) ? (y_pos + height) : end_pos;
for (; row < m_ColorPoints[color_point].EndPos; row ++) {
// Paint a complete row of color data
int bitmap_offset = 0;
for (int col = x_pos; col < (x_pos + width); col ++) {
// Paint the pixel
pbits[bitmap_index + bitmap_offset] = UCHAR(((int)blue) & 0xFF);
pbits[bitmap_index + bitmap_offset+1] = UCHAR(((int)green) & 0xFF);
pbits[bitmap_index + bitmap_offset+2] = UCHAR(((int)red) & 0xFF);
// Move to the next col
bitmap_offset += 3;
}
// Advance to the next row
bitmap_index += m_iScanlineSize;
// Increment the row's color
red += m_ColorPoints[color_point].RedInc;
green += m_ColorPoints[color_point].GreenInc;
blue += m_ColorPoints[color_point].BlueInc;
}
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Paint_Bar_Horz
//
void
ColorBarClass::Paint_Bar_Horz
(
int x_pos,
int y_pos,
int width,
int height,
UCHAR *pbits
)
{
LONG style = ::GetWindowLong (m_hWnd, GWL_STYLE);
if (style & CBRS_PAINT_GRAPH) {
// Loop through all the color switches
int col = x_pos;
for (int color_point = 0; color_point < m_iColorPoints; color_point ++) {
float graph_percent = m_ColorPoints[color_point].StartGraphPercent;
// Index into the bitmap's bits
int bitmap_index = (y_pos * m_iScanlineSize) + (col * 3);
// Loop through all columns of color in this 'switch'
int end_pos = m_ColorPoints[color_point].EndPos;
end_pos = (end_pos > (x_pos + width)) ? (x_pos + width) : end_pos;
for (; col < m_ColorPoints[color_point].EndPos; col ++) {
// Paint a complete column of color data
int bitmap_offset = 0;
bool prev_was = true;
for (int row = y_pos; row < (y_pos + height); row ++) {
float percent = 1 - graph_percent;
float height_percent = (((float)row) / ((float)height));
if (percent < height_percent) {
// Paint the pixel
if (prev_was == false) {
pbits[bitmap_index + bitmap_offset] = 0;
pbits[bitmap_index + bitmap_offset+1] = 0;
pbits[bitmap_index + bitmap_offset+2] = 0;
} else {
pbits[bitmap_index + bitmap_offset] = 255;
pbits[bitmap_index + bitmap_offset+1] = 128 + UCHAR(((int)((1-height_percent) * 128)) & 0xFF);
pbits[bitmap_index + bitmap_offset+2] = UCHAR(((int)((1-height_percent) * 255)) & 0xFF);
}
prev_was = true;
} else {
// Paint the pixel
pbits[bitmap_index + bitmap_offset] = 128;
pbits[bitmap_index + bitmap_offset+1] = 128;
pbits[bitmap_index + bitmap_offset+2] = 128;
prev_was = false;
}
// Move down to the next row
bitmap_offset += m_iScanlineSize;
}
// Advance to the next column
bitmap_index += 3;
graph_percent += m_ColorPoints[color_point].GraphPercentInc;
}
}
} else {
// Loop through all the color switches
int col = x_pos;
for (int color_point = 0; color_point < m_iColorPoints; color_point ++) {
// Get the starting red, green, and blue values for this color lerp
float red = m_ColorPoints[color_point].StartRed;
float green = m_ColorPoints[color_point].StartGreen;
float blue = m_ColorPoints[color_point].StartBlue;
// Index into the bitmap's bits
int bitmap_index = (y_pos * m_iScanlineSize) + (col * 3);
// Loop through all columns of color in this 'switch'
int end_pos = m_ColorPoints[color_point].EndPos;
end_pos = (end_pos > (x_pos + width)) ? (x_pos + width) : end_pos;
for (; col < m_ColorPoints[color_point].EndPos; col ++) {
// Paint a complete column of color data
int bitmap_offset = 0;
for (int row = y_pos; row < (y_pos + height); row ++) {
// Paint the pixel
pbits[bitmap_index + bitmap_offset] = UCHAR(((int)blue) & 0xFF);
pbits[bitmap_index + bitmap_offset+1] = UCHAR(((int)green) & 0xFF);
pbits[bitmap_index + bitmap_offset+2] = UCHAR(((int)red) & 0xFF);
// Move down to the next row
bitmap_offset += m_iScanlineSize;
}
// Advance to the next column
bitmap_index += 3;
// Increment the column's color
red += m_ColorPoints[color_point].RedInc;
green += m_ColorPoints[color_point].GreenInc;
blue += m_ColorPoints[color_point].BlueInc;
}
}
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Paint_DIB
//
void
ColorBarClass::Paint_DIB (void)
{
CRect frame_rect = m_ColorArea;
frame_rect.InflateRect (1, 1);
//
// Erase the background to start...
//
CRect fill_rect (0, 0, m_iBMPWidth, m_iBMPHeight);
HBITMAP hold_bmp = (HBITMAP)::SelectObject (m_hMemDC, m_hBitmap);
::FillRect (m_hMemDC, &fill_rect, (HBRUSH)(COLOR_3DFACE + 1));
::SelectObject (m_hMemDC, hold_bmp);
//
// Paint the border (if any)
//
LONG style = ::GetWindowLong (m_hWnd, GWL_STYLE);
if (style & CBRS_SUNKEN) {
::Draw_Sunken_Rect (m_pBits, frame_rect, m_iScanlineSize);
} else if (style & CBRS_RAISED) {
::Draw_Raised_Rect (m_pBits, frame_rect, m_iScanlineSize);
} else if (style & CBRS_FRAME) {
::Frame_Rect (m_pBits, frame_rect, RGB (0, 0, 0), m_iScanlineSize);
}
//
// Now draw the color areas
//
if (style & CBRS_HORZ) {
Paint_Bar_Horz (m_ColorArea.left,
m_ColorArea.top,
m_ColorArea.Width (),
m_ColorArea.Height (),
m_pBits);
} else {
Paint_Bar_Vert (m_ColorArea.left,
m_ColorArea.top,
m_ColorArea.Width (),
m_ColorArea.Height (),
m_pBits);
}
//
// Do we need to paint the keyframe markers?
//
if (style & CBRS_SHOW_FRAMES) {
//
// Setup the marker positions
//
int x_pos = 0;
int y_pos = 0;
int *position = NULL;
int offset = 0;
if (style & CBRS_HORZ) {
position = &x_pos;
x_pos = m_ColorArea.left;
y_pos = m_ColorArea.Height () - (m_iMarkerHeight >> 1);
offset = -(m_iMarkerWidth >> 1);
} else {
position = &y_pos;
x_pos = m_ColorArea.Width () - (m_iMarkerWidth >> 1);
y_pos = m_ColorArea.top;
offset = -(m_iMarkerHeight >> 1);
}
//
// Paint all the keyframe markers
//
for (int color_point = 0; color_point < m_iColorPoints; color_point ++) {
(*position) = m_ColorPoints[color_point].StartPos;
(*position) += offset;
Paint_Key_Frame (x_pos, y_pos);
}
} else if (style & CBRS_HAS_SEL) {
CRect frame;
Get_Selection_Rectangle (frame);
//
// Paint the selection rectangles
//
::Frame_Rect (m_pBits, frame, RGB (0, 0, 0), m_iScanlineSize);
frame.InflateRect (-1, -1);
::Frame_Rect (m_pBits, frame, RGB (255, 255, 255), m_iScanlineSize);
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnPaint
//
void
ColorBarClass::OnPaint (void)
{
CPaintDC dc (this);
Paint_Screen (dc);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Paint_Screen
//
void
ColorBarClass::Paint_Screen (HDC hwnd_dc)
{
if (m_hMemDC != NULL) {
//
// Blit the actual color bar to the screen
//
HBITMAP hold_bmp = (HBITMAP)::SelectObject (m_hMemDC, m_hBitmap);
::BitBlt (hwnd_dc, 0, 0, m_iBMPWidth, m_iBMPHeight, m_hMemDC, 0, 0, SRCCOPY);
::SelectObject (m_hMemDC, hold_bmp);
//
// Do we have the focus?
//
if (::GetFocus () == m_hWnd) {
LONG style = ::GetWindowLong (m_hWnd, GWL_STYLE);
if (style & CBRS_SHOW_FRAMES) {
//
// Calculate the current frame marker's current rectangle
//
CRect focus_rect;
LONG style = ::GetWindowLong (m_hWnd, GWL_STYLE);
if (style & CBRS_HORZ) {
focus_rect.left = m_ColorPoints[m_iCurrentKey].StartPos - (m_iMarkerWidth >> 1);
focus_rect.top = m_ColorArea.Height () - (m_iMarkerHeight >> 1);
} else {
focus_rect.left = m_ColorArea.Width () - (m_iMarkerWidth >> 1);
focus_rect.top = m_ColorPoints[m_iCurrentKey].StartPos - (m_iMarkerHeight >> 1);
}
focus_rect.right = focus_rect.left + m_iMarkerWidth;
focus_rect.bottom = focus_rect.top + m_iMarkerHeight;
//
// Paint the focus rectangle
//
::DrawFocusRect (hwnd_dc, focus_rect);
} else if (style & CBRS_HAS_SEL) {
//
// Paint the focus rectangle
//
CRect focus_rect;
Get_Selection_Rectangle (focus_rect);
::DrawFocusRect (hwnd_dc, focus_rect);
}
}
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Get_Point
//
bool
ColorBarClass::Get_Point
(
int index,
float *position,
float *red,
float *green,
float *blue
)
{
// Assume failure
bool retval = false;
if ((index >= 0) && (index < m_iColorPoints)) {
// Return the position to the caller if requested
if (position != NULL) {
(*position) = m_MinPos + (m_ColorPoints[index].PosPercent * (m_MaxPos - m_MinPos));
}
// Return the red value to the caller if requested
if (red != NULL) {
(*red) = m_ColorPoints[index].StartRed;
}
// Return the green value to the caller if requested
if (green != NULL) {
(*green) = m_ColorPoints[index].StartGreen;
}
// Return the blue value to the caller if requested
if (blue != NULL) {
(*blue) = m_ColorPoints[index].StartBlue;
}
}
// Return the true/false result code
return retval;
}
/////////////////////////////////////////////////////////////////////////////
//
// Insert_Point
//
bool
ColorBarClass::Insert_Point (CPoint point, DWORD flags)
{
int new_index = 0;
int position = 0;
float percent = 0;
float red = 0;
float green = 0;
float blue = 0;
//
// Determine what properties the new point should have
//
LONG style = ::GetWindowLong (m_hWnd, GWL_STYLE);
if (style & CBRS_HORZ) {
position = point.x - m_ColorArea.left;
percent = ((float)(point.x - m_ColorArea.left)) / ((float)m_ColorArea.Width ());
int bmp_index = ((m_ColorArea.top + 1) * m_iScanlineSize) + (point.x * 3);
blue = m_pBits[bmp_index];
green = m_pBits[bmp_index+1];
red = m_pBits[bmp_index+2];
} else {
position = point.y - m_ColorArea.top;
percent = ((float)(point.y - m_ColorArea.top)) / ((float)m_ColorArea.Height ());
int bmp_index = (point.y * m_iScanlineSize) + (m_ColorArea.left * 3);
blue = m_pBits[bmp_index];
green = m_pBits[bmp_index+1];
red = m_pBits[bmp_index+2];
}
//
// Find the index where this point should be inserted
//
bool found = false;
float graph_percent = 0;
for (int index = 0; (index < m_iColorPoints) && !found; index ++) {
if ((position > m_ColorPoints[index].StartPos) &&
(position < m_ColorPoints[index].EndPos)) {
new_index = index + 1;
found = true;
//
// Determine what graph percent to use if the control
// is in graph mode
//
float key_percent = (((float)position) - ((float)m_ColorPoints[index].StartPos)) / float(m_ColorPoints[index].EndPos - m_ColorPoints[index].StartPos);
float graph_start = m_ColorPoints[index].StartGraphPercent;
float graph_delta = (m_ColorPoints[index].EndPos - m_ColorPoints[index].StartPos) * m_ColorPoints[index].GraphPercentInc;
graph_percent = graph_start + (key_percent * graph_delta);
}
}
bool retval = false;
if (found) {
Set_Redraw (false);
//
// Insert the new point
//
float position = m_MinPos + ((m_MaxPos - m_MinPos) * percent);
retval = Insert_Point (new_index, position, red, green, blue);
if (retval) {
Set_Graph_Percent (new_index, graph_percent);
m_iCurrentKey = new_index;
}
Set_Redraw (true);
}
return retval;
}
/////////////////////////////////////////////////////////////////////////////
//
// Insert_Point
//
bool
ColorBarClass::Insert_Point
(
int index,
float position,
float red,
float green,
float blue,
DWORD flags
)
{
// Assume failure
bool retval = false;
// Params valid?
if (((m_iColorPoints + 1) < MAX_COLOR_POINTS) &&
(index >= 0) &&
(index <= m_iColorPoints)) {
// Bump all the points up one position in the array
::memmove (&m_ColorPoints[index + 1],
&m_ColorPoints[index],
sizeof (COLOR_POINT) * (m_iColorPoints - index));
// Increment the point count
m_iColorPoints ++;
// Now all we have to do is modify the contents of the new point
retval = Modify_Point (index, position, red, green, blue, flags);
}
// Return the true/false result code
return retval;
}
/////////////////////////////////////////////////////////////////////////////
//
// Delete_Point
//
bool
ColorBarClass::Delete_Point (int index)
{
// Assume failure
bool retval = false;
// Params valid?
if ((index > 0) &&
(index < m_iColorPoints)) {
// Bump all the points up one position in the array
::memmove (&m_ColorPoints[index],
&m_ColorPoints[index + 1],
sizeof (COLOR_POINT) * (m_iColorPoints - (index + 1)));
// Decrement the point count
m_iColorPoints --;
if (m_iCurrentKey > 0) {
m_iCurrentKey --;
}
// Rebuild any color information we may need to
Update_Point_Info ();
// Force the window to be repainted
Repaint ();
retval = true;
}
// Return the true/false result code
return retval;
}
/////////////////////////////////////////////////////////////////////////////
//
// Modify_Point
//
bool
ColorBarClass::Modify_Point
(
int index,
float position,
float red,
float green,
float blue,
DWORD flags
)
{
// Assume failure
bool retval = false;
if ((index >= 0) && (index < m_iColorPoints)) {
// Update the information about this color point
m_ColorPoints[index].PosPercent = ((position - m_MinPos) / (m_MaxPos - m_MinPos));
m_ColorPoints[index].StartRed = red;
m_ColorPoints[index].StartGreen = green;
m_ColorPoints[index].StartBlue = blue;
m_ColorPoints[index].flags = flags;
if (index == 0) {
m_ColorPoints[index].flags &= ~POINT_CAN_MOVE;
}
// Rebuild any color information we may need to
Update_Point_Info ();
// Force the window to be repainted
Repaint ();
retval = true;
} else if (index >= m_iColorPoints) {
// If the user wants to tag on onto the end, then insert a new point...
retval = Insert_Point (m_iColorPoints, position, red, green, blue);
}
// Return the true/false result code
return retval;
}
/////////////////////////////////////////////////////////////////////////////
//
// Set_Range
//
void
ColorBarClass::Set_Range
(
float min,
float max
)
{
m_MinPos = min;
m_MaxPos = max;
m_SelectionPos = m_MinPos;
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Update_Point_Info
//
void
ColorBarClass::Update_Point_Info (void)
{
int width = m_ColorArea.Width ();
int height = m_ColorArea.Height ();
LONG style = GetWindowLong (m_hWnd, GWL_STYLE);
if (style & CBRS_HORZ) {
// Loop through all the color points
for (int index = 0; index < m_iColorPoints; index ++) {
// Update the absolute starting position for this point
m_ColorPoints[index].StartPos = m_ColorArea.left + int(m_ColorPoints[index].PosPercent * width);
// Update the color information for the previous point
if (index > 0) {
m_ColorPoints[index-1].EndPos = m_ColorPoints[index].StartPos;
//
// Assign color increments to the previous color point
//
int width = m_ColorPoints[index-1].EndPos - m_ColorPoints[index-1].StartPos;
m_ColorPoints[index-1].RedInc = (m_ColorPoints[index].StartRed - m_ColorPoints[index-1].StartRed) / ((float)width);
m_ColorPoints[index-1].GreenInc = (m_ColorPoints[index].StartGreen - m_ColorPoints[index-1].StartGreen) / ((float)width);
m_ColorPoints[index-1].BlueInc = (m_ColorPoints[index].StartBlue - m_ColorPoints[index-1].StartBlue) / ((float)width);
// Assign the graph increment to the previous point
m_ColorPoints[index-1].GraphPercentInc = (m_ColorPoints[index].StartGraphPercent - m_ColorPoints[index-1].StartGraphPercent) / ((float)width);
}
}
m_ColorPoints[index-1].RedInc = 0;
m_ColorPoints[index-1].GreenInc = 0;
m_ColorPoints[index-1].BlueInc = 0;
m_ColorPoints[index-1].GraphPercentInc = 0;
m_ColorPoints[index-1].EndPos = m_ColorArea.right;
} else {
// Loop through all the color points
for (int index = 0; index < m_iColorPoints; index ++) {
// Update the absolute starting position for this point
m_ColorPoints[index].StartPos = m_ColorArea.top + int(m_ColorPoints[index].PosPercent * height);
// Update the color information for the previous point
if (index > 0) {
m_ColorPoints[index-1].EndPos = m_ColorPoints[index].StartPos;
// Assign color increments to the previous color point
int height = m_ColorPoints[index-1].EndPos - m_ColorPoints[index-1].StartPos;
m_ColorPoints[index-1].RedInc = (m_ColorPoints[index].StartRed - m_ColorPoints[index-1].StartRed) / ((float)height);
m_ColorPoints[index-1].GreenInc = (m_ColorPoints[index].StartGreen - m_ColorPoints[index-1].StartGreen) / ((float)height);
m_ColorPoints[index-1].BlueInc = (m_ColorPoints[index].StartBlue - m_ColorPoints[index-1].StartBlue) / ((float)height);
}
}
m_ColorPoints[index-1].RedInc = 0;
m_ColorPoints[index-1].GreenInc = 0;
m_ColorPoints[index-1].BlueInc = 0;
m_ColorPoints[index-1].EndPos = m_ColorArea.bottom;
}
// Repaint the color bar
Paint_DIB ();
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Free_Marker_Bitmap
//
void
ColorBarClass::Free_Marker_Bitmap (void)
{
if (m_KeyFrameDIB != NULL) {
::DeleteObject (m_KeyFrameDIB);
m_KeyFrameDIB = NULL;
m_pKeyFrameBits = NULL;
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Load_Key_Frame_BMP
//
void
ColorBarClass::Load_Key_Frame_BMP (void)
{
Free_Marker_Bitmap ();
//
// Load the appropriate BMP based on the barstyle
//
LONG style = ::GetWindowLong (m_hWnd, GWL_STYLE);
HBITMAP hbmp = NULL;
if (style & CBRS_HORZ) {
hbmp = ::LoadBitmap (_hinstance, MAKEINTRESOURCE (IDB_KEYFRAME_V));
} else {
hbmp = ::LoadBitmap (_hinstance, MAKEINTRESOURCE (IDB_KEYFRAME_H));
}
//
// Get the dimensions of the BMP
//
BITMAP bmp_info = { 0 };
::GetObject (hbmp, sizeof (BITMAP), (LPVOID)&bmp_info);
m_iMarkerWidth = bmp_info.bmWidth;
m_iMarkerHeight = bmp_info.bmHeight;
// Set-up the fields of the BITMAPINFOHEADER
BITMAPINFOHEADER bitmap_info;
bitmap_info.biSize = sizeof (BITMAPINFOHEADER);
bitmap_info.biWidth = m_iMarkerWidth;
bitmap_info.biHeight = -m_iMarkerHeight; // Top-down DIB uses negative height
bitmap_info.biPlanes = 1;
bitmap_info.biBitCount = 24;
bitmap_info.biCompression = BI_RGB;
bitmap_info.biSizeImage = ((m_iMarkerWidth * m_iMarkerHeight) * 3);
bitmap_info.biXPelsPerMeter = 0;
bitmap_info.biYPelsPerMeter = 0;
bitmap_info.biClrUsed = 0;
bitmap_info.biClrImportant = 0;
// Get a temporary screen DC
HDC hscreen_dc = ::GetDC (NULL);
// Create a bitmap that we can access the bits directly of
m_KeyFrameDIB = ::CreateDIBSection (hscreen_dc,
(const BITMAPINFO *)&bitmap_info,
DIB_RGB_COLORS,
(void **)&m_pKeyFrameBits,
NULL,
0L);
// Release our temporary screen DC
::ReleaseDC (NULL, hscreen_dc);
// Initialize 2 temp DCs so we can copy from the BMP to the DIB section
HDC htemp_dc = ::CreateCompatibleDC (NULL);
HBITMAP hold_bmp1 = (HBITMAP)::SelectObject (m_hMemDC, m_KeyFrameDIB);
HBITMAP hold_bmp2 = (HBITMAP)::SelectObject (htemp_dc, hbmp);
// Copy the marker from the BMP to the DIB section
::BitBlt (m_hMemDC, 0, 0, m_iMarkerWidth, m_iMarkerHeight, htemp_dc, 0, 0, SRCCOPY);
// Restore the DCs
::SelectObject (m_hMemDC, hold_bmp1);
::SelectObject (htemp_dc, hold_bmp2);
::DeleteDC (htemp_dc);
::DeleteObject (hbmp);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Paint_Key_Frame
//
void
ColorBarClass::Paint_Key_Frame (int x_pos, int y_pos)
{
// Window's bitmaps are DWORD aligned, so make sure
// we take that into account.
int alignment_offset = (m_iMarkerWidth * 3) % 4;
alignment_offset = (alignment_offset != 0) ? (4 - alignment_offset) : 0;
int marker_scanline = (m_iMarkerWidth * 3) + alignment_offset;
int width_in_bytes = m_iMarkerWidth * 3;
if ((m_pBits != NULL) && (m_pKeyFrameBits != NULL)) {
int dest_index = (m_iScanlineSize * y_pos) + (x_pos * 3);
int src_index = 0;
//
// 'Blit' the image from the source buffer to the dest buffer
//
for (int scanline = 0; scanline < m_iMarkerHeight; scanline ++) {
for (int pixel = 0; pixel < m_iMarkerWidth; pixel ++) {
BYTE blue = m_pKeyFrameBits[src_index ++];
BYTE green = m_pKeyFrameBits[src_index ++];
BYTE red = m_pKeyFrameBits[src_index ++];
if (blue == 255 && green == 0 && red == 255) {
dest_index += 3;
} else {
m_pBits[dest_index ++] = blue;
m_pBits[dest_index ++] = green;
m_pBits[dest_index ++] = red;
}
}
// Skip to the next scanline
dest_index += (m_iScanlineSize - width_in_bytes);
src_index += alignment_offset;
}
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Marker_From_Point
//
int
ColorBarClass::Marker_From_Point (CPoint point)
{
int marker_index = -1;
//
// Setup the data we need for the search
//
LONG style = ::GetWindowLong (m_hWnd, GWL_STYLE);
int accept_dist = 0;
int position = 0;
if (style & CBRS_HORZ) {
position = point.x;// - m_ColorArea.left;
accept_dist = (m_iMarkerWidth + 1) >> 1;
} else {
position = point.y;// - m_ColorArea.top;
accept_dist = (m_iMarkerHeight + 1) >> 1;
}
//
// Search through all the points, trying to find the closest
//
int closest = -1;
int closest_dist = 1024;
for (int index = 0; index < m_iColorPoints; index ++) {
int delta = abs (m_ColorPoints[index].StartPos - position);
if (delta < closest_dist) {
closest_dist = delta;
closest = index;
}
}
//
// Did we find a marker at this point?
//
if (closest_dist < accept_dist) {
marker_index = closest;
}
// Return the index of the marker at the specified point (-1 if not found).
return marker_index;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnLButtonDown
//
void
ColorBarClass::OnLButtonDown
(
UINT nFlags,
CPoint point
)
{
//
// Ensure we have the focus
//
if (::GetFocus () != m_hWnd) {
::SetFocus (m_hWnd);
}
LONG style = ::GetWindowLong (m_hWnd, GWL_STYLE);
if (style & CBRS_SHOW_FRAMES) {
//
// Find the key frame the user clicked on
//
int marker_clicked = Marker_From_Point (point);
if (marker_clicked != -1) {
// Did the user select a new key?
if (m_iCurrentKey != marker_clicked) {
m_iCurrentKey = marker_clicked;
// Repaint the window
Repaint ();
}
// Should we prepare to move this marker?
if (m_ColorPoints[m_iCurrentKey].flags & POINT_CAN_MOVE) {
m_bMoving = true;
m_bMoved = false;
::SetCapture (m_hWnd);
}
} else {
//
// Insert a new point at this location if the user has the Ctrl key down
//
if (::GetAsyncKeyState (VK_CONTROL) < 0) {
Insert_Point (point);
Send_Notification (CBRN_INSERTED_POINT, m_iCurrentKey);
}
m_bMoving = false;
m_bMoved = false;
::ReleaseCapture ();
}
} else if (style & CBRS_HAS_SEL) {
Move_Selection (point);
// CRect rect;
//Get_Selection_Rectangle (rect);
//if (rect.PtInRect (point)) {
m_bMoving = true;
m_bMoved = false;
::SetCapture (m_hWnd);
//}
}
CWnd::OnLButtonDown (nFlags, point);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnLButtonUp
//
void
ColorBarClass::OnLButtonUp
(
UINT nFlags,
CPoint point
)
{
if (m_bMoving) {
::ReleaseCapture ();
m_bMoving = false;
//
// Let the parent know one of the points was dragged
//
if (m_bMoved) {
Send_Notification (CBRN_MOVED_POINT, m_iCurrentKey);
}
}
CWnd::OnLButtonUp (nFlags, point);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnMouseMove
//
void
ColorBarClass::OnMouseMove
(
UINT nFlags,
CPoint point
)
{
if (m_bMoving) {
LONG style = ::GetWindowLong (m_hWnd, GWL_STYLE);
if (style & CBRS_SHOW_FRAMES) {
float min_percent = 0;
float max_percent = 1.0F;
//
// Determine the range this marker can move
//
if (m_iCurrentKey > 0) {
min_percent = m_ColorPoints[m_iCurrentKey - 1].PosPercent + 0.01F;
}
if (m_iCurrentKey < (m_iColorPoints - 1)) {
max_percent = m_ColorPoints[m_iCurrentKey + 1].PosPercent - 0.01F;
}
//
// Determine where the marker should be
//
float new_percent = 0;
LONG style = ::GetWindowLong (m_hWnd, GWL_STYLE);
if (style & CBRS_HORZ) {
new_percent = ((float)(point.x - m_ColorArea.left)) / ((float)m_ColorArea.Width ());
} else {
new_percent = ((float)(point.y - m_ColorArea.top)) / ((float)m_ColorArea.Height ());
}
//
// Ensure the marker is in bounds
//
new_percent = max (min_percent, new_percent);
new_percent = min (max_percent, new_percent);
//
// Move the marker
//
m_ColorPoints[m_iCurrentKey].PosPercent = new_percent;
Update_Point_Info ();
//
// Repaint the screen
//
HDC hwnd_dc = ::GetDC (m_hWnd);
Paint_Screen (hwnd_dc);
::ReleaseDC (m_hWnd, hwnd_dc);
//
// Notify the parent window that the user dragged
// one of the keyframes
//
Send_Notification (CBRN_MOVING_POINT, m_iCurrentKey);
m_bMoved = true;
} else if (style & CBRS_HAS_SEL) {
Move_Selection (point);
}
}
CWnd::OnMouseMove (nFlags, point);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Send_Notification
//
LRESULT
ColorBarClass::Send_Notification (int code, int key)
{
//
// Fill in the nofitication structure
//
LONG id = ::GetWindowLong (m_hWnd, GWL_ID);
CBR_NMHDR notify_hdr = { 0 };
notify_hdr.hdr.hwndFrom = m_hWnd;
notify_hdr.hdr.idFrom = id;
notify_hdr.hdr.code = code;
notify_hdr.key_index = key;
notify_hdr.red = m_ColorPoints[key].StartRed;
notify_hdr.green = m_ColorPoints[key].StartGreen;
notify_hdr.blue = m_ColorPoints[key].StartBlue;
notify_hdr.position = m_MinPos + (m_ColorPoints[key].PosPercent * (m_MaxPos - m_MinPos));
//
// Send the notification to the parent window
//
return ::SendMessage (::GetParent (m_hWnd), WM_NOTIFY, id, (LPARAM)¬ify_hdr);
}
/////////////////////////////////////////////////////////////////////////////
//
// OnKillFocus
//
void
ColorBarClass::OnKillFocus (CWnd *pNewWnd)
{
// Force a repaint
Repaint ();
CWnd::OnKillFocus (pNewWnd);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnSetFocus
//
void
ColorBarClass::OnSetFocus (CWnd *pOldWnd)
{
// Force a repaint
Repaint ();
CWnd::OnSetFocus(pOldWnd);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnKeyDown
//
void
ColorBarClass::OnKeyDown
(
UINT nChar,
UINT nRepCnt,
UINT nFlags
)
{
if ((nChar == VK_DELETE) && (::GetFocus () == m_hWnd)) {
//
// Notify the parent window that we are deleting a key
// and ask them if its OK to contiue
//
if (Send_Notification (CBRN_DEL_POINT, m_iCurrentKey) != STOP_EVENT) {
// Go ahead and delete the point
Delete_Point (m_iCurrentKey);
Send_Notification (CBRN_DELETED_POINT, m_iCurrentKey);
}
}/* else if (::GetFocus () == m_hWnd) {
if (nChar == VK_RIGHT) &&
}*/
CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnLButtonDblClk
//
void
ColorBarClass::OnLButtonDblClk
(
UINT nFlags,
CPoint point
)
{
int marker_clicked = Marker_From_Point (point);
if (marker_clicked != -1) {
//
// Notify the parent window that the user double-clicked
// one of the keyframes
//
Send_Notification (CBRN_DBLCLK_POINT, marker_clicked);
}
CWnd::OnLButtonDblClk(nFlags, point);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Get_Selection_Rectangle
//
void
ColorBarClass::Get_Selection_Rectangle (CRect &rect)
{
float pos_percent = ((float)(m_SelectionPos - m_MinPos)) / ((float)(m_MaxPos - m_MinPos));
rect = m_ColorArea;
//
// Determine the bounding rectangle for the selection
//
LONG style = ::GetWindowLong (m_hWnd, GWL_STYLE);
if (style & CBRS_HORZ) {
rect.left = (m_ColorArea.left + int(m_ColorArea.Width () * pos_percent)) - 3;
rect.right = rect.left + 6;
if (style & CBRS_FRAME_MASK) {
rect.top --;
rect.bottom ++;
}
} else {
rect.top = (m_ColorArea.top + int(m_ColorArea.Height () * pos_percent)) - 3;
rect.bottom = rect.top + 6;
if (style & CBRS_FRAME_MASK) {
rect.left --;
rect.right ++;
}
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Set_Selection_Pos
//
void
ColorBarClass::Set_Selection_Pos (float pos)
{
// Ensure the new position is in bounds
pos = max (pos, m_MinPos);
pos = min (pos, m_MaxPos);
// Move the selection
Move_Selection (pos, false);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Move_Selection
//
void
ColorBarClass::Move_Selection (CPoint point, bool send_notify)
{
//
// Determine the selection's new position
//
float percent = 0;
LONG style = ::GetWindowLong (m_hWnd, GWL_STYLE);
if (style & CBRS_HORZ) {
percent = (((float)(point.x - m_ColorArea.left)) / ((float)m_ColorArea.Width ()));
} else {
percent = (((float)(point.y - m_ColorArea.top)) / ((float)m_ColorArea.Height ()));
}
float new_pos = m_MinPos + (percent * (m_MaxPos - m_MinPos));
new_pos = max (new_pos, m_MinPos);
new_pos = min (new_pos, m_MaxPos);
// Do the actual move
Move_Selection (new_pos, send_notify);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Move_Selection
//
void
ColorBarClass::Move_Selection (float new_pos, bool send_notify)
{
if (new_pos != m_SelectionPos) {
m_SelectionPos = new_pos;
//
// Notify the parent window that the user changed the selection
//
if (send_notify) {
LONG id = ::GetWindowLong (m_hWnd, GWL_ID);
CBR_NMHDR notify_hdr = { 0 };
notify_hdr.hdr.hwndFrom = m_hWnd;
notify_hdr.hdr.idFrom = id;
notify_hdr.hdr.code = CBRN_SEL_CHANGED;
notify_hdr.position = m_SelectionPos;
// Determine the color are this position
Get_Color (m_SelectionPos,
¬ify_hdr.red,
¬ify_hdr.green,
¬ify_hdr.blue);
//
// Send the notification to the parent
//
::SendMessage (::GetParent (m_hWnd),
WM_NOTIFY,
id,
(LPARAM)¬ify_hdr);
}
// Repaint the color bar with the new selection rectangle
Paint_DIB ();
//
// Repaint the screen
//
HDC hwnd_dc = ::GetDC (m_hWnd);
Paint_Screen (hwnd_dc);
::ReleaseDC (m_hWnd, hwnd_dc);
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Get_Color
//
void
ColorBarClass::Get_Color
(
float position,
float *red,
float *green,
float *blue
)
{
//
// Index into the color bitmap at the correct location...
//
LONG style = ::GetWindowLong (m_hWnd, GWL_STYLE);
int pixel_pos = 0;
if (style & CBRS_HORZ) {
float percent = m_MinPos + (position - m_MinPos) / (m_MaxPos - m_MinPos);
pixel_pos = int(m_ColorArea.left + (percent * (float)m_ColorArea.Width ()));
/*int bmp_index = ((m_ColorArea.top + 1) * m_iScanlineSize) + (x * 3);
(*blue) = m_pBits[bmp_index];
(*green) = m_pBits[bmp_index+1];
(*red) = m_pBits[bmp_index+2];*/
} else {
float percent = m_MinPos + (position - m_MinPos) / (m_MaxPos - m_MinPos);
pixel_pos = int(m_ColorArea.top + (percent * (float)m_ColorArea.Height ()));
/*int bmp_index = (y * m_iScanlineSize) + (m_ColorArea.left * 3);
(*blue) = m_pBits[bmp_index];
(*green) = m_pBits[bmp_index+1];
(*red) = m_pBits[bmp_index+2];*/
}
//
// Find the index where this point should be inserted
//
bool found = false;
int key_index = 0;
for (int index = 0; (index < m_iColorPoints) && !found; index ++) {
if ((pixel_pos >= m_ColorPoints[index].StartPos) &&
(pixel_pos <= m_ColorPoints[index].EndPos)) {
key_index = index;
found = true;
}
}
if (found) {
int start_pos = m_ColorPoints[key_index].StartPos;
int end_pos = m_ColorPoints[key_index].EndPos;
//float ticks = pixel_pos - start_pos) / float(end_pos - start_pos);
float ticks = float(pixel_pos) - float(m_ColorPoints[key_index].StartPos);
(*red) = m_ColorPoints[key_index].StartRed;
(*green) = m_ColorPoints[key_index].StartGreen;
(*blue) = m_ColorPoints[key_index].StartBlue;
(*red) += ticks * m_ColorPoints[key_index].RedInc;
(*green) += ticks * m_ColorPoints[key_index].GreenInc;
(*blue) += ticks * m_ColorPoints[key_index].BlueInc;
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Clear_Points
//
void
ColorBarClass::Clear_Points (void)
{
// Reset the point count
m_iColorPoints = 1;
// Rebuild the color information
Update_Point_Info ();
// Force the window to be repainted
Repaint ();
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Set_User_Data
//
bool
ColorBarClass::Set_User_Data (int index, DWORD data)
{
bool retval = false;
if ((index >= 0) && (index < m_iColorPoints)) {
m_ColorPoints[index].user_data = data;
retval = true;
}
return retval;
}
/////////////////////////////////////////////////////////////////////////////
//
// Get_User_Data
//
DWORD
ColorBarClass::Get_User_Data (int index)
{
DWORD data = 0;
if ((index >= 0) && (index < m_iColorPoints)) {
data = m_ColorPoints[index].user_data;
}
return data;
}
/////////////////////////////////////////////////////////////////////////////
//
// Set_Graph_Percent
//
bool
ColorBarClass::Set_Graph_Percent (int index, float percent)
{
bool retval = false;
if ((index >= 0) && (index < m_iColorPoints)) {
m_ColorPoints[index].StartGraphPercent = percent;
// Rebuild the color information
Update_Point_Info ();
// Force the window to be repainted
Repaint ();
retval = true;
}
return retval;
}
/////////////////////////////////////////////////////////////////////////////
//
// Get_Graph_Percent
//
float
ColorBarClass::Get_Graph_Percent (int index)
{
float percent = 0;
if ((index >= 0) && (index < m_iColorPoints)) {
percent = m_ColorPoints[index].StartGraphPercent;
}
return percent;
}
/////////////////////////////////////////////////////////////////////////////
//
// Set_Redraw
//
void
ColorBarClass::Set_Redraw (bool redraw)
{
m_bRedraw = redraw;
if (m_bRedraw) {
UpdateWindow ();
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Repaint
//
void
ColorBarClass::Repaint (void)
{
InvalidateRect (NULL, FALSE);
if (m_bRedraw) {
UpdateWindow ();
}
return ;
}