画出每一帧当前动画显示效果的图像,背景保持透明,
再将透明背景的图像显示为不规则形状窗口。
#include
#include
#include
#include
#pragma comment (lib, "opengl32.lib")
#pragma comment (lib, "gdi32.lib")
#pragma comment (lib, "user32.lib")
const int nWndWidth = 600;
const int nWndHeight = 600;
static HDC hMemDC;
static void* pMemBits;
static int nFrame;
void Render(){
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
const GLfloat vtx[] = {
-0.5, 0, 0,
0.5, 0, 0,
0, -0.866, 0
};
const GLfloat col[] = {
1, 0, 0, 0.7,
0, 1, 0, 0.8,
0, 0, 1, 1
};
glPushMatrix();
glRotatef(90.0+nFrame, 0, 1, 0);
glTranslatef(0,-0.3,0);
glRotatef((nFrame%72) * 5.0, 0, 0, 1);
glTranslatef(0,0.3,0);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vtx);
glColorPointer(4, GL_FLOAT, 0, col);
glDrawArrays(GL_TRIANGLE_FAN,0,3);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glPopMatrix();
glFlush();
}
HBITMAP CreateBit32Bitmap(int w, int h, void** ppbits){
BITMAPINFOHEADER bih;
memset(&bih, 0, sizeof(bih));
bih.biSize = sizeof(bih);
bih.biWidth = w;
bih.biHeight = 0-h;
bih.biPlanes = 1;
bih.biBitCount = 32;
bih.biCompression = BI_RGB;
return CreateDIBSection(NULL,(BITMAPINFO*)&bih,DIB_RGB_COLORS,ppbits,NULL,0);
}
HDC CreateBit32DC(HBITMAP hbm){
HDC dc = CreateCompatibleDC(NULL);
assert(dc);
SelectObject(dc,hbm);
PIXELFORMATDESCRIPTOR pfd;
memset(&pfd, 0, sizeof(pfd));
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_BITMAP ;
pfd.iPixelType = PFD_TYPE_RGBA ;
pfd.cColorBits = 32;
pfd.iLayerType = PFD_MAIN_PLANE;
pfd.cAlphaBits = 8;
int pf = ChoosePixelFormat(dc, &pfd);
assert(SetPixelFormat(dc, pf, &pfd));
return dc;
}
void InitGL(HWND hWnd){
HBITMAP hbm = CreateBit32Bitmap(nWndWidth,nWndHeight,&pMemBits);
hMemDC = CreateBit32DC(hbm);
HGLRC hglrc = wglCreateContext(hMemDC);
assert(hglrc);
wglMakeCurrent(hMemDC, hglrc);
glViewport(0,0,nWndWidth,nWndHeight);
}
void ConfigGL(){
glEnable(GL_POLYGON_SMOOTH);
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
}
void UpdateToWindow(HWND hWnd,HDC hDC,HDC fromDC){
RECT rc;
assert(GetWindowRect(hWnd, &rc));
POINT ptwin = {rc.left, rc.top};
SIZE szwin = {rc.right-rc.left, rc.bottom-rc.top};
POINT ptsrc = {0,0};
COLORREF cr = RGB(0,0,0);
BLENDFUNCTION bf = {0};
bf.SourceConstantAlpha = 255;
bf.AlphaFormat = AC_SRC_ALPHA;
UpdateLayeredWindow(hWnd,hDC,&ptwin,&szwin,fromDC,&ptsrc,cr,&bf,ULW_ALPHA);
}
void MainWndOnPaint(HWND hWnd){
PAINTSTRUCT ps;
HDC hDC = BeginPaint(hWnd, &ps);
Render();
glReadPixels(0,0,nWndWidth,nWndHeight,GL_RGBA,GL_UNSIGNED_BYTE,pMemBits);
UpdateToWindow(hWnd, hDC, hMemDC);
EndPaint(hWnd, &ps);
}
LRESULT CALLBACK MainWndProc(HWND hWnd,UINT nMsg, WPARAM wParam, LPARAM lParam){
switch(nMsg){
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_CREATE:
InitGL(hWnd);
ConfigGL();
SetTimer(hWnd,1,30,NULL);
break;
case WM_PAINT:
MainWndOnPaint(hWnd);
break;
case WM_TIMER:
if(nFrame>360){
PostQuitMessage(0);
}else{
nFrame++;
InvalidateRect(hWnd, NULL, FALSE);
}
break;
case WM_ERASEBKGND:
return 0;
}
return DefWindowProc(hWnd, nMsg, wParam, lParam);
}
int WINAPI _tWinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPTSTR lpCmd,int nShow){
WNDCLASS wc = {0};
wc.lpszClassName = _T("3d_window_demo");
wc.lpfnWndProc = MainWndProc;
wc.hInstance = hInst;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
assert(RegisterClass(&wc));
HWND hMainWnd = CreateWindowEx(WS_EX_LAYERED|WS_EX_TOOLWINDOW|WS_EX_NOACTIVATE,
_T("3d_window_demo"), NULL, 0,
CW_USEDEFAULT, CW_USEDEFAULT, nWndWidth, nWndHeight,
NULL, NULL, hInst, NULL);
assert(hMainWnd);
ShowWindow(hMainWnd, nShow);
InvalidateRect(hMainWnd, NULL, FALSE);
MSG msg;
while(GetMessage(&msg, NULL, 0, 0)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}