win32实现类酷狗安装的进度条显示

来源:互联网 发布:image lab for mac 编辑:程序博客网 时间:2024/06/07 09:39

1.前言

项目中需要一个类似酷狗安装的更新进度条显示,用win32实现了下,需要美工做三张图,代码比较简单

2.实现

1.用vs2010创建一个win32项目

2.将三张图片放在res文件夹下面,并将其导入到项目中

3.在stdafx.h中增加对gdi的支持

// stdafx.h : 标准系统包含文件的包含文件,// 或是经常使用但不常更改的// 特定于项目的包含文件//#pragma once#include "targetver.h"#define WIN32_LEAN_AND_MEAN             //  从 Windows 头文件中排除极少使用的信息// Windows 头文件:#include <windows.h>// C 运行时头文件#include <stdlib.h>#include <malloc.h>#include <memory.h>#include <tchar.h>#include <locale.h>#include <olectl.h>#include <assert.h>#include <gdiplus.h>#pragma comment(lib,"gdiplus.lib")using namespace Gdiplus;// TODO: 在此处引用程序需要的其他头文件

4.对变量函数进行声明

void SetBackground(HWND m_hWnd);  //实现图片叠加显示DWORD dw_main = IDB_PNG1;         //底图DWORD dw_process = IDB_PNG2;      //部分进度条DWORD dw_count = 0;               //当前显示的进度DWORD dw_max = 20;                //最大刻度值DWORD dw_x = 20;                  //进度条在图片上的水平起始坐标DWORD dw_y  = 310;                //进度条在图片上的垂直起始坐标#define ID_PROCESS_TIMER   200    //进度条定时器ULONG_PTR gdiplusToken = 0;       //gdi全局变量

5._tWinMain中对gdi进行初始化

