VC 中用 IPicture 在窗口中显示图片文件

来源:互联网 发布:淘宝收费的课程靠谱吗 编辑:程序博客网 时间:2024/05/18 22:40
  1. #include <windows.h>  // Windows SDK 要用到的   
  2. #include <commdlg.h>  // 打开文件的窗口要包含这个头文件   
  3.   
  4. //用到了 IPicture 接口,要包含下面两个 头文件   
  5. #include <ocidl.h>    
  6. #include <olectl.h>    
  7.   
  8. // 声明窗口函数的原型   
  9. LRESULT CALLBACK MainWndProc (HWND, UINT, WPARAM, LPARAM);   
  10.   
  11. // 声明显示图片的函数原型   
  12. HRESULT ShowPic(char *lpstrFile,HWND hWnd) ;   
  13.   
  14. //图片文件名   
  15. char lpstrFile[MAX_PATH]="";   
  16.   
  17.   
  18. int WINAPI WinMain (HINSTANCE hThisInstance,   
  19.                     HINSTANCE hPrevInstance,   
  20.                     LPSTR lpszArgument,   
  21.                     int nFunsterStil)   
  22.                        
  23. {   
  24.     // 窗口类名   
  25.     char szClassName[ ] = "ShowPicture";   
  26.        
  27.     WNDCLASSEX windclass;   
  28.        
  29.     //用描述主窗口的参数填充 WNDCLASSEX 结构   
  30.     windclass.cbSize = sizeof(windclass);  //结构大小   
  31.     windclass.hInstance = hThisInstance;   //实例句酚   
  32.     windclass.lpszClassName = szClassName;   
  33.     windclass.lpfnWndProc = MainWndProc;   //窗口函数指针   
  34.     windclass.style = CS_DBLCLKS;          //捕获双击事件   
  35.     windclass.cbSize = sizeof (WNDCLASSEX);   
  36.        
  37.     windclass.hIcon = LoadIcon (NULL, IDI_APPLICATION); //使用预定义图标   
  38.     windclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION); //使用预定义类的小图标   
  39.     windclass.hCursor = LoadCursor (NULL, IDC_ARROW); //使用预定义光标   
  40.     windclass.lpszMenuName = NULL;                 //不指定主菜单   
  41.     windclass.cbClsExtra = 0;                      //没有额外的类内存   
  42.     windclass.cbWndExtra = 0;                      //没有额外的窗口内存   
  43.        
  44.     windclass.hbrBackground = (HBRUSH) COLOR_BACKGROUND; //使用预定义背景画刷   
  45.        
  46.     //注册这个窗口类,如果失败直接退出程序    
  47.     if (!RegisterClassEx (&windclass))   
  48.         return 0;   
  49.        
  50.     //创建主窗口   
  51.     HWND hWnd = CreateWindowEx (   
  52.         0,                   //dwExStyle, 扩展样式   
  53.         szClassName,         //lpClassName, 类名   
  54.         "显示图片 -- 鼠标双击浏览图片文件      -- Author:Unmi"//lpWindowName, 标题   
  55.         WS_OVERLAPPEDWINDOW, //dwStyle, 窗口风格   
  56.         CW_USEDEFAULT,       //X, 初始 X 坐标   
  57.         CW_USEDEFAULT,       //Y, 初始 YX 坐标   
  58.         640,                 //nWidth, 宽度   
  59.         480,                 //nHeight, 高度   
  60.         HWND_DESKTOP,        //hWndParent, 父窗口句柄   
  61.         NULL,                //hMenu, 菜单句柄   
  62.         hThisInstance,       //hInstance, 程序实例句柄   
  63.         NULL                 //lpParam, 用户数据   
  64.         );   
  65.        
  66.     //显示窗口,刷新窗口客户区   
  67.     ShowWindow (hWnd, nFunsterStil);   
  68.        
  69.     // 从消息队列中取出消息,交给窗口函数处理   
  70.     // 直到 GetMessage 取出的消息是 WM_QUIT,即FALSE,则结束消息循环   
  71.     MSG messages;       
  72.     while (GetMessage (&messages, NULL, 0, 0))   
  73.     {   
  74.         //转换键盘消息,把虚拟键转换为字符消息   
  75.         TranslateMessage(&messages);   
  76.            
  77.         //将消息发送到相应的窗口函数   
  78.         DispatchMessage(&messages);   
  79.     }   
  80.        
  81.     // GetMessage 返回 FALSE,程序结束 PostQuitMessage() 发出这一消息   
  82.     return messages.wParam;   
  83. }   
  84.   
  85.   
  86. // 窗口函数,消息由 DispatchMessage 派发   
  87. LRESULT CALLBACK MainWndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)   
  88. {   
  89.     switch (message) //处理消息   
  90.     {   
  91.     case WM_DESTROY:   
  92.         //向消息队列投递一个 WM_QUIT 消息,促使 GetMessage 函数返回0,结束消息循环   
  93.         PostQuitMessage (0);   
  94.         break;   
  95.     case WM_LBUTTONDBLCLK:   
  96.         {   
  97.             OPENFILENAME file = {0};   
  98.             file.lStructSize = sizeof(file);   
  99.             file.lpstrTitle = "请选择一个图片文件";   
  100.             file.lpstrFile = lpstrFile;   
  101.             file.nMaxFile = MAX_PATH;   
  102.             file.lpstrFilter = "Pictures(*.jpg,*.gif,*.bmp)/0*.jpg;*.gif;*.bmp/0/0";   
  103.             if(::GetOpenFileName(&file))   
  104.             {          
  105.                 //清除原来的图像   
  106.                 HDC hdc=GetDC(hWnd);    
  107.                 RECT rect;   
  108.                 ::GetWindowRect(hWnd,&rect);   
  109.                 ::FillRect(hdc,&rect,(HBRUSH) COLOR_BACKGROUND);   
  110.                    
  111.                 ::SendMessage(hWnd,WM_PAINT,NULL,NULL);   
  112.             }   
  113.         }   
  114.         break;   
  115.     case WM_PAINT:   
  116.         ShowPic(lpstrFile,hWnd);   
  117.         break;   
  118.     default:   
  119.            
  120.         //将我们不处理的消息交给系统 做默认处理   
  121.         return DefWindowProc (hWnd, message, wParam, lParam);   
  122.     }   
  123.        
  124.     return 0;   
  125. }   
  126.   
  127. // 显示图片,此文的重点之所在了, lpstrFile 为图片文件名,hWnd 为窗口句柄   
  128. HRESULT ShowPic(char *lpstrFile,HWND hWnd)    
  129. {    
  130.     HDC hDC_Temp=GetDC(hWnd);    
  131.        
  132.     IPicture *pPic;    
  133.     IStream *pStm;    
  134.        
  135.     BOOL bResult;    
  136.        
  137.     HANDLE hFile=NULL;    
  138.     DWORD dwFileSize,dwByteRead;    
  139.        
  140.     //打开图形文件    
  141.     hFile=CreateFile(lpstrFile,GENERIC_READ,    
  142.         FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);    
  143.        
  144.     if (hFile!=INVALID_HANDLE_VALUE)    
  145.     {    
  146.         dwFileSize=GetFileSize(hFile,NULL);//获取文件字节数    
  147.            
  148.         if (dwFileSize==0xFFFFFFFF)    
  149.             return E_FAIL;    
  150.     }    
  151.     else    
  152.     {    
  153.         return E_FAIL;    
  154.     }    
  155.        
  156.        
  157.     //分配全局存储空间    
  158.     HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwFileSize);    
  159.     LPVOID pvData = NULL;    
  160.        
  161.     if (hGlobal == NULL)    
  162.         return E_FAIL;    
  163.        
  164.     if ((pvData = GlobalLock(hGlobal)) == NULL)//锁定分配内存块    
  165.         return E_FAIL;    
  166.        
  167.     ReadFile(hFile,pvData,dwFileSize,&dwByteRead,NULL);//把文件读入内存缓冲区    
  168.        
  169.     GlobalUnlock(hGlobal);    
  170.        
  171.     CreateStreamOnHGlobal(hGlobal, TRUE, &pStm);    
  172.        
  173.     //装入图形文件    
  174.     bResult=OleLoadPicture(pStm,dwFileSize,TRUE,IID_IPicture,(LPVOID*)&pPic);    
  175.        
  176.     if(FAILED(bResult))    
  177.         return E_FAIL;    
  178.        
  179.     OLE_XSIZE_HIMETRIC hmWidth; //图片的真实宽度, 单位为英寸   
  180.     OLE_YSIZE_HIMETRIC hmHeight; //图片的真实高度, 单位为英寸   
  181.     pPic->get_Width(&hmWidth);    
  182.     pPic->get_Height(&hmHeight);    
  183.        
  184.     //转换hmWidth和hmHeight为pixels距离,1英寸=25.4毫米   
  185.     int nWidth = MulDiv(hmWidth,GetDeviceCaps(hDC_Temp,LOGPIXELSX),2540);   
  186.     int nHeight = MulDiv(hmHeight,GetDeviceCaps(hDC_Temp,LOGPIXELSY),2540);   
  187.        
  188.     //将图形输出到屏幕上(有点像BitBlt)    
  189.     bResult=pPic->Render(hDC_Temp,0,0,nWidth,nHeight,    
  190.         0,hmHeight,hmWidth,-hmHeight,NULL);    
  191.        
  192.     pPic->Release();    
  193.        
  194.     CloseHandle(hFile);//关闭打开的文件    
  195.        
  196.     if (SUCCEEDED(bResult))    
  197.     {    
  198.         return S_OK;    
  199.     }    
  200.     else    
  201.     {    
  202.         return E_FAIL;    
  203.     }    
  204. }