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 |
|
Krustys Donuts
|
Jul 11, 2005 - 12:10 PM
|
Hi, I’m trying to play with CExtPropertyGridCtrl, and am currently trying to populate the comboboxbar with property stores. If I don’t insert any property values into the property category, everything is fine (but of course nothing appears in the property grid). If I then add values with the following code, my application crashes:
CExtPropertyGridComboBoxBar * pCombo = STATIC_DOWNCAST( CExtPropertyGridComboBoxBar,
grid.GetChildByRTC( RUNTIME_CLASS(CExtPropertyGridComboBoxBar)) );
ASSERT_VALID( pCombo );
// stores[] is of type CExtPropertyStore
for( int i=0; i<NumSides; i++) {
stores[i].NameSet( sideNames[i]);
CExtPropertyCategory * pCategoryField = new CExtPropertyCategory( _T("Field") );
pCategoryField->DescriptionSet( _T("Field properties") );
VERIFY( stores[i].ItemInsert( pCategoryField) );
pCategoryField->ItemInsert( new CExtPropertyValue( "foo"));
pCategoryField->ItemInsert( new CExtPropertyValue( "bar"));
pCombo->PropertyStoreInsert( &stores[i]);
}
I pulled this code from the propertygridctrl example, except for a change to these lines:
pCategoryField->ItemInsert( new CExtPropertyValue( "foo"));
pCategoryField->ItemInsert( new CExtPropertyValue( "bar"));
These lines are basically the same as the example, except that I’m just using passing in the base class. When my application crashes, the call stack looks like this:
msvcr71d.dll!__crtMessageBoxA(const char * lpText=0x0012a88c, const char * lpCaption=0x00388444, unsigned int uType=73746) Line 119 C
msvcr71d.dll!CrtMessageWindow(int nRptType=2, const char * szFile=0x1073f214, const char * szLine=0x0012b8d0, const char * szModule=0x00000000, const char * szUserMessage=0x0012b8f0) Line 617 + 0x16 C
msvcr71d.dll!_CrtDbgReport(int nRptType=2, const char * szFile=0x1073f214, int nLine=1561, const char * szModule=0x00000000, const char * szFormat=0x00000000, ...) Line 516 + 0x4c C
mfc71d.dll!AfxAssertFailedLine(const char * lpszFileName=0x1073f214, int nLine=1561) Line 28 + 0x14 C++
mfc71d.dll!AfxAssertValidObject(const CObject * pOb=0x00000000, const char * lpszFileName=0x1073f214, int nLine=1561) Line 74 + 0xd C++
ProfUIS240md.dll!CExtPropertyGridCellArea::OnQueryCellFont(const CExtGridWnd & wndGrid={...}, long nVisibleColNo=0, long nVisibleRowNo=1, long nColNo=0, long nRowNo=1, int nColType=0, int nRowType=0, unsigned long dwAreaFlags=512) Line 1563 C++
ProfUIS240md.dll!CExtGridCell::OnPaintText(const tagRECT & rcCellText={...}, const CExtGridWnd & wndGrid={...}, CDC & dc={...}, long nVisibleColNo=0, long nVisibleRowNo=1, long nColNo=0, long nRowNo=1, int nColType=0, int nRowType=0, const tagRECT & rcCellExtra={...}, const tagRECT & rcCell={...}, const tagRECT & rcVisibleRange={...}, unsigned long dwAreaFlags=512, unsigned long dwHelperPaintFlags=0) Line 14666 + 0x2d C++
ProfUIS240md.dll!CExtGridCell::OnPaintForeground(const CExtGridWnd & wndGrid={...}, CDC & dc={...}, long nVisibleColNo=0, long nVisibleRowNo=1, long nColNo=0, long nRowNo=1, int nColType=0, int nRowType=0, const tagRECT & rcCellExtra={...}, const tagRECT & rcCell={...}, const tagRECT & rcVisibleRange={...}, unsigned long dwAreaFlags=512, unsigned long dwHelperPaintFlags=0) Line 14061 + 0x45 C++
ProfUIS240md.dll!CExtGridWnd::OnGbwPaintCell(CDC & dc={...}, long nVisibleColNo=0, long nVisibleRowNo=1, long nColNo=0, long nRowNo=1, const tagRECT & rcCellExtra={...}, const tagRECT & rcCell={...}, const tagRECT & rcVisibleRange={...}, unsigned long dwAreaFlags=512, unsigned long dwHelperPaintFlags=0) Line 30971 + 0x41 C++
ProfUIS240md.dll!CExtTreeGridWnd::OnGbwPaintCell(CDC & dc={...}, long nVisibleColNo=0, long nVisibleRowNo=1, long nColNo=0, long nRowNo=1, const tagRECT & rcCellExtra={...}, const tagRECT & rcCell={...}, const tagRECT & rcVisibleRange={...}, unsigned long dwAreaFlags=512, unsigned long dwHelperPaintFlags=0) Line 2287 C++
ProfUIS240md.dll!CExtGridBaseWnd::OnSiwWalkCell(CDC & dc={...}, void * pQueryData=0x00000000, long nVisibleColNo=0, long nVisibleRowNo=1, long nColNo=0, long nRowNo=1, const tagRECT & rcCellExtra={...}, const tagRECT & rcCell={...}, const tagRECT & rcVisibleRange={...}, bool & bVirtualRightReached=false, bool & bVirtualBottomReached=false, unsigned long dwAreaFlags=512, bool bFocusedControl=false) Line 4033 + 0x38 C++
ProfUIS240md.dll!CExtGridBaseWnd::OnSiwWalkItemsH(CDC & dc={...}, void * pQueryData=0x00000000, const tagRECT & rcRowExtra={...}, const tagRECT & rcRow={...}, long nVisibleRowNo=1, long nRowNo=1, const tagRECT & rcVisibleRange={...}, bool & bVirtualBottomReached=false, unsigned long dwAreaFlags=512, bool bFocusedControl=false) Line 4179 + 0x4a C++
ProfUIS240md.dll!CExtGridBaseWnd::OnGbwWalkVisibleAreas(CDC & dc={...}, bool bFocusedControl=false, CExtGridHitTestInfo * pHT=0x00000000) Line 2837 + 0x48 C++
ProfUIS240md.dll!CExtGridBaseWnd::OnSiwPaintForeground(CDC & dc={...}, bool bFocusedControl=false) Line 1979 + 0x1a C++
ProfUIS240md.dll!CExtScrollItemWnd::OnSwPaint(CDC & dc={...}) Line 3458 + 0x18 C++
ProfUIS240md.dll!CExtScrollWnd::OnPaint() Line 1754 + 0x17 C++
mfc71d.dll!CWnd::OnWndMsg(unsigned int message=15, unsigned int wParam=0, long lParam=0, long * pResult=0x0012f80c) Line 2023 C++
mfc71d.dll!CWnd::WindowProc(unsigned int message=15, unsigned int wParam=0, long lParam=0) Line 1745 + 0x1e C++
ProfUIS240md.dll!CExtGridBaseWnd::WindowProc(unsigned int message=15, unsigned int wParam=0, long lParam=0) Line 10150 C++
mfc71d.dll!AfxCallWndProc(CWnd * pWnd=0x003bbfe0, HWND__ * hWnd=0x00190692, unsigned int nMsg=15, unsigned int wParam=0, long lParam=0) Line 241 + 0x1a C++
mfc71d.dll!AfxWndProc(HWND__ * hWnd=0x00190692, unsigned int nMsg=15, unsigned int wParam=0, long lParam=0) Line 389 C++
mfc71d.dll!AfxWndProcBase(HWND__ * hWnd=0x00190692, unsigned int nMsg=15, unsigned int wParam=0, long lParam=0) Line 209 + 0x15 C++
user32.dll!_InternalCallWinProc@20() + 0x28
user32.dll!_UserCallWinProcCheckWow@32() + 0xb7
user32.dll!_DispatchClientMessage@20() + 0x4d
user32.dll!___fnDWORD@4() + 0x24
ntdll.dll!_KiUserCallbackDispatcher@12() + 0x13
user32.dll!_NtUserCallHwndLock@8() + 0xc
user32.dll!_InternalCreateDialog@28() + 0x130d
user32.dll!_CreateDialogIndirectParamAorW@24() + 0x33
user32.dll!_CreateDialogIndirectParamA@20() + 0x1b
mfc71d.dll!CWnd::CreateDlgIndirect(const DLGTEMPLATE * lpDialogTemplate=0x00439ab0, CWnd * pParentWnd=0x00000000, HINSTANCE__ * hInst=0x00400000) Line 310 + 0x2a C++
mfc71d.dll!CDialog::DoModal() Line 519 + 0x20 C++
Thanks!
|
|
Technical Support
|
Jul 11, 2005 - 12:45 PM
|
Your code instantiates two property values as child items inside a category. Each property value stores two CExtGridCell objects which assumed to be the default and active values of the property. You simply forgot to initialize the CExtGridCell objects and attach them to each CExtPropertyValue instance. It is not difficult to improve your code. Please replacepCategoryField->ItemInsert(new CExtPropertyValue( "foo")); withCExtPropertyValue * pValue =
new CExtPropertyValue( "foo")
CExtGridCellComboBox * pGridCell =
STATIC_DOWNCAST(
CExtGridCellComboBox,
pValue->ValueActiveGetByRTC(
RUNTIME_CLASS(CExtGridCellComboBox)
)
);
ASSERT_VALID( pGridCell );
pGridCell->InsertString( _T("None"), 0 );
pGridCell->InsertString( _T("Slow"), 1 );
pGridCell->InsertString( _T("Middle"), 2 );
pGridCell->InsertString( _T("Fast"), 3 );
pGridCell->SetEnumMode();
// pGridCell->SetCurSel( ... );
pValue->ValueDefaultFromActive();
pCategoryField->ItemInsert( pValue ); Of course, you should do the same for the second property value in your code.
|
|
Krustys Donuts
|
Jul 11, 2005 - 3:40 PM
|
Fantastic! That solved everything, thank you.
|
|
Krustys Donuts
|
Jul 12, 2005 - 12:34 AM
|
Ok, so it worked, but not the way I wanted it to. I need my UI to update based on the item selected from the combobox. To try to fix this, I subclassed CExtGridCellComboBox and overrode OnInplaceControlTextInputComplete, but it never got called. I then looked at the grid sample, and saw that the combobox needs to be contained by a CExtPropertyValue. I proceeded to change my previous combobox class to look like this:
class CLabelPropertySource : public CExtPropertyValue
{
DECLARE_DYNCREATE(CLabelPropertySource)
public:
CLabelPropertySource();
virtual ~CLabelPropertySource();
virtual void Apply( CExtGridCell* pValue);
};
and the implementation looks like this:
IMPLEMENT_DYNCREATE( CLabelPropertySource, CExtPropertyValue)
CLabelPropertySource::CLabelPropertySource()
: CExtPropertyValue( "Source")
{
DescriptionSet( "Specifies source" );
CExtGridCellComboBox* pValue = STATIC_DOWNCAST( CExtGridCellComboBox, ValueGetByRTC( RUNTIME_CLASS(CExtGridCellComboBox)));
ASSERT_VALID( pValue );
pValue->InsertString( "Source A", 0);
pValue->InsertString( "Source B", 1);
pValue->InsertString( "Source C", 2);
pValue->InsertString( "Source D", 3);
pValue->SetEnumMode();
}
CLabelPropertySource::~CLabelPropertySource()
{
}
void CLabelPropertySource::Apply( CExtGridCell* pValue)
{
ASSERT_VALID( this );
ASSERT_VALID( pValue );
ASSERT_KINDOF( CExtGridCellComboBox, pValue );
CExtPropertyValue::Apply( pValue );
CExtGridCellComboBox * pValueComboBox = STATIC_DOWNCAST( CExtGridCellComboBox, pValue);
}
The code is pretty much copied straight from the sample. The problem is the ValueGetByRTC macro (is it a macro?). The sample compiles with this line, but my code doesn’t. I checked the docs, and I can only see ValueDefaultGetByRTC in the base class (CExtPropertyItem), but that crashes when I run.
Thanks for any help you can provide me!
|
|
Krustys Donuts
|
Jul 12, 2005 - 10:39 AM
|
Hi, sorry, I was looking at an old sample from 2.33... I was supposed to use ValueActiveGetByRTC.
|
|
Technical Support
|
Jul 12, 2005 - 12:35 PM
|
The design of property classes was changed in the Prof-UIS 2.40 major release. Please use the latest source code to avoid misunderstanding. If you are going to use your own classes derived from CExtGridCell or CExtGridCellComboBox , make sure that you dd not forget to use the IMPLEMENT_ExtGridCell_Clone pre-processor macro in the class declaration. The methods of the CExtPropertyItem class for operating with default and active cell objects were introduced in 2.40, including cell object initialization by its Run Time Class (RTC). The 2.33 version of the property value supports only one cell object and, as a result, the old property grid does not perform "Reset" operation for property values and does not display the context menu.
|
|
Eddie Judson
|
Jul 9, 2005 - 8:03 PM
|
While upgrading my application grid to use prof-uis I used to use a CDateTimeCtrl m_OLDdtPicker; I changed it over to CExtDateTimeWnd m_dtPicker; When I inistialise my grid the old picker worked fine with RECT rcMin; rcMin.left=0; rcMin.right=120; rcMin.top=0; rcMin.bottom=18; this-> m_OLDdtPicker.Create( WS_CHILD | WS_VISIBLE | MCS_NOTODAY,rcMin,this,IDC_GRIDCAL); But when I upgrade it to RECT rcMin; rcMin.left=0; rcMin.right=120; rcMin.top=0; rcMin.bottom=18; this->m_dtPicker.Create(this,rcMin,IDC_GRIDCAL,0x56010000); 0x56010000 = the same style that is in the sample application the CExtDateTimeWnd fails on the create method, stepping into the create method it failes on HWND hWnd = ::CreateWindowEx(cs.dwExStyle, cs.lpszClass, cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy, cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams); With paramaters cs.dwExStyle 0 unsigned long + cs.lpszClass 0x00bcceac "ProfUIS-DurationWnd" const char * + cs.lpszName 0x00000000 <Bad Ptr> const char * cs.style 1442906112 long cs.x 0 int cs.y 0 int cs.cx 120 int cs.cy 18 int + cs.hwndParent 0x00060fce {unused=??? } HWND__ * + cs.hMenu 0x00000349 {unused=??? } HMENU__ * + cs.hInstance 0x00400000 {unused=9460301 } HINSTANCE__ * cs.lpCreateParams 0x00000000 void * Thanks for the help! Regards, Eddie
|
|
Technical Support
|
Jul 11, 2005 - 8:27 AM
|
Thank you for the bug report. We fixed it and sent you the updated code by e-mail. If someone else encounters this problem and does not want to wait for the next release, they can fix this bug themselves: 1. At the end of the CExtDurationWnd::Create method, insert a call to the UpdateDurationWnd( false ) method: bool CExtDurationWnd::Create(
CWnd * pParentWnd,
const RECT & rcWnd,
UINT nDlgCtrlID,
DWORD dwWindowStyle,
CCreateContext * pContext
)
{
ASSERT_VALID( this );
...
...
...
m_bInitialized = true;
UpdateDurationWnd( false );
return true;
}
2. Modify the CExtDurationWnd::UpdateDurationWnd method in this way: void CExtDurationWnd::UpdateDurationWnd(
bool bUpdate // = false
)
{
ASSERT_VALID( this );
if( GetSafeHwnd() == NULL
|| ( ! ::IsWindow( m_hWnd ) )
|| ( !m_bInitialized )
)
return;
_RecalcDuration(); // should be before _RecalcLayout() !!!
_RecalcLayout();
Invalidate();
m_wndDropDown.Invalidate();
m_wndSpin.Invalidate();
if( bUpdate
&& (GetStyle() & WS_VISIBLE) != 0
)
UpdateWindow();
}
3. Recompile the library.
|
|
Eddie Judson
|
Jul 12, 2005 - 8:43 AM
|
Thanks that fixed it, but I have a new problem I am linking against ProfUIS240smd.lib and when I call this->m_dtPicker.SetDate(ThisDate.GetYear(),ThisDate.GetYear(),ThisDate.GetDay()); the linker is reporting error: unresolved external symbol public: int __thiscall CExtDateTimeWnd::SetDate(int,int,int) if I remove the AFX_INLINE statement before the method declaration and recomplie the library it seems to work fine. Do I need the AFX_INLINE statement before the declaration or is it ok to remove it?
|
|
Technical Support
|
Jul 12, 2005 - 10:35 AM
|
MFC’s AFX_INLINE declaration is just a C++ inline statement. It typically saves the overhead on function calls (including parameter passing and placing the object’s address on the stack). You can freely remove this statement without any troubles, but we think that you should just rebuild the library, because you problem may be caused by mismatches in the OBJ module between the CExtDateTimeWnd header and source files.
|
|
Chris Thomas
|
Jul 7, 2005 - 3:03 PM
|
Hello, I have a app with customization, and have an issue with redocking toolbars occasionally truncating and displaying a right-pointing double chevron.
I saw the FAQ article "How to remove the chevron button from the toolbar?", but that seems to refer to the down arrow glyph, not the right pointing chevron. It seems to me that removing that would also disable the customization system (but I’ll try it anyway).
The first time through, things get docked beautifully. It uses the FAQ "How to set the initial positions of toolbars when the application starts for the first time?" which consists of repeated RecalcLayout() and OffsetRect(1,0) calls. I’ve expanded on that technique to pop bars to the next row if there isn’t enough room on the current row. Again, that is working fine.
The app allows you to reset the toolbars, which runs through the exact same code as the initial docking. Sometimes a bar or two gets "truncated" and the right chevron appears. If you click the chevron you get a context menu with the "spilled over" buttons. Sometimes almost all the bars get this, and you see just one or two buttons on each!
I tried making the bar "fixed size" but then the docking system complains.
Any ideas? Thanks.
|
|
Technical Support
|
Jul 9, 2005 - 8:35 AM
|
We know that it is completely possible to remove the toolbar’s chevron button and, at the same time, to dock toolbars relative to each other regardless whether your application is customizable or not. Unfortunately you did not provide any code snippet demonstrating how you tried to perform this task. Alternatively you can send us your project and we will help you to find out what’s wrong.
|
|
Chris Thomas
|
Jul 11, 2005 - 9:24 AM
|
Is there an example of how to implement "reset toolbars" functionality? What I’m after is a example of starting out with a set of docked toolbars, then the user moves them around and floats some, then hits a menu "reset toolbars", and the app then redocks all the bars as they were before the user moved them.
Perhaps it would be easiest to consider how to do that with the StyleEditor example?
I seem to be having trouble with the redocking part. It seems that if a toolbar is already docked then it wants to keep its position. When the app starts for the first time, the bars are all tight without gaps and without any truncation (chevron).
How can I tell profuis to forget about all the toolbar positions and just start over, without restarting the app?
Also I sometimes (seemingly randomly) get ASSERTs about some "affixment data". I don’t understand what that is or what bearing it would have to docking. Can’t you just put the bar where it fits?
|
|
Chris Thomas
|
Jul 11, 2005 - 9:26 AM
|
Sorry for another question, but perhaps you could answer why I sometimes get toolbar truncation with the right pointing chevron (with truncated menu icons on a popup menu), but I can never drag and drap a bar to force this behavior. It simply does not let the user drop a bar onto another to force truncation, but it happens through code.
|
|
Chris Thomas
|
Jul 11, 2005 - 10:45 AM
|
OK, you can see my problem if you take the StyleEditor example and add an menu item for "Reset Toolbars" and put a handler for it in CMainFrame:
void CMainFrame::OnFileResettoolbars() { //Redock m_wndToolBarStandard to the top left DockControlBar(&m_wndToolBarStandard); RecalcLayout ();
CRect rect; m_wndToolBarStandard.GetWindowRect (&rect); rect.OffsetRect (1,0);
//Redock m_wndToolBarUiLook to the right of m_wndToolBarStandard
DockControlBar(&m_wndToolBarUiLook, AFX_IDW_DOCKBAR_TOP, &rect); RecalcLayout (); }
Try moving the bars around then clicking on Reset Toolbars. In this case I always want m_wndToolBarStandard on the top row, and m_wndToolBarUiLook on the same row to right.
Is this the wrong approach?
Thanks
|
|
Chris Thomas
|
Jul 11, 2005 - 11:41 AM
|
And if you replace the reset toolbar routine with this one, that also docks the menu bar, then you will eventually see the affixment ASSERT:
void CMainFrame::OnFileResettoolbars() { DockControlBar(&m_wndMenuBar); RecalcLayout ();
//Redock m_wndToolBarStandard to the top left CRect rect; m_wndMenuBar.GetWindowRect (&rect); rect.OffsetRect (0,1); DockControlBar(&m_wndToolBarStandard, AFX_IDW_DOCKBAR_TOP, &rect); // DockControlBar(&m_wndToolBarStandard);
// CRect rect; m_wndToolBarStandard.GetWindowRect (&rect); rect.OffsetRect (1,0);
//Redock m_wndToolBarUiLook to the right of m_wndToolBarStandard
DockControlBar(&m_wndToolBarUiLook, AFX_IDW_DOCKBAR_TOP, &rect); RecalcLayout (); }
Sorry for such a verbose bunch of questions.
|
|
Technical Support
|
Jul 11, 2005 - 12:40 PM
|
You should simply invoke the _AffixmentSafeClearOuter() method for each toolbar immediately before you redock the toolbar by calling DockControlBar() .
|
|
Technical Support
|
Jul 11, 2005 - 12:38 PM
|
Please use the _AffixmentSafeClearOuter() method as we described in one of our previous messages in this thread and send us your source code if you encounter any difficulties.
|
|
Technical Support
|
Jul 11, 2005 - 12:28 PM
|
The user really can be unable to drop some toolbar near another. For instance, you have several toolbars which are docked into one row. Then you decrease the width of the main frame window. The toolbars in the row become smaller and even they may be re-organized in two rows which are virtual rows inside one real row. These virtual rows are always assumed to be one row. You can be unable to drop another toolbar in a very compressed row. The same behavior is provided by toolbars in the latest Microsoft products.
|
|
Technical Support
|
Jul 11, 2005 - 12:25 PM
|
To reset positions of your toolbars as though your application starts for the first time, just invoke the code (in your CMainFrame::OnCreate() method) responsible for initioalizing GUI when the control bars’ state is not yet loaded from the registry.
Yes, we confirm that redocking a toolbar in this case has a problem with toolbar affixment. To make a toolbar forget its affixment information, please invoke its _AffixmentSafeClearOuter() method immediately before docking it into a new location.
|
|
Chris Thomas
|
Jul 13, 2005 - 8:30 AM
|
|
|
Dmitriy Dashevskiy
|
Jul 7, 2005 - 9:41 AM
|
I would like to restrict grouping of the CExtResizable bars into tab container only to bars within the same circle. Say if there is a bar (A) docked at circle 1 (as I understand from help file it should start from 1) and two bars (B and C) docked at circle 2. I would like to disable grouping of B and C with A but still be able to group B and C together. In my particular case A has no gripper so it can’t be dragged to another bar. In 2.3X there was a different docking behaviour for "Like 2003" and "Like 2005" modes. "Like 2005" was doing exactly what I needed. It was restricting docking to the circle 2. "Like 2003" allowed to dock anywhere and thus grouping with bar from circle 1. In 2.40 this has changed and both modes behave the same - i.e. just like old "Like 2003". Another way which will work for me as well is to allow disable groupping of internally docked bars together with externaly docked ( with DockControlBarInnerOuter( AFX_IDW_DOCKBAR_LEFT, false, this, true ); ). Is it possible? Thank you in advance for your help.
|
|
Technical Support
|
Jul 7, 2005 - 11:16 AM
|
This can be done by overriding the following internal method in your CExtControlBar -derived class:protected:
virtual bool _CanDockToTabbedContainers(
CExtControlBar * pDestBar
) const; This method allows you to detect whether the control bar can be docked with other control bar(s) in the same tabbed container. The pDestBar parameter can be a kind of the CExtDynControlBar class derived from CExtControlBar and implements a splitter-like control bar container for organizing a row with control bars inside a column with control bars and vice versa. The pDestBar parameter can also be a kind of the CExtDynTabControlBar class derived from CExtDynControlBar and implements a tabbed bar container. To enumerate control bars in these containers, you can use the code below:CExtDynControlBar * pDynBar =
DYNAMIC_DOWNCAST(
CExtDynControlBar,
pDestBar
);
if( pDynBar == NULL )
return . . .
ASSERT_VALID( pDynBar );
ASSERT_VALID( pDynBar->m_pWndDynDocker );
CWnd * pWnd = pDynBar->m_pWndDynDocker->GetWindow( GW_CHILD );
while( pWnd != NULL )
{
ASSERT_VALID( pWnd );
CExtControlBar * pOtherBarInGroup =
STATIC_DOWNCAST(
CExtControlBar,
pWnd
);
// analyze whether the pOtherBarInGroup
// can be docked within this bar into the
// same tabbed group
. . .
pWnd = pWnd->GetWindow( GW_HWNDNEXT );
} As we mentioned before, tabbed bar groups are instances of the CExtDynTabControlBar class, which are created by Prof-UIS during drag-and-drop, serialization from registry/file or by invoking the CExtControlBar::DockControlBarIntoTabbedContainer() method. You will need to make Prof-UIS use your own CExtDynTabControlBar -derived class that also implements the _CanDockToTabbedContainers() virtual method. This can be done by handling the CExtControlBar::g_nMsgCreateTabbedBar registered windows message in your main frame window:ON_REGISTERED_MESSAGE(
CExtControlBar::g_nMsgCreateTabbedBar,
OnCreateTabbedBar
)
LRESULT CMainFrame::CreateTabbedBar( WPARAM wParam, LPARAM lParam )
{
CExtDynTabControlBar ** ppTabbedBar =
reinterpret_cast
< CExtDynTabControlBar ** >
(wParam);
(*ppTabbedBar) =
new C_YOUR_DynTabControlBar;
return 0;
} Finally, we would like to ask you to send us your project if you encounter any difficulties. We also wonder why you need to restrict the control bar re-docking algorithm in your application?
|
|
Dmitriy Dashevskiy
|
Jul 8, 2005 - 1:00 AM
|
Thanks for reply. It looks like this way it is possible to disable undesired docking operation, but it is not very elegant. In "Like 2005" docking mode there are still arrows and "tabs" image offering docking to the bar A (from above example). But when dragged pane is dropped in its just remains floating. I’ll try to explain the reason for docking algorithm restriction. Document view has two areas: one is a tree to select document items and another is item view (think of Explorer window). There are several different types of items each has its own view with differerent dockable bars (panes). Selecting different items in the tree changes item view. Users can rearrange panes in each item view as they like. Ideally panes should be restricted to the item view area. Since bars need frame window as parrent all panes (from all item views) and tree are created at the moment as bars in ChildView. Selecting some item in the tree saves current state of panes, hides them all and restores state of panes for newly selected view. If there is a way to have panes dockable in a regular window - it will solve all problems. Then selection tree will be a resizable bar in ChildFrame and each view will have its own set of panes and they automatically will be bound to it. Actually this will be an ideal solution as it will allow much better switching between views. Is it possible to modify window derived from regular CWnd to support docking of CExtResizableBars?
|
|
Technical Support
|
Jul 9, 2005 - 10:22 AM
|
If you try to enumerate all possible relative positions of three or more resizable control bars, you will certainly come to conclusion that there is no reason to restrict their docking algorithm. The idea of a resizable control bar as it is implemented in Visual Studio .NET implies a window that is not restricted by its size and position. If you take a look at the class tree in Visual Studio 2005, you will see that it contains neither class methods nor property members. The methods and properties are placed in the separate list box at the bottom of the class tree. The class tree and members list box are inserted into a splitter-like container window. So, we can assume the class members list box is a preview window for the currently selected item in the class tree. This idea is not new. The properties window uses the same splitter-like container for displaying property description text at the bottom of the property grid control. In both cases the top window contains are not overloaded with information because the details are displayed in the bottom "preview" window. These real life samples demonstrate a good preview/details UI design. Of course, it makes sense when the amount of preview information is not large. If the preview window requires extensive horizontal/vertical scrolling because of lots of information to display, you can use the MDI interface and open a tree item preview as an MDI child window. As for your last question, we do not see principal differences between frame windows, dialog boxes, generic CWnd windows, common controls and so on. Yes, control bars can be re-dockable only inside CFrameWnd because it is a container window which supports re-docking for control bars, hiding when an OLE object is in-place active and much more. If you need a dialog, then you can use it as a child view and in this case the design of the main frame window and child dialog windows is not much more complicated than a single dialog box as the main window. We would appreciate if you send us some screenshots so that we can continue this discussion in details.
|
|
Eddie Judson
|
Jul 7, 2005 - 7:45 AM
|
Is there a way to stop the menus from using the collapse feature (double down arrow) so that all the items in the menu are visible all the time? Regards,
|
|
Technical Support
|
Jul 7, 2005 - 9:08 AM
|
If you want to disable the most recently used menu items, there are two ways to do this: - add these two lines to your initialization code (which is preferable):
CExtPopupMenuWnd::g_bMenuExpanding = false;
CExtPopupMenuWnd::g_bMenuHighlightRarely = false;
- use
g_CmdManager->SetBasicCommands to make all your commands basic i.e. initially visible in your menus.
|
|
Dmitriy Dashevskiy
|
Jul 7, 2005 - 6:05 AM
|
Is it possible to make STUDIO_2005 docking look same way as it was in 2.32?
|
|
Technical Support
|
Jul 7, 2005 - 8:42 AM
|
|
|
Dmitriy Dashevskiy
|
Jul 7, 2005 - 8:46 AM
|
|
|
Krustys Donuts
|
Jul 6, 2005 - 8:20 AM
|
Hi, when we upgraded from 2.30 to 2.33 (and 2.40 as well), our application started to crash immediately when adding items to our CExtPageNavigatorWnd object. I attempted to debug the problem (uh oh), and found something that didn’t make sense to me:
LONG nCount = ItemGetCount();
if( nIndex < 0 || nIndex > nCount )
nIndex = nCount;
PAGE_ITEM_INFO * pPII = new PAGE_ITEM_INFO( sText, hIconExpanded, hIconCollapsed,
dwData, this);
ASSERT_VALID( pPII );
nIndex++;
m_arrItems.InsertAt( nIndex, pPII );
As CArrays are 0-based, why is it that nIndex is incremented before the call to InsertAt()? If I change the code to increment nIndex after the call to InsertAt(), everything *seems* to operate normally. Well, at least the application doesn’t crash.
Any info would be really appreciated! Thank you!
|
|
Technical Support
|
Jul 7, 2005 - 2:19 AM
|
The first (zero) element in the m_arrItems array is always associated with the Configure Buttons item, so we need to increment nIndex before inserting user items. Anyway InsertAt will be valid even if the nIndex is greater than the array size. When you add a new element at a position beyond the end of the array, the array just grows to this new size and nIndex will always be valid. We fixed a bug in v.2.33 with icorrect insert/delete operations at run time. May be this somehow relates to your problem. Please provide us with more details about the problem (like call stack, source code in which you create and initialize the page navigator, and etc.).
|
|
Krustys Donuts
|
Jul 7, 2005 - 8:18 AM
|
Thanks for the reply. I knew that a "bug find" like that was too good to be true. :)
So anyhow, our project crashes when our page navigator gets created:
int CTasksAvailablePageNavigator::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CExtPageNavigatorWnd::OnCreate(lpCreateStruct) == -1)
return -1;
HICON h_icon1 = 0;
HICON h_icon2 = 0;
CExtPageNavigatorWnd::PAGE_ITEM_INFO *p_pii = NULL;
h_icon1 = ( HICON)::LoadImage( global_GUI_Framework_Instance, MAKEINTRESOURCE( IDI_PLATE_HANDLING), IMAGE_ICON, 24, 24, 0 );
h_icon2 = ( HICON)::LoadImage( global_GUI_Framework_Instance, MAKEINTRESOURCE( IDI_PLATE_HANDLING), IMAGE_ICON, 16, 16, 0 );
// "pages" is a vector<CExtPageNavigatorWnd::PAGE_ITEM_INFO*>
// code crashes when ItemInsert gets called
pages.push_back( p_pii = ItemInsert( -1, _T( "Pane #1"), h_icon1, h_icon2));
...
}
This is what the call stack looks like:
ProfUIS240md.dll!CExtPageNavigatorWnd::AssertValid() Line 923 + 0x19 C++
mfc71d.dll!AfxAssertValidObject(const CObject * pOb=0x00abda00, const char * lpszFileName=0x1057d398, int nLine=442) Line 104 C++
ProfUIS240md.dll!CExtPageNavigatorWnd::ItemGetCount() Line 443 C++
ProfUIS240md.dll!CExtPageNavigatorWnd::ItemInsert(long nIndex=1, const char * sText=0x005adc90, HICON__ * hIconExpanded=0x000404e3, HICON__ * hIconCollapsed=0x02b104f7, unsigned long dwData=0, bool bUpdate=false) Line 2198 + 0x8 C++
krustysdonuts.dll!CMyPageNavigator::OnCreate(tagCREATESTRUCTA * lpCreateStruct=0x0012dc20) Line 42 + 0x1e C++
Hopefully, this info helps! Thank you.
|
|
Krustys Donuts
|
Jul 7, 2005 - 8:19 AM
|
by the way, I had renamed our class in the call stack, but not in the code... sorry if that confuses anything.
|
|
Technical Support
|
Jul 7, 2005 - 9:51 AM
|
Thank you for the code snippet. We found out what the problem was. You initialized page navigator items in the OnCreate method of a class derived from CExtPageNavigatorWnd . This method in your derived class is called before we make some important operations, so you encountered the error. We fixed this problem and sent an update to you. Just replace old files with new ones and recompile the library.
|
|
Stephan Finkler
|
Jul 4, 2005 - 7:46 AM
|
Hi,
I miss the ID_EXT_BTN_NAME in the string table.
Is this your intention?
When do you set the STATE_MENUBAR_TMP state?
|
|
Technical Support
|
Jul 5, 2005 - 5:08 AM
|
ID_EXT_BTN_NAME is a command identifier used for the Name: text field in the context popup menu over any toolbar button or menu item when the Customize dialog is open. Please note that the customization subsystem is only available when both Prof-UIS and MFC are used as DLLs in your project.
The STATE_MENUBAR_TMP flag is an internal flag used by the CExtMenuControlBar window to mark CExtCmdItem objects that represent toolbar buttons with popup menus inside the menu control bar. STATE_MENUBAR_TMP is required for dynamic reallocation of command identifiers when the menu bar recreates its buttons, which is common to MDI applications.
|
|
Eddie Judson
|
Jun 30, 2005 - 7:28 AM
|
If I have:
OuterRowCountTopSet( 1L, false ); OuterColumnCountLeftSet( 1L, false ); Is there anyway I can access the cell at the top left (intersection of the outer column and outer row) so I can downcast it to my own class? Also I don’t spose you have any sample code that autosizes columns to the width of the text ? Regards, Eddie
|
|
Eddie Judson
|
Jul 4, 2005 - 8:25 PM
|
Thanks for the quick reply. The reason I wanted to know was that I want to put a CExtDateTimeWnd control in the top left outer cell. Is it possible to get a copy of the
CPageDateTimeDuration class from the samples as I can not find it in the source for the samples.
|
|
Technical Support
|
Jul 5, 2005 - 12:52 PM
|
The CPageDateTimeDuration and CExtDateTimeWnd classes are available in Prof-UIS 2.40 which you can download right now. To put them into corners, just create their windows in appropriate positions of your grid window. You should also reposition them when the grid size is changed. This requires creation of your CExtGridWnd -derived class and implementing the CExtGridWnd::OnSwRecalcLayout() virtual method which should invoke the parent’s method and move your controls into grid corners in case of the bDoLayout parameter is true .
|
|
Technical Support
|
Jun 30, 2005 - 12:44 PM
|
The grid control does not display cell objects in corners but you can repaint them if you need to display some information there. You should override the CExtGridBaseWnd::OnGbwEraseArea() virtual method like as follows:void C_YOUR_GridWnd::OnGbwEraseArea(
CDC & dc,
const RECT & rcArea,
DWORD dwAreaFlags
) const
{
ASSERT_VALID( this );
ASSERT( dc.GetSafeHdc() != NULL );
COLORREF clrDebugFill = COLORREF( -1L );
switch( dwAreaFlags )
{
case __EGBWA_OUTER_CELLS|__EGBWA_OUTER_TOP:
clrDebugFill = RGB( 255, 128, 128 );
break;
case __EGBWA_OUTER_CELLS|__EGBWA_OUTER_BOTTOM:
clrDebugFill = RGB( 128, 255, 128 );
break;
case __EGBWA_OUTER_CELLS|__EGBWA_OUTER_LEFT:
clrDebugFill = RGB( 128, 128, 255 );
break;
case __EGBWA_OUTER_CELLS|__EGBWA_OUTER_RIGHT:
clrDebugFill = RGB( 128, 255, 255 );
break;
case __EGBWA_OUTER_CELLS|__EGBWA_OUTER_LEFT|__EGBWA_OUTER_TOP:
clrDebugFill = RGB( 255, 128, 255 );
break;
case __EGBWA_OUTER_CELLS|__EGBWA_OUTER_LEFT|__EGBWA_OUTER_BOTTOM:
clrDebugFill = RGB( 255, 255, 128 );
break;
case __EGBWA_OUTER_CELLS|__EGBWA_OUTER_RIGHT|__EGBWA_OUTER_TOP:
clrDebugFill = RGB( 255, 255, 128 );
break;
case __EGBWA_OUTER_CELLS|__EGBWA_OUTER_RIGHT|__EGBWA_OUTER_BOTTOM:
clrDebugFill = RGB( 128, 128, 128 );
break;
case __EGBWA_INNER_CELLS:
clrDebugFill = RGB( 255, 255, 224 );
break;
}
if( clrDebugFill != COLORREF( -1L ) )
dc.FillSolidRect( &rcArea, clrDebugFill );
} This sample code allows you to see the areas of the grid window highlighted with custom colors. If you have a pointer to the CExtGridCell object, you can downcast its type dynamically using MFC’s DYNAMIC_DOWNCAST macro:CExtGridCell * pCell = . . .
CExtGridCellHeader * pHeaderCell =
DYNAMIC_DOWNCAST(
CExtGridCellHeader,
pCell
); The pHeaderCell pointer will be NULL if the pCell pointer does not point to a CExtGridCellHeader object. This does not depend on the cell location in the grid window.
|
|
Krustys Donuts
|
Jun 29, 2005 - 2:45 PM
|
In the documentation, users are instructed to
1. Create the popup object dynamically 2. Initialize menu items by calling LoadMenu, *or* by calling InsertItem for each item.
I’ve found that this isn’t entirely accurate. If I don’t call LoadMenu, then InsertItem doesn’t actually add anything to the menu. However, if I do call LoadMenu, then InsertItem works. However, my problem is that my context menus are entirely dynamically generated (they do not rely on the command manager). Currently, the only way I’ve been able to get this to work is to create a dummy menu, load it with LoadMenu, then delete the first item, and finally insert my item using ItemInsert.
The interesting thing is that ItemInsertSpecPopup *does* work without calling LoadMenu first. ItemInsertCommand does *not* work.
Here’s what my code looks like right now:
CExtPopupMenuWnd* p = new CExtPopupMenuWnd();
VERIFY( p->CreatePopupMenu( GetParent()->GetSafeHwnd()));
p->g_bMenuExpanding = false;
// add the selections menu
if( selectionsEnabled) {
p->ItemInsert( ContextCommands::SelectAll, -1, "Select all", 0, GetSafeHwnd());
p->ItemInsert( ContextCommands::DeselectAll, -1, "Deselect all", 0, GetSafeHwnd());
p->ItemInsert( ContextCommands::InvertSelection, -1, "Invert selection", 0, GetSafeHwnd());
// add separator
p->ItemInsert();
}
ClientToScreen( &point);
p->TrackPopupMenu( 0, point.x, point.y);
I hope you can see what I’m doing wrong!
Thank you!
|
|
Krustys Donuts
|
Jun 29, 2005 - 2:49 PM
|
Sorry, I got a bit confused between projects... the code above actually crashes (I thought it was a blank context menu). I followed the steps outlined in the documentation, though.
|
|
Krustys Donuts
|
Jun 29, 2005 - 3:00 PM
|
Sorry, I figured it out. ItemInsertCommand actually does work correctly. Can you please change the docs to reflect this? ItemInsertCommand should be called if you don’t use LoadMenu... not ItemInsert.
|
|
Technical Support
|
Jun 30, 2005 - 5:17 AM
|
Yes, we will need to update the documentation. Additionally we should note: you can download the latest source code where the CExtPopupMenu::LoadMenu() method is also able to create a pop-up menu which is not based on the command manager. This method has a new parameter that is bNoRefToCmdManager .
|
|
Stephan Finkler
|
Jun 29, 2005 - 7:53 AM
|
Hi,
I tried to use the CExtCustomizeSite::CategoryMakeFromTreeN function but I get always an assert in
int CExtCustomizeSite::CategoryMakeFromTree( CExtCustomizeCmdTreeNode * pNodeCategoryRoot, __EXT_MFC_SAFE_LPCTSTR strCategoryName // = NULL ) { ASSERT_VALID( pNodeCategoryRoot ); ASSERT_KINDOF( CExtCustomizeCmdTreeNode, pNodeCategoryRoot ); CExtSafeString _strCategoryName; if( strCategoryName != NULL ) _strCategoryName = strCategoryName; else _strCategoryName = pNodeCategoryRoot->GetTextUser(); ASSERT( ! _strCategoryName.IsEmpty() );
because pNodeCategoryRoot->GetTextUser(); returns an empty string
here is my code:
for( int nMenuInfoIdx = 0; nMenuInfoIdx < CExtCustomizeSite::MenuInfoGetCount(); nMenuInfoIdx++ ) { CExtCustomizeSite::CCmdMenuInfo *pCmdMenuInfo = CExtCustomizeSite::MenuInfoGetAt(nMenuInfoIdx) ; ASSERT( pCmdMenuInfo != NULL ); if(pCmdMenuInfo != NULL) {
CExtCustomizeCmdTreeNode *pMenuRootNode = NULL; pMenuRootNode = pCmdMenuInfo->GetNode(true); ASSERT_VALID( pMenuRootNode ); if(pMenuRootNode != NULL) { CExtCustomizeSite::CategoryMakeFromTreeN(pMenuRootNode); } } }
How can I update the categories by a command tree node?
|
|
Technical Support
|
Jun 29, 2005 - 12:37 PM
|
Thank you for the interesting question. Each command tree node has three text properties: text in menu, text in toolbar and user-defined text. The user-defined text is empty in most cases. It is empty for command tree nodes created from menu resources. The CExtCustomizeSite::CategoryMakeFromTreeN() method traverses nodes that are child to a particular node and uses creates command categories from them. The CExtCustomizeSite::CategoryMakeFromTreeN() method assumes that each child node used for creating its category has a non-empty user-defined text property because it is used as a command category name. That is why you encountered the assertion. You can simply assign user defined text (using menu text) menu text for all the child nodes by calling the CExtCustomizeCmdTreeNode::SetTextUser() method before you call CExtCustomizeSite::CategoryMakeFromTreeN() .
|
|
Russ Berman
|
Jun 28, 2005 - 12:28 PM
|
Hi,
I must be missing something in my wrapper class. Whenever I call my insertRow() method, which creates a row in the contained CExtGridWnd object and sets the cell data, I see that the GDI object count increases. So as I add more and more rows of data, the number of objects goes into the thousands. The application gets slower and slower as items are added.
I’m running 2.30 right now... is it possible that there’s some cleanup code that I’m missing? I’ve tried to identify problems with BoundsChecker, and I do get a couple of errors that pop up constantly. It looks like a GDI object is getting selected into more than one DC at a time, and the call to DeleteObject fails because the object is still selected into another DC at the time of the call. Perhaps this is related?
Thanks, Dave
|
|
Technical Support
|
Jun 29, 2005 - 3:43 AM
|
There is not enough information in your message to come to any conclusion about GDI handle leaks in the grid control. We tested all Prof-UIS samples for leaks before releasing 2.30. Could you send us your test project demonstrating GDI handle leaks? We may guess that the problem has something to do with grid cell types inserted into your grid rows.
|
|
Krustys Donuts
|
Jun 29, 2005 - 7:19 AM
|
This is a slightly modified version of how I add each cell to the grid. I normally have to lookup the data that goes into the cell by checking a map, but for clarity’s sake, I’ve just inserted a const string.
CExtGridCell* pHeaderCell = GridCellGetOuterAtTop( i, 0); CString header; pHeaderCell->TextGet( header); CExtGridCellStringDMColor* pCell = STATIC_DOWNCAST( CExtGridCellStringDMColor, GridCellGet( i, row, 0, 0, RUNTIME_CLASS( CExtGridCellStringDMColor))); string data = "ThisIsATest"; // this value is normally pulled from a map pCell->TextSet( data.c_str());
CExtGridCellStringDMColor is defined as:
class CExtGridCellStringDMColor : public CExtGridCellStringDM { COLORREF textColor; COLORREF bgColor; public: DECLARE_DYNCREATE( CExtGridCellStringDMColor ); IMPLEMENT_ExtGridCell_Clone( CExtGridCellStringDMColor, CExtGridCellStringDM ); CExtGridCellStringDMColor( CExtGridDataProvider * pDP = NULL); virtual COLORREF OnQueryTextColor( const CExtGridWnd & wndGrid, CDC & dc, LONG nVisibleColNo, LONG nVisibleRowNo, LONG nColNo, LONG nRowNo, INT nColType, INT nRowType, DWORD dwAreaFlags, DWORD dwHelperPaintFlags) const; virtual bool OnPaintBackground( const CExtGridWnd & wndGrid, CDC & dc, LONG nVisibleColNo, LONG nVisibleRowNo, LONG nColNo, LONG nRowNo, INT nColType, INT nRowType, const RECT & rcCellExtra, const RECT & rcCell, const RECT & rcVisibleRange, DWORD dwAreaFlags, DWORD dwHelperPaintFlags) const; void setTextColor( COLORREF color) { textColor = color; } void setBgColor( COLORREF color) { bgColor = color; } };
I pulled this code from the SimpleGrids application in the _InitDemoTable_Orders method. I hope you can figure out what I did wrong!
Thanks, Dave
|
|
Technical Support
|
Jun 29, 2005 - 12:50 PM
|
Your code seems to be OK. Your class is mostly similar to the CDemoColoredCell class available in the SimpleGrids sample but it just keeps color properties inside. If you modify the CDemoGrid::_InitDemoTable_Colors() method in this sample by changing the number of inserted rows, then you should note that the number of GDI handles allocated in SimpleGrids remains the same (does not change). Could you send us your test or real project that demostrates the leak? Is true that this leak appears in the information displayed on the Processes page of the Windows NT Task Manager tool with/without instrumenting the code with the Bounds Checker tool?
|
|
Krustys Donuts
|
Jun 29, 2005 - 2:30 PM
|
I will try to put together sample code that exhibits this problem today, and will send it to you when it’s ready.
By the way, yes, you can see the GDI leak in the Task Manager with or without the code instrumented.
|
|
Technical Support
|
Jun 30, 2005 - 5:14 AM
|
We appreciate your help in finding and fixing a possible bug either in Prof-UIS or in your application.
|
|
Krustys Donuts
|
Jun 30, 2005 - 11:07 PM
|
I apologize for not creating a test application before blaming the grid control for the GDI leak. I wrote a test application using my CExtGridWndWrapper class, and it didn’t leak. I then went back to the offending application and stepped into the calls, and eventually found the culprit.
It turns out that in order to calculate the ideal column width to fit my text, I need to get a DC. I called GetDC(), but didn’t follow it up with a call to ReleaseDC(), because of this line in MSDN:
Unless the device context belongs to a window class, the ReleaseDC member function must be called...
which I figured that I didn’t need to call, since my DC does belong to a window class. Anyhow, I just added the call, and now the GDI object leak is gone.
Thanks again for your prompt responses!
|
|
Technical Support
|
Jul 1, 2005 - 9:42 AM
|
You can always ask for our help and assistance when you need it and we’ll do our best to help you.
|
|
Stephan Finkler
|
Jun 27, 2005 - 8:00 AM
|
Hi,
at the moment we have to delete the file with the serialized data if we get a newer version of ProfUIS.
This is a little bit anoying for the users because they loose there settings.
Is there an workaround to keep the settings of the user?
I use following function calls to serialize ProfUIS states:
- CExtCustomizeSite::CustomizeStateSerialize(..)
- CExtControlBar::ProfileBarStateSerialize(..)
- CExtCmdProfile::SerializeState(..)
Thanks for any help.
|
|
Technical Support
|
Jun 29, 2005 - 2:42 AM
|
Currently Prof-UIS supports only binary serialization for all its subsystems. Of course, serialized data are version dependent and include a variable number of fields, MFC run-time class information and etc. Customization and dockable control bar subsystems operate with tree-like data, which are complex enough, and that is why we implemented serialization by using binary streams. To make serialization version independent, we need to switch to a text-based state format like XML. We will consider your question as a feature request.
|
|
David Coleman
|
Jun 24, 2005 - 3:13 AM
|
Hello, I have successfully created a function to change the text colour of a grid cell. However, this interferes with the drawing of the CExtContentExpandWnd and makes the text the wrong colour. The way I am attempting to get round this is to override the OnPaintExpandedContent function and implement my own drawing for the CExtContentExpandWnd. This is working well apart from the drawing of the shadow. It is only drawing a one pixel high line at the bottom of the main rectangle. Please refer to the code below and explain where I am going wrong. virtual bool OnPaintExpandedContent( CExtContentExpandWnd::PAINT_ITEM_CONTENT_DATA & picd, const CExtGridWnd & wndGrid, const CExtGridHitTestInfo & htInfo, CExtContentExpandWnd & wndContentExpand, INT nSizeOfExpandShadow ) const { // create font CFont m_Font; LOGFONT* m_pLF; m_pLF=(LOGFONT*)calloc(1,sizeof(LOGFONT)); strncpy(m_pLF->lfFaceName,"Tahoma",31); m_pLF->lfHeight=13; m_pLF->lfWeight=500; m_pLF->lfItalic=0; m_pLF->lfUnderline=0; m_Font.CreateFontIndirect(m_pLF); // draw CExtContentExpandWnd picd.m_dc.FillSolidRect(picd.m_rcItem.left, picd.m_rcItem.top, picd.m_rcItem.Width()-nSizeOfExpandShadow, picd.m_rcItem.Height()-nSizeOfExpandShadow, RGB(0,0,0)); picd.m_dc.FillSolidRect(picd.m_rcItem.left+1, picd.m_rcItem.top+1, picd.m_rcItem.Width()-2-nSizeOfExpandShadow, picd.m_rcItem.Height()-2-nSizeOfExpandShadow, RGB(255,255,225)); picd.m_dc.SelectObject(m_Font); picd.m_dc.SetTextColor(RGB(0,0,0)); picd.m_dc.TextOut(2, 2, m_strData);
free(m_pLF); // draw shadow CRect rc1stArea, rc2ndArea; rc1stArea = CRect::CRect(0,0,0,0); rc2ndArea = CRect::CRect(0,0,0,0); CExtWndShadow wndShadow; //wndShadow.Restore(picd.m_dc); wndShadow.Paint( picd.m_dc, picd.m_rcItem, &rc1stArea, &rc2ndArea, nSizeOfExpandShadow ); return true; } Regards, David.
|
|
Technical Support
|
Jun 24, 2005 - 7:21 AM
|
To change the text color in a grid cell, just override CExtGridCell::OnQueryTextColor() and return the desired COLORREF value. This is enough to see the custom text color both in the grid cell inside the grid window and in the pop-up content expand window because the same paint methods of the CExtGridCell class are used in both cases. You don’t have to code custom painting for the content expand window.
As for the source code published in your message: please do not create your own font. Just use the font returned by the CExtGridCell::OnQueryCellFont() method. We guess this should fix the one pixel size conflict.
|
|
David Coleman
|
Jun 22, 2005 - 9:39 AM
|
I have successfully created a function to change the text colour of a grid cell. The issue I have is that I want the function to override the provided colour if the cell is selected or it is currently displaying expanded text. I want the function to force the text colour to white if the cell/row is selected, and force it to black if the text is expanded. I have tried testing the __EGCPF_HIGHLIGHTED_BY_SELECTED_ROW style to check if a cell/row is selected but this does absolutely nothing! Also how do I configure the grid to highlight a row when the mouse hovers over it? Any advice would be much appreciated. David.
|
|
Technical Support
|
Jun 23, 2005 - 10:04 AM
|
Try the code like this:bool bHighlightPressing =
( (dwHelperPaintFlags&(__EGCPF_HIGHLIGHTED_BY_PRESSED_COLUMN
|__EGCPF_HIGHLIGHTED_BY_PRESSED_ROW)) != 0
) ? true : false;
if( bHighlightPressing )
clrText = wndGrid.OnSiwGetSysColor( COLOR_HIGHLIGHTTEXT );
As for highlighting, use the HoverHighlightSet method to specify highlighted cells when the mouse pointer hovers over them:void HoverHighlightSet(
bool bHighlightSingleCellsInner = true,
bool bHighlightSingleCellsOuter = true,
bool bHighlightColumnCellsInner = true,
bool bHighlightColumnCellsOuter = true,
bool bHighlightRowCellsInner = true,
bool bHighlightRowCellsOuter = true
);
|
|
Thomas Zaenker
|
Jun 21, 2005 - 6:51 AM
|
Dear support team, I have a CExtResizableDlg with custom controls and a child dialog with CSliderCtrl and static controls in it. The background color of the children does not match those of the dialog itself. My custom control uses g_PaintManager->PaintDockerBkgnd to match the background colors. Was this the right way? Then I derived the child dialog from CExtResizableDlg and disabled the gripper. But now the background of the sliders is wrong and the background of my static control is not erased. Could you please tell me, how to get a consistent background in all controls. A fully owner drawn slider is not a good solution like you did in your sample AdoRecordsetView. The slider should look like all other sliders. Thanks in advance. Axel
|
|
Technical Support
|
Jun 22, 2005 - 3:22 AM
|
We will consider your question as a feature request. We believe it is possible to code a slider control which is similar to the standard control except it uses Prof-UIS for painting its background. But unfortunately the standard slider control does not have methods to get exact positions of its parts. So, we need to conduct some research before providing you with a more detailed answer or a ready-to-use solution.
|
|
David Coleman
|
Jun 21, 2005 - 5:33 AM
|
Is this possible and if so please can you send me some code as an example? All I want is a simple grid which I can populate with text items, and set the background colour to the current theme. Cheers, David.
|
|
Technical Support
|
Jun 22, 2005 - 3:34 AM
|
We guess you need the simplest possible sample application. Please let us know which type of application is more convenient for you: dialog based or frame window based?
|
|
David Coleman
|
Jun 22, 2005 - 8:57 AM
|
After further examination of the included samples and quite a bit of stress I’ve sussed it now thanks.
|
|
Ed Kennedy
|
Jun 17, 2005 - 1:12 PM
|
I’ve just rebuilt my workstation moving from Win2K to WinXP. I’ve found that when I run my app and it gets to the point of creating the CExtStatusControlBar it fails. GetLastError returns 0x0000007F ( The specified procedure could not be found.) Runs fine on Win2K though. Any ideas?
|
|
Technical Support
|
Jun 17, 2005 - 1:41 PM
|
There is not enough information in your message to come to any conclusion about the cause of the problem. It seems like you compiled the library with one compiler (e.g. VS 6.0) and your app with another (e.g. VS NET). Could you check this? Which version of Prof-UIS do you use? Could you compile your app and the library in debug mode and tell us where exactly this error occurs?
|
|
alexey Shetinin
|
Jun 14, 2005 - 8:01 AM
|
Hello, It’s about using PropertyGrid Control.<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p> <o:p> </o:p> Initializing PropertyGrid Control like in sample project, I received memory leaks about every property class entity after closing my MDI application. Should I create a handle to every property class in CPropertyObj class or in MDI applications PropertyGrid Control must be initialized in a different way. <o:p> </o:p> Another problem is what should I do for reassign a sorting order inside the categories in the categorized property grid. I want my properties to place in that order, they’ve been created, without sorting.<o:p></o:p> <o:p> </o:p> <o:p>I have sent demo project to the support email address.</o:p> <o:p>Thanks in advance. </o:p> <o:p> </o:p>
|
|
Technical Support
|
Jun 14, 2005 - 10:13 AM
|
The property grid control does not invoke the C++ delete operator for the assigned CExtPropertyStore object. We may guess you simply forgot to delete a pointer to the property store.
The latest version of the PropertyGrid sample application allows you to have unsorted data optionally in both plain and tree like grid windows of the property grid control. You can request the source code update by e-mail.
|
|
Krustys Donuts
|
Jul 1, 2005 - 10:27 AM
|
could you please send the propertygrid control update to me as well? Also, by any chance to you have a documentation update that includes more information on the propertygrid?
Thanks!
|
|
Technical Support
|
Jul 1, 2005 - 11:52 AM
|
We sent you a link to our ftp site for registered users by e-mail.
|
|
Keith Bradbury
|
Jun 11, 2005 - 8:08 PM
|
In my scroll window, I would like to make the bottom (horizontal) scroll bar smaller and align it to the right, so that it leaves the left side for buttons and other controls. Is it possible with prof-uis? If so, could you provide an example or some pointers? Thanks!
|
|
Technical Support
|
Jun 12, 2005 - 11:07 AM
|
This can be done using a CExtScrollWnd -derived class (e.g., CExtGridWnd demonstrated in the AdoRecordsetView sample), the CExtScrollBar class, and the CExtToolControlBar class. The CExtScrollWnd class implements a scrollable window which can use either built-in window scroll bars in the non-client area of the window or external scroll bar windows. The latter can be used when you need to implement some kind of non-standard scroll bars, i.e. those that have some controls at left/right side of the horizontal scroll bar or at top/bottom side of the vertical scroll bar. CExtScrollBar is handy in this case because it is able to stick to the borders of the CExtScrollWnd window automatically and it also supports two HWND properties: m_hWndBefore and m_hWndAfter . These properties can be NULL or handles to child windows of a CExtScrollWnd -based window. The CExtScrollBar window aligns them automatically. The m_hWndBefore window is placed at the left side of the horizontal scroll bar or at the top side of the vertical scroll bar. The m_hWndAfter window is placed at the right side of the horizontal scroll bar or at the bottom side of the vertical scroll bar. We recommend you use an improved version of the Prof-UIS toolbar for implementing buttons in the same row as the horizontal scroll bar. Here is the source code for this class:class CInplaceToolbarWnd : public CExtToolControlBar
{
class TinyButton : public CExtBarButton
{
public:
TinyButton(
CExtToolControlBar * pBar = NULL,
UINT nCmdID = ID_SEPARATOR,
UINT nStyle = 0
)
: CExtBarButton(
pBar,
nCmdID,
nStyle
)
{
}
virtual CSize CalculateLayout(
CDC & dc,
CSize sizePreCalc,
BOOL bHorz
)
{
ASSERT_VALID( this );
dc;
sizePreCalc;
bHorz;
return CSize( 13, 13 );
}
}; // class TinyButton
protected:
virtual LRESULT WindowProc(
UINT message,
WPARAM wParam,
LPARAM lParam
)
{
ASSERT_VALID( this );
if( message == WM_NCCALCSIZE )
return 0L;
if( message == WM_SIZEPARENT )
return 0L;
return
CExtToolControlBar::
WindowProc( message, wParam, lParam );
}
virtual CExtBarContentExpandButton *
OnCreateBarRightBtn()
{
ASSERT_VALID( this );
return NULL;
}
virtual CExtBarButton *
OnCreateBarCommandBtn(
UINT nCmdID,
UINT nStyle = 0
)
{
ASSERT_VALID( this );
CExtBarButton * pTBB =
new TinyButton(
this, nCmdID, nStyle );
ASSERT_VALID( pTBB );
return pTBB;
}
}; NOTE: Please use 11x11 icons for toolbar buttons. Such a toolbar has a good, consistent look. Your CExtScrollWnd -derived class may look like: class CYourScrollableControl : public CExtScrollWnd
{
public:
CInplaceToolbarWnd m_wndToolBar;
CExtScrollBar m_wndScrollBarH, m_wndScrollBarV;
//{{AFX_VIRTUAL( CYourScrollableControl )
public:
virtual CScrollBar * GetScrollBarCtrl(int nBar) const;
protected:
virtual BOOL PreCreateWindow( CREATESTRUCT& cs );
//}}AFX_VIRTUAL
//{{AFX_MSG( CYourScrollableControl )
afx_msg int OnCreate( LPCREATESTRUCT lpCreateStruct );
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP( CYourScrollableControl, CExtScrollWnd )
//{{AFX_MSG_MAP( CYourScrollableControl )
ON_WM_CREATE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
CScrollBar * CYourScrollableControl::GetScrollBarCtrl(
int nBar
) const
{
ASSERT_VALID( this );
if( m_hWnd == NULL || (! ::IsWindow(m_hWnd) ) )
return NULL;
ASSERT( nBar == SB_HORZ || nBar == SB_VERT );
if( nBar == SB_HORZ )
{
if( m_wndScrollBarH.GetSafeHwnd() != NULL )
return ( const_cast < CExtScrollBar * >
( &m_wndScrollBarH ) );
}
else
{
if( m_wndScrollBarV.GetSafeHwnd() != NULL )
return ( const_cast < CExtScrollBar * >
( &m_wndScrollBarV ) );
}
return NULL;
}
BOOL CYourScrollableControl::PreCreateWindow(
CREATESTRUCT & cs
)
{
if( ! CExtScrollWnd::PreCreateWindow(
cs ) )
{
ASSERT( FALSE );
return FALSE;
}
cs.style &=
~(WS_BORDER);
cs.style |=
WS_CLIPSIBLINGS|WS_CLIPCHILDREN;
cs.dwExStyle &=
~(WS_EX_STATICEDGE|WS_EX_CLIENTEDGE);
return TRUE;
}
int CYourScrollableControl::OnCreate(
LPCREATESTRUCT lpCreateStruct
)
{
if( CExtScrollWnd::OnCreate(
lpCreateStruct
) == -1
)
{
ASSERT( FALSE );
return -1;
}
m_wndScrollBarH.m_eSO =
CExtScrollBar::__ESO_BOTTOM;
m_wndScrollBarV.m_eSO =
CExtScrollBar::__ESO_RIGHT;
if( ! m_wndScrollBarV.Create(
WS_CHILD
| WS_VISIBLE
| SBS_VERT
| SBS_RIGHTALIGN,
CRect(0,0,0,0),
this,
1
)
)
{
ASSERT( FALSE );
return -1;
}
if( ! m_wndScrollBarH.Create(
WS_CHILD
| WS_VISIBLE
| SBS_HORZ
| SBS_BOTTOMALIGN,
CRect(0,0,0,0),
this,
2
)
)
{
ASSERT( FALSE );
return -1;
}
m_wndScrollBarH.
SyncReservedSpace( &m_wndScrollBarV );
m_wndScrollBarV.
SyncReservedSpace( &m_wndScrollBarH );
if( (! m_wndToolbar.Create(
NULL,
this,
3,
WS_CHILD
| WS_VISIBLE
| CBRS_ALIGN_BOTTOM
| CBRS_TOOLTIPS
| CBRS_FLYBY
| CBRS_SIZE_DYNAMIC
) )
|| (! m_wndToolbar.LoadToolBar(
IDR_TOOLBAR_WITH_ICONS
) )
)
{
ASSERT( FALSE );
return -1;
}
m_wndToolbar.MoveWindow( 0, 0, 28, 1 );
m_wndScrollBarH.m_hWndAfter =
m_wndToolbar.GetSafeHwnd();
return 0;
}
|
|