首页
社区
课程
招聘
[求助]如何实现金山词霸的屏幕取词?
发表于: 2007-3-29 23:31 12671

[求助]如何实现金山词霸的屏幕取词?

2007-3-29 23:31
12671
实现对屏幕上的汉字进行取字词,并呈现其汉语拼音,实现发音。(即拥有类似金山词霸的功能)。那位高手能指点一下,有源码最好(最好是c/c++的代码)
Email:rainertop@163.com

[培训]科锐逆向工程师培训第53期2025年7月8日开班!

收藏
免费 0
支持
分享
最新回复 (9)
雪    币: 615
活跃值: (1372)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
Windows核心编程中说道过.
网上也有源代码.
2007-3-30 08:50
0
雪    币: 375
活跃值: (12)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
3
取词是Hook API TextOut* 之类的吧

然后发音是用TTS
2007-3-30 15:53
0
雪    币: 321
活跃值: (275)
能力值: ( LV13,RANK:1050 )
在线值:
发帖
回帖
粉丝
4
呵呵,我做过
2007-7-29 01:52
0
雪    币: 321
活跃值: (275)
能力值: ( LV13,RANK:1050 )
在线值:
发帖
回帖
粉丝
5
建议使用accessibility来做。
2007-7-29 02:58
0
雪    币: 101
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
屏幕取词可以用 钩子,和窗口子类化 这个没做过

发音方面的 倒是做过一个网络文本语音 用的是MS提供的TTS 引擎

发上来希望对你有点用呵呵
2007-8-1 15:11
0
雪    币: 101
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
木马编程DIY之文本语音
                                                        冷风

在黑防的第2期上天涯衰草(是电脑报上黑客营的老大吧呵呵)对“寿鼠”远程控制程序进行了介绍,其中有一个
功能就是“跟对方讲英语”感觉很有意思,就试着自己做了一个发现也不是太难,效果如图1所示
程序在VC6.0+WIN2000下编写分为服务端(SDK)和客户端两个文件,在其它机器的运行服务端后,就可以通过客户端让它“说话”了,如果目标
地址为空的话,会在自己的电脑上朗读。

关于文本语音

寿鼠的朗读功能就是通过文本语音实现的,文本语音又称为TTS(Text-to-Speech)它的作用就是把文本转化为语音,如果我们想
开发这种程序,需要使用软提供的软件开发包Microsoft Speech SDK,目前使用最为广泛的版本是5.1,这个包大小在65M左右在
天空,军华都可以下载到,它本身带有十分详细的开发资料,和可执行程序如图2图3所示,参考帮助文档提供的例子我们可以
很方便的做出自己的程序了。

准备工作

在开始前应该把Microsoft Speech SDK安装好,装好后进入安装目录把INCLUDE和LIB目录中的头文件与库文件复制到VC的开发目录里面
我这里是C:\Microsoft Visual Studio\VC98\Include跟LIB目录,当然你也可以在VC中设置路径(我喜欢直接复制过去)现在就可
以编写程序了

服务端编写

服务端运行后就一直在5555端口监听,收到数据就读出来,实现代码如下
2007-8-1 15:12
0
雪    币: 101
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
2007-8-1 15:13
0
雪    币: 101
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
#include <sapi.h>          //TTS所需要的头文件
#include <windows.h>
#include <winsock.h>
#pragma comment (lib,"ws2_32") //加载库函数

