Thread View: borland.public.cppbuilder.nativeapi
6 messages
6 total messages
Started by Dennis Jones
Wed, 31 May 2006 00:50
Handle of MessageBox
Author: Dennis Jones
Date: Wed, 31 May 2006 00:50
Date: Wed, 31 May 2006 00:50
23 lines
1668 bytes
1668 bytes
Hi, I need the ability to programmatically close a message box. However, I only want to close it if it was opened as a result of calling MessageBox or Application->MessageBox from a specific form (which is also open). To do so, it would seem that I need to know a couple of things: 1) If a message box is currently open 2) If the message box was opened in the context of a specific form 3) The handle of the message box Is it possible to obtain these 3 pieces of information? This requirement comes from the need to close a form programatically, which includes closing any forms opened by (owned by) that form, which also includes (potentially) message boxes. I have been able to handle closing TForm and TCommonDialog descendants, but I'm stuck on message boxes. Any suggestions would be welcome. Thanks, - Dennis
Re: Handle of MessageBox
Author: Ed Mulroy
Date: Wed, 31 May 2006 01:07
Date: Wed, 31 May 2006 01:07
28 lines
2107 bytes
2107 bytes
You are going at it the hard way. Make a window that you use as a message box. Make the button on the form open that window instead of a regular message box. You can then supply a function which closes the window. . Ed > Dennis Jones wrote in message > news:447ce85d$1@newsgroups.borland.com... > > I need the ability to programmatically close a message box. However, I > only > want to close it if it was opened as a result of calling MessageBox or > Application->MessageBox from a specific form (which is also open). To do > so, it would seem that I need to know a couple of things: > > 1) If a message box is currently open > 2) If the message box was opened in the context of a specific form > 3) The handle of the message box > > Is it possible to obtain these 3 pieces of information? > > This requirement comes from the need to close a form programatically, > which > includes closing any forms opened by (owned by) that form, which also > includes (potentially) message boxes. I have been able to handle closing > TForm and TCommonDialog descendants, but I'm stuck on message boxes. > > Any suggestions would be welcome.
Re: Handle of MessageBox
Author: Remy Lebeau (TeamB)
Date: Wed, 31 May 2006 01:12
Date: Wed, 31 May 2006 01:12
65 lines
3842 bytes
3842 bytes
"Dennis Jones" <nospam@nospam.com> wrote in message news:447ce85d$1@newsgroups.borland.com... > I need the ability to programmatically close a message box. From where exactly? MessageBox() shows a modal dialog, so you can't close it from the context of the thread that is displaying it (without some low-level hooks, that is). > However, I only want to close it if it was opened as a result of calling > MessageBox or Application->MessageBox from a specific form > (which is also open). That is going to be very tricky. Sure, you can detect whether the form is open. But you can't really detect if MessageBox() was called from any particular form. The only identifying feature of a MessageBox dialog in regards to its caller is the Owner HWND that is provided as a parameter to MessageBox(). Most of the time, that is NULL when calling MessageBox() directly. And when not NULL, there is no guarantee that it is the calling form. When calling TApplication::MessageBox(), the Owner is always the TApplication::Handle, never any form. > To do so, it would seem that I need to know a couple of things: > > 1) If a message box is currently open > 2) If the message box was opened in the context of a specific form > 3) The handle of the message box > > Is it possible to obtain these 3 pieces of information? #1 is obtained by simply using FindWindow() and similar functions to check for the existance of a dialog box. The class name is "#32770". You can then use GetWindowThreadProcessId() to make sure the HWND belongs to your target application. Do note, however, that other Win32 API dialogs might reuse that same dialog class, so you will likely have to analyze the window a bit to make sure it really is a MessageBox dialog. #2 is almost, if not completely, impossible to obtain. Especially if you are trying to do all of this outside of that form class. #3 is obtainable from the result of #1. Alternatively, the code that is calling MessageBox() can obtain the HWND directly by installing a thread-local WH_CBT hook via SetWindowHookEx() before calling MessageBox(). The HCBT_ACTIVATE notification contains the HWND. Using a WH_CBT hook is a good way to customize a standard MessageBox dialgo with extra controls, for example. > This requirement comes from the need to close a form programatically, > which includes closing any forms opened by (owned by) that form, which > also includes (potentially) message boxes. I have been able to handle closing > TForm and TCommonDialog descendants, but I'm stuck on message boxes. If the TForm owns the MessageBox dialog, meaning that the TForm::Handle was specified when calling MessageBox(), then the message should close automatically when iwns Owner TForm is closed. If, on the other hand, a NULL owner was specified (which is usually the case), then your operation is going to have a very hard time figuring out whether the dialog belongs to the TForm or not. Gambit
Re: Handle of MessageBox
Author: Dennis Jones
Date: Wed, 31 May 2006 01:25
Date: Wed, 31 May 2006 01:25
16 lines
1653 bytes
1653 bytes
"Ed Mulroy" <dont_email_me@bitbuc.ket> wrote in message news:447cec43$1@newsgroups.borland.com... > You are going at it the hard way. Make a window that you use as a message > box. Make the button on the form open that window instead of a regular > message box. You can then supply a function which closes the window. When adding enhancements to a working application, I generally like to make as few changes as possible (for obvious reasons), so creating another dialog and injecting it into my code (in who knows how many places) was something I was hoping to avoid. However, given the relative ease of implementation, I suppose it is a more reasonable alternative, comparatively speaking. Thanks, - Dennis
Re: Handle of MessageBox
Author: Dennis Jones
Date: Wed, 31 May 2006 01:44
Date: Wed, 31 May 2006 01:44
21 lines
1653 bytes
1653 bytes
"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message news:447cee05$1@newsgroups.borland.com... > From where exactly? MessageBox() shows a modal dialog, so you can't close > it from the context of the thread that is displaying it (without some > low-level hooks, that is). Right. In my case, the process is kicked off by a TTimer::OnTimer event handler on the application's main form and uses PostMessage calls to close the windows in question. The rest of your message pretty much falls in line with what I was expecting. Fortunately, Ed's suggestion is a better (and simpler!) alternative to implementing a complex solution that may or may not even work! By creating and using a custom message box class, the solution becomes trivial. Thanks, - Dennis
Re: Handle of MessageBox
Author: Remy Lebeau (TeamB)
Date: Wed, 31 May 2006 02:02
Date: Wed, 31 May 2006 02:02
66 lines
2816 bytes
2816 bytes
"Dennis Jones" <nospam@nospam.com> wrote in message
news:447cf4e6$1@newsgroups.borland.com...
> Right. In my case, the process is kicked off by a TTimer::OnTimer event
> handler on the application's main form and uses PostMessage calls to close
> the windows in question.
One thing to try is to have each form that shows a MessageBox grab the HWND,
like I mentioned earlier, and store it in a member of itself. Then your
TTimer can close the active MessageBox of any form it wants. For example
(untested):
class TForm1 : public TForm
{
private:
HWND hMsgBoxWnd;
HHOOK hMsgBoxHook;
static LRESULT CALLBACK MsgBoxCBTProc(int nCode, WPARAM wParam,
LPARAM lParam);
public:
int __fastcall ShowMsgBox(const AnsiString &Msg, const AnsiString
&Title, int Flags);
void __fastcall CloseMsgBox();
};
LRESULT CALLBACK TForm1::MsgBoxCBTProc(int nCode, WPARAM wParam, LPARAM
lParam)
{
if( nCode == HCBT_ACTIVATE )
Form1->hMsgBoxWnd = reinterpret_cast<HWND>(wParam);
return ::CallNextHookEx(Form1->hMsgBoxHook);
}
int __fastcall TForm1::ShowMsgBox(const AnsiString &Msg, const
AnsiString &Title, int Flags)
{
hMsgBoxHook = ::SetWindowsHookEx(WH_CBT, (HOOKPROC) MsgBoxCBTProc,
NULL, GetCurrentThreadId());
if( !hMsgBoxHook )
return 0;
int iRet = ::MessageBox(NULL, Msg.c_str(), Title.c_str(), Flags);
hMsgBoxWnd = NULL;
::UnhookWindowsHookEx(hMsgBoxHook);
hMsgBoxHook = NULL;
return iRet;
}
void __fastcall TForm1::CloseMsgBox()
{
if( hMsgBoxWnd )
::EndDialog(hMsgBoxWnd, IDABORT);
}
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
Form1->CloseMsgBox();
}
Gambit
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads