Liniendiagramm

Stelle Fragen zur Programmierung mit Autohotkey

Moderator: jNizM

User avatar
nnnik
Posts: 4497
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Liniendiagramm

09 May 2017, 04:15

Falls du mit dem verwenden der library nicht klar kommst dann sag etwas.
Sie ist nicht ganz einfach zu verwenden. Ich habe hier einen Post auf englisch verfasst der kurz die Möglichkeiten und Optionen vorstellt.
Falls du noch besondere Funtionalität benötigst die noch nicht vorhanden ist, dann sag dies ruhig.
Heute Abend werde ich wieder Zeit haben zum Programmieren. Eventuell kannst du auch bei unserem Discord Server oder im IRC vorbei schauen, da kann man mich oft direkt erreichen.
Siehe dazu https://autohotkey.com/boards/viewtopic.php?f=5&t=59.
Recommends AHK Studio
User avatar
jNizM
Posts: 3098
Joined: 30 Sep 2013, 01:33
GitHub: jNizM
Contact:

Re: Liniendiagramm

09 May 2017, 05:46

Sieht doch schon mal vielversprechend aus =)

1) Baust du noch .drawLabel() ein, für die X- & Y-Achsenbeschriftung (z.B. Abhänig von 3ten gdipChart Parameter oder sogar selbst erstellbar)?

Code: Select all

; =============================================================================================
/*
	.drawLabel(xTitle, yTitle)

	Möglichkeit 1:
	- 2 Zahlen

	Möglichkeit 2:
	- 2 Werte (Zahlen oder Array mit Werten)
*/
; =============================================================================================

; Beispiel 1:
chart.new gdipChart(GuihWnd, "", [0, 0, 100, 100])
chart.drawLabel(5, 10)

/*
	xTitle -> 100 / 5  -> 20
	20 | 40 | 60 | 80 | 100

	yTitle -> 100 / 10 -> 10
	10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 | 90 | 100
*/

; ==================================================================

; Beispiel 2:
chart.new gdipChart(GuihWnd, "", [0, 0, 100, 120])
yTitle := ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]
chart.drawLabel(5, yTitle)

/*
	xTitle -> 100 / 5  -> 20
	20 | 40 | 60 | 80 | 100

	yTitle -> 120 / 6  -> 20
	Jan | Feb | Mar | Apr | May | Jun
*/

; ==================================================================
2) Alternatives Gitternetz, passend zu den Achsenbeschriftungen (sieh oben) (bsp Bild siehe unten)

3) Evtl. neben den farbigem DataStream (Graph) ein zusätzlichen für z.B. einen helleren bis zum Graphen aufgefülltem Hintergrund (z.B. .drawBackground(rgb) - die zu zeichnenden Daten währen z.B. Graph - 1px) (bsp Bild siehe unten)
Image
[AHK] v2.0-beta.15 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
nnnik
Posts: 4497
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Liniendiagramm

09 May 2017, 13:30

Ich habe noch vor ein X und Y Axis Objekt zu erstellen wo man die visibilität Farbe Dicke Ursprung, sowie auch Name und Einheit zu setzten.
Sowie ein Grid Objekt mit dem man die Eigenschaften des Grids verändern kann.
Ich habe definitiv zudem geplant Zeit auf die Achsen legen zu können ( quasi als Einheit ) und die Ausgabe der Daten dann verändern zu können.
Recommends AHK Studio
just me
Posts: 8600
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Liniendiagramm

09 May 2017, 15:42

nnnik wrote:Eventuell kannst du auch bei unserem Discord Server ...
Wer bitte ist in diesem Zusammenhang 'uns'?
Nmk
Posts: 28
Joined: 20 Jan 2017, 19:29

Re: Liniendiagramm

09 May 2017, 19:46

