Is there a way to disable message boxes in MFC? - c++

I have an MFC application (using a legacy library that I can't change). When the application starts, it loads a couple of drivers and shows message boxes if some drivers couldn't be loaded. The loading of the drivers and the showing of the message boxes is done by a method inside the library that can't be changed (let's call this method Init). I would like to disable those message boxes (preventing them from "popping"). Is there something I could call before calling Init to disable Message Boxes temporarily and then re-enable them after?
(Note that if it is impossible to re-enable them after, I can very well live with that, I mostly want to disable them)
Thanks to all,
Note: If someone wonders about why I would like to do that, it is because my application exposes a COM interface and will be used by other applications. The only reason it is an application is that the library I use is much more easy to use when creating an MFC application (and not a dll). When it is called by my other applications, I don't want the message boxes to show, I just want to get the errors if something goes wrong.

I am not sure whether this could work. I use it for subclassing some messageboxes not to preven them to popup and they are not from a dll.
I set a hook to capture message boxes before poping up:
HHOK hMessageBoxHook_ = SetWindowsHookEx(WH_CBT,
&CbtHookProc,
::GetModuleHandle(NULL),
GetCurrentThreadId());
The new hook procedure (CbtHookProc) would be like this:
LRESULT CALLBACK CbtHookProc( int nCode,
WPARAM wParam,
LPARAM lParam)
{
if(nCode < 0)
{
return ::CallNextHookEx( hMessageBoxHook_,
nCode,
wParam,
lParam);
}
switch(nCode)
{
case HCBT_CREATEWND: // a window is about to be created
return -1;
}
return ::CallNextHookEx( hMessageBoxHook_,
nCode,
wParam,
lParam);
}
From microsoft documentation for HCBT_CREATEWND:
If the hook procedure returns a
nonzero value, the system destroys the
window
Then after calling Init you can remove the hook and message boxes will pop up again:
::UnhookWindowsHookEx(hMessageBoxHook_);
hMessageBoxHook_ = 0;
As I told you I can't assure it works but give it a try.

One way to do this would be to hook/unhook the calls to MessageBox/MessageBoxEx/etc. and just do nothing when these calls are made. Check this guide for details on hooking API calls. In your case, I would specifically look at Import Address Table method, which is quite easy to implement and allows you to achieve the functionality you want.
You may also want to check Microsoft's own Detours library, but I'm not sure on whether it supports replacing API calls functionality.
Hope it helps.

I had the same problem when using ODBC with MFC. Everytime there was an error, a message box would pop up showing the error, which was fine if I wanted one.
However, if I didn't, I only needed to surround it with:
TRY
{
// Call error-prone method
}
CATCH ( CException, pEx )
{
// Free resources
}
END_CATCH
The message box comes from the framework not knowing how to handle the exception. Simply catch it and do as you wish with it.

Related

How is Teamviewers Quickconnect button accomplished?

For those of you who do not know what I am talking about:
http://www.teamviewer.com/images/presse/quickconnect_en.jpg
Teamviewer overlays that button on all windows to allow you to quickly share a window with someone else. I would like any ideas on implementing something similar -- if you have example code, even better (specifically, the button -- not the sharing). I am interested in C++ and QT... but I would be interested in good solutions in other languages/libraries if there are any.
Thanks.
To draw buttons or other stuff in foreign windows, you need to inject code into the foreign processes.
Check the SetWindowsHookEx method for that:
You most probably want to install a hook for WH_CALLWNDPROCRET and watch out for the WM_NCPAINT message. This would be the right place to draw your button.
However, I'm not really sure, if you can place a window within a Non-Client-Area, so in the worst case, you'd have to paint the button "manually".
Just call this from your main application (or from within a DLL)
SetWindowsHookEx(WH_CALLWNDPROCRET, myCallWndRetProc, hModule, 0);
Note that myCallWndRetProc must reside within a DLL and hModule is the Module-HANDLE for this DLL.
Your myCallWndRetProc could look like:
LRESULT CALLBACK myCallWndRetProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode == HT_ACTION) {
CWPRETSTRUCT* cwpret = (CWPRETSTRUCT*)lParam;
if (cwpret->message == WM_NCPAINT) {
// The non-client area has just been painted.
// Now it's your turn to draw your buttons or whatever you like
}
}
return CallNextHookEx(0, nCode, wParam, lParam);
}
When starting with your implementation, I'd suggest, you just create a simple dialog application and hook your own process only:
SetWindowsHookEx(WH_CALLWNDPROCRET, myCallWndRetProc, NULL, GetCurrentThreadId());
Installing a global hook injects the DLL into all processes, which makes debugging pretty hard, and your DLL may be write-protected while it's in use.

Intercept mouse input

I was wondering if there is a way to intercept and modify mouse input before it gets to windows?
What I'm wanting to do is intercept mouse motion events, apply some custom scaling and acceleration to the values, and then continue passing them along. I'd need something that can do this before the inputs get to the raw input API or DirectInput.
In order to affect all mouse input, including DirectInput, during logon and the SAS screen, etc., you'll need to load a filter driver into the mouse driver stack.
Other people have done it, for example http://www.maf-soft.de/mafmouse/
There should be a moufiltr sample in the Windows DDK which you can use as a starting point. You will most likely want to use a virtual machine for development since errors in a driver on your development machine could be difficult to recover from.
Have you seen this method of intercepting mouse and keyboard input without having to make a filter driver or hook?
http://oblita.com/Interception.html
There is a LowLevelMouseProc hook procedure that you can use to get information on any mouse input entering the system, although I doubt if you can actually change this information (and the docs are silent on this).
If this fails, GetMsgProc is an alternative that lets you intercept all messages posted to any window. Though this hook does let you modify the message, it's probably too late to have any effect on APIs such as DirectInput.
You could try a windows hook - which are functions you set to receive windows messages before they get passed through to the rest of the system - a CBT hook (for computer based training) is what might get you best results.
I don't know Whether this will work with DirectInput or the other new stuff MS has added to break all the old internal consistency. Its easy to set up though, so try it and see.
As far as I know the best way is to hook to windows message loop, In your case you should pass HWND 0 (If I remember correctly this the HWND of the desktop) so all the messages will pass though your function first.
http://msdn.microsoft.com/en-us/library/ms633591%28VS.85%29.aspx
More on hooks : http://msdn.microsoft.com/en-us/library/ms644959%28VS.85%29.aspx
Use it as follows:
m_nOldWindowProc = ::SetWindowLong(0 /I think.../, GWL_WNDPROC, (LPARAM)(WNDPROC)WindowProcCallback);
and the callback:
LRESULT CALLBACK CStubWindow::WindowProcCallback(HWND hwnd,
UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_WINDOWPOSCHANGING:
((WINDOWPOS*)lParam)->cx = STATUS_BAR_WIDTH;
((WINDOWPOS*)lParam)->flags = SWP_NOOWNERZORDER | SWP_NOMOVE;
break;
default:
break;
}
return ::CallWindowProc(m_nOldWindowProc, hwnd, message, wParam, lParam);
}

How to set global hook for WH_CALLWNDPROCRET?

I want to set global hook that tracks which application is active.
In my main program I am doing the foloowing :
HMODULE mod=::GetModuleHandle(L"HookProcDll");
HHOOK rslt=(WH_CALLWNDPROCRET,MyCallWndRetProc,mod,0);
The hook procedure which is called MyCallWndRetProc exists in separate dll called HookProcDll.dll. The hook procedure is watching for WM_ACTIVATE message.
The thing is that the code stucks in the line where I am setting the hook, i.e in the line where I am calling ::SetWindowsHookEx. And then Windows gets unresponsive, my task bar disappears and I am left with empty desktop. Then I must reset the computer.
What am doing wrong, why Windows get unresponsive ? and
Do I need to inject HookProcDll.dll in every process in order to set the global hook, and how can I do that ?
This almost definitely sounds like a crashing bug in MyCallWndRetProc. You specify your hook DLL to get loaded in every process with a window and it crashes when MyCallWndRetProc gets called after a window message. Since it gets called after every window message in every process, it'll eventually take down every process displaying UI in the user session. You can't even launch new apps since your hook proc will be immediately loaded into them.
Including the code to MyCallWndRetProc, and perhaps your DllMain as well, should give us some insight into what is happening.
This is the code for my hook procedure, and it is stored in HookProcDll.dll :
#include "HookProcDll.h"
LRESULT CALLBACK MyCallWndRetProc(
__in int nCode,
__in WPARAM wParam, /* whether the msg is sent by the current process */
__in LPARAM lParam /* pointer to CWPRETSTRUCT , which specifies details about the message */
)
{
if(nCode >=0)
{
CWPRETSTRUCT* retStruct=(CWPRETSTRUCT*)lParam;
if(retStruct->message == WM_ACTIVATE)
{
}
}
return ::CallNextHookEx(0,nCode,wParam,lParam);
}
My HookProcDll.dll has no explicit DllMain function .The HookProcDll.dll is made with visual studio dll project so I guess it includes standrad implementation for DllMain.

