Link to home
Start Free TrialLog in
Avatar of jbirk
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.
Avatar of jbirk
jbirk

ASKER

I was able to allow tabs by launching a thread which launched it as a modal instead of modeless.  Modals seem to have no problem tabbing and such, but there are other problems with this method.  It makes it more difficult to communicate with since it's a modal now...  I would still like to find a solution that uses a true modeless dialog.

-Josh
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?
Avatar of jbirk

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
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.com

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
Avatar of jbirk

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
okay - the odds are on the sample will work properly thought just to annoy us
Avatar of jbirk

ASKER

I've thought of that as a possibility as well:)  Guess I'll find out soon enough...
Avatar of jbirk

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
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->GetSafeHwnd(), 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()->GetLogFont(&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 :)
}
Avatar of jbirk

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
ASKER CERTIFIED SOLUTION
Avatar of ShaunWilde
ShaunWilde

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of jbirk

ASKER

Duh *hits self on forehead" :)

Thanks a lot!
glad to help