C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 팁&트릭
C++Builder Programming Tip&Tricks
[1008] 빌더6에서 TSpeedButton을 상위 에디션처럼 만들기.
김태선 [cppbuilder] 17679 읽음    2010-08-14 12:00
TSpeedButton 스피드버턴은 화면 디자인에 매우 유용한 컴포넌트입니다.
특히 배경 그림 위에 버턴을 올려 놓고 Flat = true로 할 경우 배경 위에 버턴 외곽과 바탕이
투명화 되기 때문에 디자인시 매우 유용합니다.
그런데 빌더6 에서는 좀 만족스럽지 못합니다.

스피드버턴에 마우스 커서를 올리거나 클릭할 때 그냥 사각형 외각이 그려지기 때문에 모양이 안 삽니다.
그기에 비해 빌더 2007이나 2010등 상위 버전의 스피드 버턴은 마우스가 올라갔을 때와 클릭시
모양이 예쁩니다.

이와 비슷하게 빌더6에서 스피드 버턴을 개조해 봅시다.

개조하지 않고 이쁜 모양이 버턴 컴포넌트를 찾아서 설치해서 사용해도 되고,
상위 에디션으로 개발툴 갈아타기를 해도 됩니다.
하지만 빠르고 편리한 빌더6를 애용하는 분들도 있기 때문에 한번 개조하는 쪽으로 해 봅시다.

사실상 새로운 컴포넌트를 만들어야 하지만,
프로그래밍에 있어 유지 보수가 더 편리한 것은 컴포넌트 교체식이므로
컴포넌트 교체식으로 구현하겠습니다.

이를 위해서는 TSpeedButton 클래스의 Paint() 메소드를 오버라이드 하면 됩니다.
Paint() 메소드에서 버턴을 최종적으로 그리기 때문에,
TSpeedButton을 상속 받아, Paint() 메소드를 다시 만들어 주는 방법을 쓰면 됩니다.


#ifndef __TSpeedButton_H
#define __TSpeedButton_H

//---------------------------------------------------------------------------
// speed 버턴: 마우스가 올라왔을때와 클릭했을때 좀더 멋진 효과를 주기 위한 것이다.
//
// Written by KTS.

class TSpeedButton : public Buttons::TSpeedButton
{
	typedef Buttons::TSpeedButton     inherited;
private:
	struct TF
	{
		int FGroupIndex;
		void *FGlyph;
		bool FDown;
		bool FDragging;
		bool FAllowAllUp;
		TButtonLayout FLayout;
		int FSpacing;
		bool FTransparent;
		int FMargin;
		bool FFlat;
		bool FMouseInControl;
	};
	TF*    GetF() 
	{
		return (TF*)((UINT)this + sizeof(Controls::TGraphicControl));
	}

