How are components displayed?

Source: Internet
Author: User
How are components displayed? Development and Application of VCL Components
Http://www.delphi2007.net/DelphiVCL/html/delphi_20061225141614123.html
The same is a control derived from a base class, such as twinctrol. The display is different, such as BUTTON and STRINGGRID. When I look at the CREATE FUNCTION, it seems that only the initial test value is assigned to the basic parameter, after a widget is placed in a window, it is displayed. How is it displayed? How is this process handled? In other words, what functions does it call to implement display controls? How does the style of Controls change to various types? How can I encapsulate a widget to display it in its own style?

To answer your questions, you can write a book. You are advised to read the entry book or complete the book to understand it.

Generally, you can call the TCanvas method or the interface drawn by the gdi api function.
This is easy to draw. Generally, you can find a lot of time and date controls on the Internet. There are a lot of relatively simple and easy to understand, and then follow his painting, what do you want to draw?

To: maozefa (AFA)
I know that the scope of the question is too large. I have read some of the introductory books, such as inside vcl, Master breakthrough, D5 guide, and so on. I have only understood about 70%, I always feel that he knows what he is talking about, but he only knows rationally. He doesn't have a perceptual knowledge, or he understands the truth, but does not know how to start his work, we hope we can find a control, such as a BUTTON, to explain its entire implementation process. With the source code, but always returns without attack. Can you give me some basic books that meet my requirements. By the way, do you have any books dedicated to component development? There are also books on the detailed Syntax of DELPHI, because when I read VCL, I found that some grammar books are not introduced at all, such as the DEFAULT keyword. I can only look at Dong's rough views for help in English, the flexible use of the introduced knowledge is of little help, so I hope to find a detailed book.

To: zhangcheng125 (old wolf)
Can you give me a specific name for the time control you mentioned? I can search for the following: Thank you. I feel that the work of writing controls still requires a lot of windowsAPI knowledge.

In fact, writing controls is not very difficult, just to learn drawing well, such as the TCANVAS class in DELPHI, there is a part about GDI in windows api, as for the time control, there are many in the DELPHI box. You can go and have a look. I personally think that as long as I have learned this knowledge, I can write out all of his components (all components are drawn out. :)

After work, I wrote a rough one, hoping to help you.

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 (old wolf)
Thank you. It is very helpful. take the opportunity to ask a question:
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;
There is a default keyword in all. In the help section, it is not a default value. It is used to determine whether to store attribute values. It doesn't quite understand what it means. Please explain it.

Write a widget by yourself: Draw a GRID-like widget.
The specific method is to draw in the TScrollBox control. The Code is as follows:
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 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 defaults 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.

Several Problems encountered:
1. My idea is to call the Paint function when the WMPaint event occurs in the system. The Paint function calls DrawCell to complete the drawing and provides an interface to implement OnDrawCell. After implementation, when the form is minimized and re-opened, or overwritten by other hull, the image is not re-painted. The cause is that the WM_PAINT message is not generated and the control part is blocked, when some of the failure zones are valid, a message should be generated, and the message should be processed. However, check the implementation of TDRAWGRID in VCL and do not understand how it works.
2. How to generate a scroll bar when the width is greater than the container (TScrollBox.

3. What books can be learned to solve the above problems?

Thank you.

First, let's explain the Default problem. Default means that the value after Default is saved to the dfm file of the form, instead of the Default value. If you want to specify the Default value, you must specify it in the constructor.

--------------------------
1. In the re-painting problem, you do not need to call the Paint function in the WMPAINT message. The WMPAINT function will call the PAINT function. In addition, the Canvas is an attribute of TGraphicControl, so you can use it directly. You don't need to write this: Canvas. handle: = GetDC (FContainer. handle.

2. About the scroll bar. I do this in general, for example, the vertical scroll bar, the truth is:
12321321
32323232 ---------- top
43434343 scroll bar
43434343 ---------- Bottom
Based on the sliding distance of the current scroll bar, draw the painting that is not displayed in the header outside the display area, that is, when painting: for example, a region TRect, set its Top to negative, in this way, you can draw non-displayed items outside the area (this is based on the calculation of the sliding distance of the scroll bar slider to determine the maximum value of the TOp). The same is true for horizontal scroll bars.

3. For this type of problem, the best learning is to look at others' source code. I have read some basic source code and found some things in practice.


Some of the above are not clear or wrong (I tried it in my own practice, but it still works, huh, huh ), I hope you can forgive me for any improper or unclear information. If you have time, I can write an example of a simple scroll bar for the landlord.

Learning

TO: zhangcheng125 (old wolf)
"I hope you will forgive me for any improper or unclear information." --- I am not sure that I am here to ask you a question. You can't answer it anymore. As for the problem of Default, it is clear from your wealth that reading Chinese is comfortable and helpful, but not thorough. However, there are still a lot of funny syntaxes that have not been mentioned in general grammar books. For example, I don't know which basic grammar book you are reading, so I 'd like to recommend it to you :)
1. I intentionally used WMPAINT to call the PAINT function because I checked the VCL source code of DRAWGRID. Its WMPAINT does not seem to call the PAINT function, (it may also be called in the WMPAINT in the parent object earlier, but I did not trace it and did not clear the clue, so I simply wrote it over ), in the PAINT, the corresponding ONDRAWCELL is detected, but the system does not respond to the WMPAINT. It is in a depressing ing state and cannot understand how to connect a WMPAINT message, or how to avoid it. (The reason why the wmpaint message is not generated is that the Code is not executed at all ). Do you know why?
"Canvas. Handle: = GetDC (FContainer. Handle ." -- Because FContainer is a TScrollBox object instance. My idea is to draw the table into this control. I originally wanted to use TPANEL, but he didn't have a scroll bar, so I chose TScrollBox. although CANVAS is encapsulated and can be used directly, the corresponding control cannot be drawn without giving the handle to it. If you do not draw a picture directly, you can save the implementation of some attributes, such as ALIGN. In addition, you can use it directly if you have a scroll bar. You can draw a picture yourself and do more work.
2. the implementation method of the scroll bar you mentioned is listened to by Dong, but the figure does not look at Dong. In addition, if I want to implement it, there may be successive problems, I am not afraid of problems, but want to solve the current problems first.

Finally, thanks to zhangcheng125 (old wolf), there are still many problems. Sorry for the delay. However, I know that you are not trying to score either, right? :), but I cannot go through it. Haha, I hope you will give me more advice in the future.


Today I confirmed that other controls derived from TGraphicControl, such as TBevel, are drawn by rewriting the Paint method. I directly derived one and only changed the Paint method, however, the result is that it will respond to the WMPAINT message, and sometimes it will not. Back to the original control, the painting method is also rewritten. Why can't this problem be solved.

Solve the problem. At first, some of my basic attributes are not initialized. After initialization, the problem is solved. The Canva mentioned in zhangcheng125 (old wolf) can be used directly.

Finally, I would like to thank zhangcheng125 (old wolf) for further instructions.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.