Windows/C++: detect when focus has changed between windows (globally)

I'm trying to find a way to detect when focus is changed to another window (without having to poll every X ms).
I've already figured out a way to detect when focus is switched between applications using WH_SHELL and HSHELL_ACTIVATESHELLWINDOW.
The problem is I want to detect when focus is switched between dialog/windows within the same app.
ie. In Notepad, I can determine when the app switches to Notepad, but I cannot detect when the "Open" or "Save" dialogs appear because the focus is still within the same application.
You can use SetWindowsHookEx with a WH_CBT hook type. If you just want to detect focus changes within an application, pass GetCurrentThreadId() as the last parameter, otherwise the hook will be for all threads on the current desktop.
Note that using windows hooks can have an adverse effect on system performance, so the hook should only be installed when necessary and you should do a minimum amount of work in the hook procedure.
Sorry for the delay, I don't have VS installed on this computer so it's a bit hard to find the code.
Use this to hook your code into the system.
HHOOK oldShellHook = SetWindowsHookEx(WH_SHELL, BCK_WndShellProc, hDll, NULL);
if (!info->oldShellHook) {
MessageBox(m_hwnd, L"Failed to load global hook.", strTitle, MB_OK | MB_ICONERROR);
return;
}
And this your hook. Depending on what you're doing, use nMsg to figure out when you want to apply your custom logic.
LRESULT CALLBACK BCK_WndShellProc(int nMsg, WPARAM wParam, LPARAM lParam) {
...
}
Read the MSDN docs for SetWindowsHookEx() to make sure you return the expected values, otherwise you can lock up the whole system.
I use code similar to this on my Breadcrumb Killer and Spasm (Show all programs on Start menu) programs and it seems to work fine.
How about the "Computer Based Training API"; SetWindowsHookEx with WH_CBT which will enable you to receive HCBT_SETFOCUS (among others)

Notification when Windows Dialog is opened

I want to do some processing when a particular dialog is opened but I am not able to find any way to get notification when that dialog is opened.
Is there any way to get notification in application for opening of a particular windows dialog?
The only available information about the dialog is its title and its unique.
The general solution is to use windows hooks, filter to WH_CBT, filter to WM_CREATE, or something like that, get the window text and see if it is the one of your interest.
One more important point: in hook you should use SetWindowLongPtr() to set window process to your own function, that will actually receive WM_CREATE event. In all calls this function should call the original window procedure.
You can also use a CBT Hook to watch window creation messages. You'll have access to the CREATSTRUCT used to create the actual window, eg, the title and class name. You can prevent the window from being created in your hook, modify the size, etc.
EDIT: sorry didn't notice that you don't have the code yourself but only the title. So I think the other posts solution is what you need
The event handling in win32 applications is done via a so called windows procedure which is a callback function with the following signature:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
This callback gets called by windows every time there is a message for windows which are registered with this callback function. One of the first messages send to a new window is the WM_CREATE message.
If you are creating your windows "by hand" with win32 API, then there should be a static callback function like the one below where you can filter for the WM_CREATE message.
LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
{
switch( message )
{
case WM_CREATE:
// do what ever you want
return 0;
case default:
return DefWndProc( hwnd, message, wParam, lParam );
}
}
If you use MFC dialogs (CDialog) then you can overwrite the function CDialog::OnInitDialog().
OK, the way to do this is to use SetWindowsHookEx(WH_SYSMSGFILTER,...)
You'll be getting a lot more callbacks than you really need. and global hooks are a real drain on system performance (they can force the system to serialize things that would normally run independently)
be sure to read the Remarks, especially this part:
SetWindowsHookEx can be used to inject a DLL into another process. A 32-bit DLL cannot be injected into a 64-bit process, and a 64-bit DLL cannot be injected into a 32-bit process. If an application requires the use of hooks in other processes, it is required that a 32-bit application call SetWindowsHookEx to inject a 32-bit DLL into 32-bit processes, and a 64-bit application call SetWindowsHookEx to inject a 64-bit DLL into 64-bit processes. The 32-bit and 64-bit DLLs must have different names.
Your hook must live in a dll, and the dll will end up loaded into other process's address space, so you won't it won't have access to your procees's address space, you will have to set up some sort of interprocess communication between your hook and your app.
On the whole I'd say this sounds like a really bad idea.