Solved

Accelerator's problem in MDI application

Posted on 2000-03-21
34
931 Views
Last Modified: 2013-11-20
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
Comment
Question by:mike_marquet
  • 12
  • 10
  • 10
  • +1
34 Comments
 
LVL 30

Expert Comment

by:Zoppo
ID: 2639635
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
 
LVL 8

Expert Comment

by:VinExpert
ID: 2639708
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
 

Author Comment

by:mike_marquet
ID: 2639829
The WM_COMMAND is handled in CMainFrame.
The view has focus.
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 2640028
Does any window class (MainFrame, ChildFrame, View) of your app implement some PreTranslateMessage() behavior?
0
 

Author Comment

by:mike_marquet
ID: 2640099
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
 
LVL 8

Expert Comment

by:VinExpert
ID: 2640157
Hi,

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

VinExpert
0
 

Author Comment

by:mike_marquet
ID: 2640238
No, Ctrl-D is assigned to one item only.
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 2640309
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
 

Author Comment

by:mike_marquet
ID: 2640398
When I do this, I never see a call to ::TranslateAccelerator.
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 2640449
Does your code at least reach the BOOL CMDIFrameWnd::PreTranslateMessage(MSG* pMsg)
function?
0
 

Author Comment

by:mike_marquet
ID: 2640472
no
0
 
LVL 12

Expert Comment

by:migel
ID: 2640508
Hi!
just add IDR_....(ID for doc template)
accelerator resource with same command and key
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 2640535
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
 
LVL 12

Expert Comment

by:migel
ID: 2640584
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
 

Author Comment

by:mike_marquet
ID: 2640612
to migel :

In the IDR_MAINFRAME accelerator table (default)
The menu has also the IDR_MAINFRAME (default).
0
 
LVL 12

Expert Comment

by:migel
ID: 2640635
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
 
LVL 12

Expert Comment

by:migel
ID: 2640653
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
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 12

Expert Comment

by:migel
ID: 2640675
hmm
I build test project and found no problem
Is your ID attached to the menu command in the IDR_ (template  ID)
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 2640682
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
 
LVL 12

Expert Comment

by:migel
ID: 2640765
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
 
LVL 30

Expert Comment

by:Zoppo
ID: 2640817
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
 
LVL 12

Expert Comment

by:migel
ID: 2643528
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
 

Author Comment

by:mike_marquet
ID: 2643646
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
 
LVL 12

Expert Comment

by:migel
ID: 2643681
Hi!
my EMail is migel.geo@yahoo.com
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 2643683
mine is zoppo@cdsgmbh.de
0
 
LVL 12

Expert Comment

by:migel
ID: 2643753
Hi!
my EMail is migel.geo@yahoo.com
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 2643797
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
 

Author Comment

by:mike_marquet
ID: 2643867
I don't use a userdefine message in my test sample which has the same problem.
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 2643882
Then even my last idea is send us the sample ...
0
 
LVL 12

Expert Comment

by:migel
ID: 2644440
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
 
LVL 30

Accepted Solution

by:
Zoppo earned 50 total points
ID: 2644459
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
 

Author Comment

by:mike_marquet
ID: 2644585
Thanks to both.
How can I give points to both ?
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 2644899
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
 

Author Comment

by:mike_marquet
ID: 2644971
Thanks.
0

Featured Post

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Introduction: Load and Save to file, Document-View interaction inside the SDI. Continuing from the second article about sudoku.   Open the project in visual studio. From the class view select CSudokuDoc and double click to open the header …
Introduction: Ownerdraw of the grid button.  A singleton class implentation and usage. Continuing from the fifth article about sudoku.   Open the project in visual studio. Go to the class view – CGridButton should be visible as a class.  R…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now