
Die Steuerelemente sind von links nach rechts eingefügt, also zuordenbar.
Zunächst Deklarationen und die Ladeinformationen des Formulars. Die Routine Form_Resize wird gleich anschließend erläutert. Die Startwerte für beide ScrollBars werden beim Anlegen des Formulars eingestellt. Da die Werte mit den Default-Werten nicht übereinstimmen, werden die später erläuterten Change-Ereignisse ausgelöst, die dann auch die Anzeigen in Labels schon beim Start bewirken.
| Option Explicit Dim xvon As Single, xbis As Single, ymax As Single, ymin As Single, Blatt As Object Private Sub Form_Load() Form_Resize End SubHScroll1.Value = 10 HScroll2.Value = 10 |
Jetzt eine für den Nutzer ganz wichtige Sache: Bei Veränderung der Größe des Fensters, in dem die Anwendung läuft, soll die Funktionsdarstellung den jeweiligen Raum im Fenster optimal nutzen. Deshalb werden die Maße der PictureBox, die die eigentliche Diagrammdarstellung enthält, den Fenstermaßen angepaßt. Die Anpassung muß unterbleiben, wenn das Fenster minimiert worden ist und wenn der Platz nur noch für die Steuerelemente aber nicht mehr für ein anständiges Darstellungsfenster reicht. Die Ränder werden in Pixeln festgelegt, damit man von der Bildschirmauflösung unabhängig ist. Der Frame, der die Bedienelemente enthält, besitzt eine feste Größe, die berücksichtigt werden muß.
| Private Sub Form_Resize() Dim fakX As Long, fakY As Long If Not Form1.WindowState = 1 And Form1.Height > 2 * Frame1.Height Then Picture1.Cls fakX = Screen.TwipsPerPixelX fakY = Screen.TwipsPerPixelY Picture1.Left = 6 * fakX Picture1.Width = Form1.Width - 20 * fakX Picture1.Top = 7 * fakY Picture1.Height = Form1.Height - Frame1.Height - 37 * fakY Frame1.Left = 6 * fakX Frame1.Top = Form1.Height - Frame1.Height - 30 * fakY End If End Sub |
In den folgenden Unterprogrammen werden die Change-Ereignisse beider ScrollBars ausgewertet. Hier werden die x-Grenzen der Darstellung ausgewählt. Natürlich gibt es dafür auch andere Möglichkeiten. Wichtig ist, daß auf irgendeine Weise Fehleingaben verhindert werden. Hier sind die Min- und Max-Werte beider ScrollBars so eingestellt, daß nichts Schlimmes passieren kann. Der untere geht bis "0" der obere beginnt bei "1", so ist immer ein anzeigbares Intervall vorhanden. Natürlich können die Werte auch abgefragt und evtl. mittels MessageBox und einer Schleife solange erneut erfragt werden, bis sie zulässige Werte erhalten haben.
| Private Sub HScroll1_Change() Picture1.Cls xvon = -HScroll1.Value Label1.Caption = "xvon = " & xvon End Sub Private Sub HScroll2_Change() Picture1.Cls xbis = HScroll2.Value Label2.Caption = "xbis = " & xbis End Sub |
Es folgen die drei Buttons. Der erste löst die Darstellung auf dem Bildschirm aus. Hier werden zwei erst später definierte Funktionen, nämlich Achsenkreuz() und Male() unter Nennung des Objektes aufgerufen, auf das sie angewandt werden sollen. Im zweiten Unterprogramm geht es um das Drucken. Es wird das Druckerauswahlfenster aufgerufen, danach werden die beiden schon genannten Routinen auf den Drucker angewandt.
Die beiden Unterprogramme werden mit einem Objektparameter, der für Picture1 und Printer stehen, aufgerufen. Inhaltlich sind die Routinen für beide Ausgabemedien (fast) gleich. Der dritte Button beendet in bekannter Weise das ganze Unglück.
| Private Sub Command1_Click() Picture1.Cls End SubAchsenkreuz Picture1 Male Picture1 Private Sub Command2_Click() On Error GoTo hier raus:CommonDialog1.Flags = &H40 CommonDialog1.CancelError = True CommonDialog1.Action = 5 MousePointer = 11 'drucken dauert Printer.ScaleTop = 0 Printer.ScaleLeft = 0 Achsenkreuz Printer Male Printer Printer.EndDoc MousePointer = 0 hier:Exit Sub If Not CommonDialog1.CancelError Then MsgBox "Der Drucker will oder kann nicht!" End SubPrivate Sub Command3_Click() End End Sub |
Nun folgt die Funktion, die dargestellt werden soll. Natürlich ist das Programm, solange es nur für eine einzige Funktion gilt, relativ witzlos. Aber die Erweiterung überlasse ich gern meinen Nachnutzern. Aufgerufen wird die Funktion mit dem x-Wert als Parameter und sie meldet den berechneten y-Wert zurück. Die frei wählbare Funktionsbezeichnung hat zur Folge, daß ein Ausdruck wie y = f(x) eine gültige Befehlszeile im Programm darstellt.
| Function f(ByVal x As Single) As Single f = (Sin(x) - Cos(x ^ 2)) * Sqr(Abs(x)) End Function |
Es folgen die aufwendigeren, aber auch wiederverwendbaren Teile des Programms. Die Routine Achsenkreuz() wird aufgerufen mit dem Objekt, auf dem das Achsenkreuz errichtet werden soll, einmal also Picture1, einmal Printer. Theoretisch soll das reibungslos funktionieren. Leider haben aber die Erfinder von Visual Basic keinen Drucker besessen, deshalb gehört die Druckereinbindung bis heute zu den problematischen Teilen von Visual Basic.
Zu den einzelnen Abschnitten:
| Sub Achsenkreuz(wohin As Object) Dim i%, x As Single, dx As Single, y As Single Dim xrand As Single, yrand As Single 'Spannweite der y-Werte feststellen ymax = -1000000# ymin = 1000000# dx = (xbis - xvon) / 1000 For i = 0 To 1000 x = xvon + i * dx y = f(x) If y < ymin Then ymin = y If y > ymax Then ymax = y Next 'Darstellungsfeld skalieren und mit gleichmäßigem Rand versehen Select Case wohin.hDC Case Picture1.hDC xrand = 20 * (xbis - xvon) / (wohin.Width / Screen.TwipsPerPixelX - 40) yrand = 20 * (ymax - ymin) / (wohin.Height / Screen.TwipsPerPixelY - 40) Case Printer.hDC xrand = 150 * (xbis - xvon) / (wohin.Width / wohin.TwipsPerPixelX - 300) yrand = 150 * (ymax - ymin) / (wohin.Height / wohin.TwipsPerPixelY - 300) End Select wohin.Scale (xvon - xrand, -yrand)-(xbis + xrand, ymax - ymin + yrand) wohin.Line (xvon, 0)-(xbis, ymax - ymin), , B 'Achsen malen, beschriften If Sgn(xvon) <> Sgn(xbis) Then wohin.Line (0, 0)-(0, -(ymin - ymax)) If ymax - ymin > 1 Then For i = Fix(ymin) To Fix(ymax) If i <> 0 Then wohin.Line (0, -(i - ymax))-(xrand / 5, -(i - ymax)) wohin.Print i End If Next End If End If If Sgn(ymin) <> Sgn(ymax) Then wohin.Line (xvon, ymax)-(xbis, ymax) If xbis - xvon > 1 Then For i = Fix(xvon) To Fix(xbis) - 1 If i <> 0 Then wohin.Line (i, ymax)-(i, yrand / 5 + ymax) wohin.Print i End If Next End If End If End Sub'Angabe der Darstellungsgrenzen wohin.CurrentX = xvon wohin.CurrentY = ymax - ymin + yrand / 10 wohin.Print xvon & " <= X <= " & xbis & "; " & Format$(ymin, "#.##") & " <= Y <= " & Format$(ymax, "#.##"); wohin.Print " F(X) = (Sin(X) - Cos(X^2)) * Sqr(Abs(X))" |
Gleich sind wir fertig. Nur noch schnell die Kurve gemalt. Bemerkenswert hier nur die Klimmzüge, die man machen muß, um die falsch orientierte y-Richtung zu kompensieren. Vgl. dazu den obigen Abschnitt zur Skalierung.
| Sub Male(wohin As Object) Dim i%, x As Single, xalt As Single, yalt As Single, dx As Single, y As Single dx = (xbis - xvon) / 1000 xalt = xvon yalt = f(xvon) For i = 1 To 1000 x = xvon + i * dx y = f(x) wohin.Line (xalt, -(yalt - ymax))-(x, -(y - ymax)) xalt = x yalt = y Next End Sub |
Viel Erfolg!