//CRgnBitmap.h
#ifndef RGN_BITMAP_H
#define RGN_BITMAP_H
#include <windows.h>
class CRgnBitmap
{
public:
CRgnBitmap();
~CRgnBitmap();
bool LoadBmp(HINSTANCE hInstance, LPCSTR lp);
HRGN GetRgn(HWND hwnd);
HBITMAP GetHBitmap();
int GetWidth();
int GetHeight();
private:
HBITMAP m_hBitmap;
int m_width;
int m_height;
};
inline HBITMAP CRgnBitmap::GetHBitmap()
{
return m_hBitmap;
}
inline int CRgnBitmap::GetWidth()
{
return m_width;
}
inline int CRgnBitmap::GetHeight()
{
return m_height;
}
#endif
//================================
//CRgnBitmap.cpp
#include "CRgnBitmap.h"
/**
* 构造函数.
*/
CRgnBitmap::CRgnBitmap()
: m_hBitmap(NULL),
m_width(0),
m_height(0)
{
}
/**
* 析构函数.
*/
CRgnBitmap::~CRgnBitmap()
{
if (m_hBitmap != NULL)
{
DeleteObject(m_hBitmap);
m_hBitmap = NULL;
}
}
bool CRgnBitmap::LoadBmp(HINSTANCE hInstance, LPCSTR lp)
{
m_hBitmap = LoadBitmap(hInstance, lp);
if (m_hBitmap == NULL)
{
return false;
}
BITMAP bitmap;
GetObject(m_hBitmap, sizeof(BITMAP), &bitmap); //得到位图数据
m_width = bitmap.bmWidth;
m_height = bitmap.bmHeight;
return true;
}
/**
* 获得一个由位图创建的区域
*/
HRGN CRgnBitmap::GetRgn(HWND hwnd)
{
HDC hdc = GetDC(hwnd);
HDC ExterDC = CreateCompatibleDC(hdc);
BITMAP backBitmap;
GetObject(m_hBitmap, sizeof(BITMAP), &backBitmap); //得到位图数据
SelectObject(ExterDC, m_hBitmap); //把位图选进 ExterDC
RECT rect;
GetClientRect(hwnd, &rect); //得到窗口原点坐标
//计算区域的原点
int rgn_x0 = rect.left + GetSystemMetrics(SM_CYFIXEDFRAME); //加上左边框
int rgn_y0 = rect.top + GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYFIXEDFRAME); //加上上边框和标题栏
//创建一个容纳位图的区域.Region的坐标是在窗口范围内的坐标。
HRGN bitmapRgn = CreateRectRgn(rgn_x0, rgn_y0, rgn_x0+m_width, rgn_y0+m_height);
COLORREF diffColor = 0x00a63000; //透明色 0x00bbggrr
COLORREF colorRef; //颜色值
int width = 0;
//扫描所有像素,去除图像内部的空白
for(int j = 0; j < m_height; j++) //从上到下
{
width = 0;
for(int i = 0; i <= m_width; i++) //从左到右
{
colorRef = GetPixel(ExterDC, i, j);
if((i > backBitmap.bmWidth-1 || colorRef != diffColor) && width != 0)
{
HRGN tmpRgn = CreateRectRgn(rgn_x0+i-width, rgn_y0+j, rgn_x0+i, rgn_y0+j+1); //rgn不包括底边和右边
CombineRgn(bitmapRgn, tmpRgn, bitmapRgn, RGN_XOR);
DeleteObject(tmpRgn);
width = 0;
}
if(colorRef == diffColor)
{
width++; //长度
}
}
}
DeleteDC(ExterDC);
ReleaseDC(hwnd, hdc);
return bitmapRgn;
}
//================
//main.cpp
// BeatufulGUI.cpp : 定义应用程序的入口点。
//
#include "BeatufulGUI.h"
#include "CRgnBitmap.h"
#define MAX_LOADSTRING 100
// 全局变量:
HINSTANCE hInst; // 当前实例
CRgnBitmap* g_pBgRgnBitmap;
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_BEATUFULGUI));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_BACKGROUND);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_BEATUFULGUI);
wcex.lpszClassName = "BmpWindow";
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
RegisterClassEx(&wcex);
// 执行应用程序初始化:
if (!InitInstance (hInstance, nCmdShow))
{
return 0;
}
// 主消息循环:
BOOL bRet;
MSG msg;
while ( (bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
{
if (bRet == -1)
{
//fatal error
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
///*
//If the function retrieves a message other than WM_QUIT, the return value is nonzero.
//If the function retrieves the WM_QUIT message, the return value is zero.
//If there is an error, the return value is -1. For example, the function fails if hWnd is an invalid window handle or lpMsg is an invalid pointer.
//To get extended error information, call GetLastError.
//Warning
//Because the return value can be nonzero, zero, or -1, avoid code like this:
//while (GetMessage( lpMsg, hWnd, 0, 0)) ...
// The possibility of a -1 return value means that such code can lead to fatal application errors.
//*/
return (int) msg.wParam;
}
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // 将实例句柄存储在全局变量中
//开始用背景图的数据,计算窗口的尺寸和位置
g_pBgRgnBitmap = new CRgnBitmap();
g_pBgRgnBitmap->LoadBmp(hInst, (LPCSTR)IDB_BITMAP_BACK);
//获取桌面大小,以便窗口显示在中间
int DesktopWidth = GetSystemMetrics(SM_CXSCREEN);
int DesktopHeight = GetSystemMetrics(SM_CYSCREEN);
//窗口的尺寸
int WindowWidth = g_pBgRgnBitmap->GetWidth();
int WindowHeight = g_pBgRgnBitmap->GetHeight();
//计算窗口起始坐标
int StartX = (DesktopWidth - WindowWidth)/2;
int StartY = (DesktopHeight - WindowHeight)/2;
//创建窗体
HWND hWnd = CreateWindow("BmpWindow",
"BmpWin", //窗口名字
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU,
StartX, StartY,
WindowWidth, WindowHeight,
NULL, NULL,
hInstance, NULL);
if (hWnd == NULL)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
/**
// 目的: 处理主窗口的消息。
//
// WM_PAINT - 绘制主窗口
// WM_DESTROY - 发送退出消息并返回
*/
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_CREATE:
{
HRGN windowRgn = g_pBgRgnBitmap->GetRgn(hWnd);
SetWindowRgn(hWnd, windowRgn, TRUE);
}
break;
case WM_PAINT:
{
hdc = BeginPaint(hWnd, &ps);
HDC ExterDC = CreateCompatibleDC(hdc);
HBITMAP hTmpBitmap = g_pBgRgnBitmap->GetHBitmap();
BITMAP backBitmap;
GetObject(hTmpBitmap, sizeof(BITMAP), &backBitmap); //得到位图数据
SelectObject(ExterDC, hTmpBitmap); //把位图选进 ExterDC
BitBlt(hdc, 0, 0, backBitmap.bmWidth, backBitmap.bmHeight, ExterDC, 0, 0, SRCCOPY); //把位图从 ExterDC copy 到 hdc
DeleteDC(ExterDC);
ReleaseDC(hWnd, hdc);
EndPaint(hWnd, &ps);
}
break;
case WM_NCHITTEST:
{
PostMessage(hWnd, WM_LBUTTONDOWN, wParam, lParam);
return HTCAPTION;
}
break;
case WM_DESTROY:
if (g_pBgRgnBitmap != NULL)
{
delete g_pBgRgnBitmap;
g_pBgRgnBitmap = NULL;
}
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
挖位图,做窗口.
最新推荐文章于 2014-12-22 18:49:42 发布