16,548
社区成员




std::map<DWORD, HHOOK> hktable; //线程和HHOOK的关联表
struct extra_wndproc_t
{
WNDPROC wndproc;
bool has_close_sent;
extra_wndproc_t()
: wndproc(0), has_close_sent(false)//关键作用是初始化has_close_sent。至于什么用后面一看便知。
{}
};
std::map<HWND, extra_wndproc_t> subcls_table; //窗口和WNDPROC的关联表
void DocumentComplete()
{
DWORD tid = ::GetWindowThreadProcessId(控件窗口, 0);
if(hktable.count(tid) == 0) //表示该线程没有被HOOK
{
HHOOK cbt = ::SetWindowsHookEx(WH_CBT, &_m_cbtproc, NULL, tid); //设置钩子,用来拦截窗口的创建
hktable[tid] = cbt;
}
}
LRESULT CALLBACK _m_cbtproc(int nCode, WPARAM wParam, LPARAM lParam)
{
switch(nCode)
{
case HCBT_CREATEWND: //拦截创建窗口的事件
{
HWND wd = reinterpret_cast<HWND>(wParam);
char buf[260];
if(::GetClassName(wd, buf, 260))
{
if(std::string(buf) == "Internet Explorer_TridentDlgFrame") //脚本错误窗口的类名。
{
//该新建的窗口如果与脚本错误窗口同类,那么就子类化它。因为在这里判断不出这个窗口
//具体是不是用于显示脚本错误。
WNDPROC prev = (WNDPROC)::SetWindowLong(wd, GWL_WNDPROC, reinterpret_cast<LONG>(&_m_trident_wdproc));
subcls_table[wd] = prev;
}
}
}
break;
}
return ::CallNextHookEx(hktable[::GetCurrentThreadId()], nCode, wParam, lParam);
}
LRESULT CALLBACK _m_trident_wdproc(HWND wd, UINT msg, WPARAM wpar, LPARAM lpar)
{
WNDPROC wndproc = subcls_table[wd].wndproc;
switch(msg)
{
case WM_SETTEXT:
if(lpar)
{
std::string title(reinterpret_cast<char*>(lpar));
if(title == "脚本错误" || title == "Internet Explorer 脚本错误") //由于IE版本不同,标题也不同。
{
if(false == subcls_table[wd].has_sent_close) //避免重复Post WM_CLOSE
{
subcls_table[wd].has_sent_close = true;
::PostMessage(wd, WM_CLOSE, 0, 0); //肯定是Post不能是Send,你懂的
}
}
}
break;
case WM_DESTROY:
::SetWindowLong(wd, GWL_WNDPROC, wndproc); //还原子类化过程。
subcls_table.erase(wd);
break;
}
return ::CallWindowProc(wndproc, wd, msg, wpar, lpar);
}