解答你的问题可以写书了,建议看看入门书或者大全书,就了解了
一般通过调用TCanvas的方法或是GDI的API函数画出的界面。
这个要做的多了画起来就得心应手了,一般可以去找网上很多的时间日期控件,有很多比较简单的,很容易看懂,然后就照着他的画,你想画什么样的就画什么样的,呵呵
To: maozefa(阿发伯)
我知道问的问题有点范围太大了,入门的书也看了一点,比如inside vcl、高手突破、D5指南什么的,只看明白了百分之70左右,总是感觉他讲什么知道,但是只是理性上的认识,没有感性认识,或者说,明白其中的道理,但是让自己作就又不知道如何下手了,希望可以找到以一个控件比如BUTTON为主线讲其整个实现过程。跟过源码,但是总是无攻而返。能不能再给建议一些符合我情况要求的基本的书。顺便问一下,有没有专门介绍关于组件开发的书籍呢?还有关于DELPHI详细语法的书籍,因为看VCL时发现一些语法书上根本就没有介绍,比如说DEFAULT关键字等,看英文帮助总是只能看董个大概,对所介绍知识的灵活运用帮助不大,所以希望能找到一本详细点的书籍。
To:zhangcheng125(老狼)
你说的时间控件能不能给说一个具体的名称,我好搜索以下,谢谢。感觉写控件这个工作还是需要windowsAPI的知识比较多。
其实写控件并不是很难的东西,只是要学好画图的,像DELPHI里的TCANVAS类,还有就是WINDOWS API中关于GDI的部份,至于时间控件,在DELPHI盒子里很多的,可以去下来看看。个人认为只要把画图的这方面的知识学好了,管他什么组件都可以写出来(组件都是画出来的。:)
下班了,粗粗的写了一个,希望对你有帮助。
unit TestButtons;
interface
uses
SysUtils, Classes, Controls, Buttons, Windows, Messages, Graphics;
type
TTestButton = class(TCustomControl)
private
FShowEdge: Boolean;
FEdgeColor: TColor;
FEdgeWidth: Integer;
procedure SetShowEdge(const Value: Boolean);
procedure SetEdgeColor(const Value: TColor);
procedure SetEdgeWidth(const Value: Integer);
{ Private declarations }
protected
{ Protected declarations }
procedure Paint; override;
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
published
{ Published declarations }
property Caption;
property Color;
property Font;
property ShowEdge: Boolean read FShowEdge write SetShowEdge default True;
property EdgeColor: TColor read FEdgeColor write SetEdgeColor default clBlack;
property EdgeWidth: Integer read FEdgeWidth write SetEdgeWidth default 1;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Samples', [TTestButton]);
end;
{ TTestButton }
constructor TTestButton.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FShowEdge := True;
FEdgeColor := clBlack;
FEdgeWidth := 1;
end;
procedure TTestButton.Paint;
var
R: TRect;
procedure DrawTexts(AText: string; ARect: TRect);
begin
DrawText(Canvas.Handle, PChar(AText), -1, ARect, DT_CENTER or DT_VCENTER or DT_SINGLELINE);
end;
begin
inherited Paint;
R := ClientRect;
Canvas.Brush.Color := Color;
Canvas.Brush.Style := bsSolid;
Canvas.Pen.Width := EdgeWidth;
Canvas.Pen.Color := EdgeColor;
Canvas.Pen.Style := psSolid;
if ShowEdge then
Canvas.Rectangle(ClientRect);
InflateRect(R, -EdgeWidth, -EdgeWidth);
Canvas.Font.Assign(Font);
DrawTexts(Caption, R);
end;
procedure TTestButton.SetEdgeColor(const Value: TColor);
begin
if Value <> FEdgeColor then
begin
FEdgeColor := Value;
Repaint;
end;
end;
procedure TTestButton.SetEdgeWidth(const Value: Integer);
begin
if Value <> FEdgeWidth then
begin
FEdgeWidth := Value;
Repaint;
end;
end;
procedure TTestButton.SetShowEdge(const Value: Boolean);
begin
if Value <> FShowEdge then
begin
FShowEdge := Value;
Repaint;
end;
end;
end.
TO:zhangcheng125(老狼)
谢谢,很有帮助,借机会问个问题:
property ShowEdge: Boolean read FShowEdge write SetShowEdge default True;
property EdgeColor: TColor read FEdgeColor write SetEdgeColor default clBlack;
property EdgeWidth: Integer read FEdgeWidth write SetEdgeWidth default 1;
中都有个default关键字,帮助中说不是默认值,是用来决定是否存储属性值,不太理解什么含义,麻烦给解释一下。
自己试着写个控件:主要是画个类似GRID控件。
具体做法是在TScrollBox控件中来画,代码如下:
unit test;
interface
uses
Windows, Controls, Forms, Classes, Graphics, Messages, dialogs;
type
TStatu = (bgNormal, bgSelected, bgMouseIn);
TCellInfo = record
Rect: TRect;
Index: Integer;
Status: TStatu;
end;
TBrxDrawGrid = class(TGraphicControl)
private
FAlign: TAlign;
FContainer: TScrollBox;
FMax: Integer;
FRow: Integer;
FCol: Integer;
FCellWidth: Integer;
FCellHeight: Integer;
FSpRow: Integer;
FSpCol: Integer;
FClientWidth: Integer;
FClientHeight: Integer;
FCIArray: Array of Array of TCellInfo;
procedure SetAlign(Value: TAlign);
procedure SetMax(const Value: Integer);
function GetMax: Integer;
procedure SetRow(const Value: Integer);
procedure SetCol(const Value: Integer);
procedure SetCellWidth(const Value: Integer);
procedure SetCellHeight(const Value: Integer);
procedure SetSpRow(const Value: Integer);
procedure SetSpCol(const Value: Integer);
procedure SetClientHeight(const Value: Integer);
procedure SetClientWidth(const Value: Integer);
procedure InitCIArray(const Row, Col: Integer);
procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
protected
procedure SetCellInfo(const Row, Col: Integer);
procedure DrawCell;
published
property Align: TAlign read FAlign write SetAlign default alNone;
property RowCount: Integer read FRow write SetRow default 5;
property ColCount: Integer read FCol write SetCol default 5;
property DefaultColWidth: Integer read FCellWidth write SetCellWidth default 64;
property DefaultRowHeight: Integer read FCellHeight write SetCellHeight default 24;
property SpaceOfRow: Integer read FSpRow write SetSpRow default 1;
property SpaceOfCol: Integer read FSpCol write SetSpCol default 1;
property Height: Integer read FClientHeight write SetClientHeight default 120;
property Width: Integer read FClientWidth write SetClientWidth default 320;
public
constructor Create(AOwner: TComponent); override;
procedure Paint; override;
function GetCellCount: Integer;
function GetHandle: HWND;
end;
implementation
{ TBrxDrawGrid }
constructor TBrxDrawGrid.Create(AOwner: TComponent);
var
Max: Integer;
begin
inherited Create(AOwner);
FContainer := TScrollBox.Create(AOwner);
FContainer.Parent := TWinControl(AOwner);
FContainer.Align := alNone;
SetRow(5);
SetCol(5);
SetCellWidth(64);
SetCellHeight(24);
SetSpRow(1);
SetSpCol(1);
Max := 25;
SetMax(Max);
InitCIArray(5, 5);
end;
procedure TBrxDrawGrid.DrawCell;
var
i, j: Integer;
begin
Canvas.Handle := GetDC(FContainer.Handle);
Canvas.Pen.Color := clRed;
Canvas.Brush.Color := clBlue;
for i := 0 to FRow - 1 do
begin
for j := 0 to FCol - 1 do
begin
Canvas.Rectangle(FCIArray[i][j].Rect);
end;
end;
end;
function TBrxDrawGrid.GetCellCount: Integer;
begin
Result := GetMax;
end;
function TBrxDrawGrid.GetHandle: HWND;
begin
Result := FContainer.Handle;
end;
function TBrxDrawGrid.GetMax: Integer;
begin
Result := FMax;
end;
procedure TBrxDrawGrid.InitCIArray(const Row, Col: Integer);
var
i, j: Integer;
begin
SetLength(FCIArray, Row, Col);
for i := 0 to Row - 1 do
begin
for j := 0 to Col - 1 do
begin
FCIArray[i][j].Rect.Left := j * (FCellWidth + FSpCol);
FCIArray[i][j].Rect.Top := i * (FCellHeight + FSpRow);
FCIArray[i][j].Rect.Right := FCIArray[i][j].Rect.Left + FCellWidth;
FCIArray[i][j].Rect.Bottom := FCIArray[i][j].Rect.Top + FCellHeight;
FCIArray[i][j].Index := i * Col + j;
FCIArray[i][j].Status := bgNormal;
end;
end;
end;
procedure TBrxDrawGrid.Paint;
begin
inherited;
DrawCell;
end;
procedure TBrxDrawGrid.SetAlign(Value: TAlign);
begin
if FAlign <> Value then
begin
FAlign := Value;
FContainer.Align := FAlign;
end;
end;
procedure TBrxDrawGrid.SetCellHeight(const Value: Integer);
begin
if FCellHeight <> Value then
begin
FCellHeight := Value;
InitCIArray(FRow, FCol);
end;
end;
procedure TBrxDrawGrid.SetCellInfo(const Row, Col: Integer);
begin
end;
procedure TBrxDrawGrid.SetCellWidth(const Value: Integer);
begin
if FCellWidth <> Value then
begin
FCellWidth := Value;
InitCIArray(FRow, FCol);
end;
end;
procedure TBrxDrawGrid.SetClientHeight(const Value: Integer);
begin
if FClientheight <> Value then
begin
FClientHeight := Value;
FContainer.Height := FClientHeight;
end;
end;
procedure TBrxDrawGrid.SetClientWidth(const Value: Integer);
begin
if FClientWidth <> Value then
begin
FClientWidth := Value;
FContainer.Width := FClientWidth;
end;
end;
procedure TBrxDrawGrid.SetCol(const Value: Integer);
begin
if FCol <> Value then
begin
FCol := Value;
InitCIArray(FRow, FCol);
end;
end;
procedure TBrxDrawGrid.SetMax(const Value: Integer);
begin
if FMax <> Value then
begin
FMax := Value;
end;
end;
procedure TBrxDrawGrid.SetRow(const Value: Integer);
begin
if FRow <> Value then
begin
FRow := Value;
InitCIArray(FRow, FCol);
end;
end;
procedure TBrxDrawGrid.SetSpCol(const Value: Integer);
begin
if FSpCol <> Value then
begin
FSpCol := Value;
InitCIArray(FRow, FCol);
end;
end;
procedure TBrxDrawGrid.SetSpRow(const Value: Integer);
begin
if FSpRow <> Value then
begin
FSpRow := Value;
InitCIArray(FRow, FCol);
end;
end;
procedure TBrxDrawGrid.WMPaint(var Message: TWMPaint);
begin
Paint;
end;
end.
碰到几个问题:
1.我的思路是系统发生WMPaint事件,调用Paint函数,Paint函数调用DrawCell,DrawCell完成画图工作并提供接口实现OnDrawCell。实现之后,当窗体最小化再打开,或是被其他船体覆盖后,所画的图形消失,并没有重画,分析原因是因为没有产生WM_PAINT消息,控件部分被挡住,当部分失效区有效时应该会产生个消息,应该对这个消息作处理,但是查看VCL中TDRAWGRID的实现,没有弄明白他这一点是如何作的。
2.但宽度大于容器(TScrollBox)时,如何让其产生滚动条。
3.以上诸如此类的问题,通过学习什么书籍可以掌握解决方法?
谢谢
首先说明一下Default的问题,Default 是指将Default后面的值保存到窗体的dfm文件中并不是指定默认值,如果要指定默认值的话要在构造函数中给定。
--------------------------
1.重绘的问题中你不用在WMPAINT消息下调用Paint函数,WMPAINT函数本来就会调用PAINT函数的。还有就是Canvas本就是TGraphicControl的一个属性,所以直接用就行了,不用去写这个:Canvas.Handle := GetDC(FContainer.Handle);了,再就是我不懂你为什么要选创建个FContainer,直接画不就行了。
2.关于滚动条。我一般是这么做的自绘滚动条,比方说垂直的滚动条,道理是:
12321321
32323232 ----------top
43434343 滚动条
43434343 ----------Bottom
根据当前滚动条滑动的距离把头部不显示出来的画在显示区域外,也就是画的时候:比方一个区域TRect,那么就设他的Top为负的,这样就能把不显示的画在区域外面,(这要根据计算滚动条滑块滑动距离来得出TOp为负多少)同理水平滚动条也一样。
3.诸如此类问题,最好的学习是看别人的源代码,我是看了一些基础的源代码后自己在实践中摸索的一些东西
以上个人觉的有些没讲清楚,也可能是错的(全是我自己实践中尝试出来的,不过还算行还能用,呵呵),有不当或是不清楚的地方还望楼主和各位见谅,有空我可以写个简单的滚动条的例子给楼主。
学习
TO:zhangcheng125(老狼)
"有不当或是不清楚的地方还望楼主和各位见谅"---这我可不敢当,本来就是在向你请教问题,你能回答已经感不尽了。至于Default的问题现在脱您的富很清楚了,读中文就是舒服,帮助可以看懂,但是理解的不透彻。但是还有很多语法好笑一般语法书中也都没有提到过,比如重新声明什么的,不知道你看的是哪本基础的语法书籍,给推荐一下吧 :)
1.我故意用WMPAINT调用PAINT是因为我看了一下DRAWGRID的VCL源码,它的WMPAINT好像没有调用PAINT函数,(也可能在更早的父代对象中的WMPAINT中就调用了,但是我没有跟踪出来,没有掠清头绪,干脆就覆写了它),在PAINT中相应ONDRAWCELL,但是发现系统就没有响应WMPAINT,正在郁闷ing中,想不明白怎么连一个WMPAINT消息都没有产生,或者说没有相应。(之所以说没有产生wmpaint消息,是因为其中代码根本没执行)。各位知道是什么原因吗?
“Canvas.Handle := GetDC(FContainer.Handle);了,再就是我不懂你为什么要选创建个FContainer,直接画不就行了。”--因为FContainer这个本身是一个TScrollBox对象实例。我的想法是将表格画到这个控件里,本来开始想采用TPANEL,但是他没有滚动条,所以就选择了TScrollBox.虽然CANVAS被封装可以直接使用,但是不将句柄给他就画不到对应控件上。不直接画是因为可以省去一些属性的实现,比如说ALIGN等等,而且他有滚动条,可以直接拿来用,舍得自己画还要做更多的工作。
2.你说的滚动条的实现方法,我是听董了,但是图没有看董,还有就是我想要是真的实现起来可能还会有接连不断的问题随之而来,不是怕遇到问题,只是想先解决目前的问题。
最后,谢谢zhangcheng125(老狼),目前还不会结帖,因为还有很多问题困扰。所以分迟迟不能发,请见谅。不过我知道您也不是为了分数对吧:),只是我心里过不去。哈哈,还希望以后多多指教。
今天又确认了一下,其他从TGraphicControl派生下来的控件比如说TBevel,就是通过改写Paint方法来实现绘制的,我直接派生了一个,只改写了Paint方法,但是结果是又是会响应WMPAINT消息,有时又不会,赶到纳闷。在回到原来的控件上来,同样也是改写了Paint方法,为什么就不行呢,希望高人指点。
问题解决,开始是我有些基本属性没有初始化,初始化后问题解决。还有前面zhangcheng125(老狼)所说的Canva可以直接使用,是我多此一举了。
最后再次感谢zhangcheng125(老狼),以后还请多指教。