所有者使用MFC绘制CSliderCtrl:为什么程序创建的滑块有不正确的通道矩形?

时间:2014-02-13 00:38:22

标签: windows mfc

我正在尝试实现一个所有者绘制CSliderCtrl。看起来绘图很好,但改变拇指位置的鼠标非常奇怪。它仅限于非常小的矩形。我发现GetChannelRect的rect比我用来创建滑块控件的rect要小得多。 下面是.h文件:

#if !defined(AFX_OWNDRAWSLIDER_H__82981708_4CBC_4D1E_8982_504E99BE489D__INCLUDED_)
#define AFX_OWNDRAWSLIDER_H__82981708_4CBC_4D1E_8982_504E99BE489D__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 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_)

这是OwnDrawSlider类cpp:

    // 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(&channelRect);
    GetThumbRect(&thumbRect);

    GetClientRect(&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(&channelRect,&whiteBrush);
    //draw the thumb
    CBrush yellowBrush(RGB(255,255,0));
    dc.SelectObject(yellowBrush);
    dc.Ellipse(&thumbRect);

    CFont myFont;
    myFont.CreatePointFont(96,"Tahoma");
    dc.SetBkColor(RGB(0,0,0));
    dc.SetTextColor(RGB(255,255,255));

    dc.SelectObject(&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),&msgRect,DT_CENTER);

    sprintf(msg,"%d",minVal);
    msgRect.left=channelRect.left;
    msgRect.right=channelRect.left+12*strlen(msg);
    dc.DrawText(msg,strlen(msg),&msgRect,DT_LEFT);

    sprintf(msg,"%d",maxVal);
    msgRect.left=channelRect.right-12*strlen(msg);
    msgRect.right=channelRect.right;
    dc.DrawText(msg,strlen(msg),&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<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(&client);
    //COLORREF color=pDC->GetBkColor();
    COLORREF color=::GetSysColor(COLOR_WINDOW);
    //FillRect(pDC->m_hDC,&client,::GetStockObject(GRAY_BRUSH));
    //pDC->FillSolidRect(&client,color);
    pDC->FillSolidRect(&client,RGB(0,0,0));
    return true;//do not call OnEraseBkgrnd, it will fill it white
    //return CSliderCtrl::OnEraseBkgnd(pDC);
}

使用程序创建滑块(没有与之关联的资源):

pFrameSlider=new COwnDrawSlider();
pFrameSlider->Create(WS_CHILD|WS_VISIBLE|BS_OWNERDRAW|TBS_HORZ|TBS_AUTOTICKS,rButton,this,ID_FRAME_SLIDER);
//pFrameSlider->SizeToContent();
pFrameSlider->SetTicFreq(50);
pFrameSlider->ShowWindow(SW_SHOW);

在父窗口中,捕获了NM_RELEASECAPTURE。创建时,rect = [9,57,384,822]。由GetChannelRect获得的rect是[19,23,8,40]。并且鼠标操作在此矩形中受到限制。 我的问题是:为什么两个矩形是如此不同?如何通过程序更改通道rect(没有任何与之关联的资源)?

0 个答案:

没有答案