win32加载图片到窗口是一个很麻烦的问题,我们可以在窗口上绘制各种直线、圆圈、矩形,还可以填充颜色,但是加载图片和视频做成播放器或者阅读器则需要另外的库,废话不多说,上代码:
建立一个加载图片的类,我已经封装好了,大家免费使用。类名:GdiLoadImageCls
1、头文件:GdiLoadCls.h
#pragma once
#include"framework.h"
#include <shlwapi.h> // SHCreateStreamOnFile
#pragma comment (lib, "shlwapi")
#include "gdiplus.h"
using namespace Gdiplus;
#pragma comment(lib, "gdiplus.lib")
#include <Uxtheme.h> // BeginBufferedPaint
#pragma comment(lib,"Uxtheme")
class GdiLoadImageCls
{
public:
int mWidth = 800;
int mHeight = 600;
int nBitmapWidth = 0 ;
int nBitmapHeight = 0;
float nScale = 1;//图片的放大缩小参数
int nPos = 0;//图片的位置参数
Bitmap* pBitmap = NULL;
public:
GdiLoadImageCls();
~GdiLoadImageCls();
//加载图片到内存当中
bool mLoadImageA(const char* szFilename);
//加载图片到内存当中
bool mLoadImageW(const wchar_t* wszFilename);
//绘制图像到hWnd窗口上
// HWND hWnd要加载图片的目标窗口
//HDC hDC来自于hWnd窗口WM_PAINT消息下面的:HDC hDC = BeginPaint(hWnd, &ps);
void OnPaint(HWND hWnd, HDC hDC);
void OnMouseWheel(HWND hWnd, WPARAM wParam);
};
2、cpp文件:GdiLoadCls.cpp
#include "GdiLoadCls.h"
//加载图片到内存当中
bool GdiLoadImageCls::mLoadImageA(const char* szFilename)
{
//WCHAR wszURL[MAX_PATH] = TEXT("https://image.ibb.co/buLv2e/Little_Girl3.jpg");
//WCHAR wszFilename[MAX_PATH];//bjzm_1.bmp
//wsprintfW(wszFilename, L"bjzm_1.bmp");
这个函数以后要慢慢研究,很可能是http下载文件的简单手段:
//HRESULT hr = URLDownloadToCacheFileW(NULL, wszURL, wszFilename, ARRAYSIZE(wszFilename), 0x0, NULL);
//if (SUCCEEDED(hr))
{
IStream* pStream = NULL;
HRESULT hr = SHCreateStreamOnFileA(szFilename, STGM_READ | STGM_SHARE_DENY_WRITE, &pStream);
if (SUCCEEDED(hr))
{
if (!pBitmap)//前面有加载过等图片,指针还没有销毁
{
//先把旧的销毁掉
delete pBitmap;
pBitmap = nullptr;
}
MessageBoxA(NULL, "1、我们要创建Bitmap对象指针pBitmap了!", "1", MB_OK);
pBitmap = new Gdiplus::Bitmap(pStream);//为什么创建不成功???
if (pBitmap)
{
MessageBoxA(NULL, "2、创建Bitmap对象指针pBitmap!", "2", MB_OK);
nBitmapWidth = (int)pBitmap->GetWidth();
nBitmapHeight = (int)pBitmap->GetHeight();
return TRUE;
}
else
{
MessageBoxA(NULL, "3、创建Bitmap对象指针pBitmap没有成功!", "3", MB_OK);
return FALSE ;
}
}
else
MessageBoxA(NULL, "4、SHCreateStreamOnFileA()函数调用失败了!", "4", MB_OK);
}
//不使用类的情况下,这个函数返回一个new出来的Bitmap*指针,也可以
}
//加载图片到内存当中
//存在的问题,每加载一个新的图片就要:pBitmap = new Gdiplus::Bitmap(pStream);
//那么就需要判断这个指针是否为空指针
bool GdiLoadImageCls::mLoadImageW(const wchar_t* wszFilename)
{
//WCHAR wszURL[MAX_PATH] = TEXT("https://image.ibb.co/buLv2e/Little_Girl3.jpg");
//WCHAR wszFilename[MAX_PATH];//bjzm_1.bmp
//wsprintfW(wszFilename, L"bjzm_1.bmp");
//HRESULT hr = URLDownloadToCacheFileW(NULL, wszURL, wszFilename, ARRAYSIZE(wszFilename), 0x0, NULL);
//if (SUCCEEDED(hr))
{
IStream* pStream = NULL;
HRESULT hr = SHCreateStreamOnFileW(wszFilename, STGM_READ | STGM_SHARE_DENY_WRITE, &pStream);
if (SUCCEEDED(hr))
{
MessageBoxA(NULL, "1、我们要创建Bitmap对象指针pBitmap了!", "1", MB_OK);
pBitmap = new Gdiplus::Bitmap(pStream);//为什么创建不成功???
if (pBitmap)//不成功???
{
MessageBoxA(NULL, "2、创建Bitmap对象指针pBitmap!", "2", MB_OK);
nBitmapWidth = (int)pBitmap->GetWidth();
nBitmapHeight = (int)pBitmap->GetHeight();
return TRUE;
}
else
{
MessageBoxA(NULL, "3、创建Bitmap对象指针pBitmap没有成功!", "3", MB_OK);
return FALSE;
}
}
else
MessageBoxA(NULL, "4、SHCreateStreamOnFileW()函数调用失败!", "4", MB_OK);
}
}
//绘制图像到hWnd窗口上
// HWND hWnd要加载图片的目标窗口
//HDC hDC来自于hWnd窗口WM_PAINT消息下面的:HDC hDC = BeginPaint(hWnd, &ps);
void GdiLoadImageCls::OnPaint(HWND hWnd, HDC hDC)
{
RECT rcClient;
GetClientRect(hWnd, &rcClient);
if (pBitmap)
{
HDC targetDC = hDC;
HDC bufferedDC = NULL;
HRESULT hr = S_OK;
HPAINTBUFFER pb = BeginBufferedPaint(targetDC, &rcClient, BPBF_TOPDOWNDIB, 0, &bufferedDC);
Graphics* g = new Graphics(bufferedDC);
if (g && g->GetLastStatus() == Ok)
{
g->Clear(Color(255, 255, 255));
int nX = 0;//好,不会改变图片的位置
int nY = nPos;//好,改变图片的纵向位置
// g->DrawImage(pBitmap, nX, nY, (int)(nBitmapWidth), (int)(nBitmapHeight));
g->DrawImage(pBitmap, nX, nY, (int)(nBitmapWidth * nScale), (int)(nBitmapHeight * nScale));
delete g;
}
hr = EndBufferedPaint(pb, TRUE);
}
}
//响应WM_MOUSEWHEEL消息,鼠标滚轮转动,图片放大缩小
void GdiLoadImageCls::OnMouseWheel(HWND hWnd, WPARAM wParam)
{
static int nDelta = 0;
nDelta += GET_WHEEL_DELTA_WPARAM(wParam);
if (abs(nDelta) >= WHEEL_DELTA)
{
if (nDelta > 0)
{
//nScale *= 1.1f;//横向放大、缩小10%
// nScale *= 2.2f;//横向缩小
nPos -= 10;
}
else
{
//nScale /= 1.1f;//缩小%10
nPos += 10;
}
nDelta = 0;
InvalidateRect(hWnd, NULL, FALSE);
}
}
GdiLoadImageCls::GdiLoadImageCls()
{
//非常重要:没有下面这3行代码,程序不会报错,但是页不会按照你的设计运行
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
}
GdiLoadImageCls::~GdiLoadImageCls()
{
if (!pBitmap)//前面有加载过等图片,指针还没有销毁
{
//先把旧的销毁掉
delete pBitmap;
pBitmap = nullptr;
}
}
3、win32程序调用类实现图片处理的三步
(1)在窗口过程函数里面创建类对象
static GdiLoadImageCls gdiCls;//创建一个GdiLoadImageCls类对象
(2)在WM_CREATE消息下面加载图片到内存:
//加载我的电脑里面的一张图片:三星堆神树
gdiCls.mLoadImageA(“C:\Users\HIPAA\Pictures\三星堆\神树\200852815310.jpg”);
(3)在WM_PAINT消息下面把图片绘制到窗口:
gdiCls.OnPaint(hWnd, hdc);//加载图片
上代码:这是微软官方的一个win32示例程序,
// GT_HelloWorldWin32.cpp
// compile with: /D_UNICODE /DUNICODE /DWIN32 /D_WINDOWS /c
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>
#include"GdiLoadCls.h"
// Global variables
// The main window class name.
static TCHAR szWindowClass[] = _T("win32app");
// The string that appears in the application's title bar.
static TCHAR szTitle[] = _T("Win32 Guided Tour Application");
HINSTANCE hInst;
// Forward declarations of functions included in this code module:
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
if (!RegisterClassEx(&wcex))
{
MessageBox(NULL,_T("Call to RegisterClassEx failed!"),_T("Win32 Guided Tour"),NULL);
return 1;
}
hInst = hInstance; // Store instance handle in our global variable
// The parameters to CreateWindow explained:
// szWindowClass: the name of the application
// szTitle: the text that appears in the title bar
// WS_OVERLAPPEDWINDOW: the type of window to create
// CW_USEDEFAULT, CW_USEDEFAULT: initial position (x, y)
// 500, 100: initial size (width, length)
// NULL: the parent of this window
// NULL: this application does not have a menu bar
// hInstance: the first parameter from WinMain
// NULL: not used in this application
HWND hWnd = CreateWindowW(szWindowClass,szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL,NULL, hInstance, NULL);
if (!hWnd)
{
MessageBoxA(NULL,"Win32程序没有创建成功!!!","Win32 Guided Tour", NULL);
return 1;
}
// The parameters to ShowWindow explained:
// hWnd: the value returned from CreateWindow
// nCmdShow: the fourth parameter from WinMain
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
// Main message loop:
MSG msg;
while (GetMessageA(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessageA(&msg);
}
return (int)msg.wParam;
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static GdiLoadImageCls gdiCls;//创建一个GdiLoadImageCls类对象
PAINTSTRUCT ps;
HDC hdc;
CHAR greeting[] = "这是微软官方提供的一个空白win32程序";
switch (message)
{
case WM_CREATE:
{
//加载我的电脑里面一张图片,三星堆神树
gdiCls.mLoadImageA("C:\\Users\\HIPAA\\Pictures\\三星堆\\神树\\200852815310.jpg");
}
break;
case WM_LBUTTONDOWN:
{
//win32程序验证的重要手段
MessageBoxA(NULL, "鼠标点击窗口的消息\nwin32程序验证的重要手段", "点击加载图片", MB_OK);
//加载图片
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// Here your application is laid out.
// For this introduction, we just print out "Hello, World!"
// in the top left corner.
//TextOut(hdc, 5, 5, greeting, _tcslen(greeting)); //字符串为TCHAR类型的输出
TextOutA(hdc, 5, 5, greeting, strlen(greeting)); //字符串为CHAR类型的输出
// End application-specific layout section.
gdiCls.OnPaint(hWnd, hdc);//加载图片
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}
return 0;
}
效果如下: