为什么截获不了TAB键?

nightfallrove 2003-05-13 02:05:06
我在日志钩子中处理键盘和鼠标消息时写了这样的代码:
h1=GetActiveWindow();
GetcursorPos(&pos);
current=WindowFromPoint(pos);
if(current!=pre)
{
Memo1->lines->append(buffer);
pre=current;
}
else
{
SendMessage(current,WM_GETTEXT,1024,buffer);
}
我是想在Memo1里面显示用户的所有输入可是在一个有两个输入框的
窗口里,而且用户一回车就会关闭,如果用户用鼠标切换输入
框则可以得到输入的内容,但是如果用户用TAB键切换则无法得到输入的
内容而且输入框的句柄current,光标的位置pos都没有更新,怎样才能
截获TAB键并得到任何时候获得拥有光标的输入框的句柄呢?







...全文
15 点赞 收藏 8
写回复
8 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
jishiping 2003-05-20
我试了一下,用WH_CBT也不行,最后还是用WH_CALLWNDPROC解决了。
------------DLL部分----------------
HHOOK hHook=NULL;
HINSTANCE hInst=NULL;
extern "C" __declspec(dllexport)
BOOL _stdcall EnableHook(HWND, BOOL);

int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*)
{
if (reason==DLL_PROCESS_ATTACH)
hInst = hinst;
else if(reason==DLL_PROCESS_DETACH)
EnableHook(NULL, FALSE);
return 1;
}
//---------------------------------------------------------------------------
#define ATOM_NAME "HOOKWND"
#define WM_HOOKMSG (WM_APP+1)
BOOL CALLBACK EnumProc(HWND hwnd, LPARAM lParam)
{
if (GetProp(hwnd,ATOM_NAME)==hwnd) {
*(HWND*)lParam = hwnd; return 0;
}
return TRUE;
}

long CALLBACK HookFun(int nCode, WPARAM wParam,
LPARAM lParam)
{
if (nCode < 0)
return CallNextHookEx(hHook, nCode,
wParam, lParam);
CWPSTRUCT* pMsg = (CWPSTRUCT*)lParam;
HWND hWnd = NULL;
if (pMsg->message==WM_ACTIVATE) {
WORD fActive = LOWORD(pMsg->
wParam);
if (fActive==WA_INACTIVE)
hWnd = (HWND)pMsg->hwnd;
}
else if(pMsg->message==WM_KILLFOCUS)
hWnd = (HWND)pMsg->hwnd;

HWND hMain = NULL;
EnumWindows((FARPROC)EnumProc, (long)
&hMain);
if (hMain!=NULL && hWnd!=NULL)
SendMessage(hMain, WM_HOOKMSG, 0,
(long)hWnd);
return 0; //这儿必须返回 0
}

BOOL _stdcall EnableHook(HWND MainWnd, BOOL enable)
{
static HWND hMain=NULL;

if (enable) {
if (MainWnd==NULL) return FALSE;
if (MainWnd != hMain) {
if (hMain != NULL)
RemoveProp(hMain, ATOM_NAME);
SetProp(MainWnd, ATOM_NAME,
(HANDLE)MainWnd);
hMain = MainWnd;
}
if (hHook == NULL)
hHook = SetWindowsHookEx(WH_CALLWNDPROC,
(HOOKPROC)HookFun, hInst, 0);
return hHook != NULL;
}
else {
if (hMain != NULL) {
RemoveProp(hMain, ATOM_NAME);
hMain = NULL;
}
if (hHook != NULL) {
if (UnhookWindowsHookEx(hHook))
hHook = NULL;
}
return hHook == NULL;
}
}


----------EXE部分---------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TButton *Button1;
TButton *Button2;
TMemo *Memo1;
TButton *Button3;
void __fastcall Button1Click(TObject *Sender);
void __fastcall Button2Click(TObject *Sender);
void __fastcall Button3Click(TObject *Sender);
private: // User declarations
void __fastcall OnHookMsg(TMessage&);
public: // User declarations
__fastcall TForm1(TComponent* Owner);
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(WM_HOOKMSG, TMessage, OnHookMsg)
END_MESSAGE_MAP(TForm)
};

