CDlgOracleImageRWDlg.cpp
上传用户:ynjin1970
上传日期:2014-10-13
资源大小:6438k
文件大小:16k
源码类别:

中间件编程

开发平台:

Visual C++

  1. // CDlgOracleImageRWDlg.cpp : implementation file
  2. #include "stdafx.h"
  3. #include "CDlgOracleImageRW.h"
  4. #include "CDlgOracleImageRWDlg.h"
  5. #ifdef _DEBUG
  6. #define new DEBUG_NEW
  7. #undef THIS_FILE
  8. static char THIS_FILE[] = __FILE__;
  9. #endif
  10. /////////////////////////////////////////////////////////////////////////////
  11. // CAboutDlg dialog used for App About
  12. class CAboutDlg : public CDialog
  13. {
  14. public:
  15. CAboutDlg();
  16. // Dialog Data
  17. //{{AFX_DATA(CAboutDlg)
  18. enum { IDD = IDD_ABOUTBOX };
  19. //}}AFX_DATA
  20. // ClassWizard generated virtual function overrides
  21. //{{AFX_VIRTUAL(CAboutDlg)
  22. protected:
  23. virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
  24. //}}AFX_VIRTUAL
  25. // Implementation
  26. protected:
  27. //{{AFX_MSG(CAboutDlg)
  28. //}}AFX_MSG
  29. DECLARE_MESSAGE_MAP()
  30. };
  31. CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
  32. {
  33. //{{AFX_DATA_INIT(CAboutDlg)
  34. //}}AFX_DATA_INIT
  35. }
  36. void CAboutDlg::DoDataExchange(CDataExchange* pDX)
  37. {
  38. CDialog::DoDataExchange(pDX);
  39. //{{AFX_DATA_MAP(CAboutDlg)
  40. //}}AFX_DATA_MAP
  41. }
  42. BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
  43. //{{AFX_MSG_MAP(CAboutDlg)
  44. // No message handlers
  45. //}}AFX_MSG_MAP
  46. END_MESSAGE_MAP()
  47. /////////////////////////////////////////////////////////////////////////////
  48. // CCDlgOracleImageRWDlg dialog
  49. CCDlgOracleImageRWDlg::CCDlgOracleImageRWDlg(CWnd* pParent /*=NULL*/)
  50. : CDialog(CCDlgOracleImageRWDlg::IDD, pParent)
  51. {
  52. //{{AFX_DATA_INIT(CCDlgOracleImageRWDlg)
  53. m_ID = _T("");
  54. m_Name = _T("");
  55. //}}AFX_DATA_INIT
  56. // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
  57. //获得主框架指针
  58. pMainWnd=AfxGetMainWnd();
  59. //给变量赋初值
  60. m_bModify = FALSE;
  61. m_hPhotoBitmap = NULL;
  62. m_pBMPBuffer = NULL;
  63. }
  64. void CCDlgOracleImageRWDlg::DoDataExchange(CDataExchange* pDX)
  65. {
  66. CDialog::DoDataExchange(pDX);
  67. //{{AFX_DATA_MAP(CCDlgOracleImageRWDlg)
  68. DDX_Text(pDX, IDC_ID, m_ID);
  69. DDX_Text(pDX, IDC_Name, m_Name);
  70. //}}AFX_DATA_MAP
  71. }
  72. BEGIN_MESSAGE_MAP(CCDlgOracleImageRWDlg, CDialog)
  73. //{{AFX_MSG_MAP(CCDlgOracleImageRWDlg)
  74. ON_WM_SYSCOMMAND()
  75. ON_WM_PAINT()
  76. ON_WM_QUERYDRAGICON()
  77. ON_BN_CLICKED(IDC_PREVIOUSUSER, OnPrevioususer)
  78. ON_BN_CLICKED(IDC_NEXTUSER, OnNextuser)
  79. ON_BN_CLICKED(IDC_SAVEINFO, OnSave)
  80. ON_BN_CLICKED(IDC_ADDUSER, OnAddPhoto)
  81. ON_BN_CLICKED(IDC_DELETEUSER, OnDeletePhoto)
  82. ON_BN_CLICKED(IDC_SELECTPHOTO, OnSelectphoto)
  83. ON_WM_PAINT()
  84. ON_WM_DESTROY()
  85. //}}AFX_MSG_MAP
  86. END_MESSAGE_MAP()
  87. /////////////////////////////////////////////////////////////////////////////
  88. // CCDlgOracleImageRWDlg message handlers
  89. BOOL CCDlgOracleImageRWDlg::OnInitDialog()
  90. {
  91. CDialog::OnInitDialog();
  92. // Add "About..." menu item to system menu.
  93. // IDM_ABOUTBOX must be in the system command range.
  94. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
  95. ASSERT(IDM_ABOUTBOX < 0xF000);
  96. CMenu* pSysMenu = GetSystemMenu(FALSE);
  97. if (pSysMenu != NULL)
  98. {
  99. CString strAboutMenu;
  100. strAboutMenu.LoadString(IDS_ABOUTBOX);
  101. if (!strAboutMenu.IsEmpty())
  102. {
  103. pSysMenu->AppendMenu(MF_SEPARATOR);
  104. pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
  105. }
  106. }
  107. // Set the icon for this dialog.  The framework does this automatically
  108. //  when the application's main window is not a dialog
  109. SetIcon(m_hIcon, TRUE); // Set big icon
  110. SetIcon(m_hIcon, FALSE); // Set small icon
  111. // TODO: Add extra initialization here
  112. //连接数据库
  113. odb.Open("blobdb", "scott", "tiger");
  114. //打开记录集
  115. odyn.Open(odb, "SELECT * FROM IMAGE ");
  116. //检查记录集是否打开
  117. if (!odyn.IsOpen())
  118. {
  119. CString err;
  120. CString err1;
  121. err.Format("%s", (char*)(odb.GetErrorText()) );
  122. err1.Format("%s", (char*)(odb.GetErrorText()) );
  123. AfxMessageBox(err);
  124. AfxMessageBox(err1);
  125. }
  126. return TRUE;  // return TRUE  unless you set the focus to a control
  127. }
  128. void CCDlgOracleImageRWDlg::OnSysCommand(UINT nID, LPARAM lParam)
  129. {
  130. if ((nID & 0xFFF0) == IDM_ABOUTBOX)
  131. {
  132. CAboutDlg dlgAbout;
  133. dlgAbout.DoModal();
  134. }
  135. else
  136. {
  137. CDialog::OnSysCommand(nID, lParam);
  138. }
  139. }
  140. // If you add a minimize button to your dialog, you will need the code below
  141. //  to draw the icon.  For MFC applications using the document/view model,
  142. //  this is automatically done for you by the framework.
  143. void CCDlgOracleImageRWDlg::OnPaint() 
  144. {
  145. CPaintDC dc(this);
  146. if (IsIconic())
  147. {
  148. CPaintDC dc(this); // device context for painting
  149. SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
  150. // Center icon in client rectangle
  151. int cxIcon = GetSystemMetrics(SM_CXICON);
  152. int cyIcon = GetSystemMetrics(SM_CYICON);
  153. CRect rect;
  154. GetClientRect(&rect);
  155. int x = (rect.Width() - cxIcon + 1) / 2;
  156. int y = (rect.Height() - cyIcon + 1) / 2;
  157. // Draw the icon
  158. dc.DrawIcon(x, y, m_hIcon);
  159. }
  160. else
  161. {
  162. //将图像显示在对话框控件中
  163. DrawUserPhoto(50,30,&dc);
  164. CDialog::OnPaint();
  165. }
  166. }
  167. // The system calls this to obtain the cursor to display while the user drags
  168. //  the minimized window.
  169. HCURSOR CCDlgOracleImageRWDlg::OnQueryDragIcon()
  170. {
  171. return (HCURSOR) m_hIcon;
  172. }
  173. void CCDlgOracleImageRWDlg::OnPrevioususer() 
  174. {
  175. // TODO: Add your control notification handler code here
  176. // 检查记录集中是否有记录
  177. if(odyn.GetRecordCount()==0)
  178. {
  179. AfxMessageBox("记录集中没有图片!请输入");
  180. return;
  181. }
  182. //移到下一个记录
  183. odyn.MovePrev();
  184. //是否到首记录标志处
  185. if(odyn.IsBOF())
  186. odyn.MoveFirst();//移到第一个记录
  187. //从Oracle数据库中读出像片数据
  188. ReadData();
  189. Invalidate();
  190. }
  191. void CCDlgOracleImageRWDlg::OnNextuser() 
  192. {
  193. // TODO: Add your control notification handler code here
  194. // 检查记录集中是否有记录
  195. if(odyn.GetRecordCount()==0)
  196. {
  197. AfxMessageBox("记录集中没有图片!请输入");
  198. return;
  199. }
  200. //移到下一个记录
  201. odyn.MoveNext();
  202. //是否到末记录标志处
  203. if(odyn.IsEOF())
  204. odyn.MoveLast();
  205. ReadData();
  206. //从Oracle数据库中读出像片数据
  207. Invalidate();
  208. }
  209. void CCDlgOracleImageRWDlg::OnSave() 
  210. {
  211. // TODO: Add your control notification handler code here
  212. m_bNewImage = true;
  213. if(!m_bModify) return;
  214. UpdateData();
  215. if( m_Name == "")
  216. {
  217. AfxMessageBox("您没有提供完整的用户信息。rn这些信息包括:用户名、年龄、照片");
  218. return;
  219. }
  220. //指向缓存的指针
  221. char *pBuf = m_pBMPBuffer;
  222. //定义一个结果对象,返回值0为失败,1为成功
  223.    oresult ores;
  224. //移动到上一个记录
  225. ores = odyn.MoveLast();
  226. //定义一个OValue值对象
  227. OValue val;
  228. //对象置空值
  229. val.SetEmpty();
  230. //准备添加一个记录
  231. odyn.AddNewRecord();
  232. //把ID号值放到第一个字段
  233. odyn.SetFieldValue("ID", m_ID);
  234. //把名字放到第二个字段
  235. ores=odyn.SetFieldValue("NAME", m_Name);
  236. //把空值放到DATA字段
  237. ores = odyn.SetFieldValue((const char *)"DATA", val);
  238. //更新记录集
  239. ores = odyn.Update();
  240. //移动到上一个字段,此值非常重要,否者会造成属性值和BLOB图像数据的错位
  241. ////////////////////////////////////////////////////////////////////
  242. odyn.MoveLast();
  243. ////////////////////////////////////////////////////////////////////
  244. //定义一个OBlob对象
  245. OBlob oblob;
  246. //开始编辑记录集
  247. odyn.StartEdit();
  248. //把oblob对象定位到OBLOB字段上
  249. odyn.GetFieldValue("DATA", &oblob);
  250. //定义一个缓冲指针
  251. unsigned char *buffer = 0;
  252. try
  253. {
  254. // 计算一个合适的缓冲值大小
  255. unsigned long optchunk = oblob.GetOptimumChunkSize();
  256. //在分配中开辟缓冲区;用分块循环的方法可以减小开辟大块内存
  257. unsigned int bufsize = ((int)(32768/optchunk)) *optchunk;
  258. //用分块循环的方法可以减小开辟大块内存
  259. buffer = (unsigned char *)malloc(bufsize);
  260. ////定义一个fstream 对象
  261. fstream fs;
  262. //打开一个图像文件
  263. fs.open(pathname, ios::in);
  264. //设置模式
  265. fs.setmode(filebuf::binary);
  266. //移动指针到文件末尾
  267. fs.seekg(0, ios::end);
  268. //计算文件长度
  269. unsigned long filesize = fs.tellg();
  270. //回到文件指针头
  271. fs.seekg(0, ios::beg);
  272. //定义一个变量,计算一共书写的字节数
  273. unsigned long totalwritten = 0;
  274. //定义一个变量,计算每次读的字节数
  275. unsigned long amtread = 0;
  276. //第一块读取的OBLOB字段标记
  277. int piecetype = OLOB_FIRST_PIECE;
  278. //分块读入的方法可以充分利用数据流的优势,不用开很大的内存
  279. if (filesize <= bufsize)
  280. //如果文件数据字节数小于一块内存,只需一次读入
  281. piecetype = OLOB_ONE_PIECE;
  282. else
  283. //如果文件数据字节数大于一块内存,设置文件数据流读入方式
  284. oblob.EnableStreaming(filesize);
  285. while(totalwritten != filesize)
  286. {
  287. //从文件数据中读入一块缓冲块大小的内存
  288. fs.read(buffer, bufsize);
  289. //计算读入的数据字节数
  290. amtread = fs.gcount();
  291. //一次写一块缓冲块大小的数据到OBLOB对象中
  292. oblob.Write(buffer, amtread, piecetype);
  293. //计算总共书写的数据字节数
  294. totalwritten = totalwritten + amtread;
  295. //从文件数据中读入一块缓冲块大小的内存
  296. if ((filesize - totalwritten)<=bufsize)
  297. piecetype = OLOB_LAST_PIECE;
  298. else 
  299. piecetype = OLOB_NEXT_PIECE;
  300. }
  301. //结束流数据的输入
  302. oblob.DisableStreaming();
  303. //更新记录集
  304. ores = odyn.Update();
  305. //关闭流文件
  306. fs.close();
  307. }
  308. //异常处理
  309. catch(OException E)
  310. {
  311. CString err;
  312. CString err1;
  313. err.Format("%s", (char*)(E.GetFailedMethodName()) );
  314. err1.Format("%s", (char*)(E.GetErrorText()) );
  315. AfxMessageBox(err1);
  316. }
  317. //消除buffer指针
  318. if (buffer)
  319. free(buffer);
  320. }
  321. void CCDlgOracleImageRWDlg::DestroyPhoto()
  322. {
  323. //图像句柄是否为空
  324. if(m_hPhotoBitmap)
  325. {
  326. //如果非空删除
  327. DeleteObject(m_hPhotoBitmap);
  328. //图像句柄置空
  329. m_hPhotoBitmap = NULL;
  330. }
  331. //指向图像内存指针是否为空
  332. if(m_pBMPBuffer)
  333. {
  334. //如果非空,删除
  335. delete m_pBMPBuffer;
  336. //指向图像内存指针置空
  337. m_pBMPBuffer = NULL;
  338. }
  339. }
  340. void CCDlgOracleImageRWDlg::OnAddPhoto() 
  341. {
  342. // TODO: Add your control notification handler code here
  343. //装载选择图像
  344. LoadBMP();
  345. }
  346. void CCDlgOracleImageRWDlg::OnDeletePhoto() 
  347. {
  348. // TODO: Add your control notification handler code here
  349. UpdateData(false);
  350. //关闭打开的记录集
  351. odyn.Close();
  352. //准备SQL语句
  353. CString strQuery;
  354. strQuery.Format("Select * From IMAGE Where ID = '%s'", m_ID);
  355. //打开满足条件的记录集
  356. odyn.Open(odb, strQuery,ODYNASET_DEFAULT); 
  357. //删除满足条件的记录
  358. odyn.DeleteRecord();
  359. //关闭打开的记录集
  360. odyn.Close();
  361. //重新打开记录集
  362. odyn.Open(odb, "SELECT * FROM IMAGE ");
  363. }
  364. void CCDlgOracleImageRWDlg::OnSelectphoto() 
  365. {
  366. // TODO: Add your control notification handler code here
  367. //装载选择图像
  368. LoadBMP();
  369. }
  370. BOOL CCDlgOracleImageRWDlg::LoadBMPFile(const char* pBMPPathname)
  371. {
  372. CFile file;
  373. //打开系统文件上的图像
  374. if( !file.Open( pBMPPathname, CFile::modeRead) )
  375. return FALSE;
  376. //取得文件长度
  377. m_nFileLen = file.GetLength();
  378. //开辟图像文件系统缓冲内存
  379. m_pBMPBuffer = new char[m_nFileLen + 1];
  380. if(!m_pBMPBuffer)
  381. return FALSE;
  382. //读图像文件
  383. if(file.ReadHuge(m_pBMPBuffer,m_nFileLen) != m_nFileLen)
  384. return FALSE;
  385. return TRUE;
  386. }
  387. HBITMAP CCDlgOracleImageRWDlg::BufferToHBITMAP()
  388. {
  389. //BITMAP图像相关定义
  390. HBITMAP hBmp;
  391. LPSTR hDIB,lpBuffer = m_pBMPBuffer;
  392. LPVOID lpDIBBits;
  393. BITMAPFILEHEADER bmfHeader;
  394. DWORD bmfHeaderLen;
  395. //BITMAP图像文件头长度
  396. bmfHeaderLen = sizeof(bmfHeader);
  397. //把内存中数据拷贝到图像数据所指的记录象素数据的指针
  398. strncpy((LPSTR)&bmfHeader,(LPSTR)lpBuffer,bmfHeaderLen);
  399. //判断是否是一幅BMP图像
  400. if (bmfHeader.bfType != (*(WORD*)"BM")) return NULL;
  401. hDIB = lpBuffer + bmfHeaderLen;
  402. BITMAPINFOHEADER &bmiHeader = *(LPBITMAPINFOHEADER)hDIB ;
  403. BITMAPINFO &bmInfo = *(LPBITMAPINFO)hDIB ;
  404. //指针移位至图像数据所指的记录象素数据的位置
  405. lpDIBBits=(lpBuffer)+((BITMAPFILEHEADER *)lpBuffer)->bfOffBits;
  406. LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
  407. //从头文件中获取信息
  408. width= bmInfo.bmiHeader.biWidth;
  409. height =bmInfo.bmiHeader.biHeight;
  410. //获取当前客户区指针
  411. CClientDC dc(this);
  412. //生成BITMAP文件
  413. hBmp = CreateDIBitmap(dc.m_hDC,&bmiHeader,CBM_INIT,lpDIBBits,&bmInfo,DIB_RGB_COLORS);
  414. return hBmp;
  415. }
  416. void CCDlgOracleImageRWDlg::DrawUserPhoto(int x, int y, CDC *pDC)
  417. {
  418. if(!m_hPhotoBitmap) return;
  419. HBITMAP OldBitmap;
  420. CDC MemDC;
  421. MemDC.CreateCompatibleDC(pDC);
  422. OldBitmap=(HBITMAP)MemDC.SelectObject(m_hPhotoBitmap);
  423. //获得ID号为IDC_DRAWBOX的控件的CWnd指针
  424. //并使用它获得相应的设备环境
  425. CWnd *pWnd = GetDlgItem(IDC_Picture);
  426. CDC  *pDC1  = pWnd->GetDC();
  427. CRect conRect;
  428. //获得该控件的矩形区域
  429. ::GetClientRect(pWnd->m_hWnd, conRect);
  430. //将索引值为NULL_BRUSH库存对象选进设备环境
  431. pDC1->SelectStockObject(NULL_BRUSH);
  432. //设置视口原点
  433. pDC1->SetViewportOrg(conRect.left, conRect.top);
  434. // CBitmap *pbitmap=new CBitmap;///////////// no use
  435. // BITMAP  *m_bitmap=new BITMAP;/////////// no use
  436. // pbitmap->FromHandle(OldBitmap)->GetBitmap(m_bitmap);/////// no use
  437. int conW=conRect.right-conRect.left;
  438. int conH=conRect.bottom-conRect.top;
  439. // int w=m_bitmap->bmWidth;
  440. // int h=m_bitmap->bmHeight;
  441. pDC1->StretchBlt(0,0,conW,conH,&MemDC,0,0,width,height,SRCCOPY);
  442. MemDC.SelectObject(OldBitmap);
  443. pWnd->ReleaseDC(pDC1);
  444. // delete m_bitmap;///////////// no use
  445. // delete pbitmap;///////////// no use
  446. /////////////////////////////////////////////////////////////////////////////////
  447. }
  448. void CCDlgOracleImageRWDlg::ResetControls()
  449. {
  450. //是否是记录集的第一个记录
  451. BOOL IsFirstRecord =odyn.IsFirst();
  452. //是否是记录集的第二个记录
  453. BOOL IsLastRecord = odyn.IsLast();
  454. }
  455. void CCDlgOracleImageRWDlg::ReadData()
  456. {
  457. //消除图像指针,确保缓存为空
  458. DestroyPhoto();
  459. if (!odyn.IsOpen())
  460. {
  461. CString err;
  462. CString err1;
  463. err.Format("%s", (char*)(odb.GetErrorText()) );
  464. err1.Format("%s", (char*)(odb.GetErrorText()) );
  465. AfxMessageBox(err);
  466. AfxMessageBox(err1);
  467. }
  468. ////定义两个变量,保存从Oracle数据库中读出的和两个表字段(ID和NAME)相匹配的字段数据 
  469. char cval1[30]; 
  470. char cval2[30];
  471. //定义一个OBlob 对象
  472. OBlob oblob;
  473. //得到ID字段值
  474. odyn.GetFieldValue("ID", cval1,30);
  475. //得到NAME字段值
  476. odyn.GetFieldValue("NAME", cval2,30);
  477. //把字段值赋给对话框中相应变量
  478. m_ID=cval1;m_Name=cval2;
  479. //取得DATA字段定位指针
  480. odyn.GetFieldValue("DATA", &oblob);
  481. //定义缓冲区指针
  482. unsigned char *buffer = 0;
  483. try
  484. {
  485. //定义数据流对象
  486. fstream fs;
  487. //在文件系统上设定一个文件
  488. fs.open("D:\imageou.bmp", ios::out);
  489. //设置模式
  490. fs.setmode(filebuf::binary);
  491. //取得数据流对象数据合适缓冲值大小
  492. unsigned long size = oblob.GetSize();
  493. // 计算合适的缓冲值大小
  494. unsigned long optchunk = oblob.GetOptimumChunkSize();
  495. unsigned int bufsize = ((int)(32768/optchunk)) *optchunk;
  496. //比较两个缓冲值,取较小的一个
  497. if (bufsize > size)
  498. bufsize = size;
  499. //开辟缓冲区;用分块循环的方法可以减小开辟大块内存
  500. buffer = (unsigned char *)malloc(bufsize);
  501. //设置文件数据流读入方式
  502. oblob.EnableStreaming(size);
  503. //设置文件数据流读入状态
  504. short status= OLOB_NEED_DATA;
  505. //定义一个变量,计算每次读的字节数
  506. unsigned long amtread=0;
  507. while(status == OLOB_NEED_DATA)
  508. {
  509. //从Oracle数据库中读入一块缓冲块大小的数据
  510. amtread = oblob.Read(&status, buffer, bufsize);
  511. //向文件系统写入一块缓冲块大小的数据
  512. fs.write(buffer, amtread);
  513. }
  514. //结束流数据的输入
  515. oblob.DisableStreaming();
  516. //关闭流文件
  517. fs.close();
  518. CString pathname1 ="D:\imageou.bmp";
  519. //消除图像指针,确保缓存为空
  520. DestroyPhoto();
  521. //读入数据
  522. LoadBMPFile(pathname1);
  523. //生成BMP图像
  524. m_hPhotoBitmap = BufferToHBITMAP();
  525. Invalidate();
  526. }
  527. //异常处理
  528. catch(OException E)
  529. {
  530. CString err;
  531. CString err1;
  532. err.Format("%s", (char*)(E.GetFailedMethodName()) );
  533. err1.Format("%s", (char*)(E.GetErrorText()) );
  534. AfxMessageBox(err);
  535. AfxMessageBox(err1);
  536. }
  537. //消除buffer指针
  538. if (buffer)
  539. free(buffer);
  540. //更新控件变量的值
  541. UpdateData(false);
  542. }
  543. void CCDlgOracleImageRWDlg::OnDestroy() 
  544. {
  545. //关闭数据库
  546. odb.Close();
  547. //关闭连接
  548. OShutdown();
  549. CDialog::OnDestroy();
  550. }
  551. void CCDlgOracleImageRWDlg::LoadBMP()
  552. {
  553. static char BASED_CODE szFilter[] = "BMP Files (*.bmp)|*.bmp|All Files (*.*)|*.*||";
  554. CFileDialog dlg(TRUE,"BMP",NULL,  OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,szFilter);
  555. if(dlg.DoModal() == IDOK)
  556. {
  557. //取得系统图像文件路径名
  558. pathname = dlg.GetPathName();
  559. DestroyPhoto();
  560. //读入图像
  561. LoadBMPFile(pathname);
  562. //生成BMP格式的图像
  563. m_hPhotoBitmap = BufferToHBITMAP();
  564. m_bModify = TRUE;
  565. Invalidate();
  566. }
  567. }