> Herzlich willkommen beim deutschen Visual Objects Support und Vertrieb

 
 
 
 
 
 
 
  
  
  
  
  
  
  
  
  
  
  
  
 
 
 
 
 
 
 
 
 
 
 
 
 
Impressum

Tipp des Monats für März 2003


Druckversion anzeigen: Druckversion
Wussten Sie schon... ?

... dass sich die Setup()-Methode von PrintingDevice nicht korrekt verhält? Sie setzt zwar den vom Anwender gewählten Drucker korrekt, merkt sich aber diesen nicht für den nächsten Setup()-Aufruf. Ärgerlicher noch: andere Einstellungen, die dort vorgenommen werden sehr wohl beim nächsten Mal angezeigt. Aber keine Sorge wir haben gleich zwei Lösungen dazu.


Das Problemszenario: Die Standard-MDI-Anwendung hat eine PROTECT-Variable oPrinter bei der StandardShellWindow-Klasse. Diese wird in der Init-Methode von StandardShellWindow initialisiert.
CLASS StandardShellWindow INHERIT ShellWindow
PROTECT oPrinter AS PrintingDevice

METHOD Init(oOwnerApp) CLASS StandardShellWindow
.....
oPrinter := PrintingDevice{}

Wählt man jetzt im File-Menu die Option "Printer Setup...", ändert dort den Drucker, schließt den Dialog mit OK und kommt gleich wieder zurück, dann sollten Sie wieder den Standarddrucker eingestellt sehen und NICHT den gerade neu eingestellten Drucker! Dabei wird hier doch nur die folgende Methode aufgerufen:
METHOD FilePrinterSetup() CLASS StandardShellWindow
oPrinter:Setup()

Es sieht also ganz so aus, als ob an dieser etwas nicht in Ordnung ist.
Wenn Sie dieses Verhalten nicht verifizieren können, dann haben Sie schon eine der beiden Lösungen. Aber lesen Sie auch dann weiter: Wir haben immer noch etwas für Sie.


Die Lösungen: Die eine Lösung besteht in der Tat darin, dass Sie VO 2.6 verwenden. Und beinahe wäre dieser Tip des Monats damit auch schon überflüssig geworden. Jedoch zeigt das SDK von VO 2.6 immer noch nicht den korrigierten Quelltext. Da wir uns den vor langer Zeit einmal selbst für VO 2.5 geschrieben haben, können wir diesen hier für alle neugierigen VO 2.6 Anwender und für alle VO 2.5 Anwender zeigen, die dieses Problem ohne ein Upgrade lösen wollen (das wäre die zweite Lösung).

Dass die Setup()-Methode die vom Anwender vorgenommenen Einstellungen 'vergisst', liegt daran, dass diese Methode nur eine LOCAL-Variable verwendet, um sich die Struktur DevNames zu merken. Deshalb schaffen wir dafür eine neue PROTECT-Variable in einer von PrintingDevice abgeleiteten Klasse.
CLASS epPrintingDevice INHERIT PrintingDevice
PROTECT hDevNames AS PTR

Die in der folgenden Setup-Methode fett hervorgehobenen Zeilen zeigen, wie wir diese neue PROTECT-Variable einsetzen.
METHOD Setup() CLASS epPrintingDevice
LOCAL pd IS _WinPrintDlg
LOCAL struDevN AS _windevNames
LOCAL lRetVal AS LOGIC
LOCAL ptrHandle AS PTR
LOCAL ptrString AS PTR
LOCAL hDevMode AS PTR
LOCAL pTemp AS PTR
LOCAL pfnPrintDlg AS TPrintDlg PTR
// wir überspringen hier einige Zeilen, die sich
// auf hDevMode im Wesentlichen beziehen und die Sie
// ohne Änderung aus Ihrem SDK übernehmen können.


pd.hDevMode := hDevMode
// im VO 2.6 SDK steht in der folgenden Zeile
// immer noch pd.hDevNames := NULL_PTR

pd.hDevNames := SELF:hDevNames

// die folgenden Zeilen, in denen die restlichen MEMBERs
// der pd-Struktur belegt werden, haben wir ebenfalls
// ohne Änderung übernommen
//pd.nFromPage := .....


IF !__LoadComDlgDLL()
    lRetVal := FALSE
ELSEIF (pfnPrintDlg := GetProcAddress(;
    LoadLibrary(PSZ(_CAST, "COMDLG32.DLL")),;
    PSZ(_CAST, "PrintDlgA"))) == NULL_PTR
    lRetVal := FALSE
// der folgende PCALL-Aufruf konfiguriert den Printer-
// Setup-Dialog und verwendet dabei die beim letzten
// Aufruf verwendeten Einstellungen!
// siehe obige fett hervorgehobene Zeile

ELSEIF !LOGIC(_CAST, PCALL(pfnPrintDlg, @pd))
    lRetVal := FALSE
ELSE
    //in diesen Zweig gelangen wir nur, wenn der
    // Anwender den PrintDlg mit OK verlassen hat
    // und merken uns deshalb die neuen Einstellungen,
    // die uns in der pd-Struktur zurückgegeben werden.
    struDevN := GlobalLock(pd.hDevNames)
    // die folgenden Zeilen belegen die Instanzvariablen
    //der PrintingDevice-Klasse
    //(ohne Änderung übernommen)

    GlobalUnlock(pd.hDevNames)
    // die entscheidende Änderung stellen die beiden
    // folgenden Zeilen dar. In diesen ersetzen wir
    // GlobalFree() dadurch, dass wir uns die hDevNames
    // -Struktur in der neu geschaffenen PROTECT-
    // Variablen hDevNames merken

    //GlobalFree(pd.hDevNames)
    SELF:hDevNames := pd.hDevNames

    // folgenden Zeilen beziehen sich wieder auf
    // hDevMode und werden ohne Änderung übernommen.

ENDIF
RETURN lRetVal

Nachdem wir GlobalFree oben ausdrücklich auskommentiert haben, müssen wir dieses später nachholen. Und das geschieht wie meistens in der Destroy()-Methode:
METHOD Destroy() CLASS epPrintingDevice
SUPER:Destroy()
IF SELF:hDevNames != NULL_PTR
    GlobalFree(SELF:hDevNames)
ENDIF
  
Dieser Tipp stammt von: Michael Wittmer
Textliche Aufbereitung: Dieter Crispien
 
Schicken Sie uns Ihren eigenen Tipp des Monats per Email
Druckversion anzeigen: Druckversion

 

 

 

Letzte Änderung des Inhalts auf dieser Seite: 06.03.03

(c) 2002-2004 Dieter Crispien Software-Entwicklung und -Vertrieb (dcSE)