CListCtrl set font style to bold - visual-studio

I want to change font of any cell of CListCtrl control to bold. Can any one tell how to do it for CList Ctrl.
I have already done this for a CTreeCtrl, like this
pTC->SetItemState(hItemCur, TVIS_BOLD, TVIS_BOLD);
do we have something similar for CListCtrl?
Thanks in advance.

If you can use CMFCListCtrl (VS2008 SP1 and up), you can derive a class from it and override OnGetCellFont. From there you return your bold font (you can create your own or return AFX_GLOBAL_DATA::fontBold):
HFONT CMyListCtrl::OnGetCellFont( int nRow, int nColumn, DWORD dwData /*= 0*/ )
{
if (UseBoldFont(/* params */))
{
return GetGlobalData()->fontBold;
}
return NULL;
}
If you have to stick to plain old CListCtrl, the easiest way would be to use Custom Draw, where you can tweak the drawing process to your own needs. Don't confuse it with Owner Draw, where you have to do all the drawing yourself.
Here's an article explaining the basics of using Custom Draw with CListCtrl.

Add
ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomdraw)
to your message map.
Now you can simply modify items as you wish in this function. In here you can change the align, font, background-color, text-color, [...], and you can set items to bold -> example. The best way IMO, is to either store a pointer to a struct, class or simply a flag in the LPARAM of the item(s) in the control. This function works for both CListCtrl and CTreeCtrl.
Here is an example with flags:
enum ColorFlags
{
F_COLOR_BLACK = 0x1,
F_COLOR_WHITE = 0x2
//and more...
};
enum CustomColors
{
COLOR_BLACK = RGB(0, 0, 0),
COLOR_WHITE = RGB(255, 255, 255)
};
afx_msg
void CMyListCtrl::OnCustomdraw(NMHDR *pNMHDR, LRESULT *pResult)
{
NMLVCUSTOMDRAW *pDraw = reinterpret_cast<NMLVCUSTOMDRAW*>(pNMHDR);
switch (pDraw->nmcd.dwDrawStage)
{
case CDDS_PREPAINT:
*pResult = CDRF_NOTIFYITEMDRAW; //Do not forget this...
break;
case CDDS_ITEMPREPAINT:
{
switch (pDraw->nmcd.lItemlParam) //Extract color from flags
{
case F_COLOR_BLACK:
{
pDraw->clrText = COLOR_BLACK;
} break;
case F_COLOR_WHITE:
{
pDraw->clrText = COLOR_WHITE;
} break;
default:
break;
} //switch
} break;
} //switch
}

Related

Can I make a property sheet without resource script?

I'd like to add controls to a property sheet without resource script, rather using pure code.
The reason for this I'd like to create a property sheet(mimicking C#'s property grid), calling C routines/WINAPI, from another language, binary-compatible to C; but I'd like to define everything with code, without need of a resource script. Is this possible or the way to go is write my own property-sheet-like, with underlying CreateWindow*() calls? (different approaches to do this are welcome, I'm new to WINAPI) which I suppose property sheet use behind the scenes
Found the solution! I found this post from Raymond Chen where he shows how do that.
the main code goes like this:
BOOL FakeMessageBox(HWND hwnd, LPCWSTR pszMessage, LPCWSTR pszTitle)
{
BOOL fSuccess = FALSE;
HDC hdc = GetDC(NULL);
if (hdc) {
NONCLIENTMETRICSW ncm = { sizeof(ncm) };
if (SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0)) {
DialogTemplate tmp;
// Write out the extended dialog template header
tmp.Write<WORD>(1); // dialog version
tmp.Write<WORD>(0xFFFF); // extended dialog template
tmp.Write<DWORD>(0); // help ID
tmp.Write<DWORD>(0); // extended style
tmp.Write<DWORD>(WS_CAPTION | WS_SYSMENU | DS_SETFONT | DS_MODALFRAME);
tmp.Write<WORD>(2); // number of controls
tmp.Write<WORD>(32); // X
tmp.Write<WORD>(32); // Y
tmp.Write<WORD>(200); // width
tmp.Write<WORD>(80); // height
tmp.WriteString(L""); // no menu
tmp.WriteString(L""); // default dialog class
tmp.WriteString(pszTitle); // title
// Next comes the font description.
// See text for discussion of fancy formula.
if (ncm.lfMessageFont.lfHeight < 0) {
ncm.lfMessageFont.lfHeight = -MulDiv(ncm.lfMessageFont.lfHeight,
72, GetDeviceCaps(hdc, LOGPIXELSY));
}
tmp.Write<WORD>((WORD)ncm.lfMessageFont.lfHeight); // point
tmp.Write<WORD>((WORD)ncm.lfMessageFont.lfWeight); // weight
tmp.Write<BYTE>(ncm.lfMessageFont.lfItalic); // Italic
tmp.Write<BYTE>(ncm.lfMessageFont.lfCharSet); // CharSet
tmp.WriteString(ncm.lfMessageFont.lfFaceName);
// Then come the two controls. First is the static text.
tmp.AlignToDword();
tmp.Write<DWORD>(0); // help id
tmp.Write<DWORD>(0); // window extended style
tmp.Write<DWORD>(WS_CHILD | WS_VISIBLE); // style
tmp.Write<WORD>(7); // x
tmp.Write<WORD>(7); // y
tmp.Write<WORD>(200-14); // width
tmp.Write<WORD>(80-7-14-7); // height
tmp.Write<DWORD>(-1); // control ID
tmp.Write<DWORD>(0x0082FFFF); // static
tmp.WriteString(pszMessage); // text
tmp.Write<WORD>(0); // no extra data
// Second control is the OK button.
tmp.AlignToDword();
tmp.Write<DWORD>(0); // help id
tmp.Write<DWORD>(0); // window extended style
tmp.Write<DWORD>(WS_CHILD | WS_VISIBLE |
WS_GROUP | WS_TABSTOP | BS_DEFPUSHBUTTON); // style
tmp.Write<WORD>(75); // x
tmp.Write<WORD>(80-7-14); // y
tmp.Write<WORD>(50); // width
tmp.Write<WORD>(14); // height
tmp.Write<DWORD>(IDCANCEL); // control ID
tmp.Write<DWORD>(0x0080FFFF); // static
tmp.WriteString(L"OK"); // text
tmp.Write<WORD>(0); // no extra data
// Template is ready - go display it.
fSuccess = DialogBoxIndirect(g_hinst, tmp.Template(),
hwnd, DlgProc) >= 0;
}
ReleaseDC(NULL, hdc); // fixed 11 May
}
return fSuccess;
}