	bool	FStateIn(TButtonState aa, TButtonState ab)
	{
		if (FState == aa || FState == ab)
			return true;
		return false;
	}
public:
	void __fastcall Paint()
	{
		int DownStyles[2] = { BDR_RAISEDINNER, BDR_SUNKENOUTER };
		int FillStyles[2] = { BF_MIDDLE, 0 };

		TRect  	PaintRect;
		int  	DrawFlags;
		TPoint  Offset;
		TF	*F = GetF();

		if (!Enabled)
		{
			FState = bsDisabled;
			F->FDragging = false;
		}
		else if (FState == bsDisabled)
		{
			if (F->FDown && (GroupIndex != 0))
				FState = bsExclusive;
			else
				FState = bsUp;
		}
		Canvas->Font = this->Font;
		PaintRect = Rect(0, 0, Width, Height);
		if (!F->FFlat)
		{
			DrawFlags = DFCS_BUTTONPUSH | DFCS_ADJUSTRECT;
			if (FStateIn(bsDown, bsExclusive))
				DrawFlags = DrawFlags | DFCS_PUSHED;
			DrawFrameControl(Canvas->Handle, &PaintRect, DFC_BUTTON, DrawFlags);
		}
		else
		{
			if ((FStateIn(bsDown, bsExclusive)) ||
				(F->FMouseInControl &&(FState != bsDisabled)) ||
				ComponentState.Contains(csDesigning))
			{
				if (FStateIn(bsDown, bsExclusive))
				{
					Canvas->Pen->Color = clGray;
					Canvas->Brush->Color = (TColor)0x00EBEBEB;
				}
				else
				{
					Canvas->Pen->Color = clSilver;
					Canvas->Brush->Color = (TColor)0x00FFF2E8; 
				}
				Canvas->RoundRect(PaintRect.left, PaintRect.top, PaintRect.right, PaintRect.bottom, 5, 5);
			}
			else if (!Transparent)
			{
				Canvas->Brush->Color = Color;
				Canvas->FillRect(PaintRect);
			}
			InflateRect(&PaintRect, -1, -1);
		}
		if (FStateIn(bsDown, bsExclusive))
		{
			if ((FState == bsExclusive) && (!F->FFlat || !F->FMouseInControl))
			{
				Canvas->Brush->Bitmap = AllocPatternBitmap(clBtnFace, clBtnHighlight);
				Canvas->FillRect(PaintRect);
			}
			Offset.x = 1;
			Offset.y = 1;
		}
		else
		{
			Offset.x = 0;
			Offset.y = 0;
		}
		// 아래 3줄은 컴파일을 위해 추가 작업을 해야 함.
		TButtonGlyph *bg = (TButtonGlyph *)F->FGlyph;
		bg->Draw(Canvas, PaintRect, Offset, Caption, F->FLayout, F->FMargin,
			F->FSpacing, FState, Transparent, DrawTextBiDiModeFlags(0));
	}
};
#define TSpeedButton	::TSpeedButton
//---------------------------------------------------------------------------
#endif


이 소스를
TForm1.h 의 class TForm1  위에 include 해주면 됩니다.
소스는 첨부 파일로 올려 놨으니 다운로드해서 간단히 이용할 수 있습니다.

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "TSpeedButton.h"
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// IDE-managed Components
	TImage *Image1;
	TSpeedButton *SpeedButton1;
	TPanel *Panel1;
	TSpeedButton *SpeedButton2;
	TSpeedButton *SpeedButton3;
	TSpeedButton *SpeedButton4;
	TSpeedButton *SpeedButton5;
	void __fastcall FormCreate(TObject *Sender);
private:	// User declarations
public:		// User declarations
	__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif


그런데 컴파일 하면 소스의 하단부에 주석을 달아 놨듯이
3줄이 컴파일이 안됩니다.

이는 TButtonGlyph 클래스를 참조할 수 없어서입니다.
이 클래스는 VCL 소스의 Buttons.pas의 implementation 부에 있습니다.
그러니 그것을 활용하면 되겠지요.
어떻게 하면 해결할 수 있는지는 각자의 숙제로 남겨 두겠습니다.


이건 배경 그림 위에 스피드 버턴을 flat 모드로 올려 놓은 것

이건 마우스 오버시

이건 마우스 클릭시


이 정도 모양이면 Toolbar로 활용해도 손색이 없습니다.
Flat == false 시는 이전과 모양이 같은데 이는 위 소스를 아주 조금만 손보면
모서리가 둥근 버턴 등으로 쉽게 개조할 수 있습니다.
칼라도 고정했는데, 프로퍼티로 조절할 수 있도록 하는 것도 좋을 것입니다.


여기서는 스피드 버턴 개조의 기본틀을 제시한 것이고,
보다 멋진 것으로 만드는 것은 각자의 몫입니다.
원래 RS2010처럼 스피드 버턴을 만드려면 그라데이션을 고려해 그려주거나
윈도우의 Theme를 활용해야겠지만 그럴려면 소스가 좀 길어지겠죠.
여기서 필자가 제시하는 가치는 자신의 것으로서 C++빌더에서 임의로 개조할 수 있다는 것입니다.

그럼.
지금 시작 [rncjsdn2002]   2010-08-26 15:50 X
숙제로 남기신거 힌트좀 주세요 ㅠ.ㅠ 벌써 3시간째 헤매고있습니다....

+ -

관련 글 리스트
1008 빌더6에서 TSpeedButton을 상위 에디션처럼 만들기. 김태선 17679 2010/08/14
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.