**int APIENTRY _tWinMain(HINSTANCE hInstance,                     HINSTANCE hPrevInstance,                     LPTSTR    lpCmdLine,                     int       nCmdShow){    UNREFERENCED_PARAMETER(hPrevInstance);    UNREFERENCED_PARAMETER(lpCmdLine);    // TODO: 在此放置代码。    Gdiplus::GdiplusStartupInput gdiplusStartupInput;    Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);    MSG msg;    HACCEL hAccelTable;    // 初始化全局字符串    LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);    LoadString(hInstance, IDC_LIKEKUGOU, szWindowClass, MAX_LOADSTRING);    MyRegisterClass(hInstance);    // 执行应用程序初始化:    if (!InitInstance (hInstance, nCmdShow))    {        return FALSE;    }    hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_LIKEKUGOU));    // 主消息循环:    while (GetMessage(&msg, NULL, 0, 0))    {        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))        {            TranslateMessage(&msg);            DispatchMessage(&msg);        }    }    Gdiplus::GdiplusShutdown(gdiplusToken);    return (int) msg.wParam;}

6.对窗口属性进行修改

////   函数: InitInstance(HINSTANCE, int)////   目的: 保存实例句柄并创建主窗口////   注释:////        在此函数中,我们在全局变量中保存实例句柄并//        创建和显示主程序窗口。//BOOL InitInstance(HINSTANCE hInstance, int nCmdShow){   HWND hWnd;   hInst = hInstance; // 将实例句柄存储在全局变量中   //hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,   //   CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);   hWnd = CreateWindowEx(WS_EX_LAYERED, szWindowClass, szTitle, WS_POPUPWINDOW,       CW_USEDEFAULT, CW_USEDEFAULT,        CW_USEDEFAULT, CW_USEDEFAULT,        NULL, NULL, (HINSTANCE)::GetModuleHandle(NULL), 0);   if (!hWnd)   {      return FALSE;   }   ShowWindow(hWnd, nCmdShow);   UpdateWindow(hWnd);   return TRUE;}

7.wndproc中对消息的处理主要是针对定时器的

////  函数: WndProc(HWND, UINT, WPARAM, LPARAM)////  目的: 处理主窗口的消息。////  WM_COMMAND  - 处理应用程序菜单//  WM_PAINT    - 绘制主窗口//  WM_DESTROY  - 发送退出消息并返回////LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){    int wmId, wmEvent;    PAINTSTRUCT ps;    HDC hdc;    switch (message)    {    case WM_CREATE:        {            LONG styleValue = ::GetWindowLong(hWnd, GWL_STYLE);            styleValue &= ~WS_CAPTION;            styleValue &= ~WS_MAXIMIZEBOX;             styleValue &= ~WS_MINIMIZEBOX;             styleValue &= ~WS_THICKFRAME;             styleValue &= ~WS_BORDER;             styleValue &= ~WS_CAPTION;            ::SetWindowLong(hWnd, GWL_STYLE, styleValue | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);            int scrWidth = GetSystemMetrics ( SM_CXSCREEN );             int scrHeight = GetSystemMetrics ( SM_CYSCREEN );             int nleft = (scrWidth - 580) / 2;            int ntop  = (scrHeight - 380) / 2;            SetWindowPos(hWnd, HWND_TOPMOST, nleft, ntop, 580, 380, SWP_SHOWWINDOW);            InvalidateRect(hWnd, NULL, TRUE);            UpdateWindow(hWnd);            //这里开一个定时器测试下效果 看下情况.            SetTimer(hWnd, ID_PROCESS_TIMER, 500, NULL);            break;        }    case WM_TIMER:        {            if (wParam == ID_PROCESS_TIMER)            {                dw_count += (dw_count % 3+1);                if (dw_count > dw_max)                {                    //dw_count = dw_max;                    dw_main = IDB_PNG3;                    KillTimer(hWnd, ID_PROCESS_TIMER);                    InvalidateRect(hWnd, NULL, TRUE);                    UpdateWindow(hWnd);                    Sleep(1000);                    SendMessage(hWnd, WM_CLOSE, 0, 0);                    break;                }                InvalidateRect(hWnd, NULL, TRUE);                UpdateWindow(hWnd);            }            break;        }    case WM_COMMAND:        wmId    = LOWORD(wParam);        wmEvent = HIWORD(wParam);        // 分析菜单选择:        switch (wmId)        {        case IDM_ABOUT:            DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);            break;        case IDM_EXIT:            DestroyWindow(hWnd);            break;        default:            return DefWindowProc(hWnd, message, wParam, lParam);        }        break;    case WM_PAINT:        hdc = BeginPaint(hWnd, &ps);        // TODO: 在此添加任意绘图代码...        SetBackground(hWnd);        EndPaint(hWnd, &ps);        break;    case WM_DESTROY:        PostQuitMessage(0);        break;    default:        return DefWindowProc(hWnd, message, wParam, lParam);    }    return 0;}

8.对底图和进度条进行图片叠加显示

void SetBackground(HWND m_hWnd){    HMODULE hInstance = ::GetModuleHandle(NULL);    HRSRC hRsrc = ::FindResource(hInstance, MAKEINTRESOURCE(dw_main), _T("PNG"));     DWORD dwSize = ::SizeofResource(hInstance, hRsrc);    LPBYTE lpRsrc = (LPBYTE)::LoadResource(hInstance, hRsrc);    HGLOBAL hMem = ::GlobalAlloc(GMEM_FIXED, dwSize);    LPBYTE pMem = (LPBYTE)::GlobalLock(hMem);    memcpy(pMem, lpRsrc, dwSize);    IStream* pStream = NULL;    ::CreateStreamOnHGlobal( hMem, TRUE, &pStream );    Gdiplus::Image* pImage =  Gdiplus::Image::FromStream(pStream);    if (pImage==NULL)        assert(false && _T("error in FromStream."));    HRSRC hRww = ::FindResource(hInstance, MAKEINTRESOURCE(dw_process), _T("PNG"));     DWORD dwWwSize = ::SizeofResource(hInstance, hRww);    LPBYTE lpRww = (LPBYTE)::LoadResource(hInstance, hRww);    HGLOBAL hWwMem = ::GlobalAlloc(GMEM_FIXED, dwWwSize);    LPBYTE pWwMem = (LPBYTE)::GlobalLock(hWwMem);    memcpy(pWwMem, lpRww, dwWwSize);    IStream* pWwStream = NULL;    ::CreateStreamOnHGlobal( hWwMem, TRUE, &pWwStream );    Gdiplus::Image* pWwImage =  Gdiplus::Image::FromStream(pWwStream);    if (pWwImage==NULL)        assert(false && _T("error in FromStream."));    RECT windowRect;    GetWindowRect(m_hWnd,&windowRect);    SIZE sizeWindow;    if (windowRect.left==windowRect.right)    {        sizeWindow.cx=pImage->GetWidth();        sizeWindow.cy=pImage->GetHeight();    }else    {        sizeWindow.cx=windowRect.right-windowRect.left;        sizeWindow.cy=windowRect.bottom-windowRect.top;    }    HDC hDC = ::GetDC(m_hWnd);    HDC hdcMemory = CreateCompatibleDC(hDC);    RECT rcWindow;    GetWindowRect(m_hWnd,&rcWindow);    BITMAPINFOHEADER stBmpInfoHeader = { 0 };       int nBytesPerLine = ((sizeWindow.cx * 32 + 31) & (~31)) >> 3;    stBmpInfoHeader.biSize = sizeof(BITMAPINFOHEADER);       stBmpInfoHeader.biWidth = sizeWindow.cx;       stBmpInfoHeader.biHeight = sizeWindow.cy;       stBmpInfoHeader.biPlanes = 1;       stBmpInfoHeader.biBitCount = 32;       stBmpInfoHeader.biCompression = BI_RGB;       stBmpInfoHeader.biClrUsed = 0;       stBmpInfoHeader.biSizeImage = nBytesPerLine * sizeWindow.cy;       PVOID pvBits = NULL;       HBITMAP hbmpMem = ::CreateDIBSection(NULL, (PBITMAPINFO)&stBmpInfoHeader, DIB_RGB_COLORS, &pvBits, NULL, 0);    assert(hbmpMem != NULL);    HGDIOBJ hbmpOld = ::SelectObject( hdcMemory, hbmpMem);    POINT ptWinPos = { rcWindow.left, rcWindow.top };    Gdiplus::Graphics graph(hdcMemory);    graph.SetSmoothingMode(Gdiplus::SmoothingModeNone);    graph.DrawImage(pImage, 0, 0, sizeWindow.cx, sizeWindow.cy);    //20,310,560,316    int process_width = pWwImage->GetWidth();    int process_height = pWwImage->GetHeight();    if (dw_count <= dw_max)    {        for (int nindex = 0; nindex < dw_count; ++nindex)            graph.DrawImage(pWwImage, dw_x + nindex * process_width, dw_y, process_width, process_height);    }    HMODULE hFuncInst = LoadLibrary(_T("User32.DLL"));    typedef BOOL (WINAPI *MYFUNC)(HWND, HDC, POINT*, SIZE*, HDC, POINT*, COLORREF, BLENDFUNCTION*, DWORD);              MYFUNC UpdateLayeredWindow;    UpdateLayeredWindow = (MYFUNC)::GetProcAddress(hFuncInst, "UpdateLayeredWindow");    POINT ptSrc = { 0, 0};    BLENDFUNCTION blendFunc;    blendFunc.BlendOp = 0;    blendFunc.BlendFlags = 0;    blendFunc.AlphaFormat = 1;    blendFunc.SourceConstantAlpha = 255;    if(!UpdateLayeredWindow(m_hWnd, hDC, &ptWinPos, &sizeWindow, hdcMemory, &ptSrc, 0, &blendFunc, ULW_ALPHA))        assert(L"UpdateLayeredWindow failed.");    SelectObject( hdcMemory, hbmpOld);     DeleteObject(hbmpMem);     DeleteDC(hdcMemory);    ReleaseDC(m_hWnd, hDC);    FreeLibrary(hFuncInst);    if (pImage != NULL)        delete pImage;    pStream->Release();    ::GlobalUnlock(hMem);    if (pWwImage != NULL)        delete pWwImage;    pWwStream->Release();    ::GlobalUnlock(hWwMem);}

3.备注

1.http://download.csdn.net/detail/zhang_ruiqiang/9826938
2.代码比较简单,也比较随意,打破传统编码从控件继承模式,直接进行图片叠加更直观快捷,仅供参考
0 0