1.
#define TRANS_COLOR (ALPHA_MASK | RGB(255, 0, 255))
BOOL CMyDialog::OnInitDialog()
{
CDialog::OnInitDialog();
CRgn rgn;
CreateRgnByImage(_T("MyImage.png"), rgn);
SetWindowRgn(rgn, TRUE);
return TRUE;
}
void CMyDialog::CreateRgnByImage(const CString &imageName, CRgn &rgn)
{
Bitmap img(imageName);
ASSERT(PixelFormat32bppARGB == img.GetPixelFormat());
Rect rect(0, 0, img.GetWidth(), img.GetHeight());
BitmapData data;
img.LockBits(&rect, ImageLockModeRead, PixelFormat32bppARGB, &data);
UINT *pData = static_cast<UINT*>(data.Scan0);
rgn.CreateRectRgn(0, 0, 0, 0);
CRgn tempRgn;
for (UINT h = 0; h < data.Height; ++ h)
{
UINT w = 0;
while(w < data.Width)
{
UINT leftX;
while (w ++ < data.Width && TRANS_COLOR == *pData ++);
leftX = w;
while (w ++ < data.Width && TRANS_COLOR != *pData ++);
tempRgn.CreateRectRgn(leftX, h, w - 1, h + 1);
rgn.CombineRgn(&rgn, &tempRgn, RGN_OR);
tempRgn.DeleteObject();
}
}
img.UnlockBits(&data);
}
2.
如果使用一幅位图,通过挖图的方式来做成一个不规则的窗体,是很累人的一件事。
而使用GDI+,可以直接用PNG图片,通过图片本身的透明度,自动创建不规则窗体。
比如,你手中有个美女图,通过PhotoShop等工具,把美女的身体抠出来,保存为PNG格式的图片,除了美女的身体,图片的其他部门都是透明的。后面的工作就是,写一个windows小程序,加载这幅美女图,让她成为我们程序的界面。
Win32程序的框架我就懒得贴了,直接贴关键代码了。
view plain#include<GdiPlus.h>
- using namespace Gdiplus;
-
- #define MAX_LOADSTRING 100
-
- ULONG_PTR m_gdiplusToken;
- GdiplusStartupInput m_gdiplusStartupInput;
-
- BLENDFUNCTION m_Blend;
-
- Bitmap * m_BackgoundImage;
- int WINAPI WinMain(HINSTANCE hInstance,
- HINSTANCE hPrevInstance,
- LPSTR lpCmdLine,
- int nCmdShow)
- {
-
- }
- BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
- {
-
- return TRUE;
- }
- LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
- {
- switch (message)
- {
- case WM_CREATE:
- {
- GdiplusStartup(&m_gdiplusToken, &m_gdiplusStartupInput, NULL);
- m_Blend.BlendOp = AC_SRC_OVER;
- m_Blend.AlphaFormat = AC_SRC_ALPHA;
- m_Blend.BlendFlags = 0;
- m_Blend.SourceConstantAlpha = 255;
- m_BackgoundImage = Bitmap::FromFile(L"meinv.png");
- if(m_BackgoundImage == NULL)
- {
- MessageBox(hWnd, (LPCSTR)"it is null", (LPCSTR)"OO", 0);
- exit(0);
- }
-
- int DesktopWidth = GetSystemMetrics(SM_CXSCREEN);
- int DesktopHeight = GetSystemMetrics(SM_CYSCREEN);
-
- g_WindowWidth = m_BackgoundImage->GetWidth();
- g_WindowHeight = m_BackgoundImage->GetHeight();
-
- int StartX = (DesktopWidth - g_WindowWidth)/2;
- int StartY = (DesktopHeight - g_WindowHeight)/2;
- SetWindowPos(hWnd, HWND_TOP, StartX, StartY ,g_WindowWidth, g_WindowHeight, SWP_DRAWFRAME);
- }
- break;
- case WM_PAINT:
- {
- UpdateWindowView(hWnd);
- }
- break;
- case WM_NCHITTEST:
- {
- PostMessage(hWnd, WM_LBUTTONDOWN, wParam, lParam);
- return HTCAPTION;
- }
- break;
- case WM_DESTROY:
- GdiplusShutdown(m_gdiplusToken);
- PostQuitMessage(0);
- break;
- default:
- return DefWindowProc(hWnd, message, wParam, lParam);
- }
- return 0;
- }
- void UpdateWindowView(HWND hWnd)
- {
-
- RECT rct;
- GetWindowRect(hWnd, &rct);
- POINT ptWinPos = {rct.left,rct.top};
- SIZE szWinSize = {g_WindowWidth - 1, g_WindowHeight - 1};
-
- HDC dcScreen = GetDC(hWnd);
- HDC dcmemory = CreateCompatibleDC(dcScreen);
-
- HBITMAP canvas = CreateCompatibleBitmap(dcScreen, g_WindowWidth, g_WindowHeight);
-
- SelectObject(dcmemory, canvas);
-
- Graphics * graphics = Graphics::FromHDC(dcmemory);
-
- Point points[] =
- {
- Point(0, 0),
- Point(g_WindowWidth, 0),
- Point(0, g_WindowHeight)
- };
- graphics->DrawImage(m_BackgoundImage, points, 3);
-
- POINT ptSrc = {0, 0};
-
- //0x80000 是指WS_EX_LAYERED 宏值 ,下边两句可用 ModifyStyleEx(0, WS_EX_LAYERED);代替
- DWORD dwExStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
- if((dwExStyle&0x80000) != 0x80000)
- {
- SetWindowLong(hWnd, GWL_EXSTYLE, dwExStyle^0x80000);
- }
-
- BOOL res = UpdateLayeredWindow(hWnd, dcScreen, &ptWinPos, &szWinSize, dcmemory, &ptSrc, 0, &m_Blend, ULW_ALPHA);
- DWORD dw = GetLastError();
- delete graphics;
-
- DeleteObject(canvas);
- canvas = NULL;
-
-
- DeleteDC(dcmemory);
- ReleaseDC(hWnd, dcScreen);
-
- }
不过呢,这么做也有个不爽的地方,你使用的PNG图片必须也和你的程序一起发布,不能隐藏在程序代码中。当然了一般的游戏都是有专门的资源包,并且做了加密的。我看剑侠叁的启动界面应该就是使用GDI+来做的,很漂亮。
另:
//可实现透明效果,
ModifyStyleEx(0, WS_EX_LAYERED);
SetLayeredWindowAttributes(0,220,LWA_ALPHA);