• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1091
  • Last Modified:

Accelerator's problem in MDI application

I have a problem using accelerator's in my MDI application.
I have for example a menu item called IDM_MENUTEST
In my accelerator table, I have IDM_MENUTEST mapped to Ctrl+D

When my application shows 2 differents childs and when I press Ctrl+D, nothing happens.
But when I minimize this 2 childs and press then Ctrl+D, it works.

Any idea. ?
0
mike_marquet
Asked:
mike_marquet
  • 12
  • 10
  • 10
  • +1
1 Solution
 
ZoppoCommented:
Hi mike_marquet,

where do you handle the command and command_update_ui message for this item, in CMainFrame or CChildFrame?

Do the child frames or views have focus or capture set?

ZOPPO
0
 
Vinayak KumbarSr Program ManagerCommented:
Hi,

Where U have mapped that ID's member function?. I think U have done it for some child class. Then it will work if only that child is in focus. If U want that function to be called independent of the focus, then map that function to the CMainFrame or C..App class.

Give some more details about Ur prob.

VinExpert
0
 
mike_marquetAuthor Commented:
The WM_COMMAND is handled in CMainFrame.
The view has focus.
0
Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
ZoppoCommented:
Does any window class (MainFrame, ChildFrame, View) of your app implement some PreTranslateMessage() behavior?
0
 
mike_marquetAuthor Commented:
Yes, WM_SYSCOMMAND to intercept ALT-F4.
But only this.
It's the same when I remove it.
I have made some test.
When the application is started :

I press Ctrl-D (nothing happens)
I go to the menu item and press it (OK)
I press Ctrl-D (nothing happens)
I minimize all child windows.
I press Ctrl-D (nothing happens)
I go to the menu item and press it (OK)
I press Ctrl-D (It works)
0
 
Vinayak KumbarSr Program ManagerCommented:
Hi,

Is there any duplication of the hot keys?
Ctrl+D is assigned to more than one menu item?

VinExpert
0
 
mike_marquetAuthor Commented:
No, Ctrl-D is assigned to one item only.
0
 
ZoppoCommented:
you could try do following:

add the application class a PreTranslateMessage-function and there set a breakpoint like this:

BOOL CCtApp::PreTranslateMessage(MSG* pMsg)
{
 if ( pMsg->message == WM_KEYDOWN && pMsg->wParam == 'D' )
 {
  int dummyInt = 0; // set a breakpoint here
 }
 return CWinApp::PreTranslateMessage(pMsg);
}

when the breakpoint halts the app's execution you can step into CWinApp::PreTranslateMessage():

BOOL CWinThread::PreTranslateMessage(MSG* pMsg)
{
....
// step inside this WalkPreTranslateTree
 if (CWnd::WalkPreTranslateTree(pMainWnd->GetSafeHwnd(), pMsg))
  return TRUE;
 ...
}

Inside this WalkPreTranslateTree there's a PreTranslateMessage()-call for first the child frames and later the main frame. Step into these and see if execution arrives CMDIFrameWnd::PreTranslateMessage and inside it the call to ::TranslateAccelerator. If this call is not reached, check the reason why it isn't...

ZOPPO
0
 
mike_marquetAuthor Commented:
When I do this, I never see a call to ::TranslateAccelerator.
0
 
ZoppoCommented:
Does your code at least reach the BOOL CMDIFrameWnd::PreTranslateMessage(MSG* pMsg)
function?
0
 
mike_marquetAuthor Commented:
no
0
 
migelCommented:
Hi!
just add IDR_....(ID for doc template)
accelerator resource with same command and key
0
 
ZoppoCommented:
Now, than I guess either your view class or your child frame class has an implemented PreTranslateMessage() which returns TRUE in this case ... but it's just a guess as you told you haven't implemented PreTranslateMessage() for one of your window classes.

What's the deepest function you can step into from CWinThread::PreTranslateMessage() and where/why does it return?


eh, migel, he told he did...
>In my accelerator table, I have IDM_MENUTEST mapped to Ctrl+D

ZOPPO
0
 
migelCommented:
Hi!
about accelerator table
MFC load differ acc table for different doc templates and applay key mapping to the accelerator table of the current active MDI child window (based on DocTemplate defaults).
mike_marquet >> Where you define your CTRL+D key mapping?
0
 
mike_marquetAuthor Commented:
to migel :

In the IDR_MAINFRAME accelerator table (default)
The menu has also the IDR_MAINFRAME (default).
0
 
migelCommented:
Hi!
about accelerator table
MFC load differ acc table for different doc templates and applay key mapping to the accelerator table of the current active MDI child window (based on DocTemplate defaults).
mike_marquet >> Where you define your CTRL+D key mapping?
0
 
migelCommented:
Is menu command defined In the template resources? And have you handle this command in the child frames or views? also check dublicated ID in the IDR_MAINFRAME and template resources.
0
 
migelCommented:
hmm
I build test project and found no problem
Is your ID attached to the menu command in the IDR_ (template  ID)
0
 
ZoppoCommented:
Hi migel,

>MFC load differ acc table for different doc templates ...

I do not agree. There's a difference between accelerators and menus. The implementation of CFrameWnd::LoadFrame(), which is called by CMDIFrameWnd, loads the accelerator table with LoadAccelTable(). The implementation of CMDIChildWnd::LoadFrame(), which does NOT call CFrameWnd::LoadFrame(), doesn't load a new accelerator!

The only other place where a different accelerator may be loaded is in CFrameWnd::OnSetPreviewMode(), which temporary loads another one.

ZOPPO
0
 
