|
Antwort |
DualCoreCpu
(Gast)
n/a Beiträge |
#1
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:
Und nun meine Funktionen:
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.
Delphi-Quellcode:
Meine Ellipse erscheint außerdem schwarz gefüllt. Warum?
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. |
Zitat |
DualCoreCpu
(Gast)
n/a Beiträge |
#2
Das soll noch kein Push sein, habe nur die folgenden Funktionen wie folgt geändert. Dabei funktioniert die Arc Funktion noch immer überhaupt nicht, die Ellipse wird jetzt korrekt gezeichnet, ist jedoch nicht, wie im Originaldemo weiß gefüllt, sondern schwarz, obwohl ich nur die Ellipsenfunktion getauscht habe.
Delphi-Quellcode:
Die komplette Ellipse wird inzwischen korrekt gezeichnet, ist aber nicht weiß, sindern schwarz gefüllt. Wie also wird die Füllfarbe übergeben?
function Arc(dc: HDC; Left, Top, Right, Bottom, xStart, yStart, xEnd, yEnd: Integer): BOOL;
var xm, ym, a,b, startgd, endgrad: Integer; //Hier eine Funktion zur Winkelberechnung aus den x,y Koordinaten von Start und Ende des Bogens function _angle(xS,yS,x,y: Integer): Integer; begin if (xS<x) and (yS<y) then begin startgd := Round(arctan2(-xS, -yS)); delta := Round(arctan2(-yS, -xS)); startgd := startgd + delta * 2; Result := startgd; end else if (xS<x) and (yS>y) then begin startgd := Round(arctan2(yS, -xS)); delta := Round(arctan2(-xS, yS)); startgd := startgd + round(2*pi); Result := startgd; end else if (xS>x) and (yS>y) then begin startgd := Round(arctan2(xS, yS)); delta := Round(arctan2(yS, xS)); startgd := startgd + delta*2 + round(2*pi); Result := startgd; end; end; begin xm := Left + Abs(Right - Left) div 2; ym := Top + Abs(Bottom - Top) div 2; a := Right - xm; b := Bottom - ym; //startgd := Round(arctan2(xStart, yStart)); //endgrad := Round(arctan2(xEnd, yEnd)); //Hier will ich die korrekten Winkel berechnen. Laut MSDN nimmt die Arc() Funktion keinerlei //Korrekturen der Koordinaten vor, die müssen also vorher berechnet werden. Meine //Ellipsenfunktionen setzen aber auf Start- und Endwinkel. Diese will ich mit arctan() //berechnen, xStart,yStart,xEnd,yEnd werden ja übergeben und wenn die Strahlen passend //verlängert werden, schneiden sie auch einen Kreis mit gleichem Mittelpunkt. //Oben habe ich eine Unterfunktion, die mir den Winkel ebenso berechnet und die ich statt der //Winkelwerte in meine EllipseSeg Funktion eingesetzt habe. if (xStart<xm) and (yStart<ym) then begin startgd := Round(arctan2(-xStart, -yStart)); delta := Round(arctan2(-yStart, -xStart)); startgd := startgd + delta * 2; end else if (xStart<xm) and (yStart>ym) then begin startgd := Round(arctan2(yStart, -xStart)); delta := Round(arctan2(-xStart, yStart)); startgd := startgd + round(2*pi); end else if (xStart>xm) and (yStart>ym) then begin startgd := Round(arctan2(xStart, yStart)); delta := Round(arctan2(yStart, xStart)); startgd := startgd + delta*2 + round(2*pi); end; case _theArcDirection_ of AD_COUNTERCLOCKWISE: begin DrawEllipseSeg(dc, xm, ym, _angle(xStart,yStart,xm,ym), _angle(xEnd,yEnd,xm,ym), a, b, GetDCPenColor(dc)); end; AD_CLOCKWISE: begin //So hatte ich die Winkelwerte vorher eingesetzt, jetzt aber wie oben //bei AD_COUNTERCLOCKWISE 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 := Left + Abs(Right - Left) div 2; ym := Top + 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 := Left + Abs(Right - Left) div 2; ym := Top + 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; Warum funktioniert die Füllung im Original, aber nicht in meiner Funktion? Ich bleibe dran!. Geändert von DualCoreCpu ( 7. Nov 2015 um 21:56 Uhr) |
Zitat |
Ansicht |
Linear-Darstellung |
Zur Hybrid-Darstellung wechseln |
Zur Baum-Darstellung wechseln |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
LinkBack URL |
About LinkBacks |