|
Something like:
SetSheetNumber(1,FALSE);
SetColWidth(0,0);
SetSheetNumber(0,TRUE);
Should do it - tested in response to a key while on sheet 0. Remember to set the sheet number back to the current one.
Don't think there's anything built in to do this, but you could probably implement something that takes an array of columns to show/hide that would operate on all sheets and return to the current one.
Tim
|
|
|
|
|
Has anyone implemented a go to first or last tab button for a CUGTab? It is annoying to have to scroll slowly through lots of tabs. Excel has this feature.
Thanks
allen
|
|
|
|
|
There's code in the Ultimate Toolbox's COXTabViewContainer (OXTabView.cpp) that could possibly be ported over to CUGTab - would be a bit of a project.
Alternatively, you could use the COXTabViewContainer from the Ultimate Toolbox and set up multiple grids each with their own tab.
Tim
|
|
|
|
|
Hi Tim
Thanks. I thought that might be the answer.
I've got a quite a large app built so changing it at this stage to put multiple grids in their own COXTabViewContainer tab isn't a possibility.
I did experiment with moving some of the code from OXTabView.cpp to CUGTab. I got the two scroll start/end buttons displaying on either side of the main scroll buttons easily enough. Unfortunately their style is different from the scroll buttons. It looks too odd to be acceptable.
I also had a tried using two CScrollBars, an inner one and an outer one, and then trying to draw vertical lines over the outer ones. This didn't work for me.
In the end I added two plain buttons either side of the CScrollBar. They are half the width of a scroll bar button. I think aesthetically it looks OK (shame I can't attach a pic). It isn't quite as intuitive as the buttons used in COXTabViewContainer but I think it is reasonably obvious what they are for.
If it you like a I can post my changes if you're interested in including them in the library. Otherwise I can revert my changes to CUGTab and implement them in a derived class (I want to keep my copy of the base library as in sync as possible with the offical release).
Regards
Allen
|
|
|
|
|
Thanks Allen
My first thought is that yes, let's add this feature to the tab class, but wonder if it would be possible to add a setting to toggle it - some folks might want to keep the old style.
Which I guess begs the question of a new derived class. Hmmm... I think I like the concept of integrating this into the existing class, as default, but perhaps with the option of turning it off. Hmmm...
In any case, feel free to post changes here if the size is not too big, and/or send me the file at tim@codeproject.com - would just appreciate some annotation in comments for less diffing.
And thanks again - will put this in the ever increasing pile for the next update.
Tim
|
|
|
|
|
Hi Tim
I have been delibrating on this one too since your reply.
I've come to the conclusion that we shouldn't add my changes to the base CUGTab class. Even though I think it looks fine and works well it still isn't the ideal solution. I don't think we should add any non-ideal code to the base library, especially if it can be implemented with inheritence.
The ideal solution would be the more usual arrows with a vertical bar. Due to time contraints with the project I am working on I'm going to go with my derived class. Hopefully if everything goes to schedule I can revisit this and perhaps come up with a better solution for addition to the library.
I'll include my derived class in a follow up post in case it is useful for anyone else. If you want you can include this alongside the main sources files in a later release.
Cheers
Allen
|
|
|
|
|
A CUGTab control class which provides scroll to first and last tab buttons
Header
#pragma once
#define UTABSCROLLSTARTBUTTONID 101
#define UTABSCROLLENDBUTTONID 102
class CUGTab2 : public CUGTab
{
public:
CUGTab2(void);
~CUGTab2(void);
afx_msg void OnPaint();
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnBnClickedScrollStart();
afx_msg void OnBnClickedScrollEnd();
DECLARE_MESSAGE_MAP()
protected:
CButton m_btnScrollStart;
CButton m_btnScrollEnd;
int m_scrollStartEndButtonWidth;
};
Source
#include "StdAfx.h"
#include "UGTab2.h"
CUGTab2::CUGTab2(void)
{
m_scrollStartEndButtonWidth = GetSystemMetrics(SM_CXHSCROLL) / 2;
m_scrollWidth += m_scrollStartEndButtonWidth * 2;
}
CUGTab2::~CUGTab2(void)
{
}
BEGIN_MESSAGE_MAP(CUGTab2, CUGTab)
ON_WM_PAINT()
ON_WM_CREATE()
ON_WM_SIZE()
ON_BN_CLICKED(UTABSCROLLSTARTBUTTONID, OnBnClickedScrollStart)
ON_BN_CLICKED(UTABSCROLLENDBUTTONID, OnBnClickedScrollEnd)
END_MESSAGE_MAP()
void CUGTab2::OnPaint()
{
if ( m_GI->m_paintMode == FALSE )
return;
CUGTab::OnPaint();
m_btnScrollStart.Invalidate();
m_btnScrollStart.UpdateWindow();
m_btnScrollEnd.Invalidate();
m_btnScrollEnd.UpdateWindow();
}
int CUGTab2::OnCreate( LPCREATESTRUCT lpCreateStruct )
{
if ( CUGTab::OnCreate( lpCreateStruct ) == -1 )
return -1;
CRect rect;
m_btnScrollStart.Create( _T(""), WS_CHILD|WS_VISIBLE, rect, this, UTABSCROLLSTARTBUTTONID );
m_btnScrollEnd.Create( _T(""), WS_CHILD|WS_VISIBLE, rect, this, UTABSCROLLENDBUTTONID );
return 0;
}
void CUGTab2::OnSize( UINT nType, int cx, int cy )
{
CWnd::OnSize( nType, cx, cy );
CRect rect;
GetClientRect( rect );
rect.top++;
rect.right = m_scrollStartEndButtonWidth;
m_btnScrollStart.MoveWindow( rect, TRUE );
rect.left = m_scrollStartEndButtonWidth;
rect.right = m_scrollWidth - m_scrollStartEndButtonWidth;
m_scroll.MoveWindow( rect, TRUE );
rect.left = m_scrollWidth - m_scrollStartEndButtonWidth;
rect.right = m_scrollWidth;
m_btnScrollEnd.MoveWindow( rect, TRUE );
AdjustScrollBars();
}
void CUGTab2::OnBnClickedScrollStart()
{
if (m_tabOffset != 0)
{
m_tabOffset = 0;
Invalidate();
}
}
void CUGTab2::OnBnClickedScrollEnd()
{
if (m_tabOffset != m_maxTabOffset)
{
m_tabOffset = m_maxTabOffset;
Invalidate();
}
}
Example Usage
void MyCug::OnSetup()
{
CUGTab2* pTab2 = new CUGTab2;
pTab2->Create( NULL, _T(""), WS_CHILD|WS_VISIBLE, CRect(0,0,0,0), this, IDCX_STANDARD_GRID_TAB);
SetNewTabClass(pTab2);
}
|
|
|
|
|
Thanks - I'll file this under Additions - would make a nice post on the update page with a little sample project.
Thanks again
Tim
|
|
|
|
|
I'll hold off on the sample project. It is likely I'll have the time to provide a better implementation (using owner draw buttons).
|
|
|
|
|
From the help doc,
Adding XP Themes support
To add basic XP Themes support to a new project, simply add the following line to the code, preferably in the constructor of the UGCtrl derived class for the project.
UGXPThemes:UseThemes(true);
And add the following line in a destructor, preferably for the main window of your project:
UGXPThemes::CleanUp();
So I did as follows:
MyCug::MyCug()
{
UGXPThemes::UseThemes(true);
}
MyCug::~MyCug()
{
UGXPThemes::CleanUp();
}
The result is very slow grid behaviour.
I don't see what I did wrong.
Please advise.
HR
|
|
|
|
|
Hello HR
Due to a problem commenting to your posting I've sent Tim a copy of some recent changes I made to the UGXPThemes implementation. Email me if you wish to get them directly - jerry (dot) evans (at) novadsp (dot) com - no spaces. My tweak certainly gave a performance boost, you may find it helpful.
HTH
Jerry
|
|
|
|
|
Tim,
The Excel demo does not display sheet tabs.
As such, it is confusing to determine how to
include other sheets. I know the sheetnumber()
method iterates through "m_GIList[index]" to
display the sheets.
How was the first sheet added to the m_GIList?
How do I add more sheets to the m_GIList ?
Thanks,
-jc
|
|
|
|
|
Hi jc
Hmmm - could have sworn there was a 'Tabs and Sheets' demo, but no. Hmm.
Well, I think SetNumberSheets is the only way to add sheets. The usage intention was, I think, that sheets and their corresponding tabs would be set in OnSetup , and an OnSheetSetup callback was added for convenience.
But you can dynamically add sheets at runtime.
Lets say OnSetup has this:
SetNumberSheets(3);
AddTab(_T("Employees"), 0);
AddTab(_T("Movies"), 1);
AddTab(_T("Customers"), 2);
SetTabWidth(200);
SetSheetNumber(0,TRUE);
... and continues to setup the first sheet, then switch to the next and set that up, etc.
Notice that we're not using OnSheetSetup .
Usually, you'll have the following code in OnTabSelected to switch sheets:
void MyCug::OnTabSelected(int ID)
{
SetSheetNumber(ID,TRUE);
}
Now, if you want to add sheets at runtime, you can still do it:
m_pGrid->SetNumberSheets(4);
m_pGrid->AddTab(_T("Popcorn Boxes"), 3);
m_pGrid->RedrawAll();
You might also want to widen the tab area so that the new tab is visible, but as the user can change this that may require some fiddling. See m_GI->m_tabWidth .
In any case, the code in SetNumberSheets will recreate the grid info array and copy existing info from it into the new array, calling OnSheetSetup (which might be a problem if the user had changed things, as it would be called again) for each sheet.
So, though there's no AddSheet , InsertSheet , DeleteSheet (n), you can add or subtract sheets from the end of the list with SetNumberSheets . You'll need to decide how to handle the initial setup for each added sheet.
Room for improvement here, but that's what we seem to have available right now. Might be nicer to work with something like a vector<CUGGridInfo *> , but that would be a bit of code to write.
Tim
|
|
|
|
|
Hi Tim,
Thanks for the quick response.
I apologize, for the confusion.
I will try again, to explain the
information that I was looking for.
The first grid is always displayed MyCug1,
and is automatically connected to the first
tab.
How do I connect MyCug2 to the second tab?
Where do I include the second grid MyCug2,
which is completly different than MyCug1?
So, when I click the seond tab, it will
display the MyCug2, and not a "blank" screen.
Thanks,
-jc
|
|
|
|
|
Ah, ok - first thought, you could do it but it's not inherent in the design - the tabs as implemented use the same MyCug - you would have to switch in each callback on the current tab ID to change behavior to that extent.
I'd suggest having a look at the two tab view classes in the Ultimate Toolbox - check the 3DTabViews and TabViews samples in the samples/Gui dir.
If you like the look of the grid tabs, probably the TabViews class is the way to go - then each grid has it's own view. Should work nicely.
Tim
|
|
|
|
|
Hi Tim,
Finally, success!
The solution was actually very simple.
You probably suggested it, in one of your
previous posting, but I did not understand
your solution.
//code snippets
void MyCug::OnSetup()
{
SetNumberSheets(3);
//******* Add three New Tabs
AddTab(_T("Sheet 1"), 1); //cannot start with "0", subtracts 1 from the ID
AddTab(_T("Sheet 2"), 2);
AddTab(_T("Sheet 3"), 3);
//***** Set the Tab Width
SetTabWidth(200);
//***** Setup the first sheet
SetSheetNumber(0,TRUE);
void MyCug::OnSheetSetup(int sheetNumber)
{
switch (sheetNumber)
{
case 0: GridSetup1();
break;
case 1: GridSetup2();
break;
case 2: GridSetup3();
break;
}
void MyCug::GridSetup1()
{
SetNumberRows( 50 );
SetNumberCols(6);
SetColWidth(0,25); //checkbox column
SetColWidth(1,25); //checkbox column
SetColWidth(2,25); //checkbox column
SetColWidth(3,25); //category
SetColWidth(4,25); //No.
SetColWidth(5,540); //description
That's it!
I know, where a lot of my confusion came from.
The developer of the Excel demo placed all of
the "grid" code in the View class. I could'nt
understand how to support more than one tab using
that design. Once, I removed all of the grid code,
from the View class, and placed the code in the
MyCug class, things became a lot simpler.
Also, I was able to successfully build/execute the
Toolbox 3dTabview demo; however, I could not execute
the Toolbox Tabview sample. I tried setting a breakpoint
in the App constructor, but the program aborted before
reaching the breakpoint.
Thanks,
-jc
modified on Sunday, December 7, 2008 8:23 PM
|
|
|
|
|
Cool, all good for tabs then.
Tried running the TabViews sample on VS2008, and it's reporting a problem with the manifest file. After trying a full conversion from the VC6 project (and adding some missing files) same result, but setting the Generate Manifest item to No in the linker properties allowed the Release build to run.
Will have to check this again - is this the trouble you're having? You didn't mention an 'Unable to start' message.
Tim
|
|
|
|
|
Hi Tim,
Yes, that's exactly the problem that I was having.
I compared the property page of the 3dTabview and
the property page of the Tabview, and the property
pages looked the same.
-jc
|
|
|
|
|
Ok - looks like the manifest file that shipped
with the project has some problematic refs to VC8.
Open the TabViews.exe.manifest file (should be available in the
Source Files section of the Solution view) and remove the
following dependencies:
<dependency>
<dependentAssembly>
<assemblyIdentity type='win32' name='Microsoft.VC80.DebugCRT' version='8.0.50608.0' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' />
</dependentAssembly>
</dependency>
<dependency>
<dependentAssembly>
<assemblyIdentity type='win32' name='Microsoft.VC80.DebugMFC' version='8.0.50608.0' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' />
</dependentAssembly>
</dependency>
You may find that on run it complains about not being able
to find the MFC90xx.dll - this happens sometimes when
the .exe file is not being placed in the output directory -
for each build this should be edited in the Linker | General
settings to include $(OutDir)\ before the filename of the Output File.
Not sure that explains much in the 'why' category, but should help.
Tim
|
|
|
|
|
Tim,
I built/executed the demo "cell types" program,
and I reviewed the code about changing the
fonts.
However, when I tried using the" QuickSetFont() method,
in my application, I observed some strange behavior.
//code snippet
CFont noFont;
CFont boldFont,
boldFont.CreateFont( 14, 0, 0, 0, 900, 0, 0, 0, 0, 0, 0, 0, 0, _T( "Arial" ) );
QuickSetFont(yCol,xRow,&noFont)
QuickSetText(yCol,xRow,_T("No font created?"));
//The font is different than the "normal" font, but what font
//attributes are being used?
QuickSetFont(yCol,xRow,&boldFont)
QuickSetText(yCol,xRow,_T("Font created"));
//The font looks like the "noFont" ?
I made a few changes in my application, and it
appears that the font problem is related to
an "Excel" type grid and "themes".
Any suggestion, on what changes I should make,
to get the fonts to look like the fonts that
are being created?
Thanks,
-jc
modified on Saturday, December 6, 2008 3:09 PM
|
|
|
|
|
Hi Tim,
Once, we removed the grid code from the
View class, and placed the grid code into
MyCug class, the fonts now look like the
fonts that are being created.
We only have one remaining problem. In the
first grid (first tab), the grid lines are
visible, but in the other four grids the
grid lines are not visible.
For our application, it's not important if
the grid lines are visible or not. However,
all of the grids have to look consistent.
In other words, either the grid lines have
to be visible in all of the grids, or the
grid lines have to be invisible in all of
the grids.
How do we make either the grid lines visible
in all of the grids, or how do make the grid
lines invisible in all of the grids?
Thanks,
-jc
modified on Sunday, December 7, 2008 10:32 PM
|
|
|
|
|
Hi jc
The grid lines that should show by default (on all tabs) are the result of a default to 'exel' borders. You can turn this off with a call to EnableExcelBorders(FALSE) , which should leave you with no lines.
Each cell can take control of the 4 borders style and color, with calls to SetBorder() and SetBorderColor() . This can be done for column defaults for uniformity, or used as a highlight technique.
I don't see why the lines are not showing up in the other grids, but an explicit call to EnableExcelBorders(TRUE) should do it.
Tim
|
|
|
|
|
Hi Tim,
Thank you for your reply.
However, neither the EnableExcelBorders(FALSE)
nor the EnableExcelBorders(true) had any effect on our
application. As such, I tried the EnableExcelBorders(FALSE)
method on the Excel Demo program, and the method had
no effect on the grid lines.
void CExcelDemoView::OnInitialUpdate()
{
CView::OnInitialUpdate();
if( GetDocument()->GetOpenFilename() != _T(""))
{
CXMLParser xmlParser;
xmlParser.SetGridObject( &m_grid );
xmlParser.Load( GetDocument()->GetOpenFilename());
m_grid.AdjustComponentSizes();
}
else
{
int cols = 10, rows = 50;
/////
m_grid.EnableExcelBorders(FALSE);
//////
m_grid.SetDefColWidth( 60 );
m_grid.SetNumberRows( rows );
m_grid.SetNumberCols( cols );
What I am doing wrong?
Thanks,
-jc
|
|
|
|
|
Hmmm... are you starting with the setup in the Excel Demo?
What happens there is that the MyCug::OnSetup calls UGExcel::OnSetup , which sets up a column default cell with thin right and bottom borders, and calls EnableExcelBorders(FALSE) .
The EnableExcelBorders(FALSE) call will, I think, apply to susequent sheets, but not the column default cell, which would need to be put in place for each sheet.
So, the code you want in your OnSetup(s) is probably something like:
GetGridDefault( &cell );
cell.SetFont( CreateFont( -11, 0, 0, 0, 200, 0, 0, 0, 0, 0, 0, 0, 0, "Arial" ));
cell.SetBorderColor( &m_cellBorderPen );
cell.SetBorder( UG_BDR_RTHIN|UG_BDR_BTHIN );
SetGridDefault( &cell );
There's also some code in there affecting the header defaults etc.
Tim
|
|
|
|
|
Hi Tim,
Thanks again, the code snippet solved the problem.
-jc
|
|
|
|
|