Professional UI Solutions
Site Map   /  Register
 
 

Forum

Please Log In to post a new message or reply to an existing one. If you are not registered, please register.

NOTE: Some forums may be read-only if you are not currently subscribed to our technical support services.

Forums » Prof-UIS Tech Support » CExtGridInplaceEdit, cut/copy/paste accelerators Collapse All
Subject Author Date
Suhai Gyorgy Feb 14, 2007 - 8:40 AM

In my application, I have some commands connected to the usual cut/copy/paste accelerators (Ctrl+X, C and V) (for copying my internal objects). When an object is selected, its properties are shown in a CExtPropertyCtrl. But when the user changes some property (the focus is in an inplace editor of the grid) and Ctrl+X is used to cut some text from the grid, the command connected to the accelerator is invoked, my object is cut (deleted), thus the propertygrid gets cleared and my application crashes as it tries to set a value to a cell that doesn’t even exist anymore.

I’ve learnt that it is Windows’ design to have the command called before the message would be sent to the editor, but I think, with inplace editor, the situation is pretty special and your code should catch these special editing commands inside your CExtGridInplaceEdit class with PreTranslateMessage.

If I just make a CExtGridInplaceEdit-derived class and handle PreTranslateMessage as supposed to, I still have to make many cell classes derived from your cell classes as there are many different implementations of OnInplaceControlCreate in the different classes. I should copy all code from your classes to my classes just to have my CExtGridInplaceEdit-derived editor created, and if anything changes in your code over the version upgrades, I will have to take care of copying these changes to my classes. So this seems like an unfairly great work for an obvoius task like this.

Please let me know what you think of this. Thank you.

Technical Support Feb 20, 2007 - 3:20 AM

Thank you for reporting the bug. You can fix it in this way:

1) Find switch( msg.message )in the CExtGridWnd::OnGbwBeginEdit method and in the default section find the following code snippet:

if(       ( ! bStopFlag )
    &&    WM_KEYFIRST <= msg.message
    &&    msg.message <= WM_KEYLAST
    &&    msg.hwnd != m_hWndInplaceControl
    &&    (!::IsChild( m_hWndInplaceControl, msg.hwnd ))
    )
{
    if( msg.hwnd != hWndGrid )
        bStopFlag = true;
    ::PeekMessage(&msg,NULL,msg.message,msg.message,PM_REMOVE);
}<pre>

2) Rplace it with the following code:<pre>if(        ( ! bStopFlag )
    &&    WM_KEYFIRST <= msg.message
    &&    msg.message <= WM_KEYLAST
    &&    (    msg.hwnd != m_hWndInplaceControl 
        ||    (!::IsChild( m_hWndInplaceControl, msg.hwnd )) 
        )
    )
{
    bool bAlt =
        ( (::GetAsyncKeyState(VK_MENU)&0x8000) != 0 )
            ? true : false;
    if( !bAlt )
    {
        bool bCtrl =
            ( (::GetAsyncKeyState(VK_CONTROL)&0x8000) != 0 )
                ? true : false;
        bool bShift =
            ( (::GetAsyncKeyState(VK_SHIFT)&0x8000) != 0 )
                ? true : false;
        if(        bCtrl
            &&    (!bShift)
            &&    (    int(msg.wParam) == VK_INSERT
                ||    int(msg.wParam) == int( _T(’C’) )
                )
            )
        {
            ::PeekMessage(&msg,NULL,msg.message,msg.message,PM_REMOVE);
            ::SendMessage( msg.hwnd, WM_COPY, 0, 0 );
            continue;
        } 
        if(       ( bCtrl && (!bShift) && int(msg.wParam) == int( _T(’V’) ) )
            ||    ( (!bCtrl) && bShift && int(msg.wParam) == VK_INSERT )
            )
        {
            ::PeekMessage(&msg,NULL,msg.message,msg.message,PM_REMOVE);
            ::SendMessage( msg.hwnd, WM_PASTE, 0, 0 );
            continue;
        } 
        if(       ( bCtrl && (!bShift) && int(msg.wParam) == int( _T(’X’) ) )
            ||    ( (!bCtrl) && bShift && int(msg.wParam) == VK_DELETE )
            )
        {
            ::PeekMessage(&msg,NULL,msg.message,msg.message,PM_REMOVE);
            ::SendMessage( msg.hwnd, WM_CUT, 0, 0 );
            continue;
        } 
        if(    bCtrl && (!bShift) && int(msg.wParam) == int( _T(’A’) ) ) 
        {
            ::PeekMessage(&msg,NULL,msg.message,msg.message,PM_REMOVE);
            ::SendMessage( msg.hwnd, EM_SETSEL, 0, -1 );
            continue;
        }
    } // if( !bAlt )
}
After that, recompile the library.

Suhai Gyorgy Feb 20, 2007 - 4:59 AM

Thank you, it is much better now, but still not perfect. I couldn’t find out exactly when/why it happens, but sometimes Ctrl+V copies the text twice (I’m definitely just pressing the key shortly, to have it pasted once).

Another thing missing from your code is the VK_DELETE key without Ctrl or Shift (for removing characters behind caret).

Technical Support Feb 20, 2007 - 9:02 AM

Thank you for reporting the issue. Please update the source code of the CExtGridWnd::OnGbwBeginEdit() method in the ../Prof-UIS/Src/ folder:

