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
|
Nov 16, 2006 - 5:10 AM
|
Dear Support, I’m using CExtPropertyCtrl that I integrated into your FormEditor sample. One of my property stores have a property value that uses CExtGridCellFileImage cell. When I press the "..." button in the cell to open an icon file, and after that I return from the OpenFileDialog pressing OK, I get an assertion. Call stack (using ProfUIS v2.55): > FormEditor.exe!CSimpleException::GetErrorMessage(wchar_t * lpszError=0x01827ba8, unsigned int nMaxError=0, unsigned int * pnHelpContext=0x0012e874) Line 196 + 0x2a C++ FormEditor.exe!CExtGridCellFile::OnButtonPressed(CExtGridWnd & wndGrid={...}, int nButtonType=0, const tagRECT & rcCellExtra={...}, const tagRECT & rcCell={...}, long nVisibleColNo=1, long nVisibleRowNo=2, long nColNo=1, long nRowNo=2, int nColType=0, int nRowType=0) Line 30528 + 0x43 C++ Your OnButtonPressed method (partial): if( dlgFileDialog.DoModal() == IDOK )
{
TextSet( LPCTSTR(dlgFileDialog.GetPathName()) ); // <--- from here into GetErrorMessage
...
}
When I was debugging and stopped in your code just before the assertion, I saw that I get into this GetErrorMessage method right after returning from LPCTSTR() but before getting into TextSet. My main question: What could be the reason here to get into this GetErrorMessage method? Since my code grew to be quite big, I tried to put as little as neccesary into your original FormEditor sample to reproduce the bug, but (developer’s worst nightmare) that version worked flowlessly. I might try to strip down my code, but it’d be a big job, and you might know the solution to my problem without me having to go through that hassle (espacially that I’m afraid I end up with a working version again). Thank you, Chris
|
|
Technical Support
|
Nov 16, 2006 - 11:53 AM
|
We failed to reproduce the problem by adding the following code at the end of the CStarButton::GetPropertyStore() method in the PropertyGrid sample: CExtPropertyValue * pValFileImage = new CExtPropertyValue( _T("FileImage") );
pValFileImage->NameSet( _T("FileImage.") );
pValFileImage->DescriptionSet( _T("FileImage.") );
CExtGridCellFileImage * pCellFileImage =
STATIC_DOWNCAST(
CExtGridCellFileImage,
pValFileImage->ValueDefaultGetByRTC(
RUNTIME_CLASS( CExtGridCellFileImage )
)
);
pCellFileImage;
pValFileImage->ValueActiveFromDefault();
pCategoryMisc->ItemInsert(
pValFileImage
); If the problem occurs on one computer only, please try finding out what’s special with this computer. If the problem persists on more than one computer, would you send a test project to us?
|
|
Suhai Gyorgy
|
Nov 17, 2006 - 2:26 AM
|
The problem persists on another computer as well. Making a test-project that has the same problem might take me a while, though. In the meanwhile I would like to ask something different that may not to do anything with the above problem, but could solve another of my problems: As I mentioned above, I heavily modified your FormEditor sample for my own needs. But a struct named DOC_ITEM_DATA is still used, and I even added a CExtPropertyStore *m_pPS tag to it, as you suggested in your PropertyGrid-Walkthrough. Since my Document-based class has a CArray < DOC_ITEM_DATA, DOC_ITEM_DATA & > member and CArray needs an operator = for the DOC_ITEM_DATA, you wrote this operator = method already. Now I need to add the copying of this new m_pPS member to this method, as well. What’s the proper way to do this copying? //.h
struct AFX_NOVTABLE DOC_ITEM_DATA
{
DWORD m_dwItemID;
CRect m_rcItem;
CExtPropertyStore *m_pPS;
DOC_ITEM_DATA();
...
~DOC_ITEM_DATA();
DOC_ITEM_DATA & operator=( const DOC_ITEM_DATA & other );
...
}
// .cpp
CFormEditorDoc::DOC_ITEM_DATA::DOC_ITEM_DATA()
: m_dwItemID( ID_CONTROL_POINTER )
, m_rcItem( 0, 0, 0, 0 )
, m_pPS(NULL)
{
}
CFormEditorDoc::DOC_ITEM_DATA::~DOC_ITEM_DATA()
{
if( m_pPS != NULL ) {
// Is this the right code here?
CMainFrame *pFrame = reinterpret_cast<CMainFrame *>(AfxGetMainWnd());
ASSERT_VALID(pFrame);
if (pFrame->m_wndPropertyGrid.PropertyStoreGet() == m_pPS)
pFrame->m_wndPropertyGrid.PropertyStoreSet(NULL);
m_pPS->Delete();
}
}
CFormEditorDoc::DOC_ITEM_DATA & CFormEditorDoc::DOC_ITEM_DATA::operator = (
const CFormEditorDoc::DOC_ITEM_DATA & other
)
{
m_dwItemID = other.m_dwItemID;
m_rcItem = other.m_rcItem;
m_rcItem.NormalizeRect();
if (m_pPS != NULL) {
// What shall I put here?
}
return *this;
}
|
|
Technical Support
|
Nov 17, 2006 - 12:46 PM
|
We think the CFormEditorDoc::DOC_ITEM_DATA::operator=() method should look like: CFormEditorDoc::DOC_ITEM_DATA & CFormEditorDoc::DOC_ITEM_DATA::operator = (
const CFormEditorDoc::DOC_ITEM_DATA & other
)
{
m_dwItemID = other.m_dwItemID;
m_rcItem = other.m_rcItem;
m_rcItem.NormalizeRect();
bool bSetupOwnPropertyStore = false;
CMainFrame * pFrame = (CMainFrame*)( ::AfxGetMainWnd() );
ASSERT_VALID( pFrame );
if( m_pPS != NULL )
{
if( pFrame->m_wndPropertyGrid.PropertyStoreGet() == m_pPS )
{
pFrame->m_wndPropertyGrid.PropertyStoreSet( NULL );
bSetupOwnPropertyStore = true;
}
m_pPS->Delete();
m_pPS = NULL;
}
if( other.m_pPS != NULL )
{
m_pPS = new CExtPropertyStore;
CMemFile _file;
{ BLOCK BEGIN: saving
CArchive ar( &_file, CArchive::store );
other.m_pPS->Serialize( ar );
ar.Flush();
ar.Close();
} BLOCK END: saving
_file.Seek( 0, CFile::begin );
{ BLOCK BEGIN: loading
CArchive ar( &_file, CArchive::load );
m_pPS->Serialize( ar );
} BLOCK END: loading
if( bSetupOwnPropertyStore )
pFrame->m_wndPropertyGrid.PropertyStoreSet( m_pPS );
}
return *this;
} The better and faster solution should be not based on copied CExtPropertyStore objects. You can keep all the CExtPropertyStore objects somewhere outside DOC_ITEM_DATA objects. This would allow you to assign pointers only and not to reset the property store in the property grid control.
|
|
Suhai Gyorgy
|
Nov 20, 2006 - 4:36 AM
|
I don’t exactly understand what you mean by keeping all the CExtPropertyStore objects somewhere outside DOC_ITEM_DATA objects. The problem with assigning pointers only is this: (as walkthrough suggests) in the CExtPropertyValues of the CExtPropertyStore I keep a pointer to the DOC_ITEM_DATA object to which this propertyvalue is assigned to. If in the operator = method I only assign the pointer of the propertystore to the new DOC_ITEM_DATA object, the pointers inside the propertyValues won’t point to the right DOC_ITEM_DATA. Actually this is also problem with the operator = method you showed above.
|
|
Technical Support
|
Nov 20, 2006 - 1:05 PM
|
You have N controls on the form. You should use an array of N pointers to the CExtPropertyStore objects in the view class or in the document class. This will allow you to keep the pointers inside the document item classes in a simpler way and assign only pointer values without re-creating/cloning property stores and without refreshing the property grid control on assignment.
|
|
Suhai Gyorgy
|
Nov 22, 2006 - 4:38 AM
|
I could successfully strip down my code to present the original problem I mentioned in the first message of this thread (the one with the GetErrorMessage). I’m sending it to you by e-mail.
|
|