(Gast)
n/a Beiträge
|
Eigene Ellipsen- und Arc Funktion funktioniert nicht. Warum?
7. Nov 2015, 14:30
Hallo, ich habe gerade Luckies Windows API Tutorial in Arbeit und wollte gerade mal die Arc- und die Ellipdenfunktion nachbauen.
Die gibt es zwar im Windows API schon. Da ich aber mal wieder meine verschütteten Mathe Kenntnisse auffrischen will, wobei mit das reine Lehrbuchstudium zu stupide ist, hab ich mich entschlossen, diese Funktionen nachzubauen, was ja ohne Mathekenntisse unmöglich sein dürfte.
Leider ist meine eigene Ellipse zu groß und die Location stimmt auch nicht, der Mittelpunkt meiner eigenen Ellipse ist die linke obere Ecke, ich möchte aber, daß der Mittelpukt der Ellipse der gleiche ist, wie in Luckies Demo Programm.
Ich möchte also erreichen, daß sich meine eigene Arc- und Ellipse Funktion, auch meine Pie Funktion exakt genau so verhalten, wie die Originale aus dem Windows API.
Was mache ich falsch?
Hier ist mein Code, zuerst Luckies Demo:
Delphi-Quellcode:
program tut1;
{$APPTYPE CONSOLE}
uses
SysUtils,
Windows,
Messages,
arcs;
const
ClassName = ' DrawClass';
AppName = ' Zeichnen';
WindowWidth = 500;
WindowHeight = 400;
function WndProc(hWnd: HWND; uMsg: UINT; wParam: wParam; lParam: LParam):
lresult; stdcall;
var
x, y : integer;
WndDC: HDC;
ps: TPaintStruct;
RedBrush, RedBrushOld: HBRUSH;
GreenHatchBrush, GreenHatchBrushOld: HBRUSH;
Pen, PenOld: HPEN;
begin
Result := 0;
case uMsg of
WM_CREATE:
begin
{ Fenster zentrieren }
x := GetSystemMetrics(SM_CXSCREEN);
y := GetSystemMetrics(SM_CYSCREEN);
MoveWindow(hWnd, (x div 2) - (WindowWidth div 2),
(y div 2) - (WindowHeight div 2),
WindowWidth, WindowHeight, true);
end;
WM_PAINT:
begin
WndDC := BeginPaint(hWnd, ps);
{ eine einfache Linie }
MoveToEx(WndDC, 20, 10, nil);
LineTo(WndDC, 20, 90);
{ ein Rechteck }
Rectangle(WndDC, 40, 10, 60, 90);
{ und das ganze gefüllt }
RedBrush := CreateSolidBrush( RGB(255, 0, 0));
RedBrushOld := SelectObject(WndDC, RedBrush);
Rectangle(WndDC, 80, 10, 100, 90);
{ alten Brush wieder herstellen und benutzten löschen }
SelectObject(WndDc, RedBrushOld);
DeleteObject(RedBrush);
{ und das ganze noch mal mit Muster }
GreenHatchBrush := CreateHatchBrush(HS_BDIAGONAL, RGB(0, 255, 0));
GreenHatchBrushOld := SelectObject(WndDC, GreenHatchBrush);
RectAngle(WndDC, 120, 10, 140, 90);
{ alten Brush wieder herstellen und benutzten löschen }
SelectObject(WndDC, GreenHatchBrushOld);
DeleteObject(GreenHatchBrush);
{ und nochmal mit einem anderen Stift }
Pen := CreatePen(PS_DOT, 1, RGB(0, 0, 255));
SetBkMode(WndDC, TRANSPARENT);
PenOld := SelectObject(WndDC, Pen);
RectAngle(WndDC, 160, 10, 180, 90);
SelectObject(WndDC, PenOld);
DeleteObject(Pen);
{ Ellipse }
Ellipse(WndDC, 30, 110, 180, 200);
{ Kreis }
Ellipse(WndDC, 80, 130, 130, 180);
{ Chord }
Chord(WndDC, 220, 110, 300, 200, 280, 120, 190, 230);
{ Pie }
Pie(WndDC, 300, 110, 500, 200, 310, 110, 200, 260);
{ RoundRect }
RoundRect(WndDC, 30, 220, 180, 350, 35, 35);
EndPaint(hWnd, ps);
end;
WM_DESTROY: PostQuitMessage(0);
else
Result := DefWindowProc(hWnd, uMsg, wParam, lParam);
end;
end;
var
wc: TWndClassEx = (
cbSize : SizeOf(TWndClassEx);
Style : CS_HREDRAW or CS_VREDRAW;
lpfnWndProc : @WndProc;
cbClsExtra : 0;
cbWndExtra : 0;
hbrBackground : COLOR_APPWORKSPACE;
lpszMenuName : nil;
lpszClassName : ClassName;
hIconSm : 0;
);
msg: TMsg;
begin
{ TODO -oUser -cConsole Main : Insert code here }
wc.hInstance := hInstance;
wc.hIcon := LoadIcon(hInstance, IDI_WINLOGO);
wc.hCursor := LoadCursor(0, IDC_ARROW);
RegisterClassEx(wc);
CreateWindowEx(0, ClassName, AppName, WS_CAPTION or WS_VISIBLE or WS_SYSMENU,
CW_USEDEFAULT, CW_USEDEFAULT, WindowWidth, WindowHeight, 0, 0, hInstance, nil);
while GetMessage(msg, 0,0,0) do
begin
TranslateMessage(msg);
DispatchMessage(msg);
end;
end.
Und nun meine Funktionen:
Delphi-Quellcode:
unit arcs;
interface
uses
Windows, math;
function Arc( dc: HDC; Left, Top, Right, Bottom, xStart, yStart, xEnd, yEnd: Integer): BOOL;
function Ellipse( dc: HDC; left,Top,Right,Bottom: Integer): BOOL;
function Pie( dc: HDC; Left, Top, Right, Bottom, xStart, yStart, xEnd, yEnd: Integer): BOOL;
implementation
var _theArcDirection_: Longint = AD_COUNTERCLOCKWISE;
procedure DrawCircleSeg( Handle: HDC;X,Y,startgrd,endgrd,radius: Integer; Color: COLORREF);
var angle: Integer;
begin
for angle:=startGrd to endGrd do
begin
SetPixel( Handle,
Round(Radius * cos(angle * pi/180)) + x,
Round(Radius * sin(angle * pi/180)) + y,
Color
);
end;
MoveToEx( Handle, Round(radius * cos (Startgrd * pi/180)) + x, Round(radius * sin(startgrd * pi/180)) + y, nil);
LineTo( Handle,x,y);
LineTo( Handle,Round(radius * cos (endgrd * pi/180)) + x, Round(radius * sin(endgrd * pi/180)) + y);
end;
procedure DrawEllipseSeg( Handle: HDC;X,Y,startgrd,endgrd,Xradius,Yradius: Integer; Color: COLORREF);
var angle: Integer;
begin
case _theArcDirection_ of
AD_COUNTERCLOCKWISE:
for angle:=startGrd to endGrd do
begin
SetPixel( Handle,
Round(Xradius * cos(angle * pi/180)) + x,
Round(Yradius * sin(angle * pi/180)) + y,
Color
);
end;
AD_CLOCKWISE:
for angle:=endGrd downto startGrd do
begin
SetPixel( Handle,
Round(Xradius * cos(angle * pi/180)) + x,
Round(Yradius * sin(angle * pi/180)) + y,
Color
);
end;
end;
MoveToEx( Handle, Round(Xradius * cos (Startgrd * pi/180)) + x, Round(Yradius * sin(startgrd * pi/180)) + y, nil);
LineTo( Handle,x,y);
LineTo( Handle,Round(Xradius * cos (endgrd * pi/180)) + x, Round(Yradius * sin(endgrd * pi/180)) + y);
end;
procedure DrawCircleL( Handle: HDC; X,Y,R: Integer; Color: COLORREF);
var angle: Integer;
begin
for angle:=0 to 360 do
begin
SetPixel( Handle,
Round(R * cos(angle * pi/180)) + x,
Round(R * sin(angle * pi/180)) + y,
Color
);
end;
end;
procedure DrawEllipseL( Handle: HDC; X,Y,a,b: Integer; Color: COLORREF);
var angle: Integer;
begin
for angle:=0 to 360 do
begin
SetPixel( Handle,
Round(a * cos(angle * pi/180)) + x,
Round(b * sin(angle * pi/180)) + y,
Color
);
end;
end;
{filled ellipse}
procedure DrawEllipseF( Handle: HDC; xc,yc,a,b: Integer; Color: COLORREF);
var x,y:integer; aa,aa2,bb,bb2,d,dx,dy:longint;
begin
x:=0;y:=b;
aa:=longint(a)*a; aa2:=2*aa;
bb:=longint(b)*b; bb2:=2*bb;
d:=bb-aa*b+aa div 4;
dx:=0;dy:=aa2*b;
MoveToEx( Handle, xc,yc-y, nil);
LineTo( Handle,xc,yc+y); { original vLin mit denselben Parametern }
while(dx<dy) do begin
if(d>0) then begin dec(y); dec(dy,aa2); dec(d,dy); end;
inc(x); inc(dx,bb2); inc(d,bb+dx);
MoveToEx( Handle,xc-x,yc-y, nil);
LineTo( Handle,xc-x,yc+y);
MoveToEx( Handle,xc+x,yc-y, nil);
LineTo( Handle,xc+x,yc+y); { original vLin mit denselben Parametern }
end;
inc(d,(3*(aa-bb) div 2-(dx+dy)) div 2);
while(y>=0) do begin
if(d<0) then begin
inc(x); inc(dx,bb2); inc(d,bb+dx);
MoveToEx( Handle,xc-x,yc-y, nil);
LineTo( Handle,xc-x,yc+y);
MoveToEx( Handle,xc+x,yc-y, nil);
LineTo( Handle,xc+x,yc+y); { original vLin mit denselben Parametern }
end;
dec(y); dec(dy,aa2); inc(d,aa-dy);
end;
end;
function Arc( dc: HDC; Left, Top, Right, Bottom, xStart, yStart, xEnd, yEnd: Integer): BOOL;
var xm, ym, a,b, startgd, endgrad: Integer;
begin
xm := Abs(Right - Left) div 2;
ym := Abs(Bottom - Top) div 2;
a := Right - xm;
b := Bottom - ym;
startgd := Round(arctan2(xStart, yStart));
endgrad := Round(arctan2(xEnd, yEnd));
case _theArcDirection_ of
AD_COUNTERCLOCKWISE:
begin
DrawEllipseSeg( dc, xm, ym, startgd, endgrad, a, b, GetDCPenColor( dc));
end;
AD_CLOCKWISE:
begin
DrawEllipseSeg( dc, xm, ym, endgrad, startgd, a, b, GetDCPenColor( dc));
end;
end;
end;
function Pie( dc: HDC; Left, Top, Right, Bottom, xStart, yStart, xEnd, yEnd: Integer): BOOL;
var xm, ym, a,b: Integer;
begin
xm := Abs(Right - Left) div 2;
ym := Abs(Bottom - Top) div 2;
a := Right - xm;
b := Bottom - ym;
SetArcDirection( dc, AD_COUNTERCLOCKWISE);
if Arc( dc, Left, Top, Right, Bottom, xStart, yStart, xEnd, YEnd) then
begin
MoveToEx( dc, xStart, xStart, nil);
LineTo( dc, xm, ym);
MoveToEx( dc, xEnd, yEnd, nil);
LineTo( dc, xm, ym);
end
end;
function Ellipse( dc: HDC; left,Top,Right,Bottom: Integer): BOOL;
var xm, ym, a,b: Integer;
begin
xm := Abs(Right - Left) div 2;
ym := Abs(Bottom - Top) div 2;
a := Right - xm;
b := Bottom - ym;
DrawEllipseL( dc, xm, ym, a-1, b-1, GetDCPenColor( dc)); //Begrenzungslinie
DrawEllipseF( dc, xm, ym, a-1, b-1, GetDCBrushColor( dc)); //Füllung
end;
end.
Meine Ellipse erscheint außerdem schwarz gefüllt. Warum?
|