title: Owner draw CSliderCtrl using MFC: why my program-created slider has an incorrect channel rect?
body: <p>I am trying to implement an owner draw CSliderCtrl. It seems drawing is fine, however the mouse to change the thumb position is very weird. It is limited only in a very small rect. And I found that the rect by GetChannelRect is much smaller than the rect I used to create the slider control.
  Below is .h file:</p>
  
  <pre><code>#if !defined(AFX_OWNDRAWSLIDER_H__82981708_4CBC_4D1E_8982_504E99BE489D__INCLUDED_)
  #define AFX_OWNDRAWSLIDER_H__82981708_4CBC_4D1E_8982_504E99BE489D__INCLUDED_
  
  #if _MSC_VER &gt; 1000
  #pragma once
  #endif // _MSC_VER &gt; 1000
  // OwnDrawSlider.h : header file
  //
  
  /////////////////////////////////////////////////////////////////////////////
  // COwnDrawSlider window
  
  class COwnDrawSlider : public CSliderCtrl
  {
  // Construction
  public:
      COwnDrawSlider();
  
  // Attributes
  public:
      CBrush black_brush;
  
  // Operations
  public:
  
  // Overrides
      // ClassWizard generated virtual function overrides
      //{{AFX_VIRTUAL(COwnDrawSlider)
      //}}AFX_VIRTUAL
  
  // Implementation
  public:
      virtual ~COwnDrawSlider();
  
      // Generated message map functions
  protected:
      //{{AFX_MSG(COwnDrawSlider)
      afx_msg void OnPaint();
      afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
      afx_msg BOOL OnEraseBkgnd(CDC* pDC);
      afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
      //}}AFX_MSG
  
      DECLARE_MESSAGE_MAP()
  };
  
  /////////////////////////////////////////////////////////////////////////////
  
  //{{AFX_INSERT_LOCATION}}
  // Microsoft Visual C++ will insert additional declarations immediately before the previous line.
  
  #endif // !defined(AFX_OWNDRAWSLIDER_H__82981708_4CBC_4D1E_8982_504E99BE489D__INCLUDED_)
  </code></pre>
  
  <p>Here is the OwnDrawSlider class cpp:</p>
  
  <pre><code>    // OwnDrawSlider.cpp : implementation file
  //
  
  #include "stdafx.h"
  #include "OwnDrawSlider.h"
  
  #ifdef _DEBUG
  #define new DEBUG_NEW
  #undef THIS_FILE
  static char THIS_FILE[] = __FILE__;
  #endif
  
  /////////////////////////////////////////////////////////////////////////////
  // COwnDrawSlider
  
  COwnDrawSlider::COwnDrawSlider()
  {
      black_brush.CreateSolidBrush(RGB(0,0,0));
  }
  
  COwnDrawSlider::~COwnDrawSlider()
  {
  }
  
  
  BEGIN_MESSAGE_MAP(COwnDrawSlider, CSliderCtrl)
      //{{AFX_MSG_MAP(COwnDrawSlider)
      ON_WM_PAINT()
      ON_WM_CTLCOLOR()
      ON_WM_ERASEBKGND()
      //}}AFX_MSG_MAP
  END_MESSAGE_MAP()
  
  /////////////////////////////////////////////////////////////////////////////
  // COwnDrawSlider message handlers
  
  void COwnDrawSlider::OnPaint() 
  {
      CPaintDC dc(this); // device context for painting
  
      // TODO: Add your message handler code here
      CRect channelRect,thumbRect;
      GetChannelRect(&amp;channelRect);
      GetThumbRect(&amp;thumbRect);
  
      GetClientRect(&amp;channelRect);
      thumbRect=channelRect;
      channelRect.top+=5;
      channelRect.bottom-=5;
      int mid=(channelRect.top+channelRect.bottom)/2;
      int w=channelRect.right-channelRect.left;
      int pos=GetPos();
      int minVal,maxVal;
      GetRange(minVal,maxVal);
      thumbRect.left=(pos-minVal)*w/(maxVal-minVal);
      thumbRect.right=thumbRect.left+(channelRect.right-channelRect.left)*0.025f;
      thumbRect.top+=12;
      thumbRect.bottom-=12;
      //draw the channel
      //CBrush whiteBrush(RGB(255,255,255));
      //dc.SelectObject(whiteBrush);
      //dc.FrameRect(&amp;channelRect,&amp;whiteBrush);
      //draw the thumb
      CBrush yellowBrush(RGB(255,255,0));
      dc.SelectObject(yellowBrush);
      dc.Ellipse(&amp;thumbRect);
  
      CFont myFont;
      myFont.CreatePointFont(96,"Tahoma");
      dc.SetBkColor(RGB(0,0,0));
      dc.SetTextColor(RGB(255,255,255));
  
      dc.SelectObject(&amp;myFont);
      char msg[128];
      sprintf(msg,"%d",pos);
      CRect msgRect=thumbRect;
      msgRect.top=thumbRect.bottom;
      msgRect.bottom=msgRect.top+16;
      int mid0=(thumbRect.left+thumbRect.right)/2;
      msgRect.left=mid0-6*strlen(msg);
      msgRect.right=mid0+6*strlen(msg);
      dc.DrawText(msg,strlen(msg),&amp;msgRect,DT_CENTER);
  
      sprintf(msg,"%d",minVal);
      msgRect.left=channelRect.left;
      msgRect.right=channelRect.left+12*strlen(msg);
      dc.DrawText(msg,strlen(msg),&amp;msgRect,DT_LEFT);
  
      sprintf(msg,"%d",maxVal);
      msgRect.left=channelRect.right-12*strlen(msg);
      msgRect.right=channelRect.right;
      dc.DrawText(msg,strlen(msg),&amp;msgRect,DT_RIGHT);
  
      //draw the axis
      CPen yellowPen(PS_SOLID,3,RGB(255,255,255));
      dc.SelectObject(yellowPen);
      dc.MoveTo(channelRect.left,mid);
      dc.LineTo(channelRect.right,mid);
      dc.MoveTo(channelRect.left,channelRect.top+12);
      dc.LineTo(channelRect.left,channelRect.bottom-12);
      dc.MoveTo(channelRect.right,channelRect.top+12);
      dc.LineTo(channelRect.right,channelRect.bottom-12);
  
      CPen thinPen(PS_SOLID,1,RGB(255,255,0));
      dc.SelectObject(thinPen);
      int numTick=GetNumTics();
      DWORD* ptick=GetTicArray();
      float pixelPerTick=w*1.0/numTick;
      for(int i=0;i&lt;numTick;i++)
      {
          dc.MoveTo((ptick[i])*pixelPerTick+channelRect.left,mid-3);
          dc.LineTo((ptick[i])*pixelPerTick+channelRect.left,mid+3);
      }
  
      // Do not call CSliderCtrl::OnPaint() for painting messages
  }
  
  HBRUSH COwnDrawSlider::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 
  {
      HBRUSH hbr = CSliderCtrl::OnCtlColor(pDC, pWnd, nCtlColor);
  
      // TODO: Change any attributes of the DC here
  
      // TODO: Return a different brush if the default is not desired
      return black_brush;
  }
  
  BOOL COwnDrawSlider::OnEraseBkgnd(CDC* pDC) 
  {
      // TODO: Add your message handler code here and/or call default
      RECT client;
      GetClientRect(&amp;client);
      //COLORREF color=pDC-&gt;GetBkColor();
      COLORREF color=::GetSysColor(COLOR_WINDOW);
      //FillRect(pDC-&gt;m_hDC,&amp;client,::GetStockObject(GRAY_BRUSH));
      //pDC-&gt;FillSolidRect(&amp;client,color);
      pDC-&gt;FillSolidRect(&amp;client,RGB(0,0,0));
      return true;//do not call OnEraseBkgrnd, it will fill it white
      //return CSliderCtrl::OnEraseBkgnd(pDC);
  }
  </code></pre>
  
  <p>Create the slider using program (no resource associated with it):</p>
  
  <pre><code>pFrameSlider=new COwnDrawSlider();
  pFrameSlider-&gt;Create(WS_CHILD|WS_VISIBLE|BS_OWNERDRAW|TBS_HORZ|TBS_AUTOTICKS,rButton,this,ID_FRAME_SLIDER);
  //pFrameSlider-&gt;SizeToContent();
  pFrameSlider-&gt;SetTicFreq(50);
  pFrameSlider-&gt;ShowWindow(SW_SHOW);
  </code></pre>
  
  <p>In the parent window, the NM_RELEASECAPTURE is trapped. When created, the rect=[9,57,384,822]. The rect obtained by the GetChannelRect is [19,23, 8, 40]. and the mouse operation is limited in this rect.
  My question is: why the two rect are so different? How can I change the channel rect by program (without any resource associated with it)?</p>