每周一记!
接上一篇内容 使用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.因为透明穿透的原因,点击透明区域是无法收到消息的,不过可以让底层播放窗口添加判断把消息发过来。