bool CExtGridWnd::OnGbwBeginEdit(
      LONG nVisibleColNo,
      LONG nVisibleRowNo,
      LONG nColNo,
      LONG nRowNo,
      INT nColType,
      INT nRowType,
      const RECT & rcCellExtra,
      const RECT & rcCell,
      const RECT & rcInplaceControl,
      bool bContinueMsgLoop, // = true
      __EXT_MFC_SAFE_LPCTSTR strStartEditText // = NULL
      )
{
      ASSERT_VALID( this );
      if(   CExtGridBaseWnd::OnGbwBeginEdit(
                  nVisibleColNo,
                  nVisibleRowNo,
                  nColNo,
                  nRowNo,
                  nColType,
                  nRowType,
                  rcCellExtra,
                  rcCell,
                  rcInplaceControl,
                  bContinueMsgLoop,
                  strStartEditText
                  )
            )
            return true;

      if(   CExtPopupMenuWnd::IsMenuTracking() )
            CExtPopupMenuWnd::CancelMenuTracking();
      CWnd::CancelToolTips();

DWORD dwBseStyle = BseGetStyle();
      if( nColType < 0 && (dwBseStyle&__EGWS_BSE_EDIT_CELLS_OUTER_L) == 0L )
            return false;
      else if( nColType > 0 && (dwBseStyle&__EGWS_BSE_EDIT_CELLS_OUTER_R) == 0L )
            return false;
      else if( nColType == 0 && (dwBseStyle&__EGWS_BSE_EDIT_CELLS_INNER) == 0L )
            return false;
      else if( nRowType < 0 && (dwBseStyle&__EGWS_BSE_EDIT_CELLS_OUTER_T) == 0L )
            return false;
      else if( nRowType > 0 && (dwBseStyle&__EGWS_BSE_EDIT_CELLS_OUTER_B) == 0L )
            return false;
      else if( nRowType == 0 && (dwBseStyle&__EGWS_BSE_EDIT_CELLS_INNER) == 0L )
            return false;

static CExtGridCell * g_pEditCell = NULL;
bool bDoMsgLoop = true;
      if( m_hWndInplaceControl != NULL )
      {
            if( ! bContinueMsgLoop )
                  return false;
            HWND hWndInplaceControl = m_hWndInplaceControl;
            m_hWndInplaceControl = NULL;
            if( hWndInplaceControl != NULL )
            {
                  bDoMsgLoop = false;
                  if( ::IsWindow(hWndInplaceControl) )
                        ::DestroyWindow( hWndInplaceControl );
            } // if( hWndInplaceControl != NULL )
      } // if( m_hWndInplaceControl != NULL )
CRect rcActivate( rcInplaceControl );
      if(         rcActivate.left >= rcActivate.right
            ||    rcActivate.top >= rcActivate.bottom
            )
      { // if invalid rect - recalc it
            if(   ! GridCellRectsGet(
                        nColNo,
                        nRowNo,
                        nColType,
                        nRowType,
                        NULL,
                        NULL,
                        NULL,
                        &rcActivate // pRectTextArea
                        )
                  )
            {
                  g_pEditCell = NULL;
                  return false;
            }
            if( rcActivate.IsRectEmpty() )
            {
                  g_pEditCell = NULL;
                  return false;
            }
      } // if invalid rect - recalc it
CExtGridCell * pCellToEdit =
            GridCellGet(
                  nColNo,
                  nRowNo,
                  nColType,
                  nRowType
                  );
      if( pCellToEdit == NULL )
            return false;
      ASSERT_VALID( pCellToEdit );
      ASSERT( pCellToEdit->IsKindOf(RUNTIME_CLASS(CExtGridCell)) );
      ASSERT_VALID( pCellToEdit->DataProviderGet() );
      g_pEditCell = pCellToEdit;
      m_hWndInplaceControl =
            g_pEditCell->OnInplaceControlCreate(
                  *this,
                  nVisibleColNo,
                  nVisibleRowNo,
                  nColNo,
                  nRowNo,
                  nColType,
                  nRowType,
                  rcCellExtra,
                  rcCell,
                  rcActivate,
                  m_nHelperLastEditedColNo,
                  m_nHelperLastEditedRowNo
                  );
      if(         m_hWndInplaceControl == NULL
            ||    ( ! ::IsWindow( m_hWndInplaceControl ) )
            )
      {
            m_hWndInplaceControl = NULL;
            g_pEditCell = NULL;
            DWORD dwCellStyle = pCellToEdit->GetStyle();
            if( (dwCellStyle&__EGCS_CHK_MASK) == 0 )
            {
                  if( (dwCellStyle&__EGCS_BUTTON_DROPDOWN) != 0 )
                  {
                        bool bEnabled = false;
                        if( pCellToEdit->OnQueryButtonInfo(
                                    INT(CExtGridCell::__EBTT_DROPDOWN),
                                    &bEnabled
                                    )
                              )
                        {
                              if( bEnabled )
                              {
                                    pCellToEdit->OnButtonPressed(
                                          *this,
                                          INT(CExtGridCell::__EBTT_DROPDOWN),
                                          rcCellExtra,
                                          rcCell,
                                          nVisibleColNo,
                                          nVisibleRowNo,
                                          nColNo,
                                          nRowNo,
                                          nColType,
                                          nRowType
                                          );
                                    return true;
                              } // if( bEnabled )
                        }
                  } // if( (dwCellStyle&__EGCS_BUTTON_DROPDOWN) != 0 )
            } // if( (dwCellStyle&__EGCS_CHK_MASK) == 0 )
            return false;
      }
      m_nHelperLastEditedColNo = nColNo;
      m_nHelperLastEditedRowNo = nRowNo;
      if( ! bDoMsgLoop )
            return true;

CWinThread * pThread = ::AfxGetThread();
      ASSERT_VALID( pThread );

      if( strStartEditText != NULL )
      {
            bool bInplaceIsEditCommonControlOrRichEdit = false;
            TCHAR strClassName[512];
            ::GetClassName( m_hWndInplaceControl, strClassName, 512 );
            if( _tcslen( strClassName ) > 0 )
            {
                  __EXT_MFC_STRLWR( strClassName, 512 );
                  if(         _tcsstr( strClassName, _T("edit") ) != NULL
                        ||    _tcsstr( strClassName, _T("riched") ) != NULL
                        )
                  {
                        bInplaceIsEditCommonControlOrRichEdit = true;
                        ::SendMessage( m_hWndInplaceControl, EM_SETSEL, WPARAM(0), LPARAM(-1) );
                        ::SendMessage( m_hWndInplaceControl, EM_REPLACESEL, WPARAM(TRUE), LPARAM(strStartEditText) );
                  }
            } // if( _tcslen( strClassName ) > 0 )
            if( ! bInplaceIsEditCommonControlOrRichEdit )
                  ::SetWindowText( m_hWndInplaceControl, strStartEditText );
      } // if( strStartEditText != NULL )

HWND hWndGrid = m_hWnd;
bool bStopFlag = false;
      for(  MSG msg;
                        m_hWndInplaceControl != NULL
                  &&    ::IsWindow( m_hWndInplaceControl )
                  &&    ::IsWindowVisible( m_hWndInplaceControl )
                  &&    ::IsWindow( hWndGrid )
                  &&    (!bStopFlag)
                  &&    (g_pEditCell != NULL)
                  ;
            )
      { // in-place editor message loop
            if( ! ::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) )
            {
                  if(         m_hWndInplaceControl == NULL
                        ||    ( ! ::IsWindow( m_hWndInplaceControl ) )
                        ||    ( ! ::IsWindow( hWndGrid ) )
                        ||    bStopFlag
                        ||    g_pEditCell == NULL
                        )
                        break;
                  LONG nIdleCounter = 0L;
                  for(  nIdleCounter = 0L;
                              g_pEditCell->OnInplaceControlIdle(
                                    m_hWndInplaceControl,
                                    *this,
                                    nIdleCounter
                                    );
                              nIdleCounter ++
                              )
                  {
                        ASSERT_VALID( g_pEditCell );
                  }
                  if( CExtGridWnd::g_bEnableOnIdleCalls )
                  {
                        for(  nIdleCounter = 0L;
                                    pThread->OnIdle(nIdleCounter);
                                    nIdleCounter ++
                                    );
                  }
                  ::WaitMessage();
                  continue;
            } // if( ! ::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) )

            switch( msg.message )
            {
            case WM_KILLFOCUS:
                  if( msg.hwnd == m_hWndInplaceControl )
                        bStopFlag = true;
            break;
            case WM_CANCELMODE:
            case WM_ACTIVATEAPP:
            case WM_SYSCOMMAND:
            case WM_SETTINGCHANGE:
            case WM_SYSCOLORCHANGE:
                  bStopFlag = true;
            break;
            case WM_COMMAND:
                  if(         (HIWORD(msg.wParam)) == 0
                        ||    (HIWORD(msg.wParam)) == 1
                        )
                        bStopFlag = true;
            break;
            case WM_CAPTURECHANGED:
                  if( (HWND)msg.wParam != m_hWndInplaceControl )
                        bStopFlag = true;
            break;

            case WM_LBUTTONUP:
            case WM_LBUTTONDOWN:
            case WM_LBUTTONDBLCLK:
            case WM_RBUTTONUP:
            case WM_RBUTTONDOWN:
            case WM_RBUTTONDBLCLK:
            case WM_MBUTTONUP:
            case WM_MBUTTONDOWN:
            case WM_MBUTTONDBLCLK:
            case WM_NCLBUTTONUP:
            case WM_NCLBUTTONDOWN:
            case WM_NCLBUTTONDBLCLK:
            case WM_NCRBUTTONUP:
            case WM_NCRBUTTONDOWN:
            case WM_NCRBUTTONDBLCLK:
            case WM_NCMBUTTONUP:
            case WM_NCMBUTTONDOWN:
            case WM_NCMBUTTONDBLCLK:
            case WM_CONTEXTMENU:
                  if(         msg.hwnd != m_hWndInplaceControl
                        &&    (!::IsChild( m_hWndInplaceControl, msg.hwnd ))
                        )
                        bStopFlag = true;
            break;
            default:
                  if(         ( ! bStopFlag )
                        &&    WM_KEYFIRST <= msg.message
                        &&    msg.message <= WM_KEYLAST
                        &&    (     msg.hwnd != m_hWndInplaceControl 
                              ||    (!::IsChild( m_hWndInplaceControl, msg.hwnd )) 
                              )
                        )
                  {
                        bool bAlt =
                              ( (::GetAsyncKeyState(VK_MENU)&0x8000) != 0 )
                                    ? true : false;
                        if( !bAlt )
                        {
                              bool bCtrl =
                                    ( (::GetAsyncKeyState(VK_CONTROL)&0x8000) != 0 )
                                          ? true : false;
                              bool bShift =
                                    ( (::GetAsyncKeyState(VK_SHIFT)&0x8000) != 0 )
                                          ? true : false;
                              if(         bCtrl
                                    &&    (!bShift)
                                    &&    (     int(msg.wParam) == VK_INSERT
                                          ||    int(msg.wParam) == int( _T(’C’) )
                                          )
                                    )
                              {
                                    ::PeekMessage(&msg,NULL,msg.message,msg.message,PM_REMOVE);
                                    if( msg.message == WM_KEYDOWN )
                                          ::SendMessage( msg.hwnd, WM_COPY, 0, 0 );
                                    continue;
                              } 
                              if(         ( bCtrl && (!bShift) && int(msg.wParam) == int( _T(’V’) ) )
                                    ||    ( (!bCtrl) && bShift && int(msg.wParam) == VK_INSERT )
                                    )
                              {
                                    ::PeekMessage(&msg,NULL,msg.message,msg.message,PM_REMOVE);
                                    if( msg.message == WM_KEYDOWN )
                                          ::SendMessage( msg.hwnd, WM_PASTE, 0, 0 );
                                    continue;
                              } 
                              if(         ( bCtrl && (!bShift) && int(msg.wParam) == int( _T(’X’) ) )
                                    ||    ( (!bCtrl) && bShift && int(msg.wParam) == VK_DELETE )
                                    )
                              {
                                    ::PeekMessage(&msg,NULL,msg.message,msg.message,PM_REMOVE);
                                    if( msg.message == WM_KEYDOWN )
                                          ::SendMessage( msg.hwnd, WM_CUT, 0, 0 );
                                    continue;
                              } 
                              if(   bCtrl && (!bShift) && int(msg.wParam) == int( _T(’A’) ) ) 
                              {
                                    ::PeekMessage(&msg,NULL,msg.message,msg.message,PM_REMOVE);
                                    if( msg.message == WM_KEYDOWN )
                                          ::SendMessage( msg.hwnd, EM_SETSEL, 0, -1 );
                                    continue;
                              }
                        } // if( !bAlt )
                  }
            break;
            } // switch( msg.message )

            if( bStopFlag )
                  break;
            if( ! pThread->PumpMessage() )
                  break;

      } // in-place editor message loop
      
      g_pEditCell = NULL;
      if( ! ::IsWindow( hWndGrid ) )
            return true;
      ASSERT( CWnd::FromHandlePermanent(hWndGrid) == this );
      ASSERT_VALID( this );
      m_nHelperLastEditedColNo = -1L;
      m_nHelperLastEditedRowNo = -1L;
      if( m_hWndInplaceControl != NULL )
      {
            if( ::IsWindow(m_hWndInplaceControl) )
            {
                  if( ::GetCapture() == m_hWndInplaceControl )
                        ::ReleaseCapture();
                  ::ShowWindow( m_hWndInplaceControl, SW_HIDE );
                  ::SetFocus( m_hWnd ); // after changing focus inplace control kill itself
                  // ::DestroyWindow( m_hWndInplaceControl );
            } // if( ::IsWindow(m_hWndInplaceControl) )
            m_hWndInplaceControl = NULL;
      } // if( m_hWndInplaceControl != NULL )
      return true;
}

