How to change the MessageBox window (Add controls and change texts)?
This article describes how to change the MessageBox window (Add controls and change texts).
Introduction
In this article we will learn how to add controls to a MessageBox or how to change its button texts. You can use this method to create (full) Multilanguage programs (Just a suggestion!). There are some ways to do this and I chose the hooking method.
Steps of Hooking a MessageBox
To hook a MessageBox:
- Use
SetWindowsHookEx ()
function withWH_CALLWIND
and pass it to a hookproc. - Declare a hook procedure.
- In the hookproc use the
SetWindowLong ()
function to handle the MessageBox window Creation process (Maybe it is a good name for this). - Declare a
CALLBACK
function to handle the MessageBox window creation process. - Pass the
CALLBACK
function as thenew long
parameter in theSetWindowLong ()
function. - And at the end, place your codes in the
CALLBACK
function (codes for window creation).
SetWindowsHookEx () function
This function installs a hook procedure. Using this function you can hook windows events. In other words when you install a hook procedure you tell the system to notify you when the wanted event is called.
As MSDN says: The SetWindowsHookEx
function installs an application-defined hook procedure into a hook chain. You would install a hook procedure to monitor the system for certain types of events. These events are associated either with a specific thread or with all threads in the same desktop as the calling thread.
How to Install a hook procedure using SetWindowsHookEx () function?
g_hHook = SetWindowsHookEx (WH_CALLWNDPROC, (HOOKPROC)SetHook, NULL, GetCurrentThreadId ());
Where g_hHook
is a global variable and the SetHook
is my HookProc;
What is WH_CALLWNDPROC?
Use this parameter to install a hook procedure that monitors messages before the system sends them to the destination window procedure (MSDN).
Declaring a HookProcedure
Use the following declarations in your header file:
LRESULT CALLBACK SetHook(int nCode,WPARAM wParam,LPARAM lParam);
This will declare a hook procedure by name SetHook
. See this code snippet:
LRESULT CALLBACK SetHook(int nCode,WPARAM wParam,LPARAM lParam) { if (nCode==HC_ACTION) { CWPSTRUCT* pwp = (CWPSTRUCT*)lParam; if (pwp->message==WM_INITDIALOG) oldProc=(WNDPROC)SetWindowLong(pwp>hwnd, GWL_WNDPROC,(LONG)HookWndProc); } return CallNextHookEx(g_hHook,nCode,wParam,lParam); }
This code snippet is my SetHook
procedure.
What is GWL_WNDPROC?
This parameter sets a new address for the window procedure. (I think it is enough).
What is CWPSTRUCT?
This is a structure that contains information about window messages like a handle to that window (hwnd
). We pass a pointer of this structure to use the hwnd
member in the callback function.
And the HookWndProc
is a function that processes the window creation codes.
Handling the window creation process
To do this, you must declare a CALLBACK
function.
LRESULT CALLBACK HookWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
This is my HookWndProc
procedure.
LRESULT CALLBACK HookWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { //Let OS to perform basic operation LRESULT rc = CallWindowProc( oldProc, hWnd, uMsg, wParam, lParam ); //If MessageBox wanted to initialized, do something if (uMsg==WM_INITDIALOG) { if (m_hIcon) SetIcon(hWnd,m_hIcon); CreateButton(hWnd); if (m_strCaption) SetCaption(hWnd); } if (uMsg==WM_COMMAND&&wParam==IDC_CHECKBOX) //If user clicked the check box handle it! SetOut(wParam); if (uMsg==WM_NCDESTROY) //On exit Uninstall the hook procedure //If we don't do that every message box will have //A check box on it! UnInstallHook(g_hHook); return rc; }
The main operations are done. I mean the hwnd
. After having this hwnd
, we can do everything to the MessageBox window. But don’t forget to call CallWindowProc
function.
CallWindowProc
do?
According to MSDN: The CallWindowProc
function passes message information to the specified window procedure.
I used this function because I didn’t want to paint the MessageBox window myself and I wanted only to change some texts. If you want to paint the main window, I think you shouldn’t call this function!
For more information about SetWindowsHookEx
, SetWindowLong
and CallWindowProc
use MSDN Library. (I think it is the best reference to revert).
And at last I want to warn you: Call the CallNextHookEx ()
function because if you don’t do this, other applications that may have installed a hook chain will not receive the hook information and I know you don’t want it.
And like always, according to MSDN that says: Calling the CallNextHookEx
function to chain to the next hook procedure is optional, but it is highly recommended; otherwise, other applications that have installed hooks will not receive hook notifications and may behave incorrectly as a result. You should call CallNextHookEx
unless you absolutely need to prevent the notification from being seen by other applications.
Last Words
First of all, I want to thanks to Mr. Nicolas Bonamy. His article helped me a lot.
There is a demo app which if you want, can download. In that project I have a class that contains some codes for adding a CheckBox to the MessageBox and to change the text of buttons and some functions to place the controls in a right and good place.
And I want to say that my English is not very well and it is a reason to write MSDN Library definitions for some functions (Excuse me for bad grammar).
And at last I suggest you to use Visual Assist X because it is a helpful plug-in for Visual Studio.
Please vote this article if you find it interesting and informative. Opinions and comments are welcome.
G.K.Z - King Zoser.