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

大家都见过以前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 条评论
登录 后参与评论

相关文章

来自专栏潇涧技术专栏

Android Training Summary (1) Getting Started

Android Training 中Getting Started部分的阅读笔记

510
来自专栏算法channel

Python-GUI|Tk类,属性文档使用指南

这是一篇tkinter相关API的介绍性地帮助文档,包括常用的包,类结构图,属性取值等,可以作为一个工具文档,供大家查阅。 01Tk中的包 __main...

2877
来自专栏程序员互动联盟

【专业技术】Win32创建异形窗口

大家都见过在windows下各种气泡窗口、输入法窗口已经其他一些窗口,这些窗口看起来不像传统的windows窗那样,上面是标题栏,下面是窗口的客户区。这...

54410
来自专栏听雨堂

从MapX到MapXtreme2004[9]-标注的强调显示

        如果想要将一个选中的图元强调显示,用红色醒目的文字显示的话,我的思路如下:             1、不可能直接改原先的图元,所以必须要在一个...

1926
来自专栏技术小黑屋

Package Stopped State Since Android 3.1

Since Android 3.1, Android has introduced a LaunchControl mechanism. It’s call S...

641
来自专栏Hongten

pygame系列_原创百度随心听音乐播放器_完整版

 1.当鼠标移动到黄色圆区域,会展示出我的相片和'Yes,You are Luck:)'字样

813
来自专栏24K纯开源

ChartDirector应用笔记(三)

前言 继上篇文章(Simple bar chart)推出之后,本篇文章继续ChartDirector的使用。在这篇Blog中,博主实现的是soft lighti...

18810
来自专栏游戏杂谈

as3与php 上传多张图片demo

2、在一次添加的图片中如果超出最大上传数,忽略本次选中的所有图片(又得重新选一次,此现象普通存在于目前各大网站的flash批量上传中)

842
来自专栏听雨堂

从MapX到MapXtreme2004[9]-标注的强调显示

        如果想要将一个选中的图元强调显示,用红色醒目的文字显示的话,我的思路如下:             1、不可能直接改原先的图元,所以必须要在一个...

1905
来自专栏别先生

JAVA学习Swing章节流布局管理器简单学习

package com.swing; import java.awt.Container; import java.awt.FlowLayout; impo...

1800

扫码关注云+社区