Einzelnen Beitrag anzeigen

DualCoreCpu
(Gast)

n/a Beiträge
 
#1

Eigene Ellipsen- und Arc Funktion funktioniert nicht. Warum?

  Alt 7. Nov 2015, 13: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?
  Mit Zitat antworten Zitat