Suhai Gyorgy Feb 21, 2007 - 2:24 AM

Now double pasting has disappeared, thank you. But pressing VK_DELETE still doesn’t remove the character on the right side of the caret. In your code I can’t see any part that would handle that case.

Technical Support Feb 22, 2007 - 8:46 AM

Please let us know the following details:

1) Whether the problem with VK_DELETE occurs in the SimpleGrids sample when running on your computer?

2) Whether the accelerator table used in your application has a command assignment for VK_DELETE without any key modifiers (i.e. without Ctrl/Alt/Shift)?



Suhai Gyorgy Feb 22, 2007 - 9:38 AM

Sorry, I forgot to mention that, yes, I do have VK_DELETE in my accelerator-table without modifiers, so after reading your code, I wasn’t surprised that it is not working, I knew it was because of that accelerator-key entry. And of course, the problem doesn’t occur in SimpleGrids, as there is no accelerator-table entry like that in that sample.

But I think having VK_DELETE in the accelerator table is not a very special thing in an application, so I think the same part of your code should handle this situation, as well.

Thank you!
Chris

Technical Support Feb 22, 2007 - 11:48 AM

Here is the next improved version of the CExtGridWnd::OnGbwBeginEdit() method to be updated in the ../Src/ExtGridWnd.cpp file:

bool CExtGridWnd::OnGbwBeginEdit(
      LONG nVisibleColNo,
      LONG nVisibleRowNo,
      LONG nColNo,
      LONG nRowNo,
      INT nColType,
      INT nRowType,
      const RECT & rcCellExtra,
      const RECT & rcCell,
      const RECT & rcInplaceControl,
      bool bContinueMsgLoop, // = true
      __EXT_MFC_SAFE_LPCTSTR strStartEditText // = NULL
      )
{
      ASSERT_VALID( this );
      if(   CExtGridBaseWnd::OnGbwBeginEdit(
                  nVisibleColNo,
                  nVisibleRowNo,
                  nColNo,
                  nRowNo,
                  nColType,
                  nRowType,
                  rcCellExtra,
                  rcCell,
                  rcInplaceControl,
                  bContinueMsgLoop,
                  strStartEditText
                  )
            )
            return true;

      if(   CExtPopupMenuWnd::IsMenuTracking() )
            CExtPopupMenuWnd::CancelMenuTracking();
      CWnd::CancelToolTips();

DWORD dwBseStyle = BseGetStyle();
      if( nColType < 0 && (dwBseStyle&__EGWS_BSE_EDIT_CELLS_OUTER_L) == 0L )
            return false;
      else if( nColType > 0 && (dwBseStyle&__EGWS_BSE_EDIT_CELLS_OUTER_R) == 0L )
            return false;
      else if( nColType == 0 && (dwBseStyle&__EGWS_BSE_EDIT_CELLS_INNER) == 0L )
            return false;
      else if( nRowType < 0 && (dwBseStyle&__EGWS_BSE_EDIT_CELLS_OUTER_T) == 0L )
            return false;
      else if( nRowType > 0 && (dwBseStyle&__EGWS_BSE_EDIT_CELLS_OUTER_B) == 0L )
            return false;
      else if( nRowType == 0 && (dwBseStyle&__EGWS_BSE_EDIT_CELLS_INNER) == 0L )
            return false;

static CExtGridCell * g_pEditCell = NULL;
bool bDoMsgLoop = true;
      if( m_hWndInplaceControl != NULL )
      {
            if( ! bContinueMsgLoop )
                  return false;
            HWND hWndInplaceControl = m_hWndInplaceControl;
            m_hWndInplaceControl = NULL;
            if( hWndInplaceControl != NULL )
            {
                  bDoMsgLoop = false;
                  if( ::IsWindow(hWndInplaceControl) )
                        ::DestroyWindow( hWndInplaceControl );
            } // if( hWndInplaceControl != NULL )
      } // if( m_hWndInplaceControl != NULL )
CRect rcActivate( rcInplaceControl );
      if(         rcActivate.left >= rcActivate.right
            ||    rcActivate.top >= rcActivate.bottom
            )
      { // if invalid rect - recalc it
            if(   ! GridCellRectsGet(
                        nColNo,
                        nRowNo,
                        nColType,
                        nRowType,
                        NULL,
                        NULL,
                        NULL,
                        &rcActivate // pRectTextArea
                        )
                  )
            {
                  g_pEditCell = NULL;
                  return false;
            }
            if( rcActivate.IsRectEmpty() )
            {
                  g_pEditCell = NULL;
                  return false;
            }
      } // if invalid rect - recalc it
CExtGridCell * pCellToEdit =
            GridCellGet(
                  nColNo,
                  nRowNo,
                  nColType,
                  nRowType
                  );
      if( pCellToEdit == NULL )
            return false;
      ASSERT_VALID( pCellToEdit );
      ASSERT( pCellToEdit->IsKindOf(RUNTIME_CLASS(CExtGridCell)) );
      ASSERT_VALID( pCellToEdit->DataProviderGet() );
      g_pEditCell = pCellToEdit;
      m_hWndInplaceControl =
            g_pEditCell->OnInplaceControlCreate(
                  *this,
                  nVisibleColNo,
                  nVisibleRowNo,
                  nColNo,
                  nRowNo,
                  nColType,
                  nRowType,
                  rcCellExtra,
                  rcCell,
                  rcActivate,
                  m_nHelperLastEditedColNo,
                  m_nHelperLastEditedRowNo
                  );
      if(         m_hWndInplaceControl == NULL
            ||    ( ! ::IsWindow( m_hWndInplaceControl ) )
            )
      {
            m_hWndInplaceControl = NULL;
            g_pEditCell = NULL;
            DWORD dwCellStyle = pCellToEdit->GetStyle();
            if( (dwCellStyle&__EGCS_CHK_MASK) == 0 )
            {
                  if( (dwCellStyle&__EGCS_BUTTON_DROPDOWN) != 0 )
                  {
                        bool bEnabled = false;
                        if( pCellToEdit->OnQueryButtonInfo(
                                    INT(CExtGridCell::__EBTT_DROPDOWN),
                                    &bEnabled
                                    )
                              )
                        {
                              if( bEnabled )
                              {
                                    pCellToEdit->OnButtonPressed(
                                          *this,
                                          INT(CExtGridCell::__EBTT_DROPDOWN),
                                          rcCellExtra,
                                          rcCell,
                                          nVisibleColNo,
                                          nVisibleRowNo,
                                          nColNo,
                                          nRowNo,
                                          nColType,
                                          nRowType
                                          );
                                    return true;
                              } // if( bEnabled )
                        }
                  } // if( (dwCellStyle&__EGCS_BUTTON_DROPDOWN) != 0 )
            return false;
      }
      m_nHelperLastEditedColNo = nColNo;
      m_nHelperLastEditedRowNo = nRowNo;
      if( ! bDoMsgLoop )
            return true;

CWinThread * pThread = ::AfxGetThread();
      ASSERT_VALID( pThread );

      if( strStartEditText != NULL )
      {
            bool bInplaceIsEditCommonControlOrRichEdit = false;
            TCHAR strClassName[512];
            ::GetClassName( m_hWndInplaceControl, strClassName, 512 );
            if( _tcslen( strClassName ) > 0 )
            {
                  __EXT_MFC_STRLWR( strClassName, 512 );
                  if(         _tcsstr( strClassName, _T("edit") ) != NULL
                        ||    _tcsstr( strClassName, _T("riched") ) != NULL
                        )
                  {
                        bInplaceIsEditCommonControlOrRichEdit = true;
                        ::SendMessage( m_hWndInplaceControl, EM_SETSEL, WPARAM(0), LPARAM(-1) );
                        ::SendMessage( m_hWndInplaceControl, EM_REPLACESEL, WPARAM(TRUE), LPARAM(strStartEditText) );
                  }
            } // if( _tcslen( strClassName ) > 0 )
            if( ! bInplaceIsEditCommonControlOrRichEdit )
                  ::SetWindowText( m_hWndInplaceControl, strStartEditText );
      } // if( strStartEditText != NULL )

HWND hWndGrid = m_hWnd;
bool bStopFlag = false;
      for(  MSG msg;
                        m_hWndInplaceControl != NULL
                  &&    ::IsWindow( m_hWndInplaceControl )
                  &&    ::IsWindowVisible( m_hWndInplaceControl )
                  &&    ::IsWindow( hWndGrid )
                  &&    (!bStopFlag)
                  &&    (g_pEditCell != NULL)
                  ;
            )
      { // in-place editor message loop
            if( ! ::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) )
            {
                  if(         m_hWndInplaceControl == NULL
                        ||    ( ! ::IsWindow( m_hWndInplaceControl ) )
                        ||    ( ! ::IsWindow( hWndGrid ) )
                        ||    bStopFlag
                        ||    g_pEditCell == NULL
                        )
                        break;
                  LONG nIdleCounter = 0L;
                  for(  nIdleCounter = 0L;
                              g_pEditCell->OnInplaceControlIdle(
                                    m_hWndInplaceControl,
                                    *this,
                                    nIdleCounter
                                    );
                              nIdleCounter ++
                              )
                  {
                        ASSERT_VALID( g_pEditCell );
                  }
                  if( CExtGridWnd::g_bEnableOnIdleCalls )
                  {
                        for(  nIdleCounter = 0L;
                                    pThread->OnIdle(nIdleCounter);
                                    nIdleCounter ++
                                    );
                  }
                  ::WaitMessage();
                  continue;
            } // if( ! ::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) )

            switch( msg.message )
            {
            case WM_KILLFOCUS:
                  if( msg.hwnd == m_hWndInplaceControl )
                        bStopFlag = true;
            break;
            case WM_CANCELMODE:
            case WM_ACTIVATEAPP:
            case WM_SYSCOMMAND:
            case WM_SETTINGCHANGE:
            case WM_SYSCOLORCHANGE:
                  bStopFlag = true;
            break;
            case WM_COMMAND:
                  if(         (HIWORD(msg.wParam)) == 0
                        ||    (HIWORD(msg.wParam)) == 1
                        )
                        bStopFlag = true;
            break;
            case WM_CAPTURECHANGED:
                  if( (HWND)msg.wParam != m_hWndInplaceControl )
                        bStopFlag = true;
            break;

            case WM_LBUTTONUP:
            case WM_LBUTTONDOWN:
            case WM_LBUTTONDBLCLK:
            case WM_RBUTTONUP:
            case WM_RBUTTONDOWN:
            case WM_RBUTTONDBLCLK:
            case WM_MBUTTONUP:
            case WM_MBUTTONDOWN:
            case WM_MBUTTONDBLCLK:
            case WM_NCLBUTTONUP:
            case WM_NCLBUTTONDOWN:
            case WM_NCLBUTTONDBLCLK:
            case WM_NCRBUTTONUP:
            case WM_NCRBUTTONDOWN:
            case WM_NCRBUTTONDBLCLK:
            case WM_NCMBUTTONUP:
            case WM_NCMBUTTONDOWN:
            case WM_NCMBUTTONDBLCLK:
            case WM_CONTEXTMENU:
                  if(         msg.hwnd != m_hWndInplaceControl
                        &&    (!::IsChild( m_hWndInplaceControl, msg.hwnd ))
                        )
                        bStopFlag = true;
            break;
            default:
                  if(         ( ! bStopFlag )
                        &&    WM_KEYFIRST <= msg.message
                        &&    msg.message <= WM_KEYLAST
                        &&    (     msg.hwnd != m_hWndInplaceControl 
                              ||    (!::IsChild( m_hWndInplaceControl, msg.hwnd )) 
                              )
                        )
                  {
                        bool bAlt =
                              ( (::GetAsyncKeyState(VK_MENU)&0x8000) != 0 )
                                    ? true : false;
                        bool bCtrl =
                              ( (::GetAsyncKeyState(VK_CONTROL)&0x8000) != 0 )
                                    ? true : false;
                        bool bShift =
                              ( (::GetAsyncKeyState(VK_SHIFT)&0x8000) != 0 )
                                    ? true : false;
                        if( ! bAlt )
                        {
                              if(         bCtrl
                                    &&    (!bShift)
                                    &&    (     int(msg.wParam) == VK_INSERT
                                          ||    int(msg.wParam) == int( _T(’C’) )
                                          )
                                    )
                              {
                                    ::PeekMessage(&msg,NULL,msg.message,msg.message,PM_REMOVE);
                                    if( msg.message == WM_KEYDOWN )
                                          ::SendMessage( msg.hwnd, WM_COPY, 0, 0 );
                                    continue;
                              } 
                              if(         ( bCtrl && (!bShift) && int(msg.wParam) == int( _T(’V’) ) )
                                    ||    ( (!bCtrl) && bShift && int(msg.wParam) == VK_INSERT )
                                    )
                              {
                                    ::PeekMessage(&msg,NULL,msg.message,msg.message,PM_REMOVE);
                                    if( msg.message == WM_KEYDOWN )
                                          ::SendMessage( msg.hwnd, WM_PASTE, 0, 0 );
                                    continue;
                              } 
                              if(         ( bCtrl && (!bShift) && int(msg.wParam) == int( _T(’X’) ) )
                                    ||    ( (!bCtrl) && bShift && int(msg.wParam) == VK_DELETE )
                                    )
                              {
                                    ::PeekMessage(&msg,NULL,msg.message,msg.message,PM_REMOVE);
                                    if( msg.message == WM_KEYDOWN )
                                          ::SendMessage( msg.hwnd, WM_CUT, 0, 0 );
                                    continue;
                              } 
                              if(   bCtrl && (!bShift) && int(msg.wParam) == int( _T(’A’) ) ) 
                              {
                                    ::PeekMessage(&msg,NULL,msg.message,msg.message,PM_REMOVE);
                                    if( msg.message == WM_KEYDOWN )
                                          ::SendMessage( msg.hwnd, EM_SETSEL, 0, -1 );
                                    continue;
                              }
                              if(   (!bCtrl) && (!bShift) && int(msg.wParam) == VK_DELETE )
                              {
                                    ::PeekMessage(&msg,NULL,msg.message,msg.message,PM_REMOVE);
                                    if( msg.message == WM_KEYDOWN )
                                    {
                                          LPTSTR strEmpty = _T(""); 
                                          ::SendMessage( msg.hwnd, EM_REPLACESEL, 1, reinterpret_cast < LPARAM > ( strEmpty ) );
                                    }
                                    continue;
                              }
                        } // if( ! bAlt )
                        if(         ( (!bAlt) && bCtrl && (!bShift) && int(msg.wParam) == int( _T(’Z’) ) )
                              ||    ( bAlt && (!bCtrl) && (!bShift) && int(msg.wParam) == VK_BACK )
                              )
                        {
                              ::PeekMessage(&msg,NULL,msg.message,msg.message,PM_REMOVE);
                              if( msg.message == WM_KEYDOWN )
                                    ::SendMessage( msg.hwnd, WM_UNDO, 0, 0 );
                              continue;
                        } 
                  }
            break;
            } // switch( msg.message )

            if( bStopFlag )
                  break;
            if( ! pThread->PumpMessage() )
                  break;

      } // in-place editor message loop
      
      g_pEditCell = NULL;
      if( ! ::IsWindow( hWndGrid ) )
            return true;
      ASSERT( CWnd::FromHandlePermanent(hWndGrid) == this );
      ASSERT_VALID( this );
      m_nHelperLastEditedColNo = -1L;
      m_nHelperLastEditedRowNo = -1L;
      if( m_hWndInplaceControl != NULL )
      {
            if( ::IsWindow(m_hWndInplaceControl) )
            {
                  if( ::GetCapture() == m_hWndInplaceControl )
                        ::ReleaseCapture();
                  ::ShowWindow( m_hWndInplaceControl, SW_HIDE );
                  ::SetFocus( m_hWnd ); // after changing focus inplace control kill itself
                  // ::DestroyWindow( m_hWndInplaceControl );
            } // if( ::IsWindow(m_hWndInplaceControl) )
            m_hWndInplaceControl = NULL;
      } // if( m_hWndInplaceControl != NULL )
      return true;
}