I want to copy, paste and cut content in my CEdit from my Clipboard

This is the event handlers i implemented to the copy, paste and Cut buttons in my MFCRibbonBar:
in the MyRibbonView.cpp:
void CMyRibbonView::OnEditCopy()
{
CWnd *wnd = GetFocus();
if (wnd == pEdit)
pEdit->Copy();
if (!OpenClipboard())
{
AfxMessageBox(_T("Cannot open the Clipboard"));
return;
}
if (!EmptyClipboard())
{
AfxMessageBox(_T("Cannot empty the Clipboard"));
return;
}
HGLOBAL hGlob = GlobalAlloc(GMEM_FIXED, 64);
strcpy_s((char*)hGlob, 64, "Current selection\r\n");
if (::SetClipboardData(CF_TEXT, hGlob) == NULL)
{
CString msg;
msg.Format(_T("Unable to set Clipboard data, error: %d"), GetLastError());
AfxMessageBox(msg);
CloseClipboard();
GlobalFree(hGlob);
return;
}
CloseClipboard();
}
void CMyRibbonView::OnEditPaste()
{
if (OpenClipboard())
{
HANDLE hClipboardData = GetClipboardData(CF_TEXT);
char *pchData = (char*)GlobalLock(hClipboardData);
CString strFromClipboard;
strFromClipboard = pchData;
pEdit->SetWindowText(strFromClipboard);
GlobalUnlock(hClipboardData);
CloseClipboard();
}
}
void CMyRibbonView::OnEditCut()
{
OnEditCopy();
pEdit->SetWindowText(L" ");
}
There is no errors, it's just not working. I tested it by adding the messages to check if it's actually the data or not but they're not popping up.
You need to GlobalLock your hGlob memory before copying your character string into it (this operation converts it into a usable pointer for your process - see here), and then call GlobalUnlock after you've done that (so that the clipboard can access hGlob):
HGLOBAL hGlob = GlobalAlloc(GMEM_FIXED, 64); // Maybe also need GMEM_MOVEABLE here instead?
char* cCopy = (char*)GlobalLock(hGlob);
strcpy_s(cGlob, 64, "Current selection\r\n");
GlobalUnlock(hGlob);
if (::SetClipboardData(CF_TEXT, hGlob) == NULL)
{
//...
And you'll need a similar arrangement for the paste operation.

CSpinButtonCtrl: How to remove Autobuddy style?

I use a CSpinButtonCtrl, the AutoBuddy Style is set in the DialogResssource to TRUE.
I must now remove/hide the CSliderButtonCtrl in KioskMode (FullScreen).
I have tried this, it is not enough, the associated CEditCtrl does not redraw, the place where the SpinCtrl was.
CMyFormView::OnInitialUpdate()
{
if (g_bKiosMode)
{
m_ctlSpin1.ShowWindow(SW_HIDE);
m_ctlSpin1.ShowWindow(SW_ENABLE);
LONG style = GetWindowLong(m_ctlSpinSollwert1.GetSafeHwnd(), GWL_STYLE);
style &= ~UDS_AUTOBUDDY;
SetWindowLong(m_ctlSpinSollwert2.GetSafeHwnd(), GWL_STYLE, style);
}
}
}
tried too:
if (!g_bKioskMode)
{
DDX_Control(pDX, IDC_SPIN1, m_ctlSpin1);
}
tried too: Subclass the CSpinCtrl, but the PreCreateWindow(..) is not called
class CMySpinButton : public CSpinButtonCtrl
{
DECLARE_DYNAMIC(CMySpinButton)
public:
CMySpinButton();
virtual ~CMySpinButton();
protected:
DECLARE_MESSAGE_MAP()
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
};
further ideas?
You can detach a Up-Down control by sending it the UDM_SETBUDDY message with a NULL HWND and then hiding the window.
The Up-Down control will actually resize its buddy so you need to resize the edit control after you have detached.

