|
how about in FormView?when i added the codes in FormView, some problems happened.
|
|
|
|
|
I am trying to make my CList shows multilines in both header and column.
I think this solution allows setting items in the header only when it is created. Which means items need to be defined in the code, but I want to dynamically insert/change it.
Does any one know how?
I think the main idead of this solution is enlarge column by setting big font then draw header text with small font. Am I right?
modified on Tuesday, July 7, 2009 10:31 PM
|
|
|
|
|
This format wont works
UINT uFormat = DT_CENTER | DT_VCENTER
When applying DT_VCENTER format, the \n is no longer drawn as a seconde line
Just too to bad ...
It would be great if vertical alignment could be CENTERED.
Any of you have a solution for that ?
Else, thank for the GREAT ACTICLE !
|
|
|
|
|
it does not work under XP when you use manifest file (=XP look for controls).
it seems that height of header can not be changed in XP look.
|
|
|
|
|
Using the font size to set the CHeaderCtrl height of an MFC CListCtrl is a hack and does not work with common ctrl 6.0 in Windows XP style theme. Here is way to set the height directly and that works with both Windows 2000 and Windows XP.
Solution is posted by Migel on http://www.experts-exchange.com/Programming/Programming_Languages/MFC/Q_20705214.html
Basically, capture HDM_LAYOUT message and let Windows figure out the default layout for the header ctrl but then substitute the height you like. You still need to use owner-draw to actually draw the header ctrl but no longer need a dummy big font.
BEGIN_MESSAGE_MAP(CHeaderCtrlBase, CHeaderCtrl)
ON_MESSAGE(HDM_LAYOUT, OnLayout)
END_MESSAGE_MAP()
LRESULT CHeaderCtrlBase::OnLayout( WPARAM wParam, LPARAM lParam ) {
LRESULT lResult = CHeaderCtrl::DefWindowProc(HDM_LAYOUT, 0, lParam);
HD_LAYOUT &hdl = *( HD_LAYOUT * ) lParam;
RECT *prc = hdl.prc;
WINDOWPOS *pwpos = hdl.pwpos;
int nHeight = pwpos->cy * 2.30;
pwpos->cy = nHeight;
prc->top = nHeight;
return lResult;
}
www.zidsoft.com CompareData: compare and synchronize SQL DBMS data visually between two databases using ODBC drivers
|
|
|
|
|
Thanks...
thank you!
|
|
|
|
|
Hi, I am trying to aling header labels left instead center.
I am not successful with it, I am trying it in:
hdItem.mask = HDI_FORMAT;
for(i=0; i < m_HeaderCtrl.GetItemCount(); i++)
{
m_HeaderCtrl.GetItem(i,&hdItem);
hdItem.fmt|= HDF_OWNERDRAW | HDF_LEFT;
m_HeaderCtrl.SetItem(i,&hdItem);
}
but still it is centered. Is possible to align it left ?
Thx!
|
|
|
|
|
Hallo
Please, is it possible this code rewrite to the VB.NET. I need multiline header in my program, but i cannot in C/C++.
Thank you
Rudolf Pliva
|
|
|
|
|
Hello Rudolf,
VB.NET is greek to me so sorry but I can't.
However why don't you make a .NET control out of my code and useit in VB.NET?
Cheers!
Alberto Bar-Noy
Software Engineer
http://www.certagon.com
|
|
|
|
|
Hello,
i don't make a .NET control out of you code. Can you make a .NET control and send this control for my mail, please?
Thank you very much
Rudolf Pliva
|
|
|
|
|
I'm sorry but I can't help you with that.
Good luck!
Alberto Bar-Noy
Software Engineer
http://www.certagon.com
|
|
|
|
|
|
hi,
i have to do same thing .but not for header instead for rows which we are adding at runtime .it is possible ? if so plz. give me some code ..
i want to display text in the column in two or more lines according to the length of the text.
iam using listview report mode and win32 api for sending message to the listview and vc++6.0
thanks in advance
Selvaraj
|
|
|
|
|
Hi ,
My requirement also exactly same.Did you get information regarding this?
Could you please help if you have some point on this.
Thanks
Poornima
|
|
|
|
|
Hi!
I have a problem with the BOOL CXListCtrl::DeleteItem(int nItem) and void CXListCtrl::OnDestroy() fucnction.
In debug mode, I have an exception when I try to pass the line delete [] pXLCD; which bring me in void AFXAPI AfxUnlockGlobals(int nLockType)
However, I have items, and no problem for other oprations like item insertion or modification.The only thing seems wrong is this line.
If someone has an idea to propose it would be great!
|
|
|
|
|
Hi !
I've tried this with MDI application. With SDI it works , but when I've tried MDI application , when first appear, the hight does not change. When place focus on this View , the window redraw in write manner.
|
|
|
|
|
I've have the same thing happening in a MDI application (plus it's in a splitted frame). Does anybody have a clue ?
|
|
|
|
|
I have the same problem with an MDI and a Splitter app. Refer to the post by mijob about using the HDM_LAYOUT message as this will resize the header without altering the font size. However, I also had a problem with this in that on startup the header was displayed in the usual default height and only drew itself correctly when the parent window was resized.
It seems that the HDM_LAYOUT message is not sent immediately to the control unless certain properties are present in the HDITEM struct. I overcame this issue by first doing a setitem() on the first column with just the HDI_HEIGHT mask and a height value of zero. This appears to force a HDM_LAYOUT to be sent and if you previously set the number of lines in the header then the code outlined by mijob will adjust the header to the required height.
Here is the code...
// Get the header
CHeaderCtrl* pHeader = NULL;
pHeader = ListCtrl.GetHeaderCtrl ();
if ( pHeader == NULL )
return;
// Do the subclassy bit
VERIFY ( m_HeaderCtrl.SubclassWindow ( pHeader->m_hWnd ) );
// Set the line count, its just a varialble in the
// header control
m_HeaderCtrl.SetLineCount ( 2 );
// This should force an HDI_LAYOUT message
HDITEM hdItem.mask = HDI_HEIGHT;
hdItem.cxy = 0;
m_HeaderCtrl.SetItem ( 0,&hdItem );
// Set the rest of the column info, I include the width
// here as well just to make sure!
hdItem.mask = HDI_FORMAT | HDI_IMAGE | HDI_WIDTH;
for ( i = 0; i < m_HeaderCtrl.GetItemCount (); i++ )
{
m_HeaderCtrl.GetItem ( i,&hdItem );
hdItem.fmt |= HDF_OWNERDRAW;
hdItem.cxy = _gnColumnWidth[i];
m_HeaderCtrl.SetItem ( i,&hdItem );
}
// By the time you get here the header should be the correct height
// HDM_LAYOUT handler in CHeaderCtrlExt
LRESULT CHeaderCtrlEx::OnLayout ( WPARAM wParam, LPARAM lParam )
{
CClientDC dc ( this );
CSize size = dc.GetTextExtent ( _T("test") );
HDLAYOUT* pLayout = ( HDLAYOUT* ) lParam; // cast the lParam
pLayout->pwpos->hwnd = GetSafeHwnd (); // populate WINDOWPOS struct
pLayout->pwpos->hwndInsertAfter = NULL;
pLayout->pwpos->flags = SWP_FRAMECHANGED;
pLayout->pwpos->x = pLayout->prc->left;
pLayout->pwpos->y = 0;
pLayout->pwpos->cx = pLayout->prc->right - pLayout->prc->left;
// Where nLineCount is set by the call to SetLineCount()
// in this case, two
int nHdrBottom = nLineCount * ( size.cy ) + 3;
pLayout->pwpos->cy = nHdrBottom;
pLayout->prc->top = nHdrBottom;
return ( -1 );
}
Hope this helps
|
|
|
|
|
wrote: Hope this helps
It sure helped me! Google and you gave me just what I was looking for.
|
|
|
|
|
Hi, I have an old project, entirely in plain C, and I need to implement exactly this situation, but can't change all the project to C++, so I was wondering if it is possible to do it only by Windows messages, or something similar.
Thanks for any clue you can give.
|
|
|
|
|
I use it in a dialog, but the "OnCreate" function of my ListCtrl derived from CListCtrl does nothing! It seems that "OnCreate" doesn't been called.
|
|
|
|
|
If you use dialog, the listctrl OnCreate() will not be called. You need to use the virtual function PreSubclassWindow().
|
|
|
|
|
It doesn't work either, because at that point CHeaderCtrl::GetItemCount() returns 0, since normally columns are added in OnInitDialog( ) method.
I don't know how to solve it.
Jaime
|
|
|
|
|
I had the EXACT same situation... OnCreate() doesn't get called. Tried moving it to PreSubClassWindow(), but like you said, GetItemCount() returns 0. I tried putting it in all kinds of different functions that I thought might get called when the control is first being created/displayed, but nothing seems to work! Anyone figure this out yet?
--luke
|
|
|
|
|
Good news... I figured out a workaround for getting multiline headers to work in a CListCtrl object. Unfortunately, with the author's code, you can't use OnCreate() or PreSubClassWindow(). However, you can try the following approach, which in some ways makes your list class more usable because you can turn on/off multiline whenever you feel like it.
In your derived list control class (Example: CMyListCtrl) you need these four member variables in MyListCtrl.h:
bool m_bInit;
CFont m_FontSingle;
CFont m_FontMultiple;
CCtrlListHeaderEx m_HeaderCtrl; // multiline header control
Two of these need to be initialized, so in the constructor of your list class (CMyListCtrl), place the following:
m_bInit = false;
m_FontMultiple.CreatePointFont(190,"MS Serif"); // 190 for two rows of text
You will need the CCtrlListHeaderEx class, which is pretty much a tiny class with only one real function, so i just inline it and put it above the list class in MyListCtrl.h:
// A simple extension to the header class to allow multi-line headers
class CCtrlListHeaderEx : public CHeaderCtrl
{
public:
CCtrlListHeaderEx() { m_bMultiline = false; }
virtual ~CCtrlListHeaderEx() { }
bool m_bMultiline;
protected:
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) // override
{
ASSERT(lpDrawItemStruct->CtlType == ODT_HEADER);
HDITEM hdi;
TCHAR lpBuffer[256];
hdi.mask = HDI_TEXT;
hdi.pszText = lpBuffer;
hdi.cchTextMax = 256;
GetItem(lpDrawItemStruct->itemID, &hdi);
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
pDC->SelectObject(GetStockObject(DEFAULT_GUI_FONT)); // this font is only for drawing as long as we don't do a SetFont()
::DrawFrameControl(lpDrawItemStruct->hDC, &lpDrawItemStruct->rcItem, DFC_BUTTON, DFCS_BUTTONPUSH); // Draw the button frame.
UINT uFormat;
if (m_bMultiline) { uFormat = DT_CENTER; } else { uFormat = DT_SINGLELINE | DT_CENTER; }
::DrawText(lpDrawItemStruct->hDC, lpBuffer, strlen(lpBuffer), &lpDrawItemStruct->rcItem, uFormat); // Draw the text
pDC->SelectStockObject(SYSTEM_FONT);
}
};
It's basically the same class that the author used, except that I added a m_bMultiline variable and some code to switch between one and the other.
Then, override PreSubclassWindow() for CMyListCtrl. The function should contain the following:
void CMyListCtrl::PreSubclassWindow()
{
CHeaderCtrl* pHeader = GetHeaderCtrl();
if (pHeader==NULL) { return; }
VERIFY(m_HeaderCtrl.SubclassWindow(pHeader->m_hWnd));
CListCtrl::PreSubclassWindow();
}
Then create a function for CMyListCtrl called SetHeaderMultiline() which looks like:
void CMyListCtrl::SetHeaderMultiline(bool bMulti)
{
// Set up multiline headers
InsertItem(0,"DELETE!"); // Used to trick the column bar to refresh
// the following code will only ever get called once in the class's lifetime
if (!m_bInit) {
m_bInit = true;
// get the current font so we can revert back to singleline later if needed
CFont* pOldFont = m_HeaderCtrl.GetFont();
LOGFONT LogFont; pOldFont->GetLogFont(&LogFont);
m_FontSingle.CreateFontIndirect(&LogFont);
// set ownerdraw to true (unfortunately we have to do this here because
// there doesn't seem to be an init method that we can override
// since OnCreate() doesn't get called for CListCtrl derived classes
// and GetItemCount() returns 0 within PreSubclassWindow()
HDITEM hdItem; hdItem.mask = HDI_FORMAT;
for (int i = 0; i < m_HeaderCtrl.GetItemCount(); i++) {
m_HeaderCtrl.GetItem(i,&hdItem);
hdItem.fmt |= HDF_OWNERDRAW;
m_HeaderCtrl.SetItem(i,&hdItem);
}
}
//bool bFlipOwnerDraw = false;
if (bMulti && !m_HeaderCtrl.m_bMultiline) {
m_HeaderCtrl.SetFont(&m_FontMultiple);
m_HeaderCtrl.m_bMultiline = true;
} else if (m_HeaderCtrl.m_bMultiline) {
m_HeaderCtrl.SetFont(&m_FontSingle);
m_HeaderCtrl.m_bMultiline = false;
}
DeleteItem(0); // Completing the trick requires removing the grabage!
}
At this point your derived CMyListCtrl class should have a nifty new function called
SetHeaderMultiline(...); Now, all you have to do is call that function from in the class which contains the list. A good example might be to call this from OnInitDialog() in a dialog box.
m_List.SetHeaderMultiline(true);
It sounds more complicated than it is... just add those 4 variables, initialize two of them in the list's constructor, define the CCtrlListHeaderEx class, and paste in the SetHeaderMultiline() function -- and your derived list control class should be displaying multiline headers in no time.
questions/comments: lclemens@gmail.com
--luke
|
|
|
|