Danke für das Angebot. Sehr nett! Aber ich war so erpicht darauf das Diagramm fertigzustellen und dann sowas > ... beschäftige mich seit gut drei Tagen mit diversen JS Chart Bibliotheken, habe es mit d3.js endlich so hinbekommen wie ich es benötige ... UND DAS DING LÄUFT NICHT IM INTERNET EXPLORER! Es wäre doch dämlich, wenn ich gleich mit dem IE arbeiten würde. Firefox ist doch viel besser. :crazy: ... war schon mal spaßiger.

Aber wenn gdiChartLib weiter so vorangeht, sollte ich vielleicht einfach zwei Tage Pause machen und dann wiederkommen. :crazy: Mir brummt nämlich der Schädel.

@nnnik: Hierbei wird doch kein Bild erzeugt, sondern mittels SVG dargestellt. Richtig? Ist so ein Chart auch, bei Größenänderung der Gui, skalierbar?

N8

Nmk
User avatar
nnnik
Posts: 4497
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Liniendiagramm

10 May 2017, 01:11

Doch hier wird ein Bild erzeugt. Dieses Bild wird abhängig von der momentanen Scrollposition, Daten und der Größe des GUIs gezeichnet.
Sobald sich irgendwas davon verändert wird das ganze neu gezeichnet. Jedoch muss man im Moment die Klasse noch selber davon informieren, dass sie sich neu zeichnen muss - da sie nicht selber testet ob sich die Größe des Fensters/Controls verändert hat. Ich plane das jedoch Heute zu ändern.
Recommends AHK Studio
just me
Posts: 8600
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Liniendiagramm

12 May 2017, 05:39

Moin,
Nmk wrote:... Ich kann größtenteils Balkendiagramme verwenden. Dabei habe ich an „Progress“ gedacht ...
Ich habe mal eine alte Funktion von mir (__Diagramm__.ahk) überarbeitet und auf das für mich Wesentliche reduziert. Die erzeugte Bitmap skaliert recht gut, wenn man auf das Raster verzichtet, und es scheint auch relativ schnell zu sein. Ich habe das allerdings bisher nur 'recht grob' getestet:

Code: Select all

