I created a window with Win32s, I wish it could handle incoming messages from another thread in addition to typical windows messages.
I'm using this piece of code:
while (dataAvailable || GetMessage(&msg, nullptr, 0, 0))
{
// if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
if (dataAvailable == true)
{
cout << "My thread message/signal!" << endl;
dataAvailable = false;
}
else
{
//Windows message
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
the "DataAvailable" is an atomic bool that I set when I would like pass a my own message to win32 app/windows.
This don't work well.
It is possible to do this?
I suggest you to use standard messages. Register your own new message and use PostMessage from another thread to your main window thread.
I base my example code on standard windows sample code: https://github.com/microsoft/Windows-classic-samples/blob/main/Samples/Win7Samples/begin/LearnWin32/HelloWorld/cpp/main.cpp
In this code I add a standard std::thread :
// ...
auto th1 = std::thread([=] {
const UINT WM_EX_SOME_SPECIALINTERNALMESSAGE = ::RegisterWindowMessage(L"SomeSpecialInternalMessage");
for (int n = 0; n < 10; ++n) {
PostMessage(hwnd, WM_EX_SOME_SPECIALINTERNALMESSAGE, 0, 0);
Sleep(1000);
}
});
// Run the message loop.
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
th1.join();
As you see in this code, WM_EX_SOME_SPECIALINTERNALMESSAGE is a custom windows message. Its posted every second to you main window proc: WindowProc. To receive it modify WindowProc:
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
const UINT WM_EX_SOME_SPECIALINTERNALMESSAGE = ::RegisterWindowMessage(L"SomeSpecialInternalMessage");
if(uMsg == WM_EX_SOME_SPECIALINTERNALMESSAGE) {
OutputDebugStringW(L"WM_EX_SOME_SPECIALINTERNALMESSAGE\n");
}
// ...
Related
I have a program (not a DLL) that creates a thread, and in this thread I create a hook using SetWindowsHookExW() to get keyboard events. I also have a global variable that I can use to turn off this thread.
The thing is that I don't know how to release the hooks and continue the function/thread, because it also does some cleanup. When I use UnhookWindowsHookEx() and place breakpoints in the following lines, the breakpoints are never reached.
The example on MSDN is "broken", because it needs an app.h; Also, every tutorial on the Internet, either input systems, keylogger, etc, they talk about DLLs, that I'm not using, and some of them implement a wrapper Unhook function but they never use it.
What I've been trying:
#include <Windows.h>
bool bContinue;
wchar_t vkTecla;
LRESULT CALLBACK KeyboardCallBack(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode >= 0)
{
vkTecla = ((KBDLLHOOKSTRUCT*)lParam)->vkCode;
if (wParam == WM_KEYDOWN)
{
// Do stuff here
}
// ...
}
if (bContinue)
{
UnhookWindowsHookEx(hHook);
return 0;
}
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
void MainThread(HANDLE hfile)
{
hHook = SetWindowsHookExW(WH_KEYBOARD_LL, KeyboardCallBack, 0, 0);
MSG msg;
// I tested these 3 cases
/*************/
while(GetMessageW(&msg, 0, 0, 0));
// Or
GetMessageW(&msg, 0, 0, 0);
/*************/
while(GetMessageW(&msg, 0, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
/*************/
while (bContinue)
{
// PeekMessage(...);
GetMessageW(&msg, 0, 0, 0);
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// In this example I would remove the other Unhook function
UnhookWindowsHookEx(hHook);
/*************/
CloseHandle(hfile);
}
If I do the first example, the:
while(GetMessageW(&msg, 0, 0, 0));
and check bContinue inside of the callback function;
or use the third one:
while (bContinue)
{
GetMessageW(&msg, 0, 0, 0);
TranslateMessage(&msg);
DispatchMessage(&msg);
}
UnhookWindowsHookEx(hHook);
And place a breakpoint in CloseHandle(hArquivo);, when I make the bContinue = false, this line never gets executed.
So the question is:
Where do I place UnhookWindowsHookEx()? Is it inside the Callback function, or somewhere else?
When I release the hook, will the thread continue? Because at the moment, I don't get the program to stop at breakpoints past the unhooking that have some cleanup.
GetMessage() is a blocking function. It will not exit until the message queue of the calling thread has a message available for the caller to process.
But, you are running this code in a worker thread that has no UI of its own. And, although hooks do use messaging internally, they are private to the hook implementation and the caller of (Peek|Get)Message() will never see them. So, unless the other threads in your app are posting messages to this worker thread via PostThreadMessage(), there are simply no messages for GetMessage() to return to your code. That is why your loop doesn't break.
So, you need to either:
use PeekMessage() instead of GetMessage() so you can monitor your bContinue variable in between polls of the message queue:
#include <Windows.h>
bool bContinue = TRUE;
LRESULT CALLBACK KeyboardCallBack(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode >= 0)
{
wchar_t vkTecla = ((KBDLLHOOKSTRUCT*)lParam)->vkCode;
if (wParam == WM_KEYDOWN)
{
// Do stuff here
}
// ...
}
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
void MainThread(HANDLE hfile)
{
HHOOK hHook = SetWindowsHookExW(WH_KEYBOARD_LL, KeyboardCallBack, 0, 0);
MSG msg;
while (bContinue)
{
if (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
Sleep(10);
}
UnhookWindowsHookEx(hHook);
CloseHandle(hfile);
}
...
// to stop the thread:
bContinue = FALSE;
change bContinue to be a HANDLE returned by CreateEvent(), and then use MsgWaitForMultipleObjects() in a loop to monitor that event and the message queue at the same time, calling (Get|Peek)Message() only when it reports the message queue has messages to process. Then you can use SetEvent() when you want to trigger the loop to end.
#include <Windows.h>
HANDLE hStop = CreateEvent(NULL, TRUE, FALSE, NULL);
LRESULT CALLBACK KeyboardCallBack(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode >= 0)
{
wchar_t vkTecla = ((KBDLLHOOKSTRUCT*)lParam)->vkCode;
if (wParam == WM_KEYDOWN)
{
// Do stuff here
}
// ...
}
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
void MainThread(HANDLE hfile)
{
HHOOK hHook = SetWindowsHookExW(WH_KEYBOARD_LL, KeyboardCallBack, 0, 0);
MSG msg;
while (MsgWaitForMultipleObjects(1, &hStop, FALSE, INFINITE, QS_ALLINPUT) == (WAIT_OBJECT_0 + 1))
{
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
UnhookWindowsHookEx(hHook);
CloseHandle(hfile);
}
...
// to stop the thread:
SetEvent(hStop);
Below is a code I use to capture what ever the key is being pressed or not and I update the statuses of the keys according to their states.
I keep the statues in my simple array of values 0,1,2,3.
formatted as: keyboardmap[256] = {0};
Problem is, what ever I try to do, keys keep getting stuck at some point. They never get reset back to zero as if the WM_KEYUP would not fire up properly.
while (true)
{
if ( PeekMessage(&msg, 0, 0, 0, PM_REMOVE) )
{
TranslateMessage(&msg);
DispatchMessage(&msg);
if (msg.message == WM_QUIT)
{
break;
}
// Check for keystates and update them.
if (msg.message == WM_KEYDOWN)
{
// Fetch the key state.
unsigned int keycode = msg.wParam;
unsigned int cstate = engine.GetKeyState(msg.wParam);
if (engine.GetKeyState(keycode) == 0)
{
engine.SetKeyState(keycode, 1); // Just started pressing.
}
else
{
engine.SetKeyState(keycode, 2); // Actively pressed down.
}
}
else if (msg.message == WM_KEYUP)
{
// Fetch the key state.
unsigned int keycode = msg.wParam;
unsigned int cstate = engine.GetKeyState(msg.wParam);
if ( engine.GetKeyState(keycode) == 2)
{
engine.SetKeyState(keycode, 3);
}
else
{
engine.SetKeyState(keycode, 0);
}
}
}
}
That's not how the message loop is supposed to be. Use the following example for a game engine where you need to constantly update the game/screen:
WNDCLASSEX wc = { sizeof(WNDCLASSEX) };
wc.lpfnWndProc = WndProc;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpszClassName = L"WindowClass";
RegisterClassEx(&wc);
CreateWindow(...);
MSG msg = { 0 };
//while (msg.message != WM_QUIT) <=== removed in edit
while(true) //<=== **** edit ****
{
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if(msg.message == WM_QUIT) //<=== **** edit ****
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
engine.update();
}
}
Window's messages should be handled in separate window procedure:
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_KEYDOWN:
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
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 have a standard win32 window, that I draw on with D2D1. Everything is responsive and runs smoothly. My problem is as follows: After the window is created, it calls WM_PAINT once and then gets "stuck" waiting for any user input (ex. mouse move or click in the window area). As it receives the input, it runs without any further problems. While this doesn't necessarily render the program nonfunctional, it seems highly unprofessional and... ugly. Oh, and what I mean by "stuck" is that the background processes still run without problems, so the loop runs as intended - however, the WM_PAINT isn't called for some reason.
Here is the current code:
header file:
#define PROGRAM_FPS 30
#define GWINDOW_STYLE (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_CLIPCHILDREN | WS_CLIPSIBLINGS)
class Application
{
public:
Application();
~Application();
// Register the window class and call methods for instantiating drawing resources
HRESULT Initialize();
// Process and dispatch messages
void RunMessageLoop();
static inline void SafeRelease(IUnknown * _X)
{
if(_X != NULL)
_X->Release();
};
HRESULT SetFullscreen(bool);
private:
// Time (ms) between frames of the application
// Initiation: m_AppFPS_Div( (DWORD)1000.0 / (DWORD)PROGRAM_FPS )
const DWORD m_AppFPS_Div;
// Initialize device-independent resources.
HRESULT CreateDeviceIndependentResources();
// Initialize device-dependent resources.
HRESULT CreateDeviceResources();
// Release device-dependent resource.
void DiscardDeviceResources();
// Draw content.
HRESULT OnRender();
HRESULT LoadBitmapFromFile(
ID2D1RenderTarget*,
PCWSTR,
UINT,
UINT,
ID2D1Bitmap **
);
// The windows procedure.
static LRESULT CALLBACK WndProc(
HWND hWnd,
UINT message,
WPARAM wParam,
LPARAM lParam
);
HWND m_hwnd;
ID2D1Factory * m_pDirect2dFactory;
ID2D1HwndRenderTarget * m_pRenderTarget;
IWICImagingFactory *m_pIWICFactory;
ID2D1SolidColorBrush * m_pWhiteBrush;
ID2D1SolidColorBrush * m_pGrayBrush;
ID2D1LinearGradientBrush * m_pLinearGradientBrush;
ID2D1Bitmap *m_LoadingPicture;
};
parts of the .cpp file
void Application::RunMessageLoop()
{
HACCEL hAccelTable = LoadAccelerators(hInst, MAKEINTRESOURCE(IDC_WIN32APP));
DWORD screen_last_refresh = 0;
MSG msg;
for(bool applicationRunning = true; applicationRunning;)
{
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if(msg.message == WM_QUIT)
{
applicationRunning = false;
}
if(!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
/*** HERE I RUN VARIOUS BACKGROUND PROCESSES ***/
while((GetTickCount() - screen_last_refresh) < m_AppFPS_Div)
Sleep(2);
InvalidateRect(msg.hwnd, NULL, false);
screen_last_refresh = GetTickCount();
}
}
LRESULT CALLBACK Application::WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
LRESULT result = 0;
if (message == WM_CREATE)
{
LPCREATESTRUCT pcs = (LPCREATESTRUCT)lParam;
Application *pApp = (Application *)pcs->lpCreateParams;
::SetWindowLongPtrW(hwnd, GWLP_USERDATA, PtrToUlong(pApp) );
InvalidateRect(hwnd, NULL, false);
result = 1;
}
else
{
Application *pApp = reinterpret_cast<Application *>(static_cast<LONG_PTR>(
::GetWindowLongPtrW(
hwnd,
GWLP_USERDATA
)));
bool wasHandled = false;
if (pApp)
{
switch (message)
{
case WM_SIZE:
{
UINT width = LOWORD(lParam);
UINT height = HIWORD(lParam);
pApp->OnResize(width, height);
}
result = 0;
wasHandled = true;
break;
case WM_DISPLAYCHANGE:
{
InvalidateRect(hwnd, NULL, FALSE);
}
result = 0;
wasHandled = true;
break;
case WM_PAINT:
{
pApp->OnRender();
ValidateRect(hwnd, NULL);
}
result = 0;
wasHandled = true;
break;
case WM_DESTROY:
{
PostQuitMessage(0);
}
result = 1;
wasHandled = true;
break;
}
}
if (!wasHandled)
{
result = DefWindowProc(hwnd, message, wParam, lParam);
}
}
return result;
}
HRESULT Application::OnRender()
{
HRESULT hr = S_OK;
hr = CreateDeviceResources();
if (SUCCEEDED(hr))
{
m_pRenderTarget->BeginDraw();
m_pRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());
/** HERE I HANDLE THE OPENING ANIMATION **/
hr = m_pRenderTarget->EndDraw();
}
if (hr == D2DERR_RECREATE_TARGET)
{
hr = S_OK;
DiscardDeviceResources();
}
return hr;
}
So, I've tested it on 2 computers (both using Win 8.1) with VS 2012 Ultimate and VS 2013 Professional, run debug tests back and forth, stripping certain parts of the program, searched MDSN, Google and StackExchange - to no avail. This freeze also happens when I handle WM_COMMAND of a child window. There was also no such issue when I tried implementing GDI+, but it proved to be highly ineffective, hence the switch to DirectX. Aside from that, the program runs flawlessly. I hope I've provided enough information.
You have not been clear about what you are doing to run "various background processes." That is probably where the "stuck" issue comes from. A suggestion is to move that out of the message loop. Instead, call SetTimer during window initialization and then do a bit of your background process work each time the WM_TIMER message comes in.
And, when you want a WM_PAINT to come in call InvalidateRect().
I am working on an App which has Multiple Threads waiting for different inputs from DLLs and Serial Ports.
I want to add a functionality that before machine going to Sleep, I have to unload certain DLL and On waking up have to Re-load the DLL.
For this, I need to get notified on Sleep and Wake up.
I found many files about doing in C# but I want to do this in C++.
I tried using this code Project but could not capture any event. I removed everything related to Window Paint and All that as I do not need it's GUI and kept only main message loop (The While loop in the main)
EDIT:-
I am using this as my main loop:-
// Start the message loop.
while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
To be frank I have copied this from CodeProject, and Made only one Modification i.e. Checked GetMessage(..) != 0 from a MSDN Article.
Am I missing something?
Or anyother Solution??
I am using VS2010 and programming in C++
Thanks in Advance!
Try handling the WM_POWERBROADCAST message
Here's sample code that should work. Apparently you do need to create a window otherwise you don't receive the messages. The sample creates a hidden window to achieve this.
static long FAR PASCAL WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if(message == WM_POWERBROADCAST)
{
//Do something
return TRUE;
}
else
return DefWindowProc(hWnd, message, wParam, lParam);
}
int _tmain(int argc, _TCHAR* argv[])
{
WNDCLASS wc = {0};
// Set up and register window class
wc.lpfnWndProc = WindowProc;
wc.lpszClassName = _T("SomeNameYouInvented");
RegisterClass(&wc);
HWND hWin = CreateWindow(_T("SomeNameYouInvented"), _T(""), 0, 0, 0, 0, 0, NULL, NULL, NULL, 0);
BOOL bRet;
MSG msg;
while( (bRet = GetMessage( &msg, hWin, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return 0;
}