ColorBar.cpp 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /////////////////////////////////////////////////////////////////////////////////
  19. //
  20. // ColorBar.cpp : implementation file
  21. //
  22. //
  23. #include "stdafx.h"
  24. #include "colorbar.h"
  25. #include "colorutils.h"
  26. #include "resource.h"
  27. #include <math.h>
  28. #ifdef _DEBUG
  29. #define new DEBUG_NEW
  30. #undef THIS_FILE
  31. static char THIS_FILE[] = __FILE__;
  32. #endif
  33. //extern HINSTANCE _hinstance;
  34. /////////////////////////////////////////////////////////////////////////////
  35. //
  36. // ColorBarClass
  37. //
  38. ColorBarClass::ColorBarClass (void)
  39. : m_hBitmap (NULL),
  40. m_iBMPWidth (0),
  41. m_iBMPHeight (0),
  42. m_pBits (NULL),
  43. m_hMemDC (NULL),
  44. m_iColorPoints (0),
  45. m_iMarkerWidth (0),
  46. m_iMarkerHeight (0),
  47. m_KeyFrameDIB (NULL),
  48. m_pKeyFrameBits (NULL),
  49. m_iCurrentKey (0),
  50. m_MinPos (0),
  51. m_MaxPos (1),
  52. m_iScanlineSize (0),
  53. m_bMoving (false),
  54. m_bMoved (false),
  55. m_SelectionPos (0),
  56. m_bRedraw (true),
  57. CWnd ()
  58. {
  59. ::memset (m_ColorPoints, 0, sizeof (m_ColorPoints));
  60. m_iColorPoints = 1;
  61. m_ColorPoints[0].PosPercent = 0;
  62. m_ColorPoints[0].StartRed = 0;
  63. m_ColorPoints[0].StartGreen = 0;
  64. m_ColorPoints[0].StartBlue = 0;
  65. m_ColorPoints[0].flags = POINT_VISIBLE;
  66. /*m_iColorPoints = 7;
  67. m_ColorPoints[0].PosPercent = 0;
  68. m_ColorPoints[0].StartRed = 255;
  69. m_ColorPoints[0].StartGreen = 0;
  70. m_ColorPoints[0].StartBlue = 0;
  71. m_ColorPoints[0].flags = POINT_VISIBLE;
  72. m_ColorPoints[1].PosPercent = (1.0F / 6.0F);
  73. m_ColorPoints[1].StartRed = 255;
  74. m_ColorPoints[1].StartGreen = 255;
  75. m_ColorPoints[1].StartBlue = 0;
  76. m_ColorPoints[1].flags = POINT_VISIBLE | POINT_CAN_MOVE;
  77. m_ColorPoints[2].PosPercent = (2.0F / 6.0F);
  78. m_ColorPoints[2].StartRed = 0;
  79. m_ColorPoints[2].StartGreen = 255;
  80. m_ColorPoints[2].StartBlue = 0;
  81. m_ColorPoints[2].flags = POINT_VISIBLE | POINT_CAN_MOVE;
  82. m_ColorPoints[3].PosPercent = (3.0F / 6.0F);
  83. m_ColorPoints[3].StartRed = 0;
  84. m_ColorPoints[3].StartGreen = 255;
  85. m_ColorPoints[3].StartBlue = 255;
  86. m_ColorPoints[3].flags = POINT_VISIBLE | POINT_CAN_MOVE;
  87. m_ColorPoints[4].PosPercent = (4.0F / 6.0F);
  88. m_ColorPoints[4].StartRed = 0;
  89. m_ColorPoints[4].StartGreen = 0;
  90. m_ColorPoints[4].StartBlue = 255;
  91. m_ColorPoints[4].flags = POINT_VISIBLE | POINT_CAN_MOVE;
  92. m_ColorPoints[5].PosPercent = (5.0F / 6.0F);
  93. m_ColorPoints[5].StartRed = 255;
  94. m_ColorPoints[5].StartGreen = 0;
  95. m_ColorPoints[5].StartBlue = 255;
  96. m_ColorPoints[5].flags = POINT_VISIBLE | POINT_CAN_MOVE;
  97. m_ColorPoints[6].PosPercent = 1;
  98. m_ColorPoints[6].StartRed = 255;
  99. m_ColorPoints[6].StartGreen = 0;
  100. m_ColorPoints[6].StartBlue = 0;
  101. m_ColorPoints[6].flags = POINT_VISIBLE | POINT_CAN_MOVE;*/
  102. return ;
  103. }
  104. /////////////////////////////////////////////////////////////////////////////
  105. //
  106. // ~ColorBarClass
  107. //
  108. ColorBarClass::~ColorBarClass (void)
  109. {
  110. if (m_hMemDC != NULL) {
  111. ::DeleteObject (m_hMemDC);
  112. m_hMemDC = NULL;
  113. }
  114. Free_Marker_Bitmap ();
  115. Free_Bitmap ();
  116. return ;
  117. }
  118. BEGIN_MESSAGE_MAP(ColorBarClass, CWnd)
  119. //{{AFX_MSG_MAP(ColorBarClass)
  120. ON_WM_CREATE()
  121. ON_WM_SIZE()
  122. ON_WM_PAINT()
  123. ON_WM_LBUTTONDOWN()
  124. ON_WM_LBUTTONUP()
  125. ON_WM_MOUSEMOVE()
  126. ON_WM_KILLFOCUS()
  127. ON_WM_SETFOCUS()
  128. ON_WM_KEYDOWN()
  129. ON_WM_LBUTTONDBLCLK()
  130. //}}AFX_MSG_MAP
  131. END_MESSAGE_MAP()
  132. /////////////////////////////////////////////////////////////////////////////
  133. //
  134. // RegisterColorBar
  135. //
  136. void
  137. RegisterColorBar (HINSTANCE hinst)
  138. {
  139. // Has the class already been registered?
  140. WNDCLASS wndclass = { 0 };
  141. if (::GetClassInfo (hinst, "WWCOLORBAR", &wndclass) == FALSE) {
  142. wndclass.style = CS_GLOBALCLASS | CS_OWNDC | CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
  143. wndclass.lpfnWndProc = fnColorBarProc;
  144. wndclass.hInstance = hinst;
  145. wndclass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
  146. wndclass.hCursor = ::LoadCursor (NULL, IDC_ARROW);
  147. wndclass.lpszClassName = "WWCOLORBAR";
  148. // Let the windows manager know about this global class
  149. ::RegisterClass (&wndclass);
  150. }
  151. return ;
  152. }
  153. /////////////////////////////////////////////////////////////////////////////
  154. //
  155. // fnColorBarProc
  156. //
  157. LRESULT WINAPI
  158. fnColorBarProc
  159. (
  160. HWND hwnd,
  161. UINT message,
  162. WPARAM wparam,
  163. LPARAM lparam
  164. )
  165. {
  166. switch (message)
  167. {
  168. case WM_CREATE:
  169. {
  170. LPCREATESTRUCT pcreate_info = (LPCREATESTRUCT)lparam;
  171. if (pcreate_info != NULL) {
  172. // Should we create a new class manager for this window?
  173. ColorBarClass *pwnd = (ColorBarClass *)pcreate_info->lpCreateParams;
  174. BOOL created = FALSE;
  175. if (pwnd == NULL) {
  176. pwnd = new ColorBarClass;
  177. created = TRUE;
  178. }
  179. // Pull some hacks to get MFC to use the message map
  180. pwnd->Attach (hwnd);
  181. // Let the window know its being created
  182. pwnd->OnCreate (pcreate_info);
  183. WNDPROC *pOldWndProc = pwnd->GetSuperWndProcAddr ();
  184. if (pOldWndProc) {
  185. WNDPROC pold_proc = (WNDPROC)::SetWindowLong (hwnd, GWL_WNDPROC, (DWORD)::AfxGetAfxWndProc ());
  186. ASSERT (pold_proc != NULL);
  187. (*pOldWndProc) = pold_proc;
  188. }
  189. // Store some information in the window handle
  190. ::SetProp (hwnd, "CLASSPOINTER", (HANDLE)pwnd);
  191. ::SetProp (hwnd, "CREATED", (HANDLE)created);
  192. }
  193. }
  194. break;
  195. case WM_DESTROY:
  196. {
  197. // Get the creation information from the window handle
  198. ColorBarClass *pwnd = (ColorBarClass *)::GetProp (hwnd, "CLASSPOINTER");
  199. BOOL created = (BOOL)::GetProp (hwnd, "CREATED");
  200. if (pwnd != NULL) {
  201. pwnd->Detach ();
  202. WNDPROC *pOldWndProc = pwnd->GetSuperWndProcAddr ();
  203. if (pOldWndProc) {
  204. ::SetWindowLong (hwnd, GWL_WNDPROC, (DWORD)(*pOldWndProc));
  205. (*pOldWndProc) = NULL;
  206. }
  207. if (created) {
  208. delete pwnd;
  209. pwnd = NULL;
  210. }
  211. }
  212. }
  213. break;
  214. }
  215. // Allow default processing to occur
  216. return ::DefWindowProc (hwnd, message, wparam, lparam);
  217. }
  218. /////////////////////////////////////////////////////////////////////////////
  219. //
  220. // OnCreate
  221. //
  222. int
  223. ColorBarClass::OnCreate (LPCREATESTRUCT lpCreateStruct)
  224. {
  225. if (CWnd::OnCreate (lpCreateStruct) == -1)
  226. return -1;
  227. m_hMemDC = ::CreateCompatibleDC (NULL);
  228. Create_Bitmap ();
  229. return 0;
  230. }
  231. /////////////////////////////////////////////////////////////////////////////
  232. //
  233. // Create
  234. //
  235. BOOL
  236. ColorBarClass::Create
  237. (
  238. LPCTSTR /*lpszClassName*/,
  239. LPCTSTR lpszWindowName,
  240. DWORD dwStyle,
  241. const RECT &rect,
  242. CWnd *pparent_wnd,
  243. UINT nID,
  244. CCreateContext * /*pContext*/
  245. )
  246. {
  247. // Create the window (it will force the message map and everthing)
  248. HWND hparent_wnd = (pparent_wnd != NULL) ? pparent_wnd->m_hWnd : NULL;
  249. HWND hwnd = ::CreateWindow ("WWCOLORBAR",
  250. lpszWindowName,
  251. dwStyle,
  252. rect.left,
  253. rect.top,
  254. rect.right - rect.left,
  255. rect.bottom - rect.top,
  256. hparent_wnd,
  257. (HMENU)nID,
  258. ::AfxGetInstanceHandle (),
  259. this);
  260. // Return the true/false result code
  261. return (hwnd != NULL);
  262. }
  263. /////////////////////////////////////////////////////////////////////////////
  264. //
  265. // Create_Bitmap
  266. //
  267. void
  268. ColorBarClass::Create_Bitmap (void)
  269. {
  270. // Start fresh
  271. Free_Bitmap ();
  272. CRect rect;
  273. GetClientRect (&rect);
  274. m_iBMPWidth = rect.Width ();
  275. m_iBMPHeight = rect.Height ();
  276. // Assume the color portion of the control takes the whole client aread
  277. m_ColorArea.left = 0;
  278. m_ColorArea.top = 0;
  279. m_ColorArea.right = m_iBMPWidth;
  280. m_ColorArea.bottom = m_iBMPHeight;
  281. //
  282. // Deflate the rect to make room for any frame
  283. //
  284. LONG style = ::GetWindowLong (m_hWnd, GWL_STYLE);
  285. if (style & CBRS_FRAME_MASK) {
  286. m_ColorArea.InflateRect (-1, -1);
  287. }
  288. //
  289. // Decrease the width or height if frame markers are shown
  290. //
  291. if (style & CBRS_SHOW_FRAMES) {
  292. Load_Key_Frame_BMP ();
  293. if (style & CBRS_HORZ) {
  294. m_ColorArea.left += (m_iMarkerWidth >> 1);
  295. m_ColorArea.right -= (m_iMarkerWidth >> 1);
  296. m_ColorArea.bottom -= (m_iMarkerHeight >> 1);
  297. } else {
  298. m_ColorArea.top += (m_iMarkerHeight >> 1);
  299. m_ColorArea.bottom -= (m_iMarkerHeight >> 1);
  300. m_ColorArea.right -= (m_iMarkerWidth >> 1);
  301. }
  302. } else if (style & CBRS_HAS_SEL) {
  303. if (style & CBRS_HORZ) {
  304. m_ColorArea.left += 2;
  305. m_ColorArea.right -= 2;
  306. } else {
  307. m_ColorArea.top += 2;
  308. m_ColorArea.bottom -= 2;
  309. }
  310. }
  311. // Set-up the fields of the BITMAPINFOHEADER
  312. BITMAPINFOHEADER bitmap_info;
  313. bitmap_info.biSize = sizeof (BITMAPINFOHEADER);
  314. bitmap_info.biWidth = m_iBMPWidth;
  315. bitmap_info.biHeight = -m_iBMPHeight; // Top-down DIB uses negative height
  316. bitmap_info.biPlanes = 1;
  317. bitmap_info.biBitCount = 24;
  318. bitmap_info.biCompression = BI_RGB;
  319. bitmap_info.biSizeImage = ((m_iBMPWidth * m_iBMPHeight) * 3);
  320. bitmap_info.biXPelsPerMeter = 0;
  321. bitmap_info.biYPelsPerMeter = 0;
  322. bitmap_info.biClrUsed = 0;
  323. bitmap_info.biClrImportant = 0;
  324. // Get a temporary screen DC
  325. HDC hscreen_dc = ::GetDC (NULL);
  326. // Create a bitmap that we can access the bits directly of
  327. m_hBitmap = ::CreateDIBSection (hscreen_dc,
  328. (const BITMAPINFO *)&bitmap_info,
  329. DIB_RGB_COLORS,
  330. (void **)&m_pBits,
  331. NULL,
  332. 0L);
  333. // Release our temporary screen DC
  334. ::ReleaseDC (NULL, hscreen_dc);
  335. // Window's bitmaps are DWORD aligned, so make sure
  336. // we take that into account.
  337. int alignment_offset = (m_iBMPWidth * 3) % 4;
  338. alignment_offset = (alignment_offset != 0) ? (4 - alignment_offset) : 0;
  339. m_iScanlineSize = (m_iBMPWidth * 3) + alignment_offset;
  340. Update_Point_Info ();
  341. return ;
  342. }
  343. /////////////////////////////////////////////////////////////////////////////
  344. //
  345. // Free_Bitmap
  346. //
  347. void
  348. ColorBarClass::Free_Bitmap (void)
  349. {
  350. if (m_hBitmap != NULL) {
  351. ::DeleteObject (m_hBitmap);
  352. m_hBitmap = NULL;
  353. m_pBits = NULL;
  354. }
  355. m_iBMPWidth = 0;
  356. m_iBMPHeight = 0;
  357. return ;
  358. }
  359. /////////////////////////////////////////////////////////////////////////////
  360. //
  361. // OnSize
  362. //
  363. void
  364. ColorBarClass::OnSize
  365. (
  366. UINT nType,
  367. int cx,
  368. int cy
  369. )
  370. {
  371. // Allow the base class to process this message
  372. CWnd::OnSize (nType, cx, cy);
  373. // Recreate the BMP to reflect the new window size
  374. Create_Bitmap ();
  375. return ;
  376. }
  377. /////////////////////////////////////////////////////////////////////////////
  378. //
  379. // Paint_Bar_Vert
  380. //
  381. void
  382. ColorBarClass::Paint_Bar_Vert
  383. (
  384. int x_pos,
  385. int y_pos,
  386. int width,
  387. int height,
  388. UCHAR *pbits
  389. )
  390. {
  391. // Loop through all the color switches
  392. int row = y_pos;
  393. for (int color_point = 0; color_point < m_iColorPoints; color_point ++) {
  394. // Get the starting red, green, and blue values for this color lerp
  395. float red = m_ColorPoints[color_point].StartRed;
  396. float green = m_ColorPoints[color_point].StartGreen;
  397. float blue = m_ColorPoints[color_point].StartBlue;
  398. // Index into the bitmap's bits
  399. int bitmap_index = (row * m_iScanlineSize) + (x_pos * 3);
  400. // Loop through all rows of color in this 'switch'
  401. int end_pos = m_ColorPoints[color_point].EndPos;
  402. end_pos = (end_pos > (y_pos + height)) ? (y_pos + height) : end_pos;
  403. for (; row < m_ColorPoints[color_point].EndPos; row ++) {
  404. // Paint a complete row of color data
  405. int bitmap_offset = 0;
  406. for (int col = x_pos; col < (x_pos + width); col ++) {
  407. // Paint the pixel
  408. pbits[bitmap_index + bitmap_offset] = UCHAR(((int)blue) & 0xFF);
  409. pbits[bitmap_index + bitmap_offset+1] = UCHAR(((int)green) & 0xFF);
  410. pbits[bitmap_index + bitmap_offset+2] = UCHAR(((int)red) & 0xFF);
  411. // Move to the next col
  412. bitmap_offset += 3;
  413. }
  414. // Advance to the next row
  415. bitmap_index += m_iScanlineSize;
  416. // Increment the row's color
  417. red += m_ColorPoints[color_point].RedInc;
  418. green += m_ColorPoints[color_point].GreenInc;
  419. blue += m_ColorPoints[color_point].BlueInc;
  420. }
  421. }
  422. return ;
  423. }
  424. /////////////////////////////////////////////////////////////////////////////
  425. //
  426. // Paint_Bar_Horz
  427. //
  428. void
  429. ColorBarClass::Paint_Bar_Horz
  430. (
  431. int x_pos,
  432. int y_pos,
  433. int width,
  434. int height,
  435. UCHAR *pbits
  436. )
  437. {
  438. LONG style = ::GetWindowLong (m_hWnd, GWL_STYLE);
  439. if (style & CBRS_PAINT_GRAPH) {
  440. // Loop through all the color switches
  441. int col = x_pos;
  442. for (int color_point = 0; color_point < m_iColorPoints; color_point ++) {
  443. float graph_percent = m_ColorPoints[color_point].StartGraphPercent;
  444. // Index into the bitmap's bits
  445. int bitmap_index = (y_pos * m_iScanlineSize) + (col * 3);
  446. // Loop through all columns of color in this 'switch'
  447. int end_pos = m_ColorPoints[color_point].EndPos;
  448. end_pos = (end_pos > (x_pos + width)) ? (x_pos + width) : end_pos;
  449. for (; col < m_ColorPoints[color_point].EndPos; col ++) {
  450. // Paint a complete column of color data
  451. int bitmap_offset = 0;
  452. bool prev_was = true;
  453. for (int row = y_pos; row < (y_pos + height); row ++) {
  454. float percent = 1 - graph_percent;
  455. float height_percent = (((float)row) / ((float)height));
  456. if (percent < height_percent) {
  457. // Paint the pixel
  458. if (prev_was == false) {
  459. pbits[bitmap_index + bitmap_offset] = 0;
  460. pbits[bitmap_index + bitmap_offset+1] = 0;
  461. pbits[bitmap_index + bitmap_offset+2] = 0;
  462. } else {
  463. pbits[bitmap_index + bitmap_offset] = 255;
  464. pbits[bitmap_index + bitmap_offset+1] = 128 + UCHAR(((int)((1-height_percent) * 128)) & 0xFF);
  465. pbits[bitmap_index + bitmap_offset+2] = UCHAR(((int)((1-height_percent) * 255)) & 0xFF);
  466. }
  467. prev_was = true;
  468. } else {
  469. // Paint the pixel
  470. pbits[bitmap_index + bitmap_offset] = 128;
  471. pbits[bitmap_index + bitmap_offset+1] = 128;
  472. pbits[bitmap_index + bitmap_offset+2] = 128;
  473. prev_was = false;
  474. }
  475. // Move down to the next row
  476. bitmap_offset += m_iScanlineSize;
  477. }
  478. // Advance to the next column
  479. bitmap_index += 3;
  480. graph_percent += m_ColorPoints[color_point].GraphPercentInc;
  481. }
  482. }
  483. } else {
  484. // Loop through all the color switches
  485. int col = x_pos;
  486. for (int color_point = 0; color_point < m_iColorPoints; color_point ++) {
  487. // Get the starting red, green, and blue values for this color lerp
  488. float red = m_ColorPoints[color_point].StartRed;
  489. float green = m_ColorPoints[color_point].StartGreen;
  490. float blue = m_ColorPoints[color_point].StartBlue;
  491. // Index into the bitmap's bits
  492. int bitmap_index = (y_pos * m_iScanlineSize) + (col * 3);
  493. // Loop through all columns of color in this 'switch'
  494. int end_pos = m_ColorPoints[color_point].EndPos;
  495. end_pos = (end_pos > (x_pos + width)) ? (x_pos + width) : end_pos;
  496. for (; col < m_ColorPoints[color_point].EndPos; col ++) {
  497. // Paint a complete column of color data
  498. int bitmap_offset = 0;
  499. for (int row = y_pos; row < (y_pos + height); row ++) {
  500. // Paint the pixel
  501. pbits[bitmap_index + bitmap_offset] = UCHAR(((int)blue) & 0xFF);
  502. pbits[bitmap_index + bitmap_offset+1] = UCHAR(((int)green) & 0xFF);
  503. pbits[bitmap_index + bitmap_offset+2] = UCHAR(((int)red) & 0xFF);
  504. // Move down to the next row
  505. bitmap_offset += m_iScanlineSize;
  506. }
  507. // Advance to the next column
  508. bitmap_index += 3;
  509. // Increment the column's color
  510. red += m_ColorPoints[color_point].RedInc;
  511. green += m_ColorPoints[color_point].GreenInc;
  512. blue += m_ColorPoints[color_point].BlueInc;
  513. }
  514. }
  515. }
  516. return ;
  517. }
  518. /////////////////////////////////////////////////////////////////////////////
  519. //
  520. // Paint_DIB
  521. //
  522. void
  523. ColorBarClass::Paint_DIB (void)
  524. {
  525. CRect frame_rect = m_ColorArea;
  526. frame_rect.InflateRect (1, 1);
  527. //
  528. // Erase the background to start...
  529. //
  530. CRect fill_rect (0, 0, m_iBMPWidth, m_iBMPHeight);
  531. HBITMAP hold_bmp = (HBITMAP)::SelectObject (m_hMemDC, m_hBitmap);
  532. ::FillRect (m_hMemDC, &fill_rect, (HBRUSH)(COLOR_3DFACE + 1));
  533. ::SelectObject (m_hMemDC, hold_bmp);
  534. //
  535. // Paint the border (if any)
  536. //
  537. LONG style = ::GetWindowLong (m_hWnd, GWL_STYLE);
  538. if (style & CBRS_SUNKEN) {
  539. ::Draw_Sunken_Rect (m_pBits, frame_rect, m_iScanlineSize);
  540. } else if (style & CBRS_RAISED) {
  541. ::Draw_Raised_Rect (m_pBits, frame_rect, m_iScanlineSize);
  542. } else if (style & CBRS_FRAME) {
  543. ::Frame_Rect (m_pBits, frame_rect, RGB (0, 0, 0), m_iScanlineSize);
  544. }
  545. //
  546. // Now draw the color areas
  547. //
  548. if (style & CBRS_HORZ) {
  549. Paint_Bar_Horz (m_ColorArea.left,
  550. m_ColorArea.top,
  551. m_ColorArea.Width (),
  552. m_ColorArea.Height (),
  553. m_pBits);
  554. } else {
  555. Paint_Bar_Vert (m_ColorArea.left,
  556. m_ColorArea.top,
  557. m_ColorArea.Width (),
  558. m_ColorArea.Height (),
  559. m_pBits);
  560. }
  561. //
  562. // Do we need to paint the keyframe markers?
  563. //
  564. if (style & CBRS_SHOW_FRAMES) {
  565. //
  566. // Setup the marker positions
  567. //
  568. int x_pos = 0;
  569. int y_pos = 0;
  570. int *position = NULL;
  571. int offset = 0;
  572. if (style & CBRS_HORZ) {
  573. position = &x_pos;
  574. x_pos = m_ColorArea.left;
  575. y_pos = m_ColorArea.Height () - (m_iMarkerHeight >> 1);
  576. offset = -(m_iMarkerWidth >> 1);
  577. } else {
  578. position = &y_pos;
  579. x_pos = m_ColorArea.Width () - (m_iMarkerWidth >> 1);
  580. y_pos = m_ColorArea.top;
  581. offset = -(m_iMarkerHeight >> 1);
  582. }
  583. //
  584. // Paint all the keyframe markers
  585. //
  586. for (int color_point = 0; color_point < m_iColorPoints; color_point ++) {
  587. (*position) = m_ColorPoints[color_point].StartPos;
  588. (*position) += offset;
  589. Paint_Key_Frame (x_pos, y_pos);
  590. }
  591. } else if (style & CBRS_HAS_SEL) {
  592. CRect frame;
  593. Get_Selection_Rectangle (frame);
  594. //
  595. // Paint the selection rectangles
  596. //
  597. ::Frame_Rect (m_pBits, frame, RGB (0, 0, 0), m_iScanlineSize);
  598. frame.InflateRect (-1, -1);
  599. ::Frame_Rect (m_pBits, frame, RGB (255, 255, 255), m_iScanlineSize);
  600. }
  601. return ;
  602. }
  603. /////////////////////////////////////////////////////////////////////////////
  604. //
  605. // OnPaint
  606. //
  607. void
  608. ColorBarClass::OnPaint (void)
  609. {
  610. CPaintDC dc (this);
  611. Paint_Screen (dc);
  612. return ;
  613. }
  614. /////////////////////////////////////////////////////////////////////////////
  615. //
  616. // Paint_Screen
  617. //
  618. void
  619. ColorBarClass::Paint_Screen (HDC hwnd_dc)
  620. {
  621. if (m_hMemDC != NULL) {
  622. //
  623. // Blit the actual color bar to the screen
  624. //
  625. HBITMAP hold_bmp = (HBITMAP)::SelectObject (m_hMemDC, m_hBitmap);
  626. ::BitBlt (hwnd_dc, 0, 0, m_iBMPWidth, m_iBMPHeight, m_hMemDC, 0, 0, SRCCOPY);
  627. ::SelectObject (m_hMemDC, hold_bmp);
  628. //
  629. // Do we have the focus?
  630. //
  631. if (::GetFocus () == m_hWnd) {
  632. LONG style = ::GetWindowLong (m_hWnd, GWL_STYLE);
  633. if (style & CBRS_SHOW_FRAMES) {
  634. //
  635. // Calculate the current frame marker's current rectangle
  636. //
  637. CRect focus_rect;
  638. LONG style = ::GetWindowLong (m_hWnd, GWL_STYLE);
  639. if (style & CBRS_HORZ) {
  640. focus_rect.left = m_ColorPoints[m_iCurrentKey].StartPos - (m_iMarkerWidth >> 1);
  641. focus_rect.top = m_ColorArea.Height () - (m_iMarkerHeight >> 1);
  642. } else {
  643. focus_rect.left = m_ColorArea.Width () - (m_iMarkerWidth >> 1);
  644. focus_rect.top = m_ColorPoints[m_iCurrentKey].StartPos - (m_iMarkerHeight >> 1);
  645. }
  646. focus_rect.right = focus_rect.left + m_iMarkerWidth;
  647. focus_rect.bottom = focus_rect.top + m_iMarkerHeight;
  648. //
  649. // Paint the focus rectangle
  650. //
  651. ::DrawFocusRect (hwnd_dc, focus_rect);
  652. } else if (style & CBRS_HAS_SEL) {
  653. //
  654. // Paint the focus rectangle
  655. //
  656. CRect focus_rect;
  657. Get_Selection_Rectangle (focus_rect);
  658. ::DrawFocusRect (hwnd_dc, focus_rect);
  659. }
  660. }
  661. }
  662. return ;
  663. }
  664. /////////////////////////////////////////////////////////////////////////////
  665. //
  666. // Get_Point
  667. //
  668. bool
  669. ColorBarClass::Get_Point
  670. (
  671. int index,
  672. float *position,
  673. float *red,
  674. float *green,
  675. float *blue
  676. )
  677. {
  678. // Assume failure
  679. bool retval = false;
  680. if ((index >= 0) && (index < m_iColorPoints)) {
  681. // Return the position to the caller if requested
  682. if (position != NULL) {
  683. (*position) = m_MinPos + (m_ColorPoints[index].PosPercent * (m_MaxPos - m_MinPos));
  684. }
  685. // Return the red value to the caller if requested
  686. if (red != NULL) {
  687. (*red) = m_ColorPoints[index].StartRed;
  688. }
  689. // Return the green value to the caller if requested
  690. if (green != NULL) {
  691. (*green) = m_ColorPoints[index].StartGreen;
  692. }
  693. // Return the blue value to the caller if requested
  694. if (blue != NULL) {
  695. (*blue) = m_ColorPoints[index].StartBlue;
  696. }
  697. }
  698. // Return the true/false result code
  699. return retval;
  700. }
  701. /////////////////////////////////////////////////////////////////////////////
  702. //
  703. // Insert_Point
  704. //
  705. bool
  706. ColorBarClass::Insert_Point (CPoint point, DWORD flags)
  707. {
  708. int new_index = 0;
  709. int position = 0;
  710. float percent = 0;
  711. float red = 0;
  712. float green = 0;
  713. float blue = 0;
  714. //
  715. // Determine what properties the new point should have
  716. //
  717. LONG style = ::GetWindowLong (m_hWnd, GWL_STYLE);
  718. if (style & CBRS_HORZ) {
  719. position = point.x - m_ColorArea.left;
  720. percent = ((float)(point.x - m_ColorArea.left)) / ((float)m_ColorArea.Width ());
  721. int bmp_index = ((m_ColorArea.top + 1) * m_iScanlineSize) + (point.x * 3);
  722. blue = m_pBits[bmp_index];
  723. green = m_pBits[bmp_index+1];
  724. red = m_pBits[bmp_index+2];
  725. } else {
  726. position = point.y - m_ColorArea.top;
  727. percent = ((float)(point.y - m_ColorArea.top)) / ((float)m_ColorArea.Height ());
  728. int bmp_index = (point.y * m_iScanlineSize) + (m_ColorArea.left * 3);
  729. blue = m_pBits[bmp_index];
  730. green = m_pBits[bmp_index+1];
  731. red = m_pBits[bmp_index+2];
  732. }
  733. //
  734. // Find the index where this point should be inserted
  735. //
  736. bool found = false;
  737. float graph_percent = 0;
  738. for (int index = 0; (index < m_iColorPoints) && !found; index ++) {
  739. if ((position > m_ColorPoints[index].StartPos) &&
  740. (position < m_ColorPoints[index].EndPos)) {
  741. new_index = index + 1;
  742. found = true;
  743. //
  744. // Determine what graph percent to use if the control
  745. // is in graph mode
  746. //
  747. float key_percent = (((float)position) - ((float)m_ColorPoints[index].StartPos)) / float(m_ColorPoints[index].EndPos - m_ColorPoints[index].StartPos);
  748. float graph_start = m_ColorPoints[index].StartGraphPercent;
  749. float graph_delta = (m_ColorPoints[index].EndPos - m_ColorPoints[index].StartPos) * m_ColorPoints[index].GraphPercentInc;
  750. graph_percent = graph_start + (key_percent * graph_delta);
  751. }
  752. }
  753. bool retval = false;
  754. if (found) {
  755. Set_Redraw (false);
  756. //
  757. // Insert the new point
  758. //
  759. float position = m_MinPos + ((m_MaxPos - m_MinPos) * percent);
  760. retval = Insert_Point (new_index, position, red, green, blue);
  761. if (retval) {
  762. Set_Graph_Percent (new_index, graph_percent);
  763. m_iCurrentKey = new_index;
  764. }
  765. Set_Redraw (true);
  766. }
  767. return retval;
  768. }
  769. /////////////////////////////////////////////////////////////////////////////
  770. //
  771. // Insert_Point
  772. //
  773. bool
  774. ColorBarClass::Insert_Point
  775. (
  776. int index,
  777. float position,
  778. float red,
  779. float green,
  780. float blue,
  781. DWORD flags
  782. )
  783. {
  784. // Assume failure
  785. bool retval = false;
  786. // Params valid?
  787. if (((m_iColorPoints + 1) < MAX_COLOR_POINTS) &&
  788. (index >= 0) &&
  789. (index <= m_iColorPoints)) {
  790. // Bump all the points up one position in the array
  791. ::memmove (&m_ColorPoints[index + 1],
  792. &m_ColorPoints[index],
  793. sizeof (COLOR_POINT) * (m_iColorPoints - index));
  794. // Increment the point count
  795. m_iColorPoints ++;
  796. // Now all we have to do is modify the contents of the new point
  797. retval = Modify_Point (index, position, red, green, blue, flags);
  798. }
  799. // Return the true/false result code
  800. return retval;
  801. }
  802. /////////////////////////////////////////////////////////////////////////////
  803. //
  804. // Delete_Point
  805. //
  806. bool
  807. ColorBarClass::Delete_Point (int index)
  808. {
  809. // Assume failure
  810. bool retval = false;
  811. // Params valid?
  812. if ((index > 0) &&
  813. (index < m_iColorPoints)) {
  814. // Bump all the points up one position in the array
  815. ::memmove (&m_ColorPoints[index],
  816. &m_ColorPoints[index + 1],
  817. sizeof (COLOR_POINT) * (m_iColorPoints - (index + 1)));
  818. // Decrement the point count
  819. m_iColorPoints --;
  820. if (m_iCurrentKey > 0) {
  821. m_iCurrentKey --;
  822. }
  823. // Rebuild any color information we may need to
  824. Update_Point_Info ();
  825. // Force the window to be repainted
  826. Repaint ();
  827. retval = true;
  828. }
  829. // Return the true/false result code
  830. return retval;
  831. }
  832. /////////////////////////////////////////////////////////////////////////////
  833. //
  834. // Modify_Point
  835. //
  836. bool
  837. ColorBarClass::Modify_Point
  838. (
  839. int index,
  840. float position,
  841. float red,
  842. float green,
  843. float blue,
  844. DWORD flags
  845. )
  846. {
  847. // Assume failure
  848. bool retval = false;
  849. if ((index >= 0) && (index < m_iColorPoints)) {
  850. // Update the information about this color point
  851. m_ColorPoints[index].PosPercent = ((position - m_MinPos) / (m_MaxPos - m_MinPos));
  852. m_ColorPoints[index].StartRed = red;
  853. m_ColorPoints[index].StartGreen = green;
  854. m_ColorPoints[index].StartBlue = blue;
  855. m_ColorPoints[index].flags = flags;
  856. if (index == 0) {
  857. m_ColorPoints[index].flags &= ~POINT_CAN_MOVE;
  858. }
  859. // Rebuild any color information we may need to
  860. Update_Point_Info ();
  861. // Force the window to be repainted
  862. Repaint ();
  863. retval = true;
  864. } else if (index >= m_iColorPoints) {
  865. // If the user wants to tag on onto the end, then insert a new point...
  866. retval = Insert_Point (m_iColorPoints, position, red, green, blue);
  867. }
  868. // Return the true/false result code
  869. return retval;
  870. }
  871. /////////////////////////////////////////////////////////////////////////////
  872. //
  873. // Set_Range
  874. //
  875. void
  876. ColorBarClass::Set_Range
  877. (
  878. float min,
  879. float max
  880. )
  881. {
  882. m_MinPos = min;
  883. m_MaxPos = max;
  884. m_SelectionPos = m_MinPos;
  885. return ;
  886. }
  887. /////////////////////////////////////////////////////////////////////////////
  888. //
  889. // Update_Point_Info
  890. //
  891. void
  892. ColorBarClass::Update_Point_Info (void)
  893. {
  894. int width = m_ColorArea.Width ();
  895. int height = m_ColorArea.Height ();
  896. LONG style = GetWindowLong (m_hWnd, GWL_STYLE);
  897. if (style & CBRS_HORZ) {
  898. // Loop through all the color points
  899. for (int index = 0; index < m_iColorPoints; index ++) {
  900. // Update the absolute starting position for this point
  901. m_ColorPoints[index].StartPos = m_ColorArea.left + int(m_ColorPoints[index].PosPercent * width);
  902. // Update the color information for the previous point
  903. if (index > 0) {
  904. m_ColorPoints[index-1].EndPos = m_ColorPoints[index].StartPos;
  905. //
  906. // Assign color increments to the previous color point
  907. //
  908. int width = m_ColorPoints[index-1].EndPos - m_ColorPoints[index-1].StartPos;
  909. m_ColorPoints[index-1].RedInc = (m_ColorPoints[index].StartRed - m_ColorPoints[index-1].StartRed) / ((float)width);
  910. m_ColorPoints[index-1].GreenInc = (m_ColorPoints[index].StartGreen - m_ColorPoints[index-1].StartGreen) / ((float)width);
  911. m_ColorPoints[index-1].BlueInc = (m_ColorPoints[index].StartBlue - m_ColorPoints[index-1].StartBlue) / ((float)width);
  912. // Assign the graph increment to the previous point
  913. m_ColorPoints[index-1].GraphPercentInc = (m_ColorPoints[index].StartGraphPercent - m_ColorPoints[index-1].StartGraphPercent) / ((float)width);
  914. }
  915. }
  916. m_ColorPoints[index-1].RedInc = 0;
  917. m_ColorPoints[index-1].GreenInc = 0;
  918. m_ColorPoints[index-1].BlueInc = 0;
  919. m_ColorPoints[index-1].GraphPercentInc = 0;
  920. m_ColorPoints[index-1].EndPos = m_ColorArea.right;
  921. } else {
  922. // Loop through all the color points
  923. for (int index = 0; index < m_iColorPoints; index ++) {
  924. // Update the absolute starting position for this point
  925. m_ColorPoints[index].StartPos = m_ColorArea.top + int(m_ColorPoints[index].PosPercent * height);
  926. // Update the color information for the previous point
  927. if (index > 0) {
  928. m_ColorPoints[index-1].EndPos = m_ColorPoints[index].StartPos;
  929. // Assign color increments to the previous color point
  930. int height = m_ColorPoints[index-1].EndPos - m_ColorPoints[index-1].StartPos;
  931. m_ColorPoints[index-1].RedInc = (m_ColorPoints[index].StartRed - m_ColorPoints[index-1].StartRed) / ((float)height);
  932. m_ColorPoints[index-1].GreenInc = (m_ColorPoints[index].StartGreen - m_ColorPoints[index-1].StartGreen) / ((float)height);
  933. m_ColorPoints[index-1].BlueInc = (m_ColorPoints[index].StartBlue - m_ColorPoints[index-1].StartBlue) / ((float)height);
  934. }
  935. }
  936. m_ColorPoints[index-1].RedInc = 0;
  937. m_ColorPoints[index-1].GreenInc = 0;
  938. m_ColorPoints[index-1].BlueInc = 0;
  939. m_ColorPoints[index-1].EndPos = m_ColorArea.bottom;
  940. }
  941. // Repaint the color bar
  942. Paint_DIB ();
  943. return ;
  944. }
  945. /////////////////////////////////////////////////////////////////////////////
  946. //
  947. // Free_Marker_Bitmap
  948. //
  949. void
  950. ColorBarClass::Free_Marker_Bitmap (void)
  951. {
  952. if (m_KeyFrameDIB != NULL) {
  953. ::DeleteObject (m_KeyFrameDIB);
  954. m_KeyFrameDIB = NULL;
  955. m_pKeyFrameBits = NULL;
  956. }
  957. return ;
  958. }
  959. /////////////////////////////////////////////////////////////////////////////
  960. //
  961. // Load_Key_Frame_BMP
  962. //
  963. void
  964. ColorBarClass::Load_Key_Frame_BMP (void)
  965. {
  966. Free_Marker_Bitmap ();
  967. //
  968. // Load the appropriate BMP based on the barstyle
  969. //
  970. LONG style = ::GetWindowLong (m_hWnd, GWL_STYLE);
  971. HBITMAP hbmp = NULL;
  972. if (style & CBRS_HORZ) {
  973. hbmp = ::LoadBitmap (::AfxGetResourceHandle (), MAKEINTRESOURCE (IDB_KEYFRAME_V));
  974. } else {
  975. hbmp = ::LoadBitmap (::AfxGetResourceHandle (), MAKEINTRESOURCE (IDB_KEYFRAME_H));
  976. }
  977. //
  978. // Get the dimensions of the BMP
  979. //
  980. BITMAP bmp_info = { 0 };
  981. ::GetObject (hbmp, sizeof (BITMAP), (LPVOID)&bmp_info);
  982. m_iMarkerWidth = bmp_info.bmWidth;
  983. m_iMarkerHeight = bmp_info.bmHeight;
  984. // Set-up the fields of the BITMAPINFOHEADER
  985. BITMAPINFOHEADER bitmap_info;
  986. bitmap_info.biSize = sizeof (BITMAPINFOHEADER);
  987. bitmap_info.biWidth = m_iMarkerWidth;
  988. bitmap_info.biHeight = -m_iMarkerHeight; // Top-down DIB uses negative height
  989. bitmap_info.biPlanes = 1;
  990. bitmap_info.biBitCount = 24;
  991. bitmap_info.biCompression = BI_RGB;
  992. bitmap_info.biSizeImage = ((m_iMarkerWidth * m_iMarkerHeight) * 3);
  993. bitmap_info.biXPelsPerMeter = 0;
  994. bitmap_info.biYPelsPerMeter = 0;
  995. bitmap_info.biClrUsed = 0;
  996. bitmap_info.biClrImportant = 0;
  997. // Get a temporary screen DC
  998. HDC hscreen_dc = ::GetDC (NULL);
  999. // Create a bitmap that we can access the bits directly of
  1000. m_KeyFrameDIB = ::CreateDIBSection (hscreen_dc,
  1001. (const BITMAPINFO *)&bitmap_info,
  1002. DIB_RGB_COLORS,
  1003. (void **)&m_pKeyFrameBits,
  1004. NULL,
  1005. 0L);
  1006. // Release our temporary screen DC
  1007. ::ReleaseDC (NULL, hscreen_dc);
  1008. // Initialize 2 temp DCs so we can copy from the BMP to the DIB section
  1009. HDC htemp_dc = ::CreateCompatibleDC (NULL);
  1010. HBITMAP hold_bmp1 = (HBITMAP)::SelectObject (m_hMemDC, m_KeyFrameDIB);
  1011. HBITMAP hold_bmp2 = (HBITMAP)::SelectObject (htemp_dc, hbmp);
  1012. // Copy the marker from the BMP to the DIB section
  1013. ::BitBlt (m_hMemDC, 0, 0, m_iMarkerWidth, m_iMarkerHeight, htemp_dc, 0, 0, SRCCOPY);
  1014. // Restore the DCs
  1015. ::SelectObject (m_hMemDC, hold_bmp1);
  1016. ::SelectObject (htemp_dc, hold_bmp2);
  1017. ::DeleteDC (htemp_dc);
  1018. ::DeleteObject (hbmp);
  1019. return ;
  1020. }
  1021. /////////////////////////////////////////////////////////////////////////////
  1022. //
  1023. // Paint_Key_Frame
  1024. //
  1025. void
  1026. ColorBarClass::Paint_Key_Frame (int x_pos, int y_pos)
  1027. {
  1028. // Window's bitmaps are DWORD aligned, so make sure
  1029. // we take that into account.
  1030. int alignment_offset = (m_iMarkerWidth * 3) % 4;
  1031. alignment_offset = (alignment_offset != 0) ? (4 - alignment_offset) : 0;
  1032. int marker_scanline = (m_iMarkerWidth * 3) + alignment_offset;
  1033. int width_in_bytes = m_iMarkerWidth * 3;
  1034. if ((m_pBits != NULL) && (m_pKeyFrameBits != NULL)) {
  1035. int dest_index = (m_iScanlineSize * y_pos) + (x_pos * 3);
  1036. int src_index = 0;
  1037. //
  1038. // 'Blit' the image from the source buffer to the dest buffer
  1039. //
  1040. for (int scanline = 0; scanline < m_iMarkerHeight; scanline ++) {
  1041. for (int pixel = 0; pixel < m_iMarkerWidth; pixel ++) {
  1042. BYTE blue = m_pKeyFrameBits[src_index ++];
  1043. BYTE green = m_pKeyFrameBits[src_index ++];
  1044. BYTE red = m_pKeyFrameBits[src_index ++];
  1045. if (blue == 255 && green == 0 && red == 255) {
  1046. dest_index += 3;
  1047. } else {
  1048. m_pBits[dest_index ++] = blue;
  1049. m_pBits[dest_index ++] = green;
  1050. m_pBits[dest_index ++] = red;
  1051. }
  1052. }
  1053. // Skip to the next scanline
  1054. dest_index += (m_iScanlineSize - width_in_bytes);
  1055. src_index += alignment_offset;
  1056. }
  1057. }
  1058. return ;
  1059. }
  1060. /////////////////////////////////////////////////////////////////////////////
  1061. //
  1062. // Marker_From_Point
  1063. //
  1064. int
  1065. ColorBarClass::Marker_From_Point (CPoint point)
  1066. {
  1067. int marker_index = -1;
  1068. //
  1069. // Setup the data we need for the search
  1070. //
  1071. LONG style = ::GetWindowLong (m_hWnd, GWL_STYLE);
  1072. int accept_dist = 0;
  1073. int position = 0;
  1074. if (style & CBRS_HORZ) {
  1075. position = point.x;// - m_ColorArea.left;
  1076. accept_dist = (m_iMarkerWidth + 1) >> 1;
  1077. } else {
  1078. position = point.y;// - m_ColorArea.top;
  1079. accept_dist = (m_iMarkerHeight + 1) >> 1;
  1080. }
  1081. //
  1082. // Search through all the points, trying to find the closest
  1083. //
  1084. int closest = -1;
  1085. int closest_dist = 1024;
  1086. for (int index = 0; index < m_iColorPoints; index ++) {
  1087. int delta = abs (m_ColorPoints[index].StartPos - position);
  1088. if (delta < closest_dist) {
  1089. closest_dist = delta;
  1090. closest = index;
  1091. }
  1092. }
  1093. //
  1094. // Did we find a marker at this point?
  1095. //
  1096. if (closest_dist < accept_dist) {
  1097. marker_index = closest;
  1098. }
  1099. // Return the index of the marker at the specified point (-1 if not found).
  1100. return marker_index;
  1101. }
  1102. /////////////////////////////////////////////////////////////////////////////
  1103. //
  1104. // OnLButtonDown
  1105. //
  1106. void
  1107. ColorBarClass::OnLButtonDown
  1108. (
  1109. UINT nFlags,
  1110. CPoint point
  1111. )
  1112. {
  1113. //
  1114. // Ensure we have the focus
  1115. //
  1116. if (::GetFocus () != m_hWnd) {
  1117. ::SetFocus (m_hWnd);
  1118. }
  1119. LONG style = ::GetWindowLong (m_hWnd, GWL_STYLE);
  1120. if (style & CBRS_SHOW_FRAMES) {
  1121. //
  1122. // Find the key frame the user clicked on
  1123. //
  1124. int marker_clicked = Marker_From_Point (point);
  1125. if (marker_clicked != -1) {
  1126. // Did the user select a new key?
  1127. if (m_iCurrentKey != marker_clicked) {
  1128. m_iCurrentKey = marker_clicked;
  1129. // Repaint the window
  1130. Repaint ();
  1131. }
  1132. // Should we prepare to move this marker?
  1133. if (m_ColorPoints[m_iCurrentKey].flags & POINT_CAN_MOVE) {
  1134. m_bMoving = true;
  1135. m_bMoved = false;
  1136. ::SetCapture (m_hWnd);
  1137. }
  1138. } else {
  1139. //
  1140. // Insert a new point at this location if the user has the Ctrl key down
  1141. //
  1142. if (::GetAsyncKeyState (VK_CONTROL) < 0) {
  1143. Insert_Point (point);
  1144. Send_Notification (CBRN_INSERTED_POINT, m_iCurrentKey);
  1145. }
  1146. m_bMoving = false;
  1147. m_bMoved = false;
  1148. ::ReleaseCapture ();
  1149. }
  1150. } else if (style & CBRS_HAS_SEL) {
  1151. Move_Selection (point);
  1152. // CRect rect;
  1153. //Get_Selection_Rectangle (rect);
  1154. //if (rect.PtInRect (point)) {
  1155. m_bMoving = true;
  1156. m_bMoved = false;
  1157. ::SetCapture (m_hWnd);
  1158. //}
  1159. }
  1160. CWnd::OnLButtonDown (nFlags, point);
  1161. return ;
  1162. }
  1163. /////////////////////////////////////////////////////////////////////////////
  1164. //
  1165. // OnLButtonUp
  1166. //
  1167. void
  1168. ColorBarClass::OnLButtonUp
  1169. (
  1170. UINT nFlags,
  1171. CPoint point
  1172. )
  1173. {
  1174. if (m_bMoving) {
  1175. ::ReleaseCapture ();
  1176. m_bMoving = false;
  1177. //
  1178. // Let the parent know one of the points was dragged
  1179. //
  1180. if (m_bMoved) {
  1181. Send_Notification (CBRN_MOVED_POINT, m_iCurrentKey);
  1182. }
  1183. }
  1184. CWnd::OnLButtonUp (nFlags, point);
  1185. return ;
  1186. }
  1187. /////////////////////////////////////////////////////////////////////////////
  1188. //
  1189. // OnMouseMove
  1190. //
  1191. void
  1192. ColorBarClass::OnMouseMove
  1193. (
  1194. UINT nFlags,
  1195. CPoint point
  1196. )
  1197. {
  1198. if (m_bMoving) {
  1199. LONG style = ::GetWindowLong (m_hWnd, GWL_STYLE);
  1200. if (style & CBRS_SHOW_FRAMES) {
  1201. float min_percent = 0;
  1202. float max_percent = 1.0F;
  1203. //
  1204. // Determine the range this marker can move
  1205. //
  1206. if (m_iCurrentKey > 0) {
  1207. min_percent = m_ColorPoints[m_iCurrentKey - 1].PosPercent + 0.01F;
  1208. }
  1209. if (m_iCurrentKey < (m_iColorPoints - 1)) {
  1210. max_percent = m_ColorPoints[m_iCurrentKey + 1].PosPercent - 0.01F;
  1211. }
  1212. //
  1213. // Determine where the marker should be
  1214. //
  1215. float new_percent = 0;
  1216. LONG style = ::GetWindowLong (m_hWnd, GWL_STYLE);
  1217. if (style & CBRS_HORZ) {
  1218. new_percent = ((float)(point.x - m_ColorArea.left)) / ((float)m_ColorArea.Width ());
  1219. } else {
  1220. new_percent = ((float)(point.y - m_ColorArea.top)) / ((float)m_ColorArea.Height ());
  1221. }
  1222. //
  1223. // Ensure the marker is in bounds
  1224. //
  1225. new_percent = max (min_percent, new_percent);
  1226. new_percent = min (max_percent, new_percent);
  1227. //
  1228. // Move the marker
  1229. //
  1230. m_ColorPoints[m_iCurrentKey].PosPercent = new_percent;
  1231. Update_Point_Info ();
  1232. //
  1233. // Repaint the screen
  1234. //
  1235. HDC hwnd_dc = ::GetDC (m_hWnd);
  1236. Paint_Screen (hwnd_dc);
  1237. ::ReleaseDC (m_hWnd, hwnd_dc);
  1238. //
  1239. // Notify the parent window that the user dragged
  1240. // one of the keyframes
  1241. //
  1242. Send_Notification (CBRN_MOVING_POINT, m_iCurrentKey);
  1243. m_bMoved = true;
  1244. } else if (style & CBRS_HAS_SEL) {
  1245. Move_Selection (point);
  1246. }
  1247. }
  1248. CWnd::OnMouseMove (nFlags, point);
  1249. return ;
  1250. }
  1251. /////////////////////////////////////////////////////////////////////////////
  1252. //
  1253. // Send_Notification
  1254. //
  1255. LRESULT
  1256. ColorBarClass::Send_Notification (int code, int key)
  1257. {
  1258. //
  1259. // Fill in the nofitication structure
  1260. //
  1261. LONG id = ::GetWindowLong (m_hWnd, GWL_ID);
  1262. CBR_NMHDR notify_hdr = { 0 };
  1263. notify_hdr.hdr.hwndFrom = m_hWnd;
  1264. notify_hdr.hdr.idFrom = id;
  1265. notify_hdr.hdr.code = code;
  1266. notify_hdr.key_index = key;
  1267. notify_hdr.red = m_ColorPoints[key].StartRed;
  1268. notify_hdr.green = m_ColorPoints[key].StartGreen;
  1269. notify_hdr.blue = m_ColorPoints[key].StartBlue;
  1270. notify_hdr.position = m_MinPos + (m_ColorPoints[key].PosPercent * (m_MaxPos - m_MinPos));
  1271. //
  1272. // Send the notification to the parent window
  1273. //
  1274. return ::SendMessage (::GetParent (m_hWnd), WM_NOTIFY, id, (LPARAM)&notify_hdr);
  1275. }
  1276. /////////////////////////////////////////////////////////////////////////////
  1277. //
  1278. // OnKillFocus
  1279. //
  1280. void
  1281. ColorBarClass::OnKillFocus (CWnd *pNewWnd)
  1282. {
  1283. // Force a repaint
  1284. Repaint ();
  1285. CWnd::OnKillFocus (pNewWnd);
  1286. return ;
  1287. }
  1288. /////////////////////////////////////////////////////////////////////////////
  1289. //
  1290. // OnSetFocus
  1291. //
  1292. void
  1293. ColorBarClass::OnSetFocus (CWnd *pOldWnd)
  1294. {
  1295. // Force a repaint
  1296. Repaint ();
  1297. CWnd::OnSetFocus(pOldWnd);
  1298. return ;
  1299. }
  1300. /////////////////////////////////////////////////////////////////////////////
  1301. //
  1302. // OnKeyDown
  1303. //
  1304. void
  1305. ColorBarClass::OnKeyDown
  1306. (
  1307. UINT nChar,
  1308. UINT nRepCnt,
  1309. UINT nFlags
  1310. )
  1311. {
  1312. if ((nChar == VK_DELETE) && (::GetFocus () == m_hWnd)) {
  1313. //
  1314. // Notify the parent window that we are deleting a key
  1315. // and ask them if its OK to contiue
  1316. //
  1317. if (Send_Notification (CBRN_DEL_POINT, m_iCurrentKey) != STOP_EVENT) {
  1318. // Go ahead and delete the point
  1319. Delete_Point (m_iCurrentKey);
  1320. Send_Notification (CBRN_DELETED_POINT, m_iCurrentKey);
  1321. }
  1322. }/* else if (::GetFocus () == m_hWnd) {
  1323. if (nChar == VK_RIGHT) &&
  1324. }*/
  1325. CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
  1326. return ;
  1327. }
  1328. /////////////////////////////////////////////////////////////////////////////
  1329. //
  1330. // OnLButtonDblClk
  1331. //
  1332. void
  1333. ColorBarClass::OnLButtonDblClk
  1334. (
  1335. UINT nFlags,
  1336. CPoint point
  1337. )
  1338. {
  1339. int marker_clicked = Marker_From_Point (point);
  1340. if (marker_clicked != -1) {
  1341. //
  1342. // Notify the parent window that the user double-clicked
  1343. // one of the keyframes
  1344. //
  1345. Send_Notification (CBRN_DBLCLK_POINT, marker_clicked);
  1346. }
  1347. CWnd::OnLButtonDblClk(nFlags, point);
  1348. return ;
  1349. }
  1350. /////////////////////////////////////////////////////////////////////////////
  1351. //
  1352. // Get_Selection_Rectangle
  1353. //
  1354. void
  1355. ColorBarClass::Get_Selection_Rectangle (CRect &rect)
  1356. {
  1357. float pos_percent = ((float)(m_SelectionPos - m_MinPos)) / ((float)(m_MaxPos - m_MinPos));
  1358. rect = m_ColorArea;
  1359. //
  1360. // Determine the bounding rectangle for the selection
  1361. //
  1362. LONG style = ::GetWindowLong (m_hWnd, GWL_STYLE);
  1363. if (style & CBRS_HORZ) {
  1364. rect.left = (m_ColorArea.left + int(m_ColorArea.Width () * pos_percent)) - 3;
  1365. rect.right = rect.left + 6;
  1366. if (style & CBRS_FRAME_MASK) {
  1367. rect.top --;
  1368. rect.bottom ++;
  1369. }
  1370. } else {
  1371. rect.top = (m_ColorArea.top + int(m_ColorArea.Height () * pos_percent)) - 3;
  1372. rect.bottom = rect.top + 6;
  1373. if (style & CBRS_FRAME_MASK) {
  1374. rect.left --;
  1375. rect.right ++;
  1376. }
  1377. }
  1378. return ;
  1379. }
  1380. /////////////////////////////////////////////////////////////////////////////
  1381. //
  1382. // Set_Selection_Pos
  1383. //
  1384. void
  1385. ColorBarClass::Set_Selection_Pos (float pos)
  1386. {
  1387. // Ensure the new position is in bounds
  1388. pos = max (pos, m_MinPos);
  1389. pos = min (pos, m_MaxPos);
  1390. // Move the selection
  1391. Move_Selection (pos, false);
  1392. return ;
  1393. }
  1394. /////////////////////////////////////////////////////////////////////////////
  1395. //
  1396. // Move_Selection
  1397. //
  1398. void
  1399. ColorBarClass::Move_Selection (CPoint point, bool send_notify)
  1400. {
  1401. //
  1402. // Determine the selection's new position
  1403. //
  1404. float percent = 0;
  1405. LONG style = ::GetWindowLong (m_hWnd, GWL_STYLE);
  1406. if (style & CBRS_HORZ) {
  1407. percent = (((float)(point.x - m_ColorArea.left)) / ((float)m_ColorArea.Width ()));
  1408. } else {
  1409. percent = (((float)(point.y - m_ColorArea.top)) / ((float)m_ColorArea.Height ()));
  1410. }
  1411. float new_pos = m_MinPos + (percent * (m_MaxPos - m_MinPos));
  1412. new_pos = max (new_pos, m_MinPos);
  1413. new_pos = min (new_pos, m_MaxPos);
  1414. // Do the actual move
  1415. Move_Selection (new_pos, send_notify);
  1416. return ;
  1417. }
  1418. /////////////////////////////////////////////////////////////////////////////
  1419. //
  1420. // Move_Selection
  1421. //
  1422. void
  1423. ColorBarClass::Move_Selection (float new_pos, bool send_notify)
  1424. {
  1425. if (new_pos != m_SelectionPos) {
  1426. m_SelectionPos = new_pos;
  1427. //
  1428. // Notify the parent window that the user changed the selection
  1429. //
  1430. if (send_notify) {
  1431. LONG id = ::GetWindowLong (m_hWnd, GWL_ID);
  1432. CBR_NMHDR notify_hdr = { 0 };
  1433. notify_hdr.hdr.hwndFrom = m_hWnd;
  1434. notify_hdr.hdr.idFrom = id;
  1435. notify_hdr.hdr.code = CBRN_SEL_CHANGED;
  1436. notify_hdr.position = m_SelectionPos;
  1437. // Determine the color are this position
  1438. Get_Color (m_SelectionPos,
  1439. &notify_hdr.red,
  1440. &notify_hdr.green,
  1441. &notify_hdr.blue);
  1442. //
  1443. // Send the notification to the parent
  1444. //
  1445. ::SendMessage (::GetParent (m_hWnd),
  1446. WM_NOTIFY,
  1447. id,
  1448. (LPARAM)&notify_hdr);
  1449. }
  1450. // Repaint the color bar with the new selection rectangle
  1451. Paint_DIB ();
  1452. //
  1453. // Repaint the screen
  1454. //
  1455. HDC hwnd_dc = ::GetDC (m_hWnd);
  1456. Paint_Screen (hwnd_dc);
  1457. ::ReleaseDC (m_hWnd, hwnd_dc);
  1458. }
  1459. return ;
  1460. }
  1461. /////////////////////////////////////////////////////////////////////////////
  1462. //
  1463. // Get_Color
  1464. //
  1465. void
  1466. ColorBarClass::Get_Color
  1467. (
  1468. float position,
  1469. float *red,
  1470. float *green,
  1471. float *blue
  1472. )
  1473. {
  1474. //
  1475. // Index into the color bitmap at the correct location...
  1476. //
  1477. LONG style = ::GetWindowLong (m_hWnd, GWL_STYLE);
  1478. int pixel_pos = 0;
  1479. if (style & CBRS_HORZ) {
  1480. float percent = m_MinPos + (position - m_MinPos) / (m_MaxPos - m_MinPos);
  1481. pixel_pos = int(m_ColorArea.left + (percent * (float)m_ColorArea.Width ()));
  1482. /*int bmp_index = ((m_ColorArea.top + 1) * m_iScanlineSize) + (x * 3);
  1483. (*blue) = m_pBits[bmp_index];
  1484. (*green) = m_pBits[bmp_index+1];
  1485. (*red) = m_pBits[bmp_index+2];*/
  1486. } else {
  1487. float percent = m_MinPos + (position - m_MinPos) / (m_MaxPos - m_MinPos);
  1488. pixel_pos = int(m_ColorArea.top + (percent * (float)m_ColorArea.Height ()));
  1489. /*int bmp_index = (y * m_iScanlineSize) + (m_ColorArea.left * 3);
  1490. (*blue) = m_pBits[bmp_index];
  1491. (*green) = m_pBits[bmp_index+1];
  1492. (*red) = m_pBits[bmp_index+2];*/
  1493. }
  1494. //
  1495. // Find the index where this point should be inserted
  1496. //
  1497. bool found = false;
  1498. int key_index = 0;
  1499. for (int index = 0; (index < m_iColorPoints) && !found; index ++) {
  1500. if ((pixel_pos >= m_ColorPoints[index].StartPos) &&
  1501. (pixel_pos <= m_ColorPoints[index].EndPos)) {
  1502. key_index = index;
  1503. found = true;
  1504. }
  1505. }
  1506. if (found) {
  1507. int start_pos = m_ColorPoints[key_index].StartPos;
  1508. int end_pos = m_ColorPoints[key_index].EndPos;
  1509. //float ticks = pixel_pos - start_pos) / float(end_pos - start_pos);
  1510. float ticks = float(pixel_pos) - float(m_ColorPoints[key_index].StartPos);
  1511. (*red) = m_ColorPoints[key_index].StartRed;
  1512. (*green) = m_ColorPoints[key_index].StartGreen;
  1513. (*blue) = m_ColorPoints[key_index].StartBlue;
  1514. (*red) += ticks * m_ColorPoints[key_index].RedInc;
  1515. (*green) += ticks * m_ColorPoints[key_index].GreenInc;
  1516. (*blue) += ticks * m_ColorPoints[key_index].BlueInc;
  1517. }
  1518. return ;
  1519. }
  1520. /////////////////////////////////////////////////////////////////////////////
  1521. //
  1522. // Clear_Points
  1523. //
  1524. void
  1525. ColorBarClass::Clear_Points (void)
  1526. {
  1527. // Reset the point count
  1528. m_iColorPoints = 1;
  1529. // Rebuild the color information
  1530. Update_Point_Info ();
  1531. // Force the window to be repainted
  1532. Repaint ();
  1533. return ;
  1534. }
  1535. /////////////////////////////////////////////////////////////////////////////
  1536. //
  1537. // Set_User_Data
  1538. //
  1539. bool
  1540. ColorBarClass::Set_User_Data (int index, DWORD data)
  1541. {
  1542. bool retval = false;
  1543. if ((index >= 0) && (index < m_iColorPoints)) {
  1544. m_ColorPoints[index].user_data = data;
  1545. retval = true;
  1546. }
  1547. return retval;
  1548. }
  1549. /////////////////////////////////////////////////////////////////////////////
  1550. //
  1551. // Get_User_Data
  1552. //
  1553. DWORD
  1554. ColorBarClass::Get_User_Data (int index)
  1555. {
  1556. DWORD data = 0;
  1557. if ((index >= 0) && (index < m_iColorPoints)) {
  1558. data = m_ColorPoints[index].user_data;
  1559. }
  1560. return data;
  1561. }
  1562. /////////////////////////////////////////////////////////////////////////////
  1563. //
  1564. // Set_Graph_Percent
  1565. //
  1566. bool
  1567. ColorBarClass::Set_Graph_Percent (int index, float percent)
  1568. {
  1569. bool retval = false;
  1570. if ((index >= 0) && (index < m_iColorPoints)) {
  1571. m_ColorPoints[index].StartGraphPercent = percent;
  1572. // Rebuild the color information
  1573. Update_Point_Info ();
  1574. // Force the window to be repainted
  1575. Repaint ();
  1576. retval = true;
  1577. }
  1578. return retval;
  1579. }
  1580. /////////////////////////////////////////////////////////////////////////////
  1581. //
  1582. // Get_Graph_Percent
  1583. //
  1584. float
  1585. ColorBarClass::Get_Graph_Percent (int index)
  1586. {
  1587. float percent = 0;
  1588. if ((index >= 0) && (index < m_iColorPoints)) {
  1589. percent = m_ColorPoints[index].StartGraphPercent;
  1590. }
  1591. return percent;
  1592. }
  1593. /////////////////////////////////////////////////////////////////////////////
  1594. //
  1595. // Set_Redraw
  1596. //
  1597. void
  1598. ColorBarClass::Set_Redraw (bool redraw)
  1599. {
  1600. m_bRedraw = redraw;
  1601. if (m_bRedraw) {
  1602. UpdateWindow ();
  1603. }
  1604. return ;
  1605. }
  1606. /////////////////////////////////////////////////////////////////////////////
  1607. //
  1608. // Repaint
  1609. //
  1610. void
  1611. ColorBarClass::Repaint (void)
  1612. {
  1613. InvalidateRect (NULL, FALSE);
  1614. if (m_bRedraw) {
  1615. UpdateWindow ();
  1616. }
  1617. return ;
  1618. }