extern "C" BOOL _stdcall EnableHook(HWND, BOOL);
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
EnableHook(Handle, TRUE);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
EnableHook(Handle, FALSE);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
Memo1->Clear();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::OnHookMsg(TMessage& Msg)
{
char buffer[2048];

HWND hWnd = (HWND)Msg.LParam;
SendMessage(hWnd, WM_GETTEXT, 2048,
(long)buffer);
Memo1->Lines->Add(buffer);
}
回复
nightfallrove 2003-05-19
WH_CBT没用过,
季老大有例子不?
谢了,,,,,
回复
jishiping 2003-05-18
如果使用WH_JOURNALRECORD钩子的话,我也没有办法。实际上,你只是想在一个窗口失去焦点时,记录这个窗口的文字及ClassName之类的信息。我认为可以用WH_CBT钩子来实现。不过
这需要做成DLL才行。在WH_CBT钩子的回调函数里,拦截nCode==HCBT_ACTIVATE的情形。
回复
nightfallrove 2003-05-18
如果我要得到按tab后得到焦点的控件的句柄该怎么办呢
不能用WindowFromPoint()了,用什么呢?》
谢谢
回复
jishiping 2003-05-18
我看了(也试了)你的代码,不是拦截不到TAB键,而是你的程序的问题。对于鼠标单击没有
什么问题,但是对于按键处理却有问题。在按键处理时,你也是使用WindowFromPoint(pos);
这是不对的。当用户按键时,接收输入的窗口和鼠标下面的窗口,根本就是2个不同的窗口。
当用户按TAB键切换窗口时,鼠标没有动,所以你用WindowFromPoint(pos);得到的窗口自然
还是之前用WindowFromPoint(pos);得到的窗口。执行下面的if(cchild!=pchild)时,条件
当然不成立,结果当然不会向TMemo里添加文字了。
回复
nightfallrove 2003-05-18
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop
#include <mem.h>
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
HHOOK RecordHook=NULL;
HWND window=NULL;//当前活动窗口
HWND pchild=NULL;//前一个获得焦点的子控件
HWND cchild=NULL;//当前获得焦点的子控件
POINT pos;//鼠标点击的位置
char buffer[2048];//用来保存截到的输入数据
char title[512];//窗口标题
char cname[256];//子控件类名
HOOKPROC RecordProc(int code,WPARAM wp,LPARAM lp)//钩子
{
if(code<0)
return (HOOKPROC)CallNextHookEx(RecordHook,code,wp,lp);
if(code!=HC_ACTION)
return (HOOKPROC)CallNextHookEx(RecordHook,code,wp,lp);
//window=GetActiveWindow();
EVENTMSG *pEvent=(EVENTMSG*)lp;
if((pEvent->message==WM_KEYDOWN)||(pEvent->message==WM_KEYUP)
||(pEvent->message==WM_LBUTTONDOWN)
||(pEvent->message==WM_RBUTTONDOWN))
{
int vkey=(BYTE)(pEvent->paramL);
if((keywindow<0)&&(vkey==VK_F12))
Form1->Close();
GetCursorPos(&pos);//显示鼠标位置
Form1->Label2->Caption=IntToStr(pos.x)+" , "+IntToStr(pos.y);
cchild=WindowFromPoint(pos);//得到子控件句柄,类型
GetClassName(cchild,cname,256);
Form1->Label4->Caption=cname;
if(cchild!=pchild)//text是一个memo组件,我用来显示用户的输入数据
{
Form1->text->Lines->Append(strcat(strcat(title,": "),buffer));
memset(buffer,0,2048);
memset(title,0,512);
pchild=cchild;
SendMessage(cchild,WM_GETTEXT, 2048,(long)buffer);
}
else
{
window=GetActiveWindow();
GetWindowText(window,title,512);
SendMessage(cchild,WM_GETTEXT, 2048,(long)buffer);
}
}
return (HOOKPROC)CallNextHookEx(RecordHook,code,wp,lp);
}