Suhai Gyorgy Feb 23, 2007 - 4:23 AM

1. Pressing Delete key can do 2 things in a usual editbox:
a) When there is some text selected, it is removed (You handled this case in your last code)
b) When there is no text selected, but the caret (or cursor, or whats the name of it) is in the middle of the text, the first character on the right side of the caret is removed (This case is still not handled)

2. If you fix the problem in #1, my application in its current form will work without a mistake. But I can easily imagine a scene when an application has the Backspace (VK_BACK) key as an accelerator, which case is not handled in your code.

3. Although it is very not likely, but any other key not present in your code or in my above suggestion could happen to be an accelerator in an application (let’s say key "K" without modifiers). So the real bulletproof solution would be to somehow direct every single keystroke directly to the inplace editor without giving any chance for any other accelerator table for handling the message. I’m not that familiar with Windows API, I saw a method called OleTranslateAccelerator in a subject familiar to this one, but it could be totally useless here.

Thank you!
Chris

Technical Support Feb 23, 2007 - 5:36 AM

Here is the next step :-):

bool CExtGridWnd::OnGbwBeginEdit(
      LONG nVisibleColNo,
      LONG nVisibleRowNo,
      LONG nColNo,
      LONG nRowNo,
      INT nColType,
      INT nRowType,
      const RECT & rcCellExtra,
      const RECT & rcCell,
      const RECT & rcInplaceControl,
      bool bContinueMsgLoop, // = true
      __EXT_MFC_SAFE_LPCTSTR strStartEditText // = NULL
      )
{
      ASSERT_VALID( this );
      if(   CExtGridBaseWnd::OnGbwBeginEdit(
                  nVisibleColNo,
                  nVisibleRowNo,
                  nColNo,
                  nRowNo,
                  nColType,
                  nRowType,
                  rcCellExtra,
                  rcCell,
                  rcInplaceControl,
                  bContinueMsgLoop,
                  strStartEditText
                  )
            )
            return true;

      if(   CExtPopupMenuWnd::IsMenuTracking() )
            CExtPopupMenuWnd::CancelMenuTracking();
      CWnd::CancelToolTips();

DWORD dwBseStyle = BseGetStyle();
      if( nColType < 0 && (dwBseStyle&__EGWS_BSE_EDIT_CELLS_OUTER_L) == 0L )
            return false;
      else if( nColType > 0 && (dwBseStyle&__EGWS_BSE_EDIT_CELLS_OUTER_R) == 0L )
            return false;
      else if( nColType == 0 && (dwBseStyle&__EGWS_BSE_EDIT_CELLS_INNER) == 0L )
            return false;
      else if( nRowType < 0 && (dwBseStyle&__EGWS_BSE_EDIT_CELLS_OUTER_T) == 0L )
            return false;
      else if( nRowType > 0 && (dwBseStyle&__EGWS_BSE_EDIT_CELLS_OUTER_B) == 0L )
            return false;
      else if( nRowType == 0 && (dwBseStyle&__EGWS_BSE_EDIT_CELLS_INNER) == 0L )
            return false;

static CExtGridCell * g_pEditCell = NULL;
bool bDoMsgLoop = true;
      if( m_hWndInplaceControl != NULL )
      {
            if( ! bContinueMsgLoop )
                  return false;
            HWND hWndInplaceControl = m_hWndInplaceControl;
            m_hWndInplaceControl = NULL;
            if( hWndInplaceControl != NULL )
            {
                  bDoMsgLoop = false;
                  if( ::IsWindow(hWndInplaceControl) )
                        ::DestroyWindow( hWndInplaceControl );
            } // if( hWndInplaceControl != NULL )
      } // if( m_hWndInplaceControl != NULL )
CRect rcActivate( rcInplaceControl );
      if(         rcActivate.left >= rcActivate.right
            ||    rcActivate.top >= rcActivate.bottom
            )
      { // if invalid rect - recalc it
            if(   ! GridCellRectsGet(
                        nColNo,
                        nRowNo,
                        nColType,
                        nRowType,
                        NULL,
                        NULL,
                        NULL,
                        &rcActivate // pRectTextArea
                        )
                  )
            {
                  g_pEditCell = NULL;
                  return false;
            }
            if( rcActivate.IsRectEmpty() )
            {
                  g_pEditCell = NULL;
                  return false;
            }
      } // if invalid rect - recalc it
CExtGridCell * pCellToEdit =
            GridCellGet(
                  nColNo,
                  nRowNo,
                  nColType,
                  nRowType
                  );
      if( pCellToEdit == NULL )
            return false;
      ASSERT_VALID( pCellToEdit );
      ASSERT( pCellToEdit->IsKindOf(RUNTIME_CLASS(CExtGridCell)) );
      ASSERT_VALID( pCellToEdit->DataProviderGet() );
      g_pEditCell = pCellToEdit;
      m_hWndInplaceControl =
            g_pEditCell->OnInplaceControlCreate(
                  *this,
                  nVisibleColNo,
                  nVisibleRowNo,
                  nColNo,
                  nRowNo,
                  nColType,
                  nRowType,
                  rcCellExtra,
                  rcCell,
                  rcActivate,
                  m_nHelperLastEditedColNo,
                  m_nHelperLastEditedRowNo
                  );
      if(         m_hWndInplaceControl == NULL
            ||    ( ! ::IsWindow( m_hWndInplaceControl ) )
            )
      {
            m_hWndInplaceControl = NULL;
            g_pEditCell = NULL;
            DWORD dwCellStyle = pCellToEdit->GetStyle();
            if( (dwCellStyle&__EGCS_CHK_MASK) == 0 )
            {
                  if( (dwCellStyle&__EGCS_BUTTON_DROPDOWN) != 0 )
                  {
                        bool bEnabled = false;
                        if( pCellToEdit->OnQueryButtonInfo(
                                    INT(CExtGridCell::__EBTT_DROPDOWN),
                                    &bEnabled
                                    )
                              )
                        {
                              if( bEnabled )
                              {
                                    pCellToEdit->OnButtonPressed(
                                          *this,
                                          INT(CExtGridCell::__EBTT_DROPDOWN),
                                          rcCellExtra,
                                          rcCell,
                                          nVisibleColNo,
                                          nVisibleRowNo,
                                          nColNo,
                                          nRowNo,
                                          nColType,
                                          nRowType
                                          );
                                    return true;
                              } // if( bEnabled )
                        }
                  } // if( (dwCellStyle&__EGCS_BUTTON_DROPDOWN) != 0 )
            } // if( (dwCellStyle&__EGCS_CHK_MASK) == 0 )
            return false;
      }
      m_nHelperLastEditedColNo = nColNo;
      m_nHelperLastEditedRowNo = nRowNo;
      if( ! bDoMsgLoop )
            return true;

CWinThread * pThread = ::AfxGetThread();
      ASSERT_VALID( pThread );

      if( strStartEditText != NULL )
      {
            bool bInplaceIsEditCommonControlOrRichEdit = false;
            TCHAR strClassName[512];
            ::GetClassName( m_hWndInplaceControl, strClassName, 512 );
            if( _tcslen( strClassName ) > 0 )
            {
                  __EXT_MFC_STRLWR( strClassName, 512 );
                  if(         _tcsstr( strClassName, _T("edit") ) != NULL
                        ||    _tcsstr( strClassName, _T("riched") ) != NULL
                        )
                  {
                        bInplaceIsEditCommonControlOrRichEdit = true;
                        ::SendMessage( m_hWndInplaceControl, EM_SETSEL, WPARAM(0), LPARAM(-1) );
                        ::SendMessage( m_hWndInplaceControl, EM_REPLACESEL, WPARAM(TRUE), LPARAM(strStartEditText) );
                  }
            } // if( _tcslen( strClassName ) > 0 )
            if( ! bInplaceIsEditCommonControlOrRichEdit )
                  ::SetWindowText( m_hWndInplaceControl, strStartEditText );
      } // if( strStartEditText != NULL )

HWND hWndGrid = m_hWnd;
bool bStopFlag = false;
      for(  MSG msg;
                        m_hWndInplaceControl != NULL
                  &&    ::IsWindow( m_hWndInplaceControl )
                  &&    ::IsWindowVisible( m_hWndInplaceControl )
                  &&    ::IsWindow( hWndGrid )
                  &&    (!bStopFlag)
                  &&    (g_pEditCell != NULL)
                  ;
            )
      { // in-place editor message loop
            if( ! ::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) )
            {
                  if(         m_hWndInplaceControl == NULL
                        ||    ( ! ::IsWindow( m_hWndInplaceControl ) )
                        ||    ( ! ::IsWindow( hWndGrid ) )
                        ||    bStopFlag
                        ||    g_pEditCell == NULL
                        )
                        break;
                  LONG nIdleCounter = 0L;
                  for(  nIdleCounter = 0L;
                              g_pEditCell->OnInplaceControlIdle(
                                    m_hWndInplaceControl,
                                    *this,
                                    nIdleCounter
                                    );
                              nIdleCounter ++
                              )
                  {
                        ASSERT_VALID( g_pEditCell );
                  }
                  if( CExtGridWnd::g_bEnableOnIdleCalls )
                  {
                        for(  nIdleCounter = 0L;
                                    pThread->OnIdle(nIdleCounter);
                                    nIdleCounter ++
                                    );
                  }
                  ::WaitMessage();
                  continue;
            } // if( ! ::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) )

            switch( msg.message )
            {
            case WM_KILLFOCUS:
                  if( msg.hwnd == m_hWndInplaceControl )
                        bStopFlag = true;
            break;
            case WM_CANCELMODE:
            case WM_ACTIVATEAPP:
            case WM_SYSCOMMAND:
            case WM_SETTINGCHANGE:
            case WM_SYSCOLORCHANGE:
                  bStopFlag = true;
            break;
            case WM_COMMAND:
                  if(         (HIWORD(msg.wParam)) == 0
                        ||    (HIWORD(msg.wParam)) == 1
                        )
                        bStopFlag = true;
            break;
            case WM_CAPTURECHANGED:
                  if( (HWND)msg.wParam != m_hWndInplaceControl )
                        bStopFlag = true;
            break;

            case WM_LBUTTONUP:
            case WM_LBUTTONDOWN:
            case WM_LBUTTONDBLCLK:
            case WM_RBUTTONUP:
            case WM_RBUTTONDOWN:
            case WM_RBUTTONDBLCLK:
            case WM_MBUTTONUP:
            case WM_MBUTTONDOWN:
            case WM_MBUTTONDBLCLK:
            case WM_NCLBUTTONUP:
            case WM_NCLBUTTONDOWN:
            case WM_NCLBUTTONDBLCLK:
            case WM_NCRBUTTONUP:
            case WM_NCRBUTTONDOWN:
            case WM_NCRBUTTONDBLCLK:
            case WM_NCMBUTTONUP:
            case WM_NCMBUTTONDOWN:
            case WM_NCMBUTTONDBLCLK:
            case WM_CONTEXTMENU:
                  if(         msg.hwnd != m_hWndInplaceControl
                        &&    (!::IsChild( m_hWndInplaceControl, msg.hwnd ))
                        )
                        bStopFlag = true;
            break;
            default:
                  if(         ( ! bStopFlag )
                        &&    WM_KEYFIRST <= msg.message
                        &&    msg.message <= WM_KEYLAST
                        &&    (     msg.hwnd != m_hWndInplaceControl 
                              ||    (!::IsChild( m_hWndInplaceControl, msg.hwnd )) 
                              )
                        )
                  {
                        bool bAlt =
                              ( (::GetAsyncKeyState(VK_MENU)&0x8000) != 0 )
                                    ? true : false;
                        bool bCtrl =
                              ( (::GetAsyncKeyState(VK_CONTROL)&0x8000) != 0 )
                                    ? true : false;
                        bool bShift =
                              ( (::GetAsyncKeyState(VK_SHIFT)&0x8000) != 0 )
                                    ? true : false;
                        if( ! bAlt )
                        {
                              if(         bCtrl
                                    &&    (!bShift)
                                    &&    (     int(msg.wParam) == VK_INSERT
                                          ||    int(msg.wParam) == int( _T(’C’) )
                                          )
                                    )
                              {
                                    ::PeekMessage(&msg,NULL,msg.message,msg.message,PM_REMOVE);
                                    if( msg.message == WM_KEYDOWN )
                                          ::SendMessage( msg.hwnd, WM_COPY, 0, 0 );
                                    continue;
                              } 
                              if(         ( bCtrl && (!bShift) && int(msg.wParam) == int( _T(’V’) ) )
                                    ||    ( (!bCtrl) && bShift && int(msg.wParam) == VK_INSERT )
                                    )
                              {
                                    ::PeekMessage(&msg,NULL,msg.message,msg.message,PM_REMOVE);
                                    if( msg.message == WM_KEYDOWN )
                                          ::SendMessage( msg.hwnd, WM_PASTE, 0, 0 );
                                    continue;
                              } 
                              if(         ( bCtrl && (!bShift) && int(msg.wParam) == int( _T(’X’) ) )
                                    ||    ( (!bCtrl) && bShift && int(msg.wParam) == VK_DELETE )
                                    )
                              {
                                    ::PeekMessage(&msg,NULL,msg.message,msg.message,PM_REMOVE);
                                    if( msg.message == WM_KEYDOWN )
                                          ::SendMessage( msg.hwnd, WM_CUT, 0, 0 );
                                    continue;
                              } 
                              if(   bCtrl && (!bShift) && int(msg.wParam) == int( _T(’A’) ) ) 
                              {
                                    ::PeekMessage(&msg,NULL,msg.message,msg.message,PM_REMOVE);
                                    if( msg.message == WM_KEYDOWN )
                                          ::SendMessage( msg.hwnd, EM_SETSEL, 0, -1 );
                                    continue;
                              }
                              if(   (!bCtrl) && (!bShift) && int(msg.wParam) == VK_DELETE )
                              {
                                    ::PeekMessage(&msg,NULL,msg.message,msg.message,PM_REMOVE);
                                    if( msg.message == WM_KEYDOWN )
                                    {
                                          LPTSTR strEmpty = _T(""); 
                                          INT nSelStart = 0, nSelEnd = 0;
                                          ::SendMessage( msg.hwnd, EM_GETSEL, reinterpret_cast < WPARAM > ( &nSelStart ), reinterpret_cast < LPARAM > ( &nSelEnd ) );
                                          if( nSelStart == nSelEnd )
                                                ::SendMessage( msg.hwnd, EM_SETSEL, WPARAM( nSelStart ), LPARAM( nSelStart + 1 ) );
                                          ::SendMessage( msg.hwnd, EM_REPLACESEL, 1, reinterpret_cast < LPARAM > ( strEmpty ) );
                                    }
                                    continue;
                              }
                        } // if( ! bAlt )
                        if(         ( (!bAlt) && bCtrl && (!bShift) && int(msg.wParam) == int( _T(’Z’) ) )
                              ||    ( bAlt && (!bCtrl) && (!bShift) && int(msg.wParam) == VK_BACK )
                              )
                        {
                              ::PeekMessage(&msg,NULL,msg.message,msg.message,PM_REMOVE);
                              if( msg.message == WM_KEYDOWN )
                                    ::SendMessage( msg.hwnd, WM_UNDO, 0, 0 );
                              continue;
                        } 
                  }
            break;
            } // switch( msg.message )

            if( bStopFlag )
                  break;
            if( ! pThread->PumpMessage() )
                  break;

      } // in-place editor message loop
      
      g_pEditCell = NULL;
      if( ! ::IsWindow( hWndGrid ) )
            return true;
      ASSERT( CWnd::FromHandlePermanent(hWndGrid) == this );
      ASSERT_VALID( this );
      m_nHelperLastEditedColNo = -1L;
      m_nHelperLastEditedRowNo = -1L;
      if( m_hWndInplaceControl != NULL )
      {
            if( ::IsWindow(m_hWndInplaceControl) )
            {
                  if( ::GetCapture() == m_hWndInplaceControl )
                        ::ReleaseCapture();
                  ::ShowWindow( m_hWndInplaceControl, SW_HIDE );
                  ::SetFocus( m_hWnd ); // after changing focus inplace control kill itself
                  // ::DestroyWindow( m_hWndInplaceControl );
            } // if( ::IsWindow(m_hWndInplaceControl) )
            m_hWndInplaceControl = NULL;
      } // if( m_hWndInplaceControl != NULL )
      return true;
}

Suhai Gyorgy Feb 23, 2007 - 6:19 AM

I didn’t try it yet, but I see it will work now. Thank you very much!
Anything to add to my comment #2 and #3?

Technical Support Feb 23, 2007 - 10:08 AM

The items #2 and #3 should not be a problem. For instance, the key input control in the Keyboard page of the Customize dialog does not allow you to specify keys without modifiers and uses VK_BACK for clearing specified value. Both cases should be unreachable if your application uses CUA(common user access) style if UI.

Suhai Gyorgy Feb 23, 2007 - 1:59 PM

Personally I always go for editing the .rc file with text editor. But since my application is working now, I won’t go into further discussion about how bulletproof this solution is. Thank you for your help!

Technical Support Feb 14, 2007 - 11:41 AM

Thank you for reporting the problem. We will need a couple of days to look into it and suggest a solution.

Suhai Gyorgy Feb 19, 2007 - 2:15 AM

Along with an answer here on Forum, please send a note about it to me in e-mail, as well, once the solution is found. Thank you very much!