const int buffer_len=2048;

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{

       WSADATA wsadata;
       SOCKET server;
       SOCKET client;
       SOCKADDR_IN serveraddr;
       SOCKADDR_IN clientaddr;
       int    port=5555;
       char buffer[buffer_len];
       WCHAR wbuffer[buffer_len];

       memset(wbuffer,0,sizeof(WCHAR)*buffer_len);
       memset( buffer,0, sizeof(char)*buffer_len);

       WORD ver=MAKEWORD(2,2);                                             //判断winsock版本
       WSAStartup(ver,&wsadata);                                    //初始SOCKET

       server=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

       serveraddr.sin_family=AF_INET;
       serveraddr.sin_port=htons(port);
       serveraddr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);

       bind(server,(SOCKADDR*)&serveraddr,sizeof(serveraddr));
      
       listen(server,5);

       int len=sizeof(clientaddr);

       while(1)//循环接受连接
       {
              client=accept(server,(sockaddr *)&clientaddr,&len);

              while(1)//循环接受数据
              {
                     if(recv(client,buffer,buffer_len,0)!=0)//有数据则播放
                     {
                            memset(wbuffer,0,sizeof(WCHAR)*buffer_len);
                            //必须先转换成宽字符
                            MultiByteToWideChar( CP_ACP,
                                                                MB_PRECOMPOSED,               // character-type options
                                                                buffer,                               // address of string to map
                                                                buffer_len,                         // number of bytes in string
                                                                wbuffer,                                   // address of wide-character buffer
                                                                buffer_len                                 // size of buffer
                             );      

                           
                            memset( buffer,0, sizeof(char)*buffer_len);
                                    
                            ISpVoice * pVoice = NULL;

                            if (FAILED(CoInitialize(NULL)))//处始化COM接口

                            {
                                   MessageBox(NULL,"ERROR","Error to intiliaze COM",0);
                            }
                           //获取ISpVoice接口
                            HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL,CLSCTX_ALL, IID_ISpVoice, (void **)&pVoice);

                            if( SUCCEEDED( hr ) )
                            {   
                                   hr = pVoice->Speak(wbuffer, 0, NULL); //开始朗读
                                   pVoice->Release();//完成后释放声音对象
                                   pVoice = NULL;
                            }

                            CoUninitialize();//释放
                     }
                     else
                            break;//接受数据为0退出
              }
       }

       closesocket(server);
       closesocket(client);
       WSACleanup();

       return 0;
}
2007-8-1 15:14
0
雪    币: 101
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
实现代码挺简单的,需要注意的是在
pVoice->Speak(const WCHAR *pwcs,DWORD dwFlags,ULONG *pulStreamNumber);中pwcs是WCHAR类型的也就是Unicode编码
所以从网络收到数据后要进行Unicode转换,编码转换可以用MultiByteToWideChar API来实现,这是一个很好用的API看看上文
的代码就会用了。

客户端实现

客户端实现同样很简单,所以我就不再浪费感情了呵呵

void CMyDlg::OnOK()
...{
       UpdateData();

       if(m_addr.IsEmpty())//地址为空则本地播放
       ...{
              //实现代码与服务端相差无几            
       }
       else//把数据发送至目标
       ...{
              WSADATA wsadata;
              SOCKET client;
              SOCKADDR_IN serveraddr;
              int port=5555;

              WORD ver=MAKEWORD(2,2);                 //判断winsock版本
              WSAStartup(ver,&wsadata);        //初始SOCKET

              client=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

              serveraddr.sin_family=AF_INET;
              serveraddr.sin_port=htons(port);
              serveraddr.sin_addr.S_un.S_addr=inet_addr(m_addr.LockBuffer());//m_addr为接受地址的文本控件

              connect(client,(SOCKADDR*)&serveraddr,sizeof(serveraddr));

              send(client,m_text.LockBuffer(),m_text.GetLength(),0);//m_text为接受内容的文本控件

              closesocket(client);
              WSACleanup();
       }
}

需要的话,还可以扩充一下,让它读中文日文什么的,不过你还得专门去下载发声补丁......而且也可以指定男音或女音
朗读不过我感觉女音比较好听嘿嘿,本文实现的功能比较简单,如果想编写功能强大的程序还是请参考Microsoft Speech SDK
的帮助文档,
2007-8-1 15:14
0
游客
登录 | 注册 方可回帖
返回