void __fastcall TForm1::Button1Click(TObject *Sender)//安装HOOK
{
if(RecordHook==NULL)
RecordHook=SetWindowsHookEx(
WH_JOURNALRECORD,
(HOOKPROC)RecordProc,
HInstance,
NULL);
Form1->Button1->Enabled=false;
Form1->FormStyle=fsStayOnTop;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)//卸下HOOK
{
if(RecordHook)
{
UnhookWindowsHookEx(RecordHook);
Form1->Button1->Enabled=true;
RecordHook=NULL;
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
if(RecordHook)
{
UnhookWindowsHookEx(RecordHook);
RecordHook=NULL;
}
}

//---------------------------------------------------------------------------

//清屏
void __fastcall TForm1::Button3Click(TObject *Sender)
{
Form1->text->Lines->Clear();
}
//---------------------------------------------------------------------------

回复
jishiping 2003-05-17
“如果用户用鼠标切换输入框则可以得到输入的内容,但是如果用户用TAB键切换则无法得到
输入的内容”

这说明,用户按Tab键时,你的钩子函数没有拦截到。你的代码怎么写的,需要将调用函数
SetWindowsHookEx的代码以及回调函数的相关代码都贴出来,才知道错在哪儿。
回复
Lewolf 2003-05-15
看一看WantTab属性,有一些Edit类的控件可以自己获取Tab,而不是转移焦点的。
回复
相关推荐
综教楼后的那个坑用双向链表实现 描述   在 LIT 综教楼后有一个深坑,关于这个坑的来历,有很多种不同的说法。其中一种说法是,在很多年以前,这个坑就已经在那里了。这种说法也被大多数人认可,这是因为该坑有一种特别的结构,想要人工建造是有相当困难的。   从横截面图来看,坑底成阶梯状,由从左至右的 1..N 个的平面构成(其中 1 ≤ N ≤ 100,000),如图:    *            * :    *            * :    *            * 8    *    **      * 7    *    **      * 6    *    **      * 5    *    ********* 4 <- 高度    *    ********* 3    ************** 2    ************** 1 平面 |  1  |2|   3    | 每个平面 i 可以用两个数字来描述,即它的宽度 Wi 和高度 Hi,其中 1 ≤ Wi ≤ 1,000、1 ≤ Hi ≤ 1,000,000,而这个坑最特别的地方在于坑底每个平面的高度都是不同的。每到夏天,雨水会把坑填满,而在其它的季节,则需要通过人工灌水的方式把坑填满。灌水点设在坑底位置最低的那个平面,每分钟灌水量为一个单位(即高度和宽度均为 1)。随着水位的增长,水自然会向其它平面扩散,当水将某平面覆盖且水高达到一个单位时,就认为该平面被水覆盖了。   请你计算每个平面被水覆盖的时间。    灌水 水满后自动扩散 | | * | * * | * * * * V * * V * * * * * * .... * *~~~~~~~~~~~~* * ** * *~~~~** : * *~~~~**~~~~~~* * ** * *~~~~** : * *~~~~**~~~~~~* * ** * *~~~~**~~~~~~* *~~~~**~~~~~~* * ********* *~~~~********* *~~~~********* *~~~~********* *~~~~********* *~~~~********* ************** ************** ************** ************** ************** **************    4 分钟后    26 分钟后        50 分钟后    平面 1 被水覆盖     平面 3 被水覆盖    平面 2 被水覆盖输入   输入的第一行是一个整数 N,表示平面的数量。从第二行开始的 N 行上分别有两个整数,分别表示平面的宽度和高度。 输出   输出每个平面被水覆盖的时间。
发帖
Windows SDK/API
创建于2007-08-02

1206

社区成员

C++ Builder Windows SDK/API
申请成为版主
帖子事件
创建了帖子
2003-05-13 02:05
社区公告
暂无公告