// CImgPlayerDlg.cpp : 实现文件 // #include "stdafx.h" #include "libimgplayer.h" #include "CImgPlayerDlg.h" #include "afxdialogex.h" #include #define TIMERID 8 CImgPlayerDlg::CImgPlayerDlg(CWnd* pParent /*=NULL*/) : CDialogEx(CImgPlayerDlg::IDD, pParent), m_pConfig(NULL) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); m_bInit = false; m_bTimer = false; m_hMonitor = NULL; m_nPicInx = 0; m_nPlayCnt = 0; m_pMemDC = new CDC(); m_pMemBitmap = new CBitmap(); m_pOldBitmap = NULL; } CImgPlayerDlg::CImgPlayerDlg(CImgPlayConfig *pConfig, CWnd* pParent /*= NULL*/) : CDialogEx(CImgPlayerDlg::IDD, pParent), m_pMemDC(NULL), m_pMemBitmap(NULL) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); m_bInit = false; m_bTimer = false; m_hMonitor = NULL; m_pConfig = pConfig; m_nPicInx = 0; m_nPlayCnt = 0; m_pMemDC = new CDC(); m_pMemBitmap = new CBitmap(); m_pOldBitmap = NULL; } CImgPlayerDlg::~CImgPlayerDlg() { delete m_pMemBitmap; m_pMemBitmap = NULL; delete m_pMemDC; m_pMemBitmap = NULL; } void CImgPlayerDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); } void CImgPlayerDlg::ShowImage(CImage& img, UINT ID) { // 获得显示控件的DC CDC* pDC = m_pMemDC; // 获取HDC(设备句柄)来进行绘图操作 HDC hDC = pDC->GetSafeHdc(); CRect rect; GetDlgItem(ID)->GetClientRect(&rect); // 读取图片控件的宽和高 int rw = rect.right-rect.left; int rh = rect.bottom-rect.top; // 设置图片控件背景色为黑色 CBrush brush(RGB(0,0,0)); pDC->FillRect(CRect(0, 0, rw, rh), &brush); // 读取图片的宽和高 int iw = img.GetWidth(); int ih = img.GetHeight(); // 图片左上角在图片控件中的坐标 int tx = 0; int ty = 0; // 图片绘制时的宽和高 int nw = iw; int nh = ih; if (iw <= rw && ih <= rh) { float scale_x = (float) rw / iw; float scale_y = (float) rh / ih; float scale = scale_x - scale_y >= 1e-6? scale_y : scale_x; nw = (int)(iw * scale); nh = (int)(ih * scale); tx = (scale_x-scale_y >= 1e-6) ? (int)(rw-nw)/2 : 0; ty = (scale_x-scale_y >= 1e-6) ? 0 : (int)(rw-nw)/2; } else { // 计算横向和纵向缩放因子 float scale_x = (float)iw / rw; float scale_y = (float)ih / rh; float scale; if (scale_x-scale_y >= 1e-6) scale = scale_x; else scale = scale_y; // 缩放后图片的宽和高 nw = (int)(iw/scale); nh = (int)(ih/scale); // 缩放后的图片在m_Image的正中部位绘制,计算图片左上角在m_Image中的坐标 tx = (scale_x-scale_y >= 1e-6) ? 0 : (int)(rw-nw)/2; ty = (scale_x-scale_y >= 1e-6) ? (int)(rh-nh)/2 : 0; } SetRect(&rect, tx, ty, tx+nw, ty+nh); // 将图片绘制到显示控件的指定区域 SetStretchBltMode(hDC, HALFTONE); // 保持原有图片质量 SetBrushOrgEx(hDC, 0, 0, NULL); // 设置刷子的起始点 img.Draw(hDC,rect); brush.DeleteObject(); //ReleaseDC(pDC); m_Image.Destroy(); //主动释放位图资源 相当于对Detach返回的结果执行DeleteObject pDC = GetDlgItem(ID)->GetDC(); GetDlgItem(ID)->GetClientRect(&rect); pDC->BitBlt(0, 0, rect.Width(), rect.Height(), m_pMemDC, 0, 0, SRCCOPY); //DeleteObject(m_pMemBitmap); ReleaseDC(pDC); } BEGIN_MESSAGE_MAP(CImgPlayerDlg, CDialogEx) ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_WM_SIZE() ON_WM_CLOSE() ON_WM_TIMER() ON_WM_ERASEBKGND() END_MESSAGE_MAP() // CImgPlayerDlg 消息处理程序 BOOL CImgPlayerDlg::OnInitDialog() { CDialogEx::OnInitDialog(); // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动 // 执行此操作 SetIcon(m_hIcon, TRUE); // 设置大图标 SetIcon(m_hIcon, FALSE); // 设置小图标 long ScreenWidth = GetSystemMetrics(SM_CXSCREEN); //主屏幕宽度 long ScreenHeight = GetSystemMetrics(SM_CYSCREEN); //主屏幕高度 MONITORINFOEX mix; mix.cbSize = sizeof(mix); if (m_pConfig->bPrimMonitor == false) // 默认情况,在副屏显示 { POINT pt; pt.x = ScreenWidth+5; pt.y = 5; m_hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONULL); //尝试获取副屏的句柄 if (m_hMonitor != NULL) { GetMonitorInfo(m_hMonitor, (LPMONITORINFO)&mix); SetRect(&m_monitorRect, mix.rcMonitor.left, mix.rcMonitor.top, mix.rcMonitor.right, mix.rcMonitor.bottom); } else { OnCancel(); return FALSE; } } else // 在主屏显示 { m_hMonitor = MonitorFromWindow(this->GetSafeHwnd(), MONITOR_DEFAULTTONULL); GetMonitorInfo(m_hMonitor, (LPMONITORINFO)&mix); SetRect(&m_monitorRect, mix.rcMonitor.left, mix.rcMonitor.top, mix.rcMonitor.right, mix.rcMonitor.bottom); } // TODO: 在此添加额外的初始化代码 m_bInit = true; // 去掉标题栏和边框 ModifyStyle(WS_CAPTION, 0, 0); ModifyStyleEx(WS_EX_DLGMODALFRAME, 0, 0); if (m_pConfig->bFullScreen == true) { //ShowWindow(SW_MAXIMIZE); // 设置窗口最大化 ::SetWindowPos(this->GetSafeHwnd(),HWND_TOP,m_monitorRect.left,m_monitorRect.top, m_monitorRect.Width(),m_monitorRect.Height(),SWP_SHOWWINDOW); //设置窗口的位置和大小 } else { if (m_pConfig->nWndWidth > m_monitorRect.Width()) { m_pConfig->nWndWidth = m_monitorRect.Width(); } if (m_pConfig->nWndHeight > m_monitorRect.Height()) { m_pConfig->nWndHeight = m_monitorRect.Height(); } ::SetWindowPos(this->GetSafeHwnd(),HWND_TOP,m_monitorRect.left+m_pConfig->nWndX,m_monitorRect.top+m_pConfig->nWndY, m_pConfig->nWndWidth,m_pConfig->nWndHeight,SWP_SHOWWINDOW); //设置窗口的位置和大小 } CRect rect; this->GetClientRect(&rect); //使PictureControl填充整个窗口,超出窗口并增加宽高各1个像素,以隐藏PictureControl的边框(注意控件是相对于窗口的) ::SetWindowPos(GetDlgItem(IDC_ShowImg)->GetSafeHwnd(),HWND_TOP,-1,-1, rect.Width()+2,rect.Height()+2,SWP_SHOWWINDOW); ::GetWindowRect(GetDlgItem(IDC_ShowImg)->GetSafeHwnd(), &rect); // 计算PictureControl的屏幕坐标 //this->ScreenToClient(&rect); // 转换到相对于Dialog客户区的坐标 //int borderWidth = -rect.left; // 计算边框的厚度 // 双缓冲机制 int x = rect.Width(); int y = rect.Height(); CDC *pDC = GetDlgItem(IDC_ShowImg)->GetDC(); m_pMemDC->CreateCompatibleDC(pDC); // 依附图片控件DC创建兼容内存DC m_pMemBitmap->CreateCompatibleBitmap(pDC, x, y); // 创建兼容位图 m_pOldBitmap = m_pMemDC->SelectObject(m_pMemBitmap); // 将位图选进内存DC,原位图保存到m_pOldBitmap ReleaseDC(pDC); DeleteObject(m_pOldBitmap); // 加载并显示第一张图片 if (m_pConfig->nFileCnt > 0) { CString imgPath; imgPath.Format(_T("%s%s"),m_pConfig->strRootPath,m_pConfig->strFileNames[0]); // 判断文件是否存在 if (_access(LPCTSTR(imgPath), 0) != -1) { HRESULT hRet = m_Image.Load(LPCTSTR(imgPath)); if (S_OK == hRet){ ShowImage(m_Image, IDC_ShowImg); } } } // 每m_nPlayInterval毫秒显示下一张图片 if (m_pConfig->nFileCnt > 1) { if (m_pConfig->nPlayInterval <= 1000) { m_pConfig->nPlayInterval = 1000; } SetTimer(TIMERID, m_pConfig->nPlayInterval, 0); m_bTimer = true; } return TRUE; // 除非将焦点设置到控件,否则返回 TRUE } // 如果向对话框添加最小化按钮,则需要下面的代码 // 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序, // 这将由框架自动完成。 void CImgPlayerDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // 用于绘制的设备上下文 SendMessage(WM_ICONERASEBKGND, reinterpret_cast(dc.GetSafeHdc()), 0); // 使图标在工作区矩形中居中 int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // 绘制图标 dc.DrawIcon(x, y, m_hIcon); } else { CDialogEx::OnPaint(); } } //当用户拖动最小化窗口时系统调用此函数取得光标 //显示。 HCURSOR CImgPlayerDlg::OnQueryDragIcon() { return static_cast(m_hIcon); } void CImgPlayerDlg::OnSize(UINT nType, int cx, int cy) { if (m_bInit == FALSE) return; CDialogEx::OnSize(nType, cx, cy); // TODO: 在此处添加消息处理程序代码 GetDlgItem(IDC_ShowImg)->MoveWindow(0, 0, cx, cy); } void CImgPlayerDlg::OnClose() { // TODO: 在此添加消息处理程序代码和/或调用默认值 CDialogEx::OnClose(); EndPlay(); } void CImgPlayerDlg::OnTimer(UINT_PTR nIDEvent) { // TODO: 在此添加消息处理程序代码和/或调用默认值 if (nIDEvent == TIMERID) { m_nPicInx = (m_nPicInx+1)%m_pConfig->nFileCnt; if (m_pConfig->nPlayCnt != 0) // 非循环播放 { if (m_nPicInx == 0) { m_nPlayCnt++; } if (m_nPlayCnt == m_pConfig->nPlayCnt)//播放次数到了 { // 结束播放 EndPlay(); return; } } CString imgPath; imgPath.Format(_T("%s%s"),m_pConfig->strRootPath,m_pConfig->strFileNames[m_nPicInx]); // 判断文件是否存在 if (_access((LPCTSTR)imgPath, 0) != -1) { HRESULT hRet = m_Image.Load(LPCTSTR(imgPath)); if (S_OK == hRet){ ShowImage(m_Image, IDC_ShowImg); } } } CDialogEx::OnTimer(nIDEvent); } // 屏蔽背景刷新 BOOL CImgPlayerDlg::OnEraseBkgnd(CDC* pDC) { // TODO: 在此添加消息处理程序代码和/或调用默认值 return TRUE; //return CDialogEx::OnEraseBkgnd(pDC); } BOOL CImgPlayerDlg::EndPlay() { // 停止定时器 if (m_bTimer) { KillTimer(TIMERID); m_bTimer = false; // 释放绘图对象 DeleteObject(m_pMemBitmap); ReleaseDC(m_pMemDC); } // 关闭窗口 EndDialog(IDCANCEL); return TRUE; }