I want to detect everytime I paste something. It's just something to make some data entry work simpler.
I set a global hook and then "wait" for the wm_paste. This is part of the code I have:
LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if(nCode < 0)//Do not process the message
return CallNextHookEx(msg_hook,nCode,wParam,lParam);
LPMSG m=(LPMSG)lParam;
if(m->message == WM_PASTE)
{
OutputString("Paste detected!\n");
}
if(m->message == WM_PASTE)
{
OutputString("Paste detected!\n");
}
return CallNextHookEx(msg_hook,nCode,wParam,lParam);
}
//DLL_ATTACH:
...
if(strstr(ProcName, LOADERNAME))
{
InitCommonControls();
if(!(msg_hook=SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, hinstDLL, 0)))
{
ErrorExit(TEXT("SetWindowsHookEx"));
//MessageBox(0, "WH_GETMESSAGE", 0, 0);
//return -1;
}
}
WM_PASTE debug string never gets printed. I'm aware that not all applications use WM_PASTE. But at least notepad should work.
Any suggestions?
Thanks!
In GetMsgProc, the wParam parameter is not the message being intercepted, but a flag that indicates whether or not the message in lParam and been removed from the message queue.
You should be using m->wParam instead.
Wm_paste message is fired only in combo box and edit control. There is no easy way to capture paste, but you can get copy message by creating a tiny window and adding this window to the chain of clipboard viewers.
Related
I have two devices that create keyboard input, one of them is a real keyboard and the other uses SendInput() to send Injected keyboard input. I am modifying an existing program that uses a hook to send the keyboard message only to its own window and blocks the input globally to other programs. However I do not want the Injected input to be blocked, and I also don't want the program to process the Injected input.
I used a WH_KEYBOARD_LL hook to determine if the input is Injected, Then I used a global WH_KEYBOARD hook to send the message only to the window if it is the real keyboard. What I am looking for is a way to sendMessage() to everything except the main window. I couldn't find a method in the documentation to do this though, so I decided to pass the hook farther down.
// WH_KEYBOARD
static LRESULT CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam) {
if (code < 0) {
return CallNextHookEx(hookHandle, code, wParam, lParam);
}
//Report the event to the main window, but do not pass it to the hook chain
if (realKeyboard) {
SendMessage(hwndServer, WM_HOOK, wParam, lParam);//only listen to real keyboard, block emulated one
}
else {
//what i want is to sendMessage to everythng except the main window
return CallNextHookEx(hookHandle, code, wParam, lParam); //let injected keyboard passthrough
//however we want to ignore injected inputs in the main window(keyboard program).
}
return 1;
}
I created a local WH_GETMESSAGE hook using GetCurrentThreadId(), to see if I could ignore the injected input there.
// WH_GETMESSAGE
static LRESULT CALLBACK GetMessageProc(int code, WPARAM wParam, LPARAM lParam) {
if (code < 0) {
return CallNextHookEx(hookHandle, code, wParam, lParam);
}
if (!realKeyboard) {
MSG * info = (MSG *)lParam;
info->message = WM_NULL;
}
return CallNextHookEx(hookHandle, code, wParam, lParam);
}
I read somewhere that info->message = WM_NULL; would work to block the message but it doesn't seem to have an effect. I also Tried creating a message loop something like this but it didn't work either.
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
if(IsRealKeyboard()){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
Any ideas how I can ignore the injected message only in the main window and let it through to the rest of the system?
You could use RAW INPUT in the target window and process the WM_INPUT message, then get the Raw Input buffer via GetRawInputData.
I am trying to add the possibility to use the RETURN key in an already made Login/Password form.
The thing is, I didn't make the form, and it is the first time I've used the Window API for Windows. So there is a lot I don't know...
So basically, a window is created, and inside of it, three child "windows" are created.
One editable: Login
A second one editable: Password
And a button: OK
Basically, I added a handle for the WM_CHAR in the message callback method:
else if (msg == WM_CHAR)
{
if (wParam == VK_RETURN)
{
char BufLogin[128];
char BufPasswd[128];
GetWindowText(hwndEditLogin, BufLogin, sizeof(BufLogin));
GetWindowText(hwndEditPasswd, BufPasswd, sizeof(BufPasswd));
print_msg(BufLogin);
print_msg(BufPasswd);
return (0);
}
else
return (DefWindowProcW(hwnd, msg, wParam, lParam));
}
(I also tried by replacing WM_CHAR with WM_KEYDOWN to no success.)
I checked on stack overflow, and the only solutions I've found so far talk of things I don't understand, or simply don't work...
I added a check in the message loog like so:
while(GetMessage(&msg, NULL, 0, 0))
{
if (!IsDialogMessage(hWnd, &msg) || msg.wParam == VK_RETURN)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
And it did work, unless the user had clicked on any child window... Basically, it worked if the user hadn't clicked on anything or modified anything, which makes the Login/password part of the window pretty useless! ^^'
So what I'm guessing is that the (!IsDialogMessage) check rules out the WM_CHAR and the WM_KEYDOWN messages (still allowing the user to type for some reason), and if I add the check for the wParam, it works but only for the parent window.
If you guys had any idea on how to work aroun this conundrum of mine, I would be so grateful! Thanks in advance! :)
(P.S.: I edited this question, before I asked on how to make the TAB key work, because the IsDialogMessage check would make each character appear four times. I simply forgot to put the ! before the IsDialogMessage! ^^'
I make this note in case anyone found my question and had the same problem I had before editing! ;) )
Ok, so I've finally figured it out! Here's my solution for it if anyone needs to do the same! ;)
I made two global variables, one for each window that needs to handle the ENTER key:
WNDPROC wpOldEditProcPass;
WNDPROC wpOldEditProcLogin;
Then I created two CALLBACK methods, again, one for each window:
(Placed them before my main CALLBACK)
LRESULT CALLBACK CustomEditProcLogin(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CHAR:
{
if (wParam == VK_RETURN)
{
SendMessage(GetParent(hWnd), WM_COMMAND, MAKEWPARAM(ID_BUTTON, BN_CLICKED), 0);
return(0);
}
}
}
CallWindowProc(wpOldEditProcLogin, hWnd, msg, wParam, lParam);
}
LRESULT CALLBACK CustomEditProcPass(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CHAR:
{
if (wParam == VK_RETURN)
{
SendMessage(GetParent(hWnd), WM_COMMAND, MAKEWPARAM(ID_BUTTON, BN_CLICKED), 0);
return(0);
}
}
}
CallWindowProc(wpOldEditProcPass, hWnd, msg, wParam, lParam);
}
In the main CALLBACK, in the WM_CREATE handle, after I created the child windows, I subclassed them:
wpOldEditProcPass = (WNDPROC)SetWindowLongPtr(hwndEditPasswd, GWLP_WNDPROC, (LONG_PTR)CustomEditProcPass);
wpOldEditProcLogin = (WNDPROC)SetWindowLongPtr(hwndEditLogin, GWLP_WNDPROC, (LONG_PTR)CustomEditProcLogin);
And then in WM_DESTROY, I gave them back their original process:
(Before PostQuitMessage(0); )
SetWindowLongPtr(hwndEditPasswd, GWLP_WNDPROC, (LONG_PTR)wpOldEditProcPass);
SetWindowLongPtr(hwndEditLogin, GWLP_WNDPROC, (LONG_PTR)wpOldEditProcLogin);
And then I replaced the:
if (!IsDialogMessage(hWnd, &msg))
With:
if (!IsDialogMessage(hWnd, &msg) ||(msg.message == WM_KEYDOWN && msg.wParam == VK_RETURN))
And it works like a charm! :D
(I still can't figure out why I have to allow a WM_KEYDOWN message, but handle a WM_CHAR message... If I allow a WM_CHAR message, it doesn't work, and if I handle a WM_KEYDOWN message, I get the obnoxious "Ding" sound when I press enter! ^^' )
I am having issues with creating a modeless dialog from a DLL file. My dialog has nothing special on it, just an OK button and an edit box. I have looked at this Microsoft KB Article (http://support.microsoft.com/kb/233263) and have implemented its solution to create a window hook to grab and process messages.
The method provided by Microsoft solves the tab key problem, however, it creates another problem. When I type into the edit box on the dialog, whatever I press is duplicated 4 times. For example, if I press 'a' on the keyboard, 'aaaa' will show up in the edit box.
If I disable the Window Hook, then the edit box works correctly and only displays one 'a'.
What do I need to do to the Window Hook procedure to solve this problem?
Any help is greatly appreciated.
- - EDIT - -
As per request, my Window Hook Procedure Code: (It's the same as the KB article)
LRESULT FAR PASCAL GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam) {
LPMSG lpMsg = (LPMSG) lParam;
if (nCode >= 0 && PM_REMOVE == wParam) {
// Don't translate non-input events.
if ((lpMsg->message >= WM_KEYFIRST && lpMsg->message <= WM_KEYLAST)) {
if (IsDialogMessage(hwndDllDlg, lpMsg)) {
// The value returned from this hookproc is ignored,
// and it cannot be used to tell Windows the message has been handled.
// To avoid further processing, convert the message to WM_NULL
// before returning.
lpMsg->message = WM_NULL;
lpMsg->lParam = 0;
lpMsg->wParam = 0;
}
}
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
My Dialog Callback Procedure:
BOOL CALLBACK DllDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_INITDIALOG:
hHook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, NULL, GetCurrentThreadId());
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
DestroyWindow(hwndDlg);
hwndDllDlg = NULL;
}
return TRUE;
case WM_DESTROY:
UnhookWindowsHookEx(hHook);
return FALSE;
}
return FALSE;
}
}
Both hHook and hwndDllDlg are defined as HHOOK and HWND respectively.
HHOOK hHook;
HWND hwndDllDlg = CreateDialog(0, MAKEINTRESOURCE(DLG_MAIN), 0, DllDlgProc);
I looked at the KB article. It sounds reasonable. There is some point where you was not enough accurate while following the instructions from KB. Post your code. This may help.
If you have control over the message pump of the executable and can add IsDialogMessage there, then you do not need any hook. Code from the dll is part of the code of the process. Window handles are in the common space either.
Other approach is starting your own UI thread. If you create your dialog on this thread, then you will have your own message pump. The hook will not be needed in this case either.
Well, this is more of a question to author of the post..
I have the tab key issue and am trying to understand the microsoft article better.
So my dialog is shipped out as Dll and the application which I don't have access to is launching dialog from my dll.
HWND hwndDllDlg = CreateDialog(0, MAKEINTRESOURCE(DLG_MAIN), 0, DllDlgProc);
I don't understand what dialog the code refers to when they said hwndDllDlg in the article. Should I point my dialog creation to this variable ?
I'm using Windows 7 and VC++. The business is to know how many seconds my system has been set into screen saver mode or monitor screen off. To achieve this, I'm trying to catch the events WM_SYSCOMMAND and SC_SCREENSAVE, SC_MONITORPOWER. So I have created a Win32 project in Visual Studio 2008 and I'm receiving the events in WndProc function:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_SYSCOMMAND:
{
switch (LOWORD(wParam))
{
case SC_SCREENSAVE:
{
FILE *fl = fopen("this_is_a_event_test.txt","a");
fputs("SC_SCREENSAVE\n",fl);
fclose(fl);
}
break;
case SC_MONITORPOWER:
{
FILE *fl = fopen("this_is_a_event_test.txt","a");
fputs("SC_MONITORPOWER\n",fl);
fclose(fl);
}
break;
default:
{
}
}
}
break;
}
}
It works fine when dialog is in foreground, but in background (or if I comment ShowWindow function) it only works if I manually send the events:
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_SCREENSAVE, (LPARAM)2);
or
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM)2);
So, it is not working when system power configuration sets the screen saver after 2 minutes of inactivity, and the same thing with automatic monitor screen off. Thats the real thing I want, know when the system is turning off the screen or setting the screen saver, with a background monitoring program.
I have also tried to use hook events with extern dll. I have followed this example http://www.codeproject.com/Articles/1037/Hooks-and-DLLs adding in the CALLBACK msghook() function the same switch code above in WndProc. It doesn't work even using the SendMessage.
After several days stuck with this issue, searching in the Internet, forums... I don't know what else I can do. Can anyone help me?
I were not using hooks properly, but it has been rare. Firstly, about setWindowsHookEx function, I have read WH_CALLWNDPROC or WH_SYSMSGFILTER must be used to get WM_SYSCOMMAND sent messages, and then get SC_SCREENSAVE wParam. In this case, I don't know why and maybe I'm wrong, but thats seems not to be true.
After use every possible message to SetWindowsHookEx, I realised WH_GETMESSAGE is the only one who sends SC_SCREENSAVE wParam, at least in this hook example in Windows 7.
HHOOK hook;
HHOOK hook = SetWindowsHookEx(WH_GETMESSAGE,
(HOOKPROC)msghook,
hInst,
0);
Secondly, listening for every message catched in hook function, WM_SYSCOMMAND were appeared with LPMSG. I have read also that wParam must to be combined to 0xFFF0 to be compared. But wParam & 0xFFF0 == SC_SCREENSAVE didn't work and wParam == SC_SCREENSAVE neither. In this case the only way is using LPMSG for both WM_SYSCOMMAND and SC_SCREENSAVE.
static LRESULT CALLBACK msghook(UINT code, WPARAM wParam, LPARAM lParam)
{
if(code > 0)
{
CallNextHookEx(hook, code, wParam, lParam);
return 0;
}
LPMSG msg = (LPMSG)lParam;
if(msg->message == WM_SYSCOMMAND)
{
if (msg->wParam == SC_SCREENSAVE)
{
MessageBoxA(NULL,L"SC_SCREENSAVE",L"SC_SCREENSAVE",MB_OK);
}
if (msg->wParam == SC_MONITORPOWER)
{
MessageBoxA(NULL,L"SC_MONITORPOWER",L"SC_MONITORPOWER",MB_OK);
}
}
return CallNextHookEx(hook, nCode, wParam, lParam);
}
And using FILE to test the events was a very bad idea, I think using MessageBox is not much better but I don't know how to test ir correctly.
I want to print out a message using MessageBox (or similar). I would also like control over where exactly on the screen the box appears but can find nothing in the description of MessageBox that allows you control over the location. Did I miss something? If MessageBox can not be used, then is there an alternative?
For reasons too complex to go into here, I would prefer an answer which didn't involve making my own window and passing the address of a callback function.
Step 1: Create a CBT hook to trap the creation of the message box:
// global hook procedure
HHOOK hhookCBTProc = 0;
LRESULT CALLBACK pfnCBTMsgBoxHook(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode == HCBT_CREATEWND)
{
CREATESTRUCT *pcs = ((CBT_CREATEWND *)lParam)->lpcs;
if (pcs->style & WS_DLGFRAME || pcs->style & WS_POPUP)
{
HWND hwnd = (HWND)wParam;
// At this point you have the hwnd of the newly created
// message box that so you can position it at will
SetWindowPos(hwnd, ...);
}
}
return CallNextHookEx(hhookCBTProc, nCode, wParam, lParam);
}
Step 2: Install/remove the hook before and after showing the message box:
// set hook to center the message box that follows
hhookCBTProc = SetWindowsHookEx(WH_CBT,
pfnCBTMsgBoxHook,
0, GetCurrentThreadId());
int sResult = MessageBox(hwndParent, pszMsg, pszTitle, usStyle);
// remove the hook
UnhookWindowsHookEx(hhookCBTProc);
If I needed additional behavior for a Messagebox I always created my own window and made it look like a standard MessageBox. You do it right once and you can always reuse it in other projects.
MessageBox is a basically a set of defaults. Don't like them? Bring your own. If you don't want a real window with all its complexities, but MessageBox is too restrictring, create a dialog.
You could do this with a CBT hook procedure. There is an MSDN article on how to do this in VB but converting it to C++ wouldn't be hard.
http://support.microsoft.com/kb/180936