Win32加载图片到窗口

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;
}

效果如下:
在这里插入图片描述

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Win32应用程序中加载rc文件中的对话框,可以按照以下步骤进行操作: 1. 创建一个对话框资源文件(通常具有.rc扩展名),其中包含对话框的描述。在资源文件中,使用对话框模板定义对话框的布局和控件。 2. 在你的应用程序的资源文件(通常是一个.rc文件)中添加对话框资源,使用`DIALOG`关键字指定对话框的ID和属性。例如: ``` IDD_MYDIALOG DIALOG DISCARDABLE 0, 0, 200, 150 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "My Dialog" FONT 8, "MS Shell Dlg" BEGIN // 对话框中的控件定义 // ... END ``` 3. 在你的代码中使用`CreateDialog`或`DialogBox`函数加载并创建对话框。这些函数会根据资源ID加载并显示对话框。 ```cpp #include <Windows.h> // ... // 使用CreateDialog函数加载并创建对话框 HWND hDlg = CreateDialog(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_MYDIALOG), hWndParent, DialogProc); if (hDlg == NULL) { // 处理错误 } // 或者使用DialogBox函数加载并创建对话框 INT_PTR result = DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_MYDIALOG), hWndParent, DialogProc); if (result == -1) { // 处理错误 } // ... // 对话框过程函数 INT_PTR CALLBACK DialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { // 处理对话框消息 // ... } return FALSE; // 返回FALSE表示未处理的消息将由系统处理 } ``` 以上代码中的`IDC_MYDIALOG`是对话框资源的ID,`hWndParent`是对话框的父窗口句柄,`DialogProc`是对话框过程函数,用于处理对话框消息。 这样,你就可以在Win32应用程序中加载rc文件里的对话框了。记得根据实际情况进行相应的修改和处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值