CImgPlayerDlg.cpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. 
  2. // CImgPlayerDlg.cpp : 实现文件
  3. //
  4. #include "stdafx.h"
  5. #include "libimgplayer.h"
  6. #include "CImgPlayerDlg.h"
  7. #include "afxdialogex.h"
  8. #include <io.h>
  9. #define TIMERID 8
  10. CImgPlayerDlg::CImgPlayerDlg(CWnd* pParent /*=NULL*/)
  11. : CDialogEx(CImgPlayerDlg::IDD, pParent), m_pConfig(NULL)
  12. {
  13. m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  14. m_bInit = false;
  15. m_bTimer = false;
  16. m_hMonitor = NULL;
  17. m_nPicInx = 0;
  18. m_nPlayCnt = 0;
  19. m_pMemDC = new CDC();
  20. m_pMemBitmap = new CBitmap();
  21. m_pOldBitmap = NULL;
  22. }
  23. CImgPlayerDlg::CImgPlayerDlg(CImgPlayConfig *pConfig, CWnd* pParent /*= NULL*/)
  24. : CDialogEx(CImgPlayerDlg::IDD, pParent), m_pMemDC(NULL), m_pMemBitmap(NULL)
  25. {
  26. m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  27. m_bInit = false;
  28. m_bTimer = false;
  29. m_hMonitor = NULL;
  30. m_pConfig = pConfig;
  31. m_nPicInx = 0;
  32. m_nPlayCnt = 0;
  33. m_pMemDC = new CDC();
  34. m_pMemBitmap = new CBitmap();
  35. m_pOldBitmap = NULL;
  36. }
  37. CImgPlayerDlg::~CImgPlayerDlg()
  38. {
  39. delete m_pMemBitmap; m_pMemBitmap = NULL;
  40. delete m_pMemDC; m_pMemBitmap = NULL;
  41. }
  42. void CImgPlayerDlg::DoDataExchange(CDataExchange* pDX)
  43. {
  44. CDialogEx::DoDataExchange(pDX);
  45. }
  46. void CImgPlayerDlg::ShowImage(CImage& img, UINT ID)
  47. {
  48. // 获得显示控件的DC
  49. CDC* pDC = m_pMemDC;
  50. // 获取HDC(设备句柄)来进行绘图操作
  51. HDC hDC = pDC->GetSafeHdc();
  52. CRect rect;
  53. GetDlgItem(ID)->GetClientRect(&rect);
  54. // 读取图片控件的宽和高
  55. int rw = rect.right-rect.left;
  56. int rh = rect.bottom-rect.top;
  57. // 设置图片控件背景色为黑色
  58. CBrush brush(RGB(0,0,0));
  59. pDC->FillRect(CRect(0, 0, rw, rh), &brush);
  60. // 读取图片的宽和高
  61. int iw = img.GetWidth();
  62. int ih = img.GetHeight();
  63. // 图片左上角在图片控件中的坐标
  64. int tx = 0;
  65. int ty = 0;
  66. // 图片绘制时的宽和高
  67. int nw = iw;
  68. int nh = ih;
  69. if (iw <= rw && ih <= rh)
  70. {
  71. float scale_x = (float) rw / iw;
  72. float scale_y = (float) rh / ih;
  73. float scale = scale_x - scale_y >= 1e-6? scale_y : scale_x;
  74. nw = (int)(iw * scale);
  75. nh = (int)(ih * scale);
  76. tx = (scale_x-scale_y >= 1e-6) ? (int)(rw-nw)/2 : 0;
  77. ty = (scale_x-scale_y >= 1e-6) ? 0 : (int)(rw-nw)/2;
  78. }
  79. else
  80. {
  81. // 计算横向和纵向缩放因子
  82. float scale_x = (float)iw / rw;
  83. float scale_y = (float)ih / rh;
  84. float scale;
  85. if (scale_x-scale_y >= 1e-6)
  86. scale = scale_x;
  87. else
  88. scale = scale_y;
  89. // 缩放后图片的宽和高
  90. nw = (int)(iw/scale);
  91. nh = (int)(ih/scale);
  92. // 缩放后的图片在m_Image的正中部位绘制,计算图片左上角在m_Image中的坐标
  93. tx = (scale_x-scale_y >= 1e-6) ? 0 : (int)(rw-nw)/2;
  94. ty = (scale_x-scale_y >= 1e-6) ? (int)(rh-nh)/2 : 0;
  95. }
  96. SetRect(&rect, tx, ty, tx+nw, ty+nh);
  97. // 将图片绘制到显示控件的指定区域
  98. SetStretchBltMode(hDC, HALFTONE); // 保持原有图片质量
  99. SetBrushOrgEx(hDC, 0, 0, NULL); // 设置刷子的起始点
  100. img.Draw(hDC,rect);
  101. brush.DeleteObject();
  102. //ReleaseDC(pDC);
  103. m_Image.Destroy(); //主动释放位图资源 相当于对Detach返回的结果执行DeleteObject
  104. pDC = GetDlgItem(ID)->GetDC();
  105. GetDlgItem(ID)->GetClientRect(&rect);
  106. pDC->BitBlt(0, 0, rect.Width(), rect.Height(), m_pMemDC, 0, 0, SRCCOPY);
  107. //DeleteObject(m_pMemBitmap);
  108. ReleaseDC(pDC);
  109. }
  110. BEGIN_MESSAGE_MAP(CImgPlayerDlg, CDialogEx)
  111. ON_WM_PAINT()
  112. ON_WM_QUERYDRAGICON()
  113. ON_WM_SIZE()
  114. ON_WM_CLOSE()
  115. ON_WM_TIMER()
  116. ON_WM_ERASEBKGND()
  117. END_MESSAGE_MAP()
  118. // CImgPlayerDlg 消息处理程序
  119. BOOL CImgPlayerDlg::OnInitDialog()
  120. {
  121. CDialogEx::OnInitDialog();
  122. // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
  123. // 执行此操作
  124. SetIcon(m_hIcon, TRUE); // 设置大图标
  125. SetIcon(m_hIcon, FALSE); // 设置小图标
  126. long ScreenWidth = GetSystemMetrics(SM_CXSCREEN); //主屏幕宽度
  127. long ScreenHeight = GetSystemMetrics(SM_CYSCREEN); //主屏幕高度
  128. MONITORINFOEX mix;
  129. mix.cbSize = sizeof(mix);
  130. if (m_pConfig->bPrimMonitor == false) // 默认情况,在副屏显示
  131. {
  132. POINT pt;
  133. pt.x = ScreenWidth+5;
  134. pt.y = 5;
  135. m_hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONULL); //尝试获取副屏的句柄
  136. if (m_hMonitor != NULL)
  137. {
  138. GetMonitorInfo(m_hMonitor, (LPMONITORINFO)&mix);
  139. SetRect(&m_monitorRect, mix.rcMonitor.left, mix.rcMonitor.top, mix.rcMonitor.right, mix.rcMonitor.bottom);
  140. }
  141. else
  142. {
  143. OnCancel();
  144. return FALSE;
  145. }
  146. }
  147. else // 在主屏显示
  148. {
  149. m_hMonitor = MonitorFromWindow(this->GetSafeHwnd(), MONITOR_DEFAULTTONULL);
  150. GetMonitorInfo(m_hMonitor, (LPMONITORINFO)&mix);
  151. SetRect(&m_monitorRect, mix.rcMonitor.left, mix.rcMonitor.top, mix.rcMonitor.right, mix.rcMonitor.bottom);
  152. }
  153. // TODO: 在此添加额外的初始化代码
  154. m_bInit = true;
  155. // 去掉标题栏和边框
  156. ModifyStyle(WS_CAPTION, 0, 0);
  157. ModifyStyleEx(WS_EX_DLGMODALFRAME, 0, 0);
  158. if (m_pConfig->bFullScreen == true)
  159. {
  160. //ShowWindow(SW_MAXIMIZE); // 设置窗口最大化
  161. ::SetWindowPos(this->GetSafeHwnd(),HWND_TOP,m_monitorRect.left,m_monitorRect.top,
  162. m_monitorRect.Width(),m_monitorRect.Height(),SWP_SHOWWINDOW); //设置窗口的位置和大小
  163. }
  164. else
  165. {
  166. if (m_pConfig->nWndWidth > m_monitorRect.Width())
  167. {
  168. m_pConfig->nWndWidth = m_monitorRect.Width();
  169. }
  170. if (m_pConfig->nWndHeight > m_monitorRect.Height())
  171. {
  172. m_pConfig->nWndHeight = m_monitorRect.Height();
  173. }
  174. ::SetWindowPos(this->GetSafeHwnd(),HWND_TOP,m_monitorRect.left+m_pConfig->nWndX,m_monitorRect.top+m_pConfig->nWndY,
  175. m_pConfig->nWndWidth,m_pConfig->nWndHeight,SWP_SHOWWINDOW); //设置窗口的位置和大小
  176. }
  177. CRect rect;
  178. this->GetClientRect(&rect);
  179. //使PictureControl填充整个窗口,超出窗口并增加宽高各1个像素,以隐藏PictureControl的边框(注意控件是相对于窗口的)
  180. ::SetWindowPos(GetDlgItem(IDC_ShowImg)->GetSafeHwnd(),HWND_TOP,-1,-1,
  181. rect.Width()+2,rect.Height()+2,SWP_SHOWWINDOW);
  182. ::GetWindowRect(GetDlgItem(IDC_ShowImg)->GetSafeHwnd(), &rect); // 计算PictureControl的屏幕坐标
  183. //this->ScreenToClient(&rect); // 转换到相对于Dialog客户区的坐标
  184. //int borderWidth = -rect.left; // 计算边框的厚度
  185. // 双缓冲机制
  186. int x = rect.Width();
  187. int y = rect.Height();
  188. CDC *pDC = GetDlgItem(IDC_ShowImg)->GetDC();
  189. m_pMemDC->CreateCompatibleDC(pDC); // 依附图片控件DC创建兼容内存DC
  190. m_pMemBitmap->CreateCompatibleBitmap(pDC, x, y); // 创建兼容位图
  191. m_pOldBitmap = m_pMemDC->SelectObject(m_pMemBitmap); // 将位图选进内存DC,原位图保存到m_pOldBitmap
  192. ReleaseDC(pDC);
  193. DeleteObject(m_pOldBitmap);
  194. // 加载并显示第一张图片
  195. if (m_pConfig->nFileCnt > 0)
  196. {
  197. CString imgPath;
  198. imgPath.Format(_T("%s%s"),m_pConfig->strRootPath,m_pConfig->strFileNames[0]);
  199. // 判断文件是否存在
  200. if (_access(LPCTSTR(imgPath), 0) != -1)
  201. {
  202. HRESULT hRet = m_Image.Load(LPCTSTR(imgPath));
  203. if (S_OK == hRet){
  204. ShowImage(m_Image, IDC_ShowImg);
  205. }
  206. }
  207. }
  208. // 每m_nPlayInterval毫秒显示下一张图片
  209. if (m_pConfig->nFileCnt > 1)
  210. {
  211. if (m_pConfig->nPlayInterval <= 1000)
  212. {
  213. m_pConfig->nPlayInterval = 1000;
  214. }
  215. SetTimer(TIMERID, m_pConfig->nPlayInterval, 0);
  216. m_bTimer = true;
  217. }
  218. return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
  219. }
  220. // 如果向对话框添加最小化按钮,则需要下面的代码
  221. // 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
  222. // 这将由框架自动完成。
  223. void CImgPlayerDlg::OnPaint()
  224. {
  225. if (IsIconic())
  226. {
  227. CPaintDC dc(this); // 用于绘制的设备上下文
  228. SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
  229. // 使图标在工作区矩形中居中
  230. int cxIcon = GetSystemMetrics(SM_CXICON);
  231. int cyIcon = GetSystemMetrics(SM_CYICON);
  232. CRect rect;
  233. GetClientRect(&rect);
  234. int x = (rect.Width() - cxIcon + 1) / 2;
  235. int y = (rect.Height() - cyIcon + 1) / 2;
  236. // 绘制图标
  237. dc.DrawIcon(x, y, m_hIcon);
  238. }
  239. else
  240. {
  241. CDialogEx::OnPaint();
  242. }
  243. }
  244. //当用户拖动最小化窗口时系统调用此函数取得光标
  245. //显示。
  246. HCURSOR CImgPlayerDlg::OnQueryDragIcon()
  247. {
  248. return static_cast<HCURSOR>(m_hIcon);
  249. }
  250. void CImgPlayerDlg::OnSize(UINT nType, int cx, int cy)
  251. {
  252. if (m_bInit == FALSE)
  253. return;
  254. CDialogEx::OnSize(nType, cx, cy);
  255. // TODO: 在此处添加消息处理程序代码
  256. GetDlgItem(IDC_ShowImg)->MoveWindow(0, 0, cx, cy);
  257. }
  258. void CImgPlayerDlg::OnClose()
  259. {
  260. // TODO: 在此添加消息处理程序代码和/或调用默认值
  261. CDialogEx::OnClose();
  262. EndPlay();
  263. }
  264. void CImgPlayerDlg::OnTimer(UINT_PTR nIDEvent)
  265. {
  266. // TODO: 在此添加消息处理程序代码和/或调用默认值
  267. if (nIDEvent == TIMERID)
  268. {
  269. m_nPicInx = (m_nPicInx+1)%m_pConfig->nFileCnt;
  270. if (m_pConfig->nPlayCnt != 0) // 非循环播放
  271. {
  272. if (m_nPicInx == 0)
  273. {
  274. m_nPlayCnt++;
  275. }
  276. if (m_nPlayCnt == m_pConfig->nPlayCnt)//播放次数到了
  277. {
  278. // 结束播放
  279. EndPlay();
  280. return;
  281. }
  282. }
  283. CString imgPath;
  284. imgPath.Format(_T("%s%s"),m_pConfig->strRootPath,m_pConfig->strFileNames[m_nPicInx]);
  285. // 判断文件是否存在
  286. if (_access((LPCTSTR)imgPath, 0) != -1)
  287. {
  288. HRESULT hRet = m_Image.Load(LPCTSTR(imgPath));
  289. if (S_OK == hRet){
  290. ShowImage(m_Image, IDC_ShowImg);
  291. }
  292. }
  293. }
  294. CDialogEx::OnTimer(nIDEvent);
  295. }
  296. // 屏蔽背景刷新
  297. BOOL CImgPlayerDlg::OnEraseBkgnd(CDC* pDC)
  298. {
  299. // TODO: 在此添加消息处理程序代码和/或调用默认值
  300. return TRUE;
  301. //return CDialogEx::OnEraseBkgnd(pDC);
  302. }
  303. BOOL CImgPlayerDlg::EndPlay()
  304. {
  305. // 停止定时器
  306. if (m_bTimer)
  307. {
  308. KillTimer(TIMERID);
  309. m_bTimer = false;
  310. // 释放绘图对象
  311. DeleteObject(m_pMemBitmap);
  312. ReleaseDC(m_pMemDC);
  313. }
  314. // 关闭窗口
  315. EndDialog(IDCANCEL);
  316. return TRUE;
  317. }