Subject |
Author |
Date |
|
Bangjun Lei
|
Oct 16, 2007 - 2:19 PM
|
Dear Sir./Madam.,
How can I implement a toolbar that slides up to disappear from the resides dialog when my mouse leaves the dialog while it slides down to appear when my moue moves into the dialog?
Thanks!
|
|
Technical Support
|
Oct 17, 2007 - 1:19 PM
|
Here is the code that returns the toolbar’s size (in a CSize object) which fits the dialog width: pToolBar->CalcDynamicLayout( -1, LM_HORZ | LM_HORZDOCK ); The toolbar should be created inside a container window that in turn is a child of the dialog window. This container window should always have the width computed as we described above. The returned CSize also contains the desired height of container window. So, the container window will have exactly the same size as its child CExtToolControlBar window and your code should implement a sliding/moving algorithm for this container as you need it.
|
|
marc uchida
|
Oct 16, 2007 - 12:33 PM
|
The first bit of info on my problem is that it only occurred after I updated to profuis 280 from 262. My app was working fine in 262.
I have a class whose base class is CExtTabMdiOneNoteWnd. It was created so that we could do something out of the ordinary with the tab mdi windows. We want to make certain tabs hide-able in some situations. This now leads to an Assertion failure in CExtTabWnd::AssertValid(), because m_nVisibleItemCount end up greater than nItemCount. In release build, the result is flashing windows, because they are being inserted and removed continuously. _SyncAllItems keeps trying to snyc the item and visibility counters, but it never can.
To solve the problem for now, we made a virtual function for _SyncAllItems so we could apply a change here in the logic. The change as follow....
ModifyTabWndStyle( bCloseEnabled ? 0 : __ETWS_ENABLED_BTN_CLOSE, bCloseEnabled ? __ETWS_ENABLED_BTN_CLOSE : 0, false ); INT nVisibleCount = 0; for( ; hWndMdiChild != NULL; hWndMdiChild = ::GetWindow( hWndMdiChild, GW_HWNDNEXT ) ) { // original code here: checking for visibility before checking for the handle !? // if( ( ::GetWindowLong( hWndMdiChild, GWL_STYLE ) & WS_VISIBLE ) != 0 ) // nVisibleCount ++; ///////////////////////////////////////////////////////////////////////////////////////
LONG nIndexExist = ItemFindByHWND( hWndMdiChild, -1, true, true ); if( nIndexExist >= 0 ) { // our solution to the flashing window problem... move above code down here. if( ( ::GetWindowLong( hWndMdiChild, GWL_STYLE ) & WS_VISIBLE ) != 0 ) nVisibleCount ++; ////////////////////////////////////////////////////////////////////////////////////////
if( hWndMdiChild == pWndActiveMdiChild->GetSafeHwnd() ) SelectionSet( nIndexExist, true, false ); continue; } ItemInsert( NULL, NULL, false, 0, -1, LPARAM( hWndMdiChild ), false );
My question to you then has several angles. .. 1. is this code change going to lead to other problems? It seems to work ok now. 2. is this change better in general? I ask because it seem funny to check for visibility before checking for the handle existence, rather than the other way around, as our changes do. If you are checking for the visibility of a window it must have a handle, no? 3. is there a better way around this problem?
any insight would be appreciated, thanks.
p.s. not looking forward to comparing our version of_SyncAllItems with yours every time we get an upgrade from you... the problems with overriding profuis functions. ;P
|
|
marc uchida
|
Oct 16, 2007 - 12:06 PM
|
The first bit of info on my problem is that it only occurred after I updated to profuis 280 from 262. My app was working fine in 262.
I have a tabbed page container (CExtTabPageContainerFlatWnd in this case) which sets the initial page on creation with PageSelectionSet(). Now when the user interacts with these tabbed pages, initially everything looks fine. One can choose any tab and the contents (controls) are working as expected. However, when I switch back to the tab that was initially set by PageSelectionSet(), it does not redraw the form contents. Worse yet, in debug mode, when you close the app it crashes while trying to destroy the form in CWnd::DestroyWindow(), called from CExtScrollWnd::~CExtScrollWnd() while doing PmBridge_Uninstall();
Ever hear about anything like this before? Suggestions?
p.s. of course if I do not call PageSelectionSet(x), the current page index will be set to 0, and that is the tabbed page that will have the problem.
thanks for your time
|
|
marc uchida
|
Oct 29, 2007 - 1:10 PM
|
I updated to v281, and the problem was resolved. thanks
|
|
Thomas Maurer
|
Oct 16, 2007 - 11:11 AM
|
Hello
I am programming an application that is working as an IE plugin as well as stand-alone.
Now when I set a push pin in my plugin the view next to the tool bar is supposed to be resized. This does not happen and I assume it is because the view was not created with AFX_IDW_PANE_FIRST as id. I am not doing this because this will cause an assertion in the OLE part of the plugin.
Is there a way to force a recalculation of the layout in my derived AutHideModeSet method that will affect my view?
Thanks in advance
Thomas
|
|
Technical Support
|
Nov 10, 2007 - 1:08 PM
|
The g_bEmbeddedMode is added for good.
|
|
Technical Support
|
Nov 6, 2007 - 1:56 PM
|
We guess you are talking about resizable control bars. Could you provide a screenshot and a step-by-step description about what we should do to reproduce the background problem? The child view window can be un-painted if itās not in the correct location inside the frame window. This can be checked by using the SPY++ utility. If our guess is correct, then you simply forgot to re-compute the layout of your embedded frame window at startup.
|
|
Thomas Maurer
|
Nov 7, 2007 - 11:27 PM
|
|
|
Thomas Maurer
|
Nov 8, 2007 - 3:45 AM
|
Hello
I found the solution myself: I did not install the correct paint manager in the in-place scenario. This also caused my "problems" with the status bar. I think and hope that I have solved all Prof-UIS related problems for my in-place version of the software.
Many many thanks for your support.
Thomas Maurer
P.S. You introduced a g_bEmbeddedMode variable into one of your classes. Will you introduce that into the product or will that remain a "Thomas specific" feature?
|
|
Thomas Maurer
|
Nov 6, 2007 - 2:40 AM
|
Hello
Many thanks for your (as always) great support. My in-place application is getting better and better.
Sorry to ask two more questions:
1) When I integrate your code into my "real" project the CChildView is not painted the first time it is displayed. I can easily make an UpdateWindow but the question is where should I do that. Is there some location that is called only once and only when all bars are correctly positioned?
2) I asked that before and I might have overlooked the answer: When the toolbars on the left are collapsed/unpinned the bar on the left side has a white background (apart from the tabs). How can I set this to gray? Some WM_ERASEBKGND or some window style at the right place?
Thanks again
Thomas
|
|
Thomas Maurer
|
Nov 4, 2007 - 11:33 PM
|
Hello
Thanks a lot for your modified solution. This is much better!!!
There are a few problems remaining which I would be glad you could help with:
- When a pinned toolbar on the left side is unpinned the toolbar is not collapsed when the main view gets the focus. It just stays where it was. There has to be some other event to trigger the collapsing. Can something be done about that?
- When the toolbars on the left side are collapsed they will only fly out when you open one of the toolbar’s menus. They are not flying out when you just click on one of them. This might have someting to do with the point above.
- The menus on the toolbars are reduced to what has recently been selected so when you open them the first time you only see the "down arrows". How can I make the menu display its whole content always (not depending on what was recently selected)?
- When the toolbars on the left side are collapsed the background of the toolbar is white and not gray. How can I achieve that it becomes gray?
- This is a MFC question I guess and maybe it does not have anything to do with Prof-UIS. Maybe you can help anyways: When I create the status bar in the in-place scenario it has this gripper on the bottom right which allows resizing of the status bar. This comes from not having the SBT_NOBORDERS style (according to Spy++). In my non-in-place mainframe I create the statusbar in an identical way and it does get that style.
Many thanks in advance
Thomas
|
|
Technical Support
|
Nov 5, 2007 - 9:22 AM
|
We found out that the auto-hide areas with grouped tabs not always can determine that the IE window is active. So to meet the requirements described in your first two questions requires Prof-UIS to be modified. We added a g_bEmbeddedMode public static property in the CExtDynAutoHideArea class: static bool g_bEmbeddedMode; We also set its initial value to false and modified the beginning of the CExtDynAutoHideArea::_CanActivate() method: bool CExtDynAutoHideArea::g_bEmbeddedMode = false;
bool CExtDynAutoHideArea::_CanActivate()
{
if( g_bEmbeddedMode ) // THIS LINE WAS ADDED
return true; // THIS LINE WAS ADDED
if( ( ! CExtPopupMenuWnd::TestHoverEnabledFromActiveHWND( GetSafeHwnd() ) )
&& ( ! m_bInsertMode )
)
return false;
. . . Then we set this property to true in the CVEViewApp::InitInstance() (in your project) if (this->RunEmbedded())
{
CExtDynAutoHideArea::g_bEmbeddedMode = true; // THIS LINE WAS ADDED
AfxMessageBox(_T("Embedded"));
COleHandler::RunEmbedded(&m_oleserver);
return TRUE;
} These two modifications should solve the problem with the auto-hide feature for control bars embedded in IE. We added the following two lines in the constructor of the application class to make all the menus initially expanded and always displaying all its menu items CExtPopupMenuWnd::g_bMenuExpanding = false;
CExtPopupMenuWnd::g_bMenuHighlightRarely = false; Your last question is really more MFC-related than Prof-UIS-related because the CExtStatusControlBar class from Prof-UIS is simply a re-painted version of the MFC’s CExtControlBar . The CExtStatusControlBar class does not compute any layout of the parts of the status bar: it simply paints the status bar items and the gripper through the paint manager’s calls. It looks like the status bar common control constantly reserves some space for the gripper. Anyway we solved this problem in scope of your project by adding the ID_STATUSBAR_LAST_EMPTY_INDICATOR status pane as the last status pane with empty text. Here is the new version of your project.
|
|
Technical Support
|
Nov 1, 2007 - 8:28 AM
|
Please download a modified version of your application. The most important improvements are marked with PROF-UIS TECH SUPPORT. Generally, the embedded child view was incorrectly repositioned in your code. Some window classes were incorrect what generated flickering while resizing the embedded frame. All the control bar handles were attached to command managerās profile to let toolbars display their icons while floating. All the frame/view windows were made clipping siblings/children to remove flickering while resizing the embedded frame. Please check this project and let us know if we missed something.
|
|
Technical Support
|
Oct 30, 2007 - 2:56 PM
|
The new registry files allow us to run your test project embedded in embedded mode. Please give us one more day so we can play with your project.
|
|
Technical Support
|
Oct 29, 2007 - 1:02 PM
|
We can compile and run the application, but we cannot embed it into IE. We have tried both the registration ways but in any case IE opens a file in the popup frame of your application rather than in the OLE embedded in-place frame. Could you try to do the same on a clean computer? We tested this with IE 6 on Windows XP SP2?
|
|
Thomas Maurer
|
Oct 30, 2007 - 1:03 AM
|
Hello
A most strange thing happened (which I am afradi I must solve properly when the software goes into production).
First the same happened at my computer = the program started outside IE. For testing I then started Word and I inserted an object of my "VEView AFP Document" class. This worked fine. When you activate the object you see my view. I think this is a good test to see if everything is registered properly for basic in-place activation.
After checking the internet I came across the following:
In HKEY_LOCAL_MACHINE\SOFTWARE\Classes\VEView.AFPDocument add the following DWORD value: "BrowserFlags".
Now the problem is what value to set it to. I didn’t read the kb article properly and set the value to 8. This means open the program in a separate window which it did but not with the usual frame but just a simple frame around the view.
I then read a little more and set the value to 1: same effect.
Then I set the value to 0: It worked!!!
Then I removed the BrowserFlags value altogether and it still worked!!! (and ???).
So I guess something caused IE to change its general behaviour.
HINT: Could you please set the BrowserFlags value to 0 at the beginning and see if it works? If it does that would make my life easier because I just set this registry value upon installation when we go into prodcution. If this doesn’t work you can still set the value to 8 (and if necessary to 1) and then back to 0. Of course you must open the test document via IE after changing the value.
FURTHER PROBLEMS:
1) I noticed that the toolbars - once unpinned - don’t close right away. Is that also due to lacking idle processing?
2) Reopening them once they are unpinned and closed often only works by pressing the right mouse key on them. Same problem?
Thanks in advance
Thomas
|
|
Thomas Maurer
|
Oct 30, 2007 - 1:07 AM
|
My post above sounds as if I had done that on my development computer but I did these steps on a clean machine as you suggested.
When I did this yesterday I remember I must have done something similar on my development computer a 2 months ago. But since I removed "BrowserFlags" from the registry again I did not see any traces anymore.
T.M.
|
|
Thomas Maurer
|
Oct 30, 2007 - 10:20 AM
|
Hello
My post from Oct 30, 1:03AM contains two things:
- How to register my program - A few additional problems I found when using it as a plugin
=== How to register my program ===
What I wrote in my former e-mail was true for Windows 2000. For Windows XP this did not work. Please do the following for XP (maybe also for W2K, did not test yet)
- download http://download.ierax.ch/Prof-UISRegistry.zip - adjust paths in reg files (only document.reg has changed) - register files
Now it should work without any other operation necessary.
=== Additional problems ===
The additional problems in my post from 1:03AM are still valid and I would be glad if you could take a look.
=== Comments for registration (if you are interested, not really relevant anymore) ===
I spent a few hours searching for this problem on the internet and nobody had a real answer. Not even Microsoft. I googled articles and newsgroups. At a certain point I decided to check with regmon what registry keys and values IE is checking and I came across a value named "BrowseInPlace". When I added that to my document class everything was fine. You can not find one single entry on microsoft.com about that. This solution works for IE6 and XP. Let’s hope it is the key to success for W2K and IE7 as well!
|
|
Thomas Maurer
|
Oct 26, 2007 - 8:54 AM
|
Hello I have prepared a stripped version of our Software which you can download at:
http://download.ierax.ch/VEViewProfUIS.zip
In the Zipfile there are instructions too how to register the IE plugin.
Now you can see all problems live in the IE plugin.
|
|
Thomas Maurer
|
Oct 23, 2007 - 5:02 PM
|
Hello
http://download.ierax.ch/afterbeginning.jpg
Above link shows the IE upon startup. The document mode is set to page width = the document should occupy the whole width. You see that you can not really distinguish where the document ends and where the bar ends. The status bar looks strange too.
http://download.ierax.ch/closingbar.jpg
Above link shows the bar closed and the document is displayed properly.
http://download.ierax.ch/afteropeningagain.jpg
Above link shows the bar with push pin set again. Now the document is correct.
I accomplished this by deriving RecalcLayout with the following method (4711 is the id of the view)
void CViewFrameInPlace::RecalcLayout(BOOL bNotify) { __super::RecalcLayout(bNotify); this->RepositionBars(0,65535,4711); }
Let me know if I can help more
Thomas
|
|
Technical Support
|
Oct 24, 2007 - 6:36 AM
|
You have correctly implemented the RecalcLayout() virtual method but the real problem is that your IE extension is an MFC kind of project which does not control threadās message loop like MFC EXE applications do. The frame window layout re-calculation can be delayed by control bars inside this frame and the real layout re-calculation will be performed when the frame window reaches the idle state. This is detected automatically by the message loop processing code implemented in the CWinThread /CWinApp classes. In the case of COM objects like IE extensions, you should track some timer inside the frame window and implement idle time processing in it. This timer should have a 100ms period and its handler code should be as follows: CWinThread * pWinThread = ::AfxGetThread();
ASSERT_VALID( pWinThread );
pWinThread->OnIdle(0); Could you provide more details about project type which implements the IE embeddable UI?
|
|
Technical Support
|
Oct 23, 2007 - 3:10 PM
|
Could you send us a screenshot demonstrating the incorrect view position when the button is clicked?
|
|
Thomas Maurer
|
Oct 23, 2007 - 7:30 AM
|
I have solved this problem myself in the meantime by deriving RecalcLayout. I do not have the code here at the moment but will gladly provide it if you want it.
And yet, not all is working properly: When the push pin is set from the beginning the underlying view will not be resized accordingly but only when you release the push pin the view is adjusted. When you set the push pin again it works fine. Do you know what I could do to trigger the view size calculation from the beginning?
I think I would be able to construct an equivalent test project but it would take some time I guess.
|
|
Technical Support
|
Oct 22, 2007 - 12:43 PM
|
We are sorry for the delay with this reply. Would you send us a test project that implements a UI similar to that in your real project and embeds itself into the IE frame? That would allow us to help you more efficiently.
|
|
Bangjun Lei
|
Oct 16, 2007 - 11:05 AM
|
Dear Sir./Madam.,
I try to use RowAdd to add a row, but it doesn’t succeed. I try to use RowRemove to remove a row, an alert in CExtTreeGridDataProvider::RowRemove prevents me from doing this.
However, I found out that I can use ReportItemRegister() to add a row.
How can this happen?
Thanks!
|
|
Technical Support
|
Oct 16, 2007 - 12:30 PM
|
You should use the CExtReportGridWnd::ReportItemRegister() method instead of RowAdd() .
|
|
Bangjun Lei
|
Oct 16, 2007 - 10:46 AM
|
Dear Sir./Madam.,
I tried to use RowRemove of CExtReportGridWnd but an alert in CExtTreeGridDataProvider::RowRemove jumps out saying that this function cannot be used. What should I do then?
Thanks!
|
|
Technical Support
|
Oct 16, 2007 - 12:17 PM
|
You should not use CExtGridWnd::RowRemove() and CExtGridWnd::RowRemoveAll() in conjunction with the CExtReportGridWnd class. You can remove all the report grid items (rows) using the following code CExtReportGridWnd * pReportGrid = . . .
LONG nColCount = pReportGrid->ColumnCountGet();
LONG nRowCount = pReportGrid->RowCountGet();
if( nRowCount == 0 || nColCount == 0 )
return;
pReportGrid->SelectionUnset( false, false );
pReportGrid->SelectionInsertAt( 0, CRect( 0, 0, nColCount - 1, nRowCount - 1 ), false );
pReportGrid->ReportItemUnRegisterSelection(); The following code allows you to remove only a particular report grid item CExtReportGridWnd * pReportGrid = . . .
CExtReportGridItem * pRGI = . . .
VERIFY( pReportGrid->ReportItemUnRegister( pRGI ) );
|
|
Bangjun Lei
|
Oct 16, 2007 - 9:31 AM
|
Dear Sir./Madam.,
What reason might cause that I cannot edit the text field in my grid when I double click on it?
Thanks!
|
|
Bangjun Lei
|
Oct 16, 2007 - 10:07 AM
|
|
|
Bangjun Lei
|
Oct 16, 2007 - 8:05 AM
|
Dear Sir./Madam.,
Can you teach me how to select a row in the grid using instructions but not mouse click?
Thanks!
|
|
Bangjun Lei
|
Oct 16, 2007 - 8:06 AM
|
In the above situation I only know the row index.
|
|
Suhai Gyorgy
|
Oct 16, 2007 - 8:35 AM
|
Support’s answer: <<<<<<<<<<<<<<<<< Just use the CExtGridBaseWnd::SelectionSet() method CPoint ptSelection( 0, nRowNo );
SelectionSet( ptSelection );
In the full row mode, the column number will simply be ignored. >>>>>>>>>>>>>>>>> But personally I prefer FocusSet(CPoint(0, nRowNo)) as one of its default parameters indicates to set the selection along with the focus. If you don’t use full row mode, you need to use SelectionSet(CRect(0, nRowNo, ColumnCountGet() - 1, nRowNo));
|
|
Offer Har
|
Oct 16, 2007 - 6:41 AM
|
Dear Support,
I need to change the color of the grid’s tool-tip’s background color - Please advise as to how this could be done.
Regards, Ron.
|
|
Technical Support
|
Oct 16, 2007 - 12:39 PM
|
Although this feature is not supported, but it can be implemented in quite a simple way.
1) Create a CExtPopupMenuTipWnd -derived class and override the CExtPopupMenuTipWnd::_DoPaint() virtual method. Copy the method body from the base class and modify the code that sets the background color. 2) Override the CExtGridBaseWnd::OnAdvancedPopupMenuTipWndGet() virtual method in your grid and return a pointer to your CExtPopupMenuTipWnd object.
Still we can regard your question as a feature request. We could add the SetBkColor() /GetBkColor() and SetTextColor() /GetTextColor() methods in the CExtPopupMenuTipWnd class so you can use these methods instead of overriding the _DoPaint() method. What do you think about this?
|
|
Offer Har
|
Oct 16, 2007 - 2:36 PM
|
Dear Support,
For the time being I chose a simpler solution, by changing the default color for all the tool-tips by setting m_colors[COLOR_INFOBK] , as your suggested solution will consume too much time, which I am lacking right now.
Your suggestion sound as the way to go. Please let me know when this feature is implemented.
P.S. still waiting for the excel-type tool-tips for the grid...
Regards, Ron.
|
|
Pierre MEDART
|
Oct 16, 2007 - 4:14 AM
|
We are using CExtTabMdiWhidbeyWnd to display our Views.
We are facing an issue because in the OnActivateView the p_OurView->IsWindowVisible() always return false.
This is annoying because previously we did some synchronization with other part of our UI that are no longer done.
No code was changed at the view level. Does the CExtTabMdiWhidbeyWnd change this behaviour? If so, can we change it ?
void COurView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView) {
if (bActivate && pActivateView && pActivateView->IsWindowVisible()) { Synchronize(); } CBaseClassVIew::OnActivateView(bActivate, pActivateView, pDeactiveView); }
|
|
Technical Support
|
Oct 16, 2007 - 12:26 PM
|
Could you send us this test MDI application with instructions how we can see the incorrect behavior so we can find out whatās wrong?
|
|
Pierre MEDART
|
Oct 16, 2007 - 8:03 AM
|
The issue is that I, me as a user, can see the window associated with this view. (nothing is on the way...)
I made a small MFC mdi application, the behaviour is still the same. It really seems that holding the VIew in the MdiTab changes the IsWindowVisible()
|
|
Technical Support
|
Oct 16, 2007 - 7:07 AM
|
The IsWindowVisible() API can return FALSE even if the window has the WS_VISIBLE style, but it is completely covered by other window(s). We think you should simply use the bActivate flag parameter and invoke Synchronize() if bActivate!=FALSE .
|
|
Pierre MEDART
|
Oct 16, 2007 - 4:14 AM
|
We are using CExtTabMdiWhidbeyWnd to display our Views.
We are facing an issue because in the OnActivateView the p_OurView->IsWindowVisible() always return false.
This is annoying because previously we did some synchronization with other part of our UI that are no longer done.
No code was changed at the view level. Does the CExtTabMdiWhidbeyWnd change this behaviour? If so, can we change it ?
void COurView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView) {
if (bActivate && pActivateView && pActivateView->IsWindowVisible()) { Synchronize(); } CBaseClassVIew::OnActivateView(bActivate, pActivateView, pDeactiveView); }
|
|
Bangjun Lei
|
Oct 15, 2007 - 2:14 PM
|
Dear Sir./Madam.,
I created a CExtReportGridWnd in my program. Now I want to carry out some actions on it. Could you teach me? 1. Every time when I click the header the header reacts by being pressed down and showing a dialog saying "You cannot sort ..column." How to prevent any actions from happening when clicking at the header? 2. I want to process the message when the user clicks a cell. How to do this?
Thanks!
|
|
Suhai Gyorgy
|
Oct 16, 2007 - 2:17 AM
|
1. By default, users can sort and group a reportgrid by every column. You can disable this column by column, with the following code:
CExtReportGridColumn * pRGC = ...; pRGC->GroupingEnabledSet( false ); pRGC->SortingEnabledSet( false ); If you don’t want to see the above mentioned message popping up, you need to override CExtReportGridWnd::OnReportGridSortOrderVerificationFailed method and leave its body empty. 2. Override OnGbwAnalyzeCellMouseClickEvent method of Reportgrid. It is called every time any of the mouse buttons is clicked over the grid. Testing its parameters can tell you which mouse button was clicked, how many times (doubleclick), and whether it was clicked over a cell or not. Check Out Help on this method to find out more.
|
|
Bangjun Lei
|
Oct 15, 2007 - 6:42 AM
|
Dear Sir./Madam.,
I’m using LoadBMP_Resource to load an icon resource into my program. It always fails (at FindResource in CExtResourceManager::FindResourceHandle). However, I can use theApp.LoadIcon to load it. What is the problem here? What should I do then?
Thanks!
|
|
Technical Support
|
Oct 15, 2007 - 8:28 AM
|
|
|
Bangjun Lei
|
Oct 15, 2007 - 9:11 AM
|
Thanks! But I’m loading an Icon of myself. It sits in my resource file.
|
|
Christophe Guibert
|
Oct 14, 2007 - 3:31 PM
|
Dear Support,
I use a CExtGridCellCheckListComboBox derived class in a grid to allow multiple selection.
In your ProfUIS_Controls sample, Grid tab, CheckComboBox column (6th) , I would like to type new values (separated by ; delimitor) and add them to the current list of values, but the editable field is emptied when I leave it and none of the new values are added to the list.
Worse, in the first row, I select two items (for instance Windows 98 and Windows 2000), they are displayed as "Windows 98; Windows 2000" in the cell. Then I click to activate the in-place editor and set the insertion point anywhere in the string, BUT DO NOT TYPE ANYTHING : just a click. When leaving the in-place editor, only "Windows 2000", the last value, is kept. (possible bug ?).
I used a derived class where the OnInplaceControlTextInputComplete() method was overriden and added a piece of code to extract the values between the delimitors in the new text, add them to the Cell and Check them :
if( bSaveChanges
&& _tcscmp( LPCTSTR(sText), LPCTSTR(sTextNew) ) != 0
)
{
CStringList list;
CString separator = _T(";");
CString str(sTextNew);
::ExplodeWords(str, &list, separator, TRUE); // parsing the new text
for (POSITION pos = list.GetHeadPosition(); pos != NULL ; )
{
CString val = list.GetNext(pos);
int index = FindStringExact(val);
if (index < 0)
{
// new value : add it
int idx = AddString(val);
ItemCheckSet(idx, 1);
}
else
{
ItemCheckSet(index, 1);
}
}
list.RemoveAll();
TextSet(sTextNew);
...
It almost works : - the new values that were typed in the in-place editor are added (they weren’t before), - but only the last one is checked (although all calls to ItemCheckSet returned 1), - the Cell displays only the last one (like in the ProfUIS_Controls sample).
Could you say if I miss something, if there’s a bug, or both ?
Best Regards,
Christophe Guibert
|
|
Technical Support
|
Oct 16, 2007 - 5:29 AM
|
We completely agree with you. Thank you. In the bug fix the following line strWalk1 += ( nLenSep * sizeof(TCHAR) ); in fact should be strWalk1 += nLenSep;
|
|
Technical Support
|
Oct 15, 2007 - 1:10 PM
|
Thank you for reporting this bug. Below is the bug fix. void CExtGridCellCheckListComboBox::TextSet(
__EXT_MFC_SAFE_LPCTSTR str, // = __EXT_MFC_SAFE_LPCTSTR(NULL) // empty text
bool bAllowChangeDataType // = false
)
{
ASSERT_VALID( this );
bAllowChangeDataType;
ItemCheckAll( 0 );
CExtSafeString strListSeparator;
OnQueryListSeparator( strListSeparator );
INT nLenSep = INT(_tcslen(strListSeparator));
LPCTSTR strWalk = str;
LPCTSTR strWalk1 = NULL;
while( true )
{
strWalk1 = _tcsstr( strWalk, strListSeparator );
LONG nBufferLen = 0L;
if( strWalk1 != NULL )
nBufferLen = ( LONG(strWalk1) - LONG(strWalk) ) / sizeof(TCHAR);
else
nBufferLen = INT( _tcslen( strWalk ) );
ASSERT( nBufferLen >= 0 );
LONG nBufferSize = ( nBufferLen + 1 ) * sizeof(TCHAR);
TCHAR * lpstrBuffer = new TCHAR[ nBufferSize ];
ASSERT( lpstrBuffer != NULL );
::memset( lpstrBuffer, 0, nBufferSize );
__EXT_MFC_STRNCPY( lpstrBuffer, nBufferLen + 1, strWalk, nBufferLen );
CExtSafeString sBuffer( lpstrBuffer );
sBuffer.TrimLeft( _T(" ") );
sBuffer.TrimRight( _T(" ") );
LONG nItem = FindStringExact( sBuffer );
if( nItem >= 0L )
ItemCheckSet( nItem, 1 );
delete [] lpstrBuffer;
lpstrBuffer = NULL;
if( strWalk1 == NULL )
break;
strWalk1 += ( nLenSep * sizeof(TCHAR) );
strWalk = strWalk1;
}
}
|
|
Christophe Guibert
|
Oct 15, 2007 - 3:22 PM
|
I thank you for the prompt response, which makes the sample work properly, and my application better, but not completely : some characters are lost in Unicode build.
I suppose that the
strWalk1 += ( nLenSep * sizeof(TCHAR) );
should be replaced by
strWalk1 += nLenSep;
as it was before, because the += operator should deal with Unicode char width.
I propose the code below, which finally works and adds items in the list if the user types new ones with delimitors. Of course, it should be adapted to wider situations, but this is what I needed and is consistent wih editable combo boxes.
void CMyDerivedCheckListComboCell::TextSet(
__EXT_MFC_SAFE_LPCTSTR str, // = __EXT_MFC_SAFE_LPCTSTR(NULL) // empty text
bool bAllowChangeDataType // = false
)
{
ASSERT_VALID( this );
bAllowChangeDataType;
ItemCheckAll( 0 );
CExtSafeString strListSeparator;
OnQueryListSeparator( strListSeparator );
INT nLenSep = INT(_tcslen(strListSeparator));
LPCTSTR strWalk = str;
LPCTSTR strWalk1 = NULL;
while( true )
{
strWalk1 = _tcsstr( strWalk, strListSeparator );
LONG nBufferLen = 0L;
if( strWalk1 != NULL )
nBufferLen = ( LONG(strWalk1) - LONG(strWalk) ) / sizeof(TCHAR);
else
nBufferLen = INT( _tcslen( strWalk ) );
ASSERT( nBufferLen >= 0 );
LONG nBufferSize = ( nBufferLen + 1 ) * sizeof(TCHAR);
TCHAR * lpstrBuffer = new TCHAR[ nBufferSize ];
ASSERT( lpstrBuffer != NULL );
::memset( lpstrBuffer, 0, nBufferSize );
__EXT_MFC_STRNCPY( lpstrBuffer, nBufferLen + 1, strWalk, nBufferLen );
CExtSafeString sBuffer( lpstrBuffer );
sBuffer.TrimLeft( _T(" ") );
sBuffer.TrimRight( _T(" ") );
LONG nItem = FindStringExact( sBuffer );
if( nItem >= 0L )
ItemCheckSet( nItem, 1 );
// Modification - chr
else
{
// new item : add it
if (sBuffer != _T(""))
{
LONG nNew = AddString( sBuffer );
if( nNew >= 0L )
ItemCheckSet( nNew, 1 );
}
}
// End of modification - chr
delete [] lpstrBuffer;
lpstrBuffer = NULL;
if( strWalk1 == NULL )
break;
strWalk1 += ( nLenSep ); //* sizeof(TCHAR) );
strWalk = strWalk1;
}
}
Best Regards,
Christophe Guibert
|
|
Technical Support
|
Oct 15, 2007 - 8:37 AM
|
Unfortunately we cannot reproduce the problem with showing only the last checked item in the cell. Would you create and send us some test project (or change the Prof-UIS_Controls sample) in a way that demonstrates the problem?
|
|
Christophe Guibert
|
Oct 15, 2007 - 11:31 AM
|
I discovered that the Prof-UIS_Controls sample behaves properly in MBCS version, but NOT in Unicode version. So what I described earlier still applies to this version.
So you could try with Unicode : I suspect your parsing code for delimited text in the CExtGridCellCheckListComboBox implementation.
Hoping it will help,
Best Regards,
Christophe Guibert
|
|
Bangjun Lei
|
Oct 14, 2007 - 7:23 AM
|
Dear Sir./Madam.,
I want to add language switch into my dialog system that also has a menu (in the form of menubar) associated with it. Could you instruct me how to do this? The LanguageSwitch sample is based on SDI application and a bit difficult to figure out what should I do for dialog-based systems.
Thanks!
|
|
Technical Support
|
Oct 15, 2007 - 1:48 PM
|
In Prof-UIS uses there is a CExtResourceManager class (that is accessible via the g_ResourceManager global smart pointer variable) and this class is used for loading resources of any type instead using Win32 APIs and methods of MFC classes. This makes possible to specify the preferred language identifier for loading resources using the following code: g_ResourceManager->AllowCustomLang( true );
g_ResourceManager->SetLangIdDesired( nLangID ); with nLangID set to one of the __EXT_MFC_LANG_ID_*** constants defined in the ../Prof-UIS/Include/ExtCmdManager.h file. After invoking the code lines above, all the resource loading invocations will be searching for and loading the resources of the specified language. That means you should re-initialize the entire UI in your application: re-load toolbars, menus, cached string variables and re-create dialogs. To re-create dialogs is essential because dialog template resources can be different for different languages.
|
|
Bangjun Lei
|
Oct 14, 2007 - 7:20 AM
|
What are the actual differences between those two? I saw different applications use one or the other at the same place.
|
|
Technical Support
|
Oct 15, 2007 - 7:16 AM
|
Actually there are no differences. You can either define some constant like __PROF_UIS_PROJECT_CMD_PROFILE_NAME with the profile name and use it everywhere where it is needed or initialize the m_pszProfileName variable at the application startup and use it in the same way.
|
|
Roongrit Charoensupkul
|
Oct 14, 2007 - 2:39 AM
|
I’m implementing a property dialog following CPageGrid::_InitColumnComboBox(...) method in ProfUIS_Controls example. I can create a combo box on runtime and set the list of option for it. However, when user click on the cell, the edit control show up and enable user to modify the string option. I don’t want to let the user be able to modify the string option, what should I do?
|
|
Technical Support
|
Oct 15, 2007 - 8:28 AM
|
The in-place editor window for a particular grid cell will not be activated if you modify the cell styles in this way pCell->ModifyStyle( __EGCS_NO_INPLACE_CONTROL );
|
|
Bangjun Lei
|
Oct 13, 2007 - 2:30 PM
|
Hello,
I tried to run the LanguageSwitcher sample (Static unicode release). But when I change the language, the frontal view doesn’t change accordingly, only the menu, toolbar, and all later popup dialogs change. What’s wrong here?
Thanks!
|
|
Technical Support
|
Oct 15, 2007 - 1:42 PM
|
In the LanguageSwitcher sample, the dialog view window is simply not recreated after switching the language identifier. This is not a bug. This is by design so you can see this dialog with the same language as the default locale of your Windows OS.
|
|
David Skok
|
Oct 12, 2007 - 12:01 PM
|
I extended your join sample to join 3 cells. I works however if the right side of the grid is scrolled within the boundary of the second cell of the join the size is adjusted back into individual cells. I have sent a sample that shows the problem.
Please take a look and recommend a fix.
Thanks, Dave
|
|
David Skok
|
Oct 11, 2007 - 9:59 AM
|
I tested my app on win98 and discovered that the text in control bar tabs docked on the left or right side is actually painted horizontally rather than vertically as it should. As a result you only see at most the first letter of the text. This is also exhibited in the MDI_DynamicBars sample by collapsing a control bar that is docked on the left or right side and looking at what is painted in the tab representing the control bar.
|
|
Technical Support
|
Oct 16, 2007 - 12:24 PM
|
We are sorry for the delay with this reply. Thank you for reporting this issue. Please update the source code for the following two methods: void CExtTabWnd::_GetTabWndFont(
CFont * pFont,
bool bSelected,
DWORD dwOrientation // = DWORD(-1) // default orientation
) const
{
ASSERT_VALID( this );
if( dwOrientation == DWORD(-1) )
dwOrientation = OrientationGet();
CExtPaintManager * pPM = PmBridge_GetPM();
ASSERT_VALID( pPM );
bool bBold =
( bSelected && SelectionBoldGet() )
? true
: false
;
CFont * pSrcFont = NULL;
if( dwOrientation == __ETWS_ORIENT_TOP
|| dwOrientation == __ETWS_ORIENT_BOTTOM
)
pSrcFont =
bBold
? (&pPM->m_FontBold)
: (&pPM->m_FontNormal)
;
else
if( GetTabWndStyle() & __ETWS_INVERT_VERT_FONT )
pSrcFont =
bBold
? (&pPM->m_FontBoldVertX)
: (&pPM->m_FontNormalVertX)
;
else
pSrcFont =
bBold
? (&pPM->m_FontBoldVert)
: (&pPM->m_FontNormalVert)
;
ASSERT( pSrcFont != NULL );
ASSERT( pSrcFont->GetSafeHandle() != NULL );
LOGFONT _lf;
::memset( &_lf, 0, sizeof(LOGFONT) );
pSrcFont->GetLogFont( &_lf );
if( pFont->GetSafeHandle() != NULL )
pFont->DeleteObject();
pFont->CreateFontIndirect( &_lf );
}
void CExtPaintManager::stat_PaintTabItemImpl(
CDC & dc,
CRect & rcTabItemsArea,
bool bTopLeft,
bool bHorz,
bool bSelected,
bool bEnabled,
bool bCenteredText,
bool bGroupedMode,
bool bInGroupActive,
bool bInvertedVerticalMode,
bool bDrawIcon,
const CRect & rcEntireItem,
CSize sizeTextMeasured,
CFont * pFont,
__EXT_MFC_SAFE_LPCTSTR sText,
CExtCmdIcon * pIcon,
CExtCmdIcon * pIconTabItemCloseButton,
INT nPaintStateITICB,
CRect & rcTabItemCloseButton,
COLORREF clrText,
COLORREF clrTabBk,
COLORREF clrTabBorderLT,
COLORREF clrTabBorderRB,
COLORREF clrTabSeparator,
bool bEnableEndEllipsis, // = true
CObject * pHelperSrc // = NULL
)
{
ASSERT( dc.GetSafeHdc() != NULL );
pHelperSrc;
rcTabItemsArea;
sizeTextMeasured;
bInGroupActive;
CRect rcItem( rcEntireItem );
CRect rcTabSel( rcItem );
if( bGroupedMode )
{
CRect rcTabMargin( rcItem );
rcTabMargin.InflateRect(
0,
0,
bHorz ? 1 : 0,
bHorz ? 0 : 1
);
rcTabMargin.InflateRect(
bHorz ? 0 : 2,
bHorz ? 2 : 0
);
if( clrTabBk != COLORREF(-1L) )
dc.FillSolidRect(
&rcTabMargin,
clrTabBk
);
if( clrTabBorderLT != COLORREF(-1L)
&& clrTabBorderRB != COLORREF(-1L)
)
dc.Draw3dRect(
rcTabMargin,
clrTabBorderLT,
clrTabBorderRB
);
} // if( bGroupedMode )
else
{
if( bSelected )
{
rcTabSel.InflateRect(
bHorz ? __EXTTAB_SEPARATOR_DX : 0,
bHorz ? 0 : __EXTTAB_SEPARATOR_DY,
0,
0
);
CRect rcSetMargins(
( (!bHorz) && (!bTopLeft) ) ? 1 : 0,
( bHorz && (!bTopLeft) ) ? 1 : 0,
( (!bHorz) && bTopLeft ) ? 1 : 0,
( bHorz && bTopLeft ) ? 1 : 0
);
rcTabSel.InflateRect(
rcSetMargins.left,
rcSetMargins.top,
rcSetMargins.right,
rcSetMargins.bottom
);
if( clrTabBorderLT != COLORREF(-1L)
&& clrTabBorderRB != COLORREF(-1L)
)
{
CPen penTabBorderLT(PS_SOLID,1,clrTabBorderLT);
CPen penTabBorderRB(PS_SOLID,1,clrTabBorderRB);
if( bHorz )
{
if( bTopLeft )
{
CPen * pOldPen = dc.SelectObject( &penTabBorderLT );
dc.MoveTo( rcTabSel.left, rcTabSel.bottom );
dc.LineTo( rcTabSel.left, rcTabSel.top );
dc.LineTo( rcTabSel.right, rcTabSel.top );
dc.SelectObject( &penTabBorderRB );
dc.MoveTo( rcTabSel.right-1, rcTabSel.top );
dc.LineTo( rcTabSel.right-1, rcTabSel.bottom-1 );
dc.SelectObject( pOldPen );
}
else
{
CPen * pOldPen = dc.SelectObject( &penTabBorderLT );
dc.MoveTo( rcTabSel.left, rcTabSel.top-1 );
dc.LineTo( rcTabSel.left, rcTabSel.bottom );
dc.SelectObject( &penTabBorderRB );
dc.MoveTo( rcTabSel.left, rcTabSel.bottom-1 );
dc.LineTo( rcTabSel.right-1, rcTabSel.bottom-1 );
dc.LineTo( rcTabSel.right-1, rcTabSel.top-1 );
dc.SelectObject( pOldPen );
}
}
else
{
if( bTopLeft )
{
CPen * pOldPen = dc.SelectObject( &penTabBorderLT );
dc.MoveTo( rcTabSel.right-1, rcTabSel.top );
dc.LineTo( rcTabSel.left, rcTabSel.top );
dc.LineTo( rcTabSel.left, rcTabSel.bottom );
dc.SelectObject( &penTabBorderRB );
dc.MoveTo( rcTabSel.left, rcTabSel.bottom-1 );
dc.LineTo( rcTabSel.right-1, rcTabSel.bottom-1 );
dc.SelectObject( pOldPen );
}
else
{
CPen * pOldPen = dc.SelectObject( &penTabBorderLT );
dc.MoveTo( rcTabSel.left, rcTabSel.top );
dc.LineTo( rcTabSel.right, rcTabSel.top );
dc.SelectObject( &penTabBorderRB );
dc.MoveTo( rcTabSel.right-1, rcTabSel.top );
dc.LineTo( rcTabSel.right-1, rcTabSel.bottom-1 );
dc.LineTo( rcTabSel.left, rcTabSel.bottom-1 );
dc.SelectObject( pOldPen );
}
}
}
rcTabSel.DeflateRect(
(rcSetMargins.left == 0) ? 1 : 0,
(rcSetMargins.top == 0) ? 1 : 0,
(rcSetMargins.right == 0) ? 1 : 0,
(rcSetMargins.bottom == 0) ? 1 : 0
);
if( clrTabBk != COLORREF(-1L) )
dc.FillSolidRect( &rcTabSel, clrTabBk );
} // if( bSelected )
else
{
CRect rcSeparator( rcItem );
if( bHorz )
{
rcSeparator.left = rcSeparator.right - 1;
rcSeparator.DeflateRect( 0, __EXTTAB_SEPARATOR_GAP_HORZ );
}
else
{
rcSeparator.top = rcSeparator.bottom - 1;
rcSeparator.DeflateRect( __EXTTAB_SEPARATOR_GAP_VERT, 0 );
}
if( clrTabSeparator != COLORREF(-1L) )
dc.FillSolidRect( &rcSeparator, clrTabSeparator );
} // else from if( bSelected )
} // else from if( bGroupedMode )
rcItem.DeflateRect(
bHorz ? __EXTTAB_MARGIN_BORDER_HX : __EXTTAB_MARGIN_BORDER_VX,
bHorz ? __EXTTAB_MARGIN_BORDER_HY : __EXTTAB_MARGIN_BORDER_VY
);
CSize _sizeIcon( 0, 0 );
if( bDrawIcon )
{
_sizeIcon = pIcon->GetSize();
ASSERT( _sizeIcon.cx > 0 && _sizeIcon.cy > 0 );
} // if( bDrawIcon )
CExtSafeString sItemText( (sText == NULL) ? _T("") : sText );
// IMPORTANT: the rcText calculation fixed by Genka
CRect rcText(
rcItem.left
+ ( bHorz
? (_sizeIcon.cx +
((_sizeIcon.cx > 0) ? __EXTTAB_MARGIN_ICON2TEXT_X : 0)
)
: 0
),
rcItem.top
+ ( bHorz
? 0
: (_sizeIcon.cy +
((_sizeIcon.cy > 0) ? __EXTTAB_MARGIN_ICON2TEXT_Y : 0)
)
),
rcItem.right,
rcItem.bottom
);
if( !bHorz )
{
if( pIconTabItemCloseButton != NULL )
rcText.bottom = min( rcText.bottom, rcTabItemCloseButton.top );
int nWidth0 = rcText.Width();
int nWidth1 = rcItem.Width() + __EXTTAB_MARGIN_ICON2TEXT_X*2;
if( nWidth1 > nWidth0 )
{
if( bInvertedVerticalMode )
{
//rcText.right -= __EXTTAB_MARGIN_ICON2TEXT_X;
rcText.left = rcText.right - nWidth1;
} // if( bInvertedVerticalMode )
else
{
//rcText.left += __EXTTAB_MARGIN_ICON2TEXT_X;
rcText.right = rcText.left + nWidth1;
} // else from if( bInvertedVerticalMode )
} // if( nWidth1 > nWidth0 )
} // if( !bHorz )
else
{
if( pIconTabItemCloseButton != NULL )
rcText.right = min( rcText.right, rcTabItemCloseButton.left );
}
bool bDrawText = ( rcText.Width() > 0 && rcText.Height() > 0 ) ? true : false;
if( bDrawIcon )
{
INT nIconAlignment = __ALIGN_VERT_TOP;
if( (!bDrawText) && !( bGroupedMode && (!bInGroupActive) ) )
nIconAlignment |= __ALIGN_HORIZ_CENTER;
if( (bHorz && rcItem.Width() >= _sizeIcon.cx )
|| (!bHorz && rcItem.Height() >= _sizeIcon.cy)
)
{
g_PaintManager->PaintIcon(
dc,
bHorz,
pIcon,
rcItem,
false,
bEnabled,
false,
nIconAlignment
);
}
} // if( bDrawIcon )
if( bDrawText )
{ // if we have sense to paint text on tab item
ASSERT( pFont != NULL );
ASSERT( pFont->GetSafeHandle() != NULL );
COLORREF clrOldText = dc.SetTextColor( clrText );
INT nOldBkMode = dc.SetBkMode( TRANSPARENT );
CFont * pOldFont = dc.SelectObject( pFont );
if( ! bHorz )
{
if( bCenteredText )
{
UINT nOldTA = dc.SetTextAlign(
TA_CENTER | TA_BASELINE
);
rcText.OffsetRect(
bInvertedVerticalMode
? sizeTextMeasured.cy/2
: - sizeTextMeasured.cy/2
,
0
);
CPoint ptCenter = rcText.CenterPoint();
dc.ExtTextOut(
ptCenter.x,
ptCenter.y,
ETO_CLIPPED,
&rcText,
sItemText,
sItemText.GetLength(),
NULL
);
dc.SetTextAlign( nOldTA );
} // if( bCenteredText )
else
{
UINT nOldTA = dc.SetTextAlign(
TA_TOP | TA_BASELINE
);
rcText.OffsetRect(
bInvertedVerticalMode
? sizeTextMeasured.cy/2
: - sizeTextMeasured.cy/2
,
0
);
CPoint ptCenter = rcText.CenterPoint();
if( bInvertedVerticalMode )
ptCenter.y =
rcText.bottom - 4
- (rcText.Height() - sizeTextMeasured.cx)
;
else
ptCenter.y =
rcText.top + 4
;
dc.ExtTextOut(
ptCenter.x,
ptCenter.y,
ETO_CLIPPED,
&rcText,
sItemText,
sItemText.GetLength(),
NULL
);
dc.SetTextAlign( nOldTA );
} // else from if( bCenteredText )
} // if( ! bHorz )
else
{
UINT nFormat =
DT_SINGLELINE
| DT_VCENTER
| ( bEnableEndEllipsis ? (DT_END_ELLIPSIS) : 0 )
;
INT nTextLen = sItemText.GetLength();
if( bCenteredText )
{
CRect rcMeasure( 0, 0, 0, 0 );
dc.DrawText(
LPCTSTR(sItemText),
nTextLen,
rcMeasure,
DT_SINGLELINE|DT_LEFT|DT_TOP|DT_CALCRECT
);
INT nMeasuredWidth = rcMeasure.Width();
INT nTextAreaWidth = rcText.Width();
if( nTextAreaWidth < nMeasuredWidth )
bCenteredText = false;
}
if( bCenteredText )
nFormat |= DT_CENTER;
else
nFormat |= DT_LEFT;
dc.DrawText(
LPCTSTR(sItemText),
nTextLen,
rcText,
nFormat
);
} // else from if( ! bHorz )
dc.SelectObject( pOldFont );
dc.SetBkMode( nOldBkMode );
dc.SetTextColor( clrOldText );
} // if we have sense to paint text on tab item
if( pIconTabItemCloseButton != NULL )
{
ASSERT( ! pIconTabItemCloseButton->IsEmpty() );
if( dc.RectVisible( &rcTabItemCloseButton ) )
pIconTabItemCloseButton->Paint(
g_PaintManager.GetPM(),
dc.m_hDC,
rcTabItemCloseButton,
(CExtCmdIcon::e_paint_type_t)nPaintStateITICB
);
} // if( pIconTabItemCloseButton != NULL )
}
|