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.
Subject |
Author |
Date |
|
Suhai Gyorgy
|
Feb 16, 2007 - 1:23 PM
|
I noticed some drawing problem in the property grid. I could reproduce it in your PropertyGrid sample. I just added a new button on the main dialog and in its "clicked" message handler I wrote the following code: void CMainDlg::OnNewButtonClicked()
{
m_PGC.SetRedraw( FALSE );
CExtPropertyGridWnd *pActiveGrid = m_PGC.GetActiveGrid();
ASSERT_VALID(pActiveGrid);
CExtPropertyItem *pFocusedItem = pActiveGrid->PropertyItemFromTreeItem(pActiveGrid->ItemFocusGet());
m_PGC.PropertyStoreSynchronize();
if (pFocusedItem != NULL)
pActiveGrid->ItemFocusSet( pActiveGrid->PropertyItemToTreeItem( pFocusedItem ) );
m_PGC.SetRedraw( TRUE );
m_PGC.RedrawWindow( NULL, NULL, RDW_INVALIDATE|RDW_ERASE|RDW_ALLCHILDREN );
}
After running the sample, I start clicking the up or down button of any of the grid cells with up-down button, and then click on the new button of the dialog. The button last clicked in the grid turns to pressed state and the only way to remove this state is to click it again. If I don’t call PropertyStoreSynchronize(), the drawing problem doesn’t appear. Could you check this, please? Thank you!
|
|
Technical Support
|
Feb 17, 2007 - 1:19 PM
|
Thank you for reporting the bug. The problem occurred because grid cell assignment moved the __EGCS_PRESSED grid cell style from the source grid cell into the destination one. You can fix this problem by removing this style: void CExtPropertyItem::OnGridRowInitialized(
CExtPropertyGridWnd & wndPG,
HTREEITEM hTreeItem,
CExtGridCell * pCellCaption,
CExtGridCell * pCellValue
)
{
ASSERT_VALID( this );
ASSERT_VALID( (&wndPG) );
ASSERT( hTreeItem != NULL );
ASSERT_VALID( pCellCaption );
#ifdef _DEBUG
if( pCellValue != NULL )
{
ASSERT_VALID( pCellValue );
}
#endif
pCellCaption;
pCellValue;
if( wndPG.ItemIsExpanded( hTreeItem ) )
{
if( ! ExpandedGet() )
wndPG.ItemExpand( hTreeItem, TVE_COLLAPSE );
}
else
{
if( ExpandedGet() )
wndPG.ItemExpand( hTreeItem, TVE_EXPAND );
}
if( pCellValue != NULL )
{
pCellValue->ModifyStyle( 0, __EGCS_PRESSED ); // THIS LINE WAS ADDED
pCellValue->ModifyStyleEx( 0, __EGCS_EX_UNDEFINED_ROLE );
}
}
|
|
Hans Bergmeister
|
Feb 16, 2007 - 9:57 AM
|
Hello,
we want to achieve a themed look for the NC area of our CDialog based dialogs. We tried using CExtNCW<CDialog> and this seems to do what we need.
We have the following problems, however:
- Many dialog boxes are contained in DLLs. , that are delivered independently from the calling .EXE files. This means, that it may happen, that a DLL is called, that we delivered in - say - 2006, by a .EXE (with Prof-UIS support), that will be delivered in 2007. The dialog boxes in these DLLs should show the themed look, too, if possible.
- in total there are more than 50 of such DLLs with several hundred dialog boxes. It would mean a huge work for us, to change all references to CDialog to CExtNCW<CDialog> in the source code of all DLLs.
- we want to enable our customers, to change the theme on the fly at runtime. This would probably mean, that we have to implement some kind of notification scheme to notify our CExtNCW<CDialog> based dialog boxes sitting in the DLLs about such change. Note, that these dialog boxes are usually non-modal and will have to be able to change their look while being opened.
Now my question: is there a (relatively) simple approach to hook the NC-Painting of these dialog boxes by the .EXE file and to change the look of these dialog boxes by source code, that is only contained in the .EXE files?
Additional information: all our executables are statically linked against MFC. Our DLLs are thus no MFC extension DLLs. To enable the already delivered DLLs to run with our new (Prof-UIS enabled) version of the .EXE file we cannot change this for compatibility reasons.
Any suggestions?
|
|
Technical Support
|
Feb 18, 2007 - 1:39 PM
|
The CExtNCW < CDialog > windows would provide a skinned non-client area only (the client area will remain non-themed). So the only way to make your dialogs and controls on these dialogs theme-consistent, is to
1) use CExtNCW < CExtResizableDialog > windows 2) use the corresponding CExt*** classes for all the dialog controls
Of course, you will have to recompile you dlls. But please note that this is quite a task and even Microsoft cannot afford to make all the dialogs in Office applications theme-consistent and in most cases you will be able to find only default Windows dialogs in most cases. So you can make this step by step.
In the latest Prof-UIS versions, all paint managers in scope of one application can be easily synchronized. You can use this feature in your regular MFC DLLs and main application. In the main application, please invoke: CExtPmSynchronizeSink * pAppPaintManagerContainer = &g_PaintManager;
CExtPmSynchronizeSink * pSomeDllPaintManagerContainer1 = ...; // get it using exported API
//from some DLL which has its own g_PaintManager;
CExtPmSynchronizeSink * pSomeDllPaintManagerContainer2 = ...;
CExtPmSynchronizeSink * pSomeDllPaintManagerContainer3 = ...;
pAppPaintManagerContainer->PmSynchronizeSink_PerformSynchronizationWith( pSomeDllPaintManagerContainer1 );
pAppPaintManagerContainer->PmSynchronizeSink_PerformSynchronizationWith( pSomeDllPaintManagerContainer2 );
pAppPaintManagerContainer->PmSynchronizeSink_PerformSynchronizationWith( pSomeDllPaintManagerContainer3 ); This enables all paint managers to be synchronized when you call g_PaintManager.InstallPaintManager() . Please also note that using 50 copies of MFC and Prof-UIS in all your 50 DLLs is not effective. We would recommend to switch to the MFC extension DLL-based approach in all the cases like yours. And it is not difficult. The application objects should be removed from DLLs, the DLL entry method should be added and the AfxLoadLibrary() API should be used in the main application for loading MFC extension DLLs dynamically.
|
|
Hans Bergmeister
|
Feb 19, 2007 - 2:47 AM
|
Hello,
many thanks for the comprehensive response. This supports my concerns, that there is no solution, that covers also all already compiled and distributed DLLs.
> Please also note that using 50 copies of MFC and Prof-UIS in all your 50 DLLs is not effective. If hard disk space is the only issue, then this is no actual problem. Note, that always only a few DLLs are actually installed on an end user computer. No end user actually has the need to install all DLLs. We also do not have another choice, because many already distributed DLLs were compiled with MS VS 5 and 6, while our .EXE comes compiled with MS VS 2005. Changing the new version to MFC extension DLLs would make the old DLLs incompatible. The ability to provide such extrem range of compatibility is a good reason not to use extension DLLs.
Another question: if we link our DLLs statically against Prof-UIS just to include CExtNCW < CDialog > and the needed paint manager functions, how big is the overhead in terms of file size of these DLLs?
|
|
Technical Support
|
Feb 20, 2007 - 12:58 PM
|
You could avoid recompiling your old dlls using VS 2005. Why don’t you compile them using the same versions of VS with which they were initially produced? In this case, you could ask us about how you should Prof-UIS then? The answer would be to assign different names for the Prof-UIS dlls so the library for a particular version of Visual Studio can have its unique name. If such an approach is suitable for you, we can provide more details.
As for the second question, there is a FAQ How to reduce the size of the Prof-UIS dll that I use in my project? which describes how to exclude some features.
|
|
Hans Bergmeister
|
Feb 21, 2007 - 2:30 AM
|
Many thanks for your offer.
This proposal is a solution from a pure technical point of view, but due to the complexity and specific characteristics of our application not workable for our customers and our support team. We have very good reasons not to go with the dynamically linked version and we will not change this just for themed dialog boxes.
Perhaps I made myself not clear enough: I didn’t want to enter into a discussion, whether and how to link our DLLs dynamically or how to use CExtNCW in the source code of our DLLs.
We are searching for a solution or workaround to make the dialog boxes hosted within our DLLs look themed without (!) touching the source code of these DLLs (e.g. perhaps by hooking certain windows messages in the .EXE file). If there is no such hook we will have to abandon the use of Prof-UIS in that particular area of our applications.
|
|
Technical Support
|
Feb 22, 2007 - 12:00 PM
|
It is possible to code a subsystem which will hook any windows in your application and subclass them with the Prof-UIS controls which are in-fact should be the classes derived from CExt*** classes and implementing the PostNcDestroy() virtual method for deleting their instances when the subclassed window handles are destroyed. But we don’t think this is technically correct.
Alternatively it is possible to code a hook which will simply re-paint everything what can be re-painted. But this is enough large work and it does not change behavior of repainted windows. I.e. It does not implement such things as alpha blending animation in the Office 2007 themes and it does not display Prof-UIS context menus over controls such as edit box. This is why we think you can switch into more modern UI in your DLL modules step by step - not at once.
|
|
Hans Bergmeister
|
Feb 22, 2007 - 12:12 PM
|
Hello,
many thanks for this suggestion. For now it would be sufficient to just hook the functions related to NC-Painting of the dialog boxes. We just want to give the dialog boxes contained in our DLLs a "themed NC" look, i.e. mainly the title bar, the caption and the border of the dialog boxes shall be themed, nothing else. We decided already, that the contained controls shall remain "classic MFC" for the time being.
Is there a way to hook NC painting of these dialog box frames? And if so, how is this done? Could you draft an idea?
|
|
Technical Support
|
Feb 23, 2007 - 10:34 AM
|
You need to install a thread wide CBT hook procedure that should allow you to detect the creation event for each new window in the same thread. All the popup windows which are not subclassed yet can be subclassed with CExtNCW < CWnd > windows.
|
|
Hans Bergmeister
|
Feb 23, 2007 - 10:48 AM
|
Hello,
many thanks. We will try this out.
|
|
Vincent Lin
|
Feb 15, 2007 - 7:02 AM
|
Dear Sir,
I derived a class from CExtEdit , how to make it has tooltip function like CExtEdit ? Thanks.
|
|
Technical Support
|
Feb 15, 2007 - 1:54 PM
|
You can use the SetTooltipText() method for setting tooltip text.
|
|
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!
|
|
Christoffer Buchhorn
|
Feb 14, 2007 - 5:49 AM
|
Hi,
I would like to rezise the columns automatically so the grid window is filled completely. Your help states how to do it, but I can’t make it work. Furthermore you refer to the Report Grid sample. It does not use the proposed solution at all. Could you try to show how to do it in the ProfUIS_Controls sample?
I am using CExtGridWnd.
|
|
Suhai Gyorgy
|
Feb 14, 2007 - 7:12 AM
|
Here’s how it can be done with ProfUIS_Controls sample. I’m reducing the number of columns to 3 to make the change more obvious.
- Inside CPageGrid::OnInitDialog, look for the struct arrHeader. Right before declaration of this struct, add the lines: m_wndGrid.SiwScrollTypeHSet( __ESIW_ST_NONE, false );
m_wndGrid.BseModifyStyleEx( __EGBS_BSE_EX_PROPORTIONAL_COLUMN_WIDTHS, 0, false );
- The declaration of the struct is LPCTSTR sText; INT nWidth; DWORD dwStyle; , make it LPCTSTR sText; double nWidth; DWORD dwStyle; (changing INT to double). - Comment all items of the struct except for the first 3 (Boolean, CheckBox, RadioButton). - Change the widths from 85, 85, 85 to 0.5, 0.25, 0.25 . - Right after this struct there’s a loop to initialize all the headers on the top. Inside the loop there’s a call pCell->ExtentSet( arrHeader[nColNo].nWidth ); , change this to pCell->ExtentPercentSet( arrHeader[nColNo].nWidth ); . - Look for a series of calls _InitColumn.... Comment all except for the first 3. - Rebuild, run. You will see the 3 columns taking up all the width of the grid. Try resizing the window, columns are resizing accordingly. Actually the first step is enough to show the effect of style __EGBS_BSE_EX_PROPORTIONAL_COLUMN_WIDTHS, but all the columns would be very narrow.
|
|
Vincent Lin
|
Feb 14, 2007 - 2:34 AM
|
Why CExtSpinWnd don’t have SetPos32() member function? the spin positon will reset to zero while CExtEdit value is great than 0x7fff
|
|
Technical Support
|
Feb 14, 2007 - 11:16 AM
|
The CExtSpinWnd class is derived from CSpinButtonCtrl . So derives all the methods and functionality from the latter.
|
|
Vincent Lin
|
Feb 14, 2007 - 7:08 PM
|
what should i do while spin position is large than 0x7fff? I use GetPos() to get it’s position, and always got 0x10000 .
|
|
Technical Support
|
Feb 15, 2007 - 4:14 AM
|
MSDN says: For SetRange, neither limit can be greater than UD_MAXVAL nor less than UD_MINVAL; in addition, the difference between the two limits cannot exceed UD_MAXVAL. SetRange32 places no restrictions on the limits; use any integers.
So did you try the SetRange32 method? By the way, SetPos32 and GetPos32 are available in the CSpinButtonCtrl class. You can use them for setting and getting 32-bit values.
|
|
Vincent Lin
|
Feb 15, 2007 - 4:28 AM
|
I had use SetRange32() to my spin, and the compiler (VisualStudio 2005) says "SetPos32() is not a member of CSpinButtonCtrl", why ?
|
|
Technical Support
|
Feb 15, 2007 - 5:05 AM
|
Here is how these methods are declared in the source files: #if _WIN32_IE >= 0x0500
int GetPos32(LPBOOL lpbError = NULL) const;
int SetPos32(int nPos);
#endif As you can see you should declare the _WIN32_IE constant equal to 0x0500 somewhere in the StdAfx.h file or, which is better, in the project settings. But anyway you can directly send the UDM_GETPOS32 and UDM_SETPOS32 messages to the control using SendMessage . Please note these methods are available only starting from Internet Explorer 5.
|
|
Stan Miasnikov
|
Feb 13, 2007 - 6:12 PM
|
Hi,
I have a ribbon group that contains a button with the drop-down menu. When the Group is not collapsed it works fine and when I select a menu item the command is received by the parent window correctly. However, when this group is collapsed, I need to click on the collapsed group button, then open a menu and only then select the menu command. In this case the parent (main) window does not receive the WM_COMMAND message for the selected command. It seems that WM_COMMAND is being forwarded to a wrong parent window when the group is collapsed. It is reproducible with the RibbonPage sample. Fragment of my code that creates the group is below. I had this problem with 2.62 and still have it with 2.63.4.
Thanks,
CExtRibbonNode * CNoteRibbonMenu::InitRibbonNodeHome( bool bVisible ) { CString str, str1; CExtRibbonNodeGroup * pRibbonGroup =new CExtRibbonNodeGroup( ID_RIBBON_PAGE_HOME ); VERIFY( pRibbonGroup->m_iconBig.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE( ID_FILE_SAVE_BIG ) ) ); pRibbonGroup->m_iconBig.m_bmpNormal.Make32(); pRibbonGroup->m_iconBig.m_bmpNormal.AlphaColor( ALPHACLR1, ALPHACLR2, 0 ); VERIFY( pRibbonGroup->m_iconSmall.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE( ID_FILE_SAVE_SMALL ) ) ); pRibbonGroup->m_iconSmall.m_bmpNormal.Make32(); pRibbonGroup->m_iconSmall.m_bmpNormal.AlphaColor( ALPHACLR1, ALPHACLR2, 0 ); str.LoadString( IDS_RB_HOME ); pRibbonGroup->SetTextInToolbar( str );
pRibbonGroup->RibbonILE_SetCollapsed( __EXT_RIBBON_ILE_MAX-2 ); if ( !bVisible ) pRibbonGroup->ModifyFlags( __ECTN_TBB_HIDDEN );
// CExtRibbonNodeDialogLauncher * pRibbonDLB = new CExtRibbonNodeDialogLauncher( ID_RIBBON_PAGE_HOME ); // pRibbonGroup->InsertNode( NULL, pRibbonDLB );
str.LoadString( IDS_RB_SAVENOTE ); CExtRibbonNode * pNodeSave = new CExtRibbonNode( ID_FILE_SAVENOTE, 0, NULL, 0, str ); pNodeSave->RibbonILE_RuleArrayGet().RemoveAll(); VERIFY( pNodeSave->m_iconBig.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE( ID_FILE_SAVE_BIG) ) ); pNodeSave->m_iconBig.m_bmpNormal.Make32(); pNodeSave->m_iconBig.m_bmpNormal.AlphaColor( ALPHACLR1, ALPHACLR2, 0 ); pRibbonGroup->InsertNode( NULL, pNodeSave ); pNodeSave->ModifyFlags( __ECTN_TBB_SEPARATED_DROPDOWN ); str.LoadString( IDS_RB_SAVENOTE1 ); str1 = CString("&") + str; pNodeSave->InsertNode( NULL, new CExtCustomizeCmdTreeNode( ID_FILE_SAVENOTE, ID_FILE_SAVENOTE, NULL, 0, str, str1 ) ); // separator pNodeSave->InsertNode( NULL, new CExtCustomizeCmdTreeNode ); str.LoadString( IDS_RB_IMPORTNOTE ); pNodeSave->InsertNode( NULL, new CExtCustomizeCmdTreeNode( ID_FILE_IMPORT, ID_FILE_IMPORT, NULL, 0, str ) ); str.LoadString( IDS_RB_EXPORTNOTE ); pNodeSave->InsertNode( NULL, new CExtCustomizeCmdTreeNode( ID_FILE_EXPORT, ID_FILE_EXPORT, NULL, 0, str ) ); // separator pNodeSave->InsertNode( NULL, new CExtCustomizeCmdTreeNode ); /* str.LoadString( IDS_RB_CLOSENOTE ); str1 = CString("&") + str; pNodeSave->InsertNode( NULL, new CExtCustomizeCmdTreeNode( ID_CANCEL, ID_CANCEL, NULL, 0, str1 ) ); */ str.LoadString( IDS_RB_DELETENOTE ); pNodeSave->InsertNode( NULL, new CExtCustomizeCmdTreeNode( ID_FILE_DELETE, ID_FILE_DELETE, NULL, 0, str ) );
// separator // pRibbonGroup->InsertNode( NULL, new CExtRibbonNode );
str.LoadString( IDS_RB_PROTECTNOTE ); CExtRibbonNode * pNodeProtect = new CExtRibbonNode( ID_FILE_PROTECT, 0, NULL, 0, str ); // pNodeProtect->RibbonILE_RuleRemoveLargeILV(); VERIFY( pNodeProtect->m_iconBig.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE( ID_PROTECT_BIG ) ) ); pNodeProtect->m_iconBig.m_bmpNormal.Make32(); pNodeProtect->m_iconBig.m_bmpNormal.AlphaColor( ALPHACLR1, ALPHACLR2, 0 ); VERIFY( pNodeProtect->m_iconSmall.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE(ID_PROTECT_SMALL ) ) ); pNodeProtect->m_iconSmall.m_bmpNormal.Make32(); pNodeProtect->m_iconSmall.m_bmpNormal.AlphaColor( ALPHACLR1, ALPHACLR2, 0 ); pRibbonGroup->InsertNode( NULL, pNodeProtect );
str.LoadString( IDS_RB_SENDMAIL ); CExtRibbonNode * pNodeMail = new CExtRibbonNode( ID_FILE_MAIL, 0, NULL, 0, str ); // pNodeMail->RibbonILE_RuleRemoveLargeILV(); VERIFY( pNodeMail->m_iconBig.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE( ID_SENDMAIL_BIG ) ) ); pNodeMail->m_iconBig.m_bmpNormal.Make32(); pNodeMail->m_iconBig.m_bmpNormal.AlphaColor( ALPHACLR1, ALPHACLR2, 0 ); VERIFY( pNodeMail->m_iconSmall.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE(ID_SENDMAIL_SMALL ) ) ); pNodeMail->m_iconSmall.m_bmpNormal.Make32(); pNodeMail->m_iconSmall.m_bmpNormal.AlphaColor( ALPHACLR1, ALPHACLR2, 0 ); pRibbonGroup->InsertNode( NULL, pNodeMail );
return pRibbonGroup; }
|
|
Stan Miasnikov
|
Feb 19, 2007 - 1:19 PM
|
It is working now, however, there is another issue: if the goup contains a button with drop-down menus and is collapced, then, when closing a menu the application assers inside of the CWnd::AssertValid() method in the wincode.cpp (line 882). Basically it happens in CWnd::GetTopLevelParent() that is called in the standard PreTranslateMessage(MSG* pMsg) method for the main application window. I can ignore this ASSERT and it still works. I do not know if this problem was before I’ve implemented the changes you have suggested, but it is there now. If the group is not collapsed then this
|
|
Technical Support
|
Feb 22, 2007 - 3:41 AM
|
Thank you for reporting the assertion failure. We will fix it as soon as possible.
|
|
Technical Support
|
Feb 14, 2007 - 11:28 AM
|
Thank you for reporting the problem. To fix it, please update the following method in ../Prof-UIS/Src/ExtPopupMenuWnd.cpp : void CExtPopupMenuWnd::_EndSequence(
UINT nCmdID, // = 0
HWND hWndDeliver // = NULL
)
{
__PROF_UIS_MANAGE_STATE;
ASSERT_VALID( this );
HWND hWndOwn = GetSafeHwnd();
ASSERT( hWndOwn != NULL );
bool bCustomizeMode = _FindCustomizeMode();
if( (! _IsFadeOutAnimation() )
&& m_ctrlShadow.GetSafeHwnd() != NULL
)
m_ctrlShadow.DestroyWindow();
#ifdef _DEBUG
if( hWndDeliver != NULL )
{
ASSERT( ::IsWindow(hWndDeliver) );
}
#endif // _DEBUG
ASSERT( m_hWndCmdReceiver != NULL );
ASSERT( ::IsWindow(m_hWndCmdReceiver) );
CExtPopupMenuSite & _site = GetSite();
UINT * lpnResultCmdID = _site.GetTargetCmdIdPtr();
if( lpnResultCmdID != NULL )
*lpnResultCmdID = nCmdID;
DWORD dwTrackFlags = TrackFlagsGet();
CExtCmdItem * pCmdItem = NULL;
if( nCmdID > 0 && ((dwTrackFlags&TPMX_NO_WM_COMMAND)==0) )
{
pCmdItem =
g_CmdManager->CmdGetPtr(
g_CmdManager->ProfileNameFromWnd( m_hWndCmdReceiver ),
nCmdID
);
//ASSERT( pCmdItem != NULL );
} // if( nCmdID > 0 && ((dwTrackFlags&TPMX_NO_WM_COMMAND)==0) )
CExtPopupMenuWnd * pTopPopup = _site.GetInstance();
ASSERT_VALID( pTopPopup );
HWND hWndTopPopup = pTopPopup->GetSafeHwnd();
ASSERT(
hWndTopPopup != NULL
&& ::IsWindow( hWndTopPopup )
);
if( hWndDeliver == NULL )
hWndDeliver = m_hWndCmdReceiver;
CWnd * pTopLevelParent = GetTopLevelParent();
HWND hWndTopLevelParent = pTopLevelParent->GetSafeHwnd();
CRect rcBkUpdate( 0, 0, 0, 0 );
// hide all sequence
bool bFadeOut = _IsFadeOutAnimation();
if( ! bFadeOut )
{
CExtPopupMenuWnd * pPopup = this;
for( ; pPopup != NULL; pPopup = pPopup->m_pWndParentMenu )
{
ASSERT_VALID( pPopup );
ASSERT( pPopup->GetSafeHwnd() != NULL );
ASSERT( ::IsWindow( pPopup->GetSafeHwnd() ) );
CRect rcPopup;
pPopup->GetWindowRect( &rcPopup );
if( rcBkUpdate.IsRectEmpty() )
rcBkUpdate = rcPopup;
else
{
CRect rcPrev( rcBkUpdate );
rcBkUpdate.UnionRect( &rcPrev, &rcPopup );
}
CExtPopupMenuTipWnd & _tipWnd = pPopup->GetTip();
if( _tipWnd.GetSafeHwnd() != NULL
&& ::IsWindow( _tipWnd.GetSafeHwnd() )
&& _tipWnd.IsWindowVisible()
)
{
CRect rcToolTip;
_tipWnd.GetWindowRect( &rcToolTip );
CRect rcPrev( rcBkUpdate );
rcBkUpdate.UnionRect( &rcPrev, &rcToolTip );
}
pPopup->ShowWindow( SW_HIDE );
} // for( ; pPopup != NULL; pPopup = pPopup->m_pWndParentMenu )
if( ! g_PaintManager.m_bIsWin2000orLater )
CExtPaintManager::stat_PassPaintMessages();
// allow bottom windows repaint
if( !rcBkUpdate.IsRectEmpty()
&& hWndTopLevelParent != NULL
&& ::IsWindow(hWndTopLevelParent)
)
{
::ScreenToClient(
hWndTopLevelParent, (LPPOINT)&rcBkUpdate);
::ScreenToClient(
hWndTopLevelParent, ((LPPOINT)&rcBkUpdate)+1
);
}
} // if( ! bFadeOut )
if( m_hWndNotifyMenuClosed != NULL
&& ::IsWindow( m_hWndNotifyMenuClosed )
)
::SendMessage(
m_hWndNotifyMenuClosed,
g_nMsgNotifyMenuClosed,
WPARAM(nCmdID),
LPARAM( this )
);
// top popup (and all children) finally must be closed
if( ! bFadeOut )
{
if( ::IsWindow( hWndTopPopup ) )
::PostMessage( hWndTopPopup, WM_CLOSE, 0, 0 );
CExtToolControlBar::_CloseCustomMenusAll();
if( CExtToolControlBar::g_bMenuTracking )
CExtToolControlBar::_CloseTrackingMenus();
} // if( ! bFadeOut )
bool bOwnWindowExist = ::IsWindow( hWndOwn ) ? true : false;
if( ::IsWindow( hWndDeliver )
&& (! bCustomizeMode )
)
{
if( pCmdItem != NULL )
{
// if command target still exists -> deliver command to it
if( (dwTrackFlags&TPMX_NO_WM_COMMAND)==0 )
{
if( ! bFadeOut )
_site.DoneInstance();
VERIFY( pCmdItem->Deliver( hWndDeliver ) );
}
} // if( pCmdItem != NULL )
else
{
if( bOwnWindowExist
&& bFadeOut
&& m_nCurIndex >= 0
&& ItemGetInfo( m_nCurIndex ).IsPopup()
)
{
CExtPopupMenuWnd * pPopup = ItemGetInfo( m_nCurIndex ).GetPopup();
if( pPopup->GetSafeHwnd() != NULL )
{
INT nSaved = pPopup->m_nFadeOutAnimationStepCount;
if( nCmdID == 0 )
pPopup->m_nFadeOutAnimationStepCount = -1;
pPopup->_EndSequence( nCmdID, hWndDeliver );
pPopup->m_nFadeOutAnimationStepCount = nSaved;
return;
}
}
if( (dwTrackFlags&TPMX_NO_WM_COMMAND) == 0
&& nCmdID != 0
)
::PostMessage(
hWndDeliver,
WM_COMMAND,
WPARAM(nCmdID),
0L
);
} // else from if( pCmdItem != NULL )
g_SoundPlayer->PlaySound(
CExtSoundPlayer::__ON_MENU_CMD_CLICKED
);
} // if( pCmdItem != NULL && ...
if( ! bOwnWindowExist )
return;
if( bFadeOut )
DestroyWindow();
else
_site.DoneInstance();
}
|
|
Suhai Gyorgy
|
Feb 12, 2007 - 7:28 AM
|
Dear Support, I need to get notified when selection changes in PropertyGrid’s combobox. For this reason I made a class derived from CExtPropertyGridCtrl and gave it a messagemap like this: BEGIN_MESSAGE_MAP( CMyPropertyGridCtrl, CExtPropertyGridCtrl )
ON_CBN_SELENDOK(__EXT_MFC_ID_PROPERTY_GRID_COMBO_BOX, OnComboSelEndOK)
END_MESSAGE_MAP()
Message handler method is afx_msg void OnComboSelEndOK(); I can never step inside this method. What am I missing? Thank you.
|
|
Suhai Gyorgy
|
Feb 12, 2007 - 7:33 AM
|
Sorry, I should have looked inside code before asking. I found OnPgcStoreSelect virtual method, just what I need.
|
|
Technical Support
|
Feb 13, 2007 - 2:42 AM
|
Yes, the CExtPropertyGridComboBoxBar class has a reflection handler for the CBN_SELENDOK notification and that is why you do not receive this notification in the parent CExtPropertyGridCtrl . So you can handle the selection of a property store in the combo box by overriding the CExtPropertyGridCtrl::OnPgcStoreSelect() method.
|
|
Abdul Rahim
|
Feb 12, 2007 - 6:57 AM
|
Hi My application is based on the RibbonBarMDI sample. When the combo boxes font name or size (embedded in the home ribbon page ) is changed I need to be able to detect the selection change event in the MainFrm or ChilldFrm class. I have tried the conventional method like ON_CBN_SELCHANGE in the MainFrm but to no avail. Can you please show how i can do this. Also What is the best way to update these combo boxes from the Mainfrm or ChildFrm. Thank You
|
|
Technical Support
|
Feb 13, 2007 - 3:27 AM
|
The combo boxes in question are not based on the combo box common control . Such a combo box is a kind of combo field and you can work with it by overriding virtual methods of the CExtCustomizeSite class. Tha latter is the base class of CExtRibbonBar . There are the following methods you can override:
OnPopupListBoxGetStyles() allows you to add the LBS_SORT style to the popup list box in order to make the font names sorted.
OnPopupListBoxInitContent() allows you to initialize the list box with font names.
OnPopupListBoxItemDraw() , CExtCustomizeSite::OnPopupListBoxItemMeasure() allows you to draw font names and measure list box items.
OnPopupListBoxMeasureTrackSize() can be helpful if you need to measure the size of the entire list box before it appears on the screen.
OnTextFieldVerify() allows you to verify the edited text on-the-fly.
OnTextFieldInplaceTextGet() returns the text displayed in the combo box.
OnTextFieldInplaceTextSet() allows you to catch the following events: the user selected an item in the list and the user finished editing.
The built-in combo boxes are assumed as edit controls with the combo box like dropdown button displaying popup list box. The above methods are designed to provide content synchronization between multiple copies of the same combo box in customizable toolbars, menus and ribbon bar. The Font combo box in the ribbon bar can be both under the Home tab and in the Quick Access Toolbar. When in a toolbar , the font combo box can be copied by the user into several copies in different toolbars and menus using the combo box drag-n-drop with the ALT key hold pressed. In both cases, the built-in combo boxes are fully controlled by the CExtCustomizeSite class. The described above methods are implemented in the CMyRibbonBar class of the RibbonBar and RibbonBarMDI sample applications and in the CMainFrame class of the StyleEditor sample.
|
|
Massimo Germi
|
Feb 10, 2007 - 1:31 AM
|
Dear support, in some case I need to prevent cell modification in a CExtPropertyGridCtrl derived class.
Tx a lot
|
|
Suhai Gyorgy
|
Feb 10, 2007 - 10:22 AM
|
If you have cells which can be changed with buttonclick as well (like combo cell, for example), you will also have to override OnGbwAnalyzeCellMouseClickEvent method and do the same in it: return false if editing is disabled and invoke the parent class method otherwise.
|
|
Technical Support
|
Feb 10, 2007 - 10:14 AM
|
The CExtPropertyGridCtrl control is container for one or more tree grid windows displaying properties. By default, there are two tree grids: CExtPropertyGridWndCategorized and CExtPropertyGridWndSorted. You can override the CExtPropertyGridCtrl::OnPgcCreateGrids() method and create custom versions of these grids in it. In your CExtPropertyGridWndCategorized -derived and CExtPropertyGridWndSorted -derived classes, you should implement the CExtGridBaseWnd::OnGbwBeginEdit() virtual method that returns false if editing is disabled and invokes the parent class method otherwise.
|
|
Jia Hong Li
|
Feb 10, 2007 - 12:29 AM
|
Hi, I am trying to combine my project with ProUIS GUI, and get 1 error, as following:
error LNK2019: unresolved external symbol "class CDlgFileOper dlgFileOper" (?dlgFileOper@@3VCDlgFileOper@@A) referenced in function "public: void __thiscall ABPlusV::OnBrowseCopyFileTo(void)" (?OnBrowseCopyFileTo@ABPlusV@@QAEXXZ)
How could I resolve it ?
PS: my vs environment: Use MFC in a shared DLL Not using ATL Use Unicode Character Set
|
|
Suhai Gyorgy
|
Feb 10, 2007 - 6:03 AM
|
|
|
Ed Kennedy
|
Feb 9, 2007 - 8:12 PM
|
Would you have any simple demo’s using the CExtToolBoxWnd?
Thanks
|
|
Suhai Gyorgy
|
Feb 10, 2007 - 4:47 AM
|
Check out FormEditor sample.
|
|
Massimo Germi
|
Feb 9, 2007 - 12:59 PM
|
Hi, is there a printing framework for CExtPropertyGrid?
tx a lot
|
|
Technical Support
|
Feb 10, 2007 - 10:10 AM
|
There is no printing support for the CExtPropertyGridCtrl window at the moment. But we can easily add such support because CExtPropertyGridCtrl is a container for property view windows based on CExtTreeGridWnd . The latter supports the printing and print preview. Please let us know where we should put the print and print preview commands in the property grid control? Inside the toolbar at the right of the categorized and sorted buttons? Somewhere else?
|
|
Massimo Germi
|
Feb 11, 2007 - 2:22 PM
|
Inside the toolbar is the best place for me.
Tx again
|
|
Technical Support
|
Feb 13, 2007 - 1:12 PM
|
We can provide you with the ready-to-use printing and print preview extension for the property grid control approximately in one week.
|
|
Offer Har
|
Feb 8, 2007 - 11:04 AM
|
Dear Support,
1) I am placing two controls, a combo-box and an edit-box, both derived from Prof-UI classes. 2) I set the height of the two controls to 12 in the resource editor.
When the application is running i see that the height of the editable area (white) of the edit-box is 18 pixel, and the combo-box is 17. Why is this? can this issue be resolved?
Thanks, Ron.
|
|
Technical Support
|
Feb 11, 2007 - 1:25 PM
|
The smaller size of the combo box at run time is caused by the behavior of the combo box common control. We would recommend to align the edit manually according to the height of the neighbouring combo box.
|
|
Brian Horn
|
Feb 7, 2007 - 10:35 PM
|
How to assign short cut keys to ribbonbar buttons?
|
|
Technical Support
|
Feb 8, 2007 - 8:49 AM
|
There are customizable keyboard accelerators only that are available in the ribbon bar/ribbon page controls at the moment. The key tips are under development ans will be available very soon.
The keyboard accelerator support is provided by the CExtCustomizeSite class which is the base class for both CExtRibbonBar and CExtRibbonPage classes. The accelerator table is stored as a property of the menu line information object in the customize site. You can access The ribbon controls are using only one default menu information object which you should access for loading the accelerator table. VERIFY(
m_wndRibbonBar.
MenuInfoGetDefault()->
AccelTableLoad( IDR_MAINFRAME )
);
|
|
Andrew Banks
|
Feb 16, 2007 - 11:58 AM
|
I have done this and it doesn’t work.
I use ID_QA_FILE_SAVE for the quick access save button.
I associate ID_QA_FILE_SAVE with controls s in the accelator which is loaded as VERIFY( m_wndRibbonBar. MenuInfoGetDefault()-> AccelTableLoad( IDR_MAINFRAME ) );
Control s does not send ID_QA_FILE_SAVE to the message queue.
|
|
Technical Support
|
Feb 17, 2007 - 1:25 PM
|
We guess the empty accelerators were loaded from the system registry. Please reset the keyboard accelerators from the Options dialog or delete the application’s state data in the system registry.
|
|
Brian Horn
|
Feb 7, 2007 - 10:32 PM
|
In Ribbonbar application I have loaded all recent files list in Application button of ribbonbar. But can you tell me how to write the code to open these recent files again. ( How to handle events to open these recent files list. Is there any virtual method that we need to override? )
|
|
Andrew Banks
|
Feb 16, 2007 - 12:22 PM
|
I dont know if you care but this works.
void CMyRibbonBar::OnRibbonGalleryItemSelEndOK( CExtRibbonGalleryWnd & wndRG, CExtRibbonGalleryPopupMenuWnd * pGalleryPopup, CExtRibbonButtonGallery * pRibbonGalleryTBB, CExtToolBoxWnd::TOOLBOX_ITEM_DATA * pTBCI ) { pGalleryPopup->DestroyWindow() ; theApp.OpenDocumentFile( LPCSTR(pTBCI->TextGet()) ); }
theApp is variable made by mfc in your ProgApp class.
|
|
Technical Support
|
Feb 17, 2007 - 1:24 PM
|
|
|
Technical Support
|
Feb 8, 2007 - 8:45 AM
|
The Application button is a modified version of the ribbon gallery button. The recent file list is a styled version of the ribbon gallery control. You should override the CExtRibbonPage::OnRibbonGalleryItemSelEndOK() virtual method to handle click/selection events on the gallery control.
If you are using the MFC’s document/view architecture, you should get the registered in application document template object and invoke its CDocTemplate::OpenDocumentFile() method to open a new document from a file.
|
|
Brian Horn
|
Feb 7, 2007 - 10:31 PM
|
I want to write code on click event of button that will destroy ribbonbar and invalidate the screen so that ribbonbar will not appear on the screen. Can you tell me how to do this?
I tried writing code on button created on ribbonbar. When I click on that button it’s destroying ribbonbar but still its appearing on the screen. I think its not invalidating the screen. If I minimize the screen and again opens the same then it’s showing the screen without ribbonbar.
Can you tell me how to invalidate screen so that destroy and hiding of ribbonbar change will appear immediately on the screen.
|
|
Technical Support
|
Feb 8, 2007 - 8:40 AM
|
You can call the CFrameWnd::RecalcLayout() method to update any pending layout changes relating to any kind of control bar inside the frame. Would you modify the RibbonBar sample in order to reproduce the problem and send it to us?
|
|
Offer Har
|
Feb 7, 2007 - 12:08 PM
|
Dear Support,
I saw this version on the FTP site - what goodies does it contain?
Thanks, Ron.
|
|
Szabo Zoltan
|
Feb 20, 2007 - 8:54 AM
|
Dear support,
May I have your FTP link to download the new version ?
Thanks
|
|
Technical Support
|
Feb 21, 2007 - 3:02 AM
|
We are going to announce a new release today. So you will be able to download the new version today (directly from this website).
|
|
Technical Support
|
Feb 8, 2007 - 3:24 AM
|
Fixed MDI crashes in some cases.
Fixed an incorrect size of the tab control inside the tabbed control bar container in the following cases: when the container is floating and when a skinned paint manager is applied.
Added support for multiple header rows/columns in CExtTreeGridWnd class.
Improved drag-and-drop in CExtTreeGridWnd (you can download a test project).
Changed the way the printing and print preview subsystem renders 32-bit bitmap surfaces to prevent crashes when some printer drivers are used. The bug was found when using HP 1022.
Changed the ribbon bar’s code to avoid certain unwanted assertions in debug mode.
|
|
Simon DESEE
|
Feb 13, 2007 - 1:43 AM
|
Dear support,
Can I have your FTP link to download this new version or can you say when you plan to finish this version ?
When I try to use the new printing functionnality, my application stops during 10 seconds. I’ve a network printer, but this printer isn’t always on the network. Is this normal ?
Thanks
|
|
Technical Support
|
Feb 13, 2007 - 12:47 PM
|
We plan to release a new version later this week or early next week. You can download the latest code from our ftp site (we emailed you how to download it).
The speed of printing and print preview depends both from the driver implementation for a particular printer and your network configuration/structure/hardware. The 10 second delay is a bit longer than expected. Please try installing the driver for the same printer type on your computer locally and provide us with the time delay information when generating the print preview data for the print preview window.
|
|
Suhai Gyorgy
|
Feb 7, 2007 - 7:30 AM
|
I need to get hold of the PropertyValue which corresponds to a cell inside CExtPropertyGrid. I’d need it from inside an OnButtonPressed overriden method. I made this code and I also tested it some, but I’d like to know if it is a safe code. void CMyCellInPropGrid::OnButtonPressed(
CExtGridWnd & wndGrid,
INT nButtonType,
const RECT & rcCellExtra,
const RECT & rcCell,
LONG nVisibleColNo,
LONG nVisibleRowNo,
LONG nColNo,
LONG nRowNo,
INT nColType,
INT nRowType
)
{
CExtGridCellString::OnButtonPressed(...);
if ( nButtonType == __EBTT_ELLIPSIS ) {
CExtPropertyGridWnd *pPropGrid = reinterpret_cast<CExtPropertyGridWnd *>(&wndGrid);
HTREEITEM hItem = pPropGrid->ItemGetByVisibleRowIndex(nRowNo);
CMyPropValue *pValue = (CMyPropValue *)pPropGrid->PropertyItemFromTreeItem(hItem);
// here would come other code using pValue
}
}
Of course I only use CMyCellInPropGrid from inside CMyPropValue’s constructor: CMyCellInPropGrid *pCell = STATIC_DOWNCAST( CMyCellInPropGrid , ValueDefaultGetByRTC( RUNTIME_CLASS( CMyCellInPropGrid ) ) ); Thank you, Chris.
|
|
Technical Support
|
Feb 7, 2007 - 8:47 AM
|
The source code is absolutely correct. All the method invocations will always return the correct result (i.e. you should never get NULL pointers nor NULL values of HTREEITEM handles).
|
|
Wes Aday
|
Feb 6, 2007 - 2:53 PM
|
Can the caption area of the tab control have multilines, or make the text word wrap?
Thanks
|
|
Technical Support
|
Feb 7, 2007 - 8:59 AM
|
Unfortunately only single line text is supported in tabs now. We can only regard your question as a feature request.
|
|