上午被“美帝国主义”放了鸽子,这样也好,把安排的review提前做完了,下午也就空了点,于是就想起了昨天的一个和LingosHook相关的问题了--不是所有单词的查询都是来自于鼠标方式,还有一种更加常用的方式:直接输入查询。应该是当时被HOOK给迷住,一门心思就想着去Hook Lingoes的消息了,完全没有考虑实际的使用。
于是发扬“源码在手,天下我有”的精神,很快添加Hotkey对象用于注册热键,用于需要提取查询结果时使用。
#ifndef __HOTKEYOBJECT_H__
#define __HOTKEYOBJECT_H__
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
#include "wx/wx.h"
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
class LingosHookFrame;
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
class CHotkeyObject
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
public:
CHotkeyObject(LingosHookFrame* frame);
virtual ~CHotkeyObject();
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
int Register(UINT mod, UINT key);
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
int MessageProc(WXUINT msg, WXWPARAM wparam, WXLPARAM lparam);
protected:
void Unregister();
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
int GetResult(WXWPARAM wparam, WXLPARAM lparam);
int GetIEDocResult(HWND hwnd);
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
static int _wincount;
static BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lparam);
private:
LingosHookFrame* _objFrame;
int _id;
};
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
#endif
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
int CHotkeyObject::Register(UINT mod, UINT key)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
_id = ::GlobalAddAtom(_T("LingosHook"));
if(_id == 0)
return -1;
if(::RegisterHotKey((HWND)_objFrame->GetHWND(), _id, mod, key) != TRUE)
return -1;
return 0;
}
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
void CHotkeyObject::Unregister()
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
if(_id != 0)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
::UnregisterHotKey((HWND)_objFrame->GetHWND(), _id);
_id = 0;
}
}
模块化设计的好处就是添加新的模块,完全不需要涉及其它模块的代码。新的CHotkeyObject几乎十五分钟就可以使用,然后模仿提取Lingoes悬浮窗口的方法,开始提取其主窗口的IE控件窗口的结果,登时傻了。其主窗口远比悬浮窗口复杂,所使用的IE控件窗口远不是一个。所有使用到的IE窗口都有着相同的Class - 'Internet Explorer_Server',且都没有Title,这让我没法区分哪个是结果窗口。折腾了很久,耐心全部被消耗后,拿出了最终的方法来 -- 硬编码!这种方法对我来说,有些像原子弹--反对使用,但却很有效。 怎么个硬编码,看下面代码就知道了。
BOOL CALLBACK CHotkeyObject::EnumChildProc(HWND hwnd, LPARAM lparam)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
++ _wincount;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
if(_wincount == 0x24)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
*(HWND*)lparam = hwnd;
return FALSE;
}
return TRUE;
}
看出来了吗?0x24!就是直接找主窗口上的第36个子窗口(控件)就是需要的结果窗口。。。
紧接着在结果的处理上,我原以为通过两种方式得到的TEXT结果应该是一样,使用原有的CDictionaryObject应该可以正常工作,然而实际情况确实两者差了一个\r\n,导致无法解析。看来使用TEXT解析结果的方法不能再使用,只有HTML方式才是靠谱。但想起前面被0x24的折磨,顿时“老羞成怒”,不再考虑什么使用“优雅”的方式分解HTML,比如写一个好看的CHtmlAnalseObject什么的,直接来硬的吧 --把HTML当TEXT使用 --
唉,又是硬编码了,太暴力了。。。但谁叫Lingoes招惹我呢?!(。。。)
<---自我原谅的分割线---->
硬编码是编程中非常不好的习惯和做法,但这种方法实际在被经常使用着,比如我们常说的‘魔数’。硬编码的一个主要害处就是使代码失去了灵活性和可读性。
这里使用硬编码是么办法啊,不过再说了,LingosHook本身使用Hook方式就已经失去了自身的灵活了,完全和Lingoes的实现息息相关了。当前Lingoes版本是2.6.3,悬浮只有一个IE窗口,使用WM_COPYDATA消息,结果是HTML格式的,等等等等,随便一个因素稍微的变化,都会导致LingosHook的无法使用。