void ImageViewDialog::SelectCash(int index) {
  cashIndex_ = index;

  if (monitor_ != NULL && cashIndex_ != -1) {
    int cashCount = monitor_->Freeze();
    if (cashIndex_ < cashCount) {
      Cash *cash = monitor_->GetCash(cashIndex_);        
      // draw image.
      Bitmap *topImage = cash->GetTopImage();          
      Bitmap *bottomImage = cash->GetBottomImage();
      CString title;
      title.Format(IDS_VIEW_CASH_IMAGE, CA2T(cash->GetSN()));
      labelTitle_.SetWindowText(title);
      ASSERT(topImage != NULL && bottomImage != NULL);
      topImage_ = *topImage;
      bottomImage_ = *bottomImage;
    }
    monitor_->Unfreeze();
  }
  
  Invalidate();
}
BOOL ImageViewDialog::PreTranslateMessage(MSG* pMsg) {
  if (pMsg->message == WM_KEYDOWN) {
    UINT key = pMsg->wParam;
    if (key == VK_DOWN || key == VK_UP || key == VK_LEFT || key == VK_RIGHT || key == VK_NEXT || key == VK_PRIOR || key == VK_SPACE) {
      if (monitor_ != NULL && cashIndex_ != -1) {
        int cashCount = monitor_->Freeze();
        int cashIndex = cashIndex_;
        if (key == VK_DOWN || key == VK_RIGHT || key == VK_NEXT || key == VK_SPACE) {
          cashIndex++;
        } else if (key == VK_UP || key == VK_LEFT || key == VK_PRIOR) {
          cashIndex--;
        }
        if (cashIndex < 0) {
          cashIndex = 0;
        }
        if (cashIndex >= cashCount) {
          cashIndex = cashCount - 1;
        }
        if (cashIndex != cashIndex_) {
          cashIndex_ = cashIndex;
          Cash *cash = monitor_->GetCash(cashIndex_);        
          // draw image.
          Bitmap *topImage = cash->GetTopImage();          
          Bitmap *bottomImage = cash->GetBottomImage();
          CString title;
          title.Format(IDS_VIEW_CASH_IMAGE, CA2T(cash->GetSN()));
          labelTitle_.SetWindowText(title);
          ASSERT(topImage != NULL && bottomImage != NULL);
          topImage_ = *topImage;
          bottomImage_ = *bottomImage;
          Invalidate();
        }
        monitor_->Unfreeze();
      }
    }
  }

  return CDialog::PreTranslateMessage(pMsg);
}
void CashListView::OnRButtonDown(UINT nFlags, CPoint point)
{
	// TODO:  在此添加消息处理程序代码和/或调用默认值
	SetFocus();

	CRect clientRect;
	GetClientRect(&clientRect);
	clientRect.top += itemHeight_;
	int index = (point.y - clientRect.top) / itemHeight_ + topItem_;

	if (index >= 0 && index < itemCount_) 
	{
		EnsureItemVisiable(index);
		SelectItemAndNotify(index);
		UpdateWindow();

		if (monitor_ != NULL)
		{
			CMenu menu;
			menu.LoadMenu(IDR_POPUP_SAVE_WAVE);
			CMenu *contextMenu = menu.GetSubMenu(0);
			ClientToScreen(&point);
			int choice = contextMenu->TrackPopupMenu(TPM_RETURNCMD, point.x, point.y, this);
			if (choice == ID_SAVE_WAVE)
			{
				BROWSEINFO bi;// 选择路径的对话框
				bi.hwndOwner = NULL;// 父窗体句柄
				bi.pidlRoot = NULL;// LPCITEMIDLIST (ITEMIDLIST结构的地址),保存初始根目录(若为NUll则默认为桌面目录,并初始位置在我的电脑)
				bi.pszDisplayName = NULL;// 保存用户选中的目录的字符串的内存地址,大小默认为MAX_PATH(260)
				bi.lpszTitle = _T("请选择用于保存的文件夹");// 对话框的标题
				bi.ulFlags = 0;
				bi.lpfn = BrowseCallbackProc;
				bi.iImage = 0;
				LPCITEMIDLIST pidl = SHBrowseForFolder(&bi);//调用显示选择对话框 
												//注意下 这个函数会分配内存 但不会释放 需要手动释放
				if (pidl)
				{
					TCHAR folderName[MAX_PATH];
					SHGetPathFromIDList(pidl, folderName);//将文件夹路径放到folderName中
					AfxGetApp()->WriteProfileString(_T("Recently"), _T("WaveSavePath"), folderName);

					int count = monitor_->Freeze();
					Cash *cash = monitor_->GetCash(index);
					if (cash->Valid(Cash::VALID_ADC))
					{
						if (LocalFileSaver::GetInstance()->SaveADCData(cash, folderName))
						{
							AfxMessageBox(IDS_PROMPT_SAVE_WAVE_SUCCESS, MB_ICONINFORMATION | MB_OK);
						}
						else
						{
							AfxMessageBox(IDS_PROMPT_SAVE_WAVE_FAILED, MB_ICONINFORMATION | MB_OK);
						}
					}
					else
					{
						AfxMessageBox(IDS_PROMPT_INVALID_WAVE, MB_ICONWARNING | MB_OK);
					}
					monitor_->Unfreeze();
				}

				CoTaskMemFree((LPVOID)pidl); //释放pIDL所指向内存空间;

			}
		}
	}

	CWnd::OnRButtonDown(nFlags, point);
}
// CashListView message handlers
void CashListView::OnPaint() {  
  CRect clientRect;
  GetClientRect(&clientRect);
  int clientWidth = clientRect.Width();

  BufferredPaintDC dc(this);

  dc.FillSolidRect(clientRect, RGB(255, 255, 255));

  CFont *oldFont = dc.SelectObject(GuiResources::GetInstance()->GetFont(GuiResources::FONT_NORMAL));
  dc.SetTextColor(RGB(0, 0, 0));
  dc.SetBkMode(TRANSPARENT);

  CString text[6];
  int width[6];
  text[0] = _T("序号"); // __XXXX__
  width[0] = 8 * clientWidth / 49;
  text[1] = _T("面额"); // __XXX__
  width[1] = 7 * clientWidth / 49;
  text[2] = _T("版本"); // __XX__
  width[2] = 6 * clientWidth / 49;
  text[3] = _T("结果"); // __XXX__
  width[3] = 7 * clientWidth / 49;
  text[4] = _T("方向"); // __X__
  width[4] = 5 * clientWidth / 49;
  text[5] = _T("冠字号"); // __XXXXXXXXXXXX__  
  width[5] = 16 * clientWidth / 49;

  int y = clientRect.top;
  CRect itemRect(clientRect.left, y, clientRect.right, y + itemHeight_);
  dc.FillSolidRect(itemRect, RGB(248, 248, 248));
  DrawRow(&dc, y, 0, text, width);

  if (monitor_ != NULL) {
    int count = monitor_->Freeze();
    for (int i = topItem_; i < count; i++) {
      y += itemHeight_;
      if (y > clientRect.bottom) {
        break;
      }
      itemRect.OffsetRect(0, itemHeight_);
      
      if (i == selectedItem_) {        
        dc.FillSolidRect(itemRect, GetFocus() == this ? RGB(54, 133, 214) : RGB(128, 128, 128));
        dc.SetTextColor(RGB(255, 255, 255));
      } else {
        if (((i + 1) & 1) == 0) {
          dc.FillSolidRect(itemRect, RGB(248, 248, 248));
        }
        dc.SetTextColor(RGB(0, 0, 0));
      }

      Cash *cash = monitor_->GetCash(i);
      if (cash->Valid(Cash::VALID_INFO)) {
        text[0].Format(_T("%d"), cash->Id());
        if (cash->GetDenomination() <= 0) {
          text[1] = _T("?");
        } else {
          text[1].Format(_T("%d"), cash->GetDenomination());
        }
        if (cash->GetVersion() <= 0) {
          text[2] = _T("?");
        } else {
          text[2].Format(_T("%02d"), cash->GetVersion());
        }
        text[3].Format(_T("%03d"), cash->GetError());
        if (cash->GetDirection() <= 0) {
          text[4] = _T("?");
        } else {
          text[4].Format(_T("%d"), cash->GetDirection());
        }
        text[5] = cash->GetSN();
        DrawRow(&dc, y, i + 1, text, width);
      }
    }
    monitor_->Unfreeze();
  }

  dc.SelectObject(oldFont);
}
// WaveformViewDialog message handlers
void WaveformViewDialog::OnPaint() {
  BufferredPaintDC dc(this);
  
  CRect rectTitle;
  GetDlgItem(IDC_PLACE_CAPTION)->GetWindowRect(&rectTitle);
  ScreenToClient(&rectTitle);
  dc.FillSolidRect(rectTitle, RGB(54, 133, 214));

  CRect waveformRect;
  GetDlgItem(IDC_PLACE_WAVEFORM)->GetWindowRect(&waveformRect);
  ScreenToClient(&waveformRect);
  dc.FillSolidRect(waveformRect, RGB(0, 0, 0));

  CFont *oldFont = dc.SelectObject(GuiResources::GetInstance()->GetFont(GuiResources::FONT_NORMAL));
  dc.SetTextColor(RGB(255, 255, 255));
  dc.SetBkMode(TRANSPARENT);
  CSize textSize = dc.GetTextExtent(_T("88888"));
  waveformRect.left += textSize.cx + 8;

  if (monitor_ != NULL && cashIndex_ != -1) {
    int cashCount = monitor_->Freeze();
    if (cashIndex_ < cashCount) {
      Cash *cash = monitor_->GetCash(cashIndex_);
      CPen penYellow(PS_SOLID, 1, RGB(255, 255, 0));
      CPen penGreen(PS_SOLID, 1, RGB(0, 255, 0));
      int count = cash->GetADCSampleCount(g_ADCChannels[channel_].id);      
      if (count > 0) {
        CString title;
        title.Format(_T("%s - %s"), (LPCTSTR)CA2T(cash->GetSN()), g_ADCChannels[channel_].name);
        labelTitle_.SetWindowText(title);

        const short *codes = cash->GetADCSampleCodes(g_ADCChannels[channel_].id);
        const short *values = cash->GetADCSampleValues(g_ADCChannels[channel_].id);
        
        // draw scaler
        __int64 sum = 0;
        short minValue = SHORT_MAX, maxValue = SHORT_MIN;
        for (int i = 0; i < count; i++) {
          if (values[i] < minValue) {
            minValue = values[i];
          }
          if (values[i] > maxValue) {
            maxValue = values[i];
          }
          sum += values[i];
        }
        CPen whitePen(PS_SOLID, 1, RGB(255, 255, 255));
        CPen *oldPen = dc.SelectObject(&whitePen);
        dc.MoveTo(waveformRect.left, waveformRect.top);
        dc.LineTo(waveformRect.left, waveformRect.bottom);
        
        int height = waveformRect.Height();
        int range = g_ADCChannels[channel_].maxValue - g_ADCChannels[channel_].minValue;
        // min
        CString label;
        int x = waveformRect.left - textSize.cx - 8;
        int y = waveformRect.bottom - (minValue - g_ADCChannels[channel_].minValue) * height / range;
        dc.MoveTo(waveformRect.left - 4, y);
        dc.LineTo(waveformRect.right, y);
        label.Format(_T("%d"), minValue);
        dc.TextOut(x, y - textSize.cy / 2, label);
        // center
        short median = (short)(sum / count);
        y = waveformRect.bottom - (median - g_ADCChannels[channel_].minValue) * height / range;
        dc.MoveTo(waveformRect.left - 4, y);
        dc.LineTo(waveformRect.right, y);
        label.Format(_T("%d"), median);
        dc.TextOut(x, y - textSize.cy / 2, label);
        // max
        y = waveformRect.bottom - (maxValue - g_ADCChannels[channel_].minValue) * height / range;
        dc.MoveTo(waveformRect.left - 4, y);
        dc.LineTo(waveformRect.right, y);
        label.Format(_T("%d"), maxValue);
        dc.TextOut(x, y - textSize.cy / 2, label);

        dc.SelectObject(oldPen);

        ::DrawWaveform(&dc, waveformRect, codes, codes[0], codes[count - 1], count, &penYellow);
        ::DrawWaveform(&dc, waveformRect, values, 
            g_ADCChannels[channel_].minValue, 
            g_ADCChannels[channel_].maxValue, count, &penGreen);
      }
    }
    monitor_->Unfreeze();
  }

  dc.SelectObject(oldFont);
}