windows下3D窗口动画示例

如QQ登录界面点设置按钮窗口翻转,类似这样的3D窗口动画效果如何实现呢?

简单的说,就是使用3D图形库,进行离屏渲染(在内存/显存里画图,而不是屏幕上),

画出每一帧当前动画显示效果的图像,背景保持透明,

再将透明背景的图像显示为不规则形状窗口。


3D图形库可以使用opengl或DirectX。

显示不规则形状窗口可以通过UpdateLayeredWindow来实现。

这是使用opengl实现的一个3D窗口动画的简单demo,

效果图:



代码:
#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;
}


       
       
      
      
     
     
    
    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

churuxu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值