PlayerSubresyncBar.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:34k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /* 
  2.  * Copyright (C) 2003-2005 Gabest
  3.  * http://www.gabest.org
  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 2, or (at your option)
  8.  *  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 GNU Make; see the file COPYING.  If not, write to
  17.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  18.  *  http://www.gnu.org/copyleft/gpl.html
  19.  *
  20.  */
  21. // PlayerSubresyncBar.cpp : implementation file
  22. //
  23. #include "stdafx.h"
  24. #include "mplayerc.h"
  25. #include "mainfrm.h"
  26. #include "PlayerSubresyncBar.h"
  27. // CPlayerSubresyncBar
  28. IMPLEMENT_DYNAMIC(CPlayerSubresyncBar, CSizingControlBarG)
  29. CPlayerSubresyncBar::CPlayerSubresyncBar()
  30. {
  31. m_rt = 0;
  32. m_fUnlink = false;
  33. m_lastSegment = -1;
  34. }
  35. CPlayerSubresyncBar::~CPlayerSubresyncBar()
  36. {
  37. }
  38. BOOL CPlayerSubresyncBar::Create(CWnd* pParentWnd, CCritSec* pSubLock)
  39. {
  40. if(!CSizingControlBarG::Create(_T("Subresync"), pParentWnd, 50))
  41. return FALSE;
  42. m_pSubLock = pSubLock;
  43. m_list.CreateEx(
  44. WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE, 
  45. WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_TABSTOP|LVS_REPORT/*|LVS_SHOWSELALWAYS*/|LVS_AUTOARRANGE|LVS_NOSORTHEADER, 
  46. CRect(0,0,100,100), this, IDC_SUBRESYNCLIST);
  47. m_list.SetExtendedStyle(m_list.GetExtendedStyle()|LVS_EX_FULLROWSELECT|LVS_EX_DOUBLEBUFFER);
  48. return TRUE;
  49. }
  50. BOOL CPlayerSubresyncBar::PreCreateWindow(CREATESTRUCT& cs)
  51. {
  52. if(!CSizingControlBarG::PreCreateWindow(cs))
  53. return FALSE;
  54. return TRUE;
  55. }
  56. BOOL CPlayerSubresyncBar::PreTranslateMessage(MSG* pMsg)
  57. {
  58. if(IsWindow(pMsg->hwnd) && IsVisible() && pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST)
  59. {
  60. if(IsDialogMessage(pMsg))
  61. return TRUE;
  62. }
  63. return CSizingControlBarG::PreTranslateMessage(pMsg);
  64. }
  65. void CPlayerSubresyncBar::SetTime(__int64 rt)
  66. {
  67. m_rt = rt;
  68. int curSegment;
  69. if(!m_sts.SearchSubs((int)(rt/10000), 25, &curSegment))
  70. {
  71. curSegment = -1;
  72. }
  73. if(m_lastSegment != curSegment) m_list.Invalidate();
  74. m_lastSegment = curSegment;
  75. }
  76. void CPlayerSubresyncBar::SetSubtitle(ISubStream* pSubStream, double fps)
  77. {
  78. m_pSubStream = pSubStream;
  79. m_mode = NONE;
  80. m_lastSegment = -1;
  81. m_sts.Empty();
  82. ResetSubtitle();
  83. if(!m_pSubStream) return;
  84. CLSID clsid;
  85. m_pSubStream->GetClassID(&clsid);
  86. if(clsid == __uuidof(CVobSubFile))
  87. {
  88. CVobSubFile* pVSF = (CVobSubFile*)(ISubStream*)m_pSubStream;
  89. m_mode = VOBSUB;
  90. CArray<CVobSubFile::SubPos>& sp = pVSF->m_langs[pVSF->m_iLang].subpos;
  91. for(int i = 0, j = sp.GetSize(); i < j; i++)
  92. {
  93. CString str;
  94. str.Format(_T("%d,%d,%d,%d"), sp[i].vobid, sp[i].cellid, sp[i].fForced, i);
  95. m_sts.Add(TToW(str), false, (int)sp[i].start, (int)sp[i].stop);
  96. }
  97. m_sts.CreateDefaultStyle(DEFAULT_CHARSET);
  98. pVSF->m_fOnlyShowForcedSubs = false;
  99. for(int i = 0, j = m_list.GetHeaderCtrl()->GetItemCount(); i < j; i++) m_list.DeleteColumn(0);
  100. m_list.InsertColumn(COL_START, _T("Time"), LVCFMT_LEFT, 80);
  101. m_list.InsertColumn(COL_END, _T("End"), LVCFMT_LEFT, 80);
  102. m_list.InsertColumn(COL_PREVSTART, _T("Preview"), LVCFMT_LEFT, 80);
  103. m_list.InsertColumn(COL_PREVEND, _T("End"), LVCFMT_LEFT, 80);
  104. m_list.InsertColumn(COL_VOBID, _T("Vob ID"), LVCFMT_CENTER, 60);
  105. m_list.InsertColumn(COL_CELLID, _T("Cell ID"), LVCFMT_CENTER, 60);
  106. m_list.InsertColumn(COL_FORCED, _T("Forced"), LVCFMT_CENTER, 60);
  107. }
  108. else if(clsid == __uuidof(CRenderedTextSubtitle))
  109. {
  110. CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)m_pSubStream;
  111. m_mode = TEXTSUB;
  112. m_sts.Copy(*pRTS);
  113. m_sts.ConvertToTimeBased(fps);
  114. m_sts.Sort(true); /*!!m_fUnlink*/
  115. #ifndef UNICODE
  116. if(!m_sts.IsEntryUnicode(0))
  117. {
  118. CFont* f = m_list.GetFont();
  119. LOGFONT lf;
  120. f->GetLogFont(&lf);
  121. lf.lfCharSet = m_sts.GetCharSet(0);
  122. m_font.DeleteObject();
  123. m_font.CreateFontIndirect(&lf);
  124. m_list.SetFont(&m_font);
  125. }
  126. #endif
  127. for(int i = 0, j = m_list.GetHeaderCtrl()->GetItemCount(); i < j; i++) m_list.DeleteColumn(0);
  128. m_list.InsertColumn(COL_START, _T("Time"), LVCFMT_LEFT, 90);
  129. m_list.InsertColumn(COL_END, _T("End"), LVCFMT_LEFT, 4);
  130. m_list.InsertColumn(COL_PREVSTART, _T("Preview"), LVCFMT_LEFT, 80);
  131. m_list.InsertColumn(COL_PREVEND, _T("End"), LVCFMT_LEFT, 4);
  132. m_list.InsertColumn(COL_TEXT, _T("Text"), LVCFMT_LEFT, 275);
  133. m_list.InsertColumn(COL_STYLE, _T("Style"), LVCFMT_LEFT, 80);
  134. m_list.InsertColumn(COL_FONT, _T("Font"), LVCFMT_LEFT, 60);
  135. m_list.InsertColumn(COL_CHARSET, _T("CharSet"), LVCFMT_CENTER, 20);
  136. m_list.InsertColumn(COL_UNICODE, _T("Unicode"), LVCFMT_CENTER, 40);
  137. m_list.InsertColumn(COL_LAYER, _T("Layer"), LVCFMT_CENTER, 50);
  138. m_list.InsertColumn(COL_ACTOR, _T("Actor"), LVCFMT_LEFT, 80);
  139. m_list.InsertColumn(COL_EFFECT, _T("Effect"), LVCFMT_LEFT, 80);
  140. }
  141. m_subtimes.SetSize(m_sts.GetSize());
  142. for(int i = 0, j = m_sts.GetSize(); i < j; i++)
  143. {
  144. m_subtimes[i].orgstart = m_sts[i].start;
  145. m_subtimes[i].orgend = m_sts[i].end;
  146. }
  147. ResetSubtitle();
  148. }
  149. void CPlayerSubresyncBar::ResetSubtitle()
  150. {
  151. m_list.DeleteAllItems();
  152. if(m_mode == VOBSUB || m_mode == TEXTSUB) 
  153. {
  154. TCHAR buff[32];
  155. int prevstart = INT_MIN;
  156. for(int i = 0, j = m_sts.GetSize(); i < j; i++)
  157. {
  158. m_subtimes[i].newstart = m_subtimes[i].orgstart;
  159. m_subtimes[i].newend = m_subtimes[i].orgend;
  160. FormatTime(i, buff, 0, false);
  161. m_list.InsertItem(i, buff, COL_START);
  162. FormatTime(i, buff, 0, true);
  163. m_list.SetItemText(i, COL_END, buff);
  164. if(prevstart > m_subtimes[i].orgstart) m_list.SetItemData(i, TSEP);
  165. prevstart = m_subtimes[i].orgstart;
  166. SetCheck(i, false, false);
  167. }
  168. UpdatePreview();
  169. m_list.SetColumnWidth(COL_START, LVSCW_AUTOSIZE);
  170. m_list.SetColumnWidth(COL_PREVSTART, LVSCW_AUTOSIZE);
  171. }
  172. UpdateStrings();
  173. }
  174. void CPlayerSubresyncBar::SaveSubtitle()
  175. {
  176. CMainFrame* pFrame = ((CMainFrame*)AfxGetMainWnd());
  177. if(!pFrame) return;
  178. CLSID clsid;
  179. m_pSubStream->GetClassID(&clsid);
  180. if(clsid == __uuidof(CVobSubFile) && m_mode == VOBSUB)
  181. {
  182. CVobSubFile* pVSF = (CVobSubFile*)(ISubStream*)m_pSubStream;
  183. CAutoLock cAutoLock(m_pSubLock);
  184. CArray<CVobSubFile::SubPos>& sp = pVSF->m_langs[pVSF->m_iLang].subpos;
  185. for(int i = 0, j = sp.GetSize(); i < j; i++) 
  186. {
  187. sp[i].fValid = false;
  188. }
  189. for(int i = 0, j = m_sts.GetSize(); i < j; i++) 
  190. {
  191. int vobid, cellid, forced, spnum, c;
  192. if(_stscanf(m_sts.GetStr(i), _T("%d%c%d%c%d%c%d"), &vobid, &c, &cellid, &c, &forced, &c, &spnum) != 7) continue;
  193.             sp[spnum].start = m_sts[i].start;
  194. sp[spnum].stop = m_sts[i].end;
  195. sp[spnum].fValid = true;
  196. }
  197. }
  198. else if(clsid == __uuidof(CRenderedTextSubtitle) && m_mode == TEXTSUB)
  199. {
  200. CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)m_pSubStream;
  201. CAutoLock cAutoLock(m_pSubLock);
  202. pRTS->Copy(m_sts);
  203. }
  204. else 
  205. {
  206. return;
  207. }
  208. pFrame->InvalidateSubtitle();
  209. }
  210. void CPlayerSubresyncBar::UpdatePreview()
  211. {
  212. if(m_mode == VOBSUB || m_mode == TEXTSUB) 
  213. {
  214. if(0/*m_fUnlink*/)
  215. {
  216. for(int i = 0, j = m_sts.GetSize(); i < j; i++)
  217. {
  218. bool fStartMod, fEndMod, fStartAdj, fEndAdj;
  219. GetCheck(i, fStartMod, fEndMod, fStartAdj, fEndAdj);
  220. m_sts[i].start = (fStartMod||fStartAdj) ? m_subtimes[i].newstart : m_subtimes[i].orgstart;
  221. m_sts[i].end = (fEndMod||fEndAdj) ? m_subtimes[i].newend : m_subtimes[i].orgend;
  222. }
  223. }
  224. else
  225. {
  226. CArray <int, int> schk;
  227. for(int i = 0, j = m_sts.GetSize(); i < j;)
  228. {
  229. schk.RemoveAll();
  230. int start = i, end;
  231. for(end = i; end < j; end++)
  232. {
  233. int data = (int)m_list.GetItemData(end);
  234. if((data&TSEP) && end > i) break;
  235. if(data&(TSMOD|TSADJ))
  236. schk.Add(end);
  237. }
  238. if(schk.GetSize() == 0)
  239. {
  240. for(; start < end; start++) 
  241. {
  242. m_sts[start].start = m_subtimes[start].orgstart;
  243. m_sts[start].end = m_subtimes[start].orgend;
  244. }
  245. }
  246. else if(schk.GetSize() == 1)
  247. {
  248. int k = schk[0];
  249. int dt = m_subtimes[k].newstart - m_subtimes[k].orgstart;
  250. for(; start < end; start++) 
  251. {
  252. m_sts[start].start = m_subtimes[start].orgstart + dt;
  253. m_sts[start].end = (m_list.GetItemData(start)&TEMOD)
  254. ? m_subtimes[start].newend
  255. : (m_subtimes[start].orgend + dt);
  256. }
  257. }
  258. else if(schk.GetSize() >= 2)
  259. {
  260. int i0, i1, ti0, ds;
  261. double m = 0;
  262. for(int k = 0, l = schk.GetSize()-1; k < l; k++)
  263. {
  264. i0 = schk[k];
  265. i1 = schk[k+1];
  266. ti0 = m_subtimes[i0].orgstart;
  267. ds = m_subtimes[i1].orgstart - ti0;
  268. if(ds == 0)
  269. {
  270. for(; start < i1; start++)
  271. {
  272. m_sts[start].start = ti0;
  273. m_sts[start].end = (m_list.GetItemData(start)&TEMOD)
  274. ? m_subtimes[start].newend
  275. : (ti0 + m_subtimes[start].orgend - m_subtimes[start].orgstart);
  276. }
  277. }
  278. else
  279. {
  280. m = double(m_subtimes[i1].newstart - m_subtimes[i0].newstart) / ds;
  281. for(; start < i1; start++) 
  282. {
  283. m_sts[start].start = int((m_subtimes[start].orgstart - ti0)*m + m_subtimes[i0].newstart);
  284. m_sts[start].end = (m_list.GetItemData(start)&TEMOD)
  285. ? m_subtimes[start].newend
  286. : m_mode == VOBSUB
  287. ? (m_sts[start].start + m_subtimes[start].orgend - m_subtimes[start].orgstart)
  288. : (m_sts[start].start + int((m_subtimes[start].orgend - m_subtimes[start].orgstart)*m));
  289. }
  290. }
  291. }
  292. if(ds == 0)
  293. {
  294. for(; start < end; start++) 
  295. {
  296. m_sts[start].start = ti0;
  297. m_sts[start].end = (m_list.GetItemData(start)&TEMOD)
  298. ? m_subtimes[start].newend
  299. : (ti0 + (m_subtimes[start].orgend - m_subtimes[start].orgstart));
  300. }
  301. }
  302. else
  303. {
  304. for(; start < end; start++)
  305. {
  306. m_sts[start].start = int((m_subtimes[start].orgstart - ti0)*m + m_subtimes[i0].newstart);
  307. m_sts[start].end = (m_list.GetItemData(start)&TEMOD)
  308. ? m_subtimes[start].newend
  309. : m_mode == VOBSUB
  310. ? (m_sts[start].start + m_subtimes[start].orgend - m_subtimes[start].orgstart)
  311. : (m_sts[start].start + int((m_subtimes[start].orgend - m_subtimes[start].orgstart)*m));
  312. }
  313. }
  314. }
  315. i = end;
  316. }
  317. }
  318. m_sts.CreateSegments();
  319. for(int i = 0, j = m_sts.GetSize(); i < j; i++)
  320. {
  321. TCHAR buff[32];
  322. FormatTime(i, buff, 2, false);
  323. m_list.SetItemText(i, COL_PREVSTART, buff);
  324. FormatTime(i, buff, 2, true);
  325. m_list.SetItemText(i, COL_PREVEND, buff);
  326. }
  327. if(IsWindowVisible())
  328. {
  329. SaveSubtitle();
  330. }
  331. }
  332. }
  333. void CPlayerSubresyncBar::UpdateStrings()
  334. {
  335. CString str;
  336. if(m_mode == TEXTSUB)
  337. {
  338. for(int i = 0, j = m_sts.GetSize(); i < j; i++)
  339. {
  340. STSStyle stss;
  341. m_sts.GetStyle(i, stss);
  342. m_list.SetItemText(i, COL_TEXT, m_sts.GetStr(i, true));
  343. m_list.SetItemText(i, COL_STYLE, m_sts[i].style);
  344. m_list.SetItemText(i, COL_FONT, stss.fontName);
  345. str.Format(_T("%d"), stss.charSet);
  346. m_list.SetItemText(i, COL_CHARSET, str);
  347. m_list.SetItemText(i, COL_UNICODE, m_sts.IsEntryUnicode(i) ? _T("yes") : _T("no"));
  348. str.Format(_T("%d"), m_sts[i].layer);
  349. m_list.SetItemText(i, COL_LAYER, str);
  350. m_list.SetItemText(i, COL_ACTOR, m_sts[i].actor);
  351. m_list.SetItemText(i, COL_EFFECT, m_sts[i].effect);
  352. }
  353. }
  354. else if(m_mode == VOBSUB)
  355. {
  356. for(int i = 0, j = m_sts.GetSize(); i < j; i++)
  357. {
  358. int vobid, cellid, forced, c;
  359. if(_stscanf(m_sts.GetStr(i), _T("%d%c%d%c%d"), &vobid, &c, &cellid, &c, &forced) != 5) continue;
  360. if(vobid < 0) str = _T("-");
  361. else str.Format(_T("%d"), vobid);
  362. m_list.SetItemText(i, COL_VOBID, str);
  363. if(cellid < 0) str = _T("-");
  364. else str.Format(_T("%d"), cellid);
  365. m_list.SetItemText(i, COL_CELLID, str);
  366. str = forced?_T("Yes"):_T("");
  367. m_list.SetItemText(i, COL_FORCED, str);
  368. }
  369. }
  370. }
  371. void CPlayerSubresyncBar::GetCheck(int iItem, bool& fStartMod, bool& fEndMod, bool& fStartAdj, bool& fEndAdj)
  372. {
  373. if(0 <= iItem && iItem < m_sts.GetSize())
  374. {
  375.         int nCheck = (int)m_list.GetItemData(iItem);
  376. fStartMod = !!(nCheck&TSMOD);
  377. fEndMod = !!(nCheck&TEMOD);
  378. fStartAdj = !!(nCheck&TSADJ);
  379. fEndAdj = !!(nCheck&TEADJ);
  380. }
  381. }
  382. void CPlayerSubresyncBar::SetCheck(int iItem, bool fStart, bool fEnd)
  383. {
  384. if(0 <= iItem && iItem < m_sts.GetSize())
  385. {
  386. SubTime& st = m_subtimes[iItem];
  387.         int nCheck = (int)m_list.GetItemData(iItem) & TSEP;
  388. if(fStart) nCheck |= TSMOD;
  389. else if(abs(st.orgstart-st.newstart)) nCheck |= TSADJ;
  390. if(fEnd) nCheck |= TEMOD;
  391. else if(abs(st.orgend-st.newend)) nCheck |= TEADJ;
  392. m_list.SetItemData(iItem, (DWORD)nCheck);
  393. TCHAR buff[32];
  394. FormatTime(iItem, buff, fStart, false);
  395. m_list.SetItemText(iItem, COL_START, buff);
  396. FormatTime(iItem, buff, fEnd, true);
  397. m_list.SetItemText(iItem, COL_END, buff);
  398. }
  399. }
  400. bool CPlayerSubresyncBar::ModStart(int iItem, int t, bool fReset)
  401. {
  402. bool fRet = false;
  403. bool fStartMod, fEndMod, fStartAdj, fEndAdj;
  404. GetCheck(iItem, fStartMod, fEndMod, fStartAdj, fEndAdj);
  405. SubTime& st = m_subtimes[iItem];
  406. // if(fStartMod || fStartAdj || st.orgstart != t || fReset)
  407. {
  408. fRet = (st.newstart != t);
  409. st.newstart = t;
  410. if(!fEndMod) st.newend = st.newstart + (st.orgend - st.orgstart);
  411. else if(fReset) st.newstart = st.newend - (st.orgend - st.orgstart);
  412. SetCheck(iItem, !fReset, fEndMod);
  413. }
  414. return(fRet);
  415. }
  416. bool CPlayerSubresyncBar::ModEnd(int iItem, int t, bool fReset)
  417. {
  418. bool fRet = false;
  419. bool fStartMod, fEndMod, fStartAdj, fEndAdj;
  420. GetCheck(iItem, fStartMod, fEndMod, fStartAdj, fEndAdj);
  421. SubTime& st = m_subtimes[iItem];
  422. // if(fEndMod || fEndAdj || st.orgend != t || fReset)
  423. {
  424. fRet = (st.newend != t);
  425. st.newend = t;
  426. if(!fStartMod) st.newstart = st.newend - (st.orgend - st.orgstart);
  427. else if(fReset) st.newend = st.newstart + (st.orgend - st.orgstart);
  428. SetCheck(iItem, fStartMod, !fReset);
  429. }
  430. return(fRet);
  431. }
  432. void CPlayerSubresyncBar::FormatTime(int iItem, TCHAR* buff, int time, bool fEnd)
  433. {
  434. int t = !fEnd 
  435. ?(time == 2 ? m_sts[iItem].start
  436. : time == 1 ? m_subtimes[iItem].newstart 
  437. : m_subtimes[iItem].orgstart)
  438. : (time == 2 ? m_sts[iItem].end
  439. : time == 1 ? m_subtimes[iItem].newend
  440. : m_subtimes[iItem].orgend);
  441. _stprintf(buff, t >= 0 
  442. ? _T("%02d:%02d:%02d.%03d") 
  443. : _T("-%02d:%02d:%02d.%03d"), 
  444. abs(t)/60/60/1000, 
  445. (abs(t)/60/1000)%60, 
  446. (abs(t)/1000)%60, 
  447. abs(t)%1000);
  448. }
  449. BEGIN_MESSAGE_MAP(CPlayerSubresyncBar, CSizingControlBarG)
  450. ON_WM_SIZE()
  451. ON_NOTIFY(LVN_BEGINLABELEDIT, IDC_SUBRESYNCLIST, OnBeginlabeleditList)
  452. ON_NOTIFY(LVN_DOLABELEDIT, IDC_SUBRESYNCLIST, OnDolabeleditList)
  453. ON_NOTIFY(LVN_ENDLABELEDIT, IDC_SUBRESYNCLIST, OnEndlabeleditList)
  454. ON_NOTIFY(NM_RCLICK, IDC_SUBRESYNCLIST, OnRclickList)
  455. ON_NOTIFY(NM_DBLCLK, IDC_SUBRESYNCLIST, OnNMDblclkList)
  456. ON_NOTIFY(LVN_KEYDOWN, IDC_SUBRESYNCLIST, OnLvnKeydownList)
  457. ON_NOTIFY(NM_CUSTOMDRAW, IDC_SUBRESYNCLIST, OnCustomdrawList)
  458. END_MESSAGE_MAP()
  459. // CPlayerSubresyncBar message handlers
  460. void CPlayerSubresyncBar::OnSize(UINT nType, int cx, int cy)
  461. {
  462. CSizingControlBarG::OnSize(nType, cx, cy);
  463. if(::IsWindow(m_list.m_hWnd))
  464. {
  465. CRect r;
  466. GetClientRect(r);
  467. r.DeflateRect(2, 2);
  468. m_list.MoveWindow(r);
  469. }
  470. }
  471. static bool ParseTime(CString str, int& ret, bool fWarn = true)
  472. {
  473. int sign = 1, h, m, s, ms;
  474. TCHAR c;
  475. str.Trim();
  476. if(str.GetLength() > 0 && str[0] == '-') sign = -1;
  477. int n = _stscanf(str, _T("%d%c%d%c%d%c%d"), &h, &c, &m, &c, &s, &c, &ms);
  478. h = abs(h);
  479. if(n == 7
  480. && 0 <= h && h < 24 
  481. && 0 <= m && m < 60 
  482. && 0 <= s && s < 60 
  483. && 0 <= ms && ms < 1000)
  484. {
  485. ret = sign*(h*60*60*1000+m*60*1000+s*1000+ms);
  486. return(true);
  487. }
  488. if(fWarn) AfxMessageBox(_T("The correct time format is [-]hh:mm:ss.msn(e.g. 01:23:45.678)"));
  489. return(false);
  490. }
  491. void CPlayerSubresyncBar::OnBeginlabeleditList(NMHDR* pNMHDR, LRESULT* pResult) 
  492. {
  493. LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
  494. LV_ITEM* pItem = &pDispInfo->item;
  495. *pResult = FALSE;
  496. if(pItem->iItem >= 0)
  497. {
  498. if((pItem->iSubItem == COL_START || pItem->iSubItem == COL_END || pItem->iSubItem == COL_TEXT
  499. || pItem->iSubItem == COL_STYLE || pItem->iSubItem == COL_LAYER
  500. || pItem->iSubItem == COL_ACTOR || pItem->iSubItem == COL_EFFECT) 
  501. && m_mode == TEXTSUB)
  502. {
  503. *pResult = TRUE;
  504. }
  505. else if((pItem->iSubItem == COL_START) 
  506. && m_mode == VOBSUB)
  507. {
  508. *pResult = TRUE;
  509. }
  510. }
  511. }
  512. void CPlayerSubresyncBar::OnDolabeleditList(NMHDR* pNMHDR, LRESULT* pResult) 
  513. {
  514. LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
  515. LV_ITEM* pItem = &pDispInfo->item;
  516. *pResult = FALSE;
  517. if(pItem->iItem >= 0)
  518. {
  519. if((pItem->iSubItem == COL_START || pItem->iSubItem == COL_END || pItem->iSubItem == COL_TEXT
  520. || pItem->iSubItem == COL_STYLE || pItem->iSubItem == COL_LAYER
  521. || pItem->iSubItem == COL_ACTOR || pItem->iSubItem == COL_EFFECT)
  522. && m_mode == TEXTSUB)
  523. {
  524. m_list.ShowInPlaceEdit(pItem->iItem, pItem->iSubItem);
  525. *pResult = TRUE;
  526. }
  527. else if((pItem->iSubItem == COL_START)
  528. && m_mode == VOBSUB)
  529. {
  530. m_list.ShowInPlaceEdit(pItem->iItem, pItem->iSubItem);
  531. *pResult = TRUE;
  532. }
  533. }
  534. }
  535. void CPlayerSubresyncBar::OnEndlabeleditList(NMHDR* pNMHDR, LRESULT* pResult) 
  536. {
  537. LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
  538. LV_ITEM* pItem = &pDispInfo->item;
  539. *pResult = FALSE;
  540. if(!m_list.m_fInPlaceDirty)
  541. return;
  542. bool fNeedsUpdate = false;
  543. if(pItem->iItem >= 0 && pItem->pszText && (m_mode == VOBSUB || m_mode == TEXTSUB))
  544. {
  545. if(pItem->iSubItem == COL_START)
  546. {
  547. int t;
  548. if(ParseTime(pItem->pszText, t))
  549. {
  550. fNeedsUpdate = ModStart(pItem->iItem, t);
  551. *pResult = TRUE;
  552. }
  553. }
  554. else if(pItem->iSubItem == COL_END && m_mode == TEXTSUB)
  555. {
  556. int t;
  557. if(ParseTime(pItem->pszText, t))
  558. {
  559. fNeedsUpdate = ModEnd(pItem->iItem, t);
  560. *pResult = TRUE;
  561. }
  562. }
  563. else if(pItem->iSubItem == COL_TEXT && m_mode == TEXTSUB)
  564. {
  565. CString str = m_sts.GetStr(pItem->iItem, true);
  566. if(str != pItem->pszText) 
  567. {
  568. fNeedsUpdate = true;
  569. m_sts.SetStr(pItem->iItem, CString(pItem->pszText), true);
  570. m_list.SetItemText(pItem->iItem, pItem->iSubItem, m_sts.GetStr(pItem->iItem, true));
  571. }
  572. }
  573. else if(pItem->iSubItem == COL_STYLE && m_mode == TEXTSUB)
  574. {
  575. CString str(pItem->pszText);
  576. str.Trim();
  577. if(!str.IsEmpty() && m_sts[pItem->iItem].style != str) 
  578. {
  579. fNeedsUpdate = true;
  580. void* val;
  581. if(!m_sts.m_styles.Lookup(str, val))
  582. m_sts.AddStyle(str, new STSStyle());
  583. m_sts[pItem->iItem].style = str;
  584. m_list.SetItemText(pItem->iItem, pItem->iSubItem, pItem->pszText);
  585. }
  586. }
  587. else if(pItem->iSubItem == COL_LAYER && m_mode == TEXTSUB)
  588. {
  589. int l;
  590. if(_stscanf(pItem->pszText, _T("%d"), &l) == 1)
  591. {
  592. fNeedsUpdate = true;
  593. m_sts[pItem->iItem].layer = l;
  594. CString str;
  595. str.Format(_T("%d"), l);
  596. m_list.SetItemText(pItem->iItem, pItem->iSubItem, str);
  597. }
  598. }
  599. else if(pItem->iSubItem == COL_ACTOR && m_mode == TEXTSUB)
  600. {
  601. CString str(pItem->pszText);
  602. str.Trim();
  603. if(!str.IsEmpty())
  604. {
  605. fNeedsUpdate = true;
  606. m_sts[pItem->iItem].actor = str;
  607. m_list.SetItemText(pItem->iItem, pItem->iSubItem, str);
  608. }
  609. }
  610. else if(pItem->iSubItem == COL_EFFECT && m_mode == TEXTSUB)
  611. {
  612. CString str(pItem->pszText);
  613. str.Trim();
  614. if(!str.IsEmpty())
  615. {
  616. fNeedsUpdate = true;
  617. m_sts[pItem->iItem].effect = str;
  618. m_list.SetItemText(pItem->iItem, pItem->iSubItem, str);
  619. }
  620. }
  621. }
  622. if(fNeedsUpdate)
  623. {
  624. UpdatePreview();
  625. }
  626. }
  627. static int uintcomp(const void* i1, const void* i2)
  628. {
  629. return(*((UINT*)i2) - *((UINT*)i1));
  630. }
  631. void CPlayerSubresyncBar::OnRclickList(NMHDR* pNMHDR, LRESULT* pResult) 
  632. {
  633. LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)pNMHDR;
  634. if(lpnmlv->iItem >= 0 && lpnmlv->iSubItem >= 0)
  635. {
  636. enum 
  637. {
  638. TOGSEP=1, 
  639. DUPITEM, DELITEM, 
  640. RESETS, SETOS, SETCS, RESETE, SETOE, SETCE,
  641. STYLEFIRST, STYLELAST=STYLEFIRST+1000, STYLEEDIT,
  642. UNICODEYES, UNICODENO,
  643. LAYERDEC, LAYERINC,
  644. ACTORFIRST, ACTORLAST=ACTORFIRST+1000,
  645. EFFECTFIRST, EFFECTLAST=EFFECTFIRST+1000
  646. };
  647. CStringArray styles;
  648. CStringArray actors;
  649. CStringArray effects;
  650. CMenu m;
  651. m.CreatePopupMenu();
  652. if(m_mode == VOBSUB || m_mode == TEXTSUB)
  653. {
  654. m.AppendMenu(MF_STRING|MF_ENABLED, TOGSEP, ResStr(IDS_SUBRESYNC_SEPARATOR));
  655. m.AppendMenu(MF_SEPARATOR);
  656. if(m_mode == TEXTSUB) m.AppendMenu(MF_STRING|MF_ENABLED, DUPITEM, ResStr(IDS_SUBRESYNC_DUPLICATE));
  657. m.AppendMenu(MF_STRING|MF_ENABLED, DELITEM, ResStr(IDS_SUBRESYNC_DELETE));
  658. }
  659. if(lpnmlv->iSubItem == COL_START && (m_mode == VOBSUB || m_mode == TEXTSUB))
  660. {
  661. m.AppendMenu(MF_SEPARATOR);
  662. m.AppendMenu(MF_STRING|MF_ENABLED, RESETS, ResStr(IDS_SUBRESYNC_RESET));
  663. m.AppendMenu(MF_STRING|MF_ENABLED, SETOS, ResStr(IDS_SUBRESYNC_ORIGINAL));
  664. m.AppendMenu(MF_STRING|MF_ENABLED, SETCS, ResStr(IDS_SUBRESYNC_CURRENT));
  665. }
  666. else if(lpnmlv->iSubItem == COL_END && m_mode == TEXTSUB)
  667. {
  668. m.AppendMenu(MF_SEPARATOR);
  669. m.AppendMenu(MF_STRING|MF_ENABLED, RESETE, ResStr(IDS_SUBRESYNC_RESET));
  670. m.AppendMenu(MF_STRING|MF_ENABLED, SETOE, ResStr(IDS_SUBRESYNC_ORIGINAL));
  671. m.AppendMenu(MF_STRING|MF_ENABLED, SETCE, ResStr(IDS_SUBRESYNC_CURRENT));
  672. }
  673. else if(lpnmlv->iSubItem == COL_STYLE && m_mode == TEXTSUB)
  674. {
  675. m.AppendMenu(MF_SEPARATOR);
  676. int id = STYLEFIRST;
  677. POSITION pos = m_sts.m_styles.GetStartPosition();
  678. while(pos && id <= STYLELAST)
  679. {
  680. CString key;
  681. void* val;
  682. m_sts.m_styles.GetNextAssoc(pos, key, val);
  683. styles.Add(key);
  684. m.AppendMenu(MF_STRING|MF_ENABLED, id++, key);
  685. }
  686. if(id > STYLEFIRST && m_list.GetSelectedCount() == 1)
  687. {
  688. m.AppendMenu(MF_SEPARATOR);
  689. m.AppendMenu(MF_STRING|MF_ENABLED, STYLEEDIT, ResStr(IDS_SUBRESYNC_EDIT));
  690. }
  691. }
  692. else if(lpnmlv->iSubItem == COL_UNICODE && m_mode == TEXTSUB)
  693. {
  694. m.AppendMenu(MF_SEPARATOR);
  695. m.AppendMenu(MF_STRING|MF_ENABLED, UNICODEYES, ResStr(IDS_SUBRESYNC_YES));
  696. m.AppendMenu(MF_STRING|MF_ENABLED, UNICODENO, ResStr(IDS_SUBRESYNC_NO));
  697. }
  698.   else if(lpnmlv->iSubItem == COL_LAYER && m_mode == TEXTSUB)
  699. {
  700. m.AppendMenu(MF_SEPARATOR);
  701. m.AppendMenu(MF_STRING|MF_ENABLED, LAYERDEC, ResStr(IDS_SUBRESYNC_DECREASE));
  702. m.AppendMenu(MF_STRING|MF_ENABLED, LAYERINC, ResStr(IDS_SUBRESYNC_INCREASE));
  703. }
  704. else if(lpnmlv->iSubItem == COL_ACTOR && m_mode == TEXTSUB)
  705. {
  706. CMapStringToPtr actormap;
  707. for(int i = 0, j = m_sts.GetSize(); i < j; i++)
  708. actormap[m_sts[i].actor] = NULL;
  709. actormap.RemoveKey(_T(""));
  710. if(actormap.GetCount() > 0)
  711. {
  712. m.AppendMenu(MF_SEPARATOR);
  713. int id = ACTORFIRST;
  714. POSITION pos = actormap.GetStartPosition();
  715. while(pos && id <= ACTORLAST)
  716. {
  717. CString key;
  718. void* val;
  719. actormap.GetNextAssoc(pos, key, val);
  720. actors.Add(key);
  721. m.AppendMenu(MF_STRING|MF_ENABLED, id++, key);
  722. }
  723. }
  724. }
  725. else if(lpnmlv->iSubItem == COL_EFFECT && m_mode == TEXTSUB)
  726. {
  727. CMapStringToPtr effectmap;
  728. for(int i = 0, j = m_sts.GetSize(); i < j; i++)
  729. effectmap[m_sts[i].effect] = NULL;
  730. effectmap.RemoveKey(_T(""));
  731. if(effectmap.GetCount() > 0)
  732. {
  733. m.AppendMenu(MF_SEPARATOR);
  734. int id = EFFECTFIRST;
  735. POSITION pos = effectmap.GetStartPosition();
  736. while(pos && id <= EFFECTLAST)
  737. {
  738. CString key;
  739. void* val;
  740. effectmap.GetNextAssoc(pos, key, val);
  741. effects.Add(key);
  742. m.AppendMenu(MF_STRING|MF_ENABLED, id++, key);
  743. }
  744. }
  745. }
  746. CPoint p = lpnmlv->ptAction;
  747. ::MapWindowPoints(pNMHDR->hwndFrom, HWND_DESKTOP, &p, 1);
  748. UINT id = m.TrackPopupMenu(TPM_LEFTBUTTON|TPM_RETURNCMD, p.x, p.y, this);
  749. bool fNeedsUpdate = false;
  750. POSITION pos = m_list.GetFirstSelectedItemPosition();
  751. while(pos)
  752. {
  753. int iItem = m_list.GetNextSelectedItem(pos);
  754. SubTime& st = m_subtimes[iItem];
  755. switch(id)
  756. {
  757. case TOGSEP: 
  758. m_list.SetItemData(iItem, m_list.GetItemData(iItem)^TSEP); 
  759. m_list.Invalidate(); 
  760. fNeedsUpdate = true; 
  761. break;
  762. case DUPITEM:
  763. {
  764. CUIntArray items;
  765. pos = m_list.GetFirstSelectedItemPosition();
  766. while(pos) items.Add(m_list.GetNextSelectedItem(pos));
  767. qsort(items.GetData(), items.GetSize(), sizeof(UINT), uintcomp);
  768. for(int i = 0; i < items.GetSize(); i++)
  769. {
  770. iItem = items[i];
  771. STSEntry stse = m_sts[iItem];
  772. m_sts.InsertAt(iItem+1, stse);
  773. SubTime st = m_subtimes[iItem];
  774. m_subtimes.InsertAt(iItem+1, st);
  775. CHeaderCtrl* pHeader = (CHeaderCtrl*)m_list.GetDlgItem(0);
  776. int nColumnCount = pHeader->GetItemCount();
  777. CStringArray sa;
  778. sa.SetSize(nColumnCount);
  779. for(int col = 0; col < nColumnCount; col++)
  780. sa[col] = m_list.GetItemText(iItem, col);
  781. DWORD data = m_list.GetItemData(iItem);
  782. m_list.InsertItem(iItem+1, sa[0]);
  783. m_list.SetItemData(iItem+1, data);
  784. for(int col = 1; col < nColumnCount; col++)
  785. m_list.SetItemText(iItem+1, col, sa[col]);
  786. }
  787. }
  788. fNeedsUpdate = true; 
  789. break;
  790. case DELITEM:
  791. {
  792. CUIntArray items;
  793. pos = m_list.GetFirstSelectedItemPosition();
  794. while(pos) items.Add(m_list.GetNextSelectedItem(pos));
  795. qsort(items.GetData(), items.GetSize(), sizeof(UINT), uintcomp);
  796. for(int i = 0; i < items.GetSize(); i++)
  797. {
  798. iItem = items[i];
  799. m_sts.RemoveAt(iItem);
  800. m_subtimes.RemoveAt(iItem);
  801. m_list.DeleteItem(iItem);
  802. }
  803. iItem = items[items.GetSize()-1];
  804. if(iItem >= m_list.GetItemCount()) iItem = m_list.GetItemCount()-1;
  805. m_list.SetSelectionMark(iItem);
  806. }
  807. fNeedsUpdate = true; 
  808. break;
  809. case RESETS: /*if(*/ModStart(iItem, st.orgstart, true);/*)*/ fNeedsUpdate = true; break;
  810. case SETOS: /*if(*/ModStart(iItem, st.orgstart);/*)*/ fNeedsUpdate = true; break;
  811. case SETCS: /*if(*/ModStart(iItem, (int)(m_rt/10000));/*)*/ fNeedsUpdate = true; break;
  812. case RESETE: /*if(*/ModEnd(iItem, st.orgend, true);/*)*/ fNeedsUpdate = true; break;
  813. case SETOE: /*if(*/ModEnd(iItem, st.orgend);/*)*/ fNeedsUpdate = true; break;
  814. case SETCE: /*if(*/ModEnd(iItem, (int)(m_rt/10000));/*)*/ fNeedsUpdate = true; break;
  815. default: 
  816. if(STYLEFIRST <= id && id <= STYLELAST)
  817. {
  818. CString s = styles[id - STYLEFIRST];
  819. if(m_sts[iItem].style != s) fNeedsUpdate = true;
  820. m_sts[iItem].style = s;
  821. m_list.SetItemText(iItem, lpnmlv->iSubItem, s);
  822. }
  823. else if(id == STYLEEDIT)
  824. {
  825. CAutoPtrArray<CPPageSubStyle> pages;
  826. CArray<STSStyle*> styles;
  827. STSStyle* stss = m_sts.GetStyle(iItem);
  828. int iSelPage = 0;
  829. POSITION pos = m_sts.m_styles.GetStartPosition();
  830. for(int i = 0; pos; i++)
  831. {
  832. CString key;
  833. void* val;
  834. m_sts.m_styles.GetNextAssoc(pos, key, val);
  835. CAutoPtr<CPPageSubStyle> page(new CPPageSubStyle());
  836. page->InitStyle(key, *(STSStyle*)val);
  837. pages.Add(page);
  838. styles.Add((STSStyle*)val);
  839. if(stss == (STSStyle*)val) 
  840. iSelPage = i;
  841. }
  842. CPropertySheet dlg(_T("Styles..."), this, iSelPage);
  843. for(int i = 0; i < (int)pages.GetCount(); i++) dlg.AddPage(pages[i]);
  844. if(dlg.DoModal() == IDOK)
  845. {
  846. for(int j = 0; j < (int)pages.GetCount(); j++)
  847. {
  848. stss = styles[j];
  849. pages[j]->GetStyle(*stss);
  850. for(int i = 0; i < m_sts.GetSize(); i++)
  851. {
  852. if(m_sts.GetStyle(i) == stss)
  853. {
  854. CString str;
  855. m_list.SetItemText(i, COL_TEXT, m_sts.GetStr(i, true));
  856. m_list.SetItemText(i, COL_FONT, stss->fontName);
  857. str.Format(_T("%d"), stss->charSet);
  858. m_list.SetItemText(i, COL_CHARSET, str);
  859. str.Format(_T("%d"), m_sts[i].layer);
  860. }
  861. }
  862. }
  863. fNeedsUpdate = true;
  864. }
  865. }
  866. else if(id == UNICODEYES || id == UNICODENO)
  867. {
  868. m_sts.ConvertUnicode(iItem, id == UNICODEYES);
  869. m_list.SetItemText(iItem, COL_TEXT, m_sts.GetStr(iItem, true));
  870. m_list.SetItemText(iItem, COL_UNICODE, m_sts.IsEntryUnicode(iItem) ? _T("yes") : _T("no"));
  871. fNeedsUpdate = true;
  872. }
  873. else if(id == LAYERDEC || id == LAYERINC)
  874. {
  875. int d = (id == LAYERDEC) ? -1 : (id == LAYERINC) ? +1 : 0;
  876. if(d != 0) fNeedsUpdate = true;
  877. m_sts[iItem].layer += d;
  878. CString s;
  879. s.Format(_T("%d"), m_sts[iItem].layer);
  880. m_list.SetItemText(iItem, lpnmlv->iSubItem, s);
  881. }
  882. else if(ACTORFIRST <= id && id <= ACTORLAST)
  883. {
  884. CString s = actors[id - ACTORFIRST];
  885. if(m_sts[iItem].actor != s) fNeedsUpdate = true;
  886. m_sts[iItem].actor = s;
  887. m_list.SetItemText(iItem, lpnmlv->iSubItem, s);
  888. }
  889. else if(EFFECTFIRST <= id && id <= EFFECTLAST)
  890. {
  891. CString s = effects[id - EFFECTFIRST];
  892. if(m_sts[iItem].effect != s) fNeedsUpdate = true;
  893. m_sts[iItem].effect = s;
  894. m_list.SetItemText(iItem, lpnmlv->iSubItem, s);
  895. }
  896. break;
  897. }
  898. }
  899. if(fNeedsUpdate) 
  900. {
  901. UpdatePreview();
  902. }
  903. }
  904. *pResult = 0;
  905. }
  906. void CPlayerSubresyncBar::OnNMDblclkList(NMHDR* pNMHDR, LRESULT* pResult)
  907. {
  908. LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)pNMHDR;
  909. if(lpnmlv->iItem >= 0 && lpnmlv->iSubItem >= 0 && (m_mode == VOBSUB || m_mode == TEXTSUB))
  910. {
  911. if(CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd())
  912. {
  913. int t = 0;
  914. if(!ParseTime(m_list.GetItemText(lpnmlv->iItem, lpnmlv->iSubItem), t, false))
  915. t = m_sts[lpnmlv->iItem].start;
  916. REFERENCE_TIME rt = 
  917. lpnmlv->iSubItem == COL_START ? ((REFERENCE_TIME)t*10000) : 
  918. lpnmlv->iSubItem == COL_END ? ((REFERENCE_TIME)t*10000) : 
  919. lpnmlv->iSubItem == COL_PREVSTART ? ((REFERENCE_TIME)t*10000) : 
  920. lpnmlv->iSubItem == COL_PREVEND ? ((REFERENCE_TIME)t*10000) : 
  921. ((REFERENCE_TIME)t*10000);
  922. pFrame->SeekTo(rt);
  923. }
  924. }
  925. *pResult = 0;
  926. }
  927. void CPlayerSubresyncBar::OnLvnKeydownList(NMHDR* pNMHDR, LRESULT* pResult)
  928. {
  929. LPNMLVKEYDOWN pLVKeyDown = reinterpret_cast<LPNMLVKEYDOWN>(pNMHDR);
  930. *pResult = 0;
  931. }
  932. static CUIntArray m_itemGroups;
  933. static int m_totalGroups;
  934. void CPlayerSubresyncBar::OnCustomdrawList(NMHDR* pNMHDR, LRESULT* pResult)
  935. {
  936. NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>(pNMHDR);
  937. *pResult = CDRF_DODEFAULT;
  938. if(CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage)
  939. {
  940. m_itemGroups.SetSize(m_list.GetItemCount());
  941. m_totalGroups = 0;
  942. for(int i = 0, j = m_list.GetItemCount(); i < j; i++)
  943. {
  944. if(m_list.GetItemData(i)&TSEP) m_totalGroups++;
  945. m_itemGroups[i] = m_totalGroups;
  946. }
  947. *pResult = CDRF_NOTIFYPOSTPAINT|CDRF_NOTIFYITEMDRAW;
  948. }
  949. else if(CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage)
  950. {
  951. pLVCD->nmcd.uItemState &= ~CDIS_FOCUS;
  952. *pResult = CDRF_NOTIFYPOSTPAINT|CDRF_NOTIFYSUBITEMDRAW;
  953. }
  954. else if((CDDS_ITEMPREPAINT|CDDS_SUBITEM) == pLVCD->nmcd.dwDrawStage)
  955. {
  956. COLORREF clrText;
  957. COLORREF clrTextBk;
  958. if((pLVCD->iSubItem == COL_START || pLVCD->iSubItem == COL_END || pLVCD->iSubItem == COL_TEXT || pLVCD->iSubItem == COL_STYLE
  959. || pLVCD->iSubItem == COL_LAYER || pLVCD->iSubItem == COL_ACTOR || pLVCD->iSubItem == COL_EFFECT)
  960. && m_mode == TEXTSUB)
  961. {
  962. clrText = 0;
  963. }
  964. else if((pLVCD->iSubItem == COL_START)
  965. && m_mode == VOBSUB)
  966. {
  967. clrText = 0;
  968. }
  969. else
  970. {
  971. clrText = 0x606060;
  972. }
  973. clrTextBk = 0xffffff;
  974. // if(m_totalGroups > 0)
  975. clrTextBk -= ((m_itemGroups[pLVCD->nmcd.dwItemSpec]&1) ? 0x100010 : 0x200020);
  976. if(m_sts[pLVCD->nmcd.dwItemSpec].start <= m_rt/10000 && m_rt/10000 < m_sts[pLVCD->nmcd.dwItemSpec].end)
  977. {
  978. clrText |= 0xFF;
  979. }
  980. int nCheck = (int)m_list.GetItemData(pLVCD->nmcd.dwItemSpec);
  981. if((nCheck&1) && (pLVCD->iSubItem == COL_START || pLVCD->iSubItem == COL_PREVSTART))
  982. {
  983. clrTextBk = 0xffddbb;
  984. }
  985. else if((nCheck&4) && (/*pLVCD->iSubItem == COL_START ||*/ pLVCD->iSubItem == COL_PREVSTART))
  986. {
  987. clrTextBk = 0xffeedd;
  988. }
  989. if((nCheck&2) && (pLVCD->iSubItem == COL_END || pLVCD->iSubItem == COL_PREVEND))
  990. {
  991. clrTextBk = 0xffddbb;
  992. }
  993. else if((nCheck&8) && (/*pLVCD->iSubItem == COL_END ||*/ pLVCD->iSubItem == COL_PREVEND))
  994. {
  995. clrTextBk = 0xffeedd;
  996. }
  997. pLVCD->clrText = clrText;
  998. pLVCD->clrTextBk = clrTextBk;
  999. *pResult = CDRF_NOTIFYPOSTPAINT;
  1000. }
  1001. else if((CDDS_ITEMPOSTPAINT|CDDS_SUBITEM) == pLVCD->nmcd.dwDrawStage)
  1002. {
  1003. // *pResult = CDRF_DODEFAULT;
  1004. }
  1005. else if(CDDS_ITEMPOSTPAINT == pLVCD->nmcd.dwDrawStage)
  1006. {
  1007.         int nItem = static_cast<int>(pLVCD->nmcd.dwItemSpec);
  1008. LVITEM rItem;
  1009.         ZeroMemory(&rItem, sizeof(LVITEM));
  1010.         rItem.mask  = LVIF_IMAGE | LVIF_STATE;
  1011.         rItem.iItem = nItem;
  1012.         rItem.stateMask = LVIS_SELECTED;
  1013.         m_list.GetItem(&rItem);
  1014. {
  1015.             CDC* pDC = CDC::FromHandle(pLVCD->nmcd.hdc);
  1016. CRect rcItem;
  1017.             m_list.GetItemRect(nItem, &rcItem, LVIR_BOUNDS);
  1018. {
  1019. bool fSeparator = nItem < m_list.GetItemCount()-1 && (m_list.GetItemData(nItem+1)&TSEP);
  1020. CPen p(PS_INSIDEFRAME, 1, fSeparator ? 0x404040 : 0xe0e0e0);
  1021. CPen* old = pDC->SelectObject(&p);
  1022. pDC->MoveTo(CPoint(rcItem.left, rcItem.bottom-1));
  1023. pDC->LineTo(CPoint(rcItem.right, rcItem.bottom-1));
  1024. pDC->SelectObject(old);
  1025. }
  1026. {
  1027. CPen p(PS_INSIDEFRAME, 1, 0xe0e0e0);
  1028. CPen* old = pDC->SelectObject(&p);
  1029. CHeaderCtrl* pHeader = (CHeaderCtrl*)m_list.GetDlgItem(0);
  1030. int nColumnCount = pHeader->GetItemCount();
  1031. // Get the column offset
  1032. int offset = rcItem.left;
  1033. for(int i = 0; i < nColumnCount; i++)
  1034. {
  1035. offset += m_list.GetColumnWidth(i);
  1036. pDC->MoveTo(CPoint(offset, rcItem.top));
  1037. pDC->LineTo(CPoint(offset, rcItem.bottom));
  1038. }
  1039. pDC->SelectObject(old);
  1040. }
  1041.             *pResult = CDRF_SKIPDEFAULT;
  1042.         }
  1043. }
  1044. else if(CDDS_POSTPAINT == pLVCD->nmcd.dwDrawStage)
  1045. {
  1046. }
  1047. }