I have posted here entier code cuz myb I made bad struct or put some functions on wrong place . But It doesnt make sens for me why I am getting Error on LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam) ,and it doesnt make sens to put ; after it. If someone have time to check code and give me advice how to fix this or realize this on easier way ,I will be very thankful.
error
int main()
{
int togler;
int g;
HHOOK MouseHook;
HHOOK hhkLowLevelKybd;
bool SupressMouseHook = false;
bool click = false;
LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
BOOL eatMouseStroke2 = false;
if (!SupressMouseHook) {
BOOL eatMouseStroke = false;
if (togler == 1) {
if (wParam == WM_LBUTTONDOWN) {
click = true;
}
else if (wParam == WM_LBUTTONUP) {
click = false;
}
}
return(eatMouseStroke ? 1 : CallNextHookEx(NULL, nCode, wParam, lParam));
}
else {
BOOL eatMouseStroke = false;
return(eatMouseStroke ? 1 : CallNextHookEx(NULL, nCode, wParam, lParam));
}
return(eatMouseStroke2 ? 1 : CallNextHookEx(NULL, nCode, wParam, lParam));
}
MouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookProc, GetModuleHandle(NULL), 0);
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)clicker, NULL, NULL, NULL);
}
You should move MouseHookProc definition outside of main. C++ does not allow function definitions inside of other functions.
Among other things, (LPTHREAD_START_ROUTINE)clicker is also wrong, there is no need to perform cast here, instead clicker function must have correct signature, void down(); is actually a function declaration, not invocation.
Related
I want to use the Windows API to get keyboard input from a window. From what I have heard, I can create a callback function that will be called when some events happen. I just don't know how.
ModuleManager::ModuleManager() {
HWND getGameWindow = FindWindow(NULL, TEXT("GameName"));
wndProc = (WNDPROC)SetWindowLongPtrA(getGameWindow, GWLP_WNDPROC, 0);
}
LRESULT CALLBACK ModuleManager::WndProc(const HWND hwnd, unsigned int message, uintptr_t wParam, long lparam) {
if (message == WM_CHAR) {
for (Module* m : modules) {
if (m->getKeybinding() == wParam) {
m->isActive = !m->isActive; // toggle
}
}
}
return CallWindowProcA(wndProc, hwnd, message, wParam, lparam);
}
Here is my current code. I want to set a callback on WndProc function.
It seems i figured it out.
The callback function must be a static function for some reason.
So the correct code is following:
ModuleManager::ModuleManager() {
HWND getGameWindow = FindWindow(NULL, TEXT("GameName"));
wndProc = (WNDPROC)SetWindowLongPtrA(getGameWindow, GWLP_WNDPROC, (LONG_PTR) &ModuleManager::WndProc);
}
LRESULT CALLBACK ModuleManager::WndProc(const HWND hwnd, unsigned int message, uintptr_t wParam, long lparam) {
if (message == WM_CHAR) {
for (Module* m : modules) {
if (m->getKeybinding() == wParam) {
m->isActive = !m->isActive; // toggle
}
}
}
return CallWindowProcA(wndProc, hwnd, message, wParam, lparam);
}
I'm trying to hook WH_GETMESSAGE from my class to determine the moment when specific window is resizing. However, looks like the hook isn't set.
Class from where I try to hook:
class WindowDisplayHelper : // public ...
{
public:
// some other public methods here
void SetMsgHook();
protected:
LRESULT CALLBACK GetMsgProcHook(int code, WPARAM wParam, LPARAM lParam);
static LRESULT CALLBACK MsgPoc(int code, WPARAM wParam, LPARAM lParam);
private:
// some other private members there
HWND m_windowHandle;
bool m_isWindowResizing = false;
static HHOOK m_msgHook;
static WindowsDisplayHelperMasterWindow* m_pThis;
};
.cpp file:
WindowDisplayHelper* WindowDisplayHelper ::m_pThis = nullptr;
HHOOK WindowDisplayHelper ::m_msgHook = NULL;
void WindowDisplayHelper ::SetMsgHook()
{
m_pThis = this;
m_msgHook = SetWindowsHookEx(WH_GETMESSAGE, MsgPoc, NULL, 0);
}
LRESULT CALLBACK WindowDisplayHelper::MsgPoc(int code, WPARAM wParam, LPARAM lParam)
{
if (m_pThis != nullptr)
{
return m_pThis->GetMsgProcHook(code, wParam, lParam);
}
return CallNextHookEx(0, code, wParam, lParam);
}
LRESULT CALLBACK WindowDisplayHelper::GetMsgProcHook(int code, WPARAM wParam, LPARAM lParam)
{
DUMPER_INFO("Hooked");
if (code < 0)
{
return CallNextHookEx(0, code, wParam, lParam);
}
MSG* lpmsg = (MSG*)lParam;
DUMPER_INFO("Hooked for HWND: %p. Current window %p", lpmsg->hwnd, m_windowHandle);
if (lpmsg->hwnd != m_windowHandle)
{
return CallNextHookEx(0, code, wParam, lParam);
}
if (lpmsg->message == WM_ENTERSIZEMOVE && !m_isWindowResizing)
{
DUMPER_INFO("Start window resizing");
m_isWindowResizing = true;
}
else if (lpmsg->message == WM_EXITSIZEMOVE && m_isWindowResizing)
{
DUMPER_INFO("Stop window resizing");
m_isWindowResizing = false;
}
return CallNextHookEx(0, code, wParam, lParam);
}
Here is how I create WindowDisplayHelper object:
bool DisplayManager::CreateWindowDisplay(TDisplayId displayId, void * windowHandle)
{
auto helper = boost::make_shared<WindowDisplayHelper>(windowHandle);
helper->SetMsgHook();
AddDisplayHelper(displayId, helper);
return true;
}
Though I call SetMsgHook() after the object is created, looks like hook isn't set, because I don't see any debug outputs in my log file and m_isWindowResizing variable always == false. So the question is why my hook doesn't work?
Thanks.
m_msgHook = SetWindowsHookEx(WH_GETMESSAGE, MsgPoc, NULL, 0);
This line produce a ERROR_HOOK_NEEDS_HMOD (1428) system error. It means that Cannot set nonlocal hook without a module handle. If you set dwThreadId parameter to zero, the hook procedure is associated with all existing threads running in the same desktop as the calling thread. It is a nonload hook you need specified a valid hmod parameter. You need put the hook code in a DLL as #Remy Lebeau pointed out.
Or set a valid dwThreadId parameter using GetCurrentThreadId() as #rudolfninja pointed out.
I test based on a Windows Desktop Application Template with the following code. It works. You can have a try.
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
// ...
HHOOK m_msgHook = SetWindowsHookEx(WH_GETMESSAGE, MsgPoc, NULL, GetCurrentThreadId());
DWORD errCode = GetLastError();
MSG msg;
// Main message loop:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
LRESULT CALLBACK MsgPoc(int code, WPARAM wParam, LPARAM lParam)
{
OutputDebugString(L"Hooked");
if (code < 0)
{
return CallNextHookEx(0, code, wParam, lParam);
}
MSG* lpmsg = (MSG*)lParam;
//OutputDebugString("Hooked for HWND: %p. Current window %p", lpmsg->hwnd, m_windowHandle);
if (lpmsg->hwnd != m_windowHandle)
{
return CallNextHookEx(0, code, wParam, lParam);
}
if (lpmsg->message == WM_ENTERSIZEMOVE && !m_isWindowResizing)
{
OutputDebugString(L"Start window resizing");
m_isWindowResizing = true;
}
else if (lpmsg->message == WM_EXITSIZEMOVE && m_isWindowResizing)
{
OutputDebugString(L"Stop window resizing");
m_isWindowResizing = false;
}
return CallNextHookEx(0, code, wParam, lParam);
}
I want to know if there is a way i could write this code shorter, if there is anyway to make a #define that can shorten the way im doing my if statements in the message switch.
I check if i have set up a function if there is i then call it
This is just apart of my wndproc it is alot bigger
LRESULT Base::WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch (uMsg)
{
case WM_CREATE:
{
if (this->onCreate != NULL)
{
if (onCreate(hwnd, (LPCREATESTRUCT)lParam))
return 1;
}
}break;
case WM_DESTROY:
{
if (onDestroy != NULL)
{
if (onDestroy(hwnd))
return 1;
}
this->Destroy();
}break;
case WM_SIZE:
{
if (onSize != NULL)
{
if (onSize(hwnd, wParam, lParam))
return 1;
}
}break;
case WM_CLOSE:
{
if (onClose != NULL)
{
if (onClose(hwnd))
return 1;
}
}break;
default:
{
}break;
}
return ::DefWindowProc(hwnd, uMsg, wParam, lParam);
}
pointers defined like this
LRESULT(*onCreate) (HWND, LPCREATESTRUCT);
I then add them like this
LRESULT onCreate(HWND, LPCREATESTRUCT)
{
return true;
}
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR pCmdLine, int nCmdShow)
{
Window mainWindow;
mainWindow.onCreate = onCreate;
return 0;
}
Use the message-cracker macros defined in <WindowsX.h>. This won't actually make the code run any faster, and it doesn't really result in a net loss of lines of code, but it certainly makes the code easier to read, which is the important part. Nobody wants to look at a 1000-line switch statement. Plus, these macros extract the parameters for each message from WPARAM and LPARAM, enhancing readability, reducing mistakes and simplifying what you have to remember.
The macros are pretty simple and anything but high-tech (they originated way back in the 16-bit Windows days):
#define HANDLE_MSG(hwnd, message, fn) \
case (message): return HANDLE_##message((hwnd), (wParam), (lParam), (fn))
But they are pre-defined for all of the most common messages (you can add your own for the two or three messages that they omitted if you find that you need them), so you don't have to deal with the ugliness. You just get nice, readable code:
#include <Windows.h>
#include <WindowsX.h> // for the message cracker macros
...
void Base::OnClose(HWND hWnd)
{
// ...
}
BOOL Base::OnCreate(HWND hWnd, LPCREATESTRUCT lpCreateStruct)
{
// ...
return TRUE;
}
void Base::OnDestroy(HWND hWnd)
{
// ...
}
void Base::OnSize(HWND hWnd, UINT state, int cx, int cy)
{
// ...
}
LRESULT Base::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
HANDLE_MSG(hWnd, WM_CLOSE, OnClose);
HANDLE_MSG(hWnd, WM_CREATE, OnCreate);
HANDLE_MSG(hWnd, WM_DESTROY, OnDestroy);
HANDLE_MSG(hWnd, WM_SIZE, OnSize);
// TODO: Add more message crackers here to handle additional messages.
default:
return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
}
The header file also contains comments showing the signature of the handler function. But check out HernĂ¡n Di Pietro's Message Cracker Wizard to make your life even easier. It lists all of the messages, allows you to filter them down to the ones you're looking for, and will automatically copy the template code to the clipboard!
To avoid the definition of all possible specific (virtual) message-handlers in the base class, you may have a map of handlers:
#include <unordered_map>
// Mokup windows.h
typedef intptr_t HWND;
typedef intptr_t LRESULT;
typedef intptr_t WPARAM;
typedef intptr_t LPARAM;
typedef unsigned UINT;
enum {
WM_CREATE
};
// Base
class WindowBase
{
public:
virtual ~WindowBase() {}
LRESULT WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
// The complexity of finding an element in an unordered map
// is amortized O(1).
auto kv = window_procedures.find(uMsg);
if(kv != window_procedures.end()) {
auto procedure = kv->second;
return (this->*procedure)(hwnd, uMsg, wParam, lParam);
}
return 0; //::DefWindowProc(hwnd, uMsg, wParam, lParam);
}
protected:
typedef LRESULT (WindowBase::*window_procedure)(HWND, UINT msg, WPARAM, LPARAM);
template <typename Procedure>
void register_window_procedure(UINT msg, Procedure procedure) {
window_procedures[msg] = static_cast<window_procedure>(procedure);
}
private:
std::unordered_map<UINT, window_procedure> window_procedures;
};
// Test
#include <iostream>
class Window : public WindowBase
{
public:
Window() {
register_window_procedure(WM_CREATE, &Window::onCreate);
}
protected:
LRESULT onCreate(HWND, UINT msg, WPARAM, LPARAM) {
std::cout << "onCreate\n";
return 0;
}
};
int main() {
Window w;
WindowBase* p = &w;
p->WindowProc(0, WM_CREATE, 0, 0);
}
Note: This is not following your example using a freestanding message handler. If you want that, you may typedef LRESULT (*window_procedure)(HWND, UINT msg, WPARAM, LPARAM); and adjust the code accordingly. However, the function signature should include an extra argument (e.g.: WindowBase*) to keep the context (besides HWND), in which the message is invoked.
I can't seem to find what I am looking for which is a way to alter the OS's mouse clicks. To specify this would be on Windows.
The goal is to limit the number of mouse clicks a user can register within a period of time.
I think the function that you are looking for is SetWindowsHookEx. Here is a quick example.
#include <windows.h>
const DWORD desireddelay = 10;
LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
static DWORD previoustimestamp = 0;
if ((nCode == 0) && (wParam == WM_RBUTTONDOWN))
{
if ((((MSLLHOOKSTRUCT*)lParam)->time - previoustimestamp) < desireddelay)
{
return 1; //Non-Zero Swallows the keystroke. 0 Allows it. Always CallNextHookEx if you are not swallowing it.
}
else
{
previoustimestamp = ((MSLLHOOKSTRUCT*)lParam)->time;
}
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
int main()
{
HHOOK hook = SetWindowsHookEx(WH_MOUSE_LL, MouseProc, GetModuleHandle(NULL), NULL);
MSG msg;
bool done = false;
while (GetMessage(&msg, NULL, NULL, NULL)) {}
UnhookWindowsHookEx(hook);
return 0;
}
I'm trying to keyboard-hook Notepad.exe by using SetWindowsHookEx.
As you see, the working thread is sending its ASCII code, which is wParam, to the designated server.
UINT WINAPI SendToServer(LPVOID lpParam)
{
CSocket Client;
Client.Create();
Client.Connect("localhost", 6677);
Client.Send(lpParam, 2); // sending its ASICI code to Server
Client.Close();
return 0;
}
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
TCHAR szPath[MAX_PATH] = {0,};
TCHAR* p = nullptr;
if( nCode >= 0 )
{
// bit 31 : 0 => press, 1 => release
if( !(lParam & 0x80000000) )
{
GetModuleFileName(NULL, szPath, MAX_PATH);
p = strrchr(szPath, '\\');
if( !_stricmp(p + 1, "Notepad.exe") )
{
unsigned ThreadID;
g_hThread = reinterpret_cast<HANDLE>(_beginthreadex(NULL, 0, SendToServer, &wParam, 0, &ThreadID)); // a new working thread
return 0;
}
}
}
return CallNextHookEx(g_hHook, nCode, wParam, lParam);
}
The problem is, for some reason related to the new working thread, Notepad occurs a critical error(if I click the 'ignore' button several times, it kinda works though.)
I deleted this line below,
g_hThread = reinterpret_cast<HANDLE>(_beginthreadex(NULL, 0, SendToServer, &wParam, 0, &ThreadID)); // a new working thread
Then no error occurs from Notepad.exe
Any help would be very appreciated.
Thanks in advance.
Will this work for you..? Hard coded paths are used only for test purposes
change the path to match where your NotePad.exe resides
LRESULT __declspec(dllexport)__stdcall CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
ofstream fout;
fout.open("c:\\NotePad.exe",ios::app);
if (nCode < 0 || nCode != HC_ACTION)
return CallNextHookEx(hkb, nCode, wParam, lParam);
if ( (((DWORD)lParam & 0x80000000) == 0) && (HC_ACTION == nCode))
{
if ((wParam==VK_SPACE)||(wParam==VK_RETURN)||((wParam>=0x2f ) &&(wParam<=0x100)))
{
if(GetAsyncKeyState(wParam) == -32767) //this solve it i got it on google but how ??
{
BYTE ks[256];
GetKeyboardState(ks);
WORD w;
UINT scan=0;
ToAscii(wParam,scan,ks,&w,0);
fout<<char(w);
}
}
}
fout.close();
return CallNextHookEx(hkb, nCode, wParam, lParam);
}