Re: Transparent tracker control
"tsehonkit" <tsehonkit-/[email protected]>
| Newsgroups | gmane.comp.windows.wtl |
|---|---|
| Message-ID | <[email protected]> |
Thanks for the help.
I found that no message WM_CTLCOLORSTATIC can be recieved from the control. No luck to manage this message. I studied some transparent slider code in code project but none of them using WTL.
From those information, I finally make a simple transparent slider control in WTL. It does not have much features and may be some mistake inside I guess. As I use many WTL code contributed form others, here is my code.
Please comment!
class CThemedSliderCtrl :
public CWindowImpl<CThemedSliderCtrl, CTrackBarCtrl>,
public CCustomDraw< CThemedSliderCtrl >
{
protected:
CWindow m_wndThemeParent;
CBrush m_brBack;
COLORREF m_ChannelColor;
COLORREF m_ChannelColorShadow;
COLORREF m_ChannelColorHilite;
CRect ChannelRc; // channel rectangle
CRect TicsRc; // Ticks rectangle
DWORD dwStyle; // store slider style
int TicsFreq;
public:
BEGIN_MSG_MAP(CThemedSliderCtrl)
MESSAGE_HANDLER(WM_MOVE, Refresh)
CHAIN_MSG_MAP_ALT(CCustomDraw< CThemedSliderCtrl >, 1)
REFLECT_NOTIFICATIONS()
END_MSG_MAP()
void SetTicFreq(int nFreq)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, TBM_SETTICFREQ, nFreq, 0L);
TicsFreq = nFreq; // need to remember to take care tick drawing
}
LRESULT Refresh(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
// slider control do not repaint itself unless it take focus
// So call this routine to repaint the control when the control is moved
int minvalue, maxvalue;
GetRange(minvalue, maxvalue);
SetRange(minvalue, maxvalue, TRUE);
return TRUE;
}
DWORD OnPrePaint(int idCtrl, LPNMCUSTOMDRAW lpNMCustomDraw) // Before the painting cycle begins.
{
// call item draw routine
return CDRF_NOTIFYITEMDRAW;
}
DWORD OnPreErase(int idCtrl, LPNMCUSTOMDRAW lpNMCustomDraw) // Before the erasing cycle begins.
{
return CDRF_DODEFAULT;
}
DWORD OnPostPaint(int idCtrl, LPNMCUSTOMDRAW lpNMCustomDraw) // After the painting cycle is complete.
{
return CDRF_DODEFAULT;
}
DWORD OnPostErase(int idCtrl, LPNMCUSTOMDRAW lpNMCustomDraw) // After the erasing cycle is complete.
{
return CDRF_DODEFAULT;
}
DWORD OnItemPrePaint(int idCtrl, LPNMCUSTOMDRAW lpNMCustomDraw)
{
CDCHandle dc = lpNMCustomDraw->hdc;
CRect rcPaint = lpNMCustomDraw->rc;
UINT itemSpec = lpNMCustomDraw->dwItemSpec;
UINT itemState = lpNMCustomDraw->uItemState;
dwStyle = GetStyle();
switch (itemSpec)
{
case TBCD_CHANNEL:
ChannelRc = rcPaint;
return CDRF_DODEFAULT; break;
case TBCD_TICS:
return CDRF_DODEFAULT; break;
case TBCD_THUMB:
DrawSlider(dc, rcPaint); // we draw our own background
return CDRF_DODEFAULT; break; // we keep the orginal thumb drawing
default: return CDRF_DODEFAULT;
}
}
DWORD OnItemPostPaint(int idCtrl, LPNMCUSTOMDRAW lpNMCustomDraw)
{
CDCHandle dc = lpNMCustomDraw->hdc;
CRect rcPaint = lpNMCustomDraw->rc;
UINT itemSpec = lpNMCustomDraw->dwItemSpec;
UINT itemState = lpNMCustomDraw->uItemState;
switch (itemSpec)
{
case TBCD_CHANNEL:
return CDRF_DODEFAULT; break;
case TBCD_TICS:
return CDRF_DODEFAULT; break;
case TBCD_THUMB:
return CDRF_DODEFAULT; break;
default: return CDRF_DODEFAULT;
};
}
DWORD OnItemPreErase(int idCtrl, LPNMCUSTOMDRAW lpNMCustomDraw)
{
return CDRF_DODEFAULT;
}
DWORD OnItemPostErase(int idCtrl, LPNMCUSTOMDRAW lpNMCustomDraw)
{
return CDRF_DODEFAULT;
}
DWORD OnSubItemPrePaint(int idCtrl, LPNMCUSTOMDRAW lpNMCustomDraw)
{
return CDRF_DODEFAULT;
}
BOOL SubclassWindow(HWND hWnd)
{
ATLASSERT(m_hWnd==NULL);
ATLASSERT(::IsWindow(hWnd));
BOOL bRet = CWindowImpl<CThemedSliderCtrl, CTrackBarCtrl>::SubclassWindow(hWnd);
if (bRet)
{
m_wndThemeParent = GetTopLevelParent();
SetLineColor(RGB(200,200,200)); // set default color to light gray
TicsFreq = 1;
}
return bRet;
}
COLORREF SetLineColor (COLORREF ch)
{
COLORREF oldch = m_ChannelColor;
m_ChannelColor = ch;
m_ChannelColorHilite = ::ColorAdjustLuma( ch, 500, TRUE ); // increase by 50%
m_ChannelColorShadow = ::ColorAdjustLuma( ch, -210, TRUE ); // decrease by 33.3%
return oldch;
}
void DrawSlider(CDCHandle pDC, CRect rc)
{
CRect rcClient;
GetClientRect(&rcClient);
CDC dc;
dc.CreateCompatibleDC(pDC);
CBitmap dcBmp;
dcBmp.CreateCompatibleBitmap(pDC, rcClient.Width(), rcClient.Height()); // create from pDC
HBITMAP oldbm = (HBITMAP)::SelectObject(dc, dcBmp);
// draw background get from parent
// background code copy from viksoe.dk
m_brBack = AtlGetBackgroundBrush(m_hWnd, m_wndThemeParent);
HBRUSH hOldBrush = dc.SelectBrush(m_brBack);
dc.PatBlt(rcClient.left, rcClient.top, rcClient.Width(), rcClient.Height(), PATCOPY);
// draw channel
RECT rrc = {ChannelRc.left + 1, ChannelRc.top + 1, ChannelRc.right - 1, ChannelRc.bottom - 1};
dc.Draw3dRect(&rrc, m_ChannelColorHilite, m_ChannelColorShadow);
//dc.Draw3dRect(&ChannelRc, m_ChannelColorShadow, m_ChannelColorHilite);
// draw tics info
// TBS_RIGHT, TBS_BOTTOM and TBS_HORZ are all defined as 0x0000, so avoid testing on them
if( !(dwStyle & TBS_NOTICKS) )
{
int tickcount = GetNumTics();
RECT tickloc;
int i;
if (dwStyle & TBS_VERT) // draw vertical ticks
{
// define vertical drawing rectangle
TicsRc.top = ChannelRc.top + rc.Height()/2;
TicsRc.bottom = ChannelRc.bottom - rc.Height()/2;
TicsRc.left = rc.left - 7;
TicsRc.right = rc.right + 7;
bool printleft = false, printright = false;
if (dwStyle & TBS_BOTH)
{
printleft = true;
printright = true;
}
else
{
if (dwStyle & TBS_LEFT)
{
printleft = true;
printright = false;
}
else
{
printleft = false;
printright = true;
}
}
// draw first tick and last tick
if (printleft)
{
tickloc.left = TicsRc.left;
tickloc.top = TicsRc.top - 1;
tickloc.right = TicsRc.left + 5;
tickloc.bottom = TicsRc.top + 1;
dc.Draw3dRect(&tickloc, m_ChannelColorHilite, m_ChannelColorShadow);
tickloc.left = TicsRc.left;
tickloc.top = TicsRc.bottom - 1;
tickloc.right = TicsRc.left + 5;
tickloc.bottom = TicsRc.bottom + 1;
dc.Draw3dRect(&tickloc, m_ChannelColorHilite, m_ChannelColorShadow);
}
// draw first tick and last tick
if (printright)
{
tickloc.left = TicsRc.right - 5;
tickloc.top = TicsRc.top - 1;
tickloc.right = TicsRc.right;
tickloc.bottom =TicsRc.top + 1;
dc.Draw3dRect(&tickloc, m_ChannelColorHilite, m_ChannelColorShadow);
tickloc.left = TicsRc.right - 5;
tickloc.top = TicsRc.bottom - 1;
tickloc.right = TicsRc.right;
tickloc.bottom = TicsRc.bottom + 1;
dc.Draw3dRect(&tickloc, m_ChannelColorHilite, m_ChannelColorShadow);
}
// draw ticks between
for ( i = 0; i < tickcount - 2; i++)
{
if (printleft)
{
tickloc.left = TicsRc.left;
tickloc.top = GetTicPos(TicsFreq * (i + 1) - 1) - 1; // take care of SetTicFreq
tickloc.right = TicsRc.left + 5;
tickloc.bottom = GetTicPos(TicsFreq * (i + 1) - 1) + 1;
dc.Draw3dRect(&tickloc, m_ChannelColorHilite, m_ChannelColorShadow);
}
if (printright)
{
tickloc.left = TicsRc.right - 5;
tickloc.top = GetTicPos(TicsFreq * (i + 1) - 1) - 1;
tickloc.right = TicsRc.right;
tickloc.bottom = GetTicPos(TicsFreq * (i + 1) - 1) + 1;
dc.Draw3dRect(&tickloc, m_ChannelColorHilite, m_ChannelColorShadow);
}
}
}
else // draw horizontal ticks
{
// define horizontal drawing rectangle
TicsRc.left = ChannelRc.left + rc.Width()/2;
TicsRc.right = ChannelRc.right - rc.Width()/2;
TicsRc.top = rc.top - 7;
TicsRc.bottom = rc.bottom + 7;
bool printtop = false, printbtm = false;
if (dwStyle & TBS_BOTH)
{
printtop = true;
printbtm = true;
}
else
{
if (dwStyle & TBS_TOP)
{
printtop = true;
printbtm = false;
}
else
{
printtop = false;
printbtm = true;
}
}
// draw first tick and last tick
if (printtop)
{
tickloc.left = TicsRc.left - 1;
tickloc.top = TicsRc.top;
tickloc.right = TicsRc.left + 1;
tickloc.bottom = TicsRc.top + 5;
dc.Draw3dRect(&tickloc, m_ChannelColorHilite, m_ChannelColorShadow);
tickloc.left = TicsRc.right - 1;
tickloc.top = TicsRc.top;
tickloc.right = TicsRc.right + 1;
tickloc.bottom = TicsRc.top + 5;
dc.Draw3dRect(&tickloc, m_ChannelColorHilite, m_ChannelColorShadow);
}
// draw first tick and last tick
if (printbtm)
{
tickloc.left = TicsRc.left - 1;
tickloc.top = TicsRc.bottom - 5;
tickloc.right = TicsRc.left + 1;
tickloc.bottom = TicsRc.bottom;
dc.Draw3dRect(&tickloc, m_ChannelColorHilite, m_ChannelColorShadow);
tickloc.left = TicsRc.right - 1;
tickloc.top = TicsRc.bottom - 5;
tickloc.right = TicsRc.right + 1;
tickloc.bottom = TicsRc.bottom;
dc.Draw3dRect(&tickloc, m_ChannelColorHilite, m_ChannelColorShadow);
}
// draw ticks between
for ( i = 0; i < tickcount - 2; i++)
{
if (printtop)
{
tickloc.left = GetTicPos(TicsFreq * (i + 1) - 1) - 1;
tickloc.top = TicsRc.top;
tickloc.right = GetTicPos(TicsFreq * (i + 1) - 1) + 1;
tickloc.bottom =TicsRc.top + 5;
dc.Draw3dRect(&tickloc, m_ChannelColorHilite, m_ChannelColorShadow);
}
if (printbtm)
{
tickloc.left = GetTicPos(TicsFreq * (i + 1) - 1) - 1;
tickloc.top = TicsRc.bottom - 5;
tickloc.right = GetTicPos(TicsFreq * (i + 1) - 1) + 1;
tickloc.bottom =TicsRc.bottom;
dc.Draw3dRect(&tickloc, m_ChannelColorHilite, m_ChannelColorShadow);
}
}
}
}
pDC.BitBlt(0, 0, rcClient.Width(), rcClient.Height(), dc, 0, 0, SRCCOPY);
dc.SelectBrush(hOldBrush);
}
};
Thanks
Kit
--- In [email protected], "domehead100" <domehead100@...> wrote:
>
> I think your parent (m_wndThemeParent) should be obtained via GetParent() rather than GetTopLevelParent().
>
> I have no idea if this would work for what you need, but one way to get the parent to draw the background is to create a memory DC and pass that to the parent via WM_PAINT or WM_PRINT or WM_PRINTCLIENT. The parent should then draw using the DC that you provide.
>
> It's possible that the parent's WS_CLIPCHILDREN setting might affect how this works.
>
> Others probably have better approaches; I'm not very familiar with "transparent" controls.
>
> Maybe something like this:
>
> // Draw the background from the parent
> CWindow wndParent(GetParent());
> wndParent.SetRedraw(FALSE);
> if(wndParent.IsWindow())
> {
> CMemoryDC dcMemory(dc.m_hDC, m_rcClient);
> CPoint ptOrigin(0);
> MapWindowPoints(wndParent, &ptOrigin, 1);
> dcMemory.OffsetWindowOrg(ptOrigin.x, ptOrigin.y, &ptOrigin);
> wndParent.SendMessage(WM_PAINT, (WPARAM)dcMemory.m_hDC);
> dcMemory.SetWindowOrg(ptOrigin);
> }
> wndParent.SetRedraw(TRUE);
>
> Best of luck with this :o)
>
> ~Mike
>
>
> --- In [email protected], "tsehonkit" <tsehonkit@> wrote:
> >
> > Thanks for your advise!
> > I tried this one but no effect!
> >
> > Here is the code I used.
> > If the background is ok, I will try to custom draw the slider. So, there are some code preparing for these.
> >
> > class CThemedSliderCtrl :
> > public CWindowImpl<CThemedSliderCtrl, CTrackBarCtrl>,
> > public CCustomDraw< CThemedSliderCtrl >
> > {
> > public:
> > CWindow m_wndThemeParent;
> > CBrush m_brBack;
> >
> > BEGIN_MSG_MAP(CThemedSliderCtrl)
> > MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnBackground)
> > CHAIN_MSG_MAP_ALT(CCustomDraw< CThemedSliderCtrl >, 1)
> > END_MSG_MAP()
> >
> > DWORD OnPrePaint(int idCtrl, LPNMCUSTOMDRAW lpNMCustomDraw)
> > {
> > return CDRF_NOTIFYITEMDRAW | CDRF_NOTIFYPOSTPAINT;
> > }
> >
> > DWORD OnPreErase(int idCtrl, LPNMCUSTOMDRAW lpNMCustomDraw)
> > {
> > return CDRF_DODEFAULT;
> > }
> >
> > DWORD OnPostPaint(int idCtrl, LPNMCUSTOMDRAW lpNMCustomDraw)
> > {
> > return CDRF_DODEFAULT;
> > }
> >
> > DWORD OnPostErase(int idCtrl, LPNMCUSTOMDRAW lpNMCustomDraw)
> > {
> > return CDRF_DODEFAULT;
> > }
> >
> > DWORD OnItemPrePaint(int idCtrl, LPNMCUSTOMDRAW lpNMCustomDraw)
> > {
> > CDCHandle dc = lpNMCustomDraw->hdc;
> > CRect rcPaint = lpNMCustomDraw->rc;
> > UINT itemSpec = lpNMCustomDraw->dwItemSpec;
> > UINT itemState = lpNMCustomDraw->uItemState;
> >
> > switch (itemSpec)
> > {
> > case TBCD_CHANNEL:
> > return CDRF_DODEFAULT; break;
> > case TBCD_TICS:
> > return CDRF_DODEFAULT; break;
> > case TBCD_THUMB:
> > return CDRF_DODEFAULT; break;
> > default: return CDRF_DODEFAULT;
> > }
> > }
> >
> > DWORD OnItemPostPaint(int idCtrl, LPNMCUSTOMDRAW lpNMCustomDraw)
> > {
> > CDCHandle dc = lpNMCustomDraw->hdc;
> > CRect rcPaint = lpNMCustomDraw->rc;
> > UINT itemSpec = lpNMCustomDraw->dwItemSpec;
> > UINT itemState = lpNMCustomDraw->uItemState;
> >
> > switch (itemSpec)
> > {
> > case TBCD_CHANNEL:
> > return CDRF_DODEFAULT; break;
> > case TBCD_TICS:
> > return CDRF_DODEFAULT; break;
> > case TBCD_THUMB:
> > return CDRF_DODEFAULT; break;
> > default: return CDRF_DODEFAULT;
> > };
> > }
> >
> > DWORD OnItemPreErase(int idCtrl, LPNMCUSTOMDRAW lpNMCustomDraw)
> > {
> > return CDRF_DODEFAULT;
> > }
> >
> > DWORD OnItemPostErase(int idCtrl, LPNMCUSTOMDRAW lpNMCustomDraw)
> > {
> > return CDRF_DODEFAULT;
> > }
> >
> > DWORD OnSubItemPrePaint(int idCtrl, LPNMCUSTOMDRAW lpNMCustomDraw)
> > {
> > return CDRF_DODEFAULT;
> > }
> >
> > BOOL SubclassWindow(HWND hWnd)
> > {
> > ATLASSERT(m_hWnd==NULL);
> > ATLASSERT(::IsWindow(hWnd));
> > BOOL bRet = CWindowImpl<CThemedSliderCtrl, CTrackBarCtrl>::SubclassWindow(hWnd);
> >
> > if (bRet) m_wndThemeParent = GetTopLevelParent();
> > return bRet;
> > }
> >
> > LRESULT OnBackground(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
> > {
> > CDCHandle dc((HDC)wParam);
> > CRect rcPaint;
> > GetClientRect(&rcPaint);
> >
> > // Paint background from parent
> > if( m_brBack.IsNull() ) m_brBack = AtlGetBackgroundBrush(m_hWnd, m_wndThemeParent);
> > HBRUSH hOldBrush = dc.SelectBrush(m_brBack);
> > dc.PatBlt(rcPaint.left, rcPaint.top, rcPaint.Width(), rcPaint.Height(), PATCOPY);
> > dc.SelectBrush(hOldBrush);
> > return true;
> > }
> > };
> >
> >
> >
> >
> > --- In [email protected], Timo Kunze <TKunze71216@> wrote:
> > >
> > > Handle WM_CTLCOLORSTATIC. I doubt you can use this message to make the
> > > control really transparent, but you could use it to create a pattern
> > > brush out of the things behind the track bar and return this brush as
> > > the background brush.
> > >
> > > Timo
> > > --
> > > www.TimoSoft-Software.de - Unicode controls for VB6
> > > "Those who sacrifice freedom for safety deserve neither."
> > > "Demokratie ist per Definition unsicher. Ihr Schutz entsteht aus der
> > > �berzeugung, dass die demokratischen Kräfte überwiegen und sich �� auf
> > > demokratischem Wege �� durchsetzen."
> > >
> >
>
------------------------------------
Yahoo! Groups Links
<*> To visit your group on the web, go to:
http://groups.yahoo.com/group/wtl/
<*> Your email settings:
Individual Email | Traditional
<*> To change settings online go to:
http://groups.yahoo.com/group/wtl/join
(Yahoo! ID required)
<*> To change settings via email:
mailto:[email protected]
mailto:[email protected]
<*> To unsubscribe from this group, send an email to:
[email protected]
<*> Your use of Yahoo! Groups is subject to:
http://docs.yahoo.com/info/terms/