前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【专业技术】搜狗歌词窗口如何来实现

【专业技术】搜狗歌词窗口如何来实现

作者头像
程序员互动联盟
发布2018-03-12 11:49:41
8070
发布2018-03-12 11:49:41
举报

大家都见过以前Sogou歌词窗口的样子吧,感觉是歌词的字体直接贴在windows桌面上一样,但是还可以用鼠标控制,这个是怎么做成的呢?其实我也不知道^_^,估计大家会说不知道还在这里写个啥?首先我不是Sogou公司做这个的人,我当然不知道了。我今天要说的是模仿这种效果,因为要实现这种效果不止一种办法,也许Sogou歌词就是采用这个办法,也可能不是。好了,废话少说了,直接如题吧。

要实现这种效果,有一点一般是需要的,就是窗口透明的效果,所以关键之一就是如何实现windows窗口的透明。Windows API中有一个函数能实现这个效果:

BOOL SetLayeredWindowAttributes( HWND hwnd,

COLORREF crKey,

BYTE bAlpha,

DWORD dwFlags

);

hwnd:要设置透明的窗口句柄。

crKey:指定要实现透明的color key。

bAlpha:指定整个窗口的透明度。

dwFlags:透明标记,LWA_COLORKEY则指定crKey作为透明颜色,LWA_ALPHA则指定bAlpha作为整个窗口的透明色。

我们要实现像Sogou歌词窗口那样,显然是没有标题栏和边框,并且是最顶层窗口,所以我们创建窗口时要指定相应的属性。

CreateWindowEx(WS_EX_TOOLWINDOW|WS_EX_TOPMOST|WS_EX_LAYERED,// extended style

szClassName, // pointer toregistered class name

"SogouLike Win", // pointer towindow name

WS_POPUP, // window style

400, //horizontal position of window

200, // vertical positionof window

500, // windowwidth

240, // windowheight

HWND_DESKTOP, // handle to parent

NULL, // handleto menu, or child-window identifier

hInstance, // handle toapplication instance

NULL); // pointerto window-creation data

由于不需要菜单和边框,所以这里采用WS_POPUP风格,顶层窗口采用WS_EX_TOPMOST属性指定,要实现透明度,需要指定WS_EX_LAYERED属性,由于这个窗口应该是在所以的窗口之上,所以父窗口应该是桌面HWND_DESKTOP。

因为没有菜单,鼠标的拖放以及关闭都没有地方操作,故我们的程序中需要将窗口客户区的点击定向到标题区,并捕获鼠标按键,鼠标按下后移动时,我们相应的移动窗口,所以整个相当于将整个客户区变成标题部分,就可以拖动了。所有代码如下:

#include <windows.h>

charszClassName[] = "Windows App";

HINSTANCE ghApplication = NULL;

HWND ghMainWindow = NULL;

LRESULT CALLBACK WindowProc(HWND hwnd,UINT uMsg, WPARAM wParam, LPARAM lParam);

intAPIENTRY WinMain(HINSTANCE hInstance,

HINSTANCE hPrevInstance,

LPSTR lpCmdLine,

int nCmdShow)

{

MSGmessages;

WNDCLASSEXwcex;

//注册窗口类

wcex.cbClsExtra = 0;

wcex.cbSize = sizeof(WNDCLASSEX);

wcex.cbWndExtra = 0;

wcex.hbrBackground= (HBRUSH)(COLOR_3DFACE);

wcex.hCursor = LoadCursor(NULL, IDC_ARROW);

wcex.hIcon = NULL;

wcex.hIconSm = NULL;

wcex.hInstance = hInstance;

wcex.lpfnWndProc = WindowProc;

wcex.lpszClassName= szClassName;

wcex.lpszMenuName = NULL;

wcex.style = CS_HREDRAW | CS_VREDRAW;

if (!RegisterClassEx(&wcex))

{

return 0;

}

ghApplication= hInstance;

//创建透明、顶层窗口

ghMainWindow= CreateWindowEx(WS_EX_TOOLWINDOW|WS_EX_TOPMOST|WS_EX_LAYERED, szClassName, "Win32App", WS_POPUP,

400, 200, 500, 240,

HWND_DESKTOP,NULL, hInstance, NULL);

HINSTANCEhModule = LoadLibrary("User32.DLL");

typedef BOOL (WINAPI *MYFUNC)(HWND, COLORREF, BYTE,DWORD);

MYFUNCpfn = (MYFUNC)GetProcAddress(hModule, "SetLayeredWindowAttributes");

/* 设置窗口透明 */

pfn(ghMainWindow,RGB(0xFF,0xFF,0xFF), 0xFF, LWA_COLORKEY|LWA_ALPHA); // crkey与字体的颜色一样

FreeLibrary(hModule);

ShowWindow(ghMainWindow,nCmdShow); /* Shows the window */

UpdateWindow(ghMainWindow); /* SendsWM_PAINT message */

while(GetMessage(&messages, NULL, 0, 0))

{

if (!IsDialogMessage(ghMainWindow, &messages))

{

TranslateMessage(&messages);

DispatchMessage(&messages);

}

}

return (int)messages.wParam;

}