; ================================================================================================================================
; Drawing bar charts with GDI.
; ================================================================================================================================
Class BarChart {
   ; =============================================================================================================================
   ; Class variables
   ; HTML colors as BGR
   Static HTML := {Aqua: 0xFFFF00, Black: 0x000000, Blue: 0xFF0000, Fuchsia: 0xFF00FF, Gray: 0x808080, Green: 0x00FF00
                 , Lime: 0x00FF00, Maroon: 0x000080, Navy: 0x800000, Olive: 0x800080, Purple: 0x800080, Red: 0x0000FF
                 , Silver: 0xC0C0C0, Teal: 0x808000, White: 0xFFFFFF, Yellow: 0x00FFFF}
   Static DCB := DllCall("GetStockObject", "Int", 18, "UPtr") ; DC_BRUSH
   Static DCP := DllCall("GetStockObject", "Int", 19, "UPtr") ; DC_PEN
   ; =============================================================================================================================
   ; Instance variables
   Count := 0
   Colors := []
   Names := []
   Values := []
   MinVal := 9223372036854775807
   MaxVal := -9223372036854775808
   ; =============================================================================================================================
   ; Constructor
   ; Parameters:
   ;     Width    -  the width of the chart bitmap in pixels.
   ;     Height   -  the height of the chart bitmap in pixels.
   ;     BkgColor -  the background color used for the bitmap as HTML color name or RGB integer value (0xRRGGBB).
   ;                 Default: White
   ; =============================================================================================================================
   __New(Width, Height, BkgColor := "") {
      If (BkgColor <> "")
         If This.HTML.HasKey(BkgColor)
            This.BkgColor := This.HTML[BkgColor]
         Else
            This.BkgColor := ((BkgColor & 0x0000FF) << 16) | (BkgColor & 0x00FF00) | ((BkgColor & 0xFF0000) >> 16)
      Else
         This.BkgColor := This.HTML.White
      If (This.BkgColor = "")
         Throw Exception("Invalid parameter BkgColor: " . BkgColor)
      HDC := DllCall("GetDC", "Ptr", 0, "UPtr")
      MDC := DllCall("CreateCompatibleDC", "Ptr", HDC, "UPtr")
      MBM := DllCall("CreateCompatibleBitmap", "Ptr", HDC, "Int", Width, "Int", Height, "UPtr")
      DllCall("ReleaseDC", "Ptr", 0, "Ptr", HDC)
      If !(MDC) || !(MBM)
         Throw Exception(MDC ? "Couldn't create a bitmap!" : "Couldn't create a DC!")
      This.Width := Width
      This.Height := Height
      This.MDC := MDC
      This.MBM := MBM
      DllCall("ReleaseDC", "Ptr", 0, "Ptr", HDC)
      DllCall("SelectObject", "Ptr", This.MDC, "Ptr", This.MBM)
      DllCall("SelectObject", "Ptr", This.MDC, "Ptr", This.DCB)
      DllCall("SelectObject", "Ptr", This.MDC, "Ptr", This.DCP)
      This.Clear()
   }
   ; =============================================================================================================================
   ; Destructor
   __Delete() {
      If (This.MBM)
         DllCall("DeleteObject", "Ptr", This.MBM)
      If (This.MDC)
         DllCall("DeleteObject", "Ptr", This.MDC)
   }
   ; =============================================================================================================================
   ; Adds a row of values.
   ; Parameters:
   ;     Name     -  a name associated with the values (currently not used).
   ;     Color    -  the color used to draw the values as HTML color name or RGB integer value (0xRRGGBB).
   ;     Values   -  the values passed as array or as '|'-delimited list.
   ; =============================================================================================================================
   AddValues(Name, Color, Values) {
      This.CheckColor(Color, A_ThisFunc, "Color")
      This.Count++
      Return This.SetValues(This.Count, Name, Color, Values)
   }
   ; =============================================================================================================================
   ; Deletes a row of values or all values.
   ; Parameters:
   ;     Index    -  the index of the values to be removed. Pass 0 to remove all values.
   ; =============================================================================================================================
   DelValues(Index) {
      If Index Is Not Integer
         Return False
      If (Index < 0) || (Index > This.Count)
         Return False
      If (Index = 0) {
         This.Delete("Values")
         This.Count := 0
      }
      Else {
         This.Values.RemoveAt(Index)
         This.Count--
      }
      Return True
   }
   ; =============================================================================================================================
   ; Updates a row of values.
   ; Parameters:
   ;     Index    -  the index of the values to be updated.
   ;     Name     -  a name associated with the values (currently not used).
   ;     Color    -  the color used to draw the values as HTML color name or RGB integer value (0xRRGGBB).
   ;     Values   -  the values passed as array or as '|'-delimited list.
   ; =============================================================================================================================
   UpdValues(Index, Name, Color, Values) {
      This.CheckColor(Color, A_ThisFunc, "Color")
      If Index Is Not Integer
         Return False
      If (Index < 0) || (Index > This.Count)
         Return False
      Return This.SetValues(Index, Name, Color, Values)
   }
   ; =============================================================================================================================
   ; Clears the bitmap.
   ; You need to call this method before you update the bitmap.
   ; =============================================================================================================================
   Clear() {
      If !(This.MBM)
         Return False
      DllCall("SetDCBrushColor", "Ptr", This.MDC, "UInt", This.BkgColor)
      DllCall("SetDCPenColor", "Ptr", This.MDC, "UInt", This.BkgColor)
      DllCall("Rectangle", "Ptr", This.MDC, "UInt", 0, "UInt", 0, "UInt", This.Width, "UInt", This.Height)
      Return True
   }
   ; =============================================================================================================================
   ; Draws a grid.
   ; Parameters:
   ;     DeltaX      -  the horizontal distance of the vertical grid lines in pixels
   ;                    Default: 0 - no vertical grid
   ;     DeltaY      -  the vertical distance of the horizontal grid lines in pixels
   ;                    Default: 0 - no horizontal grid
   ;     GridColor   -  the color used for the grid lines as HTML color name or RGB integer value (0xRRGGBB)
   ;                    Default: Gray
   ; =============================================================================================================================
   DrawGrid(DeltaX := 0, DeltaY := 0, GridColor := "") {
      If DeltaX Is Not Integer
         Throw Exception("Invalid parameter DeltaX: " . DeltaX)
      If DeltaY Is Not Integer
         Throw Exception("Invalid parameter DeltaY: " . DeltaY)
      If (GridColor <> "")
         If This.HTML.HasKey(GridColor)
            GridColor := This.HTML[GridColor]
         Else
            GridColor := ((GridColor & 0x0000FF) << 16) | (GridColor & 0x00FF00) | ((GridColor & 0xFF0000) >> 16)
      Else
         GridColor := This.HTML.Gray
      If (GridColor = "")
         Throw Exception("Invalid parameter Color: " . GridColor)
      This.GridDX := DeltaX
      This.GridDY := DeltaY
      This.GridColor := GridColor
      DllCall("SetDCPenColor", "Ptr", This.MDC, "UInt", GridColor)
      If (DeltaY > 1) {
         Lines := Round(This.Height // DeltaY) - 1
         , VarSetCapacity(PointArr, Lines * 16, 0)
         , VarSetCapacity(PointCnt, Lines * 4, 0)
         , Addr1 := &PointArr
         , Addr2 := &PointCnt
         , Y := -1
         Loop, %Lines% {
            Y += DeltaY
            , Addr1 := NumPut(Y, NumPut(This.Width, NumPut(Y, Addr1 + 4, "Int"), "Int"), "Int")
            , Addr2 := NumPut(2, Addr2 + 0, "Int")
         }
         DllCall("PolyPolyline", "Ptr", This.MDC, "Ptr", &PointArr, "Ptr", &PointCnt, "UInt", Lines)
      }
      If (DeltaX > 1) {
         Lines := Round(This.Width // DeltaX) - 1
         , VarSetCapacity(PointArr, Lines * 16, 0)
         , VarSetCapacity(PointCnt, Lines * 4, 0)
         , Addr1 := &PointArr
         , Addr2 := &PointCnt
         , X := 0
         Loop, %Lines% {
            X += DeltaX
            , Addr1 := NumPut(This.Height, NumPut(X, NumPut(X, Addr1 + 0, "Int") + 4, "Int"), "Int")
            , Addr2 := NumPut(2, Addr2 + 0, "Int")
         }
         DllCall("PolyPolyline", "Ptr", This.MDC, "Ptr", &PointArr, "Ptr", &PointCnt, "UInt", Lines)
      }
      VarSetCapacity(PointArr, 0)
      , VarSetCapacity(PointCnt, 0)
      Return True
   }
   ; =============================================================================================================================
   ; Draws the bars.
   ; Parameters:
   ;     ScaleX   -  the width of a bar in pixels
   ;     Min      -  the minimum value to be used for the chart
   ;                 Default: "" - use the minimum of the passed values
   ;     Max      -  the maximum value to be used for the chart
   ;                 Default: "" - use the maximum of the passed values
   ;     Count    -  the maximum number of values used to draw the chart
   ;                 Default: "" - all values
   ; =============================================================================================================================
   DrawBars(ScaleX := "", Min := "", Max := "", Count := "") {
      If (This.Count < 1)
         Return False
      If (ScaleX = "")
         ScaleX := 1
      If (Min = "")
         Min := This.MinVal
      If (Max = "")
         Max := This.MaxVal
      If ScaleX Is Not Integer
         Throw Exception("Invalid parameter ScaleX: " . ScaleX)
      If Min Is Not Number
         Throw Exception("Invalid parameter Min: " . Min)
      If Max Is Not Number
         Throw Exception("Invalid parameter Max: " . Max)
      F := This.Height / (Max - Min)
      , D := ScaleX * This.Count
      , H := This.Height
      Loop, % This.Count {
         Values := This.Values[A_Index]
         , ValCount := Values.Length()
         , Bars := ((Count = "") || (Count > ValCount)) ? ValCount : Count
         , DllCall("SetDCBrushColor", "Ptr", This.MDC, "UInt", This.Colors[A_Index])
         , DllCall("SetDCPenColor", "Ptr", This.MDC, "UInt", This.Colors[A_Index])
         , X := 0 + (ScaleX * (A_Index - 1))
         Loop, %Bars% {
            V := StrReplace(Values[A_Index], ",", ".")
            If (V <= Min) {
               X += ScaleX
               Continue
            }
            If (V > Max)
               V := Max
            Y := Round((V - Min) * F)
            , DllCall("Rectangle", "Ptr", This.MDC, "Int", X, "Int", H - Y, "Int", X + ScaleX, "Int", H)
            , X += D
         }
      }
      Return True
   }
   ; =============================================================================================================================
   ; Retrieves the chart bitmap.
   ;     Width    -  the width of the returned bitmap in pixels
   ;                 Default: 0 - original width
   ;     Height   -  the height of the returned bitmap in pixels
   ;                 Default: 0 - original height
   ; Note:
   ;     If -1 is passed for either Width or Height the value will be calculated preserving the aspect ratio.
   ; =============================================================================================================================
   GetBitmap(Width := 0, Height := 0) {
      If !(This.MBM)
         Return False
      If Width Is Not Integer
         Throw Exception("Invalid parameter Width: " . Width)
      If Height Is Not Integer
         Throw Exception("Invalid parameter Height: " . Height)
      If (Width < 0) && (Height < 0)
         Width := Height := 0
      Else If (Width < 0)
         Width := Round(Height * (This.Width / This.Height))
      Else If (Height < 0)
         Height := Round(Width * (This.Height / This.Width))
      Return DllCall("CopyImage", "Ptr", This.MBM, "UInt", 0, "Int", Width, "Int", Height, "UInt", 0x00002000, "UPtr")
   }
   ; =============================================================================================================================
   ; For internal use ============================================================================================================
   ; =============================================================================================================================
   CheckColor(ByRef Color, Method, Param) {
      If This.HTML.HasKey(Color)
         Color := This.HTML[Color]
      Else
         Color := ((Color & 0x0000FF) << 16) | (Color & 0x00FF00) | ((Color & 0xFF0000) >> 16)
      If (Color = "")
         Throw Exception("Invalid color " . Param . ": " . Color, Method)
   }
   ; -----------------------------------------------------------------------------------------------------------------------------
   SetValues(Index, Name, Color, Values) {
      This.Names[Index] := Name
      This.Colors[Index] := Color
      If !IsObject(Values)
         Values := StrSplit(Values, "|")
      This.Values[Index] := Values
      Min := This.MinVal, Max := This.MaxVal
      For I, V In Values
         If (V < Min)
            Min := V
         Else If (V > Max)
            Max := V
      This.MinVal := Min, This.MaxVal := Max
      Return True
   }
}
Beispiel:

Code: Select all

#NoEnv
SetBatchLines, -1
#Include BarChart.ahk
; Balkendiagramm vorbereiten -----------------------------------------------------------------------------------------------------
; Anzahl der Wertereihen
RowCount := 3
; Anzahl der Werte pro Reihe
RowValues := 24
; Breite eines Balkens
BarWidth := 12
; Um alle Werte darstellen zu können, muss die Breite der Bitmap wie folgt bestimmt werden:
; Anzahl der Wertereihen * Anzahl der Werte pro Reihe * Breite eines Balkens
Width := RowCount * RowValues * BarWidth
; Die Höhe der Bitmap wird im Verhältnis 16 : 10 bestimmt.
Height := Round((Width / 16) * 10)
; Balkendiagramm erstellen und mit Werten füllen ---------------------------------------------------------------------------------
; Eine neue GdiChart-Instanz mit der Hintergrundfarbe 'Silver' wird erstellt.
Chart := New BarChart(Width, Height, "Silver")
; Vorgaben für die Namen der Reihen (z.Zt. ungenutzt)
Names := ["Name 1", "Name 2", "Name 3"]
; Vorgaben für die Farben der Reihen
Colors := ["Navy", "Red", "Purple"]
; Wertelisten mit Zufallszahlen im Bereich von 7000 - 10000 füllen und an die Instanz übergeben.
; Die Wertelisten können als Array oder als '|'-getrennte Liste übergeben werden.
Loop, %RowCount% {
   N := Names[A_Index]
   C := Colors[A_Index]
   V := ""
   Loop, % RowValues {
      Random, I, 7000, 10000
      V .= "|" . I
   }
   Chart.AddValues(N, C, SubStr(V, 2))
}
; Diagramm zeichnen --------------------------------------------------------------------------------------------------------------
; Ein Hintergrundraster der Farbe 'White' wird gezeichnet.
; Der Abstand der senkrechten Rasterlinien wird als Breite eines Balkens * Anzahl der Reihen festgelegt,
; für die wagerechten Rasterlinien wird ein Abstand bestimmt, der ungefähr einem Zehntel der Höhe entspricht.
Start := A_TickCount
Chart.DrawGrid(BarWidth * RowCount, Round(Height / 10), "White")
; Jetzt wird das Balkendiagramm gezeichnet.
; Die Breite der Balken muss übergeben werden.
; Außerdem werden im Beispiel der kleinste und der größte darzustellende Wert festgelegt.
Chart.DrawBars(BarWidth, 5000, 10000)
; Das Zeichnen ist damit erst einmal abgeschlossen. Wir können uns das Handle der Bitmap holen.
ChartBM := Chart.GetBitmap()
Time := A_TickCount - Start
; Gui ----------------------------------------------------------------------------------------------------------------------------
Gui, +Resize
Gui, Margin, 10, 10
Gui, Add, Pic, vPic, HBITMAP:%ChartBM%
Gui, Show, , Bar Chart Test (%Time% ms)
Return
; --------------------------------------------------------------------------------------------------------------------------------
GuiCLose:
GuiEscape:
ExitApp
; --------------------------------------------------------------------------------------------------------------------------------
GuiSize:
If (A_EventInfo <> 1)
   GuiControl, MoveDraw, Pic, % "w" . (A_GuiWidth - 20) . " h" . (A_GuiHeight - 20)
Return
just me
Posts: 8600
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Liniendiagramm

13 May 2017, 06:06

jNizM wrote:3) Evtl. neben den farbigem DataStream (Graph) ein zusätzlichen für z.B. einen helleren bis zum Graphen aufgefülltem Hintergrund ...
Ich habe hier was zur freien Verwendung (ich bin nicht 'ausreichend motiviert', mich weiter damit zu beschäftigen):

Code: Select all

#NoEnv
SetBatchLines, -1
Plot := {}
; Plot.BackClr := 0x808080
Plot.LineClr := 0x3399FF ; 0xFFFF00
Plot.Frame := True
Plot.ScaleX := True
Plot.ScaleY := True
Plot.Values := GeneratePoints(300, 200, -200)
Start := A_TickCount
HBM := Plot2BitMap(Plot, 600, 400)
Time := A_TickCount - STart
Gui, Margin, 20, 20
Gui, Add, Pic, , HBITMAP:%HBM%
Gui, Show, , Plot (%Time% ms)
Return
GuiClose:
GuiEscape:
ExitApp

GeneratePoints(Count, Max, Start := 0) {
   Y := Start
   Points := []
   Loop, %Count% {
      Points.Push(Y)
      Y += Rand(-20, 20)
      If (Y < Start)
         Y := Start
      If (Y > Max)
         Y := Max
   }
   Return Points
}

Rand(Min, Max) {
   Random, R, %Min%, %Max%
   Return R
}

; ================================================================================================================================
; Plot   -  An object containing one or more the following key/value pairs:
;           Values:     An array of values to plot.
;           BackClr:    The background color of the bitmap as RGB integer value (0xRRGGBB).
;                       Default: 0xFFFFFF (white)
;           LineClr:    The color of the line created of the values as RGB integer value (0xRRGGBB).
;                       Default: 0x000000 (black)
;           ScaleX:     Scale the values to fit the width (True/False).
;                       Default: False (don't scale)
;           ScaleY:     Scale the values to fit the height (True/False).
;                       Default: False (don't scale)
;           Frame:      Frame the bitmap using the line color (True/False).
;                       Default: False (don't frame)
; W      -  the width of the bitmap in pixels.
; H      -  the height of the bitmap in pixels.
; ================================================================================================================================
Plot2BitMap(Plot, W, H) {
   Static Defaults := {LineClr: 0x000000, BackClr: 0xFFFFFF, Frame: False, ScaleX: False, ScaleY: False}
   ; Init variables --------------------------------------------------------------------------------------------------------------
   Plot.Base := Defaults
   Min := 9223372036854775807
   Max := -9223372036854775808
   BC := 0xFF000000 + (Plot.BackClr & 0xFFFFFF)  ; background color
   LC := 0xFF000000 + (Plot.LineClr & 0xFFFFFF)  ; line color
   FC := LC & 0x20FFFFFF                         ; fill color
   Values := Plot.Values
   For I, V In Values
      If (V < Min)
         Min := V
      Else If (V > Max)
         Max := V
   DX := Plot.ScaleX ? W / (Values.Length() - 1) : 1
   DY := Plot.ScaleY ? H / (Max - Min) : 1
   ; Plot ------------------------------------------------------------------------------------------------------------------------
   DllCall("Gdiplus.dll\GdipCreateBitmapFromScan0", "Int", W, "Int", H, "Int", 0, "Int", 0x26200A, "Ptr", 0, "PtrP", Bitmap)
   DllCall("Gdiplus.dll\GdipGetImageGraphicsContext", "Ptr", Bitmap, "PtrP", Graphics)
   DllCall("Gdiplus.dll\GdipSetSmoothingMode", "Ptr", Graphics, "Int", 4) ; or 2
   DllCall("Gdiplus.dll\GdipGraphicsClear", "Ptr", Graphics, "UInt", BC)
   DllCall("Gdiplus.dll\GdipCreateSolidFill", "UInt", FC, "PtrP", Brush)
   DllCall("Gdiplus.dll\GdipCreatePen1", "UInt", 0xFFE0E0E0, "Float", 1, "Int", 2, "PtrP", Pen)                             ; test
   Y := H - ((Max - Min) * DY / 2)                                                                                          ; test
   DllCall("Gdiplus.dll\GdipDrawLine", "Ptr", Graphics, "Ptr", Pen, "Float", 0, "Float", Y, "Float", W, "Float", Y)         ; test
   DllCall("Gdiplus.dll\GdipSetPenColor", "Ptr", Pen, "UInt", LC)                                                           ; test
   DllCall("Gdiplus.dll\GdipCreatePath", "UInt", 0, "PtrP", Path)
   X := 0
   X1 := -1
   Y1 := H - (Values[1] * DY)
   For I, V In Values {
      Y := H - ((V - Min) * DY)
      DllCall("Gdiplus.dll\GdipAddPathLine", "Ptr", Path, "Float", X1, "Float", Y1, "Float", X, "Float", Y)
      X1 := X
      Y1 := Y
      X += DX
   }
   DllCall("Gdiplus.dll\GdipAddPathLine", "Ptr", Path, "Float", X1, "Float", Y1, "Float", X1, "Float", H)
   DllCall("Gdiplus.dll\GdipAddPathLine", "Ptr", Path, "Float", X1, "Float", H, "Float", -1, "Float", H)
   DllCall("Gdiplus.dll\GdipDrawPath", "Ptr", Graphics, "Ptr", Pen, "Ptr", Path)
   DllCall("Gdiplus.dll\GdipFillPath", "Ptr", Graphics, "Ptr", Brush, "Ptr", Path)
   If (Plot.Frame)
      DllCall("Gdiplus.dll\GdipDrawRectangleI", "Ptr", Graphics, "Ptr", Pen, "Int", 0, "Int", 0, "Int", W - 1, "Int", H - 1)
   DllCall("Gdiplus.dll\GdipCreateHBITMAPFromBitmap", "Ptr", Bitmap, "PtrP", HBITMAP, "UInt", BC)
   DllCall("Gdiplus.dll\GdipDeletePen", "Ptr", Pen)
   DllCall("Gdiplus.dll\GdipDeleteBrush", "Ptr", Brush)
   DllCall("Gdiplus.dll\GdipDeleteGraphics", "Ptr", Graphics)
   DllCall("Gdiplus.dll\GdipDeletePath", "Ptr", Path)
   DllCall("Gdiplus.dll\GdipDisposeImage", "Ptr", Bitmap)
   ; Return the bitmap -----------------------------------------------------------------------------------------------------------
   Return HBITMAP
}
; ================================================================================================================================
UseGDIP(Params*) {
   Static GdipObject := ""
   Static GdipModule := ""
   Static GdipToken  := ""
   Static Load := UseGDIP()
   If (GdipModule = "") {
      If !(GdipModule := DllCall("LoadLibrary", "Str", "Gdiplus.dll", "UPtr")) {
         MsgBox, 262160, UseGDIP, The Gdiplus.dll could not be loaded!`n`nThe program will exit!
         ExitApp
      }
      Else {
         VarSetCapacity(SI, 24, 0), NumPut(1, SI, 0, "UInt") ; size of 64-bit structure
         If DllCall("Gdiplus.dll\GdiplusStartup", "PtrP", GdipToken, "Ptr", &SI, "Ptr", 0) {
            MsgBox, 262160, UseGDIP, GDI+ could not be startet!`n`nThe program will exit!
            ExitApp
         }
         GdipObject := {Base: {__Delete: Func("UseGDIP").Bind(GdipModule, GdipToken)}}
      }
   }
   Else If (Params[1] = GdipModule) && (Params[2] = GdipToken) {
      DllCall("Gdiplus.dll\GdiplusShutdown", "Ptr", GdipToken)
      DllCall("FreeLibrary", "Ptr", GdipModule)
   }
}
User avatar
nnnik
Posts: 4497
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Liniendiagramm

13 May 2017, 06:33

Das wird bei mir noch eingebaut. Momentan hat eine Matheklausur am Dienstag aber Vorrang.
Ich würde es über GdipFillPolygon zeichnen, obwohl mir die Path Methode auch sehr gefällt.
Neueste Updates findet man übrigens hier:
https://autohotkey.com/boards/viewtopic.php?f=6&t=31533
Recommends AHK Studio
just me
Posts: 8600
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Liniendiagramm

13 May 2017, 08:02

Ja, die Polygon-Funktionen sollten es auch tun und sind wahrscheinlich auch schneller, weil es nicht so viele DllCall's braucht. Ich bin zuerst über die GraphicsPath-Funktionen gestolpert und habe dann nicht weiter nachgedacht.
Nmk
Posts: 28
Joined: 20 Jan 2017, 19:29

Re: Liniendiagramm

15 May 2017, 07:35

Hallo zusammen,

ich brauchte mal ein paar Tage abstand. Ich habe es bisher für eine unlösbare Aufgabe gehalten, aber das was Ihr hier ausgräbt und fabriziert, lässt mich glauben es sei zum greifen nah.

Ich schaue mir das nachher mal in Ruhe an.

Gruß

Nmk

Return to “Ich brauche Hilfe”

Who is online

Users browsing this forum: No registered users and 5 guests