WM_POWERBROADCAST message not caught in MFC Dlg - mfc

I try to catch WM_POWERBROADCAST message when the system goes into sleep mode.
I'm doing like :
BOOL CPowManApp::PreTranslateMessage(MSG* pMsg)
{
if(pMsg->message == WM_POWERBROADCAST || pMsg->message == WM_POWER)
{
CString strMessage;
strMessage.Format(_T("%d WM_POWERB%s wParam %x lParam %x"),
pMsg->time,
pMsg->message == WM_POWER?_T(""):_T("BRAODCAST"),
pMsg->wParam,
pMsg->lParam);
OutputDebugString(strMessage);
}
return CWinApp::PreTranslateMessage(pMsg);
}
It simply doesn't work. Meanwhile a win32 app works just fine. I tried to put the message handler in the Dlg class in vain.
I'm building the app with VS6.0. Where am I wrong?

In your message map
ON_MESSAGE( WM_POWERBROADCAST, OnPowerBroadcast )
Implementation
LRESULT CDialogDlg::OnPowerBroadcast(WPARAM wParam, LPARAM lParam)
{
switch (wParam)
{
case PBT_...
}
}
Be sure to check MSDN for some OS-specific cases around the wParam values.

The documentation of this message specifically says:
A window receives this message through its WindowProc function.
Have you tried to overwrite this method on your main window?

Related

Blocking windows mouse click using SetWindowsHookEx()

I have written an application to hook some procedure onto a new process to monitor mouse down events and to disable mouse down events on the new process. As of now, I am able to capture to mouse down events coming to this process and I am trying to disable all mouse down events as a POC. This is what I am doing currently in the hook procedure.
extern "C" __declspec(dllexport) LRESULT __stdcall meconnect(int code, WPARAM wParam, LPARAM lParam) {
if (code >= 0) {
LPMSG msg = (LPMSG)lParam;
if (msg->message == WM_LBUTTONDOWN) {
OutputDebugString(L"Mouse down event happened \n");
return false;
}
}
return(CallNextHookEx(NULL, code, wParam, lParam));
}
When I perform mouse down event, I am getting the log message that I have written. But I also expect that click event to be blocked since I am returning false. but it does not happen so and click event proceed as a normal click. How could I disable mouse down event. Thanks in advance for any help on this
This is how I call setWindowsHookEx
HHOOK handle = SetWindowsHookEx(WH_GETMESSAGE, addr, dll, threadID);
The reason you are supposed to call CallNextHookEx during your hook routine is so that the message can be passed on to any other hooks that might be installed. Failing to do so does not prevent the message from being seen by the application that received it.
The documentation for WM_NULL explains how to block the message:
For example, if an application has installed a WH_GETMESSAGE hook and wants to prevent a message from being processed, the GetMsgProc callback function can change the message number to WM_NULL so the recipient will ignore it.
The corrected code should therefore look something like this:
extern "C" __declspec(dllexport) LRESULT __stdcall meconnect(int code, WPARAM wParam, LPARAM lParam) {
if (code >= 0) {
LPMSG msg = (LPMSG)lParam;
if (msg->message == WM_LBUTTONDOWN) {
OutputDebugString(L"Mouse down event happened \n");
msg->message = WM_NULL;
return false;
}
}
return(CallNextHookEx(NULL, code, wParam, lParam));
}
However, this may cause inconsistent behaviour if other hooks are present, because whether another hook sees WM_LBUTTONDOWN or WM_NULL will depend on the order of the hook chain, which is unpredictable. It might be preferable to try something like this:
extern "C" __declspec(dllexport) LRESULT __stdcall meconnect(int code, WPARAM wParam, LPARAM lParam) {
if (code >= 0) {
LPMSG msg = (LPMSG)lParam;
int result = CallNextHookEx(NULL, code, wParam, lParam);
if (msg->message == WM_LBUTTONDOWN) {
OutputDebugString(L"Mouse down event happened \n");
msg->message = WM_NULL;
}
return result;
}
return(CallNextHookEx(NULL, code, wParam, lParam));
}

How to use enter key on a Login/Password window in c++?

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! ^^' )

C++ Modeless Dialog created from DLL doesn't process input properly

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 ?

How to know how many time your computer has been in screen saver or monitor/screen off?

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.

WM_PASTE hook not working

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.