在对话框上设计一个三角形的按钮

我们知道MAC中提供的都是矩形的按钮,但是如果你想要得到三角形的怎么办呢?接下来我就教大家怎么做

1.在对话框上直接拖放一个button,修改其ID和caption。

2.添加一个.h和.cpp文件

这是.h文件  // TriangleButton.h : header file
/
// Copyright (C) 1997 by Janus Kjempff
// All rights reserved

// class CTriangleButton shows a triangle button pointing in one of four
// directions (UP, DOWN, LEFT, RIGHT), and works like the CButton MFC class
// Please distribute, but don't remove my name from the source or
// documentation (don't take credit for my work), mark your changes (don't
// get me blamed for your possible bugs), don't alter or remove this
// notice.


// No warrantee of any kind, express or implied, is included with this
// software; use at your own risk, responsibility for damages (if any) to
// anyone resulting from the use of this software rests entirely with the
// user.


// Note: I copy/pasted the structure of this class from the class CRoundButton
// Thanx to Chris Maunder who made the CRoundButton class in the first place.
// The OnNCHitTest function was in the CRoundButton class, but though
// I have implemented it, I don't know what it should do (it is therefore
// outcommented at the moment, but feel free to "unlock" it if it is
// anything useful)

// reach me at jak@sign-tronic.dk

// Preaching: Microsoft explorer is a fatal stupidity, remove it from windows
// again (no need not to learn by mistake)


#ifndef __TRIANGLEBUTTON_H__INCLUDED
#define __TRIANGLEBUTTON_H__INCLUDED



class CTriangleButton : public CButton
{
public:
enum POINTDIRECTION {POINT_UP, POINT_DOWN, POINT_LEFT, POINT_RIGHT};

// Construction
public:
CTriangleButton();
virtual ~CTriangleButton();

// Attributes
public:

protected:
POINTDIRECTION PointDirection;
CRgn CurrentRegion;

// Operations
public:

// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CTriangleButton)
public:
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
protected:
virtual void PreSubclassWindow();
//}}AFX_VIRTUAL

public:
//note: SetWindowPos decreases the cx, cy parameter to nearest number dividable by two
BOOL SetWindowPos(const CWnd* pWndInsertAfter, int x, int y, int cx, int cy, UINT nFlags );

// Implementation
public:
void SetDirection(POINTDIRECTION PointDirection); //sets the direction of triangle
POINTDIRECTION GetDirection(); //gets the direction of triangle

// Generated message map functions
protected:
//{{AFX_MSG(CTriangleButton)
//}}AFX_MSG

DECLARE_MESSAGE_MAP()
};


#endif // __TRIANGLEBUTTON_H__INCLUDED

 

这是.cpp文件

 // TriangleButton.cpp : implementation file
//

#include "stdafx.h"
#include "math.h"
#include "TriangleButton.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/
// CTriangleButton

CTriangleButton::CTriangleButton()
{
PointDirection = POINT_RIGHT;
}

CTriangleButton::~CTriangleButton()
{
}

BEGIN_MESSAGE_MAP(CTriangleButton, CButton)
//{{AFX_MSG_MAP(CRoundButton)
ON_WM_NCHITTEST()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()


void CTriangleButton::SetDirection(POINTDIRECTION Direction)
{
PointDirection = Direction;
PreSubclassWindow();
}

CTriangleButton::POINTDIRECTION CTriangleButton::GetDirection()
{
return PointDirection;
}



BOOL CTriangleButton::SetWindowPos(const CWnd* pWndInsertAfter, int x, int y, int cx, int cy, UINT nFlags)
{
//Size must be dividable by two (else triangle will look strange when drawn)
cx -= cx % 2; cy -= cy % 2;
//TRACE("x=%i y=%i\n", cx, cy);
return CButton::SetWindowPos(pWndInsertAfter, x, y, cx, cy, nFlags);
}


/
// CRoundButton message handlers

void CTriangleButton::PreSubclassWindow()
{
CButton::PreSubclassWindow();

//get client rectangle
CRect rect;
GetClientRect(rect);
rect.bottom = rect.right = min(rect.bottom,rect.right); //make it square
rect.bottom -= rect.bottom % 2; rect.right -= rect.right % 2;

SetWindowPos(NULL, 0, 0, rect.right, rect.bottom, SWP_NOMOVE | SWP_NOZORDER);

CPoint Head, RightLeg, LeftLeg;

switch (PointDirection) {
case POINT_UP :
Head.x = rect.right / 2; Head.y = 0;
RightLeg.x = rect.right; RightLeg.y = rect.bottom;
LeftLeg.x = 0; LeftLeg.y = rect.bottom;
break;
case POINT_DOWN :
Head.x = rect.right / 2; Head.y = rect.bottom;
RightLeg.x = 0; RightLeg.y = 0;
LeftLeg.x = rect.right; LeftLeg.y = 0;
break;
case POINT_LEFT :
Head.x = 0; Head.y = rect.bottom / 2;
RightLeg.x = rect.right; RightLeg.y = 0;
LeftLeg.x = rect.right; LeftLeg.y = rect.bottom;
break;
case POINT_RIGHT :
Head.x = rect.right; Head.y = rect.bottom / 2;
RightLeg.x = 0; RightLeg.y = rect.bottom;
LeftLeg.x = 0; LeftLeg.y = 0;
break;
default :
ASSERT(FALSE);
}//switch

CPoint points[3];
points[0] = Head; points[1] = RightLeg; points[2] = LeftLeg;

SetWindowRgn(NULL, FALSE);

CurrentRegion.DeleteObject();
CurrentRegion.CreatePolygonRgn(points, 3, ALTERNATE);

SetWindowRgn(CurrentRegion, TRUE);

ModifyStyle(0, BS_OWNERDRAW);
}


void CTriangleButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
ASSERT(lpDrawItemStruct != NULL);
CRect rect = lpDrawItemStruct->rcItem;
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
UINT state = lpDrawItemStruct->itemState;
UINT nStyle = GetStyle();

int nSavedDC = pDC->SaveDC();

//make the rect a square
rect.bottom = rect.right = min(rect.bottom, rect.right);
pDC->FillSolidRect(rect, ::GetSysColor(COLOR_BTNFACE));

rect.right -= 1; rect.bottom -= 1; //avoid drawing outside area

//make some pens
CPen HighlightPen(PS_SOLID, 1, ::GetSysColor(COLOR_3DHIGHLIGHT));
CPen DarkShadowPen(PS_SOLID, 1, ::GetSysColor(COLOR_3DDKSHADOW));
CPen ShadowPen(PS_SOLID, 1, ::GetSysColor(COLOR_3DSHADOW));
CPen BlackPen(PS_SOLID, 1, RGB(0,0,0));
//NOTE: If U use this class for NT apps only, use the implementation of FocusPen below
// instead, as WIN95 doesn't support this yet (though the doc says **dang ms-fools**)
// (WIN98 might also support this)
//LOGBRUSH logbrush; logbrush.lbStyle = BS_SOLID; logbrush.lbColor = RGB(0,0,0); logbrush.lbHatch = NULL;
//CPen FocusPen(PS_COSMETIC | PS_ALTERNATE, 1, &logbrush);
CPen FocusPen(PS_DOT, 0, RGB(0,0,0));


//Draw button
switch (PointDirection) {
case POINT_UP : {
//Draw the raised/sunken edges of the button (unless flat)
if (nStyle & BS_FLAT) { //style is flat
pDC->SelectObject(BlackPen);
pDC->MoveTo(rect.right / 2, 0);
pDC->LineTo(0, rect.bottom);
pDC->LineTo(rect.right, rect.bottom);
pDC->LineTo(rect.right / 2, 0);
pDC->SelectObject(HighlightPen);
pDC->MoveTo(rect.right / 2, 2);
pDC->LineTo(2, rect.bottom - 1);
pDC->LineTo(rect.right - 2, rect.bottom - 1);
pDC->LineTo(rect.right / 2, 2);
} else { //style not flat
if ((state & ODS_SELECTED)) { //Button is down
pDC->SelectObject(HighlightPen);
pDC->MoveTo(0, rect.bottom);
pDC->LineTo(rect.right - 1, rect.bottom);
pDC->LineTo(rect.right / 2, 0);

pDC->SelectObject(ShadowPen);
pDC->LineTo(0, rect.bottom);

pDC->SelectObject(DarkShadowPen);
pDC->MoveTo(rect.right / 2 - 1, 4);
pDC->LineTo(1, rect.bottom);
} else { //Button is not down
pDC->SelectObject(HighlightPen);
pDC->MoveTo(rect.right /2, 0);
pDC->LineTo(0, rect.bottom - 1);

pDC->SelectObject(ShadowPen);
pDC->LineTo(rect.right - 1, rect.bottom - 1);
pDC->LineTo(rect.right / 2, 0);

pDC->SelectObject(DarkShadowPen);
pDC->MoveTo(rect.right / 2 + 2, 3);
pDC->LineTo(rect.right + 1, rect.bottom + 1);

pDC->MoveTo(rect.right - 1, rect.bottom);
pDC->LineTo(1, rect.bottom);
}//else|if
}//else|if
break;
}//case

case POINT_DOWN : {
//Draw the raised/sunken edges of the button (unless flat)
if (nStyle & BS_FLAT) { //style is flat
pDC->SelectObject(BlackPen);
pDC->MoveTo(rect.right / 2, rect.bottom);
pDC->LineTo(0, 0);
pDC->LineTo(rect.right, 0);
pDC->LineTo(rect.right / 2, rect.bottom);

pDC->SelectObject(HighlightPen);
pDC->MoveTo(rect.right / 2, rect.bottom - 2);
pDC->LineTo(2, 1);
pDC->LineTo(rect.right - 2, 1);
pDC->LineTo(rect.right / 2, rect.bottom - 2);
} else { //style not flat
if ((state & ODS_SELECTED)) { //Button is down
pDC->SelectObject(ShadowPen);
pDC->MoveTo(rect.right, 1);
pDC->LineTo(1, 1);
pDC->LineTo(rect.right / 2, rect.bottom - 1);

pDC->SelectObject(BlackPen);
pDC->MoveTo(rect.right - 2, 2);
pDC->LineTo(1, 2);

pDC->SelectObject(HighlightPen);
pDC->MoveTo(rect.right + 1, 0);
pDC->LineTo(rect.right / 2 + 1, rect.bottom + 1);

} else { //Button is not down
pDC->SelectObject(ShadowPen);
pDC->MoveTo(0, 0);
pDC->LineTo(rect.right / 2, rect.bottom);
pDC->LineTo(rect.right, 0);
pDC->MoveTo(1, 1);
pDC->LineTo(rect.right / 2 + 1, rect.bottom);

pDC->SelectObject(DarkShadowPen);
pDC->MoveTo(rect.right, 2);
pDC->LineTo(rect.right / 2 + 1, rect.bottom + 1);

pDC->SelectObject(HighlightPen);
pDC->MoveTo(0, 0);
pDC->LineTo(rect.right, 0);

}
}//else|if
break;
}//case

case POINT_LEFT : {
if (nStyle & BS_FLAT) { //style is flat
pDC->SelectObject(BlackPen);
pDC->MoveTo(rect.right, 0);
pDC->LineTo(0, rect.bottom / 2);
pDC->LineTo(rect.right, rect.bottom);
pDC->LineTo(rect.right, 0);

pDC->SelectObject(HighlightPen);
pDC->MoveTo(rect.right - 1, 2);
pDC->LineTo(3, rect.bottom / 2);
pDC->LineTo(rect.right - 1, rect.bottom - 2);
pDC->LineTo(rect.right - 1, 2);
} else { //style not flat
if ((state & ODS_SELECTED)) { //Button is down
pDC->SelectObject(ShadowPen);
pDC->MoveTo(rect.right, 0);
pDC->LineTo(0, rect.bottom / 2);

pDC->SelectObject(DarkShadowPen);
pDC->MoveTo(rect.right, 1);
pDC->LineTo(2, rect.bottom / 2);

pDC->SelectObject(HighlightPen);
pDC->MoveTo(rect.right, 0);
pDC->LineTo(rect.right, rect.bottom);
pDC->LineTo(0, rect.bottom / 2);
} else { //Button is not down
pDC->SelectObject(ShadowPen);
pDC->MoveTo(rect.right - 1, 0);
pDC->LineTo(rect.right - 1, rect.bottom - 1);
pDC->LineTo(0, rect.bottom / 2);
pDC->MoveTo(1, rect.bottom / 2 + 1);
pDC->LineTo(6, rect.bottom / 2 + 4);

pDC->SelectObject(DarkShadowPen);
pDC->MoveTo(rect.right, 1);
pDC->LineTo(rect.right, rect.bottom);
pDC->LineTo(2, rect.bottom / 2 + 2);

pDC->SelectObject(HighlightPen);
pDC->MoveTo(0, rect.bottom / 2);
pDC->LineTo(rect.right, 0);
}
}//else|if
break;
}//case

case POINT_RIGHT : {
if (nStyle & BS_FLAT) { //style is flat
pDC->SelectObject(BlackPen);
pDC->MoveTo(0, 0);
pDC->LineTo(rect.right, rect.bottom / 2);
pDC->LineTo(0, rect.bottom);
pDC->LineTo(0, 0);

pDC->SelectObject(HighlightPen);
pDC->MoveTo(1, 2);
pDC->LineTo(rect.right - 2, rect.bottom / 2);
pDC->LineTo(1, rect.bottom - 2);
pDC->LineTo(1, 2);
} else { //style not flat
if ((state & ODS_SELECTED)) { //Button is down
pDC->SelectObject(ShadowPen);
pDC->MoveTo(0, rect.bottom);
pDC->LineTo(0, 0);
pDC->LineTo(rect.right, rect.bottom / 2);

pDC->SelectObject(DarkShadowPen);
pDC->MoveTo(1, rect.bottom - 2);
pDC->LineTo(1, 1);
pDC->MoveTo(rect.right - 3, rect.bottom / 2);
pDC->LineTo(0, 1);

pDC->SelectObject(HighlightPen);
pDC->MoveTo(0, rect.bottom);
pDC->LineTo(rect.right, rect.bottom / 2);

} else { //Button is not down
pDC->SelectObject(ShadowPen);
pDC->MoveTo(0, rect.bottom);
pDC->LineTo(rect.right, rect.bottom / 2);

pDC->SelectObject(DarkShadowPen);
pDC->MoveTo(0, rect.bottom + 1);
pDC->LineTo(rect.right, rect.bottom / 2 + 1);

pDC->SelectObject(HighlightPen);
pDC->MoveTo(0, rect.bottom);
pDC->LineTo(0, 0);
pDC->LineTo(rect.right, rect.bottom / 2);
}
}//else|if

break;
}//case

default :
ASSERT(FALSE);
}//switch


//Draw text if any
CString strText;
GetWindowText(strText);
if (!strText.IsEmpty()) {
CSize TextExtent = pDC->GetTextExtent(strText);
CPoint TextPos;
pDC->SetBkMode(TRANSPARENT);

switch (PointDirection) {
case POINT_UP : {
TextPos = CPoint((int)(rect.right / 2.0 - TextExtent.cx / 2.0),
rect.bottom - (int)(rect.bottom / 5.0 + TextExtent.cy));

int iXLimit = (int)((rect.bottom / 5.0 + TextExtent.cy) * 4.0 / 7.0);

CRgn rgn; rgn.CreateRectRgn(iXLimit, TextPos.y, rect.right - iXLimit, rect.bottom - 2);
pDC->SelectClipRgn(&rgn);

break;
}//case
case POINT_DOWN : {
TextPos = CPoint((int)(rect.right / 2.0 - TextExtent.cx / 2.0),
(int)(rect.bottom / 5.0));

int iXLimit = (int)((rect.bottom / 5.0 + TextExtent.cy) * 4.0 / 7.0);

CRgn rgn; rgn.CreateRectRgn(iXLimit, (int)(rect.bottom / 5.0), rect.right - iXLimit, (int)(rect.bottom / 5.0) + TextExtent.cy + 2);
pDC->SelectClipRgn(&rgn);

break;
}

case POINT_LEFT : {
TextPos = CPoint((int)((rect.right / 2.0 - TextExtent.cx / 2.0) + (rect.right / 8.0)),
(int)(rect.bottom / 2.0 - TextExtent.cy / 2.0) );

int iXLimitLeft = (int)(TextExtent.cy / 2.0 * 7.0 / 4.0) + 4;
int iXLimitRight = rect.right - 4;

CRgn rgn; rgn.CreateRectRgn(iXLimitLeft, (int)(rect.bottom / 2.0 - TextExtent.cy / 2.0),
iXLimitRight, (int)(rect.bottom / 2.0 + TextExtent.cy / 2.0) );
pDC->SelectClipRgn(&rgn);

break;
}//case

case POINT_RIGHT : {
TextPos = CPoint((int)((rect.right / 2.0 - TextExtent.cx / 2.0) - (rect.right / 8.0)),
(int)(rect.bottom / 2.0 - TextExtent.cy / 2.0) );

int iXLimitLeft = 4;
int iXLimitRight = rect.right - (int)(TextExtent.cy / 2.0 * 7.0 / 4.0) - 4;

CRgn rgn; rgn.CreateRectRgn(iXLimitLeft, (int)(rect.bottom / 2.0 - TextExtent.cy / 2.0),
iXLimitRight, (int)(rect.bottom / 2.0 + TextExtent.cy / 2.0) );
pDC->SelectClipRgn(&rgn);

break;
}//case

default :
ASSERT(FALSE);
}//switch

//common for all directions
if (state & ODS_SELECTED) TextPos.Offset(1,1);

if (state & ODS_DISABLED) {
pDC->DrawState(TextPos, TextExtent, strText, DSS_DISABLED, TRUE, 0, (HBRUSH)NULL);
} else {
pDC->TextOut(TextPos.x, TextPos.y, strText);
}

}//if


//Draw the focus triangle on the inside of the button if we have focus
if ((state & ODS_FOCUS)) {
CRgn rgn; rgn.CreateRectRgn(rect.left, rect.top, rect.right, rect.bottom);
pDC->SelectClipRgn(&rgn);
pDC->SelectObject(FocusPen);
switch (PointDirection) {
case POINT_UP : {
pDC->MoveTo(rect.right / 2, 12);
pDC->LineTo(9, rect.bottom - 6);
pDC->LineTo(rect.right - 9, rect.bottom - 6);
pDC->LineTo(rect.right / 2, 12);
break;
}
case POINT_DOWN : {
pDC->MoveTo(rect.right / 2 + 1, rect.bottom - 13);
pDC->LineTo(10, 6);
pDC->LineTo(rect.right - 9, 6);
pDC->LineTo(rect.right / 2 + 1, rect.bottom - 13);
break;
}
case POINT_LEFT : {
pDC->MoveTo(12, rect.bottom / 2);
pDC->LineTo(rect.right - 6, 9);
pDC->LineTo(rect.right - 6, rect.bottom - 9);
pDC->LineTo(12, rect.bottom / 2);
break;
}//case
case POINT_RIGHT : {
pDC->MoveTo(6, 9);
pDC->LineTo(rect.right - 12, rect.bottom / 2);
pDC->LineTo(6, rect.bottom - 9);
pDC->LineTo(6, 9);
break;
}//case

default :
ASSERT(FALSE);
}//switch
}//if

pDC->RestoreDC(nSavedDC);

}

/* I'm not sure what this function is supposed to do, but it was in the
CRoundButton class i used to make this class, so I have implemented it, though
I don't know what the function should do ! (if it is nescessary just remove comments)
UINT CTriangleButton::OnNcHitTest(CPoint point)
{
ScreenToClient(&point);
if (CurrentRegion.PtInRegion(point)) {
//TRACE("HTCLIENT: %i, %i\n", point.x, point.y);
return HTCLIENT;
}
else {
//TRACE("HTNOWHERE: %i, %i\n", point.x, point.y);
return HTNOWHERE;
}
}
*/


这个类提供了操作的方法,直接使用就可以了

3. 定义CTriangleButton行变量。然后在 DoDataExchange中直接用DDX_Control(pDX, IDC_BYNRUN,RunBTN);调用就可以了。运行看看,是不是你的也button也变成了三角形?

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值