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

大家都见过以前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扩展属性来实现。

原文发布于微信公众号 - 程序员互动联盟(coder_online)

原文发表时间:2015-05-03

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏我和未来有约会

Silverlight初级教程-绘图布局

Silverlight初级教程 绘图布局 正如之前所说Blend是和flash很像的东西。在这里将介绍一下如何在Blend中绘图。 这里的Blend中“舞台...

1658
来自专栏前端知识分享

第2天:HTML常用标签

一、超链接a href:www.baidu.com(跳转页面);id名(锚点跳到相应div位置);01.rar(压缩包) target:_blank(新窗口打...

641
来自专栏前端儿

CSS常见兼容性问题总结

浏览器的兼容性问题,通常是因为不同的浏览器对同一段代码有不同的解析,造成页面显示不统一的情况。

863
来自专栏Keegan小钢

Android样式的开发:drawable汇总篇

Android有很多种drawable类型,除了前几篇详细讲解的shape、selector、layer-list,还有上一篇提到的color、bitmap、c...

291
来自专栏Java帮帮-微信公众号-技术文章全总结

04.HTML区块/布局/表单/框架/颜色/颜色名/颜色值

04.HTML区块/布局/表单/ 框架/颜色/颜色名/颜色值 HTML <div> 和<span> ---- HTML 可以通过 <div> 和 <span>将...

3135
来自专栏吾爱乐享

php学习之css入门(一)

1212
来自专栏河湾欢儿的专栏

display:inline-block

1.块在一行显示 2.行内属性标签支持宽高 3.没有宽度的时候内容撑开宽度 4.标签之间的换行被解析(问题) 5.Ie6 7不支持inline-bloc...

563
来自专栏数据小魔方

数据地图系列10|excel(VBA)数据地图透明度填充法

今天要跟大家分享数据地图系列的第10篇——excel(VBA)数据地图透明度填充法。 这种方法的制作步骤难度与前一篇相比都较低,但是涉及到的VBA代码却要比前一...

3815
来自专栏IMWeb前端团队

移动端重构实战系列5——form元素

form 大概要实现的效果如下图(具体demo可见sheral form): ? 粗略一看,跟line list差不多,好像可以直接套用,但是深究起来还是有那么...

2045
来自专栏闻道于事

正式学习第二天上午——常用标签及列表 0605

今天2017.0605上午,主要学习了常用标签和列表,以下面代码为例 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 ...

2686

扫描关注云+社区