win32API实现透明字幕窗口

每周一记!
接上一篇内容 使用GDI实现视频字幕及特效,在实现了写入字幕功能后,添加一个透明的添加字幕窗口。
首先利用Windows窗口的扩展风格——分层窗口,创建一个对某一特定颜色值透明的窗口(如果直接设置窗口透明的话,整个窗口都会透明,无法显示需要添加的字幕)。

    HWND hWnd = CreateWindowEx(WS_EX_LAYERED, TEXT("TestWindow"), TEXT("透明窗口"), WS_POPUP | WS_VISIBLE, 0, 0, 20, 20, NULL, hInstance, NULL);
    SetLayeredWindowAttributes(hWnd, 0, 0, LWA_COLORKEY);

这样就创建了一个对黑色透明的窗口。
然后我们在WM_PAINT消息处理中给字幕框绘制边框和字幕内容。

    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        // TODO: Add any drawing code here...
        RECT rc;
        GetClientRect(hWnd, &rc);
        //绑定字体
        HFONT hOldFont = (HFONT)SelectObject(hdc, m_hfont);
        //写入字幕内容
        DrawText(hdc, szText, strlen(szText), &rc, DT_EDITCONTROL | DT_WORDBREAK);
        //创建画笔画边框
        LOGPEN lg;
        lg.lopnColor = 0x00ff0000;
        lg.lopnStyle = PS_DASH;
        lg.lopnWidth.x = 2;

        HPEN hPen = CreatePenIndirect(&lg);
        HPEN hOldPen = (HPEN)SelectObject(hdc, hPen);
        POINT pt;
        ::MoveToEx(hdc, rc.left, rc.top, &pt);
        LineTo(hdc, rc.left, rc.bottom);
        LineTo(hdc, rc.right, rc.bottom);
        LineTo(hdc, rc.right, rc.top);
        LineTo(hdc, rc.left, rc.top);
        SelectObject(hdc, hOldFont);
        SelectObject(hdc, hOldPen);
        EndPaint(hWnd, &ps);
        break;

绘制了内容后,我们就可以看到字体下面是透明的了,不过我们还要加上边框拉伸的功能,和拖动功能,响应WM_NCHITTEST和WM_SIZE消息。

case WM_NCHITTEST: 
    //获取鼠标位置 
    POINT pt;   
    pt.x = GET_X_LPARAM(lParam);   
    pt.y = GET_Y_LPARAM(lParam);  
    ::ScreenToClient(hWnd,&pt);  

    //得到窗口矩形
    RECT rcClient;  
    ::GetClientRect(hWnd, &rcClient);  

    //左上角
    if (pt.x20&&pt.y20)
    {  
        return HTTOPLEFT;  
    //右上角
    else if (pt.x>rcClient.right-20 && pt.y20)  
    {  
        return HTTOPRIGHT;  
    }
    //左下角
    else if (pt.x20 && pt.y>rcClient.bottom-20)  
    {  
        return HTBOTTOMLEFT;  
    }
    //右下角
    else if (pt.x>rcClient.right-20 && pt.y>rcClient.bottom-20)  
    {  
        return HTBOTTOMRIGHT;  
    }
    //以下这四个是上、下、左、右四个边
    else if (pt.x20)  
    {  
        return HTLEFT;  
    }else if (pt.x>rcClient.right-20)  
    {  
        return HTRIGHT;  
    }else if (pt.y20)  
    {  
        return HTTOP;  
    }if (pt.y>rcClient.bottom-20)  
    {  
        return HTBOTTOM;            
    }else  
    {  
        return HTCAPTION;  
    }  
    break; 
    //响应WM-SIZE消息 
case WM_SIZE:     
    {  
        RECT rcClient = { 0 };  
        ::GetClientRect(hWnd, &rcClient);   
        InvalidateRect(hWnd,&rcClient,FALSE);  
    }  
    break;  

这样我们的窗口边框就能拉伸和移动了,实现方法就是把客户区的点击设为标题栏的消息,让它处理拖动,判断边框让系统自动处理拉伸。这样我们就实现了一个透明可拉伸和拖动的窗口了。
Ps.因为透明穿透的原因,点击透明区域是无法收到消息的,不过可以让底层播放窗口添加判断把消息发过来。

你可能感兴趣的:(界面)