tags:

views:

369

answers:

4

Hi, we have a C++ application that hosts a flex application in a MFC dialog. Everything works fine, all button pushes etc are passed directly on to flex with no problem at all, except the enter and escape keys, which immediately closes the dialog.

We can trap the enter key, by implementing PreTranslateMessage() or OnOK() and impede the window closing behavior, but we still have the problem of passing these enter key pushes on to the hosted flex app further.

There is no "default" button on the form or anything like that, perhaps MFC is linking the enter key to the close button in the title bar behind the scenes or something.

Does anyone have any ideas how we can stop MFC from treating the enter key from being a special case.

Thanks a lot for any hints.

Edit: Here is PreTranslateMessage() that mmonem requested.

BOOL CFlexDialog::PreTranslateMessage(MSG* pMsg)
{
  if ((pMsg->message == WM_KEYDOWN))
  {
    if (pMsg->wParam == VK_RETURN)
    {
      m_ctrlFlex->OnReturnKeyPressed();
      return TRUE;
    }
  }
  return __super::PreTranslateMessage(pMsg);
}

But it is not a suitable solution, calling a method in the flex app like that, as it makes life too difficult for the flex developer, it means he must write a special version implementing the return key behavior for every control.

We just want MFC to treat the return and escape keys like every other key.

A: 

MFC command buttons can respond to events even if they do not have the focus.

Have you tried trapping the OnClicked event and OnOk to return nothing?

Example: trap OnClick...

   void CMyDialog::OnClickedMyOK()
   {
      CDialog::OnOK();
   }

Then do a no-op in the OnOk()

void CMyDialog::OnOK()
{
}

This should stop the enter key from being processed.

JustBoo
Thanks but we want to pass the enter key on like all the other normal keys. This will solve the first problem, and prevent the enter key from closing the dialog, but it doesn't solve the second problem.
Kurt
If you trap the event in PreTranslateMessage() you can't just call the flex event directly? Or call it directly from OnOk()? What I mean is call/trigger/kick-off the flex "enter" event directly? You may have to give up on a "natural" passing of the event and trigger it yourself.
JustBoo
Any idea how I can "trigger a flex event" directly? I can call a method in the flex app like ReturnKeyPressed, but the flex developer says he cannot simulate a key press directly, he would have to subclass various controls like the TextField, and DataGrid etc to make sure the right thing happens. He just want's the return key to come through like a normal key event. I can trap it in various places, I just cannot pass it on to flex like a normal key press event.
Kurt
Note a new/different link for the subclassing post. HTH
JustBoo
A: 

Another approach is "Windows Subclassing." That is, sending messages from one Window Procedure, that is a WindProc() to another WndProc(). This may provide a way without direct intervention. (This is not C++ subclassing.)

Here's a way with MFC Subclassing Edit: Provided a better link.

Search for "Windows / MFC Subclassing" if more info needed.

The flex control/window has a WndProc and your window certainly has a WndProc, Windows Subclassing should work.


New Edit: Here is perhaps a better link for subclassing an ActiveX control.

ActiveX Controls: Subclassing a Windows Control

Subclassing Windows Forms Controls - More .Net-centric.

Notice: In MFC you should see these functions.

CWnd::SubclassDlgItem

CWnd::SubclassWindow

CDialog inherits from CWnd so you will see those two functions as "dialog" functions as well. They are key to making this work. If the flash window is a true window, use SubclassWindow. If it's a control use SubclassDlgItem.

And finally, if nothing else works. A product/library that will hopefully make it easy. EasyHook looks like a product here. EasyHook at CodeProject, you can get all the source code.

JustBoo
Thanks I will try this when I get time.
Kurt
I dunno, I am having a lot of trouble with this. I take it I am supposed to redefine the WndProc of the Flex control, trap the Enter key in my MFC dialog, and then call either this new WndProc (or the original, as SetWindowLongPtr returns the function pointer for the original WndProc) directly in a way that simulates an Enter key event.In my MFC dialog control's OnInitDialog I call this SetWindowLongPtr to get the original WndProc, and specify my own. At the moment my own one just does a CallWindowProc on the original. But now I am getting run time errors in wincore.cpp and dlgcore.cpp.
Kurt
Anyway, this has to be a common scenario, MFC trapping the enter and escape keys, when it is desired that they go through like normal keypresses must be a common problem, there must be a trivial solution. Or at least how MFC Subclassing is supposed to lead to a solution, and how that is best implemented.Is there maybe a better website that explains in more detail exactly what I need to do?
Kurt
Although I am skeptical whether being able to "inject" events directly into the Flex Controls WndProc will solve the problem. I have the feeling that this WndProc doesn't see the events anyway, and that this WndProc will still have to do something special to ensure the specific controls in the flex app get the events like a normal keypress. Basically I just want MFC to ignore escape and return and pass them on like every other key.
Kurt
+1  A: 

Remove OnOK() and OnCancel(); PreTransateMessage is enough after considering VK_ESCAPE.

Why don't you use:

m_ctrlFlex->SendMessage(WM_KEYDOWN, VK_RETURN, 0)

instead of

m_ctrlFlex->OnReturnKeyPressed();

in your implementation of PreTranslateMessage ?

mmonem
Thanks for the answer. In this case, m_ctrlFlex is a CWinFormsControl<NGuiFlex::FlexUserControl>m_ctrlFlex->SendMessage did not work, as SendMessage is not a member of our type FlexUserControl, but m_ctrlFlex.SendMessage did work, as CWinFormsControl is an MFC dialog.Unfortunately it did not work. We did not get an error message or anything, the message seemed to be sent, but the controls on the flex form did not react in a way they usually do when the return key is pressed.I guess CWinFormsControl got the event, but did not want to do anything with it.
Kurt
I don't know if trying `PostMessage()` instead of `SendMessage()` can help but try to send/post any other test message to the control to know whether the problem comes from sending/posting in general or from this message specifically
mmonem
This is a good article about hosting CWinFormsControl in CDialog:http://www.codeproject.com/KB/miscctrl/mfcdialogwinforms.aspx
mmonem
It might be that Flex does not process a keypress until the KeyDown and KeyUp events occur. What happens if you send WM_KEYUP immediately after WM_KEYDOWN?
Aidan Ryan
A: 

If you are having issues handling tabs & enter keys I would recommend you look into using a window instead of a dialog. The dialog adds modal ( if you are using modal ), tabbing & default button handling. If you don't need/want those features, or if they are getting in your way, then don't use a dialog.

If I understand what you are doing, then you want flex to handle tabbing, enter key, and all sorts of other messages. Get the dialog code out of the way. If you still want modal style, then you may have to handle the enable/disabling of parent windows - thats all that windows does when you open a modal dialog.

Zac