VC 中用 IPicture 在窗口中显示图片文件
想做个东西,用VC,希望是在程序界面上能把指定 URL 的图片显示出来,还没找到如何显示 HTTP 资源的图片,先还是让本地图片能在 VC 的窗口(包括各种控件)中显示出来吧。在网上搜索了一番,大家代码都如出一辙,我也不能生搬硬载,不由又亲手实践了一下,并连同原来学过的 Window SDK 做窗口程序也复习了一遍,没有使用到 MFC,只需存成单个源文件,甚至用 CL 命令来编译都无须打开 VC 的,在 VC6 中测试通过。
效果图如下:

代码如下:(仅需关键最后一个方法 ShowPic(char *lpstrFile, HWND hWnd))
函数 HRESULT ShowPic(char *lpstrFile,HWND hWnd) 是本日志要义之所在,传入文件名和窗口句柄(比如按或者静态文本框的句柄亦可),然后会在指定窗口中按图片实际尺寸显示出来。
注意,必须包含头文件 ocidl.h 和 olectl.h 。关键的方法只有 ShowPic,其余的代码只不过为我练手之用,权可当是累赘。以上实现的是在主窗口中显示图片,图片格式暂定为允许选择JPG/GIF/BMP三种,其他没一一尝试,不过我想只要 IE 中能支持的图片式在此应无问题。
操作方法是:在窗口中双击鼠标左键就会弹出图片选择窗口,选择适当的图片就会在窗口中显示。目前只是读取图片文件显示,期待中的是下一步显示内存中的图片数据字节数组或流,进而给个 HTTP 协议的图片 URL 就能正确显示,那么在这个小范围内的研究对我说算是一个小突破。
现在想来,好像都不是问题,只是不同的 File HANDLE 而已,通过 CInternetSession 读取图片 URL 也会是生成一个 FILE HANDLE,交给 ReadFile 去读取就行了,晚上回去试一试。
参考:1. 在MFC程序中显示JPG/GIF图像
2. 用IPicture显示图片
3. 利用IPicture接口加载、显示图片
4. VC下显示JPEG、GIF图像的简便方法
5. cool !!!! 在VC中显示JPEG和GIF图像 永久链接 https://yanbin.blog/vc-ipicture-show-picture/, 来自 隔叶黄莺 Yanbin's Blog
[版权声明]
本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。
效果图如下:
代码如下:(仅需关键最后一个方法 ShowPic(char *lpstrFile, HWND hWnd))
1#include <windows.h> // Windows SDK 要用到的
2#include <commdlg.h> // 打开文件的窗口要包含这个头文件
3
4//用到了 IPicture 接口,要包含下面两个 头文件
5#include <ocidl.h>
6#include <olectl.h>
7
8// 声明窗口函数的原型
9LRESULT CALLBACK MainWndProc (HWND, UINT, WPARAM, LPARAM);
10
11// 声明显示图片的函数原型
12HRESULT ShowPic(char *lpstrFile,HWND hWnd) ;
13
14//图片文件名
15char lpstrFile[MAX_PATH]="";
16
17
18int 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 派发
87LRESULT 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 为窗口句柄
128HRESULT 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}函数 HRESULT ShowPic(char *lpstrFile,HWND hWnd) 是本日志要义之所在,传入文件名和窗口句柄(比如按或者静态文本框的句柄亦可),然后会在指定窗口中按图片实际尺寸显示出来。
注意,必须包含头文件 ocidl.h 和 olectl.h 。关键的方法只有 ShowPic,其余的代码只不过为我练手之用,权可当是累赘。以上实现的是在主窗口中显示图片,图片格式暂定为允许选择JPG/GIF/BMP三种,其他没一一尝试,不过我想只要 IE 中能支持的图片式在此应无问题。
操作方法是:在窗口中双击鼠标左键就会弹出图片选择窗口,选择适当的图片就会在窗口中显示。目前只是读取图片文件显示,期待中的是下一步显示内存中的图片数据字节数组或流,进而给个 HTTP 协议的图片 URL 就能正确显示,那么在这个小范围内的研究对我说算是一个小突破。
现在想来,好像都不是问题,只是不同的 File HANDLE 而已,通过 CInternetSession 读取图片 URL 也会是生成一个 FILE HANDLE,交给 ReadFile 去读取就行了,晚上回去试一试。
参考:1. 在MFC程序中显示JPG/GIF图像
2. 用IPicture显示图片
3. 利用IPicture接口加载、显示图片
4. VC下显示JPEG、GIF图像的简便方法
5. cool !!!! 在VC中显示JPEG和GIF图像 永久链接 https://yanbin.blog/vc-ipicture-show-picture/, 来自 隔叶黄莺 Yanbin's Blog
[版权声明]
本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。