// 下面是窗口过程的实现,在其中处理鼠标捕获,点击转发,实现拖放的过程。

LRESULT CALLBACK WindowProc(HWND hwnd,UINT uMsg, WPARAM wParam, LPARAM lParam)

{

HGDIOBJhDefaultFont = NULL;

HFONThFont = NULL;

switch(uMsg)

{

case WM_NCRBUTTONUP: //处理右击菜单时退出

PostQuitMessage(0);

break;

caseWM_NCHITTEST:

return (LRESULT)HTCAPTION ;//始终返回非客户区的标题区域

case WM_LBUTTONDOWN:

SetCapture(hwnd);

break;

case WM_LBUTTONUP:

ReleaseCapture();

break;

case WM_MOUSEMOVE:

{

POINTpoint;

GetCursorPos(&point);

MoveWindow(hwnd,point.x,point.y,32,32,TRUE);

}

break;

case WM_PAINT:

{

PAINTSTRUCTpt;

HDChDC = BeginPaint(hwnd, &pt);

HFONThFont = CreateFont(96, //所创建字体的字符高度

0,//字体的字符平均宽度

200,//字符输出方向与水平向右的方向所成角度,以.1度为单位

0, //字符与基线的角度,以.1度为单位

FW_BOLD,//字符颜色的深浅度

TRUE,//斜体属性标志(FALSE:正常字体,TRUE:斜体)

FALSE,//下划线属性标志(FALSE:无下划线,TRUE:有下划线)

FALSE,//删除线属性标志(FALSE:无删除线,TRUE:有删除线)

ANSI_CHARSET,//字符集标识:ANSI字符集,:系统缺省字符集

OUT_DEFAULT_PRECIS,//输出精度

CLIP_DEFAULT_PRECIS,//剪切精度

DEFAULT_QUALITY,//输出品质

DEFAULT_PITCH|FF_SWISS,//字符间距

"Arial");//现有系统TrueType字体名称

HFONThOldFont = (HFONT)SelectObject(hDC, hFont);

SetBkMode(hDC,TRANSPARENT);

SetTextColor(hDC,RGB(0xFF, 0x00, 0x00)); // red font

TextOut(hDC,0, 50, "Hello", 5);

SetTextColor(hDC,RGB(0x00, 0xFF, 0x00)); // gree font

TextOut(hDC,100, 120, "Hello", 5);

DeleteObject(hFont);

EndPaint(hwnd,&pt);

}

break;

default:

return DefWindowProc(hwnd, uMsg, wParam, lParam);

}

return 0L;

}

本程序执行效果如下:

本方法实现的类似Sogou歌词显示窗口的关键有两处:

一是需要实现透明窗口效果,用WS_EX_LAYERED属性和SetLayeredWindowAttributes函数实现,这样就只有窗口上的字出现。

二是将窗口设为zorder的顶层,才会在桌面不被其他窗口盖住,因此本窗口的父窗口是HWND_DESKTOP,也可以通过GetDesktopWindow()函数来获取。

三是创建窗口时要去掉标题栏和边框,这个通过采用WS_POPUP属性和WS_EX_TOOLWINDOW扩展属性来实现。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2015-05-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员互动联盟 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档