CToolTipCtrl with TTF_TRACK Flag won't disappear, SetDelayTime doesn't work?

I found if set TTF_TRACK flag to CTooltipCtrl, SetDelayTime doesn't work anymore, so the tooltip won't disappear automatically. I want to show the tooltip just below specified control, and expect it to disappear after a few seconds(the time can set with SetDelayTime).
Anybody can help me?
Here is my steps to construct tool tip:
1. Add member variable
CToolTipCtrl m_tooltip;
2. override PreTranslateMessage
BOOL CPF_GetSetNameDlg::PreTranslateMessage( MSG* pMsg )
{
switch (pMsg->message)
{
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_MBUTTONDOWN:
case WM_LBUTTONUP:
case WM_RBUTTONUP:
case WM_MBUTTONUP:
case WM_MOUSEMOVE:
m_tooltip.RelayEvent(pMsg);
break;
}
return CDialog::PreTranslateMessage(pMsg);
}
3. OnInitialDialog
BOOL CPF_GetSetNameDlg::OnInitDialog()
{
CDialog::OnInitDialog();
//tooltip
EnableToolTips();
m_tooltip.Create(this , WS_POPUP | TTS_NOPREFIX | TTS_BALLOON);
m_tooltip.SetDelayTime(TTDT_INITIAL, 0);
m_tooltip.SetDelayTime(TTDT_AUTOPOP, 30000);
m_tooltip.SetDelayTime(TTDT_RESHOW, 30000);
m_tooltip.AddTool(GetDlgItem(IDC_SETNAME), _T(""));
m_tooltip.SetMaxTipWidth(600);
}
4. Control to show tool tip
if(bShow)
{
m_tooltip.UpdateTipText(_T("Hello, money~"), pWnd);
CToolInfo sTinfo;
m_tooltip.GetToolInfo(sTinfo, pWnd);
sTinfo.uFlags = TTF_TRACK;
m_tooltip.SetToolInfo(&sTinfo);
CRect rect;
pWnd->GetWindowRect(rect);
m_tooltip.SendMessage(TTM_TRACKPOSITION, 0, (LPARAM)MAKELONG(rect.left, rect.bottom));
m_tooltip.SendMessage(TTM_TRACKACTIVATE, TRUE, (LPARAM)&sTinfo );
}
If you use tracking tooltips then you are responsible for showing and hiding the tooltip manually. The tooltip timers (like "autopop") are ignored. So you need to create your own timer and hide the tooltip yourself when it fires.

Changing filename color in Windows Explorer list view.

I would like to customize Windows Explorer.
One thing I want to do is changing file name's color in list view if the file has a special condition.
Is it possible by window subclassing? or does it need api hooking?
Please let me know what is the best way to do this.
Thanks.
Yes, you can do it with the window subclassing:
Add NM_CUSTOMDRAW handler to your CListCtrl-derived class
void CMyList::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult)
{
LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW)pNMHDR;
switch (lplvcd->nmcd.dwDrawStage)
{
case CDDS_PREPAINT:
*pResult = CDRF_NOTIFYITEMDRAW;
break;
case CDDS_ITEMPREPAINT:
*pResult = CDRF_NOTIFYSUBITEMDRAW;
break;
case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
lplvcd->clrText = **MY_COLOR**;
*pResult = CDRF_DODEFAULT;
}
}

Resources