jbirk
asked on
tabbing between edits on a modeless dialog
This should be something easy, but for reason I can't get my modeless dialog to tab between items or receive the enter key (I want to take a special action when enter is pressed while the modeless dialog is in focus).
PLEASE HELP!
I'm using Visual C++ 6.
If you need any other info, just ask and I can post code or whatever.
PLEASE HELP!
I'm using Visual C++ 6.
If you need any other info, just ask and I can post code or whatever.
this is probably because you are not calling IsDialogMessage in your message processing. what window is the parent to this modeless dialog
ps - if you are launching it modeless why is it in a different thread?
ASKER
No I used a different thread to launch a modal, so the modal didn't interfere with the main app (i.e. acted like a modeless even though I used DoModal()). That was just a work around...
How do I call IsDialogMessage, and from where? Which message handler provided by mfc will allow this, or if not how do I get around the mfc code to do it? I don't have any message processing function or loop cause it's an mfc app.
For now the parent window is just a framework that I'm using to launch a series of modeless dialogs. Each dialogs' code is in a dll to make the project more updateable (some of the dialogs have images making them rather large too).
Thanks,
Josh
How do I call IsDialogMessage, and from where? Which message handler provided by mfc will allow this, or if not how do I get around the mfc code to do it? I don't have any message processing function or loop cause it's an mfc app.
For now the parent window is just a framework that I'm using to launch a series of modeless dialogs. Each dialogs' code is in a dll to make the project more updateable (some of the dialogs have images making them rather large too).
Thanks,
Josh
I've just made an app myself and the tabbing worked fine with no modifications in a modeless dialog - do you want to post code - you can send to shaun_wilde@many-monkeys.c om
IsDialogMessage should be already be called - the only time this cocks up is when you have anMFC app being hosted by a non MFC parent window
IsDialogMessage should be already be called - the only time this cocks up is when you have anMFC app being hosted by a non MFC parent window
ASKER
Hmm... interesting. My exe app is MFC as well as the dll which runs the dialog. I'll put an example of the code together tomorrow at work and send it to you. (the whole thing would be too much since it's a couple megabytes and includes some direct3d stuff as well)
Thanks for the help!
-Josh
Thanks for the help!
-Josh
okay - the odds are on the sample will work properly thought just to annoy us
ASKER
I've thought of that as a possibility as well:) Guess I'll find out soon enough...
ASKER
OK, it still didn't work. I've sent on my example. Please take a look at it. I included instructions on using it in the e-mail. Hopefully it's just some silly setting I don't have set right:)
-Josh
-Josh
ahhh - I see - the dialog is being hosted by a standard dll that supports MFC - this is the cause of your problems
If the host app was guaranteed to be an MFC app then I would opt for using an MFC extension DLL - this is what I did to get it working - copied over the dialog files and added the LaunchProperties function (but without the AFX_MANAGE_STATE call as it isn't needed in extension DLLs)
however if you do need to run it in an a normal DLL then...
this problem is actually documented in the MS KB
PRB: Modeless Dialog Box in a DLL Does Not Process TAB Key
ID: Q233263
(I was looking at this last night - but didn't think that it applied)
If you have to host the properties in a standalone DLL rather than an MFC extension DLL then you will need to use a message hook the obove article describes how you can do that
However - since this was a fun one I did it for you :) I modified you code to look like this (I hope you don't mind this being posted here but I couldn't see anything confidential that you wouldn't want seen)
HHOOK hHook;
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(prop->GetS afeHwnd(), 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(hHook, nCode, wParam, lParam);
}
BOOL CProperties::OnInitDialog( )
{
CDialog::OnInitDialog();
CFont cf;
LOGFONT lf;
m_quote1.GetFont()->GetLog Font(&lf);
lf.lfWeight = 700;
cf.CreateFontIndirect(&lf) ;
m_quote1.SetFont(&cf,TRUE) ;
m_quote2.SetFont(&cf,TRUE) ;
m_quote3.SetFont(&cf,TRUE) ;
m_quote4.SetFont(&cf,TRUE) ;
m_quote5.SetFont(&cf,TRUE) ;
hHook = SetWindowsHookEx( WH_GETMESSAGE, GetMsgProc,
NULL, GetCurrentThreadId() );
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CProperties::OnDestroy()
{
CDialog::OnDestroy();
// TODO: Add your message handler code here
UnhookWindowsHookEx( hHook );
}
void CProperties::OnClose()
{
if (m_bBlockCommands)
return;
CDialog::OnClose();
// removed the call to delete prop here as that will be handled in the PostNcDestroy - you may have noticed the warning messages in the debug view :)
}
If the host app was guaranteed to be an MFC app then I would opt for using an MFC extension DLL - this is what I did to get it working - copied over the dialog files and added the LaunchProperties function (but without the AFX_MANAGE_STATE call as it isn't needed in extension DLLs)
however if you do need to run it in an a normal DLL then...
this problem is actually documented in the MS KB
PRB: Modeless Dialog Box in a DLL Does Not Process TAB Key
ID: Q233263
(I was looking at this last night - but didn't think that it applied)
If you have to host the properties in a standalone DLL rather than an MFC extension DLL then you will need to use a message hook the obove article describes how you can do that
However - since this was a fun one I did it for you :) I modified you code to look like this (I hope you don't mind this being posted here but I couldn't see anything confidential that you wouldn't want seen)
HHOOK hHook;
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(prop->GetS
{
// 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(hHook, nCode, wParam, lParam);
}
BOOL CProperties::OnInitDialog(
{
CDialog::OnInitDialog();
CFont cf;
LOGFONT lf;
m_quote1.GetFont()->GetLog
lf.lfWeight = 700;
cf.CreateFontIndirect(&lf)
m_quote1.SetFont(&cf,TRUE)
m_quote2.SetFont(&cf,TRUE)
m_quote3.SetFont(&cf,TRUE)
m_quote4.SetFont(&cf,TRUE)
m_quote5.SetFont(&cf,TRUE)
hHook = SetWindowsHookEx( WH_GETMESSAGE, GetMsgProc,
NULL, GetCurrentThreadId() );
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CProperties::OnDestroy()
{
CDialog::OnDestroy();
// TODO: Add your message handler code here
UnhookWindowsHookEx( hHook );
}
void CProperties::OnClose()
{
if (m_bBlockCommands)
return;
CDialog::OnClose();
// removed the call to delete prop here as that will be handled in the PostNcDestroy - you may have noticed the warning messages in the debug view :)
}
ASKER
Cool! That works. But I had to leave the delete in the close handler, because for some reason if you click the x it doesn't call postncdestroy so the var doesn't get nulled out and it won't launch a second time. Also I had to add the Unhook command to close and postncdestroy or I got a stack overflow when the window is launched a second time.
OK, now I have the problem that hitting enter closes the window. Instead I want enter to run the "Apply changes" button handler/code. Is there something I put in the hook function to do this?
Thanks!
-Josh
OK, now I have the problem that hitting enter closes the window. Instead I want enter to run the "Apply changes" button handler/code. Is there something I put in the hook function to do this?
Thanks!
-Josh
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Duh *hits self on forehead" :)
Thanks a lot!
Thanks a lot!
glad to help
ASKER
-Josh