migelCommented:
Hmm
ZOPPO>>
you aren`t right
look to the
void CMultiDocTemplate::LoadTemplate()->
this function read ACcelerator table and menu for specific doc template.
when template create MDIChildFrame it pass HANDLE to the accelerator to newl window.
sorry :-) (look to the MFC source)

0
 
ZoppoCommented:
Hmm, you're right, but only the mainframe's accelerator is used unless it's a COleServerDoc-derived embedded or in-place document or the (undocumented) virtual function CDocument::GetDefaultAccelerator() is overridden to return the templated m_hAccelTable (even look in MFC source)
0
 
migelCommented:
hmm
look at CMDIFrameWnd::PreTranslateMessage(...)
{
      CMDIChildWnd* pActiveChild = MDIGetActive();

      // current active child gets first crack at it
      if (pActiveChild != NULL && pActiveChild->PreTranslateMessage(pMsg))
            return TRUE;

      if (pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST)
      {
            // translate accelerators for frame and any children
            if (m_hAccelTable != NULL &&
                  ::TranslateAccelerator(m_hWnd, m_hAccelTable, pMsg))
            {
                  return TRUE;
            }

            // special processing for MDI accelerators last
            // and only if it is not in SDI mode (print preview)
            if (GetActiveView() == NULL)
            {
                  if (pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN)
                  {
                        // the MDICLIENT window may translate it
                        if (::TranslateMDISysAccel(m_hWndMDIClient, pMsg))
                              return TRUE;
                  }
            }
      }
}
an implementation CMDIChildWnd::PreTranslateMessage()
child window uses DocAccelerator (default NULL unless case you mentoned) or its own accelerators if doc acc is null
:-)
0
 
mike_marquetAuthor Commented:
The problem comes from the CPropertySheet which is inserted in my child view.

Can I send a sample to anyone, to look where's the problem comes from ?
0
 
migelCommented:
Hi!
my EMail is migel.geo@yahoo.com
0
 
ZoppoCommented:
mine is zoppo@cdsgmbh.de
0
 
migelCommented:
Hi!
my EMail is migel.geo@yahoo.com
0
 
ZoppoCommented:
Hi mike_marquet,

just an idea: do you use/handle any userdefine messages WM_USER or WM_USER+1? If so, could you test if one of these message handlers is called when CTRL-D doesn't work?

ZOPPO
0
 
mike_marquetAuthor Commented:
I don't use a userdefine message in my test sample which has the same problem.
0
 
ZoppoCommented:
Then even my last idea is send us the sample ...
0
 
migelCommented:
Hi!
mike
I found problem solution. PropertySheet::PreTranslateMessage handle keyboard input and assume that all input valid for it.
Solution
derive your own class form CPropertySheet and add virtual method PreTranslateMessage to it (don`t forget replace CPropertySheet to the your derived class in the View :-)
// method realisation
BOOL
CAccPropertySheet::PreTranslateMessage(MSG* pMsg)
{
      ASSERT_VALID(this);

      // allow tooltip messages to be filtered
      if (CWnd::PreTranslateMessage(pMsg))
            return TRUE;

      // allow sheet to translate Ctrl+Tab, Shift+Ctrl+Tab,
      //  Ctrl+PageUp, and Ctrl+PageDown
      if (pMsg->message == WM_KEYDOWN && GetAsyncKeyState(VK_CONTROL) < 0 &&
            (pMsg->wParam == VK_TAB || pMsg->wParam == VK_PRIOR || pMsg->wParam == VK_NEXT))
      {
            if (SendMessage(PSM_ISDIALOGMESSAGE, 0, (LPARAM)pMsg))
                  return TRUE;
      }

      if (pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST)
            {
            CFrameWnd* pFrame = GetParentFrame();
            while (pFrame)
                  {
                  if (pFrame->PreTranslateMessage(pMsg))
                        return TRUE;
                  pFrame = pFrame->GetParentFrame();
                  }
            }
      return PreTranslateInput(pMsg);
}

if you want I can send your modified test project back to you.
0
 
ZoppoCommented:
I have found similar solution:

// this is a copy of CPropertySheet::PreTranslateMessage() except the call to PreTranslateInput()
BOOL CMyPropSheet::PreTranslateMessage(MSG* pMsg)
{
 ASSERT_VALID(this);

 // allow tooltip messages to be filtered
 if (CWnd::PreTranslateMessage(pMsg))
            return TRUE;

 // allow sheet to translate Ctrl+Tab, Shift+Ctrl+Tab,
 //  Ctrl+PageUp, and Ctrl+PageDown
 if (pMsg->message == WM_KEYDOWN && GetAsyncKeyState(VK_CONTROL) < 0 &&
 (pMsg->wParam == VK_TAB || pMsg->wParam == VK_PRIOR || pMsg->wParam == VK_NEXT))
 {
  if (SendMessage(PSM_ISDIALOGMESSAGE, 0, (LPARAM)pMsg))
   return TRUE;
 }

 // handle rest with IsDialogMessage
 // return PreTranslateInput(pMsg);
 return FALSE;
}


seems that calling of IsDialogMessage() (called by PreTranslateInput) for modeless property sheets always returns TRUE.

ZOPPO
0
 
mike_marquetAuthor Commented:
Thanks to both.
How can I give points to both ?
0
 
ZoppoCommented:
Unfortunately it's not (yet?) possible to split points ...

If you want to give both of us some points you can only accept comment of one of us as answer and ask a new (dummy) question 'points for XYZ'...

If you don't want to give further points you should accept the comment you use ...


BTW, it was an interesting problem, and I'm glad for you that it's working now...
0
 
mike_marquetAuthor Commented:
Thanks.
0

Featured Post

[Webinar] Improve your customer journey

A positive customer journey is important in attracting and retaining business. To improve this experience, you can use Google Maps APIs to increase checkout conversions, boost user engagement, and optimize order fulfillment. Learn how in this webinar presented by Dito.

  • 12
  • 10
  • 10
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now