1.前言
项目中需要一个类似酷狗安装的更新进度条显示,用win32实现了下,需要美工做三张图,代码比较简单
2.实现
1.用vs2010创建一个win32项目
2.将三张图片放在res文件夹下面,并将其导入到项目中
3.在stdafx.h中增加对gdi的支持
#pragma once
#include "targetver.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#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;
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;
5._tWinMain中对gdi进行初始化
**int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
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.对窗口属性进行修改
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance;
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中对消息的处理主要是针对定时器的
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_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);
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);
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.代码比较简单,也比较随意,打破传统编码从控件继承模式,直接进行图片叠加更直观快捷,仅供参考