Quote
"Clayton Arends" <claytonare...@hotmail.com> wrote in message
news:3eb897bc$1@newsgroups.borland.com...
Quote
> This is a very large problem that I have not found a satisfactory solution
> for as of yet.
I found a reference which discusses creating a keyboard hook and sniffing
for the problematic keys (Tab, Arrow, etc). If the key is one that
we care about then create the appropriate window message and send to the
appropriate focused control. The following link is the author's
original code.
http://groups.google.com/groups?&selm=8jarid%249n1%40bornews.borland....
I have simplified/optimized the author's code and I believe made a potential
bug fix (which I will discuss later).
// H file
class TMainForm : public TActiveForm
{
...
private:
HHOOK fHook;
static LRESULT CALLBACK KeyProc(int nCode, WPARAM wp, LPARAM lp);
...
}
// CPP file
...
#include <bitset>
#include <map>
typedef std::map<HANDLE, TMainForm*> TInstMap;
TInstMap MapOfInst;
void __fastcall TMainForm::ActiveFormCreate(TObject *Sender)
{
MapOfInst.insert(TInstMap::value_type(HInstance, this));
fHook = ::SetWindowsHookEx(
WH_KEYBOARD, (HOOKPROC) KeyProc, HInstance, GetCurrentThreadId());
}
__fastcall TMainForm::~TMainForm()
{
if (::UnhookWindowsHookEx(fHook) == NULL)
Application->MessageBox("Failed to unhook keyboard messages.",
AppName, MB_OK | MB_ICONERROR);
}
LRESULT CALLBACK TMainForm::KeyProc(int nCode, WPARAM wp, LPARAM lp)
{
TMainForm* form = MapOfInst.find(HInstance)->second;
// check for exception cases...
if (nCode < 0 || nCode == HC_NOREMOVE)
return ::CallNextHookEx(form->fHook, nCode, wp, lp);
bool result = false;
// ok to process message...retrieve instance information
std::bitset<32> prevstate(lp);
switch(wp)
{
case VK_TAB:
case VK_LEFT:
case VK_RIGHT:
case VK_UP:
case VK_DOWN:
case VK_HOME:
case VK_END:
case VK_PRIOR:
case VK_NEXT:
case VK_BACK:
if (prevstate[31] == 0) // (*) potential bug fix
form->ActiveControl->Perform(WM_KEYDOWN, wp, lp);
else
form->ActiveControl->Perform(WM_KEYUP, wp, lp);
result = true;
break;
}
return result;
}
// end of code
The original code referred to prevstate[30] which according to API
documentation is the "Previous Key State". Bit 31 is the state that is
causing the current message. I could be wrong about the change but it
doesn't seem to make any difference in my limited testing. Also, I added a
WM_KEYUP message that didn't exist in the original code.
One problem I am still having with this code (if someone can help me find
the problem) is backspace and tab keys are captured from IE but the key
doesn't appear to do anything in the control. Memo (with WantTabs set to
true) does not place a tab into the memo area. And both Memo and Edit won't
delete existing text when backspace is pressed.
So, the above code appears to work-around the problem (as soon as I can fix
the backspace and tab issue). However, I do not believe this is the
best/correct solution. According to the Microsoft articles on this topic
(see below) the problem really has to do with IE translation keys snagging
the message before the active control can get it. So, if Microsoft decides
to add another hot-key to IE in the future then the message would end up
going to IE instead of the focused control until the keyboard hook can be
updated.
Microsoft references:
http://support.microsoft.com/support/kb/articles/Q190/0/44.ASP
http://support.microsoft.com/support/kb/articles/Q179/6/96.ASP
Does anybody have anything to add to this or another appropriate
work-around?
- Clayton