|
|
Umstieg auf PB Win für Dossies Teil (6) Was hat sich eigentlich verändert
#1543 - 23.01.2006 15:15
|
Ändern
|
Antworten
|
Zitieren
|
|
|
Zum einen der Aufbau. Jetzt heißt es halt PBMain oder WinMain (evtl. mit Funktionsparametern). Dieser Kopf wird für Windows als Einsprung genutzt, d.h. hier wird mit der Abarbeitung des PB Win Programms begonnen. Die Parameter werden von Windows an das PB Win Programm geliefert. So u.a.
hInstance Handle bzw. Index für das Programm (unter Windows als Multitasking laufen halt mehrere Programme, diese müssen über Ihre Indizes unterschieden werden)
hPrevInst Da unter Windows im Gegensatz zu DOS das gleiche Program mehrmals aufgerufen werden kann, wird unter hPrevInst das Handle der zuletzt aufgerufenen Sitzung angegeben. Das bedeutet: ist der Wert von hPrevInst 0 so handelt es sich um den ersten Aufruf des Programms. Ist es ungleich 0 so kann man die Meldung „Programm läuft bereits“ ausgeben (falls gewünscht) und das Programm (also das was nochmal also zuviel aufgerufen wurde) wieder beenden. Oder aber man läßt es zu, daß das Programm mehrmals läuft.
lpszCmdLine Ein Pointer (Zeiger) auf einen ASCIIZ String wo alles steht, was hinter dem *.exe Dateinamen bei Aufruf aus einer Commandzeile noch steht. Beispiel: „test.exe Hallo“; Dadurch wird das Programm test.exe gestartet und in lpszCmdLine steht die Adresse der Speicherstelle, wo der Zusatz, in diesem Fall Hallo der hinter test.exe eingegeben wurde zu finden ist. Dieses erhält man aber auch über den in PB eingebauten Befehl command$.
nCmdShow ein LONG Zahlenwert der eine Aussage darüber macht, wie der Benutzer, welcher die *.exe Datei aufgerufen hat, das Programm angezeigt haben will. Als normales Fenster, als maximiertes Fenster, als Ikone usw. Hier wird also bspw. bei Windows Programmen, welche über ein Icon z.B. vom Desktop aus gestartet werden, der Wert übergeben, den man unter Eigenschaften zu der Ikone eintragen kann (unter dem Reiter Programm – Ausführen als)
Was ist Neu ?
Eigentlich nur die sog. Callbacks. Callbacks sind lediglich Funktionen bzw. Subs innerhalb des eigenen Programms, welche von Windows aufgerufen werden. Dies ist aber quasi gleichzusetzen mit einem extern ausgelösten IRQ unter DOS. Die Callback Routine stellt somit die IRQ Routine dar, welche durch das Auslösen des Interrupts früher aufgerufen wurde, sich jedoch nun innerhalb des eigenen Programms als Function bzw. Sub Routine befindet anstelle früher über die IRQ Tabelle an einer bestimmten separaten Speicheradresse zu befinden. Genauso ruft Windows nun die als Callback definierte Function auf (jedoch nicht ausschließlich aufgrund eines Hardware Ereignisses sondern auch zu anderen Anläßen).
Ansonsten hat sich nur die Art und Weise geändert. Als ich angefangen habe mich mit den Besonderheiten um Windows zu beschäftigen, dachte ich zunächst es sei alles ganz anders als früher. Hat man jedoch erst einmal verstanden wie Windows arbeitet, so erkennt man, daß eigentlich alles so ist wie früher.
Statt eigene Interrupt Aufrufe beim DOS bzw. BIOS durchzuführen, um die ein oder andere Funktion ausführen zu können, ruft man unter Windows die entsprechende API Funktion auf (entweder als Function mit Rückgabewert oder auch als Sub falls der Rückgabewert nicht erforderlich ist).
Direkte Zugriffe auf Hardware mittels in/Out oder eben Int sind jedoch nicht mehr so ohne weiteres möglich und auch nicht erwünscht. Der Grund dafür ist erneut das Multitasking. Es kann nur einen Koch geben, der alle Ereignisse überwacht und steuert und das ist halt Windows. Würde ein Programm direkt auf Hardware zugreifen, von dem Windows keine Kenntnis hat oder umgekehrt, mein Programm mit direktem Hardwarezugriff hat wiederrum keine Kenntnis darüber wann Windows die gleiche Hardware plötzlich neu initialisiert oder abfragt, dann kann das nur zum Chaos führen. Deshalb sind hier spezielle Treiberprogramme nötig. Nur die können direkt diese Hardware ansprechen. Diese Treiberprogramme stellen wiederrum Funktionen (API) als Schnittstelle zur Verfügung anstelle der In/Out und Int Befehle von früher.
Message Pump Auch dieses ist nichts wirklich neues. Es ist eigentlich gleichzusetzen mit der ehemaligen Inkey$ Abfrage. Auch hier hat man unter DOS eine Schleife geschrieben, die solange wiederholt wurde, bis der Benutzer eine Taste gedrückt hat oder eine Mausbewegung auslöste (oder eben alternativ hat man ab und zu mal abgefragt ob eine Taste gedrückt wurde und zwischendurch andere Aufgaben durch das Programm erledigen lassen). So wird auch unter Windows über GetMessage (früher inkey unter DOS) die nächste anliegende Botschaft (früher Tastenereignis bei DOS) abgerufen. Der Inhalt der Botschaft wird jedoch bei GetMessage zunächst übersetzt (TranslateMessage) und zu der entsprechenden WindowProcedure (die entsprechende Bearbeitungsfunktion) mittels DispatchMessage gesendet. Durch den Befehl DispatchMessage wird Windows veranlaßt, den Inhalt der nächsten anliegenden Mitteilung bzw. Ereignisses aus der Warteschlange (früher Tastaturpuffer unter DOS) an diese Funktion zu übermitteln und zwar mittels Callback. Das heißt die WindowProcedure Funktion befindet sich in dem eigenen Programm wird aber von Windows aus aufgerufen. Bei diesem Aufruf wird der Funktion entsprechend die Parameter von Windows übergeben, die den Inhalt des Ereignisses entsprechen. Dieser Inhalt ist natürlich umfangreicher als früher der bloße Code der gedrückten Taste. Denn es werden nun auch mehr Ereignisse erfaßt als früher u.a. Tasten, Mauspositionen, das Verhalten der Fenster von anderen Programmen, Timer Ereignisse, usw.
Was sich für den Programmierer unter Windows verschlechtert hat ist zum einen die dürftige API Dokumentation (alles muß man sich teilweise recht mühsam zusammensuchen) und die enorme API Vielfältigkeit. Geradezu erschlagen wird man von den vielen zur Verfügung stehenden Funktionen und den dafür erforderlichen Datentypen und Strukturen in denen die Daten für die Funktionen oder die Ergebnisse der Funktionen zur Verfügung gestellt werden.
-------------------- KPA
Extras:
|
|
|
|
Hallo, Klaus-Peter Anhalt, danke für Ihre Beitrag DOS zu Window. Das hat mir schon mal etwas geholfen. Habe große Probleme durch den Umstieg. Ich vermisse in PB für Windows den LPRINT USING-Befehl: Schreibe für mich Statistik-Programme und weiß nicht, wie ich die auszugebenden Tabellen formatieren soll. Es sind stets Zahlenkolonnen. Hätte ich statt PB/Win besser PB/CC gekauft? Ich brauche keine Grafik und andere Oberflächen. Ich muss mein Programm lediglich aufrufen und starten. Dann greift es auf Daten zu, berechnet alles Mögliche und soll die Ergebnisse auf Nadeldrucker oder Laserdrucker ausdrucken. Wäre nett, wenn Sie mir einen Tipp geben könnten, wie ich das mit dem Drucken anstelle. Freundliche Grüße Manfred Oetting
Extras:
|
|
Uwe Heyer
|
|
Mitglied 100+
|
|
|
|
|
Registriert: 09.06.2003
|
|
Beiträge: 105
|
|
|
|
|
Hi Manfred,
es ist keine Antwort auf die Frage, nur eine Bemerkung
das mit dem LPRINT funzt nur bei Druckern, die noch die gute alte DOS Zeit unterstützen. Solche werden aber immer weniger produziert (zumindest im low-cost, hi-end wird sicherlich folgen) und dies wird sicherlich auch an reine DOS Programme nicht spurlos vorüber gehen. LPRINT / DOS ist ein sterbender Schwan.
LPRINT nutzt die ESCAPE-Funktionalität des Druckertreibers/Druckers, falls (in dem) vorhanden. USB und GDI Drucker bieten so etwas nicht.
Also für LPRINT USING gibt es die USING$ um die Zeile vorher aufzubereiten
für neuere Programme würde ich mir als PB Programierer mal die XPRINT Familie anschauen. Das gilt sowohl für PB/CC sowei PB/Win oder die pure API von Windows
Ahoj -Uwe
Extras:
|
Josef Kirschbaum
|
|
Moderator
|
|
|
|
|
Registriert: 15.12.2002
|
|
Beiträge: 344
|
|
Wohnort: Emmering
|
|
|
Weil die Frage zum Drucken nicht direkt zu diesem Thema passt, habe ich für die Antwort einen gesonderten Beitrag erstellt.
Extras:
|
|
Dieter Mayr
|
|
Mitglied 10+
|
|
|
|
|
Registriert: 18.07.2007
|
|
Beiträge: 13
|
|
Wohnort: Salzburg
|
|
|
Hallo Klaus-Peter
Ich lese jetzt schon zum x-ten mal deinen Absatz zur Message Pump aber irgendwie fehlt mir noch der Durchblick.
Unter PB-DOS hätte ich es so gelöst:
Code:
SUB Berabeitungsschleife (Parameterliste) DO ' Verarbeitung der Daten LOOP UNTIL INKEY$ = CHR$(27) END SUB
Unter Windows brauche ich einen Dialog mit Abbruch-Button. Ich habe also wieder meine SUB für die Bearbeitung der Daten wie oben, erstelle vor der Verarbeitung der Daten den Dailog (bzw. rufe die entsprechende FUNCTION auf), der Dialog ist MODELESS. Nur wie mache ich jetzt die Abfrage auf den Abbruch-Button in meiner SUB ? Einfach den Rückgabewert der CALLBACK FUNCTION auswerten ?
Code:
SUB Berabeitungsschleife (Parameterliste) CALL DialogModeless DO ' Verarbeitung der Daten LOOP UNTIL CallbackFunction = Rückgabewert END SUB
lg
Dieter
Extras:
|
|
Lordchen
|
|
Mitglied 100+
|
|
|
|
|
Registriert: 30.03.2007
|
|
Beiträge: 110
|
|
|
|
|
Hi Dieter,
das ist so zu verstehen, dass Windows über eine Nachrichtenkette verfügt - am Ende steht dann das Window, für das die Nachricht gedacht ist. Jedes Window-Programm fügt sich in diese Kette ein, wenn es von Windows über Benutzeraktionen informiert werden möchte - durch einen Message Loop. Dieser Message Loop ist eine elegante Methode. Sie bewirkt, dass der Thread - und Dein Programm hat mindestens einen Thread, zwar unterbrochen - aber nicht direkt gebloggt wird. Es gibt Warteroutinen, die den Thread solange halten, bis ein Ereignis eintritt, eine dieser Methoden ist GetMessage().
Deswegen verfügt jede WinMAIN() Methode über solch einen Message Loop,
Code:
Local msg As tagMsg
While (GetMessage(msg, 0, 0, 0)) TransLateMessage msg DispatchMessage msg Wend
in diesem Loop wird keine CPU-Zeit verbraucht und das Programm wartet eigentlich nur auf Messages. tagMsg ist eine Struktur, in der genau beschrieben wird, welche Nachricht von dem Programm empfangen wurde - egal, ob von der Maus, Tastatur oder ein Systemevent eingetreten ist, wie zB NetWork Aktivitäten, Drucker uvam.
Extras:
|
|